diff --git a/localization/rssguard_cs.ts b/localization/rssguard_cs.ts index e06cfde02..170450a47 100644 --- a/localization/rssguard_cs.ts +++ b/localization/rssguard_cs.ts @@ -108,6 +108,37 @@ <body>RSS Guard je (velmi) jednoduchá čtečka kanálů.<br><br>Tento software je šířen pod licencí GNU General Public License, verze 3.<br><br>Kontakty:<ul><li><a href="mailto://%1">%1</a> ~email</li><li><a href="%2">%2</a> ~webová stránka</li></ul>Zdrojové kódy aplikace lze získat z jejího web.u<br><br><br>Copyright (C) 2011-%3 %4</body> + + FormCategoryDetails + + Dialog + + + + Parent category + + + + Title + Nadpis + + + Title of the category + + + + Description + + + + Icon + + + + Add new category + + + FormMain @@ -170,10 +201,6 @@ Close current &tab Zavřít aktivní &panel - - Fee&ds - &Kanály - &Messages &Zprávy @@ -254,18 +281,6 @@ Close current web browser tab. Zavřít aktuální panel webového prohlížeče.. - - Update &all feeds - Aktualizov&at vše - - - Update &selected feeds - Aktualizovat vybrané kanál&y - - - &Delete selected feed(s)/category(ies) - Smazat vybrané kanály/kategor&ie - Delete selected messages. Smazat vybrané zprávy. @@ -314,18 +329,10 @@ &Edit selected feed/category Uprav&it vybraní kanál/kategorii - - Mark &selected feeds read - Označit vybrané kanály jako &přečtené - Marks all messages (without message filters) from selected feeds as read. Označí všechny zprávy z vybraných kanálů jako přečtené, neuvažuje filtry zpráv. - - Mark selected feeds unread - Označit vybrané kanály jako nepřečtené - Marks all messages (without message filters) from selected feeds as unread. Označí všechny zprávy z vybraných kanálů jako nepřečtené, neuvažuje filtry zpráv. @@ -334,10 +341,6 @@ &Clear selected messages &Smazat vybrané zprávy - - Clear selected feeds - Promazat vybrané kanály - Removes all messages from selected feeds. Smaže všechny zprávy z vybraných kanálů. @@ -350,6 +353,42 @@ No actions are available right now. Žádná akce není právě dostupná. + + Fee&ds && categories + + + + Update &all items + + + + Update &selected items + + + + &Delete selected feeds/categories + + + + Mark &selected items read + + + + Mark selected items unread + + + + Clear selected items + + + + Mark all &items read + + + + Mark all messages in all feeds read. This does not take message filters into account. + + FormSettings diff --git a/localization/rssguard_en.ts b/localization/rssguard_en.ts index 89f079c15..fa894975a 100644 --- a/localization/rssguard_en.ts +++ b/localization/rssguard_en.ts @@ -108,6 +108,37 @@ + + FormCategoryDetails + + Dialog + + + + Parent category + + + + Title + + + + Title of the category + + + + Description + + + + Icon + + + + Add new category + + + FormMain @@ -170,10 +201,6 @@ Close current &tab - - Fee&ds - - &Messages @@ -254,18 +281,6 @@ Close current web browser tab. - - Update &all feeds - - - - Update &selected feeds - - - - &Delete selected feed(s)/category(ies) - - Delete selected messages. @@ -314,18 +329,10 @@ &Edit selected feed/category - - Mark &selected feeds read - - Marks all messages (without message filters) from selected feeds as read. - - Mark selected feeds unread - - Marks all messages (without message filters) from selected feeds as unread. @@ -334,10 +341,6 @@ &Clear selected messages - - Clear selected feeds - - Removes all messages from selected feeds. @@ -350,6 +353,42 @@ No actions are available right now. + + Fee&ds && categories + + + + Update &all items + + + + Update &selected items + + + + &Delete selected feeds/categories + + + + Mark &selected items read + + + + Mark selected items unread + + + + Clear selected items + + + + Mark all &items read + + + + Mark all messages in all feeds read. This does not take message filters into account. + + FormSettings diff --git a/localization/rssguard_nl.ts b/localization/rssguard_nl.ts index 750eff89c..e203de85e 100644 --- a/localization/rssguard_nl.ts +++ b/localization/rssguard_nl.ts @@ -108,6 +108,37 @@ <body>RSS Guard is een (zeer) makelijk om te gebruiken feed lezer.<br><br>Dit programma is beschikbaar onder te termenvan de GNU General Public License versie 3.<br><br>Contacts:<ul><li><a href="mailto://%1">%1</a> ~email</li><li><a ref="%2">%2</a> ~website </li><ul>U kunt de broncode voor RSS Guard verkrijgen op de website.<br><br><br>Auteursrecht(C)2011-%3 %4</body> + + FormCategoryDetails + + Dialog + + + + Parent category + + + + Title + Titel + + + Title of the category + + + + Description + + + + Icon + + + + Add new category + + + FormMain @@ -170,10 +201,6 @@ Close current &tab Sluit huidig &tabblad - - Fee&ds - - &Messages &Berichten @@ -254,18 +281,6 @@ Close current web browser tab. Sluit huidige webbrowser tabblad. - - Update &all feeds - Update a&lle feeds - - - Update &selected feeds - Update ge&selecteerde feeds - - - &Delete selected feed(s)/category(ies) - &Verwijder geselecteerde feed(s)/categorie(ën) - Delete selected messages. Verwijder geselecteerde berichten. @@ -314,18 +329,10 @@ &Edit selected feed/category - - Mark &selected feeds read - - Marks all messages (without message filters) from selected feeds as read. - - Mark selected feeds unread - - Marks all messages (without message filters) from selected feeds as unread. @@ -334,10 +341,6 @@ &Clear selected messages - - Clear selected feeds - - Removes all messages from selected feeds. @@ -350,6 +353,42 @@ No actions are available right now. + + Fee&ds && categories + + + + Update &all items + + + + Update &selected items + + + + &Delete selected feeds/categories + + + + Mark &selected items read + + + + Mark selected items unread + + + + Clear selected items + + + + Mark all &items read + + + + Mark all messages in all feeds read. This does not take message filters into account. + + FormSettings diff --git a/src/core/databasefactory.cpp b/src/core/databasefactory.cpp index b50683002..60a56b5cf 100644 --- a/src/core/databasefactory.cpp +++ b/src/core/databasefactory.cpp @@ -76,6 +76,7 @@ QSqlDatabase DatabaseFactory::initialize(const QString &connection_name) { else { QSqlQuery query_db(database); + query_db.setForwardOnly(true); query_db.exec("PRAGMA encoding = \"UTF-8\""); query_db.exec("PRAGMA synchronous = OFF"); query_db.exec("PRAGMA journal_mode = MEMORY"); diff --git a/src/core/defs.h.in b/src/core/defs.h.in index 8c2b9f5a6..be6408fa3 100755 --- a/src/core/defs.h.in +++ b/src/core/defs.h.in @@ -31,7 +31,9 @@ #define TRAY_ICON_BUBBLE_TIMEOUT 15000 #define KEY_MESSAGES_VIEW "messages_view_column_" #define CLOSE_LOCK_TIMEOUT 3000 +#define DOWNLOAD_TIMEOUT 5000 #define MESSAGES_VIEW_DEFAULT_COL 170 +#define ELLIPSIS_LENGTH 3 #define APP_DB_INIT_FILE "db_init.sql" #define APP_DB_INIT_SPLIT "-- !\n" diff --git a/src/core/feedsmodel.cpp b/src/core/feedsmodel.cpp index b0d076be8..af7ce7ee8 100644 --- a/src/core/feedsmodel.cpp +++ b/src/core/feedsmodel.cpp @@ -11,7 +11,6 @@ #include #include #include -#include #include @@ -23,9 +22,7 @@ FeedsModel::FeedsModel(QObject *parent) : QAbstractItemModel(parent) { m_rootItem->setId(NO_PARENT_CATEGORY); m_rootItem->setTitle(tr("root")); m_rootItem->setIcon(IconThemeFactory::getInstance()->fromTheme("folder-red")); - m_countsIcon = IconThemeFactory::getInstance()->fromTheme("mail-mark-unread"); - m_headerData << tr("Title"); m_tooltipData << tr("Titles of feeds/categories.") << tr("Counts of unread/all meesages."); @@ -204,50 +201,6 @@ QModelIndex FeedsModel::indexForItem(FeedsModelRootItem *item) const { return QModelIndex(); } -/* -QModelIndex FeedsModel::indexForItem(FeedsModelRootItem *item) const { - if (item->kind() == FeedsModelRootItem::RootItem) { - // Root item lies on invalid index. - return QModelIndex(); - } - - // TODO: Rewrite for better performance. - - QModelIndexList parents; - - // Start with invalid index (so that we start from the root - // item). - parents << QModelIndex(); - - while (!parents.isEmpty()) { - QModelIndex active_index = parents.takeFirst(); - int row_count = rowCount(active_index); - - // Iterate all childs of this parent. - for (int i = 0; i < row_count; i++) { - QModelIndex candidate_index = index(i, 0, active_index); - - // This index could be our target item. - FeedsModelRootItem *target_item = itemForIndex(candidate_index); - - if (target_item != NULL) { - if (FeedsModelRootItem::isEqual(target_item, item)) { - // We found our target index, it's good. - return candidate_index; - } - else if (hasChildren(candidate_index)) { - // This is not our target index but it has children, - // scan them too. - parents << candidate_index; - } - } - } - - } - - return QModelIndex(); -}*/ - void FeedsModel::reloadChangedLayout(QModelIndexList list) { while (!list.isEmpty()) { QModelIndex ix = list.takeLast(); @@ -293,9 +246,11 @@ void FeedsModel::loadFromDatabase() { FeedAssignment feeds; // Obtain data for categories from the database. - QSqlQuery query_categories("SELECT * FROM Categories;", database); + QSqlQuery query_categories(database); + query_categories.setForwardOnly(true); - if (query_categories.lastError().isValid()) { + if (!query_categories.exec("SELECT * FROM Categories;") || + query_categories.lastError().isValid()) { qFatal("Query for obtaining categories failed."); } @@ -322,9 +277,11 @@ void FeedsModel::loadFromDatabase() { } // All categories are now loaded. - QSqlQuery query_feeds("SELECT * FROM Feeds;", database); + QSqlQuery query_feeds(database); + query_feeds.setForwardOnly(true); - if (query_feeds.lastError().isValid()) { + if (!query_feeds.exec("SELECT * FROM Feeds;") || + query_feeds.lastError().isValid()) { qFatal("Query for obtaining feeds failed."); } @@ -403,6 +360,8 @@ bool FeedsModel::markFeedsRead(const QList &feeds, } QSqlQuery query_read_msg(db_handle); + query_read_msg.setForwardOnly(true); + if (!query_read_msg.prepare(QString("UPDATE messages SET read = :read " "WHERE feed IN (%1) AND deleted = 0").arg(textualFeedIds(feeds).join(", ")))) { qWarning("Query preparation failed for feeds read change."); @@ -437,6 +396,8 @@ bool FeedsModel::markFeedsDeleted(const QList &feeds, } QSqlQuery query_delete_msg(db_handle); + query_delete_msg.setForwardOnly(true); + if (!query_delete_msg.prepare(QString("UPDATE messages SET deleted = :deleted " "WHERE feed IN (%1) AND deleted = 0").arg(textualFeedIds(feeds).join(", ")))) { qWarning("Query preparation failed for feeds clearing."); @@ -498,13 +459,13 @@ QList FeedsModel::getFeeds(FeedsModelRootItem *root) { } else { // Root itself is a CATEGORY or ROOT item. - QQueue traversable_items; + QList traversable_items; - traversable_items.enqueue(root); + traversable_items.append(root); // Iterate all nested categories. while (!traversable_items.isEmpty()) { - FeedsModelRootItem *active_category = traversable_items.dequeue(); + FeedsModelRootItem *active_category = traversable_items.takeFirst(); foreach (FeedsModelRootItem *child, active_category->childItems()) { if (child->kind() == FeedsModelRootItem::Feed) { @@ -513,7 +474,7 @@ QList FeedsModel::getFeeds(FeedsModelRootItem *root) { } else if (child->kind() == FeedsModelRootItem::Category) { // This child is category, add its child feeds too. - traversable_items.enqueue(static_cast(child)); + traversable_items.append(static_cast(child)); } } } diff --git a/src/core/feedsmodelcategory.cpp b/src/core/feedsmodelcategory.cpp index 638b6b653..8f06de9a5 100755 --- a/src/core/feedsmodelcategory.cpp +++ b/src/core/feedsmodelcategory.cpp @@ -3,8 +3,6 @@ #include "core/feedsmodelstandardcategory.h" #include "core/feedsmodelstandardfeed.h" -#include - FeedsModelCategory::FeedsModelCategory(FeedsModelRootItem *parent_item) : FeedsModelRootItem(parent_item) { diff --git a/src/core/feedsmodelfeed.cpp b/src/core/feedsmodelfeed.cpp index a62bf74c1..190948679 100755 --- a/src/core/feedsmodelfeed.cpp +++ b/src/core/feedsmodelfeed.cpp @@ -68,6 +68,7 @@ QString FeedsModelFeed::typeToString(FeedsModelFeed::Type type) { void FeedsModelFeed::updateCounts(bool including_total_count) { QSqlDatabase database = DatabaseFactory::getInstance()->addConnection("FeedsModelFeed"); QSqlQuery query_all(database); + query_all.setForwardOnly(true); if (including_total_count) { if (query_all.exec(QString("SELECT count() FROM messages " diff --git a/src/core/feedsmodelstandardfeed.cpp b/src/core/feedsmodelstandardfeed.cpp index a2add5354..3d280a7f8 100755 --- a/src/core/feedsmodelstandardfeed.cpp +++ b/src/core/feedsmodelstandardfeed.cpp @@ -149,7 +149,7 @@ void FeedsModelStandardFeed::update() { QByteArray feed_contents; int download_timeout = Settings::getInstance()->value(APP_CFG_FEEDS, "download_timeout", - 5000).toInt(); + DOWNLOAD_TIMEOUT).toInt(); // TODO: Provide download time-measures debugging // outputs here. @@ -211,9 +211,11 @@ void FeedsModelStandardFeed::updateMessages(const QList &messages) { QSqlQuery query_select(database); QSqlQuery query_insert(database); + query_select.setForwardOnly(true); query_select.prepare("SELECT id, feed, date_created FROM Messages " "WHERE feed = :feed AND title = :title AND url = :url;"); + query_insert.setForwardOnly(true); query_insert.prepare("INSERT INTO Messages " "(feed, title, url, author, date_created, contents) " "VALUES (:feed, :title, :url, :author, :date_created, :contents);"); @@ -257,6 +259,11 @@ void FeedsModelStandardFeed::updateMessages(const QList &messages) { // Message is already persistently stored. // TODO: Update message if it got updated in the // online feed. + if (message.m_createdFromFeed) { + // Creation data of the message was obtained from + // feed itself. + + } } } diff --git a/src/core/messagesmodel.cpp b/src/core/messagesmodel.cpp index 7727a190f..836617070 100644 --- a/src/core/messagesmodel.cpp +++ b/src/core/messagesmodel.cpp @@ -233,9 +233,11 @@ bool MessagesModel::setMessageRead(int row_index, int read) { } int message_id; - QSqlQuery query_delete_msg(db_handle); - if (!query_delete_msg.prepare("UPDATE messages SET read = :read " - "WHERE id = :id")) { + QSqlQuery query_read_msg(db_handle); + query_read_msg.setForwardOnly(true); + + if (!query_read_msg.prepare("UPDATE messages SET read = :read " + "WHERE id = :id")) { qWarning("Query preparation failed for message read change."); db_handle.rollback(); @@ -244,9 +246,9 @@ bool MessagesModel::setMessageRead(int row_index, int read) { // Rewrite the actual data in the database itself. message_id = messageId(row_index); - query_delete_msg.bindValue(":id", message_id); - query_delete_msg.bindValue(":read", read); - query_delete_msg.exec(); + query_read_msg.bindValue(":id", message_id); + query_read_msg.bindValue(":read", read); + query_read_msg.exec(); // Commit changes. if (db_handle.commit()) { @@ -287,9 +289,11 @@ bool MessagesModel::switchMessageImportance(int row_index) { } int message_id; - QSqlQuery query_delete_msg(db_handle); - if (!query_delete_msg.prepare("UPDATE messages SET important = :important " - "WHERE id = :id")) { + QSqlQuery query_importance_msg(db_handle); + query_importance_msg.setForwardOnly(true); + + if (!query_importance_msg.prepare("UPDATE messages SET important = :important " + "WHERE id = :id")) { qWarning("Query preparation failed for message importance switch."); db_handle.rollback(); @@ -297,10 +301,10 @@ bool MessagesModel::switchMessageImportance(int row_index) { } message_id = messageId(row_index); - query_delete_msg.bindValue(":id", message_id); - query_delete_msg.bindValue(":important", - current_importance == 1 ? 0 : 1); - query_delete_msg.exec(); + query_importance_msg.bindValue(":id", message_id); + query_importance_msg.bindValue(":important", + current_importance == 1 ? 0 : 1); + query_importance_msg.exec(); // Commit changes. if (db_handle.commit()) { @@ -324,9 +328,11 @@ bool MessagesModel::switchBatchMessageImportance(const QModelIndexList &messages } int message_id, importance; - QSqlQuery query_delete_msg(db_handle); - if (!query_delete_msg.prepare("UPDATE messages SET important = :important " - "WHERE id = :id")) { + QSqlQuery query_importance_msg(db_handle); + query_importance_msg.setForwardOnly(true); + + if (!query_importance_msg.prepare("UPDATE messages SET important = :important " + "WHERE id = :id")) { qWarning("Query preparation failed for message importance switch."); db_handle.rollback(); @@ -337,10 +343,10 @@ bool MessagesModel::switchBatchMessageImportance(const QModelIndexList &messages message_id = messageId(message.row()); importance = data(message.row(), MSG_DB_IMPORTANT_INDEX, Qt::EditRole).toInt(); - query_delete_msg.bindValue(":id", message_id); - query_delete_msg.bindValue(":important", - importance == 1 ? 0 : 1); - query_delete_msg.exec(); + query_importance_msg.bindValue(":id", message_id); + query_importance_msg.bindValue(":important", + importance == 1 ? 0 : 1); + query_importance_msg.exec(); } // Commit changes. @@ -365,6 +371,8 @@ bool MessagesModel::setBatchMessagesDeleted(const QModelIndexList &messages, int int message_id; QSqlQuery query_delete_msg(db_handle); + query_delete_msg.setForwardOnly(true); + if (!query_delete_msg.prepare("UPDATE messages SET deleted = :deleted " "WHERE id = :id")) { qWarning("Query preparation failed for message deletion."); @@ -404,8 +412,10 @@ bool MessagesModel::setBatchMessagesRead(const QModelIndexList &messages, int re int message_id; QSqlQuery query_read_msg(db_handle); + query_read_msg.setForwardOnly(true); + if (!query_read_msg.prepare("UPDATE messages SET read = :read " - "WHERE id = :id")) { + "WHERE id = :id")) { qWarning("Query preparation failed for message read change."); db_handle.rollback(); diff --git a/src/core/networkfactory.cpp b/src/core/networkfactory.cpp index 4fe741792..e4922e150 100644 --- a/src/core/networkfactory.cpp +++ b/src/core/networkfactory.cpp @@ -59,10 +59,12 @@ QNetworkReply::NetworkError NetworkFactory::downloadFile(const QString &url, } // In this phase, some part of downloading process is completed. + QUrl redirection_url = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); - if (reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl().isValid()) { + if (redirection_url.isValid()) { // Communication indicates that HTTP redirection is needed. - request.setUrl(reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl()); + // Setup redirection URL and download again. + request.setUrl(redirection_url); } else { // No redirection is indicated. Final file is obtained diff --git a/src/core/textfactory.cpp b/src/core/textfactory.cpp index f5b836319..f0d438c96 100644 --- a/src/core/textfactory.cpp +++ b/src/core/textfactory.cpp @@ -40,7 +40,7 @@ QDateTime TextFactory::parseDateTime(const QString &date_time) { QString TextFactory::shorten(const QString &input, int text_length_limit) { if (input.size() > text_length_limit) { - return input.left(text_length_limit - 3) + QString(3, '.'); + return input.left(text_length_limit - ELLIPSIS_LENGTH) + QString(ELLIPSIS_LENGTH, '.'); } else { return input; diff --git a/src/gui/messagesview.cpp b/src/gui/messagesview.cpp index 644bbb19f..1759941aa 100644 --- a/src/gui/messagesview.cpp +++ b/src/gui/messagesview.cpp @@ -248,8 +248,16 @@ void MessagesView::openSelectedSourceArticlesExternally() { void MessagesView::openSelectedSourceMessagesInternally() { foreach (const QModelIndex &index, selectionModel()->selectedRows()) { - // TODO: What to do with messages w/o link? - emit openLinkMessageNewTabRequested(m_sourceModel->messageAt(m_proxyModel->mapToSource(index).row()).m_url); + Message message = m_sourceModel->messageAt(m_proxyModel->mapToSource(index).row()); + + if (message.m_url.isEmpty()) { + QMessageBox::warning(this, + tr("Meesage without URL"), + tr("Message '%s' does not contain URL.").arg(message.m_title)); + } + else { + emit openLinkMessageNewTabRequested(message.m_url); + } } }