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 "contentdialogmanager.h"
21
22 #include "src/friendlist.h"
23 #include "src/grouplist.h"
24 #include "src/model/friend.h"
25 #include "src/model/group.h"
26 #include "src/widget/friendwidget.h"
27 #include "src/widget/groupwidget.h"
28
29 #include <tuple>
30
31 namespace {
removeDialog(ContentDialog * dialog,QHash<const ContactId &,ContentDialog * > & dialogs)32 void removeDialog(ContentDialog* dialog, QHash<const ContactId&, ContentDialog*>& dialogs)
33 {
34 for (auto it = dialogs.begin(); it != dialogs.end();) {
35 if (*it == dialog) {
36 it = dialogs.erase(it);
37 } else {
38 ++it;
39 }
40 }
41 }
42 } // namespace
43
44 ContentDialogManager* ContentDialogManager::instance;
45
current()46 ContentDialog* ContentDialogManager::current()
47 {
48 return currentDialog;
49 }
50
contactWidgetExists(const ContactId & contactId)51 bool ContentDialogManager::contactWidgetExists(const ContactId& contactId)
52 {
53 const auto dialog = contactDialogs.value(contactId, nullptr);
54 if (dialog == nullptr) {
55 return false;
56 }
57
58 return dialog->hasContact(contactId);
59 }
60
addFriendToDialog(ContentDialog * dialog,std::shared_ptr<FriendChatroom> chatroom,GenericChatForm * form)61 FriendWidget* ContentDialogManager::addFriendToDialog(ContentDialog* dialog,
62 std::shared_ptr<FriendChatroom> chatroom,
63 GenericChatForm* form)
64 {
65 auto friendWidget = dialog->addFriend(chatroom, form);
66 const auto& friendPk = friendWidget->getFriend()->getPublicKey();
67
68 ContentDialog* lastDialog = getFriendDialog(friendPk);
69 if (lastDialog) {
70 lastDialog->removeFriend(friendPk);
71 }
72
73 contactDialogs[friendPk] = dialog;
74 return friendWidget;
75 }
76
addGroupToDialog(ContentDialog * dialog,std::shared_ptr<GroupChatroom> chatroom,GenericChatForm * form)77 GroupWidget* ContentDialogManager::addGroupToDialog(ContentDialog* dialog,
78 std::shared_ptr<GroupChatroom> chatroom,
79 GenericChatForm* form)
80 {
81 auto groupWidget = dialog->addGroup(chatroom, form);
82 const auto& groupId = groupWidget->getGroup()->getPersistentId();
83
84 ContentDialog* lastDialog = getGroupDialog(groupId);
85 if (lastDialog) {
86 lastDialog->removeGroup(groupId);
87 }
88
89 contactDialogs[groupId] = dialog;
90 return groupWidget;
91 }
92
focusContact(const ContactId & contactId)93 void ContentDialogManager::focusContact(const ContactId& contactId)
94 {
95 auto dialog = focusDialog(contactId, contactDialogs);
96 if (dialog != nullptr) {
97 dialog->focusContact(contactId);
98 }
99 }
100
101 /**
102 * @brief Focus the dialog if it exists.
103 * @param id User Id.
104 * @param list List with dialogs
105 * @return ContentDialog if found, nullptr otherwise
106 */
focusDialog(const ContactId & id,const QHash<const ContactId &,ContentDialog * > & list)107 ContentDialog* ContentDialogManager::focusDialog(const ContactId& id,
108 const QHash<const ContactId&, ContentDialog*>& list)
109 {
110 auto iter = list.find(id);
111 if (iter == list.end()) {
112 return nullptr;
113 }
114
115 ContentDialog* dialog = *iter;
116 if (dialog->windowState() & Qt::WindowMinimized) {
117 dialog->showNormal();
118 }
119
120 dialog->raise();
121 dialog->activateWindow();
122 return dialog;
123 }
124
updateFriendStatus(const ToxPk & friendPk)125 void ContentDialogManager::updateFriendStatus(const ToxPk& friendPk)
126 {
127 auto dialog = contactDialogs.value(friendPk);
128 if (dialog == nullptr) {
129 return;
130 }
131
132 dialog->updateContactStatusLight(friendPk);
133 if (dialog->isContactActive(friendPk)) {
134 dialog->updateTitleAndStatusIcon();
135 }
136
137 Friend* f = FriendList::findFriend(friendPk);
138 dialog->updateFriendStatus(friendPk, f->getStatus());
139 }
140
updateGroupStatus(const GroupId & groupId)141 void ContentDialogManager::updateGroupStatus(const GroupId& groupId)
142 {
143 auto dialog = contactDialogs.value(groupId);
144 if (dialog == nullptr) {
145 return;
146 }
147
148 dialog->updateContactStatusLight(groupId);
149 if (dialog->isContactActive(groupId)) {
150 dialog->updateTitleAndStatusIcon();
151 }
152 }
153
isContactActive(const ContactId & contactId)154 bool ContentDialogManager::isContactActive(const ContactId& contactId)
155 {
156 const auto dialog = contactDialogs.value(contactId);
157 if (dialog == nullptr) {
158 return false;
159 }
160
161 return dialog->isContactActive(contactId);
162 }
163
getFriendDialog(const ToxPk & friendPk) const164 ContentDialog* ContentDialogManager::getFriendDialog(const ToxPk& friendPk) const
165 {
166 return contactDialogs.value(friendPk);
167 }
168
getGroupDialog(const GroupId & groupId) const169 ContentDialog* ContentDialogManager::getGroupDialog(const GroupId& groupId) const
170 {
171 return contactDialogs.value(groupId);
172 }
173
getInstance()174 ContentDialogManager* ContentDialogManager::getInstance()
175 {
176 if (instance == nullptr) {
177 instance = new ContentDialogManager();
178 }
179
180 return instance;
181 }
182
addContentDialog(ContentDialog & dialog)183 void ContentDialogManager::addContentDialog(ContentDialog& dialog)
184 {
185 currentDialog = &dialog;
186 connect(&dialog, &ContentDialog::willClose, this, &ContentDialogManager::onDialogClose);
187 connect(&dialog, &ContentDialog::activated, this, &ContentDialogManager::onDialogActivate);
188 }
189
onDialogActivate()190 void ContentDialogManager::onDialogActivate()
191 {
192 ContentDialog* dialog = qobject_cast<ContentDialog*>(sender());
193 currentDialog = dialog;
194 }
195
onDialogClose()196 void ContentDialogManager::onDialogClose()
197 {
198 ContentDialog* dialog = qobject_cast<ContentDialog*>(sender());
199 if (currentDialog == dialog) {
200 currentDialog = nullptr;
201 }
202
203 removeDialog(dialog, contactDialogs);
204 }
205
getFriendDialogs(const ToxPk & friendPk) const206 IDialogs* ContentDialogManager::getFriendDialogs(const ToxPk& friendPk) const
207 {
208 return getFriendDialog(friendPk);
209 }
210
getGroupDialogs(const GroupId & groupId) const211 IDialogs* ContentDialogManager::getGroupDialogs(const GroupId& groupId) const
212 {
213 return getGroupDialog(groupId);
214 }
215