Exemplo n.º 1
0
Arquivo: base.py Projeto: gpa14/enki
def _processPendingEvents():
    """Process pending application events."""

    # Create an event loop to run in. Otherwise, we need to use the
    # QApplication main loop, which may already be running and therefore
    # unusable.
    qe = QEventLoop()

    # Create a single-shot timer. Could use QTimer.singleShot(),
    # but can't cancel this / disconnect it.
    timer = QTimer()
    timer.setSingleShot(True)
    timer.timeout.connect(qe.quit)
    timer.start(1)

    # Wait for an emitted signal.
    qe.exec_()

    # Clean up: don't allow the timer to call qe.quit after this
    # function exits, which would produce "interesting" behavior.
    timer.stop()
    # Stopping the timer may not cancel timeout signals in the
    # event queue. Disconnect the signal to be sure that loop
    # will never receive a timeout after the function exits.
    timer.timeout.disconnect(qe.quit)
Exemplo n.º 2
0
Arquivo: gost.py Projeto: fheeger/gost
class QtWaitForSelection(QMessageBox):
    """Window to wait for the user to select an object"""
    def __init__(self, parent=None):
        super(QtWaitForSelection, self).__init__(QMessageBox.Question, "Warte auf Auswahl",
                                                 "Bitte wählen sie ein Object im 3d view  aus",
                                                 buttons=QMessageBox.Cancel,
                                                 parent=parent)
        self.move(0,0)
        #create a timer
        self.timer = QTimer(self)
        self.timer.setInterval(50)
        #connect the timer to checking is anything was selected
        self.timer.timeout.connect(self.pollSelection)
        self.timer.start()
        self.selected = None

    def pollSelection(self):
        """Check if anything was selected"""
        try:
            #get the selected object
            nowSelected = getSelectedObject()
        except ValueError:
            QMessageBox.critical(self, "Mehrer Objekt Ausgewählt", 
                                 "Es darf nicht mehr als ein Objekt ausgewählt sein.")
            for obj in bpy.data.objects:
                obj.select = False
        else:
            if not nowSelected is None:
                #stotre the selected object
                self.selected = nowSelected
                #stop the timer and close the window
                self.timer.stop()
                self.accept()
Exemplo n.º 3
0
class Main(APIS):

    sequence = 2    # 插件加载顺序(重要,顺序不同可能导致界面混乱)
    name = ProgressUi.__name__    # 模块名
    author = __Author__    # 作者
    version = __Version__    # 版本
    description = "自定义标题栏"    # 描述

    def __init__(self, parent = None):
        super(Main, self).__init__(parent)
        self.progressui = ProgressUi(self.parent)
        self.progressui.setVisible(False)    # 默认不可见
        self.setStyleSheet(self.progressui, self.name)

        # 测试加载进度
        self.i = 0
        self.progressui.setVisible(True)    # 测试改为可见
        self.timer = QTimer(timeout = self.onTimeout)
        self.timer.start(50)

    def onTimeout(self):
        self.i += 1
        self.progressui.setValue(self.i)
        if self.i > 100:
            self.timer.stop()
            self.progressui.setValue(0)
            self.progressui.setVisible(False)

    def run(self):
        self.parent.vLayout.insertWidget(self.parent.vLayout.count() - 1, self.progressui)

    def stop(self):
        self.timer.stop()
        self.progressui.close()
        self.parent.vLayout.removeWidget(self.progressui)
Exemplo n.º 4
0
class PWidget2D(QWidget):
    def __init__(self, parent):
        super(PWidget2D, self).__init__(parent)

        self.painting = Painting2D()
        self.elapsed = 0
        self.setFixedSize(800, 600)
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.animate)

    def animate(self):
        self.elapsed = (self.elapsed + self.sender().interval()) % 1000
        self.repaint()
        
    def setAnimating(self, animating):
        self.m_animating = animating
        
        if animating:
            self.timer.start(50)

    def paintEvent(self, event):
        painter = QPainter()
        painter.begin(self)
        painter.setRenderHint(QPainter.Antialiasing)
        self.painting.paint(painter, event, self.elapsed)
        painter.end()
