diff --git a/AUTHORS b/AUTHORS index 9cff06784..5cecf9e75 100644 --- a/AUTHORS +++ b/AUTHORS @@ -3,10 +3,11 @@ Animazing / Tachikoma - Styled the new GUI. Mac version. Azelphur - GUI stuff. Coblee - Alternate coin support and py2app support. Deafboy - Ubuntu packages. +Soren Stoutner - Debian packages and some Qt GUI layout. EagleTM - Bugfixes. ErebusBat - Mac distribution. Genjix - Porting pro-mode functionality to lite-gui and worked on server Slush - Work on the server. Designed the original Stratum spec. Julian Toash (Tuxavant) - Various fixes to the client. rdymac - Website and translations. -kyuupichan - Miscellaneous. \ No newline at end of file +kyuupichan - Miscellaneous. diff --git a/electrum/plugins/revealer/qt.py b/electrum/plugins/revealer/qt.py index 49882c961..2139f53fa 100644 --- a/electrum/plugins/revealer/qt.py +++ b/electrum/plugins/revealer/qt.py @@ -4,8 +4,12 @@ Revealer Do you have something to hide? Secret backup plug-in for the electrum wallet. -Tiago Romagnani Silveira, 2017 +Copyright: + 2017 Tiago Romagnani Silveira + 2023 Soren Stoutner +Distributed under the MIT software license, see the accompanying +file LICENCE or http://www.opensource.org/licenses/mit-license.php ''' @@ -96,42 +100,55 @@ class Plugin(RevealerPlugin): self.update_wallet_name(self.wallet) self.user_input = False - self.d = WindowModalDialog(window, "Setup Dialog") - self.d.setMinimumWidth(500) - self.d.setMinimumHeight(210) - self.d.setMaximumHeight(320) + self.d = WindowModalDialog(window, "Revealer Visual Cryptography Plugin - Select Noise File") self.d.setContentsMargins(11,11,1,1) - self.hbox = QHBoxLayout(self.d) - vbox = QVBoxLayout() - logo = QLabel() - self.hbox.addWidget(logo) - logo.setPixmap(QPixmap(icon_path('revealer.png'))) - logo.setAlignment(Qt.AlignLeft) - self.hbox.addSpacing(16) - vbox.addWidget(WWLabel(""+_("Revealer Visual Cryptography Plugin")+"

