From 13df852479bf84f297bf59ed99236e52f486a095 Mon Sep 17 00:00:00 2001
From: Nicolas Werner <nicolas.werner@hotmail.de>
Date: Sat, 14 Dec 2019 23:39:02 +0100
Subject: [PATCH] Reduce some include of Cache.h since it needs 11s on average

---
 src/Cache.cpp                 | 101 +++++++++++++++-
 src/Cache.h                   | 218 +---------------------------------
 src/CacheCryptoStructs.h      |  67 +++++++++++
 src/CacheStructs.h            |  91 ++++++++++++++
 src/ChatPage.h                |   2 +-
 src/CommunitiesList.h         |   3 +-
 src/RoomInfoListItem.cpp      |   2 +-
 src/RoomInfoListItem.h        |   5 +-
 src/dialogs/RoomSettings.cpp  |   8 +-
 src/popups/SuggestionsPopup.h |   2 +
 src/timeline/TimelineModel.h  |   2 +-
 11 files changed, 275 insertions(+), 226 deletions(-)
 create mode 100644 src/CacheCryptoStructs.h
 create mode 100644 src/CacheStructs.h

diff --git a/src/Cache.cpp b/src/Cache.cpp
index d3aec9dbd..e61d101ef 100644
--- a/src/Cache.cpp
+++ b/src/Cache.cpp
@@ -78,6 +78,13 @@ constexpr auto OUTBOUND_MEGOLM_SESSIONS_DB("outbound_megolm_sessions");
 using CachedReceipts = std::multimap<uint64_t, std::string, std::greater<uint64_t>>;
 using Receipts       = std::map<std::string, std::map<std::string, uint64_t>>;
 
+Q_DECLARE_METATYPE(SearchResult)
+Q_DECLARE_METATYPE(QVector<SearchResult>)
+Q_DECLARE_METATYPE(RoomMember)
+Q_DECLARE_METATYPE(mtx::responses::Timeline)
+Q_DECLARE_METATYPE(RoomSearchResult)
+Q_DECLARE_METATYPE(RoomInfo)
+
 namespace {
 std::unique_ptr<Cache> instance_ = nullptr;
 }
@@ -1504,7 +1511,7 @@ Cache::getRoomName(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb)
         return "Empty Room";
 }
 
-JoinRule
+mtx::events::state::JoinRule
 Cache::getRoomJoinRule(lmdb::txn &txn, lmdb::dbi &statesdb)
 {
         using namespace mtx::events;
@@ -1516,14 +1523,14 @@ Cache::getRoomJoinRule(lmdb::txn &txn, lmdb::dbi &statesdb)
 
         if (res) {
                 try {
-                        StateEvent<JoinRules> msg =
+                        StateEvent<state::JoinRules> msg =
                           json::parse(std::string(event.data(), event.size()));
                         return msg.content.join_rule;
                 } catch (const json::exception &e) {
                         nhlog::db()->warn("failed to parse m.room.join_rule event: {}", e.what());
                 }
         }
-        return JoinRule::Knock;
+        return state::JoinRule::Knock;
 }
 
 bool
@@ -2313,3 +2320,91 @@ from_json(const json &j, RoomInfo &info)
         if (j.count("tags"))
                 info.tags = j.at("tags").get<std::vector<std::string>>();
 }
