1 /*
2     Copyright © 2019 by The qTox Project Contributors
3 
4     This file is part of qTox, a Qt-based graphical interface for Tox.
5 
6     qTox is libre software: you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation, either version 3 of the License, or
9     (at your option) any later version.
10 
11     qTox is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with qTox.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "chatlogitem.h"
21 #include "src/core/core.h"
22 #include "src/friendlist.h"
23 #include "src/grouplist.h"
24 #include "src/model/friend.h"
25 #include "src/model/group.h"
26 
27 #include <cassert>
28 
29 namespace {
30 
31 /**
32  * Helper template to get the correct deleter function for our type erased unique_ptr
33  */
34 template <typename T>
35 struct ChatLogItemDeleter
36 {
doDelete__anon8da9f1c80111::ChatLogItemDeleter37     static void doDelete(void* ptr)
38     {
39         delete static_cast<T*>(ptr);
40     }
41 };
42 
resolveToxPk(const ToxPk & pk)43 QString resolveToxPk(const ToxPk& pk)
44 {
45     Friend* f = FriendList::findFriend(pk);
46     if (f) {
47         return f->getDisplayedName();
48     }
49 
50     for (Group* it : GroupList::getAllGroups()) {
51         QString res = it->resolveToxId(pk);
52         if (!res.isEmpty()) {
53             return res;
54         }
55     }
56 
57     return pk.toString();
58 }
59 
resolveSenderNameFromSender(const ToxPk & sender)60 QString resolveSenderNameFromSender(const ToxPk& sender)
61 {
62     // TODO: Remove core instance
63     const Core* core = Core::getInstance();
64 
65     // In unit tests we don't have a core instance so we just stringize the key
66     if (!core) {
67         return sender.toString();
68     }
69 
70     bool isSelf = sender == core->getSelfId().getPublicKey();
71     QString myNickName = core->getUsername().isEmpty() ? sender.toString() : core->getUsername();
72 
73     return isSelf ? myNickName : resolveToxPk(sender);
74 }
75 } // namespace
76 
ChatLogItem(ToxPk sender_,ChatLogFile file_)77 ChatLogItem::ChatLogItem(ToxPk sender_, ChatLogFile file_)
78     : ChatLogItem(std::move(sender_), ContentType::fileTransfer,
79                   ContentPtr(new ChatLogFile(std::move(file_)),
80                              ChatLogItemDeleter<ChatLogFile>::doDelete))
81 {}
82 
ChatLogItem(ToxPk sender_,ChatLogMessage message_)83 ChatLogItem::ChatLogItem(ToxPk sender_, ChatLogMessage message_)
84     : ChatLogItem(sender_, ContentType::message,
85                   ContentPtr(new ChatLogMessage(std::move(message_)),
86                              ChatLogItemDeleter<ChatLogMessage>::doDelete))
87 {}
88 
ChatLogItem(ToxPk sender_,ContentType contentType_,ContentPtr content_)89 ChatLogItem::ChatLogItem(ToxPk sender_, ContentType contentType_, ContentPtr content_)
90     : sender(std::move(sender_))
91     , displayName(resolveSenderNameFromSender(sender))
92     , contentType(contentType_)
93     , content(std::move(content_))
94 {}
95 
getSender() const96 const ToxPk& ChatLogItem::getSender() const
97 {
98     return sender;
99 }
100 
getContentType() const101 ChatLogItem::ContentType ChatLogItem::getContentType() const
102 {
103     return contentType;
104 }
105 
getContentAsFile()106 ChatLogFile& ChatLogItem::getContentAsFile()
107 {
108     assert(contentType == ContentType::fileTransfer);
109     return *static_cast<ChatLogFile*>(content.get());
110 }
111 
getContentAsFile() const112 const ChatLogFile& ChatLogItem::getContentAsFile() const
113 {
114     assert(contentType == ContentType::fileTransfer);
115     return *static_cast<ChatLogFile*>(content.get());
116 }
117 
getContentAsMessage()118 ChatLogMessage& ChatLogItem::getContentAsMessage()
119 {
120     assert(contentType == ContentType::message);
121     return *static_cast<ChatLogMessage*>(content.get());
122 }
123 
getContentAsMessage() const124 const ChatLogMessage& ChatLogItem::getContentAsMessage() const
125 {
126     assert(contentType == ContentType::message);
127     return *static_cast<ChatLogMessage*>(content.get());
128 }
129 
getTimestamp() const130 QDateTime ChatLogItem::getTimestamp() const
131 {
132     switch (contentType) {
133     case ChatLogItem::ContentType::message: {
134         const auto& message = getContentAsMessage();
135         return message.message.timestamp;
136     }
137     case ChatLogItem::ContentType::fileTransfer: {
138         const auto& file = getContentAsFile();
139         return file.timestamp;
140     }
141     }
142 
143     assert(false);
144     return QDateTime();
145 }
146 
setDisplayName(QString name)147 void ChatLogItem::setDisplayName(QString name)
148 {
149     displayName = name;
150 }
151 
getDisplayName() const152 const QString& ChatLogItem::getDisplayName() const
153 {
154     return displayName;
155 }
156