diff --git a/electrum/gui/qt/util.py b/electrum/gui/qt/util.py
index 4817855be..4a06f6a29 100644
--- a/electrum/gui/qt/util.py
+++ b/electrum/gui/qt/util.py
@@ -1242,14 +1242,21 @@ def getSaveFileName(
def icon_path(icon_basename: str):
return resource_path('gui', 'icons', icon_basename)
+def internal_plugin_icon_path(plugin_name, icon_basename: str):
+ return resource_path('plugins', plugin_name, icon_basename)
+
@lru_cache(maxsize=1000)
def read_QIcon(icon_basename: str) -> QIcon:
return QIcon(icon_path(icon_basename))
-def read_QIcon_from_bytes(b: bytes) -> QIcon:
+def read_QPixmap_from_bytes(b: bytes) -> QPixmap:
qp = QPixmap()
qp.loadFromData(b)
+ return qp
+
+def read_QIcon_from_bytes(b: bytes) -> QIcon:
+ qp = read_QPixmap_from_bytes(b)
return QIcon(qp)
class IconLabel(QWidget):
diff --git a/electrum/plugin.py b/electrum/plugin.py
index 33294be34..eb7a8f49d 100644
--- a/electrum/plugin.py
+++ b/electrum/plugin.py
@@ -441,13 +441,16 @@ class BasePlugin(Logger):
raise NotImplementedError()
def read_file(self, filename: str) -> bytes:
- """ note: only for external plugins """
import zipfile
- plugin_filename = self.parent.external_plugin_path(self.name)
- with zipfile.ZipFile(plugin_filename) as myzip:
- with myzip.open(os.path.join(self.name, filename)) as myfile:
- s = myfile.read()
- return s
+ if self.name in self.parent.external_plugin_metadata:
+ plugin_filename = self.parent.external_plugin_path(self.name)
+ with zipfile.ZipFile(plugin_filename) as myzip:
+ with myzip.open(os.path.join(self.name, filename)) as myfile:
+ return myfile.read()
+ else:
+ path = os.path.join(os.path.dirname(__file__), 'plugins', self.name, filename)
+ with open(path, 'rb') as myfile:
+ return myfile.read()
class DeviceUnpairableError(UserFacingException): pass
diff --git a/electrum/gui/icons/bitbox02.png b/electrum/plugins/bitbox02/bitbox02.png
similarity index 100%
rename from electrum/gui/icons/bitbox02.png
rename to electrum/plugins/bitbox02/bitbox02.png
diff --git a/electrum/gui/icons/bitbox02_unpaired.png b/electrum/plugins/bitbox02/bitbox02_unpaired.png
similarity index 100%
rename from electrum/gui/icons/bitbox02_unpaired.png
rename to electrum/plugins/bitbox02/bitbox02_unpaired.png
diff --git a/electrum/gui/icons/coldcard.png b/electrum/plugins/coldcard/coldcard.png
similarity index 100%
rename from electrum/gui/icons/coldcard.png
rename to electrum/plugins/coldcard/coldcard.png
diff --git a/electrum/gui/icons/coldcard.svg b/electrum/plugins/coldcard/coldcard.svg
similarity index 100%
rename from electrum/gui/icons/coldcard.svg
rename to electrum/plugins/coldcard/coldcard.svg
diff --git a/electrum/gui/icons/coldcard_unpaired.png b/electrum/plugins/coldcard/coldcard_unpaired.png
similarity index 100%
rename from electrum/gui/icons/coldcard_unpaired.png
rename to electrum/plugins/coldcard/coldcard_unpaired.png
diff --git a/electrum/gui/icons/coldcard_unpaired.svg b/electrum/plugins/coldcard/coldcard_unpaired.svg
similarity index 100%
rename from electrum/gui/icons/coldcard_unpaired.svg
rename to electrum/plugins/coldcard/coldcard_unpaired.svg
diff --git a/electrum/gui/icons/digitalbitbox.png b/electrum/plugins/digitalbitbox/digitalbitbox.png
similarity index 100%
rename from electrum/gui/icons/digitalbitbox.png
rename to electrum/plugins/digitalbitbox/digitalbitbox.png
diff --git a/electrum/gui/icons/digitalbitbox_unpaired.png b/electrum/plugins/digitalbitbox/digitalbitbox_unpaired.png
similarity index 100%
rename from electrum/gui/icons/digitalbitbox_unpaired.png
rename to electrum/plugins/digitalbitbox/digitalbitbox_unpaired.png
diff --git a/electrum/plugins/hw_wallet/qt.py b/electrum/plugins/hw_wallet/qt.py
index c75d1be04..99a58ec9b 100644
--- a/electrum/plugins/hw_wallet/qt.py
+++ b/electrum/plugins/hw_wallet/qt.py
@@ -36,6 +36,7 @@ from electrum.gui.qt.util import (read_QIcon, WWLabel, OkButton, WindowModalDial
Buttons, CancelButton, TaskThread, char_width_in_lineedit,
PasswordLineEdit)
from electrum.gui.qt.main_window import StatusBarButton
+from electrum.gui.qt.util import read_QIcon_from_bytes
from electrum.i18n import _
from electrum.logging import Logger
@@ -92,8 +93,9 @@ class QtHandlerBase(HardwareHandlerBase, QObject, Logger):
def _update_status(self, paired):
if hasattr(self, 'button'):
button = self.button
- icon_name = button.icon_paired if paired else button.icon_unpaired
- button.setIcon(read_QIcon(icon_name))
+ icon_bytes = button.icon_paired if paired else button.icon_unpaired
+ icon = read_QIcon_from_bytes(icon_bytes)
+ button.setIcon(icon)
def query_choice(self, msg: str, labels: Sequence[Tuple]):
self.done.clear()
@@ -222,9 +224,10 @@ class QtPluginBase(object):
tooltip = self.device + '\n' + (keystore.label or 'unnamed')
cb = partial(self._on_status_bar_button_click, window=window, keystore=keystore)
sb = window.statusBar()
- button = StatusBarButton(read_QIcon(self.icon_unpaired), tooltip, cb, sb.height())
- button.icon_paired = self.icon_paired
- button.icon_unpaired = self.icon_unpaired
+ icon = read_QIcon_from_bytes(self.read_file(self.icon_unpaired))
+ button = StatusBarButton(icon, tooltip, cb, sb.height())
+ button.icon_paired = self.read_file(self.icon_paired)
+ button.icon_unpaired = self.read_file(self.icon_unpaired)
sb.addPermanentWidget(button)
handler = self.create_handler(window)
handler.button = button
diff --git a/electrum/gui/icons/jade.png b/electrum/plugins/jade/jade.png
similarity index 100%
rename from electrum/gui/icons/jade.png
rename to electrum/plugins/jade/jade.png
diff --git a/electrum/gui/icons/jade_unpaired.png b/electrum/plugins/jade/jade_unpaired.png
similarity index 100%
rename from electrum/gui/icons/jade_unpaired.png
rename to electrum/plugins/jade/jade_unpaired.png
diff --git a/electrum/gui/icons/keepkey.png b/electrum/plugins/keepkey/keepkey.png
similarity index 100%
rename from electrum/gui/icons/keepkey.png
rename to electrum/plugins/keepkey/keepkey.png
diff --git a/electrum/gui/icons/keepkey_unpaired.png b/electrum/plugins/keepkey/keepkey_unpaired.png
similarity index 100%
rename from electrum/gui/icons/keepkey_unpaired.png
rename to electrum/plugins/keepkey/keepkey_unpaired.png
diff --git a/electrum/gui/icons/ledger.png b/electrum/plugins/ledger/ledger.png
similarity index 100%
rename from electrum/gui/icons/ledger.png
rename to electrum/plugins/ledger/ledger.png
diff --git a/electrum/gui/icons/ledger_unpaired.png b/electrum/plugins/ledger/ledger_unpaired.png
similarity index 100%
rename from electrum/gui/icons/ledger_unpaired.png
rename to electrum/plugins/ledger/ledger_unpaired.png
diff --git a/electrum/plugins/revealer/qt.py b/electrum/plugins/revealer/qt.py
index 3e82b07b2..077d5a512 100644
--- a/electrum/plugins/revealer/qt.py
+++ b/electrum/plugins/revealer/qt.py
@@ -32,10 +32,11 @@ from PyQt6.QtWidgets import (QGridLayout, QVBoxLayout, QHBoxLayout, QLabel,
from electrum.plugin import hook
from electrum.i18n import _
from electrum.util import make_dir, InvalidPassword, UserCancelled
-from electrum.gui.qt.util import (read_QIcon, EnterButton, WWLabel, icon_path,
+from electrum.gui.qt.util import (read_QIcon, EnterButton, WWLabel, icon_path, internal_plugin_icon_path,
WindowModalDialog, Buttons, CloseButton, OkButton)
from electrum.gui.qt.qrtextedit import ScanQRTextEdit
from electrum.gui.qt.main_window import StatusBarButton
+from electrum.gui.qt.util import read_QIcon_from_bytes, read_QPixmap_from_bytes
from .revealer import RevealerPlugin
@@ -69,6 +70,7 @@ class Plugin(RevealerPlugin):
self.extension = False
self._init_qt_received = False
+ self.icon_bytes = self.read_file("revealer.png")
@hook
def init_qt(self, gui: 'ElectrumGui'):
@@ -81,8 +83,10 @@ class Plugin(RevealerPlugin):
@hook
def create_status_bar(self, sb):
- b = StatusBarButton(read_QIcon('revealer.png'), "Revealer "+_("Visual Cryptography Plugin"),
- partial(self.setup_dialog, sb), sb.height())
+ b = StatusBarButton(
+ read_QIcon_from_bytes(self.icon_bytes),
+ "Revealer "+_("Visual Cryptography Plugin"),
+ partial(self.setup_dialog, sb), sb.height())
sb.addPermanentWidget(b)
def requires_settings(self):
@@ -125,7 +129,7 @@ class Plugin(RevealerPlugin):
logo_label = QLabel()
# Set the logo label pixmap.
- logo_label.setPixmap(QPixmap(icon_path('revealer.png')))
+ logo_label.setPixmap(read_QPixmap_from_bytes(self.icon_bytes))
# Align the logo label to the top left.
logo_label.setAlignment(Qt.AlignmentFlag.AlignLeft)
@@ -308,7 +312,7 @@ class Plugin(RevealerPlugin):
logo_label = QLabel()
# Set the logo label pixmap.
- logo_label.setPixmap(QPixmap(icon_path('revealer.png')))
+ logo_label.setPixmap(read_QPixmap_from_bytes(self.icon_bytes))
# Align the logo label to the top left.
logo_label.setAlignment(Qt.AlignmentFlag.AlignLeft)
@@ -670,7 +674,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(icon_path('electrumb.png')).scaledToWidth(round(2.1*total_distance_h), Qt.TransformationMode.SmoothTransformation))
+ QImage(internal_icon_path('electrumb.png')).scaledToWidth(round(2.1*total_distance_h), Qt.TransformationMode.SmoothTransformation))
painter.setPen(QPen(Qt.GlobalColor.white, border_thick*8))
painter.drawLine(int(base_img.width()-total_distance_h-(border_thick*8)/2-(border_thick/2)-2),
@@ -696,7 +700,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(icon_path('revealer_c.png')).scaledToWidth(round(1.3*(total_distance_h)))
+ logo = QImage(internal_plugin_icon_path(self.name, 'revealer_c.png')).scaledToWidth(round(1.3*(total_distance_h)))
painter.drawImage(int(total_distance_h+border_thick), int(total_distance_h+border_thick), logo, Qt.TransformationMode.SmoothTransformation)
#frame around logo
diff --git a/electrum/gui/icons/revealer.png b/electrum/plugins/revealer/revealer.png
similarity index 100%
rename from electrum/gui/icons/revealer.png
rename to electrum/plugins/revealer/revealer.png
diff --git a/electrum/gui/icons/safe-t.png b/electrum/plugins/safe_t/safe-t.png
similarity index 100%
rename from electrum/gui/icons/safe-t.png
rename to electrum/plugins/safe_t/safe-t.png
diff --git a/electrum/gui/icons/safe-t_unpaired.png b/electrum/plugins/safe_t/safe-t_unpaired.png
similarity index 100%
rename from electrum/gui/icons/safe-t_unpaired.png
rename to electrum/plugins/safe_t/safe-t_unpaired.png
diff --git a/electrum/gui/icons/trezor.png b/electrum/plugins/trezor/trezor.png
similarity index 100%
rename from electrum/gui/icons/trezor.png
rename to electrum/plugins/trezor/trezor.png
diff --git a/electrum/gui/icons/trezor_unpaired.png b/electrum/plugins/trezor/trezor_unpaired.png
similarity index 100%
rename from electrum/gui/icons/trezor_unpaired.png
rename to electrum/plugins/trezor/trezor_unpaired.png
diff --git a/electrum/plugins/trustedcoin/qt.py b/electrum/plugins/trustedcoin/qt.py
index 0f98f6c8f..703161904 100644
--- a/electrum/plugins/trustedcoin/qt.py
+++ b/electrum/plugins/trustedcoin/qt.py
@@ -40,13 +40,14 @@ from electrum.logging import Logger, get_logger
from electrum import keystore
from electrum.gui.qt.util import (read_QIcon, WindowModalDialog, WaitingDialog, OkButton,
- CancelButton, Buttons, icon_path, WWLabel, CloseButton, ColorScheme,
+ CancelButton, Buttons, icon_path, internal_plugin_icon_path, WWLabel, CloseButton, ColorScheme,
ChoiceWidget, PasswordLineEdit, char_width_in_lineedit)
from electrum.gui.qt.qrcodewidget import QRCodeWidget
from electrum.gui.qt.amountedit import AmountEdit
from electrum.gui.qt.main_window import StatusBarButton
from electrum.gui.qt.wizard.wallet import WCCreateSeed, WCConfirmSeed, WCHaveSeed, WCEnterExt, WCConfirmExt
from electrum.gui.qt.wizard.wizard import WizardComponent
+from electrum.gui.qt.util import read_QIcon_from_bytes
from .common_qt import TrustedcoinPluginQObject
from .trustedcoin import TrustedCoinPlugin, server, DISCLAIMER
@@ -103,10 +104,10 @@ class Plugin(TrustedCoinPlugin):
_('Therefore, two-factor authentication is disabled.')
])
action = lambda: window.show_message(msg)
- icon = read_QIcon("trustedcoin-status-disabled.png")
+ icon = read_QIcon_from_bytes(self.read_file("trustedcoin-status-disabled.png"))
else:
action = partial(self.settings_dialog, window)
- icon = read_QIcon("trustedcoin-status.png")
+ icon = read_QIcon_from_bytes(self.read_file("trustedcoin-status.png"))
sb = window.statusBar()
button = StatusBarButton(icon, _("TrustedCoin"), action, sb.height())
sb.addPermanentWidget(button)
@@ -166,6 +167,9 @@ class Plugin(TrustedCoinPlugin):
self.waiting_dialog_for_billing_info(window,
on_finished=partial(self.show_settings_dialog, window))
+ def icon_path(self, name):
+ return internal_plugin_icon_path(self.name, name)
+
def show_settings_dialog(self, window, success):
if not success:
window.show_message(_('Server not reachable.'))
@@ -178,7 +182,7 @@ class Plugin(TrustedCoinPlugin):
hbox = QHBoxLayout()
logo = QLabel()
- logo.setPixmap(QPixmap(icon_path("trustedcoin-status.png")))
+ logo.setPixmap(QPixmap(self.icon_path("trustedcoin-status.png")))
msg = _('This wallet is protected by TrustedCoin\'s two-factor authentication.') + '
'\
+ _("For more information, visit") + " https://api.trustedcoin.com/#/electrum-help"
label = QLabel(msg)
@@ -228,46 +232,46 @@ class Plugin(TrustedCoinPlugin):
wizard.trustedcoin_qhelper = TrustedcoinPluginQObject(self, wizard, None)
self.extend_wizard(wizard)
if wizard.start_viewstate and wizard.start_viewstate.view.startswith('trustedcoin_'):
- wizard.start_viewstate.params.update({'icon': icon_path('trustedcoin-wizard.png')})
+ wizard.start_viewstate.params.update({'icon': self.icon_path('trustedcoin-wizard.png')})
def extend_wizard(self, wizard: 'QENewWalletWizard'):
super().extend_wizard(wizard)
views = {
'trustedcoin_start': {
'gui': WCDisclaimer,
- 'params': {'icon': icon_path('trustedcoin-wizard.png')},
+ 'params': {'icon': self.icon_path('trustedcoin-wizard.png')},
},
'trustedcoin_choose_seed': {
'gui': WCChooseSeed,
- 'params': {'icon': icon_path('trustedcoin-wizard.png')},
+ 'params': {'icon': self.icon_path('trustedcoin-wizard.png')},
},
'trustedcoin_create_seed': {
'gui': WCCreateSeed,
- 'params': {'icon': icon_path('trustedcoin-wizard.png')},
+ 'params': {'icon': self.icon_path('trustedcoin-wizard.png')},
},
'trustedcoin_confirm_seed': {
'gui': WCConfirmSeed,
- 'params': {'icon': icon_path('trustedcoin-wizard.png')},
+ 'params': {'icon': self.icon_path('trustedcoin-wizard.png')},
},
'trustedcoin_have_seed': {
'gui': WCHaveSeed,
- 'params': {'icon': icon_path('trustedcoin-wizard.png')},
+ 'params': {'icon': self.icon_path('trustedcoin-wizard.png')},
},
'trustedcoin_keep_disable': {
'gui': WCKeepDisable,
- 'params': {'icon': icon_path('trustedcoin-wizard.png')},
+ 'params': {'icon': self.icon_path('trustedcoin-wizard.png')},
},
'trustedcoin_tos': {
'gui': WCTerms,
- 'params': {'icon': icon_path('trustedcoin-wizard.png')},
+ 'params': {'icon': self.icon_path('trustedcoin-wizard.png')},
},
'trustedcoin_keystore_unlock': {
'gui': WCKeystorePassword,
- 'params': {'icon': icon_path('trustedcoin-wizard.png')},
+ 'params': {'icon': self.icon_path('trustedcoin-wizard.png')},
},
'trustedcoin_show_confirm_otp': {
'gui': WCShowConfirmOTP,
- 'params': {'icon': icon_path('trustedcoin-wizard.png')},
+ 'params': {'icon': self.icon_path('trustedcoin-wizard.png')},
}
}
wizard.navmap_merge(views)
@@ -279,7 +283,7 @@ class Plugin(TrustedCoinPlugin):
},
'trustedcoin_create_ext': {
'gui': WCEnterExt,
- 'params': {'icon': icon_path('trustedcoin-wizard.png')},
+ 'params': {'icon': self.icon_path('trustedcoin-wizard.png')},
'next': 'trustedcoin_confirm_seed',
},
'trustedcoin_confirm_seed': {
@@ -287,7 +291,7 @@ class Plugin(TrustedCoinPlugin):
},
'trustedcoin_confirm_ext': {
'gui': WCConfirmExt,
- 'params': {'icon': icon_path('trustedcoin-wizard.png')},
+ 'params': {'icon': self.icon_path('trustedcoin-wizard.png')},
'next': 'trustedcoin_tos',
},
'trustedcoin_have_seed': {
@@ -295,7 +299,7 @@ class Plugin(TrustedCoinPlugin):
},
'trustedcoin_have_ext': {
'gui': WCEnterExt,
- 'params': {'icon': icon_path('trustedcoin-wizard.png')},
+ 'params': {'icon': self.icon_path('trustedcoin-wizard.png')},
'next': 'trustedcoin_keep_disable',
},
}
@@ -305,7 +309,7 @@ class Plugin(TrustedCoinPlugin):
ext_online = {
'trustedcoin_continue_online': {
'gui': WCContinueOnline,
- 'params': {'icon': icon_path('trustedcoin-wizard.png')},
+ 'params': {'icon': self.icon_path('trustedcoin-wizard.png')},
'next': lambda d: 'trustedcoin_tos' if d['trustedcoin_go_online'] else 'wallet_password',
'accept': self.on_continue_online,
'last': lambda d: not d['trustedcoin_go_online'] and wizard.is_single_password()
diff --git a/electrum/gui/icons/trustedcoin-status-disabled.png b/electrum/plugins/trustedcoin/trustedcoin-status-disabled.png
similarity index 100%
rename from electrum/gui/icons/trustedcoin-status-disabled.png
rename to electrum/plugins/trustedcoin/trustedcoin-status-disabled.png
diff --git a/electrum/gui/icons/trustedcoin-status.png b/electrum/plugins/trustedcoin/trustedcoin-status.png
similarity index 100%
rename from electrum/gui/icons/trustedcoin-status.png
rename to electrum/plugins/trustedcoin/trustedcoin-status.png
diff --git a/electrum/gui/icons/trustedcoin-wizard.png b/electrum/plugins/trustedcoin/trustedcoin-wizard.png
similarity index 100%
rename from electrum/gui/icons/trustedcoin-wizard.png
rename to electrum/plugins/trustedcoin/trustedcoin-wizard.png