331 lines
14 KiB
C++
331 lines
14 KiB
C++
// For license of this file, see <project-root-folder>/LICENSE.md.
|
|
|
|
#ifndef SERVICEROOT_H
|
|
#define SERVICEROOT_H
|
|
|
|
#include "services/abstract/rootitem.h"
|
|
|
|
#include "core/message.h"
|
|
#include "core/messagefilter.h"
|
|
#include "definitions/typedefs.h"
|
|
|
|
#include <QJsonDocument>
|
|
#include <QNetworkProxy>
|
|
#include <QPair>
|
|
|
|
class QAction;
|
|
class QMutex;
|
|
class FeedsModel;
|
|
class RecycleBin;
|
|
class ImportantNode;
|
|
class UnreadNode;
|
|
class SearchsNode;
|
|
class LabelsNode;
|
|
class Label;
|
|
class MessagesModel;
|
|
class CustomMessagePreviewer;
|
|
class CacheForServiceRoot;
|
|
|
|
// THIS IS the root node of the service.
|
|
// NOTE: The root usually contains some core functionality of the
|
|
// service like service account username/password etc.
|
|
class ServiceRoot : public RootItem {
|
|
Q_OBJECT
|
|
|
|
public:
|
|
enum class LabelOperation {
|
|
Adding = 1,
|
|
Editing = 2,
|
|
Deleting = 4,
|
|
|
|
// NOTE: Service fetches list of labels from remote source
|
|
// and does not use local offline labels.
|
|
Synchronised = 8
|
|
};
|
|
|
|
enum class BagOfMessages {
|
|
Read,
|
|
Unread,
|
|
Starred
|
|
};
|
|
|
|
public:
|
|
explicit ServiceRoot(RootItem* parent = nullptr);
|
|
virtual ~ServiceRoot();
|
|
|
|
// These methods bellow are part of "interface".
|
|
RecycleBin* recycleBin() const;
|
|
ImportantNode* importantNode() const;
|
|
LabelsNode* labelsNode() const;
|
|
SearchsNode* probesNode() const;
|
|
UnreadNode* unreadNode() const;
|
|
|
|
virtual void updateCounts(bool including_total_count);
|
|
virtual bool canBeDeleted() const;
|
|
virtual bool deleteViaGui();
|
|
virtual bool markAsReadUnread(ReadStatus status);
|
|
virtual QList<Message> undeletedMessages() const;
|
|
virtual bool supportsFeedAdding() const;
|
|
virtual bool supportsCategoryAdding() const;
|
|
virtual LabelOperation supportedLabelOperations() const;
|
|
virtual QString additionalTooltip() const;
|
|
virtual void saveAccountDataToDatabase();
|
|
virtual QVariantHash customDatabaseData() const;
|
|
virtual void setCustomDatabaseData(const QVariantHash& data);
|
|
virtual bool wantsBaggedIdsOfExistingMessages() const;
|
|
virtual bool displaysEnclosures() const;
|
|
virtual void aboutToBeginFeedFetching(const QList<Feed*>& feeds,
|
|
const QHash<QString, QHash<ServiceRoot::BagOfMessages, QStringList>>&
|
|
stated_messages,
|
|
const QHash<QString, QStringList>& tagged_messages);
|
|
|
|
// Returns list of specific actions for "Add new item" main window menu.
|
|
// So typical list of returned actions could look like:
|
|
// a) Add new feed
|
|
// b) Add new category
|
|
// c) ...
|
|
// NOTE: Caller does NOT take ownership of created menu/actions!
|
|
virtual QList<QAction*> addItemMenu();
|
|
|
|
// NOTE: Caller does NOT take ownership of created menu/actions!
|
|
virtual QList<QAction*> contextMenuFeedsList();
|
|
|
|
// NOTE: Caller does NOT take ownership of created menu/actions!
|
|
virtual QList<QAction*> contextMenuMessagesList(const QList<Message>& messages);
|
|
|
|
// Returns list of specific actions to be shown in main window menu
|
|
// bar in sections "Services -> 'this service'".
|
|
// NOTE: Caller does NOT take ownership of created menu!
|
|
virtual QList<QAction*> serviceMenu();
|
|
|
|
// If plugin uses online synchronization of feeds/labels/etc, then returns true.
|
|
virtual bool isSyncable() const;
|
|
|
|
// Start/stop services.
|
|
// Start method is called when feed model gets initialized OR after user adds new service.
|
|
// Account should synchronously initialize its children (load them from DB is recommended
|
|
// here).
|
|
//
|
|
// Stop method is called just before application exits OR when
|
|
// user explicitly deletes existing service instance.
|
|
virtual void start(bool freshly_activated);
|
|
virtual void stop();
|
|
|
|
// Obtains list of messages.
|
|
// Throws exception subclassed from ApplicationException, preferably FeedFetchException
|
|
// if any problems arise.
|
|
virtual QList<Message> obtainNewMessages(Feed* feed,
|
|
const QHash<ServiceRoot::BagOfMessages, QStringList>& stated_messages,
|
|
const QHash<QString, QStringList>& tagged_messages) = 0;
|
|
|
|
// Returns special widget to display articles of this account type.
|
|
// Caller does NOT free returned previewer after usage from memory,
|
|
// it only may hide it.
|
|
// Thus, account is responsible to free any custom previewers.
|
|
virtual CustomMessagePreviewer* customMessagePreviewer();
|
|
|
|
// This method should load messages for given "item" into model.
|
|
virtual bool loadMessagesForItem(RootItem* item, MessagesModel* model);
|
|
|
|
// Called BEFORE this read status update (triggered by user in message list) is stored in DB,
|
|
// when false is returned, change is aborted.
|
|
// This is the place to make some other changes like updating
|
|
// some ONLINE service or something.
|
|
//
|
|
// "read" is status which is ABOUT TO BE SET.
|
|
virtual bool onBeforeSetMessagesRead(RootItem* selected_item, const QList<Message>& messages, ReadStatus read);
|
|
|
|
// Called AFTER this read status update (triggered by user in message list) is stored in DB,
|
|
// when false is returned, change is aborted.
|
|
// Here service root should inform (via signals)
|
|
// which items are actually changed.
|
|
//
|
|
// "read" is status which is ABOUT TO BE SET.
|
|
virtual bool onAfterSetMessagesRead(RootItem* selected_item, const QList<Message>& messages, ReadStatus read);
|
|
|
|
// Called BEFORE this importance switch update is stored in DB,
|
|
// when false is returned, change is aborted.
|
|
// This is the place to make some other changes like updating
|
|
// some ONLINE service or something.
|
|
//
|
|
// "changes" - list of pairs - <message (integer id), new status>
|
|
virtual bool onBeforeSwitchMessageImportance(RootItem* selected_item, const QList<ImportanceChange>& changes);
|
|
|
|
// Called AFTER this importance switch update is stored in DB,
|
|
// when false is returned, change is aborted.
|
|
// Here service root should inform (via signals)
|
|
// which items are actually changed.
|
|
//
|
|
// "changes" - list of pairs - <message (integer id), new status>
|
|
virtual bool onAfterSwitchMessageImportance(RootItem* selected_item, const QList<ImportanceChange>& changes);
|
|
|
|
// Called BEFORE the list of messages is about to be deleted
|
|
// by the user from message list.
|
|
virtual bool onBeforeMessagesDelete(RootItem* selected_item, const QList<Message>& messages);
|
|
|
|
// Called AFTER the list of messages was deleted
|
|
// by the user from message list.
|
|
virtual bool onAfterMessagesDelete(RootItem* selected_item, const QList<Message>& messages);
|
|
|
|
// Called BEFORE some labels are assigned/deassigned from/to messages.
|
|
virtual bool onBeforeLabelMessageAssignmentChanged(const QList<Label*>& labels,
|
|
const QList<Message>& messages,
|
|
bool assign);
|
|
|
|
// Called AFTER some labels are assigned/deassigned from/to messages.
|
|
virtual bool onAfterLabelMessageAssignmentChanged(const QList<Label*>& labels,
|
|
const QList<Message>& messages,
|
|
bool assign);
|
|
|
|
// Called BEFORE the list of messages is about to be restored from recycle bin
|
|
// by the user from message list.
|
|
// Selected item is naturally recycle bin.
|
|
virtual bool onBeforeMessagesRestoredFromBin(RootItem* selected_item, const QList<Message>& messages);
|
|
|
|
// Called AFTER the list of messages was restored from recycle bin
|
|
// by the user from message list.
|
|
// Selected item is naturally recycle bin.
|
|
virtual bool onAfterMessagesRestoredFromBin(RootItem* selected_item, const QList<Message>& messages);
|
|
|
|
// Returns the UNIQUE code of the given service.
|
|
// NOTE: Keep in sync with ServiceEntryRoot::code().
|
|
virtual QString code() const = 0;
|
|
|
|
public:
|
|
CacheForServiceRoot* toCache() const;
|
|
|
|
// Account ID corresponds with DB attribute Accounts (id).
|
|
int accountId() const;
|
|
void setAccountId(int account_id);
|
|
|
|
QNetworkProxy networkProxy() const;
|
|
void setNetworkProxy(const QNetworkProxy& network_proxy);
|
|
|
|
// Removes all data associated with this account from DB
|
|
// and from model.
|
|
void completelyRemoveAllData();
|
|
|
|
// Returns counts of updated messages <unread, all>.
|
|
QPair<int, int> updateMessages(QList<Message>& messages, Feed* feed, bool force_update, QMutex* db_mutex);
|
|
|
|
QIcon feedIconForMessage(const QString& feed_custom_id) const;
|
|
|
|
// Removes all/read only messages from given underlying feeds.
|
|
bool cleanFeeds(const QList<Feed*>& items, bool clean_read_only);
|
|
|
|
// Marks all messages from feeds read/unread.
|
|
bool markFeedsReadUnread(const 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);
|
|
|
|
// Some message/feed attribute selectors.
|
|
QStringList textualFeedUrls(const QList<Feed*>& feeds) const;
|
|
QStringList textualFeedIds(const QList<Feed*>& feeds) const;
|
|
QStringList customIDsOfMessages(const QList<ImportanceChange>& changes);
|
|
QStringList customIDsOfMessages(const QList<Message>& messages);
|
|
|
|
// Returns list of article IDs depending on what target operation is.
|
|
// NOTE: So if we want to mark some articles as read,
|
|
// then we only return UNREAD IDs here to really return
|
|
// only IDs when the change makes sense.
|
|
// NOTE: Importance is not dealt here because it was not needed
|
|
// yet.
|
|
QStringList customIDSOfMessagesForItem(RootItem* item,
|
|
RootItem::ReadStatus target_read = RootItem::ReadStatus::Unknown);
|
|
|
|
void performInitialAssembly(const Assignment& categories,
|
|
const Assignment& feeds,
|
|
const QList<Label*>& labels,
|
|
const QList<Search*>& probes);
|
|
|
|
public slots:
|
|
virtual void addNewFeed(RootItem* selected_item, const QString& url = QString());
|
|
virtual void addNewCategory(RootItem* selected_item);
|
|
virtual void syncIn();
|
|
|
|
protected:
|
|
// This method should obtain new tree of feed/categories/whatever to perform sync in.
|
|
virtual RootItem* obtainNewTreeForSyncIn() const;
|
|
|
|
// Removes all messages/categories/feeds which are
|
|
// associated with this account.
|
|
void removeOldAccountFromDatabase(bool delete_messages_too, bool delete_labels_too);
|
|
void cleanAllItemsFromModel(bool clean_labels_too);
|
|
void appendCommonNodes();
|
|
|
|
// Removes messages which do not belong to any
|
|
// existing feed.
|
|
//
|
|
// NOTE: This situation may happen if user deletes some feed
|
|
// from another machine and then performs sync-in on this machine.
|
|
void removeLeftOverMessages();
|
|
|
|
// Removes all msg. filter assignments which are (within this account)
|
|
// assigned to feed (via custom ID) which does not exist anymore.
|
|
//
|
|
// NOTE: This situation may happen if user deletes some feed
|
|
// from another machine and then performs sync-in on this machine.
|
|
void removeLeftOverMessageFilterAssignments();
|
|
|
|
// Takes lists of feeds/categories and assembles them into the tree structure.
|
|
void assembleCategories(const Assignment& categories);
|
|
void assembleFeeds(const Assignment& feeds);
|
|
|
|
signals:
|
|
void proxyChanged(QNetworkProxy proxy);
|
|
void dataChanged(QList<RootItem*> items);
|
|
void reloadMessageListRequested(bool mark_selected_messages_read);
|
|
void itemExpandRequested(QList<RootItem*> items, bool expand);
|
|
void itemExpandStateSaveRequested(RootItem* subtree_root);
|
|
|
|
void itemReassignmentRequested(RootItem* item, RootItem* new_parent);
|
|
void itemRemovalRequested(RootItem* item);
|
|
|
|
private:
|
|
void resortAccountTree(RootItem* tree,
|
|
const QMap<QString, QVariantMap>& custom_category_data,
|
|
const QMap<QString, QVariantMap>& custom_feed_data) const;
|
|
|
|
// Key is feed's custom ID.
|
|
virtual QMap<QString, QVariantMap> storeCustomFeedsData();
|
|
|
|
// Key is category's custom ID.
|
|
virtual QMap<QString, QVariantMap> storeCustomCategoriesData();
|
|
|
|
virtual void restoreCustomFeedsData(const QMap<QString, QVariantMap>& data, const QHash<QString, Feed*>& feeds);
|
|
virtual void restoreCustomCategoriesData(const QMap<QString, QVariantMap>& data,
|
|
const QHash<QString, Category*>& cats);
|
|
|
|
protected:
|
|
RecycleBin* m_recycleBin;
|
|
ImportantNode* m_importantNode;
|
|
LabelsNode* m_labelsNode;
|
|
SearchsNode* m_probesNode;
|
|
UnreadNode* m_unreadNode;
|
|
int m_accountId;
|
|
QList<QAction*> m_serviceMenu;
|
|
QNetworkProxy m_networkProxy;
|
|
};
|
|
|
|
#if QT_VERSION_MAJOR == 6
|
|
inline size_t qHash(ServiceRoot::BagOfMessages key, size_t seed) {
|
|
return ::qHash(static_cast<uint>(key), seed);
|
|
}
|
|
|
|
#else
|
|
inline uint qHash(ServiceRoot::BagOfMessages key, uint seed) {
|
|
return ::qHash(static_cast<uint>(key), seed);
|
|
}
|
|
|
|
#endif
|
|
|
|
ServiceRoot::LabelOperation operator|(ServiceRoot::LabelOperation lhs, ServiceRoot::LabelOperation rhs);
|
|
ServiceRoot::LabelOperation operator&(ServiceRoot::LabelOperation lhs, ServiceRoot::LabelOperation rhs);
|
|
|
|
#endif // SERVICEROOT_H
|