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(QDialog): 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) if get_lang()[:2] not in ('zh', 'ja'): cl.setWordWrap(True) l.addWidget(cl, 0, 0, 1, 1) self.bb = bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.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 ¤t defaults'), bb.ResetRole) b.setToolTip(_('Restore defaults for currently displayed preferences')) b.clicked.connect(self.restore_current_defaults) self.rconfs = b = bb.addButton(_('Restore c&onfirmations'), bb.ResetRole) b.setToolTip(_('Restore all disabled confirmation prompts')) b.clicked.connect(self.restore_confirmations) l.addWidget(bb, 1, 0, 1, 2) self.resize(800, 600) geom = tprefs.get('preferences_geom', None) if geom is not None: QApplication.instance().safe_restore_geometry(self, geom) self.keyboard_panel = ShortcutConfig(self) self.keyboard_panel.initialize(gui.keyboard) self.editor_panel = EditorSettings(self) self.integration_panel = IntegrationSettings(self) self.main_window_panel = MainWindowSettings(self) self.preview_panel = PreviewSettings(self) self.toolbars_panel = ToolbarSettings(self) for name, icon, panel in [ (_('Main window'), 'page.png', 'main_window'), (_('Editor settings'), 'modified.png', 'editor'), (_('Preview settings'), 'viewer.png', 'preview'), (_('Keyboard shortcuts'), 'keyboard-prefs.png', 'keyboard'), (_('Toolbars'), 'wizard.png', 'toolbars'), (_('Integration with calibre'), 'lt.png', 'integration'), ]: i = QListWidgetItem(QIcon(I(icon)), name, cl) i.setToolTip(name) 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 range(cl.count()): h = cl.sizeHintForRow(i) cl.item(i).setSizeHint(QSize(w, h)) cl.setMaximumWidth(cl.sizeHintForColumn(0) + 35) cl.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) cl.setMinimumWidth(min(cl.maximumWidth(), cl.sizeHint().width())) @property def dictionaries_changed(self): return self.editor_panel.dictionaries_changed @property def snippets_changed(self): return self.editor_panel.snippets_changed @property def toolbars_changed(self): return self.toolbars_panel.changed def restore_all_defaults(self): for i in range(self.stacks.count()): w = self.stacks.widget(i) w.restore_defaults() def restore_current_defaults(self): self.stacks.currentWidget().restore_defaults() def restore_confirmations(self): changed = 0 for key in tuple(tprefs): if key.endswith('_again') and tprefs.get(key) is False: del tprefs[key] changed += 1 elif key.startswith('skip_ask_to_show_current_diff_for_'): del tprefs[key] changed += 1 msg = _('There are no disabled confirmation prompts') if changed: msg = ngettext( 'One disabled confirmation prompt was restored', '{} disabled confirmation prompts were restored', changed).format(changed) info_dialog(self, _('Disabled confirmations restored'), msg, show=True) def accept(self): tprefs.set('preferences_geom', bytearray(self.saveGeometry())) for i in range(self.stacks.count()): w = self.stacks.widget(i) w.commit() QDialog.accept(self) def reject(self): tprefs.set('preferences_geom', bytearray(self.saveGeometry())) QDialog.reject(self)
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 MainWindow(QMainWindow): def __init__(self, app): super(MainWindow, self).__init__() self.app = app print('window created') self.setWindowIcon(QIcon('img/icon.png')) self.setWindowTitle('Kasino') self.setPalette(QPalette(Qt.darkGreen)) self.setup_music() self.statusbar = QStatusBar(self) self.statusbar.setStyleSheet('background: white') self.setStatusBar(self.statusbar) self.statusbar.showMessage('Welcome to the Cassino game!') self.menubar = QMenuBar(self) self.optionsMenu = self.menubar.addMenu('Options') self.music_toggle = QAction() self.music_toggle.setText('Music') self.music_toggle.setShortcut('Ctrl+m') self.music_toggle.setCheckable(True) self.music_toggle.setChecked(True) self.optionsMenu.addAction(self.music_toggle) self.music_toggle.triggered.connect(self.toggle_music) self.speedGroup = QActionGroup(self) self.speedGroup.triggered.connect(self.set_speed) self.slow_speed = QAction('Slow', self.speedGroup) self.slow_speed.setCheckable(True) self.normal_speed = QAction('Normal', self.speedGroup) self.normal_speed.setCheckable(True) self.fast_speed = QAction('Fast', self.speedGroup) self.fast_speed.setCheckable(True) self.vfast_speed = QAction('Very Fast', self.speedGroup) self.vfast_speed.setCheckable(True) self.normal_speed.setChecked(True) self.speed_menu = self.optionsMenu.addMenu('Speed') self.speed_menu.addActions(self.speedGroup.actions()) self.menubar.setMouseTracking(False) self.setMenuBar(self.menubar) self.play_widget = PlayWidget(self) self.main_menu = MainMenu(self) self.start_menu = StartMenu(self) self.widgets = QStackedWidget(self) self.widgets.addWidget(self.play_widget) self.widgets.addWidget(self.main_menu) self.widgets.addWidget(self.start_menu) self.widgets.setCurrentWidget(self.main_menu) self.setCentralWidget(self.widgets) self.setGeometry(25, 50, 1028, 720) self.main_menu.startbutton.clicked.connect(self.init_game) self.main_menu.loadbutton.clicked.connect(self.load_game) self.main_menu.quitbutton.clicked.connect(self.quit) self.play_widget.quit_button.clicked.connect(self.quit_to_menu) self.play_widget.save_button.clicked.connect(self.save_game) self.start_menu.startbutton.clicked.connect(self.start_game) def setup_music(self): self.music = QMediaPlayer() self.playlist = QMediaPlaylist() self.playlist.setPlaybackMode(QMediaPlaylist.Loop) file_name = "sound/bg.mp3" self.media = QMediaContent(QUrl.fromLocalFile(file_name)) self.playlist.addMedia(self.media) self.music.setPlaylist(self.playlist) self.music.setVolume(20) self.music.play() def toggle_music(self): if self.music.isMuted(): self.music.setMuted(False) self.statusbar.showMessage('Music on', 5000) else: self.music.setMuted(True) self.statusbar.showMessage('Music off', 5000) def set_speed(self, action): if action == self.slow_speed: self.play_widget.speed = 1 elif action == self.normal_speed: self.play_widget.speed = 3 elif action == self.fast_speed: self.play_widget.speed = 4 else: self.play_widget.speed = 6 def start_game(self): self.play_widget.init_game( self.start_menu.extract_info_and_init_game()) self.widgets.setCurrentWidget(self.play_widget) self.statusbar.showMessage('Game launched', 2000) def load_game(self): path = QFileDialog.getOpenFileName(self, 'Open save file', QDir.currentPath() + '/sav')[0] if path != '': game, msg, count = load(path) self.play_widget.resume_from_save(game, msg, count) self.widgets.setCurrentWidget(self.play_widget) self.statusbar.showMessage('Loaded save file', 5000) def save_game(self): path = QFileDialog.getSaveFileName(self, 'Create save file', QDir.currentPath() + '/sav')[0] if path != '': save(path, self.play_widget.game, self.play_widget.export_log(), self.play_widget.move_count) self.statusbar.showMessage('Game saved', 5000) def init_game(self): self.widgets.setCurrentWidget(self.start_menu) self.statusbar.showMessage('Starting new game') def quit_to_menu(self): #Reset playwidget self.widgets.removeWidget(self.play_widget) speed = self.play_widget.speed self.play_widget.setParent(None) self.play_widget = PlayWidget(self) self.play_widget.speed = speed self.widgets.addWidget(self.play_widget) self.play_widget.quit_button.clicked.connect(self.quit_to_menu) self.play_widget.save_button.clicked.connect(self.save_game) self.widgets.setCurrentWidget(self.main_menu) def closeEvent(self, *args, **kwargs): #for handling closing from 'x' button self.quit() def quit(self): print('Exited game. Thanks for playing!\n') self.app.exit()
class Preferences(QDialog): 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) self.rconfs = b = bb.addButton(_('Restore confirmations'), bb.ResetRole) b.setToolTip(_('Restore all disabled confirmation prompts')) b.clicked.connect(self.restore_confirmations) 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) self.main_window_panel = MainWindowSettings(self) self.preview_panel = PreviewSettings(self) self.toolbars_panel = ToolbarSettings(self) for name, icon, panel in [ (_('Main window'), 'page.png', 'main_window'), (_('Editor settings'), 'modified.png', 'editor'), (_('Preview settings'), 'viewer.png', 'preview'), (_('Keyboard shortcuts'), 'keyboard-prefs.png', 'keyboard'), (_('Toolbars'), 'wizard.png', 'toolbars'), (_('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) @property def dictionaries_changed(self): return self.editor_panel.dictionaries_changed @property def snippets_changed(self): return self.editor_panel.snippets_changed @property def toolbars_changed(self): return self.toolbars_panel.changed def restore_all_defaults(self): for i in xrange(self.stacks.count()): w = self.stacks.widget(i) w.restore_defaults() def restore_current_defaults(self): self.stacks.currentWidget().restore_defaults() def restore_confirmations(self): changed = 0 for key in tuple(tprefs): if key.endswith('_again') and tprefs.get(key) is False: del tprefs[key] changed += 1 msg = _('There are no disabled confirmation prompts') if changed: msg = ngettext( 'One disabled confirmation prompt was restored', '{} disabled confirmation prompts were restored', changed).format(changed) info_dialog(self, _('Disabled confirmations restored'), msg, show=True) def accept(self): tprefs.set('preferences_geom', bytearray(self.saveGeometry())) for i in xrange(self.stacks.count()): w = self.stacks.widget(i) w.commit() QDialog.accept(self) def reject(self): tprefs.set('preferences_geom', bytearray(self.saveGeometry())) QDialog.reject(self)
def __add_address(self, gb_l): wgts = {} gb_l.addWidget(QLabel(tr('Почтовый индекс'))) w = QLineEdit() gb_l.addWidget(w, 0, 1, 1, 1) wgts['Postal_Code'] = w gb_l.addWidget(QLabel(tr('Регион'))) w = QLineEdit() gb_l.addWidget(w) wgts['Region'] = w gb_l.addWidget(QLabel(tr('Район'))) w = QLineEdit() gb_l.addWidget(w) wgts['District'] = w gb_l.addWidget(QLabel(tr('Муниципальное образование'))) w = QLineEdit() gb_l.addWidget(w) wgts['City'] = w gb_l.addWidget(QLabel(tr('Городской район'))) w = QLineEdit() gb_l.addWidget(w) wgts['Urban_District'] = w gb_l.addWidget(QLabel(tr('Сельсовет'))) w = QLineEdit() gb_l.addWidget(w) wgts['Soviet_Village'] = w gb_l.addWidget( QLabel(tr('Населенный пункт <em style="color: red">*</em>'))) w = QLineEdit() gb_l.addWidget(w) wgts['Locality'] = w cb = QComboBox() cb.addItems(('Вариант 1', 'Вариант 2')) gb_l.addWidget(cb) st = QStackedWidget() p1 = QWidget() l = QGridLayout() l.setSpacing(3) l.addWidget(QLabel(tr('Улица <em style="color: red">*</em>'))) w = QLineEdit() l.addWidget(w, 0, 1, 1, 1) wgts["Street"] = w l.addWidget(QLabel(tr('Дом <em style="color: red">*</em>'))) w = QLineEdit() l.addWidget(w) wgts["House"] = w p1.setLayout(l) st.addWidget(p1) p2 = QWidget() l = QGridLayout() l.setSpacing(3) l.addWidget(QLabel(tr('Ориентир'))) w = QLineEdit() l.addWidget(w, 0, 1, 1, 1) wgts["Reference_point"] = w p2.setLayout(l) st.addWidget(p2) gb_l.addWidget(st, 9, 0, 1, 2) cb.activated.connect(st.setCurrentIndex) gb_l.addWidget(QLabel(tr('Корпус'))) w = QLineEdit() gb_l.addWidget(w) wgts['Housing'] = w gb_l.addWidget(QLabel(tr('Строение'))) w = QLineEdit() gb_l.addWidget(w) wgts['Building'] = w gb_l.addWidget(QLabel(tr('Квартира'))) w = QLineEdit() gb_l.addWidget(w) wgts['Apartment'] = w return wgts
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(QDialog): 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) self.main_window_panel = MainWindowSettings(self) self.preview_panel = PreviewSettings(self) self.toolbars_panel = ToolbarSettings(self) for name, icon, panel in [ (_('Main window'), 'page.png', 'main_window'), (_('Editor settings'), 'modified.png', 'editor'), (_('Preview settings'), 'viewer.png', 'preview'), (_('Keyboard shortcuts'), 'keyboard-prefs.png', 'keyboard'), (_('Toolbars'), 'wizard.png', 'toolbars'), (_('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) @property def dictionaries_changed(self): return self.editor_panel.dictionaries_changed @property def snippets_changed(self): return self.editor_panel.snippets_changed @property def toolbars_changed(self): return self.toolbars_panel.changed def restore_all_defaults(self): for i in xrange(self.stacks.count()): w = self.stacks.widget(i) w.restore_defaults() def restore_current_defaults(self): self.stacks.currentWidget().restore_defaults() def accept(self): tprefs.set('preferences_geom', bytearray(self.saveGeometry())) for i in xrange(self.stacks.count()): w = self.stacks.widget(i) w.commit() QDialog.accept(self) def reject(self): tprefs.set('preferences_geom', bytearray(self.saveGeometry())) QDialog.reject(self)
class ParameterPanel(EditionWidget, WidgetController): """Edition Panel implementation.""" def __init__(self, astergui, parent=None): """ Create panel. Arguments: astergui (AsterGui): AsterGui instance. parent (Optional[QWidget]): Parent widget. """ super(ParameterPanel, self).__init__(parent=parent, name=translate("ParameterPanel", "Edit command"), astergui=astergui) self.setPixmap(load_pixmap("as_pic_edit_command.png")) self._files_model = astergui.study().dataFilesModel() self._unit_model = None self._command = None self.title = ParameterTitle(self) self.title.installEventFilter(self) self._name = QLineEdit(self) self.views = QStackedWidget(self) v_layout = QVBoxLayout(self) v_layout.setContentsMargins(0, 0, 0, 0) v_layout.setSpacing(5) v_layout.addWidget(self.title) v_layout.addWidget(HLine(self)) n_layout = QHBoxLayout() v_layout.addLayout(n_layout) n_layout.addWidget(QLabel(translate("ParameterPanel", "Name"), self)) n_layout.addWidget(self._name) # force to be a valid identifier + length <= 8 self._name.setValidator(QRegExpValidator(QRegExp(r"[a-zA-Z]\w{1,7}"))) # create toolbar tbar = QToolBar(self) tbar.setToolButtonStyle(Qt.ToolButtonIconOnly) # - Edit comment edit_comment = QAction(translate("AsterStudy", "Edit &Comment"), self) edit_comment.setToolTip(translate("AsterStudy", "Edit comment")) edit_comment.setStatusTip( translate("AsterStudy", "Edit comment for the " "selected object")) edit_comment.setIcon(load_icon("as_pic_edit_comment.png")) connect(edit_comment.triggered, self._editComment) tbar.addAction(edit_comment) # - Switch on/off business-translations title = translate("AsterStudy", "Use Business-Oriented Translations") self.use_translations = QAction(title, self) title = translate("AsterStudy", "Use business-oriented translations") self.use_translations.setToolTip(title) self.use_translations.setStatusTip(title) self.use_translations.setIcon(load_icon("as_pic_use_translations.png")) self.use_translations.setCheckable(True) if behavior().forced_native_names: force = behavior().force_native_names self.use_translations.setDisabled(True) is_on = not force else: is_on = behavior().use_business_translations Options.use_translations = is_on self.use_translations.setChecked(is_on) connect(self.use_translations.toggled, self.updateTranslations) tbar.addAction(self.use_translations) # - Hide unused hide_unused = astergui.action(ActionType.HideUnused) connect(hide_unused.toggled, self._unusedVisibility) tbar.addAction(hide_unused) # - What's this whats_this = QWhatsThis.createAction(tbar) whats_this.setToolTip(translate("AsterStudy", "What's this?")) whats_this.setStatusTip( translate("AsterStudy", "Show element's description")) whats_this.setIcon(load_icon("as_pic_whats_this.png")) tbar.addAction(whats_this) # - Link to doc tbar.addAction(astergui.action(ActionType.LinkToDoc)) n_layout.addWidget(tbar) v_layout.addWidget(self.views) self._updateState() def unitModel(self): """ Method that get unit model. Returns: UnitModel: Unit model. """ return self._unit_model def command(self): """ Get command being edited. Returns: Command: Command being edited. """ return self._command def setCommand(self, command): """ Set command to edit. Arguments: command (Command): Command to edit. """ self.clear() self._command = command if self._command is None: self._name.setText("") else: self._name.setText(self._command.name) self._unit_model = UnitModel(command.stage) pview = self._createParameterView(ParameterPath(self._command), '') pview.view().setItemValue(command.storage) hide_unused = self.astergui().action(ActionType.HideUnused) pview.setUnusedVisibile(not hide_unused.isChecked()) self.views.setCurrentWidget(pview) self._updateState() def currentPath(self): """ Get currently edited parameter path. Returns: str: currently edited parameter path. """ path = "" wid = self.currentParameterView() if wid is not None: path = wid.path() return path def isCurrentCommand(self): """ Get true if the currently edited view contains command. Returns: bool: Current edited command flag """ curpath = self.currentPath() return ParameterPath(self.command()).isEqual(curpath) def currentParameterView(self): """ Get current parameter view. Returns: ParameterView: current view. """ return self.views.currentWidget() def clear(self): """Remove all parameter views.""" while self.views.count() > 0: wid = self.views.widget(0) if wid is not None: self.views.removeWidget(wid) wid.deleteLater() def store(self): """ Save data from all parameter views. """ cmd = self.command() if cmd is not None: with auto_dupl_on(self.astergui().study().activeCase): cmd.rename(self._name.text()) wid = self._viewByPath(ParameterPath(cmd)) if wid is not None: cmd.init(wid.view().itemValue()) def requiredButtons(self): """ Return the combination of standard button flags required for this widget. Returns: int: button flags for buttons required for this widget (combination of QDialogButtonBox.StandardButton flags). """ if self.isCurrentCommand(): return QDialogButtonBox.Ok | QDialogButtonBox.Apply | \ QDialogButtonBox.Close else: return QDialogButtonBox.Ok | QDialogButtonBox.Cancel | \ QDialogButtonBox.Abort def isButtonEnabled(self, button): """ Return True if a particular button is enabled. Arguments: button (QDialogButtonBox.StandardButton): button flag. Returns: True: that means that all buttons should be enabled. """ return True def perform(self, button): """ Perform action on button click. Redefined method from the base class. Arguments: button (QDialogButtonBox.StandardButton): clicked button flag. """ if button == QDialogButtonBox.Ok: self.performOk() elif button == QDialogButtonBox.Apply: self.performApply() elif button == QDialogButtonBox.Abort: self.performAbort() elif button == QDialogButtonBox.Close or \ button == QDialogButtonBox.Cancel: self.performClose() def performOk(self): """Called when `Ok` button is clicked in Edition panel.""" self.performChanges(True) def performApply(self): """Called when `Apply` button is clicked in Edition panel.""" self.performChanges(False) def performAbort(self): """Called when `Abort` button is clicked in Edition panel.""" pref_mgr = self.astergui().preferencesMgr() msg = translate( "ParameterPanel", "Command edition will be aborted and " "all made changes will be lost. " "Do you want to continue?") noshow = "parampanel_abort" ask = MessageBox.question(self.astergui().mainWindow(), translate("ParameterPanel", "Abort"), msg, QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes, noshow=noshow, prefmgr=pref_mgr) if ask == QMessageBox.Yes: self.close() self.astergui().study().revert() def performClose(self): """Called when `Cancel` button is clicked in Edition panel.""" has_modif = self._hasModifications() if has_modif: pref_mgr = self.astergui().preferencesMgr() msg = translate( "ParameterPanel", "There are some unsaved modifications will be " "lost. Do you want to continue?") noshow = "parampanel_close" ask = MessageBox.question(self.astergui().mainWindow(), translate("ParameterPanel", "Close"), msg, QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes, noshow=noshow, prefmgr=pref_mgr) has_modif = ask != QMessageBox.Yes if not has_modif: self.performDissmis(True) def performChanges(self, close=True): """ Validate and store the command into data model. """ wid = self.currentParameterView() if wid is not None: view = wid.view() if view.validate(): cur_path = self.currentPath() if self.isCurrentCommand(): self.store() self._files_model.update() if self.astergui() is not None: opname = translate("ParameterPanel", "Edit command") self.astergui().study().commit(opname) self.astergui().update() if close: self.performDissmis(False) msg = translate("ParameterPanel", "Command '{}' successfully stored") msg = msg.format(self._name.text()) self.astergui().showMessage(msg) else: child_val = view.itemValue() self._removeCurrentView() curview = self.currentParameterView() subitem = curview.view().findItemByPath(cur_path) if subitem is not None: subitem.setItemValue(child_val) self._updateState() self.updateButtonStatus() def performDissmis(self, revert=True): """ Cancel changes and revert the command changes. """ if self.isCurrentCommand(): self.close() if revert: self.astergui().study().revert() else: self._removeCurrentView() self._updateState() self.updateButtonStatus() def showEvent(self, event): """ Reimplemented for internal reason: updates the title depending on read only state, etc. """ title = translate("ParameterPanel", "View command") \ if self.isReadOnly() else \ translate("ParameterPanel", "Edit command") self.setWindowTitle(title) hide_unused = self.astergui().action(ActionType.HideUnused) hide_unused.setVisible(True) hide_unused.setChecked(self.isReadOnly()) # update meshview meshes = avail_meshes_in_cmd(self.command()) for i, mesh in enumerate(meshes): filename, meshname = get_cmd_mesh(mesh) if filename: if i > 0: self.meshview().displayMEDFileName(filename, meshname, 1.0, False) else: self.meshview().displayMEDFileName(filename, meshname, 1.0, True) super(ParameterPanel, self).showEvent(event) def hideEvent(self, event): """ Reimplemented for internal reason: hides "Hide unused" action. """ hide_unused = self.astergui().action(ActionType.HideUnused) hide_unused.setVisible(False) super(ParameterPanel, self).hideEvent(event) def updateTranslations(self): """ Update translations in GUI elements. """ Options.use_translations = self.use_translations.isChecked() self._updateState() for i in xrange(self.views.count()): view = self.views.widget(i) view.updateTranslations() def eventFilter(self, receiver, event): """ Event filter; processes clicking ln links in What's This window. """ if receiver == self.title and event.type() == QEvent.WhatsThisClicked: QDesktopServices.openUrl(QUrl(event.href())) return super(ParameterPanel, self).eventFilter(receiver, event) def _hasModifications(self): curview = self.currentParameterView().view() \ if self.currentParameterView() is not None else None return curview.hasModifications() \ if curview is not None else False def _updateState(self): """Update state and current title label.""" disabled = self.command() is None self.setDisabled(disabled) if not disabled: disabled = self.command().gettype(ConversionLevel.NoFail) is None self._name.setDisabled(disabled) txt = [] pview = self.currentParameterView() if pview is not None: txt = pview.path().names() ppath = None txt_list = [] tooltip = "" whats_this = "" while len(txt) > 0: name = txt.pop(0) if ppath is None: ppath = ParameterPath(self.command(), name=name) else: ppath = ppath.absolutePath(name) if ppath.isInSequence(): txt_list.append("[" + name + "]") elif get_cata_typeid(ppath.keyword()) in (IDS.simp, IDS.fact): # translate keyword kwtext = Options.translate_command(ppath.command().title, name) txt_list.append(kwtext) elif get_cata_typeid(ppath.keyword()) == IDS.command: # translate command translation = Options.translate_command(name) txt_list.append(translation) if translation != name: wttext = italic(translation) + " ({})".format(bold(name)) else: wttext = bold(name) tooltip = preformat(wttext) url = self.astergui().doc_url(name) if url: wttext += " " wttext += href( image(CFG.rcfile("as_pic_help.png"), width=20, height=20), url) wttext = preformat(wttext) docs = CATA.get_command_docstring(name) if docs: wttext += "<hr>" wttext += docs whats_this = wttext self.title.setTitle(txt_list) self.title.setToolTip(tooltip) self.title.setWhatsThis(whats_this) def _removeCurrentView(self): """ Remove the parameter view for given object. Arguments: obj (Parameter): Command's parameter. """ curview = self.currentParameterView() if curview is not None: master = curview.view().masterItem() if master is not None and master.slaveItem() == curview.view(): master.setSlaveItem(None) curview.view().setMasterItem(None) view = self._parentView(curview) if view is not None: self.views.setCurrentWidget(view) hide_unused = self.astergui().action(ActionType.HideUnused) view.setUnusedVisibile(not hide_unused.isChecked()) self.views.removeWidget(curview) curview.deleteLater() self._updateState() def _viewByPath(self, path): view = None for i in xrange(self.views.count()): the_view = self.views.widget(i) if the_view.path().isEqual(path): view = the_view break return view def _parentView(self, curview): view = None path = curview.path() while path is not None and view is None: path = path.parentPath() view = self._viewByPath(path) return view def _gotoParameter(self, path, link): """ Activate the parameter view for object with given id. Arguments: uid (int): Object's UID. """ curview = self.currentParameterView() act_item = curview.view().findItemByPath(path) child_val = None wid = self._createParameterView(path, link) if act_item is not None: child_val = act_item.itemValue() act_item.setSlaveItem(wid.view()) wid.view().setMasterItem(act_item) hide_unused = self.astergui().action(ActionType.HideUnused) wid.setUnusedVisibile(not hide_unused.isChecked()) self.views.setCurrentWidget(wid) wid.view().setItemValue(child_val) self._updateState() self.updateButtonStatus() def _createParameterView(self, path, link): """ Create parameter view for given object. Arguments: path (ParameterPath): Path of parameter to edit. Returns: ParameterWindow: Parameter view for parameter path. """ # pragma pylint: disable=redefined-variable-type pview = None if link == EditorLink.Table: pview = ParameterTableWindow(path, self, self.views) elif link == EditorLink.List: pview = ParameterListWindow(path, self, self.views) elif link == EditorLink.GrMa: pview = ParameterMeshGroupWindow(path, self, self.views) else: pview = ParameterFactWindow(path, self, self.views) connect(pview.gotoParameter, self._gotoParameter) self.views.addWidget(pview) return pview def _unusedVisibility(self, ison): """ Invoked when 'Hide unused' button toggled """ curview = self.currentParameterView() curview.setUnusedVisibile(not ison) def meshview(self): """ Returns the central *MeshView* object """ return self.astergui().workSpace().panels[Panel.View] def _editComment(self): """ Invoked when 'Edit comment' button is clicked """ panel = CommentPanel(self.astergui(), owner=self) panel.node = self.command() self.astergui().workSpace().panel(Panel.Edit).setEditor(panel) def pendingStorage(self): """ Dictionnary being filled as this command is edited. """ wid = self._viewByPath(ParameterPath(self.command())) if wid is not None: return wid.view().itemValue() return None
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(QDialog): 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) self.main_window_panel = MainWindowSettings(self) self.preview_panel = PreviewSettings(self) self.toolbars_panel = ToolbarSettings(self) for name, icon, panel in [ (_("Main window"), "page.png", "main_window"), (_("Editor settings"), "modified.png", "editor"), (_("Preview settings"), "viewer.png", "preview"), (_("Keyboard shortcuts"), "keyboard-prefs.png", "keyboard"), (_("Toolbars"), "wizard.png", "toolbars"), (_("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) @property def dictionaries_changed(self): return self.editor_panel.dictionaries_changed @property def toolbars_changed(self): return self.toolbars_panel.changed def restore_all_defaults(self): for i in xrange(self.stacks.count()): w = self.stacks.widget(i) w.restore_defaults() def restore_current_defaults(self): self.stacks.currentWidget().restore_defaults() def accept(self): tprefs.set("preferences_geom", bytearray(self.saveGeometry())) for i in xrange(self.stacks.count()): w = self.stacks.widget(i) w.commit() QDialog.accept(self) def reject(self): tprefs.set("preferences_geom", bytearray(self.saveGeometry())) QDialog.reject(self)
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)
class ImageControlDialog(QDialog): def __init__(self, parent, rc, imgman): """An ImageControlDialog is initialized with a parent widget, a RenderControl object, and an ImageManager object""" QDialog.__init__(self, parent) image = rc.image self.setWindowTitle("%s: Colour Controls" % image.name) self.setWindowIcon(pixmaps.colours.icon()) self.setModal(False) self.image = image self._rc = rc self._imgman = imgman self._currier = PersistentCurrier() # init internal state self._prev_range = self._display_range = None, None self._hist = None self._geometry = None # create layouts lo0 = QVBoxLayout(self) # lo0.setContentsMargins(0,0,0,0) # histogram plot whide = self.makeButton("Hide", self.hide, width=128) whide.setShortcut(Qt.Key_F9) lo0.addWidget(Separator(self, "Histogram and ITF", extra_widgets=[whide])) lo1 = QHBoxLayout() lo1.setContentsMargins(0, 0, 0, 0) self._histplot = QwtPlot(self) self._histplot.setAutoDelete(False) lo1.addWidget(self._histplot, 1) lo2 = QHBoxLayout() lo2.setContentsMargins(0, 0, 0, 0) lo2.setSpacing(2) lo0.addLayout(lo2) lo0.addLayout(lo1) self._wautozoom = QCheckBox("autozoom", self) self._wautozoom.setChecked(True) self._wautozoom.setToolTip("""<P>If checked, then the histrogram plot will zoom in automatically when you narrow the current intensity range.</P>""") self._wlogy = QCheckBox("log Y", self) self._wlogy.setChecked(True) self._ylogscale = True self._wlogy.setToolTip( """<P>If checked, a log-scale Y axis is used for the histogram plot instead of a linear one.""") self._wlogy.toggled[bool].connect(self._setHistLogScale) self._whistunzoom = self.makeButton("", self._unzoomHistogram, icon=pixmaps.full_range.icon()) self._whistzoomout = self.makeButton("-", self._currier.curry(self._zoomHistogramByFactor, math.sqrt(.1))) self._whistzoomin = self.makeButton("+", self._currier.curry(self._zoomHistogramByFactor, math.sqrt(10))) self._whistzoomin.setToolTip("""<P>Click to zoom into the histogram plot by one step. This does not change the current intensity range.</P>""") self._whistzoomout.setToolTip("""<P>Click to zoom out of the histogram plot by one step. This does not change the current intensity range.</P>""") self._whistunzoom.setToolTip("""<P>Click to reset the histogram plot back to its full extent. This does not change the current intensity range.</P>""") self._whistzoom = QwtWheel(self) self._whistzoom.setMass(0.5) self._whistzoom.setOrientation(Qt.Horizontal) self._whistzoom.setMaximumWidth(80) self._whistzoom.setRange(0, 10) self._whistzoom.setSingleStep(0.1) self._whistzoom.setPageStepCount(1) self._whistzoom.setTickCount(30) self._whistzoom.setTracking(False) self._whistzoom.valueChanged['double'].connect(self._zoomHistogramFinalize) self._whistzoom.wheelMoved['double'].connect(self._zoomHistogramPreview) self._whistzoom.setToolTip("""<P>Use this wheel control to zoom in/out of the histogram plot. This does not change the current intensity range. Note that the zoom wheel should also respond to your mouse wheel, if you have one.</P>""") # This works around a stupid bug in QwtSliders -- when using the mousewheel, only sliderMoved() signals are emitted, # with no final valueChanged(). If we want to do a fast preview of something on sliderMoved(), and a "slow" final # step on valueChanged(), we're in trouble. So we start a timer on sliderMoved(), and if the timer expires without # anything else happening, do a valueChanged(). # Here we use a timer to call zoomHistogramFinalize() w/o an argument. self._whistzoom_timer = QTimer(self) self._whistzoom_timer.setSingleShot(True) self._whistzoom_timer.setInterval(500) self._whistzoom_timer.timeout.connect(self._zoomHistogramFinalize) # set same size for all buttons and controls width = 24 for w in self._whistunzoom, self._whistzoomin, self._whistzoomout: w.setMinimumSize(width, width) w.setMaximumSize(width, width) self._whistzoom.setMinimumSize(80, width) self._wlab_histpos_text = "(hover for help)" self._wlab_histpos = QLabel(self._wlab_histpos_text, self) help_font = QFont() help_font.setPointSize(8) self._wlab_histpos.setFont(help_font) self._wlab_histpos.setToolTip(""" <P>The plot shows a histogram of either the full image or its selected subset (as per the "Data subset" section below).</P> <P>The current intensity range is indicated by the grey box in the plot.</P> <P>Use the left mouse button to change the low intensity limit, and the right button (on Macs, use Ctrl-click) to change the high limit.</P> <P>Use Shift with the left mouse button to zoom into an area of the histogram, or else use the "zoom wheel" control or the plus/minus toolbuttons above the histogram to zoom in or out. To zoom back out to the full extent of the histogram, click on the rightmost button above the histogram.</P> """) lo2.addWidget(self._wlab_histpos, 1) lo2.addWidget(self._wautozoom) lo2.addWidget(self._wlogy, 0) lo2.addWidget(self._whistzoomin, 0) lo2.addWidget(self._whistzoom, 0) lo2.addWidget(self._whistzoomout, 0) lo2.addWidget(self._whistunzoom, 0) self._zooming_histogram = False sliced_axes = rc.slicedAxes() dprint(1, "sliced axes are", sliced_axes) self._stokes_axis = None # subset indication lo0.addWidget(Separator(self, "Data subset")) # sliced axis selectors self._wslicers = [] if sliced_axes: lo1 = QHBoxLayout() lo1.setContentsMargins(0, 0, 0, 0) lo1.setSpacing(2) lo0.addLayout(lo1) lo1.addWidget(QLabel("Current slice: ", self)) for i, (iextra, name, labels) in enumerate(sliced_axes): lo1.addWidget(QLabel("%s:" % name, self)) if name == "STOKES": self._stokes_axis = iextra # add controls wslicer = QComboBox(self) self._wslicers.append(wslicer) wslicer.addItems(labels) wslicer.setToolTip("""<P>Selects current slice along the %s axis.</P>""" % name) wslicer.setCurrentIndex(self._rc.currentSlice()[iextra]) wslicer.activated[int].connect(self._currier.curry(self._rc.changeSlice, iextra)) lo2 = QVBoxLayout() lo1.addLayout(lo2) lo2.setContentsMargins(0, 0, 0, 0) lo2.setSpacing(0) wminus = QToolButton(self) wminus.setArrowType(Qt.UpArrow) wminus.clicked.connect(self._currier.curry(self._rc.incrementSlice, iextra, 1)) if i == 0: wminus.setShortcut(Qt.SHIFT + Qt.Key_F7) elif i == 1: wminus.setShortcut(Qt.SHIFT + Qt.Key_F8) wplus = QToolButton(self) wplus.setArrowType(Qt.DownArrow) wplus.clicked.connect(self._currier.curry(self._rc.incrementSlice, iextra, -1)) if i == 0: wplus.setShortcut(Qt.Key_F7) elif i == 1: wplus.setShortcut(Qt.Key_F8) wminus.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) wplus.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) sz = QSize(12, 8) wminus.setMinimumSize(sz) wplus.setMinimumSize(sz) wminus.resize(sz) wplus.resize(sz) lo2.addWidget(wminus) lo2.addWidget(wplus) lo1.addWidget(wslicer) lo1.addSpacing(5) lo1.addStretch(1) # subset indicator lo1 = QHBoxLayout() lo1.setContentsMargins(0, 0, 0, 0) lo1.setSpacing(2) lo0.addLayout(lo1) self._wlab_subset = QLabel("Subset: xxx", self) self._wlab_subset.setToolTip("""<P>This indicates the current data subset to which the histogram and the stats given here apply. Use the "Reset to" control on the right to change the current subset and recompute the histogram and stats.</P>""") lo1.addWidget(self._wlab_subset, 1) self._wreset_full = self.makeButton("\u2192 full", self._rc.setFullSubset) lo1.addWidget(self._wreset_full) if sliced_axes: # if self._stokes_axis is not None and len(sliced_axes)>1: # self._wreset_stokes = self.makeButton(u"\u21920Stokes",self._rc.setFullSubset) self._wreset_slice = self.makeButton("\u2192 slice", self._rc.setSliceSubset) lo1.addWidget(self._wreset_slice) else: self._wreset_slice = None # min/max controls lo1 = QHBoxLayout() lo1.setContentsMargins(0, 0, 0, 0) lo0.addLayout(lo1, 0) self._wlab_stats = QLabel(self) self._wlab_stats.setWordWrap(True) self._wlab_stats.setMinimumWidth(384) lo1.addWidget(self._wlab_stats, 0) self._wmore_stats = self.makeButton("more...", self._showMeanStd) self._wlab_stats.setMinimumHeight(self._wmore_stats.height()) lo1.addWidget(self._wmore_stats, 0) lo1.addStretch(1) # intensity controls lo0.addWidget(Separator(self, "Intensity mapping")) lo1 = QHBoxLayout() lo1.setContentsMargins(0, 0, 0, 0) lo1.setSpacing(2) lo0.addLayout(lo1, 0) self._range_validator = FloatValidator(self) self._wrange = QLineEdit(self), QLineEdit(self) self._wrange[0].setToolTip("""<P>This is the low end of the intensity range.</P>""") self._wrange[1].setToolTip("""<P>This is the high end of the intensity range.</P>""") for w in self._wrange: w.setValidator(self._range_validator) w.editingFinished.connect(self._changeDisplayRange) lo1.addWidget(QLabel("low:", self), 0) lo1.addWidget(self._wrange[0], 1) self._wrangeleft0 = self.makeButton("\u21920", self._setZeroLeftLimit, width=32) self._wrangeleft0.setToolTip("""<P>Click this to set the low end of the intensity range to 0.</P>""") lo1.addWidget(self._wrangeleft0, 0) lo1.addSpacing(8) lo1.addWidget(QLabel("high:", self), 0) lo1.addWidget(self._wrange[1], 1) lo1.addSpacing(8) self._wrange_full = self.makeButton(None, self._setHistDisplayRange, icon=pixmaps.intensity_graph.icon()) lo1.addWidget(self._wrange_full) self._wrange_full.setToolTip( """<P>Click this to reset the intensity range to the current extent of the histogram plot.</P>""") # add menu for display range range_menu = QMenu(self) wrange_menu = QToolButton(self) wrange_menu.setText("Reset to") wrange_menu.setToolTip("""<P>Use this to reset the intensity range to various pre-defined settings.</P>""") lo1.addWidget(wrange_menu) self._qa_range_full = range_menu.addAction(pixmaps.full_range.icon(), "Full subset", self._rc.resetSubsetDisplayRange) self._qa_range_hist = range_menu.addAction(pixmaps.intensity_graph.icon(), "Current histogram limits", self._setHistDisplayRange) for percent in (99.99, 99.9, 99.5, 99, 98, 95): range_menu.addAction("%g%%" % percent, self._currier.curry(self._changeDisplayRangeToPercent, percent)) wrange_menu.setMenu(range_menu) wrange_menu.setPopupMode(QToolButton.InstantPopup) lo1 = QGridLayout() lo1.setContentsMargins(0, 0, 0, 0) lo0.addLayout(lo1, 0) self._wimap = QComboBox(self) lo1.addWidget(QLabel("Intensity policy:", self), 0, 0) lo1.addWidget(self._wimap, 1, 0) self._wimap.addItems(rc.getIntensityMapNames()) self._wimap.currentIndexChanged[int].connect(self._rc.setIntensityMapNumber) self._wimap.setToolTip("""<P>Use this to change the type of the intensity transfer function (ITF).</P>""") # log cycles control lo1.setColumnStretch(1, 1) self._wlogcycles_label = QLabel("Log cycles: ", self) lo1.addWidget(self._wlogcycles_label, 0, 1) # self._wlogcycles = QwtWheel(self) # self._wlogcycles.setTotalAngle(360) self._wlogcycles = QwtSlider(self) self._wlogcycles.setToolTip( """<P>Use this to change the log-base for the logarithmic intensity transfer function (ITF).</P>""") # This works around a stupid bug in QwtSliders -- see comments on histogram zoom wheel above self._wlogcycles_timer = QTimer(self) self._wlogcycles_timer.setSingleShot(True) self._wlogcycles_timer.setInterval(500) self._wlogcycles_timer.timeout.connect(self._setIntensityLogCycles) lo1.addWidget(self._wlogcycles, 1, 1) # self._wlogcycles.setRange(1., 10) # need to find 6.1.5 change from v5 self._wlogcycles.setScale(1., 10) # self._wlogcycles.setStep(0.1) # need to find 6.1.5 change from v5 # self._wlogcycles.setScaleStepSize(0.1) self._wlogcycles.setTracking(False) self._wlogcycles.valueChanged.connect(self._setIntensityLogCycles) self._wlogcycles.sliderMoved.connect(self._previewIntensityLogCycles) self._updating_imap = False # lock intensity map lo1 = QHBoxLayout() lo1.setContentsMargins(0, 0, 0, 0) lo0.addLayout(lo1, 0) # lo1.addWidget(QLabel("Lock range accross",self)) wlock = QCheckBox("Lock display range", self) wlock.setMinimumWidth(192) wlock.setToolTip("""<P>If checked, then the intensity range will be locked. The ranges of all locked images change simultaneously.</P>""") lo1.addWidget(wlock) wlockall = QToolButton(self) wlockall.setIcon(pixmaps.locked.icon()) wlockall.setText("Lock all to this") wlockall.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) wlockall.setAutoRaise(True) wlockall.setToolTip("""<P>Click this to lock together the intensity ranges of all images.</P>""") lo1.addWidget(wlockall) wunlockall = QToolButton(self) wunlockall.setIcon(pixmaps.unlocked.icon()) wunlockall.setText("Unlock all") wunlockall.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) wunlockall.setAutoRaise(True) wunlockall.setToolTip("""<P>Click this to unlock the intensity ranges of all images.</P>""") lo1.addWidget(wunlockall) wlock.setChecked(self._rc.isDisplayRangeLocked()) wlock.clicked[bool].connect(self._rc.lockDisplayRange) wlockall.clicked.connect(self._currier.curry(self._imgman.lockAllDisplayRanges, self._rc)) wunlockall.clicked.connect(self._imgman.unlockAllDisplayRanges) self._rc.displayRangeLocked.connect(wlock.setChecked) # self._wlock_imap_axis = [ QCheckBox(name,self) for iaxis,name,labels in sliced_axes ] # for iw,w in enumerate(self._wlock_imap_axis): # QObject.connect(w,pyqtSignal("toggled(bool)"),self._currier.curry(self._rc.lockDisplayRangeForAxis,iw)) # lo1.addWidget(w,0) lo1.addStretch(1) # lo0.addWidget(Separator(self,"Colourmap")) # color bar self._colorbar = QwtPlot(self) lo0.addWidget(self._colorbar) self._colorbar.setAutoDelete(False) self._colorbar.setMinimumHeight(32) self._colorbar.enableAxis(QwtPlot.yLeft, False) self._colorbar.enableAxis(QwtPlot.xBottom, False) # color plot self._colorplot = QwtPlot(self) lo0.addWidget(self._colorplot) self._colorplot.setAutoDelete(False) self._colorplot.setMinimumHeight(64) self._colorplot.enableAxis(QwtPlot.yLeft, False) self._colorplot.enableAxis(QwtPlot.xBottom, False) # self._colorplot.setSizePolicy(QSizePolicy.Expanding,QSizePolicy.Preferred) self._colorbar.hide() self._colorplot.hide() # color controls lo1 = QHBoxLayout() lo1.setContentsMargins(0, 0, 0, 0) lo0.addLayout(lo1, 1) lo1.addWidget(QLabel("Colourmap:", self)) # colormap list ### NB: use setIconSize() and icons in QComboBox!!! self._wcolmaps = QComboBox(self) self._wcolmaps.setIconSize(QSize(128, 16)) self._wcolmaps.setToolTip("""<P>Use this to select a different colourmap.</P>""") for cmap in self._rc.getColormapList(): self._wcolmaps.addItem(QIcon(cmap.makeQPixmap(128, 16)), cmap.name) lo1.addWidget(self._wcolmaps) self._wcolmaps.activated[int].connect(self._rc.setColorMapNumber) # add widgetstack for colormap controls self._wcolmap_control_stack = QStackedWidget(self) self._wcolmap_control_blank = QWidget(self._wcolmap_control_stack) self._wcolmap_control_stack.addWidget(self._wcolmap_control_blank) lo0.addWidget(self._wcolmap_control_stack) self._colmap_controls = [] # add controls to stack for index, cmap in enumerate(self._rc.getColormapList()): if isinstance(cmap, Colormaps.ColormapWithControls): controls = cmap.makeControlWidgets(self._wcolmap_control_stack) self._wcolmap_control_stack.addWidget(controls) cmap.colormapChanged.connect(self._currier.curry(self._previewColormapParameters, index, cmap)) cmap.colormapPreviewed.connect(self._currier.curry(self._previewColormapParameters, index, cmap)) self._colmap_controls.append(controls) else: self._colmap_controls.append(self._wcolmap_control_blank) # connect updates from renderControl and image self.image.signalSlice.connect(self._updateImageSlice) self._rc.intensityMapChanged.connect(self._updateIntensityMap) self._rc.colorMapChanged.connect(self._updateColorMap) self._rc.dataSubsetChanged.connect(self._updateDataSubset) self._rc.displayRangeChanged.connect(self._updateDisplayRange) # update widgets self._setupHistogramPlot() self._updateDataSubset(*self._rc.currentSubset()) self._updateColorMap(image.colorMap()) self._updateIntensityMap(rc.currentIntensityMap(), rc.currentIntensityMapNumber()) self._updateDisplayRange(*self._rc.displayRange()) def makeButton(self, label, callback=None, width=None, icon=None): btn = QToolButton(self) # btn.setAutoRaise(True) label and btn.setText(label) icon and btn.setIcon(icon) # btn = QPushButton(label,self) # btn.setFlat(True) if width: btn.setMinimumWidth(width) btn.setMaximumWidth(width) if icon: btn.setIcon(icon) if callback: btn.clicked.connect(callback) return btn # def closeEvent (self,ev): # ev.ignore() # self.hide() def hide(self): self._geometry = self.geometry() QDialog.hide(self) self.parent().setVisible(False) def show(self): dprint(4, "show entrypoint") if self._geometry: dprint(4, "setting geometry") self.setGeometry(self._geometry) if self._hist is None: busy = BusyIndicator() dprint(4, "updating histogram") self._updateHistogram() dprint(4, "updating stats") self._updateStats(self._subset, self._subset_range) busy.reset_cursor() dprint(4, "calling QDialog.show") QDialog.show(self) # number of bins used to compute intensity transfer function NumItfBins = 1000 # number of bins used for displaying histograms NumHistBins = 500 # number of bins used for high-res histograms NumHistBinsHi = 10000 # colorbar height, as fraction of plot area ColorBarHeight = 0.1 class HistLimitPicker(QwtPlotPicker): """Auguments QwtPlotPicker with functions for selecting hist min/max values""" def __init__(self, plot, label, color="green", mode=QwtPickerClickPointMachine(), rubber_band=QwtPicker.VLineRubberBand, tracker_mode=QwtPicker.ActiveOnly, track=None): QwtPlotPicker.__init__(self, QwtPlot.xBottom, QwtPlot.yRight, rubber_band, tracker_mode, plot.canvas()) self.setStateMachine(mode) self.plot = plot self.label = label self.track = track self.color = QColor(color) self.setRubberBandPen(QPen(self.color)) self.setRubberBand(rubber_band) def trackerText(self, pos): x, y = self.plot.invTransform(QwtPlot.xBottom, pos.x()), self.plot.invTransform(QwtPlot.yLeft, pos.y()) if self.track: text = self.track(x, y) if text is not None: return text if self.label: text = QwtText(self.label % dict(x=x, y=y)) text.setColor(self.color) return text return QwtText() def widgetLeaveEvent(self, ev): if self.track: self.track(None, None) QwtPlotPicker.widgetLeaveEvent(self, ev) class ColorBarPlotItem(QwtPlotItem): def __init__(self, y0, y1, *args): QwtPlotItem.__init__(self, *args) self.RenderAntialiased self.imap = None self.cmap = None self._y0 = y1 self._dy = y1 - y0 def setIntensityMap(self, imap): self.imap = imap def setColorMap(self, cmap): self.cmap = cmap def draw(self, painter, xmap, ymap, rect): """Implements QwtPlotItem.draw(), to render the colorbar on the given painter.""" xp1, xp2, xdp, xs1, xs2, xds = xinfo = xmap.p1(), xmap.p2(), xmap.pDist(), xmap.s1(), xmap.s2(), xmap.sDist() yp1, yp2, ydp, ys1, ys2, yds = yinfo = ymap.p1(), ymap.p2(), ymap.pDist(), ymap.s1(), ymap.s2(), ymap.sDist() # xp: coordinates of pixels xp1...xp2 in data units xp = xs1 + (xds / xdp) * (0.5 + numpy.arange(int(xdp))) # convert y0 and y1 into pixel coordinates y0 = yp1 - (self._y0 - ys1) * (ydp / yds) dy = self._dy * (ydp / yds) # remap into an Nx1 image qimg = self.cmap.colorize(self.imap.remap(xp.reshape((len(xp), 1)))) # plot image painter.drawImage(QRect(xp1, y0, xdp, dy), qimg) class HistogramLineMarker: """Helper class implementing a line marker for a histogram plot""" def __init__(self, plot, color="black", linestyle=Qt.DotLine, align=Qt.AlignBottom | Qt.AlignRight, z=90, label="", zlabel=None, linewidth=1, spacing=2, yaxis=QwtPlot.yRight): self.line = TiggerPlotCurve() self.line.setRenderHint(QwtPlotItem.RenderAntialiased) self.color = color = color if isinstance(color, QColor) else QColor(color) self.line.setPen(QPen(color, linewidth, linestyle)) self.marker = TiggerPlotMarker() self.marker.setRenderHint(QwtPlotItem.RenderAntialiased) self.marker.setLabelAlignment(align) try: self.marker.setSpacing(spacing) except AttributeError: pass self.setText(label) self.line.setZ(z) self.marker.setZ(zlabel if zlabel is not None else z) # set axes -- using yRight, since that is the "markup" z-axis self.line.setAxes(QwtPlot.xBottom, yaxis) self.marker.setAxes(QwtPlot.xBottom, yaxis) # attach to plot self.line.attach(plot) self.marker.attach(plot) def show(self): self.line.show() self.marker.show() def hide(self): self.line.hide() self.marker.hide() def setText(self, text): label = QwtText(text) label.setColor(self.color) self.marker.setLabel(label) def _setupHistogramPlot(self): self._histplot.setCanvasBackground(QColor("lightgray")) self._histplot.setAxisFont(QwtPlot.yLeft, QApplication.font()) self._histplot.setAxisFont(QwtPlot.xBottom, QApplication.font()) # add histogram curves self._histcurve1 = TiggerPlotCurve() self._histcurve1.setRenderHint(QwtPlotItem.RenderAntialiased) self._histcurve2 = TiggerPlotCurve() self._histcurve2.setRenderHint(QwtPlotItem.RenderAntialiased) self._histcurve1.setStyle(QwtPlotCurve.Steps) self._histcurve2.setStyle(QwtPlotCurve.Steps) self._histcurve1.setPen(QPen(Qt.NoPen)) self._histcurve1.setBrush(QBrush(QColor("slategrey"))) pen = QPen(QColor("red")) pen.setWidth(1) self._histcurve2.setPen(pen) self._histcurve1.setZ(0) self._histcurve2.setZ(100) # self._histcurve1.attach(self._histplot) self._histcurve2.attach(self._histplot) # add maxbin and half-max curves self._line_0 = self.HistogramLineMarker(self._histplot, color="grey50", linestyle=Qt.SolidLine, align=Qt.AlignTop | Qt.AlignLeft, z=90) self._line_mean = self.HistogramLineMarker(self._histplot, color="black", linestyle=Qt.SolidLine, align=Qt.AlignBottom | Qt.AlignRight, z=91, label="mean", zlabel=151) self._line_std = self.HistogramLineMarker(self._histplot, color="black", linestyle=Qt.SolidLine, align=Qt.AlignTop | Qt.AlignRight, z=91, label="std", zlabel=151) sym = QwtSymbol() sym.setStyle(QwtSymbol.VLine) sym.setSize(8) self._line_std.line.setSymbol(sym) self._line_maxbin = self.HistogramLineMarker(self._histplot, color="green", linestyle=Qt.DotLine, align=Qt.AlignTop | Qt.AlignRight, z=92, label="max bin", zlabel=150) self._line_halfmax = self.HistogramLineMarker(self._histplot, color="green", linestyle=Qt.DotLine, align=Qt.AlignBottom | Qt.AlignRight, z=90, label="half-max", yaxis=QwtPlot.yLeft) # add current range self._rangebox = TiggerPlotCurve() self._rangebox.setRenderHint(QwtPlotItem.RenderAntialiased) self._rangebox.setStyle(QwtPlotCurve.Steps) self._rangebox.setYAxis(QwtPlot.yRight) self._rangebox.setPen(QPen(Qt.NoPen)) self._rangebox.setBrush(QBrush(QColor("darkgray"))) self._rangebox.setZ(50) self._rangebox.attach(self._histplot) self._rangebox2 = TiggerPlotCurve() self._rangebox2.setRenderHint(QwtPlotItem.RenderAntialiased) self._rangebox2.setStyle(QwtPlotCurve.Sticks) self._rangebox2.setYAxis(QwtPlot.yRight) self._rangebox2.setZ(60) # self._rangebox2.attach(self._histplot) # add intensity transfer function self._itfcurve = TiggerPlotCurve() self._itfcurve.setRenderHint(QwtPlotItem.RenderAntialiased) self._itfcurve.setStyle(QwtPlotCurve.Lines) self._itfcurve.setPen(QPen(QColor("blue"))) self._itfcurve.setYAxis(QwtPlot.yRight) self._itfcurve.setZ(120) self._itfcurve.attach(self._histplot) self._itfmarker = TiggerPlotMarker() self._itfmarker.setRenderHint(QwtPlotItem.RenderAntialiased) label = QwtText("ITF") label.setColor(QColor("blue")) self._itfmarker.setLabel(label) try: self._itfmarker.setSpacing(0) except AttributeError: pass self._itfmarker.setLabelAlignment(Qt.AlignTop | Qt.AlignRight) self._itfmarker.setZ(120) self._itfmarker.attach(self._histplot) # add colorbar self._cb_item = self.ColorBarPlotItem(1, 1 + self.ColorBarHeight) self._cb_item.setYAxis(QwtPlot.yRight) self._cb_item.attach(self._histplot) # add pickers self._hist_minpicker = self.HistLimitPicker(self._histplot, "low: %(x).4g") self._hist_minpicker.setMousePattern(QwtEventPattern.MouseSelect1, Qt.LeftButton) self._hist_minpicker.selected.connect(self._selectLowLimit) self._hist_maxpicker = self.HistLimitPicker(self._histplot, "high: %(x).4g") self._hist_maxpicker.setMousePattern(QwtEventPattern.MouseSelect1, Qt.RightButton) self._hist_maxpicker.selected.connect(self._selectHighLimit) self._hist_maxpicker1 = self.HistLimitPicker(self._histplot, "high: %(x).4g") self._hist_maxpicker1.setMousePattern(QwtEventPattern.MouseSelect1, Qt.LeftButton, Qt.ControlModifier) self._hist_maxpicker1.selected.connect(self._selectHighLimit) self._hist_zoompicker = self.HistLimitPicker(self._histplot, label="zoom", tracker_mode=QwtPicker.AlwaysOn, track=self._trackHistCoordinates, color="black", mode=QwtPickerClickRectMachine(), rubber_band=QwtPicker.RectRubberBand) self._hist_zoompicker.setMousePattern(QwtEventPattern.MouseSelect1, Qt.LeftButton, Qt.ShiftModifier) # self._hist_zoompicker.selected[QRectF].connect(self._zoomHistogramIntoRect) self._hist_zoompicker.selected.connect(self._zoomHistogramIntoRect) def _trackHistCoordinates(self, x, y): self._wlab_histpos.setText((DataValueFormat + " %d") % (x, y) if x is not None else self._wlab_histpos_text) return QwtText() def _updateITF(self): """Updates current ITF array.""" # do nothing if no histogram -- means we're not visible if self._hist is not None: xdata = self._itf_bins ydata = self.image.intensityMap().remap(xdata) self._rangebox.setData(self._rc.displayRange(), [1, 1]) self._rangebox2.setData(self._rc.displayRange(), [1, 1]) self._itfcurve.setData(xdata, ydata) self._itfmarker.setValue(xdata[0], 1) def _updateHistogram(self, hmin=None, hmax=None): """Recomputes histogram. If no arguments, computes full histogram for data subset. If hmin/hmax is specified, computes zoomed-in histogram.""" busy = BusyIndicator() self._prev_range = self._display_range dmin, dmax = self._subset_range hmin0, hmax0 = dmin, dmax if hmin0 >= hmax0: hmax0 = hmin0 + 1 subset, mask = self.image.optimalRavel(self._subset) # compute full-subset hi-res histogram, if we don't have one (for percentile stats) if self._hist_hires is None: dprint(1, "computing histogram for full subset range", hmin0, hmax0) self._hist_hires = measurements.histogram(subset, hmin0, hmax0, self.NumHistBinsHi, labels=mask, index=None if mask is None else False) self._hist_bins_hires = hmin0 + (hmax0 - hmin0) * (numpy.arange(self.NumHistBinsHi) + 0.5) / float( self.NumHistBinsHi) self._hist_binsize_hires = (hmax0 - hmin0) / self.NumHistBins # if hist limits not specified, then compute lo-res histogram based on the hi-res one if hmin is None: hmin, hmax = hmin0, hmax0 # downsample to low-res histogram self._hist = self._hist_hires.reshape((self.NumHistBins, int(self.NumHistBinsHi / self.NumHistBins))).sum(1) else: # zoomed-in low-res histogram # bracket limits at subset range hmin, hmax = max(hmin, dmin), min(hmax, dmax) if hmin >= hmax: hmax = hmin + 1 dprint(1, "computing histogram for", self._subset.shape, self._subset.dtype, hmin, hmax) self._hist = measurements.histogram(subset, hmin, hmax, self.NumHistBins, labels=mask, index=None if mask is None else False) dprint(1, "histogram computed") # compute bins self._itf_bins = hmin + (hmax - hmin) * (numpy.arange(self.NumItfBins)) / (float(self.NumItfBins) - 1) self._hist_bins = hmin + (hmax - hmin) * (numpy.arange(self.NumHistBins) + 0.5) / float(self.NumHistBins) # histogram range and position of peak self._hist_range = hmin, hmax self._hist_min, self._hist_max, self._hist_imin, self._hist_imax = measurements.extrema(self._hist) self._hist_peak = self._hist_bins[self._hist_imax] # set controls accordingly if dmin >= dmax: dmax = dmin + 1 zoom = math.log10((dmax - dmin) / (hmax - hmin)) self._whistzoom.setValue(zoom) self._whistunzoom.setEnabled(zoom > 0) self._whistzoomout.setEnabled(zoom > 0) # reset scales self._histplot.setAxisScale(QwtPlot.xBottom, hmin, hmax) self._histplot.setAxisScale(QwtPlot.yRight, 0, 1 + self.ColorBarHeight) # update curves # call _setHistLogScale() (with current setting) to update axis scales and set data self._setHistLogScale(self._ylogscale, replot=False) # set plot lines self._line_0.line.setData([0, 0], [0, 1]) self._line_0.marker.setValue(0, 0) self._line_maxbin.line.setData([self._hist_peak, self._hist_peak], [0, 1]) self._line_maxbin.marker.setValue(self._hist_peak, 0) self._line_maxbin.setText(("max bin:" + DataValueFormat) % self._hist_peak) # set half-max line self._line_halfmax.line.setData(self._hist_range, [self._hist_max / 2, self._hist_max / 2]) self._line_halfmax.marker.setValue(hmin, self._hist_max / 2) # update ITF self._updateITF() busy.reset_cursor() def _updateStats(self, subset, minmax): """Recomputes subset statistics.""" if subset.size <= (2048 * 2048): self._showMeanStd(busy=False) else: self._wlab_stats.setText( ("min: %s max: %s np: %d" % (DataValueFormat, DataValueFormat, self._subset.size)) % minmax) self._wmore_stats.show() def _updateDataSubset(self, subset, minmax, desc, subset_type): """Called when the displayed data subset is changed. Updates the histogram.""" self._subset = subset self._subset_range = minmax self._wlab_subset.setText("Subset: %s" % desc) self._hist = self._hist_hires = None self._wreset_full.setVisible(subset_type is not RenderControl.SUBSET_FULL) self._wreset_slice and self._wreset_slice.setVisible(subset_type is not RenderControl.SUBSET_SLICE) # hide the mean/std markers, they will only be shown when _showMeanStd() is called self._line_mean.hide() self._line_std.hide() # if we're visibile, recompute histograms and stats if self.isVisible(): # if subset is sufficiently small, compute extended stats on-the-fly. Else show the "more" button to compute them later self._updateHistogram() self._updateStats(subset, minmax) self._histplot.replot() def _showMeanStd(self, busy=True): if busy: busy = BusyIndicator() dmin, dmax = self._subset_range subset, mask = self.image.optimalRavel(self._subset) dprint(5, "computing mean") mean = measurements.mean(subset, labels=mask, index=None if mask is None else False) dprint(5, "computing std") std = measurements.standard_deviation(subset, labels=mask, index=None if mask is None else False) dprint(5, "done") text = " ".join([("%s: " + DataValueFormat) % (name, value) for name, value in (("min", dmin), ("max", dmax), ("mean", mean), ("\n std", std))] + ["np: %d" % self._subset.size]) self._wlab_stats.setText(text) self._wmore_stats.hide() # update markers ypos = 0.3 self._line_mean.line.setData([mean, mean], [0, 1]) self._line_mean.marker.setValue(mean, ypos) self._line_mean.setText(("\u03BC=" + DataValueFormat) % mean) self._line_mean.show() self._line_std.line.setData([mean - std, mean + std], [ypos, ypos]) self._line_std.marker.setValue(mean, ypos) self._line_std.setText(("\u03C3=" + DataValueFormat) % std) self._line_std.show() self._histplot.replot() if not isinstance(busy, bool): busy.reset_cursor() def _setIntensityLogCyclesLabel(self, value): self._wlogcycles_label.setText("Log cycles: %4.1f" % value) def _previewIntensityLogCycles(self, value): self._setIntensityLogCycles(value, notify_image=False, write_config=False) self._wlogcycles_timer.start(500) def _setIntensityLogCycles(self, value=None, notify_image=True, write_config=True): if value is None: value = self._wlogcycles.value() # stop timer if being called to finalize the change in value if notify_image: self._wlogcycles_timer.stop() if not self._updating_imap: self._setIntensityLogCyclesLabel(value) self._rc.setIntensityMapLogCycles(value, notify_image=notify_image, write_config=write_config) self._updateITF() self._histplot.replot() def _updateDisplayRange(self, dmin, dmax): self._rangebox.setData([dmin, dmax], [.9, .9]) self._wrange[0].setText(DataValueFormat % dmin) self._wrange[1].setText(DataValueFormat % dmax) self._wrangeleft0.setEnabled(dmin != 0) self._display_range = dmin, dmax # if auto-zoom is on, zoom the histogram # try to be a little clever about this. Zoom only if (a) both limits have changed (so that adjusting one end of the range # does not cause endless rezooms), or (b) display range is < 1/10 of the histogram range if self._wautozoom.isChecked() and self._hist is not None: if (dmax - dmin) / (self._hist_range[1] - self._hist_range[0]) < .1 or ( dmin != self._prev_range[0] and dmax != self._prev_range[1]): margin = (dmax - dmin) / 8 self._updateHistogram(dmin - margin, dmax + margin) self._updateITF() self._histplot.replot() def _updateIntensityMap(self, imap, index): self._updating_imap = True try: self._cb_item.setIntensityMap(imap) self._updateITF() self._histplot.replot() self._wimap.setCurrentIndex(index) if isinstance(imap, Colormaps.LogIntensityMap): self._wlogcycles.setValue(imap.log_cycles) self._setIntensityLogCyclesLabel(imap.log_cycles) self._wlogcycles.show() self._wlogcycles_label.show() else: self._wlogcycles.hide() self._wlogcycles_label.hide() finally: self._updating_imap = False def _updateColorMap(self, cmap): self._cb_item.setColorMap(cmap) self._histplot.replot() try: index = self._rc.getColormapList().index(cmap) except: return self._setCurrentColormapNumber(index, cmap) def _previewColormapParameters(self, index, cmap): """Called to preview a new colormap parameter value""" self._histplot.replot() self._wcolmaps.setItemIcon(index, QIcon(cmap.makeQPixmap(128, 16))) def _setCurrentColormapNumber(self, index, cmap): self._wcolmaps.setCurrentIndex(index) # show controls for colormap self._wcolmap_control_stack.setCurrentWidget(self._colmap_controls[index]) def _changeDisplayRange(self): """Gets display range from widgets and updates the image with it.""" try: newrange = [float(str(w.text())) for w in self._wrange] except ValueError: return self._rc.setDisplayRange(*newrange) def _setHistDisplayRange(self): self._rc.setDisplayRange(*self._hist_range) def _updateImageSlice(self, _slice): for i, (iextra, name, labels) in enumerate(self._rc.slicedAxes()): self._wslicers[i].setCurrentIndex(_slice[iextra]) def _changeDisplayRangeToPercent(self, percent): busy = BusyIndicator() if self._hist is None: self._updateHistogram() self._updateStats(self._subset, self._subset_range) # delta: we need the [delta,100-delta] interval of the total distribution delta = self._subset.size * ((100. - percent) / 200.) # get F(x): cumulative sum cumsum = numpy.zeros(len(self._hist_hires) + 1, dtype=int) cumsum[1:] = numpy.cumsum(self._hist_hires) bins = numpy.zeros(len(self._hist_hires) + 1, dtype=float) bins[0] = self._subset_range[0] bins[1:] = self._hist_bins_hires + self._hist_binsize_hires / 2 # use interpolation to find value interval corresponding to [delta,100-delta] of the distribution dprint(2, self._subset.size, delta, self._subset.size - delta) dprint(2, cumsum, self._hist_bins_hires) # if first bin is already > delta, then set colour range to first bin x0, x1 = numpy.interp([delta, self._subset.size - delta], cumsum, bins) # and change the display range (this will also cause a histplot.replot() via _updateDisplayRange above) self._rc.setDisplayRange(x0, x1) busy.reset_cursor() def _setZeroLeftLimit(self): self._rc.setDisplayRange(0., self._rc.displayRange()[1]) def _selectLowLimit(self, pos): self._rc.setDisplayRange(pos.x(), self._rc.displayRange()[1]) def _selectHighLimit(self, pos): self._rc.setDisplayRange(self._rc.displayRange()[0], pos.x()) def _unzoomHistogram(self): self._updateHistogram() self._histplot.replot() def _zoomHistogramByFactor(self, factor, curry=None): """ Changes histogram limits by specified factor. curry=None is due to an error raised from the signal to zoom and is unused. """ # get max distance of plot limit from peak dprint(1, "zooming histogram by", factor) halfdist = (self._hist_range[1] - self._hist_range[0]) / (factor * 2) self._updateHistogram(self._hist_peak - halfdist, self._hist_peak + halfdist) self._histplot.replot() def _zoomHistogramIntoRect(self, rect): hmin, hmax = rect.bottomLeft().x(), rect.bottomRight().x() if hmax > hmin: self._updateHistogram(rect.bottomLeft().x(), rect.bottomRight().x()) self._histplot.replot() def _zoomHistogramPreview(self, value): dprint(2, "wheel moved to", value) self._zoomHistogramFinalize(value, preview=True) self._whistzoom_timer.start() def _zoomHistogramFinalize(self, value=None, preview=False): if self._zooming_histogram: return self._zooming_histogram = True try: if value is not None: dmin, dmax = self._subset_range dist = max(dmax - self._hist_peak, self._hist_peak - dmin) / 10 ** value self._preview_hist_range = max(self._hist_peak - dist, dmin), min(self._hist_peak + dist, dmax) if preview: self._histplot.setAxisScale(QwtPlot.xBottom, *self._preview_hist_range) else: dprint(2, "wheel finalized at", value) self._whistzoom_timer.stop() self._updateHistogram(*self._preview_hist_range) self._histplot.replot() finally: self._zooming_histogram = False def _setHistLogScale(self, logscale, replot=True): self._ylogscale = logscale if logscale: self._histplot.setAxisScaleEngine(QwtPlot.yLeft, QwtLogScaleEngine()) ymax = max(1, self._hist_max) self._histplot.setAxisScale(QwtPlot.yLeft, 1, 10 ** (math.log10(ymax) * (1 + self.ColorBarHeight))) y = self._hist.copy() y[y == 0] = 1 self._histcurve1.setData(self._hist_bins, y) self._histcurve2.setData(self._hist_bins, y) else: self._histplot.setAxisScaleEngine(QwtPlot.yLeft, QwtLinearScaleEngine()) self._histplot.setAxisScale(QwtPlot.yLeft, 0, self._hist_max * (1 + self.ColorBarHeight)) self._histcurve1.setData(self._hist_bins, self._hist) self._histcurve2.setData(self._hist_bins, self._hist) if replot: self._histplot.replot()