view MainWindow.py @ 259:304917762618 default tip

implementation of feed updates
author Dirk Olmes <dirk@xanthippe.ping.de>
date Tue, 12 Mar 2019 02:41:22 +0100
parents 3ce39af93e77
children
line wrap: on
line source

# -*- coding: utf-8 -*-
from AddFeed import AddFeed
from PyQtLib.GenericListModel import GenericListModel
from PyQtLib.GenericTableModel import GenericTableModel
from FeedEntryItemDelegate import FeedEntryItemDelegate
from FeedSettings import FeedSettings
from PreferencesDialog import PreferencesDialog
from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget
from PyQt5.QtGui import QDesktopServices
from Ui_MainWindow import Ui_MainWindow

STATUS_MESSAGE_DISPLAY_MILLIS = 20000

class MainWindow(QMainWindow):
    def __init__(self, backend=None):
        QWidget.__init__(self, None)
        self.backend = backend
        self.preferences = backend.preferences()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.updateFeedList()
        self.initFeedEntryTable()

    def updateFeedList(self):
        allFeeds = self.backend.getFeeds()
        feedModel = GenericListModel(self,  allFeeds, 'title')
        self.ui.feedList.setModel(feedModel)
        self.ui.feedList.update()
        self.__updateFeedCountLabel(allFeeds)

    def __updateFeedCountLabel(self,  feeds):
        feedCount = len(feeds)
        text = '%d feed' % feedCount
        if feedCount > 1:
            text = text + 's'
        self.ui.feedCountLabel.setText(text)

    def initFeedEntryTable(self):
        # setup the default row height. This must be called before a table model is set
        self.ui.feedEntryTable.verticalHeader().setDefaultSectionSize(20)

        self.ui.feedEntryTable.setItemDelegate(FeedEntryItemDelegate())
        model = self.__buildFeedEntryTableModel()
        self.ui.feedEntryTable.setModel(model)
        self.ui.feedEntryTable.horizontalHeader().setStretchLastSection(True)

    def __buildFeedEntryTableModel(self):
        model = GenericTableModel(self,  [])
        titleDisplay = lambda feedEntry: feedEntry.title
        model.defineColumn('Title',  titleDisplay)
        dateDisplay = lambda feedEntry: feedEntry.updated.strftime('%d.%m.%Y')
        model.defineColumn('Date',  dateDisplay)
        return model

    def feedSelected(self, index):
        self.backend.selectFeed(index.row())
        self.enableFeedRelatedWidgets()
        self.setupFeedEntries()

    def enableFeedRelatedWidgets(self):
        self.ui.actionFeedSettings.setEnabled(True)
        self.ui.actionMarkFeedRead.setEnabled(True)
        self.ui.actionMarkSelectedEntriesRead.setEnabled(True)
        self.ui.actionDeleteFeed.setEnabled(True)

    def setupFeedEntries(self):
        feedEntries = self.backend.entriesForSelectedFeed()
        self.setupFeedEntriesTableModel(feedEntries)
        self.ui.feedEntryTable.update()
        self.setupFeedEntriesTableHeaderWidths()
        self.scrollFirstRowInFeedEntriesTableToVisible()
        self.__updateFeedEntryCountLabel(feedEntries)

    def setupFeedEntriesTableModel(self,  feedEntries):
        model = self.ui.feedEntryTable.model()
        model.setDisplayedObjects(feedEntries)

    def setupFeedEntriesTableHeaderWidths(self):
        width = self.ui.feedEntryTable.width()
        firstColumnWidth = int(width * 0.8)
        self.ui.feedEntryTable.setColumnWidth(0, firstColumnWidth)

    def scrollFirstRowInFeedEntriesTableToVisible(self):
        model = self.ui.feedEntryTable.model()
        visibleIndex = model.createIndex(0, 0)
        self.ui.feedEntryTable.scrollTo(visibleIndex)

    def __updateFeedEntryCountLabel(self, feedEntries):
        count = len(feedEntries)
        text = '%d Article' % count
        if count > 1:
            text = text + 's'
        self.ui.feedEntryCountLabel.setText(text)

    def feedEntrySelected(self, index):
        self.ui.webView.setZoomFactor(1.0)
        self.ui.menuArticle.setEnabled(True)
        self.ui.actionOpenLink.setEnabled(True)

        row = index.row()
        self.backend.selectFeedEntry(row)

        if self.backend.selectedFeed.auto_load_entry_link:
            self.openLinkFromSelectedEntry()
        else:
            self.openSummaryFromSelectedEntry()

    def feedEntryDoubleClicked(self, index):
        self.ui.menuArticle.setEnabled(True)
        self.openSelectedEntryInBrowser()

    def openSummaryFromSelectedEntry(self):
        # TODO: this is the wrong base url, figure out the correct one
        feedEntry = self.backend.selectedFeedEntry
        baseUrl = QUrl(feedEntry.link)
        self.ui.webView.setHtml(feedEntry.summary, baseUrl)

    def openLinkFromSelectedEntry(self):
        if self.backend.selectedFeed.always_open_in_browser:
            self.openSelectedEntryInBrowser()
        else:
            self.openSelectedEntryInWebView()

    def openSelectedEntryInWebView(self):
        feedEntry = self.backend.selectedFeedEntry
        message = "Open %s ..." % (feedEntry.title)
        self._updateStatusBar(message)
        url = QUrl(feedEntry.link)
        self.ui.webView.load(url)
        self.ui.webView.show()

    def openSelectedEntryInBrowser(self):
        article = self.backend.selectedFeedEntry
        message = "Open %s in external browser" % (article.title)
        self._updateStatusBar(message)
        url = QUrl(article.link)
        QDesktopServices.openUrl(url)

    def toggleReadOnSelectedEntry(self):
        self.backend.toggleSelectedFeedEntryRead()
        self.ui.feedEntryTable.doItemsLayout()

    def markSelectedFeedRead(self):
        self.backend.markSelectedFeedAsRead()
        self.ui.feedEntryTable.doItemsLayout()

    def markSelectedEntriesRead(self):
        indexes = []
        selectedIndexes = self.ui.feedEntryTable.selectedIndexes()
        for index in selectedIndexes:
            # selectedIndexes returns one QModelIndex instance per row/column combo.
            # We are only interested in the rows here so just operate on the first
            # column
            if index.column() == 0:
                row = index.row()
                indexes.append(row)
        self.backend.markFeedEntriesAsRead(indexes)
        self.ui.feedEntryTable.doItemsLayout()

    def addFeed(self):
        addFeed = AddFeed(self.backend)
        success = addFeed.exec_()
        if not success:
            return

        if addFeed.exception is not None:
            message = "Error while adding feed: " + str(addFeed.exception)
            self._updateStatusBar(message)
        else:
            self.updateFeedList()

    def deleteFeed(self):
        try:
            self.backend.deleteSelectedFeed()
            self.updateFeedList()
        except Exception as exception:
            message = "Error while deleting feed: " + str(exception)
            self._updateStatusBar(message)

    def showPreferences(self):
        preferences = PreferencesDialog(self.backend)
        preferences.exec_()

    def showFeedSettings(self):
        feedSettings = FeedSettings(self.backend)
        feedSettings.exec_()

    def _updateStatusBar(self, message):
        self.ui.statusbar.showMessage(message, STATUS_MESSAGE_DISPLAY_MILLIS)

    def close(self):
        self.backend.dispose()
        QMainWindow.close(self)

    def copyArticleURLToClipboard(self):
        clipboard = QApplication.clipboard()
        clipboard.setText(self.backend.selectedFeedEntry.link)

    def zoomIn(self):
        zoom = self.ui.webView.zoomFactor() + 0.1
        self.ui.webView.setZoomFactor(zoom)

    def zoomOut(self):
        zoom = self.ui.webView.zoomFactor() - 0.1
        self.ui.webView.setZoomFactor(zoom)

    def aboutQtClicked(self):
        QApplication.aboutQt()