summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board.cpp11
-rw-r--r--boardmodel.cpp1
-rw-r--r--fetchpostsaction.cpp26
-rw-r--r--fetchpostsaction.h4
-rw-r--r--fetchtopicsaction.cpp31
-rw-r--r--fetchtopicsaction.h4
-rw-r--r--forummodel.cpp14
-rw-r--r--forummodel.h7
-rw-r--r--global.h6
-rw-r--r--qml/tapasboard/BoardPage.qml20
-rw-r--r--qml/tapasboard/ForumPage.qml20
-rw-r--r--qml/tapasboard/TopicPage.qml20
-rw-r--r--topicmodel.cpp9
-rw-r--r--topicmodel.h3
14 files changed, 157 insertions, 19 deletions
diff --git a/board.cpp b/board.cpp
index 2cad565..d8660ef 100644
--- a/board.cpp
+++ b/board.cpp
@@ -215,10 +215,13 @@ QString Board::renderHumanTime(const QDateTime &dateTime)
void Board::cancelAllActions()
{
- disconnect(this, SLOT(handleActionFinished(Action*)));
- while (!_queue.isEmpty()) {
- Action *action = _queue.dequeue();
- delete action;
+ if (!_queue.isEmpty()) {
+ disconnect(this, SLOT(handleActionFinished(Action*)));
+ while (!_queue.isEmpty()) {
+ Action *action = _queue.dequeue();
+ delete action;
+ }
+ emit busyChanged();
}
}
diff --git a/boardmodel.cpp b/boardmodel.cpp
index 7454d6f..dc1757e 100644
--- a/boardmodel.cpp
+++ b/boardmodel.cpp
@@ -119,6 +119,7 @@ void BoardModel::fetchMore(const QModelIndex &parent)
void BoardModel::refresh()
{
+ // Forcefully refresh the forums list
if (_board) {
_board->enqueueAction(new FetchForumsAction(_board));
}
diff --git a/fetchpostsaction.cpp b/fetchpostsaction.cpp
index 0e4284b..2493aa3 100644
--- a/fetchpostsaction.cpp
+++ b/fetchpostsaction.cpp
@@ -3,6 +3,7 @@
#include <QtSql/QSqlDatabase>
#include <QtSql/QSqlQuery>
+#include "global.h"
#include "board.h"
#include "xmlrpcinterface.h"
#include "xmlrpcreply.h"
@@ -18,7 +19,15 @@ bool FetchPostsAction::isSupersetOf(Action *action) const
FetchPostsAction *other = qobject_cast<FetchPostsAction*>(action);
if (other) {
if (other->_topicId == _topicId) {
- if (_start <= other->_start && _end >= other->_end) {
+ if (_end == FetchAllPosts) {
+ // If this is fetching all posts, then this is a superset
+ // of every other action... except those that also fetch all.
+ return other->_end != FetchAllPosts;
+ } else if (other->_end == FetchAllPosts) {
+ // If the other action fetches all posts, this cannot be a
+ // superset
+ return false;
+ } else if (_start <= other->_start && _end >= other->_end) {
return true;
}
}
@@ -28,8 +37,15 @@ bool FetchPostsAction::isSupersetOf(Action *action) const
void FetchPostsAction::execute()
{
+ int end = _end;
+ if (end == FetchAllPosts) {
+ // Fetch posts in blocks of size 50.
+ end = _start + MAX_TOPIC_PAGE_SIZE;
+ // After finishing this action, a new one will be enqueued with the next 50.
+ }
+
_call = _board->service()->asyncCall("get_thread",
- QString::number(_topicId), _start, _end);
+ QString::number(_topicId), _start, end);
_call->setParent(this);
connect(_call, SIGNAL(finished(XmlRpcPendingCall*)), SLOT(handleFinishedCall()));
}
@@ -84,6 +100,12 @@ void FetchPostsAction::handleFinishedCall()
_board->notifyTopicPostsChanged(_topicId,
_start, _start + posts.size() - 1);
}
+ if (_end == FetchAllPosts && posts.size() == MAX_TOPIC_PAGE_SIZE) {
+ // Ok, let's prepare to fetch the next block of posts because
+ // there are probably more of them
+ int start = _start + MAX_TOPIC_PAGE_SIZE;
+ _board->enqueueAction(new FetchPostsAction(_topicId, start, FetchAllPosts, _board));
+ }
} else {
qWarning() << "Could not fetch posts";
// TODO emit error ...
diff --git a/fetchpostsaction.h b/fetchpostsaction.h
index 9951989..732c0d2 100644
--- a/fetchpostsaction.h
+++ b/fetchpostsaction.h
@@ -13,6 +13,10 @@ class FetchPostsAction : public Action
public:
explicit FetchPostsAction(int topicId, int start, int end, Board *board);
+ enum {
+ FetchAllPosts = -1
+ };
+
bool isSupersetOf(Action *action) const;
void execute();
diff --git a/fetchtopicsaction.cpp b/fetchtopicsaction.cpp
index ead8d4d..bc94965 100644
--- a/fetchtopicsaction.cpp
+++ b/fetchtopicsaction.cpp
@@ -3,6 +3,7 @@
#include <QtSql/QSqlDatabase>
#include <QtSql/QSqlQuery>
+#include "global.h"
#include "board.h"
#include "xmlrpcinterface.h"
#include "xmlrpcreply.h"
@@ -18,7 +19,18 @@ bool FetchTopicsAction::isSupersetOf(Action *action) const
FetchTopicsAction *other = qobject_cast<FetchTopicsAction*>(action);
if (other) {
if (other->_forumId == _forumId) {
- if (_start <= other->_start && _end >= other->_end) {
+ if (_end == FetchAllTopics) {
+ // If this is fetching all topics, then this is a superset
+ // of every other action... except those that also fetch all
+ // topics.
+ return other->_end != FetchAllTopics;
+ } else if (other->_end == FetchAllTopics) {
+ // If the other action fetches all topics, this cannot be a
+ // superset
+ return false;
+ } else if (_start <= other->_start && _end >= other->_end) {
+ // Otherwise, check if the range of posts fetched by this
+ // action fully contains the other action.
return true;
}
}
@@ -28,8 +40,15 @@ bool FetchTopicsAction::isSupersetOf(Action *action) const
void FetchTopicsAction::execute()
{
+ int end = _end;
+ if (end == FetchAllTopics) {
+ // Fetch topics in blocks of size 50.
+ end = _start + MAX_FORUM_PAGE_SIZE;
+ // 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);
+ QString::number(_forumId), _start, end);
_call->setParent(this);
connect(_call, SIGNAL(finished(XmlRpcPendingCall*)), SLOT(handleFinishedCall()));
}
@@ -85,8 +104,12 @@ void FetchTopicsAction::handleFinishedCall()
if (topics.size() > 0) {
_board->notifyForumTopicsChanged(_forumId,
_start, _start + topics.size() - 1);
- } else {
- qWarning() << "Asked for topics, got none...";
+ }
+ if (_end == FetchAllTopics && topics.size() == MAX_FORUM_PAGE_SIZE) {
+ // Ok, let's prepare to fetch the next block of topics because
+ // there are probably more of them
+ int start = _start + MAX_FORUM_PAGE_SIZE;
+ _board->enqueueAction(new FetchTopicsAction(_forumId, start, FetchAllTopics, _board));
}
} else {
qWarning() << "Could not fetch topics";
diff --git a/fetchtopicsaction.h b/fetchtopicsaction.h
index 0b02fa3..9c12784 100644
--- a/fetchtopicsaction.h
+++ b/fetchtopicsaction.h
@@ -13,6 +13,10 @@ class FetchTopicsAction : public Action
public:
explicit FetchTopicsAction(int forumId, int start, int end, Board *board);
+ enum {
+ FetchAllTopics = -1
+ };
+
bool isSupersetOf(Action *action) const;
void execute();
diff --git a/forummodel.cpp b/forummodel.cpp
index bdc2d17..4d59916 100644
--- a/forummodel.cpp
+++ b/forummodel.cpp
@@ -14,6 +14,7 @@ ForumModel::ForumModel(QObject *parent) :
roles[TitleRole] = QByteArray("title");
roles[IconRole] = QByteArray("icon");
roles[TopicIdRole] = QByteArray("topicId");
+ roles[NumPostsRole] = QByteArray("numPosts");
setRoleNames(roles);
}
@@ -79,10 +80,10 @@ QVariant ForumModel::data(const QModelIndex &index, int role) const
switch (role) {
case TitleRole:
return _data[row].title;
- break;
case TopicIdRole:
return _data[row].topic_id;
- break;
+ case NumPostsRole:
+ return _data[row].num_replies;
}
return QVariant();
@@ -138,6 +139,15 @@ void ForumModel::fetchMore(const QModelIndex &parent)
}
}
+void ForumModel::refresh()
+{
+ // Forcefully refresh all topics on this forum
+ _board->enqueueAction(new FetchTopicsAction(_forumId,
+ 0,
+ FetchTopicsAction::FetchAllTopics,
+ _board));
+}
+
QDateTime ForumModel::parseDateTime(const QVariant &v)
{
QString s = v.toString();
diff --git a/forummodel.h b/forummodel.h
index 5a84f64..0458cfd 100644
--- a/forummodel.h
+++ b/forummodel.h
@@ -21,7 +21,8 @@ public:
IconRole = Qt::DecorationRole,
TopicIdRole = Qt::UserRole,
- TopicTypeRole
+ TopicTypeRole,
+ NumPostsRole
};
Board * board() const;
@@ -36,6 +37,9 @@ public:
bool canFetchMore(const QModelIndex &parent = QModelIndex()) const;
void fetchMore(const QModelIndex &parent = QModelIndex());
+public slots:
+ void refresh();
+
signals:
void boardChanged();
void forumIdChanged();
@@ -44,6 +48,7 @@ protected:
struct Topic {
int topic_id;
QString title;
+ int num_replies;
QDateTime last_reply_time;
QDateTime last_update_time;
};
diff --git a/global.h b/global.h
index 3b1d6ae..694dce0 100644
--- a/global.h
+++ b/global.h
@@ -21,6 +21,9 @@
/** Number of topics per "block" in subforum view */
#define FORUM_PAGE_SIZE 20
+/** This is the absolute maximum page size the API will allow. */
+#define MAX_FORUM_PAGE_SIZE 50
+
/** Time we should consider the most recent posts in a topic up to date, in seconds. */
#define TOPIC_TOP_TLL 5 * 60
@@ -30,6 +33,9 @@
/** Number of posts per "block" in topic view */
#define TOPIC_PAGE_SIZE 20
+/** This is the absolute maximum page size the API will allow. */
+#define MAX_TOPIC_PAGE_SIZE 50
+
// Some singletons
extern BoardManager *board_manager;
diff --git a/qml/tapasboard/BoardPage.qml b/qml/tapasboard/BoardPage.qml
index dd1bd24..7efc6db 100644
--- a/qml/tapasboard/BoardPage.qml
+++ b/qml/tapasboard/BoardPage.qml
@@ -14,17 +14,26 @@ Page {
tools: ToolBarLayout {
ToolIcon {
- id: backToolIcon
platformIconId: "toolbar-back"
- anchors.left: parent.left
onClicked: pageStack.pop()
}
+ ToolIcon {
+ platformIconId: board.busy ? "toolbar-cancle" : "toolbar-refresh"
+ onClicked: {
+ if (board.busy) {
+ board.cancelAllActions();
+ } else {
+ boardModel.refresh();
+ }
+ }
+ }
}
ListView {
id: forumsView
anchors.fill: parent
model: BoardModel {
+ id: boardModel
board: boardPage.board
forumId: boardPage.forumId
}
@@ -87,4 +96,11 @@ Page {
ScrollDecorator {
flickableItem: forumsView
}
+
+ BusyIndicator {
+ anchors.centerIn: parent
+ platformStyle: BusyIndicatorStyle { size: "large" }
+ visible: forumsView.count == 0 && board.busy
+ running: visible
+ }
}
diff --git a/qml/tapasboard/ForumPage.qml b/qml/tapasboard/ForumPage.qml
index 18953cb..aed65a0 100644
--- a/qml/tapasboard/ForumPage.qml
+++ b/qml/tapasboard/ForumPage.qml
@@ -14,17 +14,26 @@ Page {
tools: ToolBarLayout {
ToolIcon {
- id: backToolIcon
platformIconId: "toolbar-back"
- anchors.left: parent.left
onClicked: pageStack.pop()
}
+ ToolIcon {
+ platformIconId: board.busy ? "toolbar-cancle" : "toolbar-refresh"
+ onClicked: {
+ if (board.busy) {
+ board.cancelAllActions();
+ } else {
+ forumModel.refresh();
+ }
+ }
+ }
}
ListView {
id: topicsView
anchors.fill: parent
model: ForumModel {
+ id: forumModel
board: forumPage.board
forumId: forumPage.forumId
}
@@ -66,4 +75,11 @@ Page {
ScrollDecorator {
flickableItem: topicsView
}
+
+ BusyIndicator {
+ anchors.centerIn: parent
+ platformStyle: BusyIndicatorStyle { size: "large" }
+ visible: topicsView.count == 0 && board.busy
+ running: visible
+ }
}
diff --git a/qml/tapasboard/TopicPage.qml b/qml/tapasboard/TopicPage.qml
index ba132b5..689dce7 100644
--- a/qml/tapasboard/TopicPage.qml
+++ b/qml/tapasboard/TopicPage.qml
@@ -14,17 +14,26 @@ Page {
tools: ToolBarLayout {
ToolIcon {
- id: backToolIcon
platformIconId: "toolbar-back"
- anchors.left: parent.left
onClicked: pageStack.pop()
}
+ ToolIcon {
+ platformIconId: board.busy ? "toolbar-cancle" : "toolbar-refresh"
+ onClicked: {
+ if (board.busy) {
+ board.cancelAllActions();
+ } else {
+ topicModel.refresh();
+ }
+ }
+ }
}
ListView {
id: postsView
anchors.fill: parent
model: TopicModel {
+ id: topicModel
board: topicPage.board
topicId: topicPage.topicId
}
@@ -103,4 +112,11 @@ Page {
ScrollDecorator {
flickableItem: postsView
}
+
+ BusyIndicator {
+ anchors.centerIn: parent
+ platformStyle: BusyIndicatorStyle { size: "large" }
+ visible: postsView.count == 0 && board.busy
+ running: visible
+ }
}
diff --git a/topicmodel.cpp b/topicmodel.cpp
index 965481f..c058a6a 100644
--- a/topicmodel.cpp
+++ b/topicmodel.cpp
@@ -156,6 +156,15 @@ void TopicModel::fetchMore(const QModelIndex &parent)
}
}
+void TopicModel::refresh()
+{
+ // Forcefully refresh all posts on this topic
+ _board->enqueueAction(new FetchPostsAction(_topicId,
+ 0,
+ FetchPostsAction::FetchAllPosts,
+ _board));
+}
+
QDateTime TopicModel::parseDbDateTime(const QVariant &v)
{
QString s = v.toString();
diff --git a/topicmodel.h b/topicmodel.h
index 6f1e99f..0151242 100644
--- a/topicmodel.h
+++ b/topicmodel.h
@@ -41,6 +41,9 @@ public:
bool canFetchMore(const QModelIndex &parent = QModelIndex()) const;
void fetchMore(const QModelIndex &parent = QModelIndex());
+public slots:
+ void refresh();
+
signals:
void boardChanged();
void topicIdChanged();