Пример #1
0
    def __init__(self, appPath):
        QWidget.__init__(self)
        global rc
        rc = ResourceCache(normpath(appPath + "/resources"))

        self.__config = Config(appPath)
        self.__noteProvider = SqliteNoteProvider(
            normpath(appPath + "/resources/notes/notes.db"))
        self.__remoteNoteProvider = None
        self.__notes = []
        self.__tags = []

        self.setWindowTitle("Scroll, Quill & INK   " + version)
        self.setMinimumSize(400, 240)
        self.resize(800, 600)

        icon = QIcon()
        icon.addPixmap(rc.pixmap("sqink-16x16.png"))
        icon.addPixmap(rc.pixmap("sqink-32x32.png"))
        self.setWindowIcon(icon)

        layout = QVBoxLayout()
        layout.setContentsMargins(5, 5, 5, 2)
        self.setLayout(layout)

        splitter = QSplitter()
        splitter.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        # noinspection PyCallByClass,PyTypeChecker
        splitter.setStyle(QStyleFactory.create("Cleanlooks"))
        layout.addWidget(splitter)

        self.__statusBar = QStatusBar()
        self.__statusBar.setSizeGripEnabled(False)
        layout.addWidget(self.__statusBar)

        self.__lblNotesCount = QLabel()
        self.__lblNotesCount.setStyleSheet("border:1px solid #b2dfdb; border-radius:0.5em; background-color:#b2dfdb;" +\
                                           " padding:0 0.5em;")
        self.__statusBar.addPermanentWidget(self.__lblNotesCount)

        self.__lblError = QLabel()
        self.__lblError.setStyleSheet(
            "border-radius:0.5em; background-color:#f36c60; padding:0 0.5em;")
        self.__lblError.setVisible(False)
        self.__statusBar.addWidget(self.__lblError)

        panelA = QWidget()
        splitter.addWidget(panelA)
        layoutA = QGridLayout()
        layoutA.setContentsMargins(0, 0, 0, 0)
        panelA.setLayout(layoutA)

        barButtons = QWidget()
        layoutButtons = QHBoxLayout()
        layoutButtons.setContentsMargins(0, 0, 0, 0)
        barButtons.setLayout(layoutButtons)
        layoutA.addWidget(barButtons, 0, 0, 1, 2)

        btnNew = QPushButton()
        btnNew.setIcon(rc.icon("note-new-16x16.png"))
        btnNew.setToolTip("New note (CTRL + N)")
        # noinspection PyUnresolvedReferences
        btnNew.clicked.connect(self.__onNewNoteClicked)
        btnNew.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_N))
        layoutButtons.addWidget(btnNew)

        self.__btnEdit = QPushButton()
        self.__btnEdit.setIcon(rc.icon("note-edit-16x16.png"))
        self.__btnEdit.setToolTip("Edit note (CTRL + E)")
        # noinspection PyUnresolvedReferences
        self.__btnEdit.clicked.connect(self.__onEditNoteClicked)
        self.__btnEdit.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_E))
        layoutButtons.addWidget(self.__btnEdit)

        self.__btnDelete = QPushButton()
        self.__btnDelete.setIcon(rc.icon("note-delete-16x16.png"))
        self.__btnDelete.setToolTip("Delete note (CTRL + L)")
        # noinspection PyUnresolvedReferences
        self.__btnDelete.clicked.connect(self.__onDeleteNoteClicked)
        self.__btnDelete.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_L))
        layoutButtons.addWidget(self.__btnDelete)

        layoutButtons.addStretch(1)

        self.__btnSync = QPushButton()
        self.__btnSync.setIcon(rc.icon("sync-16x16.png"))
        self.__btnSync.setToolTip("Sync (CTRL + I)")
        # noinspection PyUnresolvedReferences
        self.__btnSync.clicked.connect(self.__onSyncClicked)
        self.__btnSync.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_I))
        layoutButtons.addWidget(self.__btnSync)

        btnConfig = QPushButton()
        btnConfig.setIcon(rc.icon("preferences-16x16.png"))
        btnConfig.setToolTip("Preferences")
        # noinspection PyUnresolvedReferences
        btnConfig.clicked.connect(self.__onPreferencesClicked)
        layoutButtons.addWidget(btnConfig)

        lblSearch = QLabel()
        lblSearch.setPixmap(rc.pixmap("search-16x16.png"))
        lblSearch.setToolTip("Find (CTRL + F)")
        layoutA.addWidget(lblSearch, 1, 0)

        self.__txtSearch = QLineEdit()
        self.__txtSearch.setValidator(
            QRegExpValidator(
                QRegExp("[A-ZÁÉÍÓÚÜÑa-záéíóúüñ0-9 @:/#&=\.\-\?\\\\]+")))
        # noinspection PyUnresolvedReferences
        self.__txtSearch.textEdited.connect(self.__onSearchEdited)
        QShortcut(QKeySequence(Qt.CTRL + Qt.Key_F), self.__txtSearch,
                  self.__txtSearch.setFocus)
        layoutA.addWidget(self.__txtSearch, 1, 1)

        lblTag = QLabel()
        lblTag.setPixmap(rc.pixmap("tag-16x16.png"))
        lblTag.setToolTip("Filter by tag (CTRL + T)")
        layoutA.addWidget(lblTag, 2, 0)

        self.__cmbTag = QComboBox()
        # noinspection PyUnresolvedReferences
        self.__cmbTag.activated.connect(self.__onTagFilterSelectionChanged)
        QShortcut(QKeySequence(Qt.CTRL + Qt.Key_T), self.__cmbTag,
                  self.__onTagFilterShortcutPressed)
        layoutA.addWidget(self.__cmbTag, 2, 1)

        self.__lstNotes = ListWidget(self.__onDeleteNoteClicked)
        self.__lstNotes.setSizePolicy(QSizePolicy.Expanding,
                                      QSizePolicy.Expanding)
        self.__lstNotes.setItemDelegate(ListItemDelegate())
        # noinspection PyUnresolvedReferences
        self.__lstNotes.itemSelectionChanged.connect(
            self.__onNoteSelectionChanged)
        layoutA.addWidget(self.__lstNotes, 3, 0, 1, 2)

        self.__viewerEditor = ViewerEditor(self)
        splitter.addWidget(self.__viewerEditor)

        self.configureSync()
        self.reload()
        self.__txtSearch.setFocus()