+
+int
+numeric_key_comparison(const MDB_val *a, const MDB_val *b)
+{
+        auto lhs = std::stoull(std::string((char *)a->mv_data, a->mv_size));
+        auto rhs = std::stoull(std::string((char *)b->mv_data, b->mv_size));
+
+        if (lhs < rhs)
+                return 1;
+        else if (lhs == rhs)
+                return 0;
+
+        return -1;
+}
+
+void
+to_json(json &j, const ReadReceiptKey &key)
+{
+        j = json{{"event_id", key.event_id}, {"room_id", key.room_id}};
+}
+
+void
+from_json(const json &j, ReadReceiptKey &key)
+{
+        key.event_id = j.at("event_id").get<std::string>();
+        key.room_id  = j.at("room_id").get<std::string>();
+}
+
+void
+to_json(json &j, const MemberInfo &info)
+{
+        j["name"]       = info.name;
+        j["avatar_url"] = info.avatar_url;
+}
+
+void
+from_json(const json &j, MemberInfo &info)
+{
+        info.name       = j.at("name");
+        info.avatar_url = j.at("avatar_url");
+}
+
+void
+to_json(nlohmann::json &obj, const OutboundGroupSessionData &msg)
+{
+        obj["session_id"]    = msg.session_id;
+        obj["session_key"]   = msg.session_key;
+        obj["message_index"] = msg.message_index;
+}
+
+void
+from_json(const nlohmann::json &obj, OutboundGroupSessionData &msg)
+{
+        msg.session_id    = obj.at("session_id");
+        msg.session_key   = obj.at("session_key");
+        msg.message_index = obj.at("message_index");
+}
+
+void
+to_json(nlohmann::json &obj, const DevicePublicKeys &msg)
+{
+        obj["ed25519"]    = msg.ed25519;
+        obj["curve25519"] = msg.curve25519;
+}
+
+void
+from_json(const nlohmann::json &obj, DevicePublicKeys &msg)
+{
+        msg.ed25519    = obj.at("ed25519");
+        msg.curve25519 = obj.at("curve25519");
+}
+
+void
+to_json(nlohmann::json &obj, const MegolmSessionIndex &msg)
+{
+        obj["room_id"]    = msg.room_id;
+        obj["session_id"] = msg.session_id;
+        obj["sender_key"] = msg.sender_key;
+}
+
+void
+from_json(const nlohmann::json &obj, MegolmSessionIndex &msg)
+{
+        msg.room_id    = obj.at("room_id");
+        msg.session_id = obj.at("session_id");
+        msg.sender_key = obj.at("sender_key");
+}
+
diff --git a/src/Cache.h b/src/Cache.h
index 878ac9cea..02346287b 100644
--- a/src/Cache.h
+++ b/src/Cache.h
@@ -28,224 +28,16 @@
 #include <lmdb++.h>
 #include <nlohmann/json.hpp>
 
-#include <mtx/events/join_rules.hpp>
 #include <mtx/responses.hpp>
 #include <mtxclient/crypto/client.hpp>
 
+#include "CacheCryptoStructs.h"
+#include "CacheStructs.h"
 #include "Logging.h"
 #include "MatrixClient.h"
 