" - +_("To encrypt a secret, first create or load noise.")+"
")) - vbox.addSpacing(7) - bcreate = QPushButton(_("Create a new Revealer")) - bcreate.setMaximumWidth(181) - bcreate.setDefault(True) - vbox.addWidget(bcreate, Qt.AlignCenter) - self.load_noise = ScanQRTextEdit(config=self.config) - self.load_noise.setTabChangesFocus(True) - self.load_noise.textChanged.connect(self.on_edit) - self.load_noise.setMaximumHeight(33) - self.hbox.addLayout(vbox) - vbox.addWidget(WWLabel(_("or type an existing revealer code below and click 'next':"))) - vbox.addWidget(self.load_noise) - vbox.addSpacing(3) + # Create an HBox layout. The logo will be on the left and the rest of the dialog on the right. + hbox_layout = QHBoxLayout(self.d) + + # Create the logo label. + logo_label = QLabel() + + # Set the logo label pixmap. + logo_label.setPixmap(QPixmap(icon_path('revealer.png'))) + + # Align the logo label to the top left. + logo_label.setAlignment(Qt.AlignLeft) + + # Create a VBox layout for the main contents of the dialog. + vbox_layout = QVBoxLayout() + + # Populate the HBox layout with spacing between the two columns. + hbox_layout.addWidget(logo_label) + hbox_layout.addSpacing(16) + hbox_layout.addLayout(vbox_layout) + + # Create the labels. + create_or_load_noise_file_label = QLabel(_("To encrypt a secret, you must first create or load a noise file.")) + instructions_label = QLabel(_("Click the button above or type an existing revealer code in the box below.")) + + # Allow users to select text in the labels. + create_or_load_noise_file_label.setTextInteractionFlags(Qt.TextSelectableByMouse) + instructions_label.setTextInteractionFlags(Qt.TextSelectableByMouse) + + # Create the buttons. + create_button = QPushButton(_("Create a new Revealer noise file")) self.next_button = QPushButton(_("Next"), self.d) - self.next_button.setEnabled(False) - vbox.addLayout(Buttons(self.next_button)) - self.next_button.clicked.connect(self.d.close) - self.next_button.clicked.connect(partial(self.cypherseed_dialog, window)) + # Calculate the desired width of the create button + create_button_width = create_button.fontMetrics().boundingRect(create_button.text()).width() + 40 + + # Set the create button width. + create_button.setMaximumWidth(create_button_width) + + # Set the create button to be the default. + create_button.setDefault(True) - def mk_digital(): + # Initially disable the next button. + self.next_button.setEnabled(False) + + # Define the create noise file function. + def create_noise_file(): try: self.make_digital(self.d) except Exception: @@ -139,11 +156,36 @@ class Plugin(RevealerPlugin): else: self.cypherseed_dialog(window) - bcreate.clicked.connect(mk_digital) + # Handle clicks on the buttons. + create_button.clicked.connect(create_noise_file) + self.next_button.clicked.connect(self.d.close) + self.next_button.clicked.connect(partial(self.cypherseed_dialog, window)) + + # Create the noise scan QR text edit. + self.noise_scan_qr_textedit = ScanQRTextEdit(config=self.config) + + # Make tabs change focus from the text edit instead of inserting a tab into the field. + self.noise_scan_qr_textedit.setTabChangesFocus(True) + + # Update the UI when the text changes. + self.noise_scan_qr_textedit.textChanged.connect(self.on_edit) + + # Populate the VBox layout. + vbox_layout.addWidget(create_or_load_noise_file_label) + vbox_layout.addWidget(create_button, alignment=Qt.AlignCenter) + vbox_layout.addWidget(instructions_label) + vbox_layout.addWidget(self.noise_scan_qr_textedit) + vbox_layout.addLayout(Buttons(self.next_button)) + + # Add stretches to the end of the layouts to prevent the contents from spreading when the dialog is enlarged. + hbox_layout.addStretch(1) + vbox_layout.addStretch(1) + return bool(self.d.exec_()) def get_noise(self): - text = self.load_noise.text() + # Get the text from the scan QR text edit. + text = self.noise_scan_qr_textedit.text() return ''.join(text.split()).lower() def on_edit(self): @@ -195,17 +237,34 @@ class Plugin(RevealerPlugin): def customtxt_limits(self): - txt = self.text.text() - self.max_chars.setVisible(False) - self.char_count.setText(f"({len(txt)}/{self.MAX_PLAINTEXT_LEN})") - if len(txt)>0: - self.ctext.setEnabled(True) + txt = self.custom_secret_scan_qr_textedit.text() + self.custom_secret_character_count_label.setText(f"({len(txt)}/{self.MAX_PLAINTEXT_LEN})") + + # Hide the custom secret maximum characters warning label. + self.custom_secret_maximum_characters_warning_label.setVisible(False) + + # Update the status of the encrypt custom secret button. + self.encrypt_custom_secret_button.setEnabled(len(txt)>0) + + # Check to make sure the length of the text has not exceeded the limit. if len(txt) > self.MAX_PLAINTEXT_LEN: - self.text.setPlainText(txt[:self.MAX_PLAINTEXT_LEN]) - self.max_chars.setVisible(True) + # Truncate the text to the maximum limit. + self.custom_secret_scan_qr_textedit.setPlainText(txt[:self.MAX_PLAINTEXT_LEN]) + + # Get the text cursor. + textCursor = self.custom_secret_scan_qr_textedit.textCursor() + + # Move the cursor position to the end (setting the text above automatically moves the cursor to the beginning, which is undesirable) + textCursor.movePosition(textCursor.End) + + # Set the text cursor with the corrected position. + self.custom_secret_scan_qr_textedit.setTextCursor(textCursor) + + # Display the custom secret maximum characters warning label. + self.custom_secret_maximum_characters_warning_label.setVisible(True) def t(self): - self.txt = self.text.text() + self.txt = self.custom_secret_scan_qr_textedit.text() self.seed_img(is_seed=False) def warn_old_revealer(self): @@ -223,55 +282,99 @@ class Plugin(RevealerPlugin): def cypherseed_dialog(self, window): self.warn_old_revealer() - d = WindowModalDialog(window, "Encryption Dialog") - d.setMinimumWidth(500) - d.setMinimumHeight(210) - d.setMaximumHeight(450) + d = WindowModalDialog(window, "Revealer Visual Cryptography Plugin - Encryption Data") d.setContentsMargins(11, 11, 1, 1) self.c_dialog = d - hbox = QHBoxLayout(d) - self.vbox = QVBoxLayout() - logo = QLabel() - hbox.addWidget(logo) - logo.setPixmap(QPixmap(icon_path('revealer.png'))) - logo.setAlignment(Qt.AlignLeft) - hbox.addSpacing(16) - self.vbox.addWidget(WWLabel("" + _("Revealer Visual Cryptography Plugin") + "

