示例#1
0
 def __init__(self, parent=None, pixmap=None):
     super().__init__(parent, Qt.Dialog)
     self.parent = parent
     self.min_width = 100  #px
     self.max_width = pixmap.width() * 3
     _width = min(pixmap.width(),
                  QDesktopWidget().availableGeometry().width())
     pixmap = pixmap.scaledToWidth(_width, Qt.SmoothTransformation)
     self.pixmap = pixmap
     self.now_width = pixmap.width()
     #
     self.grid = QGridLayout()
     self.grid.setSpacing(0)
     self.grid.setContentsMargins(0, 0, 0, 0)
     self.label = QLabel('ImagePreviewer', self)
     self.label.setPixmap(pixmap)
     self.grid.addWidget(self.label, 0, 0)
     self.grid.setSizeConstraint(QLayout.SetFixedSize)
     self.setLayout(self.grid)
     self.resize(self.sizeHint())
     #
     qr = self.frameGeometry()
     cp = QDesktopWidget().availableGeometry().center()
     qr.moveCenter(cp)
     self.move(qr.topLeft())
     #
     self.keysFn = KeysReactor(self)
     self.keysFn.register(CFG.KEYS_CLOSE(), lambda: self.close())
     self.keysFn.register(CFG.KEYS_CLOSE1(self), lambda: self.close())
     self.keysFn.register(CFG.KEYS_CLOSE2(self), lambda: self.close())
     #
     self.styleHelper()
     self.setFocus()
     self.show()
     pass
示例#2
0
 def __init__(self, parent):
     super().__init__(parent)
     self.parent = parent
     self.w_history = parent.parent
     self.keysFn = KeysReactor(self)
     self.registerKeys()
     self.styleHelper()
     pass
示例#3
0
class InputBox(QPlainTextEdit):
    def __init__(self, parent):
        super().__init__(parent)
        self.parent = parent
        self.w_history = parent.parent
        self.keysFn = KeysReactor(self)
        self.registerKeys()
        self.styleHelper()
        pass

    def styleHelper(self):
        self.setFont(CFG.FONT_DEFAULT(self))
        self.setPlaceholderText("Search with Regex ...")
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setFixedSize(*CFG.SIZE_TOPBAR_MAIN())
        self.setVisible(False)
        pass

    def registerKeys(self):
        self.keysFn.register(CFG.KEYS_EDIT(self), lambda: self.setFilter())
        self.keysFn.register(CFG.KEYS_CLOSE(), lambda: self.focusOut())
        pass

    def setFilter(self):
        _regex = self.toPlainText()
        if len(_regex) > 0:
            # _regex = re.sub(r'(?<!\\)\*', "(.*)", _regex)
            _regex = re.compile(_regex, re.IGNORECASE)
            self.w_history.setFilter(_regex)
        else:
            self.w_history.setFilter(None)
        self.focusOut()
        pass

    def focusOut(self):
        self.parent.switch()
        self.w_history.setFocus()
        pass

    def focusOutEvent(self, e):
        if len(self.toPlainText()) == 0:
            self.w_history.setFilter(None)
        return super().focusOutEvent(e)

    pass
示例#4
0
 def __init__(self, parent, w_history, w_todo):
     super().__init__(parent)
     self.parent = parent
     self.w_history = w_history
     self.w_todo = w_todo
     self.clipboard = QApplication.clipboard()
     #
     self.pressed = False
     self.press_pos = QPoint(0, 0)
     self.init_pos = self.parent.pos()
     self.font_style = QFont(CFG.FONT_DEFAULT(self))
     self.font_metric = QFontMetrics(self.font_style)
     self.styleHelper()
     #
     self.setAcceptDrops(True)
     self.textChanged.connect(self.textChangedEvent)
     self.keysFn = KeysReactor(self, 'MFTextEdit')
     self.keysFn.setKeyPressHook(self.showCaret)
     self.registerKeys()
     pass
