示例#1
0
文件: main.py 项目: zwenlong666/pqcom
class MainWindow(QMainWindow, main_ui.Ui_MainWindow):
    serial_failed = Signal()
    data_received = Signal()

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

        self.collections = []
        try:
            saved = open(PQCOM_DATA_FILE, 'rb')
            self.collections = pickle.load(saved)
            saved.close()
        except IOError:
            pass

        self.input_history = ''
        self.output_history = []
        self.repeater = Repeater()

        self.setWindowIcon(QIcon(resource_path('img/pqcom-logo.png')))

        self.aboutDialog = AboutDialog(self)

        self.setupDialog = SetupDialog(self)
        port, baud, bytebits, stopbits, parity = self.setupDialog.get()
        self.setWindowTitle('pqcom - ' + port + ' ' + str(baud))

        self.actionNew.setIcon(QIcon(resource_path('img/new.svg')))
        self.actionSetup.setIcon(QIcon(resource_path('img/settings.svg')))
        self.actionRun.setIcon(QIcon(resource_path('img/run.svg')))
        self.actionHex.setIcon(QIcon(resource_path('img/hex.svg')))
        self.actionClear.setIcon(QIcon(resource_path('img/clear.svg')))
        self.actionPin.setIcon(QIcon(resource_path('img/pin.svg')))
        self.actionAbout.setIcon(QIcon(resource_path('img/about.svg')))

        self.actionUseCR = QAction('EOL - \\r', self)
        self.actionUseCR.setCheckable(True)
        self.actionUseLF = QAction('EOL - \\n', self)
        self.actionUseLF.setCheckable(True)
        self.actionUseCRLF = QAction('EOL - \\r\\n', self)
        self.actionUseCRLF.setCheckable(True)
        self.actionUseCRLF.setChecked(True)
        eolGroup = QActionGroup(self)
        eolGroup.addAction(self.actionUseCR)
        eolGroup.addAction(self.actionUseLF)
        eolGroup.addAction(self.actionUseCRLF)
        eolGroup.setExclusive(True)

        self.actionAppendEol = QAction('Append extra EOL', self)
        self.actionAppendEol.setCheckable(True)

        popupMenu = QMenu(self)
        popupMenu.addAction(self.actionUseCR)
        popupMenu.addAction(self.actionUseLF)
        popupMenu.addAction(self.actionUseCRLF)
        popupMenu.addSeparator()
        popupMenu.addAction(self.actionAppendEol)
        self.sendButton.setMenu(popupMenu)

        self.outputHistoryActions = []
        self.outputHistoryMenu = QMenu(self)
        self.outputHistoryMenu.addAction('None')
        self.historyButton.setMenu(self.outputHistoryMenu)

        self.collectActions = []
        self.collectMenu = QMenu(self)
        self.collectMenu.setTearOffEnabled(True)
        if not self.collections:
            self.collectMenu.addAction('None')
        else:
            for item in self.collections:
                icon = QIcon(resource_path(ICON_LIB[item[0]]))
                action = self.collectMenu.addAction(icon, item[1])
                self.collectActions.append(action)

        self.collectButton.setMenu(self.collectMenu)
        self.collectButton.setIcon(QIcon(resource_path('img/star.svg')))

        self.collectMenu.setContextMenuPolicy(Qt.CustomContextMenu)
        # self.connect(self.collectMenu, QtCore.SIGNAL('customContextMenuRequested(const QPoint&)'),
                    #  self.on_collect_context_menu)
        self.collectContextMenu = QMenu(self)
        self.removeCollectionAction = QAction('Remove', self)
        self.removeAllCollectionsAction = QAction('Remove all', self)
        self.collectContextMenu.addAction(self.removeCollectionAction)
        self.collectContextMenu.addAction(self.removeAllCollectionsAction)

        self.activeCollectAction = None

        self.removeCollectionAction.triggered.connect(self.remove_collection)
        self.removeAllCollectionsAction.triggered.connect(self.remove_all_collections)

        self.sendButton.clicked.connect(self.send)
        self.repeatCheckBox.toggled.connect(self.repeat)
        self.actionSetup.triggered.connect(self.setup)
        self.actionNew.triggered.connect(self.new)
        self.actionRun.toggled.connect(self.run)
        self.actionHex.toggled.connect(self.convert)
        self.actionClear.triggered.connect(self.clear)
        self.actionPin.toggled.connect(self.pin)
        self.actionAbout.triggered.connect(self.aboutDialog.show)
        self.outputHistoryMenu.triggered.connect(self.on_history_item_clicked)
        self.collectButton.clicked.connect(self.collect)
        self.collectMenu.triggered.connect(self.on_collect_item_clicked)

        self.serial_failed.connect(self.handle_serial_error)
        self.data_received.connect(self.display)

        QShortcut(QKeySequence('Ctrl+Return'), self.sendPlainTextEdit, self.send)

        def gen_shortcut_callback(n):
            def on_shortcut():
                self.send_collection(n - 1)

            return on_shortcut

        for i in range(1, 10):
            QShortcut(QKeySequence('Ctrl+' + str(i)), self, gen_shortcut_callback(i))

        # self.extendRadioButton.setVisible(False)
        self.periodSpinBox.setVisible(False)

    def new(self):
        save = open(PQCOM_DATA_FILE, 'wb')
        pickle.dump(self.collections, save)
        save.close()

        args = sys.argv
        if args != [sys.executable]:
            args = [sys.executable] + args
        subprocess.Popen(args)

    def send(self):
        if self.repeatCheckBox.isChecked():
            if self.sendButton.text().find('Stop') >= 0:
                self.repeater.stop()
                self.sendButton.setText('Start')
                return

        raw = str(self.sendPlainTextEdit.toPlainText())
        data = raw
        form = 'N'
        if self.normalRadioButton.isChecked():
            if self.actionAppendEol.isChecked():
                data += '\n'

            if self.actionUseCRLF.isChecked():
                data = data.replace('\n', '\r\n')
            elif self.actionUseCR.isChecked():
                data = data.replace('\n', '\r')
        elif self.hexRadioButton.isChecked():
            form = 'H'
            data = translator.from_hex_string(data)
        else:
            form = 'E'
            data = translator.from_extended_string(data)

        if self.repeatCheckBox.isChecked():
            self.repeater.start(data, self.periodSpinBox.value())
            self.sendButton.setText('Stop')
        else:
            serial.write(data)

        # record history
        record = [form, raw, data]
        if record in self.output_history:
            self.output_history.remove(record)

        self.output_history.insert(0, record)

        self.outputHistoryActions = []
        self.outputHistoryMenu.clear()
        for item in self.output_history:
            icon = QIcon(resource_path(ICON_LIB[item[0]]))

            action = self.outputHistoryMenu.addAction(icon, item[1])
            self.outputHistoryActions.append(action)

    def repeat(self, is_true):
        if is_true:
            self.periodSpinBox.setVisible(True)
            self.sendButton.setText('Start')
        else:
            self.periodSpinBox.setVisible(False)
            self.sendButton.setText('Send')
            self.repeater.stop()

    def on_history_item_clicked(self, action):
        try:
            index = self.outputHistoryActions.index(action)
        except ValueError:
            return

        form, raw, data = self.output_history[index]
        if form == 'H':
            self.hexRadioButton.setChecked(True)
        elif form == 'E':
            self.extendRadioButton.setChecked(True)
        else:
            self.normalRadioButton.setChecked(True)

        self.sendPlainTextEdit.clear()
        self.sendPlainTextEdit.insertPlainText(raw)
        self.send()

    def collect(self):
        if not self.collections:
            self.collectMenu.clear()
        raw = str(self.sendPlainTextEdit.toPlainText())
        form = 'N'
        if self.hexRadioButton.isChecked():
            form = 'H'
        elif self.extendRadioButton.isChecked():
            form = 'E'

        item = [form, raw]
        if item in self.collections:
            return

        self.collections.append(item)
        icon = QIcon(resource_path(ICON_LIB[form]))
        action = self.collectMenu.addAction(icon, raw)
        self.collectActions.append(action)

    def on_collect_context_menu(self, point):
        self.activeCollectAction = self.collectMenu.activeAction()
        self.collectContextMenu.exec_(self.collectMenu.mapToGlobal(point))

    def on_collect_item_clicked(self, action):
        try:
            index = self.collectActions.index(action)
        except ValueError:
            return
        self.send_collection(index)

    def send_collection(self, index):
        if len(self.collections) > index:
            form, raw = self.collections[index]
            if form == 'H':
                self.hexRadioButton.setChecked(True)
            elif form == 'E':
                self.extendRadioButton.setChecked(True)
            else:
                self.normalRadioButton.setChecked(True)

            self.sendPlainTextEdit.clear()
            self.sendPlainTextEdit.insertPlainText(raw)
            self.send()

    def remove_collection(self):
        try:
            index = self.collectActions.index(self.activeCollectAction)
        except ValueError:
            return

        del self.collectActions[index]
        del self.collections[index]

        self.collectMenu.clear()
        for item in self.collections:
            icon = QIcon(resource_path(ICON_LIB[item[0]]))
            action = self.collectMenu.addAction(icon, item[1])
            self.collectActions.append(action)

        save = open(PQCOM_DATA_FILE, 'wb')
        pickle.dump(self.collections, save)
        save.close()

    def remove_all_collections(self):
        self.collectMenu.clear()
        self.collections = []
        self.collectActions = []
        self.collectMenu.addAction('None')

        save = open(PQCOM_DATA_FILE, 'wb')
        save.close()
        pickle.dump(self.collections, save)

    def on_serial_failed(self):
        if self.sendButton.text().find('Stop') >= 0:
            self.repeater.stop()
            self.sendButton.setText('Start')
        self.serial_failed.emit()

    def handle_serial_error(self):
        self.actionRun.setChecked(False)
        self.setup(True)

    def on_data_received(self):
        self.data_received.emit()

    def setup(self, warning=False):
        choice = self.setupDialog.show(warning)
        if choice == QDialog.Accepted:
            if self.actionRun.isChecked():
                self.actionRun.setChecked(False)
            self.actionRun.setChecked(True)

    def run(self, is_true):
        port, baud, bytebits, stopbits, parity = self.setupDialog.get()
        if is_true:
            serial.start(port, baud, bytebits, stopbits, parity)
            self.setWindowTitle('pqcom - ' + port + ' ' + str(baud) + ' opened')
        else:
            if self.sendButton.text().find('Stop') >= 0:
                self.repeater.stop()
                self.sendButton.setText('Start')
            serial.join()
            self.setWindowTitle('pqcom - ' + port + ' ' + str(baud) + ' closed')

    def display(self):
        data = serial.read()
        self.input_history += data  # store history data

        if self.actionHex.isChecked():
            data = translator.to_hex_prefix_string(data)

        self.recvTextEdit.moveCursor(QTextCursor.End)
        self.recvTextEdit.insertPlainText(data)
        self.recvTextEdit.moveCursor(QTextCursor.End)

    def convert(self, is_true):
        if is_true:
            text = translator.to_hex_prefix_string(self.input_history)
        else:
            text = self.input_history

        self.recvTextEdit.clear()
        self.recvTextEdit.insertPlainText(text)
        self.recvTextEdit.moveCursor(QTextCursor.End)

    def pin(self, is_true):
        if is_true:
            self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)
        else:
            self.setWindowFlags(self.windowFlags() & ~Qt.WindowStaysOnTopHint)

        self.show()

    def clear(self):
        self.recvTextEdit.clear()
        self.input_history = ''

    def closeEvent(self, event):
        save = open(PQCOM_DATA_FILE, 'wb')
        pickle.dump(self.collections, save)
        save.close()

        event.accept()