" - + _("Ready to encrypt for revealer {}") - .format(self.versioned_seed.version+'_'+self.versioned_seed.checksum))) - self.vbox.addSpacing(11) - hbox.addLayout(self.vbox) - grid = QGridLayout() - self.vbox.addLayout(grid) - - cprint = QPushButton(_("Encrypt {}'s seed").format(self.wallet_name)) - cprint.setMaximumWidth(250) - cprint.clicked.connect(partial(self.seed_img, True)) - self.vbox.addWidget(cprint) - self.vbox.addSpacing(1) - self.vbox.addWidget(WWLabel(""+_("OR")+" "+_("type a custom alphanumerical secret below:"))) - self.text = ScanQRTextEdit(config=self.config) - self.text.setTabChangesFocus(True) - self.text.setMaximumHeight(70) - self.text.textChanged.connect(self.customtxt_limits) - self.vbox.addWidget(self.text) - self.char_count = WWLabel("") - self.char_count.setAlignment(Qt.AlignRight) - self.vbox.addWidget(self.char_count) - self.max_chars = WWLabel("" - + _("This version supports a maximum of {} characters.").format(self.MAX_PLAINTEXT_LEN) - +"") - self.vbox.addWidget(self.max_chars) - self.max_chars.setVisible(False) - self.ctext = QPushButton(_("Encrypt custom secret")) - self.ctext.clicked.connect(self.t) - self.vbox.addWidget(self.ctext) - self.ctext.setEnabled(False) - self.vbox.addSpacing(11) - self.vbox.addLayout(Buttons(CloseButton(d))) - self.vbox.addWidget( - QLabel("
"+"" + _("Warning ") + ": " + _("each Revealer is a one-time-pad, use it for a single secret."))) + # Create an HBox layout. The logo will be on the left and the rest of the dialog on the right. + hbox_layout = QHBoxLayout(d) + + # Create the logo label. + logo_label = QLabel() + + # Set the logo label pixmap. + logo_label.setPixmap(QPixmap(icon_path('revealer.png'))) + + # Align the logo label to the top left. + logo_label.setAlignment(Qt.AlignLeft) + + # Create a VBox layout for the main contents of the dialog. + vbox_layout = QVBoxLayout() + + # Populate the HBox layout. + hbox_layout.addWidget(logo_label) + hbox_layout.addSpacing(16) + hbox_layout.addLayout(vbox_layout) + + # Create the labels. + ready_to_encrypt_label = QLabel(_("Ready to encrypt for revealer {}.").format(self.versioned_seed.version+'_'+self.versioned_seed.checksum)) + instructions_label = QLabel(_("Click the button above to encrypt the seed or type a custom alphanumerical secret below.")) + self.custom_secret_character_count_label = QLabel(f"(0/{self.MAX_PLAINTEXT_LEN})") + self.custom_secret_maximum_characters_warning_label = QLabel("" + + _("This version supports a maximum of {} characters.").format(self.MAX_PLAINTEXT_LEN) + +"") + one_time_pad_warning_label = QLabel("" + _("Warning ") + ": " + _("each Revealer is a one-time-pad, use it for a single secret.")) + + # Allow users to select text in the labels. + ready_to_encrypt_label.setTextInteractionFlags(Qt.TextSelectableByMouse) + instructions_label.setTextInteractionFlags(Qt.TextSelectableByMouse) + self.custom_secret_character_count_label.setTextInteractionFlags(Qt.TextSelectableByMouse) + self.custom_secret_maximum_characters_warning_label + one_time_pad_warning_label.setTextInteractionFlags(Qt.TextSelectableByMouse) + + # Align the custom secret character count label to the right. + self.custom_secret_character_count_label.setAlignment(Qt.AlignRight) + + # Initially hide the custom secret character count label. + self.custom_secret_maximum_characters_warning_label.setVisible(False) + + # Create the buttons. + encrypt_seed_button = QPushButton(_("Encrypt {}'s seed").format(self.wallet_name)) + self.encrypt_custom_secret_button = QPushButton(_("Encrypt custom secret")) + + # Calculate the desired width of the buttons. + encrypt_seed_button_width = encrypt_seed_button.fontMetrics().boundingRect(encrypt_seed_button.text()).width() + 40 + encrypt_custom_secret_button_width = self.encrypt_custom_secret_button.fontMetrics().boundingRect(self.encrypt_custom_secret_button.text()).width() + 40 + + # Set the button widths. + encrypt_seed_button.setMaximumWidth(encrypt_seed_button_width) + self.encrypt_custom_secret_button.setMaximumWidth(encrypt_custom_secret_button_width) + + # Set the encrypt seed button to be the default. + encrypt_seed_button.setDefault(True) + + # Initially disable the encrypt custom secret button. + self.encrypt_custom_secret_button.setEnabled(False) + + # Handle clicks on the buttons. + encrypt_seed_button.clicked.connect(partial(self.seed_img, True)) + self.encrypt_custom_secret_button.clicked.connect(self.t) + + # Create the custom secret scan QR text edit. + self.custom_secret_scan_qr_textedit = ScanQRTextEdit(config=self.config) + + # Make tabs change focus from the text edit instead of inserting a tab into the field. + self.custom_secret_scan_qr_textedit.setTabChangesFocus(True) + + # Update the UI when the custom secret text changes. + self.custom_secret_scan_qr_textedit.textChanged.connect(self.customtxt_limits) + + # Populate the VBox layout. + vbox_layout.addWidget(ready_to_encrypt_label) + vbox_layout.addWidget(encrypt_seed_button, alignment=Qt.AlignCenter) + vbox_layout.addWidget(instructions_label) + vbox_layout.addWidget(self.custom_secret_scan_qr_textedit) + vbox_layout.addWidget(self.custom_secret_character_count_label) + vbox_layout.addWidget(self.custom_secret_maximum_characters_warning_label) + vbox_layout.addWidget(self.encrypt_custom_secret_button, alignment=Qt.AlignCenter) + vbox_layout.addSpacing(40) + vbox_layout.addWidget(one_time_pad_warning_label) + vbox_layout.addLayout(Buttons(CloseButton(d))) + + # Add stretches to the end of the layouts to prevent the contents from spreading when the dialog is enlarged. + hbox_layout.addStretch(1) + vbox_layout.addStretch(1) + return bool(d.exec_()) def update_wallet_name(self, name):