def hikdef(self): chue_nod_kho_nok = None chue_nod_poly = self.cbb_poly.currentText() if (mc.objExists(chue_nod_poly)): if (mc.objExists(chue_nod_poly + '_sentaa')): chue_nod_kho_nok = chue_nod_poly + '_sentaa' elif (mc.objExists(chue_nod_poly + '_subetenooya')): chue_nod_kho_nok = chue_nod_poly + '_subetenooya' if (not chue_nod_kho_nok): QMessageBox.about(self, '何か間違いかも', '該当のジョイントが見つかりません') return self.wdg.setFixedSize(600, 2000) self.btn_hikdef.setEnabled(False) self.cbb_poly.setEnabled(False) dic_chue = {} if (chue_nod_kho_nok[0] != '|'): chue_nod_kho_nok = '|' + chue_nod_kho_nok set_hik = set(mc.ls(type='HIKCharacterNode')) mel.eval('hikCreateDefinition') chue_nod_hik = (set(mc.ls(type='HIKCharacterNode')) - set_hik).pop() chue_nod_hik = mc.rename(chue_nod_hik, 'HIK_' + chue_nod_poly) lis_chue_nod_kho = [chue_nod_kho_nok] + mc.listRelatives( chue_nod_kho_nok, allDescendents=True, fullPath=True) for lek in dic_hik: hbl = QHBoxLayout() self.vbl.addLayout(hbl) lb = QLabel(dic_hik[lek][0]) hbl.addWidget(lb) lb.setFixedWidth(80) for chue_nod_kho in lis_chue_nod_kho: khonha = re.findall(r'\|%s$' % dic_hik[lek][1], chue_nod_kho) if (khonha): dic_chue[lek] = chue_nod_kho mel.eval('hikSetCharacterObject %s %s %d 0' % (chue_nod_kho, chue_nod_hik, lek)) btn = QPushButton('選択') hbl.addWidget(btn) btn.setFixedSize(50, 30) le = QLineEdit(chue_nod_kho) hbl.addWidget(le) btn.clicked.connect((lambda x: (lambda: mc.select(x.text())))(le)) le.setFixedWidth(400) le.setStyleSheet('font-size: 12px; color: #ffe;') break else: lb = QLabel('見つかりません') hbl.addWidget(lb) lb.setFixedWidth(400) lb.setStyleSheet('color: #fab;') hbl.addStretch() kangkhaen(dic_chue) self.vbl.addStretch() self.btn_sang_hik.setEnabled(True)
class ClusterDialog(QDialog): editClusterName = None def __init__(self, lifeline, defaultName, parent = None): super(ClusterDialog, self).__init__(parent) self.lifeline = lifeline layout = QVBoxLayout(self) message = QLabel('Enter group name') layout.addWidget(message) self.editClusterName = QLineEdit(defaultName) self.editClusterName.setFixedHeight(30) self.editClusterName.setFixedWidth(400) self.editClusterName.textChanged.connect(self.validateCluster) layout.addWidget(self.editClusterName) self.validation_msg = QLabel(' ') layout.addWidget(self.validation_msg) buttons = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, QtCore.Qt.Horizontal, self) buttons.accepted.connect(self.accept) buttons.rejected.connect(self.reject) layout.addWidget(buttons) self.validateCluster() def validateCluster(self): cnt = 0 for l in self.lifeline: if self.editClusterName.text() in l.getClassName() and not l.getFlagCluster() and not l.getClusterLifeline(): cnt += 1 available_flag = True for l in self.lifeline: if self.editClusterName.text() in l.getClassName() and l.getFlagCluster(): available_flag = False break if available_flag: self.validation_msg.setText("group name includes %d life-lines" % (cnt)) else: self.validation_msg.setText("group name is not available") def getClusterText(self): return self.editClusterName.text() @staticmethod def getClusterName(lifelines, defaultName, parent = None): dialog = ClusterDialog(lifelines,defaultName,parent) result = dialog.exec_() return (result, dialog.getClusterText())
def __init__(self, on_serves_entered: CallbackType) -> None: self._on_serves_entered = on_serves_entered serves_amount_line_edit = QLineEdit("1") serves_amount_line_edit.setFixedWidth(30) serves_amount_line_edit.setValidator(QIntValidator()) serves_amount_line_edit.setMaxLength(2) super().__init__("Количество порций:", serves_amount_line_edit) self._connect_slots()
def __init__(self, food_names: List[str], on_ingredient_entered: CallbackType, on_ingredient_finalized: CallbackType) -> None: super().__init__() self._food_names = food_names self._on_ingredient_entered = on_ingredient_entered self._on_ingredient_finalized = on_ingredient_finalized # ingredient ingredient_label = QLabel("Продукт:") ingredient_line_edit = QLineEdit() # Completer for the ingredient line edit completer = QCompleter(self._food_names) completer.setCaseSensitivity(Qt.CaseInsensitive) ingredient_line_edit.setCompleter(completer) # ingredient mass line edit ingredient_mass_line_edit = QLineEdit() ingredient_mass_line_edit.setPlaceholderText("Масса (гр.)") ingredient_mass_line_edit.setFixedWidth(100) ingredient_mass_line_edit.setValidator(QIntValidator()) ingredient_mass_line_edit.setMaxLength(4) # Button to add ingredient to the recipe ingredient_add_button = QPushButton("+") # Layout for ingredient_label / ingredient_line_edit ingredient_layout = QHBoxLayout() ingredient_layout.addWidget(ingredient_label) ingredient_layout.addWidget(ingredient_line_edit) ingredient_layout.addWidget(ingredient_mass_line_edit) ingredient_layout.addWidget(ingredient_add_button) self.setLayout(ingredient_layout) self._ingredient_line_edit = ingredient_line_edit self._ingredient_mass_line_edit = ingredient_mass_line_edit self._ingredient_add_button = ingredient_add_button self._connect_slots()
def __init__(self, lookup_names: List, on_item_added: CallbackType) -> None: super().__init__() recipe_search_label = QLabel("Блюдо:") recipe_search_line_edit = QLineEdit("") completer = QCompleter(lookup_names) completer.setCaseSensitivity(Qt.CaseInsensitive) completer.setFilterMode(Qt.MatchFlag.MatchContains) completer.setMaxVisibleItems(50) recipe_search_line_edit.setCompleter(completer) serves_amount_label = QLabel("Порций:") serves_amount_line_edit = QLineEdit(str(self.DEFAULT_SERVES_AMOUNT)) serves_amount_line_edit.setFixedWidth(30) serves_amount_line_edit.setValidator(QIntValidator()) serves_amount_line_edit.setMaxLength(2) add_push_button = QPushButton("+") # Widget layout layout = QHBoxLayout() layout.addWidget(recipe_search_label) layout.addWidget(recipe_search_line_edit) layout.addWidget(serves_amount_label) layout.addWidget(serves_amount_line_edit) layout.addWidget(add_push_button) layout.addStretch() self.setLayout(layout) # Init self data self._on_item_added = on_item_added self._recipe_search_line_edit = recipe_search_line_edit self._serves_amount_line_edit = serves_amount_line_edit self._add_push_button = add_push_button # Connect slots self._connect_slots()
class MyWidget(QWidget): def __init__(self): QWidget.__init__(self) event_ids = [18218, 17412, 18308, 18106, 16981, 18995] self.layout = QVBoxLayout() self.setWindowIconText('Test') self.text = QLabel("Event ID:s") self.text.setAlignment(Qt.AlignLeft) self.layout.addWidget(self.text) self.event1 = QLineEdit() self.event1.setAlignment(Qt.AlignLeft) self.event1.setFixedWidth(120) self.event1.setText(str(event_ids[0])) self.layout.addWidget(self.event1) self.event2 = QLineEdit() self.event2.setAlignment(Qt.AlignLeft) self.event2.setFixedWidth(120) self.event2.setText(str(event_ids[1])) self.layout.addWidget(self.event2) self.event3 = QLineEdit() self.event3.setAlignment(Qt.AlignLeft) self.event3.setFixedWidth(120) self.event3.setText(str(event_ids[2])) self.layout.addWidget(self.event3) self.event4 = QLineEdit() self.event4.setAlignment(Qt.AlignLeft) self.event4.setFixedWidth(120) self.event4.setText(str(event_ids[3])) self.layout.addWidget(self.event4) self.event5 = QLineEdit() self.event5.setAlignment(Qt.AlignLeft) self.event5.setFixedWidth(120) self.event5.setText(str(event_ids[4])) self.layout.addWidget(self.event5) self.event6 = QLineEdit() self.event6.setAlignment(Qt.AlignLeft) self.event6.setFixedWidth(120) self.event6.setText(str(event_ids[5])) self.layout.addWidget(self.event6) self.output1 = QLabel("--Nothing analysed yet--") self.output1.setAlignment(Qt.AlignRight) self.layout.addWidget(self.output1) self.output2 = QLabel(" ") self.output2.setAlignment(Qt.AlignRight) self.layout.addWidget(self.output2) self.button = QPushButton("Extract and analyse events") self.layout.addWidget(self.button) self.setLayout(self.layout) # Connecting the signal self.button.clicked.connect(self.magic) @Slot() def magic(self): self.output1.setText("Analysing...") eventlist = [ self.event1.text(), self.event2.text(), self.event3.text(), self.event4.text(), self.event5.text(), self.event6.text() ] club_file, ind_file = extract_and_analyse(eventlist) self.output1.setText('Saved: ' + club_file) self.output2.setText('Saved: ' + ind_file)
class RightSide: def __init__(self, font): self._font = font self.layout = QVBoxLayout() self.stdout_info = QTextEdit() self.stdout_info.setFixedWidth(800) self.stdout_info.moveCursor(QtGui.QTextCursor.Start) self.stdout_info.ensureCursorVisible() self.stdout_info.setLineWrapColumnOrWidth(500) self.stdout_info.setLineWrapMode(QTextEdit.FixedPixelWidth) self.layout.addWidget(self.stdout_info) self._set_media_player() self._midi_path = os.path.abspath( os.path.join(str(Path(__file__).parent.parent.parent), 'results')) self._midi_file = None self.midi_player = MidiPlayer() self._toggle_pause = True self._already_playing = False self._play_default_stylesheet = None self._pause_default_stylesheet = None self._stop_default_stylesheet = None self.end_signal = 'NO END.' self.player_timer_thread = threading.Thread( target=self._update_media_player_timer) self.player_timer_thread.start() def update_stdout_text_window(self, msg): cursor = self.stdout_info.textCursor() cursor.movePosition(QtGui.QTextCursor.End) cursor.insertText(msg) self.stdout_info.setTextCursor(cursor) self.stdout_info.ensureCursorVisible() def _set_media_player(self): self._resources_path = os.path.abspath( os.path.join(str(Path(__file__).parent.parent.parent), 'resources', 'gui')) self._media_box = QHBoxLayout() self._play_button = QPushButton('PLAY') self._play_icon = QtGui.QPixmap( os.path.join(self._resources_path, 'play.png')) self._play_button.setIcon(self._play_icon) self._play_default_stylesheet = self._play_button.styleSheet() self._play_button.setEnabled(False) self._play_button.clicked.connect(lambda c: self._play_midi()) self._pause_button = QPushButton('PAUSE') self._pause_icon = QtGui.QPixmap( os.path.join(self._resources_path, 'pause.png')) self._pause_button.setIcon(self._pause_icon) self._pause_default_stylesheet = self._pause_button.styleSheet() self._pause_button.setEnabled(False) self._pause_button.clicked.connect(lambda c: self._pause()) self._stop_button = QPushButton('STOP') self._stop_icon = QtGui.QPixmap( os.path.join(self._resources_path, 'stop.png')) self._stop_button.setIcon(self._stop_icon) self._stop_button.setEnabled(False) self._stop_button.clicked.connect(lambda c: self._stop()) self._stop_button.setStyleSheet( "QPushButton:pressed { background-color: red }") self._player_timer = QLineEdit('--/-- sec.') self._player_timer.setFixedWidth(200) self._player_timer.setEnabled(False) self._media_box.addWidget(self._play_button) self._media_box.addWidget(self._pause_button) self._media_box.addWidget(self._stop_button) self._media_box.addWidget(self._player_timer) self.layout.addLayout(self._media_box) def update_media_player(self, msg): self._midi_file = os.path.join(self._midi_path, msg[:-4] + '.mid') self.midi_player.load(self._midi_file) self._play_button.setEnabled(True) self._pause_button.setEnabled(True) self._stop_button.setEnabled(True) def _play_midi(self): self._play_button.setStyleSheet("background-color: green") self._pause_button.setStyleSheet(self._pause_default_stylesheet) self._toggle_pause = True if self._already_playing is False: self.midi_player.play() self._already_playing = True def _pause(self): self._play_button.setStyleSheet(self._play_default_stylesheet) self._pause_button.setStyleSheet("background-color: green") if self._toggle_pause is True: self.midi_player.pause() self._already_playing = False else: self.midi_player.unpause() self._already_playing = True self._toggle_pause = not self._toggle_pause def _stop(self): self._play_button.setStyleSheet(self._play_default_stylesheet) self._pause_button.setStyleSheet(self._pause_default_stylesheet) self._toggle_pause = True self.midi_player.stop() self._already_playing = False def _update_media_player_timer(self): while True: if self.end_signal == 'End.': break total = self.midi_player.song_duration if total != 0: current = self.midi_player.current_runtime if int(current) > math.floor(total): current = total output = f'{current}/{total} sec.' else: output = '--/-- sec.' self._player_timer.setText(output)
class Separate(QDialog): videoPath = '' duration = 60000 processToken = False voiceList = Signal(list) avgList = Signal(list) clrSep = Signal() tablePreset = Signal(list) autoFillToken = True autoSpanToken = True multipleThread = True def __init__(self): super().__init__() self.resize(800, 150) self.setWindowTitle('AI智能打轴 (测试版)') layout = QGridLayout() self.setLayout(layout) layout.addWidget(QLabel('前侧留白(ms)'), 0, 0, 1, 1) self.beforeEdit = QLineEdit('20') validator = QIntValidator() validator.setRange(0, 5000) self.beforeEdit.setValidator(validator) self.beforeEdit.setFixedWidth(50) layout.addWidget(self.beforeEdit, 0, 1, 1, 1) layout.addWidget(QLabel(''), 0, 2, 1, 1) layout.addWidget(QLabel('后侧留白(ms)'), 0, 3, 1, 1) self.afterEdit = QLineEdit('300') self.afterEdit.setValidator(validator) self.afterEdit.setFixedWidth(50) layout.addWidget(self.afterEdit, 0, 4, 1, 1) layout.addWidget(QLabel(''), 0, 5, 1, 1) self.autoFill = QPushButton('填充字符') self.autoFill.setStyleSheet('background-color:#3daee9') self.autoFill.clicked.connect(self.setAutoFill) layout.addWidget(self.autoFill, 0, 6, 1, 1) self.fillWord = QLineEdit('#AI自动识别#') layout.addWidget(self.fillWord, 0, 7, 1, 1) layout.addWidget(QLabel(''), 0, 8, 1, 1) self.autoSpan = QPushButton('自动合并') self.autoSpan.setStyleSheet('background-color:#3daee9') self.autoSpan.clicked.connect(self.setAutoSpan) layout.addWidget(self.autoSpan, 0, 9, 1, 1) self.multiCheck = QPushButton('启用多进程') self.multiCheck.setStyleSheet('background-color:#3daee9') self.multiCheck.clicked.connect(self.setMultipleThread) layout.addWidget(self.multiCheck, 0, 10, 1, 1) self.processBar = QProgressBar() layout.addWidget(self.processBar, 1, 0, 1, 10) self.checkButton = QPushButton('开始') self.checkButton.setFixedWidth(100) self.checkButton.clicked.connect(self.separateProcess) layout.addWidget(self.checkButton, 1, 10, 1, 1) def setDefault(self, videoPath, duration): self.videoPath = videoPath self.duration = duration def separateProcess(self): self.processToken = not self.processToken if self.videoPath: if self.processToken: self.processBar.setValue(0) self.checkButton.setText('初始化中') if not self.beforeEdit.text(): self.beforeEdit.setText('0') before = self.beforeEdit.text() if not self.afterEdit.text(): self.afterEdit.setText('0') after = self.afterEdit.text() if self.autoFillToken: try: fillWord = self.fillWord.text() except: fillWord = '' else: fillWord = '' self.sepProc = separateQThread(self.videoPath, self.duration, before, after, self.multipleThread) self.clrSep.emit() # 清空第一条字幕轴 self.sepProc.position.connect(self.setTitle) # 设置标题分析至第几分钟 self.sepProc.percent.connect(self.setProgressBar) # 设置滚动条进度 self.sepProc.voiceList.connect( self.sendVoiceList) # 二次传球给主界面标记表格 self.sepProc.avgList.connect( self.sendAvgList) # 平均音频响度 预留给后面画音频图 self.tablePreset.emit([fillWord, self.autoSpanToken]) # 自动填充 填充文本 自动合并 self.sepProc.finish.connect(self.sepFinished) self.sepProc.start() else: self.setWindowTitle('AI智能打轴 (测试版)') self.processBar.setValue(0) self.checkButton.setText('开始') self.checkButton.setStyleSheet('background-color:#31363b') # self.sepProc.separate._pool.terminate() # try: # p = psutil.Process(self.sepProc.p.pid) # for proc in p.children(True): # proc.kill() # except: # pass self.sepProc.terminate() self.sepProc.quit() self.sepProc.wait() def setTitle(self, pos): self.setWindowTitle('AI智能打轴 (已分析至第%s分钟)' % pos) def setProgressBar(self, percent): self.checkButton.setText('停止') self.checkButton.setStyleSheet('background-color:#3daee9') self.processBar.setValue(percent) def sendVoiceList(self, voiceList): self.voiceList.emit(voiceList) def sendAvgList(self, avgList): self.avgList.emit(avgList) def sepFinished(self, result): if result: self.processToken = not self.processToken self.setWindowTitle('AI智能打轴 (测试版)') self.processBar.setValue(100) self.checkButton.setText('开始') self.checkButton.setStyleSheet('background-color:#31363b') # self.sepProc.separate._pool.terminate() # try: # p = psutil.Process(self.sepProc.p.pid) # for proc in p.children(True): # proc.kill() # except: # pass self.sepProc.terminate() self.sepProc.quit() self.sepProc.wait() def setAutoFill(self): self.autoFillToken = not self.autoFillToken if self.autoFillToken: self.autoFill.setStyleSheet('background-color:#3daee9') self.fillWord.setEnabled(True) else: self.autoFill.setStyleSheet('background-color:#31363b') self.fillWord.setEnabled(False) def setAutoSpan(self): self.autoSpanToken = not self.autoSpanToken if self.autoSpanToken: self.autoSpan.setStyleSheet('background-color:#3daee9') else: self.autoSpan.setStyleSheet('background-color:#31363b') def setMultipleThread(self): self.multipleThread = not self.multipleThread if self.multipleThread: self.multiCheck.setStyleSheet('background-color:#3daee9') else: self.multiCheck.setStyleSheet('background-color:#31363b')
def ui_components(self): font = QFont("Roboto", 16) title_label = QLabel("Convert currency:", self) title_label.move(7, 27) title_label.setFont(font) title_label.adjustSize() to_be_converted = QLineEdit(self) to_be_converted.setPlaceholderText("Amount") to_be_converted.setFont(font) to_be_converted.move(7, 67) to_be_converted.setFixedWidth(230) valid = QDoubleValidator() to_be_converted.setValidator(valid) converted = QLineEdit(self) converted.setPlaceholderText("Converted Amount") converted.isEnabled = False converted.move(7, 107) converted.setFixedWidth(230) converted.setFont(font) converted.setValidator(valid) currency_list_1 = QComboBox(self) currency_list_1.addItem("USD") currency_list_1.addItem("TND") currency_list_1.addItem("EUR") currency_list_1.move(260, 66) currency_list_2 = QComboBox(self) currency_list_2.addItem("USD") currency_list_2.addItem("TND") currency_list_2.addItem("EUR") currency_list_2.move(260, 100) convert_btn = QPushButton("Convert", self) convert_btn.move(260, 140) menubar = QMenuBar(self) Info = menubar.addMenu("Info") exchange = Info.addAction("Exchange rates") exchange.triggered.connect(self.open_exchange_rates) def convertor(): if str(currency_list_1.currentText()) == "USD" or str( currency_list_2.currentText()) == "USD": # ============== USD AND TND ================== if str(currency_list_2.currentText()) == "TND": rate_usd_tnd = Exchanges().usd_tnd() converted_amount = float( to_be_converted.text()) * float(rate_usd_tnd) if to_be_converted != '': converted.setText(str(converted_amount)) if str(currency_list_1.currentText()) == "TND": rate_usd_tnd = Exchanges().usd_tnd() converted_amount = float(to_be_converted.text()) * float( 1 / rate_usd_tnd) if to_be_converted != '': converted.setText(str(converted_amount)) # =============== EUR AND USD ================= if str(currency_list_2.currentText()) == "EUR": rate_usd_eur = Exchanges().usd_eur() converted_amount = float( to_be_converted.text()) * float(rate_usd_eur) if to_be_converted != '': converted.setText(str(converted_amount)) if str(currency_list_1.currentText()) == "EUR": rate_usd_eur = Exchanges().usd_eur() converted_amount = float(to_be_converted.text()) * float( 1 / rate_usd_eur) if to_be_converted != '': converted.setText(str(converted_amount)) if (currency_list_1.currentText()) == "TND" or ( currency_list_2.currentText()) == "TND": if str(currency_list_2.currentText()) == "EUR": rate_tnd_eur = Exchanges().tnd_eur() converted_amount = float( to_be_converted.text()) * float(rate_tnd_eur) if to_be_converted != '': converted.setText(str(converted_amount)) if str(currency_list_1.currentText()) == "EUR": rate_tnd_eur = Exchanges().tnd_eur() converted_amount = float(to_be_converted.text()) * float( 1 / rate_tnd_eur) if to_be_converted != '': converted.setText(str(converted_amount)) convert_btn.clicked.connect(convertor)
class VOGView(AbstractView): def __init__(self, name: str = "VOG_NONE", log_handlers: [StreamHandler] = None): self._logger = getLogger(__name__) if log_handlers: for h in log_handlers: self._logger.addHandler(h) self._logger.debug("Initializing") super().__init__(name) """ Min size for the VOG window """ self._subwindow_height = 222 self._subwindow_width = 518 """ min and max sizes for the configuration popup (width, height) """ self._popup_min = (229, 409) self._popup_max = (300, 409) """ Set configuration value display area""" self._config_frame = EasyFrame() self._config_vertical_layout = QVBoxLayout(self._config_frame) self._config_label = QLabel(self._config_frame) self._config_label.setAlignment(Qt.AlignCenter) self._config_val_line_edit = QLineEdit(self._config_frame) self._config_val_line_edit.setAlignment(Qt.AlignCenter) self._config_vertical_layout.addWidget(self._config_label) self._config_vertical_layout.addWidget(self._config_val_line_edit) """ Set preset button selection area. """ self._nhtsa_button = ClickAnimationButton() self._eblindfold_button = ClickAnimationButton() self._direct_control_button = ClickAnimationButton() """ Set open duration, close duration, and debounce time settings display area. """ self._input_box_frame = EasyFrame() self._input_box_grid_layout = QGridLayout(self._input_box_frame) self._input_box_grid_layout.setContentsMargins(0, 6, 0, 6) self._open_dur_label = QLabel(self._input_box_frame) self._open_dur_line_edit = QLineEdit(self._input_box_frame) self._open_dur_line_edit.setFixedWidth(80) self._open_inf_check_box = QCheckBox(self._input_box_frame) self._close_dur_label = QLabel(self._input_box_frame) self._close_dur_line_edit = QLineEdit(self._input_box_frame) self._close_dur_line_edit.setFixedWidth(80) self._close_inf_check_box = QCheckBox(self._input_box_frame) self._debounce_label = QLabel(self._input_box_frame) self._debounce_time_line_edit = QLineEdit(self._input_box_frame) self._debounce_time_line_edit.setFixedWidth(80) self._input_box_grid_layout.addWidget(self._open_dur_label, 0, 0, 1, 1) self._input_box_grid_layout.addWidget(self._open_dur_line_edit, 0, 1, 1, 1) self._input_box_grid_layout.addWidget(self._open_inf_check_box, 0, 2, 1, 1) self._input_box_grid_layout.addWidget(self._close_dur_label, 1, 0, 1, 1) self._input_box_grid_layout.addWidget(self._close_dur_line_edit, 1, 1, 1, 1) self._input_box_grid_layout.addWidget(self._close_inf_check_box, 1, 2, 1, 1) self._input_box_grid_layout.addWidget(self._debounce_label, 2, 0, 1, 1) self._input_box_grid_layout.addWidget(self._debounce_time_line_edit, 2, 1, 1, 1) """ Set button mode setting display area. """ self._button_mode_frame = EasyFrame() self._button_mode_horiz_layout = QGridLayout(self._button_mode_frame) self._button_mode_horiz_layout.setContentsMargins(0, 6, 0, 6) self._button_mode_label = QLabel(self._button_mode_frame) self._button_mode_selector = QComboBox(self._button_mode_frame) self._button_mode_selector.addItem("") self._button_mode_selector.addItem("") self._button_mode_horiz_layout.addWidget(self._button_mode_label, 0, 0, 1, 1) self._button_mode_horiz_layout.addWidget(self._button_mode_selector, 0, 1, 1, 1) """ Set control mode setting display area. """ self._control_mode_label = QLabel(self._button_mode_frame) self._control_mode_selector = QComboBox(self._button_mode_frame) self._control_mode_selector.addItem("") self._control_mode_selector.addItem("") self._button_mode_horiz_layout.addWidget(self._control_mode_label, 1, 0, 1, 1) self._button_mode_horiz_layout.addWidget(self._control_mode_selector, 1, 1, 1, 1) """ Set upload button selection area. """ self._upload_settings_button = ClickAnimationButton() """ Set manual control selection area. """ self._manual_control_button_frame = EasyFrame() self._manual_control_button_layout = QHBoxLayout( self._manual_control_button_frame) self._manual_control_open_button = ClickAnimationButton() self._manual_control_close_button = ClickAnimationButton() self._manual_control_button_layout.addWidget( self._manual_control_open_button) self._manual_control_button_layout.addWidget( self._manual_control_close_button) self._manual_control_button_layout.setMargin(0) """ device settings display """ self._dev_sets_frame = EasyFrame() self._dev_sets_layout = QVBoxLayout(self._dev_sets_frame) self.config_button = ClickAnimationButton() self.config_button.clicked.connect(self._config_button_handler) self._config_win = ConfigPopUp() self._config_win.setMinimumSize(self._popup_min[0], self._popup_min[1]) self._config_win.setMaximumSize(self._popup_max[0], self._popup_max[1]) self._config_win.setLayout(self._dev_sets_layout) """ Add widgets to layout. """ self._dev_sets_layout.addWidget(self._config_frame) self._dev_sets_layout.addWidget(self._input_box_frame) self._dev_sets_layout.addWidget(self._button_mode_frame) self._dev_sets_layout.addWidget(self._nhtsa_button) self._dev_sets_layout.addWidget(self._eblindfold_button) self._dev_sets_layout.addWidget(self._direct_control_button) self._dev_sets_layout.addWidget(self._upload_settings_button) self.layout().addWidget(self.config_button, 0, 0, Qt.AlignTop | Qt.AlignRight) self.config_button.setFixedSize(30, 25) self.layout().addWidget(self._manual_control_button_frame, 0, 0, Qt.AlignBottom | Qt.AlignLeft) self._manual_control_open_button.setFixedSize(70, 25) self._manual_control_close_button.setFixedSize(70, 25) self.layout().setMargin(0) self._strings = dict() self._lang_enum = LangEnum.ENG self.setMinimumSize(self._subwindow_width, self._subwindow_height) self.resize(self._subwindow_width, self._subwindow_height) self._logger.debug("Initialized") def add_graph(self, graph) -> None: """ Add Graph to view. :return None: """ self._logger.debug("running") self.layout().addWidget(graph, 0, 0) self.config_button.raise_() self._manual_control_button_frame.raise_() self._logger.debug("done") def _config_button_handler(self) -> None: """ handles the config button :return None: """ self._logger.debug("running") self._config_win.exec_() self._logger.debug("done") def set_config_val_line_edit_handler(self, func: classmethod) -> None: """ Sets the config val line handler. :param func: classmethod that handles the config val line. :return None: """ self._logger.debug("running") self._config_val_line_edit.textChanged.connect(func) self._logger.debug("done") def set_nhtsa_button_handler(self, func: classmethod) -> None: """ Sets NHTSA button press handler. :param func: classmethod that handles the NHTSA button. :return None: """ self._logger.debug("running") self._nhtsa_button.clicked.connect(func) self._logger.debug("done") def set_eblindfold_button_handler(self, func: classmethod) -> None: """ Sets eBlindfold button press handler. :param func: classmethod that handles the eBlindfold button. :return None: """ self._logger.debug("running") self._eblindfold_button.clicked.connect(func) self._logger.debug("done") def set_direct_control_button_handler(self, func: classmethod) -> None: """ Sets Direct Control button press handler. :param func: classmethod that handles the Direct Control button. :return None: """ self._logger.debug("running") self._direct_control_button.clicked.connect(func) self._logger.debug("done") def set_open_dur_line_edit_handler(self, func: classmethod) -> None: """ Sets open duration line edit handler. :param func: classmethod that handles the line edit. :return None: """ self._logger.debug("running") self._open_dur_line_edit.textChanged.connect(func) self._logger.debug("done") def set_close_dur_line_edit_handler(self, func: classmethod) -> None: """ Sets close duration line edit handler. :param func: classmethod that handles the line edit. :return None: """ self._logger.debug("running") self._close_dur_line_edit.textChanged.connect(func) self._logger.debug("done") def set_open_inf_check_box_handler(self, func: classmethod) -> None: """ Sets open INF checkbox handler. :param func: classmethod that handles the checkbox, requires bool param. :return None: """ self._logger.debug("running") self._open_inf_check_box.stateChanged.connect(func) self._logger.debug("done") def set_close_inf_check_box_handler(self, func: classmethod) -> None: """ Sets close INF checkbox handler. :param func: classmethod that handles the checkbox, requires bool param. :return None: """ self._logger.debug("running") self._close_inf_check_box.stateChanged.connect(func) self._logger.debug("done") def set_debounce_time_line_edit_handler(self, func: classmethod) -> None: """ Sets debounce time line edit handler. :param func: classmethod that handles the line edit. :return None: """ self._logger.debug("running") self._debounce_time_line_edit.textChanged.connect(func) self._logger.debug("done") def set_button_mode_selector_handler(self, func: classmethod) -> None: """ Sets button mode combo box handler. :param func: classmethod that handles the combo. :return None: """ self._logger.debug("running") self._button_mode_selector.currentIndexChanged.connect(func) self._logger.debug("done") def set_control_mode_selector_handler(self, func: classmethod) -> None: """ Sets button mode combo box handler. :param func: classmethod that handles the combo. :return None: """ self._logger.debug("running") self._control_mode_selector.currentIndexChanged.connect(func) self._logger.debug("done") def set_upload_settings_button_handler(self, func: classmethod) -> None: """ Sets upload settings button handler. :param func: classmethod that handles the button. :return None: """ self._logger.debug("running") self._upload_settings_button.clicked.connect(func) self._logger.debug("done") def set_manual_control_open_button_handler(self, func: classmethod) -> None: """ Sets manual open button handler. :param func: classmethod that handles the button. :return None: """ self._logger.debug("running") self._manual_control_open_button.clicked.connect(func) self._logger.debug("done") def set_manual_control_close_button_handler(self, func: classmethod) -> None: """ Sets manual close button handler. :param func: classmethod that handles the button. :return None: """ self._logger.debug("running") self._manual_control_close_button.clicked.connect(func) self._logger.debug("done") @property def config_text(self) -> str: """ Get the string value found in the config text box. :return str: string value in the text box. """ return self._config_val_line_edit.text() @config_text.setter def config_text(self, val: str) -> None: """ Set the string value found in the config text box. :param val: string value to set the config text box. :return None: """ self._logger.debug("running") self._config_val_line_edit.setText(val) self._logger.debug("done") @property def open_duration(self) -> str: """ Get the string value found in the open duration text box. :return str: string value in the text box. """ return self._open_dur_line_edit.text() @open_duration.setter def open_duration(self, val: str) -> None: """ Set the string value found in the open duration text box. :param val: string value to set the open duration text box. :return None: """ self._logger.debug("running") self._open_dur_line_edit.setText(val) self._logger.debug("done") @property def close_duration(self) -> str: """ Get the string value found in the close duration text box. :return str: string value in the text box. """ return self._close_dur_line_edit.text() @close_duration.setter def close_duration(self, val: str) -> None: """ Set the string value found in the close duration text box. :param val: string value to set the close duration text box. :return None: """ self._logger.debug("running") self._close_dur_line_edit.setText(val) self._logger.debug("done") @property def debounce_val(self) -> str: """ Get the string value found in the debounce time text box. :return str: string value in the text box. """ return self._debounce_time_line_edit.text() @debounce_val.setter def debounce_val(self, val: str) -> None: """ Set the string value found in the debounce time text box. :param val: string value to set the debounce text box. :return None: """ self._logger.debug("running") self._debounce_time_line_edit.setText(val) self._logger.debug("done") @property def open_inf_check_box(self) -> bool: """ Get the check box state. :return bool: returns true if the box is checked. """ return self._open_inf_check_box.isChecked() @open_inf_check_box.setter def open_inf_check_box(self, val: bool) -> None: """ Set the check box state. :param val: bool value to set the check box. :return None: """ self._logger.debug("running") self._open_inf_check_box.setChecked(val) self._logger.debug("done") @property def close_inf_check_box(self) -> bool: """ Get the check box state. :return bool: returns true if the box is checked. """ return self._close_inf_check_box.isChecked() @close_inf_check_box.setter def close_inf_check_box(self, val: bool) -> None: """ Set the check box state. :param val: bool value to set the check box. :return None: """ self._logger.debug("running") self._close_inf_check_box.setChecked(val) self._logger.debug("done") @property def button_mode(self) -> int: """ Get index of button mode. :return int: index of current button mode. """ return self._button_mode_selector.currentIndex() @button_mode.setter def button_mode(self, val: int) -> None: """ Set index of button mode. :return None: """ self._logger.debug("running") self._button_mode_selector.setCurrentIndex(val) self._logger.debug("done") @property def control_mode(self) -> int: """ Get index of button mode. :return int: index of current button mode. """ return self._control_mode_selector.currentIndex() @control_mode.setter def control_mode(self, val: int) -> None: """ Set index of button mode. :return None: """ self._logger.debug("running") self._control_mode_selector.setCurrentIndex(val) self._logger.debug("done") def set_open_dur_err(self, err: bool) -> None: """ Set this text entry to error style depending on err. :param err: If this text entry needs to be error styel :return None: """ self._logger.debug("running") if err: self._open_dur_line_edit.setStyleSheet(tab_line_edit_error_style) else: self._open_dur_line_edit.setStyleSheet( tab_line_edit_compliant_style) self._logger.debug("done") def set_close_dur_err(self, err: bool) -> None: """ Set this text entry to error style depending on err. :param err: If this text entry needs to be error styel :return None: """ self._logger.debug("running") if err: self._close_dur_line_edit.setStyleSheet(tab_line_edit_error_style) else: self._close_dur_line_edit.setStyleSheet( tab_line_edit_compliant_style) self._logger.debug("done") def set_debounce_err(self, err: bool) -> None: """ Set this text entry to error style depending on err. :param err: If this text entry needs to be error styel :return None: """ self._logger.debug("running") if err: self._debounce_time_line_edit.setStyleSheet( tab_line_edit_error_style) else: self._debounce_time_line_edit.setStyleSheet( tab_line_edit_compliant_style) self._logger.debug("done") @property def language(self) -> LangEnum: """ Get the current language setting :return LangEnum: The current language enumerator being used """ return self._lang_enum @language.setter def language(self, lang: LangEnum) -> None: """ Set the language for this view object and reload the text and tooltips. :param lang: the language to use. :return None: """ self._logger.debug("running") self._strings = strings[lang] self._set_texts() self._set_tooltips() self._logger.debug("done") def set_upload_button(self, is_active: bool) -> None: """ Set upload button activity to is_active. :param is_active: Whether this button should be active. :return None: """ self._logger.debug("running") self._upload_settings_button.setEnabled(is_active) self._logger.debug("done") def _set_texts(self) -> None: """ Set text fields of view object. :return None: """ self._logger.debug("running") self._config_label.setText(self._strings[StringsEnum.CONFIG_LABEL]) self._config_val_line_edit.setText( self._strings[StringsEnum.CONFIG_LABEL]) self._nhtsa_button.setText(self._strings[StringsEnum.NHTSA_LABEL]) self._eblindfold_button.setText( self._strings[StringsEnum.EBLIND_LABEL]) self._direct_control_button.setText( self._strings[StringsEnum.DCON_LABEL]) self._open_dur_label.setText( self._strings[StringsEnum.OPEN_DURATION_LABEL]) self._open_inf_check_box.setText(self._strings[StringsEnum.INF_LABEL]) self._close_dur_label.setText( self._strings[StringsEnum.CLOSE_DURATION_LABEL]) self._close_inf_check_box.setText(self._strings[StringsEnum.INF_LABEL]) self._debounce_label.setText(self._strings[StringsEnum.DEBOUNCE_LABEL]) self._button_mode_label.setText( self._strings[StringsEnum.BUTTON_MODE_LABEL]) self._button_mode_selector.setItemText( 0, self._strings[StringsEnum.HOLD_VAL_LABEL]) self._button_mode_selector.setItemText( 1, self._strings[StringsEnum.CLICK_VAL_LABEL]) self._control_mode_label.setText( self._strings[StringsEnum.CONTROL_MODE_LABEL]) self._control_mode_selector.setItemText( 0, self._strings[StringsEnum.LENS_VAL_LABEL]) self._control_mode_selector.setItemText( 1, self._strings[StringsEnum.TRIAL_VAL_LABEL]) self._upload_settings_button.setText( self._strings[StringsEnum.UPLOAD_BUTTON_LABEL]) self._manual_control_open_button.setText( self._strings[StringsEnum.MANUAL_OPEN_LABEL]) self._manual_control_close_button.setText( self._strings[StringsEnum.MANUAL_CLOSE_LABEL]) self.config_button.setText(self._strings[StringsEnum.CONFIG_TAB_LABEL]) self.config_button.setText("...") self._config_win.setWindowTitle( self.get_name() + " " + self._strings[StringsEnum.CONFIG_TAB_LABEL]) self._logger.debug("done") def _set_tooltips(self) -> None: """ Set tooltip text fields of view object. :return None: """ self._logger.debug("running") self._config_label.setToolTip( self._strings[StringsEnum.CONFIG_LABEL_TOOLTIP]) self._config_val_line_edit.setToolTip( self._strings[StringsEnum.CONFIG_LABEL_TOOLTIP]) self._open_dur_label.setToolTip( self._strings[StringsEnum.OPEN_DURATION_TOOLTIP]) self._close_dur_label.setToolTip( self._strings[StringsEnum.CLOSE_DURATION_TOOLTIP]) self._debounce_label.setToolTip( self._strings[StringsEnum.DEBOUNCE_TOOLTIP]) self._button_mode_label.setToolTip( self._strings[StringsEnum.BUTTON_MODE_TOOLTIP]) self._control_mode_label.setToolTip( self._strings[StringsEnum.CONTROL_MODE_TOOLTIP]) self._upload_settings_button.setToolTip( self._strings[StringsEnum.UPLOAD_BUTTON_TOOLTIP]) self._manual_control_open_button.setToolTip( self._strings[StringsEnum.MANUAL_OPEN_TOOLTIP]) self._manual_control_close_button.setToolTip( self._strings[StringsEnum.MANUAL_CLOSE_TOOLTIP]) self.config_button.setToolTip( self._strings[StringsEnum.CONFIG_TAB_TOOLTIP]) self._logger.debug("done")
class SettingsEditionDialog(QDialog): languages = {"Français": "fr", "English": "en"} def __init__(self): QDialog.__init__(self) self.setWindowTitle(tr("btn_config")) self.setFixedSize(QSize(700, 670)) # Retrieve current settings self.settings = AssetManager.getInstance().config_to_dico( AssetManager.getInstance().get_config_parser()) self.__restart_needed = False self.__restore_required = False # Version self.lab_version = QLabel(self.settings['main']['version']) # Language self.combo_language = QComboBox() self.combo_language.addItems(list(self.languages.keys())) for lang in self.languages: # Look for the current language to select it if self.languages[lang] == self.settings['main']['language']: self.combo_language.setCurrentText(lang) break # CSV separator self.csv_sep_edit = QLineEdit() self.csv_sep_edit.setMaxLength(2) self.csv_sep_edit.setFixedWidth(25) self.csv_sep_edit.setAlignment(Qt.AlignCenter) self.csv_sep_edit.setText(self.settings['main']['csv_separator']) # BDD path self.btn_bdd_path = QPushButton(self.settings['main']['bdd_path']) self.btn_bdd_path.clicked.connect(self.choose_bdd_path) # Port self.wepapp_port = QSpinBox() self.wepapp_port.setMinimum(1024) self.wepapp_port.setMaximum(65535) self.wepapp_port.setValue(int(self.settings['webapp']['port'])) # Colors self.tile_color = ColorChooser(self.settings['colors']['tile']) self.hovered_tile_color = ColorChooser( self.settings['colors']['hovered_tile']) self.hovered_empty_tile_color = ColorChooser( self.settings['colors']['hovered_empty_tile']) self.dragged_tile_color = ColorChooser( self.settings['colors']['dragged_tile']) self.drag_selected_tile_color = ColorChooser( self.settings['colors']['drag_selected_tile']) self.selected_tile_color = ColorChooser( self.settings['colors']['selected_tile']) self.tile_text_color = ColorChooser( self.settings['colors']['tile_text']) self.room_bg_color = ColorChooser(self.settings['colors']['room_bg']) self.room_grid_color = ColorChooser( self.settings['colors']['room_grid']) self.main_bg_color = ColorChooser(self.settings['colors']['main_bg']) self.board_bg_color = ColorChooser(self.settings['colors']['board_bg']) self.attr_colors = "" # Chosen colors self.attributes_colors_chooser = AttrColorsChooser( self.settings['colors']['attr_colors'].split()) # Sizes (unmodifiable) self.unmodifiable = QLabel(tr("unmodifiable_data")) self.unmodifiable.setAlignment(Qt.AlignCenter) self.desk_size = QLineEdit(self.settings['size']['desk']) self.desk_size.setEnabled(False) self.desk_size.setFixedWidth(50) self.grid_rows = QLineEdit(self.settings['size']['default_room_rows']) self.grid_rows.setEnabled(False) self.grid_rows.setFixedWidth(50) self.grid_cols = QLineEdit( self.settings['size']['default_room_columns']) self.grid_cols.setEnabled(False) self.grid_cols.setFixedWidth(50) # --- Buttons --- # Confirm button self.ok_btn = QPushButton(tr("btn_save")) self.ok_btn.clicked.connect(self.accept) self.ok_btn.setFocus() # Cancel button self.cancel_btn = QPushButton(tr("btn_cancel")) self.cancel_btn.clicked.connect(self.reject) # Restore defaults button self.restore_btn = QPushButton(tr("btn_restore")) self.restore_btn.clicked.connect(self.__restore) self.__set_layout() def __set_layout(self) -> None: """ Sets the dialog layout """ # Main layout layout = QVBoxLayout() layout.setMargin(0) layout.addSpacing(5) # Main section main_layout = QFormLayout() main_layout.addRow(tr("app_version"), self.lab_version) main_layout.addRow(tr("language"), self.combo_language) main_layout.addRow(tr("csv_sep"), self.csv_sep_edit) main_layout.addRow(tr("bdd_path"), self.btn_bdd_path) # Web app widget_port = QWidget() layout_port = QHBoxLayout() layout_port.setMargin(0) layout_port.addWidget(self.wepapp_port) layout_port.addWidget(ShutDownToolTip()) widget_port.setLayout(layout_port) main_layout.addRow(tr("web_port"), widget_port) layout.addLayout(main_layout) Separator(self.width(), layout) # Colors colors_layout1 = QFormLayout() colors_layout1.addRow(tr("tile"), self.tile_color) colors_layout1.addRow(tr("hovered_tile"), self.hovered_tile_color) colors_layout1.addRow(tr("hovered_empty_tile"), self.hovered_empty_tile_color) colors_layout1.addRow(tr("dragged_tile"), self.dragged_tile_color) colors_layout1.addRow(tr("drag_selected_tile"), self.drag_selected_tile_color) colors_layout1.addRow(tr("selected_tile"), self.selected_tile_color) colors_layout2 = QFormLayout() colors_layout2.addRow(tr("tile_text"), self.tile_text_color) colors_layout2.addRow(tr("room_bg"), self.room_bg_color) colors_layout2.addRow(tr("room_grid"), self.room_grid_color) colors_layout2.addRow(tr("main_bg"), self.main_bg_color) colors_layout2.addRow(tr("board_bg"), self.board_bg_color) colors_layout = QHBoxLayout() colors_layout.setMargin(0) colors_layout.addLayout(colors_layout1) colors_layout.addLayout(colors_layout2) layout.addLayout(colors_layout) layout.addSpacing(15) colors_layout3 = QFormLayout() colors_layout3.setMargin(0) colors_layout3.addRow(tr("attr_colors"), self.attributes_colors_chooser) layout.addLayout(colors_layout3) Separator(self.width(), layout) # Unmodifiable data sizes_layout = QFormLayout() sizes_layout.setMargin(0) sizes_layout.addRow(tr("desk_size"), self.desk_size) sizes_layout.addRow(tr("grid_rows"), self.grid_rows) sizes_layout.addRow(tr("grid_cols"), self.grid_cols) layout.addWidget(self.unmodifiable, alignment=Qt.AlignCenter) layout.addSpacing(5) layout.addLayout(sizes_layout) Separator(self.width(), layout) # Buttons layout_buttons = QHBoxLayout() layout_buttons.addWidget(self.ok_btn) layout_buttons.addWidget(self.restore_btn) layout_buttons.addWidget(self.cancel_btn) layout.addLayout(layout_buttons) self.setLayout(layout) self.setStyleSheet(get_stylesheet("dialog2")) def __restore(self) -> None: """ Restore default parameters before closing dialog """ self.__restart_needed = True self.__restore_required = True self.accept() def __new_settings(self) -> dict: """ Retrieves the new settings to use """ settings = self.settings # Language language = self.languages[self.combo_language.currentText()] if language != settings['main']['language']: settings['main']['language'] = language self.__restart_needed = True # CSV separator settings['main']['csv_separator'] = self.csv_sep_edit.text() # BDD path if self.btn_bdd_path.text() != settings['main']['bdd_path']: if self.btn_bdd_path.text().endswith("sdc_db"): settings['main']['bdd_path'] = self.btn_bdd_path.text() else: settings['main']['bdd_path'] = "" self.__restart_needed = True # Port if str(self.wepapp_port.value()) != settings['webapp']['port']: settings['webapp']['port'] = str(self.wepapp_port.value()) # Colors settings['colors']['tile'] = self.tile_color.get_color() settings['colors']['hovered_tile'] = self.hovered_tile_color.get_color( ) settings['colors'][ 'hovered_empty_tile'] = self.hovered_empty_tile_color.get_color() settings['colors']['dragged_tile'] = self.dragged_tile_color.get_color( ) settings['colors'][ 'drag_selected_tile'] = self.drag_selected_tile_color.get_color() settings['colors'][ 'selected_tile'] = self.selected_tile_color.get_color() settings['colors']['tile_text'] = self.tile_text_color.get_color() settings['colors']['room_grid'] = self.room_grid_color.get_color() if self.room_bg_color.get_color() != settings['colors']['room_bg']: settings['colors']['room_bg'] = self.room_bg_color.get_color() self.__restart_needed = True if self.main_bg_color.get_color() != settings['colors']['main_bg']: settings['colors']['main_bg'] = self.main_bg_color.get_color() self.__restart_needed = True if self.board_bg_color.get_color() != settings['colors']['board_bg']: settings['colors']['board_bg'] = self.board_bg_color.get_color() self.__restart_needed = True settings['colors']['attr_colors'] = self.attr_colors return settings def new_config(self) -> ConfigParser: """ Retrieves the new config parser object """ conf = ConfigParser() conf.read_dict(self.__new_settings()) return conf def need_restart(self): return self.__restart_needed def restore_default(self) -> bool: return self.__restore_required def accept(self) -> None: """ Performs actions before calling parent's accept method """ self.attr_colors = self.attributes_colors_chooser.get_colors_to_str() super().accept() def choose_bdd_path(self) -> None: """ Opens a file chooser to select the bdd path. Then sets the name as button text. """ bdd_path = QFileDialog.getOpenFileName(self, tr("bdd_path"), self.btn_bdd_path.text())[0] if bdd_path: self.btn_bdd_path.setText(bdd_path)
class SyncConfig(QDialog): def __init__(self, instance, parent=None): super().__init__(parent) self.setWindowTitle("Configure BinSync") if binsync is None: QMessageBox(self).critical(None, 'Dependency error', "binsync is not installed. Please install binsync first.") self.close() # initialization self._instance = instance self._main_layout = QVBoxLayout() self._user_edit = None # type:QLineEdit self._repo_edit = None # type:QLineEdit self._remote_edit = None # type:QLineEdit self._initrepo_checkbox = None # type:QCheckBox self._init_widgets() self.setLayout(self._main_layout) self.show() # # Private methods # def _init_widgets(self): upper_layout = QGridLayout() # user label user_label = QLabel(self) user_label.setText("User name") self._user_edit = QLineEdit(self) self._user_edit.setText("user0_angrm") row = 0 upper_layout.addWidget(user_label, row, 0) upper_layout.addWidget(self._user_edit, row, 1) row += 1 # binsync label binsync_label = QLabel(self) binsync_label.setText("Git repo") # repo path self._repo_edit = QLineEdit(self) self._repo_edit.textChanged.connect(self._on_repo_textchanged) self._repo_edit.setFixedWidth(150) # repo path selection button repo_button = QPushButton(self) repo_button.setText("...") repo_button.clicked.connect(self._on_repo_clicked) repo_button.setFixedWidth(40) upper_layout.addWidget(binsync_label, row, 0) upper_layout.addWidget(self._repo_edit, row, 1) upper_layout.addWidget(repo_button, row, 2) row += 1 # clone from a remote URL remote_label = QLabel(self) remote_label.setText("Remote URL") self._remote_edit = QLineEdit(self) self._remote_edit.setEnabled(False) upper_layout.addWidget(remote_label, row, 0) upper_layout.addWidget(self._remote_edit, row, 1) row += 1 # initialize repo checkbox self._initrepo_checkbox = QCheckBox(self) self._initrepo_checkbox.setText("Initialize repo") self._initrepo_checkbox.setToolTip("I'm the first user of this sync repo and I'd like to initialize it as a new " "repo.") self._initrepo_checkbox.setChecked(False) self._initrepo_checkbox.setEnabled(False) upper_layout.addWidget(self._initrepo_checkbox, row, 1) row += 1 # buttons ok_button = QPushButton(self) ok_button.setText("OK") ok_button.setDefault(True) ok_button.clicked.connect(self._on_ok_clicked) cancel_button = QPushButton(self) cancel_button.setText("Cancel") cancel_button.clicked.connect(self._on_cancel_clicked) buttons_layout = QHBoxLayout() buttons_layout.addWidget(ok_button) buttons_layout.addWidget(cancel_button) # main layout self._main_layout.addLayout(upper_layout) self._main_layout.addLayout(buttons_layout) # # Event handlers # def _on_ok_clicked(self): proj = self._instance.project user = self._user_edit.text() path = self._repo_edit.text() if not user: QMessageBox(self).critical(None, "Invalid user name", "User name cannot be empty." ) return if not os.path.isdir(path): QMessageBox(self).critical(None, "Repo does not exist", "The specified sync repo does not exist." ) return # TODO: Add a user ID to angr management if not self.is_git_repo(path): init_repo = self._initrepo_checkbox.isChecked() remote_url = self._remote_edit.text() else: init_repo = False remote_url = None self._instance.sync.connect(user, path, init_repo=init_repo, remote_url=remote_url) self._instance.workspace.view_manager.first_view_in_category('sync').reload() self.close() def _on_repo_clicked(self): dir = QFileDialog.getExistingDirectory(self, "Select sync repo", "", QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks) self._repo_edit.setText(QDir.toNativeSeparators(dir)) def _on_repo_textchanged(self, new_text): # is it a git repo? if not self.is_git_repo(new_text.strip()): # no it's not # maybe we want to clone from the remote side? self._remote_edit.setEnabled(True) self._initrepo_checkbox.setEnabled(True) else: # yes it is! # we don't want to initialize it or allow cloning from the remote side self._remote_edit.setEnabled(False) self._initrepo_checkbox.setEnabled(False) def _on_cancel_clicked(self): self.close() # # Static methods # @staticmethod def is_git_repo(path): return os.path.isdir(os.path.join(path, ".git"))
class Ui_FE14CharacterEditor(QMainWindow): def __init__(self, parent=None): super().__init__(parent) self.search_bar = QLineEdit() self.search_bar.setPlaceholderText("Search...") self.search_bar.setFixedWidth(225) self.characters_list_view = QListView() self.characters_list_view.setContextMenuPolicy( QtCore.Qt.CustomContextMenu) self.characters_list_view.setFixedWidth(225) self.characters_list_layout = QVBoxLayout() self.characters_list_layout.addWidget(self.search_bar) self.characters_list_layout.addWidget(self.characters_list_view) self.character_details_box = QGroupBox(title="Character Details") self.portrait_display = QGraphicsView() self.portrait_display.setFixedSize(140, 140) self.character_details_form_contents_1 = QWidget() self.character_details_form_contents_2 = QWidget() self.character_details_layout = QHBoxLayout() self.character_details_layout.addWidget(self.portrait_display) self.character_details_layout.addWidget( self.character_details_form_contents_1) self.character_details_layout.addWidget( self.character_details_form_contents_2) self.character_details_box.setLayout(self.character_details_layout) self.character_details_box.setFixedHeight(200) self.tab_widget = QTabWidget() self.ids_tab = QWidget() self.classes_tab = QWidget() self.stats_tab = QScrollArea() self.skills_tab = QScrollArea() self.misc_tab = QScrollArea() self.portraits_tab = PortraitViewer() self.stats_contents = QWidget() self.stats_tab.setWidget(self.stats_contents) self.stats_tab.setWidgetResizable(True) self.stats_layout = QVBoxLayout() self.stats_layout.setAlignment(QtCore.Qt.AlignTop) self.stats_contents.setLayout(self.stats_layout) self.skills_contents = QWidget() self.skills_tab.setWidget(self.skills_contents) self.skills_tab.setWidgetResizable(True) self.misc_contents = QWidget() self.misc_tab.setWidget(self.misc_contents) self.misc_tab.setWidgetResizable(True) self.misc_layout = QVBoxLayout() self.misc_layout.setAlignment(QtCore.Qt.AlignTop) self.misc_contents.setLayout(self.misc_layout) self.tab_widget.addTab(self.ids_tab, "IDs") self.tab_widget.addTab(self.classes_tab, "Classes") self.tab_widget.addTab(self.stats_tab, "Stats") self.tab_widget.addTab(self.skills_tab, "Skills") self.tab_widget.addTab(self.misc_tab, "Misc.") self.tab_widget.addTab(self.portraits_tab, "Portraits") self.editor_layout = QVBoxLayout() self.editor_layout.addWidget(self.character_details_box) self.editor_layout.addWidget(self.tab_widget) self.main_layout = QHBoxLayout() self.main_layout.addLayout(self.characters_list_layout) self.visual_splitter = QFrame() self.visual_splitter.setFrameShape(QFrame.VLine) self.visual_splitter.setFrameShadow(QFrame.Sunken) self.main_layout.addWidget(self.visual_splitter) self.main_layout.addLayout(self.editor_layout) self.tool_bar = QToolBar() self.action_add = QAction(text="Add") self.action_remove = QAction(text="Remove") self.action_copy_to = QAction(text="Copy To") self.tool_bar.addActions( [self.action_add, self.action_remove, self.action_copy_to]) self.addToolBar(self.tool_bar) self.resize(1000, 600) central_widget = QWidget() central_widget.setLayout(self.main_layout) self.setWindowTitle("Character Editor") self.setWindowIcon(QIcon("paragon.ico")) self.setCentralWidget(central_widget)
class Natang_mayammd(QWidget): ''' mayaからmmdモデルへエクスポートするためのウィンドウ ''' def __init__(self, parent): QWidget.__init__(self) self.parent = parent self.setWindowFlags(Qt.WindowStaysOnTopHint) self.setWindowTitle('~ Maya > MMD ~') self.setStyleSheet('font-size: 15px; color: #ddf;') vbl = QVBoxLayout() self.setLayout(vbl) self.file_khatangton = os.path.join(os.path.dirname(__file__), 'asset', 'khatangton2.txt') try: with open(self.file_khatangton, 'r', encoding='utf-8') as f: chue_tem_file = f.readline().split('=')[-1].strip() satsuan = f.readline().split('=')[-1].strip() chai_bs = int(f.readline().split('=')[-1].strip()) chai_kraduk = int(f.readline().split('=')[-1].strip()) chai_watsadu = int(f.readline().split('=')[-1].strip()) lok_tex = int(f.readline().split('=')[-1].strip()) thangmot = int(f.readline().split('=')[-1].strip()) pit_mai = int(f.readline().split('=')[-1].strip()) except: chue_tem_file = '' satsuan = '0.125' chai_bs = True chai_kraduk = True chai_watsadu = True lok_tex = False thangmot = False pit_mai = True hbl = QHBoxLayout() vbl.addLayout(hbl) hbl.addWidget(QLabel('ファイル')) self.le_chue_file = QLineEdit(chue_tem_file) hbl.addWidget(self.le_chue_file) self.le_chue_file.setFixedWidth(300) self.le_chue_file.textChanged.connect(self.chue_thuk_kae) self.btn_khon_file = QPushButton('...') hbl.addWidget(self.btn_khon_file) self.btn_khon_file.clicked.connect(self.khon_file) hbl = QHBoxLayout() vbl.addLayout(hbl) hbl.addWidget(QLabel('尺度')) self.le_satsuan = QLineEdit(satsuan) hbl.addWidget(self.le_satsuan) self.le_satsuan.setFixedWidth(100) self.le_satsuan.textEdited.connect(self.satsuan_thuk_kae) hbl.addWidget(QLabel('×')) hbl.addStretch() self.cb_chai_kraduk = QCheckBox('骨も作る') vbl.addWidget(self.cb_chai_kraduk) self.cb_chai_kraduk.setChecked(chai_kraduk) self.cb_chai_bs = QCheckBox('モーフも作る') vbl.addWidget(self.cb_chai_bs) self.cb_chai_bs.setChecked(chai_bs) self.cb_chai_watsadu = QCheckBox('材質を使う') vbl.addWidget(self.cb_chai_watsadu) self.cb_chai_watsadu.setChecked(chai_watsadu) self.cb_lok_tex = QCheckBox('テクスチャファイルをコピーする') vbl.addWidget(self.cb_lok_tex) self.cb_lok_tex.setChecked(lok_tex) hbl = QHBoxLayout() vbl.addLayout(hbl) hbl.addWidget(QLabel('使うポリゴン')) self.btng = QButtonGroup() self.rb_thangmot = QRadioButton('全部') hbl.addWidget(self.rb_thangmot) self.btng.addButton(self.rb_thangmot) self.rb_thilueak = QRadioButton('選択されている') hbl.addWidget(self.rb_thilueak) self.btng.addButton(self.rb_thilueak) hbl.addStretch() if (thangmot): self.rb_thangmot.setChecked(True) else: self.rb_thilueak.setChecked(True) hbl = QHBoxLayout() vbl.addLayout(hbl) hbl.addStretch() self.btn_roem_sang = QPushButton('作成開始') hbl.addWidget(self.btn_roem_sang) self.btn_roem_sang.clicked.connect(self.roem_sang) self.btn_roem_sang.setFixedSize(220, 50) self.chue_thuk_kae(self.le_chue_file.text()) self.cb_pit = QCheckBox('終わったらこの\nウィンドウを閉じる') hbl.addWidget(self.cb_pit) self.cb_pit.setChecked(pit_mai) def khon_file(self): self.setWindowFlags(self.windowFlags() & ~Qt.WindowStaysOnTopHint) chue_file, ok = QFileDialog.getSaveFileName(filter='PMX (*.pmx)') if (ok): self.le_chue_file.setText(chue_file) self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint) self.show() def chue_thuk_kae(self, chue_file): sakun = chue_file.split('.')[-1] sang_dai = (sakun.lower() == 'pmx') self.btn_roem_sang.setEnabled(sang_dai) self.btn_roem_sang.setStyleSheet( ['text-decoration: line-through; color: #aab;', ''][sang_dai]) def satsuan_thuk_kae(self, kha): try: float(kha) except: self.le_satsuan.setText('1') def roem_sang(self): chue_tem_file = self.le_chue_file.text() try: satsuan = float(self.le_satsuan.text()) except: self.le_satsuan.setText('1') satsuan = 1. chai_watsadu = self.cb_chai_watsadu.isChecked() chai_bs = self.cb_chai_bs.isChecked() chai_kraduk = self.cb_chai_kraduk.isChecked() lok_tex = self.cb_lok_tex.isChecked() thangmot = self.btng.checkedButton() == self.rb_thangmot mayapaipmx.sang(chue_tem_file, satsuan, chai_kraduk, chai_bs, chai_watsadu, lok_tex, thangmot) pit_mai = self.cb_pit.isChecked() with open(self.file_khatangton, 'w', encoding='utf-8') as f: f.write('ファイルの名前 = %s\n' % chue_tem_file) f.write('尺度 = %f\n' % satsuan) f.write('ブレンドシェープ = %d\n' % chai_bs) f.write('ジョイント = %d\n' % chai_kraduk) f.write('材質 = %d\n' % chai_watsadu) f.write('テクスチャのコピー = %d\n' % lok_tex) f.write('ポリゴン全部 = %d\n' % thangmot) f.write('閉じる = %d\n' % pit_mai) if (pit_mai): self.close() def keyPressEvent(self, e): if (e.key() == Qt.Key_Escape): self.close() def closeEvent(self, e): self.parent.natangyoi['mayammd'] = None
class Preferences(QDialog): def __init__(self, prefs, icon=None): super().__init__() self.prefs = prefs self.hotkey_format_regex = r'^\<ctrl\>\+\<alt\>(\+\<shift\>)?\+[a-zA-Z0-9]$' if icon: self.setWindowIcon(icon) # checkbox: Include Minimized include_minimized = QCheckBox() include_minimized.setFixedWidth(35) include_minimized.setChecked(self.prefs["include_minimized"]["value"]) include_minimized.stateChanged.connect( lambda: self.include_minimized(include_minimized.isChecked())) include_minimized_descr = QLabel( self.prefs["include_minimized"]["description"]) include_minimized_descr.setWordWrap(True) include_minimized_layout = QHBoxLayout() include_minimized_layout.addWidget(include_minimized) include_minimized_layout.addWidget(include_minimized_descr) include_minimized_groupbox = QGroupBox("Include Minimized") include_minimized_groupbox.setLayout(include_minimized_layout) # checkbox: snap to grid snap_to_grid = QCheckBox() snap_to_grid.setFixedWidth(35) snap_to_grid.setChecked(self.prefs["snap_to_grid"]["value"]) snap_to_grid.stateChanged.connect( lambda: self.snap_to_grid(snap_to_grid.isChecked())) snap_to_grid_descr = QLabel(self.prefs["snap_to_grid"]["description"]) snap_to_grid_descr.setWordWrap(True) snap_to_grid_layout = QHBoxLayout() snap_to_grid_layout.addWidget(snap_to_grid) snap_to_grid_layout.addWidget(snap_to_grid_descr) snap_to_grid_groupbox = QGroupBox("Snap To Grid") snap_to_grid_groupbox.setLayout(snap_to_grid_layout) # checkbox: fit into screen fit_into_screen = QCheckBox() fit_into_screen.setFixedWidth(35) fit_into_screen.setChecked(self.prefs["fit_into_screen"]["value"]) fit_into_screen.stateChanged.connect( lambda: self.fit_into_screen(fit_into_screen.isChecked())) fit_into_screen_descr = QLabel( self.prefs["fit_into_screen"]["description"]) fit_into_screen_descr.setWordWrap(True) fit_into_screen_layout = QHBoxLayout() fit_into_screen_layout.addWidget(fit_into_screen) fit_into_screen_layout.addWidget(fit_into_screen_descr) fit_into_screen_groupbox = QGroupBox("Fit Into Screen") fit_into_screen_groupbox.setLayout(fit_into_screen_layout) # doublespinBox: match cutoff match_cutoff = QDoubleSpinBox() match_cutoff.setFixedWidth(35) match_cutoff.setValue(self.prefs["match_cutoff"]["value"]) match_cutoff.setRange(0.1, 1.0) match_cutoff.setSingleStep(0.1) match_cutoff.setDecimals(1) match_cutoff.valueChanged.connect( lambda: self.match_cutoff(match_cutoff.value())) match_cutoff_descr = QLabel(self.prefs["match_cutoff"]["description"]) match_cutoff_descr.setWordWrap(True) match_cutoff_layout = QHBoxLayout() match_cutoff_layout.addWidget(match_cutoff) match_cutoff_layout.addWidget(match_cutoff_descr) match_cutoff_groupbox = QGroupBox("Match Cutoff") match_cutoff_groupbox.setLayout(match_cutoff_layout) # checkbox: enable hotkeys enable_hotkeys = QCheckBox() enable_hotkeys.setFixedWidth(35) enable_hotkeys.setChecked(self.prefs["enable_hotkeys"]["value"]) enable_hotkeys.stateChanged.connect( lambda: self.enable_hotkeys(enable_hotkeys.isChecked())) enable_hotkeys_descr = QLabel( self.prefs["enable_hotkeys"]["description"]) enable_hotkeys_descr.setWordWrap(True) enable_hotkeys_layout = QHBoxLayout() enable_hotkeys_layout.addWidget(enable_hotkeys) enable_hotkeys_layout.addWidget(enable_hotkeys_descr) # lineedit: hotkeys shortcuts hotkey_freeze_new_name = QLabel("Freeze New:") hotkey_freeze_new_name.setFixedWidth(75) self.hotkey_freeze_new_status = QLabel() self.hotkey_freeze_new = QLineEdit( self.prefs["hotkeys"]["value"]["freeze_new"]) self.hotkey_freeze_new.setFixedWidth(140) self.hotkey_freeze_new.editingFinished.connect( lambda: self.hotkey_freeze_new_update(self.hotkey_freeze_new.text( ))) self.hotkey_freeze_new.cursorPositionChanged.connect( self.hotkey_freeze_new_status.clear) hotkey_freeze_new_layout = QHBoxLayout() hotkey_freeze_new_layout.addWidget(hotkey_freeze_new_name) hotkey_freeze_new_layout.addWidget(self.hotkey_freeze_new) hotkey_freeze_new_layout.addWidget(self.hotkey_freeze_new_status) hotkey_freeze_all_name = QLabel("Freeze All:") hotkey_freeze_all_name.setFixedWidth(75) self.hotkey_freeze_all_status = QLabel() self.hotkey_freeze_all = QLineEdit( self.prefs["hotkeys"]["value"]["freeze_all"]) self.hotkey_freeze_all.setFixedWidth(140) self.hotkey_freeze_all.editingFinished.connect( lambda: self.hotkey_freeze_all_update(self.hotkey_freeze_all.text( ))) self.hotkey_freeze_all.cursorPositionChanged.connect( self.hotkey_freeze_all_status.clear) hotkey_freeze_all_layout = QHBoxLayout() hotkey_freeze_all_layout.addWidget(hotkey_freeze_all_name) hotkey_freeze_all_layout.addWidget(self.hotkey_freeze_all) hotkey_freeze_all_layout.addWidget(self.hotkey_freeze_all_status) hotkey_restore_name = QLabel("Restore:") hotkey_restore_name.setFixedWidth(75) self.hotkey_restore_status = QLabel() self.hotkey_restore = QLineEdit( self.prefs["hotkeys"]["value"]["restore"]) self.hotkey_restore.setFixedWidth(140) self.hotkey_restore.editingFinished.connect( lambda: self.hotkey_restore_update(self.hotkey_restore.text())) self.hotkey_restore.cursorPositionChanged.connect( self.hotkey_restore_status.clear) hotkey_restore_layout = QHBoxLayout() hotkey_restore_layout.addWidget(hotkey_restore_name) hotkey_restore_layout.addWidget(self.hotkey_restore) hotkey_restore_layout.addWidget(self.hotkey_restore_status) self.hotkeys_statusbar = QLabel() self.hotkeys_statusbar.setWordWrap(True) self.hotkeys_statusbar.setText(hotkeys_statusbar_map[ self.prefs['enable_hotkeys']['value']]['text']) self.hotkeys_statusbar.setStyleSheet(hotkeys_statusbar_map[ self.prefs['enable_hotkeys']['value']]['style']) close_button = QPushButton("Close") close_button.setMaximumWidth(75) close_button.clicked.connect(self.close) hotkeys_statusbar_layout = QHBoxLayout() hotkeys_statusbar_layout.addWidget(self.hotkeys_statusbar) hotkeys_statusbar_layout.addWidget(close_button) hotkeys_layout = QVBoxLayout() hotkeys_layout.addLayout(hotkey_freeze_new_layout) hotkeys_layout.addLayout(hotkey_freeze_all_layout) hotkeys_layout.addLayout(hotkey_restore_layout) self.hotkeys_groupbox = QGroupBox() self.hotkeys_groupbox.setFlat(True) self.hotkeys_groupbox.setDisabled( not self.prefs["enable_hotkeys"]["value"]) self.hotkeys_groupbox.setLayout(hotkeys_layout) enable_hotkeys_outer_layout = QVBoxLayout() enable_hotkeys_outer_layout.addLayout(enable_hotkeys_layout) enable_hotkeys_outer_layout.addWidget(self.hotkeys_groupbox) enable_hotkeys_groupbox = QGroupBox("Enable Hotkeys") enable_hotkeys_groupbox.setLayout(enable_hotkeys_outer_layout) # Create main layout and add widgets main_layout = QVBoxLayout() main_layout.addWidget(include_minimized_groupbox) main_layout.addWidget(snap_to_grid_groupbox) main_layout.addWidget(fit_into_screen_groupbox) main_layout.addWidget(match_cutoff_groupbox) main_layout.addWidget(enable_hotkeys_groupbox) main_layout.addWidget(self.hotkeys_groupbox) #main_layout.addWidget(hotkeys_statusbar_groupbox) main_layout.addLayout(hotkeys_statusbar_layout) self.setLayout(main_layout) def include_minimized(self, isChecked): print(f'include_minimized: {isChecked}') self.prefs["include_minimized"]["value"] = isChecked def snap_to_grid(self, isChecked): print(f'snap_to_grid: {isChecked}') self.prefs["snap_to_grid"]["value"] = isChecked def fit_into_screen(self, isChecked): print(f'fit_into_screen: {isChecked}') self.prefs["fit_into_screen"]["value"] = isChecked def match_cutoff(self, value): rounded_value = round(value, 1) print(f'match_cutoff: {rounded_value}') self.prefs["match_cutoff"]["value"] = rounded_value def enable_hotkeys(self, isChecked): print(f'enable_hotkeys: {isChecked}') self.prefs["enable_hotkeys"]["value"] = isChecked self.hotkeys_groupbox.setDisabled(not isChecked) self.hotkeys_statusbar.setText( hotkeys_statusbar_map[isChecked]['text']) self.hotkeys_statusbar.setStyleSheet( hotkeys_statusbar_map[isChecked]['style']) def hotkey_freeze_new_update(self, text): print(f'hotkey_freeze_new: {text}') if re.match(self.hotkey_format_regex, text): self.prefs["hotkeys"]["value"]["freeze_new"] = text self.hotkey_freeze_new_status.setText(f'Updated!') self.hotkey_freeze_new_status.setStyleSheet("color: green;") else: self.hotkey_freeze_new.setText( self.prefs["hotkeys"]["value"]["freeze_new"]) self.hotkey_freeze_new_status.setText( 'Failed to update: unsupported format') self.hotkey_freeze_new_status.setStyleSheet("color: red;") def hotkey_freeze_all_update(self, text): print(f'hotkey_freeze_all: {text}') if re.match(self.hotkey_format_regex, text): self.prefs["hotkeys"]["value"]["freeze_all"] = text self.hotkey_freeze_all_status.setText(f'Updated!') self.hotkey_freeze_all_status.setStyleSheet("color: green;") else: self.hotkey_freeze_all.setText( self.prefs["hotkeys"]["value"]["freeze_all"]) self.hotkey_freeze_all_status.setText( 'Failed to update: unsupported format') self.hotkey_freeze_all_status.setStyleSheet("color: red;") def hotkey_restore_update(self, text): print(f'hotkey_restore: {text}') if re.match(self.hotkey_format_regex, text): self.prefs["hotkeys"]["value"]["restore"] = text self.hotkey_restore_status.setText(f'Updated!') self.hotkey_restore_status.setStyleSheet("color: green;") else: self.hotkey_restore.setText( self.prefs["hotkeys"]["value"]["restore"]) self.hotkey_restore_status.setText( 'Failed to update: unsupported format') self.hotkey_restore_status.setStyleSheet("color: red;")
class VideoPlayer(QWidget): def __init__(self, aPath, parent=None): super(VideoPlayer, self).__init__(parent) self.setAttribute(Qt.WA_NoSystemBackground, True) self.setAcceptDrops(True) self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.StreamPlayback) self.mediaPlayer.mediaStatusChanged.connect(self.printMediaData) self.mediaPlayer.setVolume(80) self.videoWidget = QVideoWidget(self) self.lbl = QLineEdit('00:00:00') self.lbl.setReadOnly(True) self.lbl.setFixedWidth(70) self.lbl.setUpdatesEnabled(True) self.lbl.setStyleSheet(stylesheet(self)) self.lbl.selectionChanged.connect(lambda: self.lbl.setSelection(0, 0)) self.elbl = QLineEdit('00:00:00') self.elbl.setReadOnly(True) self.elbl.setFixedWidth(70) self.elbl.setUpdatesEnabled(True) self.elbl.setStyleSheet(stylesheet(self)) self.elbl.selectionChanged.connect( lambda: self.elbl.setSelection(0, 0)) self.playButton = QPushButton() self.playButton.setEnabled(False) self.playButton.setFixedWidth(32) self.playButton.setStyleSheet("background-color: black") self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.playButton.clicked.connect(self.play) self.positionSlider = QSlider(Qt.Horizontal, self) self.positionSlider.setStyleSheet(stylesheet(self)) self.positionSlider.setRange(0, 100) self.positionSlider.sliderMoved.connect(self.setPosition) self.positionSlider.setSingleStep(2) self.positionSlider.setPageStep(20) self.positionSlider.setAttribute(Qt.WA_TranslucentBackground, True) self.clip = QApplication.clipboard() self.process = QProcess(self) self.process.readyRead.connect(self.dataReady) self.process.finished.connect(self.playFromURL) self.myurl = "" controlLayout = QHBoxLayout() controlLayout.setContentsMargins(5, 0, 5, 0) controlLayout.addWidget(self.playButton) controlLayout.addWidget(self.lbl) controlLayout.addWidget(self.positionSlider) controlLayout.addWidget(self.elbl) layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(self.videoWidget) layout.addLayout(controlLayout) self.setLayout(layout) self.myinfo = "©2016\nAxel Schneider\n\nMouse Wheel = Zoom\nUP = Volume Up\nDOWN = Volume Down\n" + \ "LEFT = < 1 Minute\nRIGHT = > 1 Minute\n" + \ "SHIFT+LEFT = < 10 Minutes\nSHIFT+RIGHT = > 10 Minutes" self.widescreen = True #### shortcuts #### self.shortcut = QShortcut(QKeySequence("q"), self) self.shortcut.activated.connect(self.handleQuit) self.shortcut = QShortcut(QKeySequence("u"), self) self.shortcut.activated.connect(self.playFromURL) self.shortcut = QShortcut(QKeySequence("y"), self) self.shortcut.activated.connect(self.getYTUrl) self.shortcut = QShortcut(QKeySequence("o"), self) self.shortcut.activated.connect(self.openFile) self.shortcut = QShortcut(QKeySequence(" "), self) self.shortcut.activated.connect(self.play) self.shortcut = QShortcut(QKeySequence("f"), self) self.shortcut.activated.connect(self.handleFullscreen) self.shortcut = QShortcut(QKeySequence("i"), self) self.shortcut.activated.connect(self.handleInfo) self.shortcut = QShortcut(QKeySequence("s"), self) self.shortcut.activated.connect(self.toggleSlider) self.shortcut = QShortcut(QKeySequence(Qt.Key_Right), self) self.shortcut.activated.connect(self.forwardSlider) self.shortcut = QShortcut(QKeySequence(Qt.Key_Left), self) self.shortcut.activated.connect(self.backSlider) self.shortcut = QShortcut(QKeySequence(Qt.Key_Up), self) self.shortcut.activated.connect(self.volumeUp) self.shortcut = QShortcut(QKeySequence(Qt.Key_Down), self) self.shortcut.activated.connect(self.volumeDown) self.shortcut = QShortcut( QKeySequence(Qt.ShiftModifier + Qt.Key_Right), self) self.shortcut.activated.connect(self.forwardSlider10) self.shortcut = QShortcut(QKeySequence(Qt.ShiftModifier + Qt.Key_Left), self) self.shortcut.activated.connect(self.backSlider10) self.mediaPlayer.setVideoOutput(self.videoWidget) self.mediaPlayer.stateChanged.connect(self.mediaStateChanged) self.mediaPlayer.positionChanged.connect(self.positionChanged) self.mediaPlayer.durationChanged.connect(self.durationChanged) self.mediaPlayer.error.connect(self.handleError) print("QT5 Player started") print("press 'o' to open file (see context menu for more)") self.suspend_screensaver() def mouseDoubleClickEvent(self, event): self.handleFullscreen() def playFromURL(self): self.mediaPlayer.pause() self.myurl = self.clip.text() self.mediaPlayer.setMedia(QMediaContent(QUrl(self.myurl))) self.playButton.setEnabled(True) self.mediaPlayer.play() self.hideSlider() print(self.myurl) def getYTUrl(self): cmd = "youtube-dl -g -f best " + self.clip.text() print("grabbing YouTube URL") self.process.start(cmd) def dataReady(self): self.myurl = str(self.process.readAll(), encoding='utf8').rstrip() ### self.myurl = self.myurl.partition("\n")[0] print(self.myurl) self.clip.setText(self.myurl) self.playFromURL() def suspend_screensaver(self): 'suspend linux screensaver' proc = subprocess.Popen( 'gsettings set org.gnome.desktop.screensaver idle-activation-enabled false', shell=True) proc.wait() def resume_screensaver(self): 'resume linux screensaver' proc = subprocess.Popen( 'gsettings set org.gnome.desktop.screensaver idle-activation-enabled true', shell=True) proc.wait() def openFile(self): fileName, _ = QFileDialog.getOpenFileName( self, "Open Movie", QDir.homePath() + "/Videos", "Media (*.webm *.mp4 *.ts *.avi *.mpeg *.mpg *.mkv *.VOB *.m4v *.3gp *.mp3 *.m4a *.wav *.ogg *.flac *.m3u *.m3u8)" ) if fileName != '': self.loadFilm(fileName) print("File loaded") def play(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() def mediaStateChanged(self, state): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPause)) else: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPlay)) def positionChanged(self, position): self.positionSlider.setValue(position) mtime = QTime(0, 0, 0, 0) mtime = mtime.addMSecs(self.mediaPlayer.position()) self.lbl.setText(mtime.toString()) def durationChanged(self, duration): self.positionSlider.setRange(0, duration) mtime = QTime(0, 0, 0, 0) mtime = mtime.addMSecs(self.mediaPlayer.duration()) self.elbl.setText(mtime.toString()) def setPosition(self, position): self.mediaPlayer.setPosition(position) def handleError(self): self.playButton.setEnabled(False) print("Error: ", self.mediaPlayer.errorString()) def handleQuit(self): self.mediaPlayer.stop() self.resume_screensaver() print("Goodbye ...") app.quit() def contextMenuRequested(self, point): menu = QMenu() actionFile = menu.addAction(QIcon.fromTheme("video-x-generic"), "open File (o)") actionclipboard = menu.addSeparator() actionURL = menu.addAction(QIcon.fromTheme("browser"), "URL from Clipboard (u)") actionclipboard = menu.addSeparator() actionYTurl = menu.addAction(QIcon.fromTheme("youtube"), "URL from YouTube (y)") actionclipboard = menu.addSeparator() actionToggle = menu.addAction(QIcon.fromTheme("next"), "show / hide Slider (s)") actionFull = menu.addAction(QIcon.fromTheme("view-fullscreen"), "Fullscreen (f)") action169 = menu.addAction(QIcon.fromTheme("tv-symbolic"), "16 : 9") action43 = menu.addAction(QIcon.fromTheme("tv-symbolic"), "4 : 3") actionSep = menu.addSeparator() actionInfo = menu.addAction(QIcon.fromTheme("help-about"), "Info (i)") action5 = menu.addSeparator() actionQuit = menu.addAction(QIcon.fromTheme("application-exit"), "Exit (q)") actionFile.triggered.connect(self.openFile) actionQuit.triggered.connect(self.handleQuit) actionFull.triggered.connect(self.handleFullscreen) actionInfo.triggered.connect(self.handleInfo) actionToggle.triggered.connect(self.toggleSlider) actionURL.triggered.connect(self.playFromURL) actionYTurl.triggered.connect(self.getYTUrl) action169.triggered.connect(self.screen169) action43.triggered.connect(self.screen43) menu.exec_(self.mapToGlobal(point)) def wheelEvent(self, event): mwidth = self.frameGeometry().width() mheight = self.frameGeometry().height() mleft = self.frameGeometry().left() mtop = self.frameGeometry().top() mscale = event.angleDelta().y() / 5 if self.widescreen == True: self.setGeometry(mleft, mtop, mwidth + mscale, round((mwidth + mscale) / 1.778)) else: self.setGeometry(mleft, mtop, mwidth + mscale, round((mwidth + mscale) / 1.33)) #elif self.positionSlider.hasFocus(): # self.positionSlider.value = self.positionSlider.value + 5 def screen169(self): self.widescreen = True mwidth = self.frameGeometry().width() mheight = self.frameGeometry().height() mleft = self.frameGeometry().left() mtop = self.frameGeometry().top() mratio = 1.778 self.setGeometry(mleft, mtop, mwidth, round(mwidth / mratio)) def screen43(self): self.widescreen = False mwidth = self.frameGeometry().width() mheight = self.frameGeometry().height() mleft = self.frameGeometry().left() mtop = self.frameGeometry().top() mratio = 1.33 self.setGeometry(mleft, mtop, mwidth, round(mwidth / mratio)) def handleFullscreen(self): if self.windowState() & Qt.WindowFullScreen: QApplication.setOverrideCursor(Qt.ArrowCursor) self.showNormal() print("no Fullscreen") else: self.showFullScreen() QApplication.setOverrideCursor(Qt.BlankCursor) print("Fullscreen entered") def handleInfo(self): msg = QMessageBox.about(self, "QT5 Player", self.myinfo) def toggleSlider(self): if self.positionSlider.isVisible(): self.hideSlider() else: self.showSlider() def hideSlider(self): self.playButton.hide() self.lbl.hide() self.positionSlider.hide() self.elbl.hide() mwidth = self.frameGeometry().width() mheight = self.frameGeometry().height() mleft = self.frameGeometry().left() mtop = self.frameGeometry().top() if self.widescreen == True: self.setGeometry(mleft, mtop, mwidth, round(mwidth / 1.778)) else: self.setGeometry(mleft, mtop, mwidth, round(mwidth / 1.33)) def showSlider(self): self.playButton.show() self.lbl.show() self.positionSlider.show() self.elbl.show() mwidth = self.frameGeometry().width() mheight = self.frameGeometry().height() mleft = self.frameGeometry().left() mtop = self.frameGeometry().top() if self.widescreen == True: self.setGeometry(mleft, mtop, mwidth, round(mwidth / 1.55)) else: self.setGeometry(mleft, mtop, mwidth, round(mwidth / 1.33)) def forwardSlider(self): self.mediaPlayer.setPosition(self.mediaPlayer.position() + 1000 * 60) def forwardSlider10(self): self.mediaPlayer.setPosition(self.mediaPlayer.position() + 10000 * 60) def backSlider(self): self.mediaPlayer.setPosition(self.mediaPlayer.position() - 1000 * 60) def backSlider10(self): self.mediaPlayer.setPosition(self.mediaPlayer.position() - 10000 * 60) def volumeUp(self): self.mediaPlayer.setVolume(self.mediaPlayer.volume() + 10) print("Volume: " + str(self.mediaPlayer.volume())) def volumeDown(self): self.mediaPlayer.setVolume(self.mediaPlayer.volume() - 10) print("Volume: " + str(self.mediaPlayer.volume())) def mousePressEvent(self, evt): self.oldPos = evt.globalPos() def mouseMoveEvent(self, evt): delta = QPoint(evt.globalPos() - self.oldPos) self.move(self.x() + delta.x(), self.y() + delta.y()) self.oldPos = evt.globalPos() def dragEnterEvent(self, event): if event.mimeData().hasUrls(): event.accept() elif event.mimeData().hasText(): event.accept() else: event.ignore() def dropEvent(self, event): print("drop") if event.mimeData().hasUrls(): url = event.mimeData().urls()[0].toString() print("url = ", url) self.mediaPlayer.stop() self.mediaPlayer.setMedia(QMediaContent(QUrl(url))) self.playButton.setEnabled(True) self.mediaPlayer.play() elif event.mimeData().hasText(): mydrop = event.mimeData().text() ### YouTube url if "youtube" in mydrop: print("is YouTube", mydrop) self.clip.setText(mydrop) self.getYTUrl() else: ### normal url print("generic url = ", mydrop) self.mediaPlayer.setMedia(QMediaContent(QUrl(mydrop))) self.playButton.setEnabled(True) self.mediaPlayer.play() self.hideSlider() def loadFilm(self, f): self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(f))) self.playButton.setEnabled(True) self.mediaPlayer.play() def printMediaData(self): if self.mediaPlayer.mediaStatus() == 6: if self.mediaPlayer.isMetaDataAvailable(): res = str(self.mediaPlayer.metaData("Resolution")).partition( "PyQt5.QtCore.QSize(")[2].replace(", ", "x").replace(")", "") print("%s%s" % ("Video Resolution = ", res)) if int(res.partition("x")[0]) / int( res.partition("x")[2]) < 1.5: self.screen43() else: self.screen169() else: print("no metaData available") def openFileAtStart(self, filelist): matching = [s for s in filelist if ".myformat" in s] if len(matching) > 0: self.loadFilm(matching)
class inputField(QWidget): def __init__(self, label, text=None, value_type=VALUETYPE.STRING, ipRegex=None, input_width=50, parent=None, callback=None, runner=None): QWidget.__init__(self, parent) self.parent = parent self.__label = label self.input_width = input_width self.__ipRegex = ipRegex if value_type != VALUETYPE.STRING: self.__text = str(text) if not self.__ipRegex: self.__ipRegex = QRegExp("^[1-9]\\d{,3}$") else: self.__text = text self.callback = callback self.__runner = runner self.gui_init() def gui_init(self): layout = QGridLayout() layout.setContentsMargins(0, 0, 0, 0) self.setLayout(layout) label = QLabel(self.__label, self) layout.addWidget(label, 0, 0, Qt.AlignCenter) self.__edit = QLineEdit(self.__text, self) self.__edit.setFixedWidth(self.input_width) if self.__ipRegex: ipValidator = QRegExpValidator(self.__ipRegex) self.__edit.setValidator(ipValidator) layout.addWidget(self.__edit, 0, 1, Qt.AlignCenter) self.__edit.textChanged.connect(self.__changed__) if self.callback: self.__edit.textEdited.connect(partial(self.callback)) if self.__runner: run_but = QPushButton(self) run_but.setText(self.parent.qapp.tr("Run")) layout.addWidget(run_but, 0, 3, Qt.AlignCenter) run_but.pressed.connect(self.__runner__) def __runner__(self): self.__runner(self.__text) def __changed__(self, text): if not text: if self.__text != "-": self.__edit.setText(self.__text) else: self.__edit.setText("0") else: self.__text = text def getText(self): return self.__text def setText(self, text): self.__edit.setText(text)
class SpotExtractor(QMainWindow): def __init__(self): QMainWindow.__init__(self) self.setWindowTitle("Spot Extractor") menuBar = self.buildMenuBar() widget = QWidget(self) layout = QGridLayout(widget) # Main Image Window self.scrollArea = QScrollArea() self.imageLabel = ImageLabel(self) self.scrollArea.setWidget(self.imageLabel) # Text Label for Lot Name self.lotNameTextField = QLineEdit() self.lotNameTextField.setFixedWidth(300) # Spot List self.spotList = SpotListWidget(self) # Image Box Layout imageGroupBox = QGroupBox("Image") imageLayout = QHBoxLayout() imageLayout.addWidget(self.scrollArea) imageGroupBox.setLayout(imageLayout) # Spot List Box Layout rightGroupBox = QGroupBox() rightGroupBox.setMaximumWidth(300) rightGroupLayout = QVBoxLayout() lotNameGroupBox = QGroupBox("Lot Name") lotNameLayout = QHBoxLayout() lotNameLayout.addWidget(self.lotNameTextField) lotNameGroupBox.setLayout(lotNameLayout) spotsGroupBox = QGroupBox("Spot List") spotsLayout = QHBoxLayout() spotsLayout.addWidget(self.spotList) spotsGroupBox.setLayout(spotsLayout) rightGroupLayout.addWidget(lotNameGroupBox) rightGroupLayout.addWidget(spotsGroupBox) rightGroupBox.setLayout(rightGroupLayout) # Control Buttons Box Layout horizontalGroupBox = QGroupBox("Control Buttons") controlButtonLayout = QHBoxLayout() checkAllButton = QPushButton("Check All") uncheckAllButton = QPushButton("Uncheck All") deleteCheckedButton = QPushButton("Delete Checked") checkAllButton.clicked.connect(self.checkAll) uncheckAllButton.clicked.connect(self.uncheckAll) deleteCheckedButton.clicked.connect(self.deleteAllChecked) controlButtonLayout.addWidget(checkAllButton) controlButtonLayout.addWidget(uncheckAllButton) controlButtonLayout.addWidget(deleteCheckedButton) horizontalGroupBox.setLayout(controlButtonLayout) layout.addWidget(imageGroupBox, 0, 0) layout.addWidget(rightGroupBox, 0, 1) layout.addWidget(horizontalGroupBox, 1, 0, 1, 2) self.setMenuBar(menuBar) self.setLayout(layout) self.setCentralWidget(widget) def buildMenuBar(self): menuBar = QMenuBar(self) fileMenu = QMenu("File") loadImageAction = QAction("Load Image", self) loadDataAction = QAction("Load Lot Data", self) saveDataAction = QAction("Save Lot Data", self) exitAction = QAction("Exit", self) # Set Trigger for each Action loadImageAction.triggered.connect(self.loadImage) loadDataAction.triggered.connect(self.loadData) saveDataAction.triggered.connect(self.saveData) exitAction.triggered.connect(QtGui.qApp.quit) # Add actions to menu fileMenu.addAction(loadImageAction) fileMenu.addAction(loadDataAction) fileMenu.addAction(saveDataAction) fileMenu.addAction(exitAction) menuBar.addMenu(fileMenu) return menuBar def loadImage(self): options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog fileName, _ = QFileDialog.getOpenFileName( self, "Load Image", "", "PNG Files (*.png);;JPEG Files (*.jpg)", options=options) if fileName: mat = cv.imread(fileName, cv.IMREAD_UNCHANGED) self.imageLabel.setImage(mat) def loadData(self): options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog fileName, _ = QFileDialog.getOpenFileName(self, "Load JSON Data", "", "JSON Files (*.json)", options=options) if fileName: f = open(fileName, "r") j = json.load(f) self.lotNameTextField.setText(j["lotName"]) for spot in j["spots"]: p1 = int(spot["topLeft"][0]), int(spot["topLeft"][1]) p2 = int(spot["topRight"][0]), int(spot["topRight"][1]) p3 = int(spot["bottomLeft"][0]), int(spot["bottomLeft"][1]) p4 = int(spot["bottomRight"][0]), int(spot["bottomRight"][1]) realID = int(spot["realID"]) id = int(spot["spotID"]) s = Spot([p1, p2, p3, p4], realID, id) self.spotList.addSpot(s) self.imageLabel.resetOriginal() self.imageLabel.drawSpots() self.imageLabel.updateView() def saveData(self): lotData["spots"].clear() lotData["lotName"] = self.lotNameTextField.text() for i in range(len(self.spotList)): s = self.spotList.spots[i] spotData = { "spotID": i, "realID": s.realID, "topLeft": s.points[0], "topRight": s.points[1], "bottomLeft": s.points[2], "bottomRight": s.points[3], } lotData["spots"].append(spotData) options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog fileName, _ = QFileDialog.getSaveFileName(self, "Save JSON Data", "", "JSON Files (*.json)", options=options) if fileName: jsonData = json.dumps(lotData, indent=2) if not fileName.endswith(".json"): fileName = fileName + ".json" f = open(fileName, "w") f.write(jsonData) f.flush() f.close() def checkAll(self): for i in range(len(self.spotList)): self.spotList.item(i).setCheckState(Qt.Checked) self.imageLabel.resetOriginal() self.imageLabel.drawSpots() self.imageLabel.updateView() def uncheckAll(self): for i in range(len(self.spotList)): self.spotList.item(i).setCheckState(Qt.Unchecked) self.imageLabel.resetOriginal() self.imageLabel.updateView() def deleteAllChecked(self): for i in range(len(self.spotList) - 1, -1, -1): if self.spotList.item(i).checkState() == Qt.Checked: self.spotList.removeSpot(i) self.imageLabel.resetOriginal() self.imageLabel.drawSpots() self.imageLabel.updateView()
class Natang_mmdmaya(QWidget): ''' mmdモデルからmayaへインポートするためのウィンドウ ''' def __init__(self, parent): QWidget.__init__(self) self.setAcceptDrops(True) self.parent = parent self.setWindowFlags(Qt.WindowStaysOnTopHint) self.setWindowTitle('~ MMD > Maya ~') self.setStyleSheet('font-size: 15px; color: #ddf;') vbl = QVBoxLayout() self.setLayout(vbl) self.file_khatangton = os.path.join(os.path.dirname(__file__), 'asset', 'khatangton1.txt') try: with open(self.file_khatangton, 'r', encoding='utf-8') as f: chue_tem_file = f.readline().split('=')[-1].strip() satsuan = f.readline().split('=')[-1].strip() yaek_poly = int(f.readline().split('=')[-1].strip()) ao_bs = int(f.readline().split('=')[-1].strip()) ao_kraduk = int(f.readline().split('=')[-1].strip()) watsadu = int(f.readline().split('=')[-1].strip()) pit_mai = int(f.readline().split('=')[-1].strip()) except: chue_tem_file = '' satsuan = '8' yaek_poly = 0 ao_bs = 1 ao_kraduk = 1 watsadu = 4 pit_mai = 1 hbl = QHBoxLayout() vbl.addLayout(hbl) hbl.addWidget(QLabel('ファイル')) self.le_chue_file = QLineEdit(chue_tem_file) hbl.addWidget(self.le_chue_file) self.le_chue_file.setFixedWidth(300) self.le_chue_file.textChanged.connect(self.chue_thuk_kae) self.btn_khon_file = QPushButton('...') hbl.addWidget(self.btn_khon_file) self.btn_khon_file.clicked.connect(self.khon_file) hbl = QHBoxLayout() vbl.addLayout(hbl) hbl.addWidget(QLabel('尺度')) self.le_satsuan = QLineEdit(satsuan) hbl.addWidget(self.le_satsuan) self.le_satsuan.setFixedWidth(100) self.le_satsuan.textEdited.connect(self.satsuan_thuk_kae) hbl.addWidget(QLabel('×')) hbl.addStretch() self.cb_yaek_poly = QCheckBox('材質ごとにポリゴンを分割する') vbl.addWidget(self.cb_yaek_poly) self.cb_ao_kraduk = QCheckBox('骨も作る') vbl.addWidget(self.cb_ao_kraduk) self.cb_ao_bs = QCheckBox('ブレンドシェープも作る') vbl.addWidget(self.cb_ao_bs) hbl = QHBoxLayout() vbl.addLayout(hbl) hbl.addWidget(QLabel('材質')) self.cbb_watsadu = QComboBox() hbl.addWidget(self.cbb_watsadu) self.cbb_watsadu.addItem('無い') self.cbb_watsadu.addItem('blinn') self.cbb_watsadu.addItem('phong') self.cbb_watsadu.addItem('lambert') self.cbb_watsadu.addItem('standardSurface') hbl.addStretch() hbl = QHBoxLayout() vbl.addLayout(hbl) hbl.addStretch() self.btn_roem_sang = QPushButton('作成開始') hbl.addWidget(self.btn_roem_sang) self.btn_roem_sang.clicked.connect(self.roem_sang) self.btn_roem_sang.setFixedSize(220, 50) self.chue_thuk_kae(self.le_chue_file.text()) self.cb_pit = QCheckBox('終わったらこの\nウィンドウを閉じる') hbl.addWidget(self.cb_pit) self.cb_yaek_poly.setChecked(yaek_poly) self.cb_ao_kraduk.setChecked(ao_kraduk) self.cb_ao_bs.setChecked(ao_bs) self.cbb_watsadu.setCurrentIndex(watsadu) self.cb_yaek_poly.toggled.connect( lambda: self.chue_thuk_kae(self.le_chue_file.text())) self.cb_pit.setChecked(pit_mai) def chue_thuk_kae(self, chue_file): # ファイルの名前が更新されたら sakun = chue_file.split('.')[-1] sang_dai = (sakun.lower() in ['pmd', 'pmx', 'x']) self.btn_roem_sang.setEnabled(sang_dai) self.btn_roem_sang.setStyleSheet( ['text-decoration: line-through; color: #aab;', ''][sang_dai]) dai = chue_file[-2:] != '.x' and not self.cb_yaek_poly.isChecked() self.cb_ao_kraduk.setEnabled(dai) self.cb_ao_bs.setEnabled(dai) self.cb_ao_kraduk.setStyleSheet( ['text-decoration: line-through; color: #aab;', ''][dai]) self.cb_ao_bs.setStyleSheet( ['text-decoration: line-through; color: #aab;', ''][dai]) def khon_file(self): # 読み込むファイルをブラウスする self.setWindowFlags(self.windowFlags() & ~Qt.WindowStaysOnTopHint) chue_file, ok = QFileDialog.getOpenFileName( filter='PMD/PMX/X (*.pmd *.pmx *.x)') if (ok): self.le_chue_file.setText(chue_file) self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint) self.show() def dragEnterEvent(self, e): if (e.mimeData().hasUrls()): # ファイルがドラッグされたら使える e.accept() def dropEvent(self, e): self.le_chue_file.setText( e.mimeData().urls()[0].toLocalFile()) # ドラッグされたファイルの名前を取得する def satsuan_thuk_kae(self, kha): # 尺度が更新されたら try: float(kha) except: self.le_satsuan.setText('1') def roem_sang(self): # ボタンがクリックされたら、作成は開始 chue_tem_file = self.le_chue_file.text() try: satsuan = float(self.le_satsuan.text()) except: self.le_satsuan.setText('1') satsuan = 1. yaek_poly = self.cb_yaek_poly.isChecked() ao_bs = not yaek_poly and self.cb_ao_bs.isChecked() ao_kraduk = not yaek_poly and self.cb_ao_kraduk.isChecked() watsadu = self.cbb_watsadu.currentIndex() # ここでmayaのシーンの中でモデルを作る pmxpaimaya.sang(chue_tem_file, satsuan, yaek_poly, ao_bs, ao_kraduk, watsadu) pit_mai = self.cb_pit.isChecked() # 今回使った設定を保存しておく with open(self.file_khatangton, 'w', encoding='utf-8') as f: f.write('ファイルの名前 = %s\n' % chue_tem_file) f.write('尺度 = %f\n' % satsuan) f.write('ポリゴンの分割 = %d\n' % yaek_poly) f.write('ブレンドシェープ = %d\n' % ao_bs) f.write('ジョイント = %d\n' % ao_kraduk) f.write('材質 = %d\n' % watsadu) f.write('閉じる = %d\n' % pit_mai) if (pit_mai): # 終わったらこのウィンドウを閉じる self.close() def keyPressEvent(self, e): # escが押されたら閉じる if (e.key() == Qt.Key_Escape): self.close() def closeEvent(self, e): self.parent.natangyoi['mmdmaya'] = None
class NewWindow2(QMainWindow): def __init__(self): super(NewWindow2, self).__init__() self.latlong = "0" self.textEdit = QTextEdit() self.mainWidget = QWidget() self.mainLayout = QVBoxLayout() font0 = QFont("Arial", 12) font0.setBold(True) font01 = QFont("Arial", 12) font02 = QFont("Arial", 12) self.text1 = QLabel("<b>Domyślne Współrzędne:</b><br/>" "Szerokość: 51° 06' 00''<br/>" "Długość: 17° 01' 00''<br/>" "(Współrzędne geograficzne Wrocławia)") self.solarpanelcordinates = QLabel('WSPÓŁRZĘDNE PANELU SŁONECZNEGO: ') self.solarpanelcordinates.setFont(font0) # self.solarpanelcordinates.setFrameStyle(QFrame.Box | QFrame.Sunken) # self.solarpanelcordinates.setMidLineWidth(6) #self.text1.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) self.text1.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) self.text1.setFont(font01) self.text1.setFrameStyle(QFrame.Box | QFrame.Raised) self.text1.setMidLineWidth(6) self.result4 = QLabel('') self.result4.setFont(font02) self.result4.setMidLineWidth(3) self.result5 = QLabel('') self.result5.setFont(font02) self.result6 = QLabel('') self.result6.setFont(font02) self.result7 = QLabel('') self.result7.setFont(font02) self.result8 = QLabel('') self.result8.setFont(font02) self.result9 = QLabel('') self.result9.setFont(font02) self.mainLayout.addWidget(self.text1) self.mainLayout.addWidget(self.solarpanelcordinates) self.mainLayout.addWidget(self.result4) self.mainLayout.addWidget(self.result5) self.mainLayout.addWidget(self.result6) self.mainLayout.addWidget(self.result7) self.mainLayout.addWidget(self.result8) self.mainLayout.addWidget(self.result9) self.mainWidget.setLayout(self.mainLayout) self.setCentralWidget(self.mainWidget) self.createActions() self.createMenus() #self.createToolBars() self.createStatusBar() self.createDockWindows() self.setWindowTitle("Nowe Okno") self.rad = 0 self.o = 0 self.timer = QTimer() self.timer.timeout.connect(self.dLocation) self.timerIsUp = False self.timer2 = QTimer() self.timer2.timeout.connect(self.update) self.timer2.start(1000) self.newLetter() self.s = ephem.Sun() self.o = ephem.Observer() # zmienna = [] # i=0 # with open('Breslau.txt', 'r') as f: # for line in f: # zmienna.append(line) # i=i+1 # print(zmienna) # f = self.nameEdit.text() # f = self.latitudeEdit.text() # f = self.longitudeEdit.text() # f = self.dateandtimeEdit.text() # print(self.nameEdit.text()) # print(self.latitudeEdit.text()) # print(self.longitudeEdit.text()) # print(self.dateandtimeEdit.text()) # class MainWindow(QMainWindow): # def __init__(self): # super(MainWindow, self).__init__() # # self.latlong = "0" # self.textEdit = QTextEdit() # self.setCentralWidget(self.textEdit) # self.createActions() # self.createMenus() # #self.createToolBars() # self.createStatusBar() # self.createDockWindows() # self.setWindowTitle("Panel Słoneczny") # self.rad = 0 # self.o = 0 # self.timer = QTimer() # self.timer.timeout.connect(self.dLocation) # self.timerIsUp = False # self.timer2 = QTimer() # self.timer2.timeout.connect(self.update) # self.timer2.start(1000) # self.newLetter() # self.s = ephem.Sun() # self.o = ephem.Observer() def newWindow(self): self.newWin = NewWindow() self.newWin.show() def newWindow2(self): self.newWin2 = NewWindow2() self.newWin2.show() def newLetter(self): self.textEdit.clear() self.text2 = QLabel("<b>Domyślne Współrzędne:</b><br/>" "Szerokość: 51° 06' 00''<br/>" "Długość: 17° 01' 00''<br/>" "(Współrzędne geograficzne Wrocławia)") cursor = self.textEdit.textCursor() cursor.movePosition(QTextCursor.Start) topFrame = cursor.currentFrame() topFrameFormat = topFrame.frameFormat() topFrameFormat.setPadding(16) topFrame.setFrameFormat(topFrameFormat) textFormat = QTextCharFormat() boldFormat = QTextCharFormat() boldFormat.setFontWeight(QFont.Bold) italicFormat = QTextCharFormat() italicFormat.setFontItalic(True) tableFormat = QTextTableFormat() tableFormat.setBorder(1) tableFormat.setCellPadding(16) tableFormat.setAlignment(Qt.AlignRight) cursor.insertTable(1, 1, tableFormat) cursor.insertText("Domyślne Współrzędne: ", boldFormat) self.text2.setText(self.nameEdit.text()) cursor.insertText #self.text1.setText(self.nameEdit.text()) cursor.insertBlock() cursor.insertBlock() cursor.insertText("Szerokość: 51° 06' 00''", textFormat) cursor.insertBlock() cursor.insertBlock() cursor.insertText("Długość: 17° 01' 00''") cursor.insertBlock() cursor.insertBlock() cursor.insertText("(Współrzędne geograficzne Wrocławia)") cursor.setPosition(topFrame.lastPosition()) # cursor.insertText(QDate.currentDate().toString("Dziś jest: d MMMM yyyy:"), # textFormat) # cursor.insertText(QTime.currentTime().toString(" hh:mm:ss"), textFormat) # # cursor.insertText(QTimer.timer(" hh:mm:ss", 1000), textFormat) # cursor.insertBlock() # cursor.insertBlock() # cursor.insertText("Wrocław: ", textFormat) # cursor.insertText("17.03 deg; 51.10 deg", textFormat) # cursor.insertText(",", textFormat) # for i in range(3): # cursor.insertBlock() # cursor.insertText("Text", textFormat) def dLocation(self): self.s = ephem.Sun() self.s.compute(epoch=ephem.now()) if self.nameEdit.text(): self.text1.setText(self.nameEdit.text()) font03 = QFont("Arial", 16) font03.setBold(True) self.text1.setFont(font03) if not self.dateandtimeEdit.text(): self.o.date = ephem.now() # 00:22:07 EDT 06:22:07 UT+1 else: if self.dateandtimeEdit.text(): self.o.date = self.dateandtimeEdit.text() self.text1.setText("<b>Obliczenia dla:</b><br/> " + self.dateandtimeEdit.text()) font03 = QFont("Arial", 16) font03.setBold(True) self.text1.setFont(font03) else: self.o.date = ephem.now() # 00:22:07 EDT 06:22:07 UT+1 #self.o.date = ephem.now() # 00:22:07 EDT 06:22:07 UT+1 self.s.compute(self.o) hour_angle = self.o.sidereal_time() - self.s.ra t = ephem.hours(hour_angle + ephem.hours('12:00')).norm # .norm for 0..24 self.rad = str(ephem.hours(hour_angle + ephem.hours('12:00')).norm) # self.result.setText("R.A.: " + str(self.s.a_ra) + " DEC.: " + str(self.s.a_dec)) # self.result2.setText("HOUR ANGLE: " + str(self.rad) + " SIDERAL TIME: " + str(self.o.sidereal_time())) # self.result3.setText("SUN Altitude: " + str(self.s.alt) + " SUN Azimuth: " + str(self.s.az)) self.result4.setText("R.A.: " + str(self.s.a_ra)) self.result5.setText("DEC.: " + str(self.s.a_dec)) self.result6.setText("HOUR ANGLE: " + str(self.rad)) self.result7.setText("SIDERAL TIME: " + str(self.o.sidereal_time())) self.result8.setText("SUN Altitude: " + str(self.s.alt)) self.result9.setText("SUN Azimuth: " + str(self.s.az)) def update(self): time = QTime.currentTime() self.clock.setText(QTime.currentTime().toString("hh:mm:ss")) def about(self): QMessageBox.about( self, "O Programie", "<p align=justify>Program <b><i>''Panel Słoneczny''</b></i> pozwala na wyliczenie współrzędnych Słońca, " "na podstawie których należy ustawić Panel. Domyślnie program startuje dla " "szerokości i długości geograficznej Wrocławia z obecną dla użytkownika datą i godziną. " "Użytkownik może podać swoją szerokość i długość geograficzną oraz swój czas i datę wpisując " "w odpowiednie pola swoje dane. W polach Szerokość i Długość należy podać w stopniach dziesiętnych " "W polu ''Data i Czas'' własne dane należy wpisywać zgodnie ze schematem: " "rok/mies/dzień godz:min:sek (np.: 2019/02/04 14:02:03). Pisanie zer przed godzinami, minutami i sekundami " "dla liczb poniżej dziesięciu nie jest wymagane (2019/02/04 14:02:03 = 2019/2/4 14:2:3)<p/>" ) def about2(self): QMessageBox.about( self, "Symbole i skróty", "<p align=justify><b><i>Rektascensja (R.A.)</b></i> – (Right Ascension; wznoszenie proste) jest kątem dwuściennym " "pomiędzy płaszczyzną koła godzinnego przechodzącego przez punkt Barana, a płaszczyzną koła godzinnego " "danego ciała niebieskiego). <br/>" "<b><i>Deklinacja (DEC.)</b></i> - kąt zawarty między płaszczyzną równika niebieskiego," "a prostą łączącą punkt na sferze niebieskiej, a środkiem sfery niebieskiej. " "Deklinacja zmienia się w zakresie od 90° (biegun północny) przez 0° (równik niebieski) do -90° (biegun południowy).<br/> " "<b><i>Kąt Godzinny (HOUR ANGLE)</b></i> - kąt dwuścienny zawarty pomiędzy płaszczyzną lokalnego południka " "i płaszczyzną koła godzinnego danego obiektu. Kąt godzinny odmierza się w kierunku zgodnym " "z dziennym ruchem sfery niebieskiej, a przyjmuje on wartości (0h,24h) lub (0°,360°) " "Kąt godzinny zależy od miejsca obserwacji (ulokowania panela) i od lokalnego czasu.<br/> " "<b><i>Czas Gwiazdowy (SIDERAL TIME)</b></i> - czyli kąt godzinny punktu Barana. ( Jeden z dwóch punktów " "przecięcia się ekliptyki z równikiem niebieskim. Moment przejścia Słońca przez punkt Barana " "oznacza początek astronomicznej wiosny na półkuli północnej. Dlatego nazywany jest także punktem " "równonocy wiosennej.)<br/> " "<b><i>Wysokość Słońca (nad horyzontem; SUN Altitude)</b></i> - na daną chwilę wyliczona wysokość Słońca, " "jeżeli jest ujemna to znaczy, że słońce jest pod horyzontem.<br/> " "<b><i>Azymut Słońca (SUN Azimuth)</b></i> - kąt dwuścienny, w programie liczy się w kierunku na wschód " "(stojąc twarzą do północy w prawo; w Astronomii jest tak samo, tzn. w prawo, ale zaczyna od południka)." "Azymut geograficzny i astronomiczny różni się o 180°.<p/> ") def createActions(self): # self.newLetterAct = QAction(QIcon.fromTheme('document-new', QIcon(':/images/new.png')), "&New Letter", # self, shortcut=QKeySequence.New, # statusTip="Create a new form letter", triggered=self.newLetter()) self.newWindowAct = QAction(QIcon.fromTheme('document-new', QIcon(':/images/new.png')), "&Nowe Okno", self, shortcut=QKeySequence.New, statusTip="Create a new form letter", triggered=self.newWindow2) self.saveAct = QAction(QIcon.fromTheme('document-save', QIcon(':/images/save.png')), "&Zapisz", self, shortcut=QKeySequence.Save, statusTip="Zapisz obecne współrzędne", triggered=self.save) self.loadAct = QAction(QtGui.QIcon(':/images/open.png'), "&Wczytaj", self, shortcut=QtGui.QKeySequence.Open, statusTip="Wczytaj współrzędne z pliku", triggered=self.load) self.aboutAct = QAction("&O Programie", self, statusTip="Pokazuje pomoc dla programu", triggered=self.about) self.aboutAct2 = QAction( "&Symbole i skróty", self, statusTip= "Pokazuje objaśnienia używanych w programie skrótów i symboli", triggered=self.about2) self.quitAct = QAction("&Zamknij", self, shortcut="Ctrl+Q", statusTip="Zamyka aplikację", triggered=self.close) self.DefaultAct = QAction( QIcon.fromTheme('document-default', QIcon(':/images/def.png')), "&Rozpocznij dla domyślnej lokacji", self, statusTip="Rozpoczyna obliczenia dla domyślnej lokacji (Wrocław)", triggered=self.handleButton2) def createToolBars(self): self.fileToolBar = self.addToolBar("File") self.fileToolBar.addAction(self.newLetterAct) def createMenus(self): self.fileMenu = self.menuBar().addMenu("&Plik") self.fileMenu.addAction(self.newWindowAct) self.fileMenu.addAction(self.saveAct) self.fileMenu.addAction(self.loadAct) self.fileMenu.addAction(self.DefaultAct) self.fileMenu.addSeparator() self.fileMenu.addAction(self.quitAct) self.fileMenu.addSeparator() self.editMenu = self.menuBar().addMenu("&Edycja") self.viewMenu = self.menuBar().addMenu("&Widok") self.menuBar().addSeparator() self.helpMenu = self.menuBar().addMenu("&Pomoc") self.helpMenu.addAction(self.aboutAct) self.helpMenu.addAction(self.aboutAct2) def createStatusBar(self): self.statusBar().showMessage("Gotowy", 3000) def saving(self): cursor = self.textEdit.textCursor() self.nameEdit.text() cursor.insertBlock() self.latitudeEdit.text() cursor.insertBlock() self.longitudeEdit.text() cursor.insertBlock() self.dateandtimeEdit.text() def save(self): filename, _ = QFileDialog.getSaveFileName(self, "Zapisywanie jako", '.', "Dokumenty textowe(*.txt)") if not filename: return file = QFile(filename) if not file.open(QFile.WriteOnly | QFile.Text): QMessageBox.warning( self, "Panel Słoneczny", "nie mógł zapisać pliku %s:\n%s." % (filename, file.errorString())) return out = QTextStream(file) #QApplication.setOverrideCursor(Qt.WaitCursor) #out << self.textEdit.toPlainText() out << self.nameEdit.text() + "\n" + self.latitudeEdit.text( ) + "\n" + self.longitudeEdit.text( ) + "\n" + self.dateandtimeEdit.text() #out << "self.text1.setText("+self.nameEdit.text()+")" #QApplication.restoreOverrideCursor() self.statusBar().showMessage("Zapisano w '%s'" % filename, 2000) def load(self): filename, _ = QFileDialog.getOpenFileName(self) if not filename: return file = QFile(filename) if not file.open(QFile.ReadOnly | QFile.Text): QMessageBox.warning( self, "Panel Słoneczny", "nie mógł wczytać pliku %s:\n%s." % (filename, file.errorString())) return inf = QTextStream(file) #QApplication.setOverrideCursor(QtCore.Qt.WaitCursor) self.textEdit.setPlainText(inf.readAll()) #with open(file, 'r') as input: with open('Breslau.txt', 'r') as f: # f = self.nameEdit.text() # f = self.latitudeEdit.text() # f = self.longitudeEdit.text() # f = self.dateandtimeEdit.text() # print(self.nameEdit.text()) # print(self.latitudeEdit.text()) # print(self.longitudeEdit.text()) # print(self.dateandtimeEdit.text()) # for line in f: # print (line, end='') f_name = f.readline() #f_name = self.nameEdit.text() self.text1.setText(f_name) f_lat = f.readline() f_lat = self.latitudeEdit.text() f_lon = f.readline() f_lon = self.longitudeEdit.text() f_dnt = f.readline() f_dnt = self.dateandtimeEdit.text() # for line in f: # if 'name' in line: # self.text1.setText(line) #if 'lat' in line: #self.text1.setText(self.textEdit.setPlainText(inf.readAll())) #self.text1.setText(self.nameEdit.text()) #QApplication.restoreOverrideCursor() #self.setCurrentFile(filename) self.statusBar().showMessage("Wczytano plik", 2000) def createDockWindows(self): # dock = QDockWidget('n', self) # dock.setFeatures(dock.NoDockWidgetFeatures) # dock.DockWidgetMovable = False # dock.setAllowedAreas(Qt.TopDockWidgetArea) # self.addDockWidget(Qt.TopDockWidgetArea, dock) dock = QDockWidget("Program", self) dock.setFeatures(dock.NoDockWidgetFeatures) dock.DockWidgetMovable = False dock.setAllowedAreas(Qt.LeftDockWidgetArea) self.multiWidget = QWidget() font1 = QFont("Courier New", 10) self.title = QLabel("SOLAR PANEL Program") font2 = QFont("Courier New", 10) font2.setBold(True) self.author = QLabel("Tomasz Dróżdż") self.author.setFont(font2) self.other = QLabel("Politechnika Wrocławska") self.other2 = QLabel("Automatyka i Robotyka") self.vLayout = QVBoxLayout() self.vLayout.addWidget(self.title) self.vLayout.addWidget(self.author) self.vLayout.addWidget(self.other) self.vLayout.addWidget(self.other2) self.multiWidget.setLayout(self.vLayout) dock.setWidget(self.multiWidget) self.addDockWidget(Qt.LeftDockWidgetArea, dock) dock = QDockWidget("Zegar", self) dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.multiWidget2 = QWidget() font3 = QFont("Arial", 13) font4 = QFont("Arial", 20) self.date = QLabel(QDate.currentDate().toString("d MMMM yyyy: ")) self.clock = QLabel(QTime.currentTime().toString("hh:mm:ss")) self.date.setFont(font3) self.clock.setFont(font4) font4.setBold(True) self.vLayout2 = QVBoxLayout() self.vLayout2.addWidget(self.date) self.vLayout2.addWidget(self.clock) self.multiWidget2.setLayout(self.vLayout2) dock.setWidget(self.multiWidget2) self.addDockWidget(Qt.LeftDockWidgetArea, dock) self.viewMenu.addAction(dock.toggleViewAction()) dock = QDockWidget("Współrzędne Geograficzne Panelu: ", self) s = ephem.Sun() s.compute(epoch=ephem.now()) dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.multiWidget3 = QWidget() font5 = QFont("Arial", 12) font6 = QFont("Arial", 17) self.vLayout3 = QGridLayout() self.result = QLabel(self.latlong) self.name = QLabel('Nazwa') self.latitude = QLabel('Szerokość') self.longitude = QLabel('Długość') self.dateandtime = QLabel('Data i Czas') # self.result = QLabel('') # self.result2 = QLabel('') # self.result3 = QLabel('') self.solarpanelcor = QLabel('WSPÓŁRZĘDNE PANELU SŁONECZNEGO: ') self.nameEdit = QLineEdit() self.nameEdit.setFixedHeight(28) self.nameEdit.setFixedWidth(386) self.nameEdit.setStatusTip( "Wprowadź nazwę dla konfiguracji współrzędnych i czasu") self.latitudeEdit = QLineEdit() self.latitudeEdit.setFixedHeight(28) self.latitudeEdit.setFixedWidth(386) self.latitudeEdit.setStatusTip( "Wprowadzona szerokość powinna być w stopniach dziesiętnych (np.: 51.100000)" ) self.longitudeEdit = QLineEdit() self.longitudeEdit.setFixedHeight(28) self.longitudeEdit.setFixedWidth(386) self.longitudeEdit.setStatusTip( "Wprowadzona długość powinna być w stopniach dziesiętnych (np.: 17.03333)" ) self.dateandtimeEdit = QLineEdit() self.dateandtimeEdit.setFixedHeight(28) self.dateandtimeEdit.setFixedWidth(386) self.dateandtimeEdit.setStatusTip( "Wprowadzona data powinna być w formacie: rok/mies/dzień<spacja>godz:min:sek (np.: 2022/12/4 8:12:7)" ) self.button = QPushButton('Wylicz współrzędne / Przerwij liczenie', self) self.button.clicked.connect(self.handleButton4) self.name.setFont(font5) self.latitude.setFont(font5) self.longitude.setFont(font5) self.dateandtime.setFont(font5) self.button.setFont(font6) self.button.setStatusTip("Rozpoczyna Obliczenia") # self.button.addAction(self.buttonAct) # self.solarpanelcor.setFont(font5) # self.result.setFont(font6) # self.result2.setFont(font6) # self.result3.setFont(font6) self.vLayout3.addWidget(self.name) self.vLayout3.addWidget(self.nameEdit) self.vLayout3.addWidget(self.latitude) self.vLayout3.addWidget(self.latitudeEdit) self.vLayout3.addWidget(self.longitude) self.vLayout3.addWidget(self.longitudeEdit) self.vLayout3.addWidget(self.dateandtime) self.vLayout3.addWidget(self.dateandtimeEdit) self.vLayout3.addWidget(self.button) # self.vLayout3.addWidget(self.solarpanelcor) # self.vLayout3.addWidget(self.result) # self.vLayout3.addWidget(self.result2) # self.vLayout3.addWidget(self.result3) self.multiWidget3.setLayout(self.vLayout3) dock.setWidget(self.multiWidget3) self.addDockWidget(Qt.RightDockWidgetArea, dock) self.viewMenu.addAction(dock.toggleViewAction()) def handleButton2(self): self.button.setStatusTip("Przerywa liczenie") if self.timerIsUp == False: self.o.lon, self.o.lat = '17.03333', '51.100000' # Współrzędne Wrocławia self.text1.setText("Wrocław") font03 = QFont("Arial", 16) font03.setBold(True) self.text1.setFont(font03) self.timer.start(1000) self.timerIsUp = True else: self.timer.stop() self.timerIsUp = False self.button.setStatusTip("Rozpoczyna Obliczenia") # def handleButton2(self): # print(self.nameEdit.text()) # print(self.latitudeEdit.text()) # print(self.longitudeEdit.text()) # print(self.dateandtimeEdit.text()) def handleButton3(self): self.button.setStatusTip("Przerywa liczenie") if self.timerIsUp == False: if self.latitudeEdit.text() and self.longitudeEdit.text(): self.o.lat = self.latitudeEdit.text() self.o.lon = self.longitudeEdit.text() if self.nameEdit.text(): self.text1.setText(self.nameEdit.text()) font03 = QFont("Arial", 16) font03.setBold(True) self.text1.setFont(font03) else: self.text1.setText("Wrocław") font03 = QFont("Arial", 16) font03.setBold(True) self.text1.setFont(font03) self.o.lon, self.o.lat = '17.03333', '51.100000' # Współrzędne Wrocławia self.timer.start(1000) self.timerIsUp = True else: self.timer.stop() self.timerIsUp = False self.button.setStatusTip("Rozpoczyna Obliczenia") def handleButton4(self): self.button.setStatusTip("Przerywa liczenie") if self.timerIsUp == False: #zastąpic wlasna logika # if self.latitudeEdit.text() and self.longitudeEdit.text(): # self.o.lat = self.latitudeEdit.text() # self.o.lon = self.longitudeEdit.text() if self.nameEdit.text(): self.text1.setText(self.nameEdit.text()) font03 = QFont("Arial", 16) font03.setBold(True) self.text1.setFont(font03) else: if self.latitudeEdit.text() and self.longitudeEdit.text(): self.o.lat = self.latitudeEdit.text() self.o.lon = self.longitudeEdit.text() self.text1.setText("<b>Obliczenia dla:</b><br/> " + "Szerokość: " + self.latitudeEdit.text() + "°" + " " + "Długość: " + self.longitudeEdit.text() + "°") font03 = QFont("Arial", 16) #font03.setBold(True) self.text1.setFont(font03) else: self.text1.setText("Wrocław") font03 = QFont("Arial", 16) font03.setBold(True) self.text1.setFont(font03) self.o.lon, self.o.lat = '17.03333', '51.100000' # Współrzędne Wrocławia self.timer.start(1000) self.timerIsUp = True else: self.timer.stop() self.timerIsUp = False self.button.setStatusTip("Rozpoczyna Obliczenia")
class SendWidget(QWidget): tokens_file = 'tokens.json' def __init__(self, parent=None): super(SendWidget, self).__init__(parent) self.token_name = 'Ethereum' self.setupSenderSection() self.setupDestinationSection() self.setupTokenSection() self.setupProgressSection() self.setupSendButtonSection() self.setupFeeSection() self.send_thread = SendThread() self.send_thread.send_transaction.connect(self.sendTransactionFinished) self.send_token_thread = SendTokenThread() self.send_token_thread.send_token_transaction.connect( self.sendTransactionFinished) layout = QGridLayout() layout.addLayout(self.sender_layout, 0, 0) layout.addLayout(self.destination_layout, 0, 1) layout.addLayout(self.progress_layout, 1, 0, 1, 2, Qt.AlignCenter) layout.addLayout(self.token_layout, 2, 0) layout.addLayout(self.send_layout, 2, 1) layout.addLayout(self.slider_layout, 3, 0) self.setLayout(layout) def setupSenderSection(self): accounts = blockchain.get_accounts() sender_label = QLabel("Sender") sender_label.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) self.balance_label = QLabel("Balance: ") self.balance_label.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) self.avatar = QLabel() self.sender_combo_box = QComboBox() self.sender_items = [] for account, balance in accounts: self.sender_items.append(account) self.sender_combo_box.addItems(self.sender_items) self.sender_combo_box.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) self.sender_combo_box.currentTextChanged.connect(self.filterSender) first_account = self.sender_items[0] self.filterSender(first_account) self.setAvatar(first_account, self.avatar) self.sender_layout = QVBoxLayout() sender_wrapper_layout = QHBoxLayout() sender_right_layout = QVBoxLayout() sender_right_layout.addWidget(sender_label) sender_right_layout.addWidget(self.sender_combo_box) sender_right_layout.addWidget(self.balance_label) sender_wrapper_layout.addWidget(self.avatar) sender_wrapper_layout.addLayout(sender_right_layout) sender_wrapper_layout.addStretch() self.sender_layout.addLayout(sender_wrapper_layout) self.sender_layout.addStretch() def setupDestinationSection(self): self.destination_layout = QVBoxLayout() destination_label = QLabel("Destination") destination_label.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) self.destination_line_edit = QLineEdit() self.destination_line_edit.setFixedWidth(380) self.destination_line_edit.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) self.destination_layout.addWidget(destination_label) self.destination_layout.addWidget(self.destination_line_edit) self.destination_layout.addStretch() def setupTokenSection(self): token_label = QLabel("Token") token_label.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) token_combo_box = QComboBox() tokens = blockchain.get_tokens() first_token = 'Ethereum' items = [first_token] self.token_address = { 'Ethereum': '0xcccccccccccccccccccccccccccccccccccccccc' } self.token_informations = {} for address, token_from_json in tokens.items(): token_information = blockchain.get_token_named_tuple( token_from_json, address) self.token_informations[token_information.name] = token_information self.token_address[ token_information.name] = token_information.address items.append(token_information.name) self.amount_label = QLabel("Amount (in ethers)") token_combo_box.addItems(items) token_combo_box.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) token_combo_box.currentTextChanged.connect(self.filterToken) self.token_avatar = QLabel() self.filterToken(first_token) token_address = self.token_address[first_token] self.setAvatar(token_address, self.token_avatar) self.token_layout = QVBoxLayout() token_wrapper_layout = QHBoxLayout() token_right_layout = QVBoxLayout() token_right_layout.addWidget(token_label) token_right_layout.addWidget(token_combo_box) token_wrapper_layout.addWidget(self.token_avatar) token_wrapper_layout.addLayout(token_right_layout) token_wrapper_layout.addStretch() self.token_layout.addLayout(token_wrapper_layout) def setupProgressSection(self): self.progress_layout = QHBoxLayout() progress_vertical_layout = QVBoxLayout() progress_wrapper_layout = QHBoxLayout() self.progress_label = QLabel() movie = QMovie('icons/ajax-loader.gif') self.progress_label.setMovie(movie) movie.start() self.progress_label.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) self.progress_description_label = QLabel() self.progress_description_label.setText( "Transaction is being confirmed. Please wait!") self.progress_description_label.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) progress_wrapper_layout.addWidget(self.progress_label) progress_wrapper_layout.addWidget(self.progress_description_label) progress_vertical_layout.addLayout(progress_wrapper_layout, 1) self.progress_layout.addLayout(progress_vertical_layout) self.sendTransactionFinished() def setupSendButtonSection(self): self.send_layout = QVBoxLayout() self.amount_line_edit = QLineEdit() self.send_button = QPushButton("Send") self.send_button.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) self.send_button.clicked.connect(self.sendButtonClicked) pal = self.send_button.palette() pal.setColor(QPalette.Button, QColor(Qt.green)) self.send_button.setAutoFillBackground(True) self.send_button.setPalette(pal) self.send_button.update() self.send_layout.addWidget(self.amount_label) self.send_layout.addWidget(self.amount_line_edit) self.send_layout.addWidget(self.send_button) def setupFeeSection(self): self.slider_layout = QVBoxLayout() fee_label = QLabel("Fee") self.fee_slider = QSlider(Qt.Horizontal) self.fee_slider.setRange(1, 10) self.fee_slider.setValue(3) self.fee_slider.valueChanged.connect(self.feeSliderChanged) self.gwei_label = QLabel() self.feeSliderChanged(3) self.slider_layout.addWidget(fee_label) self.slider_layout.addWidget(self.fee_slider) self.slider_layout.addWidget(self.gwei_label) def filterToken(self, token_name): address = self.token_address[token_name] token_information = None if token_name != 'Ethereum': token_information = self.token_informations[token_name] self.amount_label.setText("Amount") else: self.amount_label.setText("Amount (in ethers)") self.updateBalanceLabel(token_name, self.sender_account, token_information) self.setAvatar(address, self.token_avatar) self.token_name = token_name def filterSender(self, account_address): self.sender_account = account_address token_information = None if self.token_name != 'Ethereum': token_information = self.token_informations[self.token_name] self.updateBalanceLabel(self.token_name, account_address, token_information) self.setAvatar(account_address, self.avatar) def updateBalanceLabel(self, token_name, account_address, token_information=None): if token_name == 'Ethereum': self.balance_label.setText("Balance: %.5f ethers" % blockchain.get_balance(account_address)) else: self.balance_label.setText("Balance: %d coins" % blockchain.get_token_balance( account_address, token_information)) def setAvatar(self, code, avatar): img_filename = render_avatar(code) pixmap = QPixmap(img_filename) avatar.setPixmap(pixmap) def feeSliderChanged(self, value): self.gwei_label.setText("%d GWei" % value) self.fee = value def sendButtonClicked(self): password, ok = QInputDialog.getText(self, "Create A New Transaction", "Password:", QLineEdit.Password) if ok and password != '': self.progress_label.setVisible(True) self.progress_description_label.setVisible(True) tx = SendTransaction(sender=self.sender_account, password=password, destination=self.destination_line_edit.text(), amount=self.amount_line_edit.text(), fee=self.fee) token_information = None if self.token_name != 'Ethereum': token_information = self.token_informations[self.token_name] self.send_token_thread.prepareTransaction( tx, token_information) self.send_token_thread.start() else: self.send_thread.prepareTransaction(tx) self.send_thread.start() def sendTransactionFinished(self): self.progress_label.setVisible(False) self.progress_description_label.setVisible(False)
class NewWindow(QMainWindow): def __init__(self): super(NewWindow, self).__init__() # def setupUi(self, NewWindow): self.latlong = "0" self.textEdit = QTextEdit() self.mainWidget = QWidget() self.mainLayout = QVBoxLayout() font0 = QFont("Arial", 12) font0.setBold(True) font01 = QFont("Arial", 12) font02 = QFont("Arial", 12) self.text1 = QLabel("<b>Domyślne Współrzędne:</b><br/>" "Szerokość: 51° 06' 00''<br/>" "Długość: 17° 01' 00''<br/>" "(Współrzędne geograficzne Wrocławia)") self.solarpanelcordinates = QLabel('WSPÓŁRZĘDNE PANELU SŁONECZNEGO: ') self.solarpanelcordinates.setFont(font0) # self.solarpanelcordinates.setFrameStyle(QFrame.Box | QFrame.Sunken) # self.solarpanelcordinates.setMidLineWidth(6) self.text1.setFont(font01) self.text1.setFrameStyle(QFrame.Box | QFrame.Raised) self.text1.setMidLineWidth(6) self.result4 = QLabel('') self.result4.setFont(font02) self.result4.setMidLineWidth(3) self.result5 = QLabel('') self.result5.setFont(font02) self.result6 = QLabel('') self.result6.setFont(font02) self.result7 = QLabel('') self.result7.setFont(font02) self.result8 = QLabel('') self.result8.setFont(font02) self.result9 = QLabel('') self.result9.setFont(font02) self.mainLayout.addWidget(self.text1) self.mainLayout.addWidget(self.solarpanelcordinates) self.mainLayout.addWidget(self.result4) self.mainLayout.addWidget(self.result5) self.mainLayout.addWidget(self.result6) self.mainLayout.addWidget(self.result7) self.mainLayout.addWidget(self.result8) self.mainLayout.addWidget(self.result9) self.mainWidget.setLayout(self.mainLayout) self.setCentralWidget(self.mainWidget) #self.createActions() #self.createMenus() #self.createToolBars() #self.createStatusBar() self.createDockWindows() self.setWindowTitle("Nowe Okno") self.rad = 0 self.o = 0 self.timer = QTimer() self.timer.timeout.connect(self.dLocation) self.timerIsUp = False self.timer2 = QTimer() self.timer2.timeout.connect(self.update) self.timer2.start(1000) #self.newLetter() self.s = ephem.Sun() self.o = ephem.Observer() def createStatusBar(self): self.statusBar().showMessage("Gotowy") def dLocation(self): self.s = ephem.Sun() self.s.compute(epoch=ephem.now()) if self.dateandtimeEdit.text(): self.o.date = self.dateandtimeEdit.text() else: self.o.date = ephem.now() # 00:22:07 EDT 06:22:07 UT+1 self.s.compute(self.o) hour_angle = self.o.sidereal_time() - self.s.ra t = ephem.hours(hour_angle + ephem.hours('12:00')).norm # .norm for 0..24 self.rad = str(ephem.hours(hour_angle + ephem.hours('12:00')).norm) # self.result.setText("R.A.: " + str(self.s.a_ra) + " DEC.: " + str(self.s.a_dec)) # self.result2.setText("HOUR ANGLE: " + str(self.rad) + " SIDERAL TIME: " + str(self.o.sidereal_time())) # self.result3.setText("SUN Altitude: " + str(self.s.alt) + " SUN Azimuth: " + str(self.s.az)) self.result4.setText("R.A.: " + str(self.s.a_ra)) self.result5.setText("DEC.: " + str(self.s.a_dec)) self.result6.setText("HOUR ANGLE: " + str(self.rad)) self.result7.setText("SIDERAL TIME: " + str(self.o.sidereal_time())) self.result8.setText("SUN Altitude: " + str(self.s.alt)) self.result9.setText("SUN Azimuth: " + str(self.s.az)) def createDockWindows(self): dock = QDockWidget("Współrzędne Geograficzne Panelu: ", self) s = ephem.Sun() s.compute(epoch=ephem.now()) dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.multiWidget3 = QWidget() font5 = QFont("Arial", 12) font6 = QFont("Arial", 17) self.vLayout3 = QGridLayout() self.result = QLabel(self.latlong) self.latitude = QLabel('Szerokość') self.longitude = QLabel('Długość') self.dateandtime = QLabel('Data i Czas') self.solarpanelcor = QLabel('WSPÓŁRZĘDNE PANELU SŁONECZNEGO: ') self.latitudeEdit = QLineEdit() self.latitudeEdit.setFixedHeight(28) self.latitudeEdit.setFixedWidth(386) self.latitudeEdit.setStatusTip( "Wprowadzona szerokość powinna być w stopniach dziesiętnych (np.: 51.100000)" ) self.longitudeEdit = QLineEdit() self.longitudeEdit.setFixedHeight(28) self.longitudeEdit.setFixedWidth(386) self.longitudeEdit.setStatusTip( "Wprowadzona długość powinna być w stopniach dziesiętnych (np.: 17.03333)" ) self.dateandtimeEdit = QLineEdit() self.dateandtimeEdit.setFixedHeight(28) self.dateandtimeEdit.setFixedWidth(386) self.dateandtimeEdit.setStatusTip( "Wprowadzona data powinna być w formacie: rok/mies/dzień<spacja>godz:min:sek (np.: 2022/12/4 8:12:7)" ) self.button = QPushButton('Wylicz współrzędne / Przerwij liczenie', self) self.button.clicked.connect(self.handleButton3) self.latitude.setFont(font5) self.longitude.setFont(font5) self.dateandtime.setFont(font5) self.button.setFont(font6) self.button.setStatusTip("Rozpoczyna Obliczenia") self.vLayout3.addWidget(self.latitude) self.vLayout3.addWidget(self.latitudeEdit) self.vLayout3.addWidget(self.longitude) self.vLayout3.addWidget(self.longitudeEdit) self.vLayout3.addWidget(self.dateandtime) self.vLayout3.addWidget(self.dateandtimeEdit) self.vLayout3.addWidget(self.button) self.multiWidget3.setLayout(self.vLayout3) dock.setWidget(self.multiWidget3) self.addDockWidget(Qt.RightDockWidgetArea, dock) # self.viewMenu.addAction(dock.toggleViewAction()) def handleButton3(self): self.button.setStatusTip("Przerywa liczenie") if self.timerIsUp == False: if self.latitudeEdit.text() and self.longitudeEdit.text(): self.o.lat = self.latitudeEdit.text() self.o.lon = self.longitudeEdit.text() else: self.o.lon, self.o.lat = '17.03333', '51.100000' # Współrzędne Wrocławia self.timer.start(1000) self.timerIsUp = True else: self.timer.stop() self.timerIsUp = False self.button.setStatusTip("Rozpoczyna Obliczenia")
class AbstractReferenceSelector(ABC, QWidget, metaclass=SelectorMeta): changed = Signal() def __init__(self, parent=None): QWidget.__init__(self, parent) self.completer = None self.p_selected_id = 0 self.layout = QHBoxLayout() self.layout.setMargin(0) self.name = QLineEdit() self.name.setText("") self.layout.addWidget(self.name) self.details = QLabel() self.details.setText("") self.details.setVisible(False) self.layout.addWidget(self.details) self.button = QPushButton("...") self.button.setFixedWidth(self.button.fontMetrics().width("XXXX")) self.layout.addWidget(self.button) self.setLayout(self.layout) self.setFocusProxy(self.name) self.button.clicked.connect(self.on_button_clicked) if self.details_field: self.name.setFixedWidth(self.name.fontMetrics().width("X") * 15) self.details.setVisible(True) self.completer = QCompleter(self.dialog.model.completion_model) self.completer.setCompletionColumn( self.dialog.model.completion_model.fieldIndex(self.selector_field)) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.name.setCompleter(self.completer) self.completer.activated[QModelIndex].connect(self.on_completion) def getId(self): return self.p_selected_id def setId(self, selected_id): if self.p_selected_id == selected_id: return self.p_selected_id = selected_id self.name.setText( self.dialog.model.getFieldValue(selected_id, self.selector_field)) if self.details_field: self.details.setText( self.dialog.model.getFieldValue(selected_id, self.details_field)) selected_id = Property(int, getId, setId, notify=changed, user=True) def on_button_clicked(self): ref_point = self.mapToGlobal(self.name.geometry().bottomLeft()) self.dialog.setGeometry(ref_point.x(), ref_point.y(), self.dialog.width(), self.dialog.height()) res = self.dialog.exec_(enable_selection=True, selected=self.selected_id) if res: self.selected_id = self.dialog.selected_id self.changed.emit() @Slot(QModelIndex) def on_completion(self, index): model = index.model() self.selected_id = model.data(model.index(index.row(), 0), Qt.DisplayRole) self.changed.emit() def isCustom(self): return True
class UIMainWindow(object): """Container class to hold all UI-related creation methods. Must be sublcassed. """ def create_ui(self): """Setup main UI elements, dock widgets, UI-related elements, etc. """ log.debug('Loading UI') # Undo Stack self.undo_stack = QUndoStack(self) self.undo_stack.setUndoLimit(100) # Object navigation history self.obj_history = deque([], config.MAX_OBJ_HISTORY) app = QApplication.instance() base_font = QFont() base_font.fromString(self.prefs['base_font']) app.setFont(base_font) # Object class table widget # classTable = QTableView(self) classTable = classtable.TableView(self) classTable.setObjectName("classTable") classTable.setAlternatingRowColors(True) classTable.setFrameShape(QFrame.StyledPanel) classTable_font = QFont() classTable_font.fromString(self.prefs['class_table_font']) classTable.setFont(classTable_font) fm = classTable.fontMetrics() classTable.setWordWrap(True) classTable.setEditTriggers(QAbstractItemView.EditKeyPressed | QAbstractItemView.DoubleClicked | QAbstractItemView.AnyKeyPressed | QAbstractItemView.SelectedClicked) # classTable.horizontalHeader().setMovable(True) # classTable.verticalHeader().setMovable(False) classTable.horizontalHeader().setSectionResizeMode(QHeaderView.Interactive) classTable.verticalHeader().setSectionResizeMode(QHeaderView.Interactive) classTable.horizontalHeader().setDefaultSectionSize(self.prefs['default_column_width']) classTable.verticalHeader().setDefaultSectionSize(fm.height() + 0) classTable.setSelectionMode(QAbstractItemView.ExtendedSelection) classTable.setContextMenuPolicy(Qt.CustomContextMenu) classTable.customContextMenuRequested.connect(self.custom_table_context_menu) # Create table model and proxy layers for transposing and filtering self.classTableModel = classtable.IDFObjectTableModel(classTable) self.transposeableModel = classtable.TransposeProxyModel(self.classTableModel) self.transposeableModel.setSourceModel(self.classTableModel) self.sortableModel = classtable.SortFilterProxyModel(self.transposeableModel) self.sortableModel.setSourceModel(self.transposeableModel) # Assign model to table (enable sorting FIRST) # table.setSortingEnabled(True) # Disable for now, CRUD actions won't work! classTable.setModel(self.sortableModel) # Connect some signals selection_model = classTable.selectionModel() selection_model.selectionChanged.connect(self.table_selection_changed) scroll_bar = classTable.verticalScrollBar() scroll_bar.valueChanged.connect(self.scroll_changed) # These are currently broken # classTable.horizontalHeader().sectionMoved.connect(self.moveObject) # classTable.verticalHeader().sectionMoved.connect(self.moveObject) # Object class tree widget classTreeDockWidget = QDockWidget("Object Classes and Counts", self) classTreeDockWidget.setObjectName("classTreeDockWidget") classTreeDockWidget.setAllowedAreas(Qt.AllDockWidgetAreas) classTree = QTreeView(classTreeDockWidget) classTree.setUniformRowHeights(True) classTree.setAllColumnsShowFocus(True) classTree.setRootIsDecorated(False) classTree.setExpandsOnDoubleClick(True) classTree.setIndentation(15) classTree.setAnimated(True) classTree_font = QFont() classTree_font.fromString(self.prefs['class_tree_font']) classTree.setFont(classTree_font) classTree.setAlternatingRowColors(True) classTree.setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel) palette = classTree.palette() palette.setColor(QPalette.Highlight, Qt.darkCyan) classTree.setPalette(palette) class_tree_window = QWidget(classTreeDockWidget) class_tree_dock_layout_v = QVBoxLayout() class_tree_dock_layout_h = QHBoxLayout() class_tree_dock_layout_v.setContentsMargins(0, 8, 0, 0) class_tree_dock_layout_h.setContentsMargins(0, 0, 0, 0) class_tree_filter_edit = QLineEdit(classTreeDockWidget) class_tree_filter_edit.setPlaceholderText("Filter Classes") class_tree_filter_edit.textChanged.connect(self.treeFilterRegExpChanged) class_tree_filter_cancel = QPushButton("Clear", classTreeDockWidget) class_tree_filter_cancel.setMaximumWidth(45) class_tree_filter_cancel.clicked.connect(self.clearTreeFilterClicked) class_tree_dock_layout_h.addWidget(class_tree_filter_edit) class_tree_dock_layout_h.addWidget(class_tree_filter_cancel) class_tree_dock_layout_v.addLayout(class_tree_dock_layout_h) class_tree_dock_layout_v.addWidget(classTree) class_tree_window.setLayout(class_tree_dock_layout_v) classTreeDockWidget.setWidget(class_tree_window) classTreeDockWidget.setContentsMargins(0,0,0,0) # Comments widget commentDockWidget = QDockWidget("Comments", self) commentDockWidget.setObjectName("commentDockWidget") commentDockWidget.setAllowedAreas(Qt.AllDockWidgetAreas) commentView = UndoRedoTextEdit(commentDockWidget, self) commentView.setLineWrapMode(QTextEdit.FixedColumnWidth) commentView.setLineWrapColumnOrWidth(499) commentView.setFrameShape(QFrame.StyledPanel) commentView_font = QFont() commentView_font.fromString(self.prefs['comments_font']) commentView.setFont(commentView_font) commentDockWidget.setWidget(commentView) # Info and help widget infoDockWidget = QDockWidget("Info", self) infoDockWidget.setObjectName("infoDockWidget") infoDockWidget.setAllowedAreas(Qt.AllDockWidgetAreas) infoView = QTextEdit(infoDockWidget) infoView.setFrameShape(QFrame.StyledPanel) infoView.setReadOnly(True) infoDockWidget.setWidget(infoView) # Node list and jump menu widget refDockWidget = QDockWidget("Field References", self) refDockWidget.setObjectName("refDockWidget") refDockWidget.setAllowedAreas(Qt.AllDockWidgetAreas) ref_model = reftree.ReferenceTreeModel(None, refDockWidget) refView = QTreeView(refDockWidget) refView.setModel(ref_model) refView.setUniformRowHeights(True) refView.setRootIsDecorated(False) refView.setIndentation(15) refView.setColumnWidth(0, 160) refView.setFrameShape(QFrame.StyledPanel) refDockWidget.setWidget(refView) refView.doubleClicked.connect(self.ref_tree_double_clicked) # Logging and debugging widget logDockWidget = QDockWidget("Log Viewer", self) logDockWidget.setObjectName("logDockWidget") logDockWidget.setAllowedAreas(Qt.AllDockWidgetAreas) logView = QPlainTextEdit(logDockWidget) logView.setLineWrapMode(QPlainTextEdit.NoWrap) logView.setReadOnly(True) logView_font = QFont() logView_font.fromString(self.prefs['base_font']) logView.setFont(logView_font) logView.ensureCursorVisible() logDockWidget.setWidget(logView) # Undo view widget undoDockWidget = QDockWidget("Undo History", self) undoDockWidget.setObjectName("undoDockWidget") undoDockWidget.setAllowedAreas(Qt.AllDockWidgetAreas) undoView = QUndoView(self.undo_stack) undoDockWidget.setWidget(undoView) # Define corner docking behaviour self.setDockNestingEnabled(True) self.setCorner(Qt.TopLeftCorner, Qt.LeftDockWidgetArea) self.setCorner(Qt.TopRightCorner, Qt.RightDockWidgetArea) self.setCorner(Qt.BottomLeftCorner, Qt.LeftDockWidgetArea) self.setCorner(Qt.BottomRightCorner, Qt.RightDockWidgetArea) # Assign main widget and dock widgets to QMainWindow self.setCentralWidget(classTable) self.addDockWidget(Qt.LeftDockWidgetArea, classTreeDockWidget) self.addDockWidget(Qt.RightDockWidgetArea, commentDockWidget) self.addDockWidget(Qt.RightDockWidgetArea, infoDockWidget) self.addDockWidget(Qt.RightDockWidgetArea, refDockWidget) self.addDockWidget(Qt.RightDockWidgetArea, logDockWidget) self.addDockWidget(Qt.RightDockWidgetArea, undoDockWidget) # Store widgets for access by other objects self.classTable = classTable self.commentView = commentView self.infoView = infoView self.classTree = classTree self.logView = logView self.undoView = undoView self.refView = refView self.filterTreeBox = class_tree_filter_edit # Store docks for access by other objects self.commentDockWidget = commentDockWidget self.infoDockWidget = infoDockWidget self.classTreeDockWidget = classTreeDockWidget self.logDockWidget = logDockWidget self.undoDockWidget = undoDockWidget self.refDockWidget = refDockWidget # Perform other UI-related initialization tasks self.center() self.setUnifiedTitleAndToolBarOnMac(True) self.setWindowIcon(QIcon(':/images/logo.png')) # Status bar setup self.statusBar().showMessage('Status: Ready') self.unitsLabel = QLabel() self.unitsLabel.setAlignment(Qt.AlignCenter) self.unitsLabel.setMinimumSize(self.unitsLabel.sizeHint()) self.unitsLabel.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken) self.statusBar().addPermanentWidget(self.unitsLabel) self.pathLabel = QLabel() self.pathLabel.setAlignment(Qt.AlignCenter) self.pathLabel.setMinimumSize(self.pathLabel.sizeHint()) self.pathLabel.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken) self.statusBar().addPermanentWidget(self.pathLabel) self.versionLabel = QLabel() self.versionLabel.setAlignment(Qt.AlignCenter) self.versionLabel.setMinimumSize(self.versionLabel.sizeHint()) self.versionLabel.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken) self.statusBar().addPermanentWidget(self.versionLabel) self.progressBarIDF = QProgressBar() self.progressBarIDF.setAlignment(Qt.AlignCenter) self.progressBarIDF.setMaximumWidth(200) self.statusBar().addPermanentWidget(self.progressBarIDF) self.clipboard = QApplication.instance().clipboard() self.obj_clipboard = [] self.setStyleSheet(""" QToolTip { background-color: gray; color: white; border: black solid 1px } # QMenu { # background-color: rgbf(0.949020, 0.945098, 0.941176); # color: rgb(255,255,255); # } # QMenu::item::selected { # background-color: rgbf(0.949020, 0.945098, 0.941176); # } """) def create_tray_menu(self): """Creates an icon and menu for the system tray """ # Menu for the system tray self.trayIconMenu = QMenu(self) self.trayIconMenu.addAction(self.minimizeAction) self.trayIconMenu.addAction(self.maximizeAction) self.trayIconMenu.addAction(self.restoreAction) self.trayIconMenu.addSeparator() self.trayIconMenu.addAction(self.exitAct) # System tray itself self.trayIcon = QSystemTrayIcon(self) self.trayIcon.setContextMenu(self.trayIconMenu) self.trayIcon.setIcon(QIcon(':/images/logo.png')) self.trayIcon.setToolTip('IDF+') self.trayIcon.show() def create_actions(self): """Creates appropriate actions for use in menus and toolbars. """ self.newAct = QAction(QIcon(':/images/new1.png'), "&New", self, shortcut=QKeySequence.New, statusTip="Create a new file", iconVisibleInMenu=True, triggered=self.new_file) self.openAct = QAction(QIcon(':/images/open.png'), "&Open...", self, shortcut=QKeySequence.Open, statusTip="Open an existing file", iconVisibleInMenu=True, triggered=self.open_file) self.saveAct = QAction(QIcon(':/images/save.png'), "&Save", self, shortcut=QKeySequence.Save, statusTip="Save the document to disk", iconVisibleInMenu=True, triggered=self.save) self.saveFormatAct = QAction(QIcon(':/images/save.png'), "&Format && Save", self, shortcut=QKeySequence('Ctrl+Shift+F'), statusTip="Format File and Save to disk", iconVisibleInMenu=True, triggered=self.format_save) self.saveAsAct = QAction(QIcon(':/images/saveas.png'), "Save &As...", self, shortcut=QKeySequence.SaveAs, statusTip="Save the document under a new name", iconVisibleInMenu=True, triggered=self.save_as) self.exitAct = QAction(QIcon(':/images/quit.png'), "E&xit", self, shortcut=QKeySequence('Ctrl+Q'), iconVisibleInMenu=True, statusTip="Exit the application", triggered=self.closeAllWindows) self.cutObjAct = QAction(QIcon(':/images/cut.png'), "Cu&t Object", self, shortcut=QKeySequence.Cut, statusTip="Cut current selection's contents to clipboard", iconVisibleInMenu=True, triggered=self.cutObject, iconText='Cut Obj') self.copyAct = QAction(QIcon(':/images/copy.png'), "&Copy Selected Values", self, statusTip="Copy current selection's contents to clipboard", iconVisibleInMenu=True, triggered=self.copySelected) self.pasteAct = QAction(QIcon(':/images/paste.png'), "&Paste Selected Values", self, statusTip="Paste clipboard into current selection", iconVisibleInMenu=True, triggered=self.pasteSelected) self.pasteExtAct = QAction(QIcon(':/images/paste.png'), "&Paste from External", self, shortcut=QKeySequence('Ctrl+Shift+v'), statusTip="Paste from external program", iconVisibleInMenu=True, triggered=self.paste_from_external) self.transposeAct = QAction("Transpose", self, shortcut=QKeySequence('Ctrl+t'), statusTip="Transpose rows and columns in object display", triggered=self.transpose_table) self.newObjAct = QAction(QIcon(':/images/new2.png'), "New Object", self, shortcut=QKeySequence('Ctrl+Shift+n'), statusTip="Create new object in current class", iconVisibleInMenu=True, triggered=self.newObject, iconText='New Obj') self.copyObjAct = QAction(QIcon(':/images/copy.png'), "Copy Object", self, shortcut=QKeySequence.Copy, statusTip="Copy the current Object(s)", iconVisibleInMenu=True, triggered=self.copyObject, iconText='Copy Obj') self.pasteObjAct = QAction(QIcon(':/images/paste.png'), "Paste Object", self, shortcut=QKeySequence.Paste, statusTip="Paste the currently copies Object(s)", iconVisibleInMenu=True, triggered=self.pasteObject, iconText='Paste Obj') self.dupObjAct = QAction(QIcon(':/images/copy.png'), "Duplicate Object", self, shortcut=QKeySequence('Shift+Ctrl+d'), statusTip="Duplicate the current Object(s)", iconVisibleInMenu=True, triggered=self.duplicateObject, iconText='Dup Obj') self.delObjAct = QAction(QIcon(':/images/delete.png'), "Delete Object", self, shortcut=QKeySequence.Delete, statusTip="Delete the current Object(s)", iconVisibleInMenu=True, triggered=self.deleteObject, iconText='Del Obj') self.undoAct = QAction(QIcon(':/images/undo.png'), "&Undo", self, shortcut=QKeySequence.Undo, statusTip="Undo previous action", iconVisibleInMenu=True, triggered=self.undo_stack.undo) self.redoAct = QAction(QIcon(':/images/redo.png'), "&Redo", self, shortcut=QKeySequence.Redo, statusTip="Redo previous action", iconVisibleInMenu=True, triggered=self.undo_stack.redo) self.groupAct = QAction("Hide Groups in Class Tree", self, shortcut=QKeySequence('Ctrl+g'), triggered=self.toggle_groups, checkable=True) # self.navForwardAct = QAction("Forward", self, # shortcut=QKeySequence('Ctrl+Plus'), # statusTip="Go forward to the next object", # triggered=self.navForward) # # self.navBackAct = QAction("Back", self, # shortcut=QKeySequence('Ctrl+Minus'), # statusTip="Go back to the previous object", # triggered=self.navBack) self.showInFolderAct = QAction(QIcon(':/images/new.png'), "&Show in folder", self, shortcut=QKeySequence('Ctrl+Shift+t'), statusTip="Open location of current file", iconVisibleInMenu=True) self.showInFolderAct.triggered.connect(lambda: self.show_in_folder()) self.epDocGettingStartedAction = QAction("EnergyPlus Getting Started", self, triggered=self.energy_plus_docs) self.epDocIORefAction = QAction("EnergyPlus I/O Reference", self, triggered=self.energy_plus_docs) self.epDocOutputDetailsAction = QAction("EnergyPlus Output Details and Examples", self, triggered=self.energy_plus_docs) self.epDocEngineeringRefAction = QAction("EnergyPlus Engineering Reference", self, triggered=self.energy_plus_docs) self.epDocAuxiliaryProgsAction = QAction("EnergyPlus Auxiliary Programs", self, triggered=self.energy_plus_docs) self.epDocEMSGuideAction = QAction("EnergyPlus EMS Application Guide", self, triggered=self.energy_plus_docs) self.epDocComplianceAction = QAction("Using EnergyPlus for Compliance", self, triggered=self.energy_plus_docs) self.epDocInterfaceAction = QAction("External Interface Application Guide", self, triggered=self.energy_plus_docs) self.epDocTipsTricksAction = QAction("Tips and Tricks Using EnergyPlus", self, triggered=self.energy_plus_docs) self.epDocPlantGuideAction = QAction("EnergyPlus Plant Application Guide", self, triggered=self.energy_plus_docs) self.epDocAcknowledgmentsAction = QAction("EnergyPlus Acknowledgments", self, triggered=self.energy_plus_docs) self.openInEditorAct = QAction(QIcon(':/images/new.png'), "&Open in text editor", self, shortcut=QKeySequence('Ctrl+e'), statusTip="Open current file in default editor", iconVisibleInMenu=True, triggered=self.open_in_text_editor) self.helpAct = QAction("&EnergyPlus Help (Online)", self, statusTip="Show the EnergyPlus' help", triggered=self.energyplus_help) self.aboutAct = QAction("&About IDF+", self, statusTip="Show the application's About box", triggered=self.about) self.clearRecentAct = QAction("Clear Recent", self, statusTip="Clear recent files", triggered=self.clear_recent) self.minimizeAction = QAction("Mi&nimize", self, triggered=self.hide) self.maximizeAction = QAction("Ma&ximize", self, triggered=self.showMaximized) self.restoreAction = QAction("&Restore", self, triggered=self.showNormal) self.showPrefsAction = QAction("&Preferences", self, triggered=self.show_prefs_dialog) self.showSearchAction = QAction("&Search && Replace", self, shortcut=QKeySequence('Ctrl+f'), triggered=self.show_search_dialog) self.findThisAct = QAction("Find This", self, triggered=self.find_this) self.jumpFilterGeometry = QAction("Include Geometry", self, triggered=self.jump_to_filter_geometry, checkable=True) self.setIPUnitsAction = QAction("&IP Units", self, triggered=self.toggle_units, checkable=True) self.setSIUnitsAction = QAction("&SI Units", self, triggered=self.toggle_units, checkable=True) self.classWithObjsAction = QAction("Show Only Classes With Objects", self, shortcut=QKeySequence('Ctrl+l'), statusTip="Show Only Classes With Objects", triggered=self.toggle_full_tree, checkable=True) self.fillRightAction = QAction("Fill right", self, shortcut=QKeySequence('Ctrl+d'), statusTip="Fill right", triggered=self.fill_right) self.logDockWidgetAct = self.logDockWidget.toggleViewAction() self.transposeAct.setEnabled(False) self.setSIUnitsAction.setChecked(True) self.undoAct.setEnabled(False) self.redoAct.setEnabled(False) self.saveAct.setEnabled(False) self.undo_stack.canUndoChanged.connect(self.toggle_can_undo) self.undo_stack.canRedoChanged.connect(self.toggle_can_redo) self.logDockWidgetAct.toggled.connect(self.start_log_watcher) def toggle_can_undo(self): if self.undo_stack.canUndo(): new_state = True else: new_state = False self.undoAct.setEnabled(new_state) self.set_dirty(new_state) def toggle_can_redo(self): if self.undo_stack.canRedo(): new_state = True else: new_state = False self.redoAct.setEnabled(new_state) def create_menus(self): """Create all required items for menus. """ # File Menu self.fileMenu = self.menuBar().addMenu("&File") self.fileMenuActions = (self.newAct, self.openAct, self.saveAct, self.saveAsAct, self.saveFormatAct, None, self.exitAct) self.update_file_menu() self.fileMenu.aboutToShow.connect(self.update_file_menu) # Edit Menu self.editMenu = self.menuBar().addMenu("&Edit") self.editMenu.addAction(self.undoAct) self.editMenu.addAction(self.redoAct) self.editMenu.addSeparator().setText('Objects') self.editMenu.addAction(self.newObjAct) self.editMenu.addAction(self.dupObjAct) self.editMenu.addSeparator() self.editMenu.addAction(self.cutObjAct) self.editMenu.addAction(self.copyObjAct) self.editMenu.addAction(self.pasteObjAct) self.editMenu.addAction(self.pasteExtAct) self.editMenu.addSeparator() self.editMenu.addAction(self.delObjAct) self.editMenu.addSeparator().setText('Values') self.editMenu.addAction(self.copyAct) self.editMenu.addAction(self.pasteAct) self.editMenu.addSeparator() self.editMenu.addAction(self.fillRightAction) self.editMenu.addSeparator() self.editMenu.addAction(self.showSearchAction) # Tools Menu self.toolsMenu = self.menuBar().addMenu("&Tools") self.toolsMenu.addAction(self.showInFolderAct) self.toolsMenu.addAction(self.openInEditorAct) self.toolsMenu.addSeparator() self.toolsMenu.addAction(self.showPrefsAction) # View Menu self.viewMenu = self.menuBar().addMenu("&View") action_group = QActionGroup(self) self.viewMenu.addAction(action_group.addAction(self.setSIUnitsAction)) self.viewMenu.addAction(action_group.addAction(self.setIPUnitsAction)) self.viewMenu.addSeparator().setText('Dockable Widgets') self.viewMenu.addAction(self.classTreeDockWidget.toggleViewAction()) self.viewMenu.addAction(self.infoView.parent().toggleViewAction()) self.viewMenu.addAction(self.commentView.parent().toggleViewAction()) self.viewMenu.addAction(self.logDockWidgetAct) self.viewMenu.addAction(self.undoView.parent().toggleViewAction()) self.viewMenu.addSeparator().setText('Toolbars') self.viewMenu.addAction(self.fileToolBar.toggleViewAction()) self.viewMenu.addAction(self.editToolBar.toggleViewAction()) # self.viewMenu.addAction(self.navToolBar.toggleViewAction()) self.viewMenu.addAction(self.filterToolBar.toggleViewAction()) self.viewMenu.addSeparator() self.viewMenu.addAction(self.classWithObjsAction) self.viewMenu.addAction(self.groupAct) self.viewMenu.addSeparator() self.viewMenu.addAction(self.transposeAct) # Jump Menu self.jumpToMenu = self.menuBar().addMenu("&Jump") self.update_jump_menu() self.jumpToMenu.aboutToShow.connect(self.update_jump_menu) self.jumpFilterGeometry.setEnabled(False) # Help Menu self.helpMenu = self.menuBar().addMenu("&Help") self.helpMenu.addAction(self.helpAct) self.helpMenu.addAction(self.aboutAct) self.helpMenu.addSeparator() self.helpMenu.addAction(self.epDocGettingStartedAction) self.helpMenu.addAction(self.epDocIORefAction) self.helpMenu.addAction(self.epDocOutputDetailsAction) self.helpMenu.addAction(self.epDocEngineeringRefAction) self.helpMenu.addAction(self.epDocAuxiliaryProgsAction) self.helpMenu.addAction(self.epDocEMSGuideAction) self.helpMenu.addAction(self.epDocComplianceAction) self.helpMenu.addAction(self.epDocInterfaceAction) self.helpMenu.addAction(self.epDocTipsTricksAction) self.helpMenu.addAction(self.epDocPlantGuideAction) self.helpMenu.addAction(self.epDocAcknowledgmentsAction) def create_tool_bars(self): """Creates the necessary toolbars. """ # File Toolbar self.fileToolBar = self.addToolBar("File Toolbar") self.fileToolBar.setObjectName('fileToolbar') self.fileToolBar.addAction(self.newAct) self.fileToolBar.addAction(self.openAct) self.fileToolBar.addAction(self.saveAct) self.fileToolBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) # Edit Toolbar self.editToolBar = self.addToolBar("Edit Toolbar") self.editToolBar.setObjectName('editToolbar') self.editToolBar.addAction(self.undoAct) self.editToolBar.addAction(self.redoAct) self.editToolBar.addAction(self.newObjAct) self.editToolBar.addAction(self.dupObjAct) self.editToolBar.addAction(self.delObjAct) self.editToolBar.addAction(self.cutObjAct) self.editToolBar.addAction(self.copyObjAct) self.editToolBar.addAction(self.pasteObjAct) self.editToolBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) # Object history navigation toolbar # self.navToolBar = self.addToolBar("Navigation Toolbar") # self.navToolBar.setObjectName('viewToolBar') # self.navToolBar.addAction(self.navForwardAct) # self.navToolBar.addAction(self.navBackAct) # self.navToolBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) # Object filter toolbar self.filterToolBar = self.addToolBar("Filter Toolbar") self.filterToolBar.setObjectName('filterToolBar') self.filterBox = QLineEdit() self.filterBox.setPlaceholderText("Filter Objects") self.filterBox.setMaximumWidth(160) self.filterBox.setFixedWidth(160) # filterLabel = QLabel("Filter Obj:", self) # filterLabel.setBuddy(self.filterBox) # self.filterToolBar.addWidget(filterLabel) self.filterBox.textChanged.connect(self.tableFilterRegExpChanged) self.filterBox.textChanged.connect(self.treeFilterRegExpChanged) clearFilterButton = QPushButton('Clear') clearFilterButton.setMaximumWidth(45) clearFilterButton.clicked.connect(self.clearFilterClicked) self.filterToolBar.addWidget(self.filterBox) self.filterToolBar.addWidget(clearFilterButton) self.caseSensitivity = QCheckBox('Case Sensitive') self.caseSensitivity.stateChanged.connect(self.caseSensitivityChanged) self.filterToolBar.addWidget(self.caseSensitivity) self.filterToolBar.addSeparator() self.filterToolBar.addAction(self.transposeAct) def create_shortcuts(self): """Creates keyboard shortcuts. """ # QShortcut(QKeySequence('Ctrl+l'), self).activated.connect(self.toggle_full_tree) # QShortcut(QKeySequence('Ctrl+d'), self).activated.connect(self.fill_right) # QShortcut(QKeySequence('Ctrl+d'), self).activated.connect(self.fill_right) # def createAction(self, text, slot=None, shortcut=None, icon=None, # tip=None, checkable=False, signal="triggered()"): # action = QAction(text, self) # if icon is not None: # action.setIcon(QIcon(":/%s.png" % icon)) # if shortcut is not None: # action.setShortcut(shortcut) # if tip is not None: # action.setToolTip(tip) # action.setStatusTip(tip) # if slot is not None: # self.connect(action, QtCore.SIGNAL(signal), slot) # if checkable: # action.setCheckable(True) # return action # def custom_table_context_menu(self, position): # Create a menu and populate it with actions menu = QMenu(self) menu.addAction(self.undoAct) menu.addAction(self.redoAct) menu.addSeparator() menu.addAction(self.copyObjAct) menu.addAction(self.dupObjAct) menu.addAction(self.delObjAct) menu.addAction(self.newObjAct) menu.addAction(self.cutObjAct) menu.addSeparator() menu.addMenu(self.jumpToMenu) menu.addSeparator() menu.addAction(self.findThisAct) menu.popup(self.classTable.viewport().mapToGlobal(position)) self.mouse_position = position def reset_progress_bar(self): self.progressBarIDF.hide() def center(self): """Called to center the window on the screen on startup. """ screen = QDesktopWidget().screenGeometry() size = self.geometry() self.move((screen.width() - size.width()) / 2, (screen.height() - size.height()) / 2) def show_prefs_dialog(self): """Handles showing the settings dialog and setting its values. """ dlg = PrefsDialog(self, self.prefs) if dlg.exec_(): # Refresh the table view to take into account any new prefs self.load_table_view(self.current_obj_class) # Clear the idd cache if requested if self.prefs.get('clear_idd_cache', False) == True: self.clear_idd_cache() # Update preferences if various flags apply if not self.idf: return options_dict = dict() if self.prefs.get('apply_default_save_behaviour', False) == True: options_dict.update({'sort_order': self.prefs.get('sort_order'), 'special_formatting': self.prefs.get('special_formatting')}) # if self.prefs.get('apply_default_units_behaviour', False) == True: # options_dict.update({'save_units': self.prefs.get('save_units')}) # if self.prefs.get('apply_default_hidden_class_behaviour', False) == True: # options_dict.update({'save_hidden_classes': self.prefs.get('save_hidden_classes')}) if options_dict: self.idf.set_options(options_dict) self.set_dirty(True) def show_search_dialog(self): """Opens the search dialog. """ SearchReplaceDialog(self).show() def find_this(self): """Searches for fields with similar content. """ index = self.classTable.indexAt(self.mouse_position) text = self.classTable.model().data(index, Qt.EditRole) if text: SearchReplaceDialog(self, initial_query=text).show()
class MainWindow(QMainWindow): def __init__(self, application, *args, **kwargs): super(MainWindow, self).__init__(*args, **kwargs) self.printer_thread = WorkerThread() self.printer_thread.message.connect(self.standardOutputWritten) self.printer_thread.start() self.app = application self.app.setStyle("Fusion") self.__set_interface() self.__set_layouts() self.__set_stylesheet() self.__set_connections() self.__set_params() def closeEvent(self, event): self.printer_thread.stop() def __set_interface(self): self.button_width = 0.35 self.button_height = 0.05 self.setWindowTitle("GSI-RADS") self.__getScreenDimensions() self.setGeometry(self.left, self.top, self.width, self.height) self.setMaximumWidth(self.width) #self.setMaximumHeight(self.height) self.setMinimumWidth(self.width) self.setMinimumHeight(self.height) self.move(self.width / 2, self.height / 2) self.menu_bar = QMenuBar(self) self.menu_bar.setNativeMenuBar( False ) # https://stackoverflow.com/questions/25261760/menubar-not-showing-for-simple-qmainwindow-code-qt-creator-mac-os self.file_menu = self.menu_bar.addMenu('File') self.import_dicom_action = QAction( QIcon( os.path.join(os.path.dirname(os.path.realpath(__file__)), 'images/database-icon.png')), 'Import DICOM', self) self.import_dicom_action.setShortcut('Ctrl+D') self.file_menu.addAction(self.import_dicom_action) self.quit_action = QAction('Quit', self) self.quit_action.setShortcut("Ctrl+Q") self.file_menu.addAction(self.quit_action) self.settings_menu = self.menu_bar.addMenu('Settings') self.settings_seg_menu = self.settings_menu.addMenu("Segmentation...") self.settings_seg_preproc_menu = self.settings_seg_menu.addMenu( "Preprocessing...") self.settings_seg_preproc_menu_p1_action = QAction( "Brain-masking off (P1)", checkable=True) self.settings_seg_preproc_menu_p2_action = QAction( "Brain-masking on (P2)", checkable=True) self.settings_seg_preproc_menu_p2_action.setChecked(True) self.settings_seg_preproc_menu.addAction( self.settings_seg_preproc_menu_p1_action) self.settings_seg_preproc_menu.addAction( self.settings_seg_preproc_menu_p2_action) self.help_menu = self.menu_bar.addMenu('Help') self.readme_action = QAction( QIcon( os.path.join(os.path.dirname(os.path.realpath(__file__)), 'images/readme-icon.jpeg')), 'Tutorial', self) self.readme_action.setShortcut("Ctrl+R") self.help_menu.addAction(self.readme_action) self.about_action = QAction( QIcon( os.path.join(os.path.dirname(os.path.realpath(__file__)), 'images/about-icon.png')), 'About', self) self.about_action.setShortcut("Ctrl+A") self.help_menu.addAction(self.about_action) self.help_action = QAction( QIcon.fromTheme("help-faq"), "Help", self ) # Default icons can be found here: https://specifications.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html#guidelines self.help_action.setShortcut("Ctrl+J") self.help_menu.addAction(self.help_action) self.input_image_lineedit = QLineEdit() self.input_image_lineedit.setFixedWidth(self.width * (0.93 - self.button_width / 2)) self.input_image_lineedit.setFixedHeight(self.height * self.button_height) self.input_image_lineedit.setReadOnly(True) self.input_image_pushbutton = QPushButton('Input MRI') self.input_image_pushbutton.setFixedWidth(self.height * self.button_width) self.input_image_pushbutton.setFixedHeight(self.height * self.button_height) self.input_segmentation_lineedit = QLineEdit() self.input_segmentation_lineedit.setReadOnly(True) self.input_segmentation_lineedit.setFixedWidth( self.width * (0.93 - self.button_width / 2)) self.input_segmentation_lineedit.setFixedHeight(self.height * self.button_height) self.input_segmentation_pushbutton = QPushButton('Input segmentation') self.input_segmentation_pushbutton.setFixedWidth(self.height * self.button_width) self.input_segmentation_pushbutton.setFixedHeight(self.height * self.button_height) self.output_folder_lineedit = QLineEdit() self.output_folder_lineedit.setReadOnly(True) self.output_folder_lineedit.setFixedWidth( self.width * (0.93 - self.button_width / 2)) self.output_folder_lineedit.setFixedHeight(self.height * self.button_height) self.output_folder_pushbutton = QPushButton('Output destination') self.output_folder_pushbutton.setFixedWidth(self.height * self.button_width) self.output_folder_pushbutton.setFixedHeight(self.height * self.button_height) self.run_button = QPushButton('Run diagnosis') self.run_button.setFixedWidth(self.height * self.button_width) self.run_button.setFixedHeight(self.height * self.button_height) self.main_display_tabwidget = QTabWidget() self.tutorial_textedit = QPlainTextEdit() self.tutorial_textedit.setReadOnly(True) self.tutorial_textedit.setFixedWidth(self.width * 0.97) self.tutorial_textedit.setPlainText( "HOW TO USE THE SOFTWARE: \n" " 1) Click 'Input MRI...' to select from your file explorer the MRI scan to process (unique file).\n" " 1*) Alternatively, Click File > Import DICOM... if you wish to process an MRI scan as a DICOM sequence.\n" " 2) Click 'Output destination' to choose a directory where to save the results \n" " 3) (OPTIONAL) Click 'Input segmentation' to choose a tumor segmentation mask file, if nothing is provided the internal model with generate the segmentation automatically \n" " 4) Click 'Run diagnosis' to perform the analysis. The human-readable version will be displayed in the interface.\n" " \n" "NOTE: \n" "The output folder is populated automatically with the following: \n" " * The diagnosis results in human-readable text (report.txt) and Excel-ready format (report.csv).\n" " * The automatic segmentation masks of the brain and the tumor in the original patient space (input_brain_mask.nii.gz and input_tumor_mask.nii.gz).\n" " * The input volume and tumor segmentation mask in MNI space in the sub-directory named \'registration\'.\n" ) self.main_display_tabwidget.addTab(self.tutorial_textedit, 'Tutorial') self.prompt_lineedit = QPlainTextEdit() self.prompt_lineedit.setReadOnly(True) self.prompt_lineedit.setFixedWidth(self.width * 0.97) self.main_display_tabwidget.addTab(self.prompt_lineedit, 'Logging') self.results_textedit = QPlainTextEdit() self.results_textedit.setReadOnly(True) self.results_textedit.setFixedWidth(self.width * 0.97) self.main_display_tabwidget.addTab(self.results_textedit, 'Results') self.sintef_logo_label = QLabel() self.sintef_logo_label.setPixmap( QPixmap( os.path.join(os.path.dirname(os.path.realpath(__file__)), 'images/sintef-logo.png'))) self.sintef_logo_label.setFixedWidth(0.95 * (self.width / 3)) self.sintef_logo_label.setFixedHeight( 1 * (self.height * self.button_height)) self.sintef_logo_label.setScaledContents(True) self.stolavs_logo_label = QLabel() self.stolavs_logo_label.setPixmap( QPixmap( os.path.join(os.path.dirname(os.path.realpath(__file__)), 'images/stolavs-logo.png'))) self.stolavs_logo_label.setFixedWidth(0.95 * (self.width / 3)) self.stolavs_logo_label.setFixedHeight( 1 * (self.height * self.button_height)) self.stolavs_logo_label.setScaledContents(True) self.amsterdam_logo_label = QLabel() self.amsterdam_logo_label.setPixmap( QPixmap( os.path.join(os.path.dirname(os.path.realpath(__file__)), 'images/amsterdam-logo.png'))) self.amsterdam_logo_label.setFixedWidth(0.95 * (self.width / 3)) self.amsterdam_logo_label.setFixedHeight( 1 * (self.height * self.button_height)) self.amsterdam_logo_label.setScaledContents(True) def __set_layouts(self): self.input_volume_hbox = QHBoxLayout() self.input_volume_hbox.addStretch(1) self.input_volume_hbox.addWidget(self.input_image_lineedit) self.input_volume_hbox.addWidget(self.input_image_pushbutton) self.input_volume_hbox.addStretch(1) self.input_seg_hbox = QHBoxLayout() self.input_seg_hbox.addStretch(1) self.input_seg_hbox.addWidget(self.input_segmentation_lineedit) self.input_seg_hbox.addWidget(self.input_segmentation_pushbutton) self.input_seg_hbox.addStretch(1) self.output_dir_hbox = QHBoxLayout() self.output_dir_hbox.addStretch(1) self.output_dir_hbox.addWidget(self.output_folder_lineedit) self.output_dir_hbox.addWidget(self.output_folder_pushbutton) self.output_dir_hbox.addStretch(1) self.run_action_hbox = QHBoxLayout() self.run_action_hbox.addStretch(1) self.run_action_hbox.addWidget(self.run_button) self.run_action_hbox.addStretch(1) self.dump_area_hbox = QHBoxLayout() self.dump_area_hbox.addStretch(1) self.dump_area_hbox.addWidget(self.main_display_tabwidget) self.dump_area_hbox.addStretch(1) self.logos_hbox = QHBoxLayout() self.logos_hbox.addStretch(1) self.logos_hbox.addWidget(self.sintef_logo_label) self.logos_hbox.addWidget(self.stolavs_logo_label) self.logos_hbox.addWidget(self.amsterdam_logo_label) self.logos_hbox.addStretch(1) self.main_vbox = QVBoxLayout() self.main_vbox.addWidget(self.menu_bar) #self.main_vbox.addStretch(1) self.main_vbox.addLayout(self.input_volume_hbox) self.main_vbox.addLayout(self.output_dir_hbox) self.main_vbox.addLayout(self.input_seg_hbox) self.main_vbox.addLayout(self.run_action_hbox) #self.main_vbox.addStretch(1) self.main_vbox.addLayout(self.dump_area_hbox) self.main_vbox.addLayout(self.logos_hbox) #self.main_vbox.addStretch(1) self.central_label = QLabel() self.central_label.setLayout(self.main_vbox) self.setCentralWidget(self.central_label) def __set_stylesheet(self): self.central_label.setStyleSheet( 'QLabel{background-color: qlineargradient(spread:pad, x1:0.5, y1:1, x2:0.5, y2:0, stop:0 rgba(207, 209, 207, 255), stop:1 rgba(230, 229, 230, 255));}' ) self.menu_bar.setStyleSheet(get_stylesheet('QMenuBar')) self.input_image_lineedit.setStyleSheet(get_stylesheet('QLineEdit')) self.input_image_pushbutton.setStyleSheet( get_stylesheet('QPushButton')) self.input_segmentation_lineedit.setStyleSheet( get_stylesheet('QLineEdit')) self.input_segmentation_pushbutton.setStyleSheet( get_stylesheet('QPushButton')) self.output_folder_lineedit.setStyleSheet(get_stylesheet('QLineEdit')) self.output_folder_pushbutton.setStyleSheet( get_stylesheet('QPushButton')) self.results_textedit.setStyleSheet(get_stylesheet('QTextEdit')) self.prompt_lineedit.setStyleSheet(get_stylesheet('QTextEdit')) self.run_button.setStyleSheet(get_stylesheet('QPushButton')) def __set_connections(self): self.run_button.clicked.connect(self.diagnose_main_wrapper) self.input_image_pushbutton.clicked.connect( self.run_select_input_image) self.input_segmentation_pushbutton.clicked.connect( self.run_select_input_segmentation) self.output_folder_pushbutton.clicked.connect( self.run_select_output_folder) self.readme_action.triggered.connect(self.readme_action_triggered) self.about_action.triggered.connect(self.about_action_triggered) self.quit_action.triggered.connect(self.quit_action_triggered) self.import_dicom_action.triggered.connect( self.import_dicom_action_triggered) self.help_action.triggered.connect(self.help_action_triggered) self.settings_seg_preproc_menu_p1_action.triggered.connect( self.settings_seg_preproc_menu_p1_action_triggered) self.settings_seg_preproc_menu_p2_action.triggered.connect( self.settings_seg_preproc_menu_p2_action_triggered) def __set_params(self): self.input_image_filepath = '' self.input_annotation_filepath = '' self.output_folderpath = '' def __getScreenDimensions(self): screen = self.app.primaryScreen() size = screen.size() self.left = size.width() / 2 self.top = size.height() / 2 self.width = 0.4 * size.width() self.height = 0.4 * size.height() def readme_action_triggered(self): popup = QMessageBox() popup.setWindowTitle('Tutorial') popup.setText( "HOW TO USE THE SOFTWARE: \n" " 1) Click 'Input MRI...' to select from your file explorer the MRI scan to process (unique file).\n" " 1*) Alternatively, Click File > Import DICOM... if you wish to process an MRI scan as a DICOM sequence.\n" " 2) Click 'Output destination' to choose a directory where to save the results \n" " 3) (OPTIONAL) Click 'Input segmentation' to choose a tumor segmentation mask file, if nothing is provided the internal model with generate the segmentation automatically \n" " 4) Click 'Run diagnosis' to perform the analysis. The human-readable version will be displayed in the interface.\n" " \n" "NOTE: \n" "The output folder is populated automatically with the following: \n" " * The diagnosis results in human-readable text (report.txt) and Excel-ready format (report.csv).\n" " * The automatic segmentation masks of the brain and the tumor in the original patient space (input_brain_mask.nii.gz and input_tumor_mask.nii.gz).\n" " * The input volume and tumor segmentation mask in MNI space in the sub-directory named \'registration\'.\n" ) popup.exec_() def about_action_triggered(self): popup = QMessageBox() popup.setWindowTitle('About') popup.setText( 'Software developed as part of a collaboration between: \n' ' * Departement of Health Research, SINTEF\n' ' * St. Olavs hospital, Trondheim University Hospital\n' ' * Amsterdam University Medical Center\n\n' 'Contact: David Bouget, Andre Pedersen\n\n' 'For questions about the software, please visit:\n' 'https://github.com/SINTEFMedtek/GSI-RADS\n' 'For questions about the methodological aspect, please refer to the original publication:\n' 'https://www.mdpi.com/2072-6694/13/12/2854/review_report') popup.exec_() def quit_action_triggered(self): self.printer_thread.stop() sys.exit() def diagnose_main_wrapper(self): self.run_diagnosis_thread = threading.Thread(target=self.run_diagnosis) self.run_diagnosis_thread.daemon = True # using daemon thread the thread is killed gracefully if program is abruptly closed self.run_diagnosis_thread.start() def run_diagnosis(self): if not os.path.exists(self.input_image_filepath) or not os.path.exists( self.output_folderpath): self.standardOutputWritten( 'Process could not be started - The 1st and 2nd above-fields must be filled in.\n' ) return self.run_button.setEnabled(False) self.prompt_lineedit.clear() self.main_display_tabwidget.setCurrentIndex(1) QApplication.processEvents( ) # to immidiently update GUI after button is clicked self.seg_preprocessing_scheme = 'P1' if self.settings_seg_preproc_menu_p1_action.isChecked( ) else 'P2' try: start_time = time.time() print('Initialize - Begin (Step 0/6)') from diagnosis.main import diagnose_main print('Initialize - End (Step 0/6)') print('Step runtime: {} seconds.'.format( np.round(time.time() - start_time, 3)) + "\n") diagnose_main( input_volume_filename=self.input_image_filepath, input_segmentation_filename=self.input_annotation_filepath, output_folder=self.output_folderpath, preprocessing_scheme=self.seg_preprocessing_scheme) except Exception as e: print('{}'.format(traceback.format_exc())) self.run_button.setEnabled(True) self.standardOutputWritten( 'Process could not be completed - Issue arose.\n') QApplication.processEvents() return self.run_button.setEnabled(True) results_filepath = os.path.join( ResourcesConfiguration.getInstance().output_folder, 'report.txt') self.results_textedit.setPlainText(open(results_filepath, 'r').read()) self.main_display_tabwidget.setCurrentIndex(2) def run_select_input_image(self): input_image_filedialog = QFileDialog() self.input_image_filepath = input_image_filedialog.getOpenFileName( self, 'Select input T1 MRI', '~', "Image files (*.nii *.nii.gz *.nrrd *.mha *.mhd)")[0] self.input_image_lineedit.setText(self.input_image_filepath) def run_select_input_segmentation(self): filedialog = QFileDialog() self.input_annotation_filepath = filedialog.getOpenFileName( self, 'Select input segmentation file', '~', "Image files (*.nii *.nii.gz)")[0] self.input_segmentation_lineedit.setText( self.input_annotation_filepath) def import_dicom_action_triggered(self): filedialog = QFileDialog() filedialog.setFileMode(QFileDialog.DirectoryOnly) self.input_image_filepath = filedialog.getExistingDirectory( self, 'Select DICOM folder', '~') self.input_image_lineedit.setText(self.input_image_filepath) def run_select_output_folder(self): filedialog = QFileDialog() filedialog.setFileMode(QFileDialog.DirectoryOnly) self.output_folderpath = filedialog.getExistingDirectory( self, 'Select output folder', '~') self.output_folder_lineedit.setText(self.output_folderpath) def standardOutputWritten(self, text): self.prompt_lineedit.moveCursor(QTextCursor.End) self.prompt_lineedit.insertPlainText(text) QApplication.processEvents() def help_action_triggered(self): # opens browser with specified url, directs user to Issues section of GitHub repo QDesktopServices.openUrl( QUrl("https://github.com/SINTEFMedtek/GSI-RADS/issues")) def settings_seg_preproc_menu_p1_action_triggered(self, status): if status: self.settings_seg_preproc_menu_p2_action.setChecked(False) else: self.settings_seg_preproc_menu_p2_action.setChecked(True) def settings_seg_preproc_menu_p2_action_triggered(self, status): if status: self.settings_seg_preproc_menu_p1_action.setChecked(False) else: self.settings_seg_preproc_menu_p1_action.setChecked(True)
class VOGTab(QWidget): """ This code is for helping the user interact with the configurations of the VOG device. """ def __init__(self, device, ch): self.logger = logging.getLogger(__name__) self.logger.addHandler(ch) self.logger.debug("Initializing") try: super().__init__() except Exception as e: self.logger.exception( "Error making VOGTab, passed parent is invalid") return self.setLayout(QVBoxLayout(self)) self.setGeometry(QRect(0, 0, 200, 500)) self.setMaximumHeight(500) self.layout().addWidget(EasyFrame(line=True)) """ Set configuration value display area""" self.__config_frame = EasyFrame() self.__config_horiz_layout = QHBoxLayout(self.__config_frame) self.__config_label = QLabel(self.__config_frame) self.__config_label.setAlignment(Qt.AlignCenter) self.__config_horiz_layout.addWidget(self.__config_label) self.__config_val_line_edit = QLineEdit(self.__config_frame) self.__config_val_line_edit.setAlignment(Qt.AlignCenter) self.__config_horiz_layout.addWidget(self.__config_val_line_edit) self.layout().addWidget(self.__config_frame) self.layout().addWidget(EasyFrame(line=True)) """ Set preset button selection area. """ self.__presets_frame = EasyFrame() self.__presets_vert_layout = QVBoxLayout(self.__presets_frame) self.__nhtsa_button = ClickAnimationButton(self.__presets_frame) self.__presets_vert_layout.addWidget(self.__nhtsa_button) self.__eblindfold_button = ClickAnimationButton(self.__presets_frame) self.__presets_vert_layout.addWidget(self.__eblindfold_button) self.__direct_control_button = ClickAnimationButton( self.__presets_frame) self.__presets_vert_layout.addWidget(self.__direct_control_button) self.layout().addWidget(self.__presets_frame) self.layout().addWidget(EasyFrame(line=True)) """ Set open duration, close duration, and debounce time settings display area. """ self.__input_box_frame = EasyFrame() self.__input_box_grid_layout = QGridLayout(self.__input_box_frame) self.__input_box_grid_layout.setContentsMargins(0, 6, 0, 6) self.__open_dur_label = QLabel(self.__input_box_frame) self.__input_box_grid_layout.addWidget(self.__open_dur_label, 0, 0, 1, 1) self.__open_dur_line_edit = QLineEdit(self.__input_box_frame) self.__open_dur_line_edit.setFixedWidth(80) self.__input_box_grid_layout.addWidget(self.__open_dur_line_edit, 0, 1, 1, 1) self.__open_inf_check_box = QCheckBox(self.__input_box_frame) self.__input_box_grid_layout.addWidget(self.__open_inf_check_box, 0, 2, 1, 1) self.__close_dur_label = QLabel(self.__input_box_frame) self.__input_box_grid_layout.addWidget(self.__close_dur_label, 1, 0, 1, 1) self.__close_dur_line_edit = QLineEdit(self.__input_box_frame) self.__close_dur_line_edit.setFixedWidth(80) self.__input_box_grid_layout.addWidget(self.__close_dur_line_edit, 1, 1, 1, 1) self.__close_inf_check_box = QCheckBox(self.__input_box_frame) self.__input_box_grid_layout.addWidget(self.__close_inf_check_box, 1, 2, 1, 1) self.__debounce_label = QLabel(self.__input_box_frame) self.__input_box_grid_layout.addWidget(self.__debounce_label, 2, 0, 1, 1) self.__debounce_time_line_edit = QLineEdit(self.__input_box_frame) self.__debounce_time_line_edit.setFixedWidth(80) self.__input_box_grid_layout.addWidget(self.__debounce_time_line_edit, 2, 1, 1, 1) self.layout().addWidget(self.__input_box_frame) self.layout().addWidget(EasyFrame(line=True)) """ Set button mode setting display area. """ self.__button_mode_frame = EasyFrame() self.__button_mode_horiz_layout = QHBoxLayout(self.__button_mode_frame) self.__button_mode_label = QLabel(self.__button_mode_frame) self.__button_mode_horiz_layout.addWidget(self.__button_mode_label) self.__button_mode_selector = QComboBox(self.__button_mode_frame) self.__button_mode_selector.addItem("") self.__button_mode_selector.addItem("") self.__button_mode_horiz_layout.addWidget(self.__button_mode_selector) self.layout().addWidget(self.__button_mode_frame) self.layout().addWidget(EasyFrame(line=True)) """ Set upload button selection area. """ self.__upload_settings_button = ClickAnimationButton() self.layout().addWidget(self.__upload_settings_button) self.layout().addWidget(EasyFrame(line=True)) """ Set manual control selection area. """ self.__manual_control_button = ClickAnimationButton() self.layout().addWidget(self.__manual_control_button) self.layout().addWidget(EasyFrame(line=True)) self.__graph_buttons = [] self.device_info = device self.__index = 0 self.__set_texts() self.__set_tooltips() self.logger.debug("Initialized") def add_manual_control_handler(self, func): self.logger.debug("running") self.__manual_control_button.clicked.connect(func) self.logger.debug("done") def add_nhtsa_button_handler(self, func): self.logger.debug("running") self.__nhtsa_button.clicked.connect(func) self.logger.debug("done") def add_eblind_button_handler(self, func): self.logger.debug("running") self.__eblindfold_button.clicked.connect(func) self.logger.debug("done") def add_direct_control_button_handler(self, func): self.logger.debug("running") self.__direct_control_button.clicked.connect(func) self.logger.debug("done") def add_upload_button_handler(self, func): self.logger.debug("running") self.__upload_settings_button.clicked.connect(func) self.logger.debug("done") def add_open_inf_handler(self, func): self.logger.debug("running") self.__open_inf_check_box.toggled.connect(func) self.logger.debug("done") def add_close_inf_handler(self, func): self.logger.debug("running") self.__close_inf_check_box.toggled.connect(func) self.logger.debug("done") def add_open_entry_changed_handler(self, func): self.logger.debug("running") self.__open_dur_line_edit.textChanged.connect(func) self.logger.debug("done") def add_close_entry_changed_handler(self, func): self.logger.debug("running") self.__close_dur_line_edit.textChanged.connect(func) self.logger.debug("done") def add_debounce_entry_changed_handler(self, func): self.logger.debug("running") self.__debounce_time_line_edit.textChanged.connect(func) self.logger.debug("done") def add_button_mode_entry_changed_handler(self, func): self.logger.debug("running") self.__button_mode_selector.currentIndexChanged.connect(func) self.logger.debug("done") def add_config_val_changed_handler(self, func): self.logger.debug("running") self.__config_val_line_edit.textChanged.connect(func) self.logger.debug("done") def set_upload_button_activity(self, is_active): """ Set upload button to enabled or disabled depending on is_active bool. """ self.logger.debug("running") self.__upload_settings_button.setEnabled(is_active) self.logger.debug("done") def set_config_value(self, value): """ Set display value of config.txt. """ self.logger.debug("running") self.__config_val_line_edit.setText(value) self.logger.debug("done") def get_config_value(self): return self.__config_val_line_edit.text() def get_open_val(self): return self.__open_dur_line_edit.text() def set_open_val(self, val): """ Set display value of open duration. """ self.logger.debug("running") self.__open_dur_line_edit.setText(str(val)) self.logger.debug("done") def set_open_val_error(self, is_error): """ Set display of error in open duration line edit. """ self.logger.debug("running") if is_error: self.__open_dur_line_edit.setStyleSheet(tab_line_edit_error_style) else: self.__open_dur_line_edit.setStyleSheet( tab_line_edit_compliant_style) self.logger.debug("done") def set_close_val_error(self, is_error): """ Set display of error in close duration line edit. """ self.logger.debug("running") if is_error: self.__close_dur_line_edit.setStyleSheet(tab_line_edit_error_style) else: self.__close_dur_line_edit.setStyleSheet( tab_line_edit_compliant_style) self.logger.debug("done") def set_debounce_val_error(self, is_error): """ Set display of error in debounce line edit. """ self.logger.debug("running") if is_error: self.__debounce_time_line_edit.setStyleSheet( tab_line_edit_error_style) else: self.__debounce_time_line_edit.setStyleSheet( tab_line_edit_compliant_style) self.logger.debug("done") def set_open_val_entry_activity(self, is_active): """ Set open value line edit to enabled or disabled depending on is_active bool. """ self.logger.debug("running") self.__open_dur_line_edit.setEnabled(is_active) self.logger.debug("done") def get_open_inf(self): return self.__open_inf_check_box.isChecked() def set_open_inf(self, is_checked): """ Set open infinity checkbox state to is_checked. """ self.logger.debug("running") self.__open_inf_check_box.setChecked(is_checked) self.logger.debug("done") def get_close_val(self): return self.__close_dur_line_edit.text() def set_close_val(self, val): """ Set display value of close duration. """ self.logger.debug("running") self.__close_dur_line_edit.setText(str(val)) self.logger.debug("done") def set_close_val_entry_activity(self, is_active): """ Set close value line edit to enabled or disabled depending on is_active bool. """ self.logger.debug("running") self.__close_dur_line_edit.setEnabled(is_active) self.logger.debug("done") def get_close_inf(self): return self.__close_inf_check_box.isChecked() def set_close_inf(self, is_checked): """ Set close infinity checkbox state to is_checked. """ self.logger.debug("running") self.__close_inf_check_box.setChecked(is_checked) self.logger.debug("done") def get_debounce_val(self): return self.__debounce_time_line_edit.text() def set_debounce_val(self, val): """ Set debounce display value. """ self.logger.debug("running") self.__debounce_time_line_edit.setText(str(val)) self.logger.debug("done") def get_button_mode(self): return self.__button_mode_selector.currentIndex() def set_button_mode(self, val): """ Set display value of button mode. """ self.logger.debug("running") self.__button_mode_selector.setCurrentIndex(int(val)) self.logger.debug("done") def get_name(self): return self.device_info def __set_texts(self): self.logger.debug("running") self.__config_label.setText("Current configuration:") self.__config_val_line_edit.setText("DIRECT CONTROL") self.__nhtsa_button.setText("NHTSA") self.__eblindfold_button.setText("eBlindfold") self.__direct_control_button.setText("Direct Control") self.__open_dur_label.setText("Open Duration") self.__open_inf_check_box.setText("INF") self.__close_dur_label.setText("Close Duration") self.__close_inf_check_box.setText("INF") self.__debounce_label.setText("Debounce Time") self.__button_mode_label.setText("Button Mode") self.__button_mode_selector.setItemText(0, "Hold") self.__button_mode_selector.setItemText(1, "Click") self.__upload_settings_button.setText("Upload settings") self.__manual_control_button.setText("Toggle Lens") self.logger.debug("done") def __set_tooltips(self): self.logger.debug("running") self.__config_label.setToolTip("Current device configuration") self.__config_val_line_edit.setToolTip("Enter custom config name here") self.__config_val_line_edit.setPlaceholderText("Custom config name") self.__nhtsa_button.setToolTip("Set Device to NHTSA standard") self.__eblindfold_button.setToolTip("Set Device to eBlindfold mode") self.__direct_control_button.setToolTip( "Set Device to Direct Control mode") self.__button_mode_label.setToolTip("CHANGEME") self.__open_dur_label.setToolTip("Range: " + str(vog_min_open_close) + "-" + str(vog_max_open_close)) self.__close_dur_label.setToolTip("Range: " + str(vog_min_open_close) + "-" + str(vog_max_open_close)) self.__debounce_label.setToolTip("Range: " + str(vog_debounce_min) + "-" + str(vog_debounce_max)) self.__open_inf_check_box.setToolTip("Set to manual switching") self.__close_inf_check_box.setToolTip("Set to manual switching") self.__upload_settings_button.setToolTip( "Upload current configuration to device") self.__manual_control_button.setToolTip( "Manually open or close the lens") self.logger.debug("done")
class FormAndMenuWindow(QMainWindow): """ This class creates a form to edit a dictionary. It nests tabs for different levels of the nesting within the dictionaries. This automatically builds an interface from the dictionary. """ def __init__(self, parent=None): """ Parameters ---------- dict_to_edit: Dict[str, Any] The dictionary to edit in this form. output_filename: str The filename to write the dictionary when the save button is clicked. parent The parent as needed by the base class. """ super(FormAndMenuWindow, self).__init__(parent) self.analysis_yaml_editor_widget = None self.modeling_yaml_widget = None self.geometry_yaml_widget = None self.geometry_filename_line_edit = None self.modeling_filename_line_edit = None self.analysis_filename_line_edit = None self.geometry_dict = None self.analysis_dict = None self.modeling_dict = None self.geometry_filename = None self.analysis_filename = None self.modeling_filename = None self.main_widget = None self.status_widget = None self.status_label = None def setup(self) -> None: """ After this class is instantiated, this method should be called to lay out the user interface. """ self.setWindowTitle("YAML GUI") # self.setup_menu_bar() central_widget = self.create_central_widget() self.setCentralWidget(central_widget) def recursion_ui_setup(self, dict_or_list: Union[List[Any], Dict[str, Any]]) -> QFormLayout: """ This recursive method is where the automatic layout magic happens. This method calls itself recursively as it descends down the dictionary nesting structure. Basically, any given dictionary can consist of scalar and dictionary values. At each level of the dictionary, edit fields are placed for scalar values and tabbed widgets are placed for the next level of nesting. Parameters ---------- dict_or_list: Dict[str, Any] The dictionary to automatically lay out in to the interface. """ form_level_layout = QFormLayout() dict_tabs = QTabWidget() display_tabs = False subscripts_values = dict_or_list.items() if type(dict_or_list) is dict else enumerate(dict_or_list) # type: ignore for k, v in subscripts_values: # Recursive call for nested dictionaries within dictionaries. if type(v) is dict: display_tabs = True child_widget = QWidget() child_layout = self.recursion_ui_setup(v) child_widget.setLayout(child_layout) dict_tabs.addTab(child_widget, str(k)) # Recursive call for nested dictionaries within lists. elif type(v) is list and type(v[0]) is dict: display_tabs = True child_widget = QWidget() child_layout = self.recursion_ui_setup(v) child_widget.setLayout(child_layout) dict_tabs.addTab(child_widget, str(k)) # Otherwise just lay out a label and text field. else: line_edit = FocusQLineEdit(str(v)) line_edit.setMinimumWidth(150) line_edit.set_dictionary_and_key(dict_or_list, k) form_level_layout.addRow(QLabel(k), line_edit) # If there is a nested dictionary, display it. if display_tabs: form_level_layout.addRow(dict_tabs) # Return the whole layout return form_level_layout def write_dict_to_yaml(self) -> None: """ This is the event handler for the save button. It simply writes the dictionary (which has been continuously updated during focus out events) to a YAML file as specified in self.output_filename. """ with open(self.output_filename, "w") as file: yaml.dump(self.dict_to_edit, file) def create_central_widget(self) -> QWidget: """ Returns ------- QWidget The form with buttons on it. """ status_and_main_widget = QWidget() status_and_main_widget_layout = QVBoxLayout() self.status_widget = QWidget() status_form_layout = QFormLayout() status_label = QLabel("Status:") self.status_label = QLabel() self.status_label.setText("Please create simulation configurations.") status_form_layout.addRow(status_label, self.status_label) self.status_widget.setLayout(status_form_layout) self.main_widget = QWidget() subsection_width = 500 subsection_height = 900 geometry_section_label = QLabel("Geometry") geometry_section_label.setStyleSheet("font-weight: bold;") geometry_filename_button = QPushButton("Select geometry YAML...") # geometry_visualize_button = QPushButton("Visualize geometry") self.geometry_filename_line_edit = QLineEdit() self.geometry_filename_line_edit.setPlaceholderText("Please select a geometry file.") self.geometry_filename_line_edit.setFixedWidth(200) self.geometry_filename_line_edit.setReadOnly(True) geometry_filename_button.clicked.connect(self.file_picker_geometry) modeling_section_label = QLabel("Modeling") modeling_section_label.setStyleSheet("font-weight: bold;") modeling_filename_button = QPushButton("Select modeling YAML...") self.modeling_filename_line_edit = QLineEdit() self.modeling_filename_line_edit.setPlaceholderText("Please select a modeling file.") self.modeling_filename_line_edit.setFixedWidth(200) self.modeling_filename_line_edit.setReadOnly(True) modeling_filename_button.clicked.connect(self.file_picker_modeling) analysis_section_label = QLabel("Analysis") analysis_section_label.setStyleSheet("font-weight: bold;") analysis_filename_button = QPushButton("Select analysis YAML...") self.analysis_filename_line_edit = QLineEdit() self.analysis_filename_line_edit.setPlaceholderText("Please select an analysis file...") self.analysis_filename_line_edit.setFixedWidth(200) self.analysis_filename_line_edit.setReadOnly(True) analysis_filename_button.clicked.connect(self.file_picker_analysis) run_weis_button = QPushButton("Run WISDEM") run_weis_button.clicked.connect(self.run_weis_clicked) self.modeling_yaml_widget = QWidget() self.analysis_yaml_editor_widget = QWidget() self.geometry_yaml_widget = QWidget() geometry_layout = QFormLayout() geometry_layout.addRow(geometry_section_label) geometry_layout.addRow(self.geometry_filename_line_edit, geometry_filename_button) # geometry_layout.addRow(geometry_visualize_button) geometry_layout.addRow(self.geometry_yaml_widget) geometry_widget = QWidget() geometry_widget.setFixedWidth(subsection_width) geometry_widget.setFixedHeight(subsection_height) geometry_widget.setLayout(geometry_layout) modeling_layout = QFormLayout() modeling_layout.addRow(modeling_section_label) modeling_layout.addRow(self.modeling_filename_line_edit, modeling_filename_button) modeling_layout.addRow(self.modeling_yaml_widget) modeling_widget = QWidget() modeling_widget.setFixedWidth(subsection_width) modeling_widget.setFixedHeight(subsection_height) modeling_widget.setLayout(modeling_layout) analysis_layout = QFormLayout() analysis_layout.addRow(analysis_section_label) analysis_layout.addRow(self.analysis_filename_line_edit, analysis_filename_button) analysis_layout.addRow(self.analysis_yaml_editor_widget) analysis_widget = QWidget() analysis_widget.setFixedWidth(subsection_width) analysis_widget.setFixedHeight(subsection_height) analysis_widget.setLayout(analysis_layout) main_layout = QHBoxLayout() main_layout.addWidget(geometry_widget) main_layout.addWidget(modeling_widget) main_layout.addWidget(analysis_widget) main_layout.addWidget(run_weis_button) self.main_widget.setLayout(main_layout) # return self.main_widget status_and_main_widget_layout.addWidget(self.status_widget) status_and_main_widget_layout.addWidget(self.main_widget) status_and_main_widget.setLayout(status_and_main_widget_layout) return status_and_main_widget def run_weis_clicked(self): """ When the "Run WEIS" button is clicked, a popup dialog will pop up asking what the user wants to do. If the user has skipped any configuration files, then it will tell them to go back and create those configuration files. If the user has specified all the configuration files, then it will prompt the user for confirmation before saving the WEIS configuration files. """ if self.geometry_filename is None: msg = QMessageBox() msg.setText("Run WISDEM: Missing file") msg.setInformativeText("You did not specify a geometry file.") msg.addButton(QMessageBox.Cancel) msg.exec() elif self.modeling_filename is None: msg = QMessageBox() msg.setText("Run WISDEM: Missing file") msg.setInformativeText("You did not specify a modeling file.") msg.addButton(QMessageBox.Cancel) msg.exec() elif self.analysis_filename is None: msg = QMessageBox() msg.setText("Run WISDEM: Missing file") msg.setInformativeText("You did not specify an analysis file.") msg.addButton(QMessageBox.Cancel) msg.exec() else: self.status_label.setText("Writing files...") self.write_configuration_files() self.status_label.setText("Configuration files written.") msg = QMessageBox() msg.setText("Run WISDEM: Configuration files complete!") msg.setInformativeText("Click cancel to back out and continue editing. Click OK to run WISDEM.") msg.addButton(QMessageBox.Cancel) msg.addButton(QMessageBox.Ok) choice = msg.exec() if choice == QMessageBox.Ok: self.disable_ui_and_execute_wisdem() def write_configuration_files(self): """ The "Run WEIS" click event handler calls this method when it is ready to make an attempt to run WEIS. It checks to see if all file shave been edited """ if self.geometry_filename is not None: print(f"Writing geometry: {self.geometry_filename}") with open(self.geometry_filename, "w") as file: yaml.dump(self.geometry_dict, file) else: print("No geometry file to write") if self.analysis_filename is not None: print(f"Writing analysis: {self.analysis_filename}") with open(self.analysis_filename, "w") as file: yaml.dump(self.analysis_dict, file) else: print("No analysis file to write") if self.modeling_filename is not None: print(f"Writing modeling: {self.modeling_filename}") with open(self.modeling_filename, "w") as file: yaml.dump(self.modeling_dict, file) else: print("No modeling file to write") def disable_ui_and_execute_wisdem(self): """ This method disables all widgets on the UI and executes WISDEM. It displays message boxes depending on whether WISDEM executed successfully. """ self.main_widget.setEnabled(False) self.status_label.setText("Running WISDEM") try: wt_opt, modeling_options, analysis_options = run_wisdem( self.geometry_filename, self.modeling_filename, self.analysis_filename ) except Exception as err: short_error_message = f"{type(err)}: {err}. More details on command line." traceback.print_exc(file=sys.stdout) self.status_label.setText("Execution error") msg = QMessageBox() msg.setText("WISDEM execution error") msg.setInformativeText(short_error_message) msg.addButton(QMessageBox.Ok) msg.exec() self.main_widget.setEnabled(True) else: self.status_label.setText("Execution success") msg = QMessageBox() msg.setText("WISDEM executed successfully") msg.addButton(QMessageBox.Ok) msg.exec() self.main_widget.setEnabled(True) def file_picker_geometry(self): """ Shows the open file dialog for the geometry file. Returns ------- None Returns nothing for now. """ dialog = QFileDialog(self) dialog.setFileMode(QFileDialog.ExistingFile) dialog.setViewMode(QFileDialog.Detail) self.geometry_filename, _ = dialog.getOpenFileName(None, "Open File", str(Path.home()), "YAML (*.yml *.yaml)") self.geometry_filename_line_edit.setText(self.geometry_filename) self.geometry_dict = self.read_yaml_to_dictionary(self.geometry_filename) layout = self.recursion_ui_setup(self.geometry_dict) self.geometry_yaml_widget.setLayout(layout) def file_picker_modeling(self): """ Shows the open dialog Returns ------- None Returns nothing for now. """ dialog = QFileDialog(self) dialog.setFileMode(QFileDialog.ExistingFile) dialog.setViewMode(QFileDialog.Detail) self.modeling_filename, _ = dialog.getOpenFileName(None, "Open File", str(Path.home()), "YAML (*.yml *.yaml)") self.modeling_filename_line_edit.setText(self.modeling_filename) self.modeling_dict = self.read_yaml_to_dictionary(self.modeling_filename) layout = self.recursion_ui_setup(self.modeling_dict) self.modeling_yaml_widget.setLayout(layout) def file_picker_analysis(self) -> None: """ Shows the open dialog for the analysis YAML Returns ------- None """ dialog = QFileDialog(self) dialog.setFileMode(QFileDialog.ExistingFile) dialog.setViewMode(QFileDialog.Detail) self.analysis_filename, _ = dialog.getOpenFileName(None, "Open File", str(Path.home()), "YAML (*.yml *.yaml)") self.analysis_filename_line_edit.setText(self.analysis_filename) self.analysis_dict = self.read_yaml_to_dictionary(self.analysis_filename) layout = self.recursion_ui_setup(self.analysis_dict) self.analysis_yaml_editor_widget.setLayout(layout) @staticmethod def read_yaml_to_dictionary(input_filename: str) -> Dict[str, Any]: """ This reads the YAML input which is used to build the user interface. """ with open(input_filename) as file: result = yaml.load(file, Loader=yaml.FullLoader) return result
class ParameterInteger(QWidget): def check_int(self, s): if s[0] in ("-", "+"): return s[1:].isdigit() return s.isdigit() def clamp(self, value, min_value, max_value): if value < min_value: return min_value elif value > max_value: return max_value else: return value def __init__(self, parent=None, value=0, name="", label_text="", min_value=None, max_value=None, label_width=64, height=22, min_visible=0, max_visible=10, change_callback=None): QWidget.__init__(self, parent) self.VERTICAL_MARGIN = 0 self.HORIZONTAL_MARGIN = 0 self.name = name self.label_text = label_text self.min_value_raw = min_value self.max_value_raw = max_value self.min_value = min_value if min_value is not None else -sys.maxsize self.max_value = max_value if max_value is not None else sys.maxsize self.value = self.clamp(value, self.min_value, self.max_value) self.min_visible = max(self.min_value, min(min_visible, self.value)) self.max_visible = min(self.max_value, max(max_visible, self.value)) self._is_callback_define = False if change_callback is not None: self._change_callback = change_callback self._is_callback_define = True self._last_call = None self.label = QLabel(label_text) self.label.setFixedWidth(label_width) self.label.setFixedHeight(height) self.value_textbox = QLineEdit() self.value_textbox.setFixedWidth(52) self.value_textbox.setFixedHeight(height) self._update_value_label() self.slider = QSlider(Qt.Horizontal) self.slider.setFixedHeight(height) self._update_visible_interval() self.slider.setValue(value) layout = QHBoxLayout() layout.setContentsMargins(self.HORIZONTAL_MARGIN, self.VERTICAL_MARGIN, self.HORIZONTAL_MARGIN, self.VERTICAL_MARGIN) layout.addWidget(self.label) layout.addWidget(self.value_textbox) layout.addWidget(self.slider) self.setLayout(layout) self.slider.valueChanged.connect(self.slider_valueChanged) self.value_textbox.returnPressed.connect(self.textbox_enter) self.value_textbox.editingFinished.connect(self.textbox_enter) self.slider.sliderReleased.connect(self.slider_sliderReleased) def _update_visible_interval(self): self.slider.setRange(self.min_visible, self.max_visible) def _update_value_label(self): self.value_textbox.setText(str(self.value)) def slider_valueChanged(self, value): self.value = value self._update_value_label() self.value_change() def slider_sliderReleased(self): self.try_change_visible(self.value) self.slider.setValue(self.value) def try_change_visible(self, new_value): delta = self.max_visible - self.min_visible # increase visible interval if new value out of the current if new_value <= self.min_visible: self.min_visible = max(self.min_value, new_value - delta) if new_value >= self.max_visible: self.max_visible = min(self.max_value, new_value + delta) self._update_visible_interval() def textbox_enter(self): text = self.value_textbox.text() # check is this text is integer if self.check_int(text): new_value = int(text) # clamp value if new_value < self.min_value: new_value = self.min_value if new_value > self.max_value: new_value = self.max_value self.try_change_visible(new_value) self.slider.setValue(new_value) self._update_value_label() self.value_change() else: self._update_value_label() self.value_textbox.clearFocus() def value_change(self): if self._is_callback_define: if self._last_call is None or self._last_call != self.value: self._last_call = self.value self._change_callback(param_name=self.name, param_value=self.value)
class MonteCarloTab(NewAnalysisTab): def __init__(self, parent=None): super(MonteCarloTab, self).__init__(parent) self.parent: LCAResultsSubTab = parent self.layout.addLayout(get_header_layout('Monte Carlo Simulation')) self.scenario_label = QLabel("Scenario:") self.include_box = QGroupBox("Include uncertainty for:", self) grid = QGridLayout() self.include_tech = QCheckBox("Technosphere", self) self.include_tech.setChecked(True) self.include_bio = QCheckBox("Biosphere", self) self.include_bio.setChecked(True) self.include_cf = QCheckBox("Characterization Factors", self) self.include_cf.setChecked(True) self.include_parameters = QCheckBox("Parameters", self) self.include_parameters.setChecked(True) grid.addWidget(self.include_tech, 0, 0) grid.addWidget(self.include_bio, 0, 1) grid.addWidget(self.include_cf, 1, 0) grid.addWidget(self.include_parameters, 1, 1) self.include_box.setLayout(grid) self.add_MC_ui_elements() self.table = LCAResultsTable() self.table.table_name = 'MonteCarlo_' + self.parent.cs_name self.plot = MonteCarloPlot(self.parent) self.plot.hide() self.plot.plot_name = 'MonteCarlo_' + self.parent.cs_name self.layout.addWidget(self.plot) self.export_widget = self.build_export(has_plot=True, has_table=True) self.layout.addWidget(self.export_widget) self.layout.setAlignment(QtCore.Qt.AlignTop) self.connect_signals() def connect_signals(self): self.button_run.clicked.connect(self.calculate_mc_lca) # signals.monte_carlo_ready.connect(self.update_mc) # self.combobox_fu.currentIndexChanged.connect(self.update_plot) self.combobox_methods.currentIndexChanged.connect( # ignore the index and send the cs_name instead lambda x: self.update_mc(cs_name=self.parent.cs_name)) # signals # self.radio_button_biosphere.clicked.connect(self.button_clicked) # self.radio_button_technosphere.clicked.connect(self.button_clicked) if self.using_presamples: self.scenario_box.currentIndexChanged.connect( self.parent.update_scenario_data) self.parent.update_scenario_box_index.connect( lambda index: self.set_combobox_index(self.scenario_box, index )) def add_MC_ui_elements(self): layout_mc = QVBoxLayout() # H-LAYOUT start simulation self.button_run = QPushButton('Run Simulation') self.label_iterations = QLabel('Iterations:') self.iterations = QLineEdit('10') self.iterations.setFixedWidth(40) self.iterations.setValidator(QtGui.QIntValidator(1, 1000)) self.label_seed = QLabel('Random seed:') self.label_seed.setToolTip( 'Seed value (integer) for the random number generator. ' 'Use this for reproducible samples.') self.seed = QLineEdit('') self.seed.setFixedWidth(30) self.hlayout_run = QHBoxLayout() self.hlayout_run.addWidget(self.scenario_label) self.hlayout_run.addWidget(self.scenario_box) self.hlayout_run.addWidget(self.button_run) self.hlayout_run.addWidget(self.label_iterations) self.hlayout_run.addWidget(self.iterations) self.hlayout_run.addWidget(self.label_seed) self.hlayout_run.addWidget(self.seed) self.hlayout_run.addWidget(self.include_box) self.hlayout_run.addStretch(1) layout_mc.addLayout(self.hlayout_run) # self.label_running = QLabel('Running a Monte Carlo simulation. Please allow some time for this. ' # 'Please do not run another simulation at the same time.') # self.layout_mc.addWidget(self.label_running) # self.label_running.hide() # # buttons for all FUs or for all methods # self.radio_button_all_fu = QRadioButton("For all functional units") # self.radio_button_all_methods = QRadioButton("Technosphere flows") # # self.radio_button_biosphere.setChecked(True) # self.radio_button_technosphere.setChecked(False) # # self.label_for_all_fu = QLabel('For all functional units') # self.combobox_fu = QRadioButton() # self.hlayout_fu = QHBoxLayout() # FU selection # self.label_fu = QLabel('Choose functional unit') # self.combobox_fu = QComboBox() # self.hlayout_fu = QHBoxLayout() # # self.hlayout_fu.addWidget(self.label_fu) # self.hlayout_fu.addWidget(self.combobox_fu) # self.hlayout_fu.addStretch() # self.layout_mc.addLayout(self.hlayout_fu) # method selection self.method_selection_widget = QWidget() self.label_methods = QLabel('Choose LCIA method') self.combobox_methods = QComboBox() self.hlayout_methods = QHBoxLayout() self.hlayout_methods.addWidget(self.label_methods) self.hlayout_methods.addWidget(self.combobox_methods) self.hlayout_methods.addStretch() self.method_selection_widget.setLayout(self.hlayout_methods) layout_mc.addWidget(self.method_selection_widget) self.method_selection_widget.hide() self.layout.addLayout(layout_mc) def build_export(self, has_table: bool = True, has_plot: bool = True) -> QWidget: """Construct the export layout but set it into a widget because we want to hide it.""" export_layout = super().build_export(has_table, has_plot) export_widget = QWidget() export_widget.setLayout(export_layout) # Hide widget until MC is calculated export_widget.hide() return export_widget @QtCore.Slot(name="calculateMcLca") def calculate_mc_lca(self): self.method_selection_widget.hide() self.plot.hide() self.export_widget.hide() iterations = int(self.iterations.text()) seed = None if self.seed.text(): print('SEED: ', self.seed.text()) try: seed = int(self.seed.text()) except ValueError: traceback.print_exc() QMessageBox.warning( self, 'Warning', 'Seed value must be an integer number or left empty.') self.seed.setText('') return includes = { "technosphere": self.include_tech.isChecked(), "biosphere": self.include_bio.isChecked(), "cf": self.include_cf.isChecked(), "parameters": self.include_parameters.isChecked(), } try: self.parent.mc.calculate(iterations=iterations, seed=seed, **includes) self.update_mc() except InvalidParamsError as e: # This can occur if uncertainty data is missing or otherwise broken # print(e) traceback.print_exc() QMessageBox.warning(self, 'Could not perform Monte Carlo simulation', str(e)) # a threaded way for this - unfortunatley this crashes as: # pypardsio_solver is used for the 'spsolve' and 'factorized' functions. Python crashes on windows if multiple # instances of PyPardisoSolver make calls to the Pardiso library # worker_thread = WorkerThread() # print('Created local worker_thread') # worker_thread.set_mc(self.parent.mc, iterations=iterations) # print('Passed object to thread.') # worker_thread.start() # self.label_running.show() # # thread = NewCSMCThread() #self.parent.mc # thread.calculation_finished.connect( # lambda x: print('Calculation finished.')) # thread.start() # # give us a thread and start it # thread = QtCore.QThread() # thread.start() # # # create a worker and move it to our extra thread # worker = Worker() # worker.moveToThread(thread) # self.parent.mct.start() # self.parent.mct.run(iterations=iterations) # self.parent.mct.finished() # objThread = QtCore.QThread() # obj = QObjectMC() # self.parent.cs_name # obj.moveToThread(objThread) # obj.finished.connect(objThread.quit) # objThread.started.connect(obj.long_running) # # objThread.finished.connect(app.exit) # objThread.finished.connect( # lambda x: print('Finished Thread!') # ) # objThread.start() # objThread = QtCore.QThread() # obj = SomeObject() # obj.moveToThread(objThread) # obj.finished.connect(objThread.quit) # objThread.started.connect(obj.long_running) # objThread.finished.connect( # lambda x: print('Finished Thread!') # ) # objThread.start() # self.method_selection_widget.show() # self.plot.show() # self.export_widget.show() def configure_scenario(self): super().configure_scenario() self.scenario_label.setVisible(self.using_presamples) def update_tab(self): self.update_combobox(self.combobox_methods, [str(m) for m in self.parent.mc.methods]) # self.update_combobox(self.combobox_methods, [str(m) for m in self.parent.mct.mc.methods]) def update_mc(self, cs_name=None): # act = self.combobox_fu.currentText() # activity_index = self.combobox_fu.currentIndex() # act_key = self.parent.mc.activity_keys[activity_index] # if cs_name != self.parent.cs_name: # relevant if several CS are open at the same time # return # self.label_running.hide() self.method_selection_widget.show() self.export_widget.show() method_index = self.combobox_methods.currentIndex() method = self.parent.mc.methods[method_index] # data = self.parent.mc.get_results_by(act_key=act_key, method=method) self.df = self.parent.mc.get_results_dataframe(method=method) self.update_table() self.update_plot(method=method) filename = '_'.join([ str(x) for x in [self.parent.cs_name, 'Monte Carlo results', str(method)] ]) self.plot.plot_name, self.table.table_name = filename, filename def update_plot(self, method): idx = self.layout.indexOf(self.plot) self.plot.figure.clf() self.plot.deleteLater() self.plot = MonteCarloPlot(self.parent) self.layout.insertWidget(idx, self.plot) self.plot.plot(self.df, method=method) self.plot.show() if self.layout.parentWidget(): self.layout.parentWidget().updateGeometry() def update_table(self): self.table.sync(self.df)
class MyWidget(QWidget): def __init__(self, parent=None): QWidget.__init__(self, parent) self.thread = SerialMonitorThread() self.thread.dataReady.connect(self.get_data, Qt.QueuedConnection) self.thread.setTerminationEnabled(True) #Menu self.setPalette(get_verifone_color()) collapsible = CollapsibleWidget() self.init_logging(collapsible) self.init_download(collapsible) self.init_analyser(collapsible) collapsible.add_sections() # Scroll Area self.createLoggingDisplayLabel() self.scrollArea = QScrollArea() self.scrollArea.setBackgroundRole(QPalette.Dark) self.scrollArea.setWidget(self.text) self.scrollArea.setWidgetResizable(True) hLayout = QHBoxLayout() #hLayout.addLayout(vLayout) hLayout.addWidget(collapsible) hLayout.addWidget(self.scrollArea) self.setLayout(hLayout) def init_logging(self, collapsible): self.logger = QPushButton("Start Logging", self) self.logger.setFont(QFont("Times", 14, QFont.Bold)) self.logger.clicked.connect(lambda: self.display_log_data()) self.logger.setStyleSheet("background-color: white") #self.filterLayout = QtWidgets.QHBoxLayout() self.logFilterLabel = QLabel('Filter', self) self.logFilterLabel.setFont(QFont("Times", 14, QFont.Bold)) self.logFilterLabel.setPalette(get_white_color_text()) self.logFilterLabel.setFixedWidth(60) self.logFilter = QLineEdit(self) self.logFilter.setPalette(get_white_color()) self.logFilter.setStyleSheet("background-color: white") self.logFilter.setFixedWidth(200) #self.filterLayout.addWidget(self.logFilterLabel, QtCore.Qt.AlignLeft) #self.filterLayout.addWidget(self.logFilter, QtCore.Qt.AlignLeft) self.serialList = QComboBox() ports = get_available_serial_ports() if (len(ports) == 1): self.serialList.addItem(ports[0]) self.thread.set_comport(self.serialList.currentText()) else: self.serialList.addItem("Select") for port in ports: self.serialList.addItem(port) self.serialList.currentIndexChanged.connect( lambda: self.set_serial_port()) self.serialList.setStyleSheet("background-color: white") self.clear = QPushButton("Clear Log File", self) self.clear.setStyleSheet("background-color: white") self.clear.setFont(QFont("Times", 14, QFont.Bold)) self.clear.clicked.connect(lambda: self.clear_data()) widget = QFrame(collapsible.get_tree()) widget.setPalette(get_verifone_color()) title = "Logging" self.loggerGrid = QGridLayout(widget) self.loggerGrid.addWidget(self.logger, 0, 0, 1, 2) self.loggerGrid.addWidget(self.logFilterLabel, 1, 0, 1, 1) self.loggerGrid.addWidget(self.logFilter, 1, 1, 1, 1) self.loggerGrid.addWidget(self.serialList, 2, 0, 1, 2) self.loggerGrid.addWidget(self.clear, 3, 0, 1, 2) collapsible.include_section(title, widget) def init_download(self, collapsible): self.download = QPushButton("Download Package", self) self.download.setFont(QFont("Times", 14, QFont.Bold)) self.download.clicked.connect(lambda: self.send_file()) self.download.setStyleSheet("background-color: white") self.loadDownloadFile = QPushButton("Load File", self) self.loadDownloadFile.setFont(QFont("Times", 14, QFont.Bold)) self.loadDownloadFile.clicked.connect(self.loadFromFile) self.loadDownloadFile.setStyleSheet("background-color: white") self.downloadFileName = QLineEdit("File name", self) self.downloadFileName.setStyleSheet("background-color: white") self.downloadFileName.setFixedWidth(300) self.downloadAddress = QLineEdit("IP Address", self) self.downloadAddress.setStyleSheet("background-color: white") self.downloadAddress.setFixedWidth(300) self.downloadStatus = QLabel("Download Status", self) self.downloadStatus.setStyleSheet( "background-color: rgba(3, 169, 229, 0); color : white") self.downloadStatus.setFixedWidth(300) widget = QFrame(collapsible.get_tree()) title = "Download" self.downloadGrid = QGridLayout(widget) self.downloadGrid.addWidget(self.download, 0, 0, 1, 2) self.downloadGrid.addWidget(self.loadDownloadFile, 1, 0, 1, 2) self.downloadGrid.addWidget(self.downloadFileName, 2, 0, 1, 2) self.downloadGrid.addWidget(self.downloadAddress, 3, 0, 1, 2) self.downloadGrid.addWidget(self.downloadStatus, 4, 0, 1, 2) collapsible.include_section(title, widget) def init_analyser(self, collapsible): self.performanceData = QPushButton("View Performance Data", self) self.performanceData.setFont(QFont("Times", 14, QFont.Bold)) self.performanceData.clicked.connect( lambda: self.display_performance_data()) self.performanceData.setStyleSheet("background-color: white") self.performanceChart = QPushButton("View Performance Chart", self) self.performanceChart.setFont(QFont("Times", 14, QFont.Bold)) self.performanceChart.clicked.connect( lambda: self.display_performance_chart()) self.performanceChart.setStyleSheet("background-color: white") widget = QFrame(collapsible.get_tree()) title = "Analyser" self.analyserGrid = QGridLayout(widget) self.analyserGrid.addWidget(self.performanceData, 0, 0, 1, 2) self.analyserGrid.addWidget(self.performanceChart, 1, 0, 1, 2) collapsible.include_section(title, widget) def loadFromFile(self): fileName, _ = QFileDialog.getOpenFileName( self, "Load Package", '', "Download Files (*.tgz);;All Files (*)") if not fileName: return try: in_file = open(str(fileName), 'rb') except IOError: QMessageBox.information( self, "Unable to open file", "There was an error opening \"%s\"" % fileName) return in_file.close() self.downloadFileName.setText(fileName) def createLoggingDisplayLabel(self): # Display Area self.text = QPlainTextEdit(self) self.text.setReadOnly(True) self.text.setFont(QFont("Times", 12, QFont.Bold)) self.text.setTextInteractionFlags(Qt.TextSelectableByMouse | Qt.TextSelectableByKeyboard) def clear_data(self): self.text.clear() os.remove(logfile_path, dir_fd=None) def display_log_data(self): #send_file() if ('COM' in self.serialList.currentText()): self.createLoggingDisplayLabel() self.scrollArea.setWidget(self.text) self.thread.stop() self.thread.start() data = get_data_from_file(logfile_path) if (len(data) > 0 and data != None): self.text.appendPlainText(data) self.logger.setDisabled(True) def get_data(self, data): if (len(data) > 0): logFile = open(logfile_path, "a") logFile.write(data) logFile.close() filterText = self.logFilter.text() if filterText in data.rstrip(): self.text.appendPlainText(data.rstrip()) vbar = self.scrollArea.verticalScrollBar() vbar.setValue(vbar.maximum()) def display_performance_data(self): self.thread.stop() data = get_data_from_file(logfile_path) jsonData = translate_data_to_json(data) self.performanceData = DisplayPerformanceData() self.performanceData.loadCsv( os.path.join(base_log_path, "performance_data.csv")) self.scrollArea.setWidget(self.performanceData) self.logger.setDisabled(False) def display_performance_chart(self): self.thread.stop() self.scrollArea.setWidget(get_performace_chart()) self.logger.setDisabled(False) def set_serial_port(self): self.thread.set_comport(self.serialList.currentText()) def send_file(self): base_path = os.path.join("c:/", "VFI", 'wks', 'global-payment-application', 'GPA', 'output', 'vos2', 'gpa', 'dl.gpa-1.0.0.0-000.tgz') fileName = self.downloadFileName.text() try: in_file = open(str(fileName), 'rb') except IOError: QMessageBox.information( self, "Unable to open file", "There was an error opening \"%s\"" % fileName) return in_file.close() load_vos_package_ip('192.168.0.104', fileName, self.downloadStatus)