Пример #2
0
Файл: ui.py Проект: vijo/sqink
    def __init__(self, appPath):
        QWidget.__init__(self)
        rc.init(normpath(appPath + "/resources"))
        self.__config= Config(appPath)
        self.__noteProvider= SqliteNoteProvider(normpath(appPath + "/resources/notes/notes.db"))

        self.setWindowTitle("Scroll, Quill & INK")
        self.setMinimumSize(400, 240)
        self.resize(800, 600)

        icon= QIcon()
        icon.addPixmap(rc.pixmap("sqink-16x16.png"))
        icon.addPixmap(rc.pixmap("sqink-32x32.png"))
        self.setWindowIcon(icon)

        layout= QVBoxLayout()
        layout.setContentsMargins(5, 5, 5, 2)
        self.setLayout(layout)

        splitter= QSplitter()
        splitter.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        splitter.setStyle(QStyleFactory.create("Cleanlooks"))
        layout.addWidget(splitter)

        self.__statusBar= QStatusBar()
        self.__statusBar.setSizeGripEnabled(False)
        layout.addWidget(self.__statusBar)

        self.__lblNotesCount= QLabel()
        self.__lblNotesCount.setStyleSheet("border-radius:0.5em; background-color:#b2dfdb; padding:0 0.5em;")
        self.__statusBar.addPermanentWidget(self.__lblNotesCount)

        self.__lblError= QLabel()
        self.__lblError.setStyleSheet("border-radius:0.5em; background-color:#f36c60; padding:0 0.5em;")
        self.__lblError.setVisible(False)
        self.__statusBar.addWidget(self.__lblError)

        panelA= QWidget()
        splitter.addWidget(panelA)
        layoutA= QGridLayout()
        layoutA.setContentsMargins(0, 0, 0, 0)
        panelA.setLayout(layoutA)

        barButtons= QWidget()
        layoutButtons= QHBoxLayout()
        layoutButtons.setContentsMargins(0, 0, 0, 0)
        barButtons.setLayout(layoutButtons)
        layoutA.addWidget(barButtons, 0, 0, 1, 2)

        btnNew= QPushButton()
        btnNew.setIcon(rc.icon("note-new-16x16.png"))
        btnNew.setToolTip("New note (CTRL + N)")
        btnNew.clicked.connect(self.__onNewNoteClicked)
        btnNew.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_N))
        layoutButtons.addWidget(btnNew)

        self.__btnEdit= QPushButton()
        self.__btnEdit.setIcon(rc.icon("note-edit-16x16.png"))
        self.__btnEdit.setToolTip("Edit note (CTRL + E)")
        self.__btnEdit.clicked.connect(self.__onEditNoteClicked)
        self.__btnEdit.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_E))
        layoutButtons.addWidget(self.__btnEdit)

        self.__btnDelete= QPushButton()
        self.__btnDelete.setIcon(rc.icon("note-delete-16x16.png"))
        self.__btnDelete.setToolTip("Delete note (CTRL + L)")
        self.__btnDelete.clicked.connect(self.__onDeleteNoteClicked)
        self.__btnDelete.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_L))
        layoutButtons.addWidget(self.__btnDelete)

        layoutButtons.addStretch(1)

        self.__btnSync= QPushButton()
        self.__btnSync.setIcon(rc.icon("sync-16x16.png"))
        self.__btnSync.setToolTip("Sync (CTRL + I)")
        self.__btnSync.clicked.connect(self.__onSyncClicked)
        self.__btnSync.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_I))
        layoutButtons.addWidget(self.__btnSync)

        btnConfig= QPushButton()
        btnConfig.setIcon(rc.icon("preferences-16x16.png"))
        btnConfig.setToolTip("Preferences")
        btnConfig.clicked.connect(self.__onPreferencesClicked)
        layoutButtons.addWidget(btnConfig)

        lblSearch= QLabel()
        lblSearch.setPixmap(rc.pixmap("search-16x16.png"))
        lblSearch.setToolTip("Find (CTRL + F)")
        layoutA.addWidget(lblSearch, 1, 0)

        self.__txtSearch= QLineEdit()
        self.__txtSearch.setValidator(QRegExpValidator(QRegExp("[A-ZÁÉÍÓÚÜÑa-záéíóúüñ0-9 @:/#&=\.\-\?\\\\]+")))
        self.__txtSearch.textEdited.connect(self.__onSearchEdited)
        QShortcut(QKeySequence(Qt.CTRL + Qt.Key_F), self.__txtSearch, self.__txtSearch.setFocus)
        layoutA.addWidget(self.__txtSearch, 1, 1)

        lblTag= QLabel()
        lblTag.setPixmap(rc.pixmap("tag-16x16.png"))
        lblTag.setToolTip("Filter by tag (CTRL + T)")
        layoutA.addWidget(lblTag, 2, 0)

        self.__cmbTag= QComboBox()
        self.__cmbTag.activated.connect(self.__onTagFilterSelectionChanged)
        QShortcut(QKeySequence(Qt.CTRL + Qt.Key_T), self.__cmbTag, self.__onTagFilterShortcutPressed)
        layoutA.addWidget(self.__cmbTag, 2, 1)

        self.__lstNotes= ListWidget(self.__onDeleteNoteClicked)
        self.__lstNotes.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.__lstNotes.setItemDelegate(ListItemDelegate())
        self.__lstNotes.itemSelectionChanged.connect(self.__onNoteSelectionChanged)
        layoutA.addWidget(self.__lstNotes, 3, 0, 1, 2)

        self.__viewerEditor= ViewerEditor(self)
        splitter.addWidget(self.__viewerEditor)

        self.configureSync()
        self.reload()
        self.__txtSearch.setFocus()
Пример #3
0
class Window(QWidget):

    tagsChanged = Signal(list)

    def __init__(self, appPath):
        QWidget.__init__(self)
        global rc
        rc = ResourceCache(normpath(appPath + "/resources"))

        self.__config = Config(appPath)
        self.__noteProvider = SqliteNoteProvider(
            normpath(appPath + "/resources/notes/notes.db"))
        self.__remoteNoteProvider = None
        self.__notes = []
        self.__tags = []

        self.setWindowTitle("Scroll, Quill & INK   " + version)
        self.setMinimumSize(400, 240)
        self.resize(800, 600)

        icon = QIcon()
        icon.addPixmap(rc.pixmap("sqink-16x16.png"))
        icon.addPixmap(rc.pixmap("sqink-32x32.png"))
        self.setWindowIcon(icon)

        layout = QVBoxLayout()
        layout.setContentsMargins(5, 5, 5, 2)
        self.setLayout(layout)

        splitter = QSplitter()
        splitter.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        # noinspection PyCallByClass,PyTypeChecker
        splitter.setStyle(QStyleFactory.create("Cleanlooks"))
        layout.addWidget(splitter)

        self.__statusBar = QStatusBar()
        self.__statusBar.setSizeGripEnabled(False)
        layout.addWidget(self.__statusBar)

        self.__lblNotesCount = QLabel()
        self.__lblNotesCount.setStyleSheet("border:1px solid #b2dfdb; border-radius:0.5em; background-color:#b2dfdb;" +\
                                           " padding:0 0.5em;")
        self.__statusBar.addPermanentWidget(self.__lblNotesCount)

        self.__lblError = QLabel()
        self.__lblError.setStyleSheet(
            "border-radius:0.5em; background-color:#f36c60; padding:0 0.5em;")
        self.__lblError.setVisible(False)
        self.__statusBar.addWidget(self.__lblError)

        panelA = QWidget()
        splitter.addWidget(panelA)
        layoutA = QGridLayout()
        layoutA.setContentsMargins(0, 0, 0, 0)
        panelA.setLayout(layoutA)

        barButtons = QWidget()
        layoutButtons = QHBoxLayout()
        layoutButtons.setContentsMargins(0, 0, 0, 0)
        barButtons.setLayout(layoutButtons)
        layoutA.addWidget(barButtons, 0, 0, 1, 2)

        btnNew = QPushButton()
        btnNew.setIcon(rc.icon("note-new-16x16.png"))
        btnNew.setToolTip("New note (CTRL + N)")
        # noinspection PyUnresolvedReferences
        btnNew.clicked.connect(self.__onNewNoteClicked)
        btnNew.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_N))
        layoutButtons.addWidget(btnNew)

        self.__btnEdit = QPushButton()
        self.__btnEdit.setIcon(rc.icon("note-edit-16x16.png"))
        self.__btnEdit.setToolTip("Edit note (CTRL + E)")
        # noinspection PyUnresolvedReferences
        self.__btnEdit.clicked.connect(self.__onEditNoteClicked)
        self.__btnEdit.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_E))
        layoutButtons.addWidget(self.__btnEdit)

        self.__btnDelete = QPushButton()
        self.__btnDelete.setIcon(rc.icon("note-delete-16x16.png"))
        self.__btnDelete.setToolTip("Delete note (CTRL + L)")
        # noinspection PyUnresolvedReferences
        self.__btnDelete.clicked.connect(self.__onDeleteNoteClicked)
        self.__btnDelete.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_L))
        layoutButtons.addWidget(self.__btnDelete)

        layoutButtons.addStretch(1)

        self.__btnSync = QPushButton()
        self.__btnSync.setIcon(rc.icon("sync-16x16.png"))
        self.__btnSync.setToolTip("Sync (CTRL + I)")
        # noinspection PyUnresolvedReferences
        self.__btnSync.clicked.connect(self.__onSyncClicked)
        self.__btnSync.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_I))
        layoutButtons.addWidget(self.__btnSync)

        btnConfig = QPushButton()
        btnConfig.setIcon(rc.icon("preferences-16x16.png"))
        btnConfig.setToolTip("Preferences")
        # noinspection PyUnresolvedReferences
        btnConfig.clicked.connect(self.__onPreferencesClicked)
        layoutButtons.addWidget(btnConfig)

        lblSearch = QLabel()
        lblSearch.setPixmap(rc.pixmap("search-16x16.png"))
        lblSearch.setToolTip("Find (CTRL + F)")
        layoutA.addWidget(lblSearch, 1, 0)

        self.__txtSearch = QLineEdit()
        self.__txtSearch.setValidator(
            QRegExpValidator(
                QRegExp("[A-ZÁÉÍÓÚÜÑa-záéíóúüñ0-9 @:/#&=\.\-\?\\\\]+")))
        # noinspection PyUnresolvedReferences
        self.__txtSearch.textEdited.connect(self.__onSearchEdited)
        QShortcut(QKeySequence(Qt.CTRL + Qt.Key_F), self.__txtSearch,
                  self.__txtSearch.setFocus)
        layoutA.addWidget(self.__txtSearch, 1, 1)

        lblTag = QLabel()
        lblTag.setPixmap(rc.pixmap("tag-16x16.png"))
        lblTag.setToolTip("Filter by tag (CTRL + T)")
        layoutA.addWidget(lblTag, 2, 0)

        self.__cmbTag = QComboBox()
        # noinspection PyUnresolvedReferences
        self.__cmbTag.activated.connect(self.__onTagFilterSelectionChanged)
        QShortcut(QKeySequence(Qt.CTRL + Qt.Key_T), self.__cmbTag,
                  self.__onTagFilterShortcutPressed)
        layoutA.addWidget(self.__cmbTag, 2, 1)

        self.__lstNotes = ListWidget(self.__onDeleteNoteClicked)
        self.__lstNotes.setSizePolicy(QSizePolicy.Expanding,
                                      QSizePolicy.Expanding)
        self.__lstNotes.setItemDelegate(ListItemDelegate())
        # noinspection PyUnresolvedReferences
        self.__lstNotes.itemSelectionChanged.connect(
            self.__onNoteSelectionChanged)
        layoutA.addWidget(self.__lstNotes, 3, 0, 1, 2)

        self.__viewerEditor = ViewerEditor(self)
        splitter.addWidget(self.__viewerEditor)

        self.configureSync()
        self.reload()
        self.__txtSearch.setFocus()

    def closeEvent(self, event):
        self.__noteProvider.close()
        QWidget.closeEvent(self, event)

    def config(self):
        return self.__config

    def noteProvider(self):
        return self.__noteProvider

    def remoteNoteProvider(self):
        return self.__remoteNoteProvider

    def textFilter(self):
        return self.__txtSearch.text().strip()

    def configureSync(self):
        config = self.config()
        if config.isDropboxEnabled():
            self.__remoteNoteProvider = DropboxNoteProvider(
                config.getDropboxToken(), config.getDropboxFolder(),
                config.getProxyHost(), config.getProxyPort(),
                config.getProxyUser(), config.getProxyPassword())
            self.__btnSync.setDisabled(False)
        elif config.isGoogleDriveEnabled():
            self.__remoteNoteProvider = GoogleDriveNoteProvider(
                config.getGoogleDriveToken(), config.getProxyHost(),
                config.getProxyPort(), config.getProxyUser(),
                config.getProxyPassword())
            self.__btnSync.setDisabled(False)
        else:
            self.__remoteNoteProvider = None
            self.__btnSync.setDisabled(True)

    def disableSync(self):
        config = self.config()
        if config.isDropboxEnabled():
            config.setDropboxEnabled(False)
            config.setDropboxToken(None)
        else:
            config.setGoogleDriveEnabled(False)
            config.setGoogleDriveToken(None)
        config.save()
        self.configureSync()

    def updateProxy(self):
        self.__viewerEditor.updateProxy()

    def showStatus(self, message, seconds=5, immediate=False):
        self.clearError()
        self.__statusBar.showMessage(message, timeout=seconds * 1000)
        if immediate:
            self.__statusBar.repaint()

    def showError(self, message):
        self.__statusBar.clearMessage()
        self.__lblError.setText(message)
        self.__lblError.setVisible(True)

    def clearError(self):
        self.__lblError.setVisible(False)

    def reload(self, selectNoteOnViewerEditor=False, skipViewerEditor=False):
        self.__notes = sorted(self.noteProvider().list(),
                              key=lambda n: n.title.lower())
        self.__tags = listTags(self.__notes)
        self.__refreshTagCombo()
        self.__refreshNoteList(selectNoteOnViewerEditor)
        self.__lblNotesCount.setText("%d notes" % len(self.__notes))

        if not skipViewerEditor:
            self.__refreshNoteViewerEditor()

        self.__refreshNoteButtons()
        # noinspection PyUnresolvedReferences
        self.tagsChanged.emit(self.__tags)

    def __setSelectedItem(self, uuid=None):
        self.__lstNotes.setDisabled(True)

        if self.__selectedItem():
            self.__selectedItem().setSelected(False)

        if uuid:
            for i in range(self.__lstNotes.count()):
                item = self.__lstNotes.item(i)
                if item.note().uuid == uuid:
                    item.setSelected(True)
                    break

        self.__lstNotes.setDisabled(False)

    def __selectedItem(self):
        selectedItems = self.__lstNotes.selectedItems()
        return selectedItems[0] if selectedItems else None

    def __refreshNoteButtons(self):
        disableButtons = not self.__viewerEditor.noteUuid()
        self.__btnEdit.setDisabled(disableButtons)
        self.__btnDelete.setDisabled(disableButtons)

    def __refreshTagCombo(self):
        tags = self.__tags[:]
        tags.insert(0, "")

        currentTag = self.__cmbTag.currentText()
        self.__cmbTag.clear()
        self.__cmbTag.addItems(tags)

        if currentTag and currentTag in tags:
            self.__cmbTag.setCurrentIndex(tags.index(currentTag))

    def __refreshNoteList(self, selectNoteOnViewerEditor=False):
        notes = self.__notes

        searchText = self.textFilter()
        if searchText:
            uuids = self.noteProvider().search(searchText)
            notes = list(filter(lambda n: n.uuid in uuids, notes))

        currentTag = self.__cmbTag.currentText()
        if currentTag:
            notes = list(filter(lambda n: n.hasTag(currentTag), notes))

        selectUuid = None
        if selectNoteOnViewerEditor:
            selectUuid = self.__viewerEditor.noteUuid()
        elif self.__selectedItem():
            selectUuid = self.__selectedItem().note().uuid
        elif len(notes) > 0:
            selectUuid = notes[0].uuid

        self.__lstNotes.setDisabled(True)
        self.__lstNotes.clear()
        selectedNoteItem = None
        for note in notes:
            item = ListItem(note, self.__lstNotes)
            if selectUuid == note.uuid:
                item.setSelected(True)
                selectedNoteItem = item
        if selectedNoteItem:
            self.__lstNotes.setCurrentItem(selectedNoteItem)
        self.__lstNotes.setDisabled(False)

    def __refreshNoteViewerEditor(self):
        if self.__selectedItem():
            note = self.noteProvider().get(self.__selectedItem().note().uuid)
        else:
            note = renderHtml(Note())
        self.__viewerEditor.view(note)

    def __onNewNoteClicked(self):
        if self.__viewerEditor.isAllowedToChange():
            self.__lstNotes.setCurrentItem(None)
            self.__viewerEditor.edit(renderHtml(Note()))
            self.__refreshNoteButtons()

    def __onEditNoteClicked(self):
        if self.__viewerEditor.isAllowedToChange():
            self.__viewerEditor.edit()

    def __onDeleteNoteClicked(self):
        # noinspection PyCallByClass
        choice = QMessageBox.question(self,
                                      "Delete note",
                                      "Are you ABSOLUTELY sure?",
                                      buttons=QMessageBox.Yes | QMessageBox.No,
                                      defaultButton=QMessageBox.No)
        if choice != QMessageBox.Yes:
            return

        note = Note(self.__viewerEditor.noteUuid(),
                    datetime.utcnow().replace(microsecond=0))
        self.noteProvider().remove(note)
        self.__setSelectedItem()

        self.reload()
        self.showStatus("Note deleted")
        self.__lstNotes.setFocus()

    def __onSyncClicked(self):
        if self.remoteNoteProvider() and self.__viewerEditor.isAllowedToChange(
        ):
            self.showStatus("Starting synchronization, please wait...",
                            immediate=True)
            try:
                Synchronizer(self.noteProvider(),
                             self.remoteNoteProvider()).sync()
                self.reload(True)
                self.showStatus("Synchronization finished")
            except TokenExpiredError:
                self.showError(
                    "Authentication expired. Synchronization account must be configured again"
                )
                self.disableSync()
            except AConnectionError:
                self.showError("Failed to connect to server")
            except InvalidProxyError:
                self.showError("Proxy settings are invalid")

    def __onPreferencesClicked(self):
        Preferences(self).show()

    def __onSearchEdited(self):
        self.__refreshNoteList(True)
        self.__viewerEditor.updateHighlight()

    def __onTagFilterSelectionChanged(self):
        self.__refreshNoteList(True)

    def __onTagFilterShortcutPressed(self):
        self.__cmbTag.setFocus()
        self.__cmbTag.showPopup()

    def __onNoteSelectionChanged(self):
        if self.__lstNotes.isEnabled() and self.__selectedItem():
            if self.__viewerEditor.isAllowedToChange():
                note = self.noteProvider().get(
                    self.__selectedItem().note().uuid)
                self.__viewerEditor.view(note)
                self.__refreshNoteButtons()
            else:
                self.__setSelectedItem(self.__viewerEditor.noteUuid())
