def start_threads(self):
        self.log.append('starting {} threads'.format(self.NUM_THREADS))
        self.button_start_threads.setDisabled(True)
        self.button_stop_threads.setEnabled(True)

        self.__workers_done = 0
        self.__threads = []
        for idx in range(self.NUM_THREADS):
            worker = Worker(idx)
            thread = QThread()
            thread.setObjectName('thread_' + str(idx))
            self.__threads.append((thread, worker))  # need to store worker too otherwise will be gc'd
            worker.moveToThread(thread)

            # get progress messages from worker:
            worker.sig_step.connect(self.on_worker_step)
            worker.sig_done.connect(self.on_worker_done)
            worker.sig_msg.connect(self.log.append)

            # control worker:
            self.sig_abort_workers.connect(worker.abort)

            # get read to start worker:
            # self.sig_start.connect(worker.work)  # needed due to PyCharm debugger bug (!); comment out next line
            thread.started.connect(worker.work)
            thread.start()  # this will emit 'started' and start thread's event loop
Beispiel #2
0
    def start_threads_and_send_mails(self):
        mails_to_send = []
        for i in range(self.listWidget_emails.count()):
            item = self.listWidget_emails.item(i)
            if item.checkState():
                item.setSelected(True)
                xlsx_row = item.xlsx_row
                # Сохраняем номер строки, чтобы потом легко пометить её зелёным
                xlsx_row['QListWidgetIndex_WcCRve89'] = i
                mails_to_send.append(item.xlsx_row)
        if not mails_to_send:
            msg = 'Ни одно письмо для отправки не выбрано'
            QMessageBox.information(self.parent, 'OK', msg)
            raise Exception(msg)
        # Создаём по отправляльщику на каждый worker
        # Равномерно распределяем на них на всех почту
        self.USE_THREADS = min(self.NUM_THREADS, len(mails_to_send))
        envelopes = [self.envelope.copy() for __ in range(self.USE_THREADS)]
        for i, xlsx_row in enumerate(mails_to_send):
            envelopes[i % self.USE_THREADS].add_mail_to_queue(
                recipients=xlsx_row['email'],
                subject=xlsx_row['subject'],
                html=self.template.format(**xlsx_row),
                files=xlsx_row['attach_list'],
                xls_id=xlsx_row[ORIGINAL_ROW_NUM],
                qt_id=xlsx_row['QListWidgetIndex_WcCRve89'])
        # Лочим кнопки
        self.pushButton_ask_and_send.setDisabled(True)
        self.pushButton_open_list_and_template.setDisabled(True)
        self.pushButton_cancel_send.setEnabled(True)
        # Готовим worker'ов
        self.__workers_done = 0
        self.__threads = []
        for idx in range(self.USE_THREADS):
            worker = Worker(idx, envelopes[idx])
            thread = QThread()
            thread.setObjectName('thread_' + str(idx))
            self.__threads.append(
                (thread,
                 worker))  # need to store worker too otherwise will be gc'd
            worker.moveToThread(thread)

            # get progress messages from worker:
            worker.sig_step.connect(self.on_worker_step)
            worker.sig_done.connect(self.on_worker_done)
            worker.sig_mail_sent.connect(self.on_mail_sent)
            worker.sig_mail_error.connect(self.on_mail_error)

            # control worker:
            self.sig_abort_workers.connect(worker.abort)

            # get read to start worker:
            thread.started.connect(worker.work)
            thread.start(
            )  # this will emit 'started' and start thread's event loop