-using mtx::events::state::JoinRule;
-
-struct RoomMember
-{
-        QString user_id;
-        QString display_name;
-        QImage avatar;
-};
-
-struct SearchResult
-{
-        QString user_id;
-        QString display_name;
-};
-
-static int
-numeric_key_comparison(const MDB_val *a, const MDB_val *b)
-{
-        auto lhs = std::stoull(std::string((char *)a->mv_data, a->mv_size));
-        auto rhs = std::stoull(std::string((char *)b->mv_data, b->mv_size));
-
-        if (lhs < rhs)
-                return 1;
-        else if (lhs == rhs)
-                return 0;
-
-        return -1;
-}
-
-Q_DECLARE_METATYPE(SearchResult)
-Q_DECLARE_METATYPE(QVector<SearchResult>)
-Q_DECLARE_METATYPE(RoomMember)
-Q_DECLARE_METATYPE(mtx::responses::Timeline)
-
-//! Used to uniquely identify a list of read receipts.
-struct ReadReceiptKey
-{
-        std::string event_id;
-        std::string room_id;
-};
-
-inline void
-to_json(json &j, const ReadReceiptKey &key)
-{
-        j = json{{"event_id", key.event_id}, {"room_id", key.room_id}};
-}
-
-inline void
-from_json(const json &j, ReadReceiptKey &key)
-{
-        key.event_id = j.at("event_id").get<std::string>();
-        key.room_id  = j.at("room_id").get<std::string>();
-}
-
-struct DescInfo
-{
-        QString event_id;
-        QString userid;
-        QString body;
-        QString timestamp;
-        QDateTime datetime;
-};
-
-//! UI info associated with a room.
-struct RoomInfo
-{
-        //! The calculated name of the room.
-        std::string name;
-        //! The topic of the room.
-        std::string topic;
-        //! The calculated avatar url of the room.
-        std::string avatar_url;
-        //! The calculated version of this room set at creation time.
-        std::string version;
-        //! Whether or not the room is an invite.
-        bool is_invite = false;
-        //! Total number of members in the room.
-        int16_t member_count = 0;
-        //! Who can access to the room.
-        JoinRule join_rule = JoinRule::Public;
-        bool guest_access  = false;
-        //! Metadata describing the last message in the timeline.
-        DescInfo msgInfo;
-        //! The list of tags associated with this room
-        std::vector<std::string> tags;
-};
-
-void
-to_json(json &j, const RoomInfo &info);
-
-void
-from_json(const json &j, RoomInfo &info);
-
-//! Basic information per member;
-struct MemberInfo
-{
-        std::string name;
-        std::string avatar_url;
-};
-
-inline void
-to_json(json &j, const MemberInfo &info)
-{
-        j["name"]       = info.name;
-        j["avatar_url"] = info.avatar_url;
-}
-
-inline void
-from_json(const json &j, MemberInfo &info)
-{
-        info.name       = j.at("name");
-        info.avatar_url = j.at("avatar_url");
-}
-
-struct RoomSearchResult
-{
-        std::string room_id;
-        RoomInfo info;
-};
-
-Q_DECLARE_METATYPE(RoomSearchResult)
-Q_DECLARE_METATYPE(RoomInfo)
-
-// Extra information associated with an outbound megolm session.
-struct OutboundGroupSessionData
-{
-        std::string session_id;
-        std::string session_key;
-        uint64_t message_index = 0;
-};
-
-inline void
-to_json(nlohmann::json &obj, const OutboundGroupSessionData &msg)
-{
-        obj["session_id"]    = msg.session_id;
-        obj["session_key"]   = msg.session_key;
-        obj["message_index"] = msg.message_index;
-}
-
-inline void
-from_json(const nlohmann::json &obj, OutboundGroupSessionData &msg)
-{
-        msg.session_id    = obj.at("session_id");
-        msg.session_key   = obj.at("session_key");
-        msg.message_index = obj.at("message_index");
-}
-
-struct OutboundGroupSessionDataRef
-{
-        OlmOutboundGroupSession *session;
-        OutboundGroupSessionData data;
-};
-
-struct DevicePublicKeys
-{
-        std::string ed25519;
-        std::string curve25519;
-};
-
-inline void
-to_json(nlohmann::json &obj, const DevicePublicKeys &msg)
-{
-        obj["ed25519"]    = msg.ed25519;
-        obj["curve25519"] = msg.curve25519;
-}
-
-inline void
-from_json(const nlohmann::json &obj, DevicePublicKeys &msg)
-{
-        msg.ed25519    = obj.at("ed25519");
-        msg.curve25519 = obj.at("curve25519");
-}
-
-//! Represents a unique megolm session identifier.
-struct MegolmSessionIndex
-{
-        //! The room in which this session exists.
-        std::string room_id;
-        //! The session_id of the megolm session.
-        std::string session_id;
-        //! The curve25519 public key of the sender.
-        std::string sender_key;
-};
-
-inline void
-to_json(nlohmann::json &obj, const MegolmSessionIndex &msg)
-{
-        obj["room_id"]    = msg.room_id;
-        obj["session_id"] = msg.session_id;
-        obj["sender_key"] = msg.sender_key;
-}
-
-inline void
-from_json(const nlohmann::json &obj, MegolmSessionIndex &msg)
-{
-        msg.room_id    = obj.at("room_id");
-        msg.session_id = obj.at("session_id");
-        msg.sender_key = obj.at("sender_key");
-}
-
-struct OlmSessionStorage
-{
-        // Megolm sessions
-        std::map<std::string, mtx::crypto::InboundGroupSessionPtr> group_inbound_sessions;
-        std::map<std::string, mtx::crypto::OutboundGroupSessionPtr> group_outbound_sessions;
-        std::map<std::string, OutboundGroupSessionData> group_outbound_session_data;
-
-        // Guards for accessing megolm sessions.
-        std::mutex group_outbound_mtx;
-        std::mutex group_inbound_mtx;
-};
+int
+numeric_key_comparison(const MDB_val *a, const MDB_val *b);
 
 class Cache : public QObject
 {
@@ -287,7 +79,7 @@ public:
         //! Calculate & return the name of the room.
         QString getRoomName(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb);
         //! Get room join rules
-        JoinRule getRoomJoinRule(lmdb::txn &txn, lmdb::dbi &statesdb);
+        mtx::events::state::JoinRule getRoomJoinRule(lmdb::txn &txn, lmdb::dbi &statesdb);
         bool getRoomGuestAccess(lmdb::txn &txn, lmdb::dbi &statesdb);
         //! Retrieve the topic of the room if any.
         QString getRoomTopic(lmdb::txn &txn, lmdb::dbi &statesdb);
diff --git a/src/CacheCryptoStructs.h b/src/CacheCryptoStructs.h
new file mode 100644
index 000000000..14c9c86b2
--- /dev/null
+++ b/src/CacheCryptoStructs.h
@@ -0,0 +1,67 @@
+#pragma once
+
+#include <map>
+#include <mutex>
+
+//#include <nlohmann/json.hpp>
+
+#include <mtx/responses.hpp>
+#include <mtxclient/crypto/client.hpp>
+
+// Extra information associated with an outbound megolm session.
+struct OutboundGroupSessionData
+{
+        std::string session_id;
+        std::string session_key;
+        uint64_t message_index = 0;
+};
+
+void
+to_json(nlohmann::json &obj, const OutboundGroupSessionData &msg);
+void
+from_json(const nlohmann::json &obj, OutboundGroupSessionData &msg);
+
+struct OutboundGroupSessionDataRef
+{
+        OlmOutboundGroupSession *session;
+        OutboundGroupSessionData data;
+};
+
+struct DevicePublicKeys
+{
+        std::string ed25519;
+        std::string curve25519;
+};
+
+void
+to_json(nlohmann::json &obj, const DevicePublicKeys &msg);
+void
+from_json(const nlohmann::json &obj, DevicePublicKeys &msg);
+
+//! Represents a unique megolm session identifier.
+struct MegolmSessionIndex
+{
+        //! The room in which this session exists.
+        std::string room_id;
+        //! The session_id of the megolm session.
+        std::string session_id;
+        //! The curve25519 public key of the sender.
+        std::string sender_key;
+};
+
+void
+to_json(nlohmann::json &obj, const MegolmSessionIndex &msg);
+void
+from_json(const nlohmann::json &obj, MegolmSessionIndex &msg);
+
+struct OlmSessionStorage
+{
+        // Megolm sessions
+        std::map<std::string, mtx::crypto::InboundGroupSessionPtr> group_inbound_sessions;
+        std::map<std::string, mtx::crypto::OutboundGroupSessionPtr> group_outbound_sessions;
+        std::map<std::string, OutboundGroupSessionData> group_outbound_session_data;
+
+        // Guards for accessing megolm sessions.
+        std::mutex group_outbound_mtx;
+        std::mutex group_inbound_mtx;
+};
diff --git a/src/CacheStructs.h b/src/CacheStructs.h
new file mode 100644
index 000000000..275d20cb6
--- /dev/null
+++ b/src/CacheStructs.h
@@ -0,0 +1,91 @@
+#pragma once
+
+#include <QDateTime>
+#include <QImage>
+#include <QString>
+
+#include <string>
+
+#include <mtx/events/join_rules.hpp>
+
+struct RoomMember
+{
+        QString user_id;
+        QString display_name;
+        QImage avatar;
+};
+
+struct SearchResult
+{
+        QString user_id;
+        QString display_name;
+};
+
+//! Used to uniquely identify a list of read receipts.
+struct ReadReceiptKey
+{
+        std::string event_id;
+        std::string room_id;
+};
+
+void
+to_json(json &j, const ReadReceiptKey &key);
+
+void
+from_json(const json &j, ReadReceiptKey &key);
+
+struct DescInfo
+{
+        QString event_id;
+        QString userid;
+        QString body;
+        QString timestamp;
+        QDateTime datetime;
+};
+
+//! UI info associated with a room.
+struct RoomInfo
+{
+        //! The calculated name of the room.
+        std::string name;
+        //! The topic of the room.
+        std::string topic;
+        //! The calculated avatar url of the room.
+        std::string avatar_url;
+        //! The calculated version of this room set at creation time.
+        std::string version;
+        //! Whether or not the room is an invite.
+        bool is_invite = false;
+        //! Total number of members in the room.
+        int16_t member_count = 0;
+        //! Who can access to the room.
+        mtx::events::state::JoinRule join_rule = mtx::events::state::JoinRule::Public;
+        bool guest_access                      = false;
+        //! Metadata describing the last message in the timeline.
+        DescInfo msgInfo;
+        //! The list of tags associated with this room
+        std::vector<std::string> tags;
+};
+
+void
+to_json(json &j, const RoomInfo &info);
+void
+from_json(const json &j, RoomInfo &info);
+
+//! Basic information per member;
+struct MemberInfo
+{
+        std::string name;
+        std::string avatar_url;
+};
+
+void
+to_json(json &j, const MemberInfo &info);
+void
+from_json(const json &j, MemberInfo &info);
+
+struct RoomSearchResult
+{
+        std::string room_id;
+        RoomInfo info;
+};
diff --git a/src/ChatPage.h b/src/ChatPage.h
index 6ca30b3d1..6337f800e 100644
--- a/src/ChatPage.h
+++ b/src/ChatPage.h
@@ -32,7 +32,7 @@
 #include <QTimer>
 #include <QWidget>
 
-#include "Cache.h"
+#include "CacheStructs.h"
 #include "CommunitiesList.h"
 #include "MatrixClient.h"
 #include "Utils.h"
diff --git a/src/CommunitiesList.h b/src/CommunitiesList.h
index b18df654e..fbb63ff0c 100644
--- a/src/CommunitiesList.h
+++ b/src/CommunitiesList.h
@@ -4,7 +4,7 @@
 #include <QSharedPointer>
 #include <QVBoxLayout>
 
-#include "Cache.h"
+#include "CacheStructs.h"
 #include "CommunitiesListItem.h"
 #include "ui/Theme.h"
 
@@ -53,3 +53,4 @@ private:
 
         std::map<QString, QSharedPointer<CommunitiesListItem>> communities_;
 };
