From 76241cb772bb53901cdd3308262f76ba718d9a47 Mon Sep 17 00:00:00 2001
From: Kitsune Ral <Kitsune-Ral@users.sf.net>
Date: Wed, 31 Aug 2016 17:49:43 +0900
Subject: Dismiss ConnectionPrivate, long live Connection::Private

Closer investigation found out that there are only two actually used member functions in ConnectionPrivate - provideRoom() and resolveServer(). These two have been transferred to Connection; and data members from ConnectionPrivate found new home in Connection::Private.

Factoring out room management and user management from Connection is still a pending task.
---
 CMakeLists.txt        |   1 -
 connection.cpp        |  93 +++++++++++++++++++++++++++++++------
 connection.h          |  19 ++++++--
 connectionprivate.cpp | 126 --------------------------------------------------
 connectionprivate.h   |  66 --------------------------
 5 files changed, 95 insertions(+), 210 deletions(-)
 delete mode 100644 connectionprivate.cpp
 delete mode 100644 connectionprivate.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1e5dae8f..80ffcfd7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -28,7 +28,6 @@ message( STATUS )
 set(libqmatrixclient_SRCS
    connectiondata.cpp
    connection.cpp
-   connectionprivate.cpp
    room.cpp
    user.cpp
    logmessage.cpp
diff --git a/connection.cpp b/connection.cpp
index 904649bc..d357599b 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,39 @@
 #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)
+        { }
+        Private(Private&) = delete;
+        ~Private() { delete data; }
+
+        Room* provideRoom( QString id );
+
+        Connection* q;
+        ConnectionData* data;
+        QHash<QString, Room*> roomMap;
+        QHash<QString, User*> userMap;
+        bool isConnected;
+        QString username;
+        QString password;
+        QString userId;
+};
+
 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,7 +80,26 @@ 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)
@@ -113,9 +156,9 @@ SyncJob* Connection::sync(int timeout)
     syncJob->setTimeout(timeout);
     connect( syncJob, &SyncJob::success, [=] () {
         d->data->setLastEvent(syncJob->nextBatch());
-        for( const auto roomData: syncJob->roomData() )
+        for( const auto& roomData: syncJob->roomData() )
         {
-            if ( Room* r = d->provideRoom(roomData.roomId) )
+            if ( Room* r = provideRoom(roomData.roomId) )
                 r->updateData(roomData);
         }
         emit syncDone();
@@ -147,7 +190,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 +202,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)
 {
@@ -221,6 +264,30 @@ ConnectionData* Connection::connectionData()
     return d->data;
 }
 
+Room* Connection::provideRoom(QString id)
+{
+    if (id.isEmpty())
+    {
+        qDebug() << "ConnectionPrivate::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..2816895e 100644
--- a/connection.h
+++ b/connection.h
@@ -55,7 +55,7 @@ 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 );
 
@@ -81,10 +81,21 @@ 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
              */
@@ -96,8 +107,8 @@ namespace QMatrixClient
             virtual Room* createRoom(QString roomId);
 
         private:
-            friend class ConnectionPrivate;
-            ConnectionPrivate* d;
+            class Private;
+            Private* d;
     };
 }
 
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
-- 
cgit v1.2.3