示例#5
0
 def __init__(self):
     super().__init__()
     self.mf_exec = mf_exec
     self.w_todo = MFTodoWidget(self, MF_DIR, sync=False)
     self.w_history = MFHistory(self, MF_DIR, mf_exec)
     self.w_editor = MFTextEdit(self, self.w_history, self.w_todo)
     # set main window layout as grid
     self.grid = QGridLayout()
     self.grid.setSpacing(0)
     self.grid.setContentsMargins(0, 0, 0, 0)
     self.grid.addWidget(self.w_todo, 0, 0)
     self.grid.addWidget(self.w_editor, 1, 0)
     self.grid.setSizeConstraint(QLayout.SetFixedSize)
     self.setLayout(self.grid)
     self.resize(self.sizeHint())
     # register global shortcuts
     self.keysFn = KeysReactor(self, 'MFGui')
     self.registerGlobalKeys()
     # move window to desktop center
     qr = self.frameGeometry()
     cp = QDesktopWidget().availableGeometry().center()
     qr.moveCenter(cp)
     self.move(qr.topLeft())
     # set window style
     self.setWindowTitle(MF_NAME)
     self.setWindowIcon(QIcon('./res/icons/pulse_heart.png'))
     self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
     self.setAttribute(Qt.WA_InputMethodEnabled)
     self.setAttribute(Qt.WA_TranslucentBackground, True)
     self.setContentsMargins(5, 5, 5, 5)
     self.setGraphicsEffect(
         QGraphicsDropShadowEffect(blurRadius=5, xOffset=3, yOffset=3))
     self.setFocus()
     self.show()
     # check update
     self.worker = MFWorker(self.checkUpdate)
     self.worker.start()
     pass
示例#6
0
class MFImagePreviewer(QWidget):
    def __init__(self, parent=None, pixmap=None):
        super().__init__(parent, Qt.Dialog)
        self.parent = parent
        self.min_width = 100  #px
        self.max_width = pixmap.width() * 3
        _width = min(pixmap.width(),
                     QDesktopWidget().availableGeometry().width())
        pixmap = pixmap.scaledToWidth(_width, Qt.SmoothTransformation)
        self.pixmap = pixmap
        self.now_width = pixmap.width()
        #
        self.grid = QGridLayout()
        self.grid.setSpacing(0)
        self.grid.setContentsMargins(0, 0, 0, 0)
        self.label = QLabel('ImagePreviewer', self)
        self.label.setPixmap(pixmap)
        self.grid.addWidget(self.label, 0, 0)
        self.grid.setSizeConstraint(QLayout.SetFixedSize)
        self.setLayout(self.grid)
        self.resize(self.sizeHint())
        #
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())
        #
        self.keysFn = KeysReactor(self)
        self.keysFn.register(CFG.KEYS_CLOSE(), lambda: self.close())
        self.keysFn.register(CFG.KEYS_CLOSE1(self), lambda: self.close())
        self.keysFn.register(CFG.KEYS_CLOSE2(self), lambda: self.close())
        #
        self.styleHelper()
        self.setFocus()
        self.show()
        pass

    def styleHelper(self):
        self.setWindowTitle('Image Previewer')
        self.setWindowFlags(Qt.Dialog | Qt.FramelessWindowHint)
        self.setStyleSheet(CFG.STYLESHEET(self))
        pass

    def mousePressEvent(self, e):
        if e.buttons() & Qt.LeftButton:
            self.press_pos = e.pos()
        elif e.buttons() & Qt.RightButton:
            self.close()
        pass

    def mouseMoveEvent(self, e):
        if e.buttons() & Qt.LeftButton:
            self.move(self.mapToParent(e.pos() - self.press_pos))
            pass
        elif e.buttons() & Qt.RightButton:
            pass
        pass

    def wheelEvent(self, e):
        num_scroll = int(e.angleDelta().y() / 8 / 15)
        self.now_width += 50 * num_scroll
        self.now_width = max(min(self.now_width, self.max_width),
                             self.min_width)
        _pixmap = self.pixmap.scaledToWidth(self.now_width,
                                            Qt.SmoothTransformation)
        self.label.setPixmap(_pixmap)
        pass

    def focusOutEvent(self, e):
        self.close()
        pass

    pass