Exemplo n.º 5
0
class GUI_Timer(QMainWindow):
    def __init__(self):
        super(QMainWindow, self).__init__()
        self.ui = Ui_ToF_Timer()
        self.ui.setupUi(self)
        self.timer = QTimer(self);
        self.timer.timeout.connect(self.update)
        self.timer.start(1000);
        
    def update(self):
        ok = False
        A = findWindow("Measurement Progress")
        if len(A)>0:
            B = findWindow(C="Edit", parent=A[0])
            if len(B)>0:
                AnalTime = int(getText(B[2]).replace(",",""))
                TotScans = int(getText(B[1]).replace(",",""))
                Scans = int(getText(B[0]).replace(",",""))
                self.ui.label_2.setText("Scans: {} / {}".format(Scans, TotScans));
                self.ui.label_3.setText("Analysis Time: {} s".format(AnalTime));
                self.ui.progressBar.setValue(Scans);
                self.ui.progressBar.setMaximum(TotScans);
                ok = True
        if not ok:
            self.ui.label.setText("Remaining time: Unavailable (measurement not in progress?)")
            return
        if Scans>0:
            r = AnalTime*(TotScans-Scans)/Scans;
            h = int(r//3600)
            m = int((r-h*3600)//60)
            s = int(r-h*3600-m*60)
            self.ui.label.setText("Remaining time: {:02d}:{:02d}:{:02d}".format(h,m,s));
        else:
            self.ui.label.setText("Remaining time: Unknown");
Exemplo n.º 6
0
    def wait(self, time_ms, callback, onredirect=None, onerror=None):
        """
        Wait for time_ms, then run callback.

        If onredirect is True then the timer is cancelled if redirect happens.
        If onredirect is callable then in case of redirect the timer is
        cancelled and this callable is called.

        If onerror is True then the timer is cancelled if a render error
        happens. If onerror is callable then in case of a render error the
        timer is cancelled and this callable is called.
        """
        timer = QTimer()
        timer.setSingleShot(True)
        timer_callback = functools.partial(self._on_wait_timeout,
            timer=timer,
            callback=callback,
        )
        timer.timeout.connect(timer_callback)

        self.logger.log("waiting %sms; timer %s" % (time_ms, id(timer)), min_level=2)

        timer.start(time_ms)
        self._active_timers.add(timer)
        if onredirect:
            self._timers_to_cancel_on_redirect[timer] = onredirect
        if onerror:
            self._timers_to_cancel_on_error[timer] = onerror
Exemplo n.º 7
0
class NPGPull(ZMQPull):

    def __init__(self, host, port, imgModel, table, opts, flags):
        ZMQPull.__init__(self, host, port, opts=[], flags=flags)
        self.socketTimer = QTimer()
        self.socketTimer.timeout.connect(self.receive)
        self.imgModel = imgModel
        self.table = table

    def start(self):
        self.connect()
        self.socketTimer.start(100)

    def stop(self):
        self.close()
        self.socketTimer.stop()

    def receive(self):

        try:
            data = self.puller.recv_json(flags=zmq.NOBLOCK)
            fn = str(data['fn'].strip())
            path = str(data['path'])
            index = int(data['index'])
            total = int(data['total'])
            N = int(data['processed'])
            hit = int(data['hit'])
            self.imgModel.updateData(fn, path, int(index))
            self.table.progress((total, N, hit))
            return
        except zmq.error.Again:
            return
Exemplo n.º 8
0
class _GlobalUpdateWordSetTimer:
    """Timer updates word set, when editor is idle. (5 sec. after last change)
    Timer is global, for avoid situation, when all instances
    update set simultaneously
    """
    _IDLE_TIMEOUT_MS = 1000

    def __init__(self):
        self._timer = QTimer()
        self._timer.setSingleShot(True)
        self._timer.timeout.connect(self._onTimer)
        self._scheduledMethods = []

    def schedule(self, method):
        if not method in self._scheduledMethods:
            self._scheduledMethods.append(method)
        self._timer.start(self._IDLE_TIMEOUT_MS)

    def cancel(self, method):
        """Cancel scheduled method
        Safe method, may be called with not-scheduled method"""
        if method in self._scheduledMethods:
            self._scheduledMethods.remove(method)

        if not self._scheduledMethods:
            self._timer.stop()

    def _onTimer(self):
        method = self._scheduledMethods.pop()
        method()
        if self._scheduledMethods:
            self._timer.start(self._IDLE_TIMEOUT_MS)
Exemplo n.º 9
0
class SC_QtGUIModule(sc_module.SCModule):
    def __init__(self, sc_state):
        super(SC_QtGUIModule, self).__init__(sc_state, "qt_gui", "qt_gui module")
        self.__app = QApplication([])
        
        self.mapWidget = MapWidget()
        self.mapWidget.show()

        self.__dashboardDialog = DashboardDialog(self.sc_state)
        self.__dashboardDialog.show()

        #periodic updates...
        self.__updater = QTimer()
        self.__updater.setInterval(500)
        self.__updater.timeout.connect(self.time_to_update)
        self.__updater.start();

        #more frequent updates...
        self.__updaterFrequent = QTimer()
        self.__updaterFrequent.setInterval(40)
        self.__updaterFrequent.timeout.connect(self.time_to_update_frequent)
        self.__updaterFrequent.start();

        #zoom to default location:
        self.mapWidget.zoomTo(16, 35.716888, -120.7646408)

        #slots
        self.mapWidget.getView().just_selected_uav.connect(self.on_uav_select)

    def start_app(self):
        sys.exit(self.__app.exec_())

    def time_to_update_frequent(self):
        #update dashboard and map:
        self.__dashboardDialog.update_uav_states()

        #update icons on map
        for id, uav_state in self.sc_state.swarm_state.uav_states.items():
            self.mapWidget.updateIcon(id, uav_state)

    def time_to_update(self):
        #check for new textures for the map:
        self.mapWidget.checkForNewTextures()

    def unload(self):
        #THIS NEEDS TO WORK (IT DOES CURRENTLY)
        #The closeEvent handler of the dialog is what saves config:
        self.__dashboardDialog.close()
        
        #Doesn't work -- dunno why:
        #self.__mapWidget.close()

        #do any cleanup here
        self.mapWidget.done(0)
        self.__dashboardDialog.done(0)
        
        QApplication.quit()

    def on_uav_select(self, id):
        self.__dashboardDialog.selectUAV(id)
Exemplo n.º 10
0
Arquivo: qt.py Projeto: hibtc/madgui
class Queued:

    """
    A queued trigger. Calling the trigger will invoke the handler function
    in another mainloop iteration.

    Calling the trigger multiple times before the handler was invoked (e.g.
    within the same mainloop iteration) will result in only a *single* handler
    invocation!

    This can only be used with at least a ``QCoreApplication`` instanciated.
    """

    def __init__(self, func):
        self.timer = QTimer()
        self.timer.setSingleShot(True)
        self.timer.timeout.connect(func)

    def __call__(self):
        """Schedule the handler invocation for another mainloop iteration."""
        self.timer.start()

    @classmethod
    def method(cls, func):
        """Decorator for a queued method, i.e. a method that when called,
        actually runs at a later time."""
        return property(memoize(functools.wraps(func)(
            lambda self: cls(func.__get__(self)))))
Exemplo n.º 11
0
class MemoryInfo(QObject):
    def __init__(self, parent=None):
        super(MemoryInfo, self).__init__(parent)

        self.__usage = 0
        self.load_usage()
        self.__timer = QTimer(self)
        self.__timer.setInterval(1000)
        self.__timer.setSingleShot(False)
        self.__timer.timeout.connect(self.load_usage)
        self.__timer.start()

    def load_usage(self):
        with open("/proc/self/status") as f:
            data = f.read()
        index = data.index("VmRSS:")
        split = data[index:].split(None, 3)
        self.__usage = int(split[1])
        self.usage_changed.emit()

    usage_changed = pyqtSignal(name="usageChanged")

    @pyqtProperty(int, notify=usage_changed)
    def usage(self):
        return self.__usage

    @usage.setter
    def usage(self, usage):
        if self.__usage != usage:
            self.__usage = usage
            self.usage_changed.emit()
Exemplo n.º 12
0
Arquivo: pysb.py Projeto: klasbj/pysb
def main():
    app = QApplication(sys.argv)

    io = InputHandler()

    # Set up signal handler to manage Ctrl+c
    signal.signal(signal.SIGINT, lambda *_: QApplication.quit())
    global timer
    timer = QTimer()
    timer.start(500)
    timer.timeout.connect(lambda: None) # let python run every 500ms

    desktop = app.desktop()
    sgeom = desktop.screenGeometry()

    global bars
    bars.append(dict())
    bars[0][Dock.top] = Bar(sgeom.left(), sgeom.top(), sgeom.width(), BAR_HEIGHT, flags=Qt.Widget | Qt.BypassWindowManagerHint)
    bars[0][Dock.bottom] = Bar(sgeom.left(), sgeom.bottom()-BAR_HEIGHT+1, sgeom.width(), BAR_HEIGHT, flags=Qt.Widget | Qt.BypassWindowManagerHint)

    print(bars, file=sys.stderr)

    for bar in bars[0].values():
        bar.show()
        #bar.lower()

    io.line.connect(handle_input)

    sys.exit(app.exec_())
Exemplo n.º 13
0
    def test_simulator_graphics_view(self):
        self.__setup_project()
        self.add_all_signals_to_simulator()
        stc = self.form.simulator_tab_controller  # type: SimulatorTabController
        self.assertGreater(len(stc.simulator_config.get_all_items()), 0)

        self.assertEqual(len(stc.simulator_scene.selectedItems()), 0)

        # select first message
        messages = stc.simulator_scene.get_all_message_items()
        pos = stc.ui.gvSimulator.mapFromScene(messages[0].scenePos())

        QTest.mouseClick(stc.ui.gvSimulator.viewport(), Qt.LeftButton, Qt.NoModifier, pos)

        self.assertEqual(len(stc.simulator_scene.selectedItems()), 1)
        self.assertIsInstance(stc.simulator_scene.selectedItems()[0], MessageItem)

        rules = [item for item in stc.simulator_scene.items() if isinstance(item, RuleItem)]
        self.assertEqual(len(rules), 0)
        self.menus_to_ignore = [w for w in QApplication.topLevelWidgets() if isinstance(w, QMenu)]
        timer = QTimer(self.form)
        timer.setInterval(1)
        timer.setSingleShot(True)
        timer.timeout.connect(self.__on_context_menu_simulator_graphics_view_timer_timeout)
        timer.start()

        stc.ui.gvSimulator.contextMenuEvent(QContextMenuEvent(QContextMenuEvent.Mouse, pos))

        rules = [item for item in stc.simulator_scene.items() if isinstance(item, RuleItem)]
        self.assertEqual(len(rules), 1)
Exemplo n.º 14
0
    def __init__(self):
        super(Window, self).__init__()

        aliasedLabel = self.createLabel("Aliased")
        antialiasedLabel = self.createLabel("Antialiased")
        intLabel = self.createLabel("Int")
        floatLabel = self.createLabel("Float")

        layout = QGridLayout()
        layout.addWidget(aliasedLabel, 0, 1)
        layout.addWidget(antialiasedLabel, 0, 2)
        layout.addWidget(intLabel, 1, 0)
        layout.addWidget(floatLabel, 2, 0)

        timer = QTimer(self)

        for i in range(2):
            for j in range(2):
                w = CircleWidget()
                w.setAntialiased(j != 0)
                w.setFloatBased(i != 0)

                timer.timeout.connect(w.nextAnimationFrame)

                layout.addWidget(w, i + 1, j + 1)

        timer.start(100)
        self.setLayout(layout)

        self.setWindowTitle("Concentric Circles")
Exemplo n.º 15
0
    def initUI(self):
        self.setGeometry(300, 100, 400, 200)

        self.clock = QtWidgets.QLCDNumber(self)
        self.clock.setDigitCount(8)

        self.setWindowIcon(QtGui.QIcon('clock-icon.png'))

        tray_icon = SystemTrayIcon(QtGui.QIcon('clock-icon.png'), self)
        tray_icon.show()

        self.progress_bar = QtWidgets.QProgressBar(self)

        timer = QTimer(self)
        timer.timeout.connect(self.update_time)
        timer.setInterval(100)
        timer.start()

        self.btn = QtWidgets.QPushButton("Copy")
        self.btn.clicked.connect(self.copy_files)

        self.status_bar = QtWidgets.QStatusBar(self)

        grid = QtWidgets.QGridLayout()
        grid.addWidget(self.clock, 0, 0)
        grid.addWidget(self.progress_bar, 1, 0)
        grid.addWidget(self.btn, 2, 0)

        self.setLayout(grid)
        self.show()
Exemplo n.º 16
0
def _process_entry_point(channel, iface_name):
    logger.info('Bus monitor process started with PID %r', os.getpid())
    app = QApplication(sys.argv)    # Inheriting args from the parent process

    def exit_if_should():
        if RUNNING_ON_WINDOWS:
            return False
        else:
            return os.getppid() != PARENT_PID       # Parent is dead

    exit_check_timer = QTimer()
    exit_check_timer.setSingleShot(False)
    exit_check_timer.timeout.connect(exit_if_should)
    exit_check_timer.start(2000)

    def get_frame():
        received, obj = channel.receive_nonblocking()
        if received:
            if obj == IPC_COMMAND_STOP:
                logger.info('Bus monitor process has received a stop request, goodbye')
                app.exit(0)
            else:
                return obj

    win = BusMonitorWindow(get_frame, iface_name)
    win.show()

    logger.info('Bus monitor process %r initialized successfully, now starting the event loop', os.getpid())
    sys.exit(app.exec_())
Exemplo n.º 17
0
    def start(self):
        timer           = QTimer(self)
        timer.timeout.connect(self.receiveFromNodes)
        timer.start(20)

        # Start the first simulation node on start
        self.addNode()
Exemplo n.º 18
0
    def test_save_remove_decoding(self):
        def set_save_name():
            timer.stop()
            input_dialog = next(w for w in qApp.topLevelWidgets() if isinstance(w, QInputDialog))
            input_dialog.setTextValue("Test decoding")
            input_dialog.accept()

        def accept_delete():
            timer.stop()
            message_box = next(w for w in qApp.topLevelWidgets() if isinstance(w, QMessageBox))
            message_box.button(QMessageBox.Yes).click()

        self.dialog.ui.decoderchain.addItem(constants.DECODING_CUT)
        self.dialog.decoderchainUpdate()

        self.assertEqual(self.dialog.ui.decoderchain.count(), 1)

        timer = QTimer(self.dialog)
        timer.setSingleShot(True)
        timer.timeout.connect(set_save_name)
        timer.start(10)
        self.dialog.ui.saveas.click()

        self.assertEqual(self.dialog.ui.combobox_decodings.currentText(), "Test decoding")

        timer.timeout.disconnect(set_save_name)
        timer.timeout.connect(accept_delete)
        timer.start(10)

        self.dialog.ui.delete_decoding.click()

        self.assertNotEqual(self.dialog.ui.combobox_decodings.currentText(), "Test decoding")
Exemplo n.º 19
0
def askPasswordDialog(parent, title, prompt, timeout = None):
    if parent is None:
        app = qttools.createQApplication()
        translator = qttools.translator()
        app.installTranslator(translator)

    import icon
    dialog = QInputDialog()

    timer = QTimer()
    if not timeout is None:
        timer.timeout.connect(dialog.reject)
        timer.setInterval(timeout * 1000)
        timer.start()

    dialog.setWindowIcon(icon.BIT_LOGO)
    dialog.setWindowTitle(title)
    dialog.setLabelText(prompt)
    dialog.setTextEchoMode(QLineEdit.Password)
    QApplication.processEvents()

    ret = dialog.exec_()

    timer.stop()
    if ret:
        password = dialog.textValue()
    else:
        password = ''
    del(dialog)

    return(password)
Exemplo n.º 20
0
class GameSceneInterface(QWidget):
    def __init__(self, scene, parent=None):
        super().__init__(parent)
        self.scene = scene
        self.scene.window = self
        self.resize(INTERFACE_WIDTH, INTERFACE_HEIGHT)
        self.view = graphics.GameView(self.scene, self)
        self.record_view = RecordArea(self)
        scene.set_text_out(self.record_view.text_out)
        self.property_view = PropertyArea(self.scene.player.status, self)
        self.paint_timer = QTimer()
        self.paint_timer.timeout.connect(self.update)
        self.paint_timer.start(1000 // FPS)

    def resizeEvent(self, event):
        self.view.resize(SCENE_WIDTH, SCENE_HEIGHT)
        self.view.move((self.size().width() - SCENE_WIDTH) // 2, self.size().height() - SCENE_HEIGHT)
        self.property_view.resize((self.size().width() - SCENE_WIDTH) // 2,
                                  (self.size().width() - SCENE_WIDTH) // 10 + TEXT_HEIGHT)
        self.property_view.move(0, self.size().height() - SCENE_HEIGHT)
        self.record_view.resize((self.size().width() - SCENE_WIDTH) // 2, self.size().height() / 2)
        self.record_view.move(0, self.size().height() / 2)

    def update(self):
        if self.scene.game_update_end_flag and self.scene.update_end_flag:
            self.view.update()
            self.property_view.update()
Exemplo n.º 21
0
class GenericTerminalOutputBox(QtWidgets.QLineEdit):
    def __init__(self) -> None:
        super().__init__()
        self.animate = False
        self.timer = QTimer(self)
        self.timer.setInterval(5)
        self.timer.timeout.connect(self._add_character)
        self.buffer = ''

    def set_timer_interval(self, num: int) -> None:
        self.timer.setInterval(num)

    def _add_character(self) -> None:
        if not self.buffer:
            self.timer.stop()
            return
        super().setText(self.text() + self.buffer[0])
        self.buffer = self.buffer[1:]

    def setText(self, text: str) -> None:
        if not self.animate or not text:
            super().setText(text)
            return
        super().setText(text[0])
        if len(text) > 1:
            self.buffer = text[1:]
            self.timer.start()
Exemplo n.º 22
0
class ConnectionHandler(QObject):

    value_changed = pyqtSignal(bool)

    def __init__(self, frequency_check, time_before_time_out, parent=None):
        super(ConnectionHandler, self).__init__(parent)
        self.frequency_check = frequency_check
        self.time_before_time_out = time_before_time_out
        self.internet_ok = None
        self.timer = QTimer(self)

    def start(self):
        self.timer.setInterval(self.frequency_check)
        self.timer.timeout.connect(self.update)
        self.timer.start()

    def stop(self):
        self.timer.stop()

    def emit_if_changed(self, new_value):
        if not self.internet_ok is new_value:
            self.internet_ok = new_value
            self.value_changed.emit(new_value)

    def check_internet_call(self):
        urllib2.urlopen('http://www.demerio.com', timeout=self.time_before_time_out)

    @pyqtSlot()
    def update(self):
        try:
            self.check_internet_call()
        except Exception as e:
            self.emit_if_changed(False)
        else:
            self.emit_if_changed(True)
Exemplo n.º 23
0
def main():
    app = QApplication(sys.argv)
    QCoreApplication.setOrganizationName('Hardcoded Software')
    QCoreApplication.setApplicationName(__appname__)
    QCoreApplication.setApplicationVersion(__version__)
    setupQtLogging()
    settings = QSettings()
    lang = settings.value('Language')
    locale_folder = op.join(BASE_PATH, 'locale')
    install_gettext_trans_under_qt(locale_folder, lang)
    # Handle OS signals
    setUpSignals()
    # Let the Python interpreter runs every 500ms to handle signals.  This is
    # required because Python cannot handle signals while the Qt event loop is
    # running.
    from PyQt5.QtCore import QTimer
    timer = QTimer()
    timer.start(500)
    timer.timeout.connect(lambda: None)
    # Many strings are translated at import time, so this is why we only import after the translator
    # has been installed
    from qt.app import DupeGuru
    app.setWindowIcon(QIcon(QPixmap(":/{0}".format(DupeGuru.LOGO_NAME))))
    global dgapp
    dgapp = DupeGuru()
    install_excepthook('https://github.com/hsoft/dupeguru/issues')
    result = app.exec()
    # I was getting weird crashes when quitting under Windows, and manually deleting main app
    # references with gc.collect() in between seems to fix the problem.
    del dgapp
    gc.collect()
    del app
    gc.collect()
    return result
Exemplo n.º 24
0
class Runner(object):
    """Useful class for running jobs with a delay"""

    def __init__(self, delay=2000):
        self._timer = QTimer()
        self._timer.setSingleShot(True)
        self._timer.timeout.connect(self._execute_job)
        self._delay = delay

        self._job = None
        self._args = []
        self._kw = {}

    def cancel(self):
        """Cancel the current job"""
        self._timer.stop()
        self._job = None
        self._args = []
        self._kw = {}

    def run(self, job, *args, **kw):
        """Request a job run. If there is a job, cancel and run the new job
        with a delay specified in __init__"""
        self.cancel()
        self._job = job
        self._args = args
        self._kw = kw
        self._timer.start(self._delay)

    def _execute_job(self):
        """Execute job after the timer has timeout"""
        self._timer.stop()
        self._job(*self._args, **self._kw)
Exemplo n.º 25
0
def run_gui_tests(tstcls, gui_test_bag):
    assert tstcls.app is None, "Should only encounter every class once. Check Sorting"
    tst_queue = queue.Queue()
    app = tstcls.app = QApplication([])
    app.setQuitOnLastWindowClosed(False)
    ThreadRouter.app_is_shutting_down = False
    app.thread_router = ThreadRouter(app)
    tstcls.shell = launchShell(None, [], [])

    platform_str = platform.platform().lower()
    if 'ubuntu' in platform_str or 'fedora' in platform_str:
        QApplication.setAttribute(Qt.AA_X11InitThreads, True)

    if ilastik.config.cfg.getboolean("ilastik", "debug"):
        QApplication.setAttribute(Qt.AA_DontUseNativeMenuBar, True)

    # Note on the class test execution lifecycle
    # pytest infers that finalizer teardown_class should be called when
    # nextitem is None
    for item, nextitem in pairwise(gui_test_bag, tail=None):
        tst_queue.put((item, nextitem))

    # Spawn a suite runner as a interval task
    suite = GuiTestSuite(tst_queue, tstcls.shell)
    timer = QTimer()
    # This timer will fire only after application is started running
    timer.timeout.connect(suite.poll)
    timer.start(100)  # Every 100 ms

    app.exec_()
    timer.stop()

    tst_queue.join()
Exemplo n.º 26
0
    def highlight(self, format, cursors, priority=0, msec=0):
        """Highlights the selection of an arbitrary list of QTextCursors.

        format can be a name for a predefined text format or a QTextCharFormat;
        in the first case the textFormat() method should return a qtextformat to use.
        priority determines the order of drawing, highlighting with higher priority
        is drawn over highlighting with lower priority.
        msec, if > 0, removes the highlighting after that many milliseconds.

        """
        if isinstance(format, QTextFormat):
            fmt = format
            key = id(format)
            self._formats[key] = format
        else:
            fmt = self.textFormat(format)
            key = format
        selections = []
        for cursor in cursors:
            es = QTextEdit.ExtraSelection()
            es.cursor = cursor
            es.format = fmt
            selections.append(es)
        if msec:
            def clear(selfref=weakref.ref(self)):
                self = selfref()
                if self:
                    self.clear(format)
            timer = QTimer(timeout=clear, singleShot=True)
            timer.start(msec)
            self._selections[key] = (priority, selections, timer)
        else:
            self._selections[key] = (priority, selections)
        self.update()
Exemplo n.º 27
0
 def register_timer(self, time_delta, callback):
     """Registers a callback function to be run after time_delta ms."""
     timer = QTimer(self.window)
     timer.setSingleShot(True)
     timer.timeout.connect(callback)
     timer.setInterval(time_delta)
     timer.start()
class DeviceReader(QThread):
    """Used for polling data from the Input layer during configuration"""
    raw_axis_data_signal = pyqtSignal(object)
    raw_button_data_signal = pyqtSignal(object)
    mapped_values_signal = pyqtSignal(object)

    def __init__(self, input):
        QThread.__init__(self)

        self._input = input
        self._read_timer = QTimer()
        self._read_timer.setInterval(25)

        self._read_timer.timeout.connect(self._read_input)

    def stop_reading(self):
        """Stop polling data"""
        self._read_timer.stop()

    def start_reading(self):
        """Start polling data"""
        self._read_timer.start()

    def _read_input(self):
        [rawaxis, rawbuttons, mapped_values] = self._input.read_raw_values()
        self.raw_axis_data_signal.emit(rawaxis)
        self.raw_button_data_signal.emit(rawbuttons)
        self.mapped_values_signal.emit(mapped_values)
Exemplo n.º 29
0
class _StatusBar(QStatusBar):
    """Extended status bar. Supports HTML messages
    """

    def __init__(self, *args):
        QStatusBar.__init__(self, *args)
        self.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Expanding)
        self.setSizeGripEnabled(False)
        self.setStyleSheet("QStatusBar {border: 0} QStatusBar::item {border: 0}")
        self._label = QLabel(self)
        self._label.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
        self._label.setStyleSheet("color: red")
        self.addWidget(self._label)
        self._timer = QTimer()
        self._timer.setSingleShot(True)
        self._timer.timeout.connect(self.clearMessage)

    def term(self):
        self._timer.stop()

    def showMessage(self, text, timeout=0):
        """QStatusBar.showMessage()
        """
        self._label.setText(text)
        self._timer.stop()
        if timeout > 0:
            self._timer.start(timeout)

    def clearMessage(self):
        """QStatusBar.clearMessage()
        """
        self._label.clear()

    def currentMessage(self):
        return self._label.text()
Exemplo n.º 30
0
Arquivo: t.py Projeto: intijk/MicRobot
class Example(QMainWindow):
    def __init__(self):
        super(Example, self).__init__()
        self.initUI()
        self.initRobot()
        self.initTimer()
        self.label.show()

    def initUI(self):
        self.imgAvailable = QImage("./image/robot_available.png")
        self.imgDisable = QImage("./image/robot_disable.png")
        self.label = QLabel()
        self.label.setPixmap(QPixmap.fromImage(self.imgDisable))

    def initRobot(self):
        self.R = MicRobot()
        self.R.serReady.connect(self.robotReady)
        self.R.serFail.connect(self.robotFail)

    def robotReady(self):
        self.label.setPixmap(QPixmap.fromImage(self.imgAvailable))

    def robotFail(self):
        print "robotFail"
        self.label.setPixmap(QPixmap.fromImage(self.imgDisable))

    def initTimer(self):
        self.timer = QTimer()
        self.timer.timeout.connect(self.R.checkAvailable)
        self.timer.start(1000)
Exemplo n.º 31
0
class Check_In_Window(QMainWindow):
    def __init__(self):
        super(Check_In_Window, self).__init__()
        loadUi("/home/bit/PycharmProjects/GrabNGOCheckIn&Out/Check_In_Window.ui", self)
        # self.detector = MTCNN()
        self.mtcnn = MTCNN(select_largest=True, device='cuda')
        # some constants kept as default from facenet
        minsize = 20
        threshold = [0.6, 0.7, 0.7]
        factor = 0.709
        margin = 44
        self.input_image_size = 160

        self.sess = tf.compat.v1.Session(config=tf.compat.v1.ConfigProto(log_device_placement=True))
        pre_trained_facenet.load_model('/home/bit/PycharmProjects/GrabNGOCheckIn&Out/model/20170512-110547.pb')
        self.images_placeholder = tf.get_default_graph().get_tensor_by_name("input:0")
        self.embeddings = tf.get_default_graph().get_tensor_by_name("embeddings:0")
        self.phase_train_placeholder = tf.get_default_graph().get_tensor_by_name("phase_train:0")
        self.embedding_size = self.embeddings.get_shape()[1]
        self.startVideo('0')

    def startVideo(self, camera_name):
        """
        :param camera_name: link of camera or usb camera
        :return:
        """
        if len(camera_name) == 1:
        	self.capture = cv2.VideoCapture(int(camera_name))
        else:
        	self.capture = cv2.VideoCapture(camera_name)
        self.timer = QTimer(self)  # Create Timer
        # path = './Face_Recognition/images'
        path = '/home/ftpuser/ftp/files/'
        if not os.path.exists(path):
            os.mkdir(path)
        # known face encoding and known face name list
        self.images = []
        self.class_names = []
        self.boxes = []

        attendance_list = os.listdir(path)
        for cl in attendance_list:
            cur_img = cv2.imread(f'{path}/{cl}')
            print(cur_img)
            self.images.append(cur_img)
            # print('image',cur_img)
            # cur_img = cv2.resize(cur_img, (504,378))
            faces_detected = 0
            start = time.time()
            # result = self.detector.detect_faces(cur_img)
            box = self.mtcnn.detect(cur_img,True)
            faces_detected += len(box)
            print(box)
            print(
                f'Frames per second: {(time.time() - start):.3f},',
                f'faces detected: {faces_detected}\r'
            )
            self.boxes.append(box)
            self.class_names.append(os.path.splitext(cl)[0])

        self.timer.timeout.connect(self.update_frame)  # Connect timeout to the output function
        self.timer.start(10)  # emit the timeout() signal at x=10ms

    def face_rec_(self, frame):
        """
        :param frame: frame from camera
        :param encode_list_known: known face encoding
        :param class_names: known face names
        :return:
        """
        box = self.mtcnn.detect(frame,True)
        # print(box)
        # print(box[0])
        # print('길이',len(box[0]))
        if box[0] is None:
            print('없')
        else:
            print('heeeeeeeeeeeeeeeeeeeeeeee')
            print(box)
            print(len(self.images),len(self.boxes),len(self.class_names))
            for i, b, c in zip(self.images,self.boxes,self.class_names):
                print('for loop')
                print(b)
                distance = self.compare2face(i, frame, b, box)
                print('여기까진?')
                threshold = 0.7  # set yourself to meet your requirement
                print("distance = " + str(distance),' 사진번호: ', c)
                name = 'unknonw'
                if (distance <= threshold):
                    name = c
                    print(name)
                    print("distance = " + str(distance), ' 인덱: ', c)
                self.mark_attendance(name)
        return frame

    def mark_attendance(self, name):
        """
        :param name: detected face known or unknown one
        :return:
        """

        if name != 'unknonw':
            print(name)
            self.logIn(name)

    def logIn(self, name):
        customer_id = int(name)
        DB = DB_Connection()
        cnt = DB.select_user(customer_id)

        if cnt[0] == "False":
            greeting = cnt[1] + '님이 입장하셨습니다.'
            print(name, '님이 입장하셨습니다.')
            DB.update_login_session_T(customer_id)

            self.GreetingLabel.setText(greeting)

    def update_frame(self):
        ret, image = self.capture.read()
        # print(image)
        self.displayImage(image)

    def displayImage(self, image, window=1):
        """
        :param image: frame from camera
        :param encode_list: known face encoding list
        :param class_names: known face names
        :param window: number of window
        :return:
        """
        # print(image.shape)
        try:
            image = self.face_rec_(image)
        except Exception as e:
            print('뭐지?',e)
        # image = cv2.resize(image, (640, 480))
        qformat = QImage.Format_Indexed8
        if len(image.shape) == 3:
            if image.shape[2] == 4:
                qformat = QImage.Format_RGBA8888
            else:
                qformat = QImage.Format_RGB888
        outImage = QImage(image, image.shape[1], image.shape[0], image.strides[0], qformat)
        outImage = outImage.rgbSwapped()

        if window == 1:
            self.imgLabel.setPixmap(QPixmap.fromImage(outImage))
            self.imgLabel.setScaledContents(True)

    def getFace(self, img, box):
        faces = []
        # print(box)
        box = box[0][0]
        # print(box)
        box = np.int32(box)
        # Result is an array with all the bounding boxes detected. We know that for 'ivan.jpg' there is only one.
        # bounding_box = result
        # keypoints = result[0]['keypoints']
        cv2.rectangle(img,
                      (box[0], box[1]), (box[2], box[3]),
                      (0, 155, 255),
                      2)
        # cv2.circle(img, (keypoints['left_eye']), 2, (0, 155, 255), 2)
        # cv2.circle(img, (keypoints['right_eye']), 2, (0, 155, 255), 2)
        # cv2.circle(img, (keypoints['nose']), 2, (0, 155, 255), 2)
        # cv2.circle(img, (keypoints['mouth_left']), 2, (0, 155, 255), 2)
        # cv2.circle(img, (keypoints['mouth_right']), 2, (0, 155, 255), 2)
        # cv2.imwrite("/home/bit/PycharmProjects/GrabNGOCheckIn&Out/Webcam-based-Face-Recognition-using-Deep-Learning-/Face_Recognition/check/dd_drawn.jpg", img)
        cropped = img[box[1]:box[3],
                  box[0]:box[2]]
        # cv2.imwrite("/home/bit/PycharmProjects/GrabNGOCheckIn&Out/Webcam-based-Face-Recognition-using-Deep-Learning-/Face_Recognition/check/dd_cropped.jpg", cropped)
        rearranged = cv2.resize(cropped, (self.input_image_size, self.input_image_size), interpolation=cv2.INTER_CUBIC)
        # cv2.imwrite("/home/bit/PycharmProjects/GrabNGOCheckIn&Out/Webcam-based-Face-Recognition-using-Deep-Learning-/Face_Recognition/check/dd_resized.jpg", rearranged)
        prewhitened = pre_trained_facenet.prewhiten(rearranged)
        faces.append({'face': rearranged, 'embedding': self.getEmbedding(prewhitened)})
        return faces

    def getEmbedding(self, resized):
        reshaped = resized.reshape(-1, self.input_image_size, self.input_image_size, 3)
        feed_dict = {self.images_placeholder: reshaped, self.phase_train_placeholder: False}
        embedding = self.sess.run(self.embeddings, feed_dict=feed_dict)
        return embedding

    def compare2face(self, img1, img2, box1,  box2):
        face1 = self.getFace(img1,box1)
        print('여기')
        face2 = self.getFace(img2,box2)
        # cv2.imwrite('image1.jpg', img2)
        print('여기2')
        if face1 and face2:
            # print('face1',face1)
            # print('face2',face2)
            # print(len(face1[2]))
            # print(len(face2[0]))
            # calculate Euclidean distance
            dist = np.sqrt(np.sum(np.square(np.subtract(face1[0]['embedding'], face2[0]['embedding']))))
            return dist
        return -1
 def delayExecuting(self, func, delayInSec):
     timer = QTimer(self)
     timer.setInterval(delayInSec)
     timer.setSingleShot(True)
     timer.timeout.connect(func)
     timer.start()
Exemplo n.º 33
0
class ControlWindow(QMainWindow):
    def __init__(self, parent):
        super().__init__(parent)

        self.title = "tring"
        self.openCamera = False
        self.caper = None

        self.samplerAction = QAction("sampler", self)
        self.trainAction = QAction("train", self)
        self.saveAction = QAction("save", self)
        self.loadAction = QAction("load", self)
        self.selectImageAction = QAction("selectIamge", self)
        self.cameraAction = QAction("openCamera", self)

        self.imageLabel = ShowLabel(None)
        self.timer = QTimer(self)

        self.initUI()
        self.initAction()

    def initUI(self):
        widget = QWidget(None)
        layout = QHBoxLayout(None)
        layout.addWidget(self.imageLabel, 1, Qt.AlignCenter)
        widget.setLayout(layout)

        self.setCentralWidget(widget)

        menubar = self.menuBar()

        moduleMenu = menubar.addMenu("module")
        moduleMenu.addAction(self.samplerAction)
        moduleMenu.addAction(self.trainAction)
        moduleMenu.addAction(self.saveAction)
        moduleMenu.addAction(self.loadAction)

        imageMenu = menubar.addMenu("image")
        imageMenu.addAction(self.selectImageAction)
        imageMenu.addAction(self.cameraAction)

        self.resize(300, 300)

    def initAction(self):
        self.samplerAction.triggered.connect(self.onSampler)
        self.trainAction.triggered.connect(self.onTrain)
        self.saveAction.triggered.connect(self.onSave)
        self.loadAction.triggered.connect(self.onLoad)

        self.selectImageAction.triggered.connect(self.onSelectImage)
        self.cameraAction.triggered.connect(self.onCamera)

        self.timer.timeout.connect(self.onTimer)
        self.timer.start(100)

    def onSampler(self):
        path = QFileDialog.getExistingDirectory(self, "select sample dir")
        if len(path) <= 0: return

        sampler.initSampler(path)

    def onTrain(self):
        classfier.startTrain()

    def onSave(self):
        path = QFileDialog.getSaveFileName(self, "save path")[0]
        if len(path) == 0: return
        print(path)
        classfier.setSavePath(path)

    def onLoad(self):
        path = QFileDialog.getOpenFileName(self, "select")[0]
        if len(path) == 0: return
        path = os.path.splitext(path)[0]
        print(path)
        classfier.loadModule(path)

    def passImage(self, image):
        retRect = recognizer.getFaceRegion(image)
        self.imageLabel.setRect(retRect)

        cv2.imwrite("temp.png", image)
        pixmap = QPixmap.fromImage(QImage("temp.png"))
        #pixmap=QPixmap.fromImage(image)
        self.imageLabel.setPixmap(pixmap)

        self.imageLabel.update()

    def onSelectImage(self):
        if self.openCamera == True: return

        path = QFileDialog.getOpenFileName(self, "select")[0]
        if len(path) == 0: return

        image = cv2.imread(path)
        self.passImage(image)

    def onCamera(self):
        if self.openCamera == False:
            try:
                self.caper = cv2.VideoCapture(0)
            except Exception as e:
                print(str(e))
                return
            self.openCamera = True
        else:
            try:
                self.caper.release()
                self.caper = None
            except Exception as e:
                print(str(e))
                return
            self.openCamera = False

    def onTimer(self):
        if len(classfier.message) == 0:
            self.setWindowTitle(self.title)
        else:
            self.setWindowTitle(classfier.message)

        if self.openCamera == True:
            ret, image = self.caper.read()
            self.passImage(image)
class TurtleUIClass(QWidget):
    def __init__(self):  # Konstrukor
        # Konstruktor der Elternklasse aufrufen
        super(TurtleUIClass, self).__init__()
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.update)
        self.initUI()

    def initUI(self):
        # Instanziierung der Widgets
        startWert = 0
        lcd = QLCDNumber(self)
        lcd.display(startWert)
        lcdY = QLCDNumber(self)
        lcdY.display(startWert)

        self.sld = QSlider(Qt.Horizontal, self)
        self.sld.setMaximum(6)
        self.sld.setMinimum(-6)
        self.sld.setValue(startWert)
        self.sldY = QSlider(Qt.Horizontal, self)
        self.sldY.setMaximum(6)
        self.sldY.setMinimum(-6)
        self.sldY.setValue(startWert)

        pbLess = QPushButton('<')
        pbMore = QPushButton('>')
        pbLessY = QPushButton('<')
        pbMoreY = QPushButton('>')
        pbGo = QPushButton(' Go Turtle ')
        pbStop = QPushButton(' STOPP ')
        self.lblStatus = QLabel('Statuszeile')
        self.lblInfoX = QLabel('X-Goal')
        self.lblInfoY = QLabel('Y-Goal')

        # BOX-Layout mit Widgets füllen
        vbox = QVBoxLayout()
        # 0.Reihe
        hbox = QHBoxLayout()
        hbox.addWidget(self.lblInfoX)
        hbox.addWidget(self.lblInfoY)
        vbox.addLayout(hbox)
        # 1.Reihe
        hbox = QHBoxLayout()
        hbox.addWidget(lcd)
        hbox.addWidget(lcdY)
        vbox.addLayout(hbox)
        # 2.Reihe
        hbox = QHBoxLayout()
        hbox.addWidget(self.sld)
        hbox.addWidget(self.sldY)
        vbox.addLayout(hbox)
        # 3.Reihe
        hbox = QHBoxLayout()
        hbox.addWidget(pbLess)
        hbox.addWidget(pbMore)
        hbox.addWidget(pbLessY)
        hbox.addWidget(pbMoreY)
        vbox.addLayout(hbox)
        # 4.Reihe
        hbox = QHBoxLayout()
        hbox.addWidget(pbGo)
        hbox.addWidget(pbStop)
        vbox.addLayout(hbox)
        # Alle Boxen ins Window setzen
        self.setLayout(vbox)

        # Signal und Slot verbinden
        self.sld.valueChanged.connect(lcd.display)
        self.sldY.valueChanged.connect(lcdY.display)

        pbLess.clicked.connect(self.SlotKlick)
        pbMore.clicked.connect(self.SlotKlick)
        pbLessY.clicked.connect(self.SlotKlickY)
        pbMoreY.clicked.connect(self.SlotKlickY)
        pbGo.clicked.connect(self.SlotGo)
        pbStop.clicked.connect(self.timer.stop)
        pbStop.clicked.connect(self.SlotStop)

        # Fenster Konfigurieren
        self.setGeometry(300, 300, 250, 150)
        self.setWindowTitle('RTC - PyQt - TurtleSteering')
        self.show()

    def SlotKlick(self):
        sender = self.sender()
        self.lblStatus.setText(sender.text() + ' was pressed')
        if sender.text() == '<':
            wert = self.sld.value()
            wert = wert - 1
            self.sld.setValue(wert)
        else:
            wert = self.sld.value()
            wert = wert + 1
            self.sld.setValue(wert)

    def SlotKlickY(self):
        sender = self.sender()
        if sender.text() == '<':
            wert = self.sldY.value()
            wert = wert - 1
            self.sldY.setValue(wert)
        else:
            wert = self.sldY.value()
            wert = wert + 1
            self.sldY.setValue(wert)

    def SlotGo(self, timerIntervall=20):
        self.Stop = False
        """ Hier geht die Turtle ab """
        turtle1.goal.x = self.sld.value()
        turtle1.goal.y = self.sldY.value()
        self.timer.start(timerIntervall)  # in ms

    def SlotStop(self):
        turtle1.stop_robot()

    def get_scan(self):
        scan = rospy.wait_for_message('scan', LaserScan)
        scan_filtered = []
        numbOfScans = len(scan.ranges)  #
        # This number of samples is defined in
        # turtlebot3_<model>.gazebo.xacro file,
        # the default is 360.
        samples_view = 1  # 1 <= samples_view <= samples

        if samples_view > numbOfScans:
            samples_view = numbOfScans

        if samples_view == 1:
            scan_filtered.append(scan.ranges[0])

        else:
            left_lidar_samples_ranges = -(samples_view // 2 + samples_view % 2)
            right_lidar_samples_ranges = samples_view // 2
            left_lidar_samples = scan.ranges[left_lidar_samples_ranges:]
            right_lidar_samples = scan.ranges[:right_lidar_samples_ranges]
            scan_filtered.extend(left_lidar_samples + right_lidar_samples)

        for i in range(samples_view):
            if scan_filtered[i] == float('Inf'):
                scan_filtered[i] = 3.5
            elif math.isnan(scan_filtered[i]):
                scan_filtered[i] = 0

        return scan_filtered

    def obstacle_detected(self):
        STOP_DISTANCE = 0.3
        LIDAR_ERROR = 0.05
        SAFE_STOP_DISTANCE = STOP_DISTANCE + LIDAR_ERROR

        lidar_distances = self.get_scan()
        min_distance = min(lidar_distances)
        if min_distance < SAFE_STOP_DISTANCE:
            rospy.loginfo(" Obstacle detected ")
            return True
        else:
            rospy.loginfo(" No Obstacle detected ")
            return False

    def update(self):  # Aufruf per Timer alle 20ms
        self.get_scan()
        if not self.obstacle_detected():
            turtle1.move2goal()
        else:
            turtle1.robot_wait()
Exemplo n.º 35
0
class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        loadUi("ui_source_server/server_panel.ui", self)  # 加载面板文件,使用qt designer开发
        self.setWindowTitle("多媒体管理软件 -樱桃智库")  # 设置窗口标题
        icon_info = qta.icon('fa5s.chalkboard-teacher', color='#3a8ee6')
        self.setWindowIcon(icon_info)  # 设置窗口的图标
        self.setFixedSize(1160, 865)  # 设置窗口固定尺寸

        self.clients_list = []
        self.comboBox.addItems(self.clients_list)  # 为客户端选择框填充项目
        self.window_initial()  # 窗口初始化

        self.check_thread = Server([])  # 多线程去获取
        self.check_thread.signal.connect(self.server_callback)
        self.check_thread.start()  # 启动线程

        current_time = NowTime().now_time()
        self.textBrowser.append("" + current_time + "\n"
                                + "学生端输入本机ip:" + host + " 本机端口:" + str(port))

        icon_info = qta.icon('fa5s.info-circle', color='white')
        icon_reboot = qta.icon('fa5s.redo', color='white')
        icon_power_off = qta.icon('fa5s.power-off', color='white')
        icon_lock = qta.icon('fa5s.lock', color='white')
        icon_broadcast = qta.icon('fa5s.bullhorn', color='white')
        self.pushButton_5.setIcon(icon_info)
        self.pushButton.setIcon(icon_reboot)
        self.pushButton_2.setIcon(icon_power_off)
        self.pushButton_3.setIcon(icon_lock)
        self.pushButton_4.setIcon(icon_broadcast)

        for i in range(9):
            client_button = 'self.pushButtonClient_' + str(i + 1)
            eval(client_button).clicked.connect(self.child_window)

        self.statusbar.showMessage("软件版本 v0.0.1", 5000)

    def child_window(self):
        sender = self.sender()
        button_client = sender.objectName()
        client_num = int(button_client.split('_')[1])
        if not client_num > len(students):
            self.child = Child(students[client_num - 1])  # 创建子窗口实例
            self.child.exec()
        else:
            pass

    def window_initial(self):
        if self.clients_list:
            self.current_client = self.clients_list[0]  # 当前客户端是第一个客户端
        else:
            # 如果没有客户端,那么这些按钮不可用
            self.pushButton_5.setEnabled(False)
            self.pushButton.setEnabled(False)
            self.pushButton_2.setEnabled(False)
            self.pushButton_3.setEnabled(False)
        self.comboBox.currentIndexChanged.connect(self.choose_client)  # 选中一个客户端
        self.pushButton_5.clicked.connect(self.device_info)  # 点击设备信息以后的操作
        self.pushButton.clicked.connect(self.reboot_device)  # 点击重启设备的操作
        self.pushButton_2.clicked.connect(self.close_device)  # 点击关闭设备的操作
        self.pushButton_3.clicked.connect(self.lock_screen)  # 锁屏操作
        self.pushButton_4.clicked.connect(self.broadcast)  # 广播操作
        img_path = "ui_source_server/no_data.png"  # 图片路径
        image = QPixmap(img_path).scaled(300, 180)  # 加载图片,并自定义图片展示尺寸
        for i in range(9):
            video = 'self.video_' + str(i + 1)
            eval(video).setPixmap(image)  # 显示图片

    def setup_ui(self):
        """
        轮询所有的监控屏幕
        :return:
        """
        self.timer = QTimer(self)  # 初始化一个定时器
        if students:
            self.timer.timeout.connect(self.get_client_screen)  # 每次计时到时间时发出信号
            self.timer.start(1000)  # 设置计时间隔并启动;单位毫秒
        else:
            pass

    def choose_client(self, i):
        self.current_client = self.comboBox.currentText()
        now_client = str(self.current_client)
        if now_client:
            current_time = NowTime().now_time()
            self.textBrowser.append("<font color='black'>" + current_time + "\n连接" + now_client + "</font>")
        self.pushButton_5.setEnabled(True)
        self.pushButton.setEnabled(True)
        self.pushButton_2.setEnabled(True)
        self.pushButton_3.setEnabled(True)

    def device_info(self):
        """查看设备信息"""
        send_msg = {'device_info': True}
        self.control_client(send_msg)
        current_time = NowTime().now_time()
        self.textBrowser.append("<font color='blue'>" + current_time + "\n" + "查看设备信息</font>")

    def reboot_device(self):
        """
        教师端重启客户端
        :return:
        """
        send_msg = {'reboot': True}
        self.control_client(send_msg)
        current_time = NowTime().now_time()
        self.textBrowser.append("<font color='blue'>" + current_time + "\n" + "重启设备</font>")

    def close_device(self):
        """
        教师端关闭学生端计算机
        :return:
        """
        send_msg = {'turn_off': True}
        self.control_client(send_msg)
        current_time = NowTime().now_time()
        self.textBrowser.append("<font color='blue'>" + current_time + "\n" + "关闭设备</font>")

    def get_client_screen(self):
        self.check_thread = AutoPollScreen(students)  # 多线程去获取
        self.check_thread.signal.connect(self.screen_callback)
        self.check_thread.start()  # 启动线程

    def screen_callback(self, videos):
        """
        学生端视频轮询回调函数
        TODO 需要增加多个视频的连接!
        :param videos:
        :return:
        """
        if videos:
            for i, video in enumerate(videos):
                video = video.scaled(300, 200)
                if i > 9:
                    break
                eval('self.video_' + str(i + 1)).setPixmap(video)
        else:
            pass

    def server_callback(self, value):
        """
        回调函数中新增了连接的client,一方面去保持该client,另一方面是1、连接桌面视频2、增添combox
        :param value:
        :return:
        """
        self.update_clients()  # 更新tcp
        self.check_thread = TcpLink(value)  # 多线程去获取
        self.check_thread.signal.connect(self.tcp_callback)
        self.check_thread.start()  # 启动线程

    def tcp_callback(self, value):
        """
        tcp传输的回调函数,子线程的回复内容在这里出现。
        :param value: list
        :return: None
        """
        if value:
            client_addr = value[0].get('client_addr')
            receive_msg = value[0].get('receive_msg')
            offline = value[0].get('offline')
            stu_file = value[0].get('stu_file')

            if offline:
                client_name = client_addr[0] + ':' + str(client_addr[1])
                current_time = NowTime().now_time()
                self.textBrowser.append("<font color='red'>" + current_time + "\n"
                                        + client_name + "已经掉线!</font>")
                print("已经掉线")
                self.timer.stop()  # 停掉计时器
                # 掉线以后应该及时将students清掉!
                # 先停掉timer然后清掉,然后再开启!
                for i, student in enumerate(students):
                    if client_addr in student.values():
                        students.pop(i)
                        break
                self.setup_ui()  # 开启记时
                self.update_clients()  # 更新
            elif receive_msg:
                receive_msg = eval(receive_msg)
                stu_name = receive_msg.get('stu_name')
                stu_addr = receive_msg.get('stu_addr')
                mem_percent = receive_msg.get('mem_percent')
                if stu_name and stu_addr:
                    # 如果返回学生端计算名和计算地址
                    student = receive_msg
                    student['client_addr'] = client_addr  #
                    students.append(student)  # 添加到用户列表中
                    self.setup_ui()  # 开启记时
                elif mem_percent:
                    mem_percent = receive_msg['mem_percent']
                    current_time = NowTime().now_time()
                    self.textBrowser.append(
                        "<font color='Orange'>" + current_time + "\n" + "设备状态:CPU核心数"
                        + receive_msg['cpu_count'] + ",CPU占用:" + receive_msg['cpu_percent']
                        + ",内存占用:" + receive_msg['mem_percent'] + ".</font>")
                else:
                    client_name = client_addr[0] + ':' + str(client_addr[1])
                    current_time = NowTime().now_time()
                    # TODO 这里应该设置多线程后台连接,设置超时10次
                    self.textBrowser.append("<font color='red'>" + current_time + "\n"
                                            + client_name + " 举手一次</font>")
            elif stu_file:
                receive_data = value[0]
                stu_address = receive_data['client_addr']
                filename = stu_address[0] + '_' + str(stu_address[1]) + '_' + receive_data['stu_filename']  # 重建名字
                content = receive_data['stu_file']  # 获取数据
                with open("./received_files/" + filename, 'wb') as f:
                    f.write(content)
                current_time = NowTime().now_time()
                self.textBrowser.append(
                    "<font color='Orange'>" + current_time + "\n" + "收到文件" + filename + ",并保存成功!</font>")

    def lock_screen(self):
        send_msg = {'lock_screen': True}
        self.control_client(send_msg)
        current_time = NowTime().now_time()
        self.textBrowser.append("<font color='blue'>" + current_time + "\n" + "锁定计算机</font>")

    def control_client(self, command):
        """
        发送控制指令!
        :param command: dict
        :return: None
        """
        now_client = self.current_client
        client_addr = now_client.split(':')
        conn = (client_addr[0], int(client_addr[1]))
        try:
            conn_dt[conn].sendall((str(command)).encode("utf-8"))
        except Exception as err:
            print(err)

    def broadcast(self):
        broadcast_content = self.plainTextEdit.toPlainText()
        if broadcast_content and conn_list:
            current_time = NowTime().now_time()
            self.textBrowser.append("<font color='red'>" + current_time + " 广播\n"
                                    + broadcast_content + "</font>")
            send_msg = {'broadcast': broadcast_content}
            for client in conn_list:
                try:
                    conn_dt[client].sendall((str(send_msg)).encode("utf-8"))
                except Exception as err:
                    print(err)
                    continue
        else:
            pass

    def update_clients(self):
        """
        更新连接设备的下拉菜单
        :return:
        """
        self.comboBox.clear()
        # 从连接的设备中取地址
        connected_clients = [item[0] + ':' + str(item[1]) for item in conn_list]
        self.comboBox.addItems(connected_clients)
        if len(conn_list) == 0:
            # 如果没有客户端,那么这些按钮不可用
            self.pushButton_5.setEnabled(False)
            self.pushButton.setEnabled(False)
            self.pushButton_2.setEnabled(False)
            self.pushButton_3.setEnabled(False)
Exemplo n.º 36
0
class Ui_register_Dialog(QWidget):
    def setupUi(self, register_Dialog):
        register_Dialog.setObjectName("register_Dialog")
        register_Dialog.resize(width_px, height_px)

        self.space = 20
        self.displayed_image_size = 100
        self.col = 0
        self.row =0
        self.initial_path =None

        print(width_px)
        print(height_px)
        self.re_Save_pushButton = QtWidgets.QPushButton(register_Dialog)
        self.re_Save_pushButton.setGeometry(QtCore.QRect(30, 560, 89, 25))
        self.re_Save_pushButton.setObjectName("re_Save_pushButton")

        self.horizontalLayoutWidget = QtWidgets.QWidget(register_Dialog)
        self.horizontalLayoutWidget.setGeometry(QtCore.QRect(10, 20, 351, 31))
        self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget")
        self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget)
        self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout.setObjectName("horizontalLayout")

        self.label = QtWidgets.QLabel(self.horizontalLayoutWidget)
        self.label.setObjectName("label")
        self.horizontalLayout.addWidget(self.label)

        self.register_Camera_comboBox = QtWidgets.QComboBox(self.horizontalLayoutWidget)
        self.register_Camera_comboBox.setObjectName("register_Camera_comboBox")
        self.horizontalLayout.addWidget(self.register_Camera_comboBox)

        self.Register_Zoom_In_pushButton = QtWidgets.QPushButton(self.horizontalLayoutWidget)
        self.Register_Zoom_In_pushButton.setText("")
        self.Register_Zoom_In_pushButton.setIconSize(QtCore.QSize(25, 25))
        self.Register_Zoom_In_pushButton.setObjectName("Register_Zoom_In_pushButton")
        self.horizontalLayout.addWidget(self.Register_Zoom_In_pushButton)

        self.Register_Zoom_out_pushButton = QtWidgets.QPushButton(self.horizontalLayoutWidget)
        self.Register_Zoom_out_pushButton.setText("")
        self.Register_Zoom_out_pushButton.setIconSize(QtCore.QSize(25, 25))
        self.Register_Zoom_out_pushButton.setObjectName("Register_Zoom_out_pushButton")
        self.horizontalLayout.addWidget(self.Register_Zoom_out_pushButton)

        self.Register_Zoom_fit_pushButton = QtWidgets.QPushButton(self.horizontalLayoutWidget)
        self.Register_Zoom_fit_pushButton.setText("")
        self.Register_Zoom_fit_pushButton.setIconSize(QtCore.QSize(25, 25))
        self.Register_Zoom_fit_pushButton.setObjectName("Register_Zoom_fit_pushButton")
        self.horizontalLayout.addWidget(self.Register_Zoom_fit_pushButton)

        self.scrollArea = QtWidgets.QScrollArea(register_Dialog)
        self.scrollArea.setGeometry(QtCore.QRect(10, 60, 701, 491))
        self.scrollArea.setWidgetResizable(True)
        self.scrollArea.setObjectName("scrollArea")
        self.scrollAreaWidgetContents = QtWidgets.QWidget()
        self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 699, 489))
        self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")

        self.scrollArea_2 = QtWidgets.QScrollArea(register_Dialog)
        self.scrollArea_2.setWidgetResizable(True)
        self.scrollArea_2.setBackgroundRole(QPalette.Dark)#THEM DONG

        self.scrollAreaWidgetContents_2 = QtWidgets.QWidget()

        self.gridLayout = QtWidgets.QGridLayout(self.scrollAreaWidgetContents_2)
        self.scrollArea_2.setWidget(self.scrollAreaWidgetContents_2)
        self.scrollArea_2.setGeometry(width_px-3*displayed_image_size-space, space,displayed_image_size*2,height_px-displayed_image_size)  # khung show image

        self.verticalLayout = QtWidgets.QVBoxLayout()
        self.verticalLayout.addWidget(self.scrollArea_2)


        ################################################################################
        register_Dialog.closeEvent = self.CloseEvent
        dir_file_goc=os.getcwd()

        file_config_incon_zoom_in=dir_file_goc+"/resources/icons/zoom-in.png"
        file_config_incon_zoom_out=dir_file_goc+"/resources/icons/zoom-out.png"
        file_config_incon_zoom_fit=dir_file_goc+"/resources/icons/zoom.png"
        self.Register_Zoom_In_pushButton.setIcon(QtGui.QIcon(file_config_incon_zoom_in))
        self.Register_Zoom_out_pushButton.setIcon(QtGui.QIcon(file_config_incon_zoom_out))
        self.Register_Zoom_fit_pushButton.setIcon(QtGui.QIcon(file_config_incon_zoom_fit))

        self.re_img_label = QtWidgets.QLabel(self.scrollAreaWidgetContents)#THEM DONG
        self.scrollArea.setBackgroundRole(QPalette.Dark)#THEM DONG
        self.re_img_label.setWordWrap(True)
        self.re_img_label.setObjectName("label")
        self.scrollArea.setWidget(self.re_img_label)

        self.timer = QTimer()
        #self.Close_pushButton.clicked.connect()
        self.re_Save_pushButton.clicked.connect(self.save_img)
        self.timer.timeout.connect(self.viewCam_1)
        self.controlTimer()
        

        #self.show()
        ################################################################################
        self.retranslateUi(register_Dialog)
        QtCore.QMetaObject.connectSlotsByName(register_Dialog)

    def retranslateUi(self, register_Dialog):
        _translate = QtCore.QCoreApplication.translate
        register_Dialog.setWindowTitle(_translate("register_Dialog", "Dialog"))
        self.re_Save_pushButton.setText(_translate("register_Dialog", "Save"))
        self.label.setText(_translate("register_Dialog", "Camera"))

    def viewCam_1(self):
        converter = pylon.ImageFormatConverter()
        converter.OutputPixelFormat = pylon.PixelType_BGR8packed
        converter.OutputBitAlignment = pylon.OutputBitAlignment_MsbAligned

            # create video capture
        grabResult = camera.RetrieveResult(5000, pylon.TimeoutHandling_ThrowException)
        if grabResult.GrabSucceeded():
        # Access the image data
            image = converter.Convert(grabResult)
            self.img = image.GetArray()
            self.image = cv2.cvtColor(self.img, cv2.COLOR_BGR2RGB)
            height, width, channel = self.image.shape
            step = channel * width
            qImg = QImage(self.image.data, width, height, step, QImage.Format_RGB888)
            self.re_img_label.setPixmap(QPixmap.fromImage(qImg))

    def controlTimer(self):
        if not self.timer.isActive():
            camera.StartGrabbing(pylon.GrabStrategy_LatestImageOnly) 
            self.timer.start(20)

    def save_img(self):
        dir_image_raw = os.getcwd()+"/image_raw"
        dir_image_raw = dir_image_raw.rstrip()
        count_img_raw_saved = len(os.listdir(dir_image_raw))
        count_img_raw_saved = count_img_raw_saved + 1
 
        if (count_img_raw_saved <10):
            self.name = "image_raw_"+"000"+str(count_img_raw_saved)
        elif (count_img_raw_saved < 100):
            self.name = "image_raw_"+"00"+str(count_img_raw_saved)
        elif (count_img_raw_saved < 1000):
            self.name = "image_raw_"+"0"+str(count_img_raw_saved)
        else:
            self.name = str(count_img_raw_saved)

        name_save = dir_image_raw+"/"+self.name+".jpg"
        cv2.imwrite(name_save,self.image)
        self.remRow()
        self.show_img()

    def CloseEvent(self, event):
        self.timer.stop()
        camera.StopGrabbing()
        print("dong")
      
############################################################################
    def show_img(self):
        dir_image_raw = os.getcwd()+"/image_raw"
        file_path = dir_image_raw.rstrip()#bo khoang trang
        img_type = 'jpg'
        png_list = list(i for i in os.listdir(file_path) if str(i).endswith('.{}'.format(img_type)))
        png_list = sorted(png_list) #mang 1 chieu
        num = len(png_list)
        print(num)
        if num !=0:
            for i in range(num):
                print(png_list[i])
                image_id = str(file_path + '/'+png_list[i])
                pixmap = QPixmap(image_id)
                image_id = str(png_list[i])
                self.addImage(pixmap, image_id)
                QApplication.processEvents()

    def addImage(self, pixmap, image_id):
        self.row +=1
        clickable_image = QClickableImage(self.displayed_image_size, self.displayed_image_size, pixmap, image_id)
        self.gridLayout.addWidget(clickable_image, self.row, 0)

    def remRow(self):
        while self.gridLayout.count():
            item = self.gridLayout.takeAt(0)
            widget = item.widget()
            widget.deleteLater()
Exemplo n.º 37
0
class KMeansCanvas(FigureCanvas):
    # '''FigureCanvas的最终父类是QWidget'''

    def __init__(self, parent=None, width=5, height=4, dpi=100):
        self.mark = ['dr', '*b', 'sg', 'pk', '^r', '+b', '<g', 'hk']  # 聚类的图标加颜色, 最多设置8个聚类

        # 新建一个绘图对象
        self.fig = Figure(figsize=(width, height), dpi=dpi)
        self.fig.suptitle("KMeans")                                   # 设置figure的名字

        # 建立一个子图。如果要建立复合图, 可以在这里修改
        self.axes = self.fig.add_subplot(111)

        FigureCanvas.__init__(self, self.fig)
        self.setParent(parent)

        # 定义FigureCanvas的尺寸策略, 使之尽可能的向外填充空间
        FigureCanvas.setSizePolicy(self,
                                   QSizePolicy.Expanding,
                                   QSizePolicy.Expanding)
        FigureCanvas.updateGeometry(self)

    def kMeansPlot(self, dataSet, k, statusBar, button):
        self.kMeans = kMeans(dataSet, k)                                    # KMeans生成器

        # 设置Timer
        self.timerStart = True
        self.timer = QTimer(self)
        self.timer.timeout.connect(
            lambda: self.update_figure(dataSet, k, statusBar, button))      # 每隔一段时间就会触发一次 update函数

        self.update_figure(dataSet, k, statusBar, button)                   # 第一次自己来调用, 后面交给定时器Timer

    # 打开文件后显示图
    def plotInit(self, dataSet, statusBar):
        self.axes.clear()  # 清除上次绘图结果
        for i in range(len(dataSet)):
            self.axes.plot(dataSet[i, 0], dataSet[i, 1], 'oc', markersize=5)
        self.draw()
        statusBar.showMessage('数据已显示...')


    def update_figure(self, dataSet, k, statusBar, button):
        self.axes.clear()  # 清除上次绘图结果
        try:
            centroids, clusterAssessment, status = next(self.kMeans)  # 用生成器来迭代
            centroidsX = centroids.getA()[:, 0]
            centroidsY = centroids.getA()[:, 1]

            if status == CLASSIFICATION:
                # 表明分了类
                statusBar.showMessage('正在分类...')
                for i in range(len(dataSet)):
                    self.axes.plot(dataSet[i, 0], dataSet[i, 1], self.mark[int(clusterAssessment[i, 0])], markersize=5)

            elif status == NEWCENTROID:
                # 生成了新的聚类中心
                statusBar.showMessage('更新聚类中心...')
                for i in range(len(dataSet)):
                    self.axes.plot(dataSet[i, 0], dataSet[i, 1], self.mark[int(clusterAssessment[i, 0])], markersize=5)

            elif status == BEGINING:
                statusBar.showMessage('生成随机聚类中心...')
                # 最开始状态没有分类, 所以未分类的颜色点颜色都是一样的
                for i in range(len(dataSet)):
                    self.axes.plot(dataSet[i, 0], dataSet[i, 1], 'oc', markersize=5)

            legends = []
            for i in range(k):
                legend, = self.axes.plot(centroidsX[i], centroidsY[i], self.mark[i], markersize=10)
                legends.append(legend)
            self.axes.legend(legends, list(range(k)), loc="upper left")

            self.draw()

            if self.timerStart:
                self.timer.start(2000)
                self.timerStart = False
        except:
            statusBar.showMessage('KMeans已收敛')
            button.setEnabled(True)
            self.timer.stop()                       # 聚类收敛了, 停止迭代器
class DataUpdateUi(QWidget, TaskQueue.Observer):
    task_finish_signal = pyqtSignal([UpdateTask])
    refresh_finish_signal = pyqtSignal()

    INDEX_CHECK = 0
    INDEX_ITEM = 1
    INDEX_STATUS = 8
    TABLE_HEADER = ['', 'Item', 'Local Data Since', 'Local Data Until', 'Latest Update',
                    'Update Estimation', 'Sub Update', 'Update', 'Status']

    NO_SUB_UPDATE_URI = ['Market.SecuritiesInfo', 'Market.IndexInfo', ]
    SUB_UPDATE_STOCK_URI = ['Finance.Audit', 'Finance.BusinessComposition',
                            'Finance.BalanceSheet', 'Finance.IncomeStatement', 'Finance.CashFlowStatement',
                            'Stockholder.PledgeStatus', 'Stockholder.PledgeHistory', 'Stockholder.Statistics',
                            'TradeData.Stock.Daily', 'Market.NamingHistory', 'Market.SecuritiesTags']
    SUB_UPDATE_INDEX_URI = ['TradeData.Index.Daily']
    SUB_UPDATE_STOCK_EXCHANGE_URI = ['Market.TradeCalender']

    def get_uri_sub_update(self, uri: str) -> list or None:
        if uri in DataUpdateUi.SUB_UPDATE_STOCK_URI:
            data_utility = self.__data_hub.get_data_utility()
            return data_utility.get_stock_identities()
        elif uri in DataUpdateUi.SUB_UPDATE_INDEX_URI:
            return list(DEPENDS_INDEX.keys())
        elif uri in DataUpdateUi.SUB_UPDATE_STOCK_EXCHANGE_URI:
            return A_SHARE_MARKET
        elif uri in DataUpdateUi.NO_SUB_UPDATE_URI:
            return None
        else:
            print('Sub update declare missing.')
            assert False

    def __init__(self, data_hub_entry: DataHubEntry, update_table: UpdateTableEx):
        super(DataUpdateUi, self).__init__()

        # Access entry
        self.__data_hub = data_hub_entry
        self.__data_center = self.__data_hub.get_data_center()
        self.__update_table = update_table

        # Table content
        self.__display_uri = []
        self.__display_identities = None
        self.__display_table_lines = []

        # Page related
        self.__page = 0
        self.__item_per_page = 20

        # For processing updating
        self.__processing_update_tasks = []
        # Fot task counting
        self.__processing_update_tasks_count = []

        self.task_finish_signal.connect(self.__on_task_done)
        self.refresh_finish_signal.connect(self.update_table_display)

        # Timer for update status
        self.__timer = QTimer()
        self.__timer.setInterval(1000)
        self.__timer.timeout.connect(self.on_timer)
        self.__timer.start()

        # UI related
        self.__info_panel = QLabel(DEFAULT_INFO)

        self.__table_main = TableViewEx()
        self.__button_head_page = QPushButton('<<')
        self.__button_prev_page = QPushButton('<')
        self.__button_next_page = QPushButton('>')
        self.__button_tail_page = QPushButton('>>')
        self.__button_upper_level = QPushButton('↑')

        self.__button_refresh = QPushButton('Refresh')
        self.__button_batch_auto_update = QPushButton('Auto Update Select')
        self.__button_batch_force_update = QPushButton('Force Update Select')

        self.init_ui()

        # Post update and cache stock list after posting RefreshTask
        data_utility = self.__data_hub.get_data_utility()
        StockAnalysisSystem().get_task_queue().add_observer(self)
        StockAnalysisSystem().get_task_queue().append_task(UpdateStockListTask(data_utility))

    # ---------------------------------------------------- UI Init -----------------------------------------------------

    def init_ui(self):
        self.__layout_control()
        self.__config_control()
        self.__to_top_level()

    def __layout_control(self):
        main_layout = QVBoxLayout()
        self.setLayout(main_layout)
        self.setMinimumSize(600, 400)
        main_layout.addWidget(self.__table_main)

        bottom_control_area = QHBoxLayout()
        main_layout.addLayout(bottom_control_area)

        bottom_right_area = QVBoxLayout()
        bottom_control_area.addWidget(self.__info_panel, 99)
        bottom_control_area.addLayout(bottom_right_area, 0)

        line = horizon_layout([self.__button_head_page, self.__button_prev_page,
                               self.__button_next_page, self.__button_tail_page,
                               self.__button_upper_level, self.__button_refresh])
        bottom_right_area.addLayout(line)

        line = horizon_layout([self.__button_batch_auto_update, self.__button_batch_force_update])
        bottom_right_area.addLayout(line)

    def __config_control(self):
        self.__table_main.SetColumn(DataUpdateUi.TABLE_HEADER)
        self.__table_main.SetCheckableColumn(DataUpdateUi.INDEX_CHECK)
        self.__table_main.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)

        self.__button_head_page.clicked.connect(partial(self.on_page_control, '<<'))
        self.__button_prev_page.clicked.connect(partial(self.on_page_control, '<'))
        self.__button_next_page.clicked.connect(partial(self.on_page_control, '>'))
        self.__button_tail_page.clicked.connect(partial(self.on_page_control, '>>'))
        self.__button_upper_level.clicked.connect(partial(self.on_page_control, '^'))
        self.__button_refresh.clicked.connect(partial(self.on_page_control, 'r'))

        self.__button_batch_auto_update.clicked.connect(partial(self.on_batch_update, False))
        self.__button_batch_force_update.clicked.connect(partial(self.on_batch_update, True))

    def on_detail_button(self, uri: str):
        print('Detail of ' + uri)
        self.__page = 0
        self.__to_detail_level(uri)

    def on_auto_update_button(self, uri: str, identity: str):
        print('Auto update ' + uri + ':' + str(identity))
        self.__build_post_update_task(uri, identity, False)

    def on_force_update_button(self, uri: str, identity: str):
        print('Force update ' + uri + ' : ' + str(identity))
        self.__build_post_update_task(uri, identity, True)

    def on_batch_update(self, force: bool):
        for i in range(self.__table_main.RowCount()):
            if self.__table_main.GetItemCheckState(i, DataUpdateUi.INDEX_CHECK) == Qt.Checked:
                item_id = self.__table_main.GetItemText(i, DataUpdateUi.INDEX_ITEM)
                # A little ugly...To distinguish it's uri or securities ideneity
                if self.__display_identities is None:
                    self.__build_post_update_task(item_id, None, force)
                else:
                    self.__build_post_update_task(self.__display_uri[0], item_id, force)

    def on_page_control(self, control: str):
        # data_utility = self.__data_hub.get_data_utility()
        # stock_list = data_utility.get_stock_list()
        # max_page = len(stock_list) // self.__item_per_page

        if self.__display_identities is None:
            max_item_count = len(self.__display_uri)
        else:
            max_item_count = len(self.__display_identities)
        max_page = max_item_count // self.__item_per_page

        new_page = self.__page
        if control == '<<':
            new_page = 0
        elif control == '<':
            new_page = max(self.__page - 1, 0)
        elif control == '>':
            new_page = min(self.__page + 1, max_page)
        elif control == '>>':
            new_page = max_page
        elif control == '^':
            self.__to_top_level()

        if control in ['<<', '<', '>', '>>', 'r']:
            if control == 'r' or new_page != self.__page:
                self.update_table()
                self.__page = new_page

    def on_timer(self):
        for i in range(self.__table_main.RowCount()):
            item_id = self.__table_main.GetItemText(i, DataUpdateUi.INDEX_ITEM)
            # A little ugly...To distinguish it's uri or securities identity
            if self.__display_identities is None:
                uri = item_id
                prog_id = uri
            else:
                uri = self.__display_uri[0]
                prog_id = [uri, item_id]
            for task in self.__processing_update_tasks:
                if not task.in_work_package(uri):
                    continue
                text = []
                if task.status() in [TaskQueue.Task.STATUS_IDLE, TaskQueue.Task.STATUS_PENDING]:
                    text.append('等待中...')
                else:
                    if task.progress.has_progress(prog_id):
                        rate = task.progress.get_progress_rate(prog_id)
                        text.append('%ss' % task.clock.elapsed_s())
                        text.append('%.2f%%' % (rate * 100))
                    if task.status() == TaskQueue.Task.STATUS_CANCELED:
                        text.append('[Canceled]')
                    elif task.status() == TaskQueue.Task.STATUS_FINISHED:
                        text.append('[Finished]')
                    elif task.status() == TaskQueue.Task.STATUS_EXCEPTION:
                        text.append('[Error]')
                self.__table_main.SetItemText(i, DataUpdateUi.INDEX_STATUS, ' | '.join(text))
                break

    # def closeEvent(self, event):
    #     if self.__task_thread is not None:
    #         QMessageBox.information(self,
    #                                 QtCore.QCoreApplication.translate('', '无法关闭窗口'),
    #                                 QtCore.QCoreApplication.translate('', '更新过程中无法关闭此窗口'),
    #                                 QMessageBox.Close, QMessageBox.Close)
    #         event.ignore()
    #     else:
    #         event.accept()

    # ---------------------------------------- Table Update ----------------------------------------

    def update_table(self):
        self.__table_main.Clear()
        self.__table_main.SetColumn(DataUpdateUi.TABLE_HEADER)
        self.__table_main.AppendRow(['', '刷新中...', '', '', '', '', '', '', ''])
        task = RefreshTask(self)
        StockAnalysisSystem().get_task_queue().append_task(task)

    def update_table_display(self):
        self.__table_main.Clear()
        self.__table_main.SetColumn(DataUpdateUi.TABLE_HEADER)

        for line in self.__display_table_lines:
            self.__table_main.AppendRow(line)
            index = self.__table_main.RowCount() - 1

            # Add check box
            # check_item = QTableWidgetItem()
            # check_item.setCheckState(QtCore.Qt.Unchecked)
            # self.__table_main.setItem(index, 0, check_item)

            # Add detail button
            # Only if currently in top level
            if self.__display_identities is None or len(self.__display_identities) == 0:
                if line[1] not in DataUpdateUi.NO_SUB_UPDATE_URI:
                    button = QPushButton('Enter')
                    button.clicked.connect(partial(self.on_detail_button, line[1]))
                    self.__table_main.SetCellWidget(index, 6, button)

            # Add update button
            button_auto = QPushButton('Auto')
            button_force = QPushButton('Force')
            if self.__display_identities is None:
                button_auto.clicked.connect(partial(self.on_auto_update_button, line[1], None))
                button_force.clicked.connect(partial(self.on_force_update_button, line[1], None))
            else:
                button_auto.clicked.connect(partial(self.on_auto_update_button, self.__display_uri[0], line[1]))
                button_force.clicked.connect(partial(self.on_force_update_button, self.__display_uri[0], line[1]))
            self.__table_main.SetCellWidget(index, 7, [button_auto, button_force])

    def update_table_content(self):
        contents = []
        count = self.__item_per_page
        offset = self.__page * self.__item_per_page

        for uri in self.__display_uri:
            update_details = self.__display_identities if \
                self.__display_identities is not None else [None]
            for index in range(offset, offset + count):
                if index >= len(update_details):
                    break
                line = self.generate_line_content(uri, update_details[index])
                if line is not None:
                    contents.append(line)
        self.__display_table_lines = contents

    def generate_line_content(self, uri: str, identity: str or None) -> [list] or None:
        line = []

        data_table, _ = self.__data_center.get_data_table(uri)
        update_table = self.__update_table

        if data_table is None:
            return None

        since, until = update_table.get_since_until(uri.split('.'))
        if since is None or until is None:
            # TODO: Workaround - because each stock storage in each table.
            # So we cannot fetch its time range with this method.
            since, until = data_table.range(uri, identity)
        if until is not None:
            update_since = min(tomorrow_of(until), now())
            update_until = now()
        else:
            update_since, update_until = self.__data_center.calc_update_range(uri, identity)

        update_tags = uri.split('.')
        latest_update = self.__update_table.get_last_update_time(update_tags)

        line.append('')     # Place holder for check box
        line.append(identity if str_available(identity) else uri)
        line.append(date2text(since) if since is not None else ' - ')
        line.append(date2text(until) if until is not None else ' - ')
        line.append(date2text(latest_update) if latest_update is not None else ' - ')

        if update_since is not None and update_until is not None:
            line.append(date2text(update_since) + ' - ' + date2text(update_until))
        else:
            line.append(' - ')
        line.append('-')    # Place holder for detail button
        line.append('')     # Place holder for update button
        line.append('')     # Place holder for status

        return line

    # def update_table(self):
    #     if self.__current_uri == '':
    #         self.update_uri_level()
    #     else:
    #         self.update_identity_level(self.__current_uri, self.__page * self.__item_per_page, self.__item_per_page)
    #
    # def update_uri_level(self):
    #     self.__table_main.clear()
    #     self.__table_main.setRowCount(0)
    #     self.__table_main.setHorizontalHeaderLabels(DataUpdateUi.TABLE_HEADER_URI)
    #
    #     for declare in DATA_FORMAT_DECLARE:
    #         line = []
    #         uri = declare[0]
    #         data_table, _ = self.__data_center.get_data_table(uri)
    #
    #         # TODO: Fetching finance data's date range spends a lost of time because the data is huge.
    #         since, until = data_table.range(uri, None)
    #         update_since, update_until = self.__data_center.calc_update_range(uri)
    #
    #         update_tags = uri.split('.')
    #         latest_update = self.__update_table.get_last_update_time(update_tags)
    #
    #         line.append('')     # Place holder for check box
    #         line.append(uri)
    #         line.append(date2text(since) if since is not None else ' - ')
    #         line.append(date2text(until) if until is not None else ' - ')
    #         line.append(date2text(latest_update) if latest_update is not None else ' - ')
    #
    #         if update_since is not None and update_until is not None:
    #             line.append(date2text(update_since) + ' - ' + date2text(update_until))
    #         else:
    #             line.append(' - ')
    #         line.append('-')    # Place holder for detail button
    #         line.append('')     # Place holder for update button
    #         line.append('')     # Place holder for status
    #
    #         self.__table_main.AppendRow(line)
    #         index = self.__table_main.rowCount() - 1
    #
    #         # Add check box
    #         check_item = QTableWidgetItem()
    #         check_item.setCheckState(QtCore.Qt.Unchecked)
    #         self.__table_main.setItem(index, 0, check_item)
    #
    #         # Add detail button
    #         if uri in DataUpdateUi.INCLUDES_SECURITIES_SUB_UPDATE_LIST:
    #             button = QPushButton('Enter')
    #             button.clicked.connect(partial(self.on_detail_button, uri))
    #             self.__table_main.AddWidgetToCell(index, 6, button)
    #
    #         # Add update button
    #         button_auto = QPushButton('Auto')
    #         button_force = QPushButton('Force')
    #         button_auto.clicked.connect(partial(self.on_auto_update_button, uri, None))
    #         button_force.clicked.connect(partial(self.on_force_update_button, uri, None))
    #         self.__table_main.AddWidgetToCell(index, 7, [button_auto, button_force])
    #
    # def update_identity_level(self, uri: str, offset: int, count: int):
    #     if uri == '':
    #         self.update_uri_level()
    #         return
    #
    #     self.__table_main.clear()
    #     self.__table_main.setRowCount(0)
    #     self.__table_main.setHorizontalHeaderLabels(DataUpdateUi.TABLE_HEADER_IDENTITY)
    #
    #     data_utility = self.__data_hub.get_data_utility()
    #     stock_list = data_utility.get_stock_list()
    #
    #     for index in range(offset, offset + count):
    #         if index >= len(stock_list):
    #             break
    #
    #         stock_identity, name = stock_list[index]
    #         data_table, _ = self.__data_center.get_data_table(uri)
    #
    #         since, until = data_table.range(uri, stock_identity)
    #         update_since, update_until = self.__data_center.calc_update_range(uri, stock_identity)
    #
    #         update_tags = uri.split('.')
    #         update_tags.append(stock_identity.replace('.', '_'))
    #         latest_update = self.__update_table.get_last_update_time(update_tags)
    #
    #         line = []
    #         line.append('')     # Place holder for check box
    #         line.append(stock_identity)
    #         line.append(date2text(since) if since is not None else ' - ')
    #         line.append(date2text(until) if until is not None else ' - ')
    #         line.append(date2text(latest_update) if latest_update is not None else ' - ')
    #
    #         if update_since is not None and update_until is not None:
    #             line.append(date2text(update_since) + ' - ' + date2text(update_until))
    #         else:
    #             line.append(' - ')
    #         line.append('')     # Place holder for update button
    #         line.append('')     # Place holder for status
    #
    #         self.__table_main.AppendRow(line)
    #         index = self.__table_main.rowCount() - 1
    #
    #         # Add check box
    #         check_item = QTableWidgetItem()
    #         check_item.setCheckState(QtCore.Qt.Unchecked)
    #         self.__table_main.setItem(index, 0, check_item)
    #
    #         # Add update button
    #         button_auto = QPushButton('Auto')
    #         button_force = QPushButton('Force')
    #         button_auto.clicked.connect(partial(self.on_auto_update_button, uri, stock_identity))
    #         button_force.clicked.connect(partial(self.on_force_update_button, uri, stock_identity))
    #         self.__table_main.AddWidgetToCell(index, 6, [button_auto, button_force])

    # --------------------------------------------------------------------------

    def __to_top_level(self):
        self.__display_uri = [declare[0] for declare in DATA_FORMAT_DECLARE]
        self.__display_identities = None
        self.__page = 0
        self.update_table()

    def __to_detail_level(self, uri: str):
        self.__display_uri = [uri]
        self.__display_identities = self.get_uri_sub_update(uri)
        # if uri in ['Market.TradeCalender']:
        #     self.__display_identities = ['SSE']
        # elif uri in DataUpdateUi.INCLUDES_SECURITIES_SUB_UPDATE_LIST:
        #     data_utility = self.__data_hub.get_data_utility()
        #     self.__display_identities = data_utility.get_stock_identities()
        self.__page = 0
        self.update_table()

    def __build_post_update_task(self, uri: str, identities: list or None, force: bool) -> bool:
        task = UpdateTask(self, self.__data_hub, self.__data_center, force)
        if identities is None:
            identities = self.get_uri_sub_update(uri)
            # if uri == 'Market.TradeCalender':
            #     identities = 'SSE'
            # elif uri in DataUpdateUi.INCLUDES_SECURITIES_SUB_UPDATE_LIST:
            #     data_utility = self.__data_hub.get_data_utility()
            #     identities = data_utility.get_stock_identities()
        task.set_work_package(uri, identities)
        self.__processing_update_tasks.append(task)
        self.__processing_update_tasks_count.append(task)
        ret = StockAnalysisSystem().get_task_queue().append_task(task)
        # After updating market info, also update stock list cache
        if ret and uri == 'Market.SecuritiesInfo':
            data_utility = self.__data_hub.get_data_utility()
            StockAnalysisSystem().get_task_queue().append_task(UpdateStockListTask(data_utility))
        return ret

    # def __work_around_for_update_pack(self):
    #     for i in range(0, len(self.__update_pack)):
    #         if self.__update_pack[i][0] == 'Market.TradeCalender':
    #             self.__update_pack[i][1] = ['SSE']
    #         elif self.__update_pack[i][0] in DataUpdateUi.INCLUDES_SECURITIES_SUB_UPDATE_LIST:
    #             if self.__update_pack[i][1] is None:
    #                 data_utility = self.__data_hub.get_data_utility()
    #                 stock_list = data_utility.get_stock_identities()
    #                 self.__update_pack[i][1] = stock_list

    # --------------------------------- Thread ---------------------------------

    # ------------------------- Refresh Task -------------------------

    # def execute_refresh_task(self):
    #     if self.__refresh_thread is None:
    #         self.__refresh_thread = threading.Thread(target=self.refresh_task)
    #         self.__refresh_thread.start()
    #
    # def refresh_task(self):
    #     print('Refresh task start.')
    #     self.update_table_content()
    #     self.__refresh_thread = None
    #     self.refresh_finish_signal.emit()
    #     print('Refresh task finished.')

    # ----------------------- Data Update Task ----------------------

    # def execute_update_task(self):
    #     if self.__refresh_thread is not None:
    #         QMessageBox.information(self,
    #                                 QtCore.QCoreApplication.translate('', '无法执行'),
    #                                 QtCore.QCoreApplication.translate('', '列表刷新中,无法执行数据更新'),
    #                                 QMessageBox.Close, QMessageBox.Close)
    #         return
    #
    #     self.__work_around_for_update_pack()
    #     if self.__task_thread is None:
    #         self.__task_thread = threading.Thread(target=self.update_task)
    #         StockAnalysisSystem().lock_sys_quit()
    #         self.__task_thread.start()
    #     else:
    #         print('Task already running...')
    #         QMessageBox.information(self,
    #                                 QtCore.QCoreApplication.translate('', '无法执行'),
    #                                 QtCore.QCoreApplication.translate('', '已经有更新在运行中,无法同时运行多个更新'),
    #                                 QMessageBox.Close, QMessageBox.Close)
    #
    # def update_task(self):
    #     print('Update task start.')
    #
    #     self.__lock.acquire()
    #     task = copy.deepcopy(self.__update_pack)
    #     force = self.__update_force
    #     self.__lock.release()
    #
    #     self.__timing_clock.reset()
    #     self.__progress_rate.reset()
    #     for uri, identities in task:
    #         if identities is not None:
    #             self.__progress_rate.set_progress(uri, 0, len(identities))
    #             for identity in identities:
    #                 self.__progress_rate.set_progress([uri, identity], 0, 1)
    #         else:
    #             self.__progress_rate.set_progress(uri, 0, 1)
    #
    #     for uri, identities in task:
    #         if identities is not None:
    #             for identity in identities:
    #                 # Optimise: Update not earlier than listing date.
    #                 listing_date = self.__data_hub.get_data_utility().get_stock_listing_date(identity, default_since())
    #
    #                 if force:
    #                     since, until = listing_date, now()
    #                 else:
    #                     since, until = self.__data_center.calc_update_range(uri, identity)
    #                     since = max(listing_date, since)
    #
    #                 self.__data_center.update_local_data(uri, identity, (since, until))
    #                 self.__progress_rate.increase_progress([uri, identity])
    #                 self.__progress_rate.increase_progress(uri)
    #         else:
    #             self.__data_center.update_local_data(uri, force=force)
    #             self.__progress_rate.increase_progress(uri)
    #
    #     self.task_finish_signal.emit()
    #     print('Update task finished.')

    # ---------------------------------------------------------------------------------

    def on_task_updated(self, task, change: str):
        if change in ['canceled', 'finished']:
            if task in self.__processing_update_tasks_count:
                self.task_finish_signal[UpdateTask].emit(task)

    def __on_task_done(self, task: UpdateTask):
        if task in self.__processing_update_tasks_count:
            self.__processing_update_tasks_count.remove(task)
            print('Finish task: %s, remaining count: %s' % (task.name(), len(self.__processing_update_tasks_count)))
            if len(self.__processing_update_tasks_count) == 0:
                QMessageBox.information(self,
                                        QtCore.QCoreApplication.translate('main', '更新完成'),
                                        QtCore.QCoreApplication.translate('main', '数据更新完成'),
                                        QMessageBox.Ok, QMessageBox.Ok)
                self.__processing_update_tasks.clear()
                self.update_table()
        else:
            print('Impossible: Cannot find finished task in task list.')
class thirdDialog(QDialog):
    def __init__(self):
        super(thirdDialog, self).__init__()
        loadUi(
            r"/home/pi/Desktop/Testing bench part1/GUI/UI-main/thirddialog.ui",
            self)  #loadui
        self.backbutton3.clicked.connect(self.pagetwo)
        self.savebutton.clicked.connect(self.savetofile)
        self.clickherebutton.clicked.connect(self.calibration)
        self.weightlabel1 = self.weightlabel
        self.showweight()
        self.DIPlabel1 = self.DIP1label
        self.DIPlabel2 = self.DIP2label
        self.DIPlabel3 = self.DIP3label
        self.DOPlabel1 = self.DOP1label
        self.DOPlabel2 = self.DOP2label
        self.DOPlabel3 = self.DOP3label
        self.DOPlabel4 = self.DOP4label
        self.calibratelabel1 = self.calibratelabel
        self.clickedbutton1 = self.clickedbutton
        self.inputdevicestatus()
        self.qTimer = QTimer()
        # set interval to 1 s
        self.qTimer.setInterval(10)  # 10 ms
        # connect timeout signal to signal handler
        self.qTimer.timeout.connect(self.showweight)
        self.qTimer.timeout.connect(self.inputdevicestatus)
        self.qTimer.start()
        self.calibratelabel1.setText("To calibrate with Ref. weight of " +
                                     str(RW) + "g")
        self.status_DOP()
        self.clickedbutton.clicked.connect(self.changeoutput)

    '''def start(self):
        self.DIPlabel1.setStyleSheet("background-color: ")
        self.DIPlabel2.setStyleSheet("background-color: ")
        self.DIPlabel3.setStyleSheet("background-color: ")
        self.DOPlabel1.setStyleSheet("background-color: ")
        self.DOPlabel2.setStyleSheet("background-color: ")
        self.DOPlabel3.setStyleSheet("background-color: ")
        self.DOPlabel4.setStyleSheet("background-color: ")'''

    def status_DOP(self):
        global state
        state = get_DOP_status(1)
        if get_DOP_status(1):
            self.DOPlabel1.setStyleSheet("background-color: lightgreen")
            DOP1_working = "On"
        else:
            self.DOPlabel1.setStyleSheet("background-color: red")
            DOP1_working = "Off"
        if get_DOP_status(2):
            self.DOPlabel2.setStyleSheet("background-color: lightgreen")
            DOP2_working = "On"
        else:
            self.DOPlabel2.setStyleSheet("background-color: red")
            DOP2_working = "Off"
        if get_DOP_status(3):
            self.DOPlabel3.setStyleSheet("background-color: lightgreen")
            DOP3_working = "On"
        else:
            self.DOPlabel3.setStyleSheet("background-color: red")
            DOP3_working = "Off"
        if get_DOP_status(4):
            self.DOPlabel4.setStyleSheet("background-color: lightgreen")
            DOP4_working = "On"
        else:
            self.DOPlabel4.setStyleSheet("background-color: red")
            DOP4_working = "Off"

    def changeoutput(self):
        global state
        if state == 0:
            DOP_H(1)
            time.sleep(.1)
            DOP_H(2)
            time.sleep(.1)
            DOP_H(3)
            time.sleep(.1)
            DOP_H(4)
            time.sleep(.1)
            self.DOPlabel1.setStyleSheet("background-color: lightgreen")
            self.DOPlabel2.setStyleSheet("background-color: lightgreen")
            self.DOPlabel3.setStyleSheet("background-color: lightgreen")
            self.DOPlabel4.setStyleSheet("background-color: lightgreen")
            state = 1
            DOP1_working = "On"
            DOP2_working = "On"
            DOP3_working = "On"
            DOP4_working = "On"
        else:
            DOP_L(1)
            time.sleep(.1)
            DOP_L(2)
            time.sleep(.1)
            DOP_L(3)
            time.sleep(.1)
            DOP_L(4)
            time.sleep(.1)
            self.DOPlabel1.setStyleSheet("background-color: red")
            self.DOPlabel2.setStyleSheet("background-color: red")
            self.DOPlabel3.setStyleSheet("background-color: red")
            self.DOPlabel4.setStyleSheet("background-color: red")
            state = 0
            DOP1_working = "Off"
            DOP2_working = "Off"
            DOP3_working = "Off"
            DOP4_working = "Off"

    def pagetwo(self):
        self.qTimer.stop()
        #backpage1=secondDialog(serialno_of_DUT)
        widget.addWidget(secondpage1)
        print("Secondpage")
        #print("Index",widget.currentIndex()-1)
        widget.setCurrentIndex(widget.currentIndex() + 1)

    def showweight(self):  #connect the first page
        self.weightlabel1.setText(str(get_data_via_rs232()) + " g")
        self.weightlabel1.show()

    def calibration(self):
        ser.write(RS232_wreq_calibration)
        time.sleep(0.5)

    def inputdevicestatus(self):
        global DIP1_working
        global DIP2_working
        global DIP3_working
        if get_DIP_status(1):
            self.DIPlabel1.setStyleSheet("background-color: lightgreen")
            DIP1_working = "On"
        else:
            self.DIPlabel1.setStyleSheet("background-color: red")
            DIP1_working = "Off"
        if get_DIP_status(2):
            self.DIPlabel2.setStyleSheet("background-color: lightgreen")
            DIP2_working = "On"
        else:
            self.DIPlabel2.setStyleSheet("background-color: red")
            DIP2_working = "Off"
        if get_DIP_status(3):
            self.DIPlabel3.setStyleSheet("background-color: lightgreen")
            DIP3_working = "On"
        else:
            self.DIPlabel3.setStyleSheet("background-color: red")
            DIP3_working = "Off"

    def savetofile(self):

        global old1, old2, old3, q
        global index
        self.qTimer.stop()
        with open(r'/home/pi/Desktop/Testing bench part1/report.csv',
                  'a') as f:
            writer = csv.writer(f)
            writer.writerow([q], [6])
            q += 1
        mbox = QMessageBox()  #popup the message box widget
        mbox.setWindowTitle("")
        range_check = ""
        Stability_check = ""
        DIP1_working = ""
        DIP2_working = ""
        DIP3_working = ""
        DOP1_working = ""
        DOP2_working = ""
        DOP3_working = ""
        DOP4_working = ""
        mbox.setText("Saved successfully")
        mbox.setText("\nRS232_connection : ", RS232_connection)
        mbox.setText("\nRS485_connection : ", RS485_connection)
        mbox.setText("Range : ")
        mbox.setText("Stability : ")
        mbox.setText("DOP : ")
        #mbox.setIcon(QMessageBox.Warning)
        x = mbox.exec_()
        #firstDialog.serialnumber.clear()
        #index=2
        #secondDialog.backfunction(self,index)
        #index=1
        old1 = False
        old2 = False
        old3 = False
        RS232_connection = ""
        RS485_connection = ""
        range_check = ""
        Stability_check = ""
        DIP1_working = ""
        DIP2_working = ""
        DIP3_working = ""
        DOP1_working = ""
        DOP2_working = ""
        DOP3_working = ""
        DOP4_working = ""

        currentpage = firstDialog()
        widget.addWidget(currentpage)
        #print("Index",widget.currentIndex()+1)
        widget.setCurrentIndex(widget.currentIndex() + 1)
        #self.showweight()
        print("Firstpage")
Exemplo n.º 40
0
class DemoMdi(QMainWindow):
    def __init__(self, parent=None):
        super(DemoMdi, self).__init__(parent)

        # 设置窗口标题
        self.setWindowTitle(
            'MDI with a dockWidget tree and a tab-view mdiArea')
        # 设置窗口大小
        self.resize(800, 640)
        self.initUi()

        self.mytimer = QTimer(self)
        self.mytimer.start(1000)
        self.mytimer.timeout.connect(self.timerCallback)

    def initUi(self):
        self.initMenuBar()
        self.initToolBar()
        self.initDockTree()
        self.initStatusBar()

        self.mdiArea = QMdiArea(self)
        self.setCentralWidget(self.mdiArea)

        # set as tabbedView by default
        self.mdiArea.setViewMode(QMdiArea.TabbedView)
        self.mdiArea.setTabShape(QTabWidget.Triangular)
        self.mdiArea.setTabsClosable(True)
        self.mdiArea.setTabsMovable(True)

        # index of document
        self.newDocIndex = 1

    def initDockTree(self):
        self.dockWind = QDockWidget(self)
        self.dockWind.setWindowTitle('QProfile Explorer')

        self.initTree()
        self.dockWind.setWidget(self.tree)
        self.dockWind.setFloating(False)  # set floating = false
        self.addDockWidget(Qt.LeftDockWidgetArea,
                           self.dockWind)  # set the position at left side
        # remove all features of DockWidget like Closable, Moveable, Floatable, VerticalTitle etc.
        self.dockWind.setFeatures(QDockWidget.NoDockWidgetFeatures)

    def initTree(self):
        self.tree = QTreeWidget()
        self.tree.setColumnCount(1)  #设置列数
        #self.tree.setHeaderLabels(['QProfiler items'])  #设置树形控件头部的标题
        self.tree.setIndentation(20)  # 项目的缩进
        self.tree.setHeaderHidden(True)
        #设置根节点

        Perfmon = myQTreeWidgetItem(sin(pi * perfmon_x))
        Perfmon.setText(0, 'Perfmon')
        perfmon_00 = myQTreeWidgetItem(sin(2 * pi * perfmon_x))
        perfmon_00.setText(0, 'perfmon_00')
        Perfmon.addChild(perfmon_00)
        perfmon_01 = QTreeWidgetItem()
        perfmon_01.setText(0, 'perfmon_01')
        Perfmon.addChild(perfmon_01)
        perfmon_02 = QTreeWidgetItem()
        perfmon_02.setText(0, 'perfmon_02')
        Perfmon.addChild(perfmon_02)
        perfmon_03 = QTreeWidgetItem()
        perfmon_03.setText(0, 'perfmon_03')
        Perfmon.addChild(perfmon_03)
        self.tree.addTopLevelItem(Perfmon)
        # CPU
        cpuLoad = QTreeWidgetItem()
        cpuLoad.setText(0, 'CPU')
        cpuLoad_1 = QTreeWidgetItem()
        cpuLoad_1.setText(0, 'core 1')
        cpuLoad.addChild(cpuLoad_1)
        cpuLoad_2 = QTreeWidgetItem()
        cpuLoad_2.setText(0, 'core 2')
        cpuLoad.addChild(cpuLoad_2)
        self.tree.addTopLevelItem(cpuLoad)

        # treeItem signal
        self.tree.itemClicked[QTreeWidgetItem,
                              int].connect(self.treeItemClicked)

    def treeItemWindow_open(self, item):
        title = item.text(0)
        subWind = QMdiSubWindow(self)
        subWind.setAttribute(Qt.WA_DeleteOnClose)
        subWind.setWindowTitle(title)
        self.newDocIndex += 1
        mainWid = QWidget()
        l = QtWidgets.QVBoxLayout(mainWid)
        txtWind = QPlainTextEdit(mainWid)
        txtWind.setPlainText(f"perfmon.x = {item.x}, \n y = {item.y}")
        figWind = MyCanvas(mainWid,
                           width=5,
                           height=4,
                           dpi=100,
                           treeWidgetItem=item)
        l.addWidget(figWind)
        l.addWidget(txtWind)
        l.setStretch(0, 3)  # 设置第一列的伸展比例为 3
        l.setStretch(1, 1)  # 设置第二列的伸展比例为 1, 这样2列的伸展比为3:1

        subWind.setWidget(mainWid)
        self.mdiArea.addSubWindow(subWind)
        subWind.show()

    def treeItemClicked(self, item, column):
        tab = self.get_treeItem_tab(item.text(column))
        if tab is not None:
            tab.setFocus()
        else:
            if item.text(column) == 'Perfmon':
                self.treeItemWindow_open(item)
            else:
                newDoc = QMdiSubWindow(self)
                newDoc.setAttribute(Qt.WA_DeleteOnClose)
                newDoc.setWindowTitle(item.text(column))
                self.newDocIndex += 1
                newDoc.setWidget(QPlainTextEdit(
                    item.text(column) * 10, newDoc))
                self.mdiArea.addSubWindow(newDoc)
                newDoc.show()

    def get_treeItem_tab(self, title):
        for wind in self.mdiArea.subWindowList():
            if title == wind.windowTitle():
                return wind
        return None

    def initStatusBar(self):
        self.statusBar = self.statusBar()
        self.statusBar.showMessage('Ready to start ...', 0)

    def initMenuBar(self):
        menuBar = self.menuBar()
        style = QApplication.style()

        #==== 文件 ====#
        fileMenu = menuBar.addMenu('文件')

        #新建一个文档
        aFileNew = QAction('新建文档', self)
        aFileNew.setIcon(style.standardIcon(QStyle.SP_FileIcon))
        aFileNew.triggered.connect(self.onFileNew)
        fileMenu.addAction(aFileNew)

        #打开一个文档
        aFileOpen = QAction('打开文档', self)
        aFileOpen.setIcon(style.standardIcon(QStyle.SP_DialogOpenButton))
        aFileOpen.triggered.connect(self.onFileOpen)
        fileMenu.addAction(aFileOpen)

        #关闭一个文档
        aFileCloseAll = QAction('关闭全部', self)
        aFileCloseAll.setIcon(style.standardIcon(QStyle.SP_DialogCloseButton))
        aFileOpen.triggered.connect(self.onFileCloseAll)
        fileMenu.addAction(aFileCloseAll)

        #添加分割线
        fileMenu.addSeparator()

        #退出
        aFileExit = QAction('退出', self)
        aFileExit.triggered.connect(self.close)
        fileMenu.addAction(aFileExit)

        #==== 编辑 ====#
        editMenu = menuBar.addMenu('编辑')

        #剪切
        aEditCut = QAction('剪切', self)
        aEditCut.setIcon(QIcon(':/ico/cut.png'))
        aEditCut.triggered.connect(self.onEditCut)
        editMenu.addAction(aEditCut)

        #复制
        aEditCopy = QAction('复制', self)
        aEditCopy.setIcon(QIcon(':/ico/copy.png'))
        aEditCopy.triggered.connect(self.onEditCopy)
        editMenu.addAction(aEditCopy)

        #粘贴
        aEditPaste = QAction('粘贴', self)
        aEditPaste.setIcon(QIcon(':/ico/paste.png'))
        aEditPaste.triggered.connect(self.onEditPaste)
        editMenu.addAction(aEditPaste)

        #==== 窗口排列方式 ====#
        windowMenu = menuBar.addMenu('窗口')

        #子窗口模式
        aWndSubView = QAction('子窗口模式', self)
        aWndSubView.triggered.connect(lambda: self.onWinowdMode(0))
        windowMenu.addAction(aWndSubView)
        #标签页模式
        aWndTab = QAction('标签页模式', self)
        aWndTab.triggered.connect(lambda: self.onWinowdMode(1))
        windowMenu.addAction(aWndTab)

        windowMenu.addSeparator()

        #平铺模式
        aWndTile = QAction('平铺模式', self)
        aWndTile.triggered.connect(lambda: self.onWinowdMode(2))
        windowMenu.addAction(aWndTile)
        #窗口级联模式
        aWndCascade = QAction('窗口级联模式', self)
        aWndCascade.triggered.connect(lambda: self.onWinowdMode(3))
        windowMenu.addAction(aWndCascade)

    def initToolBar(self):
        toolBar = self.addToolBar('ToolBar')
        style = QApplication.style()

        min_width = 64

        btnFileNew = QToolButton(self)
        btnFileNew.setText('新建文档')
        btnFileNew.setMinimumWidth(min_width)
        btnFileNew.setIcon(style.standardIcon(QStyle.SP_FileIcon))
        btnFileNew.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
        btnFileNew.clicked.connect(self.onFileNew)
        toolBar.addWidget(btnFileNew)

        btnFileOpen = QToolButton(self)
        btnFileOpen.setText('打开文档')
        btnFileOpen.setMinimumWidth(min_width)
        btnFileOpen.setIcon(style.standardIcon(QStyle.SP_DialogOpenButton))
        btnFileOpen.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
        btnFileOpen.clicked.connect(self.onFileOpen)
        toolBar.addWidget(btnFileOpen)

        btnFileCloseAll = QToolButton(self)
        btnFileCloseAll.setText('关闭全部')
        btnFileCloseAll.setMinimumWidth(min_width)
        btnFileCloseAll.setIcon(style.standardIcon(
            QStyle.SP_DialogCloseButton))
        btnFileCloseAll.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
        btnFileCloseAll.clicked.connect(self.onFileCloseAll)
        toolBar.addWidget(btnFileCloseAll)

        toolBar.addSeparator()

        btnEditCut = QToolButton(self)
        btnEditCut.setText('剪切')
        btnEditCut.setMinimumWidth(64)
        btnEditCut.setIcon(QIcon(':/ico/cut.png'))
        btnEditCut.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
        btnEditCut.clicked.connect(self.onEditCut)
        toolBar.addWidget(btnEditCut)

        btnEditCopy = QToolButton(self)
        btnEditCopy.setText('复制')
        btnEditCopy.setMinimumWidth(64)
        btnEditCopy.setIcon(QIcon(':/ico/copy.png'))
        btnEditCopy.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
        btnEditCopy.clicked.connect(self.onEditCopy)
        toolBar.addWidget(btnEditCopy)

        btnEditPaste = QToolButton(self)
        btnEditPaste.setText('粘贴')
        btnEditPaste.setMinimumWidth(64)
        btnEditPaste.setIcon(QIcon(':/ico/paste.png'))
        btnEditPaste.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
        btnEditPaste.clicked.connect(self.onEditPaste)
        toolBar.addWidget(btnEditPaste)

    def msgCritical(self, strInfo):
        dlg = QMessageBox(self)
        dlg.setIcon(QMessageBox.Critical)
        dlg.setText(strInfo)
        dlg.show()

    def onFileNew(self):
        newDoc = QMdiSubWindow(self)
        newDoc.setAttribute(Qt.WA_DeleteOnClose)
        newDoc.setWindowTitle('新文档 ' + str(self.newDocIndex))
        self.newDocIndex += 1
        newDoc.setWidget(QPlainTextEdit(newDoc))
        self.mdiArea.addSubWindow(newDoc)
        newDoc.show()

    def onFileOpen(self):
        path, _ = QFileDialog.getOpenFileName(self, '打开文件', '',
                                              '文本文件 (*.txt, *.prf)')
        if path:
            try:
                with open(path, 'rU') as f:
                    text = f.read()
            except Exception as e:
                self.msgCritical(str(e))
            else:
                openDoc = QMdiSubWindow(self)
                openDoc.setWindowTitle(path)
                txtEdit = QPlainTextEdit(openDoc)
                txtEdit.setPlainText(text)
                openDoc.setWidget(txtEdit)
                self.mdiArea.addSubWindow(openDoc)
                openDoc.show()

    def onFileCloseAll(self):
        self.mdiArea.closeAllSubWindows()

    def onEditCut(self):
        txtEdit = self.mdiArea.activeSubWindow().widget()
        txtEdit.cut()

    def onEditCopy(self):
        txtEdit = self.mdiArea.activeSubWindow().widget()
        txtEdit.copy()

    def onEditPaste(self):
        txtEdit = self.mdiArea.activeSubWindow().widget()
        txtEdit.paste()

    def onWinowdMode(self, index):
        if index == 3:
            self.mdiArea.cascadeSubWindows()
        elif index == 2:
            self.mdiArea.tileSubWindows()
        elif index == 1:
            self.mdiArea.setViewMode(QMdiArea.TabbedView)
        else:
            self.mdiArea.setViewMode(QMdiArea.SubWindowView)

    def timerCallback(self):
        self.statusBar.showMessage(
            f'Document Index = {self.newDocIndex}, subWind num ={len(self.mdiArea.subWindowList())}',
            0)
Exemplo n.º 41
0
class ElectrumGui(Logger):
    @profiler
    def __init__(self, config, daemon, plugins):
        set_language(config.get('language', get_default_language()))
        Logger.__init__(self)
        # Uncomment this call to verify objects are being properly
        # GC-ed when windows are closed
        #network.add_jobs([DebugMem([Abstract_Wallet, SPV, Synchronizer,
        #                            ElectrumWindow], interval=5)])
        QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_X11InitThreads)
        if hasattr(QtCore.Qt, "AA_ShareOpenGLContexts"):
            QtCore.QCoreApplication.setAttribute(
                QtCore.Qt.AA_ShareOpenGLContexts)
        if hasattr(QGuiApplication, 'setDesktopFileName'):
            QGuiApplication.setDesktopFileName('electrum-dash.desktop')
        self.gui_thread = threading.current_thread()
        self.config = config
        self.daemon = daemon
        self.plugins = plugins
        self.windows = []
        self.efilter = OpenFileEventFilter(self.windows)
        self.app = QElectrumApplication(sys.argv)
        self.app.installEventFilter(self.efilter)
        self.app.setWindowIcon(read_QIcon("electrum-dash.png"))
        # timer
        self.timer = QTimer(self.app)
        self.timer.setSingleShot(False)
        self.timer.setInterval(500)  # msec

        self.nd = None
        self.network_updated_signal_obj = QNetworkUpdatedSignalObject()
        self._num_wizards_in_progress = 0
        self._num_wizards_lock = threading.Lock()
        # init tray
        self.dark_icon = self.config.get("dark_icon", False)
        self.tray = QSystemTrayIcon(self.tray_icon(), None)
        self.tray.setToolTip('Dash Electrum')
        self.tray.activated.connect(self.tray_activated)
        self.build_tray_menu()
        self.tray.show()
        self.app.new_window_signal.connect(self.start_new_window)
        self.set_dark_theme_if_needed()
        run_hook('init_qt', self)

    def set_dark_theme_if_needed(self):
        use_dark_theme = self.config.get('qt_gui_color_theme',
                                         'default') == 'dark'
        self.app.setStyle('Fusion')
        if use_dark_theme:
            from .dark_dash_style import dash_stylesheet
            self.app.setStyleSheet(dash_stylesheet)
        else:
            from .dash_style import dash_stylesheet
            self.app.setStyleSheet(dash_stylesheet)
        # Apply any necessary stylesheet patches
        patch_qt_stylesheet(use_dark_theme=use_dark_theme)
        # Even if we ourselves don't set the dark theme,
        # the OS/window manager/etc might set *a dark theme*.
        # Hence, try to choose colors accordingly:
        ColorScheme.update_from_widget(QWidget(), force_dark=use_dark_theme)

    def build_tray_menu(self):
        # Avoid immediate GC of old menu when window closed via its action
        if self.tray.contextMenu() is None:
            m = QMenu()
            self.tray.setContextMenu(m)
        else:
            m = self.tray.contextMenu()
            m.clear()
        for window in self.windows:
            submenu = m.addMenu(window.wallet.basename())
            submenu.addAction(_("Show/Hide"), window.show_or_hide)
            submenu.addAction(_("Close"), window.close)
        m.addAction(_("Dark/Light"), self.toggle_tray_icon)
        m.addSeparator()
        m.addAction(_("Exit Dash Electrum"), self.close)

    def tray_icon(self):
        if self.dark_icon:
            return read_QIcon('electrum_dark_icon.png')
        else:
            return read_QIcon('electrum_light_icon.png')

    def toggle_tray_icon(self):
        self.dark_icon = not self.dark_icon
        self.config.set_key("dark_icon", self.dark_icon, True)
        self.tray.setIcon(self.tray_icon())

    def tray_activated(self, reason):
        if reason == QSystemTrayIcon.DoubleClick:
            if all([w.is_hidden() for w in self.windows]):
                for w in self.windows:
                    w.bring_to_top()
            else:
                for w in self.windows:
                    w.hide()

    def close(self):
        for window in self.windows:
            window.close()

    def new_window(self, path, uri=None):
        # Use a signal as can be called from daemon thread
        self.app.new_window_signal.emit(path, uri)

    def show_network_dialog(self, parent):
        if not self.daemon.network:
            parent.show_warning(_(
                'You are using Dash Electrum in offline mode; restart Dash Electrum if you want to get connected'
            ),
                                title=_('Offline'))
            return
        if self.nd:
            self.nd.on_update()
            self.nd.show()
            self.nd.raise_()
            return
        self.nd = NetworkDialog(self.daemon.network, self.config,
                                self.network_updated_signal_obj)
        self.nd.show()

    def _create_window_for_wallet(self, wallet):
        w = ElectrumWindow(self, wallet)
        self.windows.append(w)
        self.build_tray_menu()
        # FIXME: Remove in favour of the load_wallet hook
        run_hook('on_new_window', w)
        w.warn_if_testnet()
        w.warn_if_watching_only()
        return w

    def count_wizards_in_progress(func):
        def wrapper(self: 'ElectrumGui', *args, **kwargs):
            with self._num_wizards_lock:
                self._num_wizards_in_progress += 1
            try:
                return func(self, *args, **kwargs)
            finally:
                with self._num_wizards_lock:
                    self._num_wizards_in_progress -= 1

        return wrapper

    @count_wizards_in_progress
    def start_new_window(self, path, uri, *, app_is_starting=False):
        '''Raises the window for the wallet if it is open.  Otherwise
        opens the wallet and creates a new window for it'''
        wallet = None
        try:
            wallet = self.daemon.load_wallet(path, None)
        except BaseException as e:
            self.logger.exception('')
            custom_message_box(icon=QMessageBox.Warning,
                               parent=None,
                               title=_('Error'),
                               text=_('Cannot load wallet') + ' (1):\n' +
                               str(e))
            # if app is starting, still let wizard to appear
            if not app_is_starting:
                return
        if not wallet:
            try:
                wallet = self._start_wizard_to_select_or_create_wallet(path)
            except (WalletFileException, BitcoinException) as e:
                self.logger.exception('')
                custom_message_box(icon=QMessageBox.Warning,
                                   parent=None,
                                   title=_('Error'),
                                   text=_('Cannot load wallet') + ' (2):\n' +
                                   str(e))
        if not wallet:
            return
        # create or raise window
        try:
            for window in self.windows:
                if window.wallet.storage.path == wallet.storage.path:
                    break
            else:
                window = self._create_window_for_wallet(wallet)
        except BaseException as e:
            self.logger.exception('')
            custom_message_box(icon=QMessageBox.Warning,
                               parent=None,
                               title=_('Error'),
                               text=_('Cannot create window for wallet') +
                               ':\n' + str(e))
            if app_is_starting:
                wallet_dir = os.path.dirname(path)
                path = os.path.join(wallet_dir,
                                    get_new_wallet_name(wallet_dir))
                self.start_new_window(path, uri)
            return
        if uri:
            window.pay_to_URI(uri)
        window.bring_to_top()
        window.setWindowState(window.windowState() & ~QtCore.Qt.WindowMinimized
                              | QtCore.Qt.WindowActive)

        window.activateWindow()
        return window

    def _start_wizard_to_select_or_create_wallet(
            self, path) -> Optional[Abstract_Wallet]:
        wizard = InstallWizard(self.config, self.app, self.plugins)
        try:
            path, storage = wizard.select_storage(path, self.daemon.get_wallet)
            # storage is None if file does not exist
            if storage is None:
                wizard.path = path  # needed by trustedcoin plugin
                wizard.run('new')
                storage = wizard.create_storage(path)
            else:
                wizard.run_upgrades(storage)
        except (UserCancelled, GoBack):
            return
        except WalletAlreadyOpenInMemory as e:
            return e.wallet
        finally:
            wizard.terminate()
        # return if wallet creation is not complete
        if storage is None or storage.get_action():
            return
        wallet = Wallet(storage)
        wallet.start_network(self.daemon.network)
        self.daemon.add_wallet(wallet)
        return wallet

    def close_window(self, window: ElectrumWindow):
        if window in self.windows:
            self.windows.remove(window)
        self.build_tray_menu()
        # save wallet path of last open window
        if not self.windows:
            self.config.save_last_wallet(window.wallet)
        run_hook('on_close_window', window)
        self.daemon.stop_wallet(window.wallet.storage.path)

    def init_network(self):
        # Show network dialog if config does not exist
        if self.daemon.network:
            if self.config.get('auto_connect') is None:
                wizard = InstallWizard(self.config, self.app, self.plugins)
                wizard.init_network(self.daemon.network)
                wizard.terminate()

    def main(self):
        try:
            self.init_network()
        except UserCancelled:
            return
        except GoBack:
            return
        except BaseException as e:
            self.logger.exception('')
            return
        self.timer.start()
        self.config.open_last_wallet()
        path = self.config.get_wallet_path()
        if not self.start_new_window(
                path, self.config.get('url'), app_is_starting=True):
            return
        signal.signal(signal.SIGINT, lambda *args: self.app.quit())

        def quit_after_last_window():
            # keep daemon running after close
            if self.config.get('daemon'):
                return
            # check if a wizard is in progress
            with self._num_wizards_lock:
                if self._num_wizards_in_progress > 0 or len(self.windows) > 0:
                    return
            self.app.quit()

        self.app.setQuitOnLastWindowClosed(
            False)  # so _we_ can decide whether to quit
        self.app.lastWindowClosed.connect(quit_after_last_window)

        def clean_up():
            # Shut down the timer cleanly
            self.timer.stop()
            # clipboard persistence. see http://www.mail-archive.com/[email protected]/msg17328.html
            event = QtCore.QEvent(QtCore.QEvent.Clipboard)
            self.app.sendEvent(self.app.clipboard(), event)
            self.tray.hide()

        self.app.aboutToQuit.connect(clean_up)

        # main loop
        self.app.exec_()
        # on some platforms the exec_ call may not return, so use clean_up()

    def stop(self):
        self.logger.info('closing GUI')
        self.app.quit()
