diff --git a/CMakeLists.txt b/CMakeLists.txt index d533fae50..25126c46b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -288,12 +288,16 @@ set(${PROJECT_NAME}_SOURCES src/core/toxfilepause.h src/core/toxid.cpp src/core/toxid.h + src/core/groupid.cpp + src/core/groupid.h src/core/toxlogger.cpp src/core/toxlogger.h src/core/toxoptions.cpp src/core/toxoptions.h src/core/toxpk.cpp src/core/toxpk.h + src/core/contactid.cpp + src/core/contactid.h src/core/toxstring.cpp src/core/toxstring.h src/friendlist.cpp diff --git a/cmake/Testing.cmake b/cmake/Testing.cmake index 7ec68ca1d..6906df5f2 100644 --- a/cmake/Testing.cmake +++ b/cmake/Testing.cmake @@ -19,7 +19,7 @@ function(auto_test subsystem module) endfunction() auto_test(core core) -auto_test(core toxpk) +auto_test(core contactid) auto_test(core toxid) auto_test(core toxstring) auto_test(chatlog textformatter) diff --git a/src/core/contactid.cpp b/src/core/contactid.cpp new file mode 100644 index 000000000..1aee125af --- /dev/null +++ b/src/core/contactid.cpp @@ -0,0 +1,93 @@ +#include +#include +#include +#include +#include "src/core/contactid.h" + +/** + * @brief The default constructor. Creates an empty id. + */ +ContactId::ContactId() + : id() +{ +} + +/** + * @brief Constructs a ContactId from bytes. + * @param rawId The bytes to construct the ContactId from. + */ +ContactId::ContactId(const QByteArray& rawId) +{ + id = QByteArray(rawId); +} + +/** + * @brief Compares the equality of the ContactId. + * @param other ContactId to compare. + * @return True if both ContactId are equal, false otherwise. + */ +bool ContactId::operator==(const ContactId& other) const +{ + return id == other.id; +} + +/** + * @brief Compares the inequality of the ContactId. + * @param other ContactId to compare. + * @return True if both ContactIds are not equal, false otherwise. + */ +bool ContactId::operator!=(const ContactId& other) const +{ + return id != other.id; +} + +/** + * @brief Compares two ContactIds + * @param other ContactId to compare. + * @return True if this ContactIds is less than the other ContactId, false otherwise. + */ +bool ContactId::operator<(const ContactId& other) const +{ + return id < other.id; +} + +/** + * @brief Converts the ContactId to a uppercase hex string. + * @return QString containing the hex representation of the id + */ +QString ContactId::toString() const +{ + return id.toHex().toUpper(); +} + +/** + * @brief Returns a pointer to the raw id data. + * @return Pointer to the raw id data, which is exactly `ContactId::getPkSize()` + * bytes long. Returns a nullptr if the ContactId is empty. + */ +const uint8_t* ContactId::getData() const +{ + if (id.isEmpty()) { + return nullptr; + } + + return reinterpret_cast(id.constData()); +} + +/** + * @brief Get a copy of the id + * @return Copied id bytes + */ +QByteArray ContactId::getByteArray() const +{ + return QByteArray(id); // TODO: Is a copy really necessary? +} + +/** + * @brief Checks if the ContactId contains a id. + * @return True if there is a id, False otherwise. + */ +bool ContactId::isEmpty() const +{ + return id.isEmpty(); +} diff --git a/src/core/contactid.h b/src/core/contactid.h new file mode 100644 index 000000000..bdc1b8458 --- /dev/null +++ b/src/core/contactid.h @@ -0,0 +1,38 @@ +#ifndef CONTACTID_H +#define CONTACTID_H + +#include +#include +#include +#include +#include + +class ContactId +{ +public: + virtual ~ContactId() = default; + ContactId& operator=(const ContactId& other) = default; + ContactId& operator=(ContactId&& other) = default; + bool operator==(const ContactId& other) const; + bool operator!=(const ContactId& other) const; + bool operator<(const ContactId& other) const; + QString toString() const; + QByteArray getByteArray() const; + const uint8_t* getData() const; + bool isEmpty() const; + virtual int getSize() const = 0; + +protected: + ContactId(); + explicit ContactId(const QByteArray& rawId); + QByteArray id; +}; + +inline uint qHash(const std::shared_ptr id) +{ + return qHash(id->getByteArray()); +} + +using ContactIdPtr = std::shared_ptr; + +#endif // CONTACTID_H diff --git a/src/core/core.cpp b/src/core/core.cpp index 8dcf757b8..e1e034ad6 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -455,7 +455,7 @@ void Core::bootstrapDht() ToxPk pk = ToxId{dhtServer.userId}.getPublicKey(); - const uint8_t* pkPtr = reinterpret_cast(pk.getBytes()); + const uint8_t* pkPtr = pk.getData(); if (!tox_bootstrap(tox.get(), address.constData(), dhtServer.port, pkPtr, nullptr)) { qDebug() << "Error bootstrapping from " + dhtServer.name; @@ -599,7 +599,7 @@ void Core::acceptFriendRequest(const ToxPk& friendPk) { QMutexLocker ml{&coreLoopLock}; // TODO: error handling - uint32_t friendId = tox_friend_add_norequest(tox.get(), friendPk.getBytes(), nullptr); + uint32_t friendId = tox_friend_add_norequest(tox.get(), friendPk.getData(), nullptr); if (friendId == std::numeric_limits::max()) { emit failedToAddFriend(friendPk); } else { @@ -1027,17 +1027,18 @@ void Core::loadGroups() for(size_t i = 0; i < groupCount; ++i) { TOX_ERR_CONFERENCE_TITLE error; - size_t titleSize = tox_conference_get_title_size(tox.get(), groupIds[i], &error); + const auto groupId = static_cast(groupIds[i]); + size_t titleSize = tox_conference_get_title_size(tox.get(), groupId, &error); if (LogConferenceTitleError(error)) { continue; } QByteArray name(titleSize, Qt::Uninitialized); - if (!tox_conference_get_title(tox.get(), groupIds[i], reinterpret_cast(name.data()), &error)) + if (!tox_conference_get_title(tox.get(), groupId, reinterpret_cast(name.data()), &error)) if (LogConferenceTitleError(error)) { continue; } - emit emptyGroupCreated(static_cast(groupIds[i]), ToxString(name).getQString()); + emit emptyGroupCreated(groupId, getGroupPersistentId(groupId), ToxString(name).getQString()); } delete[] groupIds; @@ -1095,6 +1096,19 @@ bool Core::parsePeerQueryError(Tox_Err_Conference_Peer_Query error) const } } +GroupId Core::getGroupPersistentId(uint32_t groupNumber) { + QMutexLocker ml{&coreLoopLock}; + + size_t conferenceIdSize = TOX_CONFERENCE_UID_SIZE; + QByteArray groupPersistentId(conferenceIdSize, Qt::Uninitialized); + if (tox_conference_get_id(tox.get(), groupNumber, reinterpret_cast(groupPersistentId.data()))) { + return GroupId{groupPersistentId}; + } else { + qCritical() << "Failed to get conference ID of group" << groupNumber; + return {}; + } +} + /** * @brief Get number of peers in the conference. * @return The number of peers in the conference. UINT32_MAX on failure. @@ -1323,7 +1337,7 @@ int Core::createGroup(uint8_t type) switch (error) { case TOX_ERR_CONFERENCE_NEW_OK: - emit emptyGroupCreated(groupId); + emit emptyGroupCreated(groupId, getGroupPersistentId(groupId)); return groupId; case TOX_ERR_CONFERENCE_NEW_INIT: @@ -1335,7 +1349,7 @@ int Core::createGroup(uint8_t type) } } else if (type == TOX_CONFERENCE_TYPE_AV) { uint32_t groupId = toxav_add_av_groupchat(tox.get(), CoreAV::groupCallCallback, this); - emit emptyGroupCreated(groupId); + emit emptyGroupCreated(groupId, getGroupPersistentId(groupId)); return groupId; } else { qWarning() << "createGroup: Unknown type " << type; @@ -1366,7 +1380,7 @@ bool Core::hasFriendWithPublicKey(const ToxPk& publicKey) const } // TODO: error handling - uint32_t friendId = tox_friend_by_public_key(tox.get(), publicKey.getBytes(), nullptr); + uint32_t friendId = tox_friend_by_public_key(tox.get(), publicKey.getData(), nullptr); return friendId != std::numeric_limits::max(); } @@ -1443,7 +1457,7 @@ QString Core::getPeerName(const ToxPk& id) const QMutexLocker ml{&coreLoopLock}; QString name; - uint32_t friendId = tox_friend_by_public_key(tox.get(), id.getBytes(), nullptr); + uint32_t friendId = tox_friend_by_public_key(tox.get(), id.getData(), nullptr); if (friendId == std::numeric_limits::max()) { qWarning() << "getPeerName: No such peer"; return name; diff --git a/src/core/core.h b/src/core/core.h index ac8ee2273..7a3ccf85b 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -23,6 +23,8 @@ #include "toxfile.h" #include "toxid.h" +#include "toxpk.h" +#include "groupid.h" #include "src/util/strongtype.h" #include @@ -77,10 +79,9 @@ public: static const QString TOX_EXT; static QStringList splitMessage(const QString& message, int maxLen); - QString getPeerName(const ToxPk& id) const; - QVector getFriendList() const; + GroupId getGroupPersistentId(uint32_t groupNumber); uint32_t getGroupNumberPeers(int groupId) const; QString getGroupPeerName(int groupId, int peerId) const; ToxPk getGroupPeerPk(int groupId, int peerId) const; @@ -171,7 +172,7 @@ signals: void friendRemoved(uint32_t friendId); void friendLastSeenChanged(uint32_t friendId, const QDateTime& dateTime); - void emptyGroupCreated(int groupnumber, const QString& title = QString()); + void emptyGroupCreated(int groupnumber, const GroupId groupId, const QString& title = QString()); void groupInviteReceived(const GroupInvite& inviteInfo); void groupMessageReceived(int groupnumber, int peernumber, const QString& message, bool isAction); void groupNamelistChanged(int groupnumber, int peernumber, uint8_t change); diff --git a/src/core/groupid.cpp b/src/core/groupid.cpp new file mode 100644 index 000000000..981e3f411 --- /dev/null +++ b/src/core/groupid.cpp @@ -0,0 +1,61 @@ +#include "groupid.h" + +#include + +#include +#include + +#include + +/** + * @class GroupId + * @brief This class represents a long term persistent group identifier. + */ + +/** + * @brief The default constructor. Creates an empty Tox group ID. + */ +GroupId::GroupId() + : ContactId() +{ +} + +/** + * @brief The copy constructor. + * @param other GroupId to copy + */ +GroupId::GroupId(const GroupId& other) + : ContactId(other.id) +{ +} + +/** + * @brief Constructs a GroupId from bytes. + * @param rawId The bytes to construct the GroupId from. The lenght must be exactly + * TOX_CONFERENCE_UID_SIZE, else the GroupId will be empty. + */ +GroupId::GroupId(const QByteArray& rawId) + : ContactId([rawId](){ + assert(rawId.length() == TOX_CONFERENCE_UID_SIZE); + return rawId;}()) +{ +} + +/** + * @brief Constructs a GroupId from bytes. + * @param rawId The bytes to construct the GroupId from, will read exactly + * TOX_CONFERENCE_UID_SIZE from the specified buffer. + */ +GroupId::GroupId(const uint8_t* rawId) + : ContactId(QByteArray(reinterpret_cast(rawId), TOX_CONFERENCE_UID_SIZE)) +{ +} + +/** + * @brief Get size of public id in bytes. + * @return Size of public id in bytes. + */ +int GroupId::getSize() const +{ + return TOX_CONFERENCE_UID_SIZE; +} diff --git a/src/core/groupid.h b/src/core/groupid.h new file mode 100644 index 000000000..3ba1d834e --- /dev/null +++ b/src/core/groupid.h @@ -0,0 +1,18 @@ +#ifndef GROUPID_H +#define GROUPID_H + +#include "src/core/contactid.h" +#include +#include + +class GroupId : public ContactId +{ +public: + GroupId(); + GroupId(const GroupId& other); + explicit GroupId(const QByteArray& rawId); + explicit GroupId(const uint8_t* rawId); + int getSize() const override; +}; + +#endif // GROUPID_H diff --git a/src/core/toxid.cpp b/src/core/toxid.cpp index decd7a9b2..38d092a06 100644 --- a/src/core/toxid.cpp +++ b/src/core/toxid.cpp @@ -193,7 +193,12 @@ const uint8_t* ToxId::getBytes() const */ ToxPk ToxId::getPublicKey() const { - return ToxPk(toxId.left(TOX_PUBLIC_KEY_SIZE)); + auto const pkBytes = toxId.left(TOX_PUBLIC_KEY_SIZE); + if (pkBytes.isEmpty()) { + return ToxPk{}; + } else { + return ToxPk{pkBytes}; + } } /** diff --git a/src/core/toxpk.cpp b/src/core/toxpk.cpp index 0f4b777ea..82dbbdb1f 100644 --- a/src/core/toxpk.cpp +++ b/src/core/toxpk.cpp @@ -5,6 +5,8 @@ #include #include +#include + /** * @class ToxPk * @brief This class represents a Tox Public Key, which is a part of Tox ID. @@ -14,7 +16,7 @@ * @brief The default constructor. Creates an empty Tox key. */ ToxPk::ToxPk() - : key() + : ContactId() { } @@ -23,7 +25,7 @@ ToxPk::ToxPk() * @param other ToxPk to copy */ ToxPk::ToxPk(const ToxPk& other) - : key(other.key) + : ContactId(other.id) { } @@ -33,12 +35,10 @@ ToxPk::ToxPk(const ToxPk& other) * TOX_PUBLIC_KEY_SIZE, else the ToxPk will be empty. */ ToxPk::ToxPk(const QByteArray& rawId) + : ContactId([rawId](){ + assert(rawId.length() == TOX_PUBLIC_KEY_SIZE); + return rawId;}()) { - if (rawId.length() == TOX_PUBLIC_KEY_SIZE) { - key = QByteArray(rawId); - } else { - key = QByteArray(); - } } /** @@ -47,86 +47,15 @@ ToxPk::ToxPk(const QByteArray& rawId) * TOX_PUBLIC_KEY_SIZE from the specified buffer. */ ToxPk::ToxPk(const uint8_t* rawId) + : ContactId(QByteArray(reinterpret_cast(rawId), TOX_PUBLIC_KEY_SIZE)) { - key = QByteArray(reinterpret_cast(rawId), TOX_PUBLIC_KEY_SIZE); -} - -/** - * @brief Compares the equality of the ToxPk. - * @param other ToxPk to compare. - * @return True if both ToxPks are equal, false otherwise. - */ -bool ToxPk::operator==(const ToxPk& other) const -{ - return key == other.key; -} - -/** - * @brief Compares the inequality of the ToxPk. - * @param other ToxPk to compare. - * @return True if both ToxPks are not equal, false otherwise. - */ -bool ToxPk::operator!=(const ToxPk& other) const -{ - return key != other.key; -} - -/** - * @brief Compares two ToxPks - * @param other ToxPk to compare. - * @return True if this ToxPks is less than the other ToxPk, false otherwise. - */ -bool ToxPk::operator<(const ToxPk& other) const -{ - return key < other.key; -} - -/** - * @brief Converts the ToxPk to a uppercase hex string. - * @return QString containing the hex representation of the key - */ -QString ToxPk::toString() const -{ - return key.toHex().toUpper(); -} - -/** - * @brief Returns a pointer to the raw key data. - * @return Pointer to the raw key data, which is exactly `ToxPk::getPkSize()` - * bytes long. Returns a nullptr if the ToxPk is empty. - */ -const uint8_t* ToxPk::getBytes() const -{ - if (key.isEmpty()) { - return nullptr; - } - - return reinterpret_cast(key.constData()); -} - -/** - * @brief Get a copy of the key - * @return Copied key bytes - */ -QByteArray ToxPk::getKey() const -{ - return QByteArray(key); // TODO: Is a copy really necessary? -} - -/** - * @brief Checks if the ToxPk contains a key. - * @return True if there is a key, False otherwise. - */ -bool ToxPk::isEmpty() const -{ - return key.isEmpty(); } /** * @brief Get size of public key in bytes. * @return Size of public key in bytes. */ -int ToxPk::getPkSize() +int ToxPk::getSize() const { return TOX_PUBLIC_KEY_SIZE; } diff --git a/src/core/toxpk.h b/src/core/toxpk.h index a78034b6f..6c8c467f0 100644 --- a/src/core/toxpk.h +++ b/src/core/toxpk.h @@ -1,32 +1,18 @@ #ifndef TOXPK_H #define TOXPK_H +#include "src/core/contactid.h" #include -#include #include -class ToxPk +class ToxPk : public ContactId { public: ToxPk(); ToxPk(const ToxPk& other); explicit ToxPk(const QByteArray& rawId); explicit ToxPk(const uint8_t* rawId); - ToxPk& operator=(const ToxPk& other) = default; - ToxPk& operator=(ToxPk&& other) = default; - - bool operator==(const ToxPk& other) const; - bool operator!=(const ToxPk& other) const; - bool operator<(const ToxPk& other) const; - QString toString() const; - QByteArray getKey() const; - const uint8_t* getBytes() const; - bool isEmpty() const; - - static int getPkSize(); - -private: - QByteArray key; + int getSize() const override; }; #endif // TOXPK_H diff --git a/src/friendlist.cpp b/src/friendlist.cpp index 5198069be..4b88f08e8 100644 --- a/src/friendlist.cpp +++ b/src/friendlist.cpp @@ -37,7 +37,7 @@ Friend* FriendList::addFriend(uint32_t friendId, const ToxPk& friendPk) QString alias = Settings::getInstance().getFriendAlias(friendPk); Friend* newfriend = new Friend(friendId, friendPk, alias); friendList[friendId] = newfriend; - key2id[friendPk.getKey()] = friendId; + key2id[friendPk.getByteArray()] = friendId; return newfriend; } @@ -71,7 +71,7 @@ void FriendList::clear() Friend* FriendList::findFriend(const ToxPk& friendPk) { - auto id = key2id.find(friendPk.getKey()); + auto id = key2id.find(friendPk.getByteArray()); if (id != key2id.end()) { Friend* f = findFriend(*id); if (!f) diff --git a/src/grouplist.cpp b/src/grouplist.cpp index ff08b3ae7..22aa4ec71 100644 --- a/src/grouplist.cpp +++ b/src/grouplist.cpp @@ -24,14 +24,14 @@ QHash GroupList::groupList; -Group* GroupList::addGroup(int groupId, const QString& name, bool isAvGroupchat, +Group* GroupList::addGroup(int groupId, const GroupId& persistentGroupId, const QString& name, bool isAvGroupchat, const QString& selfName) { auto checker = groupList.find(groupId); if (checker != groupList.end()) qWarning() << "addGroup: groupId already taken"; - Group* newGroup = new Group(groupId, name, isAvGroupchat, selfName); + Group* newGroup = new Group(groupId, persistentGroupId, name, isAvGroupchat, selfName); groupList[groupId] = newGroup; return newGroup; diff --git a/src/grouplist.h b/src/grouplist.h index 3e8989172..199c1ae1a 100644 --- a/src/grouplist.h +++ b/src/grouplist.h @@ -20,6 +20,8 @@ #ifndef GROUPLIST_H #define GROUPLIST_H +#include "src/core/groupid.h" + template class QHash; template @@ -30,7 +32,7 @@ class QString; class GroupList { public: - static Group* addGroup(int groupId, const QString& name, bool isAvGroupchat, const QString& selfName); + static Group* addGroup(int groupId, const GroupId& persistentGroupId, const QString& name, bool isAvGroupchat, const QString& selfName); static Group* findGroup(int groupId); static void removeGroup(int groupId, bool fake = false); static QList getAllGroups(); diff --git a/src/main.cpp b/src/main.cpp index 22f17f81a..717ae6433 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -365,8 +365,6 @@ int main(int argc, char* argv[]) QObject::connect(a.get(), &QApplication::aboutToQuit, cleanup); - qRegisterMetaType(); - qRegisterMetaType(); // Run int errorcode = a->exec(); diff --git a/src/model/contact.h b/src/model/contact.h index e466261b6..61a944610 100644 --- a/src/model/contact.h +++ b/src/model/contact.h @@ -20,6 +20,7 @@ #ifndef CONTACT_H #define CONTACT_H +#include "src/core/contactid.h" #include #include @@ -32,7 +33,7 @@ public: virtual void setName(const QString& name) = 0; virtual QString getDisplayedName() const = 0; virtual uint32_t getId() const = 0; - + virtual const ContactId& getPersistentId() const = 0; virtual void setEventFlag(bool flag) = 0; virtual bool getEventFlag() const = 0; diff --git a/src/model/friend.cpp b/src/model/friend.cpp index 13481b158..907bc2dc8 100644 --- a/src/model/friend.cpp +++ b/src/model/friend.cpp @@ -137,6 +137,11 @@ uint32_t Friend::getId() const return friendId; } +const ContactId& Friend::getPersistentId() const +{ + return friendPk; +} + void Friend::setEventFlag(bool flag) { hasNewEvents = flag; diff --git a/src/model/friend.h b/src/model/friend.h index e0f7ae6ee..71ad0e34d 100644 --- a/src/model/friend.h +++ b/src/model/friend.h @@ -23,6 +23,7 @@ #include "contact.h" #include "src/core/core.h" #include "src/core/toxid.h" +#include "src/core/contactid.h" #include #include @@ -47,6 +48,7 @@ public: const ToxPk& getPublicKey() const; uint32_t getId() const override; + const ContactId& getPersistentId() const override; void setStatus(Status s); Status getStatus() const; diff --git a/src/model/group.cpp b/src/model/group.cpp index e1b715c1b..32e94c672 100644 --- a/src/model/group.cpp +++ b/src/model/group.cpp @@ -22,6 +22,9 @@ #include "src/friendlist.h" #include "src/core/core.h" #include "src/core/coreav.h" +#include "src/core/contactid.h" +#include "src/core/groupid.h" +#include "src/core/toxpk.h" #include "src/persistence/settings.h" #include "src/widget/form/groupchatform.h" #include "src/widget/groupwidget.h" @@ -29,10 +32,11 @@ static const int MAX_GROUP_TITLE_LENGTH = 128; -Group::Group(int groupId, const QString& name, bool isAvGroupchat, const QString& selfName) +Group::Group(int groupId, const GroupId persistentGroupId, const QString& name, bool isAvGroupchat, const QString& selfName) : selfName{selfName} , title{name} , groupId(groupId) + , persistentGroupId{persistentGroupId} , avGroupchat{isAvGroupchat} { // in groupchats, we only notify on messages containing your name <-- dumb @@ -134,6 +138,11 @@ uint32_t Group::getId() const return groupId; } +const ContactId& Group::getPersistentId() const +{ + return persistentGroupId; +} + int Group::getPeersCount() const { return toxpks.size(); diff --git a/src/model/group.h b/src/model/group.h index dd11e68e4..19b60d56a 100644 --- a/src/model/group.h +++ b/src/model/group.h @@ -22,6 +22,8 @@ #include "contact.h" +#include "src/core/contactid.h" +#include "src/core/groupid.h" #include "src/core/toxpk.h" #include @@ -32,10 +34,10 @@ class Group : public Contact { Q_OBJECT public: - Group(int groupId, const QString& name, bool isAvGroupchat, const QString& selfName); - + Group(int groupId, const GroupId persistentGroupId, const QString& name, bool isAvGroupchat, const QString& selfName); bool isAvGroupchat() const; uint32_t getId() const override; + const ContactId& getPersistentId() const override; int getPeersCount() const; void regeneratePeerList(); const QMap& getPeerList() const; @@ -73,6 +75,7 @@ private: bool hasNewMessages; bool userWasMentioned; int groupId; + const GroupId persistentGroupId; bool avGroupchat; }; diff --git a/src/nexus.cpp b/src/nexus.cpp index 69655ec46..70dc0b226 100644 --- a/src/nexus.cpp +++ b/src/nexus.cpp @@ -99,7 +99,11 @@ void Nexus::start() qRegisterMetaType>("std::shared_ptr"); qRegisterMetaType("ToxPk"); qRegisterMetaType("ToxId"); + qRegisterMetaType("GroupId"); + qRegisterMetaType("ContactId"); qRegisterMetaType("GroupInvite"); + qRegisterMetaType("ReceiptNum"); + qRegisterMetaType("RowId"); qApp->setQuitOnLastWindowClosed(false); diff --git a/src/persistence/profile.cpp b/src/persistence/profile.cpp index 7dc50464a..3d4121295 100644 --- a/src/persistence/profile.cpp +++ b/src/persistence/profile.cpp @@ -394,7 +394,7 @@ QString Profile::avatarPath(const ToxPk& owner, bool forceUnencrypted) } QByteArray idData = ownerStr.toUtf8(); - QByteArray pubkeyData = core->getSelfId().getPublicKey().getKey(); + QByteArray pubkeyData = core->getSelfId().getPublicKey().getByteArray(); constexpr int hashSize = TOX_PUBLIC_KEY_SIZE; static_assert(hashSize >= crypto_generichash_BYTES_MIN && hashSize <= crypto_generichash_BYTES_MAX, "Hash size not supported by libsodium"); @@ -428,7 +428,7 @@ QPixmap Profile::loadAvatar(const ToxPk& owner) const QByteArray avatarData = loadAvatarData(owner); if (avatarData.isEmpty()) { - pic = QPixmap::fromImage(Identicon(owner.getKey()).toImage(16)); + pic = QPixmap::fromImage(Identicon(owner.getByteArray()).toImage(16)); } else { pic.loadFromData(avatarData); } @@ -478,7 +478,7 @@ void Profile::loadDatabase(const ToxId& id, QString password) return; } - QByteArray salt = id.getPublicKey().getKey(); + QByteArray salt = id.getPublicKey().getByteArray(); if (salt.size() != TOX_PASS_SALT_LENGTH) { qWarning() << "Couldn't compute salt from public key" << name; GUI::showError(QObject::tr("Error"), @@ -511,7 +511,7 @@ void Profile::setAvatar(QByteArray pic) avatarData = pic; } else { if (Settings::getInstance().getShowIdenticons()) { - const QImage identicon = Identicon(selfPk.getKey()).toImage(32); + const QImage identicon = Identicon(selfPk.getByteArray()).toImage(32); pixmap = QPixmap::fromImage(identicon); } else { @@ -541,7 +541,7 @@ void Profile::setFriendAvatar(const ToxPk& owner, QByteArray pic) avatarData = pic; emit friendAvatarSet(owner, pixmap); } else if (Settings::getInstance().getShowIdenticons()) { - const QImage identicon = Identicon(owner.getKey()).toImage(32); + const QImage identicon = Identicon(owner.getByteArray()).toImage(32); pixmap = QPixmap::fromImage(identicon); emit friendAvatarSet(owner, pixmap); } else { diff --git a/src/persistence/settings.cpp b/src/persistence/settings.cpp index 783586cd7..1f96bb275 100644 --- a/src/persistence/settings.cpp +++ b/src/persistence/settings.cpp @@ -320,7 +320,7 @@ void Settings::loadPersonal(QString profileName, const ToxEncrypt* passKey) if (getEnableLogging()) fp.activity = ps.value("activity", QDate()).toDate(); - friendLst.insert(ToxId(fp.addr).getPublicKey().getKey(), fp); + friendLst.insert(ToxId(fp.addr).getPublicKey().getByteArray(), fp); } ps.endArray(); } @@ -1312,7 +1312,7 @@ QString Settings::getAutoAcceptDir(const ToxPk& id) const { QMutexLocker locker{&bigLock}; - auto it = friendLst.find(id.getKey()); + auto it = friendLst.find(id.getByteArray()); if (it != friendLst.end()) return it->autoAcceptDir; @@ -1335,7 +1335,7 @@ Settings::AutoAcceptCallFlags Settings::getAutoAcceptCall(const ToxPk& id) const { QMutexLocker locker{&bigLock}; - auto it = friendLst.find(id.getKey()); + auto it = friendLst.find(id.getByteArray()); if (it != friendLst.end()) return it->autoAcceptCall; @@ -1358,7 +1358,7 @@ bool Settings::getAutoGroupInvite(const ToxPk& id) const { QMutexLocker locker{&bigLock}; - auto it = friendLst.find(id.getKey()); + auto it = friendLst.find(id.getByteArray()); if (it != friendLst.end()) { return it->autoGroupInvite; } @@ -1382,7 +1382,7 @@ QString Settings::getContactNote(const ToxPk& id) const { QMutexLocker locker{&bigLock}; - auto it = friendLst.find(id.getKey()); + auto it = friendLst.find(id.getByteArray()); if (it != friendLst.end()) return it->note; @@ -1980,7 +1980,7 @@ QString Settings::getFriendAddress(const QString& publicKey) const { QMutexLocker locker{&bigLock}; // TODO: using ToxId here is a hack - QByteArray key = ToxId(publicKey).getPublicKey().getKey(); + QByteArray key = ToxId(publicKey).getPublicKey().getByteArray(); auto it = friendLst.find(key); if (it != friendLst.end()) return it->addr; @@ -2000,7 +2000,7 @@ void Settings::updateFriendAddress(const QString& newAddr) QString Settings::getFriendAlias(const ToxPk& id) const { QMutexLocker locker{&bigLock}; - auto it = friendLst.find(id.getKey()); + auto it = friendLst.find(id.getByteArray()); if (it != friendLst.end()) return it->alias; @@ -2017,7 +2017,7 @@ void Settings::setFriendAlias(const ToxPk& id, const QString& alias) int Settings::getFriendCircleID(const ToxPk& id) const { QMutexLocker locker{&bigLock}; - auto it = friendLst.find(id.getKey()); + auto it = friendLst.find(id.getByteArray()); if (it != friendLst.end()) return it->circleID; @@ -2033,7 +2033,8 @@ void Settings::setFriendCircleID(const ToxPk& id, int circleID) QDate Settings::getFriendActivity(const ToxPk& id) const { - auto it = friendLst.find(id.getKey()); + QMutexLocker locker{&bigLock}; + auto it = friendLst.find(id.getByteArray()); if (it != friendLst.end()) return it->activity; @@ -2056,7 +2057,7 @@ void Settings::saveFriendSettings(const ToxPk& id) void Settings::removeFriendSettings(const ToxPk& id) { QMutexLocker locker{&bigLock}; - friendLst.remove(id.getKey()); + friendLst.remove(id.getByteArray()); } bool Settings::getFauxOfflineMessaging() const @@ -2375,9 +2376,9 @@ Settings::friendProp& Settings::getOrInsertFriendPropRef(const ToxPk& id) { // No mutex lock, this is a private fn that should only be called by other // public functions that already locked the mutex - auto it = friendLst.find(id.getKey()); + auto it = friendLst.find(id.getByteArray()); if (it == friendLst.end()) { - it = friendLst.insert(id.getKey(), friendProp{id.toString()}); + it = friendLst.insert(id.getByteArray(), friendProp{id.toString()}); } return *it; diff --git a/src/widget/form/addfriendform.cpp b/src/widget/form/addfriendform.cpp index 24e4a1c25..02b4f1a5f 100644 --- a/src/widget/form/addfriendform.cpp +++ b/src/widget/form/addfriendform.cpp @@ -307,7 +307,7 @@ void AddFriendForm::setIdFromClipboard() const QString trimmedId = clipboard->text().trimmed(); const QString strippedId = getToxId(trimmedId); const Core* core = Core::getInstance(); - const bool isSelf = ToxId(strippedId) != core->getSelfId(); + const bool isSelf = ToxId::isToxId(strippedId) && ToxId(strippedId) != core->getSelfId(); if (!strippedId.isEmpty() && ToxId::isToxId(strippedId) && isSelf) { toxId.setText(trimmedId); } diff --git a/src/widget/widget.cpp b/src/widget/widget.cpp index 4c2f093b2..44f3e2649 100644 --- a/src/widget/widget.cpp +++ b/src/widget/widget.cpp @@ -234,7 +234,7 @@ void Widget::init() updateCheck->checkForUpdate(); #endif - Core* core = Nexus::getCore(); + core = Nexus::getCore(); CoreFile* coreFile = core->getCoreFile(); Profile* profile = Nexus::getProfile(); profileInfo = new ProfileInfo(core, profile); @@ -256,7 +256,7 @@ void Widget::init() connect(ui->statusLabel, &CroppingLabel::editFinished, this, &Widget::onStatusMessageChanged); connect(ui->mainSplitter, &QSplitter::splitterMoved, this, &Widget::onSplitterMoved); connect(addFriendForm, &AddFriendForm::friendRequested, this, &Widget::friendRequested); - connect(groupInviteForm, &GroupInviteForm::groupCreate, Core::getInstance(), &Core::createGroup); + connect(groupInviteForm, &GroupInviteForm::groupCreate, core, &Core::createGroup); connect(timer, &QTimer::timeout, this, &Widget::onUserAwayCheck); connect(timer, &QTimer::timeout, this, &Widget::onEventIconTick); connect(timer, &QTimer::timeout, this, &Widget::onTryCreateTrayIcon); @@ -603,7 +603,7 @@ void Widget::resizeEvent(QResizeEvent* event) QString Widget::getUsername() { - return Nexus::getCore()->getUsername(); + return core->getUsername(); } void Widget::onSelfAvatarLoaded(const QPixmap& pic) @@ -614,13 +614,13 @@ void Widget::onSelfAvatarLoaded(const QPixmap& pic) void Widget::onConnected() { ui->statusButton->setEnabled(true); - emit statusSet(Nexus::getCore()->getStatus()); + emit statusSet(core->getStatus()); } void Widget::onDisconnected() { ui->statusButton->setEnabled(false); - emit Core::getInstance()->statusSet(Status::Offline); + emit core->statusSet(Status::Offline); } void Widget::onFailedToStartCore() @@ -909,7 +909,7 @@ void Widget::setUsername(const QString& username) void Widget::onStatusMessageChanged(const QString& newStatusMessage) { // Keep old status message until Core tells us to set it. - Nexus::getCore()->setStatusMessage(newStatusMessage); + core->setStatusMessage(newStatusMessage); } void Widget::setStatusMessage(const QString& statusMessage) @@ -965,7 +965,7 @@ void Widget::onStopNotification() void Widget::onRejectCall(uint32_t friendId) { - CoreAV* const av = Core::getInstance()->getAv(); + CoreAV* const av = core->getAv(); av->cancelCall(friendId); } @@ -1447,7 +1447,7 @@ bool Widget::newMessageAlert(QWidget* currentWindow, bool isActive, bool sound, #endif eventFlag = true; } - bool isBusy = Nexus::getCore()->getStatus() == Status::Busy; + bool isBusy = core->getStatus() == Status::Busy; bool busySound = settings.getBusySound(); bool notifySound = settings.getNotifySound(); @@ -1518,7 +1518,7 @@ void Widget::removeFriend(Friend* f, bool fake) FriendList::removeFriend(friendId, fake); if (!fake) { - Nexus::getCore()->removeFriend(friendId); + core->removeFriend(friendId); } friendWidgets.remove(friendId); @@ -1585,7 +1585,7 @@ ContentDialog* Widget::createContentDialog() const connect(contentDialog, &ContentDialog::friendDialogShown, this, &Widget::onFriendDialogShown); connect(contentDialog, &ContentDialog::groupDialogShown, this, &Widget::onGroupDialogShown); - connect(Core::getInstance(), &Core::usernameSet, contentDialog, &ContentDialog::setUsername); + connect(core, &Core::usernameSet, contentDialog, &ContentDialog::setUsername); connect(&settings, &Settings::groupchatPositionChanged, contentDialog, &ContentDialog::reorderLayouts); #ifdef Q_OS_MAC @@ -1604,10 +1604,11 @@ ContentLayout* Widget::createContentDialog(DialogType type) const class Dialog : public ActivateDialog { public: - explicit Dialog(DialogType type, Settings& settings) + explicit Dialog(DialogType type, Settings& settings, Core* core) : ActivateDialog(nullptr, Qt::Window) , type(type) , settings(settings) + , core{core} { restoreGeometry(settings.getDialogSettingsGeometry()); Translator::registerHandler(std::bind(&Dialog::retranslateUi, this), this); @@ -1615,7 +1616,7 @@ ContentLayout* Widget::createContentDialog(DialogType type) const setWindowIcon(QIcon(":/img/icons/qtox.svg")); setStyleSheet(Style::getStylesheet("window/general.css")); - connect(Core::getInstance(), &Core::usernameSet, this, &Dialog::retranslateUi); + connect(core, &Core::usernameSet, this, &Dialog::retranslateUi); } ~Dialog() @@ -1627,7 +1628,7 @@ ContentLayout* Widget::createContentDialog(DialogType type) const void retranslateUi() { - setWindowTitle(Core::getInstance()->getUsername() + QStringLiteral(" - ") + setWindowTitle(core->getUsername() + QStringLiteral(" - ") + Widget::fromDialogType(type)); } @@ -1647,9 +1648,10 @@ ContentLayout* Widget::createContentDialog(DialogType type) const private: DialogType type; Settings& settings; + Core* core; }; - Dialog* dialog = new Dialog(type, settings); + Dialog* dialog = new Dialog(type, settings, core); dialog->setAttribute(Qt::WA_DeleteOnClose); ContentLayout* contentLayoutDialog = new ContentLayout(dialog); @@ -1678,7 +1680,7 @@ void Widget::copyFriendIdToClipboard(int friendId) Friend* f = FriendList::findFriend(friendId); if (f != nullptr) { QClipboard* clipboard = QApplication::clipboard(); - const ToxPk& pk = Nexus::getCore()->getFriendPublicKey(f->getId()); + const ToxPk& pk = core->getFriendPublicKey(f->getId()); clipboard->setText(pk.toString(), QClipboard::Clipboard); } } @@ -1713,7 +1715,7 @@ void Widget::onGroupInviteReceived(const GroupInvite& inviteInfo) void Widget::onGroupInviteAccepted(const GroupInvite& inviteInfo) { - const uint32_t groupId = Core::getInstance()->joinGroupchat(inviteInfo); + const uint32_t groupId = core->joinGroupchat(inviteInfo); if (groupId == std::numeric_limits::max()) { qWarning() << "onGroupInviteAccepted: Unable to accept group invite"; return; @@ -1726,7 +1728,6 @@ void Widget::onGroupMessageReceived(int groupnumber, int peernumber, const QStri Group* g = GroupList::findGroup(groupnumber); assert(g); - const Core* core = Core::getInstance(); ToxPk author = core->getGroupPeerPk(groupnumber, peernumber); bool isSelf = author == core->getSelfId().getPublicKey(); @@ -1816,7 +1817,7 @@ void Widget::removeGroup(Group* g, bool fake) } if (!fake) { - Nexus::getCore()->removeGroup(groupId); + core->removeGroup(groupId); } contactListWidget->removeGroupWidget(widget); // deletes widget @@ -1840,7 +1841,7 @@ void Widget::removeGroup(int groupId) removeGroup(GroupList::findGroup(groupId)); } -Group* Widget::createGroup(int groupId) +Group* Widget::createGroup(int groupId, const GroupId& groupPersistentId) { Group* g = GroupList::findGroup(groupId); if (g) { @@ -1849,10 +1850,10 @@ Group* Widget::createGroup(int groupId) } const auto groupName = tr("Groupchat #%1").arg(groupId); - Core* core = Nexus::getCore(); + Core* core = core; bool enabled = core->getGroupAvEnabled(groupId); - Group* newgroup = GroupList::addGroup(groupId, groupName, enabled, core->getUsername()); + Group* newgroup = GroupList::addGroup(groupId, groupPersistentId, groupName, enabled, core->getUsername()); std::shared_ptr chatroom(new GroupChatroom(newgroup)); const auto compact = settings.getCompactLayout(); auto widget = new GroupWidget(chatroom, compact); @@ -1886,9 +1887,9 @@ Group* Widget::createGroup(int groupId) return newgroup; } -void Widget::onEmptyGroupCreated(int groupId, const QString& title) +void Widget::onEmptyGroupCreated(int groupId, const GroupId& groupPersistentId, const QString& title) { - Group* group = createGroup(groupId); + Group* group = createGroup(groupId, groupPersistentId); if (!group) { return; } @@ -2028,7 +2029,7 @@ void Widget::setStatusOnline() return; } - Nexus::getCore()->setStatus(Status::Online); + core->setStatus(Status::Online); } void Widget::setStatusAway() @@ -2037,7 +2038,7 @@ void Widget::setStatusAway() return; } - Nexus::getCore()->setStatus(Status::Away); + core->setStatus(Status::Away); } void Widget::setStatusBusy() @@ -2046,7 +2047,7 @@ void Widget::setStatusBusy() return; } - Nexus::getCore()->setStatus(Status::Busy); + core->setStatus(Status::Busy); } void Widget::onGroupSendFailed(int groupId) @@ -2346,7 +2347,7 @@ void Widget::friendListContextMenu(const QPoint& pos) if (chosenAction == addCircleAction) { contactListWidget->addCircleWidget(); } else if (chosenAction == createGroupAction) { - Nexus::getCore()->createGroup(); + core->createGroup(); } } @@ -2411,7 +2412,7 @@ void Widget::setActiveToolMenuButton(ActiveToolMenuButton newActiveButton) void Widget::retranslateUi() { - Core* core = Nexus::getCore(); + Core* core = core; ui->retranslateUi(this); setUsername(core->getUsername()); setStatusMessage(core->getStatusMessage()); @@ -2473,6 +2474,6 @@ void Widget::focusChatInput() void Widget::refreshPeerListsLocal(const QString &username) { for (Group* g : GroupList::getAllGroups()) { - g->updateUsername(Core::getInstance()->getSelfPublicKey(), username); + g->updateUsername(core->getSelfPublicKey(), username); } } diff --git a/src/widget/widget.h b/src/widget/widget.h index b283bdd64..d78fa3a1e 100644 --- a/src/widget/widget.h +++ b/src/widget/widget.h @@ -31,6 +31,8 @@ #include "src/core/core.h" #include "src/core/toxfile.h" +#include "src/core/groupid.h" +#include "src/core/toxpk.h" #include "src/core/toxid.h" #if DESKTOP_NOTIFICATIONS #include "src/platform/desktop_notifications/desktopnotify.h" @@ -168,7 +170,7 @@ public slots: void onFriendMessageReceived(int friendId, const QString& message, bool isAction); void onFriendRequestReceived(const ToxPk& friendPk, const QString& message); void updateFriendActivity(const Friend* frnd); - void onEmptyGroupCreated(int groupId, const QString& title); + void onEmptyGroupCreated(int groupId, const GroupId& groupPersistentId, const QString& title); void onGroupInviteReceived(const GroupInvite& inviteInfo); void onGroupInviteAccepted(const GroupInvite& inviteInfo); void onGroupMessageReceived(int groupnumber, int peernumber, const QString& message, bool isAction); @@ -239,7 +241,7 @@ private: bool newMessageAlert(QWidget* currentWindow, bool isActive, bool sound = true, bool notify = true); void setActiveToolMenuButton(ActiveToolMenuButton newActiveButton); void hideMainForms(GenericChatroomWidget* chatroomWidget); - Group* createGroup(int groupId); + Group* createGroup(int groupId, const GroupId& groupPersistentId); void removeFriend(Friend* f, bool fake = false); void removeGroup(Group* g, bool fake = false); void saveWindowGeometry(); @@ -316,6 +318,7 @@ private: QMap groupWidgets; QMap> groupChatrooms; QMap> groupChatForms; + Core* core = nullptr; #if DESKTOP_NOTIFICATIONS DesktopNotify notifier; diff --git a/test/core/toxpk_test.cpp b/test/core/contactid_test.cpp similarity index 74% rename from test/core/toxpk_test.cpp rename to test/core/contactid_test.cpp index 49dadfa33..02cd8f46b 100644 --- a/test/core/toxpk_test.cpp +++ b/test/core/contactid_test.cpp @@ -17,7 +17,12 @@ along with qTox. If not, see . */ +#include "src/core/contactid.h" +#include "src/core/toxpk.h" #include "src/core/toxid.h" +#include "src/core/groupid.h" + +#include #include #include @@ -35,7 +40,7 @@ const QString echoStr = QStringLiteral("76518406F6A9F2217E8DC487CC783C25CC16A15EB36FF32E335A235342C48A39"); const QByteArray echoPk = QByteArray::fromHex(echoStr.toLatin1()); -class TestToxPk : public QObject +class TestContactId : public QObject { Q_OBJECT private slots: @@ -43,16 +48,17 @@ private slots: void equalTest(); void clearTest(); void copyTest(); - void publicKeyTest(); + void dataTest(); + void sizeTest(); }; -void TestToxPk::toStringTest() +void TestContactId::toStringTest() { ToxPk pk(testPk); QVERIFY(testStr == pk.toString()); } -void TestToxPk::equalTest() +void TestContactId::equalTest() { ToxPk pk1(testPk); ToxPk pk2(testPk); @@ -62,7 +68,7 @@ void TestToxPk::equalTest() QVERIFY(!(pk1 != pk2)); } -void TestToxPk::clearTest() +void TestContactId::clearTest() { ToxPk empty; ToxPk pk(testPk); @@ -70,22 +76,29 @@ void TestToxPk::clearTest() QVERIFY(!pk.isEmpty()); } -void TestToxPk::copyTest() +void TestContactId::copyTest() { ToxPk src(testPk); ToxPk copy = src; QVERIFY(copy == src); } -void TestToxPk::publicKeyTest() +void TestContactId::dataTest() { ToxPk pk(testPk); - QVERIFY(testPk == pk.getKey()); - for (int i = 0; i < ToxPk::getPkSize(); i++) { - QVERIFY(testPkArray[i] == pk.getBytes()[i]); + QVERIFY(testPk == pk.getByteArray()); + for (int i = 0; i < pk.getSize(); i++) { + QVERIFY(testPkArray[i] == pk.getData()[i]); } } -QTEST_GUILESS_MAIN(TestToxPk) -#include "toxpk_test.moc" +void TestContactId::sizeTest() +{ + ToxPk pk; + GroupId id; + QVERIFY(pk.getSize() == TOX_PUBLIC_KEY_SIZE); + QVERIFY(id.getSize() == TOX_CONFERENCE_UID_SIZE); +} +QTEST_GUILESS_MAIN(TestContactId) +#include "contactid_test.moc"