Beispiel #3
0
class ProcessController(QObject):

    processBeanChanged = Signal()
    settingsBeanChanged = Signal()
    closingApplicationSignal = Signal()
    showDialogSignal = Signal(str, arguments=['message'])

    # laserFolderWatcherConnectedSignal = Signal(bool, arguments=['isConnected'])

    def __init__(self, parent=None):
        super().__init__(parent)
        self.__processBean: ProcessBean = None
        self.__settingsBean: SettingsBean = None
        self.__ftpWatcherThread: QThread = None
        self.__ftpWatcher: FTPWatcher = None
        self.__sshWatcher: SSHWatcher = None
        self.__fsWatcher: FSWatcher = None
        self.__fsWatcherThread: QThread = None
        self.__csvRegeneratorThread = CSVRegenerator()
        self.setupSignalsAndSlots()

    def getProcessBean(self):
        return self.__processBean

    def setProcessBean(self, bean: ProcessBean):
        self.__processBean = bean
        self.processBeanChanged.emit()

    def getSettingsBean(self):
        return self.__settingsBean

    def setSettingsBean(self, bean: SettingsBean):
        self.__settingsBean = bean
        self.settingsBeanChanged.emit()

    pProcessBean = Property(ProcessBean,
                            getProcessBean,
                            setProcessBean,
                            notify=processBeanChanged)
    pSettingsBean = Property(SettingsBean,
                             getSettingsBean,
                             setSettingsBean,
                             notify=settingsBeanChanged)

    def setupSignalsAndSlots(self):
        self.closingApplicationSignal.connect(self.freeResources)

    @Slot()
    def freeResources(self):
        if isinstance(self.__ftpWatcherThread, QThread):
            if self.__processBean.isLaserWatcherRunning():
                Logger().debug("Stop laser watcher thread")
                QMetaObject.invokeMethod(self.__ftpWatcher, "stopProcess")

        if isinstance(self.__fsWatcherThread, QThread):
            if self.__processBean.isCameraWatcherRunning():
                Logger().debug("Stop camera watcher thread")
                QMetaObject.invokeMethod(self.__fsWatcher, "stopProcess")

    @Slot()
    def initBean(self):
        QTimer.singleShot(2000, self.startCameraWatcher)
        QTimer.singleShot(2500, self.startLaserWatcher)

    @Slot(None)
    def saveParameters(self):
        s = Settings()
        s.saveCurrentParameters()

    @Slot(str)
    def setLocalLoadingPath(self, path: str):
        path = self.handleUrlPath(path)
        Logger().debug("Impostato loading path: " + path)
        self.__settingsBean.setLocalLoadingPath(path)

    @Slot(str)
    def setLocalDownloadingPath(self, path: str):
        path = self.handleUrlPath(path)
        Logger().debug("Impostato downloading path: " + path)
        self.__settingsBean.setLocalDownloadingPath(path)

    @Slot(str)
    def setCameraRemotePath(self, path: str):
        path = self.handleUrlPath(path)
        Logger().debug("Impostato camera path: " + path)
        self.__settingsBean.setCameraRemotePath(path)

    def handleUrlPath(self, path: str) -> str:
        url = QUrl(path)
        pathOk = ""
        if url.isLocalFile():
            pathOk = QDir.toNativeSeparators(url.toLocalFile())
        else:
            pathOk = path
        return pathOk

    @Slot(str, result=str)
    def getUrlFromNativePath(self, path: str):
        path = QDir.fromNativeSeparators(path)
        url = QUrl.fromLocalFile(path)
        res = str(url.toString())
        return res

    @Slot(None)
    def startLaserWatcher(self):
        Logger().debug("Start laser watcher thread")

        self.__ftpWatcherThread = QThread()
        self.__ftpWatcherThread.setObjectName("CSVWatcherThread")
        self.__ftpWatcher = FTPWatcher(
            remotePath=self.__settingsBean.getLaserRemotePath(),
            ftpAddress=self.__settingsBean.getLaserIp(),
            intervalMs=self.__settingsBean.getLaserPollingTimeMs(),
            ftpPort=self.__settingsBean.getLaserPort())
        self.__ftpWatcher.moveToThread(self.__ftpWatcherThread)

        self.__ftpWatcherThread.started.connect(self.__ftpWatcher.startProcess)
        self.__ftpWatcher.itemsPathUpdatedSignal.connect(
            lambda items: (self.__processBean.setLaserFolderItems(items),
                           self.analizeFolderItems()))
        # self.__csvWatcher.isConnectedSignal.connect(self.laserFolderWatcherConnectedSignal)
        self.__ftpWatcher.isConnectedSignal.connect(
            lambda isConnected: self.__processBean.setLaserConnectionUp(
                isConnected))

        self.__ftpWatcher.startedSignal.connect(
            lambda: self.__processBean.setLaserWatcherRunning(True))
        self.__ftpWatcher.stoppedSignal.connect(
            lambda: self.__processBean.setLaserWatcherRunning(False))

        self.__ftpWatcher.stoppedSignal.connect(self.__ftpWatcherThread.quit)
        self.__ftpWatcherThread.finished.connect(
            self.__ftpWatcherThread.deleteLater)
        self.__ftpWatcherThread.finished.connect(self.__ftpWatcher.deleteLater)

        Logger().debug("Laser watcher thread avviato")

        self.__ftpWatcherThread.start()

    @Slot(None)
    def stopLaserWatcher(self):
        Logger().debug("Stop laser watcher thread")
        QMetaObject.invokeMethod(self.__ftpWatcher, "stopProcess")

    @Slot(None)
    def startCameraWatcher(self):
        Logger().debug("Start camera watcher thread")

        self.__fsWatcherThread = QThread()
        self.__fsWatcherThread.setObjectName("FSWatcherThread")
        self.__fsWatcher = FSWatcher(
            path=self.__settingsBean.getCameraRemotePath(),
            intervalMs=self.__settingsBean.getCameraPollingTimeMs())
        self.__fsWatcher.moveToThread(self.__fsWatcherThread)

        self.__fsWatcherThread.started.connect(self.__fsWatcher.startProcess)
        self.__fsWatcher.itemsPathUpdatedSignal.connect(
            lambda items: self.__processBean.setCameraFolderItems(items))
        self.__fsWatcher.isConnectedSignal.connect(
            lambda isConnected: self.__processBean.setCameraConnectionUp(
                isConnected))
        self.__fsWatcher.startedSignal.connect(
            lambda: self.__processBean.setCameraWatcherRunning(True))
        self.__fsWatcher.stoppedSignal.connect(
            lambda: self.__processBean.setCameraWatcherRunning(False))

        self.__fsWatcher.stoppedSignal.connect(self.__fsWatcherThread.quit)
        self.__fsWatcherThread.finished.connect(
            self.__fsWatcherThread.deleteLater)
        self.__fsWatcherThread.finished.connect(self.__fsWatcher.deleteLater)

        Logger().debug("Camera watcher thread avviato")

        self.__fsWatcherThread.start()

    @Slot(None)
    def stopCameraWatcher(self):
        Logger().debug("Stop camera watcher thread")
        QMetaObject.invokeMethod(self.__fsWatcher, "stopProcess")

    @Slot(None)
    def sendCsvFileToDevices(self):

        localloadingPath = self.__settingsBean.getLocalLoadingPath()
        csvFilename = self.__settingsBean.getLocalCsvFilename()
        csvLocalPath = localloadingPath + "\\" + csvFilename
        cameraPath = self.__settingsBean.getCameraRemotePath()
        csvCameraPath = cameraPath + "\\" + csvFilename

        if not os.path.exists(csvLocalPath):
            Logger().error("File " + csvLocalPath + " non trovato")
            self.showDialogSignal.emit(
                "Nessun file trovato nella cartella locale")
            return

        # invio file csv al laser
        Logger().info("Invio file " + csvFilename + " al laser")

        ftpController = FTP()
        ftpController.host = self.__settingsBean.getLaserIp()
        ftpController.port = self.__settingsBean.getLaserPort()
        laserFTPRemotePath = self.__settingsBean.getLaserRemotePath()

        try:
            ftpController.connect()
            ftpController.login()
            ftpController.cwd(laserFTPRemotePath)
            cmd = "STOR " + csvFilename
            Logger().debug("Comando: " + cmd)
            fp = open(csvLocalPath, "rb")
            ftpController.storbinary(cmd, fp)

        except ftplib.all_errors as ftpErr:
            Logger().error("Error on FTP:" + str(ftpErr))
            ftpController.close()
            self.showDialogSignal.emit("Errore invio file csv al laser")
            return

        if self.__settingsBean.getCameraSendCSV():
            # invio il file csv alla camera
            Logger().info("Invio file " + csvFilename + " alla camera")
            try:
                shutil.copy(csvLocalPath, csvCameraPath)
            except:
                Logger().error("Impossibile copiare il file csv in camera")
                self.showDialogSignal.emit("Errore invio file csv alla camera")
                return

            self.showDialogSignal.emit("Invio OK al laser e camera")
        else:
            Logger().info("Invio file " + csvFilename +
                          " alla camera non richiesto")
            self.showDialogSignal.emit("Invio OK al laser")

        self.__processBean.setCsvRegThreadCsvNewEmpty(False)

    @Slot(None)
    def removeCsvFileFromDevices(self):

        Logger().info("Rimozione file cartella laser")

        ftpController = FTP()
        ftpController.host = self.__settingsBean.getLaserIp()
        ftpController.port = self.__settingsBean.getLaserPort()
        laserFTPRemotePath = self.__settingsBean.getLaserRemotePath()
        cameraPath = self.__settingsBean.getCameraRemotePath()
        csvFilename = self.__settingsBean.getLocalCsvFilename()
        csvCameraPath = cameraPath + "\\" + csvFilename

        try:
            ftpController.connect()
            ftpController.login()
            ftpController.cwd(laserFTPRemotePath)
            Logger().info("Rimozione file: " + csvFilename)
            ftpController.delete(csvFilename)

        except ftplib.all_errors as ftpErr:
            Logger().error("Errore rimozione file: " + str(ftpErr))
            self.showDialogSignal.emit(
                "Errore cancellazione file csv dal laser - " + str(ftpErr))
        finally:
            ftpController.close()

        try:
            if os.path.exists(csvCameraPath):
                Logger().debug("Rimozione file .csv dalla camera")
                os.remove(csvCameraPath)
        except OSError as err:
            if err != errno.ENOENT:
                Logger().error("Errore rimozione file dalla camera")
                self.showDialogSignal.emit(
                    "Errore cancellazione file csv dalla camera")

        Logger().info("Rimozione file cartella laser OK")

    @Slot()
    def removeErrorFileFromLaser(self):
        Logger().info("Rimozione file error dal laser")

        ftpController = FTP()
        ftpController.host = self.__settingsBean.getLaserIp()
        ftpController.port = self.__settingsBean.getLaserPort()
        laserFTPRemotePath = self.__settingsBean.getLaserRemotePath()
        errorFilename = self.__settingsBean.getLocalLaserErrorFilename()

        try:
            ftpController.connect()
            ftpController.login()
            ftpController.cwd(laserFTPRemotePath)
            Logger().info("Rimozione file: " + errorFilename)
            ftpController.delete(errorFilename)

        except ftplib.all_errors as ftpErr:
            Logger().error("Errore rimozione file: " + str(ftpErr))
            self.showDialogSignal.emit(
                "Errore cancellazione file csv dal laser - " + str(ftpErr))
        finally:
            ftpController.close()

        Logger().info("Rimozione file error dal laser")

    @Slot(bool)
    def changeStopRequestValue(self, stop: bool):
        self.__csvRegeneratorThread.setStopRequest(stop)
        self.__processBean.setStopRegThread(stop)

    @Slot(bool)
    def changePauseRequestValue(self, pause: bool):
        self.__csvRegeneratorThread.setPauseRequest(pause)
        self.__processBean.setPauseRegThread(pause)

    def analizeFolderItems(self):

        # Logger().debug("Analisi lista file laser")

        items = self.getProcessBean().getLaserFolderItems()
        isErrorFounded = False
        isCsvFounded = False

        for item in items:
            if item.lower() == self.__settingsBean.getLocalLaserErrorFilename(
            ).lower():
                # Logger().debug("Trovato error file: "+self.__settingsBean.getLocalLaserErrorFilename().lower())
                isErrorFounded = True
            if item.lower() == self.__settingsBean.getLocalCsvFilename().lower(
            ):
                # Logger().debug("Trovato csv file: "+self.__settingsBean.getLocalCsvFilename().lower())
                isCsvFounded = True
            if isCsvFounded and isErrorFounded:
                break

        self.__processBean.setErrorFileFounded(isErrorFounded)

        if self.__csvRegeneratorThread.isRunning():
            return

        if self.__processBean.isStopRegThread():
            return

        if isCsvFounded and isErrorFounded:

            Logger().debug(
                "Trovato error file: " +
                self.__settingsBean.getLocalLaserErrorFilename().lower())
            Logger().debug("Trovato csv file: " +
                           self.__settingsBean.getLocalCsvFilename().lower())

            Logger().debug("Avvio thread per rigenerazione file")
            self.__csvRegeneratorThread.setLaserFileList(items)
            self.__csvRegeneratorThread.setLaserConnectionParameters(
                self.__settingsBean.getLaserIp(),
                self.__settingsBean.getLaserPort(),
                self.__settingsBean.getLaserRemotePath())

            self.__csvRegeneratorThread.setLocalWaitTimeBeforeStart(
                self.__settingsBean.getLocalWaitTimeBeforeProcess())
            self.__csvRegeneratorThread.setLocalLoadingPath(
                self.__settingsBean.getLocalLoadingPath())
            self.__csvRegeneratorThread.setLocalDownloadingPath(
                self.__settingsBean.getLocalDownloadingPath())

            self.__csvRegeneratorThread.setCameraConnectionParameters(
                self.__settingsBean.getCameraRemotePath())
            self.__csvRegeneratorThread.setCameraSendCSV(
                self.__settingsBean.getCameraSendCSV())

            self.__csvRegeneratorThread.setCsvFilename(
                self.__settingsBean.getLocalCsvFilename())
            self.__csvRegeneratorThread.setErrorFilename(
                self.__settingsBean.getLocalLaserErrorFilename())
            self.__csvRegeneratorThread.setLogFilename(
                self.__settingsBean.getLocalLaserLogFilename())

            self.__csvRegeneratorThread.setRowMargin(
                self.__settingsBean.getLocalRowMargin())

            self.__csvRegeneratorThread.cleanLocalFolderStepSignal.connect(
                lambda value: self.__processBean.
                setCsvRegThreadCleanLocalFolderStatus(value))

            self.__csvRegeneratorThread.cleanCameraFolderStepSignal.connect(
                lambda value: self.__processBean.
                setCsvRegThreadCleanCameraFolderStatus(value))

            self.__csvRegeneratorThread.renameLaserItemsStepSignal.connect(
                lambda value: self.__processBean.
                setCsvRegThreadRenameLaserItemsStatus(value))

            self.__csvRegeneratorThread.downloadItemsFromLaserStepSignal.connect(
                lambda value: self.__processBean.
                setCsvRegThreadDownloadItemsStatus(value))

            self.__csvRegeneratorThread.cleanLaserFolderStepSignal.connect(
                lambda value: self.__processBean.
                setCsvRegThreadCleanLaserFolderStatus(value))

            self.__csvRegeneratorThread.csvBuildProcessStepSignal.connect(
                lambda value: self.__processBean.
                setCsvRegThreadCsvCreationProcessStatus(value))

            self.__csvRegeneratorThread.sendCsvToLaserStepSignal.connect(
                lambda value: self.__processBean.
                setCsvRegThreadSendCsvToLaserStatus(value))

            self.__csvRegeneratorThread.sendCsvToCameraStepSignal.connect(
                lambda value: self.__processBean.
                setCsvRegThreadSendCsvToCameraStatus(value))

            self.__csvRegeneratorThread.exitCodeSignal.connect(
                lambda value: self.__processBean.setCsvRegThreadExitCode(value
                                                                         ))

            self.__csvRegeneratorThread.started.connect(
                lambda: self.__processBean.setCsvRegThreadRunning(True))

            self.__csvRegeneratorThread.finished.connect(
                lambda: self.__processBean.setCsvRegThreadRunning(False))

            self.__csvRegeneratorThread.threadPausedSignal.connect(
                lambda value: self.__processBean.setCsvRegThreadPause(value))

            self.__csvRegeneratorThread.cvsNewFileEmptySignal.connect(
                lambda isEmpty: self.__processBean.setCsvRegThreadCsvNewEmpty(
                    isEmpty))

            self.__csvRegeneratorThread.start()
