class main_window(QMainWindow): def __init__(self, parent=None): #super(main_window, self.__init__(parent)) QWidget.__init__(self, parent) #Importing UI self.ui = Ui_MainWindow() self.ui.setupUi(self) #Setting up Initials # print("Constructor Called") self.setFixedSize(1024, 640) self.ui.pushButton.setFocusPolicy(Qt.NoFocus) self.move(QApplication.desktop().screen().rect().center() - self.rect().center()) self.setWindowTitle("NIDS") self.connect(self.ui.pushButton, SIGNAL("clicked()"), lambda: self.clicked()) # self.ui.pushButton.setChecked(True) # self.ui.pushButton_3.setChecked(True) # self.ui.pushButton_2.setChecked(False) def init(self): print("Hello") def clicked(self): print("Clicked") file_win = file_browser() self.close() file_win.exec()
class MyForm(QtGui.QMainWindow): def __init__(self, parent=None): QtGui.QWidget.__init__(self, parent) self.ui = Ui_MainWindow() self.ui.setupUi(self) QtCore.QObject.connect(self.ui.btnFileBrowser, QtCore.SIGNAL("clicked()"), self.selectFile) QtCore.QObject.connect(self.ui.btnDirBrowser, QtCore.SIGNAL("clicked()"), self.selectDir) QtCore.QObject.connect(self.ui.btnFilterFile, QtCore.SIGNAL("clicked()"), self.playFile) QtCore.QObject.connect(self, QtCore.SIGNAL("triggered()"), self.closeWindow) def selectFile(self): self.input_file = QtGui.QFileDialog.getOpenFileName() self.ui.txtFilename.setText(self.input_file) def selectDir(self): self.output_dir = QtGui.QFileDialog.getExistingDirectory(self, 'Select Output Directory') self.ui.txtOutputDir.setText(self.output_dir) def closeWindow(self): try: tb.stop() tb.wait() except NameError: pass def playFile(self): if os.path.isfile(self.input_file) is not True: print("Path is not a file!") return tb = top_block() tb.set_input_file(self.input_file) tb.setup_blocks() tb.start() tb.wait()
class MainWindow(QMainWindow): def __init__(self, parent=None): """Constructor""" super().__init__(parent) self.__ui = Ui_MainWindow() self.__ui.setupUi(self) @property def title_widget(self): """Expose the titlebar widget so it can be styled""" return self.__ui.title_widget
class MainWindow(QtGui.QMainWindow): def __init__(self): super(MainWindow, self).__init__() self.database = products.database self.ui = Ui_MainWindow() self.ui.setupUi(self) self.initSignals() self.key_buf = [] self.ui.codeBox.setFocus() self.total_price = 0 def initSignals(self): self.ui.quitButton.clicked.connect(self.close) self.ui.codeBox.returnPressed.connect(self.search_add_prod) self.ui.newButton.clicked.connect(self.new_list) def search_add_prod(self): search_code = str(self.ui.codeBox.text()) self.ui.codeBox.setText("") print("Searching and adding code %s" % search_code) if self.database.has_key(search_code): price = self.database[search_code]["price"] human_name = self.database[search_code]["name"] if self.database[search_code].has_key("picture"): pixmap = QtGui.QPixmap() pixmap.load("products/" + self.database[search_code]["picture"]) pixmap = pixmap.scaledToWidth(self.ui.imgLabel.size().width()) self.ui.imgLabel.setPixmap(pixmap) else: human_name = search_code price = int(random.random() * 20) self.add_to_list(human_name, price) self.update_total() def add_to_list(self, product_name, price): self.ui.listProducts.addItem(product_name) self.ui.listPrices.addItem(str(price)) self.ui.listProducts.scrollToBottom() self.ui.listPrices.scrollToBottom() self.total_price += price def update_total(self): self.ui.totalBox.setText("%d" % self.total_price) def new_list(self): self.total_price = 0 self.ui.listProducts.clear() self.ui.listPrices.clear() self.update_total() self.ui.codeBox.setFocus()
class MainWindow(QMainWindow): def __init__(self, parent=None): """Constructor""" super().__init__(parent) self.__ui = Ui_MainWindow() self.__ui.setupUi(self) self.__ui.tabWidget.setTabsClosable(True) self.__ui.tabWidget.setMovable(True) @property def tab_widget(self): """Expose the titlebar tab widget so it can be styled""" return self.__ui.tabWidget
class MyWindow(QMainWindow): def __init__(self): super().__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) centralWidget = QWidget() self.setCentralWidget(centralWidget) gridLayout = QGridLayout(centralWidget) gridLayout.addWidget(self.ui.label, 0, 0, alignment=Qt.AlignCenter) gridLayout.addWidget(self.ui.pushButton, 1, 0) def dialogbox(self): self.hide() self.myDialog = MyDialog() self.myDialog.show()
class MainWindow(QMainWindow): def __init__(self, parent=None): super().__init__(parent) self.__ui = Ui_MainWindow() self.__ui.setupUi(self) self.setWindowTitle('QDialog Test') self.__ui.msgWarning.clicked.connect(self.show_warning_msgbox) self.__ui.msgCritical.clicked.connect(self.show_critical_msgbox) self.__ui.msgQuestion.clicked.connect(self.show_question_msgbox) self.__ui.msgInformation.clicked.connect(self.show_information_msgbox) self.__ui.msgNoIcon.clicked.connect(self.show_regular_msgbox) def show_warning_msgbox(self): self.show_msg_box(QMessageBox.Warning) def show_critical_msgbox(self): self.show_msg_box(QMessageBox.Critical) def show_question_msgbox(self): self.show_msg_box(QMessageBox.Question) def show_information_msgbox(self): self.show_msg_box(QMessageBox.Information) def show_regular_msgbox(self): self.show_msg_box(QMessageBox.NoIcon) def show_msg_box(self, icon): msg = QtModernRedux.wrap( QMessageBox(self), parent=self, window_buttons_position=QtModernRedux.WINDOW_BUTTONS_RIGHT) msg.setIcon(icon) msg.setText("This is a message box") msg.setInformativeText("This is additional information") msg.setWindowTitle("MessageBox demo") msg.setDetailedText("The details are as follows:") retval = msg.exec_() print("value of pressed message box button:", retval)
class MyForm(QtWidgets.QMainWindow): def __init__(self, parent=None): QtWidgets.QWidget.__init__(self, parent) self.ui = Ui_MainWindow() self.ui.setupUi(self) def openFileNamesDialog(self) -> str: options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog file_path, _ = QFileDialog.getOpenFileName( self, "Select graph to load", "", "Graph Modelling Language (*.gml)", options=options) return file_path def showErrorDialog(self, errorMessage): msg = QMessageBox() msg.setIcon(QMessageBox.Critical) msg.setText(errorMessage) msg.setWindowTitle("Error") msg.exec_()
class LauncherWindow(QMainWindow): def __init__(self, parent=None): super(LauncherWindow, self).__init__(parent) self.__setupUI() self.setWindowTitle("launcher") for paneclass in launcherPanes.pluginClassList: pane = paneclass(self) paneName, paneIcon = pane.paneHeader() newheader = QRadioButton(self) newheader.setText(paneName) newheader.setIcon(QIcon(paneIcon)) newheader.setIconSize(QSize(32, 32)) newheader.toggled.connect(pane.setActive) self.ui.buttonsLayout.addWidget(newheader) self.ui.horizontalLayout.addWidget(pane) pane.hide() if (self.ui.buttonsLayout.count() == 1): newheader.setChecked(True) def __setupUI(self): self.ui = Ui_MainWindow() self.ui.setupUi(self) self.setStyleSheet('')
class MainWindow(QtGui.QMainWindow): def __init__(self): QtGui.QMainWindow.__init__(self) self.ui = Ui_MainWindow() self.ui.setupUi(self) self.ui.pushButton_translate.clicked.connect(self.check) def check(self): dict_obj = dict_lib.yandex_dict(r'') text_in = str(unicode(self.ui.lineEdit_input.text()).encode('utf-8')) words = dict_obj.check_text( text_in, str(self.ui.comboBox_from.currentText()) + '-' + str(self.ui.comboBox_to.currentText())) self.ui.textEdit_main.clear() result_text = '' for word in words: result_text = result_text + word + '<br>' result_text = result_text + '<br>' self.ui.textEdit_main.insertHtml(result_text) # http://stackoverflow.com/questions/5506781/pyqt4-application-on-windows-is-crashing-on-exit def closeEvent(self, event): sys.exit(0)
class MainWindow(QMainWindow, QObject): def __init__(self, parent=None): super().__init__(parent) self.ui = Ui_MainWindow() self.ui.setupUi(self) self.setWindowTitle('vk_chat_bot') # Все действия к прикрепляемым окнам поместим в меню for dock in self.findChildren(QDockWidget): self.ui.menuDockWindow.addAction(dock.toggleViewAction()) # Все действия к toolbar'ам окнам поместим в меню for tool in self.findChildren(QToolBar): self.ui.menuTools.addAction(tool.toggleViewAction()) # Выполнение кода в окне "Выполнение скрипта" self.ui.button_exec.clicked.connect(lambda x=None: exec(self.ui.code.toPlainText())) # # # # Чтобы не было проблем запуска компов с прокси: QNetworkProxyFactory.setUseSystemConfiguration(True) QWebSettings.globalSettings().setAttribute(QWebSettings.DeveloperExtrasEnabled, True) # TODO: оптимищация # QWebSettings::PrintElementBackgrounds # QWebSettings.globalSettings().setAttribute(QWebSettings.AutoLoadImages, False) self.web_view = QWebView() self.setCentralWidget(self.web_view) self.web_view.load('http://www.boibot.com/en/') self.wait_loading() # TODO: Установка вопроса, отправка его # self.slog( # self.doc.evaluateJavaScript(""" # //cleverbot.stimuluselement.value = "Расскажи анекдот!" # alert(cleverbot.stimuluselement.value) # alert(cleverbot.input) # alert(cleverbot.reply) # //cleverbot.sendAI() # """) # ) def _get_doc(self): return self.web_view.page().mainFrame().documentElement() doc = property(_get_doc) def wait_loading(self): """Функция ожидания загрузки страницы. Использовать только при изменении url.""" logger.debug('Начинаю ожидание загрузки страницы.') # Ждем пока прогрузится страница loop = QEventLoop() self.web_view.loadFinished.connect(loop.quit) loop.exec_() logger.debug('Закончено ожидание загрузки страницы.') # TODO: добавить возможность выбрать область поиска элемента для клика, а то она все время вся страница -- self.doc def click_tag(self, css_path): """Функция находит html тег по указанному пути и эмулирует клик на него. Строки в css_path нужно оборачивать в апострофы. Пример: # Кликаем на кнопку "Отнять у слабого" self.click_tag("div[class='button-big btn f1']") # Кликаем на кнопку "Искать другого" self.click_tag(".button-search a") """ logger.debug('Выполняю клик по тегу: %s', css_path) # Используем для клика jQuery code = """ tag = $("{}"); tag.click();""".format(css_path) ok = self.doc.evaluateJavaScript(code) if ok is None: logger.warn('Выполнение js скрипта неудачно. Code:\n' + code) def slog(self, text): """Функция для добавления текста в виджет-лог, находящегося на форме.""" self.ui.simple_log.appendPlainText('{}'.format(text)) def read_settings(self): # TODO: при сложных настройках, лучше перейти на json или yaml config = QSettings(CONFIG_FILE, QSettings.IniFormat) self.restoreState(config.value('MainWindow_State')) self.restoreGeometry(config.value('MainWindow_Geometry')) def write_settings(self): config = QSettings(CONFIG_FILE, QSettings.IniFormat) config.setValue('MainWindow_State', self.saveState()) config.setValue('MainWindow_Geometry', self.saveGeometry()) def closeEvent(self, *args, **kwargs): self.write_settings() super().closeEvent(*args, **kwargs)
class mywindow(QtWidgets.QMainWindow): tray_icon = None etalon_temp = None prev_tab_index = 0 time_line = [] temp_line = [] port_lines = [] time_line_current_tab = [] temp_line_current_tab = [] # serial_1 = QSerialPort(self) # myThread = SerialReadThread() thread1 = QtCore.QThread() thread2 = QtCore.QThread() thread3 = QtCore.QThread() thread4 = QtCore.QThread() thread5 = QtCore.QThread() thread6 = QtCore.QThread() thread7 = QtCore.QThread() thread8 = QtCore.QThread() thread9 = QtCore.QThread() thread10 = QtCore.QThread() def __init__(self): super(mywindow, self).__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) # Соединения кнопок меню self.ui.exit.triggered.connect(qApp.quit) self.ui.ports.triggered.connect(self.ports_open) self.ui.graph.triggered.connect(self.graph_open) self.plots = [self.ui.MplWidget_1, self.ui.MplWidget_2, self.ui.MplWidget_3, self.ui.MplWidget_4, self.ui.MplWidget_5, self.ui.MplWidget_6, self.ui.MplWidget_7, self.ui.MplWidget_8, self.ui.MplWidget_9, self.ui.MplWidget_10] # Инициализация навигационных баров для графиков self.plotNavs = [NavigationToolbar(self.plots[0].canvas, self), NavigationToolbar(self.plots[1].canvas, self), NavigationToolbar(self.plots[2].canvas, self), NavigationToolbar(self.plots[3].canvas, self), NavigationToolbar(self.plots[4].canvas, self), NavigationToolbar(self.plots[5].canvas, self), NavigationToolbar(self.plots[6].canvas, self), NavigationToolbar(self.plots[7].canvas, self), NavigationToolbar(self.plots[8].canvas, self), NavigationToolbar(self.plots[9].canvas, self)] for navBar in self.plotNavs: self.addToolBar(QtCore.Qt.BottomToolBarArea, navBar) navBar.toggleViewAction().trigger() navBar.toggleViewAction().trigger() self.plotNavs[0].toggleViewAction().trigger() self.ui.tabWidget.currentChanged.connect(self.tab_changed) self.update_tab_graph(0) # QThreads for serial port try: with open('port_configuration.cfg', 'r') as f: lines = f.readlines() f.close() except FileNotFoundError: print('File port_configuration.cfg not found') self.worker1 = SerialWorker(1, lines[0][:-1], lines[1][:-1]) self.worker2 = SerialWorker(2, lines[5][:-1], lines[6][:-1]) self.worker3 = SerialWorker(3, lines[10][:-1], lines[11][:-1]) self.worker4 = SerialWorker(4, lines[15][:-1], lines[16][:-1]) self.worker5 = SerialWorker(5, lines[20][:-1], lines[21][:-1]) self.worker6 = SerialWorker(6, lines[25][:-1], lines[26][:-1]) self.worker7 = SerialWorker(7, lines[30][:-1], lines[31][:-1]) self.worker8 = SerialWorker(8, lines[35][:-1], lines[36][:-1]) self.worker9 = SerialWorker(9, lines[40][:-1], lines[41][:-1]) self.worker10 = SerialWorker(10, lines[45][:-1], lines[46][:-1]) self.worker1.moveToThread(self.thread1) self.thread1.started.connect(self.worker1.task) self.thread1.start() self.worker2.moveToThread(self.thread2) self.thread2.started.connect(self.worker2.task) self.thread2.start() self.worker3.moveToThread(self.thread3) self.thread3.started.connect(self.worker3.task) self.thread3.start() self.worker4.moveToThread(self.thread4) self.thread4.started.connect(self.worker4.task) self.thread4.start() self.worker5.moveToThread(self.thread5) self.thread5.started.connect(self.worker5.task) self.thread5.start() self.worker6.moveToThread(self.thread6) self.thread6.started.connect(self.worker6.task) self.thread6.start() self.worker7.moveToThread(self.thread7) self.thread7.started.connect(self.worker7.task) self.thread7.start() self.worker8.moveToThread(self.thread8) self.thread8.started.connect(self.worker8.task) self.thread8.start() self.worker9.moveToThread(self.thread9) self.thread9.started.connect(self.worker9.task) self.thread9.start() self.worker10.moveToThread(self.thread10) self.thread10.started.connect(self.worker10.task) self.thread10.start() # Инициализируем QSystemTrayIcon self.tray_icon = QSystemTrayIcon(self) self.tray_icon.setIcon(QtGui.QIcon('lines.png')) show_action = QAction("Показать", self) quit_action = QAction("Выход", self) hide_action = QAction("Спрятать", self) show_action.triggered.connect(self.show) hide_action.triggered.connect(self.hide) quit_action.triggered.connect(qApp.quit) tray_menu = QMenu() tray_menu.addAction(show_action) tray_menu.addAction(hide_action) tray_menu.addAction(quit_action) self.tray_icon.setContextMenu(tray_menu) self.tray_icon.show() def tab_changed(self, index): # Показ навбара для текущей вкладки и скрытие от предыдущей self.plotNavs[self.prev_tab_index].toggleViewAction().trigger() self.plotNavs[index].toggleViewAction().trigger() self.prev_tab_index = index # Обновление эталонного графика для текущей вкладки self.update_tab_graph(index) def closeEvent(self, event): event.ignore() self.hide() self.tray_icon.showMessage( "Анализатор Варта ТП703", "Приложение было свернуто в трей", QSystemTrayIcon.Information, 2000 ) def on_serial_1_read(self): print(self.serial_1.readAll()) def graph_open(self): self.window_graph = QtWidgets.QMainWindow() self.ui_graph = Ui_Graph_editor() self.ui_graph.setupUi(self.window_graph) self.ui_graph.MplWidgetGraphEditor.canvas.axes.set_title('Эталон') self.ui_graph.comboBoxOwen.activated[str].connect(self.change_etalon_graph) self.ui_graph.lineEditTemp1.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTemp2.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTemp3.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTemp4.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTemp5.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTemp6.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTemp7.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTemp8.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTemp9.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTemp10.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTemp11.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTemp12.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTemp13.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTemp14.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTemp15.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTemp16.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTemp17.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTemp18.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTemp19.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTemp20.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTemp21.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTemp22.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTemp23.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTemp24.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTime1.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTime2.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTime3.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTime4.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTime5.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTime6.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTime7.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTime8.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTime9.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTime10.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTime11.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTime12.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTime13.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTime14.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTime15.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTime16.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTime17.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTime18.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTime19.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTime20.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTime21.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTime22.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTime23.editingFinished.connect(self.update_etalon_graph) self.ui_graph.lineEditTime24.editingFinished.connect(self.update_etalon_graph) try: with open('graph.cfg', 'r') as fr: lines = fr.readlines() self.temp_line = lines[0].split() self.temp_line = list(map(float, self.temp_line)) # line = fr.readline() self.time_line = lines[1].split() self.time_line = list(map(float, self.time_line)) fr.close() except FileNotFoundError: print('File graph.cfg not found') with open('graph.cfg', 'w') as fr: for i in range(20): fr.write('\n') fr.close() self.update_lines_graph() self.update_etalon_draw() self.window_graph.show() def ports_open(self): self.window_ports = QtWidgets.QMainWindow() self.ui_ports = Ui_Form() self.ui_ports.setupUi(self.window_ports) for dev in comports(): self.ui_ports.port_Name_comboBox.addItem(str(dev).split()[0]) self.ui_ports.owenName_comboBox.currentIndexChanged.connect(self.update_port_settings) self.ui_ports.port_Name_comboBox.currentIndexChanged.connect(self.update_port_Name_settings) self.ui_ports.speed_comboBox.currentIndexChanged.connect(self.update_speed_settings) self.ui_ports.parity_comboBox.currentIndexChanged.connect(self.update_parity_settings) self.ui_ports.bits_comboBox.currentIndexChanged.connect(self.update_bits_settings) self.ui_ports.stop_bits_comboBox.currentIndexChanged.connect(self.update_stop_bits_settings) self.window_ports.show() try: with open('port_configuration.cfg', 'r') as fr: self.port_lines = fr.readlines() fr.close() self.update_port_settings(0) except FileNotFoundError: print('File port_configuration.cfg not found') with open('port_configuration.cfg', 'w') as fr: for i in range(50): fr.write('\n') fr.close() def update_port_settings(self, index): try: with open('port_configuration.cfg', 'r') as fr: self.port_lines = fr.readlines() port_ind = self.ui_ports.port_Name_comboBox.findText(self.port_lines[index * 5][:-1], QtCore.Qt.MatchFixedString) if port_ind >= 0: self.ui_ports.port_Name_comboBox.setCurrentIndex(port_ind) speed_ind = self.ui_ports.speed_comboBox.findText(self.port_lines[index * 5 + 1][:-1], QtCore.Qt.MatchFixedString) if speed_ind >= 0: self.ui_ports.speed_comboBox.setCurrentIndex(speed_ind) # -------------------------------------------------- parity_ind = self.ui_ports.parity_comboBox.findText(self.port_lines[index * 5 + 2][:-1], QtCore.Qt.MatchFixedString) if parity_ind >= 0: self.ui_ports.parity_comboBox.setCurrentIndex(parity_ind) # -------------------------------------------------- bits_ind = self.ui_ports.bits_comboBox.findText(self.port_lines[index * 5 + 3][:-1], QtCore.Qt.MatchFixedString) if bits_ind >= 0: self.ui_ports.bits_comboBox.setCurrentIndex(bits_ind) # -------------------------------------------------- stop_bits_ind = self.ui_ports.stop_bits_comboBox.findText(self.port_lines[index * 5 + 4][:-1], QtCore.Qt.MatchFixedString) if stop_bits_ind >= 0: self.ui_ports.stop_bits_comboBox.setCurrentIndex(stop_bits_ind) fr.close() except FileNotFoundError: print('File port_configuration.cfg not found') # ser = serial.Serial() # open serial port # ser.baudrate = 9600 # ser.stopbits = 1 # ser.parity = 'N' # ser.port = 'COM12' # ser.open() # print(ser.read(6)) # ser.close() # global window2 # if window2 is None: # window2 = port_parameters_ui.Ui_Form() # window2.show() def update_port_Name_settings(self, index): owen_index = self.ui_ports.owenName_comboBox.currentIndex() try: with open('port_configuration.cfg', 'r') as f: self.port_lines = f.readlines() f.close() except FileNotFoundError: print('File port_configuration.cfg not found') try: with open('port_configuration.cfg', 'w') as f: self.port_lines[owen_index * 5] = self.ui_ports.port_Name_comboBox.currentText() + '\n' f.writelines(self.port_lines) f.close() except FileNotFoundError: print('File port_configuration.cfg not found') def update_speed_settings(self, index): owen_index = self.ui_ports.owenName_comboBox.currentIndex() try: with open('port_configuration.cfg', 'r') as f: self.port_lines = f.readlines() f.close() except FileNotFoundError: print('File port_configuration.cfg not found') try: with open('port_configuration.cfg', 'w') as f: self.port_lines[owen_index * 5 + 1] = str(self.ui_ports.speed_comboBox.currentText()) + '\n' f.writelines(self.port_lines) f.close() except FileNotFoundError: print('File port_configuration.cfg not found') def update_parity_settings(self, index): owen_index = self.ui_ports.owenName_comboBox.currentIndex() try: with open('port_configuration.cfg', 'r') as f: self.port_lines = f.readlines() f.close() except FileNotFoundError: print('File port_configuration.cfg not found') try: with open('port_configuration.cfg', 'w') as f: self.port_lines[owen_index * 5 + 2] = str(self.ui_ports.parity_comboBox.currentText()) + '\n' f.writelines(self.port_lines) f.close() except FileNotFoundError: print('File port_configuration.cfg not found') def update_bits_settings(self, index): owen_index = self.ui_ports.owenName_comboBox.currentIndex() try: with open('port_configuration.cfg', 'r') as f: self.port_lines = f.readlines() f.close() except FileNotFoundError: print('File port_configuration.cfg not found') try: with open('port_configuration.cfg', 'w') as f: self.port_lines[owen_index * 5 + 3] = str(self.ui_ports.bits_comboBox.currentText()) + '\n' f.writelines(self.port_lines) f.close() except FileNotFoundError: print('File port_configuration.cfg not found') def update_stop_bits_settings(self, index): owen_index = self.ui_ports.owenName_comboBox.currentIndex() try: with open('port_configuration.cfg', 'r') as f: self.port_lines = f.readlines() f.close() except FileNotFoundError: print('File port_configuration.cfg not found') try: with open('port_configuration.cfg', 'w') as f: self.port_lines[owen_index * 5 + 4] = str(self.ui_ports.stop_bits_comboBox.currentText()) + '\n' f.writelines(self.port_lines) f.close() except FileNotFoundError: print('File port_configuration.cfg not found') def update_etalon_graph(self): self.time_line = [] self.temp_line = [] if self.ui_graph.lineEditTime1.text(): if self.ui_graph.lineEditTime1.text(): self.temp_line.append(float(self.ui_graph.lineEditTemp1.text())) self.time_line.append(float(self.ui_graph.lineEditTime1.text())) if self.ui_graph.lineEditTime2.text(): if self.ui_graph.lineEditTemp2.text(): self.temp_line.append(float(self.ui_graph.lineEditTemp2.text())) self.time_line.append(float(self.ui_graph.lineEditTime2.text())) if self.ui_graph.lineEditTime3.text(): if self.ui_graph.lineEditTemp3.text(): self.temp_line.append(float(self.ui_graph.lineEditTemp3.text())) self.time_line.append(float(self.ui_graph.lineEditTime3.text())) if self.ui_graph.lineEditTime4.text(): if self.ui_graph.lineEditTemp4.text(): self.temp_line.append(float(self.ui_graph.lineEditTemp4.text())) self.time_line.append(float(self.ui_graph.lineEditTime4.text())) if self.ui_graph.lineEditTime5.text(): if self.ui_graph.lineEditTemp5.text(): self.temp_line.append(float(self.ui_graph.lineEditTemp5.text())) self.time_line.append(float(self.ui_graph.lineEditTime5.text())) if self.ui_graph.lineEditTime6.text(): if self.ui_graph.lineEditTemp6.text(): self.temp_line.append(float(self.ui_graph.lineEditTemp6.text())) self.time_line.append(float(self.ui_graph.lineEditTime6.text())) if self.ui_graph.lineEditTime7.text(): if self.ui_graph.lineEditTemp7.text(): self.temp_line.append(float(self.ui_graph.lineEditTemp7.text())) self.time_line.append(float(self.ui_graph.lineEditTime7.text())) if self.ui_graph.lineEditTime8.text(): if self.ui_graph.lineEditTemp8.text(): self.temp_line.append(float(self.ui_graph.lineEditTemp8.text())) self.time_line.append(float(self.ui_graph.lineEditTime8.text())) if self.ui_graph.lineEditTime9.text(): if self.ui_graph.lineEditTemp9.text(): self.temp_line.append(float(self.ui_graph.lineEditTemp9.text())) self.time_line.append(float(self.ui_graph.lineEditTime9.text())) if self.ui_graph.lineEditTime10.text(): if self.ui_graph.lineEditTemp10.text(): self.temp_line.append(float(self.ui_graph.lineEditTemp10.text())) self.time_line.append(float(self.ui_graph.lineEditTime10.text())) if self.ui_graph.lineEditTime11.text(): if self.ui_graph.lineEditTemp11.text(): self.temp_line.append(float(self.ui_graph.lineEditTemp11.text())) self.time_line.append(float(self.ui_graph.lineEditTime11.text())) if self.ui_graph.lineEditTime12.text(): if self.ui_graph.lineEditTemp12.text(): self.temp_line.append(float(self.ui_graph.lineEditTemp12.text())) self.time_line.append(float(self.ui_graph.lineEditTime12.text())) if self.ui_graph.lineEditTime13.text(): if self.ui_graph.lineEditTemp13.text(): self.temp_line.append(float(self.ui_graph.lineEditTemp13.text())) self.time_line.append(float(self.ui_graph.lineEditTime13.text())) if self.ui_graph.lineEditTime14.text(): if self.ui_graph.lineEditTemp14.text(): self.temp_line.append(float(self.ui_graph.lineEditTemp14.text())) self.time_line.append(float(self.ui_graph.lineEditTime14.text())) if self.ui_graph.lineEditTime15.text(): if self.ui_graph.lineEditTemp15.text(): self.temp_line.append(float(self.ui_graph.lineEditTemp15.text())) self.time_line.append(float(self.ui_graph.lineEditTime15.text())) if self.ui_graph.lineEditTime16.text(): if self.ui_graph.lineEditTemp16.text(): self.temp_line.append(float(self.ui_graph.lineEditTemp16.text())) self.time_line.append(float(self.ui_graph.lineEditTime16.text())) if self.ui_graph.lineEditTime17.text(): if self.ui_graph.lineEditTemp17.text(): self.temp_line.append(float(self.ui_graph.lineEditTemp17.text())) self.time_line.append(float(self.ui_graph.lineEditTime17.text())) if self.ui_graph.lineEditTime18.text(): if self.ui_graph.lineEditTemp18.text(): self.temp_line.append(float(self.ui_graph.lineEditTemp18.text())) self.time_line.append(float(self.ui_graph.lineEditTime18.text())) if self.ui_graph.lineEditTime19.text(): if self.ui_graph.lineEditTemp19.text(): self.temp_line.append(float(self.ui_graph.lineEditTemp19.text())) self.time_line.append(float(self.ui_graph.lineEditTime19.text())) if self.ui_graph.lineEditTime20.text(): if self.ui_graph.lineEditTemp20.text(): self.temp_line.append(float(self.ui_graph.lineEditTemp20.text())) self.time_line.append(float(self.ui_graph.lineEditTime20.text())) if self.ui_graph.lineEditTime21.text(): if self.ui_graph.lineEditTemp21.text(): self.temp_line.append(float(self.ui_graph.lineEditTemp21.text())) self.time_line.append(float(self.ui_graph.lineEditTime21.text())) if self.ui_graph.lineEditTime22.text(): if self.ui_graph.lineEditTemp22.text(): self.temp_line.append(float(self.ui_graph.lineEditTemp22.text())) self.time_line.append(float(self.ui_graph.lineEditTime22.text())) if self.ui_graph.lineEditTime23.text(): if self.ui_graph.lineEditTemp23.text(): self.temp_line.append(float(self.ui_graph.lineEditTemp23.text())) self.time_line.append(float(self.ui_graph.lineEditTime23.text())) if self.ui_graph.lineEditTime24.text(): if self.ui_graph.lineEditTemp24.text(): self.temp_line.append(float(self.ui_graph.lineEditTemp24.text())) self.time_line.append(float(self.ui_graph.lineEditTime24.text())) try: with open('graph.cfg', 'r') as file: lines = file.readlines() lines_len = len(lines) except FileNotFoundError: print('File graph.cfg not found') with open('graph.cfg', 'w') as graph_file: if self.ui_graph.comboBoxOwen.currentText() == 'Печь 1': lines[0] = " ".join(map(str, self.temp_line)) + '\n' lines[1] = " ".join(map(str, self.time_line)) + '\n' if self.ui_graph.comboBoxOwen.currentText() == 'Печь 2': lines[2] = " ".join(map(str, self.temp_line)) + '\n' lines[3] = " ".join(map(str, self.time_line)) + '\n' if self.ui_graph.comboBoxOwen.currentText() == 'Печь 3': lines[4] = " ".join(map(str, self.temp_line)) + '\n' lines[5] = " ".join(map(str, self.time_line)) + '\n' if self.ui_graph.comboBoxOwen.currentText() == 'Печь 4': lines[6] = " ".join(map(str, self.temp_line)) + '\n' lines[7] = " ".join(map(str, self.time_line)) + '\n' if self.ui_graph.comboBoxOwen.currentText() == 'Печь 5': lines[8] = " ".join(map(str, self.temp_line)) + '\n' lines[9] = " ".join(map(str, self.time_line)) + '\n' if self.ui_graph.comboBoxOwen.currentText() == 'Печь 6': lines[10] = " ".join(map(str, self.temp_line)) + '\n' lines[11] = " ".join(map(str, self.time_line)) + '\n' if self.ui_graph.comboBoxOwen.currentText() == 'Печь 7': lines[12] = " ".join(map(str, self.temp_line)) + '\n' lines[13] = " ".join(map(str, self.time_line)) + '\n' if self.ui_graph.comboBoxOwen.currentText() == 'Печь 8': lines[14] = " ".join(map(str, self.temp_line)) + '\n' lines[15] = " ".join(map(str, self.time_line)) + '\n' if self.ui_graph.comboBoxOwen.currentText() == 'Печь 9': lines[16] = " ".join(map(str, self.temp_line)) + '\n' lines[17] = " ".join(map(str, self.time_line)) + '\n' if self.ui_graph.comboBoxOwen.currentText() == 'Печь 10': lines[18] = " ".join(map(str, self.temp_line)) + '\n' lines[19] = " ".join(map(str, self.time_line)) + '\n' graph_file.writelines(lines) graph_file.close() self.update_etalon_draw() def update_etalon_draw(self): self.ui_graph.MplWidgetGraphEditor.canvas.axes.clear() self.ui_graph.MplWidgetGraphEditor.canvas.axes.plot(self.time_line, self.temp_line, lw=2) self.ui_graph.MplWidgetGraphEditor.canvas.axes.set_ylabel('Градусы, °С') self.ui_graph.MplWidgetGraphEditor.canvas.axes.set_xlabel('Время, ч') self.ui_graph.MplWidgetGraphEditor.canvas.axes.legend(u'Эталон', loc='lower center') self.ui_graph.MplWidgetGraphEditor.canvas.draw() def change_etalon_graph(self, text): if text == 'Печь 1': try: with open('graph.cfg', 'r') as fr: lines = fr.readlines() self.temp_line = lines[0].split() self.temp_line = list(map(float, self.temp_line)) self.time_line = lines[1].split() self.time_line = list(map(float, self.time_line)) fr.close() except FileNotFoundError: print('File graph.cfg not found') self.update_lines_graph() self.update_etalon_draw() if text == 'Печь 2': try: with open('graph.cfg', 'r') as fr: lines = fr.readlines() self.temp_line = lines[2].split() self.temp_line = list(map(float, self.temp_line)) self.time_line = lines[3].split() self.time_line = list(map(float, self.time_line)) fr.close() except FileNotFoundError: print('File graph.cfg not found') self.update_lines_graph() self.update_etalon_draw() if text == 'Печь 3': try: with open('graph.cfg', 'r') as fr: lines = fr.readlines() self.temp_line = lines[4].split() self.temp_line = list(map(float, self.temp_line)) self.time_line = lines[5].split() self.time_line = list(map(float, self.time_line)) fr.close() except FileNotFoundError: print('File graph.cfg not found') self.update_lines_graph() self.update_etalon_draw() if text == 'Печь 4': try: with open('graph.cfg', 'r') as fr: lines = fr.readlines() self.temp_line = lines[6].split() self.temp_line = list(map(float, self.temp_line)) self.time_line = lines[7].split() self.time_line = list(map(float, self.time_line)) fr.close() except FileNotFoundError: print('File graph.cfg not found') self.update_lines_graph() self.update_etalon_draw() if text == 'Печь 5': try: with open('graph.cfg', 'r') as fr: lines = fr.readlines() self.temp_line = lines[8].split() self.temp_line = list(map(float, self.temp_line)) self.time_line = lines[9].split() self.time_line = list(map(float, self.time_line)) fr.close() except FileNotFoundError: print('File graph.cfg not found') self.update_lines_graph() self.update_etalon_draw() if text == 'Печь 6': try: with open('graph.cfg', 'r') as fr: lines = fr.readlines() self.temp_line = lines[10].split() self.temp_line = list(map(float, self.temp_line)) self.time_line = lines[11].split() self.time_line = list(map(float, self.time_line)) fr.close() except FileNotFoundError: print('File graph.cfg not found') self.update_lines_graph() self.update_etalon_draw() if text == 'Печь 7': try: with open('graph.cfg', 'r') as fr: lines = fr.readlines() self.temp_line = lines[12].split() self.temp_line = list(map(float, self.temp_line)) self.time_line = lines[13].split() self.time_line = list(map(float, self.time_line)) fr.close() except FileNotFoundError: print('File graph.cfg not found') self.update_lines_graph() self.update_etalon_draw() if text == 'Печь 8': try: with open('graph.cfg', 'r') as fr: lines = fr.readlines() self.temp_line = lines[14].split() self.temp_line = list(map(float, self.temp_line)) self.time_line = lines[15].split() self.time_line = list(map(float, self.time_line)) fr.close() except FileNotFoundError: print('File graph.cfg not found') self.update_lines_graph() self.update_etalon_draw() if text == 'Печь 9': try: with open('graph.cfg', 'r') as fr: lines = fr.readlines() self.temp_line = lines[16].split() self.temp_line = list(map(float, self.temp_line)) self.time_line = lines[17].split() self.time_line = list(map(float, self.time_line)) fr.close() except FileNotFoundError: print('File graph.cfg not found') self.update_lines_graph() self.update_etalon_draw() if text == 'Печь 10': try: with open('graph.cfg', 'r') as fr: lines = fr.readlines() self.temp_line = lines[18].split() self.temp_line = list(map(float, self.temp_line)) self.time_line = lines[19].split() self.time_line = list(map(float, self.time_line)) fr.close() except FileNotFoundError: print('File graph.cfg not found') self.update_lines_graph() self.update_etalon_draw() def update_lines_graph(self): if len(self.temp_line) >= 1: self.ui_graph.lineEditTemp1.setText(str(self.temp_line[0])) else: self.ui_graph.lineEditTemp1.setText('') if len(self.temp_line) >= 2: self.ui_graph.lineEditTemp2.setText(str(self.temp_line[1])) else: self.ui_graph.lineEditTemp2.setText('') if len(self.temp_line) >= 3: self.ui_graph.lineEditTemp3.setText(str(self.temp_line[2])) else: self.ui_graph.lineEditTemp3.setText('') if len(self.temp_line) >= 4: self.ui_graph.lineEditTemp4.setText(str(self.temp_line[3])) else: self.ui_graph.lineEditTemp4.setText('') if len(self.temp_line) >= 5: self.ui_graph.lineEditTemp5.setText(str(self.temp_line[4])) else: self.ui_graph.lineEditTemp5.setText('') if len(self.temp_line) >= 6: self.ui_graph.lineEditTemp6.setText(str(self.temp_line[5])) else: self.ui_graph.lineEditTemp6.setText('') if len(self.temp_line) >= 7: self.ui_graph.lineEditTemp7.setText(str(self.temp_line[6])) else: self.ui_graph.lineEditTemp7.setText('') if len(self.temp_line) >= 8: self.ui_graph.lineEditTemp8.setText(str(self.temp_line[7])) else: self.ui_graph.lineEditTemp8.setText('') if len(self.temp_line) >= 9: self.ui_graph.lineEditTemp9.setText(str(self.temp_line[8])) else: self.ui_graph.lineEditTemp9.setText('') if len(self.temp_line) >= 10: self.ui_graph.lineEditTemp10.setText(str(self.temp_line[9])) else: self.ui_graph.lineEditTemp10.setText('') if len(self.temp_line) >= 11: self.ui_graph.lineEditTemp11.setText(str(self.temp_line[10])) else: self.ui_graph.lineEditTemp11.setText('') if len(self.temp_line) >= 12: self.ui_graph.lineEditTemp12.setText(str(self.temp_line[11])) else: self.ui_graph.lineEditTemp12.setText('') if len(self.temp_line) >= 13: self.ui_graph.lineEditTemp13.setText(str(self.temp_line[12])) else: self.ui_graph.lineEditTemp13.setText('') if len(self.temp_line) >= 14: self.ui_graph.lineEditTemp14.setText(str(self.temp_line[13])) else: self.ui_graph.lineEditTemp14.setText('') if len(self.temp_line) >= 15: self.ui_graph.lineEditTemp15.setText(str(self.temp_line[14])) else: self.ui_graph.lineEditTemp15.setText('') if len(self.temp_line) >= 16: self.ui_graph.lineEditTemp16.setText(str(self.temp_line[15])) else: self.ui_graph.lineEditTemp16.setText('') if len(self.temp_line) >= 17: self.ui_graph.lineEditTemp17.setText(str(self.temp_line[16])) else: self.ui_graph.lineEditTemp17.setText('') if len(self.temp_line) >= 18: self.ui_graph.lineEditTemp18.setText(str(self.temp_line[17])) else: self.ui_graph.lineEditTemp18.setText('') if len(self.temp_line) >= 19: self.ui_graph.lineEditTemp19.setText(str(self.temp_line[18])) else: self.ui_graph.lineEditTemp19.setText('') if len(self.temp_line) >= 20: self.ui_graph.lineEditTemp20.setText(str(self.temp_line[19])) else: self.ui_graph.lineEditTemp20.setText('') if len(self.temp_line) >= 21: self.ui_graph.lineEditTemp21.setText(str(self.temp_line[20])) else: self.ui_graph.lineEditTemp21.setText('') if len(self.temp_line) >= 22: self.ui_graph.lineEditTemp22.setText(str(self.temp_line[21])) else: self.ui_graph.lineEditTemp22.setText('') if len(self.temp_line) >= 23: self.ui_graph.lineEditTemp23.setText(str(self.temp_line[22])) else: self.ui_graph.lineEditTemp23.setText('') if len(self.temp_line) >= 24: self.ui_graph.lineEditTemp24.setText(str(self.temp_line[23])) else: self.ui_graph.lineEditTemp24.setText('') if len(self.time_line) >= 1: self.ui_graph.lineEditTime1.setText(str(self.time_line[0])) else: self.ui_graph.lineEditTime1.setText('') if len(self.time_line) >= 2: self.ui_graph.lineEditTime2.setText(str(self.time_line[1])) else: self.ui_graph.lineEditTime2.setText('') if len(self.time_line) >= 3: self.ui_graph.lineEditTime3.setText(str(self.time_line[2])) else: self.ui_graph.lineEditTime3.setText('') if len(self.time_line) >= 4: self.ui_graph.lineEditTime4.setText(str(self.time_line[3])) else: self.ui_graph.lineEditTime4.setText('') if len(self.time_line) >= 5: self.ui_graph.lineEditTime5.setText(str(self.time_line[4])) else: self.ui_graph.lineEditTime5.setText('') if len(self.time_line) >= 6: self.ui_graph.lineEditTime6.setText(str(self.time_line[5])) else: self.ui_graph.lineEditTime6.setText('') if len(self.time_line) >= 7: self.ui_graph.lineEditTime7.setText(str(self.time_line[6])) else: self.ui_graph.lineEditTime7.setText('') if len(self.time_line) >= 8: self.ui_graph.lineEditTime8.setText(str(self.time_line[7])) else: self.ui_graph.lineEditTime8.setText('') if len(self.time_line) >= 9: self.ui_graph.lineEditTime9.setText(str(self.time_line[8])) else: self.ui_graph.lineEditTime9.setText('') if len(self.time_line) >= 10: self.ui_graph.lineEditTime10.setText(str(self.time_line[9])) else: self.ui_graph.lineEditTime10.setText('') if len(self.time_line) >= 11: self.ui_graph.lineEditTime11.setText(str(self.time_line[10])) else: self.ui_graph.lineEditTime11.setText('') if len(self.time_line) >= 12: self.ui_graph.lineEditTime12.setText(str(self.time_line[11])) else: self.ui_graph.lineEditTime12.setText('') if len(self.time_line) >= 13: self.ui_graph.lineEditTime13.setText(str(self.time_line[12])) else: self.ui_graph.lineEditTime13.setText('') if len(self.time_line) >= 14: self.ui_graph.lineEditTime14.setText(str(self.time_line[13])) else: self.ui_graph.lineEditTime14.setText('') if len(self.time_line) >= 15: self.ui_graph.lineEditTime15.setText(str(self.time_line[14])) else: self.ui_graph.lineEditTime15.setText('') if len(self.time_line) >= 16: self.ui_graph.lineEditTime16.setText(str(self.time_line[15])) else: self.ui_graph.lineEditTime16.setText('') if len(self.time_line) >= 17: self.ui_graph.lineEditTime17.setText(str(self.time_line[16])) else: self.ui_graph.lineEditTime17.setText('') if len(self.time_line) >= 18: self.ui_graph.lineEditTime18.setText(str(self.time_line[17])) else: self.ui_graph.lineEditTime18.setText('') if len(self.time_line) >= 19: self.ui_graph.lineEditTime19.setText(str(self.time_line[18])) else: self.ui_graph.lineEditTime19.setText('') if len(self.time_line) >= 20: self.ui_graph.lineEditTime20.setText(str(self.time_line[19])) else: self.ui_graph.lineEditTime21.setText('') if len(self.time_line) >= 21: self.ui_graph.lineEditTime21.setText(str(self.time_line[20])) else: self.ui_graph.lineEditTime21.setText('') if len(self.time_line) >= 22: self.ui_graph.lineEditTime22.setText(str(self.time_line[21])) else: self.ui_graph.lineEditTime22.setText('') if len(self.time_line) >= 23: self.ui_graph.lineEditTime23.setText(str(self.time_line[22])) else: self.ui_graph.lineEditTime23.setText('') if len(self.time_line) >= 24: self.ui_graph.lineEditTime24.setText(str(self.time_line[23])) else: self.ui_graph.lineEditTime24.setText('') def update_graph(self): fs = 500 f = random.randint(1, 100) ts = 1 / fs length_of_signal = 100 t = np.linspace(0, 1, length_of_signal) cosinus_signal = np.cos(2 * np.pi * f * t) sinus_signal = np.sin(2 * np.pi * f * t) self.ui.MplWidget_1.canvas.axes.clear() self.ui.MplWidget_1.canvas.axes.plot(t, cosinus_signal) self.ui.MplWidget_1.canvas.axes.legend(('Реальная', 'Заданная'), loc='upper right') self.ui.MplWidget_1.canvas.draw() self.ui.MplWidget_2.canvas.axes.clear() self.ui.MplWidget_2.canvas.axes.plot(t, cosinus_signal) self.ui.MplWidget_2.canvas.axes.plot(t, sinus_signal) self.ui.MplWidget_2.canvas.axes.legend(('Реальная', 'Заданная'), loc='upper right') self.ui.MplWidget_2.canvas.draw() def update_tab_graph(self, index): # Считываем значения из файла 'graph.cfg' try: with open('graph.cfg', 'r') as fr: lines = fr.readlines() self.temp_line_current_tab = lines[index * 2].split() # self.temp_line_current_tab = list(map(float, self.temp_line_current_tab)) self.time_line_current_tab = lines[index * 2 + 1].split() # self.time_line_current_tab = list(map(float, self.time_line_current_tab)) fr.close() except FileNotFoundError: print('File graph.cfg not found') self.plots[index].canvas.axes.clear() self.plots[index].canvas.axes.set_title('Печь №' + str(index + 1)) # self.plots[index].canvas.axes.plot_date(self.time_line_current_tab, self.temp_line_current_tab, '-') x, y = self.get_last_graph_points(index + 1) self.plots[index].canvas.axes.plot_date(x, y, '-') print(self.get_last_graph_points(index + 1)) self.plots[index].canvas.axes.legend(('Заданная', 'Реальная'), loc='upper left') self.plots[index].canvas.axes.grid() self.plots[index].canvas.draw() def get_last_graph_points(self, num): # Извлекаем текущий месяц для проверки существует ли такая папка time_current = time.strftime("%Y,%m,%d,%H,%M,%S") t = time_current.split(',') numbers = [int(x) for x in t] # Проверяем есть ли такая папка если нет, то создаем ее if os.path.isdir(r'.\dat' + '\\' + str(numbers[1]) + '\\' + str(numbers[2])): path = r'.\dat' + '\\' + str(numbers[1]) + '\\' + str(numbers[2]) else: os.makedirs(r'.\dat' + '\\' + str(numbers[1]) + '\\' + str(numbers[2])) path = r'.\dat' + '\\' + str(numbers[1]) + '\\' + str(numbers[2]) file_names = glob.glob1(path, "owen" + str(num) + "*") print('Files count:{}', len(file_names)) realtime_data_timeline = [] realtime_data_temperature = [] if file_names: for file in file_names: with open(path + '\\' + file, 'r', newline='') as fp: reader = csv.reader(fp, delimiter=';') if reader: for row in reader: # timeline = time.strftime("%H.%M", time.localtime(int(row[0]))) # data = [int(row[1]), float(timeline)] realtime_data_timeline.append(row[0]) realtime_data_temperature.append(int(row[1])) else: return [] return realtime_data_timeline, realtime_data_temperature else: return []
class MainWindow(QMainWindow): ui = None mainWindow = None client = WudaoClient() painter = GuiDraw() draw_conf = True is_zh = False word = '' def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.history_manager = UserHistory() self.setup_ui() def setup_ui(self): self.ui = Ui_MainWindow() self.ui.setupUi(self) # auto complete self.auto_com_init() self.ui.ol_cb.setChecked(False) darkula = QPalette() # theme darkula.setColor(QPalette.Background, QColor('#300A24')) darkula.setColor(QPalette.Base, QColor('#300A24')) self.ui.textBrowser.setPalette(darkula) # status bar self.ui.statusbar.showMessage('@2016 Chestnut Studio') # signal slot self.ui.lineEdit.returnPressed.connect(self.search_bt_clicked) self.ui.search_b.clicked.connect(self.search_bt_clicked) self.ui.detail_rb.clicked.connect(self.detail_rb_clicked) self.ui.intro_rb.clicked.connect(self.intro_rb_clicked) def detail_rb_clicked(self): self.draw_conf = True self.search_bt_clicked() def intro_rb_clicked(self): self.draw_conf = False self.search_bt_clicked() # auto complete def auto_com_init(self): sl = ['a', 'air', 'airplane'] com = QCompleter(sl) com.setCaseSensitivity(Qt.CaseInsensitive) self.ui.lineEdit.setCompleter(com) def search_bt_clicked(self): self.word = self.ui.lineEdit.text().strip() if self.word: # if chinese if is_alphabet(self.word[0]): self.is_zh = False else: self.is_zh = True # query on server server_context = self.client.get_word_info(self.word).strip() if server_context != 'None': wi = json.loads(server_context) self.painter.html = '' if self.is_zh: self.painter.draw_zh_text(wi, self.draw_conf) else: self.history_manager.add_item(self.word) self.painter.draw_text(wi, self.draw_conf) self.ui.textBrowser.setHtml(self.painter.html) else: # Online search html = '' if self.ui.ol_cb.isChecked(): self.painter.html = '' try: self.ui.textBrowser.setHtml(self.painter.P_W_PATTERN % 'Searching OL...') from src.WudaoOnline import get_text, get_zh_text from urllib.error import URLError if self.is_zh: word_info = get_zh_text(self.word) else: word_info = get_text(self.word) if not word_info['paraphrase']: html += self.painter.P_W_PATTERN % ('No such word: %s found online' % self.word) if not self.is_zh: self.history_manager.add_word_info(word_info) self.painter.draw_text(word_info, self.draw_conf) else: self.painter.draw_zh_text(word_info, self.draw_conf) self.ui.textBrowser.setHtml(self.painter.html) return except ImportError: html += self.painter.P_W_PATTERN % 'You need install bs4 first.' html += self.painter.P_W_PATTERN % 'Use \'pip3 install bs4\' or get bs4 online.' except URLError: html += self.painter.P_W_PATTERN % 'No Internet : Please check your connection first' else: # search in online cache first word_info = self.history_manager.get_word_info(self.word) if word_info: self.history_manager.add_item(self.word) self.painter.draw_text(word_info, self.draw_conf) self.ui.textBrowser.setHtml(self.painter.html) return else: html += self.painter.P_W_PATTERN % ('Error: no such word :' + self.word) html += self.painter.P_W_PATTERN % 'You can check Online Box to search it online.' self.ui.textBrowser.setHtml(html)
class MainWindow(QMainWindow): def __init__(self, parent=None): super().__init__(parent) self.__ui = Ui_MainWindow() self.__ui.setupUi(self)
class MainWindow(QtGui.QMainWindow): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.ui_controller = Ui_MainWindow() self.ui_controller.setupUi(self) self.connect() self.ui_controller.matplotlibWidget.connect() self.init_style_menu() self.init_indicator_menu() self.init_strategy_panel() self.ui_controller.dateStartEdit.setDateTime(datetime(1990,1,1)) self.ui_controller.dateEndEdit.setDateTime(datetime.now()) self.df = None def init_style_menu(self): self.ui_controller.styleMenu = QtGui.QMenu(self) self.ui_controller.lineChartAction = QtGui.QAction("Line", self) self.ui_controller.areaChartAction = QtGui.QAction("Area", self) self.ui_controller.barChartAction = QtGui.QAction("Bar", self) self.ui_controller.candleChartAction = QtGui.QAction("Candle", self) self.ui_controller.styleMenu.addAction(self.ui_controller.lineChartAction) self.ui_controller.styleMenu.addAction(self.ui_controller.areaChartAction) self.ui_controller.styleMenu.addAction(self.ui_controller.barChartAction) self.ui_controller.styleMenu.addAction(self.ui_controller.candleChartAction) self.ui_controller.styleToolButton.setMenu(self.ui_controller.styleMenu) def init_indicator_menu(self): self.ui_controller.indicatorMenu = QtGui.QMenu(self) self.ui_controller.indicator_SMAAction = QtGui.QAction("Simple Moving Average (SMA)", self) self.ui_controller.indicator_EMAAction = QtGui.QAction("Exponential Moving Average (EMA)", self) self.ui_controller.indicator_MACDAction = QtGui.QAction("MACD", self) self.ui_controller.indicator_RSIAction = QtGui.QAction("Relative Strength Index (RSI)", self) self.ui_controller.indicatorMenu.addAction(self.ui_controller.indicator_SMAAction) self.ui_controller.indicatorMenu.addAction(self.ui_controller.indicator_EMAAction) self.ui_controller.indicatorMenu.addAction(self.ui_controller.indicator_MACDAction) self.ui_controller.indicatorMenu.addAction(self.ui_controller.indicator_RSIAction) self.ui_controller.indicatorToolButton.setMenu(self.ui_controller.indicatorMenu) def init_strategy_panel(self): strategy_files = sorted(glob.glob('%s/*.py' % strategy_path)) for file in strategy_files: base = os.path.splitext(os.path.basename(file))[0] item = QtGui.QListWidgetItem(base, self.ui_controller.strategyListWidget) item.setData(QtCore.Qt.UserRole, QtCore.QVariant(file)) self.ui_controller.strategyListWidget.addItem(item) self.ui_controller.strategyListWidget.customContextMenuRequested.connect(self.showMenu) def connect(self): for toolButton in self.ui_controller.buttonGroup.buttons(): toolButton.clicked.connect(partial(self.on_toolButtonClicked, toolButton)) self.ui_controller.actionRunStrategy.triggered.connect(self.on_runStrategy) self.ui_controller.actionEditStrategy.triggered.connect(self.on_editStrategy) self.ui_controller.symbolLineEdit.returnPressed.connect(self.load_symbol) self.ui_controller.symbolLineEdit.textChanged.connect(self.on_symbolEditChanged) def on_loadQuoteClicked(self): logger.info('load quote') fileName = QtGui.QFileDialog.getOpenFileName( self, self.tr("Open Quote Data"), data_path, self.tr("Quote Files (*.csv)")) logger.info("Filename %s" % fileName) if os.path.isfile(fileName): df = pd.read_csv(unicode(fileName)) df.columns = [col.lower() for col in df.columns] if 'datetime' in df.columns: df = df.sort(['datetime']) df['datetime'] = df.apply( lambda row: mdates.date2num(parser.parse(row['datetime'])), axis=1) elif 'date' in df.columns: df = df.sort(['date']) df['datetime'] = df.apply( lambda row: mdates.date2num(parser.parse(row['date'])), axis=1) if 'datetime' in df.columns and not df['datetime'].empty: self.ui_controller.matplotlibWidget.set_data(df) self.ui_controller.matplotlibWidget.draw_data() self.df = df def on_toolButtonClicked(self, button): name = str(button.objectName()) button_values = { 'oneDayToolButton': WindowSize.ONEDAY, 'fiveDayToolButton': WindowSize.FIVEDAY, 'oneMonthToolButton': WindowSize.ONEMONTH, 'threeMonthToolButton': WindowSize.THREEMONTH, 'sixMonthToolButton': WindowSize.SIXMONTH, 'oneYearToolButton': WindowSize.ONEYEAR, 'twoYearToolButton': WindowSize.TWOYEAR, 'fiveYearToolButton': WindowSize.FIVEYEAR, 'maxToolButton': WindowSize.MAX, } size = button_values[name] self.ui_controller.matplotlibWidget.setxlim(size) def showMenu(self, position): indexes = self.ui_controller.strategyListWidget.selectedIndexes() if len(indexes) > 0: menu = QtGui.QMenu() menu.addAction(self.ui_controller.actionRunStrategy) menu.addAction(self.ui_controller.actionEditStrategy) menu.exec_(self.ui_controller.strategyListWidget.viewport().mapToGlobal(position)) def on_runStrategy(self, check): indexes = self.ui_controller.strategyListWidget.selectedIndexes() if len(indexes) > 0: logger.info('Run strategy') index = indexes[0].row() item = self.ui_controller.strategyListWidget.item(index) strategy_file = str(item.data(QtCore.Qt.UserRole).toPyObject()) strategy = imp.load_source('strategy', strategy_file) if hasattr(strategy, 'initialize') and hasattr(strategy, 'run'): runner = StrategyRunner(initialize=strategy.initialize, run=strategy.run) runner.run(self.df) else: logger.error("%s is not a valid strategy" % strategy_file) def on_editStrategy(self, check): indexes = self.ui_controller.strategyListWidget.selectedIndexes() if len(indexes) > 0: logger.info('Edit strategy') index = indexes[0].row() item = self.ui_controller.strategyListWidget.item(index) strategy_file = item.data(QtCore.Qt.UserRole).toPyObject() sysopen(strategy_file) def on_symbolEditChanged(self, text): if text: self.ui_controller.symbolLineEdit.setText(str(text).upper()) def load_symbol(self): start = parser.parse(str(self.ui_controller.dateStartEdit.text())) end = parser.parse(str(self.ui_controller.dateEndEdit.text())) symbol = str(self.ui_controller.symbolLineEdit.text()) if not symbol: return data = _load_raw_yahoo_data(stocks=[symbol], indexes={}, start=start, end=end) self.df = data[symbol] self.df.columns = [col.lower() for col in self.df.columns] self.df['datetime'] = self.df.index self.df['datetime'] = self.df.apply( lambda row: mdates.date2num(row['datetime']), axis=1) if 'adj close' in self.df.columns: self.df['close'] = self.df['adj close'] self.ui_controller.matplotlibWidget.set_data(self.df) self.ui_controller.matplotlibWidget.draw_data() self.ui_controller.symbolLineEdit.setText('')
access_key = access_info["access_key"] secret_key = access_info["secret_key"] server_url = "https://api.upbit.com" # 외부 개인지갑 암호화폐 보유 갯수 external_wallet_amount = access_info['external_wallet_amount'] fOriginalFiatBalance = access_info["original_fiat_balance"] myApp = QtWidgets.QApplication(sys.argv) obj = UpbitRebalancing(secret_key, access_key, server_url, external_wallet_amount) form = QtWidgets.QMainWindow() ui = Ui_MainWindow() ui.setupUi(form) def onChkShowBalanceStateChanged(btnChkState): if (btnChkState == Qt.Checked): ui.lblCryptoBalance.setHidden(False) ui.lblFiatBalance.setHidden(False) ui.lblOriBalance.setHidden(False) else: ui.lblCryptoBalance.setHidden(True) ui.lblFiatBalance.setHidden(True) ui.lblOriBalance.setHidden(True) def onStyleSheetChanged(strStyleSheet): myApp.setStyleSheet(strStyleSheet) # 기존 투입 자산 대비 현재 얼마나 가치를 가지고 있나 측정
class MainWindow(QMainWindow): FIT_WINDOW, FIT_WIDTH, MANUAL_ZOOM = range(3) resized = QtCore.pyqtSignal() def __init__(self, app_name, cfg_file): super(MainWindow, self).__init__() # setup config self.cfg_file = cfg_file self.setup_config() # setup workers self.worker01 = GetImage() self.worker02 = GetImage() self.worker03 = GetImage() self.worker04 = GetImage() self.worker05 = GetImage() self.setup_workers() # setup ui self.ui = Ui_MainWindow() self.ui.setupUi(self) self.ui.banner.setText(cfg_priv.GLOBAL.BANNER) # canvas main window self.setWindowIcon(QIcon(cfg_priv.ICONS.LOGO)) self.canvas = Canvas() self.canvas.image = QImage(cfg_priv.ICONS.BACKGROUND) self.canvas.zoomRequest.connect(self.zoomRequest) scroll = QScrollArea() scroll.setWidget(self.canvas) scroll.setWidgetResizable(True) self.scrollBars = { Qt.Vertical: scroll.verticalScrollBar(), Qt.Horizontal: scroll.horizontalScrollBar() } self.canvas.scrollRequest.connect(self.scrollRequest) self.ui.main_video_layout.addWidget(scroll) self.zoomWidget = ZoomWidget() zoom = QWidgetAction(self) zoom.setDefaultWidget(self.zoomWidget) self.zoomWidget.setWhatsThis( u"Zoom in or out of the image. Also accessible with" " %s and %s from the canvas." % (fmtShortcut("Ctrl+[-+]"), fmtShortcut("Ctrl+Wheel"))) self.zoomWidget.setEnabled(False) self.scalers = { self.FIT_WINDOW: self.scaleFitWindow, self.FIT_WIDTH: self.scaleFitWidth, # Set to one to scale to 100% when loading files. self.MANUAL_ZOOM: lambda: 1, } self.zoomMode = self.FIT_WINDOW self.canvas.setEnabled(True) self.adjustScale(initial=True) self.paintCanvas() self.zoomWidget.valueChanged.connect(self.paintCanvas) self.resized.connect(self.adjustScale) # camera self.camera_device = CameraDevice(video_path=cfg_priv.ICONS.BACKGROUND) self.camera_device.newFrame.connect(self.onNewImage) self.camera_device.video_time_out.connect(self.clear) # top button functions self.ui.thread1_bn.clicked.connect(self.start_camera) self.ui.thread2_bn.clicked.connect(self.start_video1) self.ui.thread3_bn.clicked.connect(self.start_video2) self.ui.thread4_bn.clicked.connect(self.start_pic) self.ui.thread5_bn.clicked.connect(self.load_video) # left button functions self.ui.play_bn.clicked.connect(self.start_cap) self.ui.pause_bn.clicked.connect(self.stop_cap) self.ui.record_bn.clicked.connect(self.save_video) self.ui.exit_bn.clicked.connect(self.close) # right button functions self.ui.model1_bn.clicked.connect(self.apply_model1) self.ui.model2_bn.clicked.connect(self.apply_model2) self.ui.model3_bn.clicked.connect(self.apply_model3) self.ui.model4_bn.clicked.connect(self.apply_model4) self.ui.model5_bn.clicked.connect(self.apply_model5) # top button functions self.ui.thread1_bn.setIcon(QIcon(cfg_priv.ICONS.TOP.LEFT1)) self.ui.thread1_bn.setIconSize( QSize(cfg_priv.ICONS.TOP.SIZE[0], cfg_priv.ICONS.TOP.SIZE[1])) self.ui.thread2_bn.setIcon(QIcon(cfg_priv.ICONS.TOP.LEFT2)) self.ui.thread2_bn.setIconSize( QSize(cfg_priv.ICONS.TOP.SIZE[0], cfg_priv.ICONS.TOP.SIZE[1])) self.ui.thread3_bn.setIcon(QIcon(cfg_priv.ICONS.TOP.LEFT3)) self.ui.thread3_bn.setIconSize( QSize(cfg_priv.ICONS.TOP.SIZE[0], cfg_priv.ICONS.TOP.SIZE[1])) self.ui.thread4_bn.setIcon(QIcon(cfg_priv.ICONS.TOP.LEFT4)) self.ui.thread4_bn.setIconSize( QSize(cfg_priv.ICONS.TOP.SIZE[0], cfg_priv.ICONS.TOP.SIZE[1])) self.ui.thread5_bn.setIcon(QIcon(cfg_priv.ICONS.TOP.LEFT5)) self.ui.thread5_bn.setIconSize( QSize(cfg_priv.ICONS.TOP.SIZE[0], cfg_priv.ICONS.TOP.SIZE[1])) # left button functions self.ui.play_bn.setIcon(QIcon(cfg_priv.ICONS.LEFT.TOP1)) self.ui.play_bn.setIconSize( QSize(cfg_priv.ICONS.LEFT.SIZE[0], cfg_priv.ICONS.LEFT.SIZE[1])) self.ui.pause_bn.setIcon(QIcon(cfg_priv.ICONS.LEFT.TOP2)) self.ui.pause_bn.setIconSize( QSize(cfg_priv.ICONS.LEFT.SIZE[0], cfg_priv.ICONS.LEFT.SIZE[1])) self.ui.record_bn.setIcon(QIcon(cfg_priv.ICONS.LEFT.TOP3)) self.ui.record_bn.setIconSize( QSize(cfg_priv.ICONS.LEFT.SIZE[0], cfg_priv.ICONS.LEFT.SIZE[1])) self.ui.empty_bn.setIcon(QIcon(cfg_priv.ICONS.LEFT.TOP4)) self.ui.empty_bn.setIconSize( QSize(cfg_priv.ICONS.LEFT.SIZE[0], cfg_priv.ICONS.LEFT.SIZE[1])) self.ui.setting_bn.setIcon(QIcon(cfg_priv.ICONS.LEFT.TOP5)) self.ui.setting_bn.setIconSize( QSize(cfg_priv.ICONS.LEFT.SIZE[0], cfg_priv.ICONS.LEFT.SIZE[1])) self.ui.exit_bn.setIcon(QIcon(cfg_priv.ICONS.LEFT.TOP6)) self.ui.exit_bn.setIconSize( QSize(cfg_priv.ICONS.LEFT.SIZE[0], cfg_priv.ICONS.LEFT.SIZE[1])) # right button icons self.ui.model1_bn.setIcon(QIcon(cfg_priv.FUNC_OPT.FUNC1.ICON)) self.ui.model1_bn.setIconSize( QSize(cfg_priv.FUNC_OPT.FUNC1.ICON_SIZE[0], cfg_priv.FUNC_OPT.FUNC1.ICON_SIZE[1])) self.ui.model2_bn.setIcon(QIcon(cfg_priv.FUNC_OPT.FUNC2.ICON)) self.ui.model2_bn.setIconSize( QSize(cfg_priv.FUNC_OPT.FUNC2.ICON_SIZE[0], cfg_priv.FUNC_OPT.FUNC2.ICON_SIZE[1])) self.ui.model3_bn.setIcon(QIcon(cfg_priv.FUNC_OPT.FUNC3.ICON)) self.ui.model3_bn.setIconSize( QSize(cfg_priv.FUNC_OPT.FUNC3.ICON_SIZE[0], cfg_priv.FUNC_OPT.FUNC3.ICON_SIZE[1])) self.ui.model4_bn.setIcon(QIcon(cfg_priv.FUNC_OPT.FUNC4.ICON)) self.ui.model4_bn.setIconSize( QSize(cfg_priv.FUNC_OPT.FUNC4.ICON_SIZE[0], cfg_priv.FUNC_OPT.FUNC4.ICON_SIZE[1])) self.ui.model5_bn.setIcon(QIcon(cfg_priv.FUNC_OPT.FUNC5.ICON)) self.ui.model5_bn.setIconSize( QSize(cfg_priv.FUNC_OPT.FUNC5.ICON_SIZE[0], cfg_priv.FUNC_OPT.FUNC5.ICON_SIZE[1])) # task special param self.image_render = GetImage() self.init_openfolder = './' self.flag_savevideo = False self.info_header = u"Hello from PriVision!\n " self.shown_info(self.info_header) self.allframes = [] self.video_writer = None self.savevideo_counting = 0 self.savevideo_max = cfg_priv.GLOBAL.SAVE_VIDEO_MAX_SECOND def setup_config(self): print('==> Using config:') merge_priv_cfg_from_file(self.cfg_file) pprint.pprint(cfg_priv) def setup_workers(self): if len(cfg_priv.FUNC_OPT.FUNC1.MODULE): func1 = importlib.import_module('modules.{}'.format( cfg_priv.FUNC_OPT.FUNC1.MODULE)) self.worker01 = eval('func1.{}(gpu_id={})'.format( cfg_priv.FUNC_OPT.FUNC1.CLASS, cfg_priv.FUNC_OPT.FUNC1.GPU_ID)) ###w print('Setup function: {}.{} at GPU: {}'.format( cfg_priv.FUNC_OPT.FUNC1.MODULE, cfg_priv.FUNC_OPT.FUNC1.CLASS, cfg_priv.FUNC_OPT.FUNC1.GPU_ID)) if len(cfg_priv.FUNC_OPT.FUNC2.MODULE): func2 = importlib.import_module('modules.{}'.format( cfg_priv.FUNC_OPT.FUNC2.MODULE)) self.worker02 = eval('func2.{}(gpu_id={})'.format( cfg_priv.FUNC_OPT.FUNC2.CLASS, cfg_priv.FUNC_OPT.FUNC2.GPU_ID)) print('Setup function: {}.{} at GPU: {}'.format( cfg_priv.FUNC_OPT.FUNC2.MODULE, cfg_priv.FUNC_OPT.FUNC2.CLASS, cfg_priv.FUNC_OPT.FUNC2.GPU_ID)) if len(cfg_priv.FUNC_OPT.FUNC3.MODULE): func3 = importlib.import_module('modules.{}'.format( cfg_priv.FUNC_OPT.FUNC3.MODULE)) self.worker03 = eval('func3.{}(gpu_id={})'.format( cfg_priv.FUNC_OPT.FUNC3.CLASS, cfg_priv.FUNC_OPT.FUNC3.GPU_ID)) print('Setup function: {}.{} at GPU: {}'.format( cfg_priv.FUNC_OPT.FUNC3.MODULE, cfg_priv.FUNC_OPT.FUNC3.CLASS, cfg_priv.FUNC_OPT.FUNC3.GPU_ID)) if len(cfg_priv.FUNC_OPT.FUNC4.MODULE): func4 = importlib.import_module('modules.{}'.format( cfg_priv.FUNC_OPT.FUNC4.MODULE)) self.worker04 = eval('func4.{}(gpu_id={})'.format( cfg_priv.FUNC_OPT.FUNC4.CLASS, cfg_priv.FUNC_OPT.FUNC4.GPU_ID)) print('Setup function: {}.{} at GPU: {}'.format( cfg_priv.FUNC_OPT.FUNC4.MODULE, cfg_priv.FUNC_OPT.FUNC4.CLASS, cfg_priv.FUNC_OPT.FUNC4.GPU_ID)) if len(cfg_priv.FUNC_OPT.FUNC5.MODULE): func5 = importlib.import_module('modules.{}'.format( cfg_priv.FUNC_OPT.FUNC5.MODULE)) self.worker05 = eval('func5.{}(gpu_id={})'.format( cfg_priv.FUNC_OPT.FUNC5.CLASS, cfg_priv.FUNC_OPT.FUNC5.GPU_ID)) print('Setup function: {}.{} at GPU: {}'.format( cfg_priv.FUNC_OPT.FUNC5.MODULE, cfg_priv.FUNC_OPT.FUNC5.CLASS, cfg_priv.FUNC_OPT.FUNC5.GPU_ID)) def resizeEvent(self, event): self.resized.emit() return super(MainWindow, self).resizeEvent(event) def update_image(self): pass def zoomRequest(self, delta): units = delta / (8 * 15) scale = 10 self.addZoom(scale * units) def scrollRequest(self, delta, orientation): units = -delta / (8 * 15) bar = self.scrollBars[orientation] bar.setValue(bar.value() + bar.singleStep() * units) def setZoom(self, value): self.actions.fitWidth.setChecked(False) self.actions.fitWindow.setChecked(False) self.zoomMode = self.MANUAL_ZOOM self.zoomWidget.setValue(value) def addZoom(self, increment=10): self.setZoom(self.zoomWidget.value() + increment) def setFitWindow(self, value=True): self.zoomMode = self.FIT_WINDOW if value else self.MANUAL_ZOOM self.adjustScale() def setFitWidth(self, value=True): if value: self.actions.fitWindow.setChecked(False) self.zoomMode = self.FIT_WIDTH if value else self.MANUAL_ZOOM self.adjustScale() def adjustScale(self, initial=False): value = self.scalers[self.FIT_WINDOW if initial else self.zoomMode]() self.zoomWidget.setValue(int(100 * value)) def scaleFitWindow(self): """Figure out the size of the pixmap in order to fit the main widget.""" e = 2.0 # So that no scrollbars are generated. w1 = self.width() * 0.65 - e h1 = self.height() * 0.65 - e a1 = w1 / h1 # Calculate a new scale value based on the pixmap's aspect ratio. w2 = self.canvas.image.width() - 0.0 h2 = self.canvas.image.height() - 0.0 a2 = w2 / h2 return w1 / w2 if a2 >= a1 else h1 / h2 def scaleFitWidth(self): # The epsilon does not seem to work too well here. w = self.centralWidget().width() / 5 * 3 - 2.0 return w / self.canvas.pixmap.width() def paintCanvas(self): self.canvas.scale = 0.01 * self.zoomWidget.value() # self.canvas.scale = 0.5 self.canvas.adjustSize() self.canvas.update() def start_cap(self): # self.ui.play_bn.setIcon(QIcon("./files/icons/icon-left/play-color.png")) self.ui.pause_bn.setIcon(QIcon(cfg_priv.ICONS.LEFT.TOP2)) self.camera_device.paused = False def stop_cap(self): self.ui.pause_bn.setIcon( QIcon(cfg_priv.ICONS.LEFT.TOP2.replace('bright', 'color'))) self.camera_device.paused = True def save_video(self): if not self.flag_savevideo: self.flag_savevideo = True self.savevideo_counting = 0 video_name = datetime.datetime.now().strftime('%Y%m%d%H%M%S') fourcc = cv2.VideoWriter_fourcc(*'MJPG') self.video_writer = cv2.VideoWriter( '{}/{}_save.avi'.format(cfg_priv.GLOBAL.SAVE_VIDEO_PATH, video_name), fourcc, cfg_priv.GLOBAL.SAVE_VIDEO_FPS, tuple(cfg_priv.GLOBAL.SAVE_VIDEO_SIZE)) self.ui.record_bn.setIcon( QIcon(cfg_priv.ICONS.LEFT.TOP3.replace('bright', 'color'))) else: self.video_writer.release() self.savevideo_counting = 0 self.flag_savevideo = False self.video_writer = None self.ui.record_bn.setIcon(QIcon(cfg_priv.ICONS.LEFT.TOP3)) pass def clear(self): self.allframes = [] def shown_info(self, info): self.ui.info_display.setPlainText(info) def set_all_func_false(self): cfg_priv.GLOBAL.F_MODEL1 = False self.ui.model1_bn.setIcon(QIcon(cfg_priv.FUNC_OPT.FUNC1.ICON)) cfg_priv.GLOBAL.F_MODEL2 = False self.ui.model2_bn.setIcon(QIcon(cfg_priv.FUNC_OPT.FUNC2.ICON)) cfg_priv.GLOBAL.F_MODEL3 = False self.ui.model3_bn.setIcon(QIcon(cfg_priv.FUNC_OPT.FUNC3.ICON)) cfg_priv.GLOBAL.F_MODEL4 = False self.ui.model4_bn.setIcon(QIcon(cfg_priv.FUNC_OPT.FUNC4.ICON)) cfg_priv.GLOBAL.F_MODEL5 = False self.ui.model5_bn.setIcon(QIcon(cfg_priv.FUNC_OPT.FUNC5.ICON)) def apply_model1(self): tmp_status = cfg_priv.GLOBAL.F_MODEL1 self.set_all_func_false() if not tmp_status: cfg_priv.GLOBAL.F_MODEL1 = True self.ui.model1_bn.setIcon( QIcon(cfg_priv.FUNC_OPT.FUNC1.ICON.replace('bright', 'color'))) def apply_model2(self): tmp_status = cfg_priv.GLOBAL.F_MODEL2 self.set_all_func_false() if not tmp_status: cfg_priv.GLOBAL.F_MODEL2 = True self.ui.model2_bn.setIcon( QIcon(cfg_priv.FUNC_OPT.FUNC2.ICON.replace('bright', 'color'))) def apply_model3(self): tmp_status = cfg_priv.GLOBAL.F_MODEL3 self.set_all_func_false() if not tmp_status: cfg_priv.GLOBAL.F_MODEL3 = True self.ui.model3_bn.setIcon( QIcon(cfg_priv.FUNC_OPT.FUNC3.ICON.replace('bright', 'color'))) def apply_model4(self): tmp_status = cfg_priv.GLOBAL.F_MODEL4 self.set_all_func_false() if not tmp_status: cfg_priv.GLOBAL.F_MODEL4 = True self.ui.model4_bn.setIcon( QIcon(cfg_priv.FUNC_OPT.FUNC4.ICON.replace('bright', 'color'))) def apply_model5(self): tmp_status = cfg_priv.GLOBAL.F_MODEL5 self.set_all_func_false() if not tmp_status: cfg_priv.GLOBAL.F_MODEL5 = True self.ui.model5_bn.setIcon( QIcon(cfg_priv.FUNC_OPT.FUNC5.ICON.replace('bright', 'color'))) def start_camera(self): self.ui.thread1_bn.setIcon( QIcon(cfg_priv.ICONS.TOP.LEFT1.replace('bright', 'color'))) self.ui.thread2_bn.setIcon(QIcon(cfg_priv.ICONS.TOP.LEFT2)) self.ui.thread3_bn.setIcon(QIcon(cfg_priv.ICONS.TOP.LEFT3)) self.ui.thread4_bn.setIcon(QIcon(cfg_priv.ICONS.TOP.LEFT4)) self.ui.thread5_bn.setIcon(QIcon(cfg_priv.ICONS.TOP.LEFT5)) self.camera_device = CameraDevice(cameraId=0) self.camera_device.newFrame.connect(self.onNewImage) self.clear() def start_video1(self): self.ui.thread1_bn.setIcon(QIcon(cfg_priv.ICONS.TOP.LEFT1)) self.ui.thread2_bn.setIcon( QIcon(cfg_priv.ICONS.TOP.LEFT2.replace('bright', 'color'))) self.ui.thread3_bn.setIcon(QIcon(cfg_priv.ICONS.TOP.LEFT3)) self.ui.thread4_bn.setIcon(QIcon(cfg_priv.ICONS.TOP.LEFT4)) self.ui.thread5_bn.setIcon(QIcon(cfg_priv.ICONS.TOP.LEFT5)) self.camera_device.set_video_path(cfg_priv.GLOBAL.VIDEO1) self.clear() def start_video2(self): self.ui.thread1_bn.setIcon(QIcon(cfg_priv.ICONS.TOP.LEFT1)) self.ui.thread2_bn.setIcon(QIcon(cfg_priv.ICONS.TOP.LEFT2)) self.ui.thread3_bn.setIcon( QIcon(cfg_priv.ICONS.TOP.LEFT3.replace('bright', 'color'))) self.ui.thread4_bn.setIcon(QIcon(cfg_priv.ICONS.TOP.LEFT4)) self.ui.thread5_bn.setIcon(QIcon(cfg_priv.ICONS.TOP.LEFT5)) self.camera_device.set_video_path(cfg_priv.GLOBAL.VIDEO2) self.clear() def start_pic(self): self.ui.thread1_bn.setIcon(QIcon(cfg_priv.ICONS.TOP.LEFT1)) self.ui.thread2_bn.setIcon(QIcon(cfg_priv.ICONS.TOP.LEFT2)) self.ui.thread3_bn.setIcon(QIcon(cfg_priv.ICONS.TOP.LEFT3)) self.ui.thread4_bn.setIcon( QIcon(cfg_priv.ICONS.TOP.LEFT4.replace('bright', 'color'))) self.ui.thread5_bn.setIcon(QIcon(cfg_priv.ICONS.TOP.LEFT5)) image_name, image_type = QFileDialog.getOpenFileName( self, "select file", self.init_openfolder, "IMAGE (*.*)") self.init_openfolder = image_name self.camera_device.set_image_path(image_name) self.clear() def load_video(self): self.ui.thread1_bn.setIcon(QIcon(cfg_priv.ICONS.TOP.LEFT1)) self.ui.thread2_bn.setIcon(QIcon(cfg_priv.ICONS.TOP.LEFT2)) self.ui.thread3_bn.setIcon(QIcon(cfg_priv.ICONS.TOP.LEFT3)) self.ui.thread4_bn.setIcon(QIcon(cfg_priv.ICONS.TOP.LEFT4)) self.ui.thread5_bn.setIcon( QIcon(cfg_priv.ICONS.TOP.LEFT5.replace('bright', 'color'))) video_name, video_type = QFileDialog.getOpenFileName( self, "select file", self.init_openfolder, "VIDEO (*.*)") self.init_openfolder = video_name self.camera_device.set_video_path(video_name) self.clear() @QtCore.pyqtSlot(np.ndarray) def onNewImage(self, frame): self.adjustScale() frame = np.asarray(frame[:, :]) t = clock() if cfg_priv.GLOBAL.F_MODEL1: vis = self.worker01(frame) elif cfg_priv.GLOBAL.F_MODEL2: vis = self.worker02(frame) elif cfg_priv.GLOBAL.F_MODEL3: vis = self.worker03(frame) elif cfg_priv.GLOBAL.F_MODEL4: vis = self.worker04(frame) elif cfg_priv.GLOBAL.F_MODEL5: vis = self.worker05(frame) else: vis = frame.copy() dt = clock() - t if self.flag_savevideo and self.savevideo_counting <= self.savevideo_max: save_im = cv2.resize(vis, tuple(cfg_priv.GLOBAL.SAVE_VIDEO_SIZE)) self.video_writer.write(save_im) self.savevideo_counting += 1 elif self.savevideo_counting > self.savevideo_max: self.savevideo_counting = 0 self.flag_savevideo = False self.ui.record_bn.setIcon(QIcon(cfg_priv.ICONS.LEFT.TOP3)) draw_str(vis, 30, 30, 'speed: %.1f fps' % (min(1.0 / dt, 30))) cur_info = self.info_header + u'--------------------\n ' if self.flag_savevideo: cur_info += u'Saving Video~~\n--------------------\n' cur_info += u'当前视频频率为: {:.1f}fps\n '.format(min(1.0 / dt, 30)) cur_info += u'--------------------\n ' self.shown_info(cur_info) vis = cv2.resize(vis, tuple(cfg_priv.GLOBAL.IM_SHOW_SIZE)) image = QImage(vis.tostring(), vis.shape[1], vis.shape[0], QImage.Format_RGB888).rgbSwapped() self.canvas.update_image(image)
class MainWindow(QMainWindow, QObject): def __init__(self, parent=None): super().__init__(parent) self.ui = Ui_MainWindow() self.ui.setupUi(self) # Все действия к прикрепляемым окнам поместим в меню for dock in self.findChildren(QDockWidget): self.ui.menuDockWindow.addAction(dock.toggleViewAction()) # Все действия к toolbar'ам окнам поместим в меню for tool in self.findChildren(QToolBar): self.ui.menuTools.addAction(tool.toggleViewAction()) self.progress_bar = QProgressBar() self.progress_bar_timer = QTimer() self.progress_bar_timer.setInterval(1000) self.progress_bar_timer.timeout.connect(lambda x=None: self.progress_bar.setValue(self.progress_bar.value() - 1)) self.progress_bar.valueChanged.connect(lambda value: self.progress_bar_timer.stop() if self.progress_bar.value() <= 0 else None) self.ui.statusbar.addWidget(self.progress_bar) # TODO: показывать историю бота: self.view.history() self.moswar_url = 'http://www.moswar.ru/' # Чтобы не было проблем запуска компов с прокси: QNetworkProxyFactory.setUseSystemConfiguration(True) QWebSettings.globalSettings().setAttribute(QWebSettings.DeveloperExtrasEnabled, True) self.ui.view.urlChanged.connect(lambda x: self.ui.url_le.setText(x.toString())) self.ui.view.linkClicked.connect(lambda x: self.ui.url_le.setText(x.toString())) self.ui.pushButtonBackWebPage.clicked.connect(self.ui.view.back) # При клике на кнопку, мы получаем значение data текущего элемента и вызываем функцию, хранящуюся там self.ui.run_pb.clicked.connect(lambda: self.ui.commands_cb.itemData(self.ui.commands_cb.currentIndex())()) self.thimblerig = Thimblerig(self) self.fight = Fight(self) self.restore_hp = RestoreHP(self) self.factory_petric = FactoryPetric(self) self.shaurburgers = Shaurburgers(self) self.patrol = Patrol(self) # Список действий бота self.name_action_dict = { 'Закоулки': self.alley, 'Площадь': self.square, 'Метро': self.metro, 'Завод': self.factory, 'Задания': self.jobs, 'Персонаж': self.player, 'Хата': self.home, 'Игра в наперстки': self.thimblerig.run, 'Напасть': self.fight.run, 'Ищем следующего противника': self.fight._next_enemy, 'Восстановление жизней': self.restore_hp.run, 'Варка нано-петриков': self.factory_petric.run, 'Убрать таймаут Тонусом': self.fight.use_tonus, 'Шаурбургерс': self.shaurburgers.go, 'Работать в Шаурбургерсе': self.shaurburgers.run, 'Патрулировать': self.patrol.run, } # Добавляем команды for command in sorted(self.name_action_dict): self.ui.commands_cb.addItem(command, self.name_action_dict[command]) # Выполнение кода в окне "Выполнение скрипта" self.ui.button_exec.clicked.connect(lambda x=None: exec(self.ui.code.toPlainText())) # Таймер используемый для вызова функции для запуска задач self._task_timer = QTimer() self._task_timer.setSingleShot(True) self._task_timer.timeout.connect(self._task_tick) self.ui.actionStartTimer.triggered.connect(self._task_tick) self.ui.actionStopTimer.triggered.connect(self._task_timer.stop) self.ui.actionStopTimer.triggered.connect(self.progress_bar_timer.stop) # Если стоит True -- происходит выполнение задачи и функция _task_tick прерывается self._used = False # Название процесса, из-за которого в данный момент _task_tick не может выполниться self._used_process = None # Минимальная сумма для игры в Наперстки self.min_money_for_thimblerig = 200000 def _task_tick(self): """Функция для запуска задач.""" if self._used: logger.debug('Запуск задач отменяется -- процесс занят "%s".', self._used_process) else: logger.debug('Запуск задач.') try: # Если уже играем в Наперстки или набрали нужную сумму для игры в Наперстки if 'thimble' in self.current_url() or self.money() >= self.min_money_for_thimblerig: self.thimblerig.run() elif self.shaurburgers.is_ready(): self.shaurburgers.run() elif self.patrol.is_ready(): self.patrol.run() elif self.factory_petric.is_ready(): self.factory_petric.run() elif self.fight.is_ready(): self.fight.run() except MoswarClosedError as e: logger.warn(e) # В случаи закрытия сайт, каждый час проверяем interval = 60 * 60 * 1000 except MoswarBotError as e: logger.error(e) # Возможно, в следующий раз ошибки не будет interval = 1 * 1000 except Exception as e: logger.error(e) # Возможно, в следующий раз ошибки не будет interval = 1 * 1000 import traceback traceback.print_exc() else: # TODO: настраивать interval: спрашивать у другиз модулей их таймауты (если есть) и выбирать # наименьший, он и будет interval. Если же interval не был изменен, то задавать рандомное время # Это позволит увеличить эффективность бота # Запускаем таймер выполнение задач # Следующий вызов будет случайным от 3 до 10 минут + немного случайных секунд interval = int((randint(3, 10) + random()) * 60 * 1000) self._start_task_timer(interval) def _start_task_timer(self, interval): secs = interval / 1000 logger.debug('Повторный запуск задач через %s секунд.', secs) self._task_timer.start(interval) self.progress_bar.setRange(0, secs) self.progress_bar.setValue(secs) self.progress_bar_timer.start() def _get_doc(self): return self.ui.view.page().mainFrame().documentElement() doc = property(_get_doc) def current_url(self): """Функция возвращает текущий адрес страницы.""" return self.ui.view.url().toString() def wait_loading(self): """Функция ожидания загрузки страницы. Использовать только при изменении url.""" logger.debug('Начинаю ожидание загрузки страницы.') # Ждем пока прогрузится страница loop = QEventLoop() self.ui.view.loadFinished.connect(loop.quit) loop.exec_() logger.debug('Закончено ожидание загрузки страницы.') def go(self, relative_url): """Функция для загрузки страниц. Если вызывать без параметров, то загрузит основную страницу. Если указывать relative_url, то он будет присоединен к адресу мосвара. Функция ожидание окончания загрузки страницы. Выбрасывает исключение MoswarClosedError, когда сайта закрыт (closed.html) """ url = urljoin(self.moswar_url, relative_url) logger.debug('Перехожу по адресу "%s"', url) self.ui.view.load(url) self.wait_loading() # TODO: вынести обработку переадресаций в отдельную функцию # Проверяем, что не случилось переадресации. Она возможна, например, при игре # в наперстки или попадании в милицию current_url = self.current_url() # Сравниваем url'ы между собой. Такая проверка для обхода ситуации, когда QWebView отдает url # со слешем на конце. Если сравнить их обычной проверкой (== или !=), то это будет неправильно. # http://www.moswar.ru/shaurburgers/ # # А сравниваем с: # http://www.moswar.ru/shaurburgers equal = url in current_url or current_url in url # Если адреса не равны if not equal: self.slog(url + " -> " + current_url) self.slog('Текущий заголовок: "{}"'.format(self.title())) logger.warn('Похоже, случилась переадресация: шли на %s, а попали на %s.', url, current_url) # TODO: Для http://www.moswar.ru/closed.html описывать причину -- брать из auth() # Проверка на временное отсутствие доступа к сайту if 'closed.html' in current_url: reason = self.doc.toPlainText().strip() logger.warn('Закрыто, причина:\n%s', reason) raise MoswarClosedError(reason) # TODO: руды может не хватать, поэтому предусмотреть ситуацию, когда придется платить деньгами # Обработка ситуации: Задержка за бои # url полиции police, но url'ы иногда неправильно возвращаются, поэтому надежнее смотреть # на заголовок страницы if self.title() == 'Милиция': logger.debug('Задержаны в милиции.') # Ищем кнопку для налаживания связей рудой button = self.doc.findFirst('.police-relations .button') if not button.isNull(): logger.debug('Плачу взятку рудой.') # Нажать на кнопку что-то не получается, поэтому просто шлем запрос, # который и так бы отослался при клике на кнопку self.go('police/relations') # TODO: если новый уровень выпал в момент выполнения задания, то возможна такая неприятная # ситуация: попадаем на is_ready таски, делается переход к локации такси, перенапрявляет нас # на страницу поздравления, мы это определяем, кликаем на кнопку, в этот момент is_ready # возвращает True, и мы попадаем в функцию выполнения, которая снова переходит на страницу локации # и снова нас перенапрявляет, мы это определяем, кликаем и это так может случится несколько раз # TODO: возвращать признак перенаправления и по нему таска сама решает -- отменить или нет свое # выполнение # # Проверка на новый уровень if 'quest' in current_url: level_up = self.doc.findFirst('.levelup') if not level_up.isNull(): # Показать столько побед / награблено for td in level_up.findAll('td'): logger.debug('Получен новый уровень! Результат:\n' + ' '.join(td.toPlainText().split())) # Ищем кнопку 'Вперед, к новым победам!' и кликаем на нее button = self.doc.findFirst('.levelup .button') if button.isNull(): raise MoswarButtonIsMissError('Вперед, к новым победам!') button.evaluateJavaScript('this.click()') def auth(self): """Функция загружает страницу мосвара, заполняет поля логина и пароля и нажимает на кнопку Войти. После нажатия на Войти происходит ожидание загрузки страницы. """ logger.debug('Авторизуюсь.') # Открываем страницу мосвара url = self.moswar_url logger.debug('Перехожу по адресу "%s"', url) self.ui.view.load(url) self.wait_loading() # Если закрыт доступ к сайту if 'closed.html' in self.current_url(): logger.warn('Закрыто, причина:\n%s', self.doc.toPlainText().strip()) # Попробуем снова авторизоваться через 1 час QTimer.singleShot(60 * 60 * 1000, self.auth) return login = self.doc.findFirst('#login-email') password = self.doc.findFirst('#login-password') if login.isNull() or password.isNull(): raise MoswarAuthError('Не найдены поля логина и пароля.') login.setAttribute("value", LOGIN) password.setAttribute("value", PASSWORD) submit = self.doc.findFirst("input[type=submit]") if submit.isNull(): raise MoswarButtonIsMissError('Войти') logger.debug('Захожу в игру.') submit.evaluateJavaScript("this.click()") self.wait_loading() logger.debug('Запуск таймера выполнения задач.') # Выполнение первых задач self._task_tick() def alley(self): self.go('alley') def square(self): self.go('square') def factory(self): self.go('factory') def metro(self): self.go('metro') def jobs(self): self.go('nightclub/jobs') def player(self): self.go('player') def home(self): self.go('home') def name(self): """Функция возвращает имя текущего персонажа.""" try: css_path = '#personal .name' name = self.doc.findFirst(css_path).toPlainText() name = name[:name.rindex('[')] return name.strip() except Exception as e: raise MoswarElementIsMissError(e) def money(self): """Функция возвращает количество денег персонажа.""" try: css_path = '.tugriki-block' tugriki = self.doc.findFirst(css_path) tugriki = tugriki.attribute('title') tugriki = tugriki.split(': ')[-1] return int(tugriki) except Exception as e: raise MoswarElementIsMissError(e) def current_hp(self): """Функция возвращает текущее количество жизней персонажа.""" try: css_path = '#personal #currenthp' hp = self.doc.findFirst(css_path) hp = hp.toPlainText() return int(hp) except Exception as e: raise MoswarElementIsMissError(e) def max_hp(self): """Функция возвращает текущее количество жизней персонажа.""" try: hp = self.doc.findFirst('#personal #maxhp') hp = hp.toPlainText() return int(hp) except Exception as e: raise MoswarElementIsMissError(e) def level(self): """Функция возвращает уровень персонажа.""" try: level = self.doc.findFirst('#personal b').toPlainText() level = level.split()[-1] level = level.replace('[', '').replace(']', '') return int(level) except Exception as e: raise MoswarElementIsMissError(e) def title(self): """Функция возвращает заголовок текущей страницы.""" title = self.doc.findFirst('head title') if title.isNull(): logger.warn('Не найден заголовок текущей страницы (%s).', self.current_url()) return title.toPlainText() # TODO: добавить возможность выбрать область поиска элемента для клика, а то она все время вся страница -- self.doc def click_tag(self, css_path): """Функция находит html тег по указанному пути и эмулирует клик на него. Строки в css_path нужно оборачивать в апострофы. Пример: # Кликаем на кнопку "Отнять у слабого" self.click_tag("div[class='button-big btn f1']") # Кликаем на кнопку "Искать другого" self.click_tag(".button-search a") """ logger.debug('Выполняю клик по тегу: %s', css_path) # Используем для клика jQuery code = """ tag = $("{}"); tag.click();""".format(css_path) ok = self.doc.evaluateJavaScript(code) if ok is None: logger.warn('Выполнение js скрипта неудачно. Code:\n' + code) def alert(self, text): """Функция показывает окно сообщений в браузере, используя javascript функцию alert.""" self.doc.evaluateJavaScript('alert("{}")'.format(text)) def slog(self, *args, **kwargs): """Функция для добавления текста в виджет-лог, находящегося на форме.""" # Используем стандартный print для печати в строку str_io = io.StringIO() kwargs['file'] = str_io kwargs['end'] = '' print(*args, **kwargs) text = str_io.getvalue() self.ui.simple_log.appendPlainText(text) def read_settings(self): # TODO: при сложных настройках, лучше перейти на json или yaml config = QSettings(CONFIG_FILE, QSettings.IniFormat) self.restoreState(config.value('MainWindow_State')) self.restoreGeometry(config.value('MainWindow_Geometry')) def write_settings(self): config = QSettings(CONFIG_FILE, QSettings.IniFormat) config.setValue('MainWindow_State', self.saveState()) config.setValue('MainWindow_Geometry', self.saveGeometry()) def closeEvent(self, *args, **kwargs): self.write_settings() super().closeEvent(*args, **kwargs)
class MainWindow(QMainWindow): ui = None mainWindow = None client = WudaoClient() painter = GuiDraw() draw_conf = True is_zh = False word = '' def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.history_manager = UserHistory() self.setup_ui() def setup_ui(self): self.ui = Ui_MainWindow() self.ui.setupUi(self) # auto complete self.auto_com_init() self.ui.ol_cb.setChecked(False) darkula = QPalette() # theme darkula.setColor(QPalette.Background, QColor('#300A24')) darkula.setColor(QPalette.Base, QColor('#300A24')) self.ui.textBrowser.setPalette(darkula) # status bar self.ui.statusbar.showMessage('@2016 Chestnut Studio') # signal slot self.ui.lineEdit.returnPressed.connect(self.search_bt_clicked) self.ui.search_b.clicked.connect(self.search_bt_clicked) self.ui.detail_rb.clicked.connect(self.detail_rb_clicked) self.ui.intro_rb.clicked.connect(self.intro_rb_clicked) def detail_rb_clicked(self): self.draw_conf = True self.search_bt_clicked() def intro_rb_clicked(self): self.draw_conf = False self.search_bt_clicked() # auto complete def auto_com_init(self): sl = ['a', 'air', 'airplane'] com = QCompleter(sl) com.setCaseSensitivity(Qt.CaseInsensitive) self.ui.lineEdit.setCompleter(com) def search_bt_clicked(self): self.word = self.ui.lineEdit.text().strip() if self.word: # if chinese if is_alphabet(self.word[0]): self.is_zh = False else: self.is_zh = True # query on server server_context = self.client.get_word_info(self.word).strip() if server_context != 'None': wi = json.loads(server_context) self.painter.html = '' if self.is_zh: self.painter.draw_zh_text(wi, self.draw_conf) else: self.history_manager.add_item(self.word) self.painter.draw_text(wi, self.draw_conf) self.ui.textBrowser.setHtml(self.painter.html) else: # Online search html = '' if self.ui.ol_cb.isChecked(): self.painter.html = '' try: self.ui.textBrowser.setHtml(self.painter.P_W_PATTERN % 'Searching OL...') from src.WudaoOnline import get_text, get_zh_text from urllib.error import URLError if self.is_zh: word_info = get_zh_text(self.word) else: word_info = get_text(self.word) if not word_info['paraphrase']: html += self.painter.P_W_PATTERN % ( 'No such word: %s found online' % self.word) if not self.is_zh: self.history_manager.add_word_info(word_info) self.painter.draw_text(word_info, self.draw_conf) else: self.painter.draw_zh_text(word_info, self.draw_conf) self.ui.textBrowser.setHtml(self.painter.html) return except ImportError: html += self.painter.P_W_PATTERN % 'You need install bs4 first.' html += self.painter.P_W_PATTERN % 'Use \'pip3 install bs4\' or get bs4 online.' except URLError: html += self.painter.P_W_PATTERN % 'No Internet : Please check your connection first' else: # search in online cache first word_info = self.history_manager.get_word_info(self.word) if word_info: self.history_manager.add_item(self.word) self.painter.draw_text(word_info, self.draw_conf) self.ui.textBrowser.setHtml(self.painter.html) return else: html += self.painter.P_W_PATTERN % ( 'Error: no such word :' + self.word) html += self.painter.P_W_PATTERN % 'You can check Online Box to search it online.' self.ui.textBrowser.setHtml(html)
class MainWindow(QMainWindow): def __init__(self): super().__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) # Все действия к прикрепляемым окнам поместим в меню for dock in self.findChildren(QDockWidget): self.ui.menuDockWindow.addAction(dock.toggleViewAction()) # Все действия к toolbar'ам окнам поместим в меню for tool in self.findChildren(QToolBar): self.ui.menuTools.addAction(tool.toggleViewAction()) self.model = QStandardItemModel() self.clear_model() self.ui.treeView.setModel(self.model) self.ui.treeView.clicked.connect(lambda: self.show_info_in_status_bar) self.ui.treeView.doubleClicked.connect(lambda: self.show_in_explorer()) self.ui.button_select_dir.clicked.connect(self.select_dir) self.ui.action_go.triggered.connect(self.fill) self.ui.action_show_in_explorer.triggered.connect( lambda: self.show_in_explorer()) self.ui.action_apply_filter.triggered.connect(self.slot_remove_dirs) self.ui.label_root_dir.setText(self.ui.line_edit_dir_path.text()) self.ui.action_apply_filter.setEnabled(False) self.read_settings() def update_states(self): pass def show_in_explorer(self, index=None): if index is None: index = self.ui.treeView.currentIndex() if index is None: return row = self.get_row_item_from_index(index) if row is None: return # TODO: Qt.UserRole + 1 path = row[0].data(Qt.UserRole + 1) cmd = 'Explorer /n,"{}"'.format(path) logger.debug('Command: %s.', cmd) os.system(cmd) def select_dir(self): dir_path = QFileDialog.getExistingDirectory( self, None, self.ui.line_edit_dir_path.text()) if dir_path: self.ui.line_edit_dir_path.setText(dir_path) def get_row_item_from_index(self, index): if index is None or not index.isValid: logger.warn('get_row_from_index: invalid index: %s.', index) return row = index.row() item = self.model.itemFromIndex(index) if item is None: return parent = item.parent() if parent is None: parent = self.model.invisibleRootItem() return [parent.child(row, i) for i in range(self.model.columnCount())] def show_info_in_status_bar(self, index): row = self.get_row_item_from_index(index) if row is None: return path, size = row # TODO: Лучше дать конкретные константные имена, чем так: Qt.UserRole + 1 / Qt.UserRole + 2 self.ui.statusbar.showMessage('{} ({} / {} bytes)'.format( path.data(Qt.UserRole + 1), size.data(Qt.UserRole + 1), size.data(Qt.UserRole + 2))) def clear_model(self): self.model.clear() header_labels = ['Name', 'Size'] self.model.setColumnCount(len(header_labels)) self.model.setHorizontalHeaderLabels(header_labels) def remove_dirs(self, root): """Удаление элементов, у которых размер не совпадает с фильтром""" for row in reversed(range(root.rowCount())): child = root.child(row, 1) filter_size = self.ui.line_edit_filter.text() if not check_filter_size_eval( filter_size, get_bytes(child.data(Qt.UserRole + 1))): root.removeRow(child.row()) else: self.remove_dirs(root.child(row, 0)) def slot_remove_dirs(self): self.ui.action_apply_filter.setEnabled(False) self.remove_dirs(self.model.invisibleRootItem()) def fill(self): self.ui.action_go.setEnabled(False) self.clear_model() dir_path = self.ui.line_edit_dir_path.text() if not dir_path or not os.path.exists(dir_path): QMessageBox.information(self, 'Info', 'Choose dir path!') return filter_size = self.ui.line_edit_filter.text() if not filter_size: logger.debug('filter_size is empty. Setting default filter_size.') filter_size = "{size} >= %1GB%" logger.debug('filter_size: %s.', filter_size) t = time.clock() # Соберем список папок dir_list = [ os.path.join(dir_path, entry) for entry in os.listdir(dir_path) if os.path.isdir(os.path.join(dir_path, entry)) ] for entry in dir_list: self.dir_size_bytes(entry, self.model.invisibleRootItem(), filter_size) self.ui.action_apply_filter.setEnabled(True) if self.ui.check_box_auto_apply_filter.isChecked(): self.slot_remove_dirs() self.ui.action_apply_filter.setEnabled(False) t = time.clock() - t logger.debug('Done! Elapsed time {:.2f} sec.'.format(t)) self.ui.action_go.setEnabled(True) QMessageBox.information(self, 'Info', 'Done!\n\nElapsed time {:.2f} sec.'.format(t)) def dir_size_bytes(self, dir_path, root_item, filter_size, level=0): dir_path = QDir.toNativeSeparators(dir_path) it = QDirIterator( dir_path, QDir.AllEntries | QDir.NoDotAndDotDot | QDir.Hidden | QDir.System) sizes = 0 path_short_name = os.path.split(dir_path) path_short_name = path_short_name[1] if path_short_name[ 1] else path_short_name[0] row = [QStandardItem(path_short_name), QStandardItem('-')] row[0].setData(dir_path) row[1].setText('-') row[1].setData('-') row[0].setEditable(False) row[1].setEditable(False) root_item.appendRow(row) while it.hasNext(): file_name = it.next() file = QFileInfo(file_name) if file.isDir(): size = self.dir_size_bytes(file_name, row[0], filter_size, level + 1) else: size = file.size() sizes += size qApp.processEvents() text_size = pretty_file_size(sizes)[1] row[1].setText(text_size) row[1].setData(text_size) row[1].setData(str(sizes), Qt.UserRole + 2) return sizes def read_settings(self): config = QSettings(CONFIG_FILE, QSettings.IniFormat) mainwindow_state = config.value('MainWindow_State') if mainwindow_state: self.restoreState(mainwindow_state) mainwindow_geometry = config.value('MainWindow_Geometry') if mainwindow_geometry: self.restoreGeometry(mainwindow_geometry) dir_path = config.value('Dir_path', None) if not dir_path: dir_path = "C:\\" self.ui.line_edit_dir_path.setText(dir_path) filter_size = config.value('Filter_size', None) if not filter_size: filter_size = "{size} >= %1GB%" self.ui.line_edit_filter.setText(filter_size) self.ui.check_box_auto_apply_filter.setChecked( 'true' in config.value('Auto_apply_filter', 'true').lower()) def write_settings(self): config = QSettings(CONFIG_FILE, QSettings.IniFormat) config.setValue('MainWindow_State', self.saveState()) config.setValue('MainWindow_Geometry', self.saveGeometry()) config.setValue('Dir_path', self.ui.line_edit_dir_path.text()) config.setValue('Filter_size', self.ui.line_edit_filter.text()) config.setValue( 'Auto_apply_filter', 'true' if self.ui.check_box_auto_apply_filter.isChecked() else 'false') def closeEvent(self, event): self.write_settings() quit()
class Window(QMainWindow): def __init__(self): super().__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) # fix stuff impossible to do in qtdesigner # remove dock titlebar for addressbar w = QWidget() self.ui.addrDockWidget.setTitleBarWidget(w) # add view actions in menu bar self.ui.menuView.addAction(self.ui.treeDockWidget.toggleViewAction()) self.ui.menuView.addAction(self.ui.attrDockWidget.toggleViewAction()) self.ui.menuView.addAction(self.ui.refDockWidget.toggleViewAction()) self.ui.menuView.addAction(self.ui.logDockWidget.toggleViewAction()) # we only show statusbar in case of errors self.ui.statusBar.hide() # setup QSettings for application and get a settings object QCoreApplication.setOrganizationName("UniCT") QCoreApplication.setApplicationName("OpcUaClient") self.settings = QSettings() self._address_list = self.settings.value("address_list", [ "opc.tcp://localhost:4334/UA/NodeServer", "opc.tcp://localhost:51210/UA/SampleServer", "Clear all..." ]) print("ADR", self._address_list) self._address_list_max_count = int( self.settings.value("address_list_max_count", 10)) self.opc_ua_client = OpcUaClient() # URL ComboBox address_list_len = len(self._address_list) for index in range(address_list_len): self.ui.addrComboBox.insertItem(index, self._address_list[index]) icon = "icons/server.svg" if index < address_list_len - 1 else "icons/x.svg" self.ui.addrComboBox.setItemIcon(index, QIcon(icon)) self.ui.addrComboBox.currentTextChanged.connect(self.clear_addresses) self.ui.addrComboBox.lineEdit().returnPressed.connect( self.handle_connect) self.ui.addrComboBox.setCompleter(None) # Objects Tree self.tree_ui = TreeWidget(self.ui.treeView, self.opc_ua_client.custom_objects) self.tree_ui.error.connect(self.show_error) self.setup_context_menu_tree() self.ui.treeView.selectionModel().selectionChanged.connect( self.show_refs) self.ui.treeView.selectionModel().selectionChanged.connect( self.show_attrs) # Context Menu self.ui.actionCopyPath.triggered.connect(self.tree_ui.copy_path) self.ui.actionCopyNodeId.triggered.connect(self.tree_ui.copy_nodeid) self.ui.actionCall.triggered.connect(self.call_method) self.ui.actionReload.triggered.connect(self.tree_ui.reload_current) self.ui.actionAddMonitoredItem.triggered.connect( self.add_monitored_item) self.ui.actionDeleteMonitoredItem.triggered.connect( self.delete_monitored_item) # populate contextual menu self.addAction(self.ui.actionAddMonitoredItem) self.addAction(self.ui.actionDeleteMonitoredItem) # References Widget self.refs_ui = RefsWidget(self.ui.refView) self.refs_ui.error.connect(self.show_error) # Attributes Widget self.attrs_ui = AttrsWidget(self.ui.attrView) self.attrs_ui.error.connect(self.show_error) self._contextMenu.addSeparator() self._contextMenu.addAction(self.ui.actionReload) self.ui.attrRefreshButton.clicked.connect(self.show_attrs) # Tabs Widget self.ui.tabWidget.tabBar().tabButton(0, QTabBar.RightSide).resize(0, 0) self.ui.tabWidget.setTabEnabled(0, False) self.ui.noSubLabel.hide() self.subTabs = [] self.datachange_uis = [] self.previous_index = -1 self.ui.tabWidget.tabBarClicked.connect(self.add_sub_tab) self.ui.tabWidget.currentChanged.connect(self.restore_index) self.ui.tabWidget.tabCloseRequested.connect(self.remove_sub_tab) # Connection Buttons self.ui.connectButton.clicked.connect(self.handle_connect) # self.ui.treeView.expanded.connect(self._fit) self.ui.settingsButton.clicked.connect( self.show_connect_settings_dialog) # Main Window self.resize(int(self.settings.value("main_window_width", 800)), int(self.settings.value("main_window_height", 600))) data = self.settings.value("main_window_state", None) if data: self.restoreState(data) def createPopupMenu(self): self.popup = QMenu() self.popup.addActions(self.ui.menuView.actions()) return self.popup def add_sub_tab(self, index): if self.ui.tabWidget.isTabEnabled( index) and index == self.ui.tabWidget.count() - 1: uri = self.ui.addrComboBox.currentText() self.opc_ua_client.load_subscription_settings(uri) # Init Dialog with current settings dia = SubSettingsDialog( self.opc_ua_client.requestedPublishingInterval, self.opc_ua_client.requestedMaxKeepAliveCount, self.opc_ua_client.requestedLifetimeCount, self.opc_ua_client.maxNotificationsPerPublish, self.opc_ua_client.priority) ret = dia.exec_() if ret: self.opc_ua_client.requestedPublishingInterval, self.opc_ua_client.requestedMaxKeepAliveCount, \ self.opc_ua_client.requestedLifetimeCount, self.opc_ua_client.maxNotificationsPerPublish, \ self.opc_ua_client.priority = dia.get_selected_options() self.opc_ua_client.save_subscription_settings(uri) subTab = SubTab() self.ui.tabWidget.insertTab(index, subTab, f"Sub{index + 1}") self.ui.tabWidget.setTabToolTip(index, self.get_sub_tooltip()) data_change_ui = DataChangeUI(self, self.opc_ua_client, subTab.subView) data_change_ui.create_subscription() self.subTabs.append(subTab) self.datachange_uis.append(data_change_ui) else: self.previous_index = self.get_current_tab_index() def restore_index(self, index): if index == self.ui.tabWidget.count( ) - 1 and self.previous_index != -1: self.ui.tabWidget.setCurrentIndex(self.previous_index) self.previous_index = -1 def get_sub_tooltip(self): return f"PublishingInterval = {self.opc_ua_client.requestedPublishingInterval}\nKeepAliveCount = {self.opc_ua_client.requestedMaxKeepAliveCount}\nLifetimeCount = {self.opc_ua_client.requestedLifetimeCount}\nMaxNotificationsPerPublish = {self.opc_ua_client.maxNotificationsPerPublish}\nPriority = {self.opc_ua_client.priority}" def get_monitored_item_tooltip(self): tooltip = f"SamplingInterval = {self.opc_ua_client.samplingInterval}\nQueueSize = {self.opc_ua_client.queueSize}\nDiscardOldest = {self.opc_ua_client.discardOldest}\nDataChangeFilter = {self.opc_ua_client.dataChangeFilter}" if not self.opc_ua_client.dataChangeFilter: return tooltip datachange_trigger = ua.DataChangeTrigger( self.opc_ua_client.dataChangeTrigger).name deadband_type = ua.DeadbandType(self.opc_ua_client.deadbandType).name if deadband_type == "None_": filter_info = f"\nDataChangeTrigger = {datachange_trigger}\nDeadBandType = None" else: filter_info = f"\nDataChangeTrigger = {datachange_trigger}\nDeadBandType = {deadband_type}\nDeadBandValue = {self.opc_ua_client.deadbandValue}" return tooltip + filter_info def remove_sub_tab(self, index): self.datachange_uis[index].delete_subscription(index) del self.datachange_uis[index] self.ui.tabWidget.removeTab(index) del self.subTabs[index] if index == self.ui.tabWidget.count() - 1: self.ui.tabWidget.setCurrentIndex(index - 1) @trycatchslot def show_connect_settings_dialog(self): uri = self.ui.addrComboBox.currentText() try: # Query Endpoints endpoints = self.opc_ua_client.get_endpoints(uri) # Load security settings self.opc_ua_client.load_security_settings(uri) # Init Dialog with current settings dia = ConnectSettingsDialog(endpoints, self.opc_ua_client.security_mode, self.opc_ua_client.security_policy, self.opc_ua_client.certificate_path, self.opc_ua_client.private_key_path) ret = dia.exec_() if ret: self.opc_ua_client.security_mode, self.opc_ua_client.security_policy, self.opc_ua_client.certificate_path, self.opc_ua_client.private_key_path = dia.get_selected_options( ) self.opc_ua_client.save_security_settings(uri) self.connect() except Exception as ex: self.ui.addrComboBox.setFocus() self.show_error(ex) raise @trycatchslot def show_refs(self, selection): if isinstance(selection, QItemSelection): if not selection.indexes(): # no selection return node = self.get_current_node() if node: self.refs_ui.show_refs(node) @trycatchslot def show_attrs(self, selection): if isinstance(selection, QItemSelection): if not selection.indexes(): # no selection return node = self.get_current_node() if node: self.attrs_ui.show_attrs(node) def show_error(self, msg): logger.warning("showing error: %s") self.ui.statusBar.show() self.ui.statusBar.setStyleSheet( "QStatusBar { background-color : red; color : black; }") self.ui.statusBar.showMessage(str(msg)) QTimer.singleShot(1500, self.ui.statusBar.hide) def get_current_node(self, idx=None): return self.tree_ui.get_current_node(idx) def handle_connect(self): if self.ui.connectButton.text() == "Connect": self.connect() else: self.disconnect() @trycatchslot def connect(self): self.ui.connectButton.setText("Connecting...") self.ui.connectButton.setEnabled(False) self.ui.connectButton.repaint() uri = self.ui.addrComboBox.currentText() self.opc_ua_client.load_security_settings(uri) try: # Connect self.opc_ua_client.connect(uri) # Show widgets self._update_address_list(uri) self.opc_ua_client.load_custom_objects() self.tree_ui.set_root_node( self.opc_ua_client.client.get_root_node()) self.ui.treeView.setFocus() self.load_current_node() self.ui.connectButton.setText("Disconnect") self.ui.connectButton.setEnabled(True) self.ui.settingsButton.setEnabled(False) self.ui.addrComboBox.setEnabled(False) self.ui.tabWidget.setTabEnabled(0, True) self.ui.noSubLabel.show() except Exception as ex: self.ui.connectButton.setText("Connect") self.ui.connectButton.setEnabled(True) self.ui.addrComboBox.setFocus() self.show_error(ex) raise def get_current_tab_index(self): return self.ui.tabWidget.currentIndex() def add_monitored_item(self, node=None): if not isinstance(node, Node): node = self.get_current_node() if node is None: return index = self.get_current_tab_index() if node in self.datachange_uis[index].subscribed_nodes: logger.warning("already subscribed to node: %s ", node) return uri = self.ui.addrComboBox.currentText() self.opc_ua_client.load_monitored_items_settings(uri) idx = self.ui.tabWidget.currentIndex() # Init Dialog with current settings dia = MiSettingsDialog(self.opc_ua_client.publishingIntervals[idx], self.opc_ua_client.queueSize, self.opc_ua_client.discardOldest, self.opc_ua_client.dataChangeFilter, self.opc_ua_client.dataChangeTrigger, self.opc_ua_client.deadbandType, self.opc_ua_client.deadbandValue) ret = dia.exec_() if ret: self.opc_ua_client.samplingInterval, self.opc_ua_client.queueSize, self.opc_ua_client.discardOldest, \ self.opc_ua_client.dataChangeFilter, self.opc_ua_client.dataChangeTrigger, self.opc_ua_client.deadbandType, \ self.opc_ua_client.deadbandValue = dia.get_selected_options() self.opc_ua_client.save_monitored_items_settings(uri) self.datachange_uis[index].add_monitored_item(index, node) def delete_monitored_item(self): index = self.get_current_tab_index() self.datachange_uis[index].delete_monitored_item(index) def _update_address_list(self, uri): if uri in self._address_list: self._address_list.remove(uri) self._address_list.insert(0, uri) if len(self._address_list) > self._address_list_max_count: self._address_list.pop(-2) # update combo box self.ui.addrComboBox.clear() address_list_len = len(self._address_list) for index in range(address_list_len): self.ui.addrComboBox.insertItem(index, self._address_list[index]) icon = "icons/server.svg" if index < address_list_len - 1 else "icons/x.svg" self.ui.addrComboBox.setItemIcon(index, QIcon(icon)) def clear_addresses(self, text): if text == "Clear all...": for _ in range(len(self._address_list) - 1): self._address_list.pop(0) self.ui.addrComboBox.removeItem(0) self.ui.addrComboBox.clearEditText() def disconnect(self): try: self.opc_ua_client.delete_subscriptions() self.opc_ua_client.disconnect() except Exception as ex: self.show_error(ex) raise finally: self.save_current_node() self.tree_ui.clear() self.attrs_ui.clear() self.refs_ui.clear() for _ in range(self.ui.tabWidget.count() - 1): self.ui.tabWidget.removeTab(0) self.datachange_uis = [] self.subTabs = [] self.ui.connectButton.setText("Connect") self.ui.settingsButton.setEnabled(True) self.ui.addrComboBox.setEnabled(True) self.ui.noSubLabel.hide() self.ui.tabWidget.setTabEnabled(0, False) self.ui.addrComboBox.setFocus() def closeEvent(self, event): self.tree_ui.save_state() self.attrs_ui.save_state() self.refs_ui.save_state() self.settings.setValue("main_window_width", self.size().width()) self.settings.setValue("main_window_height", self.size().height()) self.settings.setValue("main_window_state", self.saveState()) self.settings.setValue("address_list", self._address_list) self.disconnect() event.accept() def save_current_node(self): current_node = self.get_current_node() if current_node: mysettings = self.settings.value("current_node", None) if mysettings is None: mysettings = {} uri = self.ui.addrComboBox.currentText() mysettings[uri] = current_node.nodeid.to_string() self.settings.setValue("current_node", mysettings) def load_current_node(self): mysettings = self.settings.value("current_node", None) if mysettings is None: return uri = self.ui.addrComboBox.currentText() if uri in mysettings: nodeid = ua.NodeId.from_string(mysettings[uri]) node = self.opc_ua_client.client.get_node(nodeid) self.tree_ui.expand_to_node(node) def setup_context_menu_tree(self): self.ui.treeView.setContextMenuPolicy(Qt.CustomContextMenu) self.ui.treeView.customContextMenuRequested.connect( self._show_context_menu_tree) self._contextMenu = QMenu() self.addAction(self.ui.actionCopyPath) self.addAction(self.ui.actionCopyNodeId) self._contextMenu.addSeparator() self._contextMenu.addAction(self.ui.actionCall) self._contextMenu.addSeparator() def addAction(self, action): self._contextMenu.addAction(action) def _show_context_menu_tree(self, position): node = self.get_current_node() if node: self._update_actions_state(node) self._contextMenu.exec_( self.ui.treeView.viewport().mapToGlobal(position)) @trycatchslot def _update_actions_state(self, node): # Method action self.ui.actionCall.setEnabled( node.get_node_class() == ua.NodeClass.Method) # DataChange actions if node.get_node_class( ) != ua.NodeClass.Variable or self.ui.tabWidget.count() == 1: self.ui.actionAddMonitoredItem.setEnabled(False) self.ui.actionDeleteMonitoredItem.setEnabled(False) else: index = self.get_current_tab_index() datachange_ui = self.datachange_uis[index] self.ui.actionAddMonitoredItem.setEnabled( node not in datachange_ui.subscribed_nodes) self.ui.actionDeleteMonitoredItem.setEnabled( not self.ui.actionAddMonitoredItem.isEnabled()) def call_method(self): node = self.get_current_node() dia = CallMethodDialog(self, self.opc_ua_client.client, node) dia.show()
class MainWindow(QtWidgets.QMainWindow): def __init__(self): QtWidgets.QMainWindow.__init__(self) self.ui = Ui_MainWindow() self.ui.setupUi(self) self.sports = [] self.ui.add_btn.clicked.connect(self._newForm) self.ui.item1 = QtWidgets.QListWidgetItem("Events") self.ui.main_list.addItem(self.ui.item1) self.ui.item2 = QtWidgets.QListWidgetItem("Results") self.ui.main_list.addItem(self.ui.item2) self.ui.main_list.itemClicked.connect(self._mainClicked) self.manager = QtNetwork.QNetworkAccessManager() self.sport_req = QtNetwork.QNetworkRequest(QtCore.QUrl("API URL")) self.sport_reply = self.manager.get(self.sport_req) self.sport_reply.finished.connect(self._sportsReply) self.ui.sport_combo.activated.connect(self._mainReq) self.ui.subClass_list.itemClicked.connect(self._loadForm) self.sport_dic = {} self.loaded = [] self.resizeTimer = QtCore.QTimer() self.resizeTimer.setSingleShot(True) self.resizeTimer.timeout.connect(self.tryResize) def _mainReq(self): self.ui.subClass_list.clear() self.ui.add_btn.setEnabled(True) self.selected_sport = self.sport_dic.get( self.ui.sport_combo.currentText()) selected = self.ui.main_list.currentItem() if selected.text() == "Events": dic = {"offset": 0, "limit": 100, "sport_id": self.selected_sport} vari_req = QtCore.QJsonDocument.fromVariant(dic) json_req = QtCore.QJsonDocument.toJson(vari_req) req = QtNetwork.QNetworkRequest(QtCore.QUrl("API URL")) req.setHeader(QtNetwork.QNetworkRequest.ContentTypeHeader, "application/json") self.event_reply = self.manager.post(req, json_req) self.event_reply.finished.connect(self._eventsReply) if selected.text() == "Results": pass def _loadForm(self, item): i = self.ui.subClass_list.currentRow() self.form = Form() self.ui.formWidgetLayout.addWidget(self.form) self.form.formClosed.connect(self._closeForm) title = self.events["message"][i]["title"] self.loaded.append(title) self.form.form.title_edit_3.setText(title) dateTime = str(self.events["message"][i]["event_time"])[0:19] date = QtCore.QDateTime.fromString(dateTime, "yyyy-MM-ddTHH:mm:ss") self.form.form.dateTime_edit_3.setDateTime(date) self.loaded.append(dateTime) ####fix this after Ali comes! description = self.events["message"][i]["description"] self.form.form.description_edit_5.append(description) self.loaded.append(description) self.event_id = self.events["message"][i]["id"] league = self.events["message"][i]["league"]["name"] self.form.form.lig_combo_5.addItem(league) self.loaded.append(league) self.leaguesReq(self.selected_sport) location = self.events["message"][i]["location"][ "address"] + " " + self.events["message"][i]["location"][ "name"] + " " + self.events["message"][i]["location"]["city"] self.form.form.location_combo_3.addItem(location) self.loaded.append(location) teams = [] for j in range(len(self.events["message"][i]["teams"])): self.form.team.addTeam( self.events["message"][i]["teams"][j]["name"]) teams.append(self.events["message"][i]["teams"][j]["name"]) self.loaded.append(teams) def _eventsReply(self): reply_file = self.event_reply.readAll() json_file = QtCore.QJsonDocument.fromJson(reply_file) self.events = json_file.toVariant() # print(self.events) for i in range(len(self.events["message"])): self.ui.subClass_list.addItem( str(self.events["message"][i]["title"])) def leaguesReq(self, sport_id): dic = {"sports": [{"id": sport_id}]} vari_req = QtCore.QJsonDocument.fromVariant(dic) json_req = QtCore.QJsonDocument.toJson(vari_req) req = QtNetwork.QNetworkRequest(QtCore.QUrl("API URL")) req.setHeader(QtNetwork.QNetworkRequest.ContentTypeHeader, "application/json") self.league_reply = self.manager.post(req, json_req) self.league_reply.finished.connect(self._leaguesReply) def _leaguesReply(self): reply_file = self.league_reply.readAll() json_file = QtCore.QJsonDocument.fromJson(reply_file) v = json_file.toVariant() for i in range(len(v["message"])): self.form.form.lig_combo_5.addItem(v["message"][i]["name"]) def _sportsReply(self): reply_file = self.sport_reply.readAll() json_file = QtCore.QJsonDocument.fromJson(reply_file) v = json_file.toVariant( ) #changing variant of c++ to normal python variable that can be anything for i in range(len(v["message"])): self.sport_dic.update( {v["message"][i]["name"]: v["message"][i]["id"]}) self.ui.sport_combo.addItem(v["message"][i]["name"]) def _mainClicked(self): try: self.form.cancel() except AttributeError: self.ui.sport_combo.setEnabled(True) def _newForm(self): self.ui.add_btn.setDisabled(True) self.ui.sport_combo.setDisabled(True) self.leaguesReq(self.selected_sport) self.form = Form() self.ui.formWidgetLayout.addWidget(self.form) self.form.formClosed.connect(self._closeForm) self.repaint() def _closeForm(self, btn): if btn == "save": pass # self.ui.sizePolicy.setHorizontalStretch(0) # self.restoreState(self.state) elif btn == "close": pass self.form.close() del (self.form) self.ui.add_btn.setEnabled(True) self.ui.sport_combo.setEnabled(True) self.resizeTimer.start(200) self.updateGeometry() self.repaint() def tryResize(self): self.resize(400, 400)
class MainWindow(QMainWindow, QObject): def __init__(self, parent=None): super().__init__(parent) self.ui = Ui_MainWindow() self.ui.setupUi(self) self.setWindowTitle('Preparation description tag stackoverflow') # Все действия к прикрепляемым окнам поместим в меню for dock in self.findChildren(QDockWidget): self.ui.menuDockWindow.addAction(dock.toggleViewAction()) # Все действия к toolbar'ам окнам поместим в меню for tool in self.findChildren(QToolBar): self.ui.menuTools.addAction(tool.toggleViewAction()) self.ui.action_save.triggered.connect(self.save) self.ui.action_save_all.triggered.connect(self.save_all) self.ui.ref_guide.textChanged.connect(self.ref_guide_text_changed) self.ui.description.textChanged.connect(self.description_text_changed) # TODO: при изменении тега менять и окно с его содержимым -- plain_text_edit_tag_info # TODO: заменить модель комбобокса нашим списком self.tags_dict = dict() self.modified_tags = list() # Словарь, ключом, которого id тега, а значением -- элемент списка self.tag_id_item_dict = dict() self.tag_list_model = QStandardItemModel() self.modified_tags_model = QStandardItemModel() self.ui.list_view_tag_list.setModel(self.tag_list_model) self.ui.list_view_modified_tags.setModel(self.modified_tags_model) self.ui.list_view_tag_list.clicked.connect( self.list_view_tag_list_clicked) self.ui.list_view_modified_tags.clicked.connect( self.list_view_modified_tags_clicked) self.ui.check_box_only_empty.clicked.connect( self.filter_list_tag_only_empty) # TODO: добавить кнопку для постинга изменений тега. Перед постингом нужно авторизоваться # получить текущее состояние и сравнить с новым -- может кто-то что-то добавил и # если оно было лучше, того, что я хочу добавить, получится не хорошо # TODO: кнопка сохранения всех измененных тегов self.update_states() def update_states(self): self.ui.action_save.setEnabled(False) self.ui.action_save_all.setEnabled(len(self.modified_tags) > 0) index = self.ui.list_view_tag_list.currentIndex() if not index.isValid(): return tag_id = self.tag_id_from_index(index) if tag_id is not None: self.ui.action_save.setEnabled(tag_id in self.modified_tags) def filter_list_tag_only_empty(self, has_filter=None): if has_filter is None: has_filter = self.ui.check_box_only_empty.isChecked() tags = self.tags_dict # Фильтр пустых тегов или измененных пользователем if has_filter: tags = dict( filter( lambda x: (not x[1]['description'] and not x[1][ 'ref_guide']) or 'user_changed' in x[1], self.tags_dict.items())) self._fill_tag_list(tags) def list_view_tag_list_clicked(self, index): item = self.tag_list_model.itemFromIndex(index) if item is not None: tag_id = item.data() self.fill_tag_info_from_id(tag_id) else: logger.warn('Item from index; "%s" not found.', index) def list_view_modified_tags_clicked(self, index): item = self.modified_tags_model.itemFromIndex(index) if item is not None: tag_id = item.data() tag_item = self.tag_id_item_dict[tag_id] self.ui.list_view_tag_list.setCurrentIndex(tag_item.index()) self.fill_tag_info_from_id(tag_id) else: logger.warn('Item from index; "%s" not found.', index) @staticmethod def tag_title(tag): return '#{}: {}'.format(tag['id'], ', '.join(tag['name'])) def fill_tag_list(self): self.tags_dict.clear() tag_file_list = [ DIR + '/' + tag for tag in os.listdir(DIR) if tag.endswith('.tag') ] for file_name in tag_file_list: with open(file_name, 'rb') as f: # Пример: {'ref_guide': '', 'id': '1', 'description': '', 'name': ['python']} data = pickle.load(f) data['hash'] = self.hash_tag(data) self.tags_dict[data['id']] = data self.filter_list_tag_only_empty() # self._fill_tag_list(self.tags_dict) # Делаем текущим первый тег и выводим информацию о нем if self.tag_list_model.rowCount(): index = self.tag_list_model.item(0).index() self.fill_tag_info_from_index(index) self.ui.list_view_tag_list.setCurrentIndex(index) self.update_states() def _fill_tag_list(self, tags_dict): self.tag_list_model.clear() self.ui.list_view_tag_list.blockSignals(True) logger.debug('Total tags: %s.', len(tags_dict)) logger.debug('Fill list tags start.') # При долгой загрузкк показываем прогресс диалог progress = QProgressDialog("Adding tags...", "Abort", 0, len(tags_dict), self) progress.setWindowModality(Qt.WindowModal) progress.setWindowTitle('Progress dialog') tags = sorted(tags_dict.items(), key=lambda x: int(x[0])) for i, (tag_id, tag) in enumerate(tags): progress.setValue(i) if progress.wasCanceled(): break name = self.tag_title(tag) item = QStandardItem(name) item.setData(tag_id) self.tag_list_model.appendRow(item) self.tag_id_item_dict[tag_id] = item progress.setValue(len(tags_dict)) logger.debug('Fill list tags finish.') self.ui.list_view_tag_list.blockSignals(False) @staticmethod def hash_tag(tag): text = tag['ref_guide'] + tag['description'] import hashlib md5 = hashlib.md5() md5.update(text.encode()) return md5.hexdigest() def check_modified_tag(self, tag_id): tag = self.tags_dict[tag_id] new_hash = self.hash_tag(tag) if tag['hash'] == new_hash: if tag_id in self.modified_tags: self.modified_tags.remove(tag_id) else: if tag_id not in self.modified_tags: self.modified_tags.append(tag_id) self.fill_list_modified_tags() # Если тег есть в списке измененных, меняем его цвет, иначе возвращаем черный цвет item = self.tag_id_item_dict[tag_id] item.setForeground(Qt.darkCyan if tag_id in self.modified_tags else Qt.black) font = item.font() font.setBold(tag_id in self.modified_tags) item.setFont(font) def fill_list_modified_tags(self): # Обновление списка измененных тегов self.modified_tags_model.clear() for tag_id in sorted(self.modified_tags, key=int): tag = self.tags_dict[tag_id] item = QStandardItem(self.tag_title(tag)) item.setData(tag_id) self.modified_tags_model.appendRow(item) def tag_id_from_index(self, index): if index.isValid(): item = self.tag_list_model.itemFromIndex(index) if item is not None: return item.data() else: logger.warn('Item from index: "%s" is None.', index) else: logger.warn('Index: "%s" is not valid.', index) def ref_guide_text_changed(self): index = self.ui.list_view_tag_list.currentIndex() if not index.isValid(): logger.warn('Index "%s" is not valid!', index) return tag_id = self.tag_id_from_index(index) tag = self.tags_dict[tag_id] tag['ref_guide'] = self.ui.ref_guide.toPlainText() self.check_modified_tag(tag_id) self.update_states() def description_text_changed(self): index = self.ui.list_view_tag_list.currentIndex() tag_id = self.tag_id_from_index(index) tag = self.tags_dict[tag_id] tag['description'] = self.ui.description.toPlainText() self.check_modified_tag(tag_id) self.update_states() def fill_tag_info_from_id(self, tag_id): if tag_id not in self.tags_dict: logger.warn('Tag id: "%s" not found!', tag_id) return tag = self.tags_dict[tag_id] logger.debug('Fill tag info from tag id: "%s", tag: %s', tag_id, tag) # Вывод внутреннего представления тега order_key = ['id', 'name', 'ref_guide', 'description'] text = '' for k in order_key: text += '{}:\n{}\n\n'.format(k, tag[k]) for k, v in sorted(tag.items()): if k not in order_key: text += '{}:\n{}\n\n'.format(k, v) self.ui.plain_text_edit_tag_info.setPlainText(text) url = 'http://ru.stackoverflow.com/tags/{}/info'.format(tag['name'][0]) url = '<a href="{0}">{0}</a>'.format(url) self.ui.url.setText(url) self.ui.ref_guide.blockSignals(True) self.ui.description.blockSignals(True) self.ui.ref_guide.setPlainText(tag['ref_guide']) self.ui.description.setPlainText(tag['description']) self.ui.ref_guide.blockSignals(False) self.ui.description.blockSignals(False) self.update_states() def fill_tag_info_from_index(self, index): tag_id = self.tag_id_from_index(index) self.fill_tag_info_from_id(tag_id) def save_tag(self, tag_id): if tag_id not in self.tags_dict: logger.warn('Tag with id "%s" not found.', tag_id) return tag = self.tags_dict[tag_id] file_name = DIR + '/{}.tag'.format(tag['id']) file_name_backup = file_name + '.backup' # Перед переписыванием файла, делаем его копию shutil.copyfile(file_name, file_name_backup) try: with open(file_name, mode='wb') as f: # Обновляем хеш tag['hash'] = self.hash_tag(tag) # Флаг, говорящий, что данный тег был изменен пользователем tag['user_changed'] = True self.modified_tags.remove(tag_id) self.fill_list_modified_tags() # После сохранения обновляем состояние тега в списке self.check_modified_tag(tag_id) pickle.dump(tag, f) except Exception as e: logger.exception("Error:") logger.debug('Restore {} from {}.'.format(file_name, file_name_backup)) # Произошла ошибка. Восстанавливаем файл из бекапа os.remove(file_name) os.rename(file_name_backup, file_name) else: logger.debug( 'Update {} was successful, removed the backup: {}.'.format( file_name, file_name_backup)) # Переписывание прошло хорошо, удаляем файл бекапа if os.path.exists(file_name_backup): os.remove(file_name_backup) self.update_states() def save(self): index = self.ui.list_view_tag_list.currentIndex() tag_id = self.tag_id_from_index(index) self.save_tag(tag_id) def save_all(self): while self.modified_tags: self.save_tag(self.modified_tags[0]) def read_settings(self): # TODO: при сложных настройках, лучше перейти на json или yaml config = QSettings(CONFIG_FILE, QSettings.IniFormat) self.restoreState(config.value('MainWindow_State')) self.restoreGeometry(config.value('MainWindow_Geometry')) self.ui.splitter.restoreState(config.value('Splitter_State')) self.ui.check_box_only_empty.setChecked( bool(config.value('Check_box_only_empty', False))) def write_settings(self): config = QSettings(CONFIG_FILE, QSettings.IniFormat) config.setValue('MainWindow_State', self.saveState()) config.setValue('MainWindow_Geometry', self.saveGeometry()) config.setValue('Splitter_State', self.ui.splitter.saveState()) config.setValue('Check_box_only_empty', self.ui.check_box_only_empty.isChecked()) def closeEvent(self, event): self.write_settings() quit()
class MainWindow(QtWidgets.QMainWindow): def __init__(self): super().__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) self.ui.de_start.setDate(QtCore.QDate().currentDate()) self.ui.de_stop.setDate(QtCore.QDate().currentDate()) self.ui.cb_whocalled.setVisible(False) self.ui.btn_report.setVisible(False) self.ui.tab_2.setEnabled(False) self.mango = MangoOffice() self.dframe = PandasDataFrame() # connections self.ui.btn_connection.clicked.connect(self.connection) self.ui.btn_download.clicked.connect(self.feel_table) self.ui.cb_whocalledtype.currentIndexChanged.connect( self.who_called_type_change) self.ui.cb_ats.currentIndexChanged.connect(self.who_called_type_change) self.ui.btn_clear.clicked.connect(self.btn_clear_click) self.ui.de_start.dateChanged.connect(self.de_start_date_change) self.ui.de_stop.dateChanged.connect(self.de_stop_date_change) self.ui.btn_report.clicked.connect(self.export_to_xls) def connection(self): """ подключение к сервису MangoOffice, загрузка дополнительной информации :return: """ # подключаемся к сервису MangoOffice self.ui.statusbar.showMessage('Подключение') connected, info = self.mango.connect(self.ui.edt_login.text(), self.ui.edt_pass.text()) # выводим в статус бар информацию о подключении self.ui.statusbar.showMessage(info) if not connected: return None # обновляем информацию о профиле self.mango.upload_profile_data() self.ui.cb_ats.clear() # подгружаем названия продуктов и список пользователей в этих продуктах for product in self.mango.profile['products']: self.ui.cb_ats.addItem(product) self.mango.get_sip_users(product) # переключаемся на вкладку с настройками self.ui.tab_2.setEnabled(True) self.ui.tabWidget.setCurrentIndex(1) def feel_table(self): """ Загрузка истории звонков с использованием выбранных польхователем параметров и отображении данных в таблице :return: """ # TODO self.ui.statusbar.showMessage('Загружаем данные..') не работает # устанвливаем тип звонящего self.mango.set_who_called_type(self.ui.cb_whocalledtype.currentText()) # Видимость кнопки Отчет в XLS if self.ui.cb_whocalledtype.currentText() == 'Сотрудник': self.ui.btn_report.setVisible(True) else: self.ui.btn_report.setVisible(False) # уточняем кто звонил if self.ui.cb_whocalled.isVisible(): self.mango.set_who_called(self.ui.cb_ats.currentText(), self.ui.cb_whocalled.currentText()) if self.ui.ed_clientnumber.isVisible(): self.mango.set_client_number(self.ui.ed_clientnumber.text()) # устанавливаем период self.mango.set_star_stop_date(self.ui.de_start.date().toPython(), self.ui.de_stop.date().toPython()) # получаем статистику self.mango.get_call_statics(self.ui.cb_ats.currentText()) # загружаем данные self.dframe.load_data('static.csv') dframe = self.dframe.data # формируем модель model = DataFrameModel(dframe) # передаем модель на отображениие в интерфейсе таблицы self.ui.tbl_view_pandas.setModel(model) self.ui.tbl_view_pandas.horizontalHeader().setSectionResizeMode( 0, QtWidgets.QHeaderView.Fixed) self.ui.tbl_view_pandas.horizontalHeader().setSectionResizeMode( 1, QtWidgets.QHeaderView.Fixed) self.ui.tbl_view_pandas.horizontalHeader().setSectionResizeMode( 2, QtWidgets.QHeaderView.Fixed) self.ui.tbl_view_pandas.horizontalHeader().setSectionResizeMode( 3, QtWidgets.QHeaderView.ResizeToContents) self.ui.tbl_view_pandas.horizontalHeader().setSectionResizeMode( 4, QtWidgets.QHeaderView.ResizeToContents) self.ui.tbl_view_pandas.horizontalHeader().setSectionResizeMode( 5, QtWidgets.QHeaderView.Stretch) self.ui.tbl_view_pandas.horizontalHeader().setSectionResizeMode( 6, QtWidgets.QHeaderView.ResizeToContents) self.ui.statusbar.showMessage( f'Всего {self.ui.tbl_view_pandas.model().rowCount()} записей') def who_called_type_change(self): # при выборе типа звоняшего caller_type = self.ui.cb_whocalledtype.currentText() self.ui.ed_clientnumber.setVisible(True) self.ui.ed_clientnumber.setEnabled(False) self.ui.cb_whocalled.setVisible(False) if caller_type == 'Сотрудник': self.ui.ed_clientnumber.setVisible(False) self.ui.cb_whocalled.setVisible(True) self.ui.cb_whocalled.clear() self.ui.cb_whocalled.addItem('') for user in self.mango.profile['products'][ self.ui.cb_ats.currentText()]['users']: self.ui.cb_whocalled.addItem(user) if caller_type == 'Клиент': self.ui.ed_clientnumber.setEnabled(True) def btn_clear_click(self): # действие на кнопку Очистить date = QtCore.QDate().currentDate() self.ui.de_start.setDate(date) self.ui.de_stop.setDate(date) self.ui.ed_clientnumber.clear() self.ui.cb_whocalledtype.setCurrentIndex(0) def de_start_date_change(self): date = self.ui.de_start.date() if date > self.ui.de_stop.date(): self.ui.de_stop.setDate(date) def de_stop_date_change(self): date = self.ui.de_stop.date() if date < self.ui.de_start.date(): self.ui.de_start.setDate(date) def export_to_xls(self): dframe = self.dframe.call_stat_by_day() dframe.to_excel('report.xls')
class MainWindow(QMainWindow): def __init__(self): super().__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) # Все действия к прикрепляемым окнам поместим в меню for dock in self.findChildren(QDockWidget): self.ui.menuDockWindow.addAction(dock.toggleViewAction()) # Все действия к toolbar'ам окнам поместим в меню for tool in self.findChildren(QToolBar): self.ui.menuTools.addAction(tool.toggleViewAction()) self.model = QStandardItemModel() self.clear_model() self.ui.treeView.setModel(self.model) self.ui.treeView.clicked.connect(self.show_info_in_status_bar) self.ui.treeView.doubleClicked.connect(self.show_in_explorer) self.ui.button_select_dir.clicked.connect(self.select_dir) self.ui.action_go.triggered.connect(self.fill) self.ui.action_show_in_explorer.triggered.connect(self.show_in_explorer) self.ui.action_apply_filter.triggered.connect(self.slot_remove_dirs) self.ui.label_root_dir.setText(self.ui.line_edit_dir_path.text()) self.ui.action_apply_filter.setEnabled(False) self.read_settings() def update_states(self): pass def show_in_explorer(self, index=None): if index is None: index = self.ui.treeView.currentIndex() if index is None: return row = self.get_row_item_from_index(index) if row is None: return # TODO: Qt.UserRole + 1 path = row[0].data(Qt.UserRole + 1) cmd = 'Explorer /n,"{}"'.format(path) logger.debug('Command: %s.', cmd) os.system(cmd) def select_dir(self): dir_path = QFileDialog.getExistingDirectory(self, None, self.ui.line_edit_dir_path.text()) if dir_path: self.ui.line_edit_dir_path.setText(dir_path) def get_row_item_from_index(self, index): if index is None or not index.isValid: logger.warn('get_row_from_index: invalid index: %s.', index) return row = index.row() item = self.model.itemFromIndex(index) if item is None: return parent = item.parent() if parent is None: parent = self.model.invisibleRootItem() return [parent.child(row, i) for i in range(self.model.columnCount())] def show_info_in_status_bar(self, index): row = self.get_row_item_from_index(index) if row is None: return path, size = row # TODO: Лучше дать конкретные константные имена, чем так: Qt.UserRole + 1 / Qt.UserRole + 2 self.ui.statusbar.showMessage('{} ({} / {} bytes)'.format( path.data(Qt.UserRole + 1), size.data(Qt.UserRole + 1), size.data(Qt.UserRole + 2))) def clear_model(self): self.model.clear() header_labels = ['Name', 'Size'] self.model.setColumnCount(len(header_labels)) self.model.setHorizontalHeaderLabels(header_labels) def remove_dirs(self, root): """Удаление элементов, у которых размер не совпадает с фильтром""" for row in reversed(range(root.rowCount())): child = root.child(row, 1) filter_size = self.ui.line_edit_filter.text() if not check_filter_size_eval(filter_size, directory_sizes.get_bytes(child.data(Qt.UserRole + 1))): root.removeRow(child.row()) else: self.remove_dirs(root.child(row, 0)) def slot_remove_dirs(self): self.ui.action_apply_filter.setEnabled(False) self.remove_dirs(self.model.invisibleRootItem()) def fill(self): self.ui.action_go.setEnabled(False) self.clear_model() dir_path = self.ui.line_edit_dir_path.text() if not dir_path or not os.path.exists(dir_path): QMessageBox.information(self, 'Info', 'Choose dir path!') return filter_size = self.ui.line_edit_filter.text() if not filter_size: logger.debug('filter_size is empty. Setting default filter_size.') filter_size = "{size} >= %1GB%" logger.debug('filter_size: %s.', filter_size) t = time.clock() # Соберем список папок dir_list = [os.path.join(dir_path, entry) for entry in os.listdir(dir_path) if os.path.isdir(os.path.join(dir_path, entry))] for entry in dir_list: self.dir_size_bytes(entry, self.model.invisibleRootItem(), filter_size) self.ui.action_apply_filter.setEnabled(True) if self.ui.check_box_auto_apply_filter.isChecked(): self.slot_remove_dirs() self.ui.action_apply_filter.setEnabled(False) t = time.clock() - t logger.debug('Done! Elapsed time {:.2f} sec.'.format(t)) self.ui.action_go.setEnabled(True) QMessageBox.information(self, 'Info', 'Done!\n\nElapsed time {:.2f} sec.'.format(t)) def dir_size_bytes(self, dir_path, root_item, filter_size, level=0): dir_path = QDir.toNativeSeparators(dir_path) it = QDirIterator(dir_path, '*.*', QDir.AllEntries | QDir.NoDotAndDotDot | QDir.Hidden | QDir.System) sizes = 0 path_short_name = os.path.split(dir_path) path_short_name = path_short_name[1] if path_short_name[1] else path_short_name[0] row = [QStandardItem(path_short_name), QStandardItem('-')] row[0].setData(dir_path) row[1].setText('-') row[1].setData('-') row[0].setEditable(False) row[1].setEditable(False) root_item.appendRow(row) while it.hasNext(): file_name = it.next() file = QFileInfo(file_name) if file.isDir(): size = self.dir_size_bytes(file_name, row[0], filter_size, level + 1) else: size = file.size() sizes += size qApp.processEvents() text_size = directory_sizes.pretty_file_size(sizes)[1] row[1].setText(text_size) row[1].setData(text_size) row[1].setData(str(sizes), Qt.UserRole + 2) return sizes def read_settings(self): # TODO: при сложных настройках, лучше перейти на json или yaml config = QSettings(CONFIG_FILE, QSettings.IniFormat) self.restoreState(config.value('MainWindow_State')) self.restoreGeometry(config.value('MainWindow_Geometry')) dir_path = config.value('Dir_path', None) if not dir_path: dir_path = "C:\\" self.ui.line_edit_dir_path.setText(dir_path) filter_size = config.value('Filter_size', None) if not filter_size: filter_size = "{size} >= %1GB%" self.ui.line_edit_filter.setText(filter_size) self.ui.check_box_auto_apply_filter.setChecked('true' in config.value('Auto_apply_filter', 'true').lower()) def write_settings(self): config = QSettings(CONFIG_FILE, QSettings.IniFormat) config.setValue('MainWindow_State', self.saveState()) config.setValue('MainWindow_Geometry', self.saveGeometry()) config.setValue('Dir_path', self.ui.line_edit_dir_path.text()) config.setValue('Filter_size', self.ui.line_edit_filter.text()) config.setValue('Auto_apply_filter', 'true' if self.ui.check_box_auto_apply_filter.isChecked() else 'false') def closeEvent(self, event): self.write_settings() quit()
class MainWindowTest(unittest.TestCase): mainwindow = None # hold QMainWindow in variable ui = None # hold GUI in variable def setUp(self): self.mainwindow = QMainWindow() # create empty QMainWindow self.ui = Ui_MainWindow() # we want to test GUI - only self.ui.setupUi(self.mainwindow) # set GUI for freshly created QMainWindow # Check tab names of QTabWidget def test_checkTabNames(self): self.assertEqual(self.ui.tabWidgetTests.tabText(0), "Complete Blood Count") self.assertEqual(self.ui.tabWidgetTests.tabText(1), "Renal Panel") self.assertEqual(self.ui.tabWidgetTests.tabText(2), "Liver Panel") self.assertEqual(self.ui.tabWidgetTests.tabText(3), "Thyroid Panel") self.assertEqual(self.ui.tabWidgetTests.tabText(4), "Electrolyte Panel") self.assertEqual(self.ui.tabWidgetTests.tabText(5), "Lipid Panel") # Check labels in Complete Blood Count tab def test_checkCBCLabels(self): self.assertEqual(self.ui.wbcLabel.text(), "WBC") self.assertEqual(self.ui.pltLabel.text(), "PLT") self.assertEqual(self.ui.hgbLabel.text(), "Hgb") self.assertEqual(self.ui.hctLabel.text(), "HCT") self.assertEqual(self.ui.rbcLabel.text(), "RBC") # Check labels in Renal Panel tab def test_checkRenalLabels(self): self.assertEqual(self.ui.bunLabel.text(), "BUN") self.assertEqual(self.ui.crLabel.text(), "Cr") # Check labels in Liver Panel tab def test_checkLiverLabels(self): self.assertEqual(self.ui.albLabel.text(), "ALB") self.assertEqual(self.ui.tbilLabel.text(), "TBIL/SBR") # Check labels in Thyroid Panel tab def test_checkThyroidLabels(self): self.assertEqual(self.ui.tshLabel.text(), "TSH") self.assertEqual(self.ui.t3Label.text(), "T3") self.assertEqual(self.ui.t4Label.text(), "T4") # Check labels in Electrolyte Panel tab def test_checkElectrolyteLabels(self): self.assertEqual(self.ui.hco3Label.text(), "HCO3") self.assertEqual(self.ui.clLabel.text(), "Cl") self.assertEqual(self.ui.kLabel.text(), "K") self.assertEqual(self.ui.naLabel.text(), "Na") # Check labels in Lipid Panel tab def test_checkLipidLabels(self): self.assertEqual(self.ui.tcLabel.text(), "TC") self.assertEqual(self.ui.tgLabel.text(), "TG") self.assertEqual(self.ui.hdlLabel.text(), "HDL") self.assertEqual(self.ui.ldlLabel.text(), "LDL") # Check if amounts widgets for CBC are not disabled def test_CBCAmountsEnabled(self): self.assertTrue(self.ui.wbcAmountSpinBox.isEnabled()) self.assertTrue(self.ui.pltAmountSpinBox.isEnabled()) self.assertTrue(self.ui.hgbAmountSpinBox.isEnabled()) self.assertTrue(self.ui.hctAmountSpinBox.isEnabled()) self.assertTrue(self.ui.rbcAmountSpinBox.isEnabled()) # Check if amounts widgets for Renal Panel are not disabled def test_RenalAmountsEnabled(self): self.assertTrue(self.ui.bunAmountSpinBox.isEnabled()) self.assertTrue(self.ui.crAmountSpinBox.isEnabled()) # Check if amounts widgets for Liver Panel are not disabled def test_LiverAmountsEnabled(self): self.assertTrue(self.ui.albAmountSpinBox.isEnabled()) self.assertTrue(self.ui.tbilAmountSpinBox.isEnabled()) # Check if amounts widgets for Thyroid Panel are not disabled def test_ThyroidAmountsEnabled(self): self.assertTrue(self.ui.tshAmountSpinBox.isEnabled()) self.assertTrue(self.ui.t3AmountSpinBox.isEnabled()) self.assertTrue(self.ui.t4AmountSpinBox.isEnabled()) # Check if amounts widgets for Electrolyte Panel are not disabled def test_ElectrolyteAmountsEnabled(self): self.assertTrue(self.ui.hco3AmountSpinBox.isEnabled()) self.assertTrue(self.ui.clAmountSpinBox.isEnabled()) self.assertTrue(self.ui.kAmountSpinBox.isEnabled()) self.assertTrue(self.ui.naAmountSpinBox.isEnabled()) # Check if amounts widgets for Lipid Panel are not disabled def test_LipidAmountsEnabled(self): self.assertTrue(self.ui.tcAmountSpinBox.isEnabled()) self.assertTrue(self.ui.tgAmountSpinBox.isEnabled()) self.assertTrue(self.ui.hdlAmountSpinBox.isEnabled()) self.assertTrue(self.ui.ldlAmountSpinBox.isEnabled()) # Check if units widgets can hold duplicated values def test_unitsAmountSetForDupl(self): self.assertFalse(self.ui.wbcUnitComboBox.duplicatesEnabled()) self.assertFalse(self.ui.pltUnitComboBox.duplicatesEnabled()) self.assertFalse(self.ui.hgbUnitComboBox.duplicatesEnabled()) self.assertFalse(self.ui.hctUnitComboBox.duplicatesEnabled()) self.assertFalse(self.ui.rbcUnitComboBox.duplicatesEnabled()) self.assertFalse(self.ui.bunUnitComboBox.duplicatesEnabled()) self.assertFalse(self.ui.crUnitComboBox.duplicatesEnabled()) self.assertFalse(self.ui.albUnitComboBox.duplicatesEnabled()) self.assertFalse(self.ui.tbilUnitComboBox.duplicatesEnabled()) self.assertFalse(self.ui.tshUnitComboBox.duplicatesEnabled()) self.assertFalse(self.ui.t3UnitComboBox.duplicatesEnabled()) self.assertFalse(self.ui.t4UnitComboBox.duplicatesEnabled()) self.assertFalse(self.ui.hco3UnitComboBox.duplicatesEnabled()) self.assertFalse(self.ui.clUnitComboBox.duplicatesEnabled()) self.assertFalse(self.ui.kUnitComboBox.duplicatesEnabled()) self.assertFalse(self.ui.kUnitComboBox.duplicatesEnabled()) self.assertFalse(self.ui.naUnitComboBox.duplicatesEnabled()) self.assertFalse(self.ui.tcUnitComboBox.duplicatesEnabled()) self.assertFalse(self.ui.tgUnitComboBox.duplicatesEnabled()) self.assertFalse(self.ui.hdlUnitComboBox.duplicatesEnabled()) self.assertFalse(self.ui.ldlUnitComboBox.duplicatesEnabled()) # Check if amounts widgets for units widgets are not disabled def test_unitsAmountEnabled(self): self.assertTrue(self.ui.wbcUnitComboBox.isEnabled()) self.assertTrue(self.ui.pltUnitComboBox.isEnabled()) self.assertTrue(self.ui.hgbUnitComboBox.isEnabled()) self.assertTrue(self.ui.hctUnitComboBox.isEnabled()) self.assertTrue(self.ui.rbcUnitComboBox.isEnabled()) self.assertTrue(self.ui.bunUnitComboBox.isEnabled()) self.assertTrue(self.ui.crUnitComboBox.isEnabled()) self.assertTrue(self.ui.albUnitComboBox.isEnabled()) self.assertTrue(self.ui.tbilUnitComboBox.isEnabled()) self.assertTrue(self.ui.tshUnitComboBox.isEnabled()) self.assertTrue(self.ui.t3UnitComboBox.isEnabled()) self.assertTrue(self.ui.t4UnitComboBox.isEnabled()) self.assertTrue(self.ui.hco3UnitComboBox.isEnabled()) self.assertTrue(self.ui.clUnitComboBox.isEnabled()) self.assertTrue(self.ui.kUnitComboBox.isEnabled()) self.assertTrue(self.ui.kUnitComboBox.isEnabled()) self.assertTrue(self.ui.naUnitComboBox.isEnabled()) self.assertTrue(self.ui.tcUnitComboBox.isEnabled()) self.assertTrue(self.ui.tgUnitComboBox.isEnabled()) self.assertTrue(self.ui.hdlUnitComboBox.isEnabled()) self.assertTrue(self.ui.ldlUnitComboBox.isEnabled()) # Check units amount in each QComboBox in QTabWidget def test_unitsAmount(self): self.assertEqual(self.ui.wbcUnitComboBox.count(), 43) self.assertEqual(self.ui.pltUnitComboBox.count(), 43) self.assertEqual(self.ui.hgbUnitComboBox.count(), 43) self.assertEqual(self.ui.hctUnitComboBox.count(), 43) self.assertEqual(self.ui.rbcUnitComboBox.count(), 43) self.assertEqual(self.ui.bunUnitComboBox.count(), 43) self.assertEqual(self.ui.crUnitComboBox.count(), 43) self.assertEqual(self.ui.albUnitComboBox.count(), 43) self.assertEqual(self.ui.tbilUnitComboBox.count(), 43) self.assertEqual(self.ui.tshUnitComboBox.count(), 43) self.assertEqual(self.ui.t3UnitComboBox.count(), 43) self.assertEqual(self.ui.t4UnitComboBox.count(), 43) self.assertEqual(self.ui.hco3UnitComboBox.count(), 43) self.assertEqual(self.ui.clUnitComboBox.count(), 43) self.assertEqual(self.ui.kUnitComboBox.count(), 43) self.assertEqual(self.ui.kUnitComboBox.count(), 43) self.assertEqual(self.ui.naUnitComboBox.count(), 43) self.assertEqual(self.ui.tcUnitComboBox.count(), 43) self.assertEqual(self.ui.tgUnitComboBox.count(), 43) self.assertEqual(self.ui.hdlUnitComboBox.count(), 43) self.assertEqual(self.ui.ldlUnitComboBox.count(), 43) def test_checkGenderLabel(self): self.assertEqual(self.ui.genderLabel.text(), "Gender: ") def test_genderOptions(self): self.assertEqual(self.ui.genderChoice.itemText(0), "male") self.assertEqual(self.ui.genderChoice.itemText(1), "female") def test_checkAgeLabel(self): self.assertEqual(self.ui.ageLabel.text(), "Age: ") # Check max limit for age (54000 is max of days = 150 years) def test_ageMaxLimit(self): self.assertEqual(self.ui.ageAmountSpinBox.maximum(), 54000) def test_ageMinLimit(self): self.assertEqual(self.ui.ageAmountSpinBox.minimum(), 0) def test_ageOptions(self): self.assertEqual(self.ui.ageTypeComboBox.itemText(0), "days") self.assertEqual(self.ui.ageTypeComboBox.itemText(1), "months") self.assertEqual(self.ui.ageTypeComboBox.itemText(2), "years") def test_checkResultBtn(self): self.assertEqual(self.ui.checkResultBtn.text(), "Check result") self.assertTrue(self.ui.checkResultBtn.isEnabled()) def test_exitBtn(self): self.assertRegex(self.ui.closeBtn.text(), "^(Close|Exit)$") self.assertTrue(self.ui.closeBtn.isEnabled()) def test_menuSettings(self): self.assertFalse(self.ui.menuSettings.isEmpty()) self.assertTrue(self.ui.actionLanguage.isEnabled()) self.assertTrue(self.ui.actionLanguage.isIconVisibleInMenu()) self.assertTrue(self.ui.actionLanguage.isShortcutVisibleInContextMenu()) self.assertTrue(self.ui.actionMotiv.isEnabled()) self.assertTrue(self.ui.actionMotiv.isIconVisibleInMenu()) self.assertTrue(self.ui.actionMotiv.isShortcutVisibleInContextMenu()) self.assertTrue(self.ui.actionPrinting.isEnabled()) self.assertTrue(self.ui.actionPrinting.isIconVisibleInMenu()) self.assertTrue(self.ui.actionPrinting.isShortcutVisibleInContextMenu()) self.assertTrue(self.ui.actionTabs.isEnabled()) self.assertTrue(self.ui.actionTabs.isIconVisibleInMenu()) self.assertTrue(self.ui.actionTabs.isShortcutVisibleInContextMenu()) def test_menuAboutNotEmpty(self): self.assertFalse(self.ui.menuAbout.isEmpty()) self.assertTrue(self.ui.actionLabtests.isEnabled()) self.assertTrue(self.ui.actionLanguage.isIconVisibleInMenu()) self.assertTrue(self.ui.actionLanguage.isShortcutVisibleInContextMenu()) self.assertTrue(self.ui.actionAuthor.isEnabled()) self.assertTrue(self.ui.actionAuthor.isIconVisibleInMenu()) self.assertTrue(self.ui.actionAuthor.isShortcutVisibleInContextMenu()) self.assertTrue(self.ui.actionSources.isEnabled()) self.assertTrue(self.ui.actionSources.isIconVisibleInMenu()) self.assertTrue(self.ui.actionSources.isShortcutVisibleInContextMenu()) def test_menuHelpNotEmpty(self): self.assertFalse(self.ui.menuHelp.isEmpty()) self.assertTrue(self.ui.actionReport_issue.isEnabled()) self.assertTrue(self.ui.actionReport_issue.isIconVisibleInMenu()) self.assertTrue(self.ui.actionReport_issue.isShortcutVisibleInContextMenu()) self.assertTrue(self.ui.actionPropose.isEnabled()) self.assertTrue(self.ui.actionPropose.isIconVisibleInMenu()) self.assertTrue(self.ui.actionPropose.isShortcutVisibleInContextMenu()) self.assertTrue(self.ui.actionFAQ.isEnabled()) self.assertTrue(self.ui.actionFAQ.isIconVisibleInMenu()) self.assertTrue(self.ui.actionFAQ.isShortcutVisibleInContextMenu()) def test_labelsToolTips(self): self.assertEqual(self.ui.wbcLabel.toolTip(), "White Blood Cells") self.assertEqual(self.ui.pltLabel.toolTip(), "Platelets") self.assertEqual(self.ui.hgbLabel.toolTip(), "Hgb/Hb - Hemoglobin") self.assertEqual(self.ui.hctLabel.toolTip(), "Hematocrit") self.assertEqual(self.ui.rbcLabel.toolTip(), "Red Blood Cells") self.assertEqual(self.ui.bunLabel.toolTip(), "Blood Urea Nitrogen") self.assertEqual(self.ui.crLabel.toolTip(), "Cr / CREAT - Creatinine") self.assertEqual(self.ui.albLabel.toolTip(), "Albumin") self.assertEqual(self.ui.tbilLabel.toolTip(), "Total Bilirubin / Serum Bilirubin") self.assertEqual(self.ui.tshLabel.toolTip(), "Thyroid") self.assertEqual(self.ui.t3Label.toolTip(), "Triiodothyronine") self.assertEqual(self.ui.t4Label.toolTip(), "Thyroxine") self.assertEqual(self.ui.hco3Label.toolTip(), "Bicarbonate") self.assertEqual(self.ui.clLabel.toolTip(), "Chloride") self.assertEqual(self.ui.kLabel.toolTip(), "Potassium") self.assertEqual(self.ui.naLabel.toolTip(), "Sodium") self.assertEqual(self.ui.tcLabel.toolTip(), "Total Cholesterol") self.assertEqual(self.ui.tgLabel.toolTip(), "Triglycerides") self.assertEqual(self.ui.hdlLabel.toolTip(), "High-Density Lipoprotein") self.assertEqual(self.ui.ldlLabel.toolTip(), "Low-Density Lipoprotein")
class MyWindow(QtWidgets.QMainWindow): __processes = None logger = None tia = None templater = None model = None templates_path = None template_conf = None activate_buttons = False prj_config = None prj_file_path = None plc_name = '' new_template_window = None def __init__(self): super(MyWindow, self).__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) self.init_logger() self.init_project_table() self.settings() self.logger.info("Program started") self.tia = TiaHandler() # self.templater = Templater() # self.templater.new_template('Test_temp') self.main_slots() # Подключаем слоты self.model = QtGui.QStandardItemModel() self.ui.project_tree.setModel(self.model) self.ui.project_tree.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection) self.model.setHorizontalHeaderLabels(['Дерево проекта']) self.ui.project_tree.setModel(self.model) self.ui.new_folder_action.setEnabled(False) self.ui.sync_action.setEnabled(False) self.ui.import_action.setEnabled(False) self.ui.export_action.setEnabled(False) def create_project_tree(self, children, parent): self.model.setHorizontalHeaderLabels(['Дерево проекта']) for child in children: child_item = QtGui.QStandardItem(child) parent.appendRow(child_item) if isinstance(children, dict): self.create_project_tree(children[child], child_item) def main_slots(self): # File Menu actions self.ui.open_action.triggered.connect(self.slot_open_project) self.ui.save_action.triggered.connect(self.save_project) self.ui.save_as_action.triggered.connect(self.save_project_as) self.ui.export_action.triggered.connect(self.export_blocks) self.ui.import_action.triggered.connect(self.import_blocks) self.ui.exit_action.triggered.connect(self.close) # TIA Menu actions self.ui.connect_action.triggered.connect(self.slot_connect_tia) self.ui.sync_action.triggered.connect(self.slot_sync_action) self.ui.new_folder_action.triggered.connect(self.slot_new_folder) # Template Menu actions self.ui.path_folder.triggered.connect(self.slot_folder_template) self.ui.new_row_action.triggered.connect(self.add_table_empty_line) self.ui.new_template_action.triggered.connect(self.slot_new_template) # Project Tree signals/slots self.tia.attached_cpu.connect(self.print_cpu_tree) self.ui.project_tree.doubleClicked.connect(self.print_blocks_tree) # MainTable widget signals/slots self.ui.tableWidget.cellActivated.connect(self.add_table_empty_line) def slot_connect_tia(self): self.__processes = self.tia.get_running_instances() window = TiaChoose(parent=self, tia=self.__processes) window.return_id.connect(self.tia.attach) window.show() def slot_new_template(self): self.window = TemplateGen() self.window.show() def slot_folder_template(self): options = QtWidgets.QFileDialog.Options() options |= QtWidgets.QFileDialog.DontUseNativeDialog options |= QtWidgets.QFileDialog.ShowDirsOnly self.templates_path = QtWidgets.QFileDialog.getExistingDirectory(self, 'Выбор папки шаблонов', options=options) if self.templates_path: self.update_setting('Settings', 'template_config_path', self.templates_path) if not os.path.exists(self.templates_path + '/templates_params.conf'): self.template_conf = self.templates_path + '/templates_params.conf' self.create_config(self.template_conf) def slot_open_project(self): options = QtWidgets.QFileDialog.Options() options |= QtWidgets.QFileDialog.DontUseNativeDialog fileName, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Select Project file", "", "Project Files (*.prj);;All Files (*)", options=options) if fileName: self.prj_file_path = fileName self.prj_config = self.get_config(fileName) for section in self.prj_config.sections(): if section == 'zones': pass elif section == 'settings': pass else: self.add_project_line(self.prj_config, section) def slot_sync_action(self): self.update_project_tree() def slot_new_folder(self): text, ok = QtWidgets.QInputDialog.getText(self, 'Input Dialog', 'Enter your name:') # QtWidgets.QInputDialog.textValueChanged.connect(test_func()) if ok: self.tia.create_group(text) self.update_project_tree() def test_func(self, text): print(text) def print_cpu_tree(self, cpus): self.model.clear() self.model.setHorizontalHeaderLabels(['Доступные PLC']) self.create_project_tree(cpus, self.model.invisibleRootItem()) def print_blocks_tree(self, cpu): title = self.model.itemFromIndex(cpu).text() self.plc_name = title self.model.clear() self.model.setHorizontalHeaderLabels([title]) self.tia.get_software_object(title) dict_str = self.tia.get_block_structure() self.create_program_blocks_tree(dict_str, self.model.invisibleRootItem()) self.ui.new_folder_action.setEnabled(True) self.ui.sync_action.setEnabled(True) self.ui.import_action.setEnabled(True) self.ui.export_action.setEnabled(True) def update_project_tree(self): self.model.clear() self.model.setHorizontalHeaderLabels([self.plc_name]) self.tia.get_software_object(self.plc_name) dict_str = self.tia.get_block_structure() self.create_program_blocks_tree(dict_str, self.model.invisibleRootItem()) @staticmethod def get_children_list(parent): ret_list = [] for i in range(parent.rowCount()): ret_list.append(parent.child(i)) return ret_list @staticmethod def get_children_index(parent): ret_list = [] for i in range(parent.rowCount()): ret_list.append(parent.child(i).index()) return ret_list def create_tree_items_recursively(self, children, parent): for child in children: child_item = QtGui.QStandardItem(child) parent.appendRow(child_item) if isinstance(children, dict): self.create_project_tree(children[child], child_item) def add_elements_by_path(self, parent, path, elements): """ Рекурсивно проходит по дереву и добавляет блоки elements по пути path :param parent: :param path: :param elements: :return: """ if path: if parent.text() == path[0]: parent.appendRows(elements) return children = self.get_children_list(parent) for child in children: for path_row in path: if child.text() == path_row: if len(path) == 1: child.appendRows(elements) return else: self.add_elements_by_path(child, path[1:], elements) return parent.appendRow(QtGui.QStandardItem(path[0])) children = self.get_children_list(parent) children[-1].setIcon(QtGui.QIcon('icons/folder.ico')) if len(path) == 1: children[-1].appendRows(elements) else: self.add_elements_by_path(children[-1], path[1:], elements) else: parent.appendRows(elements) def create_program_blocks_tree(self, dict_struct, parent): """ Функция создает из словаря структуру папок и блоков :param dict_struct: Словарь полученный от метода tia.get_block_structure() :param parent: Родитель от которого начинается обход дерева :return: """ for line in dict_struct: tia_blocks = [] tia_path = self.parse_tia_folders(line) for i in dict_struct[line]: tia_blocks.append(self.set_block_icon(i)) self.add_elements_by_path(parent, tia_path, tia_blocks) @staticmethod def set_block_icon(block): """ До конца не реализованная функция по установке иконок блокам Щас если в конце имени содержится 'DB', то назначается иконка DB во всех остальных случаях FB иконка :param block: :return: """ item = QtGui.QStandardItem(block) if block[-2:] == 'DB': item.setIcon(QtGui.QIcon('icons/db_block.png')) else: item.setIcon(QtGui.QIcon('icons/fb_block.png')) return item @staticmethod def parse_tia_folders(path): """ Разделяет путь на список папок и убирает знаки '/' :param path: путь к папке в формате строки '/path/to/the/blocks/' :return: список типа ['path', 'to', 'the', 'blocks'] """ temp = path.split('/') return list(filter(None, temp)) def export_blocks(self): for item in self.ui.project_tree.selectedIndexes(): self.tia.export_block(self.model.itemFromIndex(item).text()) print(self.model.itemFromIndex(item).text()) def import_blocks(self): path_tia = None error = 'ERROR' if self.ui.project_tree.selectedIndexes(): group_of_blocks = self.ui.project_tree.selectedIndexes()[0] group_of_blocks = self.model.itemFromIndex(group_of_blocks) if not self.tia.is_block(group_of_blocks.text()): path_tia = self.get_path_by_item(group_of_blocks) options = QtWidgets.QFileDialog.Options() options |= QtWidgets.QFileDialog.DontUseNativeDialog path_to_xml, _ = QtWidgets.QFileDialog.getOpenFileNames(self, 'Выбор файлов для импорта', options=options) for path in path_to_xml: print(path_tia, path) path = path.replace('/', '\\') try: error = self.tia.import_block(path, path_tia) except: self.logger.info(error) self.update_project_tree() def get_path_by_item(self, item): if item.parent(): return self.get_path_by_item(item.parent()) + item.text() + '/' else: return '/' + item.text() + '/' def settings(self): path = 'settings.conf' if not os.path.exists(path): config = configparser.ConfigParser() config.add_section('Settings') config.set('Settings', 'template_config_path', '') with open(path, 'w') as config_file: config.write(config_file) else: config = configparser.ConfigParser() config.read(path) self.templates_path = config.get('Settings', 'template_config_path') def init_project_table(self): self.ui.tableWidget.setColumnCount(18) # Устанавливаем три колонки self.ui.tableWidget.setRowCount(0) # и одну строку в таблице # Устанавливаем заголовки таблицы self.ui.tableWidget.setHorizontalHeaderLabels(['Название блока', 'Шаблон', 'Имя элемента', 'Номер', 'Сброс', 'Безопасность', 'Режим авто', 'Путь', 'Блок вызова', 'Клапан NO/NC', 'Теги', 'Дат. давл. аналог.', 'Дат. давл. дискр', 'SEQ_Pause', 'SEQ_in_Progress', 'Клапан вибросита', 'Триг. фильтров', 'Симулятор']) self.ui.tableWidget.resizeColumnsToContents() def add_table_empty_line(self): self.ui.tableWidget.setRowCount(self.ui.tableWidget.rowCount() + 1) combo_templ = QtWidgets.QComboBox() combo_templ.addItems(self.get_templates_list()) combo_tags = QtWidgets.QComboBox() combo_tags.addItems(['', 'AUX', 'IO', 'AUX+IO']) for column in range(self.ui.tableWidget.columnCount()): self.ui.tableWidget.setItem(self.ui.tableWidget.rowCount() - 1, column, QtWidgets.QTableWidgetItem('')) self.ui.tableWidget.setCellWidget(self.ui.tableWidget.rowCount() - 1, 1, combo_templ) self.ui.tableWidget.setCellWidget(self.ui.tableWidget.rowCount() - 1, 10, combo_tags) def copy_table_line(self, line_num): row_num = self.ui.tableWidget.rowCount() self.ui.tableWidget.setRowCount(row_num + 1) combo_templ = QtWidgets.QComboBox() combo_templ.addItems(self.get_templates_list()) self.ui.tableWidget.setCellWidget(row_num, 1, combo_templ) self.ui.tableWidget.setItem(row_num, 0, QtWidgets.QTableWidgetItem("Texfffff")) self.ui.tableWidget.resizeColumnsToContents() def get_row_table(self, row): ret = [] for i in range(self.ui.tableWidget.columnCount()): print(i) if i == 1: ret.append(self.get_templ_from_table(row)) elif i == 10: ret.append(self.get_tags_from_table(row)) else: ret.append(self.ui.tableWidget.item(row, i).text()) return ret def get_templ_from_table(self, row): return self.ui.tableWidget.cellWidget(row, 1).currentText() def get_tags_from_table(self, row): return self.ui.tableWidget.cellWidget(row, 10).currentText() def add_project_line(self, project, section): row_num = self.ui.tableWidget.rowCount() self.ui.tableWidget.setRowCount(row_num + 1) combo_templ = QtWidgets.QComboBox() combo_templ.addItems(self.get_templates_list()) combo_tags = QtWidgets.QComboBox() combo_tags.addItems(['', 'AUX', 'IO', 'AUX+IO']) counter = 1 self.ui.tableWidget.setItem(row_num, 0, QtWidgets.QTableWidgetItem(section)) for option in project.options(section): value = project.get(section, option) if option == 'шаблон': self.ui.tableWidget.setCellWidget(row_num, 1, combo_templ) self.ui.tableWidget.cellWidget(row_num, 1).setCurrentText(value) elif option == 'теги': self.ui.tableWidget.setCellWidget(row_num, 10, combo_tags) self.ui.tableWidget.cellWidget(row_num, 10).setCurrentText(value) else: self.ui.tableWidget.setItem(row_num, counter, QtWidgets.QTableWidgetItem(value)) counter += 1 self.ui.tableWidget.resizeColumnsToContents() def save_project(self): new_config = configparser.ConfigParser() for row in range(self.ui.tableWidget.rowCount()): new_config.add_section(self.ui.tableWidget.item(row, 0).text()) for column in range(1, self.ui.tableWidget.columnCount()): if column == 1 or column == 10: new_config.set(self.ui.tableWidget.item(row, 0).text(), self.ui.tableWidget.horizontalHeaderItem(column).text(), self.ui.tableWidget.cellWidget(row, column).currentText()) else: new_config.set(self.ui.tableWidget.item(row, 0).text(), self.ui.tableWidget.horizontalHeaderItem(column).text(), self.ui.tableWidget.item(row, column).text()) with open(self.prj_file_path, 'w') as config_file: new_config.write(config_file) def save_project_as(self): options = QtWidgets.QFileDialog.Options() options |= QtWidgets.QFileDialog.DontUseNativeDialog # Qt's builtin File Dialogue fileName, _ = QtWidgets.QFileDialog.getSaveFileName(self, "Open", "", "All Files (*.prj)", options=options) if fileName: print(fileName[-4:]) if fileName[-4:] == '.prj': self.prj_file_path = fileName else: self.prj_file_path = fileName + '.prj' print(self.prj_file_path) self.save_project() @staticmethod def get_templates_list(): # Каталог из которого будем брать шаблоны directory = 'templates' # Получаем список файлов в переменную files files = os.listdir(directory) # Фильтруем список templ = list(filter(lambda x: x.endswith('.tpl'), files)) ret = [] for item in templ: ret.append(item[:-4]) return ret @staticmethod def get_config(path): """ Returns the config object """ if os.path.exists(path): config = configparser.ConfigParser() config.read(path) return config def update_setting(self, section, setting, value): """ Update a setting """ path = 'settings.conf' config = self.get_config(path) config.set(section, setting, value) with open(path, 'w') as config_file: config.write(config_file) def init_logger(self): """ Initialization logger function to print information to log file :return: """ self.logger = logging.getLogger("MyWindow") self.logger.setLevel(logging.INFO) # create the logging file handler fh = logging.FileHandler("logs.log") formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') fh.setFormatter(formatter) # add handler to logger object self.logger.addHandler(fh)
class MainWindow(QMainWindow, QObject): def __init__(self, parent=None): super().__init__(parent) self.ui = Ui_MainWindow() self.ui.setupUi(self) self.setWindowTitle('dev_window') # Все действия к прикрепляемым окнам поместим в меню for dock in self.findChildren(QDockWidget): self.ui.menuDockWindow.addAction(dock.toggleViewAction()) # Все действия к toolbar'ам окнам поместим в меню for tool in self.findChildren(QToolBar): self.ui.menuTools.addAction(tool.toggleViewAction()) # Выполнение кода в окне "Выполнение скрипта" self.ui.button_exec.clicked.connect(self.exec_script) try: self.code_editor = create_code_editor() self.ui.container_code_editor.setWidget(self.code_editor) except Exception as e: logger.warn(e) self.code_editor = QPlainTextEdit() self.ui.container_code_editor.setWidget(self.code_editor) self.write_code_to_editor() self.timer_save_code = QTimer() self.timer_save_code.setSingleShot(True) self.timer_save_code.setInterval(300) self.timer_save_code.timeout.connect(self.save_code_from_editor) self.code_editor.textChanged.connect(self.timer_save_code.start) OUTPUT_LOGGER_STDOUT.emit_write.connect(self.write_output) OUTPUT_LOGGER_STDERR.emit_write.connect(self.write_output) def save_code_from_editor(self): logger.debug('Save code from editor to file: %s. Start.', CODE_EDITOR_BACKUP) with open(CODE_EDITOR_BACKUP, mode='w', encoding='utf-8') as f: f.write(self.code_editor.toPlainText()) logger.debug('Finish save code from editor.') def write_code_to_editor(self): logger.debug('Write code to editor in file: %s. Start.', CODE_EDITOR_BACKUP) try: with open(CODE_EDITOR_BACKUP, encoding='utf-8') as f: content = f.read() try: self.code_editor.setPlainText(content, None, None) except: self.code_editor.setPlainText(content) except Exception as e: logger.warn(e) logger.debug('Finish write code to editor.') def exec_script(self): try: has_selected = self.code_editor.textCursor().hasSelection() if has_selected: # http://doc.qt.io/qt-4.8/qtextcursor.html#selectedText # Note: If the selection obtained from an editor spans a line break, the text will contain a # Unicode U+2029 paragraph separator character instead of a newline \n character. Use QString::replace() # to replace these characters with newlines. code = self.code_editor.textCursor().selectedText() code = code.replace('\u2028', '\n').replace('\u2029', '\n') else: code = self.code_editor.toPlainText() exec(code.strip()) except Exception as e: import traceback # Выводим ошибку в консоль traceback.print_exc() # Сохраняем в переменную tb = traceback.format_exc() last_error_message = str(e) last_detail_error_message = str(tb) message = last_error_message + '\n\n' + last_detail_error_message mb = QErrorMessage() mb.setWindowTitle('Error') # Сообщение ошибки содержит отступы, символы-переходы на следующую строку, # которые поломаются при вставке через QErrorMessage.showMessage, и нет возможности # выбрать тип текста, то делаем такой хак. mb.findChild(QTextEdit).setPlainText(message) mb.exec_() def write_output(self, text, severity): """Функция для добавления сообщения с указанием серьезности (Debug, Error).""" # save text_cursor = self.ui.output.textCursor() orig_fmt = text_cursor.charFormat() fmt = QTextCharFormat() # modify if severity == OutputLogger.Severity.ERROR: fmt.setFontWeight(QFont.DemiBold) fmt.setForeground(Qt.red) # append text_cursor.movePosition(QTextCursor.End) text_cursor.setCharFormat(fmt) text_cursor.insertText(text) # restore text_cursor.setCharFormat(orig_fmt) def clear_slog(self): self.ui.simple_log.clear() def slog(self, *args, **kwargs): """Функция для добавления текста в виджет-лог, находящегося на форме.""" try: # Используем стандартный print для печати в строку str_io = io.StringIO() kwargs['file'] = str_io kwargs['end'] = '' print(*args, **kwargs) text = str_io.getvalue() self.ui.simple_log.appendPlainText(text) except Exception as e: self.ui.simple_log.appendPlainText(str(e)) def read_settings(self): # TODO: при сложных настройках, лучше перейти на json или yaml config = QSettings(CONFIG_FILE, QSettings.IniFormat) self.restoreState(config.value('MainWindow_State')) self.restoreGeometry(config.value('MainWindow_Geometry')) def write_settings(self): config = QSettings(CONFIG_FILE, QSettings.IniFormat) config.setValue('MainWindow_State', self.saveState()) config.setValue('MainWindow_Geometry', self.saveGeometry()) def closeEvent(self, event): self.write_settings() quit()
""" Main module for PyReddit """ from mainwindow_ui import Ui_MainWindow from PyQt4 import QtGui if __name__ == "__main__": import sys APP = QtGui.QApplication(sys.argv) MAIN_WIN = QtGui.QMainWindow() UI = Ui_MainWindow() UI.setupUi(MAIN_WIN) MAIN_WIN.show() sys.exit(APP.exec_())
class MainWindow(QMainWindow): def __init__(self, parent=None): super().__init__(parent) self.ui = Ui_MainWindow() self.ui.setupUi(self) self.docsModel = QSqlTableModel() # self.docsModel = QSqlRelationalTableModel() self.docsModel.setTable('DOCUMENTS') # self.docsModel.setRelation(2, QSqlRelation('THEMES', 'ID', 'NAME')) self.docsModel.setEditStrategy(QSqlTableModel.OnManualSubmit) self.docsModel.select() self.docsModel.setHeaderData(1, Qt.Horizontal, "Путь к файлу") self.docsModel.setHeaderData(2, Qt.Horizontal, "Тема") self.ui.docsView.setModel(self.docsModel) # self.ui.docsView.setItemDelegate(QSqlRelationalDelegate(self.ui.docsView)) self.ui.docsView.horizontalHeader().setStretchLastSection(True) self.updateThemes() self.ui.themes.header().setStretchLastSection(True) self.ui.themes.setHeaderHidden(True) self.ui.themes.itemSelectionChanged.connect(self.themes_selectionChanged) self.ui.themes.setCurrentItem(self.root_theme) self.ui.actionQuit.triggered.connect(self.close) self.ui.actionAdd.triggered.connect(self.add) self.ui.actionDelete.triggered.connect(self.delete) self.read_settings() def themes_selectionChanged(self): item = self.ui.themes.currentItem() if item: if item is self.root_theme: self.docsModel.setFilter(None) else: # pid = item.data(0, Qt.UserRole)[0] # self.docsModel.setFilter('ID_THEME = {}'.format(pid)) name = item.data(0, Qt.UserRole)[1] self.docsModel.setFilter('THEME = "{}"'.format(name)) def updateThemes(self): self.ui.themes.clear() self.root_theme = QTreeWidgetItem(['Все темы']) self.ui.themes.addTopLevelItem(self.root_theme) query = QSqlQuery() query.exec_('SELECT ID, NAME FROM THEMES') while query.next(): pid = query.value(0) name = query.value(1) child = QTreeWidgetItem([name]) child.setData(0, Qt.UserRole, [pid, name]) self.root_theme.addChild(child) self.ui.themes.expandAll() def add(self): d = DocDialog() d.exec_() # TODO: обновлять когда диалог закрывается на Ок self.docsModel.select() def delete(self): pass def read_settings(self): ini = QSettings('settings.ini') self.restoreGeometry(ini.value('MainWindow_Geometry')) self.restoreState(ini.value('MainWindow_State')) self.ui.splitter.restoreState(ini.value('Splitter_State')) def write_settings(self): ini = QSettings('settings.ini') ini.setValue('MainWindow_State', self.saveState()) ini.setValue('MainWindow_Geometry', self.saveGeometry()) ini.setValue('Splitter_State', self.ui.splitter.saveState()) def closeEvent(self, *args, **kwargs): self.write_settings() super().closeEvent(*args, **kwargs)
class Window(QMainWindow): def __init__(self): QMainWindow.__init__(self) self.ui = Ui_MainWindow() self.ui.setupUi(self) self.setWindowIcon(QIcon(":/network.svg")) # fix stuff imposible to do in qtdesigner # remove dock titlebar for addressbar w = QWidget() self.ui.addrDockWidget.setTitleBarWidget(w) # tabify some docks self.tabifyDockWidget(self.ui.evDockWidget, self.ui.subDockWidget) self.tabifyDockWidget(self.ui.subDockWidget, self.ui.refDockWidget) # we only show statusbar in case of errors self.ui.statusBar.hide() # setup QSettings for application and get a settings object QCoreApplication.setOrganizationName("FreeOpcUa") QCoreApplication.setApplicationName("OpcUaClient") self.settings = QSettings() self._address_list = self.settings.value("address_list", [ "opc.tcp://localhost:4840", "opc.tcp://localhost:53530/OPCUA/SimulationServer/" ]) self._address_list_max_count = int( self.settings.value("address_list_max_count", 10)) # init widgets for addr in self._address_list: self.ui.addrComboBox.insertItem(-1, addr) self.uaclient = UaClient() self.tree_ui = TreeWidget(self.ui.treeView) self.tree_ui.error.connect(self.show_error) self.refs_ui = RefsWidget(self.ui.refView) self.refs_ui.error.connect(self.show_error) self.attrs_ui = AttrsWidget(self.ui.attrView) self.attrs_ui.error.connect(self.show_error) self.datachange_ui = DataChangeUI(self, self.uaclient) self.event_ui = EventUI(self, self.uaclient) self.ui.addrComboBox.currentTextChanged.connect(self._uri_changed) self._uri_changed(self.ui.addrComboBox.currentText() ) # force update for current value at startup self.ui.treeView.activated.connect(self.show_refs) self.ui.treeView.clicked.connect(self.show_refs) self.ui.actionCopyPath.triggered.connect(self.tree_ui.copy_path) self.ui.actionCopyNodeId.triggered.connect(self.tree_ui.copy_nodeid) # add items to context menu self.ui.treeView.addAction(self.ui.actionCopyPath) self.ui.treeView.addAction(self.ui.actionCopyNodeId) self.ui.treeView.activated.connect(self.show_attrs) self.ui.treeView.clicked.connect(self.show_attrs) self.ui.attrRefreshButton.clicked.connect(self.show_attrs) self.resize(int(self.settings.value("main_window_width", 800)), int(self.settings.value("main_window_height", 600))) data = self.settings.value("main_window_state", None) if data: self.restoreState(data) self.ui.connectButton.clicked.connect(self.connect) self.ui.disconnectButton.clicked.connect(self.disconnect) # self.ui.treeView.expanded.connect(self._fit) self.ui.actionConnect.triggered.connect(self.connect) self.ui.actionDisconnect.triggered.connect(self.disconnect) self.ui.connectOptionButton.clicked.connect( self.show_connection_dialog) def _uri_changed(self, uri): self.uaclient.load_security_settings(uri) def show_connection_dialog(self): dia = ConnectionDialog(self, self.ui.addrComboBox.currentText()) dia.security_mode = self.uaclient.security_mode dia.security_policy = self.uaclient.security_policy dia.certificate_path = self.uaclient.certificate_path dia.private_key_path = self.uaclient.private_key_path ret = dia.exec_() if ret: self.uaclient.security_mode = dia.security_mode self.uaclient.security_policy = dia.security_policy self.uaclient.certificate_path = dia.certificate_path self.uaclient.private_key_path = dia.private_key_path @trycatchslot def show_refs(self, idx): node = self.get_current_node(idx) if node: self.refs_ui.show_refs(node) @trycatchslot def show_attrs(self, idx): if not isinstance(idx, QModelIndex): idx = None node = self.get_current_node(idx) if node: self.attrs_ui.show_attrs(node) def show_error(self, msg): logger.warning("showing error: %s") self.ui.statusBar.show() self.ui.statusBar.setStyleSheet( "QStatusBar { background-color : red; color : black; }") self.ui.statusBar.showMessage(str(msg)) QTimer.singleShot(1500, self.ui.statusBar.hide) def get_current_node(self, idx=None): return self.tree_ui.get_current_node(idx) def get_uaclient(self): return self.uaclient @trycatchslot def connect(self): uri = self.ui.addrComboBox.currentText() try: self.uaclient.connect(uri) except Exception as ex: self.show_error(ex) raise self._update_address_list(uri) self.tree_ui.set_root_node(self.uaclient.client.get_root_node()) def _update_address_list(self, uri): if uri == self._address_list[0]: return if uri in self._address_list: self._address_list.remove(uri) self._address_list.insert(0, uri) if len(self._address_list) > self._address_list_max_count: self._address_list.pop(-1) def disconnect(self): try: self.uaclient.disconnect() except Exception as ex: self.show_error(ex) raise finally: self.tree_ui.clear() self.refs_ui.clear() self.attrs_ui.clear() self.datachange_ui.clear() self.event_ui.clear() def closeEvent(self, event): self.tree_ui.save_state() self.attrs_ui.save_state() self.refs_ui.save_state() self.settings.setValue("main_window_width", self.size().width()) self.settings.setValue("main_window_height", self.size().height()) self.settings.setValue("main_window_state", self.saveState()) self.settings.setValue("address_list", self._address_list) self.disconnect() event.accept()
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): def __init__(self): QtWidgets.QMainWindow.__init__(self) Ui_MainWindow.__init__(self) self.global_start_time = time.strftime('%Y%m%d_%H%M') self.ui = Ui_MainWindow() self.ui.setupUi(self) self.setWindowTitle("OptoWorld") self.start_mqtt() self.ui.button_lightswitch.clicked.connect(self.button_clicked) self.ui.actionedit_light_profile.triggered.connect( self.edit_light_profile) self.ui.actionshow_live_graphs.triggered.connect( self.toggle_live_graphs) self.make_graphs() if not os.path.exists(f"{HOME}/optoworld_logs"): os.mkdir(f"{HOME}/optoworld_logs") def start_mqtt(self): start_thread = Thread(target=self.start_mqtt_thread, ) start_thread.start() def start_mqtt_thread(self): self.connected = False start_time = time.time() while not self.connected: try: self.mqtt_listener = MQTT_Listener(BROKER_IP, "listener") self.ui.label_mqtt_status.setText("Connected to Broker") self.ui.label_mqtt_status.setStyleSheet("color: green") self.mqtt_listener.signals.new_status.connect( self.update_status_labels) self.mqtt_listener.signals.disconnected.connect( self.start_mqtt) self.threadpool = QtCore.QThreadPool() self.threadpool.start(self.mqtt_listener) self.connected = True except Exception as e: self.ui.label_mqtt_status.setText( f"Broker not found. ({int(time.time()-start_time)}s)") self.ui.label_mqtt_status.setStyleSheet("color: red") self.connected = False sys.stdout.write(str(e)) time.sleep(1) self.plotting = False self.ui.framePlotWidget.setVisible(False) def keyPressEvent(self, event): if event.key() == QtCore.Qt.Key_Q: self.close() elif event.key() == QtCore.Qt.Key_Plus: self.send_light_value(255) elif event.key() == QtCore.Qt.Key_Minus: self.send_light_value(0) def edit_light_profile(self): if not hasattr(self, "stim_widget"): self.stim_widget = Stim_widget(parent=self) self.dock = self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, self.stim_widget) # self.dock.setWidget(self.stim_widget) self.stim_widget.show() def button_clicked(self): self.send_light_value(self.ui.slider_light.value()) def send_light_value(self, val): switch = client.Client("Yay") switch.connect(BROKER_IP, port=1883) switch.publish("optoworld/switch", val) switch.disconnect() def update_status_labels(self, m): temperature, light_value, light_intensity = str(m).split("_") self.ui.label_status_temperature.setText( f"Temperature: {temperature} C") self.ui.label_status_light.setText(f"Light Value: {light_value}") self.ui.label_status_light_intensity.setText( f"Light Level: {light_intensity} lux") df = pd.DataFrame() df["date"] = [datetime.datetime.now().strftime("%Y%m%d")] df["time"] = [time.strftime("%H:%M:%S")] # df["time"] = time.time()? df["temperature"] = [float(temperature)] df["value"] = [int(light_value)] df["intensity"] = [float(light_intensity)] try: self.df = pd.concat([self.df, df], ignore_index=True) except Exception as e: self.df = df if self.plotting == True: self.update_plots(self.df[-100:]) def toggle_live_graphs(self): if self.plotting == False: self.plotting = True self.ui.framePlotWidget.setVisible(True) else: self.plotting = False self.ui.framePlotWidget.setVisible(False) def update_plots(self, df): try: frame_height = self.ui.framePlotWidget.size().height() if frame_height < 700: fs = 6 elif frame_height > 700 and frame_height < 800: fs = 8 else: fs = 10 self.axes_temperature.clear() self.axes_temperature.plot(df["time"], df["temperature"]) self.axes_temperature.set_ylabel('Temperature (C)', fontsize=fs) self.axes_intensity.clear() # self.axes_intensity.set_ylim(0,1050) self.axes_intensity.plot(df["time"], df["intensity"]) self.axes_intensity.set_ylabel('Intensity (lux)', fontsize=fs) self.axes_light_value.clear() self.axes_light_value.set_ylim(0, 300) self.axes_light_value.plot(df["time"], df["value"]) self.axes_light_value.set_ylabel('Value (0-255)', fontsize=fs) for ax in [ self.axes_temperature, self.axes_intensity, self.axes_light_value ]: ax.set_xlabel("Time") ax.xaxis.set_major_locator(plt.MaxNLocator(15)) self.plot.canvas.figure.autofmt_xdate() self.plot.draw() # self.plot.canvas.figure.tight_layout() except Exception as e: print(str(e)) def make_graphs(self): # self.plot_temperature = PlotWidget() # self.plot_light_intensity = PlotWidget() # self.plot_light_value = PlotWidget() self.plot = PlotWidget() self.ui.framePlotWidget.setLayout(QtWidgets.QVBoxLayout()) self.ui.framePlotWidget.layout().addWidget(self.plot) self.axes_temperature = self.plot.canvas.figure.add_subplot(311) self.axes_intensity = self.plot.canvas.figure.add_subplot(312) self.axes_light_value = self.plot.canvas.figure.add_subplot(313) # for widget in [self.plot_light_intensity, self.plot_light_value, self.plot_temperature]: # self.ui.framePlotWidget.layout().addWidget(widget) # self.axes_temperature = self.plot_temperature.canvas.figure.gca() # self.axes_intensity = self.plot_light_intensity.canvas.figure.gca() # self.axes_light_value = self.plot_light_value.canvas.figure.gca() def closeEvent(self, event): switch_off = QtWidgets.QMessageBox.question( self, "Switch Off?", "Do you want to switch off the light on closing?", QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No) if switch_off == QtWidgets.QMessageBox.Yes: self.send_light_value(0) else: pass sys.stdout.write( "\n\n Closing... \n\n Killing mqtt-monitor thread.... \n") self.mqtt_listener.alive = False self.mqtt_listener.client.disconnect() try: self.stim_widget.timer.alive = False self.stim_widget.timer.client.disconnect() sys.stdout.write("\nCleaning up remaining timer-threads...") except: sys.stdout.write("\nNo remaining timer-threads found") self.df.to_csv( f"{HOME}/optoworld_logs/MAIN_LOG_{self.global_start_time}_to_{time.strftime('%Y%m%d_%H%M')}.csv", sep="\t") sys.stdout.write("\n\nGood Bye") event.accept()
class mainWindowUI(QMainWindow): #mainwindow inheriting from QMainWindow here. def __init__(self): QDialog.__init__( self ) # Constructs a dialog with parent parent. self being ImageDailog # Set up the UI from Designer: self.ui = Ui_MainWindow() self.ui.setupUi(self) self.ui.graphicsView.DontAdjustForAntialiasing #seems to help fix artifacts left by mouse track markers #make a scene: self.scene = QtGui.QGraphicsScene() #set it to show in the graphicsview window: self.ui.graphicsView.setScene(self.scene) self.items = [QtGui.QGraphicsTextItem(), QtGui.QGraphicsRectItem() ] #for squares and indexes that follow mouse self.ui.graphicsView.viewport().installEventFilter( self) #for mouse functions #Setup IO table on right self.ui.tableWidget.resizeColumnToContents(0) self.ui.tableWidget.resizeColumnToContents(1) self.ui.tableWidget.setColumnWidth(2, 50) self.ui.tableWidget.setColumnWidth(3, 40) #setup datagrid and elements: self.Tools = elementList(elementStruct) self.setupDataGrid() #set up rung variables: self.signalConnections() #default: self.currentHW = "Waltech" self.projectName = None self.currentFileDir = None def signalConnections(self): #connect signals: self.ui.actionUndo.triggered.connect(self.unDo) self.ui.actionRedo.triggered.connect(self.reDo) self.ui.actionSave_As.triggered.connect(self.saveFileAs) self.ui.actionSave.triggered.connect(self.saveFile) self.ui.actionOpen.triggered.connect(self.openFile) self.ui.actionNew.triggered.connect(self.newFile) self.ui.actionWhatsThis.triggered.connect(self.whatsThis) self.ui.actionCheck_HW_2.triggered.connect(self.checkHW) self.ui.actionUSBHelp.triggered.connect(self.USBHelp) self.ui.actionArduino_IO.triggered.connect(self.ArduinoIOHelp) self.ui.actionAbout.triggered.connect(self.AboutHelp) self.ui.infoButton.clicked.connect(self.parseGrid) #FOR DEBUG BUTTON #self.ui.pushButton.clicked.connect(self.showInfo) #self.ui.pushButton_3.clicked.connect(self.printLadder) #action group for tool buttons: self.connect(self.ui.actionContNO, QtCore.SIGNAL("triggered()"), lambda who="contNO": self.anyButton(who)) self.connect(self.ui.actionContNC, QtCore.SIGNAL("triggered()"), lambda who="contNC": self.anyButton(who)) self.connect(self.ui.actionCoil, QtCore.SIGNAL("triggered()"), lambda who="Coil": self.anyButton(who)) #self.connect(self.ui.actionCoilNot, QtCore.SIGNAL("triggered()"),lambda who="CoilNot": self.anyButton(who)) self.connect(self.ui.actionaddRung, QtCore.SIGNAL("triggered()"), lambda who="addRung": self.anyButton(who)) self.connect(self.ui.actionWiden, QtCore.SIGNAL("triggered()"), lambda who="Widen": self.anyButton(who)) #self.connect(self.ui.actionORbranch, QtCore.SIGNAL("triggered()"),lambda who="blankOR": self.anyButton(who)) self.connect(self.ui.actionDEL, QtCore.SIGNAL("triggered()"), lambda who="Del": self.anyButton(who)) self.connect(self.ui.actionORwire, QtCore.SIGNAL("triggered()"), lambda who="ORwire": self.anyButton(who)) self.connect(self.ui.actionNarrow, QtCore.SIGNAL("triggered()"), lambda who="Narrow": self.anyButton(who)) #self.connect(self.ui.actionRising, QtCore.SIGNAL("triggered()"),lambda who="Rising": self.anyButton(who)) self.connect(self.ui.actionFalling, QtCore.SIGNAL("triggered()"), lambda who="Fall": self.anyButton(who)) self.connect(self.ui.actionTimer, QtCore.SIGNAL("triggered()"), lambda who="Timer": self.anyButton(who)) self.connect(self.ui.actionCounter, QtCore.SIGNAL("triggered()"), lambda who="Counter": self.anyButton(who)) #make a actiongroup so tools are exclusive (only one clicked) toolActionGroup = QActionGroup( self.ui.toolBar) #toolbar is named in _ui.py toolActionGroup.addAction(self.ui.actionContNO) toolActionGroup.addAction(self.ui.actionContNC) toolActionGroup.addAction(self.ui.actionCoil) #toolActionGroup.addAction(self.ui.actionCoilNot) toolActionGroup.addAction(self.ui.actionaddRung) toolActionGroup.addAction(self.ui.actionWiden) #toolActionGroup.addAction(self.ui.actionORbranch) toolActionGroup.addAction(self.ui.actionDEL) toolActionGroup.addAction(self.ui.actionORwire) toolActionGroup.addAction(self.ui.actionNarrow) #toolActionGroup.addAction(self.ui.actionRising) toolActionGroup.addAction(self.ui.actionFalling) toolActionGroup.addAction(self.ui.actionTimer) toolActionGroup.addAction(self.ui.actionCounter) toolActionGroup.setExclusive(True) self.connect(self.ui.actionWaltech, QtCore.SIGNAL("triggered()"), lambda HW="Waltech": self.chooseHW(HW)) self.connect(self.ui.actionArduino, QtCore.SIGNAL("triggered()"), lambda HW="Arduino": self.chooseHW(HW)) hwActionGroup = QActionGroup(self.ui.menuDiagnostics) hwActionGroup.addAction(self.ui.actionWaltech) hwActionGroup.addAction(self.ui.actionArduino) def checkmarkHW(self): print "hardware clicked" def chooseHW(self, HW): self.currentHW = HW if str(HW) == "Waltech": pass if str(HW) == "Arduino": #self.ui.actionArduino.setChecked(True) self.dialog = popupDialogs.ardIODialog() self.dialog.exec_() # For Modal dialogs print "Hardware:", HW def USBHelp(self): self.dialog = popupDialogs.USBHelpDialog() self.dialog.exec_() # For Modal dialogs def ArduinoIOHelp(self): self.dialog = popupDialogs.ArduinoIOHelpDialog() self.dialog.exec_() # For Modal dialogs def AboutHelp(self): self.dialog = popupDialogs.AboutHelpDialog() self.dialog.exec_() # For Modal dialogs def checkHW(self): plat = sys.platform.lower( ) # try to detect the OS so that a device can be selected... print "checked platform" if plat[:5] == 'linux': opSys = "NIX" elif plat == 'win32': opSys = "WIN" else: opSys = "WIN" tester(opSys, self.currentHW).test1(self.ui.textBrowser) def printLadder(self): #printer = QPrinter(QPrinter.HighResolution) printer = QPrinter() dialog = QtGui.QPrintDialog(printer, self) if dialog.exec_() != QDialog.Accepted: return #printer.setResolution(600) #resolution = printer.resolution() #pageRect = printer.pageRect() painter = QPainter(printer) self.scene.render(painter) #self.ui.tableWidget.render(painter) del painter def makeImage(self): #def printLadder(self): image = QtGui.QImage(400, 400, QtGui.QImage.Format_ARGB32) #for png #image = QtGui.QImage(256,256,QtGui.QImage.Format_RGB32) painter = QtGui.QPainter(image) painter.setRenderHint(QtGui.QPainter.Antialiasing) self.scene.render(painter) painter.end() print "saving image" if image.save('hexes/newImage.png', 'PNG'): print('saved') else: print("didn't save") #image.save("out.png") del painter def setupDataGrid(self): #x,y, element there, rung there, & there, element name, variable name, i/o connection. self.grid = [ [] ] # grid: list of rows ex: grid [2][6] gives cell 6 in row(rung) 2 self.reDoGrid = [[[]]] # list of grids for redo self.unDoGrid = [[[]]] # list of grids for undo self.currentTool = 0 #to track the tool being used width = 10 for i in range(width): #fill the first row self.grid[0].append( cellStruct(i * 60, 60, "MT", "Rung", None, None, None, None, False, False, False, False, False, False)) for i in range(1, 6): # add 5 more rungs to start ManageGrid(self.grid, self.scene, self.Tools, self.items).insertRung(i) def reFillList(self, uiList): #clear list rows = uiList.rowCount() for i in range(rows): #delete this row uiList.removeRow(0) #refill list print "refilling list" height = len(self.grid) width = len(self.grid[0]) for i in range(height): for j in range(width): if self.grid[i][j].MTorElement != "MT" and self.grid[i][ j].MTorElement != "blankOR": uiList.setRowCount(uiList.rowCount() + 1) numRows = uiList.rowCount() try: uiList.setItem( numRows - 1, 0, QtGui.QTableWidgetItem( self.grid[i][j].variableName)) except: pass try: uiList.setItem( numRows - 1, 1, QtGui.QTableWidgetItem(self.grid[i][j].ioAssign)) except: pass try: uiList.setItem( numRows - 1, 2, QtGui.QTableWidgetItem( self.grid[i][j].MTorElement)) except: pass try: uiList.setItem( numRows - 1, 3, QtGui.QTableWidgetItem(str(i) + "," + str(j))) except: pass #track which tool is being used. maybe use names here? def anyButton(self, who): self.currentTool = who def parseGrid(self): #self.showInfo() font = self.ui.textBrowser.currentFont() font.setWeight(QFont.Bold) self.ui.textBrowser.setCurrentFont(font) self.ui.textBrowser.setText("compiling with avr-gcc") QApplication.processEvents( ) #this makes the UI update before going on. font.setWeight(QFont.Normal) self.ui.textBrowser.setCurrentFont(font) outLine = ladderToOutLine(self.grid).makeOutLine() OutLineToC(self.grid, self.currentHW).makeC(outLine, self.ui.textBrowser) #hexMaker(self).self.saveCfileAndCompile(C_txt,displayOutputPlace) def showInfo(self): ManageGrid(self.grid, self.scene, self.Tools, self.items).reportCellInfo() #ManageGrid(self.grid, self.scene,self.Tools,self.items).showCellData() ManageGrid(self.grid, self.scene, self.Tools, self.items).findStartsAndEnds() ManageGrid(self.grid, self.scene, self.Tools, self.items).reportCellStartsEnds() def unDo(self): if len(self.unDoGrid) > 1: self.reDoGrid.append(copy.deepcopy( self.grid)) #save this grid for re-do self.grid = copy.deepcopy( self.unDoGrid[-1]) #make current grid last one in undo self.unDoGrid.pop() #delete last one in undo ManageGrid(self.grid, self.scene, self.Tools, self.items).totalRedraw() print("undone") else: print("no more undoes") def reDo(self): if len(self.reDoGrid) > 1: self.unDoGrid.append(copy.deepcopy( self.grid)) #save this grid for re-do if len(self.unDoGrid) > 20: #limit to 20 undos self.unDoGrid.pop(0) #pop 0 self.grid = copy.deepcopy(self.reDoGrid[-1]) self.reDoGrid.pop() ManageGrid(self.grid, self.scene, self.Tools, self.items).totalRedraw() print("redone") else: print("no more redoes") def newFile(self): #verify popup self.clearList(self.ui.tableWidget) self.setupDataGrid() #set up rung variables: def saveFile(self): if self.projectName == None: format = "wlm" initialPath = os.getcwd() + "/untitled." + format filename = QtGui.QFileDialog.getSaveFileName( self, 'Save As', initialPath) self.projectName = filename else: filename = self.projectName print "filename", filename f = open(filename, 'w') pickle.dump(self.grid, f) f.close() def saveFileAs(self): format = "wlm" if self.currentFileDir == None: initialPath = os.getcwd() + "/untitled." + format else: initialPath = self.currentFileDir + "untitled." + format filename = QtGui.QFileDialog.getSaveFileName(self, 'Save As', initialPath) import ntpath justName = ntpath.basename(str(filename)) self.currentFileDir = filename[0:(len(filename) - len(justName))] self.projectName = filename print "filename", filename f = open(filename, 'w') pickle.dump(self.grid, f) f.close() def openFile(self): filedialog = QtGui.QFileDialog() #filedialog.setNameFilter('*.jpg') filename = filedialog.getOpenFileName(self, 'Open File', os.path.expanduser("~"), "*.wlm") f = open(filename, 'r') import ntpath justName = ntpath.basename(str(filename)) self.currentFileDir = filename[0:(len(filename) - len(justName))] self.projectName = filename self.grid = pickle.load(f) f.close() #check width and height, make bounding box ManageGrid(self.grid, self.scene, self.Tools, self.items).changeRectangle() ManageGrid(self.grid, self.scene, self.Tools, self.items).totalRedraw() self.reFillList(self.ui.tableWidget) def whatsThis(self): QtGui.QWhatsThis.enterWhatsThisMode() def eventFilter(self, source, event): if event.type() == QtCore.QEvent.MouseMove: self.eraseMarker() cellNum = self.findCell(event) self.showMarker(cellNum) elif event.type() == QtCore.QEvent.Leave or event.type( ) == QtCore.QEvent.Wheel: self.eraseMarker() elif event.type() == QtCore.QEvent.MouseButtonPress: self.eraseMarker() cellNum = self.findCell(event) if cellNum != [None, None, None, None]: if event.button() == QtCore.Qt.LeftButton: print "left" self.leftClick(cellNum) elif event.button() == QtCore.Qt.RightButton: print "right" self.rightClick(cellNum) #if cellNum == [None,None,None,None]: else: pass # do other stuff return QtGui.QMainWindow.eventFilter(self, source, event) #self.ui.graphicsView.viewport().installEventFilter(self) def findCell(self, event): #Pos = event.globalPos() #doesn't stay when window moves #Pos = event.pos()# offset -60,-50 #Pos = self.ui.graphicsView.mapToScene(event.globalPos()) #doesn't stay when window moves Pos = self.ui.graphicsView.mapToScene(event.pos()) #things that don't work: #Pos = event.screenPos() #Pos = self.ui.graphicsView.mapToScene(event.screenPos()) #Qmousevent has no attribute screenPos #Pos = event.scenePos() #Pos = self.ui.graphicsView.mapToScene(event.scenePos()) #Qmousevent has no attribute scenePos #x=Pos.x()-172 x = Pos.x() - 30 y = Pos.y() + 60 self.ui.label_2.setNum(x) # set x,y display values self.ui.label_4.setNum(y) if 1 == 1: #pos = self.ui.graphicsView.mapToScene(event.pos()) #pos = event.pos() #x = pos.x()-30 #y = pos.y()+60 cellNum = [None, None, None, None] for i in range(len( self.grid)): #cellNum[0]=i #backwards: row,col for j in range(len(self.grid[i])): if (self.grid[i][j].midPointX - 30 < x < self.grid[i][j].midPointX + 30) and ( self.grid[i][j].midPointY - 30 < y < self.grid[i][j].midPointY + 30): cellNum = [i, j, None, None] if y < self.grid[cellNum[0]][ cellNum[1]].midPointY: #insert above cellNum[2] = "up" else: #insert below cellNum[2] = "dn" if x < self.grid[cellNum[0]][ cellNum[1]].midPointX: #insert left or right cellNum[3] = "rt" else: cellNum[3] = "lt" return cellNum def eraseMarker(self): itemlist = self.scene.items( ) #this is a list of ALL items in the scene for k in range(len(itemlist)): #compare to items placed last mousemove if itemlist[k] == self.items[0]: self.scene.removeItem(self.items[0]) if itemlist[k] == self.items[1]: self.scene.removeItem(self.items[1]) #puts a box around cell or marks or wire, or rung insert spot. called by mouse move in event filter def showMarker(self, cellNum): i = cellNum[0] j = cellNum[1] #see if the item was deleted elsewhere, like by scene.clear() #self.eraseMarker() if cellNum != [None, None, None, None]: #Optional: Don't show mouse pointer on graphiscview #self.ui.graphicsView.viewport().setCursor(QtCore.Qt.BlankCursor ) #show cell numbers: if self.currentTool != "addRung": self.items[0] = QtGui.QGraphicsTextItem("%d, %d" % (i, j)) self.items[0].setPos(self.grid[i][j].midPointX + 35, self.grid[i][j].midPointY - 35) self.scene.addItem(self.items[0]) #go through elementList and see which tool is being used if self.currentTool == "addRung": if cellNum[2] == "up" and cellNum[0] == 0: x = self.grid[i][j].midPointX y = self.grid[i][j].midPointY - 90 else: x = self.grid[i][j].midPointX y = self.grid[i][j].midPointY - 30 #y=self.grid[i][j].midPointY-90 w = 200 h = 1 self.items[1] = QtGui.QGraphicsRectItem(x - 100, y, w, h) self.items[1].setPen(QtGui.QColor("blue")) self.scene.addItem(self.items[1]) self.items[0] = QtGui.QGraphicsTextItem( "< >") self.items[0].setPos(self.grid[i][j].midPointX - 111, y - 15) self.items[0].setFont(QtGui.QFont("Arial", 16)) self.items[0].setDefaultTextColor(QtGui.QColor("blue")) self.scene.addItem(self.items[0]) elif self.currentTool == "Widen": x = self.grid[i][j].midPointX y = self.grid[i][j].midPointY - 90 w = 1 h = 62 self.items[1] = QtGui.QGraphicsRectItem(x, y, w, h) self.items[1].setPen(QtGui.QColor("blue")) self.scene.addItem(self.items[1]) elif self.currentTool == "ORwire": if cellNum[2] == "up": y = self.grid[i][j].midPointY - 120 if cellNum[2] == "dn": y = self.grid[i][j].midPointY - 60 x = self.grid[i][j].midPointX #y=self.grid[i][j].midPointY-60 w = 1 h = 60 self.items[1] = QtGui.QGraphicsRectItem(x, y, w, h) self.items[1].setPen(QtGui.QColor("blue")) self.scene.addItem(self.items[1]) elif self.currentTool == "blankOR": #"blankOR" 5 pixmap = QtGui.QPixmap(_fromUtf8(":/icons/icons/OR_big.png")) self.items[1] = QtGui.QGraphicsPixmapItem(pixmap) x = self.grid[i][j].midPointX y = self.grid[i][j].midPointY - 60 self.items[1].setPos(x, y) self.scene.addItem(self.items[1]) else: #show box around cell: x = self.grid[i][j].midPointX y = self.grid[i][j].midPointY - 90 w = 58 h = 58 self.items[1] = QtGui.QGraphicsRectItem(x, y, w, h) self.items[1].setPen(QtGui.QColor("blue")) self.scene.addItem(self.items[1]) def rightClick(self, cellNum): if cellNum != [None, None, None, None]: tool = self.grid[cellNum[0]][cellNum[1]].MTorElement clickSuccssful = False #update undo/redo stack here del self.reDoGrid[:] #first clear re-do satck self.unDoGrid.append(copy.deepcopy( self.grid)) #save a copy(list) of this grid for undo if len(self.unDoGrid) > 30: #limit to 30 undos self.unDoGrid.pop(0) #pop 0 #run popup: tempCellData = self.runPopup(tool, cellNum) if tempCellData != False: # Yes, new data entered, so update list at right: #update cell: self.grid[cellNum[0]][ cellNum[1]].variableName = tempCellData.variableName print "varname:", tempCellData.variableName self.grid[cellNum[0]][ cellNum[1]].comment = tempCellData.comment print "comment:", tempCellData.comment self.grid[cellNum[0]][ cellNum[1]].ioAssign = tempCellData.ioAssign print "ioassign:", tempCellData.ioAssign self.grid[cellNum[0]][ cellNum[1]].setPoint = tempCellData.setPoint print "setpoint:", tempCellData.setPoint clickSuccssful = True #>>>>>cleanup and redraw: if clickSuccssful == False: print("nothing done") self.unDoGrid.pop() #delete last one in undo ManageGrid(self.grid, self.scene, self.Tools, self.items).totalRedraw() self.reFillList(self.ui.tableWidget) def leftClick( self, cellNum ): #this def is a specific one, automatically connected to mousePressEvent in UI if cellNum != [None, None, None, None ]: #mouse click was located in cells #variable bridge from findng position (todo: change this): if cellNum[2] == "up": UpDwn = 0 if cellNum[2] == "dn": UpDwn = 1 if cellNum[3] == "rt": RtLft = 1 if cellNum[3] == "lt": RtLft = 0 clickSuccssful = False #will be set to true if an action is taken, allows undo to be rolled back of not #update undo/redo stack here del self.reDoGrid[:] #first clear re-do satck self.unDoGrid.append(copy.deepcopy( self.grid)) #save a copy(list) of this grid for undo if len(self.unDoGrid) > 30: #limit to 30 undos self.unDoGrid.pop(0) #pop 0 #go through elementList and see which tool is being used numTools = len(self.Tools.toolList) toolToPlace = ("0", 0) #name and index of tool in toolList for i in range(0, numTools): if self.Tools.toolList[i].toolName == self.currentTool: toolToPlace = (self.Tools.toolList[i].toolName, i) print("tool #: %d" % (toolToPlace[1])) #>>>>>↓↓↓ELEMENT PLACEMENT↓↓↓<<<<<<<<< #>>>>place Element on rung: if self.Tools.toolList[toolToPlace[1]].toolType == "Element"\ and self.grid[cellNum[0]][cellNum[1]].rungOrOR != "OR": #tool to place is an elememt, (not widen or add rung) #>>>>place non-coil Element on rung: if self.Tools.toolList[toolToPlace[1]].position == "any": if self.grid[cellNum[0]][cellNum[1]].MTorElement == "MT"\ and cellNum[1] != len(self.grid[cellNum[0]])-1: #not at the far right # cause popup dialog tempCellInfo = self.runPopup(toolToPlace[0], cellNum) if tempCellInfo != False: #update list at right #self.addToList(self.ui.tableWidget,tempCellInfo,(cellNum[0],cellNum[1])) #place element on grid ManageGrid(self.grid, self.scene, self.Tools,self.items)\ .placeElememt(cellNum,tempCellInfo,toolToPlace) clickSuccssful = True #>>element that should shift to right if "right" (coil, timerreset..) elif self.Tools.toolList[toolToPlace[1]].position == "right": cellNum[1] = len(self.grid[0]) - 1 #right most spot if self.grid[cellNum[0]][cellNum[1]].MTorElement == "MT": # cause popup dialog tempCellInfo = self.runPopup(toolToPlace[0], cellNum) if tempCellInfo != False: #update list at right #self.addToList(self.ui.tableWidget,tempCellInfo,(cellNum[0],cellNum[1])) #place element on grid ManageGrid(self.grid, self.scene, self.Tools,self.items)\ .placeElememt(cellNum,tempCellInfo,toolToPlace) clickSuccssful = True #>>>>place Element on OR: if self.Tools.toolList[toolToPlace[1]].toolType == "Element"\ and self.grid[cellNum[0]][cellNum[1]].MTorElement == "blankOR": if self.Tools.toolList[toolToPlace[1]].position == "any": # cause popup dialog tempCellInfo = self.runPopup(toolToPlace[0], cellNum) if tempCellInfo != False: #update list at right #self.addToList(self.ui.tableWidget,tempCellInfo,(cellNum[0],cellNum[1])) #place element on grid ManageGrid(self.grid, self.scene, self.Tools,self.items)\ .placeElememt(cellNum,tempCellInfo,toolToPlace) clickSuccssful = True #>>element only allowed on rt (coil, timerreset..) elif self.Tools.toolList[toolToPlace[1]].position == "right": cellNum[1] = len(self.grid[0]) - 1 #right most spot print("elemnt to right") if self.grid[cellNum[0]][ cellNum[1]].MTorElement == "blankOR": # cause popup dialog tempCellInfo = self.runPopup(toolToPlace[0], cellNum) if tempCellInfo != False: #update list at right #self.addToList(self.ui.tableWidget,tempCellInfo,(cellNum[0],cellNum[1])) #place element on grid ManageGrid(self.grid, self.scene, self.Tools,self.items)\ .placeElememt(cellNum,tempCellInfo,toolToPlace) clickSuccssful = True #>>>>↑↑↑ELEMENT PLACEMENT↑↑↑<<<<< #>>>>>addRung: if self.Tools.toolList[toolToPlace[1]].toolName == "addRung": Ypos = cellNum[0] + UpDwn print "upDwn", UpDwn ManageGrid(self.grid, self.scene, self.Tools, self.items).insertRung(Ypos) clickSuccssful = True #>>>>>Widen: elif self.Tools.toolList[toolToPlace[1]].toolName == "Widen": #cellNum[1] = cellNum[1] + RtLft ManageGrid(self.grid, self.scene, self.Tools, self.items).Widen(cellNum) clickSuccssful = True #>>>>>addOR: elif self.Tools.toolList[toolToPlace[1]].toolName == "blankOR": cellNum[0] = cellNum[0] + UpDwn #cellNum[1] = cellNum[1] - RtLft #adjust for right or left clickage of cell if cellNum[1] < 0: # don't add off left cellNum[1] = 0 if cellNum[0] < 1: cellNum[0] = 1 #don't add an OR above ManageGrid(self.grid, self.scene, self.Tools, self.items).insertBlankOR(cellNum) clickSuccssful = True print("blank OR added") #>>>>>addORwire: elif self.Tools.toolList[toolToPlace[1]].toolName == "ORwire": cellNum[0] = cellNum[0] + UpDwn #cellNum[1] = cellNum[1] - RtLft #adjust for right or left clickage of cell if cellNum[1] < 0: # don't add off left cellNum[1] = 0 if cellNum[0] < 1: cellNum[0] = 1 #don't add an OR above ManageGrid(self.grid, self.scene, self.Tools, self.items).addWire(cellNum) clickSuccssful = True print("wire placed") #>>>>>Delete: elif self.Tools.toolList[toolToPlace[1]].toolName == "Del": loc = (cellNum[0], cellNum[1]) #self.removeFromList(self.ui.tableWidget,loc) #delete element on OR branch: if self.grid[cellNum[0]][cellNum[1]].rungOrOR == "OR"\ and self.grid[cellNum[0]][cellNum[1]].MTorElement != "MT"\ and self.grid[cellNum[0]][cellNum[1]].MTorElement != "blankOR": ManageGrid(self.grid, self.scene, self.Tools, self.items).Delete(cellNum) #delete of element on Rung or delete the rung: elif self.grid[cellNum[0]][cellNum[1]].rungOrOR == "Rung": ManageGrid(self.grid, self.scene, self.Tools, self.items).Delete(cellNum) clickSuccssful = True #>>>>>Shrink elif self.Tools.toolList[toolToPlace[1]].toolName == "Narrow": #self.ui.graphicsView.prepareGeometryChange() ManageGrid(self.grid, self.scene, self.Tools, self.items).Shrink( cellNum) #then do function to narrow if can #>>>>>cleanup and redraw: if clickSuccssful == False: print("nothing done") self.unDoGrid.pop() #delete last one in undo ManageGrid(self.grid, self.scene, self.Tools, self.items).totalRedraw() self.reFillList(self.ui.tableWidget) #will run popup and return tempCellData with all info from popup #send tool being used, cellNum #doesn't do anything with the grid. def runPopup(self, tool, cellNum): popUpOKed = False #becomes true if dialog is OK'ed tempCellInfo = cellStruct(None, None, None, None, None, None, None, None, False, False, False, False, False, False) if tool == "Coil" or tool == "CoilNot": #do dialog for this tool: self.dialog = popupDialogs.CoilDialog(self.grid, cellNum, self.currentHW) popUpOKed = self.dialog.exec_() # For Modal dialogs elif tool == "contNO" or tool == "contNC": #do dialog for this tool: self.dialog = popupDialogs.ContDialog(self.grid, cellNum, self.currentHW) popUpOKed = self.dialog.exec_() # For Modal dialogs elif tool == "Rising" or tool == "Fall": #do dialog for this tool: self.dialog = popupDialogs.EdgeDialog(self.grid, cellNum, self.currentHW) popUpOKed = self.dialog.exec_() # For Modal dialogs elif tool == "Timer": #do dialog for this tool: self.dialog = popupDialogs.TimerDialog(self.grid, cellNum, self.currentHW) popUpOKed = self.dialog.exec_() # For Modal dialogs elif tool == "Counter": #do dialog for this tool: self.dialog = popupDialogs.CounterDialog(self.grid, cellNum, self.currentHW) popUpOKed = self.dialog.exec_() # For Modal dialogs if popUpOKed == True: # get all info from popup: try: tempCellInfo.ioAssign = self.dialog.ui.comboBox.currentText( ) #I/O assign except: pass try: tempCellInfo.variableName = self.dialog.ui.comboBox_2.currentText( ) #variable Name except: pass try: tempCellInfo.comment = self.dialog.ui.lineEdit.text() #comment except: pass try: tempCellInfo.setPoint = self.dialog.ui.doubleSpinBox.value( ) #setpoint decimal except: pass try: tempCellInfo.setPoint = self.dialog.ui.spinBox.value( ) #setpoint integer except: pass try: tempCellInfo.ioAssign = self.dialog.ui.comboBox.currentText() except: pass tempCellInfo.MTorElement = tool return tempCellInfo else: return False
class MainWindow(QMainWindow, QObject): def __init__(self, data_singleton, parent=None): super().__init__(parent) self.ui = Ui_MainWindow() self.ui.setupUi(self) self.data_singleton = data_singleton self.mUndoStackGroup = QUndoGroup(self) self.mUndoStackGroup.canUndoChanged.connect(self.can_undo_changed) self.mUndoStackGroup.canRedoChanged.connect(self.can_redo_changed) self.can_undo_changed(self.mUndoStackGroup.canUndo()) self.can_redo_changed(self.mUndoStackGroup.canRedo()) self.ui.actionUndo.triggered.connect(self.mUndoStackGroup.undo) self.ui.actionRedo.triggered.connect(self.mUndoStackGroup.redo) self.ui.actionSave.triggered.connect(self.save) self.ui.actionSaveAs.triggered.connect(self.save_as) self.ui.actionNew.triggered.connect(self.new_tab) self.ui.actionOpen.triggered.connect(self.open) self.ui.actionSettings.triggered.connect(self.show_settings) self.ui.actionPlugin_Manager.triggered.connect(self.show_plugin_manager) self.ui.tabWidget.currentChanged.connect(self.activate_tab) self.ui.tabWidget.currentChanged.connect(self.send_tab_changed) self.ui.tabWidget.tabCloseRequested.connect(self.close_tab) self.update_states() send_cursor_pos = Signal(int, int) send_new_image_size = Signal(int, int) send_tab_changed = Signal(int) def load_plugins(self): # TODO: проверить импортирование пакетов пакетов loader = PluginsLoader(self.data_singleton) loader.enableOutput = True # TODO: список папок плагинов доставать из синглетона loader.load(['plugins']) # TODO: rem print('Plugins:') for plugin in loader.plugins(): print(' ', plugin) print() def update_states(self): if self.ui.tabWidget.count() == 0: self.setWindowTitle('Empty' + ' - ' + self.data_singleton.PROGRAM_NAME) else: canvas = self.get_current_canvas() file_name = canvas.get_file_name() title = self.data_singleton.UNTITLED if file_name is None else file_name tab_title = title if canvas.edited: title += '[*]' tab_title += '*' self.setWindowTitle(title + ' - ' + self.data_singleton.PROGRAM_NAME) index = self.ui.tabWidget.currentIndex() self.ui.tabWidget.setTabText(index, tab_title) self.setWindowModified(canvas.edited) def close_tab(self, index): canvas = self.get_canvas(index) if canvas.edited: reply = QMessageBox.warning(self, "Closing Tab...", "File has been modified\n" "Do you want to save changes?", QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel, QMessageBox.Yes) if reply == QMessageBox.Yes: self.save(canvas) elif reply == QMessageBox.Cancel: return self.mUndoStackGroup.removeStack(canvas.getUndoStack()) tab = self.ui.tabWidget.widget(index) self.ui.tabWidget.removeTab(index) tab.deleteLater() self.update_states() def new_tab(self): canvas = Canvas(self.data_singleton) self.mUndoStackGroup.addStack(canvas.getUndoStack()) canvas.send_cursor_pos.connect(self.send_cursor_pos) canvas.send_new_image_size.connect(self.send_new_image_size) canvas.send_change_edited.connect(self.update_states) scroll_area = QScrollArea() scroll_area.setWidget(canvas) scroll_area.setBackgroundRole(QPalette.Dark) file_name = canvas.get_file_name() title = self.data_singleton.UNTITLED if file_name is None else file_name self.ui.tabWidget.addTab(scroll_area, title) self.update_states() def activate_tab(self, index): if index == -1: return canvas = self.get_current_canvas() self.mUndoStackGroup.setActiveStack(canvas.getUndoStack()) self.send_new_image_size.emit(canvas.width(), canvas.height()) self.update_states() def save(self, canvas_=None): try: # Если canvas_ не указан, берем текущий canvas = self.get_current_canvas() if canvas_ is None else canvas_ if canvas is not None: # Если у холста есть файл, сохраняем в него, иначе вызываем "сохранить как" if canvas.file_path is None: self.save_as() else: canvas.save() except Exception as e: QMessageBox.warning(self, 'Warning', str(e)) self.update_states() def save_as(self): canvas = self.get_current_canvas() if canvas is None: return # Список строк с поддерживаемыми форматами изображений formats = [str(x) for x in QImageWriter.supportedImageFormats()] # Описываем как фильтры диалога filters = ["{} ( *.{} )".format(x.upper(), x) for x in formats] file_name = canvas.get_file_name() if file_name is None: file_name = os.path.join(QDir.homePath(), self.data_singleton.UNTITLED) default_filter = "{} ( *.{} )".format('PNG', 'png') # Получим путь к файлу file_name = QFileDialog.getSaveFileName(self, None, file_name, '\n'.join(filters), default_filter)[0] if file_name: try: canvas.save(file_name) except Exception as e: QMessageBox.warning(self, 'Warning', str(e)) self.update_states() def open(self): # Список строк с поддерживаемыми форматами изображений formats = [str(x) for x in QImageReader.supportedImageFormats()] # Описываем как фильтры диалога filters = 'Поддерживаемые форматы (' filters += ' '.join(["*.{}".format(x.lower()) for x in formats]) filters += ')' # Получим путь к файлу file_name = QFileDialog.getOpenFileName(self, None, None, filters)[0] if file_name: try: canvas = self.get_current_canvas() if canvas is not None: canvas.load(file_name) self.update_states() except Exception as e: QMessageBox.warning(self, 'Внимание', str(e)) def show_settings(self): settings = Settings(self.data_singleton) settings.exec_() def show_plugin_manager(self): plugin_manager = PluginManager(self.data_singleton) plugin_manager.exec_() def can_undo_changed(self, enabled): self.ui.actionUndo.setEnabled(enabled) def get_canvas(self, index): if index < 0 or index >= self.ui.tabWidget.count(): return None tab = self.ui.tabWidget.widget(index) return tab.widget() def get_current_canvas(self): index = self.ui.tabWidget.currentIndex() if index != -1: return self.get_canvas(index) def can_redo_changed(self, enabled): self.ui.actionRedo.setEnabled(enabled) def read_settings(self): try: import json with open(self.data_singleton.settings_path, 'r') as f: data = json.load(f) self.restoreGeometry(QByteArray.fromHex(data['MainWindow']['geometry'])) self.restoreState(QByteArray.fromHex(data['MainWindow']['state'])) # TODO: синглетон должен сам грузить свои настройки, еще до загрузки mainwindow # self.data_singleton.from_serialize(data['Settings']) except Exception as e: print(e) def write_settings(self): # TODO: для ini есть модуль ConfigParser try: import json with open(self.data_singleton.settings_path, 'w') as f: data = { 'MainWindow': { 'state': str(self.saveState().toHex()), 'geometry': str(self.saveGeometry().toHex()), }, # TODO: вызывать у синглетона функцию 'Settings': self.data_singleton.to_serialize(), } json.dump(data, f, sort_keys=True, indent=4, ensure_ascii=False) except Exception as e: print(e) def closeEvent(self, *args, **kwargs): self.write_settings() # Закрывать вкладки будем с правого края for i in reversed(range(self.ui.tabWidget.count())): self.close_tab(i) # TODO: спрашивать о том уверенности пользователя нужно с учетом флажка # reply = QtGui.QMessageBox.question(self, 'Message', # "Are you sure to quit?", QtGui.QMessageBox.Yes | # QtGui.QMessageBox.No, QtGui.QMessageBox.No) # # if reply == QtGui.QMessageBox.Yes: # event.accept() # else: # event.ignore() super().closeEvent(*args, **kwargs)
class MainWin(QMainWindow): # noinspection PyArgumentList def __init__(self, parent=None): super().__init__(parent) self.ui = Ui_MainWindow() self.ui.setupUi(self) # try connection self.settings = QSettings('elektroNIK', 'P3DA') self.con = Connection(baud=38400) self.devs = self.detectdevices() if self.devs: self.con.createconnection(self.devs[0]) msg = 'Connected to {}'.format( self.con.dev) if self.con.con else 'No serial adapter found!' self.ui.statusbar.showMessage(msg) # corrections self.gamma = self.ui.doubleSpinBox_gamma.value() r = self.ui.horizontalSlider_wb_r.value() g = self.ui.horizontalSlider_wb_g.value() b = self.ui.horizontalSlider_wb_b.value() self.wb = {'R': r, 'G': g, 'B': b} # initializing classes self.tablight = TabLight(self) self.tabilumination = TabIlumination(self) self.tabsound = TabSound(self) self.tabextbacklight = TabExtBacklight(self) self.tabsetup = TabSetup(self) # restoring self.restoresettings() self.tablight.updatepalette() # init self.ui.tabWidget.currentChanged.connect(self.updatetab) self.updatetab(self.ui.tabWidget.currentIndex()) def updatetab(self, val): switch = { 0: self.tablight.enabletab, 1: self.tabilumination.enabletab, 2: self.tabsound.enabletab, 3: self.tabextbacklight.enabletab, 4: self.tabsetup.enabletab } switch[val](flag=self.con.connectionisopen()) def settabsenable(self, flag): count = list(range(self.ui.tabWidget.count())) count.remove(self.ui.tabWidget.currentIndex()) for i in count: self.ui.tabWidget.setTabEnabled(i, flag) def detectdevices(self): baddevices = ['Android Platform', 'AndroidNet'] # bug with write on 38400 baud (Windows?) res = [] devs = self.con.devicesonline() coms = list(devs.keys()) for i in coms: bad = False for j in baddevices: if j in devs[i]: bad = True if not bad: self.con.createconnection(i) delay.sleep(1.5) self.con.write('#T') answ = self.con.read(3) if answ == '#OK': res.append(i) self.con.close() return res def setcolor(self, r, g, b, ch): msg = '#S{:1}{:03x}{:03x}{:03x}'.format(ch, self.gammacorrection(r, 'R'), self.gammacorrection(g, 'G'), self.gammacorrection(b, 'B')) self.con.write(msg) def gammacorrection(self, val, color): return round((val / 255)**self.gamma * self.wb[color]) @staticmethod def checktext(text): for i in text.split(): if len(i) == 6 + 1: try: int(i[1:], 16) except ValueError: return False else: return False return True def savesettings(self): # Window self.settings.setValue('Window/geometry', self.geometry()) self.settings.setValue('Window/tab', self.ui.tabWidget.currentIndex()) # Tab light self.settings.beginGroup('TabLight') for i in range(20): exec( 'self.settings.setValue("color{:02}", self.ui.pushButton_last{:02}.text())' .format(i + 1, i + 1)) self.settings.setValue('color', self.ui.pushButton_color.text()) self.settings.endGroup() # Tab effect self.settings.beginGroup('TabEffect') for i in range(4): exec( 'self.settings.setValue("index{}", self.ui.comboBox_effect{}.currentIndex())' .format(i + 1, i + 1)) exec( 'self.settings.setValue("time{}", self.ui.spinBox_time{}.value())' .format(i + 1, i + 1)) exec( 'self.settings.setValue("colors{}", self.ui.plainTextEdit_input{}.toPlainText())' .format(i + 1, i + 1)) self.settings.endGroup() # Tab sound self.settings.beginGroup('TabSound') self.settings.setValue('input', self.ui.comboBox_input.currentIndex()) self.settings.setValue('colors', [ self.ui.pushButton_color_low.text(), self.ui.pushButton_color_mid.text(), self.ui.pushButton_color_high.text() ]) self.settings.setValue('mult', [ self.ui.doubleSpinBox_mult_low.value(), self.ui.doubleSpinBox_mult_mid.value(), self.ui.doubleSpinBox_mult_high.value() ]) self.settings.setValue('sliderslow', [ self.ui.verticalSlider_lower_low.value(), self.ui.verticalSlider_higher_low.value() ]) self.settings.setValue('slidersmid', [ self.ui.verticalSlider_lower_mid.value(), self.ui.verticalSlider_higher_mid.value() ]) self.settings.setValue('slidershigh', [ self.ui.verticalSlider_lower_high.value(), self.ui.verticalSlider_higher_high.value() ]) self.settings.setValue('noise', self.ui.horizontalSlider_noise.value()) self.settings.setValue('effect', self.ui.comboBox_effect_music.currentIndex()) self.settings.setValue('bitcolors', self.ui.plainTextEdit_bitdetector.toPlainText()) self.settings.endGroup() # Tab ext backlight self.settings.beginGroup('TabExtBacklight') self.settings.setValue('count', self.ui.spinBox_count_zones.value()) self.settings.setValue('time', self.ui.spinBox_update.value()) self.settings.setValue('zones', self.tabextbacklight.getzones()) self.settings.endGroup() # Tab setup self.settings.beginGroup('TabSetup') self.settings.setValue('device', self.ui.comboBox_device.currentIndex()) self.settings.setValue('wb', [ self.ui.horizontalSlider_wb_r.value(), self.ui.horizontalSlider_wb_g.value(), self.ui.horizontalSlider_wb_b.value() ]) self.settings.setValue('gamma', self.ui.doubleSpinBox_gamma.value()) self.settings.endGroup() def restoresettings(self): if self.settings.allKeys(): # Window self.setGeometry(self.settings.value('Window/geometry')) self.ui.tabWidget.setCurrentIndex( int(self.settings.value('Window/tab'))) # Tab light self.settings.beginGroup('TabLight') for i in range(20): exec( 'self.ui.pushButton_last{:02}.setText(self.settings.value("color{:02}"))' .format(i + 1, i + 1)) self.ui.pushButton_color.setText(self.settings.value('color')) self.settings.endGroup() # Tab effect self.settings.beginGroup('TabEffect') for i in range(4): exec( 'self.ui.comboBox_effect{}.setCurrentIndex(int(self.settings.value("index{}")))' .format(i + 1, i + 1)) exec( 'self.ui.spinBox_time{}.setValue(int(self.settings.value("time{}")))' .format(i + 1, i + 1)) exec( 'self.ui.plainTextEdit_input{}.setPlainText(self.settings.value("colors{}"))' .format(i + 1, i + 1)) self.settings.endGroup() # Tab sound self.settings.beginGroup('TabSound') self.ui.comboBox_input.setCurrentIndex( int(self.settings.value('input'))) low, mid, high = self.settings.value('colors') self.ui.pushButton_color_low.setText(low) self.ui.pushButton_color_mid.setText(mid) self.ui.pushButton_color_high.setText(high) low, mid, high = self.settings.value('mult') self.ui.doubleSpinBox_mult_low.setValue(float(low)) self.ui.doubleSpinBox_mult_mid.setValue(float(mid)) self.ui.doubleSpinBox_mult_high.setValue(float(high)) low, high = self.settings.value('sliderslow') self.ui.verticalSlider_lower_low.setValue(int(low)) self.ui.verticalSlider_higher_low.setValue(int(high)) low, high = self.settings.value('slidersmid') self.ui.verticalSlider_lower_mid.setValue(int(low)) self.ui.verticalSlider_higher_mid.setValue(int(high)) low, high = self.settings.value('slidershigh') self.ui.verticalSlider_lower_high.setValue(int(low)) self.ui.verticalSlider_higher_high.setValue(int(high)) self.ui.horizontalSlider_noise.setValue( int(self.settings.value('noise'))) self.ui.comboBox_effect_music.setCurrentIndex( int(self.settings.value('effect'))) self.ui.plainTextEdit_bitdetector.setPlainText( self.settings.value('bitcolors')) self.settings.endGroup() # Tab ext backlight self.settings.beginGroup('TabExtBacklight') self.ui.spinBox_count_zones.setValue( int(self.settings.value('count'))) self.ui.spinBox_update.setValue(int(self.settings.value('time'))) self.tabextbacklight.setzones(self.settings.value('zones')) self.settings.endGroup() # Tab setup self.settings.beginGroup('TabSetup') self.ui.comboBox_device.setCurrentIndex( int(self.settings.value('device'))) r, g, b = self.settings.value('wb') self.ui.horizontalSlider_wb_r.setValue(int(r)) self.ui.horizontalSlider_wb_g.setValue(int(g)) self.ui.horizontalSlider_wb_b.setValue(int(b)) self.ui.doubleSpinBox_gamma.setValue( float(self.settings.value('gamma'))) self.settings.endGroup() def closeEvent(self, event): self.savesettings()
class MainWindow(QMainWindow): FIT_WINDOW, FIT_WIDTH, MANUAL_ZOOM = range(3) resized = QtCore.pyqtSignal() def __init__(self, app_name): super(MainWindow, self).__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) # canvas main window self.setWindowIcon(QIcon(cfg.ICONS.LOGO)) self.canvas = Canvas() self.canvas.image = QImage(cfg.ICONS.BACKGROUND) self.canvas.zoomRequest.connect(self.zoomRequest) scroll = QScrollArea() scroll.setWidget(self.canvas) scroll.setWidgetResizable(True) self.scrollBars = { Qt.Vertical: scroll.verticalScrollBar(), Qt.Horizontal: scroll.horizontalScrollBar() } self.canvas.scrollRequest.connect(self.scrollRequest) self.ui.main_video_layout.addWidget(scroll) self.zoomWidget = ZoomWidget() zoom = QWidgetAction(self) zoom.setDefaultWidget(self.zoomWidget) self.zoomWidget.setWhatsThis( u"Zoom in or out of the image. Also accessible with" " %s and %s from the canvas." % (fmtShortcut("Ctrl+[-+]"), fmtShortcut("Ctrl+Wheel"))) self.zoomWidget.setEnabled(False) self.scalers = { self.FIT_WINDOW: self.scaleFitWindow, self.FIT_WIDTH: self.scaleFitWidth, # Set to one to scale to 100% when loading files. self.MANUAL_ZOOM: lambda: 1, } self.zoomMode = self.FIT_WINDOW self.canvas.setEnabled(True) self.adjustScale(initial=True) self.paintCanvas() self.zoomWidget.valueChanged.connect(self.paintCanvas) self.resized.connect(self.adjustScale) # camera self.camera_device = CameraDevice(video_path=cfg.GLOBAL.VIDEO1) self.camera_device.newFrame.connect(self.onNewImage) self.camera_device.video_time_out.connect(self.clear) # top button functions self.ui.thread1_bn.clicked.connect(self.start_camera) self.ui.thread2_bn.clicked.connect(self.start_video1) self.ui.thread3_bn.clicked.connect(self.start_video2) self.ui.thread4_bn.clicked.connect(self.start_pic) self.ui.thread5_bn.clicked.connect(self.load_video) # left button functions self.ui.play_bn.clicked.connect(self.start_cap) self.ui.pause_bn.clicked.connect(self.stop_cap) self.ui.record_bn.clicked.connect(self.save_video) self.ui.exit_bn.clicked.connect(self.close) # right button functions self.ui.model1_bn.clicked.connect(self.apply_model1) self.ui.model2_bn.clicked.connect(self.apply_model2) self.ui.model3_bn.clicked.connect(self.apply_model3) self.ui.model4_bn.clicked.connect(self.apply_model4) self.ui.model5_bn.clicked.connect(self.apply_model5) # top button functions self.ui.thread1_bn.setIcon(QIcon(cfg.ICONS.TOP_LEFT1)) self.ui.thread1_bn.setIconSize( QSize(cfg.ICONS.TOP_SIZE[0], cfg.ICONS.TOP_SIZE[1])) self.ui.thread2_bn.setIcon(QIcon(cfg.ICONS.TOP_LEFT2)) self.ui.thread2_bn.setIconSize( QSize(cfg.ICONS.TOP_SIZE[0], cfg.ICONS.TOP_SIZE[1])) self.ui.thread3_bn.setIcon(QIcon(cfg.ICONS.TOP_LEFT3)) self.ui.thread3_bn.setIconSize( QSize(cfg.ICONS.TOP_SIZE[0], cfg.ICONS.TOP_SIZE[1])) self.ui.thread4_bn.setIcon(QIcon(cfg.ICONS.TOP_LEFT4)) self.ui.thread4_bn.setIconSize( QSize(cfg.ICONS.TOP_SIZE[0], cfg.ICONS.TOP_SIZE[1])) self.ui.thread5_bn.setIcon(QIcon(cfg.ICONS.TOP_LEFT5)) self.ui.thread5_bn.setIconSize( QSize(cfg.ICONS.TOP_SIZE[0], cfg.ICONS.TOP_SIZE[1])) # left button functions self.ui.play_bn.setIcon(QIcon(cfg.ICONS.LEFT_TOP1)) self.ui.play_bn.setIconSize( QSize(cfg.ICONS.LEFT_SIZE[0], cfg.ICONS.LEFT_SIZE[1])) self.ui.pause_bn.setIcon(QIcon(cfg.ICONS.LEFT_TOP2)) self.ui.pause_bn.setIconSize( QSize(cfg.ICONS.LEFT_SIZE[0], cfg.ICONS.LEFT_SIZE[1])) self.ui.record_bn.setIcon(QIcon(cfg.ICONS.LEFT_TOP3)) self.ui.record_bn.setIconSize( QSize(cfg.ICONS.LEFT_SIZE[0], cfg.ICONS.LEFT_SIZE[1])) self.ui.empty_bn.setIcon(QIcon(cfg.ICONS.LEFT_TOP4)) self.ui.empty_bn.setIconSize( QSize(cfg.ICONS.LEFT_SIZE[0], cfg.ICONS.LEFT_SIZE[1])) self.ui.setting_bn.setIcon(QIcon(cfg.ICONS.LEFT_TOP5)) self.ui.setting_bn.setIconSize( QSize(cfg.ICONS.LEFT_SIZE[0], cfg.ICONS.LEFT_SIZE[1])) self.ui.exit_bn.setIcon(QIcon(cfg.ICONS.LEFT_TOP6)) self.ui.exit_bn.setIconSize( QSize(cfg.ICONS.LEFT_SIZE[0], cfg.ICONS.LEFT_SIZE[1])) # right button icons self.ui.model1_bn.setIcon(QIcon(cfg.ICONS.RIGHT_TOP1)) self.ui.model1_bn.setIconSize( QSize(cfg.ICONS.RIGHT_SIZE[0], cfg.ICONS.RIGHT_SIZE[1])) self.ui.model2_bn.setIcon(QIcon(cfg.ICONS.RIGHT_TOP2)) self.ui.model2_bn.setIconSize( QSize(cfg.ICONS.RIGHT_SIZE[0], cfg.ICONS.RIGHT_SIZE[1])) self.ui.model3_bn.setIcon(QIcon(cfg.ICONS.RIGHT_TOP3)) self.ui.model3_bn.setIconSize( QSize(cfg.ICONS.RIGHT_SIZE[0], cfg.ICONS.RIGHT_SIZE[1])) self.ui.model4_bn.setIcon(QIcon(cfg.ICONS.RIGHT_TOP4)) self.ui.model4_bn.setIconSize( QSize(cfg.ICONS.RIGHT_SIZE[0], cfg.ICONS.RIGHT_SIZE[1])) self.ui.model5_bn.setIcon(QIcon(cfg.ICONS.RIGHT_TOP5)) self.ui.model5_bn.setIconSize( QSize(cfg.ICONS.RIGHT_SIZE[0], cfg.ICONS.RIGHT_SIZE[1])) # task special param self.image_render = GetImage() self.flag_savevideo = False self.info_header = u"Hello from PriVision!\n " self.shown_info(self.info_header) self.allframes = [] self.video_writer = None self.savevideo_counting = 0 self.savevideo_max = cfg.GLOBAL.SAVE_VIDEO_MAX_SECOND def resizeEvent(self, event): self.resized.emit() return super(MainWindow, self).resizeEvent(event) def update_image(self): pass def zoomRequest(self, delta): units = delta / (8 * 15) scale = 10 self.addZoom(scale * units) def scrollRequest(self, delta, orientation): units = -delta / (8 * 15) bar = self.scrollBars[orientation] bar.setValue(bar.value() + bar.singleStep() * units) def setZoom(self, value): self.actions.fitWidth.setChecked(False) self.actions.fitWindow.setChecked(False) self.zoomMode = self.MANUAL_ZOOM self.zoomWidget.setValue(value) def addZoom(self, increment=10): self.setZoom(self.zoomWidget.value() + increment) def setFitWindow(self, value=True): self.zoomMode = self.FIT_WINDOW if value else self.MANUAL_ZOOM self.adjustScale() def setFitWidth(self, value=True): if value: self.actions.fitWindow.setChecked(False) self.zoomMode = self.FIT_WIDTH if value else self.MANUAL_ZOOM self.adjustScale() def adjustScale(self, initial=False): value = self.scalers[self.FIT_WINDOW if initial else self.zoomMode]() self.zoomWidget.setValue(int(100 * value)) def scaleFitWindow(self): """Figure out the size of the pixmap in order to fit the main widget.""" e = 2.0 # So that no scrollbars are generated. w1 = self.width() * 0.65 - e h1 = self.height() * 0.65 - e a1 = w1 / h1 # Calculate a new scale value based on the pixmap's aspect ratio. w2 = self.canvas.image.width() - 0.0 h2 = self.canvas.image.height() - 0.0 a2 = w2 / h2 return w1 / w2 if a2 >= a1 else h1 / h2 def scaleFitWidth(self): # The epsilon does not seem to work too well here. w = self.centralWidget().width() / 5 * 3 - 2.0 return w / self.canvas.pixmap.width() def paintCanvas(self): self.canvas.scale = 0.01 * self.zoomWidget.value() # self.canvas.scale = 0.5 self.canvas.adjustSize() self.canvas.update() def start_cap(self): # self.ui.play_bn.setIcon(QIcon("./files/icons/icon-left/play-color.png")) self.ui.pause_bn.setIcon(QIcon(cfg.ICONS.LEFT_TOP2)) self.camera_device.paused = False def stop_cap(self): self.ui.pause_bn.setIcon( QIcon(cfg.ICONS.LEFT_TOP2.replace('bright', 'color'))) self.camera_device.paused = True def save_video(self): if not self.flag_savevideo: self.flag_savevideo = True self.savevideo_counting = 0 video_name = datetime.datetime.now().strftime('%Y%m%d%H%M%S') fourcc = cv2.VideoWriter_fourcc(*'MJPG') self.video_writer = cv2.VideoWriter( '{}/{}_save.avi'.format(cfg.GLOBAL.SAVE_VIDEO_PATH, video_name), fourcc, cfg.GLOBAL.SAVE_VIDEO_FPS, tuple(cfg.GLOBAL.SAVE_VIDEO_SIZE)) self.ui.record_bn.setIcon( QIcon(cfg.ICONS.LEFT_TOP3.replace('bright', 'color'))) else: self.video_writer.release() self.savevideo_counting = 0 self.flag_savevideo = False self.video_writer = None self.ui.record_bn.setIcon(QIcon(cfg.ICONS.LEFT_TOP3)) pass def clear(self): self.allframes = [] def shown_info(self, info): self.ui.info_display.setPlainText(info) def apply_model1(self): if cfg.GLOBAL.F_MODEL1: cfg.GLOBAL.F_MODEL1 = False self.ui.model1_bn.setIcon(QIcon(cfg.ICONS.RIGHT_TOP1)) else: cfg.GLOBAL.F_MODEL1 = True self.ui.model1_bn.setIcon( QIcon(cfg.ICONS.RIGHT_TOP1.replace('bright', 'color'))) def apply_model2(self): if cfg.GLOBAL.F_MODEL2: cfg.GLOBAL.F_MODEL2 = False self.ui.model2_bn.setIcon(QIcon(cfg.ICONS.RIGHT_TOP2)) else: cfg.GLOBAL.F_MODEL2 = True self.ui.model2_bn.setIcon( QIcon(cfg.ICONS.RIGHT_TOP2.replace('bright', 'color'))) def apply_model3(self): if cfg.GLOBAL.F_MODEL3: cfg.GLOBAL.F_MODEL3 = False self.ui.model3_bn.setIcon(QIcon(cfg.ICONS.RIGHT_TOP3)) else: cfg.GLOBAL.F_MODEL3 = True self.ui.model3_bn.setIcon( QIcon(cfg.ICONS.RIGHT_TOP3.replace('bright', 'color'))) def apply_model4(self): if cfg.GLOBAL.F_MODEL4: cfg.GLOBAL.F_MODEL4 = False self.ui.model4_bn.setIcon(QIcon(cfg.ICONS.RIGHT_TOP4)) else: cfg.GLOBAL.F_MODEL4 = True self.ui.model4_bn.setIcon( QIcon(cfg.ICONS.RIGHT_TOP4.replace('bright', 'color'))) def apply_model5(self): pass def start_camera(self): self.ui.thread1_bn.setIcon( QIcon(cfg.ICONS.TOP_LEFT1.replace('bright', 'color'))) self.ui.thread2_bn.setIcon(QIcon(cfg.ICONS.TOP_LEFT2)) self.ui.thread3_bn.setIcon(QIcon(cfg.ICONS.TOP_LEFT3)) self.ui.thread4_bn.setIcon(QIcon(cfg.ICONS.TOP_LEFT4)) self.ui.thread5_bn.setIcon(QIcon(cfg.ICONS.TOP_LEFT5)) self.camera_device = CameraDevice() self.camera_device.newFrame.connect(self.onNewImage) self.clear() def start_video1(self): self.ui.thread1_bn.setIcon(QIcon(cfg.ICONS.TOP_LEFT1)) self.ui.thread2_bn.setIcon( QIcon(cfg.ICONS.TOP_LEFT2.replace('bright', 'color'))) self.ui.thread3_bn.setIcon(QIcon(cfg.ICONS.TOP_LEFT3)) self.ui.thread4_bn.setIcon(QIcon(cfg.ICONS.TOP_LEFT4)) self.ui.thread5_bn.setIcon(QIcon(cfg.ICONS.TOP_LEFT5)) self.camera_device.set_video_path(cfg.GLOBAL.VIDEO1) self.clear() def start_video2(self): self.ui.thread1_bn.setIcon(QIcon(cfg.ICONS.TOP_LEFT1)) self.ui.thread2_bn.setIcon(QIcon(cfg.ICONS.TOP_LEFT2)) self.ui.thread3_bn.setIcon( QIcon(cfg.ICONS.TOP_LEFT3.replace('bright', 'color'))) self.ui.thread4_bn.setIcon(QIcon(cfg.ICONS.TOP_LEFT4)) self.ui.thread5_bn.setIcon(QIcon(cfg.ICONS.TOP_LEFT5)) self.camera_device.set_video_path(cfg.GLOBAL.VIDEO2) self.clear() def start_pic(self): self.ui.thread1_bn.setIcon(QIcon(cfg.ICONS.TOP_LEFT1)) self.ui.thread2_bn.setIcon(QIcon(cfg.ICONS.TOP_LEFT2)) self.ui.thread3_bn.setIcon(QIcon(cfg.ICONS.TOP_LEFT3)) self.ui.thread4_bn.setIcon( QIcon(cfg.ICONS.TOP_LEFT4.replace('bright', 'color'))) self.ui.thread5_bn.setIcon(QIcon(cfg.ICONS.TOP_LEFT5)) self.camera_device.set_video_path(cfg.GLOBAL.VIDEO3) self.clear() def load_video(self): self.ui.thread1_bn.setIcon(QIcon(cfg.ICONS.TOP_LEFT1)) self.ui.thread2_bn.setIcon(QIcon(cfg.ICONS.TOP_LEFT2)) self.ui.thread3_bn.setIcon(QIcon(cfg.ICONS.TOP_LEFT3)) self.ui.thread4_bn.setIcon(QIcon(cfg.ICONS.TOP_LEFT4)) self.ui.thread5_bn.setIcon( QIcon(cfg.ICONS.TOP_LEFT5.replace('bright', 'color'))) self.clear() @QtCore.pyqtSlot(np.ndarray) def onNewImage(self, frame): self.adjustScale() frame = np.asarray(frame[:, :]) frame = cv2.resize(frame, tuple(cfg.GLOBAL.IM_SHOW_SIZE)) self.allframes.append(frame) vis = frame.copy() # vis = cv2.resize(vis, (960, 640)) t = clock() result1, result2, result3, result4 = None, None, None, None if cfg.GLOBAL.F_MODEL1: task1_in.put(frame) if cfg.GLOBAL.F_MODEL2: task2_in.put(frame) if cfg.GLOBAL.F_MODEL3: task3_in.put(frame) if cfg.GLOBAL.F_MODEL4: task4_in.put(frame) while True: if cfg.GLOBAL.F_MODEL1: task1_empty = task1_out.empty() else: task1_empty = False if cfg.GLOBAL.F_MODEL2: task2_empty = task2_out.empty() else: task2_empty = False if cfg.GLOBAL.F_MODEL3: task3_empty = task3_out.empty() else: task3_empty = False if cfg.GLOBAL.F_MODEL4: task4_empty = task4_out.empty() else: task4_empty = False if not task1_empty and not task2_empty and not task3_empty and not task4_empty: if cfg.GLOBAL.F_MODEL1: result1 = task1_out.get() else: result1 = None if cfg.GLOBAL.F_MODEL2: result2 = task2_out.get() else: result2 = None if cfg.GLOBAL.F_MODEL3: result3 = task3_out.get() else: result3 = None if cfg.GLOBAL.F_MODEL4: result4 = task4_out.get() else: result4 = None break if result1 is not None: vis = draw_pose_kpts(vis, result1, V.COLORMAP19, V.POSE19_LINKPAIR) if result2 is not None: vis = draw_fancybbox(vis, result2) if result3 is not None: vis = draw_fancybbox(vis, result3) if result4 is not None: vis = draw_fancybbox(vis, result4) # vis = draw_fancybbox(vis, result4, attri=True) # vis = draw_face68_kpts(vis, result4) dt = clock() - t if self.flag_savevideo and self.savevideo_counting <= self.savevideo_max: save_im = cv2.resize(vis, tuple(cfg.GLOBAL.SAVE_VIDEO_SIZE)) self.video_writer.write(save_im) self.savevideo_counting += 1 elif self.savevideo_counting > self.savevideo_max: self.savevideo_counting = 0 self.flag_savevideo = False self.ui.record_bn.setIcon(QIcon(cfg.ICONS.LEFT_TOP3)) draw_str(vis, (30, 30), 'speed: %.1f fps' % (min(1.0 / dt, 30))) if len(self.allframes) % 15 == 0: cur_info = self.info_header + u'--------------------\n ' if self.flag_savevideo: cur_info += u'Saving Video~~\n--------------------\n' cur_info += u'当前为第{}帧视频\n 当前视频频率为: {:.1f}fps\n '. \ format(len(self.allframes), min(1.0 / dt, 30)) cur_info += u'--------------------\n ' self.shown_info(cur_info) vis = cv2.resize(vis, tuple(cfg.GLOBAL.IM_SHOW_SIZE)) image = QImage(vis.tostring(), vis.shape[1], vis.shape[0], QImage.Format_RGB888).rgbSwapped() self.canvas.update_image(image)
class mainWindowUI(QMainWindow): #mainwindow inheriting from QMainWindow here. projectName = None currentFileDir = None tempName = "variables.var" def __init__(self): QDialog.__init__(self)# Constructs a dialog with parent parent. self being ImageDailog # Set up the UI from Designer: self.ui = Ui_MainWindow() self.ui.setupUi(self) self.ui.graphicsView.DontAdjustForAntialiasing #seems to help fix artifacts left by mouse track markers #make a scene: self.scene = QtGui.QGraphicsScene() #set it to show in the graphicsview window: self.ui.graphicsView.setScene(self.scene) self.items=[QtGui.QGraphicsTextItem(),QtGui.QGraphicsRectItem()]#for squares and indexes that follow mouse self.ui.graphicsView.viewport().installEventFilter(self)#for mouse functions #Setup IO table on right self.ui.tableWidget.resizeColumnToContents(0) self.ui.tableWidget.resizeColumnToContents(1) self.ui.tableWidget.setColumnWidth(2, 50) self.ui.tableWidget.setColumnWidth(3, 40) #setup datagrid and elements: self.Tools = elementList(elementStruct) self.setupDataGrid()#set up rung variables: self.signalConnections() #default: self.currentHW = "Waltech" self.ui.actionPWM.setEnabled(False) self.ui.actionADC.setEnabled(False) f=open(self.__class__.tempName, 'w') f.write("") f.close() def signalConnections(self): #connect signals: self.ui.actionUndo.triggered.connect(self.unDo) self.ui.actionRedo.triggered.connect(self.reDo) self.ui.actionSave_As.triggered.connect(self.saveFileAs) self.ui.actionSave.triggered.connect(self.saveFile) self.ui.actionOpen.triggered.connect(self.openFile) self.ui.actionNew.triggered.connect(self.newFile) self.ui.actionWhatsThis.triggered.connect(self.whatsThis) self.ui.actionCheck_HW_2.triggered.connect(self.checkHW) self.ui.actionUSBHelp.triggered.connect(self.USBHelp) self.ui.actionArduinoMega_IO.triggered.connect(self.ArduinoMegaIOHelp) self.ui.actionArduinoUno_IO.triggered.connect(self.ArduinoUnoIOHelp) self.ui.actionArduinoNano_IO.triggered.connect(self.ArduinoNanoIOHelp) self.ui.actionAbout.triggered.connect(self.AboutHelp) self.ui.infoButton.clicked.connect(self.parseGrid) self.ui.burnButton.clicked.connect(self.burn) #FOR DEBUG BUTTON #self.ui.pushButton.clicked.connect(self.showInfo) #self.ui.pushButton_3.clicked.connect(self.printLadder) ##003## #action group for tool buttons: self.connect(self.ui.actionContNO, QtCore.SIGNAL("triggered()"),lambda who="contNO": self.anyButton(who)) self.connect(self.ui.actionContNC, QtCore.SIGNAL("triggered()"),lambda who="contNC": self.anyButton(who)) self.connect(self.ui.actionCoil, QtCore.SIGNAL("triggered()"),lambda who="Coil": self.anyButton(who)) #self.connect(self.ui.actionCoilNot, QtCore.SIGNAL("triggered()"),lambda who="CoilNot": self.anyButton(who)) self.connect(self.ui.actionaddRung, QtCore.SIGNAL("triggered()"),lambda who="addRung": self.anyButton(who)) self.connect(self.ui.actionWiden, QtCore.SIGNAL("triggered()"),lambda who="Widen": self.anyButton(who)) #self.connect(self.ui.actionORbranch, QtCore.SIGNAL("triggered()"),lambda who="blankOR": self.anyButton(who)) self.connect(self.ui.actionDEL, QtCore.SIGNAL("triggered()"),lambda who="Del": self.anyButton(who)) self.connect(self.ui.actionORwire, QtCore.SIGNAL("triggered()"),lambda who="ORwire": self.anyButton(who)) self.connect(self.ui.actionNarrow, QtCore.SIGNAL("triggered()"),lambda who="Narrow": self.anyButton(who)) #self.connect(self.ui.actionRising, QtCore.SIGNAL("triggered()"),lambda who="Rising": self.anyButton(who)) self.connect(self.ui.actionFalling, QtCore.SIGNAL("triggered()"),lambda who="Fall": self.anyButton(who)) self.connect(self.ui.actionTimer, QtCore.SIGNAL("triggered()"),lambda who="Timer": self.anyButton(who)) self.connect(self.ui.actionCounter, QtCore.SIGNAL("triggered()"),lambda who="Counter": self.anyButton(who)) self.connect(self.ui.actionEquals, QtCore.SIGNAL("triggered()"),lambda who="Equals": self.anyButton(who)) self.connect(self.ui.actionPlus, QtCore.SIGNAL("triggered()"),lambda who="Plus": self.anyButton(who)) self.connect(self.ui.actionMinus, QtCore.SIGNAL("triggered()"),lambda who="Minus": self.anyButton(who)) self.connect(self.ui.actionMove, QtCore.SIGNAL("triggered()"),lambda who="Move": self.anyButton(who)) self.connect(self.ui.actionMult, QtCore.SIGNAL("triggered()"),lambda who="Mult": self.anyButton(who)) self.connect(self.ui.actionGreater, QtCore.SIGNAL("triggered()"),lambda who="Greater": self.anyButton(who)) self.connect(self.ui.actionLessthan, QtCore.SIGNAL("triggered()"),lambda who="Lessthan": self.anyButton(who)) self.connect(self.ui.actionGreaterOrEq, QtCore.SIGNAL("triggered()"),lambda who="GreaterOrEq": self.anyButton(who)) self.connect(self.ui.actionLessOrEq, QtCore.SIGNAL("triggered()"),lambda who="LessOrEq": self.anyButton(who)) self.connect(self.ui.actionPWM, QtCore.SIGNAL("triggered()"),lambda who="PWM": self.anyButton(who)) self.connect(self.ui.actionADC, QtCore.SIGNAL("triggered()"),lambda who="ADC": self.anyButton(who)) self.connect(self.ui.actionDivide, QtCore.SIGNAL("triggered()"),lambda who="Divide": self.anyButton(who)) ##002## #make a actiongroup so tools are exclusive (only one clicked) toolActionGroup = QActionGroup(self.ui.toolBar)#toolbar is named in _ui.py toolActionGroup.addAction(self.ui.actionContNO) toolActionGroup.addAction(self.ui.actionContNC) toolActionGroup.addAction(self.ui.actionCoil) #toolActionGroup.addAction(self.ui.actionCoilNot) toolActionGroup.addAction(self.ui.actionaddRung) toolActionGroup.addAction(self.ui.actionWiden) #toolActionGroup.addAction(self.ui.actionORbranch) toolActionGroup.addAction(self.ui.actionDEL) toolActionGroup.addAction(self.ui.actionORwire) toolActionGroup.addAction(self.ui.actionNarrow) #toolActionGroup.addAction(self.ui.actionRising) toolActionGroup.addAction(self.ui.actionFalling) toolActionGroup.addAction(self.ui.actionTimer) toolActionGroup.addAction(self.ui.actionCounter) toolActionGroup.addAction(self.ui.actionEquals) toolActionGroup.addAction(self.ui.actionPlus) toolActionGroup.addAction(self.ui.actionMinus) toolActionGroup.addAction(self.ui.actionMove) toolActionGroup.addAction(self.ui.actionMult) toolActionGroup.addAction(self.ui.actionGreater) toolActionGroup.addAction(self.ui.actionLessthan) toolActionGroup.addAction(self.ui.actionGreaterOrEq) toolActionGroup.addAction(self.ui.actionLessOrEq) toolActionGroup.addAction(self.ui.actionPWM) toolActionGroup.addAction(self.ui.actionADC) toolActionGroup.addAction(self.ui.actionDivide) toolActionGroup.setExclusive(True) self.connect(self.ui.actionWaltech, QtCore.SIGNAL("triggered()"),lambda HW="Waltech": self.chooseHW(HW)) self.connect(self.ui.actionOpenPLC, QtCore.SIGNAL("triggered()"),lambda HW="OpenPLC": self.chooseHW(HW)) self.connect(self.ui.actionArduinoUno, QtCore.SIGNAL("triggered()"),lambda HW="ArduinoUno": self.chooseHW(HW)) self.connect(self.ui.actionArduinoNano, QtCore.SIGNAL("triggered()"),lambda HW="ArduinoNano": self.chooseHW(HW)) self.connect(self.ui.actionArduinoMega, QtCore.SIGNAL("triggered()"),lambda HW="ArduinoMega": self.chooseHW(HW) ) hwActionGroup = QActionGroup(self.ui.menuDiagnostics) hwActionGroup.addAction(self.ui.actionWaltech) hwActionGroup.addAction(self.ui.actionOpenPLC) hwActionGroup.addAction(self.ui.actionArduinoUno) hwActionGroup.addAction(self.ui.actionArduinoNano) hwActionGroup.addAction(self.ui.actionArduinoMega) def checkmarkHW(self): pass #print "hardware clicked" ##########hardware choosing def chooseHW(self,HW): oldHW = self.currentHW self.currentHW = HW if self.checkForHiIO(HW)==True: #make popup refusing to change self.dialog = popupDialogs.ardIODialog() self.dialog.exec_()# For Modal dialogs self.currentHW = oldHW #change back HW = oldHW if str(HW)=="Waltech": self.ui.actionPWM.setEnabled(False) self.ui.actionADC.setEnabled(False) self.ui.actionWaltech.setChecked(True) if str(HW)=="OpenPLC": self.ui.actionPWM.setEnabled(True) self.ui.actionADC.setEnabled(True) self.ui.actionOpenPLC.setChecked(True) if str(HW)=="ArduinoUno": self.ui.actionPWM.setEnabled(True) self.ui.actionADC.setEnabled(True) self.ui.actionArduinoUno.setChecked(True) if str(HW)=="ArduinoNano": self.ui.actionPWM.setEnabled(True) self.ui.actionADC.setEnabled(True) self.ui.actionArduinoNano.setChecked(True) if str(HW)=="ArduinoMega": self.ui.actionPWM.setEnabled(True) self.ui.actionADC.setEnabled(True) self.ui.actionArduinoMega.setChecked(True) print "Hardware:", HW def checkForHiIO(self,oldHW): #go through grid and look for I higher than 12 for Waltech, 5 for ArduinoUno , 6 for ArduinoNano if self.currentHW == "Waltech" and ( self.checkInputNums() > 12 or self.checkOutputNums() >12 or self.checkADCPWMNs() != [0,0]): print ">>too high number io or have PWM or ADC" return True if self.currentHW == "ArduinoUno" and ( self.checkInputNums() > 5 or self.checkOutputNums() >7 or self.checkADCPWMNs()[0] > 4 or self.checkADCPWMNs()[1] > 2): print ">>too high number io or PWM or ADC" return True if self.currentHW == "ArduinoNano" and ( self.checkInputNums() > 6 or self.checkOutputNums() >8 or self.checkADCPWMNs()[0] > 4 or self.checkADCPWMNs()[1] > 2): print ">>too high number io or PWM or ADC" return True return False def checkADCPWMNs(self): #count up PWMs and ADCs #PWMADC[0] is number pf PWMs #PWMADC[1] is number pf ADCs height = len(self.grid) width = len(self.grid[0]) PWMADC = [0,0] for i in range(height): for j in range(width): if self.grid[i][j].MTorElement != None: print"mtorelement", self.grid[i][j].MTorElement if self.grid[i][j].MTorElement[:3] == 'PWM': PWMADC[0] = PWMADC[0] +1 if self.grid[i][j].MTorElement[:3] == 'ADC': PWMADC[1] = PWMADC[1] +1 print "PWM,ADC ",PWMADC return PWMADC def checkInputNums(self): height = len(self.grid) width = len(self.grid[0]) MaxIONum = 0 for i in range(height): for j in range(width): if self.grid[i][j].ioAssign != None and self.grid[i][j].ioAssign[:3] == 'in_': #print "input: ", self.grid[i][j].ioAssign[3:] if int(self.grid[i][j].ioAssign[3:]) > MaxIONum: MaxIONum = int(self.grid[i][j].ioAssign[3:]) return MaxIONum def checkOutputNums(self): height = len(self.grid) width = len(self.grid[0]) MaxIONum = 0 for i in range(height): for j in range(width): if self.grid[i][j].ioAssign != None and self.grid[i][j].ioAssign[:4] == 'out_': #print "input: ", self.grid[i][j].ioAssign[3:] if int(self.grid[i][j].ioAssign[4:]) > MaxIONum: MaxIONum = int(self.grid[i][j].ioAssign[4:]) return MaxIONum ##########hardware choosing^^^^^ def USBHelp(self): self.dialog = popupDialogs.USBHelpDialog() self.dialog.exec_()# For Modal dialogs def ArduinoUnoIOHelp(self): self.dialog = popupDialogs.ArduinoUnoIOHelpDialog() self.dialog.exec_()# For Modal dialogs def ArduinoNanoIOHelp(self): self.dialog = popupDialogs.ArduinoNanoIOHelpDialog() self.dialog.exec_()# For Modal dialogs def ArduinoMegaIOHelp(self): self.dialog = popupDialogs.ArduinoMegaIOHelpDialog() self.dialog.exec_()# For Modal dialogs def AboutHelp(self): self.dialog = popupDialogs.AboutHelpDialog() self.dialog.exec_()# For Modal dialogs def checkHW(self): plat = sys.platform.lower() # try to detect the OS so that a device can be selected... print "checked platform" if plat[:5] == 'linux': opSys = "NIX" elif plat == 'win32': opSys = "WIN" elif plat == "darwin": opSys = "MAC" else: opSys = "WIN" tester(opSys,self.currentHW).test1(self.ui.textBrowser) def printLadder(self): #printer = QPrinter(QPrinter.HighResolution) printer = QPrinter() dialog = QtGui.QPrintDialog(printer, self) if dialog.exec_() != QDialog.Accepted: return #printer.setResolution(600) #resolution = printer.resolution() #pageRect = printer.pageRect() painter = QPainter(printer) self.scene.render(painter) #self.ui.tableWidget.render(painter) del painter def makeImage(self): #def printLadder(self): image = QtGui.QImage(400,400,QtGui.QImage.Format_ARGB32)#for png #image = QtGui.QImage(256,256,QtGui.QImage.Format_RGB32) painter = QtGui.QPainter(image) painter.setRenderHint(QtGui.QPainter.Antialiasing) self.scene.render(painter) painter.end() print "saving image" if image.save('hexes/newImage.png', 'PNG'): print('saved') else: print("didn't save") #image.save("out.png") del painter def setupDataGrid(self): #x,y, element there, rung there, & there, element name, variable name, i/o connection. self.grid = [[]] # grid: list of rows ex: grid [2][6] gives cell 6 in row(rung) 2 self.reDoGrid = [[[]]]# list of grids for redo self.unDoGrid = [[[]]]# list of grids for undo self.currentTool = 0 #to track the tool being used width=10 for i in range(width):#fill the first row self.grid[0].append(cellStruct(i*60, 60, "MT","Rung", None, None, None, None, False, False, False, False, False, False,None,None,None,None,None)) for i in range(1,6):# add 5 more rungs to start ManageGrid(self.grid, self.scene,self.Tools,self.items).insertRung(i) def reFillList(self,uiList): #clear list while uiList.rowCount() > 0 : uiList.removeRow(0) #rows = uiList.rowCount() #for i in range(rows): # #delete this row # uiList.removeRow(0) #refill list print "refilling list" height = len(self.grid) width = len(self.grid[0]) for i in range(height): for j in range(width): if self.grid[i][j].MTorElement != "MT" and self.grid[i][j].MTorElement !="blankOR": uiList.setSortingEnabled(False)#stop sorting while adding row uiList.setRowCount(uiList.rowCount()+1) numRows= uiList.rowCount() try: uiList.setItem(numRows-1,0,QtGui.QTableWidgetItem(self.grid[i][j].variableName)) except: pass try: uiList.setItem(numRows-1,1,QtGui.QTableWidgetItem(self.grid[i][j].ioAssign)) except: pass try: uiList.setItem(numRows-1,2,QtGui.QTableWidgetItem(self.grid[i][j].MTorElement)) except: pass try: uiList.setItem(numRows-1,3,QtGui.QTableWidgetItem(str(i)+","+str(j))) except: pass uiList.setSortingEnabled(True) #track which tool is being used. maybe use names here? def anyButton(self,who): self.currentTool = who #print who def parseGrid(self): #self.showInfo() font=self.ui.textBrowser.currentFont() font.setWeight(QFont.Bold) self.ui.textBrowser.setCurrentFont(font) self.ui.textBrowser.setText("compiling with avr-gcc") QApplication.processEvents()#this makes the UI update before going on. font.setWeight(QFont.Normal) self.ui.textBrowser.setCurrentFont(font) QApplication.processEvents()#this makes the UI update before going on. outLine = ladderToOutLine(self.grid).makeOutLine() OutLineToC(self.grid,self.currentHW).makeC(outLine,self.ui.textBrowser, "C") #hexMaker(self).self.saveCfileAndCompile(C_txt,displayOutputPlace) def burn(self): #self.showInfo() font=self.ui.textBrowser.currentFont() font.setWeight(QFont.Bold) self.ui.textBrowser.setCurrentFont(font) self.ui.textBrowser.setText("compiling with avr-gcc") QApplication.processEvents()#this makes the UI update before going on. font.setWeight(QFont.Normal) self.ui.textBrowser.setCurrentFont(font) QApplication.processEvents()#this makes the UI update before going on. outLine = ladderToOutLine(self.grid).makeOutLine() OutLineToC(self.grid,self.currentHW).makeC(outLine,self.ui.textBrowser, "B") def showInfo(self): """ ManageGrid(self.grid, self.scene,self.Tools,self.items).reportCellInfo() ManageGrid(self.grid, self.scene,self.Tools,self.items).findStartsAndEnds() ManageGrid(self.grid, self.scene,self.Tools,self.items).reportCellStartsEnds() """ def unDo(self): if len(self.unDoGrid)>1: self.reDoGrid.append(copy.deepcopy(self.grid))#save this grid for re-do self.grid = copy.deepcopy(self.unDoGrid[-1])#make current grid last one in undo self.unDoGrid.pop()#delete last one in undo ManageGrid(self.grid, self.scene,self.Tools,self.items).totalRedraw() print("undone") else: print("no more undoes") def reDo(self): if len(self.reDoGrid)>0: self.unDoGrid.append(copy.deepcopy(self.grid))#save this grid for re-do if len(self.unDoGrid) >20:#limit to 20 undos self.unDoGrid.pop(0)#pop 0 self.grid = copy.deepcopy(self.reDoGrid[-1]) self.reDoGrid.pop() ManageGrid(self.grid, self.scene,self.Tools,self.items).totalRedraw() print("redone") else: print("no more redoes") def newFile(self): #verify popup self.clearList(self.ui.tableWidget) self.setupDataGrid()#set up rung variables: def saveGlobal(self): f=open(self.__class__.tempName, 'w') f.write(self.__class__.currentFileDir + "\n" + self.__class__.projectName) f.close() def saveFile(self): if self.__class__.projectName == None: format = "wlm" initialPath = os.getcwd() + "/untitled." + format; filename = QtGui.QFileDialog.getSaveFileName(self, 'Save As',initialPath) if filename == "": return self.__class__.currentFileDir=ntpath.dirname(str(filename)) self.__class__.projectName = filename self.saveGlobal() else: filename = self.__class__.projectName print "filename", filename f = open(filename, 'w') gridToSave = copy.deepcopy(self.grid) gridToSave.insert(0,self.currentHW)#put current hardware in list at 0 pickle.dump(gridToSave, f) f.close() def saveFileAs(self): format = "wlm" if self.__class__.currentFileDir == None: initialPath = os.getcwd() + "/untitled." + format; else: initialPath = self.__class__.currentFileDir + "untitled." + format; filename = QtGui.QFileDialog.getSaveFileName(self, 'Save As',initialPath) self.__class__.currentFileDir = ntpath.dirname(str(filename)) self.__class__.projectName = filename self.saveGlobal() print "filename", filename if filename == "": return f = open(str(filename), 'w') gridToSave = copy.deepcopy(self.grid) gridToSave.insert(0,self.currentHW)#put current hardware in list at 0 pickle.dump(gridToSave, f) f.close() def openFile(self): filedialog = QtGui.QFileDialog() #filedialog.setNameFilter('*.jpg') filename = filedialog.getOpenFileName(self, 'Open File', os.path.expanduser("~"),"*.wlm") if filename == "": return f = open(str(filename), 'r') justName = ntpath.basename(str(filename)) self.__class__.currentFileDir = ntpath.dirname(str(filename)) self.__class__.projectName = filename self.saveGlobal() print "self.currentFileDir:", self.__class__.currentFileDir print "self.projectName:", self.__class__.projectName self.grid = pickle.load(f) f.close() self.currentHW = self.grid.pop(0)#get current hardware from file print self.currentHW self.chooseHW(self.currentHW) #check width and height, make bounding box ManageGrid(self.grid, self.scene,self.Tools,self.items).changeRectangle() try: ManageGrid(self.grid, self.scene,self.Tools,self.items).totalRedraw() except: self.dialog = popupDialogs.wrongVersionDialog() self.dialog.exec_()# For Modal dialogs self.setupDataGrid() else: self.reFillList(self.ui.tableWidget) def whatsThis(self): QtGui.QWhatsThis.enterWhatsThisMode() def eventFilter(self, source, event): if event.type() == QtCore.QEvent.MouseMove: self.eraseMarker() cellNum = self.findCell(event) self.showMarker(cellNum) elif event.type() == QtCore.QEvent.Leave or event.type() == QtCore.QEvent.Wheel: self.eraseMarker() elif event.type() == QtCore.QEvent.MouseButtonPress: self.eraseMarker() cellNum = self.findCell(event) if cellNum != [None,None,None,None]: if event.button() == QtCore.Qt.LeftButton: print "left" self.leftClick(cellNum) elif event.button() == QtCore.Qt.RightButton: print "right" self.rightClick(cellNum) #if cellNum == [None,None,None,None]: else: pass # do other stuff return QtGui.QMainWindow.eventFilter(self, source, event) #self.ui.graphicsView.viewport().installEventFilter(self) def findCell(self,event): #Pos = event.globalPos() #doesn't stay when window moves #Pos = event.pos()# offset -60,-50 #Pos = self.ui.graphicsView.mapToScene(event.globalPos()) #doesn't stay when window moves Pos = self.ui.graphicsView.mapToScene(event.pos()) #things that don't work: #Pos = event.screenPos() #Pos = self.ui.graphicsView.mapToScene(event.screenPos()) #Qmousevent has no attribute screenPos #Pos = event.scenePos() #Pos = self.ui.graphicsView.mapToScene(event.scenePos()) #Qmousevent has no attribute scenePos #x=Pos.x()-172 x=Pos.x() -30 y=Pos.y() +60 self.ui.label_2.setNum(x)# set x,y display values self.ui.label_4.setNum(y) if 1 == 1:#disabled if #pos = self.ui.graphicsView.mapToScene(event.pos()) #pos = event.pos() #x = pos.x()-30 #y = pos.y()+60 cellNum = [None,None,None,None] for i in range(len(self.grid)): #cellNum[0]=i #backwards: row,col for j in range(len(self.grid[i])): if (self.grid[i][j].midPointX-30< x < self.grid[i][j].midPointX+30) and (self.grid[i][j].midPointY-30< y< self.grid[i][j].midPointY+30): cellNum = [i,j,None,None] if y<self.grid[cellNum[0]][cellNum[1]].midPointY: #insert above cellNum[2] = "up" else:#insert below cellNum[2] = "dn" if x<self.grid[cellNum[0]][cellNum[1]].midPointX: #insert left or right cellNum[3] = "rt" else: cellNum[3] = "lt" return cellNum def eraseMarker(self): itemlist = self.scene.items() #this is a list of ALL items in the scene for k in range(len(itemlist)): #compare to items placed last mousemove if itemlist[k] == self.items[0]: self.scene.removeItem(self.items[0]) if itemlist[k] == self.items[1]: self.scene.removeItem(self.items[1]) #puts a box around cell or marks or wire, or rung insert spot. called by mouse move in event filter def showMarker(self, cellNum): i=cellNum[0] j=cellNum[1] #see if the item was deleted elsewhere, like by scene.clear() #self.eraseMarker() if cellNum != [None,None,None,None]: #Optional: Don't show mouse pointer on graphiscview #self.ui.graphicsView.viewport().setCursor(QtCore.Qt.BlankCursor ) #show cell numbers: if self.currentTool != "addRung": self.items[0] = QtGui.QGraphicsTextItem("%d, %d" %(i,j)) self.items[0].setPos(self.grid[i][j].midPointX+35,self.grid[i][j].midPointY-35) self.scene.addItem(self.items[0]) #go through elementList and see which tool is being used if self.currentTool == "addRung": if cellNum[2] =="up" and cellNum[0] == 0: x=self.grid[i][j].midPointX y=self.grid[i][j].midPointY-90 else: x=self.grid[i][j].midPointX y=self.grid[i][j].midPointY-30 #y=self.grid[i][j].midPointY-90 w=200 h=1 self.items[1] = QtGui.QGraphicsRectItem(x-100,y,w,h) self.items[1].setPen(QtGui.QColor("blue")) self.scene.addItem(self.items[1]) self.items[0] = QtGui.QGraphicsTextItem("< >") self.items[0].setPos(self.grid[i][j].midPointX-111,y-15) self.items[0].setFont(QtGui.QFont("Arial",16)) self.items[0].setDefaultTextColor(QtGui.QColor("blue")) self.scene.addItem(self.items[0]) elif self.currentTool == "Widen": x=self.grid[i][j].midPointX y=self.grid[i][j].midPointY-90 w=1 h=62 self.items[1] = QtGui.QGraphicsRectItem(x,y,w,h) self.items[1].setPen(QtGui.QColor("blue")) self.scene.addItem(self.items[1]) elif self.currentTool == "ORwire": if cellNum[2] =="up": y=self.grid[i][j].midPointY-120 if cellNum[2] =="dn": y=self.grid[i][j].midPointY-60 x=self.grid[i][j].midPointX #y=self.grid[i][j].midPointY-60 w=1 h=60 self.items[1] = QtGui.QGraphicsRectItem(x,y,w,h) self.items[1].setPen(QtGui.QColor("blue")) self.scene.addItem(self.items[1]) elif self.currentTool == "blankOR": #"blankOR" 5 pixmap = QtGui.QPixmap(_fromUtf8(":/icons/icons/OR_big.png")) self.items[1] = QtGui.QGraphicsPixmapItem(pixmap) x=self.grid[i][j].midPointX y=self.grid[i][j].midPointY-60 self.items[1].setPos(x,y) self.scene.addItem(self.items[1]) else: #show box around cell: x=self.grid[i][j].midPointX y=self.grid[i][j].midPointY-90 w=58 h=58 self.items[1] = QtGui.QGraphicsRectItem(x,y,w,h) self.items[1].setPen(QtGui.QColor("blue")) self.scene.addItem(self.items[1]) def rightClick(self, cellNum): if cellNum != [None,None,None,None]: tool = self.grid[cellNum[0]][cellNum[1]].MTorElement clickSuccssful = False #update undo/redo stack here del self.reDoGrid[:]#first clear re-do satck self.unDoGrid.append(copy.deepcopy(self.grid))#save a copy(list) of this grid for undo if len(self.unDoGrid) >30:#limit to 30 undos self.unDoGrid.pop(0)#pop 0 #run popup: tempCellData = self.runPopup(tool,cellNum) if tempCellData != False:# Yes, new data entered, so update list at right: orphan = False if self.grid[cellNum[0]][cellNum[1]].variableName != tempCellData.variableName:#check if leaving orphan names orphan = ManageGrid(self.grid, self.scene, self.Tools,self.items).checkOrphanName(cellNum) if orphan == False: #update cell: ##014## """ #check that name is OK if not re.match(r'^[a-zA-Z0-9_]+$', tempCellData.variableName): print "bad name" self.grid[cellNum[0]][cellNum[1]].variableName = "rename_this" else: self.grid[cellNum[0]][cellNum[1]].variableName = tempCellData.variableName print "varname:", tempCellData.variableName """ self.grid[cellNum[0]][cellNum[1]].variableName = tempCellData.variableName print "varname:", tempCellData.variableName self.grid[cellNum[0]][cellNum[1]].comment = tempCellData.comment print "comment:", tempCellData.comment self.grid[cellNum[0]][cellNum[1]].ioAssign = tempCellData.ioAssign print "ioassign:", tempCellData.ioAssign self.grid[cellNum[0]][cellNum[1]].setPoint = tempCellData.setPoint print "setpoint:", tempCellData.setPoint self.grid[cellNum[0]][cellNum[1]].source_A = tempCellData.source_A print "source_A:", tempCellData.source_A self.grid[cellNum[0]][cellNum[1]].source_B = tempCellData.source_B print "source_B:", tempCellData.source_B self.grid[cellNum[0]][cellNum[1]].const_A = tempCellData.const_A print "const_A:", tempCellData.const_A self.grid[cellNum[0]][cellNum[1]].const_B = tempCellData.const_B print "const_B:", tempCellData.const_B self.grid[cellNum[0]][cellNum[1]].functType = tempCellData.functType #not used print "functType:", tempCellData.functType #not used clickSuccssful = True #>>>>>cleanup and redraw: if clickSuccssful == False: print("nothing done") self.unDoGrid.pop()#delete last one in undo ManageGrid(self.grid, self.scene, self.Tools,self.items).totalRedraw() self.reFillList(self.ui.tableWidget) def leftClick(self, cellNum): #this def is a specific one, automatically connected to mousePressEvent in UI if cellNum != [None,None,None,None]:#mouse click was located in cells #variable bridge from findng position (todo: change this): if cellNum[2] == "up":UpDwn = 0 if cellNum[2] == "dn":UpDwn = 1 if cellNum[3] == "rt":RtLft = 1 if cellNum[3] == "lt":RtLft = 0 clickSuccssful = False #will be set to true if an action is taken, allows undo to be rolled back of not #update undo/redo stack here del self.reDoGrid[:]#first clear re-do satck self.unDoGrid.append(copy.deepcopy(self.grid))#save a copy(list) of this grid for undo if len(self.unDoGrid) >30:#limit to 30 undos self.unDoGrid.pop(0)#pop 0 #go through elementList and see which tool is being used numTools = len(self.Tools.toolList) toolToPlace = ("0",0)#name and index of tool in toolList for i in range(0,numTools): if self.Tools.toolList[i].toolName == self.currentTool: toolToPlace = (self.Tools.toolList[i].toolName,i) print("tool #: %d" %(toolToPlace[1])) #>>>>>↓↓↓ELEMENT PLACEMENT↓↓↓<<<<<<<<< #>>>>place Element on rung: if self.Tools.toolList[toolToPlace[1]].toolType == "Element"\ and self.grid[cellNum[0]][cellNum[1]].rungOrOR != "OR": #tool to place is an elememt, (not widen or add rung) #>>>>place non-coil Element on rung: if self.Tools.toolList[toolToPlace[1]].position == "any": if self.grid[cellNum[0]][cellNum[1]].MTorElement == "MT"\ and cellNum[1] != len(self.grid[cellNum[0]])-1: #not at the far right # cause popup dialog tempCellInfo = self.runPopup(toolToPlace[0],cellNum) if tempCellInfo != False: #update list at right #self.addToList(self.ui.tableWidget,tempCellInfo,(cellNum[0],cellNum[1])) #place element on grid ManageGrid(self.grid, self.scene, self.Tools,self.items)\ .placeElememt(cellNum,tempCellInfo,toolToPlace) clickSuccssful = True #>>element that should shift to right if "right" (coil, timerreset..) elif self.Tools.toolList[toolToPlace[1]].position == "right": cellNum[1] = len(self.grid[0])-1 #right most spot if self.grid[cellNum[0]][cellNum[1]].MTorElement == "MT": # cause popup dialog tempCellInfo = self.runPopup(toolToPlace[0],cellNum) if tempCellInfo != False: #update list at right #self.addToList(self.ui.tableWidget,tempCellInfo,(cellNum[0],cellNum[1])) #place element on grid ManageGrid(self.grid, self.scene, self.Tools,self.items)\ .placeElememt(cellNum,tempCellInfo,toolToPlace) clickSuccssful = True #>>>>place Element on OR: if self.Tools.toolList[toolToPlace[1]].toolType == "Element"\ and self.grid[cellNum[0]][cellNum[1]].MTorElement == "blankOR": if self.Tools.toolList[toolToPlace[1]].position == "any": # cause popup dialog tempCellInfo = self.runPopup(toolToPlace[0],cellNum) if tempCellInfo != False: ManageGrid(self.grid, self.scene, self.Tools,self.items)\ .placeElememt(cellNum,tempCellInfo,toolToPlace) clickSuccssful = True #>>element only allowed on rt (coil, timerreset..) elif self.Tools.toolList[toolToPlace[1]].position == "right": cellNum[1] = len(self.grid[0])-1 #right most spot print ("elemnt to right") if self.grid[cellNum[0]][cellNum[1]].MTorElement == "blankOR": tempCellInfo = self.runPopup(toolToPlace[0],cellNum)# cause popup dialog if tempCellInfo != False: ManageGrid(self.grid, self.scene, self.Tools,self.items)\ .placeElememt(cellNum,tempCellInfo,toolToPlace) clickSuccssful = True #>>>>↑↑↑ELEMENT PLACEMENT↑↑↑<<<<< #>>>>>addRung: if self.Tools.toolList[toolToPlace[1]].toolName == "addRung": Ypos = cellNum[0] + UpDwn print "upDwn", UpDwn ManageGrid(self.grid, self.scene, self.Tools,self.items).insertRung(Ypos) clickSuccssful = True #>>>>>Widen: elif self.Tools.toolList[toolToPlace[1]].toolName == "Widen": #cellNum[1] = cellNum[1] + RtLft ManageGrid(self.grid, self.scene, self.Tools,self.items).Widen(cellNum) clickSuccssful = True #>>>>>addOR: elif self.Tools.toolList[toolToPlace[1]].toolName == "blankOR": cellNum[0] = cellNum[0] + UpDwn #cellNum[1] = cellNum[1] - RtLft #adjust for right or left clickage of cell if cellNum[1]< 0:# don't add off left cellNum[1] = 0 if cellNum[0] <1: cellNum[0]= 1#don't add an OR above ManageGrid(self.grid, self.scene, self.Tools,self.items).insertBlankOR(cellNum) clickSuccssful = True print("blank OR added") #>>>>>addORwire: elif self.Tools.toolList[toolToPlace[1]].toolName == "ORwire": cellNum[0] = cellNum[0] + UpDwn #cellNum[1] = cellNum[1] - RtLft #adjust for right or left clickage of cell if cellNum[1]< 0:# don't add off left cellNum[1] = 0 if cellNum[0] <1: cellNum[0]= 1#don't add an OR above ManageGrid(self.grid, self.scene, self.Tools,self.items).addWire(cellNum) clickSuccssful = True print("wire placed") #>>>>>Delete: elif self.Tools.toolList[toolToPlace[1]].toolName == "Del": #loc = (cellNum[0],cellNum[1]) if ManageGrid(self.grid, self.scene, self.Tools,self.items).checkOrphanName(cellNum)==False: #delete element on OR branch: if self.grid[cellNum[0]][cellNum[1]].rungOrOR == "OR"\ and self.grid[cellNum[0]][cellNum[1]].MTorElement != "MT"\ and self.grid[cellNum[0]][cellNum[1]].MTorElement != "blankOR": ManageGrid(self.grid, self.scene, self.Tools,self.items).Delete(cellNum) #delete of element on Rung or delete the rung: elif self.grid[cellNum[0]][cellNum[1]].rungOrOR == "Rung": ManageGrid(self.grid, self.scene, self.Tools,self.items).Delete(cellNum) clickSuccssful = True #>>>>>Shrink elif self.Tools.toolList[toolToPlace[1]].toolName == "Narrow": #self.ui.graphicsView.prepareGeometryChange() ManageGrid(self.grid, self.scene, self.Tools,self.items).Shrink(cellNum)#then do function to narrow if can #>>>>>cleanup and redraw: if clickSuccssful == False: print("nothing done") self.unDoGrid.pop()#delete last one in undo ManageGrid(self.grid, self.scene, self.Tools,self.items).totalRedraw() self.showInfo() self.reFillList(self.ui.tableWidget) #will run popup and return tempCellData with all info from popup #send tool being used, cellNum #doesn't do anything with the grid. def runPopup(self, tool, cellNum): popUpOKed = False #becomes true if dialog is OK'ed tempCellInfo = cellStruct(None,None,None,None,None,None,None,None, False, False, False, False, False, False,None,None,None,None,None) ##004## if tool == "Coil" or tool =="CoilNot":#do dialog for this tool: self.dialog = popupDialogs.CoilDialog(self.grid, cellNum,self.currentHW) popUpOKed = self.dialog.exec_()# For Modal dialogs elif tool == "contNO" or tool =="contNC":#do dialog for this tool: self.dialog = popupDialogs.ContDialog(self.grid, cellNum,self.currentHW) popUpOKed = self.dialog.exec_()# For Modal dialogs elif tool == "Rising" or tool =="Fall":#do dialog for this tool: self.dialog = popupDialogs.EdgeDialog(self.grid, cellNum,self.currentHW) popUpOKed = self.dialog.exec_()# For Modal dialogs elif tool == "Timer" :#do dialog for this tool: self.dialog = popupDialogs.TimerDialog(self.grid, cellNum,self.currentHW) popUpOKed = self.dialog.exec_()# For Modal dialogs elif tool == "Counter" :#do dialog for this tool: self.dialog = popupDialogs.CounterDialog(self.grid, cellNum,self.currentHW) popUpOKed = self.dialog.exec_()# For Modal dialogs elif tool == "Plus"or tool =="Minus"or tool =="Divide"or tool =="Mult" or tool == "Move" :#do dialog for this tool: self.dialog = popupDialogs.MathDialog(self.grid, cellNum,self.currentHW,tool) popUpOKed = self.dialog.exec_()# For Modal dialogs elif tool == "Equals" or tool =="Greater"or tool =="Lessthan"or tool =="GreaterOrEq"or tool =="LessOrEq":#do dialog for this tool: self.dialog = popupDialogs.CompairDialog(self.grid, cellNum,self.currentHW,tool) popUpOKed = self.dialog.exec_()# For Modal dialogs #elif tool == "Move" :#do dialog for this tool: # self.dialog = popupDialogs.MoveDialog(self.grid, cellNum,self.currentHW) # popUpOKed = self.dialog.exec_()# For Modal dialogs elif tool == "PWM" :#do dialog for this tool: self.dialog = popupDialogs.PWMDialog(self.grid, cellNum,self.currentHW) popUpOKed = self.dialog.exec_()# For Modal dialogs elif tool == "ADC" :#do dialog for this tool: self.dialog = popupDialogs.ADCDialog(self.grid, cellNum,self.currentHW) popUpOKed = self.dialog.exec_()# For Modal dialogs #Equals Greater Lessthan GreaterOrEq LessOrEq Plus Minus Divide Mult Move PWM ADC if popUpOKed == True: ##008## # get all info from popup: try: tempCellInfo.ioAssign = self.dialog.ui.comboBox.currentText()#I/O assign except: pass try: tempCellInfo.variableName = self.dialog.ui.comboBox_2.currentText()#variable Name except: pass else: #check that name is OK if not re.match(r'^[a-zA-Z0-9_]+$', tempCellInfo.variableName): print "bad name" tempCellInfo.variableName = "please_rename" try: tempCellInfo.comment = self.dialog.ui.lineEdit.text()#comment except: pass try: tempCellInfo.setPoint = self.dialog.ui.doubleSpinBox.value() #setpoint decimal except: pass try: tempCellInfo.setPoint = self.dialog.ui.spinBox.value() #setpoint integer except: pass #try: tempCellInfo.ioAssign = self.dialog.ui.comboBox.currentText() #except: pass #for comparison operators: try: tempCellInfo.source_A = self.dialog.ui.comboBox_A.currentText() except: pass try: tempCellInfo.source_B = self.dialog.ui.comboBox_B.currentText() except: pass try: tempCellInfo.const_A = self.dialog.ui.spinBox_A.value() except: pass try: tempCellInfo.const_B = self.dialog.ui.spinBox_B.value() except: pass tempCellInfo.MTorElement = tool return tempCellInfo else: return False