示例#7
0
class MFTextEdit(QPlainTextEdit):
    def __init__(self, parent, w_history, w_todo):
        super().__init__(parent)
        self.parent = parent
        self.w_history = w_history
        self.w_todo = w_todo
        self.clipboard = QApplication.clipboard()
        #
        self.pressed = False
        self.press_pos = QPoint(0, 0)
        self.init_pos = self.parent.pos()
        self.font_style = QFont(CFG.FONT_DEFAULT(self))
        self.font_metric = QFontMetrics(self.font_style)
        self.styleHelper()
        #
        self.setAcceptDrops(True)
        self.textChanged.connect(self.textChangedEvent)
        self.keysFn = KeysReactor(self, 'MFTextEdit')
        self.keysFn.setKeyPressHook(self.showCaret)
        self.registerKeys()
        pass

    def styleHelper(self):
        # Basic Style
        self.setStyleSheet(CFG.STYLESHEET(self))
        self.setFixedSize(*CFG.SIZE_EDIT())
        self.setTabChangesFocus(True)
        self.setWordWrapMode(QTextOption.WrapAtWordBoundaryOrAnywhere)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        # Font Style
        self.setFont(self.font_style)
        # Cursor Style
        QApplication.setOverrideCursor(Qt.ArrowCursor)
        self.ensureCursorVisible()
        self.lastKeyStroke = time.time() - 1.0
        self.hideCaret()
        # Placeholder Text
        self.showHelpText()
        pass

    def registerKeys(self):
        #NOTE: Ctrl+Return; insert newline
        def mf_edit_binding():
            self.showCaret()
            self.insertPlainText('\n')
            pass

        self.keysFn.register(CFG.KEYS_EDIT(self), mf_edit_binding)

        #NOTE: Return; flash recording
        def mf_flush_binding():
            mf_text = self.toPlainText().encode('utf-8').decode('utf-8')
            if mf_text:
                self.saveFileCache()
                mf_exec.mf_record(repr(mf_text.strip()))
            #
            if mf_text and self.w_history.isVisible():
                self.clear()
                self.w_history.updateHistory(None, None)
            else:
                self.parent.close()
            pass

        self.keysFn.register(CFG.KEYS_FLUSH(self), mf_flush_binding)

        #NOTE: Ctrl+V; paste actions
        def mf_paste_binding():
            if self.canPaste():
                self.dropEvent(self.clipboard)
            else:
                pixmap = self.clipboard.mimeData().imageData()
                if pixmap:
                    fake_path = mdm.savePixmap(pixmap)
                    _text = "![img]({})".format(fake_path)
                    self.insertPlainText(_text)
                pass
            pass

        self.keysFn.register(CFG.KEYS_PASTE(self), mf_paste_binding)

        #NOTE: Alt+Q; add to todo list
        def mf_add_todo():
            todo_text = self.toPlainText().encode('utf-8').decode('utf-8')
            if todo_text:
                self.clear()
                self.w_todo.todos.append(['+', todo_text])
                self.w_todo.saveTodoList()
                self.w_todo.renderTodos()
                pass
            pass

        self.keysFn.register(CFG.KEYS_ADD_TODO(self), mf_add_todo)

        ### Alt+V ###
        self.keysFn.register(
            CFG.KEYS_RANGE_SWITCH(),
            lambda: self.w_history.updateHistory(+1, None, True))
        ### Alt+J ###
        self.keysFn.register(CFG.KEYS_JUMP_FORWARD(),
                             lambda: self.w_history.updateHistory(0, +1))
        ### Alt+K ###
        self.keysFn.register(CFG.KEYS_JUMP_BACKWARD(),
                             lambda: self.w_history.updateHistory(0, -1))
        ### Alt+H ###
        self.keysFn.register(CFG.KEYS_TOGGLE(),
                             lambda: self.toggleHistoryWidget())
        ### Escape ###
        self.keysFn.register(CFG.KEYS_CLOSE(), lambda: self.parent.close())
        pass

    def showHelpText(self):
        if mf_exec.first_run:
            self.setPlaceholderText('Try Double Click on Me!')
        elif mf_exec.no_record:
            self.setPlaceholderText('Press ENTER to Flush It!')
        else:
            pass
        pass

    def toggleHistoryWidget(self):
        size_half = int(self.w_history.height() / 2)
        if self.w_history.isVisible():  #hide history widget
            mf_exec.first_run = False
            self.showHelpText()
            self.parent.grid.replaceWidget(self.w_history, self.w_todo)
            self.w_history.setVisible(False)
            self.w_todo.setVisible(True)
            self.parent.adjustSize()
            self.parent.resize(self.size())
            self.parent.move(self.parent.pos() + QPoint(0, size_half))
            pass
        else:  #show history widget
            self.parent.grid.replaceWidget(self.w_todo, self.w_history)
            self.w_todo.setVisible(False)
            self.w_history.setVisible(True)
            self.parent.adjustSize()
            self.parent.move(self.parent.pos() - QPoint(0, size_half))
            self.w_history.updateHistory(
                0, 0)  #refresh, default history for today
            pass
        self.setFocus()  # for convenience
        pass

    def saveFileCache(self):
        link_iter = link_filter.finditer(self.toPlainText())
        for _link in link_iter:
            (_tag, _alt, _path) = _link.groups()
            if _tag == "!" or _alt == "img" or _alt == "file":  #only save image or file
                mdm.save(_path)
            pass
        pass

    def hideCaret(self):
        if time.time() - self.lastKeyStroke > 1.0:
            # QApplication.setCursorFlashTime(0)
            self.setCursorWidth(0)
        QTimer.singleShot(250, self.hideCaret)
        pass

    def showCaret(self, e=None, force=False):
        # QApplication.setCursorFlashTime(1000)
        self.setCursorWidth(1)
        if force or not self.keysFn.hasSpecsKeys():
            self.lastKeyStroke = time.time()
        pass

    def getLineCount(self):
        _count = 0
        _doc = self.document()
        _it = _doc.begin()
        while _it != _doc.end():
            _count += _it.layout().lineCount()
            _it = _it.next()
        return _count

    def mousePressEvent(self, e):
        self.pressed = True
        self.press_pos = e.pos()
        pass

    def mouseMoveEvent(self, e):
        if (e.buttons() & Qt.LeftButton) and self.pressed:
            self.parent.move(self.parent.mapToParent(e.pos() - self.press_pos))
            # print(self.parent.pos() - self.init_pos)
            pass
        elif e.buttons() & Qt.RightButton:
            pass
        pass

    def mouseReleaseEvent(self, e):
        self.pressed = False
        return super().mouseReleaseEvent(e)

    def mouseDoubleClickEvent(self, e):
        self.toggleHistoryWidget()
        pass

    def textChangedEvent(self):
        _lines = min(self.getLineCount(), len(INPUTBOX_RESIZE) - 1)
        _width, _height = CFG.SIZE_EDIT()
        _size = QSize(_width, int(_height / 2) * (2 + INPUTBOX_RESIZE[_lines]))
        if _size != self.size():
            self.setFixedSize(_size)
            self.parent.adjustSize()
            self.parent.resize(self.size())
        pass

    def focusInEvent(self, e):
        self.keysFn.clear()
        return super().focusInEvent(e)

    def focusOutEvent(self, e):
        self.keysFn.clear()
        return super().focusOutEvent(e)

    #Reference: https://www.qtcentre.org/threads/33513-QTextEdit-Drag-and-Drop
    def dragEnterEvent(self, e):
        e.accept()
        pass

    def dragMoveEvent(self, e):
        e.accept()
        pass

    def dropEvent(self, e):
        _mime = e.mimeData()
        if _mime.hasUrls():
            url_list = _mime.urls()
            #
            local_urls = list(filter(lambda x: x.isLocalFile(), url_list))
            if len(local_urls) > 0:
                ret = mdm.saveUrls(local_urls)
                ret = ["[file]({})".format(_path) for _path in ret]
                _text = '\n'.join(ret)
                self.insertPlainText(_text)
                pass
            #
            web_urls = list(filter(lambda x: not x.isLocalFile(), url_list))
            if len(web_urls) > 0:
                for _url in url_list:
                    _text = '[url]({url})\n'.format(url=_url.toString())
                    self.insertPlainText(_text)
                pass
            pass
        elif _mime.hasHtml():
            _doc = QTextDocument()
            _doc.setHtml(_mime.html())
            _text = _doc.toPlainText()
            self.insertPlainText(_text)
            pass
        elif _mime.hasText():
            _text = _mime.text().strip()
            self.insertPlainText(_text)
            pass
        self.textChangedEvent()
        self.showCaret(force=True)
        self.setFocus()
        pass

    pass
