def func_wrapper(plugin, workspace, *args, **kwargs): """ Wrapper function that, when called, causes the plugin to be loaded into a specific workspace. """ if workspace is None: return parent = workspace.main_tool_bar action = QAction(parent) action.setText(name) if icon is not None: action.setIcon(icon) if location is not None and isinstance(location, str): for level in location.split('/'): parent = self.get_action(parent, level) if isinstance(location, int): parent.insertAction(parent.actions()[location], action) else: parent.addAction(action) action.triggered.connect(lambda: func(plugin, *args, **kwargs))
def create_action(parent, text, on_triggered=None, shortcut=None, shortcut_context=None, icon_name=None): """Create a QAction based on the give properties :param parent: The parent object :param text: Text string to display :param on_triggered: An optional slot to call on the triggered signal :param shortcut: An optional shortcut :param shortcut_context: An optional context for the supplied shortcut. Only applies if a shortcut has been given :param icon_name: The name of the qt awesome uri for an icon. :return: A new QAction object """ action = QAction(text, parent) if on_triggered is not None: action.triggered.connect(on_triggered) if shortcut is not None: action.setShortcut(shortcut) if shortcut_context is not None: action.setShortcutContext(shortcut_context) if icon_name is not None: action.setIcon(get_icon(icon_name)) return action
def func_wrapper(plugin, workspace, *args, **kwargs): """ Wrapper function that, when called, causes the plugin to be loaded into a specific workspace. """ if workspace is None: return if workspace.current_plot_window is None: return parent = workspace.current_plot_window.tool_bar action = QAction(parent) action.setText(name) if icon is not None: action.setIcon(icon) if location is not None and isinstance(location, str): for level in location.split('/'): parent = self.get_action(parent, level) before_action = [x for x in parent.actions() if x.isSeparator()].pop(-2) parent.insertAction(before_action, action) action.triggered.connect(lambda: func(plugin, *args, **kwargs))
def func_wrapper(plugin, workspace, *args, **kwargs): """ Wrapper function that, when called, causes the plugin to be loaded into a specific workspace. """ if workspace is None: return if workspace.current_plot_window is None: return parent = workspace.current_plot_window.tool_bar action = QAction(parent) action.setText(name) if icon is not None: action.setIcon(icon) if location is not None and isinstance(location, str): for level in location.split('/'): parent = self.get_action(parent, level) before_action = [ x for x in parent.actions() if x.isSeparator() ].pop(-2) parent.insertAction(before_action, action) action.triggered.connect(lambda: func(plugin, *args, **kwargs))
def _cfg_action( self, menu, title, setting, icon=None, shortcut=None ): action = QAction(title, self) if icon: action.setIcon(self._ide.theme.qicon(icon)) if shortcut: action.setShortcut(shortcut) action.setToolTip( u'{} ({})'.format(title.replace(u'&', u''), shortcut) ) def change_setting(value): self._ide.extension_manager.fire( 'setting_changed', setting=setting, value=value ) action.triggered.connect(change_setting) action.setCheckable(True) action.setChecked(cfg[setting]) action.setPriority(QAction.HighPriority) menu.addAction(action) self._cfg_actions[setting] = action return action
def create_action(parent, text, shortcut=None, icon=None, tip=None, toggled=None, triggered=None, data=None, menurole=None, context=Qt.WindowShortcut): """Create a QAction""" action = QAction(text, parent) if triggered is not None: action.triggered.connect(triggered) if toggled is not None: action.toggled.connect(toggled) action.setCheckable(True) if icon is not None: if is_text_string(icon): icon = get_icon(icon) action.setIcon(icon) if shortcut is not None: action.setShortcut(shortcut) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if data is not None: action.setData(to_qvariant(data)) if menurole is not None: action.setMenuRole(menurole) #TODO: Hard-code all shortcuts and choose context=Qt.WidgetShortcut # (this will avoid calling shortcuts from another dockwidget # since the context thing doesn't work quite well with these widgets) action.setShortcutContext(context) return action
def create_action(parent, text, shortcut=None, icon=None, tip=None, toggled=None, triggered=None, data=None, menurole=None, context=Qt.WindowShortcut): """Create a QAction.""" action = QAction(text, parent) if triggered is not None: action.triggered.connect(triggered) if toggled is not None: action.toggled.connect(toggled) action.setCheckable(True) if icon is not None: action.setIcon(icon) if shortcut is not None: action.setShortcut(shortcut) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if data is not None: action.setData(to_qvariant(data)) if menurole is not None: action.setMenuRole(menurole) # TODO: Hard-code all shortcuts and choose context=Qt.WidgetShortcut # (this will avoid calling shortcuts from another dockwidget # since the context thing doesn't work quite well with these widgets) action.setShortcutContext(context) return action
def __init__(self, env): super().__init__() self._env = env self._extra_menu_actions = [] self._extra_toolbar_actions = [] self.update_title() main_menu = self.menuBar() self.main_menu = main_menu project_menu = main_menu.addMenu("&Project") toolbar = self.addToolBar("Top") self.toolbar = toolbar new_action = QAction("&New", self) new_action.setShortcut("Ctrl+N") new_action.setStatusTip("Create a new empty project") new_action.triggered.connect(lambda: env.new()) project_menu.addAction(new_action) open_action = QAction("&Open...", self) open_action.setShortcut("Ctrl+O") open_action.setStatusTip("Open an existing project") open_action.triggered.connect(lambda: env.open()) project_menu.addAction(open_action) save_action = QAction("&Save", self) self.save_action = save_action save_action.setShortcut("Ctrl+S") save_action.setIcon(QIcon.fromTheme("document-save")) #save_action.setIcon(self.style().standardIcon( # self.style().SP_DialogSaveButton)) save_action.setStatusTip("Save project") save_action.setEnabled(False) save_action.triggered.connect(lambda: env.save()) project_menu.addAction(save_action) toolbar.addAction(save_action) save_as_action = QAction("Save &As...", self) save_as_action.setStatusTip("Save project under a new name") save_as_action.triggered.connect(lambda: env.save_as()) project_menu.addAction(save_as_action) quit_action = QAction("&Quit", self) quit_action.setShortcut("Ctrl+Q") quit_action.setStatusTip("Quit Hildegard") quit_action.triggered.connect(self.handle_quit) project_menu.addAction(quit_action) self.tabs = QTabWidget() self.tabs.setTabsClosable(True) self.tabs.tabCloseRequested.connect( lambda index: env.close(self.tabs.widget(index).entity, quit=True)) self.tabs.currentChanged.connect(self._handle_switch_to_tab) self.setCentralWidget(self.tabs) self.statusBar()
def _set_rf_menu(self, sec): menu = LEVEL2M('RF', self) menu.setObjectName(sec.upper() + 'App') status = QAction('Main', menu) status.setIcon(qta.icon('mdi.waves')) self.connect_newprocess( status, 'sirius-hla-' + sec.lower() + '-rf-control.py') menu.addAction(status) return menu
class Main(QMainWindow): def __init__(self, tracker: Tracker) -> None: super().__init__() self.qttracker = QtTracker(tracker) self.bg_thread = QThread(self) self.qttracker.moveToThread(self.bg_thread) self.bg_thread.start() self.qttracker.start_recording() self.setCentralWidget(Controls(self.qttracker)) toolbar = QToolBar() self.addToolBar(toolbar) toolbar.setMovable(False) toolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) self.new_action = QAction("New", self) self.new_action.setToolTip("Create a new file for tracking.") icon = self.style().standardIcon(QStyle.SP_FileIcon) self.new_action.setIcon(icon) self.new_action.triggered.connect(self.new_db) toolbar.addAction(self.new_action) self.load_action = QAction("Load", self) self.load_action.setToolTip("Load a existing file for tracking.") icon = self.style().standardIcon(QStyle.SP_DialogOpenButton) self.load_action.setIcon(icon) self.load_action.triggered.connect(self.load_db) toolbar.addAction(self.load_action) @Slot() def load_db(self): fname, ftype = QFileDialog.getOpenFileName( self, "Tracking files", str(Path.home()), "CamTrack Files (*.camtrack)", options=QFileDialog.DontUseNativeDialog) if fname != "": self.qttracker.tracker.open_db(fname) @Slot() def new_db(self): fname, ftype = QFileDialog.getSaveFileName( self, "New file", str(Path.home()), "CamTrack Files (*.camtrack)", options=QFileDialog.DontUseNativeDialog) if fname != 0: if (p := Path(fname).with_suffix('.camtrack')).exists(): p.unlink() self.qttracker.tracker.open_db(fname + '.camtrack')
def create_action(parent, text, shortcut=None, icon=None, tip=None, toggled=None, triggered=None, data=None, menurole=None, context=Qt.WindowShortcut): """Create a QAction""" action = QAction(text, parent) if triggered is not None: action.triggered.connect(triggered) if toggled is not None: action.toggled.connect(toggled) action.setCheckable(True) if icon is not None: if is_text_string(icon): icon = get_icon(icon) action.setIcon(icon) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if data is not None: action.setData(to_qvariant(data)) if menurole is not None: action.setMenuRole(menurole) # Workround for Mac because setting context=Qt.WidgetShortcut # there doesn't have any effect if sys.platform == 'darwin': action._shown_shortcut = None if context == Qt.WidgetShortcut: if shortcut is not None: action._shown_shortcut = shortcut else: # This is going to be filled by # main.register_shortcut action._shown_shortcut = 'missing' else: if shortcut is not None: action.setShortcut(shortcut) action.setShortcutContext(context) else: if shortcut is not None: action.setShortcut(shortcut) action.setShortcutContext(context) return action
def add_menu_to(self, button_name: str, action_texts: List[str], action_commands: List['Callable'], action_icon: QIcon = None) -> Optional[QMenu]: button = self.get_control_widget(button_name) if button is not None: menu = QMenu(self) for text, cmd in zip(action_texts, action_commands): a = QAction(text=text, parent=menu) if action_icon is not None: a.setIcon(action_icon) menu.addAction(a) a.triggered.connect(cmd) button.setMenu(menu) return menu return None
def __init__(self, entity, env): d = Diagram_Item(entity) d.modified_callback = self.set_modified super().__init__(d) self.modified_callback = env.set_modified self.entity = entity show_ports_action = QAction("Connection Ports", self) self._show_ports_action = show_ports_action show_ports_action.setStatusTip("Show connection ports when hovering") show_ports_action.setCheckable(True) show_ports_action.setChecked(False) show_ports_action.setIcon(QIcon.fromTheme("edit-find")) show_ports_action.triggered.connect( lambda x: d.set_show_connection_ports_on_hover(x)) self.view_menu.addAction(show_ports_action) self.tools.append(show_ports_action)
def func_wrapper(plugin, workspace, *args, **kwargs): if workspace is None: return parent = workspace.main_tool_bar action = QAction(parent) action.setText(name) if icon is not None: action.setIcon(icon) if location is not None: for level in location.split('/'): parent = self.get_action(parent, level) parent.addAction(action) action.triggered.connect(lambda: func(plugin, *args, **kwargs))
def append_menu(self, button_name: str, action_text: str, action_command: 'Callable', action_icon: QIcon = None) -> 'QAction': button: 'QToolButton' = self.get_control_widget(button_name) action = None if button is not None: menu = button.menu() if menu is None: menu = self.add_menu_to(button_name, [action_text], [action_command], action_icon=action_icon) return menu.actions()[0] else: action = QAction(text=action_text, parent=menu) if action_icon is not None: action.setIcon(action_icon) menu.addAction(action) action.triggered.connect(action_command) return action
def create_action(parent, text, icon=None, triggered=None, shortcut=None, statustip=None): """Create a QAction""" action = QAction(text, parent) if triggered is not None: action.triggered.connect(triggered) if icon is not None: action.setIcon(icon) if shortcut is not None: action.setShortcut(shortcut) if statustip is not None: action.setStatusTip(statustip) # action.setShortcutContext(Qt.WidgetShortcut) return action
def func_wrapper(*args, **kwargs): app = QApplication.instance() if app.current_workspace is None: return parent = app.current_workspace.main_tool_bar action = QAction(parent) action.setText(name) if icon is not None: action.setIcon(icon) if location is not None: for level in location.split('/'): parent = self.get_action(parent, level) parent.addAction(action) action.triggered.connect(lambda: func(*args, **kwargs))
class SpyderAction(QAction): """Spyder QAction class wrapper to handle cross platform patches.""" def __init__(self, *args, **kwargs): """Spyder QAction class wrapper to handle cross platform patches.""" super(SpyderAction, self).__init__(*args, **kwargs) self._action_no_icon = None if sys.platform == 'darwin': self._action_no_icon = QAction(*args, **kwargs) self._action_no_icon.setIcon(QIcon()) self._action_no_icon.triggered.connect(self.triggered) self._action_no_icon.toggled.connect(self.toggled) self._action_no_icon.changed.connect(self.changed) self._action_no_icon.hovered.connect(self.hovered) else: self._action_no_icon = self def __getattribute__(self, name): """Intercept method calls and apply to both actions, except signals.""" attr = super(SpyderAction, self).__getattribute__(name) if hasattr(attr, '__call__') and name not in [ 'triggered', 'toggled', 'changed', 'hovered' ]: def newfunc(*args, **kwargs): result = attr(*args, **kwargs) if name not in ['setIcon']: action_no_icon = self.__dict__['_action_no_icon'] attr_no_icon = super(QAction, action_no_icon).__getattribute__(name) attr_no_icon(*args, **kwargs) return result return newfunc else: return attr @property def no_icon_action(self): """Return the action without an Icon.""" return self._action_no_icon
def makeAction(parent, descr, menutext, slot, icon=None, key=None, checkable=False): a = QAction(parent) a.setText(menutext) a.setStatusTip(descr) a.setToolTip(textwrap.fill(descr, 25)) if slot: a.triggered.connect(slot) if icon: a.setIcon(getIcon(icon)) if key: a.setShortcut(QKeySequence(key)) if checkable: a.setCheckable(True) return a
def _action(self, title, icon, shortcut, target, checkable=False, checked=False): action = QAction(title, self) if icon: action.setIcon(self._ide.theme.qicon(icon)) if shortcut: action.setShortcut(shortcut) action.setToolTip(u'{} ({})'.format(title.replace(u'&', u''), shortcut)) action.triggered.connect(target) if checkable: action.setCheckable(True) action.setChecked(checked) action.setPriority(QAction.HighPriority) return action
class SpyderAction(QAction): """Spyder QAction class wrapper to handle cross platform patches.""" def __init__(self, *args, **kwargs): """Spyder QAction class wrapper to handle cross platform patches.""" super(SpyderAction, self).__init__(*args, **kwargs) self._action_no_icon = None if sys.platform == 'darwin': self._action_no_icon = QAction(*args, **kwargs) self._action_no_icon.setIcon(QIcon()) self._action_no_icon.triggered.connect(self.triggered) self._action_no_icon.toggled.connect(self.toggled) self._action_no_icon.changed.connect(self.changed) self._action_no_icon.hovered.connect(self.hovered) else: self._action_no_icon = self def __getattribute__(self, name): """Intercept method calls and apply to both actions, except signals.""" attr = super(SpyderAction, self).__getattribute__(name) if hasattr(attr, '__call__') and name not in ['triggered', 'toggled', 'changed', 'hovered']: def newfunc(*args, **kwargs): result = attr(*args, **kwargs) if name not in ['setIcon']: action_no_icon = self.__dict__['_action_no_icon'] attr_no_icon = super(QAction, action_no_icon).__getattribute__(name) attr_no_icon(*args, **kwargs) return result return newfunc else: return attr @property def no_icon_action(self): """Return the action without an Icon.""" return self._action_no_icon
def addMenuItem(self, menu, text, triggered, checkcall=None, enabled=True, statusTip=None, icon=None, enablecall=None): menuTrace = getMenuTrace(menu) menuTrace.append(text) catMenyShortCuts = self.qapp.menuCallShortCuts.get(self.category, {}) keySequence = catMenyShortCuts.get(relax_menu_trace(menuTrace), None) # if not keySequence is None: # Note that the \t will place the keySequence in a nice second column # Like a real shortcut # text = f'{text}\t[{keySequence}]' action = QAction(text, self, enabled=enabled, statusTip=statusTip) #action = TriggerlessShortcutAction(text, self, enabled=enabled, statusTip=statusTip) action.triggered.connect(triggered) if not keySequence is None: action.setShortcut(QtGui.QKeySequence(keySequence)) #Disable the shortcut, #it is handled by the qapp.panelsDialog window #Shortcuts are send to the correct selected panel action.setShortcutContext(Qt.WidgetShortcut) if isinstance(icon, str): icon = QtGui.QIcon(str(respath / 'icons' / 'px16' / icon)) if not icon is None: action.setIcon(icon) menu.addAction(action, checkcall=checkcall, enablecall=enablecall) return action
def create_action( parent, title, triggered=None, toggled=None, shortcut=None, icon=None, tip=None, checkable=None, context=Qt.WindowShortcut, enabled=None, ): """ Create a new QAction """ action = QAction(title, parent) if triggered: if checkable: action.triggered.connect(triggered) else: action.triggered.connect(lambda checked=False: triggered()) if checkable is not None: # Action may be checkable even if the toggled signal is not connected action.setCheckable(checkable) if toggled: action.toggled.connect(toggled) action.setCheckable(True) if icon is not None: assert isinstance(icon, QIcon) action.setIcon(icon) if shortcut is not None: action.setShortcut(shortcut) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if enabled is not None: action.setEnabled(enabled) action.setShortcutContext(context) return action
def func_wrapper(*args, **kwargs): app = QApplication.instance() if app.current_workspace is None: return parent = app.current_workspace.current_plot_window.tool_bar action = QAction(parent) action.setText(name) if icon is not None: action.setIcon(icon) if location is not None: for level in location.split('/'): parent = self.get_action(parent, level) before_action = [ x for x in parent.actions() if x.isSeparator() ].pop() parent.insertAction(before_action, action) action.triggered.connect(lambda: func(*args, **kwargs))
def setAddRemoveColumnMenu(self, columns): """ Fill the "add/remove column" menu. This function is triggered each time the menu is displayed to display a correct icon depending on the status of the column (hidden or not). Args: columns (list(str)): list of column titles """ if self.menuAddRemoveColumn.receivers(QMenu.triggered): self.menuAddRemoveColumn.triggered.disconnect() self.menuAddRemoveColumn.clear() hidden = self.table.getHiddenColumns() for c in columns: action = QAction(c, self.menuAddRemoveColumn) if c in hidden: action.setIcon(icons.get_icon("mdi.close")) else: action.setIcon(icons.get_icon("mdi.check")) self.menuAddRemoveColumn.addAction(action) self.menuAddRemoveColumn.triggered.connect( lambda action: self.table.toggleColumnVisibility(action.text()))
def create_action(parent, text, on_triggered=None, shortcut=None, shortcut_context=None, icon_name=None, shortcut_visible_in_context_menu=None): """Create a QAction based on the give properties :param parent: The parent object :param text: Text string to display :param on_triggered: An optional slot to call on the triggered signal :param shortcut: An optional shortcut :param shortcut_context: An optional context for the supplied shortcut. Only applies if a shortcut has been given :param icon_name: The name of the qt awesome uri for an icon. :param shortcut_visible_in_context_menu: Qt 5.10 decided that all QMenus that are NOT inside a QMenuBar are context menus, and are styled as such. By default keyboard shortcuts are NOT shown on context menus. Set this to True to show them. :return: A new QAction object """ from ...icons import get_icon # noqa action = QAction(text, parent) if on_triggered is not None: action.triggered.connect(on_triggered) if shortcut is not None: if isinstance(shortcut, tuple) or isinstance(shortcut, list): qshortcuts = [QKeySequence(s) for s in shortcut] action.setShortcuts(qshortcuts) else: action.setShortcut(shortcut) if shortcut_context is not None: action.setShortcutContext(shortcut_context) if icon_name is not None: action.setIcon(get_icon(icon_name)) # shortcuts in context menus option is only available after Qt 5.10 if hasattr(action, 'setShortcutVisibleInContextMenu') and shortcut_visible_in_context_menu: action.setShortcutVisibleInContextMenu(shortcut_visible_in_context_menu) return action
def _create_action(self, text, slot=None, shortcut=None, icon=None, tip=None, checkable=False, checked=False): """Convenience function to create actions""" action = QAction(text, self) if icon is not None: action.setIcon(QIcon(icon)) if shortcut is not None: action.setShortcut(shortcut) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if slot is not None: action.triggered.connect(slot) if checkable: action.setCheckable(True) if checked: action.setChecked(True) return action
def _set_optics_menu(self, sec): optics = LEVEL2M('Optics', self) optics.setObjectName(sec.upper() + 'App') if sec in {'tb', 'ts'}: launcher = QAction('Main', optics) self.connect_newprocess(launcher, 'sirius-hla-' + sec + '-ap-control.py') optics.addAction(launcher) elif sec == 'bo': injbo = QAction('InjBO', optics) self.connect_newprocess(injbo, 'sirius-hla-bo-ap-injcontrol.py') optics.addAction(injbo) sofb = QAction('SOFB', optics) sofb.setIcon(qta.icon('fa5s.hammer')) self.connect_newprocess(sofb, 'sirius-hla-' + sec + '-ap-sofb.py') optics.addAction(sofb) if sec in {'tb', 'ts'}: PosAng = QAction('PosAng', optics) self.connect_newprocess(PosAng, 'sirius-hla-' + sec + '-ap-posang.py') optics.addAction(PosAng) if 'tb' in sec: Emittance = QAction('Emittance Meas', optics) self.connect_newprocess(Emittance, 'sirius-hla-tb-ap-emittance.py') optics.addAction(Emittance) if sec in {'bo', 'si'}: TuneCorr = QAction('Tune Correction', optics) icon = qta.icon('mdi.pulse', 'mdi.hammer', options=[ dict(scale_factor=1.3, offset=(0.0, 0.05)), dict(scale_factor=0.72, offset=(-0.1, -0.3), hflip=True) ]) TuneCorr.setIcon(icon) self.connect_newprocess( TuneCorr, 'sirius-hla-' + sec + '-ap-tunecorr.py') optics.addAction(TuneCorr) ChromCorr = QAction('Chromaticity Correction', optics) self.connect_newprocess( ChromCorr, 'sirius-hla-' + sec + '-ap-chromcorr.py') optics.addAction(ChromCorr) trajfit = QAction('Trajectory Fitting', optics) self.connect_newprocess(trajfit, 'sirius-hla-' + sec + '-ap-trajfit.py') optics.addAction(trajfit) if 'si' in sec: CurrLT = QAction('Current and Lifetime', optics) self.connect_newprocess(CurrLT, 'sirius-hla-si-ap-currlt.py') optics.addAction(CurrLT) coupm = QAction('Coupling Meas', optics) self.connect_newprocess(coupm, 'sirius-hla-si-ap-coupmeas.py') optics.addAction(coupm) if 'bo' in sec: ChargeMon = QAction('Charge Monitor', optics) self.connect_newprocess(ChargeMon, 'sirius-hla-bo-ap-chargemon.py') optics.addAction(ChargeMon) ramp = QAction('Ramp', optics) ramp.setIcon(qta.icon('mdi.escalator', scale_factor=1.5)) self.connect_newprocess(ramp, 'sirius-hla-bo-ap-ramp.py') optics.addAction(ramp) return optics
def _set_diagnostic_menu(self, sec): diag = LEVEL2M('DI', self) diag.setObjectName(sec.upper() + 'App') BPMs = self._set_bpm_menu(sec) act = QAction('BPMs', diag) act.setIcon(qta.icon('mdi.currency-sign')) act.setMenu(BPMs) diag.addAction(act) # diag.addMenu(BPMs) if sec in {'tb', 'ts'}: ICTs = QAction('ICTs', diag) self.connect_newprocess(ICTs, 'sirius-hla-' + sec + '-di-icts.py') diag.addAction(ICTs) elif sec in {'bo', 'si'}: DCCT = QMenu('DCCTs', diag) DCCT.setObjectName(sec.upper() + 'App') DCCT.setIcon(qta.icon('mdi.current-dc')) for dev in get_dcct_list(sec.upper()): act_dev = DCCT.addAction(dev) self.connect_newprocess(act_dev, ['sirius-hla-as-di-dcct.py', dev]) diag.addMenu(DCCT) if 'tb' in sec: Slits = QAction('Slits', diag) self.connect_newprocess(Slits, 'sirius-hla-tb-di-slits.py') diag.addAction(Slits) if sec in {'bo', 'si'}: Tune = QAction('Tune', diag) Tune.setIcon(qta.icon('mdi.pulse', scale_factor=1.3)) self.connect_newprocess(Tune, 'sirius-hla-' + sec + '-di-tune.py') diag.addAction(Tune) VLight = QAction('VLight', diag) self.connect_newprocess(VLight, 'sirius-hla-' + sec + '-di-vlight.py') diag.addAction(VLight) if 'si' not in sec: Scrns = QMenu('Screens', diag) Scrns.setObjectName(sec.upper() + 'App') for dev in get_scrn_list(sec.upper()): act_dev = Scrns.addAction(dev) self.connect_newprocess(act_dev, ['sirius-hla-as-di-scrn.py', dev]) diag.addMenu(Scrns) else: Scrap = QAction('Scrapers', diag) self.connect_newprocess(Scrap, 'sirius-hla-si-di-scraps.py') diag.addAction(Scrap) BbB = QMenu('BbB', diag) BbB.setObjectName(sec.upper() + 'App') AllBbB = BbB.addAction('All') self.connect_newprocess( AllBbB, ['sirius-hla-si-di-bbb.py', '-dev', 'all']) for idc in ['Horizontal', 'Vertical', 'Longitudinal']: dev_pref = 'SI-Glob:DI-BbBProc-' + idc[0] act_dev = BbB.addAction(idc) self.connect_newprocess( act_dev, ['sirius-hla-si-di-bbb.py', '-dev', dev_pref]) diag.addMenu(BbB) return diag
class ObjectExplorer(QTreeView): nodevalue_changed = pyqtSignal(AbstractJsonItem) nodeproperty_changed = pyqtSignal(AbstractJsonItem) def __init__(self, rootnode: JsonNode, parent): super().__init__(parent) self.mainwindow = parent self.setModel(JsonDataModel(rootnode, self.mainwindow)) self.model().dataChanged.connect(self.data_changed) self.setItemDelegate(MyItemDelegate()) self.setDragDropMode(QTreeView.DragDrop) self.setDragEnabled(True) self.setAcceptDrops(True) self.setDropIndicatorShown(True) self.doubleClicked.connect(self.double_clicked) # context menu self.setContextMenuPolicy(Qt.CustomContextMenu) self.customContextMenuRequested.connect(self.show_contextmenu) # actions # properties action self.propertiesAction = QAction(self.tr("properties"), self) self.propertiesAction.setIcon(QIcon(pixmap("document_properties.png"))) self.propertiesAction.triggered.connect(self.show_properties) # edit action self.editAction = QAction(self.tr("edit value"), self) self.editAction.setShortcut("F2") self.editAction.setIcon(QIcon(pixmap("edit.png"))) self.editAction.triggered.connect(self.edit_value) # edit key action self.editkeyAction = QAction(self.tr("edit key"), self) self.editkeyAction.setIcon(QIcon(pixmap("kgpg_key1_kgpg.png"))) self.editkeyAction.triggered.connect(self.edit_key) # insert item action self.insertitemAction = QAction(self.tr("insert item"), self) self.insertitemAction.setIcon(QIcon(pixmap("list_add.png"))) self.insertitemAction.triggered.connect(self.insert_item) # insert node action self.insertnodeAction = QAction(self.tr("insert node"), self) self.insertnodeAction.setIcon(QIcon(pixmap("list_add.png"))) self.insertnodeAction.triggered.connect(self.insert_node) # remove item action self.removeitemAction = QAction(self.tr("remove"), self) self.removeitemAction.setIcon(QIcon(pixmap("list_remove"))) self.removeitemAction.triggered.connect(self.remove_item) def data_changed(self, topleft, bottomright, *args): node = topleft.internalPointer() if node is not None and isinstance(node, JsonItem): self.nodevalue_changed.emit(node) def double_clicked(self, *args, **kwargs): index = self.currentIndex() if not index.isValid(): return column = self.model().columns[index.column()] if column.name == "value": self.edit_value() else: self.show_properties() def edit_key(self): index = self.currentIndex() if index.isValid(): node = index.internalPointer() key, b = QInputDialog.getText( self, "Edit Json item", "Insert new key for item:", text=node.key ) if not b: return node.key = key try: # PyQt5 self.model().dataChanged.emit(index, index, [Qt.DisplayRole]) except TypeError: # PyQt4, PySide self.model().dataChanged.emit(index, index) def edit_value(self): index = self.currentIndex() if not index.isValid(): return i = self.model().index(index.row(), 2, index.parent()) self.edit(i) def insert_item(self): index = self.currentIndex() if index.isValid(): node = index.internalPointer() else: node = self.model().root key, b = QInputDialog.getText( self, "Insert Json item", "Insert key for new item:") if not b: return item = JsonItem(key) node.add(item) row = node.index(item) self.model().beginInsertRows(index, row, row) self.model().endInsertRows() def insert_node(self): index = self.currentIndex() parentnode = index.internalPointer() or self.model().root key, b = QInputDialog.getText( self, "Insert Json node", "Insert key for new node:") if not b: return node = JsonNode(key) parentnode.add(node) row = parentnode.index(node) self.model().beginInsertRows(index, row, row) self.model().endInsertRows() def mousePressEvent(self, event): index = self.indexAt(event.pos()) if not index.isValid(): self.setCurrentIndex(QModelIndex()) super().mousePressEvent(event) def refresh(self): self.model().refresh() def remove_item(self): index = self.currentIndex() self.model().beginRemoveRows(index.parent(), index.row(), index.row()) if index.isValid(): node = index.internalPointer() if node.parent is not None: node.parent.remove(node.key) self.model().refresh() self.model().endRemoveRows() def show_contextmenu(self, pos: QPoint): menu = QMenu(self) index = self.currentIndex() node = index.internalPointer() # insert item and node menu.addAction(self.insertitemAction) menu.addAction(self.insertnodeAction) # edit key if isinstance(node, (JsonNode, JsonItem)): menu.addSeparator() menu.addAction(self.editkeyAction) if isinstance(node, JsonItem): menu.addAction(self.editAction) self.editAction.setEnabled(not node.readonly) # remove if isinstance(node, (JsonNode, JsonItem)): menu.addSeparator() menu.addAction(self.removeitemAction) # properties if isinstance(node, JsonItem): menu.addSeparator() menu.addAction(self.propertiesAction) menu.setDefaultAction(self.propertiesAction) menu.popup(self.viewport().mapToGlobal(pos), self.editAction) def show_properties(self): index = self.currentIndex() node = index.internalPointer() if not (index.isValid() and isinstance(node, JsonItem)): return dlg = ItemPropertyDialog(node, self.parent()) if dlg.exec_() == QDialog.Accepted: self.nodeproperty_changed.emit(node)
def __init__(self, item): super().__init__() self._shown = False self.modified_callback = None scene = QGraphicsScene() self.scene = scene self.scene_item = item scene.addItem(item) layout = QBoxLayout(QBoxLayout.TopToBottom, self) scene_view = View(self) self.scene_view = scene_view scene_view.setScene(scene) scene_view.setMinimumSize(350, 350) scene_view.setRenderHint(QPainter.Antialiasing) layout.addWidget(scene_view) self.double_click_callback = None self.mouse_press_callback = None if hasattr(self.scene_item, "mouse_pressed_in"): self.mouse_press_callback = self.scene_item.mouse_pressed_in if hasattr(self.scene_item, "double_clicked_in_background"): self.double_click_callback = \ self.scene_item.double_clicked_in_background if hasattr(self.scene_item, "mouse_moved_in_scene"): self.scene_view.mouse_move_callback = \ self.scene_item.mouse_moved_in_scene self.menus = [] view_menu = QMenu("&View") self.view_menu = view_menu self.menus.append(view_menu) export_menu = QMenu("&Export") self.menus.append(export_menu) self.tools = [] fit_action = QAction("&Fit", self) fit_action.setShortcut("0") fit_action.setIcon(QIcon.fromTheme("zoom-fit-best")) fit_action.setStatusTip("Fit the entire scene to the viewport") fit_action.triggered.connect(self.scene_view.fit_all_in_view) view_menu.addAction(fit_action) self.tools.append(fit_action) reset_action = QAction("&Reset (1:1)", self) reset_action.setShortcut("9") reset_action.setIcon(QIcon.fromTheme("zoom-original")) reset_action.setStatusTip("Reset the view to 100% scale") reset_action.triggered.connect(self.scene_view.reset_scale) view_menu.addAction(reset_action) self.tools.append(reset_action) zoom_in_action = QAction("Zoom &In", self) zoom_in_action.setShortcuts(["+", "="]) zoom_in_action.setStatusTip("Zoom in") zoom_in_action.triggered.connect(lambda: self.scene_view.zoom_in()) view_menu.addAction(zoom_in_action) zoom_out_action = QAction("Zoom &Out", self) zoom_out_action.setShortcuts(["-", "_"]) zoom_out_action.setStatusTip("Zoom out") zoom_out_action.triggered.connect(lambda: self.scene_view.zoom_out()) view_menu.addAction(zoom_out_action) export_svg_action = QAction("As &SVG...", self) export_svg_action.setStatusTip("Export the current tab as an SVG file") export_svg_action.triggered.connect(lambda: export_as_svg(self.scene)) export_menu.addAction(export_svg_action) export_png_action = QAction("As PN&G...", self) export_png_action.setStatusTip("Export the current tab as an PNG file") export_png_action.triggered.connect(lambda: export_as_png(self.scene)) export_menu.addAction(export_png_action) export_pdf_action = QAction("As &PDF...", self) export_pdf_action.setStatusTip("Export the current tab as an PDF file") export_pdf_action.triggered.connect(lambda: export_as_pdf(self.scene)) export_menu.addAction(export_pdf_action) export_svg_clip_action = QAction("To Clipboard as SVG", self) export_svg_clip_action.setStatusTip( "Export the current tab to the clipoard in SVG format") export_svg_clip_action.triggered.connect( lambda: export_to_clipboard_as_svg(self.scene)) export_menu.addAction(export_svg_clip_action) export_image_clip_action = QAction("To &Clipboard as Image", self) export_image_clip_action.setStatusTip( "Export the current tab to the clipoard as an image") export_image_clip_action.triggered.connect( lambda: export_to_clipboard_as_image(self.scene)) export_menu.addAction(export_image_clip_action) self.resize(800, 600)
class ActionCollection: def __init__(self, parent): # Tree Actions self.action_show = QAction('&Show', parent) self.action_show.setIcon(IconCollection.get('flash_on.svg')) self.action_hide = QAction('&Hide', parent) self.action_hide.setIcon(IconCollection.get('flash_off.svg')) self.action_delete = QAction('&Delete', parent) self.action_delete.setIcon(IconCollection.get('cancel.svg')) self.action_focus_camera = QAction('&Focus camera', parent) self.action_focus_camera.setIcon(IconCollection.get('collect.svg')) self.action_highlight = QAction('H&ighlight', parent) self.action_highlight.setIcon(IconCollection.get('idea.svg')) self.action_highlight.setCheckable(True) self.action_wireframe = QAction('&Wireframe', parent) self.action_wireframe.setIcon(IconCollection.get('grid.svg')) self.action_wireframe.setCheckable(True) self.action_properties = QAction('&Properties', parent) self.action_properties.setIcon(IconCollection.get('settings.svg')) self.action_setup_colors = QAction('Setup c&olors', parent) self.action_setup_colors.setIcon(IconCollection.get('picture.svg')) self.action_setup_multiple = QAction('Setup &multiple', parent) self.action_setup_multiple.setIcon(IconCollection.get('picture.svg')) self.action_export_element = QAction('&Export', parent) self.action_export_element.setIcon(IconCollection.get('export.svg')) # MainWindow Actions self.action_load_mesh = QAction('Load &mesh', parent) self.action_load_mesh.setIcon(IconCollection.get('area_chart.svg')) self.action_load_mesh.setShortcut('Ctrl+A') self.action_load_blocks = QAction('Load &blocks', parent) self.action_load_blocks.setIcon(IconCollection.get('data_sheet.svg')) self.action_load_blocks.setShortcut('Ctrl+E') self.action_load_points = QAction('Load &points', parent) self.action_load_points.setIcon(IconCollection.get('scatter_plot.svg')) self.action_load_points.setShortcut('Ctrl+P') self.action_load_lines = QAction('Load &lines', parent) self.action_load_lines.setIcon(IconCollection.get('line_chart.svg')) self.action_load_lines.setShortcut('Ctrl+L') self.action_load_tubes = QAction('Load &tubes', parent) self.action_load_tubes.setIcon(IconCollection.get('radar_plot.svg')) self.action_load_tubes.setShortcut('Ctrl+T') self.action_load_mesh_folder = QAction('Load m&esh folder', parent) self.action_load_mesh_folder.setIcon( IconCollection.get('area_chart.svg')) self.action_load_mesh_folder.setShortcut('Ctrl+Shift+A') self.action_load_blocks_folder = QAction('Load b&locks folder', parent) self.action_load_blocks_folder.setIcon( IconCollection.get('data_sheet.svg')) self.action_load_blocks_folder.setShortcut('Ctrl+Shift+E') self.action_load_points_folder = QAction('Load p&oints folder', parent) self.action_load_points_folder.setIcon( IconCollection.get('scatter_plot.svg')) self.action_load_points_folder.setShortcut('Ctrl+Shift+P') self.action_load_lines_folder = QAction('Load l&ines folder', parent) self.action_load_lines_folder.setIcon( IconCollection.get('line_chart.svg')) self.action_load_lines_folder.setShortcut('Ctrl+Shift+L') self.action_load_tubes_folder = QAction('Load t&ubes folder', parent) self.action_load_tubes_folder.setIcon( IconCollection.get('radar_plot.svg')) self.action_load_tubes_folder.setShortcut('Ctrl+Shift+T') self.action_quit = QAction('&Quit', parent) self.action_quit.setIcon(IconCollection.get('cancel.svg')) self.action_quit.setShortcut('Ctrl+Q') self.action_show_tree = QAction('Show &tree', parent) self.action_show_tree.setIcon(IconCollection.get('list.svg')) self.action_show_tree.setShortcut('Ctrl+W') self.action_help = QAction('&Help', parent) self.action_help.setIcon(IconCollection.get('document.svg')) self.action_help.setShortcut('F1') self.action_about = QAction('&About', parent) self.action_about.setIcon(IconCollection.get('about.svg')) self.action_about.setShortcut('?') self.action_animated = QAction('A&nimate movements', parent) self.action_animated.setIcon(IconCollection.get('film_reel.svg')) self.action_animated.setShortcut('Shift+N') self.action_animated.setCheckable(True) self.action_autofit = QAction('&Auto-fit to screen', parent) self.action_autofit.setIcon(IconCollection.get('globe.svg')) self.action_autofit.setShortcut('Shift+F') self.action_autofit.setCheckable(True) self.action_autorotate = QAction('Auto-&rotate on slice', parent) self.action_autorotate.setIcon(IconCollection.get('process.svg')) self.action_autorotate.setShortcut('Shift+R') self.action_autorotate.setCheckable(True) self.action_turbo_rendering = QAction('&Turbo rendering', parent) self.action_turbo_rendering.setIcon( IconCollection.get('sports_mode.svg')) self.action_turbo_rendering.setShortcut('Shift+T') self.action_turbo_rendering.setCheckable(True) self.action_normal_controller = QAction('&Normal controller', parent) self.action_normal_controller.setIcon( IconCollection.get('rotate_camera.svg')) self.action_normal_controller.setShortcut('Ctrl+N') self.action_measurement_controller = QAction('&Measure meshes', parent) self.action_measurement_controller.setIcon( IconCollection.get('ruler.svg')) self.action_measurement_controller.setShortcut('Ctrl+M') self.action_detection_controller = QAction('&Detect meshes/lines', parent) self.action_detection_controller.setIcon( IconCollection.get('cursor.svg')) self.action_detection_controller.setShortcut('Ctrl+D') self.action_slice_meshes = QAction('&Slice meshes', parent) self.action_slice_meshes.setIcon(IconCollection.get('flash_on.svg')) self.action_slice_meshes.setShortcut('Ctrl+S') self.action_slice_blocks = QAction('Slice &blocks', parent) self.action_slice_blocks.setIcon(IconCollection.get('flash_on.svg')) self.action_slice_blocks.setShortcut('Ctrl+B') self.action_slice_points = QAction('Slice &points', parent) self.action_slice_points.setIcon(IconCollection.get('flash_on.svg')) self.action_slice_points.setShortcut('Ctrl+Shift+P') self.action_xsection = QAction('&Cross-section', parent) self.action_xsection.setIcon(IconCollection.get('flash_on.svg')) self.action_xsection.setShortcut('Ctrl+Shift+S') self.action_grid = QAction('&Grid settings', parent) self.action_grid.setIcon(IconCollection.get('grid.svg')) self.action_grid.setShortcut('Ctrl+G') self.action_viewer_properties = QAction('&Viewer properties', parent) self.action_viewer_properties.setIcon( IconCollection.get('compact_camera.svg')) self.action_viewer_properties.setShortcut('Ctrl+C') self.action_plan_view = QAction('&Plan view', parent) self.action_plan_view.setIcon(IconCollection.get('upload.svg')) self.action_plan_view.setShortcut('Ctrl+1') self.action_north_view = QAction('&North view', parent) self.action_north_view.setIcon(IconCollection.get('up.svg')) self.action_north_view.setShortcut('Ctrl+2') self.action_east_view = QAction('&East view', parent) self.action_east_view.setIcon(IconCollection.get('right.svg')) self.action_east_view.setShortcut('Ctrl+3') self.action_fit_to_screen = QAction('&Fit to screen', parent) self.action_fit_to_screen.setIcon(IconCollection.get('collect.svg')) self.action_fit_to_screen.setShortcut('Ctrl+F') self.action_perspective_projection = QAction('P&erspective projection', parent) self.action_perspective_projection.setIcon( IconCollection.get('ruler.svg')) self.action_perspective_projection.setShortcut('Ctrl+4') self.action_orthographic_projection = QAction( 'O&rthographic projection', parent) self.action_orthographic_projection.setIcon( IconCollection.get('ruler.svg')) self.action_orthographic_projection.setShortcut('Ctrl+5') self.action_take_screenshot = QAction('&Take screenshot', parent) self.action_take_screenshot.setIcon(IconCollection.get('webcam.svg')) self.action_take_screenshot.setShortcut('Shift+S')
def createMenus(self): self.layoutMenu = QtWidgets.QMenu() panDiaAct = QAction("Panels Dialog", self, triggered=self.qapp.showDialog) panDiaAct.setIcon( QIcon( str(respath / 'icons' / 'px16' / 'application_view_gallery.png'))) self.layoutMenu.addAction(panDiaAct) self.newPanelMenu = NewPanelMenu(self, showIcon=True) self.layoutMenu.addMenu(self.newPanelMenu) self.panelMenu = ShowMenu(self, showIcon=True) self.layoutMenu.addMenu(self.panelMenu) self.layoutMenu.addMenu(WindowMenu(self, showIcon=True)) def addWindowMenuItem(caption, function, icon=None): keySequence = self.qapp.menuCallShortCuts.get('window', {}).get( (relax_menu_text(caption), ), None) if not keySequence is None: caption = f'{caption}\t{keySequence}' if isinstance(icon, str): icon = QtGui.QIcon(str(respath / 'icons' / 'px16' / icon)) if not icon is None: action = QAction(caption, self.windowMenu, triggered=function, icon=icon) else: action = QAction(caption, self.windowMenu, triggered=function) self.windowMenu.addAction(action) self.windowMenu = CheckMenu("&Layout Edit") self.windowMenu.setIcon( QtGui.QIcon(str(respath / 'icons' / 'px16' / 'layout_edit.png'))) self.layoutMenu.addMenu(self.windowMenu) self.toolWinAction = QAction(self.winActionLabel(), self, triggered=self.asToolWindow) self.windowMenu.addAction(self.toolWinAction, checkcall=self.isToolWindow) addWindowMenuItem("Distribute", self.container.distribute, 'layouts_six_grid.png') addWindowMenuItem("Drop In", lambda: self.qapp.panels.ezm.drop_in(self.container), 'layouts_body_select.png') addWindowMenuItem("Screenshot to Clipboard", self.screenShot, 'lcd_tv_image.png') addWindowMenuItem("Cycle Tag Level", self.cycle_tag_level) addWindowMenuItem("Full Screen", self.fullScreen, 'view_fullscreen_view.png') addWindowMenuItem("Hide/Show Menu && Statusbar", self.toggleMenuStatusbar) addWindowMenuItem('Save Layout...', self.qapp.panelsDialog.layoutMenu.saveLayout) self.layoutMenu.addSeparator() self.qapp.panelsDialog.layoutMenu.addLayoutActions(self.layoutMenu) self.layoutMenu.addSeparator() act = QAction("E&xit", self, shortcut=QKeySequence.Quit, statusTip="Exit the application", triggered=QApplication.instance().quit) act.setIcon( QtGui.QIcon(str(respath / 'icons' / 'px16' / 'door_out.png'))) self.layoutMenu.addAction(act) self.panelsDialogBtn = QtWidgets.QToolButton(self) self.panelsDialogBtn.setIcon( QIcon( str(respath / 'icons' / 'px16' / 'application_view_gallery.png'))) self.panelsDialogBtn.clicked.connect(self.qapp.showDialog) self.panelsDialogBtn.setMenu(self.layoutMenu) self.panelsDialogBtn.setPopupMode( QtWidgets.QToolButton.MenuButtonPopup) self.menuBar().setCornerWidget(self.panelsDialogBtn, corner=Qt.TopLeftCorner) self.cycleTabBtn = QtWidgets.QToolButton(self) self.cycleTabBtn.setIcon( QIcon(str(respath / 'icons' / 'px16' / 'layout_content.png'))) self.cycleTabBtn.clicked.connect(self.cycle_tag_level) self.cycleTabBtn.setMenu(self.windowMenu) self.cycleTabBtn.setPopupMode(QtWidgets.QToolButton.MenuButtonPopup) self.menuBar().setCornerWidget(self.cycleTabBtn, corner=Qt.TopRightCorner)
class UiLinelistsWindow(object): # this code was taken as-is from the Designer. # Cleaning it up sounds like a lower priority # task for now. def setupUi(self, MainWindow, title): MainWindow.setWindowTitle(title) MainWindow.setObjectName("MainWindow") MainWindow.resize(600, 850) MainWindow.setMinimumSize(QSize(300, 350)) self.centralWidget = QWidget(MainWindow) self.centralWidget.setObjectName("centralWidget") self.gridLayout = QGridLayout(self.centralWidget) self.gridLayout.setContentsMargins(11, 11, 11, 11) self.gridLayout.setSpacing(6) self.gridLayout.setObjectName("gridLayout") self.horizontalLayout_5 = QHBoxLayout() self.horizontalLayout_5.setContentsMargins(11, 11, 11, 11) self.horizontalLayout_5.setSpacing(6) self.horizontalLayout_5.setObjectName("horizontalLayout_5") self.lines_selected_label = QLabel(self.centralWidget) self.lines_selected_label.setObjectName("lines_selected_label") self.horizontalLayout_5.addWidget(self.lines_selected_label) self.label = QLabel(self.centralWidget) self.label.setObjectName("label") self.horizontalLayout_5.addWidget(self.label) spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout_5.addItem(spacerItem) self.draw_button = QPushButton(self.centralWidget) self.draw_button.setObjectName("draw_button") self.horizontalLayout_5.addWidget(self.draw_button) self.erase_button = QPushButton(self.centralWidget) self.erase_button.setObjectName("erase_button") self.horizontalLayout_5.addWidget(self.erase_button) self.dismiss_button = QPushButton(self.centralWidget) self.dismiss_button.setObjectName("dismiss_button") self.horizontalLayout_5.addWidget(self.dismiss_button) self.gridLayout.addLayout(self.horizontalLayout_5, 4, 0, 1, 1) self.verticalLayout_11 = QVBoxLayout() self.verticalLayout_11.setContentsMargins(11, 11, 11, 11) self.verticalLayout_11.setSpacing(6) self.verticalLayout_11.setObjectName("verticalLayout_11") self.tabWidget = QTabWidget(self.centralWidget) self.tabWidget.setObjectName("tabWidget") self.tabWidget.setTabsClosable(True) self.verticalLayout_11.addWidget(self.tabWidget) self.gridLayout.addLayout(self.verticalLayout_11, 0, 0, 1, 1) self.horizontalLayout_7 = QHBoxLayout() self.horizontalLayout_7.setContentsMargins(11, 11, 11, 11) self.horizontalLayout_7.setSpacing(6) spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout_7.addItem(spacerItem) self.horizontalLayout_7.setObjectName("horizontalLayout_7") self.gridLayout.addLayout(self.horizontalLayout_7, 2, 0, 2, 1) MainWindow.setCentralWidget(self.centralWidget) # self.menuBar = QMenuBar(MainWindow) # self.menuBar.setGeometry(QRect(0, 0, 767, 22)) # self.menuBar.setObjectName("menuBar") # # self.menuFile = QMenu(self.menuBar) # self.menuFile.setObjectName("menuFile") # # MainWindow.setMenuBar(self.menuBar) self.mainToolBar = QToolBar(MainWindow) self.mainToolBar.setMovable(False) self.mainToolBar.setFloatable(False) self.mainToolBar.setObjectName("mainToolBar") MainWindow.addToolBar(Qt.TopToolBarArea, self.mainToolBar) # self.statusBar = QStatusBar(MainWindow) # self.statusBar.setObjectName("statusBar") # MainWindow.setStatusBar(self.statusBar) self.actionOpen = QAction(MainWindow) icon = QIcon(os.path.join(ICON_PATH, "Open Folder-48.png")) self.actionOpen.setIcon(icon) self.actionOpen.setObjectName("actionOpen") self.actionExport = QAction(MainWindow) icon = QIcon(os.path.join(ICON_PATH, "Export-48.png")) self.actionExport.setIcon(icon) self.actionExport.setObjectName("actionExport") self.line_list_selector = QComboBox() self.line_list_selector.setToolTip( "Select line list from internal library") self.actionExit = QAction(MainWindow) self.actionExit.setObjectName("actionExit") self.actionRemove = QAction(MainWindow) self.actionRemove.setObjectName("actionRemove") self.actionChange_Color = QAction(MainWindow) self.actionChange_Color.setObjectName("actionChange_Color") # self.menuFile.addAction(self.actionOpen) # self.menuFile.addSeparator() # self.menuFile.addAction(self.actionExit) # self.menuBar.addAction(self.menuFile.menuAction()) self.mainToolBar.addAction(self.actionOpen) self.mainToolBar.addAction(self.actionExport) self.mainToolBar.addSeparator() self.mainToolBar.addWidget(self.line_list_selector) self.retranslateUi(MainWindow) QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): _translate = QCoreApplication.translate self.lines_selected_label.setText(_translate("MainWindow", "0")) self.lines_selected_label.setToolTip( "Total number of lines selected in all sets.") self.label.setText(_translate("MainWindow", "lines selected")) self.label.setToolTip("Total number of lines selected in all sets.") self.draw_button.setText(_translate("MainWindow", "Draw")) self.draw_button.setToolTip( "Plot markers for all selected lines in all sets.") self.erase_button.setText(_translate("MainWindow", "Erase")) self.erase_button.setToolTip("Erase all markers") self.dismiss_button.setText(_translate("MainWindow", "Dismiss")) self.dismiss_button.setToolTip("Dismiss this window") # self.menuFile.setTitle(_translate("MainWindow", "File")) self.actionOpen.setText(_translate("MainWindow", "Open")) self.actionExport.setText( _translate("MainWindow", "Export plotted lines")) self.actionExit.setText(_translate("MainWindow", "Exit")) self.actionRemove.setText(_translate("MainWindow", "Remove")) self.actionRemove.setToolTip( _translate("MainWindow", "Removes the selected layer")) self.actionChange_Color.setText( _translate("MainWindow", "Change Color")) self.actionChange_Color.setToolTip( _translate("MainWindow", "Change the line color selected layer"))
class MainWindow(QMainWindow): def __init__(self, parent=None): super().__init__(parent) self.recording_enabled = False self.serial = serial.Serial() self.rootnode = JsonNode('') self._connected = False self._dirty = False self._filename = None # settings self.settings = QSettingsManager() set_default_settings(self.settings) # Controller Settings self.settingsDialog = None # object explorer self.objectexplorer = ObjectExplorer(self.rootnode, self) self.objectexplorer.nodevalue_changed.connect(self.send_serialdata) self.objectexplorer.nodeproperty_changed.connect(self.set_dirty) self.objectexplorerDockWidget = QDockWidget(self.tr("object explorer"), self) self.objectexplorerDockWidget.setObjectName( "objectexplorer_dockwidget") self.objectexplorerDockWidget.setWidget(self.objectexplorer) # plot widget self.plot = PlotWidget(self.rootnode, self.settings, self) # plot settings self.plotsettings = PlotSettingsWidget(self.settings, self.plot, self) self.plotsettingsDockWidget = QDockWidget(self.tr("plot settings"), self) self.plotsettingsDockWidget.setObjectName("plotsettings_dockwidget") self.plotsettingsDockWidget.setWidget(self.plotsettings) # log widget self.loggingWidget = LoggingWidget(self) self.loggingDockWidget = QDockWidget(self.tr("logger"), self) self.loggingDockWidget.setObjectName("logging_dockwidget") self.loggingDockWidget.setWidget(self.loggingWidget) # record widget self.recordWidget = RecordWidget(self.rootnode, self) self.recordDockWidget = QDockWidget(self.tr("data recording"), self) self.recordDockWidget.setObjectName("record_dockwidget") self.recordDockWidget.setWidget(self.recordWidget) # actions and menus self._init_actions() self._init_menus() # statusbar statusbar = self.statusBar() statusbar.setVisible(True) self.connectionstateLabel = QLabel(self.tr("Not connected")) statusbar.addPermanentWidget(self.connectionstateLabel) statusbar.showMessage(self.tr("Ready")) # layout self.setCentralWidget(self.plot) self.addDockWidget(Qt.LeftDockWidgetArea, self.objectexplorerDockWidget) self.addDockWidget(Qt.LeftDockWidgetArea, self.plotsettingsDockWidget) self.addDockWidget(Qt.BottomDockWidgetArea, self.loggingDockWidget) self.addDockWidget(Qt.BottomDockWidgetArea, self.recordDockWidget) self.load_settings() def _init_actions(self): # Serial Dialog self.serialdlgAction = QAction(self.tr("Serial Settings..."), self) self.serialdlgAction.setShortcut("F6") self.serialdlgAction.setIcon(QIcon(pixmap("configure.png"))) self.serialdlgAction.triggered.connect(self.show_serialdlg) # Connect self.connectAction = QAction(self.tr("Connect"), self) self.connectAction.setShortcut("F5") self.connectAction.setIcon(QIcon(pixmap("network-connect-3.png"))) self.connectAction.triggered.connect(self.toggle_connect) # Quit self.quitAction = QAction(self.tr("Quit"), self) self.quitAction.setShortcut("Alt+F4") self.quitAction.setIcon(QIcon(pixmap("window-close-3.png"))) self.quitAction.triggered.connect(self.close) # Save Config as self.saveasAction = QAction(self.tr("Save as..."), self) self.saveasAction.setShortcut("Ctrl+Shift+S") self.saveasAction.setIcon(QIcon(pixmap("document-save-as-5.png"))) self.saveasAction.triggered.connect(self.show_savecfg_dlg) # Save file self.saveAction = QAction(self.tr("Save"), self) self.saveAction.setShortcut("Ctrl+S") self.saveAction.setIcon(QIcon(pixmap("document-save-5.png"))) self.saveAction.triggered.connect(self.save_file) # Load file self.loadAction = QAction(self.tr("Open..."), self) self.loadAction.setShortcut("Ctrl+O") self.loadAction.setIcon(QIcon(pixmap("document-open-7.png"))) self.loadAction.triggered.connect(self.show_opencfg_dlg) # New self.newAction = QAction(self.tr("New"), self) self.newAction.setShortcut("Ctrl+N") self.newAction.setIcon(QIcon(pixmap("document-new-6.png"))) self.newAction.triggered.connect(self.new) # start recording self.startrecordingAction = QAction(self.tr("Start recording"), self) self.startrecordingAction.setShortcut("F9") self.startrecordingAction.setIcon(QIcon(pixmap("media-record-6.png"))) self.startrecordingAction.triggered.connect(self.start_recording) # stop recording self.stoprecordingAction = QAction(self.tr("Stop recording"), self) self.stoprecordingAction.setShortcut("F10") self.stoprecordingAction.setIcon(QIcon(pixmap("media-playback-stop-8.png"))) self.stoprecordingAction.setEnabled(False) self.stoprecordingAction.triggered.connect(self.stop_recording) # clear record self.clearrecordAction = QAction(self.tr("Clear"), self) self.clearrecordAction.setIcon(QIcon(pixmap("editclear.png"))) self.clearrecordAction.triggered.connect(self.clear_record) # export record self.exportcsvAction = QAction(self.tr("Export to csv..."), self) self.exportcsvAction.setIcon(QIcon(pixmap("text_csv.png"))) self.exportcsvAction.triggered.connect(self.export_csv) # show record settings self.recordsettingsAction = QAction(self.tr("Settings..."), self) self.recordsettingsAction.setIcon(QIcon(pixmap("configure.png"))) self.recordsettingsAction.triggered.connect(self.show_recordsettings) # Info self.infoAction = QAction(self.tr("Info"), self) self.infoAction.setShortcut("F1") self.infoAction.triggered.connect(self.show_info) def _init_menus(self): # file menu self.fileMenu = self.menuBar().addMenu(self.tr("File")) self.fileMenu.addAction(self.newAction) self.fileMenu.addAction(self.loadAction) self.fileMenu.addAction(self.saveAction) self.fileMenu.addAction(self.saveasAction) self.fileMenu.addSeparator() self.fileMenu.addAction(self.connectAction) self.fileMenu.addAction(self.serialdlgAction) self.fileMenu.addSeparator() self.fileMenu.addAction(self.quitAction) # view menu self.viewMenu = self.menuBar().addMenu(self.tr("View")) self.viewMenu.addAction( self.objectexplorerDockWidget.toggleViewAction()) self.viewMenu.addAction(self.plotsettingsDockWidget.toggleViewAction()) self.viewMenu.addAction(self.loggingDockWidget.toggleViewAction()) self.viewMenu.addAction(self.recordDockWidget.toggleViewAction()) # record menu self.recordMenu = self.menuBar().addMenu(self.tr("Record")) self.recordMenu.addAction(self.startrecordingAction) self.recordMenu.addAction(self.stoprecordingAction) self.recordMenu.addAction(self.exportcsvAction) self.recordMenu.addSeparator() self.recordMenu.addAction(self.clearrecordAction) self.recordMenu.addSeparator() self.recordMenu.addAction(self.recordsettingsAction) # info menu self.menuBar().addAction(self.infoAction) def show_info(self): QMessageBox.about( self, QApplication.applicationName(), "%s %s\n" "Copyright (c) by %s" % ( QCoreApplication.applicationName(), QCoreApplication.applicationVersion(), QCoreApplication.organizationName(), ) ) def load_file(self, filename): old_filename = self.filename if self.filename != filename else None self.filename = filename try: with open(filename, 'rb') as f: try: self.objectexplorer.model().beginResetModel() self.rootnode.load(bytearray_to_utf8(f.read())) self.objectexplorer.model().endResetModel() except ValueError as e: critical(self, "File '%s' is not a valid config file." % filename) logger.error(str(e)) if old_filename is not None: self.load_file(old_filename) else: self.filename = None except FileNotFoundError as e: logger.error(str(e)) self.filename = None self.objectexplorer.refresh() def load_settings(self): settings = QSettings() # window geometry try: self.restoreGeometry(settings.value(GEOMETRY_SETTING)) except: logger.debug("error restoring window geometry") # window state try: self.restoreState(settings.value(WINDOWSTATE_SETTING)) except: logger.debug("error restoring window state") # filename self.filename = settings.value(FILENAME_SETTING) if self.filename is not None: self.load_file(self.filename) def save_settings(self): settings = QSettings() settings.setValue(WINDOWSTATE_SETTING, self.saveState()) settings.setValue(GEOMETRY_SETTING, self.saveGeometry()) settings.setValue(FILENAME_SETTING, self.filename) def closeEvent(self, event): if self.dirty: res = QMessageBox.question( self, QCoreApplication.applicationName(), self.tr("Save changes to file '%s'?" % self.filename if self.filename is not None else "unknown"), QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel ) if res == QMessageBox.Cancel: event.ignore() return elif res == QMessageBox.Yes: self.save_file() self.save_settings() try: self.worker.quit() except AttributeError: pass try: self.serial.close() except (SerialException, AttributeError): pass def new(self): self.objectexplorer.model().beginResetModel() self.rootnode.clear() self.objectexplorer.model().endResetModel() def send_reset(self): jsonstring = json.dumps({"resetpid": 1}) self.serial.write(bytearray(jsonstring, 'utf-8')) def receive_serialdata(self, time, data): self.loggingWidget.log_input(data) try: self.rootnode.from_json(data) except ValueError as e: logger.error(str(e)) # refresh widgets self.objectexplorer.refresh() self.plot.refresh(time) if self.recording_enabled: self.recordWidget.add_data(time, self.rootnode) def send_serialdata(self, node): if isinstance(node, JsonItem): if self.serial.isOpen(): s = node.to_json() self.serial.write(utf8_to_bytearray(s + '\n')) self.loggingWidget.log_output(s.strip()) def show_serialdlg(self): dlg = SerialDialog(self.settings, self) dlg.exec_() def toggle_connect(self): if self.serial.isOpen(): self.disconnect() else: self.connect() def connect(self): # Load port setting port = self.settings.get(PORT_SETTING) baudrate = self.settings.get(BAUDRATE_SETTING) # If no port has been selected before show serial settings dialog if port is None: if self.show_serialdlg() == QDialog.Rejected: return port = self.settings.get(PORT_SETTING) baudrate = self.settings.get(BAUDRATE_SETTING) # Serial connection try: self.serial.port = port self.serial.baudrate = baudrate self.serial.open() except ValueError: QMessageBox.critical( self, QCoreApplication.applicationName(), self.tr("Serial parameters e.g. baudrate, databits are out " "of range.") ) except SerialException: QMessageBox.critical( self, QCoreApplication.applicationName(), self.tr("The device '%s' can not be found or can not be " "configured." % port) ) else: self.worker = SerialWorker(self.serial, self) self.worker.data_received.connect(self.receive_serialdata) self.worker.start() self.connectAction.setText(self.tr("Disconnect")) self.connectAction.setIcon(QIcon(pixmap("network-disconnect-3.png"))) self.serialdlgAction.setEnabled(False) self.connectionstateLabel.setText( self.tr("Connected to %s") % port) self._connected = True self.objectexplorer.refresh() def disconnect(self): self.worker.quit() self.serial.close() self.connectAction.setText(self.tr("Connect")) self.connectAction.setIcon(QIcon(pixmap("network-connect-3.png"))) self.serialdlgAction.setEnabled(True) self.connectionstateLabel.setText(self.tr("Not connected")) self._connected = False self.objectexplorer.refresh() def show_savecfg_dlg(self): filename, _ = QFileDialog.getSaveFileName( self, self.tr("Save configuration file..."), directory=os.path.expanduser("~"), filter="Json file (*.json)" ) if filename: self.filename = filename self.save_file() def save_file(self): if self.filename is not None: config_string = self.rootnode.dump() with open(self.filename, 'w') as f: f.write(config_string) self.dirty = False else: self.show_savecfg_dlg() def show_opencfg_dlg(self): # show file dialog filename, _ = QFileDialog.getOpenFileName( self, self.tr("Open configuration file..."), directory=os.path.expanduser("~"), filter=self.tr("Json file (*.json);;All files (*.*)") ) # load config file if filename: self.load_file(filename) def refresh_window_title(self): s = "%s %s" % (QCoreApplication.applicationName(), QCoreApplication.applicationVersion()) if self.filename is not None: s += " - " + self.filename if self.dirty: s += "*" self.setWindowTitle(s) def start_recording(self): self.recording_enabled = True self.startrecordingAction.setEnabled(False) self.stoprecordingAction.setEnabled(True) def stop_recording(self): self.recording_enabled = False self.startrecordingAction.setEnabled(True) self.stoprecordingAction.setEnabled(False) def export_csv(self): filename, _ = QFileDialog.getSaveFileName( self, QCoreApplication.applicationName(), filter="CSV files(*.csv);;All files (*.*)" ) if filename == "": return # get current dataframe and export to csv df = self.recordWidget.dataframe decimal = self.settings.get(DECIMAL_SETTING) df = df.applymap(lambda x: str(x).replace(".", decimal)) df.to_csv( filename, index_label="time", sep=self.settings.get(SEPARATOR_SETTING) ) def clear_record(self): self.recordWidget.clear() def show_recordsettings(self): dlg = CSVSettingsDialog(self) dlg.exec_() # filename property @property def filename(self): return self._filename @filename.setter def filename(self, value=""): self._filename = value self.refresh_window_title() # dirty property @property def dirty(self): return self._dirty @dirty.setter def dirty(self, value): self._dirty = value self.refresh_window_title() def set_dirty(self): self.dirty = True # connected property @property def connected(self): return self._connected