示例#1
0
    def __init__(self, parent=None):
        super().__init__(parent)
        self._delegate = None
        # ScrollPerPixel means user can draw scroll bar and move list items pixel by pixel,
        # but mouse wheel still scroll item by item (the number of items scrolled depends on
        # qApp.wheelScrollLines)
        self.setVerticalScrollMode(self.ScrollPerPixel)
        self.scrollbar = DiaryList.ScrollBar(self)
        self.scrollbar.wantSetRow.connect(self.setRow)
        self.setVerticalScrollBar(self.scrollbar)

        self.setupTheme()
        # disable default editor. Editor is implemented in the View
        self.setEditTriggers(QAbstractItemView.NoEditTriggers)

        self.originModel = DiaryModel(self)
        self.modelProxy = MultiSortFilterProxyModel(self)
        self.modelProxy.setSourceModel(self.originModel)
        self.modelProxy.setDynamicSortFilter(True)
        self.modelProxy.addFilter([db.TAGS], cs=Qt.CaseSensitive)
        self.modelProxy.addFilter([db.TITLE, db.TEXT], cs=Qt.CaseInsensitive)
        self.modelProxy.addFilter([db.DATETIME])
        self.setModel(self.modelProxy)
        self.sort()

        self.editAct = QAction(self.tr('Edit'), self)
        self.delAct = QAction(makeQIcon(':/menu/list-delete.png', scaled2x=True),
                              self.tr('Delete'), self, shortcut=QKeySequence.Delete)
        self.randAct = QAction(makeQIcon(':/menu/random-big.png', scaled2x=True),
                               self.tr('Random'), self,
                               shortcut=QKeySequence(Qt.Key_F7), triggered=self.selectRandomly)
        self.gotoAct = QAction(self.tr('Go to location'), self)
        for i in (self.editAct, self.delAct, self.randAct, self.gotoAct):
            self.addAction(i)
示例#2
0
    def __init__(self, parent=None):
        super().__init__(parent)
        self._delegate = None
        # ScrollPerPixel means user can draw scroll bar and move list items pixel by pixel,
        # but mouse wheel still scroll item by item (the number of items scrolled depends on
        # qApp.wheelScrollLines)
        self.setVerticalScrollMode(self.ScrollPerPixel)
        self.scrollbar = DiaryListScrollBar(self)
        self.scrollbar.wantSetRow.connect(self.setRow)
        self.setVerticalScrollBar(self.scrollbar)

        # disable default editor. Editor is implemented in the View
        self.setEditTriggers(QAbstractItemView.NoEditTriggers)

        self.originModel = DiaryModel(self)
        self.modelProxy = MultiSortFilterProxyModel(self)
        self.modelProxy.setSourceModel(self.originModel)
        self.modelProxy.setDynamicSortFilter(True)
        self.modelProxy.addFilter([db.TAGS], cs=Qt.CaseSensitive)
        self.modelProxy.addFilter([db.TITLE, db.TEXT], cs=Qt.CaseInsensitive)
        self.modelProxy.addFilter([db.DATETIME])
        self.setModel(self.modelProxy)
        self.sort()

        self.setupTheme()

        self.editAct = QAction(self.tr('Edit'), self)
        self.delAct = QAction(makeQIcon(':/menu/list-delete.png',
                                        scaled2x=True),
                              self.tr('Delete'),
                              self,
                              shortcut=QKeySequence.Delete)
        self.randAct = QAction(makeQIcon(':/menu/random-big.png',
                                         scaled2x=True),
                               self.tr('Random'),
                               self,
                               shortcut=QKeySequence(Qt.Key_F7),
                               triggered=self.selectRandomly)
        self.gotoAct = QAction(self.tr('Go to location'), self)
        for i in (self.editAct, self.delAct, self.randAct, self.gotoAct):
            self.addAction(i)