Exemplo n.º 42
0
class Mouse(QGraphicsItem):
    Pi = math.pi
    TwoPi = 2.0 * Pi

    # Create the bounding rectangle once.
    adjust = 0.5
    BoundingRect = QRectF(-20 - adjust, -22 - adjust, 40 + adjust, 83 + adjust)

    def __init__(self):
        super(Mouse, self).__init__()

        self.angle = 0.0
        self.speed = 0.0
        self.mouseEyeDirection = 0.0
        self.color = QColor(qrand() % 256, qrand() % 256, qrand() % 256)

        self.setRotation(qrand() % (360 * 16))

        # In the C++ version of this example, this class is also derived from
        # QObject in order to receive timer events.  PyQt does not support
        # deriving from more than one wrapped class so we just create an
        # explicit timer instead.
        self.timer = QTimer()
        self.timer.timeout.connect(self.timerEvent)
        self.timer.start(1000 / 33)

    @staticmethod
    def normalizeAngle(angle):
        while angle < 0:
            angle += Mouse.TwoPi
        while angle > Mouse.TwoPi:
            angle -= Mouse.TwoPi
        return angle

    def boundingRect(self):
        return Mouse.BoundingRect

    def shape(self):
        path = QPainterPath()
        path.addRect(-10, -20, 20, 40)
        return path

    def paint(self, painter, option, widget):
        # Body.
        painter.setBrush(self.color)
        painter.drawEllipse(-10, -20, 20, 40)

        # Eyes.
        painter.setBrush(Qt.white)
        painter.drawEllipse(-10, -17, 8, 8)
        painter.drawEllipse(2, -17, 8, 8)

        # Nose.
        painter.setBrush(Qt.black)
        painter.drawEllipse(QRectF(-2, -22, 4, 4))

        # Pupils.
        painter.drawEllipse(QRectF(-8.0 + self.mouseEyeDirection, -17, 4, 4))
        painter.drawEllipse(QRectF(4.0 + self.mouseEyeDirection, -17, 4, 4))

        # Ears.
        if self.scene().collidingItems(self):
            painter.setBrush(Qt.red)
        else:
            painter.setBrush(Qt.darkYellow)

        painter.drawEllipse(-17, -12, 16, 16)
        painter.drawEllipse(1, -12, 16, 16)

        # Tail.
        path = QPainterPath(QPointF(0, 20))
        path.cubicTo(-5, 22, -5, 22, 0, 25)
        path.cubicTo(5, 27, 5, 32, 0, 30)
        path.cubicTo(-5, 32, -5, 42, 0, 35)
        painter.setBrush(Qt.NoBrush)
        painter.drawPath(path)

    def timerEvent(self):
        # Don't move too far away.
        lineToCenter = QLineF(QPointF(0, 0), self.mapFromScene(0, 0))
        if lineToCenter.length() > 150:
            angleToCenter = math.acos(lineToCenter.dx() /
                                      lineToCenter.length())
            if lineToCenter.dy() < 0:
                angleToCenter = Mouse.TwoPi - angleToCenter
            angleToCenter = Mouse.normalizeAngle((Mouse.Pi - angleToCenter) +
                                                 Mouse.Pi / 2)

            if angleToCenter < Mouse.Pi and angleToCenter > Mouse.Pi / 4:
                # Rotate left.
                self.angle += [-0.25, 0.25][self.angle < -Mouse.Pi / 2]
            elif angleToCenter >= Mouse.Pi and angleToCenter < (
                    Mouse.Pi + Mouse.Pi / 2 + Mouse.Pi / 4):
                # Rotate right.
                self.angle += [-0.25, 0.25][self.angle < Mouse.Pi / 2]
        elif math.sin(self.angle) < 0:
            self.angle += 0.25
        elif math.sin(self.angle) > 0:
            self.angle -= 0.25

        # Try not to crash with any other mice.
        dangerMice = self.scene().items(
            QPolygonF([
                self.mapToScene(0, 0),
                self.mapToScene(-30, -50),
                self.mapToScene(30, -50)
            ]))

        for item in dangerMice:
            if item is self:
                continue

            lineToMouse = QLineF(QPointF(0, 0), self.mapFromItem(item, 0, 0))
            angleToMouse = math.acos(lineToMouse.dx() / lineToMouse.length())
            if lineToMouse.dy() < 0:
                angleToMouse = Mouse.TwoPi - angleToMouse
            angleToMouse = Mouse.normalizeAngle((Mouse.Pi - angleToMouse) +
                                                Mouse.Pi / 2)

            if angleToMouse >= 0 and angleToMouse < Mouse.Pi / 2:
                # Rotate right.
                self.angle += 0.5
            elif angleToMouse <= Mouse.TwoPi and angleToMouse > (Mouse.TwoPi -
                                                                 Mouse.Pi / 2):
                # Rotate left.
                self.angle -= 0.5

        # Add some random movement.
        if len(dangerMice) > 1 and (qrand() % 10) == 0:
            if qrand() % 1:
                self.angle += (qrand() % 100) / 500.0
            else:
                self.angle -= (qrand() % 100) / 500.0

        self.speed += (-50 + qrand() % 100) / 100.0

        dx = math.sin(self.angle) * 10
        self.mouseEyeDirection = 0.0 if qAbs(dx / 5) < 1 else dx / 5

        self.setRotation(self.rotation() + dx)
        self.setPos(self.mapToParent(0, -(3 + math.sin(self.speed) * 3)))
