def add_menu_theme(self, parent, menu): """""" self.menu_theme_ = menu action_group = QActionGroup(menu) try: action_group.setExclusive(True) except: action_group.exclusive = True for i, theme in enumerate(['default'] + list_themes()): action = QAction(parent) # action.triggered.connect(self._wrapper(parent, theme, self.extra_values, self.update_buttons)) action.triggered.connect(lambda: self.update_theme_event(parent)) try: action.setText(theme) action.setCheckable(True) action.setChecked(not bool(i)) action.setActionGroup(action_group) menu.addAction(action) action_group.addAction(action) except: # snake_case, true_property action.text = theme action.checkable = True action.checked = not bool(i) action.action_group = action_group menu.add_action(action) action_group.add_action(action)
def add_menu_density(self, parent, menu): """""" self.menu_density_ = menu action_group = QActionGroup(menu) try: action_group.setExclusive(True) except: action_group.exclusive = True for density in map(str, range(-3, 4)): action = QAction(parent) # action.triggered.connect(self._wrapper(parent, density, self.extra_values, self.update_buttons)) action.triggered.connect(lambda: self.update_theme_event(parent)) try: action.setText(density) action.setCheckable(True) action.setChecked(density == '0') action.setActionGroup(action_group) menu.addAction(action) action_group.addAction(action) except: # snake_case, true_property action.text = density action.checkable = True action.checked = density == '0' action.action_group = action_group menu.add_action(action) action_group.add_action(action)
def _show_menu(self, colleague, pos): if not self._is_owner and not colleague.is_you or colleague.is_deleting: return menu = QMenu(self._ui.colleagues_list) menu.setStyleSheet("background-color: #EFEFF4; ") if colleague.is_you: if colleague.is_owner: action = menu.addAction(tr("Quit collaboration")) action.triggered.connect(self._on_quit_collaboration) else: action = menu.addAction(tr("Leave collaboration")) action.triggered.connect(self._on_leave_collaboration) else: rights_group = QActionGroup(menu) rights_group.setExclusive(True) menu.addSection(tr("Access rights")) action = menu.addAction(tr("Can view")) action.setCheckable(True) rights_action = rights_group.addAction(action) rights_action.setData(False) rights_action.setChecked(not colleague.can_edit) action = menu.addAction(tr("Can edit")) action.setCheckable(True) rights_action = rights_group.addAction(action) rights_action.setChecked(colleague.can_edit) rights_action.setData(True) rights_group.triggered.connect( lambda a: self._on_grant_edit(colleague, a)) menu.addSeparator() action = menu.addAction(tr("Remove user")) action.triggered.connect(lambda: self._on_remove_user(colleague)) pos_to_show = QPoint(pos.x(), pos.y() + 10) menu.exec_(pos_to_show)
class GuiLogger(ConsoleLogger): """ Logging service in GUI mode. """ def __init__(self): super().__init__() srv = Services.getService("MainWindow") self.dockWidget = srv.newDockWidget( "Log", parent=None, defaultArea=Qt.BottomDockWidgetArea, allowedArea=Qt.LeftDockWidgetArea | Qt.BottomDockWidgetArea) self.logWidget = LogView() self.dockWidget.setWidget(self.logWidget) logMenu = srv.menuBar().addMenu("&Log") mainLogger = logging.getLogger() self.handler = LogHandler(self.logWidget) mainLogger.addHandler(self.handler) self.logWidget.destroyed.connect( lambda: mainLogger.removeHandler(self.handler)) self.actFollow = QAction("Follow") self.actFollow.setCheckable(True) self.actFollow.setChecked(True) self.actClear = QAction("Clear") self.actSingleLine = QAction("Single Line") self.actSingleLine.setCheckable(True) self.actSingleLine.setChecked(True) self.logWidget.setUniformRowHeights(True) self.actFollow.toggled.connect(self.logWidget.setFollow) self.actClear.triggered.connect(self.logWidget.clear) self.actSingleLine.toggled.connect(self.logWidget.setUniformRowHeights) self.actDisable = QAction("Disable") self.actDisable.triggered.connect(self.setLogLevel) self.actGroup = QActionGroup(self) self.actGroup.setExclusive(True) levelno = mainLogger.level self.loglevelMap = {} for lv in ["INTERNAL", "DEBUG", "INFO", "WARNING", "ERROR"]: a = QAction(lv[:1] + lv[1:].lower()) a.setCheckable(True) loglevel = getattr(logging, lv) self.loglevelMap[a] = loglevel setattr(self, "setLogLevel_" + lv, self.setLogLevel) a.triggered.connect(getattr(self, "setLogLevel_" + lv)) self.actGroup.addAction(a) if levelno == loglevel: a.setChecked(True) else: a.setChecked(False) logMenu.addAction(a) self.loglevelMap[self.actDisable] = 100 logMenu.addAction(self.actDisable) logMenu.addSeparator() logMenu.addAction(self.actClear) logMenu.addAction(self.actFollow) logMenu.addAction(self.actSingleLine) def setLogLevel(self): """ Sets the current log level from the calling action. :return: None """ lv = self.loglevelMap[self.sender()] logging.getLogger().setLevel(lv)
class CreateMenu(QMenu): def __init__(self, parent_widget, menu_name: str = _("Erstellen")): super(CreateMenu, self).__init__(menu_name, parent_widget) self.parent_widget = parent_widget self.current_view = None i = IconRsc self.create_action_grp = QActionGroup(self) self.create_action_grp.setExclusive(False) # -- Create User Preset from selection action self.user_preset_from_selected = QAction( i.get_icon('preset'), _('User Preset aus Selektion'), self.create_action_grp) self.user_preset_from_selected.triggered.connect( self._create_user_preset_from_selected) # -- Create Render Preset from selection action self.render_preset_from_selected = QAction( i.get_icon('render'), _('Render Preset aus Selektion'), self.create_action_grp) self.render_preset_from_selected.triggered.connect( self._create_render_preset_from_selected) action_list = [ (_("Render Preset\tEnthält User Presets, Viewsets und Rendereinstellungen" ), i.get_icon('render'), self._create_render_preset_from_selected), (_("User Preset\tEnthält Varianten und/oder Referenzen"), i.get_icon('preset'), self._create_user_preset_from_selected), (_("Viewset\tEnthält **eine** Shot Variante"), i.get_icon('viewset'), self._create_viewset), (_("Reset\tVarianten für eine Resetschaltung"), i.get_icon('reset'), self._create_reset), (_("Trimline Preset\tVarianten für eine Serienschaltung"), i.get_icon('car'), self._create_trimline), (_("Paket Preset\tVarianten eines Pakets"), i.get_icon('pkg'), self._create_package), (_("FaKom Serien\tVarianten einer Serien Farbkombination"), i.get_icon('fakom_trim'), self._create_fakom_trim), (_("FaKom Option\tVarianten einer Farbkombination"), i.get_icon('fakom'), self._create_fakom_option), (_('Ausgabe Objekt\tDefiniert einen Ausgabepfad'), i.get_icon('folder'), self._create_output_item), (_('PlmXml Objekt\tDefiniert einen Pfad zur PlmXml Datei'), i.get_icon('assignment'), self._create_plmxml_item), (_('Kamera Objekt\tEnthält 3DS DeltaGen Kameradaten'), i.get_icon('videocam'), self._create_camera_item), (_("Separator\tNicht-interagierbares Ordnungselement"), i.get_icon('navicon'), self._create_separator) ] for a in action_list: name, icon, method_call = a action = QAction(icon, name, self.create_action_grp) action.triggered.connect(method_call) self.addAction(action) self.aboutToShow.connect(self.update_current_view) def _create_user_preset_from_selected(self): self._create_preset_from_selected(is_user_preset=True) def _create_render_preset_from_selected(self): rp = self._create_preset_from_selected(is_user_preset=False) if rp: LOGGER.debug('RP ID: %s', rp.data(Kg.ID)) def _create_preset_from_selected(self, is_user_preset: bool = True ) -> Union[None, KnechtItem]: """ Copy and create a preset from selected items """ if not self.current_view: LOGGER.error('Can not find view in focus to add items to.') return child_items = self.current_view.editor.copypaste.copy_preset_items_from_selection( ) if is_user_preset: return self.current_view.editor.create.create_preset_from_items( child_items) else: return self.current_view.editor.create.create_render_preset_from_items( child_items) def _create_camera_item(self): if not self.current_view: return name = _('DeltaGen_Kamera_{:03d}').format( self.current_view.editor.create.item_count) self.current_view.editor.create.item_count += 1 new_item = self.current_view.editor.create.create_camera_item( name, KnechtImageCameraInfo.camera_example_info) self.current_view.editor.create_top_level_rows([new_item]) def _create_viewset(self): self._create_item(ItemTemplates.viewset) def _create_reset(self): self._create_item(ItemTemplates.reset) def _create_trimline(self): self._create_item(ItemTemplates.trim) def _create_package(self): self._create_item(ItemTemplates.package) def _create_fakom_trim(self): self._create_item(ItemTemplates.fakom_trim) def _create_fakom_option(self): self._create_item(ItemTemplates.fakom_option) def _create_output_item(self): self._create_item(ItemTemplates.output) def _create_plmxml_item(self): self._create_item(ItemTemplates.plmxml) def _create_separator(self): self._create_item(ItemTemplates.separator, False) def _create_item(self, item, create_id: bool = True): if not self.current_view: LOGGER.error('Can not find view in focus to add items to.') return self.current_view.editor.create.add_item(item, create_id=create_id) @Slot() def update_current_view(self): current_view = None if isinstance(self.parent_widget, QMainWindow): current_view = self.parent_widget.view_mgr.current_view() self.create_action_grp.setEnabled(True) LOGGER.debug('Create Menu about to show from Main Window Menu.') elif isinstance(self.parent_widget, QMenu): current_view = self.parent_widget.view self.create_action_grp.setEnabled(True) LOGGER.debug('Create Menu about to show from Context Menu.') if current_view.is_render_view: self.create_action_grp.setEnabled(False) self.current_view = current_view
def __init__(self, *args, **kwargs): super(MainWindow, self).__init__(*args, **kwargs) layout = QVBoxLayout() self.editor = TextEdit() # Setup the QTextEdit editor configuration self.editor.setAutoFormatting(QTextEdit.AutoAll) self.editor.selectionChanged.connect(self.update_format) # Initialize default font size. font = QFont('Times', 12) self.editor.setFont(font) # We need to repeat the size to init the current format. self.editor.setFontPointSize(12) # self.path holds the path of the currently open file. # If none, we haven't got a file open yet (or creating new). self.path = None layout.addWidget(self.editor) container = QWidget() container.setLayout(layout) self.setCentralWidget(container) self.status = QStatusBar() self.setStatusBar(self.status) # Uncomment to disable native menubar on Mac # self.menuBar().setNativeMenuBar(False) file_toolbar = QToolBar("File") file_toolbar.setIconSize(QSize(14, 14)) self.addToolBar(file_toolbar) file_menu = self.menuBar().addMenu("&File") open_file_action = QAction( QIcon(os.path.join('images', 'blue-folder-open-document.png')), "Open file...", self) open_file_action.setStatusTip("Open file") open_file_action.triggered.connect(self.file_open) file_menu.addAction(open_file_action) file_toolbar.addAction(open_file_action) save_file_action = QAction(QIcon(os.path.join('images', 'disk.png')), "Save", self) save_file_action.setStatusTip("Save current page") save_file_action.triggered.connect(self.file_save) file_menu.addAction(save_file_action) file_toolbar.addAction(save_file_action) saveas_file_action = QAction( QIcon(os.path.join('images', 'disk--pencil.png')), "Save As...", self) saveas_file_action.setStatusTip("Save current page to specified file") saveas_file_action.triggered.connect(self.file_saveas) file_menu.addAction(saveas_file_action) file_toolbar.addAction(saveas_file_action) print_action = QAction(QIcon(os.path.join('images', 'printer.png')), "Print...", self) print_action.setStatusTip("Print current page") print_action.triggered.connect(self.file_print) file_menu.addAction(print_action) file_toolbar.addAction(print_action) edit_toolbar = QToolBar("Edit") edit_toolbar.setIconSize(QSize(16, 16)) self.addToolBar(edit_toolbar) edit_menu = self.menuBar().addMenu("&Edit") undo_action = QAction( QIcon(os.path.join('images', 'arrow-curve-180-left.png')), "Undo", self) undo_action.setStatusTip("Undo last change") undo_action.triggered.connect(self.editor.undo) edit_menu.addAction(undo_action) redo_action = QAction(QIcon(os.path.join('images', 'arrow-curve.png')), "Redo", self) redo_action.setStatusTip("Redo last change") redo_action.triggered.connect(self.editor.redo) edit_toolbar.addAction(redo_action) edit_menu.addAction(redo_action) edit_menu.addSeparator() cut_action = QAction(QIcon(os.path.join('images', 'scissors.png')), "Cut", self) cut_action.setStatusTip("Cut selected text") cut_action.setShortcut(QKeySequence.Cut) cut_action.triggered.connect(self.editor.cut) edit_toolbar.addAction(cut_action) edit_menu.addAction(cut_action) copy_action = QAction( QIcon(os.path.join('images', 'document-copy.png')), "Copy", self) copy_action.setStatusTip("Copy selected text") cut_action.setShortcut(QKeySequence.Copy) copy_action.triggered.connect(self.editor.copy) edit_toolbar.addAction(copy_action) edit_menu.addAction(copy_action) paste_action = QAction( QIcon(os.path.join('images', 'clipboard-paste-document-text.png')), "Paste", self) paste_action.setStatusTip("Paste from clipboard") cut_action.setShortcut(QKeySequence.Paste) paste_action.triggered.connect(self.editor.paste) edit_toolbar.addAction(paste_action) edit_menu.addAction(paste_action) select_action = QAction( QIcon(os.path.join('images', 'selection-input.png')), "Select all", self) select_action.setStatusTip("Select all text") cut_action.setShortcut(QKeySequence.SelectAll) select_action.triggered.connect(self.editor.selectAll) edit_menu.addAction(select_action) edit_menu.addSeparator() wrap_action = QAction( QIcon(os.path.join('images', 'arrow-continue.png')), "Wrap text to window", self) wrap_action.setStatusTip("Toggle wrap text to window") wrap_action.setCheckable(True) wrap_action.setChecked(True) wrap_action.triggered.connect(self.edit_toggle_wrap) edit_menu.addAction(wrap_action) format_toolbar = QToolBar("Format") format_toolbar.setIconSize(QSize(16, 16)) self.addToolBar(format_toolbar) format_menu = self.menuBar().addMenu("&Format") # We need references to these actions/settings to update as selection changes, so attach to self. self.fonts = QFontComboBox() self.fonts.currentFontChanged.connect(self.editor.setCurrentFont) format_toolbar.addWidget(self.fonts) self.fontsize = QComboBox() self.fontsize.addItems([str(s) for s in FONT_SIZES]) # Connect to the signal producing the text of the current selection. Convert the string to float # and set as the pointsize. We could also use the index + retrieve from FONT_SIZES. self.fontsize.currentIndexChanged[str].connect( lambda s: self.editor.setFontPointSize(float(s))) format_toolbar.addWidget(self.fontsize) self.bold_action = QAction( QIcon(os.path.join('images', 'edit-bold.png')), "Bold", self) self.bold_action.setStatusTip("Bold") self.bold_action.setShortcut(QKeySequence.Bold) self.bold_action.setCheckable(True) self.bold_action.toggled.connect(lambda x: self.editor.setFontWeight( QFont.Bold if x else QFont.Normal)) format_toolbar.addAction(self.bold_action) format_menu.addAction(self.bold_action) self.italic_action = QAction( QIcon(os.path.join('images', 'edit-italic.png')), "Italic", self) self.italic_action.setStatusTip("Italic") self.italic_action.setShortcut(QKeySequence.Italic) self.italic_action.setCheckable(True) self.italic_action.toggled.connect(self.editor.setFontItalic) format_toolbar.addAction(self.italic_action) format_menu.addAction(self.italic_action) self.underline_action = QAction( QIcon(os.path.join('images', 'edit-underline.png')), "Underline", self) self.underline_action.setStatusTip("Underline") self.underline_action.setShortcut(QKeySequence.Underline) self.underline_action.setCheckable(True) self.underline_action.toggled.connect(self.editor.setFontUnderline) format_toolbar.addAction(self.underline_action) format_menu.addAction(self.underline_action) format_menu.addSeparator() self.alignl_action = QAction( QIcon(os.path.join('images', 'edit-alignment.png')), "Align left", self) self.alignl_action.setStatusTip("Align text left") self.alignl_action.setCheckable(True) self.alignl_action.triggered.connect( lambda: self.editor.setAlignment(Qt.AlignLeft)) format_toolbar.addAction(self.alignl_action) format_menu.addAction(self.alignl_action) self.alignc_action = QAction( QIcon(os.path.join('images', 'edit-alignment-center.png')), "Align center", self) self.alignc_action.setStatusTip("Align text center") self.alignc_action.setCheckable(True) self.alignc_action.triggered.connect( lambda: self.editor.setAlignment(Qt.AlignCenter)) format_toolbar.addAction(self.alignc_action) format_menu.addAction(self.alignc_action) self.alignr_action = QAction( QIcon(os.path.join('images', 'edit-alignment-right.png')), "Align right", self) self.alignr_action.setStatusTip("Align text right") self.alignr_action.setCheckable(True) self.alignr_action.triggered.connect( lambda: self.editor.setAlignment(Qt.AlignRight)) format_toolbar.addAction(self.alignr_action) format_menu.addAction(self.alignr_action) self.alignj_action = QAction( QIcon(os.path.join('images', 'edit-alignment-justify.png')), "Justify", self) self.alignj_action.setStatusTip("Justify text") self.alignj_action.setCheckable(True) self.alignj_action.triggered.connect( lambda: self.editor.setAlignment(Qt.AlignJustify)) format_toolbar.addAction(self.alignj_action) format_menu.addAction(self.alignj_action) format_group = QActionGroup(self) format_group.setExclusive(True) format_group.addAction(self.alignl_action) format_group.addAction(self.alignc_action) format_group.addAction(self.alignr_action) format_group.addAction(self.alignj_action) format_menu.addSeparator() # A list of all format-related widgets/actions, so we can disable/enable signals when updating. self._format_actions = [ self.fonts, self.fontsize, self.bold_action, self.italic_action, self.underline_action, # We don't need to disable signals for alignment, as they are paragraph-wide. ] # Initialize. self.update_format() self.update_title() self.show()
class MainWindow(QMainWindow, Ui_MainWindow): """docstring for MainWindow.""" def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self._csvFilePath = "" self.serialport = serial.Serial() self.receiver_thread = readerThread(self) self.receiver_thread.setPort(self.serialport) self._localEcho = None self.setupUi(self) self.setCorner(Qt.TopLeftCorner, Qt.LeftDockWidgetArea) self.setCorner(Qt.BottomLeftCorner, Qt.LeftDockWidgetArea) font = QtGui.QFont() font.setFamily(EDITOR_FONT) font.setPointSize(10) self.txtEdtOutput.setFont(font) self.txtEdtInput.setFont(font) self.quickSendTable.setFont(font) if UI_FONT is not None: font = QtGui.QFont() font.setFamily(UI_FONT) font.setPointSize(9) self.dockWidget_PortConfig.setFont(font) self.dockWidget_SendHex.setFont(font) self.dockWidget_QuickSend.setFont(font) self.setupFlatUi() self.onEnumPorts() icon = QtGui.QIcon(":/icon.ico") self.setWindowIcon(icon) self.actionAbout.setIcon(icon) icon = QtGui.QIcon(":/qt_logo_16.ico") self.actionAbout_Qt.setIcon(icon) self._viewGroup = QActionGroup(self) self._viewGroup.addAction(self.actionAscii) self._viewGroup.addAction(self.actionHex_lowercase) self._viewGroup.addAction(self.actionHEX_UPPERCASE) self._viewGroup.setExclusive(True) # bind events self.actionOpen_Cmd_File.triggered.connect(self.openCSV) self.actionSave_Log.triggered.connect(self.onSaveLog) self.actionExit.triggered.connect(self.onExit) self.actionOpen.triggered.connect(self.openPort) self.actionClose.triggered.connect(self.closePort) self.actionPort_Config_Panel.triggered.connect(self.onTogglePrtCfgPnl) self.actionQuick_Send_Panel.triggered.connect(self.onToggleQckSndPnl) self.actionSend_Hex_Panel.triggered.connect(self.onToggleHexPnl) self.dockWidget_PortConfig.visibilityChanged.connect(self.onVisiblePrtCfgPnl) self.dockWidget_QuickSend.visibilityChanged.connect(self.onVisibleQckSndPnl) self.dockWidget_SendHex.visibilityChanged.connect(self.onVisibleHexPnl) self.actionLocal_Echo.triggered.connect(self.onLocalEcho) self.actionAlways_On_Top.triggered.connect(self.onAlwaysOnTop) self.actionAscii.triggered.connect(self.onViewChanged) self.actionHex_lowercase.triggered.connect(self.onViewChanged) self.actionHEX_UPPERCASE.triggered.connect(self.onViewChanged) self.actionAbout.triggered.connect(self.onAbout) self.actionAbout_Qt.triggered.connect(self.onAboutQt) self.btnOpen.clicked.connect(self.onOpen) self.btnClear.clicked.connect(self.onClear) self.btnSaveLog.clicked.connect(self.onSaveLog) self.btnEnumPorts.clicked.connect(self.onEnumPorts) self.btnSendHex.clicked.connect(self.sendHex) self.receiver_thread.read.connect(self.receive) self.receiver_thread.exception.connect(self.readerExcept) self._signalMap = QSignalMapper(self) self._signalMap.mapped[int].connect(self.tableClick) # initial action self.actionHEX_UPPERCASE.setChecked(True) self.receiver_thread.setViewMode(VIEWMODE_HEX_UPPERCASE) self.initQuickSend() self.restoreLayout() self.moveScreenCenter() self.syncMenu() if self.isMaximized(): self.setMaximizeButton("restore") else: self.setMaximizeButton("maximize") self.LoadSettings() def setupFlatUi(self): self._dragPos = self.pos() self._isDragging = False self.setMouseTracking(True) self.setWindowFlags(Qt.FramelessWindowHint) self.setStyleSheet(""" QWidget { background-color:#99d9ea; /*background-image: url(:/background.png);*/ outline: 1px solid #0057ff; } QLabel { color:#202020; font-size:13px; font-family:Century; } QComboBox { color:#202020; font-size:13px; font-family:Century Schoolbook; } QComboBox { border: none; padding: 1px 18px 1px 3px; } QComboBox:editable { background: white; } QComboBox:!editable, QComboBox::drop-down:editable { background: #62c7e0; } QComboBox:!editable:hover, QComboBox::drop-down:editable:hover { background: #c7eaf3; } QComboBox:!editable:pressed, QComboBox::drop-down:editable:pressed { background: #35b6d7; } QComboBox:on { padding-top: 3px; padding-left: 4px; } QComboBox::drop-down { subcontrol-origin: padding; subcontrol-position: top right; width: 16px; border: none; } QComboBox::down-arrow { image: url(:/downarrow.png); } QComboBox::down-arrow:on { image: url(:/uparrow.png); } QGroupBox { color:#202020; font-size:12px; font-family:Century Schoolbook; border: 1px solid gray; margin-top: 15px; } QGroupBox::title { subcontrol-origin: margin; subcontrol-position: top left; left:5px; top:3px; } QCheckBox { color:#202020; spacing: 5px; font-size:12px; font-family:Century Schoolbook; } QScrollBar:horizontal { background-color:#99d9ea; border: none; height: 15px; margin: 0px 20px 0 20px; } QScrollBar::handle:horizontal { background: #61b9e1; min-width: 20px; } QScrollBar::add-line:horizontal { image: url(:/rightarrow.png); border: none; background: #7ecfe4; width: 20px; subcontrol-position: right; subcontrol-origin: margin; } QScrollBar::sub-line:horizontal { image: url(:/leftarrow.png); border: none; background: #7ecfe4; width: 20px; subcontrol-position: left; subcontrol-origin: margin; } QScrollBar:vertical { background-color:#99d9ea; border: none; width: 15px; margin: 20px 0px 20px 0px; } QScrollBar::handle::vertical { background: #61b9e1; min-height: 20px; } QScrollBar::add-line::vertical { image: url(:/downarrow.png); border: none; background: #7ecfe4; height: 20px; subcontrol-position: bottom; subcontrol-origin: margin; } QScrollBar::sub-line::vertical { image: url(:/uparrow.png); border: none; background: #7ecfe4; height: 20px; subcontrol-position: top; subcontrol-origin: margin; } QTableView { background-color: white; /*selection-background-color: #FF92BB;*/ border: 1px solid #eeeeee; color: #2f2f2f; } QTableView::focus { /*border: 1px solid #2a7fff;*/ } QTableView QTableCornerButton::section { border: none; border-right: 1px solid #eeeeee; border-bottom: 1px solid #eeeeee; background-color: #8ae6d2; } QTableView QWidget { background-color: white; } QTableView::item:focus { border: 1px red; background-color: transparent; color: #2f2f2f; } QHeaderView::section { border: none; border-right: 1px solid #eeeeee; border-bottom: 1px solid #eeeeee; padding-left: 2px; padding-right: 2px; color: #444444; background-color: #8ae6d2; } QTextEdit { background-color:white; color:#2f2f2f; border: 1px solid white; } QTextEdit::focus { border: 1px solid #2a7fff; } QPushButton { background-color:#30a7b8; border:none; color:#ffffff; font-size:14px; font-family:Century Schoolbook; } QPushButton:hover { background-color:#51c0d1; } QPushButton:pressed { background-color:#3a9ecc; } QMenuBar { color: #2f2f2f; } QMenuBar::item { background-color: transparent; margin: 8px 0px 0px 0px; padding: 1px 8px 1px 8px; height: 15px; } QMenuBar::item:selected { background: #51c0d1; } QMenuBar::item:pressed { } QMenu { color: #2f2f2f; } QMenu { margin: 2px; } QMenu::item { padding: 2px 25px 2px 21px; border: 1px solid transparent; } QMenu::item:selected { background: #51c0d1; } QMenu::icon { background: transparent; border: 2px inset transparent; } QDockWidget { font-size:13px; font-family:Century; color: #202020; titlebar-close-icon: none; titlebar-normal-icon: none; } QDockWidget::title { margin: 0; padding: 2px; subcontrol-origin: content; subcontrol-position: right top; text-align: left; background: #67baed; } QDockWidget::float-button { max-width: 12px; max-height: 12px; background-color:transparent; border:none; image: url(:/restore_inactive.png); } QDockWidget::float-button:hover { background-color:#227582; image: url(:/restore_active.png); } QDockWidget::float-button:pressed { padding: 0; background-color:#14464e; image: url(:/restore_active.png); } QDockWidget::close-button { max-width: 12px; max-height: 12px; background-color:transparent; border:none; image: url(:/close_inactive.png); } QDockWidget::close-button:hover { background-color:#ea5e00; image: url(:/close_active.png); } QDockWidget::close-button:pressed { background-color:#994005; image: url(:/close_active.png); padding: 0; } """) self.dockWidgetContents.setStyleSheet(""" QPushButton { min-height:23px; } """) self.dockWidget_QuickSend.setStyleSheet(""" QPushButton { background-color:#27b798; font-family:Consolas; font-size:12px; min-width:46px; } QPushButton:hover { background-color:#3bd5b4; } QPushButton:pressed { background-color:#1d8770; } """) self.dockWidgetContents_2.setStyleSheet(""" QPushButton { min-height:23px; min-width:50px; } """) w = self.frameGeometry().width() self._minBtn = QPushButton(self) self._minBtn.setGeometry(w-103,0,28,24) self._minBtn.clicked.connect(self.onMinimize) self._minBtn.setStyleSheet(""" QPushButton { background-color:transparent; border:none; outline: none; image: url(:/minimize_inactive.png); } QPushButton:hover { background-color:#227582; image: url(:/minimize_active.png); } QPushButton:pressed { background-color:#14464e; image: url(:/minimize_active.png); } """) self._maxBtn = QPushButton(self) self._maxBtn.setGeometry(w-74,0,28,24) self._maxBtn.clicked.connect(self.onMaximize) self.setMaximizeButton("maximize") self._closeBtn = QPushButton(self) self._closeBtn.setGeometry(w-45,0,36,24) self._closeBtn.clicked.connect(self.onExit) self._closeBtn.setStyleSheet(""" QPushButton { background-color:transparent; border:none; outline: none; image: url(:/close_inactive.png); } QPushButton:hover { background-color:#ea5e00; image: url(:/close_active.png); } QPushButton:pressed { background-color:#994005; image: url(:/close_active.png); } """) def resizeEvent(self, event): w = event.size().width() self._minBtn.move(w-103,0) self._maxBtn.move(w-74,0) self._closeBtn.move(w-45,0) def onMinimize(self): self.showMinimized() def isMaximized(self): return ((self.windowState() == Qt.WindowMaximized)) def onMaximize(self): if self.isMaximized(): self.showNormal() self.setMaximizeButton("maximize") else: self.showMaximized() self.setMaximizeButton("restore") def setMaximizeButton(self, style): if "maximize" == style: self._maxBtn.setStyleSheet(""" QPushButton { background-color:transparent; border:none; outline: none; image: url(:/maximize_inactive.png); } QPushButton:hover { background-color:#227582; image: url(:/maximize_active.png); } QPushButton:pressed { background-color:#14464e; image: url(:/maximize_active.png); } """) elif "restore" == style: self._maxBtn.setStyleSheet(""" QPushButton { background-color:transparent; border:none; outline: none; image: url(:/restore_inactive.png); } QPushButton:hover { background-color:#227582; image: url(:/restore_active.png); } QPushButton:pressed { background-color:#14464e; image: url(:/restore_active.png); } """) def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self._isDragging = True self._dragPos = event.globalPos() - self.pos() event.accept() def mouseMoveEvent(self, event): if event.buttons() == Qt.LeftButton and self._isDragging and not self.isMaximized(): self.move(event.globalPos() - self._dragPos) event.accept() def mouseReleaseEvent(self, event): self._isDragging = False event.accept() def SaveSettings(self): root = ET.Element("MyTerm") GUISettings = ET.SubElement(root, "GUISettings") PortCfg = ET.SubElement(GUISettings, "PortConfig") ET.SubElement(PortCfg, "port").text = self.cmbPort.currentText() ET.SubElement(PortCfg, "baudrate").text = self.cmbBaudRate.currentText() ET.SubElement(PortCfg, "databits").text = self.cmbDataBits.currentText() ET.SubElement(PortCfg, "parity").text = self.cmbParity.currentText() ET.SubElement(PortCfg, "stopbits").text = self.cmbStopBits.currentText() ET.SubElement(PortCfg, "rtscts").text = self.chkRTSCTS.isChecked() and "on" or "off" ET.SubElement(PortCfg, "xonxoff").text = self.chkXonXoff.isChecked() and "on" or "off" View = ET.SubElement(GUISettings, "View") ET.SubElement(View, "LocalEcho").text = self.actionLocal_Echo.isChecked() and "on" or "off" ET.SubElement(View, "ReceiveView").text = self._viewGroup.checkedAction().text() with open(get_config_path('settings.xml'), 'w') as f: f.write('<?xml version="1.0" encoding="UTF-8"?>\n') f.write(ET.tostring(root, encoding='utf-8', pretty_print=True).decode("utf-8")) def LoadSettings(self): if os.path.isfile(get_config_path("settings.xml")): with open(get_config_path("settings.xml"), 'r') as f: tree = safeET.parse(f) port = tree.findtext('GUISettings/PortConfig/port', default='') if port != '': self.cmbPort.setCurrentText(port) baudrate = tree.findtext('GUISettings/PortConfig/baudrate', default='38400') if baudrate != '': self.cmbBaudRate.setCurrentText(baudrate) databits = tree.findtext('GUISettings/PortConfig/databits', default='8') id = self.cmbDataBits.findText(databits) if id >= 0: self.cmbDataBits.setCurrentIndex(id) parity = tree.findtext('GUISettings/PortConfig/parity', default='None') id = self.cmbParity.findText(parity) if id >= 0: self.cmbParity.setCurrentIndex(id) stopbits = tree.findtext('GUISettings/PortConfig/stopbits', default='1') id = self.cmbStopBits.findText(stopbits) if id >= 0: self.cmbStopBits.setCurrentIndex(id) rtscts = tree.findtext('GUISettings/PortConfig/rtscts', default='off') if 'on' == rtscts: self.chkRTSCTS.setChecked(True) else: self.chkRTSCTS.setChecked(False) xonxoff = tree.findtext('GUISettings/PortConfig/xonxoff', default='off') if 'on' == xonxoff: self.chkXonXoff.setChecked(True) else: self.chkXonXoff.setChecked(False) LocalEcho = tree.findtext('GUISettings/View/LocalEcho', default='off') if 'on' == LocalEcho: self.actionLocal_Echo.setChecked(True) self._localEcho = True else: self.actionLocal_Echo.setChecked(False) self._localEcho = False ReceiveView = tree.findtext('GUISettings/View/ReceiveView', default='HEX(UPPERCASE)') if 'Ascii' in ReceiveView: self.actionAscii.setChecked(True) elif 'lowercase' in ReceiveView: self.actionHex_lowercase.setChecked(True) elif 'UPPERCASE' in ReceiveView: self.actionHEX_UPPERCASE.setChecked(True) def closeEvent(self, event): self.saveLayout() self.saveCSV() self.SaveSettings() event.accept() def tableClick(self, row): self.sendTableRow(row) def initQuickSend(self): #self.quickSendTable.horizontalHeader().setDefaultSectionSize(40) #self.quickSendTable.horizontalHeader().setMinimumSectionSize(25) self.quickSendTable.setRowCount(50) self.quickSendTable.setColumnCount(20) for row in range(50): item = QPushButton(str("Send")) item.clicked.connect(self._signalMap.map) self._signalMap.setMapping(item, row) self.quickSendTable.setCellWidget(row, 0, item) self.quickSendTable.setRowHeight(row, 20) if os.path.isfile(get_config_path('QckSndBckup.csv')): self.loadCSV(get_config_path('QckSndBckup.csv')) self.quickSendTable.resizeColumnsToContents() def openCSV(self): fileName = QFileDialog.getOpenFileName(self, "Select a file", os.getcwd(), "CSV Files (*.csv)")[0] if fileName: self.loadCSV(fileName, notifyExcept = True) def saveCSV(self): # scan table rows = self.quickSendTable.rowCount() cols = self.quickSendTable.columnCount() tmp_data = [[self.quickSendTable.item(row, col) is not None and self.quickSendTable.item(row, col).text() or '' for col in range(1, cols)] for row in range(rows)] data = [] # delete trailing blanks for row in tmp_data: for idx, d in enumerate(row[::-1]): if '' != d: break new_row = row[:len(row) - idx] data.append(new_row) #import pprint #pprint.pprint(data, width=120, compact=True) # write to file with open(get_config_path('QckSndBckup.csv'), 'w') as csvfile: csvwriter = csv.writer(csvfile, delimiter=',', lineterminator='\n') csvwriter.writerows(data) def loadCSV(self, path, notifyExcept = False): data = [] set_rows = 0 set_cols = 0 try: with open(path) as csvfile: csvData = csv.reader(csvfile) for row in csvData: data.append(row) set_rows = set_rows + 1 if len(row) > set_cols: set_cols = len(row) except IOError as e: print("({})".format(e)) if notifyExcept: QMessageBox.critical(self, "Open failed", str(e), QMessageBox.Close) return rows = self.quickSendTable.rowCount() cols = self.quickSendTable.columnCount() # clear table for col in range(cols): for row in range(rows): self.quickSendTable.setItem(row, col, QTableWidgetItem("")) self._csvFilePath = path if (cols - 1) < set_cols: # first colume is used by the "send" buttons. cols = set_cols + 10 self.quickSendTable.setColumnCount(cols) if rows < set_rows: rows = set_rows + 20 self.quickSendTable.setRowCount(rows) for row, rowdat in enumerate(data): if len(rowdat) > 0: for col, cell in enumerate(rowdat, 1): self.quickSendTable.setItem(row, col, QTableWidgetItem(str(cell))) self.quickSendTable.resizeColumnsToContents() #self.quickSendTable.resizeRowsToContents() def sendTableRow(self, row): cols = self.quickSendTable.columnCount() try: data = ['0' + self.quickSendTable.item(row, col).text() for col in range(1, cols) if self.quickSendTable.item(row, col) is not None and self.quickSendTable.item(row, col).text() is not ''] except: print("Exception in get table data(row = %d)" % (row + 1)) else: tmp = [d[-2] + d[-1] for d in data if len(d) >= 2] for t in tmp: if not is_hex(t): QMessageBox.critical(self, "Error", "'%s' is not hexadecimal." % (t), QMessageBox.Close) return h = [int(t, 16) for t in tmp] self.transmitHex(h) def sendHex(self): hexStr = self.txtEdtInput.toPlainText() hexStr = ''.join(hexStr.split(" ")) hexarray = [] for i in range(0, len(hexStr), 2): hexarray.append(int(hexStr[i:i+2], 16)) self.transmitHex(hexarray) def readerExcept(self, e): self.closePort() QMessageBox.critical(self, "Read failed", str(e), QMessageBox.Close) def timestamp(self): return datetime.datetime.now().time().isoformat()[:-3] def receive(self, data): self.appendOutputText("\n%s R<-:%s" % (self.timestamp(), data)) def appendOutputText(self, data, color=Qt.black): # the qEditText's "append" methon will add a unnecessary newline. # self.txtEdtOutput.append(data.decode('utf-8')) tc=self.txtEdtOutput.textColor() self.txtEdtOutput.moveCursor(QtGui.QTextCursor.End) self.txtEdtOutput.setTextColor(QtGui.QColor(color)) self.txtEdtOutput.insertPlainText(data) self.txtEdtOutput.moveCursor(QtGui.QTextCursor.End) self.txtEdtOutput.setTextColor(tc) def transmitHex(self, hexarray): if len(hexarray) > 0: byteArray = bytearray(hexarray) if self.serialport.isOpen(): try: self.serialport.write(byteArray) except serial.SerialException as e: print("Exception in transmitHex(%s)" % repr(hexarray)) QMessageBox.critical(self, "Exception in transmitHex", str(e), QMessageBox.Close) else: # self.txCount += len( b ) # self.frame.statusbar.SetStatusText('Tx:%d' % self.txCount, 2) text = ''.join(['%02X ' % i for i in hexarray]) self.appendOutputText("\n%s T->:%s" % (self.timestamp(), text), Qt.blue) def GetPort(self): return self.cmbPort.currentText() def GetDataBits(self): s = self.cmbDataBits.currentText() if s == '5': return serial.FIVEBITS elif s == '6': return serial.SIXBITS elif s == '7': return serial.SEVENBITS elif s == '8': return serial.EIGHTBITS def GetParity(self): s = self.cmbParity.currentText() if s == 'None': return serial.PARITY_NONE elif s == 'Even': return serial.PARITY_EVEN elif s == 'Odd': return serial.PARITY_ODD elif s == 'Mark': return serial.PARITY_MARK elif s == 'Space': return serial.PARITY_SPACE def GetStopBits(self): s = self.cmbStopBits.currentText() if s == '1': return serial.STOPBITS_ONE elif s == '1.5': return serial.STOPBITS_ONE_POINT_FIVE elif s == '2': return serial.STOPBITS_TWO def openPort(self): if self.serialport.isOpen(): return _port = self.GetPort() if '' == _port: QMessageBox.information(self, "Invalid parameters", "Port is empty.") return _baudrate = self.cmbBaudRate.currentText() if '' == _baudrate: QMessageBox.information(self, "Invalid parameters", "Baudrate is empty.") return self.serialport.port = _port self.serialport.baudrate = _baudrate self.serialport.bytesize = self.GetDataBits() self.serialport.stopbits = self.GetStopBits() self.serialport.parity = self.GetParity() self.serialport.rtscts = self.chkRTSCTS.isChecked() self.serialport.xonxoff = self.chkXonXoff.isChecked() # self.serialport.timeout = THREAD_TIMEOUT # self.serialport.writeTimeout = SERIAL_WRITE_TIMEOUT try: self.serialport.open() except serial.SerialException as e: QMessageBox.critical(self, "Could not open serial port", str(e), QMessageBox.Close) else: self._start_reader() self.setWindowTitle("%s on %s [%s, %s%s%s%s%s]" % ( appInfo.title, self.serialport.portstr, self.serialport.baudrate, self.serialport.bytesize, self.serialport.parity, self.serialport.stopbits, self.serialport.rtscts and ' RTS/CTS' or '', self.serialport.xonxoff and ' Xon/Xoff' or '', ) ) pal = self.btnOpen.palette() pal.setColor(QtGui.QPalette.Button, QtGui.QColor(0,0xff,0x7f)) self.btnOpen.setAutoFillBackground(True) self.btnOpen.setPalette(pal) self.btnOpen.setText('Close') self.btnOpen.update() def closePort(self): if self.serialport.isOpen(): self._stop_reader() self.serialport.close() self.setWindowTitle(appInfo.title) pal = self.btnOpen.style().standardPalette() self.btnOpen.setAutoFillBackground(True) self.btnOpen.setPalette(pal) self.btnOpen.setText('Open') self.btnOpen.update() def _start_reader(self): """Start reader thread""" self.receiver_thread.start() def _stop_reader(self): """Stop reader thread only, wait for clean exit of thread""" self.receiver_thread.join() def onTogglePrtCfgPnl(self): if self.actionPort_Config_Panel.isChecked(): self.dockWidget_PortConfig.show() else: self.dockWidget_PortConfig.hide() def onToggleQckSndPnl(self): if self.actionQuick_Send_Panel.isChecked(): self.dockWidget_QuickSend.show() else: self.dockWidget_QuickSend.hide() def onToggleHexPnl(self): if self.actionSend_Hex_Panel.isChecked(): self.dockWidget_SendHex.show() else: self.dockWidget_SendHex.hide() def onVisiblePrtCfgPnl(self, visible): self.actionPort_Config_Panel.setChecked(visible) def onVisibleQckSndPnl(self, visible): self.actionQuick_Send_Panel.setChecked(visible) def onVisibleHexPnl(self, visible): self.actionSend_Hex_Panel.setChecked(visible) def onLocalEcho(self): self._localEcho = self.actionLocal_Echo.isChecked() def onAlwaysOnTop(self): if self.actionAlways_On_Top.isChecked(): style = self.windowFlags() self.setWindowFlags(style|Qt.WindowStaysOnTopHint) self.show() else: style = self.windowFlags() self.setWindowFlags(style & ~Qt.WindowStaysOnTopHint) self.show() def onOpen(self): if self.serialport.isOpen(): self.closePort() else: self.openPort() def onClear(self): self.txtEdtOutput.clear() def onSaveLog(self): fileName = QFileDialog.getSaveFileName(self, "Save as", os.getcwd(), "Log files (*.log);;Text files (*.txt);;All files (*.*)")[0] if fileName: import codecs f = codecs.open(fileName, 'w', 'utf-8') f.write(self.txtEdtOutput.toPlainText()) f.close() def moveScreenCenter(self): w = self.frameGeometry().width() h = self.frameGeometry().height() desktop = QDesktopWidget() screenW = desktop.screen().width() screenH = desktop.screen().height() self.setGeometry((screenW-w)/2, (screenH-h)/2, w, h) def onEnumPorts(self): for p in enum_ports(): self.cmbPort.addItem(p) # self.cmbPort.update() def onAbout(self): q = QWidget() icon = QtGui.QIcon(":/icon.ico") q.setWindowIcon(icon) QMessageBox.about(q, "About MyTerm", appInfo.aboutme) def onAboutQt(self): QMessageBox.aboutQt(None) def onExit(self): if self.serialport.isOpen(): self.closePort() self.close() def restoreLayout(self): if os.path.isfile(get_config_path("layout.dat")): try: f=open(get_config_path("layout.dat"), 'rb') geometry, state=pickle.load(f) self.restoreGeometry(geometry) self.restoreState(state) except Exception as e: print("Exception on restoreLayout, {}".format(e)) else: try: f=QFile(':/default_layout.dat') f.open(QIODevice.ReadOnly) geometry, state=pickle.loads(f.readAll()) self.restoreGeometry(geometry) self.restoreState(state) except Exception as e: print("Exception on restoreLayout, {}".format(e)) def saveLayout(self): with open(get_config_path("layout.dat"), 'wb') as f: pickle.dump((self.saveGeometry(), self.saveState()), f) def syncMenu(self): self.actionPort_Config_Panel.setChecked(not self.dockWidget_PortConfig.isHidden()) self.actionQuick_Send_Panel.setChecked(not self.dockWidget_QuickSend.isHidden()) self.actionSend_Hex_Panel.setChecked(not self.dockWidget_SendHex.isHidden()) def onViewChanged(self): checked = self._viewGroup.checkedAction() if checked is None: self.actionHEX_UPPERCASE.setChecked(True) self.receiver_thread.setViewMode(VIEWMODE_HEX_UPPERCASE) else: if 'Ascii' in checked.text(): self.receiver_thread.setViewMode(VIEWMODE_ASCII) elif 'lowercase' in checked.text(): self.receiver_thread.setViewMode(VIEWMODE_HEX_LOWERCASE) elif 'UPPERCASE' in checked.text(): self.receiver_thread.setViewMode(VIEWMODE_HEX_UPPERCASE)
class AsSceneMenu(QMenu): def __init__(self, ui, menu_name: str = _('DeltaGen')): """ Setup AsConnector Scene Selection menu :param modules.gui.main_ui.KnechtWindow ui: :param menu_name: name of the menu that will be displayed """ super(AsSceneMenu, self).__init__(menu_name, ui) self.ui = ui self.addAction(self._no_conn_action()) self.action_grp = QActionGroup(self) self.action_grp.setExclusive(True) self.setIcon(IconRsc.get_icon('paperplane')) self._awaiting_result = False self.aboutToShow.connect(self._about_to_show) QTimer.singleShot(500, self._delayed_setup) def _delayed_setup(self): self.ui.app.send_dg.plm_xml_controller.scene_active_result.connect(self._update_menu) self.ui.app.send_dg.plm_xml_controller.no_connection.connect(self._update_menu) def _update_menu(self, active_scene=None, scenes=None): self._clear_menu() if not active_scene and not scenes: self.addAction(self._no_conn_action()) return for scene_name in scenes: self.create_scene_action(scene_name, scene_name == active_scene) self._awaiting_result = False def _warn_msg(self): return QAction(IconRsc.get_icon('warn'), _('AsConnector unterstützt nur Schaltungen in zuletzt geladener ' 'Szene! Diese Funktion ist experimentell.'), self) def _no_conn_action(self): return QAction(IconRsc.get_icon('close'), _('Keine AsConnector Verbindung oder keine Szenen geöffnet.'), self) def _requested_info(self): return QAction(IconRsc.get_icon('later'), _('AsConnector Szenen angefordert, einen Moment.'), self) def _toggle_scene(self): for s in self.actions(): if s.isChecked(): scene_name = s.text() self.ui.app.send_dg.send_active_scene_request(scene_name) def create_scene_action(self, scene_name: str, is_active: bool): s = QAction(IconRsc.get_icon('document'), scene_name, self.action_grp) s.setCheckable(True) s.setChecked(is_active) s.triggered.connect(self._toggle_scene) self.addAction(s) def _clear_menu(self): self.clear() self.addAction(self._warn_msg()) def _about_to_show(self): if len(self.actions()) == 1: self._clear_menu() self.addAction(self._requested_info()) if not self._awaiting_result: # Request list of available AsConnector scene without setting a scene active(None) self.ui.app.send_dg.send_active_scene_request(None) self._awaiting_result = True
class EditMenu(QMenu): enable_undo_actions = Signal(bool) def __init__(self, ui, menu_name: str = _('Bearbeiten')): """ :param modules.gui.main_ui.KnechtWindow ui: The main ui class :param str menu_name: Edit Menu display name """ super(EditMenu, self).__init__(menu_name, ui) self.ui = ui self.view = None # View Editor self.history = DocHistoryWidget(ui, self) self.undo_timer = QTimer() self.undo_timer.setInterval(50) self.undo_timer.setSingleShot(True) self.undo_timer.timeout.connect(self.undo_timeout_stop) self.undo_action_grp = QActionGroup(self) self.undo_action_grp.setExclusive(False) self.undo_action_grp.triggered.connect(self.undo_timeout_start) self.undo_action = ui.app.undo_grp.createUndoAction( self.undo_action_grp, prefix=_('Rückgängig:')) self.undo_action.setIcon(IconRsc.get_icon('undo')) self.undo_action.setShortcut(QKeySequence('Ctrl+Z')) self.addAction(self.undo_action) self.redo_action = ui.app.undo_grp.createRedoAction( self.undo_action_grp, prefix=_('Wiederherstellen:')) self.redo_action.setIcon(IconRsc.get_icon('redo')) self.redo_action.setShortcut(QKeySequence('Ctrl+Y')) self.addAction(self.redo_action) self.history_action = QAction(IconRsc.get_icon('later'), _('Historie\tStrg+H'), self) self.history_action.triggered.connect(self.toggle_history) self.history_action.setShortcut(QKeySequence('Ctrl+H')) self.addAction(self.history_action) self.addSeparator() self.search_action = QAction(IconRsc.get_icon('search'), _('Suchen und Ersetzen\tStrg+F'), self) self.search_action.triggered.connect(self.search) self.search_action.setShortcut(QKeySequence('Ctrl+F')) self.addAction(self.search_action) self.search_dlg = SearchDialog(self.ui) self.addSeparator() self.copy_action = QAction(IconRsc.get_icon('clip_copy'), _('Kopieren\tStrg+C'), self) self.copy_action.setShortcut(QKeySequence('Ctrl+C')) self.copy_action.triggered.connect(self.copy) self.addAction(self.copy_action) self.cut_action = QAction(IconRsc.get_icon('clip_cut'), _('Ausschneiden\tStrg+X'), self) self.cut_action.setShortcut(QKeySequence('Ctrl+X')) self.cut_action.triggered.connect(self.cut) self.addAction(self.cut_action) self.paste_action = QAction(IconRsc.get_icon('clip_paste'), _('Einfügen\tStrg+V'), self) self.paste_action.setShortcut(QKeySequence('Ctrl+V')) self.paste_action.triggered.connect(self.paste) self.addAction(self.paste_action) self.addSeparator() self.remove_rows_action = QAction( IconRsc.get_icon('trash-a'), _('Selektierte Zeilen entfernen\tEntf'), self) self.remove_rows_action.setShortcut(QKeySequence.Delete) self.remove_rows_action.triggered.connect(self.remove_rows) self.addAction(self.remove_rows_action) self.addSeparator() self.select_ref_action = QAction(_('Referenzen selektieren\tStrg+R'), self) self.select_ref_action.setShortcut(QKeySequence('Ctrl+R')) self.select_ref_action.triggered.connect(self.select_references) self.addAction(self.select_ref_action) self.select_none_action = QAction(_('Selektion aufheben\tStrg+D'), self) self.select_none_action.setShortcut(QKeySequence('Ctrl+D')) self.select_none_action.triggered.connect(self.deselect) self.addAction(self.select_none_action) self.aboutToShow.connect(self.update_view) QTimer.singleShot(1, self.delayed_setup) @Slot() def delayed_setup(self): """ Setup attributes that require a fully initialized ui""" self.view = self.ui.variantTree self.update_view() self.ui.tree_focus_changed.connect(self.update_view) def undo_timeout_start(self): self.undo_action_grp.setEnabled(False) self.undo_timer.start() def undo_timeout_stop(self): if not self.view.editor.enabled: self.undo_timer.start() return self.undo_action_grp.setEnabled(True) def search(self): self.search_dlg.center_on_ui() self.search_dlg.show() def select_references(self): self.view.editor.selection.select_references() def deselect(self): self.view.editor.selection.clear_selection() def copy(self): self.ui.clipboard.items = self.view.editor.copy_items() self.ui.clipboard.origin = self.view.editor.view def cut(self): self.copy() self.view.editor.remove_rows() def paste(self): if not self.ui.clipboard.items: return self.view.editor.paste_items(self.ui.clipboard) def remove_rows(self): self.view.editor.remove_rows() def toggle_history(self): if self.history.isHidden(): self.history.show() else: self.history.hide() def update_view(self): self.view = self.ui.tree_with_focus()
def __init__(self, *args, **kwargs): super(MainWindow, self).__init__(*args, **kwargs) view = QGraphicsView() self.scene = QGraphicsScene() self.scene.setSceneRect(QRectF(0, 0, *WINDOW_SIZE)) felt = QBrush(QPixmap(os.path.join('images', 'felt.png'))) self.scene.setBackgroundBrush(felt) name = QGraphicsPixmapItem() name.setPixmap(QPixmap(os.path.join('images', 'ronery.png'))) name.setPos(QPointF(170, 375)) self.scene.addItem(name) view.setScene(self.scene) # Timer for the win animation only. self.timer = QTimer() self.timer.setInterval(5) self.timer.timeout.connect(self.win_animation) self.animation_event_cover = AnimationCover() self.scene.addItem(self.animation_event_cover) menu = self.menuBar().addMenu("&Game") deal_action = QAction( QIcon(os.path.join('images', 'playing-card.png')), "Deal...", self) deal_action.triggered.connect(self.restart_game) menu.addAction(deal_action) menu.addSeparator() deal1_action = QAction("1 card", self) deal1_action.setCheckable(True) deal1_action.triggered.connect(lambda: self.set_deal_n(1)) menu.addAction(deal1_action) deal3_action = QAction("3 card", self) deal3_action.setCheckable(True) deal3_action.setChecked(True) deal3_action.triggered.connect(lambda: self.set_deal_n(3)) menu.addAction(deal3_action) dealgroup = QActionGroup(self) dealgroup.addAction(deal1_action) dealgroup.addAction(deal3_action) dealgroup.setExclusive(True) menu.addSeparator() rounds3_action = QAction("3 rounds", self) rounds3_action.setCheckable(True) rounds3_action.setChecked(True) rounds3_action.triggered.connect(lambda: self.set_rounds_n(3)) menu.addAction(rounds3_action) rounds5_action = QAction("5 rounds", self) rounds5_action.setCheckable(True) rounds5_action.triggered.connect(lambda: self.set_rounds_n(5)) menu.addAction(rounds5_action) roundsu_action = QAction("Unlimited rounds", self) roundsu_action.setCheckable(True) roundsu_action.triggered.connect(lambda: self.set_rounds_n(None)) menu.addAction(roundsu_action) roundgroup = QActionGroup(self) roundgroup.addAction(rounds3_action) roundgroup.addAction(rounds5_action) roundgroup.addAction(roundsu_action) roundgroup.setExclusive(True) menu.addSeparator() quit_action = QAction("Quit", self) quit_action.triggered.connect(self.quit) menu.addAction(quit_action) self.deck = [] self.deal_n = 3 # Number of cards to deal each time self.rounds_n = 3 # Number of rounds (restacks) before end. for suit in SUITS: for value in range(1, 14): card = Card(value, suit) self.deck.append(card) self.scene.addItem(card) card.signals.doubleclicked.connect( lambda card=card: self.auto_drop_card(card)) self.setCentralWidget(view) self.setFixedSize(*WINDOW_SIZE) self.deckstack = DeckStack() self.deckstack.setPos(OFFSET_X, OFFSET_Y) self.scene.addItem(self.deckstack) # Set up the working locations. self.works = [] for n in range(7): stack = WorkStack() stack.setPos(OFFSET_X + CARD_SPACING_X * n, WORK_STACK_Y) self.scene.addItem(stack) self.works.append(stack) self.drops = [] # Set up the drop locations. for n in range(4): stack = DropStack() stack.setPos(OFFSET_X + CARD_SPACING_X * (3 + n), OFFSET_Y) stack.signals.complete.connect(self.check_win_condition) self.scene.addItem(stack) self.drops.append(stack) # Add the deal location. self.dealstack = DealStack() self.dealstack.setPos(OFFSET_X + CARD_SPACING_X, OFFSET_Y) self.scene.addItem(self.dealstack) # Add the deal click-trigger. dealtrigger = DealTrigger() dealtrigger.signals.clicked.connect(self.deal) self.scene.addItem(dealtrigger) self.shuffle_and_stack() self.setWindowTitle("Ronery") self.show()