示例#3
0
class DiaryList(QListView):
    """Main List that display preview of diaries"""
    startLoading = Signal()
    countChanged = Signal()

    class ScrollBar(QScrollBar):
        """Annotated scrollbar."""
        wantSetRow = Signal(int)

        def __init__(self, parent):
            super().__init__(parent, objectName='diaryListSB')
            self._poses = ()
            self._pairs = ()  # year: row
            self._color = QColor('gold')

        def paintEvent(self, event):
            super().paintEvent(event)
            if not self._poses:
                return
            p = QPainter(self)
            # avoid painting on slider handle
            opt = QStyleOptionSlider()
            self.initStyleOption(opt)
            groove = self.style().subControlRect(QStyle.CC_ScrollBar, opt,
                                                 QStyle.SC_ScrollBarGroove, self)
            slider = self.style().subControlRect(QStyle.CC_ScrollBar, opt,
                                                 QStyle.SC_ScrollBarSlider, self)
            p.setClipRegion(QRegion(groove) - QRegion(slider), Qt.IntersectClip)

            x, y, w, h = groove.getRect()
            x += 1
            w -= 2
            c = self._color
            c.setAlpha(70)
            p.setBrush(c)
            c.setAlpha(145)
            p.setPen(QPen(c, scaleRatio))
            p.drawRects([QRect(x, y+h*i, w, 3*scaleRatio) for i in self._poses])

        def contextMenuEvent(self, event):
            """Used to jump to the first day of years. Original menu is almost useless."""
            menu = QMenu()
            menu.addAction(QAction(self.tr('Go to the first diary of each year'), menu, enabled=False))
            for year, row in self._pairs:
                menu.addAction(QAction(str(year), menu,
                                       triggered=lambda r=row: self.wantSetRow.emit(r)))
            menu.exec_(event.globalPos())
            menu.deleteLater()

        def setPositions(self, rowCount, pairs):
            self._poses = tuple(p / rowCount for _, p in pairs)
            self._pairs = pairs

        annotateColor = NProperty(QColor, '_color')

    def __init__(self, parent=None):
        super().__init__(parent)
        self._delegate = None
        # ScrollPerPixel means user can draw scroll bar and move list items pixel by pixel,
        # but mouse wheel still scroll item by item (the number of items scrolled depends on
        # qApp.wheelScrollLines)
        self.setVerticalScrollMode(self.ScrollPerPixel)
        self.scrollbar = DiaryList.ScrollBar(self)
        self.scrollbar.wantSetRow.connect(self.setRow)
        self.setVerticalScrollBar(self.scrollbar)

        self.setupTheme()
        # disable default editor. Editor is implemented in the View
        self.setEditTriggers(QAbstractItemView.NoEditTriggers)

        self.originModel = DiaryModel(self)
        self.modelProxy = MultiSortFilterProxyModel(self)
        self.modelProxy.setSourceModel(self.originModel)
        self.modelProxy.setDynamicSortFilter(True)
        self.modelProxy.addFilter([db.TAGS], cs=Qt.CaseSensitive)
        self.modelProxy.addFilter([db.TITLE, db.TEXT], cs=Qt.CaseInsensitive)
        self.modelProxy.addFilter([db.DATETIME])
        self.setModel(self.modelProxy)
        self.sort()

        self.editAct = QAction(self.tr('Edit'), self)
        self.delAct = QAction(makeQIcon(':/menu/list-delete.png', scaled2x=True),
                              self.tr('Delete'), self, shortcut=QKeySequence.Delete)
        self.randAct = QAction(makeQIcon(':/menu/random-big.png', scaled2x=True),
                               self.tr('Random'), self,
                               shortcut=QKeySequence(Qt.Key_F7), triggered=self.selectRandomly)
        self.gotoAct = QAction(self.tr('Go to location'), self)
        for i in (self.editAct, self.delAct, self.randAct, self.gotoAct):
            self.addAction(i)

    def contextMenuEvent(self, event):
        menu = QMenu()
        menu.addAction(self.editAct)
        menu.addAction(self.delAct)
        menu.addSeparator()
        menu.addAction(self.randAct)
        selCount = len(self.selectedIndexes())
        if selCount == 1 and self.modelProxy.isFiltered():
            menu.addAction(self.gotoAct)
        self.editAct.setDisabled(selCount != 1)
        self.delAct.setDisabled(selCount == 0)
        self.randAct.setDisabled(self.modelProxy.rowCount() == 0)
        menu.exec_(event.globalPos())

    def selectAll(self):
        """Prevent original implement to select invisible columns from the Table Model."""
        sel = QItemSelection(self.model().index(0, 0),
                             self.model().index(self.model().rowCount()-1, 0))
        self.selectionModel().select(sel, QItemSelectionModel.ClearAndSelect)

    def setRow(self, row):
        self.setCurrentIndex(self.modelProxy.index(row, 0))

    def selectRandomly(self):
        self.setRow(random.randrange(0, self.modelProxy.rowCount()))

    def load(self):
        self.startLoading.emit()
        self.originModel.loadFromDb()
        self.setAnnotatedScrollbar()
        self.countChanged.emit()

    def setupTheme(self):
        theme = settings['Main']['theme']
        self._delegate = {'colorful': DiaryListDelegateColorful}.get(theme, DiaryListDelegate)()
        self.setItemDelegate(self._delegate)
        if self.isVisible():
            # force items to be laid again
            self.setSpacing(self.spacing())
            self.setAnnotatedScrollbar()

    def reload(self):
        self.originModel.clear()
        self.load()

    def handleExport(self, path, export_all):
        if export_all:
            selected = None
        else:
            selected = list(map(self.getDiaryDict, self.selectedIndexes()))
        db.export_txt(path, selected)

    def getDiaryDict(self, idx):
        """Get a diary dict by its index in proxy model. Diary dict is only used by Editor."""
        return self.originModel.getDiaryDictByRow(self.modelProxy.mapToSource(idx).row())

    def sort(self):
        sortBy = settings['Main']['listSortBy']
        sortByCol = getattr(DiaryModel, sortBy.upper(), DiaryModel.DATETIME)
        reverse = settings['Main'].getboolean('listReverse')
        self.modelProxy.sort(sortByCol,
                             Qt.DescendingOrder if reverse else Qt.AscendingOrder)
        if self.isVisible():
            self.setAnnotatedScrollbar()

    def setAnnotatedScrollbar(self, show=None):
        if show is not False and settings['Main'].getboolean('listAnnotated'):
            self.scrollbar.setPositions(self.originModel.rowCount(), self.originModel.getYearFirsts())
            self.scrollbar.update()
        else:
            self.scrollbar.poses = ()

    def _setFilter(self, filterKey, s):
        self.modelProxy.setFilterPattern(filterKey, s)
        self.setAnnotatedScrollbar(False if s else not self.modelProxy.isFiltered())
        self.countChanged.emit()

    def setFilterBySearchString(self, s):
        self._setFilter(1, s)

    def setFilterByTag(self, s):
        self._setFilter(0, s)

    def setFilterByDatetime(self, s):
        self._setFilter(2, s)

    @Slot(str)
    def refreshFilteredTags(self, newTagName):
        """Update items with old tag after a tag's name changed, and update filter (
        Right click tag item and rename it will always set filter)."""
        model, modelP = self.originModel, self.modelProxy
        needRefresh = [modelP.mapToSource(modelP.index(i, 0))
                       for i in range(modelP.rowCount())]
        for i in needRefresh:
            diary = db[i.data()]  # lazy
            model.setData(i.sibling(i.row(), DiaryModel.TAGS), diary[DiaryModel.TAGS])
        self.setFilterByTag(newTagName)