+
diff --git a/src/RoomInfoListItem.cpp b/src/RoomInfoListItem.cpp
index 1e06d9147..926e13590 100644
--- a/src/RoomInfoListItem.cpp
+++ b/src/RoomInfoListItem.cpp
@@ -97,7 +97,7 @@ RoomInfoListItem::init(QWidget *parent)
         menu_->addAction(leaveRoom_);
 }
 
-RoomInfoListItem::RoomInfoListItem(QString room_id, RoomInfo info, QWidget *parent)
+RoomInfoListItem::RoomInfoListItem(QString room_id, const RoomInfo &info, QWidget *parent)
   : QWidget(parent)
   , roomType_{info.is_invite ? RoomType::Invited : RoomType::Joined}
   , roomId_(std::move(room_id))
diff --git a/src/RoomInfoListItem.h b/src/RoomInfoListItem.h
index 54e02a763..16553c733 100644
--- a/src/RoomInfoListItem.h
+++ b/src/RoomInfoListItem.h
@@ -22,9 +22,10 @@
 #include <QSharedPointer>
 #include <QWidget>
 
-#include "Cache.h"
 #include <mtx/responses.hpp>
 
+#include "CacheStructs.h"
+
 class Menu;
 class RippleOverlay;
 
@@ -64,7 +65,7 @@ class RoomInfoListItem : public QWidget
         Q_PROPERTY(QColor btnTextColor READ btnTextColor WRITE setBtnTextColor)
 
 public:
