def _set_col_installed(self, col: int, pkg: PackageView): toolbar = QToolBar() toolbar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred) if pkg.model.installed: if pkg.model.can_be_uninstalled(): def uninstall(): self._uninstall_app(pkg) style = 'color: {c}; font-size: 10px; font-weight: bold;'.format( c=BROWN) item = self._gen_row_button( self.i18n['uninstall'].capitalize(), style, uninstall) else: item = QLabel() item.setPixmap((QPixmap(resource.get_path('img/checked.svg')))) item.setAlignment(Qt.AlignCenter) item.setToolTip(self.i18n['installed']) elif pkg.model.can_be_installed(): def install(): self._install_app(pkg) style = 'background: {b}; color: white; font-size: 10px; font-weight: bold'.format( b=GREEN) item = self._gen_row_button(self.i18n['install'].capitalize(), style, install) else: item = None toolbar.addWidget(item) self.setCellWidget(pkg.table_index, col, toolbar)
def _set_col_installed(self, col: int, pkg: PackageView): toolbar = QToolBar() toolbar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred) if pkg.model.installed: if pkg.model.can_be_uninstalled(): def uninstall(): self._uninstall_app(pkg) item = self._gen_row_button( self.i18n['uninstall'].capitalize(), INSTALL_BT_STYLE.format(back='#ff1a1a'), uninstall) else: item = QLabel() item.setPixmap((QPixmap(resource.get_path('img/checked.svg')))) item.setAlignment(Qt.AlignCenter) item.setToolTip(self.i18n['installed']) elif pkg.model.can_be_installed(): def install(): self._install_app(pkg) item = self._gen_row_button( self.i18n['install'].capitalize(), INSTALL_BT_STYLE.format(back='#088A08'), install) else: item = None toolbar.addWidget(item) self.setCellWidget(pkg.table_index, col, toolbar)
def _update_row(self, pkg: PackageView, update_check_enabled: bool = True, change_update_col: bool = True): self._set_col_name(0, pkg) self._set_col_version(1, pkg) self._set_col_description(2, pkg) self._set_col_publisher(3, pkg) self._set_col_type(4, pkg) self._set_col_installed(5, pkg) self._set_col_actions(6, pkg) if change_update_col: col_update = None if update_check_enabled and pkg.model.update: col_update = QToolBar() col_update.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred) col_update.addWidget( UpdateToggleButton(pkg=pkg, root=self.window, i18n=self.i18n, checked=pkg.update_checked if pkg.model.can_be_updated() else False, clickable=pkg.model.can_be_updated())) self.setCellWidget(pkg.table_index, 7, col_update)
def __init__(self, manager: SoftwareManager, i18n: I18n, screen_size: QSize, tray, window: QWidget, parent: QWidget = None): super(SettingsWindow, self).__init__(parent=parent) self.setWindowTitle(i18n['settings'].capitalize()) self.setLayout(QVBoxLayout()) self.manager = manager self.i18n = i18n self.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred) self.tray = tray self.window = window self.settings_model = self.manager.get_settings(screen_size.width(), screen_size.height()) tab_group = to_widget(self.settings_model, i18n) tab_group.setMinimumWidth(int(screen_size.width() / 3)) self.layout().addWidget(tab_group) action_bar = QToolBar() action_bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) bt_close = QPushButton() bt_close.setText(self.i18n['close'].capitalize()) bt_close.clicked.connect(lambda: self.close()) action_bar.addWidget(bt_close) action_bar.addWidget(new_spacer()) bt_change = QPushButton() bt_change.setStyleSheet(css.OK_BUTTON) bt_change.setText(self.i18n['change'].capitalize()) bt_change.clicked.connect(self._save_settings) action_bar.addWidget(bt_change) self.layout().addWidget(action_bar)
def _set_col_installed(self, col: int, pkg: PackageView): toolbar = QToolBar() toolbar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred) if pkg.model.installed: if pkg.model.can_be_uninstalled(): def uninstall(): self._uninstall(pkg) item = self._gen_row_button( self.i18n['uninstall'].capitalize(), self.STYLE_BT_UNINSTALL, uninstall) else: item = None elif pkg.model.can_be_installed(): def install(): self._install_app(pkg) item = self._gen_row_button(self.i18n['install'].capitalize(), self.STYLE_BT_INSTALL, install) else: item = None toolbar.addWidget(item) self.setCellWidget(pkg.table_index, col, toolbar)
def _set_col_settings(self, col: int, pkg: PackageView): item = QToolBar() item.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred) if pkg.model.installed: def run(): self.window.run_app(pkg) bt = IconButton(QIcon(resource.get_path('img/app_play.svg')), i18n=self.i18n, action=run, background='#088A08', tooltip=self.i18n['action.run.tooltip']) bt.setEnabled(pkg.model.can_be_run()) item.addWidget(bt) def get_info(): self.window.get_app_info(pkg) bt = IconButton(QIcon(resource.get_path('img/app_info.svg')), i18n=self.i18n, action=get_info, background='#2E68D3', tooltip=self.i18n['action.info.tooltip']) bt.setEnabled(bool(pkg.model.has_info())) item.addWidget(bt) if not pkg.model.installed: def get_screenshots(): self.window.get_screenshots(pkg) bt = IconButton(QIcon(resource.get_path('img/camera.svg')), i18n=self.i18n, action=get_screenshots, background='#ac00e6', tooltip=self.i18n['action.screenshots.tooltip']) bt.setEnabled(bool(pkg.model.has_screenshots())) item.addWidget(bt) def handle_click(): self.show_pkg_settings(pkg) settings = self.has_any_settings(pkg) if pkg.model.installed: bt = IconButton(QIcon(resource.get_path('img/app_settings.svg')), i18n=self.i18n, action=handle_click, background='#12ABAB', tooltip=self.i18n['action.settings.tooltip']) bt.setEnabled(bool(settings)) item.addWidget(bt) self.setCellWidget(pkg.table_index, col, item)
class ToolBarActionsContainer(QWidget): def __init__(self, parent=None): super().__init__(parent) hLayout = QHBoxLayout(self) self.setLayout(hLayout) self.toolBar = QToolBar() self.toolBar.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Expanding) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) hLayout.addItem( QSpacerItem(40, 0, QSizePolicy.Expanding, QSizePolicy.Maximum)) hLayout.addWidget(self.toolBar)
def _set_col_actions(self, col: int, pkg: PackageView): item = QToolBar() item.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred) if pkg.model.installed: def run(): self.window.begin_launch_package(pkg) bt = IconButton(QIcon(resource.get_path('img/app_play.svg')), i18n=self.i18n, action=run, tooltip=self.i18n['action.run.tooltip']) bt.setEnabled(pkg.model.can_be_run()) item.addWidget(bt) def handle_click(): self.show_pkg_actions(pkg) settings = self.has_any_settings(pkg) if pkg.model.installed: bt = IconButton(QIcon(resource.get_path('img/app_actions.svg')), i18n=self.i18n, action=handle_click, tooltip=self.i18n['action.settings.tooltip']) bt.setEnabled(bool(settings)) item.addWidget(bt) if not pkg.model.installed: def show_screenshots(): self.window.begin_show_screenshots(pkg) bt = IconButton(QIcon(resource.get_path('img/camera.svg')), i18n=self.i18n, action=show_screenshots, tooltip=self.i18n['action.screenshots.tooltip']) bt.setEnabled(bool(pkg.model.has_screenshots())) item.addWidget(bt) def show_info(): self.window.begin_show_info(pkg) bt = IconButton(QIcon(resource.get_path('img/app_info.svg')), i18n=self.i18n, action=show_info, tooltip=self.i18n['action.info.tooltip']) bt.setEnabled(bool(pkg.model.has_info())) item.addWidget(bt) self.setCellWidget(pkg.table_index, col, item)
def add_toolbar(self, title=None, toolbar=None): """Creates, adds and returns a QToolBar """ if 1 != bool(toolbar) + bool(title): raise ValueError('Just one of toolbar or title should be given') if not toolbar: toolbar = QToolBar(title) toolbar.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Maximum) self.addTab(toolbar, toolbar.windowTitle()) # This style applies to QToolButtons that are immediate children # of the toolbar - it does not apply to QToolButtons that are # contained within QWidgets added to toolbar. toolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) toolbar.setMovable(False) toolbar.setFloatable(False) return toolbar
class Ui_MainWindow(object): def setupUi(self, main_window): main_window.setObjectName("mainWindow") main_window.resize(1024, 768) main_window.setMinimumSize(QSize(1024, 768)) main_window.setToolButtonStyle(Qt.ToolButtonIconOnly) self.central_widget = QWidget(main_window) self.central_widget.setObjectName("central_widget") self.horizontalLayout = QHBoxLayout(self.central_widget) self.horizontalLayout.setObjectName("horizontalLayout") self.topDownSplitter = QSplitter(self.central_widget) self.topDownSplitter.setOrientation(Qt.Vertical) self.topDownSplitter.setOpaqueResize(True) self.topDownSplitter.setHandleWidth(5) self.topDownSplitter.setObjectName("topDownSplitter") self.leftRightSplitter = QSplitter(self.topDownSplitter) self.leftRightSplitter.setOrientation(Qt.Horizontal) self.leftRightSplitter.setObjectName("leftRightSplitter") self.leftPanel = QFrame(self.leftRightSplitter) sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.leftPanel.sizePolicy().hasHeightForWidth()) self.leftPanel.setSizePolicy(sizePolicy) self.leftPanel.setMinimumSize(QSize(245, 550)) self.leftPanel.setMaximumSize(QSize(245, 16777215)) self.leftPanel.setFrameShape(QFrame.StyledPanel) self.leftPanel.setFrameShadow(QFrame.Raised) self.leftPanel.setObjectName("leftPanel") self.leftPanelVLayout = QVBoxLayout(self.leftPanel) self.leftPanelVLayout.setObjectName("leftPanelVLayout") self.colorPickerFrame = QFrame(self.leftPanel) self.colorPickerFrame.setMinimumSize(QSize(0, 0)) self.colorPickerFrame.setMaximumSize(QSize(16777215, 16777215)) self.colorPickerFrame.setFrameShape(QFrame.StyledPanel) self.colorPickerFrame.setFrameShadow(QFrame.Raised) self.colorPickerFrame.setObjectName("colorPickerFrame") self.leftPanelVLayout.addWidget(self.colorPickerFrame) self.leftPanelVLayout.setStretch(0, 5) self.mainPanel = QFrame(self.leftRightSplitter) sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(1) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.mainPanel.sizePolicy().hasHeightForWidth()) self.mainPanel.setSizePolicy(sizePolicy) self.mainPanel.setMinimumSize(QSize(320, 240)) self.mainPanel.setAutoFillBackground(False) self.mainPanel.setFrameShape(QFrame.StyledPanel) self.mainPanel.setFrameShadow(QFrame.Raised) self.mainPanel.setObjectName("mainPanel") self.verticalLayout = QVBoxLayout(self.mainPanel) self.verticalLayout.setObjectName("verticalLayout") self.canvasFrame = QFrame(self.mainPanel) sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.canvasFrame.sizePolicy().hasHeightForWidth()) self.canvasFrame.setSizePolicy(sizePolicy) self.canvasFrame.setMinimumSize(310, 230) self.canvasFrame.setFrameShape(QFrame.StyledPanel) self.canvasFrame.setFrameShadow(QFrame.Raised) self.canvasFrame.setObjectName("canvasFrame") self.verticalLayout.addWidget(self.canvasFrame) self.verticalLayout.setStretch(0, 12) self.rightPanel = QFrame(self.leftRightSplitter) sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.rightPanel.sizePolicy().hasHeightForWidth()) self.rightPanel.setSizePolicy(sizePolicy) self.rightPanel.setMinimumSize(QSize(245, 550)) self.rightPanel.setMaximumSize(QSize(340, 16777215)) self.rightPanel.setFrameShape(QFrame.StyledPanel) self.rightPanel.setFrameShadow(QFrame.Raised) self.rightPanel.setObjectName("rightPanel") self.rightPanelLayout = QVBoxLayout(self.rightPanel) self.rightPanelLayout.setObjectName("rightPanelLayout") self.previewFrame = QFrame(self.rightPanel) self.previewFrame.setMaximumSize(320, 500) self.previewFrame.setFrameShape(QFrame.StyledPanel) self.previewFrame.setFrameShadow(QFrame.Raised) self.previewFrame.setObjectName("previewFrame") self.rightPanelLayout.addWidget(self.previewFrame) self.layerListFrame = QFrame(self.rightPanel) self.layerListFrame.setFrameShape(QFrame.StyledPanel) self.layerListFrame.setFrameShadow(QFrame.Raised) self.layerListFrame.setObjectName("layerListFrame") self.rightPanelLayout.addWidget(self.layerListFrame) self.animationBarFrame = QFrame(self.topDownSplitter) sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.animationBarFrame.sizePolicy().hasHeightForWidth()) self.animationBarFrame.setSizePolicy(sizePolicy) self.animationBarFrame.setMinimumSize(QSize(600, 100)) self.animationBarFrame.setMaximumSize(QSize(16777215, 100)) self.animationBarFrame.setFrameShape(QFrame.StyledPanel) self.animationBarFrame.setFrameShadow(QFrame.Raised) self.animationBarFrame.setObjectName("animationBarFrame") self.horizontalLayout.addWidget(self.topDownSplitter) main_window.setCentralWidget(self.central_widget) self.toolBar = QToolBar(main_window) sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.toolBar.sizePolicy().hasHeightForWidth()) self.toolBar.setSizePolicy(sizePolicy) self.toolBar.setMovable(False) self.toolBar.setFloatable(False) self.toolBar.setObjectName("toolBar") main_window.addToolBar(Qt.TopToolBarArea, self.toolBar) self.actionNew = QAction(main_window) self.actionNew.setObjectName("actionNew") self.actionQuit = QAction(main_window) self.actionQuit.setObjectName("actionQuit") self.actionOpen = QAction(main_window) self.actionOpen.setObjectName("actionOpen") self.actionSave = QAction(main_window) self.actionSave.setObjectName("actionSave") self.actionSaveAs = QAction(main_window) self.actionSaveAs.setObjectName("actionSaveAs") self.actionClose = QAction(main_window) self.actionClose.setObjectName("actionClose") self.actionExport = QAction(main_window) self.actionExport.setObjectName("actionExport") self.actionImport = QAction(main_window) self.actionImport.setObjectName("actionImport") self.toolBar.addAction(self.actionNew) self.toolBar.addAction(self.actionOpen) self.toolBar.addAction(self.actionImport) self.toolBar.addAction(self.actionSave) self.toolBar.addAction(self.actionSaveAs) self.toolBar.addAction(self.actionExport) self.toolBar.addAction(self.actionClose) self.toolBar.addAction(self.actionQuit) self.retranslateUi(main_window) QMetaObject.connectSlotsByName(main_window) def retranslateUi(self, main_window): _translate = QCoreApplication.translate main_window.setWindowTitle(_translate("MainWindow", "SpriteMator")) self.toolBar.setWindowTitle(_translate("MainWindow", "toolBar")) self.actionNew.setText(_translate("MainWindow", "New")) self.actionNew.setIconText(_translate("MainWindow", "New")) self.actionNew.setToolTip(_translate("MainWindow", "New Sprite")) self.actionNew.setShortcut(_translate("MainWindow", "Ctrl+N")) self.actionQuit.setText(_translate("MainWindow", "Quit")) self.actionQuit.setToolTip( _translate("MainWindow", "Close Application")) self.actionQuit.setShortcut(_translate("MainWindow", "Esc")) self.actionOpen.setText(_translate("MainWindow", "Open")) self.actionOpen.setToolTip(_translate("MainWindow", "Open Sprite")) self.actionOpen.setShortcut(_translate("MainWindow", "Ctrl+O")) self.actionSave.setText(_translate("MainWindow", "Save")) self.actionSave.setToolTip(_translate("MainWindow", "Save Sprite")) self.actionSave.setShortcut(_translate("MainWindow", "Ctrl+S")) self.actionSaveAs.setText(_translate("MainWindow", "SaveAs")) self.actionSaveAs.setToolTip( _translate("MainWindow", "Save Sprite with another name")) self.actionSaveAs.setShortcut(_translate("MainWindow", "Ctrl+Shift+S")) self.actionClose.setText(_translate("MainWindow", "Close")) self.actionClose.setToolTip(_translate("MainWindow", "Close Sprite")) self.actionClose.setShortcut(_translate("MainWindow", "Ctrl+Q")) self.actionExport.setText(_translate("MainWindow", "Export")) self.actionExport.setToolTip( _translate( "MainWindow", "Export Sprite animations : Either as separate images or as a spritesheet" )) self.actionExport.setShortcut(_translate("MainWindow", "Ctrl+E")) self.actionImport.setText(_translate("MainWindow", "Import")) self.actionImport.setToolTip( _translate("MainWindow", "Create a Sprite from one or more images")) self.actionImport.setShortcut(_translate("MainWindow", "Ctrl+I"))
class QuickPanel(QWidget, WidgetManager): """ 一个快捷面板。类似于KDE的桌面。只不过功能会简单些。主要的方法有: addQuickAccessShortcut() 供插件添加一个系统快捷方式。 removeQuickAccessShortcut() 删除插件添加的系统快捷方式。 toggle() 如果快捷面板已经显示就隐藏它。如果处于隐藏状态则显示它。 showAndGetFocus() 显示快捷面板并且将焦点放置于常用的位置。 registerWidget() 注册部件 unregisterWidget() 反注册部件 """ def __init__(self, platform): QWidget.__init__(self, None, Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint) self.setWindowModality(Qt.ApplicationModal) self.platform = platform self.db = QuickPanelDatabase(platform.databaseFile) self.createActions() self.createControls() self.loadSettings() self.makeConnections() #Besteam系统快捷方式作为QuickPanel提供的一个服务,必须定义在这里 #虽然部件可能没有运行。QuickPanel也应该记住其它插件添加的快捷方式,以便在 #用户添加QuickAccessWidget之后,可以显示所有的系统快捷方式 self.quickAccessModel = QuickAccessModel() def createActions(self): self.actionChangeBackground = QAction(self) self.actionChangeBackground.setIcon(QIcon(":/images/change_background.png")) self.actionChangeBackground.setText(self.tr("Change &Background")) self.actionChangeBackground.setIconText(self.tr("Background")) self.actionChangeBackground.setToolTip(self.tr("Change Background")) self.actionClose = QAction(self) self.actionClose.setIcon(QIcon(":/images/close.png")) self.actionClose.setText(self.tr("&Close")) self.actionClose.setIconText(self.tr("Close")) self.actionClose.setToolTip(self.tr("Close")) self.actionChangeLayout = QAction(self) self.actionChangeLayout.setIcon(QIcon(":/images/change_layout.png")) self.actionChangeLayout.setText(self.tr("Change &Layout")) self.actionChangeLayout.setIconText(self.tr("Layout")) self.actionChangeLayout.setToolTip(self.tr("Change Layout")) self.actionChangeLayout.setCheckable(True) self.actionSelectWidgets = QAction(self) self.actionSelectWidgets.setIcon(QIcon(":/images/select_widgets.png")) self.actionSelectWidgets.setText(self.tr("&Select Widgets")) self.actionSelectWidgets.setIconText(self.tr("Widgets")) self.actionSelectWidgets.setToolTip(self.tr("Select Widgets")) self.actionResetBackground = QAction(self) self.actionResetBackground.setIcon(QIcon(":/images/reset.png")) self.actionResetBackground.setText(self.tr("&Reset Background")) self.actionResetBackground.setIconText(self.tr("Reset")) self.actionResetBackground.setToolTip(self.tr("Reset Background")) self.actionResetDefaultLayout = QAction(self) self.actionResetDefaultLayout.setIcon(QIcon(":/images/reset.png")) self.actionResetDefaultLayout.setText(self.tr("Reset &Layout")) self.actionResetDefaultLayout.setIconText(self.tr("Reset")) self.actionResetDefaultLayout.setToolTip(self.tr("Reset Layout")) def createControls(self): self.toolBarMain = QToolBar(self) self.toolBarMain.addAction(self.actionChangeBackground) self.toolBarMain.addAction(self.actionResetBackground) self.toolBarMain.addAction(self.actionChangeLayout) self.toolBarMain.addAction(self.actionClose) self.toolBarMain.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) self.toolBarMain.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.toolBarLayout = QToolBar(self) self.toolBarLayout.addAction(self.actionSelectWidgets) self.toolBarLayout.addAction(self.actionResetDefaultLayout) self.toolBarLayout.addAction(self.actionChangeLayout) self.toolBarLayout.addAction(self.actionClose) self.toolBarLayout.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) self.toolBarLayout.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.canvas = Canvas(self) self.layoutEditor = LayoutEditor(self) self.lblTitle = QLabel(self) self.lblTitle.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) self.setLayout(QVBoxLayout()) self.layoutTop = QHBoxLayout() self.layoutTop.addWidget(self.lblTitle) self.layoutTop.addWidget(self.toolBarMain) self.layoutTop.addWidget(self.toolBarLayout) self.toolBarLayout.hide() self.layout().addLayout(self.layoutTop) self.layout().addWidget(self.canvas) self.layout().addWidget(self.layoutEditor) self.layoutEditor.hide() def loadSettings(self): settings = self.platform.getSettings() filepath = settings.value("background", "background.png") if not os.path.exists(filepath): filepath = os.path.join(os.path.dirname(__file__), filepath) if not os.path.exists(filepath): return image = QImage(filepath) self._makeBackground(image) def makeConnections(self): self.actionClose.triggered.connect(self.close) self.actionChangeLayout.triggered.connect(self.toggleLayoutEditor) self.actionChangeBackground.triggered.connect(self.changeBackground) self.actionResetBackground.triggered.connect(self.useDefaultBackground) self.actionSelectWidgets.triggered.connect(self.selectWidgets) self.actionResetDefaultLayout.triggered.connect(self.resetDefaultLayout) QApplication.instance().focusChanged.connect(self.onWindowFocusChanged) def paintEvent(self, event): painter = QPainter(self) painter.drawImage(event.rect(), self._background_image, event.rect()) def keyPressEvent(self, event): QWidget.keyPressEvent(self, event) if not event.isAccepted() and event.key() == Qt.Key_Escape: if self.layoutEditor.isVisible(): self.leaveLayoutEditor() self.actionChangeLayout.setChecked(False) else: self.close() def onWindowFocusChanged(self, old, new): "实现类似于Qt.Popup那样点击其它窗口就立即关闭本窗口的效果。" if self.isVisible() and not self.isActiveWindow(): self.close() def showEvent(self, event): settings = self.platform.getSettings() key = settings.value("globalkey", "Alt+`") if key is not None: if os.name == "nt": #在Windows系统下,Meta键习惯叫Win键 key = key.replace("Meta", "Win") title = self.tr("提示:在任何位置按<b>{0}</b>打开快捷面板。").format(key) self.lblTitle.setText('<span style=" font-size:14pt;font-style:italic;">{0}</span>'.format(title)) else: title = self.tr("快捷面板") self.lblTitle.setText('<span style=" font-size:14pt;font-style:italic;">{0}</span>'.format(title)) #如果有时候运行全屏程序,快捷面板的位置就会发生改变 self._makeBackground(self._background_image) moveToCenter(self) self.canvas.positWidgets() QWidget.showEvent(self, event) def showAndGetFocus(self): if not self.isVisible(): self.show() if self.windowState() & Qt.WindowMinimized: self.setWindowState(self.windowState() ^ Qt.WindowMinimized) self.raise_() if os.name == "nt": ctypes.windll.user32.BringWindowToTop(int(self.winId())) ctypes.windll.user32.SwitchToThisWindow(int(self.winId()), 1) self.activateWindow() def toggle(self): if self.isVisible(): self.hide() else: self.showAndGetFocus() def addQuickAccessShortcut(self, name, icon, callback): """ 添加一个快捷方式。有一个widget专门用于显示Besteam内部各种工具的快捷方式。 name 快捷方式的名字 icon 快捷方式的图标 callback 当用户点击快捷方式的时候调用的回调函数。不会传入任何参数。 """ self.quickAccessModel.addShortcut(name, icon, callback) def removeQuickAccessShortcut(self, name): """删除一个系统快捷方式。参数name是快捷方式的名字。""" self.quickAccessModel.removeShortcut(name) def enterLayoutEditor(self): self.layoutEditor.show() self.canvas.hide() self.toolBarLayout.show() self.toolBarMain.hide() self.layoutEditor.beginEdit(self.widgets) def leaveLayoutEditor(self): self.layoutEditor.hide() self.canvas.show() self.toolBarLayout.hide() self.toolBarMain.show() changedWidgets = self.layoutEditor.saveLayout(self.widgets) for widget in changedWidgets: conf = {} conf["left"] = widget.rect.left() conf["top"] = widget.rect.top() conf["width"] = widget.rect.width() conf["height"] = widget.rect.height() conf["enabled"] = widget.enabled conf["id"] = widget.id self.db.saveWidgetConfig(conf) if widget.enabled: self._enableWidget(widget, False) else: self._disableWidget(widget, False) self.canvas.positWidgets(True) self.layoutEditor.endEdit() def toggleLayoutEditor(self, checked): if checked: self.enterLayoutEditor() else: self.leaveLayoutEditor() def changeBackground(self): filename, selectedFilter = QFileDialog.getOpenFileName(self, self.tr("Change Background"), \ QStandardPaths.writableLocation(QStandardPaths.PicturesLocation), \ self.tr("Image Files (*.png *.gif *.jpg *.jpeg *.bmp *.mng *ico)")) if not filename: return image = QImage(filename) if image.isNull(): QMessageBox.information(self, self.tr("Change Background"), \ self.tr("不能读取图像文件,请检查文件格式是否正确,或者图片是否已经损坏。")) return if image.width() < 800 or image.height() < 600: answer = QMessageBox.information(self, self.tr("Change Background"), \ self.tr("不建议设置小于800x600的图片作为背景图案。如果继续,可能会使快捷面板显示错乱。是否继续?"), QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if answer == QMessageBox.No: return self._makeBackground(image) moveToCenter(self) self.canvas.positWidgets() self.update() with self.platform.getSettings() as settings: settings.setValue("background", filename) def useDefaultBackground(self): filename = "background.png" if not os.path.exists(filename): filename = os.path.join(os.path.dirname(__file__), filename) if os.path.exists(filename): image = QImage(filename) if not image.isNull(): self._makeBackground(image) moveToCenter(self) self.canvas.positWidgets() self.update() settings = self.platform.getSettings() settings.remove("background") def _makeBackground(self, image): desktopSize = QApplication.desktop().screenGeometry(self).size() if desktopSize.width() < image.width() or desktopSize.height() < image.height(): self._background_image = image.scaled(desktopSize, Qt.KeepAspectRatio, Qt.SmoothTransformation) else: self._background_image = image self.resize(self._background_image.size()) def runDialog(self, *args, **kwargs): """ 在QuickPanel中显示一个对话框。主要是为了避免对话框显示的时候,快捷面板会隐藏。 接受两种形式的参数,其中d是对话框: runDialog(d, d.exec_) runDialog(d.exec_, *args, **kwargs) 建议使用第二种 """ if isinstance(args[0], QDialog): return self._runDialog2(args[0], args[1]) else: callback, args = args[0], args[1:] return self._runDialog3(callback, args, kwargs) def _runDialog2(self, d, callback): return self._runDialog(d, self.canvas, callback) def _runDialog3(self, callback, args, kwargs): d = callback.__self__ f = functools.partial(callback, *args, **kwargs) return self._runDialog(d, self.canvas, f) def _runDialog(self, d, container, callback): shutter = ShutterWidget(container) newPaintEvent = functools.partial(self._dialog_paintEvent, d) oldPaintEvent = d.paintEvent d.paintEvent = newPaintEvent r = d.geometry() r.moveCenter(container.rect().center()) d.setGeometry(r) d.setWindowFlags(Qt.Widget) d.setParent(container) d.setFocus(Qt.OtherFocusReason) try: shutter.show() d.raise_() return callback() finally: d.paintEvent = oldPaintEvent shutter.close() shutter.setParent(None) def _dialog_paintEvent(self, d, event): QDialog.paintEvent(d, event) pen = QPen() pen.setWidth(2) pen.setColor(QColor(200, 200, 200)) rect = d.rect() rect = rect.adjusted(0, 0, -1, -1) painter = QPainter(d) painter.setRenderHint(QPainter.Antialiasing, True) painter.setPen(pen) painter.setOpacity(0.8) painter.setBrush(QBrush(QColor(Qt.white))) painter.drawRoundedRect(rect, 15, 15)
class kstImageViewer(QWidget): def __init__(self, sourceFile, data, type, image, mode): """ Class constructor. """ QWidget.__init__(self) # Initialize image panel: self.imagePanel = _kstImagePanel() # Set original mode: self.__originalMode = mode # Set the type of image with respect of the lightfield pipeline: self.__imageType = type # 'raw', 'pre-processed', 'reconstructed', 'post-processed' # The actual object handled by the image viewer: self.__data = data # Properties: self.__sourceFile = sourceFile # Current view index: self.__view = 0 # Top toolbar: self.topToolBar = QToolBar() self._createTopToolbar() # Bottom toolbar: self.bottomToolBar = QToolBar() self._createBottomToolbar() # Handle mouse hover with custom slot: self.imagePanel.mouseHoverEvent.connect(self._handleMouseHover) # Compose layout of the whole widget: layout = QVBoxLayout() layout.addWidget(self.topToolBar) layout.addWidget(self.imagePanel) layout.addWidget(self.bottomToolBar) layout.setContentsMargins(0,0,0,0) self.setLayout(layout) self.setContentsMargins(0,0,0,0) # Set image: self.__setImage(image) def _createTopToolbar(self): """ """ topToolbarSizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) self.topToolBar.setSizePolicy(topToolbarSizePolicy) #pan_zoom = QAction(QIcon(dir + "/resources/btnDrag.png"),"Pan (Mouse #Left)",self) #self.toolBar.addAction(pan_zoom) #zoomSelect = QAction(QIcon(dir + "/resources/btnZoomSelect.png"),"ROI Zoom #(Mouse Left)",self) #self.toolBar.addAction(zoomSelect) exitAct = QAction('Exit', self) exitAct.setShortcut('Ctrl+Q') self._panZoom = QToolButton(self) self._panZoom.setIcon(QIcon(PAN_ZOOM_ICON)) self._panZoom.setToolTip(PAN_ZOOM_TOOLTIP) self._panZoom.setCheckable(True) self._panZoom.setChecked(True) self._panZoom.clicked.connect(self._panZoomSwitch) self.topToolBar.addWidget(self._panZoom) self._zoomSelect = QToolButton(self) self._zoomSelect.setIcon(QIcon(ZOOM_SELECT_ICON)) self._zoomSelect.setToolTip(ZOOM_SELECT_TOOLTIP) self._zoomSelect.setCheckable(True) self._zoomSelect.setChecked(False) self._zoomSelect.clicked.connect(self._zoomSelectSwitch) self.topToolBar.addWidget(self._zoomSelect) self.topToolBar.addSeparator() zoomIn = QAction(QIcon(ZOOM_IN_ICON),ZOOM_IN_TOOLTIP,self) self.topToolBar.addAction(zoomIn) zoomOut = QAction(QIcon(ZOOM_OUT_ICON),ZOOM_OUT_TOOLTIP,self) self.topToolBar.addAction(zoomOut) zoomReset = QAction(QIcon(ZOOM_RESET_ICON),ZOOM_RESET_TOOLTIP,self) self.topToolBar.addAction(zoomReset) self.topToolBar.addSeparator() # Separator: #self.fooWidget = QWidget() #self.fooWidget.setFixedWidth(6) #self.fooWidgetAction = self.topToolBar.addWidget(self.fooWidget) #self.extraSeparatorAction = self.topToolBar.addSeparator() export = QAction(QIcon(EXPORT_ICON),EXPORT_TOOLTIP,self) self.topToolBar.addAction(export) exportAll = QAction(QIcon(EXPORTALL_ICON),EXPORTALL_TOOLTIP,self) self.topToolBar.addAction(exportAll) # Spacer: spacer = QWidget() spacerSizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum) spacer.setSizePolicy(spacerSizePolicy) self.topToolBar.addWidget(spacer) # Label on the right: self.hoverLabel = QLabel(self) self.hoverLabel.setText("") self.topToolBar.addWidget(self.hoverLabel) # Connect handler for toolbar buttons: self.topToolBar.actionTriggered[QAction].connect(self._toolBarBtnPressed) def _createBottomToolbar(self): """ """ bottomToolbarSizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) self.bottomToolBar.setSizePolicy(bottomToolbarSizePolicy) # Combo box for the 4 "views" of a dataset: self.lblView = QLabel(" View: ") # Use spaces self.lblViewAction = self.bottomToolBar.addWidget(self.lblView) self.cbxView = QComboBox() self.cbxView.addItems(["Projection/Axial", "Sinogram/Sagittal", "Lateral/Frontal"]) self.cbxView.currentIndexChanged.connect(self.changeView) self.cbxViewAction = self.bottomToolBar.addWidget(self.cbxView) self.indexLabel = QLabel(self) self.indexLabel.setText("") self.indexLabel.setFixedWidth(70) self.indexLabel.setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.bottomToolBar.addWidget(self.indexLabel) # Slider for the projection/slices: self.lblImageSlider = QLabel(" Image: ") # Use spaces self.lblImageSliderAction = self.bottomToolBar.addWidget(self.lblImageSlider) self.sldDataset = QSlider(Qt.Horizontal) self.sldDataset.setFixedWidth(250) self.sldDataset.setFocusPolicy(Qt.StrongFocus) self.sldDataset.setTickPosition(QSlider.TicksBelow) self.sldDataset.valueChanged.connect(self.changeDatasetView) self.sldDatasetAction = self.bottomToolBar.addWidget(self.sldDataset) # Slider for the repetitions: self.lblRepetitionIndex = QLabel(self) self.lblRepetitionIndex.setText("") self.lblRepetitionIndex.setFixedWidth(50) self.lblRepetitionIndex.setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.bottomToolBar.addWidget(self.lblRepetitionIndex) self.lblRepetitionSlider = QLabel(" Repetition: ") # Use spaces self.lblRepetitionSlider.setFixedWidth(80) self.lblRepetitionSlider.setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.lblRepetitionSliderAction = self.bottomToolBar.addWidget(self.lblRepetitionSlider) self.sldRepetition = QSlider(Qt.Horizontal) self.sldRepetition.setFixedWidth(150) self.sldRepetition.setFocusPolicy(Qt.StrongFocus) self.sldRepetition.setTickPosition(QSlider.TicksBelow) self.sldRepetition.valueChanged.connect(self.changeRepetitionView) self.sldRepetitionAction = self.bottomToolBar.addWidget(self.sldRepetition) if self.__data.ndim == 4: self.lblRepetitionSliderAction.setVisible(True) self.sldRepetitionAction.setVisible(True) else: self.lblRepetitionSliderAction.setVisible(False) self.sldRepetitionAction.setVisible(False) #def drawBackground(self, painter, rect): # color = self.palette().color(QPalette.Background) # background_brush = QBrush( color, Qt.SolidPattern) # painter.fillRect(rect, background_brush) def _panZoomSwitch(self): self._zoomSelect.setChecked(not self._panZoom.isChecked()) self.imagePanel.togglePanZoom = self._zoomSelect.isChecked() def _zoomSelectSwitch(self): self._panZoom.setChecked(not self._zoomSelect.isChecked()) self.imagePanel.togglePanZoom = self._zoomSelect.isChecked() def _toolBarBtnPressed(self, button): if button.text() == ZOOM_IN_TOOLTIP: self.imagePanel.performZoom(min(400.0,self.imagePanel.zoomFactor*1.15)) elif button.text() == ZOOM_OUT_TOOLTIP: self.imagePanel.performZoom(max(1.0,self.imagePanel.zoomFactor/1.15)) elif button.text() == ZOOM_RESET_TOOLTIP: self.imagePanel.performZoom(1.0) elif button.text() == EXPORT_TOOLTIP: # Open a Save As dialog: try: options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog filename, _ = QFileDialog.getSaveFileName(self,"Save as TIFF", "","TIFF Files (*.tif);;All Files (*)", options=options) if filename: # Call the method to save the current displayed image: self.imagePanel.saveAsTIFF(filename) except Exception as e: eprint(str(e)) elif button.text() == EXPORTALL_TOOLTIP: # Open a Save As dialog: try: options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog options |= QFileDialog.DirectoryOnly folder = QFileDialog.getExistingDirectory(self, "Select Folder for TIFF sequence") if folder: for i in range(0,self.__data.shape[2]): # Prepare filename: filename = os.path.join(folder, "image_" + "{:04d}".format(i) + ".tif") # Save as TIFF with tiffile library: tifffile.imsave(filename, data=self.__data[:,:,i]) except Exception as e: eprint(str(e)) def _handleMouseHover(self, x, y, z, type): if (x == -1): self.hoverLabel.setText("") else: if (type == 'float'): s = "{:0.4f}".format(z) if (z > 1e-2) else "{:.4E}".format(z) else: s = "{:d}".format(round(z)) self.hoverLabel.setText("[" + str(x) + "," + str(y) + "]=" + s + " " ) def __setImage(self, npImage): """ Set the scene's current image pixmap to the input image as a numpy array. :type npImage: numpy array """ # Set the new numpy image: self.imagePanel.setImage(npImage) # Enable/disable UI widgets: if (self.__imageType == 'raw'): self.lblViewAction.setVisible(True) self.cbxViewAction.setVisible(True) self.lblImageSliderAction.setVisible(True) self.sldDatasetAction.setVisible(True) if self.__data.ndim == 4: self.lblRepetitionSliderAction.setVisible(True) self.lblRepetitionIndex.setVisible(True) self.sldRepetitionAction.setVisible(True) else: self.lblRepetitionSliderAction.setVisible(False) self.lblRepetitionIndex.setVisible(False) self.sldRepetitionAction.setVisible(False) elif (self.__imageType == 'pre-processed'): self.lblViewAction.setVisible(True) self.cbxViewAction.setVisible(True) self.lblImageSliderAction.setVisible(True) self.sldDatasetAction.setVisible(True) self.sldRepetitionAction.setVisible(False) self.lblRepetitionIndex.setVisible(False) self.lblRepetitionSliderAction.setVisible(False) elif (self.__imageType == 'reconstructed'): self.lblViewAction.setVisible(True) self.cbxViewAction.setVisible(True) self.lblImageSliderAction.setVisible(True) self.sldDatasetAction.setVisible(True) self.sldRepetitionAction.setVisible(False) self.lblRepetitionIndex.setVisible(False) self.lblRepetitionSliderAction.setVisible(False) # Set dimension of the slider and default: self.sldDataset.setMinimum(0) self.sldDataset.setMaximum(self.__data.shape[2]-1) self.sldDataset.setValue(round(self.__data.shape[2]/2)) self.indexLabel.setText(str(round(self.__data.shape[2]/2)) \ + "/" + str(round(self.__data.shape[2]))) def changeView(self, idx): """ Called when the combo box index is changed. """ # Reset sliders: self.sldDataset.setValue(0) if self.__data.ndim == 4: self.sldRepetition.setValue(0) # Transpose datasets: if idx == 0: # Axial or projection view: if self.__data.ndim == 4: if self.__view == 1: self.__data = numpy.transpose(self.__data, (2,1,0,3)) # OK if self.__view == 2: self.__data = numpy.transpose(self.__data, (1,2,0,3)) # OK else: if self.__view == 1: self.__data = numpy.transpose(self.__data, (2,1,0)) # OK if self.__view == 2: self.__data = numpy.transpose(self.__data, (1,2,0)) # OK elif idx == 1: # Sinogram of sagittal view: if self.__data.ndim == 4: if self.__view == 0: self.__data = numpy.transpose(self.__data, (2,1,0,3)) # OK if self.__view == 2: self.__data = numpy.transpose(self.__data, (0,2,1,3)) # OK else: if self.__view == 0: self.__data = numpy.transpose(self.__data, (2,1,0)) # OK if self.__view == 2: self.__data = numpy.transpose(self.__data, (0,2,1)) # OK else: # Lateral or coronal view: if self.__data.ndim == 4: if self.__view == 0: self.__data = numpy.transpose(self.__data, (2,0,1,3)) # OK if self.__view == 1: self.__data = numpy.transpose(self.__data, (0,2,1,3)) # OK else: if self.__view == 0: self.__data = numpy.transpose(self.__data, (2,0,1)) # OK if self.__view == 1: self.__data = numpy.transpose(self.__data, (0,2,1)) # OK # Set new view: self.__view = idx # Change to the new numpy image: if self.__data.ndim == 4: self.imagePanel.changeImage(self.__data[:,:,round(self.__data.shape[2]/2),round(self.__data.shape[3]/2)]) else: self.imagePanel.changeImage(self.__data[:,:,round(self.__data.shape[2]/2)]) # Set the index: self.sldDataset.setMinimum(0) self.sldDataset.setMaximum(self.__data.shape[2]-1) self.sldDataset.setValue(round(self.__data.shape[2]/2)) # Reset zoom: self.imagePanel.performZoom(1.0) def changeDatasetView(self): """ Called when the slider is moved, so user wants to see a different projection or slice. """ val = int(self.sldDataset.value()) # Change to the new numpy image: if self.__data.ndim == 4: rep = int(self.sldRepetition.value()) self.imagePanel.changeImage(self.__data[:,:,val,rep]) #self.sldRepetition.setValue(round(self.__data.shape[3]/2)) else: self.imagePanel.changeImage(self.__data[:,:,val]) # Set the index: self.indexLabel.setText(str(val + 1) + "/" + str(round(self.__data.shape[2]))) def changeRepetitionView(self): """ Called when the slider is moved, so user wants to see a different repetition of the same projection. """ img = int(self.sldDataset.value()) val = int(self.sldRepetition.value()) # Change to the new numpy image: self.imagePanel.changeImage(self.__data[:,:,img,val]) # Set the index: self.lblRepetitionIndex.setText(str(val+1) + "/" + str(round(self.__data.shape[3]))) def getType(self): """ Get the type of current image viewer. """ # Set the new numpy image: return self.__imageType def getOriginalMode(self): """ Get the original mode (2COL or 1COL). """ # Set the new numpy image: return self.__originalMode def getSourceFile(self): """ Get the source file of current image viewer. """ # Set the new numpy image: return self.__sourceFile def getImage(self): """ Get the scene's current image pixmap as a numpy array. """ # Set the new numpy image: return self.imagePanel.npImage def getData(self): """ Get the data connected to this image viewer. """ return self.__data