commit f05aabd8028e74b62eb63ad32e17cec679c3b38d parent 185d02d9df38cc2da1e6ba76d2724e87d2478050 Author: ThomasV <thomasv@electrum.org> Date: Fri, 1 Feb 2019 20:47:16 +0100 Merge pull request #5053 from SomberNight/qt_icons_file_rm rm qt icons file Diffstat:
38 files changed, 109 insertions(+), 216 deletions(-)
diff --git a/.gitignore b/.gitignore @@ -17,7 +17,6 @@ bin/ .idea # icons -electrum/gui/qt/icons_rc.py electrum/gui/kivy/theming/light-0.png electrum/gui/kivy/theming/light.atlas diff --git a/.gitmodules b/.gitmodules @@ -1,6 +1,3 @@ -[submodule "contrib/deterministic-build/electrum-icons"] - path = contrib/deterministic-build/electrum-icons - url = https://github.com/spesmilo/electrum-icons [submodule "contrib/deterministic-build/electrum-locale"] path = contrib/deterministic-build/electrum-locale url = https://github.com/spesmilo/electrum-locale diff --git a/MANIFEST.in b/MANIFEST.in @@ -7,7 +7,6 @@ include contrib/requirements/requirements.txt include contrib/requirements/requirements-hw.txt recursive-include packages *.py recursive-include packages cacert.pem -include icons.qrc graft icons graft electrum diff --git a/README.rst b/README.rst @@ -66,14 +66,6 @@ Run install (this should install dependencies):: python3 -m pip install .[fast] -Render the SVG icons to PNGs (optional):: - - for i in lock unlock confirmed status_lagging status_disconnected status_connected_proxy status_connected status_waiting preferences; do convert -background none icons/$i.svg icons/$i.png; done - -Compile the icons file for Qt:: - - sudo apt-get install pyqt5-dev-tools - pyrcc5 icons.qrc -o electrum/gui/qt/icons_rc.py Compile the protobuf description file:: diff --git a/contrib/build-wine/build-electrum-git.sh b/contrib/build-wine/build-electrum-git.sh @@ -20,7 +20,7 @@ cd tmp pushd $WINEPREFIX/drive_c/electrum -# Load electrum-icons and electrum-locale for this release +# Load electrum-locale for this release git submodule init git submodule update @@ -43,7 +43,6 @@ find -exec touch -d '2000-11-11T11:11:11+00:00' {} + popd cp $WINEPREFIX/drive_c/electrum/LICENCE . -cp $WINEPREFIX/drive_c/electrum/contrib/deterministic-build/electrum-icons/icons_rc.py $WINEPREFIX/drive_c/electrum/electrum/gui/qt/ # Install frozen dependencies $PYTHON -m pip install -r ../../deterministic-build/requirements.txt diff --git a/contrib/build-wine/deterministic.spec b/contrib/build-wine/deterministic.spec @@ -42,6 +42,8 @@ datas = [ (home+'electrum/locale', 'electrum/locale'), (home+'electrum/plugins', 'electrum/plugins'), ('C:\\Program Files (x86)\\ZBar\\bin\\', '.'), + (home+'icons/*.png', 'icons'), + (home+'icons/*.svg', 'icons'), ] datas += collect_data_files('trezorlib') datas += collect_data_files('safetlib') diff --git a/contrib/deterministic-build/check_submodules.sh b/contrib/deterministic-build/check_submodules.sh @@ -18,13 +18,6 @@ function get_git_mtime { fail=0 -for f in icons/* "icons.qrc"; do - if (( $(get_git_mtime "$f") > $(get_git_mtime "contrib/deterministic-build/electrum-icons/") )); then - echo "Modification time of $f (" $(get_git_mtime --readable "$f") ") is newer than"\ - "last update of electrum-icons" - fail=1 - fi -done if [ $(date +%s -d "2 weeks ago") -gt $(get_git_mtime "contrib/deterministic-build/electrum-locale/") ]; then echo "Last update from electrum-locale is older than 2 weeks."\ diff --git a/contrib/deterministic-build/electrum-icons b/contrib/deterministic-build/electrum-icons @@ -1 +0,0 @@ -Subproject commit 201d45cd5d855c4f9de5680ab5c53621574dc6b6 diff --git a/contrib/osx/make_osx b/contrib/osx/make_osx @@ -66,7 +66,6 @@ rm -rf $BUILDDIR > /dev/null 2>&1 mkdir $BUILDDIR cp -R ./contrib/deterministic-build/electrum-locale/locale/ ./electrum/locale/ -cp ./contrib/deterministic-build/electrum-icons/icons_rc.py ./electrum/gui/qt/ info "Downloading libusb..." diff --git a/contrib/osx/osx.spec b/contrib/osx/osx.spec @@ -76,6 +76,8 @@ datas = [ (electrum + PYPKG + '/wordlist/english.txt', PYPKG + '/wordlist'), (electrum + PYPKG + '/locale', PYPKG + '/locale'), (electrum + PYPKG + '/plugins', PYPKG + '/plugins'), + (electrum + 'icons/*.png', 'icons'), + (electrum + 'icons/*.svg', 'icons'), ] datas += collect_data_files('trezorlib') datas += collect_data_files('safetlib') diff --git a/electrum/gui/qt/__init__.py b/electrum/gui/qt/__init__.py @@ -49,14 +49,6 @@ from electrum.util import (UserCancelled, PrintError, profiler, from .installwizard import InstallWizard -try: - from . import icons_rc -except Exception as e: - print(e) - print("Error: Could not find icons file.") - print("Please run 'pyrcc5 icons.qrc -o electrum/gui/qt/icons_rc.py'") - sys.exit(1) - from .util import * # * needed for plugins from .main_window import ElectrumWindow from .network_dialog import NetworkDialog @@ -157,9 +149,9 @@ class ElectrumGui(PrintError): def tray_icon(self): if self.dark_icon: - return QIcon(':icons/electrum_dark_icon.png') + return read_QIcon('electrum_dark_icon.png') else: - return QIcon(':icons/electrum_light_icon.png') + return read_QIcon('electrum_light_icon.png') def toggle_tray_icon(self): self.dark_icon = not self.dark_icon diff --git a/electrum/gui/qt/address_dialog.py b/electrum/gui/qt/address_dialog.py @@ -59,7 +59,7 @@ class AddressDialog(WindowModalDialog): vbox.addWidget(QLabel(_("Address:"))) self.addr_e = ButtonsLineEdit(self.address) self.addr_e.addCopyButton(self.app) - icon = ":icons/qrcode_white.png" if ColorScheme.dark_scheme else ":icons/qrcode.png" + icon = "qrcode_white.png" if ColorScheme.dark_scheme else "qrcode.png" self.addr_e.addButton(icon, self.show_qr, _("Show QR Code")) self.addr_e.setReadOnly(True) vbox.addWidget(self.addr_e) diff --git a/electrum/gui/qt/exception_window.py b/electrum/gui/qt/exception_window.py @@ -32,7 +32,7 @@ from PyQt5.QtWidgets import * from electrum.i18n import _ from electrum.base_crash_reporter import BaseCrashReporter -from .util import MessageBoxMixin +from .util import MessageBoxMixin, read_QIcon class Exception_Window(BaseCrashReporter, QWidget, MessageBoxMixin): @@ -74,7 +74,7 @@ class Exception_Window(BaseCrashReporter, QWidget, MessageBoxMixin): report_button = QPushButton(_('Send Bug Report')) report_button.clicked.connect(self.send_report) - report_button.setIcon(QIcon(":icons/tab_send.png")) + report_button.setIcon(read_QIcon("tab_send.png")) buttons.addWidget(report_button) never_button = QPushButton(_('Never')) diff --git a/electrum/gui/qt/history_list.py b/electrum/gui/qt/history_list.py @@ -149,7 +149,7 @@ class HistoryModel(QAbstractItemModel, PrintError): return QVariant(d[col]) if role not in (Qt.DisplayRole, Qt.EditRole): if col == HistoryColumns.STATUS_ICON and role == Qt.DecorationRole: - return QVariant(self.view.icon_cache.get(":icons/" + TX_ICONS[status])) + return QVariant(read_QIcon(TX_ICONS[status])) elif col == HistoryColumns.STATUS_ICON and role == Qt.ToolTipRole: return QVariant(str(conf) + _(" confirmation" + ("s" if conf != 1 else ""))) elif col > HistoryColumns.DESCRIPTION and role == Qt.TextAlignmentRole: @@ -159,7 +159,7 @@ class HistoryModel(QAbstractItemModel, PrintError): return QVariant(monospace_font) elif col == HistoryColumns.DESCRIPTION and role == Qt.DecorationRole \ and self.parent.wallet.invoices.paid.get(tx_hash): - return QVariant(self.view.icon_cache.get(":icons/seal")) + return QVariant(read_QIcon("seal")) elif col in (HistoryColumns.DESCRIPTION, HistoryColumns.COIN_VALUE) \ and role == Qt.ForegroundRole and tx_item['value'].value < 0: red_brush = QBrush(QColor("#BC1E1E")) @@ -584,7 +584,7 @@ class HistoryList(MyTreeView, AcceptFileDragDrop): if child_tx: menu.addAction(_("Child pays for parent"), lambda: self.parent.cpfp(tx, child_tx)) if pr_key: - menu.addAction(self.icon_cache.get(":icons/seal"), _("View invoice"), lambda: self.parent.show_invoice(pr_key)) + menu.addAction(read_QIcon("seal"), _("View invoice"), lambda: self.parent.show_invoice(pr_key)) if tx_URL: menu.addAction(_("View on block explorer"), lambda: webbrowser.open(tx_URL)) menu.exec_(self.viewport().mapToGlobal(position)) diff --git a/electrum/gui/qt/installwizard.py b/electrum/gui/qt/installwizard.py @@ -154,7 +154,7 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard): hbox.setStretchFactor(scroll, 1) outer_vbox.addLayout(hbox) outer_vbox.addLayout(Buttons(self.back_button, self.next_button)) - self.set_icon(':icons/electrum.png') + self.set_icon('electrum.png') self.show() self.raise_() self.refresh_gui() # Need for QT on MacOSX. Lame. @@ -329,7 +329,8 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard): def set_icon(self, filename): prior_filename, self.icon_filename = self.icon_filename, filename - self.logo.setPixmap(QPixmap(filename).scaledToWidth(60, mode=Qt.SmoothTransformation)) + self.logo.setPixmap(QPixmap(icon_path(filename)) + .scaledToWidth(60, mode=Qt.SmoothTransformation)) return prior_filename def set_layout(self, layout, title=None, next_enabled=True): diff --git a/electrum/gui/qt/invoice_list.py b/electrum/gui/qt/invoice_list.py @@ -53,7 +53,7 @@ class InvoiceList(MyTreeView): labels = [date_str, requestor, pr.memo, self.parent.format_amount(pr.get_amount(), whitespaces=True), pr_tooltips.get(status,'')] items = [QStandardItem(e) for e in labels] self.set_editability(items) - items[4].setIcon(self.icon_cache.get(pr_icons.get(status))) + items[4].setIcon(read_QIcon(pr_icons.get(status))) items[0].setData(key, role=Qt.UserRole) items[1].setFont(QFont(MONOSPACE_FONT)) items[3].setFont(QFont(MONOSPACE_FONT)) diff --git a/electrum/gui/qt/main_window.py b/electrum/gui/qt/main_window.py @@ -161,9 +161,9 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): self.utxo_tab = self.create_utxo_tab() self.console_tab = self.create_console_tab() self.contacts_tab = self.create_contacts_tab() - tabs.addTab(self.create_history_tab(), QIcon(":icons/tab_history.png"), _('History')) - tabs.addTab(self.send_tab, QIcon(":icons/tab_send.png"), _('Send')) - tabs.addTab(self.receive_tab, QIcon(":icons/tab_receive.png"), _('Receive')) + tabs.addTab(self.create_history_tab(), read_QIcon("tab_history.png"), _('History')) + tabs.addTab(self.send_tab, read_QIcon("tab_send.png"), _('Send')) + tabs.addTab(self.receive_tab, read_QIcon("tab_receive.png"), _('Receive')) def add_optional_tab(tabs, tab, icon, description, name): tab.tab_icon = icon @@ -173,10 +173,10 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): if self.config.get('show_{}_tab'.format(name), False): tabs.addTab(tab, icon, description.replace("&", "")) - add_optional_tab(tabs, self.addresses_tab, QIcon(":icons/tab_addresses.png"), _("&Addresses"), "addresses") - add_optional_tab(tabs, self.utxo_tab, QIcon(":icons/tab_coins.png"), _("Co&ins"), "utxo") - add_optional_tab(tabs, self.contacts_tab, QIcon(":icons/tab_contacts.png"), _("Con&tacts"), "contacts") - add_optional_tab(tabs, self.console_tab, QIcon(":icons/tab_console.png"), _("Con&sole"), "console") + add_optional_tab(tabs, self.addresses_tab, read_QIcon("tab_addresses.png"), _("&Addresses"), "addresses") + add_optional_tab(tabs, self.utxo_tab, read_QIcon("tab_coins.png"), _("Co&ins"), "utxo") + add_optional_tab(tabs, self.contacts_tab, read_QIcon("tab_contacts.png"), _("Con&tacts"), "contacts") + add_optional_tab(tabs, self.console_tab, read_QIcon("tab_console.png"), _("Con&sole"), "console") tabs.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.setCentralWidget(tabs) @@ -184,7 +184,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): if self.config.get("is_maximized"): self.showMaximized() - self.setWindowIcon(QIcon(":icons/electrum.png")) + self.setWindowIcon(read_QIcon("electrum.png")) self.init_menubar() wrtabs = weakref.proxy(tabs) @@ -675,7 +675,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): if self.tray: try: # this requires Qt 5.9 - self.tray.showMessage("Electrum", message, QIcon(":icons/electrum_dark_icon"), 20000) + self.tray.showMessage("Electrum", message, read_QIcon("electrum_dark_icon"), 20000) except TypeError: self.tray.showMessage("Electrum", message, QSystemTrayIcon.Information, 20000) @@ -773,7 +773,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): if self.network is None: text = _("Offline") - icon = QIcon(":icons/status_disconnected.png") + icon = read_QIcon("status_disconnected.png") elif self.network.is_connected(): server_height = self.network.get_server_height() @@ -784,10 +784,10 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): # Display the synchronizing message in that case. if not self.wallet.up_to_date or server_height == 0: text = _("Synchronizing...") - icon = QIcon(":icons/status_waiting.png") + icon = read_QIcon("status_waiting.png") elif server_lag > 1: text = _("Server is lagging ({} blocks)").format(server_lag) - icon = QIcon(":icons/status_lagging%s.png"%fork_str) + icon = read_QIcon("status_lagging%s.png"%fork_str) else: c, u, x = self.wallet.get_balance() text = _("Balance" ) + ": %s "%(self.format_amount_and_units(c)) @@ -801,15 +801,15 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): text += self.fx.get_fiat_status_text(c + u + x, self.base_unit(), self.get_decimal_point()) or '' if not self.network.proxy: - icon = QIcon(":icons/status_connected%s.png"%fork_str) + icon = read_QIcon("status_connected%s.png"%fork_str) else: - icon = QIcon(":icons/status_connected_proxy%s.png"%fork_str) + icon = read_QIcon("status_connected_proxy%s.png"%fork_str) else: if self.network.proxy: text = "{} ({})".format(_("Not connected"), _("proxy enabled")) else: text = _("Not connected") - icon = QIcon(":icons/status_disconnected.png") + icon = read_QIcon("status_disconnected.png") self.tray.setToolTip("%s (%s)" % (text, self.wallet.basename())) self.balance_label.setText(text) @@ -1237,7 +1237,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): _('Also, when batching RBF transactions, BIP 125 imposes a lower bound on the fee.')) QMessageBox.information(self, 'Fee rounding', text) - self.feerounding_icon = QPushButton(QIcon(':icons/info.png'), '') + self.feerounding_icon = QPushButton(read_QIcon('info.png'), '') self.feerounding_icon.setFixedWidth(20) self.feerounding_icon.setFlat(True) self.feerounding_icon.clicked.connect(feerounding_onclick) @@ -2038,24 +2038,23 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): 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.setIcon(read_QIcon("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 ) + self.password_button = StatusBarButton(QIcon(), _("Password"), self.change_password_dialog ) sb.addPermanentWidget(self.password_button) - sb.addPermanentWidget(StatusBarButton(QIcon(":icons/preferences.png"), _("Preferences"), self.settings_dialog ) ) - self.seed_button = StatusBarButton(QIcon(":icons/seed.png"), _("Seed"), self.show_seed_dialog ) + sb.addPermanentWidget(StatusBarButton(read_QIcon("preferences.png"), _("Preferences"), self.settings_dialog ) ) + self.seed_button = StatusBarButton(read_QIcon("seed.png"), _("Seed"), self.show_seed_dialog ) sb.addPermanentWidget(self.seed_button) - self.status_button = StatusBarButton(QIcon(":icons/status_disconnected.png"), _("Network"), lambda: self.gui_object.show_network_dialog(self)) + self.status_button = StatusBarButton(read_QIcon("status_disconnected.png"), _("Network"), lambda: self.gui_object.show_network_dialog(self)) sb.addPermanentWidget(self.status_button) run_hook('create_status_bar', sb) self.setStatusBar(sb) def update_lock_icon(self): - icon = QIcon(":icons/lock.png") if self.wallet.has_password() else QIcon(":icons/unlock.png") + icon = read_QIcon("lock.png") if self.wallet.has_password() else read_QIcon("unlock.png") self.password_button.setIcon(icon) def update_buttons_on_seed(self): @@ -3356,5 +3355,5 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): msg = (_("Transaction added to wallet history.") + '\n\n' + _("Note: this is an offline transaction, if you want the network " "to see it, you need to broadcast it.")) - win.msg_box(QPixmap(":icons/offline_tx.png"), None, _('Success'), msg) + win.msg_box(QPixmap(icon_path("offline_tx.png")), None, _('Success'), msg) return True diff --git a/electrum/gui/qt/network_dialog.py b/electrum/gui/qt/network_dialog.py @@ -270,7 +270,7 @@ class NetworkChoiceLayout(object): self.proxy_password.textEdited.connect(self.proxy_settings_changed) self.tor_cb = QCheckBox(_("Use Tor Proxy")) - self.tor_cb.setIcon(QIcon(":icons/tor_logo.png")) + self.tor_cb.setIcon(read_QIcon("tor_logo.png")) self.tor_cb.hide() self.tor_cb.clicked.connect(self.use_tor_proxy) diff --git a/electrum/gui/qt/password_dialog.py b/electrum/gui/qt/password_dialog.py @@ -103,10 +103,11 @@ class PasswordLayout(object): if wallet and wallet.has_password(): grid.addWidget(QLabel(_('Current Password:')), 0, 0) grid.addWidget(self.pw, 0, 1) - lockfile = ":icons/lock.png" + lockfile = "lock.png" else: - lockfile = ":icons/unlock.png" - logo.setPixmap(QPixmap(lockfile).scaledToWidth(36, mode=Qt.SmoothTransformation)) + lockfile = "unlock.png" + logo.setPixmap(QPixmap(icon_path(lockfile)) + .scaledToWidth(36, mode=Qt.SmoothTransformation)) grid.addWidget(QLabel(msgs[0]), 1, 0) grid.addWidget(self.new_pw, 1, 1) @@ -195,10 +196,11 @@ class PasswordLayoutForHW(object): vbox.addLayout(logo_grid) if wallet and wallet.has_storage_encryption(): - lockfile = ":icons/lock.png" + lockfile = "lock.png" else: - lockfile = ":icons/unlock.png" - logo.setPixmap(QPixmap(lockfile).scaledToWidth(36, mode=Qt.SmoothTransformation)) + lockfile = "unlock.png" + logo.setPixmap(QPixmap(icon_path(lockfile)) + .scaledToWidth(36, mode=Qt.SmoothTransformation)) vbox.addLayout(grid) diff --git a/electrum/gui/qt/qrtextedit.py b/electrum/gui/qt/qrtextedit.py @@ -13,7 +13,7 @@ class ShowQRTextEdit(ButtonsTextEdit): def __init__(self, text=None): ButtonsTextEdit.__init__(self, text) self.setReadOnly(1) - icon = ":icons/qrcode_white.png" if ColorScheme.dark_scheme else ":icons/qrcode.png" + icon = "qrcode_white.png" if ColorScheme.dark_scheme else "qrcode.png" self.addButton(icon, self.qr_show, _("Show as QR code")) run_hook('show_text_edit', self) @@ -38,8 +38,8 @@ class ScanQRTextEdit(ButtonsTextEdit, MessageBoxMixin): ButtonsTextEdit.__init__(self, text) self.allow_multi = allow_multi self.setReadOnly(0) - self.addButton(":icons/file.png", self.file_input, _("Read file")) - icon = ":icons/camera_white.png" if ColorScheme.dark_scheme else ":icons/camera_dark.png" + self.addButton("file.png", self.file_input, _("Read file")) + icon = "camera_white.png" if ColorScheme.dark_scheme else "camera_dark.png" self.addButton(icon, self.qr_input, _("Read QR code")) run_hook('scan_text_edit', self) diff --git a/electrum/gui/qt/request_list.py b/electrum/gui/qt/request_list.py @@ -33,7 +33,7 @@ from electrum.plugin import run_hook from electrum.paymentrequest import PR_UNKNOWN from electrum.wallet import InternalAddressCorruption -from .util import MyTreeView, pr_tooltips, pr_icons +from .util import MyTreeView, pr_tooltips, pr_icons, read_QIcon class RequestList(MyTreeView): filter_columns = [0, 1, 2, 3, 4] # Date, Account, Address, Description, Amount @@ -108,10 +108,10 @@ class RequestList(MyTreeView): items = [QStandardItem(e) for e in labels] self.set_editability(items) if signature is not None: - items[2].setIcon(self.icon_cache.get(":icons/seal.png")) + items[2].setIcon(read_QIcon("seal.png")) items[2].setToolTip('signed by '+ requestor) if status is not PR_UNKNOWN: - items[5].setIcon(self.icon_cache.get(pr_icons.get(status))) + items[5].setIcon(read_QIcon(pr_icons.get(status))) items[3].setData(address, Qt.UserRole) self.model().insertRow(self.model().rowCount(), items) diff --git a/electrum/gui/qt/seed_dialog.py b/electrum/gui/qt/seed_dialog.py @@ -110,7 +110,8 @@ class SeedLayout(QVBoxLayout): hbox = QHBoxLayout() if icon: logo = QLabel() - logo.setPixmap(QPixmap(":icons/seed.png").scaledToWidth(64, mode=Qt.SmoothTransformation)) + logo.setPixmap(QPixmap(icon_path("seed.png")) + .scaledToWidth(64, mode=Qt.SmoothTransformation)) logo.setMaximumWidth(60) hbox.addWidget(logo) hbox.addWidget(self.seed_e) diff --git a/electrum/gui/qt/transaction_dialog.py b/electrum/gui/qt/transaction_dialog.py @@ -98,7 +98,7 @@ class TxDialog(QDialog, MessageBoxMixin): vbox.addWidget(QLabel(_("Transaction ID:"))) self.tx_hash_e = ButtonsLineEdit() qr_show = lambda: parent.show_qrcode(str(self.tx_hash_e.text()), 'Transaction ID', parent=self) - qr_icon = ":icons/qrcode_white.png" if ColorScheme.dark_scheme else ":icons/qrcode.png" + qr_icon = "qrcode_white.png" if ColorScheme.dark_scheme else "qrcode.png" self.tx_hash_e.addButton(qr_icon, qr_show, _("Show as QR code")) self.tx_hash_e.setReadOnly(True) vbox.addWidget(self.tx_hash_e) diff --git a/electrum/gui/qt/util.py b/electrum/gui/qt/util.py @@ -6,7 +6,7 @@ import platform import queue import traceback from distutils.version import StrictVersion -from functools import partial +from functools import partial, lru_cache from typing import NamedTuple, Callable, Optional, TYPE_CHECKING import base64 @@ -18,7 +18,8 @@ from electrum import version from electrum import ecc from electrum import constants from electrum.i18n import _, languages -from electrum.util import FileImportFailed, FileExportFailed, make_aiohttp_session, PrintError +from electrum.util import (FileImportFailed, FileExportFailed, make_aiohttp_session, + PrintError, resource_path) from electrum.paymentrequest import PR_UNPAID, PR_PAID, PR_EXPIRED if TYPE_CHECKING: @@ -36,9 +37,9 @@ else: dialogs = [] pr_icons = { - PR_UNPAID:":icons/unpaid.png", - PR_PAID:":icons/confirmed.png", - PR_EXPIRED:":icons/expired.png" + PR_UNPAID:"unpaid.png", + PR_PAID:"confirmed.png", + PR_EXPIRED:"expired.png" } pr_tooltips = { @@ -429,8 +430,6 @@ class MyTreeView(QTreeView): self.customContextMenuRequested.connect(create_menu) self.setUniformRowHeights(True) - self.icon_cache = IconCache() - # Control which columns are editable if editable_columns is None: editable_columns = {stretch_column} @@ -599,7 +598,7 @@ class ButtonsWidget(QWidget): def addButton(self, icon_name, on_click, tooltip): button = QToolButton(self) - button.setIcon(QIcon(icon_name)) + button.setIcon(read_QIcon(icon_name)) button.setIconSize(QSize(25,25)) button.setStyleSheet("QToolButton { border: none; hover {border: 1px} pressed {border: 1px} padding: 0px; }") button.setVisible(True) @@ -610,7 +609,7 @@ class ButtonsWidget(QWidget): def addCopyButton(self, app): self.app = app - self.addButton(":icons/copy.png", self.on_copy, _("Copy to clipboard")) + self.addButton("copy.png", self.on_copy, _("Copy to clipboard")) def on_copy(self): self.app.clipboard().setText(self.text()) @@ -795,15 +794,14 @@ def get_parent_main_window(widget): return widget return None -class IconCache: - def __init__(self): - self.__cache = {} +def icon_path(icon_basename): + return resource_path('icons', icon_basename) + - def get(self, file_name): - if file_name not in self.__cache: - self.__cache[file_name] = QIcon(file_name) - return self.__cache[file_name] +@lru_cache(maxsize=1000) +def read_QIcon(icon_basename): + return QIcon(icon_path(icon_basename)) def get_default_language(): diff --git a/electrum/plugins/audio_modem/qt.py b/electrum/plugins/audio_modem/qt.py @@ -6,7 +6,7 @@ import sys import platform from electrum.plugin import BasePlugin, hook -from electrum.gui.qt.util import WaitingDialog, EnterButton, WindowModalDialog +from electrum.gui.qt.util import WaitingDialog, EnterButton, WindowModalDialog, read_QIcon from electrum.util import print_msg, print_error from electrum.i18n import _ @@ -71,7 +71,7 @@ class Plugin(BasePlugin): @hook def transaction_dialog(self, dialog): b = QPushButton() - b.setIcon(QIcon(":icons/speaker.png")) + b.setIcon(read_QIcon("speaker.png")) def handler(): blob = json.dumps(dialog.tx.as_dict()) @@ -81,7 +81,7 @@ class Plugin(BasePlugin): @hook def scan_text_edit(self, parent): - parent.addButton(':icons/microphone.png', partial(self._recv, parent), + parent.addButton('microphone.png', partial(self._recv, parent), _("Read from microphone")) @hook @@ -89,7 +89,7 @@ class Plugin(BasePlugin): def handler(): blob = str(parent.toPlainText()) self._send(parent=parent, blob=blob) - parent.addButton(':icons/speaker.png', handler, _("Send to speaker")) + parent.addButton('speaker.png', handler, _("Send to speaker")) def _audio_interface(self): interface = amodem.audio.Interface(config=self.modem_config) diff --git a/electrum/plugins/coldcard/qt.py b/electrum/plugins/coldcard/qt.py @@ -11,8 +11,8 @@ from ..hw_wallet.plugin import only_hook_if_libraries_available class Plugin(ColdcardPlugin, QtPluginBase): - icon_unpaired = ":icons/coldcard_unpaired.png" - icon_paired = ":icons/coldcard.png" + icon_unpaired = "coldcard_unpaired.png" + icon_paired = "coldcard.png" def create_handler(self, window): return Coldcard_Handler(window) diff --git a/electrum/plugins/digitalbitbox/qt.py b/electrum/plugins/digitalbitbox/qt.py @@ -10,8 +10,8 @@ from .digitalbitbox import DigitalBitboxPlugin class Plugin(DigitalBitboxPlugin, QtPluginBase): - icon_unpaired = ":icons/digitalbitbox_unpaired.png" - icon_paired = ":icons/digitalbitbox.png" + icon_unpaired = "digitalbitbox_unpaired.png" + icon_paired = "digitalbitbox.png" def create_handler(self, window): return DigitalBitbox_Handler(window) diff --git a/electrum/plugins/hw_wallet/qt.py b/electrum/plugins/hw_wallet/qt.py @@ -73,8 +73,8 @@ class QtHandlerBase(QObject, PrintError): def _update_status(self, paired): if hasattr(self, 'button'): button = self.button - icon = button.icon_paired if paired else button.icon_unpaired - button.setIcon(QIcon(icon)) + icon_name = button.icon_paired if paired else button.icon_unpaired + button.setIcon(read_QIcon(icon_name)) def query_choice(self, msg, labels): self.done.clear() @@ -234,4 +234,4 @@ class QtPluginBase(object): def show_address(): addr = receive_address_e.text() keystore.thread.add(partial(plugin.show_address, wallet, addr, keystore)) - receive_address_e.addButton(":icons/eye1.png", show_address, _("Show on {}").format(plugin.device)) + receive_address_e.addButton("eye1.png", show_address, _("Show on {}").format(plugin.device)) diff --git a/electrum/plugins/keepkey/qt.py b/electrum/plugins/keepkey/qt.py @@ -295,8 +295,8 @@ class QtPlugin(QtPluginBase): class Plugin(KeepKeyPlugin, QtPlugin): - icon_paired = ":icons/keepkey.png" - icon_unpaired = ":icons/keepkey_unpaired.png" + icon_paired = "keepkey.png" + icon_unpaired = "keepkey_unpaired.png" @classmethod def pin_matrix_widget_class(self): diff --git a/electrum/plugins/ledger/qt.py b/electrum/plugins/ledger/qt.py @@ -11,8 +11,8 @@ from ..hw_wallet.plugin import only_hook_if_libraries_available class Plugin(LedgerPlugin, QtPluginBase): - icon_unpaired = ":icons/ledger_unpaired.png" - icon_paired = ":icons/ledger.png" + icon_unpaired = "ledger_unpaired.png" + icon_paired = "ledger.png" def create_handler(self, window): return Ledger_Handler(window) diff --git a/electrum/plugins/revealer/qt.py b/electrum/plugins/revealer/qt.py @@ -54,7 +54,7 @@ class Plugin(RevealerPlugin): @hook def create_status_bar(self, parent): - b = StatusBarButton(QIcon(':icons/revealer.png'), "Revealer "+_("secret backup utility"), + b = StatusBarButton(read_QIcon('revealer.png'), "Revealer "+_("secret backup utility"), partial(self.setup_dialog, parent)) parent.addPermanentWidget(b) @@ -98,7 +98,7 @@ class Plugin(RevealerPlugin): vbox = QVBoxLayout() logo = QLabel() self.hbox.addWidget(logo) - logo.setPixmap(QPixmap(':icons/revealer.png')) + logo.setPixmap(QPixmap(icon_path('revealer.png'))) logo.setAlignment(Qt.AlignLeft) self.hbox.addSpacing(16) vbox.addWidget(WWLabel("<b>"+_("Revealer Secret Backup Plugin")+"</b><br>" @@ -228,7 +228,7 @@ class Plugin(RevealerPlugin): self.vbox = QVBoxLayout() logo = QLabel() hbox.addWidget(logo) - logo.setPixmap(QPixmap(':icons/revealer.png')) + logo.setPixmap(QPixmap(icon_path('revealer.png'))) logo.setAlignment(Qt.AlignLeft) hbox.addSpacing(16) self.vbox.addWidget(WWLabel("<b>" + _("Revealer Secret Backup Plugin") + "</b><br>" @@ -549,7 +549,7 @@ class Plugin(RevealerPlugin): painter.drawLine(base_img.width()-(dist_h), 0, base_img.width()-(dist_h), base_img.height()) painter.drawImage(((total_distance_h))+11, ((total_distance_h))+11, - QImage(':icons/electrumb.png').scaledToWidth(2.1*(total_distance_h), Qt.SmoothTransformation)) + QImage(icon_path('electrumb.png')).scaledToWidth(2.1*(total_distance_h), Qt.SmoothTransformation)) painter.setPen(QPen(Qt.white, border_thick*8)) painter.drawLine(base_img.width()-((total_distance_h))-(border_thick*8)/2-(border_thick/2)-2, @@ -575,7 +575,7 @@ class Plugin(RevealerPlugin): painter.drawLine(dist_h, 0, dist_h, base_img.height()) painter.drawLine(0, base_img.height()-dist_v, base_img.width(), base_img.height()-(dist_v)) painter.drawLine(base_img.width()-(dist_h), 0, base_img.width()-(dist_h), base_img.height()) - logo = QImage(':icons/revealer_c.png').scaledToWidth(1.3*(total_distance_h)) + logo = QImage(icon_path('revealer_c.png')).scaledToWidth(1.3*(total_distance_h)) painter.drawImage((total_distance_h)+ (border_thick), ((total_distance_h))+ (border_thick), logo, Qt.SmoothTransformation) #frame around logo diff --git a/electrum/plugins/safe_t/qt.py b/electrum/plugins/safe_t/qt.py @@ -169,8 +169,8 @@ class QtPlugin(QtPluginBase): class Plugin(SafeTPlugin, QtPlugin): - icon_unpaired = ":icons/safe-t_unpaired.png" - icon_paired = ":icons/safe-t.png" + icon_unpaired = "safe-t_unpaired.png" + icon_paired = "safe-t.png" @classmethod def pin_matrix_widget_class(self): diff --git a/electrum/plugins/trezor/qt.py b/electrum/plugins/trezor/qt.py @@ -259,8 +259,8 @@ class QtPlugin(QtPluginBase): class Plugin(TrezorPlugin, QtPlugin): - icon_unpaired = ":icons/trezor_unpaired.png" - icon_paired = ":icons/trezor.png" + icon_unpaired = "trezor_unpaired.png" + icon_paired = "trezor.png" @classmethod def pin_matrix_widget_class(self): diff --git a/electrum/plugins/trustedcoin/qt.py b/electrum/plugins/trustedcoin/qt.py @@ -90,7 +90,7 @@ class Plugin(TrustedCoinPlugin): action = lambda: window.show_message(msg) else: action = partial(self.settings_dialog, window) - button = StatusBarButton(QIcon(":icons/trustedcoin-status.png"), + button = StatusBarButton(read_QIcon("trustedcoin-status.png"), _("TrustedCoin"), action) window.statusBar().addPermanentWidget(button) self.start_request_thread(window.wallet) @@ -152,7 +152,7 @@ class Plugin(TrustedCoinPlugin): hbox = QHBoxLayout() logo = QLabel() - logo.setPixmap(QPixmap(":icons/trustedcoin-status.png")) + logo.setPixmap(QPixmap(icon_path("trustedcoin-status.png"))) msg = _('This wallet is protected by TrustedCoin\'s two-factor authentication.') + '<br/>'\ + _("For more information, visit") + " <a href=\"https://api.trustedcoin.com/#/electrum-help\">https://api.trustedcoin.com/#/electrum-help</a>" label = QLabel(msg) diff --git a/electrum/plugins/trustedcoin/trustedcoin.py b/electrum/plugins/trustedcoin/trustedcoin.py @@ -492,7 +492,7 @@ class TrustedCoinPlugin(BasePlugin): window.wallet.is_billing = False def show_disclaimer(self, wizard): - wizard.set_icon(':icons/trustedcoin-wizard.png') + wizard.set_icon('trustedcoin-wizard.png') wizard.stack = [] wizard.confirm_dialog(title='Disclaimer', message='\n\n'.join(self.disclaimer_msg), run_next = lambda x: wizard.run('choose_seed')) @@ -581,7 +581,7 @@ class TrustedCoinPlugin(BasePlugin): wizard.passphrase_dialog(run_next=f) if is_ext else f('') def restore_choice(self, wizard, seed, passphrase): - wizard.set_icon(':icons/trustedcoin-wizard.png') + wizard.set_icon('trustedcoin-wizard.png') wizard.stack = [] title = _('Restore 2FA wallet') msg = ' '.join([ diff --git a/electrum/util.py b/electrum/util.py @@ -488,6 +488,15 @@ def user_dir(): #raise Exception("No home directory found in environment variables.") return + +def resource_path(*parts): + return os.path.join(base_dir, *parts) + + +# absolute path to project root dir when running from source +base_dir = os.path.split(os.path.dirname(os.path.realpath(__file__)))[0] + + def is_valid_email(s): regexp = r"[^@]+@[^@]+\.[^@]+" return re.match(regexp, s) is not None diff --git a/icons.qrc b/icons.qrc @@ -1,70 +0,0 @@ -<RCC> - <qresource prefix="/" > - <file>icons/electrum.png</file> - <file>icons/clock1.png</file> - <file>icons/clock2.png</file> - <file>icons/clock3.png</file> - <file>icons/clock4.png</file> - <file>icons/clock5.png</file> - <file>icons/confirmed.png</file> - <file>icons/copy.png</file> - <file>icons/digitalbitbox.png</file> - <file>icons/digitalbitbox_unpaired.png</file> - <file>icons/expired.png</file> - <file>icons/electrum_light_icon.png</file> - <file>icons/electrum_dark_icon.png</file> - <file>icons/electrumb.png</file> - <file>icons/eye1.png</file> - <file>icons/file.png</file> - <file>icons/info.png</file> - <file>icons/keepkey.png</file> - <file>icons/keepkey_unpaired.png</file> - <file>icons/key.png</file> - <file>icons/ledger.png</file> - <file>icons/ledger_unpaired.png</file> - <file>icons/lock.png</file> - <file>icons/microphone.png</file> - <file>icons/network.png</file> - <file>icons/offline_tx.png</file> - <file>icons/revealer.png</file> - <file>icons/revealer_c.png</file> - <file>icons/qrcode.png</file> - <file>icons/qrcode_white.png</file> - <file>icons/camera_dark.png</file> - <file>icons/camera_white.png</file> - <file>icons/preferences.png</file> - <file>icons/safe-t_unpaired.png</file> - <file>icons/safe-t.png</file> - <file>icons/seed.png</file> - <file>icons/status_connected.png</file> - <file>icons/status_connected_fork.png</file> - <file>icons/status_connected_proxy.png</file> - <file>icons/status_connected_proxy_fork.png</file> - <file>icons/status_disconnected.png</file> - <file>icons/status_waiting.png</file> - <file>icons/status_lagging.png</file> - <file>icons/status_lagging_fork.png</file> - <file>icons/seal.png</file> - <file>icons/tab_addresses.png</file> - <file>icons/tab_coins.png</file> - <file>icons/tab_console.png</file> - <file>icons/tab_contacts.png</file> - <file>icons/tab_history.png</file> - <file>icons/tab_receive.png</file> - <file>icons/tab_send.png</file> - <file>icons/tor_logo.png</file> - <file>icons/speaker.png</file> - <file>icons/trezor_unpaired.png</file> - <file>icons/trezor.png</file> - <file>icons/coldcard.png</file> - <file>icons/coldcard_unpaired.png</file> - <file>icons/trustedcoin-status.png</file> - <file>icons/trustedcoin-wizard.png</file> - <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> -</RCC> diff --git a/setup.py b/setup.py @@ -58,23 +58,6 @@ extras_require = { extras_require['full'] = [pkg for sublist in list(extras_require.values()) for pkg in sublist] -class CustomInstallCommand(install): - def run(self): - install.run(self) - # potentially build Qt icons file - try: - import PyQt5 - except ImportError: - pass - else: - try: - path = os.path.join(self.install_lib, "electrum/gui/qt/icons_rc.py") - if not os.path.exists(path): - subprocess.call(["pyrcc5", "icons.qrc", "-o", path]) - except Exception as e: - print('Warning: building icons file failed with {}'.format(repr(e))) - - setup( name="Electrum", version=version.ELECTRUM_VERSION, @@ -105,7 +88,4 @@ setup( license="MIT Licence", url="https://electrum.org", long_description="""Lightweight Bitcoin Wallet""", - cmdclass={ - 'install': CustomInstallCommand, - }, )