diff options
-rw-r--r-- | CMakeLists.txt | 2 | ||||
-rw-r--r-- | connection.cpp | 155 | ||||
-rw-r--r-- | connection.h | 32 | ||||
-rw-r--r-- | connectiondata.cpp | 8 | ||||
-rw-r--r-- | connectiondata.h | 4 | ||||
-rw-r--r-- | connectionprivate.cpp | 126 | ||||
-rw-r--r-- | connectionprivate.h | 66 | ||||
-rw-r--r-- | events/event.cpp | 10 | ||||
-rw-r--r-- | events/event.h | 12 | ||||
-rw-r--r-- | jobs/basejob.cpp | 2 | ||||
-rw-r--r-- | jobs/roommessagesjob.cpp | 7 | ||||
-rw-r--r-- | jobs/roommessagesjob.h | 5 | ||||
-rw-r--r-- | jobs/syncjob.cpp | 3 | ||||
-rw-r--r-- | jobs/syncjob.h | 5 | ||||
-rw-r--r-- | room.cpp | 96 | ||||
-rw-r--r-- | room.h | 3 | ||||
-rw-r--r-- | settings.cpp | 102 | ||||
-rw-r--r-- | settings.h | 97 |
18 files changed, 382 insertions, 353 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 8be4be70..ea340476 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,11 +37,11 @@ message( STATUS ) set(libqmatrixclient_SRCS connectiondata.cpp connection.cpp - connectionprivate.cpp room.cpp user.cpp logmessage.cpp state.cpp + settings.cpp events/event.cpp events/roommessageevent.cpp events/roomnameevent.cpp diff --git a/connection.cpp b/connection.cpp index 904649bc..98ff914a 100644 --- a/connection.cpp +++ b/connection.cpp @@ -18,7 +18,7 @@ #include "connection.h" #include "connectiondata.h" -#include "connectionprivate.h" +//#include "connectionprivate.h" #include "user.h" #include "events/event.h" #include "room.h" @@ -33,15 +33,42 @@ #include "jobs/syncjob.h" #include "jobs/mediathumbnailjob.h" +#include <QtNetwork/QDnsLookup> #include <QtCore/QDebug> using namespace QMatrixClient; +class Connection::Private +{ + public: + explicit Private(QUrl serverUrl) + : q(nullptr) + , data(new ConnectionData(serverUrl)) + , isConnected(false) + , syncJob(nullptr) + { } + Private(Private&) = delete; + ~Private() { delete data; } + + Connection* q; + ConnectionData* data; + QHash<QString, Room*> roomMap; + QHash<QString, User*> userMap; + bool isConnected; + QString username; + QString password; + QString userId; + + SyncJob* syncJob; + + SyncJob* startSyncJob(const QString& filter, int timeout); +}; + Connection::Connection(QUrl server, QObject* parent) : QObject(parent) + , d(new Private(server)) { - d = new ConnectionPrivate(this); - d->data = new ConnectionData(server); + d->q = this; // All d initialization should occur before this line } Connection::Connection() @@ -56,14 +83,32 @@ Connection::~Connection() void Connection::resolveServer(QString domain) { - d->resolveServer( domain ); + // Find the Matrix server for the given domain. + QScopedPointer<QDnsLookup, QScopedPointerDeleteLater> dns { new QDnsLookup() }; + dns->setType(QDnsLookup::SRV); + dns->setName("_matrix._tcp." + domain); + + dns->lookup(); + connect(dns.data(), &QDnsLookup::finished, [&]() { + // Check the lookup succeeded. + if (dns->error() != QDnsLookup::NoError || + dns->serviceRecords().isEmpty()) { + emit resolveError("DNS lookup failed"); + return; + } + + // Handle the results. + auto record = dns->serviceRecords().front(); + d->data->setHost(record.target()); + d->data->setPort(record.port()); + emit resolved(); + }); } void Connection::connectToServer(QString user, QString password) { PasswordLogin* loginJob = new PasswordLogin(d->data, user, password); connect( loginJob, &PasswordLogin::success, [=] () { - qDebug() << "Our user ID: " << loginJob->id(); connectWithToken(loginJob->id(), loginJob->token()); }); connect( loginJob, &PasswordLogin::failure, [=] () { @@ -79,7 +124,9 @@ void Connection::connectWithToken(QString userId, QString token) d->isConnected = true; d->userId = userId; d->data->setToken(token); - qDebug() << "Connected with token:"; + qDebug() << "Accessing" << d->data->baseUrl() + << "by user" << userId + << "with the following access token:"; qDebug() << token; emit connected(); } @@ -98,6 +145,12 @@ void Connection::reconnect() loginJob->start(); } +void Connection::disconnectFromServer() +{ + d->syncJob->abandon(); + d->isConnected = false; +} + void Connection::logout() { auto job = new LogoutJob(d->data); @@ -107,27 +160,39 @@ void Connection::logout() SyncJob* Connection::sync(int timeout) { - QString filter = "{\"room\": { \"timeline\": { \"limit\": 100 } } }"; - SyncJob* syncJob = new SyncJob(d->data, d->data->lastEvent()); - syncJob->setFilter(filter); - syncJob->setTimeout(timeout); - connect( syncJob, &SyncJob::success, [=] () { - d->data->setLastEvent(syncJob->nextBatch()); - for( const auto roomData: syncJob->roomData() ) + if (d->syncJob) + return d->syncJob; + + const QString filter = "{\"room\": { \"timeline\": { \"limit\": 100 } } }"; + auto job = d->startSyncJob(filter, timeout); + connect( job, &SyncJob::success, [=] () { + d->data->setLastEvent(job->nextBatch()); + for( const auto& roomData: job->roomData() ) { - if ( Room* r = d->provideRoom(roomData.roomId) ) + if ( Room* r = provideRoom(roomData.roomId) ) r->updateData(roomData); } + d->syncJob = nullptr; emit syncDone(); }); - connect( syncJob, &SyncJob::failure, [=] () { - if (syncJob->error() == BaseJob::ContentAccessError) - emit loginError(syncJob->errorString()); + connect( job, &SyncJob::failure, [=] () { + d->syncJob = nullptr; + if (job->error() == BaseJob::ContentAccessError) + emit loginError(job->errorString()); else - emit connectionError(syncJob->errorString()); + emit connectionError(job->errorString()); }); + return job; +} + +SyncJob* Connection::Private::startSyncJob(const QString& filter, int timeout) +{ + syncJob = new SyncJob(data, data->lastEvent()); + syncJob->setFilter(filter); + syncJob->setTimeout(timeout); syncJob->start(); return syncJob; + } void Connection::postMessage(Room* room, QString type, QString message) @@ -147,7 +212,7 @@ void Connection::joinRoom(QString roomAlias) { JoinRoomJob* job = new JoinRoomJob(d->data, roomAlias); connect( job, &SyncJob::success, [=] () { - if ( Room* r = d->provideRoom(job->roomId()) ) + if ( Room* r = provideRoom(job->roomId()) ) emit joinedRoom(r); }); job->start(); @@ -159,12 +224,12 @@ void Connection::leaveRoom(Room* room) job->start(); } -void Connection::getMembers(Room* room) -{ - RoomMembersJob* job = new RoomMembersJob(d->data, room); - connect( job, &RoomMembersJob::result, d, &ConnectionPrivate::gotRoomMembers ); - job->start(); -} +//void Connection::getMembers(Room* room) +//{ +// RoomMembersJob* job = new RoomMembersJob(d->data, room); +// connect( job, &RoomMembersJob::result, d, &ConnectionPrivate::gotRoomMembers ); +// job->start(); +//} RoomMessagesJob* Connection::getMessages(Room* room, QString from) { @@ -180,6 +245,11 @@ MediaThumbnailJob* Connection::getThumbnail(QUrl url, int requestedWidth, int re return job; } +QUrl Connection::homeserver() const +{ + return d->data->baseUrl(); +} + User* Connection::user(QString userId) { if( d->userMap.contains(userId) ) @@ -196,14 +266,19 @@ User *Connection::user() return user(d->userId); } -QString Connection::userId() +QString Connection::userId() const { return d->userId; } -QString Connection::token() +QString Connection::token() const { - return d->data->token(); + return accessToken(); +} + +QString Connection::accessToken() const +{ + return d->data->accessToken(); } QHash< QString, Room* > Connection::roomMap() const @@ -221,6 +296,30 @@ ConnectionData* Connection::connectionData() return d->data; } +Room* Connection::provideRoom(QString id) +{ + if (id.isEmpty()) + { + qDebug() << "Connection::provideRoom() with empty id, doing nothing"; + return nullptr; + } + + if (d->roomMap.contains(id)) + return d->roomMap.value(id); + + // Not yet in the map, create a new one. + Room* room = createRoom(id); + if (room) + { + d->roomMap.insert( id, room ); + emit newRoom(room); + } else { + qCritical() << "Failed to create a room!!!" << id; + } + + return room; +} + User* Connection::createUser(QString userId) { return new User(userId, this); diff --git a/connection.h b/connection.h index f3a15cba..c221d7eb 100644 --- a/connection.h +++ b/connection.h @@ -20,6 +20,7 @@ #define QMATRIXCLIENT_CONNECTION_H #include <QtCore/QObject> +#include <QtCore/QUrl> namespace QMatrixClient { @@ -48,6 +49,7 @@ namespace QMatrixClient Q_INVOKABLE virtual void connectToServer( QString user, QString password ); Q_INVOKABLE virtual void connectWithToken( QString userId, QString token ); Q_INVOKABLE virtual void reconnect(); + Q_INVOKABLE virtual void disconnectFromServer(); Q_INVOKABLE virtual void logout(); Q_INVOKABLE virtual SyncJob* sync(int timeout=-1); @@ -55,14 +57,17 @@ namespace QMatrixClient Q_INVOKABLE virtual PostReceiptJob* postReceipt( Room* room, Event* event ); Q_INVOKABLE virtual void joinRoom( QString roomAlias ); Q_INVOKABLE virtual void leaveRoom( Room* room ); - Q_INVOKABLE virtual void getMembers( Room* room ); +// Q_INVOKABLE virtual void getMembers( Room* room ); Q_INVOKABLE virtual RoomMessagesJob* getMessages( Room* room, QString from ); virtual MediaThumbnailJob* getThumbnail( QUrl url, int requestedWidth, int requestedHeight ); - Q_INVOKABLE virtual User* user(QString userId); - Q_INVOKABLE virtual User* user(); - Q_INVOKABLE virtual QString userId(); - Q_INVOKABLE virtual QString token(); + Q_INVOKABLE QUrl homeserver() const; + Q_INVOKABLE User* user(QString userId); + Q_INVOKABLE User* user(); + Q_INVOKABLE QString userId() const; + /** @deprecated Use accessToken() instead. */ + Q_INVOKABLE QString token() const; + Q_INVOKABLE QString accessToken() const; signals: void resolved(); @@ -81,11 +86,22 @@ namespace QMatrixClient protected: /** - * Access the underlying ConnectionData class + * @brief Access the underlying ConnectionData class */ ConnectionData* connectionData(); /** + * @brief Find a (possibly new) Room object for the specified id + * Use this method whenever you need to find a Room object in + * the local list of rooms. Note that this does not interact with + * the server; in particular, does not automatically create rooms + * on the server. + * @return a pointer to a Room object with the specified id; nullptr + * if roomId is empty if createRoom() failed to create a Room object. + */ + Room* provideRoom(QString roomId); + + /** * makes it possible for derived classes to have its own User class */ virtual User* createUser(QString userId); @@ -96,8 +112,8 @@ namespace QMatrixClient virtual Room* createRoom(QString roomId); private: - friend class ConnectionPrivate; - ConnectionPrivate* d; + class Private; + Private* d; }; } diff --git a/connectiondata.cpp b/connectiondata.cpp index 4a3bd47f..72e8f3d8 100644 --- a/connectiondata.cpp +++ b/connectiondata.cpp @@ -29,7 +29,7 @@ class ConnectionData::Private QUrl baseUrl; //bool isConnected; - QString token; + QString accessToken; QString lastEvent; QNetworkAccessManager* nam; }; @@ -52,9 +52,9 @@ ConnectionData::~ConnectionData() // return d->isConnected; // } -QString ConnectionData::token() const +QString ConnectionData::accessToken() const { - return d->token; + return d->accessToken; } QUrl ConnectionData::baseUrl() const @@ -69,7 +69,7 @@ QNetworkAccessManager* ConnectionData::nam() const void ConnectionData::setToken(QString token) { - d->token = token; + d->accessToken = token; } void ConnectionData::setHost(QString host) diff --git a/connectiondata.h b/connectiondata.h index 6407780c..5c8342d7 100644 --- a/connectiondata.h +++ b/connectiondata.h @@ -32,11 +32,11 @@ namespace QMatrixClient virtual ~ConnectionData(); //bool isConnected() const; - QString token() const; + QString accessToken() const; QUrl baseUrl() const; QNetworkAccessManager* nam() const; - void setToken( QString token ); + void setToken( QString accessToken ); void setHost( QString host ); void setPort( int port ); diff --git a/connectionprivate.cpp b/connectionprivate.cpp deleted file mode 100644 index 6556a8ee..00000000 --- a/connectionprivate.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/****************************************************************************** - * Copyright (C) 2015 Felix Rohrbach <kde@fxrh.de> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "connectionprivate.h" -#include "connection.h" -#include "state.h" -#include "room.h" -#include "user.h" -#include "jobs/passwordlogin.h" -#include "jobs/syncjob.h" -#include "jobs/joinroomjob.h" -#include "jobs/roommembersjob.h" -#include "events/event.h" -#include "events/roommessageevent.h" -#include "events/roommemberevent.h" - -#include <QtCore/QDebug> -#include <QtNetwork/QDnsLookup> - -using namespace QMatrixClient; - -ConnectionPrivate::ConnectionPrivate(Connection* parent) - : q(parent) -{ - isConnected = false; - data = nullptr; -} - -ConnectionPrivate::~ConnectionPrivate() -{ - delete data; -} - -void ConnectionPrivate::resolveServer(QString domain) -{ - // Find the Matrix server for the given domain. - QDnsLookup* dns = new QDnsLookup(); - dns->setType(QDnsLookup::SRV); - dns->setName("_matrix._tcp." + domain); - - connect(dns, &QDnsLookup::finished, [this,dns]() { - // Check the lookup succeeded. - if (dns->error() != QDnsLookup::NoError || - dns->serviceRecords().isEmpty()) { - emit q->resolveError("DNS lookup failed"); - dns->deleteLater(); - return; - } - - // Handle the results. - QDnsServiceRecord record = dns->serviceRecords().first(); - data->setHost(record.target()); - data->setPort(record.port()); - emit q->resolved(); - dns->deleteLater(); - }); - dns->lookup(); -} - -void ConnectionPrivate::processState(State* state) -{ - if( state->event()->type() == QMatrixClient::EventType::RoomMember ) - { - QMatrixClient::RoomMemberEvent* e = static_cast<QMatrixClient::RoomMemberEvent*>(state->event()); - User* user = q->user(e->userId()); - user->processEvent(e); - } - - if ( Room* r = provideRoom(state->event()->roomId()) ) - r->addInitialState(state); -} - -Room* ConnectionPrivate::provideRoom(QString id) -{ - if (id.isEmpty()) - { - qDebug() << "ConnectionPrivate::provideRoom() with empty id, doing nothing"; - return nullptr; - } - - if (roomMap.contains(id)) - return roomMap.value(id); - - // Not yet in the map, create a new one. - Room* room = q->createRoom(id); - if (!room) - qCritical() << "Failed to create a room!!!" << id; - - roomMap.insert( id, room ); - emit q->newRoom(room); - return room; -} - -void ConnectionPrivate::gotRoomMembers(BaseJob* job) -{ - RoomMembersJob* membersJob = static_cast<RoomMembersJob*>(job); - if( !membersJob->error() ) - { - for( State* state: membersJob->states() ) - { - processState(state); - } - qDebug() << membersJob->states().count() << " processed..."; - } - else - { - qDebug() << "MembersJob error: " <<membersJob->errorString(); - if( membersJob->error() == BaseJob::NetworkError ) - emit q->connectionError( membersJob->errorString() ); - } -} diff --git a/connectionprivate.h b/connectionprivate.h deleted file mode 100644 index 424ef998..00000000 --- a/connectionprivate.h +++ /dev/null @@ -1,66 +0,0 @@ -/****************************************************************************** - * Copyright (C) 2015 Felix Rohrbach <kde@fxrh.de> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef QMATRIXCLIENT_CONNECTIONPRIVATE_H -#define QMATRIXCLIENT_CONNECTIONPRIVATE_H - -#include <QtCore/QObject> -#include <QtCore/QHash> -#include <QtCore/QJsonObject> - -#include "connection.h" -#include "connectiondata.h" - -namespace QMatrixClient -{ - class Connection; - class Event; - class State; - class User; - class BaseJob; - class SyncRoomData; - - class ConnectionPrivate : public QObject - { - Q_OBJECT - public: - ConnectionPrivate(Connection* parent); - ~ConnectionPrivate(); - - void resolveServer( QString domain ); - - void processState( State* state ); - - /** Finds a room with this id or creates a new one and adds it to roomMap. */ - Room* provideRoom( QString id ); - - Connection* q; - ConnectionData* data; - QHash<QString, Room*> roomMap; - QHash<QString, User*> userMap; - bool isConnected; - QString username; - QString password; - QString userId; - - public slots: - void gotRoomMembers(BaseJob* job); - }; -} - -#endif // QMATRIXCLIENT_CONNECTIONPRIVATE_H diff --git a/events/event.cpp b/events/event.cpp index d05d666f..0c7700ee 100644 --- a/events/event.cpp +++ b/events/event.cpp @@ -151,11 +151,11 @@ bool Event::parseJson(const QJsonObject& obj) return correct; } -QList<Event*> QMatrixClient::eventListFromJson(const QJsonArray& json) +Events QMatrixClient::eventsFromJson(const QJsonArray& json) { - QList<Event*> l; - l.reserve(json.size()); + Events evs; + evs.reserve(json.size()); for (auto event: json) - l.push_back(Event::fromJson(event.toObject())); - return l; + evs.push_back(Event::fromJson(event.toObject())); + return evs; } diff --git a/events/event.h b/events/event.h index 72d26208..d9316747 100644 --- a/events/event.h +++ b/events/event.h @@ -24,6 +24,7 @@ #include <QtCore/QString> #include <QtCore/QDateTime> #include <QtCore/QJsonObject> +#include <QtCore/QVector> class QJsonArray; @@ -38,7 +39,8 @@ namespace QMatrixClient class Event { public: - Event(EventType type); + explicit Event(EventType type); + Event(Event&) = delete; virtual ~Event(); EventType type() const; @@ -57,8 +59,9 @@ namespace QMatrixClient class Private; Private* d; }; + using Events = QVector<Event*>; - QList<Event*> eventListFromJson(const QJsonArray& contents); + Events eventsFromJson(const QJsonArray& contents); /** * Finds a place in the timeline where a new event/message could be inserted. @@ -71,6 +74,11 @@ namespace QMatrixClient { return std::lower_bound (timeline.begin(), timeline.end(), item, [](const typename ContT::value_type a, const ItemT * b) { + // FIXME: We should not order the message list by origin timestamp. + // Rather, an order of receiving should be used (which actually + // poses a question on whether this method is needed at all - + // or we'd just prepend and append, depending on whether we + // received something from /sync or from /messages. return a->timestamp() < b->timestamp(); } ); diff --git a/jobs/basejob.cpp b/jobs/basejob.cpp index e0dff287..20b45a15 100644 --- a/jobs/basejob.cpp +++ b/jobs/basejob.cpp @@ -92,7 +92,7 @@ void BaseJob::start() url.setPath( url.path() + "/" + apiPath() ); QUrlQuery query = this->query(); if( d->needsToken ) - query.addQueryItem("access_token", connection()->token()); + query.addQueryItem("access_token", connection()->accessToken()); url.setQuery(query); QNetworkRequest req = QNetworkRequest(url); req.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); diff --git a/jobs/roommessagesjob.cpp b/jobs/roommessagesjob.cpp index ba075007..f880713d 100644 --- a/jobs/roommessagesjob.cpp +++ b/jobs/roommessagesjob.cpp @@ -18,7 +18,6 @@ #include "roommessagesjob.h" #include "../room.h" -#include "../events/event.h" #include <QtCore/QJsonObject> #include <QtCore/QJsonArray> @@ -35,7 +34,7 @@ class RoomMessagesJob::Private FetchDirectory dir; int limit; - QList<Event*> events; + Events events; QString end; }; @@ -54,7 +53,7 @@ RoomMessagesJob::~RoomMessagesJob() delete d; } -QList<Event*> RoomMessagesJob::events() +Events RoomMessagesJob::events() { return d->events; } @@ -84,7 +83,7 @@ QUrlQuery RoomMessagesJob::query() const BaseJob::Status RoomMessagesJob::parseJson(const QJsonDocument& data) { QJsonObject obj = data.object(); - d->events = eventListFromJson(obj.value("chunk").toArray()); + d->events = eventsFromJson(obj.value("chunk").toArray()); d->end = obj.value("end").toString(); return Success; } diff --git a/jobs/roommessagesjob.h b/jobs/roommessagesjob.h index 52a72f70..9bedcad9 100644 --- a/jobs/roommessagesjob.h +++ b/jobs/roommessagesjob.h @@ -21,10 +21,11 @@ #include "basejob.h" +#include "../events/event.h" + namespace QMatrixClient { class Room; - class Event; enum class FetchDirectory { Backwards, Forward }; @@ -34,7 +35,7 @@ namespace QMatrixClient RoomMessagesJob(ConnectionData* data, Room* room, QString from, FetchDirectory dir = FetchDirectory::Backwards, int limit=10); virtual ~RoomMessagesJob(); - QList<Event*> events(); + Events events(); QString end(); protected: diff --git a/jobs/syncjob.cpp b/jobs/syncjob.cpp index a9865b55..2b2705b1 100644 --- a/jobs/syncjob.cpp +++ b/jobs/syncjob.cpp @@ -26,7 +26,6 @@ #include "../room.h" #include "../connectiondata.h" -#include "../events/event.h" using namespace QMatrixClient; @@ -139,7 +138,7 @@ BaseJob::Status SyncJob::parseJson(const QJsonDocument& data) void SyncRoomData::EventList::fromJson(const QJsonObject& roomContents) { - auto l = eventListFromJson(roomContents[jsonKey].toObject()["events"].toArray()); + auto l = eventsFromJson(roomContents[jsonKey].toObject()["events"].toArray()); swap(l); } diff --git a/jobs/syncjob.h b/jobs/syncjob.h index f08a6b56..ed99b38b 100644 --- a/jobs/syncjob.h +++ b/jobs/syncjob.h @@ -22,15 +22,14 @@ #include "basejob.h" #include "../joinstate.h" +#include "../events/event.h" namespace QMatrixClient { - class Event; - class SyncRoomData { public: - class EventList : public QList<Event*> + class EventList : public Events { private: QString jsonKey; @@ -51,8 +51,6 @@ class Room::Private Room* q; - //static LogMessage* parseMessage(const QJsonObject& message); - // This updates the room displayname field (which is the way a room // should be shown in the room list) It should be called whenever the // list of members or the room name (m.room.name) or canonical alias change. @@ -330,18 +328,6 @@ QString Room::roomMembername(QString userId) const return roomMembername(connection()->user(userId)); } -void Room::addMessage(Event* event) -{ - processMessageEvent(event); - emit newMessage(event); - //d->addState(event); -} - -void Room::addInitialState(State* state) -{ - processStateEvent(state->event()); -} - void Room::updateData(const SyncRoomData& data) { if( d->prevBatch.isEmpty() ) @@ -578,85 +564,3 @@ void Room::Private::updateDisplayname() if (old_name != displayname) emit q->displaynameChanged(q); } - -// void Room::setAlias(QString alias) -// { -// d->alias = alias; -// emit aliasChanged(this); -// } -// -// bool Room::parseEvents(const QJsonObject& json) -// { -// QList<LogMessage*> newMessages; -// QJsonValue value = json.value("messages").toObject().value("chunk"); -// if( !value.isArray() ) -// { -// return false; -// } -// QJsonArray messages = value.toArray(); -// for(const QJsonValue& val: messages ) -// { -// if( !val.isObject() ) -// continue; -// LogMessage* msg = Private::parseMessage(val.toObject()); -// if( msg ) -// { -// newMessages.append(msg); -// } -// -// } -// addMessages(newMessages); -// return true; -// } -// -// bool Room::parseSingleEvent(const QJsonObject& json) -// { -// qDebug() << "parseSingleEvent"; -// LogMessage* msg = Private::parseMessage(json); -// if( msg ) -// { -// addMessage(msg); -// return true; -// } -// return false; -// } -// -// bool Room::parseState(const QJsonObject& json) -// { -// QJsonValue value = json.value("state"); -// if( !value.isArray() ) -// { -// return false; -// } -// QJsonArray states = value.toArray(); -// for( const QJsonValue& val: states ) -// { -// QJsonObject state = val.toObject(); -// QString type = state.value("type").toString(); -// if( type == "m.room.aliases" ) -// { -// QJsonArray aliases = state.value("content").toObject().value("aliases").toArray(); -// if( aliases.count() > 0 ) -// { -// setAlias(aliases.at(0).toString()); -// } -// } -// } -// return true; -// } -// -// LogMessage* Room::Private::parseMessage(const QJsonObject& message) -// { -// if( message.value("type") == "m.room.message" ) -// { -// QJsonObject content = message.value("content").toObject(); -// if( content.value("msgtype").toString() != "m.text" ) -// return 0; -// QString user = message.value("user_id").toString(); -// QString body = content.value("body").toString(); -// LogMessage* msg = new LogMessage( LogMessage::UserMessage, body, user ); -// return msg; -// } -// return 0; -// } - @@ -30,7 +30,6 @@ namespace QMatrixClient { class Event; - class State; class Connection; class User; @@ -65,8 +64,6 @@ namespace QMatrixClient */ Q_INVOKABLE QString roomMembername(QString userId) const; - Q_INVOKABLE void addMessage( Event* event ); - Q_INVOKABLE void addInitialState( State* state ); Q_INVOKABLE void updateData( const SyncRoomData& data ); Q_INVOKABLE void setJoinState( JoinState state ); diff --git a/settings.cpp b/settings.cpp new file mode 100644 index 00000000..45af33e3 --- /dev/null +++ b/settings.cpp @@ -0,0 +1,102 @@ +#include "settings.h"
+
+#include <QtCore/QUrl>
+#include <QtCore/QDebug>
+
+using namespace QMatrixClient;
+
+Settings::~Settings()
+{ }
+
+void Settings::setValue(const QString& key, const QVariant& value)
+{
+// qDebug() << "Setting" << key << "to" << value;
+ QSettings::setValue(key, value);
+}
+
+QVariant Settings::value(const QString& key, const QVariant& defaultValue) const
+{
+ return QSettings::value(key, defaultValue);
+}
+
+SettingsGroup::~SettingsGroup()
+{ }
+
+void SettingsGroup::setValue(const QString& key, const QVariant& value)
+{
+ Settings::setValue(groupPath + "/" + key, value);
+}
+
+bool SettingsGroup::contains(const QString& key) const
+{
+ return Settings::contains(groupPath + "/" + key);
+}
+
+QVariant SettingsGroup::value(const QString& key, const QVariant& defaultValue) const
+{
+ return Settings::value(groupPath + "/" + key, defaultValue);
+}
+
+QString SettingsGroup::group() const
+{
+ return groupPath;
+}
+
+QStringList SettingsGroup::childGroups() const
+{
+ const_cast<SettingsGroup*>(this)->beginGroup(groupPath);
+ QStringList l { Settings::childGroups() };
+ const_cast<SettingsGroup*>(this)->endGroup();
+ return l;
+}
+
+void SettingsGroup::remove(const QString& key)
+{
+ QString fullKey { groupPath };
+ if (!key.isEmpty())
+ fullKey += "/" + key;
+ Settings::remove(fullKey);
+}
+
+AccountSettings::~AccountSettings()
+{ }
+
+bool AccountSettings::keepLoggedIn() const
+{
+ return value("keep_logged_in", false).toBool();
+}
+
+void AccountSettings::setKeepLoggedIn(bool newSetting)
+{
+ setValue("keep_logged_in", newSetting);
+}
+
+QUrl AccountSettings::homeserver() const
+{
+ return QUrl::fromUserInput(value("homeserver").toString());
+}
+
+void AccountSettings::setHomeserver(const QUrl& url)
+{
+ setValue("homeserver", url.toString());
+}
+
+QString AccountSettings::userId() const
+{
+ return group().section('/', -1);
+}
+
+QString AccountSettings::accessToken() const
+{
+ return value("access_token").toString();
+}
+
+void AccountSettings::setAccessToken(const QString& accessToken)
+{
+ setValue("access_token", accessToken);
+}
+
+void AccountSettings::clearAccessToken()
+{
+ remove("access_token");
+}
diff --git a/settings.h b/settings.h new file mode 100644 index 00000000..10b2bb0a --- /dev/null +++ b/settings.h @@ -0,0 +1,97 @@ +/******************************************************************************
+ * Copyright (C) 2016 Kitsune Ral <kitsune-ral@users.sf.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#pragma once
+
+#include <QtCore/QSettings>
+#include <QtCore/QVector>
+
+class QVariant;
+class QUrl;
+
+namespace QMatrixClient
+{
+ class Settings: public QSettings
+ {
+ public:
+#if defined(_MSC_VER) && _MSC_VER < 1900
+ // VS 2013 (and probably older) aren't friends with 'using' statements
+ // that involve private constructors
+ explicit Settings(QObject* parent = 0) : QSettings(parent) { }
+#else
+ using QSettings::QSettings;
+#endif
+ virtual ~Settings();
+
+ Q_INVOKABLE void setValue(const QString &key,
+ const QVariant &value);
+ Q_INVOKABLE QVariant value(const QString &key,
+ const QVariant &defaultValue = {}) const;
+ };
+
+ class SettingsGroup: public Settings
+ {
+ public:
+ template <typename... ArgTs>
+ explicit SettingsGroup(const QString& path, ArgTs... qsettingsArgs)
+ : Settings(qsettingsArgs...)
+ , groupPath(path)
+ { }
+ virtual ~SettingsGroup();
+
+ Q_INVOKABLE bool contains(const QString& key) const;
+ Q_INVOKABLE QVariant value(const QString &key,
+ const QVariant &defaultValue = {}) const;
+ Q_INVOKABLE QString group() const;
+ Q_INVOKABLE QStringList childGroups() const;
+ Q_INVOKABLE void setValue(const QString &key,
+ const QVariant &value);
+
+ Q_INVOKABLE void remove(const QString& key);
+
+ private:
+ QString groupPath;
+ };
+
+ class AccountSettings: public SettingsGroup
+ {
+ Q_OBJECT
+ Q_PROPERTY(QString userId READ userId)
+ Q_PROPERTY(QUrl homeserver READ homeserver WRITE setHomeserver)
+ Q_PROPERTY(bool keepLoggedIn READ keepLoggedIn WRITE setKeepLoggedIn)
+ Q_PROPERTY(QString accessToken READ accessToken WRITE setAccessToken)
+ public:
+ template <typename... ArgTs>
+ explicit AccountSettings(const QString& accountId, ArgTs... qsettingsArgs)
+ : SettingsGroup("Accounts/" + accountId, qsettingsArgs...)
+ { }
+ virtual ~AccountSettings();
+
+ QString userId() const;
+
+ QUrl homeserver() const;
+ void setHomeserver(const QUrl& url);
+
+ bool keepLoggedIn() const;
+ void setKeepLoggedIn(bool newSetting);
+
+ QString accessToken() const;
+ void setAccessToken(const QString& accessToken);
+ Q_INVOKABLE void clearAccessToken();
+ };
+}
|