def _customContextMenu(self, pos): menu = QMenu(self) menu.addAction(self.closeAction) menu.addSeparator() menu.addAction(self.dockProperties) menu.popup(self.mapToGlobal(pos))
def _show_context_menu(self, event): """Display a relevant context menu on the canvas :param event: The MouseEvent that generated this call """ if not event.inaxes: # the current context menus are ony relevant for axes return fig_type = figure_type(self.canvas.figure) if fig_type == FigureType.Empty: # Fitting or changing scale types does not make sense in this case return menu = QMenu() if fig_type == FigureType.Image or fig_type == FigureType.Contour: if isinstance(event.inaxes, MantidAxes): self._add_axes_scale_menu(menu, event.inaxes) self._add_normalization_option_menu(menu, event.inaxes) self._add_colorbar_axes_scale_menu(menu, event.inaxes) elif fig_type == FigureType.Surface: self._add_colorbar_axes_scale_menu(menu, event.inaxes) elif fig_type != FigureType.Wireframe: if self.fit_browser.tool is not None: self.fit_browser.add_to_menu(menu) menu.addSeparator() self._add_axes_scale_menu(menu, event.inaxes) if isinstance(event.inaxes, MantidAxes): self._add_normalization_option_menu(menu, event.inaxes) self.add_error_bars_menu(menu, event.inaxes) self._add_marker_option_menu(menu, event) self._add_plot_type_option_menu(menu, event.inaxes) menu.exec_(QCursor.pos())
def open_menu(self, position): menu = QMenu(self) preset_menu = menu.addMenu('Presets') preset_menu.addAction('New preset', self.new_preset_dialog) preset_menu.addSeparator() preset_names = CONFIG.get_header_presets() if len(preset_names) == 0: action = preset_menu.addAction('No presets') action.setEnabled(False) else: delete_menu = menu.addMenu('Delete preset') for name in preset_names: preset_menu.addAction(name, partial(self.load_preset, name)) delete_menu.addAction(name, partial(self.delete_preset, name)) menu.addSeparator() menu.addAction('New column...', self.create_new_column_dialog) if len(self.columnList.selectedIndexes()) > 0: menu.addAction('Delete selected', self.delete_selected) menu.popup(self.columnList.viewport().mapToGlobal(position))
class WorkflowWidget(QWidget): sigAddFunction = Signal(object) def __init__(self, workflowview: QAbstractItemView): super(WorkflowWidget, self).__init__() self.view = workflowview self.toolbar = QToolBar() self.addfunctionmenu = QToolButton() self.addfunctionmenu.setIcon(QIcon(path("icons/addfunction.png"))) self.addfunctionmenu.setText("Add Function") # Defer menu population to once the plugins have been loaded; otherwise, the menu may not contain anything # if this widget is init'd before all plugins have been loaded. self.functionmenu = QMenu() self.functionmenu.aboutToShow.connect(self.populateFunctionMenu) self.addfunctionmenu.setMenu(self.functionmenu) self.addfunctionmenu.setPopupMode(QToolButton.InstantPopup) self.toolbar.addWidget(self.addfunctionmenu) # self.toolbar.addAction(QIcon(path('icons/up.png')), 'Move Up') # self.toolbar.addAction(QIcon(path('icons/down.png')), 'Move Down') self.toolbar.addAction(QIcon(path("icons/folder.png")), "Load Workflow") self.toolbar.addAction(QIcon(path("icons/trash.png")), "Delete Operation", self.deleteOperation) v = QVBoxLayout() v.addWidget(self.view) v.addWidget(self.toolbar) v.setContentsMargins(0, 0, 0, 0) self.setLayout(v) def populateFunctionMenu(self): self.functionmenu.clear() sortingDict = {} for plugin in pluginmanager.get_plugins_of_type("OperationPlugin"): typeOfOperationPlugin = plugin.getCategory() if not typeOfOperationPlugin in sortingDict.keys(): sortingDict[typeOfOperationPlugin] = [] sortingDict[typeOfOperationPlugin].append(plugin) for key in sortingDict.keys(): self.functionmenu.addSeparator() self.functionmenu.addAction(key) self.functionmenu.addSeparator() for plugin in sortingDict[key]: self.functionmenu.addAction( plugin.name, partial(self.addOperation, plugin, autoconnectall=True)) def addOperation(self, operation: OperationPlugin, autoconnectall=True): self.view.model().workflow.addOperation(operation(), autoconnectall) print("selected new row:", self.view.model().rowCount() - 1) self.view.setCurrentIndex(self.view.model().index( self.view.model().rowCount() - 1, 0)) def deleteOperation(self): for index in self.view.selectedIndexes(): operation = self.view.model().workflow.operations[index.row()] self.view.model().workflow.remove_operation(operation)
def customMenuRequested(self, position): """Builds a custom menu for items items""" index = self.indexAt(position) # type: QModelIndex menu = QMenu(self) if index.isValid(): if index.data(EnsembleModel.data_type_role ) == WorkspaceDataType.Ensemble: # Allow renaming the ensemble via the context menu rename_action = QAction("Rename Collection", menu) rename_action.triggered.connect(self._rename_action) menu.addAction(rename_action) # Allow toggling the active ensemble via the context menu # * there can only be at most 1 active ensemble # * there are only 0 active ensembles when data has not yet been loaded ??? # * opening data updates the active ensemble to that data is_active = index.data(EnsembleModel.active_role) active_text = "Active" toggle_active_action = QAction(active_text, menu) toggle_active_action.setCheckable(True) if is_active is True: toggle_active_action.setChecked(True) else: toggle_active_action.setChecked(False) toggle_active_action.setText(f"Not {active_text}") # Make sure to update the model with the active / deactivated ensemble toggle_active_action.toggled.connect(self._set_active_action) # Don't allow deactivating the active ensemble if there is only one loaded if self.model().rowCount() == 1: toggle_active_action.setEnabled(False) menu.addAction(toggle_active_action) menu.addSeparator() remove_text = "Remove " data_type_role = index.data(EnsembleModel.data_type_role) if data_type_role == WorkspaceDataType.Ensemble: remove_text += "Ensemble" elif data_type_role == WorkspaceDataType.Catalog: remove_text += "Catalog" elif data_type_role == WorkspaceDataType.Intent: remove_text += "Item" remove_action = QAction(remove_text, menu) remove_action.triggered.connect(self._remove_action) menu.addAction(remove_action) else: create_ensemble_action = QAction("Create New Collection", menu) create_ensemble_action.triggered.connect( self._create_ensemble_action) menu.addAction(create_ensemble_action) # Display menu wherever the user right-clicked menu.popup(self.viewport().mapToGlobal(position))
def contextMenuEvent(self, event): """Show context menu.""" menu = QMenu(self) menu.addAction(self._act_check_all) menu.addAction(self._act_uncheck_all) menu.addSeparator() menu.addAction(self._act_expand_all) menu.addAction(self._act_collapse_all) menu.popup(event.globalPos())
def context_menu(self): try: menu = super(PyDMRelatedDisplayButton, self).context_menu() except: menu = QMenu(self) if len(menu.findChildren(QAction)) > 0: menu.addSeparator() menu.addAction(self.open_in_new_window_action) return menu
def context_menu(self): try: menu = super(PyDMRelatedDisplayButton, self).context_menu() except: menu = QMenu(self) if len(menu.findChildren(QAction)) > 0: menu.addSeparator() menu.addAction(self.open_in_new_window_action) return menu
def add_error_bars_menu(self, menu, ax): """ Add menu actions to toggle the errors for all lines in the plot. Lines without errors are added in the context menu first, then lines containing errors are appended afterwards. This is done so that the context menu always has the same order of curves as the legend is currently showing - and the legend always appends curves with errors after the lines without errors. Relevant source, as of 10 July 2019: https://github.com/matplotlib/matplotlib/blob/154922992722db37a9d9c8680682ccc4acf37f8c/lib/matplotlib/legend.py#L1201 :param menu: The menu to which the actions will be added :type menu: QMenu :param ax: The Axes containing lines to toggle errors on """ # if the ax is not a MantidAxes, and there are no errors plotted, # then do not add any options for the menu if not isinstance(ax, MantidAxes) and len(ax.containers) == 0: return error_bars_menu = QMenu(self.ERROR_BARS_MENU_TEXT, menu) error_bars_menu.addAction(self.SHOW_ERROR_BARS_BUTTON_TEXT, partial(self.errors_manager.update_plot_after, self.errors_manager.toggle_all_errors, ax, make_visible=True)) error_bars_menu.addAction(self.HIDE_ERROR_BARS_BUTTON_TEXT, partial(self.errors_manager.update_plot_after, self.errors_manager.toggle_all_errors, ax, make_visible=False)) menu.addMenu(error_bars_menu) self.errors_manager.active_lines = self.errors_manager.get_curves_from_ax(ax) # if there's more than one line plotted, then # add a sub menu, containing an action to hide the # error bar for each line error_bars_menu.addSeparator() add_later = [] for index, line in enumerate(self.errors_manager.active_lines): if curve_has_errors(line): curve_props = CurveProperties.from_curve(line) # Add lines without errors first, lines with errors are appended later. Read docstring for more info if not isinstance(line, ErrorbarContainer): action = error_bars_menu.addAction(line.get_label(), partial( self.errors_manager.update_plot_after, self.errors_manager.toggle_error_bars_for, ax, line)) action.setCheckable(True) action.setChecked(not curve_props.hide_errors) else: add_later.append((line.get_label(), partial( self.errors_manager.update_plot_after, self.errors_manager.toggle_error_bars_for, ax, line), not curve_props.hide_errors)) for label, function, visible in add_later: action = error_bars_menu.addAction(label, function) action.setCheckable(True) action.setChecked(visible)
def contextMenuEvent(self, event): """Show a custom context menu.""" point = event.pos() menu = QMenu("Actions", self) menu.addAction(self.blctrl_enbl_act) menu.addAction(self.blctrl_dsbl_act) menu.addSeparator() action = menu.addAction('Show Connections...') action.triggered.connect(self.show_connections) menu.popup(self.mapToGlobal(point))
def open_levels_table_menu(self, position): menu = QMenu(self) enable_all_action = menu.addAction("Enable all") enable_all_action.triggered.connect(self.enable_all_levels) disable_all_action = menu.addAction("Disable all") disable_all_action.triggered.connect(self.disable_all_levels) menu.addSeparator() if self.levelsTable.selectedIndexes(): edit_action = menu.addAction("Edit selected level") edit_action.triggered.connect(self.open_level_edit_dialog) presets_dialog_action = menu.addAction("Presets") presets_dialog_action.triggered.connect(self.open_levels_preset_dialog) menu.popup(self.levelsTable.viewport().mapToGlobal(position))
def context_menu(self): try: menu = super(PyDMRelatedDisplayButton, self).context_menu() except: menu = QMenu(self) if len(menu.findChildren(QAction)) > 0: menu.addSeparator() if len(self.filenames) <= 1: menu.addAction(self.open_in_new_window_action) return menu sub_menu = menu.addMenu("Open in New Window") self._assemble_menu(sub_menu, target=self.NEW_WINDOW) return menu
def contextMenuEvent(self, event): """Show a custom context menu.""" point = event.pos() menu = QMenu("Actions", self) menu.addAction(self.turn_on_act) menu.addAction(self.turn_off_act) menu.addAction(self.pulse_on_act) menu.addAction(self.pulse_off_act) menu.addAction(self.reset_act) menu.addAction(self.set_voltage) menu.addSeparator() action = menu.addAction('Show Connections...') action.triggered.connect(self.show_connections) menu.popup(self.mapToGlobal(point))
def show_context_menu(self, pos: QPoint): ''' Show context menu Parameters ---------- pos : QPoint ''' menu = QMenu(self) menu.addAction("Detach Area", self.on_undock_button_clicked) menu.addSeparator() action = menu.addAction("Close Area", self.on_close_button_clicked) action.setEnabled(self.d.dock_area.closable) menu.addAction("Close Other Areas", self.d.dock_area.close_other_areas) menu.exec_(self.mapToGlobal(pos))
def showContextMenu(self, point): p = self._list.mapToGlobal(point) menu = QMenu() check_selected = menu.addAction("Check selected") uncheck_selected = menu.addAction("Uncheck selected") menu.addSeparator() clear_selection = menu.addAction("Clear selection") selected_item = menu.exec_(p) if selected_item == check_selected: self.checkSelected() elif selected_item == uncheck_selected: self.uncheckSelected() elif selected_item == clear_selection: self._list.clearSelection()
def contextMenuEvent(self, ev: QContextMenuEvent): ''' Contextmenuevent Parameters ---------- ev : QContextMenuEvent ''' ev.accept() self.d.drag_start_mouse_position = ev.pos() menu = QMenu(self) menu.addAction("Detach", self.on_detach_action_triggered) menu.addSeparator() action = menu.addAction("Close", self.close_requested) action.setEnabled(self.is_closable()) menu.addAction("Close Others", self.close_other_tabs_requested) menu.exec(self.mapToGlobal(ev.pos()))
def onCustomTrackMenuRequested(self): menu = QMenu("Animator Track Context") itemTitle = menu.addAction('Create Custom Animator Track') itemTitle.setEnabled(False) menu.addSeparator() #check if there is animator track trackTypes = _MOCK.getCustomAnimatorTrackTypesForObject( self.getTarget()) if not trackTypes: return for id, clas in list(trackTypes.items()): action = menu.addAction(id) def _makeTrackCreator(trackId): return lambda x: self.addCustomAnimatorTrack(trackId) action.triggered.connect(_makeTrackCreator(id)) action.setIcon(getIcon('object_track')) menu.exec_(QtGui.QCursor.pos())
def contextMenuEvent(self, event): """Show a custom context menu.""" point = event.pos() menu = QMenu("Actions", self) menu.addAction(self.turn_on_act) menu.addAction(self.turn_off_act) menu.addAction(self.ctrlloop_close_act) menu.addAction(self.ctrlloop_open_act) menu.addAction(self.set_current_sp_act) if not self._dev_list[0].dev in ('FCH', 'FCV'): menu.addAction(self.set_slowref_act) menu.addAction(self.reset_act) menu.addAction(self.wfmupdate_on_act) menu.addAction(self.wfmupdate_off_act) menu.addAction(self.updparms_act) menu.addSeparator() action = menu.addAction('Show Connections...') action.triggered.connect(self.show_connections) menu.popup(self.mapToGlobal(point))
def _make_sort_button(self): """ Make the sort button, with separate groups for ascending and descending, sorting by name or last shown :return: The sort menu button """ sort_button = QPushButton("Sort") sort_menu = QMenu() ascending_action = QAction("Ascending", sort_menu, checkable=True) ascending_action.setChecked(True) ascending_action.toggled.connect(self.presenter.set_sort_order) descending_action = QAction("Descending", sort_menu, checkable=True) order_group = QActionGroup(sort_menu) order_group.addAction(ascending_action) order_group.addAction(descending_action) number_action = QAction("Number", sort_menu, checkable=True) number_action.setChecked(True) number_action.toggled.connect( lambda: self.presenter.set_sort_type(Column.Number)) name_action = QAction("Name", sort_menu, checkable=True) name_action.toggled.connect( lambda: self.presenter.set_sort_type(Column.Name)) last_active_action = QAction("Last Active", sort_menu, checkable=True) last_active_action.toggled.connect( lambda: self.presenter.set_sort_type(Column.LastActive)) sort_type_group = QActionGroup(sort_menu) sort_type_group.addAction(number_action) sort_type_group.addAction(name_action) sort_type_group.addAction(last_active_action) sort_menu.addAction(ascending_action) sort_menu.addAction(descending_action) sort_menu.addSeparator() sort_menu.addAction(number_action) sort_menu.addAction(name_action) sort_menu.addAction(last_active_action) sort_button.setMenu(sort_menu) return sort_button
def _show_context_menu(self, event): """Display a relevant context menu on the canvas :param event: The MouseEvent that generated this call """ if not event.inaxes: # the current context menus are ony relevant for axes return fig_type = figure_type(self.canvas.figure) if fig_type == FigureType.Empty or fig_type == FigureType.Image: # Fitting or changing scale types does not make sense in # these cases return menu = QMenu() if self.fit_browser.tool is not None: self.fit_browser.add_to_menu(menu) menu.addSeparator() self._add_axes_scale_menu(menu) menu.exec_(QCursor.pos())
def __init__(self, orientation=Qt.Horizontal, parent=None): """Init.""" self._decimals = 0 self._scale = 1 super(QDoubleScrollBar, self).__init__(orientation, parent) super().rangeChanged.connect(self._intercept_rangeChanged) super().sliderMoved.connect(self._intercept_sliderMoved) super().valueChanged.connect(self._intercept_valueChanged) menu = QMenu(self) ac = menu.addAction('Set Single Step') ac.triggered.connect(self.dialogSingleStep) ac = menu.addAction('Set Page Step') ac.triggered.connect(self.dialogPageStep) menu.addSeparator() ac = menu.addAction("Left edge") ac.triggered.connect(lambda: self.triggerAction(self.SliderToMinimum)) ac = menu.addAction("Right edge") ac.triggered.connect(lambda: self.triggerAction(self.SliderToMaximum)) self.contextMenu = menu
def __init__(self, workflowview: QAbstractItemView): super(WorkflowWidget, self).__init__() self.view = workflowview self.toolbar = QToolBar() addfunctionmenu = QToolButton() functionmenu = QMenu() sortingDict = {} for plugin in pluginmanager.getPluginsOfCategory("ProcessingPlugin"): typeOfProcessingPlugin = plugin.plugin_object.getCategory() if not typeOfProcessingPlugin in sortingDict.keys(): sortingDict[typeOfProcessingPlugin] = [] sortingDict[typeOfProcessingPlugin].append(plugin) for key in sortingDict.keys(): functionmenu.addSeparator() functionmenu.addAction(key) functionmenu.addSeparator() for plugin in sortingDict[key]: functionmenu.addAction( plugin.name, partial(self.addProcess, plugin.plugin_object, autoconnectall=True)) addfunctionmenu.setMenu(functionmenu) addfunctionmenu.setIcon(QIcon(path("icons/addfunction.png"))) addfunctionmenu.setText("Add Function") addfunctionmenu.setPopupMode(QToolButton.InstantPopup) self.toolbar.addWidget(addfunctionmenu) # self.toolbar.addAction(QIcon(path('icons/up.png')), 'Move Up') # self.toolbar.addAction(QIcon(path('icons/down.png')), 'Move Down') self.toolbar.addAction(QIcon(path("icons/folder.png")), "Load Workflow") self.toolbar.addAction(QIcon(path("icons/trash.png")), "Delete Operation", self.deleteProcess) v = QVBoxLayout() v.addWidget(self.view) v.addWidget(self.toolbar) v.setContentsMargins(0, 0, 0, 0) self.setLayout(v)
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 _make_sort_button(self): """ Make the sort button, with separate groups for ascending and descending, sorting by name or last shown :return: The sort menu button """ sort_button = QPushButton("Sort") sort_menu = QMenu() ascending_action = QAction("Ascending", sort_menu, checkable=True) ascending_action.setChecked(True) ascending_action.toggled.connect(self.presenter.set_sort_order) descending_action = QAction("Descending", sort_menu, checkable=True) order_group = QActionGroup(sort_menu) order_group.addAction(ascending_action) order_group.addAction(descending_action) number_action = QAction("Number", sort_menu, checkable=True) number_action.setChecked(True) number_action.toggled.connect(lambda: self.presenter.set_sort_type(Column.Number)) name_action = QAction("Name", sort_menu, checkable=True) name_action.toggled.connect(lambda: self.presenter.set_sort_type(Column.Name)) last_active_action = QAction("Last Active", sort_menu, checkable=True) last_active_action.toggled.connect(lambda: self.presenter.set_sort_type(Column.LastActive)) sort_type_group = QActionGroup(sort_menu) sort_type_group.addAction(number_action) sort_type_group.addAction(name_action) sort_type_group.addAction(last_active_action) sort_menu.addAction(ascending_action) sort_menu.addAction(descending_action) sort_menu.addSeparator() sort_menu.addAction(number_action) sort_menu.addAction(name_action) sort_menu.addAction(last_active_action) sort_button.setMenu(sort_menu) return sort_button
def _popup_menu(self, event): axes = self._find_calling_axes(event) # find axes calling right click if axes is None: return pos = self.parent.mapFromGlobal(QtGui.QCursor().pos()) popup_menu = QMenu(self.parent) xScaleMenu = popup_menu.addMenu('x-scale') yScaleMenu = popup_menu.addMenu('y-scale') for coord in ['x', 'y']: menu = eval(coord + 'ScaleMenu') for type in axes.scale[coord].keys(): action = QAction(type, menu, checkable=True) if axes.scale[coord][type]: # if it's checked action.setEnabled(False) else: action.setEnabled(True) menu.addAction(action) action.setChecked(axes.scale[coord][type]) fcn = lambda event, coord=coord, type=type: self._set_scale( coord, type, axes, True) action.triggered.connect(fcn) # Create menu for AutoScale options X Y All popup_menu.addSeparator() autoscale_options = ['AutoScale X', 'AutoScale Y', 'AutoScale All'] for n, text in enumerate(autoscale_options): action = QAction(text, menu, checkable=True) if n < len(self.autoScale): action.setChecked(self.autoScale[n]) else: action.setChecked(all(self.autoScale)) popup_menu.addAction(action) action.toggled.connect( lambda event, n=n: self._setAutoScale(n, event, axes)) popup_menu.exec_(self.parent.mapToGlobal(pos))
def _show_context_menu(self, event): """Display a relevant context menu on the canvas :param event: The MouseEvent that generated this call """ if not event.inaxes: # the current context menus are ony relevant for axes return fig_type = figure_type(self.canvas.figure) if fig_type == FigureType.Empty: # Fitting or changing scale types does not make sense in this case return menu = QMenu() if fig_type == FigureType.Image: if isinstance(event.inaxes, MantidAxes): self._add_axes_scale_menu(menu, event.inaxes) self._add_normalization_option_menu(menu, event.inaxes) self._add_colorbar_axes_scale_menu(menu, event.inaxes) else: if self.fit_browser.tool is not None: self.fit_browser.add_to_menu(menu) menu.addSeparator() self._add_axes_scale_menu(menu, event.inaxes) if isinstance(event.inaxes, MantidAxes): self._add_normalization_option_menu(menu, event.inaxes) self.add_error_bars_menu(menu, event.inaxes) self._add_marker_option_menu(menu, event) # Able to change the plot type to waterfall if there is only one axes, it is a MantidAxes, and there is more # than one line on the axes. if len(event.inaxes.get_figure().get_axes()) == 1 and isinstance(event.inaxes, MantidAxes)\ and len(event.inaxes.get_lines()) > 1: self._add_plot_type_option_menu(menu, event.inaxes) menu.exec_(QCursor.pos())
def _showHeaderMenu(self, point): column = self.headers.logicalIndexAt(point.x()) if column == -1: return menu = QMenu(self) # Actions cols = self.table.selectionModel().selectedColumns() if len(cols) != 2 or column not in [col.column() for col in cols]: self.table.selectColumn(column) menu.aboutToHide.connect(lambda: self.table.clearSelection()) save = QAction("Save", menu) save.triggered.connect(lambda: self._saveConfiguration(column)) save_all = QAction("Save all", menu) save_all.triggered.connect(lambda: self._saveChanges()) save_all.setShortcut(QKeySequence.Save) rename = QAction("Rename", menu) rename.triggered.connect(lambda: self._renameConfiguration(column)) close = QAction("Close", menu) close.triggered.connect(lambda: self._closeConfiguration(column)) close.setShortcut(QKeySequence.Close) close_right = QAction("Close to the right", menu) close_right.triggered.connect( lambda: self._closeConfigurationsToTheRight(column)) close_others = QAction("Close other", menu) close_others.triggered.connect( lambda: self._closeOtherConfigurations(column)) close_all = QAction("Close all", menu) close_all.triggered.connect(lambda: self._closeAllConfigurations()) tune = QAction("Tune", menu) tune.triggered.connect(lambda: self._tuneConfiguration(column)) menu.addActions([save, save_all]) menu.addSeparator() menu.addActions([rename]) menu.addSeparator() menu.addActions([close, close_right, close_others, close_all]) menu.addSeparator() menu.addActions([tune]) else: bar = QAction("Interpolate", menu) bar.triggered.connect(lambda: self._barConfiguration(cols)) menu.addAction(bar) vheader_offset = self.table.verticalHeader().width() point.setX(point.x() + vheader_offset) menu.popup(self.mapToGlobal(point))
def contextMenuEvent(self, event): """Overload to create a custom context menu.""" widget = self.childAt(event.pos()) parent = widget.parent() grand_parent = parent.parent() if widget.objectName() == 'DCLinkContainer' or \ parent.objectName() == 'DCLinkContainer' or \ grand_parent.objectName() == 'DCLinkContainer': menu = QMenu(self) menu.addAction(self._turn_on_action) menu.addAction(self._turn_off_action) menu.addSeparator() menu.addAction(self._close_loop_action) menu.addAction(self._open_loop_action) menu.addSeparator() menu.addAction(self._set_setpoint_action) menu.addSeparator() menu.addAction(self._reset_intlk_action) menu.addSeparator() action = menu.addAction('Show Connections...') action.triggered.connect(self.show_connections) menu.popup(event.globalPos()) else: super().contextMenuEvent(event)
def onFieldContextMenuRequested(self, target, fieldId): menu = QMenu("Field Context") itemTitle = menu.addAction('[ %s ]' % fieldId) itemTitle.setEnabled(False) menu.addSeparator() animator = app.getModule('animator') if animator: itemAddKey = menu.addAction('Add key') itemAddKey.setIcon(getIcon('key')) itemAddKey.triggered.connect(self.onFieldAddKey) menu.addSeparator() itemDefault = menu.addAction('Set Default') itemDefault.triggered.connect(self.onFieldResetDefault) if _MOCK.isProtoInstanceOverrided(target, fieldId): menu.addSeparator() itemProtoReset = menu.addAction('Reset To Proto Value') itemProtoReset.triggered.connect(self.onFieldResetProto) itemProtoReset.setIcon(getIcon('reset')) self.currentFieldContext = (target, fieldId) menu.exec_(QtGui.QCursor.pos())
def right_click(self, position=None): _duplicate_row = -1 _plot_sofq = -1 _remove_row = -1 _new_row = -1 _copy = -1 _paste = -1 _cut = -1 _refresh_table = -1 _clear_table = -1 # _import = -1 # _export = -1 _check_all = -1 _uncheck_all = -1 _undo = -1 _redo = -1 _plot_sofq_diff_first_run_row = -1 _plot_sofq_diff_average_row = -1 _plot_cryostat = -1 _plot_furnace = -1 _invert_selection = -1 menu = QMenu(self.main_window) if self.main_window.table_selection_buffer == {}: paste_status = False else: paste_status = True if (self.main_window.postprocessing_ui.table.rowCount() > 0): _undo = menu.addAction("Undo") _undo.setEnabled(self.main_window.undo_button_enabled) _redo = menu.addAction("Redo") _redo.setEnabled(self.main_window.redo_button_enabled) menu.addSeparator() _copy = menu.addAction("Copy") _paste = menu.addAction("Paste") self._paste_menu = _paste _paste.setEnabled(paste_status) _cut = menu.addAction("Clear") menu.addSeparator() _check_all = menu.addAction("Check All") _uncheck_all = menu.addAction("Unchecked All") menu.addSeparator() _invert_selection = menu.addAction("Inverse Selection") menu.addSeparator() _new_row = menu.addAction("Insert Blank Row") if (self.main_window.postprocessing_ui.table.rowCount() > 0): _duplicate_row = menu.addAction("Duplicate Row") _remove_row = menu.addAction("Remove Row(s)") menu.addSeparator() _plot_menu = menu.addMenu('Plot') _plot_sofq = _plot_menu.addAction("S(Q) ...") _plot_sofq_diff_first_run_row = _plot_menu.addAction("S(Q) Diff (1st run)...") _plot_sofq_diff_average_row = _plot_menu.addAction("S(Q) Diff (Avg.)...") _temp_menu = _plot_menu.addMenu("Temperature") _plot_cryostat = _temp_menu.addAction("Cyrostat...") _plot_furnace = _temp_menu.addAction("Furnace...") menu.addSeparator() _refresh_table = menu.addAction("Refresh/Reset Table") _clear_table = menu.addAction("Clear Table") action = menu.exec_(QCursor.pos()) self.current_row = self.current_row() if action == _undo: self.main_window.action_undo_clicked() elif action == _redo: self.main_window.action_redo_clicked() elif action == _copy: self._copy() elif action == _paste: self._paste() elif action == _cut: self._cut() elif action == _duplicate_row: self._duplicate_row() elif action == _plot_sofq: self._plot_sofq() elif action == _plot_sofq_diff_first_run_row: self._plot_sofq_diff_first_run_row() elif action == _plot_sofq_diff_average_row: self._plot_sofq_diff_average_row() elif action == _plot_cryostat: self._plot_temperature(samp_env_choice='cryostat') elif action == _plot_furnace: self._plot_temperature(samp_env_choice='furnace') elif action == _invert_selection: self._inverse_selection() elif action == _new_row: self._new_row() elif action == _remove_row: self._remove_selected_rows() elif action == _refresh_table: self._refresh_table() elif action == _clear_table: self._clear_table() elif action == _check_all: self.check_all() elif action == _uncheck_all: self.uncheck_all()
def populate_menu(menu: QMenu, actions: List['MenuItem']): """Populate a QMenu from a declarative list of QAction dicts. Parameters ---------- menu : QMenu the menu to populate actions : list of dict A list of dicts with one or more of the following keys **Required: One of "text" or "menu" MUST be present in the dict** text: str the name of the QAction to add menu: str if present, creates a submenu instead. "menu" keys may also provide an "items" key to populate the menu. **Optional:** slot: callable a callback to call when the action is triggered shortcut: str a keyboard shortcut to trigger the actoin statusTip: str used for setStatusTip menuRole: QAction.MenuRole used for setMenuRole checkable: bool used for setCheckable checked: bool used for setChecked (only if `checkable` is provided and True) check_on: EventEmitter If provided, and `checkable` is True, this EventEmitter will be connected to action.setChecked: `dct['check_on'].connect(lambda e: action.setChecked(e.value))` """ for ax in actions: if not ax: menu.addSeparator() continue if not ax.get("when", True): continue if 'menu' in ax: sub = ax['menu'] if isinstance(sub, QMenu): menu.addMenu(sub) sub.setParent(menu) else: sub = menu.addMenu(sub) populate_menu(sub, ax.get("items", [])) continue action: QAction = menu.addAction(ax['text']) if 'slot' in ax: if ax.get("checkable"): action.toggled.connect(ax['slot']) else: action.triggered.connect(ax['slot']) action.setShortcut(ax.get('shortcut', '')) action.setStatusTip(ax.get('statusTip', '')) if 'menuRole' in ax: action.setMenuRole(ax['menuRole']) if ax.get("checkable"): action.setCheckable(True) action.setChecked(ax.get("checked", False)) if 'check_on' in ax: emitter = ax['check_on'] @emitter.connect def _setchecked(e, action=action): action.setChecked(e.value if hasattr(e, 'value') else e) action.setData(ax)
def __init__(self): super(XicamMainWindow, self).__init__() # Set icon self.setWindowIcon(QIcon(QPixmap(str(path("icons/xicam.gif"))))) # Set size and position self.setGeometry(0, 0, 1000, 600) frameGm = self.frameGeometry() screen = QApplication.desktop().screenNumber( QApplication.desktop().cursor().pos()) centerPoint = QApplication.desktop().screenGeometry(screen).center() frameGm.moveCenter(centerPoint) self.move(frameGm.topLeft()) # Init child widgets to None self.topwidget = (self.leftwidget) = (self.rightwidget) = ( self.bottomwidget ) = self.lefttopwidget = self.righttopwidget = self.leftbottomwidget = self.rightbottomwidget = None # Setup appearance self.setWindowTitle("Xi-cam") self.load_style() # Attach an object to restore config when loaded self._config_restorer = ConfigRestorer() # Load plugins pluginmanager.qt_is_safe = True pluginmanager.initialize_types() pluginmanager.collect_plugins() pluginmanager.collect_user_plugins() # Setup center/toolbar/statusbar/progressbar self.pluginmodewidget = pluginModeWidget() self.pluginmodewidget.sigSetStage.connect(self.setStage) self.pluginmodewidget.sigSetGUIPlugin.connect(self.setGUIPlugin) self.addToolBar(self.pluginmodewidget) self.setStatusBar(QStatusBar(self)) msg.progressbar = QProgressBar(self) msg.progressbar.hide() msg.statusbar = self.statusBar() self.statusBar().addPermanentWidget(msg.progressbar) self.setCentralWidget(QStackedWidget()) # NOTE: CentralWidgets are force-deleted when replaced, even if the object is still referenced; # To avoid this, a QStackedWidget is used for the central widget. # Setup menubar menubar = DebuggableMenuBar() self.setMenuBar(menubar) file = QMenu("&File", parent=menubar) plugins = QMenu("&Plugins", parent=menubar) menubar.addMenu(file) file.addAction("Se&ttings", self.showSettings, shortcut=QKeySequence(Qt.CTRL + Qt.ALT + Qt.Key_S)) file.addAction("E&xit", self.close) menubar.addMenu(plugins) plugins.addAction("Open User &Plugin Directory", self.openUserPluginDir, shortcut=QKeySequence(Qt.CTRL + Qt.ALT + Qt.Key_P)) # Set up help help = QMenu("&Help", parent=menubar) documentation_link = QUrl("https://xi-cam.readthedocs.io/en/latest/") help.addAction("Xi-CAM &Help", lambda: QDesktopServices.openUrl(documentation_link)) slack_link = QUrl("https://nikea.slack.com") help.addAction("Chat on &Slack", lambda: QDesktopServices.openUrl(slack_link)) help.addSeparator() about_title = "About Xi-CAM" version_text = f"""Version: <strong>{version.get_versions()['version']}</strong>""" copyright_text = f"""<small>Copyright (c) 2016, The Regents of the University of California, \ through Lawrence Berkeley National Laboratory \ (subject to receipt of any required approvals from the U.S. Dept. of Energy). \ All rights reserved.</small>""" funding_text = f"""Funding for this research was provided by: \ Lawrence Berkeley National Laboratory (grant No. TReXS LDRD to AH); \ US Department of Energy (award No. Early Career Award to AH; \ contract No. DE-SC0012704; contract No. DE-AC02-06CH11357; \ contract No. DE-AC02-76SF00515; contract No. DE-AC02-05CH11231); \ Center for Advanced Mathematics in Energy Research Applications; \ Light Source Directors Data Solution Task Force Pilot Project.""" about_text = version_text + "<br><br>" + funding_text + "<br><hr>" + copyright_text about_box = QMessageBox(QMessageBox.NoIcon, about_title, about_text) about_box.setTextFormat(Qt.RichText) about_box.setWindowModality(Qt.NonModal) help.addAction("&About Xi-CAM", lambda: about_box.show()) help.addSeparator() help.addAction(QWhatsThis.createAction(help)) menubar.addMenu(help) # Initialize layout with first plugin self._currentGUIPlugin = None self.build_layout() # self._currentGUIPlugin = pluginmanager.getPluginsOfCategory("GUIPlugin")[0] self.populate_layout() # Make F key bindings fkeys = [ Qt.Key_F1, Qt.Key_F2, Qt.Key_F3, Qt.Key_F4, Qt.Key_F5, Qt.Key_F6, Qt.Key_F7, Qt.Key_F8, Qt.Key_F9, Qt.Key_F10, Qt.Key_F11, Qt.Key_F12, ] self.Fshortcuts = [QShortcut(QKeySequence(key), self) for key in fkeys] for i in range(12): self.Fshortcuts[i].activated.connect(partial(self.setStage, i)) self.readSettings() # Wireup default widgets get_default_stage()["left"].sigOpen.connect(self.open) get_default_stage()["left"].sigOpen.connect(print) get_default_stage()["left"].sigPreview.connect( get_default_stage()["lefttop"].preview)
class Q7Diff(Q7Window, Ui_Q7DiffWindow): def __init__(self, control, fgprintindexA, fgprintindexB, diag): Q7Window.__init__(self, Q7Window.VIEW_DIFF, control, None, fgprintindexA) self._depthExpanded = 0 self._lastEntered = None self._fgidxA = fgprintindexA self._fgidxB = fgprintindexB ldiag = self.diagAnalysis(diag) self.treeviewA.expanded[QModelIndex].connect(self.expandNode) self.treeviewA.collapsed.connect(self.collapseNode) self.treeviewA.clicked[QModelIndex].connect(self.clickedNode) self.treeviewA.customContextMenuRequested[QPoint].connect( self.clickedNode) self.treeviewB.expanded[QModelIndex].connect(self.expandNode) self.treeviewB.collapsed.connect(self.collapseNode) self.treeviewB.clicked[QModelIndex].connect(self.clickedNode) self.treeviewB.customContextMenuRequested[QPoint].connect( self.clickedNode) # QObject.connect(self.treeviewA, # SIGNAL("expanded(QModelIndex)"), # self.expandNode) # QObject.connect(self.treeviewA, # SIGNAL("collapsed()"), # self.collapseNode) # QObject.connect(self.treeviewA, # SIGNAL("clicked(QModelIndex)"), # self.clickedNode) # QObject.connect(self.treeviewA, # SIGNAL("customContextMenuRequested(QPoint)"), # self.clickedNode) # QObject.connect(self.treeviewB, # SIGNAL("expanded(QModelIndex)"), # self.expandNode) # QObject.connect(self.treeviewB, # SIGNAL("collapsed()"), # self.collapseNode) # QObject.connect(self.treeviewB, # SIGNAL("clicked(QModelIndex)"), # self.clickedNode) # QObject.connect(self.treeviewB, # SIGNAL("customContextMenuRequested(QPoint)"), # self.clickedNode) # QObject.connect(self.bLockScroll, # SIGNAL("clicked()"), # self.syncScrolls) self.bLockScroll.clicked.connect(self.syncScrolls) self.bClose.clicked.connect(self.leave) self.bInfo.clicked.connect(self.infoTreeView) self.bZoomIn.clicked.connect(self.expandLevel) self.bZoomOut.clicked.connect(self.collapseLevel) self.bZoomAll.clicked.connect(self.expandMinMax) self.bSaveDiff.clicked.connect(self.savediff) self.setContextMenuPolicy(Qt.CustomContextMenu) self.popupmenu = QMenu() self.proxyA = Q7DiffTreeModel(self._fgidxA) self.proxyB = Q7DiffTreeModel(self._fgidxB) self.proxyA.setDiag(ldiag) self.proxyB.setDiag(ldiag) self.treeviewA.setModel(self.proxyA) self.treeviewB.setModel(self.proxyB) fga = Q7FingerPrint.getByIndex(self._fgidxA) fgb = Q7FingerPrint.getByIndex(self._fgidxB) model_a = fga.model model_b = fgb.model self.treeviewA.setItemDelegate( Q7DiffItemDelegate(self.treeviewA, model_a, ldiag)) self.treeviewB.setItemDelegate( Q7DiffItemDelegate(self.treeviewB, model_b, ldiag)) self.treeviewA.setControlWindow(self, model_a) self.treeviewB.setControlWindow(self, model_b) self.treeviewA.hideColumn(NMT.COLUMN_FLAG_LINK) self.treeviewA.hideColumn(NMT.COLUMN_FLAG_CHECK) self.treeviewA.hideColumn(NMT.COLUMN_FLAG_SELECT) self.treeviewA.hideColumn(NMT.COLUMN_FLAG_USER) self.treeviewB.hideColumn(NMT.COLUMN_FLAG_LINK) self.treeviewB.hideColumn(NMT.COLUMN_FLAG_CHECK) self.treeviewB.hideColumn(NMT.COLUMN_FLAG_SELECT) self.treeviewB.hideColumn(NMT.COLUMN_FLAG_USER) self.wvsa = self.treeviewA.verticalScrollBar() self.wvsb = self.treeviewB.verticalScrollBar() self.uvsa = self.verticalScrollBarA self.uvsb = self.verticalScrollBarB self.uvsa.setToolTip("%s/%s" % (fga.filedir, fga.filename)) self.uvsb.setToolTip("%s/%s" % (fgb.filedir, fgb.filename)) self.syncScrolls(True) def diagAnalysis(self, diag): ldiag = {} for k in diag: ldiag[k] = DIFF_NX for d in diag[k]: if d[0] == 'NA': ldiag[d[1]] = DIFF_NA if d[0] == 'ND': ldiag[d[1]] = DIFF_ND if d[0] in ['CT']: ldiag[k] = DIFF_CT if d[0] in ['C3', 'C1', 'C2']: ldiag[k] = DIFF_CQ if d[0] in ['C6', 'C7']: ldiag[k] = DIFF_CV if d[0] in ['C4', 'C5']: ldiag[k] = DIFF_CS return ldiag def syncScrolls(self, force=False): self.uvsa.valueChanged[int].connect(self.wvsa.setValue[int]) self.uvsb.valueChanged[int].connect(self.wvsb.setValue[int]) self.wvsa.valueChanged[int].connect(self.uvsa.setValue[int]) self.wvsb.valueChanged[int].connect(self.uvsb.setValue[int]) # # QObject.connect(self.uvsa, SIGNAL("valueChanged(int)"), # self.wvsa, SLOT("setValue(int)")) # QObject.connect(self.uvsb, SIGNAL("valueChanged(int)"), # self.wvsb, SLOT("setValue(int)")) # QObject.connect(self.wvsa, SIGNAL("valueChanged(int)"), # self.uvsa, SLOT("setValue(int)")) # QObject.connect(self.wvsb, SIGNAL("valueChanged(int)"), # self.uvsb, SLOT("setValue(int)")) if force or self.bLockScroll.isChecked(): self.wvsa.valueChanged[int].connect(self.wvsb.setValue[int]) self.wvsb.valueChanged[int].connect(self.wvsa.setValue[int]) # QObject.connect(self.wvsa, SIGNAL("valueChanged(int)"), # self.wvsb, SLOT("setValue(int)")) # QObject.connect(self.wvsb, SIGNAL("valueChanged(int)"), # self.wvsa, SLOT("setValue(int)")) else: self.wvsa.valueChanged[int].disconnect(self.wvsb.setValue[int]) self.wvsb.valueChanged[int].disconnect(self.wvsa.setValue[int]) # QObject.disconnect(self.wvsa, SIGNAL("valueChanged(int)"), # self.wvsb, SLOT("setValue(int)")) # QObject.disconnect(self.wvsb, SIGNAL("valueChanged(int)"), # self.wvsa, SLOT("setValue(int)")) def model(self): return self._fgprint.model def modelIndex(self, idx): if not idx.isValid(): return -1 midx = idx # if (idx.model() != self.treeview.M()): # midx=self.treeview.model().mapToSource(idx) return midx def modelData(self, idx): if not idx.isValid(): return None return self.modelIndex(idx).internalPointer() def infoTreeView(self): self._control.helpWindow('Tree') def savediff(self): pass def expandMinMax(self): if self._depthExpanded == Q7FingerPrint.getByIndex( self._fgidxA).depth - 2: self._depthExpanded = -1 self.treeviewA.collapseAll() self.treeviewB.collapseAll() else: self._depthExpanded = Q7FingerPrint.getByIndex( self._fgidxA).depth - 2 self.treeviewA.expandAll() self.treeviewB.expandAll() self.resizeAll() def expandLevel(self): if self._depthExpanded < Q7FingerPrint.getByIndex( self._fgidxA).depth - 2: self._depthExpanded += 1 self.treeviewA.expandToDepth(self._depthExpanded) self.treeviewB.expandToDepth(self._depthExpanded) self.resizeAll() def collapseLevel(self): if self._depthExpanded != -1: self._depthExpanded -= 1 if self._depthExpanded == -1: self.treeviewA.collapseAll() self.treeviewB.collapseAll() else: self.treeviewA.expandToDepth(self._depthExpanded) self.treeviewB.expandToDepth(self._depthExpanded) self.resizeAll() def updateStatus(self, node): return self.lineEdit.clear() self.lineEdit.insert(node.sidsPath()) def updateMenu(self, nodeidxs): return nodeidx = self.modelIndex(nodeidxs) if not nodeidx.isValid: return False if nodeidx.internalPointer() is None: return False if nodeidx.internalPointer().sidsPath() == '/CGNSTree': return False self.setLastEntered(nodeidxs) if nodeidx != -1: node = nodeidx.internalPointer() lknode = not node.sidsIsLink() lznode = node.hasLazyLoad() actlist = ( ("About %s" % node.sidsType(), self.aboutSIDS, None, False), None, ("Mark/unmark node", self.marknode, 'Space', False), ("Add new child node", self.newnodechild, 'Ctrl+A', False), ("Add new brother node", self.newnodebrother, 'Ctrl+Z', False), None, ("Open form", self.popform, 'Ctrl+F', False), ("Open view", self.openSubTree, 'Ctrl+W', False), ("Open view on linked-to file", self.openLkTree, 'Ctrl+O', lknode), None, ("Load node data in memory", self.dataLoad, 'Ctrl+L', not lznode), ("Release memory node data", self.dataRelease, 'Ctrl+R', lznode), None, ("Copy", self.mcopy, 'Ctrl+C', False), ("Cut", self.mcut, 'Ctrl+X', False), ("Paste as brother", self.mpasteasbrother, 'Ctrl+V', False), ("Paste as child", self.mpasteaschild, 'Ctrl+Y', False), None, ("Cut all selected", self.mcutselected, 'Ctrl+Shift+X', False), ("Paste as brother for each selected", self.mpasteasbrotherselected, 'Ctrl+Shift+V', False), ("Paste as child for each selected", self.mpasteaschildselected, 'Ctrl+Shift+Y', False), ("Load nodes data in memory for each selected", self.dataLoadSelected, 'Ctrl+Shift+L', False), ("Release memory node data for each selected", self.dataReleaseSelected, 'Ctrl+Shift+R', False), ) self.popupmenu.clear() self.popupmenu.setTitle('Node menu') for aparam in actlist: if aparam is None: self.popupmenu.addSeparator() else: a = QAction(aparam[0], self) a.triggered.connect(aparam[1]) if aparam[2] is not None: a.setShortcut(aparam[2]) self.popupmenu.addAction(a) a.setDisabled(aparam[3]) return True def setLastEntered(self, nix=None): self._lastEntered = None def getLastEntered(self): return self._lastEntered def clearLastEntered(self): self._lastEntered = None self.treeview.selectionModel().clearSelection() return None def clickedNode(self, index): pass def expandNode(self, *args): self.resizeAll() def collapseNode(self, *args): pass def resizeAll(self): for n in range(NMT.COLUMN_LAST + 1): self.treeviewA.resizeColumnToContents(n) self.treeviewB.resizeColumnToContents(n) def show(self): super(Q7Diff, self).show() def closeAlone(self): pass def leave(self): self.close() def doRelease(self): pass
class Q7Tree(Q7Window, Ui_Q7TreeWindow): def __init__(self, control, path, fgprintindex): Q7Window.__init__(self, Q7Window.VIEW_TREE, control, path, fgprintindex) self._depthExpanded = 0 self._lastEntered = None self.lastdiag = None self._linkwindow = None self._querywindow = None self._vtkwindow = None self._selectwindow = None self._column = {NMT.COLUMN_SIDS: OCTXT.ShowSIDSColumn, NMT.COLUMN_FLAG_LINK: OCTXT.ShowLinkColumn, NMT.COLUMN_FLAG_SELECT: OCTXT.ShowSelectColumn, NMT.COLUMN_FLAG_CHECK: OCTXT.ShowCheckColumn, NMT.COLUMN_FLAG_USER: OCTXT.ShowUserColumn, NMT.COLUMN_SHAPE: OCTXT.ShowShapeColumn, NMT.COLUMN_DATATYPE: OCTXT.ShowDataTypeColumn} self.selectForLinkSrc = None # one link source per tree view allowed #self.treeview.expanded[QModelIndex].connect(self.expandNode) self.treeview.collapsed.connect(self.collapseNode) self.treeview.pressed[QModelIndex].connect(self.clickedPressedNode) self.treeview.customContextMenuRequested.connect(self.clickedNode) # QObject.connect(self.treeview, # SIGNAL("expanded(QModelIndex)"), # self.expandNode) # QObject.connect(self.treeview, # SIGNAL("collapsed()"), # self.collapseNode) # QObject.connect(self.treeview, # SIGNAL("pressed(QModelIndex)"), # self.clickedPressedNode) # QObject.connect(self.treeview, # SIGNAL("customContextMenuRequested(QPoint)"), # self.clickedNode) self.bSave.clicked.connect(self.savetree) self.lockable(self.bSave) self.bQueryView.clicked.connect(self.queryview) self.lockable(self.bQueryView) self.bSaveAs.clicked.connect(self.savetreeas) self.lockable(self.bSaveAs) self.bInfo.clicked.connect(self.infoTreeView) self.bZoomIn.clicked.connect(self.expandLevel) self.bZoomOut.clicked.connect(self.collapseLevel) self.bZoomAll.clicked.connect(self.expandMinMax) self.bFormView.clicked.connect(self.formview) self.bMarkAll.clicked.connect(self.markall) self.bUnmarkAll_1.clicked.connect(self.unmarkall) self.bUnmarkAll_2.clicked.connect(self.unmarkall) self.bPreviousMark.clicked.connect(self.previousmark) self.bNextMark.clicked.connect(self.nextmark) self.bSwapMarks.clicked.connect(self.swapmarks) self.bMarksAsList.clicked.connect(self.selectionlist) self.bVTKView.clicked.connect(self.vtkview) self.lockable(self.bVTKView) self.bScreenShot.clicked.connect(self.screenshot) self.bCheck.clicked.connect(self.check) self.bCheckList.clicked.connect(self.checklist) self.bClearChecks.clicked.connect(self.clearchecks) self.bLinkView.clicked.connect(self.linklist) self.bPatternView.clicked.connect(self.patternlist) self.bToolsView.clicked.connect(self.tools) self.setContextMenuPolicy(Qt.CustomContextMenu) self.popupmenu = QMenu() self.diagview = None lmodel = self.FG.model self.treeview.setModel(lmodel) self.treeview.setItemDelegate(Q7TreeItemDelegate(self.treeview, lmodel)) self.treeview.setControlWindow(self, self.FG.index) if (self._control.transientRecurse or OCTXT.RecursiveTreeDisplay): self.expandMinMax() if (self._control.transientVTK): self.vtkview() self._control.transientRecurse = False self._control.transientVTK = False self.clearchecks() # self.bCheckList.setDisabled(True) if (not OCTXT._HasProPackage): self.bToolsView.setDisabled(True) self.bCheckView.setDisabled(True) self.bPatternDB.setDisabled(True) self.bAddLink.clicked.connect(self.linkadd) self.bSelectLinkSrc.clicked.connect(self.linkselectsrc) self.bSelectLinkDst.clicked.connect(self.linkselectdst) self.bAddLink.setDisabled(True) self.lineEdit.returnPressed.connect(self.jumpToNode) # QObject.connect(self.lineEdit, # SIGNAL("returnPressed()"), # self.jumpToNode) tvh = self.treeview.header() tvh.setContextMenuPolicy(Qt.CustomContextMenu) tvh.customContextMenuRequested.connect(self.headerMenu) self._hmenu = QMenu() self._hmenu._idx = {} self._tlist = (('SIDS type', NMT.COLUMN_SIDS), ('Link flag', NMT.COLUMN_FLAG_LINK), ('Mark flag', NMT.COLUMN_FLAG_SELECT), ('Check flag', NMT.COLUMN_FLAG_CHECK), ('User flag', NMT.COLUMN_FLAG_USER), ('Shape', NMT.COLUMN_SHAPE), ('Data type', NMT.COLUMN_DATATYPE)) for (tag, idx) in self._tlist: a = QAction(tag, self._hmenu, checkable=True) self._hmenu._idx[idx] = a if (self._column[idx]): a.setChecked(True) else: a.setChecked(False) self._hmenu.addAction(a) self.treeview.setColumnHidden(idx, not self._column[idx]) self._recursiveAddNewNode = False self.updateTreeStatus() def headerMenu(self, pos): for (tag, idx) in self._tlist: self._hmenu._idx[idx].setChecked(self._column[idx]) self._hmenu.exec_(self.treeview.mapToGlobal(pos)) for (tag, idx) in self._tlist: if (self._hmenu._idx[idx].isChecked()): self._column[idx] = True else: self._column[idx] = False self.treeview.setColumnHidden(idx, not self._column[idx]) def model(self): return self.FG.model def modelIndex(self, idx): if not idx.isValid(): return -1 midx = idx if idx.model() != self.treeview.M(): midx = self.treeview.model().mapToSource(idx) return midx def modelData(self, idx): if not idx.isValid(): return None return self.modelIndex(idx).internalPointer() def savetree(self): if (not (self.FG.isSaveable() and self.FG.isModified())): return self._control.savedirect(self.FG) self.updateTreeStatus() def tools(self): from CGNS.NAV.wtools import Q7ToolsView if (self._control._toolswindow is None): self._control._toolswindow = Q7ToolsView(self._control, self.FG, self) self._control._toolswindow.show() else: self._control._toolswindow.raise_() def savetreeas(self): self._control.save(self.FG) self.updateTreeStatus() def infoTreeView(self): self._control.helpWindow('Tree') def screenshot(self): self.treeview.model().sort(0) sshot = QScreen.grabWindow(self.treeview.winId()) sshot.save('/tmp/foo.png', 'png') def expandMinMax(self): if (self._depthExpanded == self.FG.depth - 2): self._depthExpanded = -1 self.treeview.collapseAll() else: self._depthExpanded = self.FG.depth - 2 self.treeview.expandAll() self.resizeAll() def resetOptions(self): if (OCTXT.AutoExpand): self.treeview.setAutoExpandDelay(1000) else: self.treeview.setAutoExpandDelay(-1) def expandLevel(self): if (self._depthExpanded < self.FG.depth - 2): self._depthExpanded += 1 self.treeview.expandToDepth(self._depthExpanded) self.resizeAll() def collapseLevel(self): if (self._depthExpanded != -1): self._depthExpanded -= 1 if (self._depthExpanded == -1): self.treeview.collapseAll() else: self.treeview.expandToDepth(self._depthExpanded) self.resizeAll() def updateStatus(self, node): if (not self.lineEditLock.isChecked()): self.lineEdit.clear() self.lineEdit.insert(node.sidsPath()) def jumpToNode(self): path = self.lineEdit.text() self.treeview.selectByPath(path) def popform(self): self.formview() def openLkTree(self): self.busyCursor() filename = self.getLastEntered().sidsLinkFilename() if (filename is not None): self._control.loadfile(filename) self.readyCursor() def openSubTree(self): self.busyCursor() node = self.getLastEntered().sidsPath() child = Q7Tree(self._control, node, self.FG) self.readyCursor() child.show() def pop0(self): pass def newnodebrother(self): if (self.getLastEntered() is not None): self.model().newNodeBrother(self.getLastEntered()) def newnodechild(self): if (self.getLastEntered() is not None): self.model().newNodeChild(self.getLastEntered()) def marknode(self): if (self.getLastEntered() is not None): self.treeview.markNode(self.getLastEntered()) def mcopy(self): if (self.getLastEntered() is not None): self.model().copyNode(self.getLastEntered()) self.clearOtherSelections() def mcutselected(self): self.model().cutAllSelectedNodes() self.clearLastEntered() self.clearOtherSelections() def mcut(self): if (self.getLastEntered() is not None): self.model().cutNode(self.getLastEntered()) self.clearLastEntered() self.clearOtherSelections() def mpasteasbrotherselected(self): self.model().pasteAsBrotherAllSelectedNodes() def mpasteasbrother(self): if (self.getLastEntered() is not None): self.model().pasteAsBrother(self.getLastEntered()) def mpasteaschildselected(self): self.model().pasteAsChildAllSelectedNodes() def mpasteaschild(self): if (self.getLastEntered() is not None): self.model().pasteAsChild(self.getLastEntered()) def updateMenu(self, nodeidxs): nodeidx = self.modelIndex(nodeidxs) if (not nodeidx.isValid): return False if (nodeidx.internalPointer() is None): return False if (nodeidx.internalPointer().sidsPath() == '/CGNSTree'): return False self.setLastEntered(nodeidxs) if (nodeidx != -1): node = nodeidx.internalPointer() lknode = not node.sidsIsLink() lznode = node.hasLazyLoad() actlist = ( ("%s goodies" % node.sidsType(),), None, ("Expand sub-tree from this node", self.expand_sb, 'Ctrl++', False), ("Collapses sub-tree from this node", self.collapse_sb, 'Ctrl+-', False), None, ['Mark nodes...',[ ("Mark/unmark node", self.marknode, 'Space', False), None, ("Mark all nodes same SIDS type", self.marknode_t, 'Ctrl+1', False), ("Mark all nodes same name", self.marknode_n, 'Ctrl+2', False), ("Mark all nodes same value", self.marknode_v, 'Ctrl+3', False), None, ("Mark parent path", self.marknode_p, 'Ctrl+4', False)]], ("Add new child node", self.newnodechild, 'Ctrl+A', False), ("Add new brother node", self.newnodebrother, 'Ctrl+Z', False), # None, # ("Open form",self.popform,'Ctrl+F',False), # ("Open view",self.openSubTree,'Ctrl+W',False), # ("Open view on linked-to file",self.openLkTree,'Ctrl+O',lknode), None, ("Load node data in memory", self.dataLoad, 'Ctrl+L', not lznode), ("Release memory node data", self.dataRelease, 'Ctrl+R', lznode), None, ("Copy current", self.mcopy, 'Ctrl+C', False), ("Cut current", self.mcut, 'Ctrl+X', False), ("Paste as brother", self.mpasteasbrother, 'Ctrl+V', False), ("Paste as child", self.mpasteaschild, 'Ctrl+Y', False), None, ['On selected nodes...',[ ("Expand sub-tree from all selected nodes", self.sexpand_sb, 'Ctrl+Shift++', False), ("Collapses sub-tree from all selected nodes", self.scollapse_sb, 'Ctrl+Shift+-', False), None, ("Cut all selected", self.mcutselected, 'Ctrl+Shift+X', False), ("Paste as brother for each selected", self.mpasteasbrotherselected, 'Ctrl+Shift+V', False), ("Paste as child for each selected", self.mpasteaschildselected, 'Ctrl+Shift+Y', False), None, ("Load nodes data in memory for each selected", self.dataLoadSelected, 'Ctrl+Shift+L', False), ("Release memory node data for each selected", self.dataReleaseSelected, 'Ctrl+Shift+R', False)]], ) self.popupmenu.clear() self.popupmenu.setTitle('Node menu') for aparam in actlist: if (aparam is None): self.popupmenu.addSeparator() elif (len(aparam) == 1): stp = node.sidsType() tag = '_GM_{}'.format(stp) subm = self.popupmenu.addMenu('{}...'.format(stp)) a = QAction("About %s" % node.sidsType(), self, triggered=self.aboutSIDS) subm.addAction(a) patmenu = subm.addMenu('Insert pattern') self.patternMenu(patmenu, node.sidsNode()) subm.addSeparator() if (hasattr(self, tag)): getattr(self, tag)(subm, node) else: if isinstance(aparam,list): subm = self.popupmenu.addMenu(aparam[0]) for aaparam in aparam[1]: if (aaparam is None): subm.addSeparator() else: a = QAction(aaparam[0], self, triggered=aaparam[1]) if (aaparam[2] is not None): a.setShortcut(aaparam[2]) subm.addAction(a) a.setDisabled(aaparam[3]) else: a = QAction(aparam[0], self, triggered=aparam[1]) if (aparam[2] is not None): a.setShortcut(aparam[2]) self.popupmenu.addAction(a) a.setDisabled(aparam[3]) return True def _runAndSelect(self, qname, value): q = Q7Query.getQuery(qname) sl = q.run(self.FG.tree, self.FG.links, list(self.FG.lazy), False, value) self.model().markExtendToList(sl) self.model().updateSelected() self.treeview.refreshView() def patternMenu(self, menu, node): a = QAction("Recursive sub-pattern add", self, checkable=True) menu.addAction(a) a.setChecked(self._recursiveAddNewNode) menu.addSeparator() for t in [n[0] for n in CGU.getAuthChildren(node)]: def genCopyPattern(arg): def copyPattern(): self.model().copyNodeRaw(CGS.profile[arg][0]) if (self.getLastEntered() is not None): self.model().pasteAsChild(self.getLastEntered()) return copyPattern a = QAction("{}".format(t), self, triggered=genCopyPattern(t)) menu.addAction(a) def _gm_family_1(self, node): self._runAndSelect('013. FamilyName reference', "'%s'" % node.sidsName()) def _gm_family_2(self, node): self._runAndSelect('003. Node type', "'Family_t'") def _GM_Family_t(self, m, node): a = QAction('Select references to myself', self) a.triggered.connect(functools.partial(self._gm_family_1, node)) m.addAction(a) a = QAction('Select all families', self) a.triggered.connect(functools.partial(self._gm_family_2, node)) m.addAction(a) m.addSeparator() return True def _GM_IndexRange_t(self, m, node): if (node.sidsName() != CGK.ElementRange_s): v = 0 a = QAction('Range size: %d' % (v), self) m.addAction(a) else: v = node.sidsValue()[1] - node.sidsValue()[0] etp = CGU.getEnumAsString(node.sidsParent()) a = QAction('Number of elements of type [%s]: %d' % (etp, v), self) m.addAction(a) return True def _GM_Elements_t(self, m, node): etp = CGU.getEnumAsString(node.sidsNode()) npe = CGK.ElementTypeNPE[etp] a = QAction('Element type [%s] npe [%d]' % (etp, npe), self) m.addAction(a) return True def marknode_t(self): node = self.getLastEntered() self._runAndSelect('003. Node type', "'%s'" % node.sidsType()) def marknode_n(self): node = self.getLastEntered() self._runAndSelect('001. Node name', "'%s'" % node.sidsName()) def marknode_v(self): node = self.getLastEntered() value = node.sidsValue() self._runAndSelect('005. Node value', value) def marknode_p(self): node = self.getLastEntered() node.switchMarked() path = node.sidsPath() while path is not None: path = CGU.getPathAncestor(path) if (path not in ['/', None]): node = self.model().nodeFromPath('/CGNSTree' + path) node.switchMarked() self.model().updateSelected() def setLastEntered(self, nix=None): if ((nix is None) or (not nix.isValid())): nix = self.treeview.modelCurrentIndex() self._lastEntered = None if (nix.isValid()): self.treeview.exclusiveSelectRow(nix, False) self._lastEntered = self.modelData(nix) def getLastEntered(self): return self._lastEntered def clearLastEntered(self): self._lastEntered = None self.treeview.selectionModel().clearSelection() return None def clearOtherSelections(self): if (self._control._patternwindow is not None): self._control._patternwindow.clearSelection() def clickedPressedNode(self, index): self.clickedNode(index) def clickedNode(self, index): self.treeview.exclusiveSelectRow(index) if (self.treeview.lastButton == Qt.RightButton): if (self.updateMenu(index)): self.popupmenu.popup(self.treeview.lastPos) def expandNode(self, *args): self.resizeAll() def collapseNode(self, *args): pass def expand_sb(self): self.treeview.expand_sb() def collapse_sb(self): self.treeview.collapse_sb() def sexpand_sb(self): self.treeview.sexpand_sb() def scollapse_sb(self): self.treeview.scollapse_sb() def resizeAll(self): for n in range(NMT.COLUMN_LAST + 1): self.treeview.resizeColumnToContents(n) def show(self): super(Q7Tree, self).show() def linkselectsrc(self): if (self.bSelectLinkSrc.isChecked()): if (self.getLastEntered() is None): return self.bAddLink.setDisabled(False) node = self.getLastEntered() self.selectForLinkSrc = (node, node.sidsPath()) else: self.bAddLink.setDisabled(True) self.selectForLinkSrc = None def linkselectdst(self): if (self.getLastEntered() is None): return node = self.getLastEntered() if (node is None): return if (node.sidsIsLink()): return if (node.sidsType() == CGK.CGNSTree_ts): return if (self._control.selectForLinkDst is not None): bt = self._control.selectForLinkDst[-1].bSelectLinkDst bt.setChecked(Qt.Unchecked) if (self._control.selectForLinkDst[-1] == self): self._control.selectForLinkDst = None return self._control.selectForLinkDst = (node, node.sidsPath(), self.FG.filedir, self.FG.filename, self) self.bSelectLinkDst.setChecked(Qt.Checked) if (self._linkwindow is not None): n = node.sidsPath() d = self.FG.filedir f = self.FG.filename self._linkwindow.updateSelected(d, f, n) def linkadd(self): if (self._control.selectForLinkDst is None): return dst = self._control.selectForLinkDst str_dst = "%s:%s" % (dst[3], dst[1]) tpath = 'relative' newname = CGU.getPathLeaf(dst[1]) if (CGU.checkDuplicatedName(self.selectForLinkSrc[0].sidsNode(), newname, dienow=False)): str_cnm = "New child node name is <b>%s</b>" % newname else: count = 0 while (not CGU.checkDuplicatedName(self.selectForLinkSrc[0].sidsNode(), newname, dienow=False)): count += 1 newname = '{%s#%.3d}' % (dst[0].sidsType(), count) str_cnm = """As a child with this name already exists, the name <b>%s</b> is used (generated name)""" % \ newname str_src = "%s:%s/%s" % (self.FG.filename, self.selectForLinkSrc[1], newname) str_msg = "you want to create a link from <b>%s</b> to <b>%s</b><br>%s<br>Your current user options do force " \ "the link to use <b>%s</b> destination file path.""" % ( str_src, str_dst, str_cnm, tpath) reply = MSG.wQuestion(self, 231, 'Create link as a new node', str_msg) def linklist(self): if (self._linkwindow is None): self._linkwindow = Q7LinkList(self._control, self.FG.index, self) self._linkwindow.show() else: self._linkwindow.raise_() def patternlist(self): if (self._control._patternwindow is None): self._control._patternwindow = Q7PatternList(self._control, self.FG) self._control._patternwindow.show() self._control._patternwindow.raise_() def check(self): self.busyCursor() if (self.diagview is not None): self.diagview.close() self.diagview = None self.lastdiag = self.model().checkSelected() self.readyCursor() self.treeview.refreshView() self.bCheckList.setDisabled(False) def checklist(self): if (self.lastdiag is None): return self.diagview = Q7CheckList(self, self.lastdiag, self.FG.index) self.diagview.show() def clearchecks(self): self.model().checkClear() self.treeview.refreshView() self.lastdiag = None self.bCheckList.setDisabled(True) def selectionlist(self): if (self._selectwindow is not None): self._selectwindow.close() self._selectwindow = None self._selectwindow = Q7SelectionList(self, self.model(), self.FG.index) self._selectwindow.show() self._selectwindow.raise_() def previousmark(self): self.treeview.changeSelectedMark(-1) def nextmark(self): self.treeview.changeSelectedMark(+1) def markall(self): self.model().markAll() self.model().updateSelected() self.treeview.refreshView() def unmarkall(self): self.model().unmarkAll() self.model().updateSelected() self.treeview.refreshView() def swapmarks(self): self.model().swapMarks() self.model().updateSelected() self.treeview.refreshView() def formview(self): ix = self.treeview.modelCurrentIndex() node = self.modelData(ix) if (node is None): MSG.wInfo(self, 254, "Form view:", """You have to select a node to open its form view""", again=False) return if (node.sidsType() == CGK.CGNSTree_ts): return form = Q7Form(self._control, node, self.FG.index) form.show() def vtkview(self): if (not HAS_VTK): return from CGNS.NAV.wvtk import Q7VTK if (self._vtkwindow is None): self.busyCursor() ix = self.treeview.modelCurrentIndex() zlist = self.model().getSelectedZones() node = self.modelData(ix) self._vtkwindow = Q7VTK(self._control, self, node, self.FG.index, self.model(), zlist) if (self._vtkwindow._vtkstatus): self._vtkwindow.show() else: self._vtkwindow.close() self._vtkwindow = None self.readyCursor() else: self._vtkwindow.raise_() def plotview(self): return def queryview(self): if (self._querywindow is None): self._querywindow = Q7Query(self._control, self.FG.index, self) self._querywindow.show() else: self._querywindow.raise_() def aboutSIDS(self): path = self.getLastEntered().sidsPath() def dataLoadSelected(self): self.model().dataLoadSelected() def dataReleaseSelected(self): self.model().dataReleaseSelected() def dataLoad(self): node = self.getLastEntered() self.model().dataLoadSelected(single=node.sidsPath()) def dataRelease(self): node = self.getLastEntered() self.model().dataReleaseSelected(single=node.sidsPath()) def forceapply(self): pass def updateTreeStatus(self): if ((Q7FingerPrint.STATUS_MODIFIED in self.FG._status) and (Q7FingerPrint.STATUS_SAVEABLE in self.FG._status)): self.bSave.setEnabled(True) else: self.bSave.setEnabled(False) def doRelease(self): # break cyclic refs to allow garbage self.treeview.itemDelegate().doRelease() self.treeview.setItemDelegate(None) self.treeview.doRelease() self.treeview = None