Enhanced message previewer.

This commit is contained in:
Martin Rotter 2016-04-06 09:16:49 +02:00
parent 2956880d10
commit 3bc79c071c
12 changed files with 204 additions and 87 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 B

View File

@ -38,8 +38,9 @@ MessagePreviewer::MessagePreviewer(QWidget *parent) : QWidget(parent),
// User clicked some URL. Open it in external browser or download?
MessageBox box(qApp->mainForm());
box.setText(tr("You clicked link \"%1\". You can download the link contents or open it in external web browser.").arg(url.toString()));
box.setText(tr("You clicked some link. You can download the link contents or open it in external web browser."));
box.setInformativeText(tr("What action do you want to take?"));
box.setDetailedText(url.toString());
QAbstractButton *btn_open = box.addButton(tr("Open in external browser"), QMessageBox::AcceptRole);
QAbstractButton *btn_download = box.addButton(tr("Download"), QMessageBox::RejectRole);
QAbstractButton *btn_cancel = box.addButton(QMessageBox::Cancel);

View File

@ -20,9 +20,6 @@
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
@ -45,16 +42,13 @@
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="margin">
<number>5</number>
</property>
<property name="textInteractionFlags">
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QTextBrowser" name="m_txtMessage">
<widget class="MessageTextBrowser" name="m_txtMessage">
<property name="autoFillBackground">
<bool>true</bool>
</property>
@ -74,6 +68,13 @@
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>MessageTextBrowser</class>
<extends>QTextBrowser</extends>
<header>messagetextbrowser.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,28 @@
#include "gui/messagetextbrowser.h"
#include "miscellaneous/application.h"
#include "miscellaneous/iconfactory.h"
MessageTextBrowser::MessageTextBrowser(QWidget *parent) : QTextBrowser(parent) {
}
MessageTextBrowser::~MessageTextBrowser() {
}
QVariant MessageTextBrowser::loadResource(int type, const QUrl &name) {
Q_UNUSED(name)
switch (type) {
case QTextDocument::ImageResource: {
if (m_imagePlaceholder.isNull()) {
m_imagePlaceholder = qApp->icons()->pixmap(QSL("image-placeholder")).scaledToWidth(20, Qt::FastTransformation);
}
return m_imagePlaceholder;
}
default:
return QVariant();
}
}

View File

@ -0,0 +1,19 @@
#ifndef MESSAGETEXTBROWSER_H
#define MESSAGETEXTBROWSER_H
#include <QTextBrowser>
class MessageTextBrowser : public QTextBrowser {
public:
explicit MessageTextBrowser(QWidget *parent = 0);
virtual ~MessageTextBrowser();
QVariant loadResource(int type, const QUrl &name);
private:
QPixmap m_imagePlaceholder;
};
#endif // MESSAGETEXTBROWSER_H

View File