-        RoomInfoListItem(QString room_id, RoomInfo info, QWidget *parent = 0);
+        RoomInfoListItem(QString room_id, const RoomInfo &info, QWidget *parent = 0);
 
         void updateUnreadMessageCount(int count, int highlightedCount);
         void clearUnreadMessageCount() { updateUnreadMessageCount(0, 0); };
diff --git a/src/dialogs/RoomSettings.cpp b/src/dialogs/RoomSettings.cpp
index 25909cd86..1be33d33b 100644
--- a/src/dialogs/RoomSettings.cpp
+++ b/src/dialogs/RoomSettings.cpp
@@ -248,10 +248,10 @@ RoomSettings::RoomSettings(const QString &room_id, QWidget *parent)
                         switch (index) {
                         case 0:
                         case 1:
-                                event.join_rule = JoinRule::Public;
+                                event.join_rule = state::JoinRule::Public;
                                 break;
                         default:
-                                event.join_rule = JoinRule::Invite;
+                                event.join_rule = state::JoinRule::Invite;
                         }
 
                         return event;
@@ -260,7 +260,7 @@ RoomSettings::RoomSettings(const QString &room_id, QWidget *parent)
                 updateAccessRules(room_id_.toStdString(), join_rule, guest_access);
         });
 
-        if (info_.join_rule == JoinRule::Public) {
+        if (info_.join_rule == state::JoinRule::Public) {
                 if (info_.guest_access) {
                         accessCombo->setCurrentIndex(0);
                 } else {
@@ -342,7 +342,7 @@ RoomSettings::RoomSettings(const QString &room_id, QWidget *parent)
         }
 
         // Hide encryption option for public rooms.
-        if (!usesEncryption_ && (info_.join_rule == JoinRule::Public)) {
+        if (!usesEncryption_ && (info_.join_rule == state::JoinRule::Public)) {
                 encryptionToggle_->hide();
                 encryptionLabel->hide();
 
diff --git a/src/popups/SuggestionsPopup.h b/src/popups/SuggestionsPopup.h
index 1ef720b2f..536c82fbc 100644
--- a/src/popups/SuggestionsPopup.h
+++ b/src/popups/SuggestionsPopup.h
@@ -10,6 +10,8 @@
 #include "../ChatPage.h"
 #include "PopupItem.h"
 
+Q_DECLARE_METATYPE(QVector<SearchResult>)
+
 class SuggestionsPopup : public QWidget
 {
         Q_OBJECT
diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h
index 05e059620..5391c7c10 100644
--- a/src/timeline/TimelineModel.h
+++ b/src/timeline/TimelineModel.h
@@ -9,7 +9,7 @@
 #include <mtx/common.hpp>
 #include <mtx/responses.hpp>
 
-#include "Cache.h"
+#include "CacheCryptoStructs.h"
 #include "Logging.h"
 #include "MatrixClient.h"
 
-- 
GitLab