Exemplo n.º 43
0
	def clock(self):
		timer = QTimer(self)
		timer.timeout.connect(self.showTime)
		timer.start(1000)
		self.showTime()
Exemplo n.º 44
0
class MyDialog(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):

        self.LeftPlotEnableCB = QtWidgets.QCheckBox("Cummulative", self)
        self.SquareCB = QtWidgets.QCheckBox("Square", self)
        self.CircleCB = QtWidgets.QCheckBox("Circle", self)

        #define the dialog layouts.
        TopLayout = QtWidgets.QGridLayout(self)

        ButtonLayout = QtWidgets.QVBoxLayout()
        GraphLayout = QtWidgets.QHBoxLayout()
        ParametersLayout = QtWidgets.QFormLayout()
        ResultsLayout = QtWidgets.QFormLayout()

        TopLayout.addLayout(ParametersLayout, 7, 2, 1, 2)
        TopLayout.addLayout(ResultsLayout, 7, 5, 1, 2)
        TopLayout.addLayout(ButtonLayout, 1, 1, 4, 1)
        TopLayout.addLayout(GraphLayout, 1, 2, 6, 6)

        #define the buttons.
        ResetButton = QtWidgets.QPushButton("Reset", self)
        ResetButton.clicked.connect(self.Reset)
        StartButton = QtWidgets.QPushButton("start", self)
        StartButton.clicked.connect(self.StartOpt)
        StopButton = QtWidgets.QPushButton("stop", self)
        LoadFileButton = QtWidgets.QPushButton("Load", self)
        StopButton.clicked.connect(self.StopOpt)

        SaveFileButton = QtWidgets.QPushButton("Save", self)

        #add buttons ton button layout.
        ButtonLayout.addWidget(ResetButton)
        ButtonLayout.addWidget(StartButton)
        ButtonLayout.addWidget(StopButton)
        ButtonLayout.addWidget(LoadFileButton)
        ButtonLayout.addWidget(SaveFileButton)
        ButtonLayout.addWidget(self.LeftPlotEnableCB)
        ButtonLayout.addWidget(self.SquareCB)
        ButtonLayout.addWidget(self.CircleCB)

        fig1 = Figure(figsize=(5, 5), dpi=100)
        self.axes1 = fig1.add_subplot(111)
        self.figCanvas1 = FigureCanvas(fig1)
        self.figCanvas1.setParent(self)
        GraphLayout.addWidget(self.figCanvas1)

        fig2 = Figure(figsize=(5, 5), dpi=100)
        self.axes2 = fig2.add_subplot(111)
        self.figCanvas2 = FigureCanvas(fig2)
        self.figCanvas2.setParent(self)
        GraphLayout.addWidget(self.figCanvas2)

        StepSizeLabel = QtWidgets.QLabel("StepSize")
        self.StepSizeText = QtWidgets.QLineEdit("0.1")
        self.StepSizeText.textChanged.connect(self.UpdateParameters)
        ParametersLayout.addRow(StepSizeLabel, self.StepSizeText)

        NumberOfPointsLabel = QtWidgets.QLabel("Numder of points")
        self.NumberOfPointsText = QtWidgets.QLineEdit("65")
        self.NumberOfPointsText.textChanged.connect(self.UpdateNumberOfPoints)
        ParametersLayout.addRow(NumberOfPointsLabel, self.NumberOfPointsText)

        MaxLoopCountLabel = QtWidgets.QLabel("Maximum Trials")
        self.MaxLoopCountText = QtWidgets.QLineEdit("100000")
        self.MaxLoopCountText.textChanged.connect(self.UpdateParameters)
        ParametersLayout.addRow(MaxLoopCountLabel, self.MaxLoopCountText)

        TestFieldLabel = QtWidgets.QLabel("Test Field")
        self.TestFieldText = QtWidgets.QLineEdit("ux")
        ResultsLayout.addRow(TestFieldLabel, self.TestFieldText)

        QualityLabel = QtWidgets.QLabel("Quality")
        self.QualityText = QtWidgets.QLineEdit("???")
        ResultsLayout.addRow(QualityLabel, self.QualityText)

        self.mp = Maxp.Maxp()
        self.Reset()

        self.Timer = QTimer(self)
        self.Timer.setInterval(0)
        self.Timer.timeout.connect(self.TimerProcess)
        #        self.Timer.start()

        self.show()
        self.testcounter = 0

    def GetNumberOfPoints(self):
        return int(self.NumberOfPointsText.text())

    def GetMaxLoopCount(self):
        return int(self.MaxLoopCountText.text())

    def GetStepSize(self):
        return float(self.StepSizeText.text())

    def UpdateParameters(self):
        self.mp.SetStepSize(float(self.StepSizeText.text()))
        self.mp.SetNumberOfPoints(int(self.NumberOfPointsText.text()))
        self.mp.SetMaxLoopCount(int(self.MaxLoopCountText.text()))

    def UpdateNumberOfPoints(self):
        self.mp.SetNumberOfPoints(int(self.NumberOfPointsText.text()))
        self.Reset()

    def PlotLeft(self, array):
        self.axes1.clear()
        self.axes1.plot(array[0], array[1], 'r+')
        self.figCanvas1.draw()

    def PlotRight(self, array):
        self.axes2.plot(array[0], array[1], 'r.')
        self.figCanvas2.draw()

    def StartOpt(self):
        self.NumberOfPointsText.setReadOnly(True)
        self.Timer.start()

    def StopOpt(self):
        self.NumberOfPointsText.setReadOnly(False)
        self.Timer.stop()

    def Reset(self):
        self.mp.SetStepSize(float(self.StepSizeText.text()))
        self.mp.SetMaxLoopCount(int(self.MaxLoopCountText.text()))
        self.mp.SetNumberOfPoints(int(self.NumberOfPointsText.text()))
        self.mp.InitMaxp()

    def TimerProcess(self):
        if self.SquareCB.isChecked() == True:
            self.mp.SetShape("Square")
        elif self.CircleCB.isChecked() == True:
            self.mp.SetShape("Circle")

        self.testcounter = self.testcounter + 1
        self.TestFieldText.setText(str(self.testcounter))
        self.PlotLeft(self.mp.GetArrayOfPoints())
        if self.LeftPlotEnableCB.isChecked() == True:
            self.PlotRight(self.mp.GetArrayOfPoints())

        if self.mp.Search() >= self.GetMaxLoopCount():
            self.Timer.stop()

        self.QualityText.setText(str(self.mp.GetQuality()))
Exemplo n.º 45
0
class CuraEngineBackend(QObject, Backend):
    ##  Starts the back-end plug-in.
    #
    #   This registers all the signal listeners and prepares for communication
    #   with the back-end in general.
    #   CuraEngineBackend is exposed to qml as well.
    def __init__(self, parent = None):
        super().__init__(parent = parent)
        # Find out where the engine is located, and how it is called.
        # This depends on how Cura is packaged and which OS we are running on.
        executable_name = "CuraEngine"
        if Platform.isWindows():
            executable_name += ".exe"
        default_engine_location = executable_name
        if os.path.exists(os.path.join(Application.getInstallPrefix(), "bin", executable_name)):
            default_engine_location = os.path.join(Application.getInstallPrefix(), "bin", executable_name)
        if hasattr(sys, "frozen"):
            default_engine_location = os.path.join(os.path.dirname(os.path.abspath(sys.executable)), executable_name)
        if Platform.isLinux() and not default_engine_location:
            if not os.getenv("PATH"):
                raise OSError("There is something wrong with your Linux installation.")
            for pathdir in os.getenv("PATH").split(os.pathsep):
                execpath = os.path.join(pathdir, executable_name)
                if os.path.exists(execpath):
                    default_engine_location = execpath
                    break

        if not default_engine_location:
            raise EnvironmentError("Could not find CuraEngine")

        Logger.log("i", "Found CuraEngine at: %s" %(default_engine_location))

        default_engine_location = os.path.abspath(default_engine_location)
        Preferences.getInstance().addPreference("backend/location", default_engine_location)

        # Workaround to disable layer view processing if layer view is not active.
        self._layer_view_active = False
        Application.getInstance().getController().activeViewChanged.connect(self._onActiveViewChanged)
        self._onActiveViewChanged()
        self._stored_layer_data = []
        self._stored_optimized_layer_data = []

        self._scene = Application.getInstance().getController().getScene()
        self._scene.sceneChanged.connect(self._onSceneChanged)

        # Triggers for auto-slicing. Auto-slicing is triggered as follows:
        #  - auto-slicing is started with a timer
        #  - whenever there is a value change, we start the timer
        #  - sometimes an error check can get scheduled for a value change, in that case, we ONLY want to start the
        #    auto-slicing timer when that error check is finished
        #  If there is an error check, it will set the "_is_error_check_scheduled" flag, stop the auto-slicing timer,
        #  and only wait for the error check to be finished to start the auto-slicing timer again.
        #
        self._global_container_stack = None
        Application.getInstance().globalContainerStackChanged.connect(self._onGlobalStackChanged)
        self._onGlobalStackChanged()

        Application.getInstance().stacksValidationFinished.connect(self._onStackErrorCheckFinished)

        # A flag indicating if an error check was scheduled
        # If so, we will stop the auto-slice timer and start upon the error check
        self._is_error_check_scheduled = False

        # Listeners for receiving messages from the back-end.
        self._message_handlers["cura.proto.Layer"] = self._onLayerMessage
        self._message_handlers["cura.proto.LayerOptimized"] = self._onOptimizedLayerMessage
        self._message_handlers["cura.proto.Progress"] = self._onProgressMessage
        self._message_handlers["cura.proto.GCodeLayer"] = self._onGCodeLayerMessage
        self._message_handlers["cura.proto.GCodePrefix"] = self._onGCodePrefixMessage
        self._message_handlers["cura.proto.PrintTimeMaterialEstimates"] = self._onPrintTimeMaterialEstimates
        self._message_handlers["cura.proto.SlicingFinished"] = self._onSlicingFinishedMessage

        self._start_slice_job = None
        self._slicing = False  # Are we currently slicing?
        self._restart = False  # Back-end is currently restarting?
        self._tool_active = False  # If a tool is active, some tasks do not have to do anything
        self._always_restart = True  # Always restart the engine when starting a new slice. Don't keep the process running. TODO: Fix engine statelessness.
        self._process_layers_job = None  # The currently active job to process layers, or None if it is not processing layers.
        self._need_slicing = False
        self._engine_is_fresh = True  # Is the newly started engine used before or not?

        self._backend_log_max_lines = 20000  # Maximum number of lines to buffer
        self._error_message = None  # Pop-up message that shows errors.
        self._last_num_objects = 0  # Count number of objects to see if there is something changed
        self._postponed_scene_change_sources = []  # scene change is postponed (by a tool)

        self.backendQuit.connect(self._onBackendQuit)
        self.backendConnected.connect(self._onBackendConnected)

        # When a tool operation is in progress, don't slice. So we need to listen for tool operations.
        Application.getInstance().getController().toolOperationStarted.connect(self._onToolOperationStarted)
        Application.getInstance().getController().toolOperationStopped.connect(self._onToolOperationStopped)

        self._slice_start_time = None

        Preferences.getInstance().addPreference("general/auto_slice", True)

        self._use_timer = False
        # When you update a setting and other settings get changed through inheritance, many propertyChanged signals are fired.
        # This timer will group them up, and only slice for the last setting changed signal.
        # TODO: Properly group propertyChanged signals by whether they are triggered by the same user interaction.
        self._change_timer = QTimer()
        self._change_timer.setSingleShot(True)
        self._change_timer.setInterval(500)
        self.determineAutoSlicing()
        Preferences.getInstance().preferenceChanged.connect(self._onPreferencesChanged)

    ##  Terminate the engine process.
    #
    #   This function should terminate the engine process.
    #   Called when closing the application.
    def close(self):
        # Terminate CuraEngine if it is still running at this point
        self._terminate()

    ##  Get the command that is used to call the engine.
    #   This is useful for debugging and used to actually start the engine.
    #   \return list of commands and args / parameters.
    def getEngineCommand(self):
        json_path = Resources.getPath(Resources.DefinitionContainers, "fdmprinter.def.json")
        return [Preferences.getInstance().getValue("backend/location"), "connect", "127.0.0.1:{0}".format(self._port), "-j", json_path, ""]

    ##  Emitted when we get a message containing print duration and material amount.
    #   This also implies the slicing has finished.
    #   \param time The amount of time the print will take.
    #   \param material_amount The amount of material the print will use.
    printDurationMessage = Signal()

    ##  Emitted when the slicing process starts.
    slicingStarted = Signal()

    ##  Emitted when the slicing process is aborted forcefully.
    slicingCancelled = Signal()

    @pyqtSlot()
    def stopSlicing(self):
        self.backendStateChange.emit(BackendState.NotStarted)
        if self._slicing:  # We were already slicing. Stop the old job.
            self._terminate()
            self._createSocket()

        if self._process_layers_job:  # We were processing layers. Stop that, the layers are going to change soon.
            self._process_layers_job.abort()
            self._process_layers_job = None

        if self._error_message:
            self._error_message.hide()

    ##  Manually triggers a reslice
    @pyqtSlot()
    def forceSlice(self):
        if self._use_timer:
            self._change_timer.start()
        else:
            self.slice()

    ##  Perform a slice of the scene.
    def slice(self):
        self._slice_start_time = time()
        if not self._need_slicing:
            self.processingProgress.emit(1.0)
            self.backendStateChange.emit(BackendState.Done)
            Logger.log("w", "Slice unnecessary, nothing has changed that needs reslicing.")
            return
        if Application.getInstance().getPrintInformation():
            Application.getInstance().getPrintInformation().setToZeroPrintInformation()

        self._stored_layer_data = []
        self._stored_optimized_layer_data = []

        if self._process is None:
            self._createSocket()
        self.stopSlicing()
        self._engine_is_fresh = False  # Yes we're going to use the engine

        self.processingProgress.emit(0.0)
        self.backendStateChange.emit(BackendState.NotStarted)

        self._scene.gcode_list = []
        self._slicing = True
        self.slicingStarted.emit()

        slice_message = self._socket.createMessage("cura.proto.Slice")
        self._start_slice_job = StartSliceJob.StartSliceJob(slice_message)
        self._start_slice_job.start()
        self._start_slice_job.finished.connect(self._onStartSliceCompleted)

    ##  Terminate the engine process.
    #   Start the engine process by calling _createSocket()
    def _terminate(self):
        self._slicing = False
        self._stored_layer_data = []
        self._stored_optimized_layer_data = []
        if self._start_slice_job is not None:
            self._start_slice_job.cancel()

        self.slicingCancelled.emit()
        self.processingProgress.emit(0)
        Logger.log("d", "Attempting to kill the engine process")

        if Application.getInstance().getCommandLineOption("external-backend", False):
            return

        if self._process is not None:
            Logger.log("d", "Killing engine process")
            try:
                self._process.terminate()
                Logger.log("d", "Engine process is killed. Received return code %s", self._process.wait())
                self._process = None

            except Exception as e:  # terminating a process that is already terminating causes an exception, silently ignore this.
                Logger.log("d", "Exception occurred while trying to kill the engine %s", str(e))

    ##  Event handler to call when the job to initiate the slicing process is
    #   completed.
    #
    #   When the start slice job is successfully completed, it will be happily
    #   slicing. This function handles any errors that may occur during the
    #   bootstrapping of a slice job.
    #
    #   \param job The start slice job that was just finished.
    def _onStartSliceCompleted(self, job):
        if self._error_message:
            self._error_message.hide()

        # Note that cancelled slice jobs can still call this method.
        if self._start_slice_job is job:
            self._start_slice_job = None

        if job.isCancelled() or job.getError() or job.getResult() == StartSliceJob.StartJobResult.Error:
            return

        if job.getResult() == StartSliceJob.StartJobResult.MaterialIncompatible:
            if Application.getInstance().platformActivity:
                self._error_message = Message(catalog.i18nc("@info:status",
                                            "Unable to slice with the current material as it is incompatible with the selected machine or configuration."), title = catalog.i18nc("@info:title", "Unable to slice"))
                self._error_message.show()
                self.backendStateChange.emit(BackendState.Error)
            else:
                self.backendStateChange.emit(BackendState.NotStarted)
            return

        if job.getResult() == StartSliceJob.StartJobResult.SettingError:
            if Application.getInstance().platformActivity:
                extruders = list(ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId()))
                error_keys = []
                for extruder in extruders:
                    error_keys.extend(extruder.getErrorKeys())
                if not extruders:
                    error_keys = self._global_container_stack.getErrorKeys()
                error_labels = set()
                for key in error_keys:
                    for stack in [self._global_container_stack] + extruders: #Search all container stacks for the definition of this setting. Some are only in an extruder stack.
                        definitions = stack.getBottom().findDefinitions(key = key)
                        if definitions:
                            break #Found it! No need to continue search.
                    else: #No stack has a definition for this setting.
                        Logger.log("w", "When checking settings for errors, unable to find definition for key: {key}".format(key = key))
                        continue
                    error_labels.add(definitions[0].label)

                error_labels = ", ".join(error_labels)
                self._error_message = Message(catalog.i18nc("@info:status", "Unable to slice with the current settings. The following settings have errors: {0}".format(error_labels)),
                                              title = catalog.i18nc("@info:title", "Unable to slice"))
                self._error_message.show()
                self.backendStateChange.emit(BackendState.Error)
            else:
                self.backendStateChange.emit(BackendState.NotStarted)
            return

        if job.getResult() == StartSliceJob.StartJobResult.BuildPlateError:
            if Application.getInstance().platformActivity:
                self._error_message = Message(catalog.i18nc("@info:status", "Unable to slice because the prime tower or prime position(s) are invalid."),
                                              title = catalog.i18nc("@info:title", "Unable to slice"))
                self._error_message.show()
                self.backendStateChange.emit(BackendState.Error)
            else:
                self.backendStateChange.emit(BackendState.NotStarted)

        if job.getResult() == StartSliceJob.StartJobResult.NothingToSlice:
            if Application.getInstance().platformActivity:
                self._error_message = Message(catalog.i18nc("@info:status", "Nothing to slice because none of the models fit the build volume. Please scale or rotate models to fit."),
                                              title = catalog.i18nc("@info:title", "Unable to slice"))
                self._error_message.show()
                self.backendStateChange.emit(BackendState.Error)
            else:
                self.backendStateChange.emit(BackendState.NotStarted)
            return
        # Preparation completed, send it to the backend.
        self._socket.sendMessage(job.getSliceMessage())

        # Notify the user that it's now up to the backend to do it's job
        self.backendStateChange.emit(BackendState.Processing)

        Logger.log("d", "Sending slice message took %s seconds", time() - self._slice_start_time )

    ##  Determine enable or disable auto slicing. Return True for enable timer and False otherwise.
    #   It disables when
    #   - preference auto slice is off
    #   - decorator isBlockSlicing is found (used in g-code reader)
    def determineAutoSlicing(self):
        enable_timer = True

        if not Preferences.getInstance().getValue("general/auto_slice"):
            enable_timer = False
        for node in DepthFirstIterator(self._scene.getRoot()):
            if node.callDecoration("isBlockSlicing"):
                enable_timer = False
                self.backendStateChange.emit(BackendState.Disabled)
            gcode_list = node.callDecoration("getGCodeList")
            if gcode_list is not None:
                self._scene.gcode_list = gcode_list

        if self._use_timer == enable_timer:
            return self._use_timer
        if enable_timer:
            self.backendStateChange.emit(BackendState.NotStarted)
            self.enableTimer()
            return True
        else:
            self.disableTimer()
            return False

    ##  Listener for when the scene has changed.
    #
    #   This should start a slice if the scene is now ready to slice.
    #
    #   \param source The scene node that was changed.
    def _onSceneChanged(self, source):
        if type(source) is not SceneNode:
            return

        root_scene_nodes_changed = False
        if source == self._scene.getRoot():
            num_objects = 0
            for node in DepthFirstIterator(self._scene.getRoot()):
                # Only count sliceable objects
                if node.callDecoration("isSliceable"):
                    num_objects += 1
            if num_objects != self._last_num_objects:
                self._last_num_objects = num_objects
                root_scene_nodes_changed = True
            else:
                return

        if not source.callDecoration("isGroup") and not root_scene_nodes_changed:
            if source.getMeshData() is None:
                return
            if source.getMeshData().getVertices() is None:
                return

        if self._tool_active:
            # do it later, each source only has to be done once
            if source not in self._postponed_scene_change_sources:
                self._postponed_scene_change_sources.append(source)
            return

        self.needsSlicing()
        self.stopSlicing()
        self._onChanged()

    ##  Called when an error occurs in the socket connection towards the engine.
    #
    #   \param error The exception that occurred.
    def _onSocketError(self, error):
        if Application.getInstance().isShuttingDown():
            return

        super()._onSocketError(error)
        if error.getErrorCode() == Arcus.ErrorCode.Debug:
            return

        self._terminate()
        self._createSocket()

        if error.getErrorCode() not in [Arcus.ErrorCode.BindFailedError, Arcus.ErrorCode.ConnectionResetError, Arcus.ErrorCode.Debug]:
            Logger.log("w", "A socket error caused the connection to be reset")

    ##  Remove old layer data (if any)
    def _clearLayerData(self):
        for node in DepthFirstIterator(self._scene.getRoot()):
            if node.callDecoration("getLayerData"):
                node.getParent().removeChild(node)
                break

    ##  Convenient function: set need_slicing, emit state and clear layer data
    def needsSlicing(self):
        self.stopSlicing()
        self._need_slicing = True
        self.processingProgress.emit(0.0)
        self.backendStateChange.emit(BackendState.NotStarted)
        if not self._use_timer:
            # With manually having to slice, we want to clear the old invalid layer data.
            self._clearLayerData()

    ##  A setting has changed, so check if we must reslice.
    # \param instance The setting instance that has changed.
    # \param property The property of the setting instance that has changed.
    def _onSettingChanged(self, instance, property):
        if property == "value":  # Only reslice if the value has changed.
            self.needsSlicing()
            self._onChanged()

        elif property == "validationState":
            if self._use_timer:
                self._is_error_check_scheduled = True
                self._change_timer.stop()

    def _onStackErrorCheckFinished(self):
        self._is_error_check_scheduled = False
        if self._need_slicing:
            self.needsSlicing()
            self._onChanged()

    ##  Called when a sliced layer data message is received from the engine.
    #
    #   \param message The protobuf message containing sliced layer data.
    def _onLayerMessage(self, message):
        self._stored_layer_data.append(message)

    ##  Called when an optimized sliced layer data message is received from the engine.
    #
    #   \param message The protobuf message containing sliced layer data.
    def _onOptimizedLayerMessage(self, message):
        self._stored_optimized_layer_data.append(message)

    ##  Called when a progress message is received from the engine.
    #
    #   \param message The protobuf message containing the slicing progress.
    def _onProgressMessage(self, message):
        self.processingProgress.emit(message.amount)
        self.backendStateChange.emit(BackendState.Processing)

    ##  Called when the engine sends a message that slicing is finished.
    #
    #   \param message The protobuf message signalling that slicing is finished.
    def _onSlicingFinishedMessage(self, message):
        self.backendStateChange.emit(BackendState.Done)
        self.processingProgress.emit(1.0)

        for line in self._scene.gcode_list:
            replaced = line.replace("{print_time}", str(Application.getInstance().getPrintInformation().currentPrintTime.getDisplayString(DurationFormat.Format.ISO8601)))
            replaced = replaced.replace("{filament_amount}", str(Application.getInstance().getPrintInformation().materialLengths))
            replaced = replaced.replace("{filament_weight}", str(Application.getInstance().getPrintInformation().materialWeights))
            replaced = replaced.replace("{filament_cost}", str(Application.getInstance().getPrintInformation().materialCosts))
            replaced = replaced.replace("{jobname}", str(Application.getInstance().getPrintInformation().jobName))

            self._scene.gcode_list[self._scene.gcode_list.index(line)] = replaced

        self._slicing = False
        self._need_slicing = False
        Logger.log("d", "Slicing took %s seconds", time() - self._slice_start_time )
        if self._layer_view_active and (self._process_layers_job is None or not self._process_layers_job.isRunning()):
            self._process_layers_job = ProcessSlicedLayersJob.ProcessSlicedLayersJob(self._stored_optimized_layer_data)
            self._process_layers_job.finished.connect(self._onProcessLayersFinished)
            self._process_layers_job.start()
            self._stored_optimized_layer_data = []

    ##  Called when a g-code message is received from the engine.
    #
    #   \param message The protobuf message containing g-code, encoded as UTF-8.
    def _onGCodeLayerMessage(self, message):
        self._scene.gcode_list.append(message.data.decode("utf-8", "replace"))

    ##  Called when a g-code prefix message is received from the engine.
    #
    #   \param message The protobuf message containing the g-code prefix,
    #   encoded as UTF-8.
    def _onGCodePrefixMessage(self, message):
        self._scene.gcode_list.insert(0, message.data.decode("utf-8", "replace"))

    ##  Creates a new socket connection.
    def _createSocket(self):
        super()._createSocket(os.path.abspath(os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "Cura.proto")))
        self._engine_is_fresh = True

    ##  Called when anything has changed to the stuff that needs to be sliced.
    #
    #   This indicates that we should probably re-slice soon.
    def _onChanged(self, *args, **kwargs):
        self.needsSlicing()
        if self._use_timer:
            # if the error check is scheduled, wait for the error check finish signal to trigger auto-slice,
            # otherwise business as usual
            if self._is_error_check_scheduled:
                self._change_timer.stop()
            else:
                self._change_timer.start()

    ##  Called when a print time message is received from the engine.
    #
    #   \param message The protobuf message containing the print time per feature and
    #   material amount per extruder
    def _onPrintTimeMaterialEstimates(self, message):
        material_amounts = []
        for index in range(message.repeatedMessageCount("materialEstimates")):
            material_amounts.append(message.getRepeatedMessage("materialEstimates", index).material_amount)

        times = self._parseMessagePrintTimes(message)
        self.printDurationMessage.emit(times, material_amounts)

    ##  Called for parsing message to retrieve estimated time per feature
    #
    #   \param message The protobuf message containing the print time per feature
    def _parseMessagePrintTimes(self, message):

        result = {
            "inset_0": message.time_inset_0,
            "inset_x": message.time_inset_x,
            "skin": message.time_skin,
            "infill": message.time_infill,
            "support_infill": message.time_support_infill,
            "support_interface": message.time_support_interface,
            "support": message.time_support,
            "skirt": message.time_skirt,
            "travel": message.time_travel,
            "retract": message.time_retract,
            "none": message.time_none
        }
        return result

    ##  Called when the back-end connects to the front-end.
    def _onBackendConnected(self):
        if self._restart:
            self._restart = False
            self._onChanged()

    ##  Called when the user starts using some tool.
    #
    #   When the user starts using a tool, we should pause slicing to prevent
    #   continuously slicing while the user is dragging some tool handle.
    #
    #   \param tool The tool that the user is using.
    def _onToolOperationStarted(self, tool):
        self._tool_active = True  # Do not react on scene change
        self.disableTimer()
        # Restart engine as soon as possible, we know we want to slice afterwards
        if not self._engine_is_fresh:
            self._terminate()
            self._createSocket()

    ##  Called when the user stops using some tool.
    #
    #   This indicates that we can safely start slicing again.
    #
    #   \param tool The tool that the user was using.
    def _onToolOperationStopped(self, tool):
        self._tool_active = False  # React on scene change again
        self.determineAutoSlicing()  # Switch timer on if appropriate
        # Process all the postponed scene changes
        while self._postponed_scene_change_sources:
            source = self._postponed_scene_change_sources.pop(0)
            self._onSceneChanged(source)

    ##  Called when the user changes the active view mode.
    def _onActiveViewChanged(self):
        if Application.getInstance().getController().getActiveView():
            view = Application.getInstance().getController().getActiveView()
            if view.getPluginId() == "LayerView":  # If switching to layer view, we should process the layers if that hasn't been done yet.
                self._layer_view_active = True
                # There is data and we're not slicing at the moment
                # if we are slicing, there is no need to re-calculate the data as it will be invalid in a moment.
                if self._stored_optimized_layer_data and not self._slicing:
                    self._process_layers_job = ProcessSlicedLayersJob.ProcessSlicedLayersJob(self._stored_optimized_layer_data)
                    self._process_layers_job.finished.connect(self._onProcessLayersFinished)
                    self._process_layers_job.start()
                    self._stored_optimized_layer_data = []
            else:
                self._layer_view_active = False

    ##  Called when the back-end self-terminates.
    #
    #   We should reset our state and start listening for new connections.
    def _onBackendQuit(self):
        if not self._restart:
            if self._process:
                Logger.log("d", "Backend quit with return code %s. Resetting process and socket.", self._process.wait())
                self._process = None

    ##  Called when the global container stack changes
    def _onGlobalStackChanged(self):
        if self._global_container_stack:
            self._global_container_stack.propertyChanged.disconnect(self._onSettingChanged)
            self._global_container_stack.containersChanged.disconnect(self._onChanged)
            extruders = list(ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId()))

            for extruder in extruders:
                extruder.propertyChanged.disconnect(self._onSettingChanged)
                extruder.containersChanged.disconnect(self._onChanged)

        self._global_container_stack = Application.getInstance().getGlobalContainerStack()

        if self._global_container_stack:
            self._global_container_stack.propertyChanged.connect(self._onSettingChanged)  # Note: Only starts slicing when the value changed.
            self._global_container_stack.containersChanged.connect(self._onChanged)
            extruders = list(ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId()))
            for extruder in extruders:
                extruder.propertyChanged.connect(self._onSettingChanged)
                extruder.containersChanged.connect(self._onChanged)
            self._onChanged()

    def _onProcessLayersFinished(self, job):
        self._process_layers_job = None

    ##  Connect slice function to timer.
    def enableTimer(self):
        if not self._use_timer:
            self._change_timer.timeout.connect(self.slice)
            self._use_timer = True

    ##  Disconnect slice function from timer.
    #   This means that slicing will not be triggered automatically
    def disableTimer(self):
        if self._use_timer:
            self._use_timer = False
            self._change_timer.timeout.disconnect(self.slice)

    def _onPreferencesChanged(self, preference):
        if preference != "general/auto_slice":
            return
        auto_slice = self.determineAutoSlicing()
        if auto_slice:
            self._change_timer.start()

    ##   Tickle the backend so in case of auto slicing, it starts the timer.
    def tickle(self):
        if self._use_timer:
            self._change_timer.start()
