def _create_categories_boxes(self, size_policy): self._boxes_for_category = {} current_row = 0 for major_item_category in iterate_enum(ItemCategory): if not major_item_category.is_major_category and major_item_category != ItemCategory.ENERGY_TANK: continue category_button = QToolButton(self.major_items_box) category_button.setGeometry(QRect(20, 30, 24, 21)) category_button.setText("+") category_label = QLabel(self.major_items_box) category_label.setSizePolicy(size_policy) category_label.setText(major_item_category.long_name) category_box = QGroupBox(self.major_items_box) category_box.setSizePolicy(size_policy) category_box.setObjectName(f"category_box {major_item_category}") category_layout = QGridLayout(category_box) category_layout.setObjectName(f"category_layout {major_item_category}") self.major_items_layout.addWidget(category_button, 2 * current_row + 1, 0, 1, 1) self.major_items_layout.addWidget(category_label, 2 * current_row + 1, 1, 1, 1) self.major_items_layout.addWidget(category_box, 2 * current_row + 2, 0, 1, 2) self._boxes_for_category[major_item_category] = category_box, category_layout, {} category_button.clicked.connect(partial(_toggle_box_visibility, category_button, category_box)) category_box.setVisible(False) current_row += 1
def _add_output(self): output_groupbox = QGroupBox("Output") output_groupbox.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) output_layout = QVBoxLayout() output_layout.setSpacing(0) output_groupbox.setLayout(output_layout) output_file_layout = QHBoxLayout() output_file_layout.setSpacing(4) self.output_file_input = QLineEdit() self.output_file_input.textChanged.connect( self._on_output_filename_changed) self.output_file_input.setMinimumWidth(400) self.output_file_input.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) output_file_layout.addWidget(self.output_file_input) output_layout.addLayout(output_file_layout) self.open_output_file_button = QPushButton() output_file_layout.addWidget(self.open_output_file_button) self.open_output_file_button.setIcon(qta.icon('fa.folder-open')) self.open_output_file_button.setToolTip("Select output file location") self.open_output_file_button.clicked.connect(self._click_open_output) self.layout.addWidget(output_groupbox)
def build_results_group(self): """Build the results group to contain the results of analysis. Returns: results_grp (QGroupBox): The group box that contains the results layout. """ grp_results = QGroupBox("Results: Largest island zone.") grp_results.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) # Add a layout to hold all the results from the Analysis. self.layout_results = QVBoxLayout() self.layout_results.setContentsMargins(0, 0, 0, 0) grp_results.setLayout(self.layout_results) return grp_results
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 _add_inputs(self): inputs_groupbox = QGroupBox("Inputs") inputs_groupbox.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) inputs_layout = QVBoxLayout() inputs_layout.setSpacing(0) inputs_groupbox.setLayout(inputs_layout) for input_band_name in input_band_names: inputband = GridTransformerInputBand(input_band_name) inputs_layout.addWidget(inputband) inputband.band_selected.connect(self._band_selected) inputband.log_message.connect(self._log_message) self.layout.addWidget(inputs_groupbox)
class AppBaseClassUI(object): def setupUi(self, main_window): self.central_widget = QWidget(main_window) self.p0_layout = QGridLayout(self.central_widget) self.p0_layout.setSpacing(10), self.p0_layout.setContentsMargins( 15, 15, 15, 15) self.page_1 = QWidget(self.central_widget) self.page_2 = QGroupBox(self.central_widget) self.page_3 = QWidget(self.central_widget) self.p0_layout.addWidget(self.page_1, 0, 0, 1, 1) self.p0_layout.addWidget(self.page_2, 0, 1, 1, 1) self.p0_layout.addWidget(self.page_3, 1, 0, 1, 2) self.statusbar = QStatusBar(main_window) main_window.setCentralWidget(self.central_widget) main_window.setStatusBar(self.statusbar) # instantiate buttons etc self.p3_layout = QHBoxLayout(self.page_3) self.p3_layout.setContentsMargins(0, 0, 0, 0) self.p3_about = QPushButton('About') self.p3_about.setStyleSheet( 'padding-left:10px; padding-right:10px; padding-top:2px; padding-bottom:2px;' ) self.p3_layout.addWidget(self.p3_about) self.p3_layout.addSpacing(5) self.p3_example = QPushButton('Example') self.p3_example.setStyleSheet( 'padding-left:10px; padding-right:10px; padding-top:2px; padding-bottom:2px;' ) self.p3_layout.addWidget(self.p3_example) self.p3_layout.addStretch(1) self.p3_submit = QPushButton('Submit') self.p3_submit.setStyleSheet( 'padding-left:10px; padding-right:10px; padding-top:2px; padding-bottom:2px;' ) self.p3_layout.addWidget(self.p3_submit) self.page_1.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) self.page_2.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) self.page_3.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)
class AppUI(object): def setupUi(self, main_window): self.central_widget = QWidget(main_window) self.p0_layout = QGridLayout(self.central_widget) self.p0_layout.setSpacing(10), self.p0_layout.setContentsMargins( 15, 15, 15, 15) self.page_2 = QGroupBox(self.central_widget) self.label_version = QLabel(__version__) self.label_version.setWordWrap(True) self.p0_layout.addWidget(self.page_2, 0, 0, 1, 1) self.p0_layout.addWidget(self.label_version, 1, 0, 1, 1) main_window.setCentralWidget(self.central_widget) self.page_2.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)
def _create_categories_boxes(self, item_database: ItemDatabase, size_policy): self._boxes_for_category = {} categories = set() for major_item in item_database.major_items.values(): if not major_item.required: categories.add(major_item.item_category) all_categories = list(iterate_enum(ItemCategory)) current_row = 0 for major_item_category in sorted( categories, key=lambda it: all_categories.index(it)): category_button = QToolButton(self.major_items_box) category_button.setGeometry(QRect(20, 30, 24, 21)) category_button.setText("+") category_label = QLabel(self.major_items_box) category_label.setSizePolicy(size_policy) category_label.setText(major_item_category.long_name) category_box = QGroupBox(self.major_items_box) category_box.setSizePolicy(size_policy) category_box.setObjectName(f"category_box {major_item_category}") category_layout = QGridLayout(category_box) category_layout.setObjectName( f"category_layout {major_item_category}") self.major_items_layout.addWidget(category_button, 2 * current_row + 1, 0, 1, 1) self.major_items_layout.addWidget(category_label, 2 * current_row + 1, 1, 1, 1) self.major_items_layout.addWidget(category_box, 2 * current_row + 2, 0, 1, 2) self._boxes_for_category[ major_item_category] = category_box, category_layout, {} category_button.clicked.connect( partial(_toggle_box_visibility, category_button, category_box)) category_box.setVisible(False) current_row += 1
def _create_categories_boxes(self, item_database: ItemDatabase, size_policy): self._boxes_for_category = {} categories = set() for major_item in item_database.major_items.values(): if not major_item.required: categories.add(major_item.item_category) all_categories = list(iterate_enum(ItemCategory)) for major_item_category in sorted(categories, key=lambda it: all_categories.index(it)): category_box = QGroupBox(self.scroll_area_contents) category_box.setTitle(major_item_category.long_name) category_box.setSizePolicy(size_policy) category_box.setObjectName(f"category_box {major_item_category}") category_layout = QGridLayout(category_box) category_layout.setObjectName(f"category_layout {major_item_category}") self.item_pool_layout.addWidget(category_box) self._boxes_for_category[major_item_category] = category_box, category_layout, {}
def _gui(self): layout = QVBoxLayout() self.setLayout(layout) group = QGroupBox('Other', self) group.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) layout.addWidget(group) layout = QVBoxLayout() group.setLayout(layout) problems = List(self) problems.problem_selected.connect(self.problem_selected) problems.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) layout.addWidget(problems, 0) for i in PROBLEMS: problems.addItem(i) problems.clearSelection() layout.setSizeConstraint(QVBoxLayout.SetMinimumSize) layout.update()
def setupUi(self, MainWindow): def fun(spoiler): if spoiler.isOpened(): spoiler.close() else: spoiler.open() # app = QApplication(sys.argv) w = QMainWindow() cw = QWidget() mainLayout = QHBoxLayout() cw.setLayout(mainLayout) gridLayout = QGridLayout() spacerItem1 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) gridLayout.addItem(spacerItem1, 0, 0, 1, 1) pushButton1 = QPushButton() pushButton1.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Preferred) pushButton1.setText("") # gridLayout.addWidget(pushButton1, 0, 1, 1, 1) self.label1 = QLabel() self.label1.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) self.label1.setObjectName("") gridLayout.addWidget(self.label1, 0, 2, 1, 1) datePicker1 = DatePicker() gridLayout.addWidget(datePicker1, 0, 1, 1, 1) datePicker1.selectionChanged.connect(lambda: self.__setLableDate__( self.label1, datePicker1.selectedDate())) spacerItem2 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) gridLayout.addItem(spacerItem2, 0, 3, 1, 1) self.label2 = QLabel() self.label2.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) self.label2.setObjectName("") gridLayout.addWidget(self.label2, 0, 4, 1, 1) datePicker2 = DatePicker() gridLayout.addWidget(datePicker2, 0, 5, 1, 1) datePicker2.selectionChanged.connect(lambda: self.__setLableDate__( self.label2, datePicker2.selectedDate())) pushButton2 = QPushButton() pushButton2.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Preferred) pushButton2.setText("") #gridLayout.addWidget(pushButton2, 0, 5, 1, 1) spacerItem3 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) gridLayout.addItem(spacerItem3, 0, 6, 1, 1) groupBox = QGroupBox() groupBox.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum) verticalLayout = QVBoxLayout(groupBox) radioButton1 = QRadioButton(groupBox) radioButton1.setText("Subscribers") verticalLayout.addWidget(radioButton1) radioButton2 = QRadioButton(groupBox) radioButton1.setText("PatientsServices") verticalLayout.addWidget(radioButton2) export_btn = QPushButton() export_btn.setText("export") gridLayout.addWidget(export_btn) export_btn.clicked.connect(lambda: self.onExport_btn()) gridLayout.addWidget(groupBox, 1, 1, 1, 2, Qt.AlignTop) self.comboBox = QComboBox() self.h_values = [ "all", "مستشفي الصفوة الدولي", "مختبر مصراتة المركزي", "مستشفى الحكمه الحديث" ] self.comboBox.addItems(self.h_values) if self.comboBox.currentIndex() == 1: print("kln") self.comboBox.activated.connect(self.oncomboBoxChanged) gridLayout.addWidget(self.comboBox, 1, 4, 1, 2, Qt.AlignTop) btn = QPushButton("Click me") btn.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) spoiler = Spoiler(Spoiler.Orientation.VERTICAL) spoiler.setContentLayout(gridLayout) mainLayout.addWidget(btn) #self.searchGridLayout.addWidget(spoiler) # mainLayout.setAlignment(Qt.AlignRight) MainWindow.setObjectName(_fromUtf8("MainWindow")) MainWindow.resize(716, 392) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName(_fromUtf8("centralwidget")) self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget) self.verticalLayout.setObjectName(_fromUtf8("verticalLayout")) self.tabWidget = QtWidgets.QTabWidget(self.centralwidget) self.tabWidget.setTabsClosable(False) self.tabWidget.setObjectName(_fromUtf8("tabWidget")) self.InsertTab = QtWidgets.QWidget() self.InsertTab.setObjectName(_fromUtf8("InsertTab")) self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.InsertTab) self.verticalLayout_2.setObjectName(_fromUtf8("verticalLayout_2")) spacerItem = QtWidgets.QSpacerItem(20, 109, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) self.verticalLayout_2.addItem(spacerItem) self.insertGridLayout = QtWidgets.QGridLayout() self.insertGridLayout.setObjectName(_fromUtf8("insertGridLayout")) self.runBtn = QtWidgets.QPushButton(self.InsertTab) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.runBtn.sizePolicy().hasHeightForWidth()) self.runBtn.setSizePolicy(sizePolicy) self.runBtn.setMouseTracking(False) self.runBtn.setAutoFillBackground(False) self.runBtn.setStyleSheet(_fromUtf8("border: none")) self.runBtn.setText(_fromUtf8("")) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(_fromUtf8("icons/run.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.runBtn.setIcon(icon) self.runBtn.setIconSize(QtCore.QSize(64, 64)) self.runBtn.setObjectName(_fromUtf8("runBtn")) self.insertGridLayout.addWidget(self.runBtn, 0, 3, 2, 1) spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.combo = QComboBox() self.values = [ "مستشفي الصفوة الدولي", "مختبر مصراتة المركزي", "مستشفى الحكمه الحديث", "مستشفى المدينه السكنيه" ] self.combo.addItems(self.values) if self.combo.currentIndex() == 1: print("kln") self.combo.activated.connect(self.oncomboChanged) self.insertGridLayout.addWidget(self.combo, 1, 4, 1, 2, Qt.AlignTop) self.insertGridLayout.addItem(spacerItem1, 0, 5, 1, 1) self.excelLabel = QtWidgets.QLabel(self.InsertTab) self.excelLabel.setText(_fromUtf8("")) self.excelLabel.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter) self.excelLabel.setObjectName(_fromUtf8("excelLabel")) self.insertGridLayout.addWidget(self.excelLabel, 1, 0, 1, 3) self.sqlBtn = QtWidgets.QPushButton(self.InsertTab) self.sqlBtn.setMinimumSize(QtCore.QSize(200, 0)) self.sqlBtn.setObjectName(_fromUtf8("sqlBtn")) self.insertGridLayout.addWidget(self.sqlBtn, 0, 4, 1, 1) self.excelBtn = QtWidgets.QPushButton(self.InsertTab) self.excelBtn.setMinimumSize(QtCore.QSize(200, 0)) self.excelBtn.setObjectName(_fromUtf8("excelBtn")) self.insertGridLayout.addWidget(self.excelBtn, 0, 2, 1, 1) spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.insertGridLayout.addItem(spacerItem2, 0, 1, 1, 1) self.sqlLabel = QtWidgets.QLabel(self.InsertTab) self.sqlLabel.setText(_fromUtf8("")) self.sqlLabel.setObjectName(_fromUtf8("sqlLabel")) self.insertGridLayout.addWidget(self.sqlLabel, 1, 4, 1, 2) self.verticalLayout_2.addLayout(self.insertGridLayout) spacerItem3 = QtWidgets.QSpacerItem(20, 108, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) self.verticalLayout_2.addItem(spacerItem3) self.tabWidget.addTab(self.InsertTab, _fromUtf8("")) # self.filterBtn = QtWidgets.QPushButton(self.searchTab) # self.filterBtn.setStyleSheet(_fromUtf8("border: none")) # icon2 = QtGui.QIcon() # icon2.addPixmap(QtGui.QPixmap(_fromUtf8("icons/filter_icon.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) # self.filterBtn.setIcon(icon2) # self.filterBtn.setObjectName(_fromUtf8("filterBtn")) # self.searchGridLayout.addWidget(self.filterBtn, 0, 3, 1, 1) # self.searchGridLayout.addWidget(spoiler) self.export_btn = QPushButton() self.export_btn.setText("export") #self.gridLayout.addWidget(export_btn) self.export_btn.clicked.connect(lambda: self.onExport_btnSubscribers()) #self.exprt_btn = QtWidgets.QPushButton() #self.exprt_btn.setText("export") #self.exprt_btn.setObjectName(_fromUtf8("exprt_btn")) #self.searchGridLayout1.addWidget(self.exprt_btn, 0, 0, 2, 1) self.verticalLayout.addWidget(self.tabWidget) MainWindow.setCentralWidget(self.centralwidget) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName(_fromUtf8("statusbar")) MainWindow.setStatusBar(self.statusbar) self.retranslateUi(MainWindow) self.tabWidget.setCurrentIndex(1) QtCore.QMetaObject.connectSlotsByName(MainWindow) self.excelBtn.clicked.connect(MainWindow, QtCore.SLOT("onExcelBtnClick()")) self.sqlBtn.clicked.connect(MainWindow, QtCore.SLOT("onSqlBtnClick()")) self.runBtn.clicked.connect(MainWindow, QtCore.SLOT("onRunBtnClick()")) self.excelFileName = None self.sqlFileName = "/home/eamon/Desktop/test.sqlite" self.sqlLabel.setText(self.sqlFileName) conn = sqlite3.connect("C:\\Users\\PC WORLD\\Downloads\\test.sqlite") result = conn.execute("SELECT * FROM Subscribers") conn.close()
def __init__(self, parent: Optional[QWidget] = None, url: str = '') -> None: super().__init__(parent, ) if parent: self.setWindowTitle('Download Mod') else: self.setWindowTitle(getTitleString('Download Mod')) self.setAttribute(Qt.WA_DeleteOnClose) mainLayout = QVBoxLayout(self) self.signals = DownloadWindowEvents(self) # URL input gbUrl = QGroupBox('Mod URL') gbUrlLayout = QVBoxLayout() gbUrl.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self.url = QLineEdit() self.url.setPlaceholderText( 'https://www.nexusmods.com/witcher3/mods/...') self.url.setText(url) self.url.textChanged.connect(lambda: self.validateUrl(self.url.text())) gbUrlLayout.addWidget(self.url) self.urlInfo = QLabel('🌐') self.urlInfo.setContentsMargins(4, 4, 4, 4) self.urlInfo.setMinimumHeight(36) self.urlInfo.setWordWrap(True) gbUrlLayout.addWidget(self.urlInfo) gbUrl.setLayout(gbUrlLayout) mainLayout.addWidget(gbUrl) # File selection gbFiles = QGroupBox('Mod Files') gbFilesLayout = QVBoxLayout() gbFiles.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) self.files = QTableWidget(0, 4) self.files.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel) self.files.setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel) self.files.setContextMenuPolicy(Qt.CustomContextMenu) self.files.setSelectionMode(QAbstractItemView.ExtendedSelection) self.files.setSelectionBehavior(QAbstractItemView.SelectRows) self.files.setWordWrap(False) self.files.setSortingEnabled(True) self.files.setFocusPolicy(Qt.StrongFocus) self.files.verticalHeader().hide() self.files.setSortingEnabled(True) self.files.sortByColumn(2, Qt.DescendingOrder) self.files.verticalHeader().setVisible(False) self.files.verticalHeader().setDefaultSectionSize(25) self.files.horizontalHeader().setHighlightSections(False) self.files.horizontalHeader().setStretchLastSection(True) self.files.setHorizontalHeaderLabels( ['File Name', 'Version', 'Upload Date', 'Description']) self.files.setEditTriggers(QAbstractItemView.NoEditTriggers) self.files.verticalScrollBar().valueChanged.connect( lambda: self.files.clearFocus()) self.files.itemSelectionChanged.connect(lambda: self.validateFiles()) self.files.setDisabled(True) self.files.setStyleSheet(''' QTableView { gridline-color: rgba(255,255,255,1); } QTableView::item { padding: 5px; margin: 1px 0; } QTableView::item:!selected:hover { background-color: rgb(217, 235, 249); padding: 0; } ''') gbFilesLayout.addWidget(self.files) _mouseMoveEvent = self.files.mouseMoveEvent self.files.hoverIndexRow = -1 def mouseMoveEvent(event: QMouseEvent) -> None: self.files.hoverIndexRow = self.files.indexAt(event.pos()).row() _mouseMoveEvent(event) self.files.mouseMoveEvent = mouseMoveEvent # type: ignore self.files.setItemDelegate(ModListItemDelegate(self.files)) self.files.setMouseTracking(True) gbFiles.setLayout(gbFilesLayout) mainLayout.addWidget(gbFiles) # Actions actionsLayout = QHBoxLayout() actionsLayout.setAlignment(Qt.AlignRight) self.download = QPushButton('Download', self) self.download.clicked.connect(lambda: self.downloadEvent()) self.download.setAutoDefault(True) self.download.setDefault(True) self.download.setDisabled(True) actionsLayout.addWidget(self.download) cancel = QPushButton('Cancel', self) cancel.clicked.connect(self.cancelEvent) actionsLayout.addWidget(cancel) mainLayout.addLayout(actionsLayout) # Setup self.setMinimumSize(QSize(420, 420)) self.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) self.resize(QSize(720, 420)) self.finished.connect( lambda: self.validateUrl.cancel()) # type: ignore self.finished.connect( lambda: self.downloadEvent.cancel()) # type: ignore self.modId = 0 self.validateUrl(self.url.text())
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_database.resource_database_for(self.game) broad_to_category = { ItemCategory.BEAM_RELATED: ItemCategory.BEAM, ItemCategory.MORPH_BALL_RELATED: ItemCategory.MORPH_BALL, ItemCategory.MISSILE_RELATED: ItemCategory.MISSILE, } for ammo in item_database.ammo.values(): category_box, category_layout, _ = self._boxes_for_category[ broad_to_category[ammo.broad_category]] pickup_box = QGroupBox(category_box) pickup_box.setSizePolicy(size_policy) pickup_box.setTitle(ammo.name + "s") 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] = AmmoPickupWidgets( pickup_spinbox, expected_count, pickup_box, require_major_item_check) category_layout.addWidget(pickup_box)
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)
class EMMAResultChart(QDialog): N_DISPLAY_SAMPLES = 200 def __init__(self, parent=None, toolbar=False): flags = Qt.Window | Qt.WindowTitleHint | Qt.CustomizeWindowHint | Qt.WindowCloseButtonHint super().__init__(parent=parent, f=flags) self.setWindowTitle(self.tr("EMMA Result Chart")) self.figure = plt.figure(figsize=(6, 8)) self.canvas = FigureCanvas(self.figure) self.toolbar = NavigationToolbar(self.canvas, self) self.main_layout = QGridLayout(self) self.main_layout.addWidget(self.toolbar, 0, 0) self.main_layout.addWidget(self.canvas, 1, 0) if not toolbar: self.toolbar.hide() self.supported_scales = [("log-linear", self.tr("Log-linear")), ("log", self.tr("Log")), ("phi", self.tr("φ")), ("linear", self.tr("Linear"))] self.control_group = QGroupBox(self.tr("Control")) self.control_group.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed) self.control_layout = QGridLayout(self.control_group) self.main_layout.addWidget(self.control_group, 0, 1, 2, 1) self.scale_label = QLabel(self.tr("Scale")) self.scale_combo_box = QComboBox() self.scale_combo_box.addItems( [name for key, name in self.supported_scales]) self.scale_combo_box.currentIndexChanged.connect(self.update_chart) self.control_layout.addWidget(self.scale_label, 0, 0) self.control_layout.addWidget(self.scale_combo_box, 0, 1) self.supported_distances = ("1-norm", "2-norm", "3-norm", "4-norm", "MSE", "log10MSE", "cosine", "angular") self.distance_label = QLabel(self.tr("Distance")) self.distance_combo_box = QComboBox() self.distance_combo_box.addItems(self.supported_distances) self.distance_combo_box.setCurrentText("log10MSE") self.distance_combo_box.currentIndexChanged.connect(self.update_chart) self.control_layout.addWidget(self.distance_label, 1, 0) self.control_layout.addWidget(self.distance_combo_box, 1, 1) self.animated_checkbox = QCheckBox(self.tr("Animated")) self.animated_checkbox.setChecked(False) self.animated_checkbox.stateChanged.connect(self.on_animated_changed) self.control_layout.addWidget(self.animated_checkbox, 2, 0) self.interval_label = QLabel(self.tr("Interval [ms]")) self.interval_input = QSpinBox() self.interval_input.setRange(0, 10000) self.interval_input.setValue(30) self.interval_input.valueChanged.connect(self.update_chart) self.control_layout.addWidget(self.interval_label, 3, 0) self.control_layout.addWidget(self.interval_input, 3, 1) self.repeat_check_box = QCheckBox(self.tr("Repeat")) self.repeat_check_box.setChecked(False) self.repeat_check_box.stateChanged.connect(self.update_chart) self.save_button = QPushButton(self.tr("Save")) self.save_button.clicked.connect(self.save_animation) self.control_layout.addWidget(self.repeat_check_box, 4, 0) self.control_layout.addWidget(self.save_button, 4, 1) self.animation = None self.last_result = None self.normal_msg = QMessageBox(parent=self) self.file_dialog = QFileDialog(parent=self) self.on_animated_changed() @property def scale(self) -> str: index = self.scale_combo_box.currentIndex() key, name = self.supported_scales[index] return key @property def transfer(self) -> typing.Callable: if self.scale == "log-linear": return lambda classes_φ: convert_φ_to_μm(classes_φ) elif self.scale == "log": return lambda classes_φ: np.log(convert_φ_to_μm(classes_φ)) elif self.scale == "phi": return lambda classes_φ: classes_φ elif self.scale == "linear": return lambda classes_φ: convert_φ_to_μm(classes_φ) @property def xlabel(self) -> str: if self.scale == "log-linear": return self.tr("Grain-size [μm]") elif self.scale == "log": return self.tr("Ln(grain-size in μm)") elif self.scale == "phi": return self.tr("Grain-size [φ]") elif self.scale == "linear": return self.tr("Grain-size [μm]") @property def ylabel(self) -> str: return self.tr("Frequency") @property def xlog(self) -> bool: if self.scale == "log-linear": return True else: return False @property def distance(self) -> str: return self.distance_combo_box.currentText() @property def interval(self) -> float: return self.interval_input.value() @property def repeat(self) -> bool: return self.repeat_check_box.isChecked() def update_chart(self): if self.last_result is not None: self.show_result(self.last_result) def on_animated_changed(self): if self.animated_checkbox.isChecked(): enabled = True else: enabled = False self.interval_label.setEnabled(enabled) self.interval_input.setEnabled(enabled) self.repeat_check_box.setEnabled(enabled) self.save_button.setEnabled(enabled) self.update_chart() def show_final_result(self, result: EMMAResult): self.last_result = result self.figure.clear() if self.animation is not None: self.animation._stop() self.animation = None classes = self.transfer(result.dataset.classes_φ) sample_indexes = np.linspace(1, result.n_samples, result.n_samples) iteration_indexes = np.linspace(1, result.n_iterations, result.n_iterations) first_result = next(result.history) def get_valid(values): values = np.array(values) return values[~np.isinf(values) & ~np.isnan(values)] if self.distance == "cosine": min_class_wise_distance = np.max( get_valid(result.get_class_wise_distance_series( self.distance))) max_class_wise_distance = np.min( get_valid( first_result.get_class_wise_distance_series( self.distance))) min_sample_wise_distance = np.max( get_valid(result.get_sample_wise_distance_series( self.distance))) max_sample_wise_distance = np.min( get_valid( first_result.get_sample_wise_distance_series( self.distance))) else: min_class_wise_distance = np.min( get_valid(result.get_class_wise_distance_series( self.distance))) max_class_wise_distance = np.max( get_valid( first_result.get_class_wise_distance_series( self.distance))) min_sample_wise_distance = np.min( get_valid(result.get_sample_wise_distance_series( self.distance))) max_sample_wise_distance = np.max( get_valid( first_result.get_sample_wise_distance_series( self.distance))) d_class_wise_distance = max_class_wise_distance - min_class_wise_distance min_class_wise_distance -= d_class_wise_distance / 10 max_class_wise_distance += d_class_wise_distance / 10 d_sample_wise_distance = max_sample_wise_distance - min_sample_wise_distance min_sample_wise_distance -= d_sample_wise_distance / 10 max_sample_wise_distance += d_sample_wise_distance / 10 distance_history_axes = self.figure.add_subplot(3, 1, 1) distance_history_axes.plot(iteration_indexes, result.get_distance_series(self.distance)) distance_history_axes.set_xlim(iteration_indexes[0], iteration_indexes[-1]) distance_history_axes.set_xlabel(self.tr("Iteration index")) distance_history_axes.set_ylabel(self.tr("Distance")) distance_history_axes.set_title(self.tr("Distance history")) class_wise_distance_axes = self.figure.add_subplot(3, 2, 3) if self.xlog: class_wise_distance_axes.set_xscale("log") class_wise_distance_axes.plot( classes, result.get_class_wise_distance_series(self.distance)) class_wise_distance_axes.set_xlim(classes[0], classes[-1]) class_wise_distance_axes.set_ylim(min_class_wise_distance, max_class_wise_distance) class_wise_distance_axes.set_xlabel(self.xlabel) class_wise_distance_axes.set_ylabel(self.tr("Distance")) class_wise_distance_axes.set_title(self.tr("Class-wise distances")) sample_wise_distance_axes = self.figure.add_subplot(3, 2, 4) sample_wise_distance_axes.plot( sample_indexes, result.get_sample_wise_distance_series(self.distance)) sample_wise_distance_axes.set_xlim(sample_indexes[0], sample_indexes[-1]) sample_wise_distance_axes.set_ylim(min_sample_wise_distance, max_sample_wise_distance) sample_wise_distance_axes.set_xlabel(self.tr("Sample index")) sample_wise_distance_axes.set_ylabel(self.tr("Distance")) sample_wise_distance_axes.set_title(self.tr("Sample-wise distances")) # get the mode size of each end-members modes = [(i, result.dataset.classes_μm[np.unravel_index( np.argmax(result.end_members[i]), result.end_members[i].shape)]) for i in range(result.n_members)] # sort them by mode size modes.sort(key=lambda x: x[1]) end_member_axes = self.figure.add_subplot(3, 2, 5) if self.xlog: end_member_axes.set_xscale("log") for i_em, (index, _) in enumerate(modes): end_member_axes.plot(classes, result.end_members[index], c=plt.get_cmap()(i_em), label=self.tr("EM{0}").format(i_em + 1)) end_member_axes.set_xlim(classes[0], classes[-1]) end_member_axes.set_ylim(0.0, round(np.max(result.end_members) * 1.2, 2)) end_member_axes.set_xlabel(self.xlabel) end_member_axes.set_ylabel(self.ylabel) end_member_axes.set_title(self.tr("End-members")) if result.n_members < 6: end_member_axes.legend(loc="upper left") if result.n_samples > self.N_DISPLAY_SAMPLES: interval = result.n_samples // self.N_DISPLAY_SAMPLES else: interval = 1 proportion_axes = self.figure.add_subplot(3, 2, 6) bottom = np.zeros(result.n_samples) for i_em, (index, _) in enumerate(modes): proportion_axes.bar(sample_indexes[::interval], result.fractions[:, index][::interval], bottom=bottom[::interval], width=interval, color=plt.get_cmap()(i_em)) bottom += result.fractions[:, index] proportion_axes.set_xlim(sample_indexes[0], sample_indexes[-1]) proportion_axes.set_ylim(0.0, 1.0) proportion_axes.set_xlabel(self.tr("Sample index")) proportion_axes.set_ylabel(self.tr("Proportion")) proportion_axes.set_title(self.tr("EM abundances")) self.figure.tight_layout() self.canvas.draw() def show_history_animation(self, result: EMMAResult): self.last_result = result self.figure.clear() if self.animation is not None: self.animation._stop() self.animation = None classes = self.transfer(result.dataset.classes_φ) sample_indexes = np.linspace(1, result.n_samples, result.n_samples) iteration_indexes = np.linspace(1, result.n_iterations, result.n_iterations) distance_series = result.get_distance_series(self.distance) min_distance, max_distance = np.min(distance_series), np.max( distance_series) first_result = next(result.history) def get_valid(values): values = np.array(values) return values[~np.isinf(values) & ~np.isnan(values)] if self.distance == "cosine": min_class_wise_distance = np.max( get_valid(result.get_class_wise_distance_series( self.distance))) max_class_wise_distance = np.min( get_valid( first_result.get_class_wise_distance_series( self.distance))) min_sample_wise_distance = np.max( get_valid(result.get_sample_wise_distance_series( self.distance))) max_sample_wise_distance = np.min( get_valid( first_result.get_sample_wise_distance_series( self.distance))) else: min_class_wise_distance = np.min( get_valid(result.get_class_wise_distance_series( self.distance))) max_class_wise_distance = np.max( get_valid( first_result.get_class_wise_distance_series( self.distance))) min_sample_wise_distance = np.min( get_valid(result.get_sample_wise_distance_series( self.distance))) max_sample_wise_distance = np.max( get_valid( first_result.get_sample_wise_distance_series( self.distance))) d_class_wise_distance = max_class_wise_distance - min_class_wise_distance min_class_wise_distance -= d_class_wise_distance / 10 max_class_wise_distance += d_class_wise_distance / 10 d_sample_wise_distance = max_sample_wise_distance - min_sample_wise_distance min_sample_wise_distance -= d_sample_wise_distance / 10 max_sample_wise_distance += d_sample_wise_distance / 10 self.distance_history_axes = self.figure.add_subplot(3, 1, 1) self.distance_history_axes.plot(iteration_indexes, distance_series) self.distance_history_axes.set_xlim(iteration_indexes[0], iteration_indexes[-1]) self.distance_history_axes.set_xlabel(self.tr("Iteration index")) self.distance_history_axes.set_ylabel(self.tr("Distance")) self.distance_history_axes.set_title(self.tr("Distance history")) self.class_wise_distance_axes = self.figure.add_subplot(3, 2, 3) if self.xlog: self.class_wise_distance_axes.set_xscale("log") self.class_wise_distance_axes.set_xlim(classes[0], classes[-1]) self.class_wise_distance_axes.set_ylim(min_class_wise_distance, max_class_wise_distance) self.class_wise_distance_axes.set_xlabel(self.xlabel) self.class_wise_distance_axes.set_ylabel(self.tr("Distance")) self.class_wise_distance_axes.set_title( self.tr("Class-wise distances")) self.sample_wise_distance_axes = self.figure.add_subplot(3, 2, 4) self.sample_wise_distance_axes.set_xlim(sample_indexes[0], sample_indexes[-1]) self.sample_wise_distance_axes.set_ylim(min_sample_wise_distance, max_sample_wise_distance) self.sample_wise_distance_axes.set_xlabel(self.tr("Sample index")) self.sample_wise_distance_axes.set_ylabel(self.tr("Distance")) self.sample_wise_distance_axes.set_title( self.tr("Sample-wise distances")) # get the mode size of each end-members self.modes = [(i, result.dataset.classes_μm[np.unravel_index( np.argmax(result.end_members[i]), result.end_members[i].shape)]) for i in range(result.n_members)] # sort them by mode size self.modes.sort(key=lambda x: x[1]) self.end_member_axes = self.figure.add_subplot(3, 2, 5) if self.xlog: self.end_member_axes.set_xscale("log") self.end_member_axes.set_xlim(classes[0], classes[-1]) self.end_member_axes.set_ylim( 0.0, round(np.max(result.end_members) * 1.2, 2)) self.end_member_axes.set_xlabel(self.xlabel) self.end_member_axes.set_ylabel(self.ylabel) self.end_member_axes.set_title(self.tr("End-members")) if result.n_samples > self.N_DISPLAY_SAMPLES: interval = result.n_samples // self.N_DISPLAY_SAMPLES else: interval = 1 self.proportion_axes = self.figure.add_subplot(3, 2, 6) self.proportion_axes.set_xlim(sample_indexes[0] - 0.5, sample_indexes[-1] - 0.5) self.proportion_axes.set_ylim(0.0, 1.0) self.proportion_axes.set_xlabel(self.tr("Sample index")) self.proportion_axes.set_ylabel(self.tr("Proportion")) self.proportion_axes.set_title(self.tr("EM abundances")) # self.figure.tight_layout() # self.canvas.draw() def init(): self.iteration_position_line = self.distance_history_axes.plot( [1, 1], [min_distance, max_distance], c="black")[0] self.class_wise_distance_curve = self.class_wise_distance_axes.plot( classes, result.get_class_wise_distance_series(self.distance), c=plt.get_cmap()(0))[0] self.sample_wise_distance_curve = self.sample_wise_distance_axes.plot( sample_indexes, result.get_sample_wise_distance_series(self.distance), c=plt.get_cmap()(0))[0] self.end_member_curves = [] for i_em, (index, _) in enumerate(self.modes): end_member_curve = self.end_member_axes.plot( classes, result.end_members[index], c=plt.get_cmap()(i_em), label=self.tr("EM{0}").format(i_em + 1))[0] self.end_member_curves.append(end_member_curve) bottom = np.zeros(result.n_samples) self.fraction_bars = [] self.patches = [] for i_em, (index, _) in enumerate(self.modes): bar = self.proportion_axes.bar( sample_indexes[::interval], result.fractions[:, index][::interval], bottom=bottom[::interval], width=interval, color=plt.get_cmap()(i_em)) self.fraction_bars.append(bar) self.patches.extend(bar.patches) bottom += result.fractions[:, index] return self.iteration_position_line, self.class_wise_distance_curve, self.sample_wise_distance_curve, *( self.end_member_curves + self.patches) def animate(args): iteration, current = args self.iteration_position_line.set_xdata([iteration, iteration]) self.class_wise_distance_curve.set_ydata( current.get_class_wise_distance_series(self.distance)) self.sample_wise_distance_curve.set_ydata( current.get_sample_wise_distance_series(self.distance)) for i_em, (index, _) in enumerate(self.modes): self.end_member_curves[i_em].set_ydata( current.end_members[index]) bottom = np.zeros(current.n_samples) for i_em, (index, _) in enumerate(self.modes): for rect, height, y in zip( self.fraction_bars[i_em].patches, current.fractions[:, index][::interval], bottom[::interval]): rect.set_height(height) rect.set_y(y) bottom += current.fractions[:, index] return self.iteration_position_line, self.class_wise_distance_curve, self.sample_wise_distance_curve, *( self.end_member_curves + self.patches) self.animation = FuncAnimation(self.figure, animate, init_func=init, frames=enumerate(result.history), interval=self.interval, blit=True, repeat=self.repeat, repeat_delay=3.0, save_count=result.n_iterations) def show_result(self, result: EMMAResult): if self.animated_checkbox.isChecked(): self.show_history_animation(result) else: self.show_final_result(result) def save_animation(self): if self.last_result is not None: filename, format_str = self.file_dialog.getSaveFileName( self, self.tr("Save the animation of this EMMA result"), None, self. tr("MPEG-4 Video File (*.mp4);;Graphics Interchange Format (*.gif)" )) if filename is None or filename == "": return progress = QProgressDialog(self) progress.setRange(0, 100) progress.setLabelText( self.tr("Saving Animation [{0} Frames]").format( self.last_result.n_iterations)) canceled = False def save_callback(i, n): if progress.wasCanceled(): nonlocal canceled canceled = True raise StopIteration() progress.setValue((i + 1) / n * 100) QCoreApplication.processEvents() self.show_history_animation(self.last_result) # plt.rcParams["savefig.dpi"] = 120.0 if "*.gif" in format_str: if not ImageMagickWriter.isAvailable(): self.normal_msg.setWindowTitle(self.tr("Error")) self.normal_msg.setText( self. tr("ImageMagick is not installed, please download and install it from its offical website (https://imagemagick.org/index.php)." )) self.normal_msg.exec_() else: self.animation.save(filename, writer="imagemagick", fps=30, progress_callback=save_callback) elif "*.mp4" in format_str: if not FFMpegWriter.isAvailable(): self.normal_msg.setWindowTitle(self.tr("Error")) self.normal_msg.setText( self. tr("FFMpeg is not installed, please download and install it from its offical website (https://ffmpeg.org/)." )) self.normal_msg.exec_() else: self.animation.save(filename, writer="ffmpeg", fps=30, progress_callback=save_callback) # plt.rcParams["savefig.dpi"] = 300.0 if not canceled: progress.setValue(100)
class Window(QMainWindow): def __init__(self): QMainWindow.__init__(self) # Title and dimensions self.setWindowTitle("Patterns detection") self.setGeometry(0, 0, 800, 500) # Main menu bar self.menu = self.menuBar() self.menu_file = self.menu.addMenu("File") exit = QAction("Exit", self, triggered=qApp.quit) self.menu_file.addAction(exit) self.menu_about = self.menu.addMenu("&About") about = QAction("About Qt", self, shortcut=QKeySequence(QKeySequence.HelpContents), triggered=qApp.aboutQt) self.menu_about.addAction(about) # Create a label for the display camera self.label = QLabel(self) self.label.setFixedSize(640, 480) # Thread in charge of updating the image self.th = Thread(self) self.th.finished.connect(self.close) self.th.updateFrame.connect(self.setImage) # Model group self.group_model = QGroupBox("Trained model") self.group_model.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding) model_layout = QHBoxLayout() self.combobox = QComboBox() for xml_file in os.listdir(cv2.data.haarcascades): if xml_file.endswith(".xml"): self.combobox.addItem(xml_file) model_layout.addWidget(QLabel("File:"), 10) model_layout.addWidget(self.combobox, 90) self.group_model.setLayout(model_layout) # Buttons layout buttons_layout = QHBoxLayout() self.button1 = QPushButton("Start") self.button2 = QPushButton("Stop/Close") self.button1.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding) self.button2.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding) buttons_layout.addWidget(self.button2) buttons_layout.addWidget(self.button1) right_layout = QHBoxLayout() right_layout.addWidget(self.group_model, 1) right_layout.addLayout(buttons_layout, 1) # Main layout layout = QVBoxLayout() layout.addWidget(self.label) layout.addLayout(right_layout) # Central widget widget = QWidget(self) widget.setLayout(layout) self.setCentralWidget(widget) # Connections self.button1.clicked.connect(self.start) self.button2.clicked.connect(self.kill_thread) self.button2.setEnabled(False) self.combobox.currentTextChanged.connect(self.set_model) @Slot() def set_model(self, text): self.th.set_file(text) @Slot() def kill_thread(self): print("Finishing...") self.button2.setEnabled(False) self.button1.setEnabled(True) self.th.cap.release() cv2.destroyAllWindows() self.status = False self.th.terminate() # Give time for the thread to finish time.sleep(1) @Slot() def start(self): print("Starting...") self.button2.setEnabled(True) self.button1.setEnabled(False) self.th.set_file(self.combobox.currentText()) self.th.start() @Slot(QImage) def setImage(self, image): self.label.setPixmap(QPixmap.fromImage(image))
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)
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 _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)
class PredefinedModelsWidget(QWidget): def __init__(self, predefined_models_window, parent: "QWidget" = None): super().__init__(parent) # Model picker size (left) self._predefined_models_window = predefined_models_window self._predefined_models_group = QGroupBox("Predefined Models:") self._predefined_models_layout = QHBoxLayout() self._predefined_models_layout.setContentsMargins(0, 0, 0, 0) self._predefined_models_group.setLayout(self._predefined_models_layout) self._predefined_models_layout.addWidget( self._predefined_models_window) # Description Side (right) self._model_name = QLabel("") self._include_top = QCheckBox("Include") self._include_top.setChecked(True) self._shape_textbox = QLineEdit("(224, 224, 3)") self._shape_textbox.setEnabled(False) self._classes_intbox = QSpinBox() self._classes_intbox.setMinimum(2) self._classes_intbox.setMaximum(999999) self._classes_intbox.setValue(1000) self._weights_combobox = QComboBox() self._weights_combobox.addItem("Imagenet", "imagenet") self._weights_combobox.addItem("None", None) # Add widgets to layout self._description_group = QGroupBox("Description:") self._description_layout = QFormLayout() self._description_group.setLayout(self._description_layout) self._description_layout.addRow("Name:", self._model_name) self._description_layout.addRow("Include Top:", self._include_top) self._description_layout.addRow("Input Shape:", self._shape_textbox) self._description_layout.addRow("Classes:", self._classes_intbox) self._description_layout.addRow("Weights:", self._weights_combobox) self._main_layout = QHBoxLayout() self._main_layout.addWidget(self._predefined_models_group) self._main_layout.addWidget(self._description_group) self.setLayout(self._main_layout) sp_left = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) sp_left.setHorizontalStretch(1) self._predefined_models_group.setSizePolicy(sp_left) sp_right = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) sp_right.setHorizontalStretch(2.5) self._description_group.setSizePolicy(sp_right) self._include_top.stateChanged.connect( lambda: self._update_enabled_widgets()) self._weights_combobox.currentIndexChanged[int].connect( lambda: self._update_enabled_widgets()) self._predefined_models_window.selected_model_changed.connect( self._update_description_labels) self._update_enabled_widgets() def get_model(self) -> Optional["Model"]: try: LOGGER.debug("Include Top: %s", self._include_top.isChecked()) LOGGER.debug("Classes: %s", self._classes_intbox.value()) LOGGER.debug("Weights: %s", self._weights_combobox.currentData()) if not self._include_top.isChecked(): input_shape = tuple( map( int, re.sub("[()]", "", self._shape_textbox.text()).split(","))) LOGGER.debug("Input tuple: %s", input_shape) return self._predefined_models_window.get_selected_model( )["loader"]( include_top=False, input_shape=input_shape, weights=self._weights_combobox.currentData(), ) return self._predefined_models_window.get_selected_model( )["loader"]( include_top=True, classes=self._classes_intbox.value(), weights=self._weights_combobox.currentData(), ) except TypeError as err: LOGGER.exception(err) return None def get_image_transformations(self) -> List[Callable]: try: transformations = self._predefined_models_window.get_selected_model( )["transformations"] return transformations except KeyError as err: LOGGER.exception(err) return None def _update_description_labels(self, model_desc: dict): self._model_name.setText(model_desc["name"]) def _update_enabled_widgets(self): self._shape_textbox.setEnabled(not self._include_top.isChecked()) if (self._include_top.isChecked() and self._weights_combobox.currentText() == "None"): self._classes_intbox.setEnabled(True) else: self._classes_intbox.setEnabled(False) def sizeHint(self) -> "QSize": return QSize(400, 170)
class Ui_FilewriterCtrl(object): def setupUi(self, FilewriterCtrl): FilewriterCtrl.resize(649, 450) broker_placeholder_text = "address:port/topic" self.central_widget = QWidget(FilewriterCtrl) self.vertical_layout_2 = QVBoxLayout(self.central_widget) self.vertical_layout = QVBoxLayout() self.horizontal_layout = QHBoxLayout() self.horizontal_layout.setContentsMargins(-1, -1, 0, -1) self.status_layout = QVBoxLayout() self.status_layout.setContentsMargins(-1, -1, -1, 0) self.status_topic_layout = QHBoxLayout() self.status_topic_layout.setContentsMargins(-1, -1, -1, 0) self.status_broker_label = QLabel(self.central_widget) self.status_topic_layout.addWidget(self.status_broker_label) self.status_broker_edit = QLineEdit(self.central_widget) self.status_broker_edit.setPlaceholderText(broker_placeholder_text) self.status_topic_layout.addWidget(self.status_broker_edit) self.status_layout.addLayout(self.status_topic_layout) self.line_2 = QFrame(self.central_widget) self.line_2.setFrameShape(QFrame.HLine) self.line_2.setFrameShadow(QFrame.Sunken) self.status_layout.addWidget(self.line_2) self.file_writer_table_group = QGroupBox(self.central_widget) size_policy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding) size_policy.setHorizontalStretch(0) size_policy.setVerticalStretch(1) size_policy.setHeightForWidth( self.file_writer_table_group.sizePolicy().hasHeightForWidth()) self.file_writer_table_group.setSizePolicy(size_policy) self.vertical_layout_4 = QVBoxLayout(self.file_writer_table_group) self.vertical_layout_3 = QVBoxLayout() self.file_writers_list = QTreeView(self.file_writer_table_group) self.file_writers_list.setEditTriggers( QAbstractItemView.NoEditTriggers) self.file_writers_list.setIndentation(0) self.vertical_layout_3.addWidget(self.file_writers_list) self.vertical_layout_4.addLayout(self.vertical_layout_3) self.status_layout.addWidget(self.file_writer_table_group) self.files_group = QGroupBox(self.central_widget) size_policy.setHorizontalStretch(0) size_policy.setVerticalStretch(4) size_policy.setHeightForWidth( self.files_group.sizePolicy().hasHeightForWidth()) self.files_group.setSizePolicy(size_policy) self.vertical_layout_6 = QVBoxLayout(self.files_group) self.files_list = QTreeView(self.files_group) self.files_list.setIndentation(0) self.vertical_layout_6.addWidget(self.files_list) self.vertical_layout_5 = QVBoxLayout() self.horizontal_layout_4 = QHBoxLayout() spacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontal_layout_4.addItem(spacer) self.stop_file_writing_button = QPushButton(self.files_group) self.stop_file_writing_button.setEnabled(False) self.horizontal_layout_4.addWidget(self.stop_file_writing_button) self.vertical_layout_5.addLayout(self.horizontal_layout_4) self.vertical_layout_6.addLayout(self.vertical_layout_5) self.status_layout.addWidget(self.files_group) self.horizontal_layout.addLayout(self.status_layout) self.line = QFrame(self.central_widget) self.line.setFrameShape(QFrame.VLine) self.line.setFrameShadow(QFrame.Sunken) self.horizontal_layout.addWidget(self.line) self.command_layout = QVBoxLayout() self.command_layout.setContentsMargins(-1, 0, -1, 0) self.command_broker_layout = QHBoxLayout() self.command_broker_label = QLabel(self.central_widget) self.command_broker_layout.addWidget(self.command_broker_label) self.command_broker_edit = QLineEdit(self.central_widget) self.command_broker_edit.setPlaceholderText(broker_placeholder_text) self.command_broker_layout.addWidget(self.command_broker_edit) self.command_layout.addLayout(self.command_broker_layout) self.command_widget = FilewriterCommandWidget(FilewriterCtrl) self.command_layout.addWidget(self.command_widget) self.horizontal_layout.addLayout(self.command_layout) self.vertical_layout.addLayout(self.horizontal_layout) self.vertical_layout_2.addLayout(self.vertical_layout) FilewriterCtrl.setCentralWidget(self.central_widget) self.status_broker_label.setText("Status broker") self.file_writer_table_group.setTitle("File-writers") self.files_group.setTitle("Files") self.stop_file_writing_button.setText("Stop file-writing") self.command_broker_label.setText("Command broker") self.command_broker_edit.setPlaceholderText("address:port/topic") QMetaObject.connectSlotsByName(FilewriterCtrl)
class DLPSettingsGUI(QWidget): def __init__(self, dlp_controller=None, dlp_slicer=None, parent=None): QWidget.__init__(self, parent) self.parent = parent self.dlp_controller = dlp_controller self.dlp_slicer = dlp_slicer self.dlp_color_calibrator = DLPColorCalibrator() self.dlp_color_calibrator.analysis_completed_signal.connect(self.update_charts) self.__printer_parameters_list = {} self.__slicer_parameters_list = {} self.data_fit_chart_view = None self.data_fit_chart = None self.main_layout = QHBoxLayout() self.__init_table_widget__() self.__init_color_calibration_widget() self.__default_parameters_widget.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.MinimumExpanding) self.main_layout.addWidget(self.__default_parameters_widget, stretch=1) self.main_layout.addWidget(self.__color_calibration_widget, stretch=2) self.setLayout(self.main_layout) self.main_layout.update() def __init_color_calibration_widget(self, parent=None): self.__color_calibration_widget = QGroupBox("Color Correction Options", parent) self.__color_calibration_widget.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) color_calibration_layout = QVBoxLayout(self.__color_calibration_widget) chart_widget = QWidget(self.__color_calibration_widget) chart_layout = QGridLayout(chart_widget) self.data_fit_chart = QtCharts.QChart() self.data_fit_chart_view = QtCharts.QChartView(self.data_fit_chart) self.axis_x = QtCharts.QValueAxis() self.axis_x.setTitleText("Pixel Intensity") self.axis_x.setRange(0, 1) self.data_fit_chart.addAxis(self.axis_x, Qt.AlignBottom) self.axis_y = QtCharts.QValueAxis() self.axis_y.setTitleText("Voxel Height (\u03BCm)") self.axis_y.setRange(0, 10) self.data_fit_chart.addAxis(self.axis_y, Qt.AlignLeft) chart_layout.addWidget(self.data_fit_chart_view, 0, 0, 1, 4) chart_widget.setLayout(chart_layout) buttons_widget = QWidget(self.__color_calibration_widget) buttons_layout = QHBoxLayout(buttons_widget) analyze_data_button = QPushButton("Analyze Data") analyze_data_button.clicked.connect(self.analyze_images) self.parameters_estimation_label = QLabel(f'Estimated parameters: \u03B1 = {self.dlp_color_calibrator.optimized_parameters[0]:.3f}, \u03B2 = {self.dlp_color_calibrator.optimized_parameters[1]:.3f}, \u03B3 = {self.dlp_color_calibrator.optimized_parameters[2]:.3f}', buttons_widget) buttons_layout.addWidget(analyze_data_button) buttons_layout.addWidget(self.parameters_estimation_label) buttons_widget.setLayout(buttons_layout) color_calibration_layout.addWidget(chart_widget) color_calibration_layout.addWidget(buttons_widget) self.__color_calibration_widget.setLayout(color_calibration_layout) @Slot() def analyze_images(self): file_names = QFileDialog.getOpenFileNames(caption='Select data', dir='../measured_data/grayscale_measured_data', filter="Image Files (*.asc)") self.dlp_color_calibrator.analyze_data_files(file_names[0]) @Slot() def update_charts(self): self.data_fit_chart = QtCharts.QChart() self.data_fit_chart.setAnimationOptions(QtCharts.QChart.AllAnimations) self.add_series(self.data_fit_chart, "Measured Data", self.dlp_color_calibrator.input_values, self.dlp_color_calibrator.average_data) self.add_series(self.data_fit_chart, "Fitted Curve", self.dlp_color_calibrator.input_values, self.dlp_color_calibrator.fitted_curve) self.add_series(self.data_fit_chart, "Predicted Result", self.dlp_color_calibrator.input_values, self.dlp_color_calibrator.corrected_output_values) series = self.data_fit_chart.series() self.data_fit_chart.addAxis(self.axis_x, Qt.AlignBottom) self.axis_y.setRange(0, self.dlp_color_calibrator.measured_thickness) self.data_fit_chart.addAxis(self.axis_y, Qt.AlignLeft) for s in series: s.attachAxis(self.axis_x) s.attachAxis(self.axis_y) self.data_fit_chart_view.setRenderHint(QPainter.Antialiasing) self.data_fit_chart_view.setChart(self.data_fit_chart) self.parameters_estimation_label.setText(f'Estimated parameters: \u03B1 = {self.dlp_color_calibrator.optimized_parameters[0]:.3f}, \u03B2 = {self.dlp_color_calibrator.optimized_parameters[1]:.3f}, \u03B3 = {self.dlp_color_calibrator.optimized_parameters[2]:.3f}') def add_series(self, chart, title, x, y): series = QtCharts.QLineSeries() series.setName(title) for idx, elem in enumerate(x): series.append(x[idx], y[idx]) chart.addSeries(series) def __init_table_widget__(self, parent=None): self.__default_parameters_widget = QGroupBox("Default Parameters", parent) self.printer_parameters_list = self.dlp_controller.get_default_parameters() self.table_view = QTableView() self.table_model = self.MyTableModel(parent=self.__default_parameters_widget, data_list=self.printer_parameters_list) self.table_view.setModel(self.table_model) self.table_view.horizontalHeader().setVisible(False) self.table_view.verticalHeader().setVisible(False) self.table_view.horizontalHeader().setStretchLastSection(False) # self.table_view.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) self.table_view.resizeColumnsToContents() self.table_view.update() # self.table_view.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) # self.table_view.setSizeAdjustPolicy(QAbstractScrollArea.AdjustToContents) apply_button = QPushButton("Apply Changes", self.__default_parameters_widget) apply_button.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) apply_button.clicked.connect(self.dlp_controller.save_default_parameters) default_parameters_layout = QVBoxLayout(self.__default_parameters_widget) default_parameters_layout.addWidget(self.table_view) default_parameters_layout.addWidget(apply_button) self.__default_parameters_widget.setLayout(default_parameters_layout) self.__default_parameters_widget.updateGeometry() # default_parameters_layout.update() # QGuiApplication.processEvents() @Slot() def __adjust_table_size__(self): self.table_view.resizeColumnToContents(0) self.table_view.resizeColumnToContents(1) rect = self.table_view.geometry() rect.setWidth(1 + self.table_view.verticalHeader().width() + self.table_view.columnWidth(0) + self.table_view.columnWidth(1) + self.table_view.verticalScrollBar().width()) self.table_view.setGeometry(rect) self.table_view.resize(rect.width(), rect.height()) class MyTableModel(QAbstractTableModel): def __init__(self, parent, data_list, *args): QAbstractTableModel.__init__(self, parent, *args) self.parent = parent self.data_list = data_list def rowCount(self, parent): return len(self.data_list) def columnCount(self, parent): return 2 def data(self, index, role): if not index.isValid(): return None elif role != Qt.DisplayRole: return None return list(self.data_list.items())[index.row()][index.column()] def setData(self, index, value, role): if role == Qt.EditRole: if not index.isValid(): return False elif index.column() == 0: return False else: key = list(self.data_list.items())[index.row()][0] old_value = list(self.data_list.items())[index.row()][1] try: if isinstance(old_value, float): self.data_list[key] = float(value) elif isinstance(old_value, bool): if value == "True" or value == "true": self.data_list[key] = True else: self.data_list[key] = False elif isinstance(old_value, str): if index.row() == 0: if not (value.upper() == "TOP-DOWN" or value.upper() == "BOTTOM-UP"): return False self.data_list[key] = str(value).upper() except ValueError: return False self.dataChanged.emit(index, index) return True else: return False def flags(self, index): if not index.isValid() or index.column() == 0: return Qt.ItemIsEnabled return Qt.ItemFlags(QAbstractTableModel.flags(self, index) | Qt.ItemIsEditable)