Start to work in "starred" node in feed list.

This commit is contained in:
Martin Rotter 2020-06-09 14:56:32 +02:00
parent 1fcc0b1f29
commit 0cd6e1c9a3
20 changed files with 287 additions and 109 deletions

View File

@ -233,10 +233,13 @@ nl_before_c_comment = 2 # unsigned number
nl_before_cpp_comment = 2 # unsigned number
# The number of newlines before a class definition
nl_before_class = 2 # unsigned number
nl_before_class = 0 # unsigned number
# The number of newlines after '}' or ';' of a class definition
nl_after_class = 2 # unsigned number
nl_after_class = 0 # unsigned number
# The number of newlines after '}' or ';' of a struct/enum/union definition.
nl_after_struct = 0 # unsigned number
# The number of newlines after '}' of a multi-line function body
nl_after_func_body = 2 # unsigned number
@ -265,7 +268,7 @@ nl_remove_extra_newlines = 0 # unsigned number
## Splitting.
# Try to limit code width to N number of columns
code_width = 140 # unsigned number
code_width = 160 # unsigned number
# Whether to fully split long function protos/calls at commas
ls_func_split_full = true # false/true
@ -288,4 +291,4 @@ cmt_c_group = true # false/true
# If True, will sort consecutive single-line '#include' statements [C/C++] and '#import' statements [Obj-C]
# This is generally a bad idea, as it may break your code.
mod_sort_include = true # false/true
mod_sort_include = true # false/true

View File