Exemplo n.º 46
0
class PopupWin(QtWidgets.QWidget):

    # 构造函数,调用初始化函数
    def __init__(self):
        super().__init__()
        self._init()

    # 初始化函数,设置弹框窗体大小、样式、布局、窗体内的关闭、查看按钮等控件、不同邮件类型的处理、弹框动画、动画起始位置
    def _init(self):
        # 设置widget大小
        self.resize(450, 200)
        # 隐藏任务栏,去掉边框,顶层显示
        self.setWindowFlags(Qt.Tool | Qt.X11BypassWindowManagerHint
                            | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
        # 设置样式表
        self.setStyleSheet("QWidget#widgetTitle {\n"
                           "    background-color: rgb(76, 169, 106);\n"
                           "}\n"
                           "QWidget#widgetBottom {\n"
                           "    border-top-style: solid;\n"
                           "    border-top-width: 2px;\n"
                           "    border-top-color: rgb(185, 218, 201);\n"
                           "}\n"
                           "QLabel#labelTitle {\n"
                           "    color: rgb(255, 255, 255);\n"
                           "}\n"
                           "QLabel#labelContent {\n"
                           "    padding: 5px;\n"
                           "}\n"
                           "QPushButton {\n"
                           "    border: none;\n"
                           "    background: transparent;\n"
                           "}\n"
                           "QPushButton#buttonClose {\n"
                           "    font-family: \"webdings\";\n"
                           "    color: rgb(255, 255, 255);\n"
                           "}\n"
                           "QPushButton#buttonClose:hover {\n"
                           "    background-color: rgb(212, 64, 39);\n"
                           "}\n"
                           "QPushButton#buttonView {\n"
                           "    color: rgb(255, 255, 255);\n"
                           "    border-radius: 5px;\n"
                           "    border: solid 1px rgb(76, 169, 106);\n"
                           "    background-color: rgb(76, 169, 106);\n"
                           "}\n"
                           "QPushButton#buttonView:hover {\n"
                           "    color: rgb(0, 0, 0);\n"
                           "}")
        # 设置横着的布局,总体布局
        self.verticalLayout = QtWidgets.QVBoxLayout(self)
        # 设置布局内预留的空白边框宽度
        self.verticalLayout.setContentsMargins(0, 0, 0, 0)
        # 设置布局内各个空间横向和纵向的间距6px
        self.verticalLayout.setSpacing(6)
        self.verticalLayout.setObjectName("verticalLayout")
        # 标题栏
        self.widgetTitle = QtWidgets.QWidget(self)
        self.widgetTitle.setMinimumSize(QtCore.QSize(0, 26))
        self.widgetTitle.setObjectName("widgetTitle")
        # 竖着的布局
        self.horizontalLayout_1 = QtWidgets.QHBoxLayout(self.widgetTitle)
        # 设置布局内预留的空白边框宽度
        self.horizontalLayout_1.setContentsMargins(10, 0, 0, 0)
        # 设置布局内各个空间横向和纵向的间距0px
        self.horizontalLayout_1.setSpacing(0)
        self.horizontalLayout_1.setObjectName("horizontalLayout_1")
        # 标题栏标签
        self.labelTitle = QtWidgets.QLabel(self.widgetTitle)
        self.labelTitle.setText("新邮件")
        self.labelTitle.setObjectName("labelTitle")
        # 竖着的布局增加标题栏标签
        self.horizontalLayout_1.addWidget(self.labelTitle)
        # 添加空白区宽40px、高20px,宽度尽可能扩大,高度尽可能缩小
        spacerItem = QtWidgets.QSpacerItem(40, 20,
                                           QtWidgets.QSizePolicy.Expanding,
                                           QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_1.addItem(spacerItem)
        # 关闭按钮
        self.buttonClose = QtWidgets.QPushButton(self.widgetTitle)
        self.buttonClose.setText("r")
        self.buttonClose.setMinimumSize(QtCore.QSize(30, 30))
        self.buttonClose.setMaximumSize(QtCore.QSize(30, 30))
        self.buttonClose.setObjectName("buttonClose")
        # 竖着的布局增加关闭按钮
        self.horizontalLayout_1.addWidget(self.buttonClose)
        # 横着的布局添加竖着的布局的标题栏在上面
        self.verticalLayout.addWidget(self.widgetTitle)
        # 增加放新邮件内容的窗口
        self.mailInfo = QtWidgets.QWidget(self)
        self.mailInfo.resize(420, 130)
        self.mailInfo.setObjectName("mailInfo")
        # 在邮件内容窗体中添加竖着的布局
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.mailInfo)
        # 设置布局内预留的空白边框宽度
        self.horizontalLayout_2.setContentsMargins(10, 0, 0, 0)
        # 设置布局内各个空间横向和纵向的间距0px
        self.horizontalLayout_2.setSpacing(10)
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        # 邮件图标(正常邮件,垃圾邮件,星标邮件)
        self.mailPicLabel = QtWidgets.QLabel(self)
        self.mailPicLabel.setMinimumSize(100, 100)
        self.mailPicLabel.setMaximumSize(100, 100)
        # 普通邮件图标
        self.normalPic = QtGui.QPixmap("./pic/normalMail.png")
        # 垃圾邮件图标
        self.junkPic = QtGui.QPixmap("./pic/junkMail.png")
        # 星标邮件图标
        self.starPic = QtGui.QPixmap("./pic/starMail.png")
        # 默认邮件图标
        self.defaultPic = QtGui.QPixmap("./pic/defaultMail.png")
        # 让图片自适应label大小
        self.mailPicLabel.setScaledContents(True)
        self.mailPicLabel.setObjectName("mailPicLabel")
        self.horizontalLayout_2.addWidget(self.mailPicLabel)
        self.mailInfoWidget = QtWidgets.QWidget(self)
        # 添加装载邮件信息的布局
        self.mailInfoLayout = QtWidgets.QVBoxLayout(self.mailInfoWidget)
        # 设置布局内预留的空白边框宽度
        self.mailInfoLayout.setContentsMargins(0, 0, 0, 0)
        # 设置布局内各个空间横向和纵向的间距6px
        self.mailInfoLayout.setSpacing(6)
        self.mailInfoLayout.setObjectName("mailInfoLayout")
        # 主题标签
        self.subject = QtWidgets.QLabel(self)
        self.subject.setText("")
        # 自动换行
        self.subject.setWordWrap(True)
        self.subject.setObjectName("subject")
        self.mailInfoLayout.addWidget(self.subject)
        # 发件人标签
        self.sender = QtWidgets.QLabel(self)
        self.sender.setText("")
        # 自动换行
        self.sender.setWordWrap(True)
        self.sender.setObjectName("sender")
        self.mailInfoLayout.addWidget(self.sender)
        # 邮件内容标签
        self.body = QtWidgets.QLabel(self)
        self.body.setText("")
        self.body.setObjectName("body")
        self.mailInfoLayout.addWidget(self.body)
        self.horizontalLayout_2.addWidget(self.mailInfoWidget)
        self.verticalLayout.addWidget(self.mailInfo)
        self.verticalLayout.setObjectName("verticalLayout")
        # 底部的widget
        self.widgetBottom = QtWidgets.QWidget(self)
        self.widgetBottom.setObjectName("widgetBottom")
        # 底部竖着的布局
        self.horizontalLayout = QtWidgets.QHBoxLayout(self.widgetBottom)
        # 设置布局内预留的空白边框宽度
        self.horizontalLayout.setContentsMargins(0, 5, 5, 5)
        # 设置布局内各个空间横向和纵向的间距0px
        self.horizontalLayout.setSpacing(0)
        self.horizontalLayout.setObjectName("horizontalLayout")
        # 添加空白区宽170px、高20px,宽度尽可能扩大,高度尽可能缩小
        spacerItem1 = QtWidgets.QSpacerItem(170, 20,
                                            QtWidgets.QSizePolicy.Expanding,
                                            QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem1)
        # 查看按钮
        self.buttonView = QtWidgets.QPushButton(self.widgetBottom)
        self.buttonView.setText("查看")
        self.buttonView.setObjectName("buttonView")
        self.buttonView.setMinimumSize(QtCore.QSize(80, 30))
        # 设置光标(手指)
        self.buttonView.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
        self.buttonView.setObjectName("buttonView")
        self.horizontalLayout.addWidget(self.buttonView)
        self.verticalLayout.addWidget(self.widgetBottom)
        # 两个空间1:1
        self.verticalLayout.setStretch(1, 1)

        # 信号:点击关闭按钮 槽函数:以动画形式关闭窗口
        self.buttonClose.clicked.connect(self.onclose)
        # 鼠标是否在窗口的标志
        self.mouseIsInWidget = False
        # 是否在显示标志
        self.isShow = True
        # 超时标志
        self.isTimeOut = False
        # 页面停留时间是5s(ok)
        self.timeout = 5000
        # 计时器, 计时开始后每1秒进入一次关闭动画的函数
        # 2019/9/6 14:48 debug 计时器乱套
        # 将self.timer = QTimer(self) 改为 self.timer = QTimer(self, timeout=self.closeAnimation)
        self.timer = QTimer(self, timeout=self.closeAnimation)
        # 获取桌面
        self.deskTop = QApplication.instance().desktop()
        # 获取窗口开始位置
        self.startPos = QPoint(
            self.deskTop.screenGeometry().width() - self.width() - 5,
            self.deskTop.screenGeometry().height())
        # 获取窗口弹出结束位置
        self.endPos = QPoint(
            self.deskTop.screenGeometry().width() - self.width() - 5,
            self.deskTop.availableGeometry().height() - self.height() - 5)
        # 初始化位置到右下角
        self.move(self.startPos)
        # 添加动画(b'pos'是弹出, b'windowOpacity'是渐隐)
        self.animation = QPropertyAnimation(self, b'pos')
        # 动画结束的信号连接关闭并清理窗口的槽函数
        self.animation.finished.connect(self.animationEnd)
        # 设置动画持续时间1s
        self.animation.setDuration(1000)

    # 槽函数,点击关闭按钮后0.1s启动弹回动画
    def onclose(self):
        self.isShow = False
        QTimer.singleShot(100, self.closeAnimation)

    # 重写show()函数,参数分别是邮件类型、主题、发件人、信体 (type: 正常邮件,垃圾邮件,星标邮件)
    def show(self, type, subject, sender, body):
        # 停止计时器,防止第二个弹窗弹出时之前的定时器出现问题
        self.timer.stop()
        # 先隐藏
        self.hide()
        # 初始化位置到右下角
        self.move(self.startPos)
        # 调用父类方法
        super(PopupWin, self).show()
        # 根据邮件种类切换图标
        if type == "正常邮件":
            self.mailPicLabel.setPixmap(self.normalPic)
        elif type == "垃圾邮件":
            self.mailPicLabel.setPixmap(self.junkPic)
        elif type == "星标邮件":
            self.mailPicLabel.setPixmap(self.starPic)
        else:
            self.mailPicLabel.setPixmap(self.defaultPic)
        # 设置邮件主题、发件人、信体(控制长度)
        self.subject.setText(subject)
        self.sender.setText(sender)
        try:
            bodyLen = len(body)
            if bodyLen > 40:
                # 只读取前50个字符, 每20个字符添加一个\n
                bodyStr = body[0:20] + '\n' + body[20:40] + '...'
            elif bodyLen > 20 and bodyLen <= 40:
                bodyStr = body[0:20] + '\n' + body[20:bodyLen] + '...'
            else:
                bodyStr = body
            self.body.setText(bodyStr)
        except Exception as e:
            traceback.print_exc()
        return self

    # 弹窗从桌面右下角弹出的动画
    def showAnimation(self):
        # 显示动画
        self.isShow = True
        # 先停止之前的动画,重新开始
        self.animation.stop()
        # 2019/9/6 14:44 debug 设置动画起始和停止的位置
        self.animation.setStartValue(self.pos())
        self.animation.setEndValue(self.endPos)
        # 开始动画
        self.animation.start()
        # 弹出5秒后,如果没有焦点则弹回去
        self.timer.start(self.timeout)

    # 弹窗弹回桌面右下角的动画
    def closeAnimation(self):
        # 计时器开始
        self.timer.start()
        # 关闭动画
        # 如果鼠标点击了closeButton并停留其上,则执行下面的操作
        if self.isShow:
            if self.mouseIsInWidget:
                # 如果弹出后倒计时5秒后鼠标还在窗体里,则鼠标移开后后需要主动触发关闭
                self.isTimeOut = True
                return
        # 计时器停止
        self.timer.stop()
        # 不再show
        self.isShow = False
        self.animation.stop()
        # 设置动画起始和停止的位置
        # 2019/9/6 14:43 debug, 起始位置有偏差
        # 将setStartValue(self.endPos())换为setStartValue(self.pos())
        self.animation.setStartValue(self.pos())
        self.animation.setEndValue(self.startPos)
        self.animation.start()
        # 动画结束, 关闭当前窗口并清理
        self.animation.finished.connect(self.animationEnd)

    # 动画结束,关闭窗口并清理
    def animationEnd(self):
        # 动画结束,关闭窗口并清理
        if not self.isShow:
            # 关闭窗口
            self.close()
            # 停止计时器
            self.timer.stop()

    # 重写鼠标进入窗口事件,变量mouseIsInWidget为True
    def enterEvent(self, event):
        super().enterEvent(event)
        self.mouseIsInWidget = True

    # 重写鼠标离开窗口事件,变量mouseIsInWidget为False
    def leaveEvent(self, event):
        super().leaveEvent(event)
        self.mouseIsInWidget = False
Exemplo n.º 47
0
class TabBar(QTabBar):

    """Custom tab bar with our own style.

    FIXME: Dragging tabs doesn't look as nice as it does in QTabBar.  However,
    fixing this would be a lot of effort, so we'll postpone it until we're
    reimplementing drag&drop for other reasons.

    https://github.com/The-Compiler/qutebrowser/issues/126

    Attributes:
        vertical: When the tab bar is currently vertical.
        win_id: The window ID this TabBar belongs to.
    """

    def __init__(self, win_id, parent=None):
        super().__init__(parent)
        self._win_id = win_id
        self.setStyle(TabBarStyle(self.style()))
        self.set_font()
        config_obj = objreg.get('config')
        config_obj.changed.connect(self.set_font)
        self.vertical = False
        self._auto_hide_timer = QTimer()
        self._auto_hide_timer.setSingleShot(True)
        self._auto_hide_timer.setInterval(
            config.get('tabs', 'show-switching-delay'))
        self._auto_hide_timer.timeout.connect(self._tabhide)
        self.setAutoFillBackground(True)
        self.set_colors()
        config_obj.changed.connect(self.set_colors)
        QTimer.singleShot(0, self._tabhide)
        config_obj.changed.connect(self.on_tab_colors_changed)
        config_obj.changed.connect(self.on_show_switching_delay_changed)
        config_obj.changed.connect(self.tabs_show)

    def __repr__(self):
        return utils.get_repr(self, count=self.count())

    @config.change_filter('tabs', 'show')
    def tabs_show(self):
        """Hide or show tab bar if needed when tabs->show got changed."""
        self._tabhide()

    @config.change_filter('tabs', 'show-switching-delay')
    def on_show_switching_delay_changed(self):
        """Set timer interval when tabs->show-switching-delay got changed."""
        self._auto_hide_timer.setInterval(
            config.get('tabs', 'show-switching-delay'))

    def on_change(self):
        """Show tab bar when current tab got changed."""
        show = config.get('tabs', 'show')
        if show == 'switching':
            self.show()
            self._auto_hide_timer.start()

    def _tabhide(self):
        """Hide the tab bar if needed."""
        show = config.get('tabs', 'show')
        show_never = show == 'never'
        switching = show == 'switching'
        multiple = show == 'multiple'
        if show_never or (multiple and self.count() == 1) or switching:
            self.hide()
        else:
            self.show()

    def set_tab_data(self, idx, key, value):
        """Set tab data as a dictionary."""
        if not 0 <= idx < self.count():
            raise IndexError("Tab index ({}) out of range ({})!".format(
                idx, self.count()))
        data = self.tabData(idx)
        if data is None:
            data = {}
        data[key] = value
        self.setTabData(idx, data)

    def tab_data(self, idx, key):
        """Get tab data for a given key."""
        if not 0 <= idx < self.count():
            raise IndexError("Tab index ({}) out of range ({})!".format(
                idx, self.count()))
        data = self.tabData(idx)
        if data is None:
            data = {}
        return data[key]

    def page_title(self, idx):
        """Get the tab title user data.

        Args:
            idx: The tab index to get the title for.
            handle_unset: Whether to return an empty string on KeyError.
        """
        try:
            return self.tab_data(idx, 'page-title')
        except KeyError:
            return ''

    def refresh(self):
        """Properly repaint the tab bar and relayout tabs."""
        # This is a horrible hack, but we need to do this so the underlying Qt
        # code sets layoutDirty so it actually relayouts the tabs.
        self.setIconSize(self.iconSize())

    @config.change_filter('fonts', 'tabbar')
    def set_font(self):
        """Set the tab bar font."""
        self.setFont(config.get('fonts', 'tabbar'))
        size = self.fontMetrics().height() - 2
        self.setIconSize(QSize(size, size))

    @config.change_filter('colors', 'tabs.bg.bar')
    def set_colors(self):
        """Set the tab bar colors."""
        p = self.palette()
        p.setColor(QPalette.Window, config.get('colors', 'tabs.bg.bar'))
        self.setPalette(p)

    @pyqtSlot(str, str)
    def on_tab_colors_changed(self, section, option):
        """Set the tab colors."""
        if section == 'colors' and option.startswith('tabs.'):
            self.update()

    def mousePressEvent(self, e):
        """Override mousePressEvent to close tabs if configured."""
        button = config.get('tabs', 'close-mouse-button')
        if (e.button() == Qt.RightButton and button == 'right' or
                e.button() == Qt.MiddleButton and button == 'middle'):
            idx = self.tabAt(e.pos())
            if idx != -1:
                e.accept()
                self.tabCloseRequested.emit(idx)
                return
        super().mousePressEvent(e)

    def minimumTabSizeHint(self, index):
        """Set the minimum tab size to indicator/icon/... text.

        Args:
            index: The index of the tab to get a size hint for.

        Return:
            A QSize.
        """
        icon = self.tabIcon(index)
        padding = config.get('tabs', 'padding')
        padding_h = padding.left + padding.right
        padding_v = padding.top + padding.bottom
        if icon.isNull():
            icon_size = QSize(0, 0)
        else:
            extent = self.style().pixelMetric(QStyle.PM_TabBarIconSize, None,
                                              self)
            icon_size = icon.actualSize(QSize(extent, extent))
            padding_h += self.style().pixelMetric(
                PixelMetrics.icon_padding, None, self)
        indicator_width = config.get('tabs', 'indicator-width')
        height = self.fontMetrics().height() + padding_v
        width = (self.fontMetrics().width('\u2026') + icon_size.width() +
                 padding_h + indicator_width)
        return QSize(width, height)

    def tabSizeHint(self, index):
        """Override tabSizeHint so all tabs are the same size.

        https://wiki.python.org/moin/PyQt/Customising%20tab%20bars

        Args:
            index: The index of the tab.

        Return:
            A QSize.
        """
        minimum_size = self.minimumTabSizeHint(index)
        height = minimum_size.height()
        if self.vertical:
            confwidth = str(config.get('tabs', 'width'))
            if confwidth.endswith('%'):
                main_window = objreg.get('main-window', scope='window',
                                         window=self._win_id)
                perc = int(confwidth.rstrip('%'))
                width = main_window.width() * perc / 100
            else:
                width = int(confwidth)
            size = QSize(max(minimum_size.width(), width), height)
        elif self.count() == 0:
            # This happens on startup on OS X.
            # We return it directly rather than setting `size' because we don't
            # want to ensure it's valid in this special case.
            return QSize()
        elif self.count() * minimum_size.width() > self.width():
            # If we don't have enough space, we return the minimum size so we
            # get scroll buttons as soon as needed.
            size = minimum_size
        else:
            # If we *do* have enough space, tabs should occupy the whole window
            # width.
            width = self.width() / self.count()
            # If width is not divisible by count, add a pixel to some tabs so
            # that there is no ugly leftover space.
            if index < self.width() % self.count():
                width += 1
            size = QSize(width, height)
        qtutils.ensure_valid(size)
        return size

    def paintEvent(self, _e):
        """Override paintEvent to draw the tabs like we want to."""
        # pylint: disable=bad-config-call
        # WORKAROUND for https://bitbucket.org/logilab/astroid/issue/104
        p = QStylePainter(self)
        selected = self.currentIndex()
        for idx in range(self.count()):
            tab = QStyleOptionTab()
            self.initStyleOption(tab, idx)

            bg_parts = ['tabs', 'bg']
            fg_parts = ['tabs', 'fg']
            if idx == selected:
                bg_parts.append('selected')
                fg_parts.append('selected')

            if idx % 2:
                bg_parts.append('odd')
                fg_parts.append('odd')
            else:
                bg_parts.append('even')
                fg_parts.append('even')

            bg_color = config.get('colors', '.'.join(bg_parts))
            fg_color = config.get('colors', '.'.join(fg_parts))
            tab.palette.setColor(QPalette.Window, bg_color)
            tab.palette.setColor(QPalette.WindowText, fg_color)

            try:
                indicator_color = self.tab_data(idx, 'indicator-color')
            except KeyError:
                indicator_color = QColor()
            tab.palette.setColor(QPalette.Base, indicator_color)
            if tab.rect.right() < 0 or tab.rect.left() > self.width():
                # Don't bother drawing a tab if the entire tab is outside of
                # the visible tab bar.
                continue
            p.drawControl(QStyle.CE_TabBarTab, tab)

    def tabInserted(self, idx):
        """Update visibility when a tab was inserted."""
        super().tabInserted(idx)
        self._tabhide()

    def tabRemoved(self, idx):
        """Update visibility when a tab was removed."""
        super().tabRemoved(idx)
        self._tabhide()

    def wheelEvent(self, e):
        """Override wheelEvent to make the action configurable.

        Args:
            e: The QWheelEvent
        """
        if config.get('tabs', 'mousewheel-tab-switching'):
            super().wheelEvent(e)
        else:
            tabbed_browser = objreg.get('tabbed-browser', scope='window',
                                        window=self._win_id)
            tabbed_browser.wheelEvent(e)
Exemplo n.º 48
0
class TextEditorWidget(QWidget):
    """
    Simple Editor widget that stores the edited files in a unixfs node
    """

    rootMultihashChanged = pyqtSignal(str)
    documentChanged = pyqtSignal(Document)
    documentNameChanged = pyqtSignal(Document, str)
    filenameEntered = pyqtSignal(str)

    def __init__(self, offline=False, editing=False, sessionDagCid=None,
                 pyramidOrigin=None,
                 pyramidAutoPush=False, parent=None):
        super(TextEditorWidget, self).__init__(parent)

        self.app = QApplication.instance()
        self.setLayout(QVBoxLayout(self))
        self.textEditor = Editor(self)

        self.checkoutPath = None
        self.pyramidOrigin = pyramidOrigin
        self.pyramidAutoPush = pyramidAutoPush

        self.busyCube = AnimatedLabel(
            RotatingCubeRedFlash140d(speed=100),
            parent=self
        )
        self.busyCube.clip.setScaledSize(QSize(24, 24))
        self.busyCube.startClip()
        self.busyCube.hide()

        self._previewTimer = QTimer(self)
        self._previewTimer.timeout.connect(self.onPreviewRerender)
        self._editing = editing
        self._currentDocument = None
        self._localCheckoutChanged = False
        self._unixDir = None

        self.model = QFileSystemModel()

        self.filesView = CheckoutTreeView(self)
        self.filesView.setModel(self.model)
        self.filesView.doubleClick.connect(self.onFsViewItemDoubleClicked)
        self.filesView.itemRightClick.connect(self.onFsViewRightClicked)

        self.model.setFilter(
            QDir.Files | QDir.AllDirs | QDir.NoDot | QDir.NoDotDot
        )
        self.model.setRootPath(self.checkoutPath)

        self.filesView.setVisible(False)
        self.filesView.hideColumn(1)
        self.filesView.hideColumn(2)
        self.filesView.hideColumn(3)

        self.setObjectName('textEditor')
        self.inPreview = False
        self.offline = offline

        self.editHistory = EditHistory(parent=self)
        self.editHistory.hide()
        self.copiesLayout = self.editHistory.fLayout

        self.ctrlLayout = QHBoxLayout()

        self.editorViewButton = CheckableToolButton(
            icon=qta.icon('fa.edit'),
            toggled=self.onEditorViewToggled, parent=self
        )

        self.editorViewButton.setToolTip(iEditorView())

        self.offlineModeButton = CheckableToolButton(
            icon=getIcon('offline.png')
        )
        self.offlineModeButton.setChecked(offline)
        self.offlineModeButton.setEnabled(False)
        self.offlineModeButton.setVisible(False)
        self.offlineModeButton.setToolTip(iOfflineMode())

        self.autoMdHtmlSaveButton = CheckableToolButton(
            icon=qta.icon('fa5b.markdown')
        )
        self.autoMdHtmlSaveButton.setToolTip(iAutoMarkdownToHtmlSave())
        self.autoMdHtmlSaveButton.hide()

        self.previewButton = CheckableToolButton(
            icon=getIcon('document-preview.png'),
            toggled=self.onPreviewToggled, parent=self
        )
        self.previewButton.setToolTip(iPreview())

        self.editorViewButton.setChecked(True)

        self.fsViewButton = CheckableToolButton(
            icon=getIcon('folder-open.png'),
            toggled=self.onFsViewToggled, parent=self
        )
        self.fsViewButton.setEnabled(True)
        self.fsViewButton.setChecked(False)
        self.fsViewButton.setToolTip(iFilesystemView())

        self.editButton = CheckableToolButton(
            toggled=self.onEditToggled, parent=self
        )

        self.saveButton = QToolButton(self)
        self.saveButton.setIcon(getIcon('save-file.png'))
        self.saveButton.clicked.connect(self.onSave)
        self.saveButton.setToolTip(iSave())
        self.saveButton.setEnabled(False)
        self.saveButton.setShortcut(QKeySequence('Ctrl+s'))

        self.strokeIcon = getIcon('stroke-cube.png')

        self.editButton.setText(iEdit())

        self.unixDirCid = None
        self.unixDirPath = None
        self.unixDirDescrLabel = QLabel('Current session:')
        self.unixDirLabel = IPFSUrlLabel(
            None, invalidPathLabel='No session yet')
        self.unixDirClipButton = IPFSPathClipboardButton(None, parent=self)

        self.nameInputLabel = QLabel('File name')
        self.nameInputLine = QLineEdit('', self)
        self.nameInputLine.setMaximumWidth(160)
        self.nameInputValidate = QPushButton('OK')
        self.nameInputValidate.setMaximumWidth(40)
        self.nameInputValidate.clicked.connect(self.onNameInput)
        self.nameInputLine.returnPressed.connect(self.onNameInput)

        self.filenameEntered.connect(self.onFilenameEntered)

        self.ctrlLayout.addWidget(self.busyCube)
        self.ctrlLayout.addWidget(self.editButton)
        self.ctrlLayout.addItem(
            QSpacerItem(10, 10, QSizePolicy.Minimum, QSizePolicy.Minimum))
        self.ctrlLayout.addWidget(self.editorViewButton)
        self.ctrlLayout.addWidget(self.previewButton)
        self.ctrlLayout.addWidget(self.fsViewButton)
        self.ctrlLayout.addWidget(self.offlineModeButton)
        self.ctrlLayout.addWidget(self.autoMdHtmlSaveButton)
        self.ctrlLayout.addWidget(self.saveButton)

        self.ctrlLayout.addWidget(self.nameInputLabel)
        self.ctrlLayout.addWidget(self.nameInputLine)
        self.ctrlLayout.addWidget(self.nameInputValidate)

        self.showNameInput(False)

        self.ctrlLayout.addItem(
            QSpacerItem(10, 10, QSizePolicy.Expanding, QSizePolicy.Minimum))
        self.ctrlLayout.addWidget(self.unixDirDescrLabel)
        self.ctrlLayout.addWidget(self.unixDirLabel)
        self.ctrlLayout.addWidget(self.unixDirClipButton)

        self.textVLayout = QVBoxLayout()
        self.textHLayout = QHBoxLayout()
        self.textVLayout.addLayout(self.textHLayout)

        self.previewWidget = PreviewWidget(parent=self)
        self.previewWidget.hide()

        self.currentDocument = self.newDocument()
        self.textHLayout.addWidget(self.filesView)
        self.textHLayout.addWidget(self.textEditor)
        self.textHLayout.addWidget(self.previewWidget)

        optionsLayout = QHBoxLayout()
        self.tabReplaceButton = QCheckBox('Replace tabs', self)
        self.tabReplaceButton.stateChanged.connect(self.onTabReplaceToggled)
        self.tabReplaceButton.setEnabled(False)
        optionsLayout.addWidget(self.tabReplaceButton)
        self.textVLayout.addLayout(optionsLayout)

        self.layout().addLayout(self.ctrlLayout)
        self.layout().addWidget(self.editHistory)
        self.layout().addLayout(self.textVLayout)

        self.editing = editing
        self.rootMultihashChanged.connect(self.onSessionCidChanged)

        self.filesView.setMinimumWidth(self.width() / 4)

        self.textEditor.setSizePolicy(
            QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.filesView.setSizePolicy(
            QSizePolicy.Minimum, QSizePolicy.Expanding)

    @property
    def unixDirCid(self):
        return self._unixDirCid

    @property
    def unixDir(self):
        return self._unixDir

    @unixDirCid.setter
    def unixDirCid(self, cid):
        self._unixDirCid = cid

    @property
    def editing(self):
        return self._editing

    @editing.setter
    def editing(self, editing):
        if not isinstance(editing, bool):
            return

        self._editing = editing
        self.textEditor.setReadOnly(not self.editing)
        self.editButton.setChecked(self.editing)
        self.tabReplaceButton.setEnabled(self.editing)
        self.applyStylesheet()

        if self.editing is True and self.checkoutPath is None:
            self.sessionNew()

    @property
    def localCheckoutChanged(self):
        return self._localCheckoutChanged

    @localCheckoutChanged.setter
    def localCheckoutChanged(self, val):
        self._localCheckoutChanged = val
        self.saveButton.setEnabled(val)

    @property
    def currentDocument(self):
        return self._currentDocument

    @currentDocument.setter
    def currentDocument(self, doc):
        self._currentDocument = doc
        self.textEditor.setDocument(self.currentDocument)

        self.applyOptionsForDocument()

        self.documentChanged.emit(self.currentDocument)
        self.currentDocument.setModified(False)

        self.currentDocument.modified.connect(
            functools.partial(self.saveButton.setEnabled, True))
        self.currentDocument.contentsChanged.connect(self.onDocumentChanged)

        self.applyStylesheet()

    def applyOptionsForDocument(self):
        if self.currentDocument.filename:
            if self.currentDocument.filename.endswith('.py'):
                self.highlighter = PythonSyntaxHighlighter(
                    self.currentDocument)
                self.tabReplaceButton.setChecked(True)
            if filenameIsMarkdown(self.currentDocument.filename):
                self.previewButton.setChecked(True)
                self.autoMdHtmlSaveButton.show()
            if filenameIsHtml(self.currentDocument.filename):
                self.previewButton.setChecked(True)
        else:
            self.highlighter = None

    def cleanup(self):
        if os.path.isdir(self.checkoutPath):
            log.debug('Cleaning up checkout directory: {}'.format(
                self.checkoutPath))
            shutil.rmtree(self.checkoutPath)

    def busy(self, busy=True):
        self.busyCube.setVisible(busy)
        self.setEnabled(not busy)

        if busy:
            self.busyCube.startClip()
        else:
            self.busyCube.stopClip()

    def onFsViewRightClicked(self, idx, event, fInfo):
        pos = event.globalPos()
        fullPath = fInfo.absoluteFilePath()
        _path = Path(fullPath)

        menu = QMenu(self)

        if not _path.exists() or _path.is_dir():
            menu.addAction(
                self.strokeIcon,
                iAddNewFile(), functools.partial(
                    self.fsAddFile, fullPath))
            menu.addSeparator()
            menu.addAction(
                self.strokeIcon,
                iAddNewDir(), functools.partial(
                    self.fsAddDirectory, fullPath))
            menu.addSeparator()

            menu.addAction(
                self.strokeIcon,
                iImportFile(), functools.partial(
                    self.fsImportFile, fullPath))
            menu.addSeparator()
            menu.addAction(
                self.strokeIcon,
                iImportDir(), functools.partial(
                    self.fsImportDirectory, fullPath))
            menu.addSeparator()

        menu.addAction(
            getIcon('clear-all.png'),
            'Delete',
            partialEnsure(self.fsDelete, fullPath)
        )

        menu.exec_(pos)

    async def fsDelete(self, path):
        if path and await questionBoxAsync(iRemove(), iRemoveFileAsk()):
            await self._fsDelete(path)

    def fsAddFile(self, root):
        if not root:
            rootDir = Path(self.checkoutPath)
        else:
            rootDir = Path(root)

        if not rootDir.is_dir():
            return

        name = self.nameInput()
        if name:
            filepath = rootDir.joinpath(name)
            if filepath.exists():
                return messageBox('Already exists')

            filepath.touch()
            self.localCheckoutChanged = True
            self.sessionViewUpdate()

    def fsImportFile(self, root):
        if not root:
            rootDir = Path(self.checkoutPath)
        else:
            rootDir = Path(root)

        filepath = fileSelect()

        if filepath:
            ensure(self._fsImportFile(filepath, str(rootDir)))

    async def _fsDelete(self, filepath):
        self.busy()

        try:
            if os.path.isdir(filepath):
                await self.app.loop.run_in_executor(
                    self.app.executor,
                    shutil.rmtree,
                    filepath
                )
            elif os.path.isfile(filepath):
                os.unlink(filepath)
        except Exception:
            pass

        self.localCheckoutChanged = True
        self.busy(False)

    async def _fsImportFile(self, filepath, rootDir):
        self.busy()

        try:
            await self.app.loop.run_in_executor(
                self.app.executor,
                shutil.copy,
                filepath,
                rootDir
            )
        except Exception:
            messageBox(iImportError())

        self.localCheckoutChanged = True
        self.busy(False)

    async def _fsImportDirectory(self, dirpath, dstDir):
        self.busy()

        try:
            await self.app.loop.run_in_executor(
                self.app.executor,
                shutil.copytree,
                dirpath,
                dstDir
            )
        except Exception:
            messageBox(iImportError())

        self.localCheckoutChanged = True
        self.busy(False)

    def fsImportDirectory(self, root):
        if not root:
            rootDir = Path(self.checkoutPath)
        else:
            rootDir = Path(root)

        dirpath = directorySelect()

        if dirpath:
            dstPath = rootDir.joinpath(os.path.basename(dirpath))
            ensure(self._fsImportDirectory(dirpath, str(dstPath)))

    def fsAddDirectory(self, root):
        if not root:
            rootDir = Path(self.checkoutPath)
        else:
            rootDir = Path(root)

        if not rootDir.is_dir():
            return

        name = self.nameInput('Directory name')
        if name:
            dirpath = rootDir.joinpath(name)
            if dirpath.exists():
                return messageBox('Already exists')

            dirpath.mkdir()
            self.localCheckoutChanged = True
            self.sessionViewUpdate()

    def onFsViewItemDoubleClicked(self, idx, fInfo):
        fullPath = fInfo.absoluteFilePath()

        if not self.checkoutPath:
            return

        if not os.path.isfile(fullPath):
            return

        filepath = re.sub(self.checkoutPath, '', fullPath).lstrip('/')
        ensure(self.openFileFromCheckout(filepath))

    def onDocumentChanged(self):
        if self.previewWidget.isVisible():
            self._previewTimer.stop()
            self._previewTimer.start(1200)

    def onEditorViewToggled(self, toggle):
        if self.previewButton.isChecked():
            self.textEditor.setVisible(toggle)
        else:
            self.editorViewButton.setChecked(True)

    def onPreviewRerender(self):
        ensure(self.updatePreview())
        self._previewTimer.stop()

    def showNameInput(self, view=True):
        self.nameInputLabel.setVisible(view)
        self.nameInputLine.setVisible(view)
        self.nameInputValidate.setVisible(view)

        if view is False:
            self.nameInputLine.clear()

        if view is True:
            self.nameInputLine.setFocus(Qt.OtherFocusReason)

    def onTabReplaceToggled(self, state):
        self.textEditor.tabReplace = state

    def onNameInput(self):
        filename = self.nameInputLine.text()
        if len(filename) > 0:
            self.filenameEntered.emit(filename)

    def onFilenameEntered(self, filename):
        if self.currentDocument:
            self.currentDocument.filename = filename
            self.currentDocument.filenameChanged.emit(filename)

            self.documentNameChanged.emit(self.currentDocument, filename)
            self.showNameInput(False)
            ensure(self.saveDocument(self.currentDocument))

    def onDocnameChanged(self, doc, name):
        if doc == self.currentDocument:
            self.setTabName(name, widget=self)

    def applyStylesheet(self):
        if self.editing is True:
            self.textEditor.setStyleSheet('''
                QPlainTextEdit {
                    background-color: #D2DBD6;
                    color: #242424;
                    padding: 5px;
                    font: 14pt "Courier";
                    font-weight: bold;
                }
            ''')
            self.textEditor.connectSignals()
        else:
            self.textEditor.highlightCurrentLine()
            self.textEditor.setStyleSheet(defaultStyleSheet)

    def display(self, ipfsPath):
        if not isinstance(ipfsPath, IPFSPath) or not ipfsPath.valid:
            return

        ensure(self.showFromPath(ipfsPath))

    def genUid(self):
        return str(uuid.uuid4())

    def newDocument(self, name=None, text='', encoding='utf-8',
                    textLayout=True):
        self.textEditor.setStyleSheet(defaultStyleSheet)
        doc = Document(name=name, text=text, parent=self, encoding=encoding,
                       textLayout=textLayout)
        doc._previewDocument = Document(parent=doc, textLayout=False)
        return doc

    async def updatePreview(self):
        textData = self.currentDocument.toPlainText()
        pDocument = self.currentDocument.previewDocument

        try:
            mimeType = await detectMimeTypeFromBuffer(textData.encode())
        except:
            pass

        if self.currentDocument.filename:
            await self.writeDocument(self.currentDocument)

        if mimeType and mimeType.isHtml:
            if self.currentDocument.filename:
                url = self.checkoutChildFileUrl(self.currentDocument.filename)
                self.previewWidget.setUrl(url)
            else:
                self.previewWidget.setHtml(textData)
        else:
            try:
                html = markitdown(textData)
                pDocument.setHtml(html)
                self.previewWidget.setHtml(html)
            except Exception:
                pDocument.setPlainText(textData)

    def showPreview(self):
        self.previewWidget.show()
        ensure(self.updatePreview())

    def showText(self, textData, preview=False):
        if preview:
            text = textData
            newDocument = self.newDocument(text=textData)

            try:
                html = markitdown(text)
                newDocument.setHtml(html)
            except Exception:
                newDocument.setPlainText(text)

            self.textEditor.setReadOnly(True)
            return newDocument
        else:
            doc = self.newDocument(text=textData)
            self.textEditor.setReadOnly(not self.editing)
            return doc

    def onFsViewToggled(self, checked):
        self.toggleFsView(checked)

    def toggleFsView(self, view):
        if self.filesView:
            self.filesView.setVisible(view)

    def onSave(self):
        if self.currentDocument.changed:
            if self.currentDocument.filename is None:
                self.showNameInput(True)
            else:
                ensure(self.saveDocument(self.currentDocument))
        else:
            ensure(self.syncSession())

    def nameInput(self, label='File name'):
        name = inputText(label=label)
        if name and len(name) in range(1, 256):
            return name

    async def checkChanges(self):
        if self.currentDocument and self.currentDocument.changed is True:
            return await questionBoxAsync(
                'Unsaved changes',
                'The current document was not saved, continue ?')
        return True

    def onEditToggled(self, checked):
        self.editing = checked

    def onPreviewToggled(self, checked):
        self.inPreview = checked

        if checked:
            self.showPreview()
        else:
            if self.editorViewButton.isChecked():
                self.previewWidget.setVisible(checked)
            else:
                self.previewButton.setChecked(True)

    def onSessionCidChanged(self, cid):
        log.debug('Session now at CID: {}'.format(cid))
        self.unixDirCid = cid
        self.unixDirPath = IPFSPath(cid)
        self.unixDirLabel.path = self.unixDirPath
        self.unixDirClipButton.path = self.unixDirPath

    def sessionViewUpdate(self, root=None):
        path = root if root else self.checkoutPath
        self.model.setRootPath(path)
        self.filesView.setRootIndex(self.model.index(path))

    def sessionNew(self):
        localDirName = self.genUid()
        localPath = os.path.join(
            self.app.tempDir.path(), localDirName)

        if not os.path.exists(localPath):
            try:
                os.mkdir(localPath)
            except:
                pass

        ensure(self.sync())
        self.sessionViewUpdate(localPath)
        self.checkoutPath = localPath
        return localPath

    def makeDatetime(self, date=None):
        datet = date if date else datetime.now()
        return isoformat(datet)

    @ipfsOp
    async def sync(self, ipfsop):
        self.busy(True)
        try:
            entry = await ipfsop.addPath(
                self.checkoutPath,
                wrap=False,
                hidden=True,
                offline=self.offlineModeButton.isChecked()
            )
        except Exception as err:
            self.busy(False)
            log.debug(str(err))
        else:
            self.localCheckoutChanged = False
            self.busy(False)
            if not entry:
                return

            self.rootMultihashChanged.emit(entry['Hash'])
            return entry

    def checkoutChildPath(self, path):
        if self.checkoutPath:
            return Path(os.path.join(self.checkoutPath, path))

    def checkoutChildFileUrl(self, path):
        return QUrl('file://{0}'.format(self.checkoutChildPath(path)))

    async def writeDocument(self, document):
        docPath = self.checkoutChildPath(document.filename)
        text = document.toPlainText()

        async with aiofiles.open(docPath, 'w+t') as fd:
            log.debug('Writing document: {}'.format(docPath))
            await fd.write(text)

    @ipfsOp
    async def onShowDiff(self, ipfsop, path, prevPath, changes, *extra):
        """
        Show the object diff in a QTextBrowser

        TODO: refactor, at least ..
        """

        dlg = QDialog()
        dlg.setWindowTitle(iObjectDiff())
        layout = QVBoxLayout()
        dlg.setLayout(layout)
        dlg.setWindowFlag(Qt.WindowMinimizeButtonHint, True)
        dlg.setWindowFlag(Qt.WindowMaximizeButtonHint, True)
        dlg.setWindowFlag(Qt.WindowCloseButtonHint, True)
        dlg.setMinimumSize(
            (2 * self.app.desktopGeometry.width()) / 3,
            (2 * self.app.desktopGeometry.height()) / 3,
        )

        dBrowser = QTextBrowser(dlg)
        layout.addWidget(dBrowser)

        async def getTextContent(cid):
            mType = await detectMimeType(cid, bufferSize=1024)
            if mType and mType.isText:
                return await ipfsop.catObject(cid)

        for change in changes:
            objPath = change.get('Path')
            before = change.get('Before')
            after = change.get('After')
            beforeCid = before.get('/') if before else None
            afterCid = after.get('/') if after else None

            if change['Type'] == 2 and beforeCid and afterCid:
                try:
                    _bData = await getTextContent(beforeCid)
                    _aData = await getTextContent(afterCid)

                    if not _bData:
                        dBrowser.insertHtml(
                            '<p>Ignoring object {}</p>'.format(beforeCid))
                        continue

                    if not _aData:
                        dBrowser.insertHtml(
                            '<p>Ignoring object {}</p>'.format(afterCid))
                        continue

                    diff = difflib.HtmlDiff().make_file(
                        _bData.decode().split('\n'),
                        _aData.decode().split('\n'),
                        fromdesc=objPath if objPath else '',
                        todesc=objPath if objPath else '',
                        context=True,
                        numlines=10
                    )

                    dBrowser.insertHtml(diff)
                except Exception:
                    continue
            elif change['Type'] == 0 and afterCid:
                try:
                    _aData = await getTextContent(afterCid)

                    if not _aData:
                        dBrowser.insertHtml(
                            '<p>Ignoring object {}</p>'.format(afterCid))
                        continue

                    lines = _aData.decode().split('\n')

                    diff = difflib.HtmlDiff().make_file(
                        [],
                        lines,
                        fromdesc='',
                        todesc=objPath if objPath else '',
                        context=True,
                        numlines=len(lines)
                    )

                    dBrowser.insertHtml(diff)
                except Exception:
                    continue
            elif change['Type'] == 1 and beforeCid:
                try:
                    _bData = await getTextContent(beforeCid)

                    if not _bData:
                        dBrowser.insertHtml(
                            '<p>Ignoring object {}</p>'.format(beforeCid))
                        continue

                    lines = _bData.decode().split('\n')

                    diff = difflib.HtmlDiff().make_file(
                        lines,
                        [],
                        todesc='',
                        fromdesc=objPath if objPath else '',
                        context=True,
                        numlines=len(lines)
                    )

                    dBrowser.insertHtml(diff)
                except Exception:
                    continue

        dBrowser.moveCursor(QTextCursor.Start)
        dlg.showMaximized()
        await threadExec(dlg.exec_)

    @ipfsOp
    async def saveDocument(self, ipfsop, document, offline=True):
        text = document.toPlainText()

        if not document.filename:
            return

        await self.writeDocument(self.currentDocument)

        self.applyOptionsForDocument()

        if document.previewDocument:
            if filenameIsMarkdown(document.filename):
                document.previewDocument.filename = \
                    document.filename.replace('.md', '.html')

            if document.previewDocument.filename and \
                    self.autoMdHtmlSaveButton.isChecked():
                pPath = os.path.join(self.checkoutPath,
                                     document.previewDocument.filename)
                text = document.previewDocument.toHtml()

                async with aiofiles.open(pPath, 'w+t') as fd:
                    await fd.write(text)

        document.setModified(False)

        self.sessionViewUpdate(self.checkoutPath)

        await self.syncSession()

    @ipfsOp
    async def syncSession(self, ipfsop):
        # Previous session's IPFS path
        prevSessPath = self.unixDirPath

        entry = await self.sync()
        if entry:
            layout = QHBoxLayout()
            path = IPFSPath(entry['Hash'])

            diffButton = None
            if prevSessPath:
                # Generate an object diff tooltip
                changes = await ipfsop.objectDiff(prevSessPath, path)

                if isinstance(changes, list):
                    diffButton = QToolButton()
                    diffButton.setIcon(getIcon('code-fork.png'))
                    diffButton.setToolTip(
                        objectDiffSummaryShort(changes)
                    )
                    diffButton.clicked.connect(
                        partialEnsure(
                            self.onShowDiff,
                            path, prevSessPath, changes
                        )
                    )

            urlLabel = IPFSUrlLabel(path)
            clipButton = IPFSPathClipboardButton(path)
            pyrDropButton = self.app.mainWindow.getPyrDropButtonFor(
                path, origin=self.pyramidOrigin
            )

            now = QDateTime.currentDateTime()
            date = QLabel()
            date.setText(now.toString('hh:mm:ss'))

            hmarkButton = HashmarkThisButton(str(path))

            publishButton = QToolButton()
            publishButton.setText('Publish')
            publishButton.clicked.connect(functools.partial(
                self.onPublishFile, entry, publishButton))

            layout.addWidget(date)
            layout.addWidget(urlLabel)
            layout.addWidget(clipButton)

            if diffButton:
                layout.addWidget(diffButton)

            layout.addWidget(hmarkButton)
            layout.addWidget(pyrDropButton)
            layout.addItem(QSpacerItem(10, 10, QSizePolicy.Expanding,
                                       QSizePolicy.Minimum))

            if self.offlineModeButton.isChecked():
                layout.addWidget(publishButton)

            self.copiesLayout.insertLayout(0, layout)
            self.editHistory.show()

            self.saveButton.setEnabled(False)

    @ipfsOp
    async def publishEntry(self, ipfsop, entry):
        log.debug('Publishing {}'.format(entry))
        try:
            async for msg in ipfsop.client.dht.provide(entry['Hash']):
                log.debug('Provide result: {}'.format(msg))
        except Exception as err:
            messageBox('Could not publish')
            log.debug(str(err))
            return False
        else:
            return True

    def onPublishFile(self, entry, pButton):
        def finished(future):
            try:
                result = future.result()
                if result is True:
                    pButton.setStyleSheet('''
                        QToolButton {
                            color: green;
                        }'''
                                          )
                    pButton.setText('OK')
            except:
                pButton.setText('ERR')

        ensure(self.publishEntry(entry), futcallback=finished)
        pButton.setEnabled(False)
        pButton.setText('Publishing ..')

    @ipfsOp
    async def showFromPath(self, ipfsop, ipfsPath):
        if not await self.checkChanges():
            return

        if not ipfsPath.valid:
            return

        self.busy()

        try:
            dstdir = self.sessionNew()
            mimeType, stat = await self.app.rscAnalyzer(ipfsPath)

            if not stat:
                self.busy(False)
                messageBox('Object stat failed')
                return

            sInfo = StatInfo(stat)

            if not await ipfsop.client.get(
                ipfsPath.objPath,
                dstdir=dstdir
            ):
                raise Exception('Fetch failed')
        except Exception as err:
            self.busy(False)
            messageBox('Error fetching object: {}'.format(str(err)))
        else:
            rooted = os.path.join(dstdir, ipfsPath.basename)

            if os.path.isdir(rooted):
                path = rooted
            elif os.path.isfile(rooted):
                path = dstdir
            else:
                path = dstdir

            self.checkoutPath = path
            self.sessionViewUpdate(self.checkoutPath)

            for file in os.listdir(self.checkoutPath):
                await asyncio.sleep(0)

                fp = os.path.join(self.checkoutPath, file)
                mtype = await detectMimeTypeFromFile(fp)

                # Open first text file we find
                if mtype and (mtype.isText or mtype.isHtml):
                    await self.openFileFromCheckout(file)
                    break

            self.fsViewButton.setChecked(True)
            self.rootMultihashChanged.emit(sInfo.cid)

        self.busy(False)

    async def isTextFile(self, path):
        mtype = await detectMimeTypeFromFile(path)
        return mtype and (mtype.isText or mtype.isHtml)

    async def openFileFromCheckout(self, relpath):
        if not await self.checkChanges():
            return

        self.previewButton.setChecked(False)
        fp = Path(os.path.join(self.checkoutPath, relpath))

        if not fp.exists():
            return

        fsize = fp.stat().st_size

        if fsize > 0 and not await self.isTextFile(str(fp)):
            return messageBox('Not a text file')

        self.busy()

        basename = relpath
        doc = self.newDocument(name=basename)
        cursor = QTextCursor(doc)

        async for chunk in asyncReadTextFileChunked(
                str(fp), mode='rt'):
            await asyncio.sleep(0.1)
            cursor.insertText(chunk)

        self.currentDocument = doc
        self.busy(False)
        return doc

    def decode(self, data):
        for enc in ['utf-8', 'latin1', 'ascii']:
            try:
                textData = data.decode(enc)
            except BaseException:
                continue
            else:
                return enc, textData
        return None, None
Exemplo n.º 49
0
class QLabelsVisualization(QWidget):
    """
    This widget is designed to show Q-values of the state
    corresponding to cell over which cursor hovers.
    """
    def __init__(self, q_learning: QLearning):
        """
        Constructs widget with four arrows.
        Takes Q-learning object as input to take
        Q-values from it.

        Args:
            q_learning(QLearning): object that implements Q-learning algorithm
        """
        super().__init__()

        self._q_learning = q_learning
        self._layout = QGridLayout()

        self._q_labels = [QLabel() for _ in range(4)]
        self._arrows = [QLabel() for _ in range(4)]

        pics = [
            settings.RIGHT_ARROW_BUTTON_IMAGE,
            settings.LEFT_ARROW_BUTTON_IMAGE, settings.DOWN_ARROW_BUTTON_IMAGE,
            settings.UP_ARROW_BUTTON_IMAGE
        ]
        font = QFont("Impact", weight=QFont.Bold)
        font.setPixelSize(24)

        for _q_label, pos in zip(self._q_labels, [(2, 4), (2, 0), (4, 2),
                                                  (0, 2)]):
            self._layout.addWidget(_q_label, *pos)
            _q_label.setAlignment(Qt.AlignCenter)
            _q_label.setFont(font)
            _q_label.setFixedSize(QSize(50, 30))
        for _arrow, pos, pic in zip(self._arrows, [(2, 3), (2, 1), (3, 2),
                                                   (1, 2)], pics):
            self._layout.addWidget(_arrow, *pos)
            _arrow.setAlignment(Qt.AlignCenter)
            _arrow.setPixmap(QPixmap(pic).scaled(50, 50, Qt.KeepAspectRatio))
            _arrow.setScaledContents(False)

        self._displayed_coords = None
        self._timer = QTimer()
        self._timer.setInterval(settings.VALUE_UPDATE_TIME)
        self._timer.timeout.connect(self._update)

        self.setLayout(self._layout)
        self.setFixedSize(settings.Q_VISUALIZATION_NAILS)

    def cell_entered(self):
        """Updates Q-values on the arrows"""
        cell = self.sender()
        self._displayed_coords = cell.x, cell.y

        qvalues = self._q_learning.get_q_values(self._displayed_coords)
        self._qvalues = [qvalues[2], qvalues[0], qvalues[3], qvalues[1]]

        for i in range(4):
            self._q_labels[i].setText(f"{self._qvalues[i]:.2f}")

    def cell_left(self):
        """Removes text from arrows if cursor hovers over nothing"""
        for i in range(4):
            self._q_labels[i].setText("")

    def _update(self):
        all_done = True
        for i in range(4):
            self._qvalues[i], done = value_update(self._qvalues[i],
                                                  self._target_qvalues[i],
                                                  0.01)
            all_done = all_done and done
            self._q_labels[i].setText(f"{self._qvalues[i]:.2f}")

        if all_done:
            self._timer.stop()

    def values_updates(self, x: int, y: int):
        """
        Notifies widget that cell with coordinates x, y has updated Q-values

        Args:
            x - int
            y - int
        """
        if (x, y) == self._displayed_coords:
            qvalues = self._q_learning.get_q_values(self._displayed_coords)
            self._target_qvalues = [
                qvalues[2], qvalues[0], qvalues[3], qvalues[1]
            ]

            self._timer.start()
Exemplo n.º 50
0
class Image(QDialog):
    def __init__(self):
        super(Image, self).__init__()
        loadUi("presentation/Webcam.ui", self)
        self.image = None
        self.processed_image = None
        self.btn_start.clicked.connect(self.start_webcam)
        self.btn_stop.clicked.connect(self.stop_webcam)
        self.btn_canny.toggled.connect(self.canny_webcam)
        self.btn_canny.setCheckable(True)
        self.canny_enabled = False
        self.btn_detect.setCheckable(True)
        self.btn_detect.toggled.connect(self.detect_webcam_face)
        self.face_enabled = False

        self.face_cascade = cv2.CascadeClassifier(
            "data/haarcascade_frontalface_default.xml")

    def detect_webcam_face(self, status):
        if status:
            self.face_enabled = True
            self.btn_detect.setText("Stop face detection")
        else:
            self.face_enabled = False
            self.btn_detect.setText("Detect")

    def canny_webcam(self, status):
        if status:
            self.canny_enabled = True
            self.btn_canny.setText("Stop Canny")
        else:
            self.canny_enabled = False
            self.btn_canny.setText("Canny")

    def start_webcam(self):
        self.capture = cv2.VideoCapture(0)
        self.capture.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
        self.capture.set(cv2.CAP_PROP_FRAME_WIDTH, 640)

        self.timer = QTimer(self)
        self.timer.timeout.connect(self.update_frame)
        self.timer.start(5)

    def update_frame(self):
        ret, self.image = self.capture.read()
        self.image = cv2.flip(self.image, 1)

        if self.canny_enabled:
            gray = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) if len(
                self.image.shape) >= 3 else self.image
            self.processed_image = cv2.Canny(gray, 100, 200)
            self.display_image(self.processed_image, 2)

        if self.face_enabled:
            detected_face = self.detect_face(self.image)
            self.display_image(detected_face, 1)
        else:
            self.display_image(self.image, 1)

    def detect_face(self, img):
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        faces = self.face_cascade.detectMultiScale(gray,
                                                   1.3,
                                                   5,
                                                   minSize=(90, 90))
        for (x, y, w, h) in faces:
            cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2)

        return img

    def stop_webcam(self):
        self.timer.stop()

    def display_image(self, img, window=1):
        qformat = QImage.Format_Indexed8
        if len(img.shape) == 3:  # [0]=row ,[1]=cols, [2]=Channels
            if img.shape[2] == 4:
                qformat = QImage.Format_RGBA8888
            else:
                qformat = QImage.Format_RGB888

        out_image = QImage(img, img.shape[1], img.shape[0], img.strides[0],
                           qformat)
        # BGR>>RGB
        out_image = out_image.rgbSwapped()
        if window == 1:
            self.lbl_webcamfeed.setPixmap(QPixmap.fromImage(out_image))
            self.lbl_webcamfeed.setScaledContents(True)

        else:
            self.lbl_processed_webcamfeed.setPixmap(
                QPixmap.fromImage(out_image))
            self.lbl_processed_webcamfeed.setScaledContents(True)
