class DeltaGenMenu(QMenu): def __init__(self, ui, menu_name: str = _('DeltaGen')): """ Setup the DeltaGen MainMenu setting KnechtSettings for DeltaGen communication :param modules.gui.main_ui.KnechtWindow ui: :param menu_name: name of the menu that will be displayed """ super(DeltaGenMenu, self).__init__(menu_name, ui) self.ui = ui self.reset, self.freeze, self.check = None, None, None self.hidden_actions = QActionGroup(self) self.hidden_actions.setVisible(False) self.send_camera, self.display, self.display_overlay = None, None, None self.enable_material_dummy, self.validate_plmxml, self.change_port = None, None, None self.as_scene_menu = QMenu() self.setup_deltagen_menu() # Apply settings before showing self.aboutToShow.connect(self._menu_about_to_show) def setup_deltagen_menu(self): # ---- Reset On/Off ---- self.reset = self._setup_checkable_action(_('Reset senden'), True, self.toggle_reset) # ---- Freeze Viewer On/Off ---- self.freeze = self._setup_checkable_action(_('Freeze Viewer'), True, self.toggle_freeze_viewer) # ---- Variants State Check On/Off ---- self.check = self._setup_checkable_action( _('Varianten State Check'), True, self.toggle_variants_state_check) # ---- Send Camera Data On/Off ---- self.send_camera = self._setup_checkable_action( _('Kamera Daten übertragen'), True, self.toggle_camera_send) # ---- Display State Check On/Off ---- self.display = self._setup_checkable_action( _('State Check im Baum anzeigen'), False, self.toggle_state_check_display) # ---- Display Overlay after Preset Send operation finished ---- self.display_overlay = self._setup_checkable_action( _('Zuletzt gesendetes Preset als Overlay anzeigen'), False, self.toggle_display_finished_overlay) # ---- Assign Dummy Material before applying PlmXml Materials self.enable_material_dummy = self._setup_checkable_action( _('Dummy Material auf PlmXml Konfiguration anwenden'), False, self.toggle_plmxml_material_dummy) # ---- Validate DeltaGen Scene vs PlmXml before switching configurations self.validate_plmxml = self._setup_checkable_action( _('DeltaGen Szene vor dem konfigurieren mit PlmXml abgleichen.'), True, self.toggle_validate_plmxml, self.hidden_actions) # --- As Connector choose active scene menu --- self.as_scene_menu.deleteLater() self.as_scene_menu = AsSceneMenu(self.ui, _('AsConnector aktive Szene:')) self.addMenu(self.as_scene_menu) # --- Change DeltaGen Command Port self.change_port = QAction(IconRsc.get_icon('paperplane'), _('DeltaGen Port ändern'), self) self.change_port.triggered.connect(self.change_deltagen_port) self.addAction(self.change_port) self._apply_settings() def _setup_checkable_action(self, name: str, checked: bool, target: object, action_grp: QActionGroup = None): check_icon = IconRsc.get_icon('check_box_empty') check_icon.addPixmap(IconRsc.get_pixmap('check_box'), QIcon.Normal, QIcon.On) if action_grp: action = QAction(check_icon, name, action_grp) else: action = QAction(check_icon, name, self) action.setCheckable(True) action.setChecked(checked) action.triggered.connect(target) self.addAction(action) return action def _menu_about_to_show(self): """ Setup method before menu is visible """ # Hide hidden actions self.hidden_actions.setVisible(False) # Show hidden actions with Ctrl Key if QApplication.keyboardModifiers() & QtCore.Qt.ControlModifier: self.hidden_actions.setVisible(True) self._apply_settings() def _apply_settings(self): """ Apply saved settings """ self.reset.setChecked(KnechtSettings.dg.get('reset')) self.freeze.setChecked(KnechtSettings.dg.get('freeze_viewer')) self.check.setChecked(KnechtSettings.dg.get('check_variants')) self.send_camera.setChecked(KnechtSettings.dg.get('send_camera_data')) self.display.setChecked(KnechtSettings.dg.get('display_variant_check')) self.display_overlay.setChecked( KnechtSettings.dg.get('display_send_finished_overlay')) self.enable_material_dummy.setChecked( KnechtSettings.dg.get('use_material_dummy')) self.validate_plmxml.setChecked( KnechtSettings.dg.get('validate_plmxml_scene')) @Slot(bool) def toggle_reset(self, checked: bool): LOGGER.debug('Received from: %s', self.sender().text()) KnechtSettings.dg['reset'] = checked @Slot(bool) def toggle_freeze_viewer(self, checked: bool): KnechtSettings.dg['freeze_viewer'] = checked @Slot(bool) def toggle_variants_state_check(self, checked: bool): KnechtSettings.dg['check_variants'] = checked @Slot(bool) def toggle_state_check_display(self, checked: bool): KnechtSettings.dg['display_variant_check'] = checked @Slot(bool) def toggle_display_finished_overlay(self, checked: bool): KnechtSettings.dg['display_send_finished_overlay'] = checked @Slot(bool) def toggle_plmxml_material_dummy(self, checked: bool): KnechtSettings.dg['use_material_dummy'] = checked @Slot(bool) def toggle_validate_plmxml(self, checked: bool): KnechtSettings.dg['validate_plmxml_scene'] = checked @Slot(bool) def toggle_camera_send(self, checked: bool): KnechtSettings.dg['send_camera_data'] = checked def change_deltagen_port(self): box = QMessageBox(self) box.setText( _('Port zwischen 3000-3999 angeben. ' 'Muss mit DeltaGen>Preferences>Tools>External Commands übereinstimmen.' )) box.setWindowTitle(_('DeltaGen Kommando Port')) port = QSpinBox(box) port.setMinimum(3000) port.setMaximum(3999) port.setValue(KnechtSettings.dg.get('port', DG_TCP_PORT)) box.layout().addWidget(port, box.layout().rowCount() - 1, 0, 1, box.layout().columnCount()) box.layout().addWidget( box.layout().takeAt(box.layout().rowCount() - 1).widget(), box.layout().rowCount(), 0, 1, box.layout().columnCount()) box.exec_() if 3000 <= port.value() <= 3999: KnechtSettings.dg['port'] = port.value() box = QMessageBox(self) box.setText( _('Anwendung neu starten um geänderten Port zu übernehmen.')) box.setWindowTitle(_('Neustart erforderlich')) box.exec_() def enable_menus(self, enabled: bool = True): for a in self.menu.actions(): a.setEnabled(enabled)
class TreeContextMenu(QMenu): def __init__(self, view, ui, menu_name: str = _('Baum Kontextmenü')): """ Context menu of tree views :param modules.itemview.tree_view.KnechtTreeView view: tree view :param KnechtWindow ui: main window ui class :param str menu_name: name of the menu """ super(TreeContextMenu, self).__init__(menu_name, view) self.view, self.ui, self.status_bar = view, ui, ui.statusBar() self.edit_menu = self.ui.main_menu.edit_menu self.create_menu = CreateMenu(self) self.tree_menu = TreeMenu(self, ui) self.send_dg_action = QAction(IconRsc.get_icon('paperplane'), _('Senden an DeltaGen'), self) dg_tip_1 = _( 'Selektierte Bauminhalte als Variantenschaltung mit vorherigem Reset an DeltaGen senden.' ) self.send_dg_action.setToolTip(dg_tip_1) self.send_dg_action.setStatusTip(dg_tip_1) self.send_dg_action.triggered.connect(self.send_to_deltagen) self.addAction(self.send_dg_action) self.addSeparator() self.send_ave_action = QAction(IconRsc.get_icon('paperplane'), _('Senden an AVE'), self) dg_tip_1 = _( 'Selektierte Bauminhalte als Konfiguration an laufende AVE Instanz senden.' ) self.send_ave_action.setToolTip(dg_tip_1) self.send_ave_action.setStatusTip(dg_tip_1) self.send_ave_action.triggered.connect(self.send_to_ave) self.addAction(self.send_ave_action) self.addSeparator() self.send_dg_short = QAction(IconRsc.get_icon('paperplane'), _('Ohne Reset an DeltaGen senden'), self) dg_tip_2 = _( 'Selektierte Bauminhalte ohne einen Reset an DeltaGen senden.') self.send_dg_short.setToolTip(dg_tip_2) self.send_dg_short.setStatusTip(dg_tip_2) self.send_dg_short.triggered.connect(self.send_to_deltagen_wo_reset) self.addAction(self.send_dg_short) self.addSeparator() # -- PR-String Actions copy_pr = QAction(IconRsc.get_icon('options'), _('PR String in Zwischenablage kopieren'), self) copy_pr.triggered.connect(self.copy_strings_to_clipboard) self.addAction(copy_pr) copy_li = QAction(IconRsc.get_icon('assignment'), _('Linc String in Zwischenablage kopieren'), self) copy_li.triggered.connect(self.copy_linc_string_to_clipboard) self.addAction(copy_li) self.addSeparator() # -- PlmXml Actions self.show_plmxml_scn = QAction(IconRsc.get_icon('dog'), 'PlmXml Schnuffi', self) self.show_plmxml_scn.triggered.connect(self.show_plmxml_scene) self.addAction(self.show_plmxml_scn) self.addSeparator() # ---- Create preset from selected actions ---- self.addActions([ self.create_menu.user_preset_from_selected, self.create_menu.render_preset_from_selected ]) self.addSeparator() # ---- Prepare Context Menus & Actions ---- # ---- Add main menu > edit ----- self.addMenu(self.edit_menu) # ---- Add main menu > tree ----- self.addMenu(self.tree_menu) # ---- Add main menu > create ----- self.addMenu(self.create_menu) self.addSeparator() self.remove_row_action = QAction( IconRsc.get_icon('trash-a'), _('Selektierte Zeilen entfernen\tEntf'), self) self.remove_row_action.triggered.connect( self.edit_menu.remove_rows_action.trigger) self.addAction(self.remove_row_action) self.addSeparator() # ---- Developer Actions ----- self.dev_actions = QActionGroup(self) cake = QAction(IconRsc.get_icon('layer'), '--- The cake was a lie ---', self.dev_actions) show_id_action = QAction(IconRsc.get_icon('options'), 'Show ID columns', self.dev_actions) show_id_action.triggered.connect(self.show_id_columns) hide_id_action = QAction(IconRsc.get_icon('options-neg'), _('Hide ID columns'), self.dev_actions) hide_id_action.triggered.connect(self.hide_id_columns) list_tab_widgets = QAction(IconRsc.get_icon('navicon'), 'List Tab Widgets', self.dev_actions) list_tab_widgets.triggered.connect(self.list_tab_widgets) report_action = QAction('Report Item attributes to log', self.dev_actions) report_action.setShortcut(QKeySequence('Ctrl+B')) report_action.triggered.connect(self.report_current) log_level = QAction(IconRsc.get_icon('sort'), 'Enable DEBUG log level', self.dev_actions) log_level.triggered.connect(self.ui.app.set_debug_log_level) produce_exception = QAction(IconRsc.get_icon('warn'), 'Produce Exception', self.dev_actions) produce_exception.triggered.connect(self.ui.app.produce_exception) open_dir = QAction(IconRsc.get_icon('folder'), 'Open Settings Directoy', self.dev_actions) open_dir.triggered.connect(self.open_settings_dir) notify = QAction(IconRsc.get_icon('eye-disabled'), 'Show tray notification', self.dev_actions) notify.triggered.connect(self.noclick_tray_notification) notify_click = QAction(IconRsc.get_icon('eye'), 'Show click tray notification', self.dev_actions) notify_click.triggered.connect(self.click_tray_notification) overlay_btn_msg = QAction(IconRsc.get_icon('check_box'), 'Show overlay confirm message', self.dev_actions) overlay_btn_msg.triggered.connect(self.overlay_confirm_message) overlay_msg = QAction(IconRsc.get_icon('check_box_empty'), 'Show regular overlay message', self.dev_actions) overlay_msg.triggered.connect(self.overlay_message) overlay_imm_msg = QAction(IconRsc.get_icon('reset'), 'Show immediate overlay message', self.dev_actions) overlay_imm_msg.triggered.connect(self.overlay_message_immediate) restart = QAction(IconRsc.get_icon('reset'), 'Restart', self.dev_actions) restart.triggered.connect(self.restart_app) reorder = QAction(IconRsc.get_icon('sort'), 'Rewrite item order whole tree', self.dev_actions) reorder.triggered.connect(self.reorder_tree) self.addActions(self.dev_actions.actions()) self.dev_actions.setVisible(False) self.aboutToShow.connect(self.update_actions) # Install context menu event filter self.view.installEventFilter(self) def eventFilter(self, obj, event): if obj is not self.view: return False if event.type() == QtCore.QEvent.ContextMenu: self.dev_actions.setVisible(False) # Hold Control and Shift to display dev context if event.modifiers( ) == QtCore.Qt.ShiftModifier | QtCore.Qt.ControlModifier: self.dev_actions.setVisible(True) self.popup(event.globalPos()) return True return False def send_to_deltagen(self): variants = self.view.editor.collect.collect_current_index() self.ui.app.send_dg.send_variants(variants, self.view) def send_to_ave(self): variants = self.view.editor.collect.collect_current_index() variants.ave = True self.ui.app.send_dg.send_variants(variants, self.view) def send_to_deltagen_wo_reset(self): variants = self.view.editor.collect.collect_current_index( collect_reset=False) self.ui.app.send_dg.send_variants(variants, self.view) def copy_strings_to_clipboard(self): variants = self.view.editor.collect.collect_current_index( collect_reset=False) pr_string = '' for variant in variants.variants: pr_string += f'{variant.name} {variant.value};' self.ui.app.clipboard().setText(pr_string) def copy_linc_string_to_clipboard(self): variants = self.view.editor.collect.collect_current_index( collect_reset=False) pr_string = '' for variant in variants.variants: pr_string += f'+{variant.name}' self.ui.app.clipboard().setText(pr_string) def _get_plmxml_item(self, variants: KnechtVariantList) -> Optional[Path]: if variants.plm_xml_path: return Path(variants.plm_xml_path) index, src_model = self.view.editor.get_current_selection() current_item = src_model.get_item(index) if current_item.userType != Kg.plmxml_item: return else: plmxml_file = Path(current_item.data(Kg.VALUE)) if not path_exists(plmxml_file): return return plmxml_file def show_plmxml_scene(self): variants = self.view.editor.collect.collect_current_index() plmxml_file = self._get_plmxml_item(variants) if not plmxml_file: return plmxml_scene_page = KnechtPlmXmlScene(self.ui, plmxml_file, variants) GenericTabWidget(self.ui, plmxml_scene_page) def hide_id_columns(self): self.view.hideColumn(Kg.REF) self.view.hideColumn(Kg.ID) def show_id_columns(self): self.view.showColumn(Kg.REF) self.view.showColumn(Kg.ID) def list_tab_widgets(self): self.ui.view_mgr.log_tabs() def report_current(self): self.view.editor.report_current() def open_settings_dir(self): settings_dir = Path(get_settings_dir()) if path_exists(settings_dir): q = QUrl.fromLocalFile(settings_dir.as_posix()) QDesktopServices.openUrl(q) def noclick_tray_notification(self): self.ui.show_tray_notification( title='Test Notification', message='Clicking the message should hopefully emit nothing.') def click_tray_notification(self): def test_callback(): LOGGER.info('Test notification click callback activated.') self.ui.msg('Message triggered by notification messageClicked.', 4000) self.ui.show_tray_notification( title='Test Notification', message='Clicking the message should trigger a overlay message.', clicked_callback=test_callback) def restart_app(self): restart_knecht_app(self.ui) def reorder_tree(self): for idx, _ in self.view.editor.iterator.iterate_view(): self.view.editor.iterator.order_items(idx) def overlay_message(self): self.view.info_overlay.display( 'Message in queue for a duration of 5000ms', 5000) def overlay_message_immediate(self): self.view.info_overlay.display( 'Immediate message for a duration of 6000ms', 6000, True) def overlay_confirm_message(self): buttons = (('Buttontext 1', None), ('Buttontext 2', None)) self.view.info_overlay.display_confirm( 'Test Message to confirm something. ' 'Lenghty information ahead! This message ends ' 'with this sentence.', buttons) def update_actions(self): src_model = self.view.model().sourceModel() if src_model.id_mgr.has_recursive_items(): self.send_dg_action.setEnabled(False) self.send_dg_short.setEnabled(False) else: self.send_dg_action.setEnabled(True) self.send_dg_short.setEnabled(True) self.create_menu.update_current_view() if self.view.is_render_view: self.send_dg_action.setEnabled(False) self.send_dg_short.setEnabled(False) self.show_plmxml_scn.setEnabled(False) index, src_model = self.view.editor.get_current_selection() current_item = src_model.get_item(index) if current_item.userType in (Kg.plmxml_item, Kg.preset): self.show_plmxml_scn.setEnabled(True)