class SubFileDialog(QFileDialog): def __init__(self, parent = None, caption = "", directory = "", filter = ""): super().__init__(parent, caption, directory, filter) self.setOption(QFileDialog.DontUseNativeDialog) def _initAllSubFormats(self, formatList): self._formats = {} for f in formatList: self._formats[f.NAME] = f def _addEncodingsBox(self, row, addAuto): mainLayout = self.layout() encodingLabel = QLabel(_("File encoding:"), self) self._encodingBox = QComboBox(self) if addAuto is True: self._encodingBox.addItem(AUTO_ENCODING_STR) self._encodingBox.addItems(ALL_ENCODINGS) self._encodingBox.setToolTip(_("Change file encoding")) self._encodingBox.setEditable(True) mainLayout.addWidget(encodingLabel, row, 0) mainLayout.addWidget(self._encodingBox, row, 1) def _addFormatBox(self, row, formatList): self._initAllSubFormats(formatList) displayedFormats = list(self._formats.keys()) displayedFormats.sort() mainLayout = self.layout() formatLabel = QLabel(_("Subtitle format:"), self) self._formatBox = QComboBox(self) self._formatBox.addItems(displayedFormats) mainLayout.addWidget(formatLabel, row, 0) mainLayout.addWidget(self._formatBox, row, 1) def getEncoding(self): encoding = self._encodingBox.currentText() if encoding == AUTO_ENCODING_STR: encoding = None return encoding def setEncoding(self, encoding): index = self._encodingBox.findText(encoding) self._encodingBox.setCurrentIndex(index) def getSubFormat(self): return self._formats.get(self._formatBox.currentText()) def setSubFormat(self, subFormat): for key, val in self._formats.items(): if val == subFormat: index = self._formatBox.findText(key) self._formatBox.setCurrentIndex(index) return
class General(SettingsPage): NAME = 'General' def __init__(self, **kwargs): super().__init__(**kwargs) self.setLayout(QVBoxLayout()) self.layout().setAlignment(Qt.AlignTop) # Startup layout self.layoutGroup = QGroupBox(self) self.layoutGroup.setTitle('Startup layout') self.layoutGroup.setLayout(QVBoxLayout()) self.layout().addWidget(self.layoutGroup) self.startupDialogCheck = QCheckBox(self.layoutGroup) self.startupDialogCheck.setText('Use startup dialog') self.layoutGroup.layout().addWidget(self.startupDialogCheck) self.layoutCombo = QComboBox(self.layoutGroup) self.layoutCombo.addItems([lay.NAME for lay in layouts.get_layouts()]) self.layoutGroup.layout().addWidget(self.layoutCombo) self.startupDialogCheck.clicked.connect( lambda check: self.layoutCombo.setEnabled(not check)) # Application style self.themeGroup = QGroupBox(self) self.themeGroup.setTitle('Application theme') self.themeGroup.setLayout(QVBoxLayout()) self.layout().addWidget(self.themeGroup) self.themeCombo = QComboBox(self.themeGroup) self.themeCombo.addItems(styles.get_styles()) self.themeGroup.layout().addWidget(self.themeCombo) def get_settings(self): conf = {'Layout': {}, 'Theme': {}} if self.startupDialogCheck.isChecked(): conf['Layout']['default'] = 'NoDefault' else: conf['Layout']['default'] = self.layoutCombo.currentText() conf['Theme']['theme'] = self.themeCombo.currentText() styles.apply_style(self.themeCombo.currentText()) return conf def load_settings(self, settings): if 'default' in settings['Layout']: if settings['Layout']['default'].lower() == 'nodefault': self.startupDialogCheck.setChecked(True) self.layoutCombo.setEnabled(False) else: self.layoutCombo.setCurrentText(settings['Layout']['default']) if 'theme' in settings['Theme']: self.themeCombo.setCurrentText(settings['Theme']['theme'])
class General(SettingsSection): NAME = 'General' def __init__(self, size, parent=None): super().__init__(size, parent) # Startup layout self.layoutGroup = QGroupBox(self) self.layoutGroup.setTitle('Startup layout') self.layoutGroup.setLayout(QVBoxLayout()) self.layoutGroup.setGeometry(0, 0, self.width(), 120) self.startupDialogCheck = QCheckBox(self.layoutGroup) self.startupDialogCheck.setText('Use startup dialog') self.layoutGroup.layout().addWidget(self.startupDialogCheck) self.layoutCombo = QComboBox(self.layoutGroup) self.layoutCombo.addItems([lay.NAME for lay in layouts.get_layouts()]) self.layoutGroup.layout().addWidget(self.layoutCombo) self.startupDialogCheck.clicked.connect( lambda check: self.layoutCombo.setEnabled(not check)) # Application style self.themeGroup = QGroupBox(self) self.themeGroup.setTitle('Application theme') self.themeGroup.setLayout(QVBoxLayout()) self.themeGroup.setGeometry(0, 125, self.width(), 80) self.themeCombo = QComboBox(self.themeGroup) self.themeCombo.addItems(styles.get_styles()) self.themeGroup.layout().addWidget(self.themeCombo) def get_configuration(self): conf = {'Layout': {}, 'Theme': {}} if self.startupDialogCheck.isChecked(): conf['Layout']['default'] = 'NoDefault' else: conf['Layout']['default'] = self.layoutCombo.currentText() conf['Theme']['current'] = self.themeCombo.currentText() styles.apply_style(self.themeCombo.currentText()) return conf def set_configuration(self, conf): if 'default' in conf['Layout']: if conf['Layout']['default'].lower() == 'nodefault': self.startupDialogCheck.setChecked(True) self.layoutCombo.setEnabled(False) else: self.layoutCombo.setCurrentText(conf['Layout']['default']) if 'current' in conf['Theme']: self.themeCombo.setCurrentText(conf['Theme']['current'])
class AreaOperation(QWidget): # - add objects to an area # - remove objects from an area @update_paths def __init__(self, mode, obj, AS=set(), controller=None): super().__init__() title = 'Add to area' if mode == 'add' else 'Remove from area' self.setWindowTitle(title) values = tuple(map(str, AS)) # list of existing AS self.AS_list = QComboBox() self.AS_list.addItems(values) self.AS_list.activated.connect(self.update_value) # list of areas self.area_list = QComboBox() self.update_value() # confirmation button button_area_operation = QPushButton() button_area_operation.setText('OK') button_area_operation.clicked.connect(lambda: self.area_operation(mode, *obj)) # position in the grid layout = QGridLayout() layout.addWidget(self.AS_list, 0, 0, 1, 2) layout.addWidget(self.area_list, 1, 0, 1, 2) layout.addWidget(button_area_operation, 2, 0, 1, 1) layout.addWidget(cancel_button, 2, 1, 1, 1) self.setLayout(layout) def update_value(self, index): self.area_list.clear() selected_AS = self.network.AS_factory(name=self.AS_list.currentText()) self.area_list.addItems(tuple(map(str, selected_AS.areas))) def area_operation(self, mode, *objects): selected_AS = self.network.AS_factory(name=self.AS_list.currentText()) selected_area = self.area_list.currentText() if mode == 'add': selected_AS.management.add_to_area(selected_area, *objects) else: selected_AS.management.remove_from_area(selected_area, *objects) self.close()
class GestionEleve(QWidget): def __init__(self,parent=None): super(GestionEleve,self).__init__(parent) #charge la classe en cour self.initClass() palette = QPalette() palette.setColor(QPalette.Text,QColor(128,128,128)) self.leNom = QLineEdit(self) self.leNom.setText("NOM..") self.leNom.setPalette(palette) self.lePrenom = QLineEdit(self) self.lePrenom.setText("PRENOM..") self.lePrenom.setPalette(palette) self.comboSex = QComboBox(self) self.comboSex.addItem("sexe..") self.comboSex.addItem("M") self.comboSex.addItem("F") self.comboClasse = self.initComboClasse(["CE1","CE2"]) self.buttonSave = QPushButton("Save") self.buttonSave.clicked.connect(self.saveEleve) layout = QHBoxLayout() layout.addStretch() layout.addWidget(self.leNom) layout.addWidget(self.lePrenom) layout.addWidget(self.comboSex) layout.addWidget(self.comboClasse) layout.addWidget(self.buttonSave) layout.addStretch() self.setLayout(layout) def initComboClasse(self,list): res = QComboBox() res.addItem("classe..") for elt in list: res.addItem(elt) return res def saveEleve(self): if (self.leNom.text == "NOM.." or self.lePrenom.text == "PRENOM.." or str(self.comboSex.currentText()) == "sexe.." or str(self.comboClasse.currentText()) == "classe.." ): pass #on enregistre pas else : pass #on enregistre def initClass(self): pass
class CueItemWidget(QWidget): def __init__(self, target, action, cue_dialog, **kwargs): super().__init__(**kwargs) self.target = target self.cue_dialog = cue_dialog self.setLayout(QHBoxLayout(self)) self.layout().setContentsMargins(2, 1, 2, 1) self.selectButton = QPushButton(self) self.selectButton.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Fixed) self.selectButton.setText(target.name) self.selectButton.setToolTip(target.name) self.selectButton.clicked.connect(self.select_target) self.layout().addWidget(self.selectButton) self.targetActionsCombo = QComboBox(self) self.targetActionsCombo.addItems([a.name for a in CueAction]) self.targetActionsCombo.setCurrentText(CueAction[action].name) self.layout().addWidget(self.targetActionsCombo) self.layout().setStretch(0, 3) self.layout().setStretch(1, 1) def get_target(self): return self.target.id, self.targetActionsCombo.currentText() def select_target(self): if self.cue_dialog.exec_() == QDialog.Accepted: self.target = self.cue_dialog.selected_cues()[0] self.selectButton.setText(self.target.name) self.selectButton.setToolTip(self.target.name)
class ModeSelectionToolbar(QToolBar): switch_mode = pyqtSignal(str) def __init__(self, network_handler): super().__init__("Mode selection") self._nh = network_handler mode_text = QLabel() mode_text.setText("Select mode:") self._mode_selection = QComboBox() self._mode_selection.setMinimumWidth(100) self._mode_selection.setMaximumWidth(140) self._mode_selection.addItem("RC") self._mode_selection.addItem("GPS") self.addWidget(mode_text) self.addWidget(self._mode_selection) self.addAction("Select", self._send_mode) @QtCore.pyqtSlot() def _send_mode(self): mode = self._mode_selection.currentText() self.switch_mode.emit(mode) if mode == "RC": command = "START_PROG_RC" elif mode == "GPS": command = "START_PROG_GPS" else: command = "START_PROG_RC" self._nh.send_command(command)
class PropertyChanger(QWidget): @update_paths def __init__(self, objects, type, controller): super().__init__() # list of properties self.property_list = QComboBox() self.property_list.addItems(map(str, object_properties[type])) self.value_edit = QLineEdit() confirmation_button = QPushButton() confirmation_button.setText('OK') confirmation_button.clicked.connect(lambda: self.confirm(objects)) # position in the grid layout = QGridLayout() layout.addWidget(self.property_list, 0, 0) layout.addWidget(self.value_edit, 1, 0) layout.addWidget(confirmation_button, 2, 0) self.setLayout(layout) def confirm(self, objects): selected_property = pretty_name_to_class[self.property_list.currentText()] str_value = self.value_edit.text() value = self.network.objectizer(selected_property.name, str_value) for object in objects: setattr(object, selected_property.name, value) self.close()
class AlsaSinkSettings(SettingsSection): NAME = "ALSA Sink" ELEMENT = AlsaSink def __init__(self, size, Id, parent=None): super().__init__(size, parent) self.id = Id self.devs = self._discover_pcm_devices() self.devs['default'] = 'default' self.group = QGroupBox(self) self.group.setTitle('ALSA device') self.group.setGeometry(0, 0, self.width(), 100) self.group.setLayout(QHBoxLayout()) self.device = QComboBox(self.group) self.device.addItems(self.devs.keys()) self.device.setCurrentText('default') self.device.setToolTip('ALSA device, as defined in an asound ' 'configuration file') self.group.layout().addWidget(self.device) self.label = QLabel('ALSA device', self.group) self.label.setAlignment(QtCore.Qt.AlignCenter) self.group.layout().addWidget(self.label) def sizeHint(self): return QSize(450, 100) def enable_check(self, enable): self.group.setCheckable(enable) self.group.setChecked(False) def set_configuration(self, conf): if self.id in conf: device = conf[self.id].get('device', 'default') for name in self.devs: if device == self.devs[name]: self.device.setCurrentText(name) break def get_configuration(self): if not (self.group.isCheckable() and not self.group.isChecked()): return {self.id: {'device': self.devs[self.device.currentText()]}} else: return {} def _discover_pcm_devices(self): devices = {} with open('/proc/asound/pcm', mode='r') as f: for dev in f.readlines(): dev_name = dev[7:dev.find(':', 7)].strip() dev_code = 'hw:' + dev[:5].replace('-', ',') devices[dev_name] = dev_code return devices
class TriggerWidget(QWidget): def __init__(self, tr_action, target, ta_action, cue_dialog, **kwargs): super().__init__(**kwargs) self.target = target self.cue_dialog = cue_dialog self.target_actions = {a.name: a.value for a in target.CueActions} self.setLayout(QHBoxLayout(self)) self.layout().setContentsMargins(2, 1, 2, 1) self.triggerActions = QComboBox(self) # MediaTriggers members names and values are equals self.triggerActions.addItems([a.value for a in CueTriggers]) self.triggerActions.setCurrentText(tr_action) self.layout().addWidget(self.triggerActions) self.selectButton = QPushButton(self) self.selectButton.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Fixed) self.selectButton.setText(target.name) self.selectButton.setToolTip(target.name) self.selectButton.clicked.connect(self.select_target) self.layout().addWidget(self.selectButton) self.targetActionCombo = QComboBox(self) self.targetActionCombo.addItems(self.target_actions.keys()) self.targetActionCombo.setCurrentText(CueAction(ta_action).name) self.layout().addWidget(self.targetActionCombo) self.layout().setStretch(0, 1) self.layout().setStretch(1, 3) self.layout().setStretch(2, 1) def get_trigger(self): target = self.target.id tr_action = self.triggerActions.currentText() ta_action = self.target_actions[self.targetActionCombo.currentText()] return tr_action, target, ta_action def select_target(self): if self.cue_dialog.exec_() == QDialog.Accepted: self.target = self.cue_dialog.selected_cues()[0] self.selectButton.setText(self.target.name) self.selectButton.setToolTip(self.target.name)
class Subplot(QHBoxLayout): def __init__(self, customize, id, name): QHBoxLayout.__init__(self) self.customize = customize self.checkbox = QCheckBox(name) self.id = id self.checkbox.setCheckState(0) self.checkbox.stateChanged.connect(self.handleChecking) self.comscale = QComboBox() self.comscale.addItems(['linear', 'log']) self.comscale.currentIndexChanged.connect(self.updateScale) self.addWidget(self.checkbox) self.addWidget(self.comscale) @property def customAxes(self): return self.customize.customAxes @property def scale(self): return self.comscale.currentText() @property def graph(self): return self.customize.plotWindow.graph def handleChecking(self): if self.checkbox.isChecked(): self.customAxes.append(self) else: self.customAxes.remove(self) self.customize.plotWindow.createGraph(self.customAxes) self.customize.checkAvailable() def updateScale(self): try: self.graph.updateScale(self.graph.allAxes[self.id], self.comscale.currentText()) except Exception as e: print(e)
class ASOperation(QWidget): # - add objects to an AS # - remove objects from an AS # - enter the AS management window @update_paths def __init__(self, mode, obj, AS=set(), controller=None): super().__init__() title = { 'add': 'Add to AS', 'remove': 'Remove from AS', 'manage': 'Manage AS' }[mode] self.setWindowTitle(title) if mode == 'add': # all AS are proposed values = tuple(map(str, self.network.pnAS)) else: # only the common AS among all selected objects values = tuple(map(str, AS)) # list of existing AS self.AS_list = QComboBox() self.AS_list.addItems(values) # confirmation button button_AS_operation = QPushButton() button_AS_operation.setText('OK') button_AS_operation.clicked.connect(lambda: self.as_operation(mode, *obj)) # cancel button cancel_button = QPushButton() cancel_button.setText('Cancel') # position in the grid layout = QGridLayout() layout.addWidget(self.AS_list, 0, 0, 1, 2) layout.addWidget(button_AS_operation, 1, 0, 1, 1) layout.addWidget(cancel_button, 1, 1, 1, 1) self.setLayout(layout) def as_operation(self, mode, *objects): selected_AS = self.network.AS_factory(name=self.AS_list.currentText()) if mode == 'add': selected_AS.management.add_to_AS(*objects) elif mode == 'remove': selected_AS.management.remove_from_AS(*objects) else: selected_AS.management.show() self.close()
class DisjointSPWindow(QWidget): algorithms = ( 'Constrained A*', 'Bhandari algorithm', 'Suurbale algorithm', 'Linear programming' ) def __init__(self, controller): super().__init__() self.controller = controller self.setWindowTitle('Disjoint shortest paths algorithms') algorithm = QLabel('Algorithm') self.dsp_list = QComboBox() self.dsp_list.addItems(self.algorithms) source = QLabel('Source') self.source_edit = QLineEdit() destination = QLabel('Destination') self.destination_edit = QLineEdit() number_of_paths = QLabel('Number of paths') self.number_of_paths_edit = QLineEdit() # confirmation button button_compute = QPushButton() button_compute.setText('Compute') button_compute.clicked.connect(self.compute_dsp) # position in the grid layout = QGridLayout() layout.addWidget(algorithm, 0, 0, 1, 1) layout.addWidget(self.dsp_list, 0, 1, 1, 1) layout.addWidget(source, 1, 0, 1, 1) layout.addWidget(self.source_edit, 1, 1, 1, 1) layout.addWidget(destination, 2, 0, 1, 1) layout.addWidget(self.destination_edit, 2, 1, 1, 1) layout.addWidget(number_of_paths, 3, 0, 1, 1) layout.addWidget(self.number_of_paths_edit, 3, 1, 1, 1) layout.addWidget(button_compute, 4, 0, 1, 2) self.setLayout(layout) @update_paths def compute_dsp(self, _): source = self.network.nf(name=self.source_edit.text()) destination = self.network.nf(name=self.destination_edit.text()) algorithm = { 'Constrained A*': self.network.A_star_shortest_pair, 'Bhandari algorithm': self.network.bhandari, 'Suurbale algorithm': self.network.suurbale, 'Linear programming': lambda: 'to repair' }[self.dsp_list.currentText()] nodes, physical_links = algorithm(source, destination) self.view.select(*(nodes + physical_links))
class JackSinkSettings(SettingsSection): NAME = "Jack Sink" ELEMENT = JackSink def __init__(self, size, Id, parent=None): super().__init__(size, parent) self.id = Id self.group = QGroupBox(self) self.group.setTitle('Jack') self.group.setGeometry(0, 0, self.width(), 100) self.group.setLayout(QGridLayout()) self.client = QLineEdit(self.group) self.client.setToolTip('The client name of the Jack instance') self.client.setText('Linux Show Player') self.group.layout().addWidget(self.client, 0, 0) self.clientLabel = QLabel('Client name', self.group) self.clientLabel.setAlignment(QtCore.Qt.AlignCenter) self.group.layout().addWidget(self.clientLabel, 0, 1) self.connection = QComboBox(self.group) self.connection.setToolTip('Specify how the output ports will be' 'connected') self.connection.addItems([JackSink.CONNECT_NONE, JackSink.CONNECT_AUTO, JackSink.CONNECT_AUTO_FORCED]) self.connection.setCurrentIndex(1) self.group.layout().addWidget(self.connection, 1, 0) self.connLabel = QLabel('Connection mode', self.group) self.connLabel.setAlignment(QtCore.Qt.AlignCenter) self.group.layout().addWidget(self.connLabel, 1, 1) def sizeHint(self): return QSize(450, 100) def enable_check(self, enable): self.group.setCheckable(enable) self.group.setChecked(False) def set_configuration(self, conf): if self.id in conf: if 'client-name' in conf[self.id]: self.client.setText(conf[self.id]['client-name']) if 'connection' in conf[self.id]: self.connection.setCurrentText(conf[self.id]['connection']) def get_configuration(self): if not (self.group.isCheckable() and not self.group.isChecked()): return {self.id: {'client-name': self.client.text(), 'connection': self.connection.currentText()}} else: return {}
class StartSession(preferences.Group): def __init__(self, page): super(StartSession, self).__init__(page) grid = QGridLayout() self.setLayout(grid) def changed(): self.changed.emit() self.combo.setEnabled(self.custom.isChecked()) self.none = QRadioButton(toggled=changed) self.lastused = QRadioButton(toggled=changed) self.custom = QRadioButton(toggled=changed) self.combo = QComboBox(currentIndexChanged=changed) grid.addWidget(self.none, 0, 0, 1, 2) grid.addWidget(self.lastused, 1, 0, 1, 2) grid.addWidget(self.custom, 2, 0, 1, 1) grid.addWidget(self.combo, 2, 1, 1, 1) app.translateUI(self) def translateUI(self): self.setTitle(_("Session to load if Frescobaldi is started without arguments")) self.none.setText(_("Start with no session")) self.lastused.setText(_("Start with last used session")) self.custom.setText(_("Start with session:")) def loadSettings(self): s = QSettings() s.beginGroup("session") startup = s.value("startup", "none", str) if startup == "lastused": self.lastused.setChecked(True) elif startup == "custom": self.custom.setChecked(True) else: self.none.setChecked(True) sessionNames = sessions.sessionNames() self.combo.clear() self.combo.addItems(sessionNames) custom = s.value("custom", "", str) if custom in sessionNames: self.combo.setCurrentIndex(sessionNames.index(custom)) def saveSettings(self): s = QSettings() s.beginGroup("session") s.setValue("custom", self.combo.currentText()) if self.custom.isChecked(): startup = "custom" elif self.lastused.isChecked(): startup = "lastused" else: startup = "none" s.setValue("startup", startup)
class Example(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): config = configparser.ConfigParser() config.read('launcher.original.ini') Login = config.get('Options', 'Logins') addlogins = Login.split(",") self.lbl = QLabel("Logins", self) self.combo = QComboBox(self) self.combo.addItems(addlogins) self.combo.move(50, 50) self.lbl.move(50, 30) btn = QPushButton('Set', self) btn.setGeometry(230, 50, 42, 32) btn.clicked.connect(self.buttonSet) self.resize(350, 140) self.center() self.setWindowTitle('Message box') self.show() self.setWindowTitle('Launcher') self.show() def buttonSet(self): config = configparser.ConfigParser() config.read('launcher.ini') config.set('Options', 'Autologin', self.combo.currentText()) with open('launcher.ini', 'w') as configfile: config.write(configfile) def center(self): qr = self.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft()) def closeEvent(self, event): reply = QMessageBox.question(self, 'Message', "Are you sure to quit?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: event.accept() else: event.ignore()
class DeleteForm(QDialog): def __init__(self): super(DeleteForm, self).__init__() self.initUI(self) def initUI(self, DeleteForm): layout = QGridLayout(self) self.delete_label = QLabel("Delete by:") self.delete_combo_box = QComboBox() self.delete_combo_box.addItem("ISBN") self.delete_combo_box.addItem("Title") self.delete_line_edit = QLineEdit() self.delete_button = QPushButton("Delete") layout.addWidget(self.delete_label, 0, 0) layout.addWidget(self.delete_combo_box, 0, 1) layout.addWidget(self.delete_line_edit, 0, 2) layout.addWidget(self.delete_button, 0, 3, 1, 2) self.setLayout(layout) self.delete_button.clicked.connect(self.delete_button_click) self.layout().setSizeConstraint(QLayout.SetFixedSize) self.setWindowTitle("Delete Book") self.setWindowIcon(QIcon(QPixmap('../images/delete.png'))) def delete_button_click(self): search = self.delete_combo_box.currentText() text = self.delete_line_edit.text() if search == 'ISBN': if not(Validations.is_valid_isbn(text)): QMessageBox(QMessageBox.Critical, "Error", "Invalid ISBN. Please correct it!").exec_() books = select_by_isbn(text) if books != []: delete_by_isbn(text) QMessageBox(QMessageBox.Information, "Information", "You successfully deleted this book!").exec_() return else: QMessageBox(QMessageBox.Information, "No results", "There is NO such book in the library!").exec_() return elif search == 'Title': books = select_by_title(string.capwords(text)) if books != []: delete_by_title(string.capwords(text)) QMessageBox(QMessageBox.Information, "Information", "You successfully deleted this book!").exec_() return else: QMessageBox(QMessageBox.Information, "No results", "There is NO such book in the library!").exec_() return
class RequestDialog(QDialog): """ The dialog used to add and edit requests. """ def __init__(self, parent=None): super(RequestDialog, self).__init__(parent) self.parent = parent self.set_up_window() self.set_up_request_dialog() def set_up_window(self): self.resize(200, 150) center_x = self.parent.x() + (self.parent.frameGeometry().width() - self.frameGeometry().width()) / 2 center_y = self.parent.y() + (self.parent.frameGeometry().height() - self.frameGeometry().height()) / 2 self.move(center_x, center_y) font = QFont() font.setPointSize(10) self.setFont(font) def set_up_request_dialog(self): keyword_label = QLabel("Keyword ") self.keyword_edit = QLineEdit() subreddit_label = QLabel("Subreddit ") self.subreddit_edit = QLineEdit() listing_label = QLabel("Listing") self.listing_combo_box = QComboBox() self.listing_combo_box.addItems(["Hot", "New", "Rising", "Controversial", "Top"]) info_layout = QFormLayout() info_layout.addRow(keyword_label, self.keyword_edit) info_layout.addRow(subreddit_label, self.subreddit_edit) info_layout.addRow(listing_label, self.listing_combo_box) add_button = QPushButton("Add") add_button.setMaximumWidth(100) add_button.clicked.connect(self.accept) add_button_layout = QHBoxLayout() add_button_layout.addWidget(add_button) dialog_layout = QVBoxLayout() dialog_layout.addLayout(info_layout) dialog_layout.addLayout(add_button_layout) self.setLayout(dialog_layout) def values(self): return self.keyword_edit.text(), self.subreddit_edit.text(), self.listing_combo_box.currentText()
class LilyPondPreferences(QGroupBox): def __init__(self, parent): super(LilyPondPreferences, self).__init__(parent) grid = QGridLayout() self.setLayout(grid) self.pitchLanguageLabel = QLabel() self.pitchLanguage = QComboBox() self.versionLabel = QLabel() self.version = QComboBox(editable=True) self.pitchLanguage.addItem('') self.pitchLanguage.addItems([lang.title() for lang in sorted(scoreproperties.keyNames)]) self.version.addItem(lilypondinfo.preferred().versionString()) for v in ("2.18.0", "2.16.0", "2.14.0", "2.12.0"): if v != lilypondinfo.preferred().versionString(): self.version.addItem(v) grid.addWidget(self.pitchLanguageLabel, 0, 0) grid.addWidget(self.pitchLanguage, 0, 1) grid.addWidget(self.versionLabel, 1, 0) grid.addWidget(self.version, 1, 1) self.pitchLanguage.activated.connect(self.slotPitchLanguageChanged) app.translateUI(self) self.loadSettings() self.window().finished.connect(self.saveSettings) def translateUI(self): self.setTitle(_("LilyPond")) self.pitchLanguageLabel.setText(_("Pitch name language:")) self.pitchLanguage.setToolTip(_( "The LilyPond language you want to use for the pitch names.")) self.pitchLanguage.setItemText(0, _("Default")) self.versionLabel.setText(_("Version:")) self.version.setToolTip(_( "The LilyPond version you will be using for this document.")) def slotPitchLanguageChanged(self, index): if index == 0: language = '' else: language = self.pitchLanguage.currentText().lower() self.window().setPitchLanguage(language) def loadSettings(self): language = self.window().pitchLanguage() languages = list(sorted(scoreproperties.keyNames)) index = languages.index(language) + 1 if language in languages else 0 self.pitchLanguage.setCurrentIndex(index) def saveSettings(self): QSettings().setValue('scorewiz/lilypond/pitch_language', self.window().pitchLanguage())
class MCFlowWindow(QWidget): algorithms = ('Linear programming', 'Klein') def __init__(self, controller): super().__init__() self.controller = controller self.setWindowTitle('Minimum-cost flow algorithms') algorithm = QLabel('Algorithm') self.mcf_list = QComboBox() self.mcf_list.addItems(self.algorithms) source = QLabel('Source') self.source_edit = QLineEdit() destination = QLabel('Destination') self.destination_edit = QLineEdit() flow = QLabel('Flow') self.flow_edit = QLineEdit() # confirmation button button_compute = QPushButton() button_compute.setText('Compute') button_compute.clicked.connect(self.compute_mcflow) # position in the grid layout = QGridLayout() layout.addWidget(algorithm, 0, 0, 1, 1) layout.addWidget(self.mcf_list, 0, 1, 1, 1) layout.addWidget(source, 1, 0, 1, 1) layout.addWidget(self.source_edit, 1, 1, 1, 1) layout.addWidget(destination, 2, 0, 1, 1) layout.addWidget(self.destination_edit, 2, 1, 1, 1) layout.addWidget(flow, 3, 0, 1, 1) layout.addWidget(self.flow_edit, 3, 1, 1, 1) layout.addWidget(button_compute, 4, 0, 1, 2) self.setLayout(layout) @update_paths def compute_mcflow(self, _): source = self.network.nf(name=self.source_edit.text()) destination = self.network.nf(name=self.destination_edit.text()) flow = self.flow_entry.text algorithm = { 'Linear programming': self.network.LP_MCF_formulation, 'Klein': lambda: 'to be implemented' }[self.mcf_list.currentText()] cost = algorithm(source, destination, flow) print(cost)
class MaximumFlowWindow(QWidget): algorithms = ( 'Ford-Fulkerson', 'Edmond-Karps', 'Dinic', 'Linear programming' ) def __init__(self, controller): super().__init__() self.controller = controller self.setWindowTitle('Maximum flow algorithms') algorithm = QLabel('Algorithm') self.mf_list = QComboBox() self.mf_list.addItems(self.algorithms) source = QLabel('Source') self.source_edit = QLineEdit() destination = QLabel('Destination') self.destination_edit = QLineEdit() # confirmation button button_compute = QPushButton() button_compute.setText('Compute') button_compute.clicked.connect(self.compute_flow) # position in the grid layout = QGridLayout() layout.addWidget(algorithm, 0, 0, 1, 1) layout.addWidget(self.mf_list, 0, 1, 1, 1) layout.addWidget(source, 1, 0, 1, 1) layout.addWidget(self.source_edit, 1, 1, 1, 1) layout.addWidget(destination, 2, 0, 1, 1) layout.addWidget(self.destination_edit, 2, 1, 1, 1) layout.addWidget(button_compute, 3, 0, 1, 2) self.setLayout(layout) @update_paths def compute_flow(self, _): source = self.network.nf(name=self.source_edit.text()) destination = self.network.nf(name=self.destination_edit.text()) algorithm = { 'Ford-Fulkerson': self.network.ford_fulkerson, 'Edmond-Karps': self.network.edmonds_karp, 'Dinic': self.network.dinic, 'Linear programming': self.network.LP_MF_formulation }[self.mf_list.currentText()] maximum_flow = algorithm(source, destination) print(maximum_flow)
class ShortestPathWindow(QWidget): algorithms = ( 'Constrained A*', 'Bellman-Ford algorithm', 'Floyd-Warshall algorithm', 'Linear programming' ) def __init__(self, controller): super().__init__() self.controller = controller self.setWindowTitle('Shortest path algorithms') algorithm = QLabel('Algorithm') self.sp_list = QComboBox() self.sp_list.addItems(self.algorithms) source = QLabel('Source') self.source_edit = QLineEdit() destination = QLabel('Destination') self.destination_edit = QLineEdit() # confirmation button button_compute = QPushButton() button_compute.setText('Compute') button_compute.clicked.connect(self.compute_sp) # position in the grid layout = QGridLayout() layout.addWidget(algorithm, 0, 0, 1, 1) layout.addWidget(self.sp_list, 0, 1, 1, 1) layout.addWidget(source, 1, 0, 1, 1) layout.addWidget(self.source_edit, 1, 1, 1, 1) layout.addWidget(destination, 2, 0, 1, 1) layout.addWidget(self.destination_edit, 2, 1, 1, 1) layout.addWidget(button_compute, 3, 0, 1, 2) self.setLayout(layout) @update_paths def compute_sp(self, _): source = self.network.nf(name=self.source_edit.text()) destination = self.network.nf(name=self.destination_edit.text()) algorithm = { 'Constrained A*': self.network.A_star, 'Bellman-Ford algorithm': self.network.bellman_ford, 'Floyd-Warshall algorithm': self.network.floyd_warshall, 'Linear programming': self.network.LP_SP_formulation }[self.sp_list.currentText()] nodes, physical_links = algorithm(source, destination) self.view.select(*(nodes + physical_links))
def update_annotation(self, child: QTreeWidgetItem, cbox: QComboBox): """ On getting a change signal from the parameter option combobox, set options on the volume.annotations object Also set the selected row to active Parameters ---------- child: is the node in the QTreeWidget that corresponds to our paramter option selection cbox: Qt combobox that was clicked row: The row of the qtreewidget where the combobox is """ vol = self.controller.current_annotation_volume() if not vol: error_dialog(self, "Error", "No volume selected") return try: x = int(self.ui.labelXPos.text()) y = int(self.ui.labelYPos.text()) z = int(self.ui.labelZPos.text()) except ValueError: x = y = z = None base_node = child term = base_node.text(1) option = cbox.currentText() # If we are updating the annotation to ImageOnly, we should wipe any coordinates that may have been added to # a previous annotation option. if option == 'imageOnly': x = y = z = None elif option in (centre_stage_options.opts['options_requiring_points']): if None in (x, y, z): info_dialog(self, 'Select a region!', "For option '{}' coordinates must be specified".format(option)) # this will reset the option back to what it is on the volume.annotation object cbox.setCurrentIndex(cbox.findText(vol.annotations.get_by_term(term).selected_option)) return if not term: error_dialog(self, "Error", "No term is selected!") return vol.annotations.update_annotation(term, x, y, z, option) self.on_tree_clicked(base_node) # We are now autosaving. so save on each annotation term changed self.save_annotations(suppress_msg=True)
class ComboBoxDelegate(QStyledItemDelegate): typeSelected = pyqtSignal(str) def __init__(self, parent=None): super().__init__(parent) def createEditor(self, parent, option=None, index=None): self.comboBox = QComboBox(parent) self.comboBox.currentIndexChanged.connect(self.currentIndexChanged) return self.comboBox def setEditorData(self, editor, index): self.comboBox = editor editor.blockSignals(True) cboIndex = -1 if not index.model().data(index) is None: for i in range(editor.count()): if editor.itemText(i) == index.model().data(index): cboIndex = i break editor.setCurrentIndex(cboIndex) editor.blockSignals(False) def setModelData(self, editor, model, index): self.comboBox = editor model.setData(index, self.comboBox.currentText()) #, QtGui.Qt.EditRole) def updateEditorGeometry(self, editor, option, index): editor.setGeometry(option.rect) def currentIndexChanged(self): self.commitData.emit(self.sender()) self.typeSelected.emit(self.comboBox.currentText())
class tb_lasers(QWidget): def update(self): self.sim_mode.clear() lines=[] files=inp_lsdir() if files!=False: for i in range(0,len(files)): if files[i].endswith(".inp"): inp_load_file(lines,files[i]) value=inp_search_token_value(lines, "#laser_name") if value!=False: value=value.rstrip() self.sim_mode.addItem(value) token=inp_get_token_value(self.config_file, "#pump_laser") all_items = [self.sim_mode.itemText(i) for i in range(self.sim_mode.count())] for i in range(0,len(all_items)): if all_items[i] == token: self.sim_mode.setCurrentIndex(i) found=True def __init__(self,config_file): self.config_file=config_file QWidget.__init__(self) layout=QHBoxLayout() label=QLabel() label.setText(_("Laser:")) layout.addWidget(label) self.sim_mode = QComboBox(self) self.sim_mode.setEditable(True) self.update() self.sim_mode.currentIndexChanged.connect(self.call_back_sim_mode_changed) layout.addWidget(self.sim_mode) self.setLayout(layout) return def call_back_sim_mode_changed(self): mode=self.sim_mode.currentText() inp_update_token_value(self.config_file, "#pump_laser", mode,1)
class TZprompt(QDialog): def __init__(self, parent=None): super(TZprompt, self).__init__(parent) #self.idDates = QCheckBox("Import ID and created/modified dates") promptLabel = QLabel("Time Zone in which the Tellico data was entered:") self.zoneName = QComboBox(self) current = -1 self.suppliedTZ = 'America/Chicago' for i, zone in enumerate (pytz.common_timezones): self.zoneName.addItem(zone, i) if self.suppliedTZ == zone: current = i self.zoneName.setCurrentIndex(current) self.submitButton = QPushButton("Submit") self.submitButton.isDefault() buttonLayout1 = QVBoxLayout() #buttonLayout1.addWidget(self.idDates) buttonLayout1.addWidget(promptLabel) buttonLayout1.addWidget(self.zoneName) buttonLayout1.addWidget(self.submitButton) self.submitButton.clicked.connect(self.TZsubmitted) mainLayout = QGridLayout() mainLayout.addLayout(buttonLayout1, 0, 1) self.setLayout(mainLayout) self.setWindowTitle("Time Zone") def TZsubmitted(self): self.suppliedTZ = self.zoneName.currentText() QDialog.accept(self) @staticmethod def getTZ(parent = None): TZdialog = TZprompt(parent) result = TZdialog.exec_() if result == QDialog.Accepted: return TZdialog.suppliedTZ return 'UTC'
def loadUser(self,elem:QComboBox): user = elem.currentText() userdata = user.split() if len(userdata) > 2: last = userdata[-1] userdata = [" ".join(userdata[:-1]), last] user = QueryTool().queryByNames(userdata[0], userdata[1]) print(user) self.sportlerID.setText("{}".format(user[0])) self.sportlerName.setEditText(user[1]) self.sportlerVName.setEditText(user[2]) self.sportlerAlter.setCurrentIndex(user[3]-2) self.sportlerGeschlecht.setCurrentIndex(int(bool(user[4]))+1) self.sportlerAusDatenbank = True
class tb_pulse_load_type(QWidget): changed = pyqtSignal() def __init__(self,index): self.index=index QWidget.__init__(self) layout=QHBoxLayout() label=QLabel() label.setText(_("Load type:")) layout.addWidget(label) self.sim_mode = QComboBox(self) self.sim_mode.setEditable(True) layout.addWidget(self.sim_mode) self.setLayout(layout) self.sim_mode.addItem("open_circuit") self.sim_mode.addItem("load") self.sim_mode.addItem("ideal_diode_ideal_load") lines=[] inp_load_file(lines,os.path.join(get_inp_file_path(),"pulse"+str(self.index)+".inp")) token=inp_get_token_value("pulse"+str(self.index)+".inp", "#pulse_sim_mode") all_items = [self.sim_mode.itemText(i) for i in range(self.sim_mode.count())] for i in range(0,len(all_items)): if all_items[i] == token: self.sim_mode.setCurrentIndex(i) self.sim_mode.currentIndexChanged.connect(self.call_back_sim_mode_changed) def call_back_sim_mode_changed(self): mode=self.sim_mode.currentText() inp_update_token_value("pulse"+str(self.index)+".inp", "#pulse_sim_mode", mode,1) self.changed.emit()
def createDateTimeEdits(self): self.editsGroup = QGroupBox("Date and time spin boxes") dateLabel = QLabel() dateEdit = QDateEdit(QDate.currentDate()) dateEdit.setDateRange(QDate(2005, 1, 1), QDate(2010, 12, 31)) dateLabel.setText("Appointment date (between %s and %s):" % (dateEdit.minimumDate().toString(Qt.ISODate), dateEdit.maximumDate().toString(Qt.ISODate))) timeLabel = QLabel() timeEdit = QTimeEdit(QTime.currentTime()) timeEdit.setTimeRange(QTime(9, 0, 0, 0), QTime(16, 30, 0, 0)) timeLabel.setText("Appointment time (between %s and %s):" % (timeEdit.minimumTime().toString(Qt.ISODate), timeEdit.maximumTime().toString(Qt.ISODate))) self.meetingLabel = QLabel() self.meetingEdit = QDateTimeEdit(QDateTime.currentDateTime()) formatLabel = QLabel("Format string for the meeting date and time:") formatComboBox = QComboBox() formatComboBox.addItem('yyyy-MM-dd hh:mm:ss (zzz \'ms\')') formatComboBox.addItem('hh:mm:ss MM/dd/yyyy') formatComboBox.addItem('hh:mm:ss dd/MM/yyyy') formatComboBox.addItem('hh:mm:ss') formatComboBox.addItem('hh:mm ap') formatComboBox.activated[str].connect(self.setFormatString) self.setFormatString(formatComboBox.currentText()) editsLayout = QVBoxLayout() editsLayout.addWidget(dateLabel) editsLayout.addWidget(dateEdit) editsLayout.addWidget(timeLabel) editsLayout.addWidget(timeEdit) editsLayout.addWidget(self.meetingLabel) editsLayout.addWidget(self.meetingEdit) editsLayout.addWidget(formatLabel) editsLayout.addWidget(formatComboBox) self.editsGroup.setLayout(editsLayout)
def CreateInputGroup(self): #QCombobox used to pick the csv file to be read #initialises the signal and slot mechanism used to change data.values csvComboBox = QComboBox() csvComboBox.insertPolicy = csvComboBox.InsertAlphabetically csvComboBox.addItems(DiscoverCSV()) csvComboBox.currentIndexChanged[str].connect( lambda v: self.UpdateDateRange(self.GetDateRangeCSV(v), startBox, endBox)) csvComboBox.currentIndexChanged[str].connect( ApplicationData.csvFile.fset.__get__(data)) data.csvFile = csvComboBox.currentText() #QDateEdit used to interact and change the starting and ending dates startBox = QDateEdit() startBox.dateChanged.connect( ApplicationData.startDate.fset.__get__(data)) data.startDate = startBox.date() startLabel = QLabel("&Start") startLabel.setBuddy(startBox) endBox = QDateEdit() endBox.dateChanged.connect(ApplicationData.endDate.fset.__get__(data)) data.endDate = endBox.date() endLabel = QLabel("&End") endLabel.setBuddy(endBox) #initialises the begging and ending dates self.UpdateDateRange(self.GetDateRangeCSV(data.csvFile), startBox, endBox) #QLineEdit used to interact and change the money used to trade amountBox = QLineEdit() amountBox.textEdited.connect(ApplicationData.amount.fset.__get__(data)) amountLabel = QLabel("&Amount") amountLabel.setBuddy(amountBox) runButton = QPushButton("&Run") runButton.clicked.connect(self.graph.getPlotItem().clear) runButton.clicked.connect( lambda: ApplicationData.plotData.fset.__get__(data)({})) runButton.clicked.connect(lambda: self.StandardGraph(self, data)) runButton.clicked.connect(lambda: self.SMAGraph(self, data)) runButton.clicked.connect(lambda: self.buySellScatter(data)) #the QGridLayout used to manager the positioning of above widgets layout = QGridLayout() layout.addWidget(csvComboBox, 0, 0, 1, 4) layout.addWidget(startLabel, 1, 0) layout.addWidget(startBox, 1, 1) layout.addWidget(endLabel, 1, 2) layout.addWidget(endBox, 1, 3) layout.addWidget(amountLabel, 2, 0) layout.addWidget(amountBox, 2, 1) layout.addWidget(runButton, 2, 3) return layout
class ColorPaletteDock(QDockWidget): """Dock containing the color palette and preview area :param source: Subject source for the dock and its contents, either sprite or tile :type source: Source :param parent: Parent widget, defaults to None :type parent: QWidget, optional """ palette_updated = pyqtSignal(str) def __init__(self, source, parent=None): super().__init__("Color Palettes", parent) self.source = source self.setFloating(False) self.setFeatures( QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable ) self.docked_widget = QWidget(self) self.setWidget(self.docked_widget) self.docked_widget.setLayout(QVBoxLayout()) self.docked_widget.setSizePolicy( QSizePolicy.Maximum, QSizePolicy.Maximum ) self.color_palette = ColorPalette(self.source, self) self.color_palette_list = QComboBox() self.color_palette_list.setSizePolicy( QSizePolicy.Minimum, QSizePolicy.Maximum ) self.palette_picker = QHBoxLayout() self.palette_label = QLabel("Palette:") self.palette_label.setSizePolicy( QSizePolicy.Maximum, QSizePolicy.Maximum ) self.palette_picker.addWidget(self.palette_label) self.palette_picker.addWidget(self.color_palette_list) self.add_palette = QToolButton(self) self.add_palette.mousePressEvent = self.addPaletteReq self.add_palette.setToolTip("Add new palette") add_icon = QIcon() add_icon.addPixmap(QPixmap(":/icons/add.png")) self.add_palette.setIcon(add_icon) self.add_palette.setEnabled(False) self.remove_palette = QToolButton(self) self.remove_palette.mousePressEvent = self.removePaletteReq self.remove_palette.setToolTip("Remove current palette") remove_icon = QIcon() remove_icon.addPixmap(QPixmap(":/icons/remove.png")) self.remove_palette.setIcon(remove_icon) self.remove_palette.setEnabled(False) self.rename_palette = QToolButton(self) self.rename_palette.mousePressEvent = self.renamePaletteReq self.rename_palette.setToolTip("Rename current palette") rename_icon = QIcon() rename_icon.addPixmap(QPixmap(":/icons/rename.png")) self.rename_palette.setIcon(rename_icon) self.rename_palette.setEnabled(False) self.palette_picker.addWidget(self.add_palette) self.palette_picker.addWidget(self.remove_palette) self.palette_picker.addWidget(self.rename_palette) self.docked_widget.layout().addLayout(self.palette_picker) self.docked_widget.layout().addWidget(self.color_palette) self.color_palette_list.setEnabled(False) self.color_palette.setEnabled(False) self.color_palette.palette_updated.connect(self.verifyCurrentPalette) def setup(self, data): """Sets up the data source for the dock's contents and enables UI elements :param data: Data source of dock :type data: GameData """ self.data = data self.data.col_pal_renamed.connect(self.renamePalette) self.data.col_pal_added.connect(self.addPalette) self.data.col_pal_removed.connect(self.removePalette) self.color_palette.setup(self.data) self.color_palette_list.currentIndexChanged.connect( self.setColorPalette ) self.color_palette_list.setEnabled(True) self.color_palette.setEnabled(True) self.add_palette.setEnabled(True) self.remove_palette.setEnabled(True) self.rename_palette.setEnabled(True) for name in self.data.getColPalNames(self.source): self.color_palette_list.addItem(name) def addPaletteReq(self, event=None): """Sends command to GameData source to add a color palette :param event: Mouse click event which triggered the request, defaults to None :type event: QMouseEvent, optional """ name, accepted = QInputDialog.getText( self, "Add", "Palette name:", QLineEdit.Normal, "New palette" ) if accepted: self.data.addColPal(name, self.source) def removePaletteReq(self, event=None): """Sends command to GameData source to remove a color palette :param event: Mouse click event which triggered the request, defaults to None :type event: QMouseEvent, optional """ if self.color_palette_list.count() == 1: QMessageBox( QMessageBox.Critical, "Error", "There must be at least one sprite and tile color palette in \ the project", ).exec() else: name = self.color_palette_list.currentText() self.data.remColPal(name, self.source) def renamePaletteReq(self, event=None): """Sends command to GameData source to rename a color palette :param event: Mouse click event which triggered the request, defaults to None :type event: QMouseEvent, optional """ cur_name = self.color_palette_list.currentText() new_name, accepted = QInputDialog.getText( self, "Rename", "Palette name:", QLineEdit.Normal, cur_name ) if accepted: self.data.setColPalName(cur_name, new_name, self.source) @pyqtSlot(Source, str, int) def addPalette(self, source, name, index): """Adds a new color palette :param source: Subject source of the addition, either sprite or tile :type source: Source :param name: Name of the added color palette :type name: str :param index: Index in color palette list to insert the new palette :type index: int """ if source is not self.source: return if name is not None: self.color_palette_list.insertItem(index, name) self.color_palette_list.setCurrentIndex(index) self.color_palette.current_palette = name else: QMessageBox( QMessageBox.Critical, "Error", "Palette with that name already exists", ).exec() self.addPaletteReq() @pyqtSlot(Source, str) def removePalette(self, source, name): """Removes a color palette :param source: Subject source of the removal, either sprite or tile :type source: Source :param name: Name of the removed color palette :type name: str """ if source is not self.source: return if name is not None: index = self.color_palette_list.findText(name) self.color_palette_list.removeItem(index) name = self.color_palette_list.currentText() self.color_palette.current_palette = name else: QMessageBox( QMessageBox.Critical, "Error", "Unable to remove palette {}".format(name), ).exec() @pyqtSlot(Source, str, str) def renamePalette(self, source, cur_name, new_name): """Renames a color palette :param source: Subject source of the removal, either sprite or tile :type source: Source :param cur_name: Current name of the target color palette :type cur_name: str :param new_name: New name of the target color palette :type new_name: str """ if source is not self.source: return if cur_name != new_name: self.color_palette_list.setItemText( self.color_palette_list.findText(cur_name), new_name ) self.color_palette_list.setCurrentIndex( self.color_palette_list.findText(new_name) ) self.color_palette.current_palette = new_name else: QMessageBox( QMessageBox.Critical, "Error", "Palette with that name already exists", ).exec() self.renamePaletteReq() @pyqtSlot(str) def verifyCurrentPalette(self, name): """Ensures that the current color palette in the selection list is accurate :param name: Name of the selected color palette :type name: str """ self.color_palette_list.setCurrentIndex( self.color_palette_list.findText(name) ) self.palette_updated.emit(name) def setColorPalette(self): """Sets the active color palette to the one chosen in the selection list """ self.color_palette.setPalette( self.source, self.color_palette_list.currentText() ) def closeEvent(self, event): """Intercepts the dock close event to prevent its closure :param event: Source event :type event: QEvent """ event.ignore()
class Ui_Class(QWidget): click_btn_sig = pyqtSignal(bool) def __init__(self): super().__init__() self.dg_clicked_flg = True #这个标识是:勾选手动输城市时,第一次点弹出下拉框,第二次点确认信息; self.usr_define_city = False self.usr_def_flag_ret = False self.cid_list = [] self.city_name_list = [] self.city = QLabel("当前城市", self) self.time = QLabel("当前时间", self) self.weath = QLabel("当前天气", self) self.weath_1 = QLabel("明天天气", self) self.weath_2 = QLabel("后天天气", self) self.city_line = QLineEdit(self) self.time_line = QLineEdit(self) self.weat_line = QLineEdit(self) self.weat_line_1 = QLineEdit(self) self.weat_line_2 = QLineEdit(self) self.manu_check = QCheckBox("手动输入城市名称", self) self.usr_city_line = QLineEdit(self) self.usr_confirm_btn = QPushButton("确定", self) #系统托盘实例 self.trayIcon = QSystemTrayIcon(self) self.trayIcon.setIcon(QIcon('weather.ico')) self.trayIcon.activated.connect(self.ico_clicked) #托盘添加右键退出菜单 self.quit_action = QAction("退出", self, triggered=self.tray_quit) self.traymenu = QMenu(self) self.traymenu.addAction(self.quit_action) self.trayIcon.setContextMenu(self.traymenu) self.tray_msg_flag = True self.init_ui() #重写关闭事件 def closeEvent(self, e): sel = QMessageBox.question(self, "后台提示", "是否需要最小化到系统托盘", QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) if sel == QMessageBox.Yes: e.ignore() #忽略关闭事件 self.trayIcon.setVisible(True) self.hide() else: self.trayIcon.setVisible(False) e.accept() #响应关闭事件 def tray_quit(self): self.trayIcon.setVisible(False) qApp.quit() #托盘上的图标被左键单击或者双击时的响应函数 def ico_clicked(self, reason): if (reason == QSystemTrayIcon.Trigger or reason == QSystemTrayIcon.DoubleClick): if self.isVisible(): self.hide() else: self.show() def init_ui(self): ui_font = QFont("宋体", 12) self.setFont(ui_font) self.resize(480, 320) self.setWindowTitle("简易天气") #将窗体部署到屏幕中间 screen_size = QDesktopWidget().screenGeometry() app_ui_size = self.geometry() self.move((screen_size.width() - app_ui_size.width()) / 2, (screen_size.height() - app_ui_size.height()) / 2) #设置lineedit不可编辑 self.city_line.setDisabled(True) self.time_line.setDisabled(True) self.weat_line.setDisabled(True) self.weat_line_1.setDisabled(True) self.weat_line_2.setDisabled(True) self.usr_city_line.setDisabled(True) self.usr_confirm_btn.setDisabled(False) #控件布局 grid = QGridLayout() grid.setSpacing(2) grid.addWidget(self.manu_check, 0, 0) grid.addWidget(self.usr_city_line, 0, 1) grid.addWidget(self.usr_confirm_btn, 0, 2) grid.addWidget(self.city, 1, 0) grid.addWidget(self.city_line, 1, 1, 1, 2) grid.addWidget(self.time, 2, 0) grid.addWidget(self.time_line, 2, 1, 1, 2) grid.addWidget(self.weath, 3, 0) grid.addWidget(self.weat_line, 3, 1, 1, 2) grid.addWidget(self.weath_1, 4, 0) grid.addWidget(self.weat_line_1, 4, 1, 1, 2) grid.addWidget(self.weath_2, 5, 0) grid.addWidget(self.weat_line_2, 5, 1, 1, 2) #设置信号响应 self.manu_check.toggled.connect(self.check_box_toggle) self.usr_confirm_btn.clicked.connect(self.confirm_btn_click) self.setLayout(grid) self.show() #更新 当前天气 信息 def update_now_weather(self, str_info): self.weat_line.setText(str_info) #更新当前时间信息 def update_time(self, str_info): self.time_line.setText(str_info) #更新 明天天气 信息 def update_1_weather(self, str_info): self.weat_line_1.setText(str_info) #更新 后天天气 信息 def update_2_weather(self, str_info): self.weat_line_2.setText(str_info) #设置 当前天气 字体颜色 def set_now_weathercolor(self, str_color): self.weat_line.setStyleSheet("color:" + str_color) #更新当前城市信息 def update_location(self, str_info): self.city_line.setText(str_info) #设置 label 内容,index为1表示明日天气, 为2表示后天天气 def set_label(self, index, str): if index == 1: self.weath_1.setText(str) elif index == 2: self.weath_2.setText(str) else: pass #设置 明天或后天 天气字体颜色 def set_otr_weathercolor(self, index, str_color): if index == 1: self.weat_line_1.setStyleSheet("color:" + str_color) else: self.weat_line_2.setStyleSheet("color:" + str_color) #手动输入城市名称checkbox响应 def check_box_toggle(self, check_stat): if check_stat == True: #checkBox被勾选 self.usr_city_line.setDisabled(False) self.usr_confirm_btn.setDisabled(False) self.usr_define_city = True else: self.usr_city_line.setDisabled(True) self.usr_confirm_btn.setDisabled(True) self.usr_define_city = False #确定按钮响应函数 def confirm_btn_click(self): #自动模式下点击 确定 按钮 if self.usr_define_city == False: self.usr_def_flag_ret = False self.usr_confirm_btn.setDisabled(True) self.manu_check.setDisabled(True) self.click_btn_sig.emit(False) #手动模式下点击 确定 按钮 else: self.usr_def_flag_ret = True if self.dg_clicked_flg == True: #当前是第一次点击 确定 按钮 self.city_name_list.clear() #清空list,否则会在输入内容变化时,无法及时更新城市信息 usr_def_city_str = self.usr_city_line.text() if len(usr_def_city_str) > 0: url_str = SEARCH_CITY_URL + usr_def_city_str + USR_KEY + SEARCH_GROUP rs_we = requests.get(url_str).json() get_status = rs_we["HeWeather6"][0]["status"] if get_status == "ok": city_num = len(rs_we["HeWeather6"][0]["basic"]) city_str_index = 0 while (city_str_index < city_num): self.city_name_list.append( rs_we["HeWeather6"][0]["basic"][city_str_index] ["admin_area"] + "-" + rs_we["HeWeather6"][0] ["basic"][city_str_index]["parent_city"] + "-" + rs_we["HeWeather6"][0]["basic"] [city_str_index]["location"]) self.cid_list.append( rs_we["HeWeather6"][0]["basic"][city_str_index] ["cid"]) city_str_index = city_str_index + 1 self.showDialog(self.city_name_list) else: QMessageBox.warning(self, "错误", "无法获取城市信息!") else: QMessageBox.warning(self, "错误", "用户未输入!") else: #第二次点击 self.usr_city_line.setDisabled(True) self.usr_confirm_btn.setDisabled(True) self.manu_check.setDisabled(True) self.click_btn_sig.emit(True) #托盘弹出气泡提示框,弹出频率由刷新天气频率确定 def tray_msg_show(self, str_info): if len(str_info) > 5: #确保是有效数据 if self.tray_msg_flag == True: self.trayIcon.showMessage("简易天气提示", str_info, QSystemTrayIcon.Information, 2000) #self.tray_msg_flag = False #保留功能 else: pass else: pass def showDialog(self, city_list): vbox = QVBoxLayout() #纵向布局 hbox = QHBoxLayout() #横向布局 self.dialog = QDialog(self) self.dialog.resize(100, 60) self.okBtn = QPushButton("确定") self.cancelBtn = QPushButton("取消") self.okBtn.clicked.connect(self.click_diag_ok_btn) self.cancelBtn.clicked.connect(self.click_diag_cancel_btn) self.city_cmb = QComboBox(self) for ct in city_list: self.city_cmb.addItem(ct) self.dialog.setWindowTitle("城市选择") # 确定与取消按钮横向布局 hbox.addWidget(self.okBtn) hbox.addWidget(self.cancelBtn) vbox.addWidget(self.city_cmb) vbox.addLayout(hbox) self.dialog.setLayout(vbox) self.dialog.setWindowModality( Qt.ApplicationModal) #该模式下,只有该dialog关闭,才可以关闭父界面 self.dialog.exec_() # 弹出的对话框里的确认按钮 def click_diag_ok_btn(self): select_txt = self.city_cmb.currentText() self.usr_city_line.setText(select_txt) self.dialog.close() self.dg_clicked_flg = False # 弹出的对话框里的取消按钮 def click_diag_cancel_btn(self): self.dialog.close() #根据城市名称获取城市id def get_cid(self): ret = 0 index = 0 usr_cit = self.usr_city_line.text() for i in self.city_name_list: if usr_cit == i: ret = index break else: index = index + 1 return self.cid_list[ret] def get_usr_define_flg(self): return self.usr_define_city #返回False表示使用自动获取,返回True表示用户自定义 def get_flag(self): return self.usr_def_flag_ret
class DocView(QMainWindow): #resized = QtCore.pyqtSignal() def __init__(self): super(DocView, self).__init__() # self.step = 0 self.combos = { } # project member and other project-related people selection # self.lastpath = 'c:\\' self.filename = None self.isfinished = True self.isselected = False # self.filepath_in = None self.filepath_extract = None self.filepath_out = None # self.sections = None self.project_type = '水利' # self.address_dic = {} self.selected = 0 # self.setting_info = {} # self.initUI() #################################################################### ############################UI##################################### #################################################################### def createAct(self): ########################### # create act ########################### self.openAct = QAction(QIcon('icons\\open.png'), '打开', self) self.openAct.setShortcut('Ctrl+O') self.openAct.setStatusTip('Open Document') self.openAct.triggered.connect(self.act_open) ## exit self.exitAct = QAction(QIcon('icons\\close_.png'), '终了', self) self.exitAct.setShortcut('Ctrl+Q') self.exitAct.setStatusTip('Exit application') self.exitAct.triggered.connect(self.close) ## exit self.saveAct = QAction(QIcon('icons\\save.png'), '保存', self) self.saveAct.setShortcut('Ctrl+S') self.saveAct.setStatusTip('Save Document') self.saveAct.triggered.connect(self.act_save) ## select self.selectAct = QAction(QIcon('icons\\select.png'), '选择', self) self.selectAct.setShortcut('Ctrl+E') self.selectAct.setStatusTip('Select Project Member') self.selectAct.triggered.connect(self.act_select) ## delete self.deleteAct = QAction(QIcon('icons\\delete.png'), '选择', self) self.deleteAct.setShortcut('Ctrl+D') self.deleteAct.setStatusTip('Delete Document') self.deleteAct.triggered.connect(self.act_delete) ## extract self.extractAct = QAction(QIcon('icons\\extract.png'), '提取', self) self.extractAct.setShortcut(QKeySequence('Ctrl+Shit+E')) self.extractAct.setStatusTip('Extract Format Pages') self.extractAct.triggered.connect(self.act_extract) ## split self.splitAct = QAction(QIcon('icons\\split.png'), '分离', self) self.splitAct.setShortcut('Ctrl+Shit+S') self.splitAct.setStatusTip('Split Document') self.splitAct.triggered.connect(self.act_split) ## fill self.fillAct = QAction(QIcon('icons\\fillin.png'), '填写', self) self.fillAct.setShortcut('Ctrl+Shit+F') self.fillAct.setStatusTip('Fill in Blank') self.fillAct.triggered.connect(self.act_fillin) ## auto self.autoAct = QAction(QIcon('icons\\auto.png'), '完全自动', self) self.autoAct.setShortcut('Ctrl+Shit+A') self.autoAct.setStatusTip('Do Automatically') self.autoAct.triggered.connect(self.act_auto) ## merge self.mergeAct = QAction(QIcon('icons\\merge.png'), '合并', self) self.mergeAct.setShortcut('Ctrl+Shit+M') self.mergeAct.setStatusTip('Merge Documents') self.mergeAct.triggered.connect(self.act_merge) ## check self.todocxAct = QAction(QIcon('icons\\doc.png'), '检查', self) self.todocxAct.setShortcut('Ctrl+Shit+') self.todocxAct.setStatusTip('Check Document') self.todocxAct.triggered.connect(self.act_2docx) ## 2xml self.toxmlAct = QAction(QIcon('icons\\xml.png'), '变换到XML', self) self.toxmlAct.setShortcut('Ctrl+Shit+X') self.toxmlAct.setStatusTip('Convert Docx to Xml') self.toxmlAct.triggered.connect(self.act_2xml) ## 2html self.tohtmlAct = QAction(QIcon('icons\\html.png'), '变换到HTML', self) self.tohtmlAct.setShortcut('Ctrl+Shit+H') self.tohtmlAct.setStatusTip('Convert docx to HTML') self.tohtmlAct.triggered.connect(self.act_2html) ## setting self.settingAct = QAction(QIcon('icons\\setting_.png'), '设置', self) self.settingAct.setShortcut('Ctrl+Shit+T') self.settingAct.setStatusTip('Setting') self.settingAct.triggered.connect(self.act_setting) ## help self.aboutAct = QAction(QIcon('icons\\help.png'), '关于', self) self.aboutAct.setShortcut('Ctrl+H') self.aboutAct.setStatusTip('About Program') self.aboutAct.triggered.connect(self.act_about) def createMenu(self): ########################### # create menu ########################### self.menubar = self.menuBar() ## File fileMenu = self.menubar.addMenu('&文件') fileMenu.addAction(self.openAct) fileMenu.addAction(self.saveAct) fileMenu.addAction(self.exitAct) ## Edit editMenu = self.menubar.addMenu('&编辑') editMenu.addAction(self.selectAct) ## Act processMenu = self.menubar.addMenu('&执行') processMenu.addAction(self.extractAct) processMenu.addAction(self.splitAct) processMenu.addAction(self.fillAct) processMenu.addAction(self.autoAct) processMenu.addAction(self.mergeAct) ## Tool toolMenu = self.menubar.addMenu('&工具') toolMenu.addAction(self.todocxAct) toolMenu.addAction(self.toxmlAct) toolMenu.addAction(self.tohtmlAct) ## Setting settingMenu = self.menubar.addMenu('&设置') settingMenu.addAction(self.settingAct) ## Help helpMenu = self.menubar.addMenu('&帮助') helpMenu.addAction(self.aboutAct) def createToolbar(self): ########################### # create toolbar ########################### self.toolbar = self.addToolBar('File') self.toolbar.addAction(self.openAct) self.toolbar.addAction(self.saveAct) #self.toolbar.addAction(self.exitAct) # self.toolbar = self.addToolBar('Edit') self.toolbar.addAction(self.settingAct) self.toolbar.addAction(self.selectAct) # self.toolbar = self.addToolBar('Act') self.toolbar.addAction(self.extractAct) self.toolbar.addAction(self.splitAct) self.toolbar.addAction(self.fillAct) self.toolbar.addAction(self.autoAct) self.toolbar.addAction(self.mergeAct) # self.toolbar = self.addToolBar('Tool') self.toolbar.addAction(self.todocxAct) self.toolbar.addAction(self.toxmlAct) self.toolbar.addAction(self.tohtmlAct) # #self.toolbar = self.addToolBar('Setting') #self.toolbar.addAction(self.settingAct) # self.toolbar = self.addToolBar('Delete') self.toolbar.addAction(self.deleteAct) #### # create combobox self.toolbar = self.addToolBar('Select Target') self.combobox = QComboBox() self.combobox.currentIndexChanged.connect(self.selection_change) self.combobox.setMinimumWidth(150) self.combobox.setMinimumHeight(20) self.toolbar.addWidget(self.combobox) # create progress bar self.toolbar = self.addToolBar('Progress') self.progressBar = QProgressBar(self) self.progressBar.setEnabled(True) #width = self.frameGeometry().width() #height = self.frameGeometry().height() #self.progressBar.setGeometry(0, height-20, width-20, 20) self.progressBar.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.progressBar.setValue(self.step) #self.setCentralWidget(self.progressBar) self.timer = QtCore.QBasicTimer() self.timer.start(20, self) self.toolbar.addWidget(self.progressBar) def createDlgs(self): ################################### ##### select ####################### ################################### self.dlg_select = QDialog(self) vbox = QVBoxLayout() vbox.addStretch(1) for position in []: #POSITION: label = QLabel() label.setText(position) label.setMinimumWidth(80) combo = QComboBox() print(position) for case in switch(position): if case('法人'): positions = ['项目经理'] break if case('联系人'): positions = ['工程师'] break if case('委托人1'): positions = ['项目经理', '工程师'] break if case('委托人2'): positions = ['项目经理', '工程师'] break if case('技术负责人'): positions = ['工程师'] break if case('财务负责人'): positions = ['工程师'] break if case(): positions = [position] break print(positions) from db_sqlite import get_name_list combo.addItems( get_name_list(positions) ) #db['human'].filtering_by_position(positions=positions)) combo.setMinimumWidth(90) self.combos[position] = combo hbox = QHBoxLayout() hbox.addStretch(1) hbox.addWidget(label) hbox.addWidget(combo) vbox.addLayout(hbox) self.refresh_project_members() self.dlg_select.setLayout(vbox) self.dlg_select.setWindowTitle(r'选择项目有关人') self.dlg_select.setWindowIcon(QIcon('icons\\select.png')) ###################################### ### setting ########################## ###################################### self.dlg_setting = QDialog(self) vbox = QVBoxLayout() vbox.addStretch(1) ##################################### from db_sqlite import get_project_types label = QLabel() label.setText('项目类型') label.setMinimumWidth(80) combo = QComboBox() for ptype in get_project_types(): combo.addItem(ptype) combo.setMinimumWidth(90) self.ptype_combo = combo hbox = QHBoxLayout() hbox.addStretch(1) hbox.addWidget(label) hbox.addWidget(self.ptype_combo) vbox.addLayout(hbox) ############################ ############################ self.setting_labels = [] self.setting_buttons = [] self.setting_edits = [] self.setting_selected = 0 for i, routine in enumerate(PATH): label = QLabel() label.setText(routine) label.setMinimumWidth(80) self.setting_labels.append(label) edit = QLineEdit() if routine in list(db.keys()): edit.setText(db[routine]) self.setting_info[PATH[i]] = db[routine] edit.setMinimumWidth(200) self.setting_edits.append(edit) button = QPushButton() self.setting_buttons.append(button) self.setting_buttons[i].setText('选择') self.setting_buttons[i].toggle() self.setting_buttons[i].setAccessibleName(str(i)) self.setting_buttons[i].released.connect(self.act_filebrowser) #self.connect(button,SIGNAL("clicked()"),self.act_filebrowser) #button.clicked.connect(lambda:self.act_filebrowser(button)) #self.setting_buttons.append(button) #self.setting_buttons[i].clicked.connect(lambda:self.act_filebrowser(self.setting_buttons[i])) hbox = QHBoxLayout() hbox.addStretch(1) hbox.addWidget(label) hbox.addWidget(edit) hbox.addWidget(button) vbox.addLayout(hbox) self.dlg_setting.setLayout(vbox) self.dlg_setting.setWindowTitle(r'选择路径') self.dlg_setting.setWindowIcon(QIcon('icons\\setting_.png')) @staticmethod def createTextEdit(): textEdit = QTextEdit() textEdit.setFont(QFont('宋体', 16)) return textEdit @staticmethod def createWebView(): webView = QWebView() webView.settings().setAttribute(QWebSettings.PluginsEnabled, True) #self.webView.settings().setAttribute(QWebSettings.WebAttribute.DeveloperExtrasEnabled, True) webView.settings().setAttribute(QWebSettings.PrivateBrowsingEnabled, True) webView.settings().setAttribute( QWebSettings.LocalContentCanAccessRemoteUrls, True) #self.webView.loadFinished.connect(self._loadfinished) #self.webView.setUrl(QtCore.QUrl("file:///G:/AutoMaking/src/Documentation/test.pdf")) #self.webView.load(QtCore.QUrl().fromLocalFile("G:\\AutoMaking\\src\\Documentation\\test.pdf")) #`self.webView.setHtml('<html><head></head><title></title><body></body></html>', baseUrl = QtCore.QUrl().fromLocalFile("G:\\AutoMaking\\src\\Documentation\\test.pdf")) #webView.setHtml(docx2html("G:\\AutoMaking\\src\\Documentation\\test.docx")) #self.webView.show() #self.webView.hide() #self.webView.setObjectName("webView") #QtCore.QTimer.singleShot(1200, self.webView.show) #self.webView.setContent() return webView def createViews(self): self.preView_L = DocView.createTextEdit() #createWebView() self.preView_L.setObjectName('TextEdit_L') #'WebView_L' self.preView_L.setAccessibleName('TextEdit_L') self.preView_R = DocView.createTextEdit() #createWebView() self.preView_R.setObjectName('TextEdit_R') #'WebView_R' self.preView_R.setAccessibleName('TextEdit_R') self.splitter = QSplitter(QtCore.Qt.Horizontal) self.splitter.setStretchFactor(1, 1) self.splitter.addWidget(self.preView_L) self.splitter.addWidget(self.preView_R) self.setCentralWidget(self.splitter) def initUI(self): # create act self.createAct() # create status bar self.statusBar() # create menu self.createMenu() # create toolbar self.createToolbar() # create dlgs self.createDlgs() # create central widgets self.createViews() # set size #self.setGeometry(300, 300, 350, 250) #self.resized.connect(self.act_resize) self.setMinimumSize(500, 350) self.showMaximized() self.setWindowTitle(r'标书自动生成') # set title self.setWindowIcon(QIcon('icons\\document_.png')) # set windowIcon self.show() ## #self.setMouseTracking(True) #################################################################### ##############################Signals################################ #################################################################### ''' def mousePressEvent(self, event): self.origin = event.pos() self.rubberband.setGeometry( QtCore.QRect(self.origin, QtCore.QSize())) self.rubberband.show() QtGui.QWidget.mousePressEvent(self, event) def mouseMoveEvent(self, event): if self.rubberband.isVisible(): self.rubberband.setGeometry( QtCore.QRect(self.origin, event.pos()).normalized()) QtGui.QWidget.mouseMoveEvent(self, event) def mouseReleaseEvent(self, event): if self.rubberband.isVisible(): self.rubberband.hide() selected = [] rect = self.rubberband.geometry() for child in self.findChildren(QtGui.QPushButton): if rect.intersects(child.geometry()): selected.append(child) print 'Selection Contains:\n ', if selected: print ' '.join( 'Button: %s\n' % child.text() for child in selected) else: print ' Nothing\n' QtGui.QWidget.mouseReleaseEvent(self, event) ''' def resizeEvent(self, event): #self.resized.emit() ''' width = self.frameGeometry().width() height = self.frameGeometry().height() print(width,height) self.progressBar.setGeometry(QtCore.QRect(0, height-20, width-20, 20)) self.progressBar.setVisible(True) self.update() ''' return super(DocView, self).resizeEvent(event) def timerEvent(self, e): if self.step >= 100: self.timer.stop() return self.step = self.step + 1 self.progressBar.setValue(self.step) def keyPressEvent(self, event): # if event.key( ) == QtCore.Qt.Key_Escape: # QtCore.Qt.Key_Escape is a value that equates to what the operating system passes to python from the keyboard when the escape key is pressed. self.close() def closeEvent(self, event): if self.isfinished: self.deleteLater() return reply = QMessageBox.question(self, '警示', "确定关闭?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: self.deleteLater() event.accept() else: event.ignore() def selection_change(self, i): ''' print("Items in the list are :") for count in range(self.combobox.count()): print(self.combobox.itemText(count)) print("Current index",i,"selection changed ",self.combobox.currentText()) ''' section_name = self.combobox.currentText() print(section_name) if '提取的文件' == section_name: inpath = self.filepath_extract outpath = None elif '原件' == section_name: inpath = self.filepath_in outpath = self.filepath_out else: inpath = os.path.join(self.split_dir, section_name + '.docx') outpath = os.path.join(self.processed_dir, section_name + '.docx') self.refresh_left_preview(inpath) self.refresh_right_preview(outpath) #################################################################### ##############################Actions################################ #################################################################### ''' def act_resize(self): width = self.frameGeometry().width() height = self.frameGeometry().height() self.progressBar.setGeometry(0, height-40, width-20, 20) ''' def act_open(self): filepath, extensions = QFileDialog.getOpenFileName( self, r'打开招标文件', '', "Document files (*.docx *.doc *.wps *pdf)") print(filepath) if filepath is self.filepath_in: return if filepath is not '': self.lastpath, self.filename = os.path.split(filepath) filename, extension = os.path.splitext(filepath) self.filepath_in = filename + '.docx' self.filepath_extract = os.path.join(self.lastpath, 'extracted.docx') self.filepath_out = os.path.join(self.lastpath, 'out.docx') self.address_dic = {} if '.docx' in extension: self.combobox.clear() self.combobox.addItem('原件') return else: reply = QMessageBox.question(self, '警示', "变换文件扩展名?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.No: QMessageBox.warning(self, '警示', '文件扩展名需要被变换') return self.combobox.clear() self.combobox.addItem('原件') # convert into docx file for case in switch(extension): if case('.doc'): doc2docx(filepath) break if case('.pdf'): pdf2docx(filepath) break if case(''): break def act_select(self): self.dlg_select.show() self.refresh_project_members() from processing.xml2dict import dic2xml dic2xml(self.setting_info, os.path.join(os.getcwd(), 'db\\项目设置.xml')) from setting import set_xml_db set_xml_db() ''' self.dlg_select.show() # self.refresh_project_members() # db['finance'].filtering(need_years=3) #db['human'].select_people(name_list=[db['project_members'][position] for position in POSITION]) db['projects_done'].filtering(project_types=['水利'],need_years=3) db['projects_being'].filtering(project_types=['水利']) ''' # def act_extract(self): if self.filepath_in is None or not os.path.exists(self.filepath_in): self.act_open() # initialize self.combobox.clear() self.combobox.addItem('原件') self.combobox.addItem(r'提取的文件') self.combobox.setCurrentIndex(1) # extract = Extract(self.filepath_in) extract.process(output_filepath=self.filepath_extract) #db['project_info'].set_db(extract.extract_project_infos()) self.refresh_left_preview(self.filepath_extract) #self.isfinished = True # def act_split(self): mkdir(self.split_dir) split = Split(input_filepath=self.filepath_extract) self.sections = split.process(self.progressBar) self.combobox.addItems(self.sections) def act_fillin(self): self.refresh_project_members() #https://stackoverflow.com/questions/6415737/change-the-value-of-the-progress-bar-from-a-class-other-than-my-gui-class-pyqt4?rq=1 section_name = self.combobox.currentText() #print(section_name) if any(key in section_name for key in ['提取的文件', '原件']): QMessageBox.about(self, '通知', '请先选择要填写的') return # set in and out path print(self.processed_dir) if not os.path.exists(self.processed_dir): os.mkdir(self.processed_dir) inpath = os.path.join(self.split_dir, section_name + '.docx') outpath = os.path.join(self.processed_dir, section_name + '.docx') # fillin if not os.path.exists(outpath): fillin = FillIn(inpath) fillin.process(outpath) # preview self.refresh_right_preview(outpath) def act_auto(self): self.refresh_project_members() self.progressBar.setValue(0) mkdir(self.processed_dir) count = len(self.sections) for index, section in enumerate(self.sections): fillin = FillIn(os.path.join(self.split_dir, section + '.docx')) fillin.process(os.path.join(self.processed_dir, section + '.docx')) self.progressBar.setValue(int((index + 1) * 100 / count)) def act_merge(self): merge = Merge(tmpdir=self.processed_dir, section_names=self.sections) merge.process(self.filepath_out) opendocument(self.filepath_out) def act_delete(self): section_name = self.combobox.currentText() #print(section_name) if '原件' == section_name: filepath = self.filepath_out elif '提取的文件' == section_name: filepath = self.filepath_extract else: filepath = os.path.join(self.processed_dir, section_name + '.docx') if os.path.exists(filepath): os.remove(filepath) self.refresh_right_preview(filepath) def act_save(self): filepath, extensions = QFileDialog.getSaveFileName( self, r'保存投标文件', '', "Document files (*.docx)") if os.path.exists(filepath): os.rename(self.filepath_out, filepath) pass def act_2docx(self): section_name = self.combobox.currentText() #print(section_name) if '原件' == section_name: outpath = self.filepath_out inpath = self.filepath_in elif '提取的文件' == section_name: outpath = self.filepath_extract inpath = None else: outpath = os.path.join(self.processed_dir, section_name + '.docx') inpath = os.path.join(self.split_dir, section_name + '.docx') if os.path.exists(outpath): opendocument(outpath) elif outpath is not None and os.path.exists(inpath): opendocument(inpath) def act_2xml(self): section_name = self.combobox.currentText() if '原件' == section_name: inpath = self.filepath_in elif '提取的文件' == section_name: inpath = self.filepath_extract else: if os.path.exists( os.path.join(self.processed_dir, section_name + '.docx')): inpath = os.path.join(self.processed_dir, section_name + '.docx') else: inpath = os.path.join(self.split_dir, section_name + '.docx') outpath = os.path.splitext(inpath)[0] + '.xml' if not os.path.exists(outpath): docx2xml(inpath) open_chrome(outpath) def act_2html(self): section_name = self.combobox.currentText() if '原件' == section_name: inpath = self.filepath_in elif '提取的文件' == section_name: inpath = self.filepath_extract else: if os.path.exists( os.path.join(self.processed_dir, section_name + '.docx')): inpath = os.path.join(self.processed_dir, section_name + '.docx') else: inpath = os.path.join(self.split_dir, section_name + '.docx') outpath = os.path.splitext(inpath)[0] + '.html' if not os.path.exists(outpath): docx2html(inpath) open_chrome(outpath) def act_about(self): QMessageBox.about(self, '关于标书自动生成软件', '版本号:0.1.0\n生成时间:2017.11.28') def act_setting(self): self.dlg_setting.show() self.setting_info['项目类型'] = self.ptype_combo.currentText() from processing.xml2dict import dic2xml dic2xml(self.setting_info, os.path.join(os.getcwd(), 'db\\项目设置.xml')) from setting import set_xml_db set_xml_db() def act_filebrowser(self): #,button): #print(selected) sending_button = self.sender() selected = int( sending_button.accessibleName() ) #int(button.accessibleName())#self.setting_buttons.index(button)#int(object.accessibleName()) dir_path = str( QFileDialog.getExistingDirectory(self, PATH[selected]) ) if '数据库' not in PATH[selected] else QFileDialog.getOpenFileName( self, PATH[selected], '', "sqlite database files (*.db)")[0] if dir_path is not None and dir_path is not '': print(dir_path) db[PATH[selected]] = dir_path self.setting_edits[selected].setText(dir_path) self.setting_info[PATH[selected]] = dir_path #print(dir_path) #################################################################### ##############################Methods################################ #################################################################### def refresh_project_members(self): project_member_info = {} for position in POSITION: project_member_info[position] = self.combos[position].currentText() self.setting_info['项目组织机构'] = project_member_info ''' for position in POSITION: db['project_members'][position] = self.combos[position].currentText() if len(db['project_members']) > 0: db['human'].select_people(name_list=[db['project_members'][position] for position in POSITION]) #print(self.project_members) ''' def _loadfinished(self, ok): #self.webView.load(QtCore.QUrl('about:blank')) pass def refresh_left_preview(self, filepath): if filepath and os.path.exists(filepath): #print(self.preView_L.accessibleName(),self.preView_L.objectName(),'here') if 'Edit' in self.preView_L.accessibleName(): fulltext = docx2text(filepath) self.preView_L.setText(fulltext) else: self.preView_L.setHtml(docx2html(filepath)) def refresh_right_preview(self, filepath): if filepath and os.path.exists(filepath): if 'Edit' in self.preView_R.accessibleName(): fulltext = docx2text(filepath) self.preView_R.setText(fulltext) else: self.preView_R.setHtml(docx2html(filepath)) else: if 'Edit' in self.preView_L.accessibleName(): self.preView_R.setText('') else: self.preView_R.setHtml('')
class ProjectPropertiesDialog(QDialog): """ The class which support the creation and management of the output. It is notably used to select the options to create the figures. """ send_log = pyqtSignal(str, name='send_log') cut_mesh_partialy_dry_signal = pyqtSignal( bool, name='cut_mesh_partialy_dry_signal') # to change suffix no_cut """ A PyQtsignal used to write the log. """ def __init__(self, path_prj, name_prj, name_icon): super().__init__() self.path_prj = path_prj self.name_prj = name_prj self.name_icon = name_icon self.is_modification = False # list with the available color map self.namecmap = [ 'coolwarm', 'jet', 'magma', 'viridis', 'inferno', 'plasma', 'Blues', 'Greens', 'Greys', 'Oranges', 'Purples', 'Reds', 'gist_earth', 'terrain', 'ocean' ] self.msg2 = QMessageBox() self.hvum = HydraulicVariableUnitManagement() self.init_iu() def init_iu(self): # insist on white background color (for linux, mac) self.setAutoFillBackground(True) p = self.palette() p.setColor(self.backgroundRole(), Qt.white) self.setPalette(p) """ WIDGETS """ """ general widgets """ # cut_2d_grid self.cut_2d_grid_label = QLabel( self.tr('Cut hydraulic mesh partialy wet')) self.cut_2d_grid_checkbox = QCheckBox(self.tr('')) # min_height min_height_label = QLabel(self.tr('2D minimum water height [m]')) self.min_height_lineedit = QLineEdit("") # erase_data self.erase_data_label = QLabel(self.tr('Erase file if exist')) self.erase_data_checkbox = QCheckBox(self.tr('')) """ outputs widgets """ self.mesh_whole_profile_hyd = QCheckBox("") self.mesh_whole_profile_hyd.setObjectName("mesh_whole_profile_hyd") self.point_whole_profile_hyd = QCheckBox("") self.point_whole_profile_hyd.setObjectName("point_whole_profile_hyd") self.mesh_units_hyd = QCheckBox("") self.mesh_units_hyd.setObjectName("mesh_units_hyd") self.mesh_units_hab = QCheckBox("") self.mesh_units_hab.setObjectName("mesh_units_hab") self.point_units_hyd = QCheckBox("") self.point_units_hyd.setObjectName("point_units_hyd") self.point_units_hab = QCheckBox("") self.point_units_hab.setObjectName("point_units_hab") vertical_exaggeration = QLabel("3D vertical exaggeration") self.vertical_exaggeration_lineedit = QLineEdit() self.vertical_exaggeration_lineedit.setToolTip( self.tr("Exaggeration coefficient of z nodes values (all 3D)")) self.vertical_exaggeration_lineedit.setAlignment(Qt.AlignCenter) self.vertical_exaggeration_lineedit.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Maximum) self.vertical_exaggeration_lineedit.setFixedHeight( self.point_units_hyd.sizeHint().height()) self.vertical_exaggeration_lineedit.setFixedWidth(75) self.elevation_whole_profile_hyd = QCheckBox("") self.elevation_whole_profile_hyd.setObjectName( "elevation_whole_profile_hyd") self.pvd_variable_z_combobox = QComboBox() self.pvd_variable_z_combobox.setToolTip( self.tr("Choose the variable to assign to the z nodes (3D)")) self.variables_units_hyd = QCheckBox("") self.variables_units_hab = QCheckBox("") self.variables_units_hyd.setObjectName("variables_units_hyd") self.variables_units_hab.setObjectName("variables_units_hab") self.mesh_detailled_text_hyd = QCheckBox("") self.mesh_detailled_text_hyd.setObjectName("mesh_detailled_text_hyd") self.point_detailled_text_hyd = QCheckBox("") self.point_detailled_text_hyd.setObjectName("point_detailled_text_hyd") self.mesh_detailled_text_hab = QCheckBox("") self.mesh_detailled_text_hab.setObjectName("mesh_detailled_text_hab") self.point_detailled_text_hab = QCheckBox("") self.point_detailled_text_hab.setObjectName("point_detailled_text_hab") self.fish_information_hab = QCheckBox("") self.fish_information_hab.setObjectName("fish_information_hab") self.output_checkbox_list = [ self.mesh_whole_profile_hyd, self.point_whole_profile_hyd, self.mesh_units_hyd, self.mesh_units_hab, self.point_units_hyd, self.point_units_hab, self.elevation_whole_profile_hyd, self.variables_units_hyd, self.variables_units_hab, self.mesh_detailled_text_hyd, self.point_detailled_text_hyd, self.mesh_detailled_text_hab, self.point_detailled_text_hab, self.fish_information_hab ] self.checkbox_list_set = list( set([ checkbox.objectName()[:-4] for checkbox in self.output_checkbox_list ])) """ figure widgets """ # fig_size fig_size_label = QLabel(self.tr('Figure size (w,h) [cm]'), self) self.fig_size_lineedit = QLineEdit("") self.fig_size_lineedit.setToolTip(self.tr("width, height")) fig_size_label.setToolTip(self.tr("width, height")) # color_map color_map_label = QLabel(self.tr('Color map'), self) self.color_map_combobox = QComboBox() self.color_map_combobox.addItems(self.namecmap) # font_size font_size_label = QLabel(self.tr('Font size'), self) self.font_size_lineedit = QLineEdit("") # font_family font_family_label = QLabel(self.tr('Font family'), self) self.font_family_combobox = QComboBox() self.font_family_combobox.addItems( ["Arial", "Calibri", "Times New Roman", "Tahoma", "DejaVu Sans"]) # line_width line_width_label = QLabel(self.tr('Line width'), self) self.line_width_lineedit = QLineEdit("") # grid grid_label = QLabel(self.tr('Grid'), self) self.grid_checkbox = QCheckBox("", self) # fig_forma fig_format_label = QLabel(self.tr('Figure format')) self.fig_format_combobox = QComboBox() self.fig_format_combobox.addItems(['.png', '.pdf']) # resolution resolution_label = QLabel(self.tr('Resolution [dpi]')) self.resolution_lineedit = QLineEdit("") # type_fishname type_fishname_label = QLabel(self.tr('Type of animal name')) self.type_fishname_combobox = QComboBox() self.type_fishname_combobox.addItems([ self.tr('Latin Name'), self.tr('French Common Name'), self.tr('English Common Name'), self.tr('Code ONEMA') ]) # order matters here, add stuff at the end! # marquers_hab_fig marquers_hab_fig_label = QLabel(self.tr('Markers for habitat figures')) self.marquers_hab_fig_checkbox = QCheckBox(self.tr('')) # reset default self.reset_by_default_pref = QPushButton(self.tr('Reset by default')) self.reset_by_default_pref.clicked.connect( lambda: self.set_pref_gui_from_dict(default=True)) # save self.save_pref_button = QPushButton(self.tr('OK')) self.save_pref_button.clicked.connect(self.save_preferences) # close self.close_pref_button = QPushButton(self.tr('Cancel')) self.close_pref_button.clicked.connect(self.close_preferences) """ LAYOUT """ # general options layout_general_options = QFormLayout() general_options_group = QGroupBox(self.tr("General")) #general_options_group.setStyleSheet('QGroupBox {font-weight: bold;}') general_options_group.setLayout(layout_general_options) layout_general_options.addRow(self.cut_2d_grid_label, self.cut_2d_grid_checkbox) layout_general_options.addRow(min_height_label, self.min_height_lineedit) layout_general_options.addRow( self.erase_data_label, self.erase_data_checkbox) # , Qt.AlignLeft # exports options self.layout_available_exports = QGridLayout() available_exports_group = QGroupBox(self.tr("Default exports")) self.doubleclick_check_uncheck_filter = DoubleClicOutputGroup() available_exports_group.installEventFilter( self.doubleclick_check_uncheck_filter) self.doubleclick_check_uncheck_filter.double_clic_signal.connect( self.check_uncheck_all_checkboxs_at_once) #available_exports_group.setStyleSheet('QGroupBox {font-weight: bold;}') available_exports_group.setLayout(self.layout_available_exports) # row 0 self.layout_available_exports.addWidget(QLabel(".hyd"), 0, 2, Qt.AlignCenter) self.layout_available_exports.addWidget(QLabel(".hab"), 0, 3, Qt.AlignCenter) # row 1 self.layout_available_exports.addWidget(QLabel("Geopackage (.gpkg)"), 1, 0) self.layout_available_exports.addWidget( QLabel(self.tr("Mesh whole profile")), 1, 1) self.layout_available_exports.addWidget(self.mesh_whole_profile_hyd, 1, 2, Qt.AlignCenter) # row 2 self.layout_available_exports.addWidget(QLabel("Geopackage (.gpkg)"), 2, 0) self.layout_available_exports.addWidget( QLabel(self.tr("Point whole profile")), 2, 1) self.layout_available_exports.addWidget(self.point_whole_profile_hyd, 2, 2, Qt.AlignCenter) # row 3 self.layout_available_exports.addWidget(QLabel("Geopackage (.gpkg)"), 3, 0) self.layout_available_exports.addWidget(QLabel(self.tr("Mesh units"))) self.layout_available_exports.addWidget(self.mesh_units_hyd, 3, 2, Qt.AlignCenter) self.layout_available_exports.addWidget(self.mesh_units_hab, 3, 3, Qt.AlignCenter) # row 4 self.layout_available_exports.addWidget(QLabel("Geopackage (.gpkg)"), 4, 0) self.layout_available_exports.addWidget(QLabel(self.tr("Point units")), 4, 1) self.layout_available_exports.addWidget(self.point_units_hyd, 4, 2, Qt.AlignCenter) self.layout_available_exports.addWidget(self.point_units_hab, 4, 3, Qt.AlignCenter) # row 5 self.layout_available_exports.addWidget(QHLine(), 5, 0, 1, 4) # row 6 self.layout_available_exports.addWidget(QLabel("3D (.stl)"), 6, 0) self.layout_available_exports.addWidget( QLabel(self.tr("Mesh whole profile")), 6, 1) self.layout_available_exports.addWidget( self.elevation_whole_profile_hyd, 6, 2, Qt.AlignCenter) # row 7 self.layout_available_exports.addWidget(QLabel("3D (.pvd, .vtu)"), 7, 0) self.pvd_variable_z_layout = QHBoxLayout() self.pvd_variable_z_layout.addWidget(QLabel(self.tr("Mesh units"))) self.pvd_variable_z_layout.addWidget(self.pvd_variable_z_combobox) self.layout_available_exports.addLayout(self.pvd_variable_z_layout, 7, 1) # self.layout_available_exports.addWidget(QLabel(self.tr("Mesh units")), 7, 1) self.layout_available_exports.addWidget(self.variables_units_hyd, 7, 2, Qt.AlignCenter) self.layout_available_exports.addWidget(self.variables_units_hab, 7, 3, Qt.AlignCenter) # row 8 self.layout_available_exports.addWidget(vertical_exaggeration, 8, 0, 1, 2) self.layout_available_exports.addWidget( self.vertical_exaggeration_lineedit, 8, 2, 1, 2, Qt.AlignCenter) # row 9 self.layout_available_exports.addWidget(QHLine(), 9, 0, 1, 4) # row 10 self.layout_available_exports.addWidget(QLabel("Text (.txt)"), 10, 0) self.layout_available_exports.addWidget( QLabel(self.tr("Mesh detailled")), 10, 1) self.layout_available_exports.addWidget(self.mesh_detailled_text_hyd, 10, 2, Qt.AlignCenter) self.layout_available_exports.addWidget(self.mesh_detailled_text_hab, 10, 3, Qt.AlignCenter) # row 11 self.layout_available_exports.addWidget(QLabel("Text (.txt)"), 11, 0) self.layout_available_exports.addWidget( QLabel(self.tr("Point detailled")), 11, 1) self.layout_available_exports.addWidget(self.point_detailled_text_hyd, 11, 2, Qt.AlignCenter) self.layout_available_exports.addWidget(self.point_detailled_text_hab, 11, 3, Qt.AlignCenter) # row 11 self.layout_available_exports.addWidget(QLabel("Text (.pdf)"), 12, 0) self.layout_available_exports.addWidget( QLabel(self.tr("Fish informations")), 12, 1) self.layout_available_exports.addWidget(self.fish_information_hab, 12, 3, Qt.AlignCenter) # figure options layout_figures = QFormLayout() figures_group = QGroupBox(self.tr("Figures")) #figures_group.setStyleSheet('QGroupBox {font-weight: bold;}') figures_group.setLayout(layout_figures) layout_figures.addRow(fig_size_label, self.fig_size_lineedit) layout_figures.addRow(color_map_label, self.color_map_combobox) layout_figures.addRow(font_size_label, self.font_size_lineedit) layout_figures.addRow(font_family_label, self.font_family_combobox) layout_figures.addRow(line_width_label, self.line_width_lineedit) layout_figures.addRow(grid_label, self.grid_checkbox) layout_figures.addRow(fig_format_label, self.fig_format_combobox) layout_figures.addRow(resolution_label, self.resolution_lineedit) layout_figures.addRow(type_fishname_label, self.type_fishname_combobox) layout_figures.addRow(marquers_hab_fig_label, self.marquers_hab_fig_checkbox) # general layout = QGridLayout(self) layout.addWidget(general_options_group, 0, 0) layout.addWidget(available_exports_group, 1, 0) layout.addWidget(figures_group, 0, 1, 3, 2) layout.addWidget(self.reset_by_default_pref, 3, 0, Qt.AlignLeft) layout.addWidget(self.save_pref_button, 3, 1) # , 1, 1 layout.addWidget(self.close_pref_button, 3, 2) # , 1, 1 self.setWindowTitle(self.tr("Project properties")) self.setWindowIcon(QIcon(self.name_icon)) def connect_modifications_signal(self): self.cut_2d_grid_checkbox.stateChanged.connect( self.set_modification_presence) self.min_height_lineedit.textChanged.connect( self.set_modification_presence) self.erase_data_checkbox.stateChanged.connect( self.set_modification_presence) self.pvd_variable_z_combobox.currentIndexChanged.connect( self.set_modification_presence) self.vertical_exaggeration_lineedit.textChanged.connect( self.set_modification_presence) for checkbox in self.output_checkbox_list: checkbox.stateChanged.connect(self.set_modification_presence) self.fig_size_lineedit.textChanged.connect( self.set_modification_presence) self.color_map_combobox.currentIndexChanged.connect( self.set_modification_presence) self.font_size_lineedit.textChanged.connect( self.set_modification_presence) self.line_width_lineedit.textChanged.connect( self.set_modification_presence) self.grid_checkbox.stateChanged.connect(self.set_modification_presence) self.fig_format_combobox.currentIndexChanged.connect( self.set_modification_presence) self.resolution_lineedit.textChanged.connect( self.set_modification_presence) self.type_fishname_combobox.currentIndexChanged.connect( self.set_modification_presence) self.marquers_hab_fig_checkbox.stateChanged.connect( self.set_modification_presence) def set_pref_gui_from_dict(self, default=False): if default: project_properties = create_default_project_properties_dict() else: # read actual figure option project_properties = load_project_properties(self.path_prj) # min_height_hyd self.min_height_lineedit.setText( str(project_properties['min_height_hyd'])) # CutMeshPartialyDry if project_properties[ 'cut_mesh_partialy_dry']: # is a string not a boolean self.cut_2d_grid_checkbox.setChecked(True) else: self.cut_2d_grid_checkbox.setChecked(False) # erase_id if project_properties['erase_id']: # is a string not a boolean self.erase_data_checkbox.setChecked(True) else: self.erase_data_checkbox.setChecked(False) # pvd_variable_z_combobox item_list = [ self.hvum.z.name_gui, self.hvum.h.name_gui, self.hvum.v.name_gui, self.hvum.level.name_gui, self.hvum.hydraulic_head_level.name_gui, self.hvum.conveyance.name_gui, self.hvum.froude.name_gui ] self.pvd_variable_z_combobox.clear() self.pvd_variable_z_combobox.addItems(item_list) self.pvd_variable_z_combobox.setCurrentIndex( item_list.index(project_properties["pvd_variable_z"])) # vertical_exaggeration self.vertical_exaggeration_lineedit.setText( str(project_properties["vertical_exaggeration"])) # check uncheck output checkboxs for checkbox in self.output_checkbox_list: type = checkbox.objectName()[-3:] if type == "hyd": index = 0 if type == "hab": index = 1 checkbox.setChecked( project_properties[checkbox.objectName()[:-4]][index]) # color_map self.color_map_combobox.setCurrentIndex( self.color_map_combobox.findText(project_properties['color_map'])) # fig_size self.fig_size_lineedit.setText( str(project_properties['width']) + ',' + str(project_properties['height'])) # font size self.font_size_lineedit.setText(str(project_properties['font_size'])) # font_family font_family_list = [ self.font_family_combobox.itemText(i) for i in range(self.font_family_combobox.count()) ] self.font_family_combobox.setCurrentIndex( font_family_list.index(project_properties['font_family'])) # line_width self.line_width_lineedit.setText(str(project_properties['line_width'])) # grid if project_properties['grid']: # is a string not a boolean self.grid_checkbox.setChecked(True) else: self.grid_checkbox.setChecked(False) # format fig_format_list = [ self.fig_format_combobox.itemText(i) for i in range(self.fig_format_combobox.count()) ] self.fig_format_combobox.setCurrentIndex( fig_format_list.index(project_properties['format'])) # resolution self.resolution_lineedit.setText(str(project_properties['resolution'])) # fish_name_type self.type_fishname_combobox.setCurrentIndex( int(project_properties['fish_name_type'])) # marker if project_properties['marker']: # is a string not a boolean self.marquers_hab_fig_checkbox.setChecked(True) else: self.marquers_hab_fig_checkbox.setChecked(False) def open_preferences(self): self.set_pref_gui_from_dict() self.connect_modifications_signal() self.check_modifications_presence() self.setModal(True) self.show() def check_modifications_presence(self): self.is_modification = False def set_modification_presence(self): self.is_modification = True def check_uncheck_all_checkboxs_at_once(self): # uncheck all if self.mesh_whole_profile_hyd.isChecked(): [ checkbox.setChecked(False) for checkbox in self.output_checkbox_list ] else: [ checkbox.setChecked(True) for checkbox in self.output_checkbox_list ] def collect_project_properties_choice(self): """ Function to collect user choices of project preferences GUI """ # get default option for security and facility project_properties = load_project_properties(self.path_prj) fig_size = self.fig_size_lineedit.text() if fig_size: fig_size = fig_size.split(',') try: project_properties['width'] = np.float(fig_size[0]) project_properties['height'] = np.float(fig_size[1]) except IndexError: self.send_log.emit('Error: ' + self.tr( 'The size of the figure should be in the format: num1,num2.\n' )) except ValueError: self.send_log.emit('Error: ' + self.tr( 'The size of the figure should be in the format: num1,num2.\n' )) # color map c1 = str(self.color_map_combobox.currentText()) if c1: project_properties['color_map'] = c1 # font size font_size = self.font_size_lineedit.text() if font_size: try: project_properties['font_size'] = int(font_size) except ValueError: self.send_log.emit( 'Error: ' + self.tr('Font size should be an integer. \n')) # font_family font_family = self.font_family_combobox.currentText() if font_family: try: project_properties['font_family'] = font_family except ValueError: self.send_log.emit('Error: ' + self.tr('Font family not recognized. \n')) # line width line_width = self.line_width_lineedit.text() if line_width: try: project_properties['line_width'] = int(line_width) except ValueError: self.send_log.emit( 'Error: ' + self.tr('Line width should be an integer. \n')) # grid if self.grid_checkbox.isChecked(): project_properties['grid'] = True else: project_properties['grid'] = False # format project_properties['format'] = self.fig_format_combobox.currentText() # resolution try: project_properties['resolution'] = int( self.resolution_lineedit.text()) except ValueError: self.send_log.emit( 'Error: ' + self.tr('The resolution should be an integer. \n')) if project_properties['resolution'] < 0: self.send_log.emit( 'Error: ' + self.tr('The resolution should be higher than zero \n')) return if project_properties['resolution'] > 2000: self.send_log.emit( self.tr('Warning: ') + self. tr('The resolution is higher than 2000 dpi. Figures might be very large.\n' )) # fish name type project_properties['fish_name_type'] = int( self.type_fishname_combobox.currentIndex()) # marker if self.marquers_hab_fig_checkbox.isChecked(): project_properties['marker'] = True else: project_properties['marker'] = False # outputs for checkbox in self.output_checkbox_list: type = checkbox.objectName()[-3:] if type == "hyd": index = 0 if type == "hab": index = 1 if checkbox.isChecked(): project_properties[checkbox.objectName()[:-4]][index] = True else: project_properties[checkbox.objectName()[:-4]][index] = False # vertical_exaggeration try: project_properties['vertical_exaggeration'] = int( self.vertical_exaggeration_lineedit.text()) if int(self.vertical_exaggeration_lineedit.text()) < 1: self.send_log.emit("Error: " + self.tr( "Vertical exaggeration value must be superior than 1. Value set to 1." )) project_properties['vertical_exaggeration'] = 1 except: self.send_log.emit("Error: " + self.tr( "Vertical exaggeration value is not integer. Value set to 1.")) project_properties['vertical_exaggeration'] = 1 # pvd_variable_z project_properties[ 'pvd_variable_z'] = self.pvd_variable_z_combobox.currentText() # other option try: project_properties['min_height_hyd'] = float( self.min_height_lineedit.text()) except ValueError: self.send_log.emit('Error: ' + self.tr('Minimum Height should be a number')) if self.erase_data_checkbox.isChecked(): project_properties['erase_id'] = True else: project_properties['erase_id'] = False # CutMeshPartialyDry if self.cut_2d_grid_checkbox.isChecked(): project_properties['cut_mesh_partialy_dry'] = True else: project_properties['cut_mesh_partialy_dry'] = False return project_properties def save_preferences(self): """ A function which save the options for the figures in the xlm project file. The options for the figures are contained in a dictionnary. The idea is to give this dictinnory in argument to all the fonction which create figures. In the xml project file, the options for the figures are saved under the attribute "Figure_Option". If you change things here, it is necessary to start a new project as the old projects will not be compatible. For the new version of HABBY, it will be necessary to insure compatibility by adding xml attribute. """ project_properties = self.collect_project_properties_choice() # save the data in the xml file fname = os.path.join(self.path_prj, self.name_prj + '.habby') # save the name and the path in the xml .prj file if not os.path.isfile(fname): self.msg2.setIcon(QMessageBox.Warning) self.msg2.setWindowTitle(self.tr("Project properties unsaved")) self.msg2.setText(self.tr("Create or open an HABBY project.")) self.msg2.setStandardButtons(QMessageBox.Ok) self.msg2.show() else: save_project_properties(self.path_prj, project_properties) self.send_log.emit(self.tr('# Project properties saved.')) # project_properties['cut_mesh_partialy_dry'] to change suffix no_cut self.cut_mesh_partialy_dry_signal.emit( project_properties['cut_mesh_partialy_dry']) self.close() def close_preferences(self): # # really user want to save ? # if self.is_modification: # self.msg2.setIcon(QMessageBox.Warning) # self.msg2.setWindowTitle(self.tr("Preferences modified")) # self.msg2.setText(self.tr("Do you really want to close preferences without saving your changes ?")) # self.msg2.setStandardButtons(QMessageBox.Yes | QMessageBox.No) # res = self.msg2.exec_() # # # delete # if res == QMessageBox.Yes: # self.send_log.emit('Preferences not saved.') # self.close() # return # if res == QMessageBox.No: # return # close window if opened self.close()
class NetworkChoiceLayout(object): def __init__(self, network: Network, config, wizard=False): self.network = network self.config = config self.protocol = None self.tor_proxy = None self.tabs = tabs = QTabWidget() server_tab = QWidget() proxy_tab = QWidget() blockchain_tab = QWidget() tabs.addTab(blockchain_tab, _('Overview')) tabs.addTab(server_tab, _('Server')) tabs.addTab(proxy_tab, _('Proxy')) fixed_width_hostname = 30 * char_width_in_lineedit() fixed_width_port = 8 * char_width_in_lineedit() # server tab grid = QGridLayout(server_tab) grid.setSpacing(8) self.server_host = QLineEdit() self.server_host.setFixedWidth(fixed_width_hostname) self.server_port = QLineEdit() self.server_port.setFixedWidth(fixed_width_port) self.autoconnect_cb = QCheckBox(_('Select server automatically')) self.autoconnect_cb.setEnabled( self.config.is_modifiable('auto_connect')) self.server_host.editingFinished.connect(self.set_server) self.server_port.editingFinished.connect(self.set_server) self.autoconnect_cb.clicked.connect(self.set_server) self.autoconnect_cb.clicked.connect(self.update) msg = ' '.join([ _("If auto-connect is enabled, Electrum will always use a server that is on the longest blockchain." ), _("If it is disabled, you have to choose a server you want to use. Electrum will warn you if your server is lagging." ) ]) grid.addWidget(self.autoconnect_cb, 0, 0, 1, 3) grid.addWidget(HelpButton(msg), 0, 4) grid.addWidget(QLabel(_('Server') + ':'), 1, 0) grid.addWidget(self.server_host, 1, 1, 1, 2) grid.addWidget(self.server_port, 1, 3) label = _('Server peers') if network.is_connected() else _( 'Default Servers') grid.addWidget(QLabel(label), 2, 0, 1, 5) self.servers_list = ServerListWidget(self) grid.addWidget(self.servers_list, 3, 0, 1, 5) # Proxy tab grid = QGridLayout(proxy_tab) grid.setSpacing(8) # proxy setting self.proxy_cb = QCheckBox(_('Use proxy')) self.proxy_cb.clicked.connect(self.check_disable_proxy) self.proxy_cb.clicked.connect(self.set_proxy) self.proxy_cb.setEnabled(False) self.proxy_mode = QComboBox() self.proxy_mode.addItems(['SOCKS4', 'SOCKS5']) self.proxy_host = QLineEdit() self.proxy_host.setFixedWidth(fixed_width_hostname) self.proxy_port = QLineEdit() self.proxy_port.setFixedWidth(fixed_width_port) self.proxy_user = QLineEdit() self.proxy_user.setPlaceholderText(_("Proxy user")) self.proxy_password = QLineEdit() self.proxy_password.setPlaceholderText(_("Password")) self.proxy_password.setEchoMode(QLineEdit.Password) self.proxy_password.setFixedWidth(fixed_width_port) self.proxy_mode.currentIndexChanged.connect(self.set_proxy) self.proxy_host.editingFinished.connect(self.set_proxy) self.proxy_port.editingFinished.connect(self.set_proxy) self.proxy_user.editingFinished.connect(self.set_proxy) self.proxy_password.editingFinished.connect(self.set_proxy) self.proxy_mode.currentIndexChanged.connect( self.proxy_settings_changed) self.proxy_host.textEdited.connect(self.proxy_settings_changed) self.proxy_port.textEdited.connect(self.proxy_settings_changed) self.proxy_user.textEdited.connect(self.proxy_settings_changed) self.proxy_password.textEdited.connect(self.proxy_settings_changed) self.tor_cb = QCheckBox(_("Use Tor Proxy")) self.tor_cb.setIcon(read_QIcon("tor_logo.png")) self.tor_cb.hide() self.tor_cb.clicked.connect(self.use_tor_proxy) self.tor_cb.setEnabled(False) grid.addWidget(self.tor_cb, 1, 0, 1, 3) grid.addWidget(self.proxy_cb, 2, 0, 1, 3) grid.addWidget( HelpButton( _('Proxy settings apply to all connections: with Electrum servers, but also with third-party services.' )), 2, 4) grid.addWidget(self.proxy_mode, 4, 1) grid.addWidget(self.proxy_host, 4, 2) grid.addWidget(self.proxy_port, 4, 3) grid.addWidget(self.proxy_user, 5, 2) grid.addWidget(self.proxy_password, 5, 3) grid.setRowStretch(7, 1) # Blockchain Tab grid = QGridLayout(blockchain_tab) msg = ' '.join([ _("Electrum connects to several nodes in order to download block headers and find out the longest blockchain." ), _("This blockchain is used to verify the transactions sent by your transaction server." ) ]) self.status_label = QLabel('') grid.addWidget(QLabel(_('Status') + ':'), 0, 0) grid.addWidget(self.status_label, 0, 1, 1, 3) grid.addWidget(HelpButton(msg), 0, 4) self.server_label = QLabel('') msg = _( "Electrum sends your wallet addresses to a single server, in order to receive your transaction history." ) grid.addWidget(QLabel(_('Server') + ':'), 1, 0) grid.addWidget(self.server_label, 1, 1, 1, 3) grid.addWidget(HelpButton(msg), 1, 4) self.height_label = QLabel('') msg = _('This is the height of your local copy of the blockchain.') grid.addWidget(QLabel(_('Blockchain') + ':'), 2, 0) grid.addWidget(self.height_label, 2, 1) grid.addWidget(HelpButton(msg), 2, 4) self.split_label = QLabel('') grid.addWidget(self.split_label, 3, 0, 1, 3) self.nodes_list_widget = NodesListWidget(self) grid.addWidget(self.nodes_list_widget, 5, 0, 1, 5) vbox = QVBoxLayout() vbox.addWidget(tabs) self.layout_ = vbox # tor detector self.td = td = TorDetector() td.found_proxy.connect(self.suggest_proxy) td.start() self.fill_in_proxy_settings() self.proxy_cb.setChecked(True) self.tor_cb.setChecked(True) self.check_disable_proxy(9150) self.set_proxy() self.update() def check_disable_proxy(self, b): if not self.config.is_modifiable('proxy'): b = False for w in [ self.proxy_mode, self.proxy_host, self.proxy_port, self.proxy_user, self.proxy_password ]: w.setEnabled(b) def enable_set_server(self): if self.config.is_modifiable('server'): enabled = not self.autoconnect_cb.isChecked() self.server_host.setEnabled(enabled) self.server_port.setEnabled(enabled) self.servers_list.setEnabled(enabled) else: for w in [ self.autoconnect_cb, self.server_host, self.server_port, self.servers_list ]: w.setEnabled(False) def update(self): net_params = self.network.get_parameters() host, port, protocol = net_params.host, net_params.port, net_params.protocol proxy_config, auto_connect = net_params.proxy, net_params.auto_connect if not self.server_host.hasFocus() and not self.server_port.hasFocus(): self.server_host.setText(host) self.server_port.setText(str(port)) self.autoconnect_cb.setChecked(auto_connect) interface = self.network.interface host = interface.host if interface else _('None') self.server_label.setText(host) self.set_protocol(protocol) self.servers = self.network.get_servers() self.servers_list.update(self.servers, self.protocol, self.tor_cb.isChecked()) self.enable_set_server() height_str = "%d " % (self.network.get_local_height()) + _('blocks') self.height_label.setText(height_str) n = len(self.network.get_interfaces()) status = _("Connected to {0} nodes.").format(n) if n else _( "Not connected") self.status_label.setText(status) chains = self.network.get_blockchains() if len(chains) > 1: chain = self.network.blockchain() forkpoint = chain.get_max_forkpoint() name = chain.get_name() msg = _('Chain split detected at block {0}').format( forkpoint) + '\n' msg += (_('You are following branch') if auto_connect else _('Your server is on branch')) + ' ' + name msg += ' (%d %s)' % (chain.get_branch_size(), _('blocks')) else: msg = '' self.split_label.setText(msg) self.nodes_list_widget.update(self.network) def fill_in_proxy_settings(self): proxy_config = self.network.get_parameters().proxy if not proxy_config: proxy_config = { "mode": "none", "host": "localhost", "port": "9150" } b = proxy_config.get('mode') != "none" self.check_disable_proxy(b) if b: self.proxy_cb.setChecked(True) self.proxy_mode.setCurrentIndex( self.proxy_mode.findText(str( proxy_config.get("mode").upper()))) self.proxy_host.setText(proxy_config.get("host")) self.proxy_port.setText(proxy_config.get("port")) self.proxy_user.setText(proxy_config.get("user", "")) self.proxy_password.setText(proxy_config.get("password", "")) def layout(self): return self.layout_ def set_protocol(self, protocol): if protocol != self.protocol: self.protocol = protocol def change_protocol(self, use_ssl): p = 's' if use_ssl else 't' host = self.server_host.text() pp = self.servers.get(host, constants.net.DEFAULT_PORTS) if p not in pp.keys(): p = list(pp.keys())[0] port = pp[p] self.server_host.setText(host) self.server_port.setText(port) self.set_protocol(p) self.set_server() def follow_branch(self, chain_id): self.network.run_from_another_thread( self.network.follow_chain_given_id(chain_id)) self.update() def follow_server(self, server): self.network.run_from_another_thread( self.network.follow_chain_given_server(server)) self.update() def server_changed(self, x): if x: self.change_server(str(x.text(0)), self.protocol) def change_server(self, host, protocol): pp = self.servers.get(host, constants.net.DEFAULT_PORTS) if protocol and protocol not in protocol_letters: protocol = None if protocol: port = pp.get(protocol) if port is None: protocol = None if not protocol: if 's' in pp.keys(): protocol = 's' port = pp.get(protocol) else: protocol = list(pp.keys())[0] port = pp.get(protocol) self.server_host.setText(host) self.server_port.setText(port) def accept(self): pass def set_server(self): net_params = self.network.get_parameters() net_params = net_params._replace( host=str(self.server_host.text()), port=str(self.server_port.text()), auto_connect=self.autoconnect_cb.isChecked()) self.network.run_from_another_thread( self.network.set_parameters(net_params)) def set_proxy(self): net_params = self.network.get_parameters() if self.proxy_cb.isChecked(): proxy = { 'mode': str(self.proxy_mode.currentText()).lower(), 'host': str(self.proxy_host.text()), 'port': str(self.proxy_port.text()), 'user': str(self.proxy_user.text()), 'password': str(self.proxy_password.text()) } else: proxy = None self.tor_cb.setChecked(False) net_params = net_params._replace(proxy=proxy) self.network.run_from_another_thread( self.network.set_parameters(net_params)) def suggest_proxy(self, found_proxy): if found_proxy is None: self.tor_cb.hide() return self.tor_proxy = found_proxy self.tor_cb.setText("Use Tor proxy at port " + str(found_proxy[1])) if (self.proxy_cb.isChecked() and self.proxy_mode.currentIndex() == self.proxy_mode.findText('SOCKS5') and self.proxy_host.text() == "127.0.0.1" and self.proxy_port.text() == str(found_proxy[1])): self.tor_cb.setChecked(True) self.tor_cb.show() def use_tor_proxy(self, use_it): if not use_it: self.proxy_cb.setChecked(False) else: socks5_mode_index = self.proxy_mode.findText('SOCKS5') if socks5_mode_index == -1: _logger.info("can't find proxy_mode 'SOCKS5'") return self.proxy_mode.setCurrentIndex(socks5_mode_index) self.proxy_host.setText("127.0.0.1") self.proxy_port.setText(str(self.tor_proxy[1])) self.proxy_user.setText("") self.proxy_password.setText("") self.tor_cb.setChecked(True) self.proxy_cb.setChecked(True) self.check_disable_proxy(use_it) self.set_proxy() def proxy_settings_changed(self): self.tor_cb.setChecked(False)
class MainWindow(QMainWindow): loop_started = pyqtSignal() loop_finished = pyqtSignal() def __init__(self): super().__init__() # call a function that initializes user interface self.init_ui() # call a function that initializes menu bar self.init_menu_bar() # self.instruments is a dictionary containing all instruments that have been connected so far. Form of the dict # is: key:value where key is the name of the instrument assigned by you when creating the instrument, and value # contains that particular instance of that instrument. self.instruments = {} # station instruments are used to keep track of the instruments that were added to the instruments table on the # main window, each time an instrument is added to the table it is also added to this dict to keep track of # which instruments are already displayed self.station_instruments = {} # loops dictionary containing all loops that have been created so far. Form: key : value where key is the name # of the loop that is assigned automatically in order of creation of loops (loop1, loop2, loop3, ...), and the # value is an instance of that loop self.loops = {} # dividers dict holds data about all dividers created so far. Form of the data inside: key : value where key # is name of the parameter that the divider is attached to, and value is instance of that particular divider. self.dividers = {} # Keeping track of the loops that are already displayed in table on the main window (to avoid duplicate adding) self.shown_loops = [] # actions is a list containing list of all loops and the last loop added to this list is the one that will get # ran by the run/plot button. I have created this because dictionaries do not have predefined way of puting data # into it, meaning that the order of adding items to the dictionary may or may not be the same as the order of # getting that same data from the dictionary self.actions = [] # list of references to the EditInstrumentWidget windows that are currently open, used to start live updating # of parameters of each of those windows after a measurement has been started. That way only the ones that are # currently opened will be automatically self updating self.active_isntruments = [] # instrument workers is a list of handles to the workers that do the above explained actions. Reason for keeping # this list is because these workers have to be stopped at some point. self.instrument_workers = [] # contains references to buttons for editing self.edit_button_dict = {} # Thread pool for adding separate threads # (execute qcodes in another thread [to not freeze GUI thread while executing]) self.thread_pool = QThreadPool() # Handles to all active workers (with the idea of stopping them). Contains only workers that run loops, other # other workers are stored in different lists self.workers = [] # check this to see if stop has been requested self.stop_loop_requested = True # holds string representation of folder in which to save measurement data self.save_location = "" # keep track of number of line traces currently display. Used when loop in a loop is ran to draw the last n # line traces only self.line_trace_count = 0 # keep track of live plots in case someone closes one of them that they can be reopened self.live_plots = [] self.statusBar().showMessage("Ready") self.show() """""" """""" """""" """ User interface """ """""" """""" """""" def init_ui(self): """ Initializes the main window user interface, sets dimensions, position, etc. of a main window :return: NoneType """ # get dimensions of the monitor, and position the window accordingly _, _, width, height = QDesktopWidget().screenGeometry().getCoords() self.setGeometry(int(0.02 * width), int(0.05 * height), 640, 440) # define the size, title and icon of the window self.setMinimumSize(640, 440) self.setWindowTitle("qcodes starter") self.setWindowIcon(QtGui.QIcon("img/osciloscope_icon.png")) self.grid_layout = QGridLayout() self.splitter = QSplitter(Qt.Vertical) self.grid_layout.addWidget(self.splitter, 0, 0, 9, 6) self.cw = QWidget(self) self.cw.setLayout(self.grid_layout) self.setCentralWidget(self.cw) # Create and define table for displaying instruments added to the self.instruments dictionary label = QLabel("Instruments:") self.splitter.addWidget(label) self.instruments_table = QTableWidget(0, 3) self.splitter.addWidget(self.instruments_table) self.instruments_table.setHorizontalHeaderLabels( ("Name", "Type", "Edit")) header = self.instruments_table.horizontalHeader() header.setSectionResizeMode(0, QHeaderView.ResizeToContents) header.setSectionResizeMode(1, QHeaderView.Stretch) header.setSectionResizeMode(2, QHeaderView.ResizeToContents) self.instruments_table.setSelectionBehavior(QTableView.SelectRows) horizontal = QSplitter() # Create and define table for displaying loops added to the self.loops dictionary label = QLabel("Loops") horizontal.addWidget(label) self.splitter.addWidget(horizontal) # Button for displaying data structure of each created loop self.show_loop_details_btn = QPushButton("Show tree", self.cw) horizontal.addWidget(self.show_loop_details_btn) icon = QtGui.QIcon("img/binary_tree_icon.png") self.show_loop_details_btn.setIcon(icon) self.show_loop_details_btn.clicked.connect(self.open_tree) # simple text editor self.open_text_edit_btn = QPushButton("Text", self.cw) horizontal.addWidget(self.open_text_edit_btn) self.open_text_edit_btn.clicked.connect(self.open_text_editor) icon = QtGui.QIcon("img/text_icon.png") self.open_text_edit_btn.setIcon(icon) self.loops_table = QTableWidget(0, 4) self.loops_table.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.splitter.addWidget(self.loops_table) self.loops_table.setHorizontalHeaderLabels( ("Name", "Edit", "Run", "Delete")) header = self.loops_table.horizontalHeader() header.setSectionResizeMode(0, QHeaderView.Stretch) header.setSectionResizeMode(1, QHeaderView.ResizeToContents) header.setSectionResizeMode(2, QHeaderView.ResizeToContents) header.setSectionResizeMode(3, QHeaderView.ResizeToContents) self.instruments_table.setSelectionBehavior(QTableView.SelectRows) # Button for opening a new window that is used for connecting to instruments self.btn_add_instrument = QPushButton("Add instrument") self.grid_layout.addWidget(self.btn_add_instrument, 0, 6, 1, 2) self.btn_add_instrument.resize(200, 200) icon = QtGui.QIcon("img/osciloscope_icon.png") self.btn_add_instrument.setIcon(icon) self.btn_add_instrument.clicked.connect( lambda checked, name="DummyInstrument": self.add_new_instrument( name)) # Button to open a window that is used to create and manage loops (measurements) self.btn_setup_loops = QPushButton("Setup loops") self.grid_layout.addWidget(self.btn_setup_loops, 1, 6, 1, 2) icon = QtGui.QIcon("img/measure.png") self.btn_setup_loops.setIcon(icon) self.btn_setup_loops.clicked.connect(self.setup_loops) # Button to open a new window that is used for creating, editing and deleting dividers self.btn_attach_dividers = QPushButton("Attach dividers") self.grid_layout.addWidget(self.btn_attach_dividers, 2, 6, 1, 2) icon = QtGui.QIcon("img/rheostat_icon.png") self.btn_attach_dividers.setIcon(icon) self.btn_attach_dividers.clicked.connect(self.open_attach_divider) # text box used to input the desired name of your output file produced by the loop label = QLabel("Output file name") self.grid_layout.addWidget(label, 4, 6, 1, 1) self.output_file_name = QLineEdit() self.grid_layout.addWidget(self.output_file_name, 5, 6, 1, 2) # btn that opens file dialog for selecting a desired location where to save the ouput file of the loop self.btn_select_save_location = QPushButton("Select save location") self.grid_layout.addWidget(self.btn_select_save_location, 6, 6, 1, 2) icon = QtGui.QIcon("img/save_icon.png") self.btn_select_save_location.setIcon(icon) self.btn_select_save_location.clicked.connect( self.select_save_location) # btn for stoping all currently active loops self.stop_btn = QPushButton("STOP") self.grid_layout.addWidget(self.stop_btn, 7, 6, 1, 2) icon = QtGui.QIcon("img/cancel_1-512.png") self.stop_btn.setIcon(icon) self.stop_btn.clicked.connect(self.stop_all_workers) # run a loop with live ploting as a backgroud task (new window with self updating plot will be opened) """self.plot_btn = QPushButton("Plot", self) self.plot_btn.move(480, 340) self.plot_btn.resize(60, 40) self.plot_btn.clicked.connect(self.run_with_plot) icon = QtGui.QIcon("img/plot_icon.png") self.plot_btn.setIcon(icon)""" self.select_loop_cb = QComboBox() self.grid_layout.addWidget(self.select_loop_cb, 8, 6, 1, 1) # run a loop without displaying the live plot self.btn_run = QPushButton("Run") self.grid_layout.addWidget(self.btn_run, 8, 7, 1, 1) self.btn_run.clicked.connect(self.run_with_plot) icon = QtGui.QIcon("img/play_icon.png") self.btn_run.setIcon(icon) self.statusBar().showMessage("Ready") # Defining all shortcuts add_shortcut = QShortcut(QtGui.QKeySequence(Qt.Key_F12), self.cw) add_shortcut.activated.connect(self.setup_loops) # self.setCentralWidget(self) def init_menu_bar(self): """ Initializes menu bar, creates actions and submenus within menu bar, connects actions to menu items KNOWN PROBLEMS -> ["M3201A", "M3300A", "M4i", "ZIUHFLI"] list of instruments that produce bugs :return: NoneType """ # Create action and bind it to a function that exits the application and closes all of its windows exit_action = QAction("&Exit", self) exit_action.setShortcut("Ctrl+Q") exit_action.setStatusTip("Exit the application") exit_action.triggered.connect(self.exit) # Action for adding a new instrument start_new_measurement_menu = QMenu("Add instrument", self) start_new_measurement_action = QAction("New", self) start_new_measurement_action.setShortcut("Ctrl+M") start_new_measurement_action.setStatusTip( "Open 'Add New Instrument' window") start_new_measurement_action.triggered.connect( lambda checked, name="DummyInstrument": self.add_new_instrument( name)) start_new_measurement_menu.addAction(start_new_measurement_action) start_new_measurement_menu.addSeparator() # fetch all instruments defined in qcodes and add then to the Add Instrument menu. Clicking any of these will # open AddInstrumentWidget with data for this instrument already filled in that window path = os.path.dirname(inspect.getfile(qc)) + "\\instrument_drivers" brands = get_subfolders(path, True) for brand in brands: current_brand_menu = QMenu(brand, self) start_new_measurement_menu.addMenu(current_brand_menu) models = get_files_in_folder(path + "\\" + brand, True) for model in models: if model[0:-3] not in [ "M3201A", "M3300A", "M4i", "Keithley_2600_channels", "AWGFileParser", "Keysight_33500B_channels", "Infiniium", "KeysightAgilent_33XXX", "Model_336", "Base_SPDT", "RC_SP4T", "RC_SPDT", "USB_SPDT", "QDac_channels", "RTO1000", "ZNB", "SR860", "SR86x", "AWG5208", "AWG70000A", "AWG70002A", "Keithley_2600_channels" ]: # above is the list of instruments that produce error when attempting to create them current_model_action = QAction(model[0:-3], self) current_model_action.setData(model[0:-3]) current_brand_menu.addAction(current_model_action) current_model_action.triggered.connect( lambda checked, name=current_model_action.data( ): self.add_new_instrument(name)) else: current_model_action = QAction(model[0:-3], self) current_model_action.setEnabled(False) current_model_action.setIcon( QtGui.QIcon("img/disabled.png")) current_brand_menu.addAction(current_model_action) current_model_action.triggered.connect( lambda checked, name=current_model_action.data( ): self.add_new_instrument(name)) reopen_plot_window = QAction("Reopen plot", self) reopen_plot_window.triggered.connect(self.reopen_plot_windows) multi_param_measurement = QAction("Multi sweep", self) multi_param_measurement.triggered.connect( self.open_multi_sweep_measurement) file_menu = self.menuBar().addMenu("&File") file_menu.addAction(exit_action) file_menu.addMenu(start_new_measurement_menu) tools_menu = self.menuBar().addMenu("&Tools") tools_menu.addAction(reopen_plot_window) measurement_menu = self.menuBar().addMenu("&Measurement") measurement_menu.addAction(multi_param_measurement) """""" """""" """""" """ Data manipulation """ """""" """""" """""" def update_station_preview(self): """ When new instrument is added, add a line to instrument_table widget containing some data (name and type) about the instrument, as well as button to edit the instrument. :return: NoneType """ # Go ahead and iterate through all instruments that have been created so far and if any of those instruments # hasn't been added to the table , add it to the table for instrument in self.instruments: if instrument not in self.station_instruments: current_instrument = self.instruments[instrument] rows = self.instruments_table.rowCount() self.instruments_table.insertRow(rows) item = QTableWidgetItem(instrument) item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) self.instruments_table.setItem(rows, 0, item) item = QTableWidgetItem(str(current_instrument)) item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) self.instruments_table.setItem(rows, 1, item) current_instrument_btn = QPushButton("Edit") current_instrument_btn.clicked.connect( self.make_open_instrument_edit(instrument)) self.instruments_table.setCellWidget(rows, 2, current_instrument_btn) self.edit_button_dict[instrument] = current_instrument_btn self.station_instruments[instrument] = self.instruments[ instrument] # Also bind a shortcut for opening that instrument coresponding to the number of the row that the # instrument is displayed in (Example: instrument in row 1 will have shortcut F1, row 2 -> F2, ....) key = "Key_F" + str(rows + 1) key_class = getattr(Qt, key) add_shortcut = QShortcut(QtGui.QKeySequence(key_class), self) add_shortcut.activated.connect( self.make_open_instrument_edit(instrument)) def update_loops_preview(self, edit=False): """ This function is called from child class (SetupLoopsWidget) each time a new loop is created. Adds a loop to a loops_table widget which contains all loops as well as buttons to "Edit", "Run" and "Delete" a loop. Edit: opens "SetupLoopsWidget" with data from specified loop Run: runs the loop with current data (with plot) Delete: removes a loop from the table and from the self.loops dictionary, and also deletes action from self.actions that coresponds to this loop. :return: NoneType """ # Iterate through all loops that have been created and added to self.loops dictionary, if any of those has not # been added to loops table (and shown loops dict) then add it to both so that it is visible in the window for name, loop in self.loops.items(): if name not in self.shown_loops: rows = self.loops_table.rowCount() self.loops_table.insertRow(rows) # Model a string that will display loop values in the table. # Format: loop_name[lower_limit, upper_limit, num_of_steps, delay].action_parameter lower = str(loop.sweep_values[0]) upper = str(loop.sweep_values[-1]) steps = str(len(loop.sweep_values)) delay = str(loop.delay) display_string = "{} [{}, {}, {}, {}].{}".format( name, lower, upper, steps, delay, str(loop.actions[0])) item = QTableWidgetItem(display_string) item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) self.loops_table.setItem(rows, 0, item) current_loop_btn = QPushButton("Edit") current_loop_btn.resize(35, 20) current_loop_btn.clicked.connect( lambda checked, loop_name=name: self.setup_loops(loop_name )) self.loops_table.setCellWidget(rows, 1, current_loop_btn) # Button within a table that runs a loop that is in the same table row as the button run_current_loop_btn = QPushButton("Run") run_current_loop_btn.resize(35, 20) run_current_loop_btn.clicked.connect( lambda checked, loop_name=name: self.run_specific_loop( loop_name)) self.loops_table.setCellWidget(rows, 2, run_current_loop_btn) # Button within the table that removes a loop that is in the same row as the button delete_current_loop = QPushButton("Delete") delete_current_loop.resize(35, 20) delete_current_loop.clicked.connect( self.make_delete_loop(name, item)) self.loops_table.setCellWidget(rows, 3, delete_current_loop) self.shown_loops.append(name) self.select_loop_cb.addItem(name, loop) # Create a shortcut for opening each loop. Loop in row1 opens with key combo: CTRL + F1, row2: CTRL+F2 key_combo_string = "Ctrl+F" + str(rows + 1) add_shortcut = QShortcut(QtGui.QKeySequence(key_combo_string), self) add_shortcut.activated.connect( lambda loop_name=name: self.setup_loops(loop_name)) elif edit == name: for i in range(self.loops_table.rowCount()): item = self.loops_table.item(i, 0) if item.text()[:len(name) + 1] == name + " ": rows = i break # if a loop is being edited, just update the values of the edited loop lower = str(loop.sweep_values[0]) upper = str(loop.sweep_values[-1]) steps = str(len(loop.sweep_values)) delay = str(loop.delay) display_string = "{} [{}, {}, {}, {}].{}".format( name, lower, upper, steps, delay, str(loop.actions[0])) item = QTableWidgetItem(display_string) item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) self.loops_table.setItem(rows, 0, item) self.loops_table.removeCellWidget(rows, 3) delete_current_loop = QPushButton("Delete") delete_current_loop.resize(35, 20) delete_current_loop.clicked.connect( self.make_delete_loop(name, item)) self.loops_table.setCellWidget(rows, 3, delete_current_loop) def run_qcodes(self, with_plot=False): """ Runs qcodes with specified instruments and parameters. Checks for errors in data prior to runing qcodes Adds all instruments to qc.Station and runs the last created loop (i think this is not good, but hey theres a button for each loop to run that specific loop) Loop is ran in a separate thread so that it does not block GUI thread (and the program) :param with_plot: if set to true, runs (and saves) live plot while measurement is running :return: NoneType """ self.stop_loop_requested = False self.loop_started.emit() self.line_trace_count = 0 # first create a station and add all instruments to it, to have the data available in the output files station = qc.Station() for name, instrument in self.instruments.items(): station.add_component(instrument, name) # grab the last action added to the actions list. Set its data_set to None in case that loop has already been # ran. Create a new data set with the name and location provided by user input if len(self.actions): loop = self.actions[-1] loop.data_set = None # adjust save location of the file if self.save_location != "": loc_provider = qc.data.location.FormatLocation( fmt=self.save_location + '/{date}/#{counter}_{name}_{time}') qc.data.data_set.DataSet.location_provider = loc_provider data = loop.get_data_set(name=self.output_file_name.text()) # Check if the function was called with plot in background, if it was, create a new plot, delete backgroud # action of the loop (if a loop has been ran before with a background action [loop cannot have more then # 1 background action]), attach a new background action and run a loop by calling a worker to run it in a # separate thread if with_plot: # if you are running loop in a loop then create one more graph that will display 10 most recent line # traces if isinstance(loop.actions[0], ActiveLoop): line_traces_plot = qc.QtPlot(fig_x_position=0.05, fig_y_position=0.4, window_title="Line traces") self.live_plots.append(line_traces_plot) if len(loop.actions) < 3: loop.actions.append( Task(lambda: self.update_line_traces( line_traces_plot, data, parameter_name))) else: loop.actions[-1] = Task( lambda: self.update_line_traces( line_traces_plot, data, parameter_name)) loop.actions[0].progress_interval = None else: if loop.progress_interval is None: loop.progress_interval = 20 parameter = get_plot_parameter(loop) plot = qc.QtPlot(fig_x_position=0.05, fig_y_position=0.4, window_title=self.output_file_name.text()) self.live_plots.append(plot) parameter_name = str(parameter) plot.add(getattr(data, parameter_name)) # loop.with_bg_task(plot.update, plot.save).run(use_threads=True) loop.bg_task = None worker = Worker( loop.with_bg_task(plot.update, plot.save).run, False) else: # loop.run(use_threads=True) -> this has something to do with multiple gets at the same time # i guess it would get them all at the same time instead of one by one # otherwise if plot was not requested, just run a loop (also in separate thread) worker = Worker(loop.run, False) self.workers.append(worker) # connect the signals of a worker worker.signals.result.connect(print_output) worker.signals.finished.connect(self.cleanup) worker.signals.progress.connect(progress_func) # start the worker del self.workers[:] # starting live mode of all opened instruments # commented cause it causes collision in the instrument when two different sources send commands to the # instrument. Sometimes this causes crashing of the loop. """for widget in self.active_isntruments: # only if that instrument has this parameter, then start its live mode if self.actions[-1].sweep_values.name in widget.textboxes.keys(): widget.toggle_live()""" self.disable_run_buttons() self.thread_pool.start(worker) # Just in case someone presses run with no loops created else: show_error_message("Oops !", "Looks like there is no loop to be ran !") def run_with_plot(self): """ Call self.run_qcodes() with parameter with_plot set to True :return: NoneType """ self.run_qcodes(with_plot=True) @pyqtSlot() def select_save_location(self): """ Opens a QFileDialog for selecting a location on local machine, path to the selected location is set as a save location for results of the measurment :return: NoneType """ self.save_location = str( QFileDialog.getExistingDirectory(self, "Select Directory")) """""" """""" """""" """ Helper functions """ """""" """""" """""" @pyqtSlot() def exit(self): """ Close the main window :return: NoneType """ # Close all the instruments not to leave any hanging tails for name, instrument in self.instruments.items(): print("Closing", instrument) instrument.close() # Close all other windows that are currently opened app = QtGui.QGuiApplication.instance() app.closeAllWindows() def closeEvent(self, a0: QtGui.QCloseEvent): are_you_sure = QMessageBox() close = are_you_sure.question( self, "Don't do it.", "Are you sure you want to close all windows and exit the application ?", are_you_sure.Yes | are_you_sure.No) if close == are_you_sure.Yes: self.exit() a0.accept() else: a0.ignore() return @pyqtSlot() def add_new_instrument(self, name): """ Opens a new Widget (window) with text inputs for parameters of an instrument, creates new instrument(s) :return: NoneType """ # AddInstrumentWidget need access to self.instruments dictionary in order to be able to add any newly created # instruments to it self.add_instrument = Widget(self.instruments, parent=self, default=name) self.add_instrument.submitted.connect(self.update_station_preview) self.add_instrument.show() @pyqtSlot() def open_tree(self): """ Open a TreeView to inspect created loops :return: NoneType """ self.view_tree = ViewTree( {name: loop.snapshot_base() for name, loop in self.loops.items()}) self.view_tree.show() @pyqtSlot() def setup_loops(self, loop_name=""): """ Open a new widget for creating loops based on instruments added to "instruments" dictionary trough AddInstrumentWidget. Loops created with this widget are added to MainWindows "loops" dictionary, also for each loop an action to be executed is created and added to MainWindows "actions" list :return: """ self.setup_loops_widget = LoopsWidget(self.instruments, self.dividers, self.loops, self.actions, parent=self, loop_name=loop_name) self.setup_loops_widget.show() @pyqtSlot() def open_text_editor(self): """ Open a simple text editor as a new widget (possible custom tool creation) :return: NoneType """ msg = random[randint(1, len(random))] show_error_message("Do you need some motivation ?", msg) @pyqtSlot() def open_attach_divider(self): """ Opens a new widget for setting up dividers. Can attach a divider to any parameter of any instrument People are gonna add dividers to parameters that cannot have divider (like IDN) im sure of this. God help them. :return: NoneType """ self.attach_divider_widget = DividerWidget(self.instruments, self.dividers, parent=self) self.attach_divider_widget.show() @pyqtSlot() def open_multi_sweep_measurement(self, name=""): self.msm = MultiSweep(self.instruments, self.dividers, self.loops, self.actions, parent=self, loop_name=name) self.msm.show() def stop_all_workers(self): """ Reworked: Stops all instruments that are currently being live updated and returns them to static mode :return: """ print(self.workers) print("Emmiting the signal to all workers") for worker in self.instrument_workers: worker.stop_requested = True for widget in self.active_isntruments: if widget.live: widget.toggle_live() self.stop_loop_requested = True self.enable_run_buttons() # This is a function factory (wow, i'm so cool, i made a function factory) def make_open_instrument_edit(self, instrument): """ Hi, i am a function factory, and for each button you see next to an instrument i create a new function to edit that particular instrument. After creating that function i return it so it can be called with a click on the button. :param instrument: refers to a name of the instrument to be edited :return: newly created function to open "EditInstrumentWidget" with this particular instrument """ def open_instrument_edit(): """ Open a new widget and pass it an instrument that can be edited through the newly opened widget :return: NoneType """ if hasattr(self.instruments[instrument], "timeout"): self.instruments[instrument].set("timeout", 50) # Parameters: # self. instruments: widget needs access to all instruments to be able to edit them and add new ones # self.dividers: widget needs access to dividers to be able to display them if they are attached # self.active_instruments: list of instrument edit windows that are opened, to be able to remove self # from that list when closing the window # self.thread_pool: To be able to run functions in a shared thread pool (get_all, set_all) # parent: reference to this widget # instrument_name: name of the instrument that is being edited, to be able to fetch it from instruments # dictionary that is also being passed to this widget self.edit_instrument = EditInstrumentWidget( self.instruments, self.dividers, self.active_isntruments, self.thread_pool, parent=self, instrument_name=instrument) # Add newly created window to a list of active windows self.active_isntruments.append(self.edit_instrument) self.edit_instrument.show() return open_instrument_edit def run_specific_loop(self, loop_name): """ Place the action that coresponds to this loop to the last place in the actions queue so that its the one that gets ran by the run button, and then run it ... d'oh :param loop_name: name of the loop that is supposed to be ran :return: NoneType """ # since name of the loop is a parameter of this function, get the loop from loops, find it in the actions list # put it in the last place of that list (remember, the last one is the one that get run), and then run it loop = self.loops[loop_name] loop_index = self.actions.index(loop) self.actions[loop_index], self.actions[-1] = self.actions[ -1], self.actions[loop_index] self.run_with_plot() def make_delete_loop(self, loop_name, item): """ Function factory, creates functions that delete each individual loop from tableWidget for loops :param loop_name: name of the loop (to be able to remove it from loops dictionary) :param item: use this item to find which row of the tabelWidget to delete :return: pointer to the newly created function """ def delete_loop(): """ Remove a loop from loops_table widget :return: NoneType """ self.loops_table.removeRow(self.loops_table.row(item)) if loop_name in self.loops: if self.loops[loop_name] in self.actions: self.actions.remove(self.loops[loop_name]) del self.loops[loop_name] return delete_loop def check_stop_request(self): """ This function is passed to a qcodes Task() to be checked on every measure point of the loop. Function checks if the class member stop_loop_requested is set to true, and if it is it raises an exception that stops the qcodes loop. :return: """ if self.stop_loop_requested is True: self.enable_run_buttons() raise _QcodesBreak def disable_run_buttons(self): """ This function is used to disable running other loops when one of the loops has started. Multiple loops running at the same time might try to send commands to the same instrument and cause an error. :return: NoneType """ self.btn_run.setDisabled(True) for row_index in range(self.loops_table.rowCount()): run_button = self.loops_table.cellWidget(row_index, 2) run_button.setDisabled(True) delete_button = self.loops_table.cellWidget(row_index, 3) delete_button.setDisabled(True) edit_button = self.loops_table.cellWidget(row_index, 1) edit_button.setDisabled(True) def enable_run_buttons(self): """ After a loop has finished enable running other loops. :return: NoneType """ self.btn_run.setDisabled(False) for row_index in range(self.loops_table.rowCount()): run_button = self.loops_table.cellWidget(row_index, 2) run_button.setDisabled(False) delete_button = self.loops_table.cellWidget(row_index, 3) delete_button.setDisabled(False) edit_button = self.loops_table.cellWidget(row_index, 1) edit_button.setDisabled(False) def cleanup(self): """ This function is called when a thread is finished to stop the workers and re enable run buttons. :return: """ self.stop_all_workers() self.enable_run_buttons() self.loop_finished.emit() self.line_trace_count = 0 self.live_plots = [] def run_with_livedata(self): """ ################################################################################################################ LEGACY METHOD. Was used when i had no idea that each parameter hold the data of its last value so i dont need to get it everytime from the physical instrument, i can just get it from tha parameter object. ################################################################################################################ This function appends a task to a loop. Task updates value of instruments parameter every iteration of the loop. After appending the task the loop gets started with plot option turned on. :return: NoneType """ loop_name = self.select_loop_cb.currentText() loop = self.loops[loop_name] tsk = Task(self.update_opened_instruments) loop.actions.append(tsk) loop_index = self.actions.index(loop) self.actions[loop_index], self.actions[-1] = self.actions[ -1], self.actions[loop_index] self.run_with_plot() def update_opened_instruments(self): """ ################################################################################################################ LEGACY METHOD. Was used when i had no idea that each parameter hold the data of its last value so i dont need to get it everytime from the physical instrument, i can just get it from tha parameter object. ################################################################################################################ Function that updates the value of a parameter that is being swept if the EditWindow of that window is opened. :return: NoneType """ for widget in self.active_isntruments: # only if that instrument has this parameter, then start its live mode name = self.actions[-1].sweep_values.name if name in widget.textboxes.keys(): widget.update_parameters_data(name=name) def update_line_traces(self, plot, dataset, parameter_name): """ Add 10 line traces to a graph, and then clear the graph and add 10 new line traces. :param plot: Instance of a graph that we want to add a line trace eto :param dataset: Dataset from which we extract the data :param parameter_name: Name of the parameter that is being plotted :return: NoneType """ if self.line_trace_count % 10 == 0: plot.clear() plot.add(getattr(dataset, parameter_name)[self.line_trace_count]) print(self.line_trace_count) self.line_trace_count += 1 def resize_for_loop(self, decrease=False): """ Legacy method, not used anymore since switching to layouts Method that resizes the window when a loop is added/removed from it. :param decrease: If loop is being removed decreas will be set to True and window size will be decreased :return: NoneType """ if decrease == False: if self.loops_table.rowCount() > 2: self.loops_table.resize(self.loops_table.width(), self.loops_table.height() + 30) self.resize(self.width(), self.height() + 30) else: if self.loops_table.rowCount() > 1: self.loops_table.resize(self.loops_table.width(), self.loops_table.height() - 30) self.resize(self.width(), self.height() - 30) def reopen_plot_windows(self): for plot in self.live_plots: plot.win.show() print(plot)
class PaletteDocker(DockWidget): # Init the docker def __init__(self): super(PaletteDocker, self).__init__() # make base-widget and layout widget = QWidget() layout = QVBoxLayout() buttonLayout = QHBoxLayout() widget.setLayout(layout) self.setWindowTitle(i18n("Python Palette Docker")) # Make a combobox and add palettes self.cmb_palettes = QComboBox() allPalettes = Application.resources("palette") for palette_name in allPalettes: self.cmb_palettes.addItem(palette_name) self.cmb_palettes.model().sort(0) if len(allPalettes.keys()) > 0: self.currentPalette = Palette(list(allPalettes.values())[0]) else: self.currentPalette = None self.cmb_palettes.currentTextChanged.connect(self.slot_paletteChanged) layout.addWidget(self.cmb_palettes) # add combobox to the layout self.paletteView = PaletteView() self.paletteView.setPalette(self.currentPalette) layout.addWidget(self.paletteView) self.paletteView.entrySelectedForeGround.connect( self.slot_swatchSelected) self.colorComboBox = QComboBox() self.colorList = list() buttonLayout.addWidget(self.colorComboBox) self.bnSetColor = QToolButton() self.bnSetColor.setText(i18n("Set")) self.bnSetColor.clicked.connect(self.slot_get_color_from_combobox) buttonLayout.addWidget(self.bnSetColor) self.addEntry = QAction(self) self.addEntry.setIconText(i18n("+")) self.addEntry.triggered.connect(self.slot_add_entry) self.addGroup = QAction(self) self.addGroup.triggered.connect(self.slot_add_group) self.addGroup.setText(i18n("Add Group")) self.addGroup.setIconText(str("\U0001F4C2")) self.removeEntry = QAction(self) self.removeEntry.setText(i18n("Remove Entry")) self.removeEntry.setIconText("-") self.removeEntry.triggered.connect(self.slot_remove_entry) addEntryButton = QToolButton() addEntryButton.setDefaultAction(self.addEntry) buttonLayout.addWidget(addEntryButton) addGroupButton = QToolButton() addGroupButton.setDefaultAction(self.addGroup) buttonLayout.addWidget(addGroupButton) removeEntryButton = QToolButton() removeEntryButton.setDefaultAction(self.removeEntry) buttonLayout.addWidget(removeEntryButton) # QActions self.extra = QToolButton() self.editPaletteData = QAction(self) self.editPaletteData.setText(i18n("Edit Palette Settings")) self.editPaletteData.triggered.connect(self.slot_edit_palette_data) self.extra.setDefaultAction(self.editPaletteData) buttonLayout.addWidget(self.extra) self.actionMenu = QMenu() self.exportToGimp = QAction(self) self.exportToGimp.setText(i18n("Export as GIMP Palette File")) self.exportToGimp.triggered.connect(self.slot_export_to_gimp_palette) self.exportToInkscape = QAction(self) self.exportToInkscape.setText( i18n("Export as Inkscape SVG with Swatches")) self.exportToInkscape.triggered.connect( self.slot_export_to_inkscape_svg) self.sortColors = QAction(self) self.sortColors.setText(i18n("Sort Colors")) self.sortColors.triggered.connect(self.slot_sort_colors) self.actionMenu.addAction(self.editPaletteData) self.actionMenu.addAction(self.exportToGimp) self.actionMenu.addAction(self.exportToInkscape) # self.actionMenu.addAction(self.sortColors) self.extra.setMenu(self.actionMenu) layout.addLayout(buttonLayout) self.slot_fill_combobox() self.setWidget(widget) # add widget to the docker def slot_paletteChanged(self, name): allPalettes = Application.resources("palette") if len(allPalettes) > 0 and name in allPalettes: self.currentPalette = Palette( Application.resources("palette")[name]) self.paletteView.setPalette(self.currentPalette) self.slot_fill_combobox() @pyqtSlot('KisSwatch') def slot_swatchSelected(self, entry): if (self.canvas()) is not None: if (self.canvas().view()) is not None: name = entry.name() if len(entry.id) > 0: name = entry.id() + " - " + entry.name() if len(name) > 0: if name in self.colorList: self.colorComboBox.setCurrentIndex( self.colorList.index(name)) color = self.currentPalette.colorForEntry(entry) self.canvas().view().setForeGroundColor(color) def slot_fill_combobox(self): '''A function for making a combobox with the available colors. We use QCompleter on the colorComboBox so that people can type in the name of a color to select it. This is useful for people with carefully made palettes where the colors are named properly, which makes it easier for them to find colors. ''' if self.currentPalette is None: pass self.colorComboBox.clear() self.colorList = list() # palette = self.currentPalette # for info in palette.infoList(): # entry = info.swatch # color = palette.colorForEntry(entry).colorForCanvas(self.canvas()) # colorSquare = QPixmap(12, 12) # if entry.spotColor() is True: # img = colorSquare.toImage() # circlePainter = QPainter() # img.fill(self.colorComboBox.palette().color(QPalette.Base)) # circlePainter.begin(img) # brush = QBrush(Qt.SolidPattern) # brush.setColor(color) # circlePainter.setBrush(brush) # circlePainter.pen().setWidth(0) # circlePainter.drawEllipse(0, 0, 11, 11) # circlePainter.end() # colorSquare = QPixmap.fromImage(img) # else: # colorSquare.fill(color) # name = entry.name() # if len(entry.id()) > 0: # name = entry.id() + " - " + entry.name() # self.colorList.append(name) # self.colorComboBox.addItem(QIcon(colorSquare), name) self.colorComboBox.setEditable(True) self.colorComboBox.setInsertPolicy(QComboBox.NoInsert) self.colorComboBox.completer().setCompletionMode( QCompleter.PopupCompletion) self.colorComboBox.completer().setCaseSensitivity(False) self.colorComboBox.completer().setFilterMode(Qt.MatchContains) def slot_get_color_from_combobox(self): if self.currentPalette is not None: entry = self.currentPalette.colorSetEntryByIndex( self.colorComboBox.currentIndex()) self.slot_swatchSelected(entry) def slot_add_entry(self): if (self.canvas()) is not None: if (self.canvas().view()) is not None: color = self.canvas().view().foregroundColor() success = self.paletteView.addEntryWithDialog(color) if success is True: self.slot_fill_combobox() def slot_add_group(self): success = self.paletteView.addGroupWithDialog() if success is True: self.slot_fill_combobox() def slot_remove_entry(self): success = self.paletteView.removeSelectedEntryWithDialog() if success is True: self.slot_fill_combobox() def slot_edit_palette_data(self): '''A function for giving a gui to edit palette metadata... I also want this to be the way to edit the settings of the palette docker. ''' dialog = QDialog(self) tabWidget = QTabWidget() dialog.setWindowTitle(i18n("Edit Palette Data")) dialog.setLayout(QVBoxLayout()) dialog.layout().addWidget(tabWidget) paletteWidget = QWidget() paletteWidget.setLayout(QVBoxLayout()) tabWidget.addTab(paletteWidget, i18n("Palette Data")) paletteName = QLineEdit() paletteName.setText(self.cmb_palettes.currentText()) paletteWidget.layout().addWidget(paletteName) paletteColumns = QSpinBox() paletteColumns.setValue(self.currentPalette.columnCount()) paletteWidget.layout().addWidget(paletteColumns) paletteComment = QPlainTextEdit() paletteComment.appendPlainText(self.currentPalette.comment()) paletteWidget.layout().addWidget(paletteComment) buttons = QDialogButtonBox(QDialogButtonBox.Ok) dialog.layout().addWidget(buttons) buttons.accepted.connect(dialog.accept) # buttons.rejected.connect(dialog.reject()) if dialog.exec_() == QDialog.Accepted: Resource = Application.resources("palette")[ self.cmb_palettes.currentText()] Resource.setName(paletteName.text()) self.currentPalette = Palette(Resource) self.currentPalette.setColumnCount(paletteColumns.value()) self.paletteView.setPalette(self.currentPalette) self.slot_fill_combobox() self.currentPalette.setComment(paletteComment.toPlainText()) self.currentPalette.save() def slot_export_to_gimp_palette(self): palette_exporter_gimppalette.gimpPaletteExporter( self.cmb_palettes.currentText()) def slot_export_to_inkscape_svg(self): palette_exporter_inkscapeSVG.inkscapeSVGExporter( self.cmb_palettes.currentText()) def slot_sort_colors(self): colorSorter = palette_sortColors.sortColors( self.cmb_palettes.currentText()) self.paletteView.setPalette(colorSorter.palette()) def canvasChanged(self, canvas): self.cmb_palettes.clear() allPalettes = Application.resources("palette") for palette_name in allPalettes: self.cmb_palettes.addItem(palette_name) self.cmb_palettes.model().sort(0) if self.currentPalette is None and len(allPalettes.keys()) > 0: self.currentPalette = Palette(list(allPalettes.values())[0])
class SaveWindow(QDialog): def __init__(self, parent=None, file_name = None, MeasurementsLeft = None, MeasurementsRight = None, MeasurementsDeviation = None, MeasurementsPercentual = None): super(SaveWindow, self).__init__(parent) self._NewFile = True #This variable defines if the user is #trying to save results in a new file or to a #append results to an existing file self._name_of_file = file_name #this variable stores the name of the #file, it won't be modified during #execution self._file_name = file_name #this variable stores the name of the #file to be displayed. It will be #modified during execution filename, file_extension = os.path.splitext(self._file_name) delimiter = os.path.sep temp=filename.split(delimiter) photo_location = temp[0:-1] photo_location = delimiter.join(photo_location) photo_name=temp[-1] #measurements self._MeasurementsLeft = MeasurementsLeft self._MeasurementsRight = MeasurementsRight self._MeasurementsDeviation = MeasurementsDeviation self._MeasurementsPercentual = MeasurementsPercentual self._file_name = photo_name #path + file name self._photo_location = photo_location self._ID = photo_name #unique identifier self._prevspost = '' #pre-treatment vs post-treatment self._surgery = '' #type of surgery self._expression = '' #type of expression self._other = '' #additional comments self._file_to_save = '' #file to add data self.initUI() def initUI(self): self.setWindowTitle('Save') if os.name is 'posix': #is a mac or linux scriptDir = os.path.dirname(sys.argv[0]) else: #is a windows scriptDir = os.getcwd() self.setWindowIcon(QtGui.QIcon(scriptDir + os.path.sep + 'include' +os.path.sep +'icon_color'+ os.path.sep + 'save_icon.ico')) self.main_Widget = QtWidgets.QWidget(self) spacerh = QtWidgets.QWidget(self) spacerh.setFixedSize(10,0) spacerv = QtWidgets.QWidget(self) spacerv.setFixedSize(0,10) file = QLabel('File Name:') self._file = QLineEdit(self) self._file.setText(self._file_name) self.SelectFolderButton = QPushButton('Select &Folder', self) self.SelectFolderButton.setFixedWidth(150) self.SelectFolderButton.clicked.connect(self.SelectFolder) self._SelectFolder = QLineEdit(self) self._SelectFolder.setText(self._photo_location) self._SelectFolder.setFixedWidth(350) NewFileBox = QGroupBox('Create new File') NewFileBoxLayout = QGridLayout() NewFileBoxLayout.addWidget(file,0,0) NewFileBoxLayout.addWidget(spacerh,0,1) NewFileBoxLayout.addWidget(self._file,0,2) NewFileBoxLayout.addWidget(spacerv,1,0) NewFileBoxLayout.addWidget(self.SelectFolderButton,2,0) NewFileBoxLayout.addWidget(self._SelectFolder,2,2) NewFileBox.setLayout(NewFileBoxLayout) SelectFileButton = QPushButton('&Select File', self) SelectFileButton.setFixedWidth(150) SelectFileButton.clicked.connect(self.SelectFile) self._SelectFile = QLineEdit(self) self._SelectFile.setText(self._file_to_save) AppendFileBox = QGroupBox('Append to Existing File') AppendFileBoxLayout = QGridLayout() AppendFileBoxLayout.addWidget(SelectFileButton,0,0) AppendFileBoxLayout.addWidget(spacerh,0,1) AppendFileBoxLayout.addWidget(self._SelectFile,0,2) AppendFileBox.setLayout(AppendFileBoxLayout) Identifier = QLabel('Photo Identifier:') Identifier.setFixedWidth(120) self._Identifier = QLineEdit(self) self._Identifier.setText(self._ID) PrevsPost = QLabel('Pre or Post Procedure:') self._PrevsPost = QComboBox() self._PrevsPost.setFixedWidth(110) self._PrevsPost.addItem('') self._PrevsPost.addItem('Pre - Procedure') self._PrevsPost.addItem('Post - Procedure') SurgeryType = QLabel('Procedure:') self._SurgeryType = QLineEdit(self) self._SurgeryType.setText(self._surgery) ExpressionType = QLabel('Expression:') self._ExpressionType = QLineEdit(self) self._ExpressionType.setText(self._expression) AddtitionalComments = QLabel('Addtitional Comments:') self._AddtitionalComments = QLineEdit(self) self._AddtitionalComments.setText(self._other) AdditionalInformationBox = QGroupBox('Optional Information') AdditionalInformationBoxLayout = QGridLayout() AdditionalInformationBoxLayout.addWidget(Identifier,0,0) AdditionalInformationBoxLayout.addWidget(spacerh,0,1) AdditionalInformationBoxLayout.addWidget(self._Identifier,0,2) AdditionalInformationBoxLayout.addWidget(spacerv,1,0) AdditionalInformationBoxLayout.addWidget(PrevsPost,2,0) AdditionalInformationBoxLayout.addWidget(self._PrevsPost,2,2) #AdditionalInformationBoxLayout.addWidget(spacerv,3,0) AdditionalInformationBoxLayout.addWidget(SurgeryType,4,0) AdditionalInformationBoxLayout.addWidget(self._SurgeryType,4,2) #AdditionalInformationBoxLayout.addWidget(spacerv,5,0) AdditionalInformationBoxLayout.addWidget(ExpressionType,6,0) AdditionalInformationBoxLayout.addWidget(self._ExpressionType,6,2) #AdditionalInformationBoxLayout.addWidget(spacerv,7,0) AdditionalInformationBoxLayout.addWidget(AddtitionalComments,8,0) AdditionalInformationBoxLayout.addWidget(self._AddtitionalComments,8,2) AdditionalInformationBox.setLayout(AdditionalInformationBoxLayout) SaveButton = QPushButton('&Save', self) SaveButton.setFixedWidth(150) SaveButton.clicked.connect(self.Save) CancelButton = QPushButton('&Cancel', self) CancelButton.setFixedWidth(150) CancelButton.clicked.connect(self.Cancel) ButtonBox = QGroupBox('') ButtonBoxLayout = QGridLayout() ButtonBoxLayout.addWidget(SaveButton,0,0,QtCore.Qt.AlignCenter) ButtonBoxLayout.addWidget(spacerh,0,1) ButtonBoxLayout.addWidget(CancelButton,0,2,QtCore.Qt.AlignCenter) ButtonBox.setLayout(ButtonBoxLayout) ButtonBox.setStyleSheet("QGroupBox { border: 0px solid gray;}"); layout = QGridLayout() layout.addWidget(NewFileBox,0,0,2,2) layout.addWidget(spacerv,1,0) layout.addWidget(AppendFileBox,2,0,1,2) layout.addWidget(AdditionalInformationBox,4,0,8,2) layout.addWidget(ButtonBox,17,0,1,2) self.setLayout(layout) #self.show() def Cancel(self): self.close() def SelectFolder(self): name = QtWidgets.QFileDialog.getExistingDirectory(self, 'Select directory') if not name: pass else: if not self._SelectFolder.isEnabled(): self._file.setEnabled(True) self._SelectFolder.setEnabled(True) self._SelectFile.setText('') filename, file_extension = os.path.splitext(self._name_of_file) delimiter = os.path.sep temp=filename.split(delimiter) photo_name=temp[-1] self._file.setText(photo_name) name = os.path.normpath(name) self._photo_location = name self._SelectFolder.setText(self._photo_location) self._NewFile = True #a new file will be created self.update() def SelectFile(self): name,_ = QtWidgets.QFileDialog.getOpenFileName( self,'Load File', '',"Excel Spreadsheet (*.xls *.xlsx)") if not name: pass else: name = os.path.normpath(name) delimiter = os.path.sep filename, file_extension = os.path.splitext(name) temp=filename.split(delimiter) photo_location = temp[0:-1] photo_location = delimiter.join(photo_location) photo_name=temp[-1] self._file_name = photo_name self._file.setText(self._file_name) self._file.setEnabled(False) self._photo_location = photo_location self._SelectFolder.setText(self._photo_location) self._SelectFolder.setEnabled(False) #self.SelectFolderButton.setEnabled(False) self._file_to_save = name self._SelectFile.setText(self._file_to_save) self._NewFile = False #data will be appended to an exisiting file self.update() def Save(self): number_of_measurements = 10 Columns = ['Right','Left','Deviation (absolute)','Deviation (percent)'] Columns = Columns * number_of_measurements Columns.insert(0,'') Columns.insert(0,'') Columns.insert(0,'') Columns.insert(0,'') Columns.append('') temp = ['Brow Height', 'Marginal Reflex Distance 1', 'Marginal Reflex Distance 2', 'Palpebral Fissure Height', 'Commisure Excursion', 'Commisure Height Deviation', 'Smile Angle', 'Upper Lip Height Deviation', 'Dental Show', 'Lower Lip Height Deviation'] number_of_repetitions=4 Header = [item for item in temp for i in range(number_of_repetitions)] Header.insert(0,'Expression') Header.insert(0,'Procedure') Header.insert(0,'Pre vs Post Procedure') Header.insert(0,'Unique Identifier') Header.append('Additional Comments') #measurements elements = ['BH', 'MRD1', 'MRD2', 'PFH', 'CE', 'CH', 'SA', 'UVH', 'DS', 'LVH'] MeasurementsLeft = self._MeasurementsLeft MeasurementsRight = self._MeasurementsRight MeasurementsDeviation = self._MeasurementsDeviation MeasurementsPercentual = self._MeasurementsPercentual BH = np.array([[MeasurementsRight.BrowHeight,MeasurementsLeft.BrowHeight,MeasurementsDeviation.BrowHeight,MeasurementsPercentual.BrowHeight]],dtype=object) #BH=np.array([[1,1,1,1]],dtype = object) MRD1 = np.array([[MeasurementsRight.MarginalReflexDistance1, MeasurementsLeft.MarginalReflexDistance1,MeasurementsDeviation.MarginalReflexDistance1,MeasurementsPercentual.MarginalReflexDistance1]], dtype=object) #MRD1=np.array([[1,1,1,1]],dtype = object) MRD2 = np.array([[MeasurementsRight.MarginalReflexDistance2, MeasurementsLeft.MarginalReflexDistance2,MeasurementsDeviation.MarginalReflexDistance2,MeasurementsPercentual.MarginalReflexDistance2]],dtype=object) #MRD2=np.array([[1,1,1,1]],dtype = object) PFH = np.array([[MeasurementsRight.PalpebralFissureHeight, MeasurementsLeft.PalpebralFissureHeight,MeasurementsDeviation.PalpebralFissureHeight,MeasurementsPercentual.PalpebralFissureHeight]],dtype=object) CE = np.array([[MeasurementsRight.CommissureExcursion, MeasurementsLeft.CommissureExcursion,MeasurementsDeviation.CommissureExcursion,MeasurementsPercentual.CommissureExcursion]],dtype=object) #CE=np.array([[1,1,1,1]],dtype = object) CH = np.array([['', '',MeasurementsDeviation.CommisureHeightDeviation,'']],dtype=object) #CH=np.array([[1,1,1,1]],dtype = object) SA = np.array([[MeasurementsRight.SmileAngle, MeasurementsLeft.SmileAngle,MeasurementsDeviation.SmileAngle,MeasurementsPercentual.SmileAngle]],dtype=object) #SA=np.array([[1,1,1,1]],dtype = object) UVH = np.array([['', '',MeasurementsDeviation.UpperLipHeightDeviation,'']],dtype=object) #UVH=np.array([[1,1,1,1]],dtype = object) DS = np.array([[MeasurementsRight.DentalShow, MeasurementsLeft.DentalShow,MeasurementsDeviation.DentalShow,MeasurementsPercentual.DentalShow]],dtype=object) #DS=np.array([[1,1,1,1]],dtype = object) LVH = np.array([['', '',MeasurementsDeviation.LowerLipHeightDeviation,'']],dtype=object) #LVH=np.array([[1,1,1,1]],dtype = object) UI = np.array([[self._Identifier.text()]],dtype = object) #UI = np.array([['uno']],dtype = object) PvsP = np.array([[str(self._PrevsPost.currentText())]],dtype = object) #PvsP = np.array([['dos']],dtype = object) PC = np.array([[self._SurgeryType.text()]],dtype = object) #PC = np.array([['tres']],dtype = object) EX = np.array([[self._ExpressionType.text()]],dtype = object) #EX = np.array([['cuatro']],dtype = object) AD = np.array([[self._AddtitionalComments.text()]],dtype = object) #AD = np.array([['cinco']],dtype = object) fill= UI fill= np.append(fill, PvsP, axis = 1) fill= np.append(fill, PC, axis = 1) fill= np.append(fill, EX, axis = 1) for i in elements: fill = np.append(fill, eval(i), axis = 1) fill= np.append(fill, AD, axis = 1) if self._NewFile: #the user wants to create a new file filename, file_extension = os.path.splitext(self._name_of_file ) delimiter = os.path.sep temp=filename.split(delimiter) photo_name=temp[-1] + file_extension file_no_ext = os.path.join(str(self._SelectFolder.text()),str(self._file.text())) Index = [photo_name] #create data frame using data df = pd.DataFrame(fill, index = Index, columns = Columns) df.columns = pd.MultiIndex.from_tuples(list(zip(Header,df.columns))) #write data frame to an excel file writer = pd.ExcelWriter(file_no_ext+'.xlsx', engine='xlsxwriter') df.to_excel(writer, sheet_name='Sheet1', index = True) #adjust the size of each column to fit the text size_list = [15,20,20,20,20,10,10,18,18,10,10,18,18,10,10,18,18,10,10,18,18,10,10,18,18,10,10,18,18,10,10,18,18,10,10,18,18,10,10,18,18,10,10,18,18,20] worksheet = writer.sheets['Sheet1'] for k,m in enumerate(size_list): worksheet.set_column(k,k,m) writer.save() self.close() else: #the user wants to appedn to an existing file filename, file_extension = os.path.splitext(self._name_of_file ) delimiter = os.path.sep temp=filename.split(delimiter) photo_name=temp[-1] + file_extension #create data frame with new ata Index = [photo_name] df = pd.DataFrame(fill, index = Index, columns = Columns) df.columns = pd.MultiIndex.from_tuples(list(zip(Header,df.columns))) #load data from file and arrange its columns to fit the template old_df = pd.read_excel(str(self._SelectFile.text()), sheetname=0,header=[0, 1], index_col=0) #verify if the loaded file is valid if len(old_df.columns) is 45: old_df.columns = pd.MultiIndex.from_tuples(df.columns) #concatenate old and new data frame Frames = [old_df, df] resuls = pd.concat(Frames, axis=0) #write results in selected file writer = pd.ExcelWriter(str(self._SelectFile.text()), engine='xlsxwriter') resuls.to_excel(writer, sheet_name='Sheet1', index = True) #adjust the size of each column to fit the text size_list = [15,20,20,20,20,10,10,18,18,10,10,18,18,10,10,18,18,10,10,18,18,10,10,18,18,10,10,18,18,10,10,18,18,10,10,18,18,10,10,18,18,10,10,18,18,20] worksheet = writer.sheets['Sheet1'] for k,m in enumerate(size_list): worksheet.set_column(k,k,m) writer.save() self.close() else: QtWidgets.QMessageBox.warning(self,"Warning", "Invalid File", QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.NoButton)
class ScoreDB(QWidget): def __init__(self): super().__init__() self.initUI() self.dbfilename = 'assignment6.dat' self.scoredb = [] self.readScoreDB() self.showScoreDB(self.keyBox()) def initUI(self): nameLabel = QLabel("Name:") ageLabel = QLabel("Age:") scoreLabel = QLabel("Score") self.writingName = QLineEdit() self.writingAge = QLineEdit() self.writingScore = QLineEdit() firstLine = QHBoxLayout() firstLine.addWidget(nameLabel) firstLine.addWidget(self.writingName) firstLine.addWidget(ageLabel) firstLine.addWidget(self.writingAge) firstLine.addWidget(scoreLabel) firstLine.addWidget(self.writingScore) amountLabel = QLabel("Amount:") keyLabel = QLabel("Key:") self.writingAmount = QLineEdit() self.keys = QComboBox() self.keys.addItem("Name") self.keys.addItem("Age") self.keys.addItem("Score") secondLine = QHBoxLayout() secondLine.addStretch(1) secondLine.addWidget(amountLabel) secondLine.addWidget(self.writingAmount) secondLine.addWidget(keyLabel) secondLine.addWidget(self.keys) addB = QPushButton("Add") delB = QPushButton("Del") findB = QPushButton("Find") incB = QPushButton("Inc") showB = QPushButton("Show") thrLine = QHBoxLayout() thrLine.addStretch(1) thrLine.addWidget(addB) thrLine.addWidget(delB) thrLine.addWidget(findB) thrLine.addWidget(incB) thrLine.addWidget(showB) resLabel = QLabel("Result:") fourLine = QHBoxLayout() fourLine.addWidget(resLabel) self.textBox = QTextEdit() fiveLine = QHBoxLayout() fiveLine.addWidget(self.textBox) vBox = QVBoxLayout() vBox.addLayout(firstLine) vBox.addLayout(secondLine) vBox.addLayout(thrLine) vBox.addLayout(fourLine) vBox.addLayout(fiveLine) addB.clicked.connect(lambda: self.add()) showB.clicked.connect(lambda: self.showScoreDB(self.keyBox())) delB.clicked.connect(lambda: self.delete()) findB.clicked.connect(lambda: self.finding()) incB.clicked.connect(lambda: self.inc()) self.setLayout(vBox) self.setGeometry(300, 300, 500, 250) self.setWindowTitle('Assignment6') self.show() def closeEvent(self, event): self.writeScoreDB() def readScoreDB(self): try: fH = open(self.dbfilename, 'rb') except FileNotFoundError as e: self.scoredb = [] return try: self.scoredb = pickle.load(fH) except: pass else: pass fH.close() # write the data into person db def writeScoreDB(self): fH = open(self.dbfilename, 'wb') pickle.dump(self.scoredb, fH) fH.close() def showScoreDB(self, keyname): showText = "" for p in sorted(self.scoredb, key=lambda person: person[keyname]): for attr in sorted(p): showText += str(attr) + "=" + str(p[attr]) + " \t" showText += "\n" self.textBox.setText(showText) def add(self): try: record = { 'Name': self.writingName.text(), 'Age': int(self.writingAge.text()), 'Score': int(self.writingScore.text()) } except: pass else: self.scoredb += [record] self.showScoreDB("Name") def keyBox(self): returnBox = self.keys.currentText() return returnBox def delete(self): del_list = [] for p in self.scoredb: if p['Name'] == self.writingName.text(): del_list.append(p) for name in del_list: self.scoredb.remove(name) self.showScoreDB("Name") def finding(self): finding_text = "" for p in self.scoredb: if p['Name'] != self.writingName.text(): continue for attr in sorted(p): finding_text += str(attr) + "=" + str(p[attr]) + " \t" finding_text += "\n" self.textBox.setText(finding_text) def inc(self): try: for p in self.scoredb: if p['Name'] == self.writingName.text(): p['Score'] = str( int(p['Score']) + int(self.writingAmount.text())) except ValueError: pass self.showScoreDB("Name")
class PID_Tuner_Widget(QWidget): ''' This class is a PyQt widget for tunning the 6 degree of freedom PID control system. ''' def __init__(self): ''' Initialize the layout for the widget by setting its color and instantiating its components: Parameters: N/A Returns: N/A ''' QWidget.__init__(self) configs = MechOS_Network_Configs( MECHOS_CONFIG_FILE_PATH)._get_network_parameters() self.pid_gui_node = mechos.Node("PID_TUNER_GUI", '192.168.1.2', '192.168.1.14') #Publisher to tell the navigation/movement controller when new PID values are saved. self.pid_configs_update_publisher = self.pid_gui_node.create_publisher( "UPDATE_PID_CONFIGS", Bool(), protocol="tcp") #Subscriber to get PID ERRORS #self.pid_errors_subscriber = self.pid_gui_node.create_subscriber("PE", self._update_error_plot, configs["sub_port"]) #self.pid_error_proto = pid_errors_pb2.PID_ERRORS() #Mechos parameter server #Initialize parameter server client to get and set parameters related to sub self.param_serv = mechos.Parameter_Server_Client( configs["param_ip"], configs["param_port"]) self.param_serv.use_parameter_database(configs["param_server_path"]) #Set background color of the widget #nav_gui_palette = self.palette() #nav_gui_palette.setColor(self.backgroundRole(), QColor(64, 64, 64)) #self.setPalette(nav_gui_palette) #Create widgets main layout structure self.primary_linking_layout = QVBoxLayout(self) self.setLayout(self.primary_linking_layout) #Options widget self.options_linking_layout = QGridLayout() self._error_plotter() self._PID_controller_select() self._PID_sliders() self.set_desired_position = Set_Desired_Position_GUI() #Set up QTimer to update the PID errors self.pid_error_update_timer = QTimer() #self.pid_error_update_timer.timeout.connect(lambda: self.pid_gui_node.spinOnce(self.pid_errors_subscriber)) self.primary_linking_layout.addLayout(self.options_linking_layout, 1) self.primary_linking_layout.addWidget(self.set_desired_position, 2) #Start PID errors update errors. Update 100 timers a second self.pid_error_update_timer.start(10) def _PID_controller_select(self): ''' ''' self.PID_controller_layout = QGridLayout() #A combo box to select which PID channel to tune self.pid_channel_select = QComboBox() self.pid_channel_select.addItem("roll_pid") self.pid_channel_select.addItem("pitch_pid") self.pid_channel_select.addItem("yaw_pid") self.pid_channel_select.addItem("x_pid") self.pid_channel_select.addItem("y_pid") self.pid_channel_select.addItem("z_pid") #Signal to change which PID controller is being tunned when selection changes self.pid_channel_select.currentIndexChanged.connect( self._PID_controller_change) self.pid_channel_select_label = QLabel("PID Controller:") self.pid_channel_select_label.setStyleSheet("color: black") #A button to save the PID values to the parameter server. This is how to sub #will update its PID values self.PID_save_values_layout = QVBoxLayout() self.pid_values_save = QPushButton("Save PID Values") self.pid_values_save.setStyleSheet( "background-color:#2C878F; color:#01535B") self.pid_values_save.setIcon(QIcon(QPixmap("save_symbol.png"))) self.pid_values_save.clicked.connect(self._save_pid_values) self.PID_save_values_layout.addWidget(self.pid_values_save, 0) self.PID_controller_layout.addWidget(self.pid_channel_select_label, 0, 0) self.PID_controller_layout.addWidget(self.pid_channel_select, 0, 1) self.PID_save_values_layout.addLayout(self.PID_controller_layout, 1) self.options_linking_layout.addLayout(self.PID_save_values_layout, 0, 1) def _PID_sliders(self): ''' Set up the proportional, integral, and derivatives gain sliders for tunning the PID controls. Parameters: N/A Returns: N/A ''' self.slider_layout = QGridLayout() self.k_p_precision_layout = QGridLayout() self.k_i_precision_layout = QGridLayout() self.k_d_precision_layout = QGridLayout() self.k_p_slider = QSlider(Qt.Horizontal) self.k_p_slider.setMaximum(10) self.k_p_slider.setMinimum(0) self.k_p_slider.setValue(0) self.k_p_slider.valueChanged.connect(self._update_gains_with_slider) self.k_p_label = QLabel("K_P:") self.k_p_label.setStyleSheet("color: black") self.k_p_display = QLineEdit() self.k_p_display.editingFinished.connect( self._update_gain_with_line_edits) self.k_p_max_value_line_edit = QLineEdit() self.max_k_p = 10.0 self.k_p_max_value_line_edit.setText(str(self.max_k_p)) self.k_p_max_value_line_edit.editingFinished.connect( self._update_PID_precision) self.k_p_max_value_label = QLabel("Max K_P:") self.k_p_max_value_label.setStyleSheet("color: black") self.k_p_precision_combobox = QComboBox() self.k_p_precision_combobox.addItems(["1", "0.1", "0.01", "0.001"]) self.precision_k_p = float(self.k_p_precision_combobox.currentText()) self.k_p_precision_combobox.currentIndexChanged.connect( self._update_PID_precision) self.k_p_precision_label = QLabel("K_P Precision:") self.k_p_precision_label.setStyleSheet("color: black") self.k_i_slider = QSlider(Qt.Horizontal) self.k_i_slider.setMaximum(10) self.k_i_slider.setMinimum(0) self.k_i_slider.setValue(0) self.k_i_slider.valueChanged.connect(self._update_gains_with_slider) self.k_i_label = QLabel("K_I:") self.k_i_label.setStyleSheet("color: black") self.k_i_display = QLineEdit() self.k_i_display.editingFinished.connect( self._update_gain_with_line_edits) self.k_i_max_value_line_edit = QLineEdit() self.max_k_i = 10.0 self.k_i_max_value_line_edit.setText(str(self.max_k_i)) self.k_i_max_value_line_edit.editingFinished.connect( self._update_PID_precision) self.k_i_max_value_label = QLabel("Max K_I:") self.k_i_max_value_label.setStyleSheet("color: black") self.k_i_precision_combobox = QComboBox() self.k_i_precision_combobox.addItems(["1", "0.1", "0.01", "0.001"]) self.precision_k_i = float(self.k_i_precision_combobox.currentText()) self.k_i_precision_combobox.currentIndexChanged.connect( self._update_PID_precision) self.k_i_precision_label = QLabel("K_I Precision:") self.k_i_precision_label.setStyleSheet("color: black") self.k_d_slider = QSlider(Qt.Horizontal) self.k_d_slider.setMaximum(10) self.k_d_slider.setMinimum(0) self.k_d_slider.setValue(0) self.k_d_slider.valueChanged.connect(self._update_gains_with_slider) self.k_d_label = QLabel("K_D:") self.k_d_label.setStyleSheet("color: black") self.k_d_display = QLineEdit() self.k_d_display.editingFinished.connect( self._update_gain_with_line_edits) self.k_d_max_value_line_edit = QLineEdit() self.max_k_d = 10.0 self.k_d_max_value_line_edit.setText(str(self.max_k_d)) self.k_d_max_value_line_edit.editingFinished.connect( self._update_PID_precision) self.k_d_max_value_label = QLabel("Max K_D:") self.k_d_max_value_label.setStyleSheet("color: black") self.k_d_precision_combobox = QComboBox() self.k_d_precision_combobox.addItems(["1", "0.1", "0.01", "0.001"]) self.precision_k_d = float(self.k_d_precision_combobox.currentText()) self.k_d_precision_combobox.currentIndexChanged.connect( self._update_PID_precision) self.k_d_precision_label = QLabel("K_D Precision:") self.k_d_precision_label.setStyleSheet("color: black") self.k_p_precision_layout.addWidget(self.k_p_max_value_label, 0, 0) self.k_p_precision_layout.addWidget(self.k_p_max_value_line_edit, 0, 1) self.k_p_precision_layout.addWidget(self.k_p_precision_label, 1, 0) self.k_p_precision_layout.addWidget(self.k_p_precision_combobox, 1, 1) self.k_i_precision_layout.addWidget(self.k_i_max_value_label, 0, 0) self.k_i_precision_layout.addWidget(self.k_i_max_value_line_edit, 0, 1) self.k_i_precision_layout.addWidget(self.k_i_precision_label, 1, 0) self.k_i_precision_layout.addWidget(self.k_i_precision_combobox, 1, 1) self.k_d_precision_layout.addWidget(self.k_d_max_value_label, 0, 0) self.k_d_precision_layout.addWidget(self.k_d_max_value_line_edit, 0, 1) self.k_d_precision_layout.addWidget(self.k_d_precision_label, 1, 0) self.k_d_precision_layout.addWidget(self.k_d_precision_combobox, 1, 1) self.slider_layout.addWidget(self.k_p_label, 0, 0) self.slider_layout.addWidget(self.k_p_slider, 0, 1) self.slider_layout.addWidget(self.k_p_display, 0, 2) self.slider_layout.addLayout(self.k_p_precision_layout, 0, 3) self.slider_layout.addWidget(self.k_i_label, 1, 0) self.slider_layout.addWidget(self.k_i_slider, 1, 1) self.slider_layout.addWidget(self.k_i_display, 1, 2) self.slider_layout.addLayout(self.k_i_precision_layout, 1, 3) self.slider_layout.addWidget(self.k_d_label, 2, 0) self.slider_layout.addWidget(self.k_d_slider, 2, 1) self.slider_layout.addWidget(self.k_d_display, 2, 2) self.slider_layout.addLayout(self.k_d_precision_layout, 2, 3) self.options_linking_layout.addLayout(self.slider_layout, 0, 0) self._PID_controller_change() def _error_plotter(self): ''' Initialize a real time plotter widget to display the PID error of the sub. Parameters: N/A Returns: N/A ''' self.error_plot = Real_Time_Plotter(title="PID Error") self.error_plot.add_curve("Current Error", (255, 0, 0)) self.error_plot.add_curve("Zero Error", (0, 255, 0)) self.primary_linking_layout.addWidget(self.error_plot, 0) def _update_error_plot(self, pid_error_proto): ''' Update the error plot by calling the pid error subscriber. This function is the callback function to the pid_error_suscriber. Parameters: pid_error_proto: The pid error protobuf recieved from the pid error subscriber. Returns: N/A ''' self.pid_error_proto.ParseFromString(pid_error_proto) self.channel = self.pid_channel_select.currentIndex() if (self.channel == 0): current_error = self.pid_error_proto.roll_error elif (self.channel == 1): current_error = self.pid_error_proto.pitch_error elif (self.channel == 2): current_error = self.pid_error_proto.yaw_error elif (self.channel == 3): current_error = self.pid_error_proto.x_pos_error elif (self.channel == 4): current_error = self.pid_error_proto.y_pos_error elif (self.channel == 5): current_error = self.pid_error_proto.z_pos_error self.error_plot.update_values(current_error, 0) def _PID_controller_change(self): ''' If the PID controller desired to be tune changes, this callback is called to position the sliders in the last set PID control position. Parameters: N/A Returns: N/A ''' self.channel = self.pid_channel_select.currentText() k_p = self.param_serv.get_param('Control/PID/' + self.channel + '/p') k_i = self.param_serv.get_param('Control/PID/' + self.channel + '/i') k_d = self.param_serv.get_param('Control/PID/' + self.channel + '/d') #Set the max of each channel as the value from the Parameter server k_p_disp = "%.3f" % (float(k_p) + 0.10 * float(k_p)) k_i_disp = "%.3f" % (float(k_i) + 0.10 * float(k_i)) k_d_disp = "%.3f" % (float(k_d) + 0.10 * float(k_d)) self.k_p_max_value_line_edit.setText(k_p_disp) self.k_i_max_value_line_edit.setText(k_i_disp) self.k_d_max_value_line_edit.setText(k_d_disp) #Set the precision to the max precision of the self.k_p_precision_combobox.setCurrentIndex(3) self.k_i_precision_combobox.setCurrentIndex(3) self.k_d_precision_combobox.setCurrentIndex(3) self._update_PID_precision() self._update_gain_displays(k_p, k_i, k_d) self._update_sliders(k_p, k_i, k_d) def _save_pid_values(self): ''' This is the callback for the save pid values button. When it is pressed, it sets the PID gain values currently selected on the sliders/gain displays and writes it to the parameter server. Then it tells the navigation controller to update these values. Parameters: N/A Returns: N/A ''' channel = self.pid_channel_select.currentText() #Get the current PID values seen by the sliders/gain displays. Set it #to the parameter server. k_p = self.k_p_display.text() k_i = self.k_i_display.text() k_d = self.k_d_display.text() self.param_serv.set_param('Control/PID/' + channel + '/p', k_p) self.param_serv.set_param('Control/PID/' + channel + '/i', k_i) self.param_serv.set_param('Control/PID/' + channel + '/d', k_d) time.sleep(0.01) #Make sure that the parameters are properly sent. #Tell the navigation controller/movement controller to update its PIDs self.pid_configs_update_publisher.publish(bytes( '1', 'utf-8')) #The value that is sent does not matter print("[INFO]: Saving and Updating PID Configurations.") def _update_PID_precision(self): ''' This function is the callback for when the desired PID gain floating point precision is changed. It allows for the selection of the max p, i, and d values for each channel. Parameters: N/A Returns: N/A ''' k_p = self.k_p_display.text() k_i = self.k_i_display.text() k_d = self.k_d_display.text() self.max_k_p = float(self.k_p_max_value_line_edit.text()) self.precision_k_p = float(self.k_p_precision_combobox.currentText()) self.k_p_slider.setMaximum(self.max_k_p * (1 / self.precision_k_p)) self.max_k_i = float(self.k_i_max_value_line_edit.text()) self.precision_k_i = float(self.k_i_precision_combobox.currentText()) self.k_i_slider.setMaximum(self.max_k_i * (1 / self.precision_k_i)) self.max_k_d = float(self.k_d_max_value_line_edit.text()) self.precision_k_d = float(self.k_d_precision_combobox.currentText()) self.k_d_slider.setMaximum(self.max_k_d * (1 / self.precision_k_d)) #self._update_gain_displays(k_p, k_i, k_d) #self._update_sliders(k_p, k_i, k_d) def _update_gains_with_slider(self): ''' This function is the callback called when any of the sliders change in value. It will update the gain displays to view what the current gain is via number. Parameters: N/A Returns: N/A ''' k_p = self.k_p_slider.value() * self.precision_k_p k_i = self.k_i_slider.value() * self.precision_k_i k_d = self.k_d_slider.value() * self.precision_k_d self._update_gain_displays(k_p, k_i, k_d) def _update_gain_with_line_edits(self): ''' This function is the callback called when any of the gain displays change in value and the enter key is pressed. It will update the slider position to view what the current gain isvia number. Parameters: N/A Returns: N/A ''' k_p = float(self.k_p_display.text()) if (k_p > self.max_k_p): k_p = self.max_k_p k_i = float(self.k_i_display.text()) if (k_i > self.max_k_i): k_i = self.max_k_i k_d = float(self.k_d_display.text()) if (k_d > self.max_k_d): k_d = self.max_k_d self._update_sliders(k_p, k_i, k_d) self._update_gain_displays(k_p, k_i, k_d) def _update_gain_displays(self, k_p, k_i, k_d): ''' Set the text for the gain displays. Parameters: k_p: The proportional gain k_i: Integral gain k_d: Derivative gain Returns: N/A ''' self.k_p_display.setText(str(round(float(k_p), 3))) self.k_i_display.setText(str(round(float(k_i), 3))) self.k_d_display.setText(str(round(float(k_d), 3))) def _update_sliders(self, k_p, k_i, k_d): ''' Set the position for the sliders. Parameters: k_p: The proportional gain k_i: Integral gain k_d: Derivative gain Returns: N/A ''' self.k_p_slider.setValue(float(k_p) / self.precision_k_p) self.k_i_slider.setValue(float(k_i) / self.precision_k_i) self.k_d_slider.setValue(float(k_d) / self.precision_k_d)
class SettingMenu(QFrame): S_port_info = pyqtSignal(str, str, name='PortInfo') S_save_butt_clicked = pyqtSignal(bool, name='SaveButtClicked') S_update_ports = pyqtSignal(bool, name="UpdateButtClicked") def __init__(self, port, port_speed): super().__init__() self.setting_info_ = {'Port': port, 'Speed': port_speed} self.ports_ = {} speeds_ = { "1200", "2400", "4800", "9600", "19200", "38400", "57600", "115200" } self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) portEditLabel = QLabel("Port Number:") portEditLabel.setObjectName("SettMenuLabel") self.portBox = QComboBox() self.portBox.addItems(self.ports_) self.portBox.setCurrentText(self.setting_info_["Port"]) speedEditLabel = QLabel("Port Speed: ") speedEditLabel.setObjectName("SettMenuLabel") self.speedBox = QComboBox() self.speedBox.addItems(speeds_) self.speedBox.setCurrentText(self.setting_info_["Speed"]) configSaveButt = QPushButton("SAVE") configSaveButt.setObjectName("SettMenuSaveButt") configSaveButt.clicked.connect(self.set_port_info) updateButt = QPushButton("Update") updateButt.clicked.connect(self.act_update_ports) hPortBoxLay = QHBoxLayout() hPortBoxLay.addWidget(portEditLabel) hPortBoxLay.addWidget(self.portBox) hPortBoxLay.addSpacing(20) hPortBoxLay.addWidget(speedEditLabel) hPortBoxLay.addWidget(self.speedBox) hPortBoxLay.addStretch() saveButtHBoxLay = QHBoxLayout() saveButtHBoxLay.addWidget(configSaveButt) updateButtHBoxLay = QHBoxLayout() updateButtHBoxLay.addWidget(updateButt) # Создаем вертикальное пространство vBoxLay = QVBoxLayout() # Прикрепляем пространство к левому верхнему краю vBoxLay.setAlignment(Qt.AlignTop | Qt.AlignLeft) vBoxLay.addLayout(hPortBoxLay) vBoxLay.addStretch(1) vBoxLay.addLayout(saveButtHBoxLay) vBoxLay.addLayout(updateButtHBoxLay) self.setLayout(vBoxLay) self.hide() def set_port_info(self): self.setting_info_['Port'] = self.portBox.currentText() self.setting_info_['Speed'] = self.speedBox.currentText() self.S_port_info.emit(self.setting_info_["Port"], self.setting_info_['Speed']) self.S_save_butt_clicked.emit(True) def update_ports(self, ports): print("ports updated") self.ports_ = ports self.portBox.clear() self.portBox.addItems(self.ports_) def act_update_ports(self): self.S_update_ports.emit(True)
def combo_get(self, combo_name, c: QComboBox): if c.currentText(): return self.combo_substitution_idx[combo_name][c.currentText()]
class MyApp(QWidget): def __init__(self): super().__init__() self.loadDB() self.initUI() ### 1. DB load ### def loadDB(self): self.toxic_db, self.msms_db = utils.load_db() ### 2. UI initialization ### def initUI(self): grid = QGridLayout() left_grid = QGridLayout() self.search_grid = self._create_search_grid() self.info_grid = self._create_info_grid() self.action_grid = self._create_action_grid() left_grid.addWidget(self.search_grid) left_grid.addWidget(self.info_grid) left_grid.addWidget(self.action_grid) right_grid = QGridLayout() self.poison_grid = self._create_poison_grid() self.mass_grid, self.mass_layout = self._create_mass_grid() right_grid.addWidget(self.poison_grid) right_grid.addWidget(self.mass_grid) grid.addLayout(left_grid, 0, 0, 1, 1) grid.addLayout(right_grid, 0, 1, 1, 3) ## (Added) Fix the left grid ################# grid.setColumnStretch(0, 0.1) grid.setColumnStretch(1, 2) ############################################## self.setWindowTitle('TOXMASS 1.0') self.setLayout(grid) self.center() self.show() def center(self): qr = self.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft()) # 2.1 Create search grid def _create_search_grid(self): groupbox = QGroupBox('') # Search layout search_group = QGroupBox('Search') search_layout = QHBoxLayout() self.search_type_list = QComboBox() self.search_type_list.addItem('CAS') self.search_type_list.addItem('IUPAC') self.search_type_list.addItem('SMILES') search_btn = QPushButton('Search') search_btn.clicked.connect( self.search_btn_click_event) # Refer to 2.1.3 function self.search_line = QLineEdit('') self.search_line.resize(self.search_line.sizeHint()) self.search_line.returnPressed.connect( search_btn.click) # Refer to 2.1.3 function search_layout.addWidget(self.search_type_list) search_layout.addWidget(self.search_line) search_layout.addWidget(search_btn) search_group.setLayout(search_layout) # Species layout species_group = QGroupBox('Species') species_layout = QVBoxLayout() self.species_all = QCheckBox('all') self.species_all.stateChanged.connect( self.species_all_btn_click_event) # Refer to 2.1.1 function self.species_btn1 = QCheckBox('zebra fish') self.species_btn2 = QCheckBox('fathead minnow') self.species_btn3 = QCheckBox('medaka') self.species_btn4 = QCheckBox('daphnia') self.species_others = QCheckBox('others') species_layout.addWidget(self.species_all) species_layout.addWidget(self.species_btn1) species_layout.addWidget(self.species_btn2) species_layout.addWidget(self.species_btn3) species_layout.addWidget(self.species_btn4) species_layout.addWidget(self.species_others) species_group.setLayout(species_layout) # Endpoint layout endpoint_group = QGroupBox('End point') endpoint_layout = QVBoxLayout() self.ep_all = QCheckBox('all') self.ep_all.stateChanged.connect( self.endpoint_all_btn_click_event) # Refer to 2.1.2 function self.ep_lc_btn = QCheckBox('LC50') self.ep_ec_btn = QCheckBox('EC50') self.ep_others = QCheckBox('others') endpoint_layout.addWidget(self.ep_all) endpoint_layout.addWidget(self.ep_lc_btn) endpoint_layout.addWidget(self.ep_ec_btn) endpoint_layout.addWidget(self.ep_others) endpoint_group.setLayout(endpoint_layout) vbox = QVBoxLayout() vbox.addWidget(search_group) vbox.addWidget(species_group) vbox.addWidget(endpoint_group) groupbox.setLayout(vbox) return groupbox # 2.2 Create info grid def _create_info_grid(self): groupbox = QGroupBox('Chemical Information') self.info_table = QTableWidget() self.info_table.setColumnCount(1) self.info_table.horizontalHeader().setVisible(False) self.info_table.setRowCount(4) self.info_table.setVerticalHeaderLabels( ["Name", "IUPAC name", "CAS number", "SMILES"]) self.info_table.setEditTriggers(QTableWidget.NoEditTriggers) vbox = QVBoxLayout() vbox.addWidget(self.info_table) print("table", self.info_table.size()) print("vbox", groupbox.size()) groupbox.setLayout(vbox) # QTableWidget.setMinimumSize(self.info_table, 357, 120) self.info_table.setRowHeight(0, groupbox.height() / 16) self.info_table.setRowHeight(1, groupbox.height() / 16) self.info_table.setRowHeight(2, groupbox.height() / 16) self.info_table.setRowHeight(3, groupbox.height() / 16) # self.info_table.setColumnWidth(0, 300) QTableWidget.setMinimumSize(self.info_table, 357, groupbox.height() / 4) QTableWidget.setFixedSize(self.info_table, 357, groupbox.height() / 4) vbox.addStretch(0.001) return groupbox def _create_action_grid(self): groupbox = QGroupBox(' ') action_layout = QHBoxLayout() # save_btn = QPushButton('Save') save_btn.clicked.connect( partial(self.file_btn_click_event, clicked_btn='save')) # Refer to 2.4.1 function # print_btn = QPushButton('Print') print_btn.clicked.connect( partial(self.file_btn_click_event, clicked_btn='print')) # Refer to 2.4.1 function # action_layout.addWidget(save_btn) action_layout.addWidget(print_btn) groupbox.setLayout(action_layout) return groupbox # 2.3 Create poison grid def _create_poison_grid(self): groupbox = QGroupBox('') self.poison_text = QTextEdit('') self.poison_text.setReadOnly(True) vbox = QVBoxLayout() vbox.addWidget(self.poison_text) groupbox.setLayout(vbox) return groupbox # 2.4 Create mass grid def _create_mass_grid(self): groupbox = QGroupBox('') mass_layout = QVBoxLayout() self.mass_fig = plt.Figure() self.mass_canvas = FigureCanvas(self.mass_fig) self.mass_fig.clear() ax = self.mass_fig.add_subplot(111) ax.set_yticks([0, 20, 40, 60, 80, 100]) ax.set_xlabel('m/z') ax.set_ylabel('Intensity') plt.tight_layout() self.mass_canvas.draw() # Create reference line self.reference_line = QLineEdit('') self.reference_line.setReadOnly(True) # Create save and print button # self.save_print_group = QGroupBox('') # save_print_layout = QHBoxLayout() # info_btn = QPushButton('Info') # info_btn.clicked.connect(partial(self.file_btn_click_event, clicked_btn='info')) # save_btn = QPushButton('Save') # save_btn.clicked.connect(partial(self.file_btn_click_event, clicked_btn='save')) # Refer to 2.4.1 function # print_btn = QPushButton('Print') # print_btn.clicked.connect(partial(self.file_btn_click_event, clicked_btn='print')) # Refer to 2.4.1 function # save_print_layout.addWidget(info_btn) # save_print_layout.addWidget(save_btn) # save_print_layout.addWidget(print_btn) # self.save_print_group.setLayout(save_print_layout) mass_layout.addWidget(self.mass_canvas) mass_layout.addWidget(self.reference_line) # mass_layout.addWidget(self.save_print_group) groupbox.setLayout(mass_layout) return groupbox, mass_layout # 2.1.1 Connect species all button click event def species_all_btn_click_event(self): if self.species_all.isChecked(): self.species_btn1.setChecked(True) self.species_btn2.setChecked(True) self.species_btn3.setChecked(True) self.species_btn4.setChecked(True) self.species_others.setChecked(True) self.species_btn1.setEnabled(False) self.species_btn2.setEnabled(False) self.species_btn3.setEnabled(False) self.species_btn4.setEnabled(False) self.species_others.setEnabled(False) else: self.species_btn1.setChecked(False) self.species_btn2.setChecked(False) self.species_btn3.setChecked(False) self.species_btn4.setChecked(False) self.species_others.setChecked(False) self.species_btn1.setEnabled(True) self.species_btn2.setEnabled(True) self.species_btn3.setEnabled(True) self.species_btn4.setEnabled(True) self.species_others.setEnabled(True) # 2.1.2 Connect endpoint all button click event def endpoint_all_btn_click_event(self): if self.ep_all.isChecked(): self.ep_lc_btn.setChecked(True) self.ep_ec_btn.setChecked(True) self.ep_others.setChecked(True) self.ep_lc_btn.setEnabled(False) self.ep_ec_btn.setEnabled(False) self.ep_others.setEnabled(False) else: self.ep_lc_btn.setChecked(False) self.ep_ec_btn.setChecked(False) self.ep_others.setChecked(False) self.ep_lc_btn.setEnabled(True) self.ep_ec_btn.setEnabled(True) self.ep_others.setEnabled(True) # 2.1.3 Connect species all button click event def search_btn_click_event(self): ### related to search grid ### df = self.toxic_db searched_type = str(self.search_type_list.currentText()) searched_input = self.search_line.text().replace(' ', '') if searched_type == 'CAS': try: searched_cid = df[list( map(lambda f: searched_input in f, df['CAS']))]['cid'].item() except: QMessageBox.about( self, "No results found.", "We do not have any datas for \"{}\"".format( searched_input)) return elif searched_type == 'IUPAC': try: searched_cid = df[df['IUPAC'] == searched_input]['cid'].item() except: QMessageBox.about( self, "No results found.", "We do not have any datas for \"{}\"".format( searched_input)) return elif searched_type == 'SMILES': try: searched_cid = df[df['SMILES'] == searched_input]['cid'].item() except: QMessageBox.about( self, "No results found.", "We do not have any datas for \"{}\"".format( searched_input)) return else: QMessageBox.about( self, "Error", "Please select search type (CAS, IUPAC, or SMILES)") return ### related to info grid ### searched_data = df[df['cid'] == searched_cid] cas = searched_data['CAS'].item() iupac_name = searched_data['IUPAC'].item() smiles = searched_data['SMILES'].item() name, all_poison_list = utils.load_poison_info(searched_cid) self.info_table.setItem(0, 0, QTableWidgetItem(name)) self.info_table.setItem(1, 0, QTableWidgetItem(iupac_name)) self.info_table.setItem(2, 0, QTableWidgetItem(', '.join(cas))) self.info_table.setItem(3, 0, QTableWidgetItem(smiles)) self.info_table.resizeColumnsToContents() ### related to poison grid ### if not self.species_all.isChecked() \ and not self.species_btn1.isChecked() \ and not self.species_btn2.isChecked() \ and not self.species_btn3.isChecked() \ and not self.species_btn4.isChecked() \ and not self.species_others.isChecked(): self.species_all.setChecked(True) if not self.ep_all.isChecked() \ and not self.ep_lc_btn.isChecked() \ and not self.ep_ec_btn.isChecked() \ and not self.ep_others.isChecked(): self.ep_all.setChecked(True) filtered_poison_list = [] if self.species_all.isChecked() and self.ep_all.isChecked(): filtered_poison_list = all_poison_list elif self.species_all.isChecked() and not self.ep_all.isChecked(): if self.ep_lc_btn.isChecked(): filtered_poison_list += [ p for p in all_poison_list if 'LC50' in p ] if self.ep_ec_btn.isChecked(): filtered_poison_list += [ p for p in all_poison_list if 'EC50' in p ] if self.ep_others.isChecked(): filtered_poison_list += [ p for p in all_poison_list if not 'LC50' in p and not 'EC50' in p ] elif not self.species_all.isChecked() and self.ep_all.isChecked(): if self.species_btn1.isChecked(): filtered_poison_list += [p for p in all_poison_list if 'zebra fish' in p.lower() or \ 'zebrafish' in p.lower() or \ 'danio rerio' in p.lower()] if self.species_btn2.isChecked(): filtered_poison_list += [p for p in all_poison_list if 'fathead minnow' in p.lower() or \ 'pimephales promelas' in p.lower()] if self.species_btn3.isChecked(): filtered_poison_list += [p for p in all_poison_list if 'medaka' in p.lower() or \ 'oryzias latipes' in p.lower()] if self.species_btn4.isChecked(): filtered_poison_list += [ p for p in all_poison_list if 'daphnia' in p.lower() ] if self.species_others.isChecked(): filtered_poison_list += [p for p in all_poison_list if 'zebra fish' not in p.lower() and \ 'zebrafish' not in p.lower() and \ 'danio rerio' not in p.lower() and \ 'fathead minnow' not in p.lower() and \ 'pimephales promelas' not in p.lower() and \ 'medaka' not in p.lower() and \ 'oryzias latipes' not in p.lower() and \ 'daphnia' not in p.lower()] else: ep_filtered_poison_list = [] if self.ep_lc_btn.isChecked(): ep_filtered_poison_list += [ p for p in all_poison_list if 'LC50' in p ] if self.ep_ec_btn.isChecked(): ep_filtered_poison_list += [ p for p in all_poison_list if 'EC50' in p ] if self.ep_others.isChecked(): ep_filtered_poison_list += [ p for p in all_poison_list if not 'LC50' in p and not 'EC50' in p ] if self.species_btn1.isChecked(): filtered_poison_list += [p for p in ep_filtered_poison_list if 'zebra fish' in p.lower() or \ 'zebrafish' in p.lower() or \ 'danio rerio' in p.lower()] if self.species_btn2.isChecked(): filtered_poison_list += [p for p in ep_filtered_poison_list if 'fathead minnow' in p.lower() or \ 'pimephales promelas' in p.lower()] if self.species_btn3.isChecked(): filtered_poison_list += [p for p in ep_filtered_poison_list if 'medaka' in p.lower() or \ 'oryzias latipes' in p.lower()] if self.species_btn4.isChecked(): filtered_poison_list += [ p for p in ep_filtered_poison_list if 'daphnia' in p.lower() ] if self.species_others.isChecked(): filtered_poison_list += [p for p in ep_filtered_poison_list if 'zebra fish' not in p.lower() and \ 'zebrafish' not in p.lower() and \ 'danio rerio' not in p.lower() and \ 'fathead minnow' not in p.lower() and \ 'pimephales promelas' not in p.lower() and \ 'medaka' not in p.lower() and \ 'oryzias latipes' not in p.lower() and \ 'daphnia' not in p.lower()] filtered_poison_list = [' ● ' + f for f in filtered_poison_list] poison_text = 'pubchem.{}'.format(searched_cid) + '\n\n' + '\n\n'.join( filtered_poison_list) self.poison_text.setText(poison_text) ### related to mass grid ### try: searched_msms_data = self.msms_db[smiles][0]['spectrum'] self.mz_array = [ float(d.split(':')[0]) for d in searched_msms_data.split(' ') ] self.intensity_array = [ float(d.split(':')[1]) for d in searched_msms_data.split(' ') ] self.mass_fig.clear() ax = self.mass_fig.add_subplot(111) ax = utils.plot_mass(ax, self.mz_array, self.intensity_array) self.mass_canvas.draw() reference = self.msms_db[smiles][0]['library']['link'] self.reference_line.setText(reference) except: self.mass_fig.clear() ax = self.mass_fig.add_subplot(111) ax.set_yticks([0, 20, 40, 60, 80, 100]) ax.set_xlabel('m/z') ax.set_ylabel('Intensity') plt.tight_layout() self.mass_canvas.draw() self.reference_line.setText('') QMessageBox.about( self, "Error", "There is no database corresponding to the {} in the mass spectrum DB" .format(smiles)) return # 2.4.1 Connect save/print button click event def file_btn_click_event(self, clicked_btn): name = self.info_table.item(0, 0) if name is None: QMessageBox.about(self, "Error", "There is no searching history") return # search information searched_type = str(self.search_type_list.currentText()) searched_input = self.search_line.text() selected_species = [] if self.species_all.isChecked(): selected_species.append('all') else: if self.species_btn1.isChecked(): selected_species.append('zebra fish') if self.species_btn2.isChecked(): selected_species.append('fathead minnow') if self.species_btn3.isChecked(): selected_species.append('medaka') if self.species_btn4.isChecked(): selected_species.append('daphnia') if self.species_others.isChecked(): selected_species.append('others') selected_species = ', '.join(selected_species) selected_ep = [] if self.ep_all.isChecked(): selected_ep.append('all') else: if self.ep_lc_btn.isChecked(): selected_ep.append('LC50') if self.ep_ec_btn.isChecked(): selected_ep.append('EC50') if self.ep_others.isChecked(): selected_ep.append('others') selected_ep = ', '.join(selected_ep) # chemical information name = self.info_table.item(0, 0).text() iupac_name = self.info_table.item(1, 0).text() cas = self.info_table.item(2, 0).text() smiles = self.info_table.item(3, 0).text() # toxic information poison_text = self.poison_text.toPlainText() # mass spectrum try: self.msms_db[smiles] self.mass_fig.savefig('mass_fig.png', dpi=100, bbox_inches='tight') reference = self.reference_line.text() except: pass # Make the entire text edit for save/print entire_text = QTextEdit('') entire_text.append('\n' + '=' * 10 + 'Search Information' + '=' * 10 + '\n') entire_text.append('Searched type: {}'.format(searched_type)) entire_text.append('Searched input: {}'.format(searched_input)) entire_text.append('Selected species: {}'.format(selected_species)) entire_text.append('Selected end point: {}'.format(selected_ep)) entire_text.append('\n' + '=' * 10 + 'Chemical Information' + '=' * 10 + '\n') entire_text.append('Name: {}'.format(name)) entire_text.append('IUPAC name: {}'.format(iupac_name)) entire_text.append('CAS number: {}'.format(cas)) entire_text.append('SMILES: {}'.format(smiles)) entire_text.append('\n' + '=' * 10 + 'Toxic Information' + '=' * 10 + '\n') entire_text.append(poison_text) try: self.msms_db[smiles] entire_text.append('\n' + '=' * 10 + 'Mass Spectrum' + '=' * 10 + '\n') entire_text.append('reference: {}'.format(reference) + '\n') cursor = entire_text.textCursor() entire_text.moveCursor(QTextCursor.End) cursor.insertImage('mass_fig.png') except: pass if clicked_btn == 'save': fn, _ = QFileDialog.getSaveFileName( self, 'Export PDF', None, 'PDF files (.pdf);;All Files()') if fn != '': if QFileInfo(fn).suffix() == "": fn += '.pdf' printer = QPrinter(QPrinter.HighResolution) printer.setOutputFormat(QPrinter.PdfFormat) printer.setOutputFileName(fn) entire_text.document().print_(printer) try: os.remove('mass_fig.png') except: pass elif clicked_btn == 'print': printer = QPrinter(QPrinter.HighResolution) dialog = QPrintDialog(printer, self) if dialog.exec_() == QPrintDialog.Accepted: entire_text.print_(printer) try: os.remove('mass_fig.png') except: pass
class Calculator(QWidget): def __init__(self, parent=None): super().__init__() # 자료처리 관련 함수 self.dbfilename = 'assignment6.dat' self.scoredb = self.readScoreDB() self.writeScoreDB() # Display Window self.display = QLineEdit('0') self.display.setReadOnly(True) self.display.setAlignment(Qt.AlignRight) self.display.setMaxLength(10) # Layout mainLayout = QGridLayout() mainLayout.setSpacing(5) self.setLayout(mainLayout) self.setGeometry(300, 300, 500, 250) self.setWindowTitle("Assignment6") # grid1 self.grid1 = QHBoxLayout() # grid2 self.grid2 = QHBoxLayout() self.grid2.addStretch(1) self.grid2.setSpacing(10) #grid3 self.grid3 = QHBoxLayout() self.grid3.setSpacing(10) #grid 4 self.grid4 = QVBoxLayout() # QLabel self.name = QLabel('Name: ') self.age = QLabel('Age: ') self.score = QLabel('Score: ') self.amount = QLabel('Amount: ') self.key = QLabel('Key: ') self.result = QLabel('Result: ') # QCombobox self.cb = QComboBox() self.cb.addItems(["Age", "Name", "Score"]) # QPushButton self.addbtn = QPushButton("Add") self.delbtn = QPushButton("Del") self.findbtn = QPushButton("Find") self.incbtn = QPushButton("Inc") self.showbtn = QPushButton("Show") #Event self.addbtn.clicked.connect(self.addclicked) self.delbtn.clicked.connect(self.delclicked) self.findbtn.clicked.connect(self.findclicked) self.incbtn.clicked.connect(self.incclicked) self.showbtn.clicked.connect(self.showclicked) # TextEdit self.te = QTextEdit() # LineEdit self.nameEdit = QLineEdit() self.ageEdit = QLineEdit() self.scoreEdit = QLineEdit() self.amountEdit = QLineEdit() # grid1 설정 self.grid1.addWidget(self.name) self.grid1.addWidget(self.nameEdit) self.grid1.addWidget(self.age) self.grid1.addWidget(self.ageEdit) self.grid1.addWidget(self.score) self.grid1.addWidget(self.scoreEdit) self.grid1.setAlignment(Qt.AlignTop) # grid2 설정 self.grid2.addWidget(self.amount) self.grid2.addWidget(self.amountEdit) self.grid2.addWidget(self.key) self.grid2.addWidget(self.cb) # grid3 설정 self.grid3.addWidget(self.addbtn) self.grid3.addWidget(self.delbtn) self.grid3.addWidget(self.findbtn) self.grid3.addWidget(self.incbtn) self.grid3.addWidget(self.showbtn) #grid4 설정 self.grid4.addWidget(self.result) self.grid4.addWidget(self.te) # mainLayout에 배치 mainLayout.addLayout(self.grid1, 0, 0) mainLayout.addLayout(self.grid2, 1, 0) mainLayout.addLayout(self.grid3, 2, 0) mainLayout.addLayout(self.grid4, 3, 0) # Layout self.setLayout(mainLayout) self.show() ######################## 자료 관련 함수 ##################### def closeEvent(self, event): self.writeScoreDB() def readScoreDB(self): try: fH = open(self.dbfilename, 'rb') except FileNotFoundError as e: self.scdb = [] return try: self.scdb = pickle.load(fH) except: pass else: pass fH.close() return self.scdb def writeScoreDB(self): fH = open(self.dbfilename, 'wb') pickle.dump(self.scoredb, fH) fH.close() def showScoreDB(self, keyname): self.te.clear() for p in sorted(self.scdb, key=lambda person: str(person[keyname])): for attr in sorted(p): last = attr + " = " + str(p[attr]) + " " self.te.insertPlainText(last) self.te.append("") # 버튼 클릭연결 def addclicked(self): self.name = self.nameEdit.text() self.age = self.ageEdit.text() self.score = self.scoreEdit.text() record = {'Name': self.name, 'Age': self.age, 'Score': self.score} self.scdb += [record] self.showScoreDB('Name') def delclicked(self): for p in self.scdb: if self.nameEdit.text() == p['Name']: self.scdb.remove(p) self.te.clear() self.showScoreDB('Name') def findclicked(self): self.te.clear() for p in self.scdb: for p in sorted(self.scdb, key=lambda person: person['Name']): if self.nameEdit.text() == p['Name']: for attr in sorted(p): last = attr + " = " + str(p[attr]) + " " self.te.insertPlainText(last) break self.te.append("") def incclicked(self): addamount = int(self.amountEdit.text()) for p in self.scdb: if self.nameEdit.text() == p['Name']: p['Score'] += addamount self.te.clear() self.showScoreDB('Name') break def showclicked(self): self.sortkey = self.cb.currentText() self.showScoreDB(self.sortkey)
class Simulator(QWidget): def __init__(self, *args, **kwargs): super(Simulator, self).__init__(*args, **kwargs) self.__simulation = SimulationData() self.__manage_window() self.__create_layouts() self.__create_buttons_and_inputs() self.__create_canvas() self.__manage_layouts() self.__connect_buttons() self.__set_timer() self.__change_initial_configuration() self.show() def __manage_window(self): self.setWindowTitle("2D Wave Equation Simulator") self.setFixedSize(1000, 860) def __create_layouts(self): self.__main_layout = QtWidgets.QVBoxLayout(self) self.__form_layout = QFormLayout(self) self.__start_stop_layout = QFormLayout(self) def __create_buttons_and_inputs(self): self.__start_button = QtWidgets.QPushButton("Start simulation", self) self.__stop_button = QtWidgets.QPushButton("Stop simulation", self) self.__start_button.setFixedWidth(485) self.__stop_button.setFixedWidth(485) self.__stop_button.setEnabled(False) self.__only_float = QRegExpValidator(QRegExp("-?[0-9]+\.?[0-9]+")) self.__only_float_time = QRegExpValidator(QRegExp("[0-9]+\.?[0-9]+")) self.__only_int = QIntValidator() self.__only_int.setBottom(0) self.__only_int.setTop(99) self.__label1 = QLabel("Number of points (X-axis):") self.__line1 = QLineEdit() self.__line1.setValidator(self.__only_int) self.__line1.setText("25") self.__label2 = QLabel("Number of points (Y-axis):") self.__line2 = QLineEdit() self.__line2.setValidator(self.__only_int) self.__line2.setText("25") self.__label3 = QLabel("Maximum simulation time [s]:") self.__line3 = QLineEdit() self.__line3.setValidator(self.__only_float_time) self.__line3.setText("1.0") self.__label4 = QPushButton("Alpha:") self.__label4.setFixedWidth(135) self.__line4 = QLineEdit() self.__line4.setValidator(self.__only_float) self.__line4.setText("0.0") self.__label5 = QPushButton("Beta:") self.__label5.setFixedWidth(135) self.__line5 = QLineEdit() self.__line5.setValidator(self.__only_float) self.__line5.setText("0.25") self.__label6 = QPushButton("Gamma:") self.__label6.setFixedWidth(135) self.__line6 = QLineEdit() self.__line6.setValidator(self.__only_float) self.__line6.setText("0.5") self.__label7 = QLabel("Fixed boundary conditions:") self.__line7 = QComboBox() self.__line7.addItems(["True", "False"]) self.__label8 = QLabel("Zero-displacement initial condition:") self.__line8 = QComboBox() self.__line8.addItems(["False", "True"]) self.__label9 = QLabel("Forcing term:") self.__line9 = QComboBox() self.__line9.addItems(["False", "True"]) def __create_canvas(self): self.__canvas = Canvas(self) self.__canvas.setFixedSize(980, 566) def __manage_layouts(self): self.__form_layout.addRow(self.__label1, self.__line1) self.__form_layout.addRow(self.__label2, self.__line2) self.__form_layout.addRow(self.__label3, self.__line3) self.__form_layout.addRow(self.__label4, self.__line4) self.__form_layout.addRow(self.__label5, self.__line5) self.__form_layout.addRow(self.__label6, self.__line6) self.__form_layout.addRow(self.__label7, self.__line7) self.__form_layout.addRow(self.__label8, self.__line8) self.__form_layout.addRow(self.__label9, self.__line9) self.__start_stop_layout.addRow(self.__start_button, self.__stop_button) self.__main_layout.addWidget(self.__canvas) self.__main_layout.addLayout(self.__form_layout) self.__main_layout.addLayout(self.__start_stop_layout) def __connect_buttons(self): self.__start_button.clicked.connect(lambda: self.__start_simulation()) self.__stop_button.clicked.connect(lambda: self.__stop_simulation()) self.__label4.clicked.connect(lambda: self.__show_alpha_description()) self.__label5.clicked.connect(lambda: self.__show_beta_description()) self.__label6.clicked.connect(lambda: self.__show_gamma_description()) self.__line1.textChanged.connect( lambda: self.__change_initial_configuration()) self.__line2.textChanged.connect( lambda: self.__change_initial_configuration()) self.__line3.textChanged.connect( lambda: self.__change_initial_configuration()) self.__line4.textChanged.connect( lambda: self.__change_initial_configuration()) self.__line5.textChanged.connect( lambda: self.__change_initial_configuration()) self.__line6.textChanged.connect( lambda: self.__change_initial_configuration()) self.__line7.currentTextChanged.connect( lambda: self.__change_initial_configuration()) self.__line8.currentTextChanged.connect( lambda: self.__change_initial_configuration()) self.__line9.currentTextChanged.connect( lambda: self.__change_initial_configuration()) def __show_alpha_description(self): title = "Description of Alpha parameter" description = "Alpha is the factor responsible for damping the membrane movement" self.__show_message(QMessageBox.Information, title, description) def __show_beta_description(self): title = "Description of Beta parameter" description = "Beta is the scalar parameter of the Newmark algorithm" self.__show_message(QMessageBox.Information, title, description) def __show_gamma_description(self): title = "Description of Gamma parameter" description = "Gamma is the scalar parameter of the Newmark algorithm" self.__show_message(QMessageBox.Information, title, description) def __show_message(self, message_type, title, description): self.__msg = QMessageBox() self.__msg.setIcon(message_type) self.__msg.setWindowTitle(title) self.__msg.setText(description) self.__msg.exec_() def __disable_gui(self): self.__stop_button.setEnabled(True) self.__start_button.setEnabled(False) self.__line1.setEnabled(False) self.__line2.setEnabled(False) self.__line3.setEnabled(False) self.__line4.setEnabled(False) self.__line5.setEnabled(False) self.__line6.setEnabled(False) self.__line7.setEnabled(False) self.__line8.setEnabled(False) self.__line9.setEnabled(False) self.__label4.setEnabled(False) self.__label5.setEnabled(False) self.__label6.setEnabled(False) def __enable_gui(self): self.__stop_button.setEnabled(False) self.__start_button.setEnabled(True) self.__line1.setEnabled(True) self.__line2.setEnabled(True) self.__line3.setEnabled(True) self.__line4.setEnabled(True) self.__line5.setEnabled(True) self.__line6.setEnabled(True) self.__line7.setEnabled(True) self.__line8.setEnabled(True) self.__line9.setEnabled(True) self.__label4.setEnabled(True) self.__label5.setEnabled(True) self.__label6.setEnabled(True) def __set_timer(self): self.__timer = QtCore.QTimer() self.__timer.setInterval(100) self.__timer.timeout.connect(self.__continue_simulation) def __change_initial_configuration(self): try: self.__n_x = int(self.__line1.text()) self.__n_y = int(self.__line2.text()) except: return if self.__n_x < 3 or self.__n_y < 3: return if self.__line8.currentText() == "False": self.__zero_diaphragm_displacement = False elif self.__line8.currentText() == "True": self.__zero_diaphragm_displacement = True self.__x_net = np.zeros(self.__n_x * self.__n_y, dtype=np.float64) self.__y_net = np.zeros(self.__n_x * self.__n_y, dtype=np.float64) for j in range(self.__n_y): for i in range(self.__n_x): self.__x_net[j * self.__n_x + i] = i * 1.0 / self.__n_x self.__y_net[j * self.__n_x + i] = j * 1.0 / self.__n_y first_step = self.__simulation.get_first_step( self.__n_x, self.__n_y, self.__zero_diaphragm_displacement) self.__max_value = first_step.max() + 0.0001 self.__min_value = -self.__max_value self.__canvas.axes.cla() self.__canvas.axes.set_xlabel("x [m]") self.__canvas.axes.set_ylabel("y [m]") self.__canvas.axes.set_zlabel("u [m]") if not self.__zero_diaphragm_displacement: self.__canvas.axes.set_zlim(self.__min_value, self.__max_value) else: self.__canvas.axes.set_zlim(-0.075, 0.075) self.__canvas.axes.set_title( "Diaphragm displacement diagram u(x, y, t) \n t = 0.0 s") self.__canvas.axes.scatter(self.__x_net, self.__y_net, first_step, linewidth=0, antialiased=False) self.__canvas.draw() def __start_simulation(self): self.__n_x = int(self.__line1.text()) self.__n_y = int(self.__line2.text()) if self.__n_x < 3 or self.__n_y < 3: title = "Warning" description = "Number of points for X-axis and Y-axis must be at least 3" self.__show_message(QMessageBox.Warning, title, description) return self.__t = float(self.__line3.text()) self.__alpha = float(self.__line4.text()) self.__beta = float(self.__line5.text()) self.__gamma = float(self.__line6.text()) if self.__line7.currentText() == "False": self.__fixed_boundary_conditions = False elif self.__line7.currentText() == "True": self.__fixed_boundary_conditions = True if self.__line8.currentText() == "False": self.__zero_diaphragm_displacement = False elif self.__line8.currentText() == "True": self.__zero_diaphragm_displacement = True if self.__line9.currentText() == "False": self.__forcing_term_check = False elif self.__line9.currentText() == "True": self.__forcing_term_check = True self.__delta_t = 0.01 self.__n_t = int(self.__t / self.__delta_t) self.__counter = 1 self.__simulation.change_initial_configuration( self.__n_x, self.__n_y, self.__t, self.__alpha, self.__beta, self.__gamma, self.__fixed_boundary_conditions, self.__zero_diaphragm_displacement, self.__forcing_term_check) self.__disable_gui() self.__simulation.start_simulation() self.__canvas.axes.cla() self.__canvas.axes.set_xlabel("x [m]") self.__canvas.axes.set_ylabel("y [m]") self.__canvas.axes.set_zlabel("u [m]") if not self.__zero_diaphragm_displacement: self.__canvas.axes.set_zlim(self.__min_value, self.__max_value) else: self.__canvas.axes.set_zlim(-0.075, 0.075) self.__canvas.axes.set_title( "Diaphragm displacement diagram u(x, y, t) \n t = 0.0 s") self.__canvas.axes.scatter(self.__x_net, self.__y_net, self.__simulation.get_actual_step(), linewidth=0, antialiased=False) self.__canvas.draw() self.__timer.start() def __continue_simulation(self): self.__canvas.axes.cla() self.__canvas.axes.set_xlabel("x [m]") self.__canvas.axes.set_ylabel("y [m]") self.__canvas.axes.set_zlabel("u [m]") if not self.__forcing_term_check: self.__canvas.axes.set_zlim(self.__min_value, self.__max_value) else: if self.__fixed_boundary_conditions or self.__simulation.get_actual_step( ).mean() < 0.05: self.__canvas.axes.set_zlim(-0.075, 0.075) self.__canvas.axes.set_title( "Diaphragm displacement diagram u(x, y, t) \n t = " + str(round(self.__counter * self.__delta_t, 2)) + " s") self.__canvas.axes.scatter(self.__x_net, self.__y_net, self.__simulation.get_actual_step(), linewidth=0, antialiased=False) self.__canvas.draw() if self.__counter < self.__n_t: self.__counter += 1 self.__simulation.calculate_next_step(self.__counter) else: self.__stop_simulation() def __stop_simulation(self): self.__timer.stop() self.__enable_gui()
class FilterEditor(QWidget): def __init__(self, parent: QWidget = None): super(FilterEditor, self).__init__(parent) self.__history = None self.__sources = [] self.__includes = [] self.__excludes = [] self.__combo_focus = QComboBox() self.__list_source = EasyQListSuite() self.__list_include = EasyQListSuite() self.__list_exclude = EasyQListSuite() self.__button_save_filter = QPushButton('Save') self.__button_load_filter = QPushButton('Load') self.__button_check_match = QPushButton('Check') self.__button_gen_index = QPushButton('Generate Index') self.__init_ui() self.__config_ui() def get_filter(self): pass def set_filter(self): pass def set_history_core(self, history: History): self.__history = history # --------------------------------------------- Private --------------------------------------------- def __init_ui(self): main_layout = QVBoxLayout() self.setLayout(main_layout) group, layout = create_v_group_box('Source Selector') layout.addWidget(self.__list_source) main_layout.addWidget(group) group_in, layout_in = create_v_group_box('Include Label Tags') group_ex, layout_ex = create_v_group_box('Exclude Label Tags') layout_in.addWidget(self.__list_include) layout_ex.addWidget(self.__list_exclude) main_layout.addLayout(horizon_layout([group_in, group_ex])) group, layout = create_v_group_box('Focus Label') layout.addWidget(self.__combo_focus) main_layout.addWidget(group) main_layout.addLayout(horizon_layout([self.__button_save_filter, self.__button_load_filter, self.__button_check_match, self.__button_gen_index])) def __config_ui(self): self.__combo_focus.setEditable(True) self.__combo_focus.addItem('') self.__combo_focus.addItem('event') self.__combo_focus.addItem('people') self.__combo_focus.addItem('location') self.__combo_focus.addItem('organization') self.__list_source.set_add_handler(self.__on_source_add) self.__list_source.set_remove_handler(self.__on_source_remove) self.__list_include.set_add_handler(self.__on_include_add) self.__list_include.set_remove_handler(self.__on_include_remove) self.__list_exclude.set_add_handler(self.__on_exclude_add) self.__list_exclude.set_remove_handler(self.__on_exclude_remove) self.__button_save_filter.clicked.connect(self.__on_btn_click_save) self.__button_load_filter.clicked.connect(self.__on_btn_click_load) self.__button_check_match.clicked.connect(self.__on_btn_click_chk) self.__button_gen_index.clicked.connect(self.__on_btn_click_gen) # --------------------------------------------------------------- def __on_source_add(self): root_path = HistoricalRecordLoader.get_local_depot_root() fname, ftype = QFileDialog.getOpenFileNames(self, 'Select History Files', root_path, 'History Files (*.his)') fname = [f[len(root_path):] if f.startswith(root_path) else f for f in fname] self.__sources.extend(fname) self.__sources = list(set(self.__sources)) self.__list_source.update_item([(s, s) for s in self.__sources]) def __on_source_remove(self): items = self.__list_source.get_select_items() for item in items: self.__sources.remove(item) self.__list_source.update_item([(s, s) for s in self.__sources]) def __on_include_add(self): text, ok = QInputDialog.getText(self, 'Include Tags', 'Include: ', QLineEdit.Normal, '') if not ok: return self.__includes.append(text) self.__includes = list(set(self.__includes)) self.__list_include.update_item([(s, s) for s in self.__includes]) def __on_include_remove(self): items = self.__list_include.get_select_items() for item in items: self.__includes.remove(item) self.__list_include.update_item([(s, s) for s in self.__includes]) def __on_exclude_add(self): text, ok = QInputDialog.getText(self, 'Exclude Tags', 'Exclude: ', QLineEdit.Normal, '') if not ok: return self.__excludes.append(text) self.__excludes = list(set(self.__excludes)) self.__list_exclude.update_item([(s, s) for s in self.__excludes]) def __on_exclude_remove(self): items = self.__list_exclude.get_select_items() for item in items: self.__excludes.remove(item) self.__list_exclude.update_item([(s, s) for s in self.__excludes]) # --------------------------------------------------------------- def __on_btn_click_save(self): fileName_choose, filetype = QFileDialog.getSaveFileName(self, 'Save Filter', HistoricalRecordLoader.get_local_depot_root(), 'Filter Files (*.hisfilter)') if fileName_choose == '': return his_filter = self.ui_to_filter() text = his_filter.dump_text() with open(fileName_choose, 'wt') as f: f.write(text) def __on_btn_click_load(self): fileName_choose, filetype = QFileDialog.getOpenFileName(self, 'Load Filter', HistoricalRecordLoader.get_local_depot_root(), 'Filter Files (*.hisfilter)') if fileName_choose == '': return with open(fileName_choose, 'rt') as f: text = f.read() parser = LabelTagParser() if not parser.parse(text): print('Load from (' + fileName_choose + ') failed.') return his_filter = HistoricalFilter() his_filter.attach(parser.get_label_tags()) self.filter_to_ui(his_filter) def __on_btn_click_chk(self): pass def __on_btn_click_gen(self): fileName_choose, filetype = QFileDialog.getSaveFileName(self, 'Generate Index', HistoricalRecordLoader.get_local_depot_root(), 'Filter Files (*.index)') if fileName_choose == '': return records = self.load_filter_records() indexer = HistoricalRecordIndexer() indexer.index_records(records) indexer.dump_to_file(fileName_choose) QMessageBox.information(self, 'Generate Done', 'Generate index for ' + str(len(records)) + ' records Done.') # --------------------------------------------------------------- def filter_to_ui(self, his_filter: HistoricalFilter): self.__combo_focus.setCurrentText(his_filter.get_focus_label()) self.__sources = his_filter.get_sources() self.__includes = self.__label_tag_dict_to_text(his_filter.get_include_tags()) self.__excludes = self.__label_tag_dict_to_text(his_filter.get_exclude_tags()) self.__list_source.update_item([(s, s) for s in self.__sources]) self.__list_include.update_item([(s, s) for s in self.__includes]) self.__list_exclude.update_item([(s, s) for s in self.__excludes]) def ui_to_filter(self) -> HistoricalFilter: his_filter = HistoricalFilter() his_filter.set_sources(self.__sources) his_filter.set_focus_label(self.__combo_focus.currentText()) his_filter.set_include_tags_str(self.__includes) his_filter.set_exclude_tags_str(self.__excludes) return his_filter def load_source_records(self) -> [HistoricalRecord]: records = [] for source in self.__sources: loader = HistoricalRecordLoader() if path.isabs(source): ret = loader.from_file(source) else: ret = loader.from_source(source) if not ret: continue records.extend(loader.get_loaded_records()) return records def load_filter_records(self) -> [HistoricalRecord]: history = self.__history if self.__history is not None else History() records = self.load_source_records() history.set_records(records) his_filter = self.ui_to_filter() return history.select_records(sources=his_filter.get_sources(), focus_label=his_filter.get_focus_label(), include_label_tags=his_filter.get_include_tags(), include_all=False, exclude_label_tags=his_filter.get_exclude_tags(), exclude_any=True) def __label_tag_dict_to_text(self, label_tags_dict: dict): return [key + ': ' + ', '.join(label_tags_dict[key]) for key in label_tags_dict.keys()]
class calcGui(QMainWindow): # QMainWindow Class for the calculator GUI def __init__(self): super().__init__() #self.setStyleSheet(open('css/style.css').read()) self.model = evaluateProblem self.cc = CalcController(self.model, self) # Set Main Window Title self.setWindowTitle("Calculator") #Setting the main widget and the layout that will be used for the calculator self.mainWidget = QWidget(self) self.setCentralWidget(self.mainWidget) #Main layout for the window self.mainLayout = QVBoxLayout() #Put the two dropdowns side by side in horizontal layout self.selectionLayout = QHBoxLayout() #Grid layout for the buttons self.buttonsGrid = QGridLayout() #set layout for the widget self.mainWidget.setLayout(self.mainLayout) #create the buttons, dropdown, screen, etc. self.createDisplay() self.createDropDowns() self.createInitialButtons() #self.color_message = QLabel("Welcome to Calculator.") #Create the coloring options section #self.coloring_options.addWidget(self.color_message) def createDropDowns(self): #dropdown for calculator mode self.modeDropDown = QVBoxLayout() self.selectModeLabel = QLabel("Select Mode") calcType = ["Basic", "Scientific", "Subnet"] self.choose_calc = QComboBox() self.choose_calc.setFixedHeight(40) self.choose_calc.addItems(calcType) self.choose_calc.currentIndexChanged.connect(self.calc_chosen) self.modeDropDown.addWidget(self.selectModeLabel) self.modeDropDown.addWidget(self.choose_calc) self.selectionLayout.addLayout(self.modeDropDown) #dropdown for color theme self.colorDropDown = QVBoxLayout() self.selectColorLabel = QLabel("Select Theme") calcTheme = ["Default", "Peanut Butter Mood", "Orange Berry Blitz!", "Watermelon Breeze", "Razzmatazz", "BananaBerry"] self.choose_theme = QComboBox() self.choose_theme.setFixedHeight(40) self.choose_theme.addItems(calcTheme) self.choose_theme.currentIndexChanged.connect(self.theme_chosen) self.colorDropDown.addWidget(self.selectColorLabel) self.colorDropDown.addWidget(self.choose_theme) self.selectionLayout.addLayout(self.colorDropDown) #add the dropdowns horizontal layout to the main layout self.mainLayout.addLayout(self.selectionLayout) def createDisplay(self): # Create the display widget self.display = QTextEdit() # Set some display's properties self.display.setFixedHeight(60) self.display.setAlignment(Qt.AlignRight) # Add the display to the main layout self.mainLayout.addWidget(self.display) @pyqtSlot() def theme_chosen(self): calcChosen = self.choose_calc.currentText() themeChosen = self.choose_theme.currentText() if(themeChosen == 'Default'): self.setStyleSheet("") elif(themeChosen == 'Peanut Butter Mood'): self.setStyleSheet(open('css/style.css').read()) elif themeChosen == 'Orange Berry Blitz!': self.setStyleSheet(open('css/style2.css').read()) elif themeChosen == 'Watermelon Breeze': self.setStyleSheet(open('css/style3.css').read()) elif themeChosen == 'Razzmatazz': self.setStyleSheet(open('css/style4.css').read()) elif themeChosen == 'BananaBerry': self.setStyleSheet(open('css/style5.css').read()) @pyqtSlot() def calc_chosen(self): calcChosen = self.choose_calc.currentText() if(calcChosen == 'Basic'): self.setWindowTitle('Basic Calculator') self.display.setFixedHeight(60) self.destroyButtons() self.clearDisplay() self.createBasicButtons() elif calcChosen == 'Scientific': self.setWindowTitle('Scientific Calculator') self.destroyButtons() self.clearDisplay() self.createScientificButtons() elif calcChosen == 'Subnet': self.setWindowTitle('Subnet Calculator') self.display.setFixedHeight(180) self.destroyButtons() self.createSubnetButtons() self.clearDisplay() def setDisplayText(self, text): self.display.setText(text) self.display.repaint() def getDisplayText(self): """Get display's text.""" displayText = self.display.toPlainText() return displayText def clearDisplay(self): """Clear the display.""" self.setDisplayText("") @pyqtSlot() def destroyButtons(self): for i in reversed(range(self.buttonsGrid.count())): widgetToRemove = self.buttonsGrid.itemAt(i).widget() # remove it from the layout list self.buttonsGrid.removeWidget(widgetToRemove) # remove it from the gui widgetToRemove.setParent(None) def createInitialButtons(self): """Create the buttons.""" self.buttons = {} # Button text | position on the QGridLayout buttons = { "7": (0, 0), "8": (0, 1), "9": (0, 2), "/": (0, 3), "C": (0, 4), "4": (1, 0), "5": (1, 1), "6": (1, 2), "*": (1, 3), "(": (1, 4), "1": (2, 0), "2": (2, 1), "3": (2, 2), "-": (2, 3), ")": (2, 4), "0": (3, 0), "00": (3, 1), ".": (3, 2), "+": (3, 3), "=": (3, 4), } # Create the buttons and add them to the button grid layout for btnText, pos in buttons.items(): self.buttons[btnText] = QPushButton(btnText) self.buttons[btnText].setFixedSize(80, 80) self.buttonsGrid.addWidget(self.buttons[btnText], pos[0], pos[1]) # Add buttonsGrid to the Main layout self.mainLayout.addLayout(self.buttonsGrid) self.cc.connectButtons() self.buttons["="].clicked.connect(self.cc._calculateResult) @pyqtSlot() def createBasicButtons(self): """Create the buttons.""" self.buttons = {} #buttonsGrid = QGridLayout() # Button text | position on the QGridLayout buttons = { "7": (0, 0), "8": (0, 1), "9": (0, 2), "/": (0, 3), "C": (0, 4), "4": (1, 0), "5": (1, 1), "6": (1, 2), "*": (1, 3), "(": (1, 4), "1": (2, 0), "2": (2, 1), "3": (2, 2), "-": (2, 3), ")": (2, 4), "0": (3, 0), "00": (3, 1), ".": (3, 2), "+": (3, 3), "=": (3, 4), } # Create the buttons and add them to the button grid layout for btnText, pos in buttons.items(): self.buttons[btnText] = QPushButton(btnText) self.buttons[btnText].setFixedSize(80, 80) self.buttonsGrid.addWidget(self.buttons[btnText], pos[0], pos[1]) self.cc.connectButtons() self.buttons["="].clicked.connect(self.cc._calculateResult) @pyqtSlot() def createScientificButtons(self): """Create the buttons.""" self.buttons = {} #buttonsGrid = QGridLayout() # Button text | position on the QGridLayout buttons = { "π": (0,0), "√": (0,1), "log": (0,2), "ln": (0,3), "e": (0,4), "%": (0,5), "7": (1, 0), "8": (1, 1), "9": (1, 2), "sin": (1,3), "/": (1, 4), "C": (1, 5), "4": (2, 0), "5": (2, 1), "6": (2, 2), "cos": (2,3), "*": (2, 4), "(": (2, 5), "1": (3, 0), "2": (3, 1), "3": (3, 2), "tan": (3,3), "-": (3, 4), ")": (3, 5), "0": (4, 0), "00": (4, 1), ".": (4, 2), "^": (4,3), "+": (4, 4), "=": (4, 5), } # Create the buttons and add them to the button grid layout for btnText, pos in buttons.items(): self.buttons[btnText] = QPushButton(btnText) self.buttons[btnText].setFixedSize(80, 80) self.buttonsGrid.addWidget(self.buttons[btnText], pos[0], pos[1]) self.cc.connectButtons() self.buttons["="].clicked.connect(self.cc._calculateResult) #self.buttons @pyqtSlot() def createSubnetButtons(self): """Create the buttons.""" self.buttons = {} # Button text | position on the QGridLayout buttons = { "7": (0, 0), "8": (0, 1), "9": (0, 2), "/": (0, 3), "C": (0, 4), "4": (1, 0), "5": (1, 1), "6": (1, 2), "0": (1, 3), "00": (1, 4), "1": (2, 0), "2": (2, 1), "3": (2, 2), ".": (2, 3), "GO!": (2, 4), } # Create the buttons and add them to the button grid layout for btnText, pos in buttons.items(): self.buttons[btnText] = QPushButton(btnText) self.buttons[btnText].setFixedSize(80, 80) self.buttonsGrid.addWidget(self.buttons[btnText], pos[0], pos[1]) self.cc.connectButtons() self.buttons["GO!"].clicked.connect(self.cc._subnetResult)
class Window2(QDialog): def __init__(self, model, parent=None): super(Window2, self).__init__(parent) self.model = model self.mainLayout = QGridLayout() self.mainLayout.setColumnStretch(0, 1) self.mainLayout.setColumnStretch(1, 3) self.mainLayout.setColumnStretch(2, 3) self.flayout = QFormLayout() self.flayout.addRow('title', QLineEdit()) self.flayout.addRow('author', QLineEdit()) self.flayout.addRow('abstract', QLineEdit()) self.comboBox = QComboBox() self.comboBox.addItems(Scraper.scrapers) self.flayout.addRow('source', self.comboBox) self.table = TableWidget() self.table.doubleClicked.connect(self.openDocument) self.setFixedSize(1000, 600) button1 = QPushButton() button1.setText("Search") button1.clicked.connect(self.search) button2 = QPushButton() button2.setText("Save") button2.clicked.connect(self.save) self.button3 = QPushButton() self.button3.setText("Next") self.button3.clicked.connect(self.next_results) self.button3.setVisible(False) self.button4 = QPushButton() self.button4.setText("Previous") self.button4.clicked.connect(self.previous_results) self.button4.setVisible(False) self.label = QLabel() self.label.setVisible(False) self.setWindowTitle('Search') self.mainLayout.addLayout(self.flayout, 0, 0) self.mainLayout.addWidget(self.table, 0, 1, 1, 2) self.mainLayout.addWidget(self.label, 1, 0) self.mainLayout.addWidget(self.button4, 1, 1) self.mainLayout.addWidget(self.button3, 1, 2) self.mainLayout.addWidget(button1, 2, 0) self.mainLayout.addWidget(button2, 2, 1, 1, 2) self.setLayout(self.mainLayout) def getInputData(self): inputData = { self.flayout.itemAt(2 * i).widget().text(): self.flayout.itemAt(2 * i + 1).widget().text() for i in range(int(self.flayout.count() / 2) - 1) } inputData['source'] = self.comboBox.currentText() return inputData def search(self): inputData = self.getInputData() source = inputData.pop('source') self.scraper = Scraper(inputData, source) logging.info('Scraper search' + str(inputData)) results = self.scraper.search() self.table.fillTable(results) if self.scraper.total > 10: self.button3.setVisible(True) self.update_label() def update_label(self): self.label.setText('Page {} of {}'.format( self.scraper.page, int(self.scraper.total / 10) + 1)) self.label.setVisible(True) def next_results(self): self.scraper.page += 1 results = self.scraper.search() self.table.fillTable(results) self.button4.setVisible(True) if self.scraper.total <= 10 * self.scraper.page: self.button3.setVisible(False) self.update_label() def previous_results(self): self.scraper.page -= 1 results = self.scraper.search() self.table.fillTable(results) self.button3.setVisible(True) if self.scraper.page <= 1: self.button4.setVisible(False) self.update_label() def openDocument(self, y): if 'http' in y.data(): webbrowser.open(y.data(), new=2) def save(self): index = self.table.selectionModel().selectedRows() if len(index) > 0: new_data = { self.table.horizontalHeaderItem(i).text(): str(self.table.model().index(index[0].row(), i).data()) for i in range(self.table.columnCount()) } if 'document' in new_data and 'pdf' in new_data['document']: new_data = self.save_file(new_data) row_index = self.model.rowCount(QModelIndex()) record = self.model.record() record.setGenerated('id', False) record.setValue('created', QDateTime.currentDateTime()) for column in new_data: record.setValue(column, new_data[column]) self.model.insertRecord(-1, record) def save_file(self, new_data): if 'document' in new_data and len(new_data['document']) > 0: author = ', '.join( re.findall(r'(\w*)(?:$|,)', new_data.get('author'))[:-1]) title = re.sub(r"[^a-zA-Z0-9]+", ' ', new_data.get('title')) date = new_data.get('date') if new_data.get('date') else '' filename = date + ' ' + title + ' - ' + author + '.pdf' path = os.path.join(cfg['temp'], filename) logging.info('Trying to save file ' + filename) if not os.path.exists(path): response = requests.get(new_data['document'], headers=_HEADERS) if response.ok: try: with open(path, 'wb') as f: f.write(response.content) try: new_data['length'] = PdfFileReader(open( path, 'rb')).getNumPages() except: display_text = 'Corrupted document ' + filename new_data['document'] = filename display_text = 'Saved document ' + filename except: display_text = 'Dowload document successful, but not possible to save.' new_data['document'] = '' else: display_text = 'Dowload document not successful.' new_data['document'] = '' else: display_text = 'File ' + filename + 'already exists.' else: display_text = 'There is no document to save.' msgBox = QMessageBox() msgBox.setText(display_text) msgBox.exec_() logging.info(display_text) return new_data
class TestStripsDialog(QDialog): GHBox = None KHBox = None pHBox = None NO2Box = None NO3Box = None def __init__(self): super(TestStripsDialog, self).__init__() self.GHBox = QComboBox() self.KHBox = QComboBox() self.pHBox = QComboBox() self.NO2Box = QComboBox() self.NO3Box = QComboBox() self.createFormGroupBox() buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) buttonBox.accepted.connect(self.accept) buttonBox.rejected.connect(self.reject) mainLayout = QVBoxLayout() mainLayout.addWidget(self.formGroupBox) mainLayout.addWidget(buttonBox) self.setLayout(mainLayout) self.setWindowTitle("Aquarium Data Form") def createFormGroupBox(self): self.formGroupBox = QGroupBox("5-in-1 Test Strips") layout = QFormLayout() # Create the GH combobox GHItems = ['0','30','60','120','180'] self.GHBox.addItems(GHItems) # Create the KH combobox KHItems = ['0','40','80','120','180','240'] self.KHBox.addItems(KHItems) # Create the pH combobox pHItems = ['6.0','6.5','7.0','7.5','8.0','8.5','9.0'] self.pHBox.addItems(pHItems) # Create the Nitrite combobox NO2Items = ['0 ppm','0.50 ppm','1.0 ppm','3.0 ppm','5.0 ppm','10.0 ppm'] self.NO2Box.addItems(NO2Items) # Create the Nitrate combobox NO3Items = ['20 ppm','40 ppm','80 ppm','160 ppm','200 ppm'] self.NO3Box.addItems(NO3Items) layout.addRow(QLabel("General Hardness (GH):"), self.GHBox) layout.addRow(QLabel("Carbonate Hardness (KH):"), self.KHBox) layout.addRow(QLabel("pH"), self.pHBox) layout.addRow(QLabel("Nitrite (NO2-):"), self.NO2Box) layout.addRow(QLabel("Nitrate (NO3-):"), self.NO3Box) self.formGroupBox.setLayout(layout) def accept(self): date = datetime.datetime.now() print("\n5-in-1 Test Strip Results - " + str(date)) print(" GH Level:\t\t" + self.GHBox.currentText()) print(" KH Level:\t\t" + self.KHBox.currentText()) print(" pH Level:\t\t" + self.pHBox.currentText()) print(" Nitrite Level:\t" + self.NO2Box.currentText()) print(" Nitrate Level:\t" + self.NO3Box.currentText()) self.writeTestStrips(self.GHBox.currentText(), self.KHBox.currentText(), self.pHBox.currentText(), self.NO2Box.currentText(), self.NO3Box.currentText()) self.done(0) def writeTestStrips(self, GH, KH, pH, NO2, NO3): with open(".aquadata", "r") as fp: tsLine = fp.readline() fmtkLine = fp.readline() tempLine = fp.readline() fmtkLine = GH + "," + KH + "," + pH + "," + NO2 + "," + NO3 + "\n" with open(".aquadata", "w") as fp: fp.write(tsLine) fp.write(fmtkLine) fp.write(tempLine)
class App(QMainWindow): def __init__(self): super().__init__() self.initUI() self.showUI() self.show() def initUI(self): self.setGeometry(100, 50, 850, 600) self.setWindowTitle('Neural Network Interface Solver') self.setWindowIcon(QIcon('brainGUI.png')) self.toolbar = self.addToolBar('Toolbar') self.functions = [sigmoid, sigmoid, sigmoid] self.erf = error def showUI(self): # Central widget and layout wid = QWidget() self.setCentralWidget(wid) grid = QGridLayout() wid.setLayout(grid) grid.setSpacing(5) # Creamos las cuatro cajas que vamos a usar Caja1 = QGroupBox('Dimensión de los datos del entrenamiento') Caja2 = QGroupBox('Área de la representación del error') Caja3 = QGroupBox('Parámetros de la red neuronal') Caja4 = QGroupBox('Zona de resultados') Caja5 = QGroupBox('Zona de botones') Caja1.setObjectName('PrimeraCaja') # Creamos los cuatro layouts. Son 4 Grids, al fin y al cabo. Caja1Layout = QGridLayout() Caja2Layout = QGridLayout() Caja3Layout = QGridLayout() Caja4Layout = QGridLayout() Caja5Layout = QGridLayout() Caja1.setLayout(Caja1Layout) Caja2.setLayout(Caja2Layout) Caja3.setLayout(Caja3Layout) Caja4.setLayout(Caja4Layout) Caja5.setLayout(Caja5Layout) grid.addWidget(Caja1, 0, 0, 1, 2) # 1 Fila - 2 Columnas grid.addWidget(Caja2, 1, 0, 1, 4) # 1 Fila - 4 Columnas grid.addWidget(Caja3, 2, 0, 1, 4) # 1 Fila - 2 Columnas grid.addWidget(Caja4, 0, 4, 2, 1) # 2 Filas - 1 Columna grid.addWidget(Caja5, 3, 0, 3, 4) # 3 Filas - 4 Columnas grid.setColumnStretch(0, 2) Caja1.setSizePolicy( QSizePolicy.Maximum, QSizePolicy.Maximum ) # Con esto se consigue dejar pequeña la mierda esa Caja3.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) # Objects # Plot object self.figure = plt.figure(tight_layout=True) self.canvas = FigureCanvas(self.figure) self.canvas.setMinimumSize( 200, 200) # Esto hace que no se pueda hacer el widget to pequeño ax = self.figure.add_subplot(111) plt.xlabel('Iteración') plt.ylabel('Error') plt.title('Error vs Iteración') self.canvas.draw() # Labels for the functions label1 = QLabel('Input - H1') label2 = QLabel('H1 - H(-1)') label3 = QLabel('H(-1) - Output') label4 = QLabel('Error') label5 = QLabel('Layers') label6 = QLabel('Neurons') label7 = QLabel('Learning rate') label8 = QLabel('Regularization') label9 = QLabel('Resultados:') label10 = QLabel('Dimensión de inputs') label11 = QLabel('Dimensión de outputs') # Selectors for the functions self.combo1 = QComboBox(self) self.combo1.addItem('Sigmoid') self.combo1.addItem('ReLu') self.combo1.addItem('Linear') self.combo1.addItem('SoftMax') self.combo2 = QComboBox(self) self.combo2.addItem('Sigmoid') self.combo2.addItem('ReLu') self.combo2.addItem('Linear') self.combo2.addItem('SoftMax') self.combo3 = QComboBox(self) self.combo3.addItem('Sigmoid') self.combo3.addItem('ReLu') self.combo3.addItem('Linear') self.combo3.addItem('SoftMax') self.combo4 = QComboBox(self) self.combo4.addItem('Quadratic Error') self.combo4.addItem('Cross-Entropy function') # Botones btn = QPushButton('Cargar parámetros') btn.clicked.connect(self.checkParameters) btn2 = QPushButton('Crear Redes Neuronales') btn2.clicked.connect(self.initNetwork) btn3 = QPushButton('Resolver red') btn3.clicked.connect(self.solveNetwork) btn3.setStyleSheet( "font: bold; background-color: cyan; font-size: 26px; border-width: 100px; border-color: black" ) btn3.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) btn4 = QPushButton('Cargar Inputs y Outputs') btn4.clicked.connect(self.readInputs) # Edit Texts self.ed1 = QLineEdit(' ') self.ed2 = QLineEdit(' ') self.ed3 = QLineEdit(' ') self.ed4 = QLineEdit(' ') self.ed1.setText('1') self.ed2.setText('1') self.ed3.setText('1') self.ed4.setText('1') self.ed5 = QLineEdit('1') self.ed6 = QLineEdit('1') self.ed5.setMaximumWidth(30) self.ed6.setMaximumWidth(30) # Bloque de texto self.block = QTextEdit('Status:') self.block.moveCursor(QTextCursor.End) self.block.insertPlainText('\n' + 'Run for results') self.block.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) # Colocamos los objetos # Labels Caja1Layout.addWidget(label10, 0, 0) Caja1Layout.addWidget(label11, 1, 0) Caja1Layout.addWidget(self.ed5, 0, 1) Caja1Layout.addWidget(self.ed6, 1, 1) Caja1Layout.setColumnStretch(1, 3) # Plot Caja2Layout.addWidget(self.canvas, 0, 0) # 1 fila, 4 columnas # Parametros a introducir Caja3Layout.addWidget(label1, 0, 0) Caja3Layout.addWidget(self.combo1, 0, 1) Caja3Layout.addWidget(label2, 1, 0) Caja3Layout.addWidget(self.combo2, 1, 1) Caja3Layout.addWidget(label3, 2, 0) Caja3Layout.addWidget(self.combo3, 2, 1) Caja3Layout.addWidget(label4, 3, 0) Caja3Layout.addWidget(self.combo4, 3, 1) Caja3Layout.addWidget(label5, 0, 2) Caja3Layout.addWidget(self.ed1, 0, 3) Caja3Layout.addWidget(label6, 1, 2) Caja3Layout.addWidget(self.ed2, 1, 3) Caja3Layout.addWidget(label7, 2, 2) Caja3Layout.addWidget(self.ed3, 2, 3) Caja3Layout.addWidget(label8, 3, 2) Caja3Layout.addWidget(self.ed4, 3, 3) # Bloque de texto Caja4Layout.addWidget(label9, 0, 0, 1, 1) Caja4Layout.addWidget(self.block, 1, 0, 1, 1) # Botones Caja5Layout.addWidget(btn, 0, 0) Caja5Layout.addWidget(btn2, 2, 0) Caja5Layout.addWidget(btn3, 0, 1, 3, 3) Caja5Layout.addWidget(btn4, 1, 0) def checkParameters(self): f1s = str(self.combo1.currentText()) f2s = str(self.combo2.currentText()) f3s = str(self.combo3.currentText()) f4s = str(self.combo4.currentText()) if f1s[:2] == 'Si': f1 = sigmoid elif f1s[0] == 'R': f1 = relu elif f1s[0] == 'L': f1 = lin elif f1s[:2] == 'So': f1 = soft if f2s[:2] == 'Si': f2 = sigmoid elif f2s[0] == 'R': f2 = relu elif f2s[0] == 'L': f2 = lin elif f2s[:2] == 'So': f2 = soft if f3s[:2] == 'Si': f3 = sigmoid elif f3s[0] == 'R': f3 = relu elif f3s[0] == 'L': f3 = lin elif f3s[:2] == 'So': f3 = soft if f4s[:2] == 'Qu': f4 = error elif f4s[0] == 'C': f4 = crossEntrop self.functions = [f1, f2, f3] self.erf = f4 self.NI = int(self.ed5.text()) self.NO = int(self.ed6.text()) self.NL = int(self.ed1.text()) self.NN = int(self.ed2.text()) self.lr = float(self.ed3.text()) self.reg = float(self.ed4.text()) print('The functions are: ', self.functions) print('The error calculus is: ', self.erf) print('The dimension of the inputs is: ', self.NI) print('The dimension of the outputs is: ', self.NO) print('The number of layers is: ', self.NL) print('The number of neurons per hidden layer is: ', self.NN) print('The learning rate is: ', self.lr) print('The reg parameter is: ', self.reg) def readInputs(self): fname = QFileDialog.getOpenFileName(self, 'Open File') Inputs_df = read_excel(fname[0]) self.Inputs = np.array(Inputs_df.iloc[:, :self.NI]) self.Outputs = np.array(Inputs_df.iloc[:, self.NI:]) print(self.Inputs.shape) print(self.Outputs.shape) if self.NO != self.Outputs.shape[1]: print( 'AVISO: EL NUMERO DE OUTPUTS NO COINCIDE CON LOS DATOS DADOS') def initNetwork(self): self.Layers = HiddenLayers(self.functions[0], self.functions[1], self.functions[2]) self.Layers.setlayers(self.Inputs.shape[1], self.Outputs.shape[1], self.NL, self.NN) print(self.Layers.f) def solveNetwork(self): self.block.clear() self.calculo = CalculoNeural( NeuralNetwork(self.Inputs, self.Layers.W, self.Layers.b, self.Layers.f, self.lr, self.Outputs), self.erf, self.reg) self.calculo.mySignal.connect( self.setText ) # Se conecta el objeto de señal con el slot de setText, definido abajo # Creamos las listas para guardar los errores self.IterPlot = [] self.ErrorPlot = [] self.calculo.PlotSignal.connect( self.setPlot ) # Lo mismo. Se conecta la señal PlotSignal con el slot de setPlot. self.calculo.start() def setText(self, text): # Este text es lo que se envia con la señal self.block.moveCursor(QTextCursor.End) self.block.insertPlainText('\n' + text) def setPlot(self, value, iteration): print('Iteración: ', iteration, ' Valor del error : ', value) if iteration > 1: self.IterPlot.append(iteration / 10000) self.ErrorPlot.append(value) self.figure.clear() ax = self.figure.add_subplot(111) if iteration > 10000: ax.plot(self.IterPlot, self.ErrorPlot, '-*r') plt.xlabel('Iteración') plt.ylabel('Error') plt.title('Error vs Iteración') self.canvas.draw()
def edit_contact_dialog(wallet_api, contact_key=None): editing = contact_key is not None if editing: title = _("Edit Contact") else: title = _("New Contact") d = WindowModalDialog(wallet_api.wallet_window, title) vbox = QVBoxLayout(d) vbox.addWidget(QLabel(title + ':')) def _contact_insert_completion(text): if text: index = combo1.findText(text) combo1.setCurrentIndex(index) identity_line = QLineEdit() name_line = QLineEdit() combo1 = QComboBox() combo1.setFixedWidth(280) combo1.setEditable(True) # add a filter model to filter matching items contact_filter_model = QSortFilterProxyModel(combo1) contact_filter_model.setFilterCaseSensitivity(Qt.CaseInsensitive) contact_filter_model.setSourceModel(combo1.model()) contact_completer = QCompleter(contact_filter_model, combo1) contact_completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion) combo1.setCompleter(contact_completer) ok_button = OkButton(d) ok_button.setEnabled(False) def _validate_form() -> None: def _set_validation_state(element, is_valid) -> None: if not is_valid: element.setStyleSheet("border: 1px solid red") else: element.setStyleSheet("") can_submit = True system_name = combo1.currentText().lower().strip() is_valid = True try: system_id = get_system_id(system_name) except ContactDataError: system_id = None is_valid = False _set_validation_state(combo1, is_valid) can_submit = can_submit and is_valid identity_text = identity_line.text().strip() if system_id is None: identity_result = IdentityCheckResult.Invalid else: identity_result = wallet_api.check_identity_valid( system_id, identity_text, skip_exists=editing) is_valid = identity_result == IdentityCheckResult.Ok _set_validation_state(identity_line, is_valid) if is_valid: identity_line.setToolTip("") elif identity_result == IdentityCheckResult.Invalid: if system_id == IdentitySystem.OnChain: identity_line.setToolTip(_("Not a valid Bitcoin address")) else: identity_line.setToolTip(_("Incorrect format")) elif identity_result == IdentityCheckResult.InUse: identity_line.setToolTip(_("Already in use")) can_submit = can_submit and is_valid name_text = name_line.text().strip() name_result = wallet_api.check_label(name_text) is_valid = (name_result == IdentityCheckResult.Ok or editing and name_result == IdentityCheckResult.InUse) _set_validation_state(name_line, is_valid) if is_valid: name_line.setToolTip("") elif name_result == IdentityCheckResult.Invalid: name_line.setToolTip(_("Name too short")) elif name_result == IdentityCheckResult.InUse: name_line.setToolTip(_("Name already in use")) can_submit = can_submit and is_valid ok_button.setEnabled(can_submit) def _contact_text_changed(text: str) -> None: _validate_form() combo1.lineEdit().textEdited.connect( contact_filter_model.setFilterFixedString) combo1.editTextChanged.connect(_contact_text_changed) identity_line.textChanged.connect(_contact_text_changed) name_line.textChanged.connect(_contact_text_changed) contact_completer.activated.connect(_contact_insert_completion) combo1.addItems(list(IDENTITY_SYSTEM_NAMES.values())) grid = QGridLayout() identity_line.setFixedWidth(280) name_line.setFixedWidth(280) grid.addWidget(QLabel(_("Identity Type")), 1, 0) grid.addWidget(combo1, 1, 1) grid.addWidget(QLabel(_("Identity")), 2, 0) grid.addWidget(identity_line, 2, 1) grid.addWidget(QLabel(_("Name")), 3, 0) grid.addWidget(name_line, 3, 1) vbox.addLayout(grid) vbox.addLayout(Buttons(CancelButton(d), ok_button)) if contact_key is None: combo1.lineEdit().setText( IDENTITY_SYSTEM_NAMES[IdentitySystem.OnChain]) identity_line.setFocus() else: entry = wallet_api.get_contact(contact_key[0]) identity = [ ci for ci in entry.identities if ci.identity_id == contact_key[1] ][0] combo1.lineEdit().setText(IDENTITY_SYSTEM_NAMES[identity.system_id]) identity_line.setText(identity.system_data) name_line.setText(entry.label) name_line.setFocus() if d.exec_(): name_text = name_line.text().strip() identity_text = identity_line.text().strip() system_id = get_system_id(combo1.currentText()) if contact_key is not None: contact = wallet_api.get_contact(contact_key[0]) identity = [ ci for ci in contact.identities if ci.identity_id == contact_key[1] ][0] if contact_key[1] != identity.identity_id: wallet_api.remove_identity(contact_key[0], contact_key[1]) wallet_api.add_identity(contact_key[0], system_id, identity_text) if contact.label != name_text: wallet_api.set_label(contact_key[0], name_text) else: wallet_api.add_contact(system_id, name_text, identity_text)
class UnicodeSearch(QDialog): def __init__(self, parent): super(UnicodeSearch, self).__init__(parent) self.parent = parent self.selected_item = None self.selected_code = -1 self.recent_searches = [] # таблица с результатами поиска self.results = QTableWidget() self.results.verticalHeader().hide() self.results.horizontalHeader().hide() self.results.horizontalHeader().setSectionResizeMode( QHeaderView.ResizeToContents) self.results.setColumnCount(4) self.results.horizontalHeader().setSectionResizeMode( 3, QHeaderView.Stretch) self.results.setSelectionBehavior(QAbstractItemView.SelectRows) self.results.setEditTriggers(QAbstractItemView.NoEditTriggers) self.results.cellActivated.connect(self.selectItem) # строка поиска, сохраняет введенные ранее строки self.combo = QComboBox() self.combo.setEditable(True) self.combo.setInsertPolicy(QComboBox.NoInsert) self.combo.lineEdit().setClearButtonEnabled(True) self.combo.currentIndexChanged.connect(self.searchClicked) self.search_mode = QComboBox() self.search_mode.addItems(SEARCH_MODES) self.lang_select = QComboBox() self.lang_select.addItems(parent.LANG_STRINGS) current_lang_index = parent.LANG_STRINGS.index(parent.table.lang) self.lang_select.setCurrentIndex(current_lang_index) self.lang_select.currentIndexChanged.connect(self.reloadUT) search_button = QPushButton(parent.search_icon, '') search_button.setToolTip('начать поиск') search_button.clicked.connect(self.searchClicked) top_bar = QHBoxLayout() top_bar.addWidget(self.combo, 1) top_bar.addWidget(self.search_mode) top_bar.addWidget(self.lang_select) top_bar.addWidget(search_button) main_box = QVBoxLayout() main_box.addLayout(top_bar) main_box.addWidget(self.results) self.setLayout(main_box) self.resize(680, 680) self.searchClicked() # перезагрузка имен разделов/символов на указанном языке def reloadUT(self): self.parent.table = UnicodeTable(self.parent.UT_FILENAME, self.lang_select.currentText()) self.search_mode.setCurrentIndex(0) self.combo.setCurrentText('') self.searchClicked() def searchClicked(self): items = [] ut = self.parent.table self.block_mode = False text = self.combo.currentText() if text not in self.recent_searches: self.recent_searches.append(text) self.combo.addItem(text) mode = self.search_mode.currentIndex() if mode == 0: items = ut.find_block_name(text) self.block_mode = True if mode == 1: if len(text) < 3: self.combo.setCurrentText('не меньше 3 букв') else: items = ut.find_symbol_name(text) if mode == 2: items = ut.find_symbols(text) if mode == 3: items = ut.find_codes(text, 16) if mode == 4: items = ut.find_codes(text, 10) self.results.setRowCount(0) for entry in items: row = self.results.rowCount() self.results.insertRow(row) self.results.setItem(row, 0, QTableWidgetItem(entry[0])) self.results.setItem(row, 3, QTableWidgetItem(entry[2])) self.results.setItem(row, 1, QTableWidgetItem(' {:05X}'.format(entry[1]))) self.results.setItem(row, 2, QTableWidgetItem(chr(entry[1]))) self.results.sortByColumn(1, Qt.AscendingOrder) if self.block_mode: self.setWindowTitle('{0} — {1} разделов'.format( self.parent.APP_NAME, len(items))) else: self.setWindowTitle('{0} — {1} символов'.format( self.parent.APP_NAME, len(items))) # выбор одной строки из результатов поиска и # возвращение в главное окно к выбранной позиции, сохраняемой в закладки def selectItem(self, row, column): if self.block_mode: self.selected_item = self.results.item(row, 0).text() else: self.selected_item = '{0} ({1})'.format( self.results.item(row, 3).text(), self.results.item(row, 0).text()) self.selected_code = int(self.results.item(row, 1).text(), 16) self.accept() def keyPressEvent(self, event): if event.key() == Qt.Key_Return: self.searchClicked()
class finance_entry(QWidget): def __init__(self, home_button: QPushButton, parent=None): super().__init__(parent) intValidator = QIntValidator() self.setStyleSheet(QSS) self.current_pending_months = [] self.current_advance_months = [] self.home_button = home_button # -- LEVEL TWO GRID self.grid = QGridLayout() self.grid.setSpacing(20) self.setLayout(self.grid) # -- CELL ZERO self.receipt_label = QLabel("RECEIPT ID :") self.receipt_label.setWordWrap(True) self.receipt_id = QLabel() self.receipt_id.setStyleSheet("font: bold") self.receipt_id.setAlignment(Qt.AlignCenter) currentMonth = datetime.now().month currentYear = datetime.now().year currentReceipt = db_tools.generate_receipt_id(str(currentMonth), str(currentYear)) self.receipt_id.setText(currentReceipt) # --- self.flat_label = QLabel("FLAT NO. :") self.flat_combo = QComboBox() model = self.flat_combo.model() for flat in flats: model.appendRow(QStandardItem(flat)) self.flat_combo.setStyleSheet( 'text-color: black; selection-background-color: rgb(215,215,215)') self.flat_combo.currentIndexChanged['QString'].connect(self.set_name) # --- self.name_label = QLabel("NAME :") self.name_value = QLabel("Mr D. S. Patil") self.name_value.setFixedWidth(200) # --- self.finance_entry_layout0 = QFormLayout() self.finance_entry_layout0.addRow(self.receipt_label, self.receipt_id) self.finance_entry_layout0.addRow(self.flat_label, self.flat_combo) self.finance_entry_layout0.addRow(self.name_label, self.name_value) self.finance_entry_layout0.setVerticalSpacing(90) # -- CELL ONE self.date_label = QLabel("DATE OF TRANSACTION :") self.date_label.setWordWrap(True) self.date_line = QDateEdit() self.date_line.setCalendarPopup(True) self.date_line.setDate(QDate.currentDate()) self.date_line.setDisplayFormat("dd MMMM, yyyy") self.single_radio = QRadioButton("Single Month") self.multiple_radio = QRadioButton("Multiple Months") self.single_radio.setChecked(True) self.single_radio.toggled.connect( lambda: self.months(button=self.single_radio)) self.multiple_radio.toggled.connect( lambda: self.months(button=self.multiple_radio)) self.finance_entry_layout1_h1 = QHBoxLayout() self.finance_entry_layout1_h1.addWidget(self.date_line) self.finance_entry_layout1_h1.addWidget(self.single_radio) self.finance_entry_layout1_h1.addWidget(self.multiple_radio) self.finance_entry_layout1_h1.setSpacing(90) # --- self.month_label = QLabel("FEES FOR :") self.month_combo = QComboBox() self.set_pending_months() self.month_combo.setStyleSheet( 'text-color: black; selection-background-color: rgb(215,215,215)') # --- self.month_till_label = QLabel("FEES TILL :") self.month_till_label.setAlignment(Qt.AlignCenter) self.month_till_combo = QComboBox() self.set_advance_months() self.month_till_combo.setStyleSheet( 'text-color: black; selection-background-color: rgb(215,215,215)') self.finance_entry_layout1_h2 = QHBoxLayout() self.finance_entry_layout1_h2.addWidget(self.month_combo) self.finance_entry_layout1_h2.addWidget(self.month_till_label) self.finance_entry_layout1_h2.addWidget(self.month_till_combo) self.finance_entry_layout1_h2.setSpacing(90) self.month_till_label.setEnabled(False) self.month_till_combo.setEnabled(False) # --- self.amount_label = QLabel("AMOUNT :") self.amount_label.setAlignment(Qt.AlignCenter) self.amount_line = QLineEdit() self.amount_line.setText("1500") self.amount_line.setValidator(intValidator) # --- self.fine_label = QLabel("FINE :") self.fine_label.setAlignment(Qt.AlignCenter) self.fine_line = QLineEdit() if int(self.date_line.text().split(" ")[0]) <= 5: self.fine_line.setText("0") else: self.fine_line.setText("50") self.fine_line.setValidator(intValidator) self.fine_line.setStyleSheet("border: 1px solid red; color: red") self.finance_entry_layout1_h3 = QHBoxLayout() self.finance_entry_layout1_h3.addWidget(self.amount_line) self.finance_entry_layout1_h3.addWidget(self.fine_label) self.finance_entry_layout1_h3.addWidget(self.fine_line) self.finance_entry_layout1_h3.setSpacing(90) # --- self.finance_entry_layout1 = QFormLayout() self.finance_entry_layout1.addRow(self.date_label, self.finance_entry_layout1_h1) self.finance_entry_layout1.addRow(self.month_label, self.finance_entry_layout1_h2) self.finance_entry_layout1.addRow(self.amount_label, self.finance_entry_layout1_h3) self.finance_entry_layout1.setVerticalSpacing(90) # -- CELL TWO self.mode_label = QLabel("PAYMENT MODE :") self.mode_label.setWordWrap(True) # --- self.mode_combo = QComboBox() self.mode_combo.addItem("Cash") self.mode_combo.addItem("Online Funds Transfer") self.mode_combo.addItem("Cheque") self.mode_combo.setStyleSheet( 'text-color: black; selection-background-color: rgb(215,215,215)') self.mode_combo.currentIndexChanged['QString'].connect( self.mode_selection) # --- self.ref_label = QLabel("REFERENCE ID :") self.ref_label.setWordWrap(True) self.ref_line = QLineEdit() self.ref_label.setDisabled(True) self.ref_line.setDisabled(True) self.total_label = QLabel( f"TOTAL PAYABLE AMOUNT : {int(self.amount_line.text()) + int(self.fine_line.text())}" ) self.total_label.setWordWrap(True) self.total_label.setAlignment(Qt.AlignCenter) self.save_button = QPushButton("SAVE") self.save_button.setStyleSheet("font: bold") self.save_button.clicked.connect(lambda: self.check_form()) self.status = QLabel("Ready") self.status.setStyleSheet("font: 8pt") self.status.setAlignment(Qt.AlignCenter) self.bar = QProgressBar(self) self.bar.setMaximum(100) self.bar.setValue(0) self.bar.setToolTip("Please wait until the process is completed.") # --- self.finance_entry_layout2 = QFormLayout() self.finance_entry_layout2.addRow(self.mode_label, self.mode_combo) self.finance_entry_layout2.addRow(self.ref_label, self.ref_line) self.finance_entry_layout2.addItem(create_spacer_item(w=5, h=30)) self.finance_entry_layout2.addRow(self.total_label) self.finance_entry_layout2.addRow(self.save_button) self.finance_entry_layout2.addRow(self.status) self.finance_entry_layout2.addRow(self.bar) self.finance_entry_layout2.setVerticalSpacing(50) self.finance_entry_group0 = QGroupBox() self.finance_entry_group0.setLayout(self.finance_entry_layout0) self.finance_entry_group1 = QGroupBox() self.finance_entry_group1.setLayout(self.finance_entry_layout1) self.finance_entry_group2 = QGroupBox() self.finance_entry_group2.setLayout(self.finance_entry_layout2) self.finance_entry_group2.setFixedWidth(550) # -- FUNCTIONALITY: self.date_line.dateChanged.connect(lambda: self.set_pending_months( date=str(self.date_line.date().toPyDate()))) self.month_combo.currentIndexChanged['QString'].connect( self.set_advance_months) self.month_combo.currentIndexChanged['QString'].connect( lambda ind: self.calculate_fine('from', ind)) self.month_till_combo.currentIndexChanged['QString'].connect( lambda ind: self.calculate_fine('till', ind)) self.month_combo.currentTextChanged.connect(self.calculate_amount) self.month_till_combo.currentTextChanged.connect(self.calculate_amount) self.amount_line.textChanged.connect(self.set_total) self.fine_line.textChanged.connect(self.set_total) # -- FINANCE ENTRY GRID self.grid.addWidget(self.finance_entry_group0, 0, 0, 2, 1) self.grid.addWidget(self.finance_entry_group1, 0, 1, 2, 1) self.grid.addWidget(self.finance_entry_group2, 0, 2, 2, 1) def months(self, button): if button.isChecked(): if button.text() == "Single Month": self.month_till_label.setEnabled(False) self.month_till_combo.setEnabled(False) elif button.text() == "Multiple Months": self.month_till_label.setEnabled(True) self.month_till_combo.setEnabled(True) self.calculate_amount() def mode_selection(self, selection): if selection == "Cash": self.ref_label.setText("REFERENCE ID :") self.ref_label.setDisabled(True) self.ref_line.setDisabled(True) elif selection == "Cheque": self.ref_label.setText("CHEQUE NO. :") self.ref_label.setDisabled(False) self.ref_line.setDisabled(False) elif selection == "Online Funds Transfer": self.ref_label.setText("REFERENCE ID :") self.ref_label.setDisabled(False) self.ref_line.setDisabled(False) def check_form(self): reply = QMessageBox() if len(self.amount_line.text()) == 0: reply.setIcon(QMessageBox.Warning) reply.setText("AMOUNTS field cannot be left empty.") reply.setStandardButtons(QMessageBox.Retry) reply.setWindowTitle("INVALID ENTRY") reply.exec_() elif len(self.fine_line.text()) == 0: reply.setIcon(QMessageBox.Warning) reply.setText("FINE field cannot be left empty.") reply.setStandardButtons(QMessageBox.Retry) reply.setWindowTitle("INVALID ENTRY") reply.exec_() elif self.ref_line.isEnabled() and len(self.ref_line.text()) == 0: reply.setIcon(QMessageBox.Warning) reply.setText( "Please enter the REFERENCE INFORMATION for the transaction.") reply.setStandardButtons(QMessageBox.Retry) reply.setWindowTitle("INVALID ENTRY") reply.exec_() elif payment_exists(flat=self.flat_combo.currentText(), month=self.month_combo.currentText()): reply.setIcon(QMessageBox.Warning) reply.setText( f"This member ({self.flat_combo.currentText()}) has already paid the fees for the month of {self.month_combo.currentText()}" ) reply.setStandardButtons(QMessageBox.Retry) reply.setWindowTitle("INVALID ENTRY") reply.exec_() else: if self.month_till_combo.isEnabled(): fee_till = f" - {self.month_till_combo.currentText()}" else: fee_till = '' if self.ref_line.isEnabled(): ref = f" - ({self.ref_line.text()})" else: ref = '' detailed_text = f"Date : {fix_date(str(self.date_line.date().toPyDate()))}\n" \ f"Fee for : {str(self.month_combo.currentText())}{fee_till}\n" \ f"Flat No : {str(self.flat_combo.currentText())}\n" \ f"Amount : {float(self.amount_line.text())}\n" \ f"Fine : {float(self.fine_line.text())}\n" \ f" -> TOTAL : {str(int(self.amount_line.text()) + int(self.fine_line.text()))} <-\n" \ f"Payment Mode : {str(self.mode_combo.currentText())}{ref}" reply.setWindowTitle("SUCCESSFUL ENTRY") reply.setIcon(QMessageBox.Information) reply.setText("ENTRY HAS BEEN RECORDED.\n") reply.setInformativeText("Please confirm the details below.") reply.setDetailedText(detailed_text) confirm_button = reply.addButton('Confirm', QMessageBox.AcceptRole) edit_button = reply.addButton('Edit', QMessageBox.RejectRole) confirm_button.clicked.connect( lambda: self.final_clicked(button=confirm_button)) edit_button.clicked.connect( lambda: self.final_clicked(button=edit_button)) reply.exec_() def set_name(self, flat): name = get_name(flat) self.name_value.setText(str(name)) def add_entry(self): receipt_id = self.receipt_id.text() date = str(self.date_line.date().toPyDate()) fee_month = self.month_combo.currentText() if self.month_till_combo.isEnabled(): fee_till = self.month_till_combo.currentText() month = f"{fee_month}-{fee_till}" else: fee_till = '' month = fee_month flat = str(self.flat_combo.currentText()) amount = float(self.amount_line.text()) fine = float(self.fine_line.text()) mode = str(self.mode_combo.currentText()) if self.ref_line.isEnabled(): ref = self.ref_line.text() else: ref = '' print(fee_month) new_receipt = receipt.receipt(date=fix_date(date), flat=flat, month=fee_month, month_till=fee_till, amount=amount, fine=fine, mode=mode, ref=ref) self.disable() self.total_label.setText( "Confirming.. PLEASE DO NOT PERFORM ANY OTHER OPERATIONS.") new_receipt.add_to_db() self.status.setText("Adding to databse & Generating receipt") self.bar.setValue(40) design_receipt(receipt_id=f"0{receipt_id}") self.status.setText( "Sending the receipt to the member. (Depends on your internet connection)" ) self.bar.setValue(75) email_status = send_receipt(flat=flat, month=month) self.enable() self.set_total() if email_status: self.bar.setValue(100) else: reply = QMessageBox() reply.setIcon(QMessageBox.Warning) reply.setText( "The system cannot access the internet. Make sure you have an active connection, or any firewall" "feature blocking the access.") reply.setStandardButtons(QMessageBox.Retry) reply.setWindowTitle("INTERNET") reply.exec_() def final_clicked(self, button): if button.text() == "Confirm": self.add_entry() currentReceipt = db_tools.generate_receipt_id( str(datetime.now().month), str(datetime.now().year)) self.receipt_id.setText(currentReceipt) self.flat_combo.setCurrentIndex(0) self.name_value.setText("Mr D. S. Patil") self.amount_line.setText('1500') if int(self.date_line.text().split(" ")[0]) <= 5: self.fine_line.setText("0") else: self.fine_line.setText("50") self.bar.setValue(0) self.status.setText("Done !") self.ref_line.clear() def set_pending_months(self, date: str = None): if date is None: date = str(self.date_line.date().toPyDate()) months = calculate_months(month=date, pending=True, advance=False) self.current_pending_months = months self.month_combo.clear() model = self.month_combo.model() for month in months: model.appendRow(QStandardItem(month)) def set_advance_months(self, date: str = None): if date is None or date == '': date = fix_date_back(self.current_pending_months[0]) else: date = fix_date_back(date) months = calculate_months(month=date, pending=False, advance=True) self.current_advance_months = months self.month_till_combo.clear() model = self.month_till_combo.model() for month in months: model.appendRow(QStandardItem(month)) def calculate_amount(self): if self.month_combo.count() == 0 or self.month_till_combo.count() == 0: self.amount_line.setText('0') return else: all_possible_months = self.current_advance_months.copy() all_possible_months = all_possible_months[::-1] all_possible_months.extend([ x for x in self.current_pending_months if x not in self.current_advance_months ]) if self.month_till_combo.isEnabled(): from_index = all_possible_months.index( self.month_combo.currentText()) till_index = all_possible_months.index( self.month_till_combo.currentText()) amount = (from_index - till_index + 1) * 1500 else: amount = 1500 self.amount_line.setText(str(amount)) self.amount_line.setToolTip(f"Total months : {amount//1500}") def calculate_fine(self, from_where: str, month): if month == '' and self.month_combo.count( ) == 0 or self.month_till_combo.count() == 0: self.fine_line.setText('0') return else: if self.month_till_combo.isEnabled(): try: till_index = self.current_pending_months.index( str(self.month_till_combo.currentText())) except ValueError: till_index = 0 else: try: till_index = self.current_pending_months.index( str(self.month_combo.currentText())) except ValueError: self.fine_line.setText('0') return try: from_index = self.current_pending_months.index( str(self.month_combo.currentText())) except ValueError: self.fine_line.setText('0') return all_fine_months = [] for month in self.current_pending_months[till_index:from_index + 1]: all_fine_months.append([month]) transact_date = str(self.date_line.date().toPyDate()) total_fine = 0 for month in all_fine_months: fine = calculate_fine(month=month[0], transact_date=fix_date(transact_date)) month = month.append(fine) total_fine += fine * 50 self.fine_line.setText(str(total_fine)) self.set_fine_tip(all_fine_months=all_fine_months) def set_fine_tip(self, all_fine_months: list): tool_line = '' for month in all_fine_months: tool_line += f"{month[0]} x {month[1]}\n" self.fine_line.setToolTip(tool_line) def set_total(self): if len(self.amount_line.text()) > 0: amount = float(self.amount_line.text()) else: amount = 0 if len(self.fine_line.text()) > 0: fine = int(self.fine_line.text()) else: fine = 0 self.total_label.setText(f"TOTAL PAYABLE AMOUNT : {amount + fine}") def disable(self): self.finance_entry_group0.setEnabled(False) self.finance_entry_group1.setEnabled(False) self.home_button.setEnabled(False) self.mode_label.setEnabled(False) self.mode_combo.setEnabled(False) self.ref_label.setEnabled(False) self.ref_line.setEnabled(False) self.save_button.setEnabled(False) def enable(self): self.finance_entry_group0.setEnabled(True) self.finance_entry_group1.setEnabled(True) self.home_button.setEnabled(True) self.home_button.setEnabled(True) self.mode_label.setEnabled(True) self.mode_combo.setEnabled(True) self.ref_label.setEnabled(True) self.ref_line.setEnabled(True) self.save_button.setEnabled(True)
class RedditScraperWindow(QWidget): """The main window of the program.""" ########### Setup ################################## def __init__(self): super().__init__() self.read_user_config() self.load_assets() self.initialize_ui() def load_assets(self): script_folder = os.path.dirname( os.path.dirname(os.path.abspath(__file__))) asset_folder = os.path.join(script_folder, "assets") if os.path.isdir(asset_folder): self.download_icon = QIcon( os.path.join(asset_folder, 'download_icon.png')) self.stop_icon = QIcon(os.path.join(asset_folder, 'stop_icon.png')) self.reddit_icon = QIcon( os.path.join(asset_folder, 'reddit_icon.png')) else: self.download_icon = QIcon( os.path.join("assets", 'download_icon.png')) self.stop_icon = QIcon(os.path.join("assets", 'stop_icon.png')) self.reddit_icon = QIcon(os.path.join("assets", 'reddit_icon.png')) def initialize_ui(self): """sets up the user interface, connects all the signals and shows the window. """ self.init_components() self.read_settings_config() self.connect_signals() self.setGeometry(100, 100, 1000, 800) self.setWindowTitle('Reddit Image Scraper') self.setWindowIcon(self.reddit_icon) self.show() def init_components(self): """initializes all components and sets up the layout""" internalWidgetInput = QWidget() internalWidgetTree = QWidget() ############ define components #################### self.subredditInput = QComboBox() self.subredditInput.setEditable(True) self.subredditInput.addItems(self.get_downloaded_subreddits()) self.numInput = QLineEdit() self.onlyInt = QIntValidator() self.numInput.setValidator(self.onlyInt) subredditLabel = QLabel('subreddit') numLabel = QLabel('number of images') self.dirLabel = QLabel('choose a directory') scale_label = QLabel("Scale images?") self.imgView = QLabel() self.outputText = QTextEdit('') self.outputText.setReadOnly(True) self.scale_cb = QCheckBox() self.sortingCb = QComboBox() self.sortingCb.addItems([ "Hot", "Top all time", "Top this month", "Top past year", "New", "Controversial" ]) sortingLabel = QLabel('sorting method') self.runButton = QPushButton('Download') self.runButton.setIcon(self.download_icon) self.chooseDirButton = QPushButton('Save dir') self.stopButton = QPushButton('Stop') self.stopButton.setIcon(self.stop_icon) self.fileModel = QFileSystemModel() self.tree = QTreeView() self.tree.setModel(self.fileModel) self.tree.setColumnHidden(1, True) self.tree.setColumnHidden(2, True) self.tree.setColumnHidden(3, True) ############## Menu stuff ################### menu_bar = QMenuBar() file_menu = menu_bar.addMenu('File') help_menu = menu_bar.addMenu('Help') self.exit_action = QAction('Exit', self) file_menu.addAction(self.exit_action) self.help_action = QAction('Help', self) help_menu.addAction(self.help_action) menu_bar.setFixedHeight(30) ############# Setup the grid layout############################### grid = QGridLayout() # grid.addWidget(menu_bar, 1, 0, 1, 4) grid.setSpacing(4) grid.addWidget(subredditLabel, 1, 0) grid.addWidget(self.subredditInput, 1, 1) grid.addWidget(numLabel, 2, 0) grid.addWidget(self.numInput, 2, 1) grid.addWidget(sortingLabel, 3, 0) grid.addWidget(self.sortingCb, 3, 1) grid.addWidget(self.chooseDirButton, 4, 0) grid.addWidget(self.dirLabel, 4, 1) grid.addWidget(self.stopButton, 5, 0) grid.addWidget(self.runButton, 5, 1) grid.addWidget(self.outputText, 7, 0, 7, 2) # grid.addWidget(self.tree,1,2, 11,7) grid.addWidget(scale_label, 6, 0) grid.addWidget(self.scale_cb, 6, 1) hboxTree = QVBoxLayout() hboxTree.addWidget(self.tree) #the image viewer, setting how it behaves under resizing. self.imgView.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.imgView.setMaximumHeight(MAX_IMAGE_HEIGHT) self.imgView.setAlignment(Qt.AlignmentFlag.AlignCenter) img_scroll_area = QScrollArea() img_scroll_area.setMinimumHeight(MAX_IMAGE_HEIGHT) img_scroll_area.setMinimumWidth(MAX_IMAGE_HEIGHT) img_scroll_area.setWidget(self.imgView) internalWidgetInput.setLayout(grid) # internalWidgetInput.setMinimumWidth(300) internalWidgetInput.setFixedWidth(300) internalWidgetInput.setSizePolicy( QSizePolicy(QSizePolicy.Fixed, QSizePolicy.MinimumExpanding)) internalWidgetTree.setLayout(hboxTree) internalWidgetTree.setFixedWidth(360) internalWidgetTree.setSizePolicy( QSizePolicy(QSizePolicy.Fixed, QSizePolicy.MinimumExpanding)) #construct layout of main window. hbox = QHBoxLayout() hbox.setSpacing(0) hbox.setContentsMargins(0, 0, 0, 0) hbox.setMenuBar(menu_bar) hbox.addWidget(internalWidgetInput) hbox.addWidget(internalWidgetTree) hbox.addWidget(img_scroll_area) self.setLayout(hbox) def connect_signals(self): """connects all the signals to the right functions""" self.chooseDirButton.clicked.connect(self.show_dir_dialog) self.runButton.clicked.connect(self.run_download_threaded) self.tree.clicked.connect(self.on_treeView_clicked) self.stopButton.clicked.connect(self.stop_download) self.scale_cb.clicked.connect(self.refresh_image) self.exit_action.triggered.connect(exit) #self.edit_login_action.triggered.connect(self.edit_login_info) self.help_action.triggered.connect(self.show_help) self.tree.selectionModel().selectionChanged.connect( self.on_selection_change) def read_user_config(self): """reads in the users username and password from the config file, or if there is no config file, shows an input dialog. Also tests so that only valid login information gets saved to the config file. """ config = configparser.ConfigParser() self.redditScraper = redditScraper() if os.path.exists('redditScraper.ini'): config.read('redditScraper.ini') if 'DIR' in config: self.folder = config['DIR']['root_folder'] else: config['REDDIT'] = { 'subreddit': "wallpapers", 'num': 10, 'sorting': "Hot", 'downloaded_subreddits': "" } with open('redditScraper.ini', 'w') as configfile: config.write(configfile) self.config = config def read_settings_config(self): """reads the saved settings from the config file, if they're there.""" if 'DIR' in self.config: self.folder = self.config['DIR']['root_folder'] idx = self.fileModel.setRootPath(str(self.folder)) self.tree.setRootIndex(idx) self.dirLabel.setText(self.folder) if 'REDDIT' in self.config: self.subredditInput.setCurrentText( self.config['REDDIT']['subreddit']) self.numInput.setText(self.config['REDDIT']['num']) self.sortingCb.setCurrentText(self.config['REDDIT']['sorting']) ################### Actions: ################## @pyqtSlot(QModelIndex) def on_treeView_clicked(self, index): """triggers when the user clicks on a file item shown in the treeView, and shows that file in the picture viewer.""" index = self.fileModel.index(index.row(), 0, index.parent()) self.show_image(index) def on_selection_change(self, selected: QItemSelection, deselected: QItemSelection): """ Triggers when the selected item in the treeview changes, and updates the shown picture. """ self.refresh_image() def refresh_image(self): selected_image_index = self.tree.selectedIndexes()[0] self.show_image(selected_image_index) def show_image(self, index: QModelIndex): filePath = self.fileModel.filePath(index) if os.path.isfile(filePath) and filePath.split(".")[-1] in [ "jpg", "gif", "png", "jpeg" ]: pixmap = QPixmap(filePath) if self.scale_cb.isChecked(): self.imgView.setFixedHeight(MAX_IMAGE_HEIGHT) scaled_img = pixmap.scaledToHeight(MAX_IMAGE_HEIGHT) self.imgView.setFixedWidth(scaled_img.width()) self.imgView.setPixmap(scaled_img) else: self.imgView.setFixedHeight(pixmap.height()) self.imgView.setFixedWidth(pixmap.width()) self.imgView.setPixmap(pixmap) def show_dir_dialog(self): """lets the user select the root folder, and saves the choice to the config file.""" self.folder = QFileDialog.getExistingDirectory( self, 'Choose base directory', '/home') self.dirLabel.setText(self.folder) self.config['DIR'] = {'root_folder': self.folder} with open('redditScraper.ini', 'w') as configfile: self.config.write(configfile) idx = self.fileModel.setRootPath(self.folder) self.tree.setRootIndex(idx) return self.folder @pyqtSlot(str) def update_output_text(self, message: str): """updates the output text area, to show progress on downloads.""" self.outputText.setText(message + self.outputText.toPlainText()) def save_subreddit(self, subreddit: str, num: int, sorting: str): """helper function to save the current settings to the config file.""" downloaded_subreddits = self.get_downloaded_subreddits() if subreddit not in downloaded_subreddits: downloaded_subreddits.append(subreddit) self.subredditInput.addItem(subreddit) downloaded_subreddits = ','.join(downloaded_subreddits) self.config['REDDIT'] = { 'subreddit': subreddit, 'num': str(num), 'sorting': sorting, 'downloaded_subreddits': downloaded_subreddits } with open('redditScraper.ini', 'w') as configfile: self.config.write(configfile) def get_downloaded_subreddits(self) -> list: if 'downloaded_subreddits' in self.config['REDDIT'].keys(): subreddits = self.config['REDDIT']['downloaded_subreddits'].split( ',') return subreddits return [] def run_download_threaded(self): """downloads the pictures. Runs in a QThread, so that the program does not freeze. Also checks whether the specified subreddit exists. """ subreddit = self.subredditInput.currentText() num = int(self.numInput.text()) sorting = self.sortingCb.currentText() if self.redditScraper.sub_exists(subreddit): if not hasattr(self, "folder"): msgBox = QMessageBox() msgBox.setText('You need to set a download folder!') msgBox.setWindowTitle("Pick a download folder") msgBox.exec_() return self.save_subreddit(subreddit, num, sorting) self.get_thread = RedditDownloadThread( self.redditScraper, subreddit, num, num * LOOKUP_LIMIT_MULTIPLIER, sorting, self.folder) self.get_thread.changeText.connect(self.update_output_text) self.get_thread.start() else: msgBox = QMessageBox() msgBox.setText('That subreddit does not exist, please try again') msgBox.setWindowTitle("Invalid subreddit") msgBox.exec_() pass def stop_download(self): """Stops the download thread and prints a message to the output.""" try: if self.get_thread.isRunning(): self.get_thread.terminate() self.outputText.setText(self.outputText.toPlainText() + ' Aborted!\n') except Exception: pass ############### Menu actions: ############### def show_help(self): msgBox = QMessageBox() msgBox.setWindowIcon(self.reddit_icon) msgBox.setText( 'This program downloads images posted to reddit.com, or more specifically, to subreddits' + '(i.e. sub-forums). To use it, one needs a valid reddit account, which one can sign up for ' + 'on reddit.com. One also needs to know some names of subreddits. \n Some suggestions for subreddits: ' + 'wallpapers , earthporn , nature , and pics . \n \n ' + "This program will download up to the specified number of images. It can handle png, jpg and gif," + "so links to gyf-files, videos or anything else will be ignored. Therefore the number of images actually " + "downloaded will usually be less than the specified number. So if you want a lot of images, just put" + " a large limit.\n The images will be placed in a subfolder of the chosen base folder, named after the subreddit. This folder will be created if it does not exist.\n \n " + "To view the images, click on them in the tree-view, and they will appear on the right" ) msgBox.setWindowTitle("Help") msgBox.exec_()
class BookManage(QGroupBox): def __init__(self): super().__init__() self.book_list = [] self.body = QVBoxLayout() self.table = None self.setTitleBar() self.setSearchBar() self.searchFunction() self.setLayout(self.body) self.initUI() def errorBox(self, mes: str): msgBox = QMessageBox( QMessageBox.Warning, "警告!", mes, QMessageBox.NoButton, self ) msgBox.addButton("确认", QMessageBox.AcceptRole) msgBox.exec_() # 标题栏 def setTitleBar(self): self.title = QLabel() self.title.setText('书籍信息管理') self.title.setFixedHeight(25) titleLayout = QHBoxLayout() titleLayout.addSpacing(50) titleLayout.addWidget(self.title) self.titleBar = QWidget() self.titleBar.setFixedSize(1000, 50) self.titleBar.setLayout(titleLayout) self.body.addWidget(self.titleBar) # 设置搜索框 def setSearchBar(self): self.selectBox = QComboBox() self.selectBox.addItems(['书号', '分类', '出版社', '作者', '书名']) self.selectBox.setFixedHeight(30) self.searchTitle = QLabel() self.searchTitle.setText('搜索书籍') self.searchInput = QLineEdit() self.searchInput.setText('') self.searchInput.setClearButtonEnabled(True) self.searchInput.setFixedSize(400, 40) self.searchButton = QToolButton() self.searchButton.setFixedSize(100, 40) self.searchButton.setText('搜索') self.searchButton.clicked.connect(self.searchFunction) self.addNewBookButton = QToolButton() self.addNewBookButton.setFixedSize(120, 40) self.addNewBookButton.setText('插入新书') self.addNewBookButton.clicked.connect(self.addNewBookFunction) searchLayout = QHBoxLayout() searchLayout.addStretch() searchLayout.addWidget(self.selectBox) searchLayout.addWidget(self.searchTitle) searchLayout.addWidget(self.searchInput) searchLayout.addWidget(self.searchButton) searchLayout.addWidget(self.addNewBookButton) searchLayout.addStretch() self.searchWidget = QWidget() self.searchWidget.setLayout(searchLayout) self.body.addWidget(self.searchWidget) # 搜索方法 def searchFunction(self): convert = {'书号': 'BID', '分类': 'CLASSIFICATION', '出版社': 'PRESS', '作者': 'AUTHOR', '书名': 'BNAME', '': 'BNAME'} self.book_list = database.search_book(self.searchInput.text(), convert[self.selectBox.currentText()]) if self.book_list == []: self.errorBox('未找到') if self.table is not None: self.table.deleteLater() self.setTable() # 设置表格 def setTable(self): self.table = QTableWidget(1, 9) self.table.setContentsMargins(10, 10, 10, 10) self.table.verticalHeader().setVisible(False) self.table.horizontalHeader().setVisible(False) self.table.setEditTriggers(QAbstractItemView.NoEditTriggers) self.table.setFocusPolicy(Qt.NoFocus) self.table.setColumnWidth(0, 80) # self.table.setColumnWidth(1, 150) # self.table.setColumnWidth(2, 125) # self.table.setColumnWidth(3, 125) # self.table.setColumnWidth(4, 100) self.table.setColumnWidth(6, 80) self.table.setItem(0, 0, QTableWidgetItem('书号')) self.table.setItem(0, 1, QTableWidgetItem('书名')) self.table.setItem(0, 2, QTableWidgetItem('作者')) self.table.setItem(0, 3, QTableWidgetItem('出版日期')) self.table.setItem(0, 4, QTableWidgetItem('出版社')) self.table.setItem(0, 5, QTableWidgetItem('分类')) self.table.setItem(0, 6, QTableWidgetItem('位置')) self.table.setItem(0, 7, QTableWidgetItem('总数/剩余')) self.table.setItem(0, 8, QTableWidgetItem('操作')) for i in range(9): self.table.item(0, i).setTextAlignment(Qt.AlignCenter) self.table.item(0, i).setFont(QFont('微软雅黑', 15)) # 显示借阅详情 for i in self.book_list: self.insertRow(i) self.body.addWidget(self.table) # 插入行 def insertRow(self, val: list): itemBID = QTableWidgetItem(val[0]) itemBID.setTextAlignment(Qt.AlignCenter) itemNAME = QTableWidgetItem('《' + val[1] + '》') itemNAME.setTextAlignment(Qt.AlignCenter) itemAUTHOR = QTableWidgetItem(val[2]) itemAUTHOR.setTextAlignment(Qt.AlignCenter) itemDATE = QTableWidgetItem(val[3]) itemDATE.setTextAlignment(Qt.AlignCenter) itemPRESS = QTableWidgetItem(val[4]) itemPRESS.setTextAlignment(Qt.AlignCenter) itemPOSITION = QTableWidgetItem(val[5]) itemPOSITION.setTextAlignment(Qt.AlignCenter) itemSUM = QTableWidgetItem(str(val[6])+'/'+str(val[7])) itemSUM.setTextAlignment(Qt.AlignCenter) itemCLASSIFICATION = QTableWidgetItem(val[8]) itemCLASSIFICATION.setTextAlignment(Qt.AlignCenter) itemModify = QToolButton(self.table) itemModify.setFixedSize(50, 25) itemModify.setText('修改') itemModify.clicked.connect(lambda: self.updateBookFunction(val[0])) itemModify.setStyleSheet(''' *{ color: white; font-family: 微软雅黑; background: rgba(38, 175, 217, 1); border: 0; border-radius: 10px; } ''') itemDelete = QToolButton(self.table) itemDelete.setFixedSize(50, 25) itemDelete.setText('删除') itemDelete.clicked.connect(lambda: self.deleteBookFunction(val[0])) itemDelete.setStyleSheet(''' *{ color: white; font-family: 微软雅黑; background: rgba(222, 52, 65, 1); border: 0; border-radius: 10px; } ''') itemLayout = QHBoxLayout() itemLayout.setContentsMargins(0, 0, 0, 0) itemLayout.addWidget(itemModify) itemLayout.addWidget(itemDelete) itemWidget = QWidget() itemWidget.setLayout(itemLayout) self.table.insertRow(1) self.table.setItem(1, 0, itemBID) self.table.setItem(1, 1, itemNAME) self.table.setItem(1, 2, itemAUTHOR) self.table.setItem(1, 3, itemDATE) self.table.setItem(1, 4, itemPRESS) self.table.setItem(1, 5, itemCLASSIFICATION) self.table.setItem(1, 6, itemPOSITION) self.table.setItem(1, 7, itemSUM) self.table.setCellWidget(1, 8, itemWidget) def updateBookFunction(self, BID: str): book_info = database.get_book_info(BID) if book_info is None: return self.sum = book_info['SUM'] self.updateBookDialog = book_information.BookInfo(book_info) self.updateBookDialog.after_close.connect(self.updateBook) self.updateBookDialog.show() def updateBook(self, book_info: dict): change = self.sum - book_info['SUM'] # 书本减少的数量不能大于未借出的书本数 if change > book_info['NUM']: book_info['SUM'] = self.sum - book_info['NUM'] book_info['NUM'] = 0 else: book_info['NUM'] -= change ans = database.update_book(book_info) if ans: self.searchFunction() def addNewBookFunction(self): self.newBookDialog = book_information.BookInfo() self.newBookDialog.show() self.newBookDialog.after_close.connect(self.addNewBook) def addNewBook(self, book_info: dict): ans = database.new_book(book_info) if ans: self.searchFunction() def deleteBookFunction(self, BID: str): msgBox = QMessageBox(QMessageBox.Warning, "警告!", '您将会永久删除这本书以及相关信息!', QMessageBox.NoButton, self) msgBox.addButton("确认", QMessageBox.AcceptRole) msgBox.addButton("取消", QMessageBox.RejectRole) if msgBox.exec_() == QMessageBox.AcceptRole: ans = database.delete_book(BID) if ans: self.searchFunction() def initUI(self): self.setFixedSize(1100, 600) self.setStyleSheet(''' *{ background-color: white; border:0px; } ''') self.titleBar.setStyleSheet(''' QWidget { border:0; background-color: rgba(216, 216, 216, 1); border-radius: 20px; color: rgba(113, 118, 121, 1); } QLabel{ font-size: 25px; font-family: 微软雅黑; } ''') self.searchTitle.setStyleSheet(''' QLabel{ font-size:25px; color: black; font-family: 微软雅黑; } ''') self.searchInput.setStyleSheet(''' QLineEdit{ border: 1px solid rgba(201, 201, 201, 1); border-radius: 5px; color: rgba(120, 120, 120, 1) } ''') self.searchButton.setStyleSheet(''' QToolButton{ border-radius: 10px; background-color:rgba(135, 206, 235, 1); color: white; font-size: 25px; font-family: 微软雅黑; } ''') self.addNewBookButton.setStyleSheet(''' QToolButton{ border-radius: 10px; background-color:rgba(135, 206, 235, 1); color: white; font-size: 25px; font-family: 微软雅黑; } ''') self.selectBox.setStyleSheet(''' *{ border: 0px; } QComboBox{ border: 1px solid rgba(201, 201, 201, 1); } ''')
class CourseInputDialog(QWidget): loaddashlayout = pyqtSignal(int) refreshCourses_request = pyqtSignal() def __init__(self, user: User, parent=None): super(CourseInputDialog, self).__init__(parent) self.controller = CourseInputController() self.user = user if (isinstance(user, Professor) == True): self.StartProf() elif (isinstance(user, Student) == True): self.StartStud() #***************************************************************************************************** def StartStud(self): self.setWindowTitle("Enroll in a Course") layout = QVBoxLayout() self.Hbox = QHBoxLayout() self.fram = QFrame() self.cb = QComboBox() self.cb_courses = QComboBox() self.enroll_button = QPushButton("Enroll In Course") self.enroll_button.setObjectName("enroll_button") self.enroll_button.setFixedWidth(200) self.Hbox.addWidget(self.enroll_button) self.fram.setLayout(self.Hbox) self.enroll_button.clicked.connect(lambda: self.enrollStudent()) self.error_message = QLabel("") self.info = self.controller.getAllCourses() self.item = [] for courseID, faculty, courseName in self.info: if ((str(faculty) in self.item) == False): self.cb.addItem(str(faculty)) self.item.append(faculty) self.courses = self.controller.getCoursePerFaculty( self.cb.currentText()) self.cb_courses.clear() self.courseIDs = [] for courseIds, coursenames in self.courses: self.cb_courses.addItem(coursenames) self.courseIDs.append(courseIds) self.cb.currentIndexChanged.connect(self.selectionchange) self.cb_courses.currentIndexChanged.connect( self.selectionchangeCourses) layout.addWidget(self.cb) layout.addWidget(self.cb_courses) layout.addWidget(self.fram) layout.addWidget(self.error_message) #self.cb.setStyleSheet("QComboBox { background-color: white; }") #self.cb_courses.setStyleSheet("QComboBox { background-color: white; }") self.setLayout(layout) def selectionchange(self, i): for count in range(self.cb.count()): self.cb.itemText(count) self.courses = self.controller.getCoursePerFaculty( self.cb.currentText()) self.cb_courses.clear() self.courseIDs = [] for courseIds, coursenames in self.courses: self.cb_courses.addItem(coursenames) self.courseIDs.append(courseIds) def selectionchangeCourses(self, i): for count in range(self.cb_courses.count()): self.cb_courses.itemText(count) def enrollStudent(self): courseID = self.courseIDs[self.cb_courses.currentIndex()] result = self.controller.EnrollStudent(courseID, self.user.id, self.cb_courses.currentText()) if (result == 0): self.error_message.setText("Database error Enrolling in course") elif (result == 1): self.refreshCourses_request.emit() self.loaddashlayout.emit(4) #Student #******************************************************************************************************* #Professor def StartProf(self): self.layout = QFormLayout() self.le = QLineEdit() self.btn1 = QLabel("Course Name") self.le1 = QLineEdit() self.layout.addRow(self.btn1, self.le1) self.btn2 = QLabel("Description") self.le2 = QLineEdit() self.le2.setFixedHeight(150) self.done = QPushButton("Done") self.done.setObjectName("done") self.done.clicked.connect(lambda: self.SubmitCourse()) self.cancel = QPushButton("Cancel") self.cancel.setObjectName("cancel") self.cancel.clicked.connect(lambda: self.goBack()) self.layout.addRow(self.btn2, self.le2) self.facultyIndicator = QLabel("Faculty") self.faculty = QLineEdit() self.typeIndicator = QLabel("Type") self.typeOfCourse = QLineEdit() self.layout.addRow(self.facultyIndicator, self.faculty) self.layout.addRow(self.typeIndicator, self.typeOfCourse) self.layout.addRow(self.cancel, self.done) self.setLayout(self.layout) self.setWindowTitle("Add Course") self.errorText = QLabel("") self.layout.addRow(self.errorText) #Contacts controller with proper input to add course to database def SubmitCourse(self): result = self.controller.addCourse(self.le1.text(), self.le2.text(), self.user.id, self.faculty.text(), self.typeOfCourse.text()) if (result == 1): # self.errorText.setText("Course Added Successfully") self.refreshCourses_request.emit() self.loaddashlayout.emit(1) elif (result == 0): self.errorText.setText("Database Error") elif (result == 2): self.errorText.setText("Course Already Added Before") elif (result == 3): self.errorText.setText("Youtube Error") else: self.errorText.setText("Unknown Error") def goBack(self): self.loaddashlayout.emit(0)
class Example(QWidget): def __init__(self): super().__init__() self.initUI() self.row = -1 def initUI(self): # self.setGeometry(300, 300, 300, 220) self.resize(1144, 400) self.setMinimumSize(624, 400) # self.setMinimumSize(1144, 400) self.center() self.setWindowTitle('Xmind转Excel') self.setWindowIcon(QIcon(':/contacts.png')) # self.setWindowIcon(QIcon("../Icon/window.ico")) layout = QVBoxLayout() self.column = 6 # 使用水平布局 self.tablewidget = QTableWidget() self.tablewidget.setColumnCount(self.column) self.tablewidget.setSelectionBehavior( QAbstractItemView.SelectRows) # 设置表格的选取方式是行选取 self.tablewidget.setSelectionMode( QAbstractItemView.SingleSelection) # 设置选取方式为单个选取 self.tablewidget.setHorizontalHeaderLabels( ['#ID', '用例名称', '预期结果', '用例等级', '需求ID', '用例类型']) self.tablewidget.setAlternatingRowColors(True) # 行是否自动变色 self.tablewidget.horizontalHeader().setSectionResizeMode( QHeaderView.Stretch) # 设置列宽的适应方式 # self.tablewidget.setColumnWidth(1, 350) self.qc = QComboBox(self) self.qc.addItems(['请选择用例类型', '功能测试', '冒烟测试', '回归测试']) self.qc.activated[str].connect(self.onActivated) # self.tablewidget.itemChanged.connect(QCoreApplication.instance().quit) self.tablewidget.itemChanged.connect(self.table_update) self.button1 = QPushButton("选择XMind文件", self) self.button1.clicked.connect(self.read_XMind) self.button2 = QPushButton("转成Excel", self) self.button2.clicked.connect(self.to_Excel) layout.addWidget(self.tablewidget) layout.addWidget(self.qc) layout.addWidget(self.button1) layout.addWidget(self.button2) self.setLayout(layout) self.show() def read_XMind(self): # self.tablewidget.clearContents() # 清除所有数据--不包括标题头 for i in range(1, self.row + 1): self.tablewidget.removeRow(0) self.tablewidget.horizontalHeader().setSectionResizeMode( QHeaderView.Stretch) self.qc.setCurrentIndex(0) fileName, _ = QFileDialog.getOpenFileName(self, "打开文件", ".", "XMind(*.xmind)") if fileName == '': return ds = XMindData.read_XMind_to_list(fileName)[0]["topic"] # 获取头节点title,就是需求名 self.title = ds["title"] # 获取头节点下的其余所有节点内容 nodes_data = ds["topics"] # 创建XMData格式化xMind读取的数据 md = XMindData() # 清空缓存数据 md.clear_init_list_data() # 调用 data = md.get_lists_data(data=nodes_data) # 动态设置行 self.row = len(data) # 设置表格的行 self.tablewidget.setRowCount(self.row) for case in enumerate(data): # id item1 = QTableWidgetItem(str(case[0] + 1)) # 需求名 # item2 = QTableWidgetItem("_".join(case[1][:3])) item_1 = "_".join(case[1][:-2]) item_2 = item_1.replace('_', '', 1) # aaa=re.findall(r"\d+\.?\d*", item_2) # print(aaa[0]) # item2 = QTableWidgetItem(item_2) # item2 = str(items).replace('_','',1) # 模块名 item3 = QTableWidgetItem(case[1][-2]) # 用例 item4 = QTableWidgetItem(case[1][-1]) item2 = None item5 = None # 需求ID bool1 = False try: # item2 = QTableWidgetItem(re.sub(re.findall(r"\d+\.?\d*", item_2)[0], '', item_2)) item2 = QTableWidgetItem( re.sub(re.findall(r"\d+\.?\d*", item_2)[0], '', item_2)) item5 = QTableWidgetItem( re.findall(r"\d+\.?\d*", case[1][0])[0]) bool1 = True except: item2 = QTableWidgetItem(item_2) pass # print(re.sub(re.findall(r"\d+\.?\d*", item_2)[0],'',item_2)) self.tablewidget.setItem(case[0], 0, item1) self.tablewidget.setItem(case[0], 1, item2) self.tablewidget.setItem(case[0], 2, item3) self.tablewidget.setItem(case[0], 3, item4) if bool1: self.tablewidget.setItem(case[0], 4, item5) for i in range(0, self.row + 1): item6 = QTableWidgetItem(None) self.tablewidget.setItem(i, 5, item6) self.qc.setCurrentIndex(0) # 设置下拉框默认值 self.tablewidget.horizontalHeader().setSectionResizeMode( QHeaderView.Fixed) self.tablewidget.setColumnWidth(1, 400) self.tablewidget.setColumnWidth(2, 400) for i in [0, 3, 4, 5]: self.tablewidget.setColumnWidth(i, 70) fileName = '' def table_update(self): """ 如果表格被编辑,则会保存编辑后的数据 """ self.tablewidget.selectedItems() def to_Excel(self): """ 保存到Excel中 """ if self.row == -1: QMessageBox.about(self, "请先选择", '请先选择Xmind文件...') self.qc.setCurrentIndex(0) return # 返回值是一个元祖,需要两个参数接收,第一个是文件名,第二个是文件类型 fileName, fileType = QFileDialog.getSaveFileName( self, "保存Excel", self.title, "xlsx(*.xlsx)") if fileName == "": return else: try: if not fileName.endswith('.xlsx'): # 如果后缀不是.xlsx,那么就加上后缀 fileName = fileName + '.xlsx' QMessageBox.about(self, "转换中...", '转换中,可能会有延迟,请不要关闭应用...') we = ExcelData(file_name=fileName) # 创建Excel we.creat_excel_and_set_title(titles=[ '#ID', '用例名称', '预期结果', '用例等级', '需求ID', '用例类型', '前置条件', '操作步骤', '实际结果' ]) # 保存并写入(表格中更新后的数据)写入从第二行开始写入(行需要+1,列需要+1) for r in range(self.row): for c in range(self.column): # print(self.tablewidget.item(r, c)) if self.tablewidget.item(r, c) is None: # if self.tablewidget.item(r, c).text() is None: we.write_excel_data(row=r + 2, column=c + 1, value='') continue we.write_excel_data(row=r + 2, column=c + 1, value=self.tablewidget.item( r, c).text()) QMessageBox.about(self, "写入Excel", "写入Excel成功!\n路径:{}".format(fileName)) except Exception as e: QMessageBox.critical(self, "写入Excel", "出错了,请重试!!!\n错误信息:{}".format(e), QMessageBox.Yes, QMessageBox.Yes) def onActivated(self, text): # 把下拉列表框中选中的列表项的文本显示在标签组件上 if self.row == -1: QMessageBox.about(self, "请先选择", '请先选择Xmind文件...') self.qc.setCurrentIndex(0) for i in range(0, self.row + 1): if self.qc.currentText() == '请选择用例类型': item6 = QTableWidgetItem(None) else: item6 = QTableWidgetItem(self.qc.currentText()) self.tablewidget.setItem(i, 5, item6) # 退出提醒 def closeEvent(self, event): reply = QMessageBox.question(self, '退出提醒', "确认退出吗?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: event.accept() else: event.ignore() # 居中显示 def center(self): qr = self.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft())
class Window(QDialog): def __init__(self): super().__init__() self.title = "PyQt5 Window" self.top = 100 self.left = 100 self.width = 400 self.height = 150 self.lang = "java19" self.setWindowTitle(self.title) self.setFixedSize(self.width, self.height) self.create_layout() vbox_layout = QVBoxLayout() vbox_layout.addWidget(self.group_box) self.setLayout(vbox_layout) self.show() def create_layout(self): vbox_layout = QVBoxLayout() hbox_layout = QHBoxLayout() btn_source = QPushButton("Choose Source", self) btn_source.setMinimumHeight(28) btn_source.clicked.connect(self.click_source_btn) hbox_layout.addWidget(btn_source) btn_destination = QPushButton("Choose Destination", self) btn_destination.setMinimumHeight(28) btn_destination.clicked.connect(self.click_destination_btn) hbox_layout.addWidget(btn_destination) btn_start = QPushButton("Start", self) btn_start.setMinimumHeight(28) btn_start.clicked.connect(self.click_start_btn) hbox_layout.addWidget(btn_start) vbox_layout.addLayout(hbox_layout) self.lang_cb = QComboBox() self.lang_cb.addItems( "java19,java17,java15,java15dm,java12,java11,python3,c/c++,c#-1.2,char,text,scheme" .split(",")) self.lang_cb.currentIndexChanged.connect( self.selection_changed_lang_gb) vbox_layout.addWidget(self.lang_cb) self.group_box = QGroupBox("JPlag Wrapper") self.group_box.setLayout(vbox_layout) def click_source_btn(self): dlg = QFileDialog() dlg.setFileMode(QFileDialog.DirectoryOnly) if dlg.exec_() == QFileDialog.Accepted: self.source_dir = dlg.selectedFiles()[0] logging.info("Source dir: '%s'", dlg.selectedFiles()) print(dlg.selectedFiles()) def click_destination_btn(self): dlg = QFileDialog() dlg.setFileMode(QFileDialog.DirectoryOnly) if dlg.exec_() == QFileDialog.Accepted: self.destination_dir = dlg.selectedFiles()[0] logging.info("Destination dir: '%s'", dlg.selectedFiles()) print(dlg.selectedFiles()) def click_start_btn(self): logging.info("JPlag started with source: '%s' and destination: '%s'", self.source_dir, self.destination_dir) print("Started with source: {} and destination: {}".format( self.source_dir, self.destination_dir)) jplag_process = subprocess.run( f"java -jar ./jplag.jar -l {self.lang} -s '{self.source_dir}' -r '{self.destination_dir}'", shell=True, stdout=subprocess.PIPE) with open("jplag_output.txt", "w") as jplag_output_fd: jplag_output_fd.write(jplag_process.stdout.decode()) logging.info("JPlag completed.") print("JPlag completed.") def selection_changed_lang_gb(self, i): logging.info("Selection changed to %s", self.lang_cb.currentText()) print("Selection changed to", self.lang_cb.currentText()) self.lang = self.lang_cb.currentText()
class search(QWidget): def __init__(self): super().__init__() self.combo_text = '' self.searchUI() def searchUI(self): self.combo = QComboBox() self.label = QLabel("검색:") self.lineEdit = QLineEdit() self.pushbtn = QPushButton("확인") self.table = QTableWidget() self.table.resize(700, 400) self.table.setAlternatingRowColors(True) self.pushbtn.clicked.connect(self.search) self.lineEdit.returnPressed.connect(self.search) self.combo.currentIndexChanged.connect(self.combo_act) # combobox self.combo.addItem('TYPE') self.combo.addItem('ITEM') self.combo.addItem('PU') # self.combo.addItem('LR') self.combo.addItem('LQ') # self.combo.addItem('PSN') # self.combo.addItem('STN') # self.combo.addItem('W') Hbox = QHBoxLayout() Hbox.addWidget(self.label) Hbox.addWidget(self.combo) Hbox.addWidget(self.lineEdit) Hbox.addWidget(self.pushbtn) Vbox = QVBoxLayout() Vbox.addLayout(Hbox) Vbox.addWidget(self.table) self.setLayout(Vbox) self.setWindowTitle('Ybio') self.setWindowIcon(QIcon('Ybio.png')) self.resize(750, 450) self.show() def search(self): search_text = self.lineEdit.text() search_text = search_text.upper() if self.combo_text == 'TYPE': reply = QMessageBox(self) reply.question(self, 'ERROR', 'TYPE을 입력하세요.', QMessageBox.Yes) DF = pd.DataFrame() if self.combo_text == 'ITEM': func = self.ITEM_f() df = self.ITEM elif self.combo_text == 'PU': df = self.PU_f() elif self.combo_text == 'LQ': df = self.LQ_f() if self.combo_text != 'TYPE': df_search = df['NAME'].str.contains(search_text) DF = df[df_search] if DF.empty: self.reply = QMessageBox(self) self.reply.question(self, 'Error', '검색되지 않습니다.', QMessageBox.Yes) else: self.numROW = len(DF) self.numCOL = len(DF.columns) self.table.setRowCount(self.numROW) self.table.setColumnCount(self.numCOL) self.table.setHorizontalHeaderLabels(DF.columns.tolist()) self.v_list = DF.values.tolist() for m, n in zip(self.v_list, range(self.numROW)): for a, b in zip(range(self.numCOL), m): b = str(b) self.table.setItem(n, a, QTableWidgetItem(b)) def ITEM_f(self): self.ITEM_3 = pd.read_excel("Z:/ANRT/물품구매/INVENTORY(2.0).xlsx", sheet_name='M') self.ITEM_2 = self.ITEM_3.drop(self.ITEM_3.index[0:6]) self.ITEM_2.columns = [ '1', '2', '3', 'PSNID', 'ITID', 'VENID', 'CATID', '판매자', 'SUPPLYER', 'CAT', 'NAME', 'QUAN', '단가', '구매요청일', '담당자', '15', '16', '17', '18' ] self.ITEM = self.ITEM_2[[ 'PSNID', 'CAT', '구매요청일', 'NAME', 'SUPPLYER', 'CATID', '담당자', '판매자' ]] self.ITEM = self.ITEM.fillna('-') P = self.ITEM['NAME'] != 0 self.ITEM = self.ITEM[P] self.ITEM = self.ITEM.sort_values(["PSNID"], ascending=[False]) self.ITEM = self.ITEM.reset_index(drop=True) for i in range(len(self.ITEM)): X = self.ITEM['구매요청일'][i] x = str(X)[0:10] self.ITEM['구매요청일'][i] = x self.ITEM['NAME'] = self.ITEM['NAME'].str.upper() return self.ITEM def PU_f(self): self.PU_3 = pd.read_excel("Z:/REGI/REGI/REGI008PU(2.0).xlsx", sheet_name='M') self.PU_2 = self.PU_3.drop(self.PU_3.index[0:6]) self.PU_2.columns = [ '1', '2', '3', 'PUID', 'TRID', 'SID', 'NAME', 'VOL', 'PRODUCTIVITY', 'DATE', 'CONC', 'AMOUNT', 'RESEARCHER', 'ELUTION', 'DIALYSIS', 'METHOD', 'COMMENT', 'BATCH' ] self.PU = self.PU_2[['PUID', 'TRID', 'NAME', 'SID', 'DATE']] self.PU['DATE'] = self.PU.loc[:, 'DATE'].dt.strftime('%Y-%m-%d') self.PU = self.PU.sort_values(["PUID"], ascending=[False]) self.PU = self.PU.reset_index(drop=True) self.PU = self.PU.fillna('-') self.PU['NAME'] = self.PU['NAME'].str.upper() return self.PU def LQ_f(self): self.LQ_3 = pd.read_excel("Z:/REGI/REGI/REGI008LQV2.xlsx", sheet_name='Main') self.LQ_2 = self.LQ_3.drop(self.LQ_3.index[0:6]) self.LQ = self.LQ_2[[ 'Unnamed: 4', 'Unnamed: 5', 'Unnamed: 8', 'Unnamed: 6', 'Unnamed: 7' ]] self.LQ.columns = ['LQID', 'TARGET', 'NAME', 'PUID', 'SID'] self.LQ = self.LQ.sort_values(["LQID"], ascending=[False]) self.LQ = self.LQ.reset_index(drop=True) self.LQ['NAME'] = self.LQ['NAME'].str.upper() return self.LQ def combo_act(self): self.combo_text = self.combo.currentText()
class EditForm(QDialog): def __init__(self): super(EditForm, self).__init__() self.initUI(self) def initUI(self, EditForm): layout = QGridLayout(self) self.title_label = QLabel("Title:") self.title_line_edit = QLineEdit() self.rating_label = QLabel("Rating:") self.rating_slider = QSlider(Qt.Horizontal) self.rating_slider.setMinimum(0) self.rating_slider.setMaximum(5) self.rating_slider.setValue(0) self.rating_slider.setTickPosition(QSlider.TicksBelow) self.rating_slider.setTickInterval(5) self.review_label = QLabel("Review:") self.review_text_edit = QTextEdit() self.status_label = QLabel("Status:") self.status_combo_box = QComboBox() self.status_combo_box.addItems(["Read", "Currently Reading", "Want Тo Read"]) self.edit_button = QPushButton("Edit book") layout.addWidget(self.title_label, 0, 0) layout.addWidget(self.title_line_edit, 0, 1) layout.addWidget(self.rating_label, 1, 0) layout.addWidget(self.rating_slider, 1, 1) layout.addWidget(self.review_label, 2, 0) layout.addWidget(self.review_text_edit, 2, 1) layout.addWidget(self.status_label, 3, 0) layout.addWidget(self.status_combo_box, 3, 1) layout.addWidget(self.edit_button, 4, 0, 1, 2, Qt.AlignCenter) self.setLayout(layout) self.edit_button.clicked.connect(self.edit_button_click) self.layout().setSizeConstraint(QLayout.SetFixedSize) self.setWindowTitle("Edit Book") self.setWindowIcon(QIcon(QPixmap('../images/edit.png'))) def edit_button_click(self): title = self.title_line_edit.text() rating = self.rating_slider.value() review = self.review_text_edit.toPlainText() status = self.status_combo_box.currentText() if select_by_title(string.capwords(title)) == []: QMessageBox(QMessageBox.Critical, "Error", "There is no such book in the library!").exec_() else: if update_entry(string.capwords(title), rating, review, status): QMessageBox(QMessageBox.Information, "Updated book info", "You updated the info about this book!").exec_() else: QMessageBox(QMessageBox.Information, "Information", "The book was NOT edited! Try again.").exec_()