def __init__(self, plugin): DefaultConfigWidget.__init__(self, plugin) c = plugin_prefs[STORE_NAME] other_group_box = QGroupBox('Other options', self) self.l.addWidget(other_group_box, self.l.rowCount(), 0, 1, 2) other_group_box_layout = QGridLayout() other_group_box.setLayout(other_group_box_layout) max_downloads_label = QLabel('Maximum title/author search matches to download/evaluate (1 = fastest):', self) max_downloads_label.setToolTip('More matches means higher chance of better\n' 'metadata (but not necessarily).\n') other_group_box_layout.addWidget(max_downloads_label, 1, 0, 1, 1) self.max_downloads_spin = QtGui.QSpinBox(self) self.max_downloads_spin.setMinimum(1) self.max_downloads_spin.setMaximum(100) self.max_downloads_spin.setProperty('value', c.get(KEY_MAX_DOWNLOADS, DEFAULT_STORE_VALUES[KEY_MAX_DOWNLOADS])) other_group_box_layout.addWidget(self.max_downloads_spin, 1, 1, 1, 1) other_group_box_layout.setColumnStretch(2, 1)
def populate_metadata_page(layout, db, book_id, bulk=False, two_column=False, parent=None): def widget_factory(typ, key): if bulk: w = bulk_widgets[typ](db, key, parent) else: w = widgets[typ](db, key, parent) if book_id is not None: w.initialize(book_id) return w fm = db.field_metadata # Get list of all non-composite custom fields. We must make widgets for these fields = fm.custom_field_keys(include_composites=False) cols_to_display = fields cols_to_display.sort(key=partial(field_sort_key, fm=fm)) # This will contain the fields in the order to display them cols = [] # The fields named here must be first in the widget list tweak_cols = tweaks['metadata_edit_custom_column_order'] comments_in_tweak = 0 for key in (tweak_cols or ()): # Add the key if it really exists in the database if key in cols_to_display: cols.append(key) if fm[key]['datatype'] == 'comments': comments_in_tweak += 1 # Add all the remaining fields comments_not_in_tweak = 0 for key in cols_to_display: if key not in cols: cols.append(key) if fm[key]['datatype'] == 'comments': comments_not_in_tweak += 1 count = len(cols) layout_rows_for_comments = 9 if two_column: turnover_point = ((count-comments_not_in_tweak+1) + comments_in_tweak*(layout_rows_for_comments-1))/2 else: # Avoid problems with multi-line widgets turnover_point = count + 1000 ans = [] column = row = base_row = max_row = 0 for key in cols: if not fm[key]['is_editable']: continue # this almost never happens dt = fm[key]['datatype'] if dt == 'composite' or (bulk and dt == 'comments'): continue w = widget_factory(dt, fm[key]['colnum']) ans.append(w) if two_column and dt == 'comments': # Here for compatibility with old layout. Comments always started # in the left column comments_in_tweak -= 1 # no special processing if the comment field was named in the tweak if comments_in_tweak < 0 and comments_not_in_tweak > 0: # Force a turnover, adding comments widgets below max_row. # Save the row to return to if we turn over again column = 0 row = max_row base_row = row turnover_point = row + (comments_not_in_tweak * layout_rows_for_comments)/2 comments_not_in_tweak = 0 l = QGridLayout() if dt == 'comments': layout.addLayout(l, row, column, layout_rows_for_comments, 1) layout.setColumnStretch(column, 100) row += layout_rows_for_comments else: layout.addLayout(l, row, column, 1, 1) layout.setColumnStretch(column, 100) row += 1 for c in range(0, len(w.widgets), 2): if dt != 'comments': w.widgets[c].setWordWrap(True) w.widgets[c].setBuddy(w.widgets[c+1]) l.addWidget(w.widgets[c], c, 0) l.addWidget(w.widgets[c+1], c, 1) l.setColumnStretch(1, 10000) else: l.addWidget(w.widgets[0], 0, 0, 1, 2) l.addItem(QSpacerItem(0, 0, vPolicy=QSizePolicy.Expanding), c, 0, 1, 1) max_row = max(max_row, row) if row >= turnover_point: column = 1 turnover_point = count + 1000 row = base_row items = [] if len(ans) > 0: items.append(QSpacerItem(10, 10, QSizePolicy.Minimum, QSizePolicy.Expanding)) layout.addItem(items[-1], layout.rowCount(), 0, 1, 1) layout.setRowStretch(layout.rowCount()-1, 100) return ans, items
def __init__(self, window, plugin, device_id): title = _("%s Settings") % plugin.device super(SettingsDialog, self).__init__(window, title) self.setMaximumWidth(540) devmgr = plugin.device_manager() config = devmgr.config keystore = window.wallet.get_keystore() handler = keystore.handler thread = keystore.thread # wallet can be None, needn't be window.wallet wallet = devmgr.wallet_by_id(device_id) hs_rows, hs_cols = (64, 128) def invoke_client(method, *args, **kw_args): unpair_after = kw_args.pop('unpair_after', False) def task(): client = devmgr.client_by_id(device_id, handler) if not client: raise RuntimeError("Device not connected") if method: getattr(client, method)(*args, **kw_args) if unpair_after: devmgr.unpair_id(device_id) return client.features thread.add(task, on_success=update) def update(features): self.features = features set_label_enabled() bl_hash = features.bootloader_hash.encode('hex') bl_hash = "\n".join([bl_hash[:32], bl_hash[32:]]) noyes = [_("No"), _("Yes")] endis = [_("Enable Passphrases"), _("Disable Passphrases")] disen = [_("Disabled"), _("Enabled")] setchange = [_("Set a PIN"), _("Change PIN")] version = "%d.%d.%d" % (features.major_version, features.minor_version, features.patch_version) coins = ", ".join(coin.coin_name for coin in features.coins) device_label.setText(features.label) pin_set_label.setText(noyes[features.pin_protection]) passphrases_label.setText(disen[features.passphrase_protection]) bl_hash_label.setText(bl_hash) label_edit.setText(features.label) device_id_label.setText(features.device_id) initialized_label.setText(noyes[features.initialized]) version_label.setText(version) coins_label.setText(coins) clear_pin_button.setVisible(features.pin_protection) clear_pin_warning.setVisible(features.pin_protection) pin_button.setText(setchange[features.pin_protection]) pin_msg.setVisible(not features.pin_protection) passphrase_button.setText(endis[features.passphrase_protection]) language_label.setText(features.language) def set_label_enabled(): label_apply.setEnabled(label_edit.text() != self.features.label) def rename(): invoke_client('change_label', unicode(label_edit.text())) def toggle_passphrase(): title = _("Confirm Toggle Passphrase Protection") currently_enabled = self.features.passphrase_protection if currently_enabled: msg = _("After disabling passphrases, you can only pair this " "Electrum wallet if it had an empty passphrase. " "If its passphrase was not empty, you will need to " "create a new wallet with the install wizard. You " "can use this wallet again at any time by re-enabling " "passphrases and entering its passphrase.") else: msg = _("Your current Electrum wallet can only be used with " "an empty passphrase. You must create a separate " "wallet with the install wizard for other passphrases " "as each one generates a new set of addresses.") msg += "\n\n" + _("Are you sure you want to proceed?") if not self.question(msg, title=title): return invoke_client('toggle_passphrase', unpair_after=currently_enabled) def change_homescreen(): from PIL import Image # FIXME dialog = QFileDialog(self, _("Choose Homescreen")) filename = dialog.getOpenFileName() if filename: im = Image.open(str(filename)) if im.size != (hs_cols, hs_rows): raise Exception('Image must be 64 x 128 pixels') im = im.convert('1') pix = im.load() img = '' for j in range(hs_rows): for i in range(hs_cols): img += '1' if pix[i, j] else '0' img = ''.join( chr(int(img[i:i + 8], 2)) for i in range(0, len(img), 8)) invoke_client('change_homescreen', img) def clear_homescreen(): invoke_client('change_homescreen', '\x00') def set_pin(): invoke_client('set_pin', remove=False) def clear_pin(): invoke_client('set_pin', remove=True) def wipe_device(): if wallet and sum(wallet.get_balance()): title = _("Confirm Device Wipe") msg = _("Are you SURE you want to wipe the device?\n" "Your wallet still has bitcoins in it!") if not self.question( msg, title=title, icon=QMessageBox.Critical): return invoke_client('wipe_device', unpair_after=True) def slider_moved(): mins = timeout_slider.sliderPosition() timeout_minutes.setText(_("%2d minutes") % mins) def slider_released(): config.set_session_timeout(timeout_slider.sliderPosition() * 60) # Information tab info_tab = QWidget() info_layout = QVBoxLayout(info_tab) info_glayout = QGridLayout() info_glayout.setColumnStretch(2, 1) device_label = QLabel() pin_set_label = QLabel() passphrases_label = QLabel() version_label = QLabel() device_id_label = QLabel() bl_hash_label = QLabel() bl_hash_label.setWordWrap(True) coins_label = QLabel() coins_label.setWordWrap(True) language_label = QLabel() initialized_label = QLabel() rows = [ (_("Device Label"), device_label), (_("PIN set"), pin_set_label), (_("Passphrases"), passphrases_label), (_("Firmware Version"), version_label), (_("Device ID"), device_id_label), (_("Bootloader Hash"), bl_hash_label), (_("Supported Coins"), coins_label), (_("Language"), language_label), (_("Initialized"), initialized_label), ] for row_num, (label, widget) in enumerate(rows): info_glayout.addWidget(QLabel(label), row_num, 0) info_glayout.addWidget(widget, row_num, 1) info_layout.addLayout(info_glayout) # Settings tab settings_tab = QWidget() settings_layout = QVBoxLayout(settings_tab) settings_glayout = QGridLayout() # Settings tab - Label label_msg = QLabel( _("Name this %s. If you have mutiple devices " "their labels help distinguish them.") % plugin.device) label_msg.setWordWrap(True) label_label = QLabel(_("Device Label")) label_edit = QLineEdit() label_edit.setMinimumWidth(150) label_edit.setMaxLength(plugin.MAX_LABEL_LEN) label_apply = QPushButton(_("Apply")) label_apply.clicked.connect(rename) label_edit.textChanged.connect(set_label_enabled) settings_glayout.addWidget(label_label, 0, 0) settings_glayout.addWidget(label_edit, 0, 1, 1, 2) settings_glayout.addWidget(label_apply, 0, 3) settings_glayout.addWidget(label_msg, 1, 1, 1, -1) # Settings tab - PIN pin_label = QLabel(_("PIN Protection")) pin_button = QPushButton() pin_button.clicked.connect(set_pin) settings_glayout.addWidget(pin_label, 2, 0) settings_glayout.addWidget(pin_button, 2, 1) pin_msg = QLabel( _("PIN protection is strongly recommended. " "A PIN is your only protection against someone " "stealing your bitcoins if they obtain physical " "access to your %s.") % plugin.device) pin_msg.setWordWrap(True) pin_msg.setStyleSheet("color: red") settings_glayout.addWidget(pin_msg, 3, 1, 1, -1) # Settings tab - Homescreen if plugin.device != 'KeepKey': # Not yet supported by KK firmware homescreen_layout = QHBoxLayout() homescreen_label = QLabel(_("Homescreen")) homescreen_change_button = QPushButton(_("Change...")) homescreen_clear_button = QPushButton(_("Reset")) homescreen_change_button.clicked.connect(change_homescreen) homescreen_clear_button.clicked.connect(clear_homescreen) homescreen_msg = QLabel( _("You can set the homescreen on your " "device to personalize it. You must " "choose a %d x %d monochrome black and " "white image.") % (hs_rows, hs_cols)) homescreen_msg.setWordWrap(True) settings_glayout.addWidget(homescreen_label, 4, 0) settings_glayout.addWidget(homescreen_change_button, 4, 1) settings_glayout.addWidget(homescreen_clear_button, 4, 2) settings_glayout.addWidget(homescreen_msg, 5, 1, 1, -1) # Settings tab - Session Timeout timeout_label = QLabel(_("Session Timeout")) timeout_minutes = QLabel() timeout_slider = QSlider(Qt.Horizontal) timeout_slider.setRange(1, 60) timeout_slider.setSingleStep(1) timeout_slider.setTickInterval(5) timeout_slider.setTickPosition(QSlider.TicksBelow) timeout_slider.setTracking(True) timeout_msg = QLabel( _("Clear the session after the specified period " "of inactivity. Once a session has timed out, " "your PIN and passphrase (if enabled) must be " "re-entered to use the device.")) timeout_msg.setWordWrap(True) timeout_slider.setSliderPosition(config.get_session_timeout() // 60) slider_moved() timeout_slider.valueChanged.connect(slider_moved) timeout_slider.sliderReleased.connect(slider_released) settings_glayout.addWidget(timeout_label, 6, 0) settings_glayout.addWidget(timeout_slider, 6, 1, 1, 3) settings_glayout.addWidget(timeout_minutes, 6, 4) settings_glayout.addWidget(timeout_msg, 7, 1, 1, -1) settings_layout.addLayout(settings_glayout) settings_layout.addStretch(1) # Advanced tab advanced_tab = QWidget() advanced_layout = QVBoxLayout(advanced_tab) advanced_glayout = QGridLayout() # Advanced tab - clear PIN clear_pin_button = QPushButton(_("Disable PIN")) clear_pin_button.clicked.connect(clear_pin) clear_pin_warning = QLabel( _("If you disable your PIN, anyone with physical access to your " "%s device can spend your bitcoins.") % plugin.device) clear_pin_warning.setWordWrap(True) clear_pin_warning.setStyleSheet("color: red") advanced_glayout.addWidget(clear_pin_button, 0, 2) advanced_glayout.addWidget(clear_pin_warning, 1, 0, 1, 5) # Advanced tab - toggle passphrase protection passphrase_button = QPushButton() passphrase_button.clicked.connect(toggle_passphrase) passphrase_msg = WWLabel(PASSPHRASE_HELP) passphrase_warning = WWLabel(PASSPHRASE_NOT_PIN) passphrase_warning.setStyleSheet("color: red") advanced_glayout.addWidget(passphrase_button, 3, 2) advanced_glayout.addWidget(passphrase_msg, 4, 0, 1, 5) advanced_glayout.addWidget(passphrase_warning, 5, 0, 1, 5) # Advanced tab - wipe device wipe_device_button = QPushButton(_("Wipe Device")) wipe_device_button.clicked.connect(wipe_device) wipe_device_msg = QLabel( _("Wipe the device, removing all data from it. The firmware " "is left unchanged.")) wipe_device_msg.setWordWrap(True) wipe_device_warning = QLabel( _("Only wipe a device if you have the recovery seed written down " "and the device wallet(s) are empty, otherwise the bitcoins " "will be lost forever.")) wipe_device_warning.setWordWrap(True) wipe_device_warning.setStyleSheet("color: red") advanced_glayout.addWidget(wipe_device_button, 6, 2) advanced_glayout.addWidget(wipe_device_msg, 7, 0, 1, 5) advanced_glayout.addWidget(wipe_device_warning, 8, 0, 1, 5) advanced_layout.addLayout(advanced_glayout) advanced_layout.addStretch(1) tabs = QTabWidget(self) tabs.addTab(info_tab, _("Information")) tabs.addTab(settings_tab, _("Settings")) tabs.addTab(advanced_tab, _("Advanced")) dialog_vbox = QVBoxLayout(self) dialog_vbox.addWidget(tabs) dialog_vbox.addLayout(Buttons(CloseButton(self))) # Update information invoke_client(None)
def __init__(self, window, plugin, device_id): title = _("%s Settings") % plugin.device super(SettingsDialog, self).__init__(window, title) self.setMaximumWidth(540) devmgr = plugin.device_manager() handler = window.wallet.handler thread = window.wallet.thread # wallet can be None, needn't be window.wallet wallet = devmgr.wallet_by_id(device_id) hs_rows, hs_cols = (64, 128) self.current_label=None def invoke_client(method, *args, **kw_args): unpair_after = kw_args.pop('unpair_after', False) def task(): client = devmgr.client_by_id(device_id, handler) if not client: raise RuntimeError("Device not connected") if method: getattr(client, method)(*args, **kw_args) if unpair_after: devmgr.unpair_id(device_id) return client.features thread.add(task, on_success=update) def update(features): self.current_label = features.label set_label_enabled() bl_hash = features.bootloader_hash.encode('hex') bl_hash = "\n".join([bl_hash[:32], bl_hash[32:]]) noyes = [_("No"), _("Yes")] endis = [_("Enable Passphrases"), _("Disable Passphrases")] disen = [_("Disabled"), _("Enabled")] setchange = [_("Set a PIN"), _("Change PIN")] version = "%d.%d.%d" % (features.major_version, features.minor_version, features.patch_version) coins = ", ".join(coin.coin_name for coin in features.coins) device_label.setText(features.label) pin_set_label.setText(noyes[features.pin_protection]) passphrases_label.setText(disen[features.passphrase_protection]) bl_hash_label.setText(bl_hash) label_edit.setText(features.label) device_id_label.setText(features.device_id) initialized_label.setText(noyes[features.initialized]) version_label.setText(version) coins_label.setText(coins) clear_pin_button.setVisible(features.pin_protection) clear_pin_warning.setVisible(features.pin_protection) pin_button.setText(setchange[features.pin_protection]) pin_msg.setVisible(not features.pin_protection) passphrase_button.setText(endis[features.passphrase_protection]) language_label.setText(features.language) def set_label_enabled(): label_apply.setEnabled(label_edit.text() != self.current_label) def rename(): invoke_client('change_label', unicode(label_edit.text())) def toggle_passphrase(): title = _("Confirm Toggle Passphrase Protection") msg = _("This will cause your Electrum wallet to be unpaired " "unless your passphrase was or will be empty.\n\n" "This is because addresses will no " "longer correspond to those used by your %s.\n\n" "You will need to create a new Electrum wallet " "with the install wizard so that they match.\n\n" "Are you sure you want to proceed?") % plugin.device if not self.question(msg, title=title): return invoke_client('toggle_passphrase', unpair_after=True) def change_homescreen(): from PIL import Image # FIXME dialog = QFileDialog(self, _("Choose Homescreen")) filename = dialog.getOpenFileName() if filename: im = Image.open(str(filename)) if im.size != (hs_cols, hs_rows): raise Exception('Image must be 64 x 128 pixels') im = im.convert('1') pix = im.load() img = '' for j in range(hs_rows): for i in range(hs_cols): img += '1' if pix[i, j] else '0' img = ''.join(chr(int(img[i:i + 8], 2)) for i in range(0, len(img), 8)) invoke_client('change_homescreen', img) def clear_homescreen(): invoke_client('change_homescreen', '\x00') def set_pin(): invoke_client('set_pin', remove=False) def clear_pin(): invoke_client('set_pin', remove=True) def wipe_device(): if wallet and sum(wallet.get_balance()): title = _("Confirm Device Wipe") msg = _("Are you SURE you want to wipe the device?\n" "Your wallet still has bitcoins in it!") if not self.question(msg, title=title, icon=QMessageBox.Critical): return invoke_client('wipe_device', unpair_after=True) def slider_moved(): mins = timeout_slider.sliderPosition() timeout_minutes.setText(_("%2d minutes") % mins) def slider_released(): seconds = timeout_slider.sliderPosition() * 60 wallet.set_session_timeout(seconds) # Information tab info_tab = QWidget() info_layout = QVBoxLayout(info_tab) info_glayout = QGridLayout() info_glayout.setColumnStretch(2, 1) device_label = QLabel() pin_set_label = QLabel() passphrases_label = QLabel() version_label = QLabel() device_id_label = QLabel() bl_hash_label = QLabel() bl_hash_label.setWordWrap(True) coins_label = QLabel() coins_label.setWordWrap(True) language_label = QLabel() initialized_label = QLabel() rows = [ (_("Device Label"), device_label), (_("PIN set"), pin_set_label), (_("Passphrases"), passphrases_label), (_("Firmware Version"), version_label), (_("Device ID"), device_id_label), (_("Bootloader Hash"), bl_hash_label), (_("Supported Coins"), coins_label), (_("Language"), language_label), (_("Initialized"), initialized_label), ] for row_num, (label, widget) in enumerate(rows): info_glayout.addWidget(QLabel(label), row_num, 0) info_glayout.addWidget(widget, row_num, 1) info_layout.addLayout(info_glayout) # Settings tab settings_tab = QWidget() settings_layout = QVBoxLayout(settings_tab) settings_glayout = QGridLayout() # Settings tab - Label label_msg = QLabel(_("Name this %s. If you have mutiple devices " "their labels help distinguish them.") % plugin.device) label_msg.setWordWrap(True) label_label = QLabel(_("Device Label")) label_edit = QLineEdit() label_edit.setMinimumWidth(150) label_edit.setMaxLength(plugin.MAX_LABEL_LEN) label_apply = QPushButton(_("Apply")) label_apply.clicked.connect(rename) label_edit.textChanged.connect(set_label_enabled) settings_glayout.addWidget(label_label, 0, 0) settings_glayout.addWidget(label_edit, 0, 1, 1, 2) settings_glayout.addWidget(label_apply, 0, 3) settings_glayout.addWidget(label_msg, 1, 1, 1, -1) # Settings tab - PIN pin_label = QLabel(_("PIN Protection")) pin_button = QPushButton() pin_button.clicked.connect(set_pin) settings_glayout.addWidget(pin_label, 2, 0) settings_glayout.addWidget(pin_button, 2, 1) pin_msg = QLabel(_("PIN protection is strongly recommended. " "A PIN is your only protection against someone " "stealing your bitcoins if they obtain physical " "access to your %s.") % plugin.device) pin_msg.setWordWrap(True) pin_msg.setStyleSheet("color: red") settings_glayout.addWidget(pin_msg, 3, 1, 1, -1) # Settings tab - Homescreen if plugin.device != 'KeepKey': # Not yet supported by KK firmware homescreen_layout = QHBoxLayout() homescreen_label = QLabel(_("Homescreen")) homescreen_change_button = QPushButton(_("Change...")) homescreen_clear_button = QPushButton(_("Reset")) homescreen_change_button.clicked.connect(change_homescreen) homescreen_clear_button.clicked.connect(clear_homescreen) homescreen_msg = QLabel(_("You can set the homescreen on your " "device to personalize it. You must " "choose a %d x %d monochrome black and " "white image.") % (hs_rows, hs_cols)) homescreen_msg.setWordWrap(True) settings_glayout.addWidget(homescreen_label, 4, 0) settings_glayout.addWidget(homescreen_change_button, 4, 1) settings_glayout.addWidget(homescreen_clear_button, 4, 2) settings_glayout.addWidget(homescreen_msg, 5, 1, 1, -1) # Settings tab - Session Timeout if wallet: timeout_label = QLabel(_("Session Timeout")) timeout_minutes = QLabel() timeout_slider = QSlider(Qt.Horizontal) timeout_slider.setRange(1, 60) timeout_slider.setSingleStep(1) timeout_slider.setTickInterval(5) timeout_slider.setTickPosition(QSlider.TicksBelow) timeout_slider.setTracking(True) timeout_msg = QLabel( _("Clear the session after the specified period " "of inactivity. Once a session has timed out, " "your PIN and passphrase (if enabled) must be " "re-entered to use the device.")) timeout_msg.setWordWrap(True) timeout_slider.setSliderPosition(wallet.session_timeout // 60) slider_moved() timeout_slider.valueChanged.connect(slider_moved) timeout_slider.sliderReleased.connect(slider_released) settings_glayout.addWidget(timeout_label, 6, 0) settings_glayout.addWidget(timeout_slider, 6, 1, 1, 3) settings_glayout.addWidget(timeout_minutes, 6, 4) settings_glayout.addWidget(timeout_msg, 7, 1, 1, -1) settings_layout.addLayout(settings_glayout) settings_layout.addStretch(1) # Advanced tab advanced_tab = QWidget() advanced_layout = QVBoxLayout(advanced_tab) advanced_glayout = QGridLayout() # Advanced tab - clear PIN clear_pin_button = QPushButton(_("Disable PIN")) clear_pin_button.clicked.connect(clear_pin) clear_pin_warning = QLabel( _("If you disable your PIN, anyone with physical access to your " "%s device can spend your bitcoins.") % plugin.device) clear_pin_warning.setWordWrap(True) clear_pin_warning.setStyleSheet("color: red") advanced_glayout.addWidget(clear_pin_button, 0, 2) advanced_glayout.addWidget(clear_pin_warning, 1, 0, 1, 5) # Advanced tab - toggle passphrase protection passphrase_button = QPushButton() passphrase_button.clicked.connect(toggle_passphrase) passphrase_msg = WWLabel(PASSPHRASE_HELP) passphrase_warning = WWLabel(PASSPHRASE_NOT_PIN) passphrase_warning.setStyleSheet("color: red") advanced_glayout.addWidget(passphrase_button, 3, 2) advanced_glayout.addWidget(passphrase_msg, 4, 0, 1, 5) advanced_glayout.addWidget(passphrase_warning, 5, 0, 1, 5) # Advanced tab - wipe device wipe_device_button = QPushButton(_("Wipe Device")) wipe_device_button.clicked.connect(wipe_device) wipe_device_msg = QLabel( _("Wipe the device, removing all data from it. The firmware " "is left unchanged.")) wipe_device_msg.setWordWrap(True) wipe_device_warning = QLabel( _("Only wipe a device if you have the recovery seed written down " "and the device wallet(s) are empty, otherwise the bitcoins " "will be lost forever.")) wipe_device_warning.setWordWrap(True) wipe_device_warning.setStyleSheet("color: red") advanced_glayout.addWidget(wipe_device_button, 6, 2) advanced_glayout.addWidget(wipe_device_msg, 7, 0, 1, 5) advanced_glayout.addWidget(wipe_device_warning, 8, 0, 1, 5) advanced_layout.addLayout(advanced_glayout) advanced_layout.addStretch(1) tabs = QTabWidget(self) tabs.addTab(info_tab, _("Information")) tabs.addTab(settings_tab, _("Settings")) tabs.addTab(advanced_tab, _("Advanced")) dialog_vbox = QVBoxLayout(self) dialog_vbox.addWidget(tabs) dialog_vbox.addLayout(Buttons(CloseButton(self))) # Update information invoke_client(None)
def populate_metadata_page(layout, db, book_id, bulk=False, two_column=False, parent=None): def widget_factory(typ, key): if bulk: w = bulk_widgets[typ](db, key, parent) else: w = widgets[typ](db, key, parent) if book_id is not None: w.initialize(book_id) return w fm = db.field_metadata # Get list of all non-composite custom fields. We must make widgets for these fields = fm.custom_field_keys(include_composites=False) cols_to_display = fields cols_to_display.sort(key=partial(field_sort_key, fm=fm)) # This will contain the fields in the order to display them cols = [] # The fields named here must be first in the widget list tweak_cols = tweaks['metadata_edit_custom_column_order'] comments_in_tweak = 0 for key in (tweak_cols or ()): # Add the key if it really exists in the database if key in cols_to_display: cols.append(key) if fm[key]['datatype'] == 'comments': comments_in_tweak += 1 # Add all the remaining fields comments_not_in_tweak = 0 for key in cols_to_display: if key not in cols: cols.append(key) if fm[key]['datatype'] == 'comments': comments_not_in_tweak += 1 count = len(cols) layout_rows_for_comments = 9 if two_column: turnover_point = ((count-comments_not_in_tweak+1) + comments_in_tweak*(layout_rows_for_comments-1))/2 else: # Avoid problems with multi-line widgets turnover_point = count + 1000 ans = [] column = row = base_row = max_row = 0 for key in cols: if not fm[key]['is_editable']: continue # this almost never happens dt = fm[key]['datatype'] if dt == 'composite' or (bulk and dt == 'comments'): continue w = widget_factory(dt, fm[key]['colnum']) ans.append(w) if two_column and dt == 'comments': # Here for compatibility with old layout. Comments always started # in the left column comments_in_tweak -= 1 # no special processing if the comment field was named in the tweak if comments_in_tweak < 0 and comments_not_in_tweak > 0: # Force a turnover, adding comments widgets below max_row. # Save the row to return to if we turn over again column = 0 row = max_row base_row = row turnover_point = row + (comments_not_in_tweak * layout_rows_for_comments)/2 comments_not_in_tweak = 0 l = QGridLayout() if dt == 'comments': layout.addLayout(l, row, column, layout_rows_for_comments, 1) layout.setColumnStretch(column, 100) row += layout_rows_for_comments else: layout.addLayout(l, row, column, 1, 1) layout.setColumnStretch(column, 100) row += 1 for c in range(0, len(w.widgets), 2): if dt != 'comments': w.widgets[c].setWordWrap(True) w.widgets[c].setBuddy(w.widgets[c+1]) l.addWidget(w.widgets[c], c, 0) l.addWidget(w.widgets[c+1], c, 1) l.setColumnStretch(1, 10000) else: l.addWidget(w.widgets[0], 0, 0, 1, 2) l.addItem(QSpacerItem(0, 0, vPolicy=QSizePolicy.Expanding), c, 0, 1, 1) max_row = max(max_row, row) if row >= turnover_point: column = 1 turnover_point = count + 1000 row = base_row items = [] if len(ans) > 0: items.append(QSpacerItem(10, 10, QSizePolicy.Minimum, QSizePolicy.Expanding)) layout.addItem(items[-1], layout.rowCount(), 0, 1, 1) layout.setRowStretch(layout.rowCount()-1, 100) return ans, items
def __init__(self, main): self.main = main ########################################################################## ##### Display the conversion values based on the Coinbase API self.lastPriceFetch = 0 self.lblHeader = QRichLabel(tr("""<b>Tracking buy and sell prices on Coinbase every 60 seconds</b>"""), doWrap=False) self.lblLastTime = QRichLabel('', doWrap=False) self.lblSellLabel = QRichLabel(tr('Coinbase <b>Sell</b> Price (USD):'), doWrap=False) self.lblBuyLabel = QRichLabel(tr('Coinbase <b>Buy</b> Price (USD):'), doWrap=False) self.lblSellPrice = QRichLabel('<Not Available>') self.lblBuyPrice = QRichLabel('<Not Available>') self.lastSellStr = '' self.lastBuyStr = '' self.btnUpdate = QPushButton(tr('Check Now')) self.main.connect(self.btnUpdate, SIGNAL('clicked()'), self.checkUpdatePrice) ########################################################################## ##### A calculator for converting prices between USD and BTC lblCalcTitle = QRichLabel(tr("""Convert between USD and BTC using Coinbase sell price"""), hAlign=Qt.AlignHCenter, doWrap=False) self.edtEnterUSD = QLineEdit() self.edtEnterBTC = QLineEdit() self.lblEnterUSD1 = QRichLabel('$') self.lblEnterUSD2 = QRichLabel('USD') self.lblEnterBTC = QRichLabel('BTC') btnClear = QPushButton('Clear') self.main.connect(self.edtEnterUSD, SIGNAL('textEdited(QString)'), self.updateCalcBTC) self.main.connect(self.edtEnterBTC, SIGNAL('textEdited(QString)'), self.updateCalcUSD) def clearCalc(): self.edtEnterUSD.setText('') self.edtEnterBTC.setText('') self.main.connect(btnClear, SIGNAL('clicked()'), clearCalc) frmCalcMid = makeHorizFrame( [self.lblEnterUSD1, self.edtEnterUSD, self.lblEnterUSD2, 'Stretch', self.edtEnterBTC, self.lblEnterBTC]) frmCalcClear = makeHorizFrame(['Stretch', btnClear, 'Stretch']) frmCalc = makeVertFrame([lblCalcTitle, frmCalcMid, frmCalcClear], STYLE_PLAIN) ########################################################################## ##### A table showing you the total balance of each wallet in USD and BTC lblWltTableTitle = QRichLabel(tr("Wallet balances converted to USD"), doWrap=False, hAlign=Qt.AlignHCenter) numWallets = len(self.main.walletMap) self.wltTable = QTableWidget(self.main) self.wltTable.setRowCount(numWallets) self.wltTable.setColumnCount(4) self.wltTable.horizontalHeader().setStretchLastSection(True) self.wltTable.setMinimumWidth(600) ########################################################################## ##### Setup the main layout for the tab mainLayout = QGridLayout() i=0 mainLayout.addWidget(self.lblHeader, i,0, 1,3) i+=1 mainLayout.addItem(QSpacerItem(15,15), i,0) mainLayout.addWidget(self.lblSellLabel, i,1) mainLayout.addWidget(self.lblSellPrice, i,2) i+=1 mainLayout.addItem(QSpacerItem(15,15), i,0) mainLayout.addWidget(self.lblBuyLabel, i,1) mainLayout.addWidget(self.lblBuyPrice, i,2) i+=1 mainLayout.addWidget(self.lblLastTime, i,0, 1,2) mainLayout.addWidget(self.btnUpdate, i,2) i+=1 mainLayout.addItem(QSpacerItem(20,20), i,0) i+=1 mainLayout.addWidget(frmCalc, i,0, 1,3) i+=1 mainLayout.addItem(QSpacerItem(30,30), i,0) i+=1 mainLayout.addWidget(lblWltTableTitle, i,0, 1,3) i+=1 mainLayout.addWidget(self.wltTable, i,0, 1,3) mainLayout.setColumnStretch(0,0) mainLayout.setColumnStretch(1,1) mainLayout.setColumnStretch(2,1) tabWidget = QWidget() tabWidget.setLayout(mainLayout) frmH = makeHorizFrame(['Stretch', tabWidget, 'Stretch']) frm = makeVertFrame(['Space(20)', frmH, 'Stretch']) # Now set the scrollarea widget to the layout self.tabToDisplay = QScrollArea() self.tabToDisplay.setWidgetResizable(True) self.tabToDisplay.setWidget(frm)
def __init__(self, window, plugin): self.plugin = plugin self.window = window # The main electrum window title = _("%s Settings") % plugin.device super(SettingsDialog, self).__init__(window, title) self.setMaximumWidth(540) hs_rows, hs_cols = (64, 128) def get_client(lookup=DeviceMgr.PAIRED): return self.plugin.get_client(wallet, lookup) def update(): features = get_client(DeviceMgr.PAIRED).features self.features = features # The above was for outer scopes. Now the real logic. set_label_enabled() bl_hash = features.bootloader_hash.encode('hex') bl_hash = "\n".join([bl_hash[:32], bl_hash[32:]]) noyes = [_("No"), _("Yes")] endis = [_("Enable Passphrases"), _("Disable Passphrases")] setchange = [_("Set a PIN"), _("Change PIN")] version = "%d.%d.%d" % (features.major_version, features.minor_version, features.patch_version) coins = ", ".join(coin.coin_name for coin in features.coins) device_label.setText(features.label) pin_set_label.setText(noyes[features.pin_protection]) bl_hash_label.setText(bl_hash) label_edit.setText(features.label) device_id_label.setText(features.device_id) initialized_label.setText(noyes[features.initialized]) version_label.setText(version) coins_label.setText(coins) clear_pin_button.setVisible(features.pin_protection) clear_pin_warning.setVisible(features.pin_protection) pin_button.setText(setchange[features.pin_protection]) pin_msg.setVisible(not features.pin_protection) passphrase_button.setText(endis[features.passphrase_protection]) language_label.setText(features.language) def set_label_enabled(): label_apply.setEnabled(label_edit.text() != self.features.label) def rename(): get_client().change_label(unicode(label_edit.text())) update() def toggle_passphrase(): title = _("Confirm Toggle Passphrase Protection") msg = _("This will cause your Electrum wallet to be unpaired " "unless your passphrase was or will be empty.\n\n" "This is because addresses will no " "longer correspond to those used by your %s.\n\n" "You will need to create a new Electrum wallet " "with the install wizard so that they match.\n\n" "Are you sure you want to proceed?") % plugin.device if not self.question(msg, title=title): return get_client().toggle_passphrase() self.device_manager().close_wallet(wallet) # Unpair update() def change_homescreen(): dialog = QFileDialog(self, _("Choose Homescreen")) filename = dialog.getOpenFileName() if filename: im = Image.open(str(filename)) if im.size != (hs_cols, hs_rows): raise Exception('Image must be 64 x 128 pixels') im = im.convert('1') pix = im.load() img = '' for j in range(hs_rows): for i in range(hs_cols): img += '1' if pix[i, j] else '0' img = ''.join(chr(int(img[i:i + 8], 2)) for i in range(0, len(img), 8)) get_client().change_homescreen(img) def clear_homescreen(): get_client().change_homescreen('\x00') def set_pin(remove=False): get_client().set_pin(remove=remove) update() def clear_pin(): set_pin(remove=True) def wipe_device(): # FIXME: cannot yet wipe a device that is only plugged in if sum(wallet.get_balance()): title = _("Confirm Device Wipe") msg = _("Are you SURE you want to wipe the device?\n" "Your wallet still has bitcoins in it!") if not self.question(msg, title=title, icon=QMessageBox.Critical): return # Note: we use PRESENT so that a user who has forgotten # their PIN is not prevented from wiping their device get_client(DeviceMgr.PRESENT).wipe_device() self.device_manager().close_wallet(wallet) update() def slider_moved(): mins = timeout_slider.sliderPosition() timeout_minutes.setText(_("%2d minutes") % mins) wallet = window.wallet handler = wallet.handler device = plugin.device dialog_vbox = QVBoxLayout(self) # Information tab info_tab = QWidget() info_layout = QVBoxLayout(info_tab) info_glayout = QGridLayout() info_glayout.setColumnStretch(2, 1) device_label = QLabel() pin_set_label = QLabel() version_label = QLabel() device_id_label = QLabel() bl_hash_label = QLabel() bl_hash_label.setWordWrap(True) coins_label = QLabel() coins_label.setWordWrap(True) language_label = QLabel() initialized_label = QLabel() rows = [ (_("Device Label"), device_label), (_("PIN set"), pin_set_label), (_("Firmware Version"), version_label), (_("Serial Number"), device_id_label), (_("Bootloader Hash"), bl_hash_label), (_("Supported Coins"), coins_label), (_("Language"), language_label), (_("Initialized"), initialized_label), ] for row_num, (label, widget) in enumerate(rows): info_glayout.addWidget(QLabel(label), row_num, 0) info_glayout.addWidget(widget, row_num, 1) info_layout.addLayout(info_glayout) # Settings tab settings_tab = QWidget() settings_layout = QVBoxLayout(settings_tab) settings_glayout = QGridLayout() #settings_glayout.setColumnStretch(3, 1) # Settings tab - Label label_msg = QLabel(_("Name this %s. If you have mutiple devices " "their labels help distinguish them.") % plugin.device) label_msg.setWordWrap(True) label_label = QLabel(_("Device Label")) label_edit = QLineEdit() label_edit.setMinimumWidth(150) label_edit.setMaxLength(self.plugin.MAX_LABEL_LEN) label_apply = QPushButton(_("Apply")) label_apply.clicked.connect(rename) label_edit.textChanged.connect(set_label_enabled) settings_glayout.addWidget(label_label, 0, 0) settings_glayout.addWidget(label_edit, 0, 1, 1, 2) settings_glayout.addWidget(label_apply, 0, 3) settings_glayout.addWidget(label_msg, 1, 1, 1, -1) # Settings tab - PIN pin_label = QLabel(_("PIN Protection")) pin_button = QPushButton() pin_button.clicked.connect(set_pin) settings_glayout.addWidget(pin_label, 2, 0) settings_glayout.addWidget(pin_button, 2, 1) pin_msg = QLabel(_("PIN protection is strongly recommended. " "A PIN is your only protection against someone " "stealing your bitcoins if they obtain physical " "access to your %s.") % plugin.device) pin_msg.setWordWrap(True) pin_msg.setStyleSheet("color: red") settings_glayout.addWidget(pin_msg, 3, 1, 1, -1) settings_layout.addLayout(settings_glayout) # Settings tab - Homescreen homescreen_layout = QHBoxLayout() homescreen_label = QLabel(_("Homescreen")) homescreen_change_button = QPushButton(_("Change...")) homescreen_clear_button = QPushButton(_("Reset")) homescreen_change_button.clicked.connect(change_homescreen) homescreen_clear_button.clicked.connect(clear_homescreen) homescreen_msg = QLabel(_("You can set the homescreen on your device " "to personalize it. You must choose a " "%d x %d monochrome black and white image.") % (hs_rows, hs_cols)) homescreen_msg.setWordWrap(True) settings_glayout.addWidget(homescreen_label, 4, 0) settings_glayout.addWidget(homescreen_change_button, 4, 1) settings_glayout.addWidget(homescreen_clear_button, 4, 2) settings_glayout.addWidget(homescreen_msg, 5, 1, 1, -1) # Settings tab - Session Timeout timeout_label = QLabel(_("Session Timeout")) timeout_minutes = QLabel() timeout_slider = self.slider = QSlider(Qt.Horizontal) timeout_slider.setRange(1, 60) timeout_slider.setSingleStep(1) timeout_slider.setSliderPosition(wallet.session_timeout // 60) timeout_slider.setTickInterval(5) timeout_slider.setTickPosition(QSlider.TicksBelow) timeout_slider.setTracking(True) timeout_slider.valueChanged.connect(slider_moved) timeout_msg = QLabel(_("Clear the session after the specified period " "of inactivity. Once a session has timed out, " "your PIN and passphrase (if enabled) must be " "re-entered to use the device.")) timeout_msg.setWordWrap(True) settings_glayout.addWidget(timeout_label, 6, 0) settings_glayout.addWidget(timeout_slider, 6, 1, 1, 3) settings_glayout.addWidget(timeout_minutes, 6, 4) settings_glayout.addWidget(timeout_msg, 7, 1, 1, -1) # Advanced tab advanced_tab = QWidget() advanced_layout = QVBoxLayout(advanced_tab) advanced_glayout = QGridLayout() # Advanced tab - clear PIN clear_pin_button = QPushButton(_("Disable PIN")) clear_pin_button.clicked.connect(clear_pin) clear_pin_warning = QLabel(_("If you disable your PIN, anyone with " "physical access to your %s device can " "spend your bitcoins.") % plugin.device) clear_pin_warning.setWordWrap(True) clear_pin_warning.setStyleSheet("color: red") advanced_glayout.addWidget(clear_pin_button, 0, 2) advanced_glayout.addWidget(clear_pin_warning, 1, 0, 1, 5) # Advanced tab - toggle passphrase protection passphrase_button = QPushButton() passphrase_button.clicked.connect(toggle_passphrase) passphrase_msg = QLabel( _("Passphrases allow you to access new wallets, each " "hidden behind a particular case-sensitive passphrase. You " "need to create a separate Electrum wallet for each passphrase " "you use as they each generate different addresses. Changing " "your passphrase does not lose other wallets, each is still " "accessible behind its own passphrase.")) passphrase_msg.setWordWrap(True) passphrase_warning = QLabel( _("If you forget a passphrase you will be unable to access any " "bitcoins in the wallet behind it. A passphrase is not a PIN. " "Only change this if you are sure you understand it.")) passphrase_warning.setWordWrap(True) passphrase_warning.setStyleSheet("color: red") advanced_glayout.addWidget(passphrase_button, 3, 2) advanced_glayout.addWidget(passphrase_msg, 4, 0, 1, 5) advanced_glayout.addWidget(passphrase_warning, 5, 0, 1, 5) # Advanced tab - wipe device wipe_device_button = QPushButton(_("Wipe Device")) wipe_device_button.clicked.connect(wipe_device) wipe_device_msg = QLabel( _("Wipe the device, removing all data from it. The firmware " "is left unchanged.")) wipe_device_msg.setWordWrap(True) wipe_device_warning = QLabel( _("Only wipe a device if you have the recovery seed written down " "and the device wallet(s) are empty, otherwise the bitcoins " "will be lost forever.")) wipe_device_warning.setWordWrap(True) wipe_device_warning.setStyleSheet("color: red") advanced_glayout.addWidget(wipe_device_button, 6, 2) advanced_glayout.addWidget(wipe_device_msg, 7, 0, 1, 5) advanced_glayout.addWidget(wipe_device_warning, 8, 0, 1, 5) advanced_layout.addLayout(advanced_glayout) advanced_layout.addStretch(1) tabs = QTabWidget(self) tabs.addTab(info_tab, _("Information")) tabs.addTab(settings_tab, _("Settings")) tabs.addTab(advanced_tab, _("Advanced")) # Update information and then connect change slots update() slider_moved() dialog_vbox.addWidget(tabs) dialog_vbox.addLayout(Buttons(CloseButton(self)))
class FtcGuiApplication(TouchApplication): def __init__(self, args): TouchApplication.__init__(self, args) # create the empty main window self.w = TouchWindow("Run JetsonEV") self.relative_path = os.path.dirname(os.path.realpath(__file__)) self.script = os.path.join(self.relative_path, 'Run_car.py') self.grid = QGridLayout() self.grid.setSpacing(0) self.process = QProcess() self.process.readyReadStandardOutput.connect(self.stdoutReady) self.process.readyReadStandardError.connect(self.stderrReady) self.play_btn = ShadowButton(os.path.join(self.relative_path, 'start')) self.play_btn.setText("Start") self.play_btn.clicked.connect(self.start_script) self.grid.addWidget(self.play_btn, 0, 0, 1, 1) self.grid.setColumnStretch(0, 1.25) self.imu_box = QCheckBox('IMU') self.imu_box.setChecked(True) self.camera_box = QCheckBox('Cam') self.camera_box.setChecked(False) self.lidar_box = QCheckBox('Lidar') self.lidar_box.setChecked(False) self.grid.addWidget(self.imu_box, 0, 1, 1, 1) self.grid.setColumnStretch(1, 1) self.grid.addWidget(self.camera_box, 0, 2, 1, 1) self.grid.setColumnStretch(2, 1) self.grid.addWidget(self.lidar_box, 0, 3, 1, 1) self.grid.setColumnStretch(3, 1.5) self.grid.setAlignment(Qt.AlignCenter) self.stop_btn = ShadowButton(os.path.join(self.relative_path, 'stop')) self.stop_btn.setText("Stop") self.stop_btn.clicked.connect(self.stop_script) self.grid.addWidget(self.stop_btn, 0, 4, 1, 1) self.grid.setRowStretch(1, 4) self.console_output = QPlainTextEdit() self.console_output.setReadOnly(True) console_style = "QPlainTextEdit {" \ "background-color: black;" \ "color: white;" \ "}" self.console_output.setFocusPolicy(Qt.NoFocus) self.console_output.setFrameStyle(3) self.console_output.setStyleSheet(console_style) self.grid.addWidget(self.console_output, 1, 0, 1, 5) self.w.centralWidget.setLayout(self.grid) self.w.centralWidget.keyReleaseEvent = lambda event: self.filter_out_arrow_release_keys( self.w.centralWidget, event) self.w.centralWidget.keyPressEvent = lambda event: self.filter_out_arrow_press_keys( self.w.centralWidget, event) self.w.keyPressEvent = lambda event: self.filter_out_arrow_press_keys( self.w, event) self.w.keyReleaseEvent = lambda event: self.filter_out_arrow_release_keys( self.w, event) self.play_btn.keyReleaseEvent = lambda event: self.filter_out_arrow_release_keys( self.play_btn, event) self.play_btn.keyPressEvent = lambda event: self.filter_out_arrow_press_keys( self.play_btn, event) self.stop_btn.keyReleaseEvent = lambda event: self.filter_out_arrow_release_keys( self.stop_btn, event) self.stop_btn.keyPressEvent = lambda event: self.filter_out_arrow_press_keys( self.stop_btn, event) self.imu_box.keyReleaseEvent = lambda event: self.filter_out_arrow_release_keys( self.imu_box, event) self.imu_box.keyPressEvent = lambda event: self.filter_out_arrow_press_keys( self.imu_box, event) self.camera_box.keyReleaseEvent = lambda event: self.filter_out_arrow_release_keys( self.camera_box, event) self.camera_box.keyPressEvent = lambda event: self.filter_out_arrow_press_keys( self.camera_box, event) self.lidar_box.keyReleaseEvent = lambda event: self.filter_out_arrow_release_keys( self.lidar_box, event) self.lidar_box.keyPressEvent = lambda event: self.filter_out_arrow_press_keys( self.lidar_box, event) self.xbox_controller = XBoxInput() self.xbox_controller.cycle_right.connect(self.cycle_right) self.xbox_controller.cycle_left.connect(self.cycle_left) self.speed_widget = SpeedWidget() self.grid.addWidget(self.speed_widget, 1, 0, 1, 5) self.speed_widget.hide() self.imu_widget = IMUWidget() self.grid.addWidget(self.imu_widget, 1, 0, 1, 5) self.imu_widget.hide() self.camera_widget = VideoWidget() self.grid.addWidget(self.camera_widget, 1, 0, 1, 5) self.camera_widget.hide() self.lidar_widget = LidarWidget() self.grid.addWidget(self.lidar_widget, 1, 0, 1, 5) self.lidar_widget.hide() self.widgets_to_show = [] self.show_widget_index = 0 self.w.show() self.aboutToQuit.connect(self.xbox_controller.xbox_controller.close) self.exec_() def cycle_right(self, axis): last_index = self.show_widget_index self.show_widget_index += 1 if self.show_widget_index >= len(self.widgets_to_show): self.show_widget_index = 0 self.widgets_to_show[last_index].hide() self.widgets_to_show[self.show_widget_index].show() def cycle_left(self, axis): last_index = self.show_widget_index self.show_widget_index -= 1 if self.show_widget_index < 0: self.show_widget_index = len(self.widgets_to_show) - 1 self.widgets_to_show[last_index].hide() self.widgets_to_show[self.show_widget_index].show() def start_script(self): self.widgets_to_show = [self.console_output, self.speed_widget] flags = ['-u', self.script] self.speed_widget.start(port=4021) if self.imu_box.isChecked(): print('starting imu socket') self.imu_widget.start(port=9009) self.widgets_to_show.append(self.imu_widget) flags.extend(['--enable-imu']) if self.lidar_box.isChecked(): print('starting lidar socket') self.lidar_widget.start(port=9010) self.widgets_to_show.append(self.lidar_widget) flags.extend(['--enable-lidar']) if self.camera_box.isChecked(): print('starting camera socket') self.camera_widget.start(port=9011) self.widgets_to_show.append(self.camera_widget) flags.extend(['--enable-camera']) self.process.start('python3', flags) def stop_script(self): self.imu_widget.shutdown() self.camera_widget.shutdown() self.lidar_widget.shutdown() self.speed_widget.shutdown() self.process.terminate() def fwd_output(self, text): self.console_output.appendPlainText(text) cursor = self.console_output.textCursor() cursor.movePosition(cursor.End) def stdoutReady(self): text = str(self.process.readAllStandardOutput(), encoding='utf8') self.fwd_output(text) def stderrReady(self): text = str(self.process.readAllStandardError(), encoding='utf8') self.fwd_output(text) def filter_out_arrow_release_keys(self, widget, event): if event.key() == Qt.Key_Up: self.console_output.verticalScrollBar().triggerAction( QAbstractSlider.SliderSingleStepSub) elif event.key() == Qt.Key_Down: self.console_output.verticalScrollBar().triggerAction( QAbstractSlider.SliderSingleStepAdd) else: type(widget).keyReleaseEvent(widget, event) def filter_out_arrow_press_keys(self, widget, event): if event.key() == Qt.Key_Up: self.console_output.verticalScrollBar().triggerAction( QAbstractSlider.SliderSingleStepSub) elif event.key() == Qt.Key_Down: self.console_output.verticalScrollBar().triggerAction( QAbstractSlider.SliderSingleStepAdd) else: type(widget).keyPressEvent(widget, event)
class FtcGuiApplication(TouchApplication): def __init__(self, args): TouchApplication.__init__(self, args) self.script_directory = '/home/isys/git/JetsonEV-scripts' # create the empty main window self.w = TouchWindow("Run Python Script") self.relative_path = os.path.dirname(os.path.realpath(__file__)) self.grid = QGridLayout() environment = QProcessEnvironment() environment.insert('PYTHONPATH', self.script_directory) self.process = QProcess() self.process.setProcessEnvironment(environment) self.process.readyReadStandardOutput.connect(self.stdoutReady) self.process.readyReadStandardError.connect(self.stderrReady) self.play_btn = ShadowButton(os.path.join(self.relative_path, 'start')) self.play_btn.setText("Start") self.play_btn.clicked.connect(self.start_script) self.grid.addWidget(self.play_btn, 0, 0, 1, 1) self.script_selector = QComboBox() self.scan_scripts() self.grid.addWidget(self.script_selector, 0, 1, 1, 3) self.grid.setColumnStretch(1, 1.5) self.grid.setAlignment(Qt.AlignCenter) self.stop_btn = ShadowButton(os.path.join(self.relative_path, 'stop')) self.stop_btn.setText("Stop") self.stop_btn.clicked.connect(self.stop_script) self.grid.addWidget(self.stop_btn, 0, 4, 1, 1) self.grid.setRowStretch(1, 4) self.console_output = QPlainTextEdit() self.console_output.setReadOnly(True) console_style = "QPlainTextEdit {" \ "background-color: black;" \ "color: white;" \ "}" self.console_output.setFocusPolicy(Qt.NoFocus) self.console_output.setFrameStyle(3) self.console_output.setStyleSheet(console_style) self.grid.addWidget(self.console_output, 1, 0, 1, 5) self.w.centralWidget.setLayout(self.grid) self.w.centralWidget.keyReleaseEvent = lambda event: self.filter_out_arrow_release_keys( self.w.centralWidget, event) self.w.centralWidget.keyPressEvent = lambda event: self.filter_out_arrow_press_keys( self.w.centralWidget, event) self.w.keyPressEvent = lambda event: self.filter_out_arrow_press_keys( self.w, event) self.w.keyReleaseEvent = lambda event: self.filter_out_arrow_release_keys( self.w, event) self.play_btn.keyReleaseEvent = lambda event: self.filter_out_arrow_release_keys( self.play_btn, event) self.play_btn.keyPressEvent = lambda event: self.filter_out_arrow_press_keys( self.play_btn, event) self.stop_btn.keyReleaseEvent = lambda event: self.filter_out_arrow_release_keys( self.stop_btn, event) self.stop_btn.keyPressEvent = lambda event: self.filter_out_arrow_press_keys( self.stop_btn, event) self.w.show() self.exec_() def scan_scripts(self): self.script_selector.clear() for script in os.listdir(self.script_directory): if os.path.isfile(os.path.join(self.script_directory, script)): if script[-3:] == '.py': self.script_selector.addItem(script[:-3]) def start_script(self): flags = [ '-u', os.path.join(self.script_directory, self.script_selector.currentText() + '.py') ] self.process.start('python3', flags) def stop_script(self): self.process.terminate() def fwd_output(self, text): self.console_output.appendPlainText(text) cursor = self.console_output.textCursor() cursor.movePosition(cursor.End) def stdoutReady(self): text = str(self.process.readAllStandardOutput(), encoding='utf8') self.fwd_output(text) def stderrReady(self): text = str(self.process.readAllStandardError(), encoding='utf8') self.fwd_output(text) def filter_out_arrow_release_keys(self, widget, event): if event.key() == Qt.Key_Up: self.console_output.verticalScrollBar().triggerAction( QAbstractSlider.SliderSingleStepSub) elif event.key() == Qt.Key_Down: self.console_output.verticalScrollBar().triggerAction( QAbstractSlider.SliderSingleStepAdd) else: type(widget).keyReleaseEvent(widget, event) def filter_out_arrow_press_keys(self, widget, event): if event.key() == Qt.Key_Up: self.console_output.verticalScrollBar().triggerAction( QAbstractSlider.SliderSingleStepSub) elif event.key() == Qt.Key_Down: self.console_output.verticalScrollBar().triggerAction( QAbstractSlider.SliderSingleStepAdd) else: type(widget).keyPressEvent(widget, event)