Beispiel #4
0
class DevicesView(QTreeView):
    def __init__(self, *args, **kwargs):
        super().__init__()

        self.setModel(DevicesModel())

        self.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
        self.customContextMenuRequested.connect(self.context_menu_handler)

        self.reload()

        self.device_monitor = DeviceMonitor()
        self.thread = QThread(self)
        self.device_monitor.device_signal.connect(
            self.device_signal__handler
        )  # set handler for device_monitor "device_signal" event
        self.device_monitor.moveToThread(self.thread)
        self.thread.setObjectName('DeviceMonitorThread')
        self.thread.started.connect(self.device_monitor.monitor_devices
                                    )  # set handler for thread "started" event
        self.thread.start()

    @Slot(object)  # handler
    def device_signal__handler(self, device):
        action = device.action
        logging.debug(' '.join(
            ['handling device event:',
             str(action), str(device)]))
        device_path = device.sys_path
        if not device_path.startswith('/sys/devices/'):
            return
        elif action == 'add':
            item = self.model().insert(device.sys_path)
            self.set_current_item(item)
        elif action == 'remove':
            current_device_path = self.get_current_device()
            parent_item = self.model().remove(device.sys_path)
            if current_device_path.startswith(device_path):
                self.set_current_index(parent_item.index())

    def reload(self):
        current_device_path = self.get_current_device()
        self.model().reload()
        if current_device_path is not None:
            self.set_current_device(current_device_path)

    def currentChanged(self, current, previous):
        QTreeView.currentChanged(self, current, previous)
        device_path = self.model().itemFromIndex(current).data()
        logging.debug('device selected: ' + device_path)
        device_props_tree_widget.clear()
        device_props_tree_widget.addTopLevelItems([
            item for item in iter_device_props_tree_items(
                device_path, devices_dict[device_path])
        ])
        device_props_tree_widget.expandAll()
        if self.history_push_flag:
            self.history_push(device_path)
        self.history_push_flag = True

    def get_current_device(self):
        current_index = self.currentIndex()
        if current_index is not None:
            current_item = self.model().itemFromIndex(current_index)
            if current_item is not None:
                return current_item.data()

    def set_current_index(self, index):
        self.setCurrentIndex(index)
        self.scrollTo(index)

    # scrollTo() doesn't expand everything (bug?), thus have to expand() every ancestor explicitly
    def set_current_item(self, item):
        parent = item.parent()
        while parent is not None:
            self.expand(parent.index())
            parent = parent.parent()
        index = item.index()
        self.set_current_index(index)

    def set_current_device(self, device_path):
        item = items_dict[device_path]
        self.set_current_item(item)

    def context_menu_handler(self, point):
        device_path = self.get_current_device()
        context_menu = QMenu()
        action_copy_path = context_menu.addAction('Copy path')
        device_listdir = os.listdir(device_path)
        if 'firmware_node' in device_listdir:
            action_to_firmware = context_menu.addAction('Go to firmware node')
        elif 'physical_node' in device_listdir:
            action_to_physical = context_menu.addAction('Go to physical node')
        # plugins which extend device actions menu must implement add_device_actions(device, menu, tuples) method
        #  it should add actions to the menu object
        #  and append (action, handler, handler_args, handler_kwargs) to the tuples list
        # tuples list is then used to check for chosen action and to call matching handler with args
        plugins_actions_tuples = []
        device = devices_dict[device_path]
        for plugin in [plugins.attach_to_vm]:
            if 'add_device_actions' in dir(plugin):
                plugin.add_device_actions(device, context_menu,
                                          plugins_actions_tuples)
        chosen_action = context_menu.exec_(self.mapToGlobal(point))
        if chosen_action == action_copy_path:
            clipboard.setText(device_path)
        elif 'firmware_node' in device_listdir and chosen_action is action_to_firmware:
            target_device_path = os.path.abspath(
                os.path.join(
                    device_path,
                    os.readlink(os.path.join(device_path, 'firmware_node'))))
            self.set_current_device(target_device_path)
        elif 'physical_node' in device_listdir and chosen_action is action_to_physical:
            target_device_path = os.path.abspath(
                os.path.join(
                    device_path,
                    os.readlink(os.path.join(device_path, 'physical_node'))))
            self.set_current_device(target_device_path)
        else:
            for action, handler, args, kwargs in plugins_actions_tuples:
                if chosen_action == action:
                    handler(device, *args, **kwargs)
                    break

    # QTreeView doesn't seem to have any navigation history logic, thus implement our own
    # Provides signal for external widgets like toolbar nav buttons to update state when history state changes
    history_list = []
    history_index = 0
    history_push_flag = True
    history_back_flag = False
    history_forward_flag = False
    history_signal = Signal(bool, bool)

    def history_push(self, device_path):
        self.history_list = self.history_list[self.history_index:self.
                                              history_index + 16]
        self.history_list.insert(0, device_path)
        self.history_index = 0
        self.history_forward_flag = False
        if len(self.history_list) > 1:
            self.history_back_flag = True
        self.history_signal.emit(self.history_back_flag,
                                 self.history_forward_flag)

    def history_back(self):
        # TODO: device can be already gone
        self.history_push_flag = False
        self.history_index += 1
        self.set_current_device(self.history_list[self.history_index])
        self.history_forward_flag = True
        if self.history_index == len(self.history_list) - 1:
            self.history_back_flag = False
        self.history_signal.emit(self.history_back_flag,
                                 self.history_forward_flag)

    def history_forward(self):
        self.history_push_flag = False
        self.history_index -= 1
        self.set_current_device(self.history_list[self.history_index])
        self.history_back_flag = True
        if self.history_index == 0:
            self.history_forward_flag = False
        self.history_signal.emit(self.history_back_flag,
                                 self.history_forward_flag)
Beispiel #5
0
@Slot()
def update_app_language():
    app.installTranslator(translator.translator)
    engine.retranslate()


if __name__ == '__main__':
    # os.environ['QT_QUICK_CONTROLS_CONF'] = 'resources/qtquickcontrols2.conf'

    app = QGuiApplication(sys.argv)
    app.instance().thread().setObjectName('MainThread')

    worker_manager = WorkerManager()
    worker_interface_thread = QThread()
    worker_interface_thread.setObjectName("WorkerInterfaceThread")
    worker_interface = WorkerInterface(start_signal=worker_manager.start,
                                       stop_signal=worker_manager.stop)
    worker_interface.msg_from_job.connect(worker_manager.receive_msg)
    worker_interface.moveToThread(worker_interface_thread)
    worker_interface_thread.start()

    viewer = Viewer()
    translator = Translator()
    translator.updateAppLanguage.connect(update_app_language)

    qml_file = os.path.abspath(
        os.path.join(os.path.dirname(__file__), 'main.qml'))

    engine = QQmlApplicationEngine()