#ifndef BOARD_H #define BOARD_H #include #include #include #include #include #include #include #include #include #include class Action; class XmlRpcInterface; class Board : public QObject { Q_OBJECT Q_PROPERTY(bool busy READ busy NOTIFY busyChanged) Q_PROPERTY(bool loggedIn READ loggedIn NOTIFY loggedInChanged) Q_PROPERTY(int rootForumId READ rootForumId CONSTANT) Q_ENUMS(TopicType) Q_FLAGS(DateTimePrecisionOptions) public: explicit Board(QObject *parent = 0); Board(const QUrl& url, const QString& username, const QString& password, QObject *parent = 0); ~Board(); enum TopicType { Normal = 0, Sticky = 1, Announcement = 2 }; enum DateTimePrecisionOption { ShowTime = 1 << 0, RelativeTime = 1 << 1, // "n second(s) ago" instead of "Today HH:MM" TodayYesterday = 1 << 2, // "Today", "Yesterday" and "Today HH:MM" if ShowTime RelativeDate = 1 << 3 // "n week(s) ago", incompatible with ShowTime }; Q_DECLARE_FLAGS(DateTimePrecisionOptions, DateTimePrecisionOption) static const QLatin1String CURRENT_DB_VERSION; bool busy() const; void enqueueAction(Action* action); QSqlDatabase database(); XmlRpcInterface *service(); int rootForumId() const; // Configuration table Q_INVOKABLE QString getConfig(const QString& key) const; void setConfig(const QString& key, const QString &value); // Login/logout stuff QVariant getLoginInfo(const QString& key) const; bool loggedIn() const; void login(const QString& username, const QString& password); void logout(); // Other functions that query the database int getTopicForumId(int topicId); // Posting stuff Q_INVOKABLE void newTopic(int forumId, const QString& subject, const QString& text); Q_INVOKABLE void replyToTopic(int topicId, const QString& text); // BBCode-related helper functions QString removeHtml(QString text) const; QString removeBbcode(QString text) const; QString bbcodeToRichText(QString text) const; QString parseSmilies(QString text) const; Q_INVOKABLE QString formatDateTime(const QDateTime& dateTime, DateTimePrecisionOptions precision) const; public slots: void cancelAllActions(); // These functions wrap emitting the signals below void notifyConfigChanged(const QString& key = QString()); void notifyForumsChanged(); void notifyForumChanged(int forumId); void notifyForumTopicsChanged(int forumId, Board::TopicType type, int start, int end); void notifyForumTopicChanged(int forumId, int topicId); void notifyTopicPostsChanged(int topicId, int start, int end); void notifyTopicPostsUnread(int topicId, int position); void notifyLogin(const QMap& info); void notifyLogout(); // Functions for marking posts as read void markTopicAsRead(int topicId); signals: void busyChanged(); void loggedInChanged(); void configChanged(const QString& key); void forumsChanged(); void forumChanged(int forumId); void forumTopicsChanged(int forumId, Board::TopicType type, int start, int end); void forumTopicChanged(int forumId, int topicId); void topicPostsChanged(int topicId, int start, int end); void topicPostsUnread(int topicId, int position); private: static QString createSlug(const QUrl& url); static QString getDbPathFor(const QString& slug); static QString getTempDbPathFor(const QString& slug); int dbSize() const; bool checkCompatibleDb(); bool initializeDb(); bool eraseDb(); bool cleanDb(); bool removeFromActionQueue(Action *action); void executeActionFromQueue(); void initializeBbCode(); void initializeSmilies(); void fetchConfigIfOutdated(); void fetchForumsIfOutdated(); void updateForumReadState(int forumId); private slots: void handleActionFinished(Action *action); void handleActionError(Action *action, const QString& message); private: QUrl _url; QString _slug; QSqlDatabase _db; XmlRpcInterface *_iface; /** The queue of pending actions. The first one is currently being run. */ QQueue _queue; /** Configuration cache */ mutable QHash _config; /** Login information, which is obviously not persistent. */ QMap _loginInfo; /** Bbcodes list and their HTML replacements for quick-and-dirty parsing. */ QList< QPair > _bbcodes; /** List of smilies and their replacements. */ QHash _smilies; /** A regular expression that matches every possibly smilie. */ QRegExp _smilieRegexp; }; Q_DECLARE_OPERATORS_FOR_FLAGS(Board::DateTimePrecisionOptions) inline bool Board::busy() const { return !_queue.empty(); } inline bool Board::loggedIn() const { return !_loginInfo.empty(); } inline int Board::rootForumId() const { return 0; } inline QSqlDatabase Board::database() { return _db; } inline XmlRpcInterface * Board::service() { return _iface; } #endif // BOARD_H