Some database optimizations.

This commit is contained in:
Martin Rotter 2013-12-31 17:33:42 +01:00
parent 7930580a6f
commit b79d6b2ccd
13 changed files with 275 additions and 168 deletions

View File

@ -108,6 +108,37 @@
<translation>&lt;body&gt;RSS Guard je (velmi) jednoduchá čtečka kanálů.&lt;br&gt;&lt;br&gt;Tento software je šířen pod licencí GNU General Public License, verze 3.&lt;br&gt;&lt;br&gt;Kontakty:&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;mailto://%1&quot;&gt;%1&lt;/a&gt; ~email&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;%2&quot;&gt;%2&lt;/a&gt; ~webová stránka&lt;/li&gt;&lt;/ul&gt;Zdrojové kódy aplikace lze získat z jejího web.u&lt;br&gt;&lt;br&gt;&lt;br&gt;Copyright (C) 2011-%3 %4&lt;/body&gt;</translation>
</message>
</context>
<context>
<name>FormCategoryDetails</name>
<message>
<source>Dialog</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Parent category</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Title</source>
<translation type="unfinished">Nadpis</translation>
</message>
<message>
<source>Title of the category</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Description</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Icon</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Add new category</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FormMain</name>
<message>
@ -170,10 +201,6 @@
<source>Close current &amp;tab</source>
<translation>Zavřít aktivní &amp;panel</translation>
</message>
<message>
<source>Fee&amp;ds</source>
<translation>&amp;Kanály</translation>
</message>
<message>
<source>&amp;Messages</source>
<translation>&amp;Zprávy</translation>
@ -254,18 +281,6 @@
<source>Close current web browser tab.</source>
<translation>Zavřít aktuální panel webového prohlížeče..</translation>
</message>
<message>
<source>Update &amp;all feeds</source>
<translation>Aktualizov&amp;at vše</translation>
</message>
<message>
<source>Update &amp;selected feeds</source>
<translation>Aktualizovat vybrané kanál&amp;y</translation>
</message>
<message>
<source>&amp;Delete selected feed(s)/category(ies)</source>
<translation>Smazat vybrané kanály/kategor&amp;ie</translation>
</message>
<message>
<source>Delete selected messages.</source>
<translation>Smazat vybrané zprávy.</translation>
@ -314,18 +329,10 @@
<source>&amp;Edit selected feed/category</source>
<translation>Uprav&amp;it vybraní kanál/kategorii</translation>
</message>
<message>
<source>Mark &amp;selected feeds read</source>
<translation>Označit vybrané kanály jako &amp;přečtené</translation>
</message>
<message>
<source>Marks all messages (without message filters) from selected feeds as read.</source>
<translation>Označí všechny zprávy z vybraných kanálů jako přečtené, neuvažuje filtry zpráv.</translation>
</message>
<message>
<source>Mark selected feeds unread</source>
<translation>Označit vybrané kanály jako nepřečtené</translation>
</message>
<message>
<source>Marks all messages (without message filters) from selected feeds as unread.</source>
<translation>Označí všechny zprávy z vybraných kanálů jako nepřečtené, neuvažuje filtry zpráv.</translation>
@ -334,10 +341,6 @@
<source>&amp;Clear selected messages</source>
<translation>&amp;Smazat vybrané zprávy</translation>
</message>
<message>
<source>Clear selected feeds</source>
<translation>Promazat vybrané kanály</translation>
</message>
<message>
<source>Removes all messages from selected feeds.</source>
<translation>Smaže všechny zprávy z vybraných kanálů.</translation>
@ -350,6 +353,42 @@
<source>No actions are available right now.</source>
<translation>Žádná akce není právě dostupná.</translation>
</message>
<message>
<source>Fee&amp;ds &amp;&amp; categories</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Update &amp;all items</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Update &amp;selected items</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&amp;Delete selected feeds/categories</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Mark &amp;selected items read</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Mark selected items unread</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Clear selected items</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Mark all &amp;items read</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Mark all messages in all feeds read. This does not take message filters into account.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FormSettings</name>

View File

@ -108,6 +108,37 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FormCategoryDetails</name>
<message>
<source>Dialog</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Parent category</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Title</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Title of the category</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Description</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Icon</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Add new category</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FormMain</name>
<message>
@ -170,10 +201,6 @@
<source>Close current &amp;tab</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Fee&amp;ds</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&amp;Messages</source>
<translation type="unfinished"></translation>
@ -254,18 +281,6 @@
<source>Close current web browser tab.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Update &amp;all feeds</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Update &amp;selected feeds</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&amp;Delete selected feed(s)/category(ies)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Delete selected messages.</source>
<translation type="unfinished"></translation>
@ -314,18 +329,10 @@
<source>&amp;Edit selected feed/category</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Mark &amp;selected feeds read</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Marks all messages (without message filters) from selected feeds as read.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Mark selected feeds unread</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Marks all messages (without message filters) from selected feeds as unread.</source>
<translation type="unfinished"></translation>
@ -334,10 +341,6 @@
<source>&amp;Clear selected messages</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Clear selected feeds</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Removes all messages from selected feeds.</source>
<translation type="unfinished"></translation>
@ -350,6 +353,42 @@
<source>No actions are available right now.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Fee&amp;ds &amp;&amp; categories</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Update &amp;all items</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Update &amp;selected items</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&amp;Delete selected feeds/categories</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Mark &amp;selected items read</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Mark selected items unread</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Clear selected items</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Mark all &amp;items read</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Mark all messages in all feeds read. This does not take message filters into account.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FormSettings</name>