示例#4
0
class DiaryList(QListView):
    """Main List that display preview of diaries"""
    startLoading = Signal()
    countChanged = Signal()

    def __init__(self, parent=None):
        super().__init__(parent)
        self._delegate = None
        # ScrollPerPixel means user can draw scroll bar and move list items pixel by pixel,
        # but mouse wheel still scroll item by item (the number of items scrolled depends on
        # qApp.wheelScrollLines)
        self.setVerticalScrollMode(self.ScrollPerPixel)
        self.scrollbar = DiaryListScrollBar(self)
        self.scrollbar.wantSetRow.connect(self.setRow)
        self.setVerticalScrollBar(self.scrollbar)

        # disable default editor. Editor is implemented in the View
        self.setEditTriggers(QAbstractItemView.NoEditTriggers)

        self.originModel = DiaryModel(self)
        self.modelProxy = MultiSortFilterProxyModel(self)
        self.modelProxy.setSourceModel(self.originModel)
        self.modelProxy.setDynamicSortFilter(True)
        self.modelProxy.addFilter([db.TAGS], cs=Qt.CaseSensitive)
        self.modelProxy.addFilter([db.TITLE, db.TEXT], cs=Qt.CaseInsensitive)
        self.modelProxy.addFilter([db.DATETIME])
        self.setModel(self.modelProxy)
        self.sort()

        self.setupTheme()

        self.editAct = QAction(self.tr('Edit'), self)
        self.delAct = QAction(makeQIcon(':/menu/list-delete.png',
                                        scaled2x=True),
                              self.tr('Delete'),
                              self,
                              shortcut=QKeySequence.Delete)
        self.randAct = QAction(makeQIcon(':/menu/random-big.png',
                                         scaled2x=True),
                               self.tr('Random'),
                               self,
                               shortcut=QKeySequence(Qt.Key_F7),
                               triggered=self.selectRandomly)
        self.gotoAct = QAction(self.tr('Go to location'), self)
        for i in (self.editAct, self.delAct, self.randAct, self.gotoAct):
            self.addAction(i)

    def contextMenuEvent(self, event):
        menu = QMenu()
        menu.addAction(self.editAct)
        menu.addAction(self.delAct)
        menu.addSeparator()
        menu.addAction(self.randAct)
        selCount = len(self.selectedIndexes())
        if selCount == 1 and self.modelProxy.isFiltered():
            menu.addAction(self.gotoAct)
        self.editAct.setDisabled(selCount != 1)
        self.delAct.setDisabled(selCount == 0)
        self.randAct.setDisabled(self.modelProxy.rowCount() == 0)
        menu.exec_(event.globalPos())

    def selectAll(self):
        """Prevent original implement to select invisible columns from the Table Model."""
        sel = QItemSelection(
            self.model().index(0, 0),
            self.model().index(self.model().rowCount() - 1, 0))
        self.selectionModel().select(sel, QItemSelectionModel.ClearAndSelect)

    def resizeEvent(self, event):
        super().resizeEvent(event)
        if self._delegate.__class__ == DiaryListDelegateColorful:
            self._delegate.adjustWidgetCache(self.height())

    def setRow(self, row):
        self.setCurrentIndex(self.modelProxy.index(row, 0))

    def selectRandomly(self):
        self.setRow(random.randrange(0, self.modelProxy.rowCount()))

    def load(self):
        self.startLoading.emit()
        self.originModel.loadFromDb()
        self.setAnnotatedScrollbar()
        self.countChanged.emit()

    def setupTheme(self):
        theme = settings['Main']['theme']
        if theme == 'colorful':
            self._delegate = DiaryListDelegateColorful(self.modelProxy)
        else:
            self._delegate = DiaryListDelegate()
        self.setItemDelegate(self._delegate)
        if self.isVisible():
            # force items to be laid again
            self.setSpacing(self.spacing())
            self.setAnnotatedScrollbar()
            if theme == 'colorful':
                self._delegate.adjustWidgetCache(self.height())

    def reload(self):
        self.originModel.clear()
        self.load()

    def handleExport(self, path, export_all):
        if export_all:
            selected = None
        else:
            selected = list(map(self.getDiaryDict, self.selectedIndexes()))
        db.export_txt(path, selected)

    def getDiaryDict(self, idx):
        """Get a diary dict by its index in proxy model. Diary dict is only used by Editor."""
        return self.originModel.getDiaryDictByRow(
            self.modelProxy.mapToSource(idx).row())

    def sort(self):
        sortBy = settings['Main']['listSortBy']
        sortByCol = getattr(DiaryModel, sortBy.upper(), DiaryModel.DATETIME)
        reverse = settings['Main'].getboolean('listReverse')
        self.modelProxy.sort(
            sortByCol, Qt.DescendingOrder if reverse else Qt.AscendingOrder)
        if self.isVisible():
            self.setAnnotatedScrollbar()

    def setAnnotatedScrollbar(self, show=None):
        if show is not False and settings['Main'].getboolean('listAnnotated'):
            self.scrollbar.setPositions(self.originModel.rowCount(),
                                        self.originModel.getYearFirsts())
        else:
            self.scrollbar.setPositions(None, None)

    def _setFilter(self, filterKey, s):
        self.modelProxy.setFilterPattern(filterKey, s)
        self.setAnnotatedScrollbar(
            False if s else not self.modelProxy.isFiltered())
        self.countChanged.emit()

    def setFilterBySearchString(self, s):
        self._setFilter(1, s)

    def setFilterByTag(self, s):
        self._setFilter(0, s)

    def setFilterByDatetime(self, s):
        self._setFilter(2, s)

    @Slot(str)
    def refreshFilteredTags(self, newTagName):
        """Update items with old tag after a tag's name changed, and update filter (
        Right click tag item and rename it will always set filter)."""
        model, modelP = self.originModel, self.modelProxy
        needRefresh = [
            modelP.mapToSource(modelP.index(i, 0))
            for i in range(modelP.rowCount())
        ]
        for i in needRefresh:
            diary = db[i.data()]  # lazy
            model.setData(i.sibling(i.row(), DiaryModel.TAGS),
                          diary[DiaryModel.TAGS])
        self.setFilterByTag(newTagName)