@ -17,6 +17,11 @@
#include "miscellaneous/databasequeries.h"
#include "services/abstract/category.h"
#include "services/abstract/feed.h"
#include "miscellaneous/application.h"
#include "miscellaneous/iconfactory.h"
#include <QVariant>
#include <QUrl>
#include <QSqlError>
@ -328,8 +333,8 @@ QList<Message> DatabaseQueries::getUndeletedMessagesForAccount(QSqlDatabase db,
QSqlQuery q(db);
q.setForwardOnly(true);
q.prepare("SELECT * "
"FROM Messages "
"WHERE is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id;");
"FROM Messages "
"WHERE is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id;");
q.bindValue(QSL(":account_id"), account_id);
if (q.exec()) {
@ -616,13 +621,13 @@ bool DatabaseQueries::cleanFeeds(QSqlDatabase db, const QStringList &ids, bool c
if (clean_read_only) {
q.prepare(QString("UPDATE Messages SET is_deleted = :deleted "
"WHERE feed IN (%1) AND is_deleted = 0 AND is_pdeleted = 0 AND is_read = 1 AND account_id = :account_id;")
.arg(ids.join(QSL(", "))));
"WHERE feed IN (%1) AND is_deleted = 0 AND is_pdeleted = 0 AND is_read = 1 AND account_id = :account_id;")
.arg(ids.join(QSL(", "))));
}
else {
q.prepare(QString("UPDATE Messages SET is_deleted = :deleted "
"WHERE feed IN (%1) AND is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id;")
.arg(ids.join(QSL(", "))));
"WHERE feed IN (%1) AND is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id;")
.arg(ids.join(QSL(", "))));
}
q.bindValue(QSL(":deleted"), 1);
@ -653,5 +658,118 @@ bool DatabaseQueries::deleteLeftoverMessages(QSqlDatabase db, int account_id) {
}
}
bool DatabaseQueries::storeAccountTree(QSqlDatabase db, RootItem *tree_root, int account_id) {
QSqlQuery query_category(db);
QSqlQuery query_feed(db);
query_category.setForwardOnly(true);
query_feed.setForwardOnly(true);
query_category.prepare("INSERT INTO Categories (parent_id, title, account_id, custom_id) "
"VALUES (:parent_id, :title, :account_id, :custom_id);");
query_feed.prepare("INSERT INTO Feeds (title, icon, category, protected, update_type, update_interval, account_id, custom_id) "
"VALUES (:title, :icon, :category, :protected, :update_type, :update_interval, :account_id, :custom_id);");
// Iterate all children.
foreach (RootItem *child, tree_root->getSubTree()) {
if (child->kind() == RootItemKind::Category) {
query_category.bindValue(QSL(":parent_id"), child->parent()->id());
query_category.bindValue(QSL(":title"), child->title());
query_category.bindValue(QSL(":account_id"), account_id);
query_category.bindValue(QSL(":custom_id"), QString::number(child->toCategory()->customId()));
if (query_category.exec()) {
child->setId(query_category.lastInsertId().toInt());
}
else {
return false;
}
}
else if (child->kind() == RootItemKind::Feed) {
Feed *feed = child->toFeed();
query_feed.bindValue(QSL(":title"), feed->title());
query_feed.bindValue(QSL(":icon"), qApp->icons()->toByteArray(feed->icon()));
query_feed.bindValue(QSL(":category"), feed->parent()->customId());
query_feed.bindValue(QSL(":protected"), 0);
query_feed.bindValue(QSL(":update_type"), (int) feed->autoUpdateType());
query_feed.bindValue(QSL(":update_interval"), feed->autoUpdateInitialInterval());
query_feed.bindValue(QSL(":account_id"), account_id);
query_feed.bindValue(QSL(":custom_id"), feed->customId());
if (query_feed.exec()) {
feed->setId(query_feed.lastInsertId().toInt());
}
else {
return false;
}
}
}
return true;
}
QStringList DatabaseQueries::customIdsOfMessagesFromAccount(QSqlDatabase db, int account_id, bool *ok) {
QSqlQuery query(db);
QStringList ids;
query.setForwardOnly(true);
query.prepare(QSL("SELECT custom_id FROM Messages WHERE is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id;"));
query.bindValue(QSL(":account_id"), account_id);
if (ok != NULL) {
*ok = query.exec();
}
else {
query.exec();
}
while (query.next()) {
ids.append(query.value(0).toString());
}
return ids;
}
QStringList DatabaseQueries::customIdsOfMessagesFromBin(QSqlDatabase db, int account_id, bool *ok) {
QSqlQuery query(db);
QStringList ids;
query.setForwardOnly(true);
query.prepare(QSL("SELECT custom_id FROM Messages WHERE is_deleted = 1 AND is_pdeleted = 0 AND account_id = :account_id;"));
query.bindValue(QSL(":account_id"), account_id);
if (ok != NULL) {
*ok = query.exec();
}
else {
query.exec();
}
while (query.next()) {
ids.append(query.value(0).toString());
}
return ids;
}
QStringList DatabaseQueries::customIdsOfMessagesFromFeed(QSqlDatabase db, int feed_custom_id, int account_id, bool *ok) {
QSqlQuery query(db);
QStringList ids;
query.setForwardOnly(true);
query.prepare(QSL("SELECT custom_id FROM Messages WHERE is_deleted = 0 AND is_pdeleted = 0 AND feed = :feed AND account_id = :account_id;"));
query.bindValue(QSL(":account_id"), account_id);
query.bindValue(QSL(":feed"), feed_custom_id);
if (ok != NULL) {
*ok = query.exec();
}
else {
query.exec();
}
while (query.next()) {
ids.append(query.value(0).toString());
}
return ids;
}
DatabaseQueries::DatabaseQueries() {
}

View File