View File

@ -108,6 +108,37 @@
<translation>&lt;body&gt;RSS Guard is een (zeer) makelijk om te gebruiken feed lezer.&lt;br&gt;&lt;br&gt;Dit programma is beschikbaar onder te termenvan de GNU General Public License versie 3.&lt;br&gt;&lt;br&gt;Contacts:&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;mailto://%1&quot;&gt;%1&lt;/a&gt; ~email&lt;/li&gt;&lt;li&gt;&lt;a ref=&quot;%2&quot;&gt;%2&lt;/a&gt; ~website &lt;/li&gt;&lt;ul&gt;U kunt de broncode voor RSS Guard verkrijgen op de website.&lt;br&gt;&lt;br&gt;&lt;br&gt;Auteursrecht(C)2011-%3 %4&lt;/body&gt;</translation>
</message>
</context>
<context>
<name>FormCategoryDetails</name>
<message>
<source>Dialog</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Parent category</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Title</source>
<translation type="unfinished">Titel</translation>
</message>
<message>
<source>Title of the category</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Description</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Icon</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Add new category</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FormMain</name>
<message>
@ -170,10 +201,6 @@
<source>Close current &amp;tab</source>
<translation>Sluit huidig &amp;tabblad</translation>
</message>
<message>
<source>Fee&amp;ds</source>
<translation></translation>
</message>
<message>
<source>&amp;Messages</source>
<translation>&amp;Berichten</translation>
@ -254,18 +281,6 @@
<source>Close current web browser tab.</source>
<translation>Sluit huidige webbrowser tabblad.</translation>
</message>
<message>
<source>Update &amp;all feeds</source>
<translation>Update a&amp;lle feeds</translation>
</message>
<message>
<source>Update &amp;selected feeds</source>
<translation>Update ge&amp;selecteerde feeds</translation>
</message>
<message>
<source>&amp;Delete selected feed(s)/category(ies)</source>
<translation>&amp;Verwijder geselecteerde feed(s)/categorie(ën)</translation>
</message>
<message>
<source>Delete selected messages.</source>
<translation>Verwijder geselecteerde berichten.</translation>
@ -314,18 +329,10 @@
<source>&amp;Edit selected feed/category</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Mark &amp;selected feeds read</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Marks all messages (without message filters) from selected feeds as read.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Mark selected feeds unread</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Marks all messages (without message filters) from selected feeds as unread.</source>
<translation type="unfinished"></translation>
@ -334,10 +341,6 @@
<source>&amp;Clear selected messages</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Clear selected feeds</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Removes all messages from selected feeds.</source>
<translation type="unfinished"></translation>
@ -350,6 +353,42 @@
<source>No actions are available right now.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Fee&amp;ds &amp;&amp; categories</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Update &amp;all items</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Update &amp;selected items</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&amp;Delete selected feeds/categories</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Mark &amp;selected items read</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Mark selected items unread</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Clear selected items</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Mark all &amp;items read</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Mark all messages in all feeds read. This does not take message filters into account.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FormSettings</name>

View File

@ -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");

View File

@ -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"

View File

@ -11,7 +11,6 @@
#include <QSqlQuery>
#include <QSqlRecord>
#include <QPair>
#include <QQueue>
#include <algorithm>
@ -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<FeedsModelFeed*> &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<FeedsModelFeed *> &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<FeedsModelFeed*> FeedsModel::getFeeds(FeedsModelRootItem *root) {
}
else {
// Root itself is a CATEGORY or ROOT item.
QQueue<FeedsModelRootItem*> traversable_items;
QList<FeedsModelRootItem*> 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<FeedsModelFeed*> FeedsModel::getFeeds(FeedsModelRootItem *root) {
}
else if (child->kind() == FeedsModelRootItem::Category) {
// This child is category, add its child feeds too.
traversable_items.enqueue(static_cast<FeedsModelCategory*>(child));
traversable_items.append(static_cast<FeedsModelCategory*>(child));
}
}
}

View File

@ -3,8 +3,6 @@
#include "core/feedsmodelstandardcategory.h"
#include "core/feedsmodelstandardfeed.h"
#include <QQueue>
FeedsModelCategory::FeedsModelCategory(FeedsModelRootItem *parent_item)
: FeedsModelRootItem(parent_item) {

View File

@ -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 "

View File

@ -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<Message> &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<Message> &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.
}
}
}

View File

@ -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();

View File

@ -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

View File

@ -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;

View File

@ -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);
}
}
}