def on_progressbar_wanted(self, pid, maxval, label): logger.debug("Progressbar wanted. ID: %d", pid) if pid in self.progressbars: progressbar = self.progressbars[pid] progressbar.setValue(0) else: progressbar = QtWidgets.QProgressDialog(self) progressbar.setMinimumDuration(2000) progressbar.setMinimum(0) progressbar.setMaximum(maxval) progressbar.setWindowTitle("Processing") progressbar.setLabelText(label) if pid not in self.progressbars: def cancel(): # If pid not in collection, it is finished, and cancel # triggered when dialog closed. if pid in self.progressbars: logger.debug("Progressbar canceled. ID: %d", pid) self.cancel_progressbar.emit(pid) progressbar.canceled.connect(cancel) progressbar.setWindowModality(QtCore.Qt.WindowModal) self.progressbars[pid] = progressbar
def discover(self): """Auto-discover all plugins defined in plugin directory. """ import hyperspyui.plugins as plugins for plug in plugins.__all__: try: __import__('hyperspyui.plugins.' + plug, globals()) except Exception: self.warn("import", plug) # Import any plugins in extra dirs. extra_paths = self.settings['extra_plugin_directories'] if extra_paths: extra_paths = extra_paths.split(os.path.pathsep) for path in extra_paths: if not os.path.isdir(path): path = os.path.dirname(path) modules = glob.glob(path + "/*.py") # TODO: In release form, we should consider supporting # compiled plugins in pyc/pyo format # modules.extend(glob.glob(os.path.dirname(__file__)+"/*.py?")) # If so, ensure that duplicates are removed (picks py over pyc) modules = [m for m in modules if not os.path.basename(m).startswith('_')] for m in modules: name = os.path.splitext(os.path.basename(m))[0] self._import_plugin_from_path(name, m) master = Plugin self.implementors = sorted(self._inheritors(master), key=lambda x: x.name) logger.debug("Found plugins: %s", self.implementors)
def set_splash(self, message): """Set splash message""" if self.splash is None: return if message: logger.debug(message) self.splash.show() self.splash.showMessage(message, Qt.AlignBottom | Qt.AlignCenter | Qt.AlignAbsolute, QtGui.QColor(Qt.white)) QtWidgets.QApplication.processEvents()
def set_splash(self, message): """Set splash message""" if self.splash is None: return if message: logger.debug(message) self.splash.show() self.splash.showMessage( message, Qt.AlignBottom | Qt.AlignCenter | Qt.AlignAbsolute, QtGui.QColor(Qt.white)) QtWidgets.QApplication.processEvents()
def create_default_actions(self): """ Create default actions that can be used for e.g. toolbars and menus, or triggered manually. """ logger.debug("Creating plugin actions") self.plugin_manager.create_actions() self.selectable_tools = QActionGroup(self) self.selectable_tools.setExclusive(True) # Nested docking action ac_nested = QAction(tr("Nested docking"), self) ac_nested.setStatusTip(tr("Allow nested widget docking")) ac_nested.setCheckable(True) ac_nested.setChecked(self.isDockNestingEnabled()) self.connect(ac_nested, SIGNAL('triggered(bool)'), self.setDockNestingEnabled) self.actions['nested_docking'] = ac_nested # Tile windows action ac_tile = QAction(tr("Tile"), self) ac_tile.setStatusTip(tr("Arranges all figures in a tile pattern")) self.connect(ac_tile, SIGNAL('triggered()'), self.main_frame.tileSubWindows) self.actions['tile_windows'] = ac_tile # Cascade windows action ac_cascade = QAction(tr("Cascade"), self) ac_cascade.setStatusTip( tr("Arranges all figures in a cascade pattern")) self.connect(ac_cascade, SIGNAL('triggered()'), self.main_frame.cascadeSubWindows) self.actions['cascade_windows'] = ac_cascade # Close all figures action ac_close_figs = QAction(tr("Close all"), self) ac_close_figs.setStatusTip(tr("Closes all matplotlib figures")) self.connect(ac_close_figs, SIGNAL('triggered()'), lambda: matplotlib.pyplot.close("all")) self.actions['close_all_windows'] = ac_close_figs # Reset geometry action ac_reset_layout = QAction(tr("Reset layout"), self) ac_reset_layout.setStatusTip( tr("Resets layout of toolbars and " "widgets")) self.connect(ac_reset_layout, SIGNAL('triggered()'), self.reset_geometry) self.actions['reset_layout'] = ac_reset_layout
def create_default_actions(self): """ Create default actions that can be used for e.g. toolbars and menus, or triggered manually. """ logger.debug("Creating plugin actions") self.plugin_manager.create_actions() self.selectable_tools = QActionGroup(self) self.selectable_tools.setExclusive(True) # Nested docking action ac_nested = QAction(tr("Nested docking"), self) ac_nested.setStatusTip(tr("Allow nested widget docking")) ac_nested.setCheckable(True) ac_nested.setChecked(self.isDockNestingEnabled()) self.connect(ac_nested, SIGNAL('triggered(bool)'), self.setDockNestingEnabled) self.actions['nested_docking'] = ac_nested # Tile windows action ac_tile = QAction(tr("Tile"), self) ac_tile.setStatusTip(tr("Arranges all figures in a tile pattern")) self.connect(ac_tile, SIGNAL('triggered()'), self.main_frame.tileSubWindows) self.actions['tile_windows'] = ac_tile # Cascade windows action ac_cascade = QAction(tr("Cascade"), self) ac_cascade.setStatusTip( tr("Arranges all figures in a cascade pattern")) self.connect(ac_cascade, SIGNAL('triggered()'), self.main_frame.cascadeSubWindows) self.actions['cascade_windows'] = ac_cascade # Close all figures action ac_close_figs = QAction(tr("Close all"), self) ac_close_figs.setStatusTip(tr("Closes all matplotlib figures")) self.connect(ac_close_figs, SIGNAL('triggered()'), lambda: matplotlib.pyplot.close("all")) self.actions['close_all_windows'] = ac_close_figs # Reset geometry action ac_reset_layout = QAction(tr("Reset layout"), self) ac_reset_layout.setStatusTip(tr("Resets layout of toolbars and " "widgets")) self.connect(ac_reset_layout, SIGNAL('triggered()'), self.reset_geometry) self.actions['reset_layout'] = ac_reset_layout
def _load_if_enabled(self, p_type): if p_type is None or p_type.name is None: return if self.enabled_store[p_type.name] is None: # Init setting to True on first encounter self.enabled_store[p_type.name] = True enabled = self.enabled_store[p_type.name, bool] self._enabled[p_type.name] = (enabled, p_type) if enabled: # Init logger.debug("Initializing plugin: %s", p_type) p = p_type(self.ui) self.plugins[p.name] = p logger.debug("Plugin loaded: %s", p.name) return p return None
def get_figure_filepath_suggestion(self, figure, deault_ext=None): """ Get a suggestion for a file path for saving `figure`. """ canvas = figure.widget() if deault_ext is None: deault_ext = canvas.get_default_filetype() f = canvas.get_default_filename() if not f: f = self.cur_dir # Analyze suggested filename base, tail = os.path.split(f) fn, ext = os.path.splitext(tail) _logger.debug('fn before cleaning is: {}'.format(fn)) # Remove illegal characters and newlines from filename: reserved_characters = r'<>:"/\|?*' for c in reserved_characters: fn = fn.replace(c, '') fn = fn.replace('\n', ' ') _logger.debug('fn after cleaning is: {}'.format(fn)) # If no directory in filename, use self.cur_dir's dirname if base is None or base == "": base = os.path.dirname(self.cur_dir) # If extension is not valid, use the defualt if ext not in canvas.get_supported_filetypes(): ext = deault_ext # Build suggestion and return path_suggestion = os.path.sep.join((base, fn)) path_suggestion = os.path.extsep.join((path_suggestion, ext)) return path_suggestion
def discover(self): """Auto-discover all plugins defined in plugin directory. """ import hyperspyui.plugins as plugins for plug in plugins.__all__: try: __import__('hyperspyui.plugins.' + plug, globals()) except Exception: self.warn("import", plug) # Import any plugins in extra dirs. extra_paths = self.settings['extra_plugin_directories'] if extra_paths: extra_paths = extra_paths.split(os.path.pathsep) for path in extra_paths: if not os.path.isdir(path): path = os.path.dirname(path) modules = glob.glob(path + "/*.py") # TODO: In release form, we should consider supporting # compiled plugins in pyc/pyo format # modules.extend(glob.glob(os.path.dirname(__file__)+"/*.py?")) # If so, ensure that duplicates are removed (picks py over pyc) modules = [ m for m in modules if not os.path.basename(m).startswith('_') ] for m in modules: name = os.path.splitext(os.path.basename(m))[0] self._import_plugin_from_path(name, m) master = Plugin self.implementors = sorted(self._inheritors(master), key=lambda x: x.name) logger.debug("Found plugins: %s", self.implementors)
def save(self, signals=None, filenames=None): logger.debug("entering save(), with args: %s, %s", str(signals), str(filenames)) if signals is None: signals = self.get_selected_wrappers() logger.debug("No signals passed, saving selection: %s", str(signals)) extensions = self.get_accepted_extensions() type_choices = ';;'.join(["*." + e for e in extensions]) type_choices = ';;'.join(("All types (*.*)", type_choices)) logger.debug("Save type choices: %s", type_choices) i = 0 overwrite = None for s in signals: # Match signal to filename. If filenames has not been specified, # or there are no valid filename for curren signal index i, we # have to prompt the user. if filenames is None or len( filenames) <= i or filenames[i] is None: path_suggestion = self.get_signal_filepath_suggestion(s) logger.debug("No filenames passed. Auto-suggestion: %s", path_suggestion) filename = self.prompt_files(type_choices, path_suggestion, False) # Dialog should have prompted about overwrite overwrite = True if not filename: logger.info("Not saving signal %s", str(s)) continue else: filename = filenames[i] overwrite = None # We need to confirm overwrites i += 1 s.signal.save(filename, overwrite)
def default(self): ui = self.ui s = ui.get_selected_signal() logger.debug('Align zero loss peak of ' + str(s)) title = s.metadata.General.title signal_list = [ sig for sig in ui.signals if (sig.signal is not s and isinstance(sig.signal, hyperspy.signals.EELSSpectrum)) ] also_align = [] if len(signal_list) > 0: picker = SignalList(items=signal_list, parent=ui, multiselect=True) diag = ui.show_okcancel_dialog( "Select signals to align with {}".format(title), picker, modal=True) if diag.result() != QDialog.Accepted: return also_align = [sig.signal for sig in picker.get_selected()] logger.debug('Also aligning the following signals\n' + str(also_align)) s.align_zero_loss_peak(also_align=also_align) logger.debug('ZLP alignment complete')
def on_progressbar_finished(self, pid): logger.debug("Progressbar finished. ID: %d", pid) progressbar = self.progressbars.pop(pid) progressbar.close()
def cancel(): # If pid not in collection, it is finished, and cancel # triggered when dialog closed. if pid in self.progressbars: logger.debug("Progressbar canceled. ID: %d", pid) self.cancel_progressbar.emit(pid)
def create_ui(self): self.setIconSize( QSize(self.toolbar_button_size, self.toolbar_button_size)) self.main_frame = QMdiArea() self.setCorner(Qt.TopRightCorner, Qt.RightDockWidgetArea) self.setCorner(Qt.TopLeftCorner, Qt.LeftDockWidgetArea) logger.debug("Initializing plugins") self.init_plugins() logger.debug("Creating default actions") self.create_default_actions() # Goes before menu/toolbar/widgetbar # Needs to go before menu, so console can be in menu logger.debug("Creating console") self.create_console() # This needs to happen before the widgetbar and toolbar logger.debug("Creating menus") self.create_menu() logger.debug("Creating toolbars") self.create_toolbars() logger.debug("Creating widgets") self.create_widgetbar() self.setCentralWidget(self.main_frame)