class ToggleButton: def __init__(self, frame_text: str, checkbox_text: str = 'Default'): self.box = QVBoxLayout() self.lbl = QLabel(frame_text) self.checkbox = QCheckBox(checkbox_text) self.checkbox.setCheckState(Qt.Unchecked) self.numeric = QSpinBox() self.numeric.setValue(-1) self.box.addWidget(self.lbl) self.box.addWidget(self.numeric) self.box.addWidget(self.checkbox) self.checkbox.stateChanged.connect(self.checkbox_toggle) self.numeric.valueChanged.connect(self.numeric_change) self.use_default = False self.value = -1 @Slot() def checkbox_toggle(self, checked): self.use_default = self.checkbox.checkState() == Qt.Checked self.numeric.setDisabled(self.use_default) @Slot() def numeric_change(self, checked): self.value = self.numeric.value()
class MainWindow(QMainWindow): def __init__(self): super().__init__() form = QFormLayout() self.track_id = QSpinBox() self.track_id.setRange(0, 2147483647) self.track_id.setDisabled(True) self.name = QLineEdit() self.album = QComboBox() self.media_type = QComboBox() self.genre = QComboBox() self.composer = QLineEdit() self.milliseconds = QSpinBox() self.milliseconds.setRange(0, 2147483647) # <1> 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.mapper = QDataWidgetMapper() # <2> self.mapper.setModel(self.model) self.mapper.addMapping(self.track_id, 0) # <3> 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() # <4> self.mapper.toFirst() # <5> self.setMinimumSize(QSize(400, 400)) widget = QWidget() widget.setLayout(form) self.setCentralWidget(widget)
class StatisticsOptions(QWidget): polymorphic_states = { 'Regression': {'dtext': 'Tipo de Regressão:', 'xtext': 'Selecione a coluna dos valores correspondentes à variável independente:', 'ytext': 'Selecione a coluna dos valores correspondentes à variável dependente:', 'dropdown': ['Linear', 'Exponencial', 'Logarítmica', 'Potencial', 'Polinomial'], 'ctext':''}, 'Statistics': {'dtext': 'Tipo de análise estatística:', 'xtext': 'Selecione a coluna dos valores para realizar a análise:', 'ytext': '', 'dropdown': ['Média aritmética', 'Mediana', 'Moda', 'Variância Pop.', 'Variância Am.', 'Desvio Padrão Pop.', 'Desvio Padrão Am.', 'Máximo', 'Mínimo', 'Amplitude', 'Quartil', 'Percentil'], 'ctext':''}, 'Histogram': {'dtext': '', 'xtext': 'Selecione a coluna com os valores:', 'ytext': '', 'dropdown': [], 'ctext':''}, 'Boxplot': {'dtext': 'Orientação do gráfico:', 'ctext': 'Selecione as colunas onde se encontram as séries para o Boxplot (i.e. B, B:C, A:C:F:G):', 'ytext': '', 'dropdown': ['Vertical', 'Horizontal'], 'xtext':''}, } ready2calculate = Signal(bool) def __init__(self, _mode='Regression'): super().__init__() self.mode = _mode self.subtitle = QLabel(str(_mode)) self.dropdown_text = QLabel(self.polymorphic_states[self.mode]['dtext']) self.dropdown_text.setWordWrap(True) self.dropdown = Dropdown(self.polymorphic_states[self.mode]['dropdown']) self.x_column_text = QLabel(self.polymorphic_states[self.mode]['xtext']) self.x_column_text.setWordWrap(True) self.x_column = QLineEdit() self.y_column_text = QLabel(self.polymorphic_states[self.mode]['ytext']) self.y_column_text.setWordWrap(True) self.y_column = QLineEdit() self.column_range_text = QLabel(self.polymorphic_states[self.mode]['ctext']) self.column_range_text.setWordWrap(True) self.column_range = QLineEdit() self.output_text = QLabel('Select Output:') self.output_text.setWordWrap(True) self.table_button = QRadioButton('Tabela (Planilha)') self.plot_button = QRadioButton('Gráfico (Plot)') self.output_destination_text = QLabel('Selecione a coluna onde deve-se armazenar os resultados:') self.output_destination_text.setWordWrap(True) self.output_destination = QLineEdit() self.run_button = QPushButton('Começar Análise') self.selected_output = '' self.degree_l = QLabel('Ordem:') self.degree = QSpinBox() self.degree.setRange(1, 6) self.quartile_l = QLabel('Quartil:') self.quartile = QSpinBox() self.quartile.setRange(1, 4) self.percentile_l = QLabel('Percentil:') self.percentile = QSpinBox() self.percentile.setRange(1, 100) self.default_degree_stylesheet = self.degree.styleSheet() self.default_quartile_stylesheet = self.quartile.styleSheet() self.default_percentile_stylesheet = self.percentile.styleSheet() self.degree.setDisabled(True) self.results_l = QLabel('Resultados da análise: ') self.results = QTextEdit() self.payload = [] self.buildLayout() self.connections() self.initialState() self.setStyleSheet('color:white; font-family: Bahnschrift SemiLight Condensed; font-size: 14px;') self.x_column.setStyleSheet('background-color: white; color: black') self.y_column.setStyleSheet('background-color: white; color: black') self.column_range.setStyleSheet('background-color: white; color: black') self.results.setStyleSheet('background-color: white; color: black') def buildLayout(self): layout = QFormLayout() if len(self.dropdown_text.text()) > 0: layout.addWidget(self.dropdown_text) layout.addWidget(self.dropdown) if len(self.x_column_text.text()) > 0: layout.addWidget(self.x_column_text) layout.addWidget(self.x_column) if len(self.y_column_text.text()) > 0: layout.addWidget(self.y_column_text) layout.addWidget(self.y_column) if len(self.column_range_text.text()) > 0: layout.addWidget(self.column_range_text) layout.addWidget(self.column_range) if self.mode == 'Statistics': layout.addWidget(self.quartile_l) layout.addWidget(self.quartile) layout.addWidget(self.percentile_l) layout.addWidget(self.percentile) if self.mode == 'Regression': layout.addWidget(self.degree_l) layout.addWidget(self.degree) layout.addWidget(self.run_button) if self.mode != 'Boxplot' and self.mode != "Histogram": layout.addWidget(self.results_l) layout.addWidget(self.results) self.setLayout(layout) def initialState(self): self.output_destination.setDisabled(True) def connections(self): self.plot_button.clicked.connect(self.plotSelected) self.table_button.clicked.connect(self.tableSelected) self.run_button.clicked.connect(self.collectPayload) self.dropdown.currentTextChanged.connect(self.enableDegreeBox) def columnRangeDecomposition(self, text): try: return text.split(sep=':') except Exception: print('A problem happened in decomposing the column ranges. Probable bad user input.') def plotSelected(self): self.output_destination.setDisabled(True) self.selected_output = 'Plot' def enableDegreeBox(self, text): if text == 'Polinomial': self.degree.setStyleSheet('background-color: white; color: black') self.degree.setEnabled(True) else: self.degree.setStyleSheet(self.default_degree_stylesheet) self.degree.setDisabled(True) if text == 'Quartil': self.quartile.setStyleSheet('background-color: white; color: black') self.quartile.setEnabled(True) else: self.quartile.setStyleSheet(self.default_degree_stylesheet) self.quartile.setDisabled(True) if text == 'Percentil': self.percentile.setStyleSheet('background-color: white; color: black') self.percentile.setEnabled(True) else: self.percentile.setStyleSheet(self.default_degree_stylesheet) self.percentile.setDisabled(True) def tableSelected(self): self.output_destination.setDisabled(False) self.selected_output = 'Table' def collectPayload(self): if len(self.column_range_text.text()) > 0: a = self.columnRangeDecomposition(self.column_range.text()) b = 'V' else: a = None b = self.y_column.text() payload = { 'calculate': self.dropdown.currentText(), 'x_column': self.x_column.text(), 'y_column': b, 'z_column': None, 'column_range': a, 'output_selection': self.selected_output, 'output_column': self.output_destination.text() } self.payload = payload self.ready2calculate.emit(True)
class ColorDialog(QDialog): def __init__(self, model, font_metric, parent=None): super().__init__(parent) self.setWindowTitle('Color Options') self.model = model self.font_metric = font_metric self.main_window = parent self.createDialogLayout() def createDialogLayout(self): self.createGeneralTab() self.cellTable = self.createDomainTable(self.main_window.cellsModel) self.matTable = self.createDomainTable(self.main_window.materialsModel) self.tabs = { 'cell': self.createDomainTab(self.cellTable), 'material': self.createDomainTab(self.matTable), 'temperature': self.createPropertyTab('temperature'), 'density': self.createPropertyTab('density') } self.tab_bar = QTabWidget() self.tab_bar.setMaximumHeight(800) self.tab_bar.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.tab_bar.addTab(self.generalTab, 'General') self.tab_bar.addTab(self.tabs['cell'], 'Cells') self.tab_bar.addTab(self.tabs['material'], 'Materials') self.tab_bar.addTab(self.tabs['temperature'], 'Temperature') self.tab_bar.addTab(self.tabs['density'], 'Density') self.createButtonBox() self.colorDialogLayout = QVBoxLayout() self.colorDialogLayout.addWidget(self.tab_bar) self.colorDialogLayout.addWidget(self.buttonBox) self.setLayout(self.colorDialogLayout) def createGeneralTab(self): main_window = self.main_window # Masking options self.maskingCheck = QCheckBox('') self.maskingCheck.stateChanged.connect(main_window.toggleMasking) button_width = self.font_metric.boundingRect("XXXXXXXXXX").width() self.maskColorButton = QPushButton() self.maskColorButton.setCursor(QtCore.Qt.PointingHandCursor) self.maskColorButton.setFixedWidth(button_width) self.maskColorButton.setFixedHeight(self.font_metric.height() * 1.5) self.maskColorButton.clicked.connect(main_window.editMaskingColor) # Highlighting options self.hlCheck = QCheckBox('') self.hlCheck.stateChanged.connect(main_window.toggleHighlighting) self.hlColorButton = QPushButton() self.hlColorButton.setCursor(QtCore.Qt.PointingHandCursor) self.hlColorButton.setFixedWidth(button_width) self.hlColorButton.setFixedHeight(self.font_metric.height() * 1.5) self.hlColorButton.clicked.connect(main_window.editHighlightColor) self.alphaBox = QDoubleSpinBox() self.alphaBox.setRange(0, 1) self.alphaBox.setSingleStep(.05) self.alphaBox.valueChanged.connect(main_window.editAlpha) self.seedBox = QSpinBox() self.seedBox.setRange(1, 999) self.seedBox.valueChanged.connect(main_window.editSeed) # General options self.bgButton = QPushButton() self.bgButton.setCursor(QtCore.Qt.PointingHandCursor) self.bgButton.setFixedWidth(button_width) self.bgButton.setFixedHeight(self.font_metric.height() * 1.5) self.bgButton.clicked.connect(main_window.editBackgroundColor) self.colorbyBox = QComboBox(self) self.colorbyBox.addItem("material") self.colorbyBox.addItem("cell") self.colorbyBox.addItem("temperature") self.colorbyBox.addItem("density") self.colorbyBox.currentTextChanged[str].connect( main_window.editColorBy) self.universeLevelBox = QComboBox(self) self.universeLevelBox.addItem('all') for i in range(self.model.max_universe_levels): self.universeLevelBox.addItem(str(i)) self.universeLevelBox.currentTextChanged[str].connect( main_window.editUniverseLevel) # Overlap plotting self.overlapCheck = QCheckBox('', self) overlap_connector = partial(main_window.toggleOverlaps) self.overlapCheck.stateChanged.connect(overlap_connector) self.overlapColorButton = QPushButton() self.overlapColorButton.setCursor(QtCore.Qt.PointingHandCursor) self.overlapColorButton.setFixedWidth(button_width) self.overlapColorButton.setFixedHeight(self.font_metric.height() * 1.5) self.overlapColorButton.clicked.connect(main_window.editOverlapColor) self.colorResetButton = QPushButton("&Reset Colors") self.colorResetButton.setCursor(QtCore.Qt.PointingHandCursor) self.colorResetButton.clicked.connect(main_window.resetColors) formLayout = QFormLayout() formLayout.setAlignment(QtCore.Qt.AlignHCenter) formLayout.setFormAlignment(QtCore.Qt.AlignHCenter) formLayout.setLabelAlignment(QtCore.Qt.AlignLeft) formLayout.addRow('Masking:', self.maskingCheck) formLayout.addRow('Mask Color:', self.maskColorButton) formLayout.addRow(HorizontalLine()) formLayout.addRow('Highlighting:', self.hlCheck) formLayout.addRow('Highlight Color:', self.hlColorButton) formLayout.addRow('Highlight Alpha:', self.alphaBox) formLayout.addRow('Highlight Seed:', self.seedBox) formLayout.addRow(HorizontalLine()) formLayout.addRow('Background Color: ', self.bgButton) formLayout.addRow(HorizontalLine()) formLayout.addRow('Show Overlaps:', self.overlapCheck) formLayout.addRow('Overlap Color:', self.overlapColorButton) formLayout.addRow(HorizontalLine()) formLayout.addRow('Color Plot By:', self.colorbyBox) formLayout.addRow('Universe Level:', self.universeLevelBox) formLayout.addRow(self.colorResetButton, None) generalLayout = QHBoxLayout() innerWidget = QWidget() generalLayout.setAlignment(QtCore.Qt.AlignVCenter) innerWidget.setLayout(formLayout) generalLayout.addStretch(1) generalLayout.addWidget(innerWidget) generalLayout.addStretch(1) self.generalTab = QWidget() self.generalTab.setLayout(generalLayout) def createDomainTable(self, domainmodel): domainTable = QTableView() domainTable.setModel(domainmodel) domainTable.setItemDelegate(DomainDelegate(domainTable)) domainTable.verticalHeader().setVisible(False) domainTable.resizeColumnsToContents() domainTable.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) domainTable.horizontalHeader().setSectionResizeMode( 1, QHeaderView.Stretch) return domainTable def createDomainTab(self, domaintable): domainTab = QWidget() domainTab.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) domainLayout = QVBoxLayout() domainLayout.addWidget(domaintable) domainTab.setLayout(domainLayout) return domainTab def createPropertyTab(self, property_kind): propertyTab = QWidget() propertyTab.property_kind = property_kind propertyTab.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) propertyLayout = QVBoxLayout() propertyTab.minMaxCheckBox = QCheckBox() propertyTab.minMaxCheckBox.setCheckable(True) connector1 = partial(self.main_window.toggleUserMinMax, property=property_kind) propertyTab.minMaxCheckBox.stateChanged.connect(connector1) propertyTab.minBox = ScientificDoubleSpinBox(self) propertyTab.minBox.setMaximum(1E9) propertyTab.minBox.setMinimum(0) propertyTab.maxBox = ScientificDoubleSpinBox(self) propertyTab.maxBox.setMaximum(1E9) propertyTab.maxBox.setMinimum(0) connector2 = partial(self.main_window.editColorbarMin, property_type=property_kind) propertyTab.minBox.valueChanged.connect(connector2) connector3 = partial(self.main_window.editColorbarMax, property_type=property_kind) propertyTab.maxBox.valueChanged.connect(connector3) propertyTab.colormapBox = QComboBox(self) cmaps = sorted(m for m in mcolormaps.datad if not m.endswith("_r")) for cmap in cmaps: propertyTab.colormapBox.addItem(cmap) connector = partial(self.main_window.editColorMap, property_type=property_kind) propertyTab.colormapBox.currentTextChanged[str].connect(connector) propertyTab.dataIndicatorCheckBox = QCheckBox() propertyTab.dataIndicatorCheckBox.setCheckable(True) connector4 = partial(self.main_window.toggleDataIndicatorCheckBox, property=property_kind) propertyTab.dataIndicatorCheckBox.stateChanged.connect(connector4) propertyTab.colorBarScaleCheckBox = QCheckBox() propertyTab.colorBarScaleCheckBox.setCheckable(True) connector5 = partial(self.main_window.toggleColorbarScale, property=property_kind) propertyTab.colorBarScaleCheckBox.stateChanged.connect(connector5) formLayout = QFormLayout() formLayout.setAlignment(QtCore.Qt.AlignHCenter) formLayout.setFormAlignment(QtCore.Qt.AlignHCenter) formLayout.setLabelAlignment(QtCore.Qt.AlignLeft) formLayout.addRow('Colormap:', propertyTab.colormapBox) formLayout.addRow('Custom Min/Max', propertyTab.minMaxCheckBox) formLayout.addRow('Data Indicator', propertyTab.dataIndicatorCheckBox) formLayout.addRow('Log Scale', propertyTab.colorBarScaleCheckBox) formLayout.addRow(HorizontalLine()) formLayout.addRow('Max: ', propertyTab.maxBox) formLayout.addRow('Min: ', propertyTab.minBox) propertyTab.setLayout(formLayout) return propertyTab def updateDataIndicatorVisibility(self): av = self.model.activeView for key, val in av.data_indicator_enabled.items(): self.tabs[key].dataIndicatorCheckBox.setChecked(val) def updateColorMaps(self): cmaps = self.model.activeView.colormaps for key, val in cmaps.items(): idx = self.tabs[key].colormapBox.findText( val, QtCore.Qt.MatchFixedString) if idx >= 0: self.tabs[key].colormapBox.setCurrentIndex(idx) def updateColorMinMax(self): minmax = self.model.activeView.user_minmax for key, val in minmax.items(): self.tabs[key].minBox.setValue(val[0]) self.tabs[key].maxBox.setValue(val[1]) custom_minmax = self.model.activeView.use_custom_minmax for key, val, in custom_minmax.items(): self.tabs[key].minMaxCheckBox.setChecked(val) self.tabs[key].minBox.setEnabled(val) self.tabs[key].maxBox.setEnabled(val) def updateColorbarScale(self): av = self.model.activeView for key, val in av.color_scale_log.items(): self.tabs[key].colorBarScaleCheckBox.setChecked(val) def createButtonBox(self): applyButton = QPushButton("Apply Changes") applyButton.clicked.connect(self.main_window.applyChanges) closeButton = QPushButton("Close") closeButton.clicked.connect(self.hide) buttonLayout = QHBoxLayout() buttonLayout.addStretch(1) buttonLayout.addWidget(applyButton) buttonLayout.addWidget(closeButton) self.buttonBox = QWidget() self.buttonBox.setLayout(buttonLayout) def updateDialogValues(self): self.updateMasking() self.updateMaskingColor() self.updateColorMaps() self.updateColorMinMax() self.updateColorbarScale() self.updateDataIndicatorVisibility() self.updateHighlighting() self.updateHighlightColor() self.updateAlpha() self.updateSeed() self.updateBackgroundColor() self.updateColorBy() self.updateUniverseLevel() self.updateDomainTabs() self.updateOverlap() self.updateOverlapColor() def updateMasking(self): masking = self.model.activeView.masking self.maskingCheck.setChecked(masking) self.maskColorButton.setDisabled(not masking) if masking: self.cellTable.showColumn(4) self.matTable.showColumn(4) else: self.cellTable.hideColumn(4) self.matTable.hideColumn(4) def updateMaskingColor(self): color = self.model.activeView.maskBackground style_values = "border-radius: 8px; background-color: rgb{}" self.maskColorButton.setStyleSheet(style_values.format(str(color))) def updateHighlighting(self): highlighting = self.model.activeView.highlighting self.hlCheck.setChecked(highlighting) self.hlColorButton.setDisabled(not highlighting) self.alphaBox.setDisabled(not highlighting) self.seedBox.setDisabled(not highlighting) if highlighting: self.cellTable.showColumn(5) self.cellTable.hideColumn(2) self.cellTable.hideColumn(3) self.matTable.showColumn(5) self.matTable.hideColumn(2) self.matTable.hideColumn(3) else: self.cellTable.hideColumn(5) self.cellTable.showColumn(2) self.cellTable.showColumn(3) self.matTable.hideColumn(5) self.matTable.showColumn(2) self.matTable.showColumn(3) def updateHighlightColor(self): color = self.model.activeView.highlightBackground style_values = "border-radius: 8px; background-color: rgb{}" self.hlColorButton.setStyleSheet(style_values.format(str(color))) def updateAlpha(self): self.alphaBox.setValue(self.model.activeView.highlightAlpha) def updateSeed(self): self.seedBox.setValue(self.model.activeView.highlightSeed) def updateBackgroundColor(self): color = self.model.activeView.domainBackground self.bgButton.setStyleSheet("border-radius: 8px;" "background-color: rgb%s" % (str(color))) def updateOverlapColor(self): color = self.model.activeView.overlap_color self.overlapColorButton.setStyleSheet("border-radius: 8px;" "background-color: rgb%s" % (str(color))) def updateOverlap(self): colorby = self.model.activeView.colorby overlap_val = self.model.activeView.color_overlaps if colorby in ('cell', 'material'): self.overlapCheck.setChecked(overlap_val) def updateColorBy(self): colorby = self.model.activeView.colorby self.colorbyBox.setCurrentText(colorby) self.overlapCheck.setEnabled(colorby in ("cell", "material")) self.universeLevelBox.setEnabled(colorby == 'cell') def updateUniverseLevel(self): level = self.model.activeView.level if level == -1: self.universeLevelBox.setCurrentText('all') else: self.universeLevelBox.setCurrentText(str(level)) def updateDomainTabs(self): self.cellTable.setModel(self.main_window.cellsModel) self.matTable.setModel(self.main_window.materialsModel)
class MainWindow(QMainWindow): def __init__(self): super().__init__() layout = QVBoxLayout() form = QFormLayout() self.track_id = QSpinBox() self.track_id.setDisabled(True) 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.mapper = QDataWidgetMapper() self.mapper.setModel(self.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() self.mapper.toFirst() self.setMinimumSize(QSize(400, 400)) controls = QHBoxLayout() # tag::controls[] 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) # end::controls[] controls.addWidget(prev_rec) controls.addWidget(next_rec) controls.addWidget(save_rec) layout.addLayout(form) layout.addLayout(controls) widget = QWidget() widget.setLayout(layout) self.setCentralWidget(widget)
class MyWindow(QWidget): def __init__(self, parent=None): super().__init__(parent) self.setWindowTitle( 'Graphical utility for destroying, zeroing, and deleting files') self.label_donate = QLabel( 'Copyright (c) 2021, Aleksandr Suvorov | Donate: 4048 0250 0089 5923' ) self.label_donate.setAlignment(Qt.AlignCenter) self.label_logo = QLabel(f'Smart Cleaner<sup> {VERSION}</sup>') self.label_logo.setAlignment(Qt.AlignCenter) self.label_logo.setStyleSheet('font-size: 48px;') self.label_files = QLabel('Files') self.label_files.setStyleSheet("color: rgb(84, 180, 40);") self.label_dirs = QLabel('Folders') self.label_dirs.setStyleSheet("color: rgb(177, 98, 42);") self.label_errors = QLabel('Errors') self.label_errors.setStyleSheet("color: rgb(255, 68, 44);") self.lcd_files = QLCDNumber() self.lcd_files.setSegmentStyle(QLCDNumber.Flat) self.lcd_files.setStyleSheet("color: rgb(84, 180, 40);") self.lcd_dirs = QLCDNumber() self.lcd_dirs.setSegmentStyle(QLCDNumber.Flat) self.lcd_dirs.setStyleSheet("color: rgb(177, 98, 42);") self.lcd_errors = QLCDNumber() self.lcd_errors.setSegmentStyle(QLCDNumber.Flat) self.lcd_errors.setMinimumHeight(30) self.lcd_errors.setStyleSheet("color: rgb(255, 68, 44);") self.lcd_files.setDigitCount(15) self.lcd_dirs.setDigitCount(15) self.lcd_errors.setDigitCount(15) self.h_box1 = QHBoxLayout() self.h_box1.addWidget(self.label_dirs) self.h_box1.addWidget(self.label_files) self.h_box1.addWidget(self.label_errors) self.h_box2 = QHBoxLayout() self.h_box2.addWidget(self.lcd_dirs) self.h_box2.addWidget(self.lcd_files) self.h_box2.addWidget(self.lcd_errors) self.label_cons = QLabel('Information console:') self.text_browser = QTextBrowser() self.text_browser.setText( f'Smart Cleaner v{VERSION} \nUtility for overwriting, zeroing, and deleting files\n' f'https://github.com/mysmarthub') self.btn_console_clear = QPushButton('Reset') self.btn_donate = QPushButton('Donate | Visa: 4048 0250 0089 5923') self.btn_donate.setToolTip( 'We will be grateful for any financial support.\nThis will help the program ' 'develop and remain free.\nThanks!') self.btn_exit = QPushButton('Exit') self.h_box3 = QHBoxLayout() self.h_box3.addWidget(self.btn_donate) self.h_box3.addStretch(1) self.h_box3.addWidget(self.btn_console_clear) self.chb_del_dirs = QCheckBox('Delete folders') self.chb_del_dirs.setChecked(True) self.label_shred = QLabel('Rewrite:') self.spin_box = QSpinBox() self.spin_box.setMinimum(1) self.spin_box.setMaximum(1000) self.spin_box.setValue(30) self.h_box4 = QHBoxLayout() self.h_box4.addWidget(self.chb_del_dirs) self.h_box4.addWidget(self.label_shred) self.h_box4.addWidget(self.spin_box) self.h_box4.addStretch(1) self.list_widget = QListWidget() self.list_widget.setSelectionMode(QAbstractItemView.ExtendedSelection) self.btn_add_folder = QPushButton('+ Folder') self.btn_add_files = QPushButton('+ Files') self.btn_remove_item = QPushButton('- Remove') self.btn_zero_files = QPushButton('Zeroing') self.btn_shred_files = QPushButton('Erasing') self.btn_del_files = QPushButton('Delete') self.h_box5 = QHBoxLayout() self.h_box5.addWidget(self.btn_add_folder) self.h_box5.addWidget(self.btn_add_files) self.h_box5.addWidget(self.btn_remove_item) self.h_box5.addStretch(1) self.h_box5.addWidget(self.btn_shred_files) self.h_box5.addWidget(self.btn_zero_files) self.h_box5.addWidget(self.btn_del_files) self.h_box5.addWidget(self.btn_exit) self.v_box = QVBoxLayout() self.v_box.addWidget(self.label_logo) self.v_box.addLayout(self.h_box1) self.v_box.addLayout(self.h_box2) self.v_box.addWidget(self.label_cons) self.v_box.addWidget(self.text_browser) self.v_box.addLayout(self.h_box3) self.v_box.addLayout(self.h_box4) self.v_box.addWidget(self.list_widget) self.v_box.addLayout(self.h_box5) self.v_box.addWidget(self.label_donate) self.setLayout(self.v_box) self.smart_cleaner = SmartCleaner() self.btn_donate.clicked.connect( lambda: webbrowser.open('https://yoomoney.ru/to/4100115206129186')) self.btn_console_clear.clicked.connect(self.clear_console) self.btn_add_folder.clicked.connect(self.add_dir) self.btn_add_files.clicked.connect(self.add_files) self.btn_remove_item.clicked.connect(self.remove_items) self.btn_shred_files.clicked.connect(self.shred_start) self.btn_zero_files.clicked.connect(self.zeroing_start) self.btn_del_files.clicked.connect(self.delete_start) self.btn_exit.clicked.connect(self.close) self.smart_cleaner.signal.connect(self.update_information) self.smart_cleaner.started.connect(self.at_start) self.smart_cleaner.finished.connect(self.at_finish) def clear_console(self): self.lcd_dirs.display(0) self.lcd_files.display(0) self.lcd_errors.display(0) self.text_browser.setText( f'Smart Cleaner v{VERSION} \nUtility for overwriting, zeroing, and deleting files\n' f'https://github.com/mysmarthub') def add_dir(self) -> None: path = QFileDialog.getExistingDirectory(self, 'Select the folder to add: ') self._add_path(path) def add_files(self) -> None: path_tuple = QFileDialog.getOpenFileNames(self, 'Select files to add: ') for path in path_tuple[0]: self._add_path(path) def add_item(self, item: str) -> None: self.list_widget.addItem(item) def remove_items(self) -> None: for SelectedItem in self.list_widget.selectedItems(): self.list_widget.takeItem(self.list_widget.row(SelectedItem)) self.smart_cleaner.path_data.del_path(SelectedItem.text()) self.text_browser.append( f'{SelectedItem.text()}\nThe path was successfully deleted!!!') def _add_path(self, path: str) -> None: if path: if self.smart_cleaner.path_data.add_path(path): self.add_item(path) self.text_browser.append( f'{path}\nThe path was added successfully!') else: self.text_browser.append( f'Error when adding or the path was added earlier!!!') def shred_start(self): self.start(method='shred') def zeroing_start(self): self.start(method='zero') def delete_start(self): self.start(method='del') def start(self, method='shred'): if not self.smart_cleaner.path_data.is_any_data: self.show_msg('Warning!', 'There is no data for mashing!!!') else: reply = QMessageBox.question( self, 'Warning!', 'The data will be destroyed, are you sure?', QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: if method == 'zero': self.text_browser.append('Files are reset to zero.') elif method == 'shred': self.text_browser.append('File mashing is started.') elif method == 'del': self.text_browser.append('File deletion started.') self.smart_cleaner.work_method = method self.smart_cleaner.shreds = self.spin_box.value() self.smart_cleaner.delete_a_folder = self.chb_del_dirs.isChecked( ) self.smart_cleaner.start() def update_information(self, s: str) -> None: self.text_browser.append(s) self.update_lcd() def update_lcd(self) -> None: self.lcd_dirs.display(str(self.smart_cleaner.cleaner.count_del_dirs)) self.lcd_files.display(str(self.smart_cleaner.cleaner.count_del_files)) self.lcd_errors.display(str(self.smart_cleaner.num_errors)) def at_start(self): self.from_disable(True) def at_finish(self) -> None: if self.smart_cleaner.work_method != 'zero': self.list_widget.clear() self.update_lcd() self.from_disable(False) self.finish_msg() def finish_msg(self) -> None: if self.smart_cleaner.work_method == 'zero': msg = ('Reset', 'Reset files: ') count = self.smart_cleaner.cleaner.count_zero_files elif self.smart_cleaner.work_method == 'shred': msg = ('Mashing', 'Passageways: ') count = self.smart_cleaner.cleaner.count_del_files else: msg = ('Delete', 'Deleted files: ') count = self.smart_cleaner.cleaner.count_del_files self.show_msg( 'Warning!', f'{msg[0]} completed successfully!!!\n' f' {msg[1]} {count}\n ' f'Deleted folders: {self.smart_cleaner.cleaner.count_del_dirs}\n ' f'Errors: {self.smart_cleaner.num_errors}') def from_disable(self, status: bool) -> None: self.btn_zero_files.setDisabled(status) self.btn_remove_item.setDisabled(status) self.btn_add_folder.setDisabled(status) self.btn_shred_files.setDisabled(status) self.btn_console_clear.setDisabled(status) self.btn_add_files.setDisabled(status) self.btn_del_files.setDisabled(status) self.chb_del_dirs.setDisabled(status) self.spin_box.setDisabled(status) self.list_widget.setDisabled(status) def show_msg(self, title: str = 'Warning!', msg: str = 'Message...') -> None: QMessageBox.about(self, title, msg) def closeEvent(self, event) -> None: reply = QMessageBox.question( self, 'Exit', 'Are you sure you want to terminate the program?', QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: self.hide() self.smart_cleaner.wait(3000) event.accept() else: event.ignore()
class ColorDialog(QDialog): def __init__(self, model, FM, parent=None): super(ColorDialog, self).__init__(parent) self.setWindowTitle('Color Options') self.model = model self.FM = FM self.mw = parent self.createDialogLayout() def createDialogLayout(self): self.createGeneralTab() self.cellTable = self.createDomainTable(self.mw.cellsModel) self.matTable = self.createDomainTable(self.mw.materialsModel) self.cellTab = self.createDomainTab(self.cellTable) self.matTab = self.createDomainTab(self.matTable) self.tabs = QTabWidget() self.tabs.setMaximumHeight(800) self.tabs.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.tabs.addTab(self.generalTab, 'General') self.tabs.addTab(self.cellTab, 'Cells') self.tabs.addTab(self.matTab, 'Materials') self.createButtonBox() self.colorDialogLayout = QVBoxLayout() #self.colorDialogLayout.setContentsMargins(0, 0, 0, 0) self.colorDialogLayout.addWidget(self.tabs) self.colorDialogLayout.addWidget(self.buttonBox) self.setLayout(self.colorDialogLayout) def createGeneralTab(self): # Masking options self.maskingCheck = QCheckBox('') self.maskingCheck.stateChanged.connect(self.mw.toggleMasking) self.maskColorButton = QPushButton() self.maskColorButton.setCursor(QtCore.Qt.PointingHandCursor) self.maskColorButton.setFixedWidth(self.FM.width("XXXXXXXXXX")) self.maskColorButton.setFixedHeight(self.FM.height() * 1.5) self.maskColorButton.clicked.connect(self.mw.editMaskingColor) # Highlighting options self.hlCheck = QCheckBox('') self.hlCheck.stateChanged.connect(self.mw.toggleHighlighting) self.hlColorButton = QPushButton() self.hlColorButton.setCursor(QtCore.Qt.PointingHandCursor) self.hlColorButton.setFixedWidth(self.FM.width("XXXXXXXXXX")) self.hlColorButton.setFixedHeight(self.FM.height() * 1.5) self.hlColorButton.clicked.connect(self.mw.editHighlightColor) self.alphaBox = QDoubleSpinBox() self.alphaBox.setRange(0, 1) self.alphaBox.setSingleStep(.05) self.alphaBox.valueChanged.connect(self.mw.editAlpha) self.seedBox = QSpinBox() self.seedBox.setRange(1, 999) self.seedBox.valueChanged.connect(self.mw.editSeed) # General options self.bgButton = QPushButton() self.bgButton.setCursor(QtCore.Qt.PointingHandCursor) self.bgButton.setFixedWidth(self.FM.width("XXXXXXXXXX")) self.bgButton.setFixedHeight(self.FM.height() * 1.5) self.bgButton.clicked.connect(self.mw.editBackgroundColor) self.colorbyBox = QComboBox(self) self.colorbyBox.addItem("material") self.colorbyBox.addItem("cell") self.colorbyBox.currentTextChanged[str].connect(self.mw.editColorBy) formLayout = QFormLayout() formLayout.setAlignment(QtCore.Qt.AlignHCenter) formLayout.setFormAlignment(QtCore.Qt.AlignHCenter) formLayout.setLabelAlignment(QtCore.Qt.AlignLeft) #formLayout.setFieldGrowthPolicy(QFormLayout.AllNonFixedFieldsGrow) formLayout.addRow('Masking:', self.maskingCheck) formLayout.addRow('Mask Color:', self.maskColorButton) formLayout.addRow(HorizontalLine()) formLayout.addRow('Highlighting:', self.hlCheck) formLayout.addRow('Highlight Color:', self.hlColorButton) formLayout.addRow('Highlight Alpha:', self.alphaBox) formLayout.addRow('Highlight Seed:', self.seedBox) formLayout.addRow(HorizontalLine()) formLayout.addRow('Background Color: ', self.bgButton) formLayout.addRow('Color Plot By:', self.colorbyBox) generalLayout = QHBoxLayout() innerWidget = QWidget() generalLayout.setAlignment(QtCore.Qt.AlignVCenter) innerWidget.setLayout(formLayout) generalLayout.addStretch(1) generalLayout.addWidget(innerWidget) generalLayout.addStretch(1) self.generalTab = QWidget() self.generalTab.setLayout(generalLayout) def createDomainTable(self, domainmodel): domainTable = QTableView() domainTable.setModel(domainmodel) domainTable.setItemDelegate(DomainDelegate(domainTable)) domainTable.verticalHeader().setVisible(False) domainTable.resizeColumnsToContents() domainTable.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) domainTable.horizontalHeader().setSectionResizeMode( 1, QHeaderView.Stretch) return domainTable def createDomainTab(self, domaintable): domainTab = QWidget() domainTab.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) domainLayout = QVBoxLayout() domainLayout.addWidget(domaintable) domainTab.setLayout(domainLayout) return domainTab def createButtonBox(self): applyButton = QPushButton("Apply Changes") applyButton.clicked.connect(self.mw.applyChanges) closeButton = QPushButton("Close") closeButton.clicked.connect(self.hide) buttonLayout = QHBoxLayout() buttonLayout.addStretch(1) buttonLayout.addWidget(applyButton) buttonLayout.addWidget(closeButton) self.buttonBox = QWidget() self.buttonBox.setLayout(buttonLayout) def updateDialogValues(self): self.updateMasking() self.updateMaskingColor() self.updateHighlighting() self.updateHighlightColor() self.updateAlpha() self.updateSeed() self.updateBackgroundColor() self.updateColorBy() self.updateDomainTabs() def updateMasking(self): masking = self.model.activeView.masking self.maskingCheck.setChecked(masking) self.maskColorButton.setDisabled(not masking) if masking: self.cellTable.showColumn(4) self.matTable.showColumn(4) else: self.cellTable.hideColumn(4) self.matTable.hideColumn(4) def updateMaskingColor(self): color = self.model.activeView.maskBackground self.maskColorButton.setStyleSheet("border-radius: 8px;" "background-color: rgb%s" % (str(color))) def updateHighlighting(self): highlighting = self.model.activeView.highlighting self.hlCheck.setChecked(highlighting) self.hlColorButton.setDisabled(not highlighting) self.alphaBox.setDisabled(not highlighting) self.seedBox.setDisabled(not highlighting) if highlighting: self.cellTable.showColumn(5) self.cellTable.hideColumn(2) self.cellTable.hideColumn(3) self.matTable.showColumn(5) self.matTable.hideColumn(2) self.matTable.hideColumn(3) else: self.cellTable.hideColumn(5) self.cellTable.showColumn(2) self.cellTable.showColumn(3) self.matTable.hideColumn(5) self.matTable.showColumn(2) self.matTable.showColumn(3) def updateHighlightColor(self): color = self.model.activeView.highlightBackground self.hlColorButton.setStyleSheet("border-radius: 8px;" "background-color: rgb%s" % (str(color))) def updateAlpha(self): self.alphaBox.setValue(self.model.activeView.highlightAlpha) def updateSeed(self): self.seedBox.setValue(self.model.activeView.highlightSeed) def updateBackgroundColor(self): color = self.model.activeView.plotBackground self.bgButton.setStyleSheet("border-radius: 8px;" "background-color: rgb%s" % (str(color))) def updateColorBy(self): self.colorbyBox.setCurrentText(self.model.activeView.colorby) def updateDomainTabs(self): self.cellTable.setModel(self.mw.cellsModel) self.matTable.setModel(self.mw.materialsModel)
class ControlFrame(QFrame): def __init__(self, dataset, display_panel, threads): super().__init__() if isinstance(display_panel, DisplayFrame): self.display_panel = display_panel else: raise TypeError("'display_panel' must be the instance of " "'DisplayFrame'") self.dataset = dataset self.threads = threads self.__layout = QVBoxLayout() self.setLayout(self.__layout) self.__layout.setContentsMargins(0, 0, 0, 0) self.__set_running_options_ui() self.__set_fuzzy_set_operation_types_ui() self.__set_fuzzy_variables_ui() self.__set_fuzzy_rules_ui() self.__set_console_ui() def __set_running_options_ui(self): group_box = QGroupBox("Running Options") inner_layout = QHBoxLayout() group_box.setLayout(inner_layout) self.data_selector = QComboBox() self.data_selector.addItems(list(self.dataset.keys())) self.data_selector.setStatusTip("Select the road map case.") self.data_selector.currentIndexChanged.connect(self.__change_map) self.fps = QSpinBox() self.fps.setMinimum(1) self.fps.setMaximum(60) self.fps.setValue(20) self.fps.setStatusTip( "The re-drawing rate for car simulator. High fps " "may cause the plot shows discontinuously.") self.start_btn = QPushButton("Run") self.start_btn.setStatusTip("Run the car.") self.start_btn.clicked.connect(self.__run) self.stop_btn = QPushButton("Stop") self.stop_btn.setStatusTip("Force the simulation stop running.") self.stop_btn.setDisabled(True) self.save_btn = QPushButton() self.save_btn.setIcon(QIcon(':/icons/save_icon.png')) self.save_btn.setStatusTip("Save every details for the last time " "running.") self.save_btn.clicked.connect(self.__save_results) self.save_btn.setDisabled(True) self.__change_map() inner_layout.addWidget(self.data_selector, 1) inner_layout.addWidget(QLabel("FPS:")) inner_layout.addWidget(self.fps) inner_layout.addWidget(self.start_btn) inner_layout.addWidget(self.stop_btn) inner_layout.addWidget(self.save_btn) self.__layout.addWidget(group_box) def __set_fuzzy_set_operation_types_ui(self): group_box = QGroupBox("Fuzzy Sets Operation Types") inner_layout = QFormLayout() group_box.setLayout(inner_layout) self.implication_selections = RadioButtonSet([ ("imp_dr", QRadioButton("Dienes-Rescher")), ("imp_l", QRadioButton("Lukasieweicz")), ("imp_z", QRadioButton("Zadel")), ("imp_g", QRadioButton("Godel")), ("imp_m", QRadioButton("Mamdani")), ("imp_p", QRadioButton("Product")) ]) self.combination_vars_selections = RadioButtonSet([ ("tn_min", QRadioButton("Minimum")), ("tn_ap", QRadioButton("Algebraic Product")), ("tn_bp", QRadioButton("Bounded Product")), ("tn_dp", QRadioButton("Drastic Product")) ]) self.combination_rules_selections = RadioButtonSet([ ("tc_max", QRadioButton("Maximum")), ("tc_as", QRadioButton("Algebraic Sum")), ("tc_bs", QRadioButton("Bounded Sum")), ("tc_ds", QRadioButton("Drastic Sum")) ]) self.defuzzifier_selections = RadioButtonSet([ ("gravity_center", QRadioButton("Center of Gravity")), ("maxima_mean", QRadioButton("Mean of Maxima")), ("modified_maxima_mean", QRadioButton("Modified Mean of Maxima")) ]) self.implication_selections.set_selected('imp_m') self.combination_vars_selections.set_selected('tn_min') self.combination_rules_selections.set_selected('tc_max') self.defuzzifier_selections.set_selected('gravity_center') self.implication_selections.setStatusTip("Choose the method for fuzzy " "implication.") self.combination_vars_selections.setStatusTip( "Choose the method of " "combination of multiple " "fuzzy variables.") self.combination_rules_selections.setStatusTip("Choose the method of " "combination of " "multiple fuzzy rules.") self.defuzzifier_selections.setStatusTip("Choose the method for the " "defuzifier.") inner_layout.addRow(QLabel("Implication:"), self.implication_selections) inner_layout.addRow(QLabel("Combination of Variables:"), self.combination_vars_selections) inner_layout.addRow(QLabel("Combination of Rules:"), self.combination_rules_selections) inner_layout.addRow(QLabel("Defuzzifier:"), self.defuzzifier_selections) self.__layout.addWidget(group_box) def __set_fuzzy_variables_ui(self): group_box = QGroupBox("Fuzzy Variables Settings") group_box.setStatusTip("Set the membership functions for each fuzzy " "variable.") inner_layout = QVBoxLayout() self.fuzzyvar_setting_stack = QStackedWidget() self.fuzzyvar_ui_selection = RadioButtonSet([ ("front", QRadioButton("Front Distance Radar")), ("lrdiff", QRadioButton("(Left-Right) Distance Radar")), ("consequence", QRadioButton("Consequence")) ]) self.fuzzyvar_setting_dist_front = FuzzierVarSetting() self.fuzzyvar_setting_dist_front.small.mean.setValue(5) self.fuzzyvar_setting_dist_front.medium.mean.setValue(12) self.fuzzyvar_setting_dist_front.large.mean.setValue(20) self.fuzzyvar_setting_dist_lrdiff = FuzzierVarSetting() self.fuzzyvar_setting_dist_lrdiff.small.mean.setValue(-10) self.fuzzyvar_setting_dist_lrdiff.medium.mean.setValue(0) self.fuzzyvar_setting_dist_lrdiff.large.mean.setValue(10) self.fuzzyvar_setting_consequence = FuzzierVarSetting() self.fuzzyvar_setting_consequence.small.mean.setValue(-12) self.fuzzyvar_setting_consequence.small.sd.setValue(20) self.fuzzyvar_setting_consequence.medium.mean.setValue(0) self.fuzzyvar_setting_consequence.medium.sd.setValue(20) self.fuzzyvar_setting_consequence.large.mean.setValue(12) self.fuzzyvar_setting_consequence.large.sd.setValue(20) inner_layout.addWidget(self.fuzzyvar_ui_selection) inner_layout.addWidget(self.fuzzyvar_setting_stack) group_box.setLayout(inner_layout) self.fuzzyvar_setting_stack.addWidget(self.fuzzyvar_setting_dist_front) self.fuzzyvar_setting_stack.addWidget( self.fuzzyvar_setting_dist_lrdiff) self.fuzzyvar_setting_stack.addWidget( self.fuzzyvar_setting_consequence) self.fuzzyvar_ui_selection.sig_rbtn_changed.connect( self.__change_fuzzyvar_setting_ui_stack) self.__layout.addWidget(group_box) def __set_fuzzy_rules_ui(self): antecedents = ('small', 'medium', 'large') group_box = QGroupBox("Fuzzy Rules Setting") inner_layout = QVBoxLayout() group_box.setStatusTip("Set the rules for the fuzzy system.") self.rules_setting = FuzzyRulesSetting( [p for p in itertools.product(antecedents, repeat=2)]) self.rules_setting.set_consequence_fuzzysets( ('large', 'small', 'small', 'large', 'small', 'small', 'large', 'small', 'small')) inner_layout.addWidget(self.rules_setting) group_box.setLayout(inner_layout) self.__layout.addWidget(group_box) def __set_console_ui(self): self.__console = QTextEdit() self.__console.setReadOnly(True) self.__console.setStatusTip("Show the logs of status changing.") self.__layout.addWidget(self.__console) @Slot(str) def __change_fuzzyvar_setting_ui_stack(self, name): if name == 'front': self.fuzzyvar_setting_stack.setCurrentIndex(0) elif name == 'lrdiff': self.fuzzyvar_setting_stack.setCurrentIndex(1) else: self.fuzzyvar_setting_stack.setCurrentIndex(2) @Slot() def __change_map(self): self.__current_data = self.dataset[self.data_selector.currentText()] self.__car = Car(self.__current_data['start_pos'], self.__current_data['start_angle'], 3, self.__current_data['route_edge']) self.display_panel.change_map(self.__current_data) @Slot(str) def __print_console(self, text): self.__console.append(text) @Slot(list) def __get_results(self, results): """Get the results of last running and draw the path of it.""" self.results = results self.display_panel.show_path([d['x'] for d in results], [d['y'] for d in results]) @Slot() def __save_results(self): save_dir = QFileDialog.getExistingDirectory(self, 'Select Saving Directory') file4d_filepath = os.path.join(save_dir, 'train4D.txt') file6d_filepath = os.path.join(save_dir, 'train6D.txt') with open(file4d_filepath, 'w') as file4d: for result in self.results: file4d.write('{:.7f} {:.7f} {:.7f} {:.7f}\n'.format( result['front_dist'], result['right_dist'], result['left_dist'], result['wheel_angle'])) with open(file6d_filepath, 'w') as file6d: for result in self.results: file6d.write( '{:.7f} {:.7f} {:.7f} {:.7f} {:.7f} {:.7f}\n'.format( result['x'], result['y'], result['front_dist'], result['right_dist'], result['left_dist'], result['wheel_angle'])) self.__print_console('Note: Detailed results have been saved in both' ' "%s" and "%s".' % (file4d_filepath, file6d_filepath)) @Slot() def __init_widgets(self): self.start_btn.setDisabled(True) self.stop_btn.setEnabled(True) self.save_btn.setDisabled(True) self.fps.setDisabled(True) self.data_selector.setDisabled(True) self.implication_selections.setDisabled(True) self.combination_vars_selections.setDisabled(True) self.combination_rules_selections.setDisabled(True) self.defuzzifier_selections.setDisabled(True) self.fuzzyvar_setting_dist_front.setDisabled(True) self.fuzzyvar_setting_dist_lrdiff.setDisabled(True) self.fuzzyvar_setting_consequence.setDisabled(True) self.rules_setting.setDisabled(True) @Slot() def __reset_widgets(self): self.start_btn.setEnabled(True) self.stop_btn.setDisabled(True) self.save_btn.setEnabled(True) self.fps.setEnabled(True) self.data_selector.setEnabled(True) self.implication_selections.setEnabled(True) self.combination_vars_selections.setEnabled(True) self.combination_rules_selections.setEnabled(True) self.defuzzifier_selections.setEnabled(True) self.fuzzyvar_setting_dist_front.setEnabled(True) self.fuzzyvar_setting_dist_lrdiff.setEnabled(True) self.fuzzyvar_setting_consequence.setEnabled(True) self.rules_setting.setEnabled(True) @Slot() def __run(self): # reset the map self.__change_map() # create a QThread self.thread = RunCar(self.__car, self.__create_fuzzy_system(), (self.__current_data['end_area_lt'], self.__current_data['end_area_rb']), self.fps.value()) # Record the new created threads for the closeEvent in gui_base.py # By doing this, user can destroy the QMainWindow elegantly when there # are threads still running. self.threads.append(self.thread) self.stop_btn.clicked.connect(self.thread.stop) self.thread.started.connect(self.__init_widgets) self.thread.finished.connect(self.__reset_widgets) self.thread.sig_console.connect(self.__print_console) self.thread.sig_car.connect(self.display_panel.move_car) self.thread.sig_car_collided.connect( self.display_panel.show_car_collided) self.thread.sig_dists.connect(self.display_panel.show_dists) self.thread.sig_results.connect(self.__get_results) self.thread.start() def __create_fuzzy_system(self): """Create a fuzzy system with the parameter given in control panel.""" dist_front = FuzzyVariable() dist_front.add_membershipf( 'small', get_gaussianf( *self.fuzzyvar_setting_dist_front.small.get_values())) dist_front.add_membershipf( 'medium', get_gaussianf( *self.fuzzyvar_setting_dist_front.medium.get_values())) dist_front.add_membershipf( 'large', get_gaussianf( *self.fuzzyvar_setting_dist_front.large.get_values())) dist_lrdiff = FuzzyVariable() dist_lrdiff.add_membershipf( 'small', get_gaussianf( *self.fuzzyvar_setting_dist_lrdiff.small.get_values())) dist_lrdiff.add_membershipf( 'medium', get_gaussianf( *self.fuzzyvar_setting_dist_lrdiff.medium.get_values())) dist_lrdiff.add_membershipf( 'large', get_gaussianf( *self.fuzzyvar_setting_dist_lrdiff.large.get_values())) consequence = FuzzyVariable() consequence.add_membershipf( 'small', get_gaussianf( *self.fuzzyvar_setting_consequence.small.get_values())) consequence.add_membershipf( 'medium', get_gaussianf( *self.fuzzyvar_setting_consequence.medium.get_values())) consequence.add_membershipf( 'large', get_gaussianf( *self.fuzzyvar_setting_consequence.large.get_values())) fuzzy_system = FuzzySystem(consequence, dist_front, dist_lrdiff) fuzzy_system.set_operation_types( self.implication_selections.get_selected_name(), self.combination_vars_selections.get_selected_name(), self.combination_rules_selections.get_selected_name(), self.defuzzifier_selections.get_selected_name()) for antecendent_names, consequence_name in self.rules_setting.rules.items( ): fuzzy_system.add_rule(consequence_name, antecendent_names) return fuzzy_system
class DomainDock(PlotterDock): """ Domain options dock """ def __init__(self, model, font_metric, parent=None): super().__init__(model, font_metric, parent) self.setAllowedAreas(QtCore.Qt.LeftDockWidgetArea) # Create Controls self._createOriginBox() self._createOptionsBox() self._createResolutionBox() # Create submit button self.applyButton = QPushButton("Apply Changes") # Mac bug fix self.applyButton.setMinimumHeight(self.font_metric.height() * 1.6) self.applyButton.clicked.connect(self.main_window.applyChanges) # Create Zoom box self.zoomBox = QSpinBox() self.zoomBox.setSuffix(' %') self.zoomBox.setRange(25, 2000) self.zoomBox.setValue(100) self.zoomBox.setSingleStep(25) self.zoomBox.valueChanged.connect(self.main_window.editZoom) self.zoomLayout = QHBoxLayout() self.zoomLayout.addWidget(QLabel('Zoom:')) self.zoomLayout.addWidget(self.zoomBox) self.zoomLayout.setContentsMargins(0, 0, 0, 0) self.zoomWidget = QWidget() self.zoomWidget.setLayout(self.zoomLayout) # Create Layout self.dockLayout = QVBoxLayout() self.dockLayout.addWidget(QLabel("Geometry/Properties")) self.dockLayout.addWidget(HorizontalLine()) self.dockLayout.addWidget(self.originGroupBox) self.dockLayout.addWidget(self.optionsGroupBox) self.dockLayout.addWidget(self.resGroupBox) self.dockLayout.addWidget(HorizontalLine()) self.dockLayout.addWidget(self.zoomWidget) self.dockLayout.addWidget(HorizontalLine()) self.dockLayout.addStretch() self.dockLayout.addWidget(self.applyButton) self.dockLayout.addWidget(HorizontalLine()) self.optionsWidget = QWidget() self.optionsWidget.setLayout(self.dockLayout) self.setWidget(self.optionsWidget) def _createOriginBox(self): # X Origin self.xOrBox = QDoubleSpinBox() self.xOrBox.setDecimals(9) self.xOrBox.setRange(-99999, 99999) xbox_connector = partial(self.main_window.editSingleOrigin, dimension=0) self.xOrBox.valueChanged.connect(xbox_connector) # Y Origin self.yOrBox = QDoubleSpinBox() self.yOrBox.setDecimals(9) self.yOrBox.setRange(-99999, 99999) ybox_connector = partial(self.main_window.editSingleOrigin, dimension=1) self.yOrBox.valueChanged.connect(ybox_connector) # Z Origin self.zOrBox = QDoubleSpinBox() self.zOrBox.setDecimals(9) self.zOrBox.setRange(-99999, 99999) zbox_connector = partial(self.main_window.editSingleOrigin, dimension=2) self.zOrBox.valueChanged.connect(zbox_connector) # Origin Form Layout self.orLayout = QFormLayout() self.orLayout.addRow('X:', self.xOrBox) self.orLayout.addRow('Y:', self.yOrBox) self.orLayout.addRow('Z:', self.zOrBox) self.orLayout.setLabelAlignment(QtCore.Qt.AlignLeft) self.orLayout.setFieldGrowthPolicy(QFormLayout.AllNonFixedFieldsGrow) # Origin Group Box self.originGroupBox = QGroupBox('Origin') self.originGroupBox.setLayout(self.orLayout) def _createOptionsBox(self): # Width self.widthBox = QDoubleSpinBox(self) self.widthBox.setRange(.1, 99999) self.widthBox.setDecimals(9) self.widthBox.valueChanged.connect(self.main_window.editWidth) # Height self.heightBox = QDoubleSpinBox(self) self.heightBox.setRange(.1, 99999) self.heightBox.setDecimals(9) self.heightBox.valueChanged.connect(self.main_window.editHeight) # ColorBy self.colorbyBox = QComboBox(self) self.colorbyBox.addItem("material") self.colorbyBox.addItem("cell") self.colorbyBox.addItem("temperature") self.colorbyBox.addItem("density") self.colorbyBox.currentTextChanged[str].connect( self.main_window.editColorBy) # Universe level (applies to cell coloring only) self.universeLevelBox = QComboBox(self) self.universeLevelBox.addItem('all') for i in range(self.model.max_universe_levels): self.universeLevelBox.addItem(str(i)) self.universeLevelBox.currentTextChanged[str].connect( self.main_window.editUniverseLevel) # Alpha self.domainAlphaBox = QDoubleSpinBox(self) self.domainAlphaBox.setValue(self.model.activeView.domainAlpha) self.domainAlphaBox.setSingleStep(0.05) self.domainAlphaBox.setDecimals(2) self.domainAlphaBox.setRange(0.0, 1.0) self.domainAlphaBox.valueChanged.connect(self.main_window.editPlotAlpha) # Visibility self.visibilityBox = QCheckBox(self) self.visibilityBox.stateChanged.connect( self.main_window.editPlotVisibility) # Outlines self.outlinesBox = QCheckBox(self) self.outlinesBox.stateChanged.connect(self.main_window.toggleOutlines) # Basis self.basisBox = QComboBox(self) self.basisBox.addItem("xy") self.basisBox.addItem("xz") self.basisBox.addItem("yz") self.basisBox.currentTextChanged.connect(self.main_window.editBasis) # Advanced Color Options self.colorOptionsButton = QPushButton('Color Options...') self.colorOptionsButton.setMinimumHeight(self.font_metric.height() * 1.6) self.colorOptionsButton.clicked.connect(self.main_window.showColorDialog) # Options Form Layout self.opLayout = QFormLayout() self.opLayout.addRow('Width:', self.widthBox) self.opLayout.addRow('Height:', self.heightBox) self.opLayout.addRow('Basis:', self.basisBox) self.opLayout.addRow('Color By:', self.colorbyBox) self.opLayout.addRow('Universe Level:', self.universeLevelBox) self.opLayout.addRow('Plot alpha:', self.domainAlphaBox) self.opLayout.addRow('Visible:', self.visibilityBox) self.opLayout.addRow('Outlines:', self.outlinesBox) self.opLayout.addRow(self.colorOptionsButton) self.opLayout.setLabelAlignment(QtCore.Qt.AlignLeft) self.opLayout.setFieldGrowthPolicy(QFormLayout.AllNonFixedFieldsGrow) # Options Group Box self.optionsGroupBox = QGroupBox('Options') self.optionsGroupBox.setLayout(self.opLayout) def _createResolutionBox(self): # Horizontal Resolution self.hResBox = QSpinBox(self) self.hResBox.setRange(1, 99999) self.hResBox.setSingleStep(25) self.hResBox.setSuffix(' px') self.hResBox.valueChanged.connect(self.main_window.editHRes) # Vertical Resolution self.vResLabel = QLabel('Pixel Height:') self.vResBox = QSpinBox(self) self.vResBox.setRange(1, 99999) self.vResBox.setSingleStep(25) self.vResBox.setSuffix(' px') self.vResBox.valueChanged.connect(self.main_window.editVRes) # Ratio checkbox self.ratioCheck = QCheckBox("Fixed Aspect Ratio", self) self.ratioCheck.stateChanged.connect(self.main_window.toggleAspectLock) # Resolution Form Layout self.resLayout = QFormLayout() self.resLayout.addRow(self.ratioCheck) self.resLayout.addRow('Pixel Width:', self.hResBox) self.resLayout.addRow(self.vResLabel, self.vResBox) self.resLayout.setLabelAlignment(QtCore.Qt.AlignLeft) self.resLayout.setFieldGrowthPolicy(QFormLayout.AllNonFixedFieldsGrow) # Resolution Group Box self.resGroupBox = QGroupBox("Resolution") self.resGroupBox.setLayout(self.resLayout) def updateDock(self): self.updateOrigin() self.updateWidth() self.updateHeight() self.updateColorBy() self.updateUniverseLevel() self.updatePlotAlpha() self.updatePlotVisibility() self.updateOutlines() self.updateBasis() self.updateAspectLock() self.updateHRes() self.updateVRes() def updateOrigin(self): self.xOrBox.setValue(self.model.activeView.origin[0]) self.yOrBox.setValue(self.model.activeView.origin[1]) self.zOrBox.setValue(self.model.activeView.origin[2]) def updateWidth(self): self.widthBox.setValue(self.model.activeView.width) def updateHeight(self): self.heightBox.setValue(self.model.activeView.height) def updateColorBy(self): self.colorbyBox.setCurrentText(self.model.activeView.colorby) if self.model.activeView.colorby != 'cell': self.universeLevelBox.setEnabled(False) else: self.universeLevelBox.setEnabled(True) def updateUniverseLevel(self): self.universeLevelBox.setCurrentIndex(self.model.activeView.level + 1) def updatePlotAlpha(self): self.domainAlphaBox.setValue(self.model.activeView.domainAlpha) def updatePlotVisibility(self): self.visibilityBox.setChecked(self.model.activeView.domainVisible) def updateOutlines(self): self.outlinesBox.setChecked(self.model.activeView.outlines) def updateBasis(self): self.basisBox.setCurrentText(self.model.activeView.basis) def updateAspectLock(self): aspect_lock = bool(self.model.activeView.aspectLock) self.ratioCheck.setChecked(aspect_lock) self.vResBox.setDisabled(aspect_lock) self.vResLabel.setDisabled(aspect_lock) def updateHRes(self): self.hResBox.setValue(self.model.activeView.h_res) def updateVRes(self): self.vResBox.setValue(self.model.activeView.v_res) def revertToCurrent(self): cv = self.model.currentView self.xOrBox.setValue(cv.origin[0]) self.yOrBox.setValue(cv.origin[1]) self.zOrBox.setValue(cv.origin[2]) self.widthBox.setValue(cv.width) self.heightBox.setValue(cv.height) def resizeEvent(self, event): self.main_window.resizeEvent(event) hideEvent = showEvent = moveEvent = resizeEvent
class CourseEditDialog(QDialog): def __init__(self, course, is_new=False): super().__init__(GlobalAccess().get_main_window()) assert (isinstance(course, Course)) self.current_object = course self.is_new = is_new def exec_(self): self.init_ui() self.set_values_from_model() return super().exec_() def init_ui(self): self.setWindowTitle(_('Course properties')) self.setWindowIcon(QIcon(config.ICON)) self.setSizeGripEnabled(False) self.setModal(True) self.layout = QFormLayout(self) self.label_name = QLabel(_('Name')) self.item_name = QLineEdit() self.item_name.textChanged.connect(self.check_name) self.layout.addRow(self.label_name, self.item_name) self.label_length = QLabel(_('Length(m)')) self.item_length = QSpinBox() self.item_length.setMaximum(100000) self.item_length.setSingleStep(100) self.item_length.setValue(0) self.layout.addRow(self.label_length, self.item_length) self.label_climb = QLabel(_('Climb')) self.item_climb = QSpinBox() self.item_climb.setValue(0) self.item_climb.setMaximum(10000) self.item_climb.setSingleStep(10) self.layout.addRow(self.label_climb, self.item_climb) self.label_control_qty = QLabel(_('Point count')) self.item_control_qty = QSpinBox() self.item_control_qty.setDisabled(True) self.layout.addRow(self.label_control_qty, self.item_control_qty) self.label_controls = QLabel( '{}\n\n31 150\n32 200\n33\n34 500\n...\n90 150'.format( _('Controls'))) self.item_controls = QTextEdit() self.item_controls.setTabChangesFocus(True) self.layout.addRow(self.label_controls, self.item_controls) def cancel_changes(): self.close() def apply_changes(): try: self.apply_changes_impl() except Exception as e: logging.error(str(e)) self.close() button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.button_ok = button_box.button(QDialogButtonBox.Ok) self.button_ok.setText(_('OK')) self.button_ok.clicked.connect(apply_changes) self.button_cancel = button_box.button(QDialogButtonBox.Cancel) self.button_cancel.setText(_('Cancel')) self.button_cancel.clicked.connect(cancel_changes) self.layout.addRow(button_box) self.show() def check_name(self): name = self.item_name.text() self.button_ok.setDisabled(False) if name and name != self.current_object.name: org = find(race().courses, name=name) if org: self.button_ok.setDisabled(True) def set_values_from_model(self): self.item_name.setText(self.current_object.name) if self.current_object.length: self.item_length.setValue(self.current_object.length) if self.current_object.climb: self.item_climb.setValue(self.current_object.climb) if self.current_object.controls: self.item_control_qty.setValue(len(self.current_object.controls)) for i in self.current_object.controls: assert isinstance(i, CourseControl) self.item_controls.append('{} {}'.format( i.code, i.length if i.length else '')) def apply_changes_impl(self): course = self.current_object if self.is_new: race().courses.insert(0, course) if course.name != self.item_name.text(): course.name = self.item_name.text() if course.length != self.item_length.value(): course.length = self.item_length.value() if course.climb != self.item_climb.value(): course.climb = self.item_climb.value() text = self.item_controls.toPlainText() course.controls.clear() for i in text.split('\n'): control = CourseControl() if i is None or len(i) == 0: continue control.code = i.split()[0] if len(i.split()) > 1: try: control.length = int(i.split()[1]) except Exception as e: logging.error(str(e)) control.length = 0 course.controls.append(control) obj = race() ResultChecker.check_all() ResultCalculation(obj).process_results() RaceSplits(obj).generate() ScoreCalculation(obj).calculate_scores() Teamwork().send(course.to_dict())
class RenameOptionsView(QWidget): """View responsible for holding renaming options. Attributes: layout (QVBoxLayout): Main layout of view. frame_layout (QVBoxLayout: Layout of frame which holds options. frame (QFrame): Frame surrounding options. prefix_h_layout (QHBoxLayout): Layout holding prefix options. complete_rename_h_layout (QHBoxLayout): Layout holding complete rename options. search_and_replace_h_layout (QHBoxLayout): Layout holding search and replace options. renumber_h_layout (QHBoxLayout): Layout holding renumber options. remove_ext_h_layout (QHBoxLayout): Layout holding remove options. change_ext_h_layout (QHBoxLayout): Layout holding change extension options. create_backup_h_layout (QHBoxLayout): Layout holding backup options. preview_h_layout (QHBoxLayout): Layout holding preview options. start_lbl (QLabel): Label for renumbering start. padding_lbl (QLabel): Label for renumbering padding. add_prefix_cb (QCheckBox): Used to signify the user wants to add a prefix to the renaming. prefix (QLineEdit): prefix to add. complete_rename_cb (QCheckBox): Used to signify the user wants to completely rename the file. new_name (QLineEdit): New name used when renaming. search_and_replace_cb (QCheckBox): Used to signify the user wants to partially rename files. find (QLineEdit): When searching and replacing this is what the user wants to search for. replace (QLineEdit): When searching and replacing this is what the user wants to replace with. renumber_cb (QCheckBox): Used to signify the user wants to renumber while renaming. start_num (QSpinBox): Number to start with when renumbering files. padding (QComboBox): Padding to apply to renaming when renumbering files. dot_cb (QCheckBox): When checked a dot will be used to separate the renumber from the name. remove_ext_cb (QCheckBox): Used to signify the user wants to remove extensions when renaming. backup_files_cb (QCheckBox): Used to signify the user wants to backup old files before renaming. change_ext_cb (QCheckBox): Used to signify the user wants to change the extension while renaming. change_ext (QLineEdit): New extension to add to the renamed file. preview_cb (QCheckBox): Used to signify the user wants to preview the rename before renaming. """ def __init__(self): super(RenameOptionsView, self).__init__() self.layout = QVBoxLayout() self.frame_layout = QVBoxLayout() self.options_lbl = QLabel(prefs.OPTIONS) self.frame = QFrame() self.prefix_h_layout = QHBoxLayout() self.complete_rename_h_layout = QHBoxLayout() self.search_and_replace_h_layout = QHBoxLayout() self.renumber_h_layout = QHBoxLayout() self.remove_ext_h_layout = QHBoxLayout() self.change_ext_h_layout = QHBoxLayout() self.create_backup_h_layout = QHBoxLayout() self.preview_h_layout = QHBoxLayout() self.start_lbl = QLabel(prefs.START_NUM) self.padding_lbl = QLabel(prefs.PADDING) self.add_prefix_cb = QCheckBox(prefs.PREFIX) self.prefix = QLineEdit(prefs.PREFIX_DEFAULT) self.complete_rename_cb = QCheckBox(prefs.COMPLETE_RENAME) self.new_name = QLineEdit(prefs.COMPLETE_RENAME_DEFAULT) self.search_and_replace_cb = QCheckBox(prefs.SEARCH_AND_REPLACE) self.find = QLineEdit(prefs.SEARCH_AND_REPLACE_DEFAULT) self.replace = QLineEdit(prefs.REPLACE_WITH_DEFAULT) self.renumber_cb = QCheckBox(prefs.RENUMBER) self.start_num = QSpinBox() self.padding = QComboBox() self.dot_cb = QCheckBox(prefs.USE_DOT) self.remove_ext_cb = QCheckBox(prefs.REMOVE_EXT) self.backup_files_cb = QCheckBox(prefs.BACKUP) self.change_ext_cb = QCheckBox(prefs.CHANGE_EXT) self.change_ext = QLineEdit(prefs.CHANGE_EXT_DEFAULT) self.preview_cb = QCheckBox(prefs.PREVIEW) self._configure() def _configure(self) -> None: """Configure the RenameOptionsView.""" self.frame.setLayout(self.frame_layout) self.frame.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken) self.layout.addWidget(self.options_lbl) self.layout.addWidget(self.frame) self.add_prefix_cb.setToolTip(prefs.PREFIX_TOOLTIP) self.prefix.setDisabled(True) self.prefix.setMaximumWidth(prefs.PREFIX_WIDTH) self.prefix.setMinimumWidth(prefs.PREFIX_WIDTH) self.complete_rename_cb.setToolTip(prefs.COMPLETE_RENAME_TOOLTIP) self.new_name.setDisabled(True) self.new_name.setMaximumWidth(prefs.NEW_NAME_WIDTH) self.new_name.setMinimumWidth(prefs.NEW_NAME_WIDTH) self.search_and_replace_cb.setToolTip(prefs.SEARCH_AND_REPLACE_TOOLTIP) self.find.setDisabled(True) self.find.setMinimumWidth(prefs.FIND_WIDTH) self.find.setMaximumWidth(prefs.FIND_WIDTH) self.replace.setDisabled(True) self.replace.setMaximumWidth(prefs.REPLACE_WIDTH) self.replace.setMinimumWidth(prefs.REPLACE_WIDTH) self.renumber_cb.setToolTip(prefs.RENUMBER_TOOLTIP) self.start_num.setToolTip(prefs.START_NUM_TOOLTIP) self.start_num.setDisabled(True) self.start_num.setValue(prefs.START_NUM_DEFAULT) self.start_num.setMinimumWidth(prefs.START_NUM_MIN_WIDTH) self.padding.setToolTip(prefs.PADDING_TOOLTIP) self.padding.setDisabled(True) self.padding.addItems([str(x) for x in range(10)]) self.padding.setCurrentIndex(4) self.padding.setMinimumWidth(prefs.PADDING_MIN_WIDTH) self.dot_cb.setToolTip(prefs.USE_DOT_TOOLTIP) self.dot_cb.setDisabled(True) self.dot_cb.setChecked(True) self.dot_cb.setMinimumWidth(prefs.DOT_WIDTH) self.dot_cb.setMaximumWidth(prefs.DOT_WIDTH) self.remove_ext_cb.setToolTip(prefs.REMOVE_EXT_TOOLTIP) self.change_ext.setToolTip(prefs.CHANGE_EXT_TOOLTIP) self.change_ext.setDisabled(True) self.backup_files_cb.setToolTip(prefs.BACKUP_TOOLTIP) self.backup_files_cb.setChecked(True) self.preview_cb.setToolTip(prefs.PREVIEW_TOOLTIP) self.preview_cb.setChecked(True) self.prefix_h_layout.addWidget(self.add_prefix_cb) self.prefix_h_layout.addWidget(self.prefix) self.frame_layout.addLayout(self.prefix_h_layout) self.complete_rename_h_layout.addWidget(self.complete_rename_cb) self.complete_rename_h_layout.addWidget(self.new_name) self.frame_layout.addLayout(self.complete_rename_h_layout) self.search_and_replace_h_layout.addWidget(self.search_and_replace_cb) self.search_and_replace_h_layout.addWidget(self.find) self.search_and_replace_h_layout.addWidget(self.replace) self.frame_layout.addLayout(self.search_and_replace_h_layout) self.renumber_h_layout.addWidget(self.renumber_cb) self.renumber_h_layout.addStretch(1) self.renumber_h_layout.addWidget(self.start_lbl) self.renumber_h_layout.addWidget(self.start_num) self.renumber_h_layout.addSpacerItem(QSpacerItem(*prefs.SPACER_SIZE)) self.renumber_h_layout.addWidget(self.padding_lbl) self.renumber_h_layout.addWidget(self.padding) self.renumber_h_layout.addSpacerItem(QSpacerItem(*prefs.SPACER_SIZE)) self.renumber_h_layout.addWidget(self.dot_cb) self.frame_layout.addLayout(self.renumber_h_layout) self.change_ext_h_layout.addWidget(self.change_ext_cb) self.change_ext_h_layout.addWidget(self.change_ext) self.frame_layout.addLayout(self.change_ext_h_layout) self.remove_ext_h_layout.addWidget(self.remove_ext_cb) self.frame_layout.addLayout(self.remove_ext_h_layout) self.create_backup_h_layout.addWidget(self.backup_files_cb) self.frame_layout.addLayout(self.create_backup_h_layout) self.preview_h_layout.addWidget(self.preview_cb) self.frame_layout.addLayout(self.preview_h_layout) self.frame_layout.addSpacerItem(QSpacerItem(*prefs.SPACER_SIZE)) self.setLayout(self.layout) def disable_change_ext(self) -> None: """Disable change extension.""" self.change_ext.setDisabled(True) def disable_dot(self) -> None: """Disable dot checkbox.""" self.dot_cb.setDisabled(True) def disable_find(self) -> None: """Disable find.""" self.find.setDisabled(True) def disable_new_name(self) -> None: """Disable new name.""" print("disable new name") self.new_name.setDisabled(True) def disable_padding(self) -> None: """Disable padding.""" self.padding.setDisabled(True) def disable_prefix(self) -> None: """Disable prefix.""" self.prefix.setDisabled(True) def disable_start_num(self) -> None: """Disable start num.""" self.start_num.setDisabled(True) def disable_replace(self) -> None: """Disable replace.""" self.replace.setDisabled(True) def enable_change_ext(self) -> None: """Disable change extension.""" self.change_ext.setDisabled(False) def enable_dot(self) -> None: """Enable dot checkbox.""" self.dot_cb.setEnabled(True) def enable_find(self) -> None: """Enable find.""" self.find.setEnabled(True) def enable_new_name(self) -> None: """Enable new name.""" print("enable new name.") self.new_name.setEnabled(True) def enable_padding(self) -> None: """Enable padding.""" self.padding.setEnabled(True) def enable_prefix(self) -> None: """Enable prefix.""" self.prefix.setEnabled(True) def enable_replace(self) -> None: """Enable replace.""" self.replace.setEnabled(True) def enable_start_num(self) -> None: """Enable start num.""" self.start_num.setEnabled(True) def get_add_prefix(self) -> bool: """Return if end user wants to add a prefix and it is not the default value.""" result = self.get_prefix_checked() if result and self.get_prefix() == prefs.PREFIX_DEFAULT: result = False return result def get_do_backup(self) -> bool: """Return if end user wants to backup files.""" return self.backup_files_cb.isChecked() def get_change_ext(self) -> bool: """Return if the change extension checkbox is checked.""" return self.change_ext_cb.isChecked() def get_do_complete_rename(self) -> bool: """Get if end user wants to completely rename.""" return self.complete_rename_cb.isChecked() def get_dot(self) -> str: """Return dot string based on end users configuration. Note: If the end user has not enable using dot separators an empty string will be returned. """ return "." if self.get_do_dot() else "" def get_do_dot(self) -> bool: """Return if the end user wants to use dot separators when renaming.""" return self.dot_cb.isChecked() def get_do_change_ext(self) -> bool: """Return if the end user wants to change the extension.""" result = self.change_ext_cb.isChecked() if self.get_new_ext() == prefs.CHANGE_EXT_DEFAULT: return False return result def get_do_padding(self) -> bool: """Return if the end user wants to add padding.""" return False if self.get_padding() == 0 else True def get_do_preview(self) -> bool: """Return if the end user wants to preview changes.""" return self.preview_cb.isChecked() def get_do_rename(self) -> bool: """Return if end user wants to rename the full item and it is not the default value.""" result = self.complete_rename_cb.isChecked() if result and self.get_new_name() == prefs.COMPLETE_RENAME_DEFAULT: result = False return result def get_do_renumber(self) -> bool: """Return if the end user wants to renumber.""" return self.renumber_cb.isChecked() def get_do_search(self) -> bool: """Return if end user wants to perform a search and replace AND it is not the default values respectfully. Note: If you only want to know if search and replace is checked use get_search_and_replace. """ result = self.search_and_replace_cb.isChecked() if result and (self.get_find() == prefs.SEARCH_AND_REPLACE_DEFAULT or self.get_replace() == prefs.REPLACE_WITH_DEFAULT): result = False return result def get_do_search_and_replace(self) -> bool: """Return if end user wants to perform a search and replace.""" return self.search_and_replace_cb.isChecked() def get_find(self) -> str: """Return find value.""" return str(self.find.text()) def get_new_ext(self) -> str: """Return new ext.""" return str(self.change_ext.text()) def get_new_name(self) -> str: """Return new_name value.""" return str(self.new_name.text()) def get_padding(self) -> int: """Return the current padding value.""" return int(self.padding.currentText()) def get_prefix_checked(self) -> bool: """Return if the prefix checkbox is checked.""" return self.add_prefix_cb.isChecked() def get_prefix(self) -> str: """Return the current prefix value end user has entered.""" return str(self.prefix.text()) def get_remove_ext(self) -> bool: """Return if end user has checked the remove extension checkbox.""" return self.remove_ext_cb.isChecked() def get_replace(self) -> str: """Return the current replace value end user has entered.""" return str(self.replace.text()) def get_start_num(self) -> int: """Return start number from view.""" return int(self.start_num.value()) def set_change_ext_style(self, style: str) -> None: """Set style of change extension. Args: style: Style sheet applied to change extension. """ self.change_ext.setStyleSheet(style) def set_disabled(self) -> None: """Disable View.""" self.setDisabled(True) def set_enable(self) -> None: """Enable View.""" self.setEnabled(True) def set_find(self, value: str) -> None: """Set the value of find. Args: value: Value applied to find """ self.find.setText(value) def set_find_style(self, style: str) -> None: """Set style of find. Args: style: Style sheet applied to find. """ self.find.setStyleSheet(style) def set_new_name(self, value: str) -> None: """Set the value of new name. Args: value: Value applied to new_name """ self.new_name.setText(value) def set_new_name_style(self, style: str) -> None: """Set style of new_name. Args: style: Style sheet applied to new_name. """ self.new_name.setStyleSheet(style) def set_prefix(self, value: str) -> None: """Set the value of prefix. Args: value: Value applied to prefix """ self.prefix.setText(value) def set_prefix_style(self, style: str) -> None: """Set style of prefix. Args: style: Style sheet applied to prefix. """ self.prefix.setStyleSheet(style) def set_remove_ext(self, state: bool) -> None: """Set the remove_ext checkbox as checked or unchecked. Args: state: Check state of remove_ext. """ self.remove_ext_cb.setCheckState(Qt.Checked if state else Qt.Unchecked) def set_replace(self, value: str) -> None: """Set the value of replace. Args: value: Value applied to replace """ self.replace.setText(value) def set_replace_style(self, style: str) -> None: """Set style of replace. Args: style: Style sheet applied to replace. """ self.replace.setStyleSheet(style)
class Widget(QWidget): cinema_url_label_text = "粘贴独播库的连续剧/综艺/动漫 URL: " movie_url_label_text = "粘贴独播库的电影 URL: " cinema_dest_label_text = "输入连续剧/综艺/动漫名 (用来命名下载的目录): " movie_dest_label_text = "输入电影名 (用来命名下载的文件): " def __init__(self): QWidget.__init__(self) self.q = None self.pool = None self.top = QHBoxLayout() self.top.setMargin(10) self.radioButtonMov = QRadioButton("电影") self.radioButtonCinema = QRadioButton("连续剧/综艺/动漫") self.top.addWidget(self.radioButtonMov) self.top.addWidget(self.radioButtonCinema) self.middle = QVBoxLayout() self.middle.setMargin(10) self.url_label = QLabel() self.url = QLineEdit() self.url_label.setBuddy(self.url) self.middle.addWidget(self.url_label) self.middle.addWidget(self.url) self.browse_folder_label = QLabel("下载到:") self.browseFolder = QPushButton("选择目录") self.browse_folder_label.setBuddy(self.browseFolder) self.middle.addWidget(self.browse_folder_label) self.middle.addWidget(self.browseFolder) self.browse_folder_value = "" self.dest_file_label = QLabel() # "输入电影/电视剧名 (用来命名下载的文件/目录): " title set by choose_movie_widgets() later self.folder_or_filename = QLineEdit() self.dest_file_label.setBuddy(self.folder_or_filename) self.middle.addWidget(self.dest_file_label) self.middle.addWidget(self.folder_or_filename) self.bk_cinemae_spin_from = 1 self.bk_cinemae_spin_to = 1 self.fromEpSpinBox = QSpinBox() self.fromEpSpinBox.setMinimum(1) self.fromEpSpinBox.setMaximum(2147483647) self.fromEpLabel = QLabel("&从第几集开始下载:") self.fromEpLabel.setBuddy(self.fromEpSpinBox) self.toEpSpinBox = QSpinBox() self.toEpSpinBox.setMinimum(1) self.toEpSpinBox.setMaximum(2147483647) self.toEpLabel = QLabel("&到第几集停止下载:") self.toEpLabel.setBuddy(self.toEpSpinBox) self.cinema_ly = QHBoxLayout() #self.cinema_ly.setMargin(10) self.cinema_ly.addWidget(self.fromEpLabel) self.cinema_ly.addWidget(self.fromEpSpinBox) self.cinema_ly.addWidget(self.toEpLabel) self.cinema_ly.addWidget(self.toEpSpinBox) self.middle.addLayout(self.cinema_ly) self.proxy_label = QLabel("(如有)代理:") self.proxy = QLineEdit() self.proxy_label.setBuddy(self.proxy) self.middle.addWidget(self.proxy_label) self.middle.addWidget(self.proxy) self.add = QPushButton("开始下载") self.add.setEnabled(False) self.middle.addWidget(self.add) self.stop_me = QPushButton("停止下载") self.stop_me.setEnabled(False) self.middle.addWidget(self.stop_me) self.log_area = QPlainTextEdit() self.log_area.setReadOnly(True) self.log_area.setMaximumBlockCount(1000) self.middle.addWidget(self.log_area) #self.table_view.setSizePolicy(size) #self.layout.addWidget(self.table) self.layout = QVBoxLayout() self.layout.addLayout(self.top) self.layout.addLayout(self.middle) self.setLayout(self.layout) self.radioButtonMov.toggled.connect(self.choose_movie_widgets) self.radioButtonCinema.toggled.connect(self.choose_cinema_widgets) self.url.textChanged[str].connect(self.check_disable_download) self.browseFolder.clicked.connect(self.add_folder) self.folder_or_filename.textChanged[str].connect( self.check_disable_download) self.add.clicked.connect(self.start_download) self.stop_me.clicked.connect(self.stop_download) self.radioButtonMov.setChecked( True) #set default only after .connect above # TESTING PURPOSE ''' self.radioButtonMov.setChecked(False) self.url.setText('https://www.duboku.net/voddetail-969.html') self.browse_folder_value = 'C:/Users/Administrator/Documents/duboku' self.folder_or_filename.setText('初恋') ''' #set current process (not queue that one) log handler: logger = logging.getLogger(__name__) handler2 = LoggerWriter() logger.addHandler(handler2) logger.setLevel(logging.INFO) #DEBUG handler2.emitter.sigLog.connect(self.log_area.appendPlainText) sys.stdout = handler2 #LoggerWriter() #sys.stderr = handler2 #Seems no difference #handler2.emitter.sigLog.emit('hihi') @Slot() def choose_movie_widgets(self): if self.radioButtonMov.isChecked(): self.url_label.setText(self.movie_url_label_text) self.dest_file_label.setText(self.movie_dest_label_text) self.fromEpLabel.setDisabled(True) self.toEpLabel.setDisabled(True) self.fromEpSpinBox.setDisabled(True) self.toEpSpinBox.setDisabled(True) self.bk_cinemae_spin_from = self.fromEpSpinBox.value() self.bk_cinemae_spin_to = self.toEpSpinBox.value() self.fromEpSpinBox.setValue(1) self.toEpSpinBox.setValue(1) @Slot() def choose_cinema_widgets(self): if self.radioButtonCinema.isChecked(): self.url_label.setText(self.cinema_url_label_text) self.dest_file_label.setText(self.cinema_dest_label_text) self.fromEpLabel.setEnabled(True) self.toEpLabel.setEnabled(True) self.fromEpSpinBox.setEnabled(True) self.toEpSpinBox.setEnabled(True) self.fromEpSpinBox.setValue(self.bk_cinemae_spin_from) self.toEpSpinBox.setValue(self.bk_cinemae_spin_to) @Slot() def add_folder(self, s): #fname = QFileDialog.getOpenFileName(self, 'Open file', "c:\'", "Image files (*.jpg *.gif)") #fname = QFileDialog.getOpenFileName(self, 'Open file', '', QFileDialog.ShowDirsOnly) fname = QFileDialog.getExistingDirectory(self, '选择下载至什么目录', '', QFileDialog.ShowDirsOnly) #print('repr: ' + repr(fname)) if fname and fname.strip(): fname = fname.strip() self.browse_folder_value = fname #if getOpenFileName, will return ('/home/xiaobai/Pictures/disco.jpg', 'Image files (*.jpg *.gif)') #, while if getExistingDirectory, will return single path string only self.browseFolder.setText(fname) self.check_disable_download(fname) #else: # print('User cancel') @Slot() def check_disable_download(self, s): if self.url.text().strip( ) and self.browse_folder_value and self.folder_or_filename.text(): self.add.setEnabled(True) else: self.add.setEnabled(False) def task_done(self, retVal): self.add.setEnabled(True) self.stop_me.setEnabled(False) @Slot() def stop_download(self): if self.q: self.q.close() if self.pool: self.pool.terminate() self.add.setEnabled(True) self.stop_me.setEnabled(False) print('下载停止。') @Slot() def start_download(self): if self.fromEpSpinBox.value() > self.toEpSpinBox.value(): self.log_area.setPlainText('[!] 从第几集必须小于或等于到第几集。') return #No need worry click twice too fast, it seems already handle by PySide2 self.add.setEnabled(False) self.stop_me.setEnabled(True) self.log_area.clear() dest_full_path = os.path.join(self.browse_folder_value, self.folder_or_filename.text()) ''' print('dest_full_path: ' + repr(dest_full_path)) print('self.url.text(): ' + repr(self.url.text())) print('self.fromEpSpinBox.value(): ' + repr(self.fromEpSpinBox.value())) print('self.toEpSpinBox.value(): ' + repr(self.toEpSpinBox.value())) ''' import duboku_console #Windows can't set like that bcoz not update for args.url, must put explicitly #duboku_console.redirect_stdout_to_custom_stdout(arg_url, ...etc, LoggerWriter()) #failed other process handler = LogHandlerOtherProcess() handler.emitter.sigLog.connect(self.log_area.appendPlainText) ''' #ref current process: logger = logging.getLogger(__name__) handler2 = LoggerWriter() logger.addHandler(handler2) logger.setLevel(logging.DEBUG) handler2.emitter.sigLog.connect(self.log_area.appendPlainText) sys.stdout = handler2 #LoggerWriter() #handler2.emitter.sigLog.emit('hihi') ''' #handler = LoggerWriter() #handler.emitter.sigLog.connect(self.log_area.appendPlainText) self.q = multiprocessing.Queue() self.ql = QueueListener(self.q, handler) self.ql.start() self.pool = multiprocessing.Pool(1, worker_init, [self.q]) if self.radioButtonMov.isChecked(): self.pool.apply_async(duboku_console.main, args=(None, dest_full_path, self.fromEpSpinBox.value(), self.toEpSpinBox.value(), self.url.text().strip(), LoggerWriterOtherProcess(), False, self.proxy.text()), callback=self.task_done) else: self.pool.apply_async(duboku_console.main, args=(dest_full_path, None, self.fromEpSpinBox.value(), self.toEpSpinBox.value(), self.url.text().strip(), LoggerWriterOtherProcess(), False, self.proxy.text()), callback=self.task_done)
class MainWindow(QMainWindow): 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)
class TrainingPanel(Panel): def __init__(self, datasets, testing_panel, threads): super().__init__() if isinstance(testing_panel, TestingPanel): self.testing_panel = testing_panel else: raise TypeError('"testing_panel" must be the instance of ' '"TestingPanel"') self.datasets = datasets self.threads = threads self.__set_execution_ui() self.__set_options_ui() self.__set_outputs_ui() self.__set_graphic_ui() def __set_execution_ui(self): group_box = QGroupBox('Training Execution') inner_layout = QHBoxLayout() group_box.setLayout(inner_layout) self.data_selector = QComboBox() self.data_selector.addItems(list(self.datasets.keys())) self.data_selector.setStatusTip('Select the training dataset.') self.start_btn = QPushButton('Train') self.start_btn.setStatusTip('Start training.') self.start_btn.clicked.connect(self.__run) self.stop_btn = QPushButton('Stop') self.stop_btn.setStatusTip('Force the training stop running.') self.stop_btn.setDisabled(True) self.multicore_cb = QCheckBox('Multicore') self.multicore_cb.setStatusTip('Use multiprocessing in calculating ' 'fitting for populations.') self.multicore_cb.setChecked(True) inner_layout.addWidget(self.data_selector, 1) inner_layout.addWidget(self.start_btn) inner_layout.addWidget(self.stop_btn) inner_layout.addWidget(self.multicore_cb) self._layout.addWidget(group_box) def __set_options_ui(self): group_box = QGroupBox('Training Options') inner_layout = QFormLayout() group_box.setLayout(inner_layout) self.iter_times = QSpinBox() self.iter_times.setRange(1, 1000000) self.iter_times.setValue(200) self.iter_times.setStatusTip('The total iterating times for training.') self.population_size = QSpinBox() self.population_size.setRange(1, 100000) self.population_size.setValue(100) self.population_size.setStatusTip('The population size for the PSO.') self.inertia_weight = QDoubleSpinBox() self.inertia_weight.setRange(0, 50) self.inertia_weight.setValue(1) self.inertia_weight.setSingleStep(0.1) self.inertia_weight.setStatusTip('The inertia weight of the velocity ' ' for each individual.') self.cognitive_const_rand_upper = QDoubleSpinBox() self.cognitive_const_rand_upper.setRange(0, 50) self.cognitive_const_rand_upper.setValue(2) self.cognitive_const_rand_upper.setSingleStep(0.1) self.cognitive_const_rand_upper.setStatusTip( 'The random upper bound for cognitive accelerate constant.') self.social_const_rand_upper = QDoubleSpinBox() self.social_const_rand_upper.setRange(0, 50) self.social_const_rand_upper.setValue(3) self.social_const_rand_upper.setSingleStep(0.1) self.social_const_rand_upper.setStatusTip( 'The random upper bound for social accelerate constant.') self.v_max = QDoubleSpinBox() self.v_max.setRange(0.5, 100) self.v_max.setValue(5) self.v_max.setSingleStep(1) self.v_max.setStatusTip('The maximum of velocity for each individual.') self.nneuron = QSpinBox() self.nneuron.setRange(1, 100) self.nneuron.setValue(6) self.nneuron.setStatusTip('The number of RBFN neuron.') self.sd_max = QDoubleSpinBox() self.sd_max.setRange(0.01, 20) self.sd_max.setValue(10) self.sd_max.setSingleStep(0.1) self.sd_max.setStatusTip('The random range maximum of standard ' 'deviation of each neuron in RBFN (only for ' 'initialization).') inner_layout.addRow('Iterating Times:', self.iter_times) inner_layout.addRow('Population Size:', self.population_size) inner_layout.addRow('Inertia Weight:', self.inertia_weight) inner_layout.addRow('Cognitive Const Upper:', self.cognitive_const_rand_upper) inner_layout.addRow('Social Const Upper:', self.social_const_rand_upper) inner_layout.addRow('Maximum of Velocity:', self.v_max) inner_layout.addRow('Number of Neuron:', self.nneuron) inner_layout.addRow('Maximum of SD:', self.sd_max) self._layout.addWidget(group_box) def __set_outputs_ui(self): group_box = QGroupBox('Training Details') inner_layout = QFormLayout() group_box.setLayout(inner_layout) self.current_iter_time = QLabel('--') self.current_error = QLabel('--') self.avg_error = QLabel('--') self.global_best_error = QLabel('--') self.total_best_error = QLabel('--') self.progressbar = QProgressBar() self.current_iter_time.setAlignment(Qt.AlignCenter) self.current_error.setAlignment(Qt.AlignCenter) self.avg_error.setAlignment(Qt.AlignCenter) self.global_best_error.setAlignment(Qt.AlignCenter) self.total_best_error.setAlignment(Qt.AlignCenter) self.current_iter_time.setStatusTip('The current iterating time of ' 'the PSO.') self.current_error.setStatusTip('The current error from the fitting ' 'function. ("( )": normalized error)') self.avg_error.setStatusTip('The average error from the fitting ' 'function in current iteration. ("( )": ' 'normalized error)') self.global_best_error.setStatusTip( 'The error of global best individual from the fitting function in ' 'current iteration. ("( )": normalized error)') self.total_best_error.setStatusTip( 'The error of total best individual from the fitting function in ' 'training. ("( )": normalized error)') inner_layout.addRow('Current Iterating Time:', self.current_iter_time) inner_layout.addRow('Current Error:', self.current_error) inner_layout.addRow('Average Error:', self.avg_error) inner_layout.addRow('Global Best Error:', self.global_best_error) inner_layout.addRow('Total Best Error:', self.total_best_error) inner_layout.addRow(self.progressbar) self._layout.addWidget(group_box) def __set_graphic_ui(self): group_box = QGroupBox('Error Line Charts:') inner_layout = QVBoxLayout() group_box.setLayout(inner_layout) self.err_chart = ErrorLineChart(1) self.err_chart.setStatusTip('The history of error from the fitting ' 'of the PSO for each data.') self.__err_x = 1 self.iter_err_chart = ErrorLineChart( 3, ('Avg', 'Global Best', 'Total Best')) self.iter_err_chart.setStatusTip('The history of average and least ' 'error from the fitting of the PSO ' 'for each iteration.') self.iter_err_chart.setMinimumHeight(150) inner_layout.addWidget(QLabel('Current Error')) inner_layout.addWidget(self.err_chart) inner_layout.addWidget(QLabel('Average Error')) inner_layout.addWidget(self.iter_err_chart) self._layout.addWidget(group_box) @Slot() def __init_widgets(self): self.start_btn.setDisabled(True) self.stop_btn.setEnabled(True) self.multicore_cb.setDisabled(True) self.data_selector.setDisabled(True) self.iter_times.setDisabled(True) self.population_size.setDisabled(True) self.inertia_weight.setDisabled(True) self.cognitive_const_rand_upper.setDisabled(True) self.social_const_rand_upper.setDisabled(True) self.v_max.setDisabled(True) self.nneuron.setDisabled(True) self.sd_max.setDisabled(True) self.err_chart.clear() self.iter_err_chart.clear() self.__err_x = 1 @Slot() def __reset_widgets(self): self.start_btn.setEnabled(True) self.stop_btn.setDisabled(True) self.multicore_cb.setEnabled(True) self.data_selector.setEnabled(True) self.iter_times.setEnabled(True) self.population_size.setEnabled(True) self.inertia_weight.setEnabled(True) self.cognitive_const_rand_upper.setEnabled(True) self.social_const_rand_upper.setEnabled(True) self.v_max.setEnabled(True) self.nneuron.setEnabled(True) self.sd_max.setEnabled(True) self.progressbar.setMinimum(0) self.progressbar.setMaximum(100) @Slot() def __indicate_busy(self): self.progressbar.setMinimum(0) self.progressbar.setMaximum(0) @Slot(int) def __show_current_iter_time(self, value): self.current_iter_time.setText(str(value + 1)) self.progressbar.setValue(value + 1) @Slot(float) def __show_current_error(self, value): self.current_error.setText('{:.5f} ({:.5f})'.format(value, value / 40)) self.err_chart.append_point(self.__err_x, value) self.__err_x += 1 @Slot(float, float, float) def __show_iter_error(self, avg, glob, total): self.avg_error.setText('{:.5f} ({:.5f})'.format(avg, avg / 40)) self.global_best_error.setText( '{:.5f} ({:.5f})'.format(glob, glob / 40)) self.total_best_error.setText( '{:.5f} ({:.5f})'.format(total, total / 40)) self.iter_err_chart.append_point( int(self.current_iter_time.text()), total, 2) self.iter_err_chart.append_point( int(self.current_iter_time.text()), glob, 1) self.iter_err_chart.append_point( int(self.current_iter_time.text()), avg, 0) def __run(self): self.progressbar.setMaximum(self.iter_times.value()) self.__current_dataset = self.datasets[ self.data_selector.currentText()] self.__pso = PSO(self.iter_times.value(), self.population_size.value(), self.inertia_weight.value(), self.cognitive_const_rand_upper.value(), self.social_const_rand_upper.value(), self.v_max.value(), self.nneuron.value(), self.__current_dataset, self.sd_max.value(), is_multicore=self.multicore_cb.isChecked()) self.threads.append(self.__pso) self.stop_btn.clicked.connect(self.__pso.stop) self.__pso.started.connect(self.__init_widgets) self.__pso.finished.connect(self.__reset_widgets) self.__pso.sig_current_iter_time.connect(self.__show_current_iter_time) self.__pso.sig_current_error.connect(self.__show_current_error) self.__pso.sig_iter_error.connect(self.__show_iter_error) self.__pso.sig_indicate_busy.connect(self.__indicate_busy) self.__pso.sig_console.connect(self.testing_panel.print_console) self.__pso.sig_rbfn.connect(self.testing_panel.load_rbfn) self.__pso.start()
class OptionsDock(QDockWidget): def __init__(self, model, FM, parent=None): super(OptionsDock, self).__init__(parent) self.model = model self.FM = FM self.mw = parent self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding) # Doesn't work? self.setAllowedAreas(QtCore.Qt.LeftDockWidgetArea | QtCore.Qt.RightDockWidgetArea) # Create Controls self.createOriginBox() self.createOptionsBox() self.createResolutionBox() # Create submit button self.applyButton = QPushButton("Apply Changes") self.applyButton.setMinimumHeight(self.FM.height() * 1.6) # Mac bug fix self.applyButton.clicked.connect(self.mw.applyChanges) # Create Zoom box self.zoomBox = QSpinBox() self.zoomBox.setSuffix(' %') self.zoomBox.setRange(25, 2000) self.zoomBox.setValue(100) self.zoomBox.setSingleStep(25) self.zoomBox.valueChanged.connect(self.mw.editZoom) self.zoomLayout = QHBoxLayout() self.zoomLayout.addWidget(QLabel('Zoom:')) self.zoomLayout.addWidget(self.zoomBox) self.zoomLayout.setContentsMargins(0, 0, 0, 0) self.zoomWidget = QWidget() self.zoomWidget.setLayout(self.zoomLayout) # Create Layout self.dockLayout = QVBoxLayout() self.dockLayout.addWidget(self.originGroupBox) self.dockLayout.addWidget(self.optionsGroupBox) self.dockLayout.addWidget(self.resGroupBox) self.dockLayout.addWidget(self.applyButton) self.dockLayout.addStretch() self.dockLayout.addWidget(HorizontalLine()) self.dockLayout.addWidget(self.zoomWidget) self.optionsWidget = QWidget() self.optionsWidget.setLayout(self.dockLayout) self.setWidget(self.optionsWidget) def createOriginBox(self): # X Origin self.xOrBox = QDoubleSpinBox() self.xOrBox.setDecimals(9) self.xOrBox.setRange(-99999, 99999) self.xOrBox.valueChanged.connect( lambda value: self.mw.editSingleOrigin(value, 0)) # Y Origin self.yOrBox = QDoubleSpinBox() self.yOrBox.setDecimals(9) self.yOrBox.setRange(-99999, 99999) self.yOrBox.valueChanged.connect( lambda value: self.mw.editSingleOrigin(value, 1)) # Z Origin self.zOrBox = QDoubleSpinBox() self.zOrBox.setDecimals(9) self.zOrBox.setRange(-99999, 99999) self.zOrBox.valueChanged.connect( lambda value: self.mw.editSingleOrigin(value, 2)) # Origin Form Layout self.orLayout = QFormLayout() self.orLayout.addRow('X:', self.xOrBox) self.orLayout.addRow('Y:', self.yOrBox) self.orLayout.addRow('Z:', self.zOrBox) #self.orLayout.setVerticalSpacing(4) self.orLayout.setLabelAlignment(QtCore.Qt.AlignLeft) self.orLayout.setFieldGrowthPolicy(QFormLayout.AllNonFixedFieldsGrow) # Origin Group Box self.originGroupBox = QGroupBox('Origin') self.originGroupBox.setLayout(self.orLayout) def createOptionsBox(self): # Width self.widthBox = QDoubleSpinBox(self) self.widthBox.setRange(.1, 99999) self.widthBox.valueChanged.connect(self.mw.editWidth) # Height self.heightBox = QDoubleSpinBox(self) self.heightBox.setRange(.1, 99999) self.heightBox.valueChanged.connect(self.mw.editHeight) # ColorBy self.colorbyBox = QComboBox(self) self.colorbyBox.addItem("material") self.colorbyBox.addItem("cell") self.colorbyBox.currentTextChanged[str].connect(self.mw.editColorBy) # Alpha self.plotAlphaBox = QDoubleSpinBox(self) self.plotAlphaBox.setValue(self.model.activeView.plotAlpha) self.plotAlphaBox.setSingleStep(0.05) self.plotAlphaBox.setDecimals(2) self.plotAlphaBox.setRange(0.0, 1.0) self.plotAlphaBox.valueChanged.connect(self.mw.editPlotAlpha) # Basis self.basisBox = QComboBox(self) self.basisBox.addItem("xy") self.basisBox.addItem("xz") self.basisBox.addItem("yz") self.basisBox.currentTextChanged.connect(self.mw.editBasis) # Advanced Color Options self.colorOptionsButton = QPushButton('Color Options...') self.colorOptionsButton.setMinimumHeight(self.FM.height() * 1.6) self.colorOptionsButton.clicked.connect(self.mw.showColorDialog) # Options Form Layout self.opLayout = QFormLayout() self.opLayout.addRow('Width:', self.widthBox) self.opLayout.addRow('Height:', self.heightBox) self.opLayout.addRow('Basis:', self.basisBox) self.opLayout.addRow('Color By:', self.colorbyBox) self.opLayout.addRow('Plot alpha:', self.plotAlphaBox) self.opLayout.addRow(self.colorOptionsButton) self.opLayout.setLabelAlignment(QtCore.Qt.AlignLeft) self.opLayout.setFieldGrowthPolicy(QFormLayout.AllNonFixedFieldsGrow) # Options Group Box self.optionsGroupBox = QGroupBox('Options') self.optionsGroupBox.setLayout(self.opLayout) def createResolutionBox(self): # Horizontal Resolution self.hResBox = QSpinBox(self) self.hResBox.setRange(1, 99999) self.hResBox.setSingleStep(25) self.hResBox.setSuffix(' px') self.hResBox.valueChanged.connect(self.mw.editHRes) # Vertical Resolution self.vResLabel = QLabel('Pixel Height:') self.vResBox = QSpinBox(self) self.vResBox.setRange(1, 99999) self.vResBox.setSingleStep(25) self.vResBox.setSuffix(' px') self.vResBox.valueChanged.connect(self.mw.editVRes) # Ratio checkbox self.ratioCheck = QCheckBox("Fixed Aspect Ratio", self) self.ratioCheck.stateChanged.connect(self.mw.toggleAspectLock) # Resolution Form Layout self.resLayout = QFormLayout() self.resLayout.addRow(self.ratioCheck) self.resLayout.addRow('Pixel Width:', self.hResBox) self.resLayout.addRow(self.vResLabel, self.vResBox) self.resLayout.setLabelAlignment(QtCore.Qt.AlignLeft) self.resLayout.setFieldGrowthPolicy(QFormLayout.AllNonFixedFieldsGrow) # Resolution Group Box self.resGroupBox = QGroupBox("Resolution") self.resGroupBox.setLayout(self.resLayout) def updateDock(self): self.updateOrigin() self.updateWidth() self.updateHeight() self.updateColorBy() self.updatePlotAlpha() self.updateBasis() self.updateAspectLock() self.updateHRes() self.updateVRes() def updateOrigin(self): self.xOrBox.setValue(self.model.activeView.origin[0]) self.yOrBox.setValue(self.model.activeView.origin[1]) self.zOrBox.setValue(self.model.activeView.origin[2]) def updateWidth(self): self.widthBox.setValue(self.model.activeView.width) def updateHeight(self): self.heightBox.setValue(self.model.activeView.height) def updateColorBy(self): self.colorbyBox.setCurrentText(self.model.activeView.colorby) def updatePlotAlpha(self): self.plotAlphaBox.setValue(self.model.activeView.plotAlpha) def updateBasis(self): self.basisBox.setCurrentText(self.model.activeView.basis) def updateAspectLock(self): if self.model.activeView.aspectLock: self.ratioCheck.setChecked(True) self.vResBox.setDisabled(True) self.vResLabel.setDisabled(True) else: self.ratioCheck.setChecked(False) self.vResBox.setDisabled(False) self.vResLabel.setDisabled(False) def updateHRes(self): self.hResBox.setValue(self.model.activeView.h_res) def updateVRes(self): self.vResBox.setValue(self.model.activeView.v_res) def revertToCurrent(self): cv = self.model.currentView self.xOrBox.setValue(cv.origin[0]) self.yOrBox.setValue(cv.origin[1]) self.zOrBox.setValue(cv.origin[2]) self.widthBox.setValue(cv.width) self.heightBox.setValue(cv.height) def resizeEvent(self, event): self.mw.resizeEvent(event) def hideEvent(self, event): self.mw.resizeEvent(event) def showEvent(self, event): self.mw.resizeEvent(event) def moveEvent(self, event): self.mw.resizeEvent(event)
class Widget(QWidget): movie_url_label_text = "粘贴有 dailymotion 版的連續劇网址 (例子: https://dramaq.de/cn191023b/): " def __init__(self): QWidget.__init__(self) self.q = None self.pool = None self.top = QHBoxLayout() self.top.setMargin(10) self.middle = QVBoxLayout() self.middle.setMargin(10) self.radioButtonDailyMotionDrama = QRadioButton( "有 Dailymotion Drama 的網站") self.radioButtonAny = QRadioButton("其它類型網站 (例如 YouTube)") self.top.addWidget(self.radioButtonDailyMotionDrama) self.top.addWidget(self.radioButtonAny) self.url_label = QLabel() self.url = QLineEdit() self.url_label.setBuddy(self.url) self.middle.addWidget(self.url_label) self.middle.addWidget(self.url) self.browse_folder_label = QLabel("下載到:") self.browseFolder = QPushButton("選擇目錄") self.browse_folder_label.setBuddy(self.browseFolder) self.middle.addWidget(self.browse_folder_label) self.middle.addWidget(self.browseFolder) self.browse_folder_value = "" self.bk_cinemae_spin_from = 1 self.bk_cinemae_spin_to = 1 self.fromEpSpinBox = QSpinBox() self.fromEpSpinBox.setMinimum(1) self.fromEpSpinBox.setMaximum(2147483647) self.fromEpLabel = QLabel("&從第幾集開始下載:") self.fromEpLabel.setBuddy(self.fromEpSpinBox) self.toEpSpinBox = QSpinBox() self.toEpSpinBox.setMinimum(1) self.toEpSpinBox.setMaximum(2147483647) self.toEpLabel = QLabel("&到第幾集停止下載:") self.toEpLabel.setBuddy(self.toEpSpinBox) self.cinema_ly = QHBoxLayout() #self.cinema_ly.setMargin(10) self.cinema_ly.addWidget(self.fromEpLabel) self.cinema_ly.addWidget(self.fromEpSpinBox) self.cinema_ly.addWidget(self.toEpLabel) self.cinema_ly.addWidget(self.toEpSpinBox) self.middle.addLayout(self.cinema_ly) self.add = QPushButton("開始下載") self.add.setEnabled(False) self.middle.addWidget(self.add) self.stop_me = QPushButton("停止下載") self.stop_me.setEnabled(False) self.middle.addWidget(self.stop_me) self.log_area = QPlainTextEdit() self.log_area.setReadOnly(True) self.log_area.setMaximumBlockCount(1000) self.middle.addWidget(self.log_area) #self.table_view.setSizePolicy(size) #self.layout.addWidget(self.table) self.layout = QVBoxLayout() self.layout.addLayout(self.top) self.layout.addLayout(self.middle) self.setLayout(self.layout) self.radioButtonDailyMotionDrama.toggled.connect( self.choose_DailyMotionDrama_widgets) self.radioButtonAny.toggled.connect(self.choose_Any_widgets) self.url.textChanged[str].connect(self.check_disable_download) self.browseFolder.clicked.connect(self.add_folder) self.add.clicked.connect(self.start_download) self.stop_me.clicked.connect(self.stop_download) self.radioButtonDailyMotionDrama.setChecked( True) #set default only after .connect above # TESTING PURPOSE ''' self.url.setText('https://journalflash.com/cn191023b/') self.browse_folder_value = 'C:/Users/Administrator/Documents/duboku' ''' #set current process (not queue that one) log handler: logger = logging.getLogger(__name__) handler2 = LoggerWriter() logger.addHandler(handler2) logger.setLevel(logging.INFO) #DEBUG handler2.emitter.sigLog.connect(self.log_area.appendPlainText) sys.stdout = handler2 #LoggerWriter() #sys.stderr = handler2 #Seems no difference #handler2.emitter.sigLog.emit('hihi') @Slot() def choose_DailyMotionDrama_widgets(self): if self.radioButtonDailyMotionDrama.isChecked(): self.fromEpLabel.setEnabled(True) self.toEpLabel.setEnabled(True) self.fromEpSpinBox.setEnabled(True) self.toEpSpinBox.setEnabled(True) self.fromEpSpinBox.setValue(self.bk_cinemae_spin_from) self.toEpSpinBox.setValue(self.bk_cinemae_spin_to) self.fromEpLabel.setDisabled(True) self.toEpLabel.setDisabled(True) @Slot() def choose_Any_widgets(self): if self.radioButtonAny.isChecked(): self.fromEpSpinBox.setDisabled(True) self.toEpSpinBox.setDisabled(True) self.bk_cinemae_spin_from = self.fromEpSpinBox.value() self.bk_cinemae_spin_to = self.toEpSpinBox.value() self.fromEpSpinBox.setValue(1) self.toEpSpinBox.setValue(1) @Slot() def add_folder(self, s): #fname = QFileDialog.getOpenFileName(self, 'Open file', "c:\'", "Image files (*.jpg *.gif)") #fname = QFileDialog.getOpenFileName(self, 'Open file', '', QFileDialog.ShowDirsOnly) fname = QFileDialog.getExistingDirectory(self, '選擇下載至什麼目錄', '', QFileDialog.ShowDirsOnly) #print('repr: ' + repr(fname)) if fname and fname.strip(): fname = fname.strip() self.browse_folder_value = fname #if getOpenFileName, will return ('/home/xiaobai/Pictures/disco.jpg', 'Image files (*.jpg *.gif)') #, while if getExistingDirectory, will return single path string only self.browseFolder.setText(fname) self.check_disable_download(fname) #else: # print('User cancel') @Slot() def check_disable_download(self, s): if self.url.text() and self.browse_folder_value: self.add.setEnabled(True) else: self.add.setEnabled(False) def task_done(self, retVal): self.add.setEnabled(True) self.stop_me.setEnabled(False) @Slot() def stop_download(self): if self.q: self.q.close() if self.pool: self.pool.terminate() self.add.setEnabled(True) self.stop_me.setEnabled(False) print('下載停止。') @Slot() def start_download(self): if self.fromEpSpinBox.value() > self.toEpSpinBox.value(): self.log_area.setPlainText('[!] 從第幾集必須小於或等於到第幾集。') return #No need worry click twice too fast, it seems already handle by PySide2 self.add.setEnabled(False) self.stop_me.setEnabled(True) self.log_area.clear() dest_full_path = self.browse_folder_value ''' print('dest_full_path: ' + repr(dest_full_path)) print('self.url.text(): ' + repr(self.url.text())) print('self.fromEpSpinBox.value(): ' + repr(self.fromEpSpinBox.value())) print('self.toEpSpinBox.value(): ' + repr(self.toEpSpinBox.value())) ''' import drama_dailymotion_console #Windows can't set like that bcoz not update for args.url, must put explicitly #drama_dailymotion_console.redirect_stdout_to_custom_stdout(arg_url, ...etc, LoggerWriter()) #failed other process handler = LogHandlerOtherProcess() handler.emitter.sigLog.connect(self.log_area.appendPlainText) ''' #ref current process: logger = logging.getLogger(__name__) handler2 = LoggerWriter() logger.addHandler(handler2) logger.setLevel(logging.DEBUG) handler2.emitter.sigLog.connect(self.log_area.appendPlainText) sys.stdout = handler2 #LoggerWriter() #handler2.emitter.sigLog.emit('hihi') ''' #handler = LoggerWriter() #handler.emitter.sigLog.connect(self.log_area.appendPlainText) self.q = multiprocessing.Queue() self.ql = QueueListener(self.q, handler) self.ql.start() self.pool = multiprocessing.Pool(1, worker_init, [self.q]) if self.radioButtonDailyMotionDrama.isChecked(): self.pool.apply_async(drama_dailymotion_console.main, args=(dest_full_path, self.fromEpSpinBox.value(), self.toEpSpinBox.value(), self.url.text(), LoggerWriterOtherProcess(), False), callback=self.task_done) else: self.pool.apply_async(drama_dailymotion_console.main, args=(dest_full_path, self.fromEpSpinBox.value(), self.toEpSpinBox.value(), self.url.text(), LoggerWriterOtherProcess(), True), callback=self.task_done)
class TestingPanel(Panel): def __init__(self, maps, threads): super().__init__() self.maps = maps self.rbfn = None self.threads = threads self.__set_execution_ui() self.__set_outputs_ui() self.__set_graphic_ui() self.__set_console_ui() def __set_execution_ui(self): group_box = QGroupBox('Testing Execution') inner_layout = QHBoxLayout() group_box.setLayout(inner_layout) self.map_selector = QComboBox() self.map_selector.addItems(list(self.maps.keys())) self.map_selector.setStatusTip('Select the training dataset.') self.map_selector.currentIndexChanged.connect(self.__change_map) self.start_btn = QPushButton('Test') self.start_btn.setStatusTip( 'Start testing. (available after training)') self.start_btn.setDisabled(True) self.start_btn.clicked.connect(self.__run) self.stop_btn = QPushButton('Stop') self.stop_btn.setStatusTip('Force the testing stop running.') self.stop_btn.setDisabled(True) self.fps = QSpinBox() self.fps.setMinimum(1) self.fps.setMaximum(60) self.fps.setValue(20) self.fps.setStatusTip( "The re-drawing rate for car simulator. High fps " "may cause the plot shows discontinuously.") inner_layout.addWidget(self.map_selector, 1) inner_layout.addWidget(QLabel("FPS:")) inner_layout.addWidget(self.fps) inner_layout.addWidget(self.start_btn) inner_layout.addWidget(self.stop_btn) self._layout.addWidget(group_box) def __set_outputs_ui(self): group_box = QGroupBox("Testing Details") inner_layout = QFormLayout() group_box.setLayout(inner_layout) self.car_position = QLabel('--') self.car_angle = QLabel('--') self.wheel_angle = QLabel('--') self.dist_front = QLabel('--') self.dist_left = QLabel('--') self.dist_right = QLabel('--') self.car_position.setAlignment(Qt.AlignCenter) self.car_angle.setAlignment(Qt.AlignCenter) self.wheel_angle.setAlignment(Qt.AlignCenter) self.dist_front.setAlignment(Qt.AlignCenter) self.dist_left.setAlignment(Qt.AlignCenter) self.dist_right.setAlignment(Qt.AlignCenter) inner_layout.addRow('Car Position:', self.car_position) inner_layout.addRow('Car Angle:', self.car_angle) inner_layout.addRow('Wheel Angle:', self.wheel_angle) inner_layout.addRow('Front Distance:', self.dist_front) inner_layout.addRow('Left Distance:', self.dist_left) inner_layout.addRow('Right Distance:', self.dist_right) self._layout.addWidget(group_box) def __set_graphic_ui(self): self.simulator = CarSimulatorPlot() self.simulator.setStatusTip("Show the graphic of the car controled by " "the result of the PSO in mazz.") self.__change_map() self._layout.addWidget(self.simulator) def __set_console_ui(self): self.__console = QTextEdit() self.__console.setReadOnly(True) self.__console.setStatusTip("Show the logs of status changing.") self._layout.addWidget(self.__console) @Slot() def __init_widgets(self): self.start_btn.setDisabled(True) self.stop_btn.setEnabled(True) self.fps.setDisabled(True) self.map_selector.setDisabled(True) @Slot() def __reset_widgets(self): self.start_btn.setEnabled(True) self.stop_btn.setDisabled(True) self.fps.setEnabled(True) self.map_selector.setEnabled(True) @Slot(str) def print_console(self, text): self.__console.append(text) @Slot(list, list, list) def __show_dists(self, pos, intersections, dists): self.simulator.paint_dist(pos, intersections) self.dist_front.setText(str(dists[0])) self.dist_left.setText(str(dists[1])) self.dist_right.setText(str(dists[2])) @Slot() def __show_car_collided(self): self.simulator.paint_car_collided() def __show_path(self, xdata, ydata): self.simulator.paint_path(xdata, ydata) @Slot() def __change_map(self): self.__current_map = self.maps[self.map_selector.currentText()] self.__car = Car(self.__current_map['start_pos'], self.__current_map['start_angle'], 3, self.__current_map['route_edge']) self.simulator.paint_map(self.__current_map) self.__move_car(self.__current_map['start_pos'], self.__current_map['start_angle']) self.__show_dists(self.__current_map['start_pos'], [self.__current_map['start_pos']] * 3, ['--'] * 3) @Slot(list, float, float) def __move_car(self, pos, angle, wheel_angle=0.0): self.simulator.paint_car(pos, angle) self.car_position.setText("({:.7f}, {:.7f})".format(*pos)) self.car_angle.setText(str(angle)) self.wheel_angle.setText(str(wheel_angle)) @Slot(RBFN) def load_rbfn(self, rbfn): self.rbfn = rbfn self.print_console('New RBFN model has been loaded.') self.start_btn.setEnabled(True) @Slot() def __run(self): # reset the map self.__change_map() # create a QThread if self.rbfn is None: raise TypeError('The RBFN model has not yet loaded.') self.__thread = RunCar(self.__car, self.rbfn, (self.__current_map['end_area_lt'], self.__current_map['end_area_rb']), self.fps.value()) self.threads.append(self.__thread) self.stop_btn.clicked.connect(self.__thread.stop) self.__thread.started.connect(self.__init_widgets) self.__thread.finished.connect(self.__reset_widgets) self.__thread.sig_console.connect(self.print_console) self.__thread.sig_car.connect(self.__move_car) self.__thread.sig_car_collided.connect(self.__show_car_collided) self.__thread.sig_dists.connect(self.__show_dists) self.__thread.sig_results.connect(self.__get_results) self.__thread.start() @Slot(list) def __get_results(self, results): """Get the results of last running and draw the path of it.""" self.simulator.paint_path([d['x'] for d in results], [d['y'] for d in results])