def __init__(self, plugin): QWidget.__init__(self) self.plugin = plugin self.l = l = QGridLayout() self.setLayout(l) self.gb = QGroupBox(_('Downloaded metadata fields'), self) if plugin.config_help_message: self.pchm = QLabel(plugin.config_help_message) self.pchm.setWordWrap(True) self.pchm.setOpenExternalLinks(True) l.addWidget(self.pchm, 0, 0, 1, 2) l.addWidget(self.gb, l.rowCount(), 0, 1, 2) self.gb.l = QGridLayout() self.gb.setLayout(self.gb.l) self.fields_view = v = QListView(self) self.gb.l.addWidget(v, 0, 0) v.setFlow(v.LeftToRight) v.setWrapping(True) v.setResizeMode(v.Adjust) self.fields_model = FieldsModel(self.plugin) self.fields_model.initialize() v.setModel(self.fields_model) self.memory = [] self.widgets = [] for opt in plugin.options: self.create_widgets(opt)
def settings_dialog(self): get_label = lambda: self.wallet.get_client().features.label update_label = lambda: current_label_label.setText("Label: %s" % get_label()) d = QDialog() layout = QGridLayout(d) layout.addWidget(QLabel("Trezor Options"), 0, 0) layout.addWidget(QLabel("ID:"), 1, 0) layout.addWidget( QLabel(" %s" % self.wallet.get_client().get_device_id()), 1, 1) def modify_label(): response = QInputDialog().getText( None, "Set New Trezor Label", "New Trezor Label: (upon submission confirm on Trezor)") if not response[1]: return new_label = str(response[0]) twd.start("Please confirm label change on Trezor") status = self.wallet.get_client().apply_settings(label=new_label) twd.stop() update_label() current_label_label = QLabel() update_label() change_label_button = QPushButton("Modify") change_label_button.clicked.connect(modify_label) layout.addWidget(current_label_label, 3, 0) layout.addWidget(change_label_button, 3, 1) if d.exec_(): return True else: return False
def settings_dialog(self): try: device_id = self.get_client().get_device_id() except BaseException as e: self.window.show_message(str(e)) return get_label = lambda: self.get_client().features.label update_label = lambda: current_label_label.setText("Label: %s" % get_label()) d = QDialog() layout = QGridLayout(d) layout.addWidget(QLabel("KeepKey Options"), 0, 0) layout.addWidget(QLabel("ID:"), 1, 0) layout.addWidget(QLabel(" %s" % device_id), 1, 1) def modify_label(): response = QInputDialog().getText( None, "Set New KeepKey Label", "New KeepKey Label: (upon submission confirm on KeepKey)") if not response[1]: return new_label = str(response[0]) self.handler.show_message("Please confirm label change on KeepKey") status = self.get_client().apply_settings(label=new_label) self.handler.stop() update_label() current_label_label = QLabel() update_label() change_label_button = QPushButton("Modify") change_label_button.clicked.connect(modify_label) layout.addWidget(current_label_label, 3, 0) layout.addWidget(change_label_button, 3, 1) d.exec_()
class ConfigWidget(QWidget): 'Configuration widget' def __init__(self): QWidget.__init__(self) self.layout = QGridLayout() self.layout.setSpacing(10) self.setLayout(self.layout) self.key_label = QLabel('&api key:') self.key_msg = QLineEdit(self) self.key_msg.setText(PREFS['api_key']) self.layout.addWidget(self.key_label, 1, 0) self.layout.addWidget(self.key_msg, 1, 1) self.key_label.setBuddy(self.key_msg) self.threads_label = QLabel('&worker_threads:') self.threads_msg = QLineEdit(self) self.threads_msg.setText(unicode(PREFS['worker_threads'])) self.layout.addWidget(self.threads_label, 2, 0) self.layout.addWidget(self.threads_msg, 2, 1) self.threads_label.setBuddy(self.threads_msg) def save_settings(self): 'Apply new settings value' PREFS['api_key'] = unicode(self.key_msg.text()) PREFS['worker_threads'] = int(self.threads_msg.text()) pycomicvine.api_key = PREFS['api_key']
class Footer(QWidget): def __init__(self): QWidget.__init__(self) self.__InitUi() def __InitUi(self): self.setFixedHeight(160) SetWidgetBackgroundColor(COLOR_WIDGET_2, self) self.__Layout = QGridLayout() self.setLayout(self.__Layout) self.__Layout.setContentsMargins(30,30,30,30) self.__Layout.setHorizontalSpacing(30) self.__Layout.setVerticalSpacing(30) self.__lblProcess = LabelSmalSize("", COLOR_FONT_4, True) self.__Layout.addWidget(self.__lblProcess) self.__pgbProgress = Progressbar() self.__Layout.addWidget(self.__pgbProgress) def ProcessStartet(self, strProcess): self.__lblProcess.setText(strProcess) self.__pgbProgress.setMaximum(0) def ProcessEnded(self): self.__lblProcess.setText("") self.__pgbProgress.setMaximum(100)
def __init__(self, show_strength=True, parent=None): super(PinMatrixWidget, self).__init__(parent) self.password = QLineEdit() self.password.setValidator(QRegExpValidator(QRegExp('[1-9]+'), None)) self.password.setEchoMode(QLineEdit.Password) QObject.connect(self.password, SIGNAL('textChanged(QString)'), self._password_changed) self.strength = QLabel() self.strength.setMinimumWidth(75) self.strength.setAlignment(Qt.AlignCenter) self._set_strength(0) grid = QGridLayout() grid.setSpacing(0) for y in range(3)[::-1]: for x in range(3): button = PinButton(self.password, x + y * 3 + 1) button.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) button.setFocusPolicy(Qt.NoFocus) grid.addWidget(button, 3 - y, x) hbox = QHBoxLayout() hbox.addWidget(self.password) if show_strength: hbox.addWidget(self.strength) vbox = QVBoxLayout() vbox.addLayout(grid) vbox.addLayout(hbox) self.setLayout(vbox)
def __init__(self): QWidget.__init__(self) self.l = QGridLayout() self.setLayout(self.l) self.newFormatCheckboxLabel = QLabel('Generate new format data (SQLite3)') self.l.addWidget(self.newFormatCheckboxLabel, 0, 0, 1, 1) self.newFormatCheckbox = QCheckBox(self) self.l.addWidget(self.newFormatCheckbox, 0, 1, 1, 1) self.newFormatCheckbox.setChecked(prefs['newFormat']) # ARTTBD Maybe should be a native directory picker? Works for now.. self.cacheDirLabel = QLabel("Caching directory (optional, useful if re-running for a given book)") self.l.addWidget(self.cacheDirLabel, 1, 0, 1, 1) self.cacheDirEdit = QLineEdit(self) self.l.addWidget(self.cacheDirEdit, 1, 1, 1, 1) self.cacheDirEdit.setText(prefs['cacheDir']) self.autoExpandAliasesLabel = QLabel('Auto-generate aliases from character names') self.l.addWidget(self.autoExpandAliasesLabel, 2, 0, 1, 1) self.autoExpandAliasesCheckbox = QCheckBox(self) self.l.addWidget(self.autoExpandAliasesCheckbox, 2, 1, 1, 1) self.autoExpandAliasesCheckbox.setChecked(prefs['autoExpandAliases']) self.logfileLabel = QLabel('Log file (optional)') self.l.addWidget(self.logfileLabel, 3, 0, 1, 1) self.logfileEdit = QLineEdit(self) self.l.addWidget(self.logfileEdit, 3, 1, 1, 1) self.logfileEdit.setText(prefs['logfile'])
def __init__(self, parent, graphs): super(FormWidget, self).__init__(parent) self.layout = QGridLayout(self) dim = np.ceil(np.sqrt(len(graphs))) grid = np.arange(dim * np.ceil(len(graphs) / dim)).reshape(-1, dim) for k in range(len(graphs)): i, j = np.where(grid == k) self.layout.addWidget(graphs[k], i, j)
def settings_dialog(self): try: device_id = self.get_client().get_device_id() except BaseException as e: self.window.show_message(str(e)) return get_label = lambda: self.get_client().features.label update_label = lambda: current_label_label.setText("Label: %s" % get_label()) d = QDialog() layout = QGridLayout(d) layout.addWidget(QLabel("Trezor Options"), 0, 0) layout.addWidget(QLabel("ID:"), 1, 0) layout.addWidget(QLabel(" %s" % device_id), 1, 1) def modify_label(): response = QInputDialog().getText( None, "Set New Trezor Label", "New Trezor Label: (upon submission confirm on Trezor)" ) if not response[1]: return new_label = str(response[0]) self.handler.show_message("Please confirm label change on Trezor") status = self.get_client().apply_settings(label=new_label) self.handler.stop() update_label() current_label_label = QLabel() update_label() change_label_button = QPushButton("Modify") change_label_button.clicked.connect(modify_label) layout.addWidget(current_label_label, 3, 0) layout.addWidget(change_label_button, 3, 1) d.exec_()
def settings_dialog(self): get_label = lambda: self.wallet.get_client().features.label update_label = lambda: current_label_label.setText("Label: %s" % get_label()) d = QDialog() layout = QGridLayout(d) layout.addWidget(QLabel("Trezor Options"),0,0) layout.addWidget(QLabel("ID:"),1,0) layout.addWidget(QLabel(" %s" % self.wallet.get_client().get_device_id()),1,1) def modify_label(): response = QInputDialog().getText(None, "Set New Trezor Label", "New Trezor Label: (upon submission confirm on Trezor)") if not response[1]: return new_label = str(response[0]) twd.start("Please confirm label change on Trezor") status = self.wallet.get_client().apply_settings(label=new_label) twd.stop() update_label() current_label_label = QLabel() update_label() change_label_button = QPushButton("Modify") change_label_button.clicked.connect(modify_label) layout.addWidget(current_label_label,3,0) layout.addWidget(change_label_button,3,1) if d.exec_(): return True else: return False
def __init__(self, parent, db, author, series=None): QDialog.__init__(self, parent) self.db = db self.setWindowTitle(_('How many empty books?')) self._layout = QGridLayout(self) self.setLayout(self._layout) self.qty_label = QLabel(_('How many empty books should be added?')) self._layout.addWidget(self.qty_label, 0, 0, 1, 2) self.qty_spinbox = QSpinBox(self) self.qty_spinbox.setRange(1, 10000) self.qty_spinbox.setValue(1) self._layout.addWidget(self.qty_spinbox, 1, 0, 1, 2) self.author_label = QLabel(_('Set the author of the new books to:')) self._layout.addWidget(self.author_label, 2, 0, 1, 2) self.authors_combo = EditWithComplete(self) self.authors_combo.setSizeAdjustPolicy( self.authors_combo.AdjustToMinimumContentsLengthWithIcon) self.authors_combo.setEditable(True) self._layout.addWidget(self.authors_combo, 3, 0, 1, 1) self.initialize_authors(db, author) self.clear_button = QToolButton(self) self.clear_button.setIcon(QIcon(I('trash.png'))) self.clear_button.setToolTip(_('Reset author to Unknown')) self.clear_button.clicked.connect(self.reset_author) self._layout.addWidget(self.clear_button, 3, 1, 1, 1) self.series_label = QLabel(_('Set the series of the new books to:')) self._layout.addWidget(self.series_label, 4, 0, 1, 2) self.series_combo = EditWithComplete(self) self.authors_combo.setSizeAdjustPolicy( self.authors_combo.AdjustToMinimumContentsLengthWithIcon) self.series_combo.setEditable(True) self._layout.addWidget(self.series_combo, 5, 0, 1, 1) self.initialize_series(db, series) self.sclear_button = QToolButton(self) self.sclear_button.setIcon(QIcon(I('trash.png'))) self.sclear_button.setToolTip(_('Reset series')) self.sclear_button.clicked.connect(self.reset_series) self._layout.addWidget(self.sclear_button, 5, 1, 1, 1) button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) button_box.accepted.connect(self.accept) button_box.rejected.connect(self.reject) self._layout.addWidget(button_box) self.resize(self.sizeHint())
def setup_store_checks(self): first_run = self.config.get('first_run', True) # Add check boxes for each store so the user # can disable searching specific stores on a # per search basis. existing = {} for n in self.store_checks: existing[n] = self.store_checks[n].isChecked() self.store_checks = {} stores_check_widget = QWidget() store_list_layout = QGridLayout() stores_check_widget.setLayout(store_list_layout) icon = QIcon(I('donate.png')) for i, x in enumerate( sorted(self.gui.istores.keys(), key=lambda x: x.lower())): cbox = QCheckBox(x) cbox.setChecked(existing.get(x, first_run)) store_list_layout.addWidget(cbox, i, 0, 1, 1) if self.gui.istores[x].base_plugin.affiliate: iw = QLabel(self) iw.setToolTip('<p>' + _( 'Buying from this store supports the calibre developer: %s</p>' ) % self.gui.istores[x].base_plugin.author + '</p>') iw.setPixmap(icon.pixmap(16, 16)) store_list_layout.addWidget(iw, i, 1, 1, 1) self.store_checks[x] = cbox store_list_layout.setRowStretch(store_list_layout.rowCount(), 10) self.store_list.setWidget(stores_check_widget) self.config['first_run'] = False
def makeControlWidgets(self, parent): """Creates control widgets for the colormap's internal parameters. "parent" is a parent widget. Returns None if no controls are required""" top = QWidget(parent) layout = QGridLayout(top) layout.setContentsMargins(0, 0, 0, 0) for irow, icol, control in ((0, 0, self.gamma), (0, 1, self.color), (1, 0, self.cycles), (1, 1, self.hue)): control.makeControlWidgets(top, layout, irow, icol) QObject.connect(control, SIGNAL("valueChanged"), self.emitChange) QObject.connect(control, SIGNAL("valueMoved"), self.emitPreview) return top
def __init__(self, parent=None): QWidget.__init__(self, parent) self.l = l = QGridLayout(self) self.setLayout(l) self.l1 = l1 = QLabel('<p>'+_( 'You can control the color of columns in the' ' book list by creating "rules" that tell calibre' ' what color to use. Click the Add Rule button below' ' to get started.<p>You can <b>change an existing rule</b> by double' ' clicking it.')) l1.setWordWrap(True) l.addWidget(l1, 0, 0, 1, 2) self.add_button = QPushButton(QIcon(I('plus.png')), _('Add Rule'), self) self.remove_button = QPushButton(QIcon(I('minus.png')), _('Remove Rule'), self) self.add_button.clicked.connect(self.add_rule) self.remove_button.clicked.connect(self.remove_rule) l.addWidget(self.add_button, 1, 0) l.addWidget(self.remove_button, 1, 1) self.g = g = QGridLayout() self.rules_view = QListView(self) self.rules_view.doubleClicked.connect(self.edit_rule) self.rules_view.setSelectionMode(self.rules_view.SingleSelection) self.rules_view.setAlternatingRowColors(True) self.rtfd = RichTextDelegate(parent=self.rules_view, max_width=400) self.rules_view.setItemDelegate(self.rtfd) g.addWidget(self.rules_view, 0, 0, 2, 1) self.up_button = b = QToolButton(self) b.setIcon(QIcon(I('arrow-up.png'))) b.setToolTip(_('Move the selected rule up')) b.clicked.connect(self.move_up) g.addWidget(b, 0, 1, 1, 1, Qt.AlignTop) self.down_button = b = QToolButton(self) b.setIcon(QIcon(I('arrow-down.png'))) b.setToolTip(_('Move the selected rule down')) b.clicked.connect(self.move_down) g.addWidget(b, 1, 1, 1, 1, Qt.AlignBottom) l.addLayout(g, 2, 0, 1, 2) l.setRowStretch(2, 10) self.add_advanced_button = b = QPushButton(QIcon(I('plus.png')), _('Add Advanced Rule'), self) b.clicked.connect(self.add_advanced) l.addWidget(b, 3, 0, 1, 2)
def setup_store_checks(self): first_run = self.config.get('first_run', True) # Add check boxes for each store so the user # can disable searching specific stores on a # per search basis. existing = {} for n in self.store_checks: existing[n] = self.store_checks[n].isChecked() self.store_checks = {} stores_check_widget = QWidget() store_list_layout = QGridLayout() stores_check_widget.setLayout(store_list_layout) icon = QIcon(I('donate.png')) for i, x in enumerate(sorted(self.gui.istores.keys(), key=lambda x: x.lower())): cbox = QCheckBox(x) cbox.setChecked(existing.get(x, first_run)) store_list_layout.addWidget(cbox, i, 0, 1, 1) if self.gui.istores[x].base_plugin.affiliate: iw = QLabel(self) iw.setToolTip('<p>' + _('Buying from this store supports the calibre developer: %s</p>') % self.gui.istores[x].base_plugin.author + '</p>') iw.setPixmap(icon.pixmap(16, 16)) store_list_layout.addWidget(iw, i, 1, 1, 1) self.store_checks[x] = cbox store_list_layout.setRowStretch(store_list_layout.rowCount(), 10) self.store_list.setWidget(stores_check_widget) self.config['first_run'] = False
def __init__(self, movie): self.movie = movie QDialog.__init__(self, None) self.setObjectName("movie_warning") self.text_browser = QTextBrowser(self) self.text_browser.setObjectName("movie_warning_textbrowser") self.text_browser.setMinimumSize(400, 40) self.setWindowTitle('Rewind your movie?') self.text_browser.setPlainText( #bruce 080827 revised text "You may want to rewind the movie now. The atoms move as the movie " "progresses, and saving the part without rewinding will save the " "current positions, which is sometimes useful, but will make the " "movie invalid, because .dpb files only store deltas relative to " "the initial atom positions, and don't store the initial positions " "themselves.") self.ok_button = QPushButton(self) self.ok_button.setObjectName("ok_button") self.ok_button.setText("Rewind movie") self.cancel_button = QPushButton(self) self.cancel_button.setObjectName("cancel_button") self.cancel_button.setText( "Exit command without rewinding") #bruce 080827 revised text # Note: this is not, in fact, a cancel button -- # there is no option in the caller to prevent exiting the command. # There is also no option to "forward to final position", # though for a minimize movie, that might be most useful. # [bruce 080827 comment] layout = QGridLayout(self) layout.addWidget(self.text_browser, 0, 0, 0, 1) layout.addWidget(self.ok_button, 1, 0) layout.addWidget(self.cancel_button, 1, 1) self.connect(self.ok_button, SIGNAL("clicked()"), self.rewindMovie) self.connect(self.cancel_button, SIGNAL("clicked()"), self.noThanks)
def __init__(self, movie): self.movie = movie QDialog.__init__(self, None) self.setObjectName("movie_warning") self.text_browser = QTextBrowser(self) self.text_browser.setObjectName("movie_warning_textbrowser") self.text_browser.setMinimumSize(400, 40) self.setWindowTitle('Rewind your movie?') self.text_browser.setPlainText( "You may want to rewind the movie now. If you save the part without " + "rewinding the movie, the movie file will become invalid because it " + "depends upon the initial atom positions. The atoms move as the movie " + "progresses, and saving the part now will save the final positions, " + "which are incorrect for the movie you just watched.") self.ok_button = QPushButton(self) self.ok_button.setObjectName("ok_button") self.ok_button.setText("Rewind movie") self.cancel_button = QPushButton(self) self.cancel_button.setObjectName("cancel_button") self.cancel_button.setText("No thanks") layout = QGridLayout(self) layout.addWidget(self.text_browser, 0, 0, 0, 1) layout.addWidget(self.ok_button, 1, 0) layout.addWidget(self.cancel_button, 1, 1) self.connect(self.ok_button, SIGNAL("clicked()"), self.rewindMovie) self.connect(self.cancel_button, SIGNAL("clicked()"), self.noThanks)
class UpdateNotification(QDialog): def __init__(self, calibre_version, plugin_updates, parent=None): QDialog.__init__(self, parent) self.setAttribute(Qt.WA_QuitOnClose, False) self.resize(400, 250) self.l = QGridLayout() self.setLayout(self.l) self.logo = QLabel() self.logo.setMaximumWidth(110) self.logo.setPixmap(QPixmap(I('lt.png')).scaled(100, 100, Qt.IgnoreAspectRatio, Qt.SmoothTransformation)) ver = calibre_version if ver.endswith('.0'): ver = ver[:-2] self.label = QLabel(('<p>'+ _('New version <b>%(ver)s</b> of %(app)s is available for download. ' 'See the <a href="http://calibre-ebook.com/whats-new' '">new features</a>.'))%dict( app=__appname__, ver=ver)) self.label.setOpenExternalLinks(True) self.label.setWordWrap(True) self.setWindowTitle(_('Update available!')) self.setWindowIcon(QIcon(I('lt.png'))) self.l.addWidget(self.logo, 0, 0) self.l.addWidget(self.label, 0, 1) self.cb = QCheckBox( _('Show this notification for future updates'), self) self.l.addWidget(self.cb, 1, 0, 1, -1) self.cb.setChecked(config.get('new_version_notification')) self.cb.stateChanged.connect(self.show_future) self.bb = QDialogButtonBox(self) b = self.bb.addButton(_('&Get update'), self.bb.AcceptRole) b.setDefault(True) b.setIcon(QIcon(I('arrow-down.png'))) if plugin_updates > 0: b = self.bb.addButton(_('Update &plugins'), self.bb.ActionRole) b.setIcon(QIcon(I('plugins/plugin_updater.png'))) b.clicked.connect(self.get_plugins, type=Qt.QueuedConnection) self.bb.addButton(self.bb.Cancel) self.l.addWidget(self.bb, 2, 0, 1, -1) self.bb.accepted.connect(self.accept) self.bb.rejected.connect(self.reject) dynamic.set('update to version %s'%calibre_version, False) def get_plugins(self): from calibre.gui2.dialogs.plugin_updater import (PluginUpdaterDialog, FILTER_UPDATE_AVAILABLE) d = PluginUpdaterDialog(self.parent(), initial_filter=FILTER_UPDATE_AVAILABLE) d.exec_() def show_future(self, *args): config.set('new_version_notification', bool(self.cb.isChecked())) def accept(self): open_url(QUrl(get_download_url())) QDialog.accept(self)
class UpdateNotification(QDialog): def __init__(self, calibre_version, plugin_updates, parent=None): QDialog.__init__(self, parent) self.setAttribute(Qt.WA_QuitOnClose, False) self.resize(400, 250) self.l = QGridLayout() self.setLayout(self.l) self.logo = QLabel() self.logo.setMaximumWidth(110) self.logo.setPixmap( QPixmap(I('lt.png')).scaled(100, 100, Qt.IgnoreAspectRatio, Qt.SmoothTransformation)) ver = calibre_version if ver.endswith('.0'): ver = ver[:-2] self.label = QLabel(('<p>' + _( 'New version <b>%(ver)s</b> of %(app)s is available for download. ' 'See the <a href="http://calibre-ebook.com/whats-new' '">new features</a>.')) % dict(app=__appname__, ver=ver)) self.label.setOpenExternalLinks(True) self.label.setWordWrap(True) self.setWindowTitle(_('Update available!')) self.setWindowIcon(QIcon(I('lt.png'))) self.l.addWidget(self.logo, 0, 0) self.l.addWidget(self.label, 0, 1) self.cb = QCheckBox(_('Show this notification for future updates'), self) self.l.addWidget(self.cb, 1, 0, 1, -1) self.cb.setChecked(config.get('new_version_notification')) self.cb.stateChanged.connect(self.show_future) self.bb = QDialogButtonBox(self) b = self.bb.addButton(_('&Get update'), self.bb.AcceptRole) b.setDefault(True) b.setIcon(QIcon(I('arrow-down.png'))) if plugin_updates > 0: b = self.bb.addButton(_('Update &plugins'), self.bb.ActionRole) b.setIcon(QIcon(I('plugins/plugin_updater.png'))) b.clicked.connect(self.get_plugins, type=Qt.QueuedConnection) self.bb.addButton(self.bb.Cancel) self.l.addWidget(self.bb, 2, 0, 1, -1) self.bb.accepted.connect(self.accept) self.bb.rejected.connect(self.reject) dynamic.set('update to version %s' % calibre_version, False) def get_plugins(self): from calibre.gui2.dialogs.plugin_updater import ( PluginUpdaterDialog, FILTER_UPDATE_AVAILABLE) d = PluginUpdaterDialog(self.parent(), initial_filter=FILTER_UPDATE_AVAILABLE) d.exec_() def show_future(self, *args): config.set('new_version_notification', bool(self.cb.isChecked())) def accept(self): open_url(QUrl(get_download_url())) QDialog.accept(self)
def __init__(self): QWidget.__init__(self, ctx.mainScreen) self.setObjectName("InformationWindow") self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.setFixedHeight(50) self.setMaximumWidth(800) self.setStyleSheet(""" QFrame#frame { border: 1px solid rgba(255,255,255,30); /*border-radius: 4px;*/ background-color: rgba(0,0,0,100);} QLabel { border:none; color:#FFFFFF;} QProgressBar { border: 1px solid white;} QProgressBar::chunk { background-color: #F1610D; width: 0.5px;} """) self.gridlayout = QGridLayout(self) self.frame = QFrame(self) self.frame.setObjectName("frame") self.horizontalLayout = QHBoxLayout(self.frame) self.horizontalLayout.setContentsMargins(10, 0, 10, 0) # Spinner self.spinner = QLabel(self.frame) self.spinner.setMinimumSize(QSize(16, 16)) self.spinner.setMaximumSize(QSize(16, 16)) self.spinner.setIndent(6) self.movie = QMovie(':/images/working.mng') self.spinner.setMovie(self.movie) self.movie.start() self.horizontalLayout.addWidget(self.spinner) # Message self.label = QLabel(self.frame) self.label.setAlignment(Qt.AlignCenter) self.label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.icon = QLabel(self.frame) self.icon.setFixedWidth(16) self.icon.setFixedHeight(16) self.horizontalLayout.setSpacing(10) self.horizontalLayout.addWidget(self.icon) self.horizontalLayout.addWidget(self.label) self.gridlayout.addWidget(self.frame, 0, 0, 1, 1)
def __init__(self): QWidget.__init__(self) self.l = QGridLayout() self.setLayout(self.l) self.newFormatCheckboxLabel = QLabel("Generate new format data (SQLite3)") self.l.addWidget(self.newFormatCheckboxLabel, 0, 0, 1, 1) self.newFormatCheckbox = QCheckBox(self) self.l.addWidget(self.newFormatCheckbox, 0, 1, 1, 1) self.newFormatCheckbox.setChecked(prefs["newFormat"]) # ARTTBD Maybe should be a native directory picker? Works for now.. self.cacheDirLabel = QLabel("Caching directory (optional, useful if re-running for a given book)") self.l.addWidget(self.cacheDirLabel, 1, 0, 1, 1) self.cacheDirEdit = QLineEdit(self) self.l.addWidget(self.cacheDirEdit, 1, 1, 1, 1) self.cacheDirEdit.setText(prefs["cacheDir"]) self.autoExpandAliasesLabel = QLabel("Auto-generate aliases from character names") self.l.addWidget(self.autoExpandAliasesLabel, 2, 0, 1, 1) self.autoExpandAliasesCheckbox = QCheckBox(self) self.l.addWidget(self.autoExpandAliasesCheckbox, 2, 1, 1, 1) self.autoExpandAliasesCheckbox.setChecked(prefs["autoExpandAliases"]) self.logfileLabel = QLabel("Log file (optional)") self.l.addWidget(self.logfileLabel, 3, 0, 1, 1) self.logfileEdit = QLineEdit(self) self.l.addWidget(self.logfileEdit, 3, 1, 1, 1) self.logfileEdit.setText(prefs["logfile"])
def __init__(self, model, parent=None): QWidget.__init__(self, parent) self.l = l = QGridLayout(self) self.setLayout(l) self.setContentsMargins(0, 0, 0, 0) self.view = v = QListView(self) self.d = SpacedDelegate(v) v.doubleClicked.connect(self.double_clicked) v.setItemDelegate(self.d) v.setModel(model) l.addWidget(v, 0, 0, 1, -1) model.dataChanged.connect(self.data_changed) self.rb = b = QPushButton(QIcon(I('edit-undo.png')), _('&Revert to'), self) b.setToolTip(_('Revert the book to the selected checkpoint')) b.clicked.connect(self.revert_clicked) l.addWidget(b, 1, 1) self.cb = b = QPushButton(QIcon(I('diff.png')), _('&Compare'), self) b.setToolTip( _('Compare the state of the book at the selected checkpoint with the current state' )) b.clicked.connect(self.compare_clicked) l.addWidget(b, 1, 0)
def __init__(self, parent): QDialog.__init__(self, parent) self.gui = parent self.setAttribute(Qt.WA_DeleteOnClose, False) self.setWindowIcon(QIcon(I('polish.png'))) self.reports = [] self.l = l = QGridLayout() self.setLayout(l) self.view = v = QTextEdit(self) v.setReadOnly(True) l.addWidget(self.view, 0, 0, 1, 2) self.backup_msg = la = QLabel('') l.addWidget(la, 1, 0, 1, 2) la.setVisible(False) la.setWordWrap(True) self.ign_msg = _('Ignore remaining %d reports') self.ign = QCheckBox(self.ign_msg, self) l.addWidget(self.ign, 2, 0) bb = self.bb = QDialogButtonBox(QDialogButtonBox.Close) bb.accepted.connect(self.accept) bb.rejected.connect(self.reject) b = self.log_button = bb.addButton(_('View full &log'), bb.ActionRole) b.clicked.connect(self.view_log) bb.button(bb.Close).setDefault(True) l.addWidget(bb, 2, 1) self.finished.connect(self.show_next, type=Qt.QueuedConnection) self.resize(QSize(800, 600))
def __init__(self, gui, initial_panel=None): QDialog.__init__(self, gui) self.l = l = QGridLayout(self) self.setLayout(l) self.setWindowTitle(_('Preferences for Edit Book')) self.setWindowIcon(QIcon(I('config.png'))) self.stacks = QStackedWidget(self) l.addWidget(self.stacks, 0, 1, 1, 1) self.categories_list = cl = QListWidget(self) cl.currentRowChanged.connect(self.stacks.setCurrentIndex) cl.clearPropertyFlags() cl.setViewMode(cl.IconMode) cl.setFlow(cl.TopToBottom) cl.setMovement(cl.Static) cl.setWrapping(False) cl.setSpacing(15) cl.setWordWrap(True) l.addWidget(cl, 0, 0, 1, 1) self.bb = bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) bb.accepted.connect(self.accept) bb.rejected.connect(self.reject) self.rdb = b = bb.addButton(_('Restore all defaults'), bb.ResetRole) b.setToolTip(_('Restore defaults for all preferences')) b.clicked.connect(self.restore_all_defaults) self.rcdb = b = bb.addButton(_('Restore current defaults'), bb.ResetRole) b.setToolTip(_('Restore defaults for currently displayed preferences')) b.clicked.connect(self.restore_current_defaults) l.addWidget(bb, 1, 0, 1, 2) self.resize(800, 600) geom = tprefs.get('preferences_geom', None) if geom is not None: self.restoreGeometry(geom) self.keyboard_panel = ShortcutConfig(self) self.keyboard_panel.initialize(gui.keyboard) self.editor_panel = EditorSettings(self) self.integration_panel = IntegrationSettings(self) for name, icon, panel in [ (_('Editor settings'), 'modified.png', 'editor'), (_('Keyboard shortcuts'), 'keyboard-prefs.png', 'keyboard'), (_('Integration with calibre'), 'lt.png', 'integration'), ]: i = QListWidgetItem(QIcon(I(icon)), name, cl) cl.addItem(i) self.stacks.addWidget(getattr(self, panel + '_panel')) cl.setCurrentRow(0) cl.item(0).setSelected(True) w, h = cl.sizeHintForColumn(0), 0 for i in xrange(cl.count()): h = max(h, cl.sizeHintForRow(i)) cl.item(i).setSizeHint(QSize(w, h)) cl.setMaximumWidth(cl.sizeHintForColumn(0) + 35) cl.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
class Widget(QWidget, ScreenWidget): name = "network" def __init__(self): QWidget.__init__(self) self.layout = QGridLayout(self) self.networkConnector = pds.container.PNetworkManager(self) self.layout.addWidget(self.networkConnector) def shown(self): self.networkConnector.startNetworkManager() def execute(self): self.networkConnector._proc.terminate() ctx.mainScreen.disableBack() return True
def __init__(self, parent=None): QWidget.__init__(self, parent) self._layout = l = QGridLayout() self.setLayout(self._layout) self.header = QLabel( _('Double click on any entry to change the' ' keyboard shortcuts associated with it')) l.addWidget(self.header, 0, 0, 1, 3) self.view = QTreeView(self) self.view.setAlternatingRowColors(True) self.view.setHeaderHidden(True) self.view.setAnimated(True) l.addWidget(self.view, 1, 0, 1, 3) self.delegate = Delegate() self.view.setItemDelegate(self.delegate) self.delegate.sizeHintChanged.connect(self.editor_opened, type=Qt.QueuedConnection) self.delegate.changed_signal.connect(self.changed_signal) self.search = SearchBox2(self) self.search.initialize('shortcuts_search_history', help_text=_('Search for a shortcut by name')) self.search.search.connect(self.find) l.addWidget(self.search, 2, 0, 1, 1) self.nb = QPushButton(QIcon(I('arrow-down.png')), _('&Next'), self) self.pb = QPushButton(QIcon(I('arrow-up.png')), _('&Previous'), self) self.nb.clicked.connect(self.find_next) self.pb.clicked.connect(self.find_previous) l.addWidget(self.nb, 2, 1, 1, 1) l.addWidget(self.pb, 2, 2, 1, 1) l.setColumnStretch(0, 100)
def __init__(self, pdfpath, parent=None): QDialog.__init__(self, parent) self.pdfpath = pdfpath self.l = l = QGridLayout() self.setLayout(l) self.la = la = QLabel( _('Choose a cover from the list of PDF pages below')) l.addWidget(la) self.loading = la = QLabel('<b>' + _('Rendering PDF pages, please wait...')) l.addWidget(la) self.covers = c = QListWidget(self) l.addWidget(c) c.setIconSize(QSize(120, 160)) c.setSelectionMode(c.SingleSelection) c.setViewMode(c.IconMode) c.setUniformItemSizes(True) c.setResizeMode(c.Adjust) c.itemDoubleClicked.connect(self.accept) self.bb = bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) bb.accepted.connect(self.accept) bb.rejected.connect(self.reject) l.addWidget(bb) self.rendering_done.connect(self.show_pages, type=Qt.QueuedConnection) self.tdir = PersistentTemporaryDirectory('_pdf_covers') self.thread = Thread(target=self.render) self.thread.daemon = True self.thread.start() self.setWindowTitle(_('Choose cover from PDF')) self.setWindowIcon(file_icon_provider().icon_from_ext('pdf')) self.resize(QSize(800, 600))
def __init__(self, parent=None): QWidget.__init__(self, parent) self.l = l = QGridLayout(self) self.setLayout(l) l.setContentsMargins(0, 0, 0, 0) self.view = QTreeWidget(self) self.delegate = Delegate(self.view) self.view.setItemDelegate(self.delegate) self.view.setHeaderHidden(True) self.view.setAnimated(True) self.view.setContextMenuPolicy(Qt.CustomContextMenu) self.view.customContextMenuRequested.connect(self.show_context_menu, type=Qt.QueuedConnection) self.view.itemActivated.connect(self.emit_navigate) self.view.itemPressed.connect(self.item_pressed) pi = plugins['progress_indicator'][0] if hasattr(pi, 'set_no_activate_on_click'): pi.set_no_activate_on_click(self.view) self.view.itemDoubleClicked.connect(self.emit_navigate) l.addWidget(self.view) self.refresh_action = QAction(QIcon(I('view-refresh.png')), _('&Refresh'), self) self.refresh_action.triggered.connect(self.refresh) self.refresh_timer = t = QTimer(self) t.setInterval(1000), t.setSingleShot(True) t.timeout.connect(self.auto_refresh) self.toc_name = None self.currently_editing = None
def __init__(self, parent=None): QWidget.__init__(self, parent) self.l = l = QGridLayout(self) self.setLayout(l) l.setContentsMargins(0, 0, 0, 0) self.is_visible = False self.view = QTreeWidget(self) self.delegate = Delegate(self.view) self.view.setItemDelegate(self.delegate) self.view.setHeaderHidden(True) self.view.setAnimated(True) self.view.setContextMenuPolicy(Qt.CustomContextMenu) self.view.customContextMenuRequested.connect(self.show_context_menu, type=Qt.QueuedConnection) self.view.itemActivated.connect(self.emit_navigate) self.view.itemPressed.connect(self.item_pressed) pi = plugins['progress_indicator'][0] if hasattr(pi, 'set_no_activate_on_click'): pi.set_no_activate_on_click(self.view) self.view.itemDoubleClicked.connect(self.emit_navigate) l.addWidget(self.view) self.refresh_action = QAction(QIcon(I('view-refresh.png')), _('&Refresh'), self) self.refresh_action.triggered.connect(self.build)
def setup_ui(self): self.l = l = QGridLayout() self.setLayout(l) self.la = la = QLabel( _('Arrange the files in this book into sub-folders based on their types.' ' If you leave a folder blank, the files will be placed in the root.' )) la.setWordWrap(True) l.addWidget(la, 0, 0, 1, -1) folders = tprefs['folders_for_types'] for i, (typ, text) in enumerate(self.TYPE_MAP): la = QLabel('&' + text) setattr(self, '%s_label' % typ, la) le = QLineEdit(self) setattr(self, '%s_folder' % typ, le) val = folders.get(typ, '') if val and not val.endswith('/'): val += '/' le.setText(val) la.setBuddy(le) l.addWidget(la, i + 1, 0) l.addWidget(le, i + 1, 1) self.la2 = la = QLabel( _('Note that this will only arrange files inside the book,' ' it will not affect how they are displayed in the Files Browser' )) la.setWordWrap(True) l.addWidget(la, i + 2, 0, 1, -1) l.addWidget(self.bb, i + 3, 0, 1, -1)
def __init__(self, all_formats, format_map): QWidget.__init__(self) self.l = l = QGridLayout() self.setLayout(l) self.f = f = QListWidget(self) l.addWidget(f, 0, 0, 3, 1) unchecked_formats = sorted(all_formats - set(format_map)) for fmt in format_map + unchecked_formats: item = QListWidgetItem(fmt, f) item.setData(Qt.UserRole, fmt) item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable | Qt.ItemIsSelectable) item.setCheckState(Qt.Checked if fmt in format_map else Qt.Unchecked) self.button_up = b = QToolButton(self) b.setIcon(QIcon(I('arrow-up.png'))) l.addWidget(b, 0, 1) b.clicked.connect(self.up) self.button_down = b = QToolButton(self) b.setIcon(QIcon(I('arrow-down.png'))) l.addWidget(b, 2, 1) b.clicked.connect(self.down)
def __init__(self, parent): super(ChooseLibrary, self).__init__(parent) d = self d.l = l = QGridLayout() d.setLayout(l) d.setWindowTitle(_('Choose library')) la = d.la = QLabel(_('Library &path:')) l.addWidget(la, 0, 0) le = d.le = HistoryLineEdit(d) le.initialize('choose_library_for_copy') l.addWidget(le, 0, 1) la.setBuddy(le) b = d.b = QToolButton(d) b.setIcon(QIcon(I('document_open.png'))) b.setToolTip(_('Browse for library')) b.clicked.connect(self.browse) l.addWidget(b, 0, 2) self.bb = bb = QDialogButtonBox(QDialogButtonBox.Cancel) bb.accepted.connect(self.accept) bb.rejected.connect(self.reject) self.delete_after_copy = False b = bb.addButton(_('&Copy'), bb.AcceptRole) b.setIcon(QIcon(I('edit-copy.png'))) b.setToolTip(_('Copy to the specified library')) b2 = bb.addButton(_('&Move'), bb.AcceptRole) b2.clicked.connect(lambda: setattr(self, 'delete_after_copy', True)) b2.setIcon(QIcon(I('edit-cut.png'))) b2.setToolTip(_('Copy to the specified library and delete from the current library')) b.setDefault(True) l.addWidget(bb, 1, 0, 1, 3) le.setMinimumWidth(350) self.resize(self.sizeHint())
def __init__(self, stats, location, parent=None): QDialog.__init__(self, parent) self.setWindowTitle(_('No library found')) self._l = l = QGridLayout(self) self.setLayout(l) self.stats, self.location = stats, location loc = self.oldloc = location.replace('/', os.sep) self.header = QLabel( _('No existing calibre library was found at %s. ' 'If the library was moved, select its new location below. ' 'Otherwise calibre will forget this library.') % loc) self.header.setWordWrap(True) ncols = 2 l.addWidget(self.header, 0, 0, 1, ncols) self.cl = QLabel('<br><b>' + _('New location of this library:')) l.addWidget(self.cl, 1, 0, 1, ncols) self.loc = QLineEdit(loc, self) l.addWidget(self.loc, 2, 0, 1, 1) self.cd = QToolButton(self) self.cd.setIcon(QIcon(I('document_open.png'))) self.cd.clicked.connect(self.choose_dir) l.addWidget(self.cd, 2, 1, 1, 1) self.bb = QDialogButtonBox(QDialogButtonBox.Abort) b = self.bb.addButton(_('Library moved'), self.bb.AcceptRole) b.setIcon(QIcon(I('ok.png'))) b = self.bb.addButton(_('Forget library'), self.bb.RejectRole) b.setIcon(QIcon(I('edit-clear.png'))) b.clicked.connect(self.forget_library) self.bb.accepted.connect(self.accept) self.bb.rejected.connect(self.reject) l.addWidget(self.bb, 3, 0, 1, ncols) self.resize(self.sizeHint() + QSize(100, 50))
def __init__(self, parent=None): QWidget.__init__(self, parent) self.l = l = QGridLayout(self) self.setLayout(l) self.l1 = l1 = QLabel('') l1.setWordWrap(True) l.addWidget(l1, 0, 0, 1, 2) self.add_button = QPushButton(QIcon(I('plus.png')), _('Add Rule'), self) self.remove_button = QPushButton(QIcon(I('minus.png')), _('Remove Rule'), self) self.add_button.clicked.connect(self.add_rule) self.remove_button.clicked.connect(self.remove_rule) l.addWidget(self.add_button, 1, 0) l.addWidget(self.remove_button, 1, 1) self.g = g = QGridLayout() self.rules_view = QListView(self) self.rules_view.doubleClicked.connect(self.edit_rule) self.rules_view.setSelectionMode(self.rules_view.SingleSelection) self.rules_view.setAlternatingRowColors(True) self.rtfd = RichTextDelegate(parent=self.rules_view, max_width=400) self.rules_view.setItemDelegate(self.rtfd) g.addWidget(self.rules_view, 0, 0, 2, 1) self.up_button = b = QToolButton(self) b.setIcon(QIcon(I('arrow-up.png'))) b.setToolTip(_('Move the selected rule up')) b.clicked.connect(self.move_up) g.addWidget(b, 0, 1, 1, 1, Qt.AlignTop) self.down_button = b = QToolButton(self) b.setIcon(QIcon(I('arrow-down.png'))) b.setToolTip(_('Move the selected rule down')) b.clicked.connect(self.move_down) g.addWidget(b, 1, 1, 1, 1, Qt.AlignBottom) l.addLayout(g, 2, 0, 1, 2) l.setRowStretch(2, 10) self.add_advanced_button = b = QPushButton(QIcon(I('plus.png')), _('Add Advanced Rule'), self) b.clicked.connect(self.add_advanced) l.addWidget(b, 3, 0, 1, 2)
def __init__(self, img_data, parent=None): QDialog.__init__(self, parent) self.l = l = QGridLayout(self) self.setLayout(l) self.setWindowTitle(_('Trim Image')) self.bar = b = QToolBar(self) l.addWidget(b) b.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) b.setIconSize(QSize(32, 32)) self.msg = la = QLabel('\xa0' + _( 'Select a region by dragging with your mouse on the image, and then click trim' )) self.sz = QLabel('') self.canvas = c = Canvas(self) c.image_changed.connect(self.image_changed) c.load_image(img_data) self.undo_action = u = c.undo_action u.setShortcut(QKeySequence(QKeySequence.Undo)) self.redo_action = r = c.redo_action r.setShortcut(QKeySequence(QKeySequence.Redo)) self.trim_action = ac = self.bar.addAction(QIcon(I('trim.png')), _('&Trim'), c.trim_image) ac.setShortcut(QKeySequence('Ctrl+T')) ac.setToolTip( '%s [%s]' % (_('Trim image by removing borders outside the selected region'), ac.shortcut().toString(QKeySequence.NativeText))) ac.setEnabled(False) c.selection_state_changed.connect(self.selection_changed) l.addWidget(c) self.bar.addAction(self.trim_action) self.bar.addSeparator() self.bar.addAction(u) self.bar.addAction(r) self.bar.addSeparator() self.bar.addWidget(la) self.bar.addSeparator() self.bar.addWidget(self.sz) self.bb = bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) bb.accepted.connect(self.accept) bb.rejected.connect(self.reject) l.addWidget(bb) self.tok = b = bb.addButton(_('Trim and OK'), QDialogButtonBox.ActionRole) b.clicked.connect(self.trim_and_accept) b.setIcon(self.trim_action.icon()) self.resize(QSize(900, 600)) geom = gprefs.get('image-trim-dialog-geometry', None) if geom is not None: self.restoreGeometry(geom) self.setWindowIcon(self.trim_action.icon()) self.image_data = None
def __init__(self, parent, db, author, series=None): QDialog.__init__(self, parent) self.db = db self.setWindowTitle(_('How many empty books?')) self._layout = QGridLayout(self) self.setLayout(self._layout) self.qty_label = QLabel(_('How many empty books should be added?')) self._layout.addWidget(self.qty_label, 0, 0, 1, 2) self.qty_spinbox = QSpinBox(self) self.qty_spinbox.setRange(1, 10000) self.qty_spinbox.setValue(1) self._layout.addWidget(self.qty_spinbox, 1, 0, 1, 2) self.author_label = QLabel(_('Set the author of the new books to:')) self._layout.addWidget(self.author_label, 2, 0, 1, 2) self.authors_combo = EditWithComplete(self) self.authors_combo.setSizeAdjustPolicy( self.authors_combo.AdjustToMinimumContentsLengthWithIcon) self.authors_combo.setEditable(True) self._layout.addWidget(self.authors_combo, 3, 0, 1, 1) self.initialize_authors(db, author) self.clear_button = QToolButton(self) self.clear_button.setIcon(QIcon(I('trash.png'))) self.clear_button.setToolTip(_('Reset author to Unknown')) self.clear_button.clicked.connect(self.reset_author) self._layout.addWidget(self.clear_button, 3, 1, 1, 1) self.series_label = QLabel(_('Set the series of the new books to:')) self._layout.addWidget(self.series_label, 4, 0, 1, 2) self.series_combo = EditWithComplete(self) self.authors_combo.setSizeAdjustPolicy( self.authors_combo.AdjustToMinimumContentsLengthWithIcon) self.series_combo.setEditable(True) self._layout.addWidget(self.series_combo, 5, 0, 1, 1) self.initialize_series(db, series) self.sclear_button = QToolButton(self) self.sclear_button.setIcon(QIcon(I('trash.png'))) self.sclear_button.setToolTip(_('Reset series')) self.sclear_button.clicked.connect(self.reset_series) self._layout.addWidget(self.sclear_button, 5, 1, 1, 1) self.create_epub = c = QCheckBox(_('Create an empty EPUB file as well')) c.setChecked(gprefs.get('create_empty_epub_file', False)) c.setToolTip(_('Also create an empty EPUB file that you can subsequently edit')) self._layout.addWidget(c, 6, 0, 1, -1) button_box = self.bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) button_box.accepted.connect(self.accept) button_box.rejected.connect(self.reject) self._layout.addWidget(button_box, 7, 0, 1, -1) self.resize(self.sizeHint())
def create_custom_metadata_widgets(self): # {{{ self.custom_metadata_widgets_parent = w = QWidget(self) layout = QGridLayout() w.setLayout(layout) self.custom_metadata_widgets, self.__cc_spacers = \ populate_metadata_page(layout, self.db, None, parent=w, bulk=False, two_column=self.cc_two_column) self.__custom_col_layouts = [layout]
def confirm_quit(self): if self.doing_terminal_save: return False if self.save_manager.has_tasks: if not question_dialog( self.gui, _('Are you sure?'), _('The current book is being saved in the background, quitting will abort' ' the save process, are you sure?'), default_yes=False): return False if self.gui.action_save.isEnabled(): d = QDialog(self.gui) d.l = QGridLayout(d) d.setLayout(d.l) d.setWindowTitle(_('Unsaved changes')) d.i = QLabel('') d.i.setPixmap( QPixmap(I('save.png')).scaledToHeight(64, Qt.SmoothTransformation)) d.i.setMaximumSize(QSize(d.i.pixmap().width(), 64)) d.i.setScaledContents(True) d.l.addWidget(d.i, 0, 0) d.m = QLabel( _('There are unsaved changes, if you quit without saving, you will lose them.' )) d.m.setWordWrap(True) d.l.addWidget(d.m, 0, 1) d.bb = QDialogButtonBox(QDialogButtonBox.Cancel) d.bb.rejected.connect(d.reject) d.bb.accepted.connect(d.accept) d.l.addWidget(d.bb, 1, 0, 1, 2) d.do_save = None def endit(x): d.do_save = x d.accept() b = d.bb.addButton(_('&Save and Quit'), QDialogButtonBox.ActionRole) b.setIcon(QIcon(I('save.png'))) b.clicked.connect(lambda *args: endit(True)) b = d.bb.addButton(_('&Quit without saving'), QDialogButtonBox.ActionRole) b.clicked.connect(lambda *args: endit(False)) d.resize(d.sizeHint()) if d.exec_() != d.Accepted or d.do_save is None: return False if d.do_save: self.gui.action_save.trigger() self.gui.blocking_job.set_msg(_('Saving, please wait...')) self.gui.blocking_job.start() self.doing_terminal_save = True QTimer.singleShot(50, self.check_terminal_save) return False return True
def __init__(self, movie): self.movie = movie QDialog.__init__(self, None) self.setObjectName("movie_warning") self.text_browser = QTextBrowser(self) self.text_browser.setObjectName("movie_warning_textbrowser") self.text_browser.setMinimumSize(400, 40) self.setWindowTitle('Rewind your movie?') self.text_browser.setPlainText( "You may want to rewind the movie now. If you save the part without " + "rewinding the movie, the movie file will become invalid because it " + "depends upon the initial atom positions. The atoms move as the movie " + "progresses, and saving the part now will save the final positions, " + "which are incorrect for the movie you just watched.") self.ok_button = QPushButton(self) self.ok_button.setObjectName("ok_button") self.ok_button.setText("Rewind movie") self.cancel_button = QPushButton(self) self.cancel_button.setObjectName("cancel_button") self.cancel_button.setText("No thanks") layout = QGridLayout(self) layout.addWidget(self.text_browser,0,0,0,1) layout.addWidget(self.ok_button,1,0) layout.addWidget(self.cancel_button,1,1) self.connect(self.ok_button,SIGNAL("clicked()"),self.rewindMovie) self.connect(self.cancel_button,SIGNAL("clicked()"),self.noThanks)
def __init__(self, movie): self.movie = movie QDialog.__init__(self, None) self.setObjectName("movie_warning") self.text_browser = QTextBrowser(self) self.text_browser.setObjectName("movie_warning_textbrowser") self.text_browser.setMinimumSize(400, 40) self.setWindowTitle('Rewind your movie?') self.text_browser.setPlainText( #bruce 080827 revised text "You may want to rewind the movie now. The atoms move as the movie " "progresses, and saving the part without rewinding will save the " "current positions, which is sometimes useful, but will make the " "movie invalid, because .dpb files only store deltas relative to " "the initial atom positions, and don't store the initial positions " "themselves." ) self.ok_button = QPushButton(self) self.ok_button.setObjectName("ok_button") self.ok_button.setText("Rewind movie") self.cancel_button = QPushButton(self) self.cancel_button.setObjectName("cancel_button") self.cancel_button.setText("Exit command without rewinding") #bruce 080827 revised text # Note: this is not, in fact, a cancel button -- # there is no option in the caller to prevent exiting the command. # There is also no option to "forward to final position", # though for a minimize movie, that might be most useful. # [bruce 080827 comment] layout = QGridLayout(self) layout.addWidget(self.text_browser, 0, 0, 0, 1) layout.addWidget(self.ok_button, 1, 0) layout.addWidget(self.cancel_button, 1, 1) self.connect(self.ok_button, SIGNAL("clicked()"), self.rewindMovie) self.connect(self.cancel_button, SIGNAL("clicked()"), self.noThanks)
def __InitUi(self): self.setFixedHeight(160) SetWidgetBackgroundColor(COLOR_WIDGET_2, self) self.__Layout = QGridLayout() self.setLayout(self.__Layout) self.__Layout.setContentsMargins(30,30,30,30) self.__Layout.setHorizontalSpacing(30) self.__Layout.setVerticalSpacing(30) self.__lblProcess = LabelSmalSize("", COLOR_FONT_4, True) self.__Layout.addWidget(self.__lblProcess) self.__pgbProgress = Progressbar() self.__Layout.addWidget(self.__pgbProgress)
def __init__(self): QWidget.__init__(self, ctx.mainScreen) self.setObjectName("InformationWindow") self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.setFixedHeight(50) self.setMaximumWidth(800) self.setStyleSheet(""" QFrame#frame { border: 1px solid rgba(255,255,255,30); /*border-radius: 4px;*/ background-color: rgba(0,0,0,100);} QLabel { border:none; color:#FFFFFF;} QProgressBar { border: 1px solid white;} QProgressBar::chunk { background-color: #F1610D; width: 0.5px;} """) self.gridlayout = QGridLayout(self) self.frame = QFrame(self) self.frame.setObjectName("frame") self.horizontalLayout = QHBoxLayout(self.frame) self.horizontalLayout.setContentsMargins(10, 0, 10, 0) # Spinner self.spinner = QLabel(self.frame) self.spinner.setMinimumSize(QSize(16, 16)) self.spinner.setMaximumSize(QSize(16, 16)) self.spinner.setIndent(6) self.movie = QMovie(':/images/working.mng') self.spinner.setMovie(self.movie) self.movie.start() self.horizontalLayout.addWidget(self.spinner) # Message self.label = QLabel(self.frame) self.label.setAlignment(Qt.AlignCenter) self.label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.icon = QLabel(self.frame) self.icon.setFixedWidth(16) self.icon.setFixedHeight(16) self.horizontalLayout.setSpacing(10) self.horizontalLayout.addWidget(self.icon) self.horizontalLayout.addWidget(self.label) self.gridlayout.addWidget(self.frame,0,0,1,1)
def __init__(self, parent, txt): QDialog.__init__(self, parent) l = QGridLayout() self.setLayout(l) self.setWindowTitle(_('Invalid ISBN')) w = QLabel(_('Enter an ISBN')) l.addWidget(w, 0, 0, 1, 2) w = QLabel(_('ISBN:')) l.addWidget(w, 1, 0, 1, 1) self.line_edit = w = QLineEdit(); w.setText(txt) w.selectAll() w.textChanged.connect(self.checkText) l.addWidget(w, 1, 1, 1, 1) w = QDialogButtonBox(QDialogButtonBox.Ok|QDialogButtonBox.Cancel) l.addWidget(w, 2, 0, 1, 2) w.accepted.connect(self.accept) w.rejected.connect(self.reject) self.checkText(self.text()) sz = self.sizeHint() sz.setWidth(sz.width()+50) self.resize(sz)
def settings_dialog(self): get_label = lambda: self.wallet.get_client().features.label update_label = lambda: current_label_label.setText("Label: %s" % get_label()) d = QDialog() layout = QGridLayout(d) layout.addWidget(QLabel("Trezor Options"),0,0) layout.addWidget(QLabel("ID:"),1,0) layout.addWidget(QLabel(" %s" % self.wallet.get_client().get_device_id()),1,1) def modify_label(): response = QInputDialog().getText(None, "Set New Trezor Label", "New Trezor Label: (upon submission confirm on Trezor)") if not response[1]: return new_label = str(response[0]) twd.start("Please confirm label change on Trezor") status = self.wallet.get_client().apply_settings(label=new_label) twd.stop() update_label() current_label_label = QLabel() update_label() change_label_button = QPushButton("Modify") change_label_button.clicked.connect(modify_label) layout.addWidget(current_label_label,3,0) layout.addWidget(change_label_button,3,1) def remove_pin(): # twd.start("Please confirm pin removal on Trezor") try: status = self.wallet.get_client().change_pin(True) print_error(status) self.show_message(status) except Exception, e: give_error(e) finally:
def __init__(self): QWidget.__init__(self) self.layout = QGridLayout() self.layout.setSpacing(10) self.setLayout(self.layout) self.key_label = QLabel('&api key:') self.key_msg = QLineEdit(self) self.key_msg.setText(PREFS['api_key']) self.layout.addWidget(self.key_label, 1, 0) self.layout.addWidget(self.key_msg, 1, 1) self.key_label.setBuddy(self.key_msg) self.threads_label = QLabel('&worker_threads:') self.threads_msg = QLineEdit(self) self.threads_msg.setText(unicode(PREFS['worker_threads'])) self.layout.addWidget(self.threads_label, 2, 0) self.layout.addWidget(self.threads_msg, 2, 1) self.threads_label.setBuddy(self.threads_msg)
def __init__(self, plugin_action, prefs): QWidget.__init__(self) self.plugin_action = plugin_action self.prefs = prefs self.layout = QGridLayout() self.setLayout(self.layout) accounts = self.prefs[self.prefs.ACCOUNTS] # Copy any data necessary into the prefs object # The primary account, as configured in the GUI above account = accounts.get('0', {}) self.labelUrlBase = QLabel(_('URL')) self.layout.addWidget(self.labelUrlBase, 0, 0) self.urlbase = QLabel() if prefs[prefs.URLBASE] is not None: self.urlbase.setText(prefs[prefs.URLBASE]) self.layout.addWidget(self.urlbase, 0, 1) self.labelUrlBase.setBuddy(self.urlbase) self.labelUserName = QLabel(_('Username')) self.layout.addWidget(self.labelUserName, 1, 0) self.username = QLineEdit(self) if account.get(prefs.USERNAME) is not None: self.username.setText(account[prefs.USERNAME]) self.layout.addWidget(self.username, 1, 1) self.labelUserName.setBuddy(self.username) self.labelPassword = QLabel(_('Password')) self.layout.addWidget(self.labelPassword, 2, 0) self.password = QLineEdit(self) if account.get(prefs.OBFUSCATED_PASSWORD) is not None: decrypted = prefs.decrypt_password(account[prefs.OBFUSCATED_PASSWORD]) self.password.setText(decrypted) self.layout.addWidget(self.password, 2, 1) self.labelPassword.setBuddy(self.password)
def _createSponsorButton(self): """ Creates the Property Manager sponsor button, which contains a QPushButton inside of a QGridLayout inside of a QFrame. The sponsor logo image is not loaded here. """ # Sponsor button (inside a frame) self.sponsor_frame = QFrame(self) self.sponsor_frame.setFrameShape(QFrame.NoFrame) self.sponsor_frame.setFrameShadow(QFrame.Plain) SponsorFrameGrid = QGridLayout(self.sponsor_frame) SponsorFrameGrid.setMargin(PM_SPONSOR_FRAME_MARGIN) SponsorFrameGrid.setSpacing(PM_SPONSOR_FRAME_SPACING) # Has no effect. self.sponsor_btn = QPushButton(self.sponsor_frame) self.sponsor_btn.setAutoDefault(False) self.sponsor_btn.setFlat(True) self.connect(self.sponsor_btn, SIGNAL("clicked()"), self.open_sponsor_homepage) SponsorFrameGrid.addWidget(self.sponsor_btn, 0, 0, 1, 1) self.vBoxLayout.addWidget(self.sponsor_frame) button_whatsthis_widget = self.sponsor_btn #bruce 070615 bugfix -- put tooltip & whatsthis on self.sponsor_btn, # not self. # [self.sponsor_frame might be another possible place to put them.] button_whatsthis_widget.setWhatsThis("""<b>Sponsor Button</b> <p>When clicked, this sponsor logo will display a short description about a NanoEngineer-1 sponsor. This can be an official sponsor or credit given to a contributor that has helped code part or all of this command. A link is provided in the description to learn more about this sponsor.</p>""") button_whatsthis_widget.setToolTip("NanoEngineer-1 Sponsor Button") return
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 __init__(self, calibre_version, plugin_updates, parent=None): QDialog.__init__(self, parent) self.setAttribute(Qt.WA_QuitOnClose, False) self.resize(400, 250) self.l = QGridLayout() self.setLayout(self.l) self.logo = QLabel() self.logo.setMaximumWidth(110) self.logo.setPixmap(QPixmap(I('lt.png')).scaled(100, 100, Qt.IgnoreAspectRatio, Qt.SmoothTransformation)) self.label = QLabel(('<p>'+ _('New version <b>%(ver)s</b> of %(app)s is available for download. ' 'See the <a href="http://calibre-ebook.com/whats-new' '">new features</a>.'))%dict( app=__appname__, ver=calibre_version)) self.label.setOpenExternalLinks(True) self.label.setWordWrap(True) self.setWindowTitle(_('Update available!')) self.setWindowIcon(QIcon(I('lt.png'))) self.l.addWidget(self.logo, 0, 0) self.l.addWidget(self.label, 0, 1) self.cb = QCheckBox( _('Show this notification for future updates'), self) self.l.addWidget(self.cb, 1, 0, 1, -1) self.cb.setChecked(config.get('new_version_notification')) self.cb.stateChanged.connect(self.show_future) self.bb = QDialogButtonBox(self) b = self.bb.addButton(_('&Get update'), self.bb.AcceptRole) b.setDefault(True) b.setIcon(QIcon(I('arrow-down.png'))) if plugin_updates > 0: b = self.bb.addButton(_('Update &plugins'), self.bb.ActionRole) b.setIcon(QIcon(I('plugins/plugin_updater.png'))) b.clicked.connect(self.get_plugins, type=Qt.QueuedConnection) self.bb.addButton(self.bb.Cancel) self.l.addWidget(self.bb, 2, 0, 1, -1) self.bb.accepted.connect(self.accept) self.bb.rejected.connect(self.reject) dynamic.set('update to version %s'%calibre_version, False)
def __init__(self, parent, db, author): QDialog.__init__(self, parent) self.db = db self.setWindowTitle(_('How many empty books?')) self._layout = QGridLayout(self) self.setLayout(self._layout) self.qty_label = QLabel(_('How many empty books should be added?')) self._layout.addWidget(self.qty_label, 0, 0, 1, 2) self.qty_spinbox = QSpinBox(self) self.qty_spinbox.setRange(1, 10000) self.qty_spinbox.setValue(1) self._layout.addWidget(self.qty_spinbox, 1, 0, 1, 2) self.author_label = QLabel(_('Set the author of the new books to:')) self._layout.addWidget(self.author_label, 2, 0, 1, 2) self.authors_combo = EditWithComplete(self) self.authors_combo.setSizeAdjustPolicy( self.authors_combo.AdjustToMinimumContentsLengthWithIcon) self.authors_combo.setEditable(True) self._layout.addWidget(self.authors_combo, 3, 0, 1, 1) self.initialize_authors(db, author) self.clear_button = QToolButton(self) self.clear_button.setIcon(QIcon(I('trash.png'))) self.clear_button.setToolTip(_('Reset author to Unknown')) self.clear_button.clicked.connect(self.reset_author) self._layout.addWidget(self.clear_button, 3, 1, 1, 1) button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) button_box.accepted.connect(self.accept) button_box.rejected.connect(self.reject) self._layout.addWidget(button_box) self.resize(self.sizeHint())
def __init__(self, parent, main, maxSeg): super(DlgSpecifyOrdering, self).__init__(parent, main) self.maxSeg = maxSeg self.setWindowTitle('Enter Ordering') self.setWindowIcon(QIcon(self.main.iconfile)) buttonbox = QDialogButtonBox(QDialogButtonBox.Ok | \ QDialogButtonBox.Cancel) self.connect(buttonbox, SIGNAL('accepted()'), self.accept) self.connect(buttonbox, SIGNAL('rejected()'), self.reject) layout = QGridLayout() lbl = QLabel('Enter Ordering as a comma separated list of segment indices between 1 and %d:' % maxSeg) self.editOrdering = QLineEdit() h, w = relaxedSizeNChar(self, 50) self.editOrdering.setMinimumSize(h, w) self.editOrdering.setMaxLength(MAX_SEGMENTS) editSegPanel = makeHorizFrame([self.editOrdering, 'stretch']) layout.addWidget(lbl, 0, 0) layout.addWidget(editSegPanel, 0, 1) layout.addWidget(buttonbox, 1, 0) self.setLayout(layout)
def __init__(self, plugin_action): QWidget.__init__(self) self.parent = plugin_action self.gui = get_gui() self.icon = plugin_action.icon self.opts = plugin_action.opts self.prefs = plugin_prefs self.resources_path = plugin_action.resources_path self.verbose = plugin_action.verbose self.restart_required = False self._log_location() self.l = QGridLayout() self.setLayout(self.l) self.column1_layout = QVBoxLayout() self.l.addLayout(self.column1_layout, 0, 0) self.column2_layout = QVBoxLayout() self.l.addLayout(self.column2_layout, 0, 1) # ----------------------------- Column 1 ----------------------------- # ~~~~~~~~ Create the Custom fields options group box ~~~~~~~~ self.cfg_custom_fields_gb = QGroupBox(self) self.cfg_custom_fields_gb.setTitle('Custom column assignments') self.column1_layout.addWidget(self.cfg_custom_fields_gb) self.cfg_custom_fields_qgl = QGridLayout(self.cfg_custom_fields_gb) current_row = 0 # ++++++++ Labels + HLine ++++++++ self.marvin_source_label = QLabel("Marvin source") self.cfg_custom_fields_qgl.addWidget(self.marvin_source_label, current_row, 0) self.calibre_destination_label = QLabel("calibre destination") self.cfg_custom_fields_qgl.addWidget(self.calibre_destination_label, current_row, 1) current_row += 1 self.sd_hl = QFrame(self.cfg_custom_fields_gb) self.sd_hl.setFrameShape(QFrame.HLine) self.sd_hl.setFrameShadow(QFrame.Raised) self.cfg_custom_fields_qgl.addWidget(self.sd_hl, current_row, 0, 1, 3) current_row += 1 # ++++++++ Annotations ++++++++ self.cfg_annotations_label = QLabel('Annotations') self.cfg_annotations_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_annotations_label, current_row, 0) self.annotations_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.annotations_field_comboBox.setObjectName('annotations_field_comboBox') self.annotations_field_comboBox.setToolTip('Select a custom column to store Marvin annotations') self.cfg_custom_fields_qgl.addWidget(self.annotations_field_comboBox, current_row, 1) self.cfg_highlights_wizard = QToolButton() self.cfg_highlights_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_highlights_wizard.setToolTip("Create a custom column to store Marvin annotations") self.cfg_highlights_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Annotations')) self.cfg_custom_fields_qgl.addWidget(self.cfg_highlights_wizard, current_row, 2) current_row += 1 # ++++++++ Collections ++++++++ self.cfg_collections_label = QLabel('Collections') self.cfg_collections_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_collections_label, current_row, 0) self.collection_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.collection_field_comboBox.setObjectName('collection_field_comboBox') self.collection_field_comboBox.setToolTip('Select a custom column to store Marvin collection assignments') self.cfg_custom_fields_qgl.addWidget(self.collection_field_comboBox, current_row, 1) self.cfg_collections_wizard = QToolButton() self.cfg_collections_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_collections_wizard.setToolTip("Create a custom column for Marvin collection assignments") self.cfg_collections_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Collections')) self.cfg_custom_fields_qgl.addWidget(self.cfg_collections_wizard, current_row, 2) current_row += 1 # ++++++++ Last read ++++++++ self.cfg_date_read_label = QLabel("Last read") self.cfg_date_read_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_date_read_label, current_row, 0) self.date_read_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.date_read_field_comboBox.setObjectName('date_read_field_comboBox') self.date_read_field_comboBox.setToolTip('Select a custom column to store Last read date') self.cfg_custom_fields_qgl.addWidget(self.date_read_field_comboBox, current_row, 1) self.cfg_collections_wizard = QToolButton() self.cfg_collections_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_collections_wizard.setToolTip("Create a custom column to store Last read date") self.cfg_collections_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Last read')) self.cfg_custom_fields_qgl.addWidget(self.cfg_collections_wizard, current_row, 2) current_row += 1 # ++++++++ Locked ++++++++ self.cfg_locked_label = QLabel("Locked") self.cfg_locked_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_locked_label, current_row, 0) self.locked_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.locked_field_comboBox.setObjectName('locked_field_comboBox') self.locked_field_comboBox.setToolTip('Select a custom column to store Locked status') self.cfg_custom_fields_qgl.addWidget(self.locked_field_comboBox, current_row, 1) self.cfg_locked_wizard = QToolButton() self.cfg_locked_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_locked_wizard.setToolTip("Create a custom column to store Locked status") self.cfg_locked_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Locked')) self.cfg_custom_fields_qgl.addWidget(self.cfg_locked_wizard, current_row, 2) current_row += 1 # ++++++++ Progress ++++++++ self.cfg_progress_label = QLabel('Progress') self.cfg_progress_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_progress_label, current_row, 0) self.progress_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.progress_field_comboBox.setObjectName('progress_field_comboBox') self.progress_field_comboBox.setToolTip('Select a custom column to store Marvin reading progress') self.cfg_custom_fields_qgl.addWidget(self.progress_field_comboBox, current_row, 1) self.cfg_progress_wizard = QToolButton() self.cfg_progress_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_progress_wizard.setToolTip("Create a custom column to store Marvin reading progress") self.cfg_progress_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Progress')) self.cfg_custom_fields_qgl.addWidget(self.cfg_progress_wizard, current_row, 2) current_row += 1 # ++++++++ Read flag ++++++++ self.cfg_read_label = QLabel('Read') self.cfg_read_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_read_label, current_row, 0) self.read_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.read_field_comboBox.setObjectName('read_field_comboBox') self.read_field_comboBox.setToolTip('Select a custom column to store Marvin Read status') self.cfg_custom_fields_qgl.addWidget(self.read_field_comboBox, current_row, 1) self.cfg_read_wizard = QToolButton() self.cfg_read_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_read_wizard.setToolTip("Create a custom column to store Marvin Read status") self.cfg_read_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Read')) self.cfg_custom_fields_qgl.addWidget(self.cfg_read_wizard, current_row, 2) current_row += 1 # ++++++++ Reading list flag ++++++++ self.cfg_reading_list_label = QLabel('Reading list') self.cfg_reading_list_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_reading_list_label, current_row, 0) self.reading_list_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.reading_list_field_comboBox.setObjectName('reading_list_field_comboBox') self.reading_list_field_comboBox.setToolTip('Select a custom column to store Marvin Reading list status') self.cfg_custom_fields_qgl.addWidget(self.reading_list_field_comboBox, current_row, 1) self.cfg_reading_list_wizard = QToolButton() self.cfg_reading_list_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_reading_list_wizard.setToolTip("Create a custom column to store Marvin Reading list status") self.cfg_reading_list_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Reading list')) self.cfg_custom_fields_qgl.addWidget(self.cfg_reading_list_wizard, current_row, 2) current_row += 1 # ++++++++ Word count ++++++++ self.cfg_word_count_label = QLabel('Word count') self.cfg_word_count_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_word_count_label, current_row, 0) self.word_count_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.word_count_field_comboBox.setObjectName('word_count_field_comboBox') self.word_count_field_comboBox.setToolTip('Select a custom column to store Marvin word counts') self.cfg_custom_fields_qgl.addWidget(self.word_count_field_comboBox, current_row, 1) self.cfg_word_count_wizard = QToolButton() self.cfg_word_count_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_word_count_wizard.setToolTip("Create a custom column to store Marvin word counts") self.cfg_word_count_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Word count')) self.cfg_custom_fields_qgl.addWidget(self.cfg_word_count_wizard, current_row, 2) current_row += 1 self.spacerItem1 = QSpacerItem(20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding) self.column1_layout.addItem(self.spacerItem1) # ----------------------------- Column 2 ----------------------------- # ~~~~~~~~ Create the CSS group box ~~~~~~~~ self.cfg_css_options_gb = QGroupBox(self) self.cfg_css_options_gb.setTitle('CSS') self.column2_layout.addWidget(self.cfg_css_options_gb) self.cfg_css_options_qgl = QGridLayout(self.cfg_css_options_gb) current_row = 0 # ++++++++ Annotations appearance ++++++++ self.annotations_icon = QIcon(os.path.join(self.resources_path, 'icons', 'annotations_hiliter.png')) self.cfg_annotations_appearance_toolbutton = QToolButton() self.cfg_annotations_appearance_toolbutton.setIcon(self.annotations_icon) self.cfg_annotations_appearance_toolbutton.clicked.connect(self.configure_appearance) self.cfg_css_options_qgl.addWidget(self.cfg_annotations_appearance_toolbutton, current_row, 0) self.cfg_annotations_label = ClickableQLabel("Book notes, Bookmark notes and Annotations") self.connect(self.cfg_annotations_label, SIGNAL('clicked()'), self.configure_appearance) self.cfg_css_options_qgl.addWidget(self.cfg_annotations_label, current_row, 1) current_row += 1 # ++++++++ Injected CSS ++++++++ self.css_editor_icon = QIcon(I('format-text-heading.png')) self.cfg_css_editor_toolbutton = QToolButton() self.cfg_css_editor_toolbutton.setIcon(self.css_editor_icon) self.cfg_css_editor_toolbutton.clicked.connect(self.edit_css) self.cfg_css_options_qgl.addWidget(self.cfg_css_editor_toolbutton, current_row, 0) self.cfg_css_editor_label = ClickableQLabel("Articles, Vocabulary") self.connect(self.cfg_css_editor_label, SIGNAL('clicked()'), self.edit_css) self.cfg_css_options_qgl.addWidget(self.cfg_css_editor_label, current_row, 1) """ # ~~~~~~~~ Create the Dropbox syncing group box ~~~~~~~~ self.cfg_dropbox_syncing_gb = QGroupBox(self) self.cfg_dropbox_syncing_gb.setTitle('Dropbox') self.column2_layout.addWidget(self.cfg_dropbox_syncing_gb) self.cfg_dropbox_syncing_qgl = QGridLayout(self.cfg_dropbox_syncing_gb) current_row = 0 # ++++++++ Syncing enabled checkbox ++++++++ self.dropbox_syncing_checkbox = QCheckBox('Enable Dropbox updates') self.dropbox_syncing_checkbox.setObjectName('dropbox_syncing') self.dropbox_syncing_checkbox.setToolTip('Refresh custom column content from Marvin metadata') self.cfg_dropbox_syncing_qgl.addWidget(self.dropbox_syncing_checkbox, current_row, 0, 1, 3) current_row += 1 # ++++++++ Dropbox folder picker ++++++++ self.dropbox_folder_icon = QIcon(os.path.join(self.resources_path, 'icons', 'dropbox.png')) self.cfg_dropbox_folder_toolbutton = QToolButton() self.cfg_dropbox_folder_toolbutton.setIcon(self.dropbox_folder_icon) self.cfg_dropbox_folder_toolbutton.setToolTip("Specify Dropbox folder location on your computer") self.cfg_dropbox_folder_toolbutton.clicked.connect(self.select_dropbox_folder) self.cfg_dropbox_syncing_qgl.addWidget(self.cfg_dropbox_folder_toolbutton, current_row, 1) # ++++++++ Dropbox location lineedit ++++++++ self.dropbox_location_lineedit = QLineEdit() self.dropbox_location_lineedit.setPlaceholderText("Dropbox folder location") self.cfg_dropbox_syncing_qgl.addWidget(self.dropbox_location_lineedit, current_row, 2) """ # ~~~~~~~~ Create the General options group box ~~~~~~~~ self.cfg_runtime_options_gb = QGroupBox(self) self.cfg_runtime_options_gb.setTitle('General options') self.column2_layout.addWidget(self.cfg_runtime_options_gb) self.cfg_runtime_options_qvl = QVBoxLayout(self.cfg_runtime_options_gb) # ++++++++ Temporary markers: Duplicates ++++++++ self.duplicate_markers_checkbox = QCheckBox('Apply temporary markers to duplicate books') self.duplicate_markers_checkbox.setObjectName('apply_markers_to_duplicates') self.duplicate_markers_checkbox.setToolTip('Books with identical content will be flagged in the Library window') self.cfg_runtime_options_qvl.addWidget(self.duplicate_markers_checkbox) # ++++++++ Temporary markers: Updated ++++++++ self.updated_markers_checkbox = QCheckBox('Apply temporary markers to books with updated content') self.updated_markers_checkbox.setObjectName('apply_markers_to_updated') self.updated_markers_checkbox.setToolTip('Books with updated content will be flagged in the Library window') self.cfg_runtime_options_qvl.addWidget(self.updated_markers_checkbox) # ++++++++ Auto refresh checkbox ++++++++ self.auto_refresh_checkbox = QCheckBox('Automatically refresh custom column content') self.auto_refresh_checkbox.setObjectName('auto_refresh_at_startup') self.auto_refresh_checkbox.setToolTip('Update calibre custom column when Marvin XD is opened') self.cfg_runtime_options_qvl.addWidget(self.auto_refresh_checkbox) # ++++++++ Progress as percentage checkbox ++++++++ self.reading_progress_checkbox = QCheckBox('Show reading progress as percentage') self.reading_progress_checkbox.setObjectName('show_progress_as_percentage') self.reading_progress_checkbox.setToolTip('Display percentage in Progress column') self.cfg_runtime_options_qvl.addWidget(self.reading_progress_checkbox) # ~~~~~~~~ Create the Debug options group box ~~~~~~~~ self.cfg_debug_options_gb = QGroupBox(self) self.cfg_debug_options_gb.setTitle('Debug options') self.column2_layout.addWidget(self.cfg_debug_options_gb) self.cfg_debug_options_qvl = QVBoxLayout(self.cfg_debug_options_gb) # ++++++++ Debug logging checkboxes ++++++++ self.debug_plugin_checkbox = QCheckBox('Enable debug logging for Marvin XD') self.debug_plugin_checkbox.setObjectName('debug_plugin_checkbox') self.debug_plugin_checkbox.setToolTip('Print plugin diagnostic messages to console') self.cfg_debug_options_qvl.addWidget(self.debug_plugin_checkbox) self.debug_libimobiledevice_checkbox = QCheckBox('Enable debug logging for libiMobileDevice') self.debug_libimobiledevice_checkbox.setObjectName('debug_libimobiledevice_checkbox') self.debug_libimobiledevice_checkbox.setToolTip('Print libiMobileDevice diagnostic messages to console') self.cfg_debug_options_qvl.addWidget(self.debug_libimobiledevice_checkbox) self.spacerItem2 = QSpacerItem(20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding) self.column2_layout.addItem(self.spacerItem2) # ~~~~~~~~ End of construction zone ~~~~~~~~ self.resize(self.sizeHint()) # ~~~~~~~~ Populate/restore config options ~~~~~~~~ # Annotations comboBox self.populate_annotations() self.populate_collections() self.populate_date_read() self.populate_locked() self.populate_progress() self.populate_read() self.populate_reading_list() self.populate_word_count() """ # Restore Dropbox settings, hook changes dropbox_syncing = self.prefs.get('dropbox_syncing', False) self.dropbox_syncing_checkbox.setChecked(dropbox_syncing) self.set_dropbox_syncing(dropbox_syncing) self.dropbox_syncing_checkbox.clicked.connect(partial(self.set_dropbox_syncing)) self.dropbox_location_lineedit.setText(self.prefs.get('dropbox_folder', '')) """ # Restore general settings self.duplicate_markers_checkbox.setChecked(self.prefs.get('apply_markers_to_duplicates', True)) self.updated_markers_checkbox.setChecked(self.prefs.get('apply_markers_to_updated', True)) self.auto_refresh_checkbox.setChecked(self.prefs.get('auto_refresh_at_startup', False)) self.reading_progress_checkbox.setChecked(self.prefs.get('show_progress_as_percentage', False)) # Restore debug settings, hook changes self.debug_plugin_checkbox.setChecked(self.prefs.get('debug_plugin', False)) self.debug_plugin_checkbox.stateChanged.connect(self.set_restart_required) self.debug_libimobiledevice_checkbox.setChecked(self.prefs.get('debug_libimobiledevice', False)) self.debug_libimobiledevice_checkbox.stateChanged.connect(self.set_restart_required) # Hook changes to Annotations comboBox # self.annotations_field_comboBox.currentIndexChanged.connect( # partial(self.save_combobox_setting, 'annotations_field_comboBox')) self.connect(self.annotations_field_comboBox, SIGNAL('currentIndexChanged(const QString &)'), self.annotations_destination_changed) # Launch the annotated_books_scanner field = get_cc_mapping('annotations', 'field', None) self.annotated_books_scanner = InventoryAnnotatedBooks(self.gui, field) self.connect(self.annotated_books_scanner, self.annotated_books_scanner.signal, self.inventory_complete) QTimer.singleShot(1, self.start_inventory)
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
class ConfigWidget(QWidget, Logger): ''' Config dialog for Marvin Manager ''' WIZARD_PROFILES = { 'Annotations': { 'label': 'mm_annotations', 'datatype': 'comments', 'display': {}, 'is_multiple': False }, 'Collections': { 'label': 'mm_collections', 'datatype': 'text', 'display': {u'is_names': False}, 'is_multiple': True }, 'Last read': { 'label': 'mm_date_read', 'datatype': 'datetime', 'display': {}, 'is_multiple': False }, 'Locked': { 'label': 'mm_locked', 'datatype': 'bool', 'display': {}, 'is_multiple': False }, 'Progress': { 'label': 'mm_progress', 'datatype': 'float', 'display': {u'number_format': u'{0:.0f}%'}, 'is_multiple': False }, 'Read': { 'label': 'mm_read', 'datatype': 'bool', 'display': {}, 'is_multiple': False }, 'Reading list': { 'label': 'mm_reading_list', 'datatype': 'bool', 'display': {}, 'is_multiple': False }, 'Word count': { 'label': 'mm_word_count', 'datatype': 'int', 'display': {u'number_format': u'{0:n}'}, 'is_multiple': False } } def __init__(self, plugin_action): QWidget.__init__(self) self.parent = plugin_action self.gui = get_gui() self.icon = plugin_action.icon self.opts = plugin_action.opts self.prefs = plugin_prefs self.resources_path = plugin_action.resources_path self.verbose = plugin_action.verbose self.restart_required = False self._log_location() self.l = QGridLayout() self.setLayout(self.l) self.column1_layout = QVBoxLayout() self.l.addLayout(self.column1_layout, 0, 0) self.column2_layout = QVBoxLayout() self.l.addLayout(self.column2_layout, 0, 1) # ----------------------------- Column 1 ----------------------------- # ~~~~~~~~ Create the Custom fields options group box ~~~~~~~~ self.cfg_custom_fields_gb = QGroupBox(self) self.cfg_custom_fields_gb.setTitle('Custom column assignments') self.column1_layout.addWidget(self.cfg_custom_fields_gb) self.cfg_custom_fields_qgl = QGridLayout(self.cfg_custom_fields_gb) current_row = 0 # ++++++++ Labels + HLine ++++++++ self.marvin_source_label = QLabel("Marvin source") self.cfg_custom_fields_qgl.addWidget(self.marvin_source_label, current_row, 0) self.calibre_destination_label = QLabel("calibre destination") self.cfg_custom_fields_qgl.addWidget(self.calibre_destination_label, current_row, 1) current_row += 1 self.sd_hl = QFrame(self.cfg_custom_fields_gb) self.sd_hl.setFrameShape(QFrame.HLine) self.sd_hl.setFrameShadow(QFrame.Raised) self.cfg_custom_fields_qgl.addWidget(self.sd_hl, current_row, 0, 1, 3) current_row += 1 # ++++++++ Annotations ++++++++ self.cfg_annotations_label = QLabel('Annotations') self.cfg_annotations_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_annotations_label, current_row, 0) self.annotations_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.annotations_field_comboBox.setObjectName('annotations_field_comboBox') self.annotations_field_comboBox.setToolTip('Select a custom column to store Marvin annotations') self.cfg_custom_fields_qgl.addWidget(self.annotations_field_comboBox, current_row, 1) self.cfg_highlights_wizard = QToolButton() self.cfg_highlights_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_highlights_wizard.setToolTip("Create a custom column to store Marvin annotations") self.cfg_highlights_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Annotations')) self.cfg_custom_fields_qgl.addWidget(self.cfg_highlights_wizard, current_row, 2) current_row += 1 # ++++++++ Collections ++++++++ self.cfg_collections_label = QLabel('Collections') self.cfg_collections_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_collections_label, current_row, 0) self.collection_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.collection_field_comboBox.setObjectName('collection_field_comboBox') self.collection_field_comboBox.setToolTip('Select a custom column to store Marvin collection assignments') self.cfg_custom_fields_qgl.addWidget(self.collection_field_comboBox, current_row, 1) self.cfg_collections_wizard = QToolButton() self.cfg_collections_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_collections_wizard.setToolTip("Create a custom column for Marvin collection assignments") self.cfg_collections_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Collections')) self.cfg_custom_fields_qgl.addWidget(self.cfg_collections_wizard, current_row, 2) current_row += 1 # ++++++++ Last read ++++++++ self.cfg_date_read_label = QLabel("Last read") self.cfg_date_read_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_date_read_label, current_row, 0) self.date_read_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.date_read_field_comboBox.setObjectName('date_read_field_comboBox') self.date_read_field_comboBox.setToolTip('Select a custom column to store Last read date') self.cfg_custom_fields_qgl.addWidget(self.date_read_field_comboBox, current_row, 1) self.cfg_collections_wizard = QToolButton() self.cfg_collections_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_collections_wizard.setToolTip("Create a custom column to store Last read date") self.cfg_collections_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Last read')) self.cfg_custom_fields_qgl.addWidget(self.cfg_collections_wizard, current_row, 2) current_row += 1 # ++++++++ Locked ++++++++ self.cfg_locked_label = QLabel("Locked") self.cfg_locked_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_locked_label, current_row, 0) self.locked_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.locked_field_comboBox.setObjectName('locked_field_comboBox') self.locked_field_comboBox.setToolTip('Select a custom column to store Locked status') self.cfg_custom_fields_qgl.addWidget(self.locked_field_comboBox, current_row, 1) self.cfg_locked_wizard = QToolButton() self.cfg_locked_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_locked_wizard.setToolTip("Create a custom column to store Locked status") self.cfg_locked_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Locked')) self.cfg_custom_fields_qgl.addWidget(self.cfg_locked_wizard, current_row, 2) current_row += 1 # ++++++++ Progress ++++++++ self.cfg_progress_label = QLabel('Progress') self.cfg_progress_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_progress_label, current_row, 0) self.progress_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.progress_field_comboBox.setObjectName('progress_field_comboBox') self.progress_field_comboBox.setToolTip('Select a custom column to store Marvin reading progress') self.cfg_custom_fields_qgl.addWidget(self.progress_field_comboBox, current_row, 1) self.cfg_progress_wizard = QToolButton() self.cfg_progress_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_progress_wizard.setToolTip("Create a custom column to store Marvin reading progress") self.cfg_progress_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Progress')) self.cfg_custom_fields_qgl.addWidget(self.cfg_progress_wizard, current_row, 2) current_row += 1 # ++++++++ Read flag ++++++++ self.cfg_read_label = QLabel('Read') self.cfg_read_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_read_label, current_row, 0) self.read_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.read_field_comboBox.setObjectName('read_field_comboBox') self.read_field_comboBox.setToolTip('Select a custom column to store Marvin Read status') self.cfg_custom_fields_qgl.addWidget(self.read_field_comboBox, current_row, 1) self.cfg_read_wizard = QToolButton() self.cfg_read_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_read_wizard.setToolTip("Create a custom column to store Marvin Read status") self.cfg_read_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Read')) self.cfg_custom_fields_qgl.addWidget(self.cfg_read_wizard, current_row, 2) current_row += 1 # ++++++++ Reading list flag ++++++++ self.cfg_reading_list_label = QLabel('Reading list') self.cfg_reading_list_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_reading_list_label, current_row, 0) self.reading_list_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.reading_list_field_comboBox.setObjectName('reading_list_field_comboBox') self.reading_list_field_comboBox.setToolTip('Select a custom column to store Marvin Reading list status') self.cfg_custom_fields_qgl.addWidget(self.reading_list_field_comboBox, current_row, 1) self.cfg_reading_list_wizard = QToolButton() self.cfg_reading_list_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_reading_list_wizard.setToolTip("Create a custom column to store Marvin Reading list status") self.cfg_reading_list_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Reading list')) self.cfg_custom_fields_qgl.addWidget(self.cfg_reading_list_wizard, current_row, 2) current_row += 1 # ++++++++ Word count ++++++++ self.cfg_word_count_label = QLabel('Word count') self.cfg_word_count_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_word_count_label, current_row, 0) self.word_count_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.word_count_field_comboBox.setObjectName('word_count_field_comboBox') self.word_count_field_comboBox.setToolTip('Select a custom column to store Marvin word counts') self.cfg_custom_fields_qgl.addWidget(self.word_count_field_comboBox, current_row, 1) self.cfg_word_count_wizard = QToolButton() self.cfg_word_count_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_word_count_wizard.setToolTip("Create a custom column to store Marvin word counts") self.cfg_word_count_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Word count')) self.cfg_custom_fields_qgl.addWidget(self.cfg_word_count_wizard, current_row, 2) current_row += 1 self.spacerItem1 = QSpacerItem(20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding) self.column1_layout.addItem(self.spacerItem1) # ----------------------------- Column 2 ----------------------------- # ~~~~~~~~ Create the CSS group box ~~~~~~~~ self.cfg_css_options_gb = QGroupBox(self) self.cfg_css_options_gb.setTitle('CSS') self.column2_layout.addWidget(self.cfg_css_options_gb) self.cfg_css_options_qgl = QGridLayout(self.cfg_css_options_gb) current_row = 0 # ++++++++ Annotations appearance ++++++++ self.annotations_icon = QIcon(os.path.join(self.resources_path, 'icons', 'annotations_hiliter.png')) self.cfg_annotations_appearance_toolbutton = QToolButton() self.cfg_annotations_appearance_toolbutton.setIcon(self.annotations_icon) self.cfg_annotations_appearance_toolbutton.clicked.connect(self.configure_appearance) self.cfg_css_options_qgl.addWidget(self.cfg_annotations_appearance_toolbutton, current_row, 0) self.cfg_annotations_label = ClickableQLabel("Book notes, Bookmark notes and Annotations") self.connect(self.cfg_annotations_label, SIGNAL('clicked()'), self.configure_appearance) self.cfg_css_options_qgl.addWidget(self.cfg_annotations_label, current_row, 1) current_row += 1 # ++++++++ Injected CSS ++++++++ self.css_editor_icon = QIcon(I('format-text-heading.png')) self.cfg_css_editor_toolbutton = QToolButton() self.cfg_css_editor_toolbutton.setIcon(self.css_editor_icon) self.cfg_css_editor_toolbutton.clicked.connect(self.edit_css) self.cfg_css_options_qgl.addWidget(self.cfg_css_editor_toolbutton, current_row, 0) self.cfg_css_editor_label = ClickableQLabel("Articles, Vocabulary") self.connect(self.cfg_css_editor_label, SIGNAL('clicked()'), self.edit_css) self.cfg_css_options_qgl.addWidget(self.cfg_css_editor_label, current_row, 1) """ # ~~~~~~~~ Create the Dropbox syncing group box ~~~~~~~~ self.cfg_dropbox_syncing_gb = QGroupBox(self) self.cfg_dropbox_syncing_gb.setTitle('Dropbox') self.column2_layout.addWidget(self.cfg_dropbox_syncing_gb) self.cfg_dropbox_syncing_qgl = QGridLayout(self.cfg_dropbox_syncing_gb) current_row = 0 # ++++++++ Syncing enabled checkbox ++++++++ self.dropbox_syncing_checkbox = QCheckBox('Enable Dropbox updates') self.dropbox_syncing_checkbox.setObjectName('dropbox_syncing') self.dropbox_syncing_checkbox.setToolTip('Refresh custom column content from Marvin metadata') self.cfg_dropbox_syncing_qgl.addWidget(self.dropbox_syncing_checkbox, current_row, 0, 1, 3) current_row += 1 # ++++++++ Dropbox folder picker ++++++++ self.dropbox_folder_icon = QIcon(os.path.join(self.resources_path, 'icons', 'dropbox.png')) self.cfg_dropbox_folder_toolbutton = QToolButton() self.cfg_dropbox_folder_toolbutton.setIcon(self.dropbox_folder_icon) self.cfg_dropbox_folder_toolbutton.setToolTip("Specify Dropbox folder location on your computer") self.cfg_dropbox_folder_toolbutton.clicked.connect(self.select_dropbox_folder) self.cfg_dropbox_syncing_qgl.addWidget(self.cfg_dropbox_folder_toolbutton, current_row, 1) # ++++++++ Dropbox location lineedit ++++++++ self.dropbox_location_lineedit = QLineEdit() self.dropbox_location_lineedit.setPlaceholderText("Dropbox folder location") self.cfg_dropbox_syncing_qgl.addWidget(self.dropbox_location_lineedit, current_row, 2) """ # ~~~~~~~~ Create the General options group box ~~~~~~~~ self.cfg_runtime_options_gb = QGroupBox(self) self.cfg_runtime_options_gb.setTitle('General options') self.column2_layout.addWidget(self.cfg_runtime_options_gb) self.cfg_runtime_options_qvl = QVBoxLayout(self.cfg_runtime_options_gb) # ++++++++ Temporary markers: Duplicates ++++++++ self.duplicate_markers_checkbox = QCheckBox('Apply temporary markers to duplicate books') self.duplicate_markers_checkbox.setObjectName('apply_markers_to_duplicates') self.duplicate_markers_checkbox.setToolTip('Books with identical content will be flagged in the Library window') self.cfg_runtime_options_qvl.addWidget(self.duplicate_markers_checkbox) # ++++++++ Temporary markers: Updated ++++++++ self.updated_markers_checkbox = QCheckBox('Apply temporary markers to books with updated content') self.updated_markers_checkbox.setObjectName('apply_markers_to_updated') self.updated_markers_checkbox.setToolTip('Books with updated content will be flagged in the Library window') self.cfg_runtime_options_qvl.addWidget(self.updated_markers_checkbox) # ++++++++ Auto refresh checkbox ++++++++ self.auto_refresh_checkbox = QCheckBox('Automatically refresh custom column content') self.auto_refresh_checkbox.setObjectName('auto_refresh_at_startup') self.auto_refresh_checkbox.setToolTip('Update calibre custom column when Marvin XD is opened') self.cfg_runtime_options_qvl.addWidget(self.auto_refresh_checkbox) # ++++++++ Progress as percentage checkbox ++++++++ self.reading_progress_checkbox = QCheckBox('Show reading progress as percentage') self.reading_progress_checkbox.setObjectName('show_progress_as_percentage') self.reading_progress_checkbox.setToolTip('Display percentage in Progress column') self.cfg_runtime_options_qvl.addWidget(self.reading_progress_checkbox) # ~~~~~~~~ Create the Debug options group box ~~~~~~~~ self.cfg_debug_options_gb = QGroupBox(self) self.cfg_debug_options_gb.setTitle('Debug options') self.column2_layout.addWidget(self.cfg_debug_options_gb) self.cfg_debug_options_qvl = QVBoxLayout(self.cfg_debug_options_gb) # ++++++++ Debug logging checkboxes ++++++++ self.debug_plugin_checkbox = QCheckBox('Enable debug logging for Marvin XD') self.debug_plugin_checkbox.setObjectName('debug_plugin_checkbox') self.debug_plugin_checkbox.setToolTip('Print plugin diagnostic messages to console') self.cfg_debug_options_qvl.addWidget(self.debug_plugin_checkbox) self.debug_libimobiledevice_checkbox = QCheckBox('Enable debug logging for libiMobileDevice') self.debug_libimobiledevice_checkbox.setObjectName('debug_libimobiledevice_checkbox') self.debug_libimobiledevice_checkbox.setToolTip('Print libiMobileDevice diagnostic messages to console') self.cfg_debug_options_qvl.addWidget(self.debug_libimobiledevice_checkbox) self.spacerItem2 = QSpacerItem(20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding) self.column2_layout.addItem(self.spacerItem2) # ~~~~~~~~ End of construction zone ~~~~~~~~ self.resize(self.sizeHint()) # ~~~~~~~~ Populate/restore config options ~~~~~~~~ # Annotations comboBox self.populate_annotations() self.populate_collections() self.populate_date_read() self.populate_locked() self.populate_progress() self.populate_read() self.populate_reading_list() self.populate_word_count() """ # Restore Dropbox settings, hook changes dropbox_syncing = self.prefs.get('dropbox_syncing', False) self.dropbox_syncing_checkbox.setChecked(dropbox_syncing) self.set_dropbox_syncing(dropbox_syncing) self.dropbox_syncing_checkbox.clicked.connect(partial(self.set_dropbox_syncing)) self.dropbox_location_lineedit.setText(self.prefs.get('dropbox_folder', '')) """ # Restore general settings self.duplicate_markers_checkbox.setChecked(self.prefs.get('apply_markers_to_duplicates', True)) self.updated_markers_checkbox.setChecked(self.prefs.get('apply_markers_to_updated', True)) self.auto_refresh_checkbox.setChecked(self.prefs.get('auto_refresh_at_startup', False)) self.reading_progress_checkbox.setChecked(self.prefs.get('show_progress_as_percentage', False)) # Restore debug settings, hook changes self.debug_plugin_checkbox.setChecked(self.prefs.get('debug_plugin', False)) self.debug_plugin_checkbox.stateChanged.connect(self.set_restart_required) self.debug_libimobiledevice_checkbox.setChecked(self.prefs.get('debug_libimobiledevice', False)) self.debug_libimobiledevice_checkbox.stateChanged.connect(self.set_restart_required) # Hook changes to Annotations comboBox # self.annotations_field_comboBox.currentIndexChanged.connect( # partial(self.save_combobox_setting, 'annotations_field_comboBox')) self.connect(self.annotations_field_comboBox, SIGNAL('currentIndexChanged(const QString &)'), self.annotations_destination_changed) # Launch the annotated_books_scanner field = get_cc_mapping('annotations', 'field', None) self.annotated_books_scanner = InventoryAnnotatedBooks(self.gui, field) self.connect(self.annotated_books_scanner, self.annotated_books_scanner.signal, self.inventory_complete) QTimer.singleShot(1, self.start_inventory) def annotations_destination_changed(self, qs_new_destination_name): ''' If the destination field changes, move all existing annotations from old to new ''' self._log_location(str(qs_new_destination_name)) #self._log("self.eligible_annotations_fields: %s" % self.eligible_annotations_fields) old_destination_field = get_cc_mapping('annotations', 'field', None) old_destination_name = get_cc_mapping('annotations', 'combobox', None) self._log("old_destination_field: %s" % old_destination_field) self._log("old_destination_name: %s" % old_destination_name) new_destination_name = unicode(qs_new_destination_name) self._log("new_destination_name: %s" % repr(new_destination_name)) if old_destination_name == new_destination_name: self._log_location("old_destination_name = new_destination_name, no changes") return if new_destination_name == '': self._log_location("annotations storage disabled") set_cc_mapping('annotations', field=None, combobox=new_destination_name) return new_destination_field = self.eligible_annotations_fields[new_destination_name] if existing_annotations(self.parent, old_destination_field): command = self.launch_new_destination_dialog(old_destination_name, new_destination_name) if command == 'move': set_cc_mapping('annotations', field=new_destination_field, combobox=new_destination_name) if self.annotated_books_scanner.isRunning(): self.annotated_books_scanner.wait() move_annotations(self, self.annotated_books_scanner.annotation_map, old_destination_field, new_destination_field) elif command == 'change': # Keep the updated destination field, but don't move annotations pass elif command == 'cancel': # Restore previous destination self.annotations_field_comboBox.blockSignals(True) old_index = self.annotations_field_comboBox.findText(old_destination_name) self.annotations_field_comboBox.setCurrentIndex(old_index) self.annotations_field_comboBox.blockSignals(False) else: # No existing annotations, just update prefs self._log("no existing annotations, updating destination to '{0}'".format(new_destination_name)) set_cc_mapping('annotations', field=new_destination_field, combobox=new_destination_name) def configure_appearance(self): ''' ''' self._log_location() appearance_settings = { 'appearance_css': default_elements, 'appearance_hr_checkbox': False, 'appearance_timestamp_format': default_timestamp } # Save, hash the original settings original_settings = {} osh = hashlib.md5() for setting in appearance_settings: original_settings[setting] = plugin_prefs.get(setting, appearance_settings[setting]) osh.update(repr(plugin_prefs.get(setting, appearance_settings[setting]))) # Display the Annotations appearance dialog aa = AnnotationsAppearance(self, self.annotations_icon, plugin_prefs) cancelled = False if aa.exec_(): # appearance_hr_checkbox and appearance_timestamp_format changed live to prefs during previews plugin_prefs.set('appearance_css', aa.elements_table.get_data()) # Generate a new hash nsh = hashlib.md5() for setting in appearance_settings: nsh.update(repr(plugin_prefs.get(setting, appearance_settings[setting]))) else: for setting in appearance_settings: plugin_prefs.set(setting, original_settings[setting]) nsh = osh # If there were changes, and there are existing annotations, # and there is an active Annotations field, offer to re-render field = get_cc_mapping('annotations', 'field', None) if osh.digest() != nsh.digest() and existing_annotations(self.parent, field): title = 'Update annotations?' msg = '<p>Update existing annotations to new appearance settings?</p>' d = MessageBox(MessageBox.QUESTION, title, msg, show_copy_button=False) self._log_location("QUESTION: %s" % msg) if d.exec_(): self._log_location("Updating existing annotations to modified appearance") # Wait for indexing to complete while not self.annotated_books_scanner.isFinished(): Application.processEvents() move_annotations(self, self.annotated_books_scanner.annotation_map, field, field, window_title="Updating appearance") def edit_css(self): ''' ''' self._log_location() from calibre_plugins.marvin_manager.book_status import dialog_resources_path klass = os.path.join(dialog_resources_path, 'css_editor.py') if os.path.exists(klass): sys.path.insert(0, dialog_resources_path) this_dc = importlib.import_module('css_editor') sys.path.remove(dialog_resources_path) dlg = this_dc.CSSEditorDialog(self, 'css_editor') dlg.initialize(self) dlg.exec_() def get_eligible_custom_fields(self, eligible_types=[], is_multiple=None): ''' Discover qualifying custom fields for eligible_types[] ''' #self._log_location(eligible_types) eligible_custom_fields = {} for cf in self.gui.current_db.custom_field_keys(): cft = self.gui.current_db.metadata_for_field(cf)['datatype'] cfn = self.gui.current_db.metadata_for_field(cf)['name'] cfim = self.gui.current_db.metadata_for_field(cf)['is_multiple'] #self._log("cf: %s cft: %s cfn: %s cfim: %s" % (cf, cft, cfn, cfim)) if cft in eligible_types: if is_multiple is not None: if bool(cfim) == is_multiple: eligible_custom_fields[cfn] = cf else: eligible_custom_fields[cfn] = cf return eligible_custom_fields def inventory_complete(self, msg): self._log_location(msg) def launch_cc_wizard(self, column_type): ''' ''' def _update_combo_box(comboBox, destination, previous): ''' ''' cb = getattr(self, comboBox) cb.blockSignals(True) all_items = [str(cb.itemText(i)) for i in range(cb.count())] if previous and previous in all_items: all_items.remove(previous) all_items.append(destination) cb.clear() cb.addItems(sorted(all_items, key=lambda s: s.lower())) # Select the new destination in the comboBox idx = cb.findText(destination) if idx > -1: cb.setCurrentIndex(idx) cb.blockSignals(False) from calibre_plugins.marvin_manager.book_status import dialog_resources_path klass = os.path.join(dialog_resources_path, 'cc_wizard.py') if os.path.exists(klass): #self._log("importing CC Wizard dialog from '%s'" % klass) sys.path.insert(0, dialog_resources_path) this_dc = importlib.import_module('cc_wizard') sys.path.remove(dialog_resources_path) dlg = this_dc.CustomColumnWizard(self, column_type, self.WIZARD_PROFILES[column_type], verbose=True) dlg.exec_() if dlg.modified_column: self._log("modified_column: %s" % dlg.modified_column) self.restart_required = True destination = dlg.modified_column['destination'] label = dlg.modified_column['label'] previous = dlg.modified_column['previous'] source = dlg.modified_column['source'] if source == "Annotations": _update_combo_box("annotations_field_comboBox", destination, previous) # Add/update the new destination so save_settings() can find it self.eligible_annotations_fields[destination] = label # Save manually in case user cancels set_cc_mapping('annotations', combobox=destination, field=label) elif source == 'Collections': _update_combo_box("collection_field_comboBox", destination, previous) # Add/update the new destination so save_settings() can find it self.eligible_collection_fields[destination] = label # Save manually in case user cancels set_cc_mapping('collections', combobox=destination, field=label) elif source == 'Last read': _update_combo_box("date_read_field_comboBox", destination, previous) # Add/update the new destination so save_settings() can find it self.eligible_date_read_fields[destination] = label # Save manually in case user cancels set_cc_mapping('date_read', combobox=destination, field=label) elif source == 'Locked': _update_combo_box("locked_field_comboBox", destination, previous) # Add/update the new destination so save_settings() can find it self.eligible_locked_fields[destination] = label # Save manually in case user cancels set_cc_mapping('locked', combobox=destination, field=label) elif source == "Progress": _update_combo_box("progress_field_comboBox", destination, previous) # Add/update the new destination so save_settings() can find it self.eligible_progress_fields[destination] = label # Save manually in case user cancels set_cc_mapping('progress', combobox=destination, field=label) elif source == "Read": _update_combo_box("read_field_comboBox", destination, previous) # Add/update the new destination so save_settings() can find it self.eligible_read_fields[destination] = label # Save manually in case user cancels set_cc_mapping('read', combobox=destination, field=label) elif source == "Reading list": _update_combo_box("reading_list_field_comboBox", destination, previous) # Add/update the new destination so save_settings() can find it self.eligible_reading_list_fields[destination] = label # Save manually in case user cancels set_cc_mapping('reading_list', combobox=destination, field=label) elif source == "Word count": _update_combo_box("word_count_field_comboBox", destination, previous) # Add/update the new destination so save_settings() can find it self.eligible_word_count_fields[destination] = label # Save manually in case user cancels set_cc_mapping('word_count', combobox=destination, field=label) else: self._log("ERROR: Can't import from '%s'" % klass) def launch_new_destination_dialog(self, old, new): ''' Return 'move', 'change' or 'cancel' ''' from calibre_plugins.marvin_manager.book_status import dialog_resources_path self._log_location() klass = os.path.join(dialog_resources_path, 'new_destination.py') if os.path.exists(klass): self._log("importing new destination dialog from '%s'" % klass) sys.path.insert(0, dialog_resources_path) this_dc = importlib.import_module('new_destination') sys.path.remove(dialog_resources_path) dlg = this_dc.NewDestinationDialog(self, old, new) dlg.exec_() return dlg.command def populate_annotations(self): datatype = self.WIZARD_PROFILES['Annotations']['datatype'] self.eligible_annotations_fields = self.get_eligible_custom_fields([datatype]) self.annotations_field_comboBox.addItems(['']) ecf = sorted(self.eligible_annotations_fields.keys(), key=lambda s: s.lower()) self.annotations_field_comboBox.addItems(ecf) # Retrieve stored value existing = get_cc_mapping('annotations', 'combobox') if existing: ci = self.annotations_field_comboBox.findText(existing) self.annotations_field_comboBox.setCurrentIndex(ci) def populate_collections(self): datatype = self.WIZARD_PROFILES['Collections']['datatype'] self.eligible_collection_fields = self.get_eligible_custom_fields([datatype], is_multiple=True) self.collection_field_comboBox.addItems(['']) ecf = sorted(self.eligible_collection_fields.keys(), key=lambda s: s.lower()) self.collection_field_comboBox.addItems(ecf) # Retrieve stored value existing = get_cc_mapping('collections', 'combobox') if existing: ci = self.collection_field_comboBox.findText(existing) self.collection_field_comboBox.setCurrentIndex(ci) def populate_date_read(self): #self.eligible_date_read_fields = self.get_eligible_custom_fields(['datetime']) datatype = self.WIZARD_PROFILES['Last read']['datatype'] self.eligible_date_read_fields = self.get_eligible_custom_fields([datatype]) self.date_read_field_comboBox.addItems(['']) ecf = sorted(self.eligible_date_read_fields.keys(), key=lambda s: s.lower()) self.date_read_field_comboBox.addItems(ecf) # Retrieve stored value existing = get_cc_mapping('date_read', 'combobox') if existing: ci = self.date_read_field_comboBox.findText(existing) self.date_read_field_comboBox.setCurrentIndex(ci) def populate_locked(self): datatype = self.WIZARD_PROFILES['Locked']['datatype'] self.eligible_locked_fields = self.get_eligible_custom_fields([datatype]) self.locked_field_comboBox.addItems(['']) ecf = sorted(self.eligible_locked_fields.keys(), key=lambda s: s.lower()) self.locked_field_comboBox.addItems(ecf) # Retrieve stored value existing = get_cc_mapping('locked', 'combobox') if existing: ci = self.locked_field_comboBox.findText(existing) self.locked_field_comboBox.setCurrentIndex(ci) def populate_progress(self): #self.eligible_progress_fields = self.get_eligible_custom_fields(['float']) datatype = self.WIZARD_PROFILES['Progress']['datatype'] self.eligible_progress_fields = self.get_eligible_custom_fields([datatype]) self.progress_field_comboBox.addItems(['']) ecf = sorted(self.eligible_progress_fields.keys(), key=lambda s: s.lower()) self.progress_field_comboBox.addItems(ecf) # Retrieve stored value existing = get_cc_mapping('progress', 'combobox') if existing: ci = self.progress_field_comboBox.findText(existing) self.progress_field_comboBox.setCurrentIndex(ci) def populate_read(self): datatype = self.WIZARD_PROFILES['Read']['datatype'] self.eligible_read_fields = self.get_eligible_custom_fields([datatype]) self.read_field_comboBox.addItems(['']) ecf = sorted(self.eligible_read_fields.keys(), key=lambda s: s.lower()) self.read_field_comboBox.addItems(ecf) # Retrieve stored value existing = get_cc_mapping('read', 'combobox') if existing: ci = self.read_field_comboBox.findText(existing) self.read_field_comboBox.setCurrentIndex(ci) def populate_reading_list(self): datatype = self.WIZARD_PROFILES['Reading list']['datatype'] self.eligible_reading_list_fields = self.get_eligible_custom_fields([datatype]) self.reading_list_field_comboBox.addItems(['']) ecf = sorted(self.eligible_reading_list_fields.keys(), key=lambda s: s.lower()) self.reading_list_field_comboBox.addItems(ecf) # Retrieve stored value existing = get_cc_mapping('reading_list', 'combobox') if existing: ci = self.reading_list_field_comboBox.findText(existing) self.reading_list_field_comboBox.setCurrentIndex(ci) def populate_word_count(self): #self.eligible_word_count_fields = self.get_eligible_custom_fields(['int']) datatype = self.WIZARD_PROFILES['Word count']['datatype'] self.eligible_word_count_fields = self.get_eligible_custom_fields([datatype]) self.word_count_field_comboBox.addItems(['']) ecf = sorted(self.eligible_word_count_fields.keys(), key=lambda s: s.lower()) self.word_count_field_comboBox.addItems(ecf) # Retrieve stored value existing = get_cc_mapping('word_count', 'combobox') if existing: ci = self.word_count_field_comboBox.findText(existing) self.word_count_field_comboBox.setCurrentIndex(ci) """ def select_dropbox_folder(self): ''' ''' self._log_location() dropbox_location = QFileDialog.getExistingDirectory( self, "Dropbox folder", os.path.expanduser("~"), QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks) self.dropbox_location_lineedit.setText(unicode(dropbox_location)) def set_dropbox_syncing(self, state): ''' Called when checkbox changes state, or when restoring state Set enabled state of Dropbox folder picker to match ''' self.cfg_dropbox_folder_toolbutton.setEnabled(state) self.dropbox_location_lineedit.setEnabled(state) """ def set_restart_required(self, state): ''' Set restart_required flag to show show dialog when closing dialog ''' self.restart_required = True """ def save_combobox_setting(self, cb, index): ''' Apply changes immediately ''' cf = str(getattr(self, cb).currentText()) self._log_location("%s => %s" % (cb, repr(cf))) if cb == 'annotations_field_comboBox': field = None if cf: field = self.eligible_annotations_fields[cf] set_cc_mapping('annotations', combobox=cf, field=field) """ def save_settings(self): self._log_location() # Annotations field cf = unicode(self.annotations_field_comboBox.currentText()) field = None if cf: field = self.eligible_annotations_fields[cf] set_cc_mapping('annotations', combobox=cf, field=field) # Collections field cf = unicode(self.collection_field_comboBox.currentText()) field = None if cf: field = self.eligible_collection_fields[cf] set_cc_mapping('collections', combobox=cf, field=field) # Date read field cf = unicode(self.date_read_field_comboBox.currentText()) field = None if cf: field = self.eligible_date_read_fields[cf] set_cc_mapping('date_read', combobox=cf, field=field) # Locked field cf = unicode(self.locked_field_comboBox.currentText()) field = None if cf: field = self.eligible_locked_fields[cf] set_cc_mapping('locked', combobox=cf, field=field) # Progress field cf = unicode(self.progress_field_comboBox.currentText()) field = None if cf: field = self.eligible_progress_fields[cf] set_cc_mapping('progress', combobox=cf, field=field) # Read field cf = unicode(self.read_field_comboBox.currentText()) field = None if cf: field = self.eligible_read_fields[cf] set_cc_mapping('read', combobox=cf, field=field) # Reading list field cf = unicode(self.reading_list_field_comboBox.currentText()) field = None if cf: field = self.eligible_reading_list_fields[cf] set_cc_mapping('reading_list', combobox=cf, field=field) # Word count field cf = unicode(self.word_count_field_comboBox.currentText()) field = None if cf: field = self.eligible_word_count_fields[cf] set_cc_mapping('word_count', combobox=cf, field=field) ''' # Save Dropbox settings self.prefs.set('dropbox_syncing', self.dropbox_syncing_checkbox.isChecked()) self.prefs.set('dropbox_folder', unicode(self.dropbox_location_lineedit.text())) ''' # Save general settings self.prefs.set('apply_markers_to_duplicates', self.duplicate_markers_checkbox.isChecked()) self.prefs.set('apply_markers_to_updated', self.updated_markers_checkbox.isChecked()) self.prefs.set('auto_refresh_at_startup', self.auto_refresh_checkbox.isChecked()) self.prefs.set('show_progress_as_percentage', self.reading_progress_checkbox.isChecked()) # Save debug settings self.prefs.set('debug_plugin', self.debug_plugin_checkbox.isChecked()) self.prefs.set('debug_libimobiledevice', self.debug_libimobiledevice_checkbox.isChecked()) # If restart needed, inform user if self.restart_required: do_restart = show_restart_warning('Restart calibre for the changes to be applied.', parent=self.gui) if do_restart: self.gui.quit(restart=True) def start_inventory(self): self._log_location() self.annotated_books_scanner.start()
def __init__(self, win): self.xmlfile = os.path.join(_sponsordir, 'sponsors.xml') self.win = win self.needToAsk = False self.downloadSponsors = False threading.Thread.__init__(self) if not self.refreshWanted(): return if env.prefs[sponsor_permanent_permission_prefs_key]: # We have a permanent answer so no need for a dialog if env.prefs[sponsor_download_permission_prefs_key]: self.downloadSponsors = True return self.needToAsk = True QDialog.__init__(self, None) self.setObjectName("Permission") self.setModal(True) #This fixes bug 2296. Mitigates bug 2297 layout = QGridLayout() self.setLayout(layout) layout.setMargin(0) layout.setSpacing(0) layout.setObjectName("PermissionLayout") self.text_browser = QTextBrowser(self) self.text_browser.setObjectName("text_browser") layout.addWidget(self.text_browser,0,0,1,4) self.text_browser.setMinimumSize(400, 80) self.setWindowTitle('May we use your network connection?') self.setWindowIcon(geticon('ui/border/MainWindow.png')) self.text_browser.setPlainText(self.text) self.accept_button = QPushButton(self) self.accept_button.setObjectName("accept_button") self.accept_button.setText("Always OK") self.accept_once_button = QPushButton(self) self.accept_once_button.setObjectName("accept_once_button") self.accept_once_button.setText("OK now") self.decline_once_button = QPushButton(self) self.decline_once_button.setObjectName("decline_once_button") self.decline_once_button.setText("Not now") self.decline_always_button = QPushButton(self) self.decline_always_button.setObjectName("decline_always_button") self.decline_always_button.setText("Never") layout.addWidget(self.accept_button,1,0) layout.addWidget(self.accept_once_button,1,1) layout.addWidget(self.decline_once_button,1,2) layout.addWidget(self.decline_always_button,1,3) self.connect(self.accept_button,SIGNAL("clicked()"),self.acceptAlways) self.connect(self.accept_once_button,SIGNAL("clicked()"),self.acceptJustOnce) self.connect(self.decline_once_button,SIGNAL("clicked()"),self.declineJustOnce) self.connect(self.decline_always_button,SIGNAL("clicked()"),self.declineAlways)
def __init__(self, parent = None, desc = None, name = None, modal = 0, fl = 0, env = None, type = "QDialog"): if env is None: import foundation.env as env # this is a little weird... probably it'll be ok, and logically it seems correct. self.desc = desc self.typ = type if type == "QDialog": QDialog.__init__(self,parent,name,modal,fl) elif type == "QTextEdit": QTextEdit.__init__(self, parent, name) elif type == "QFrame": QFrame.__init__(self,parent,name) else: print "don't know about type == %r" % (type,) self.image1 = QPixmap() self.image1.loadFromData(image1_data,"PNG") # should be: title_icon #### self.image3 = QPixmap() self.image3.loadFromData(image3_data,"PNG") self.image4 = QPixmap() self.image4.loadFromData(image4_data,"PNG") self.image5 = QPixmap() self.image5.loadFromData(image5_data,"PNG") self.image6 = QPixmap() self.image6.loadFromData(image6_data,"PNG") self.image7 = QPixmap() self.image7.loadFromData(image7_data,"PNG") self.image0 = QPixmap(image0_data) # should be: border_icon #### self.image2 = QPixmap(image2_data) # should be: sponsor_pixmap #### try: ####@@@@ title_icon_name = self.desc.options.get('title_icon') border_icon_name = self.desc.options.get('border_icon') if title_icon_name: self.image1 = imagename_to_pixmap(title_icon_name) ###@@@ pass icon_path ###@@@ import imagename_to_pixmap or use env function # or let that func itself be an arg, or have an env arg for it ###e rename it icon_name_to_pixmap, or find_icon? (the latter only if it's ok if it returns an iconset) ###e use iconset instead? if border_icon_name: self.image0 = imagename_to_pixmap(border_icon_name) except: print_compact_traceback("bug in icon-setting code, using fallback icons: ") pass if not name: self.setName("parameter_dialog_or_frame") ### ###k guess this will need: if type == 'QDialog' self.setIcon(self.image0) # should be: border_icon #### nanotube_dialogLayout = QVBoxLayout(self,0,0,"nanotube_dialogLayout") self.heading_frame = QFrame(self,"heading_frame") self.heading_frame.setPaletteBackgroundColor(QColor(122,122,122)) self.heading_frame.setFrameShape(QFrame.NoFrame) self.heading_frame.setFrameShadow(QFrame.Plain) heading_frameLayout = QHBoxLayout(self.heading_frame,0,3,"heading_frameLayout") self.heading_pixmap = QLabel(self.heading_frame,"heading_pixmap") self.heading_pixmap.setSizePolicy(QSizePolicy(QSizePolicy.Fixed,QSizePolicy.Fixed,0,0,self.heading_pixmap.sizePolicy().hasHeightForWidth())) self.heading_pixmap.setPixmap(self.image1) # should be: title_icon #### self.heading_pixmap.setScaledContents(1) heading_frameLayout.addWidget(self.heading_pixmap) self.heading_label = QLabel(self.heading_frame,"heading_label") self.heading_label.setPaletteForegroundColor(QColor(255,255,255)) heading_label_font = QFont(self.heading_label.font()) heading_label_font.setPointSize(12) heading_label_font.setBold(1) self.heading_label.setFont(heading_label_font) heading_frameLayout.addWidget(self.heading_label) nanotube_dialogLayout.addWidget(self.heading_frame) self.body_frame = QFrame(self,"body_frame") self.body_frame.setFrameShape(QFrame.StyledPanel) self.body_frame.setFrameShadow(QFrame.Raised) body_frameLayout = QVBoxLayout(self.body_frame,3,3,"body_frameLayout") self.sponsor_frame = QFrame(self.body_frame,"sponsor_frame") self.sponsor_frame.setPaletteBackgroundColor(QColor(255,255,255)) self.sponsor_frame.setFrameShape(QFrame.StyledPanel) self.sponsor_frame.setFrameShadow(QFrame.Raised) sponsor_frameLayout = QHBoxLayout(self.sponsor_frame,0,0,"sponsor_frameLayout") self.sponsor_btn = QPushButton(self.sponsor_frame,"sponsor_btn") self.sponsor_btn.setAutoDefault(0) #bruce 060703 bugfix self.sponsor_btn.setSizePolicy(QSizePolicy(QSizePolicy.Preferred,QSizePolicy.Preferred,0,0,self.sponsor_btn.sizePolicy().hasHeightForWidth())) self.sponsor_btn.setPaletteBackgroundColor(QColor(255,255,255)) self.sponsor_btn.setPixmap(self.image2) # should be: sponsor_pixmap #### [also we'll need to support >1 sponsor] self.sponsor_btn.setFlat(1) sponsor_frameLayout.addWidget(self.sponsor_btn) body_frameLayout.addWidget(self.sponsor_frame) layout59 = QHBoxLayout(None,0,6,"layout59") left_spacer = QSpacerItem(20,20,QSizePolicy.Expanding,QSizePolicy.Minimum) layout59.addItem(left_spacer) self.done_btn = QToolButton(self.body_frame,"done_btn") self.done_btn.setIcon(QIcon(self.image3)) layout59.addWidget(self.done_btn) self.abort_btn = QToolButton(self.body_frame,"abort_btn") self.abort_btn.setIcon(QIcon(self.image4)) layout59.addWidget(self.abort_btn) self.preview_btn = QToolButton(self.body_frame,"preview_btn") self.preview_btn.setIcon(QIcon(self.image5)) layout59.addWidget(self.preview_btn) self.whatsthis_btn = QToolButton(self.body_frame,"whatsthis_btn") self.whatsthis_btn.setIcon(QIcon(self.image6)) layout59.addWidget(self.whatsthis_btn) right_spacer = QSpacerItem(20,20,QSizePolicy.Expanding,QSizePolicy.Minimum) layout59.addItem(right_spacer) body_frameLayout.addLayout(layout59) self.groups = [] self.param_getters = {} # map from param name to get-function (which gets current value out of its widget or controller) for group_desc in self.desc.kids('group'): # == start parameters_grpbox ### this will differ for Windows style header_refs = [] # keep python refcounted refs to all objects we make (at least the ones pyuic stored in self attrs) self.parameters_grpbox = QGroupBox(self.body_frame,"parameters_grpbox") self.parameters_grpbox.setFrameShape(QGroupBox.StyledPanel) self.parameters_grpbox.setFrameShadow(QGroupBox.Sunken) self.parameters_grpbox.setMargin(0) self.parameters_grpbox.setColumnLayout(0,Qt.Vertical) self.parameters_grpbox.layout().setSpacing(1) self.parameters_grpbox.layout().setMargin(4) parameters_grpboxLayout = QVBoxLayout(self.parameters_grpbox.layout()) parameters_grpboxLayout.setAlignment(Qt.AlignTop) layout20 = QHBoxLayout(None,0,6,"layout20") self.nt_parameters_grpbtn = QPushButton(self.parameters_grpbox,"nt_parameters_grpbtn") self.nt_parameters_grpbtn.setSizePolicy(QSizePolicy(QSizePolicy.Minimum,QSizePolicy.Fixed,0,0,self.nt_parameters_grpbtn.sizePolicy().hasHeightForWidth())) self.nt_parameters_grpbtn.setMaximumSize(QSize(16,16)) self.nt_parameters_grpbtn.setAutoDefault(0) self.nt_parameters_grpbtn.setIcon(QIcon(self.image7)) ### not always right, but doesn't matter self.nt_parameters_grpbtn.setFlat(1) layout20.addWidget(self.nt_parameters_grpbtn) self.parameters_grpbox_label = QLabel(self.parameters_grpbox,"parameters_grpbox_label") self.parameters_grpbox_label.setSizePolicy(QSizePolicy(QSizePolicy.Preferred,QSizePolicy.Minimum,0,0,self.parameters_grpbox_label.sizePolicy().hasHeightForWidth())) self.parameters_grpbox_label.setAlignment(QLabel.AlignVCenter) layout20.addWidget(self.parameters_grpbox_label) gbx_spacer1 = QSpacerItem(67,16,QSizePolicy.Expanding,QSizePolicy.Minimum) layout20.addItem(gbx_spacer1) parameters_grpboxLayout.addLayout(layout20) nt_parameters_body_layout = QGridLayout(None,1,1,0,6,"nt_parameters_body_layout") ### what is 6 -- is it related to number of items??? # is it 6 in all the ones we got, but that could be a designer error so i better look it up sometime. # == start its kids # will use from above: self.parameters_grpbox, nt_parameters_body_layout nextrow = 0 # which row of the QGridLayout to start filling next (loop variable) hidethese = [] # set of objects to hide or show, when this group is closed or opened for param in group_desc.kids('parameter'): # param (a group subobj desc) is always a parameter, but we already plan to extend this beyond that, # so we redundantly test for this here. getter = None paramname = None # set these for use by uniform code at the end (e.g. for tooltips) editfield = None label = None if param.isa('parameter'): label = QLabel(self.parameters_grpbox,"members_label") label.setAlignment(QLabel.AlignVCenter | QLabel.AlignRight) nt_parameters_body_layout.addWidget(label,nextrow,0) hidethese.append(label) thisrow = nextrow nextrow += 1 #e following should be known in a place that knows the input language, not here paramname = param.options.get('name') or (param.args and param.args[0]) or "?" paramlabel = param.options.get('label') or paramname ##e wrong, label "" or none ought to be possible # QtGui.QApplication.translate(self.__class__.__name__, "xyz") label.setText(QtGui.QApplication.translate(self.__class__.__name__, paramlabel)) if param.isa('parameter', widget = 'combobox', type = ('str',None)): self.members_combox = QComboBox(0,self.parameters_grpbox,"members_combox") ###k what's 0? editfield = self.members_combox #### it probably needs a handler class, and then that could do this setup self.members_combox.clear() default = param.options.get('default', None) # None is not equal to any string thewidgetkid = param.kids('widget')[-1] # kluge; need to think what the desc method for this should be for item in thewidgetkid.kids('item'): itemval = item.args[0] itemtext = itemval self.members_combox.insertItem(QtGui.QApplication.translate(self.__class__.__name__, itemtext)) #k __tr ok?? if itemval == default: #k or itemtext? pass ##k i find no setItem in our py code, so not sure yet what to do for this. nt_parameters_body_layout.addWidget(self.members_combox,thisrow,1) hidethese.append(self.members_combox) getter = (lambda combobox = self.members_combox: str(combobox.currentText())) ##e due to __tr or non-str values, it might be better to use currentIndex and look it up in a table # (though whether __tr is good here might depend on what it's used for) elif param.isa('parameter', widget = ('lineedit', None), type = ('str',None)): # this covers explicit str|lineedit, and 3 default cases str, lineedit, neither. # (i.e. if you say parameter and nothing else, it's str lineedit by default.) self.length_linedit = QLineEdit(self.parameters_grpbox,"length_linedit") editfield = self.length_linedit nt_parameters_body_layout.addWidget(self.length_linedit,thisrow,1) hidethese.append(self.length_linedit) default = str(param.options.get('default', "")) self.length_linedit.setText(QtGui.QApplication.translate(self.__class__.__name__, default)) # __tr ok? getter = (lambda lineedit = self.length_linedit: str(lineedit.text())) elif param.isa('parameter', widget = ('lineedit', None), type = 'float'): self.length_linedit = QLineEdit(self.parameters_grpbox,"length_linedit") editfield = self.length_linedit nt_parameters_body_layout.addWidget(self.length_linedit,thisrow,1) hidethese.append(self.length_linedit) controller = FloatLineeditController_Qt(self, param, self.length_linedit) header_refs.append(controller) getter = controller.get_value elif param.isa('parameter', widget = ('spinbox', None), type = 'int') or \ param.isa('parameter', widget = ('spinbox'), type = None): self.chirality_N_spinbox = QSpinBox(self.parameters_grpbox,"chirality_N_spinbox") # was chirality_m_spinbox, now chirality_N_spinbox editfield = self.chirality_N_spinbox ### seems like Qt defaults for min and max are 0,100 -- way too small a range! if param.options.has_key('min') or 1: self.chirality_N_spinbox.setMinimum(param.options.get('min', -999999999)) # was 0 if param.options.has_key('max') or 1: self.chirality_N_spinbox.setMaximum(param.options.get('max', +999999999)) # wasn't in egcode, but needed self.chirality_N_spinbox.setValue(param.options.get('default', 0)) # was 5 ##e note: i suspect this default 0 should come from something that knows this desc grammar. suffix = param.options.get('suffix', '') if suffix: self.chirality_N_spinbox.setSuffix(QtGui.QApplication.translate(self.__class__.__name__, suffix)) else: self.chirality_N_spinbox.setSuffix(QString.null) # probably not needed nt_parameters_body_layout.addWidget(self.chirality_N_spinbox,thisrow,1) hidethese.append(self.chirality_N_spinbox) getter = self.chirality_N_spinbox.value # note: it also has .text, which includes suffix else: print "didn't match:",param ###e improve this # things done the same way for all kinds of param-editing widgets if 1: #bruce 060703 moved this down here, as bugfix # set tooltip (same one for editfield and label) tooltip = param.options.get('tooltip', '') ###e do it for more kinds of params; share the code somehow; do it in controller, or setup-aid? ###k QToolTip appropriateness; tooltip option might be entirely untested if tooltip and label: QToolTip.add(label, QtGui.QApplication.translate(self.__class__.__name__, tooltip)) if tooltip and editfield: QToolTip.add(editfield, QtGui.QApplication.translate(self.__class__.__name__, tooltip)) ##k ok?? review once not all params have same-row labels. if getter and paramname and paramname != '?': self.param_getters[paramname] = getter ### also bind these params to actions... continue # next param header_refs.extend( [self.parameters_grpbox, self.nt_parameters_grpbtn, self.parameters_grpbox_label] ) # now create the logic/control object for the group group = CollapsibleGroupController_Qt(self, group_desc, header_refs, hidethese, self.nt_parameters_grpbtn) ### maybe ask env for the class to use for this? self.groups.append(group) ### needed?? only for scanning the params, AFAIK -- oh, and to maintain a python refcount. # from languageChange: if 1: # i don't know if these are needed: self.parameters_grpbox.setTitle(QString.null) self.nt_parameters_grpbtn.setText(QString.null) self.parameters_grpbox_label.setText(QtGui.QApplication.translate(self.__class__.__name__, group_desc.args[0])) # was "Nanotube Parameters" ##e note that it's questionable in the syntax design for this property of a group (overall group label) # to be in that position (desc arg 0). # == end its kids parameters_grpboxLayout.addLayout(nt_parameters_body_layout) body_frameLayout.addWidget(self.parameters_grpbox) # == end parameters groupbox continue # next group nanotube_dialogLayout.addWidget(self.body_frame) spacer14 = QSpacerItem(20,20,QSizePolicy.Minimum,QSizePolicy.Expanding) nanotube_dialogLayout.addItem(spacer14) layout42 = QHBoxLayout(None,4,6,"layout42") btm_spacer = QSpacerItem(59,20,QSizePolicy.Expanding,QSizePolicy.Minimum) layout42.addItem(btm_spacer) self.cancel_btn = QPushButton(self,"cancel_btn") self.cancel_btn.setAutoDefault(0) #bruce 060703 bugfix layout42.addWidget(self.cancel_btn) self.ok_btn = QPushButton(self,"ok_btn") self.ok_btn.setAutoDefault(0) #bruce 060703 bugfix layout42.addWidget(self.ok_btn) nanotube_dialogLayout.addLayout(layout42) self.languageChange() self.resize(QSize(246,618).expandedTo(self.minimumSizeHint())) ### this size will need to be adjusted (guess -- it's only place overall size is set) qt4todo('self.clearWState(Qt.WState_Polished)') ## self.connect(self.nt_parameters_grpbtn,SIGNAL("clicked()"),self.toggle_nt_parameters_grpbtn) #### # new: for button, methodname in ((self.sponsor_btn, 'do_sponsor_btn'), #e generalize to more than one sponsor button (self.done_btn, 'do_done_btn'), (self.abort_btn, 'do_abort_btn'), (self.preview_btn, 'do_preview_btn'), (self.whatsthis_btn, 'do_whatsthis_btn'), (self.cancel_btn, 'do_cancel_btn'), (self.ok_btn, 'do_ok_btn')): if hasattr(self, methodname): self.connect(button, SIGNAL("clicked()"), getattr(self, methodname)) return
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)