Exemplo n.º 51
0
class ZoomableGraphicView(SelectableGraphicView):

    # argument is x zoom factor
    # if argument is -1, then show_full_scene was triggered during zoom
    zoomed = pyqtSignal(float)

    def __init__(self, parent=None):
        super().__init__(parent)

        self.zoom_in_action = QAction(self.tr("Zoom in"), self)
        self.zoom_in_action.setShortcut(QKeySequence.ZoomIn)
        self.zoom_in_action.triggered.connect(self.on_zoom_in_action_triggered)
        self.zoom_in_action.setShortcutContext(Qt.WidgetWithChildrenShortcut)
        self.zoom_in_action.setIcon(QIcon.fromTheme("zoom-in"))
        self.addAction(self.zoom_in_action)

        self.zoom_out_action = QAction(self.tr("Zoom out"), self)
        self.zoom_out_action.setShortcut(QKeySequence.ZoomOut)
        self.zoom_out_action.triggered.connect(
            self.on_zoom_out_action_triggered)
        self.zoom_out_action.setShortcutContext(Qt.WidgetWithChildrenShortcut)
        self.zoom_out_action.setIcon(QIcon.fromTheme("zoom-out"))
        self.addAction(self.zoom_out_action)

        self.redraw_timer = QTimer()
        self.redraw_timer.setSingleShot(True)
        self.redraw_timer.timeout.connect(self.redraw_view)

        self.zoomed.connect(self.on_signal_zoomed)

        self.scene_y_min = float("nan")  # NaN = AutoDetect
        self.scene_y_max = float("nan")  # NaN = AutoDetect

        self.scene_x_zoom_stretch = 1

    @property
    def y_center(self):
        if not hasattr(self, "scene_type") or self.scene_type == 0:
            # Normal scene
            return 0
        else:
            return -self.signal.qad_center

    @property
    def scene_type(self):
        return 0  # gets overwritten in Epic Graphic View

    def scrollContentsBy(self, dx: int, dy: int):
        try:
            super().scrollContentsBy(dx, dy)
            self.redraw_timer.start(0)
        except RuntimeError as e:
            logger.warning("Graphic View already closed: " + str(e))

    def zoom(self, factor, zoom_to_mouse_cursor=True, cursor_pos=None):
        if factor > 1 and self.view_rect().width() / factor < 300:
            factor = self.view_rect().width() / 300

        if zoom_to_mouse_cursor:
            pos = self.mapFromGlobal(
                QCursor.pos()) if cursor_pos is None else cursor_pos
        else:
            pos = None
        old_pos = self.mapToScene(pos) if pos is not None else None

        show_full = False
        if self.view_rect().width() / factor > self.sceneRect().width():
            self.show_full_scene()
            factor = 1
            show_full = True

        self.scale(factor, 1)
        if show_full:
            self.zoomed.emit(-1)
        else:
            self.zoomed.emit(factor)

        if pos is not None:
            move = self.mapToScene(pos) - old_pos
            self.translate(move.x(), 0)

    def wheelEvent(self, event: QWheelEvent):
        zoom_factor = 1.001**event.angleDelta().y()
        self.zoom(zoom_factor, cursor_pos=event.pos())

    def resizeEvent(self, event):
        if self.sceneRect().width() == 0:
            return

        self.auto_fit_view()

    def auto_fit_view(self):
        h_tar = self.sceneRect().height()
        h_view = self.view_rect().height()

        if abs(h_tar) > 0:
            self.scale(1, h_view / h_tar)
        self.centerOn(self.view_rect().x() + self.view_rect().width() / 2,
                      self.y_center)

    def show_full_scene(self, reinitialize=False):
        y_factor = self.transform().m22()
        self.resetTransform()
        x_factor = self.view_rect().width() / (
            self.sceneRect().width() *
            self.scene_x_zoom_stretch) if self.sceneRect().width() else 1
        self.scale(x_factor, y_factor)
        self.centerOn(0, self.y_center)

        self.redraw_view(reinitialize)

    def zoom_to_selection(self, start: int, end: int):
        if start == end:
            return

        x_factor = self.view_rect().width() / (end - start)
        self.zoom(x_factor, zoom_to_mouse_cursor=False)
        self.centerOn(start + (end - start) / 2, self.y_center)

    def plot_data(self, data):
        if self.scene_manager is None:
            self.scene_manager = SceneManager(self)
            self.scene_manager.minimum = self.scene_y_min
            self.scene_manager.maximum = self.scene_y_max

        self.scene_manager.plot_data = data
        self.scene_manager.init_scene()
        self.setScene(self.scene_manager.scene)
        self.scene_manager.show_full_scene()

    def redraw_view(self, reinitialize=False):
        if self.scene_manager is not None:
            self.scene_manager.scene_type = self.scene_type
            if reinitialize:
                self.scene_manager.init_scene()

            vr = self.view_rect()
            start, end = vr.x(), vr.x() + vr.width()
            self.scene_manager.show_scene_section(
                start, end, *self._get_sub_path_ranges_and_colors(start, end))

    def _get_sub_path_ranges_and_colors(self, start: float, end: float):
        # Overwritten in Epic Graphic View
        return None, None

    def eliminate(self):
        self.redraw_timer.stop()
        super().eliminate()

    @pyqtSlot()
    def on_signal_zoomed(self):
        self.redraw_timer.start(30)

    @pyqtSlot()
    def on_zoom_in_action_triggered(self):
        self.zoom(1.1)

    @pyqtSlot()
    def on_zoom_out_action_triggered(self):
        self.zoom(0.9)