示例#2
0
class Slideshow(QMainWindow):
    
    def __init__(self, parent, gallery=list(), index=0):
        
        super(Slideshow, self).__init__()
        self.parent = parent
        self.configure_gui()
        self.create_widgets(gallery)
        self.create_menu()
        self.index = index
        self.move()
        self.showMaximized()
        self.activateWindow()
    
    def configure_gui(self):
        
        self.stack = QStackedWidget(self)
        self.setCentralWidget(self.stack)

    def create_widgets(self, gallery):
        
        self.model = Model(self, gallery)

        self.image = imageViewer(self)
        self.video = videoPlayer(self)
        self.stack.addWidget(self.image)
        self.stack.addWidget(self.video)
        
        self.setMouseTracking(True)
        self.timer = QTimer()
        self.timer.timeout.connect(
            lambda: self.setCursor(Qt.BlankCursor)
            )
        
    def create_menu(self):

        self.menubar = self.menuBar()
        self.menubar.triggered.connect(self.menuPressEvent)
        
        # File
        file = self.menubar.addMenu('File')
        file.addAction('Copy Image to',  lambda: copy_to(self, [self.model.index(self.index)]), shortcut='CTRL+SHIFT+C')
        file.addSeparator()
        file.addAction('Exit', self.close, shortcut='Ctrl+W')
        
        # View
        view = self.menubar.addMenu('View')
        view.addAction('Fullscreen', self.fullscreen, shortcut='F11')
        
        # Help
        help = self.menubar.addMenu('Help')
        
        menu = QMenu(self)
        # menu = create_menu(
            # self,
            
            # )

        self.full = QAction(
            'Fullscreen', menu, triggered=self.fullscreen
            )
        menu.addAction(self.full)
        
        self.play_menu = QMenu('Slideshow')
        group1 = QActionGroup(self.play_menu)
        group1.setExclusive(True)
        self.play_menu.addActions([
                QAction(
                    'Pause', self.play_menu, triggered=self.playEvent, checked=True
                    ),
                QAction(
                    'Play', self.play_menu, triggered=self.playEvent
                    )
            ])
        self.play_menu.addSeparator()
        group2 = QActionGroup(self.play_menu)
        group2.setExclusive(True)
        self.play_menu.addActions([
                QAction(
                    'Speed - Slow', self.play_menu, triggered=self.playEvent
                ),
                QAction(
                    'Speed - Medium', self.play_menu, triggered=self.playEvent, checked=True
                ),
                QAction(
                    'Speed - Fast', self.play_menu, triggered=self.playEvent
                )
            ])
        # menu.addMenu(self.play_menu)
        
        menu.addSeparator()
        
        menu.addAction(QAction(
            'Rotate right', menu, triggered=lambda: self.rotate(+1)
            ))
        menu.addAction(QAction(
            'Rotate left', menu, triggered=lambda: self.rotate(-1)
            ))
        
        menu.addSeparator()
        
        menu.addAction(QAction(
            'Copy', menu, triggered=self.copy
            ))
        menu.addAction(QAction(
            'Delete', menu, triggered=self.delete
            ))
        
        menu.addSeparator()
        
        menu.addAction(QAction(
            'Properties', menu, triggered=self.openEditor
            ))

        self.menu = menu

    def move(self, delta=0):
        
        if not self.model.gallery:
            self.image.no_image()
            return 0
        
        self.index = (self.index + delta) % len(self.model.gallery)
        path = self.model.index(self.index).data(Qt.UserRole)[0]
        self.setWindowTitle(f'{Path(path).name} - Slideshow')

        if path is None: pixmap = QPixmap()
        else:
            if path.endswith(('.jpg', '.png')):
                image = QImage(path)
                path = None
            elif path.endswith(('.gif', '.mp4', '.webm')):
                image = get_frame(path)
            else: print(path)
            
            pixmap = QPixmap(image).scaled(
                self.size(), Qt.KeepAspectRatio, 
                transformMode=Qt.SmoothTransformation
                )

        self.image.update(pixmap)
        self.stack.setCurrentIndex(0)
        self.video.update(path)
    
    def fullscreen(self):

        if self.isFullScreen():

            self.timer.stop()
            self.image.setStyleSheet('background: ')
            self.full.setText('Fullscreen')
            self.setCursor(Qt.ArrowCursor)
            self.showMaximized()
            self.menubar.show()

        else:

            self.image.setStyleSheet('background: black')
            self.full.setText('Exit fullscreen')
            self.setCursor(Qt.BlankCursor)
            self.menubar.hide()
            self.showFullScreen()

    def rotate(self, sign):

        path = self.model.index(self.index).data(Qt.UserRole)[0]

        if path.endswith(('jpg', 'png')):
            self.image.rotate(path, sign)
        
        else:
            self.video.rotate(path, sign)
            
        self.move()

    def copy(self):
        
        path = self.model.index(self.index).data(Qt.UserRole)[0]

        if path.endswith(('gif', '.mp4', '.webm')):
            return

            path = mktemp(suffix='.png')
            image = ImageGrab.grab(
                (0, 0, self.width(),self.height())
                )
            image.save(path)

        cb = QApplication.clipboard()
        cb.clear(mode=cb.Clipboard)
        cb.setText(path, mode=cb.Clipboard)

    def delete(self):
        
        if self.stack.currentIndex():
            self.video.update(None)
        else: self.image.update(None)
        
        index = [self.model.index(self.index)]

        if self.parent.delete_records(index):
            del self.model.gallery[self.index]
            self.model.layoutChanged.emit()

    def openEditor(self):

        index = self.model.index(self.index)
        
        Properties(self.parent, [index.data(Qt.EditRole)])
    
    def playEvent(self, event):
        
        match self.play_menu.activeAction().text:
            
            case 'Speed - Slow': pass
            case 'Speed - Medium': pass
            case 'Speed - Fast': pass
          
    def contextMenuEvent(self, event):
        
        self.menu.popup(event.globalPos())

    def menuPressEvent(self, event=None):

        action = event.text()
        
        # if action == 'Copy Image to':
            
        #     copy_to(self, [self.model.index(self.index)])

        if action == 'Exit': self.close()
        
    def keyPressEvent(self, event):

        key_press = event.key()
        video = self.stack.currentIndex()
        alt = event.modifiers() == Qt.AltModifier
        ctrl = event.modifiers() == Qt.ControlModifier
        shift = event.modifiers() == Qt.ShiftModifier

        if key_press in (Qt.Key_Right, Qt.Key_Left):
            
            self.move(1 if key_press == Qt.Key_Right else -1)
            
        elif video and key_press in (Qt.Key_Home, Qt.Key_End):
            
            if key_press == Qt.Key_Home: self.video.position(0)
            else: self.video.position(0)
            
        elif video and key_press in (Qt.Key_Period, Qt.Key_Comma):

            sign = 1 if key_press == Qt.Key_Period else -1
            if ctrl: self.video.position(sign * 50)
            else: self.video.position(sign * 5000)
        
        elif video and key_press in (Qt.Key_Up, Qt.Key_Down):

            sign = 1 if key_press == Qt.Key_Up else -1
            if ctrl: self.video.volume(sign * 1)
            else: self.video.volume(sign * 10)
        
        elif video and key_press == Qt.Key_Space: self.video.pause()
        
        elif video and key_press == Qt.Key_M: self.video.mute()
        
        elif key_press == Qt.Key_Delete: self.delete()
        
        elif key_press == Qt.Key_F11: self.fullscreen()

        elif key_press == Qt.Key_Escape:
            
            if self.isFullScreen(): self.fullscreen()
            else: self.close()
        
        elif alt:
            
            if key_press in (Qt.Key_Return, Qt.Key_Enter): self.openEditor()
            
        elif ctrl:
            
            if shift and key_press == Qt.Key_C: opy_to(self, [self.model.index(self.index)])
            
            elif key_press == Qt.Key_C: self.copy()
            
            elif key_press == Qt.Key_W: self.close()
    
    def mousePressEvent(self, event):
        
        if event.button() == Qt.MouseButton.LeftButton:
            
            if event.x() > (self.width() * .5): self.move(+1)
            elif event.x() < (self.width() * .5): self.move(-1)
    
    def mouseMoveEvent(self, event):
        
        if self.isFullScreen():

            self.setCursor(Qt.ArrowCursor)
            self.timer.start(1500)
        
    def closeEvent(self, event): self.video.update(None)