@ -20,6 +20,18 @@ FeedsProxyModel::FeedsProxyModel(FeedsModel* source_model, QObject* parent)
setFilterRole(Qt::EditRole);
setDynamicSortFilter(true);
setSourceModel(m_sourceModel);
// Describes priorities of node types for sorting.
// Smaller index means that item is "smaller" which
// means it should be more on top when sorting
// in ascending order.
m_priorities = {
RootItemKind::Kind::Category,
RootItemKind::Kind::Feed,
RootItemKind::Kind::Labels,
RootItemKind::Kind::Important,
RootItemKind::Kind::Bin
};
}
FeedsProxyModel::~FeedsProxyModel() {
@ -65,7 +77,7 @@ QModelIndexList FeedsProxyModel::match(const QModelIndex& start, int role, const
QString item_text = item_value.toString();
switch (match_type) {
case Qt::MatchRegExp:
case Qt::MatchRegularExpression:
if (QRegularExpression(entered_text,
QRegularExpression::PatternOption::CaseInsensitiveOption |
QRegularExpression::PatternOption::UseUnicodePropertiesOption).match(item_text).hasMatch()) {
@ -141,13 +153,13 @@ bool FeedsProxyModel::lessThan(const QModelIndex& left, const QModelIndex& right
// by item counts, depending on the sort column.
if (left_item->keepOnTop()) {
return sortOrder() == Qt::AscendingOrder;
return sortOrder() == Qt::SortOrder::AscendingOrder;
}
else if (right_item->keepOnTop()) {
return sortOrder() == Qt::DescendingOrder;
return sortOrder() == Qt::SortOrder::DescendingOrder;
}
else if (left_item->kind() == right_item->kind()) {
// Both items are feeds or both items are categories.
// Both items are of the same type.
if (left.column() == FDS_MODEL_COUNTS_INDEX) {
// User wants to sort according to counts.
return left_item->countOfUnreadMessages() < right_item->countOfUnreadMessages();
@ -157,24 +169,14 @@ bool FeedsProxyModel::lessThan(const QModelIndex& left, const QModelIndex& right
return QString::localeAwareCompare(left_item->title(), right_item->title()) < 0;
}
}
else if (left_item->kind() == RootItemKind::Bin) {
// Left item is recycle bin. Make sure it is "biggest" item if we have selected ascending order.
return sortOrder() == Qt::DescendingOrder;
}
else if (right_item->kind() == RootItemKind::Bin) {
// Right item is recycle bin. Make sure it is "smallest" item if we have selected descending order.
return sortOrder() == Qt::AscendingOrder;
}
else if (left_item->kind() == RootItemKind::Feed) {
// Left item is feed, right item is category.
return false;
}
else {
// Left item is category, right item is feed.
// NOTE: Category is in fact "more" than feed but we consider it to be "less" because it should be "placed"
// above the "smalles" feed when ascending sort is used.
// NOTE: We need to keep recycle bin in first position.
return true;
// We sort using priorities.
auto left_priority = m_priorities.indexOf(left_item->kind());
auto right_priority = m_priorities.indexOf(right_item->kind());
return sortOrder() == Qt::SortOrder::AscendingOrder
? left_priority < right_priority
: right_priority < left_priority;
}
}
else {

View File

@ -5,16 +5,15 @@
#include <QSortFilterProxyModel>
#include "services/abstract/rootitem.h"
class FeedsModel;
class RootItem;
class FeedsProxyModel : public QSortFilterProxyModel {
Q_OBJECT
public:
// Constructors and destructors.
explicit FeedsProxyModel(FeedsModel* source_model, QObject* parent = 0);
explicit FeedsProxyModel(FeedsModel* source_model, QObject* parent = nullptr);
virtual ~FeedsProxyModel();
// Returns index list of items which "match" given value.
@ -51,8 +50,8 @@ class FeedsProxyModel : public QSortFilterProxyModel {
FeedsModel* m_sourceModel;
const RootItem* m_selectedItem;
bool m_showUnreadOnly;
QList<QPair<int, QModelIndex>> m_hiddenIndices;
QList<RootItemKind::Kind> m_priorities;
};
#endif // FEEDSPROXYMODEL_H

View File

@ -113,7 +113,7 @@ QModelIndexList MessagesProxyModel::match(const QModelIndex& start, int role,
QString item_text = item_value.toString();
switch (match_type) {
case Qt::MatchRegExp:
case Qt::MatchRegularExpression:
if (QRegularExpression(entered_text,
QRegularExpression::PatternOption::CaseInsensitiveOption |
QRegularExpression::PatternOption::UseUnicodePropertiesOption).match(item_text).hasMatch()) {

View File

@ -11,7 +11,7 @@ LabelWithStatus::LabelWithStatus(QWidget* parent)
m_wdgInput = new QLabel(this);
// Set correct size for the tool button.
int label_height = m_wdgInput->sizeHint().height();
int label_height = m_wdgInput->sizeHint().height() * 1.2;
m_btnStatus->setFixedSize(label_height, label_height);

View File

@ -29,7 +29,7 @@
<enum>QTabWidget::North</enum>
</property>
<property name="currentIndex">
<number>2</number>
<number>0</number>
</property>
<widget class="QWidget" name="m_tabIconSkin">
<attribute name="title">

View File

@ -123,6 +123,7 @@ HEADERS += core/feeddownloader.h \
services/abstract/category.h \
services/abstract/feed.h \
services/abstract/gui/formfeeddetails.h \
services/abstract/importantnode.h \
services/abstract/recyclebin.h \
services/abstract/rootitem.h \
services/abstract/serviceentrypoint.h \
@ -263,6 +264,7 @@ SOURCES += core/feeddownloader.cpp \
services/abstract/category.cpp \
services/abstract/feed.cpp \
services/abstract/gui/formfeeddetails.cpp \
services/abstract/importantnode.cpp \
services/abstract/recyclebin.cpp \
services/abstract/rootitem.cpp \
services/abstract/serviceentrypoint.cpp \

View File

@ -171,14 +171,14 @@ bool DatabaseQueries::purgeRecycleBin(const QSqlDatabase& db) {
QMap<QString, QPair<int, int>> DatabaseQueries::getMessageCountsForCategory(const QSqlDatabase& db,
const QString& custom_id,
int account_id,
bool including_total_counts,
bool only_total_counts,
bool* ok) {
QMap<QString, QPair<int, int>> counts;
QSqlQuery q(db);
q.setForwardOnly(true);
if (including_total_counts) {
if (only_total_counts) {
q.prepare("SELECT feed, sum((is_read + 1) % 2), count(*) FROM Messages "
"WHERE feed IN (SELECT custom_id FROM Feeds WHERE category = :category AND account_id = :account_id) AND is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id "
"GROUP BY feed;");
@ -197,7 +197,7 @@ QMap<QString, QPair<int, int>> DatabaseQueries::getMessageCountsForCategory(cons
QString feed_custom_id = q.value(0).toString();
int unread_count = q.value(1).toInt();
if (including_total_counts) {
if (only_total_counts) {
int total_count = q.value(2).toInt();
counts.insert(feed_custom_id, QPair<int, int>(unread_count, total_count));
@ -221,13 +221,13 @@ QMap<QString, QPair<int, int>> DatabaseQueries::getMessageCountsForCategory(cons
}
QMap<QString, QPair<int, int>> DatabaseQueries::getMessageCountsForAccount(const QSqlDatabase& db, int account_id,
bool including_total_counts, bool* ok) {
bool only_total_counts, bool* ok) {
QMap<QString, QPair<int, int>> counts;
QSqlQuery q(db);
q.setForwardOnly(true);
if (including_total_counts) {
if (only_total_counts) {
q.prepare("SELECT feed, sum((is_read + 1) % 2), count(*) FROM Messages "
"WHERE is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id "
"GROUP BY feed;");
@ -245,7 +245,7 @@ QMap<QString, QPair<int, int>> DatabaseQueries::getMessageCountsForAccount(const
QString feed_id = q.value(0).toString();
int unread_count = q.value(1).toInt();
if (including_total_counts) {
if (only_total_counts) {
int total_count = q.value(2).toInt();
counts.insert(feed_id, QPair<int, int>(unread_count, total_count));
@ -269,12 +269,12 @@ QMap<QString, QPair<int, int>> DatabaseQueries::getMessageCountsForAccount(const
}
int DatabaseQueries::getMessageCountsForFeed(const QSqlDatabase& db, const QString& feed_custom_id,
int account_id, bool including_total_counts, bool* ok) {
int account_id, bool only_total_counts, bool* ok) {
QSqlQuery q(db);
q.setForwardOnly(true);
if (including_total_counts) {
if (only_total_counts) {
q.prepare("SELECT count(*) FROM Messages "
"WHERE feed = :feed AND is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id;");
}
@ -302,6 +302,38 @@ int DatabaseQueries::getMessageCountsForFeed(const QSqlDatabase& db, const QStri
}
}
int DatabaseQueries::getImportantMessageCounts(const QSqlDatabase& db, int account_id, bool only_total_counts, bool* ok) {
QSqlQuery q(db);
q.setForwardOnly(true);
if (only_total_counts) {
q.prepare("SELECT count(*) FROM Messages "
"WHERE is_important = 1 AND is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id;");
}
else {
q.prepare("SELECT count(*) FROM Messages "
"WHERE is_read = 0 AND is_important = 1 AND is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id;");
}
q.bindValue(QSL(":account_id"), account_id);
if (q.exec() && q.next()) {
if (ok != nullptr) {
*ok = true;
}
return q.value(0).toInt();
}
else {
if (ok != nullptr) {
*ok = false;
}
return 0;
}
}
int DatabaseQueries::getMessageCountsForBin(const QSqlDatabase& db, int account_id, bool including_total_counts, bool* ok) {
QSqlQuery q(db);

View File

@ -33,12 +33,15 @@ class DatabaseQueries {
static bool purgeLeftoverMessages(const QSqlDatabase& db, int account_id);
// Obtain counts of unread/all messages.
static QMap<QString, QPair<int, int>> getMessageCountsForCategory(const QSqlDatabase& db, const QString& custom_id, int account_id,
bool including_total_counts, bool* ok = nullptr);
static QMap<QString, QPair<int, int>> getMessageCountsForCategory(const QSqlDatabase& db, const QString& custom_id,
int account_id, bool only_total_counts,
bool* ok = nullptr);
static QMap<QString, QPair<int, int>> getMessageCountsForAccount(const QSqlDatabase& db, int account_id,
bool including_total_counts, bool* ok = nullptr);
bool only_total_counts, bool* ok = nullptr);
static int getMessageCountsForFeed(const QSqlDatabase& db, const QString& feed_custom_id, int account_id,
bool including_total_counts, bool* ok = nullptr);
bool only_total_counts, bool* ok = nullptr);
static int getImportantMessageCounts(const QSqlDatabase& db, int account_id,
bool only_total_counts, bool* ok = nullptr);
static int getMessageCountsForBin(const QSqlDatabase& db, int account_id, bool including_total_counts, bool* ok = nullptr);
// Get messages (for newspaper view for example).

View File

@ -39,7 +39,6 @@
#include "network-web/downloader.h"
class LocationLineEdit;
class QTimer;
class GoogleSuggest : public QObject {

View File

@ -0,0 +1,41 @@
// For license of this file, see <project-root-folder>/LICENSE.md.
#include "services/abstract/importantnode.h"
#include "miscellaneous/application.h"
#include "miscellaneous/databasequeries.h"
#include "miscellaneous/iconfactory.h"
#include "services/abstract/serviceroot.h"
#include <QThread>
ImportantNode::ImportantNode(RootItem* parent_item) : RootItem(parent_item) {
setKind(RootItemKind::Important);
setId(ID_RECYCLE_BIN);
setIcon(qApp->icons()->fromTheme(QSL("mail-mark-important")));
setTitle(tr("Important messages"));
setDescription(tr("You can find all important messages here."));
setCreationDate(QDateTime::currentDateTime());
}
void ImportantNode::updateCounts(bool including_total_count) {
bool is_main_thread = QThread::currentThread() == qApp->thread();
QSqlDatabase database = is_main_thread ?
qApp->database()->connection(metaObject()->className()) :
qApp->database()->connection(QSL("feed_upd"));
int account_id = getParentServiceRoot()->accountId();
if (including_total_count) {
m_totalCount = DatabaseQueries::getImportantMessageCounts(database, account_id, true);
}
m_unreadCount = DatabaseQueries::getImportantMessageCounts(database, account_id, false);
}
int ImportantNode::countOfUnreadMessages() const {
return m_unreadCount;
}
int ImportantNode::countOfAllMessages() const {
return m_totalCount;
}

View File

@ -0,0 +1,24 @@
// For license of this file, see <project-root-folder>/LICENSE.md.
#ifndef IMPORTANTNODE_H
#define IMPORTANTNODE_H
#include "services/abstract/rootitem.h"
class ImportantNode : public RootItem {
Q_OBJECT
public:
explicit ImportantNode(RootItem* parent_item = nullptr);
virtual ~ImportantNode() = default;
void updateCounts(bool including_total_count);
int countOfUnreadMessages() const;
int countOfAllMessages() const;
private:
int m_totalCount{};
int m_unreadCount{};
};
#endif // IMPORTANTNODE_H

View File

@ -21,8 +21,6 @@ RecycleBin::RecycleBin(RootItem* parent_item) : RootItem(parent_item), m_totalCo
setCreationDate(QDateTime::currentDateTime());
}
RecycleBin::~RecycleBin() = default;
QString RecycleBin::additionalTooltip() const {
return tr("%n deleted message(s).", nullptr, countOfAllMessages());
}

View File

@ -10,7 +10,7 @@ class RecycleBin : public RootItem {
public:
explicit RecycleBin(RootItem* parent_item = nullptr);
virtual ~RecycleBin();
virtual ~RecycleBin() = default;
QString additionalTooltip() const;
@ -32,7 +32,6 @@ class RecycleBin : public RootItem {
private:
int m_totalCount;
int m_unreadCount;
QList<QAction*> m_contextMenu;
};

View File

@ -209,11 +209,25 @@ bool RootItem::performDragDropChange(RootItem* target_item) {
return false;
}
int RootItem::countOfUnreadMessages() const {
int total_count = 0;
for (RootItem* child_item : m_childItems) {
if (child_item->kind() != RootItemKind::Kind::Important) {
total_count += child_item->countOfUnreadMessages();
}
}
return total_count;
}
int RootItem::countOfAllMessages() const {
int total_count = 0;
for (RootItem* child_item : m_childItems) {
total_count += child_item->countOfAllMessages();
if (child_item->kind() != RootItemKind::Kind::Important) {
total_count += child_item->countOfAllMessages();
}
}
return total_count;
@ -250,6 +264,7 @@ bool RootItem::isParentOf(const RootItem* child) const {
QList<RootItem*> RootItem::getSubTree() const {
QList<RootItem*> children;
QList<RootItem*> traversable_items;
traversable_items.append(const_cast<RootItem* const>(this));
// Iterate all nested items.
@ -266,6 +281,7 @@ QList<RootItem*> RootItem::getSubTree() const {
QList<RootItem*> RootItem::getSubTree(RootItemKind::Kind kind_of_item) const {
QList<RootItem*> children;
QList<RootItem*> traversable_items;
traversable_items.append(const_cast<RootItem* const>(this));
// Iterate all nested items.
@ -285,6 +301,7 @@ QList<RootItem*> RootItem::getSubTree(RootItemKind::Kind kind_of_item) const {
QList<Category*> RootItem::getSubTreeCategories() const {
QList<Category*> children;
QList<RootItem*> traversable_items;
traversable_items.append(const_cast<RootItem* const>(this));
// Iterate all nested items.
@ -304,6 +321,7 @@ QList<Category*> RootItem::getSubTreeCategories() const {
QHash<int, Category*> RootItem::getHashedSubTreeCategories() const {
QHash<int, Category*> children;
QList<RootItem*> traversable_items;
traversable_items.append(const_cast<RootItem* const>(this));
// Iterate all nested items.
@ -323,6 +341,7 @@ QHash<int, Category*> RootItem::getHashedSubTreeCategories() const {
QHash<QString, Feed*> RootItem::getHashedSubTreeFeeds() const {
QHash<QString, Feed*> children;
QList<RootItem*> traversable_items;
traversable_items.append(const_cast<RootItem* const>(this));
// Iterate all nested items.
@ -342,6 +361,7 @@ QHash<QString, Feed*> RootItem::getHashedSubTreeFeeds() const {
QList<Feed*> RootItem::getSubTreeFeeds() const {
QList<Feed*> children;
QList<RootItem*> traversable_items;
traversable_items.append(const_cast<RootItem* const>(this));
// Iterate all nested items.
@ -457,16 +477,6 @@ void RootItem::setKeepOnTop(bool keep_on_top) {
m_keepOnTop = keep_on_top;
}
int RootItem::countOfUnreadMessages() const {
int total_count = 0;
for (RootItem* child_item : m_childItems) {
total_count += child_item->countOfUnreadMessages();
}
return total_count;
}
bool RootItem::removeChild(int index) {
if (index >= 0 && index < m_childItems.size()) {
m_childItems.removeAt(index);

View File

@ -22,8 +22,10 @@ namespace RootItemKind {
Feed = 4,
Category = 8,
ServiceRoot = 16,
LabelsRoot = 32
Labels = 32,
Important = 64
};
inline Kind operator|(Kind a, Kind b) {
return static_cast<Kind>(static_cast<int>(a) | static_cast<int>(b));
}
@ -92,8 +94,6 @@ class RSSGUARD_DLLSPEC RootItem : public QObject {
// If this method is called on "recycle bin" instance of your
// service account, it should "empty" the recycle bin.
virtual bool cleanMessages(bool clear_only_read);
// Updates counts of all/unread messages for this feed.
virtual void updateCounts(bool including_total_count);
virtual int row() const;
virtual QVariant data(int column, int role) const;
@ -104,6 +104,7 @@ class RSSGUARD_DLLSPEC RootItem : public QObject {
// Returns counts of messages of all child items summed up.
virtual int countOfUnreadMessages() const;
virtual int countOfAllMessages() const;
inline RootItem* parent() const {
return m_parentItem;
}
@ -215,7 +216,6 @@ class RSSGUARD_DLLSPEC RootItem : public QObject {
QIcon m_icon;
QDateTime m_creationDate;
bool m_keepOnTop;
QList<RootItem*> m_childItems;
RootItem* m_parentItem;
};

View File

@ -11,9 +11,11 @@
#include "services/abstract/cacheforserviceroot.h"
#include "services/abstract/category.h"
#include "services/abstract/feed.h"
#include "services/abstract/importantnode.h"
#include "services/abstract/recyclebin.h"
ServiceRoot::ServiceRoot(RootItem* parent) : RootItem(parent), m_recycleBin(new RecycleBin(this)), m_accountId(NO_PARENT_CATEGORY) {
ServiceRoot::ServiceRoot(RootItem* parent)
: RootItem(parent), m_recycleBin(new RecycleBin(this)), m_importantNode(new ImportantNode(this)), m_accountId(NO_PARENT_CATEGORY) {
setKind(RootItemKind::ServiceRoot);
setCreationDate(QDateTime::currentDateTime());
}
@ -98,7 +100,6 @@ void ServiceRoot::updateCounts(bool including_total_count) {
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
bool ok;
QMap<QString, QPair<int, int>> counts = DatabaseQueries::getMessageCountsForAccount(database, accountId(), including_total_count, &ok);
if (ok) {
@ -163,6 +164,13 @@ bool ServiceRoot::cleanFeeds(QList<Feed*> items, bool clean_read_only) {
itemss.append(bin);
}
ImportantNode* imp = importantNode();
if (imp != nullptr) {
imp->updateCounts(true);
itemss << imp;
}
itemChanged(itemss);
requestReloadMessageList(true);
return true;
@ -267,6 +275,10 @@ void ServiceRoot::restoreCustomFeedsData(const QMap<QString, QVariant>& data, co
}
}
ImportantNode* ServiceRoot::importantNode() const {
return m_importantNode;
}
void ServiceRoot::setRecycleBin(RecycleBin* recycle_bin) {
m_recycleBin = recycle_bin;
}
@ -282,6 +294,7 @@ void ServiceRoot::syncIn() {
// Purge old data from SQL and clean all model items.
requestItemExpandStateSave(this);
QMap<QString, QVariant> feed_custom_data = storeCustomFeedsData();
removeOldFeedTree(false);
cleanAllItems();
restoreCustomFeedsData(feed_custom_data, new_tree->getHashedSubTreeFeeds());
@ -303,6 +316,7 @@ void ServiceRoot::syncIn() {
new_tree->clearChildren();
new_tree->deleteLater();
QList<RootItem*> all_items = getSubTree();
itemChanged(all_items);
requestReloadMessageList(true);
@ -388,6 +402,13 @@ bool ServiceRoot::markFeedsReadUnread(QList<Feed*> items, RootItem::ReadStatus r
itemss.append(feed);
}
ImportantNode* imp = importantNode();
if (imp != nullptr) {
imp->updateCounts(true);
itemss << imp;
}
itemChanged(itemss);
requestReloadMessageList(read == RootItem::Read);
return true;
@ -424,7 +445,7 @@ QStringList ServiceRoot::textualFeedIds(const QList<Feed*>& feeds) const {
QStringList ServiceRoot::customIDsOfMessages(const QList<ImportanceChange>& changes) {
QStringList list;
for (const auto & change : changes) {
for (const auto& change : changes) {
list.append(change.first.m_customId);
}
@ -454,6 +475,10 @@ bool ServiceRoot::loadMessagesForItem(RootItem* item, MessagesModel* model) {
model->setFilter(QString("Messages.is_deleted = 1 AND Messages.is_pdeleted = 0 AND Messages.account_id = %1")
.arg(QString::number(accountId())));
}
else if (item->kind() == RootItemKind::Kind::Important) {
model->setFilter(QString("Messages.is_important = 1 AND Messages.is_deleted = 0 AND Messages.is_pdeleted = 0 AND Messages.account_id = %1")
.arg(QString::number(accountId())));
}
else {
QList<Feed*> children = item->getSubTreeFeeds();
QString filter_clause = textualFeedIds(children).join(QSL(", "));
@ -485,8 +510,25 @@ bool ServiceRoot::onBeforeSetMessagesRead(RootItem* selected_item, const QList<M
bool ServiceRoot::onAfterSetMessagesRead(RootItem* selected_item, const QList<Message>& messages, RootItem::ReadStatus read) {
Q_UNUSED(messages)
Q_UNUSED(read)
selected_item->updateCounts(false);
itemChanged(QList<RootItem*>() << selected_item);
QList<RootItem*> items_to_reload;
ImportantNode* imp = importantNode();
if (imp == selected_item) {
updateCounts(true);
items_to_reload << getSubTree();
}
else {
selected_item->updateCounts(false);
items_to_reload << selected_item;
}
if (imp != nullptr && imp != selected_item) {
imp->updateCounts(true);
items_to_reload << imp;
}
itemChanged(items_to_reload);
return true;
}
@ -524,6 +566,16 @@ bool ServiceRoot::onBeforeSwitchMessageImportance(RootItem* selected_item, const
bool ServiceRoot::onAfterSwitchMessageImportance(RootItem* selected_item, const QList<ImportanceChange>& changes) {
Q_UNUSED(selected_item)
Q_UNUSED(changes)
QList<RootItem*> items_to_reload;
ImportantNode* imp = importantNode();
if (imp != nullptr) {
imp->updateCounts(true);
items_to_reload << imp;
}
itemChanged(items_to_reload);
return true;
}
@ -536,24 +588,26 @@ bool ServiceRoot::onBeforeMessagesDelete(RootItem* selected_item, const QList<Me
bool ServiceRoot::onAfterMessagesDelete(RootItem* selected_item, const QList<Message>& messages) {
Q_UNUSED(messages)
// User deleted some messages he selected in message list.
QList<RootItem*> items_to_reload;
selected_item->updateCounts(true);
items_to_reload << selected_item;
if (selected_item->kind() == RootItemKind::Bin) {
itemChanged(QList<RootItem*>() << selected_item);
}
else {
RecycleBin* bin = recycleBin();
RecycleBin* bin = recycleBin();
if (bin != nullptr) {
bin->updateCounts(true);
itemChanged(QList<RootItem*>() << selected_item << bin);
}
else {
itemChanged(QList<RootItem*>() << selected_item);
}
if (bin != nullptr && bin != selected_item) {
bin->updateCounts(true);
items_to_reload << bin;
}
ImportantNode* imp = importantNode();
if (imp != nullptr && imp != selected_item) {
imp->updateCounts(true);
items_to_reload << imp;
}
itemChanged(items_to_reload);
return true;
}
@ -591,6 +645,7 @@ void ServiceRoot::assembleFeeds(Assignment feeds) {
void ServiceRoot::assembleCategories(Assignment categories) {
QHash<int, RootItem*> assignments;
assignments.insert(NO_PARENT_CATEGORY, this);
// Add top-level categories.

View File

@ -11,6 +11,7 @@
class FeedsModel;
class RecycleBin;
class ImportantNode;
class QAction;
class MessagesModel;
@ -37,6 +38,7 @@ class ServiceRoot : public RootItem {
void setRecycleBin(RecycleBin* recycle_bin);
virtual ImportantNode* importantNode() const;
virtual bool downloadAttachmentOnMyOwn(const QUrl& url) const;
QList<Message> undeletedMessages() const;
@ -80,6 +82,18 @@ class ServiceRoot : public RootItem {
// Removes all/read only messages from given underlying feeds.
bool cleanFeeds(QList<Feed*> items, bool clean_read_only);
void completelyRemoveAllData();
QStringList customIDSOfMessagesForItem(RootItem* item);
bool markFeedsReadUnread(QList<Feed*> items, ReadStatus read);
// Obvious methods to wrap signals.
void itemChanged(const QList<RootItem*>& items);
void requestReloadMessageList(bool mark_selected_messages_read);
void requestItemExpand(const QList<RootItem*>& items, bool expand);
void requestItemExpandStateSave(RootItem* subtree_root);
void requestItemReassignment(RootItem* item, RootItem* new_parent);
void requestItemRemoval(RootItem* item);
// This method should prepare messages for given "item" (download them maybe?)
// into predefined "Messages" table
// and then use method QSqlTableModel::setFilter(....).
@ -137,18 +151,6 @@ class ServiceRoot : public RootItem {
// Selected item is naturally recycle bin.
virtual bool onAfterMessagesRestoredFromBin(RootItem* selected_item, const QList<Message>& messages);
void completelyRemoveAllData();
QStringList customIDSOfMessagesForItem(RootItem* item);
bool markFeedsReadUnread(QList<Feed*> items, ReadStatus read);
// Obvious methods to wrap signals.
void itemChanged(const QList<RootItem*>& items);
void requestReloadMessageList(bool mark_selected_messages_read);
void requestItemExpand(const QList<RootItem*>& items, bool expand);
void requestItemExpandStateSave(RootItem* subtree_root);
void requestItemReassignment(RootItem* item, RootItem* new_parent);
void requestItemRemoval(RootItem* item);
public slots:
virtual void addNewFeed(const QString& url = QString());
virtual void addNewCategory();
@ -197,6 +199,7 @@ class ServiceRoot : public RootItem {
private:
RecycleBin* m_recycleBin;
ImportantNode* m_importantNode;
int m_accountId;
};

View File

@ -11,6 +11,7 @@
#include "miscellaneous/iconfactory.h"
#include "miscellaneous/mutex.h"
#include "miscellaneous/settings.h"
#include "services/abstract/importantnode.h"
#include "services/abstract/recyclebin.h"
#include "services/standard/gui/formstandardcategorydetails.h"
#include "services/standard/gui/formstandardfeeddetails.h"
@ -120,6 +121,7 @@ void StandardServiceRoot::addNewFeed(const QString& url) {
}
QScopedPointer<FormStandardFeedDetails> form_pointer(new FormStandardFeedDetails(this, qApp->mainFormWidget()));
form_pointer.data()->addEditFeed(nullptr, nullptr, url);
qApp->feedUpdateLock()->unlock();
}
@ -139,6 +141,7 @@ void StandardServiceRoot::loadFromDatabase() {
// As the last item, add recycle bin, which is needed.
appendChild(recycleBin());
appendChild(importantNode());
updateCounts(true);
}
@ -185,8 +188,10 @@ QList<QAction*> StandardServiceRoot::getContextMenuForFeed(StandardFeed* feed) {
bool StandardServiceRoot::mergeImportExportModel(FeedsImportExportModel* model, RootItem* target_root_node, QString& output_message) {
QStack<RootItem*> original_parents;
original_parents.push(target_root_node);
QStack<RootItem*> new_parents;
new_parents.push(model->rootItem());
bool some_feed_category_error = false;
@ -280,18 +285,21 @@ void StandardServiceRoot::addNewCategory() {
}
QScopedPointer<FormStandardCategoryDetails> form_pointer(new FormStandardCategoryDetails(this, qApp->mainFormWidget()));
form_pointer.data()->addEditCategory(nullptr, nullptr);
qApp->feedUpdateLock()->unlock();
}
void StandardServiceRoot::importFeeds() {
QScopedPointer<FormStandardImportExport> form(new FormStandardImportExport(this, qApp->mainFormWidget()));
form.data()->setMode(FeedsImportExportModel::Import);
form.data()->exec();
}
void StandardServiceRoot::exportFeeds() {
QScopedPointer<FormStandardImportExport> form(new FormStandardImportExport(this, qApp->mainFormWidget()));
form.data()->setMode(FeedsImportExportModel::Export);
form.data()->exec();
}

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>604</width>
<height>442</height>
<height>517</height>
</rect>
</property>
<property name="windowTitle">
@ -192,21 +192,21 @@
</property>
</widget>
</item>
<item row="8" column="0" colspan="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>68</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>68</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="m_buttonBox">
<property name="orientation">