qTox  Version: nightly | Commit: bc751c8e1cac455f9690654fcfe0f560d2d7dfdd
circlewidget.cpp
Go to the documentation of this file.
1 /*
2  Copyright © 2015-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 <QBoxLayout>
21 #include <QDragEnterEvent>
22 #include <QMenu>
23 #include <QMimeData>
24 #include <QMouseEvent>
25 #include <QVariant>
26 
27 #include <cassert>
28 
29 #include "circlewidget.h"
30 #include "contentdialog.h"
31 #include "friendlistwidget.h"
32 #include "friendwidget.h"
33 #include "widget.h"
34 #include "tool/croppinglabel.h"
35 
36 #include "src/friendlist.h"
37 #include "src/model/friend.h"
40 
42 
43 CircleWidget::CircleWidget(const Core &_core, FriendListWidget* parent, int id)
44  : CategoryWidget(isCompact(), parent)
45  , id(id)
46  , core{_core}
47 {
48  setName(Settings::getInstance().getCircleName(id), false);
49  circleList[id] = this;
50 
51  connect(nameLabel, &CroppingLabel::editFinished, [this](const QString& newName) {
52  if (!newName.isEmpty())
53  emit renameRequested(this, newName);
54  });
55 
56  connect(nameLabel, &CroppingLabel::editRemoved, [this]() {
57  if (isCompact())
58  nameLabel->minimizeMaximumWidth();
59  });
60 
61  setExpanded(Settings::getInstance().getCircleExpanded(id), false);
62  updateStatus();
63 }
64 
66 {
67  if (circleList[id] == this)
68  circleList.remove(id);
69 }
70 
72 {
74 }
75 
77 {
78  auto circleIt = circleList.find(id);
79 
80  if (circleIt != circleList.end())
81  return circleIt.value();
82 
83  return nullptr;
84 }
85 
86 void CircleWidget::contextMenuEvent(QContextMenuEvent* event)
87 {
88  QMenu menu;
89  QAction* renameAction = menu.addAction(tr("Rename circle", "Menu for renaming a circle"));
90  QAction* removeAction = menu.addAction(tr("Remove circle", "Menu for removing a circle"));
91  QAction* openAction = nullptr;
92 
93  if (friendOfflineLayout()->count() + friendOnlineLayout()->count() > 0)
94  openAction = menu.addAction(tr("Open all in new window"));
95 
96  QAction* selectedItem = menu.exec(mapToGlobal(event->pos()));
97 
98  if (selectedItem) {
99  if (selectedItem == renameAction) {
100  editName();
101  } else if (selectedItem == removeAction) {
102  FriendListWidget* friendList = static_cast<FriendListWidget*>(parentWidget());
103  moveFriendWidgets(friendList);
104 
105  friendList->removeCircleWidget(this);
106 
107  int replacedCircle = Settings::getInstance().removeCircle(id);
108 
109  auto circleReplace = circleList.find(replacedCircle);
110  if (circleReplace != circleList.end())
111  circleReplace.value()->updateID(id);
112  else
113  assert(true); // This should never happen.
114 
115  circleList.remove(replacedCircle);
116  } else if (selectedItem == openAction) {
117  ContentDialog* dialog = new ContentDialog(core);
118  emit newContentDialog(*dialog);
119  for (int i = 0; i < friendOnlineLayout()->count(); ++i) {
120  QWidget* const widget = friendOnlineLayout()->itemAt(i)->widget();
121  FriendWidget* const friendWidget = qobject_cast<FriendWidget*>(widget);
122 
123  if (friendWidget != nullptr) {
124  friendWidget->activate();
125  }
126  }
127  for (int i = 0; i < friendOfflineLayout()->count(); ++i) {
128  QWidget* const widget = friendOfflineLayout()->itemAt(i)->widget();
129  FriendWidget* const friendWidget = qobject_cast<FriendWidget*>(widget);
130 
131  if (friendWidget != nullptr) {
132  friendWidget->activate();
133  }
134  }
135 
136  dialog->show();
137  dialog->ensureSplitterVisible();
138  }
139  }
140 
141  setContainerAttribute(Qt::WA_UnderMouse, false);
142 }
143 
144 void CircleWidget::dragEnterEvent(QDragEnterEvent* event)
145 {
146  if (!event->mimeData()->hasFormat("toxPk")) {
147  return;
148  }
149  ToxPk toxPk(event->mimeData()->data("toxPk"));
150  Friend* f = FriendList::findFriend(toxPk);
151  if (f != nullptr)
152  event->acceptProposedAction();
153 
154  setContainerAttribute(Qt::WA_UnderMouse, true); // Simulate hover.
155 }
156 
157 void CircleWidget::dragLeaveEvent(QDragLeaveEvent*)
158 {
159  setContainerAttribute(Qt::WA_UnderMouse, false);
160 }
161 
162 void CircleWidget::dropEvent(QDropEvent* event)
163 {
164  setExpanded(true, false);
165 
166  // Check, that the element is dropped from qTox
167  QObject* o = event->source();
168  FriendWidget* widget = qobject_cast<FriendWidget*>(o);
169  if (!widget)
170  return;
171 
172  if (!event->mimeData()->hasFormat("toxPk")) {
173  return;
174  }
175  // Check, that the user has a friend with the same ToxId
176  ToxPk toxPk{event->mimeData()->data("toxPk")};
177  Friend* f = FriendList::findFriend(toxPk);
178  if (!f)
179  return;
180 
181  // Save CircleWidget before changing the Id
182  int circleId = Settings::getInstance().getFriendCircleID(toxPk);
183  CircleWidget* circleWidget = getFromID(circleId);
184 
185  addFriendWidget(widget, f->getStatus());
187 
188  if (circleWidget != nullptr) {
189  circleWidget->updateStatus();
190  }
191 
192  setContainerAttribute(Qt::WA_UnderMouse, false);
193 }
194 
196 {
198 }
199 
201 {
204 }
205 
207 {
208  const Friend* f = w->getFriend();
209  ToxPk toxId = f->getPublicKey();
211 }
212 
213 void CircleWidget::updateID(int index)
214 {
215  // For when a circle gets destroyed, another takes its id.
216  // This function updates all friends widgets for this new id.
217 
218  if (id == index) {
219  return;
220  }
221 
222  id = index;
223  circleList[id] = this;
224 
225  for (int i = 0; i < friendOnlineLayout()->count(); ++i) {
226  const QWidget* w = friendOnlineLayout()->itemAt(i)->widget();
227  const FriendWidget* friendWidget = qobject_cast<const FriendWidget*>(w);
228 
229  if (friendWidget) {
230  const Friend* f = friendWidget->getFriend();
232  }
233  }
234 
235  for (int i = 0; i < friendOfflineLayout()->count(); ++i) {
236  const QWidget* w = friendOfflineLayout()->itemAt(i)->widget();
237  const FriendWidget* friendWidget = qobject_cast<const FriendWidget*>(w);
238 
239  if (friendWidget) {
240  const Friend* f = friendWidget->getFriend();
242  }
243  }
244 }
GenericChatItemWidget::getName
QString getName() const
Definition: genericchatitemwidget.cpp:49
CircleWidget::circleList
static QHash< int, CircleWidget * > circleList
Definition: circlewidget.h:53
friend.h
friendlist.h
settings.h
CroppingLabel::editFinished
void editFinished(const QString &newText)
Settings::setCircleExpanded
void setCircleExpanded(int id, bool expanded)
Definition: settings.cpp:2060
CategoryWidget
Definition: categorywidget.h:32
contentdialog.h
CategoryWidget::addFriendWidget
void addFriendWidget(FriendWidget *w, Status::Status s)
Definition: categorywidget.cpp:130
CircleWidget::onSetName
void onSetName() final
Definition: circlewidget.cpp:195
circlewidget.h
Settings::removeCircle
int removeCircle(int id)
Definition: settings.cpp:2130
CircleWidget::CircleWidget
CircleWidget(const Core &_core, FriendListWidget *parent, int id)
Definition: circlewidget.cpp:43
FriendList::findFriend
static Friend * findFriend(const ToxPk &friendPk)
Definition: friendlist.cpp:47
Settings::setFriendCircleID
void setFriendCircleID(const ToxPk &id, int circleID) override
Definition: settings.cpp:1904
croppinglabel.h
FriendListWidget::removeCircleWidget
void removeCircleWidget(CircleWidget *widget)
Definition: friendlistwidget.cpp:404
Settings::getFriendCircleID
int getFriendCircleID(const ToxPk &id) const override
Definition: settings.cpp:1894
chatform.h
Friend::getStatus
Status::Status getStatus() const
Definition: friend.cpp:190
ContentDialog::ensureSplitterVisible
void ensureSplitterVisible()
Definition: contentdialog.cpp:259
ContentDialog
Definition: contentdialog.h:49
CircleWidget::core
const Core & core
Definition: circlewidget.h:56
CircleWidget::dropEvent
void dropEvent(QDropEvent *event) final
Definition: circlewidget.cpp:162
ToxPk
This class represents a Tox Public Key, which is a part of Tox ID.
Definition: toxpk.h:26
Friend
Definition: friend.h:31
widget.h
FriendWidget::getFriend
const Friend * getFriend() const final
Definition: friendwidget.cpp:347
CategoryWidget::friendOfflineLayout
QLayout * friendOfflineLayout() const
Definition: categorywidget.cpp:289
friendlistwidget.h
CircleWidget::onAddFriendWidget
void onAddFriendWidget(FriendWidget *w) final
Definition: circlewidget.cpp:206
QHash< int, CircleWidget * >
CategoryWidget::editName
void editName()
Definition: categorywidget.cpp:124
CroppingLabel::editRemoved
void editRemoved()
FriendListWidget
Definition: friendlistwidget.h:42
CircleWidget::id
int id
Definition: circlewidget.h:54
Settings::getInstance
static Settings & getInstance()
Returns the singleton instance.
Definition: settings.cpp:88
CircleWidget::onExpand
void onExpand() final
Definition: circlewidget.cpp:200
CircleWidget::getFromID
static CircleWidget * getFromID(int id)
Definition: circlewidget.cpp:76
CircleWidget::dragLeaveEvent
void dragLeaveEvent(QDragLeaveEvent *event) final
Definition: circlewidget.cpp:157
CircleWidget::editName
void editName()
Definition: circlewidget.cpp:71
Friend::getPublicKey
const ToxPk & getPublicKey() const
Definition: friend.cpp:131
Settings::setCircleName
void setCircleName(int id, const QString &name)
Definition: settings.cpp:2030
CategoryWidget::setExpanded
void setExpanded(bool isExpanded, bool save=true)
Definition: categorywidget.cpp:83
CircleWidget
Definition: circlewidget.h:27
Settings::savePersonal
void savePersonal()
Asynchronous, saves the current profile.
Definition: settings.cpp:717
CircleWidget::~CircleWidget
~CircleWidget()
Definition: circlewidget.cpp:65
GenericChatroomWidget::activate
void activate()
Definition: genericchatroomwidget.cpp:164
CategoryWidget::updateStatus
void updateStatus()
Definition: categorywidget.cpp:144
CategoryWidget::moveFriendWidgets
void moveFriendWidgets(FriendListWidget *friendList)
Definition: categorywidget.cpp:299
CircleWidget::contextMenuEvent
void contextMenuEvent(QContextMenuEvent *event) final
Definition: circlewidget.cpp:86
CategoryWidget::setContainerAttribute
void setContainerAttribute(Qt::WidgetAttribute attribute, bool enabled)
Definition: categorywidget.cpp:283
CategoryWidget::isExpanded
bool isExpanded() const
Definition: categorywidget.cpp:78
CircleWidget::dragEnterEvent
void dragEnterEvent(QDragEnterEvent *event) final
Definition: circlewidget.cpp:144
friendwidget.h
FriendWidget
Definition: friendwidget.h:33
CircleWidget::newContentDialog
void newContentDialog(ContentDialog &contentDialog)
CategoryWidget::friendOnlineLayout
QLayout * friendOnlineLayout() const
Definition: categorywidget.cpp:294
CircleWidget::updateID
void updateID(int index)
Definition: circlewidget.cpp:213
Core
Definition: core.h:59