@ -38,7 +38,7 @@ class DatabaseQueries {
static bool purgeOldMessages(QSqlDatabase db, int older_than_days);
static bool purgeRecycleBin(QSqlDatabase db);
static QMap<int,int> getMessageCountsForCategory(QSqlDatabase db, int custom_id, int account_id,
bool including_total_counts, bool *ok = NULL);
bool including_total_counts, bool *ok = NULL);
static int getMessageCountsForFeed(QSqlDatabase db, int feed_custom_id, int account_id,
bool including_total_counts, bool *ok = NULL);
static int getMessageCountsForBin(QSqlDatabase db, int account_id, bool including_total_counts, bool *ok = NULL);
@ -52,6 +52,10 @@ class DatabaseQueries {
static bool deleteAccountData(QSqlDatabase db, int account_id, bool delete_messages_too);
static bool cleanFeeds(QSqlDatabase db, const QStringList &ids, bool clean_read_only, int account_id);
static bool deleteLeftoverMessages(QSqlDatabase db, int account_id);
static bool storeAccountTree(QSqlDatabase db, RootItem *tree_root, int account_id);
static QStringList customIdsOfMessagesFromAccount(QSqlDatabase db, int account_id, bool *ok = NULL);
static QStringList customIdsOfMessagesFromBin(QSqlDatabase db, int account_id, bool *ok = NULL);
static QStringList customIdsOfMessagesFromFeed(QSqlDatabase db, int feed_custom_id, int account_id, bool *ok = NULL);
private:
explicit DatabaseQueries();

View File

@ -46,6 +46,15 @@ class IconFactory : public QObject {
void clearCache();
inline QPixmap pixmap(const QString &name) {
if (m_currentIconTheme == APP_NO_THEME) {
return QPixmap();
}
else {
return QPixmap(APP_THEME_PATH + QDir::separator() + m_currentIconTheme + QDir::separator() + name + APP_THEME_SUFFIX);
}
}
// Returns icon from active theme or invalid icon if
// "no icon theme" is set.
inline QIcon fromTheme(const QString &name) {

View File

@ -128,50 +128,15 @@ bool ServiceRoot::cleanFeeds(QList<Feed*> items, bool clean_read_only) {
void ServiceRoot::storeNewFeedTree(RootItem *root) {
QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings);
QSqlQuery query_category(database);
QSqlQuery query_feed(database);
query_category.prepare("INSERT INTO Categories (parent_id, title, account_id, custom_id) "
"VALUES (:parent_id, :title, :account_id, :custom_id);");
query_feed.prepare("INSERT INTO Feeds (title, icon, category, protected, update_type, update_interval, account_id, custom_id) "
"VALUES (:title, :icon, :category, :protected, :update_type, :update_interval, :account_id, :custom_id);");
if (DatabaseQueries::storeAccountTree(database, root, accountId())) {
RecycleBin *bin = recycleBin();
// Iterate all children.
foreach (RootItem *child, root->getSubTree()) {
if (child->kind() == RootItemKind::Category) {
query_category.bindValue(QSL(":parent_id"), child->parent()->id());
query_category.bindValue(QSL(":title"), child->title());
query_category.bindValue(QSL(":account_id"), accountId());
query_category.bindValue(QSL(":custom_id"), QString::number(child->toCategory()->customId()));
if (query_category.exec()) {
child->setId(query_category.lastInsertId().toInt());
}
if (bin != NULL && !childItems().contains(bin)) {
// As the last item, add recycle bin, which is needed.
appendChild(bin);
bin->updateCounts(true);
}
else if (child->kind() == RootItemKind::Feed) {
Feed *feed = child->toFeed();
query_feed.bindValue(QSL(":title"), feed->title());
query_feed.bindValue(QSL(":icon"), qApp->icons()->toByteArray(feed->icon()));
query_feed.bindValue(QSL(":category"), feed->parent()->customId());
query_feed.bindValue(QSL(":protected"), 0);
query_feed.bindValue(QSL(":update_type"), (int) feed->autoUpdateType());
query_feed.bindValue(QSL(":update_interval"), feed->autoUpdateInitialInterval());
query_feed.bindValue(QSL(":account_id"), accountId());
query_feed.bindValue(QSL(":custom_id"), feed->customId());
if (query_feed.exec()) {
feed->setId(query_feed.lastInsertId().toInt());
}
}
}
RecycleBin *bin = recycleBin();
if (bin != NULL && !childItems().contains(bin)) {
// As the last item, add recycle bin, which is needed.
appendChild(bin);
bin->updateCounts(true);
}
}
@ -289,47 +254,19 @@ QStringList ServiceRoot::customIDSOfMessagesForItem(RootItem *item) {
case RootItemKind::ServiceRoot: {
QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings);
QSqlQuery query(database);
query.prepare(QSL("SELECT custom_id FROM Messages WHERE is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id;"));
query.bindValue(QSL(":account_id"), accountId());
query.exec();
while (query.next()) {
list.append(query.value(0).toString());
}
list = DatabaseQueries::customIdsOfMessagesFromAccount(database, accountId());
break;
}
case RootItemKind::Bin: {
QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings);
QSqlQuery query(database);
query.prepare(QSL("SELECT custom_id FROM Messages WHERE is_deleted = 1 AND is_pdeleted = 0 AND account_id = :account_id;"));
query.bindValue(QSL(":account_id"), accountId());
query.exec();
while (query.next()) {
list.append(query.value(0).toString());
}
list = DatabaseQueries::customIdsOfMessagesFromBin(database, accountId());
break;
}
case RootItemKind::Feed: {
QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings);
QSqlQuery query(database);
query.prepare(QSL("SELECT custom_id FROM Messages WHERE is_deleted = 0 AND is_pdeleted = 0 AND feed = :feed AND account_id = :account_id;"));
query.bindValue(QSL(":account_id"), accountId());
query.bindValue(QSL(":feed"), item->customId());
query.exec();
while (query.next()) {
list.append(query.value(0).toString());
}
list = DatabaseQueries::customIdsOfMessagesFromFeed(database, item->customId(), accountId());
break;
}