summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJavier S. Pedro <maemo@javispedro.com>2013-04-04 00:00:38 +0200
committerJavier S. Pedro <maemo@javispedro.com>2013-04-04 00:00:38 +0200
commit5d8d6fed3fd7dd796a5a3093a7dbd46fab8d380a (patch)
tree56d1aa55260d0081cfd99b52c53f5ddc78cba200
parenta6d8b23fd03993c0b94d21806ac3a36e251c8b9c (diff)
downloadtapasboard-5d8d6fed3fd7dd796a5a3093a7dbd46fab8d380a.tar.gz
tapasboard-5d8d6fed3fd7dd796a5a3093a7dbd46fab8d380a.zip
pass Board objects instead of boardUrls around QML
-rw-r--r--board.cpp82
-rw-r--r--board.h41
-rw-r--r--boardmanager.cpp18
-rw-r--r--boardmanager.h5
-rw-r--r--boardmodel.cpp52
-rw-r--r--boardmodel.h24
-rw-r--r--favoritesmodel.cpp2
-rw-r--r--favoritesmodel.h5
-rw-r--r--fetchconfigaction.cpp1
-rw-r--r--fetchforumsaction.cpp1
-rw-r--r--fetchpostsaction.cpp1
-rw-r--r--fetchtopicsaction.cpp1
-rw-r--r--forummodel.cpp23
-rw-r--r--forummodel.h9
-rw-r--r--loginaction.cpp50
-rw-r--r--loginaction.h28
-rw-r--r--main.cpp4
-rw-r--r--qml/tapasboard/BoardPage.qml14
-rw-r--r--qml/tapasboard/ForumPage.qml6
-rw-r--r--qml/tapasboard/MainPage.qml7
-rw-r--r--qml/tapasboard/TopicPage.qml4
-rw-r--r--tapasboard.pro6
-rw-r--r--topicmodel.cpp23
-rw-r--r--topicmodel.h9
24 files changed, 313 insertions, 103 deletions
diff --git a/board.cpp b/board.cpp
index 2df4711..1a82a91 100644
--- a/board.cpp
+++ b/board.cpp
@@ -12,8 +12,13 @@
const QLatin1String Board::CURRENT_DB_VERSION("testing2");
-Board::Board(const QString& forumUrl, QObject *parent) :
- QObject(parent), _url(forumUrl), _slug(createSlug(forumUrl)),
+Board::Board(QObject *parent) :
+ QObject(parent)
+{
+}
+
+Board::Board(const QUrl& url, const QString& username, const QString& password, QObject *parent) :
+ QObject(parent), _url(url), _slug(createSlug(url)),
_db(QSqlDatabase::addDatabase("QSQLITE", _slug)),
_iface(new XmlRpcInterface(QUrl(_url), this))
{
@@ -35,6 +40,9 @@ Board::Board(const QString& forumUrl, QObject *parent) :
initializeDb();
}
fetchConfigIfOutdated();
+ if (!username.isEmpty()) {
+ login(username, password);
+ }
fetchForumsIfOutdated();
initializeBbCode(); // TODO This might depend on board config
initializeSmilies();
@@ -43,7 +51,9 @@ Board::Board(const QString& forumUrl, QObject *parent) :
Board::~Board()
{
disconnect(this, SLOT(handleActionFinished(Action*)));
- QSqlDatabase::removeDatabase(_slug);
+ if (!_slug.isEmpty()) {
+ QSqlDatabase::removeDatabase(_slug);
+ }
}
void Board::enqueueAction(Action *action)
@@ -68,6 +78,7 @@ void Board::enqueueAction(Action *action)
if (_queue.size() == 1) {
// There were no actions queued, so start by executing this one.
executeActionFromQueue();
+ emit busyChanged();
}
}
@@ -98,7 +109,6 @@ QString Board::getConfig(const QString &key) const
void Board::setConfig(const QString &key, const QString &value)
{
-
// Try config cache first
QHash<QString, QString>::const_iterator i = _config.find(key);
if (i != _config.end()) {
@@ -121,6 +131,21 @@ void Board::setConfig(const QString &key, const QString &value)
notifyConfigChanged(key);
}
+QVariant Board::getLoginInfo(const QString &key) const
+{
+ return _loginInfo[key];
+}
+
+void Board::login(const QString &username, const QString &password)
+{
+ // TODO
+}
+
+void Board::logout()
+{
+ // TODO
+}
+
QString Board::removeHtml(QString text) const
{
static const QRegExp regexp("<[a-zA-Z\\/][^>]*>");
@@ -187,6 +212,15 @@ QString Board::renderHumanTime(const QDateTime &dateTime)
return dateTime.toLocalTime().time().toString(Qt::DefaultLocaleShortDate);
}
+void Board::cancelAllActions()
+{
+ disconnect(this, SLOT(handleActionFinished(Action*)));
+ while (!_queue.isEmpty()) {
+ Action *action = _queue.dequeue();
+ delete action;
+ }
+}
+
void Board::notifyConfigChanged(const QString& key)
{
if (!key.isEmpty()) {
@@ -215,12 +249,33 @@ void Board::notifyTopicPostsChanged(int topicId, int start, int end)
emit topicPostsChanged(topicId, start, end);
}
-QString Board::createSlug(const QString &forumUrl)
+void Board::notifyLogin(const QMap<QString, QVariant> &info)
+{
+ if (_loginInfo.empty()) {
+ _loginInfo = info;
+ qDebug() << "Now logged in as" << _loginInfo["username"].toString();
+ emit loggedInChanged();
+ } else {
+ // Double login?
+ _loginInfo = info;
+ }
+}
+
+void Board::notifyLogout()
+{
+ if (!_loginInfo.empty()) {
+ _loginInfo.clear();
+ emit loggedInChanged();
+ }
+}
+
+QString Board::createSlug(const QUrl& url)
{
static const QRegExp regexp("[^a-z0-9]+");
- QString url = forumUrl.toLower();
- url.replace(regexp, "_");
- return url;
+ QString slug = url.toString(QUrl::RemoveScheme | QUrl::RemoveUserInfo | QUrl::StripTrailingSlash);
+ slug = slug.toLower();
+ slug.replace(regexp, "_");
+ return slug;
}
QString Board::getDbPathFor(const QString &slug)
@@ -242,6 +297,12 @@ bool Board::checkCompatibleDb()
bool Board::initializeDb()
{
QSqlQuery q(_db);
+
+ if (!q.exec("PRAGMA synchronous = OFF")) {
+ qWarning() << "Could not disable synchronous flag:" << q.lastError().text();
+ // Not fatal
+ }
+
if (!q.exec("CREATE TABLE IF NOT EXISTS config (key TEXT PRIMARY KEY, value TEXT)")) {
qWarning() << "Could not create config table:" << q.lastError().text();
return false;
@@ -338,6 +399,11 @@ bool Board::removeFromActionQueue(Action *action)
executeActionFromQueue();
}
action->deleteLater();
+ // Don't use delete here because this might be called in response to
+ // error() or finished() QNetworkReply signals.
+ if (_queue.isEmpty()) {
+ emit busyChanged();
+ }
return true;
}
return false;
diff --git a/board.h b/board.h
index deb1dfb..588219c 100644
--- a/board.h
+++ b/board.h
@@ -3,10 +3,11 @@
#include <QtCore/QDateTime>
#include <QtCore/QHash>
-#include <QtCore/QObject>
#include <QtCore/QPair>
#include <QtCore/QRegExp>
#include <QtCore/QQueue>
+#include <QtCore/QUrl>
+#include <QtCore/QVariant>
#include <QtSql/QSqlDatabase>
class Action;
@@ -15,22 +16,36 @@ 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)
+
public:
- explicit Board(const QString& boardUrl, QObject *parent = 0);
+ explicit Board(QObject *parent = 0);
+ Board(const QUrl& url, const QString& username, const QString& password, QObject *parent = 0);
~Board();
static const QLatin1String CURRENT_DB_VERSION;
bool busy() const;
+
void enqueueAction(Action* action);
QSqlDatabase database();
XmlRpcInterface *service();
+ int rootForumId() const;
+
// Configuration table
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();
+
// Some helper functions
QString removeHtml(QString text) const;
QString removeBbcode(QString text) const;
@@ -40,20 +55,27 @@ public:
QString renderHumanDate(const QDateTime& dateTime);
QString renderHumanTime(const QDateTime& dateTime);
+public slots:
+ void cancelAllActions();
+
// These functions wrap emitting the signals below
void notifyConfigChanged(const QString& key = QString());
void notifyForumsChanged();
void notifyForumTopicsChanged(int forumId, int start, int end);
void notifyTopicPostsChanged(int topicId, int start, int end);
+ void notifyLogin(const QMap<QString, QVariant>& info);
+ void notifyLogout();
signals:
+ void busyChanged();
+ void loggedInChanged();
void configChanged(const QString& key);
void forumsChanged();
void forumTopicsChanged(int forumId, int start, int end);
void topicPostsChanged(int topicId, int start, int end);
private:
- static QString createSlug(const QString& forumUrl);
+ static QString createSlug(const QUrl& url);
static QString getDbPathFor(const QString& slug);
static QString getTempDbPathFor(const QString& slug);
bool checkCompatibleDb();
@@ -72,13 +94,14 @@ private slots:
void handleActionError(Action *action, const QString& message);
private:
- QString _url;
+ QUrl _url;
QString _slug;
QSqlDatabase _db;
XmlRpcInterface *_iface;
QQueue<Action*> _queue;
/** Configuration cache */
mutable QHash<QString, QString> _config;
+ QMap<QString, QVariant> _loginInfo;
QList< QPair<QRegExp, QString> > _bbcodes;
QHash<QString, QString> _smilies;
QRegExp _smilieRegexp;
@@ -89,6 +112,16 @@ 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;
diff --git a/boardmanager.cpp b/boardmanager.cpp
index 5fbcf07..ca4dad1 100644
--- a/boardmanager.cpp
+++ b/boardmanager.cpp
@@ -10,15 +10,21 @@ BoardManager::BoardManager(QObject *parent) :
{
}
-Board* BoardManager::getBoard(const QString &url)
+Board* BoardManager::getBoard(const QUrl &url, const QString& username, const QString& password)
{
- QHash<QString, Board*>::iterator i = _boards.find(url);
+ Board *b;
+ QHash<QUrl, Board*>::iterator i = _boards.find(url);
if (i != _boards.end()) {
- return i.value();
+ b = i.value();
+ if (!b->loggedIn() && !username.isEmpty()) {
+ // If requested to login but wasn't before, login now.
+ b->login(username, password);
+ }
+ } else {
+ b = new Board(url, username, password, this);
+ _boards.insert(url, b);
}
- Board *db = new Board(url, this);
- _boards.insert(url, db);
- return db;
+ return b;
}
QString BoardManager::getCachePath() const
diff --git a/boardmanager.h b/boardmanager.h
index 30ebafc..fcbfa3d 100644
--- a/boardmanager.h
+++ b/boardmanager.h
@@ -3,6 +3,7 @@
#include <QtCore/QObject>
#include <QtCore/QHash>
+#include <QtCore/QUrl>
class Board;
@@ -12,12 +13,12 @@ class BoardManager : public QObject
public:
explicit BoardManager(QObject *parent = 0);
- Board *getBoard(const QString& url);
+ Q_INVOKABLE Board *getBoard(const QUrl& url, const QString& username = QString(), const QString& password = QString());
QString getCachePath() const;
private:
- QHash<QString, Board*> _boards;
+ QHash<QUrl, Board*> _boards;
};
diff --git a/boardmodel.cpp b/boardmodel.cpp
index c2421f7..c8d8bd3 100644
--- a/boardmodel.cpp
+++ b/boardmodel.cpp
@@ -3,11 +3,11 @@
#include "global.h"
#include "board.h"
+#include "fetchforumsaction.h"
#include "boardmodel.h"
BoardModel::BoardModel(QObject *parent) :
- QAbstractListModel(parent),
- _rootForumId(0)
+ QAbstractListModel(parent), _board(0), _forumId(-1)
{
QHash<int, QByteArray> roles = roleNames();
roles[NameRole] = QByteArray("title");
@@ -19,32 +19,35 @@ BoardModel::BoardModel(QObject *parent) :
setRoleNames(roles);
}
-QString BoardModel::boardUrl() const
+Board * BoardModel::board() const
{
- return _boardUrl;
+ return _board;
}
-void BoardModel::setBoardUrl(const QString &url)
+void BoardModel::setBoard(Board *board)
{
- if (_boardUrl != url) {
+ if (_board != board) {
disconnect(this, SLOT(reload()));
- _boardUrl = url;
+ _board = board;
+ if (_board) {
+ connect(board, SIGNAL(forumsChanged()), SLOT(reload()));
+ }
reload();
- emit boardUrlChanged();
+ emit boardChanged();
}
}
-int BoardModel::rootForumId() const
+int BoardModel::forumId() const
{
- return _rootForumId;
+ return _forumId;
}
-void BoardModel::setRootForumId(const int id)
+void BoardModel::setForumId(const int id)
{
- if (_rootForumId != id) {
- _rootForumId = id;
+ if (_forumId != id) {
+ _forumId = id;
reload();
- emit rootForumIdChanged();
+ emit forumIdChanged();
}
}
@@ -56,6 +59,7 @@ int BoardModel::rowCount(const QModelIndex &parent) const
QVariant BoardModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid()) return QVariant();
+ if (!_board) return QVariant();
if (!_query.seek(index.row())) {
qWarning() << "Could not seek to" << index.row();
return QVariant();
@@ -113,6 +117,13 @@ void BoardModel::fetchMore(const QModelIndex &parent)
}
}
+void BoardModel::refresh()
+{
+ if (_board) {
+ _board->enqueueAction(new FetchForumsAction(_board));
+ }
+}
+
void BoardModel::reload()
{
beginResetModel();
@@ -120,22 +131,21 @@ void BoardModel::reload()
_records = 0;
_query.clear();
- if (!_boardUrl.isEmpty()) {
- Board *board = board_manager->getBoard(_boardUrl);
- connect(board, SIGNAL(forumsChanged()), SLOT(reload()));
- _query = QSqlQuery(board->database());
+ if (_board && _forumId >= 0) {
+ qDebug() << "Reloading" << _board << _forumId;
+ _query = QSqlQuery(_board->database());
_query.prepare("SELECT f1.forum_id,f1.forum_name,f1.logo_url,f1.description,f1.sub_only,f2.forum_name AS cat_name FROM forums f1 "
"LEFT JOIN forums f2 ON f2.forum_id = f1.parent_id "
"WHERE (f1.parent_id=:parent_id_1 AND f1.sub_only = 0) OR f1.parent_id IN "
"(SELECT forum_id from forums WHERE parent_id=:parent_id_2 AND sub_only=1) "
"ORDER by f1.sort_index ASC;");
- _query.bindValue(0, _rootForumId);
- _query.bindValue(1, _rootForumId);
+ _query.bindValue(0, _forumId);
+ _query.bindValue(1, _forumId);
if (!_query.exec()) {
qWarning() << "Coult not select forums: " << _query.lastError().text();
}
}
endResetModel();
- fetchMore();
+ fetchMore(); // So that at least a few rows are sent
}
diff --git a/boardmodel.h b/boardmodel.h
index 3662642..56d127d 100644
--- a/boardmodel.h
+++ b/boardmodel.h
@@ -9,8 +9,8 @@ class Board;
class BoardModel : public QAbstractListModel
{
Q_OBJECT
- Q_PROPERTY(QString boardUrl READ boardUrl WRITE setBoardUrl NOTIFY boardUrlChanged)
- Q_PROPERTY(int rootForumId READ rootForumId WRITE setRootForumId NOTIFY rootForumIdChanged)
+ Q_PROPERTY(Board * board READ board WRITE setBoard NOTIFY boardChanged)
+ Q_PROPERTY(int forumId READ forumId WRITE setForumId NOTIFY forumIdChanged)
public:
BoardModel(QObject *parent = 0);
@@ -25,11 +25,11 @@ public:
CategoryRole
};
- QString boardUrl() const;
- void setBoardUrl(const QString& url);
+ Board * board() const;
+ void setBoard(Board *board);
- int rootForumId() const;
- void setRootForumId(const int id);
+ int forumId() const;
+ void setForumId(const int id);
int rowCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role) const;
@@ -37,16 +37,20 @@ public:
bool canFetchMore(const QModelIndex &parent = QModelIndex()) const;
void fetchMore(const QModelIndex &parent = QModelIndex());
+public slots:
+ void refresh();
+
signals:
- void boardUrlChanged();
- void rootForumIdChanged();
+ void boardChanged();
+ void forumIdChanged();
private slots:
void reload();
private:
- QString _boardUrl;
- int _rootForumId;
+ Board *_board;
+ int _forumId;
+
mutable QSqlQuery _query;
int _records;
bool _eof;
diff --git a/favoritesmodel.cpp b/favoritesmodel.cpp
index de4bf2d..5c0f51a 100644
--- a/favoritesmodel.cpp
+++ b/favoritesmodel.cpp
@@ -55,7 +55,7 @@ void FavoritesModel::load()
settings.setArrayIndex(i);
FavoriteBoard board;
board.name = settings.value("name").toString();
- board.url = settings.value("url").toString();
+ board.url = settings.value("url").toUrl();
_boards.append(board);
}
settings.endArray();
diff --git a/favoritesmodel.h b/favoritesmodel.h
index 59959d4..a18b1dc 100644
--- a/favoritesmodel.h
+++ b/favoritesmodel.h
@@ -2,6 +2,7 @@
#define FAVORITESMODEL_H
#include <QtCore/QAbstractListModel>
+#include <QtCore/QUrl>
class FavoritesModel : public QAbstractListModel
{
@@ -22,7 +23,9 @@ public:
protected:
struct FavoriteBoard {
QString name;
- QString url;
+ QUrl url;
+ QString username;
+ QString password;
};
private:
diff --git a/fetchconfigaction.cpp b/fetchconfigaction.cpp
index 8c0ac63..787810c 100644
--- a/fetchconfigaction.cpp
+++ b/fetchconfigaction.cpp
@@ -21,6 +21,7 @@ bool FetchConfigAction::isSupersetOf(Action *action) const
void FetchConfigAction::execute()
{
_call = _board->service()->asyncCall("get_config");
+ _call->setParent(this);
connect(_call, SIGNAL(finished(XmlRpcPendingCall*)), SLOT(handleFinishedCall()));
}
diff --git a/fetchforumsaction.cpp b/fetchforumsaction.cpp
index 7b496c3..53f1f12 100644
--- a/fetchforumsaction.cpp
+++ b/fetchforumsaction.cpp
@@ -22,6 +22,7 @@ bool FetchForumsAction::isSupersetOf(Action *action) const
void FetchForumsAction::execute()
{
_call = _board->service()->asyncCall("get_forum");
+ _call->setParent(this);
connect(_call, SIGNAL(finished(XmlRpcPendingCall*)), SLOT(handleFinishedCall()));
}
diff --git a/fetchpostsaction.cpp b/fetchpostsaction.cpp
index 7ed9140..0e4284b 100644
--- a/fetchpostsaction.cpp
+++ b/fetchpostsaction.cpp
@@ -30,6 +30,7 @@ void FetchPostsAction::execute()
{
_call = _board->service()->asyncCall("get_thread",
QString::number(_topicId), _start, _end);
+ _call->setParent(this);
connect(_call, SIGNAL(finished(XmlRpcPendingCall*)), SLOT(handleFinishedCall()));
}
diff --git a/fetchtopicsaction.cpp b/fetchtopicsaction.cpp
index 31a507a..ead8d4d 100644
--- a/fetchtopicsaction.cpp
+++ b/fetchtopicsaction.cpp
@@ -30,6 +30,7 @@ void FetchTopicsAction::execute()
{
_call = _board->service()->asyncCall("get_topic",
QString::number(_forumId), _start, _end);
+ _call->setParent(this);
connect(_call, SIGNAL(finished(XmlRpcPendingCall*)), SLOT(handleFinishedCall()));
}
diff --git a/forummodel.cpp b/forummodel.cpp
index c66d3a8..bdc2d17 100644
--- a/forummodel.cpp
+++ b/forummodel.cpp
@@ -8,7 +8,7 @@
#include "forummodel.h"
ForumModel::ForumModel(QObject *parent) :
- QAbstractListModel(parent), _boardUrl(), _board(0), _forumId(-1)
+ QAbstractListModel(parent), _board(0), _forumId(-1), _eof(false)
{
QHash<int, QByteArray> roles = roleNames();
roles[TitleRole] = QByteArray("title");
@@ -17,21 +17,20 @@ ForumModel::ForumModel(QObject *parent) :
setRoleNames(roles);
}
-QString ForumModel::boardUrl() const
+Board * ForumModel::board() const
{
- return _boardUrl;
+ return _board;
}
-void ForumModel::setBoardUrl(const QString &url)
+void ForumModel::setBoard(Board *board)
{
- if (_boardUrl != url) {
+ if (_board != board) {
disconnect(this, SLOT(handleForumTopicsChanged(int,int,int)));
clearModel();
- _board = 0;
- _boardUrl = url;
- if (!_boardUrl.isEmpty()) {
- _board = board_manager->getBoard(_boardUrl);
+ _board = board;
+
+ if (_board) {
connect(_board, SIGNAL(forumTopicsChanged(int,int,int)),
SLOT(handleForumTopicsChanged(int,int,int)));
if (_forumId >= 0) {
@@ -39,7 +38,7 @@ void ForumModel::setBoardUrl(const QString &url)
reload();
}
}
- emit boardUrlChanged();
+ emit boardChanged();
}
}
@@ -91,14 +90,14 @@ QVariant ForumModel::data(const QModelIndex &index, int role) const
bool ForumModel::canFetchMore(const QModelIndex &parent) const
{
- if (parent.isValid() || !_board) return false; // Invalid state
+ if (parent.isValid() || !_board || _forumId < 0) return false; // Invalid state
return !_eof;
}
void ForumModel::fetchMore(const QModelIndex &parent)
{
if (parent.isValid()) return;
- if (!_board) return;
+ if (!_board || _forumId < 0) return;
if (_eof) return;
const int start = _data.size();
diff --git a/forummodel.h b/forummodel.h
index 8cde5cf..5a84f64 100644
--- a/forummodel.h
+++ b/forummodel.h
@@ -10,7 +10,7 @@ class Board;
class ForumModel : public QAbstractListModel
{
Q_OBJECT
- Q_PROPERTY(QString boardUrl READ boardUrl WRITE setBoardUrl NOTIFY boardUrlChanged)
+ Q_PROPERTY(Board * board READ board WRITE setBoard NOTIFY boardChanged)
Q_PROPERTY(int forumId READ forumId WRITE setForumId NOTIFY forumIdChanged)
public:
@@ -24,8 +24,8 @@ public:
TopicTypeRole
};
- QString boardUrl() const;
- void setBoardUrl(const QString& url);
+ Board * board() const;
+ void setBoard(Board *board);
int forumId() const;
void setForumId(const int id);
@@ -37,7 +37,7 @@ public:
void fetchMore(const QModelIndex &parent = QModelIndex());
signals:
- void boardUrlChanged();
+ void boardChanged();
void forumIdChanged();
protected:
@@ -61,7 +61,6 @@ private slots:
void reload();
private:
- QString _boardUrl;
Board *_board;
int _forumId;
QList<Topic> _data;
diff --git a/loginaction.cpp b/loginaction.cpp
new file mode 100644
index 0000000..445b812
--- /dev/null
+++ b/loginaction.cpp
@@ -0,0 +1,50 @@
+#include <QtCore/QDebug>
+
+#include "board.h"
+#include "xmlrpcinterface.h"
+#include "xmlrpcreply.h"
+#include "loginaction.h"
+
+LoginAction::LoginAction(const QString &name, const QString &password, Board *board)
+ : Action(board), _username(name), _password(password)
+{
+}
+
+bool LoginAction::isSupersetOf(Action *action) const
+{
+ LoginAction *other = qobject_cast<LoginAction*>(action);
+ if (other) {
+ if (other->_username == _username && other->_password == _password) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void LoginAction::execute()
+{
+ qDebug() << "Sending login call..";
+ _call = _board->service()->asyncCall("login",
+ _username.toUtf8(), _password.toUtf8());
+ _call->setParent(this);
+ connect(_call, SIGNAL(finished(XmlRpcPendingCall*)), SLOT(handleFinishedCall()));
+}
+
+void LoginAction::handleFinishedCall()
+{
+ XmlRpcReply<QVariantMap> result(_call);
+ if (result.isValid()) {
+ QVariantMap map = result;
+ bool login_ok = map["result"].toBool();
+ if (login_ok) {
+ _board->notifyLogin(map);
+ } else {
+ qWarning() << "Could not login to board as:" << _username;
+ }
+ } else {
+ qWarning() << "Could not fetch posts";
+ // TODO emit error ...
+ }
+ emit finished(this);
+ _call->deleteLater();
+}
diff --git a/loginaction.h b/loginaction.h
new file mode 100644
index 0000000..cedb910
--- /dev/null
+++ b/loginaction.h
@@ -0,0 +1,28 @@
+#ifndef LOGINACTION_H
+#define LOGINACTION_H
+
+#include "action.h"
+
+class XmlRpcPendingCall;
+
+class LoginAction : public Action
+{
+ Q_OBJECT
+public:
+ explicit LoginAction(const QString& name, const QString& password, Board *board);
+
+ bool isSupersetOf(Action *action) const;
+
+ void execute();
+
+private slots:
+ void handleFinishedCall();
+
+private:
+ XmlRpcPendingCall *_call;
+ QString _username;
+ QString _password;
+};
+
+
+#endif // LOGINACTION_H
diff --git a/main.cpp b/main.cpp
index 52086e4..ccb6fbd 100644
--- a/main.cpp
+++ b/main.cpp
@@ -25,6 +25,9 @@ Q_DECL_EXPORT int main(int argc, char *argv[])
QScopedPointer<ImageNetworkAccessManagerFactory> image_nam_factory(new ImageNetworkAccessManagerFactory);
+ qmlRegisterUncreatableType<BoardManager>("com.javispedro.tapasboard", 1, 0, "Board",
+ "BoardManager must be accessed through boardManager");
+ qmlRegisterType<Board>("com.javispedro.tapasboard", 1, 0, "Board");
qmlRegisterType<FavoritesModel>("com.javispedro.tapasboard", 1, 0, "FavoritesModel");
qmlRegisterType<BoardModel>("com.javispedro.tapasboard", 1, 0, "BoardModel");
qmlRegisterType<ForumModel>("com.javispedro.tapasboard", 1, 0, "ForumModel");
@@ -32,6 +35,7 @@ Q_DECL_EXPORT int main(int argc, char *argv[])
QmlApplicationViewer viewer;
viewer.engine()->setNetworkAccessManagerFactory(image_nam_factory.data());
+ viewer.rootContext()->setContextProperty("boardManager", board_manager);
viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto);
viewer.setMainQmlFile(QLatin1String("qml/tapasboard/main.qml"));
viewer.showExpanded();
diff --git a/qml/tapasboard/BoardPage.qml b/qml/tapasboard/BoardPage.qml
index 4aeba79..dd1bd24 100644
--- a/qml/tapasboard/BoardPage.qml
+++ b/qml/tapasboard/BoardPage.qml
@@ -9,8 +9,8 @@ Page {
anchors.leftMargin: UiConstants.DefaultMargin
anchors.rightMargin: UiConstants.DefaultMargin
- property string boardUrl;
- property int rootForumId;
+ property Board board : null;
+ property int forumId;
tools: ToolBarLayout {
ToolIcon {
@@ -25,8 +25,8 @@ Page {
id: forumsView
anchors.fill: parent
model: BoardModel {
- boardUrl: boardPage.boardUrl
- rootForumId: boardPage.rootForumId
+ board: boardPage.board
+ forumId: boardPage.forumId
}
section.criteria: ViewSection.FullString
section.property: "category"
@@ -71,12 +71,12 @@ Page {
onClicked: {
if (model.subOnly) {
pageStack.push(Qt.resolvedUrl("BoardPage.qml"), {
- boardUrl: boardPage.boardUrl,
- rootForumId: model.forumId
+ board: boardPage.board,
+ forumId: model.forumId
});
} else {
pageStack.push(Qt.resolvedUrl("ForumPage.qml"), {
- boardUrl: boardPage.boardUrl,
+ board: boardPage.board,
forumId: model.forumId
});
}
diff --git a/qml/tapasboard/ForumPage.qml b/qml/tapasboard/ForumPage.qml
index 6e39fe2..18953cb 100644
--- a/qml/tapasboard/ForumPage.qml
+++ b/qml/tapasboard/ForumPage.qml
@@ -9,7 +9,7 @@ Page {
anchors.leftMargin: UiConstants.DefaultMargin
anchors.rightMargin: UiConstants.DefaultMargin
- property string boardUrl;
+ property Board board: null;
property int forumId;
tools: ToolBarLayout {
@@ -25,7 +25,7 @@ Page {
id: topicsView
anchors.fill: parent
model: ForumModel {
- boardUrl: forumPage.boardUrl
+ board: forumPage.board
forumId: forumPage.forumId
}
delegate: EmptyListDelegate {
@@ -56,7 +56,7 @@ Page {
onClicked: {
pageStack.push(Qt.resolvedUrl("TopicPage.qml"), {
- boardUrl: forumPage.boardUrl,
+ board: forumPage.board,
topicId: model.topicId
});
}
diff --git a/qml/tapasboard/MainPage.qml b/qml/tapasboard/MainPage.qml
index de3240a..f94b505 100644
--- a/qml/tapasboard/MainPage.qml
+++ b/qml/tapasboard/MainPage.qml
@@ -21,9 +21,12 @@ Page {
}
onClicked: {
+ var board = boardManager.getBoard(model.boardUrl,
+ model.loginUsername,
+ model.loginPassword);
pageStack.push(Qt.resolvedUrl("BoardPage.qml"), {
- boardUrl: model.boardUrl,
- rootForumId: 0
+ board: board,
+ forumId: board.rootForumId
});
}
}
diff --git a/qml/tapasboard/TopicPage.qml b/qml/tapasboard/TopicPage.qml
index 805154f..ba132b5 100644
--- a/qml/tapasboard/TopicPage.qml
+++ b/qml/tapasboard/TopicPage.qml
@@ -9,7 +9,7 @@ Page {
anchors.leftMargin: UiConstants.DefaultMargin
anchors.rightMargin: UiConstants.DefaultMargin
- property string boardUrl;
+ property Board board;
property int topicId;
tools: ToolBarLayout {
@@ -25,7 +25,7 @@ Page {
id: postsView
anchors.fill: parent
model: TopicModel {
- boardUrl: topicPage.boardUrl
+ board: topicPage.board
topicId: topicPage.topicId
}
section.property: "humanDate"
diff --git a/tapasboard.pro b/tapasboard.pro
index 8430ba0..1cba839 100644
--- a/tapasboard.pro
+++ b/tapasboard.pro
@@ -47,7 +47,8 @@ SOURCES += main.cpp \
fetchpostsaction.cpp \
favoritesmodel.cpp \
imagecache.cpp \
- imagenetworkaccessmanager.cpp
+ imagenetworkaccessmanager.cpp \
+ loginaction.cpp
HEADERS += \
action.h \
@@ -66,7 +67,8 @@ HEADERS += \
fetchpostsaction.h \
favoritesmodel.h \
imagecache.h \
- imagenetworkaccessmanager.h
+ imagenetworkaccessmanager.h \
+ loginaction.h
OTHER_FILES += \
qtc_packaging/debian_harmattan/rules \
diff --git a/topicmodel.cpp b/topicmodel.cpp
index 0c7541e..965481f 100644
--- a/topicmodel.cpp
+++ b/topicmodel.cpp
@@ -8,7 +8,7 @@
#include "topicmodel.h"
TopicModel::TopicModel(QObject *parent) :
- QAbstractListModel(parent), _boardUrl(), _board(0), _topicId(-1)
+ QAbstractListModel(parent), _board(0), _topicId(-1), _eof(false)
{
QHash<int, QByteArray> roles = roleNames();
roles[TitleRole] = QByteArray("title");
@@ -23,21 +23,20 @@ TopicModel::TopicModel(QObject *parent) :
setRoleNames(roles);
}
-QString TopicModel::boardUrl() const
+Board * TopicModel::board() const
{
- return _boardUrl;
+ return _board;
}
-void TopicModel::setBoardUrl(const QString &url)
+void TopicModel::setBoard(Board *board)
{
- if (_boardUrl != url) {
+ if (_board != board) {
disconnect(this, SLOT(handleTopicPostsChanged(int,int,int)));
clearModel();
- _board = 0;
- _boardUrl = url;
- if (!_boardUrl.isEmpty()) {
- _board = board_manager->getBoard(_boardUrl);
+ _board = board;
+
+ if (_board) {
connect(_board, SIGNAL(topicPostsChanged(int,int,int)),
SLOT(handleTopicPostsChanged(int,int,int)));
if (_topicId >= 0) {
@@ -45,7 +44,7 @@ void TopicModel::setBoardUrl(const QString &url)
reload();
}
}
- emit boardUrlChanged();
+ emit boardChanged();
}
}
@@ -109,14 +108,14 @@ QVariant TopicModel::data(const QModelIndex &index, int role) const
bool TopicModel::canFetchMore(const QModelIndex &parent) const
{
- if (parent.isValid() || !_board) return false; // Invalid state
+ if (parent.isValid() || !_board || _topicId < 0) return false; // Invalid state
return !_eof;
}
void TopicModel::fetchMore(const QModelIndex &parent)
{
if (parent.isValid()) return;
- if (!_board) return;
+ if (!_board || _topicId < 0) return;
if (_eof) return;
const int start = _data.size();
diff --git a/topicmodel.h b/topicmodel.h
index 39dcdee..6f1e99f 100644
--- a/topicmodel.h
+++ b/topicmodel.h
@@ -10,7 +10,7 @@ class Board;
class TopicModel : public QAbstractListModel
{
Q_OBJECT
- Q_PROPERTY(QString boardUrl READ boardUrl WRITE setBoardUrl NOTIFY boardUrlChanged)
+ Q_PROPERTY(Board * board READ board WRITE setBoard NOTIFY boardChanged)
Q_PROPERTY(int topicId READ topicId WRITE setTopicId NOTIFY topicIdChanged)
public:
@@ -29,8 +29,8 @@ public:
HumanTimeRole
};
- QString boardUrl() const;
- void setBoardUrl(const QString& url);
+ Board * board() const;
+ void setBoard(Board * board);
int topicId() const;
void setTopicId(const int id);
@@ -42,7 +42,7 @@ public:
void fetchMore(const QModelIndex &parent = QModelIndex());
signals:
- void boardUrlChanged();
+ void boardChanged();
void topicIdChanged();
protected:
@@ -69,7 +69,6 @@ private slots:
void reload();
private:
- QString _boardUrl;
Board *_board;
int _topicId;
QList<Post> _data;