Skip to content

Commit ddad5f1

Browse files
Fix Revealer Qt layout (#8587)
* Fix Revealer Qt layout * Add license information
1 parent 307cf25 commit ddad5f1

File tree

2 files changed

+193
-89
lines changed

2 files changed

+193
-89
lines changed

AUTHORS

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ Animazing / Tachikoma - Styled the new GUI. Mac version.
33
Azelphur - GUI stuff.
44
Coblee - Alternate coin support and py2app support.
55
Deafboy - Ubuntu packages.
6+
Soren Stoutner - Debian packages and some Qt GUI layout.
67
EagleTM - Bugfixes.
78
ErebusBat - Mac distribution.
89
Genjix - Porting pro-mode functionality to lite-gui and worked on server
910
Slush - Work on the server. Designed the original Stratum spec.
1011
Julian Toash (Tuxavant) - Various fixes to the client.
1112
rdymac - Website and translations.
12-
kyuupichan - Miscellaneous.
13+
kyuupichan - Miscellaneous.

electrum/plugins/revealer/qt.py

+191-88
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,12 @@
44
Do you have something to hide?
55
Secret backup plug-in for the electrum wallet.
66
7-
Tiago Romagnani Silveira, 2017
7+
Copyright:
8+
2017 Tiago Romagnani Silveira
9+
2023 Soren Stoutner <[email protected]>
810
11+
Distributed under the MIT software license, see the accompanying
12+
file LICENCE or http://www.opensource.org/licenses/mit-license.php
913
1014
'''
1115

@@ -96,54 +100,92 @@ def setup_dialog(self, window):
96100
self.update_wallet_name(self.wallet)
97101
self.user_input = False
98102

99-
self.d = WindowModalDialog(window, "Setup Dialog")
100-
self.d.setMinimumWidth(500)
101-
self.d.setMinimumHeight(210)
102-
self.d.setMaximumHeight(320)
103+
self.d = WindowModalDialog(window, "Revealer Visual Cryptography Plugin - Select Noise File")
103104
self.d.setContentsMargins(11,11,1,1)
104105

105-
self.hbox = QHBoxLayout(self.d)
106-
vbox = QVBoxLayout()
107-
logo = QLabel()
108-
self.hbox.addWidget(logo)
109-
logo.setPixmap(QPixmap(icon_path('revealer.png')))
110-
logo.setAlignment(Qt.AlignLeft)
111-
self.hbox.addSpacing(16)
112-
vbox.addWidget(WWLabel("<b>"+_("Revealer Visual Cryptography Plugin")+"</b><br><br>"
113-
+_("To encrypt a secret, first create or load noise.")+"<br/>"))
114-
vbox.addSpacing(7)
115-
bcreate = QPushButton(_("Create a new Revealer"))
116-
bcreate.setMaximumWidth(181)
117-
bcreate.setDefault(True)
118-
vbox.addWidget(bcreate, Qt.AlignCenter)
119-
self.load_noise = ScanQRTextEdit(config=self.config)
120-
self.load_noise.setTabChangesFocus(True)
121-
self.load_noise.textChanged.connect(self.on_edit)
122-
self.load_noise.setMaximumHeight(33)
123-
self.hbox.addLayout(vbox)
124-
vbox.addWidget(WWLabel(_("or type an existing revealer code below and click 'next':")))
125-
vbox.addWidget(self.load_noise)
126-
vbox.addSpacing(3)
106+
# Create an HBox layout. The logo will be on the left and the rest of the dialog on the right.
107+
hbox_layout = QHBoxLayout(self.d)
108+
109+
# Create the logo label.
110+
logo_label = QLabel()
111+
112+
# Set the logo label pixmap.
113+
logo_label.setPixmap(QPixmap(icon_path('revealer.png')))
114+
115+
# Align the logo label to the top left.
116+
logo_label.setAlignment(Qt.AlignLeft)
117+
118+
# Create a VBox layout for the main contents of the dialog.
119+
vbox_layout = QVBoxLayout()
120+
121+
# Populate the HBox layout with spacing between the two columns.
122+
hbox_layout.addWidget(logo_label)
123+
hbox_layout.addSpacing(16)
124+
hbox_layout.addLayout(vbox_layout)
125+
126+
# Create the labels.
127+
create_or_load_noise_file_label = QLabel(_("To encrypt a secret, you must first create or load a noise file."))
128+
instructions_label = QLabel(_("Click the button above or type an existing revealer code in the box below."))
129+
130+
# Allow users to select text in the labels.
131+
create_or_load_noise_file_label.setTextInteractionFlags(Qt.TextSelectableByMouse)
132+
instructions_label.setTextInteractionFlags(Qt.TextSelectableByMouse)
133+
134+
# Create the buttons.
135+
create_button = QPushButton(_("Create a new Revealer noise file"))
127136
self.next_button = QPushButton(_("Next"), self.d)
128-
self.next_button.setEnabled(False)
129-
vbox.addLayout(Buttons(self.next_button))
130-
self.next_button.clicked.connect(self.d.close)
131-
self.next_button.clicked.connect(partial(self.cypherseed_dialog, window))
132137

138+
# Calculate the desired width of the create button
139+
create_button_width = create_button.fontMetrics().boundingRect(create_button.text()).width() + 40
140+
141+
# Set the create button width.
142+
create_button.setMaximumWidth(create_button_width)
143+
144+
# Set the create button to be the default.
145+
create_button.setDefault(True)
133146

134-
def mk_digital():
147+
# Initially disable the next button.
148+
self.next_button.setEnabled(False)
149+
150+
# Define the create noise file function.
151+
def create_noise_file():
135152
try:
136153
self.make_digital(self.d)
137154
except Exception:
138155
self.logger.exception('')
139156
else:
140157
self.cypherseed_dialog(window)
141158

142-
bcreate.clicked.connect(mk_digital)
159+
# Handle clicks on the buttons.
160+
create_button.clicked.connect(create_noise_file)
161+
self.next_button.clicked.connect(self.d.close)
162+
self.next_button.clicked.connect(partial(self.cypherseed_dialog, window))
163+
164+
# Create the noise scan QR text edit.
165+
self.noise_scan_qr_textedit = ScanQRTextEdit(config=self.config)
166+
167+
# Make tabs change focus from the text edit instead of inserting a tab into the field.
168+
self.noise_scan_qr_textedit.setTabChangesFocus(True)
169+
170+
# Update the UI when the text changes.
171+
self.noise_scan_qr_textedit.textChanged.connect(self.on_edit)
172+
173+
# Populate the VBox layout.
174+
vbox_layout.addWidget(create_or_load_noise_file_label)
175+
vbox_layout.addWidget(create_button, alignment=Qt.AlignCenter)
176+
vbox_layout.addWidget(instructions_label)
177+
vbox_layout.addWidget(self.noise_scan_qr_textedit)
178+
vbox_layout.addLayout(Buttons(self.next_button))
179+
180+
# Add stretches to the end of the layouts to prevent the contents from spreading when the dialog is enlarged.
181+
hbox_layout.addStretch(1)
182+
vbox_layout.addStretch(1)
183+
143184
return bool(self.d.exec_())
144185

145186
def get_noise(self):
146-
text = self.load_noise.text()
187+
# Get the text from the scan QR text edit.
188+
text = self.noise_scan_qr_textedit.text()
147189
return ''.join(text.split()).lower()
148190

149191
def on_edit(self):
@@ -195,17 +237,34 @@ def bdone(self, dialog):
195237

196238

197239
def customtxt_limits(self):
198-
txt = self.text.text()
199-
self.max_chars.setVisible(False)
200-
self.char_count.setText(f"({len(txt)}/{self.MAX_PLAINTEXT_LEN})")
201-
if len(txt)>0:
202-
self.ctext.setEnabled(True)
240+
txt = self.custom_secret_scan_qr_textedit.text()
241+
self.custom_secret_character_count_label.setText(f"({len(txt)}/{self.MAX_PLAINTEXT_LEN})")
242+
243+
# Hide the custom secret maximum characters warning label.
244+
self.custom_secret_maximum_characters_warning_label.setVisible(False)
245+
246+
# Update the status of the encrypt custom secret button.
247+
self.encrypt_custom_secret_button.setEnabled(len(txt)>0)
248+
249+
# Check to make sure the length of the text has not exceeded the limit.
203250
if len(txt) > self.MAX_PLAINTEXT_LEN:
204-
self.text.setPlainText(txt[:self.MAX_PLAINTEXT_LEN])
205-
self.max_chars.setVisible(True)
251+
# Truncate the text to the maximum limit.
252+
self.custom_secret_scan_qr_textedit.setPlainText(txt[:self.MAX_PLAINTEXT_LEN])
253+
254+
# Get the text cursor.
255+
textCursor = self.custom_secret_scan_qr_textedit.textCursor()
256+
257+
# Move the cursor position to the end (setting the text above automatically moves the cursor to the beginning, which is undesirable)
258+
textCursor.movePosition(textCursor.End)
259+
260+
# Set the text cursor with the corrected position.
261+
self.custom_secret_scan_qr_textedit.setTextCursor(textCursor)
262+
263+
# Display the custom secret maximum characters warning label.
264+
self.custom_secret_maximum_characters_warning_label.setVisible(True)
206265

207266
def t(self):
208-
self.txt = self.text.text()
267+
self.txt = self.custom_secret_scan_qr_textedit.text()
209268
self.seed_img(is_seed=False)
210269

211270
def warn_old_revealer(self):
@@ -223,55 +282,99 @@ def warn_old_revealer(self):
223282
def cypherseed_dialog(self, window):
224283
self.warn_old_revealer()
225284

226-
d = WindowModalDialog(window, "Encryption Dialog")
227-
d.setMinimumWidth(500)
228-
d.setMinimumHeight(210)
229-
d.setMaximumHeight(450)
285+
d = WindowModalDialog(window, "Revealer Visual Cryptography Plugin - Encryption Data")
230286
d.setContentsMargins(11, 11, 1, 1)
231287
self.c_dialog = d
232288

233-
hbox = QHBoxLayout(d)
234-
self.vbox = QVBoxLayout()
235-
logo = QLabel()
236-
hbox.addWidget(logo)
237-
logo.setPixmap(QPixmap(icon_path('revealer.png')))
238-
logo.setAlignment(Qt.AlignLeft)
239-
hbox.addSpacing(16)
240-
self.vbox.addWidget(WWLabel("<b>" + _("Revealer Visual Cryptography Plugin") + "</b><br><br>"
241-
+ _("Ready to encrypt for revealer {}")
242-
.format(self.versioned_seed.version+'_'+self.versioned_seed.checksum)))
243-
self.vbox.addSpacing(11)
244-
hbox.addLayout(self.vbox)
245-
grid = QGridLayout()
246-
self.vbox.addLayout(grid)
247-
248-
cprint = QPushButton(_("Encrypt {}'s seed").format(self.wallet_name))
249-
cprint.setMaximumWidth(250)
250-
cprint.clicked.connect(partial(self.seed_img, True))
251-
self.vbox.addWidget(cprint)
252-
self.vbox.addSpacing(1)
253-
self.vbox.addWidget(WWLabel("<b>"+_("OR")+"</b> "+_("type a custom alphanumerical secret below:")))
254-
self.text = ScanQRTextEdit(config=self.config)
255-
self.text.setTabChangesFocus(True)
256-
self.text.setMaximumHeight(70)
257-
self.text.textChanged.connect(self.customtxt_limits)
258-
self.vbox.addWidget(self.text)
259-
self.char_count = WWLabel("")
260-
self.char_count.setAlignment(Qt.AlignRight)
261-
self.vbox.addWidget(self.char_count)
262-
self.max_chars = WWLabel("<font color='red'>"
263-
+ _("This version supports a maximum of {} characters.").format(self.MAX_PLAINTEXT_LEN)
264-
+"</font>")
265-
self.vbox.addWidget(self.max_chars)
266-
self.max_chars.setVisible(False)
267-
self.ctext = QPushButton(_("Encrypt custom secret"))
268-
self.ctext.clicked.connect(self.t)
269-
self.vbox.addWidget(self.ctext)
270-
self.ctext.setEnabled(False)
271-
self.vbox.addSpacing(11)
272-
self.vbox.addLayout(Buttons(CloseButton(d)))
273-
self.vbox.addWidget(
274-
QLabel("<br>"+"<b>" + _("Warning ") + "</b>: " + _("each Revealer is a one-time-pad, use it for a single secret.")))
289+
# Create an HBox layout. The logo will be on the left and the rest of the dialog on the right.
290+
hbox_layout = QHBoxLayout(d)
291+
292+
# Create the logo label.
293+
logo_label = QLabel()
294+
295+
# Set the logo label pixmap.
296+
logo_label.setPixmap(QPixmap(icon_path('revealer.png')))
297+
298+
# Align the logo label to the top left.
299+
logo_label.setAlignment(Qt.AlignLeft)
300+
301+
# Create a VBox layout for the main contents of the dialog.
302+
vbox_layout = QVBoxLayout()
303+
304+
# Populate the HBox layout.
305+
hbox_layout.addWidget(logo_label)
306+
hbox_layout.addSpacing(16)
307+
hbox_layout.addLayout(vbox_layout)
308+
309+
# Create the labels.
310+
ready_to_encrypt_label = QLabel(_("Ready to encrypt for revealer {}.").format(self.versioned_seed.version+'_'+self.versioned_seed.checksum))
311+
instructions_label = QLabel(_("Click the button above to encrypt the seed or type a custom alphanumerical secret below."))
312+
self.custom_secret_character_count_label = QLabel(f"(0/{self.MAX_PLAINTEXT_LEN})")
313+
self.custom_secret_maximum_characters_warning_label = QLabel("<font color='red'>"
314+
+ _("This version supports a maximum of {} characters.").format(self.MAX_PLAINTEXT_LEN)
315+
+"</font>")
316+
one_time_pad_warning_label = QLabel("<b>" + _("Warning ") + "</b>: " + _("each Revealer is a one-time-pad, use it for a single secret."))
317+
318+
# Allow users to select text in the labels.
319+
ready_to_encrypt_label.setTextInteractionFlags(Qt.TextSelectableByMouse)
320+
instructions_label.setTextInteractionFlags(Qt.TextSelectableByMouse)
321+
self.custom_secret_character_count_label.setTextInteractionFlags(Qt.TextSelectableByMouse)
322+
self.custom_secret_maximum_characters_warning_label
323+
one_time_pad_warning_label.setTextInteractionFlags(Qt.TextSelectableByMouse)
324+
325+
# Align the custom secret character count label to the right.
326+
self.custom_secret_character_count_label.setAlignment(Qt.AlignRight)
327+
328+
# Initially hide the custom secret character count label.
329+
self.custom_secret_maximum_characters_warning_label.setVisible(False)
330+
331+
# Create the buttons.
332+
encrypt_seed_button = QPushButton(_("Encrypt {}'s seed").format(self.wallet_name))
333+
self.encrypt_custom_secret_button = QPushButton(_("Encrypt custom secret"))
334+
335+
# Calculate the desired width of the buttons.
336+
encrypt_seed_button_width = encrypt_seed_button.fontMetrics().boundingRect(encrypt_seed_button.text()).width() + 40
337+
encrypt_custom_secret_button_width = self.encrypt_custom_secret_button.fontMetrics().boundingRect(self.encrypt_custom_secret_button.text()).width() + 40
338+
339+
# Set the button widths.
340+
encrypt_seed_button.setMaximumWidth(encrypt_seed_button_width)
341+
self.encrypt_custom_secret_button.setMaximumWidth(encrypt_custom_secret_button_width)
342+
343+
# Set the encrypt seed button to be the default.
344+
encrypt_seed_button.setDefault(True)
345+
346+
# Initially disable the encrypt custom secret button.
347+
self.encrypt_custom_secret_button.setEnabled(False)
348+
349+
# Handle clicks on the buttons.
350+
encrypt_seed_button.clicked.connect(partial(self.seed_img, True))
351+
self.encrypt_custom_secret_button.clicked.connect(self.t)
352+
353+
# Create the custom secret scan QR text edit.
354+
self.custom_secret_scan_qr_textedit = ScanQRTextEdit(config=self.config)
355+
356+
# Make tabs change focus from the text edit instead of inserting a tab into the field.
357+
self.custom_secret_scan_qr_textedit.setTabChangesFocus(True)
358+
359+
# Update the UI when the custom secret text changes.
360+
self.custom_secret_scan_qr_textedit.textChanged.connect(self.customtxt_limits)
361+
362+
# Populate the VBox layout.
363+
vbox_layout.addWidget(ready_to_encrypt_label)
364+
vbox_layout.addWidget(encrypt_seed_button, alignment=Qt.AlignCenter)
365+
vbox_layout.addWidget(instructions_label)
366+
vbox_layout.addWidget(self.custom_secret_scan_qr_textedit)
367+
vbox_layout.addWidget(self.custom_secret_character_count_label)
368+
vbox_layout.addWidget(self.custom_secret_maximum_characters_warning_label)
369+
vbox_layout.addWidget(self.encrypt_custom_secret_button, alignment=Qt.AlignCenter)
370+
vbox_layout.addSpacing(40)
371+
vbox_layout.addWidget(one_time_pad_warning_label)
372+
vbox_layout.addLayout(Buttons(CloseButton(d)))
373+
374+
# Add stretches to the end of the layouts to prevent the contents from spreading when the dialog is enlarged.
375+
hbox_layout.addStretch(1)
376+
vbox_layout.addStretch(1)
377+
275378
return bool(d.exec_())
276379

277380
def update_wallet_name(self, name):

0 commit comments

Comments
 (0)