Пример #4
0
Файл: ui.py Проект: vijo/sqink
class Window(QWidget):

    tagsChanged= Signal(list)

    def __init__(self, appPath):
        QWidget.__init__(self)
        rc.init(normpath(appPath + "/resources"))
        self.__config= Config(appPath)
        self.__noteProvider= SqliteNoteProvider(normpath(appPath + "/resources/notes/notes.db"))

        self.setWindowTitle("Scroll, Quill & INK")
        self.setMinimumSize(400, 240)
        self.resize(800, 600)

        icon= QIcon()
        icon.addPixmap(rc.pixmap("sqink-16x16.png"))
        icon.addPixmap(rc.pixmap("sqink-32x32.png"))
        self.setWindowIcon(icon)

        layout= QVBoxLayout()
        layout.setContentsMargins(5, 5, 5, 2)
        self.setLayout(layout)

        splitter= QSplitter()
        splitter.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        splitter.setStyle(QStyleFactory.create("Cleanlooks"))
        layout.addWidget(splitter)

        self.__statusBar= QStatusBar()
        self.__statusBar.setSizeGripEnabled(False)
        layout.addWidget(self.__statusBar)

        self.__lblNotesCount= QLabel()
        self.__lblNotesCount.setStyleSheet("border-radius:0.5em; background-color:#b2dfdb; padding:0 0.5em;")
        self.__statusBar.addPermanentWidget(self.__lblNotesCount)

        self.__lblError= QLabel()
        self.__lblError.setStyleSheet("border-radius:0.5em; background-color:#f36c60; padding:0 0.5em;")
        self.__lblError.setVisible(False)
        self.__statusBar.addWidget(self.__lblError)

        panelA= QWidget()
        splitter.addWidget(panelA)
        layoutA= QGridLayout()
        layoutA.setContentsMargins(0, 0, 0, 0)
        panelA.setLayout(layoutA)

        barButtons= QWidget()
        layoutButtons= QHBoxLayout()
        layoutButtons.setContentsMargins(0, 0, 0, 0)
        barButtons.setLayout(layoutButtons)
        layoutA.addWidget(barButtons, 0, 0, 1, 2)

        btnNew= QPushButton()
        btnNew.setIcon(rc.icon("note-new-16x16.png"))
        btnNew.setToolTip("New note (CTRL + N)")
        btnNew.clicked.connect(self.__onNewNoteClicked)
        btnNew.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_N))
        layoutButtons.addWidget(btnNew)

        self.__btnEdit= QPushButton()
        self.__btnEdit.setIcon(rc.icon("note-edit-16x16.png"))
        self.__btnEdit.setToolTip("Edit note (CTRL + E)")
        self.__btnEdit.clicked.connect(self.__onEditNoteClicked)
        self.__btnEdit.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_E))
        layoutButtons.addWidget(self.__btnEdit)

        self.__btnDelete= QPushButton()
        self.__btnDelete.setIcon(rc.icon("note-delete-16x16.png"))
        self.__btnDelete.setToolTip("Delete note (CTRL + L)")
        self.__btnDelete.clicked.connect(self.__onDeleteNoteClicked)
        self.__btnDelete.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_L))
        layoutButtons.addWidget(self.__btnDelete)

        layoutButtons.addStretch(1)

        self.__btnSync= QPushButton()
        self.__btnSync.setIcon(rc.icon("sync-16x16.png"))
        self.__btnSync.setToolTip("Sync (CTRL + I)")
        self.__btnSync.clicked.connect(self.__onSyncClicked)
        self.__btnSync.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_I))
        layoutButtons.addWidget(self.__btnSync)

        btnConfig= QPushButton()
        btnConfig.setIcon(rc.icon("preferences-16x16.png"))
        btnConfig.setToolTip("Preferences")
        btnConfig.clicked.connect(self.__onPreferencesClicked)
        layoutButtons.addWidget(btnConfig)

        lblSearch= QLabel()
        lblSearch.setPixmap(rc.pixmap("search-16x16.png"))
        lblSearch.setToolTip("Find (CTRL + F)")
        layoutA.addWidget(lblSearch, 1, 0)

        self.__txtSearch= QLineEdit()
        self.__txtSearch.setValidator(QRegExpValidator(QRegExp("[A-ZÁÉÍÓÚÜÑa-záéíóúüñ0-9 @:/#&=\.\-\?\\\\]+")))
        self.__txtSearch.textEdited.connect(self.__onSearchEdited)
        QShortcut(QKeySequence(Qt.CTRL + Qt.Key_F), self.__txtSearch, self.__txtSearch.setFocus)
        layoutA.addWidget(self.__txtSearch, 1, 1)

        lblTag= QLabel()
        lblTag.setPixmap(rc.pixmap("tag-16x16.png"))
        lblTag.setToolTip("Filter by tag (CTRL + T)")
        layoutA.addWidget(lblTag, 2, 0)

        self.__cmbTag= QComboBox()
        self.__cmbTag.activated.connect(self.__onTagFilterSelectionChanged)
        QShortcut(QKeySequence(Qt.CTRL + Qt.Key_T), self.__cmbTag, self.__onTagFilterShortcutPressed)
        layoutA.addWidget(self.__cmbTag, 2, 1)

        self.__lstNotes= ListWidget(self.__onDeleteNoteClicked)
        self.__lstNotes.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.__lstNotes.setItemDelegate(ListItemDelegate())
        self.__lstNotes.itemSelectionChanged.connect(self.__onNoteSelectionChanged)
        layoutA.addWidget(self.__lstNotes, 3, 0, 1, 2)

        self.__viewerEditor= ViewerEditor(self)
        splitter.addWidget(self.__viewerEditor)

        self.configureSync()
        self.reload()
        self.__txtSearch.setFocus()

    def closeEvent(self, event):
        self.__noteProvider.close()
        QWidget.closeEvent(self, event)

    def config(self):
        return self.__config

    def noteProvider(self):
        return self.__noteProvider

    def remoteNoteProvider(self):
        return self.__remoteNoteProvider

    def textFilter(self):
        return self.__txtSearch.text().strip()

    def configureSync(self):
        config= self.config()
        if config.isDropboxEnabled():
            self.__remoteNoteProvider= DropboxNoteProvider(config.getDropboxToken(), config.getDropboxFolder(),
                    config.getProxyHost(), config.getProxyPort(), config.getProxyUser(), config.getProxyPassword())
            self.__btnSync.setDisabled(False)
        elif config.isGoogleDriveEnabled():
            self.__remoteNoteProvider= GoogleDriveNoteProvider(config.getGoogleDriveToken(), config.getProxyHost(),
                    config.getProxyPort(), config.getProxyUser(), config.getProxyPassword())
            self.__btnSync.setDisabled(False)
        else:
            self.__remoteNoteProvider= None
            self.__btnSync.setDisabled(True)

    def disableSync(self):
        config= self.config()
        if config.isDropboxEnabled():
            config.setDropboxEnabled(False)
            config.setDropboxToken(None)
        else:
            config.setGoogleDriveEnabled(False)
            config.setGoogleDriveToken(None)
        config.save()
        self.configureSync()

    def updateProxy(self):
        self.__viewerEditor.updateProxy()

    def showStatus(self, message, seconds=5):
        self.clearError()
        self.__statusBar.showMessage(message, timeout=seconds * 1000)

    def showError(self, message):
        self.__statusBar.clearMessage()
        self.__lblError.setText(message)
        self.__lblError.setVisible(True)

    def clearError(self):
        self.__lblError.setVisible(False)

    def reload(self, selectNoteOnViewerEditor=False, skipViewerEditor=False):
        self.__notes= sorted(self.noteProvider().list(), key=lambda n: n.title.lower())
        self.__tags= listTags(self.__notes)
        self.__refreshTagCombo()
        self.__refreshNoteList(selectNoteOnViewerEditor)
        self.__lblNotesCount.setText("%d notes" % len(self.__notes))

        if not skipViewerEditor:
            self.__refreshNoteViewerEditor()

        self.__refreshNoteButtons()
        self.tagsChanged.emit(self.__tags)

    def __setSelectedItem(self, uuid=None):
        self.__lstNotes.setDisabled(True)

        if self.__selectedItem():
            self.__selectedItem().setSelected(False)

        if uuid:
            for i in range(self.__lstNotes.count()):
                item= self.__lstNotes.item(i)
                if (item.note().uuid == uuid):
                    item.setSelected(True)
                    break

        self.__lstNotes.setDisabled(False)

    def __selectedItem(self):
        selectedItems= self.__lstNotes.selectedItems()
        return selectedItems[0] if selectedItems else None

    def __refreshNoteButtons(self):
        disableButtons= not self.__viewerEditor.noteUuid()
        self.__btnEdit.setDisabled(disableButtons)
        self.__btnDelete.setDisabled(disableButtons)

    def __refreshTagCombo(self):
        tags= self.__tags[:]
        tags.insert(0, "")

        currentTag= self.__cmbTag.currentText()
        self.__cmbTag.clear()
        self.__cmbTag.addItems(tags)

        if currentTag and currentTag in tags:
            self.__cmbTag.setCurrentIndex(tags.index(currentTag))

    def __refreshNoteList(self, selectNoteOnViewerEditor=False):
        notes= self.__notes

        searchText= self.textFilter()
        if searchText:
            uuids= self.noteProvider().search(searchText)
            notes= list(filter(lambda n: n.uuid in uuids, notes))

        currentTag= self.__cmbTag.currentText()
        if currentTag:
            notes= list(filter(lambda n: n.hasTag(currentTag), notes))

        selectUuid= None
        if selectNoteOnViewerEditor:
            selectUuid= self.__viewerEditor.noteUuid()
        elif self.__selectedItem():
            selectUuid= self.__selectedItem().note().uuid
        elif len(notes) > 0:
            selectUuid= notes[0].uuid

        self.__lstNotes.setDisabled(True)
        self.__lstNotes.clear()
        selectedNoteItem= None
        for note in notes:
            item= ListItem(note, self.__lstNotes)
            if selectUuid == note.uuid:
                item.setSelected(True)
                selectedNoteItem= item
        if selectedNoteItem:
            self.__lstNotes.setCurrentItem(selectedNoteItem)
        self.__lstNotes.setDisabled(False)

    def __refreshNoteViewerEditor(self):
        if self.__selectedItem():
            note= self.noteProvider().get(self.__selectedItem().note().uuid)
        else:
            note= renderHtml(Note())
        self.__viewerEditor.view(note)

    def __onNewNoteClicked(self):
        if self.__viewerEditor.isAllowedToChange():
            self.__lstNotes.setCurrentItem(None)
            self.__viewerEditor.edit(renderHtml(Note()))
            self.__refreshNoteButtons()

    def __onEditNoteClicked(self):
        if self.__viewerEditor.isAllowedToChange():
            self.__viewerEditor.edit()

    def __onDeleteNoteClicked(self):
        choice= QMessageBox.question(self, "Delete note", "Are you ABSOLUTELY sure?",
                buttons=QMessageBox.Yes | QMessageBox.No, defaultButton=QMessageBox.No)
        if choice != QMessageBox.Yes:
            return

        note= Note(self.__viewerEditor.noteUuid(), datetime.utcnow().replace(microsecond=0))
        self.noteProvider().remove(note)
        self.__setSelectedItem()

        self.reload()
        self.showStatus("Note deleted")
        self.__lstNotes.setFocus()

    def __onSyncClicked(self):
        if self.remoteNoteProvider() and self.__viewerEditor.isAllowedToChange():
            self.showStatus("Starting synchronization, please wait...")
            try:
                Synchronizer(self.noteProvider(), self.remoteNoteProvider()).sync()
                self.reload(True)
                self.showStatus("Synchronization finished")
            except TokenExpiredError:
                self.showError("Authentication expired. Synchronization account must be configured again")
                self.disableSync()
            except AConnectionError:
                self.showError("Failed to connect to server")
            except InvalidProxyError:
                self.showError("Proxy settings are invalid")

    def __onPreferencesClicked(self):
        Preferences(self).show()

    def __onSearchEdited(self):
        self.__refreshNoteList(True)
        self.__viewerEditor.updateHighlight()

    def __onTagFilterSelectionChanged(self):
        self.__refreshNoteList(True)

    def __onTagFilterShortcutPressed(self):
        self.__cmbTag.setFocus()
        self.__cmbTag.showPopup()

    def __onNoteSelectionChanged(self):
        if self.__lstNotes.isEnabled() and self.__selectedItem():
            if self.__viewerEditor.isAllowedToChange():
                note= self.noteProvider().get(self.__selectedItem().note().uuid)
                self.__viewerEditor.view(note)
                self.__refreshNoteButtons()
            else:
                self.__setSelectedItem(self.__viewerEditor.noteUuid())