示例#8
0
class MFGui(QWidget):
    _signal1 = pyqtSignal(str)
    _signal2 = pyqtSignal(object, str)

    def __init__(self):
        super().__init__()
        self.mf_exec = mf_exec
        self.w_todo = MFTodoWidget(self, MF_DIR, sync=False)
        self.w_history = MFHistory(self, MF_DIR, mf_exec)
        self.w_editor = MFTextEdit(self, self.w_history, self.w_todo)
        # set main window layout as grid
        self.grid = QGridLayout()
        self.grid.setSpacing(0)
        self.grid.setContentsMargins(0, 0, 0, 0)
        self.grid.addWidget(self.w_todo, 0, 0)
        self.grid.addWidget(self.w_editor, 1, 0)
        self.grid.setSizeConstraint(QLayout.SetFixedSize)
        self.setLayout(self.grid)
        self.resize(self.sizeHint())
        # register global shortcuts
        self.keysFn = KeysReactor(self, 'MFGui')
        self.registerGlobalKeys()
        # move window to desktop center
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())
        # set window style
        self.setWindowTitle(MF_NAME)
        self.setWindowIcon(QIcon('./res/icons/pulse_heart.png'))
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
        self.setAttribute(Qt.WA_InputMethodEnabled)
        self.setAttribute(Qt.WA_TranslucentBackground, True)
        self.setContentsMargins(5, 5, 5, 5)
        self.setGraphicsEffect(
            QGraphicsDropShadowEffect(blurRadius=5, xOffset=3, yOffset=3))
        self.setFocus()
        self.show()
        # check update
        self.worker = MFWorker(self.checkUpdate)
        self.worker.start()
        pass

    def registerGlobalKeys(self):
        ### Escape / Ctrl+W ###
        self.keysFn.register(CFG.KEYS_CLOSE(), lambda: self.close())
        self.keysFn.register(CFG.KEYS_CLOSE(self), lambda: self.close())
        ### Ctrl+L ###
        self.keysFn.register(CFG.KEYS_TO_EDIT(self), lambda: self.setFocus())

        ### Ctrl+F ###
        def mf_search_binding():
            if self.w_history.isVisible():
                _topbar = self.w_history.w_topbar
                _topbar.switch(_topbar.input_box)
                _topbar.input_box.setFocus()
            pass

        self.keysFn.register(CFG.KEYS_SEARCH(self), mf_search_binding)
        ### Alt+V ###
        self.keysFn.register(
            CFG.KEYS_RANGE_SWITCH(),
            lambda: self.w_history.updateHistory(+1, None, True))
        ### Alt+J ###
        self.keysFn.register(CFG.KEYS_JUMP_FORWARD(),
                             lambda: self.w_history.updateHistory(0, +1))
        ### Alt+K ###
        self.keysFn.register(CFG.KEYS_JUMP_BACKWARD(),
                             lambda: self.w_history.updateHistory(0, -1))
        ### Alt+H ###
        self.keysFn.register(CFG.KEYS_TOGGLE(),
                             lambda: self.w_history.toggleHistoryWidget())
        pass

    def checkUpdate(self):
        QThread.sleep(5)
        try:
            res = url_request.urlopen(MF_STATUS).read().decode('utf-8')
            res = json.loads(res)
            _latest = res[0]['name'][1:]
            if _latest != MF_VERSION and self.w_history.isVisible():
                _hint = '<a href="{url}/releases/tag/v{ver}">(v{ver} Available)</a>'.format(
                    url=MF_WEBSITE, ver=_latest)
                signal_emit(self._signal2,
                            self.w_history.w_topbar.hint_label.setDateHint,
                            (None, _hint))
                signal_emit(
                    self._signal1,
                    self.w_history.w_topbar.tool_bar.items['_'].setText,
                    (_hint, ))
        except Exception as e:
            print('Check Update Failed: ', e)
        pass

    def setFocus(self):
        self.w_editor.showCaret(force=True)
        self.w_editor.setFocus()
        pass

    pass