class DialogComputeScores(QDialog): """Dialog to set the parameters to compute scores automatically. Example (replace `parent` by the parent widget): dialog = DialogComputeScores(parent) max_score, penalize = dialog.exec_() """ def __init__(self, parent=None): super().__init__(parent) self.setWindowTitle(_('Compute default scores')) layout = QFormLayout() self.setLayout(layout) self.score = widgets.InputScore(parent=self) self.penalize = QCheckBox(_('Penalize incorrect answers'), self) buttons = QDialogButtonBox((QDialogButtonBox.Ok | QDialogButtonBox.Cancel)) layout.addRow(_('Maximum score'), self.score) layout.addRow(_('Penalizations'), self.penalize) layout.addRow(buttons) buttons.accepted.connect(self.accept) buttons.rejected.connect(self.reject) def exec_(self): """Shows the dialog and waits until it is closed. Returns the tuple (max_score, penalize) or (None, None) if the user cancels. """ success = False score = None penalize = None while not success: result = super().exec_() if result == QDialog.Accepted: if self.score.text(): score = self.score.value() if score is not None and score > 0: penalize = self.penalize.checkState() == Qt.Checked success = True if not success: QMessageBox.critical(self, _('Error'), _('Enter a valid score.')) else: score, penalize = None, None success = True return (score, penalize)
def initUI(self): StoryTypeLayer = FlowLayout() for key in WdStoryType.keys(): widget = QCheckBox(WdStoryType[key][1] if WdStoryType[key][1] != "" else WdStoryType[key][0]) widget.setObjectName("WdStoryType." + str(key)) widget.setCheckState(WdStoryType[key][2]) widget.setEnabled(widget.checkState() != 1) widget.setMinimumWidth(230) StoryTypeLayer.addWidget(widget) self.StoryTypeWdgList.append(widget) self.apply() hbox = QVBoxLayout() hbox.addLayout(StoryTypeLayer) btnGrp = QDialogButtonBox() btnClose = QPushButton("Закрыть") btnGrp.addButton(btnClose, QDialogButtonBox.ActionRole) hbox.addWidget(btnGrp) btnClose.clicked.connect(self.close) self.setLayout(hbox) self.setGeometry(500, 100, 500, 400) self.setWindowTitle("Опции") self.setWindowFlags(Qt.Dialog | Qt.WindowMinMaxButtonsHint | Qt.WindowCloseButtonHint)
class MikochikuAlarm(QWidget): def __init__(self, parent=None): QWidget.__init__(self, parent) self.search_ch_id = "UC-hM6YJuNYVAmUWxeIr9FeA" self.old_video_id_list = [] self.initUI() def initUI(self): self.timer = QTimer(self) self.timer.timeout.connect(self.check_live) self.timer.setInterval(40000) self.timer.start() label = QLabel(self) label.setPixmap(QPixmap(resource_path("icon.ico"))) label.move(60, 70) self.alarm_cb = QCheckBox('配信が始まったらアラームを鳴らす', self) self.alarm_cb.move(20, 20) self.alarm_cb.toggle() # self.loop_cb = QCheckBox('アラームをループ再生する', self) # self.loop_cb.move(20, 40) # self.loop_cb.toggle() self.webbrowser_cb = QCheckBox('配信が始まったら自動でブラウザを開く', self) self.webbrowser_cb.move(20, 40) self.webbrowser_cb.toggle() self.alarm_stop = QPushButton("待機中", self) # self.alarm_stop.setCheckable(True) # self.alarm_stop.setEnabled(False) self.alarm_stop.move(80, 80) self.alarm_stop.clicked[bool].connect(self.stop_alarm) self.setGeometry(300, 300, 250, 150) self.setWindowTitle('みこ畜アラーム') self.show() def check_live(self): buff_video_id_set = self.get_live_video_id(self.search_ch_id) print("buff_video_id_set", buff_video_id_set) print("self.old_video_id_list", self.old_video_id_list) if buff_video_id_set: for getting_video_id in buff_video_id_set: if not getting_video_id == "" and not getting_video_id is None: if not getting_video_id in self.old_video_id_list: self.old_video_id_list.append(getting_video_id) if len(self.old_video_id_list) > 30: self.old_video_id_list = self.old_video_id_list[1:] print("") print("配信が始まりました") # self.alarm_stop.setEnabled(False) self.alarm_stop.click() self.alarm_stop.setText("ストップ") if self.webbrowser_cb.checkState(): webbrowser.open( "https://www.youtube.com/watch?v=" + getting_video_id) if self.alarm_cb.checkState(): self.alarm_sound() def stop_alarm(self): pygame.mixer.music.stop() self.alarm_stop.setEnabled(True) self.alarm_stop.setText("待機中") def alarm_sound(self): # loop = 1 # if self.loop_cb.checkState(): loop_count = 5 pygame.mixer.music.play(loop_count) pygame.mixer.music.play(loop_count) def get_live_video_id(self, search_ch_id): dict_str = "" video_id_set = set() try: session = requests.Session() headers = { 'user-agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36' } html = session.get("https://www.youtube.com/channel/" + search_ch_id, headers=headers, timeout=10) soup = BeautifulSoup(html.text, 'html.parser') for scrp in soup.find_all('script'): if 'window["ytInitialData"]' in scrp.text: dict_str = scrp.text.split(' = ', 1)[1] dict_str = dict_str.replace('false', 'False') dict_str = dict_str.replace('true', 'True') index = dict_str.find("\n") dict_str = dict_str[:index - 1] dics = eval(dict_str) for section in dics.get("contents", {}).get( "twoColumnBrowseResultsRenderer", {}).get("tabs", {})[0].get("tabRenderer", {}).get("content", {}).get("sectionListRenderer", {}).get("contents", {}): for itemsection in section.get("itemSectionRenderer", {}).get("contents", {}): items = {} if "shelfRenderer" in itemsection: for items in itemsection.get("shelfRenderer", {}).get("content", {}).values(): for item in items.get("items", {}): for videoRenderer in item.values(): for badge in videoRenderer.get( "badges", {}): if badge.get( "metadataBadgeRenderer", {}).get( "style", {} ) == "BADGE_STYLE_TYPE_LIVE_NOW": video_id_set.add( videoRenderer.get( "videoId", "")) elif "channelFeaturedContentRenderer" in itemsection: for item in itemsection.get( "channelFeaturedContentRenderer", {}).get("items", {}): for badge in item.get("videoRenderer", {}).get("badges", {}): if badge.get("metadataBadgeRenderer", {}).get( "style", "") == "BADGE_STYLE_TYPE_LIVE_NOW": video_id_set.add( item.get("videoRenderer", {}).get("videoId", "")) except: return video_id_set return video_id_set
class Tab(QTabWidget): def __init__(self): super(Tab, self).__init__() self.initGUI() def initGUI(self): self.setGeometry(500, 300, 800, 650) self.setWindowTitle("CollegeBoard") self.tab1 = QWidget() self.tab2 = QWidget() self.tab3 = QWidget() self.tab4 = QWidget() self.tab5 = QWidget() self.addTab(self.tab1, "Personal information") self.addTab(self.tab2, "Choose a major") self.addTab(self.tab3, "Personal statement") self.addTab(self.tab4, "Register for a test") self.addTab(self.tab5, "Registration completed!") self.tab_1() self.tab_2() self.tab_3() self.tab_4() self.tab_5() self.setTabsClosable(True) self.tabCloseRequested.connect(self.closeTab) self.show() def closeTab(self, currentIndex): currentQWidget = self.widget(currentIndex) currentQWidget.deleteLater() self.removeTab(currentIndex) def tab_1(self): layout = QFormLayout() self.tab1.setLayout(layout) self.progressbar = QProgressBar(self) self.progressbar.setValue(0) layout.addRow(self.progressbar) self.btn1 = QPushButton('Next Page', self) self.btn1.clicked.connect(self.nextPage) self.btn1.move(650,600) self.txt1 = QLineEdit(self) self.txt1.setPlaceholderText("Cici") layout.addRow("First name", self.txt1) self.txt2 = QLineEdit(self) self.txt2.setPlaceholderText("Chen") layout.addRow("Last name", self.txt2) self.txt3 = QLineEdit(self) self.txt3.setPlaceholderText("") layout.addRow("Address", self.txt3) self.txt4 = QLineEdit(self) self.txt4.setPlaceholderText("") layout.addRow("Phone number", self.txt4) layout.addWidget(QLabel("Gender")) layout.addWidget(QCheckBox("Male")) layout.addWidget(QCheckBox("Female")) self.txt5 = QLineEdit(self) self.txt5.setPlaceholderText("") layout.addRow("Student ID", self.txt5) self.txt6 = QLineEdit(self) self.txt6.setPlaceholderText("mm/dd/yyyy") layout.addRow("Birthday", self.txt6) self.txt7 = QLineEdit(self) self.txt7.setPlaceholderText("Pacific American School") layout.addRow("High School", self.txt7) self.comboBox1 = QComboBox(self) self.comboBox1.addItem("January") self.comboBox1.addItem("February") self.comboBox1.addItem("March") self.comboBox1.addItem("April") self.comboBox1.addItem("May") self.comboBox1.addItem("June") self.comboBox1.addItem("July") self.comboBox1.addItem("August") self.comboBox1.addItem("September") self.comboBox1.addItem("October") self.comboBox1.addItem("November") self.comboBox1.addItem("December") layout.addRow("Graduation month", self.comboBox1) self.comboBox2 = QComboBox(self) self.comboBox2.addItem("2016") self.comboBox2.addItem("2017") self.comboBox2.addItem("2018") self.comboBox2.addItem("2019") self.comboBox2.addItem("2020") self.comboBox2.addItem("2021") self.comboBox2.addItem("2022") layout.addRow("Graduation year", self.comboBox2) self.btn2 = QPushButton('Change a photo', self) layout.addRow("", self.btn2) self.label1 = QLabel(self) layout.addRow(self.label1) self.label1.move(300, 60) self.label1.setPixmap(QPixmap('picture.jpg')) self.label1.resize(430, 60) def tab_2(self): layout = QFormLayout() self.tab2.setLayout(layout) self.btn1 = QPushButton('Next Page', self) self.btn1.clicked.connect(self.nextPage) self.btn1.move(650,600) self.progressbar = QProgressBar(self) self.progressbar.setValue(25) layout.addRow(self.progressbar) # -- add a checkbox self.check = QCheckBox('Biology', self) self.check.setTristate(True) # allowing tristate layout.addRow(self.check) self.check = QCheckBox('Chemistry', self) self.check.setTristate(True) # allowing tristate layout.addRow(self.check) self.check = QCheckBox('Computer science', self) self.check.setTristate(True) # allowing tristate layout.addRow(self.check) self.check = QCheckBox('Engineering', self) self.check.setTristate(True) # allowing tristate layout.addRow(self.check) self.check = QCheckBox('Arts & design', self) self.check.setTristate(True) # allowing tristate layout.addRow(self.check) self.check = QCheckBox('Literature', self) self.check.setTristate(True) # allowing tristate layout.addRow(self.check) self.check = QCheckBox('History', self) self.check.setTristate(True) # allowing tristate layout.addRow(self.check) self.check = QCheckBox('Language', self) self.check.setTristate(True) # allowing tristate layout.addRow(self.check) self.check = QCheckBox('Media', self) self.check.setTristate(True) # allowing tristate layout.addRow(self.check) self.check = QCheckBox('Philosophy', self) self.check.setTristate(True) # allowing tristate self.check.stateChanged.connect(self.dosth) layout.addRow(self.check) def dosth(self): state = self.check.checkState() if state == 0: self.setWindowTitle('You have deselected this major') elif state == 1: self.setWindowTitle('You are unsure of this major') elif state == 2: self.setWindowTitle('You have selected this major') def tab_3(self): layout = QFormLayout() self.tab3.setLayout(layout) self.btn1 = QPushButton('Next Page', self) self.btn1.clicked.connect(self.nextPage) self.btn1.move(650,600) self.progressbar = QProgressBar(self) self.progressbar.setValue(50) layout.addRow(self.progressbar) self.txt1 = QLineEdit('', self) self.txt2 = QLineEdit('', self) self.txt3 = QLineEdit('', self) self.txt4 = QLineEdit('', self) self.txt5 = QLineEdit('', self) self.dock1 = QDockWidget('Personal statement', self) self.dock1.move(20, 20) self.dock1.setWidget(self.txt1) self.dock1.setFloating(False) self.dock1.setFeatures(self.dock1.DockWidgetMovable) layout.addRow(self.dock1) layout.addRow('Please write a short statement about yourself.', self.txt1) layout.addRow(self.txt1) layout.addRow('What is your hobby?', self.txt2) layout.addRow(self.txt2) layout.addRow('What characteristics do you have that differs from others?', self.txt3) layout.addRow(self.txt3) layout.addRow('Which college do you want to go to and why?', self.txt4) layout.addRow(self.txt4) layout.addRow('Which after school activities did you attend in high school?', self.txt5) layout.addRow(self.txt5) def tab_4(self): layout = QFormLayout() self.tab4.setLayout(layout) self.btn1 = QPushButton('Next Page', self) self.btn1.clicked.connect(self.nextPage) self.btn1.move(650,600) self.progressbar = QProgressBar(self) self.progressbar.setValue(75) layout.addRow(self.progressbar) self.cal = QCalendarWidget(self) self.cal.setWindowTitle('Calendar') self.cal.setGridVisible(True) #one of the function self.cal.move(20, 100) self.cal.clicked[QDate].connect(self.showDate) self.label = QLabel(self) self.date = self.cal.selectedDate() #another function self.label.setText(self.date.toString()) self.label.move(100, 500) layout.addRow(self.cal) layout.addRow(self.label) # -- add a checkbox self.check1 = QCheckBox('SAT w/ essay', self) layout.addRow(self.check1) self.check2 = QCheckBox('Chinese w/ listening', self) layout.addRow(self.check2) self.check3 = QCheckBox('Physics', self) layout.addRow(self.check3) self.check4 = QCheckBox('Math I', self) layout.addRow(self.check4) self.check5 = QCheckBox('Math II', self) layout.addRow(self.check5) self.check6 = QCheckBox('Biology', self) layout.addRow(self.check6) self.check7 = QCheckBox('US History', self) layout.addRow(self.check7) self.check8 = QCheckBox('Literature', self) layout.addRow(self.check8) self.check9 = QCheckBox('Spanish', self) layout.addRow(self.check9) self.check10 = QCheckBox('French', self) layout.addRow(self.check10) # add a button self.btn1 = QPushButton('Reset', self) self.btn1.setToolTip('This button resets the checkbox!') self.btn1.resize(250, 90) self.btn1.move(100, 100) self.btn1.clicked.connect(self.reset) layout.addRow(self.btn1) def reset(self): self.check1.setChecked(False) self.check2.setChecked(False) self.check3.setChecked(False) self.check4.setChecked(False) self.check5.setChecked(False) self.check6.setChecked(False) self.check7.setChecked(False) self.check8.setChecked(False) self.check9.setChecked(False) self.check10.setChecked(False) def tab_5(self): layout = QFormLayout() self.tab5.setLayout(layout) self.label1 = QLabel(self) layout.addRow("Your registration have been successfully recorded. ☑️", self.label1) def showDate(self, date): self.label.setText(date.toString()) def nextPage(self): self.setCurrentIndex(self.currentIndex() + 1)
class Dice_Roller(QWidget): ''' widget for dice rolls ''' def __init__(self, parent): ''' Initialises with rote and quiet mode to false, dice to 0 and again to 10 ''' super().__init__() self.initUI() self.parent = parent self.rote = False self.quiet = False self.again = 10 self.dice = 0 def initUI(self): ''' UI for dice roller ''' grid = QGridLayout() self.setLayout(grid) #inner grid for the dice roll selecter + its label innergrid = QGridLayout() #dice_pool_selecter #inner grid for the dice roll selecter + its label innergrid = QGridLayout() #Spinner for selecting pool number self.num = QSpinBox() self.num.setMaximumSize(QSize(35, 20)) innergrid.addWidget(self.num, 0, 0) #labe; for spinner label = QLabel() label.setText("Enter Dice Pool") innergrid.addWidget(label, 0, 1) #add inner grid to normal grid grid.addLayout(innergrid, 0, 0) #roll button roll_button = QPushButton("Roll Dice Pool") roll_button.setStyleSheet( "QPushButton:pressed { background-color: white }") roll_button.clicked.connect(self.roll_handler) grid.addWidget(roll_button, 2, 2) #chance roll button chance_button = QPushButton("Roll Chance Die") chance_button.setStyleSheet( "QPushButton:pressed { background-color: white }") chance_button.clicked.connect(self.chance_handler) grid.addWidget(chance_button, 1, 2) #rote check self.rote_sel = QCheckBox() self.rote_sel.setText("Rote") grid.addWidget(self.rote_sel, 1, 0) #quiet check self.quiet_sel = QCheckBox() self.quiet_sel.setText("Quiet Mode") grid.addWidget(self.quiet_sel, 2, 0) #again buttons #10 is selected on initiation #Might look into making this an explicit button group instead again10 = QRadioButton() again10.setText("10 Again") again10.setChecked(True) again10.toggled.connect(lambda: self.change_again(again10)) grid.addWidget(again10, 0, 1) again9 = QRadioButton() again9.setText("9 Again") again9.toggled.connect(lambda: self.change_again(again9)) grid.addWidget(again9, 1, 1) again8 = QRadioButton() again8.setText("8 Again") again8.toggled.connect(lambda: self.change_again(again8)) grid.addWidget(again8, 2, 1) def change_again(self, button): ''' Method that runs whenever an again radio button is clicked ''' #dict showing value for each button agains = {'10 Again': 10, '9 Again': 9, '8 Again': 8} #uses text of pushed button as key, sets value of self.again self.again = agains[button.text()] def roll_handler(self): ''' handler for when roll button pushed ''' #Check if details entered yet if char.stats['webhook'] == "" or char.stats['user id'] == "": #Tell user something is missing and then stop self.parent.status_update("User Details Missing.") return self.parent.status_update("Rolling dice.") #reads UI elements to get other values dice = self.num.value() if dice == 0: self.parent.status_update("Please select at least 1 die.") return #Qt checkboxes are tri-state, return 2 if checked. rote = self.rote_sel.checkState() == 2 quiet = self.quiet_sel.checkState() == 2 #call roll_set method on character object #this returns a list of strings of each die result follwoed by total successes #if quiet mode selected, returns a single element list stating total successes messages = char.roll_set(dice, rote, self.again, quiet) for message in messages: self.send(message, char.stats['webhook']) time.sleep(1) #Updates status with final element in list, which will be total successes self.parent.status_update(messages[-1].replace( " for " + char.stats['user id'], "")) def chance_handler(self): ''' Handler for chance roll button. ''' self.parent.status_update("Rolling chance die.") #Check if details entered yet if char.stats['webhook'] == "" or char.stats['user id'] == "": #Tell user something is missing self.parent.status_update("User Details Missing.") return #use roll_chance method for character object #returns a list of strings, first states die value and second states its result messages = char.roll_chance() for message in messages: self.send(message, char.stats['webhook']) time.sleep(1) #Prints final result to client console self.parent.status_update(messages[-1].replace(char.stats['user id'], "You")) def send(self, message, webhook): ''' Sends message to webhook ''' #create connection #If expanding to other services further changes will be required here conn = http.client.HTTPSConnection("discordapp.com") #input sanitation: the seperator for each element is replaced by a space if found in message sep = "--11BOUND11" message = message.replace(sep, " ") #This payload will make a Discord webhook send message to its associated channel #If expanding to other services further changes may be required here payload = sep + "\r\nContent-Disposition: form-data; name=\"content\"\r\n\r\n" + message + "\r\n" + sep + "--" #headers for the connection #If expanding to other services further changes may be required here headers = { 'content-type': "multipart/form-data; boundary=" + sep[2:], 'cache-control': "no-cache", } #sends a POST command to the webhook with the payload and headers defined above conn.request("POST", webhook, payload, headers) #get response res = conn.getresponse() #warning messages text = res.read() text = text.decode("utf-8") #first check if there was a warning message #For discord, the data will be blank unless error occures sending webhook #Usually a rate limit hit #For expansion to other services this may need to be updated if text != "": if "rate limited" in text: #confirms that is is a rate limit on Discord #Discord will helpfully tell the user how long they need to wait until the next retry index1 = text.find('"retry_after"') chop = text[index1 + 13:] wait = '' for character in chop: #find the wait time requested #given in miliseconds usually if character in '0123456789': wait += character if character == '\n': break #wait will given in miliseconds, convert to seconds and add 0.5 just in case wait = int(wait) / 1000 + 0.5 #update status, should always have at least 3 significant digits self.parent.status_update( "Rate limit hit. Will try again in " + str(wait)[:4] + " seconds.") #try again after wait time.sleep(wait) send(message, webhook) if "400 Bad Request" in text: #Likely bad bad URL #look into making a pop up dialogue instead self.parent.status_update( "400 Bad Request - Double check URL.") return else: #Unexpected problem - Result printed to client console #goes as a temp message so it won't be overwritten by success message #user can still find results in last roll display #might look into making this a pop up dialogue instead index1 = text.find('"message"') index2 = text.find('\n', index1) chop = text[index1:index2] self.parent.statusBar.showMessage(chop) return #end of if statement for warning message #now include some rate limit protection remaining = int(res.getheader('X-RateLimit-Remaining')) reset = int(res.getheader('X-RateLimit-Reset')) - int(time.time()) #reset should be the number of seconds until rate limit refreshed #In my experience it will reset faster than this #For now, it will add delays to messages if remaining message count is less than or equal to 2 if remaining <= 2: self.parent.status_update( "Rate Limit approaching. Next message delay is 2 seconds.") #already a 1 second delay between messages, so extra secound added here time.sleep(1)
class QTrainingInfoBox( QWidget, QObserver, qobservables={ # FIXME[hack]: check what we are really interested in ... Trainer: Trainer.Change.all() }): """ Attributes ---------- range: numpy.ndarray trainingLoss: numpy.ndarray validationLoss: numpy.ndarray rangeIndex: int """ _trainer: Trainer = None def __init__(self, trainer: Optional[Trainer] = None, **kwargs): """Initialization of the QTrainingBox. """ super().__init__(**kwargs) self._initUI() self._layoutComponents() self._range = np.arange(100, dtype=np.float32) self._rangeIndex = 0 self._trainingLoss = np.zeros(100, dtype=np.float32) self._validationLoss = np.zeros(100, dtype=np.float32) self.setTrainer(trainer) def _initUI(self): def slot(checked: bool): if self._trainer.ready: self._trainer.start() elif self._trainer.running: self._trainer.stop() self._buttonTrainModel = QPushButton("Train") self._buttonTrainModel.clicked.connect(slot) self._plotLoss = QMatplotlib() self._checkboxPlot = QCheckBox() self._progressEpoch = QProgressBar() self._progressEpoch.setFormat("%v/%m") self._progressBatch = QProgressBar() self._progressBatch.setFormat("%v (%p%)") self._labelBatch = QLabel() self._labelEpoch = QLabel() self._labelLoss = QLabel() self._labelAccuracy = QLabel() self._labelDuration = QLabel() self._lblTrainee = QLabel() def slot(value: int): self._trainer.epochs = value self._spinboxEpochs = QSpinBox() self._spinboxEpochs.valueChanged.connect(slot) def slot(value: int): self._trainer.batch_size = value self._spinboxBatchSize = QSpinBox() self._spinboxBatchSize.valueChanged.connect(slot) def _layoutComponents(self): form = QFormLayout() form.addRow("Trainee:", self._lblTrainee) form.addRow("Batch:", self._labelBatch) form.addRow("Epoch:", self._labelEpoch) form.addRow("Loss:", self._labelLoss) form.addRow("Accuracy:", self._labelAccuracy) form.addRow("Duration:", self._labelDuration) form.addRow("Plot:", self._checkboxPlot) layout = QVBoxLayout() layout.addWidget(self._plotLoss) layout.addLayout(form) layout.addWidget(self._progressBatch) layout.addWidget(self._progressEpoch) layout.addWidget(self._buttonTrainModel) layout.addWidget(self._spinboxEpochs) layout.addWidget(self._spinboxBatchSize) self.setLayout(layout) def _enableComponents(self): enabled = (self._trainer is not None and self._trainer.ready) self._buttonTrainModel.setEnabled(enabled) enabled = enabled and not self._trainer.running self._spinboxEpochs.setEnabled(enabled) self._spinboxBatchSize.setEnabled(enabled) def setTrainer(self, trainer: Trainer) -> None: self._enableComponents() def trainer_changed(self, trainer, change): self._enableComponents() return if 'trainee_changed' in change: self._lblTrainee.setText(str(trainer.trainee)) self._enableComponents() if 'training_changed' in change: if self._trainer.epochs: self._progressEpoch.setRange(0, self._trainer.epochs) if self._trainer.batches: self._progressBatch.setRange(0, self._trainer.batches) if self._trainer is not None: if self._trainer.running: self._buttonTrainModel.setText("Stop") else: self._buttonTrainModel.setText("Train") self._enableComponents() if 'epoch_changed' in change: if self._trainer.epoch is None: self._labelEpoch.setText("") self._progressEpoch.setValue(0) else: self._labelEpoch.setText(str(self._trainer.epoch)) self._progressEpoch.setValue(self._trainer.epoch + 1) if 'batch_changed' in change: if self._trainer.batch is not None: self._labelBatch.setText(f"{self._trainer.batch}/" f"{self._trainer.batches}") self._labelDuration.setText(str(self._trainer.batch_duration)) self._progressBatch.setValue(self._trainer.batch) if 'parameter_changed' in change: self._spinboxEpochs.setRange(*self._trainer.epochs_range) self._spinboxEpochs.setValue(self._trainer.epochs) self._spinboxBatchSize.setRange(*self._trainer.batch_size_range) self._spinboxBatchSize.setValue(self._trainer.batch_size) if self._trainer.loss is not None: self._labelLoss.setText(str(self._trainer.loss)) self._trainerLoss[self._rangeIndex] = self._trainer.loss if self._checkboxPlot.checkState(): self._plotLoss.plot(self._range, self._trainerLoss) # self._plotLoss.plot(self._validationLoss) if self._trainer.accuracy is not None: self._labelAccuracy.setText(str(self._trainer.accuracy)) self._rangeIndex = (self._rangeIndex + 1) % len(self._range)
class mainWindow(QtWidgets.QWidget): def __init__(self): super(mainWindow , self).__init__() self.__initWidget() self.__initSignalSlot() self.__initUser() def __initWidget(self): self.resize(300,200) self.xhLabel = QLabel('学号') self.mmLabel = QLabel('密码') self.authLabel = QLabel('验证码') self.imageLabel = QLabel() self.xhLine = QLineEdit() self.mmLine = QLineEdit() self.mmLine.setEchoMode(QLineEdit.Password) self.authLine = QLineEdit() #self.authImageScene = QGraphicsScene self.authButton = QPushButton('获取验证码') self.okButton = QPushButton('登陆') self.chBox = QCheckBox('记住密码') self.chBox.setCheckState(Qt.Checked) self.displayScoreButton = QPushButton('显示成绩') self.okButton.setEnabled(False) self.displayScoreButton.setEnabled(False) self.tips = QLabel('正在登录 ...') self.tipsOk = QLabel('登陆成功!') self.gridLayout = QGridLayout() self.gridLayout.addWidget(self.xhLabel , 0 , 0 , 1 , 1) self.gridLayout.addWidget(self.mmLabel , 1 , 0 , 1 , 1) self.gridLayout.addWidget(self.authLabel , 2 , 0 , 1 , 1) self.gridLayout.addWidget(self.xhLine , 0 , 1 , 1 , 1) self.gridLayout.addWidget(self.mmLine , 1 , 1 , 1 , 1) self.gridLayout.addWidget(self.authLine , 2 , 1 , 1 , 1) self.gridLayout.addWidget(self.imageLabel , 3 , 1 , 1 , 1) self.gridLayout.addWidget(self.tipsOk , 4 , 1 , 2 , 1) self.gridLayout.addWidget(self.tips , 4 , 1 , 2 , 1) self.tips.hide() self.tipsOk.hide() self.hLayout = QHBoxLayout() self.hLayout.addWidget(self.authButton) self.hLayout.addWidget(self.okButton) self.hLayout.addStretch(3) self.hLayout.addWidget(self.chBox) self.vLayout = QVBoxLayout() self.vLayout.addStretch(10) self.vLayout.addLayout(self.hLayout) self.vLayout.addStretch(10) self.vLayout.addWidget(self.displayScoreButton) self.mainLayout = QVBoxLayout() self.mainLayout.addLayout(self.gridLayout) self.mainLayout.addLayout(self.vLayout) self.setLayout(self.mainLayout) def __initSignalSlot(self): self.okButton.clicked.connect(self.__logClicked) self.authButton.clicked.connect(self.__getAuthCode) self.displayScoreButton.clicked.connect(self.__showScore) #self.chBox.stateChanged.connect(self.__chBoxChange) def __initUser(self): self.user = [] try: with open('user.txt' , 'r') as file: lines = file.readlines() for line in lines: self.user.append(line.strip('\n')) except : self.user.extend(['','']) self.xhLine.setText(self.user[0]) if len(self.user) > 1: self.mmLine.setText(self.user[1]) def __getAuthCode(self): self.tips.hide() # get authcode self.login = CSpiderSchoolWeb() self.login.getAuthCode() image = QImage() image.load('image.gif') self.imageLabel.setPixmap(QPixmap.fromImage(image)) self.tipsOk.hide() self.okButton.setEnabled(True) self.displayScoreButton.setEnabled(False) def __logClicked(self): self.tips.show() xh = self.xhLine.text() mm = self.mmLine.text() auth = self.authLine.text() with open('user.txt','w') as file: file.write(xh + '\n') if self.chBox.checkState() == Qt.Checked: file.write(mm + '\n') # login self.login.loginSchoolWeb(xh , mm , auth) self.displayScoreButton.setEnabled(True) self.okButton.setEnabled(False) self.tips.hide() self.tipsOk.show() def __showScore(self): # remember use self.XXX , otherwise the windows exit imidatelt self.scoreWin = CScoreWindow() self.scoreWin.setAll( self.login.getStudentGradeAndSem() ) #self.scoreWin.setAll( (['2014-2015','2013-2014'] , ['2']) ) self.scoreWin.show()
class RepeaterWidget(QWidget): def __init__(self, client): QWidget.__init__(self) self.client = client self.history = [] self.history_pos = 0 self.setLayout(QVBoxLayout()) self.layout().setSpacing(0) self.layout().setContentsMargins(0, 0, 0, 0) buttons = QHBoxLayout() buttons.setContentsMargins(0, 0, 0, 0) buttons.setSpacing(8) submitButton = QPushButton("Submit") submitButton.clicked.connect(self.submit) self.dest_host_input = QLineEdit() self.dest_port_input = QLineEdit() self.dest_port_input.setMaxLength(5) self.dest_port_input.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred) self.dest_usetls_input = QCheckBox() self.back_button = QToolButton() self.back_button.setText("<") self.back_button.clicked.connect(self.back) self.forward_button = QToolButton() self.forward_button.setText(">") self.forward_button.clicked.connect(self.forward) buttons.addWidget(self.back_button) buttons.addWidget(self.forward_button) buttons.addWidget(submitButton) buttons.addWidget(QLabel("Host:")) buttons.addWidget(self.dest_host_input) buttons.addWidget(QLabel("Port:")) buttons.addWidget(self.dest_port_input) buttons.addWidget(QLabel("Use TLS:")) buttons.addWidget(self.dest_usetls_input) buttons.addStretch() self.reqview = ReqViewWidget(tag_tab=True) self.reqview.set_read_only(False) self.reqview.set_tags_read_only(False) self.layout().addLayout(buttons) self.layout().addWidget(self.reqview) self.req = None self.dest_host = "" self.dest_port = 80 self.use_tls = False self._update_buttons() def _set_host(self, host): self.dest_host_input.setText(host) def _set_port(self, port): if port is None or port <= 0: self.dest_port_input.setText("") else: self.dest_port_input.setText(str(port)) def _set_usetls(self, usetls): if usetls: self.dest_usetls_input.setCheckState(2) else: self.dest_usetls_input.setCheckState(0) def _set_dest_info(self, host, port, usetls): self._set_host(host) self._set_port(port) self._set_usetls(usetls) def _get_dest_info(self): host = self.dest_host_input.text() try: port = int(self.dest_port_input.text()) except: port = -1 if self.dest_usetls_input.checkState() == 0: usetls = False else: usetls = True return (host, port, usetls) def set_request(self, req, update_history=True): self._set_dest_info("", -1, False) if update_history: self.history.append(req) self.history_pos = len(self.history) - 1 self._update_buttons() if req: self.req = req self.req.tags = set(["repeater"]) self._set_dest_info(req.dest_host, req.dest_port, req.use_tls) self.reqview.set_request(self.req) @pyqtSlot(set) def update_req_tags(self, tags): if self.req: self.req.tags = tags @pyqtSlot() def submit(self): try: req = self.reqview.get_request() if not req: display_error_box("Could not parse request") return except: display_error_box("Could not parse request") return req.tags.add("repeater") host, port, usetls = self._get_dest_info() if port is None: display_error_box("Invalid port") return req.dest_host = host req.dest_port = port req.dest_usetls = usetls self.client.submit(req, save=True) self.req = req self.set_request(req) @pyqtSlot() def back(self): if self.history_pos > 0: self.history_pos -= 1 self.set_request(self.history[self.history_pos], update_history=False) self._update_buttons() @pyqtSlot() def forward(self): if self.history_pos < len(self.history) - 1: self.history_pos += 1 self.set_request(self.history[self.history_pos], update_history=False) self._update_buttons() def _update_buttons(self): self.forward_button.setEnabled(True) self.back_button.setEnabled(True) if len(self.history) == 0 or self.history_pos == len(self.history) - 1: self.forward_button.setEnabled(False) if self.history_pos == 0: self.back_button.setEnabled(False)
class QuickInstructions(QWidget): """ Implementation of the quick instructions. """ def __init__(self, parent=None): super(QuickInstructions, self).__init__(parent) # self.setAttribute(Qt.WA_DeleteOnClose) # Deletes instance on window close self.setWindowTitle('pyIMD :: Quick instructions') self.display_on_startup = 2 self.resize(400, 370) self.setWindowIcon( QtGui.QIcon( resource_path( os.path.join( os.path.join("ui", "icons", "pyIMD_logo_icon.ico"))))) grid = QGridLayout() grid.setContentsMargins(5, 5, 5, 5) ok = QPushButton('Ok') ok.setIcon(QApplication.style().standardIcon( QStyle.SP_DialogApplyButton)) ok.setMaximumWidth(100) ok.clicked.connect(self.close) self.chk = QCheckBox('Display quick instructions at startup') self.chk.setFont(QFont('Arial', 9, QFont.Bold)) self.chk.setChecked(1) self.chk.clicked.connect(self.on_display_qi) self.quick_instructions = QTextEdit(self) self.quick_instructions.setText( '<h3>Quick Instructions</h3> ' 'Edit the settings first according to your experimental setup. Second select ' 'the directory containing your experimental data and determine the file name ' 'to measurement relationship as well as the measurement mode the data was ' 'recorded with.' '<br><br>Controls:' '<ul>' '<li><b>Ctrl+N (Cmd+N):</b> Create a new pyIMD project.' '</li>' '<li><b>Ctrl+O (Cmd+O):</b> Open an existing pyIMD project' '</li>' '<li><b>Ctrl+S (Cmd+S):</b> Save the current pyIMD project' '</li>' '<li><b>Ctrl+P (Cmd+P):</b> Open the settings dialog to change the project ' 'parameters</li></ul>' 'Hints:' '<ul><li>Create a pyIMD project for all your experiments first and save ' 'the pyIMD projects before running them individually. The projects can then ' 'be run sequentially using the batch mode (Batch processing tab).' '</li>' '<li>Select multiple data files holding the Ctrl button during selection after' 'clicking on <i>Select directory</i> or Ctrl+N.</li><' '</ul>' 'You can open this window any time from the Help menu.</ul>') self.quick_instructions.setReadOnly(1) self.quick_instructions.setFont(QFont('Arial', 9)) grid.addWidget(self.quick_instructions, 0, 0, 1, 0) grid.addWidget(ok, 1, 1) grid.addWidget(self.chk, 1, 0) self.setLayout(grid) def on_display_qi(self): self.display_on_startup = self.chk.checkState() def keyPressEvent(self, event): if event.key() == Qt.Key_Escape: self.close()
class MediaCueGeneral(CueGeneral): Name = 'Cue Settings' def __init__(self, size, cue=None, parent=None): super().__init__(size, cue=cue, parent=parent) # Start at self.startGroup = QGroupBox(self) self.startGroup.setLayout(QHBoxLayout()) self.startEdit = QTimeEdit(self.startGroup) self.startEdit.setDisplayFormat('HH.mm.ss.zzz') self.startGroup.layout().addWidget(self.startEdit) self.startLabel = QLabel(self.startGroup) self.startLabel.setAlignment(QtCore.Qt.AlignCenter) self.startGroup.layout().addWidget(self.startLabel) self.layout().addWidget(self.startGroup) # Loop self.loopGroup = QGroupBox(self) self.loopGroup.setLayout(QHBoxLayout()) self.spinLoop = QSpinBox(self.loopGroup) self.spinLoop.setRange(-1, 1000000) self.loopGroup.layout().addWidget(self.spinLoop) self.loopLabel = QLabel(self.loopGroup) self.loopLabel.setAlignment(QtCore.Qt.AlignCenter) self.loopGroup.layout().addWidget(self.loopLabel) self.layout().addWidget(self.loopGroup) # Checks self.checkPause = QCheckBox(self) self.layout().addWidget(self.checkPause) self.retranslateUi() def retranslateUi(self): self.startGroup.setTitle('Start time') self.startLabel.setText('Amount of skip time') self.loopGroup.setTitle("Loop") self.loopLabel.setText("Repetition after first play (-1 = infinite)") self.checkPause.setText("Enable Pause") def get_configuration(self): conf = super().get_configuration() conf['media'] = {} checkable = self.startGroup.isCheckable() if not (checkable and not self.startGroup.isChecked()): time = self.startEdit.time().msecsSinceStartOfDay() conf['media']['start_at'] = time if not (checkable and not self.loopGroup.isChecked()): conf['media']['loop'] = self.spinLoop.value() if self.checkPause.checkState() != QtCore.Qt.PartiallyChecked: conf['pause'] = self.checkPause.isChecked() return conf def enable_check(self, enable): super().enable_check(enable) self.startGroup.setCheckable(enable) self.startGroup.setChecked(False) self.loopGroup.setCheckable(enable) self.loopGroup.setChecked(False) self.checkPause.setTristate(enable) if enable: self.checkPause.setCheckState(QtCore.Qt.PartiallyChecked) def set_configuration(self, conf): super().set_configuration(conf) if 'pause' in conf: self.checkPause.setChecked(conf['pause']) if 'media' in conf: if 'loop' in conf['media']: self.spinLoop.setValue(conf['media']['loop']) if 'duration' in conf['media'] and conf['media']['duration'] > 0: t = QTime().fromMSecsSinceStartOfDay(conf['media']['duration']) self.startEdit.setMaximumTime(t) if 'start_at' in conf['media']: t = QTime().fromMSecsSinceStartOfDay(conf['media']['start_at']) self.startEdit.setTime(t)
class QtBoolEdit(QWidget): toggledSignal = pyqtSignal(bool) def __init__(self,parent=None): super(QtBoolEdit, self).__init__(parent) self.m_checkBox = QCheckBox(self) self.m_textVisible = True lt = QHBoxLayout() if (QApplication.layoutDirection() == Qt.LeftToRight): lt.setContentsMargins(4, 0, 0, 0) else: lt.setContentsMargins(0, 0, 4, 0) lt.addWidget(self.m_checkBox) self.setLayout(lt) self.m_checkBox.toggled.connect(self.toggledSignal) self.setFocusProxy(self.m_checkBox) self.m_checkBox.setText(self.tr("True")) def textVisible(self): return self.m_textVisible def setTextVisible(self,textVisible): if (self.m_textVisible == textVisible): return self.m_textVisible = textVisible if self.m_textVisible: if self.isChecked(): self.m_checkBox.setText(self.tr("True")) else: self.m_checkBox.setText(self.tr("False")) else: self.m_checkBox.setText('') def checkState(self): return self.m_checkBox.checkState() def setCheckState(self,state): self.m_checkBox.setCheckState(state) def isChecked(self): return self.m_checkBox.isChecked() def setChecked(self,c): self.m_checkBox.setChecked(c) if self.m_textVisible==False: return if self.isChecked(): self.m_checkBox.setText(self.tr("True")) else: self.m_checkBox.setText(self.tr("False")) def blockCheckBoxSignals(self,block): return self.m_checkBox.blockSignals(block) def mousePressEvent(self, event): if (event.buttons() == Qt.LeftButton): self.m_checkBox.click() event.accept() else: super(QtBoolEdit, self).mousePressEvent(event) def paintEvent(self, pt_QPaintEvent): opt = QStyleOption() opt.initFrom(self) p = QPainter(self) self.style().drawPrimitive(QStyle.PE_Widget, opt, p, self)
class BasicFilterPage(QWidget): def __init__(self, parent=None): super(BasicFilterPage, self).__init__(parent) self.blockCombo = QComboBox() self.deviceCombo = QComboBox() self.unitCombo = QComboBox() self.combos = {'block': self.blockCombo, \ 'device': self.deviceCombo, \ 'unit': self.unitCombo} groupLayout = QFormLayout() groupLayout.addRow("Skupina měření:", self.blockCombo) groupLayout.addRow("Přístroj:", self.deviceCombo) groupLayout.addRow("Veličina:", self.unitCombo) filterGroup = QGroupBox("Základní filtry") filterGroup.setLayout(groupLayout) self.deviatedValuesCheckbox = QCheckBox() valuesLayout = QFormLayout() valuesLayout.addRow("Mimo odchylku:", self.deviatedValuesCheckbox) valuesGroup = QGroupBox("Hodnoty") valuesGroup.setLayout(valuesLayout) layout = QVBoxLayout() layout.addWidget(filterGroup) layout.addSpacing(12) layout.addWidget(valuesGroup) layout.addStretch(1) self.setLayout(layout) def setComboOptions(self, combo, options, selected=''): items = [''] for option in options: items.append(str(option)) try: index = items.index(str(selected)) except ValueError: index = 0 combo.clear() combo.addItems(items) combo.setCurrentIndex(index) def getFilter(self): filter_ = {} for name, combo in self.combos.items(): selected = combo.currentText() if selected: filter_[name] = selected filter_['deviated_values'] = bool(self.deviatedValuesCheckbox.checkState()) return filter_ def initControls(self, options, filter_): for name, combo in self.combos.items(): try: comboOptions = options[name] except KeyError: continue else: selectedOption = filter_.get(name, '') self.setComboOptions(combo, comboOptions, selectedOption) checked = filter_.get('deviated_values', False) self.deviatedValuesCheckbox.setChecked(checked)
class WeatherSationView(QTableView): def __init__(self, parent=None, *args): super(WeatherSationView, self).__init__() self.setShowGrid(False) self.setAlternatingRowColors(True) self.setMinimumWidth(650) self.setSortingEnabled(True) self.chkbox_header = QCheckBox(self.horizontalHeader()) self.chkbox_header.setToolTip('Check or uncheck all the weather ' 'stations in the table.') self.chkbox_header.stateChanged.connect(self.chkbox_header_isClicked) self.horizontalHeader().installEventFilter(self) self.verticalHeader().hide() self.set_geocoord(None) self.populate_table(WeatherSationList()) self.setItemDelegateForColumn(0, CheckBoxDelegate(self)) self.setColumnWidth(0, 32) self.setColumnWidth(3, 75) self.setColumnWidth(4, 75) self.setColumnWidth(5, 75) self.setColumnHidden(7, True) self.setColumnHidden(8, True) self.setColumnHidden(9, True) self.setColumnHidden(10, True) self.horizontalHeader().setSectionResizeMode(QHeaderView.Fixed) self.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch) @property def geocoord(self): return self.__latlon def set_geocoord(self, latlon): self.__latlon = latlon self.setColumnHidden(2, latlon is None) if latlon and self.stationlist: prox = calc_dist_from_coord(self.geocoord[0], self.geocoord[1], self.stationlist['Latitude'], self.stationlist['Longitude']) model = self.model() model._data[:, 2] = prox model.dataChanged.emit(model.index(0, 2), model.index(model.rowCount(0), 2)) def eventFilter(self, source, event): if (event.type() == QEvent.Resize): self.resize_chkbox_header() return QWidget.eventFilter(self, source, event) def chkbox_header_isClicked(self): model = self.model() model._checks[:] = int(self.chkbox_header.checkState() == Qt.Checked) model.dataChanged.emit(model.index(0, 0), model.index(model.rowCount(0), 0)) def resize_chkbox_header(self): h = self.style().pixelMetric(QStyle.PM_IndicatorHeight) w = self.style().pixelMetric(QStyle.PM_IndicatorWidth) W = self.horizontalHeader().sectionSize(0) H = self.horizontalHeader().height() y0 = (H - h)//2 x0 = (W - w)//2 self.chkbox_header.setGeometry(x0, y0, w, h) def clear(self): """Removes all items in the view.""" self.populate_table(WeatherSationList()) def populate_table(self, stationlist): self.stationlist = stationlist N = len(stationlist) M = len(WeatherStationModel.HEADER) if N == 0: data = np.empty((0, M)) else: if self.geocoord: prox = calc_dist_from_coord( self.geocoord[0], self.geocoord[1], stationlist['Latitude'], stationlist['Longitude']) self.setColumnHidden(2, False) else: prox = np.empty(N).astype(str) self.setColumnHidden(2, True) data = np.vstack([np.arange(N).astype(int), stationlist['Name'], prox, stationlist['DLY First Year'], stationlist['DLY Last Year'], stationlist['Province'], stationlist['ID'], stationlist['Station ID'], stationlist['Latitude'], stationlist['Longitude'], stationlist['Elevation'] ]).transpose() checked = self.chkbox_header.checkState() == Qt.Checked self.setModel(WeatherStationModel(data, checked)) self.model().sort(self.horizontalHeader().sortIndicatorSection(), self.horizontalHeader().sortIndicatorOrder()) # ---- Utility methods def get_row_from_climateid(self, climateid): idx = np.where(self.model()._data[:, 6] == climateid)[0] if len(idx) > 0: return idx[0] else: return None def get_checked_rows(self): return np.where(self.model()._checks == 1)[0] def get_content4rows(self, rows, daterange='full'): """ Grab the weather station info for the specified rows and save the results in a list. """ indexes = self.model()._data[rows, 0] stationlist = WeatherSationList() for index in indexes: stationlist.append(self.stationlist[int(index)]) return stationlist def get_prox_data(self): """Returns the proximity value shown in the table.""" if self.geocoord: return np.array(self.model()._data[:, 2]).astype(float) else: return None def get_stationlist(self): """Get and format the content of the QTableView.""" indexes = self.model()._data[:, 0] stationlist = WeatherSationList() for index in indexes: stationlist.append(self.stationlist[int(index)]) return stationlist def save_stationlist(self, filename): """Save the content of the QTableWidget to file.""" stationlist = self.get_stationlist() stationlist.save_to_file(filename)
class CueGeneralSettings(SettingsPage): Name = 'Cue' def __init__(self, **kwargs): super().__init__(**kwargs) self.setLayout(QVBoxLayout()) # Pre wait self.preWaitGroup = QGroupBox(self) self.preWaitGroup.setLayout(QHBoxLayout()) self.layout().addWidget(self.preWaitGroup) self.preWaitSpin = QDoubleSpinBox(self.preWaitGroup) self.preWaitSpin.setMaximum(3600 * 24) self.preWaitGroup.layout().addWidget(self.preWaitSpin) self.preWaitLabel = QLabel(self.preWaitGroup) self.preWaitLabel.setAlignment(Qt.AlignCenter) self.preWaitGroup.layout().addWidget(self.preWaitLabel) # Post wait self.postWaitGroup = QGroupBox(self) self.postWaitGroup.setLayout(QHBoxLayout()) self.layout().addWidget(self.postWaitGroup) self.postWaitSpin = QDoubleSpinBox(self.postWaitGroup) self.postWaitSpin.setMaximum(3600 * 24) self.postWaitGroup.layout().addWidget(self.postWaitSpin) self.postWaitLabel = QLabel(self.postWaitGroup) self.postWaitLabel.setAlignment(Qt.AlignCenter) self.postWaitGroup.layout().addWidget(self.postWaitLabel) # Next action self.nextActionGroup = QGroupBox(self) self.nextActionGroup.setLayout(QHBoxLayout()) self.layout().addWidget(self.nextActionGroup) self.nextActionCombo = QComboBox(self.nextActionGroup) self.nextActionCombo.addItems([e.value for e in CueNextAction]) self.nextActionGroup.layout().addWidget(self.nextActionCombo) # Checks self.stopPauseCheck = QCheckBox(self) self.layout().addWidget(self.stopPauseCheck) self.retranslateUi() def retranslateUi(self): self.preWaitGroup.setTitle('Pre wait') self.preWaitLabel.setText('Wait before cue execution') self.postWaitGroup.setTitle('Post wait') self.postWaitLabel.setText('Wait after cue execution') self.nextActionGroup.setTitle('Next action') self.stopPauseCheck.setText('Pause instead of stop (if supported)') def load_settings(self, settings): if 'pre_wait' in settings: self.preWaitSpin.setValue(settings['pre_wait']) if 'post_wait' in settings: self.postWaitSpin.setValue(settings['post_wait']) if 'next_action' in settings: self.nextActionCombo.setCurrentText(settings['next_action']) if 'stop_pause' in settings: self.stopPauseCheck.setChecked(settings['stop_pause']) def enable_check(self, enable): self.preWaitGroup.setCheckable(enable) self.preWaitGroup.setChecked(False) self.postWaitGroup.setCheckable(enable) self.postWaitGroup.setChecked(False) self.nextActionGroup.setCheckable(enable) self.nextActionGroup.setChecked(False) self.stopPauseCheck.setTristate(enable) if enable: self.stopPauseCheck.setCheckState(Qt.PartiallyChecked) def get_settings(self): conf = {} checkable = self.preWaitGroup.isCheckable() if not (checkable and not self.preWaitGroup.isChecked()): conf['pre_wait'] = self.preWaitSpin.value() if not (checkable and not self.postWaitGroup.isChecked()): conf['post_wait'] = self.postWaitSpin.value() if not (checkable and not self.nextActionGroup.isChecked()): conf['next_action'] = self.nextActionCombo.currentText() if self.stopPauseCheck.checkState() != Qt.PartiallyChecked: conf['stop_pause'] = self.stopPauseCheck.isChecked() return conf
class FileChoiceTable(QTableWidget): """displays samples so user can choose some of them """ files = pyqtSignal(int) files_chosen = pyqtSignal(int) def __init__(self, project, log, header, query, num_columns, myfilter, allele_status_column = None, instant_accept_status = None, parent = None): super().__init__() self.log = log if parent: self.settings = parent.settings else: import GUI_login self.settings = GUI_login.get_settings("admin", self.log) self.header = header self.allele_status_column = allele_status_column self.instant_accept_status = instant_accept_status self.query = query self.num_columns = num_columns self.filter = myfilter self.init_UI() def init_UI(self): self.setColumnCount(len(self.header)) self.setHorizontalHeaderLabels(self.header) self.horizontalHeader().setStretchLastSection(True) self.verticalHeader().hide() def reset_filter(self, myfilter = ""): """sets a new filter for use in self.get_data() """ self.myfilter = myfilter def get_data(self): """get alleles from database """ success, data = db_internal.execute_query(self.query + self.myfilter, self.num_columns, self.log, "retrieving data for FileChoiceTable from database", "Database error", self) if success: self.data = data self.log.debug("Emitting 'files = {}'".format(len(self.data))) self.files.emit(len(self.data)) def fill_UI(self): """fills table with data """ self.get_data() rows = len(self.data) + 1 self.setRowCount(rows) self.check_dic = {} all_checked = True for (i, row) in enumerate(self.data): cell_widget = QWidget() mini_layout = QHBoxLayout(cell_widget) cell_widget.setLayout(mini_layout) self.check_dic[i] = QCheckBox(self) self.check_dic[i].clicked.connect(self.count_chosen) self.check_dic[i].clicked.connect(self.unselect_select_all) mini_layout.addWidget(self.check_dic[i]) mini_layout.setAlignment(Qt.AlignCenter) self.setCellWidget(i, 0, cell_widget) for (k, item) in enumerate(row): self.setItem(i, k + 1, QTableWidgetItem(str(item))) if self.allele_status_column: status = row[self.allele_status_column] color = general.color_dic[general.allele_status_dic[status.lower()]] status_item = QTableWidgetItem(status) status_item.setBackground(QColor(color)) if self.instant_accept_status: if status == self.instant_accept_status: self.check_dic[i].setChecked(True) status_item.setFont(general.font_bold) else: all_checked = False self.setItem(i, self.allele_status_column + 1, status_item) # add select-all row: cell_widget = QWidget() mini_layout = QHBoxLayout(cell_widget) cell_widget.setLayout(mini_layout) self.check_all = QCheckBox(self) mini_layout.addWidget(self.check_all) if all_checked: self.check_all.setChecked(True) mini_layout.setAlignment(Qt.AlignCenter) self.check_all.clicked.connect(self.toggle_select_all) self.setCellWidget(rows-1, 0, cell_widget) self.setItem(rows-1, 1, QTableWidgetItem("")) self.setItem(rows-1, 2, QTableWidgetItem("Select All")) self.setItem(rows-1, 3, QTableWidgetItem("")) self.setItem(rows-1, 4, QTableWidgetItem("")) self.resizeColumnsToContents() self.count_chosen() def count_chosen(self): """counts and emits the number of currently chosen files """ self.log.debug("Recounting chosen files...") n = 0 for i in self.check_dic: box = self.check_dic[i] if box.checkState(): n += 1 self.log.debug("\t=> Currently {} files chosen".format(n)) self.files_chosen.emit(n) def unselect_select_all(self): """unchecks the 'select all' checkbox when a single file is unchecked manually """ if not self.sender().checkState(): self.check_all.setChecked(False) def toggle_select_all(self): """select or deselect all alleles at once """ if self.check_all.checkState(): self.log.debug("Selecting all alleles") for i in self.check_dic: box = self.check_dic[i] box.setChecked(True) self.files_chosen.emit(len(self.data)) else: self.log.debug("Deselecting all alleles") for i in self.check_dic: box = self.check_dic[i] box.setChecked(False) self.files_chosen.emit(0)
class AutonumberDialog(QDialog): newtracks = pyqtSignal(int, int, 'Qt::CheckState', int, str, str, 'Qt::CheckState', name='newtracks') def __init__(self, parent=None, minval=0, numtracks=0, enablenumtracks=False): QDialog.__init__(self, parent) self.setWindowTitle( translate('Autonumbering Wizard', "Autonumbering Wizard")) winsettings('autonumbering', self) def hbox(*widgets): box = QHBoxLayout() [box.addWidget(z) for z in widgets] box.addStretch() return box vbox = QVBoxLayout() self._start = QSpinBox() self._start.setValue(minval) self._start.setMaximum(65536) startlabel = QLabel(translate('Autonumbering Wizard', "&Start: ")) startlabel.setBuddy(self._start) vbox.addLayout(hbox(startlabel, self._start)) self._padlength = QSpinBox() self._padlength.setValue(1) self._padlength.setMaximum(65535) self._padlength.setMinimum(1) label = QLabel(translate('Autonumbering Wizard', 'Max length after padding with zeroes: ')) label.setBuddy(self._padlength) vbox.addLayout(hbox(label, self._padlength)) self._separator = QCheckBox(translate('Autonumbering Wizard', "Add track &separator ['/']: Number of tracks")) self._numtracks = QSpinBox() self._numtracks.setEnabled(False) self._numtracks.setMaximum(65535) if numtracks: self._numtracks.setValue(numtracks) self._restart_numbering = QCheckBox(translate('Autonumbering Wizard', "&Restart numbering at each directory group.")) self._restart_numbering.stateChanged.connect( self.showDirectorySplittingOptions) vbox.addLayout(hbox(self._separator, self._numtracks)) vbox.addWidget(self._restart_numbering) self.custom_numbering_widgets = [] label = QLabel(translate('Autonumbering Wizard', "Group tracks using pattern:: ")) self.grouping = QLineEdit() label.setBuddy(self.grouping) vbox.addLayout(hbox(label, self.grouping)) self.custom_numbering_widgets.extend([label, self.grouping]) label = QLabel(translate('Autonumbering Wizard', "Output field: ")) self.output_field = QComboBox() label.setBuddy(self.output_field) self.output_field.setEditable(True) completer = self.output_field.completer() completer.setCaseSensitivity(Qt.CaseSensitive) completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion) self.output_field.setCompleter(completer) self.output_field.addItems(gettaglist()) vbox.addLayout(hbox(label, self.output_field)) self.custom_numbering_widgets.extend([label, self.output_field]) self.count_by_group = QCheckBox(translate('Autonumbering Wizard', 'Increase counter only on group change')) vbox.addWidget(self.count_by_group) self.custom_numbering_widgets.append(self.count_by_group) okcancel = OKCancel() vbox.addLayout(okcancel) self.setLayout(vbox) okcancel.ok.connect(self.emitValuesAndSave) okcancel.cancel.connect(self.close) self._separator.stateChanged.connect( lambda v: self._numtracks.setEnabled(v == Qt.Checked)) # self._restart_numbering.stateChanged.connect( # self.showDirectorySplittingOptions) self._separator.setChecked(enablenumtracks) self._loadSettings() def showDirectorySplittingOptions(self, state): is_checked = state == Qt.Checked for widget in self.custom_numbering_widgets: widget.setVisible(is_checked) if is_checked: self._numtracks.setVisible(False) self._separator.setText(translate('Autonumbering Wizard', "Add track &separator ['/']")) else: self._numtracks.setVisible(True) self._separator.setText(translate('Autonumbering Wizard', "Add track &separator ['/']: Number of tracks")) def emitValuesAndSave(self): if self._numtracks.isVisible(): if self._separator.isChecked(): numtracks = self._numtracks.value() else: numtracks = -1 # Don't use totals else: if self._separator.isChecked(): numtracks = -2 # Use totals, automaticall generated else: numtracks = -1 self.close() self.newtracks.emit( self._start.value(), numtracks, self._restart_numbering.checkState(), self._padlength.value(), str(self.grouping.text()), str(self.output_field.currentText()), self.count_by_group.checkState() ) self._saveSettings() def _loadSettings(self): cparser = PuddleConfig() section = 'autonumbering' self._start.setValue(cparser.get(section, 'start', 1)) self._separator.setCheckState( cparser.get(section, 'separator', Qt.Unchecked)) self._padlength.setValue(cparser.get(section, 'padlength', 1)) self._restart_numbering.setCheckState( cparser.get(section, 'restart', Qt.Unchecked)) self.count_by_group.setCheckState( cparser.get(section, 'count_by_group', Qt.Unchecked)) self.showDirectorySplittingOptions(self._restart_numbering.checkState()) self.grouping.setText(cparser.get(section, 'grouping', '%__dirpath%')) output_field_text = cparser.get(section, 'output_field', 'track') if not output_field_text: output_field_text = 'track' last_output_field_index = self.output_field.findText(output_field_text) if last_output_field_index > -1: self.output_field.setCurrentIndex(last_output_field_index) def _saveSettings(self): cparser = PuddleConfig() section = 'autonumbering' cparser.set(section, 'start', self._start.value()) cparser.set(section, 'separator', self._separator.checkState()) cparser.set(section, 'count_by_group', self.count_by_group.checkState()) cparser.set(section, 'numtracks', self._numtracks.value()) cparser.set(section, 'restart', self._restart_numbering.checkState()) cparser.set(section, 'padlength', self._padlength.value()) cparser.set(section, 'grouping', self.grouping.text()) cparser.set(section, 'output_field', self.output_field.currentText())
class AdvancedSerialDialog(QDialog): def __init__(self, state, parent): super().__init__(parent) self.setMinimumWidth(350) self.setModal(True) self.setWindowTitle("Advanced serial settings") layout = QVBoxLayout() self.setLayout(layout) texts = [ "Please note:", ( "Overriding the baud rate disables automatic" " detection and negotiation of baud rate." ), "Only use on special hardware.", ] for text in texts: lbl = QLabel(text, self) lbl.setWordWrap(True) layout.addWidget(lbl) layout.addStretch(1) self.cb = QCheckBox("Override baud rate", self) self.cb.stateChanged.connect(self.cb_state_changed) layout.addWidget(self.cb) self.sb = QSpinBox(self) self.sb.setRange(1, int(3e6)) layout.addWidget(self.sb) layout.addStretch(1) buttons_widget = QWidget(self) layout.addWidget(buttons_widget) hbox = QHBoxLayout() buttons_widget.setLayout(hbox) hbox.addStretch(1) cancel_btn = QPushButton("Cancel") cancel_btn.clicked.connect(self.reject) hbox.addWidget(cancel_btn) save_btn = QPushButton("Save") save_btn.setDefault(True) save_btn.clicked.connect(self.accept) hbox.addWidget(save_btn) self.set_state(state) def cb_state_changed(self, state): self.sb.setEnabled(bool(state)) def set_state(self, state): checked = state is not None self.cb.setChecked(checked) self.cb_state_changed(checked) self.sb.setValue(state if checked else 115200) def get_state(self): return self.sb.value() if self.cb.checkState() else None
class PostScriptTab(QWidget): name = "Postscript" def __init__(self, font, parent=None): super(PostScriptTab, self).__init__(parent) namingGroup = QGroupBox("Naming", self) # namingGroup.setFlat(True) namingLayout = QGridLayout(self) fontNameLabel = QLabel("FontName:", self) self.fontNameEdit = QLineEdit(font.info.postscriptFontName, self) fullNameLabel = QLabel("FullName:", self) self.fullNameEdit = QLineEdit(font.info.postscriptFullName, self) weightNameLabel = QLabel("WeightName:", self) self.weightNameEdit = QLineEdit(font.info.postscriptWeightName, self) uniqueIDLabel = QLabel("Unique ID:", self) if font.info.postscriptUniqueID is not None: uniqueID = str(font.info.postscriptUniqueID) else: uniqueID = '' self.uniqueIDEdit = QLineEdit(uniqueID, self) self.uniqueIDEdit.setValidator(QIntValidator(self)) l = 0 namingLayout.addWidget(fontNameLabel, l, 0) namingLayout.addWidget(self.fontNameEdit, l, 1, 1, 2) namingLayout.addWidget(weightNameLabel, l, 3) namingLayout.addWidget(self.weightNameEdit, l, 4, 1, 2) l += 1 namingLayout.addWidget(fullNameLabel, l, 0) namingLayout.addWidget(self.fullNameEdit, l, 1, 1, 2) namingLayout.addWidget(uniqueIDLabel, l, 3) namingLayout.addWidget(self.uniqueIDEdit, l, 4, 1, 2) namingGroup.setLayout(namingLayout) hintingGroup = QGroupBox("Hinting", self) # hintingGroup.setFlat(True) hintingLayout = QGridLayout(self) blueValuesLabel = QLabel("Blue values:", self) blueValues = " ".join(str(val) for val in font.info.postscriptBlueValues) self.blueValuesEdit = QLineEdit(blueValues, self) otherBluesLabel = QLabel("Other blues:", self) otherBlues = " ".join(str(val) for val in font.info.postscriptOtherBlues) self.otherBluesEdit = QLineEdit(otherBlues, self) familyBluesLabel = QLabel("Family blues:", self) familyBlues = " ".join(str(val) for val in font.info.postscriptFamilyBlues) self.familyBluesEdit = QLineEdit(familyBlues, self) familyOtherBluesLabel = QLabel("Family other blues:", self) familyOtherBlues = " ".join( str(val) for val in font.info.postscriptFamilyOtherBlues) self.familyOtherBluesEdit = QLineEdit(familyOtherBlues, self) l = 0 hintingLayout.addWidget(blueValuesLabel, l, 0) hintingLayout.addWidget(self.blueValuesEdit, l, 1, 1, 2) hintingLayout.addWidget(familyBluesLabel, l, 3) hintingLayout.addWidget(self.familyBluesEdit, l, 4, 1, 2) l += 1 hintingLayout.addWidget(otherBluesLabel, l, 0) hintingLayout.addWidget(self.otherBluesEdit, l, 1, 1, 2) hintingLayout.addWidget(familyOtherBluesLabel, l, 3) hintingLayout.addWidget(self.familyOtherBluesEdit, l, 4, 1, 2) l += 1 blueFuzzLabel = QLabel("Blue fuzz:", self) if font.info.postscriptBlueFuzz is not None: blueFuzz = str(font.info.postscriptBlueFuzz) else: blueFuzz = '' self.blueFuzzEdit = QLineEdit(blueFuzz, self) self.blueFuzzEdit.setValidator(QDoubleValidator(self)) stemSnapHLabel = QLabel("StemSnapH:", self) stemSnapH = " ".join(str(val) for val in font.info.postscriptStemSnapH) self.stemSnapHEdit = QLineEdit(stemSnapH, self) blueScaleLabel = QLabel("Blue scale:", self) if font.info.postscriptBlueScale is not None: blueScale = str(font.info.postscriptBlueScale) else: blueScale = '' self.blueScaleEdit = QLineEdit(blueScale, self) self.blueScaleEdit.setValidator(QDoubleValidator(self)) stemSnapVLabel = QLabel("StemSnapV:", self) stemSnapV = " ".join(str(val) for val in font.info.postscriptStemSnapV) self.stemSnapVEdit = QLineEdit(stemSnapV, self) blueShiftLabel = QLabel("Blue shift:", self) if font.info.postscriptBlueShift is not None: blueShift = str(font.info.postscriptBlueShift) else: blueShift = '' self.blueShiftEdit = QLineEdit(blueShift, self) self.blueShiftEdit.setValidator(QDoubleValidator(self)) forceBoldLabel = QLabel("Force bold:", self) forceBold = font.info.postscriptForceBold self.forceBoldBox = QCheckBox(self) self.forceBoldBox.setTristate() if forceBold is None: self.forceBoldBox.setCheckState(Qt.PartiallyChecked) else: self.forceBoldBox.setChecked(forceBold) hintingLayout.addWidget(blueFuzzLabel, l, 0) hintingLayout.addWidget(self.blueFuzzEdit, l, 1, 1, 2) hintingLayout.addWidget(stemSnapHLabel, l, 3) hintingLayout.addWidget(self.stemSnapHEdit, l, 4, 1, 2) l += 1 hintingLayout.addWidget(blueScaleLabel, l, 0) hintingLayout.addWidget(self.blueScaleEdit, l, 1, 1, 2) hintingLayout.addWidget(stemSnapVLabel, l, 3) hintingLayout.addWidget(self.stemSnapVEdit, l, 4, 1, 2) l += 1 hintingLayout.addWidget(blueShiftLabel, l, 0) hintingLayout.addWidget(self.blueShiftEdit, l, 1, 1, 2) hintingLayout.addWidget(forceBoldLabel, l, 3) hintingLayout.addWidget(self.forceBoldBox, l, 4, 1, 2) hintingGroup.setLayout(hintingLayout) metricsGroup = QGroupBox("Metrics", self) # metricsGroup.setFlat(True) metricsLayout = QGridLayout(self) defaultWidthXLabel = QLabel("DefaultWidthX:", self) if font.info.postscriptDefaultWidthX is not None: defaultWidthX = str(font.info.postscriptDefaultWidthX) else: defaultWidthX = '' self.defaultWidthXEdit = QLineEdit(defaultWidthX, self) self.defaultWidthXEdit.setValidator(QDoubleValidator(self)) underlineThicknessLabel = QLabel("UnderlineThickness:", self) if font.info.postscriptUnderlineThickness is not None: underlineThickness = str(font.info.postscriptUnderlineThickness) else: underlineThickness = '' self.underlineThicknessEdit = QLineEdit(underlineThickness, self) self.underlineThicknessEdit.setValidator(QDoubleValidator(self)) nominalWidthXLabel = QLabel("NominalWidthX:", self) if font.info.postscriptNominalWidthX is not None: nominalWidthX = str(font.info.postscriptNominalWidthX) else: nominalWidthX = '' self.nominalWidthXEdit = QLineEdit(nominalWidthX, self) self.nominalWidthXEdit.setValidator(QDoubleValidator(self)) underlinePositionLabel = QLabel("UnderlinePosition:", self) if font.info.postscriptUnderlinePosition is not None: underlinePosition = str(font.info.postscriptUnderlinePosition) else: underlinePosition = '' self.underlinePositionEdit = QLineEdit(underlinePosition, self) self.underlinePositionEdit.setValidator(QDoubleValidator(self)) slantAngleLabel = QLabel("SlantAngle:", self) if font.info.postscriptSlantAngle is not None: slantAngle = str(font.info.postscriptSlantAngle) else: slantAngle = '' self.slantAngleEdit = QLineEdit(slantAngle, self) self.slantAngleEdit.setValidator(QDoubleValidator(self)) isFixedPitchLabel = QLabel("isFixedPitched:", self) isFixedPitch = font.info.postscriptIsFixedPitch self.isFixedPitchBox = QCheckBox(self) self.isFixedPitchBox.setTristate() if isFixedPitch is None: self.isFixedPitchBox.setCheckState(Qt.PartiallyChecked) else: self.isFixedPitchBox.setChecked(isFixedPitch) l = 0 metricsLayout.addWidget(defaultWidthXLabel, l, 0) metricsLayout.addWidget(self.defaultWidthXEdit, l, 1, 1, 2) metricsLayout.addWidget(underlineThicknessLabel, l, 3) metricsLayout.addWidget(self.underlineThicknessEdit, l, 4, 1, 2) l += 1 metricsLayout.addWidget(nominalWidthXLabel, l, 0) metricsLayout.addWidget(self.nominalWidthXEdit, l, 1, 1, 2) metricsLayout.addWidget(underlinePositionLabel, l, 3) metricsLayout.addWidget(self.underlinePositionEdit, l, 4, 1, 2) l += 1 metricsLayout.addWidget(slantAngleLabel, l, 0) metricsLayout.addWidget(self.slantAngleEdit, l, 1, 1, 2) metricsLayout.addWidget(isFixedPitchLabel, l, 3) metricsLayout.addWidget(self.isFixedPitchBox, l, 4, 1, 2) metricsGroup.setLayout(metricsLayout) charactersGroup = QGroupBox("Characters", self) # charactersGroup.setFlat(True) charactersLayout = QGridLayout(self) defaultCharacterLabel = QLabel("Default character:", self) self.defaultCharacterEdit = QLineEdit( font.info.postscriptDefaultCharacter, self) windowsCharacterSetLabel = QLabel("Windows character set:", self) self.windowsCharacterSetDrop = QComboBox(self) items = [ "None", "ANSI", "Default", "Symbol", "Macintosh", "Shift JIS", "Hangul", "Hangul (Johab)", "GB2312", "Chinese BIG5", "Greek", "Turkish", "Vietnamese", "Hebrew", "Arabic", "Baltic", "Bitstream", "Cyrillic", "Thai", "Eastern European", "OEM"] self.windowsCharacterSetDrop.insertItems(0, items) if font.info.postscriptWindowsCharacterSet is not None: self.windowsCharacterSetDrop.setCurrentIndex( font.info.postscriptWindowsCharacterSet) l = 0 charactersLayout.addWidget(defaultCharacterLabel, l, 0) charactersLayout.addWidget(self.defaultCharacterEdit, l, 1, 1, 2) charactersLayout.addWidget(windowsCharacterSetLabel, l, 3) charactersLayout.addWidget(self.windowsCharacterSetDrop, l, 4, 1, 2) charactersGroup.setLayout(charactersLayout) mainLayout = QVBoxLayout() mainLayout.addWidget(namingGroup) mainLayout.addWidget(hintingGroup) mainLayout.addWidget(metricsGroup) mainLayout.addWidget(charactersGroup) self.setLayout(mainLayout) def writeValues(self, font): fontName = self.fontNameEdit.text() if fontName != '': font.info.postscriptFontName = fontName else: font.info.postscriptFontName = None fullName = self.fullNameEdit.text() if fullName != '': font.info.postscriptFullName = fullName else: font.info.postscriptFullName = None weightName = self.weightNameEdit.text() if weightName != '': font.info.postscriptWeightName = weightName else: font.info.postscriptWeightName = None uniqueID = self.uniqueIDEdit.text() if uniqueID != '': font.info.postscriptUniqueID = int(uniqueID) else: font.info.postscriptUniqueID = None blueValues = self.blueValuesEdit.text().split(" ") if blueValues is None: font.info.postscriptBlueValues = None else: blues = [] for blue in blueValues: if blue != '': blues.append(int(blue)) font.info.postscriptBlueValues = blues otherBlues = self.otherBluesEdit.text().split(" ") if otherBlues is None: font.info.postscriptOtherBlues = None else: blues = [] for blue in otherBlues: if blue != '': blues.append(int(blue)) font.info.postscriptOtherBlues = blues familyBlues = self.familyBluesEdit.text().split(" ") if familyBlues is None: font.info.postscriptFamilyBlues = None else: blues = [] for blue in familyBlues: if blue != '': blues.append(int(blue)) font.info.postscriptFamilyBlues = blues familyOtherBlues = self.familyOtherBluesEdit.text().split(" ") if familyOtherBlues is None: font.info.postscriptFamilyOtherBlues = None else: blues = [] for blue in familyOtherBlues: if blue != '': blues.append(int(blue)) font.info.postscriptFamilyOtherBlues = blues blueFuzz = self.blueFuzzEdit.text() if "." in blueFuzz: font.info.postscriptBlueFuzz = float(blueFuzz) elif blueFuzz != '': font.info.postscriptBlueFuzz = int(blueFuzz) else: font.info.postscriptBlueFuzz = None blueScale = self.blueScaleEdit.text() if blueScale != '': font.info.postscriptBlueScale = float(blueScale) else: font.info.postscriptBlueScale = None blueShift = self.blueShiftEdit.text() if "." in blueShift: font.info.postscriptBlueShift = float(blueShift) elif blueShift != '': font.info.postscriptBlueShift = int(blueShift) else: font.info.postscriptBlueShift = None stemSnapH = self.stemSnapHEdit.text().split(" ") if stemSnapH is None: font.info.postscriptStemSnapH = None else: stems = [] for stem in stemSnapH: if stem != '': stems.append(int(stem)) font.info.postscriptStemSnapH = stems stemSnapV = self.stemSnapVEdit.text().split(" ") if stemSnapV is None: font.info.postscriptStemSnapV = None else: stems = [] for stem in stemSnapV: if stem != '': stems.append(int(stem)) font.info.postscriptStemSnapV = stems forceBold = self.forceBoldBox.checkState() if forceBold == Qt.PartiallyChecked: font.info.postscriptForceBold = None else: font.info.postscriptForceBold = bool(forceBold) defaultWidthX = self.defaultWidthXEdit.text() if "." in defaultWidthX: font.info.postscriptDefaultWidthX = float(defaultWidthX) elif defaultWidthX != '': font.info.postscriptDefaultWidthX = int(defaultWidthX) else: font.info.postscriptDefaultWidthX = None nominalWidthX = self.nominalWidthXEdit.text() if "." in nominalWidthX: font.info.postscriptNominalWidthX = float(nominalWidthX) elif nominalWidthX != '': font.info.postscriptNominalWidthX = int(nominalWidthX) else: font.info.postscriptNominalWidthX = None underlineThickness = self.underlineThicknessEdit.text() if "." in underlineThickness: font.info.postscriptUnderlineThickness = float(underlineThickness) elif underlineThickness != '': font.info.postscriptUnderlineThickness = \ int(underlineThickness) else: font.info.postscriptUnderlineThickness = None underlinePosition = self.underlinePositionEdit.text() if "." in underlinePosition: font.info.postscriptUnderlinePosition = float(underlinePosition) elif underlinePosition != '': font.info.postscriptUnderlinePosition = int(underlinePosition) else: font.info.postscriptUnderlinePosition = None slantAngle = self.slantAngleEdit.text() if "." in slantAngle: font.info.postscriptSlantAngle = float(slantAngle) elif slantAngle != '': font.info.postscriptSlantAngle = int(slantAngle) else: font.info.postscriptSlantAngle = None isFixedPitch = self.isFixedPitchBox.checkState() if isFixedPitch == Qt.PartiallyChecked: font.info.postscriptIsFixedPitch = None else: font.info.postscriptIsFixedPitch = bool(isFixedPitch) defaultCharacter = self.defaultCharacterEdit.text() if defaultCharacter != '': font.info.postscriptDefaultCharacter = defaultCharacter else: font.info.postscriptDefaultCharacter = None windowsCharacterSet = self.windowsCharacterSetDrop.currentIndex() if windowsCharacterSet == 0: font.info.postscriptWindowsCharacterSet = None else: font.info.postscriptWindowsCharacterSet = windowsCharacterSet
class LayerControl(QWidget): """ Custom LayerControl widget. Constructor: ipc = LayerControl('test title') Events: .change the contents were changed .remove the image should be removed The '.change' event has attached attributes holding the values from the widget, all checked so they are 'sane'. """ # various sizes ButtonWidth = 40 ButtonHeight = 40 ComboboxWidth = 70 # signals raised by this widget change = pyqtSignal(str, int, QColor, QColor, bool, bool, int, int) remove = pyqtSignal() # some stylesheets LabelStyle = 'QLabel { background-color : #f0f0f0; border: 1px solid gray; border-radius: 3px; }' GroupStyle = ('QGroupBox { background-color: rgb(230, 230, 230); }' 'QGroupBox::title { subcontrol-origin: margin; ' 'background-color: rgb(215, 215, 215); ' 'border-radius: 3px; ' 'padding: 2 2px; ' 'color: black; }') ButtonStyle = ('QPushButton {' 'margin: 1px;' 'border-color: #0c457e;' 'border-style: outset;' 'border-radius: 3px;' 'border-width: 1px;' 'color: black;' 'background-color: white;' '}') ButtonColourStyle = ('QPushButton {' 'margin: 1px;' 'border-color: #0c457e;' 'border-style: outset;' 'border-radius: 3px;' 'border-width: 1px;' 'color: black;' 'background-color: %s;' '}') def __init__(self, title, placement=DefaultPlacement, width=DefaultWidth, closed=DefaultClosed, filled=DefaultFilled, colour=DefaultColour, fillcolour=DefaultFillColour, offset_x=0, offset_y=0): """Initialise a LayerControl instance. title text to show in static box outline around control placement placement string for object width width in pixels of the drawn polygon colour sets the colour of the polygon outline closed True if the polygon is to be forcibly closed filled True if the polygon is to be filled fillcolour the colour to fill the polygon with (if filled is True) offset_x X offset of object offset_y Y offset of object """ super().__init__() # save parameters self.v_placement = placement self.v_width = width self.v_colour = colour self.v_closed = closed self.v_filled = filled self.v_fillcolour = fillcolour self.v_offset_x = offset_x self.v_offset_y = offset_y # create subwidgets used in this custom widget self.placement = QComboBox() for p in [ 'none', 'nw', 'cn', 'ne', 'ce', 'se', 'cs', 'sw', 'cw', 'cc' ]: self.placement.addItem(p) self.placement.setCurrentIndex(9) self.line_width = QComboBox() for p in range(21): self.line_width.addItem(str(p)) self.line_width.setCurrentIndex(3) self.line_width.setFixedWidth(LayerControl.ComboboxWidth) self.line_colour = QPushButton('') self.line_colour.setFixedWidth(LayerControl.ButtonWidth) self.line_colour.setToolTip('Click here to change the point colour') self.line_colour.setStyleSheet(LayerControl.ButtonStyle) self.fill_colour = QPushButton('') self.fill_colour.setFixedWidth(LayerControl.ButtonWidth) self.fill_colour.setToolTip('Click here to change the fill colour') self.fill_colour.setStyleSheet(LayerControl.ButtonStyle) self.cb_closed = QCheckBox('closed: ', self) self.cb_filled = QCheckBox('filled: ', self) self.x_offset = QComboBox() for p in range(0, 121, 10): self.x_offset.addItem(str(p - 60)) self.x_offset.setCurrentIndex(6) self.x_offset.setFixedWidth(LayerControl.ComboboxWidth) self.y_offset = QComboBox() for p in range(0, 121, 10): self.y_offset.addItem(str(p - 60)) self.y_offset.setCurrentIndex(6) self.y_offset.setFixedWidth(LayerControl.ComboboxWidth) btn_remove = QPushButton('Remove') btn_remove.resize(btn_remove.sizeHint()) btn_update = QPushButton('Update') btn_update.resize(btn_update.sizeHint()) # start the layout option_box = QGroupBox(title) option_box.setStyleSheet(LayerControl.GroupStyle) box_layout = QGridLayout() box_layout.setContentsMargins(2, 2, 2, 2) box_layout.setHorizontalSpacing(1) box_layout.setColumnStretch(0, 1) # start layout row = 1 label = QLabel('placement: ') label.setAlignment(Qt.AlignRight) box_layout.addWidget(label, row, 0) box_layout.addWidget(self.placement, row, 1) label = QLabel('width: ') label.setAlignment(Qt.AlignRight) box_layout.addWidget(label, row, 2) box_layout.addWidget(self.line_width, row, 3) row += 1 label = QLabel('colour: ') label.setAlignment(Qt.AlignRight) box_layout.addWidget(label, row, 0) box_layout.addWidget(self.line_colour, row, 1) label = QLabel('fill colour: ') label.setAlignment(Qt.AlignRight) box_layout.addWidget(label, row, 2) box_layout.addWidget(self.fill_colour, row, 3) row += 1 label = QLabel('filled: ') label.setAlignment(Qt.AlignRight) box_layout.addWidget(label, row, 2) box_layout.addWidget(self.cb_filled, row, 3) row += 1 label = QLabel('offset X: ') label.setAlignment(Qt.AlignRight) box_layout.addWidget(label, row, 0) box_layout.addWidget(self.x_offset, row, 1) label = QLabel('Y: ') label.setAlignment(Qt.AlignRight) box_layout.addWidget(label, row, 2) box_layout.addWidget(self.y_offset, row, 3) row += 1 box_layout.addWidget(btn_remove, row, 1) box_layout.addWidget(btn_update, row, 3) option_box.setLayout(box_layout) layout = QHBoxLayout() layout.setContentsMargins(1, 1, 1, 1) layout.addWidget(option_box) self.setLayout(layout) # set size hints self.setMinimumSize(300, 200) size_policy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.setSizePolicy(size_policy) # connect internal widget events to handlers self.line_colour.clicked.connect(self.changeLineColour) self.fill_colour.clicked.connect(self.changeFillColour) btn_remove.clicked.connect(self.removeImage) btn_update.clicked.connect(self.updateData) def changeLineColour(self, event): color = QColorDialog.getColor() if color.isValid(): colour = color.name() # set colour button background self.line_colour.setStyleSheet(LayerControl.ButtonColourStyle % colour) def changeFillColour(self, event): color = QColorDialog.getColor() if color.isValid(): colour = color.name() # set colour button background self.fill_colour.setStyleSheet(LayerControl.ButtonColourStyle % colour) def removeImage(self, event): self.remove.emit() def updateData(self, event): # get data from the widgets placement = str(self.placement.currentText()) if placement == 'none': placement = None line_width = int(self.line_width.currentText()) line_colour = self.line_colour.palette().color(1) fill_colour = self.fill_colour.palette().color(1) closed = self.cb_closed.checkState() filled = self.cb_filled.checkState() x_offset = int(self.x_offset.currentText()) y_offset = int(self.y_offset.currentText()) print( f'updateData: placement={placement}, line_width={line_width}, closed={closed}, filled={filled}, x_offset={x_offset}, y_offset={y_offset}' ) self.change.emit(placement, line_width, line_colour, fill_colour, closed, filled, x_offset, y_offset)
class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() browseNetwork1Button = self.createButton(_('Browse'), self.browseNetwork1File) browseNetwork2Button = self.createButton(_('Browse'), self.browseNetwork2File) browseNetworkMappingButton = self.createButton(_('Browse'), self.browseNetworkMappingFile) browseList1Button = self.createButton(_('Browse'), self.browseList1File) browseList2Button = self.createButton(_('Browse'), self.browseList2File) browseTrueMapButton = self.createButton(_('Browse'), self.browseTrueMapFile) browseNetworkFlatButton = self.createButton(_('Browse'), self.browseNetworkFlatFile) generateNetworkFlatButton = self.createButton( _('Generate flat network'), self.genFlatNetwork) userLinkButton = self.createButton( _("Link user"), self.userLink) self.network1PathComboBox = self.createComboBox() self.network2PathComboBox = self.createComboBox() self.networkMappingPathComboBox = self.createComboBox() self.networkFlatPathComboBox = self.createComboBox() self.sampleUser1PathComboBox = self.createComboBox() self.sampleUser2PathComboBox = self.createComboBox() self.trueMapPathComboBox = self.createComboBox() self.delimiterComboBox = self.createComboBox('\\t') self.delimiterComboBox.addItem(',') self.bfsLevelComboBox = self.createComboBox('2') self.bfsLevelComboBox.addItem('3') self.bfsLevelComboBox.addItem('4') self.bfsLevelComboBox.addItem('5') network1Label = QLabel(_('Network 1:')) network2Label = QLabel(_('Network 2:')) networkMappingLabel = QLabel(_('Network mapping:')) sampleUser1Label = QLabel(_("Sample user list 1:")) sampleUser2Label = QLabel(_("Sample user list 2:")) trueMapLabel = QLabel(_("True map: ")) networkFlatLabel = QLabel(_('Flat network:')) delimiterLabel = QLabel(_('CSV delimiter:')) bfsLevelLabel = QLabel(_('BFS level:')) self.infoCheckBox = QCheckBox(_('Info')) self.infoCheckBox.setCheckState(True) self.warnCheckBox = QCheckBox(_('Warn')) self.warnCheckBox.setCheckState(True) self.fatalCheckBox = QCheckBox(_('Fatal')) self.fatalCheckBox.setCheckState(True) self.importantCheckBox = QCheckBox(_('Important')) self.importantCheckBox.setCheckState(True) self.verboseCheckBox = QCheckBox(_('Verbose')) self.logTextBox = self.createLogBox() mainLayout = QGridLayout() mainLayout.setContentsMargins(5, 5, 5, 5) mainLayout.addWidget(network1Label, 0, 0) mainLayout.addWidget(self.network1PathComboBox, 0, 1, 1, 4) mainLayout.addWidget(browseNetwork1Button, 0, 5, 1, 2) mainLayout.addWidget(network2Label, 1, 0) mainLayout.addWidget(self.network2PathComboBox, 1, 1, 1, 4) mainLayout.addWidget(browseNetwork2Button, 1, 5, 1, 2) mainLayout.addWidget(networkMappingLabel, 2, 0) mainLayout.addWidget(self.networkMappingPathComboBox, 2, 1, 1, 4) mainLayout.addWidget(browseNetworkMappingButton, 2, 5, 1, 2) mainLayout.addWidget(sampleUser1Label, 3, 0) mainLayout.addWidget(self.sampleUser1PathComboBox, 3, 1, 1, 4) mainLayout.addWidget(browseList1Button, 3, 5, 1, 2) mainLayout.addWidget(sampleUser2Label, 4, 0) mainLayout.addWidget(self.sampleUser2PathComboBox, 4, 1, 1, 4) mainLayout.addWidget(browseList2Button, 4, 5, 1, 2) mainLayout.addWidget(trueMapLabel, 5, 0) mainLayout.addWidget(self.trueMapPathComboBox, 5, 1, 1, 4) mainLayout.addWidget(browseTrueMapButton, 5, 5, 1, 2) mainLayout.addWidget(networkFlatLabel, 6, 0) mainLayout.addWidget(self.networkFlatPathComboBox, 6, 1, 1, 4) mainLayout.addWidget(browseNetworkFlatButton, 6, 5, 1, 2) mainLayout.addWidget(delimiterLabel, 7, 0, 1, 1) mainLayout.addWidget(self.delimiterComboBox, 7, 1, 1, 1) mainLayout.addWidget(bfsLevelLabel, 7, 2, 1, 1) mainLayout.addWidget(self.bfsLevelComboBox , 7, 3, 1, 2) mainLayout.addWidget(generateNetworkFlatButton, 7, 5, 1, 2) mainLayout.addWidget(userLinkButton, 7, 7, 1, 2) mainLayout.addWidget(self.infoCheckBox, 8, 0, 1, 1) mainLayout.addWidget(self.warnCheckBox, 8, 1, 1, 1) mainLayout.addWidget(self.fatalCheckBox, 8, 2, 1, 1) mainLayout.addWidget(self.importantCheckBox, 8, 3, 1, 1) mainLayout.addWidget(self.verboseCheckBox, 8, 4, 1, 1) mainLayout.addWidget(self.logTextBox, 9, 0, 5, 7) widget = QWidget() self.setCentralWidget(widget) widget.setLayout(mainLayout) self.createActions() self.createMenus() self.setWindowTitle(_('Flat network user relationship tool')) @staticmethod def updateComboBox(comboBox): if comboBox.findText(comboBox.currentText()) == -1: comboBox.addItem(comboBox.currentText()) def createActions(self): self.englishAct = QAction("&English", self, triggered = self.switchToEnglish) self.chineseAct = QAction("简体中文", self, triggered = self.switchToChinese) def createMenus(self): self.langMenu = self.menuBar().addMenu(_("&Language")) self.langMenu.addAction(self.englishAct) self.langMenu.addAction(self.chineseAct) def switchToEnglish(self): gConfigure['lang'] = 'en' SaveConfigure() def switchToChinese(self): gConfigure['lang'] = 'zh' SaveConfigure() def browseNetwork1File(self): fileNetwork1Path = QFileDialog.getOpenFileName( self, _('Network 1 CSV File'), QDir.currentPath(), 'Comma-separated values (*.csv)') if fileNetwork1Path: if self.network1PathComboBox.findText( fileNetwork1Path[0]) == -1: self.network1PathComboBox.addItem(fileNetwork1Path[0]) self.network1PathComboBox.setCurrentIndex( self.network1PathComboBox.findText(fileNetwork1Path[0])) def browseNetwork2File(self): fileNetwork2Path = QFileDialog.getOpenFileName( self, _('Network 2 CSV File'), QDir.currentPath(), 'Comma-separated values (*.csv)') if fileNetwork2Path: if self.network2PathComboBox.findText(fileNetwork2Path[0]) == -1: self.network2PathComboBox.addItem(fileNetwork2Path[0]) self.network2PathComboBox.setCurrentIndex( self.network2PathComboBox.findText(fileNetwork2Path[0])) def browseList1File(self): list1FilePath = QFileDialog.getOpenFileName( self, _('Sample user list 1 CSV File'), QDir.currentPath(), 'Comma-separated values (*.csv)') if list1FilePath: if self.sampleUser1PathComboBox.findText(list1FilePath[0]) == -1: self.sampleUser1PathComboBox.addItem(list1FilePath[0]) self.sampleUser1PathComboBox.setCurrentIndex( self.sampleUser1PathComboBox.findText(list1FilePath[0])) def browseList1File(self): list1FilePath = QFileDialog.getOpenFileName( self, _('Sample user list 1 CSV File'), QDir.currentPath(), 'Comma-separated values (*.csv)') if list1FilePath: if self.sampleUser1PathComboBox.findText(list1FilePath[0]) == -1: self.sampleUser1PathComboBox.addItem(list1FilePath[0]) self.sampleUser1PathComboBox.setCurrentIndex( self.sampleUser1PathComboBox.findText(list1FilePath[0])) def browseList2File(self): list2FilePath = QFileDialog.getOpenFileName( self, _('Sample user list 2 CSV File'), QDir.currentPath(), 'Comma-separated values (*.csv)') if list2FilePath: if self.sampleUser2PathComboBox.findText(list2FilePath[0]) == -1: self.sampleUser2PathComboBox.addItem(list2FilePath[0]) self.sampleUser2PathComboBox.setCurrentIndex( self.sampleUser2PathComboBox.findText(list2FilePath[0])) def browseTrueMapFile(self): trueMapFilePath = QFileDialog.getOpenFileName( self, _('True mapping CSV File'), QDir.currentPath(), 'Comma-separated values (*.csv)') if trueMapFilePath: if self.trueMapPathComboBox.findText(trueMapFilePath[0]) == -1: self.trueMapPathComboBox.addItem(trueMapFilePath[0]) self.trueMapPathComboBox.setCurrentIndex( self.trueMapPathComboBox.findText(trueMapFilePath[0])) def browseNetworkMappingFile(self): fileNetworkMappingPath = QFileDialog.getOpenFileName( self, _('Network Mapping CSV File'), QDir.currentPath(), 'Comma-separated values (*.csv)') if fileNetworkMappingPath: if self.networkMappingPathComboBox.findText( fileNetworkMappingPath[0]) == -1: self.networkMappingPathComboBox.addItem( fileNetworkMappingPath[0]) self.networkMappingPathComboBox.setCurrentIndex( self.networkMappingPathComboBox.findText( fileNetworkMappingPath[0])) def browseNetworkFlatFile(self): fileNetworkFlatPath = QFileDialog.getSaveFileName( self, _('Flat Network CSV File'), QDir.currentPath(), 'Comma-separated values (*.csv)') if fileNetworkFlatPath: if self.networkFlatPathComboBox.findText( fileNetworkFlatPath[0]) == -1: self.networkFlatPathComboBox.addItem( fileNetworkFlatPath[0]) self.networkFlatPathComboBox.setCurrentIndex( self.networkFlatPathComboBox.findText( fileNetworkFlatPath[0])) def createButton(self, text, member): button = QPushButton(text) button.clicked.connect(member) return button def createComboBox(self, text=""): comboBox = QComboBox() comboBox.setEditable(True) comboBox.addItem(text) comboBox.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) return comboBox def createLogBox(self): logTextBox = QPlainTextEdit() logTextBox.setReadOnly(True) logTextBox.setMaximumBlockCount(100) logTextBox.setCenterOnScroll(True) return logTextBox def insertLog(self, logline=''): self.logTextBox.appendPlainText(logline) self.updateInterface() def getFilePath(self): filePath = {} filePath['FirstNetFile'] = self.network1PathComboBox.currentText() filePath['SecondNetFile'] = self.network2PathComboBox.currentText() filePath['NodeMappingFile'] = self.networkMappingPathComboBox.currentText() filePath['OutputFile'] = self.networkFlatPathComboBox.currentText() filePath['TrueMapFile'] = self.trueMapPathComboBox.currentText() return filePath def getDelimiter(self): delimiter = self.delimiterComboBox.currentText() if delimiter == '\\t': delimiter = '\t' return delimiter def getSampleFilePath(self): sampleFilePath = {} sampleFilePath["first"] = self.sampleUser1PathComboBox.currentText() sampleFilePath["second"] = self.sampleUser2PathComboBox.currentText() return sampleFilePath def genFlatNetwork(self): filePath = self.getFilePath() delimiter = self.self.getDelimiter() bfsLevel = self.bfsLevelComboBox.currentText() if not bfsLevel.isdigit(): bfsLevel = 2 Network.GenerateSubNetwork(filePath, delimiter, bfsLevel) def userLink(self): filePath = self.getFilePath() delimiter = self.getDelimiter() sampleFilePath = self.getSampleFilePath() Guess.DoUserLink(filePath, sampleFilePath, delimiter) def updateInterface(self): QApplication.processEvents() def getIsInfoLog(self): return self.infoCheckBox.checkState() def getIsWarnLog(self): return self.warnCheckBox.checkState() def getIsFatalLog(self): return self.fatalCheckBox.checkState() def getIsImportantLog(self): return self.importantCheckBox.checkState() def getIsVerboseLog(self): return self.verboseCheckBox.checkState()
class Example(QWidget): def __init__(self): ''' 一些初始设置 ''' super().__init__() self.initUI() def initUI(self): ''' 界面初始设置 ''' self.cb1 = QCheckBox('全选', self) self.cb2 = QCheckBox('你是', self) self.cb3 = QCheckBox('我的', self) self.cb4 = QCheckBox('宝贝', self) bt = QPushButton('提交', self) self.resize(300, 200) self.setWindowTitle('关注微信公众号:学点编程吧--复选框') self.cb1.move(20, 20) self.cb2.move(30, 50) self.cb3.move(30, 80) self.cb4.move(30, 110) bt.move(20, 160) self.cb1.stateChanged.connect(self.changecb1) self.cb2.stateChanged.connect(self.changecb2) self.cb3.stateChanged.connect(self.changecb2) self.cb4.stateChanged.connect(self.changecb2) bt.clicked.connect(self.go) self.show() def go(self): ''' 复选框选择状态提交后看看你能输出什么 ''' if self.cb2.isChecked() and self.cb3.isChecked( ) and self.cb4.isChecked(): QMessageBox.information(self, 'I Love U', '你是我的宝贝!') elif self.cb2.isChecked() and self.cb3.isChecked(): QMessageBox.information(self, 'I Love U', '你是我的!') elif self.cb2.isChecked() and self.cb4.isChecked(): QMessageBox.information(self, 'I Love U', '你是宝贝!') elif self.cb3.isChecked() and self.cb4.isChecked(): QMessageBox.information(self, 'I Love U', '我的宝贝!') elif self.cb2.isChecked(): QMessageBox.information(self, 'I Love U', '你是!') elif self.cb3.isChecked(): QMessageBox.information(self, 'I Love U', '我的!') elif self.cb4.isChecked(): QMessageBox.information(self, 'I Love U', '宝贝!') else: QMessageBox.information(self, 'I Love U', '貌似你没有勾选啊!') def changecb1(self): ''' 复选框cb1全选和反选 ''' if self.cb1.checkState() == Qt.Checked: self.cb2.setChecked(True) self.cb3.setChecked(True) self.cb4.setChecked(True) elif self.cb1.checkState() == Qt.Unchecked: self.cb2.setChecked(False) self.cb3.setChecked(False) self.cb4.setChecked(False) def changecb2(self): ''' 复选框cb2、cb3、cb4不同状态时,cb1状态的变化 ''' if self.cb2.isChecked() and self.cb3.isChecked( ) and self.cb4.isChecked(): self.cb1.setCheckState(Qt.Checked) #复选框cb2、cb3、cb4全选时,cb1状态是全选 elif self.cb2.isChecked() or self.cb3.isChecked( ) or self.cb4.isChecked(): self.cb1.setTristate(True) self.cb1.setCheckState( Qt.PartiallyChecked) #复选框cb2、cb3、cb4有一个被选中时,cb1状态是半选 else: self.cb1.setTristate(False) #必须设置否,否则cb1会出现半选状态。 self.cb1.setCheckState(Qt.Unchecked) #复选框cb2、cb3、cb4其他状态时,cb1状态是半选
def initUI(self): StoryTypeGroupBox = QGroupBox() StoryTypeLayer = FlowLayout() for key in WdStoryType.keys(): widget = QCheckBox(WdStoryType[key][1] if WdStoryType[key][1] != "" else WdStoryType[key][0]) widget.setObjectName("WdStoryType." + str(key)) widget.setCheckState(WdStoryType[key][2]) widget.setEnabled(widget.checkState() != 1) widget.setMinimumWidth(230) StoryTypeLayer.addWidget(widget) self.StoryTypeList.append(widget) StoryTypeGroupBox.setLayout(StoryTypeLayer) InlineShapeTypeGroupBox = QGroupBox() InlineShapeTypeLayer = FlowLayout() for key in WdInlineShapeType.keys(): widget = QCheckBox( WdInlineShapeType[key][1] if WdInlineShapeType[key][1] != "" else WdInlineShapeType[key][0] ) widget.setObjectName("WdInlineShapeType." + str(key)) widget.setCheckState(WdInlineShapeType[key][2]) widget.setEnabled(widget.checkState() != 1) widget.setMinimumWidth(230) InlineShapeTypeLayer.addWidget(widget) self.InlineShapeList.append(widget) InlineShapeTypeGroupBox.setLayout(InlineShapeTypeLayer) ShapeTypeGroupBox = QGroupBox() ShapeTypeLayer = FlowLayout() for key in MsoShapeType.keys(): widget = QCheckBox(MsoShapeType[key][1] if MsoShapeType[key][1] != "" else MsoShapeType[key][0]) widget.setObjectName("MsoShapeType." + str(key)) widget.setCheckState(MsoShapeType[key][2]) widget.setEnabled(widget.checkState() != 1) widget.setMinimumWidth(230) ShapeTypeLayer.addWidget(widget) self.ShapeTypeList.append(widget) ShapeTypeGroupBox.setLayout(ShapeTypeLayer) """TabWidget=QTabWidget() TabWidget.addTab(StoryTypeGroupBox,"StoryType") TabWidget.addTab(InlineShapeTypeGroupBox,"InlineShapeType") TabWidget.addTab(ShapeTypeGroupBox,"ShapeType") TabWidget.setCurrentIndex(0)""" TabWidget = QToolBox() TabWidget.addItem(StoryTypeGroupBox, "StoryType") TabWidget.addItem(InlineShapeTypeGroupBox, "InlineShapeType") TabWidget.addItem(ShapeTypeGroupBox, "ShapeType") TabWidget.setCurrentIndex(0) hbox = QVBoxLayout() hbox.addWidget(TabWidget) btnGrp = QDialogButtonBox() btnClose = QPushButton("Закрыть") # btnApply=QPushButton("Применить") btnGrp.addButton(btnClose, QDialogButtonBox.ActionRole) # btnGrp.addButton(btnApply,QDialogButtonBox.ActionRole) hbox.addWidget(btnGrp) btnClose.clicked.connect(self.close) # btnApply.clicked.connect(self.apply) self.apply() self.setLayout(hbox) self.setGeometry(500, 100, 500, 400) self.setWindowTitle("Опции") self.setWindowFlags(Qt.Dialog | Qt.WindowMinMaxButtonsHint | Qt.WindowCloseButtonHint)
class StartPos(QWidget): signal_modified = pyqtSignal(object) signal_selected_changed = pyqtSignal(object) signal_delete = pyqtSignal(object) all_selected = set() def __init__(self, x, y, w, *args, **kwargs): super(StartPos, self).__init__(*args, **kwargs) self.is_selected = False self.widget_show = QCheckBox(self) self.widget_x = QDoubleSpinBox(self) self.widget_y = QDoubleSpinBox(self) self.widget_w = QDoubleSpinBox(self) self.widgets = [ self.widget_show, self.widget_x, self.widget_y, self.widget_w ] # init chckbox show self.widget_show.setCheckState(Qt.Checked) # create editable fields for widget in self.widgets[1:]: widget.setDecimals(3) widget.setMinimum(-10000 if widget != self.widget_w else -np.pi) widget.setMaximum(10000 if widget != self.widget_w else np.pi) widget.setFrame(False) widget.setSingleStep(0.01) widget.setAlignment(Qt.AlignCenter) self.widget_x.setValue(x) self.widget_y.setValue(y) self.widget_w.setValue(w) # connect signals and slots self.widget_show.stateChanged.connect(self.object_changed) for widget in self.widgets[1:]: widget.valueChanged.connect(self.object_changed) def x(self): return self.widget_x.value() def y(self): return self.widget_y.value() def w(self): return self.widget_w.value() def translate(self, vector): self.widget_x.setValue(self.x() + vector.x()) self.widget_y.setValue(self.y() + vector.y()) self.object_changed() def setSelected(self, new_val: bool): # check if value changed if new_val != self.is_selected: # add or remove from selected set if new_val: StartPos.all_selected.add(self) elif self in StartPos.all_selected: StartPos.all_selected.remove(self) # set new value and signal self.is_selected = new_val self.signal_selected_changed.emit(self) def selected(self): return self.is_selected def is_hidden(self): return self.widget_show.checkState() == Qt.Unchecked def object_changed(self): self.signal_modified.emit(self) @staticmethod def clear_all_selected(): aux = StartPos.all_selected StartPos.all_selected = set() for pc in aux: pc.setSelected(False) def delete(self): if self in StartPos.all_selected: StartPos.all_selected.remove(self) self.signal_delete.emit(self) def xml_tag(self): return f'<pos x="{self.x()}" y="{self.y()}" w="{self.w()}" />' def __str__(self): return f'{self.x():9.3f}, {self.y():9.3f}, {self.w():9.3f}' @staticmethod def fromstring(s): args = np.fromstring(s.replace('[', '').replace(']', ''), sep=",") if len(args) == 3: return StartPos(args[0], args[1], args[2]) else: print('PC parse error') return None def pickable(self): return PickableStartPos(self.x(), self.y(), self.w()) def __eq__(self, pos): return abs(self.x() - pos.x()) < 0.001 and abs(self.y() - pos.y()) < 0.001 __hash__ = QWidget.__hash__
class dig_edit_conversation(QWidget): # 編輯對話 def __init__(self): super().__init__() self.initUI() def initUI(self): client = MongoClient("127.0.0.1", 27017) db = client.gossip self.collection = db.sentences self.main_layout = QVBoxLayout() situation_widget = QFormLayout() self.select_layout = QHBoxLayout() self.search_text = QLineEdit() self.search_text.textChanged.connect(self.search_situations) self.tableWidget = QTableWidget() self.tableWidget.setRowCount(self.collection.find().count()) self.tableWidget.setColumnCount(1) self.tableWidget.itemSelectionChanged.connect(self.show_selected_item) self.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers) self.tableWidget.setSelectionMode(QAbstractItemView.SingleSelection) self.tableWidget.verticalHeader().setVisible(False) self.tableWidget.horizontalHeader().setVisible(False) self.tableWidget2 = QTableWidget() self.tableWidget2.setColumnCount(1) self.tableWidget2.itemSelectionChanged.connect(self.show_selected_sentence) self.tableWidget2.setEditTriggers(QAbstractItemView.NoEditTriggers) self.tableWidget2.setSelectionMode(QAbstractItemView.SingleSelection) self.tableWidget2.verticalHeader().setVisible(False) self.tableWidget2.horizontalHeader().setVisible(False) self.situation_index_list = [] self.sentence_index_list = [] self.search_situations() self.tableWidget2.setColumnWidth(0,500) self.tableWidget.resizeColumnsToContents() self.new_or_not = QCheckBox('新增情境') self.new_or_not.stateChanged.connect(self.state_changed) self.remove_btn = QPushButton('刪除情境') self.remove_btn.clicked.connect(self.remove_btn_method) self.select_layout.addWidget(self.search_text) self.select_layout.addWidget(self.new_or_not) self.select_layout.addWidget(self.remove_btn) self.name = QTextEdit() self.sentence = QTextEdit() situation_widget.addRow(QLabel('搜尋'), self.select_layout) situation_widget.addRow(QLabel('欲編輯情境'), self.tableWidget) situation_widget.addRow(QLabel('情境所有語句'), self.tableWidget2) situation_widget.addRow(QLabel('說話者'), self.name) situation_widget.addRow(QLabel('對話語句'), self.sentence) button_layout = QHBoxLayout() save_btn = QPushButton("儲存") save_btn.clicked.connect(self.save_btn_method) cancel_btn = QPushButton("取消") cancel_btn.clicked.connect(self.cancel_btn_method) button_layout.addWidget(save_btn) button_layout.addWidget(cancel_btn) self.main_layout.addLayout(situation_widget) self.main_layout.addLayout(button_layout) self.setLayout(self.main_layout) # 好像有BUG,會拿到下一句 @pyqtSlot() def show_selected_item(self): self.tableWidget2.clear() self.sentence_index_list.clear() if len(self.situation_index_list) > 0: print(self.tableWidget.currentIndex().row()) data = self.collection.find({'Situation': self.situation_index_list[ min(self.tableWidget.currentIndex().row(), len(self.situation_index_list) - 1)]}) self.tableWidget2.setRowCount(data.count()) if data != None: for index, item in enumerate(data): self.tableWidget2.setItem(index, 0, QTableWidgetItem(str(item['Sentence']))) self.sentence_index_list.append(item['Sentence']) else: pass @pyqtSlot() def show_selected_sentence(self): if len(self.sentence_index_list) > 0: print(self.tableWidget.currentItem().text()) data = self.collection.find_one({'Sentence': self.sentence_index_list[ min(self.tableWidget2.currentIndex().row(), len(self.sentence_index_list) - 1)]}) if data != None: self.name.setText(str(data['Name'])) self.sentence.setText(data['Sentence']) else: pass @pyqtSlot() def search_situations(self): self.tableWidget.clear() self.situation_index_list.clear() if not self.search_text.text() == '': search_condition = [{'Situation': {'$regex': '{0}'.format(word)}} for word in self.search_text.text().split()] search = list(self.collection.find({'$and': search_condition})) search = sorted(set([x['Situation'] for x in search])) self.tableWidget.setRowCount(len(search)) for index, item in enumerate(search): self.tableWidget.setItem(index, 0, QTableWidgetItem(str(item))) self.situation_index_list.append(item) else: search = list(self.collection.find({'Name':''})) search = sorted(set([x['Situation'] for x in search])) self.tableWidget.setRowCount(len(search)) for index, item in enumerate(search): self.tableWidget.setItem(index, 0, QTableWidgetItem(str(item))) self.situation_index_list.append(item) # finished @pyqtSlot() def state_changed(self): self.name.clear() self.sentence.clear() if self.new_or_not.checkState(): self.tableWidget.setDisabled(True) self.tableWidget2.setDisabled(True) else: self.tableWidget.setDisabled(False) self.tableWidget2.setDisabled(False) # 清除最後一個好像有BUG # 已解決: 最後一個被刪除後會留下一個空的string @pyqtSlot() def remove_btn_method(self): if self.tableWidget2.currentItem() is not None: if self.new_or_not.checkState(): QMessageBox.information(self, "提醒", '請先勾去"新增情境"') elif len(self.sentence_index_list) > 0: result = QMessageBox.question(self, '警告', '確定要刪除"{0}"嗎?'.format(self.tableWidget2.currentItem().text()), QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if result == QMessageBox.Yes: data = self.sentence_index_list[self.tableWidget2.currentIndex().row()] self.collection.remove({'Sentence': data}) del self.sentence_index_list[self.tableWidget2.currentIndex().row()] if self.tableWidget2.rowCount() == 1: self.tableWidget2.setItem(0, 0, QTableWidgetItem('')) else: self.tableWidget2.removeRow(self.tableWidget2.currentIndex().row()) else: pass else: pass else: pass # finished @pyqtSlot() def save_btn_method(self): if self.new_or_not.checkState(): data = {'uuid': self.collection.find().count(), 'Situation': self.tableWidget.currentItem().text(), 'Sentence': self.sentence.toPlainText(), 'Name': self.name.toPlainText() } self.collection.insert(data) self.sentence_index_list.append(data['Sentence']) self.tableWidget2.insertRow(self.tableWidget2.rowCount()) self.tableWidget2.setItem(self.tableWidget2.rowCount() - 1, 0, QTableWidgetItem(str(data['Sentence']))) QMessageBox.information(self, "提醒", '已儲存"{}"'.format(self.sentence.toPlainText())) elif len(self.sentence_index_list) > 0: data = self.collection.find_one({'Sentence': self.sentence_index_list[self.tableWidget2.currentIndex().row()]}) data['Name'] = self.name.toPlainText() data['Sentence'] = self.sentence.toPlainText().split('\n') self.collection.save(data) self.tableWidget2.setItem(self.tableWidget2.currentIndex().row(), 0, QTableWidgetItem(str(data['Sentence']))) QMessageBox.information(self, "提醒", '已儲存"{}"'.format(self.sentence.toPlainText())) else: pass @pyqtSlot() def cancel_btn_method(self): self.search_text.clear() self.name.clear() self.sentence.clear()
class MainWindow(QMainWindow): def __init__(self): super().__init__() self.button_map = dict() self.initUI() def initUI(self): #Menu Bar action_open = QAction('&Open', self) action_open.setShortcut('Ctrl+O') action_open.setStatusTip('Open') action_open.triggered.connect(self.openFile) action_quit = QAction('&Exit', self) action_quit.setShortcut('Ctrl+Q') action_quit.setStatusTip('Exit application') action_quit.triggered.connect(qApp.quit) action_show_log_window = QAction('&Log', self) action_show_log_window.setShortcut('Ctrl+L') action_show_log_window.setStatusTip('Open Log Window') action_show_log_window.triggered.connect(self.openLogWindow) action_show_help_window = QAction('&Help', self) action_show_help_window.setShortcut('Ctrl+H') action_show_help_window.setStatusTip('Open Help Window') action_show_help_window.triggered.connect(self.openHelpWindow) menubar = self.menuBar() fileMenu = menubar.addMenu('&File') viewMenu = menubar.addMenu('&View') helpMenu = menubar.addMenu('&Help') fileMenu.addAction(action_open) fileMenu.addAction(action_quit) viewMenu.addAction(action_show_log_window) helpMenu.addAction(action_show_help_window) #Widgets self.input_filename_label = QLabel('Input Filename') self.input_filename = QLineEdit() self.input_filename.setText("") self.output_filename_label = QLabel('Output Filename') self.output_filename = QLineEdit() self.output_filename.setText("") self.filter_label = QLabel('Filter') self.filter = QLineEdit() self.filter.setText("< AUTO >") self.modify_label = QLabel('Modify') self.modify = QLineEdit() self.modify.setText("< AUTO >") self.type_label = QLabel('Type') self.type = QComboBox() self.type.addItem("AUTO") self.type.addItem("IP") self.type.addItem("MAC") self.type.addItem("VLAN") self.type.currentIndexChanged.connect(self.comboBoxChange) self.payload_label = QLabel('Check Payload') self.payload = QCheckBox() self.button_run = QPushButton('Run', self) self.button_run.resize(self.button_run.sizeHint()) self.button_run.clicked.connect(self.buttonHandler) self.button_map[self.button_run] = "run" self.grid = QGridLayout() self.grid.setSpacing(10) self.grid.addWidget(self.input_filename_label, 0, 0, 1, 1) self.grid.addWidget(self.input_filename, 0, 1, 1, 3) self.grid.addWidget(self.output_filename_label, 1, 0, 1, 1) self.grid.addWidget(self.output_filename, 1, 1, 1, 3) self.grid.addWidget(self.filter_label, 2, 0, 1, 1) self.grid.addWidget(self.filter, 2, 1, 1, 3) self.grid.addWidget(self.modify_label, 3, 0, 1, 1) self.grid.addWidget(self.modify, 3, 1, 1, 3) self.grid.addWidget(self.type_label, 4, 0, 1, 1) self.grid.addWidget(self.type, 4, 1, 1, 1) self.grid.addWidget(self.payload_label, 5, 0, 1, 1) self.grid.addWidget(self.payload, 5, 1, 1, 1) self.grid.addWidget(self.button_run, 5, 3, 1, 1) self.central_widget = QWidget() self.central_widget.setLayout(self.grid) #MainWindow self.setCentralWidget(self.central_widget) self.setGeometry(300, 300, 400, 250) self.setWindowTitle('PCAP Obfuscator') self.setWindowIcon(QIcon('LisboaAppsIcon.png')) self.show() #LogWindow self.log_window = LogWindow() #HelpWindow self.help_window = HelpWindow() def buttonHandler(self): action = self.button_map[self.sender()] if action == "run": error, log = pcap_obfuscator(self.input_filename.text(), self.output_filename.text(), self.filter.text(), self.modify.text(), self.type.currentText(), self.payload.checkState()) self.log_window.log(log) if error == None: msg = QMessageBox() msg.setIcon(QMessageBox.Information) msg.setText("PCAP obfuscation complete!") msg.setInformativeText(self.output_filename.text() + " created.") msg.setWindowTitle("PCAP Obfuscator") msg.setStandardButtons(QMessageBox.Ok) msg.exec_() else: msg = QMessageBox() msg.setIcon(QMessageBox.Warning) msg.setText("An error occurred.") msg.setInformativeText(error) msg.setWindowTitle("PCAP Obfuscator") msg.setStandardButtons(QMessageBox.Ok) msg.exec_() def comboBoxChange(self): if self.type.currentText() == "IP": self.filter.setText("*.*.*.*") self.modify.setText("") elif self.type.currentText() == "MAC": self.filter.setText("*:*:*:*:*:*") self.modify.setText("") elif self.type.currentText() == "VLAN": self.filter.setText("") self.modify.setText("") elif self.type.currentText() == "AUTO": self.filter.setText("< AUTO >") self.modify.setText("< AUTO >") def openFile(self, *filename): options = QFileDialog.Options() self.open_filename, _ = QFileDialog.getOpenFileName( self, "Open PCAP File", "", "PCAP Files (*.pcap);;All Files (*)", options=options) self.input_filename.setText(self.open_filename) self.output_filename.setText( self.open_filename.rsplit('/', 1)[0] + "/obfuscated.pcap") def openLogWindow(self): self.log_window.show() def openHelpWindow(self): self.help_window.show() def closeEvent(self, event): reply = QMessageBox.question(self, 'Message', "Are you sure to quit?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: self.log_window.close() self.help_window.close() event.accept() else: event.ignore()
class dig_sentence_log(QWidget): # 回答紀錄 def __init__(self): super().__init__() self.initUI() def initUI(self): client = MongoClient('localhost', 27017) db = client.gossip self.collection_log = db.logs self.collection_sen = db.sentences self.main_layout = QVBoxLayout() sentence_widget = QFormLayout() self.select_layout = QHBoxLayout() self.show_all_sentences = QCheckBox('顯示所有紀錄') self.show_all_sentences.stateChanged.connect(self.state_changed) self.sentences_id = [] self.search_text = QLineEdit() self.search_text.textChanged.connect(self.search_sentences) self.tableWidget = QTableWidget() self.tableWidget.setRowCount(self.collection_log.find().count()) self.tableWidget.setColumnCount(1) self.tableWidget.itemSelectionChanged.connect(self.show_selected_item) self.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers) self.tableWidget.setSelectionMode(QAbstractItemView.SingleSelection) self.tableWidget.verticalHeader().setVisible(False) self.tableWidget.horizontalHeader().setVisible(False) self.sentence_index_list = [] self.search_sentences() self.tableWidget.resizeColumnsToContents() self.remove_btn = QPushButton('刪除紀錄') self.remove_btn.clicked.connect(self.remove_btn_method) self.select_layout.addWidget(self.search_text) self.select_layout.addWidget(self.show_all_sentences) self.select_layout.addWidget(self.remove_btn) temp = self.collection_log.find_one() self.sentence = QTextEdit() self.name = '' self.events = QTextEdit() if temp is not None: self.sentence.setText(str(temp['Sentence'])) self.name = temp['Name'] self.events.setText('、'.join([x['Action'] for x in temp['Actions']])) self.situation = QTextEdit() sentence_widget.addRow(QLabel('搜尋'), self.select_layout) sentence_widget.addRow(QLabel('對話紀錄'), self.tableWidget) sentence_widget.addRow(QLabel('對話'), self.sentence) sentence_widget.addRow(QLabel('連續事件'), self.events) sentence_widget.addRow(QLabel('情境'), self.situation) button_layout = QHBoxLayout() save_btn = QPushButton("儲存") save_btn.clicked.connect(self.save_btn_method) cancel_btn = QPushButton("取消") cancel_btn.clicked.connect(self.cancel_btn_method) button_layout.addWidget(save_btn) button_layout.addWidget(cancel_btn) self.main_layout.addLayout(sentence_widget) self.main_layout.addLayout(button_layout) self.setLayout(self.main_layout) @pyqtSlot() def search_sentences(self): self.tableWidget.clear() self.sentence_index_list.clear() search_condition = [] if not self.search_text.text() == '': search_condition += [{'Sentence': {'$regex': '{0}'.format(word)}} for word in self.search_text.text().split()] if len(search_condition): search = self.collection_log.find({'$and': search_condition}) else: search = self.collection_log.find() self.tableWidget.setRowCount(search.count()) for index, item in enumerate(search): self.tableWidget.setItem(index, 0, QTableWidgetItem(str(item['Sentence']))) self.sentence_index_list.append(item['_id']) @pyqtSlot() def load_sentence(self): for _ in range(len(self.sentences_id)): self.log_list.removeItem(0) self.sentences_id = [] if self.show_all_sentences.checkState(): for row in self.collection_log.find(): self.sentences_id.append(row['_id']) self.log_list.addItem(str(row['Sentence'])) if self.log_list.count() > len(self.sentences_id): if len(self.sentences_id) > 0: self.log_list.removeItem(0) else: for row in self.collection_log.find(): self.sentences_id.append(row['_id']) self.log_list.addItem(str(row['Sentence'])) @pyqtSlot() def show_selected_item(self): if len(self.sentence_index_list) > 0: data = self.collection_log.find_one({'_id': self.sentence_index_list[ min(self.tableWidget.currentIndex().row(), len(self.sentence_index_list) - 1)]}) if data != None: self.sentence.setText(str(data['Sentence'])) self.events.setText('、'.join([x['Action'] for x in data['Actions']])) self.name = data['Name'] else: pass @pyqtSlot() def state_changed(self): self.sentence.clear() self.events.clear() self.search_sentences() @pyqtSlot() def remove_btn_method(self): if self.tableWidget.currentItem() is not None: if len(self.sentence_index_list) > 0: result = QMessageBox.question(self, '警告', '確定要刪除"{0}"嗎?'.format(self.tableWidget.currentItem().text()), QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if result == QMessageBox.Yes: current_index = self.sentence_index_list[self.tableWidget.currentIndex().row()] self.collection_log.remove({'_id': current_index}) del self.sentence_index_list[self.tableWidget.currentIndex().row()] if self.tableWidget.rowCount() == 1: self.tableWidget.setItem(0, 0, QTableWidgetItem('')) else: self.tableWidget.removeRow(self.tableWidget.currentIndex().row()) else: pass else: QMessageBox.information(self, '警告', '目前沒有句子') else: pass def remove_item_from_table(self): current_index = self.sentence_index_list[self.tableWidget.currentIndex().row()] self.collection_log.remove({'_id': current_index}) del self.sentence_index_list[self.tableWidget.currentIndex().row()] if self.tableWidget.rowCount() == 1: self.tableWidget.setItem(0, 0, QTableWidgetItem('')) else: self.tableWidget.removeRow(self.tableWidget.currentIndex().row()) @pyqtSlot() def save_btn_method(self): if len(self.sentence_index_list) > 0: temp = self.collection_sen.find_one() if temp is not None: temp['Sentence'].append(self.sentence.toPlainText()) self.collection_sen.save(temp) else: data = {'uuid': self.collection_ori.find().count(), 'Sentence': self.sentence.toPlainText(), 'Situation': self.situation.toPlainText(), 'Name': self.name } self.collection_sen.insert(data) QMessageBox.information(self, '提醒', '已儲存"{}"'.format(self.sentence.toPlainText())) self.remove_item_from_table() else: QMessageBox.information(self, '警告', '目前沒有句子') @pyqtSlot() def cancel_btn_method(self): data = self.collection_log.find_one({'_id': self.sentence_index_list[self.tableWidget.currentIndex().row()]}) self.sentence.setText(str(data['Sentence'])) self.events.setText('、'.join([x['Action'] for x in temp['Actions']]))
class Example(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): #-----------Creation--------------------------------------------- #label labelStroka = QLabel('Строка: ') labelResult = QLabel('Результат: ') #lineEdit self.lineEditInput = QLineEdit() self.lineEditResult = QLineEdit() self.input_ = self.lineEditInput.text() self.output_ = self.lineEditResult.text() #chekbox self.checkbox1 = QCheckBox('Удалить слова размером меньше n символов, n = ') self.checkbox2 = QCheckBox('Заменить все цифры на *') self.checkbox3 = QCheckBox('Вставить по пробелу между символами') self.checkbox4 = QCheckBox('Сортировать слова в строке') #QSpinBox self.spinBox1 = QSpinBox() #QPushButton buttonFormat = QPushButton('Форматировать!',self) #QRadioButton self.radio1 = QRadioButton('По размеру') self.radio1.setChecked(True) self.radio2 = QRadioButton('Лексиграфически') #---------------Position----------------------------- grid = QGridLayout() grid.setSpacing(10) #label grid.addWidget(labelStroka,1,0) grid.addWidget(labelResult,9,0) #lineEdit grid.addWidget(self.lineEditInput,1,1) grid.addWidget(self.lineEditResult,9,1) #chekbox grid.addWidget(self.checkbox1,2,1) grid.addWidget(self.checkbox2,3,1) grid.addWidget(self.checkbox3,4,1) grid.addWidget(self.checkbox4,5,1) #QPushButton grid.addWidget(buttonFormat,8,1) #QSpinBox grid.addWidget(self.spinBox1,2,2) #QRadioButton grid.addWidget(self.radio1,6,1) grid.addWidget(self.radio2,7,1) #--------------------------------------------------------- #---------Event Magic------------------------------------ buttonFormat.clicked.connect(self.buttonClicked) #--------------------------------------------------------- self.setLayout(grid) self.setGeometry(300, 300, 350, 300) self.setWindowTitle('Review') self.show() def keyPressEvent(self, e): if e.key() == Qt.Key_Escape: self.close def buttonClicked(self): #---on button click starts formatting------ self.input_ = '' self.output_ = '' self.input_ = self.lineEditInput.text() self.output_ = self.input_ tempArr = [] #------------------------------------------ #--------1st checkbox---------------------- if (self.checkbox1.checkState()==2): n = self.spinBox1.value() splitInputArr = self.input_.split(' ') for i in range(len(splitInputArr)): if len(splitInputArr[i])>=n: tempArr.append(splitInputArr[i]) self.output_ = ' '.join(tempArr) self.lineEditResult.setText(self.output_) #--------2nd checkbox---------------------- if (self.checkbox2.checkState()==2): self.output_ = re.sub('\d','*',self.output_) self.lineEditResult.setText(self.output_) #--------3rd checkbox---------------------- if (self.checkbox3.checkState()==2): #tempSubArr = list(self.output_) self.output_ = ' '.join(list(self.output_)) self.lineEditResult.setText(self.output_) #--------4th checkbox---------------------- if (self.checkbox4.checkState()==2) and (self.radio1.isChecked): #Size tempSplit = self.output_.split() tempSplit.sort(key=len) for i in range(len(tempSplit)): self.output_ = ' '.join(tempSplit) self.lineEditResult.setText(self.output_) if (self.checkbox4.checkState()==2) and (self.radio2.isChecked): #Lex tempSplit = self.output_.split() tempSplit.sort() for i in range(len(tempSplit)): self.output_ = ' '.join(tempSplit) self.lineEditResult.setText(self.output_) #----------Output-------------------------- if ((self.checkbox1.checkState() == 0) and (self.checkbox2.checkState()==0) and (self.checkbox3.checkState()==0) and (self.checkbox4.checkState()==0)): self.output_ = self.input_ self.lineEditResult.setText(self.output_) #------------------------------------------ self.lineEditResult.setText(self.output_)
class OperatingTimeWindow(QMainWindow): def setupUI(self, mui): self.initUI(mui) self.mainUI(mui) self.configUI(mui) self.thresholdUI(mui) self.timeUI() self.timeFigureUI(mui) self.activetiyDetailUI(mui) self.draw_figure() ## value self.cycle_counter = 0 def initUI(self, mui): self.gb_config = QGroupBox() self.gb_oprTime = QGroupBox() mui.gb_setThreshold = QGroupBox() self.gb_figTime = QGroupBox() self.gb_actDetail = QGroupBox() def mainUI(self, mui): self.setWindowTitle('Operating Time Calclation') self.setGeometry(1200, 50, 0, 0) main_frame = QWidget() sw_optForm = QStackedWidget() sw_optForm.addWidget(mui.gb_setThreshold) sw_optForm.addWidget(self.gb_figTime) sw_optForm.addWidget(self.gb_actDetail) combo_optForm = QComboBox() combo_optForm.addItem('1: Setting Threshold') combo_optForm.addItem('2: Operating Time Graph') combo_optForm.addItem('3: Activity Details') combo_optForm.currentIndexChanged.connect(sw_optForm.setCurrentIndex) vbox_main = QVBoxLayout() vbox_main.addWidget(self.gb_config) vbox_main.addWidget(self.gb_oprTime) vbox_main.addWidget(combo_optForm) vbox_main.addWidget(sw_optForm) main_frame.setLayout(vbox_main) self.setCentralWidget(main_frame) def configUI(self, mui): btn_readConfig = QPushButton('Read') btn_readConfig.clicked.connect(lambda: self.readConfig(mui)) self.le_readConfig = QLineEdit() btn_saveConfig = QPushButton('Save') btn_saveConfig.clicked.connect(lambda: self.saveConfig(mui)) self.le_saveConfig = QLineEdit() ### -1- hbox1 = QHBoxLayout() hbox1.addWidget(btn_readConfig) hbox1.addWidget(self.le_readConfig) ### -2- hbox2 = QHBoxLayout() hbox2.addWidget(btn_saveConfig) hbox2.addWidget(self.le_saveConfig) ### |-1-2-| vbox_gb_config = QVBoxLayout() vbox_gb_config.addLayout(hbox1) vbox_gb_config.addLayout(hbox2) self.gb_config.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Maximum) self.gb_config.setTitle("Config File") self.gb_config.setLayout(vbox_gb_config) def timeUI(self): ### Add Element stdOprTimeTextLabel = QLabel() stdOprTimeTextLabel.setText('Standard :') self.stdOprTimeSb = QDoubleSpinBox() self.stdOprTimeSb.setSingleStep(0.01) self.stdOprTimeSb.setSuffix(" [sec]") self.stdOprTimeSb.setValue(3.0) calcOprTimeTextLabel = QLabel() calcOprTimeTextLabel.setText('Calculation :') self.calcOprTimeLabel = QLabel() self.calcOprTimeLabel.setText('0.000') extTimeLabel = QLabel() extTimeLabel.setText("[sec]") self.fpsSb = QSpinBox() self.fpsSb.setValue(30) self.fpsSb.setPrefix("fps: ") self.fpsSb.setRange(1, 150) differenceTimeTextLabel = QLabel() differenceTimeTextLabel.setText('Difference :') self.differenceTimeLabel = QLabel() self.differenceTimeLabel.setText('x.xxx') self.cb_alarm = QCheckBox('Alarm Threshold:') self.dsb_alarmRange = QDoubleSpinBox() self.dsb_alarmRange.setRange(0, 10) self.dsb_alarmRange.setValue(3.0) self.dsb_alarmRange.setSingleStep(0.1) self.dsb_alarmRange.setSuffix(' [sec]') self.cb_saveOprTime = QCheckBox('Save:') self.le_filepath = QLineEdit() self.le_filepath.setText("CSV File") self.btn_save_fd = QPushButton('...') self.btn_save_fd.clicked.connect(self.setSaveTimeFilePath) self.btn_save_fd.setFixedWidth(30) ### -1- hbox1 = QHBoxLayout() hbox1.addWidget(stdOprTimeTextLabel) hbox1.addWidget(self.stdOprTimeSb) hbox1.addStretch(1) ### -2- hbox2 = QHBoxLayout() hbox2.addWidget(calcOprTimeTextLabel) hbox2.addWidget(self.calcOprTimeLabel) hbox2.addWidget(extTimeLabel) hbox2.addWidget(self.fpsSb) hbox2.addStretch(1) ### -3- hbox3 = QHBoxLayout() hbox3.addWidget(differenceTimeTextLabel) hbox3.addWidget(self.differenceTimeLabel) hbox3.addStretch(1) hbox3.addWidget(self.cb_alarm) hbox3.addWidget(self.dsb_alarmRange) ### -4- hbox4 = QHBoxLayout() hbox4.addWidget(self.cb_saveOprTime) hbox4.addWidget(self.le_filepath) hbox4.addWidget(self.btn_save_fd) ### |-1-2-3-4-| vbox_gb_oprTime = QVBoxLayout() vbox_gb_oprTime.addLayout(hbox1) vbox_gb_oprTime.addLayout(hbox2) vbox_gb_oprTime.addLayout(hbox3) vbox_gb_oprTime.addLayout(hbox4) self.gb_oprTime.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Maximum) self.gb_oprTime.setTitle("Operating Time") self.gb_oprTime.setLayout(vbox_gb_oprTime) def activetiyDetailUI(self, mui): series = QPieSeries() chart = QChart() chart.addSeries(series) #chart.setTitle("Activity Details") #chart.legend().hide() self.chartView = QChartView() self.chartView.setChart(chart) self.chartView.setRenderHint(QPainter.Antialiasing) self.chartView.setMinimumWidth(350) vbox_gb_actDetail = QVBoxLayout() vbox_gb_actDetail.addWidget(self.chartView) self.gb_actDetail.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Maximum) self.gb_actDetail.setLayout(vbox_gb_actDetail) def timeFigureUI(self, mui): fig = Figure((10, 5), dpi=100) self.canvas_time = FigureCanvas(fig) self.axes = fig.add_subplot(111) self.axes.clear() self.x_cycle = deque([]) self.y_time = deque([]) self.axes.bar(self.x_cycle, self.y_time) self.cb_registrationTime = QCheckBox('Registration') self.btn_initGraph = QPushButton('Init') self.btn_initGraph.clicked.connect(self.clearGraph) lbl_maxCount = QLabel('Num:') self.sb_maxCount = QSpinBox() self.sb_maxCount.setRange(1, 50) self.sb_maxCount.setValue(10) lbl_maxValue = QLabel('Val:') self.sb_maxValue = QSpinBox() self.sb_maxValue.setRange(1, 50) self.sb_maxValue.setValue(5) lbl_mean = QLabel('Mean:') self.le_mean = QLineEdit('') lbl_variance = QLabel('Variance:') self.le_variance = QLineEdit('') ### -1- hbox1 = QHBoxLayout() hbox1.addWidget(self.cb_registrationTime) hbox1.addStretch(1) hbox1.addWidget(lbl_maxCount) hbox1.addWidget(self.sb_maxCount) hbox1.addStretch(1) hbox1.addWidget(self.btn_initGraph) ### -2- hbox2 = QHBoxLayout() hbox2.addWidget(lbl_maxValue) hbox2.addWidget(self.sb_maxValue) hbox2.addWidget(lbl_mean) hbox2.addWidget(self.le_mean) hbox2.addWidget(lbl_variance) hbox2.addWidget(self.le_variance) ### |-1-2-| vbox_gb_figTime = QVBoxLayout() vbox_gb_figTime.addLayout(hbox1) vbox_gb_figTime.addWidget(self.canvas_time) vbox_gb_figTime.addLayout(hbox2) self.gb_figTime.setMinimumHeight(350) self.gb_figTime.setLayout(vbox_gb_figTime) def thresholdUI(self, mui): ### Add Element mui.cb_thX1_on = QCheckBox("X1") mui.cb_thX2_on = QCheckBox("X2") mui.cb_thY1_on = QCheckBox("Y1") mui.cb_thY2_on = QCheckBox("Y2") mui.cb_thZ1_on = QCheckBox("Z1") mui.cb_thZ2_on = QCheckBox("Z2") ## X mui.sld_thX1 = QSlider(Qt.Vertical) mui.sld_thX1.setRange(-50, 50) mui.sld_thX1.setValue(0) mui.sb_thX1 = QSpinBox() mui.sb_thX1.setRange(-50, 50) mui.sb_thX1.setValue(mui.sld_thX1.value()) mui.sb_thX1.valueChanged.connect(mui.setSliderThresholdParameter) mui.sld_thX1.valueChanged.connect(mui.setSpinBoxGraphParameter) mui.sld_thX1.valueChanged.connect(mui.refreshGraphSlider) mui.sb_thX1Variance = QSpinBox() mui.sb_thX1Variance.setRange(0, 1000) mui.sb_thX1Variance.valueChanged.connect(mui.refreshGraphSpinBox) mui.sld_thX2 = QSlider(Qt.Vertical) mui.sld_thX2.setRange(-50, 50) mui.sld_thX2.setValue(0) mui.sb_thX2 = QSpinBox() mui.sb_thX2.setRange(-50, 50) mui.sb_thX2.setValue(mui.sld_thX1.value()) mui.sb_thX2.valueChanged.connect(mui.setSliderThresholdParameter) mui.sld_thX2.valueChanged.connect(mui.setSpinBoxGraphParameter) mui.sld_thX2.valueChanged.connect(mui.refreshGraphSlider) mui.sb_thX2Variance = QSpinBox() mui.sb_thX2Variance.setRange(0, 1000) mui.sb_thX2Variance.valueChanged.connect(mui.refreshGraphSpinBox) ## Y mui.sld_thY1 = QSlider(Qt.Vertical) mui.sld_thY1.setRange(-50, 50) mui.sld_thY1.setValue(0) mui.sb_thY1 = QSpinBox() mui.sb_thY1.setRange(-50, 50) mui.sb_thY1.setValue(mui.sld_thY1.value()) mui.sb_thY1.valueChanged.connect(mui.setSliderThresholdParameter) mui.sld_thY1.valueChanged.connect(mui.setSpinBoxGraphParameter) mui.sld_thY1.valueChanged.connect(mui.refreshGraphSlider) mui.sb_thY1Variance = QSpinBox() mui.sb_thY1Variance.setRange(0, 1000) mui.sb_thY1Variance.valueChanged.connect(mui.refreshGraphSpinBox) mui.sld_thY2 = QSlider(Qt.Vertical) mui.sld_thY2.setRange(-50, 50) mui.sld_thY2.setValue(0) mui.sb_thY2 = QSpinBox() mui.sb_thY2.setRange(-50, 50) mui.sb_thY2.setValue(mui.sld_thY1.value()) mui.sb_thY2.valueChanged.connect(mui.setSliderThresholdParameter) mui.sld_thY2.valueChanged.connect(mui.setSpinBoxGraphParameter) mui.sld_thY2.valueChanged.connect(mui.refreshGraphSlider) mui.sb_thY2Variance = QSpinBox() mui.sb_thY2Variance.setRange(0, 1000) mui.sb_thY2Variance.valueChanged.connect(mui.refreshGraphSpinBox) ##Z mui.sld_thZ1 = QSlider(Qt.Vertical) mui.sld_thZ1.setRange(-50, 50) mui.sld_thZ1.setValue(0) mui.sb_thZ1 = QSpinBox() mui.sb_thZ1.setRange(-50, 50) mui.sb_thZ1.setValue(mui.sld_thZ1.value()) mui.sb_thZ1.valueChanged.connect(mui.setSliderThresholdParameter) mui.sld_thZ1.valueChanged.connect(mui.setSpinBoxGraphParameter) mui.sld_thZ1.valueChanged.connect(mui.refreshGraphSlider) mui.sb_thZ1Variance = QSpinBox() mui.sb_thZ1Variance.setRange(0, 1000) mui.sb_thZ1Variance.valueChanged.connect(mui.refreshGraphSpinBox) mui.sld_thZ2 = QSlider(Qt.Vertical) mui.sld_thZ2.setRange(-50, 50) mui.sld_thZ2.setValue(0) mui.sb_thZ2 = QSpinBox() mui.sb_thZ2.setRange(-50, 50) mui.sb_thZ2.setValue(mui.sld_thZ2.value()) mui.sb_thZ2.valueChanged.connect(mui.setSliderThresholdParameter) mui.sld_thZ2.valueChanged.connect(mui.setSpinBoxGraphParameter) mui.sld_thZ2.valueChanged.connect(mui.refreshGraphSlider) mui.sb_thZ2Variance = QSpinBox() mui.sb_thZ2Variance.setRange(0, 1000) mui.sb_thZ2Variance.valueChanged.connect(mui.refreshGraphSpinBox) # lbl_scaleX = QLabel('scale X:') lbl_scaleY = QLabel('scale Y:') lbl_scaleZ = QLabel('scale Z:') mui.sb_thX_scale = QDoubleSpinBox() mui.sb_thX_scale.setRange(0.01, 100) mui.sb_thX_scale.setValue(0.05) mui.sb_thX_scale.setSingleStep(0.01) mui.sb_thY_scale = QDoubleSpinBox() mui.sb_thY_scale.setRange(0.01, 100) mui.sb_thY_scale.setValue(0.05) mui.sb_thY_scale.setSingleStep(0.01) mui.sb_thZ_scale = QDoubleSpinBox() mui.sb_thZ_scale.setRange(0.01, 100) mui.sb_thZ_scale.setValue(0.05) mui.sb_thZ_scale.setSingleStep(0.01) ### -1- hbox1 = QHBoxLayout() hbox1.addWidget(lbl_scaleX) hbox1.addWidget(mui.sb_thX_scale) hbox1.addWidget(lbl_scaleY) hbox1.addWidget(mui.sb_thY_scale) hbox1.addWidget(lbl_scaleZ) hbox1.addWidget(mui.sb_thZ_scale) ### |1| vbox1 = QVBoxLayout() vbox1.addWidget(mui.cb_thX1_on) vbox1.addWidget(mui.sb_thX1) vbox1.addWidget(mui.sld_thX1) vbox1.addWidget(mui.sb_thX1Variance) vbox1_2 = QVBoxLayout() vbox1_2.addWidget(mui.cb_thX2_on) vbox1_2.addWidget(mui.sb_thX2) vbox1_2.addWidget(mui.sld_thX2) vbox1_2.addWidget(mui.sb_thX2Variance) ### |2| vbox2 = QVBoxLayout() vbox2.addWidget(mui.cb_thY1_on) vbox2.addWidget(mui.sb_thY1) vbox2.addWidget(mui.sld_thY1) vbox2.addWidget(mui.sb_thY1Variance) vbox2_2 = QVBoxLayout() vbox2_2.addWidget(mui.cb_thY2_on) vbox2_2.addWidget(mui.sb_thY2) vbox2_2.addWidget(mui.sld_thY2) vbox2_2.addWidget(mui.sb_thY2Variance) ### |3| vbox3 = QVBoxLayout() vbox3.addWidget(mui.cb_thZ1_on) vbox3.addWidget(mui.sb_thZ1) vbox3.addWidget(mui.sld_thZ1) vbox3.addWidget(mui.sb_thZ1Variance) vbox3_2 = QVBoxLayout() vbox3_2.addWidget(mui.cb_thZ2_on) vbox3_2.addWidget(mui.sb_thZ2) vbox3_2.addWidget(mui.sld_thZ2) vbox3_2.addWidget(mui.sb_thZ2Variance) ### -2|1|2|3|- hbox2 = QHBoxLayout() hbox2.addLayout(vbox1) hbox2.addLayout(vbox1_2) hbox2.addLayout(vbox2) hbox2.addLayout(vbox2_2) hbox2.addLayout(vbox3) hbox2.addLayout(vbox3_2) ### |-1-2-| vbox_gb_setThreshold = QVBoxLayout() vbox_gb_setThreshold.addLayout(hbox1) vbox_gb_setThreshold.addLayout(hbox2) mui.gb_setThreshold.setMinimumHeight(400) mui.gb_setThreshold.setLayout(vbox_gb_setThreshold) def readConfig(self, mui): filename = QFileDialog.getOpenFileName(self, 'Open file', '.') self.le_readConfig.setText(filename[0]) if self.le_readConfig.text() == "": return -1 config = ConfigParser() config.read(self.le_readConfig.text()) ## set parameter self.stdOprTimeSb.setValue( float(config['timeUI']['StandartOperationTime'])) self.fpsSb.setValue(int(config['timeUI']['FPS'])) self.cb_saveOprTime.setChecked( "True" == (config['timeUI']['SaveOperationTime'])) self.le_filepath.setText(config['timeUI']['SaveFilename']) mui.cb_thX1_on.setChecked( "True" == (config['thresholdUI']['UseThreshold_X1'])) mui.cb_thX2_on.setChecked( "True" == (config['thresholdUI']['UseThreshold_X2'])) mui.cb_thY1_on.setChecked( "True" == (config['thresholdUI']['UseThreshold_Y1'])) mui.cb_thY2_on.setChecked( "True" == (config['thresholdUI']['UseThreshold_Y2'])) mui.cb_thZ1_on.setChecked( "True" == (config['thresholdUI']['UseThreshold_Z1'])) mui.cb_thZ2_on.setChecked( "True" == (config['thresholdUI']['UseThreshold_Z2'])) mui.sb_thX_scale.setValue( float(config['thresholdUI']['Threshold_ScaleX'])) mui.sb_thY_scale.setValue( float(config['thresholdUI']['Threshold_ScaleY'])) mui.sb_thZ_scale.setValue( float(config['thresholdUI']['Threshold_ScaleZ'])) mui.sb_thX1.setValue(int(config['thresholdUI']['Threshold_ValueX1'])) mui.sb_thX2.setValue(int(config['thresholdUI']['Threshold_ValueX2'])) mui.sb_thY1.setValue(int(config['thresholdUI']['Threshold_ValueY1'])) mui.sb_thY2.setValue(int(config['thresholdUI']['Threshold_ValueY2'])) mui.sb_thZ1.setValue(int(config['thresholdUI']['Threshold_ValueZ1'])) mui.sb_thZ2.setValue(int(config['thresholdUI']['Threshold_ValueZ2'])) mui.sb_thX1Variance.setValue( int(config['thresholdUI']['Threshold_VarianceX1'])) mui.sb_thX2Variance.setValue( int(config['thresholdUI']['Threshold_VarianceX2'])) mui.sb_thY1Variance.setValue( int(config['thresholdUI']['Threshold_VarianceY1'])) mui.sb_thY2Variance.setValue( int(config['thresholdUI']['Threshold_VarianceY2'])) mui.sb_thZ1Variance.setValue( int(config['thresholdUI']['Threshold_VarianceZ1'])) mui.sb_thZ2Variance.setValue( int(config['thresholdUI']['Threshold_VarianceZ2'])) mui.combo.setCurrentText(config['figureUI']['TargetSkeltonParts']) def saveConfig(self, mui): filename = QFileDialog.getSaveFileName(self, 'Save File', '.') self.le_saveConfig.setText(filename[0]) if self.le_saveConfig.text() == "": return -1 config = ConfigParser() config.optionxform = str config.add_section('timeUI') config.add_section('thresholdUI') config.add_section('figureUI') config.add_section('mainUI') config.set('timeUI', 'StandartOperationTime', str(self.stdOprTimeSb.value())) config.set('timeUI', 'FPS', str(self.fpsSb.value())) config.set('timeUI', 'SaveOperationTime', str(self.cb_saveOprTime.checkState())) config.set('timeUI', 'SaveFilename', str(self.le_filepath.text())) config.set('thresholdUI', 'UseThreshold_X1', self.bool2string(mui.cb_thX1_on.checkState())) config.set('thresholdUI', 'UseThreshold_X2', self.bool2string(mui.cb_thX2_on.checkState())) config.set('thresholdUI', 'UseThreshold_Y1', self.bool2string(mui.cb_thY1_on.checkState())) config.set('thresholdUI', 'UseThreshold_Y2', self.bool2string(mui.cb_thY2_on.checkState())) config.set('thresholdUI', 'UseThreshold_Z1', self.bool2string(mui.cb_thZ1_on.checkState())) config.set('thresholdUI', 'UseThreshold_Z2', self.bool2string(mui.cb_thZ2_on.checkState())) config.set('thresholdUI', 'Threshold_ScaleX', str(mui.sb_thX_scale.value())) config.set('thresholdUI', 'Threshold_ScaleY', str(mui.sb_thY_scale.value())) config.set('thresholdUI', 'Threshold_ScaleZ', str(mui.sb_thZ_scale.value())) config.set('thresholdUI', 'Threshold_ValueX1', str(mui.sb_thX1.value())) config.set('thresholdUI', 'Threshold_ValueX2', str(mui.sb_thX2.value())) config.set('thresholdUI', 'Threshold_ValueY1', str(mui.sb_thY1.value())) config.set('thresholdUI', 'Threshold_ValueY2', str(mui.sb_thY2.value())) config.set('thresholdUI', 'Threshold_ValueZ1', str(mui.sb_thZ1.value())) config.set('thresholdUI', 'Threshold_ValueZ2', str(mui.sb_thZ2.value())) config.set('thresholdUI', 'Threshold_VarianceX1', str(mui.sb_thX1Variance.value())) config.set('thresholdUI', 'Threshold_VarianceX2', str(mui.sb_thX2Variance.value())) config.set('thresholdUI', 'Threshold_VarianceY1', str(mui.sb_thY1Variance.value())) config.set('thresholdUI', 'Threshold_VarianceY2', str(mui.sb_thY2Variance.value())) config.set('thresholdUI', 'Threshold_VarianceZ1', str(mui.sb_thZ1Variance.value())) config.set('thresholdUI', 'Threshold_VarianceZ2', str(mui.sb_thZ2Variance.value())) config.set('figureUI', 'TargetSkeltonParts', str(mui.combo.currentText())) config.write(open(self.le_saveConfig.text(), 'w')) def drawChart(self, mui): series = QPieSeries() series.append("Main", mui.keyfunc.mainActivityFrame) series.append("Key", mui.keyfunc.keyActivityFrame) slice1 = series.slices()[0] #slice1.setExploded() slice1.setLabelVisible() slice1.setPen(QPen(QColor(40, 100, 240, 250), 2)) slice1.setBrush(QColor(40, 100, 240, 200)) slice2 = series.slices()[1] slice2.setLabelVisible() slice2.setPen(QPen(QColor(20, 150, 240, 250), 2)) slice2.setBrush(QColor(20, 150, 240, 200)) chart = QChart() chart.addSeries(series) #chart.setTitle("Activity Details") #chart.legend().hide() self.chartView.setChart(chart) def getCalclationTime(self, mui): if self.cb_registrationTime.checkState(): self.setCalclationTimeGraph() self.calcDifferenceOperatingTime() if self.cb_saveOprTime.checkState(): self.writeText(mui) def setCalclationTimeGraph(self): if (len(self.x_cycle) >= self.sb_maxCount.value()): self.x_cycle.popleft() self.y_time.popleft() self.cycle_counter += 1 self.x_cycle.append(self.cycle_counter) self.y_time.append(float(self.calcOprTimeLabel.text())) self.le_mean.setText("{0:.2f}".format(np.array(self.y_time).mean())) self.le_variance.setText("{0:.2f}".format( self.calclVariance(np.array(self.y_time)))) self.draw_figure() def draw_figure(self): self.axes.clear() self.axes.set_ylim([0, self.sb_maxValue.value()]) self.axes.bar(self.x_cycle, self.y_time, color='#6060AA') self.canvas_time.draw() def clearGraph(self): self.cycle_counter = 0 self.x_cycle = deque([]) self.y_time = deque([]) self.draw_figure() def calclVariance(self, val): variance = np.sum((val * val)) / len(val) - (val.mean() * val.mean()) return variance def calcDifferenceOperatingTime(self): time = self.stdOprTimeSb.value() - float(self.calcOprTimeLabel.text()) self.differenceTimeLabel.setText("{0:.2f}[sec]".format(time)) if self.cb_alarm.checkState(): if self.dsb_alarmRange.value() <= abs(time) and 0 < time: self.popupMessage(0, abs(time)) elif self.dsb_alarmRange.value() <= abs(time) and 0 > time: self.popupMessage(1, abs(time)) def popupMessage(self, signal, time): if signal == 0: QMessageBox.warning( self, 'Alarm Message', "標準作業時間({1:.2f}秒)と比較して{0:.2f}秒速いです".format( time, self.stdOprTimeSb.value()), QMessageBox.Close) elif signal == 1: QMessageBox.warning( self, 'Alarm Message', "標準作業時間({1:.2f}秒)と比較して{0:.2f}秒遅いです".format( time, self.stdOprTimeSb.value()), QMessageBox.Close) def writeText(self, mui): import csv import os.path writeItemname = True if os.path.isfile(self.le_filepath.text()): writeItemname = False with open(self.le_filepath.text(), 'a', newline="") as f: writer = csv.writer(f) if writeItemname: writer.writerow( ['Filename', 'FPS', 'Calclation Time', 'Setting Time']) writer.writerow([ mui.fnameQle.text(), self.fpsSb.value(), float(self.calcOprTimeLabel.text()), self.stdOprTimeSb.value() ]) def setSaveTimeFilePath(self): filename = QFileDialog.getSaveFileName(self, 'Save File', '.') self.le_filepath.setText(filename[0]) def bool2string(self, bool_val): if bool_val: return 'True' else: return 'False'
class AlgWin(QWidget): okCLickedSignal = pyqtSignal(Algo, name='okClicked') def __init__(self, parent=None, alg=None): QWidget.__init__(self, parent) winsettings('algwin', self) taglabel = QLabel('&Tags') self.tags = QLineEdit('artist | title') taglabel.setBuddy(self.tags) self.alcombo = QComboBox() allabel = QLabel('&Algorithms') allabel.setBuddy(self.alcombo) self.threshold = QLineEdit('90') self.threshold.setValidator(QDoubleValidator(self.threshold)) perlabel = QLabel("&Match threshold") perlabel.setBuddy(self.threshold) self.matchcase = QCheckBox('&Match Case') okcancel = OKCancel() okcancel.okButton.setDefault(True) okcancel.ok.connect(self.okClicked) okcancel.cancel.connect(self.close) vbox = QVBoxLayout() [vbox.addWidget(z) for z in [taglabel, self.tags, perlabel, self.threshold, allabel, self.alcombo, self.matchcase]] frame = QFrame() frame.setFrameStyle(QFrame.Shape.Box) frame.setLayout(vbox) box = QVBoxLayout() box.addWidget(frame) box.addLayout(okcancel) self.setLayout(box) x = [funcinfo(z) for z in funcs] names = [z[0] for z in x] ds = [z[1] for z in x] self.alcombo.clear() self.alcombo.addItems(names) self.alcombo.setCurrentIndex(0) tooltip = "<dl>%s</dl>" % ''.join(['<dt><b>%s<b></dt> <dd>%s</dd>' % z for z in x]) self.alcombo.setToolTip(tooltip) if alg: self.loadAlgo(alg) def loadAlgo(self, alg): i = self.alcombo.findText(alg.funcname) if i >= 0: self.alcombo.setCurrentIndex(i) else: self.alcombo.addItem(alg.funcname) self.alcombo.setCurrentIndex(self.alcombo.count() - 1) self.tags.setText(' | '.join(alg.tags)) self.threshold.setText('%.2f' % (alg.threshold * 100)) if alg.matchcase: self.matchcase.setCheckState(Qt.CheckState.Checked) else: self.matchcase.setCheckState(Qt.CheckState.Unchecked) def saveAlgo(self): tags = [x for x in [z.strip() for z in str(self.tags.text()).split("|")] if x != ""] func = funcs[self.alcombo.currentIndex()] threshold = float(str(self.threshold.text())) / 100 matchcase = False if self.matchcase.checkState() == Qt.CheckState.Checked: matchcase = True return Algo(tags, threshold, func, matchcase) def okClicked(self): self.okClickedSignal.emit(self.saveAlgo()) self.close()
class Window(QWidget): def __init__(self, parent=None): super(Window, self).__init__(parent) self.initUI() def initUI(self): self.listCheckBox = [ "系统时间", "设备名称", "设备版本", "设备类型", "运行时间", "cpu利用率", '内存使用', '板卡信息', '板卡切换情况', '邻居信息', '温度与电源信息', 'ACL', 'HomelessVideo' ] grid = QGridLayout() self.resize(300, 200) self.setWindowTitle("来快活呀") for i, v in enumerate(self.listCheckBox): self.listCheckBox[i] = QCheckBox(v) grid.addWidget(self.listCheckBox[i], i, 0) self.checkbox = QCheckBox("选择全部") self.checkbox.stateChanged.connect(self.selectall) self.button = QPushButton("Run") self.button.clicked.connect(self.buttonclicked) grid.addWidget(self.checkbox, 25, 0, 1, 2) grid.addWidget(self.button, 26, 0, 1, 2) self.setLayout(grid) def buttonclicked(self): ###It will return a varlist. ###It will display what you have chosen. varlist = [] for i, v in enumerate(self.listCheckBox): if v.checkState(): varlist.append(v.text()) print(varlist) ###After a varlist is chosen, run the function in order to export the chosen items t1 = time.time() readwritevalue(varlist) GetFormated() ##Get the Final output of Xunjian-Report.csv Getxlsx() ##Get the Xunjian-Report.xls GetDocx() ##Get the docx format print("Run time %s" % (time.time() - t1)) ###Multiple process### ###Don't know how to proceed with multiprocessing under the PyQt yet. ##The following will spend more time to complete the programme. ##From the url https://stackoverflow.com/questions/15675043/multiprocessing-and-gui-updating-qprocess-or-multiprocessing ##It describes how to use multiprocessing and QThread together. # t1 = time.time() # pool = Pool(4) # pool.map(readwritevalue, varlist) # GetFormated() ##Get the Final output of Xunjian-Report.csv # Getxlsx() ##Get the Xunjian-Report.xls # GetDocx() ##Get the docx format # pool.close() # pool.join() # print("Run time %s" %(time.time()-t1)) def selectall(self): if self.checkbox.checkState() == Qt.Checked: for i, v in enumerate(self.listCheckBox): self.listCheckBox[i].setChecked(True) else: for i, v in enumerate(self.listCheckBox): self.listCheckBox[i].setChecked(False)
class FormWidget(QWidget): def __init__(self, parent): super(FormWidget, self).__init__(parent) self.resultDict = {} self.csvList = [] self.fileStartTime = "" self.fileStopTime = "" self.openGoogleEarth = True self.statusBar = QStatusBar() self.statusBar.showMessage('Open a CSV File to begin') # Buttons self.openFileBtn = QPushButton('Open CSV Files', self) self.openFileBtn.setToolTip('Open Coordinator formatted CSV files') self.openFileBtn.clicked.connect(self.showOpenFile) self.startParseBtn = QPushButton('Start Search', self) self.startParseBtn.clicked.connect(self.parseFile) self.startParseBtn.setDisabled(True) self.plotSelectionBtn = QPushButton('Plot Selected ISSI', self) self.plotSelectionBtn.clicked.connect(self.onPlotFile) self.plotSelectionBtn.setDisabled(True) self.saveDataBtn = QPushButton('Save ISSI Search Data', self) self.saveDataBtn.clicked.connect(self.save_data) self.saveDataBtn.setDisabled(True) self.resetTimeBtn = QPushButton('Reset Times', self) self.resetTimeBtn.clicked.connect(self.onResetTimes) self.resetTimeBtn.setDisabled(True) self.plotAllBtn = QPushButton("Plot all ISSI's (caution)") self.plotAllBtn.clicked.connect(self.onPlotFile) self.plotAllBtn.setDisabled(True) self.stopPlotBtn = QPushButton('Stop Plot') self.stopPlotBtn.clicked.connect(self.stopThread) self.stopPlotBtn.setDisabled(True) self.openResultsFolder = QPushButton('Open Results folder') self.openResultsFolder.clicked.connect(self.open_results_folder) self.openResultsFolder.setDisabled(True) # CheckBoxes self.areaSearchSwitch = QCheckBox('Search Area', self) self.areaSearchSwitch.stateChanged.connect(self.areaSearch) self.issiSearchSwitch = QCheckBox('search for ISSIs', self) self.issiSearchSwitch.stateChanged.connect(self.issiSearch) self.googleEarthInstalled = QCheckBox('Plot to Google Earth') self.googleEarthInstalled.stateChanged.connect(self.googleEarth) self.googleEarthInstalled.toggle() self.includeissiswitch = QCheckBox('Include Range', self) self.includeissiswitch.stateChanged.connect(self.includes) self.excludeissiswitch = QCheckBox('Exclude Range', self) self.excludeissiswitch.stateChanged.connect(self.excludes) # List Fields self.issiList = QListWidget() self.issiList.setToolTip( 'Single Click to show details\nDouble Click to add to ISSI search') self.issiList.currentItemChanged.connect(self.onIssiClick) self.issiList.itemDoubleClicked.connect(self.onissidoubleclick) self.detailsList = QListWidget() self.detailsList.setToolTip('Double Click to plot on Google Maps') self.detailsList.itemDoubleClicked.connect(self.onDetailDoubleClick) # Labels self.latLabel = QLabel('Latitude: ') self.lonLabel = QLabel('Longitude: ') self.distLabel = QLabel('Search Radius (km): ') self.starttimeLabel = QLabel('Start Time: ') self.stoptimeLabel = QLabel('Stop Time: ') self.issilabel = QLabel('ISSI Results') self.detailslabel = QLabel( 'Details [ISSI, Time, Latitude, Longitude, Speed, Heading, Distance from search, Location]' ) # Lines self.line = QFrame() self.line.setFrameShape(QFrame.HLine) self.line.setFrameShadow(QFrame.Sunken) self.line1 = QFrame() self.line1.setFrameShape(QFrame.HLine) self.line1.setFrameShadow(QFrame.Sunken) self.line2 = QFrame() self.line2.setFrameShape(QFrame.HLine) self.line2.setFrameShadow(QFrame.Sunken) self.line3 = QFrame() self.line3.setFrameShape(QFrame.HLine) self.line3.setFrameShadow(QFrame.Sunken) # Text Fields self.csvFileName = QLineEdit('No Files loaded') self.startTime = QLineEdit('Start Time') self.stopTime = QLineEdit('Stop Time') self.lat = QLineEdit('57.148778') self.lat.setDisabled(True) self.lon = QLineEdit('-2.095077') self.lon.setDisabled(True) self.distance = QLineEdit('2.5') self.distance.setDisabled(True) self.issi = QLineEdit() self.issi.setDisabled(True) self.includeissi = QLineEdit('677;6780;6785') self.includeissi.setToolTip('3 or 4 digits separated by ;') self.includeissi.setDisabled(True) self.excludeissi = QLineEdit('688;666') self.excludeissi.setToolTip('3 or 4 digits separated by ;') self.excludeissi.setDisabled(True) # Progress Bar self.progress = QProgressBar() self.progress.setRange(0, 100) self.progress.setValue(0) self.hbox_load_files = QHBoxLayout() self.hbox_load_files.addWidget(self.openFileBtn, 1) self.hbox_load_files.addWidget(self.csvFileName, 5) self.hbox_search_time = QHBoxLayout() self.hbox_times = QHBoxLayout() self.hbox_search_time.addWidget(self.resetTimeBtn, 1) self.hbox_times.addWidget(self.starttimeLabel) self.hbox_times.addWidget(self.startTime) self.hbox_times.addWidget(self.stoptimeLabel) self.hbox_times.addWidget(self.stopTime) self.hbox_times.addStretch(1) self.hbox_search_time.addLayout(self.hbox_times, 5) self.hbox_search_area = QHBoxLayout() self.hbox_search_area.addWidget(self.areaSearchSwitch) self.hbox_search_area.addStretch(1) self.hbox_search_area.addWidget(self.latLabel) self.hbox_search_area.addWidget(self.lat) self.hbox_search_area.addWidget(self.lonLabel) self.hbox_search_area.addWidget(self.lon) self.hbox_search_area.addWidget(self.distLabel) self.hbox_search_area.addWidget(self.distance) self.hbox_serach_issi = QHBoxLayout() self.hbox_serach_issi.addWidget(self.issiSearchSwitch) self.hbox_serach_issi.addWidget(self.issi, 1) self.hbox_detail_labels = QHBoxLayout() self.hbox_detail_labels.addWidget(self.issilabel, 1) self.hbox_detail_labels.addWidget(self.detailslabel, 5) self.hbox_results = QHBoxLayout() self.hbox_results.addWidget(self.issiList, 1) self.hbox_results.addWidget(self.detailsList, 5) self.hbox_plot_results = QHBoxLayout() self.hbox_plot_results.addWidget(self.googleEarthInstalled) self.hbox_plot_results.addWidget(self.plotSelectionBtn) self.hbox_plot_results.addWidget(self.plotAllBtn) self.hbox_plot_results.addWidget(self.saveDataBtn) self.hbox_plot_results.addWidget(self.openResultsFolder) self.hbox_progress_bar = QHBoxLayout() self.hbox_progress_bar.addWidget(self.stopPlotBtn) self.hbox_progress_bar.addWidget(self.progress) self.hbox_filters = QHBoxLayout() self.hbox_filters.addWidget(self.includeissiswitch) self.hbox_filters.addWidget(self.includeissi) self.hbox_filters.addWidget(self.excludeissiswitch) self.hbox_filters.addWidget(self.excludeissi) # Create Vbox self.vbox = QVBoxLayout() self.vbox.addLayout(self.hbox_load_files) self.vbox.addLayout(self.hbox_search_time) self.vbox.addWidget(self.line) self.vbox.addLayout(self.hbox_search_area) self.vbox.addWidget(self.line1) self.vbox.addLayout(self.hbox_filters) self.vbox.addLayout(self.hbox_serach_issi) self.vbox.addWidget(self.line2) self.vbox.addWidget(self.startParseBtn) self.vbox.addLayout(self.hbox_detail_labels) self.vbox.addLayout(self.hbox_results, 1) self.vbox.addLayout(self.hbox_plot_results) self.vbox.addLayout(self.hbox_progress_bar) self.vbox.addWidget(self.line3) self.vbox.addWidget(self.statusBar) self.setLayout(self.vbox) def open_results_folder(self): filepath = os.path.abspath(os.path.dirname(sys.argv[0])) resultpath = filepath + '\\results\\' os.startfile(resultpath) def includes(self, state): if state == Qt.Checked: self.includeissi.setDisabled(False) else: self.includeissi.setDisabled(True) def excludes(self, state): if state == Qt.Checked: self.excludeissi.setDisabled(False) else: self.excludeissi.setDisabled(True) def save_data(self): current = self.issiList.selectedItems() print(current[0].text()) save_file = QFileDialog.getSaveFileName( self, 'Save ISSI File', "results\\{}".format(current[0].text()), "Text Files (*.txt);;json Files (*.json);;csv Files (*.csv)") print(save_file) if save_file[1] == 'json Files (*.json)': with open(save_file[0], 'w') as jsonfile: json.dump(self.resultDict[current[0].text()], jsonfile) if save_file[1] == 'Text Files (*.txt)': with open(save_file[0], 'w') as txtfile: result_list = [] for line in self.resultDict[current[0].text()]: result_list.append('{}\n'.format(line)) txtfile.writelines(result_list) if save_file[1] == 'csv Files (*.csv)': with open(save_file[0], 'w') as csvfile: fieldnames = [ 'ISSI', 'Time', 'Latitude', 'Longitute', 'Speed', 'Heading', 'Distance', 'Location' ] writer = csv.writer(csvfile, lineterminator='\n') writer.writerow(fieldnames) writer.writerows(self.resultDict[current[0].text()]) def showOpenFile(self): self.csvList = [] self.issiList.clear() self.detailsList.clear() self.plotSelectionBtn.setDisabled(True) self.saveDataBtn.setDisabled(True) self.plotAllBtn.setDisabled(True) fname = QFileDialog.getOpenFileNames(self, 'Open Coordinator CSV file', "", "CSV Files (*.csv)") if fname[0]: start_time_text = "" end_time_text = "" files_text = "" latest_end_time = datetime.datetime.strptime( '01/01/1970 00:00:00', '%d/%m/%Y %H:%M:%S') row_count = 0 line_fail_count = 0 for file_id in range(len(fname[0])): f = open(fname[0][file_id], 'r') if files_text != "": files_text += '; ' files_text += (fname[0][file_id]).split('/')[-1] with f: for row in f: row_count += 1 self.csvList.append(row) row = 0 for item in self.csvList: row += 1 update = (row / row_count) * 100 self.progress.setValue(update) item_list = item.split(',') if item_list[0] == "Node": continue else: try: time_text = datetime.datetime.strptime( item_list[2], '%d/%m/%Y %H:%M:%S') except: line_fail_count += 1 continue if start_time_text == "": start_time_text = item_list[2] else: if time_text > latest_end_time: latest_end_time = time_text end_time_text = item_list[2] self.fileStartTime = start_time_text self.fileStopTime = end_time_text self.startTime.setText(self.fileStartTime) self.stopTime.setText(self.fileStopTime) self.csvFileName.setText(files_text) self.statusBar.showMessage( 'File Loaded, contains {} lines, with {} bad row(s)'. format(row_count, line_fail_count)) self.startParseBtn.setDisabled(False) self.resetTimeBtn.setDisabled(False) print(line_fail_count) else: pass def parseFile(self): self.plotSelectionBtn.setDisabled(True) self.saveDataBtn.setDisabled(True) self.plotAllBtn.setDisabled(True) self.progress.setValue(0) self.issiList.clear() self.detailsList.clear() distance = 0 searchlat = 0 searchlon = 0 starttime = datetime.datetime.strptime(self.startTime.text(), '%d/%m/%Y %H:%M:%S') stoptime = datetime.datetime.strptime(self.stopTime.text(), '%d/%m/%Y %H:%M:%S') issilist = [] includeslist = [] excludeslist = [] area_switch = False issi_switch = False includes = False excludes = False if self.areaSearchSwitch.checkState() == Qt.Checked: area_switch = True distance = float(self.distance.text()) searchlat = float(self.lat.text()) searchlon = float(self.lon.text()) if self.issiSearchSwitch.checkState() == Qt.Checked: issi_switch = True issilist = self.issi.text().split(';') if self.includeissiswitch.checkState() == Qt.Checked: includes = True includeslist = self.includeissi.text().split(';') if self.excludeissiswitch.checkState() == Qt.Checked: excludes = True excludeslist = self.excludeissi.text().split(';') self.parse_file = ParseFile(self.csvList, starttime, stoptime, distance, searchlat, searchlon, issilist, area_switch, issi_switch, includes, includeslist, excludes, excludeslist) self.parse_file.parse_message_signal.connect(self.parse_update) self.parse_file.parse_progress_signal.connect(self.parse_update) self.parse_file.parse_result_dict_signal.connect(self.parse_update) self.parse_file.parse_result_list_signal.connect(self.parse_update) self.parse_file.start() def parse_update(self, value): if isinstance(value, int): self.progress.setValue(value) if isinstance(value, str): self.statusBar.showMessage(value) if isinstance(value, list): for i in value: self.issiList.addItem(i) if isinstance(value, dict): self.resultDict = value def onResetTimes(self): self.startTime.setText(self.fileStartTime) self.stopTime.setText(self.fileStopTime) def areaSearch(self, state): if state != Qt.Checked: self.lat.setDisabled(True) self.lon.setDisabled(True) self.distance.setDisabled(True) else: self.lat.setDisabled(False) self.lon.setDisabled(False) self.distance.setDisabled(False) def issiSearch(self, state): if state != Qt.Checked: self.issi.setDisabled(True) else: self.issi.setDisabled(False) def googleEarth(self, state): if state != Qt.Checked: self.openGoogleEarth = False else: self.openGoogleEarth = True def onIssiClick(self, current, previous): self.detailsList.clear() if current != None: for x in range(0, len(self.resultDict[current.text()])): self.detailsList.addItem('{}'.format( self.resultDict[current.text()][x])) self.plotSelectionBtn.setDisabled(False) self.saveDataBtn.setDisabled(False) self.plotAllBtn.setDisabled(False) self.openResultsFolder.setDisabled(False) def onissidoubleclick(self, state): currentissi = self.issi.text() if currentissi != "": currentissi += ";" currentissi = currentissi + state.text() self.issi.setText(currentissi) def onDetailDoubleClick(self, state): lat = ast.literal_eval(state.text())[2] lon = ast.literal_eval(state.text())[3] url = "https://www.google.com/maps/search/?api=1&query={},{}".format( lat, lon) webbrowser.open(url) def onPlotFile(self): self.progress.setValue(0) self.stopPlotBtn.setDisabled(False) sender = self.sender() issilist = [] gps = [0] if self.areaSearchSwitch.checkState() == Qt.Checked: gps = [self.lat.text(), self.lon.text(), self.distance.text()] if sender.text() == "Plot all ISSI's (caution)": for key in sorted(self.resultDict.keys()): issilist.append(key) else: issilist.append(self.issiList.currentItem().text()) self.plot_thread = PlotFiles(self.resultDict, issilist, self.openGoogleEarth, gps) self.plot_thread.progressSignal.connect(self.updateprogress) self.plot_thread.threadMessage.connect(self.updateprogress) self.plot_thread.start() def stopThread(self): self.plot_thread.stop() self.statusBar.showMessage('Plot stopped') def updateprogress(self, value): if isinstance(value, str): self.statusBar.showMessage(value) self.stopPlotBtn.setDisabled(True) else: self.progress.setValue(value)
class FieldEdit(QWidget): valueChanged = QtCore.pyqtSignal() def __init__(self, svd_field): QWidget.__init__(self) self.svd = svd_field self.horiz_layout = QHBoxLayout(self) self.horiz_layout.setContentsMargins(0, 0, 0, 0) self.horiz_layout.setSpacing(6) if self.svd["access"] == "read-only": self.is_enabled = False else: self.is_enabled = True self.num_bwidth = self.svd["msb"] - self.svd["lsb"] + 1 if self.num_bwidth == 1: self.chbox_val = QCheckBox(self) self.chbox_val.setEnabled(self.is_enabled) self.chbox_val.setMaximumSize(QtCore.QSize(16777215, 20)) self.chbox_val.stateChanged.connect( self.handle_field_value_changed) self.horiz_layout.addWidget(self.chbox_val) else: self.nedit_val = NumEdit(self.num_bwidth) self.nedit_val.setEnabled(self.is_enabled) self.nedit_val.editingFinished.connect( self.handle_field_value_changed) self.nedit_val.setMaximumSize(QtCore.QSize(16777215, 20)) self.horiz_layout.addWidget(self.nedit_val) if self.svd["enums"]: self.is_enums = True self.combo_enum = QComboBox(self) self.combo_enum.setEnabled(self.is_enabled) self.combo_enum.currentIndexChanged.connect( self.handle_enum_value_changed) self.combo_enum.values = [] for enum in self.svd["enums"]: self.combo_enum.values += [int(enum["value"])] self.combo_enum.addItem( "(0x%x) %s : %s" % (int(enum["value"]), enum["name"], enum["description"])) self.combo_enum.setMaximumSize(QtCore.QSize(16777215, 20)) self.horiz_layout.addWidget(self.combo_enum) if self.num_bwidth == 1: self.chbox_val.setMaximumSize(QtCore.QSize(320, 20)) else: self.nedit_val.setMaximumSize(QtCore.QSize(320, 20)) else: self.is_enums = False # -- Slots -- def handle_field_value_changed(self, value=None): if self.is_enums: try: if self.val() != self.combo_enum.values[ self.combo_enum.currentIndex()]: self.combo_enum.setCurrentIndex( self.combo_enum.values.index(self.val())) except ValueError: self.combo_enum.setCurrentIndex(-1) self.valueChanged.emit() def handle_enum_value_changed(self, currentIndex): if self.is_enums and currentIndex != -1: if self.val() != self.combo_enum.values[currentIndex]: self.setVal(self.combo_enum.values[currentIndex]) # -- API -- def val(self): if self.num_bwidth == 1: if self.chbox_val.checkState(): return 1 else: return 0 else: return self.nedit_val.num() def setVal(self, val): if self.num_bwidth == 1: if val: self.chbox_val.setCheckState(QtCore.Qt.Checked) else: self.chbox_val.setCheckState(QtCore.Qt.Unchecked) else: self.nedit_val.setNum(val) self.handle_field_value_changed()
class schema_target(QDialog): def setupUi(self): # self.Dialog = Dialog self.setWindowTitle("层指标") # self.resize(400, 300) self.setFixedSize(400, 200) grid = QGridLayout() grid.setSpacing(10) py_dir_label = QLabel("py文件夹:") self.py_dir_edit = QLineEdit() py_dir_button = QPushButton("选择文件") self.qc_group_by = QCheckBox("group by 字段") self.qc_temp_table = QCheckBox("临时表个数") self.qc_join = QCheckBox("join个数") self.qc_origin_target_table = QCheckBox("源表和目标表") self.qc_sql_func = QCheckBox("sql函数个数") self.qc_all = QCheckBox("反选") py_dir_button.clicked.connect(self.get_py_dir) self.qc_all.clicked.connect(self.chang_status) comfirm_button = QPushButton("运行") quit_button = QPushButton("退出") comfirm_button.clicked.connect(self.run) quit_button.clicked.connect(self.close) grid.addWidget(py_dir_label, 1, 0) grid.addWidget(self.py_dir_edit, 1, 1) grid.addWidget(py_dir_button, 1, 2) grid.addWidget(self.qc_group_by, 2, 0) grid.addWidget(self.qc_temp_table, 2, 2) # grid.addWidget(ddl_button, 2, 2) grid.addWidget(self.qc_join, 3, 0) grid.addWidget(self.qc_origin_target_table, 3, 2) # grid.addWidget(py_dir_button, 3, 2) grid.addWidget(self.qc_sql_func, 4, 0) grid.addWidget(self.qc_all, 4, 2) grid.addWidget(comfirm_button, 5, 0) grid.addWidget(quit_button, 5, 1) self.setLayout(grid) self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint) #设置窗体总显示在最上面 # self.retranslateUi(Dialog) # Dialog.setWindowModality(Qt.ApplicationModal) self.exec_() QtCore.QMetaObject.connectSlotsByName(self) def chang_status(self, ): self.qc_group_by.setChecked( True if self.qc_group_by.checkState() == Qt.Unchecked else False ) # if self.qc_group_by.checkState() == Qt.Unchecked else False self.qc_temp_table.setChecked( True if self.qc_temp_table.checkState() == Qt.Unchecked else False) self.qc_join.setChecked(True if self.qc_join.checkState() == Qt.Unchecked else False) self.qc_origin_target_table.setChecked( True if self.qc_origin_target_table.checkState() == Qt.Unchecked else False) self.qc_sql_func.setChecked(True if self.qc_sql_func.checkState() == Qt.Unchecked else False) # print(self.qc_all.get()) def get_py_dir(self, ): dir_name = QFileDialog.getExistingDirectory(None, 'Open file', r'c:\\') # print(dir_name) self.py_dir_edit.setText(dir_name) def run(self): try: obj = statistics_target() dir_name = self.py_dir_edit.text() if self.qc_group_by.checkState() == Qt.Checked: obj.get_statistics_group_by_count(dir_name) if self.qc_join.checkState() == Qt.Checked: obj.get_statistics_join_count(dir_name) if self.qc_temp_table.checkState() == Qt.Checked: obj.get_statistics_temp_table_count(dir_name) if self.qc_sql_func.checkState() == Qt.Checked: obj.get_statistics_sql_function_count(dir_name) if self.qc_origin_target_table.checkState() == Qt.Checked: obj.get_statistics_origin_target_table(dir_name) QMessageBox.information(self, '提示', '程序执行成功') except Exception as e: QMessageBox.critical(self, '错误', f"错误信息为{e}")
class AdupUI(QMainWindow): """ADUP View (GUI).""" def __init__(self, controller): #View initializer super().__init__() self._controller = controller # Set some main window's properties self.setWindowTitle('User Creator') self.setFixedSize(400, 500) self.general_layout = QVBoxLayout() # Set the central widget which is the parent for the rest of the gui components self._central_widget = QWidget(self) self.setCentralWidget(self._central_widget) self._central_widget.setLayout(self.general_layout) #Create the main form self._create_main_form() self._create_checkboxes() self._create_buttons() self.detect_button_click() self.detect_text_changes() self.set_company_combobox() self.detect_combobox_change() self.set_ou_combobox() def _create_main_form(self): #Create the main form self.main_form_layout = QFormLayout() #Create the form's widgets self.fn_line_edit = QLineEdit() self.sn_line_edit = QLineEdit() self.dn_line_edit = QLineEdit() self.pre2k_line_edit = QLineEdit() self.uln_line_edit = QLineEdit() self.company_combobox = QComboBox() self.dept_combobox = QComboBox() self.job_title_combobox = QComboBox() self.mngr_line_edit = QLineEdit() self.mngr_check_btn = QPushButton("Check Manager Pre2k Name", self) self.emp_no_line_edit = QLineEdit() self.psswd_line_edit = QLineEdit() #Set the password to hidden self.psswd_line_edit.setEchoMode(QLineEdit.Password) self.org_unit_combobox = QComboBox() self.get_org_unit_btn = QPushButton() #Add widgets to form self.main_form_layout.addRow(QLabel("First Name: *"), self.fn_line_edit) self.main_form_layout.addRow(QLabel("Surname: *"), self.sn_line_edit) self.main_form_layout.addRow(QLabel("Display Name: *"), self.dn_line_edit) self.main_form_layout.addRow(QLabel("Pre 2k Logon Name: *"), self.pre2k_line_edit) self.main_form_layout.addRow(QLabel("User Logon Name: *"), self.uln_line_edit) self.main_form_layout.addRow(QLabel("Company: *"), self.company_combobox) self.main_form_layout.addRow(QLabel("Department: *"), self.dept_combobox) self.main_form_layout.addRow(QLabel("Job Title: *"), self.job_title_combobox) self.main_form_layout.addRow(QLabel("Manager: *"), self.mngr_line_edit) self.mngr_exists_lbl = QLabel("") self.main_form_layout.addRow(self.mngr_check_btn, self.mngr_exists_lbl) self.main_form_layout.addRow(QLabel("Employee Number:"), self.emp_no_line_edit) self.main_form_layout.addRow(QLabel("Password: *"), self.psswd_line_edit) self.main_form_layout.addRow(QLabel("Organisational Unit:"), self.org_unit_combobox) #Add this form layout to the main layout self.general_layout.addLayout(self.main_form_layout) def _create_checkboxes(self): self.checkbox_layout = QVBoxLayout() #Create checkbox widgets self.change_psswd = QCheckBox("Change Password at Next Logon") self.psswd_no_expire = QCheckBox("Password Never Expires") #set checkboxes to checked self.change_psswd.setChecked(True) self.psswd_no_expire.setChecked(True) #Add checkboxes to form self.checkbox_layout.addWidget(self.change_psswd) self.checkbox_layout.addWidget(self.psswd_no_expire) #Add to the main layout self.general_layout.addLayout(self.checkbox_layout) def _create_buttons(self): self.buttons_layout = QFormLayout() #Create the widgets self.check_duplicate_btn = QPushButton("Check for duplicates", self) self.check_duplicate_lbl = QLabel("") self.create_powershell_btn = QPushButton("Create Powershell Cmd", self) self.create_powershell_command_result_line_edit = QLineEdit() self.create_powershell_command_result_line_edit.setReadOnly(True) self.create_user_btn = QPushButton("Create User", self) #button set to disabled until conditions are met self.create_user_btn.setEnabled(False) #Add buttons to form self.buttons_layout.addRow(self.check_duplicate_btn, self.check_duplicate_lbl) self.buttons_layout.addRow(self.create_powershell_btn, self.create_powershell_command_result_line_edit) self.buttons_layout.addRow(self.create_user_btn) #Add to the main layout self.general_layout.addLayout(self.buttons_layout) def detect_combobox_change(self): """Detect changes to the comboboxes and call a function sending combobox text""" self.company_combobox.currentTextChanged.connect(self.set_department_combobox) self.dept_combobox.currentTextChanged.connect(self.set_job_combobox) def set_company_combobox(self): """Set the company combobox values""" companies = self._controller.get_companies() self.company_combobox.addItems(companies) def set_department_combobox(self): """Set the department combobox values""" #Clears the box if the user changes their mind self.dept_combobox.clear() departments = self._controller.get_next_combo_element(self.company_combobox.currentText(), 'company') self.dept_combobox.addItems(departments) def set_job_combobox(self): """Set the Job combobox values""" #Clears the box if the user changes their mind self.job_title_combobox.clear() jobs = self._controller.get_next_combo_element(self.dept_combobox.currentText(), 'department', self.company_combobox.currentText(), self.dept_combobox.currentIndex()) self.job_title_combobox.addItems(jobs) def set_ou_combobox(self): """Set the OU combobox values""" try: self.org_unit_combobox.addItems(self._controller.get_ou_structure()) except Exception as e: print("Unable to query OU structure") print(e) def detect_text_changes(self): """Detect when a form item changes and call the mandatory field check""" self.fn_line_edit.textChanged.connect(self.check_mandatory_fields) self.sn_line_edit.textChanged.connect(self.check_mandatory_fields) self.dn_line_edit.textChanged.connect(self.check_mandatory_fields) self.pre2k_line_edit.textChanged.connect(self.check_mandatory_fields) self.uln_line_edit.textChanged.connect(self.check_mandatory_fields) self.company_combobox.currentIndexChanged.connect(self.check_mandatory_fields) self.dept_combobox.currentIndexChanged.connect(self.check_mandatory_fields) self.job_title_combobox.currentIndexChanged.connect(self.check_mandatory_fields) self.mngr_line_edit.textChanged.connect(self.check_mandatory_fields) self.psswd_line_edit.textChanged.connect(self.check_mandatory_fields) self.org_unit_combobox.currentIndexChanged.connect(self.check_mandatory_fields) def detect_button_click(self): """Detects when a button is pressed and sends to controller""" self.create_powershell_btn.clicked.connect(self.create_powershell_command) self.create_user_btn.clicked.connect(self.create_user) self.check_duplicate_btn.clicked.connect(self.check_duplicate_usr) self.mngr_check_btn.clicked.connect(self.check_manager_exists) def check_mandatory_fields(self): """Detects if the mandatory fields are filled, if not the create user button will be deactivated""" if(self.fn_line_edit.text() != '' and self.sn_line_edit.text() and self.dn_line_edit.text() != '' and self.pre2k_line_edit.text() != '' and self.uln_line_edit.text() != '' and self.company_combobox.currentText != '' and self.dept_combobox.currentText != '' and self.job_title_combobox.currentText != '' and self.mngr_line_edit.text() != '' and self.psswd_line_edit.text() != '' and self.org_unit_combobox.currentText != ''): self.create_user_btn.setEnabled(True) else: self.create_user_btn.setEnabled(False) def check_duplicate_usr(self): """Checks if the filled in SAM name matches an existing user""" user_exists = self._controller.usr_exist_check(self.pre2k_line_edit.text(), self.uln_line_edit.text()) if user_exists == True: self.check_duplicate_lbl.setText("User exists") self.check_duplicate_lbl.setStyleSheet("color: red;") else: self.check_duplicate_lbl.setText("User does not exist") self.check_duplicate_lbl.setStyleSheet("color: green;") def check_manager_exists(self): """Checks if the manager exists""" try: user_exists = self._controller.usr_exist_check(self.mngr_line_edit.text()) except Exception as e: print(e) if user_exists == True: self.mngr_exists_lbl.setText("Manager Exists") self.mngr_exists_lbl.setStyleSheet("color: green;") else: self.mngr_exists_lbl.setText("Manager Does Not Exist") self.mngr_exists_lbl.setStyleSheet("color: red;") def create_powershell_command(self): """Create the user creation Powershell command""" command = self._controller.create_user_command(self.fn_line_edit.text(), self.sn_line_edit.text(), self.dn_line_edit.text(), self.pre2k_line_edit.text(), self.uln_line_edit.text(), self.company_combobox.currentText(), self.dept_combobox.currentText(), self.job_title_combobox.currentText(), self.mngr_line_edit.text(), self.org_unit_combobox.currentText(), self.psswd_line_edit.text(), self.change_psswd.checkState(), self.psswd_no_expire.checkState()) #Clear line edit before filling it self.create_powershell_command_result_line_edit.clear() self.create_powershell_command_result_line_edit.setText(command) def create_user(self): """Get create user command and create user""" command = self._controller.create_user_command(self.fn_line_edit.text(), self.sn_line_edit.text(), self.dn_line_edit.text(), self.pre2k_line_edit.text(), self.uln_line_edit.text(), self.company_combobox.currentText(), self.dept_combobox.currentText(), self.job_title_combobox.currentText(), self.mngr_line_edit.text(), self.org_unit_combobox.currentText(), self.psswd_line_edit.text(), self.change_psswd.checkState(), self.psswd_no_expire.checkState()) try: self._controller.create_user(command) except Exception as e: print(e)
class MiniViewer(QWidget): """MiniViewer that allows to rapidly visualize scans either with a single image per scan with cursors to move in five dimensions or with all images of the greater dimension of the scan. When the latter is selected, the displayed images depends on their dimension: - 3D: display all the slices. - 4D: display the middle slice of the third dimension for each time of the fourth dimension. - 5D: display the middle slice of the third dimension for the first time of the fourth dimension for each time of the fifth dimension. Note: - idx corresponds to the index of the displayed image - idx in [0, self.max_scans] - most of the class's attributes are lists of 0 to self.max_scans elements .. Methods: - __init__: initialise the MiniViewer object - boxSlider: create sliders, their connections and thumbnail labels for a selected index - changePosValue: change the value of a cursor for the selected index - check_box_cursors_state_changed: updates the config file - clearLayouts: clear the final layout - create_slider: create a slider - createDimensionLabels: create the dimension labels for the selected index - createFieldValue: create a field where will be displayed the position of a cursor - createLayouts: create the layouts - displayPosValue: display the position of each cursor for the selected index - enableSliders: enable each slider of the selected index - image_to_pixmap: create a 2D pixmap from a N-D Nifti image - image2DModifications: apply modifications to the image to display it correctly - indexImage: update the sliders values depending on the size of the selected image - navigImage: display the 2D image for the selected index - openTagsPopUp: opens a pop-up to select the legend of the thumbnails - setThumbnail: set the thumbnail tag value under the image frame - show_slices: create the thumbnails from the selected file paths - update_nb_slices: update the config file and the thumbnails - update_visualization_method: update the config file and the thumbnails - verify_slices: verify the number of selected documents """ def __init__(self, project): """Initialise the MiniViewer object :param project: current project in the software """ super().__init__() self.project = project self.first_time = True # The MiniViewer is set hidden to give more space to the data_browser self.setHidden(True) # When multiple selection, limiting the number of thumbnails to # max_scans self.max_scans = 4 # Config that allows to read the software preferences self.config = Config() # Initializing some components of the MiniViewer self.labels = QWidget() self.frame = QFrame() self.scroll_area = QScrollArea() self.scroll_area.setWidget(self.frame) self.frame_final = QFrame() self.label_nb_slices = QLabel() self.label_nb_slices.setText("Maximum number of slices: ") self.line_edit_nb_slices = QLineEdit() self.line_edit_nb_slices.setText(str(self.config.getNbAllSlicesMax())) self.line_edit_nb_slices.returnPressed.connect(self.update_nb_slices) # All these objects are depending on the number of scans to visualize self.im_2D = [] self.slider_3D = [] self.slider_4D = [] self.slider_5D = [] self.txt_slider_3D = [] self.txt_slider_4D = [] self.txt_slider_5D = [] self.label3D = [] self.label4D = [] self.label5D = [] self.imageLabel = [] self.img = [] self.label_description = [] # Layouts self.createLayouts() self.setLayout(self.v_box_final) # Checkboxes self.check_box_slices = QCheckBox('Show all slices (no cursors)') if self.config.getShowAllSlices() == True: self.check_box_slices.setCheckState(Qt.Checked) else: self.check_box_slices.setCheckState(Qt.Unchecked) self.check_box_slices.stateChanged.connect( self.update_visualization_method) self.check_box_cursors = QCheckBox('Chain cursors') self.check_box_cursors.setToolTip("Allows to connect all cursors " "when selecting multiple documents") if self.config.getChainCursors() == True: self.check_box_cursors.setCheckState(Qt.Checked) else: self.check_box_cursors.setCheckState(Qt.Unchecked) self.check_box_cursors.stateChanged.connect( self.check_box_cursors_state_changed) self.file_paths = "" def boxSlider(self, idx): """Define horizontal sliders connections and thumbnail labels. :param idx: the selected index """ self.slider_3D.insert(idx, self.create_slider(0, 0, 0)) self.slider_4D.insert(idx, self.create_slider(0, 0, 0)) self.slider_5D.insert(idx, self.create_slider(0, 0, 0)) self.slider_3D[idx].valueChanged.connect( partial(self.changePosValue, idx, 1)) self.slider_4D[idx].valueChanged.connect( partial(self.changePosValue, idx, 2)) self.slider_5D[idx].valueChanged.connect( partial(self.changePosValue, idx, 3)) self.txt_slider_3D.insert(idx, self.createFieldValue()) self.txt_slider_4D.insert(idx, self.createFieldValue()) self.txt_slider_5D.insert(idx, self.createFieldValue()) def check_box_cursors_state_changed(self): """Update the config file. Called when the state of the checkbox to chain the cursors changes. """ if self.check_box_cursors.checkState() == Qt.Checked: self.config.setChainCursors(True) elif self.check_box_cursors.checkState() == Qt.Unchecked: self.config.setChainCursors(False) def clearLayouts(self): """Clear the final layout""" for i in reversed(range(self.v_box_final.count())): if self.v_box_final.itemAt(i).widget() is not None: self.v_box_final.itemAt(i).widget().setParent(None) def changePosValue(self, idx, cursor_to_change): """ Change the value of a cursor for the selected index. :param idx: the selected index :param cursor_to_change: the cursor to change (1, 2 or 3) """ # If the "Chain cursors" mode is not selected, there is nothing to do if self.check_box_cursors.checkState() == Qt.Unchecked: self.navigImage(idx) else: # Checking with cursor has been modified if cursor_to_change == 1: cursor = self.slider_3D elif cursor_to_change == 2: cursor = self.slider_4D else: cursor = self.slider_5D # Loop on the thumbnails for idx_loop in range(min(self.max_scans, len(self.file_paths))): # Disconnecting the connection when changing other cursors # values cursor[idx_loop].valueChanged.disconnect() # Do something only when the cursor is not the one that has # been changed by the user if idx_loop != idx: if cursor[idx].value() == cursor[idx].maximum(): value = cursor[idx_loop].maximum() elif cursor[idx].value() == cursor[idx].minimum(): value = cursor[idx_loop].minimum() else: # Updating the new value as the value of the cursor # that has been changed by the user value = round((cursor[idx_loop].maximum() + 1) * (cursor[idx].value() + 1) / max(1, cursor[idx].maximum() + 1)) value = min(cursor[idx_loop].maximum(), value - 1) value = max(0, int(value)) cursor[idx_loop].setValue(value) # Changing the image to show self.navigImage(idx_loop) # Reconnecting cursor[idx_loop].valueChanged.connect( partial(self.changePosValue, idx_loop, cursor_to_change)) def createDimensionLabels(self, idx): """Create the dimension labels for the selected index. :param idx: the selected index """ font = QFont() font.setPointSize(9) self.label3D.insert(idx, QLabel()) self.label4D.insert(idx, QLabel()) self.label5D.insert(idx, QLabel()) self.label3D[idx].setFont(font) self.label4D[idx].setFont(font) self.label5D[idx].setFont(font) self.label3D[idx].setText('3D: ') self.label4D[idx].setText('4D: ') self.label5D[idx].setText('5D: ') def createFieldValue(self): """Create a field where will be displayed the position of a cursor. :return: the corresponding field """ fieldValue = QLineEdit() fieldValue.setEnabled(False) fieldValue.setFixedWidth(50) fieldValue.setAlignment(Qt.AlignCenter) fieldValue.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) font = QFont() font.setPointSize(9) fieldValue.setFont(font) return fieldValue def createLayouts(self): """Create the layouts.""" self.h_box_images = QHBoxLayout() self.h_box_images.setSpacing(10) self.v_box = QVBoxLayout() self.v_box_final = QVBoxLayout() self.h_box_slider_3D = QHBoxLayout() self.h_box_slider_4D = QHBoxLayout() self.h_box_slider_5D = QHBoxLayout() self.v_box_sliders = QVBoxLayout() self.h_box = QHBoxLayout() self.h_box_check_box = QHBoxLayout() self.v_box_thumb = QVBoxLayout() self.h_box_thumb = QHBoxLayout() def create_slider(self, maxm=0, minm=0, pos=0): """Generate an horizontal slider. :param maxm: slider's maximum :param minm: slider's minimum :param pos: slider's initial value :return: the slider object """ slider = QSlider(Qt.Horizontal) slider.setFocusPolicy(Qt.StrongFocus) slider.setTickInterval(1) slider.setMaximum(maxm) slider.setMinimum(minm) slider.setValue(pos) slider.setEnabled(False) return slider def displayPosValue(self, idx): """Display the position of each cursor for the selected index. :param idx: the selected index """ self.txt_slider_3D[idx].setText( str(self.slider_3D[idx].value() + 1) + ' / ' + str(self.slider_3D[idx].maximum() + 1)) self.txt_slider_4D[idx].setText( str(self.slider_4D[idx].value() + 1) + ' / ' + str(self.slider_4D[idx].maximum() + 1)) self.txt_slider_5D[idx].setText( str(self.slider_5D[idx].value() + 1) + ' / ' + str(self.slider_5D[idx].maximum() + 1)) def enableSliders(self, idx): """Enable all the horizontal slider. :param idx: the slider's index """ self.slider_3D[idx].setEnabled(True) self.slider_4D[idx].setEnabled(True) self.slider_5D[idx].setEnabled(True) def image_to_pixmap(self, im, i): """Create a 2D pixmap from a N-D Nifti image. :param im: Nifti image :param i: index of the slide :return: the corresponding pixmap """ # The image to display depends on the dimension of the image # In the 3D case, each slice is displayed if len(im.shape) == 3: im_2D = im.get_data()[:, :, i].copy() # In the 4D case, each middle slice of the 3D dimension is displayed # for each time in the 4D dimension elif len(im.shape) == 4: im_3D = im.get_data()[:, :, :, i].copy() middle_slice = int(im_3D.shape[2] / 2) im_2D = im_3D[:, :, middle_slice] # In the 5D case, each first time of the 4D dimension and # its middle slice of the 3D dimension is displayed elif len(im.shape) == 5: im_4D = im.get_data()[:, :, :, :, i].copy() im_3D = im_4D[:, :, :, 1] middle_slice = int(im_3D.shape[2] / 2) im_2D = im_3D[:, :, middle_slice] else: im_2D = [0] # Making some pixel modification to display the image correctly im_2D = self.image2DModifications(0, im_2D) w, h = im_2D.shape im_Qt = QImage(im_2D.data, w, h, QImage.Format_Indexed8) pixm = QPixmap.fromImage(im_Qt) return pixm def image2DModifications(self, idx, im2D=None): """Apply modifications to display the image correctly. :param idx: the selected index :param im2D: image to modify """ display_size = (128, 128) display_type = np.uint8 # this MUST be an integer data type display_pctl = 0.5 # percentile (0.5%) of values to clip at the low and high end of intensities. display_max = np.iinfo(display_type).max display_min = np.iinfo(display_type).min im2d_provided = im2D is not None if not im2d_provided: im2D = self.im_2D[idx] # Resize image first, for three reasons: # 1 - it may slightly changes the intensity scale, so re-scaling should be done after this # 2 - rescaling before rotation is slightly faster, specially for large images (> display_size). # 3 - rescaling may alter the occurrence of nan or infinite values (e.g. an image may become all-nan) # anti_aliasing keyword is defined in skimage since version 0.14.0 if verCmp(sk.__version__, '0.14.0', 'sup'): im2D = resize(im2D, display_size, mode='constant', anti_aliasing=False) else: im2D = resize(im2D, display_size, mode='constant') # Rescale image while handling Nans and infinite values im_mask = np.isfinite(im2D) if np.any(im_mask): # if we have any finite value to work with im2D -= np.percentile( im2D[im_mask], display_pctl) # shift the lower percentile chosen to 0.0 im_max = np.percentile( im2D[im_mask], 100.0 - display_pctl) # determine max from upper percentile if im_max > 0: # avoid dividing by zero im2D *= (display_max - display_min) / im_max # re-scale to display range im2D += display_min # shift lowest value to lower limit of display range np.clip( im2D, display_min, display_max, im2D) # clip all values to display range, remove infinite values im2D = im2D.astype( display_type ) # convert to integer display data type. NaNs get converted to 0. im2D = np.rot90(im2D, 3).copy( ) # Rotate. Copy array to avoid negative strides (Qt doesn't handle that) if im2d_provided: return im2D else: self.im_2D[idx] = im2D def indexImage(self, idx): """Update all slider values according to the size of the current image. :param idx: the selected index """ # Getting the sliders value sl3D = self.slider_3D[idx].value() sl4D = self.slider_4D[idx].value() sl5D = self.slider_5D[idx].value() # Depending on the dimension, reading the image data and # changing the cursors maximum if len(self.img[idx].shape) == 3: self.im_2D.insert(idx, self.img[idx].get_data()[:, :, sl3D].copy()) self.slider_3D[idx].setMaximum(self.img[idx].shape[2] - 1) self.slider_4D[idx].setMaximum(0) self.slider_5D[idx].setMaximum(0) if len(self.img[idx].shape) == 4: self.im_2D.insert( idx, self.img[idx].get_data()[:, :, sl3D, sl4D].copy()) self.slider_3D[idx].setMaximum(self.img[idx].shape[2] - 1) self.slider_4D[idx].setMaximum(self.img[idx].shape[3] - 1) self.slider_5D[idx].setMaximum(0) if len(self.img[idx].shape) == 5: self.im_2D.insert( idx, self.img[idx].get_data()[:, :, sl3D, sl4D, sl5D].copy()) self.slider_3D[idx].setMaximum(self.img[idx].shape[2] - 1) self.slider_4D[idx].setMaximum(self.img[idx].shape[3] - 1) self.slider_5D[idx].setMaximum(self.img[idx].shape[4] - 1) def navigImage(self, idx): """Display the 2D image for the selected index. :param idx: the selected index """ self.indexImage(idx) self.displayPosValue(idx) self.image2DModifications(idx) w, h = self.im_2D[idx].shape image = QImage(self.im_2D[idx].data, w, h, QImage.Format_Indexed8) pixm = QPixmap.fromImage(image) self.imageLabel[idx].setPixmap(pixm) def openTagsPopUp(self): """Open a pop-up to select the legend of the thumbnails.""" self.popUp = PopUpSelectTag(self.project) self.popUp.setWindowTitle("Select the image viewer tag") if self.popUp.exec_(): self.verify_slices(self.file_paths) def setThumbnail(self, file_path_base_name, idx): """Set the thumbnail tag value under the image frame. :param file_path_base_name: basename of the selected path :param idx: index of the image """ # Looking for the tag value to display as a legend of the thumbnail for scan in self.project.session.get_documents_names( COLLECTION_CURRENT): if scan == file_path_base_name: value = self.project.session.get_value( COLLECTION_CURRENT, scan, self.config.getThumbnailTag()) if value is not None: self.label_description[idx].setText( str(value)[:self.nb_char_max]) else: self.label_description[idx].setText( data_browser.not_defined_value[:self.nb_char_max]) self.label_description[idx].setToolTip( os.path.basename(self.config.getThumbnailTag())) def show_slices(self, file_paths): """Creates the thumbnails from the selected file paths. :param file_paths: the selected file paths """ # If it's the first time that this function is called, the MiniViewer # has to be shown if self.first_time: self.setHidden(False) self.first_time = False # If the user has willingly hidden the MiniViewer, the Processes are # not made if self.isHidden(): pass else: self.do_nothing = [False] * len(file_paths) self.file_paths = file_paths self.max_scans = len(file_paths) self.setMinimumHeight(220) self.clearLayouts() self.frame = QFrame(self) self.frame_final = QFrame(self) # Limiting the legend of the thumbnails self.nb_char_max = 60 font = QFont() font.setPointSize(9) # Reading the images from the file paths for idx, file_path in enumerate(self.file_paths.copy()): try: self.img.insert(idx, nib.load(file_path)) except nib.filebasedimages.ImageFileError: print("Error while trying to display the image " + file_path) self.file_paths.remove(file_path) except FileNotFoundError: print("File " + file_path + " not existing") self.file_paths.remove(file_path) # If we are in the "cursors" display mode if self.check_box_slices.checkState() == Qt.Unchecked: # Layout to aligne each thumbnail (image + cursors) self.h_box_thumb = QHBoxLayout() # idx represents the index of the selected image for idx in range(min(self.max_scans, len(self.file_paths))): if not self.do_nothing[idx]: # Creating sliders and labels self.boxSlider(idx) self.enableSliders(idx) self.createDimensionLabels(idx) # Getting the sliders value and reading the image data self.indexImage(idx) # Making some pixel modification to display the image # correctly self.image2DModifications(idx) self.displayPosValue(idx) w, h = self.im_2D[idx].shape im_Qt = QImage(self.im_2D[idx].data, w, h, QImage.Format_Indexed8) pixm = QPixmap.fromImage(im_Qt) file_path_base_name = os.path.basename( self.file_paths[idx]) # imageLabel is the label where the image is displayed # (as a pixmap) self.imageLabel.insert(idx, QLabel(self)) self.imageLabel[idx].setPixmap(pixm) self.imageLabel[idx].setToolTip(file_path_base_name) self.label_description.insert(idx, ClickableLabel()) self.label_description[idx].setFont(font) self.label_description[idx].clicked.connect( self.openTagsPopUp) # Looking for the tag value to display as a # legend of the thumbnail file_path_base_name = os.path.relpath( self.file_paths[idx], self.project.folder) self.setThumbnail(file_path_base_name, idx) # Layout that corresponds to the 3D dimension self.h_box_slider_3D = QHBoxLayout() self.h_box_slider_3D.addWidget(self.label3D[idx]) self.h_box_slider_3D.addWidget(self.txt_slider_3D[idx]) self.h_box_slider_3D.addWidget(self.slider_3D[idx]) # Layout that corresponds to the 4D dimension self.h_box_slider_4D = QHBoxLayout() self.h_box_slider_4D.addWidget(self.label4D[idx]) self.h_box_slider_4D.addWidget(self.txt_slider_4D[idx]) self.h_box_slider_4D.addWidget(self.slider_4D[idx]) # Layout that corresponds to the 5D dimension self.h_box_slider_5D = QHBoxLayout() self.h_box_slider_5D.addWidget(self.label5D[idx]) self.h_box_slider_5D.addWidget(self.txt_slider_5D[idx]) self.h_box_slider_5D.addWidget(self.slider_5D[idx]) # Layout for the three sliders self.v_box_sliders = QVBoxLayout() self.v_box_sliders.addLayout(self.h_box_slider_3D) self.v_box_sliders.addLayout(self.h_box_slider_4D) self.v_box_sliders.addLayout(self.h_box_slider_5D) # Layout that corresponds to the image + the sliders self.h_box = QHBoxLayout() self.h_box.addWidget(self.imageLabel[idx]) self.h_box.addLayout(self.v_box_sliders) # Layout that corresponds to the image and sliders + # the description self.v_box_thumb = QVBoxLayout() self.v_box_thumb.addLayout(self.h_box) self.v_box_thumb.addWidget(self.label_description[idx]) # Layout that will contain all the thumbnails self.h_box_thumb.addLayout(self.v_box_thumb) self.frame.setLayout(self.h_box_thumb) # If we are in the "all slices" display mode else: self.h_box_images = QHBoxLayout() self.h_box_images.setSpacing(10) self.v_box_scans = QVBoxLayout() # idx represents the index of the selected image for idx in range(len(self.file_paths)): file_path_base_name = os.path.relpath( self.file_paths[idx], self.project.folder) self.label_description.insert(idx, ClickableLabel()) self.label_description[idx].setFont(font) self.label_description[idx].clicked.connect( self.openTagsPopUp) # Looking for the tag value to display as a legend # of the thumbnail self.setThumbnail(file_path_base_name, idx) # Depending of the dimension of the image, # the legend of each image and the number of images to # display will change if not self.do_nothing[idx]: if len(self.img[idx].shape) == 3: nb_slices = self.img[idx].shape[2] txt = "Slice n°" elif len(self.img[idx].shape) == 4: nb_slices = self.img[idx].shape[3] txt = "Time n°" elif len(self.img[idx].shape) == 5: nb_slices = self.img[idx].shape[4] txt = "Study n°" else: nb_slices = 0 # Limiting the number of images to the number # chosen by the user for i in range( min(nb_slices, int(self.line_edit_nb_slices.text()))): pixm = self.image_to_pixmap(self.img[idx], i) self.v_box = QVBoxLayout() # label corresponds to the label where one image # is displayed label = QLabel(self) label.setPixmap(pixm) label.setToolTip( os.path.basename(self.file_paths[idx])) # Legend of the image (depends on the number # of dimensions) label_info = QLabel() label_info.setFont(font) label_info.setText(txt + str(i + 1)) label_info.setAlignment(QtCore.Qt.AlignCenter) self.v_box.addWidget(label) self.v_box.addWidget(label_info) # This layout allows to chain each image self.h_box_images.addLayout(self.v_box) self.v_box_scans.addLayout(self.h_box_images) self.v_box_scans.addWidget(self.label_description[idx]) self.frame.setLayout(self.v_box_scans) # Adding a scroll area if the thumbnails are too large self.scroll_area = QScrollArea() self.scroll_area.setWidget(self.frame) self.h_box_check_box = QHBoxLayout() if self.check_box_slices.isChecked(): self.h_box_check_box.addStretch(1) self.label_nb_slices.setHidden(False) self.line_edit_nb_slices.setHidden(False) self.h_box_check_box.addWidget(self.label_nb_slices) self.h_box_check_box.addWidget(self.line_edit_nb_slices) self.check_box_cursors.setHidden(True) else: self.check_box_cursors.setHidden(False) self.h_box_check_box.addWidget(self.check_box_cursors) self.h_box_check_box.addStretch(1) self.label_nb_slices.setHidden(True) self.line_edit_nb_slices.setHidden(True) self.h_box_check_box.addWidget(self.check_box_slices) self.v_box_final.addLayout(self.h_box_check_box) self.v_box_final.addWidget(self.scroll_area) def update_nb_slices(self): """Update the config file and the thumbnails. Called when the number of slices to visualize changes. """ nb_slices = self.line_edit_nb_slices.text() self.config.setNbAllSlicesMax(nb_slices) self.verify_slices(self.file_paths) def update_visualization_method(self): """Update the config file and the thumbnails. Called when the state of the checkbox to show all slices changes. """ if self.check_box_slices.checkState() == Qt.Checked: self.config.setShowAllSlices(True) elif self.check_box_slices.checkState() == Qt.Unchecked: self.config.setShowAllSlices(False) self.verify_slices(self.file_paths) def verify_slices(self, file_paths): """Make 'Show all slices' checkbox unclickable if len(file_paths) > 1. :param file_paths: the selected documents """ # Updating the config self.config = Config() if len(file_paths) > 1: self.config.setShowAllSlices(False) self.check_box_slices.setCheckState(Qt.Unchecked) self.check_box_slices.setCheckable(False) else: self.check_box_slices.setCheckable(True) self.show_slices(file_paths)
class MikochikuAlarm(QWidget): def __init__(self, parent=None): QWidget.__init__(self, parent) self.search_ch_id = settings.CHID self.old_video_id_list = [] self.initUI() def initUI(self): self.timer = QTimer(self) self.timer.timeout.connect(self.check_live) self.timer.setInterval(40000) self.timer.start() label = QLabel(self) label.setPixmap(QPixmap(resource_path(settings.ICON))) label.move(60, 70) self.language_cmb = QComboBox(self) self.language_cmb.move(180, 122) self.language_cmb.addItem("language") self.language_cmb.addItem("日本語") self.language_cmb.addItem("中文") self.language_cmb.addItem("English") self.language_cmb.currentTextChanged.connect(self.on_combobox_changed) self.alarm_cb = QCheckBox( self.get_text(self.get_locale_json(), "alarm"), self) self.alarm_cb.move(20, 20) self.alarm_cb.toggle() # self.loop_cb = QCheckBox('アラームをループ再生する', self) # self.loop_cb.move(20, 40) # self.loop_cb.toggle() self.webbrowser_cb = QCheckBox( self.get_text(self.get_locale_json(), "webbrowser"), self) self.webbrowser_cb.move(20, 40) self.webbrowser_cb.toggle() self.alarm_stop = QPushButton( self.get_text(self.get_locale_json(), "waiting"), self) # self.alarm_stop.setCheckable(True) # self.alarm_stop.setEnabled(False) self.alarm_stop.move(80, 80) self.alarm_stop.clicked[bool].connect(self.stop_alarm) self.setGeometry(300, 300, 250, 150) self.setWindowTitle(self.get_text(self.get_locale_json(), "title")) self.show() def check_live(self): buff_video_id_set = self.get_live_video_id(self.search_ch_id) print("buff_video_id_set", buff_video_id_set) print("self.old_video_id_list", self.old_video_id_list) if buff_video_id_set: for getting_video_id in buff_video_id_set: if not getting_video_id == "" and not getting_video_id is None: if not getting_video_id in self.old_video_id_list: self.old_video_id_list.append(getting_video_id) if len(self.old_video_id_list) > 30: self.old_video_id_list = self.old_video_id_list[1:] print("") print(self.get_text(self.get_locale_json(), "started")) # self.alarm_stop.setEnabled(False) self.alarm_stop.click() self.alarm_stop.setText( self.get_text(self.get_locale_json(), "stop")) if self.webbrowser_cb.checkState(): webbrowser.open( "https://www.youtube.com/watch?v=" + getting_video_id) if self.alarm_cb.checkState(): self.alarm_sound() def stop_alarm(self): pygame.mixer.music.stop() self.alarm_stop.setEnabled(True) self.alarm_stop.setText( self.get_text(self.get_locale_json(), "waiting")) def alarm_sound(self): # loop = 1 # if self.loop_cb.checkState(): loop_count = 5 pygame.mixer.music.play(loop_count) pygame.mixer.music.play(loop_count) def get_live_video_id(self, search_ch_id): dict_str = "" video_id_set = set() try: session = requests.Session() headers = { 'user-agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36' } html = session.get("https://www.youtube.com/channel/" + search_ch_id, headers=headers, timeout=10) soup = BeautifulSoup(html.text, 'html.parser') keyword = 'window["ytInitialData"]' for scrp in soup.find_all("script"): if keyword in str(scrp): dict_str = str(scrp).split(' = ', 1)[1] dict_str = dict_str.replace('false', 'False') dict_str = dict_str.replace('true', 'True') index = dict_str.find("\n") dict_str = dict_str[:index - 1] dics = eval(dict_str) for section in dics.get("contents", {}).get( "twoColumnBrowseResultsRenderer", {}).get("tabs", {})[0].get("tabRenderer", {}).get("content", {}).get("sectionListRenderer", {}).get("contents", {}): for itemsection in section.get("itemSectionRenderer", {}).get("contents", {}): items = {} if "shelfRenderer" in itemsection: for items in itemsection.get("shelfRenderer", {}).get("content", {}).values(): for item in items.get("items", {}): for videoRenderer in item.values(): for badge in videoRenderer.get( "badges", {}): if badge.get( "metadataBadgeRenderer", {}).get( "style", {} ) == "BADGE_STYLE_TYPE_LIVE_NOW": video_id_set.add( videoRenderer.get( "videoId", "")) elif "channelFeaturedContentRenderer" in itemsection: for item in itemsection.get( "channelFeaturedContentRenderer", {}).get("items", {}): for badge in item.get("videoRenderer", {}).get("badges", {}): if badge.get("metadataBadgeRenderer", {}).get( "style", "") == "BADGE_STYLE_TYPE_LIVE_NOW": video_id_set.add( item.get("videoRenderer", {}).get("videoId", "")) except: return video_id_set return video_id_set def on_combobox_changed(self): self.set_locale(self.get_locale_cmb()) print(self.get_locale_json()) def get_locale_json(self): path = ".\\lang\\locale.json" with open(path, mode='r') as file: dict_json = json.load(file) return dict_json["locale"] def get_locale_cmb(self): if self.language_cmb.currentText() == "日本語": return "ja_JP" elif self.language_cmb.currentText() == "中文": return "zh_CN" elif self.language_cmb.currentText() == "English": return "en_US" def set_locale(self, locale): path = ".\\lang\\locale.json" with open(path, mode='r') as file: dict_json = json.load(file) dict_json["locale"] = locale with open(path, mode='w') as file: json.dump(dict_json, file) def get_text(self, locale, content): path = ".\\lang\\" + locale + ".json" with open(path, encoding="UTF-8") as file: dict_json = json.load(file) print(dict_json[content]) return dict_json[content]
class DialogGenerateDojoFolder(QDialog): def __init__(self, parent, u_info): super().__init__() self.parent = parent self.u_info = u_info self.title = 'Create Dojo Folder' self.left = 200 self.top = 200 self.width = 700 self.height = 150 self.initUI() def initUI(self): lbl = [0, 0, 0] self.edit = [0, 0, 0] btn = [0, 0, 0] content = _GenerateContents(self) for i in range(3): lbl[i], self.edit[i], btn[i] = content.generate(i) ok_import = QPushButton("OK") cl_import = QPushButton("Cancel") ok_import.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) cl_import.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) ok_import.clicked.connect(self._ExecuteImport) cl_import.clicked.connect(self._Cancel) self.em_only = QCheckBox('Use blank segmentation') self.edit[1].setEnabled(self.em_only.checkState() == Qt.Unchecked) self.em_only.stateChanged.connect(self._CheckEMOnly) layout = QGridLayout() for i in range(3): layout.addWidget(lbl[i], i, 0) layout.addWidget(self.edit[i], i, 1, 1, 2) layout.addWidget(btn[i], i, 3) layout.addWidget(self.em_only, 3, 1, alignment=(Qt.AlignLeft)) layout.addWidget(ok_import, 3, 2, alignment=(Qt.AlignRight)) layout.addWidget(cl_import, 3, 3) self.setLayout(layout) self.setGeometry(self.left, self.top, self.width, self.height) self.setWindowTitle(self.title) self.setWindowIcon(QIcon(path.join(icon_dir, 'Mojo2_16.png'))) p = self.palette() p.setColor(self.backgroundRole(), Qt.white) self.setPalette(p) self.show() def _CheckEMOnly(self): self.edit[1].setEnabled(self.em_only.isChecked() == Qt.Unchecked) # if self.em_only.isChecked() == Qt.Unchecked: # self.edit2.setEnabled(True) # else: # self.edit2.setEnabled(False) def _ExecuteImport(self): # wxGlade: ImportImagesSegments.<event_handler> dir_input_images = self.edit[0].currentText() dir_input_ids = self.edit[1].currentText() dir_dojo = self.edit[2].currentText() self.u_info.SetUserInfo(dir_dojo) if len(dir_input_images) == 0: print('No input image.') return ## if (self.em_only.isChecked() == Qt.Unchecked) and (len(dir_input_ids) != 0): ## im = ImportImgSeg(self.u_info) Flag1 = im.images(dir_input_images) ### Flag2 = im.ids(dir_input_ids) ### #print(Flag1) #print(Flag2) if Flag1 == False or Flag2 == False: print('Error! Dojo files were not created.') self.close() return False print('Dojo files were successfully created.') ## File system update self._UpdateFileSystem(dir_dojo) self.close() ## else: ## im = ImportImgSeg(self.u_info) Flag1 = im.images(dir_input_images) ### Flag2 = im.ids_dummy(dir_input_images) ### #print(Flag1) #print(Flag2) if Flag1 == False or Flag2 == False: print('Error! Dojo files were not created.') self.close() return False print('Dojo files were successfully created.') ## File system update self._UpdateFileSystem(dir_dojo) ## self.close() ## self.close() return False def _Cancel(self): # wxGlade: ImportImagesSegments.<event_handler> self.close() return False def _UpdateFileSystem(self, dir_dojo): # Release m.UnlockFolder(self.u_info, dir_dojo) # Lock again m.LockFolder(self.u_info, dir_dojo) # Filetype self.u_info.open_files_type[dir_dojo] = 'Dojo' # Dropdown menu update self.parent.UpdateOpenFileMenu() # Combo box update SyncListQComboBoxExcludeDojoMtifManager.get().removeModel(dir_dojo) SyncListQComboBoxOnlyDojoManager.get().addModel(dir_dojo)
class ImgScaleView(QWidget): def __init__(self): super().__init__() self.initUI() self.defaultView() self.reloadUI() self.funType = -1 def defaultView(self): self.setWindowFlags(QtCore.Qt.WindowTitleHint | QtCore.Qt.WindowCloseButtonHint) self.resize(viewWid, viewHei) self.setFixedSize(viewWid, viewHei) self.setStyleSheet('background-color:#fff') self.center() self.setWindowTitle(zfjTools.baseTitle) def initUI(self): font = QtGui.QFont() font.setPointSize(18) margin_top = margin_size titleLab = QLabel('图片压缩工具', self) titleLab.setStyleSheet('color:#d4237a;') titleLab.setAlignment(Qt.AlignCenter) titleLab.setGeometry( QtCore.QRect(margin_size, margin_top, viewWid - margin_size * 2, 40)) titleLab.setFont(font) backMainViewBtn = QtWidgets.QPushButton(self) backMainViewBtn.setGeometry( QtCore.QRect(margin_size, margin_top + 7.5, 50, 25)) backMainViewBtn.setObjectName('logInBtn') backMainViewBtn.setText(_translate('MainWindow', '返回')) backMainViewBtn.setStyleSheet( 'color:#1667ea;background-color:#fff;border:1px solid #1667ea;') backMainViewBtn.clicked.connect(self.backMainViewBtnClick) font.setPointSize(14) backMainViewBtn.setFont(font) margin_top += 40 + margin_size oldImgLab = QLabel('请选择图片所在路径:', self) oldImgLab.setStyleSheet('color:#000000;') oldImgLab.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) oldImgLab.setGeometry(QtCore.QRect(margin_size, margin_top, 135, 30)) font.setPointSize(14) oldImgLab.setFont(font) self.oldImgEdit = QtWidgets.QLineEdit(self) self.oldImgEdit.setGeometry( QtCore.QRect(135 + margin_size * 2, margin_top, 350, 30)) font.setPointSize(14) self.oldImgEdit.setFont(font) self.oldImgEdit.setText('/Users/zhangfujie/Desktop/Obfuscated') oldImgPathBtn = QtWidgets.QPushButton(self) oldImgPathBtn.setGeometry( QtCore.QRect(margin_size * 3 + 135 + 350, margin_top, 100, 30)) oldImgPathBtn.setText(_translate('MainWindow', '选择文件夹')) oldImgPathBtn.setStyleSheet( 'color:#000000;background-color:#efeff3;border:1px solid #efeff3;') oldImgPathBtn.clicked.connect(self.oldImgPathBtnClick) oldImgPathBtn.setFont(font) margin_top += 30 + margin_size newImgLab = QLabel('请选择图片保存路径:', self) newImgLab.setStyleSheet('color:#000000;') newImgLab.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) newImgLab.setGeometry(QtCore.QRect(margin_size, margin_top, 135, 30)) font.setPointSize(14) newImgLab.setFont(font) self.newImgEdit = QtWidgets.QLineEdit(self) self.newImgEdit.setGeometry( QtCore.QRect(135 + margin_size * 2, margin_top, 350, 30)) font.setPointSize(14) self.newImgEdit.setFont(font) self.newImgEdit.setText('/Users/zhangfujie/Desktop/Obfuscated/NewImgs') newImgPathBtn = QtWidgets.QPushButton(self) newImgPathBtn.setGeometry( QtCore.QRect(margin_size * 3 + 135 + 350, margin_top, 100, 30)) newImgPathBtn.setText(_translate('MainWindow', '选择文件夹')) newImgPathBtn.setStyleSheet( 'color:#000000;background-color:#efeff3;border:1px solid #efeff3;') newImgPathBtn.clicked.connect(self.newImgPathBtnClick) newImgPathBtn.setFont(font) margin_top += 30 + margin_size line_lab = QLabel(self) line_lab.setStyleSheet('background-color:#dcdcdc') line_lab.setGeometry(QtCore.QRect(0, margin_top, viewWid, 1)) margin_top += 1 + margin_size smlTitLab = QLabel('请选择图片压缩方式', self) smlTitLab.setStyleSheet('color:#d4237a;') smlTitLab.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) smlTitLab.setGeometry(QtCore.QRect(margin_size, margin_top, 135, 30)) smlTitLab.setFont(font) textEditWid = (viewWid - margin_size * 3) / 2 self.textEdit = QTextEdit(self) self.textEdit.setStyleSheet('background-color:#262626;color:#fff;') self.textEdit.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) self.textEdit.setGeometry( QtCore.QRect(textEditWid - margin_size * 5, margin_top, textEditWid + margin_size * 6, 411 - margin_top)) font.setPointSize(12) self.textEdit.setFont(font) margin_top += 30 + margin_size self.sysBtn = QRadioButton('自动生成@1x,@2x,@3x', self) self.sysBtn.setStyleSheet('color:#000;') self.sysBtn.setGeometry( QtCore.QRect(margin_size * 2, margin_top, 200, 30)) self.sysBtn.setChecked(False) self.sysBtn.toggled.connect(lambda: self.radioBtnClick(self.sysBtn)) margin_top += 30 + margin_size self.userBtn = QRadioButton('手动设置图片尺寸(格式:宽x高)', self) self.userBtn.setStyleSheet('color:#000;') self.userBtn.setGeometry( QtCore.QRect(margin_size * 2, margin_top, 200, 30)) self.userBtn.setChecked(False) self.userBtn.toggled.connect(lambda: self.radioBtnClick(self.userBtn)) titleArr = ['@1x尺寸:', '@2x尺寸:', '@3x尺寸:'] self.checkBoxList = [] self.checkBoxEditList = [] for index in range(0, 3): margin_top += 30 + margin_size checkBox = QCheckBox(titleArr[index], self) checkBox.setStyleSheet('color:#000;') checkBox.stateChanged.connect(self.checkBoxClick) checkBox.setGeometry( QtCore.QRect(margin_size * 4, margin_top, 80, 30)) self.checkBoxList.append(checkBox) checkBoxEdit = QtWidgets.QLineEdit(self) checkBoxEdit.setText('0x0') checkBoxEdit.setGeometry( QtCore.QRect(margin_size * 4 + 80, margin_top, 200 - (margin_size * 4 + 80) + margin_size * 2, 30)) checkBoxEdit.setFont(font) checkBoxEdit.setStyleSheet( 'color:#cc0066;background-color:#efeff3;') checkBoxEdit.textChanged.connect( lambda: self.checkBoxEditChanged(index)) self.checkBoxEditList.append(checkBoxEdit) margin_top += 30 + margin_size self.alphaCheckBox = QCheckBox('移除PNG的alpha通道', self) self.alphaCheckBox.setStyleSheet('color:#000;') self.alphaCheckBox.stateChanged.connect(self.checkBoxClick) self.alphaCheckBox.setGeometry( QtCore.QRect(margin_size * 2, margin_top, 200, 30)) margin_top += 30 + margin_size self.imgTypeBox = QCheckBox('webp', self) self.imgTypeBox.setStyleSheet('color:#000;') self.imgTypeBox.stateChanged.connect(self.checkBoxClick) self.imgTypeBox.setGeometry( QtCore.QRect(margin_size * 2, margin_top, 200, 30)) margin_top += 30 + margin_size * 5 startScaleBtn = QtWidgets.QPushButton(self) startScaleBtn.setGeometry( QtCore.QRect((viewWid - 160) / 2, margin_top, 160, 40)) startScaleBtn.setText(_translate('MainWindow', '开始压缩')) startScaleBtn.setStyleSheet( 'background-color:#fff;color:#cc0066;border:1px solid #cc0066;') startScaleBtn.clicked.connect(self.startScaleBtnClick) font.setPointSize(18) startScaleBtn.setFont(font) margin_top += 40 + margin_size * 2 tipsTitLab = QLabel('使用须知', self) tipsTitLab.setStyleSheet('color:#d4237a;') tipsTitLab.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) tipsTitLab.setGeometry( QtCore.QRect(margin_size, margin_top, viewWid - margin_size * 2, 30)) font.setPointSize(14) tipsTitLab.setFont(font) margin_top += 30 tipsLabText = '1.选择自动生成@1x、@2x、@3x时,默认把原图作为@3x, @1x和@2x在此基础上向下压缩;\n2.选择手动设置图片尺寸时,为了保证图片的清晰质量,原图尺寸最好大于等于三倍尺寸;' tipsLab = QLabel(tipsLabText, self) tipsLab.setStyleSheet('color:#87b753;') tipsLab.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) tipsLab.setGeometry( QtCore.QRect(margin_size, margin_top, viewWid - margin_size * 2, 50)) font.setPointSize(12) tipsLab.setFont(font) margin_top += 50 + margin_size line_lab_1 = QLabel(self) line_lab_1.setStyleSheet('background-color:#dcdcdc') line_lab_1.setGeometry(QtCore.QRect(0, margin_top, viewWid, 1)) margin_top += 1 + margin_size downLab_wid = (viewWid - margin_size * 3) / 2 self.accountLab = QLabel(':', self) self.accountLab.setStyleSheet('color:#000;') self.accountLab.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) self.accountLab.setGeometry( QtCore.QRect(margin_size, margin_top, downLab_wid, 30)) font.setPointSize(13) self.accountLab.setFont(font) self.timeLab = QLabel(':', self) self.timeLab.setStyleSheet('color:#000;') self.timeLab.setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.timeLab.setGeometry( QtCore.QRect(margin_size * 2 + downLab_wid, margin_top, downLab_wid, 30)) font.setPointSize(13) self.timeLab.setFont(font) margin_top += 30 + margin_size def backMainViewBtnClick(self): personinfo = ZFJPersoninfo() if personinfo.mainRootView != None: personinfo.mainRootView.show() self.close() else: print('mainRootView') def oldImgPathBtnClick(self): file_dir = '' try: file_dir = QFileDialog.getExistingDirectory( self, 'open file', '/Users/') except Exception as e: try: file_dir = ',' finally: e = None del e self.oldImgEdit.setText(file_dir) def newImgPathBtnClick(self): file_dir = '' try: file_dir = QFileDialog.getExistingDirectory( self, 'open file', '/Users/') except Exception as e: try: file_dir = ',' finally: e = None del e self.newImgEdit.setText(file_dir) def radioBtnClick(self, btn): if self.sysBtn.isChecked() == True: self.funType = 0 for checkBox in self.checkBoxList: checkBox.setCheckState(Qt.Unchecked) for checkBoxEdit in self.checkBoxEditList: checkBoxEdit.setText('') else: self.funType = 1 for checkBox in self.checkBoxList: checkBox.setCheckState(Qt.Checked) def checkBoxClick(self): if self.sysBtn.isChecked() == True or self.funType == -1: for checkBox in self.checkBoxList: checkBox.setCheckState(Qt.Unchecked) def checkBoxEditChanged(self, index): if self.sysBtn.isChecked() == True or self.funType == -1: for checkBoxEdit in self.checkBoxEditList: checkBoxEdit.setText('0x0') def startScaleBtnClick(self): oldImgPath = self.oldImgEdit.text() if len(oldImgPath) == 0: self.megBoxInfor('') return if os.path.exists(oldImgPath) == False: self.megBoxInfor('') return newImgPath = self.newImgEdit.text() if len(newImgPath) == 0: self.megBoxInfor('') return if os.path.exists(newImgPath) == False: self.megBoxInfor('') return sizeTupList = None if self.funType == 1: checkCount = 0 for checkBox in self.checkBoxList: if checkBox.checkState() == Qt.Checked: checkCount += 1 continue if checkCount == 0: self.megBoxInfor('') return titleArr = ['@1x', '@2x', '@3x'] for index in range(0, len(self.checkBoxEditList)): checkBox = self.checkBoxList[index] checkBoxEdit = self.checkBoxEditList[index] checkBoxEditText = checkBoxEdit.text().replace('X', 'x') if checkBox.checkState() == Qt.Checked: if 'x' not in checkBoxEditText: self.megBoxInfor('' + titleArr[index] + '(:100x100)') return if zfjTools.is_number(checkBoxEditText.replace( 'x', '')) == False: self.megBoxInfor('' + titleArr[index] + '(:100x100)') return width = checkBoxEditText[:checkBoxEditText.find('x')] if len(width) == 0: width = '0' height = checkBoxEditText[checkBoxEditText.find('x') + 1:] if len(height) == 0: height = '0' if int(width) <= 0: self.megBoxInfor(titleArr[index] + '<=0(:100x100)') return if int(height) <= 0: self.megBoxInfor(titleArr[index] + '<=0(:100x100)') return sizeTup = (width, height) sizeTupList.append(sizeTup) else: sizeTup = (0, 0) sizeTupList.append(sizeTup) else: if self.funType == 0: sizeTupList = [] else: sizeTupList = None isCloseAlpha = False if self.alphaCheckBox.checkState() == Qt.Checked: isCloseAlpha = True isUpDateImgType = False if self.imgTypeBox.checkState() == Qt.Checked: isUpDateImgType = True self.textEdit.clear() imageScaleObj.startScaleImg(oldImgPath, newImgPath, sizeTupList, isCloseAlpha, isUpDateImgType) def reloadUI(self): personinfo = ZFJPersoninfo() self.accountLab.setText(':' + str(personinfo.account)) self.timeLab.setText(':' + personinfo.expireDate.replace('"', '')) def center(self): qr = self.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft()) def megBoxInfor(self, infor): QMessageBox.information(self, '', infor, QMessageBox.Yes)
class App(QMainWindow): def __init__(self): super().__init__() self.title = 'kfit' self.left = 400 self.top = 150 self.width = 1200 self.height = 800 self.file_name = '' self.xcol_idx = 0 self.ycol_idx = 1 self.ngau = 0 self.nlor = 0 self.nvoi = 0 self.nlin = 1 self.model = None self.result = None self.curves_df = None self.params_df = None self.edit_mode = False # empty Parameters to hold parameter guesses/constraints self.params = Parameters() self.guesses = {'value': {}, 'min': {}, 'max': {}} self.usr_vals = {'value': {}, 'min': {}, 'max': {}} self.usr_entry_widgets = {} self.cid = None # file import settings self.sep = ',' self.header = 'infer' self.index_col = None self.skiprows = None self.dtype = None self.encoding = None # keyboard shortcuts self.fit_shortcut = QShortcut(QKeySequence('Ctrl+F'), self) self.fit_shortcut.activated.connect(self.fit) self.reset_shortcut = QShortcut(QKeySequence('Ctrl+R'), self) self.reset_shortcut.activated.connect(self.hard_reset) self.save_fit = QShortcut(QKeySequence('Ctrl+S'), self) self.save_fit.activated.connect(self.export_results) self.add_gau = QShortcut(QKeySequence('G'), self) self.add_gau.activated.connect(lambda: self.increment('gau', True)) self.add_gau.activated.connect(self.init_param_widgets) self.sub_gau = QShortcut(QKeySequence('Shift+G'), self) self.sub_gau.activated.connect(lambda: self.increment('gau', False)) self.sub_gau.activated.connect(self.init_param_widgets) self.add_lor = QShortcut(QKeySequence('L'), self) self.add_lor.activated.connect(lambda: self.increment('lor', True)) self.add_lor.activated.connect(self.init_param_widgets) self.sub_lor = QShortcut(QKeySequence('Shift+L'), self) self.sub_lor.activated.connect(lambda: self.increment('lor', False)) self.sub_lor.activated.connect(self.init_param_widgets) self.add_voi = QShortcut(QKeySequence('V'), self) self.add_voi.activated.connect(lambda: self.increment('voi', True)) self.add_voi.activated.connect(self.init_param_widgets) self.sub_voi = QShortcut(QKeySequence('Shift+V'), self) self.sub_voi.activated.connect(lambda: self.increment('voi', False)) self.sub_voi.activated.connect(self.init_param_widgets) self.add_lin = QShortcut(QKeySequence('N'), self) self.add_lin.activated.connect(lambda: self.increment('lin', True)) self.add_lin.activated.connect(self.init_param_widgets) self.sub_lin = QShortcut(QKeySequence('Shift+N'), self) self.sub_lin.activated.connect(lambda: self.increment('lin', False)) self.sub_lin.activated.connect(self.init_param_widgets) # temporary data x = np.linspace(0, 10, 500) y = models.gauss(x, 0.5, 4, 0.4) + \ models.gauss(x, 0.8, 5, 0.2) + \ models.gauss(x, 0.4, 6, 0.3) + 0.2 # set data self.data = pd.DataFrame([x, y]).T self.data.columns = ['x', 'y'] self.x = self.data['x'] self.y = self.data['y'] self.xmin = self.data['x'].min() self.xmax = self.data['x'].max() self.initUI() def initUI(self): self.setGeometry(self.left, self.top, self.width, self.height) self.setWindowTitle(self.title) self.setWindowIcon(QIcon('../images/K.png')) # set up the status bar self.status_bar = QStatusBar() self.setStatusBar(self.status_bar) self.status_bar.showMessage('Welcome to kfit!', msg_length) self.status_bar.setStyleSheet('background-color: white') # Create the Main Widget and Layout self.main_layout = QVBoxLayout() self.main_widget = QSplitter() self.main_widget.setOrientation(Qt.Vertical) self.setCentralWidget(self.main_widget) # create "top bar" widget self.topbar_layout = QHBoxLayout() self.topbar_widget = QWidget() # fit button self.fit_button = QPushButton('Fit', self) self.fit_button.setMaximumWidth(100) self.fit_button.clicked.connect(self.fit) self.fit_button.installEventFilter(self) # import button self.import_button = QPushButton('Import', self) self.import_button.setMaximumWidth(100) self.import_button.clicked.connect(self.get_data) self.import_button.installEventFilter(self) # import settings button self.import_settings_button = QPushButton('', self) self.import_settings_button.setIcon( QIcon.fromTheme('stock_properties')) self.import_settings_button.setMaximumWidth(40) self.import_settings_button.clicked.connect( self.import_settings_dialog) self.import_settings_button.installEventFilter(self) # reset fit button self.reset_button = QPushButton('', self) self.reset_button.setIcon(QIcon.fromTheme('view-refresh')) self.reset_button.setMaximumWidth(40) self.reset_button.clicked.connect(self.hard_reset) self.reset_button.installEventFilter(self) # save results button self.save_button = QPushButton('', self) self.save_button.setIcon(QIcon.fromTheme('filesave')) self.save_button.setMaximumWidth(40) self.save_button.clicked.connect(self.export_results) self.save_button.installEventFilter(self) # progress bar self.progress_bar = QProgressBar() # self.progressBar.setMaximumWidth(150) self.progress_bar.hide() # get column header for x self.xlabel = QLabel(self) self.xlabel.setText('ColumnIndex(X):') self.xlabel.setAlignment(Qt.AlignRight | Qt.AlignVCenter) # self.xlabel.setMaximumWidth(250) self.xline_entry = QLineEdit(self) self.xline_entry.setText('0') self.xline_entry.setAlignment(Qt.AlignCenter) # self.xline_entry.setMaximumWidth(50) self.xline_entry.returnPressed.connect(self.column_index_set) # get column header for y self.ylabel = QLabel(self) self.ylabel.setText('ColumnIndex(Y):') self.ylabel.setAlignment(Qt.AlignRight | Qt.AlignVCenter) # self.ylabel.setMaximumWidth(100) self.yline_entry = QLineEdit(self) self.yline_entry.setText('1') self.yline_entry.setAlignment(Qt.AlignCenter) # self.yline_entry.setMaximumWidth(50) self.yline_entry.returnPressed.connect(self.column_index_set) # add topbar widgets to layout self.topbar_layout.addSpacing(600) self.topbar_layout.addWidget(self.xlabel) self.topbar_layout.addWidget(self.xline_entry) self.topbar_layout.addWidget(self.ylabel) self.topbar_layout.addWidget(self.yline_entry) self.topbar_layout.addWidget(self.fit_button) self.topbar_layout.addWidget(self.import_button) self.topbar_layout.addWidget(self.import_settings_button) self.topbar_layout.addWidget(self.reset_button) self.topbar_layout.addWidget(self.save_button) self.topbar_layout.addWidget(self.progress_bar) self.topbar_layout.setAlignment(Qt.AlignRight) self.topbar_widget.setLayout(self.topbar_layout) self.topbar_widget.setMaximumHeight(75) # create tabs widget self.tabs = QTabWidget(self) self.tab1 = QWidget(self) self.tab2 = QTableView(self) self.tab3 = QWidget(self) self.tabs.addTab(self.tab1, 'Graph') self.tabs.addTab(self.tab2, 'Data') self.tabs.addTab(self.tab3, 'Output') self.tabs.setMinimumHeight(300) # create params widget self.params_widget = QSplitter() self.gau_layout = QVBoxLayout() self.gau_layout.setAlignment(Qt.AlignTop) self.gau_widget = QWidget() self.gau_widget.setLayout(self.gau_layout) self.gau_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.gau_scroll = QScrollArea() self.gau_scroll.setWidget(self.gau_widget) self.gau_scroll.setWidgetResizable(True) self.lor_widget = QWidget() self.lor_layout = QVBoxLayout() self.lor_layout.setAlignment(Qt.AlignTop) self.lor_widget.setLayout(self.lor_layout) self.lor_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.lor_scroll = QScrollArea() self.lor_scroll.setWidget(self.lor_widget) self.lor_scroll.setWidgetResizable(True) self.voi_widget = QWidget() self.voi_layout = QVBoxLayout() self.voi_layout.setAlignment(Qt.AlignTop) self.voi_widget.setLayout(self.voi_layout) self.voi_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.voi_scroll = QScrollArea() self.voi_scroll.setWidget(self.voi_widget) self.voi_scroll.setWidgetResizable(True) self.lin_widget = QWidget() self.lin_layout = QVBoxLayout() self.lin_layout.setAlignment(Qt.AlignTop) self.lin_widget.setLayout(self.lin_layout) self.lin_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.lin_scroll = QScrollArea() self.lin_scroll.setWidget(self.lin_widget) self.lin_scroll.setWidgetResizable(True) self.params_widget.addWidget(self.gau_scroll) self.params_widget.addWidget(self.lor_scroll) self.params_widget.addWidget(self.voi_scroll) self.params_widget.addWidget(self.lin_scroll) self.params_widget.setMinimumHeight(180) # add everything to main widget self.main_widget.addWidget(self.topbar_widget) self.main_widget.addWidget(self.tabs) self.main_widget.addWidget(self.params_widget) # Tab 1 - Graph / Model # Graph plt.style.use('fivethirtyeight') self.tab1.figure = Figure(figsize=(8, 6), dpi=60) self.tab1.canvas = FigureCanvas(self.tab1.figure) self.tab1.toolbar = NavigationToolbar(self.tab1.canvas, self) # tristate checkbox for edit mode self.emode_box = QCheckBox() self.emode_box.setTristate(True) self.emode_box.setIcon(QIcon.fromTheme('stock_edit')) self.emode_box.stateChanged.connect(self.toggle_edit_mode) self.emode_box.installEventFilter(self) # tweaking the toolbar layout self.tab1.toolbar.setIconSize(QSize(18, 18)) spacer = QWidget() spacer.setFixedWidth(20) self.tab1.toolbar.addWidget(spacer) self.tab1.toolbar.addWidget(self.emode_box) self.tab1.toolbar.locLabel.setAlignment(Qt.AlignRight | Qt.AlignCenter) graph_layout = QVBoxLayout() graph_layout.addWidget(self.tab1.toolbar) graph_layout.addWidget(self.tab1.canvas) # The "Set Model" layout model_layout = QGridLayout() widget_setgau = QWidget() layout_setgau = QHBoxLayout() layout_setgau.setSizeConstraint(QLayout.SetFixedSize) widget_setgau.setLayout(layout_setgau) widget_setlor = QWidget() layout_setlor = QHBoxLayout() layout_setlor.setSizeConstraint(QLayout.SetFixedSize) widget_setlor.setLayout(layout_setlor) widget_setvoi = QWidget() layout_setvoi = QHBoxLayout() layout_setvoi.setSizeConstraint(QLayout.SetFixedSize) widget_setvoi.setLayout(layout_setvoi) widget_setlin = QWidget() layout_setlin = QHBoxLayout() layout_setlin.setSizeConstraint(QLayout.SetFixedSize) widget_setlin.setLayout(layout_setlin) model_layout.addWidget(widget_setgau, 0, 0) model_layout.addWidget(widget_setlor, 0, 1) model_layout.addWidget(widget_setvoi, 0, 2) model_layout.addWidget(widget_setlin, 0, 3) # specify number of gaussian curves gauss_label = QLabel(self) gauss_label.setText('Gaussians') gauss_label.setAlignment(Qt.AlignVCenter) gauss_button_add = QPushButton('', self) gauss_button_add.setIcon(QIcon.fromTheme('list-add')) gauss_button_add.clicked.connect(lambda: self.increment('gau', True)) gauss_button_add.clicked.connect(self.init_param_widgets) gauss_button_sub = QPushButton('', self) gauss_button_sub.setIcon(QIcon.fromTheme('list-remove')) gauss_button_sub.clicked.connect(lambda: self.increment('gau', False)) gauss_button_sub.clicked.connect(self.init_param_widgets) layout_setgau.addWidget(gauss_label) layout_setgau.addWidget(gauss_button_add) layout_setgau.addWidget(gauss_button_sub) # specify number of lorentzian curves lorentz_label = QLabel(self) lorentz_label.setText('Lorentzians') lorentz_label.setAlignment(Qt.AlignVCenter) lorentz_button_add = QPushButton('', self) lorentz_button_add.setIcon(QIcon.fromTheme('list-add')) lorentz_button_add.clicked.connect(lambda: self.increment('lor', True)) lorentz_button_add.clicked.connect(self.init_param_widgets) lorentz_button_sub = QPushButton('', self) lorentz_button_sub.setIcon(QIcon.fromTheme('list-remove')) lorentz_button_sub.clicked.connect( lambda: self.increment('lor', False)) lorentz_button_sub.clicked.connect(self.init_param_widgets) layout_setlor.addWidget(lorentz_label) layout_setlor.addWidget(lorentz_button_add) layout_setlor.addWidget(lorentz_button_sub) # specify number of voigt curves voigt_label = QLabel(self) voigt_label.setText('Pseudo-Voigts') voigt_label.setAlignment(Qt.AlignVCenter) voigt_button_add = QPushButton('', self) voigt_button_add.setIcon(QIcon.fromTheme('list-add')) voigt_button_add.clicked.connect(lambda: self.increment('voi', True)) voigt_button_add.clicked.connect(self.init_param_widgets) voigt_button_sub = QPushButton('', self) voigt_button_sub.setIcon(QIcon.fromTheme('list-remove')) voigt_button_sub.clicked.connect(lambda: self.increment('voi', False)) voigt_button_sub.clicked.connect(self.init_param_widgets) layout_setvoi.addWidget(voigt_label) layout_setvoi.addWidget(voigt_button_add) layout_setvoi.addWidget(voigt_button_sub) # specify number of lines line_label = QLabel(self) line_label.setText('Lines:') line_label.setAlignment(Qt.AlignVCenter) line_button_add = QPushButton('', self) line_button_add.setIcon(QIcon.fromTheme('list-add')) line_button_add.clicked.connect(lambda: self.increment('lin', True)) line_button_add.clicked.connect(self.init_param_widgets) line_button_sub = QPushButton('', self) line_button_sub.setIcon(QIcon.fromTheme('list-remove')) line_button_sub.clicked.connect(lambda: self.increment('lin', False)) line_button_sub.clicked.connect(self.init_param_widgets) layout_setlin.addWidget(line_label) layout_setlin.addWidget(line_button_add) layout_setlin.addWidget(line_button_sub) graph_layout.addLayout(model_layout) self.tab1.setLayout(graph_layout) self.plot() # Tab 2 - Data Table self.table_model = PandasModel(self.data) self.tab2.setModel(self.table_model) self.tab2.resizeColumnsToContents() # Tab 3 - Output self.tab3_widget = QPlainTextEdit() tab3_layout = QVBoxLayout() tab3_layout.addWidget(self.tab3_widget) self.tab3.setLayout(tab3_layout) self.init_param_widgets() self.show() def export_results(self): self.process_results() # open file dialog exp_file_name, _ = QFileDialog.getSaveFileName( self, 'QFileDialog.getSaveFileName()', 'fit_results.csv', 'CSV files (*.csv)', ) if exp_file_name: self.process_results() self.curves_df.to_csv(exp_file_name) # NOTE: if user chooses a file extension other than .csv, or does # not use a file extension, this should still work, but I haven't # tested too rigorously yet self.params_df.to_csv('{}.params.csv'.format( exp_file_name[:exp_file_name.find('.csv')])) self.status_bar.showMessage( 'Exported fit results to: ' + exp_file_name, 2 * msg_length) else: self.status_bar.showMessage('Export canceled.', 2 * msg_length) return def process_results(self): if self.result is not None: self.params_df = pd.DataFrame.from_dict(self.result.best_values, orient='index') self.params_df.index.name = 'parameter' self.params_df.columns = ['value'] curves_dict = { 'data': self.y, 'total_fit': self.result.best_fit, } components = self.result.eval_components() for i, comp in enumerate(components): curves_dict[comp[:comp.find('_')]] = components[comp] self.curves_df = pd.DataFrame.from_dict(curves_dict) self.curves_df.index = self.x self.curves_df.index.name = self.data.columns[self.xcol_idx] else: self.status_bar.showMessage('No fit results to export!', msg_length) def eventFilter(self, object, event): if event.type() == QEvent.Enter: if object is self.reset_button: self.status_bar.showMessage("Reset fit") if object is self.import_settings_button: self.status_bar.showMessage("File import settings") if object is self.import_button: self.status_bar.showMessage("Import .csv file") if object is self.fit_button: self.status_bar.showMessage("Fit data") if object is self.emode_box: self.status_bar.showMessage("Toggle edit mode") if object is self.save_button: self.status_bar.showMessage("Export fit results") return True elif event.type() == QEvent.Leave: self.status_bar.showMessage(None) return False def init_model(self): # increment() ensures nlin >= 1 self.model = models.line_mod(self.nlin) if self.ngau != 0: self.model += models.gauss_mod(self.ngau) if self.nlor != 0: self.model += models.lor_mod(self.nlor) if self.nvoi != 0: self.model += models.voigt_mod(self.nvoi) self.status_bar.showMessage( "Model updated: " + str([self.ngau, self.nlor, self.nvoi, self.nlin]), msg_length) def init_param_widgets(self): self.init_model() self.usr_entry_widgets = {'value': {}, 'min': {}, 'max': {}} labels = {} rnd = 3 # decimals to round to in placeholder text self.clear_fit_layouts() for param_name in self.model.param_names: # set param label text labels[param_name] = QLabel() labels[param_name].setText(param_name) # make qlineedit widgets for key in self.usr_entry_widgets: self.usr_entry_widgets[key][param_name] = QLineEdit() if param_name in self.usr_vals[key]: self.usr_entry_widgets[key][param_name]\ .setPlaceholderText( str(round(self.usr_vals[key][param_name], rnd)) ) else: self.usr_entry_widgets[key][param_name]\ .setPlaceholderText(key) # set up connections # connect() expects a callable func, hence the lambda self.usr_entry_widgets[key][param_name].returnPressed.connect( lambda: self.update_usr_vals(self.usr_entry_widgets)) # add widgets to respective layouts sublayout1 = QVBoxLayout() sublayout2 = QHBoxLayout() sublayout1.addWidget(labels[param_name]) for key in self.usr_entry_widgets: sublayout2.addWidget(self.usr_entry_widgets[key][param_name]) if param_name.find('gau') != -1: self.gau_layout.addLayout(sublayout1) self.gau_layout.addLayout(sublayout2) if param_name.find('lor') != -1: self.lor_layout.addLayout(sublayout1) self.lor_layout.addLayout(sublayout2) if param_name.find('voi') != -1: self.voi_layout.addLayout(sublayout1) self.voi_layout.addLayout(sublayout2) if param_name.find('lin') != -1: self.lin_layout.addLayout(sublayout1) self.lin_layout.addLayout(sublayout2) # Resize all of the LineEntry widgets for key in self.usr_entry_widgets: for param, widget in self.usr_entry_widgets[key].items(): widget.setMaximumWidth(150) if self.result is not None: self.set_params() self.update_param_widgets() def update_usr_vals(self, entry): # get text input from each usr_entry_widget for val_type, param_dict in self.usr_entry_widgets.items(): for param, param_widget in param_dict.items(): try: self.usr_vals[val_type][param] = \ float(param_widget.text()) except Exception: pass def update_param_widgets(self): rnd = 3 # the 'value' placeholder text is the result for that param # taken from self.result # the 'min' and 'max' text is from either the self.guesses # or from self.usr_vals for param in self.params: if param in self.result.best_values: self.usr_entry_widgets['value'][param].setPlaceholderText( str(round(self.result.best_values[param], rnd))) self.usr_entry_widgets['min'][param].setPlaceholderText( str(round(self.params[param].min, rnd))) self.usr_entry_widgets['max'][param].setPlaceholderText( str(round(self.params[param].max, rnd))) def guess_params(self): for comp in self.model.components: if comp.prefix.find('gau') != -1 or \ comp.prefix.find('lor') != -1 or \ comp.prefix.find('voi') != -1: # need to define explicitly to make proper guesses c = comp.prefix + 'center' a = comp.prefix + 'amplitude' s = comp.prefix + 'sigma' f = comp.prefix + 'fraction' self.guesses['value'][c] = \ self.data.iloc[:, self.xcol_idx].mean() self.guesses['value'][a] = \ self.data.iloc[:, self.ycol_idx].mean() self.guesses['value'][s] = \ self.data.iloc[:, self.xcol_idx].std() self.guesses['min'][c] = None self.guesses['min'][a] = 0 self.guesses['min'][s] = 0 self.guesses['max'][c] = None self.guesses['max'][a] = None self.guesses['max'][s] = None if comp.prefix.find('voi') != -1: self.guesses['value'][f] = 0.5 self.guesses['min'][f] = 0 self.guesses['max'][f] = 1 else: slope = comp.prefix + 'slope' intc = comp.prefix + 'intercept' for p in [slope, intc]: self.guesses['value'][p] = \ self.data.iloc[:, self.ycol_idx].mean() self.guesses['min'][p] = None self.guesses['max'][p] = None def set_params(self): self.params = Parameters() self.guess_params() self.update_usr_vals(self.usr_entry_widgets) vals = {} # fill params with any user-entered values # fill in blanks with guesses for param_name in self.model.param_names: for val_type in ['value', 'min', 'max']: if param_name in self.usr_vals[val_type]: vals[val_type] = self.usr_vals[val_type][param_name] # print('param: ' + param_name + ', type: ' +\ # val_type + ', set_by: user') else: vals[val_type] = self.guesses[val_type][param_name] # print('param: ' + param_name + ', type: ' +\ # val_type + ', set_by: guess') self.params.add(name=param_name, value=vals['value'], vary=True, min=vals['min'], max=vals['max']) def set_xy_range(self): self.x = self.data.iloc[:, self.xcol_idx] self.y = self.data.iloc[:, self.ycol_idx] self.xmin, self.xmax = self.ax.get_xlim() range_bool = (self.x >= self.xmin) & (self.x <= self.xmax) self.x = self.x[range_bool].values self.y = self.y[range_bool].values def reset_xy_range(self): self.xmin = np.min(self.x) self.xmax = np.max(self.x) def fit(self): self.emode_box.setCheckState(0) self.toggle_edit_mode() self.set_xy_range() self.set_params() self.result = self.model.fit(data=self.y, params=self.params, x=self.x, method='least_squares') self.tab3_widget.clear() self.tab3_widget.insertPlainText(self.result.fit_report()) self.plot() # overwrite widgets to clear input (not ideal method..) self.init_param_widgets() # update widgets with new placeholder text self.update_param_widgets() def column_index_set(self): # make sure user enters index that can be converted to int try: idx_x = int(self.xline_entry.text()) except ValueError: self.status_bar.showMessage(idx_type_error_msg, msg_length) self.xline_entry.setText(None) return try: idx_y = int(self.yline_entry.text()) except ValueError: self.status_bar.showMessage(idx_type_error_msg, msg_length) self.yline_entry.setText(None) return self.xcol_idx = idx_x self.ycol_idx = idx_y self.result = None # make sure user enters an index that's in the data range try: self.x = self.data.iloc[:, self.xcol_idx] except IndexError: self.status_bar.showMessage(idx_range_error_msg, msg_length) self.xline_entry.setText(None) return try: self.y = self.data.iloc[:, self.ycol_idx] except IndexError: self.status_bar.showMessage(idx_range_error_msg, msg_length) self.yline_entry.setText(None) return self.xmin = np.min(self.x) self.xmax = np.max(self.x) self.plot() self.status_bar.showMessage( 'ColumnIndex(X) = ' + str(idx_x) + ', ' + 'ColumnIndex(Y) = ' + str(idx_y), msg_length) def toggle_edit_mode(self): # first toggle off the zoom or pan button # so they don't interfere with edit_mode cursor style if self.tab1.toolbar._active == 'ZOOM': self.tab1.toolbar.zoom() if self.tab1.toolbar._active == 'PAN': self.tab1.toolbar.pan() states = { 0: 'Edit mode off', 1: 'Edit mode on | copy x-value', 2: 'Edit mode on | copy y-value', } self.status_bar.showMessage(states[self.emode_box.checkState()], msg_length) if self.emode_box.checkState() == 0: self.mpl_cursor = None self.tab1.canvas.mpl_disconnect(self.cid) if self.emode_box.checkState() == 1: self.mpl_cursor = Cursor(self.ax, lw=1, c='red', linestyle='--') self.cid = self.tab1.canvas.mpl_connect('button_press_event', self.get_coord_click) if self.emode_box.checkState() == 2: self.cid = self.tab1.canvas.mpl_connect('button_press_event', self.get_coord_click) def get_coord_click(self, event): self.x_edit, self.y_edit = round(event.xdata, 3), round(event.ydata, 3) if self.emode_box.checkState() == 1: pyperclip.copy(self.x_edit) self.status_bar.showMessage( 'Copied X=' + str(self.x_edit) + ' to clipboard!', msg_length) if self.emode_box.checkState() == 2: pyperclip.copy(self.y_edit) self.status_bar.showMessage( 'Copied Y=' + str(self.y_edit) + ' to clipboard!', msg_length) def close_app(self): sys.exit() def get_data(self): self.emode_box.setCheckState(0) self.toggle_edit_mode() # reset column indices self.xcol_idx = 0 self.ycol_idx = 1 # open file dialog self.file_name, _ = QFileDialog.getOpenFileName( self, 'Open File', '', 'CSV files (*.csv);; All Files (*)') if self.file_name: # this message isn't showing up... # TODO: needs to be threaded self.status_bar.showMessage('Importing: ' + self.file_name, msg_length) try: df = tools.to_df(self.file_name, sep=self.sep, header=self.header, index_col=self.index_col, skiprows=self.skiprows, dtype=self.dtype, encoding=self.encoding) df.iloc[:, self.xcol_idx] df.iloc[:, self.ycol_idx] except Exception: self.status_bar.showMessage(file_import_error_msg, 2 * msg_length) return else: self.status_bar.showMessage('Import canceled.', msg_length) return self.data = df self.table_model = PandasModel(self.data) self.tab2.setModel(self.table_model) self.tab2.resizeColumnsToContents() # clear any previous fit result self.result = None # reset x, y, and xlim self.x = self.data.iloc[:, self.xcol_idx].values self.y = self.data.iloc[:, self.ycol_idx].values self.xmin = self.data.iloc[:, self.xcol_idx].min() self.xmax = self.data.iloc[:, self.xcol_idx].max() self.plot() self.status_bar.showMessage('Import finished.', msg_length) def import_settings_dialog(self): self.dialog_window = QDialog() self.dialog_window.setWindowTitle('File Import Settings') toplevel = QVBoxLayout() dialog_layout = QHBoxLayout() label_layout = QVBoxLayout() entry_layout = QVBoxLayout() button_layout = QVBoxLayout() label1 = QLabel(self.dialog_window) label1.setText('sep') label2 = QLabel(self.dialog_window) label2.setText('header') label3 = QLabel(self.dialog_window) label3.setText('skiprows') label4 = QLabel(self.dialog_window) label4.setText('dtype') label5 = QLabel(self.dialog_window) label5.setText('encoding') for lbl in [label1, label2, label3, label4, label5]: label_layout.addWidget(lbl) self.sep_edit = QLineEdit(self.dialog_window) self.head_edit = QLineEdit(self.dialog_window) self.skipr_edit = QLineEdit(self.dialog_window) self.dtype_edit = QLineEdit(self.dialog_window) self.enc_edit = QLineEdit(self.dialog_window) self.sep_edit.setText(self.sep) self.head_edit.setText(self.header) # if value is None, show text as 'None' if self.skiprows is not None: self.skipr_edit.setText(self.skiprows) else: self.skipr_edit.setText('None') if self.dtype is not None: self.dtype_edit.setText(self.dtype) else: self.dtype_edit.setText('None') if self.encoding is not None: self.enc_edit.setText(self.encoding) else: self.enc_edit.setText('None') # add widgets to layout for ewidget in [ self.sep_edit, self.head_edit, self.skipr_edit, self.dtype_edit, self.enc_edit ]: ewidget.setAlignment(Qt.AlignCenter) entry_layout.addWidget(ewidget) button1 = QPushButton('Set', self.dialog_window) button2 = QPushButton('Set', self.dialog_window) button3 = QPushButton('Set', self.dialog_window) button4 = QPushButton('Set', self.dialog_window) button5 = QPushButton('Set', self.dialog_window) for btn in [button1, button2, button3, button4, button5]: btn.clicked.connect(self.set_import_settings) button_layout.addWidget(btn) reflabel = QLabel(self.dialog_window) reflabel.setText( "for help, refer to <a href='https://pandas.pydata.org/" + "pandas-docs/stable/reference/api/" + "pandas.read_csv.html'>pandas.read_csv()</a>") reflabel.setOpenExternalLinks(True) reflabel.setAlignment(Qt.AlignCenter) for lo in [label_layout, entry_layout, button_layout]: dialog_layout.addLayout(lo) toplevel.addLayout(dialog_layout) toplevel.addSpacing(25) toplevel.addWidget(reflabel) self.dialog_window.setLayout(toplevel) self.dialog_window.setWindowModality(Qt.ApplicationModal) self.dialog_window.exec_() def set_import_settings(self): self.sep = self.sep_edit.text() self.header = self.head_edit.text() # convert 'None' entries to None if self.skipr_edit.text() == 'None': self.skiprows = None else: self.skiprows = self.skipr_edit.text() if self.dtype_edit.text() == 'None': self.dtype = None else: self.dtype = self.dtype_edit.text() if self.enc_edit.text() == 'None': self.encoding = None else: self.encoding = self.enc_edit.text() def plot(self): self.tab1.figure.clear() self.ax = self.tab1.figure.add_subplot(111, label=self.file_name) self.ax.scatter(self.x, self.y, s=100, c='None', edgecolors='black', linewidth=1, label='data') if self.result is not None: yfit = self.result.best_fit self.ax.plot(self.x, yfit, c='r', linewidth=2.5) cmap = cm.get_cmap('gnuplot') components = self.result.eval_components() for i, comp in enumerate(components): self.ax.plot(self.x, components[comp], linewidth=2.5, linestyle='--', c=cmap(i / len(components)), label=comp[:comp.find('_')]) self.ax.set_xlabel(self.data.columns[self.xcol_idx], labelpad=15) self.ax.set_ylabel(self.data.columns[self.ycol_idx], labelpad=15) self.ax.set_xlim([self.xmin, self.xmax]) self.ax.legend(loc='upper right') self.tab1.figure.subplots_adjust(bottom=0.15, left=0.06, right=0.94) self.tab1.canvas.draw() def clear_layout(self, layout): if layout: while layout.count(): item = layout.takeAt(0) widget = item.widget() if widget: widget.deleteLater() else: self.clear_layout(item.layout()) layout.removeItem(item) def clear_fit_layouts(self): for layout in [ self.gau_layout, self.lor_layout, self.voi_layout, self.lin_layout ]: self.clear_layout(layout) def hard_reset(self): self.clear_fit_layouts() self.ngau = 0 self.nlor = 0 self.nvoi = 0 self.nlin = 1 self.init_model() self.params = Parameters() self.result = None self.params_df = None self.curves_df = None self.guesses = {'value': {}, 'min': {}, 'max': {}} self.usr_vals = {'value': {}, 'min': {}, 'max': {}} self.init_param_widgets() self.plot() def increment(self, val, add): if add: if val == 'gau': self.ngau += 1 if val == 'lor': self.nlor += 1 if val == 'voi': self.nvoi += 1 if val == 'lin': self.nlin += 1 if not add: if val == 'gau': self.ngau -= 1 if val == 'lor': self.nlor -= 1 if val == 'voi': self.nvoi -= 1 if val == 'lin': self.nlin -= 1 # make sure value doesn't go below zero if self.ngau < 0: self.ngau = 0 if self.nlor < 0: self.nlor = 0 if self.nvoi < 0: self.nvoi = 0 if self.nlin < 1: self.nlin = 1
class PrecisionRotate(ToolInstance): help = "https://github.com/QChASM/SEQCROW/wiki/Rotate-Tool" SESSION_ENDURING = True SESSION_SAVE = True def __init__(self, session, name): super().__init__(session, name) self.tool_window = MainToolWindow(self) self.settings = _PrecisionRotateSettings(session, name) self.bonds = {} self.bond_centers = {} self.groups = {} self.perpendiculars = {} self.perp_centers = {} self.manual_center = {} self._build_ui() self._show_rot_vec = self.session.triggers.add_handler( SELECTION_CHANGED, self.show_rot_vec) global_triggers = get_triggers() self._changes = global_triggers.add_handler("changes done", self.show_rot_vec) self.show_rot_vec() def _build_ui(self): layout = QGridLayout() layout.addWidget(QLabel("center of rotation:"), 0, 0, 1, 1, Qt.AlignLeft | Qt.AlignVCenter) self.cor_button = QComboBox() self.cor_button.addItems( ["automatic", "select atoms", "view's center of rotation"]) layout.addWidget(self.cor_button, 0, 1, 1, 1, Qt.AlignTop) self.set_cor_selection = QPushButton("set selection") self.cor_button.currentTextChanged.connect( lambda t, widget=self.set_cor_selection: widget.setEnabled( t == "select atoms")) self.set_cor_selection.clicked.connect(self.manual_cor) layout.addWidget(self.set_cor_selection, 0, 2, 1, 1, Qt.AlignTop) self.set_cor_selection.setEnabled(False) layout.addWidget(QLabel("rotation vector:"), 1, 0, 1, 1, Qt.AlignLeft | Qt.AlignVCenter) self.vector_option = QComboBox() self.vector_option.addItems([ "axis", "view axis", "bond", "perpendicular to plane", "centroid of atoms", "custom" ]) layout.addWidget(self.vector_option, 1, 1, 1, 1, Qt.AlignVCenter) vector = QWidget() vector.setToolTip("vector will be normalized before rotating") vector_layout = QHBoxLayout(vector) vector_layout.setContentsMargins(0, 0, 0, 0) self.vector_x = QDoubleSpinBox() self.vector_y = QDoubleSpinBox() self.vector_z = QDoubleSpinBox() self.vector_z.setValue(1.0) for c, t in zip([self.vector_x, self.vector_y, self.vector_z], [" x", " y", " z"]): c.setSingleStep(0.01) c.setRange(-100, 100) # c.setSuffix(t) c.valueChanged.connect(self.show_rot_vec) vector_layout.addWidget(c) layout.addWidget(vector, 1, 2, 1, 1, Qt.AlignTop) vector.setVisible(self.vector_option.currentText() == "custom") self.vector_option.currentTextChanged.connect( lambda text, widget=vector: widget.setVisible(text == "custom")) self.view_axis = QComboBox() self.view_axis.addItems(["z", "y", "x"]) layout.addWidget(self.view_axis, 1, 2, 1, 1, Qt.AlignTop) self.view_axis.setVisible( self.vector_option.currentText() == "view axis") self.vector_option.currentTextChanged.connect( lambda text, widget=self.view_axis: widget.setVisible(text == "view axis")) self.axis = QComboBox() self.axis.addItems(["z", "y", "x"]) layout.addWidget(self.axis, 1, 2, 1, 1, Qt.AlignTop) self.axis.setVisible(self.vector_option.currentText() == "axis") self.vector_option.currentTextChanged.connect( lambda text, widget=self.axis: widget.setVisible(text == "axis")) self.bond_button = QPushButton("set selected bond") self.bond_button.clicked.connect(self.set_bonds) layout.addWidget(self.bond_button, 1, 2, 1, 1, Qt.AlignTop) self.bond_button.setVisible(self.vector_option.currentText() == "bond") self.vector_option.currentTextChanged.connect( lambda text, widget=self.bond_button: widget.setVisible(text == "bond")) self.perp_button = QPushButton("set selected atoms") self.perp_button.clicked.connect(self.set_perpendicular) layout.addWidget(self.perp_button, 1, 2, 1, 1, Qt.AlignTop) self.perp_button.setVisible( self.vector_option.currentText() == "perpendicular to plane") self.vector_option.currentTextChanged.connect( lambda text, widget=self.perp_button: widget.setVisible( text == "perpendicular to plane")) self.group_button = QPushButton("set selected atoms") self.group_button.clicked.connect(self.set_group) layout.addWidget(self.group_button, 1, 2, 1, 1, Qt.AlignTop) self.group_button.setVisible( self.vector_option.currentText() == "centroid of atoms") self.vector_option.currentTextChanged.connect( lambda text, widget=self.group_button: widget.setVisible( text == "centroid of atoms")) layout.addWidget(QLabel("angle:"), 2, 0, 1, 1, Qt.AlignLeft | Qt.AlignVCenter) self.angle = QDoubleSpinBox() self.angle.setRange(-360, 360) self.angle.setSingleStep(5) self.angle.setSuffix("°") layout.addWidget(self.angle, 2, 1, 1, 1, Qt.AlignLeft | Qt.AlignVCenter) layout.addWidget(QLabel("preview rotation axis:"), 3, 0, 1, 1, Qt.AlignLeft | Qt.AlignVCenter) self.display_rot_vec = QCheckBox() self.display_rot_vec.setCheckState(Qt.Checked) self.display_rot_vec.stateChanged.connect(self.show_rot_vec) layout.addWidget(self.display_rot_vec, 3, 1, 1, 1, Qt.AlignLeft | Qt.AlignVCenter) rotate_button = QPushButton("rotate selected atoms") rotate_button.clicked.connect(self.do_rotate) layout.addWidget(rotate_button, 4, 0, 1, 3, Qt.AlignTop) self.rotate_button = rotate_button self.status_bar = QStatusBar() self.status_bar.setSizeGripEnabled(False) layout.addWidget(self.status_bar, 5, 0, 1, 3, Qt.AlignTop) self.vector_option.currentTextChanged.connect(self.show_auto_status) self.cor_button.currentIndexChanged.connect( lambda *args: self.show_auto_status("select atoms")) self.cor_button.currentIndexChanged.connect(self.show_rot_vec) self.set_cor_selection.clicked.connect(self.show_rot_vec) self.vector_option.currentIndexChanged.connect(self.show_rot_vec) self.axis.currentIndexChanged.connect(self.show_rot_vec) self.view_axis.currentIndexChanged.connect(self.show_rot_vec) self.bond_button.clicked.connect(self.show_rot_vec) self.perp_button.clicked.connect(self.show_rot_vec) self.group_button.clicked.connect(self.show_rot_vec) layout.setRowStretch(0, 0) layout.setRowStretch(1, 0) layout.setRowStretch(2, 0) layout.setRowStretch(3, 0) layout.setRowStretch(4, 0) layout.setRowStretch(5, 1) layout.setColumnStretch(0, 0) layout.setColumnStretch(1, 1) layout.setColumnStretch(2, 1) self.tool_window.ui_area.setLayout(layout) self.tool_window.manage(None) def manual_cor(self, *args): selection = selected_atoms(self.session) models = {} for atom in selection: if atom.structure not in models: models[atom.structure] = [atom] else: models[atom.structure].append(atom) self.manual_center = {} for model in models: atoms = models[model] coords = np.array([atom.coord for atom in atoms]) self.manual_center[model] = np.mean(coords, axis=0) def show_auto_status(self, text): if self.cor_button.currentText() == "automatic": if text == "bond": self.status_bar.showMessage( "center set to one of the bonded atoms") elif text == "perpendicular to plane": self.status_bar.showMessage("center set to centroid of atoms") else: self.status_bar.showMessage( "center set to centroid of rotating atoms") elif self.cor_button.currentText() == "select atoms": self.status_bar.showMessage( "center set to centroid of specified atoms") else: self.status_bar.showMessage( "center set to view's center of rotation") def set_bonds(self, *args): bonds = selected_bonds(self.session) if len(bonds) == 0: self.session.logger.error("no bonds selected") return models = [bond.structure for bond in bonds] if any(models.count(m) > 1 for m in models): self.session.logger.error( "multiple bonds selected on the same structure") return self.bonds = { model: (bond.atoms[0].coord - bond.atoms[1].coord) for model, bond in zip(models, bonds) } self.bond_centers = { model: bond.atoms[1].coord for model, bond in zip(models, bonds) } def set_perpendicular(self, *args): atoms = selected_atoms(self.session) if len(atoms) == 0: self.session.logger.error("no atoms selected") return self.perpendiculars = {} self.perp_centers = {} models = set(atom.structure for atom in atoms) for model in models: atom_coords = [] for atom in atoms: if atom.structure is model: atom_coords.append(atom.coord) if len(atom_coords) < 3: self.session.logger.error("fewer than 3 atoms selected on %s" % model.atomspec) continue xyz = np.array(atom_coords) xyz -= np.mean(atom_coords, axis=0) R = np.dot(xyz.T, xyz) u, s, vh = np.linalg.svd(R, compute_uv=True) vector = u[:, -1] self.perpendiculars[model] = vector self.perp_centers[model] = np.mean(atom_coords, axis=0) def set_group(self, *args): atoms = selected_atoms(self.session) if len(atoms) == 0: self.session.logger.error("no atoms selected") return self.groups = {} models = set(atom.structure for atom in atoms) for model in models: atom_coords = [] for atom in atoms: if atom.structure is model: atom_coords.append(atom.coord) self.groups[model] = np.mean(atom_coords, axis=0) def do_rotate(self, *args): selection = selected_atoms(self.session) models = {} for atom in selection: if atom.structure not in models: models[atom.structure] = [atom] else: models[atom.structure].append(atom) if len(models.keys()) == 0: return if self.vector_option.currentText() == "axis": if self.axis.currentText() == "z": vector = np.array([0., 0., 1.]) elif self.axis.currentText() == "y": vector = np.array([0., 1., 0.]) elif self.axis.currentText() == "x": vector = np.array([1., 0., 0.]) elif self.vector_option.currentText() == "view axis": if self.view_axis.currentText() == "z": vector = self.session.view.camera.get_position().axes()[2] elif self.view_axis.currentText() == "y": vector = self.session.view.camera.get_position().axes()[1] elif self.view_axis.currentText() == "x": vector = self.session.view.camera.get_position().axes()[0] elif self.vector_option.currentText() == "bond": vector = self.bonds elif self.vector_option.currentText() == "perpendicular to plane": vector = self.perpendiculars elif self.vector_option.currentText() == "centroid of atoms": vector = self.groups elif self.vector_option.currentText() == "custom": x = self.vector_x.value() y = self.vector_y.value() z = self.vector_z.value() vector = np.array([x, y, z]) angle = np.deg2rad(self.angle.value()) center = {} for model in models: atoms = models[model] coords = np.array([atom.coord for atom in atoms]) center[model] = np.mean(coords, axis=0) if self.cor_button.currentText() == "automatic": if self.vector_option.currentText() == "perpendicular to plane": center = self.perp_centers elif self.vector_option.currentText() == "bond": center = self.bond_centers elif self.cor_button.currentText() == "select atoms": center = self.manual_center else: center = self.session.main_view.center_of_rotation for model in models: if isinstance(vector, dict): if model not in vector.keys(): continue else: v = vector[model] else: v = vector if isinstance(center, dict): if model not in center.keys(): continue else: c = center[model] else: c = center if self.vector_option.currentText( ) == "centroid of atoms" and self.cor_button.currentText( ) != "automatic": v = v - c v = v / np.linalg.norm(v) q = np.hstack(([np.cos(angle / 2)], v * np.sin(angle / 2))) q /= np.linalg.norm(q) qs = q[0] qv = q[1:] xyz = np.array([a.coord for a in models[model]]) xyz -= c xprod = np.cross(qv, xyz) qs_xprod = 2 * qs * xprod qv_xprod = 2 * np.cross(qv, xprod) xyz += qs_xprod + qv_xprod + c for t, coord in zip(models[model], xyz): t.coord = coord def show_rot_vec(self, *args): for model in self.session.models.list(type=Generic3DModel): if model.name == "rotation vector": model.delete() if self.display_rot_vec.checkState() == Qt.Unchecked: return selection = selected_atoms(self.session) if len(selection) == 0: return models = {} for atom in selection: if atom.structure not in models: models[atom.structure] = [atom] else: models[atom.structure].append(atom) if len(models.keys()) == 0: return if self.vector_option.currentText() == "axis": if self.axis.currentText() == "z": vector = np.array([0., 0., 1.]) elif self.axis.currentText() == "y": vector = np.array([0., 1., 0.]) elif self.axis.currentText() == "x": vector = np.array([1., 0., 0.]) elif self.vector_option.currentText() == "view axis": if self.view_axis.currentText() == "z": vector = self.session.view.camera.get_position().axes()[2] elif self.view_axis.currentText() == "y": vector = self.session.view.camera.get_position().axes()[1] elif self.view_axis.currentText() == "x": vector = self.session.view.camera.get_position().axes()[0] elif self.vector_option.currentText() == "bond": vector = self.bonds elif self.vector_option.currentText() == "perpendicular to plane": vector = self.perpendiculars elif self.vector_option.currentText() == "centroid of atoms": vector = self.groups elif self.vector_option.currentText() == "custom": x = self.vector_x.value() y = self.vector_y.value() z = self.vector_z.value() vector = np.array([x, y, z]) angle = np.deg2rad(self.angle.value()) center = {} for model in models: atoms = models[model] coords = np.array([atom.coord for atom in atoms]) center[model] = np.mean(coords, axis=0) if self.cor_button.currentText() == "automatic": if self.vector_option.currentText() == "perpendicular to plane": center = self.perp_centers elif self.vector_option.currentText() == "bond": center = self.bond_centers elif self.cor_button.currentText() == "select atoms": center = self.manual_center else: center = self.session.main_view.center_of_rotation for model in models: if isinstance(vector, dict): if model not in vector.keys(): continue else: v = vector[model] else: v = vector if isinstance(center, dict): if model not in center.keys(): continue else: c = center[model] else: c = center if self.vector_option.currentText( ) == "centroid of atoms" and self.cor_button.currentText( ) != "automatic": v = v - c if np.linalg.norm(v) == 0: continue residues = [] for atom in models[model]: if atom.residue not in residues: residues.append(atom.residue) v_c = c + v s = ".color red\n" s += ".arrow %10.6f %10.6f %10.6f %10.6f %10.6f %10.6f 0.2 0.4 0.7\n" % ( *c, *v_c) stream = BytesIO(bytes(s, 'utf-8')) bild_obj, status = read_bild(self.session, stream, "rotation vector") self.session.models.add(bild_obj, parent=model) def delete(self): self.session.triggers.remove_handler(self._show_rot_vec) global_triggers = get_triggers() global_triggers.remove_handler(self._changes) for model in self.session.models.list(type=Generic3DModel): if model.name == "rotation vector": model.delete() return super().delete() def close(self): self.session.triggers.remove_handler(self._show_rot_vec) global_triggers = get_triggers() global_triggers.remove_handler(self._changes) for model in self.session.models.list(type=Generic3DModel): if model.name == "rotation vector": model.delete() return super().close()
class TagStructuresWidget(QWidget): def __init__(self, app): super().__init__() self.images_paths = [] self.selected_image_path = "" self.app = app self.files_list = QListWidget() self.structures_list = QListWidget() self.image_widget = TaggableImageWidget() self.highlighter_checkbox = QCheckBox("Wskaż wybraną strukturę") self.init_ui() def init_ui(self): self.image_widget.set_highlighter_pixmap( QPixmap("./resources/arrow.png")) self.image_widget.hide_highlighter() self.files_list.itemClicked.connect(self.on_files_list_item_clicked) self.files_list.itemActivated.connect(self.on_files_list_item_clicked) self.structures_list.itemChanged.connect( self.on_structure_name_changed) self.structures_list.itemClicked.connect( self.on_structure_name_clicked) self.structures_list.itemActivated.connect( self.on_structure_name_clicked) self.image_widget.on_tag_added.connect(self.on_tag_added) self.highlighter_checkbox.stateChanged.connect( self.set_hightlighter_visibility_state) self.grid = QGridLayout() self.grid.setColumnStretch(0, 1) self.grid.setColumnStretch(1, 3) self.lists_tab = QTabWidget() self.lists_tab.addTab(self.files_list, "Zdjęcia") self.lists_tab.addTab(self.structures_list, "Struktury") self.grid.addWidget(self.lists_tab, 0, 0) self.grid.addWidget(self.image_widget, 0, 1) back_btn = QPushButton("Zapisz i powróć") back_btn.clicked.connect(self.save_and_go_home) save_btn = QPushButton("Zapisz") save_btn.clicked.connect(self.app.save_workspace_structures) btn_layout = QHBoxLayout() btn_layout.addWidget(back_btn) btn_layout.addWidget(save_btn) self.grid.addLayout(btn_layout, 1, 0) self.grid.addWidget(self.highlighter_checkbox, 1, 1) self.setLayout(self.grid) def load_images_paths(self): self.images_paths = load_files_paths(self.app.workspace_path, ("jpeg", "jpg", "png")) self.files_list.clear() for path in self.images_paths: self.files_list.addItem(path) def on_files_list_item_clicked(self, item): self.selected_image_path = item.text() image_path = os.path.join(self.app.workspace_path, self.selected_image_path) self.image_widget.set_pixmap(QPixmap(image_path)) self.image_widget.hide_highlighter() self.image_widget.clear_tags() label_id = 0 self.structures_list.clear() for tagdata in self.app.workspace_structures.setdefault( self.selected_image_path, []): label_id += 1 self.add_tag(label_id, tagdata) def on_tag_added(self, x, y): text, ok = QInputDialog.getText(self, 'Wprowadź strukturę', 'Pol, Łac, Ang:') if ok: structures = self.app.workspace_structures[ self.selected_image_path] tagdata = {'text': text, 'x': x, 'y': y} structures.append(tagdata) label_id = len( self.app.workspace_structures[self.selected_image_path]) self.add_tag(label_id, tagdata) def on_structure_name_changed(self, item): item_id = self.structures_list.indexFromItem(item).row() if len(item.text()) > 0: self.update_structure_name(item_id, item) else: self.delete_structure(item_id, item) def on_structure_name_clicked(self, item): item_id = self.structures_list.indexFromItem(item).row() self.image_widget.highlight_tag_at(item_id) if self.highlighter_checkbox.checkState() == Qt.Checked: self.image_widget.show_highlighter() def update_structure_name(self, item_id, item): # update tag tag = self.image_widget.tag_at(item_id) tag.setToolTip(item.text()) # update structure text structures = self.app.workspace_structures[self.selected_image_path] structures[item_id]['text'] = item.text() def delete_structure(self, item_id, item): # delete from structures structures = self.app.workspace_structures[self.selected_image_path] del structures[item_id] # update list and tags, so IDs can be restored mocked_item = QListWidgetItem() mocked_item.setText(self.selected_image_path) self.on_files_list_item_clicked(mocked_item) def save_and_go_home(self): self.app.save_workspace_structures() self.app.go_home() def add_tag(self, label_id, tagdata): item_widget = QListWidgetItem() item_widget.setText(tagdata['text']) item_widget.setFlags(item_widget.flags() | Qt.ItemIsEditable) self.structures_list.addItem(item_widget) tag_widget = TagWidget(str(label_id), tagdata['text'], tagdata['x'], tagdata['y']) tag_widget.adjust_to_size(self.image_widget.image().size(), 0.015 / 2) self.image_widget.addWidget(tag_widget) def set_hightlighter_visibility_state(self, state): if len(self.structures_list.selectedItems()) > 0 and state: self.image_widget.show_highlighter() else: self.image_widget.hide_highlighter()
class _SingleRoiCtrlWidget(QWidget): """_SingleRoiCtrlWidget class. Widget which controls a single ROI. """ # (idx, x, y, w, h) where idx starts from 1 roi_geometry_change_sgn = pyqtSignal(object) _pos_validator = QIntValidator(-10000, 10000) _size_validator = QIntValidator(1, 10000) INVALID_GEOM = RectRoiGeom.INVALID def __init__(self, roi: RectROI, *, parent=None): super().__init__(parent=parent) self._roi = roi self._activate_cb = QCheckBox("On") self._lock_cb = QCheckBox("Lock") self._width_le = SmartLineEdit() self._width_le.setValidator(self._size_validator) self._height_le = SmartLineEdit() self._height_le.setValidator(self._size_validator) self._px_le = SmartLineEdit() self._px_le.setValidator(self._pos_validator) self._py_le = SmartLineEdit() self._py_le.setValidator(self._pos_validator) self._line_edits = (self._width_le, self._height_le, self._px_le, self._py_le) self.initUI() self.initConnections() self.disableAllEdit() def initUI(self): layout = QHBoxLayout() idx = self._roi.index label = QLabel(f"ROI{idx}: ") palette = label.palette() palette.setColor(palette.WindowText, FColor.mkColor(config['GUI_ROI_COLORS'][idx - 1])) label.setPalette(palette) layout.addWidget(label) layout.addWidget(self._activate_cb) layout.addWidget(self._lock_cb) layout.addWidget(QLabel("w: ")) layout.addWidget(self._width_le) layout.addWidget(QLabel("h: ")) layout.addWidget(self._height_le) layout.addWidget(QLabel("x: ")) layout.addWidget(self._px_le) layout.addWidget(QLabel("y: ")) layout.addWidget(self._py_le) self.setLayout(layout) # left, top, right, bottom self.layout().setContentsMargins(2, 1, 2, 1) def initConnections(self): self._width_le.value_changed_sgn.connect(self.onRoiSizeEdited) self._height_le.value_changed_sgn.connect(self.onRoiSizeEdited) self._px_le.value_changed_sgn.connect(self.onRoiPositionEdited) self._py_le.value_changed_sgn.connect(self.onRoiPositionEdited) self._roi.sigRegionChangeFinished.connect( self.onRoiGeometryChangeFinished) self._activate_cb.stateChanged.connect(self.onToggleRoiActivation) self._activate_cb.stateChanged.emit(self._activate_cb.checkState()) self._lock_cb.stateChanged.connect(self.onLock) @pyqtSlot(int) def onToggleRoiActivation(self, state): if state == Qt.Checked: self._roi.show() self.enableAllEdit() x, y = [int(v) for v in self._roi.pos()] w, h = [int(v) for v in self._roi.size()] else: self._roi.hide() self.disableAllEdit() x, y, w, h = self.INVALID_GEOM self.roi_geometry_change_sgn.emit((self._roi.index, x, y, w, h)) @pyqtSlot(object) def onRoiPositionEdited(self, value): x, y = [int(v) for v in self._roi.pos()] w, h = [int(v) for v in self._roi.size()] if self.sender() == self._px_le: x = int(self._px_le.text()) elif self.sender() == self._py_le: y = int(self._py_le.text()) # If 'update' == False, the state change will be remembered # but not processed and no signals will be emitted. self._roi.setPos((x, y), update=False) # trigger sigRegionChanged which moves the handler(s) # finish=False -> sigRegionChangeFinished will not emit, which # otherwise triggers infinite recursion self._roi.stateChanged(finish=False) if not self._activate_cb.isChecked(): x, y, w, h = self.INVALID_GEOM self.roi_geometry_change_sgn.emit((self._roi.index, x, y, w, h)) @pyqtSlot(object) def onRoiSizeEdited(self, value): x, y = [int(v) for v in self._roi.pos()] w, h = [int(v) for v in self._roi.size()] if self.sender() == self._width_le: w = int(self._width_le.text()) elif self.sender() == self._height_le: h = int(self._height_le.text()) # If 'update' == False, the state change will be remembered # but not processed and no signals will be emitted. self._roi.setSize((w, h), update=False) # trigger sigRegionChanged which moves the handler(s) # finish=False -> sigRegionChangeFinished will not emit, which # otherwise triggers infinite recursion self._roi.stateChanged(finish=False) if not self._activate_cb.isChecked(): x, y, w, h = self.INVALID_GEOM self.roi_geometry_change_sgn.emit((self._roi.index, x, y, w, h)) @pyqtSlot(object) def onRoiGeometryChangeFinished(self, roi): """Connect to the signal from an ROI object.""" x, y = [int(v) for v in roi.pos()] w, h = [int(v) for v in roi.size()] self.updateParameters(x, y, w, h) # inform widgets outside this window if not self._activate_cb.isChecked(): x, y, w, h = self.INVALID_GEOM self.roi_geometry_change_sgn.emit((roi.index, x, y, w, h)) def notifyRoiParams(self): # fill the QLineEdit(s) and Redis self._roi.sigRegionChangeFinished.emit(self._roi) def updateParameters(self, x, y, w, h): self.roi_geometry_change_sgn.disconnect() self._px_le.setText(str(x)) self._py_le.setText(str(y)) self._width_le.setText(str(w)) self._height_le.setText(str(h)) self.roi_geometry_change_sgn.connect(Mediator().onRoiGeometryChange) def setEditable(self, editable): for w in self._line_edits: w.setDisabled(not editable) @pyqtSlot(int) def onLock(self, state): self._roi.setLocked(state == Qt.Checked) self.setEditable(not state == Qt.Checked) def disableAllEdit(self): self.setEditable(False) self._lock_cb.setDisabled(True) def enableAllEdit(self): self._lock_cb.setDisabled(False) self.setEditable(True)
class BuildPage(QWidget): """ The GUI for the build page of a project. """ # The page's label. label = "Build" def __init__(self): """ Initialise the page. """ super().__init__() self.project = None # Create the page's GUI. layout = QGridLayout() self._log_viewer = QPlainTextEdit( whatsThis="This displays the messages generated when building " "the application.", readOnly=True) layout.addWidget(self._log_viewer, 0, 0, 5, 1) build = QPushButton("Build", whatsThis="Build the application and optionally run " "<tt>qmake</tt>, <tt>make</tt> and the application " "itself.", clicked=self._build) layout.addWidget(build, 0, 1) optimisation = QGroupBox("Optimisations") optimisation_layout = QVBoxLayout() self._opt1_button = QCheckBox("No asserts", whatsThis="The compiled Python code will not contain any " "<tt>assert</tt> statements.", checked=True, stateChanged=self._opt1_changed) optimisation_layout.addWidget(self._opt1_button) self._opt2_button = QCheckBox("No docstrings", whatsThis="The compiled Python code will not contain any " "docstrings.", checked=True, stateChanged=self._opt2_changed) optimisation_layout.addWidget(self._opt2_button) optimisation.setLayout(optimisation_layout) layout.addWidget(optimisation, 1, 1) options = QGroupBox("Build Options") options_layout = QGridLayout() self._clean_button = QCheckBox("Clean before building", whatsThis="The build directory will be deleted and recreated " "before starting a new build.", checked=True) options_layout.addWidget(self._clean_button, 0, 0, 1, 2) self._verbose_button = QCheckBox("Verbose output", whatsThis="Additional messages will be displayed during the " "build process.") options_layout.addWidget(self._verbose_button, 1, 0, 1, 2) options_layout.addWidget(QLabel("Resource files"), 2, 0) self._resources_edit = QSpinBox( whatsThis="The number of Qt <tt>.qrc</tt> files that will be " "generated. Increasing this number reduces the size " "of each file meaning <tt>rcc</tt> requires less " "memory.", minimum=1) options_layout.addWidget(self._resources_edit, 2, 1) options_layout.addWidget(QLabel("Timeout"), 3, 0) self._timeout_edit = QSpinBox( whatsThis="The number of seconds to wait for build processes " "to run before timing out.", minimum=1) self._timeout_edit.setValue(30) options_layout.addWidget(self._timeout_edit, 3, 1) options.setLayout(options_layout) layout.addWidget(options, 2, 1) steps = QGroupBox("Additional Build Steps") steps_layout = QVBoxLayout() self._run_qmake_button = QCheckBox("Run qmake", whatsThis="Run <tt>qmake</tt> after successfully generating " "the application code.", stateChanged=self._run_qmake_changed) steps_layout.addWidget(self._run_qmake_button) self._run_make_button = QCheckBox("Run make", whatsThis="Run <tt>make</tt> after successfully running " "<tt>qmake</tt>.", stateChanged=self._run_make_changed) steps_layout.addWidget(self._run_make_button) self._run_application_button = QCheckBox("Run application", whatsThis="Run the application after successfully running " "<tt>make</tt>.", stateChanged=self._run_application_changed) steps_layout.addWidget(self._run_application_button) steps.setLayout(steps_layout) layout.addWidget(steps, 3, 1) layout.setRowStretch(4, 1) self.setLayout(layout) def _build(self, _): """ Invoked when the user clicks the build button. """ project = self.project # Check the prerequisites. Note that we don't disable the button if # these are missing because (as they are spread across the GUI) the # user would have difficulty knowing what needed fixing. if project.python_target_include_dir == '': self._missing_prereq("target Python include directory") return if project.python_target_library == '': self._missing_prereq("target Python library") return logger = LoggingMessageHandler(bool(self._verbose_button.checkState()), self._log_viewer) builder = Builder(project, logger) logger.clear() logger.status_message("Generating code...") if self._opt2_button.checkState(): opt = 2 elif self._opt1_button.checkState(): opt = 1 else: opt = 0 nr_resources = self._resources_edit.value() try: builder.build(opt, nr_resources, clean=bool(self._clean_button.checkState())) except UserException as e: logger.user_exception(e) handle_user_exception(e, self.label, self) return logger.status_message("Code generation succeeded.") timeout = self._timeout_edit.value() * 1000 if self._run_qmake_button.checkState() != Qt.Unchecked: qmake = os.path.expandvars(project.qmake) if qmake == '': QMessageBox.warning(self, self.label, "qmake cannot be run because its name has not been set.") else: logger.status_message("Running qmake...") try: builder.run([qmake], "qmake failed.", in_build_dir=True, timeout=timeout) except UserException as e: logger.user_exception(e) handle_user_exception(e, self.label, self) return logger.status_message("qmake succeeded.") if self._run_make_button.checkState() != Qt.Unchecked: make = 'nmake' if sys.platform == 'win32' else 'make' logger.status_message("Running {0}...".format(make)) try: builder.run([make], "{0} failed.".format(make), in_build_dir=True, timeout=timeout) except UserException as e: logger.user_exception(e) handle_user_exception(e, self.label, self) return logger.status_message("{0} succeeded.".format(make)) if self._run_application_button.checkState() != Qt.Unchecked: build_dir = project.path_from_user(project.build_dir) exe_name = project.get_executable_basename() if sys.platform == 'win32': application = build_dir + '/Release/' + exe_name + '.exe' elif sys.platform == 'darwin' and project.application_is_bundle: application = '/'.join([build_dir, exe_name + '.app', 'Contents', 'MacOS', exe_name]) else: application = build_dir + '/' + exe_name logger.status_message("Running {0}...".format(exe_name)) try: builder.run([application], "{0} failed.".format(application)) except UserException as e: logger.user_exception(e) handle_user_exception(e, self.label, self) return logger.status_message("{0} succeeded.".format(exe_name)) def _missing_prereq(self, missing): """ Tell the user about a missing prerequisite. """ QMessageBox.warning(self, self.label, "The project cannot be built because the name of the {0} has " "not been set.".format(missing)) def _opt1_changed(self, state): """ Invoked when the user clicks on the no asserts button. """ if state == Qt.Unchecked: self._opt2_button.setCheckState(Qt.Unchecked) def _opt2_changed(self, state): """ Invoked when the user clicks on the no docstrings button. """ if state == Qt.Checked: self._opt1_button.setCheckState(Qt.Checked) def _run_qmake_changed(self, state): """ Invoked when the user clicks on the run qmake button. """ if state == Qt.Unchecked: self._run_make_button.setCheckState(Qt.Unchecked) def _run_make_changed(self, state): """ Invoked when the user clicks on the run make button. """ if state == Qt.Unchecked: self._run_application_button.setCheckState(Qt.Unchecked) else: self._run_qmake_button.setCheckState(Qt.Checked) def _run_application_changed(self, state): """ Invoked when the user clicks on the run application button. """ if state != Qt.Unchecked: self._run_make_button.setCheckState(Qt.Checked)
class BRFOptionsPanel(QWidget): """A Panel where the options to plot the graph are displayed.""" sig_graphconf_changed = QSignal() def __init__(self, parent=None): super(BRFOptionsPanel, self).__init__(parent) self.__initGUI__() self.setVisible(False) def __initGUI__(self): # ---- Line and Markers Style Widgets self._errorbar = QCheckBox('Show error bars') self._errorbar.setCheckState(Qt.Checked) self._errorbar.stateChanged.connect(self._graphconf_changed) self._drawline = QCheckBox('Draw line') self._drawline.setCheckState(Qt.Unchecked) self._drawline.stateChanged.connect(self._graphconf_changed) self._markersize = {} self._markersize['label'] = QLabel('Marker size :') self._markersize['widget'] = QSpinBox() self._markersize['widget'].setValue(5) self._markersize['widget'].setRange(0, 25) self._markersize['widget'].valueChanged.connect( self._graphconf_changed) # ---- Y-Axis Options Widgets self._ylim = {} self._ylim['min'] = QDoubleSpinBox() self._ylim['min'].setValue(0) self._ylim['min'].setDecimals(1) self._ylim['min'].setSingleStep(0.1) self._ylim['min'].setRange(-10, 10) self._ylim['min'].setEnabled(True) self._ylim['min'].valueChanged.connect(self._graphconf_changed) self._ylim['max'] = QDoubleSpinBox() self._ylim['max'].setValue(1) self._ylim['max'].setDecimals(1) self._ylim['max'].setSingleStep(0.1) self._ylim['max'].setRange(-10, 10) self._ylim['max'].setEnabled(True) self._ylim['max'].valueChanged.connect(self._graphconf_changed) self._ylim['scale'] = QDoubleSpinBox() self._ylim['scale'].setValue(0.2) self._ylim['scale'].setDecimals(2) self._ylim['scale'].setSingleStep(0.05) self._ylim['scale'].setRange(0.01, 1) self._ylim['scale'].setEnabled(True) self._ylim['scale'].valueChanged.connect(self._graphconf_changed) self._ylim['auto'] = QCheckBox('') self._ylim['auto'].setCheckState(Qt.Checked) self._ylim['auto'].stateChanged.connect(self.axis_autocheck_changed) # ---- X-Axis Options Widgets self._xlim = {} self._xlim['units'] = QComboBox() self._xlim['units'].addItems(['Hours', 'Days']) self._xlim['units'].setCurrentIndex(1) self._xlim['units'].currentIndexChanged.connect( self.time_units_changed) self._xlim['min'] = QSpinBox() self._xlim['min'].setValue(0) self._xlim['min'].setSingleStep(1) self._xlim['min'].setRange(0, 9999) self._xlim['min'].setEnabled(True) self._xlim['min'].valueChanged.connect(self._graphconf_changed) self._xlim['max'] = QSpinBox() self._xlim['max'].setValue(1) self._xlim['max'].setSingleStep(1) self._xlim['max'].setRange(1, 9999) self._xlim['max'].setEnabled(True) self._xlim['max'].valueChanged.connect(self._graphconf_changed) self._xlim['scale'] = QDoubleSpinBox() self._xlim['scale'].setValue(1) self._xlim['scale'].setDecimals(1) self._xlim['scale'].setSingleStep(0.1) self._xlim['scale'].setRange(0.1, 99) self._xlim['scale'].setEnabled(True) self._xlim['scale'].valueChanged.connect(self._graphconf_changed) self._xlim['auto'] = QCheckBox('') self._xlim['auto'].setCheckState(Qt.Checked) self._xlim['auto'].stateChanged.connect(self.axis_autocheck_changed) self.axis_autocheck_changed() # ---- Axis Options Layout axlayout = QGridLayout() row = 0 axlayout.addWidget(QLabel('y-axis limits:'), 0, 0, 1, 2) row += 1 axlayout.addWidget(QLabel(' Minimum :'), row, 0) axlayout.addWidget(self._ylim['min'], row, 1) row += 1 axlayout.addWidget(QLabel(' Maximum :'), row, 0) axlayout.addWidget(self._ylim['max'], row, 1) row += 1 axlayout.addWidget(QLabel(' Scale :'), row, 0) axlayout.addWidget(self._ylim['scale'], row, 1) row += 1 axlayout.addWidget(QLabel(' Auto :'), row, 0) axlayout.addWidget(self._ylim['auto'], row, 1) row += 1 axlayout.setRowMinimumHeight(row, 15) row += 1 axlayout.addWidget(QLabel('x-axis limits:'), row, 0, 1, 2) row += 1 axlayout.addWidget(QLabel(' Time units :'), row, 0) axlayout.addWidget(self._xlim['units'], row, 1) row += 1 axlayout.addWidget(QLabel(' Minimum :'), row, 0) axlayout.addWidget(self._xlim['min'], row, 1) row += 1 axlayout.addWidget(QLabel(' Maximum :'), row, 0) axlayout.addWidget(self._xlim['max'], row, 1) row += 1 axlayout.addWidget(QLabel(' Scale :'), row, 0) axlayout.addWidget(self._xlim['scale'], row, 1) row += 1 axlayout.addWidget(QLabel(' Auto :'), row, 0) axlayout.addWidget(self._xlim['auto'], row, 1) axlayout.setColumnStretch(3, 100) axlayout.setContentsMargins(0, 0, 0, 0) # (left, top, right, bottom) # ---- Graph Panel Layout layout = QGridLayout(self) layout.setContentsMargins(10, 0, 10, 0) # (l, t, r, b) row = 0 layout.addWidget(self._errorbar, row, 1, 1, 2) row += 1 layout.addWidget(self._drawline, row, 1, 1, 2) row += 1 layout.addWidget(self._markersize['label'], row, 1) layout.addWidget(self._markersize['widget'], row, 2) row += 1 layout.addWidget(HSep(), row, 1, 1, 2) row += 1 layout.addLayout(axlayout, row, 1, 1, 2) row += 1 layout.setRowMinimumHeight(row, 15) layout.setRowStretch(row, 100) def _graphconf_changed(self): """ Emits a signal to indicate that the graph configuration has changed. """ self.sig_graphconf_changed.emit() # ---- Graph Panel Properties @property def time_units(self): if self._xlim['auto'].checkState() == Qt.Checked: return 'auto' else: return self._xlim['units'].currentText().lower() @property def xmin(self): if self._xlim['auto'].checkState() == Qt.Checked: return None else: if self.time_units == 'hours': return self._xlim['min'].value()/24 else: return self._xlim['min'].value() @property def xmax(self): if self._xlim['auto'].checkState() == Qt.Checked: return None else: if self.time_units == 'hours': return self._xlim['max'].value()/24 else: return self._xlim['max'].value() @property def xscale(self): if self._xlim['auto'].checkState() == Qt.Checked: return None else: if self.time_units == 'hours': return self._xlim['scale'].value()/24 else: return self._xlim['scale'].value() @property def ymin(self): if self._ylim['auto'].checkState() == Qt.Checked: return None else: return self._ylim['min'].value() @property def ymax(self): if self._ylim['auto'].checkState() == Qt.Checked: return None else: return self._ylim['max'].value() @property def yscale(self): if self._ylim['auto'].checkState() == Qt.Checked: return None else: return self._ylim['scale'].value() @property def show_ebar(self): return self._errorbar.checkState() == Qt.Checked @property def draw_line(self): return self._drawline.checkState() == Qt.Checked @property def markersize(self): return self._markersize['widget'].value() # ---- Handlers def time_units_changed(self): """ Handles when the time_units combobox selection changes.""" for xlim in [self._xlim['min'], self._xlim['max'], self._xlim['scale']]: xlim.blockSignals(True) if self._xlim['units'].currentText() == 'Hours': xlim.setValue(xlim.value()*24) elif self._xlim['units'].currentText() == 'Days': xlim.setValue(xlim.value()/24) xlim.blockSignals(False) self._graphconf_changed() def axis_autocheck_changed(self): """ Handles when the Auto checkbox state change for the limits of the y-axis or the x-axis. """ self._ylim['min'].setEnabled(not self._ylim['auto'].isChecked()) self._ylim['max'].setEnabled(not self._ylim['auto'].isChecked()) self._ylim['scale'].setEnabled(not self._ylim['auto'].isChecked()) self._xlim['units'].setEnabled(not self._xlim['auto'].isChecked()) self._xlim['min'].setEnabled(not self._xlim['auto'].isChecked()) self._xlim['max'].setEnabled(not self._xlim['auto'].isChecked()) self._xlim['scale'].setEnabled(not self._xlim['auto'].isChecked()) self._graphconf_changed()