Exemplo n.º 52
0
class Ui_MainWindow(QMainWindow,tradeManager):
    def __init__(self):
        super(Ui_MainWindow, self).__init__()
        self.gen_trade(1.)

        self.hour1 = 0
        self.min1 = 0
        self.sec1 = 30
        self.hour2 = 0
        self.min2 = 0
        self.sec2 = 60

        self.setupUi(self)
        self.time = QTimer(self)
        self.time.setInterval(1000)
        self.time.timeout.connect(self.Refresh)
        self.time.start()

    def setupUi(self, MainWindow):
        MainWindow.resize(900, 600)
        self.setWindowIcon(QIcon('./icon.png'))
        self.setWindowTitle("勒索软件1.0")
        self.setObjectName("MainWindow")
        self.setStyleSheet("#MainWindow{background-color: rgb(128, 10, 10)}")

        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")

        self.textBrowser = QtWidgets.QTextBrowser(self.centralwidget)
        self.textBrowser.setGeometry(QtCore.QRect(250, 100, 600, 200))
        self.textBrowser.setObjectName("textBrowser")

        font1 = QtGui.QFont()
        font1.setFamily("Arial")  # 括号里可以设置成自己想要的其它字体
        font1.setPointSize(15)  # 括号里的数字可以设置成自己想要的字体大小
        self.textBrowser.setFont(font1)
        self.textBrowser.setText("您好!您的电脑已经中了勒索病毒,您的所有文件都已被加密,请扫描以下二维码支付赎金以便得到解密密钥,赎金的价格为¥1,我们将在12小时之内提高价格到¥2,并于24小时内删除解密密钥。扫码后我们将自动利用获取的解密密钥为您解密。")

        self.label_warn = QtWidgets.QLabel(self.centralwidget)
        self.label_warn.setText("哇哦~你的文件被加密了!")
        self.label_warn.setGeometry(QtCore.QRect(250, 30, 500, 40))
        font = QtGui.QFont()
        font.setFamily("Arial")  # 括号里可以设置成自己想要的其它字体
        font.setPointSize(20)  # 括号里的数字可以设置成自己想要的字体大小
        self.label_warn.setFont(font)
        self.label_warn.setStyleSheet("color:white")

        pix = QtGui.QPixmap(self.save_path)
        #print(self.save_path)
        self.label_qr = QtWidgets.QLabel(self.centralwidget)
        self.label_qr.setGeometry(410, 320, 250, 250)
        self.label_qr.setPixmap(pix)
        self.label_qr.setScaledContents(True)

        pix = QtGui.QPixmap('./lock.png')
        self.label_qr = QtWidgets.QLabel(self.centralwidget)
        self.label_qr.setGeometry(30, 40, 180, 180)
        self.label_qr.setPixmap(pix)
        self.label_qr.setScaledContents(True)

        self.label_time1 = QtWidgets.QLabel(self.centralwidget)
        self.label_time1.setGeometry(QtCore.QRect(30, 300, 200, 100))
        self.label_time1.setFont(font)
        self.label_time1.setStyleSheet("color:white")
        self.label_time1.setText("距离提价时间:\n   12:00:00")

        self.label_time2 = QtWidgets.QLabel(self.centralwidget)
        self.label_time2.setText("距离撕票时间:\n   24:00:00")
        self.label_time2.setGeometry(QtCore.QRect(30, 420, 200, 100))
        self.label_time2.setFont(font)
        self.label_time2.setStyleSheet("color:white")


        MainWindow.setCentralWidget(self.centralwidget)
        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        # self.pushButton2.setText(_translate("MainWindow", "解密"))

    def Refresh(self):
        if self.hour1==0 and self.min1==0 and self.sec1==0:
            QMessageBox.information(self,  # 使用infomation信息框
                                    "提示",
                                    "你未在规定时间内支付赎金,所以我们提高了赎金。")
            self.hour1=-1
            self.label_time1.setText("距离提价时间:\n   00:00:00")

            self.sk.sendall(bytes("3", "utf-8"))
            print("赎金翻倍")#开始切换二维码

            self.flag_watch_and_cancel1 = 0
            time.sleep(2)
            self.flag_watch_and_cancel1 = 1

            self.gen_trade(2.)
            Thread(target=self._watch_and_cancel).start()
            self.setupUi(self)

        if self.hour1>=0 and self.min1>=0 and self.sec1>=0:
            if self.sec1!=0:
                self.sec1 -= 1
            elif self.sec1==0 and self.min1!=0:
                self.sec1=59
                self.min1-=1
            elif self.sec1==0 and self.min1==0 and self.hour1!=0:
                self.hour1-=1
                self.min1=59
                self.sec1=59

        if self.hour2 == 0 and self.min2 == 0 and self.sec2 == 0:
            QMessageBox.information(self,  # 使用infomation信息框
                                    "提示",
                                    "你未在规定时间内支付赎金,你的文件和你永别了。")

            self.time.stop()
            self.sk.sendall(bytes("4", "utf-8"))

        if self.hour2 >= 0 and self.min2 >= 0 and self.sec2 >= 0:
            if self.sec2 != 0:
                self.sec2 -= 1
            elif self.sec2 == 0 and self.min2 != 0:
                self.sec2 = 59
                self.min2 -= 1
            elif self.sec2 == 0 and self.min2 == 0 and self.hour2 != 0:
                self.hour2 -= 1
                self.min2 = 59
                self.sec2 = 59

            hour1=str(self.hour1).rjust(2, '0')
            min1 = str(self.min1).rjust(2, '0')
            sec1 = str(self.sec1).rjust(2, '0')
            hour2 = str(self.hour2).rjust(2, '0')
            min2 = str(self.min2).rjust(2, '0')
            sec2 = str(self.sec2).rjust(2, '0')

            self.label_time1.setText("距离提价时间:\n   {}:{}:{}".format(hour1,min1,sec1))
            self.label_time2.setText("距离撕票时间:\n   {}:{}:{}".format(hour2,min2,sec2))

        if self.hour1==-1:
            self.label_time1.setText("距离提价时间:\n   00:00:00")
Exemplo n.º 53
0
class Completer(QObject):
    """Completer which manages completions in a CompletionView.

    Attributes:
        _cmd: The statusbar Command object this completer belongs to.
        _ignore_change: Whether to ignore the next completion update.
        _win_id: The window ID this completer is in.
        _timer: The timer used to trigger the completion update.
        _cursor_part: The cursor part index for the next completion update.
        _last_cursor_pos: The old cursor position so we avoid double completion
                          updates.
        _last_text: The old command text so we avoid double completion updates.
        _signals_connected: Whether the signals are connected to update the
                            completion when the command widget requests that.

    Signals:
        next_prev_item: Emitted to select the next/previous item in the
                        completion.
                        arg0: True for the previous item, False for the next.
    """

    next_prev_item = pyqtSignal(bool)

    def __init__(self, cmd, win_id, parent=None):
        super().__init__(parent)
        self._win_id = win_id
        self._cmd = cmd
        self._signals_connected = False
        self._ignore_change = False
        self._empty_item_idx = None
        self._timer = QTimer()
        self._timer.setSingleShot(True)
        self._timer.setInterval(0)
        self._timer.timeout.connect(self.update_completion)
        self._cursor_part = None
        self._last_cursor_pos = None
        self._last_text = None

        objreg.get('config').changed.connect(self.on_auto_open_changed)
        self.handle_signal_connections()
        self._cmd.clear_completion_selection.connect(
            self.handle_signal_connections)

    def __repr__(self):
        return utils.get_repr(self)

    @config.change_filter('completion', 'auto-open')
    def on_auto_open_changed(self):
        self.handle_signal_connections()

    @pyqtSlot()
    def handle_signal_connections(self):
        self._connect_signals(config.get('completion', 'auto-open'))

    def _connect_signals(self, connect=True):
        """Connect or disconnect the completion signals.

        Args:
            connect: Whether to connect (True) or disconnect (False) the
                     signals.

        Return:
            True if the signals were connected (connect=True and aren't
            connected yet) - otherwise False.
        """
        connections = [
            (self._cmd.update_completion, self.schedule_completion_update),
            (self._cmd.textChanged, self.on_text_edited),
        ]

        if connect and not self._signals_connected:
            for sender, receiver in connections:
                sender.connect(receiver)
            self._signals_connected = True
            return True
        elif not connect:
            for sender, receiver in connections:
                try:
                    sender.disconnect(receiver)
                except TypeError:
                    # Don't fail if not connected
                    pass
            self._signals_connected = False
        return False

    def _open_completion_if_needed(self):
        """If auto-open is false, temporarily connect signals.

        Also opens the completion.
        """
        if not config.get('completion', 'auto-open'):
            connected = self._connect_signals(True)
            if connected:
                self.update_completion()

    def _model(self):
        """Convienience method to get the current completion model."""
        completion = objreg.get('completion',
                                scope='window',
                                window=self._win_id)
        return completion.model()

    def _get_completion_model(self, completion, parts, cursor_part):
        """Get a completion model based on an enum member.

        Args:
            completion: A usertypes.Completion member.
            parts: The parts currently in the commandline.
            cursor_part: The part the cursor is in.

        Return:
            A completion model.
        """
        if completion == usertypes.Completion.option:
            section = parts[cursor_part - 1]
            model = instances.get(completion).get(section)
        elif completion == usertypes.Completion.value:
            section = parts[cursor_part - 2]
            option = parts[cursor_part - 1]
            try:
                model = instances.get(completion)[section][option]
            except KeyError:
                # No completion model for this section/option.
                model = None
        else:
            model = instances.get(completion)
        return model

    def _filter_cmdline_parts(self, parts, cursor_part):
        """Filter a list of commandline parts to exclude flags.

        Args:
            parts: A list of parts.
            cursor_part: The index of the part the cursor is over.

        Return:
            A (parts, cursor_part) tuple with the modified values.
        """
        if parts == ['']:
            # Empty commandline, i.e. only :.
            return [''], 0
        filtered_parts = []
        for i, part in enumerate(parts):
            if part == '--':
                break
            elif part.startswith('-'):
                if cursor_part >= i:
                    cursor_part -= 1
            else:
                filtered_parts.append(part)
        return filtered_parts, cursor_part

    def _get_new_completion(self, parts, cursor_part):
        """Get a new completion.

        Args:
            parts: The command chunks to get a completion for.
            cursor_part: The part the cursor is over currently.

        Return:
            A completion model.
        """
        try:
            if parts[cursor_part].startswith('-'):
                # cursor on a flag
                return
        except IndexError:
            pass
        log.completion.debug("Before filtering flags: parts {}, cursor_part "
                             "{}".format(parts, cursor_part))
        parts, cursor_part = self._filter_cmdline_parts(parts, cursor_part)
        log.completion.debug("After filtering flags: parts {}, cursor_part "
                             "{}".format(parts, cursor_part))
        if cursor_part == 0:
            # '|' or 'set|'
            return instances.get(usertypes.Completion.command)
        # delegate completion to command
        try:
            completions = cmdutils.cmd_dict[parts[0]].completion
        except KeyError:
            # entering an unknown command
            return None
        if completions is None:
            # command without any available completions
            return None
        dbg_completions = [c.name for c in completions]
        try:
            idx = cursor_part - 1
            completion = completions[idx]
        except IndexError:
            # More arguments than completions
            log.completion.debug("completions: {}".format(
                ', '.join(dbg_completions)))
            return None
        dbg_completions[idx] = '*' + dbg_completions[idx] + '*'
        log.completion.debug("completions: {}".format(
            ', '.join(dbg_completions)))
        model = self._get_completion_model(completion, parts, cursor_part)
        return model

    def _quote(self, s):
        """Quote s if it needs quoting for the commandline.

        Note we don't use shlex.quote because that quotes a lot of shell
        metachars we don't need to have quoted.
        """
        if not s:
            return "''"
        elif any(c in s for c in ' \'\t\n\\'):
            # use single quotes, and put single quotes into double quotes
            # the string $'b is then quoted as '$'"'"'b'
            return "'" + s.replace("'", "'\"'\"'") + "'"
        else:
            return s

    def selection_changed(self, selected, _deselected):
        """Change the completed part if a new item was selected.

        Called from the views selectionChanged method.

        Args:
            selected: New selection.
            _delected: Previous selection.
        """
        indexes = selected.indexes()
        if not indexes:
            return
        model = self._model()
        data = model.data(indexes[0])
        if data is None:
            return
        parts = self.split()
        try:
            needs_quoting = cmdutils.cmd_dict[parts[0]].maxsplit is None
        except KeyError:
            needs_quoting = True
        if needs_quoting:
            data = self._quote(data)
        if model.count() == 1 and config.get('completion', 'quick-complete'):
            # If we only have one item, we want to apply it immediately
            # and go on to the next part.
            self.change_completed_part(data, immediate=True)
        else:
            log.completion.debug("Will ignore next completion update.")
            self._ignore_change = True
            self.change_completed_part(data)

    @pyqtSlot()
    def schedule_completion_update(self):
        """Schedule updating/enabling completion.

        For performance reasons we don't want to block here, instead we do this
        in the background.
        """
        if (self._cmd.cursorPosition() == self._last_cursor_pos
                and self._cmd.text() == self._last_text):
            log.completion.debug("Ignoring update because there were no "
                                 "changes.")
        else:
            log.completion.debug("Scheduling completion update.")
            self._timer.start()
        self._last_cursor_pos = self._cmd.cursorPosition()
        self._last_text = self._cmd.text()

    @pyqtSlot()
    def update_completion(self):
        """Check if completions are available and activate them."""
        self.update_cursor_part()
        parts = self.split()

        log.completion.debug(
            "Updating completion - prefix {}, parts {}, cursor_part {}".format(
                self._cmd.prefix(), parts, self._cursor_part))

        if self._ignore_change:
            log.completion.debug("Ignoring completion update because "
                                 "ignore_change is True.")
            self._ignore_change = False
            return

        completion = objreg.get('completion',
                                scope='window',
                                window=self._win_id)

        if self._cmd.prefix() != ':':
            # This is a search or gibberish, so we don't need to complete
            # anything (yet)
            # FIXME complete searches
            # https://github.com/The-Compiler/qutebrowser/issues/32
            completion.hide()
            return

        model = self._get_new_completion(parts, self._cursor_part)

        if model != self._model():
            if model is None:
                completion.hide()
            else:
                completion.set_model(model)

        if model is None:
            log.completion.debug("No completion model for {}.".format(parts))
            return

        try:
            pattern = parts[self._cursor_part].strip()
        except IndexError:
            pattern = ''
        completion.set_pattern(pattern)

        log.completion.debug(
            "New completion for {}: {}, with pattern '{}'".format(
                parts, model.srcmodel.__class__.__name__, pattern))

        if self._model().count() == 0:
            completion.hide()
            return

        if completion.enabled:
            completion.show()

    def split(self, keep=False, aliases=False):
        """Get the text split up in parts.

        Args:
            keep: Whether to keep special chars and whitespace.
            aliases: Whether to resolve aliases.
        """
        text = self._cmd.text()[len(self._cmd.prefix()):]
        if not text:
            # When only ":" is entered, we already have one imaginary part,
            # which just is empty at the moment.
            return ['']
        if not text.strip():
            # Text is only whitespace so we treat this as a single element with
            # the whitespace.
            return [text]
        runner = runners.CommandRunner(self._win_id)
        result = runner.parse(text, fallback=True, aliases=aliases, keep=keep)
        parts = result.cmdline
        if self._empty_item_idx is not None:
            log.completion.debug("Empty element queued at {}, "
                                 "inserting.".format(self._empty_item_idx))
            parts.insert(self._empty_item_idx, '')
        #log.completion.debug("Splitting '{}' -> {}".format(text, parts))
        return parts

    @pyqtSlot()
    def update_cursor_part(self):
        """Get the part index of the commandline where the cursor is over."""
        cursor_pos = self._cmd.cursorPosition()
        snippet = slice(cursor_pos - 1, cursor_pos + 1)
        if self._cmd.text()[snippet] == '  ':
            spaces = True
        else:
            spaces = False
        cursor_pos -= len(self._cmd.prefix())
        parts = self.split(keep=True)
        log.completion.vdebug(
            "text: {}, parts: {}, cursor_pos after removing prefix '{}': "
            "{}".format(self._cmd.text(), parts, self._cmd.prefix(),
                        cursor_pos))
        skip = 0
        for i, part in enumerate(parts):
            log.completion.vdebug("Checking part {}: {!r}".format(i, parts[i]))
            if not part:
                skip += 1
                continue
            if cursor_pos <= len(part):
                # foo| bar
                self._cursor_part = i - skip
                if spaces:
                    self._empty_item_idx = i - skip
                else:
                    self._empty_item_idx = None
                log.completion.vdebug("cursor_pos {} <= len(part) {}, "
                                      "setting cursor_part {} - {} (skip), "
                                      "empty_item_idx {}".format(
                                          cursor_pos, len(part), i, skip,
                                          self._empty_item_idx))
                break
            cursor_pos -= len(part)
            log.completion.vdebug(
                "Removing len({!r}) -> {} from cursor_pos -> {}".format(
                    part, len(part), cursor_pos))
        else:
            if i == 0:
                # Initial `:` press without any text.
                self._cursor_part = 0
            else:
                self._cursor_part = i - skip
            if spaces:
                self._empty_item_idx = i - skip
            else:
                self._empty_item_idx = None
        log.completion.debug("cursor_part {}, spaces {}".format(
            self._cursor_part, spaces))
        return

    def change_completed_part(self, newtext, immediate=False):
        """Change the part we're currently completing in the commandline.

        Args:
            text: The text to set (string).
            immediate: True if the text should be completed immediately
                       including a trailing space and we shouldn't continue
                       completing the current item.
        """
        parts = self.split()
        log.completion.debug("changing part {} to '{}'".format(
            self._cursor_part, newtext))
        try:
            parts[self._cursor_part] = newtext
        except IndexError:
            parts.append(newtext)
        # We want to place the cursor directly after the part we just changed.
        cursor_str = self._cmd.prefix() + ' '.join(
            parts[:self._cursor_part + 1])
        if immediate:
            # If we should complete immediately, we want to move the cursor by
            # one more char, to get to the next field.
            cursor_str += ' '
        text = self._cmd.prefix() + ' '.join(parts)
        if immediate and self._cursor_part == len(parts) - 1:
            # If we should complete immediately and we're completing the last
            # part in the commandline, we automatically add a space.
            text += ' '
        self._cmd.setText(text)
        log.completion.debug("Placing cursor after '{}'".format(cursor_str))
        log.modes.debug("Completion triggered, focusing {!r}".format(self))
        self._cmd.setCursorPosition(len(cursor_str))
        self._cmd.setFocus()
        self._cmd.show_cmd.emit()

    @pyqtSlot()
    def on_text_edited(self):
        """Reset _empty_item_idx if text was edited."""
        self._empty_item_idx = None
        # We also want to update the cursor part and emit update_completion
        # here, but that's already done for us by cursorPositionChanged
        # anyways, so we don't need to do it twice.

    @cmdutils.register(instance='completer',
                       hide=True,
                       modes=[usertypes.KeyMode.command],
                       scope='window')
    def completion_item_prev(self):
        """Select the previous completion item."""
        self._open_completion_if_needed()
        self.next_prev_item.emit(True)

    @cmdutils.register(instance='completer',
                       hide=True,
                       modes=[usertypes.KeyMode.command],
                       scope='window')
    def completion_item_next(self):
        """Select the next completion item."""
        self._open_completion_if_needed()
        self.next_prev_item.emit(False)

    @cmdutils.register(instance='completion',
                       hide=True,
                       modes=[usertypes.KeyMode.command],
                       scope='window')
    def completion_item_del(self):
        """Delete the current completion item."""
        completion = objreg.get('completion',
                                scope='window',
                                window=self._win_id)
        if not completion.currentIndex().isValid():
            raise cmdexc.CommandError("No item selected!")
        try:
            self.model().srcmodel.delete_cur_item(completion)
        except NotImplementedError:
            raise cmdexc.CommandError("Cannot delete this item.")
Exemplo n.º 54
0
class AutomaticRL(QWidget):
    """
    This class represents a widget for the Q-learning mode.
    It consists of play/step buttons, labels for visualization of
    Q-values for hovered cell. It uses instance of `logic.gameLogic.GameLogic`
    as an environment for RL agent.
    """

    made_step_signal = pyqtSignal()
    user_interacted = pyqtSignal()

    def _init_ui(self):
        self._command_layout = QVBoxLayout()

        # Text label
        self._description_label = QLabel()
        self._description_label.setFont(QFont("Pacifico", 14, QFont.Normal))
        self._description_label.setAlignment(Qt.AlignCenter)
        self._description_label.setText(settings.Q_LEARNING_DESCRIPTION)
        self._description_label.setSizePolicy(
            QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum))
        self._description_label.setFixedSize(
            settings.AUTO_RL_DESCRIPTION_NAILS)
        self._command_layout.addWidget(self._description_label, 0,
                                       Qt.AlignHCenter)

        # q-values visualization
        self._qlabels = QLabelsVisualization(self._q_learning)
        self._command_layout.addWidget(self._qlabels, 0, Qt.AlignHCenter)

        # rl buttons
        self._buttons = QWidget()
        self._buttons_layout = QHBoxLayout()
        self._play_button = Button(settings.PLAY_BUTTON_IMAGE)
        self._next_step_button = Button(settings.STEP_BUTTON_IMAGE)
        self._buttons_layout.addWidget(self._play_button)
        self._buttons_layout.addWidget(self._next_step_button)
        self._buttons.setLayout(self._buttons_layout)
        self._buttons.setFixedWidth(settings.BUTTONS_NAILS_WIDTH)
        self._command_layout.addWidget(self._buttons, 0, Qt.AlignHCenter)

        self.setLayout(self._command_layout)

    def __init__(self, game_screen: GameScreen):
        """
        Constructs an AutomaticRL widget.

        AutomaticRL widget needs `game_screen` to update
        information in cells about Q-values.

        Args:
            game_screen - GameScreen instance.
        """
        super().__init__()

        self._game_screen = game_screen
        self._params = GameParams(Modes.AUTOMATICRL,
                                  game_height=settings.GAME_HEIGHT,
                                  game_width=settings.GAME_WIDTH,
                                  lava_random=settings.AUTOMATIC_LAVA_RANDOM,
                                  lava_reward=settings.LAVA_REWARD,
                                  lava_is_terminal=True,
                                  green_random=settings.GREEN_RANDOM,
                                  green_reward=settings.GREEN_REWARD,
                                  green_is_terminal=True)

        self._logic = GameLogic(self._params)
        self._q_learning = QLearning(self._logic)

        self._playing = False
        self._timer = QTimer()
        self._timer.timeout.connect(self._next_step)

        self._init_ui()

        # connecting player buttons
        self._play_button.clicked.connect(self._play)
        self._next_step_button.clicked.connect(self._next_step_click)

        self.made_step_signal.connect(game_screen.update_screen)

    def enter_mode(self):
        """Replaces game screen logic with RL environment and resets cells."""
        self._game_screen.change_logic(self._logic)
        self.init_cells()

    def exit_mode(self):
        """Stops playing. Used when current mode is being changed."""
        if self._playing:
            self._playing = False
            self._timer.stop()
            return

    def init_cells(self):
        """
        Reinitializes self if cells have changed.

        Internally does two things:
            1. Connects signals to new cells;
            2. Resets values for each cell.

        #TODO: if graphic scene will be switched without scene reinitialization
        (see issue #44), this function will not be required.
        """

        # connecting mouse hover from cells to our q-values visualization
        for cell in self._game_screen.cells:
            cell.enter_signal.connect(self._qlabels.cell_entered)
            cell.leave_signal.connect(self._qlabels.cell_left)

        # initialize values
        for i in range(self._logic.game_size[0]):
            for j in range(self._logic.game_size[1]):
                self._game_screen.set_cell_value(i, j, 0.)

        for pos in self._logic.terminal_cells:
            reward = self._logic.game_board.cell_reward(pos)
            self._game_screen.set_cell_value(pos[0], pos[1], reward)

    def _next_step_click(self):
        self.user_interacted.emit()
        self._stop_playing()
        self._next_step()

    def _next_step(self):
        if self._logic.done:
            self._q_learning.reset()
        else:
            old_x, old_y = self._logic.scrat_position
            # pylint: disable=W0612
            reward, done, info = self._q_learning.step()
            new_value = max(self._q_learning.get_q_values((old_x, old_y)))

            # updating value on the cell in game field
            self._game_screen.set_cell_value(old_x, old_y, new_value)

            # updating q-visualization
            self._qlabels.values_updates(old_x, old_y)

        self.made_step_signal.emit()

    def _stop_playing(self):
        if self._playing:
            self._playing = False
            self._timer.stop()
            self._play_button.updatePic(settings.PLAY_BUTTON_IMAGE)

    def reset(self):
        """Reset game state and send signal that state changed"""
        self._stop_playing()
        self._q_learning.reset()
        self.made_step_signal.emit()

    def full_reset(self):
        """Reinitialize logic randomly"""
        self._stop_playing()
        self._logic.full_reset()
        self._q_learning.reset_q()
        self.init_cells()
        self.made_step_signal.emit()

    def _play(self):
        self.user_interacted.emit()

        if self._playing:
            self._playing = False
            self._timer.stop()
            self._play_button.updatePic(settings.PLAY_BUTTON_IMAGE)
            return

        self._playing = True
        self._timer.start(settings.Q_LEARNING_PLAY_SPEED)
        self._play_button.updatePic(settings.STOP_BUTTON_IMAGE)
Exemplo n.º 55
0
class AppWindow(QMainWindow,Ui_MainWindow):
  def __init__(self,parent=None):
    super(AppWindow,self).__init__(parent)
    self.setupUi(self)
    # ^O^ static_fig can changed to any other function
    #self.fig1=static_fig(width=5, height=4, dpi=100)
    self.fig1 = static_fig(width=5, height=3, dpi=72)
    self.fig2 = dynamic_fig(width=5, height=3, dpi=72)
    # add NavigationToolbar in the figure (widgets)
    self.fig_ntb1 = NavigationToolbar(self.fig1, self)
    self.fig_ntb2 = NavigationToolbar(self.fig2, self)
    #self.Start_plot.clicked.connect(self.plot_cos)
    # add the static_fig in the Plot box
    self.gridlayout1=QGridLayout(self.Plot_static)
    self.gridlayout1.addWidget(self.fig1)
    self.gridlayout1.addWidget(self.fig_ntb1)
    # add the dynamic_fig in the Plot box
    self.gridlayout2 = QGridLayout(self.Plot_dynamic)
    self.gridlayout2.addWidget(self.fig2)
    self.gridlayout2.addWidget(self.fig_ntb2)
    # initialized flags for static/dynamic plot: on is 1,off is 0
    self._timer = QTimer(self)
    self._t = 1
    self._counts = []
    self._delay_t = []
    self._Static_on=0
    self._update_on=0



  @pyqtSlot()
  def on_Static_plot_clicked(self):
    self.plot_cos()
    self._Static_on=1
    #self.Start_plot.setEnabled(False)

  global nc
  nc=1
  def plot_cos(self):
    #print('nc=%d\n' %self.nc)
    global nc
    nc+=1
    self.fig1.axes.cla()
    self.t=np.arange(0,15,0.1)
    self.y=2*nc*self.t-self.t*np.cos(self.t/2/np.pi*1000)
    self.fig1.axes.plot(self.t,self.y)
    self.fig1.axes.set_title("signals",fontsize=18,color='c')
    self.fig1.axes.set_xlabel("delay(s)",fontsize=18,color='c')
    self.fig1.axes.set_ylabel("counts",fontsize=18,color='c')
    self.fig1.draw()

  @pyqtSlot()
  def on_dynamic_plot_clicked(self):
    print('start dynamic ploting')
    self.Static_plot.setEnabled(False)
    self.dynamic_plot.setEnabled(False)
    # start update figure every 1s; flag "update_on" : 1 is on and 0 is Off
    self._update_on = 1
    self._timer.timeout.connect(self.update_fig)
    self._timer.start(1000) # plot after 1s delay

  
  
  def update_fig(self):
    self._t+=1
    print(self._t)
    self._delay_t.append(self._t)
    print(self._delay_t)
    #new_counts=random.randint(100,900)
    new_counts= 2 * self._t - self._t * np.cos(self._t / 2 / np.pi * 1000)
    self._counts.append(new_counts)
    print(self._counts)
    self.fig2.axes.cla()
    self.fig2.axes.plot(self._delay_t,self._counts,'-ob')
    self.fig2.axes.set_title("signals",fontsize=18,color='c')
    self.fig2.axes.set_xlabel("delay(s)",fontsize=18,color='c')
    self.fig2.axes.set_ylabel("counts",fontsize=18,color='c')
    self.fig2.draw()

  @pyqtSlot()
  def on_End_plot_clicked(self):
    if self._update_on==1:
      self._update_on=0
      self._timer.timeout.disconnect(self.update_fig)
      self.dynamic_plot.setEnabled(True)
    else:
      pass

  @pyqtSlot()
  def on_Erase_plot_clicked(self):
    self.fig1.axes.cla()
    self.fig1.draw()
    self.fig2.axes.cla()
    self.fig2.draw()
    if self._update_on==1:
      self._update_on=0
      self._delay_t=[]
      self._counts=[]
      self.fig2.axes.cla()
      self.fig2.draw()
      self._timer.timeout.disconnect(self.update_fig)
      self.dynamic_plot.setEnabled(True)
    else:
      pass
    self.Static_plot.setEnabled(True)
Exemplo n.º 56
0
class MainWindow(QWidget, form_class):
    # class constructor
    def __init__(self):
        # call QWidget constructor
        super().__init__()
        self.setupUi(self)

        self.edit.setText("Input name")
        self.data_dir = "dataset/"
        self.model_path = "dataset/trained_knn_model.clf"

        # create a timer
        # set timer timeout callback function

        # viewCam함수 즉, 화면 출력을 위한 timer
        self.view_timer = QTimer()
        self.view_timer.timeout.connect(self.viewCam)

        self.detect_timer = QTimer()
        self.detect_timer.timeout.connect(self.Detection)

        # save 버튼을 누르는지 보기위한 timer
        self.save_timer = QTimer()
        self.save_timer.timeout.connect(self.saveName)

        # progressBar에 숫자를 표시해주기위한 timer
        self.progress_timer = QTimer()
        self.progress_timer.timeout.connect(self.progress)

        self.controlTimer()
        self.list()

        # set detection callback clicked  function
        # face registration 버튼을 누르면 faceRegistration 함수 호출
        self.registration.clicked.connect(self.faceRegistration)
        # detection 버튼을 누르면 faceDetection 함수 호출
        self.detection.clicked.connect(self.faceDetection)

        # Setup process and queues for multiprocessing.
        self.save_queue = Queue()
        self.progress_queue = Queue()

        # 얼굴 등록시 화면에서 계속 영상이 나오도록 등록 process를 따로 만들어줌
        self.save_process = Process(target=train,
                                    args=(self.save_queue, self.progress_queue,
                                          self.data_dir, self.model_path, 2))
        self.save_process.start()

    # progress bar에 표시해줄 숫자를 받아옴
    def progress(self):
        num = self.progress_queue.get()
        if num == 10000:
            self.log_browser.setText("등록완료")
            self.progress_timer.stop()
        self.progressBar.setProperty("value", num)

    # 등록한 사람들의 이름 리스트를 보여줌
    def list(self):
        msg = ""
        for class_dir in os.listdir(self.data_dir):
            if os.path.isdir(self.data_dir + class_dir):
                msg += str(class_dir + '\n')
        self.namelist.setText(msg)

    def faceDetection(self):
        # detect_timer가 stop상태이면 start시켜 detection 함수 호출
        if not self.detect_timer.isActive():
            if os.path.isfile(self.model_path) == False:
                self.log_browser.setText("model이 존재하지 않습니다. 등록하세요")
            else:
                self.log_browser.setText("[INFO] Start face detection")
                self.detect_timer.start(0.1)
                self.detection.setText("Stop")
        # detection 버튼을 다시 누르면 detect_timer가 start상태이므로 stop으로 변경
        else:
            self.detect_timer.stop()
            self.log_browser.setText("[INFO] Stop face detection")
            self.detection.setText("Start Detection")

    def Detection(self):
        # Grab a single frame of video
        ret, frame = self.cap.read()
        frame = cv2.flip(frame, 2)

        if ret is False:
            self.detect_timer.stop()
            self.log_browser.setText("[INFO] Detection is over...")
            self.detection.setText("Start Detection")

        # Resize frame of video to 1/4 size for faster face recognition processing
        try:
            small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25)

            # Convert the image from BGR color (which OpenCV uses) to RGB color (which face_recognition uses)
            rgb_small_frame = small_frame[:, :, ::-1]
        except Exception as e:
            print(str(e))

        # Find all the faces and face encodings in the current frame of video using a trained classifier model
        # Note: You can pass in either a classifier file name or a classifier model instance
        predictions = predict(rgb_small_frame, model_path=self.model_path)

        # 화면의 사람을 예측하여 얼굴에 bounding box로 표시
        # Display results overlaid on an image
        for name, (top, right, bottom, left) in predictions:
            # Scale back up face locations since the frame we detected in was scaled to 1/4 size
            top *= 4
            right *= 4
            bottom *= 4
            left *= 4

            # Draw a box around the face
            cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2)

            # Draw a label with a name below the face
            cv2.rectangle(frame, (left, bottom - 35), (right, bottom),
                          (0, 0, 255), cv2.FILLED)
            font = cv2.FONT_HERSHEY_DUPLEX
            cv2.putText(frame, name, (left + 6, bottom - 6), font, 1.0,
                        (255, 255, 255), 1)

        # cv2에서는 BGR이므로 RGB로 바꿈
        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

        # get image infos
        height, width, channel = frame.shape
        step = channel * width

        # create QImage from image
        qImg = QImage(frame, width, height, step, QImage.Format_RGB888)

        # show image in img_label
        self.image_label.setPixmap(QPixmap(qImg))
        self.detect_timer.start(0.1)

    # 이름을 쓰고 save버튼을 누를때까지 timer작동
    def saveName(self):
        self.log_browser.setText("이름을 입력하세요")
        self.progressBar.setProperty("value", 0)
        success = False
        if self.save_bt.isDown() is True:
            self.log_browser.setText("잠시만 기다리세요")
            name = self.edit.text()
            self.save_timer.stop()
            # print(name)
            for i in range(10):
                ret, frame = self.cap.read()
                frame = cv2.flip(frame, 2)
                image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                image = Image.fromarray(image)
                bounding_boxes = face_recognition.face_locations(frame)

                # 등록시 화면에 한명이 아닌경우
                if len(bounding_boxes) != 1:
                    self.log_browser.setText("등록실패! 한명만 시도하십시오")
                    success = False
                    break

                success = True
                image_name = "{:%Y%m%dT%H%M%S}_{}.jpg".format(
                    datetime.datetime.now(), i)

                if not os.path.isdir(self.data_dir + name):
                    os.mkdir(self.data_dir + name)
                image.save(self.data_dir + name + '/' + image_name)

        # 등록에 성공한 경우에만 progress_timer start
        if success:
            self.progress_timer.start(0.1)
            # save_queue에 무언가를 넣어줌으로써 train함수 작동
            self.save_queue.put(1)
            self.list()

    # save_timer를 작동시킴
    def faceRegistration(self):
        self.save_timer.start(0.1)
        self.log_browser.setText("Start face registration")

    def closeEvent(self, event):
        self.save_process.terminate()
        self.save_process.join()
        self.view_timer.stop()
        self.detect_timer.stop()
        self.save_timer.stop()
        self.cap.release()

    # view camera
    def viewCam(self):
        ret, frame = self.cap.read()  # 화면을 읽어오기 - 실패시 ret가 false

        if ret is False:
            self.view_timer.stop()
            self.cap.release()
            self.log_browser.setText("[INFO] video is over...")

        # If frame comes from webcam, flip it so it looks like a mirror.
        frame = cv2.flip(frame, 2)  # 화면 반전

        # OpenCV에서는 BGR 순서로 저장하니까 BGR을 RGB로
        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

        # get image infos
        height, width, channel = frame.shape
        step = channel * width
        # create QImage from image
        qImg = QImage(frame.data, width, height, step, QImage.Format_RGB888)

        # show image in img_label
        # QLabel은 이미지를 표시하는 라벨 위젯
        self.image_label.setPixmap(QPixmap.fromImage(qImg))

    # start/stop timer
    def controlTimer(self):
        # create video capture
        print("[INFO] starting video stream thread...")
        self.log_browser.setText("[INFO] starting video stream thread...")
        self.cap = cv2.VideoCapture(-1)  # cam 연결

        self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)  # 화면 크기 설정

        # start timer
        self.view_timer.start(20)  # view_timer start
