def __init__(self, previewImage, fileName): super(ImageView, self).__init__() self.fileName = fileName mainLayout = QVBoxLayout(self) self.imageLabel = QLabel() self.imageLabel.setPixmap(QPixmap.fromImage(previewImage)) mainLayout.addWidget(self.imageLabel) topLayout = QHBoxLayout() self.fileNameLabel = QLabel(QDir.toNativeSeparators(fileName)) self.fileNameLabel.setTextInteractionFlags(Qt.TextBrowserInteraction) topLayout.addWidget(self.fileNameLabel) topLayout.addStretch() copyButton = QPushButton("Copy") copyButton.setToolTip("Copy file name to clipboard") topLayout.addWidget(copyButton) copyButton.clicked.connect(self.copy) launchButton = QPushButton("Launch") launchButton.setToolTip("Launch image viewer") topLayout.addWidget(launchButton) launchButton.clicked.connect(self.launch) mainLayout.addLayout(topLayout)
def __init__(self,parent = None): QLabel.__init__(self, parent) self.headers = [] self.position = 0 self.viewWidth = 800 self.viewHeight = 100 self.hideFlag = False self.w = 180 self.h = 40 self.t = 10 self.setMouseTracking(True) self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) self.customContextMenuRequested.connect(self.createHeaderMenus) self.deleteAct = QAction('Hide', self) self.deleteAct.setStatusTip('Hide this life-line') self.deleteAct.triggered.connect(self.hideLifeLine) self.groupAct = QAction('Make a cluster', self) self.groupAct.setStatusTip('Make a cluster of multiple life-lines') self.groupAct.triggered.connect(self.showClusterDialog) self.scatterAct = QAction('Scatter', self) self.scatterAct.setStatusTip('Scatter this cluster') self.scatterAct.triggered.connect(self.scatterCluster)
def testReference(self): l = QLabel() p = QPixmap() l.setPixmap(p) # doesn't increment pixmap ref because this makes a copy self.assertEqual(sys.getrefcount(p), 2) p = l.pixmap() # this increment the reference because this is an internal pointer self.assertEqual(sys.getrefcount(p), 3) p2 = l.pixmap() self.assertEqual(p, p2)
class ClusterDialog(QDialog): editClusterName = None def __init__(self, lifeline, defaultName, parent = None): super(ClusterDialog, self).__init__(parent) self.lifeline = lifeline layout = QVBoxLayout(self) message = QLabel('Enter group name') layout.addWidget(message) self.editClusterName = QLineEdit(defaultName) self.editClusterName.setFixedHeight(30) self.editClusterName.setFixedWidth(400) self.editClusterName.textChanged.connect(self.validateCluster) layout.addWidget(self.editClusterName) self.validation_msg = QLabel(' ') layout.addWidget(self.validation_msg) buttons = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, QtCore.Qt.Horizontal, self) buttons.accepted.connect(self.accept) buttons.rejected.connect(self.reject) layout.addWidget(buttons) self.validateCluster() def validateCluster(self): cnt = 0 for l in self.lifeline: if self.editClusterName.text() in l.getClassName() and not l.getFlagCluster() and not l.getClusterLifeline(): cnt += 1 available_flag = True for l in self.lifeline: if self.editClusterName.text() in l.getClassName() and l.getFlagCluster(): available_flag = False break if available_flag: self.validation_msg.setText("group name includes %d life-lines" % (cnt)) else: self.validation_msg.setText("group name is not available") def getClusterText(self): return self.editClusterName.text() @staticmethod def getClusterName(lifelines, defaultName, parent = None): dialog = ClusterDialog(lifelines,defaultName,parent) result = dialog.exec_() return (result, dialog.getClusterText())
def __init__(self, parentQExampleScrollArea, parentQWidget = None): QLabel.__init__(self, parentQWidget) self.parentQExampleScrollArea = parentQExampleScrollArea self.scale = 1.0 self.position = (0, 0) self.pressed = None self.anchor = None self.drawer = CaptainServer.CaptainServer(self) self.drawer.initUI() self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) self.customContextMenuRequested.connect(self.drawer.createMenus)
def paintEvent(self, event): QLabel.paintEvent(self,event) self.resize(self.viewWidth,self.viewHeight) for headInfo in self.headers: name = headInfo['name'] x = headInfo['x'] x = x - self.position if x+self.w < 0: continue if x > self.viewWidth: continue self.headLeftPos = x self.headRightPos = x+self.w self.headTopPos = self.t self.headBottomPos = self.t+self.h qp = QtGui.QPainter() qp.begin(self) qp.setBrush(headInfo['color']) qp.drawRect(x,self.t,self.w,self.h) qp.setPen(QtGui.QColor(20, 20, 30)) qp.setFont(QtGui.QFont('Decorative', 10)) leaf_name = list(reversed(name.split(".")))[0] parent_name = ".".join(list(reversed(list(reversed(name.split(".")))[1:]))) if parent_name == "": qp.setFont(QtGui.QFont('Decorative', 11)) wd = QtGui.QFontMetrics(self.font()).boundingRect(leaf_name).width() align_option = QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter if wd > self.w-20 else QtCore.Qt.AlignCenter | QtCore.Qt.AlignVCenter qp.drawText(QtCore.QRect(x+10,self.t,self.w-20,self.h), align_option, leaf_name) else: qp.setFont(QtGui.QFont('Decorative', 7)) wd = QtGui.QFontMetrics(self.font()).boundingRect(parent_name).width() align_option = QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter if wd > self.w-20 else QtCore.Qt.AlignCenter | QtCore.Qt.AlignVCenter qp.drawText(QtCore.QRect(x+10,self.t,self.w-20,self.h/2), align_option, parent_name) qp.setFont(QtGui.QFont('Decorative', 11)) qp.drawText(QtCore.QRect(x+10,self.t+self.h/2,self.w-20,self.h/2), QtCore.Qt.AlignCenter | QtCore.Qt.AlignVCenter, leaf_name) qp.drawLine(x+self.w/2,self.h+self.t,x+self.w/2,90000) qp.end()
def testSetStyle(self): '''All this test have to do is not break with some invalid Python wrapper.''' def setStyleHelper(widget, style): widget.setStyle(style) widget.setPalette(style.standardPalette()) for child in widget.children(): if isinstance(child, QWidget): setStyleHelper(child, style) container = QWidget() # QFontComboBox is used because it has an QLineEdit created in C++ inside it, # and if the QWidget.setStyle(style) steals the ownership of the style # for the C++ originated widget everything will break. fontComboBox = QFontComboBox(container) label = QLabel(container) label.setText('Label') style = QStyleFactory.create(QStyleFactory.keys()[0]) setStyleHelper(container, style)
class MyWidget(QWidget): def __init__(self): QWidget.__init__(self) self.hello = ["Hallo welt!", "Ciao mondo!", "Hei maailma!", "Hola mundo!", "Hei verden!"] self.button = QPushButton("Click me!") self.text = QLabel("Hello World") self.text.setAlignment(Qt.AlignCenter) self.layout = QVBoxLayout() self.layout.addWidget(self.text) self.layout.addWidget(self.button) self.setLayout(self.layout) self.button.clicked.connect(self.magic) def magic(self): self.text.setText(random.choice(self.hello))
def __init__(self, parent=None): super(BlockingClient, self).__init__(parent) self.thread = FortuneThread() self.currentFortune = '' hostLabel = QLabel("&Server name:") portLabel = QLabel("S&erver port:") for ipAddress in QNetworkInterface.allAddresses(): if ipAddress != QHostAddress.LocalHost and ipAddress.toIPv4Address() != 0: break else: ipAddress = QHostAddress(QHostAddress.LocalHost) ipAddress = ipAddress.toString() self.hostLineEdit = QLineEdit(ipAddress) self.portLineEdit = QLineEdit() self.portLineEdit.setValidator(QIntValidator(1, 65535, self)) hostLabel.setBuddy(self.hostLineEdit) portLabel.setBuddy(self.portLineEdit) self.statusLabel = QLabel( "This example requires that you run the Fortune Server example as well.") self.statusLabel.setWordWrap(True) self.getFortuneButton = QPushButton("Get Fortune") self.getFortuneButton.setDefault(True) self.getFortuneButton.setEnabled(False) quitButton = QPushButton("Quit") buttonBox = QDialogButtonBox() buttonBox.addButton(self.getFortuneButton, QDialogButtonBox.ActionRole) buttonBox.addButton(quitButton, QDialogButtonBox.RejectRole) self.getFortuneButton.clicked.connect(self.requestNewFortune) quitButton.clicked.connect(self.close) self.hostLineEdit.textChanged.connect(self.enableGetFortuneButton) self.portLineEdit.textChanged.connect(self.enableGetFortuneButton) self.thread.newFortune.connect(self.showFortune) self.thread.error.connect(self.displayError) mainLayout = QGridLayout() mainLayout.addWidget(hostLabel, 0, 0) mainLayout.addWidget(self.hostLineEdit, 0, 1) mainLayout.addWidget(portLabel, 1, 0) mainLayout.addWidget(self.portLineEdit, 1, 1) mainLayout.addWidget(self.statusLabel, 2, 0, 1, 2) mainLayout.addWidget(buttonBox, 3, 0, 1, 2) self.setLayout(mainLayout) self.setWindowTitle("Blocking Fortune Client") self.portLineEdit.setFocus()
def __init__(self): super(MainWindow, self).__init__() self.setWindowTitle('PySide2 tabbed browser Example') self._tab_widget = BrowserTabWidget(create_main_window_with_browser) self._tab_widget.enabled_changed.connect(self._enabled_changed) self._tab_widget.download_requested.connect(self._download_requested) self.setCentralWidget(self._tab_widget) self.connect(self._tab_widget, QtCore.SIGNAL("url_changed(QUrl)"), self.url_changed) self._bookmark_dock = QDockWidget() self._bookmark_dock.setWindowTitle('Bookmarks') self._bookmark_widget = BookmarkWidget() self._bookmark_widget.open_bookmark.connect(self.load_url) self._bookmark_widget.open_bookmark_in_new_tab.connect(self.load_url_in_new_tab) self._bookmark_dock.setWidget(self._bookmark_widget) self.addDockWidget(Qt.LeftDockWidgetArea, self._bookmark_dock) self._find_tool_bar = None self._actions = {} self._create_menu() self._tool_bar = QToolBar() self.addToolBar(self._tool_bar) for action in self._actions.values(): if not action.icon().isNull(): self._tool_bar.addAction(action) self._addres_line_edit = QLineEdit() self._addres_line_edit.setClearButtonEnabled(True) self._addres_line_edit.returnPressed.connect(self.load) self._tool_bar.addWidget(self._addres_line_edit) self._zoom_label = QLabel() self.statusBar().addPermanentWidget(self._zoom_label) self._update_zoom_label() self._bookmarksToolBar = QToolBar() self.addToolBar(Qt.TopToolBarArea, self._bookmarksToolBar) self.insertToolBarBreak(self._bookmarksToolBar) self._bookmark_widget.changed.connect(self._update_bookmarks) self._update_bookmarks()
def _setupUI(self): self.setWindowTitle("Export Attributes to USD") layout = QVBoxLayout() # This section contains the attributes tagged for export. label = QLabel() label.setText('Exported Attributes:') layout.addWidget(label) self.exportedAttrsModel = ExportedAttributesModel() self.exportedAttrsView = ExportedAttributesView() self.exportedAttrsView.verticalHeader().hide() self.exportedAttrsView.setModel(self.exportedAttrsModel) selectionModel = self.exportedAttrsView.selectionModel() selectionModel.selectionChanged.connect(self._onExportedAttrsSelectionChanged) self.exportedAttrsModel.dataChanged.connect(self._onModelDataChanged) layout.addWidget(self.exportedAttrsView) self.removeExportedAttrButton = QPushButton("Remove Exported Attribute") self.removeExportedAttrButton.clicked.connect(self._onRemoveExportedAttrPressed) self.removeExportedAttrButton.setEnabled(False) layout.addWidget(self.removeExportedAttrButton) # This section contains the attributes available for export. label = QLabel() label.setText('Available Attributes:') layout.addWidget(label) self.userDefinedCheckBox = QCheckBox('User Defined') self.userDefinedCheckBox.setToolTip('Show only user-defined (dynamic) attributes') self.userDefinedCheckBox.setChecked(True) self.userDefinedCheckBox.stateChanged.connect(self._syncUI) layout.addWidget(self.userDefinedCheckBox) self.addAttrsModel = AddAttributesModel() self.addAttrsView = AddAttributesView() self.addAttrsView.setModel(self.addAttrsModel) selectionModel = self.addAttrsView.selectionModel() selectionModel.selectionChanged.connect(self._onAddAttrsSelectionChanged) self.addAttrsModel.dataChanged.connect(self._onModelDataChanged) layout.addWidget(self.addAttrsView) self.addExportedAttrButton = QPushButton("Add Exported Attribute") self.addExportedAttrButton.clicked.connect(self._onAddExportedAttrPressed) self.addExportedAttrButton.setEnabled(False) layout.addWidget(self.addExportedAttrButton) self.setLayout(layout)
def __init__(self, parent=None): super(Dialog, self).__init__(parent) self.server = FortuneServer() statusLabel = QLabel() statusLabel.setTextInteractionFlags(Qt.TextBrowserInteraction) statusLabel.setWordWrap(True) quitButton = QPushButton("Quit") quitButton.setAutoDefault(False) if not self.server.listen(): QMessageBox.critical(self, "Threaded Fortune Server", "Unable to start the server: %s." % self.server.errorString()) self.close() return for ipAddress in QNetworkInterface.allAddresses(): if ipAddress != QHostAddress.LocalHost and ipAddress.toIPv4Address() != 0: break else: ipAddress = QHostAddress(QHostAddress.LocalHost) ipAddress = ipAddress.toString() statusLabel.setText("The server is running on\n\nIP: %s\nport: %d\n\n" "Run the Fortune Client example now." % (ipAddress, self.server.serverPort())) quitButton.clicked.connect(self.close) buttonLayout = QHBoxLayout() buttonLayout.addStretch(1) buttonLayout.addWidget(quitButton) buttonLayout.addStretch(1) mainLayout = QVBoxLayout() mainLayout.addWidget(statusLabel) mainLayout.addLayout(buttonLayout) self.setLayout(mainLayout) self.setWindowTitle("Threaded Fortune Server")
def __init__(self, lifeline, defaultName, parent = None): super(ClusterDialog, self).__init__(parent) self.lifeline = lifeline layout = QVBoxLayout(self) message = QLabel('Enter group name') layout.addWidget(message) self.editClusterName = QLineEdit(defaultName) self.editClusterName.setFixedHeight(30) self.editClusterName.setFixedWidth(400) self.editClusterName.textChanged.connect(self.validateCluster) layout.addWidget(self.editClusterName) self.validation_msg = QLabel(' ') layout.addWidget(self.validation_msg) buttons = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, QtCore.Qt.Horizontal, self) buttons.accepted.connect(self.accept) buttons.rejected.connect(self.reject) layout.addWidget(buttons) self.validateCluster()
def __init__(self, parent=None): super(SettingsDialog, self).__init__(parent, "Settings") mouse_box = QGroupBox("Mouse", self) mouse_box.setLayout(QVBoxLayout()) label = QLabel("Scroll objects with mouse wheel:") label.setToolTip( "Select an object and scroll up and down to change its type.") self._scroll_check_box = QCheckBox("Enabled") self._scroll_check_box.setChecked(SETTINGS["object_scroll_enabled"]) self._scroll_check_box.toggled.connect(self._update_settings) scroll_layout = QHBoxLayout() scroll_layout.addWidget(label) scroll_layout.addStretch(1) scroll_layout.addWidget(self._scroll_check_box) label = QLabel("Show object names on hover:") label.setToolTip( "When hovering your cursor over an object in a level, its name and position is shown in a tooltip." ) self._tooltip_check_box = QCheckBox("Enabled") self._tooltip_check_box.setChecked(SETTINGS["object_tooltip_enabled"]) self._tooltip_check_box.toggled.connect(self._update_settings) tooltip_layout = QHBoxLayout() tooltip_layout.addWidget(label) tooltip_layout.addStretch(1) tooltip_layout.addWidget(self._tooltip_check_box) self.lmb_radio = QRadioButton("Left Mouse Button") rmb_radio = QRadioButton("Right Mouse Button") self.lmb_radio.setChecked(SETTINGS["resize_mode"] == RESIZE_LEFT_CLICK) rmb_radio.setChecked(SETTINGS["resize_mode"] == RESIZE_RIGHT_CLICK) self.lmb_radio.toggled.connect(self._update_settings) radio_group = QButtonGroup() radio_group.addButton(self.lmb_radio) radio_group.addButton(rmb_radio) resize_layout = QHBoxLayout() resize_layout.addWidget(QLabel("Object resize mode:")) resize_layout.addStretch(1) resize_layout.addWidget(self.lmb_radio) resize_layout.addWidget(rmb_radio) mouse_box.layout().addLayout(scroll_layout) mouse_box.layout().addLayout(tooltip_layout) mouse_box.layout().addLayout(resize_layout) # ----------------------------------------------- # GUI theme section self.gui_style_box = QGroupBox("GUI", self) QHBoxLayout(self.gui_style_box) self.gui_style_box.layout().addWidget(QLabel("Style:")) for gui_style in GUI_STYLE.keys(): gui_style = gui_style.capitalize() style_radio_button = QRadioButton(gui_style) style_radio_button.setChecked( SETTINGS["gui_style"] == GUI_STYLE[gui_style.upper()]()) style_radio_button.toggled.connect(self._update_settings) self.gui_style_box.layout().addWidget(style_radio_button) # ----------------------------------------------- # emulator command self.emulator_command_input = QLineEdit(self) self.emulator_command_input.setPlaceholderText("Path to emulator") self.emulator_command_input.setText(SETTINGS["instaplay_emulator"]) self.emulator_command_input.textChanged.connect(self._update_settings) self.emulator_path_button = QPushButton(icon("folder.svg"), "", self) self.emulator_path_button.pressed.connect(self._get_emulator_path) self.command_arguments_input = QLineEdit(self) self.command_arguments_input.setPlaceholderText("%f") self.command_arguments_input.setText(SETTINGS["instaplay_arguments"]) self.command_arguments_input.textEdited.connect(self._update_settings) self.command_label = QLabel() command_box = QGroupBox("Emulator", self) command_layout = QVBoxLayout(command_box) command_layout.addWidget(QLabel('Emulator command or "path to exe":')) command_input_layout = QHBoxLayout() command_input_layout.addWidget(self.emulator_command_input) command_input_layout.addWidget(self.emulator_path_button) command_layout.addLayout(command_input_layout) command_layout.addWidget( QLabel("Command arguments (%f will be replaced with rom path):")) command_layout.addWidget(self.command_arguments_input) command_layout.addWidget(QLabel("Command used to play the rom:")) command_layout.addWidget(self.command_label) command_layout.addWidget(HorizontalLine()) command_layout.addWidget( QLabel("Power up of Mario when playing level:")) self.powerup_combo_box = QComboBox() for name, x, y, value, p_wing in POWERUPS: powerup_icon = self._load_from_png(x, y) self.powerup_combo_box.addItem(powerup_icon, name) self.powerup_combo_box.currentIndexChanged.connect( self._update_settings) self.powerup_combo_box.setCurrentIndex(SETTINGS["default_powerup"]) command_layout.addWidget(self.powerup_combo_box) # ---------------------- layout = QVBoxLayout(self) layout.addWidget(mouse_box) layout.addWidget(self.gui_style_box) layout.addWidget(command_box) self.update()
def testWidgetStyle(self): w = QLabel('Hello') self.assertTrue(isinstance(w.style(), QMacStyle))
def __init__(self): super(Window, self).__init__() self.renderArea = RenderArea() self.shapeComboBox = QComboBox() self.shapeComboBox.addItem("Polygon", RenderArea.Polygon) self.shapeComboBox.addItem("Rectangle", RenderArea.Rect) self.shapeComboBox.addItem("Rounded Rectangle", RenderArea.RoundedRect) self.shapeComboBox.addItem("Ellipse", RenderArea.Ellipse) self.shapeComboBox.addItem("Pie", RenderArea.Pie) self.shapeComboBox.addItem("Chord", RenderArea.Chord) self.shapeComboBox.addItem("Path", RenderArea.Path) self.shapeComboBox.addItem("Line", RenderArea.Line) self.shapeComboBox.addItem("Polyline", RenderArea.Polyline) self.shapeComboBox.addItem("Arc", RenderArea.Arc) self.shapeComboBox.addItem("Points", RenderArea.Points) self.shapeComboBox.addItem("Text", RenderArea.Text) self.shapeComboBox.addItem("Pixmap", RenderArea.Pixmap) shapeLabel = QLabel("&Shape:") shapeLabel.setBuddy(self.shapeComboBox) self.penWidthSpinBox = QSpinBox() self.penWidthSpinBox.setRange(0, 20) self.penWidthSpinBox.setSpecialValueText("0 (cosmetic pen)") penWidthLabel = QLabel("Pen &Width:") penWidthLabel.setBuddy(self.penWidthSpinBox) self.penStyleComboBox = QComboBox() self.penStyleComboBox.addItem("Solid", Qt.SolidLine) self.penStyleComboBox.addItem("Dash", Qt.DashLine) self.penStyleComboBox.addItem("Dot", Qt.DotLine) self.penStyleComboBox.addItem("Dash Dot", Qt.DashDotLine) self.penStyleComboBox.addItem("Dash Dot Dot", Qt.DashDotDotLine) self.penStyleComboBox.addItem("None", Qt.NoPen) penStyleLabel = QLabel("&Pen Style:") penStyleLabel.setBuddy(self.penStyleComboBox) self.penCapComboBox = QComboBox() self.penCapComboBox.addItem("Flat", Qt.FlatCap) self.penCapComboBox.addItem("Square", Qt.SquareCap) self.penCapComboBox.addItem("Round", Qt.RoundCap) penCapLabel = QLabel("Pen &Cap:") penCapLabel.setBuddy(self.penCapComboBox) self.penJoinComboBox = QComboBox() self.penJoinComboBox.addItem("Miter", Qt.MiterJoin) self.penJoinComboBox.addItem("Bevel", Qt.BevelJoin) self.penJoinComboBox.addItem("Round", Qt.RoundJoin) penJoinLabel = QLabel("Pen &Join:") penJoinLabel.setBuddy(self.penJoinComboBox) self.brushStyleComboBox = QComboBox() self.brushStyleComboBox.addItem("Linear Gradient", Qt.LinearGradientPattern) self.brushStyleComboBox.addItem("Radial Gradient", Qt.RadialGradientPattern) self.brushStyleComboBox.addItem("Conical Gradient", Qt.ConicalGradientPattern) self.brushStyleComboBox.addItem("Texture", Qt.TexturePattern) self.brushStyleComboBox.addItem("Solid", Qt.SolidPattern) self.brushStyleComboBox.addItem("Horizontal", Qt.HorPattern) self.brushStyleComboBox.addItem("Vertical", Qt.VerPattern) self.brushStyleComboBox.addItem("Cross", Qt.CrossPattern) self.brushStyleComboBox.addItem("Backward Diagonal", Qt.BDiagPattern) self.brushStyleComboBox.addItem("Forward Diagonal", Qt.FDiagPattern) self.brushStyleComboBox.addItem("Diagonal Cross", Qt.DiagCrossPattern) self.brushStyleComboBox.addItem("Dense 1", Qt.Dense1Pattern) self.brushStyleComboBox.addItem("Dense 2", Qt.Dense2Pattern) self.brushStyleComboBox.addItem("Dense 3", Qt.Dense3Pattern) self.brushStyleComboBox.addItem("Dense 4", Qt.Dense4Pattern) self.brushStyleComboBox.addItem("Dense 5", Qt.Dense5Pattern) self.brushStyleComboBox.addItem("Dense 6", Qt.Dense6Pattern) self.brushStyleComboBox.addItem("Dense 7", Qt.Dense7Pattern) self.brushStyleComboBox.addItem("None", Qt.NoBrush) brushStyleLabel = QLabel("&Brush Style:") brushStyleLabel.setBuddy(self.brushStyleComboBox) otherOptionsLabel = QLabel("Other Options:") self.antialiasingCheckBox = QCheckBox("&Antialiasing") self.transformationsCheckBox = QCheckBox("&Transformations") self.shapeComboBox.activated.connect(self.shapeChanged) self.penWidthSpinBox.valueChanged.connect(self.penChanged) self.penStyleComboBox.activated.connect(self.penChanged) self.penCapComboBox.activated.connect(self.penChanged) self.penJoinComboBox.activated.connect(self.penChanged) self.brushStyleComboBox.activated.connect(self.brushChanged) self.antialiasingCheckBox.toggled.connect(self.renderArea.setAntialiased) self.transformationsCheckBox.toggled.connect(self.renderArea.setTransformed) mainLayout = QGridLayout() mainLayout.setColumnStretch(0, 1) mainLayout.setColumnStretch(3, 1) mainLayout.addWidget(self.renderArea, 0, 0, 1, 4) mainLayout.setRowMinimumHeight(1, 6) mainLayout.addWidget(shapeLabel, 2, 1, Qt.AlignRight) mainLayout.addWidget(self.shapeComboBox, 2, 2) mainLayout.addWidget(penWidthLabel, 3, 1, Qt.AlignRight) mainLayout.addWidget(self.penWidthSpinBox, 3, 2) mainLayout.addWidget(penStyleLabel, 4, 1, Qt.AlignRight) mainLayout.addWidget(self.penStyleComboBox, 4, 2) mainLayout.addWidget(penCapLabel, 5, 1, Qt.AlignRight) mainLayout.addWidget(self.penCapComboBox, 5, 2) mainLayout.addWidget(penJoinLabel, 6, 1, Qt.AlignRight) mainLayout.addWidget(self.penJoinComboBox, 6, 2) mainLayout.addWidget(brushStyleLabel, 7, 1, Qt.AlignRight) mainLayout.addWidget(self.brushStyleComboBox, 7, 2) mainLayout.setRowMinimumHeight(8, 6) mainLayout.addWidget(otherOptionsLabel, 9, 1, Qt.AlignRight) mainLayout.addWidget(self.antialiasingCheckBox, 9, 2) mainLayout.addWidget(self.transformationsCheckBox, 10, 2) self.setLayout(mainLayout) self.shapeChanged() self.penChanged() self.brushChanged() self.antialiasingCheckBox.setChecked(True) self.setWindowTitle("Basic Drawing")
def _initCodeEditor(self): self.codeView = CodeView(self.subject, viewTip=False) self.layout().addWidget(QLabel("Setup Code:", margin=10)) self.layout().addWidget(self.codeView) self.codeView.setDelegate(self)
class UiQuestion(object): '''Интерфейс диалогового окна программы. Created by: Qt User Interface Compiler. Задано: кнопка "подтвердить"; кнопка "отклонить". ''' def setupUi(self, Dialog): if not Dialog.objectName(): Dialog.setObjectName(u"Dialog") Dialog.resize(300, 200) Dialog.setMinimumSize(QSize(300, 200)) Dialog.setMaximumSize(QSize(300, 200)) self.verticalLayout = QVBoxLayout(Dialog) self.verticalLayout.setSpacing(0) self.verticalLayout.setObjectName(u"verticalLayout") self.verticalLayout.setContentsMargins(0, 0, 0, 0) self.dialog_main_frame = QFrame(Dialog) self.dialog_main_frame.setObjectName(u"dialog_main_frame") self.dialog_main_frame.setFrameShape(QFrame.StyledPanel) self.dialog_main_frame.setFrameShadow(QFrame.Raised) self.verticalLayout_2 = QVBoxLayout(self.dialog_main_frame) self.verticalLayout_2.setSpacing(5) self.verticalLayout_2.setObjectName(u"verticalLayout_2") self.verticalLayout_2.setContentsMargins(5, 5, 5, 5) self.text_frame = QFrame(self.dialog_main_frame) self.text_frame.setObjectName(u"text_frame") self.text_frame.setFrameShape(QFrame.StyledPanel) self.text_frame.setFrameShadow(QFrame.Raised) self.verticalLayout_3 = QVBoxLayout(self.text_frame) self.verticalLayout_3.setObjectName(u"verticalLayout_3") self.question_label = QLabel(self.text_frame) self.question_label.setObjectName(u"question_label") self.question_label.setAlignment(Qt.AlignCenter) self.verticalLayout_3.addWidget(self.question_label) self.verticalLayout_2.addWidget(self.text_frame) self.buttons_frame = QFrame(self.dialog_main_frame) self.buttons_frame.setObjectName(u"buttons_frame") self.buttons_frame.setMinimumSize(QSize(0, 50)) self.buttons_frame.setMaximumSize(QSize(16777215, 50)) self.buttons_frame.setFrameShape(QFrame.StyledPanel) self.buttons_frame.setFrameShadow(QFrame.Raised) self.horizontalLayout = QHBoxLayout(self.buttons_frame) self.horizontalLayout.setSpacing(5) self.horizontalLayout.setObjectName(u"horizontalLayout") self.horizontalLayout.setContentsMargins(5, 5, 5, 5) self.question_nok_btn = QPushButton(self.buttons_frame) self.question_nok_btn.setObjectName(u"question_nok_btn") self.question_nok_btn.setMinimumSize(QSize(0, 35)) self.question_nok_btn.setMaximumSize(QSize(16777215, 35)) icon = QIcon() icon.addFile(DISAGREE_ICON, QSize(), QIcon.Normal, QIcon.Off) self.question_nok_btn.setIcon(icon) self.question_nok_btn.setIconSize(QSize(25, 25)) self.horizontalLayout.addWidget(self.question_nok_btn) self.question_ok_btn = QPushButton(self.buttons_frame) self.question_ok_btn.setObjectName(u"question_ok_btn") self.question_ok_btn.setMinimumSize(QSize(0, 35)) self.question_ok_btn.setMaximumSize(QSize(16777215, 35)) icon1 = QIcon() icon1.addFile(AGREE_ICON, QSize(), QIcon.Normal, QIcon.Off) self.question_ok_btn.setIcon(icon1) self.question_ok_btn.setIconSize(QSize(25, 25)) self.horizontalLayout.addWidget(self.question_ok_btn) self.verticalLayout_2.addWidget(self.buttons_frame) self.verticalLayout.addWidget(self.dialog_main_frame) self.retranslateUi(Dialog) QMetaObject.connectSlotsByName(Dialog) # setupUi def retranslateUi(self, Dialog): Dialog.setWindowTitle( QCoreApplication.translate("Dialog", u"new calculation", None)) self.question_label.setText( QCoreApplication.translate("Dialog", u"Clear all fields?", None)) # if QT_CONFIG(tooltip) self.question_nok_btn.setToolTip( QCoreApplication.translate("Dialog", u"cancel", None)) # endif // QT_CONFIG(tooltip) self.question_nok_btn.setText("") # if QT_CONFIG(tooltip) self.question_ok_btn.setToolTip( QCoreApplication.translate("Dialog", u"continue", None)) # endif // QT_CONFIG(tooltip) self.question_ok_btn.setText("")
class StemOptions(QVBoxLayout): def __init__(self): super(StemOptions, self).__init__() self.curStems = '2 tracks' self.curOptions = (set(), set()) self.buildLayout() def buildLayout(self, pastOptions=(set(), set())): isolateTitle = QLabel('Isolate') removeTitle = QLabel('Remove') isolateBoxes = self.buildBoxes(True, pastOptions[0]) removeBoxes = self.buildBoxes(False, pastOptions[1]) isolateCol = QVBoxLayout() removeCol = QVBoxLayout() isolateCol.addWidget(isolateTitle) isolateCol.addLayout(isolateBoxes) removeCol.addWidget(removeTitle) removeCol.addLayout(removeBoxes) columns = QHBoxLayout() columns.addLayout(isolateCol) columns.addLayout(removeCol) self.previewOutput = QLabel() self.previewOutput.setWordWrap(True) self.updatePreview() self.addLayout(columns) self.addWidget(self.previewOutput) def setStems(self, stems): self.curStems = stems if stems != '5 tracks': self.curOptions[0].discard('piano') self.curOptions[1].discard('piano') if stems == '2 tracks': self.curOptions[0].discard('bass') self.curOptions[1].discard('bass') self.curOptions[0].discard('drums') self.curOptions[1].discard('drums') clearLayout(self) self.buildLayout(self.curOptions) def setChecked(self, stem, isIsolate, checked): if checked: self.curOptions[0 if isIsolate else 1].add(stem) else: self.curOptions[0 if isIsolate else 1].remove(stem) self.updatePreview() def updatePreview(self): text = 'Output Tracks: ' iso = map(lambda x: x + '.wav', self.curOptions[0]) rem = map(lambda x: 'no_' + x + '.wav', self.curOptions[1]) self.previewOutput.setText(text + ', '.join(list(iso) + list(rem))) def buildBoxes(self, isIsolate, pastOptions): boxColumn = QVBoxLayout() vocals = QCheckBox("Vocals") if 'vocals' in pastOptions: vocals.setChecked(True) vocals.toggled.connect( lambda x: self.setChecked('vocals', isIsolate, x)) boxColumn.addWidget(vocals) if self.curStems != '2 tracks': if self.curStems == '5 tracks': piano = QCheckBox("Piano") if 'piano' in pastOptions: piano.setChecked(True) piano.toggled.connect( lambda x: self.setChecked('piano', isIsolate, x)) boxColumn.addWidget(piano) bass = QCheckBox("Bass") if 'bass' in pastOptions: bass.setChecked(True) bass.toggled.connect( lambda x: self.setChecked('bass', isIsolate, x)) boxColumn.addWidget(bass) drums = QCheckBox("Drums") if 'drums' in pastOptions: drums.setChecked(True) drums.toggled.connect( lambda x: self.setChecked('drums', isIsolate, x)) boxColumn.addWidget(drums) other = QCheckBox('Other') if 'other' in pastOptions: other.setChecked(True) other.toggled.connect(lambda x: self.setChecked('other', isIsolate, x)) boxColumn.addWidget(other) return boxColumn
class GeneratorDialog(QDialog): """ 登录窗口 """ def __init__(self): """ 初始化产品验证登录界面 """ super().__init__() self.init_window() # # 创建布局并添加控件,用来显示提示信息 # cpu_label = QLabel("CPU 序列号:") self.cpu_input = QLineEdit() h_box1 = QHBoxLayout() h_box1.addWidget(cpu_label) h_box1.addWidget(self.cpu_input) key_label = QLabel(" 产品密钥:") self.key_input = QLineEdit() h_box2 = QHBoxLayout() h_box2.addWidget(key_label) h_box2.addWidget(self.key_input) policy = QSizePolicy() policy.setVerticalPolicy(QSizePolicy.Fixed) self.info_label = QLabel("") self.info_label.setSizePolicy(policy) self.ok_btn = QPushButton(text="获取产品密钥") self.ok_btn.clicked.connect(self.activate) h_box3 = QHBoxLayout() h_box3.addStretch() h_box3.addWidget(self.ok_btn) layout = QVBoxLayout() layout.addLayout(h_box1) layout.addLayout(h_box2) layout.addWidget(self.info_label) layout.addLayout(h_box3) self.setLayout(layout) def print_info(self, info: str): """ 输出提示信息 :param info:提示信息 :return: 无 """ self.info_label.setText(info) def init_window(self): """ 初始化对话框窗口 :return: 无 """ self.setWindowTitle("密钥生成器") #app_icon = QIcon("./other/key.ico") #self.setWindowIcon(app_icon) self.setFixedSize(600, 400) self.setWindowFlags( self.windowFlags() & ~Qt.WindowContextHelpButtonHint) # 去掉默认对话框样式左上角出现的问号 def activate(self): """ 激活按钮响应事件 :return: 无 """ cpu = self.cpu_input.text() if cpu != "": key = des_encrypt(cpu) if key != "": self.key_input.setText(key) self.print_info("") else: self.print_info("输入的 CPU 序列号有误!序列号仅包含数字和英文字母!") else: self.print_info("请输入 CPU 序列号!")
class MainWindow(QMainWindow): """Provides the parent window that includes the BookmarkWidget, BrowserTabWidget, and a DownloadWidget, to offer the complete web browsing experience.""" def __init__(self): super(MainWindow, self).__init__() self.setWindowTitle('PySide2 tabbed browser Example') self._tab_widget = BrowserTabWidget(create_main_window_with_browser) self._tab_widget.enabled_changed.connect(self._enabled_changed) self._tab_widget.download_requested.connect(self._download_requested) self.setCentralWidget(self._tab_widget) self.connect(self._tab_widget, QtCore.SIGNAL("url_changed(QUrl)"), self.url_changed) self._bookmark_dock = QDockWidget() self._bookmark_dock.setWindowTitle('Bookmarks') self._bookmark_widget = BookmarkWidget() self._bookmark_widget.open_bookmark.connect(self.load_url) self._bookmark_widget.open_bookmark_in_new_tab.connect(self.load_url_in_new_tab) self._bookmark_dock.setWidget(self._bookmark_widget) self.addDockWidget(Qt.LeftDockWidgetArea, self._bookmark_dock) self._find_tool_bar = None self._actions = {} self._create_menu() self._tool_bar = QToolBar() self.addToolBar(self._tool_bar) for action in self._actions.values(): if not action.icon().isNull(): self._tool_bar.addAction(action) self._addres_line_edit = QLineEdit() self._addres_line_edit.setClearButtonEnabled(True) self._addres_line_edit.returnPressed.connect(self.load) self._tool_bar.addWidget(self._addres_line_edit) self._zoom_label = QLabel() self.statusBar().addPermanentWidget(self._zoom_label) self._update_zoom_label() self._bookmarksToolBar = QToolBar() self.addToolBar(Qt.TopToolBarArea, self._bookmarksToolBar) self.insertToolBarBreak(self._bookmarksToolBar) self._bookmark_widget.changed.connect(self._update_bookmarks) self._update_bookmarks() def _update_bookmarks(self): self._bookmark_widget.populate_tool_bar(self._bookmarksToolBar) self._bookmark_widget.populate_other(self._bookmark_menu, 3) def _create_menu(self): file_menu = self.menuBar().addMenu("&File") exit_action = QAction(QIcon.fromTheme("application-exit"), "E&xit", self, shortcut = "Ctrl+Q", triggered=qApp.quit) file_menu.addAction(exit_action) navigation_menu = self.menuBar().addMenu("&Navigation") style_icons = ':/qt-project.org/styles/commonstyle/images/' back_action = QAction(QIcon.fromTheme("go-previous", QIcon(style_icons + 'left-32.png')), "Back", self, shortcut = QKeySequence(QKeySequence.Back), triggered = self._tab_widget.back) self._actions[QWebEnginePage.Back] = back_action back_action.setEnabled(False) navigation_menu.addAction(back_action) forward_action = QAction(QIcon.fromTheme("go-next", QIcon(style_icons + 'right-32.png')), "Forward", self, shortcut = QKeySequence(QKeySequence.Forward), triggered = self._tab_widget.forward) forward_action.setEnabled(False) self._actions[QWebEnginePage.Forward] = forward_action navigation_menu.addAction(forward_action) reload_action = QAction(QIcon(style_icons + 'refresh-32.png'), "Reload", self, shortcut = QKeySequence(QKeySequence.Refresh), triggered = self._tab_widget.reload) self._actions[QWebEnginePage.Reload] = reload_action reload_action.setEnabled(False) navigation_menu.addAction(reload_action) navigation_menu.addSeparator() new_tab_action = QAction("New Tab", self, shortcut = 'Ctrl+T', triggered = self.add_browser_tab) navigation_menu.addAction(new_tab_action) close_tab_action = QAction("Close Current Tab", self, shortcut = "Ctrl+W", triggered = self._close_current_tab) navigation_menu.addAction(close_tab_action) edit_menu = self.menuBar().addMenu("&Edit") find_action = QAction("Find", self, shortcut = QKeySequence(QKeySequence.Find), triggered = self._show_find) edit_menu.addAction(find_action) edit_menu.addSeparator() undo_action = QAction("Undo", self, shortcut = QKeySequence(QKeySequence.Undo), triggered = self._tab_widget.undo) self._actions[QWebEnginePage.Undo] = undo_action undo_action.setEnabled(False) edit_menu.addAction(undo_action) redo_action = QAction("Redo", self, shortcut = QKeySequence(QKeySequence.Redo), triggered = self._tab_widget.redo) self._actions[QWebEnginePage.Redo] = redo_action redo_action.setEnabled(False) edit_menu.addAction(redo_action) edit_menu.addSeparator() cut_action = QAction("Cut", self, shortcut = QKeySequence(QKeySequence.Cut), triggered = self._tab_widget.cut) self._actions[QWebEnginePage.Cut] = cut_action cut_action.setEnabled(False) edit_menu.addAction(cut_action) copy_action = QAction("Copy", self, shortcut = QKeySequence(QKeySequence.Copy), triggered = self._tab_widget.copy) self._actions[QWebEnginePage.Copy] = copy_action copy_action.setEnabled(False) edit_menu.addAction(copy_action) paste_action = QAction("Paste", self, shortcut = QKeySequence(QKeySequence.Paste), triggered = self._tab_widget.paste) self._actions[QWebEnginePage.Paste] = paste_action paste_action.setEnabled(False) edit_menu.addAction(paste_action) edit_menu.addSeparator() select_all_action = QAction("Select All", self, shortcut = QKeySequence(QKeySequence.SelectAll), triggered = self._tab_widget.select_all) self._actions[QWebEnginePage.SelectAll] = select_all_action select_all_action.setEnabled(False) edit_menu.addAction(select_all_action) self._bookmark_menu = self.menuBar().addMenu("&Bookmarks") add_bookmark_action = QAction("&Add Bookmark", self, triggered = self._add_bookmark) self._bookmark_menu.addAction(add_bookmark_action) add_tool_bar_bookmark_action = QAction("&Add Bookmark to Tool Bar", self, triggered = self._add_tool_bar_bookmark) self._bookmark_menu.addAction(add_tool_bar_bookmark_action) self._bookmark_menu.addSeparator() tools_menu = self.menuBar().addMenu("&Tools") download_action = QAction("Open Downloads", self, triggered = DownloadWidget.open_download_directory) tools_menu.addAction(download_action) window_menu = self.menuBar().addMenu("&Window") window_menu.addAction(self._bookmark_dock.toggleViewAction()) window_menu.addSeparator() zoom_in_action = QAction(QIcon.fromTheme("zoom-in"), "Zoom In", self, shortcut = QKeySequence(QKeySequence.ZoomIn), triggered = self._zoom_in) window_menu.addAction(zoom_in_action) zoom_out_action = QAction(QIcon.fromTheme("zoom-out"), "Zoom Out", self, shortcut = QKeySequence(QKeySequence.ZoomOut), triggered = self._zoom_out) window_menu.addAction(zoom_out_action) reset_zoom_action = QAction(QIcon.fromTheme("zoom-original"), "Reset Zoom", self, shortcut = "Ctrl+0", triggered = self._reset_zoom) window_menu.addAction(reset_zoom_action) about_menu = self.menuBar().addMenu("&About") about_action = QAction("About Qt", self, shortcut = QKeySequence(QKeySequence.HelpContents), triggered=qApp.aboutQt) about_menu.addAction(about_action) def add_browser_tab(self): return self._tab_widget.add_browser_tab() def _close_current_tab(self): if self._tab_widget.count() > 1: self._tab_widget.close_current_tab() else: self.close() def close_event(self, event): main_windows.remove(self) event.accept() def load(self): url_string = self._addres_line_edit.text().strip() if url_string: self.load_url_string(url_string) def load_url_string(self, url_s): url = QUrl.fromUserInput(url_s) if (url.isValid()): self.load_url(url) def load_url(self, url): self._tab_widget.load(url) def load_url_in_new_tab(self, url): self.add_browser_tab().load(url) def url_changed(self, url): self._addres_line_edit.setText(url.toString()) def _enabled_changed(self, web_action, enabled): action = self._actions[web_action] if action: action.setEnabled(enabled) def _add_bookmark(self): index = self._tab_widget.currentIndex() if index >= 0: url = self._tab_widget.url() title = self._tab_widget.tabText(index) icon = self._tab_widget.tabIcon(index) self._bookmark_widget.add_bookmark(url, title, icon) def _add_tool_bar_bookmark(self): index = self._tab_widget.currentIndex() if index >= 0: url = self._tab_widget.url() title = self._tab_widget.tabText(index) icon = self._tab_widget.tabIcon(index) self._bookmark_widget.add_tool_bar_bookmark(url, title, icon) def _zoom_in(self): new_zoom = self._tab_widget.zoom_factor() * 1.5 if (new_zoom <= WebEngineView.maximum_zoom_factor()): self._tab_widget.set_zoom_factor(new_zoom) self._update_zoom_label() def _zoom_out(self): new_zoom = self._tab_widget.zoom_factor() / 1.5 if (new_zoom >= WebEngineView.minimum_zoom_factor()): self._tab_widget.set_zoom_factor(new_zoom) self._update_zoom_label() def _reset_zoom(self): self._tab_widget.set_zoom_factor(1) self._update_zoom_label() def _update_zoom_label(self): percent = int(self._tab_widget.zoom_factor() * 100) self._zoom_label.setText("{}%".format(percent)) def _download_requested(self, item): # Remove old downloads before opening a new one for old_download in self.statusBar().children(): if type(old_download).__name__ == 'download_widget' and \ old_download.state() != QWebEngineDownloadItem.DownloadInProgress: self.statusBar().removeWidget(old_download) del old_download item.accept() download_widget = download_widget(item) download_widget.removeRequested.connect(self._remove_download_requested, Qt.QueuedConnection) self.statusBar().addWidget(download_widget) def _remove_download_requested(self): download_widget = self.sender() self.statusBar().removeWidget(download_widget) del download_widget def _show_find(self): if self._find_tool_bar is None: self._find_tool_bar = FindToolBar() self._find_tool_bar.find.connect(self._tab_widget.find) self.addToolBar(Qt.BottomToolBarArea, self._find_tool_bar) else: self._find_tool_bar.show() self._find_tool_bar.focus_find() def write_bookmarks(self): self._bookmark_widget.write_bookmarks()
class PanAndZoom(ZoomOnWheel): """Class providing pan & zoom interaction to a matplotlib Figure. Left button for pan, right button for zoom area and zoom on wheel. Support subplots, twin Axes and log scales. This class extends the `ZoomOnWheel` class. """ def __init__(self, figure=None, scale_factor=1.1): """ Args: figure (figure): The matplotlib figure to attach the behavior to. scale_factor (float): The scale factor to apply on wheel event. """ super(PanAndZoom, self).__init__(figure, scale_factor) self._add_connection('button_press_event', self._on_mouse_press) self._add_connection('button_release_event', self._on_mouse_release) self._add_connection('motion_notify_event', self._on_mouse_motion) self._pressed_button = None # To store active button self._axes = None # To store x and y axes concerned by interaction self._event = None # To store reference event during interaction self.options = Dict(dict(report_point_position=True, )) self.logger = None self._statusbar_label = None # self._get_images_path() # self._add_toolbar_tools() self._style_figure() self._ix_iy_old = (0, 0) def _get_images_path(self): """Get the path to images. Returns: str: path Raises: Exception: path error """ # to be removed try: # Get tool image path from pathlib import Path from ... import _gui imgs_path = Path(_gui.__file__).parent / '_imgs' if imgs_path.is_dir() == False: print(f'Bad File path for images! {imgs_path}') imgs_path = None except Exception as e: print('ERROR: ', e) imgs_path = None self.imgs_path = imgs_path return imgs_path def _add_toolbar_tools(self): """Add tools.""" # TODO: Outdated - to be removed from matplotlib.backend_tools import ToolToggleBase # ToolBase class ToolPointPosition(ToolToggleBase): """Tools.""" default_keymap = 'Ctrl+p' description = 'Click to get point coordinate printed' default_toggled = False image = None # str(imgs_path) def __init__(self, *args, parent=None, **kwargs): super().__init__(*args, **kwargs) if parent is None: raise ('Pass a parent') self.parent = parent def enable(self, *args): self.parent.options.report_point_position = True def disable(self, *args): self.parent.options.report_point_position = False fig = self.figure imgs_path = self.imgs_path # pylint: disable=attribute-defined-outside-init toolbar = self.toolbar = fig.canvas.manager.toolbar # Get tool manager # TODO: Remove use of tool manager just use PySide2 bare as below # ToolbarQt --- https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/backends/backend_qt5.py tm = fig.canvas.manager.toolmanager self.tm = tm # Tool: Print point location ToolPointPosition.image = str(imgs_path / 'click.png') with warnings.catch_warnings(): warnings.simplefilter("ignore") tm.add_tool("Point_position", ToolPointPosition, parent=self) fig.canvas.manager.toolbar.add_tool(tm.get_tool("Point_position"), "toolgroup") # Tool: Copy to Clipboard from matplotlib.backend_tools import ToolCopyToClipboard ToolCopyToClipboard.image = str(imgs_path / 'copy.png') with warnings.catch_warnings(): warnings.simplefilter("ignore") # OVvrwties Ctrl+C and issues warning tm.add_tool("Copy_to_clipboard", ToolCopyToClipboard) fig.canvas.manager.toolbar.add_tool(tm.get_tool("Copy_to_clipboard"), "toolgroup") if 1: # add QT Pieces toolbar.action_ascale = QAction( QIcon(str(imgs_path / 'auto_zoom.png')), 'Auto scale', toolbar) toolbar.action_ascale.setShortcut('A') toolbar.action_ascale.setShortcutContext(Qt.WindowShortcut) toolbar.action_ascale.setStatusTip('Autoscale') toolbar.action_ascale.triggered.connect(self.auto_scale) toolbar.addAction(toolbar.action_ascale) # Status Bar: Second label to report figManager = fig.canvas.manager # plt.get_current_fig_manager() status_bar = figManager.window.statusBar() self._status_label_2 = QLabel(status_bar) self._status_label_2.setText('') status_bar.addWidget(self._status_label_2) #from matplotlib.backends.backend_qt5 import StatusbarQt #st = StatusbarQt(figManager.window, figManager.toolmanager) # figManager.statusbar.set_message('') def auto_scale(self): """Auto scaler.""" for ax in self.figure.axes: ax.autoscale() # self.figure.canvas.flush_events() self.figure.canvas.draw() def _style_figure(self): """Style figure.""" #self.figure.dpi = 150 pass @staticmethod def _pan_update_limits(ax, axis_id, event, last_event): """Compute limits with applied pan. Args: axis_id (int): ID of the axis event (event): The event last_event (event): The previous event Returns: double: New limit Raises: ValueError: Value error OverflowError: Overflow error """ assert axis_id in (0, 1) if axis_id == 0: lim = ax.get_xlim() scale = ax.get_xscale() else: lim = ax.get_ylim() scale = ax.get_yscale() pixel_to_data = ax.transData.inverted() data = pixel_to_data.transform_point((event.x, event.y)) last_data = pixel_to_data.transform_point((last_event.x, last_event.y)) if scale == 'linear': delta = data[axis_id] - last_data[axis_id] new_lim = lim[0] - delta, lim[1] - delta elif scale == 'log': try: delta = math.log10(data[axis_id]) - \ math.log10(last_data[axis_id]) new_lim = [ pow(10., (math.log10(lim[0]) - delta)), pow(10., (math.log10(lim[1]) - delta)) ] except (ValueError, OverflowError): new_lim = lim # Keep previous limits else: logging.warning('Pan not implemented for scale "%s"' % scale) new_lim = lim return new_lim def _pan(self, event): """Pan. Args: event (event): The event """ if event.name == 'button_press_event': # begin pan self._event = event elif event.name == 'button_release_event': # end pan self._event = None elif event.name == 'motion_notify_event': # pan if self._event is None: return if event.x != self._event.x: for ax in self._axes[0]: xlim = self._pan_update_limits(ax, 0, event, self._event) ax.set_xlim(xlim) if event.y != self._event.y: for ax in self._axes[1]: ylim = self._pan_update_limits(ax, 1, event, self._event) ax.set_ylim(ylim) if event.x != self._event.x or event.y != self._event.y: self._draw() self._event = event def _zoom_area(self, event): """Zoom. Args: event (event): The event """ if event.name == 'button_press_event': # begin drag self._event = event # pylint: disable=attribute-defined-outside-init self._patch = _plt.Rectangle(xy=(event.xdata, event.ydata), width=0, height=0, fill=False, linewidth=1., linestyle='solid', color='black') self._event.inaxes.add_patch(self._patch) elif event.name == 'button_release_event': # end drag self._patch.remove() del self._patch if (abs(event.x - self._event.x) < 3 or abs(event.y - self._event.y) < 3): return # No zoom when points are too close x_axes, y_axes = self._axes for ax in x_axes: pixel_to_data = ax.transData.inverted() begin_pt = pixel_to_data.transform_point((event.x, event.y)) end_pt = pixel_to_data.transform_point( (self._event.x, self._event.y)) min_ = min(begin_pt[0], end_pt[0]) max_ = max(begin_pt[0], end_pt[0]) if not ax.xaxis_inverted(): ax.set_xlim(min_, max_) else: ax.set_xlim(max_, min_) for ax in y_axes: pixel_to_data = ax.transData.inverted() begin_pt = pixel_to_data.transform_point((event.x, event.y)) end_pt = pixel_to_data.transform_point( (self._event.x, self._event.y)) min_ = min(begin_pt[1], end_pt[1]) max_ = max(begin_pt[1], end_pt[1]) if not ax.yaxis_inverted(): ax.set_ylim(min_, max_) else: ax.set_ylim(max_, min_) self._event = None elif event.name == 'motion_notify_event': # drag if self._event is None: return if event.inaxes != self._event.inaxes: return # Ignore event outside plot self._patch.set_width(event.xdata - self._event.xdata) self._patch.set_height(event.ydata - self._event.ydata) self._draw() def _on_mouse_press(self, event): """Mouse press event. Args: event (event): The event """ if self._pressed_button is not None: return # Discard event if a button is already pressed if event.button in (1, 3): # Start x_axes, y_axes = self._axes_to_update(event) if x_axes or y_axes: self._axes = x_axes, y_axes self._pressed_button = event.button if self._pressed_button == 1: # pan self._pan(event) if self.options.report_point_position: # check if we want to report point self._report_point_position(event) elif self._pressed_button == 3: # zoom area self._zoom_area(event) def _on_mouse_release(self, event): """Mouse release event. Args: event (event): The event """ if self._pressed_button == event.button: if self._pressed_button == 1: # pan self._pan(event) elif self._pressed_button == 3: # zoom area self._zoom_area(event) self._pressed_button = None def _on_mouse_motion(self, event): """Mouse motion event. Args: event (event): The event """ if self._pressed_button == 1: # pan self._pan(event) elif self._pressed_button == 3: # zoom area self._zoom_area(event) def _report_point_position(self, event): """Report point position. Args: event (event): the event """ ix, iy = event.xdata, event.ydata if hasattr(self, '_ix_iy_old'): ix_old, iy_old = self._ix_iy_old else: ix_old, iy_old = (ix, iy) self._ix_iy_old = ix, iy _text = f'(x,y) = ({ix:.4f}, {iy:.4f}) Δ last point ({ix-ix_old:.4f}, {iy-iy_old:.4f})' if self.logger: self.logger.info(_text) if self._statusbar_label: self._statusbar_label.setText(_text)
def __init__(self, params): MWB.__init__(self, params) QLabel.__init__(self) self.resize(200, 200)
class SettingsDialog(CustomDialog): def __init__(self, parent=None): super(SettingsDialog, self).__init__(parent, "Settings") mouse_box = QGroupBox("Mouse", self) mouse_box.setLayout(QVBoxLayout()) label = QLabel("Scroll objects with mouse wheel:") label.setToolTip( "Select an object and scroll up and down to change its type.") self._scroll_check_box = QCheckBox("Enabled") self._scroll_check_box.setChecked(SETTINGS["object_scroll_enabled"]) self._scroll_check_box.toggled.connect(self._update_settings) scroll_layout = QHBoxLayout() scroll_layout.addWidget(label) scroll_layout.addStretch(1) scroll_layout.addWidget(self._scroll_check_box) label = QLabel("Show object names on hover:") label.setToolTip( "When hovering your cursor over an object in a level, its name and position is shown in a tooltip." ) self._tooltip_check_box = QCheckBox("Enabled") self._tooltip_check_box.setChecked(SETTINGS["object_tooltip_enabled"]) self._tooltip_check_box.toggled.connect(self._update_settings) tooltip_layout = QHBoxLayout() tooltip_layout.addWidget(label) tooltip_layout.addStretch(1) tooltip_layout.addWidget(self._tooltip_check_box) self.lmb_radio = QRadioButton("Left Mouse Button") rmb_radio = QRadioButton("Right Mouse Button") self.lmb_radio.setChecked(SETTINGS["resize_mode"] == RESIZE_LEFT_CLICK) rmb_radio.setChecked(SETTINGS["resize_mode"] == RESIZE_RIGHT_CLICK) self.lmb_radio.toggled.connect(self._update_settings) radio_group = QButtonGroup() radio_group.addButton(self.lmb_radio) radio_group.addButton(rmb_radio) resize_layout = QHBoxLayout() resize_layout.addWidget(QLabel("Object resize mode:")) resize_layout.addStretch(1) resize_layout.addWidget(self.lmb_radio) resize_layout.addWidget(rmb_radio) mouse_box.layout().addLayout(scroll_layout) mouse_box.layout().addLayout(tooltip_layout) mouse_box.layout().addLayout(resize_layout) # ----------------------------------------------- # GUI theme section self.gui_style_box = QGroupBox("GUI", self) QHBoxLayout(self.gui_style_box) self.gui_style_box.layout().addWidget(QLabel("Style:")) for gui_style in GUI_STYLE.keys(): gui_style = gui_style.capitalize() style_radio_button = QRadioButton(gui_style) style_radio_button.setChecked( SETTINGS["gui_style"] == GUI_STYLE[gui_style.upper()]()) style_radio_button.toggled.connect(self._update_settings) self.gui_style_box.layout().addWidget(style_radio_button) # ----------------------------------------------- # emulator command self.emulator_command_input = QLineEdit(self) self.emulator_command_input.setPlaceholderText("Path to emulator") self.emulator_command_input.setText(SETTINGS["instaplay_emulator"]) self.emulator_command_input.textChanged.connect(self._update_settings) self.emulator_path_button = QPushButton(icon("folder.svg"), "", self) self.emulator_path_button.pressed.connect(self._get_emulator_path) self.command_arguments_input = QLineEdit(self) self.command_arguments_input.setPlaceholderText("%f") self.command_arguments_input.setText(SETTINGS["instaplay_arguments"]) self.command_arguments_input.textEdited.connect(self._update_settings) self.command_label = QLabel() command_box = QGroupBox("Emulator", self) command_layout = QVBoxLayout(command_box) command_layout.addWidget(QLabel('Emulator command or "path to exe":')) command_input_layout = QHBoxLayout() command_input_layout.addWidget(self.emulator_command_input) command_input_layout.addWidget(self.emulator_path_button) command_layout.addLayout(command_input_layout) command_layout.addWidget( QLabel("Command arguments (%f will be replaced with rom path):")) command_layout.addWidget(self.command_arguments_input) command_layout.addWidget(QLabel("Command used to play the rom:")) command_layout.addWidget(self.command_label) command_layout.addWidget(HorizontalLine()) command_layout.addWidget( QLabel("Power up of Mario when playing level:")) self.powerup_combo_box = QComboBox() for name, x, y, value, p_wing in POWERUPS: powerup_icon = self._load_from_png(x, y) self.powerup_combo_box.addItem(powerup_icon, name) self.powerup_combo_box.currentIndexChanged.connect( self._update_settings) self.powerup_combo_box.setCurrentIndex(SETTINGS["default_powerup"]) command_layout.addWidget(self.powerup_combo_box) # ---------------------- layout = QVBoxLayout(self) layout.addWidget(mouse_box) layout.addWidget(self.gui_style_box) layout.addWidget(command_box) self.update() def update(self): self.command_label.setText( f" > {SETTINGS['instaplay_emulator']} {SETTINGS['instaplay_arguments']}" ) def _update_settings(self, _): SETTINGS["instaplay_emulator"] = self.emulator_command_input.text() SETTINGS["instaplay_arguments"] = self.command_arguments_input.text() if self.lmb_radio.isChecked(): SETTINGS["resize_mode"] = RESIZE_LEFT_CLICK else: SETTINGS["resize_mode"] = RESIZE_RIGHT_CLICK # setup style sheets for child_widget in self.gui_style_box.children(): if isinstance(child_widget, QRadioButton): if child_widget.isChecked(): selected_gui_style = child_widget.text().upper() loaded_style_sheet = GUI_STYLE[selected_gui_style]() SETTINGS["gui_style"] = loaded_style_sheet self.parent().setStyleSheet(SETTINGS["gui_style"]) break SETTINGS["object_scroll_enabled"] = self._scroll_check_box.isChecked() SETTINGS["object_tooltip_enabled"] = self._tooltip_check_box.isChecked( ) SETTINGS["default_powerup"] = self.powerup_combo_box.currentIndex() self.update() def _get_emulator_path(self): path_to_emulator, _ = QFileDialog.getOpenFileName( self, caption="Select emulator executable") if not path_to_emulator: return self.emulator_command_input.setText(path_to_emulator) @staticmethod def _load_from_png(x: int, y: int) -> QIcon: image = png.copy( QRect(x * Block.SIDE_LENGTH, y * Block.SIDE_LENGTH, Block.SIDE_LENGTH, Block.SIDE_LENGTH)) mask = image.createMaskFromColor( QColor(*MASK_COLOR).rgb(), Qt.MaskOutColor) image.setAlphaChannel(mask) pixmap = QPixmap.fromImage(image) icon_from_png = QIcon(pixmap) return icon_from_png def on_exit(self): save_settings() super(SettingsDialog, self).on_exit()
class RaccourcisPage(QWidget): def __init__(self, parent): super(RaccourcisPage, self).__init__() self.parent = parent self.grid = QGridLayout() self.title = QLabel("Raccourcis URL") self.title.setAlignment(Qt.AlignHCenter) self.listeW = ListWidget( self.parent.parent.db.executewithreturn( """SELECT * FROM raccourcis""")) self.liste = self.listeW.liste self.supp = PushButton("Supprimer") self.suppAll = PushButton("Tout supprimer") self.spacerItem = QSpacerItem(20, 20) self.tEntryString = "Nom du raccourci" self.uEntryString = "URL du raccourci" self.tEntry = QLineEdit(self.tEntryString) self.uEntry = QLineEdit(self.uEntryString) self.addRac = PushButton("Ajouter un raccourci URL") self.listeW.itemDoubleClicked.connect(self.launch) self.suppAll.clicked.connect(self.deleteall) self.supp.clicked.connect(self.delete) self.addRac.clicked.connect(self.addraccourci) self.grid.addWidget(self.title, 1, 1, 1, 2) self.grid.addWidget(self.listeW, 2, 1, 1, 2) self.grid.addWidget(self.supp, 3, 1) self.grid.addWidget(self.suppAll, 3, 2) self.grid.addItem(self.spacerItem, 4, 1, 1, 2) self.grid.addWidget(self.tEntry, 5, 1) self.grid.addWidget(self.uEntry, 5, 2) self.grid.addWidget(self.addRac, 6, 1, 1, 2) self.setLayout(self.grid) def launch(self): if self.listeW.currentItem(): for i in self.liste: if str(i[0]) == self.listeW.currentItem().text(3): self.parent.close() self.parent.parent.opennewongletwithurl(i[2]) break def addraccourci(self): raccourcis = self.parent.parent.db.executewithreturn( """SELECT * FROM raccourcis""") for i in raccourcis: if i[1] == self.tEntry.text(): QMessageBox.warning(self, "Erreur", "Ce raccourcis existe déjà.") return tentrybool = self.tEntry.text() != "" and self.tEntry.text( ) != self.tEntryString uentrybool = self.uEntry.text() != "" and self.uEntry.text( ) != self.uEntryString if tentrybool and uentrybool: self.parent.parent.db.executewithoutreturn( """INSERT INTO raccourcis(name, url, date) VALUES(?, ?, ?)""", (self.tEntry.text(), self.uEntry.text(), getdate())) self.showupdate() def showupdate(self): self.listeW.deleteallitems() self.liste = self.parent.parent.db.executewithreturn( """SELECT * FROM raccourcis""") self.listeW.updatelist(self.liste) def delete(self): if self.listeW.currentItem(): for i in self.liste: if str(i[0]) == self.listeW.currentItem().text(3): self.parent.parent.db.executewithoutreturn( """DELETE FROM raccourcis WHERE id = ?""", (i[0], )) self.showupdate() def deleteall(self): self.parent.parent.db.executewithoutreturn( """DELETE FROM raccourcis""") self.showupdate()
def createLayout(self): self.GridGroupBox = QGroupBox("ESD tranisent control") l1 = QLabel("HOST PORT") h1 = QHBoxLayout() a3host = QLineEdit('127.0.0.1') a3col = QLabel(':') a3port = QLineEdit('22222') h1.addWidget(a3host) h1.addWidget(a3col) h1.addWidget(a3port) l3 = QLabel("COM port") hbb = QHBoxLayout() comport = QComboBox() #comport.addItem('COM1') comport.addItems(['COM1', 'COM2', 'COM3', 'COM4', 'COM5']) l4 = QLabel("Baue rate") comBaud = QComboBox() comBaud.addItems(['9600', '115200']) hbb.addWidget(comport) hbb.addWidget(l4) hbb.addWidget(comBaud) l4 = QLabel("Profile CSV") self.prof = QLineEdit() hb = QHBoxLayout() btnSel = QPushButton("Select") btnSel.clicked.connect(self.openFileNameDialog) hb.addWidget(self.prof) hb.addWidget(btnSel) l5 = QLabel("INCA Label") self.label = QLineEdit("PhyMod_trq2qBas_MAP") self.labelType = QComboBox() l6 = QLabel("Type") self.labelType.addItems([r'MAP/CURVE', 'Single']) h2 = QHBoxLayout() h2.addWidget(self.label) h2.addWidget(l6) h2.addWidget(self.labelType) fbox = QFormLayout() fbox.addRow(l1, h1) fbox.addRow(l3, hbb) fbox.addRow(l4, hb) fbox.addRow(l5, h2) hbox = QHBoxLayout() init = QPushButton("Init") HeatBeat = QPushButton("Heart beat") run = QPushButton("Run") stop = QPushButton("Stop") hbox.addWidget(init) hbox.addWidget(stop) hbox.addWidget(run) hbox.addWidget(HeatBeat) fbox.addRow(QLabel("control"), hbox) self.GridGroupBox.setLayout(fbox)
def __init__(self, filename, image, parent=None): super(ComparisonWidget, self).__init__(parent) load_button = QPushButton(self.tr('Load reference image...')) self.comp_label = QLabel(self.tr('Comparison:')) self.normal_radio = QRadioButton(self.tr('Normal')) self.normal_radio.setToolTip(self.tr('Show reference (raw pixels)')) self.normal_radio.setChecked(True) self.difference_radio = QRadioButton(self.tr('Difference')) self.difference_radio.setToolTip( self.tr('Show evidence/reference difference')) self.ssim_radio = QRadioButton(self.tr('SSIM Map')) self.ssim_radio.setToolTip(self.tr('Structure similarity quality map')) self.butter_radio = QRadioButton(self.tr('Butteraugli')) self.butter_radio.setToolTip( self.tr('Butteraugli spatial changes heatmap')) self.gray_check = QCheckBox(self.tr('Grayscale')) self.gray_check.setToolTip(self.tr('Show desaturated output')) self.equalize_check = QCheckBox(self.tr('Equalized')) self.equalize_check.setToolTip(self.tr('Apply histogram equalization')) self.last_radio = self.normal_radio self.metric_button = QPushButton(self.tr('Compute metrics')) self.metric_button.setToolTip( self.tr('Image quality assessment metrics')) self.evidence = image self.reference = self.difference = self.ssim_map = self.butter_map = None basename = os.path.basename(filename) self.evidence_viewer = ImageViewer( self.evidence, None, self.tr('Evidence: {}'.format(basename))) self.reference_viewer = ImageViewer(np.full_like(self.evidence, 127), None, self.tr('Reference')) self.table_widget = QTableWidget(21, 3) self.table_widget.setHorizontalHeaderLabels( [self.tr('Metric'), self.tr('Value'), self.tr('Better')]) self.table_widget.setItem(0, 0, QTableWidgetItem(self.tr('RMSE'))) self.table_widget.setItem( 0, 2, QTableWidgetItem(QIcon('icons/low.svg'), '(0)')) self.table_widget.item(0, 0).setToolTip( self. tr('Root Mean Square Error (RMSE) is commonly used to compare \n' 'the difference between the reference and evidence images \n' 'by directly computing the variation in pixel values. \n' 'The combined image is close to the reference image when \n' 'RMSE value is zero. RMSE is a good indicator of the spectral \n' 'quality of the reference image.')) self.table_widget.setItem(1, 0, QTableWidgetItem(self.tr('SAM'))) self.table_widget.setItem( 1, 2, QTableWidgetItem(QIcon('icons/low.svg'), '(0)')) self.table_widget.item(1, 0).setToolTip( self. tr('It computes the spectral angle between the pixel, vector of the \n' 'evidence image and reference image. It is worked out in either \n' 'degrees or radians. It is performed on a pixel-by-pixel base. \n' 'A SAM equal to zero denotes the absence of spectral distortion.' )) self.table_widget.setItem(2, 0, QTableWidgetItem(self.tr('ERGAS'))) self.table_widget.setItem( 2, 2, QTableWidgetItem(QIcon('icons/low.svg'), '(0)')) self.table_widget.item(2, 0).setToolTip( self. tr('It is used to compute the quality of reference image in terms \n' 'of normalized average error of each band of the reference image. \n' 'Increase in the value of ERGAS indicates distortion in the \n' 'reference image, lower value of ERGAS indicates that it is \n' 'similar to the reference image.')) self.table_widget.setItem(3, 0, QTableWidgetItem(self.tr('MB'))) self.table_widget.setItem( 3, 2, QTableWidgetItem(QIcon('icons/low.svg'), '(0)')) self.table_widget.item(3, 0).setToolTip( self. tr('Mean Bias is the difference between the mean of the evidence \n' 'image and reference image. The ideal value is zero and indicates \n' 'that the evidence and reference images are similar. Mean value \n' 'refers to the grey level of pixels in an image.')) self.table_widget.setItem(4, 0, QTableWidgetItem(self.tr('PFE'))) self.table_widget.setItem( 4, 2, QTableWidgetItem(QIcon('icons/low.svg'), '(0)')) self.table_widget.item(4, 0).setToolTip( self. tr('It computes the norm of the difference between the corresponding \n' 'pixels of the reference and fused image to the norm of the reference \n' 'image. When the calculated value is zero, it indicates that both the \n' 'reference and fused images are similar and value will be increased \n' 'when the merged image is not similar to the reference image.')) self.table_widget.setItem(5, 0, QTableWidgetItem(self.tr('PSNR'))) self.table_widget.setItem( 5, 2, QTableWidgetItem(QIcon('icons/high.svg'), '(+' + u'\u221e' + ')')) self.table_widget.item(5, 0).setToolTip( self. tr('It is widely used metric it is computed by the number of gray levels \n' 'in the image divided by the corresponding pixels in the evidence and \n' 'the reference images. When the value is high, both images are similar.' )) self.table_widget.setItem(6, 0, QTableWidgetItem(self.tr('PSNR-B'))) self.table_widget.setItem( 6, 2, QTableWidgetItem(QIcon('icons/high.svg'), '(+' + u'\u221e' + ')')) self.table_widget.item(6, 0).setToolTip( self.tr('PSNR with Blocking Effect Factor.')) self.table_widget.setItem(7, 0, QTableWidgetItem(self.tr('SSIM'))) self.table_widget.setItem( 7, 2, QTableWidgetItem(QIcon('icons/high.svg'), '(1)')) self.table_widget.item(7, 0).setToolTip( self. tr('SSIM is used to compare the local patterns of pixel intensities between \n' ' the reference and fused images. The range varies between -1 to 1. \n' 'The value 1 indicates the reference and fused images are similar.' )) self.table_widget.setItem(8, 0, QTableWidgetItem(self.tr('MS-SSIM'))) self.table_widget.setItem( 8, 2, QTableWidgetItem(QIcon('icons/high.svg'), '(1)')) self.table_widget.item(8, 0).setToolTip( self.tr('Multiscale version of SSIM.')) self.table_widget.setItem(9, 0, QTableWidgetItem(self.tr('RASE'))) self.table_widget.setItem( 9, 2, QTableWidgetItem(QIcon('icons/low.svg'), '(0)')) self.table_widget.item(9, 0).setToolTip( self.tr('Relative average spectral error')) self.table_widget.setItem(10, 0, QTableWidgetItem(self.tr('SCC'))) self.table_widget.setItem( 10, 2, QTableWidgetItem(QIcon('icons/high.svg'), '(1)')) self.table_widget.item(10, 0).setToolTip( self.tr('Spatial Correlation Coefficient')) self.table_widget.setItem(11, 0, QTableWidgetItem(self.tr('UQI'))) self.table_widget.setItem( 11, 2, QTableWidgetItem(QIcon('icons/high.svg'), '(1)')) self.table_widget.item(11, 0).setToolTip( self.tr('Universal Image Quality Index')) self.table_widget.setItem(12, 0, QTableWidgetItem(self.tr('VIF-P'))) self.table_widget.setItem( 12, 2, QTableWidgetItem(QIcon('icons/high.svg'), '(1)')) self.table_widget.item(12, 0).setToolTip( self.tr('Pixel-based Visual Information Fidelity')) self.table_widget.setItem(13, 0, QTableWidgetItem(self.tr('SSIMulacra'))) self.table_widget.setItem( 13, 2, QTableWidgetItem(QIcon('icons/low.svg'), '(0)')) self.table_widget.item(13, 0).setToolTip( self.tr('Structural SIMilarity Unveiling Local ' 'And Compression Related Artifacts')) self.table_widget.setItem(14, 0, QTableWidgetItem(self.tr('Butteraugli'))) self.table_widget.setItem( 14, 2, QTableWidgetItem(QIcon('icons/low.svg'), '(0)')) self.table_widget.item(14, 0).setToolTip( self.tr('Estimate psychovisual error')) self.table_widget.setItem(15, 0, QTableWidgetItem(self.tr('Correlation'))) self.table_widget.setItem( 15, 2, QTableWidgetItem(QIcon('icons/high.svg'), '(1)')) self.table_widget.item(15, 0).setToolTip(self.tr('Histogram correlation')) self.table_widget.setItem(16, 0, QTableWidgetItem(self.tr('Chi-Square'))) self.table_widget.setItem( 16, 2, QTableWidgetItem(QIcon('icons/low.svg'), '(0)')) self.table_widget.item(16, 0).setToolTip(self.tr('Histogram Chi-Square')) self.table_widget.setItem(17, 0, QTableWidgetItem(self.tr('Chi-Square 2'))) self.table_widget.setItem( 17, 2, QTableWidgetItem(QIcon('icons/low.svg'), '(0)')) self.table_widget.item(17, 0).setToolTip(self.tr('Alternative Chi-Square')) self.table_widget.setItem(18, 0, QTableWidgetItem(self.tr('Intersection'))) self.table_widget.setItem( 18, 2, QTableWidgetItem(QIcon('icons/high.svg'), '(+' + u'\u221e' + ')')) self.table_widget.item(18, 0).setToolTip(self.tr('Histogram intersection')) self.table_widget.setItem(19, 0, QTableWidgetItem(self.tr('Hellinger'))) self.table_widget.setItem( 19, 2, QTableWidgetItem(QIcon('icons/low.svg'), '(0)')) self.table_widget.item(19, 0).setToolTip( self.tr('Histogram Hellinger distance')) self.table_widget.setItem(20, 0, QTableWidgetItem(self.tr('Divergence'))) self.table_widget.setItem( 20, 2, QTableWidgetItem(QIcon('icons/low.svg'), '(0)')) self.table_widget.item(20, 0).setToolTip( self.tr('Kullback-Leibler divergence')) for i in range(self.table_widget.rowCount()): modify_font(self.table_widget.item(i, 0), bold=True) self.table_widget.setSelectionMode(QAbstractItemView.SingleSelection) self.table_widget.setEditTriggers(QAbstractItemView.NoEditTriggers) self.table_widget.resizeColumnsToContents() self.table_widget.setMaximumWidth(250) self.table_widget.setAlternatingRowColors(True) self.stopped = False self.comp_label.setEnabled(False) self.normal_radio.setEnabled(False) self.difference_radio.setEnabled(False) self.ssim_radio.setEnabled(False) self.butter_radio.setEnabled(False) self.gray_check.setEnabled(False) self.equalize_check.setEnabled(False) self.metric_button.setEnabled(False) self.table_widget.setEnabled(False) load_button.clicked.connect(self.load) self.normal_radio.clicked.connect(self.change) self.difference_radio.clicked.connect(self.change) self.butter_radio.clicked.connect(self.change) self.gray_check.stateChanged.connect(self.change) self.equalize_check.stateChanged.connect(self.change) self.ssim_radio.clicked.connect(self.change) self.evidence_viewer.viewChanged.connect( self.reference_viewer.changeView) self.reference_viewer.viewChanged.connect( self.evidence_viewer.changeView) self.metric_button.clicked.connect(self.metrics) top_layout = QHBoxLayout() top_layout.addWidget(load_button) top_layout.addStretch() top_layout.addWidget(self.comp_label) top_layout.addWidget(self.normal_radio) top_layout.addWidget(self.difference_radio) top_layout.addWidget(self.ssim_radio) top_layout.addWidget(self.butter_radio) top_layout.addWidget(self.gray_check) top_layout.addWidget(self.equalize_check) metric_layout = QVBoxLayout() index_label = QLabel(self.tr('Image Quality Assessment')) index_label.setAlignment(Qt.AlignCenter) modify_font(index_label, bold=True) metric_layout.addWidget(index_label) metric_layout.addWidget(self.table_widget) metric_layout.addWidget(self.metric_button) center_layout = QHBoxLayout() center_layout.addWidget(self.evidence_viewer) center_layout.addWidget(self.reference_viewer) center_layout.addLayout(metric_layout) main_layout = QVBoxLayout() main_layout.addLayout(top_layout) main_layout.addLayout(center_layout) self.setLayout(main_layout)
class ComparisonWidget(ToolWidget): def __init__(self, filename, image, parent=None): super(ComparisonWidget, self).__init__(parent) load_button = QPushButton(self.tr('Load reference image...')) self.comp_label = QLabel(self.tr('Comparison:')) self.normal_radio = QRadioButton(self.tr('Normal')) self.normal_radio.setToolTip(self.tr('Show reference (raw pixels)')) self.normal_radio.setChecked(True) self.difference_radio = QRadioButton(self.tr('Difference')) self.difference_radio.setToolTip( self.tr('Show evidence/reference difference')) self.ssim_radio = QRadioButton(self.tr('SSIM Map')) self.ssim_radio.setToolTip(self.tr('Structure similarity quality map')) self.butter_radio = QRadioButton(self.tr('Butteraugli')) self.butter_radio.setToolTip( self.tr('Butteraugli spatial changes heatmap')) self.gray_check = QCheckBox(self.tr('Grayscale')) self.gray_check.setToolTip(self.tr('Show desaturated output')) self.equalize_check = QCheckBox(self.tr('Equalized')) self.equalize_check.setToolTip(self.tr('Apply histogram equalization')) self.last_radio = self.normal_radio self.metric_button = QPushButton(self.tr('Compute metrics')) self.metric_button.setToolTip( self.tr('Image quality assessment metrics')) self.evidence = image self.reference = self.difference = self.ssim_map = self.butter_map = None basename = os.path.basename(filename) self.evidence_viewer = ImageViewer( self.evidence, None, self.tr('Evidence: {}'.format(basename))) self.reference_viewer = ImageViewer(np.full_like(self.evidence, 127), None, self.tr('Reference')) self.table_widget = QTableWidget(21, 3) self.table_widget.setHorizontalHeaderLabels( [self.tr('Metric'), self.tr('Value'), self.tr('Better')]) self.table_widget.setItem(0, 0, QTableWidgetItem(self.tr('RMSE'))) self.table_widget.setItem( 0, 2, QTableWidgetItem(QIcon('icons/low.svg'), '(0)')) self.table_widget.item(0, 0).setToolTip( self. tr('Root Mean Square Error (RMSE) is commonly used to compare \n' 'the difference between the reference and evidence images \n' 'by directly computing the variation in pixel values. \n' 'The combined image is close to the reference image when \n' 'RMSE value is zero. RMSE is a good indicator of the spectral \n' 'quality of the reference image.')) self.table_widget.setItem(1, 0, QTableWidgetItem(self.tr('SAM'))) self.table_widget.setItem( 1, 2, QTableWidgetItem(QIcon('icons/low.svg'), '(0)')) self.table_widget.item(1, 0).setToolTip( self. tr('It computes the spectral angle between the pixel, vector of the \n' 'evidence image and reference image. It is worked out in either \n' 'degrees or radians. It is performed on a pixel-by-pixel base. \n' 'A SAM equal to zero denotes the absence of spectral distortion.' )) self.table_widget.setItem(2, 0, QTableWidgetItem(self.tr('ERGAS'))) self.table_widget.setItem( 2, 2, QTableWidgetItem(QIcon('icons/low.svg'), '(0)')) self.table_widget.item(2, 0).setToolTip( self. tr('It is used to compute the quality of reference image in terms \n' 'of normalized average error of each band of the reference image. \n' 'Increase in the value of ERGAS indicates distortion in the \n' 'reference image, lower value of ERGAS indicates that it is \n' 'similar to the reference image.')) self.table_widget.setItem(3, 0, QTableWidgetItem(self.tr('MB'))) self.table_widget.setItem( 3, 2, QTableWidgetItem(QIcon('icons/low.svg'), '(0)')) self.table_widget.item(3, 0).setToolTip( self. tr('Mean Bias is the difference between the mean of the evidence \n' 'image and reference image. The ideal value is zero and indicates \n' 'that the evidence and reference images are similar. Mean value \n' 'refers to the grey level of pixels in an image.')) self.table_widget.setItem(4, 0, QTableWidgetItem(self.tr('PFE'))) self.table_widget.setItem( 4, 2, QTableWidgetItem(QIcon('icons/low.svg'), '(0)')) self.table_widget.item(4, 0).setToolTip( self. tr('It computes the norm of the difference between the corresponding \n' 'pixels of the reference and fused image to the norm of the reference \n' 'image. When the calculated value is zero, it indicates that both the \n' 'reference and fused images are similar and value will be increased \n' 'when the merged image is not similar to the reference image.')) self.table_widget.setItem(5, 0, QTableWidgetItem(self.tr('PSNR'))) self.table_widget.setItem( 5, 2, QTableWidgetItem(QIcon('icons/high.svg'), '(+' + u'\u221e' + ')')) self.table_widget.item(5, 0).setToolTip( self. tr('It is widely used metric it is computed by the number of gray levels \n' 'in the image divided by the corresponding pixels in the evidence and \n' 'the reference images. When the value is high, both images are similar.' )) self.table_widget.setItem(6, 0, QTableWidgetItem(self.tr('PSNR-B'))) self.table_widget.setItem( 6, 2, QTableWidgetItem(QIcon('icons/high.svg'), '(+' + u'\u221e' + ')')) self.table_widget.item(6, 0).setToolTip( self.tr('PSNR with Blocking Effect Factor.')) self.table_widget.setItem(7, 0, QTableWidgetItem(self.tr('SSIM'))) self.table_widget.setItem( 7, 2, QTableWidgetItem(QIcon('icons/high.svg'), '(1)')) self.table_widget.item(7, 0).setToolTip( self. tr('SSIM is used to compare the local patterns of pixel intensities between \n' ' the reference and fused images. The range varies between -1 to 1. \n' 'The value 1 indicates the reference and fused images are similar.' )) self.table_widget.setItem(8, 0, QTableWidgetItem(self.tr('MS-SSIM'))) self.table_widget.setItem( 8, 2, QTableWidgetItem(QIcon('icons/high.svg'), '(1)')) self.table_widget.item(8, 0).setToolTip( self.tr('Multiscale version of SSIM.')) self.table_widget.setItem(9, 0, QTableWidgetItem(self.tr('RASE'))) self.table_widget.setItem( 9, 2, QTableWidgetItem(QIcon('icons/low.svg'), '(0)')) self.table_widget.item(9, 0).setToolTip( self.tr('Relative average spectral error')) self.table_widget.setItem(10, 0, QTableWidgetItem(self.tr('SCC'))) self.table_widget.setItem( 10, 2, QTableWidgetItem(QIcon('icons/high.svg'), '(1)')) self.table_widget.item(10, 0).setToolTip( self.tr('Spatial Correlation Coefficient')) self.table_widget.setItem(11, 0, QTableWidgetItem(self.tr('UQI'))) self.table_widget.setItem( 11, 2, QTableWidgetItem(QIcon('icons/high.svg'), '(1)')) self.table_widget.item(11, 0).setToolTip( self.tr('Universal Image Quality Index')) self.table_widget.setItem(12, 0, QTableWidgetItem(self.tr('VIF-P'))) self.table_widget.setItem( 12, 2, QTableWidgetItem(QIcon('icons/high.svg'), '(1)')) self.table_widget.item(12, 0).setToolTip( self.tr('Pixel-based Visual Information Fidelity')) self.table_widget.setItem(13, 0, QTableWidgetItem(self.tr('SSIMulacra'))) self.table_widget.setItem( 13, 2, QTableWidgetItem(QIcon('icons/low.svg'), '(0)')) self.table_widget.item(13, 0).setToolTip( self.tr('Structural SIMilarity Unveiling Local ' 'And Compression Related Artifacts')) self.table_widget.setItem(14, 0, QTableWidgetItem(self.tr('Butteraugli'))) self.table_widget.setItem( 14, 2, QTableWidgetItem(QIcon('icons/low.svg'), '(0)')) self.table_widget.item(14, 0).setToolTip( self.tr('Estimate psychovisual error')) self.table_widget.setItem(15, 0, QTableWidgetItem(self.tr('Correlation'))) self.table_widget.setItem( 15, 2, QTableWidgetItem(QIcon('icons/high.svg'), '(1)')) self.table_widget.item(15, 0).setToolTip(self.tr('Histogram correlation')) self.table_widget.setItem(16, 0, QTableWidgetItem(self.tr('Chi-Square'))) self.table_widget.setItem( 16, 2, QTableWidgetItem(QIcon('icons/low.svg'), '(0)')) self.table_widget.item(16, 0).setToolTip(self.tr('Histogram Chi-Square')) self.table_widget.setItem(17, 0, QTableWidgetItem(self.tr('Chi-Square 2'))) self.table_widget.setItem( 17, 2, QTableWidgetItem(QIcon('icons/low.svg'), '(0)')) self.table_widget.item(17, 0).setToolTip(self.tr('Alternative Chi-Square')) self.table_widget.setItem(18, 0, QTableWidgetItem(self.tr('Intersection'))) self.table_widget.setItem( 18, 2, QTableWidgetItem(QIcon('icons/high.svg'), '(+' + u'\u221e' + ')')) self.table_widget.item(18, 0).setToolTip(self.tr('Histogram intersection')) self.table_widget.setItem(19, 0, QTableWidgetItem(self.tr('Hellinger'))) self.table_widget.setItem( 19, 2, QTableWidgetItem(QIcon('icons/low.svg'), '(0)')) self.table_widget.item(19, 0).setToolTip( self.tr('Histogram Hellinger distance')) self.table_widget.setItem(20, 0, QTableWidgetItem(self.tr('Divergence'))) self.table_widget.setItem( 20, 2, QTableWidgetItem(QIcon('icons/low.svg'), '(0)')) self.table_widget.item(20, 0).setToolTip( self.tr('Kullback-Leibler divergence')) for i in range(self.table_widget.rowCount()): modify_font(self.table_widget.item(i, 0), bold=True) self.table_widget.setSelectionMode(QAbstractItemView.SingleSelection) self.table_widget.setEditTriggers(QAbstractItemView.NoEditTriggers) self.table_widget.resizeColumnsToContents() self.table_widget.setMaximumWidth(250) self.table_widget.setAlternatingRowColors(True) self.stopped = False self.comp_label.setEnabled(False) self.normal_radio.setEnabled(False) self.difference_radio.setEnabled(False) self.ssim_radio.setEnabled(False) self.butter_radio.setEnabled(False) self.gray_check.setEnabled(False) self.equalize_check.setEnabled(False) self.metric_button.setEnabled(False) self.table_widget.setEnabled(False) load_button.clicked.connect(self.load) self.normal_radio.clicked.connect(self.change) self.difference_radio.clicked.connect(self.change) self.butter_radio.clicked.connect(self.change) self.gray_check.stateChanged.connect(self.change) self.equalize_check.stateChanged.connect(self.change) self.ssim_radio.clicked.connect(self.change) self.evidence_viewer.viewChanged.connect( self.reference_viewer.changeView) self.reference_viewer.viewChanged.connect( self.evidence_viewer.changeView) self.metric_button.clicked.connect(self.metrics) top_layout = QHBoxLayout() top_layout.addWidget(load_button) top_layout.addStretch() top_layout.addWidget(self.comp_label) top_layout.addWidget(self.normal_radio) top_layout.addWidget(self.difference_radio) top_layout.addWidget(self.ssim_radio) top_layout.addWidget(self.butter_radio) top_layout.addWidget(self.gray_check) top_layout.addWidget(self.equalize_check) metric_layout = QVBoxLayout() index_label = QLabel(self.tr('Image Quality Assessment')) index_label.setAlignment(Qt.AlignCenter) modify_font(index_label, bold=True) metric_layout.addWidget(index_label) metric_layout.addWidget(self.table_widget) metric_layout.addWidget(self.metric_button) center_layout = QHBoxLayout() center_layout.addWidget(self.evidence_viewer) center_layout.addWidget(self.reference_viewer) center_layout.addLayout(metric_layout) main_layout = QVBoxLayout() main_layout.addLayout(top_layout) main_layout.addLayout(center_layout) self.setLayout(main_layout) def load(self): filename, basename, reference = load_image(self) if filename is None: return if reference.shape != self.evidence.shape: QMessageBox.critical( self, self.tr('Error'), self.tr('Evidence and reference must have the same size!')) return self.reference = reference self.reference_viewer.set_title( self.tr('Reference: {}'.format(basename))) self.difference = norm_mat(cv.absdiff(self.evidence, self.reference)) self.comp_label.setEnabled(True) self.normal_radio.setEnabled(True) self.difference_radio.setEnabled(True) self.ssim_radio.setEnabled(False) self.butter_radio.setEnabled(False) self.gray_check.setEnabled(True) self.equalize_check.setEnabled(True) self.metric_button.setEnabled(True) for i in range(self.table_widget.rowCount()): self.table_widget.setItem(i, 1, QTableWidgetItem()) self.normal_radio.setChecked(True) self.table_widget.setEnabled(False) self.change() def change(self): if self.normal_radio.isChecked(): result = self.reference self.gray_check.setEnabled(False) self.equalize_check.setEnabled(False) self.last_radio = self.normal_radio elif self.difference_radio.isChecked(): result = self.difference self.gray_check.setEnabled(True) self.equalize_check.setEnabled(True) self.last_radio = self.difference_radio elif self.ssim_radio.isChecked(): result = self.ssim_map self.gray_check.setEnabled(False) self.equalize_check.setEnabled(True) self.last_radio = self.ssim_radio elif self.butter_radio.isChecked(): result = self.butter_map self.gray_check.setEnabled(True) self.equalize_check.setEnabled(False) self.last_radio = self.butter_radio else: self.last_radio.setChecked(True) return if self.equalize_check.isChecked(): result = equalize_img(result) if self.gray_check.isChecked(): result = desaturate(result) self.reference_viewer.update_original(result) def metrics(self): progress = QProgressDialog(self.tr('Computing metrics...'), self.tr('Cancel'), 1, self.table_widget.rowCount(), self) progress.canceled.connect(self.cancel) progress.setWindowModality(Qt.WindowModal) img1 = cv.cvtColor(self.evidence, cv.COLOR_BGR2GRAY) img2 = cv.cvtColor(self.reference, cv.COLOR_BGR2GRAY) x = img1.astype(np.float64) y = img2.astype(np.float64) rmse = self.rmse(x, y) progress.setValue(1) if self.stopped: return sam = sewar.sam(img1, img2) progress.setValue(2) if self.stopped: return ergas = sewar.ergas(img1, img2) progress.setValue(3) if self.stopped: return mb = self.mb(x, y) progress.setValue(4) if self.stopped: return pfe = self.pfe(x, y) progress.setValue(5) if self.stopped: return psnr = self.psnr(x, y) progress.setValue(6) if self.stopped: return try: psnrb = sewar.psnrb(img1, img2) except NameError: # FIXME: C'\`e un bug in psnrb (https://github.com/andrewekhalel/sewar/issues/17) psnrb = 0 progress.setValue(7) if self.stopped: return ssim, self.ssim_map = self.ssim(x, y) progress.setValue(8) if self.stopped: return mssim = sewar.msssim(img1, img2).real progress.setValue(9) if self.stopped: return rase = sewar.rase(img1, img2) progress.setValue(10) if self.stopped: return scc = sewar.scc(img1, img2) progress.setValue(11) if self.stopped: return uqi = sewar.uqi(img1, img2) progress.setValue(12) if self.stopped: return vifp = sewar.vifp(img1, img2) progress.setValue(13) if self.stopped: return ssimul = self.ssimul(img1, img2) progress.setValue(14) if self.stopped: return butter, self.butter_map = self.butter(img1, img2) progress.setValue(15) if self.stopped: return sizes = [256, 256, 256] ranges = [0, 256] * 3 channels = [0, 1, 2] hist1 = cv.calcHist([self.evidence], channels, None, sizes, ranges) hist2 = cv.calcHist([self.reference], channels, None, sizes, ranges) correlation = cv.compareHist(hist1, hist2, cv.HISTCMP_CORREL) progress.setValue(16) if self.stopped: return chi_square = cv.compareHist(hist1, hist2, cv.HISTCMP_CHISQR) progress.setValue(17) if self.stopped: return chi_square2 = cv.compareHist(hist1, hist2, cv.HISTCMP_CHISQR_ALT) progress.setValue(18) if self.stopped: return intersection = cv.compareHist(hist1, hist2, cv.HISTCMP_INTERSECT) progress.setValue(19) if self.stopped: return hellinger = cv.compareHist(hist1, hist2, cv.HISTCMP_HELLINGER) progress.setValue(20) if self.stopped: return divergence = cv.compareHist(hist1, hist2, cv.HISTCMP_KL_DIV) progress.setValue(21) self.table_widget.setItem(0, 1, QTableWidgetItem('{:.2f}'.format(rmse))) self.table_widget.setItem(1, 1, QTableWidgetItem('{:.4f}'.format(sam))) self.table_widget.setItem(2, 1, QTableWidgetItem('{:.2f}'.format(ergas))) self.table_widget.setItem(3, 1, QTableWidgetItem('{:.4f}'.format(mb))) self.table_widget.setItem(4, 1, QTableWidgetItem('{:.2f}'.format(pfe))) if psnr > 0: self.table_widget.setItem( 5, 1, QTableWidgetItem('{:.2f} dB'.format(psnr))) else: self.table_widget.setItem( 5, 1, QTableWidgetItem('+' + u'\u221e' + ' dB')) self.table_widget.setItem(6, 1, QTableWidgetItem('{:.2f}'.format(psnrb))) self.table_widget.setItem(7, 1, QTableWidgetItem('{:.4f}'.format(ssim))) self.table_widget.setItem(8, 1, QTableWidgetItem('{:.4f}'.format(mssim))) self.table_widget.setItem(9, 1, QTableWidgetItem('{:.2f}'.format(rase))) self.table_widget.setItem(10, 1, QTableWidgetItem('{:.4f}'.format(scc))) self.table_widget.setItem(11, 1, QTableWidgetItem('{:.4f}'.format(uqi))) self.table_widget.setItem(12, 1, QTableWidgetItem('{:.4f}'.format(vifp))) self.table_widget.setItem(13, 1, QTableWidgetItem('{:.4f}'.format(ssimul))) self.table_widget.setItem(14, 1, QTableWidgetItem('{:.2f}'.format(butter))) self.table_widget.setItem( 15, 1, QTableWidgetItem('{:.2f}'.format(correlation))) self.table_widget.setItem( 16, 1, QTableWidgetItem('{:.2f}'.format(chi_square))) self.table_widget.setItem( 17, 1, QTableWidgetItem('{:.2f}'.format(chi_square2))) self.table_widget.setItem( 18, 1, QTableWidgetItem('{:.2f}'.format(intersection))) self.table_widget.setItem(19, 1, QTableWidgetItem('{:.2f}'.format(hellinger))) self.table_widget.setItem( 20, 1, QTableWidgetItem('{:.2f}'.format(divergence))) self.table_widget.resizeColumnsToContents() self.table_widget.setEnabled(True) self.metric_button.setEnabled(False) self.ssim_radio.setEnabled(True) self.butter_radio.setEnabled(True) def cancel(self): self.stopped = True @staticmethod def rmse(x, y): return np.sqrt(np.mean(np.square(x - y))) @staticmethod def mb(x, y): mx = np.mean(x) my = np.mean(y) return (mx - my) / mx @staticmethod def pfe(x, y): return np.linalg.norm(x - y) / np.linalg.norm(x) * 100 @staticmethod def ssim(x, y): c1 = 6.5025 c2 = 58.5225 k = (11, 11) s = 1.5 x2 = x**2 y2 = y**2 xy = x * y mu_x = cv.GaussianBlur(x, k, s) mu_y = cv.GaussianBlur(y, k, s) mu_x2 = mu_x**2 mu_y2 = mu_y**2 mu_xy = mu_x * mu_y s_x2 = cv.GaussianBlur(x2, k, s) - mu_x2 s_y2 = cv.GaussianBlur(y2, k, s) - mu_y2 s_xy = cv.GaussianBlur(xy, k, s) - mu_xy t1 = 2 * mu_xy + c1 t2 = 2 * s_xy + c2 t3 = t1 * t2 t1 = mu_x2 + mu_y2 + c1 t2 = s_x2 + s_y2 + c2 t1 *= t2 ssim_map = cv.divide(t3, t1) ssim = cv.mean(ssim_map)[0] return ssim, 255 - norm_mat(ssim_map, to_bgr=True) @staticmethod def corr(x, y): return np.corrcoef(x, y)[0, 1] @staticmethod def psnr(x, y): k = np.mean(np.square(x - y)) if k == 0: return -1 return 20 * math.log10((255**2) / k) @staticmethod def butter(x, y): try: exe = butter_exe() if exe is None: raise FileNotFoundError temp_dir = QTemporaryDir() if temp_dir.isValid(): filename1 = os.path.join(temp_dir.path(), 'img1.png') cv.imwrite(filename1, x) filename2 = os.path.join(temp_dir.path(), 'img2.png') cv.imwrite(filename2, y) filename3 = os.path.join(temp_dir.path(), 'map.ppm') p = run([exe, filename1, filename2, filename3], stdout=PIPE) value = float(p.stdout) heatmap = cv.imread(filename3, cv.IMREAD_COLOR) return value, heatmap except FileNotFoundError: return -1, cv.cvtColor(np.full_like(x, 127), cv.COLOR_GRAY2BGR) @staticmethod def ssimul(x, y): try: exe = ssimul_exe() if exe is None: raise FileNotFoundError temp_dir = QTemporaryDir() if temp_dir.isValid(): filename1 = os.path.join(temp_dir.path(), 'img1.png') cv.imwrite(filename1, x) filename2 = os.path.join(temp_dir.path(), 'img2.png') cv.imwrite(filename2, y) p = run([exe, filename1, filename2], stdout=PIPE) value = float(p.stdout) return value except FileNotFoundError: return -1
def _add_toolbar_tools(self): """Add tools.""" # TODO: Outdated - to be removed from matplotlib.backend_tools import ToolToggleBase # ToolBase class ToolPointPosition(ToolToggleBase): """Tools.""" default_keymap = 'Ctrl+p' description = 'Click to get point coordinate printed' default_toggled = False image = None # str(imgs_path) def __init__(self, *args, parent=None, **kwargs): super().__init__(*args, **kwargs) if parent is None: raise ('Pass a parent') self.parent = parent def enable(self, *args): self.parent.options.report_point_position = True def disable(self, *args): self.parent.options.report_point_position = False fig = self.figure imgs_path = self.imgs_path # pylint: disable=attribute-defined-outside-init toolbar = self.toolbar = fig.canvas.manager.toolbar # Get tool manager # TODO: Remove use of tool manager just use PySide2 bare as below # ToolbarQt --- https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/backends/backend_qt5.py tm = fig.canvas.manager.toolmanager self.tm = tm # Tool: Print point location ToolPointPosition.image = str(imgs_path / 'click.png') with warnings.catch_warnings(): warnings.simplefilter("ignore") tm.add_tool("Point_position", ToolPointPosition, parent=self) fig.canvas.manager.toolbar.add_tool(tm.get_tool("Point_position"), "toolgroup") # Tool: Copy to Clipboard from matplotlib.backend_tools import ToolCopyToClipboard ToolCopyToClipboard.image = str(imgs_path / 'copy.png') with warnings.catch_warnings(): warnings.simplefilter("ignore") # OVvrwties Ctrl+C and issues warning tm.add_tool("Copy_to_clipboard", ToolCopyToClipboard) fig.canvas.manager.toolbar.add_tool(tm.get_tool("Copy_to_clipboard"), "toolgroup") if 1: # add QT Pieces toolbar.action_ascale = QAction( QIcon(str(imgs_path / 'auto_zoom.png')), 'Auto scale', toolbar) toolbar.action_ascale.setShortcut('A') toolbar.action_ascale.setShortcutContext(Qt.WindowShortcut) toolbar.action_ascale.setStatusTip('Autoscale') toolbar.action_ascale.triggered.connect(self.auto_scale) toolbar.addAction(toolbar.action_ascale) # Status Bar: Second label to report figManager = fig.canvas.manager # plt.get_current_fig_manager() status_bar = figManager.window.statusBar() self._status_label_2 = QLabel(status_bar) self._status_label_2.setText('') status_bar.addWidget(self._status_label_2)
import sys from PySide2.QtWidgets import QApplication, QLabel app = QApplication([]) label = QLabel("Hello World!") label.show() print('hello world') app.exec_()
class MainWindow(QMainWindow): def __init__(self, font=QtGui.QFontMetrics(QtGui.QFont()), screen_size=QtCore.QSize()): super().__init__() self.screen = screen_size self.font_metric = font self.setWindowTitle('OpenMC Plot Explorer') def loadGui(self): self.pixmap = None self.zoom = 100 self.loadModel() # Create viewing area self.frame = QScrollArea(self) cw = QWidget() self.frame.setCornerWidget(cw) self.frame.setAlignment(QtCore.Qt.AlignCenter) self.frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.setCentralWidget(self.frame) # connect pinch gesture (OSX) self.grabGesture(QtCore.Qt.PinchGesture) # Create plot image self.plotIm = PlotImage(self.model, self.frame, self) self.frame.setWidget(self.plotIm) # Dock self.dock = DomainDock(self.model, self.font_metric, self) self.dock.setObjectName("Domain Options Dock") self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.dock) # Tally Dock self.tallyDock = TallyDock(self.model, self.font_metric, self) self.tallyDock.update() self.tallyDock.setObjectName("Tally Options Dock") self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.tallyDock) # Color DialogtallyDock self.colorDialog = ColorDialog(self.model, self.font_metric, self) self.colorDialog.hide() # Tools self.exportDataDialog = ExportDataDialog(self.model, self.font_metric, self) # Restore Window Settings self.restoreWindowSettings() # Create menubar self.createMenuBar() self.updateEditMenu() # Status Bar self.coord_label = QLabel() self.statusBar().addPermanentWidget(self.coord_label) self.coord_label.hide() # Keyboard overlay self.shortcutOverlay = ShortcutsOverlay(self) self.shortcutOverlay.hide() # Load Plot self.statusBar().showMessage('Generating Plot...') self.dock.updateDock() self.tallyDock.update() self.colorDialog.updateDialogValues() self.statusBar().showMessage('') # Timer allows GUI to render before plot finishes loading QtCore.QTimer.singleShot(0, self.plotIm.generatePixmap) QtCore.QTimer.singleShot(0, self.showCurrentView) def event(self, event): # use pinch event to update zoom if isinstance(event, QGestureEvent): pinch = event.gesture(QtCore.Qt.PinchGesture) self.editZoom(self.zoom * pinch.scaleFactor()) if isinstance(event, QKeyEvent) and hasattr(self, "shortcutOverlay"): self.shortcutOverlay.event(event) return super().event(event) def show(self): super().show() self.plotIm._resize() def toggleShortcuts(self): if self.shortcutOverlay.isVisible(): self.shortcutOverlay.close() else: self.shortcutOverlay.move(0, 0) self.shortcutOverlay.resize(self.width(), self.height()) self.shortcutOverlay.show() # Create and update menus: def createMenuBar(self): self.mainMenu = self.menuBar() # File Menu self.reloadModelAction = QAction("&Reload model...", self) self.reloadModelAction.setShortcut("Ctrl+Shift+R") self.reloadModelAction.setToolTip("Reload current model") self.reloadModelAction.setStatusTip("Reload current model") reload_connector = partial(self.loadModel, reload=True) self.reloadModelAction.triggered.connect(reload_connector) self.saveImageAction = QAction("&Save Image As...", self) self.saveImageAction.setShortcut("Ctrl+Shift+S") self.saveImageAction.setToolTip('Save plot image') self.saveImageAction.setStatusTip('Save plot image') self.saveImageAction.triggered.connect(self.saveImage) self.saveViewAction = QAction("Save &View...", self) self.saveViewAction.setShortcut(QtGui.QKeySequence.Save) self.saveViewAction.setStatusTip('Save current view settings') self.saveViewAction.triggered.connect(self.saveView) self.openAction = QAction("&Open View...", self) self.openAction.setShortcut(QtGui.QKeySequence.Open) self.openAction.setToolTip('Open saved view settings') self.openAction.setStatusTip('Open saved view settings') self.openAction.triggered.connect(self.openView) self.quitAction = QAction("&Quit", self) self.quitAction.setShortcut(QtGui.QKeySequence.Quit) self.quitAction.setToolTip('Quit OpenMC Plot Explorer') self.quitAction.setStatusTip('Quit OpenMC Plot Explorer') self.quitAction.triggered.connect(self.close) self.exportDataAction = QAction('E&xport...', self) self.exportDataAction.setToolTip('Export model and tally data VTK') self.setStatusTip('Export current model and tally data to VTK') self.exportDataAction.triggered.connect(self.exportTallyData) if not _HAVE_VTK: self.exportDataAction.setEnabled(False) self.exportDataAction.setToolTip( "Disabled: VTK Python module is not installed") self.fileMenu = self.mainMenu.addMenu('&File') self.fileMenu.addAction(self.reloadModelAction) self.fileMenu.addAction(self.saveImageAction) self.fileMenu.addAction(self.exportDataAction) self.fileMenu.addSeparator() self.fileMenu.addAction(self.saveViewAction) self.fileMenu.addAction(self.openAction) self.fileMenu.addSeparator() self.fileMenu.addAction(self.quitAction) # Data Menu self.openStatePointAction = QAction("&Open statepoint...", self) self.openStatePointAction.setToolTip('Open statepoint file') self.openStatePointAction.triggered.connect(self.openStatePoint) self.dataMenu = self.mainMenu.addMenu('D&ata') self.dataMenu.addAction(self.openStatePointAction) self.updateDataMenu() # Edit Menu self.applyAction = QAction("&Apply Changes", self) self.applyAction.setShortcut("Ctrl+Return") self.applyAction.setToolTip('Generate new view with changes applied') self.applyAction.setStatusTip('Generate new view with changes applied') self.applyAction.triggered.connect(self.applyChanges) self.undoAction = QAction('&Undo', self) self.undoAction.setShortcut(QtGui.QKeySequence.Undo) self.undoAction.setToolTip('Undo') self.undoAction.setStatusTip('Undo last plot view change') self.undoAction.setDisabled(True) self.undoAction.triggered.connect(self.undo) self.redoAction = QAction('&Redo', self) self.redoAction.setDisabled(True) self.redoAction.setToolTip('Redo') self.redoAction.setStatusTip('Redo last plot view change') self.redoAction.setShortcut(QtGui.QKeySequence.Redo) self.redoAction.triggered.connect(self.redo) self.restoreAction = QAction("&Restore Default Plot", self) self.restoreAction.setShortcut("Ctrl+R") self.restoreAction.setToolTip('Restore to default plot view') self.restoreAction.setStatusTip('Restore to default plot view') self.restoreAction.triggered.connect(self.restoreDefault) self.editMenu = self.mainMenu.addMenu('&Edit') self.editMenu.addAction(self.applyAction) self.editMenu.addSeparator() self.editMenu.addAction(self.undoAction) self.editMenu.addAction(self.redoAction) self.editMenu.addSeparator() self.editMenu.addAction(self.restoreAction) self.editMenu.addSeparator() self.editMenu.aboutToShow.connect(self.updateEditMenu) # Edit -> Basis Menu self.xyAction = QAction('&xy ', self) self.xyAction.setCheckable(True) self.xyAction.setShortcut('Alt+X') self.xyAction.setToolTip('Change to xy basis') self.xyAction.setStatusTip('Change to xy basis') xy_connector = partial(self.editBasis, 'xy', apply=True) self.xyAction.triggered.connect(xy_connector) self.xzAction = QAction('x&z ', self) self.xzAction.setCheckable(True) self.xzAction.setShortcut('Alt+Z') self.xzAction.setToolTip('Change to xz basis') self.xzAction.setStatusTip('Change to xz basis') xz_connector = partial(self.editBasis, 'xz', apply=True) self.xzAction.triggered.connect(xz_connector) self.yzAction = QAction('&yz ', self) self.yzAction.setCheckable(True) self.yzAction.setShortcut('Alt+Y') self.yzAction.setToolTip('Change to yz basis') self.yzAction.setStatusTip('Change to yz basis') yz_connector = partial(self.editBasis, 'yz', apply=True) self.yzAction.triggered.connect(yz_connector) self.basisMenu = self.editMenu.addMenu('&Basis') self.basisMenu.addAction(self.xyAction) self.basisMenu.addAction(self.xzAction) self.basisMenu.addAction(self.yzAction) self.basisMenu.aboutToShow.connect(self.updateBasisMenu) # Edit -> Color By Menu self.cellAction = QAction('&Cell', self) self.cellAction.setCheckable(True) self.cellAction.setShortcut('Alt+C') self.cellAction.setToolTip('Color by cell') self.cellAction.setStatusTip('Color plot by cell') cell_connector = partial(self.editColorBy, 'cell', apply=True) self.cellAction.triggered.connect(cell_connector) self.materialAction = QAction('&Material', self) self.materialAction.setCheckable(True) self.materialAction.setShortcut('Alt+M') self.materialAction.setToolTip('Color by material') self.materialAction.setStatusTip('Color plot by material') material_connector = partial(self.editColorBy, 'material', apply=True) self.materialAction.triggered.connect(material_connector) self.temperatureAction = QAction('&Temperature', self) self.temperatureAction.setCheckable(True) self.temperatureAction.setShortcut('Alt+T') self.temperatureAction.setToolTip('Color by temperature') self.temperatureAction.setStatusTip('Color plot by temperature') temp_connector = partial(self.editColorBy, 'temperature', apply=True) self.temperatureAction.triggered.connect(temp_connector) self.densityAction = QAction('&Density', self) self.densityAction.setCheckable(True) self.densityAction.setShortcut('Alt+D') self.densityAction.setToolTip('Color by density') self.densityAction.setStatusTip('Color plot by density') density_connector = partial(self.editColorBy, 'density', apply=True) self.densityAction.triggered.connect(density_connector) self.colorbyMenu = self.editMenu.addMenu('&Color By') self.colorbyMenu.addAction(self.cellAction) self.colorbyMenu.addAction(self.materialAction) self.colorbyMenu.addAction(self.temperatureAction) self.colorbyMenu.addAction(self.densityAction) self.colorbyMenu.aboutToShow.connect(self.updateColorbyMenu) self.editMenu.addSeparator() # Edit -> Other Options self.maskingAction = QAction('Enable &Masking', self) self.maskingAction.setShortcut('Ctrl+M') self.maskingAction.setCheckable(True) self.maskingAction.setToolTip('Toggle masking') self.maskingAction.setStatusTip('Toggle whether masking is enabled') masking_connector = partial(self.toggleMasking, apply=True) self.maskingAction.toggled.connect(masking_connector) self.editMenu.addAction(self.maskingAction) self.highlightingAct = QAction('Enable High&lighting', self) self.highlightingAct.setShortcut('Ctrl+L') self.highlightingAct.setCheckable(True) self.highlightingAct.setToolTip('Toggle highlighting') self.highlightingAct.setStatusTip('Toggle whether ' 'highlighting is enabled') highlight_connector = partial(self.toggleHighlighting, apply=True) self.highlightingAct.toggled.connect(highlight_connector) self.editMenu.addAction(self.highlightingAct) self.overlapAct = QAction('Enable Overlap Coloring', self) self.overlapAct.setShortcut('Ctrl+P') self.overlapAct.setCheckable(True) self.overlapAct.setToolTip('Toggle overlapping regions') self.overlapAct.setStatusTip('Toggle display of overlapping ' 'regions when enabled') overlap_connector = partial(self.toggleOverlaps, apply=True) self.overlapAct.toggled.connect(overlap_connector) self.editMenu.addAction(self.overlapAct) self.outlineAct = QAction('Enable Domain Outlines', self) self.outlineAct.setShortcut('Ctrl+U') self.outlineAct.setCheckable(True) self.outlineAct.setToolTip('Display Cell/Material Boundaries') self.outlineAct.setStatusTip('Toggle display of domain ' 'outlines when enabled') outline_connector = partial(self.toggleOutlines, apply=True) self.outlineAct.toggled.connect(outline_connector) self.editMenu.addAction(self.outlineAct) # View Menu self.dockAction = QAction('Hide &Dock', self) self.dockAction.setShortcut("Ctrl+D") self.dockAction.setToolTip('Toggle dock visibility') self.dockAction.setStatusTip('Toggle dock visibility') self.dockAction.triggered.connect(self.toggleDockView) self.tallyDockAction = QAction('Tally &Dock', self) self.tallyDockAction.setShortcut("Ctrl+T") self.tallyDockAction.setToolTip('Toggle tally dock visibility') self.tallyDockAction.setStatusTip('Toggle tally dock visibility') self.tallyDockAction.triggered.connect(self.toggleTallyDockView) self.zoomAction = QAction('&Zoom...', self) self.zoomAction.setShortcut('Alt+Shift+Z') self.zoomAction.setToolTip('Edit zoom factor') self.zoomAction.setStatusTip('Edit zoom factor') self.zoomAction.triggered.connect(self.editZoomAct) self.viewMenu = self.mainMenu.addMenu('&View') self.viewMenu.addAction(self.dockAction) self.viewMenu.addAction(self.tallyDockAction) self.viewMenu.addSeparator() self.viewMenu.addAction(self.zoomAction) self.viewMenu.aboutToShow.connect(self.updateViewMenu) # Window Menu self.mainWindowAction = QAction('&Main Window', self) self.mainWindowAction.setCheckable(True) self.mainWindowAction.setToolTip('Bring main window to front') self.mainWindowAction.setStatusTip('Bring main window to front') self.mainWindowAction.triggered.connect(self.showMainWindow) self.colorDialogAction = QAction('Color &Options', self) self.colorDialogAction.setCheckable(True) self.colorDialogAction.setToolTip('Bring Color Dialog to front') self.colorDialogAction.setStatusTip('Bring Color Dialog to front') self.colorDialogAction.triggered.connect(self.showColorDialog) # Keyboard Shortcuts Overlay self.keyboardShortcutsAction = QAction("&Keyboard Shortcuts...", self) self.keyboardShortcutsAction.setShortcut("?") self.keyboardShortcutsAction.setToolTip("Display Keyboard Shortcuts") self.keyboardShortcutsAction.setStatusTip("Display Keyboard Shortcuts") self.keyboardShortcutsAction.triggered.connect(self.toggleShortcuts) self.windowMenu = self.mainMenu.addMenu('&Window') self.windowMenu.addAction(self.mainWindowAction) self.windowMenu.addAction(self.colorDialogAction) self.windowMenu.addAction(self.keyboardShortcutsAction) self.windowMenu.aboutToShow.connect(self.updateWindowMenu) def updateEditMenu(self): changed = self.model.currentView != self.model.defaultView self.restoreAction.setDisabled(not changed) self.maskingAction.setChecked(self.model.currentView.masking) self.highlightingAct.setChecked(self.model.currentView.highlighting) self.outlineAct.setChecked(self.model.currentView.outlines) num_previous_views = len(self.model.previousViews) self.undoAction.setText('&Undo ({})'.format(num_previous_views)) num_subsequent_views = len(self.model.subsequentViews) self.redoAction.setText('&Redo ({})'.format(num_subsequent_views)) def updateBasisMenu(self): self.xyAction.setChecked(self.model.currentView.basis == 'xy') self.xzAction.setChecked(self.model.currentView.basis == 'xz') self.yzAction.setChecked(self.model.currentView.basis == 'yz') def updateColorbyMenu(self): cv = self.model.currentView self.cellAction.setChecked(cv.colorby == 'cell') self.materialAction.setChecked(cv.colorby == 'material') self.temperatureAction.setChecked(cv.colorby == 'temperature') self.densityAction.setChecked(cv.colorby == 'density') def updateViewMenu(self): if self.dock.isVisible(): self.dockAction.setText('Hide &Dock') else: self.dockAction.setText('Show &Dock') def updateWindowMenu(self): self.colorDialogAction.setChecked(self.colorDialog.isActiveWindow()) self.mainWindowAction.setChecked(self.isActiveWindow()) # Menu and shared methods def loadModel(self, reload=False): if reload: self.resetModels() else: # create new plot model self.model = PlotModel() self.restoreModelSettings() # update plot and model settings self.updateRelativeBases() self.cellsModel = DomainTableModel(self.model.activeView.cells) self.materialsModel = DomainTableModel(self.model.activeView.materials) if reload: loader_thread = Thread(target=_openmcReload) loader_thread.start() while loader_thread.is_alive(): self.statusBar().showMessage("Reloading model...") QApplication.processEvents() self.plotIm.model = self.model self.applyChanges() def saveImage(self): filename, ext = QFileDialog.getSaveFileName(self, "Save Plot Image", "untitled", "Images (*.png)") if filename: if "." not in filename: filename += ".png" self.plotIm.figure.savefig(filename, transparent=True) self.statusBar().showMessage('Plot Image Saved', 5000) def saveView(self): filename, ext = QFileDialog.getSaveFileName(self, "Save View Settings", "untitled", "View Settings (*.pltvw)") if filename: if "." not in filename: filename += ".pltvw" saved = { 'version': self.model.version, 'current': self.model.currentView } with open(filename, 'wb') as file: pickle.dump(saved, file) def openView(self): filename, ext = QFileDialog.getOpenFileName(self, "Open View Settings", ".", "*.pltvw") if filename: try: with open(filename, 'rb') as file: saved = pickle.load(file) except Exception: message = 'Error loading plot settings' saved = {'version': None, 'current': None} if saved['version'] == self.model.version: self.model.activeView = saved['current'] self.dock.updateDock() self.colorDialog.updateDialogValues() self.applyChanges() message = '{} settings loaded'.format(filename) else: message = 'Error loading plot settings. Incompatible model.' self.statusBar().showMessage(message, 5000) def openStatePoint(self): # check for an alread-open statepoint if self.model.statepoint: msg_box = QMessageBox() msg_box.setText("Please close the current statepoint file before " "opening a new one.") msg_box.setIcon(QMessageBox.Information) msg_box.setStandardButtons(QMessageBox.Ok) msg_box.exec_() return filename, ext = QFileDialog.getOpenFileName(self, "Open StatePoint", ".", "statepoint*.h5") if filename: try: self.model.openStatePoint(filename) message = 'Opened statepoint file: {}' except (FileNotFoundError, OSError): message = 'Error opening statepoint file: {}' msg_box = QMessageBox() msg = "Could open statepoint file: \n\n {} \n" msg_box.setText(msg.format(filename)) msg_box.setIcon(QMessageBox.Warning) msg_box.setStandardButtons(QMessageBox.Ok) msg_box.exec_() finally: self.statusBar().showMessage(message.format(filename), 5000) self.updateDataMenu() self.tallyDock.update() def closeStatePoint(self): # remove the statepoint object and update the data menu filename = self.model.statepoint.filename self.model.statepoint = None self.model.currentView.selectedTally = None self.model.activeView.selectedTally = None msg = "Closed statepoint file {}".format(filename) self.statusBar().showMessage(msg) self.updateDataMenu() self.tallyDock.selectTally() self.tallyDock.update() self.plotIm.updatePixmap() def updateDataMenu(self): if self.model.statepoint: self.closeStatePointAction = QAction("&Close statepoint", self) self.closeStatePointAction.setToolTip("Close current statepoint") self.closeStatePointAction.triggered.connect(self.closeStatePoint) self.dataMenu.addAction(self.closeStatePointAction) elif hasattr(self, "closeStatePointAction"): self.dataMenu.removeAction(self.closeStatePointAction) def applyChanges(self): if self.model.activeView != self.model.currentView: self.statusBar().showMessage('Generating Plot...') QApplication.processEvents() self.model.storeCurrent() self.model.subsequentViews = [] self.plotIm.generatePixmap() self.resetModels() self.showCurrentView() self.statusBar().showMessage('') else: self.statusBar().showMessage('No changes to apply.', 3000) def undo(self): self.statusBar().showMessage('Generating Plot...') QApplication.processEvents() self.model.undo() self.resetModels() self.showCurrentView() self.dock.updateDock() self.colorDialog.updateDialogValues() if not self.model.previousViews: self.undoAction.setDisabled(True) self.redoAction.setDisabled(False) self.statusBar().showMessage('') def redo(self): self.statusBar().showMessage('Generating Plot...') QApplication.processEvents() self.model.redo() self.resetModels() self.showCurrentView() self.dock.updateDock() self.colorDialog.updateDialogValues() if not self.model.subsequentViews: self.redoAction.setDisabled(True) self.undoAction.setDisabled(False) self.statusBar().showMessage('') def restoreDefault(self): if self.model.currentView != self.model.defaultView: self.statusBar().showMessage('Generating Plot...') QApplication.processEvents() self.model.storeCurrent() self.model.activeView.adopt_plotbase(self.model.defaultView) self.plotIm.generatePixmap() self.resetModels() self.showCurrentView() self.dock.updateDock() self.colorDialog.updateDialogValues() self.model.subsequentViews = [] self.statusBar().showMessage('') def editBasis(self, basis, apply=False): self.model.activeView.basis = basis self.dock.updateBasis() if apply: self.applyChanges() def editColorBy(self, domain_kind, apply=False): self.model.activeView.colorby = domain_kind self.dock.updateColorBy() self.colorDialog.updateColorBy() if apply: self.applyChanges() def toggleOverlaps(self, state, apply=False): self.model.activeView.color_overlaps = bool(state) self.colorDialog.updateOverlap() if apply: self.applyChanges() def editColorMap(self, colormap_name, property_type, apply=False): self.model.activeView.colormaps[property_type] = colormap_name self.plotIm.updateColorMap(colormap_name, property_type) self.colorDialog.updateColorMaps() if apply: self.applyChanges() def editColorbarMin(self, min_val, property_type, apply=False): av = self.model.activeView current = av.user_minmax[property_type] av.user_minmax[property_type] = (min_val, current[1]) self.colorDialog.updateColorMinMax() self.plotIm.updateColorMinMax(property_type) if apply: self.applyChanges() def editColorbarMax(self, max_val, property_type, apply=False): av = self.model.activeView current = av.user_minmax[property_type] av.user_minmax[property_type] = (current[0], max_val) self.colorDialog.updateColorMinMax() self.plotIm.updateColorMinMax(property_type) if apply: self.applyChanges() def toggleColorbarScale(self, state, property, apply=False): av = self.model.activeView av.color_scale_log[property] = bool(state) # temporary, should be resolved diferently in the future cv = self.model.currentView cv.color_scale_log[property] = bool(state) self.plotIm.updateColorbarScale() if apply: self.applyChanges() def toggleUserMinMax(self, state, property): av = self.model.activeView av.use_custom_minmax[property] = bool(state) if av.user_minmax[property] == (0.0, 0.0): av.user_minmax[property] = copy.copy(av.data_minmax[property]) self.plotIm.updateColorMinMax('temperature') self.plotIm.updateColorMinMax('density') self.colorDialog.updateColorMinMax() def toggleDataIndicatorCheckBox(self, state, property, apply=False): av = self.model.activeView av.data_indicator_enabled[property] = bool(state) cv = self.model.currentView cv.data_indicator_enabled[property] = bool(state) self.plotIm.updateDataIndicatorVisibility() if apply: self.applyChanges() def toggleMasking(self, state, apply=False): self.model.activeView.masking = bool(state) self.colorDialog.updateMasking() if apply: self.applyChanges() def toggleHighlighting(self, state, apply=False): self.model.activeView.highlighting = bool(state) self.colorDialog.updateHighlighting() if apply: self.applyChanges() def toggleDockView(self): if self.dock.isVisible(): self.dock.hide() if not self.isMaximized() and not self.dock.isFloating(): self.resize(self.width() - self.dock.width(), self.height()) else: self.dock.setVisible(True) if not self.isMaximized() and not self.dock.isFloating(): self.resize(self.width() + self.dock.width(), self.height()) self.resizePixmap() self.showMainWindow() def toggleTallyDockView(self): if self.tallyDock.isVisible(): self.tallyDock.hide() if not self.isMaximized() and not self.tallyDock.isFloating(): self.resize(self.width() - self.tallyDock.width(), self.height()) else: self.tallyDock.setVisible(True) if not self.isMaximized() and not self.tallyDock.isFloating(): self.resize(self.width() + self.tallyDock.width(), self.height()) self.resizePixmap() self.showMainWindow() def editZoomAct(self): percent, ok = QInputDialog.getInt(self, "Edit Zoom", "Zoom Percent:", self.dock.zoomBox.value(), 25, 2000) if ok: self.dock.zoomBox.setValue(percent) def editZoom(self, value): self.zoom = value self.resizePixmap() self.dock.zoomBox.setValue(value) def showMainWindow(self): self.raise_() self.activateWindow() def showColorDialog(self): self.colorDialog.show() self.colorDialog.raise_() self.colorDialog.activateWindow() def showExportDialog(self): self.exportDataDialog.show() self.exportDataDialog.raise_() self.exportDataDialog.activateWindow() # Dock methods: def editSingleOrigin(self, value, dimension): self.model.activeView.origin[dimension] = value def editPlotAlpha(self, value): self.model.activeView.domainAlpha = value def editPlotVisibility(self, value): self.model.activeView.domainVisible = bool(value) def toggleOutlines(self, value, apply=False): self.model.activeView.outlines = bool(value) self.dock.updateOutlines() if apply: self.applyChanges() def editWidth(self, value): self.model.activeView.width = value self.onRatioChange() self.dock.updateWidth() def editHeight(self, value): self.model.activeView.height = value self.onRatioChange() self.dock.updateHeight() def toggleAspectLock(self, state): self.model.activeView.aspectLock = bool(state) self.onRatioChange() self.dock.updateAspectLock() def editVRes(self, value): self.model.activeView.v_res = value self.dock.updateVRes() def editHRes(self, value): self.model.activeView.h_res = value self.onRatioChange() self.dock.updateHRes() # Color dialog methods: def editMaskingColor(self): current_color = self.model.activeView.maskBackground dlg = QColorDialog(self) dlg.setCurrentColor(QtGui.QColor.fromRgb(*current_color)) if dlg.exec_(): new_color = dlg.currentColor().getRgb()[:3] self.model.activeView.maskBackground = new_color self.colorDialog.updateMaskingColor() def editHighlightColor(self): current_color = self.model.activeView.highlightBackground dlg = QColorDialog(self) dlg.setCurrentColor(QtGui.QColor.fromRgb(*current_color)) if dlg.exec_(): new_color = dlg.currentColor().getRgb()[:3] self.model.activeView.highlightBackground = new_color self.colorDialog.updateHighlightColor() def editAlpha(self, value): self.model.activeView.highlightAlpha = value def editSeed(self, value): self.model.activeView.highlightSeed = value def editOverlapColor(self, apply=False): current_color = self.model.activeView.overlap_color dlg = QColorDialog(self) dlg.setCurrentColor(QtGui.QColor.fromRgb(*current_color)) if dlg.exec_(): new_color = dlg.currentColor().getRgb()[:3] self.model.activeView.overlap_color = new_color self.colorDialog.updateOverlapColor() if apply: self.applyChanges() def editBackgroundColor(self, apply=False): current_color = self.model.activeView.domainBackground dlg = QColorDialog(self) dlg.setCurrentColor(QtGui.QColor.fromRgb(*current_color)) if dlg.exec_(): new_color = dlg.currentColor().getRgb()[:3] self.model.activeView.domainBackground = new_color self.colorDialog.updateBackgroundColor() if apply: self.applyChanges() def resetColors(self): self.model.resetColors() self.colorDialog.updateDialogValues() self.applyChanges() # Tally dock methods def editSelectedTally(self, event): av = self.model.activeView if event is None or event == "None" or event == "": av.selectedTally = None else: av.selectedTally = int(event.split()[1]) self.tallyDock.selectTally(event) def editTallyValue(self, event): av = self.model.activeView av.tallyValue = event def updateScores(self, state): self.tallyDock.updateScores() def updateNuclides(self, state): self.tallyDock.updateNuclides() def toggleTallyVisibility(self, state, apply=False): av = self.model.activeView av.tallyDataVisible = bool(state) if apply: self.applyChanges() def toggleTallyLogScale(self, state, apply=False): av = self.model.activeView av.tallyDataLogScale = bool(state) if apply: self.applyChanges() def toggleTallyMaskZero(self, state): av = self.model.activeView av.tallyMaskZeroValues = bool(state) def editTallyAlpha(self, value, apply=False): av = self.model.activeView av.tallyDataAlpha = value if apply: self.applyChanges() def toggleTallyContours(self, state): av = self.model.activeView av.tallyContours = bool(state) def editTallyContourLevels(self, value): av = self.model.activeView av.tallyContourLevels = value def toggleTallyDataIndicator(self, state, apply=False): av = self.model.activeView av.tallyDataIndicator = bool(state) if apply: self.applyChanges() def toggleTallyDataClip(self, state): av = self.model.activeView av.clipTallyData = bool(state) def toggleTallyDataUserMinMax(self, state, apply=False): av = self.model.activeView av.tallyDataUserMinMax = bool(state) self.tallyDock.tallyColorForm.setMinMaxEnabled(bool(state)) if apply: self.applyChanges() def editTallyDataMin(self, value, apply=False): av = self.model.activeView av.tallyDataMin = value if apply: self.applyChanges() def editTallyDataMax(self, value, apply=False): av = self.model.activeView av.tallyDataMax = value if apply: self.applyChanges() def editTallyDataColormap(self, cmap, apply=False): av = self.model.activeView av.tallyDataColormap = cmap if apply: self.applyChanges() def updateTallyMinMax(self): self.tallyDock.updateMinMax() # Plot image methods def editPlotOrigin(self, xOr, yOr, zOr=None, apply=False): if zOr is not None: self.model.activeView.origin = [xOr, yOr, zOr] else: origin = [None, None, None] origin[self.xBasis] = xOr origin[self.yBasis] = yOr origin[self.zBasis] = self.model.activeView.origin[self.zBasis] self.model.activeView.origin = origin self.dock.updateOrigin() if apply: self.applyChanges() def revertDockControls(self): self.dock.revertToCurrent() def editDomainColor(self, kind, id): if kind == 'Cell': domain = self.model.activeView.cells else: domain = self.model.activeView.materials current_color = domain[id].color dlg = QColorDialog(self) if isinstance(current_color, tuple): dlg.setCurrentColor(QtGui.QColor.fromRgb(*current_color)) elif isinstance(current_color, str): current_color = openmc.plots._SVG_COLORS[current_color] dlg.setCurrentColor(QtGui.QColor.fromRgb(*current_color)) if dlg.exec_(): new_color = dlg.currentColor().getRgb()[:3] domain[id].color = new_color self.applyChanges() def toggleDomainMask(self, state, kind, id): if kind == 'Cell': domain = self.model.activeView.cells else: domain = self.model.activeView.materials domain[id].masked = bool(state) self.applyChanges() def toggleDomainHighlight(self, state, kind, id): if kind == 'Cell': domain = self.model.activeView.cells else: domain = self.model.activeView.materials domain[id].highlight = bool(state) self.applyChanges() # Helper methods: def restoreWindowSettings(self): settings = QtCore.QSettings() self.resize(settings.value("mainWindow/Size", QtCore.QSize(800, 600))) self.move( settings.value("mainWindow/Position", QtCore.QPoint(100, 100))) self.restoreState(settings.value("mainWindow/State")) self.colorDialog.resize( settings.value("colorDialog/Size", QtCore.QSize(400, 500))) self.colorDialog.move( settings.value("colorDialog/Position", QtCore.QPoint(600, 200))) is_visible = settings.value("colorDialog/Visible", 0) # some versions of PySide will return None rather than the default value if is_visible is None: is_visible = False else: is_visible = bool(int(is_visible)) self.colorDialog.setVisible(is_visible) def restoreModelSettings(self): if os.path.isfile("plot_settings.pkl"): with open('plot_settings.pkl', 'rb') as file: model = pickle.load(file) # do not replace model if the version is out of date if model.version != self.model.version: print("WARNING: previous plot settings are for a different " "version of the GUI. They will be ignored.") wrn_msg = "Existing version: {}, Current GUI version: {}" print(wrn_msg.format(model.version, self.model.version)) return try: self.model.statepoint = model.statepoint except OSError: msg_box = QMessageBox() msg = "Could open statepoint file: \n\n {} \n" msg_box.setText(msg.format(self.model.statepoint.filename)) msg_box.setIcon(QMessageBox.Warning) msg_box.setStandardButtons(QMessageBox.Ok) msg_box.exec_() self.model.statepoint = None self.model.currentView = model.currentView self.model.activeView = copy.deepcopy(model.currentView) self.model.previousViews = model.previousViews self.model.subsequentViews = model.subsequentViews def resetModels(self): self.cellsModel = DomainTableModel(self.model.activeView.cells) self.materialsModel = DomainTableModel(self.model.activeView.materials) self.cellsModel.beginResetModel() self.cellsModel.endResetModel() self.materialsModel.beginResetModel() self.materialsModel.endResetModel() self.colorDialog.updateDomainTabs() def showCurrentView(self): self.updateScale() self.updateRelativeBases() self.plotIm.updatePixmap() if self.model.previousViews: self.undoAction.setDisabled(False) if self.model.subsequentViews: self.redoAction.setDisabled(False) else: self.redoAction.setDisabled(True) self.adjustWindow() def updateScale(self): cv = self.model.currentView self.scale = (cv.h_res / cv.width, cv.v_res / cv.height) def updateRelativeBases(self): cv = self.model.currentView self.xBasis = 0 if cv.basis[0] == 'x' else 1 self.yBasis = 1 if cv.basis[1] == 'y' else 2 self.zBasis = 3 - (self.xBasis + self.yBasis) def adjustWindow(self): self.setMaximumSize(self.screen.width(), self.screen.height()) def onRatioChange(self): av = self.model.activeView if av.aspectLock: ratio = av.width / max(av.height, .001) av.v_res = int(av.h_res / ratio) self.dock.updateVRes() def showCoords(self, xPlotPos, yPlotPos): cv = self.model.currentView if cv.basis == 'xy': coords = ("({}, {}, {})".format(round(xPlotPos, 2), round(yPlotPos, 2), round(cv.origin[2], 2))) elif cv.basis == 'xz': coords = ("({}, {}, {})".format(round(xPlotPos, 2), round(cv.origin[1], 2), round(yPlotPos, 2))) else: coords = ("({}, {}, {})".format(round(cv.origin[0], 2), round(xPlotPos, 2), round(yPlotPos, 2))) self.coord_label.setText('{}'.format(coords)) def resizePixmap(self): self.plotIm._resize() self.plotIm.adjustSize() def moveEvent(self, event): self.adjustWindow() def resizeEvent(self, event): self.plotIm._resize() self.adjustWindow() self.updateScale() if self.shortcutOverlay.isVisible(): self.shortcutOverlay.resize(self.width(), self.height()) def closeEvent(self, event): settings = QtCore.QSettings() settings.setValue("mainWindow/Size", self.size()) settings.setValue("mainWindow/Position", self.pos()) settings.setValue("mainWindow/State", self.saveState()) settings.setValue("colorDialog/Size", self.colorDialog.size()) settings.setValue("colorDialog/Position", self.colorDialog.pos()) visible = int(self.colorDialog.isVisible()) settings.setValue("colorDialog/Visible", visible) openmc.lib.finalize() self.saveSettings() def saveSettings(self): if len(self.model.previousViews) > 10: self.model.previousViews = self.model.previousViews[-10:] if len(self.model.subsequentViews) > 10: self.model.subsequentViews = self.model.subsequentViews[-10:] with open('plot_settings.pkl', 'wb') as file: if self.model.statepoint: self.model.statepoint.close() pickle.dump(self.model, file) def exportTallyData(self): # show export tool dialog self.showExportDialog()
import sys from PySide2.QtWidgets import QApplication, QLabel app = QApplication(sys.argv) # label = QLabel("Hello World!") label = QLabel("<font color=red size=40>Hello World!</font>") label.show() app.exec_()
def loadGui(self): self.pixmap = None self.zoom = 100 self.loadModel() # Create viewing area self.frame = QScrollArea(self) cw = QWidget() self.frame.setCornerWidget(cw) self.frame.setAlignment(QtCore.Qt.AlignCenter) self.frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.setCentralWidget(self.frame) # connect pinch gesture (OSX) self.grabGesture(QtCore.Qt.PinchGesture) # Create plot image self.plotIm = PlotImage(self.model, self.frame, self) self.frame.setWidget(self.plotIm) # Dock self.dock = DomainDock(self.model, self.font_metric, self) self.dock.setObjectName("Domain Options Dock") self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.dock) # Tally Dock self.tallyDock = TallyDock(self.model, self.font_metric, self) self.tallyDock.update() self.tallyDock.setObjectName("Tally Options Dock") self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.tallyDock) # Color DialogtallyDock self.colorDialog = ColorDialog(self.model, self.font_metric, self) self.colorDialog.hide() # Tools self.exportDataDialog = ExportDataDialog(self.model, self.font_metric, self) # Restore Window Settings self.restoreWindowSettings() # Create menubar self.createMenuBar() self.updateEditMenu() # Status Bar self.coord_label = QLabel() self.statusBar().addPermanentWidget(self.coord_label) self.coord_label.hide() # Keyboard overlay self.shortcutOverlay = ShortcutsOverlay(self) self.shortcutOverlay.hide() # Load Plot self.statusBar().showMessage('Generating Plot...') self.dock.updateDock() self.tallyDock.update() self.colorDialog.updateDialogValues() self.statusBar().showMessage('') # Timer allows GUI to render before plot finishes loading QtCore.QTimer.singleShot(0, self.plotIm.generatePixmap) QtCore.QTimer.singleShot(0, self.showCurrentView)
def __init__(self): super().__init__() hlayout = QHBoxLayout() layout = QVBoxLayout() self.filtert = QLineEdit() self.filtert.setPlaceholderText("Search...") self.table = QTableView() vlayout = QVBoxLayout() vlayout.addWidget(self.filtert) vlayout.addWidget(self.table) # Left/right pane. hlayout.addLayout(vlayout) hlayout.addLayout(layout) form = QFormLayout() self.track_id = QSpinBox() self.track_id.setDisabled(True) self.track_id.setRange(0, 2147483647) self.name = QLineEdit() self.album = QComboBox() self.media_type = QComboBox() self.genre = QComboBox() self.composer = QLineEdit() self.milliseconds = QSpinBox() self.milliseconds.setRange(0, 2147483647) self.milliseconds.setSingleStep(1) self.bytes = QSpinBox() self.bytes.setRange(0, 2147483647) self.bytes.setSingleStep(1) self.unit_price = QDoubleSpinBox() self.unit_price.setRange(0, 999) self.unit_price.setSingleStep(0.01) self.unit_price.setPrefix("$") form.addRow(QLabel("Track ID"), self.track_id) form.addRow(QLabel("Track name"), self.name) form.addRow(QLabel("Composer"), self.composer) form.addRow(QLabel("Milliseconds"), self.milliseconds) form.addRow(QLabel("Bytes"), self.bytes) form.addRow(QLabel("Unit Price"), self.unit_price) self.model = QSqlTableModel(db=db) self.proxy_model = QSortFilterProxyModel() self.proxy_model.setSourceModel(self.model) self.proxy_model.sort(1, Qt.AscendingOrder) self.proxy_model.setFilterKeyColumn(-1) # all columns self.table.setModel(self.proxy_model) # Update search when filter changes. self.filtert.textChanged.connect(self.proxy_model.setFilterFixedString) self.mapper = QDataWidgetMapper() self.mapper.setModel(self.proxy_model) self.mapper.addMapping(self.track_id, 0) self.mapper.addMapping(self.name, 1) self.mapper.addMapping(self.composer, 5) self.mapper.addMapping(self.milliseconds, 6) self.mapper.addMapping(self.bytes, 7) self.mapper.addMapping(self.unit_price, 8) self.model.setTable("Track") self.model.select() # Change the mapper selection using the table. self.table.selectionModel().currentRowChanged.connect( self.mapper.setCurrentModelIndex) self.mapper.toFirst() # tag::controls[] self.setMinimumSize(QSize(800, 400)) controls = QHBoxLayout() prev_rec = QPushButton("Previous") prev_rec.clicked.connect(self.mapper.toPrevious) next_rec = QPushButton("Next") next_rec.clicked.connect(self.mapper.toNext) save_rec = QPushButton("Save Changes") save_rec.clicked.connect(self.mapper.submit) controls.addWidget(prev_rec) controls.addWidget(next_rec) controls.addWidget(save_rec) layout.addLayout(form) layout.addLayout(controls) widget = QWidget() widget.setLayout(hlayout) self.setCentralWidget(widget)
def widgets(self): # Facilities widgets ########################################################### # Top layout (search facilities) widgets self.searchFacilitiesText = QLabel("Search: ") self.searchFacilitesEntry = QLineEdit() self.searchFacilitesEntry.setPlaceholderText("Search facilities..") self.searchFacilitiesBtn = QPushButton("Search") self.searchFacilitiesBtn.clicked.connect(self.funcSearchFacilities) self.refreshFacilitiesBtn = QPushButton("Refresh") self.refreshFacilitiesBtn.clicked.connect(self.funcDisplayFacilities) # Middle layout (list people) widgets with radio buttons self.allFacilitiesRadioBtn = QRadioButton("All facilities") self.withOngoingIssuesFacilitiesRadioBtn = QRadioButton( "With pending issues") self.withLateIssuesRadioBtn = QRadioButton("With late issues") self.listFacilitiesBtn = QPushButton("List") # Bottom layout widget, a table showing people self.facilitiesTable = QTableWidget() self.facilitiesTable.verticalHeader().hide() self.facilitiesTable.setSortingEnabled(True) self.facilitiesTable.setShowGrid(False) self.facilitiesTable.verticalHeader().setDefaultSectionSize(40) self.facilitiesTable.setColumnCount(11) # self.peopleTable.setColumnHidden(0, True) self.facilitiesTable.setHorizontalHeaderItem(0, QTableWidgetItem("")) self.facilitiesTable.horizontalHeader().setSectionResizeMode( 0, QHeaderView.ResizeToContents) self.facilitiesTable.setHorizontalHeaderItem(1, QTableWidgetItem("ID")) self.facilitiesTable.setHorizontalHeaderItem(2, QTableWidgetItem("Name")) self.facilitiesTable.horizontalHeader().setSectionResizeMode( 1, QHeaderView.Stretch) self.facilitiesTable.setHorizontalHeaderItem( 3, QTableWidgetItem("Location")) self.facilitiesTable.horizontalHeader().setSectionResizeMode( 2, QHeaderView.Stretch) self.facilitiesTable.setHorizontalHeaderItem(4, QTableWidgetItem("Phone")) self.facilitiesTable.horizontalHeader().setSectionResizeMode( 3, QHeaderView.Stretch) self.facilitiesTable.setHorizontalHeaderItem(5, QTableWidgetItem("Email")) self.facilitiesTable.horizontalHeader().setSectionResizeMode( 4, QHeaderView.Stretch) self.facilitiesTable.setHorizontalHeaderItem( 6, QTableWidgetItem("Supervisor")) self.facilitiesTable.setHorizontalHeaderItem( 7, QTableWidgetItem("Ongoing issues")) self.facilitiesTable.setHorizontalHeaderItem( 8, QTableWidgetItem("Late issues")) self.facilitiesTable.setHorizontalHeaderItem( 9, QTableWidgetItem("Total issues")) self.facilitiesTable.setHorizontalHeaderItem( 10, QTableWidgetItem("Total inspections")) # Double clicking a row opens a window with person details self.facilitiesTable.doubleClicked.connect(self.funcSelectedFacility) # Buttons for actions on selected facilities self.addFacility = QPushButton("Add") self.addFacility.clicked.connect(self.funcAddFacility) self.viewFacility = QPushButton("View/Edit") self.viewFacility.clicked.connect(self.funcSelectedFacility) self.deleteFacility = QPushButton("Delete") self.deleteFacility.clicked.connect(self.funcDeleteFacility) self.exportFacilitiesCSVBtn = QPushButton("Export CSV") self.exportFacilitiesCSVBtn.setEnabled(False) self.exportFacilitiesCSVBtn.clicked.connect(self.funcFacilitiesToCSV) self.exportFacilitiesXSLXBtn = QPushButton("Export XLSX") self.exportFacilitiesXSLXBtn.setEnabled(False) self.exportFacilitiesXSLXBtn.clicked.connect(self.funcFacilitiesToXLSX) self.exportFacilitiesPDFBtn = QPushButton("Export PDF") self.exportFacilitiesPDFBtn.setEnabled(False) self.exportFacilitiesPDFBtn.clicked.connect(self.funcFacilitiesToPdf)
def __init__(self, db, own_path, language): QMainWindow.__init__(self, None) self.setupUi(self) self.db = db self.own_path = own_path self.currentLanguage = language self.ledger = Ledger(self.db) self.downloader = QuoteDownloader(self.db) self.downloader.download_completed.connect(self.onQuotesDownloadCompletion) self.taxes = TaxesRus(self.db) self.statements = StatementLoader(self, self.db) self.statements.load_completed.connect(self.onStatementLoaded) self.statements.load_failed.connect(self.onStatementLoadFailure) # Customize Status bar and logs self.NewLogEventLbl = QLabel(self) self.StatusBar.addPermanentWidget(VLine()) self.StatusBar.addPermanentWidget(self.NewLogEventLbl) self.Logs.setNotificationLabel(self.NewLogEventLbl) self.Logs.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')) self.logger = logging.getLogger() self.logger.addHandler(self.Logs) self.logger.setLevel(logging.INFO) # Setup reports tab self.ReportAccountBtn.init_db(self.db) self.reports = Reports(self.db, self.ReportTableView) self.reports.report_failure.connect(self.onReportFailure) # Customize UI configuration self.operations = LedgerOperationsView(self.OperationsTableView) self.ui_config = TableViewConfig(self) self.ui_config.configure_all() self.operation_details = { TransactionType.Action: ( g_tr('TableViewConfig', "Income / Spending"), self.ui_config.mappers[self.ui_config.ACTIONS], 'actions', self.ActionDetailsTableView, 'action_details', LedgerInitValues[TransactionType.Action]), TransactionType.Trade: ( g_tr('TableViewConfig', "Trade"), self.ui_config.mappers[self.ui_config.TRADES], 'trades', None, None, LedgerInitValues[TransactionType.Trade]), TransactionType.Dividend: ( g_tr('TableViewConfig', "Dividend"), self.ui_config.mappers[self.ui_config.DIVIDENDS], 'dividends', None, None, LedgerInitValues[TransactionType.Dividend]), TransactionType.Transfer: ( g_tr('TableViewConfig', "Transfer"), self.ui_config.mappers[self.ui_config.TRANSFERS], 'transfers_combined', None, None, LedgerInitValues[TransactionType.Transfer]) } self.operations.setOperationsDetails(self.operation_details) self.operations.activateOperationView.connect(self.ShowOperationTab) self.operations.stateIsCommitted.connect(self.showCommitted) self.operations.stateIsModified.connect(self.showModified) # Setup balance and holdings tables self.ledger.setViews(self.BalancesTableView, self.HoldingsTableView) self.BalanceDate.setDateTime(QDateTime.currentDateTime()) self.BalancesCurrencyCombo.init_db(self.db) # this line will trigger onBalanceDateChange -> view updated self.HoldingsDate.setDateTime(QDateTime.currentDateTime()) self.HoldingsCurrencyCombo.init_db(self.db) # and this will trigger onHoldingsDateChange -> view updated # Create menu for different operations self.ChooseAccountBtn.init_db(self.db) self.NewOperationMenu = QMenu() for operation in self.operation_details: self.NewOperationMenu.addAction(self.operation_details[operation][LedgerOperationsView.OP_NAME], partial(self.operations.addNewOperation, operation)) self.NewOperationBtn.setMenu(self.NewOperationMenu) self.ActionDetailsTableView.horizontalHeader().moveSection(self.ActionDetailsTableView.model().fieldIndex("note"), self.ActionDetailsTableView.model().fieldIndex("name")) self.langGroup = QActionGroup(self.menuLanguage) self.createLanguageMenu() self.langGroup.triggered.connect(self.onLanguageChanged) self.OperationsTableView.selectRow(0) # TODO find a way to select last row from self.operations self.OnOperationsRangeChange(0)
def _add_process(self): process_groupbox = QGroupBox("Process") process_groupbox.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) process_layout = QVBoxLayout() process_layout.setSpacing(0) process_groupbox.setLayout(process_layout) pbar_frame = QFrame() pbar_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) pbar_hbox = QHBoxLayout() pbar_hbox.setContentsMargins(QtCore.QMargins(0, 0, 0, 16)) pbar_hbox.setSpacing(16) # Run and stop buttons hbox = QHBoxLayout() hbox.setSpacing(8) self.run_button = QPushButton() # is only enabled when validation passes self.run_button.setEnabled(False) self.run_button.setText("Run") self.run_button.setFixedWidth(100) run_icon = qta.icon('fa.play', color='green') self.run_button.setIcon(run_icon) self.run_button.clicked.connect(self._click_run) hbox.addWidget(self.run_button) self.stop_button = QPushButton() self.stop_button.setEnabled(False) self.stop_button.setText("Stop") self.stop_button.setFixedWidth(100) stop_icon = qta.icon('fa.stop', color='red') self.stop_button.setIcon(stop_icon) self.stop_button.clicked.connect(self._click_stop) hbox.addWidget(self.stop_button) self.progress_bar = QProgressBar() self.progress_bar.setTextVisible(True) self.progress_bar.setAlignment(QtCore.Qt.AlignCenter) self.progress_bar.setValue(0) self.progress_bar.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) pbar_hbox.addLayout(hbox) pbar_hbox.addWidget(self.progress_bar) pbar_frame.setLayout(pbar_hbox) process_layout.addWidget(pbar_frame) self.warning_frame = QFrame() self.warning_frame.setVisible(False) self.warning_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) hbox = QHBoxLayout() warning_icon_widget = qta.IconWidget('fa.warning', color='red') warning_icon_widget.setIconSize(QtCore.QSize(48, 48)) warning_icon_widget.update() hbox.addWidget(warning_icon_widget) warning_label = QLabel( "Grid Transformer did not complete successfully. Please refer to " "log output.") warning_label.setStyleSheet("QLabel { color: red; }") warning_label.setWordWrap(True) warning_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) hbox.addWidget(warning_label) self.warning_frame.setLayout(hbox) process_layout.addWidget(self.warning_frame) self.success_frame = QFrame() self.success_frame.setVisible(False) self.success_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) hbox = QHBoxLayout() success_icon_widget = qta.IconWidget('fa.check', color='green') success_icon_widget.setIconSize(QtCore.QSize(48, 48)) success_icon_widget.update() hbox.addWidget(success_icon_widget) success_label = QLabel("Grid Transformer completed successfully.") success_label.setStyleSheet("QLabel { color: green; }") success_label.setWordWrap(True) success_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) hbox.addWidget(success_label) self.success_frame.setLayout(hbox) process_layout.addWidget(self.success_frame) log_layout = QVBoxLayout() log_layout.setSpacing(4) log_label = QLabel("Log messages") log_label.setStyleSheet("QLabel { color: grey; }") log_layout.addWidget(log_label) self.log_messages = QPlainTextEdit() log_font = QFont("monospace") log_font.setStyleHint(QFont.TypeWriter) self.log_messages.setFont(log_font) self.log_messages.setReadOnly(True) self.log_messages.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) # self.log_messages.sizePolicy.setVerticalStretch(1) log_layout.addWidget(self.log_messages) process_layout.addLayout(log_layout) self.layout.addWidget(process_groupbox)
def displayWidgets(self): """ Configura os widgets da janela """ title_lbl = QLabel("Albuns Filipe Ret") title_lbl.setfont(QFont("Arial", 17)) qust_lbl = QLabel("Qual é o melhor album do rapper?") title_hbox = QHBoxlayout() title_hbox.addStretch() title_hbox.addWidget(title_lbl) title_hbox.addStretch() # Criando Labels para 3 imagens vivaz_img = "Imagens/vivaz.png" revel_img = "Imagens/revel.png" audaz_img = "Imagens/audaz.png" try: with open(vivaz_img): vivaz1_img = QLabel(self) pixmap = QPixmap(vivaz_img) pixmap = pixmap.scaled(33, 33) vivaz1_img.SetPixmap(pixmap) vivaz1_img.Move(150, 60) except FileNotFoundError: print("A imagem não está disponível!") try: with open(revel_img): revel1_img = QLabel(self) pixmap = QPixmap(revel_img) pixmap = pixmap.scaled(66, 66) revel1_img.SetPixmap(pixmap) revel1_img.Move(150, 60) except FileNotFoundError: print("A imagem não está disponível!") try: with open(audaz_img): audaz1_img = QLabel(self) pixmap = QPixmap(audaz_img) pixmap = pixmap.scaled(99, 99) audaz1_img.SetPixmap(pixmap) audaz1_img.Move(150, 60) except FileNotFoundError: print("A imagem não está disponível!") escala = ["Vivaz", "Revel", "Audaz"] escala_hbox = QHBoxLayout() escala_hbox.setSpacing(33) escala_hbox.addStrech() for eval in escala: eval_lbl = QLabel(eval, self) escala_hbox.addWidget(eval_lbl) escala_hbox.addStrech() btng_hbox = QHBoxLayout() btng_hbox.setSpacing(55) escala_bgrp = QButtonGroup(self) btg_hbox.addStretch() for btn in range(len(escala)): eval_chkb = QCheckBox(str(btn), self) btng_hbox.addWidget(eval_chkb) escala_bgrp.addButton(eval_chkb) btng_hbox.addStretch() escala_bgrp.buttonClicked.connect(self.checkBoxClicked) close_btn = QPushButton("Fechar", self) close_btn.clicked.connect(self.close) vbox = QVBoxLayout() vbox.addLayout(title_hbox) vbox.addWidget(qust_lbl) vbox.addStretch(1) vbox.addLayout(escala_hbox) vbox.addLayout(btng_hbox) vbox.addStretch(2) vbox.addWidget(close_btn) self.setLayout(vbox)
def __init__(self, mode, parentQWidget = None): QVBoxLayout.__init__(self) self.sig.connect(self.addThreadList) self.mode = mode self.sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding) self.groupBoxSearch = QGroupBox() self.groupBoxSearch.setStyleSheet("QGroupBox {border: 1px solid gray; border-radius: 4px; };") vboxSearch = QVBoxLayout() self.searchTitle = QLabel("Search Messages") vboxSearch.addWidget(self.searchTitle) self.searchHLayout = QHBoxLayout() self.editTextSearch = QTextEdit('') self.editTextSearch.setFixedSize(200,30) self.buttonSearch = QPushButton('Search') self.buttonSearch.setFixedSize(100,30) self.buttonSearch.clicked.connect(self.searchMsg) vboxSearch.addWidget(self.editTextSearch) self.searchHLayout.addWidget(self.buttonSearch) self.searchCursor = QLabel() self.searchHLayout.addWidget(self.searchCursor) vboxSearch.addLayout(self.searchHLayout) self.browseHLayout = QHBoxLayout() self.buttonLookUp = QPushButton('\u21e7') #Arrow up self.buttonLookUp.setFixedWidth(100) self.buttonLookUp.clicked.connect(self.moveToPrev) self.buttonLookDown = QPushButton('\u21e9') #Arrow down self.buttonLookDown.setFixedWidth(100) self.buttonLookDown.clicked.connect(self.moveToNext) self.browseHLayout.addWidget(self.buttonLookUp) self.browseHLayout.addWidget(self.buttonLookDown) vboxSearch.addLayout(self.browseHLayout) self.groupBoxSearch.setLayout(vboxSearch) self.addWidget(self.groupBoxSearch) self.groupBoxSearch.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) self.buttonHiddenLifelines = QPushButton('Show hidden life-lines') self.buttonHiddenLifelines.setFixedWidth(200) self.buttonHiddenLifelines.clicked.connect(self.showHiddenLifelines) self.addWidget(self.buttonHiddenLifelines) self.buttonHiddenMessages = QPushButton('Show hidden Messages') self.buttonHiddenMessages.setFixedWidth(200) self.buttonHiddenMessages.clicked.connect(self.showHiddenMessages) self.addWidget(self.buttonHiddenMessages) if const.mode_interactive == mode: self.buttonCapture = QPushButton('Capture') self.buttonCapture.setFixedWidth(200) self.buttonCapture.clicked.connect(self.notifyCapture) self.addWidget(self.buttonCapture) self.msgRcv = [] self.msgInfo = QLabel("Message Info.") self.groupBoxMessageInfo = QGroupBox() self.groupBoxMessageInfo.setStyleSheet("QGroupBox {border: 1px solid gray; border-radius: 9px; margin-top: 0.5em} QGroupBox::title {subcontrol-origin: margin; left: 10px; padding: 0 3px 0 3px;") vbox = QVBoxLayout() vbox.addWidget(self.msgInfo) self.tableTime = QTableWidget(3,2) self.tableTime.setHorizontalHeaderLabels(['-','time']) self.tableTime.setColumnWidth(0,80) self.tableTime.setColumnWidth(1,150) vwidth = self.tableTime.verticalHeader().length() hwidth = self.tableTime.horizontalHeader().height() fwidth = self.tableTime.frameWidth() * 2 self.tableTime.setFixedHeight(vwidth + hwidth + fwidth) self.tableTime.horizontalHeader().setStretchLastSection(True) self.tableTime.setItem(0,0,QTableWidgetItem('begin')) self.tableTime.setItem(0,1,QTableWidgetItem(' - ')) self.tableTime.setItem(1,0,QTableWidgetItem('end')) self.tableTime.setItem(1,1,QTableWidgetItem(' - ')) self.tableTime.setItem(2,0,QTableWidgetItem('duration')) self.tableTime.setItem(2,1,QTableWidgetItem(' - ')) vbox.addWidget(self.tableTime) self.titleArg = QLabel('Argument List') vbox.addWidget(self.titleArg) max_arg_num = 10 self.tableArgs = QTableWidget(max_arg_num,2) self.tableArgs.setHorizontalHeaderLabels(['type','value']) for idx in range(0,max_arg_num): self.tableArgs.setItem(idx,0,QTableWidgetItem()) self.tableArgs.setItem(idx,1,QTableWidgetItem()) self.tableArgs.horizontalHeader().setStretchLastSection(True) vbox.addWidget(self.tableArgs) self.titleArg = QLabel('Return Value List') vbox.addWidget(self.titleArg) max_ret_num = 4 self.tableRet = QTableWidget(max_ret_num,2) self.tableRet.setHorizontalHeaderLabels(['type','value']) for idx in range(0,max_ret_num): self.tableRet.setItem(idx,0,QTableWidgetItem()) self.tableRet.setItem(idx,1,QTableWidgetItem()) self.tableRet.horizontalHeader().setStretchLastSection(True) vwidth = self.tableRet.verticalHeader().length() hwidth = self.tableRet.horizontalHeader().height() fwidth = self.tableRet.frameWidth() * 2 self.tableRet.setFixedHeight(vwidth + hwidth + fwidth) vbox.addWidget(self.tableRet) self.buttonSrcView = QPushButton('view code') self.buttonSrcView.setFixedWidth(200) self.buttonSrcView.clicked.connect(self.openSourceViewer) self.buttonHide = QPushButton('Hide') self.buttonHide.setFixedWidth(200) self.buttonHide.clicked.connect(self.notifyHide) self.buttonHideAllMsg = QPushButton('Hide All') self.buttonHideAllMsg.setFixedWidth(200) self.buttonHideAllMsg.clicked.connect(self.hideAllMsgNamedAsSelected) self.groupBoxMessageInfo.setLayout(vbox) self.checkHideCircular = QCheckBox('Hide Circular Messages') self.checkHideCircular.setCheckState(QtCore.Qt.Unchecked) self.checkHideCircular.stateChanged.connect(self.changeHideCircularMessage) self.addWidget(self.checkHideCircular) self.addWidget(self.groupBoxMessageInfo) self.groupBoxMessageInfo.setSizePolicy(self.sizePolicy)
class BlockingClient(QWidget): def __init__(self, parent=None): super(BlockingClient, self).__init__(parent) self.thread = FortuneThread() self.currentFortune = '' hostLabel = QLabel("&Server name:") portLabel = QLabel("S&erver port:") for ipAddress in QNetworkInterface.allAddresses(): if ipAddress != QHostAddress.LocalHost and ipAddress.toIPv4Address() != 0: break else: ipAddress = QHostAddress(QHostAddress.LocalHost) ipAddress = ipAddress.toString() self.hostLineEdit = QLineEdit(ipAddress) self.portLineEdit = QLineEdit() self.portLineEdit.setValidator(QIntValidator(1, 65535, self)) hostLabel.setBuddy(self.hostLineEdit) portLabel.setBuddy(self.portLineEdit) self.statusLabel = QLabel( "This example requires that you run the Fortune Server example as well.") self.statusLabel.setWordWrap(True) self.getFortuneButton = QPushButton("Get Fortune") self.getFortuneButton.setDefault(True) self.getFortuneButton.setEnabled(False) quitButton = QPushButton("Quit") buttonBox = QDialogButtonBox() buttonBox.addButton(self.getFortuneButton, QDialogButtonBox.ActionRole) buttonBox.addButton(quitButton, QDialogButtonBox.RejectRole) self.getFortuneButton.clicked.connect(self.requestNewFortune) quitButton.clicked.connect(self.close) self.hostLineEdit.textChanged.connect(self.enableGetFortuneButton) self.portLineEdit.textChanged.connect(self.enableGetFortuneButton) self.thread.newFortune.connect(self.showFortune) self.thread.error.connect(self.displayError) mainLayout = QGridLayout() mainLayout.addWidget(hostLabel, 0, 0) mainLayout.addWidget(self.hostLineEdit, 0, 1) mainLayout.addWidget(portLabel, 1, 0) mainLayout.addWidget(self.portLineEdit, 1, 1) mainLayout.addWidget(self.statusLabel, 2, 0, 1, 2) mainLayout.addWidget(buttonBox, 3, 0, 1, 2) self.setLayout(mainLayout) self.setWindowTitle("Blocking Fortune Client") self.portLineEdit.setFocus() def requestNewFortune(self): self.getFortuneButton.setEnabled(False) self.thread.requestNewFortune(self.hostLineEdit.text(), int(self.portLineEdit.text())) def showFortune(self, nextFortune): if nextFortune == self.currentFortune: self.requestNewFortune() return self.currentFortune = nextFortune self.statusLabel.setText(self.currentFortune) self.getFortuneButton.setEnabled(True) def displayError(self, socketError, message): if socketError == QAbstractSocket.HostNotFoundError: QMessageBox.information(self, "Blocking Fortune Client", "The host was not found. Please check the host and port " "settings.") elif socketError == QAbstractSocket.ConnectionRefusedError: QMessageBox.information(self, "Blocking Fortune Client", "The connection was refused by the peer. Make sure the " "fortune server is running, and check that the host name " "and port settings are correct.") else: QMessageBox.information(self, "Blocking Fortune Client", "The following error occurred: %s." % message) self.getFortuneButton.setEnabled(True) def enableGetFortuneButton(self): self.getFortuneButton.setEnabled(self.hostLineEdit.text() != '' and self.portLineEdit.text() != '')
def __init__(self): super().__init__() # Main Layout main_layout = QHBoxLayout(self) main_layout.setContentsMargins(0, 0, 0, 0) title = QLabel( "Sp<font color='#419DD1'>o</font>ng<font color='#F4D05C'>o</font>") title.setObjectName("title") subtitle = QLabel( "Outil de classification et de reconnaissance de morphotypes d’éponges marines" ) subtitle.setObjectName("subtitle") start_button = StylizedButton("Commencer une analyse", "blue") self._history_button = StylizedButton("Historique des analyses", "blue") about_button = StylizedButton("À propos", "blue") exit_button = StylizedButton("Quitter", "yellow") buttons_layout = QGridLayout() buttons_layout.setAlignment(Qt.AlignCenter) buttons_layout.setVerticalSpacing(24) buttons_layout.setHorizontalSpacing(30) buttons_layout.addWidget(start_button, 0, 0, 1, 2) buttons_layout.addWidget(self._history_button, 1, 0, 1, 2) buttons_layout.addWidget(about_button, 2, 0) buttons_layout.addWidget(exit_button, 2, 1) version_label = QLabel(AppInfo.version()) version_label.setAlignment(Qt.AlignCenter) version_label.setObjectName("version") center_layout = QVBoxLayout() center_layout.setAlignment(Qt.AlignCenter) center_layout.setContentsMargins(15, 15, 15, 15) center_layout.addStretch(4) center_layout.addWidget(title) center_layout.addWidget(subtitle) center_layout.addLayout(buttons_layout) center_layout.addStretch(5) center_layout.addWidget(version_label) isen_logo = QLabel() isen_logo.setPixmap( QPixmap(":/img/isen_logo.png").scaledToWidth( 180, Qt.SmoothTransformation)) left_layout = QVBoxLayout() left_layout.setContentsMargins(0, 0, 0, 0) left_layout.addWidget(isen_logo, alignment=Qt.AlignBottom) ifremer_logo = QLabel() ifremer_logo.setAlignment(Qt.AlignRight) ifremer_logo.setPixmap( QPixmap(":/img/ifremer_logo.png").scaledToWidth( 180, Qt.SmoothTransformation)) right_layout = QVBoxLayout() right_layout.setContentsMargins(0, 0, 0, 0) right_layout.addWidget(ifremer_logo, alignment=Qt.AlignBottom) main_layout.addLayout(left_layout, 1) main_layout.addLayout(center_layout, 3) main_layout.addLayout(right_layout, 1) self.setLayout(main_layout) # Button slots start_button.clicked.connect(self._startButtonClicked) self._history_button.clicked.connect(self._historyButtonClicked) about_button.clicked.connect(self._aboutButtonClicked) exit_button.clicked.connect(self._exitButtonClicked)
def main(): app = QApplication(sys.argv) vars = {} def createGui(): nonlocal vars gui = G27CalibGui() gui.setMinimumSize(1024, 700) gui.setWindowTitle("G27 Pedalsand Shifter") coll = Collector(vars["tty"]) coll.valuesChanged.connect(gui.newVals) app.aboutToQuit.connect(coll.stop) if vars["jsdev"] is not None: js = JoystickSink(vars["jsdev"]) app.aboutToQuit.connect(js.stop) else: js = None gui.sendModeCmd.connect(coll.sendModeCmd) gui.show() if main_widget is not None: main_widget.hide() vars["gui"] = gui vars["coll"] = coll vars["js"] = js if len(list_ports.comports()) != 1 or len(inputs.devices.gamepads) != 1: main_widget = QWidget() main_widget.setWindowTitle("G27 Pedalsand Shifter - serial port") layout = QGridLayout(main_widget) layout.addWidget(QLabel("Select Arduino COM port:", main_widget), 0, 0) ttyCombo = QComboBox(main_widget) layout.addWidget(ttyCombo, 0, 1) layout.addWidget(QLabel("Select G27 joystick port:", main_widget), 1, 0) jsCombo = QComboBox(main_widget) layout.addWidget(jsCombo, 1, 1) def refresh(): ttyCombo.clear() n = 0 for p in list_ports.comports(): ttyCombo.addItem(p.device) n += 1 k = 0 jsCombo.clear() for i, d in enumerate(inputs.devices.gamepads): jsCombo.addItem(d.name, userData=d) k += 1 btnStart.setEnabled(n > 0) def startgui(): idx = ttyCombo.currentIndex() vars["tty"] = ttyCombo.itemText(ttyCombo.currentIndex()) vars["jsdev"] = jsCombo.itemData(jsCombo.currentIndex()) createGui() btnRefresh = QPushButton("Refresh Devices") btnRefresh.clicked.connect(refresh) layout.addWidget(btnRefresh, 0, 2) btnStart = QPushButton("Start") btnStart.clicked.connect(startgui) refresh() layout.addWidget(btnStart, 1, 2) main_widget.show() else: main_widget = None vars["tty"] = list_ports.comports()[0].device vars["jsdev"] = inputs.devices.gamepads[0] createGui() os._exit(app.exec_())
def _create_ammo_pickup_boxes(self, size_policy, item_database: ItemDatabase): """ Creates the GroupBox with SpinBoxes for selecting the pickup count of all the ammo :param item_database: :return: """ self._ammo_maximum_spinboxes = collections.defaultdict(list) self._ammo_pickup_widgets = {} resource_database = default_prime2_resource_database() for ammo in item_database.ammo.values(): title_layout = QHBoxLayout() title_layout.setObjectName(f"{ammo.name} Title Horizontal Layout") expand_ammo_button = QToolButton(self.ammo_box) expand_ammo_button.setGeometry(QRect(20, 30, 24, 21)) expand_ammo_button.setText("+") title_layout.addWidget(expand_ammo_button) category_label = QLabel(self.ammo_box) category_label.setSizePolicy(size_policy) category_label.setText(ammo.name + "s") title_layout.addWidget(category_label) pickup_box = QGroupBox(self.ammo_box) pickup_box.setSizePolicy(size_policy) layout = QGridLayout(pickup_box) layout.setObjectName(f"{ammo.name} Box Layout") current_row = 0 for ammo_item in ammo.items: item = resource_database.get_by_type_and_index(ResourceType.ITEM, ammo_item) target_count_label = QLabel(pickup_box) target_count_label.setText(f"{item.long_name} Target" if len(ammo.items) > 1 else "Target count") maximum_spinbox = QSpinBox(pickup_box) maximum_spinbox.setMaximum(ammo.maximum) maximum_spinbox.valueChanged.connect(partial(self._on_update_ammo_maximum_spinbox, ammo_item)) self._ammo_maximum_spinboxes[ammo_item].append(maximum_spinbox) layout.addWidget(target_count_label, current_row, 0) layout.addWidget(maximum_spinbox, current_row, 1) current_row += 1 count_label = QLabel(pickup_box) count_label.setText("Pickup Count") count_label.setToolTip("How many instances of this expansion should be placed.") pickup_spinbox = QSpinBox(pickup_box) pickup_spinbox.setMaximum(AmmoState.maximum_pickup_count()) pickup_spinbox.valueChanged.connect(partial(self._on_update_ammo_pickup_spinbox, ammo)) layout.addWidget(count_label, current_row, 0) layout.addWidget(pickup_spinbox, current_row, 1) current_row += 1 if ammo.temporaries: require_major_item_check = QCheckBox(pickup_box) require_major_item_check.setText("Requires the major item to work?") require_major_item_check.stateChanged.connect(partial(self._on_update_ammo_require_major_item, ammo)) layout.addWidget(require_major_item_check, current_row, 0, 1, 2) current_row += 1 else: require_major_item_check = None expected_count = QLabel(pickup_box) expected_count.setWordWrap(True) expected_count.setText(_EXPECTED_COUNT_TEXT_TEMPLATE) expected_count.setToolTip("Some expansions may provide 1 extra, even with no variance, if the total count " "is not divisible by the pickup count.") layout.addWidget(expected_count, current_row, 0, 1, 2) current_row += 1 self._ammo_pickup_widgets[ammo] = (pickup_spinbox, expected_count, expand_ammo_button, category_label, pickup_box, require_major_item_check) expand_ammo_button.clicked.connect(partial(_toggle_box_visibility, expand_ammo_button, pickup_box)) pickup_box.setVisible(False) self.ammo_layout.addLayout(title_layout) self.ammo_layout.addWidget(pickup_box)
def __init__(self, app, parent=None): super(MainWindow, self).__init__(parent) self.imagesDir = app.dir + '/images/' self.setWindowIcon(QIcon(self.imagesDir + 'icon.png')) self.path = '' self.settings = QSettings() self.lastDir = self.settings.value('lastDir', '') self.setMinimumWidth(540) self.supportedFormats = [] for f in QImageReader.supportedImageFormats(): self.supportedFormats.append(str(f.data(), encoding="utf-8")) self.fileWatcher = QFileSystemWatcher() self.fileWatcher.fileChanged.connect(self.fileChanged) # widgets self.showPixmapWidget = None self.tileWidthSpinBox = QSpinBox() self.tileWidthSpinBox.setValue(16) self.tileWidthSpinBox.setFixedWidth(50) self.tileWidthSpinBox.setMinimum(1) self.tileHeightSpinBox = QSpinBox() self.tileHeightSpinBox.setValue(16) self.tileHeightSpinBox.setFixedWidth(50) self.tileHeightSpinBox.setMinimum(1) self.paddingSpinBox = QSpinBox() self.paddingSpinBox.setFixedWidth(50) self.paddingSpinBox.setMinimum(1) self.transparentCheckbox = QCheckBox("Transparent") self.transparentCheckbox.setChecked(True) self.transparentCheckbox.stateChanged.connect(self.transparentChanged) self.backgroundColorEdit = ColorEdit() self.backgroundColorEdit.setEnabled(False) self.backgroundColorLabel = QLabel("Background color:") self.backgroundColorLabel.setEnabled(False) self.forcePotCheckBox = QCheckBox("Force PoT") self.forcePotCheckBox.setChecked(True) self.forcePotCheckBox.stateChanged.connect(self.forcePotChanged) self.reorderTilesCheckBox = QCheckBox("Reorder tiles") self.generateAndExportButton = QPushButton("Generate and export") self.generateAndExportButton.setFixedHeight(32) self.generateAndExportButton.clicked.connect(self.generateAndExportClicked) self.generateAndExportButton.setEnabled(False) self.pixmapWidget = PixmapWidget() self.pixmapWidget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.pixmapWidget.setPixmap(self.createDropTextPixmap()) self.pixmapWidget.dropSignal.connect(self.fileDropped) self.pixmapWidget.setMinimumHeight(300) # load settings self.tileWidthSpinBox.setValue(int(self.settings.value('tileWidth', 16))) self.tileHeightSpinBox.setValue(int(self.settings.value('tileHeight', 16))) self.paddingSpinBox.setValue(int(self.settings.value('padding', 1))) self.forcePotCheckBox.setChecked(True if self.settings.value('forcePot', 'true') == 'true' else False) self.reorderTilesCheckBox.setChecked(True if self.settings.value('reorderTiles', 'false') == 'true' else False) self.transparentCheckbox.setChecked(True if self.settings.value('transparent', 'false') == 'true' else False) self.backgroundColorEdit.setColorText(str(self.settings.value('backgroundColor', '#FF00FF'))) self.restoreGeometry(QByteArray(self.settings.value('MainWindow/geometry'))) self.restoreState(QByteArray(self.settings.value('MainWindow/windowState'))) # layout hl1 = QHBoxLayout() hl1.setContentsMargins(5, 5, 5, 5) hl1.addWidget(QLabel("Tile width:")) hl1.addSpacing(5) hl1.addWidget(self.tileWidthSpinBox) hl1.addSpacing(15) hl1.addWidget(QLabel("Tile height:")) hl1.addSpacing(5) hl1.addWidget(self.tileHeightSpinBox) hl1.addSpacing(15) hl1.addWidget(QLabel("Padding:")) hl1.addSpacing(5) hl1.addWidget(self.paddingSpinBox) hl1.addSpacing(15) hl1.addWidget(self.forcePotCheckBox) hl1.addSpacing(15) hl1.addWidget(self.reorderTilesCheckBox) hl1.addStretch() hl2 = QHBoxLayout() hl2.setContentsMargins(5, 5, 5, 5) hl2.addWidget(self.transparentCheckbox) hl2.addSpacing(15) hl2.addWidget(self.backgroundColorLabel) hl2.addSpacing(5) hl2.addWidget(self.backgroundColorEdit) hl2.addStretch() hl3 = QHBoxLayout() hl3.setContentsMargins(5, 5, 5, 5) hl3.addWidget(self.generateAndExportButton) vl = QVBoxLayout() vl.setContentsMargins(0, 0, 0, 0) vl.setSpacing(0) vl.addLayout(hl1) vl.addLayout(hl2) vl.addWidget(self.pixmapWidget) vl.addLayout(hl3) w = QWidget() w.setLayout(vl) self.setCentralWidget(w) self.setTitle()
def __init__(self): super(AsemblerIDE, self).__init__() self.workspace = None self.backupTimer = 300000 PathManager.START_DIRECTORY = os.getcwd() self.workspaceConfiguration = WorkspaceConfiguration.loadConfiguration( ) self.snippetManager = SnippetManager.loadSnippetConfiguration() self.tooltipManager = TooltipManager.loadTooltipConfiguration() self.configurationManager = ConfigurationManager() self.editorTabs = EditorTabWidget(self.snippetManager, self.tooltipManager) self.menuBar = MenuBar() self.terminal = Terminal() self.toolBar = ToolBar(self.configurationManager) self.statusBar = StatusBar() self.treeView = TreeView(self.configurationManager) self.help = HelpWidget() self.ascii = AsciiTableWidget() self.setStatusBar(self.statusBar) self.addToolBar(self.toolBar) self.addDockWidget(Qt.BottomDockWidgetArea, self.terminal) self.addDockWidget(Qt.RightDockWidgetArea, self.help) self.addDockWidget(Qt.RightDockWidgetArea, self.ascii) self.splitDockWidget(self.help, self.ascii, Qt.Vertical) self.treeDock = QDockWidget() self.treeDock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.treeDock.setStyleSheet("background-color: #2D2D30; color: white;") self.treeDock.setFeatures(QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetClosable) self.treeDock.setWindowTitle("Workspace explorer") self.treeDock.setWidget(self.treeView) header = QLabel("Workspace explorer") # header.setStyleSheet("background-color: #007ACC;") self.treeDock.setTitleBarWidget(header) self.addDockWidget(Qt.LeftDockWidgetArea, self.treeDock) self.setMenuBar(self.menuBar) self.setMinimumSize(1200, 800) self.setWindowTitle("i386 Assembly Integrated Development Environment") self.setCentralWidget(self.editorTabs) self.setStyleSheet("background-color: #3E3E42; color: white;") self.setWindowIcon(QIcon(resource_path("resources/app_icon.ico"))) self.addTabWidgetEventHandlers() self.addMenuBarEventHandlers() self.addToolBarEventHandlers() self.addTreeViewEventHandlers() self.checkWorkspaceConfiguration() #self.populateTreeView() #self.statusBar.comboBox.currentTextChanged.connect(self.changeEditorSyntax) self.statusBar.tabWidthComboBox.currentTextChanged.connect( self.changeEditorTabWidth) self.timer = QTimer() self.timer.start(self.backupTimer) self.timer.timeout.connect(self.makeBackupSave) self.terminal.console.setFocus() self.tabSwitcher = TabSwitcher(self.editorTabs) self.tabSwitcher.hide() self.projectSwitcher = ProjectSwitcher(self.configurationManager, self.toolBar.projectComboBox) self.projectSwitcher.hide() self.terminal.projectSwitchRequested.connect(self.showProjectSwitcher) self.terminal.tabSwitchRequested.connect(self.showTabSwitcher) self.editorTabs.tabSwitchRequested.connect(self.showTabSwitcher) self.editorTabs.projectSwitchRequested.connect( self.showProjectSwitcher) self.helpDocsDialog = GettingStartedDialog() self.helpDocsDialog.hide()
def createLabel(self, text): label = QLabel(text) label.setAlignment(Qt.AlignCenter) label.setMargin(2) label.setFrameStyle(QFrame.Box | QFrame.Sunken) return label
class SettingsWidget(QWidget): """Widget to show and edit the settings.""" def __init__(self): super(SettingsWidget, self).__init__() self.settings = QSettings(c.SETTINGS_PATH, QSettings.IniFormat) self.keyboard_settings = QSettings(c.KEYBOARD_SETTINGS_PATH, QSettings.IniFormat) self.value_dict_settings = {} self.value_dict_keyboard = {} self.f_reg = re.compile("F[1-9]|1[0-2]") self.ctrl_reg = re.compile("CTRL\+[a-xA-X0-9]") self.forbidden_reg = re.compile("CTRL\+[vVcCzZyY]") v_box = QVBoxLayout() theme = QGroupBox("Theme") theme_layout = QFormLayout() theme_value = QComboBox() theme_value.addItem(c.THEME_D) theme_value.addItem(c.THEME_L) theme_value.setCurrentText( self.settings.value(c.THEME, defaultValue=c.THEME_D)) theme_layout.addRow(QLabel(c.THEME.capitalize()), theme_value) theme.setLayout(theme_layout) self.value_dict_settings[c.THEME] = theme_value keyboard = QGroupBox("Keyboard") keyboard_layout = QFormLayout() info_label = QLabel("Only F-Keys and CTRL+ Combinations are allowed.") info_label.setWordWrap(True) keyboard_layout.addRow(info_label) for key in self.keyboard_settings.allKeys(): line_edit = QLineEdit() line_edit.setText(self.keyboard_settings.value(key)) keyboard_layout.addRow(key, line_edit) self.value_dict_keyboard[key] = line_edit keyboard.setLayout(keyboard_layout) plugins = QGroupBox("Plug-ins") plugins_layout = QFormLayout() show_empty_buttons_check = QCheckBox( "Show Plug-ins without Buttons in Word By Word - List") show_empty_buttons_check.setChecked( self.settings.value(c.SHOW_EMPTY_BUTTONS, defaultValue=True, type=bool)) plugins_layout.addRow(show_empty_buttons_check) self.value_dict_settings[ c.SHOW_EMPTY_BUTTONS] = show_empty_buttons_check plugins.setLayout(plugins_layout) self.note = QLabel("Settings will be applied after restart") save = QPushButton("Save") save.clicked.connect(self.save_values) v_box.addWidget(theme) v_box.addWidget(keyboard) v_box.addWidget(plugins) v_box.addWidget(self.note) v_box.addWidget(save) self.setLayout(v_box) def save_values(self): """Saves the current values.""" saved = True for key in self.value_dict_settings.keys(): widget = self.value_dict_settings.get(key) if isinstance(widget, QLineEdit): self.settings.setValue(key, widget.text().strip()) if isinstance(widget, QComboBox): self.settings.setValue(key, widget.currentText().strip()) if isinstance(widget, QCheckBox): self.settings.setValue(key, widget.isChecked()) occupied = [] self.keyboard_settings.clear() for key in self.value_dict_keyboard.keys(): value = self.value_dict_keyboard.get(key).text().strip().replace( " ", "").upper() if len(value) == 0 or ((bool(self.f_reg.search(value)) or bool(self.ctrl_reg.search(value))) and not bool(self.forbidden_reg.search(value))): if value not in occupied: self.keyboard_settings.setValue(key, value) if len(value) != 0: occupied.append(value) else: saved = False self.note.setStyleSheet("QLabel {color: red;}") self.note.setText("Duplicate Values found!") self.keyboard_settings.setValue(key, "") if saved: self.note.setStyleSheet("QLabel {color: green;}") self.note.setText("Saved!") def reset_note(self): """Resets the little now text at the bottom.""" self.note.setStyleSheet("") self.note.setText("Settings will be applied after restart")
class MainWindow(QMainWindow): def __init__(self, app, parent=None): super(MainWindow, self).__init__(parent) self.imagesDir = app.dir + '/images/' self.setWindowIcon(QIcon(self.imagesDir + 'icon.png')) self.path = '' self.settings = QSettings() self.lastDir = self.settings.value('lastDir', '') self.setMinimumWidth(540) self.supportedFormats = [] for f in QImageReader.supportedImageFormats(): self.supportedFormats.append(str(f.data(), encoding="utf-8")) self.fileWatcher = QFileSystemWatcher() self.fileWatcher.fileChanged.connect(self.fileChanged) # widgets self.showPixmapWidget = None self.tileWidthSpinBox = QSpinBox() self.tileWidthSpinBox.setValue(16) self.tileWidthSpinBox.setFixedWidth(50) self.tileWidthSpinBox.setMinimum(1) self.tileHeightSpinBox = QSpinBox() self.tileHeightSpinBox.setValue(16) self.tileHeightSpinBox.setFixedWidth(50) self.tileHeightSpinBox.setMinimum(1) self.paddingSpinBox = QSpinBox() self.paddingSpinBox.setFixedWidth(50) self.paddingSpinBox.setMinimum(1) self.transparentCheckbox = QCheckBox("Transparent") self.transparentCheckbox.setChecked(True) self.transparentCheckbox.stateChanged.connect(self.transparentChanged) self.backgroundColorEdit = ColorEdit() self.backgroundColorEdit.setEnabled(False) self.backgroundColorLabel = QLabel("Background color:") self.backgroundColorLabel.setEnabled(False) self.forcePotCheckBox = QCheckBox("Force PoT") self.forcePotCheckBox.setChecked(True) self.forcePotCheckBox.stateChanged.connect(self.forcePotChanged) self.reorderTilesCheckBox = QCheckBox("Reorder tiles") self.generateAndExportButton = QPushButton("Generate and export") self.generateAndExportButton.setFixedHeight(32) self.generateAndExportButton.clicked.connect(self.generateAndExportClicked) self.generateAndExportButton.setEnabled(False) self.pixmapWidget = PixmapWidget() self.pixmapWidget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.pixmapWidget.setPixmap(self.createDropTextPixmap()) self.pixmapWidget.dropSignal.connect(self.fileDropped) self.pixmapWidget.setMinimumHeight(300) # load settings self.tileWidthSpinBox.setValue(int(self.settings.value('tileWidth', 16))) self.tileHeightSpinBox.setValue(int(self.settings.value('tileHeight', 16))) self.paddingSpinBox.setValue(int(self.settings.value('padding', 1))) self.forcePotCheckBox.setChecked(True if self.settings.value('forcePot', 'true') == 'true' else False) self.reorderTilesCheckBox.setChecked(True if self.settings.value('reorderTiles', 'false') == 'true' else False) self.transparentCheckbox.setChecked(True if self.settings.value('transparent', 'false') == 'true' else False) self.backgroundColorEdit.setColorText(str(self.settings.value('backgroundColor', '#FF00FF'))) self.restoreGeometry(QByteArray(self.settings.value('MainWindow/geometry'))) self.restoreState(QByteArray(self.settings.value('MainWindow/windowState'))) # layout hl1 = QHBoxLayout() hl1.setContentsMargins(5, 5, 5, 5) hl1.addWidget(QLabel("Tile width:")) hl1.addSpacing(5) hl1.addWidget(self.tileWidthSpinBox) hl1.addSpacing(15) hl1.addWidget(QLabel("Tile height:")) hl1.addSpacing(5) hl1.addWidget(self.tileHeightSpinBox) hl1.addSpacing(15) hl1.addWidget(QLabel("Padding:")) hl1.addSpacing(5) hl1.addWidget(self.paddingSpinBox) hl1.addSpacing(15) hl1.addWidget(self.forcePotCheckBox) hl1.addSpacing(15) hl1.addWidget(self.reorderTilesCheckBox) hl1.addStretch() hl2 = QHBoxLayout() hl2.setContentsMargins(5, 5, 5, 5) hl2.addWidget(self.transparentCheckbox) hl2.addSpacing(15) hl2.addWidget(self.backgroundColorLabel) hl2.addSpacing(5) hl2.addWidget(self.backgroundColorEdit) hl2.addStretch() hl3 = QHBoxLayout() hl3.setContentsMargins(5, 5, 5, 5) hl3.addWidget(self.generateAndExportButton) vl = QVBoxLayout() vl.setContentsMargins(0, 0, 0, 0) vl.setSpacing(0) vl.addLayout(hl1) vl.addLayout(hl2) vl.addWidget(self.pixmapWidget) vl.addLayout(hl3) w = QWidget() w.setLayout(vl) self.setCentralWidget(w) self.setTitle() def setTitle(self): p = ' - ' + os.path.basename(self.path) if self.path else '' self.setWindowTitle(QCoreApplication.applicationName() + ' ' + QCoreApplication.applicationVersion() + p) def createDropTextPixmap(self): pixmap = QPixmap(481, 300) pixmap.fill(QColor("#333333")) painter = QPainter(pixmap) font = QFont("Arial") font.setPixelSize(28) font.setBold(True) fm = QFontMetrics(font) painter.setFont(font) painter.setPen(QPen(QColor("#888888"), 1)) text = "Drop the tileset image here" x = (pixmap.width()-fm.width(text))/2 y = (pixmap.height()+fm.height())/2 painter.drawText(x, y, text) del painter return pixmap def fileDropped(self, path): path = str(path) name, ext = os.path.splitext(path) ext = ext[1:] if not ext in self.supportedFormats: QMessageBox.warning(self, "Warning", "The dropped file is not supported") return pixmap = QPixmap(path) if pixmap.isNull(): QMessageBox.warning(self, "Warning", "Can't load the image") return if self.path: self.fileWatcher.removePath(self.path) self.path = path self.fileWatcher.addPath(self.path) self.pixmapWidget.setPixmap(pixmap) self.generateAndExportButton.setEnabled(True) self.setTitle() self.activateWindow() def fileChanged(self, path): #self.fileDropped(path) pass def transparentChanged(self): e = self.transparentCheckbox.isChecked() self.backgroundColorEdit.setEnabled(not e) self.backgroundColorLabel.setEnabled(not e) def forcePotChanged(self): e = self.forcePotCheckBox.isChecked() self.reorderTilesCheckBox.setEnabled(e) def generateAndExportClicked(self): g = Generator() g.tileWidth = self.tileWidthSpinBox.value() g.tileHeight = self.tileHeightSpinBox.value() g.forcePot = self.forcePotCheckBox.isChecked() g.isTransparent = self.transparentCheckbox.isChecked() g.bgColor = self.backgroundColorEdit.getColor() g.reorder = self.reorderTilesCheckBox.isChecked() g.padding = self.paddingSpinBox.value() target = g.create(self.pixmapWidget.pixmap); # export self.lastDir = os.path.dirname(self.path) targetPath = QFileDialog.getSaveFileName(self, 'Export', self.lastDir, 'PNG (*.png)') if targetPath: target.save(targetPath[0]) showPixmap = QPixmap.fromImage(target) if self.showPixmapWidget: self.showPixmapWidget.deleteLater() del self.showPixmapWidget self.showPixmapWidget = PixmapWidget() self.showPixmapWidget.setWindowIcon(self.windowIcon()) self.showPixmapWidget.setWindowTitle(os.path.basename(targetPath[0])) self.showPixmapWidget.resize(showPixmap.width(), showPixmap.height()) self.showPixmapWidget.setPixmap(showPixmap) self.showPixmapWidget.show() def closeEvent(self, event): if self.showPixmapWidget: self.showPixmapWidget.close() # save settings self.settings.setValue('tileWidth', self.tileWidthSpinBox.value()) self.settings.setValue('tileHeight', self.tileHeightSpinBox.value()) self.settings.setValue('padding', self.paddingSpinBox.value()) self.settings.setValue('forcePot', self.forcePotCheckBox.isChecked()) self.settings.setValue('reorderTiles', self.reorderTilesCheckBox.isChecked()) self.settings.setValue('transparent', self.transparentCheckbox.isChecked()) self.settings.setValue('backgroundColor', self.backgroundColorEdit.getColor().name()) self.settings.setValue('lastDir', self.lastDir) self.settings.setValue('MainWindow/geometry', self.saveGeometry()) self.settings.setValue('MainWindow/windowState', self.saveState()) super(MainWindow, self).closeEvent(event)
def __init__(self): super(SettingsWidget, self).__init__() self.settings = QSettings(c.SETTINGS_PATH, QSettings.IniFormat) self.keyboard_settings = QSettings(c.KEYBOARD_SETTINGS_PATH, QSettings.IniFormat) self.value_dict_settings = {} self.value_dict_keyboard = {} self.f_reg = re.compile("F[1-9]|1[0-2]") self.ctrl_reg = re.compile("CTRL\+[a-xA-X0-9]") self.forbidden_reg = re.compile("CTRL\+[vVcCzZyY]") v_box = QVBoxLayout() theme = QGroupBox("Theme") theme_layout = QFormLayout() theme_value = QComboBox() theme_value.addItem(c.THEME_D) theme_value.addItem(c.THEME_L) theme_value.setCurrentText( self.settings.value(c.THEME, defaultValue=c.THEME_D)) theme_layout.addRow(QLabel(c.THEME.capitalize()), theme_value) theme.setLayout(theme_layout) self.value_dict_settings[c.THEME] = theme_value keyboard = QGroupBox("Keyboard") keyboard_layout = QFormLayout() info_label = QLabel("Only F-Keys and CTRL+ Combinations are allowed.") info_label.setWordWrap(True) keyboard_layout.addRow(info_label) for key in self.keyboard_settings.allKeys(): line_edit = QLineEdit() line_edit.setText(self.keyboard_settings.value(key)) keyboard_layout.addRow(key, line_edit) self.value_dict_keyboard[key] = line_edit keyboard.setLayout(keyboard_layout) plugins = QGroupBox("Plug-ins") plugins_layout = QFormLayout() show_empty_buttons_check = QCheckBox( "Show Plug-ins without Buttons in Word By Word - List") show_empty_buttons_check.setChecked( self.settings.value(c.SHOW_EMPTY_BUTTONS, defaultValue=True, type=bool)) plugins_layout.addRow(show_empty_buttons_check) self.value_dict_settings[ c.SHOW_EMPTY_BUTTONS] = show_empty_buttons_check plugins.setLayout(plugins_layout) self.note = QLabel("Settings will be applied after restart") save = QPushButton("Save") save.clicked.connect(self.save_values) v_box.addWidget(theme) v_box.addWidget(keyboard) v_box.addWidget(plugins) v_box.addWidget(self.note) v_box.addWidget(save) self.setLayout(v_box)
class G27CalibGui(QWidget): sendModeCmd = Signal(object) setObjectCmd = Signal(object) def __init__(self): super().__init__() self.tl_layout = QGridLayout(self) rbtn_values = QGroupBox("Calibration Values", self) vbox = QVBoxLayout(rbtn_values) self.mode_btns = [ QRadioButton(s, rbtn_values) for s in [ "Idle", "Shifter neutral zone", "Shifter 135 zone", "Shifter 246R zone", "Shifter 12 zone", "Shifter 56 zone", "Gas pedal (if not auto-calibrated)", "Brake pedal (if not auto-calibrated)", "Clutch pedal (if not auto-calibrated)" ] ] self.mode_btns[0].setChecked(True) self.mode_cmds = [b"i", b"n", b"u", b"b", b"l", b"r", b"G", b"B", b"C"] self.help_cmds = [ "First decide about the filtering needed (in middle panel). If there is a lot of noise in the signal, " "maybe because of old pots, you might want to use a multi-sample median filter. Note that this filter " "introduces some delay, so you want to keep the numbers reasonable low. Afterwards, iterate through " "the calibration values in the left panel.\n\n" "When you're done, you can save the calibration in the right panel to the EEPROM.", "Put the shifter in neutral position. Afterwards, keep the left red button pressed and move the " "shifter while still in neutral. When reaching the calibrated area, the gear will be set to neutral.", "Put the shifter in 3rd gear. Afterwards keep the left red button pressed and move the shifter " "while still in 3rd gear. When done, release the red button. Optionally repeat for gears 1st and 5th.", "Put the shifter in 4th gear. Afterwards keep the left red button pressed and move the shifter " "while still in 4th gear. When done, release the red button. Optionally repeat for gears 2nd and 6th.", "Put the shifter in 1st gear. Afterwards keep the left red button pressed and move the shifter " "while still in 1st gear. When done, release the red button. Optionally repeat for 2nd gear.", "Put the shifter in 5th gear. Afterwards keep the left red button pressed and move the shifter " "while still in 5th gear. When done, release the red button. Optionally repeat for 6th gear.", "Move the gas pedal multiple times between lowest and highest position.", "Move the brake pedal multiple times between lowest and highest position.", "Move the clutch pedal multiple times between lowest and highest position." ] for b in self.mode_btns: vbox.addWidget(b) b.toggled.connect(self.modeChanged) self.tl_layout.addWidget(rbtn_values, 0, 0, 1, 1) cbtn_options = QGroupBox("Options", self) grid = QGridLayout(cbtn_options) self.option_btns = [ QCheckBox(s, cbtn_options) for s in [ "Enable pedal auto-calibration", "Invert gas/throttle pedal", "Invert brake pedal", "Invert clutch pedal", "Use right red button for reverse instead pushing the gear", "Enable pedals", "Enable shifter" ] ] + [ QComboBox(), QComboBox(), QComboBox(), QComboBox(), QComboBox(), QComboBox() ] self.option_cmds = [ (b"p", b"P"), #0 (b"y", b"Y"), #1 (b"x", b"X"), #2 (b"z", b"Z"), #3 (b"q", b"Q"), #4 (b"e", b"E"), #5 (b"s", b"S"), #6 (b".", b"+", b"-"), #7 (b"[^", b"[!", b"[\"", b"[]", b"[$", b"[%", b"[&", b"[/"), (b"(^", b"(!", b"(\"", b"(]", b"($", b"(%", b"(&", b"(/"), (b")^", b")!", b")\"", b")]", b")$", b")%", b")&", b")/"), (b"0", b"3", b"5", b"7", b"9", b"f"), (b"1", b"2", b"4", b"6", b"8", b"F"), ] self.option_btns[-6].addItem("Do not combine clutch and gas") self.option_btns[-6].addItem( "Combine Clutch and Gas (Clutch = Gas - Clutch)") self.option_btns[-6].addItem( "Combine Clutch and Gas (Clutch = Clutch - Gas)") for (idx, name) in [(-5, "Gas"), (-4, "Brake"), (-3, "Clutch")]: for dz in [0, 2, 4, 6, 8, 10, 12, 14]: self.option_btns[idx].addItem("%s: %d%% dead zone" % (name, dz)) for (idx, name) in [(-2, "pedals"), (-1, "shifter")]: for size in [0, 3, 5, 9, 15, 49]: self.option_btns[idx].addItem( "off" if size == 0 else (str(size) + "-median"), size) for i, b in enumerate(self.option_btns): n_checkboxes = len(self.option_cmds) - 6 if i < n_checkboxes: grid.addWidget(b, i, 0, 1, 2) else: names = { n_checkboxes: "Combine", n_checkboxes + 1: "Gas Dead Zone", n_checkboxes + 2: "Brake Dead Zone", n_checkboxes + 3: "Clutch Dead Zone", n_checkboxes + 4: "Pedal filter", n_checkboxes + 5: "Shifter filter" } grid.addWidget(QLabel(names[i], parent=self), i, 0) grid.addWidget(b, i, 1) if isinstance(b, QCheckBox): b.toggled.connect(self.optionChanged) else: b.currentIndexChanged.connect(self.optionChanged) self.tl_layout.addWidget(cbtn_options, 0, 1, 1, 1) cbtn_persistent = QGroupBox("Persistency") self.persistent_btns = [ QPushButton(s, parent=self) for s in ["Save to EEPROM", "Load from EEPROM", "Defaults"] ] self.persistent_cmds = [b"w", b"U", b"c"] vbox = QVBoxLayout(cbtn_persistent) for i, b in enumerate(self.persistent_btns): vbox.addWidget(b) b.clicked.connect(self.persistent_cmd) self.tl_layout.addWidget(cbtn_persistent, 0, 2, 1, 1) self.helpArea = QLabel(self.help_cmds[0], self) self.helpArea.setWordWrap(True) f = self.helpArea.font() f.setBold(True) f.setPointSizeF(f.pointSizeF() * 1.5) self.helpArea.setFont(f) self.tl_layout.addWidget(self.helpArea, 0, 3, 1, 1) shifter_label = QLabel("Shifter") self.tl_layout.addWidget(shifter_label, 1, 2, 1, 2, alignment=Qt.AlignHCenter) shifter_plot = pg.PlotWidget(parent=self) shifter_plot.setMouseEnabled(x=False, y=False) self.tl_layout.addWidget(shifter_plot, 2, 2, 1, 2) shifter_plot.setRange(QRectF(0, 0, 1023, 1023), padding=0) pi = shifter_plot.getPlotItem() self.shifter_neutral_plot = pg.LinearRegionItem( values=(400, 600), orientation='horizontal', movable=False, brush=QBrush(QColor(200, 50, 50, 50)), pen=QPen(QColor(200, 50, 50))) shifter_plot.addItem(self.shifter_neutral_plot) self.shifter_135_plot = pg.LinearRegionItem( values=(800, 1024), orientation='horizontal', movable=False, brush=QBrush(QColor(50, 200, 50, 50)), pen=QPen(QColor(50, 200, 50))) shifter_plot.addItem(self.shifter_135_plot) self.shifter_246_plot = pg.LinearRegionItem( values=(0, 200), orientation='horizontal', movable=False, brush=QBrush(QColor(50, 50, 200, 50)), pen=QPen(QColor(50, 50, 200))) shifter_plot.addItem(self.shifter_246_plot) self.shifter_12_plot = pg.LinearRegionItem( values=(0, 200), orientation='vertical', movable=False, brush=QBrush(QColor(50, 200, 200, 50)), pen=QPen(QColor(50, 200, 200))) shifter_plot.addItem(self.shifter_12_plot) self.shifter_56_plot = pg.LinearRegionItem( values=(800, 1024), orientation='vertical', movable=False, brush=QBrush(QColor(200, 200, 50, 50)), pen=QPen(QColor(200, 200, 50))) shifter_plot.addItem(self.shifter_56_plot) self.shifter_pos_plot = pi.plot(x=[512], y=[512], symbol='+', pen=None) pedals_label = QLabel("Pedals") self.tl_layout.addWidget(pedals_label, 1, 0, 1, 2, alignment=Qt.AlignHCenter) pedals_plot = pg.PlotWidget(parent=self) pedals_plot.setMouseEnabled(x=False, y=False) pedals_plot.setRange(QRectF(-1, 0, 4, 1023), padding=0) pedals_plot.getAxis('bottom').setTicks([[(0.0, "Gas/Throttle"), (1.0, "Brake"), (2.0, "Clutch")], []]) self.tl_layout.addWidget(pedals_plot, 2, 0, 1, 2) self.pedals_pos_plot = pg.BarGraphItem(x=np.arange(3), height=[512, 512, 512], width=0.5) self.pedals_gas_calib_plot = pedals_plot.getPlotItem().plot( x=[0], y=[0], pen=QPen(QColor(255, 0, 0), width=0.1), brush=QBrush(Qt.NoBrush)) self.pedals_brake_calib_plot = pedals_plot.getPlotItem().plot( x=[0], y=[0], pen=QPen(QColor(0, 255, 0))) self.pedals_clutch_calib_plot = pedals_plot.getPlotItem().plot( x=[0], y=[0], pen=QPen(QColor(0, 0, 255))) self.pedals_pos_plot2 = pedals_plot.getPlotItem().plot(x=[], y=[], symbol='+', pen=None) pedals_plot.addItem(self.pedals_pos_plot) self.status_line = QLabel(self) self.tl_layout.addWidget(self.status_line, 3, 0, 1, 2) self.status_line2 = QLabel(self) self.tl_layout.addWidget(self.status_line2, 3, 2, 1, 2) self.currentVals = Values() def modeChanged(self, toggled): if toggled: o = self.sender() idx = self.mode_btns.index(o) self.sendModeCmd.emit(self.mode_cmds[idx]) self.helpArea.setText(self.help_cmds[idx]) def optionChanged(self, option): o = self.sender() idx = self.option_btns.index(o) self.sendModeCmd.emit(self.option_cmds[idx][int(option)]) def persistent_cmd(self): o = self.sender() idx = self.persistent_btns.index(o) self.sendModeCmd.emit(self.persistent_cmds[idx]) def newVals(self, values, dbg): updateRate = 0.040 * 1e9 # 25 Hz if len(self.currentVals.times) == 0 or ( len(values.times) > 0 and values.times[-1] > self.currentVals.times[-1] + updateRate): # each 10ms self.currentVals.add(values) values = self.currentVals self.pedals_pos_plot.setOpts( height=[values.gas[-1], values.brake[-1], values.clutch[-1]]) self.pedals_pos_plot2.setData(x=np.concatenate( ([-0.35] * len(values.gas), [0.65] * len(values.brake), [1.65] * len(values.clutch))), y=np.concatenate( (values.gas, values.brake, values.clutch))) self.pedals_gas_calib_plot.setPen(QPen(QColor(255, 0, 0), width=0)) self.pedals_gas_calib_plot.setData( x=[-0.0, -0.0, +0.0, +0.0, -0.0], y=[ values.calib.gasMin, values.calib.gasMax, values.calib.gasMax, values.calib.gasMin, values.calib.gasMin ]) self.pedals_brake_calib_plot.setData(x=[1.0, 1.0, 1.0, 1.0, 1.0], y=[ values.calib.brakeMin, values.calib.brakeMax, values.calib.brakeMax, values.calib.brakeMin, values.calib.brakeMin ]) self.pedals_clutch_calib_plot.setData(x=[2.0, 2.0, 2.0, 2.0, 2.0], y=[ values.calib.clutchMin, values.calib.clutchMax, values.calib.clutchMax, values.calib.clutchMin, values.calib.clutchMin ]) self.shifter_pos_plot.setData(x=values.sx, y=values.sy) self.shifter_neutral_plot.setRegion( (values.calib.shifter_y_neutralMin, values.calib.shifter_y_neutralMax)) self.shifter_135_plot.setRegion( (values.calib.shifter_y_135_gearZone, 1024)) self.shifter_246_plot.setRegion( (0, values.calib.shifter_y_246R_gearZone)) self.shifter_12_plot.setRegion((0, values.calib.shifter_x_12)) self.shifter_56_plot.setRegion((values.calib.shifter_x_56, 1024)) blockers = [] for b in self.option_btns: blockers.append(QSignalBlocker(b)) self.option_btns[0].setChecked(values.calib.pedals_auto_calib) self.option_btns[1].setChecked( (values.calib.flag1 & FLAG1_INVERT_GAS) != 0) self.option_btns[2].setChecked( (values.calib.flag1 & FLAG1_INVERT_BRAKE) != 0) self.option_btns[3].setChecked( (values.calib.flag1 & FLAG1_INVERT_CLUTCH) != 0) self.option_btns[4].setChecked( (values.calib.flag1 & FLAG1_REVERSE_RIGHT_RED) != 0) self.option_btns[5].setChecked( (values.calib.flag2 & FLAG2_ENABLE_PEDALS) != 0) self.option_btns[6].setChecked( (values.calib.flag3 & FLAG3_ENABLE_SHIFTER) != 0) if (values.calib.flag1 & (FLAG1_COMBINE_Z_EQUALS_X_MINUS_Z | FLAG1_COMBINE_Z_EQUALS_Z_MINUS_X)) == 0: self.option_btns[7].setCurrentIndex(0) elif (values.calib.flag1 & FLAG1_COMBINE_Z_EQUALS_X_MINUS_Z) != 0: self.option_btns[7].setCurrentIndex(1) else: self.option_btns[7].setCurrentIndex(2) self.option_btns[8].setCurrentIndex((values.calib.flag2 & FLAG2_GAS_DEAD_ZONE) >> 4) self.option_btns[9].setCurrentIndex((values.calib.flag2 & FLAG2_BRAKE_DEAD_ZONE) >> 1) self.option_btns[10].setCurrentIndex( (values.calib.flag3 & FLAG3_CLUTCH_DEAD_ZONE) >> 4) self.option_btns[11].setCurrentIndex(self.option_btns[11].findData( values.calib.pedals_median_size)) self.option_btns[12].setCurrentIndex(self.option_btns[12].findData( values.calib.shifter_median_size)) prof = "Total runtime: %9.2f ms | prof[0->1]: %9.2f ms | prof[1->2]: %9.2f ms | prof[2->3]: %9.2f ms | FPS: %04d" % ( (dbg.profiling[-1] - dbg.profiling[0]) * 1e-3, (dbg.profiling[1] - dbg.profiling[0]) * 1e-3, (dbg.profiling[2] - dbg.profiling[1]) * 1e-3, (dbg.profiling[3] - dbg.profiling[2]) * 1e-3, ((len(values.times) * 1e9 / (values.times[-1] - values.times[0])) if len(values.times) > 1 else "N/A"), ) self.status_line.setText(prof) # output values s = "" if dbg.out_axis[0] != 0xffff: s += "A0=%04d A1=%04d A2=%04d " % tuple(dbg.out_axis) else: s += "A0=N/A A1=N/A A2=N/A " if dbg.out_buttons != 0xffffffff: bstr = "{:019b}".format(dbg.out_buttons) s += "ShifterBtn: " + bstr[:-7] gear = bstr[-7:][::-1] if "1" in gear: gear = gear.index("1") + 1 else: gear = 0 s += " ShifterGear=%d" % (gear) else: s += "Shifter=N/A" self.status_line2.setText(s)
class RunTab(QtWidgets.QWidget): run_checks = QtCore.Signal() def __init__(self, prj: QAXProject): super(RunTab, self).__init__() self.prj = prj self.check_executor = None self.vbox = QtWidgets.QVBoxLayout() self.setLayout(self.vbox) self._add_check_outputs() self._add_process() # final setup self.set_run_stop_buttons_enabled(False) def _add_check_outputs(self): co_groupbox = QGroupBox("Check outputs") co_groupbox.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) co_layout = QVBoxLayout() co_layout.setSpacing(16) co_groupbox.setLayout(co_layout) self.qajson_spatial_checkbox = QCheckBox( "Include summary spatial output in QAJSON. " "Supports QAX visualisation.") self.qajson_spatial_checkbox.setCheckState( QtCore.Qt.CheckState.Checked) co_layout.addWidget(self.qajson_spatial_checkbox) export_layout = QVBoxLayout() export_layout.setSpacing(4) self.export_spatial_checkbox = QCheckBox( "Export detailed spatial outputs to file. " "Supports visualisation in other geospatial applications.") self.export_spatial_checkbox.stateChanged.connect( self._on_export_spatial_changed) export_layout.addWidget(self.export_spatial_checkbox) output_folder_layout = QHBoxLayout() output_folder_layout.setSpacing(4) output_folder_layout.addSpacerItem(QtWidgets.QSpacerItem(37, 20)) self.output_folder_label = QLabel( "Detailed spatial output folder location:") output_folder_layout.addWidget(self.output_folder_label) self.output_folder_input = QLineEdit() self.output_folder_input.setText( GuiSettings.settings().value("spatial_outputs")) self.output_folder_input.setMinimumWidth(300) self.output_folder_input.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) output_folder_layout.addWidget(self.output_folder_input) self.open_output_folder_button = QPushButton() output_folder_layout.addWidget(self.open_output_folder_button) self.open_output_folder_button.setIcon(qta.icon('fa.folder-open')) self.open_output_folder_button.setToolTip( f"Select file containing data") self.open_output_folder_button.clicked.connect( self._click_open_spatial_export_folder) export_layout.addLayout(output_folder_layout) co_layout.addLayout(export_layout) self._on_export_spatial_changed() self.vbox.addWidget(co_groupbox) def _click_open_spatial_export_folder(self): output_folder = QFileDialog.getExistingDirectory( self, f"Select folder for spatial outputs", GuiSettings.settings().value("spatial_outputs"), QFileDialog.ShowDirsOnly) if os.path.exists(output_folder): GuiSettings.settings().setValue("spatial_outputs", output_folder) self.output_folder_input.setText(output_folder) def _on_export_spatial_changed(self): is_export = self.export_spatial_checkbox.isChecked() self.output_folder_label.setEnabled(is_export) self.output_folder_input.setEnabled(is_export) self.open_output_folder_button.setEnabled(is_export) def _add_process(self): process_groupbox = QGroupBox("Process") process_groupbox.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) process_layout = QVBoxLayout() process_layout.setSpacing(0) process_groupbox.setLayout(process_layout) pbar_frame = QFrame() pbar_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) pbar_hbox = QHBoxLayout() pbar_hbox.setContentsMargins(QtCore.QMargins(0, 0, 0, 16)) pbar_hbox.setSpacing(16) # Run and stop buttons hbox = QHBoxLayout() hbox.setSpacing(8) self.run_button = QPushButton() # is only enabled when validation passes self.run_button.setEnabled(False) self.run_button.setText("Run") self.run_button.setToolTip("Start check execution") self.run_button.setFixedWidth(100) run_icon = qta.icon('fa.play', color='green') self.run_button.setIcon(run_icon) self.run_button.clicked.connect(self._click_run) hbox.addWidget(self.run_button) self.stop_button = QPushButton() self.stop_button.setEnabled(False) self.stop_button.setText("Stop") self.stop_button.setToolTip("Stop check execution") self.stop_button.setFixedWidth(100) stop_icon = qta.icon('fa.stop', color='red') self.stop_button.setIcon(stop_icon) self.stop_button.clicked.connect(self._click_stop) hbox.addWidget(self.stop_button) self.progress_bar = QProgressBar() self.progress_bar.setTextVisible(True) self.progress_bar.setAlignment(QtCore.Qt.AlignCenter) self.progress_bar.setValue(0) self.progress_bar.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) pbar_hbox.addLayout(hbox) pbar_hbox.addWidget(self.progress_bar) pbar_frame.setLayout(pbar_hbox) process_layout.addWidget(pbar_frame) vbox = QVBoxLayout() vbox.setSpacing(8) vbox.setContentsMargins(QtCore.QMargins(0, 0, 0, 16)) process_layout.addLayout(vbox) hbox = QHBoxLayout() vbox.addLayout(hbox) check_name_label = QLabel("Check:") check_name_label.setFixedWidth(80) hbox.addWidget(check_name_label) self.check_name_text_label = QLabel("n/a") hbox.addWidget(self.check_name_text_label) hbox = QHBoxLayout() vbox.addLayout(hbox) status_name_label = QLabel("Status:") status_name_label.setFixedWidth(80) hbox.addWidget(status_name_label) self.status_name_text_label = QLabel("Not started") hbox.addWidget(self.status_name_text_label) self.warning_frame = QFrame() self.warning_frame.setVisible(False) self.warning_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) hbox = QHBoxLayout() warning_icon_widget = qta.IconWidget('fa.warning', color='red') warning_icon_widget.setIconSize(QtCore.QSize(48, 48)) warning_icon_widget.update() hbox.addWidget(warning_icon_widget) warning_label = QLabel( "Grid Transformer did not complete successfully. Please refer to " "log output.") warning_label.setStyleSheet("QLabel { color: red; }") warning_label.setWordWrap(True) warning_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) hbox.addWidget(warning_label) self.warning_frame.setLayout(hbox) process_layout.addWidget(self.warning_frame) self.success_frame = QFrame() self.success_frame.setVisible(False) self.success_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) hbox = QHBoxLayout() success_icon_widget = qta.IconWidget('fa.check', color='green') success_icon_widget.setIconSize(QtCore.QSize(48, 48)) success_icon_widget.update() hbox.addWidget(success_icon_widget) success_label = QLabel("All checks completed successfully.") success_label.setStyleSheet("QLabel { color: green; }") success_label.setWordWrap(True) success_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) hbox.addWidget(success_label) self.success_frame.setLayout(hbox) process_layout.addWidget(self.success_frame) log_layout = QVBoxLayout() log_layout.setSpacing(4) log_label = QLabel("Log messages") log_label.setStyleSheet("QLabel { color: grey; }") log_layout.addWidget(log_label) self.log_messages = QPlainTextEdit() log_font = QFont("monospace") log_font.setStyleHint(QFont.TypeWriter) self.log_messages.setFont(log_font) self.log_messages.setReadOnly(True) self.log_messages.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) log_layout.addWidget(self.log_messages) process_layout.addLayout(log_layout) self.vbox.addWidget(process_groupbox) def set_run_stop_buttons_enabled(self, is_running: bool) -> NoReturn: if is_running: self.run_button.setEnabled(False) self.stop_button.setEnabled(True) else: self.run_button.setEnabled(True) self.stop_button.setEnabled(False) def _log_message(self, message): self.log_messages.appendPlainText(message) def run_executor(self, check_executor: QtCheckExecutorThread): # we pass the check_executor into the run tab as this is where the UI # components are that will display the execution status. self.set_run_stop_buttons_enabled(True) self._log_message("Check execution started") self.start_time = time.perf_counter() self.check_executor = check_executor self.check_executor.options = self.get_options() self.check_executor.check_tool_started.connect( self._on_check_tool_started) self.check_executor.progress.connect(self._on_progress) self.check_executor.qajson_updated.connect(self._on_qajson_update) self.check_executor.checks_complete.connect(self._on_checks_complete) self.check_executor.status_changed.connect(self._on_status_change) self.check_executor.start() def get_options(self) -> Dict: ''' Gets a list of options based on user entered data. eg; the spatial output specifications. ''' return { CheckOption.spatial_output_qajson: self.qajson_spatial_checkbox.isChecked(), CheckOption.spatial_output_export: self.export_spatial_checkbox.isChecked(), CheckOption.spatial_output_export_location: self.output_folder_input.text() } def _click_run(self): self.run_checks.emit() def _click_stop(self): if self.check_executor is None: logger.warn("Check executor does not exist, cannot stop") return self._log_message("Stopping check execution") self.check_executor.stop() @QtCore.Slot(float) def _on_progress(self, progress): self.progress_bar.setValue(int(progress * 100)) @QtCore.Slot() def _on_qajson_update(self): self.prj.qa_json = self.check_executor.qa_json @QtCore.Slot(object) def _on_check_tool_started(self, tpl): check_tool_name, check_number, total_check_count = tpl self.check_name_text_label.setText("{} ({}/{})".format( check_tool_name, check_number, total_check_count)) @QtCore.Slot() def _on_checks_complete(self): run_time = time.perf_counter() - self.start_time self._log_message( f"Execution time for all checks = {run_time:.2f} sec") self._log_message("\n\n") self.set_run_stop_buttons_enabled(False) self.prj.qa_json = self.check_executor.qa_json @QtCore.Slot(str) def _on_status_change(self, status): self.status_name_text_label.setText(status)
class ToolBox(QVBoxLayout): sig = QtCore.Signal(object) listThread = None groupBoxThreadInfo = None threadvbox = None mode = None def __init__(self, mode, parentQWidget = None): QVBoxLayout.__init__(self) self.sig.connect(self.addThreadList) self.mode = mode self.sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding) self.groupBoxSearch = QGroupBox() self.groupBoxSearch.setStyleSheet("QGroupBox {border: 1px solid gray; border-radius: 4px; };") vboxSearch = QVBoxLayout() self.searchTitle = QLabel("Search Messages") vboxSearch.addWidget(self.searchTitle) self.searchHLayout = QHBoxLayout() self.editTextSearch = QTextEdit('') self.editTextSearch.setFixedSize(200,30) self.buttonSearch = QPushButton('Search') self.buttonSearch.setFixedSize(100,30) self.buttonSearch.clicked.connect(self.searchMsg) vboxSearch.addWidget(self.editTextSearch) self.searchHLayout.addWidget(self.buttonSearch) self.searchCursor = QLabel() self.searchHLayout.addWidget(self.searchCursor) vboxSearch.addLayout(self.searchHLayout) self.browseHLayout = QHBoxLayout() self.buttonLookUp = QPushButton('\u21e7') #Arrow up self.buttonLookUp.setFixedWidth(100) self.buttonLookUp.clicked.connect(self.moveToPrev) self.buttonLookDown = QPushButton('\u21e9') #Arrow down self.buttonLookDown.setFixedWidth(100) self.buttonLookDown.clicked.connect(self.moveToNext) self.browseHLayout.addWidget(self.buttonLookUp) self.browseHLayout.addWidget(self.buttonLookDown) vboxSearch.addLayout(self.browseHLayout) self.groupBoxSearch.setLayout(vboxSearch) self.addWidget(self.groupBoxSearch) self.groupBoxSearch.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) self.buttonHiddenLifelines = QPushButton('Show hidden life-lines') self.buttonHiddenLifelines.setFixedWidth(200) self.buttonHiddenLifelines.clicked.connect(self.showHiddenLifelines) self.addWidget(self.buttonHiddenLifelines) self.buttonHiddenMessages = QPushButton('Show hidden Messages') self.buttonHiddenMessages.setFixedWidth(200) self.buttonHiddenMessages.clicked.connect(self.showHiddenMessages) self.addWidget(self.buttonHiddenMessages) if const.mode_interactive == mode: self.buttonCapture = QPushButton('Capture') self.buttonCapture.setFixedWidth(200) self.buttonCapture.clicked.connect(self.notifyCapture) self.addWidget(self.buttonCapture) self.msgRcv = [] self.msgInfo = QLabel("Message Info.") self.groupBoxMessageInfo = QGroupBox() self.groupBoxMessageInfo.setStyleSheet("QGroupBox {border: 1px solid gray; border-radius: 9px; margin-top: 0.5em} QGroupBox::title {subcontrol-origin: margin; left: 10px; padding: 0 3px 0 3px;") vbox = QVBoxLayout() vbox.addWidget(self.msgInfo) self.tableTime = QTableWidget(3,2) self.tableTime.setHorizontalHeaderLabels(['-','time']) self.tableTime.setColumnWidth(0,80) self.tableTime.setColumnWidth(1,150) vwidth = self.tableTime.verticalHeader().length() hwidth = self.tableTime.horizontalHeader().height() fwidth = self.tableTime.frameWidth() * 2 self.tableTime.setFixedHeight(vwidth + hwidth + fwidth) self.tableTime.horizontalHeader().setStretchLastSection(True) self.tableTime.setItem(0,0,QTableWidgetItem('begin')) self.tableTime.setItem(0,1,QTableWidgetItem(' - ')) self.tableTime.setItem(1,0,QTableWidgetItem('end')) self.tableTime.setItem(1,1,QTableWidgetItem(' - ')) self.tableTime.setItem(2,0,QTableWidgetItem('duration')) self.tableTime.setItem(2,1,QTableWidgetItem(' - ')) vbox.addWidget(self.tableTime) self.titleArg = QLabel('Argument List') vbox.addWidget(self.titleArg) max_arg_num = 10 self.tableArgs = QTableWidget(max_arg_num,2) self.tableArgs.setHorizontalHeaderLabels(['type','value']) for idx in range(0,max_arg_num): self.tableArgs.setItem(idx,0,QTableWidgetItem()) self.tableArgs.setItem(idx,1,QTableWidgetItem()) self.tableArgs.horizontalHeader().setStretchLastSection(True) vbox.addWidget(self.tableArgs) self.titleArg = QLabel('Return Value List') vbox.addWidget(self.titleArg) max_ret_num = 4 self.tableRet = QTableWidget(max_ret_num,2) self.tableRet.setHorizontalHeaderLabels(['type','value']) for idx in range(0,max_ret_num): self.tableRet.setItem(idx,0,QTableWidgetItem()) self.tableRet.setItem(idx,1,QTableWidgetItem()) self.tableRet.horizontalHeader().setStretchLastSection(True) vwidth = self.tableRet.verticalHeader().length() hwidth = self.tableRet.horizontalHeader().height() fwidth = self.tableRet.frameWidth() * 2 self.tableRet.setFixedHeight(vwidth + hwidth + fwidth) vbox.addWidget(self.tableRet) self.buttonSrcView = QPushButton('view code') self.buttonSrcView.setFixedWidth(200) self.buttonSrcView.clicked.connect(self.openSourceViewer) self.buttonHide = QPushButton('Hide') self.buttonHide.setFixedWidth(200) self.buttonHide.clicked.connect(self.notifyHide) self.buttonHideAllMsg = QPushButton('Hide All') self.buttonHideAllMsg.setFixedWidth(200) self.buttonHideAllMsg.clicked.connect(self.hideAllMsgNamedAsSelected) self.groupBoxMessageInfo.setLayout(vbox) self.checkHideCircular = QCheckBox('Hide Circular Messages') self.checkHideCircular.setCheckState(QtCore.Qt.Unchecked) self.checkHideCircular.stateChanged.connect(self.changeHideCircularMessage) self.addWidget(self.checkHideCircular) self.addWidget(self.groupBoxMessageInfo) self.groupBoxMessageInfo.setSizePolicy(self.sizePolicy) def reset(self): for idx in reversed(range(0,self.listThread.count())): self.listThread.takeItem(idx) def setMsgInfoMessage(self,msg): self.strMessage = msg def changeHideCircularMessage(self,state): if state == QtCore.Qt.Unchecked: self.diagramView.hideCircularChanged(False) elif state == QtCore.Qt.Checked: self.diagramView.hideCircularChanged(True) def setMsgInfoModule(self,module): self.strModule = module def updateSearchStatus(self,curr,number): self.searchCursor.setText("%d/%d" % (curr,number)) def connectSourceViewer(self,viewer): self.srcViewer = viewer def openSourceViewer(self): self.srcViewer.openViewer(self.strModule,self.strMessage) def setMessageInfoTime(self,begin,end,duration): self.tableTime.item(0,1).setText(begin) self.tableTime.item(1,1).setText(end) self.tableTime.item(2,1).setText(duration + ' msec') def setMessageInfoArg(self,listParam,listArg): # Clear the contents in the table max_arg_num = 10 for idx in range(0,max_arg_num): self.tableArgs.item(idx,0).setText('') self.tableArgs.item(idx,1).setText('') if listArg: for idx, text in enumerate(listArg): self.tableArgs.item(idx,1).setText(text) for idx, text in enumerate(listParam): self.tableArgs.item(idx,0).setText(text) else: for idx in range(0,self.tableArgs.rowCount()): self.tableArgs.item(idx,1).setText('') self.tableArgs.item(idx,0).setText('') def setMessageInfoRet(self,listRet): if listRet: for idx, text in enumerate(listRet): self.tableRet.item(idx,1).setText(text) else: for idx in range(0,self.tableRet.rowCount()): self.tableRet.item(idx,1).setText('') self.tableRet.item(idx,0).setText('') def notifyInteractiveStateChanged(self,state): if const.mode_interactive != self.mode: return if const.STATE_INTERACTIVE_CAPTURING == state: self.buttonCapture.setEnabled(True) self.buttonCapture.setText('Stop Capture') if const.STATE_INTERACTIVE_PROCESSING == state: self.buttonCapture.setEnabled(False) if const.STATE_INTERACTIVE_IDLE == state: self.buttonCapture.setEnabled(True) self.buttonCapture.setText('Capture') if const.STATE_INTERACTIVE_RESET == state: self.buttonCapture.setEnabled(True) self.buttonCapture.setText('Capture') elif const.STATE_INTERACTIVE_ACTIVE == state: self.buttonCapture.setEnabled(True) self.buttonCapture.setText('Capture') def setMessageInfo(self,info): self.msgInfo.setText(info) def setAvailable(self,threads): self.sig.emit(threads) def toggleThreadDisplay(self,item): print(self.listThread.currentRow()) #if item.isSelected(): # print(item.text() + " is selected") #else: # print(item.text() + " is not selected") self.diagramView.showThread(self.listThread.currentRow(),item.isSelected()) def hideAllMsgNamedAsSelected(self): self.diagramView.hideAllMessageSelected() def addThreadList(self,threads): if not self.groupBoxThreadInfo: self.groupBoxThreadInfo = QGroupBox() self.threadInfo = QLabel("Thread Info.") self.groupBoxThreadInfo.setStyleSheet("QGroupBox {border: 1px solid gray; border-radius: 9px; margin-top: 0.5em} QGroupBox::title {subcontrol-origin: margin; left: 10px; padding: 0 3px 0 3px;") if not self.threadvbox: self.threadvbox = QVBoxLayout() if not self.listThread: self.listThread = QListWidget() self.listThread.setFixedWidth(200) self.listThread.setSelectionMode(QAbstractItemView.MultiSelection) QtCore.QObject.connect(self.listThread, QtCore.SIGNAL("itemClicked(QListWidgetItem *)"), self.toggleThreadDisplay) self.threadvbox.addWidget(self.threadInfo) self.threadvbox.addWidget(self.listThread) self.groupBoxThreadInfo.setLayout(self.threadvbox) self.addWidget(self.groupBoxThreadInfo) self.groupBoxThreadInfo.setSizePolicy(self.sizePolicy) for id in threads: item = QListWidgetItem(id) self.listThread.addItem(item) def connectController(self,controller): self.controller = controller self.connect(controller,QtCore.SIGNAL('setAvailable()'),self.setAvailable) def connectDiagramView(self,view): self.diagramView = view def disconnectMsgRcv(self,receiver): print("Implement this method !!! disconnectMsgRcv") def connectMsgRcv(self,receiver): self.msgRcv.append(receiver) def notifyHide(self): for rcv in self.msgRcv: rcv.activateHide(True) def showHiddenLifelines(self): response, selected_items = HiddenDialog.HiddenDialog.getSelectedItems(self.diagramView.getHiddenLifeLines()) if response: self.diagramView.showLifelines(selected_items) def showHiddenMessages(self): response, selected_items = HiddenMessageDialog.HiddenMessageDialog.getSelectedItems(self.diagramView.getHiddenMessages(),self.diagramView.getHiddenLifeLines()) if response: if selected_items[3] in self.diagramView.getHiddenLifeLines(): confirmation = ShowLifeLineDialog.ShowLifeLineDialog.confirmToShowLifeLine(selected_items[3]) if confirmation: self.diagramView.showLifelines([selected_items[3]]) self.diagramView.showMessages(selected_items) else: self.diagramView.showMessages(selected_items) def notifyCapture(self): for rcv in self.msgRcv: rcv.activateCapture(True) def moveToPrev(self): for rcv in self.msgRcv: rcv.moveToPrev() def moveToNext(self): for rcv in self.msgRcv: rcv.moveToNext() def searchMsg(self): str = self.editTextSearch.toPlainText() for rcv in self.msgRcv: rcv.searchMessage(str)
def __init__(self): super().__init__() self.tl_layout = QGridLayout(self) rbtn_values = QGroupBox("Calibration Values", self) vbox = QVBoxLayout(rbtn_values) self.mode_btns = [ QRadioButton(s, rbtn_values) for s in [ "Idle", "Shifter neutral zone", "Shifter 135 zone", "Shifter 246R zone", "Shifter 12 zone", "Shifter 56 zone", "Gas pedal (if not auto-calibrated)", "Brake pedal (if not auto-calibrated)", "Clutch pedal (if not auto-calibrated)" ] ] self.mode_btns[0].setChecked(True) self.mode_cmds = [b"i", b"n", b"u", b"b", b"l", b"r", b"G", b"B", b"C"] self.help_cmds = [ "First decide about the filtering needed (in middle panel). If there is a lot of noise in the signal, " "maybe because of old pots, you might want to use a multi-sample median filter. Note that this filter " "introduces some delay, so you want to keep the numbers reasonable low. Afterwards, iterate through " "the calibration values in the left panel.\n\n" "When you're done, you can save the calibration in the right panel to the EEPROM.", "Put the shifter in neutral position. Afterwards, keep the left red button pressed and move the " "shifter while still in neutral. When reaching the calibrated area, the gear will be set to neutral.", "Put the shifter in 3rd gear. Afterwards keep the left red button pressed and move the shifter " "while still in 3rd gear. When done, release the red button. Optionally repeat for gears 1st and 5th.", "Put the shifter in 4th gear. Afterwards keep the left red button pressed and move the shifter " "while still in 4th gear. When done, release the red button. Optionally repeat for gears 2nd and 6th.", "Put the shifter in 1st gear. Afterwards keep the left red button pressed and move the shifter " "while still in 1st gear. When done, release the red button. Optionally repeat for 2nd gear.", "Put the shifter in 5th gear. Afterwards keep the left red button pressed and move the shifter " "while still in 5th gear. When done, release the red button. Optionally repeat for 6th gear.", "Move the gas pedal multiple times between lowest and highest position.", "Move the brake pedal multiple times between lowest and highest position.", "Move the clutch pedal multiple times between lowest and highest position." ] for b in self.mode_btns: vbox.addWidget(b) b.toggled.connect(self.modeChanged) self.tl_layout.addWidget(rbtn_values, 0, 0, 1, 1) cbtn_options = QGroupBox("Options", self) grid = QGridLayout(cbtn_options) self.option_btns = [ QCheckBox(s, cbtn_options) for s in [ "Enable pedal auto-calibration", "Invert gas/throttle pedal", "Invert brake pedal", "Invert clutch pedal", "Use right red button for reverse instead pushing the gear", "Enable pedals", "Enable shifter" ] ] + [ QComboBox(), QComboBox(), QComboBox(), QComboBox(), QComboBox(), QComboBox() ] self.option_cmds = [ (b"p", b"P"), #0 (b"y", b"Y"), #1 (b"x", b"X"), #2 (b"z", b"Z"), #3 (b"q", b"Q"), #4 (b"e", b"E"), #5 (b"s", b"S"), #6 (b".", b"+", b"-"), #7 (b"[^", b"[!", b"[\"", b"[]", b"[$", b"[%", b"[&", b"[/"), (b"(^", b"(!", b"(\"", b"(]", b"($", b"(%", b"(&", b"(/"), (b")^", b")!", b")\"", b")]", b")$", b")%", b")&", b")/"), (b"0", b"3", b"5", b"7", b"9", b"f"), (b"1", b"2", b"4", b"6", b"8", b"F"), ] self.option_btns[-6].addItem("Do not combine clutch and gas") self.option_btns[-6].addItem( "Combine Clutch and Gas (Clutch = Gas - Clutch)") self.option_btns[-6].addItem( "Combine Clutch and Gas (Clutch = Clutch - Gas)") for (idx, name) in [(-5, "Gas"), (-4, "Brake"), (-3, "Clutch")]: for dz in [0, 2, 4, 6, 8, 10, 12, 14]: self.option_btns[idx].addItem("%s: %d%% dead zone" % (name, dz)) for (idx, name) in [(-2, "pedals"), (-1, "shifter")]: for size in [0, 3, 5, 9, 15, 49]: self.option_btns[idx].addItem( "off" if size == 0 else (str(size) + "-median"), size) for i, b in enumerate(self.option_btns): n_checkboxes = len(self.option_cmds) - 6 if i < n_checkboxes: grid.addWidget(b, i, 0, 1, 2) else: names = { n_checkboxes: "Combine", n_checkboxes + 1: "Gas Dead Zone", n_checkboxes + 2: "Brake Dead Zone", n_checkboxes + 3: "Clutch Dead Zone", n_checkboxes + 4: "Pedal filter", n_checkboxes + 5: "Shifter filter" } grid.addWidget(QLabel(names[i], parent=self), i, 0) grid.addWidget(b, i, 1) if isinstance(b, QCheckBox): b.toggled.connect(self.optionChanged) else: b.currentIndexChanged.connect(self.optionChanged) self.tl_layout.addWidget(cbtn_options, 0, 1, 1, 1) cbtn_persistent = QGroupBox("Persistency") self.persistent_btns = [ QPushButton(s, parent=self) for s in ["Save to EEPROM", "Load from EEPROM", "Defaults"] ] self.persistent_cmds = [b"w", b"U", b"c"] vbox = QVBoxLayout(cbtn_persistent) for i, b in enumerate(self.persistent_btns): vbox.addWidget(b) b.clicked.connect(self.persistent_cmd) self.tl_layout.addWidget(cbtn_persistent, 0, 2, 1, 1) self.helpArea = QLabel(self.help_cmds[0], self) self.helpArea.setWordWrap(True) f = self.helpArea.font() f.setBold(True) f.setPointSizeF(f.pointSizeF() * 1.5) self.helpArea.setFont(f) self.tl_layout.addWidget(self.helpArea, 0, 3, 1, 1) shifter_label = QLabel("Shifter") self.tl_layout.addWidget(shifter_label, 1, 2, 1, 2, alignment=Qt.AlignHCenter) shifter_plot = pg.PlotWidget(parent=self) shifter_plot.setMouseEnabled(x=False, y=False) self.tl_layout.addWidget(shifter_plot, 2, 2, 1, 2) shifter_plot.setRange(QRectF(0, 0, 1023, 1023), padding=0) pi = shifter_plot.getPlotItem() self.shifter_neutral_plot = pg.LinearRegionItem( values=(400, 600), orientation='horizontal', movable=False, brush=QBrush(QColor(200, 50, 50, 50)), pen=QPen(QColor(200, 50, 50))) shifter_plot.addItem(self.shifter_neutral_plot) self.shifter_135_plot = pg.LinearRegionItem( values=(800, 1024), orientation='horizontal', movable=False, brush=QBrush(QColor(50, 200, 50, 50)), pen=QPen(QColor(50, 200, 50))) shifter_plot.addItem(self.shifter_135_plot) self.shifter_246_plot = pg.LinearRegionItem( values=(0, 200), orientation='horizontal', movable=False, brush=QBrush(QColor(50, 50, 200, 50)), pen=QPen(QColor(50, 50, 200))) shifter_plot.addItem(self.shifter_246_plot) self.shifter_12_plot = pg.LinearRegionItem( values=(0, 200), orientation='vertical', movable=False, brush=QBrush(QColor(50, 200, 200, 50)), pen=QPen(QColor(50, 200, 200))) shifter_plot.addItem(self.shifter_12_plot) self.shifter_56_plot = pg.LinearRegionItem( values=(800, 1024), orientation='vertical', movable=False, brush=QBrush(QColor(200, 200, 50, 50)), pen=QPen(QColor(200, 200, 50))) shifter_plot.addItem(self.shifter_56_plot) self.shifter_pos_plot = pi.plot(x=[512], y=[512], symbol='+', pen=None) pedals_label = QLabel("Pedals") self.tl_layout.addWidget(pedals_label, 1, 0, 1, 2, alignment=Qt.AlignHCenter) pedals_plot = pg.PlotWidget(parent=self) pedals_plot.setMouseEnabled(x=False, y=False) pedals_plot.setRange(QRectF(-1, 0, 4, 1023), padding=0) pedals_plot.getAxis('bottom').setTicks([[(0.0, "Gas/Throttle"), (1.0, "Brake"), (2.0, "Clutch")], []]) self.tl_layout.addWidget(pedals_plot, 2, 0, 1, 2) self.pedals_pos_plot = pg.BarGraphItem(x=np.arange(3), height=[512, 512, 512], width=0.5) self.pedals_gas_calib_plot = pedals_plot.getPlotItem().plot( x=[0], y=[0], pen=QPen(QColor(255, 0, 0), width=0.1), brush=QBrush(Qt.NoBrush)) self.pedals_brake_calib_plot = pedals_plot.getPlotItem().plot( x=[0], y=[0], pen=QPen(QColor(0, 255, 0))) self.pedals_clutch_calib_plot = pedals_plot.getPlotItem().plot( x=[0], y=[0], pen=QPen(QColor(0, 0, 255))) self.pedals_pos_plot2 = pedals_plot.getPlotItem().plot(x=[], y=[], symbol='+', pen=None) pedals_plot.addItem(self.pedals_pos_plot) self.status_line = QLabel(self) self.tl_layout.addWidget(self.status_line, 3, 0, 1, 2) self.status_line2 = QLabel(self) self.tl_layout.addWidget(self.status_line2, 3, 2, 1, 2) self.currentVals = Values()