class Config(QDialog): ''' Configuration dialog for single book conversion. If accepted, has the following important attributes output_format - Output format (without a leading .) input_format - Input format (without a leading .) opf_path - Path to OPF file with user specified metadata cover_path - Path to user specified cover (can be None) recommendations - A pickled list of 3 tuples in the same format as the recommendations member of the Input/Output plugins. ''' def __init__(self, parent, db, book_id, preferred_input_format=None, preferred_output_format=None): QDialog.__init__(self, parent) self.setupUi() self.opt_individual_saved_settings.setVisible(False) self.db, self.book_id = db, book_id self.setup_input_output_formats(self.db, self.book_id, preferred_input_format, preferred_output_format) self.setup_pipeline() self.input_formats.currentIndexChanged[native_string_type].connect( self.setup_pipeline) self.output_formats.currentIndexChanged[native_string_type].connect( self.setup_pipeline) self.groups.setSpacing(5) self.groups.activated[(QModelIndex)].connect(self.show_pane) self.groups.clicked[(QModelIndex)].connect(self.show_pane) self.groups.entered[(QModelIndex)].connect(self.show_group_help) rb = self.buttonBox.button(self.buttonBox.RestoreDefaults) rb.setText(_('Restore &defaults')) rb.clicked.connect(self.restore_defaults) self.groups.setMouseTracking(True) geom = gprefs.get('convert_single_dialog_geom', None) if geom: self.restoreGeometry(geom) else: self.resize(self.sizeHint()) def setupUi(self): self.setObjectName("Dialog") self.resize(1024, 700) self.setWindowIcon(QIcon(I('convert.png'))) self.gridLayout = QGridLayout(self) self.gridLayout.setObjectName("gridLayout") self.horizontalLayout = QHBoxLayout() self.horizontalLayout.setObjectName("horizontalLayout") self.input_label = QLabel(self) self.input_label.setObjectName("input_label") self.horizontalLayout.addWidget(self.input_label) self.input_formats = QComboBox(self) self.input_formats.setSizeAdjustPolicy( QComboBox.AdjustToMinimumContentsLengthWithIcon) self.input_formats.setMinimumContentsLength(5) self.input_formats.setObjectName("input_formats") self.horizontalLayout.addWidget(self.input_formats) self.opt_individual_saved_settings = QCheckBox(self) self.opt_individual_saved_settings.setObjectName( "opt_individual_saved_settings") self.horizontalLayout.addWidget(self.opt_individual_saved_settings) spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem) self.label_2 = QLabel(self) self.label_2.setObjectName("label_2") self.horizontalLayout.addWidget(self.label_2) self.output_formats = QComboBox(self) self.output_formats.setSizeAdjustPolicy( QComboBox.AdjustToMinimumContentsLengthWithIcon) self.output_formats.setMinimumContentsLength(5) self.output_formats.setObjectName("output_formats") self.horizontalLayout.addWidget(self.output_formats) self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 2) self.groups = QListView(self) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(1) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.groups.sizePolicy().hasHeightForWidth()) self.groups.setSizePolicy(sizePolicy) self.groups.setTabKeyNavigation(True) self.groups.setIconSize(QSize(48, 48)) self.groups.setWordWrap(True) self.groups.setObjectName("groups") self.gridLayout.addWidget(self.groups, 1, 0, 3, 1) self.scrollArea = QScrollArea(self) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(4) sizePolicy.setVerticalStretch(10) sizePolicy.setHeightForWidth( self.scrollArea.sizePolicy().hasHeightForWidth()) self.scrollArea.setSizePolicy(sizePolicy) self.scrollArea.setFrameShape(QFrame.NoFrame) self.scrollArea.setLineWidth(0) self.scrollArea.setWidgetResizable(True) self.scrollArea.setObjectName("scrollArea") self.scrollAreaWidgetContents = QWidget() self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 810, 494)) self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents") self.verticalLayout_3 = QVBoxLayout(self.scrollAreaWidgetContents) self.verticalLayout_3.setContentsMargins(0, 0, 0, 0) self.verticalLayout_3.setObjectName("verticalLayout_3") self.stack = QStackedWidget(self.scrollAreaWidgetContents) sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.stack.sizePolicy().hasHeightForWidth()) self.stack.setSizePolicy(sizePolicy) self.stack.setObjectName("stack") self.page = QWidget() self.page.setObjectName("page") self.stack.addWidget(self.page) self.page_2 = QWidget() self.page_2.setObjectName("page_2") self.stack.addWidget(self.page_2) self.verticalLayout_3.addWidget(self.stack) self.scrollArea.setWidget(self.scrollAreaWidgetContents) self.gridLayout.addWidget(self.scrollArea, 1, 1, 1, 1) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok | QDialogButtonBox.RestoreDefaults) self.buttonBox.setObjectName("buttonBox") self.gridLayout.addWidget(self.buttonBox, 3, 1, 1, 1) self.help = QTextEdit(self) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.help.sizePolicy().hasHeightForWidth()) self.help.setSizePolicy(sizePolicy) self.help.setMaximumHeight(80) self.help.setObjectName("help") self.gridLayout.addWidget(self.help, 2, 1, 1, 1) self.input_label.setBuddy(self.input_formats) self.label_2.setBuddy(self.output_formats) self.input_label.setText(_("&Input format:")) self.opt_individual_saved_settings.setText( _("Use &saved conversion settings for individual books")) self.label_2.setText(_("&Output format:")) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) def sizeHint(self): desktop = QCoreApplication.instance().desktop() geom = desktop.availableGeometry(self) nh, nw = max(300, geom.height() - 100), max(400, geom.width() - 70) return QSize(nw, nh) def restore_defaults(self): delete_specifics(self.db, self.book_id) self.setup_pipeline() @property def input_format(self): return unicode_type(self.input_formats.currentText()).lower() @property def output_format(self): return unicode_type(self.output_formats.currentText()).lower() @property def manually_fine_tune_toc(self): for i in range(self.stack.count()): w = self.stack.widget(i) if hasattr(w, 'manually_fine_tune_toc'): return w.manually_fine_tune_toc.isChecked() def setup_pipeline(self, *args): oidx = self.groups.currentIndex().row() input_format = self.input_format output_format = self.output_format self.plumber = create_dummy_plumber(input_format, output_format) def widget_factory(cls): return cls(self.stack, self.plumber.get_option_by_name, self.plumber.get_option_help, self.db, self.book_id) self.mw = widget_factory(MetadataWidget) self.setWindowTitle( _('Convert') + ' ' + unicode_type(self.mw.title.text())) lf = widget_factory(LookAndFeelWidget) hw = widget_factory(HeuristicsWidget) sr = widget_factory(SearchAndReplaceWidget) ps = widget_factory(PageSetupWidget) sd = widget_factory(StructureDetectionWidget) toc = widget_factory(TOCWidget) from calibre.gui2.actions.toc_edit import SUPPORTED toc.manually_fine_tune_toc.setVisible( output_format.upper() in SUPPORTED) debug = widget_factory(DebugWidget) output_widget = self.plumber.output_plugin.gui_configuration_widget( self.stack, self.plumber.get_option_by_name, self.plumber.get_option_help, self.db, self.book_id) input_widget = self.plumber.input_plugin.gui_configuration_widget( self.stack, self.plumber.get_option_by_name, self.plumber.get_option_help, self.db, self.book_id) while True: c = self.stack.currentWidget() if not c: break self.stack.removeWidget(c) widgets = [self.mw, lf, hw, ps, sd, toc, sr] if input_widget is not None: widgets.append(input_widget) if output_widget is not None: widgets.append(output_widget) widgets.append(debug) for w in widgets: self.stack.addWidget(w) w.set_help_signal.connect(self.help.setPlainText) self._groups_model = GroupModel(widgets) self.groups.setModel(self._groups_model) idx = oidx if -1 < oidx < self._groups_model.rowCount() else 0 self.groups.setCurrentIndex(self._groups_model.index(idx)) self.stack.setCurrentIndex(idx) try: shutil.rmtree(self.plumber.archive_input_tdir, ignore_errors=True) except: pass def setup_input_output_formats(self, db, book_id, preferred_input_format, preferred_output_format): if preferred_output_format: preferred_output_format = preferred_output_format.upper() output_formats = get_output_formats(preferred_output_format) input_format, input_formats = get_input_format_for_book( db, book_id, preferred_input_format) preferred_output_format = preferred_output_format if \ preferred_output_format in output_formats else \ sort_formats_by_preference(output_formats, [prefs['output_format']])[0] self.input_formats.addItems( (unicode_type(x.upper()) for x in input_formats)) self.output_formats.addItems( (unicode_type(x.upper()) for x in output_formats)) self.input_formats.setCurrentIndex(input_formats.index(input_format)) self.output_formats.setCurrentIndex( output_formats.index(preferred_output_format)) def show_pane(self, index): self.stack.setCurrentIndex(index.row()) def accept(self): recs = GuiRecommendations() for w in self._groups_model.widgets: if not w.pre_commit_check(): return x = w.commit(save_defaults=False) recs.update(x) self.opf_file, self.cover_file = self.mw.opf_file, self.mw.cover_file self._recommendations = recs if self.db is not None: recs['gui_preferred_input_format'] = self.input_format save_specifics(self.db, self.book_id, recs) self.break_cycles() QDialog.accept(self) def reject(self): self.break_cycles() QDialog.reject(self) def done(self, r): if self.isVisible(): gprefs['convert_single_dialog_geom'] = \ bytearray(self.saveGeometry()) return QDialog.done(self, r) def break_cycles(self): for i in range(self.stack.count()): w = self.stack.widget(i) w.break_cycles() @property def recommendations(self): recs = [(k, v, OptionRecommendation.HIGH) for k, v in self._recommendations.items()] return recs def show_group_help(self, index): widget = self._groups_model.widgets[index.row()] self.help.setPlainText(widget.HELP)
class Preferences(QDialog): run_wizard_requested = pyqtSignal() def __init__(self, gui, initial_plugin=None, close_after_initial=False): QDialog.__init__(self, gui) self.gui = gui self.must_restart = False self.do_restart = False self.committed = False self.close_after_initial = close_after_initial self.resize(930, 720) nh, nw = min_available_height() - 25, available_width() - 10 if nh < 0: nh = 800 if nw < 0: nw = 600 nh = min(self.height(), nh) nw = min(self.width(), nw) self.resize(nw, nh) geom = gprefs.get('preferences dialog geometry', None) if geom is not None: self.restoreGeometry(geom) # Center if islinux: self.move(gui.rect().center() - self.rect().center()) self.setWindowModality(Qt.ApplicationModal) self.setWindowTitle(__appname__ + ' - ' + _('Preferences')) self.setWindowIcon(QIcon(I('config.png'))) self.l = l = QVBoxLayout(self) self.stack = QStackedWidget(self) self.bb = QDialogButtonBox(QDialogButtonBox.Close | QDialogButtonBox.Apply | QDialogButtonBox.Discard | QDialogButtonBox.RestoreDefaults) self.bb.button(self.bb.Apply).clicked.connect(self.accept) self.bb.button(self.bb.Discard).clicked.connect(self.reject) self.bb.button(self.bb.RestoreDefaults).setIcon( QIcon(I('clear_left.png'))) self.bb.button(self.bb.RestoreDefaults).clicked.connect( self.restore_defaults) self.wizard_button = self.bb.addButton(_('Run Welcome &wizard'), self.bb.ActionRole) self.wizard_button.setIcon(QIcon(I('wizard.png'))) self.wizard_button.clicked.connect(self.run_wizard, type=Qt.QueuedConnection) self.wizard_button.setAutoDefault(False) self.bb.rejected.connect(self.reject) self.browser = Browser(self) self.browser.show_plugin.connect(self.show_plugin) self.stack.addWidget(self.browser) self.scroll_area = QScrollArea(self) self.stack.addWidget(self.scroll_area) self.scroll_area.setWidgetResizable(True) self.setContextMenuPolicy(Qt.NoContextMenu) self.title_bar = TitleBar(self) for ac, tt in [(self.bb.Apply, _('Save changes')), (self.bb.Discard, _('Cancel and return to overview'))]: self.bb.button(ac).setToolTip(tt) l.addWidget(self.title_bar), l.addWidget(self.stack), l.addWidget( self.bb) if initial_plugin is not None: category, name = initial_plugin[:2] plugin = get_plugin(category, name) if plugin is not None: self.show_plugin(plugin) if len(initial_plugin) > 2: w = self.findChild(QWidget, initial_plugin[2]) if w is not None: for c in self.showing_widget.children(): if isinstance(c, QTabWidget): idx = c.indexOf(w) if idx > -1: c.setCurrentIndex(idx) break else: self.hide_plugin() def event(self, ev): if isinstance(ev, QStatusTipEvent): msg = re.sub(r'</?[a-z1-6]+>', ' ', ev.tip()) self.title_bar.show_msg(msg) return QDialog.event(self, ev) def run_wizard(self): self.run_wizard_requested.emit() self.accept() def set_tooltips_for_labels(self): def process_child(child): for g in child.children(): if isinstance(g, QLabel): buddy = g.buddy() if buddy is not None and hasattr(buddy, 'toolTip'): htext = unicode_type(buddy.toolTip()).strip() etext = unicode_type(g.toolTip()).strip() if htext and not etext: g.setToolTip(htext) g.setWhatsThis(htext) else: process_child(g) process_child(self.showing_widget) def show_plugin(self, plugin): self.showing_widget = plugin.create_widget(self.scroll_area) self.showing_widget.genesis(self.gui) self.showing_widget.initialize() self.set_tooltips_for_labels() self.scroll_area.setWidget(self.showing_widget) self.stack.setCurrentIndex(1) self.showing_widget.show() self.setWindowTitle(__appname__ + ' - ' + _('Preferences') + ' - ' + plugin.gui_name) self.showing_widget.restart_now.connect(self.restart_now) self.title_bar.show_plugin(plugin) self.setWindowIcon(QIcon(plugin.icon)) self.bb.button(self.bb.Close).setVisible(False) self.wizard_button.setVisible(False) for button in (self.bb.Apply, self.bb.RestoreDefaults, self.bb.Discard): button = self.bb.button(button) button.setVisible(True) self.bb.button(self.bb.Apply).setEnabled(False) self.bb.button(self.bb.Apply).setDefault(False), self.bb.button( self.bb.Apply).setDefault(True) self.bb.button(self.bb.RestoreDefaults).setEnabled( self.showing_widget.supports_restoring_to_defaults) self.bb.button(self.bb.RestoreDefaults).setToolTip( self.showing_widget.restore_defaults_desc if self.showing_widget. supports_restoring_to_defaults else ( _('Restoring to defaults not supported for') + ' ' + plugin.gui_name)) self.bb.button(self.bb.RestoreDefaults).setText(_('Restore &defaults')) self.showing_widget.changed_signal.connect(self.changed_signal) def changed_signal(self): b = self.bb.button(self.bb.Apply) b.setEnabled(True) def hide_plugin(self): for sig in 'changed_signal restart_now'.split(): try: getattr(self.showing_widget, sig).disconnect(getattr(self, sig)) except Exception: pass self.showing_widget = QWidget(self.scroll_area) self.scroll_area.setWidget(self.showing_widget) self.setWindowTitle(__appname__ + ' - ' + _('Preferences')) self.stack.setCurrentIndex(0) self.title_bar.show_plugin() self.setWindowIcon(QIcon(I('config.png'))) for button in (self.bb.Apply, self.bb.RestoreDefaults, self.bb.Discard): button = self.bb.button(button) button.setVisible(False) self.bb.button(self.bb.Close).setVisible(True) self.bb.button(self.bb.Close).setDefault(False), self.bb.button( self.bb.Close).setDefault(True) self.wizard_button.setVisible(True) def restart_now(self): try: self.showing_widget.commit() except AbortCommit: return self.do_restart = True self.hide_plugin() self.accept() def commit(self, *args): must_restart = self.showing_widget.commit() rc = self.showing_widget.restart_critical self.committed = True do_restart = False if must_restart: self.must_restart = True msg = _('Some of the changes you made require a restart.' ' Please restart calibre as soon as possible.') if rc: msg = _('The changes you have made require calibre be ' 'restarted immediately. You will not be allowed to ' 'set any more preferences, until you restart.') do_restart = show_restart_warning(msg, parent=self) self.showing_widget.refresh_gui(self.gui) if do_restart: self.do_restart = True return self.close_after_initial or (must_restart and rc) or do_restart def restore_defaults(self, *args): self.showing_widget.restore_defaults() def on_shutdown(self): gprefs.set('preferences dialog geometry', bytearray(self.saveGeometry())) if self.committed: self.gui.must_restart_before_config = self.must_restart self.gui.tags_view.recount() self.gui.create_device_menu() self.gui.set_device_menu_items_state( bool(self.gui.device_connected)) self.gui.bars_manager.apply_settings() self.gui.bars_manager.update_bars() self.gui.build_context_menus() def accept(self): if self.stack.currentIndex() == 0: self.on_shutdown() return QDialog.accept(self) try: close = self.commit() except AbortCommit: return if close: self.on_shutdown() return QDialog.accept(self) self.hide_plugin() def reject(self): if self.stack.currentIndex() == 0 or self.close_after_initial: self.on_shutdown() return QDialog.reject(self) self.hide_plugin()
class FullFetch(QDialog): # {{{ def __init__(self, current_cover=None, parent=None): QDialog.__init__(self, parent) self.current_cover = current_cover self.log = Log() self.book = self.cover_pixmap = None self.setWindowTitle(_('Downloading metadata...')) self.setWindowIcon(QIcon(I('download-metadata.png'))) self.stack = QStackedWidget() self.l = l = QVBoxLayout() self.setLayout(l) l.addWidget(self.stack) self.bb = QDialogButtonBox(QDialogButtonBox.Cancel | QDialogButtonBox.Ok) self.h = h = QHBoxLayout() l.addLayout(h) self.bb.rejected.connect(self.reject) self.bb.accepted.connect(self.accept) self.ok_button = self.bb.button(self.bb.Ok) self.ok_button.setEnabled(False) self.ok_button.clicked.connect(self.ok_clicked) self.prev_button = pb = QPushButton(QIcon(I('back.png')), _('&Back'), self) pb.clicked.connect(self.back_clicked) pb.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.log_button = self.bb.addButton(_('&View log'), self.bb.ActionRole) self.log_button.clicked.connect(self.view_log) self.log_button.setIcon(QIcon(I('debug.png'))) self.prev_button.setVisible(False) h.addWidget(self.prev_button), h.addWidget(self.bb) self.identify_widget = IdentifyWidget(self.log, self) self.identify_widget.rejected.connect(self.reject) self.identify_widget.results_found.connect(self.identify_results_found) self.identify_widget.book_selected.connect(self.book_selected) self.stack.addWidget(self.identify_widget) self.covers_widget = CoversWidget(self.log, self.current_cover, parent=self) self.covers_widget.chosen.connect(self.ok_clicked) self.stack.addWidget(self.covers_widget) self.resize(850, 600) geom = gprefs.get('metadata_single_gui_geom', None) if geom is not None and geom: self.restoreGeometry(geom) self.finished.connect(self.cleanup) def view_log(self): self._lv = LogViewer(self.log, self) def book_selected(self, book, caches): self.prev_button.setVisible(True) self.book = book self.stack.setCurrentIndex(1) self.log('\n\n') self.covers_widget.start(book, self.current_cover, self.title, self.authors, caches) self.ok_button.setFocus() def back_clicked(self): self.prev_button.setVisible(False) self.stack.setCurrentIndex(0) self.covers_widget.cancel() self.covers_widget.reset_covers() def accept(self): # Prevent the usual dialog accept mechanisms from working gprefs['metadata_single_gui_geom'] = bytearray(self.saveGeometry()) if DEBUG_DIALOG: if self.stack.currentIndex() == 2: return QDialog.accept(self) else: if self.stack.currentIndex() == 1: return QDialog.accept(self) def reject(self): gprefs['metadata_single_gui_geom'] = bytearray(self.saveGeometry()) self.identify_widget.cancel() self.covers_widget.cancel() return QDialog.reject(self) def cleanup(self): self.covers_widget.cleanup() def identify_results_found(self): self.ok_button.setEnabled(True) def next_clicked(self, *args): gprefs['metadata_single_gui_geom'] = bytearray(self.saveGeometry()) self.identify_widget.get_result() def ok_clicked(self, *args): self.cover_pixmap = self.covers_widget.cover_pixmap() if self.stack.currentIndex() == 0: self.next_clicked() return if DEBUG_DIALOG: if self.cover_pixmap is not None: self.w = QLabel() self.w.setPixmap(self.cover_pixmap) self.stack.addWidget(self.w) self.stack.setCurrentIndex(2) else: QDialog.accept(self) def start(self, title=None, authors=None, identifiers={}): self.title, self.authors = title, authors self.identify_widget.start(title=title, authors=authors, identifiers=identifiers) return self.exec_()
class FullFetch(QDialog): # {{{ def __init__(self, current_cover=None, parent=None): QDialog.__init__(self, parent) self.current_cover = current_cover self.log = Log() self.book = self.cover_pixmap = None self.setWindowTitle(_('Downloading metadata...')) self.setWindowIcon(QIcon(I('download-metadata.png'))) self.stack = QStackedWidget() self.l = l = QVBoxLayout() self.setLayout(l) l.addWidget(self.stack) self.bb = QDialogButtonBox(QDialogButtonBox.Cancel|QDialogButtonBox.Ok) self.h = h = QHBoxLayout() l.addLayout(h) self.bb.rejected.connect(self.reject) self.bb.accepted.connect(self.accept) self.ok_button = self.bb.button(self.bb.Ok) self.ok_button.setEnabled(False) self.ok_button.clicked.connect(self.ok_clicked) self.prev_button = pb = QPushButton(QIcon(I('back.png')), _('&Back'), self) pb.clicked.connect(self.back_clicked) pb.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.log_button = self.bb.addButton(_('&View log'), self.bb.ActionRole) self.log_button.clicked.connect(self.view_log) self.log_button.setIcon(QIcon(I('debug.png'))) self.prev_button.setVisible(False) h.addWidget(self.prev_button), h.addWidget(self.bb) self.identify_widget = IdentifyWidget(self.log, self) self.identify_widget.rejected.connect(self.reject) self.identify_widget.results_found.connect(self.identify_results_found) self.identify_widget.book_selected.connect(self.book_selected) self.stack.addWidget(self.identify_widget) self.covers_widget = CoversWidget(self.log, self.current_cover, parent=self) self.covers_widget.chosen.connect(self.ok_clicked) self.stack.addWidget(self.covers_widget) self.resize(850, 600) geom = gprefs.get('metadata_single_gui_geom', None) if geom is not None and geom: self.restoreGeometry(geom) self.finished.connect(self.cleanup) def view_log(self): self._lv = LogViewer(self.log, self) def book_selected(self, book, caches): self.prev_button.setVisible(True) self.book = book self.stack.setCurrentIndex(1) self.log('\n\n') self.covers_widget.start(book, self.current_cover, self.title, self.authors, caches) self.ok_button.setFocus() def back_clicked(self): self.prev_button.setVisible(False) self.stack.setCurrentIndex(0) self.covers_widget.cancel() self.covers_widget.reset_covers() def accept(self): # Prevent the usual dialog accept mechanisms from working gprefs['metadata_single_gui_geom'] = bytearray(self.saveGeometry()) if DEBUG_DIALOG: if self.stack.currentIndex() == 2: return QDialog.accept(self) else: if self.stack.currentIndex() == 1: return QDialog.accept(self) def reject(self): gprefs['metadata_single_gui_geom'] = bytearray(self.saveGeometry()) self.identify_widget.cancel() self.covers_widget.cancel() return QDialog.reject(self) def cleanup(self): self.covers_widget.cleanup() def identify_results_found(self): self.ok_button.setEnabled(True) def next_clicked(self, *args): gprefs['metadata_single_gui_geom'] = bytearray(self.saveGeometry()) self.identify_widget.get_result() def ok_clicked(self, *args): self.cover_pixmap = self.covers_widget.cover_pixmap() if self.stack.currentIndex() == 0: self.next_clicked() return if DEBUG_DIALOG: if self.cover_pixmap is not None: self.w = QLabel() self.w.setPixmap(self.cover_pixmap) self.stack.addWidget(self.w) self.stack.setCurrentIndex(2) else: QDialog.accept(self) def start(self, title=None, authors=None, identifiers={}): self.title, self.authors = title, authors self.identify_widget.start(title=title, authors=authors, identifiers=identifiers) return self.exec_()
class Preferences(QMainWindow): run_wizard_requested = pyqtSignal() def __init__(self, gui, initial_plugin=None, close_after_initial=False): QMainWindow.__init__(self, gui) self.gui = gui self.must_restart = False self.committed = False self.close_after_initial = close_after_initial self.resize(930, 720) nh, nw = min_available_height() - 25, available_width() - 10 if nh < 0: nh = 800 if nw < 0: nw = 600 nh = min(self.height(), nh) nw = min(self.width(), nw) self.resize(nw, nh) self.esc_action = QAction(self) self.addAction(self.esc_action) self.esc_action.setShortcut(QKeySequence(Qt.Key_Escape)) self.esc_action.triggered.connect(self.esc) geom = gprefs.get('preferences_window_geometry', None) if geom is not None: self.restoreGeometry(geom) # Center if islinux: self.move(gui.rect().center() - self.rect().center()) self.setWindowModality(Qt.WindowModal) self.setWindowTitle(__appname__ + ' - ' + _('Preferences')) self.setWindowIcon(QIcon(I('config.png'))) self.status_bar = StatusBar(self) self.setStatusBar(self.status_bar) self.stack = QStackedWidget(self) self.cw = QWidget(self) self.cw.setLayout(QVBoxLayout()) self.cw.layout().addWidget(self.stack) self.bb = QDialogButtonBox(QDialogButtonBox.Close) self.wizard_button = self.bb.addButton(_('Run welcome wizard'), self.bb.ActionRole) self.wizard_button.setIcon(QIcon(I('wizard.png'))) self.wizard_button.clicked.connect(self.run_wizard, type=Qt.QueuedConnection) self.cw.layout().addWidget(self.bb) self.bb.button(self.bb.Close).setDefault(True) self.bb.rejected.connect(self.close, type=Qt.QueuedConnection) self.setCentralWidget(self.cw) self.browser = Browser(self) self.browser.show_plugin.connect(self.show_plugin) self.stack.addWidget(self.browser) self.scroll_area = QScrollArea(self) self.stack.addWidget(self.scroll_area) self.scroll_area.setWidgetResizable(True) self.setContextMenuPolicy(Qt.NoContextMenu) self.bar = QToolBar(self) self.addToolBar(self.bar) self.bar.setVisible(False) self.bar.setIconSize(QSize(ICON_SIZE, ICON_SIZE)) self.bar.setMovable(False) self.bar.setFloatable(False) self.bar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.apply_action = self.bar.addAction(QIcon(I('ok.png')), _('&Apply'), self.commit) self.cancel_action = self.bar.addAction(QIcon(I('window-close.png')), _('&Cancel'), self.cancel) self.bar_title = BarTitle(self.bar) self.bar.addWidget(self.bar_title) self.restore_action = self.bar.addAction(QIcon(I('clear_left.png')), _('Restore &defaults'), self.restore_defaults) for ac, tt in [('apply', _('Save changes')), ('cancel', _('Cancel and return to overview'))]: ac = getattr(self, ac + '_action') ac.setToolTip(tt) ac.setWhatsThis(tt) ac.setStatusTip(tt) for ch in self.bar.children(): if isinstance(ch, QToolButton): ch.setCursor(Qt.PointingHandCursor) ch.setAutoRaise(True) self.stack.setCurrentIndex(0) if initial_plugin is not None: category, name = initial_plugin plugin = get_plugin(category, name) if plugin is not None: self.show_plugin(plugin) def event(self, ev): if ev.type() == ev.StatusTip: msg = re.sub(r'</?[a-z1-6]+>', ' ', ev.tip()) ev = QStatusTipEvent(msg) return QMainWindow.event(self, ev) def run_wizard(self): self.close() self.run_wizard_requested.emit() def set_tooltips_for_labels(self): def process_child(child): for g in child.children(): if isinstance(g, QLabel): buddy = g.buddy() if buddy is not None and hasattr(buddy, 'toolTip'): htext = unicode(buddy.toolTip()).strip() etext = unicode(g.toolTip()).strip() if htext and not etext: g.setToolTip(htext) g.setWhatsThis(htext) else: process_child(g) process_child(self.showing_widget) def show_plugin(self, plugin): self.showing_widget = plugin.create_widget(self.scroll_area) self.showing_widget.genesis(self.gui) self.showing_widget.initialize() self.set_tooltips_for_labels() self.scroll_area.setWidget(self.showing_widget) self.stack.setCurrentIndex(1) self.showing_widget.show() self.setWindowTitle(__appname__ + ' - ' + _('Preferences') + ' - ' + plugin.gui_name) self.apply_action.setEnabled(False) self.showing_widget.changed_signal.connect( lambda: self.apply_action.setEnabled(True)) self.showing_widget.restart_now.connect(self.restart_now) self.restore_action.setEnabled( self.showing_widget.supports_restoring_to_defaults) tt = self.showing_widget.restore_defaults_desc if not self.restore_action.isEnabled(): tt = _('Restoring to defaults not supported for') + ' ' + \ plugin.gui_name self.restore_action.setToolTip(textwrap.fill(tt)) self.restore_action.setWhatsThis(textwrap.fill(tt)) self.restore_action.setStatusTip(tt) self.bar_title.show_plugin(plugin) self.setWindowIcon(QIcon(plugin.icon)) self.bar.setVisible(True) self.bb.setVisible(False) def hide_plugin(self): self.showing_widget = QWidget(self.scroll_area) self.scroll_area.setWidget(self.showing_widget) self.setWindowTitle(__appname__ + ' - ' + _('Preferences')) self.bar.setVisible(False) self.stack.setCurrentIndex(0) self.setWindowIcon(QIcon(I('config.png'))) self.bb.setVisible(True) def esc(self, *args): if self.stack.currentIndex() == 1: self.cancel() elif self.stack.currentIndex() == 0: self.close() def restart_now(self): try: self.showing_widget.commit() except AbortCommit: return self.hide_plugin() self.close() self.gui.quit(restart=True) def commit(self, *args): try: must_restart = self.showing_widget.commit() except AbortCommit: return rc = self.showing_widget.restart_critical self.committed = True do_restart = False if must_restart: self.must_restart = True msg = _('Some of the changes you made require a restart.' ' Please restart calibre as soon as possible.') if rc: msg = _('The changes you have made require calibre be ' 'restarted immediately. You will not be allowed to ' 'set any more preferences, until you restart.') do_restart = show_restart_warning(msg, parent=self) self.showing_widget.refresh_gui(self.gui) self.hide_plugin() if self.close_after_initial or (must_restart and rc) or do_restart: self.close() if do_restart: self.gui.quit(restart=True) def cancel(self, *args): if self.close_after_initial: self.close() else: self.hide_plugin() def restore_defaults(self, *args): self.showing_widget.restore_defaults() def closeEvent(self, *args): gprefs.set('preferences_window_geometry', bytearray(self.saveGeometry())) if self.committed: self.gui.must_restart_before_config = self.must_restart self.gui.tags_view.recount() self.gui.create_device_menu() self.gui.set_device_menu_items_state( bool(self.gui.device_connected)) self.gui.bars_manager.apply_settings() self.gui.bars_manager.update_bars() self.gui.build_context_menus() return QMainWindow.closeEvent(self, *args)
class Preferences(QDialog): run_wizard_requested = pyqtSignal() def __init__(self, gui, initial_plugin=None, close_after_initial=False): QDialog.__init__(self, gui) self.gui = gui self.must_restart = False self.do_restart = False self.committed = False self.close_after_initial = close_after_initial self.resize(930, 720) nh, nw = min_available_height()-25, available_width()-10 if nh < 0: nh = 800 if nw < 0: nw = 600 nh = min(self.height(), nh) nw = min(self.width(), nw) self.resize(nw, nh) geom = gprefs.get('preferences dialog geometry', None) if geom is not None: self.restoreGeometry(geom) # Center if islinux: self.move(gui.rect().center() - self.rect().center()) self.setWindowModality(Qt.ApplicationModal) self.setWindowTitle(__appname__ + ' - ' + _('Preferences')) self.setWindowIcon(QIcon(I('config.png'))) self.l = l = QVBoxLayout(self) self.stack = QStackedWidget(self) self.bb = QDialogButtonBox(QDialogButtonBox.Close | QDialogButtonBox.Apply | QDialogButtonBox.Discard | QDialogButtonBox.RestoreDefaults) self.bb.button(self.bb.Apply).clicked.connect(self.accept) self.bb.button(self.bb.Discard).clicked.connect(self.reject) self.bb.button(self.bb.RestoreDefaults).setIcon(QIcon(I('clear_left.png'))) self.bb.button(self.bb.RestoreDefaults).clicked.connect(self.restore_defaults) self.wizard_button = self.bb.addButton(_('Run Welcome &wizard'), self.bb.ActionRole) self.wizard_button.setIcon(QIcon(I('wizard.png'))) self.wizard_button.clicked.connect(self.run_wizard, type=Qt.QueuedConnection) self.wizard_button.setAutoDefault(False) self.bb.rejected.connect(self.reject) self.browser = Browser(self) self.browser.show_plugin.connect(self.show_plugin) self.stack.addWidget(self.browser) self.scroll_area = QScrollArea(self) self.stack.addWidget(self.scroll_area) self.scroll_area.setWidgetResizable(True) self.setContextMenuPolicy(Qt.NoContextMenu) self.title_bar = TitleBar(self) for ac, tt in [(self.bb.Apply, _('Save changes')), (self.bb.Discard, _('Cancel and return to overview'))]: self.bb.button(ac).setToolTip(tt) l.addWidget(self.title_bar), l.addWidget(self.stack), l.addWidget(self.bb) if initial_plugin is not None: category, name = initial_plugin[:2] plugin = get_plugin(category, name) if plugin is not None: self.show_plugin(plugin) if len(initial_plugin) > 2: w = self.findChild(QWidget, initial_plugin[2]) if w is not None: for c in self.showing_widget.children(): if isinstance(c, QTabWidget): idx = c.indexOf(w) if idx > -1: c.setCurrentIndex(idx) break else: self.hide_plugin() def event(self, ev): if isinstance(ev, QStatusTipEvent): msg = re.sub(r'</?[a-z1-6]+>', ' ', ev.tip()) self.title_bar.show_msg(msg) return QDialog.event(self, ev) def run_wizard(self): self.run_wizard_requested.emit() self.accept() def set_tooltips_for_labels(self): def process_child(child): for g in child.children(): if isinstance(g, QLabel): buddy = g.buddy() if buddy is not None and hasattr(buddy, 'toolTip'): htext = unicode_type(buddy.toolTip()).strip() etext = unicode_type(g.toolTip()).strip() if htext and not etext: g.setToolTip(htext) g.setWhatsThis(htext) else: process_child(g) process_child(self.showing_widget) def show_plugin(self, plugin): self.showing_widget = plugin.create_widget(self.scroll_area) self.showing_widget.genesis(self.gui) self.showing_widget.initialize() self.set_tooltips_for_labels() self.scroll_area.setWidget(self.showing_widget) self.stack.setCurrentIndex(1) self.showing_widget.show() self.setWindowTitle(__appname__ + ' - ' + _('Preferences') + ' - ' + plugin.gui_name) self.showing_widget.restart_now.connect(self.restart_now) self.title_bar.show_plugin(plugin) self.setWindowIcon(QIcon(plugin.icon)) self.bb.button(self.bb.Close).setVisible(False) self.wizard_button.setVisible(False) for button in (self.bb.Apply, self.bb.RestoreDefaults, self.bb.Discard): button = self.bb.button(button) button.setVisible(True) self.bb.button(self.bb.Apply).setEnabled(False) self.bb.button(self.bb.Apply).setDefault(False), self.bb.button(self.bb.Apply).setDefault(True) self.bb.button(self.bb.RestoreDefaults).setEnabled(self.showing_widget.supports_restoring_to_defaults) self.bb.button(self.bb.RestoreDefaults).setToolTip( self.showing_widget.restore_defaults_desc if self.showing_widget.supports_restoring_to_defaults else (_('Restoring to defaults not supported for') + ' ' + plugin.gui_name)) self.bb.button(self.bb.RestoreDefaults).setText(_('Restore &defaults')) self.showing_widget.changed_signal.connect(self.changed_signal) def changed_signal(self): b = self.bb.button(self.bb.Apply) b.setEnabled(True) def hide_plugin(self): for sig in 'changed_signal restart_now'.split(): try: getattr(self.showing_widget, sig).disconnect(getattr(self, sig)) except Exception: pass self.showing_widget = QWidget(self.scroll_area) self.scroll_area.setWidget(self.showing_widget) self.setWindowTitle(__appname__ + ' - ' + _('Preferences')) self.stack.setCurrentIndex(0) self.title_bar.show_plugin() self.setWindowIcon(QIcon(I('config.png'))) for button in (self.bb.Apply, self.bb.RestoreDefaults, self.bb.Discard): button = self.bb.button(button) button.setVisible(False) self.bb.button(self.bb.Close).setVisible(True) self.bb.button(self.bb.Close).setDefault(False), self.bb.button(self.bb.Close).setDefault(True) self.wizard_button.setVisible(True) def restart_now(self): try: self.showing_widget.commit() except AbortCommit: return self.do_restart = True self.hide_plugin() self.accept() def commit(self, *args): must_restart = self.showing_widget.commit() rc = self.showing_widget.restart_critical self.committed = True do_restart = False if must_restart: self.must_restart = True msg = _('Some of the changes you made require a restart.' ' Please restart calibre as soon as possible.') if rc: msg = _('The changes you have made require calibre be ' 'restarted immediately. You will not be allowed to ' 'set any more preferences, until you restart.') do_restart = show_restart_warning(msg, parent=self) self.showing_widget.refresh_gui(self.gui) if do_restart: self.do_restart = True return self.close_after_initial or (must_restart and rc) or do_restart def restore_defaults(self, *args): self.showing_widget.restore_defaults() def on_shutdown(self): gprefs.set('preferences dialog geometry', bytearray(self.saveGeometry())) if self.committed: self.gui.must_restart_before_config = self.must_restart self.gui.tags_view.recount() self.gui.create_device_menu() self.gui.set_device_menu_items_state(bool(self.gui.device_connected)) self.gui.bars_manager.apply_settings() self.gui.bars_manager.update_bars() self.gui.build_context_menus() def accept(self): if self.stack.currentIndex() == 0: self.on_shutdown() return QDialog.accept(self) try: close = self.commit() except AbortCommit: return if close: self.on_shutdown() return QDialog.accept(self) self.hide_plugin() def reject(self): if self.stack.currentIndex() == 0 or self.close_after_initial: self.on_shutdown() return QDialog.reject(self) self.hide_plugin()
class Preferences(QMainWindow): run_wizard_requested = pyqtSignal() def __init__(self, gui, initial_plugin=None, close_after_initial=False): QMainWindow.__init__(self, gui) self.gui = gui self.must_restart = False self.committed = False self.close_after_initial = close_after_initial self.resize(930, 720) nh, nw = min_available_height()-25, available_width()-10 if nh < 0: nh = 800 if nw < 0: nw = 600 nh = min(self.height(), nh) nw = min(self.width(), nw) self.resize(nw, nh) self.esc_action = QAction(self) self.addAction(self.esc_action) self.esc_action.setShortcut(QKeySequence(Qt.Key_Escape)) self.esc_action.triggered.connect(self.esc) geom = gprefs.get('preferences_window_geometry', None) if geom is not None: self.restoreGeometry(geom) # Center if islinux: self.move(gui.rect().center() - self.rect().center()) self.setWindowModality(Qt.WindowModal) self.setWindowTitle(__appname__ + ' - ' + _('Preferences')) self.setWindowIcon(QIcon(I('config.png'))) self.status_bar = StatusBar(self) self.setStatusBar(self.status_bar) self.stack = QStackedWidget(self) self.cw = QWidget(self) self.cw.setLayout(QVBoxLayout()) self.cw.layout().addWidget(self.stack) self.bb = QDialogButtonBox(QDialogButtonBox.Close) self.wizard_button = self.bb.addButton(_('Run welcome wizard'), self.bb.ActionRole) self.wizard_button.setIcon(QIcon(I('wizard.png'))) self.wizard_button.clicked.connect(self.run_wizard, type=Qt.QueuedConnection) self.cw.layout().addWidget(self.bb) self.bb.button(self.bb.Close).setDefault(True) self.bb.rejected.connect(self.close, type=Qt.QueuedConnection) self.setCentralWidget(self.cw) self.browser = Browser(self) self.browser.show_plugin.connect(self.show_plugin) self.stack.addWidget(self.browser) self.scroll_area = QScrollArea(self) self.stack.addWidget(self.scroll_area) self.scroll_area.setWidgetResizable(True) self.setContextMenuPolicy(Qt.NoContextMenu) self.bar = QToolBar(self) self.addToolBar(self.bar) self.bar.setVisible(False) self.bar.setIconSize(QSize(ICON_SIZE, ICON_SIZE)) self.bar.setMovable(False) self.bar.setFloatable(False) self.bar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.apply_action = self.bar.addAction(QIcon(I('ok.png')), _('&Apply'), self.commit) self.cancel_action = self.bar.addAction(QIcon(I('window-close.png')), _('&Cancel'), self.cancel) self.bar_title = BarTitle(self.bar) self.bar.addWidget(self.bar_title) self.restore_action = self.bar.addAction(QIcon(I('clear_left.png')), _('Restore &defaults'), self.restore_defaults) for ac, tt in [('apply', _('Save changes')), ('cancel', _('Cancel and return to overview'))]: ac = getattr(self, ac+'_action') ac.setToolTip(tt) ac.setWhatsThis(tt) ac.setStatusTip(tt) for ch in self.bar.children(): if isinstance(ch, QToolButton): ch.setCursor(Qt.PointingHandCursor) ch.setAutoRaise(True) self.stack.setCurrentIndex(0) if initial_plugin is not None: category, name = initial_plugin plugin = get_plugin(category, name) if plugin is not None: self.show_plugin(plugin) def run_wizard(self): self.close() self.run_wizard_requested.emit() def set_tooltips_for_labels(self): def process_child(child): for g in child.children(): if isinstance(g, QLabel): buddy = g.buddy() if buddy is not None and hasattr(buddy, 'toolTip'): htext = unicode(buddy.toolTip()).strip() etext = unicode(g.toolTip()).strip() if htext and not etext: g.setToolTip(htext) g.setWhatsThis(htext) else: process_child(g) process_child(self.showing_widget) def show_plugin(self, plugin): self.showing_widget = plugin.create_widget(self.scroll_area) self.showing_widget.genesis(self.gui) self.showing_widget.initialize() self.set_tooltips_for_labels() self.scroll_area.setWidget(self.showing_widget) self.stack.setCurrentIndex(1) self.showing_widget.show() self.setWindowTitle(__appname__ + ' - ' + _('Preferences') + ' - ' + plugin.gui_name) self.apply_action.setEnabled(False) self.showing_widget.changed_signal.connect(lambda : self.apply_action.setEnabled(True)) self.showing_widget.restart_now.connect(self.restart_now) self.restore_action.setEnabled(self.showing_widget.supports_restoring_to_defaults) tt = self.showing_widget.restore_defaults_desc if not self.restore_action.isEnabled(): tt = _('Restoring to defaults not supported for') + ' ' + \ plugin.gui_name self.restore_action.setToolTip(textwrap.fill(tt)) self.restore_action.setWhatsThis(textwrap.fill(tt)) self.restore_action.setStatusTip(tt) self.bar_title.show_plugin(plugin) self.setWindowIcon(QIcon(plugin.icon)) self.bar.setVisible(True) self.bb.setVisible(False) def hide_plugin(self): self.showing_widget = QWidget(self.scroll_area) self.scroll_area.setWidget(self.showing_widget) self.setWindowTitle(__appname__ + ' - ' + _('Preferences')) self.bar.setVisible(False) self.stack.setCurrentIndex(0) self.setWindowIcon(QIcon(I('config.png'))) self.bb.setVisible(True) def esc(self, *args): if self.stack.currentIndex() == 1: self.cancel() elif self.stack.currentIndex() == 0: self.close() def restart_now(self): try: self.showing_widget.commit() except AbortCommit: return self.hide_plugin() self.close() self.gui.quit(restart=True) def commit(self, *args): try: must_restart = self.showing_widget.commit() except AbortCommit: return rc = self.showing_widget.restart_critical self.committed = True do_restart = False if must_restart: self.must_restart = True msg = _('Some of the changes you made require a restart.' ' Please restart calibre as soon as possible.') if rc: msg = _('The changes you have made require calibre be ' 'restarted immediately. You will not be allowed to ' 'set any more preferences, until you restart.') do_restart = show_restart_warning(msg, parent=self) self.showing_widget.refresh_gui(self.gui) self.hide_plugin() if self.close_after_initial or (must_restart and rc) or do_restart: self.close() if do_restart: self.gui.quit(restart=True) def cancel(self, *args): if self.close_after_initial: self.close() else: self.hide_plugin() def restore_defaults(self, *args): self.showing_widget.restore_defaults() def closeEvent(self, *args): gprefs.set('preferences_window_geometry', bytearray(self.saveGeometry())) if self.committed: self.gui.must_restart_before_config = self.must_restart self.gui.tags_view.recount() self.gui.create_device_menu() self.gui.set_device_menu_items_state(bool(self.gui.device_connected)) self.gui.bars_manager.apply_settings() self.gui.bars_manager.update_bars() self.gui.build_context_menus() return QMainWindow.closeEvent(self, *args)