Exemplo n.º 57
0
class MyPointer(QWidget):
    '''グラフにドロップできるポインタ ドロップされると点にsnapしてx,yに点の座標を表示する'''
    COLOR = 'yellow'
    ALPHA = 0.5
    SIZE = 18

    def __init__(self):
        super().__init__()
        row = QHBoxLayout()
        xlabel = QLabel('X:')
        self.xEdit = QTextEdit()
        self.xEdit.setReadOnly(True)
        self.xEdit.setFixedHeight(30)
        self.xEdit.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        ylabel = QLabel('Y:')
        self.yEdit = QTextEdit()
        self.yEdit.setReadOnly(True)
        self.yEdit.setFixedHeight(30)
        self.yEdit.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        button = QPushButton('✖')
        button.pressed.connect(self.reset)
        row.addWidget(xlabel)
        row.addWidget(self.xEdit)
        row.addWidget(ylabel)
        row.addWidget(self.yEdit)
        row.addWidget(button)
        row.addStretch(1)

        self.setLayout(row)

    def reset(self):
        try:
            self.point.remove()
            self.xEdit.setText(None)
            self.yEdit.setText(None)
            self.canvas.draw()
        except:
            pass

    def setXY(self, event):
        if not len(event.ind):
            return True
        self.ax = event.artist.axes
        try:  #すでにpointがあるとき
            if self.point.axes == self.ax:  #同じaxにpointがあるとき
                pass
            else:  #前と違うaxでクリックされた時
                self.point.remove()
                self.point, = self.ax.plot([], [],
                                           'o',
                                           ms=self.SIZE,
                                           alpha=self.ALPHA,
                                           color=self.COLOR,
                                           visible=False)
        except:  #初めてクリックした時
            self.point, = self.ax.plot([], [],
                                       'o',
                                       ms=self.SIZE,
                                       alpha=self.ALPHA,
                                       color=self.COLOR,
                                       visible=False)
        ind = event.ind[0]
        x = event.artist.get_xdata()[ind]
        y = event.artist.get_ydata()[ind]
        self.target = event.artist
        self.ind = ind
        clicked = (x, y)

        self.point.set_visible(True)
        self.point.set_data(clicked)
        self.canvas.draw()
        self.xEdit.setText(str(x))
        self.yEdit.setText(str(y))

    def startMove(self, event):
        try:
            self.timer.stop()
        except:
            pass
        self.timer = QTimer(self)
        if event.key == 'right':
            self.timer.timeout.connect(self.moveRight)
        elif event.key == 'left':
            self.timer.timeout.connect(self.moveLeft)
        self.timer.start(70)

    def stopMove(self, event):
        self.timer.stop()

    def moveRight(self):
        try:
            self.ind += 1
            x = self.target.get_xdata()[self.ind]
            y = self.target.get_ydata()[self.ind]
            self.point.set_data(x, y)
            self.canvas.draw()
            self.xEdit.setText(str(x))
            self.yEdit.setText(str(y))
        except:
            pass

    def moveLeft(self):
        try:
            self.ind -= 1
            x = self.target.get_xdata()[self.ind]
            y = self.target.get_ydata()[self.ind]
            self.point.set_data(x, y)
            self.canvas.draw()
            self.xEdit.setText(str(x))
            self.yEdit.setText(str(y))
        except:
            pass

    def activate(self, canvas):
        self.show()
        self.canvas = canvas
        self.pick = self.canvas.mpl_connect('pick_event', self.setXY)
        self.key_press = self.canvas.mpl_connect('key_press_event',
                                                 self.startMove)
        self.key_release = self.canvas.mpl_connect('key_release_event',
                                                   self.stopMove)
        self.canvas.setFocusPolicy(Qt.ClickFocus)
        self.canvas.setFocus()

    def deactivate(self):
        self.hide()
        self.reset()
        try:
            self.canvas.mpl_disconnect(self.pick)
            self.canvas.mpl_disconnect(self.key_press)
            self.canvas.mpl_disconnect(self.key_release)
        except:
            pass
Exemplo n.º 58
0
class RemoteSwitchV2(COMCUPluginBase, Ui_RemoteSwitchV2):
    qtcb_switching_done = pyqtSignal()

    def __init__(self, *args):
        COMCUPluginBase.__init__(self, BrickletRemoteSwitchV2, *args)

        self.setupUi(self)

        self.rs2 = self.device

        self.qtcb_switching_done.connect(self.cb_switching_done)
        self.rs2.register_callback(self.rs2.CALLBACK_SWITCHING_DONE,
                                   self.qtcb_switching_done.emit)

        self.h_check = (self.h_check_a,
                        self.h_check_b,
                        self.h_check_c,
                        self.h_check_d,
                        self.h_check_e)

        self.r_check = (self.r_check_a,
                        self.r_check_b,
                        self.r_check_c,
                        self.r_check_d,
                        self.r_check_e)

        for h in self.h_check:
            h.stateChanged.connect(self.h_check_state_changed)

        for r in self.r_check:
            r.stateChanged.connect(self.r_check_state_changed)

        self.checkbox_switchall.stateChanged.connect(self.switchall_state_changed)
        self.spinbox_house.valueChanged.connect(self.house_value_changed)
        self.spinbox_receiver.valueChanged.connect(self.receiver_value_changed)
        self.combo_type.currentIndexChanged.connect(self.type_index_changed)

        self.spinbox_dim_value.valueChanged.connect(self.spinbox_dim_value_changed)
        self.slider_dim_value.valueChanged.connect(self.slider_dim_value_changed)

        self.button_switch_on.clicked.connect(lambda: self.button_clicked(1))
        self.button_switch_off.clicked.connect(lambda: self.button_clicked(0))
        self.button_dim.clicked.connect(self.dim_clicked)

        self.combo_remote_type.currentIndexChanged.connect(self.remote_type_changed)
        self.button_remote_input_clear.clicked.connect(self.plaintextedit_remote_input.clear)

        self.current_remote_type = None
        self.timer_get_remote_input = QTimer(self)
        self.timer_get_remote_input.timeout.connect(self.timeout_get_remote_input)
        self.timer_get_remote_input.setInterval(50)

        self.last_remote_input = {
            'a': {
                'house_code': None,
                'receiver_code': None,
                'switch_to': None,
                'repeats': None
            },
            'b': {
                'address': None,
                'unit': None,
                'switch_to': None,
                'dim_value': None,
                'repeats': None
            },
            'c': {
                'system_code': None,
                'device_code': None,
                'switch_to': None,
                'repeats': None
            }
        }

        self.type_a_widgets = [self.label_house_code,
                               self.h_check_a,
                               self.h_check_b,
                               self.h_check_c,
                               self.h_check_d,
                               self.h_check_e,
                               self.spinbox_house,
                               self.label_receiver_code,
                               self.r_check_a,
                               self.r_check_b,
                               self.r_check_c,
                               self.r_check_d,
                               self.r_check_e,
                               self.spinbox_receiver,
                               self.button_switch_on,
                               self.button_switch_off]

        self.type_b_widgets = [self.label_address,
                               self.spinbox_address,
                               self.label_unit,
                               self.spinbox_unit,
                               self.checkbox_switchall,
                               self.button_switch_on,
                               self.button_switch_off]

        self.type_b_dim_widgets = [self.label_address,
                                   self.spinbox_address,
                                   self.label_unit,
                                   self.spinbox_unit,
                                   self.checkbox_switchall,
                                   self.label_dim,
                                   self.spinbox_dim_value,
                                   self.slider_dim_value,
                                   self.button_dim]

        self.type_c_widgets = [self.label_system_code,
                               self.combo_system_code,
                               self.label_device_code,
                               self.spinbox_device_code,
                               self.button_switch_on,
                               self.button_switch_off]

        self.type_widgets = (self.type_a_widgets,
                             self.type_b_widgets,
                             self.type_b_dim_widgets,
                             self.type_c_widgets)

        self.type_index_changed(0)

    def spinbox_dim_value_changed(self, value):
        self.slider_dim_value.setValue(value)

    def slider_dim_value_changed(self, value):
        self.spinbox_dim_value.setValue(value)

    def type_index_changed(self, index):
        for i in range(len(self.type_widgets)):
            if i != index:
                for w in self.type_widgets[i]:
                    w.setVisible(False)

        for w in self.type_widgets[index]:
            w.setVisible(True)

    def house_value_changed(self, state):
        for i in range(5):
            if state & (1 << i):
                self.h_check[i].setChecked(True)
            else:
                self.h_check[i].setChecked(False)

    def receiver_value_changed(self, state):
        for i in range(5):
            if state & (1 << i):
                self.r_check[i].setChecked(True)
            else:
                self.r_check[i].setChecked(False)

    def switchall_state_changed(self, state):
        if self.checkbox_switchall.isChecked():
            self.spinbox_address.setEnabled(False)
            self.spinbox_unit.setEnabled(False)
        else:
            self.spinbox_address.setEnabled(True)
            self.spinbox_unit.setEnabled(True)

    def h_check_state_changed(self, state):
        house_code = 0
        for i in range(5):
            if self.h_check[i].isChecked():
                house_code |= (1 << i)

        self.spinbox_house.setValue(house_code)

    def r_check_state_changed(self, state):
        receiver_code = 0
        for i in range(5):
            if self.r_check[i].isChecked():
                receiver_code |= (1 << i)

        self.spinbox_receiver.setValue(receiver_code)

    def get_remote_configuration_async(self, remote_config):
        self.current_remote_type = remote_config.remote_type

        self.spinbox_remote_minimum_repeats.setValue(remote_config.minimum_repeats)

        if remote_config.remote_type == self.rs2.REMOTE_TYPE_A:
            self.combo_remote_type.setCurrentIndex(self.rs2.REMOTE_TYPE_A)
        elif remote_config.remote_type == self.rs2.REMOTE_TYPE_B:
            self.combo_remote_type.setCurrentIndex(self.rs2.REMOTE_TYPE_B)
        elif remote_config.remote_type == self.rs2.REMOTE_TYPE_C:
            self.combo_remote_type.setCurrentIndex(self.rs2.REMOTE_TYPE_C)

    def start(self):
        async_call(self.rs2.get_remote_configuration,
                   None,
                   self.get_remote_configuration_async,
                   self.increase_error_count)

        self.timer_get_remote_input.start()

    def stop(self):
        self.timer_get_remote_input.stop()

    def destroy(self):
        pass

    def dim_clicked(self):
        self.button_dim.setEnabled(False)
        self.button_dim.setText("Dimming...")

        repeats = self.spinbox_repeats.value()
        self.rs2.set_repeats(repeats)

        if self.combo_type.currentIndex() == 2:
            address = self.spinbox_address.value()
            unit = self.spinbox_unit.value()
            if self.checkbox_switchall.isChecked():
                address = 0
                unit = 255

            dim_value = self.spinbox_dim_value.value()

            self.rs2.dim_socket_b(address, unit, dim_value)

    def remote_type_changed(self, index):
        self.current_remote_type = index
        remote_config = self.rs2.get_remote_configuration()

        self.rs2.set_remote_configuration(index,
                                          remote_config.minimum_repeats,
                                          remote_config.callback_enabled)

        remote_config = self.rs2.get_remote_configuration()

    def get_remote_status_a_async(self, remote_config):
        if remote_config.repeats <= self.spinbox_remote_minimum_repeats.value():
            return

        if self.last_remote_input['a']['house_code'] == remote_config.house_code and \
           self.last_remote_input['a']['receiver_code'] == remote_config.receiver_code and \
           self.last_remote_input['a']['switch_to'] == remote_config.switch_to and \
           self.last_remote_input['a']['repeats'] == remote_config.repeats:
            return

        if self.last_remote_input['a']['house_code'] == None and \
           self.last_remote_input['a']['receiver_code'] == None and \
           self.last_remote_input['a']['switch_to'] == None and \
           self.last_remote_input['a']['repeats'] == None:
            self.last_remote_input['a']['house_code'] = remote_config.house_code
            self.last_remote_input['a']['receiver_code'] = remote_config.receiver_code
            self.last_remote_input['a']['switch_to'] = remote_config.switch_to
            self.last_remote_input['a']['repeats'] = remote_config.repeats
            return

        self.last_remote_input['a']['house_code'] = remote_config.house_code
        self.last_remote_input['a']['receiver_code'] = remote_config.receiver_code
        self.last_remote_input['a']['switch_to'] = remote_config.switch_to
        self.last_remote_input['a']['repeats'] = remote_config.repeats

        remote_input = '''Remote Type - A:
House code = {house_code}
Receiver code = {receiver_code}
Switch to = {switch_to}
Repeats = {repeats}

'''.format(house_code=remote_config.house_code,
           receiver_code=remote_config.receiver_code,
           switch_to=remote_config.switch_to,
           repeats=remote_config.repeats)

        self.plaintextedit_remote_input.appendPlainText(remote_input)
        self.plaintextedit_remote_input.moveCursor(QTextCursor.End)

    def get_remote_status_b_async(self, remote_config):
        if remote_config.repeats <= self.spinbox_remote_minimum_repeats.value():
            return

        if self.last_remote_input['b']['address'] == remote_config.address and \
           self.last_remote_input['b']['unit'] == remote_config.unit and \
           self.last_remote_input['b']['switch_to'] == remote_config.switch_to and \
           self.last_remote_input['b']['dim_value'] == remote_config.dim_value and \
           self.last_remote_input['b']['repeats'] == remote_config.repeats:
            return

        if self.last_remote_input['b']['address'] == None and \
           self.last_remote_input['b']['unit'] == None and \
           self.last_remote_input['b']['switch_to'] == None and \
           self.last_remote_input['b']['dim_value'] == None and \
           self.last_remote_input['b']['repeats'] == None:
            self.last_remote_input['b']['address'] = remote_config.address
            self.last_remote_input['b']['unit'] = remote_config.unit
            self.last_remote_input['b']['switch_to'] = remote_config.switch_to
            self.last_remote_input['b']['dim_value'] = remote_config.dim_value
            self.last_remote_input['b']['repeats'] = remote_config.repeats
            return

        self.last_remote_input['b']['address'] = remote_config.address
        self.last_remote_input['b']['unit'] = remote_config.unit
        self.last_remote_input['b']['switch_to'] = remote_config.switch_to
        self.last_remote_input['b']['dim_value'] = remote_config.dim_value
        self.last_remote_input['b']['repeats'] = remote_config.repeats

        remote_input = '''Remote Type - B:
Address = {address}
Unit = {unit}
Switch to = {switch_to}
Dim value = {dim_value}
Repeats = {repeats}

'''.format(address=remote_config.address,
           unit=remote_config.unit,
           switch_to=remote_config.switch_to,
           dim_value=remote_config.dim_value,
           repeats=remote_config.repeats)

        self.plaintextedit_remote_input.appendPlainText(remote_input)
        self.plaintextedit_remote_input.moveCursor(QTextCursor.End)

    def get_remote_status_c_async(self, remote_config):
        if remote_config.repeats <= self.spinbox_remote_minimum_repeats.value():
            return

        if self.last_remote_input['c']['system_code'] == remote_config.system_code and \
           self.last_remote_input['c']['device_code'] == remote_config.device_code and \
           self.last_remote_input['c']['switch_to'] == remote_config.switch_to and \
           self.last_remote_input['c']['repeats'] == remote_config.repeats:
            return

        if self.last_remote_input['c']['system_code'] == None and \
           self.last_remote_input['c']['device_code'] == None and \
           self.last_remote_input['c']['switch_to'] == None and \
           self.last_remote_input['c']['repeats'] == None:
            self.last_remote_input['c']['system_code'] = remote_config.system_code
            self.last_remote_input['c']['device_code'] = remote_config.device_code
            self.last_remote_input['c']['switch_to'] = remote_config.switch_to
            self.last_remote_input['c']['repeats'] = remote_config.repeats
            return

        self.last_remote_input['c']['system_code'] = remote_config.system_code
        self.last_remote_input['c']['device_code'] = remote_config.device_code
        self.last_remote_input['c']['switch_to'] = remote_config.switch_to
        self.last_remote_input['c']['repeats'] = remote_config.repeats

        remote_input = '''Remote Type - C:
System code = {system_code}
Device code = {device_code}
Switch to = {switch_to}
Repeats = {repeats}

'''.format(system_code=remote_config.system_code,
           device_code=remote_config.device_code,
           switch_to=remote_config.switch_to,
           repeats=remote_config.repeats)

        self.plaintextedit_remote_input.appendPlainText(remote_input)
        self.plaintextedit_remote_input.moveCursor(QTextCursor.End)

    def timeout_get_remote_input(self):
        if self.current_remote_type == self.rs2.REMOTE_TYPE_A:
            async_call(self.rs2.get_remote_status_a,
                       None,
                       self.get_remote_status_a_async,
                       self.increase_error_count)
        elif self.current_remote_type == self.rs2.REMOTE_TYPE_B:
            async_call(self.rs2.get_remote_status_b,
                       None,
                       self.get_remote_status_b_async,
                       self.increase_error_count)
        elif self.current_remote_type == self.rs2.REMOTE_TYPE_C:
            async_call(self.rs2.get_remote_status_c,
                       None,
                       self.get_remote_status_c_async,
                       self.increase_error_count)

    def button_clicked(self, switch_to):
        self.button_switch_on.setEnabled(False)
        self.button_switch_on.setText("Switching...")
        self.button_switch_off.setEnabled(False)
        self.button_switch_off.setText("Switching...")

        repeats = self.spinbox_repeats.value()
        self.rs2.set_repeats(repeats)

        if self.combo_type.currentText() == 'A Switch':
            house_code = self.spinbox_house.value()
            receiver_code = self.spinbox_receiver.value()
            self.rs2.switch_socket_a(house_code, receiver_code, switch_to)
        elif self.combo_type.currentText() == 'B Switch':
            address = self.spinbox_address.value()
            unit = self.spinbox_unit.value()

            if self.checkbox_switchall.isChecked():
                address = 0
                unit = 255

            self.rs2.switch_socket_b(address, unit, switch_to)
        elif self.combo_type.currentText() == 'C Switch':
            system_code = self.combo_system_code.currentText()[0]
            device_code = self.spinbox_device_code.value()
            self.rs2.switch_socket_c(system_code, device_code, switch_to)

    def cb_switching_done(self):
        self.button_switch_on.setEnabled(True)
        self.button_switch_on.setText("Switch On")
        self.button_switch_off.setEnabled(True)
        self.button_switch_off.setText("Switch Off")
        self.button_dim.setEnabled(True)
        self.button_dim.setText("Dim")

    @staticmethod
    def has_device_identifier(device_identifier):
        return device_identifier == BrickletRemoteSwitchV2.DEVICE_IDENTIFIER
Exemplo n.º 59
0
class IMUV2(PluginBase, Ui_IMUV2):
    def __init__(self, *args):
        PluginBase.__init__(self, BrickIMUV2, *args)

        self.setupUi(self)

        self.imu = self.device

        self.cbe_all_data = CallbackEmulator(self.imu.get_all_data,
                                             None,
                                             self.cb_all_data,
                                             self.increase_error_count)

        self.imu_gl = IMUV23DWidget(self)
        self.imu_gl.setFixedSize(200, 200)

        self.imu_gl_wrapper = None
        self.state = None

        self.data_plot_widget = []

        self.sensor_data = [CurveValueWrapper() for i in range(23)]

        self.data_labels = [self.label_acceleration_x, self.label_acceleration_y, self.label_acceleration_z,
                            self.label_magnetic_field_x, self.label_magnetic_field_y, self.label_magnetic_field_z,
                            self.label_angular_velocity_x, self.label_angular_velocity_y, self.label_angular_velocity_z,
                            self.label_euler_angle_heading, self.label_euler_angle_roll, self.label_euler_angle_pitch,
                            self.label_quaternion_w, self.label_quaternion_x, self.label_quaternion_y, self.label_quaternion_z,
                            self.label_linear_acceleration_x, self.label_linear_acceleration_y, self.label_linear_acceleration_z,
                            self.label_gravity_vector_x, self.label_gravity_vector_y, self.label_gravity_vector_z,
                            self.label_temperature]

        self.data_rows = [[self.label_acceleration_11, self.label_acceleration_21, self.label_acceleration_22, self.label_acceleration_23, self.label_acceleration_41, self.label_acceleration_42, self.label_acceleration_43, self.label_acceleration_x, self.label_acceleration_y, self.label_acceleration_z],
                          [self.label_magnetic_field_11, self.label_magnetic_field_21, self.label_magnetic_field_22, self.label_magnetic_field_23, self.label_magnetic_field_41, self.label_magnetic_field_42, self.label_magnetic_field_43, self.label_magnetic_field_x, self.label_magnetic_field_y, self.label_magnetic_field_z],
                          [self.label_angular_velocity_11, self.label_angular_velocity_21, self.label_angular_velocity_22, self.label_angular_velocity_23, self.label_angular_velocity_41, self.label_angular_velocity_42, self.label_angular_velocity_43, self.label_angular_velocity_x, self.label_angular_velocity_y, self.label_angular_velocity_z],
                          [self.label_euler_angle_11, self.label_euler_angle_21, self.label_euler_angle_22, self.label_euler_angle_23, self.label_euler_angle_41, self.label_euler_angle_42, self.label_euler_angle_43, self.label_euler_angle_roll, self.label_euler_angle_pitch, self.label_euler_angle_heading],
                          [self.label_quaternion_11, self.label_quaternion_21, self.label_quaternion_22, self.label_quaternion_23, self.label_quaternion_24, self.label_quaternion_41, self.label_quaternion_42, self.label_quaternion_43, self.label_quaternion_44, self.label_quaternion_w, self.label_quaternion_x, self.label_quaternion_y, self.label_quaternion_z],
                          [self.label_linear_acceleration_11, self.label_linear_acceleration_21, self.label_linear_acceleration_22, self.label_linear_acceleration_23, self.label_linear_acceleration_41, self.label_linear_acceleration_42, self.label_linear_acceleration_43, self.label_linear_acceleration_x, self.label_linear_acceleration_y, self.label_linear_acceleration_z],
                          [self.label_gravity_vector_11, self.label_gravity_vector_21, self.label_gravity_vector_22, self.label_gravity_vector_23, self.label_gravity_vector_41, self.label_gravity_vector_42, self.label_gravity_vector_43, self.label_gravity_vector_x, self.label_gravity_vector_y, self.label_gravity_vector_z],
                          [self.label_temperature_11, self.label_temperature_21, self.label_temperature_41, self.label_temperature]]

        even_color = QColor(240, 240, 240)
        odd_color = QColor(255, 255, 255)

        self.data_color = [(Qt.red, even_color), (Qt.darkGreen, even_color), (Qt.blue, even_color),
                           (Qt.red, odd_color), (Qt.darkGreen, odd_color), (Qt.blue, odd_color),
                           (Qt.red, even_color), (Qt.darkGreen, even_color), (Qt.blue, even_color),
                           (Qt.red, odd_color), (Qt.darkGreen, odd_color), (Qt.blue, odd_color),
                           (Qt.magenta, even_color), (Qt.red, even_color), (Qt.darkGreen, even_color), (Qt.blue, even_color),
                           (Qt.red, odd_color), (Qt.darkGreen, odd_color), (Qt.blue, odd_color),
                           (Qt.red, even_color), (Qt.darkGreen, even_color), (Qt.blue, even_color),
                           (Qt.magenta, odd_color)]


        even_palette = QPalette()
        even_palette.setColor(QPalette.Window, even_color)
        odd_palette = QPalette()
        odd_palette.setColor(QPalette.Window, odd_color)

        for i, row in enumerate(self.data_rows):
            for label in row:
                if i % 2:
                    label.setPalette(odd_palette)
                else:
                    label.setPalette(even_palette)

                label.setAutoFillBackground(True)

        self.plot_timer = QTimer(self)
        self.plot_timer.start(100)

        for i in range(23):
            self.data_plot_widget.append(PlotWidget("",
                                                    [("", self.data_color[i][0], self.sensor_data[i], str)],
                                                    clear_button=self.clear_graphs,
                                                    x_scale_visible=False,
                                                    y_scale_visible=False,
                                                    curve_outer_border_visible=False,
                                                    curve_motion='smooth',
                                                    canvas_color=self.data_color[i][1],
                                                    external_timer=self.plot_timer,
                                                    curve_start='right',
                                                    key=None,
                                                    y_resolution=0.01))

        for w in self.data_plot_widget:
            w.setMinimumHeight(15)
            w.setMaximumHeight(25)

        for i in range(23):
            self.data_grid.addWidget(self.data_plot_widget[i], i, 4)

        self.data_grid.setColumnMinimumWidth(2, 75)

        self.gl_layout = QVBoxLayout()
        self.gl_layout.addWidget(self.imu_gl)
        self.layout_bottom.addLayout(self.gl_layout)
        self.save_orientation.clicked.connect(self.save_orientation_clicked)
        self.button_detach_3d_view.clicked.connect(self.detach_3d_view_clicked)

        self.checkbox_leds.stateChanged.connect(self.led_clicked)
        self.button_calibration.clicked.connect(self.calibration_clicked)
        self.calibration_color = [Qt.red, QColor(0xFF, 0xA0, 0x00), Qt.yellow, Qt.darkGreen]

        self.calibration = None
        self.alive = True
        self.callback_counter = 0

        self.status_led_action = QAction('Status LED', self)
        self.status_led_action.setCheckable(True)
        self.status_led_action.toggled.connect(lambda checked: self.imu.enable_status_led() if checked else self.imu.disable_status_led())
        self.set_configs([(0, None, [self.status_led_action])])

        reset = QAction('Reset', self)
        reset.triggered.connect(self.imu.reset)
        self.set_actions([(0, None, [reset])])

    def save_orientation_clicked(self):
        self.imu_gl.save_orientation()
        if self.imu_gl_wrapper is not None:
            self.imu_gl_wrapper.glWidget.save_orientation()
        self.orientation_label.hide()

    def cleanup_gl(self):
        self.state = self.imu_gl.get_state()
        self.imu_gl.hide()
        self.imu_gl.cleanup()

    def restart_gl(self):
        self.imu_gl = IMUV23DWidget()

        self.imu_gl.setFixedSize(200, 200)
        self.gl_layout.addWidget(self.imu_gl)
        self.imu_gl.show()

        self.save_orientation.clicked.connect(self.save_orientation_clicked)
        self.imu_gl.set_state(self.state)

    def start(self):
        if not self.alive:
            return

        self.parent().add_callback_on_untab(lambda x: self.cleanup_gl(), 'imu_v2_cleanup_on_untab')
        self.parent().add_callback_post_untab(lambda x: self.restart_gl(), 'imu_v2_restart_post_untab')
        self.parent().add_callback_on_tab(lambda x: self.cleanup_gl(), 'imu_v2_cleanup_on_tab')
        self.parent().add_callback_post_tab(lambda x: self.restart_gl(), 'imu_v2_restart_post_tab')

        self.gl_layout.activate()

        async_call(self.imu.is_status_led_enabled, None, self.status_led_action.setChecked, self.increase_error_count)
        async_call(self.imu.are_leds_on, None, self.checkbox_leds.setChecked, self.increase_error_count)

        self.cbe_all_data.set_period(50)

        for w in self.data_plot_widget:
            w.stop = False

    def stop(self):
        for w in self.data_plot_widget:
            w.stop = True

        if self.imu_gl_wrapper == None:
            self.cbe_all_data.set_period(0)

    def destroy(self):
        self.alive = False

        self.cleanup_gl()
        # Stop callback to fix deadlock with callback emulation thread.
        self.cbe_all_data.set_period(0)

        if self.calibration != None:
            self.calibration.close()

        if self.imu_gl_wrapper != None:
            self.imu_gl_wrapper.close()

    @staticmethod
    def has_device_identifier(device_identifier):
        return device_identifier == BrickIMUV2.DEVICE_IDENTIFIER

    def calibration_clicked(self):
        if self.calibration is None:
            self.calibration = Calibration(self)

        self.button_calibration.setEnabled(False)
        self.calibration.show()

    def detach_3d_view_clicked(self):
        if self.imu_gl_wrapper != None:
            self.imu_gl_wrapper.close()

        self.button_detach_3d_view.setEnabled(False)

        self.imu_gl_wrapper = WrapperWidget(self)
        self.imu_gl_wrapper.glWidget.set_state(self.imu_gl.get_state())
        self.save_orientation.clicked.connect(self.save_orientation_clicked)

        self.imu_gl_wrapper.show()

    def cb_all_data(self, data):
        self.callback_counter += 1

        if self.callback_counter == 2:
            self.callback_counter = 0

            self.sensor_data[0].value  = data.acceleration[0] / 100.0
            self.sensor_data[1].value  = data.acceleration[1] / 100.0
            self.sensor_data[2].value  = data.acceleration[2] / 100.0
            self.sensor_data[3].value  = data.magnetic_field[0] / 16.0
            self.sensor_data[4].value  = data.magnetic_field[1] / 16.0
            self.sensor_data[5].value  = data.magnetic_field[2] / 16.0
            self.sensor_data[6].value  = data.angular_velocity[0] / 16.0
            self.sensor_data[7].value  = data.angular_velocity[1] / 16.0
            self.sensor_data[8].value  = data.angular_velocity[2] / 16.0
            self.sensor_data[9].value  = data.euler_angle[0] / 16.0
            self.sensor_data[10].value = data.euler_angle[1] / 16.0
            self.sensor_data[11].value = data.euler_angle[2] / 16.0
            self.sensor_data[12].value = data.quaternion[0] / (2 ** 14 - 1)
            self.sensor_data[13].value = data.quaternion[1] / (2 ** 14 - 1)
            self.sensor_data[14].value = data.quaternion[2] / (2 ** 14 - 1)
            self.sensor_data[15].value = data.quaternion[3] / (2 ** 14 - 1)
            self.sensor_data[16].value = data.linear_acceleration[0] / 100.0
            self.sensor_data[17].value = data.linear_acceleration[1] / 100.0
            self.sensor_data[18].value = data.linear_acceleration[2] / 100.0
            self.sensor_data[19].value = data.gravity_vector[0] / 100.0
            self.sensor_data[20].value = data.gravity_vector[1] / 100.0
            self.sensor_data[21].value = data.gravity_vector[2] / 100.0
            self.sensor_data[22].value = data.temperature

            for i in range(23):
                self.data_labels[i].setText("{0:.2f}".format(self.sensor_data[i].value))

            self.imu_gl.update_orientation(self.sensor_data[12].value,
                               self.sensor_data[13].value,
                               self.sensor_data[14].value,
                               self.sensor_data[15].value)

            if self.imu_gl_wrapper is not None:
                self.imu_gl_wrapper.glWidget.update_orientation(self.sensor_data[12].value,
                                                    self.sensor_data[13].value,
                                                    self.sensor_data[14].value,
                                                    self.sensor_data[15].value)

            cal_mag = data.calibration_status & 3
            cal_acc = (data.calibration_status & (3 << 2)) >> 2
            cal_gyr = (data.calibration_status & (3 << 4)) >> 4
            cal_sys = (data.calibration_status & (3 << 6)) >> 6

            if self.calibration != None:
                self.calibration.save_calibration.setEnabled(data.calibration_status == 0xFF)

                self.calibration.mag_color.set_color(self.calibration_color[cal_mag])
                self.calibration.acc_color.set_color(self.calibration_color[cal_acc])
                self.calibration.gyr_color.set_color(self.calibration_color[cal_gyr])
                self.calibration.sys_color.set_color(self.calibration_color[cal_sys])
        else:
            self.imu_gl.update_orientation(data.quaternion[0] / (2 ** 14 - 1),
                               data.quaternion[1] / (2 ** 14 - 1),
                               data.quaternion[2] / (2 ** 14 - 1),
                               data.quaternion[3] / (2 ** 14 - 1))

            if self.imu_gl_wrapper is not None:
                self.imu_gl_wrapper.glWidget.update_orientation(data.quaternion[0] / (2 ** 14 - 1),
                                                    data.quaternion[1] / (2 ** 14 - 1),
                                                    data.quaternion[2] / (2 ** 14 - 1),
                                                    data.quaternion[3] / (2 ** 14 - 1))

    def led_clicked(self, state):
        if state == Qt.Checked:
            self.imu.leds_on()
        else:
            self.imu.leds_off()
Exemplo n.º 60
0
class RobotTracking(QWidget):
    """
    The 'RobotTracking' class is a QWidget subclass that allows the user
     to follow the robot position from an initialized origin point.
    """

    def __init__(self):
        """
        The 'RobotTracking' class constructor initializes, notably, the
        widget to follow the robot's position. It builds upon the
        constructor of its parent class, 'QWidget'.
        """
        super().__init__()
        self.setStyleSheet("border:1px solid rgb(0, 0, 0)")
        self._distance_origin = 0
        self._robot_x_pos = 200
        self._robot_y_pos = 200
        self._target_x_pos = 250
        self._target_y_pos = 250
        self._vel = 60  # pixels per second
        self._speed = 10

        self.timer = QTimer(self)
        self.timer.start(round(1000 / self._vel))
        self.initTracking()

    def initTracking(self):
        """
        Sets the size of the widget and its label (tracking distance and
        position).
        """
        self.setMinimumSize(UI_MIN_W, UI_MIN_H)
        self.label = QLabel(self)
        self.label.resize(TRACK_W, TRACK_H)
        self.label.setStyleSheet("color : rgb(0,0,0)")
        self.show()

    def changePosition(self, direction):
        """
        Updates the target's distance and position according to
        geometry.
        """
        UI_Graph_W = self.geometry().width()
        UI_Graph_H = self.geometry().height()

        if direction == STR_F and self._robot_y_pos > 0:
            self._robot_y_pos -= self._speed
            ENCODED_VAR = stringToByte('FORWARD')
        elif direction == STR_B and self._robot_y_pos < UI_Graph_H:
            self._robot_y_pos += self._speed
            ENCODED_VAR = stringToByte('BACKWARD')
        elif direction == STR_R and self._robot_x_pos < UI_Graph_W:
            self._robot_x_pos += self._speed
            ENCODED_VAR = stringToByte('RIGHT')
        elif direction == STR_L and self._robot_x_pos > 0:
            self._robot_x_pos -= self._speed
            ENCODED_VAR = stringToByte('LEFT')

        self.moveRobot(self._robot_x_pos, self._robot_y_pos)
        self.update()

    def moveRobot(self, robotX, robotY):
        """
        Event that updates the target's distance and position label
        relative to the origin according to the target's movements.
        """
        self._distance_origin = round(
            ((robotY - self._target_y_pos)**2
             + (robotX - self._target_x_pos)**2)**0.5
        )

        self.label.setText(
            "Coordinates (x; y): ({}; {})\nDistance from origin: {}"
            .format(robotX, robotY, self._distance_origin)
        )

        self.update()

    def initPosition(self):
        """
        Event that updates the origin point according to reset command.
        """
        self._target_x_pos = self._robot_x_pos
        self._target_y_pos = self._robot_y_pos
        self.update()

    def paintEvent(self, event):
        """
        Event that draws a line between the target's position and its
        origin.
        """
        robot = QPixmap(SCRIPT_DIR + SEP + LOGO)
        pix_robot = robot.scaledToHeight(40)

        q = QPainter()
        q.begin(self)
        q.setPen(QColor(0, 0, 0))
        q.drawPixmap(QPoint(self._robot_x_pos-20, self._robot_y_pos-20),
                     pix_robot)
        q.drawLine(self._robot_x_pos, self._robot_y_pos,
                   self._target_x_pos, self._target_y_pos)
        moving_command = byteToString(ENCODED_VAR)
        
        '''