示例#5
0
文件: diarylist.py 项目: krrr/Hazama
class DiaryList(QListView):
    """Main List that display preview of diaries"""
    startLoading = Signal()
    countChanged = Signal()

    def __init__(self, parent=None):
        super().__init__(parent)
        self._delegate = None
        # ScrollPerPixel means user can draw scroll bar and move list items pixel by pixel,
        # but mouse wheel still scroll item by item (the number of items scrolled depends on
        # qApp.wheelScrollLines)
        self.setVerticalScrollMode(self.ScrollPerPixel)
        self.scrollbar = DiaryListScrollBar(self)
        self.scrollbar.wantSetRow.connect(self.setRow)
        self.setVerticalScrollBar(self.scrollbar)

        # disable default editor. Editor is implemented in the View
        self.setEditTriggers(QAbstractItemView.NoEditTriggers)

        self.originModel = DiaryModel(self)
        self.modelProxy = MultiSortFilterProxyModel(self)
        self.modelProxy.setSourceModel(self.originModel)
        self.modelProxy.setDynamicSortFilter(True)
        self.modelProxy.addFilter([db.TAGS], cs=Qt.CaseSensitive)
        self.modelProxy.addFilter([db.TITLE, db.TEXT], cs=Qt.CaseInsensitive)
        self.modelProxy.addFilter([db.DATETIME])
        self.setModel(self.modelProxy)
        self.sort()

        self.setupTheme()

        self.editAct = QAction(self.tr('Edit'), self)
        self.delAct = QAction(makeQIcon(':/menu/list-delete.png', scaled2x=True),
                              self.tr('Delete'), self, shortcut=QKeySequence.Delete)
        self.randAct = QAction(makeQIcon(':/menu/random-big.png', scaled2x=True),
                               self.tr('Random'), self,
                               shortcut=QKeySequence(Qt.Key_F7), triggered=self.selectRandomly)
        self.gotoAct = QAction(self.tr('Go to location'), self)
        for i in (self.editAct, self.delAct, self.randAct, self.gotoAct):
            self.addAction(i)

    def contextMenuEvent(self, event):
        menu = QMenu()
        menu.addAction(self.editAct)
        menu.addAction(self.delAct)
        menu.addSeparator()
        menu.addAction(self.randAct)
        selCount = len(self.selectedIndexes())
        if selCount == 1 and self.modelProxy.isFiltered():
            menu.addAction(self.gotoAct)
        self.editAct.setDisabled(selCount != 1)
        self.delAct.setDisabled(selCount == 0)
        self.randAct.setDisabled(self.modelProxy.rowCount() == 0)
        menu.exec_(event.globalPos())

    def selectAll(self):
        """Prevent original implement to select invisible columns from the Table Model."""
        sel = QItemSelection(self.model().index(0, 0),
                             self.model().index(self.model().rowCount()-1, 0))
        self.selectionModel().select(sel, QItemSelectionModel.ClearAndSelect)

    def resizeEvent(self, event):
        super().resizeEvent(event)
        if self._delegate.__class__ == DiaryListDelegateColorful:
            self._delegate.adjustWidgetCache(self.height())

    def setRow(self, row):
        self.setCurrentIndex(self.modelProxy.index(row, 0))

    def selectRandomly(self):
        self.setRow(random.randrange(0, self.modelProxy.rowCount()))

    def load(self):
        self.startLoading.emit()
        self.originModel.loadFromDb()
        self.setAnnotatedScrollbar()
        self.countChanged.emit()

    def setupTheme(self):
        theme = settings['Main']['theme']
        if theme == 'colorful':
            self._delegate = DiaryListDelegateColorful(self.modelProxy)
        else:
            self._delegate = DiaryListDelegate()
        self.setItemDelegate(self._delegate)
        if self.isVisible():
            # force items to be laid again
            self.setSpacing(self.spacing())
            self.setAnnotatedScrollbar()
            if theme == 'colorful':
                self._delegate.adjustWidgetCache(self.height())

    def reload(self):
        self.originModel.clear()
        self.load()

    def handleExport(self, path, export_all):
        if export_all:
            selected = None
        else:
            selected = list(map(self.getDiaryDict, self.selectedIndexes()))
        db.export_txt(path, selected)

    def getDiaryDict(self, idx):
        """Get a diary dict by its index in proxy model. Diary dict is only used by Editor."""
        return self.originModel.getDiaryDictByRow(self.modelProxy.mapToSource(idx).row())

    def sort(self):
        sortBy = settings['Main']['listSortBy']
        sortByCol = getattr(DiaryModel, sortBy.upper(), DiaryModel.DATETIME)
        reverse = settings['Main'].getboolean('listReverse')
        self.modelProxy.sort(sortByCol,
                             Qt.DescendingOrder if reverse else Qt.AscendingOrder)
        if self.isVisible():
            self.setAnnotatedScrollbar()

    def setAnnotatedScrollbar(self, show=None):
        if show is not False and settings['Main'].getboolean('listAnnotated'):
            self.scrollbar.setPositions(self.originModel.rowCount(), self.originModel.getYearFirsts())
        else:
            self.scrollbar.setPositions(None, None)

    def _setFilter(self, filterKey, s):
        self.modelProxy.setFilterPattern(filterKey, s)
        self.setAnnotatedScrollbar(False if s else not self.modelProxy.isFiltered())
        self.countChanged.emit()

    def setFilterBySearchString(self, s):
        self._setFilter(1, s)

    def setFilterByTag(self, s):
        self._setFilter(0, s)

    def setFilterByDatetime(self, s):
        self._setFilter(2, s)

    @Slot(str)
    def refreshFilteredTags(self, newTagName):
        """Update items with old tag after a tag's name changed, and update filter (
        Right click tag item and rename it will always set filter)."""
        model, modelP = self.originModel, self.modelProxy
        needRefresh = [modelP.mapToSource(modelP.index(i, 0))
                       for i in range(modelP.rowCount())]
        for i in needRefresh:
            diary = db[i.data()]  # lazy
            model.setData(i.sibling(i.row(), DiaryModel.TAGS), diary[DiaryModel.TAGS])
        self.setFilterByTag(newTagName)