Initial implementation of newspaper view.
This commit is contained in:
		
							parent
							
								
									37f631193e
								
							
						
					
					
						commit
						9149b90042
					
				
					 13 changed files with 105 additions and 32 deletions
				
			
		|  | @ -4,6 +4,7 @@ | |||
| #include "core/databasefactory.h" | ||||
| #include "core/feedsmodelstandardcategory.h" | ||||
| #include "core/feedsmodelstandardfeed.h" | ||||
| #include "core/textfactory.h" | ||||
| #include "gui/iconthemefactory.h" | ||||
| #include "gui/iconfactory.h" | ||||
| 
 | ||||
|  | @ -130,6 +131,37 @@ int FeedsModel::rowCount(const QModelIndex &parent) const { | |||
|   return parent_item->childCount(); | ||||
| } | ||||
| 
 | ||||
| QList<Message> FeedsModel::messagesForFeeds(const QList<FeedsModelFeed *> &feeds) { | ||||
|   QList<Message> messages; | ||||
| 
 | ||||
|   QSqlDatabase database = DatabaseFactory::getInstance()->addConnection(objectName()); | ||||
|   QSqlQuery query_read_msg(database); | ||||
|   query_read_msg.setForwardOnly(true); | ||||
|   query_read_msg.prepare("SELECT title, url, author, date_created, contents " | ||||
|                          "FROM Messages " | ||||
|                          "WHERE deleted = 0 AND feed = :feed;"); | ||||
| 
 | ||||
|   foreach (FeedsModelFeed *feed, feeds) { | ||||
|     query_read_msg.bindValue(":feed", feed->id()); | ||||
| 
 | ||||
|     if (query_read_msg.exec()) { | ||||
|       while (query_read_msg.next()) { | ||||
|         Message message; | ||||
| 
 | ||||
|         message.m_title = query_read_msg.value(0).toString(); | ||||
|         message.m_url = query_read_msg.value(1).toString(); | ||||
|         message.m_author = query_read_msg.value(2).toString(); | ||||
|         message.m_created = TextFactory::parseDateTime(query_read_msg.value(3).value<qint64>()); | ||||
|         message.m_contents = query_read_msg.value(4).toString(); | ||||
| 
 | ||||
|         messages.append(message); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   return messages; | ||||
| } | ||||
| 
 | ||||
| int FeedsModel::columnCount(const QModelIndex &parent) const { | ||||
|   if (parent.isValid()) { | ||||
|     return static_cast<FeedsModelRootItem*>(parent.internalPointer())->columnCount(); | ||||
|  | @ -316,7 +348,7 @@ void FeedsModel::loadFromDatabase() { | |||
| 
 | ||||
| QList<FeedsModelFeed*> FeedsModel::feedsForIndex(const QModelIndex &index) { | ||||
|   FeedsModelRootItem *item = itemForIndex(index); | ||||
|   return getFeeds(item); | ||||
|   return feedsForItem(item); | ||||
| } | ||||
| 
 | ||||
| FeedsModelFeed *FeedsModel::feedForIndex(const QModelIndex &index) { | ||||
|  | @ -423,11 +455,11 @@ bool FeedsModel::markFeedsDeleted(const QList<FeedsModelFeed *> &feeds, | |||
|   } | ||||
| } | ||||
| 
 | ||||
| QHash<int, FeedsModelCategory*> FeedsModel::getAllCategories() { | ||||
|   return getCategories(m_rootItem); | ||||
| QHash<int, FeedsModelCategory*> FeedsModel::allCategories() { | ||||
|   return categoriesForItem(m_rootItem); | ||||
| } | ||||
| 
 | ||||
| QHash<int, FeedsModelCategory*> FeedsModel::getCategories(FeedsModelRootItem *root) { | ||||
| QHash<int, FeedsModelCategory*> FeedsModel::categoriesForItem(FeedsModelRootItem *root) { | ||||
|   QHash<int, FeedsModelCategory*> categories; | ||||
|   QList<FeedsModelRootItem*> parents; | ||||
| 
 | ||||
|  | @ -453,11 +485,11 @@ QHash<int, FeedsModelCategory*> FeedsModel::getCategories(FeedsModelRootItem *ro | |||
|   return categories; | ||||
| } | ||||
| 
 | ||||
| QList<FeedsModelFeed*> FeedsModel::getAllFeeds() { | ||||
|   return getFeeds(m_rootItem); | ||||
| QList<FeedsModelFeed*> FeedsModel::allFeeds() { | ||||
|   return feedsForItem(m_rootItem); | ||||
| } | ||||
| 
 | ||||
| QList<FeedsModelFeed*> FeedsModel::getFeeds(FeedsModelRootItem *root) { | ||||
| QList<FeedsModelFeed*> FeedsModel::feedsForItem(FeedsModelRootItem *root) { | ||||
|   QList<FeedsModelFeed*> feeds; | ||||
| 
 | ||||
|   if (root->kind() == FeedsModelRootItem::Feed) { | ||||
|  | @ -491,7 +523,7 @@ QList<FeedsModelFeed*> FeedsModel::getFeeds(FeedsModelRootItem *root) { | |||
| } | ||||
| 
 | ||||
| void FeedsModel::assembleFeeds(FeedAssignment feeds) { | ||||
|   QHash<int, FeedsModelCategory*> categories = getAllCategories(); | ||||
|   QHash<int, FeedsModelCategory*> categories = allCategories(); | ||||
| 
 | ||||
|   foreach (const FeedAssignmentItem &feed, feeds) { | ||||
|     if (feed.first == NO_PARENT_CATEGORY) { | ||||
|  |  | |||
|  | @ -2,6 +2,9 @@ | |||
| #define FEEDSMODEL_H | ||||
| 
 | ||||
| #include <QAbstractItemModel> | ||||
| 
 | ||||
| #include "core/messagesmodel.h" | ||||
| 
 | ||||
| #include <QIcon> | ||||
| 
 | ||||
| 
 | ||||
|  | @ -30,20 +33,23 @@ class FeedsModel : public QAbstractItemModel { | |||
|     int columnCount(const QModelIndex &parent) const; | ||||
|     int rowCount(const QModelIndex &parent) const; | ||||
| 
 | ||||
|     // Returns all (undeleted) messages for given feeds.
 | ||||
|     QList<Message> messagesForFeeds(const QList<FeedsModelFeed*> &feeds); | ||||
| 
 | ||||
|     // Returns all categories, each pair
 | ||||
|     // consists of ID of parent item and pointer to category.
 | ||||
|     QHash<int, FeedsModelCategory*> getAllCategories(); | ||||
|     QHash<int, FeedsModelCategory*> allCategories(); | ||||
| 
 | ||||
|     // Returns categories from the subtree with given root node, each pair
 | ||||
|     // consists of ID of parent item and pointer to category.
 | ||||
|     QHash<int, FeedsModelCategory*> getCategories(FeedsModelRootItem *root); | ||||
|     QHash<int, FeedsModelCategory*> categoriesForItem(FeedsModelRootItem *root); | ||||
| 
 | ||||
|     // Returns list of all feeds contained in the model.
 | ||||
|     QList<FeedsModelFeed*> getAllFeeds(); | ||||
|     QList<FeedsModelFeed*> allFeeds(); | ||||
| 
 | ||||
|     // Get list of feeds from tree with particular item
 | ||||
|     // as root. If root itself is a feed, then it is returned.
 | ||||
|     QList<FeedsModelFeed*> getFeeds(FeedsModelRootItem *root); | ||||
|     QList<FeedsModelFeed*> feedsForItem(FeedsModelRootItem *root); | ||||
| 
 | ||||
|     // Returns list of feeds which belong to given indexes.
 | ||||
|     // NOTE: If index is "category", then all child feeds are contained in the
 | ||||
|  | @ -84,6 +90,7 @@ class FeedsModel : public QAbstractItemModel { | |||
| 
 | ||||
|     // Signals that SOME data of this model need
 | ||||
|     // to be reloaded by ALL attached views.
 | ||||
|     // NOTE: This reloads all parent valid indexes too.
 | ||||
|     void reloadChangedLayout(QModelIndexList list); | ||||
| 
 | ||||
|   protected: | ||||
|  |  | |||
|  | @ -136,10 +136,6 @@ void FeedMessageViewer::createConnections() { | |||
|           m_messagesBrowser, SLOT(clear())); | ||||
|   connect(m_messagesView, SIGNAL(currentMessageChanged(Message)), | ||||
|           m_messagesBrowser, SLOT(navigateToMessage(Message))); | ||||
| 
 | ||||
|   connect(m_messagesView, SIGNAL(openMessagesInNewspaperViewRequested(QList<Message>)), | ||||
|           m_messagesBrowser, SLOT(navigateToMessages(QList<Message>))); | ||||
| 
 | ||||
|   connect(m_messagesView, SIGNAL(openMessageNewTabRequested(Message)), | ||||
|           FormMain::getInstance()->m_ui->m_tabWidget, | ||||
|           SLOT(addBrowserWithMessage(Message))); | ||||
|  | @ -152,6 +148,9 @@ void FeedMessageViewer::createConnections() { | |||
|           m_feedsView, SLOT(updateCountsOfSelectedFeeds())); | ||||
|   connect(m_feedsView, SIGNAL(feedsNeedToBeReloaded(int)), | ||||
|           m_messagesView, SLOT(reloadSelections(int))); | ||||
|   connect(m_feedsView, SIGNAL(newspaperModeRequested(QList<Message>)), | ||||
|           FormMain::getInstance()->m_ui->m_tabWidget, | ||||
|           SLOT(addBrowserWithMessages(QList<Message>))); | ||||
| 
 | ||||
|   // Downloader connections.
 | ||||
|   connect(m_feedDownloaderThread, SIGNAL(finished()), | ||||
|  | @ -194,6 +193,8 @@ void FeedMessageViewer::createConnections() { | |||
|           SIGNAL(triggered()), m_feedsView, SLOT(addNewCategory())); | ||||
|   connect(FormMain::getInstance()->m_ui->m_actionEditSelectedFeedCategory, | ||||
|           SIGNAL(triggered()), m_feedsView, SLOT(editSelectedItem())); | ||||
|   connect(FormMain::getInstance()->m_ui->m_actionViewSelectedItemsNewspaperMode, | ||||
|           SIGNAL(triggered()), m_feedsView, SLOT(openSelectedFeedsInNewspaperMode())); | ||||
| } | ||||
| 
 | ||||
| void FeedMessageViewer::initialize() { | ||||
|  |  | |||
|  | @ -3,6 +3,8 @@ | |||
| 
 | ||||
| #include "gui/tabcontent.h" | ||||
| 
 | ||||
| #include "core/messagesmodel.h" | ||||
| 
 | ||||
| 
 | ||||
| class WebBrowser; | ||||
| class FeedsView; | ||||
|  | @ -33,10 +35,12 @@ class FeedMessageViewer : public TabContent { | |||
|     void quitDownloader(); | ||||
| 
 | ||||
|   public slots: | ||||
|     // Feed updates.
 | ||||
|     void updateSelectedFeeds(); | ||||
|     void updateAllFeeds(); | ||||
| 
 | ||||
|   protected slots: | ||||
|   protected slots:    | ||||
|     // Reacts on feed updates.
 | ||||
|     void onFeedUpdatesProgress(FeedsModelFeed *feed, int current, int total); | ||||
|     void onFeedUpdatesFinished(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -53,7 +53,7 @@ QList<FeedsModelFeed *> FeedsView::selectedFeeds() const { | |||
| } | ||||
| 
 | ||||
| QList<FeedsModelFeed *> FeedsView::allFeeds() const { | ||||
|   return m_sourceModel->getAllFeeds(); | ||||
|   return m_sourceModel->allFeeds(); | ||||
| } | ||||
| 
 | ||||
| FeedsModelCategory *FeedsView::isCurrentIndexCategory() const { | ||||
|  | @ -133,6 +133,17 @@ void FeedsView::markAllFeedsRead() { | |||
|   markAllFeedsReadStatus(1); | ||||
| } | ||||
| 
 | ||||
| void FeedsView::openSelectedFeedsInNewspaperMode() { | ||||
|   // TODO: oznacit vybrane feedy jako prectene zde
 | ||||
|   // protoze je uzivatel otvira v newspaperu -> jsou prectene automaticky
 | ||||
| 
 | ||||
|   QList<Message> messages = m_sourceModel->messagesForFeeds(selectedFeeds()); | ||||
| 
 | ||||
|   if (!messages.isEmpty()) { | ||||
|     emit newspaperModeRequested(messages); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void FeedsView::updateCountsOfSelectedFeeds(bool update_total_too) { | ||||
|   foreach (FeedsModelFeed *feed, selectedFeeds()) { | ||||
|     feed->updateCounts(update_total_too); | ||||
|  |  | |||
|  | @ -3,6 +3,8 @@ | |||
| 
 | ||||
| #include <QTreeView> | ||||
| 
 | ||||
| #include "core/messagesmodel.h" | ||||
| 
 | ||||
| 
 | ||||
| // TODO: http://soundguyrob.files.wordpress.com/2011/03/screen-shot-2011-03-01-at-7-45-23-pm.jpg
 | ||||
| // přepsat počet nepřečtených zpráv podle screenshotu (tedy smazat asi sloupec "unread")
 | ||||
|  | @ -54,6 +56,9 @@ class FeedsView : public QTreeView { | |||
|     void markAllFeedsReadStatus(int read); | ||||
|     void markAllFeedsRead(); | ||||
| 
 | ||||
|     // Newspaper accessors.
 | ||||
|     void openSelectedFeedsInNewspaperMode(); | ||||
| 
 | ||||
|     // Feed clearers.
 | ||||
|     void setSelectedFeedsClearStatus(int clear); | ||||
|     void clearSelectedFeeds(); | ||||
|  | @ -68,6 +73,7 @@ class FeedsView : public QTreeView { | |||
|     // Reloads counts for all feeds.
 | ||||
|     void updateCountsOfAllFeeds(bool update_total_too = true); | ||||
| 
 | ||||
|     // Reloads counts for particular feed.
 | ||||
|     void updateCountsOfParticularFeed(FeedsModelFeed *feed, bool update_total_too = true); | ||||
| 
 | ||||
|   protected: | ||||
|  | @ -92,6 +98,9 @@ class FeedsView : public QTreeView { | |||
|     // Emitted if user selects new feeds.
 | ||||
|     void feedsSelected(const QList<int> &feed_ids); | ||||
| 
 | ||||
|     // Requests opening of given messages in newspaper mode.
 | ||||
|     void newspaperModeRequested(const QList<Message> &messages); | ||||
| 
 | ||||
|   private: | ||||
|     QMenu *m_contextMenuCategoriesFeeds; | ||||
|     QMenu *m_contextMenuEmptySpace; | ||||
|  |  | |||
|  | @ -15,7 +15,7 @@ | |||
| FormCategoryDetails::FormCategoryDetails(FeedsModel *model, QWidget *parent) | ||||
|   : QDialog(parent), m_editableCategory(NULL) { | ||||
|   initialize(); | ||||
|   loadCategories(model->getAllCategories().values(), | ||||
|   loadCategories(model->allCategories().values(), | ||||
|                  model->rootItem()); | ||||
| 
 | ||||
|   setWindowTitle(tr("Add new category")); | ||||
|  |  | |||
|  | @ -17,7 +17,7 @@ class FeedsModelRootItem; | |||
| class FormCategoryDetailsAnswer { | ||||
|   public: | ||||
|     int m_dialogCode; | ||||
|     FeedsModelCategory *m_outputItem; | ||||
|     FeedsModelCategory *m_outputCategory; | ||||
|     FeedsModelRootItem *m_outputParentItem; | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -233,6 +233,7 @@ void FormMain::setupIcons() { | |||
|   m_ui->m_actionOpenSelectedSourceArticlesInternally->setIcon(IconThemeFactory::getInstance()->fromTheme("document-open")); | ||||
|   m_ui->m_actionOpenSelectedSourceArticlesExternally->setIcon(IconThemeFactory::getInstance()->fromTheme("document-open")); | ||||
|   m_ui->m_actionOpenSelectedMessagesInternally->setIcon(IconThemeFactory::getInstance()->fromTheme("document-open")); | ||||
|   m_ui->m_actionViewSelectedItemsNewspaperMode->setIcon(IconThemeFactory::getInstance()->fromTheme("document-multiple")); | ||||
| 
 | ||||
|   // Setup icons for underlying components: opened web browsers...
 | ||||
|   foreach (WebBrowser *browser, WebBrowser::runningWebBrowsers()) { | ||||
|  |  | |||
|  | @ -15,16 +15,7 @@ | |||
|   </property> | ||||
|   <widget class="QWidget" name="centralwidget"> | ||||
|    <layout class="QHBoxLayout" name="horizontalLayout"> | ||||
|     <property name="leftMargin"> | ||||
|      <number>0</number> | ||||
|     </property> | ||||
|     <property name="topMargin"> | ||||
|      <number>0</number> | ||||
|     </property> | ||||
|     <property name="rightMargin"> | ||||
|      <number>0</number> | ||||
|     </property> | ||||
|     <property name="bottomMargin"> | ||||
|     <property name="margin"> | ||||
|      <number>0</number> | ||||
|     </property> | ||||
|     <item> | ||||
|  | @ -48,7 +39,7 @@ | |||
|      <x>0</x> | ||||
|      <y>0</y> | ||||
|      <width>979</width> | ||||
|      <height>21</height> | ||||
|      <height>20</height> | ||||
|     </rect> | ||||
|    </property> | ||||
|    <widget class="QMenu" name="m_menuFile"> | ||||
|  | @ -102,6 +93,7 @@ | |||
|     <addaction name="m_actionEditSelectedFeedCategory"/> | ||||
|     <addaction name="m_actionDeleteSelectedFeedsCategories"/> | ||||
|     <addaction name="separator"/> | ||||
|     <addaction name="m_actionViewSelectedItemsNewspaperMode"/> | ||||
|     <addaction name="m_actionMarkAllFeedsRead"/> | ||||
|     <addaction name="m_actionMarkFeedsAsRead"/> | ||||
|     <addaction name="m_actionMarkFeedsAsUnread"/> | ||||
|  | @ -392,6 +384,14 @@ | |||
|     <string>Mark all messages in all feeds read. This does not take message filters into account.</string> | ||||
|    </property> | ||||
|   </action> | ||||
|   <action name="m_actionViewSelectedItemsNewspaperMode"> | ||||
|    <property name="text"> | ||||
|     <string>View selected items in newspaper mode</string> | ||||
|    </property> | ||||
|    <property name="toolTip"> | ||||
|     <string>Displays all messages from selected feeds/categories in a new "newspaper mode" tab.</string> | ||||
|    </property> | ||||
|   </action> | ||||
|  </widget> | ||||
|  <customwidgets> | ||||
|   <customwidget> | ||||
|  |  | |||
|  | @ -181,6 +181,12 @@ int TabWidget::addBrowserWithMessage(const Message &message)  { | |||
|   return new_index; | ||||
| } | ||||
| 
 | ||||
| int TabWidget::addBrowserWithMessages(const QList<Message> &messages) { | ||||
|   int new_index = addBrowser(false, true); | ||||
|   static_cast<WebBrowser*>(widget(new_index))->navigateToMessages(messages); | ||||
|   return new_index; | ||||
| } | ||||
| 
 | ||||
| int TabWidget::addEmptyBrowser() { | ||||
|   return addBrowser(false, true); | ||||
| } | ||||
|  |  | |||
|  | @ -77,7 +77,9 @@ class TabWidget : public QTabWidget { | |||
|     // Closes all "closable" tabs except the active tab.
 | ||||
|     void closeAllTabsExceptCurrent(); | ||||
| 
 | ||||
|     // Open single or multiple (newspaper mode) messages in new tab.
 | ||||
|     int addBrowserWithMessage(const Message &message); | ||||
|     int addBrowserWithMessages(const QList<Message> &messages); | ||||
| 
 | ||||
|     // Adds new WebBrowser tab to global TabWidget.
 | ||||
|     int addEmptyBrowser(); | ||||
|  |  | |||
|  | @ -174,7 +174,7 @@ void WebBrowser::navigateToMessage(const Message &message) { | |||
|                                                                               message.m_contents, | ||||
|                                                                               message.m_created.toString(Qt::DefaultLocaleShortDate)); | ||||
| 
 | ||||
|   QString layout_wrapper = SkinFactory::getInstance()->getCurrentMarkupLayout().arg(tr("Newspaper view"), | ||||
|   QString layout_wrapper = SkinFactory::getInstance()->getCurrentMarkupLayout().arg(message.m_title, | ||||
|                                                                                     message_layout); | ||||
| 
 | ||||
|   m_webView->setHtml(layout_wrapper); | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue