mirror of
https://github.com/LBRYFoundation/LBRY-Vault.git
synced 2025-08-23 17:47:31 +00:00
[Qt] Add optional update notifications
This commit is contained in:
parent
5613f9b903
commit
34c99c3b36
4 changed files with 138 additions and 3 deletions
|
@ -226,6 +226,28 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
|
|||
gui_object.timer.timeout.connect(self.timer_actions)
|
||||
self.fetch_alias()
|
||||
|
||||
# If the option hasn't been set yet
|
||||
if config.get('check_updates') is None:
|
||||
choice = QMessageBox.question(self,
|
||||
"Electrum - " + _("Enable update check"),
|
||||
_("For security reasons we advise that you always use the latest version of Electrum.") + " " +
|
||||
_("Would you like to be notified when there is a newer version of Electrum available?"),
|
||||
QMessageBox.Yes,
|
||||
QMessageBox.No)
|
||||
config.set_key('check_updates', choice == QMessageBox.Yes, save=True)
|
||||
|
||||
if config.get('check_updates', False):
|
||||
# The references to both the thread and the window need to be stored somewhere
|
||||
# to prevent GC from getting in our way.
|
||||
def on_version_received(v):
|
||||
if UpdateCheck.is_newer(v):
|
||||
self.update_check_button.setText(_("Update to Electrum {} is available").format(v))
|
||||
self.update_check_button.clicked.connect(lambda: self.show_update_check(v))
|
||||
self.update_check_button.show()
|
||||
self._update_check_thread = UpdateCheckThread(self)
|
||||
self._update_check_thread.checked.connect(on_version_received)
|
||||
self._update_check_thread.start()
|
||||
|
||||
def on_history(self, b):
|
||||
self.wallet.clear_coin_price_cache()
|
||||
self.new_fx_history_signal.emit()
|
||||
|
@ -577,6 +599,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
|
|||
|
||||
help_menu = menubar.addMenu(_("&Help"))
|
||||
help_menu.addAction(_("&About"), self.show_about)
|
||||
help_menu.addAction(_("&Check for updates"), self.show_update_check)
|
||||
help_menu.addAction(_("&Official website"), lambda: webbrowser.open("https://electrum.org"))
|
||||
help_menu.addSeparator()
|
||||
help_menu.addAction(_("&Documentation"), lambda: webbrowser.open("http://docs.electrum.org/")).setShortcut(QKeySequence.HelpContents)
|
||||
|
@ -604,6 +627,9 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
|
|||
"servers that handle the most complicated parts of the Bitcoin system.") + "\n\n" +
|
||||
_("Uses icons from the Icons8 icon pack (icons8.com).")))
|
||||
|
||||
def show_update_check(self, version=None):
|
||||
self._update_check = UpdateCheck(self, version)
|
||||
|
||||
def show_report_bug(self):
|
||||
msg = ' '.join([
|
||||
_("Please report any bugs as issues on github:<br/>"),
|
||||
|
@ -1998,7 +2024,6 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
|
|||
|
||||
sb = QStatusBar()
|
||||
sb.setFixedHeight(35)
|
||||
qtVersion = qVersion()
|
||||
|
||||
self.balance_label = QLabel("Loading wallet...")
|
||||
self.balance_label.setTextInteractionFlags(Qt.TextSelectableByMouse)
|
||||
|
@ -2010,6 +2035,13 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
|
|||
self.search_box.hide()
|
||||
sb.addPermanentWidget(self.search_box)
|
||||
|
||||
self.update_check_button = QPushButton("")
|
||||
self.update_check_button.setFlat(True)
|
||||
self.update_check_button.setCursor(QCursor(Qt.PointingHandCursor))
|
||||
self.update_check_button.setIcon(QIcon(":icons/update.png"))
|
||||
self.update_check_button.hide()
|
||||
sb.addPermanentWidget(self.update_check_button)
|
||||
|
||||
self.lock_icon = QIcon()
|
||||
self.password_button = StatusBarButton(self.lock_icon, _("Password"), self.change_password_dialog )
|
||||
sb.addPermanentWidget(self.password_button)
|
||||
|
@ -2905,6 +2937,13 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
|
|||
colortheme_combo.currentIndexChanged.connect(on_colortheme)
|
||||
gui_widgets.append((colortheme_label, colortheme_combo))
|
||||
|
||||
updatecheck_cb = QCheckBox(_("Automatically check for software updates"))
|
||||
updatecheck_cb.setChecked(self.config.get('check_updates', False))
|
||||
def on_set_updatecheck(v):
|
||||
self.config.set_key('check_updates', v == Qt.Checked, save=True)
|
||||
updatecheck_cb.stateChanged.connect(on_set_updatecheck)
|
||||
gui_widgets.append((updatecheck_cb, None))
|
||||
|
||||
usechange_cb = QCheckBox(_('Use change addresses'))
|
||||
usechange_cb.setChecked(self.wallet.use_change)
|
||||
if not self.config.is_modifiable('use_change'): usechange_cb.setEnabled(False)
|
||||
|
@ -3078,7 +3117,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
|
|||
tabs_info = [
|
||||
(fee_widgets, _('Fees')),
|
||||
(tx_widgets, _('Transactions')),
|
||||
(gui_widgets, _('Appearance')),
|
||||
(gui_widgets, _('General')),
|
||||
(fiat_widgets, _('Fiat')),
|
||||
(id_widgets, _('Identity')),
|
||||
]
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
import asyncio
|
||||
import os.path
|
||||
import time
|
||||
import sys
|
||||
import platform
|
||||
import queue
|
||||
import traceback
|
||||
from distutils.version import StrictVersion
|
||||
from functools import partial
|
||||
from typing import NamedTuple, Callable, Optional, TYPE_CHECKING
|
||||
|
||||
|
@ -10,8 +13,9 @@ from PyQt5.QtGui import *
|
|||
from PyQt5.QtCore import *
|
||||
from PyQt5.QtWidgets import *
|
||||
|
||||
from electrum import version
|
||||
from electrum.i18n import _, languages
|
||||
from electrum.util import FileImportFailed, FileExportFailed
|
||||
from electrum.util import FileImportFailed, FileExportFailed, make_aiohttp_session, PrintError
|
||||
from electrum.paymentrequest import PR_UNPAID, PR_PAID, PR_EXPIRED
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
@ -819,6 +823,97 @@ class FromList(QTreeWidget):
|
|||
self.header().setSectionResizeMode(0, sm)
|
||||
self.header().setSectionResizeMode(1, sm)
|
||||
|
||||
|
||||
class UpdateCheck(QWidget, PrintError):
|
||||
url = "https://electrum.org/version"
|
||||
download_url = "https://electrum.org/#download"
|
||||
|
||||
def __init__(self, main_window, latest_version=None):
|
||||
self.main_window = main_window
|
||||
QWidget.__init__(self)
|
||||
self.setWindowTitle('Electrum - ' + _('Update Check'))
|
||||
self.content = QVBoxLayout()
|
||||
self.content.setContentsMargins(*[10]*4)
|
||||
|
||||
self.heading_label = QLabel()
|
||||
self.content.addWidget(self.heading_label)
|
||||
|
||||
self.detail_label = QLabel()
|
||||
self.content.addWidget(self.detail_label)
|
||||
|
||||
self.pb = QProgressBar()
|
||||
self.pb.setMaximum(0)
|
||||
self.pb.setMinimum(0)
|
||||
self.content.addWidget(self.pb)
|
||||
|
||||
versions = QHBoxLayout()
|
||||
versions.addWidget(QLabel(_("Current version: {}".format(version.ELECTRUM_VERSION))))
|
||||
self.latest_version_label = QLabel(_("Latest version: {}".format(" ")))
|
||||
versions.addWidget(self.latest_version_label)
|
||||
self.content.addLayout(versions)
|
||||
|
||||
self.update_view(latest_version)
|
||||
|
||||
self.update_check_thread = UpdateCheckThread(self.main_window)
|
||||
self.update_check_thread.checked.connect(self.on_version_retrieved)
|
||||
self.update_check_thread.failed.connect(self.on_retrieval_failed)
|
||||
self.update_check_thread.start()
|
||||
|
||||
close_button = QPushButton(_("Close"))
|
||||
close_button.clicked.connect(self.close)
|
||||
self.content.addWidget(close_button)
|
||||
self.setLayout(self.content)
|
||||
self.show()
|
||||
|
||||
def on_version_retrieved(self, version):
|
||||
self.update_view(version)
|
||||
|
||||
def on_retrieval_failed(self):
|
||||
self.heading_label.setText('<h2>' + _("Update check failed") + '</h2>')
|
||||
self.detail_label.setText(_("Sorry, but we were unable to check for updates. Please try again later."))
|
||||
self.pb.hide()
|
||||
|
||||
@staticmethod
|
||||
def is_newer(latest_version):
|
||||
return latest_version > StrictVersion(version.ELECTRUM_VERSION)
|
||||
|
||||
def update_view(self, latest_version=None):
|
||||
if latest_version:
|
||||
self.pb.hide()
|
||||
self.latest_version_label.setText(_("Latest version: {}".format(latest_version)))
|
||||
if self.is_newer(latest_version):
|
||||
self.heading_label.setText('<h2>' + _("There is a new update available") + '</h2>')
|
||||
url = "<a href='{u}'>{u}</a>".format(u=UpdateCheck.download_url)
|
||||
self.detail_label.setText(_("You can download the new version from {}.").format(url))
|
||||
else:
|
||||
self.heading_label.setText('<h2>' + _("Already up to date") + '</h2>')
|
||||
self.detail_label.setText(_("You are already on the latest version of Electrum."))
|
||||
else:
|
||||
self.heading_label.setText('<h2>' + _("Checking for updates...") + '</h2>')
|
||||
self.detail_label.setText(_("Please wait while Electrum checks for available updates."))
|
||||
|
||||
|
||||
class UpdateCheckThread(QThread, PrintError):
|
||||
checked = pyqtSignal(object)
|
||||
failed = pyqtSignal()
|
||||
|
||||
def __init__(self, main_window):
|
||||
super().__init__()
|
||||
self.main_window = main_window
|
||||
|
||||
async def get_update_info(self):
|
||||
async with make_aiohttp_session(proxy=self.main_window.network.proxy) as session:
|
||||
async with session.get(UpdateCheck.url) as result:
|
||||
return StrictVersion((await result.text()).strip())
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
self.checked.emit(asyncio.run_coroutine_threadsafe(self.get_update_info(), self.main_window.network.asyncio_loop).result())
|
||||
except Exception:
|
||||
self.print_error(traceback.format_exc())
|
||||
self.failed.emit()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app = QApplication([])
|
||||
t = WaitingDialog(None, 'testing ...', lambda: [time.sleep(1)], lambda x: QMessageBox.information(None, 'done', "done"))
|
||||
|
|
|
@ -63,6 +63,7 @@
|
|||
<file>icons/unconfirmed.png</file>
|
||||
<file>icons/unpaid.png</file>
|
||||
<file>icons/unlock.png</file>
|
||||
<file>icons/update.png</file>
|
||||
<file>icons/warning.png</file>
|
||||
<file>icons/zoom.png</file>
|
||||
</qresource>
|
||||
|
|
BIN
icons/update.png
Normal file
BIN
icons/update.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
Loading…
Add table
Reference in a new issue