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()
Beispiel #2
0
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()
Beispiel #3
0
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
Beispiel #4
0
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()
Beispiel #5
0
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()
Beispiel #7
0
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)
Beispiel #8
0
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_()
Beispiel #9
0
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('')
Beispiel #10
0
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)
Beispiel #11
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)
Beispiel #12
0
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 []
Beispiel #13
0
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)
Beispiel #14
0
class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.__ui = Ui_MainWindow()
        self.__ui.setupUi(self)
Beispiel #15
0
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('')
Beispiel #16
0
    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)

    # 기존 투입 자산 대비 현재 얼마나 가치를 가지고 있나 측정
Beispiel #17
0
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)
Beispiel #18
0
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)
Beispiel #19
0
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)
Beispiel #20
0
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()
Beispiel #21
0
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()
Beispiel #22
0
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()
Beispiel #24
0
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')
Beispiel #25
0
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")
Beispiel #27
0
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)
Beispiel #28
0
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()
Beispiel #29
0
"""
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_())
Beispiel #30
0
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)
Beispiel #31
0
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()
Beispiel #32
0
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()
Beispiel #33
0
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)
Beispiel #35
0
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()
Beispiel #36
0
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)
Beispiel #37
0
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