From 9e67c13e587ccf10084144fea033beda316faed5 Mon Sep 17 00:00:00 2001 From: "Javier S. Pedro" Date: Sun, 7 Apr 2013 03:13:14 +0200 Subject: add support for reading announcements & stickies --- board.cpp | 12 +-- board.h | 11 ++- fetchtopicsaction.cpp | 47 ++++++++--- fetchtopicsaction.h | 7 +- forummodel.cpp | 212 ++++++++++++++++++++++++++++++++++++++------------ forummodel.h | 9 ++- newtopicaction.cpp | 1 + 7 files changed, 226 insertions(+), 73 deletions(-) diff --git a/board.cpp b/board.cpp index da469dc..26908b7 100644 --- a/board.cpp +++ b/board.cpp @@ -293,10 +293,10 @@ void Board::notifyForumChanged(int forumId) emit forumChanged(forumId); } -void Board::notifyForumTopicsChanged(int forumId, int start, int end) +void Board::notifyForumTopicsChanged(int forumId, TopicType type, int start, int end) { - qDebug() << "ForumTopics changed" << forumId << start << end; - emit forumTopicsChanged(forumId, start, end); + qDebug() << "ForumTopics changed" << forumId << type << start << end; + emit forumTopicsChanged(forumId, type, start, end); } void Board::notifyForumTopicChanged(int forumId, int topicId) @@ -415,7 +415,7 @@ bool Board::initializeDb() return false; } - if (!q.exec("CREATE TABLE IF NOT EXISTS forums (forum_id INTEGER PRIMARY KEY, forum_name TEXT, description TEXT, parent_id INT, logo_url TEXT, new_post BOOL, is_protected BOOL, is_subscribed BOOL, can_subscribe BOOL, url TEXT, sub_only BOOL, position INT)")) { + if (!q.exec("CREATE TABLE IF NOT EXISTS forums (forum_id INTEGER PRIMARY KEY, forum_name TEXT, description TEXT, parent_id INTEGER, logo_url TEXT, new_post BOOL, is_protected BOOL, is_subscribed BOOL, can_subscribe BOOL, url TEXT, sub_only BOOL, position INT)")) { qWarning() << "Could not create forums table:" << q.lastError().text(); return false; } @@ -428,7 +428,7 @@ bool Board::initializeDb() return false; } - if (!q.exec("CREATE TABLE IF NOT EXISTS topics (forum_id INTEGER, topic_id INTEGER PRIMARY KEY, topic_title TEXT, topic_author_id INTEGER, topic_author_name TEXT, is_subscribed BOOL, is_closed BOOL, icon_url TEXT, last_reply_time TEXT, reply_number INT, new_post BOOL, position INT, last_update_time TEXT)")) { + if (!q.exec("CREATE TABLE IF NOT EXISTS topics (forum_id INTEGER, topic_id INTEGER PRIMARY KEY, topic_type INT, topic_title TEXT, topic_author_id INTEGER, topic_author_name TEXT, is_subscribed BOOL, is_closed BOOL, icon_url TEXT, last_reply_time TEXT, reply_number INT, new_post BOOL, position INT, last_update_time TEXT)")) { qWarning() << "Could not create topics table:" << q.lastError().text(); return false; } @@ -440,7 +440,7 @@ bool Board::initializeDb() qWarning() << "Could not create topics_time index:" << q.lastError().text(); return false; } - if (!q.exec("CREATE INDEX IF NOT EXISTS topics_order ON topics (forum_id, position ASC)")) { + if (!q.exec("CREATE INDEX IF NOT EXISTS topics_order ON topics (forum_id, topic_type DESC, position ASC)")) { qWarning() << "Could not create topics_order index:" << q.lastError().text(); return false; } diff --git a/board.h b/board.h index 81ee81f..d7e91a2 100644 --- a/board.h +++ b/board.h @@ -21,12 +21,19 @@ class Board : public QObject 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) 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 + }; + static const QLatin1String CURRENT_DB_VERSION; bool busy() const; @@ -71,7 +78,7 @@ public slots: void notifyConfigChanged(const QString& key = QString()); void notifyForumsChanged(); void notifyForumChanged(int forumId); - void notifyForumTopicsChanged(int forumId, int start, int end); + 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); @@ -87,7 +94,7 @@ signals: void configChanged(const QString& key); void forumsChanged(); void forumChanged(int forumId); - void forumTopicsChanged(int forumId, int start, int end); + 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); diff --git a/fetchtopicsaction.cpp b/fetchtopicsaction.cpp index 4617280..1c6cc86 100644 --- a/fetchtopicsaction.cpp +++ b/fetchtopicsaction.cpp @@ -10,8 +10,9 @@ #include "xmlrpcreply.h" #include "fetchtopicsaction.h" -FetchTopicsAction::FetchTopicsAction(int forumId, int start, int end, Board *board) : - Action(board), _forumId(forumId), _start(start), _end(end) +FetchTopicsAction::FetchTopicsAction(int forumId, Board::TopicType type, + int start, int end, Board *board) : + Action(board), _forumId(forumId), _type(type), _start(start), _end(end) { } @@ -19,7 +20,7 @@ bool FetchTopicsAction::isSupersetOf(Action *action) const { FetchTopicsAction *other = qobject_cast(action); if (other) { - if (other->_forumId == _forumId) { + if (other->_forumId == _forumId && other->_type == _type) { if (_end == FetchAllTopics) { // If this is fetching all topics, then this is a superset // of every other action... except those that also fetch all @@ -48,8 +49,27 @@ void FetchTopicsAction::execute() // After finishing this action, a new one will be enqueued with the next 50. } - _call = _board->service()->asyncCall("get_topic", - QString::number(_forumId), _start, end); + switch (_type) { + case Board::Normal: + _call = _board->service()->asyncCall("get_topic", + QString::number(_forumId), + _start, end); + break; + case Board::Sticky: + _call = _board->service()->asyncCall("get_topic", + QString::number(_forumId), + _start, end, + QString("TOP")); + break; + case Board::Announcement: + _call = _board->service()->asyncCall("get_topic", + QString::number(_forumId), + _start, end, + QString("ANN")); + break; + } + Q_ASSERT(_call); + _call->setParent(this); connect(_call, SIGNAL(finished(XmlRpcPendingCall*)), SLOT(handleFinishedCall())); } @@ -77,8 +97,8 @@ void FetchTopicsAction::handleFinishedCall() int position = _start; QSqlQuery query(db); - query.prepare("INSERT OR REPLACE INTO topics (forum_id, topic_id, topic_title, topic_author_id, topic_author_name, is_subscribed, is_closed, icon_url, last_reply_time, reply_number, new_post, position, last_update_time) " - "VALUES (:forum_id, :topic_id, :topic_title, :topic_author_id, :topic_author_name, :is_subscribed, :is_closed, :icon_url, :last_reply_time, :reply_number, :new_post, :position, :last_update_time)"); + query.prepare("INSERT OR REPLACE INTO topics (forum_id, topic_id, topic_type, topic_title, topic_author_id, topic_author_name, is_subscribed, is_closed, icon_url, last_reply_time, reply_number, new_post, position, last_update_time) " + "VALUES (:forum_id, :topic_id, :topic_type, :topic_title, :topic_author_id, :topic_author_name, :is_subscribed, :is_closed, :icon_url, :last_reply_time, :reply_number, :new_post, :position, :last_update_time)"); foreach (const QVariant& topic_v, topics) { @@ -99,6 +119,7 @@ void FetchTopicsAction::handleFinishedCall() query.bindValue(":forum_id", forum_id); query.bindValue(":topic_id", topic_id); + query.bindValue(":topic_type", _type); query.bindValue(":topic_title", decodeTopicText(topic["topic_title"])); query.bindValue(":topic_author_id", topic["topic_author_id"].toInt()); query.bindValue(":topic_author_name", decodeTopicText(topic["topic_author_name"])); @@ -128,8 +149,11 @@ void FetchTopicsAction::handleFinishedCall() if (eof) { // Service did not return as many topics as we expected, thus we // can safely delete any topics after the current position. - query.prepare("DELETE FROM topics WHERE forum_id = :forum_id AND position >= :position"); + query.prepare("DELETE FROM topics " + "WHERE forum_id = :forum_id AND topic_type = :topic_type " + " AND position >= :position"); query.bindValue(":forum_id", _forumId); + query.bindValue(":topic_type", _type); query.bindValue(":position", position); if (query.exec()) { position += query.numRowsAffected(); // Advance the position counter @@ -173,7 +197,7 @@ void FetchTopicsAction::handleFinishedCall() db.commit(); if (position > _start) { - _board->notifyForumTopicsChanged(_forumId, + _board->notifyForumTopicsChanged(_forumId, _type, _start, position - 1); } if (_end == FetchAllTopics && !eof) { @@ -181,6 +205,7 @@ void FetchTopicsAction::handleFinishedCall() // there are probably more of them int next_start = fetched_end + 1; _board->enqueueAction(new FetchTopicsAction(_forumId, + _type, next_start, FetchAllTopics, _board)); @@ -204,9 +229,11 @@ QList FetchTopicsAction::getCurrentDbTopics(int start, int end) { QSqlQuery query(_board->database()); query.prepare("SELECT topic_id FROM topics " - "WHERE forum_id = :forum_id AND position BETWEEN :start AND :end " + "WHERE forum_id = :forum_id AND topic_type = :topic_type AND " + " position BETWEEN :start AND :end " "ORDER by position ASC"); query.bindValue(":forum_id", _forumId); + query.bindValue(":topic_type", _type); query.bindValue(":start", start); query.bindValue(":end", end); if (query.exec()) { diff --git a/fetchtopicsaction.h b/fetchtopicsaction.h index 307e528..f028ccb 100644 --- a/fetchtopicsaction.h +++ b/fetchtopicsaction.h @@ -3,6 +3,8 @@ #include #include + +#include "board.h" #include "action.h" class XmlRpcPendingCall; @@ -11,12 +13,12 @@ class FetchTopicsAction : public Action { Q_OBJECT public: - explicit FetchTopicsAction(int forumId, int start, int end, Board *board); - enum { FetchAllTopics = -1 }; + explicit FetchTopicsAction(int forumId, Board::TopicType type, int start, int end, Board *board); + bool isSupersetOf(Action *action) const; void execute(); @@ -31,6 +33,7 @@ private: private: XmlRpcPendingCall *_call; int _forumId; + Board::TopicType _type; int _start; int _end; }; diff --git a/forummodel.cpp b/forummodel.cpp index ea54f8e..14f053f 100644 --- a/forummodel.cpp +++ b/forummodel.cpp @@ -8,7 +8,8 @@ #include "forummodel.h" ForumModel::ForumModel(QObject *parent) : - QAbstractListModel(parent), _board(0), _forumId(-1), _eof(false) + QAbstractListModel(parent), _board(0), _forumId(-1), + _numAnnouncements(0), _numSticky(0), _eof(false) { QHash roles = roleNames(); roles[TitleRole] = QByteArray("title"); @@ -27,15 +28,15 @@ Board * ForumModel::board() const void ForumModel::setBoard(Board *board) { if (_board != board) { - disconnect(this, SLOT(handleForumTopicsChanged(int,int,int))); + disconnect(this, SLOT(handleForumTopicsChanged(int,Board::TopicType,int,int))); disconnect(this, SLOT(handleForumTopicChanged(int,int))); clearModel(); _board = board; if (_board) { - connect(_board, SIGNAL(forumTopicsChanged(int,int,int)), - SLOT(handleForumTopicsChanged(int,int,int))); + connect(_board, SIGNAL(forumTopicsChanged(int,Board::TopicType,int,int)), + SLOT(handleForumTopicsChanged(int,Board::TopicType,int,int))); connect(_board, SIGNAL(forumTopicChanged(int,int)), SLOT(handleForumTopicChanged(int,int))); if (_forumId >= 0) { @@ -86,6 +87,8 @@ QVariant ForumModel::data(const QModelIndex &index, int role) const return _data[row].title; case TopicIdRole: return _data[row].topic_id; + case TopicTypeRole: + return _data[row].type; case NumRepliesRole: return _data[row].num_replies; case UnreadRole: @@ -107,15 +110,18 @@ void ForumModel::fetchMore(const QModelIndex &parent) if (!_board || _forumId < 0) return; if (_eof) return; - const int start = _data.size(); - QList topics = loadTopics(start, start + FORUM_PAGE_SIZE - 1); - const int new_end = start + topics.size() - 1; + const int normal_offset = _numAnnouncements + _numSticky; + const int normal_start = _data.size() - normal_offset; + QList topics = loadTopics(Board::Normal, + normal_start, normal_start + FORUM_PAGE_SIZE - 1); + const int normal_new_end = normal_start + topics.size() - 1; if (topics.empty()) { // We could not load anything more from DB! _eof = true; } else { - beginInsertRows(QModelIndex(), start, new_end); + beginInsertRows(QModelIndex(), + normal_offset + normal_start, normal_offset + normal_new_end); _data.append(topics); _eof = topics.size() < FORUM_PAGE_SIZE; // If short read, we reached EOF. endInsertRows(); @@ -127,10 +133,11 @@ void ForumModel::fetchMore(const QModelIndex &parent) // If the topics we got from DB are too old, refresh online. if (last.secsTo(QDateTime::currentDateTimeUtc()) > FORUM_TOPICS_TLL) { qDebug() << "Fetching topics because of old"; - Q_ASSERT(new_end >= 0); + Q_ASSERT(normal_new_end >= 0); _board->enqueueAction(new FetchTopicsAction(_forumId, - start, - new_end, + Board::Normal, + normal_start, + normal_new_end, _board)); } } @@ -138,9 +145,11 @@ void ForumModel::fetchMore(const QModelIndex &parent) // Try to fetch more topics if board is online and we reached the end of DB if (_eof) { qDebug() << "Fetching topics because of EOF"; + const int normal_cur_end = _data.size() - 1 - normal_offset; _board->enqueueAction(new FetchTopicsAction(_forumId, - _data.size(), - _data.size() + FORUM_PAGE_SIZE - 1, + Board::Normal, + normal_cur_end + 1, + normal_cur_end + FORUM_PAGE_SIZE, _board)); } } @@ -150,6 +159,17 @@ void ForumModel::refresh() { // Forcefully refresh all topics on this forum _board->enqueueAction(new FetchTopicsAction(_forumId, + Board::Announcement, + 0, + FetchTopicsAction::FetchAllTopics, + _board)); + _board->enqueueAction(new FetchTopicsAction(_forumId, + Board::Sticky, + 0, + FetchTopicsAction::FetchAllTopics, + _board)); + _board->enqueueAction(new FetchTopicsAction(_forumId, + Board::Normal, 0, FetchTopicsAction::FetchAllTopics, _board)); @@ -178,10 +198,8 @@ QDateTime ForumModel::lastTopPostUpdate() if (!_board) return QDateTime(); QSqlDatabase db = _board->database(); QSqlQuery query(db); - query.prepare("SELECT last_update_time FROM topics " - "WHERE forum_id = :forum_id " - "ORDER BY position ASC " - "LIMIT 1"); + query.prepare("SELECT MIN(last_update_time) FROM topics " + "WHERE forum_id = :forum_id AND position = 0"); query.bindValue(":forum_id", _forumId); if (query.exec()) { if (query.next()) { @@ -193,15 +211,16 @@ QDateTime ForumModel::lastTopPostUpdate() return QDateTime(); } -QList ForumModel::loadTopics(int start, int end) +QList ForumModel::loadTopics(Board::TopicType type, int start, int end) { Q_ASSERT(_board); QList topics; QSqlQuery query(_board->database()); - query.prepare("SELECT topic_id, topic_title, reply_number, new_post, last_reply_time, last_update_time FROM topics " - "WHERE forum_id = :forum_id AND position BETWEEN :start AND :end " + query.prepare("SELECT topic_id, topic_type, topic_title, reply_number, new_post, last_reply_time, last_update_time FROM topics " + "WHERE forum_id = :forum_id AND topic_type = :topic_type AND position BETWEEN :start AND :end " "ORDER by position ASC "); query.bindValue(":forum_id", _forumId); + query.bindValue(":topic_type", type); query.bindValue(":start", start); query.bindValue(":end", end); if (query.exec()) { @@ -209,11 +228,12 @@ QList ForumModel::loadTopics(int start, int end) while (query.next()) { Topic topic; topic.topic_id = query.value(0).toInt(); - topic.title = query.value(1).toString(); - topic.num_replies = query.value(2).toInt(); - topic.unread = query.value(3).toBool(); - topic.last_reply_time = parseDateTime(query.value(4)); - topic.last_update_time = parseDateTime(query.value(5)); + topic.type = type; + topic.title = query.value(2).toString(); + topic.num_replies = query.value(3).toInt(); + topic.unread = query.value(4).toBool(); + topic.last_reply_time = parseDateTime(query.value(5)); + topic.last_update_time = parseDateTime(query.value(6)); topics.append(topic); } } else { @@ -230,66 +250,130 @@ void ForumModel::clearModel() endResetModel(); } -void ForumModel::handleForumTopicsChanged(int forumId, int start, int end) +void ForumModel::handleForumTopicsChanged(int forumId, Board::TopicType type, + int start, int end) { - if (forumId == _forumId) { + if (forumId != _forumId) { + return; // Not our topics + } + if (type == Board::Normal) { // Yep, our topics list changed. + const int normal_offset = _numAnnouncements + _numSticky; + int current_normal_end = _data.size() - 1 - normal_offset; + qDebug() << "My topics changed" << start << end; - if (end > _data.size()) { + + if (end >= current_normal_end) { // If for any reason we have more topics now, it means we might // no longer be EOF... _eof = false; } - if (start > _data.size() + 1) { - // We are still not interested into these topics. + if (start > current_normal_end + 1) { + // On the other hand, if the topics are too far away, + // do not load them until we fetchMore(). qDebug() << "Topics too far"; return; } - QList topics = loadTopics(start, end); + QList topics = loadTopics(Board::Normal, start, end); if (topics.size() < end - start + 1) { _eof = true; // Short read end = start + topics.size() - 1; - if (_data.size() > end + 1) { - beginRemoveRows(QModelIndex(), end + 1, _data.size()); - while (_data.size() > end + 1) { + if (current_normal_end > end) { + const int current_full_end = _data.size() - 1; + const int new_full_end = end + normal_offset; + + Q_ASSERT(new_full_end < current_full_end); + beginRemoveRows(QModelIndex(), + new_full_end, current_full_end); + while (_data.size() > new_full_end) { _data.removeLast(); } + current_normal_end = _data.size() - 1 - normal_offset; + Q_ASSERT(current_normal_end == end); endRemoveRows(); } } - if (end >= _data.size()) { - qDebug() << "Call insert rows" << _data.size() << end; - beginInsertRows(QModelIndex(), _data.size(), end); - _data.reserve(end + 1); - for (int i = start; i < _data.size(); i++) { - _data[i] = topics[i - start]; + if (end > current_normal_end) { + const int current_full_end = _data.size() - 1; + const int new_full_end = end + normal_offset; + qDebug() << "Insert rows" << current_full_end + 1 << new_full_end; + beginInsertRows(QModelIndex(), current_full_end + 1, new_full_end); + _data.reserve(new_full_end + 1); + const int full_start = normal_offset + start; + for (int i = full_start; i <= current_full_end; i++) { + _data[i] = topics[i - full_start]; } - for (int i = _data.size(); i <= end; i++) { - Q_ASSERT(i >= start); - _data.append(topics[i - start]); + Q_ASSERT(current_full_end + 1 >= full_start); + for (int i = current_full_end + 1; i <= new_full_end; i++) { + _data.append(topics[i - full_start]); } endInsertRows(); - emit dataChanged(createIndex(start, 0), createIndex(_data.size() - 1, 0)); + Q_ASSERT(new_full_end == _data.size() - 1); + emit dataChanged(createIndex(full_start, 0), createIndex(new_full_end, 0)); } else { qDebug() << "Just refresh the data"; - for (int i = start; i < end; i++) { - _data[i] = topics[i - start]; + const int full_start = normal_offset + start; + const int full_end = normal_offset + end; + for (int i = full_start; i < full_end; i++) { + _data[i] = topics[i - full_start]; + } + emit dataChanged(createIndex(full_start, 0), createIndex(full_end, 0)); + } + } else if (type == Board::Sticky || type == Board::Announcement) { + // We just reload these fully + QList topics = loadTopics(type, 0, MAX_FORUM_PAGE_SIZE - 1); + const int offset = type == Board::Sticky ? _numAnnouncements : 0; + int * const cur_number_p = type == Board::Sticky ? &_numSticky : &_numAnnouncements; + const int cur_number = *cur_number_p; + + if (topics.size() < cur_number) { + const int cur_end = offset + cur_number - 1; + const int new_end = offset + topics.size() - 1; + beginRemoveRows(QModelIndex(), new_end + 1, cur_end); + for (int i = new_end + 1; i <= cur_end; i++) { + _data.removeAt(i); + (*cur_number_p)--; + } + endRemoveRows(); + } else if (topics.size() > cur_number) { + const int cur_end = offset + cur_number - 1; + const int new_end = offset + topics.size() - 1; + const int new_start = cur_end + 1; + Q_ASSERT(new_end - offset == topics.size() - 1); + beginInsertRows(QModelIndex(), new_start, new_end); + for (int i = new_start; i <= new_end; i++) { + _data.insert(i, topics.takeAt(new_start - offset)); + (*cur_number_p)++; } - emit dataChanged(createIndex(start, 0), createIndex(end, 0)); + endInsertRows(); + Q_ASSERT(topics.size() == cur_number); + } + + const int start = offset; + const int end = offset + topics.size() - 1; + for (int i = start; i <= end; i++) { + _data.insert(i, topics.at(i - offset)); } + emit dataChanged(createIndex(start, 0), createIndex(end, 0)); } } void ForumModel::handleForumTopicChanged(int forumId, int topicId) { if (forumId == _forumId) { + Board::TopicType type = Board::Announcement; + int pos = 0; for (int i = 0; i < _data.size(); i++) { Topic& topic = _data[i]; + if (topic.type != type) { + type = topic.type; + pos = 0; + } if (topic.topic_id == topicId) { // Need to refresh this topic - QList topics = loadTopics(i, i); + QList topics = loadTopics(type, pos, pos); if (topics.size() == 1) { _data[i] = topics[0]; emit dataChanged(createIndex(i, 0), createIndex(i, 0)); @@ -297,6 +381,7 @@ void ForumModel::handleForumTopicChanged(int forumId, int topicId) qWarning() << "Topic changed yet not in DB"; } } + pos++; } } } @@ -311,7 +396,12 @@ void ForumModel::update() last.secsTo(QDateTime::currentDateTimeUtc()) > FORUM_TOP_TLL) { // Outdated or empty, refresh. qDebug() << "Fetching topics because the top are old"; - _board->enqueueAction(new FetchTopicsAction(_forumId, 0, FORUM_PAGE_SIZE - 1, _board)); + _board->enqueueAction(new FetchTopicsAction(_forumId, Board::Announcement, + 0, FORUM_PAGE_SIZE - 1, _board)); + _board->enqueueAction(new FetchTopicsAction(_forumId, Board::Sticky, + 0, FORUM_PAGE_SIZE - 1, _board)); + _board->enqueueAction(new FetchTopicsAction(_forumId, Board::Normal, + 0, FORUM_PAGE_SIZE - 1, _board)); } else { qDebug() << "Topics not outdated"; } @@ -321,6 +411,28 @@ void ForumModel::reload() { Q_ASSERT(_data.empty()); Q_ASSERT(!_eof); - // Fetch an initial bunch of topics + // Load announcements / sticky topics fully + QList topics; + topics = loadTopics(Board::Announcement, 0, MAX_FORUM_PAGE_SIZE - 1); + if (!topics.empty()) { + beginInsertRows(QModelIndex(), 0, topics.size() - 1); + _data.append(topics); + _numAnnouncements = topics.size(); + endInsertRows(); + } else { + _numAnnouncements = 0; + } + + topics = loadTopics(Board::Sticky, 0, MAX_FORUM_PAGE_SIZE - 1); + if (!topics.empty()) { + beginInsertRows(QModelIndex(), _numAnnouncements, _numAnnouncements + topics.size() - 1); + _data.append(topics); + _numSticky = topics.size(); + endInsertRows(); + } else { + _numSticky = 0; + } + + // Fetch an initial bunch of normal topics fetchMore(); } diff --git a/forummodel.h b/forummodel.h index 33a718e..709f5c4 100644 --- a/forummodel.h +++ b/forummodel.h @@ -5,7 +5,7 @@ #include #include -class Board; +#include "board.h" class ForumModel : public QAbstractListModel { @@ -48,6 +48,7 @@ signals: protected: struct Topic { int topic_id; + Board::TopicType type; QString title; int num_replies; bool unread; @@ -59,11 +60,11 @@ private: static QDateTime parseDateTime(const QVariant& v); static QDateTime oldestPostUpdate(const QList& topics); QDateTime lastTopPostUpdate(); - QList loadTopics(int start, int end); + QList loadTopics(Board::TopicType type, int start, int end); void clearModel(); private slots: - void handleForumTopicsChanged(int forumId, int start, int end); + void handleForumTopicsChanged(int forumId, Board::TopicType type, int start, int end); void handleForumTopicChanged(int forumId, int topicId); void update(); void reload(); @@ -72,6 +73,8 @@ private: Board *_board; int _forumId; QList _data; + int _numAnnouncements; + int _numSticky; bool _eof; }; diff --git a/newtopicaction.cpp b/newtopicaction.cpp index b984c15..6d030e6 100644 --- a/newtopicaction.cpp +++ b/newtopicaction.cpp @@ -45,6 +45,7 @@ void NewTopicAction::handleFinishedCall() } else { // Refresh topics _board->enqueueAction(new FetchTopicsAction(_forumId, + Board::Normal, 0, FORUM_PAGE_SIZE, _board)); -- cgit v1.2.3