qTox  Version: nightly | Commit: bc751c8e1cac455f9690654fcfe0f560d2d7dfdd
widget.cpp
Go to the documentation of this file.
1 /*
2  Copyright © 2014-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 "widget.h"
21 
22 #include <cassert>
23 
24 #include <QClipboard>
25 #include <QDebug>
26 #include <QDesktopServices>
27 #include <QDesktopWidget>
28 #include <QMessageBox>
29 #include <QMouseEvent>
30 #include <QPainter>
31 #include <QShortcut>
32 #include <QString>
33 #include <QSvgRenderer>
34 #include <QWindow>
35 #ifdef Q_OS_MAC
36 #include <QMenuBar>
37 #include <QSignalMapper>
38 #include <QWindow>
39 #endif
40 
41 #include "audio/audio.h"
42 #include "circlewidget.h"
43 #include "contentdialog.h"
44 #include "contentlayout.h"
45 #include "friendlistwidget.h"
46 #include "friendwidget.h"
47 #include "groupwidget.h"
48 #include "maskablepixmapwidget.h"
49 #include "splitterrestorer.h"
50 #include "form/groupchatform.h"
52 #include "src/core/core.h"
53 #include "src/core/coreav.h"
54 #include "src/core/corefile.h"
55 #include "src/friendlist.h"
56 #include "src/grouplist.h"
57 #include "src/model/chathistory.h"
60 #include "src/model/friend.h"
61 #include "src/model/group.h"
62 #include "src/model/groupinvite.h"
64 #include "src/model/status.h"
65 #include "src/net/updatecheck.h"
66 #include "src/nexus.h"
70 #include "src/platform/timer.h"
78 #include "src/widget/gui.h"
79 #include "src/widget/style.h"
80 #include "src/widget/translator.h"
82 
83 bool toxActivateEventHandler(const QByteArray&)
84 {
85  Widget* widget = Nexus::getDesktopGUI();
86  if (!widget) {
87  return true;
88  }
89 
90  qDebug() << "Handling [activate] event from other instance";
91  widget->forceShow();
92 
93  return true;
94 }
95 
96 namespace {
97 
103 bool tryRemoveFile(const QString& filepath)
104 {
105  QFile tmp(filepath);
106  bool writable = tmp.open(QIODevice::WriteOnly);
107  tmp.remove();
108  return writable;
109 }
110 } // namespace
111 
112 void Widget::acceptFileTransfer(const ToxFile& file, const QString& path)
113 {
114  QString filepath;
115  int number = 0;
116 
117  QString suffix = QFileInfo(file.fileName).completeSuffix();
118  QString base = QFileInfo(file.fileName).baseName();
119 
120  do {
121  filepath = QString("%1/%2%3.%4")
122  .arg(path, base,
123  number > 0 ? QString(" (%1)").arg(QString::number(number)) : QString(),
124  suffix);
125  ++number;
126  } while (QFileInfo(filepath).exists());
127 
128  // Do not automatically accept the file-transfer if the path is not writable.
129  // The user can still accept it manually.
130  if (tryRemoveFile(filepath)) {
131  CoreFile* coreFile = core->getCoreFile();
132  coreFile->acceptFileRecvRequest(file.friendId, file.fileNum, filepath);
133  } else {
134  qWarning() << "Cannot write to " << filepath;
135  }
136 }
137 
138 Widget* Widget::instance{nullptr};
139 
140 Widget::Widget(Profile &_profile, IAudioControl& audio, QWidget* parent)
141  : QMainWindow(parent)
142  , profile{_profile}
143  , trayMenu{nullptr}
144  , ui(new Ui::MainWindow)
145  , activeChatroomWidget{nullptr}
146  , eventFlag(false)
147  , eventIcon(false)
148  , audio(audio)
149  , settings(Settings::getInstance())
150 {
151  installEventFilter(this);
152  QString locale = settings.getTranslation();
153  Translator::translate(locale);
154 }
155 
157 {
158  ui->setupUi(this);
159 
160  QIcon themeIcon = QIcon::fromTheme("qtox");
161  if (!themeIcon.isNull()) {
162  setWindowIcon(themeIcon);
163  }
164 
165  timer = new QTimer();
166  timer->start(1000);
167 
168  icon_size = 15;
169 
170  actionShow = new QAction(this);
171  connect(actionShow, &QAction::triggered, this, &Widget::forceShow);
172 
173  // Preparing icons and set their size
174  statusOnline = new QAction(this);
175  statusOnline->setIcon(
177  connect(statusOnline, &QAction::triggered, this, &Widget::setStatusOnline);
178 
179  statusAway = new QAction(this);
181  connect(statusAway, &QAction::triggered, this, &Widget::setStatusAway);
182 
183  statusBusy = new QAction(this);
185  connect(statusBusy, &QAction::triggered, this, &Widget::setStatusBusy);
186 
187  actionLogout = new QAction(this);
188  actionLogout->setIcon(prepareIcon(":/img/others/logout-icon.svg", icon_size, icon_size));
189 
190  actionQuit = new QAction(this);
191 #ifndef Q_OS_OSX
192  actionQuit->setMenuRole(QAction::QuitRole);
193 #endif
194 
195  actionQuit->setIcon(
196  prepareIcon(Style::getImagePath("rejectCall/rejectCall.svg"), icon_size, icon_size));
197  connect(actionQuit, &QAction::triggered, qApp, &QApplication::quit);
198 
199  layout()->setContentsMargins(0, 0, 0, 0);
200 
201  profilePicture = new MaskablePixmapWidget(this, QSize(40, 40), ":/img/avatar_mask.svg");
202  profilePicture->setPixmap(QPixmap(":/img/contact_dark.svg"));
204  profilePicture->setObjectName("selfAvatar");
205  ui->myProfile->insertWidget(0, profilePicture);
206  ui->myProfile->insertSpacing(1, 7);
207 
208  filterMenu = new QMenu(this);
209  filterGroup = new QActionGroup(this);
210  filterDisplayGroup = new QActionGroup(this);
211 
212  filterDisplayName = new QAction(this);
213  filterDisplayName->setCheckable(true);
214  filterDisplayName->setChecked(true);
216  filterMenu->addAction(filterDisplayName);
217  filterDisplayActivity = new QAction(this);
218  filterDisplayActivity->setCheckable(true);
220  filterMenu->addAction(filterDisplayActivity);
222  ? filterDisplayName->setChecked(true)
223  : filterDisplayActivity->setChecked(true);
224  filterMenu->addSeparator();
225 
226  filterAllAction = new QAction(this);
227  filterAllAction->setCheckable(true);
228  filterAllAction->setChecked(true);
229  filterGroup->addAction(filterAllAction);
230  filterMenu->addAction(filterAllAction);
231  filterOnlineAction = new QAction(this);
232  filterOnlineAction->setCheckable(true);
233  filterGroup->addAction(filterOnlineAction);
234  filterMenu->addAction(filterOnlineAction);
235  filterOfflineAction = new QAction(this);
236  filterOfflineAction->setCheckable(true);
237  filterGroup->addAction(filterOfflineAction);
238  filterMenu->addAction(filterOfflineAction);
239  filterFriendsAction = new QAction(this);
240  filterFriendsAction->setCheckable(true);
241  filterGroup->addAction(filterFriendsAction);
242  filterMenu->addAction(filterFriendsAction);
243  filterGroupsAction = new QAction(this);
244  filterGroupsAction->setCheckable(true);
245  filterGroup->addAction(filterGroupsAction);
246  filterMenu->addAction(filterGroupsAction);
247 
248  ui->searchContactFilterBox->setMenu(filterMenu);
249 
250  core = &profile.getCore();
251  auto coreExt = core->getExt();
252 
253  sharedMessageProcessorParams.reset(new MessageProcessor::SharedParams(core->getMaxMessageSize(), coreExt->getMaxExtendedMessageSize()));
254 
259  ui->friendList->setWidget(contactListWidget);
260  ui->friendList->setLayoutDirection(Qt::RightToLeft);
261  ui->friendList->setContextMenuPolicy(Qt::CustomContextMenu);
262 
263  ui->statusLabel->setEditable(true);
264 
265  QMenu* statusButtonMenu = new QMenu(ui->statusButton);
266  statusButtonMenu->addAction(statusOnline);
267  statusButtonMenu->addAction(statusAway);
268  statusButtonMenu->addAction(statusBusy);
269  ui->statusButton->setMenu(statusButtonMenu);
270 
271  // disable proportional scaling
272  ui->mainSplitter->setStretchFactor(0, 0);
273  ui->mainSplitter->setStretchFactor(1, 1);
274 
276 
277  // Disable some widgets until we're connected to the DHT
278  ui->statusButton->setEnabled(false);
279 
281 
282  CoreFile* coreFile = core->getCoreFile();
283  filesForm = new FilesForm(*coreFile);
286 
287 #if UPDATE_CHECK_ENABLED
288  updateCheck = std::unique_ptr<UpdateCheck>(new UpdateCheck(settings));
290 #endif
291  settingsWidget = new SettingsWidget(updateCheck.get(), audio, core, this);
292 #if UPDATE_CHECK_ENABLED
293  updateCheck->checkForUpdate();
294 #endif
295 
298 
299 #if DESKTOP_NOTIFICATIONS
300  notificationGenerator.reset(new NotificationGenerator(settings, &profile));
301  connect(&notifier, &DesktopNotify::notificationClosed, notificationGenerator.get(), &NotificationGenerator::onNotificationActivated);
302 #endif
303 
304  // connect logout tray menu action
305  connect(actionLogout, &QAction::triggered, profileForm, &ProfileForm::onLogoutClicked);
306 
308 
310  connect(ui->addButton, &QPushButton::clicked, this, &Widget::onAddClicked);
311  connect(ui->groupButton, &QPushButton::clicked, this, &Widget::onGroupClicked);
312  connect(ui->transferButton, &QPushButton::clicked, this, &Widget::onTransferClicked);
313  connect(ui->settingsButton, &QPushButton::clicked, this, &Widget::onShowSettings);
315  connect(ui->nameLabel, &CroppingLabel::clicked, this, &Widget::showProfile);
316  connect(ui->statusLabel, &CroppingLabel::editFinished, this, &Widget::onStatusMessageChanged);
317  connect(ui->mainSplitter, &QSplitter::splitterMoved, this, &Widget::onSplitterMoved);
320  connect(timer, &QTimer::timeout, this, &Widget::onUserAwayCheck);
321  connect(timer, &QTimer::timeout, this, &Widget::onEventIconTick);
322  connect(timer, &QTimer::timeout, this, &Widget::onTryCreateTrayIcon);
323  connect(ui->searchContactText, &QLineEdit::textChanged, this, &Widget::searchContacts);
324  connect(filterGroup, &QActionGroup::triggered, this, &Widget::searchContacts);
325  connect(filterDisplayGroup, &QActionGroup::triggered, this, &Widget::changeDisplayMode);
326  connect(ui->friendList, &QWidget::customContextMenuRequested, this, &Widget::friendListContextMenu);
327 
328  // NOTE: Order of these signals as well as the use of QueuedConnection is important!
329  // Qt::AutoConnection, signals emitted from the same thread as Widget will
330  // be serviced before other signals. This is a problem when we have tight
331  // calls between file control and file info callbacks.
332  //
333  // File info callbacks are called from the core thread and will use
334  // QueuedConnection by default, our control path can easily end up on the
335  // same thread as widget. This can result in the following behavior if we
336  // are not careful
337  //
338  // * File data is received
339  // * User presses pause at the same time
340  // * Pause waits for data receive callback to complete (and emit fileTransferInfo)
341  // * Pause is executed and emits fileTransferPaused
342  // * Pause signal is handled by Qt::DirectConnection
343  // * fileTransferInfo signal is handled after by Qt::QueuedConnection
344  //
345  // This results in stale file state! In these conditions if we are not
346  // careful toxcore will think we are paused but our UI will think we are
347  // resumed, because the last signal they got was a transmitting file info
348  // signal!
349  connect(coreFile, &CoreFile::fileTransferInfo, this, &Widget::dispatchFile, Qt::QueuedConnection);
350  connect(coreFile, &CoreFile::fileSendStarted, this, &Widget::dispatchFile, Qt::QueuedConnection);
351  connect(coreFile, &CoreFile::fileReceiveRequested, this, &Widget::dispatchFile, Qt::QueuedConnection);
352  connect(coreFile, &CoreFile::fileTransferAccepted, this, &Widget::dispatchFile, Qt::QueuedConnection);
353  connect(coreFile, &CoreFile::fileTransferCancelled, this, &Widget::dispatchFile, Qt::QueuedConnection);
354  connect(coreFile, &CoreFile::fileTransferFinished, this, &Widget::dispatchFile, Qt::QueuedConnection);
355  connect(coreFile, &CoreFile::fileTransferPaused, this, &Widget::dispatchFile, Qt::QueuedConnection);
356  connect(coreFile, &CoreFile::fileTransferRemotePausedUnpaused, this, &Widget::dispatchFileWithBool, Qt::QueuedConnection);
357  connect(coreFile, &CoreFile::fileTransferBrokenUnbroken, this, &Widget::dispatchFileWithBool, Qt::QueuedConnection);
358  connect(coreFile, &CoreFile::fileSendFailed, this, &Widget::dispatchFileSendFailed, Qt::QueuedConnection);
359  // NOTE: We intentionally do not connect the fileUploadFinished and fileDownloadFinished signals
360  // because they are duplicates of fileTransferFinished NOTE: We don't hook up the
361  // fileNameChanged signal since it is only emitted before a fileReceiveRequest. We get the
362  // initial request with the sanitized name so there is no work for us to do
363 
364  // keyboard shortcuts
365  auto* const quitShortcut = new QShortcut(Qt::CTRL + Qt::Key_Q, this);
366  connect(quitShortcut, &QShortcut::activated, qApp, &QApplication::quit);
367  new QShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_Tab, this, SLOT(previousContact()));
368  new QShortcut(Qt::CTRL + Qt::Key_Tab, this, SLOT(nextContact()));
369  new QShortcut(Qt::CTRL + Qt::Key_PageUp, this, SLOT(previousContact()));
370  new QShortcut(Qt::CTRL + Qt::Key_PageDown, this, SLOT(nextContact()));
371  new QShortcut(Qt::Key_F11, this, SLOT(toggleFullscreen()));
372 
373 #ifdef Q_OS_MAC
374  QMenuBar* globalMenu = Nexus::getInstance().globalMenuBar;
375  QAction* windowMenu = Nexus::getInstance().windowMenu->menuAction();
376  QAction* viewMenu = Nexus::getInstance().viewMenu->menuAction();
377  QAction* frontAction = Nexus::getInstance().frontAction;
378 
379  fileMenu = globalMenu->insertMenu(viewMenu, new QMenu(this));
380 
381  editProfileAction = fileMenu->menu()->addAction(QString());
382  connect(editProfileAction, &QAction::triggered, this, &Widget::showProfile);
383 
384  changeStatusMenu = fileMenu->menu()->addMenu(QString());
385  fileMenu->menu()->addAction(changeStatusMenu->menuAction());
386  changeStatusMenu->addAction(statusOnline);
387  changeStatusMenu->addSeparator();
388  changeStatusMenu->addAction(statusAway);
389  changeStatusMenu->addAction(statusBusy);
390 
391  fileMenu->menu()->addSeparator();
392  logoutAction = fileMenu->menu()->addAction(QString());
393  connect(logoutAction, &QAction::triggered, []() { Nexus::getInstance().showLogin(); });
394 
395  editMenu = globalMenu->insertMenu(viewMenu, new QMenu(this));
396  editMenu->menu()->addSeparator();
397 
398  viewMenu->menu()->insertMenu(Nexus::getInstance().fullscreenAction, filterMenu);
399 
400  viewMenu->menu()->insertSeparator(Nexus::getInstance().fullscreenAction);
401 
402  contactMenu = globalMenu->insertMenu(windowMenu, new QMenu(this));
403 
404  addContactAction = contactMenu->menu()->addAction(QString());
405  connect(addContactAction, &QAction::triggered, this, &Widget::onAddClicked);
406 
407  nextConversationAction = new QAction(this);
408  Nexus::getInstance().windowMenu->insertAction(frontAction, nextConversationAction);
409  nextConversationAction->setShortcut(QKeySequence::SelectNextPage);
410  connect(nextConversationAction, &QAction::triggered, [this]() {
411  if (ContentDialogManager::getInstance()->current() == QApplication::activeWindow())
413  else if (QApplication::activeWindow() == this)
414  cycleContacts(true);
415  });
416 
417  previousConversationAction = new QAction(this);
418  Nexus::getInstance().windowMenu->insertAction(frontAction, previousConversationAction);
419  previousConversationAction->setShortcut(QKeySequence::SelectPreviousPage);
420  connect(previousConversationAction, &QAction::triggered, [this] {
421  if (ContentDialogManager::getInstance()->current() == QApplication::activeWindow())
423  else if (QApplication::activeWindow() == this)
424  cycleContacts(false);
425  });
426 
427  windowMenu->menu()->insertSeparator(frontAction);
428 
429  QAction* preferencesAction = viewMenu->menu()->addAction(QString());
430  preferencesAction->setMenuRole(QAction::PreferencesRole);
431  connect(preferencesAction, &QAction::triggered, this, &Widget::onShowSettings);
432 
433  QAction* aboutAction = viewMenu->menu()->addAction(QString());
434  aboutAction->setMenuRole(QAction::AboutRole);
435  connect(aboutAction, &QAction::triggered, [this]() {
436  onShowSettings();
437  settingsWidget->showAbout();
438  });
439 
440  QMenu* dockChangeStatusMenu = new QMenu(tr("Status"), this);
441  dockChangeStatusMenu->addAction(statusOnline);
442  statusOnline->setIconVisibleInMenu(true);
443  dockChangeStatusMenu->addSeparator();
444  dockChangeStatusMenu->addAction(statusAway);
445  dockChangeStatusMenu->addAction(statusBusy);
446  Nexus::getInstance().dockMenu->addAction(dockChangeStatusMenu->menuAction());
447 
448  connect(this, &Widget::windowStateChanged, &Nexus::getInstance(), &Nexus::onWindowStateChanged);
449 #endif
450 
451  contentLayout = nullptr;
453 
454  ui->addButton->setCheckable(true);
455  ui->groupButton->setCheckable(true);
456  ui->transferButton->setCheckable(true);
457  ui->settingsButton->setCheckable(true);
458 
459  if (contentLayout) {
460  onAddClicked();
461  }
462 
463  // restore window state
464  restoreGeometry(settings.getWindowGeometry());
465  restoreState(settings.getWindowState());
466  SplitterRestorer restorer(ui->mainSplitter);
467  restorer.restore(settings.getSplitterState(), size());
468 
469  friendRequestsButton = nullptr;
470  groupInvitesButton = nullptr;
471  unreadGroupInvites = 0;
472 
479 
480  // settings
487 
489 
490  reloadTheme();
491  updateIcons();
492  retranslateUi();
493  Translator::registerHandler(std::bind(&Widget::retranslateUi, this), this);
494 
495  if (!settings.getShowSystemTray()) {
496  show();
497  }
498 
499 #ifdef Q_OS_MAC
500  Nexus::getInstance().updateWindows();
501 #endif
502 }
503 
504 bool Widget::eventFilter(QObject* obj, QEvent* event)
505 {
506  QWindowStateChangeEvent* ce = nullptr;
507  Qt::WindowStates state = windowState();
508 
509  switch (event->type()) {
510  case QEvent::Close:
511  // It's needed if user enable `Close to tray`
512  wasMaximized = state.testFlag(Qt::WindowMaximized);
513  break;
514 
515  case QEvent::WindowStateChange:
516  ce = static_cast<QWindowStateChangeEvent*>(event);
517  if (state.testFlag(Qt::WindowMinimized) && obj) {
518  wasMaximized = ce->oldState().testFlag(Qt::WindowMaximized);
519  }
520 
521 #ifdef Q_OS_MAC
522  emit windowStateChanged(windowState());
523 #endif
524  break;
525  default:
526  break;
527  }
528 
529  return false;
530 }
531 
533 {
534  if (!icon) {
535  return;
536  }
537 
538  const QString assetSuffix = Status::getAssetSuffix(static_cast<Status::Status>(
539  ui->statusButton->property("status").toInt()))
540  + (eventIcon ? "_event" : "");
541 
542  // Some builds of Qt appear to have a bug in icon loading:
543  // QIcon::hasThemeIcon is sometimes unaware that the icon returned
544  // from QIcon::fromTheme was a fallback icon, causing hasThemeIcon to
545  // incorrectly return true.
546  //
547  // In qTox this leads to the tray and window icons using the static qTox logo
548  // icon instead of an icon based on the current presence status.
549  //
550  // This workaround checks for an icon that definitely does not exist to
551  // determine if hasThemeIcon can be trusted.
552  //
553  // On systems with the Qt bug, this workaround will always use our included
554  // icons but user themes will be unable to override them.
555  static bool checkedHasThemeIcon = false;
556  static bool hasThemeIconBug = false;
557 
558  if (!checkedHasThemeIcon) {
559  hasThemeIconBug = QIcon::hasThemeIcon("qtox-asjkdfhawjkeghdfjgh");
560  checkedHasThemeIcon = true;
561 
562  if (hasThemeIconBug) {
563  qDebug()
564  << "Detected buggy QIcon::hasThemeIcon. Icon overrides from theme will be ignored.";
565  }
566  }
567 
568  QIcon ico;
569  if (!hasThemeIconBug && QIcon::hasThemeIcon("qtox-" + assetSuffix)) {
570  ico = QIcon::fromTheme("qtox-" + assetSuffix);
571  } else {
572  QString color = settings.getLightTrayIcon() ? "light" : "dark";
573  QString path = ":/img/taskbar/" + color + "/taskbar_" + assetSuffix + ".svg";
574  QSvgRenderer renderer(path);
575 
576  // Prepare a QImage with desired characteritisc
577  QImage image = QImage(250, 250, QImage::Format_ARGB32);
578  image.fill(Qt::transparent);
579  QPainter painter(&image);
580  renderer.render(&painter);
581  ico = QIcon(QPixmap::fromImage(image));
582  }
583 
584  setWindowIcon(ico);
585  if (icon) {
586  icon->setIcon(ico);
587  }
588 }
589 
591 {
592  QWidgetList windowList = QApplication::topLevelWidgets();
593 
594  for (QWidget* window : windowList) {
595  if (window != this) {
596  window->close();
597  }
598  }
599 
601  if (icon) {
602  icon->hide();
603  }
604 
605  for (Group* g : GroupList::getAllGroups()) {
606  removeGroup(g, true);
607  }
608 
609  for (Friend* f : FriendList::getAllFriends()) {
610  removeFriend(f, true);
611  }
612 
613  for (auto form : chatForms) {
614  delete form;
615  }
616 
617  delete profileForm;
618  delete profileInfo;
619  delete addFriendForm;
620  delete groupInviteForm;
621  delete filesForm;
622  delete timer;
623  delete contentLayout;
624  delete settingsWidget;
625 
628  delete trayMenu;
629  delete ui;
630  instance = nullptr;
631 }
632 
637 {
638  onShowSettings();
639  settingsWidget->showAbout();
640 }
641 
642 void Widget::moveEvent(QMoveEvent* event)
643 {
644  if (event->type() == QEvent::Move) {
647  }
648 
649  QWidget::moveEvent(event);
650 }
651 
652 void Widget::closeEvent(QCloseEvent* event)
653 {
655  QWidget::closeEvent(event);
656  } else {
657  if (autoAwayActive) {
659  autoAwayActive = false;
660  }
663  QWidget::closeEvent(event);
664  qApp->quit();
665  }
666 }
667 
668 void Widget::changeEvent(QEvent* event)
669 {
670  if (event->type() == QEvent::WindowStateChange) {
671  if (isMinimized() && settings.getShowSystemTray() && settings.getMinimizeToTray()) {
672  this->hide();
673  }
674  }
675 }
676 
677 void Widget::resizeEvent(QResizeEvent* event)
678 {
680  QMainWindow::resizeEvent(event);
681 }
682 
684 {
685  return core->getUsername();
686 }
687 
688 void Widget::onSelfAvatarLoaded(const QPixmap& pic)
689 {
691 }
692 
694 {
695 
696  connect(&core, &Core::connected, this, &Widget::onConnected);
697  connect(&core, &Core::disconnected, this, &Widget::onDisconnected);
698  connect(&core, &Core::statusSet, this, &Widget::onStatusSet);
699  connect(&core, &Core::usernameSet, this, &Widget::setUsername);
701  connect(&core, &Core::friendAdded, this, &Widget::addFriend);
716  connect(&core, &Core::groupJoined, this, &Widget::onGroupJoined);
720 
721  auto coreExt = core.getExt();
722 
726 
727  connect(this, &Widget::statusSet, &core, &Core::setStatus);
731 
733 }
734 
736 {
737  ui->statusButton->setEnabled(true);
738  emit core->statusSet(core->getStatus());
739 }
740 
742 {
743  ui->statusButton->setEnabled(false);
745 }
746 
748 {
749  QMessageBox critical(this);
750  critical.setText(tr(
751  "Toxcore failed to start, the application will terminate after you close this message."));
752  critical.setIcon(QMessageBox::Critical);
753  critical.exec();
754  qApp->exit(EXIT_FAILURE);
755 }
756 
758 {
760  QMessageBox critical(this);
761  critical.setText(tr("Toxcore failed to start with your proxy settings. "
762  "qTox cannot run; please modify your "
763  "settings and restart.",
764  "popup text"));
765  critical.setIcon(QMessageBox::Critical);
766  critical.exec();
767  onShowSettings();
768 }
769 
771 {
772  ui->statusButton->setProperty("status", static_cast<int>(status));
773  ui->statusButton->setIcon(prepareIcon(getIconPath(status), icon_size, icon_size));
774  updateIcons();
775 }
776 
778 {
779  onSeparateWindowChanged(separate, true);
780 }
781 
782 void Widget::onSeparateWindowChanged(bool separate, bool clicked)
783 {
784  if (!separate) {
785  QWindowList windowList = QGuiApplication::topLevelWindows();
786 
787  for (QWindow* window : windowList) {
788  if (window->objectName() == "detachedWindow") {
789  window->close();
790  }
791  }
792 
793  QWidget* contentWidget = new QWidget(this);
794  contentWidget->setObjectName("contentWidget");
795 
796  contentLayout = new ContentLayout(contentWidget);
797  ui->mainSplitter->addWidget(contentWidget);
798 
799  setMinimumWidth(775);
800 
801  SplitterRestorer restorer(ui->mainSplitter);
802  restorer.restore(settings.getSplitterState(), size());
803 
804  onShowSettings();
805  } else {
806  int width = ui->friendList->size().width();
807  QSize size;
808  QPoint pos;
809 
810  if (contentLayout) {
811  pos = mapToGlobal(ui->mainSplitter->widget(1)->pos());
812  size = ui->mainSplitter->widget(1)->size();
813  }
814 
815  if (contentLayout) {
816  contentLayout->clear();
817  contentLayout->parentWidget()->setParent(nullptr); // Remove from splitter.
818  contentLayout->parentWidget()->hide();
819  contentLayout->parentWidget()->deleteLater();
820  contentLayout->deleteLater();
821  contentLayout = nullptr;
822  }
823 
824  setMinimumWidth(ui->tooliconsZone->sizeHint().width());
825 
826  if (clicked) {
827  showNormal();
828  resize(width, height());
829 
830  if (settingsWidget) {
832  contentLayout->parentWidget()->resize(size);
833  contentLayout->parentWidget()->move(pos);
836  }
837  }
838 
839  setWindowTitle(QString());
841  }
842 }
843 
844 void Widget::setWindowTitle(const QString& title)
845 {
846  if (title.isEmpty()) {
847  QMainWindow::setWindowTitle(QApplication::applicationName());
848  } else {
849  QString tmp = title;
851  QMainWindow::setWindowTitle(tmp.remove(QRegExp("<[^>]*>")) + QStringLiteral(" - ")
852  + QApplication::applicationName());
853  }
854 }
855 
857 {
858  hide(); // Workaround to force minimized window to be restored
859  show();
860  activateWindow();
861 }
862 
864 {
865  if (settings.getSeparateWindow()) {
866  if (!addFriendForm->isShown()) {
868  }
869 
871  } else {
872  hideMainForms(nullptr);
876  }
877 }
878 
880 {
881  if (settings.getSeparateWindow()) {
882  if (!groupInviteForm->isShown()) {
884  }
885 
887  } else {
888  hideMainForms(nullptr);
892  }
893 }
894 
896 {
897  if (settings.getSeparateWindow()) {
898  if (!filesForm->isShown()) {
900  }
901 
903  } else {
904  hideMainForms(nullptr);
908  }
909 }
910 
911 void Widget::confirmExecutableOpen(const QFileInfo& file)
912 {
913  static const QStringList dangerousExtensions = {"app", "bat", "com", "cpl", "dmg",
914  "exe", "hta", "jar", "js", "jse",
915  "lnk", "msc", "msh", "msh1", "msh1xml",
916  "msh2", "msh2xml", "mshxml", "msi", "msp",
917  "pif", "ps1", "ps1xml", "ps2", "ps2xml",
918  "psc1", "psc2", "py", "reg", "scf",
919  "sh", "src", "vb", "vbe", "vbs",
920  "ws", "wsc", "wsf", "wsh"};
921 
922  if (dangerousExtensions.contains(file.suffix())) {
923  bool answer = GUI::askQuestion(tr("Executable file", "popup title"),
924  tr("You have asked qTox to open an executable file. "
925  "Executable files can potentially damage your computer. "
926  "Are you sure want to open this file?",
927  "popup text"),
928  false, true);
929  if (!answer) {
930  return;
931  }
932 
933  // The user wants to run this file, so make it executable and run it
934  QFile(file.filePath())
935  .setPermissions(file.permissions() | QFile::ExeOwner | QFile::ExeUser | QFile::ExeGroup
936  | QFile::ExeOther);
937  }
938 
939  QDesktopServices::openUrl(QUrl::fromLocalFile(file.filePath()));
940 }
941 
942 void Widget::onIconClick(QSystemTrayIcon::ActivationReason reason)
943 {
944  if (reason == QSystemTrayIcon::Trigger) {
945  if (isHidden() || isMinimized()) {
946  if (wasMaximized) {
947  showMaximized();
948  } else {
949  showNormal();
950  }
951 
952  activateWindow();
953  } else if (!isActiveWindow()) {
954  activateWindow();
955  } else {
956  wasMaximized = isMaximized();
957  hide();
958  }
959  } else if (reason == QSystemTrayIcon::Unknown) {
960  if (isHidden()) {
961  forceShow();
962  }
963  }
964 }
965 
967 {
968  if (settings.getSeparateWindow()) {
969  if (!settingsWidget->isShown()) {
971  }
972 
974  } else {
975  hideMainForms(nullptr);
979  }
980 }
981 
982 void Widget::showProfile() // onAvatarClicked, onUsernameClicked
983 {
984  if (settings.getSeparateWindow()) {
985  if (!profileForm->isShown()) {
987  }
988 
990  } else {
991  hideMainForms(nullptr);
995  }
996 }
997 
999 {
1001 
1002  if (contentLayout != nullptr) {
1003  contentLayout->clear();
1004  }
1005 
1006  if (activeChatroomWidget != nullptr) {
1008  }
1009 
1010  activeChatroomWidget = chatroomWidget;
1011 }
1012 
1013 void Widget::setUsername(const QString& username)
1014 {
1015  if (username.isEmpty()) {
1016  ui->nameLabel->setText(tr("Your name"));
1017  ui->nameLabel->setToolTip(tr("Your name"));
1018  } else {
1019  ui->nameLabel->setText(username);
1020  ui->nameLabel->setToolTip(
1021  Qt::convertFromPlainText(username, Qt::WhiteSpaceNormal)); // for overlength names
1022  }
1023 
1024  sharedMessageProcessorParams->onUserNameSet(username);
1025 }
1026 
1027 void Widget::onStatusMessageChanged(const QString& newStatusMessage)
1028 {
1029  // Keep old status message until Core tells us to set it.
1030  core->setStatusMessage(newStatusMessage);
1031 }
1032 
1033 void Widget::setStatusMessage(const QString& statusMessage)
1034 {
1035  ui->statusLabel->setText(statusMessage);
1036  // escape HTML from tooltips and preserve newlines
1037  // TODO: move newspace preservance to a generic function
1038  ui->statusLabel->setToolTip("<p style='white-space:pre'>" + statusMessage.toHtmlEscaped() + "</p>");
1039 }
1040 
1046 void Widget::playNotificationSound(IAudioSink::Sound sound, bool loop)
1047 {
1049  // don't try to play sounds if audio is disabled
1050  return;
1051  }
1052 
1053  if (audioNotification == nullptr) {
1054  audioNotification = std::unique_ptr<IAudioSink>(audio.makeSink());
1055  if (audioNotification == nullptr) {
1056  qDebug() << "Failed to allocate AudioSink";
1057  return;
1058  }
1059  }
1060 
1061  audioNotification->connectTo_finishedPlaying(this, [this](){ cleanupNotificationSound(); });
1062 
1063  audioNotification->playMono16Sound(sound);
1064 
1065  if (loop) {
1066  audioNotification->startLoop();
1067  }
1068 }
1069 
1071 {
1072  audioNotification.reset();
1073 }
1074 
1075 void Widget::incomingNotification(uint32_t friendnumber)
1076 {
1077  const auto& friendId = FriendList::id2Key(friendnumber);
1078  newFriendMessageAlert(friendId, {}, false);
1079 
1080  // loop until call answered or rejected
1081  playNotificationSound(IAudioSink::Sound::IncomingCall, true);
1082 }
1083 
1085 {
1086  // loop until call answered or rejected
1087  playNotificationSound(IAudioSink::Sound::OutgoingCall, true);
1088 }
1089 
1091 {
1092  playNotificationSound(IAudioSink::Sound::CallEnd);
1093 }
1094 
1099 {
1100  audioNotification.reset();
1101 }
1102 
1107 {
1108  const auto& friendId = FriendList::id2Key(file.friendId);
1109  Friend* f = FriendList::findFriend(friendId);
1110  if (!f) {
1111  return;
1112  }
1113 
1114  auto pk = f->getPublicKey();
1115 
1116  if (file.status == ToxFile::INITIALIZING && file.direction == ToxFile::RECEIVING) {
1117  auto sender =
1118  (file.direction == ToxFile::SENDING) ? core->getSelfPublicKey() : pk;
1119 
1120  QString autoAcceptDir = settings.getAutoAcceptDir(f->getPublicKey());
1121 
1122  if (autoAcceptDir.isEmpty() && settings.getAutoSaveEnabled()) {
1123  autoAcceptDir = settings.getGlobalAutoAcceptDir();
1124  }
1125 
1126  auto maxAutoAcceptSize = settings.getMaxAutoAcceptSize();
1127  bool autoAcceptSizeCheckPassed =
1128  maxAutoAcceptSize == 0 || maxAutoAcceptSize >= file.progress.getFileSize();
1129 
1130  if (!autoAcceptDir.isEmpty() && autoAcceptSizeCheckPassed) {
1131  acceptFileTransfer(file, autoAcceptDir);
1132  }
1133  }
1134 
1135  const auto senderPk = (file.direction == ToxFile::SENDING) ? core->getSelfPublicKey() : pk;
1136  friendChatLogs[pk]->onFileUpdated(senderPk, file);
1137 
1139 }
1140 
1142 {
1143  dispatchFile(file);
1144 }
1145 
1146 void Widget::dispatchFileSendFailed(uint32_t friendId, const QString& fileName)
1147 {
1148  const auto& friendPk = FriendList::id2Key(friendId);
1149 
1150  auto chatForm = chatForms.find(friendPk);
1151  if (chatForm == chatForms.end()) {
1152  return;
1153  }
1154 
1155  chatForm.value()->addSystemInfoMessage(QDateTime::currentDateTime(),
1156  SystemMessageType::fileSendFailed, {fileName});
1157 }
1158 
1159 void Widget::onRejectCall(uint32_t friendId)
1160 {
1161  CoreAV* const av = core->getAv();
1162  av->cancelCall(friendId);
1163 }
1164 
1165 void Widget::addFriend(uint32_t friendId, const ToxPk& friendPk)
1166 {
1167  assert(core != nullptr);
1169 
1170  Friend* newfriend = FriendList::addFriend(friendId, friendPk);
1171  auto dialogManager = ContentDialogManager::getInstance();
1172  auto rawChatroom = new FriendChatroom(newfriend, dialogManager, *core);
1173  std::shared_ptr<FriendChatroom> chatroom(rawChatroom);
1174  const auto compact = settings.getCompactLayout();
1175  auto widget = new FriendWidget(chatroom, compact);
1176  connectFriendWidget(*widget);
1177  auto history = profile.getHistory();
1178 
1179  auto messageProcessor = MessageProcessor(*sharedMessageProcessorParams);
1180  auto friendMessageDispatcher =
1181  std::make_shared<FriendMessageDispatcher>(*newfriend, std::move(messageProcessor), *core, *core->getExt());
1182 
1183  // Note: We do not have to connect the message dispatcher signals since
1184  // ChatHistory hooks them up in a very specific order
1185  auto chatHistory =
1186  std::make_shared<ChatHistory>(*newfriend, history, *core, settings,
1187  *friendMessageDispatcher);
1188  auto friendForm = new ChatForm(profile, newfriend, *chatHistory, *friendMessageDispatcher);
1189  connect(friendForm, &ChatForm::updateFriendActivity, this, &Widget::updateFriendActivity);
1190 
1191  friendMessageDispatchers[friendPk] = friendMessageDispatcher;
1192  friendChatLogs[friendPk] = chatHistory;
1193  friendChatrooms[friendPk] = chatroom;
1194  friendWidgets[friendPk] = widget;
1195  chatForms[friendPk] = friendForm;
1196 
1197  const auto activityTime = settings.getFriendActivity(friendPk);
1198  const auto chatTime = friendForm->getLatestTime();
1199  if (chatTime > activityTime && chatTime.isValid()) {
1200  settings.setFriendActivity(friendPk, chatTime);
1201  }
1202 
1204 
1205 
1206  auto notifyReceivedCallback = [this, friendPk](const ToxPk& author, const Message& message) {
1207  newFriendMessageAlert(friendPk, message.content);
1208  };
1209 
1210  auto notifyReceivedConnection =
1211  connect(friendMessageDispatcher.get(), &IMessageDispatcher::messageReceived,
1212  notifyReceivedCallback);
1213 
1214  friendAlertConnections.insert(friendPk, notifyReceivedConnection);
1215  connect(newfriend, &Friend::aliasChanged, this, &Widget::onFriendAliasChanged);
1217  connect(newfriend, &Friend::statusChanged, this, &Widget::onFriendStatusChanged);
1218 
1219  connect(friendForm, &ChatForm::incomingNotification, this, &Widget::incomingNotification);
1220  connect(friendForm, &ChatForm::outgoingNotification, this, &Widget::outgoingNotification);
1221  connect(friendForm, &ChatForm::stopNotification, this, &Widget::onStopNotification);
1222  connect(friendForm, &ChatForm::endCallNotification, this, &Widget::onCallEnd);
1223  connect(friendForm, &ChatForm::rejectCall, this, &Widget::onRejectCall);
1224 
1225  connect(widget, &FriendWidget::newWindowOpened, this, &Widget::openNewDialog);
1227  connect(widget, &FriendWidget::chatroomWidgetClicked, friendForm, &ChatForm::focusInput);
1228  connect(widget, &FriendWidget::friendHistoryRemoved, friendForm, &ChatForm::clearChatArea);
1231  connect(widget, SIGNAL(removeFriend(const ToxPk&)), this, SLOT(removeFriend(const ToxPk&)));
1232 
1235 
1236  // Try to get the avatar from the cache
1237  QPixmap avatar = profile.loadAvatar(friendPk);
1238  if (!avatar.isNull()) {
1239  friendForm->onAvatarChanged(friendPk, avatar);
1240  widget->onAvatarSet(friendPk, avatar);
1241  }
1242 }
1243 
1244 void Widget::addFriendFailed(const ToxPk&, const QString& errorInfo)
1245 {
1246  QString info = QString(tr("Couldn't send friend request"));
1247  if (!errorInfo.isEmpty()) {
1248  info = info + QStringLiteral(": ") + errorInfo;
1249  }
1250 
1251  QMessageBox::critical(nullptr, "Error", info);
1252 }
1253 
1255 {
1256  const auto& friendPk = FriendList::id2Key(friendId);
1257  Friend* f = FriendList::findFriend(friendPk);
1258  if (!f) {
1259  return;
1260  }
1261 
1262  auto const oldStatus = f->getStatus();
1263  f->setStatus(status);
1264  auto const newStatus = f->getStatus();
1265 
1266  auto const startedNegotiating = (newStatus == Status::Status::Negotiating && oldStatus != newStatus);
1267  if (startedNegotiating) {
1268  constexpr auto negotiationTimeoutMs = 1000;
1269  auto timer = std::unique_ptr<QTimer>(new QTimer);
1270  timer->setSingleShot(true);
1271  timer->setInterval(negotiationTimeoutMs);
1272  connect(timer.get(), &QTimer::timeout, f, &Friend::onNegotiationComplete);
1273  timer->start();
1274  negotiateTimers[friendPk] = std::move(timer);
1275  }
1276 
1277  // Any widget behavior will be triggered based off of the status
1278  // transformations done by the Friend class
1279 }
1280 
1282 {
1283  FriendWidget* widget = friendWidgets[friendPk];
1284 
1285  if (Status::isOnline(status)) {
1287  } else {
1289  }
1290 
1291  widget->updateStatusLight();
1292  if (widget->isActive()) {
1293  setWindowTitle(widget->getTitle());
1294  }
1295 
1297 }
1298 
1299 void Widget::onFriendStatusMessageChanged(int friendId, const QString& message)
1300 {
1301  const auto& friendPk = FriendList::id2Key(friendId);
1302  Friend* f = FriendList::findFriend(friendPk);
1303  if (!f) {
1304  return;
1305  }
1306 
1307  QString str = message;
1308  str.replace('\n', ' ').remove('\r').remove(QChar('\0'));
1309  f->setStatusMessage(str);
1310 
1311  friendWidgets[friendPk]->setStatusMsg(str);
1312  chatForms[friendPk]->setStatusMessage(str);
1313 }
1314 
1315 void Widget::onFriendDisplayedNameChanged(const QString& displayed)
1316 {
1317  Friend* f = qobject_cast<Friend*>(sender());
1318  const auto& friendPk = f->getPublicKey();
1319  for (Group* g : GroupList::getAllGroups()) {
1320  if (g->getPeerList().contains(friendPk)) {
1321  g->updateUsername(friendPk, displayed);
1322  }
1323  }
1324 
1325  FriendWidget* friendWidget = friendWidgets[f->getPublicKey()];
1326  if (friendWidget->isActive()) {
1327  GUI::setWindowTitle(displayed);
1328  }
1329 
1331 }
1332 
1333 void Widget::onFriendUsernameChanged(int friendId, const QString& username)
1334 {
1335  const auto& friendPk = FriendList::id2Key(friendId);
1336  Friend* f = FriendList::findFriend(friendPk);
1337  if (!f) {
1338  return;
1339  }
1340 
1341  QString str = username;
1342  str.replace('\n', ' ').remove('\r').remove(QChar('\0'));
1343  f->setName(str);
1344 }
1345 
1346 void Widget::onFriendAliasChanged(const ToxPk& friendId, const QString& alias)
1347 {
1348  settings.setFriendAlias(friendId, alias);
1350 }
1351 
1353 {
1354  openDialog(widget, /* newWindow = */ false);
1355 }
1356 
1358 {
1359  openDialog(widget, /* newWindow = */ true);
1360 }
1361 
1362 void Widget::openDialog(GenericChatroomWidget* widget, bool newWindow)
1363 {
1364  widget->resetEventFlags();
1365  widget->updateStatusLight();
1366 
1367  GenericChatForm* form;
1368  GroupId id;
1369  const Friend* frnd = widget->getFriend();
1370  const Group* group = widget->getGroup();
1371  if (frnd) {
1372  form = chatForms[frnd->getPublicKey()];
1373  } else {
1374  id = group->getPersistentId();
1375  form = groupChatForms[id].data();
1376  }
1377  bool chatFormIsSet;
1380 
1381 
1382  if ((chatFormIsSet || form->isVisible()) && !newWindow) {
1383  return;
1384  }
1385 
1386  if (settings.getSeparateWindow() || newWindow) {
1387  ContentDialog* dialog = nullptr;
1388 
1389  if (!settings.getDontGroupWindows() && !newWindow) {
1391  }
1392 
1393  if (dialog == nullptr) {
1394  dialog = createContentDialog();
1395  }
1396 
1397  dialog->show();
1398 
1399  if (frnd) {
1400  addFriendDialog(frnd, dialog);
1401  } else {
1402  Group* group = widget->getGroup();
1403  addGroupDialog(group, dialog);
1404  }
1405 
1406  dialog->raise();
1407  dialog->activateWindow();
1408  } else {
1409  hideMainForms(widget);
1410  if (frnd) {
1411  chatForms[frnd->getPublicKey()]->show(contentLayout);
1412  } else {
1413  groupChatForms[group->getPersistentId()]->show(contentLayout);
1414  }
1415  widget->setAsActiveChatroom();
1416  setWindowTitle(widget->getTitle());
1417  }
1418 }
1419 
1420 void Widget::onFriendMessageReceived(uint32_t friendnumber, const QString& message, bool isAction)
1421 {
1422  const auto& friendId = FriendList::id2Key(friendnumber);
1423  Friend* f = FriendList::findFriend(friendId);
1424  if (!f) {
1425  return;
1426  }
1427 
1428  friendMessageDispatchers[f->getPublicKey()]->onMessageReceived(isAction, message);
1429 }
1430 
1431 void Widget::onReceiptReceived(int friendId, ReceiptNum receipt)
1432 {
1433  const auto& friendKey = FriendList::id2Key(friendId);
1434  Friend* f = FriendList::findFriend(friendKey);
1435  if (!f) {
1436  return;
1437  }
1438 
1439  friendMessageDispatchers[f->getPublicKey()]->onReceiptReceived(receipt);
1440 }
1441 
1442 void Widget::onExtendedMessageSupport(uint32_t friendNumber, bool compatible)
1443 {
1444  const auto& friendKey = FriendList::id2Key(friendNumber);
1445  Friend* f = FriendList::findFriend(friendKey);
1446  if (!f) {
1447  return;
1448  }
1449 
1450  f->setExtendedMessageSupport(compatible);
1451 }
1452 
1453 void Widget::onFriendExtMessageReceived(uint32_t friendNumber, const QString& message)
1454 {
1455  const auto& friendKey = FriendList::id2Key(friendNumber);
1456  friendMessageDispatchers[friendKey]->onExtMessageReceived(message);
1457 }
1458 
1459 void Widget::onExtReceiptReceived(uint32_t friendNumber, uint64_t receiptId)
1460 {
1461  const auto& friendKey = FriendList::id2Key(friendNumber);
1462  friendMessageDispatchers[friendKey]->onExtReceiptReceived(receiptId);
1463 }
1464 
1466 {
1467  const ToxPk& friendPk = frnd->getPublicKey();
1468  ContentDialog* contentDialog = ContentDialogManager::getInstance()->getFriendDialog(friendPk);
1469  bool isSeparate = settings.getSeparateWindow();
1470  FriendWidget* widget = friendWidgets[friendPk];
1471  bool isCurrent = activeChatroomWidget == widget;
1472  if (!contentDialog && !isSeparate && isCurrent) {
1473  onAddClicked();
1474  }
1475 
1476  auto form = chatForms[friendPk];
1477  auto chatroom = friendChatrooms[friendPk];
1478  FriendWidget* friendWidget =
1479  ContentDialogManager::getInstance()->addFriendToDialog(dialog, chatroom, form);
1480 
1481  friendWidget->setStatusMsg(widget->getStatusMsg());
1482 
1483 #if (QT_VERSION >= QT_VERSION_CHECK(5, 7, 0))
1484  auto widgetRemoveFriend = QOverload<const ToxPk&>::of(&Widget::removeFriend);
1485 #else
1486  auto widgetRemoveFriend = static_cast<void (Widget::*)(const ToxPk&)>(&Widget::removeFriend);
1487 #endif
1488  connect(friendWidget, &FriendWidget::removeFriend, this, widgetRemoveFriend);
1489  connect(friendWidget, &FriendWidget::middleMouseClicked, dialog,
1490  [=]() { dialog->removeFriend(friendPk); });
1491  connect(friendWidget, &FriendWidget::copyFriendIdToClipboard, this,
1493  connect(friendWidget, &FriendWidget::newWindowOpened, this, &Widget::openNewDialog);
1494 
1495  // Signal transmission from the created `friendWidget` (which shown in
1496  // ContentDialog) to the `widget` (which shown in main widget)
1497  // FIXME: emit should be removed
1498  connect(friendWidget, &FriendWidget::contextMenuCalled, widget,
1499  [=](QContextMenuEvent* event) { emit widget->contextMenuCalled(event); });
1500 
1501  connect(friendWidget, &FriendWidget::chatroomWidgetClicked, [=](GenericChatroomWidget* w) {
1502  Q_UNUSED(w)
1503  emit widget->chatroomWidgetClicked(widget);
1504  });
1505  connect(friendWidget, &FriendWidget::newWindowOpened, [=](GenericChatroomWidget* w) {
1506  Q_UNUSED(w)
1507  emit widget->newWindowOpened(widget);
1508  });
1509  // FIXME: emit should be removed
1510  emit widget->chatroomWidgetClicked(widget);
1511 
1512  connect(&profile, &Profile::friendAvatarSet, friendWidget, &FriendWidget::onAvatarSet);
1514 
1515  QPixmap avatar = profile.loadAvatar(frnd->getPublicKey());
1516  if (!avatar.isNull()) {
1517  friendWidget->onAvatarSet(frnd->getPublicKey(), avatar);
1518  }
1519 }
1520 
1522 {
1523  const GroupId& groupId = group->getPersistentId();
1525  bool separated = settings.getSeparateWindow();
1526  GroupWidget* widget = groupWidgets[groupId];
1527  bool isCurrentWindow = activeChatroomWidget == widget;
1528  if (!groupDialog && !separated && isCurrentWindow) {
1529  onAddClicked();
1530  }
1531 
1532  auto chatForm = groupChatForms[groupId].data();
1533  auto chatroom = groupChatrooms[groupId];
1534  auto groupWidget =
1535  ContentDialogManager::getInstance()->addGroupToDialog(dialog, chatroom, chatForm);
1536 
1537 #if (QT_VERSION >= QT_VERSION_CHECK(5, 7, 0))
1538  auto removeGroup = QOverload<const GroupId&>::of(&Widget::removeGroup);
1539 #else
1540  auto removeGroup = static_cast<void (Widget::*)(const GroupId&)>(&Widget::removeGroup);
1541 #endif
1542  connect(groupWidget, &GroupWidget::removeGroup, this, removeGroup);
1543  connect(groupWidget, &GroupWidget::chatroomWidgetClicked, chatForm, &GroupChatForm::focusInput);
1544  connect(groupWidget, &GroupWidget::middleMouseClicked, dialog,
1545  [=]() { dialog->removeGroup(groupId); });
1546  connect(groupWidget, &GroupWidget::chatroomWidgetClicked, chatForm, &ChatForm::focusInput);
1547  connect(groupWidget, &GroupWidget::newWindowOpened, this, &Widget::openNewDialog);
1548 
1549  // Signal transmission from the created `groupWidget` (which shown in
1550  // ContentDialog) to the `widget` (which shown in main widget)
1551  // FIXME: emit should be removed
1552  connect(groupWidget, &GroupWidget::chatroomWidgetClicked, [=](GenericChatroomWidget* w) {
1553  Q_UNUSED(w)
1554  emit widget->chatroomWidgetClicked(widget);
1555  });
1556 
1557  connect(groupWidget, &GroupWidget::newWindowOpened, [=](GenericChatroomWidget* w) {
1558  Q_UNUSED(w)
1559  emit widget->newWindowOpened(widget);
1560  });
1561 
1562  // FIXME: emit should be removed
1563  emit widget->chatroomWidgetClicked(widget);
1564 }
1565 
1566 bool Widget::newFriendMessageAlert(const ToxPk& friendId, const QString& text, bool sound, QString filename, size_t filesize)
1567 {
1568  bool hasActive;
1569  QWidget* currentWindow;
1570  ContentDialog* contentDialog = ContentDialogManager::getInstance()->getFriendDialog(friendId);
1571  Friend* f = FriendList::findFriend(friendId);
1572 
1573  if (contentDialog != nullptr) {
1574  currentWindow = contentDialog->window();
1575  hasActive = ContentDialogManager::getInstance()->isContactActive(friendId);
1576  } else {
1578  if (settings.getDontGroupWindows()) {
1579  contentDialog = createContentDialog();
1580  } else {
1581  contentDialog = ContentDialogManager::getInstance()->current();
1582  if (!contentDialog) {
1583  contentDialog = createContentDialog();
1584  }
1585  }
1586 
1587  addFriendDialog(f, contentDialog);
1588  currentWindow = contentDialog->window();
1589  hasActive = ContentDialogManager::getInstance()->isContactActive(friendId);
1590  } else {
1591  currentWindow = window();
1592  FriendWidget* widget = friendWidgets[friendId];
1593  hasActive = widget == activeChatroomWidget;
1594  }
1595  }
1596 
1597  if (newMessageAlert(currentWindow, hasActive, sound)) {
1598  FriendWidget* widget = friendWidgets[friendId];
1599  f->setEventFlag(true);
1600  widget->updateStatusLight();
1601  ui->friendList->trackWidget(widget);
1602 #if DESKTOP_NOTIFICATIONS
1603  auto notificationData = filename.isEmpty() ? notificationGenerator->friendMessageNotification(f, text)
1604  : notificationGenerator->fileTransferNotification(f, filename, filesize);
1605  notifier.notifyMessage(notificationData);
1606 #endif
1607 
1608  if (contentDialog == nullptr) {
1609  if (hasActive) {
1610  setWindowTitle(widget->getTitle());
1611  }
1612  } else {
1614  }
1615 
1616  return true;
1617  }
1618 
1619  return false;
1620 }
1621 
1622 bool Widget::newGroupMessageAlert(const GroupId& groupId, const ToxPk& authorPk,
1623  const QString& message, bool notify)
1624 {
1625  bool hasActive;
1626  QWidget* currentWindow;
1627  ContentDialog* contentDialog = ContentDialogManager::getInstance()->getGroupDialog(groupId);
1628  Group* g = GroupList::findGroup(groupId);
1629  GroupWidget* widget = groupWidgets[groupId];
1630 
1631  if (contentDialog != nullptr) {
1632  currentWindow = contentDialog->window();
1633  hasActive = ContentDialogManager::getInstance()->isContactActive(groupId);
1634  } else {
1635  currentWindow = window();
1636  hasActive = widget == activeChatroomWidget;
1637  }
1638 
1639  if (!newMessageAlert(currentWindow, hasActive, true, notify)) {
1640  return false;
1641  }
1642 
1643  g->setEventFlag(true);
1644  widget->updateStatusLight();
1645 #if DESKTOP_NOTIFICATIONS
1646  auto notificationData = notificationGenerator->groupMessageNotification(g, authorPk, message);
1647  notifier.notifyMessage(notificationData);
1648 #endif
1649 
1650  if (contentDialog == nullptr) {
1651  if (hasActive) {
1652  setWindowTitle(widget->getTitle());
1653  }
1654  } else {
1656  }
1657 
1658  return true;
1659 }
1660 
1662 {
1663  switch (type) {
1664  case DialogType::AddDialog:
1665  return tr("Add friend", "title of the window");
1667  return tr("Group invites", "title of the window");
1669  return tr("File transfers", "title of the window");
1671  return tr("Settings", "title of the window");
1673  return tr("My profile", "title of the window");
1674  }
1675 
1676  assert(false);
1677  return QString();
1678 }
1679 
1680 bool Widget::newMessageAlert(QWidget* currentWindow, bool isActive, bool sound, bool notify)
1681 {
1682  bool inactiveWindow = isMinimized() || !currentWindow->isActiveWindow();
1683 
1684  if (!inactiveWindow && isActive) {
1685  return false;
1686  }
1687 
1688  if (notify) {
1689  if (settings.getShowWindow()) {
1690  currentWindow->show();
1691  }
1692 
1693  if (settings.getNotify()) {
1694  if (inactiveWindow) {
1695 #if DESKTOP_NOTIFICATIONS
1696  if (!settings.getDesktopNotify()) {
1697  QApplication::alert(currentWindow);
1698  }
1699 #else
1700  QApplication::alert(currentWindow);
1701 #endif
1702  eventFlag = true;
1703  }
1704  bool isBusy = core->getStatus() == Status::Status::Busy;
1705  bool busySound = settings.getBusySound();
1706  bool notifySound = settings.getNotifySound();
1707 
1708  if (notifySound && sound && (!isBusy || busySound)) {
1709  playNotificationSound(IAudioSink::Sound::NewMessage);
1710  }
1711  }
1712  }
1713 
1714  return true;
1715 }
1716 
1717 void Widget::onFriendRequestReceived(const ToxPk& friendPk, const QString& message)
1718 {
1719  if (addFriendForm->addFriendRequest(friendPk.toString(), message)) {
1721  newMessageAlert(window(), isActiveWindow(), true, true);
1722 #if DESKTOP_NOTIFICATIONS
1723  auto notificationData = notificationGenerator->friendRequestNotification(friendPk, message);
1724  notifier.notifyMessage(notificationData);
1725 #endif
1726  }
1727 }
1728 
1730 {
1731  const ToxPk& friendPk = FriendList::id2Key(file.friendId);
1732  newFriendMessageAlert(friendPk, {}, true, file.fileName, file.progress.getFileSize());
1733 }
1734 
1736 {
1737  const ToxPk& pk = frnd.getPublicKey();
1738  const auto oldTime = settings.getFriendActivity(pk);
1739  const auto newTime = QDateTime::currentDateTime();
1740  settings.setFriendActivity(pk, newTime);
1741  FriendWidget* widget = friendWidgets[frnd.getPublicKey()];
1742  contactListWidget->moveWidget(widget, frnd.getStatus());
1743  contactListWidget->updateActivityTime(oldTime); // update old category widget
1744 }
1745 
1746 void Widget::removeFriend(Friend* f, bool fake)
1747 {
1748  if (!fake) {
1749  RemoveFriendDialog ask(this, f);
1750  ask.exec();
1751 
1752  if (!ask.accepted()) {
1753  return;
1754  }
1755 
1756  if (ask.removeHistory()) {
1758  }
1759  }
1760 
1761  const ToxPk friendPk = f->getPublicKey();
1762  auto widget = friendWidgets[friendPk];
1763  widget->setAsInactiveChatroom();
1764  if (widget == activeChatroomWidget) {
1765  activeChatroomWidget = nullptr;
1766  onAddClicked();
1767  }
1768 
1769  friendAlertConnections.remove(friendPk);
1770 
1772 
1774  if (lastDialog != nullptr) {
1775  lastDialog->removeFriend(friendPk);
1776  }
1777 
1778  FriendList::removeFriend(friendPk, fake);
1779  if (!fake) {
1780  core->removeFriend(f->getId());
1781  // aliases aren't supported for non-friend peers in groups, revert to basic username
1782  for (Group* g : GroupList::getAllGroups()) {
1783  if (g->getPeerList().contains(friendPk)) {
1784  g->updateUsername(friendPk, f->getUserName());
1785  }
1786  }
1787  }
1788 
1789  friendWidgets.remove(friendPk);
1790 
1791  auto chatForm = chatForms[friendPk];
1792  chatForms.remove(friendPk);
1793  delete chatForm;
1794 
1795  delete f;
1796  if (contentLayout && contentLayout->mainHead->layout()->isEmpty()) {
1797  onAddClicked();
1798  }
1799 }
1800 
1801 void Widget::removeFriend(const ToxPk& friendId)
1802 {
1803  removeFriend(FriendList::findFriend(friendId), false);
1804 }
1805 
1807 {
1808  widget->resetEventFlags();
1809  widget->updateStatusLight();
1810 
1811  ui->friendList->updateTracking(widget);
1812  resetIcon();
1813 }
1814 
1816 {
1818 }
1819 
1821 {
1822  const GroupId& groupId = g->getPersistentId();
1823  onDialogShown(groupWidgets[groupId]);
1824 }
1825 
1827 {
1828  if (windowState().testFlag(Qt::WindowFullScreen)) {
1829  setWindowState(windowState() & ~Qt::WindowFullScreen);
1830  } else {
1831  setWindowState(windowState() | Qt::WindowFullScreen);
1832  }
1833 }
1834 
1836 {
1837  ui->settingsButton->setProperty("update-available", true);
1838  ui->settingsButton->style()->unpolish(ui->settingsButton);
1839  ui->settingsButton->style()->polish(ui->settingsButton);
1840 }
1841 
1843 {
1844  ContentDialog* contentDialog = new ContentDialog(*core);
1845 
1846  registerContentDialog(*contentDialog);
1847  return contentDialog;
1848 }
1849 
1851 {
1853  connect(&contentDialog, &ContentDialog::friendDialogShown, this, &Widget::onFriendDialogShown);
1854  connect(&contentDialog, &ContentDialog::groupDialogShown, this, &Widget::onGroupDialogShown);
1855  connect(core, &Core::usernameSet, &contentDialog, &ContentDialog::setUsername);
1856  connect(&settings, &Settings::groupchatPositionChanged, &contentDialog,
1858  connect(&contentDialog, &ContentDialog::addFriendDialog, this, &Widget::addFriendDialog);
1859  connect(&contentDialog, &ContentDialog::addGroupDialog, this, &Widget::addGroupDialog);
1860  connect(&contentDialog, &ContentDialog::connectFriendWidget, this, &Widget::connectFriendWidget);
1861 
1862 #ifdef Q_OS_MAC
1863  Nexus& n = Nexus::getInstance();
1864  connect(&contentDialog, &ContentDialog::destroyed, &n, &Nexus::updateWindowsClosed);
1865  connect(&contentDialog, &ContentDialog::windowStateChanged, &n, &Nexus::onWindowStateChanged);
1866  connect(contentDialog.windowHandle(), &QWindow::windowTitleChanged, &n, &Nexus::updateWindows);
1867  n.updateWindows();
1868 #endif
1869 }
1870 
1872 {
1873  class Dialog : public ActivateDialog
1874  {
1875  public:
1876  explicit Dialog(DialogType type, Settings& settings, Core* core)
1877  : ActivateDialog(nullptr, Qt::Window)
1878  , type(type)
1879  , settings(settings)
1880  , core{core}
1881  {
1882  restoreGeometry(settings.getDialogSettingsGeometry());
1883  Translator::registerHandler(std::bind(&Dialog::retranslateUi, this), this);
1884  retranslateUi();
1885  setWindowIcon(QIcon(":/img/icons/qtox.svg"));
1886  reloadTheme();
1887 
1888  connect(core, &Core::usernameSet, this, &Dialog::retranslateUi);
1889  }
1890 
1891  ~Dialog()
1892  {
1893  Translator::unregister(this);
1894  }
1895 
1896  public slots:
1897 
1898  void retranslateUi()
1899  {
1900  setWindowTitle(core->getUsername() + QStringLiteral(" - ") + Widget::fromDialogType(type));
1901  }
1902 
1903  void reloadTheme() final
1904  {
1905  setStyleSheet(Style::getStylesheet("window/general.css"));
1906  }
1907 
1908  protected:
1909  void resizeEvent(QResizeEvent* event) override
1910  {
1911  settings.setDialogSettingsGeometry(saveGeometry());
1912  QDialog::resizeEvent(event);
1913  }
1914 
1915  void moveEvent(QMoveEvent* event) override
1916  {
1917  settings.setDialogSettingsGeometry(saveGeometry());
1918  QDialog::moveEvent(event);
1919  }
1920 
1921  private:
1922  DialogType type;
1923  Settings& settings;
1924  Core* core;
1925  };
1926 
1927  Dialog* dialog = new Dialog(type, settings, core);
1928  dialog->setAttribute(Qt::WA_DeleteOnClose);
1929  ContentLayout* contentLayoutDialog = new ContentLayout(dialog);
1930 
1931  dialog->setObjectName("detached");
1932  dialog->setLayout(contentLayoutDialog);
1933  dialog->layout()->setMargin(0);
1934  dialog->layout()->setSpacing(0);
1935  dialog->setMinimumSize(720, 400);
1936  dialog->setAttribute(Qt::WA_DeleteOnClose);
1937  dialog->show();
1938 
1939 #ifdef Q_OS_MAC
1940  connect(dialog, &Dialog::destroyed, &Nexus::getInstance(), &Nexus::updateWindowsClosed);
1942  &Nexus::updateWindowsStates);
1943  connect(dialog->windowHandle(), &QWindow::windowTitleChanged, &Nexus::getInstance(),
1944  &Nexus::updateWindows);
1945  Nexus::getInstance().updateWindows();
1946 #endif
1947 
1948  return contentLayoutDialog;
1949 }
1950 
1952 {
1953  Friend* f = FriendList::findFriend(friendId);
1954  if (f != nullptr) {
1955  QClipboard* clipboard = QApplication::clipboard();
1956  clipboard->setText(friendId.toString(), QClipboard::Clipboard);
1957  }
1958 }
1959 
1961 {
1962  const uint32_t friendId = inviteInfo.getFriendId();
1963  const ToxPk& friendPk = FriendList::id2Key(friendId);
1964  const Friend* f = FriendList::findFriend(friendPk);
1966 
1967  const uint8_t confType = inviteInfo.getType();
1968  if (confType == TOX_CONFERENCE_TYPE_TEXT || confType == TOX_CONFERENCE_TYPE_AV) {
1970  onGroupInviteAccepted(inviteInfo);
1971  } else {
1972  if (!groupInviteForm->addGroupInvite(inviteInfo)) {
1973  return;
1974  }
1975 
1978  newMessageAlert(window(), isActiveWindow(), true, true);
1979 #if DESKTOP_NOTIFICATIONS
1980  auto notificationData = notificationGenerator->groupInvitationNotification(f);
1981  notifier.notifyMessage(notificationData);
1982 #endif
1983  }
1984  } else {
1985  qWarning() << "onGroupInviteReceived: Unknown groupchat type:" << confType;
1986  return;
1987  }
1988 }
1989 
1991 {
1992  const uint32_t groupId = core->joinGroupchat(inviteInfo);
1993  if (groupId == std::numeric_limits<uint32_t>::max()) {
1994  qWarning() << "onGroupInviteAccepted: Unable to accept group invite";
1995  return;
1996  }
1997 }
1998 
1999 void Widget::onGroupMessageReceived(int groupnumber, int peernumber, const QString& message,
2000  bool isAction)
2001 {
2002  const GroupId& groupId = GroupList::id2Key(groupnumber);
2003  assert(GroupList::findGroup(groupId));
2004 
2005  ToxPk author = core->getGroupPeerPk(groupnumber, peernumber);
2006 
2007  groupMessageDispatchers[groupId]->onMessageReceived(author, isAction, message);
2008 }
2009 
2010 void Widget::onGroupPeerlistChanged(uint32_t groupnumber)
2011 {
2012  const GroupId& groupId = GroupList::id2Key(groupnumber);
2013  Group* g = GroupList::findGroup(groupId);
2014  assert(g);
2015  g->regeneratePeerList();
2016 }
2017 
2018 void Widget::onGroupPeerNameChanged(uint32_t groupnumber, const ToxPk& peerPk, const QString& newName)
2019 {
2020  const GroupId& groupId = GroupList::id2Key(groupnumber);
2021  Group* g = GroupList::findGroup(groupId);
2022  assert(g);
2023 
2024  const QString setName = FriendList::decideNickname(peerPk, newName);
2025  g->updateUsername(peerPk, newName);
2026 }
2027 
2028 void Widget::onGroupTitleChanged(uint32_t groupnumber, const QString& author, const QString& title)
2029 {
2030  const GroupId& groupId = GroupList::id2Key(groupnumber);
2031  Group* g = GroupList::findGroup(groupId);
2032  assert(g);
2033 
2034  GroupWidget* widget = groupWidgets[groupId];
2035  if (widget->isActive()) {
2036  GUI::setWindowTitle(title);
2037  }
2038 
2039  g->setTitle(author, title);
2041 }
2042 
2043 void Widget::titleChangedByUser(const QString& title)
2044 {
2045  const auto* group = qobject_cast<Group*>(sender());
2046  assert(group != nullptr);
2047  emit changeGroupTitle(group->getId(), title);
2048 }
2049 
2050 void Widget::onGroupPeerAudioPlaying(int groupnumber, ToxPk peerPk)
2051 {
2052  const GroupId& groupId = GroupList::id2Key(groupnumber);
2053  assert(GroupList::findGroup(groupId));
2054 
2055  auto form = groupChatForms[groupId].data();
2056  form->peerAudioPlaying(peerPk);
2057 }
2058 
2059 void Widget::removeGroup(Group* g, bool fake)
2060 {
2061  const auto& groupId = g->getPersistentId();
2062  const auto groupnumber = g->getId();
2063  auto groupWidgetIt = groupWidgets.find(groupId);
2064  if (groupWidgetIt == groupWidgets.end()) {
2065  qWarning() << "Tried to remove group" << groupnumber << "but GroupWidget doesn't exist";
2066  return;
2067  }
2068  auto widget = groupWidgetIt.value();
2069  widget->setAsInactiveChatroom();
2070  if (static_cast<GenericChatroomWidget*>(widget) == activeChatroomWidget) {
2071  activeChatroomWidget = nullptr;
2072  onAddClicked();
2073  }
2074 
2075  GroupList::removeGroup(groupId, fake);
2076  ContentDialog* contentDialog = ContentDialogManager::getInstance()->getGroupDialog(groupId);
2077  if (contentDialog != nullptr) {
2078  contentDialog->removeGroup(groupId);
2079  }
2080 
2081  if (!fake) {
2082  core->removeGroup(groupnumber);
2083  }
2084  contactListWidget->removeGroupWidget(widget); // deletes widget
2085 
2086  groupWidgets.remove(groupId);
2087  auto groupChatFormIt = groupChatForms.find(groupId);
2088  if (groupChatFormIt == groupChatForms.end()) {
2089  qWarning() << "Tried to remove group" << groupnumber << "but GroupChatForm doesn't exist";
2090  return;
2091  }
2092  groupChatForms.erase(groupChatFormIt);
2093  groupAlertConnections.remove(groupId);
2094 
2095  delete g;
2096  if (contentLayout && contentLayout->mainHead->layout()->isEmpty()) {
2097  onAddClicked();
2098  }
2099 
2100 }
2101 
2102 void Widget::removeGroup(const GroupId& groupId)
2103 {
2105 }
2106 
2107 Group* Widget::createGroup(uint32_t groupnumber, const GroupId& groupId)
2108 {
2109  assert(core != nullptr);
2110 
2111  Group* g = GroupList::findGroup(groupId);
2112  if (g) {
2113  qWarning() << "Group already exists";
2114  return g;
2115  }
2116 
2117  const auto groupName = tr("Groupchat #%1").arg(groupnumber);
2118  const bool enabled = core->getGroupAvEnabled(groupnumber);
2119  Group* newgroup =
2120  GroupList::addGroup(*core, groupnumber, groupId, groupName, enabled, core->getUsername());
2121  assert(newgroup);
2122 
2123  if (enabled) {
2124  connect(newgroup, &Group::userLeft, [=](const ToxPk& user){
2125  CoreAV *av = core->getAv();
2126  assert(av);
2127  av->invalidateGroupCallPeerSource(*newgroup, user);
2128  });
2129  }
2130  auto dialogManager = ContentDialogManager::getInstance();
2131  auto rawChatroom = new GroupChatroom(newgroup, dialogManager, *core);
2132  std::shared_ptr<GroupChatroom> chatroom(rawChatroom);
2133 
2134  const auto compact = settings.getCompactLayout();
2135  auto widget = new GroupWidget(chatroom, compact);
2136  auto messageProcessor = MessageProcessor(*sharedMessageProcessorParams);
2137  auto messageDispatcher =
2138  std::make_shared<GroupMessageDispatcher>(*newgroup, std::move(messageProcessor), *core,
2139  *core, settings);
2140  auto groupChatLog = std::make_shared<SessionChatLog>(*core);
2141 
2142  connect(messageDispatcher.get(), &IMessageDispatcher::messageReceived, groupChatLog.get(),
2144  connect(messageDispatcher.get(), &IMessageDispatcher::messageSent, groupChatLog.get(),
2146  connect(messageDispatcher.get(), &IMessageDispatcher::messageComplete, groupChatLog.get(),
2148  connect(messageDispatcher.get(), &IMessageDispatcher::messageBroken, groupChatLog.get(),
2150 
2151  auto notifyReceivedCallback = [this, groupId](const ToxPk& author, const Message& message) {
2152  auto isTargeted = std::any_of(message.metadata.begin(), message.metadata.end(),
2153  [](MessageMetadata metadata) {
2154  return metadata.type == MessageMetadataType::selfMention;
2155  });
2156  newGroupMessageAlert(groupId, author, message.content,
2157  isTargeted || settings.getGroupAlwaysNotify());
2158  };
2159 
2160  auto notifyReceivedConnection =
2161  connect(messageDispatcher.get(), &IMessageDispatcher::messageReceived, notifyReceivedCallback);
2162  groupAlertConnections.insert(groupId, notifyReceivedConnection);
2163 
2164  auto form = new GroupChatForm(*core, newgroup, *groupChatLog, *messageDispatcher, settings);
2166  form->setColorizedNames(settings.getEnableGroupChatsColor());
2167  groupMessageDispatchers[groupId] = messageDispatcher;
2168  groupChatLogs[groupId] = groupChatLog;
2169  groupWidgets[groupId] = widget;
2170  groupChatrooms[groupId] = chatroom;
2171  groupChatForms[groupId] = QSharedPointer<GroupChatForm>(form);
2172 
2174  widget->updateStatusLight();
2175  contactListWidget->activateWindow();
2176 
2178  connect(widget, &GroupWidget::newWindowOpened, this, &Widget::openNewDialog);
2179 #if (QT_VERSION >= QT_VERSION_CHECK(5, 7, 0))
2180  auto widgetRemoveGroup = QOverload<const GroupId&>::of(&Widget::removeGroup);
2181 #else
2182  auto widgetRemoveGroup = static_cast<void (Widget::*)(const GroupId&)>(&Widget::removeGroup);
2183 #endif
2184  connect(widget, &GroupWidget::removeGroup, this, widgetRemoveGroup);
2185  connect(widget, &GroupWidget::middleMouseClicked, this, [=]() { removeGroup(groupId); });
2186  connect(widget, &GroupWidget::chatroomWidgetClicked, form, &ChatForm::focusInput);
2187  connect(newgroup, &Group::titleChangedByUser, this, &Widget::titleChangedByUser);
2188  connect(core, &Core::usernameSet, newgroup, &Group::setSelfName);
2189 
2190  return newgroup;
2191 }
2192 
2193 void Widget::onEmptyGroupCreated(uint32_t groupnumber, const GroupId& groupId, const QString& title)
2194 {
2195  Group* group = createGroup(groupnumber, groupId);
2196  if (!group) {
2197  return;
2198  }
2199  if (title.isEmpty()) {
2200  // Only rename group if groups are visible.
2201  if (groupsVisible()) {
2202  groupWidgets[groupId]->editName();
2203  }
2204  } else {
2205  group->setTitle(QString(), title);
2206  }
2207 }
2208 
2209 void Widget::onGroupJoined(int groupId, const GroupId& groupPersistentId)
2210 {
2211  createGroup(groupId, groupPersistentId);
2212 }
2213 
2218 {
2219  eventIcon = false;
2220  eventFlag = false;
2221  updateIcons();
2222 }
2223 
2224 bool Widget::event(QEvent* e)
2225 {
2226  switch (e->type()) {
2227  case QEvent::MouseButtonPress:
2228  case QEvent::MouseButtonDblClick:
2229  focusChatInput();
2230  break;
2231  case QEvent::Paint:
2232  ui->friendList->updateVisualTracking();
2233  break;
2234  case QEvent::WindowActivate:
2235  if (activeChatroomWidget) {
2239  }
2240 
2241  if (eventFlag) {
2242  resetIcon();
2243  }
2244 
2245  focusChatInput();
2246 
2247 #ifdef Q_OS_MAC
2248  emit windowStateChanged(windowState());
2249 
2250  case QEvent::WindowStateChange:
2251  Nexus::getInstance().updateWindowsStates();
2252 #endif
2253  break;
2254  default:
2255  break;
2256  }
2257 
2258  return QMainWindow::event(e);
2259 }
2260 
2262 {
2263 #ifdef QTOX_PLATFORM_EXT
2264  uint32_t autoAwayTime = settings.getAutoAwayTime() * 60 * 1000;
2265  bool online = static_cast<Status::Status>(ui->statusButton->property("status").toInt())
2267  bool away = autoAwayTime && Platform::getIdleTime() >= autoAwayTime;
2268 
2269  if (online && away) {
2270  qDebug() << "auto away activated at" << QTime::currentTime().toString();
2272  autoAwayActive = true;
2273  } else if (autoAwayActive && !away) {
2274  qDebug() << "auto away deactivated at" << QTime::currentTime().toString();
2276  autoAwayActive = false;
2277  }
2278 #endif
2279 }
2280 
2282 {
2283  if (eventFlag) {
2284  eventIcon ^= true;
2285  updateIcons();
2286  }
2287 }
2288 
2290 {
2291  static int32_t tries = 15;
2292  if (!icon && tries--) {
2293  if (QSystemTrayIcon::isSystemTrayAvailable()) {
2294  icon = std::unique_ptr<QSystemTrayIcon>(new QSystemTrayIcon);
2295  updateIcons();
2296  trayMenu = new QMenu(this);
2297 
2298  // adding activate to the top, avoids accidentally clicking quit
2299  trayMenu->addAction(actionShow);
2300  trayMenu->addSeparator();
2301  trayMenu->addAction(statusOnline);
2302  trayMenu->addAction(statusAway);
2303  trayMenu->addAction(statusBusy);
2304  trayMenu->addSeparator();
2305  trayMenu->addAction(actionLogout);
2306  trayMenu->addAction(actionQuit);
2307  icon->setContextMenu(trayMenu);
2308 
2309  connect(icon.get(), &QSystemTrayIcon::activated, this, &Widget::onIconClick);
2310 
2311  if (settings.getShowSystemTray()) {
2312  icon->show();
2313  setHidden(settings.getAutostartInTray());
2314  } else {
2315  show();
2316  }
2317 
2318 #ifdef Q_OS_MAC
2319  Nexus::getInstance().dockMenu->setAsDockMenu();
2320 #endif
2321  } else if (!isVisible()) {
2322  show();
2323  }
2324  } else {
2325  disconnect(timer, &QTimer::timeout, this, &Widget::onTryCreateTrayIcon);
2326  if (!icon) {
2327  qWarning() << "No system tray detected!";
2328  show();
2329  }
2330  }
2331 }
2332 
2334 {
2335  if (!ui->statusButton->isEnabled()) {
2336  return;
2337  }
2338 
2340 }
2341 
2343 {
2344  if (!ui->statusButton->isEnabled()) {
2345  return;
2346  }
2347 
2349 }
2350 
2352 {
2353  if (!ui->statusButton->isEnabled()) {
2354  return;
2355  }
2356 
2358 }
2359 
2360 void Widget::onGroupSendFailed(uint32_t groupnumber)
2361 {
2362  const auto& groupId = GroupList::id2Key(groupnumber);
2363  assert(GroupList::findGroup(groupId));
2364 
2365  const auto curTime = QDateTime::currentDateTime();
2366  auto form = groupChatForms[groupId].data();
2367  form->addSystemInfoMessage(curTime, SystemMessageType::messageSendFailed, {});
2368 }
2369 
2370 void Widget::onFriendTypingChanged(uint32_t friendnumber, bool isTyping)
2371 {
2372  const auto& friendId = FriendList::id2Key(friendnumber);
2373  Friend* f = FriendList::findFriend(friendId);
2374  if (!f) {
2375  return;
2376  }
2377 
2378  chatForms[f->getPublicKey()]->setFriendTyping(isTyping);
2379 }
2380 
2381 void Widget::onSetShowSystemTray(bool newValue)
2382 {
2383  if (icon) {
2384  icon->setVisible(newValue);
2385  }
2386 }
2387 
2389 {
2390  settings.setWindowGeometry(saveGeometry());
2391  settings.setWindowState(saveState());
2392 }
2393 
2395 {
2396  if (!settings.getSeparateWindow()) {
2397  settings.setSplitterState(ui->mainSplitter->saveState());
2398  }
2399 }
2400 
2401 void Widget::onSplitterMoved(int pos, int index)
2402 {
2403  Q_UNUSED(pos)
2404  Q_UNUSED(index)
2406 }
2407 
2408 void Widget::cycleContacts(bool forward)
2409 {
2411 }
2412 
2414 {
2415  switch (index) {
2418  return true;
2419  default:
2420  return false;
2421  }
2422 }
2423 
2425 {
2426  switch (index) {
2429  return true;
2430  default:
2431  return false;
2432  }
2433 }
2434 
2436 {
2437  switch (index) {
2440  return true;
2441  default:
2442  return false;
2443  }
2444 }
2445 
2447 {
2449  for (Friend* f : frnds) {
2450  friendMessageDispatchers[f->getPublicKey()]->clearOutgoingMessages();
2451  }
2452 }
2453 
2455 {
2456  setStyleSheet("");
2457  QWidgetList wgts = findChildren<QWidget*>();
2458  for (auto x : wgts) {
2459  x->setStyleSheet("");
2460  }
2461 
2462  this->setStyleSheet(Style::getStylesheet("window/general.css"));
2463  QString statusPanelStyle = Style::getStylesheet("window/statusPanel.css");
2464  ui->tooliconsZone->setStyleSheet(Style::getStylesheet("tooliconsZone/tooliconsZone.css"));
2465  ui->statusPanel->setStyleSheet(statusPanelStyle);
2466  ui->statusHead->setStyleSheet(statusPanelStyle);
2467  ui->friendList->setStyleSheet(Style::getStylesheet("friendList/friendList.css"));
2468  ui->statusButton->setStyleSheet(Style::getStylesheet("statusButton/statusButton.css"));
2469 
2470  profilePicture->setStyleSheet(Style::getStylesheet("window/profile.css"));
2471 }
2472 
2474 {
2475  cycleContacts(true);
2476 }
2477 
2479 {
2480  cycleContacts(false);
2481 }
2482 
2483 // Preparing needed to set correct size of icons for GTK tray backend
2484 inline QIcon Widget::prepareIcon(QString path, int w, int h)
2485 {
2486 #ifdef Q_OS_LINUX
2487 
2488  QString desktop = getenv("XDG_CURRENT_DESKTOP");
2489  if (desktop.isEmpty()) {
2490  desktop = getenv("DESKTOP_SESSION");
2491  }
2492 
2493  desktop = desktop.toLower();
2494  if (desktop == "xfce" || desktop.contains("gnome") || desktop == "mate" || desktop == "x-cinnamon") {
2495  if (w > 0 && h > 0) {
2496  QSvgRenderer renderer(path);
2497 
2498  QPixmap pm(w, h);
2499  pm.fill(Qt::transparent);
2500  QPainter painter(&pm);
2501  renderer.render(&painter, pm.rect());
2502 
2503  return QIcon(pm);
2504  }
2505  }
2506 #endif
2507  return QIcon(path);
2508 }
2509 
2511 {
2512  QString searchString = ui->searchContactText->text();
2513  FilterCriteria filter = getFilterCriteria();
2514 
2515  contactListWidget->searchChatrooms(searchString, filterOnline(filter), filterOffline(filter),
2516  filterGroups(filter));
2517 
2518  updateFilterText();
2519 }
2520 
2522 {
2523  filterDisplayGroup->setEnabled(false);
2524 
2525  if (filterDisplayGroup->checkedAction() == filterDisplayActivity) {
2527  } else if (filterDisplayGroup->checkedAction() == filterDisplayName) {
2529  }
2530 
2531  searchContacts();
2532  filterDisplayGroup->setEnabled(true);
2533 
2534  updateFilterText();
2535 }
2536 
2538 {
2539  QString action = filterDisplayGroup->checkedAction()->text();
2540  QString text = filterGroup->checkedAction()->text();
2541  text = action + QStringLiteral(" | ") + text;
2542  ui->searchContactFilterBox->setText(text);
2543 }
2544 
2546 {
2547  QAction* checked = filterGroup->checkedAction();
2548 
2549  if (checked == filterOnlineAction)
2550  return FilterCriteria::Online;
2551  else if (checked == filterOfflineAction)
2552  return FilterCriteria::Offline;
2553  else if (checked == filterFriendsAction)
2554  return FilterCriteria::Friends;
2555  else if (checked == filterGroupsAction)
2556  return FilterCriteria::Groups;
2557 
2558  return FilterCriteria::All;
2559 }
2560 
2562 {
2564  FilterCriteria filter = getFilterCriteria();
2565  QString text = ui->searchContactText->text();
2566  circleWidget.search(text, true, filterOnline(filter), filterOffline(filter));
2567  }
2568 }
2569 
2571 {
2572  FilterCriteria filter = getFilterCriteria();
2573  return !filterGroups(filter);
2574 }
2575 
2576 void Widget::friendListContextMenu(const QPoint& pos)
2577 {
2578  QMenu menu(this);
2579  QAction* createGroupAction = menu.addAction(tr("Create new group..."));
2580  QAction* addCircleAction = menu.addAction(tr("Add new circle..."));
2581  QAction* chosenAction = menu.exec(ui->friendList->mapToGlobal(pos));
2582 
2583  if (chosenAction == addCircleAction) {
2585  } else if (chosenAction == createGroupAction) {
2586  core->createGroup();
2587  }
2588 }
2589 
2591 {
2592  unsigned int unreadFriendRequests = settings.getUnreadFriendRequests();
2593 
2594  if (unreadFriendRequests == 0) {
2595  delete friendRequestsButton;
2596  friendRequestsButton = nullptr;
2597  } else if (!friendRequestsButton) {
2598  friendRequestsButton = new QPushButton(this);
2599  friendRequestsButton->setObjectName("green");
2600  ui->statusLayout->insertWidget(2, friendRequestsButton);
2601 
2602  connect(friendRequestsButton, &QPushButton::released, [this]() {
2603  onAddClicked();
2604  addFriendForm->setMode(AddFriendForm::Mode::FriendRequest);
2605  });
2606  }
2607 
2608  if (friendRequestsButton) {
2609  friendRequestsButton->setText(tr("%n new friend request(s)", "", unreadFriendRequests));
2610  }
2611 }
2612 
2614 {
2615  if (unreadGroupInvites == 0) {
2616  delete groupInvitesButton;
2617  groupInvitesButton = nullptr;
2618  } else if (!groupInvitesButton) {
2619  groupInvitesButton = new QPushButton(this);
2620  groupInvitesButton->setObjectName("green");
2621  ui->statusLayout->insertWidget(2, groupInvitesButton);
2622 
2623  connect(groupInvitesButton, &QPushButton::released, this, &Widget::onGroupClicked);
2624  }
2625 
2626  if (groupInvitesButton) {
2627  groupInvitesButton->setText(tr("%n new group invite(s)", "", unreadGroupInvites));
2628  }
2629 }
2630 
2632 {
2633  unreadGroupInvites = 0;
2635 }
2636 
2638 {
2639  ui->addButton->setChecked(newActiveButton == ActiveToolMenuButton::AddButton);
2640  ui->addButton->setDisabled(newActiveButton == ActiveToolMenuButton::AddButton);
2641  ui->groupButton->setChecked(newActiveButton == ActiveToolMenuButton::GroupButton);
2642  ui->groupButton->setDisabled(newActiveButton == ActiveToolMenuButton::GroupButton);
2643  ui->transferButton->setChecked(newActiveButton == ActiveToolMenuButton::TransferButton);
2644  ui->transferButton->setDisabled(newActiveButton == ActiveToolMenuButton::TransferButton);
2645  ui->settingsButton->setChecked(newActiveButton == ActiveToolMenuButton::SettingButton);
2646  ui->settingsButton->setDisabled(newActiveButton == ActiveToolMenuButton::SettingButton);
2647 }
2648 
2650 {
2651  ui->retranslateUi(this);
2654 
2655  filterDisplayName->setText(tr("By Name"));
2656  filterDisplayActivity->setText(tr("By Activity"));
2657  filterAllAction->setText(tr("All"));
2658  filterOnlineAction->setText(tr("Online"));
2659  filterOfflineAction->setText(tr("Offline"));
2660  filterFriendsAction->setText(tr("Friends"));
2661  filterGroupsAction->setText(tr("Groups"));
2662  ui->searchContactText->setPlaceholderText(tr("Search Contacts"));
2663  updateFilterText();
2664 
2665  statusOnline->setText(tr("Online", "Button to set your status to 'Online'"));
2666  statusAway->setText(tr("Away", "Button to set your status to 'Away'"));
2667  statusBusy->setText(tr("Busy", "Button to set your status to 'Busy'"));
2668  actionLogout->setText(tr("Logout", "Tray action menu to logout user"));
2669  actionQuit->setText(tr("Exit", "Tray action menu to exit Tox"));
2670  actionShow->setText(tr("Show", "Tray action menu to show qTox window"));
2671 
2672  if (!settings.getSeparateWindow() && (settingsWidget && settingsWidget->isShown())) {
2674  }
2675 
2678 
2679 
2680 #ifdef Q_OS_MAC
2681  Nexus::getInstance().retranslateUi();
2682 
2683  filterMenu->menuAction()->setText(tr("Filter..."));
2684 
2685  fileMenu->setText(tr("File"));
2686  editMenu->setText(tr("Edit"));
2687  contactMenu->setText(tr("Contacts"));
2688  changeStatusMenu->menuAction()->setText(tr("Change status"));
2689  editProfileAction->setText(tr("Edit profile"));
2690  logoutAction->setText(tr("Logout"));
2691  addContactAction->setText(tr("Add contact..."));
2692  nextConversationAction->setText(tr("Next conversation"));
2693  previousConversationAction->setText(tr("Previous conversation"));
2694 #endif
2695 }
2696 
2698 {
2699  if (activeChatroomWidget) {
2700  if (const Friend* f = activeChatroomWidget->getFriend()) {
2701  chatForms[f->getPublicKey()]->focusInput();
2702  } else if (Group* g = activeChatroomWidget->getGroup()) {
2703  groupChatForms[g->getPersistentId()]->focusInput();
2704  }
2705  }
2706 }
2707 
2708 void Widget::refreshPeerListsLocal(const QString& username)
2709 {
2710  for (Group* g : GroupList::getAllGroups()) {
2711  g->updateUsername(core->getSelfPublicKey(), username);
2712  }
2713 }
2714 
2716 {
2717  connect(&circleWidget, &CircleWidget::newContentDialog, this, &Widget::registerContentDialog);
2718 }
2719 
2721 {
2722  connect(&friendWidget, &FriendWidget::updateFriendActivity, this, &Widget::updateFriendActivity);
2723 }
Core::groupTitleChanged
void groupTitleChanged(int groupnumber, const QString &author, const QString &title)
FriendListWidget::onGroupchatPositionChanged
void onGroupchatPositionChanged(bool top)
Definition: friendlistwidget.cpp:429
Settings::setProxyType
void setProxyType(ICoreSettings::ProxyType type) override
Definition: settings.cpp:1177
FriendWidget::onAvatarSet
void onAvatarSet(const ToxPk &friendPk, const QPixmap &pic)
Definition: friendwidget.cpp:409
profileform.h
FriendListWidget::addCircleWidget
void addCircleWidget(int id)
Definition: friendlistwidget.cpp:382
profile.h
Settings
Definition: settings.h:51
SessionChatLog::onMessageBroken
void onMessageBroken(DispatchedMessageId id, BrokenMessageReason reason)
Definition: sessionchatlog.cpp:439
FriendList::removeFriend
static void removeFriend(const ToxPk &friendPk, bool fake=false)
Definition: friendlist.cpp:62
SplitterRestorer::restore
void restore(const QByteArray &state, const QSize &windowSize)
Restore splitter from state. And reset in case of error. Set the splitter to a reasonnable width by d...
Definition: splitterrestorer.cpp:55
Widget::changeGroupTitle
void changeGroupTitle(uint32_t groupnumber, const QString &title)
Widget::friendRequestAccepted
void friendRequestAccepted(const ToxPk &friendPk)
Nexus::showLogin
int showLogin(const QString &profileName=QString())
Hides the main GUI, delete the profile, and shows the login screen.
Definition: nexus.cpp:153
Status::Status
Status
Definition: status.h:28
Widget::onSeparateWindowClicked
void onSeparateWindowClicked(bool separate)
Definition: widget.cpp:777
Widget::event
bool event(QEvent *e) final
Definition: widget.cpp:2224
style.h
ContentDialogManager::updateFriendStatus
void updateFriendStatus(const ToxPk &friendPk)
Definition: contentdialogmanager.cpp:125
Widget::onSelfAvatarLoaded
void onSelfAvatarLoaded(const QPixmap &pic)
Definition: widget.cpp:688
Widget::hideMainForms
void hideMainForms(GenericChatroomWidget *chatroomWidget)
Definition: widget.cpp:998
ProfileForm::show
void show(ContentLayout *contentLayout)
Definition: profileform.cpp:208
Core::statusSet
void statusSet(Status::Status status)
FriendListWidget::moveWidget
void moveWidget(FriendWidget *w, Status::Status s, bool add=false)
Definition: friendlistwidget.cpp:563
GenericChatroomWidget::getGroup
virtual Group * getGroup() const
Definition: genericchatroomwidget.h:49
ChatForm
Definition: chatform.h:46
Widget::onUserAwayCheck
void onUserAwayCheck()
Definition: widget.cpp:2261
Widget::filterOnline
static bool filterOnline(FilterCriteria index)
Definition: widget.cpp:2435
FriendWidget::friendHistoryRemoved
void friendHistoryRemoved()
Widget::updateIcons
void updateIcons()
Definition: widget.cpp:532
GenericChatForm
Parent class for all chatforms. It's provide the minimum required UI elements and methods to work wit...
Definition: genericchatform.h:67
friend.h
FriendListWidget::onCompactChanged
void onCompactChanged(bool compact)
Widget::onAddClicked
void onAddClicked()
Definition: widget.cpp:863
Settings::separateWindowChanged
void separateWindowChanged(bool enabled)
Core::connected
void connected()
Widget::onFriendDialogShown
void onFriendDialogShown(const Friend *f)
Definition: widget.cpp:1815
Widget::ActiveToolMenuButton::AddButton
@ AddButton
Widget::copyFriendIdToClipboard
void copyFriendIdToClipboard(const ToxPk &friendId)
Definition: widget.cpp:1951
FilesForm
Definition: filesform.h:106
friendlist.h
Status::Status::Offline
@ Offline
GroupInvite::getType
uint8_t getType() const
Definition: groupinvite.cpp:47
Settings::getAutostartInTray
bool getAutostartInTray() const
Definition: settings.cpp:911
Widget::eventFlag
bool eventFlag
Definition: widget.h:328
FriendListWidget::updateActivityTime
void updateActivityTime(const QDateTime &date)
Definition: friendlistwidget.cpp:590
settings.h
FriendList::decideNickname
static QString decideNickname(const ToxPk &friendPk, const QString &origName)
Definition: friendlist.cpp:84
Settings::getWindowGeometry
QByteArray getWindowGeometry() const
Definition: settings.cpp:1520
CoreFile::fileTransferAccepted
void fileTransferAccepted(ToxFile file)
GenericChatroomWidget::isActive
bool isActive()
Definition: genericchatroomwidget.cpp:119
Widget::clearAllReceipts
void clearAllReceipts()
Definition: widget.cpp:2446
AddFriendForm::show
void show(ContentLayout *contentLayout)
Definition: addfriendform.cpp:149
Widget::onCallEnd
void onCallEnd()
Definition: widget.cpp:1090
Widget::groupChatLogs
QMap< GroupId, std::shared_ptr< IChatLog > > groupChatLogs
Definition: widget.h:361
CoreExt::extendedMessageSupport
void extendedMessageSupport(uint32_t friendId, bool supported)
Widget::onGroupPeerAudioPlaying
void onGroupPeerAudioPlaying(int groupnumber, ToxPk peerPk)
Definition: widget.cpp:2050
Core::acceptFriendRequest
void acceptFriendRequest(const ToxPk &friendPk)
Definition: core.cpp:1016
FriendListWidget::getMode
SortingMode getMode() const
Definition: friendlistwidget.cpp:343
Friend::onNegotiationComplete
void onNegotiationComplete()
Definition: friend.cpp:211
GroupInviteForm
This form contains all group invites you received.
Definition: groupinviteform.h:40
CroppingLabel::editFinished
void editFinished(const QString &newText)
Widget::friendWidgets
QMap< ToxPk, FriendWidget * > friendWidgets
Definition: widget.h:340
Widget::filterAllAction
QAction * filterAllAction
Definition: widget.h:298
Core::getSelfPublicKey
ToxPk getSelfPublicKey() const override
Gets self public key.
Definition: core.cpp:1271
Widget::onTryCreateTrayIcon
void onTryCreateTrayIcon()
Definition: widget.cpp:2289
contentdialogmanager.h
Widget::friendRequestsButton
QPushButton * friendRequestsButton
Definition: widget.h:331
Widget::notify
bool notify(QObject *receiver, QEvent *event)
Core::friendRequestReceived
void friendRequestReceived(const ToxPk &friendPk, const QString &message)
Settings::getMinimizeToTray
bool getMinimizeToTray() const
Definition: settings.cpp:989
Settings::nameColorsChanged
void nameColorsChanged(bool enabled)
Profile
Handles all qTox internal paths.
Definition: profile.h:42
FriendListWidget::itemsChanged
void itemsChanged()
Definition: friendlistwidget.cpp:558
GenericChatForm::focusInput
void focusInput()
Definition: genericchatform.cpp:480
GroupWidget::removeGroup
void removeGroup(const GroupId &groupId)
Widget::refreshPeerListsLocal
void refreshPeerListsLocal(const QString &username)
Definition: widget.cpp:2708
Widget::onFriendAliasChanged
void onFriendAliasChanged(const ToxPk &friendId, const QString &alias)
Definition: widget.cpp:1346
ActivateDialog::windowStateChanged
void windowStateChanged(Qt::WindowStates state)
SessionChatLog::onMessageSent
void onMessageSent(DispatchedMessageId id, const Message &message)
Inserts message data into the chatlog buffer.
Definition: sessionchatlog.cpp:397
group.h
Widget::icon_size
int icon_size
Definition: widget.h:334
Widget::saveSplitterGeometry
void saveSplitterGeometry()
Definition: widget.cpp:2394
GroupInvite
This class contains information needed to create a group invite.
Definition: groupinvite.h:26
Core::friendStatusMessageChanged
void friendStatusMessageChanged(uint32_t friendId, const QString &message)
Widget::autoAwayActive
bool autoAwayActive
Definition: widget.h:326
Settings::getAutoAwayTime
int getAutoAwayTime() const
Definition: settings.cpp:1254
ChatForm::incomingNotification
void incomingNotification(uint32_t friendId)
Widget::filterGroupsAction
QAction * filterGroupsAction
Definition: widget.h:302
Status::Status::Busy
@ Busy
Widget::dispatchFile
void dispatchFile(ToxFile file)
Dispatches file to the appropriate chatlog and accepts the transfer if necessary.
Definition: widget.cpp:1106
Widget::createContentDialog
ContentDialog * createContentDialog() const
Definition: widget.cpp:1842
Friend::setStatus
void setStatus(Status::Status s)
Definition: friend.cpp:156
Widget::instance
static Widget * instance
Definition: widget.h:321
FriendWidget::onContextMenuCalled
void onContextMenuCalled(QContextMenuEvent *event)
FriendWidget::onContextMenuCalled.
Definition: friendwidget.cpp:96
Widget::FilterCriteria::Groups
@ Groups
Widget::prepareIcon
static QIcon prepareIcon(QString path, int w=0, int h=0)
Definition: widget.cpp:2484
NotificationGenerator::onNotificationActivated
void onNotificationActivated()
Definition: notificationgenerator.cpp:266
Settings::getShowWindow
bool getShowWindow() const override
Definition: settings.cpp:1572
Widget::updateFriendActivity
void updateFriendActivity(const Friend &frnd)
Definition: widget.cpp:1735
HistMessageContentType::file
@ file
Widget::unreadGroupInvites
unsigned int unreadGroupInvites
Definition: widget.h:333
FriendWidget::onAvatarRemoved
void onAvatarRemoved(const ToxPk &friendPk)
Definition: friendwidget.cpp:420
chathistory.h
GenericChatroomWidget::setStatusMsg
void setStatusMsg(const QString &status)
Definition: genericchatroomwidget.cpp:139
contentdialog.h
RemoveFriendDialog::accepted
bool accepted()
Definition: removefrienddialog.h:39
ContentDialog::removeGroup
void removeGroup(const GroupId &groupId) override
Definition: contentdialog.cpp:223
MessageMetadata
Definition: message.h:43
Widget::filterOffline
static bool filterOffline(FilterCriteria index)
Definition: widget.cpp:2424
Widget::eventFilter
bool eventFilter(QObject *obj, QEvent *event) final
Definition: widget.cpp:504
GroupInviteForm::groupInviteAccepted
void groupInviteAccepted(const GroupInvite &inviteInfo)
Widget::confirmExecutableOpen
static void confirmExecutableOpen(const QFileInfo &file)
Definition: widget.cpp:911
AddFriendForm::isShown
bool isShown() const
Definition: addfriendform.cpp:139
Group::regeneratePeerList
void regeneratePeerList()
Definition: group.cpp:82
Widget::Widget
Widget(Profile &_profile, IAudioControl &audio, QWidget *parent=nullptr)
Definition: widget.cpp:140
Translator::translate
static void translate(const QString &localeName)
Loads the translations according to the settings or locale.
Definition: translator.cpp:39
Widget::addFriendForm
AddFriendForm * addFriendForm
Definition: widget.h:312
Translator::unregister
static void unregister(void *owner)
Unregisters all handlers of an owner.
Definition: translator.cpp:103
UpdateCheck::updateAvailable
void updateAvailable(QString latestVersion, QUrl link)
GenericChatForm::setColorizedNames
void setColorizedNames(bool enable)
Definition: genericchatform.cpp:495
Widget::contentLayout
ContentLayout * contentLayout
Definition: widget.h:311
Widget::ActiveToolMenuButton::SettingButton
@ SettingButton
Widget::addFriend
void addFriend(uint32_t friendId, const ToxPk &friendPk)
Definition: widget.cpp:1165
Widget::groupChatForms
QMap< GroupId, QSharedPointer< GroupChatForm > > groupChatForms
Definition: widget.h:363
Widget::onStatusSet
void onStatusSet(Status::Status status)
Definition: widget.cpp:770
Widget::dispatchFileWithBool
void dispatchFileWithBool(ToxFile file, bool)
Definition: widget.cpp:1141
Widget::onFriendRequestReceived
void onFriendRequestReceived(const ToxPk &friendPk, const QString &message)
Definition: widget.cpp:1717
FriendListWidget::setMode
void setMode(SortingMode mode)
Definition: friendlistwidget.cpp:133
Widget::profileInfo
ProfileInfo * profileInfo
Definition: widget.h:315
AddFriendForm::friendRequestAccepted
void friendRequestAccepted(const ToxPk &friendAddress)
RemoveFriendDialog
Definition: removefrienddialog.h:28
Widget::contactListWidget
FriendListWidget * contactListWidget
Definition: widget.h:323
Settings::getDontGroupWindows
bool getDontGroupWindows() const
Definition: settings.cpp:1979
Widget::FilterCriteria::Friends
@ Friends
History::removeFriendHistory
void removeFriendHistory(const ToxPk &friendPk)
Erases the chat history with one friend.
Definition: history.cpp:792
Profile::loadAvatar
QPixmap loadAvatar()
Get our avatar from cache.
Definition: profile.cpp:556
MaskablePixmapWidget::setPixmap
void setPixmap(const QPixmap &pmap)
Definition: maskablepixmapwidget.cpp:54
Widget::DialogType::ProfileDialog
@ ProfileDialog
Settings::setFriendAlias
void setFriendAlias(const ToxPk &id, const QString &alias) override
Definition: settings.cpp:1887
GroupWidget::updateStatusLight
void updateStatusLight() final
Definition: groupwidget.cpp:169
Status::getIconPath
QString getIconPath(Status status, bool event)
Definition: status.cpp:72
Widget::onExtReceiptReceived
void onExtReceiptReceived(uint32_t friendNumber, uint64_t receiptId)
Definition: widget.cpp:1459
SystemMessageType::messageSendFailed
@ messageSendFailed
Widget::wasMaximized
bool wasMaximized
Definition: widget.h:330
FriendListWidget::searchChatrooms
void searchChatrooms(const QString &searchString, bool hideOnline=false, bool hideOffline=false, bool hideGroups=false)
Definition: friendlistwidget.cpp:409
Settings::getNotify
bool getNotify() const override
Definition: settings.cpp:1559
Widget::onFileReceiveRequested
void onFileReceiveRequested(const ToxFile &file)
Definition: widget.cpp:1729
GroupChatForm
Definition: groupchatform.h:39
QList
Definition: friendlist.h:25
Widget::audio
IAudioControl & audio
Definition: widget.h:336
GroupChatroom
Definition: groupchatroom.h:31
ContentDialogManager::getInstance
static ContentDialogManager * getInstance()
Definition: contentdialogmanager.cpp:174
Widget::onGroupJoined
void onGroupJoined(int groupNum, const GroupId &groupId)
Definition: widget.cpp:2209
Widget::reloadTheme
void reloadTheme()
Definition: widget.cpp:2454
Core::groupJoined
void groupJoined(int groupnumber, GroupId groupId)
Widget::onGroupDialogShown
void onGroupDialogShown(Group *g)
Definition: widget.cpp:1820
Style::getImagePath
static const QString getImagePath(const QString &filename)
Definition: style.cpp:182
FriendList::addFriend
static Friend * addFriend(uint32_t friendId, const ToxPk &friendPk)
Definition: friendlist.cpp:32
Widget::filterMenu
QMenu * filterMenu
Definition: widget.h:295
AddFriendForm::friendRequestsSeen
void friendRequestsSeen()
Widget::setStatusMessage
void setStatusMessage(const QString &statusMessage)
Definition: widget.cpp:1033
Widget::actionShow
QAction * actionShow
Definition: widget.h:293
ContentDialogManager::current
ContentDialog * current()
Definition: contentdialogmanager.cpp:46
Widget::nextContact
void nextContact()
Definition: widget.cpp:2473
GUI::askQuestion
static bool askQuestion(const QString &title, const QString &msg, bool defaultAns=false, bool warning=true, bool yesno=true)
Asks the user a question with Ok/Cancel or Yes/No buttons.
Definition: gui.cpp:169
Core::friendMessageReceived
void friendMessageReceived(uint32_t friendId, const QString &message, bool isAction)
Core::failedToAddFriend
void failedToAddFriend(const ToxPk &friendPk, const QString &errorInfo=QString())
ProfileForm
Definition: profileform.h:51
GroupList::id2Key
static const GroupId & id2Key(uint32_t groupNum)
Definition: grouplist.cpp:51
GenericChatroomWidget::setAsInactiveChatroom
virtual void setAsInactiveChatroom()=0
Core::getCoreFile
CoreFile * getCoreFile() const
Definition: core.cpp:718
Settings::getShowSystemTray
bool getShowSystemTray() const
Definition: settings.cpp:930
Widget::friendListContextMenu
void friendListContextMenu(const QPoint &pos)
Definition: widget.cpp:2576
Widget::changeEvent
void changeEvent(QEvent *event) final
Definition: widget.cpp:668
Style::setThemeColor
static void setThemeColor(int color)
Definition: style.cpp:333
Widget::negotiateTimers
std::map< ToxPk, std::unique_ptr< QTimer > > negotiateTimers
Definition: widget.h:351
circlewidget.h
ContentDialogManager::getFriendDialog
ContentDialog * getFriendDialog(const ToxPk &friendPk) const
Definition: contentdialogmanager.cpp:164
Widget::friendMessageDispatchers
QMap< ToxPk, std::shared_ptr< FriendMessageDispatcher > > friendMessageDispatchers
Definition: widget.h:342
Widget::friendRequested
void friendRequested(const ToxId &friendAddress, const QString &message)
Widget::statusAway
QAction * statusAway
Definition: widget.h:289
Widget::onEmptyGroupCreated
void onEmptyGroupCreated(uint32_t groupnumber, const GroupId &groupId, const QString &title)
Definition: widget.cpp:2193
IMessageDispatcher::messageSent
void messageSent(DispatchedMessageId id, const Message &message)
Emitted when a message is processed and sent.
Widget::onDialogShown
void onDialogShown(GenericChatroomWidget *widget)
Definition: widget.cpp:1806
CoreAV::cancelCall
bool cancelCall(uint32_t friendNum)
Definition: coreav.cpp:299
Widget::previousContact
void previousContact()
Definition: widget.cpp:2478
Widget::friendAlertConnections
QMap< ToxPk, QMetaObject::Connection > friendAlertConnections
Definition: widget.h:347
Widget::setActiveToolMenuButton
void setActiveToolMenuButton(ActiveToolMenuButton newActiveButton)
Definition: widget.cpp:2637
GroupInviteForm::isShown
bool isShown() const
Detects that form is shown.
Definition: groupinviteform.cpp:91
GroupInviteForm::show
void show(ContentLayout *contentLayout)
Shows the form.
Definition: groupinviteform.cpp:104
Widget::toggleFullscreen
void toggleFullscreen()
Definition: widget.cpp:1826
DesktopNotify::notificationClosed
void notificationClosed()
Widget::profileForm
ProfileForm * profileForm
Definition: widget.h:316
AddFriendForm::friendRequested
void friendRequested(const ToxId &friendAddress, const QString &message)
Core::groupPeerAudioPlaying
void groupPeerAudioPlaying(int groupnumber, ToxPk peerPk)
Group::setEventFlag
void setEventFlag(bool f) override
Definition: group.cpp:164
ContentDialogManager::addFriendToDialog
FriendWidget * addFriendToDialog(ContentDialog *dialog, std::shared_ptr< FriendChatroom > chatroom, GenericChatForm *form)
Definition: contentdialogmanager.cpp:61
Widget::filterOfflineAction
QAction * filterOfflineAction
Definition: widget.h:300
Group::getId
uint32_t getId() const override
Definition: group.cpp:140
Settings::getDialogSettingsGeometry
QByteArray getDialogSettingsGeometry() const
Definition: settings.cpp:1637
GUI::setWindowTitle
static void setWindowTitle(const QString &title)
Change the title of the main window.
Definition: gui.cpp:85
Core::getAv
const CoreAV * getAv() const
Definition: core.cpp:703
Status::Status::Online
@ Online
Widget::titleChangedByUser
void titleChangedByUser(const QString &title)
Definition: widget.cpp:2043
Widget::onSplitterMoved
void onSplitterMoved(int pos, int index)
Definition: widget.cpp:2401
FriendList::findFriend
static Friend * findFriend(const ToxPk &friendPk)
Definition: friendlist.cpp:47
Widget::filterGroup
QActionGroup * filterGroup
Definition: widget.h:297
GroupInviteForm::groupCreate
void groupCreate(uint8_t type)
Widget::resizeEvent
void resizeEvent(QResizeEvent *event) final
Definition: widget.cpp:677
Settings::getAutoAcceptDir
QString getAutoAcceptDir(const ToxPk &id) const override
Definition: settings.cpp:1276
Profile::getCore
Core & getCore() const
Definition: profile.cpp:428
Settings::getUnreadFriendRequests
unsigned int getUnreadFriendRequests() const
Definition: settings.cpp:2087
CoreExt::extendedMessageReceived
void extendedMessageReceived(uint32_t friendId, const QString &message)
Widget::onFriendExtMessageReceived
void onFriendExtMessageReceived(uint32_t friendNumber, const QString &message)
Definition: widget.cpp:1453
Widget::connectCircleWidget
void connectCircleWidget(CircleWidget &circleWidget)
Definition: widget.cpp:2715
FriendList::getAllFriends
static QList< Friend * > getAllFriends()
Definition: friendlist.cpp:79
Widget::groupChatrooms
QMap< GroupId, std::shared_ptr< GroupChatroom > > groupChatrooms
Definition: widget.h:362
Widget::resetIcon
void resetIcon()
Used to reset the blinking icon.
Definition: widget.cpp:2217
Settings::setDialogSettingsGeometry
void setDialogSettingsGeometry(const QByteArray &value)
Definition: settings.cpp:1643
Widget::core
Core * core
Definition: widget.h:364
Core::changeGroupTitle
void changeGroupTitle(int groupId, const QString &title)
Definition: core.cpp:1166
GUI::getInstance
static GUI & getInstance()
Returns the singleton instance.
Definition: gui.cpp:56
SystemMessageType::fileSendFailed
@ fileSendFailed
Widget::onFriendStatusMessageChanged
void onFriendStatusMessageChanged(int friendId, const QString &message)
Definition: widget.cpp:1299
SettingsWidget
Definition: settingswidget.h:42
Core::friendAdded
void friendAdded(uint32_t friendId, const ToxPk &friendPk)
Core::groupMessageReceived
void groupMessageReceived(int groupnumber, int peernumber, const QString &message, bool isAction)
coreav.h
ChatForm::clearChatArea
void clearChatArea()
Definition: chatform.cpp:569
Widget::eventIcon
bool eventIcon
Definition: widget.h:329
Widget::settings
Settings & settings
Definition: widget.h:338
ToxFile::RECEIVING
@ RECEIVING
Definition: toxfile.h:51
Widget::onEventIconTick
void onEventIconTick()
Definition: widget.cpp:2281
chatform.h
Settings::getSplitterState
QByteArray getSplitterState() const
Definition: settings.cpp:1598
Widget::removeFriend
void removeFriend(const ToxPk &friendId)
Definition: widget.cpp:1801
Settings::setWindowGeometry
void setWindowGeometry(const QByteArray &value)
Definition: settings.cpp:1526
ContentDialog::reorderLayouts
void reorderLayouts(bool newGroupOnTop)
Update layouts order according to settings.
Definition: contentdialog.cpp:402
Widget::onCoreFriendStatusChanged
void onCoreFriendStatusChanged(int friendId, Status::Status status)
Definition: widget.cpp:1254
Widget::ActiveToolMenuButton
ActiveToolMenuButton
Definition: widget.h:92
MaskablePixmapWidget::setClickable
void setClickable(bool clickable)
Definition: maskablepixmapwidget.cpp:43
Friend::getStatus
Status::Status getStatus() const
Definition: friend.cpp:190
Widget::filterDisplayGroup
QActionGroup * filterDisplayGroup
Definition: widget.h:304
Core::receiptRecieved
void receiptRecieved(int friedId, ReceiptNum receipt)
Widget::statusSet
void statusSet(Status::Status status)
ContentDialogManager::focusContact
void focusContact(const ContactId &contactId)
Definition: contentdialogmanager.cpp:93
CoreFile::fileTransferPaused
void fileTransferPaused(ToxFile file)
Widget::onSetShowSystemTray
void onSetShowSystemTray(bool newValue)
Definition: widget.cpp:2381
Settings::getEnableGroupChatsColor
bool getEnableGroupChatsColor() const
Definition: settings.cpp:2173
Widget::DialogType::SettingDialog
@ SettingDialog
ContentDialogManager::contactWidgetExists
bool contactWidgetExists(const ContactId &groupId)
Definition: contentdialogmanager.cpp:51
ContentDialog::friendDialogShown
void friendDialogShown(const Friend *f)
Widget::onShowSettings
void onShowSettings()
Definition: widget.cpp:966
Core::getSelfId
ToxId getSelfId() const override
Returns our Tox ID.
Definition: core.cpp:1258
Widget::friendRequestsUpdate
void friendRequestsUpdate()
Definition: widget.cpp:2590
Core::getUsername
QString getUsername() const override
Returns our username, or an empty string on failure.
Definition: core.cpp:1217
Widget::focusChatInput
void focusChatInput()
Definition: widget.cpp:2697
CoreAV::invalidateGroupCallPeerSource
void invalidateGroupCallPeerSource(const Group &group, ToxPk peerPk)
Called from core to make sure the source for that peer is invalidated when they leave.
Definition: coreav.cpp:511
offlinemsgengine.h
ContentDialog::setUsername
void setUsername(const QString &newName)
Update username to show in the title.
Definition: contentdialog.cpp:432
Widget::profile
Profile & profile
Definition: widget.h:285
ContentDialog
Definition: contentdialog.h:49
Core::emptyGroupCreated
void emptyGroupCreated(int groupnumber, const GroupId groupId, const QString &title=QString())
FriendWidget::updateFriendActivity
void updateFriendActivity(Friend &frnd)
Widget::onGroupMessageReceived
void onGroupMessageReceived(int groupnumber, int peernumber, const QString &message, bool isAction)
Definition: widget.cpp:1999
Widget::setStatusBusy
void setStatusBusy()
Definition: widget.cpp:2351
updatecheck.h
Widget::cycleContacts
void cycleContacts(bool forward)
Definition: widget.cpp:2408
Settings::getGlobalAutoAcceptDir
QString getGlobalAutoAcceptDir() const
Definition: settings.cpp:1394
ContentLayout::mainHead
QWidget * mainHead
Definition: contentlayout.h:37
Core::getGroupPeerPk
ToxPk getGroupPeerPk(int groupId, int peerId) const override
Get the public key of a peer of a group.
Definition: core.cpp:1540
NotificationGenerator
Definition: notificationgenerator.h:33
Widget::filterOnlineAction
QAction * filterOnlineAction
Definition: widget.h:299
FriendWidget::removeFriend
void removeFriend(const ToxPk &friendPk)
groupchatform.h
Friend::aliasChanged
void aliasChanged(const ToxPk &friendId, QString alias)
Core::getMaxMessageSize
uint64_t getMaxMessageSize() const
Definition: core.cpp:1758
HistMessageContentType::message
@ message
grouplist.h
Widget::onCoreChanged
void onCoreChanged(Core &core)
Definition: widget.cpp:693
IMessageDispatcher::messageComplete
void messageComplete(DispatchedMessageId id)
Emitted when a receiver report is received from the associated chat.
FriendListWidget::removeFriendWidget
void removeFriendWidget(FriendWidget *w)
Definition: friendlistwidget.cpp:369
Profile::friendAvatarRemoved
void friendAvatarRemoved(const ToxPk &friendPk)
filetransferwidget.h
Widget::onBadProxyCore
void onBadProxyCore()
Definition: widget.cpp:757
Widget::onUpdateAvailable
void onUpdateAvailable()
Definition: widget.cpp:1835
CategoryWidget::search
void search(const QString &searchString, bool updateAll=false, bool hideOnline=false, bool hideOffline=false)
Definition: categorywidget.cpp:157
MaskablePixmapWidget
Definition: maskablepixmapwidget.h:24
Widget::onExtendedMessageSupport
void onExtendedMessageSupport(uint32_t friendNumber, bool supported)
Definition: widget.cpp:1442
timer.h
Settings::getGroupchatPosition
bool getGroupchatPosition() const
Definition: settings.cpp:1992
Settings::getBusySound
bool getBusySound() const override
Definition: settings.cpp:1080
Settings::getSeparateWindow
bool getSeparateWindow() const
Definition: settings.cpp:1966
Widget::showProfile
void showProfile()
Definition: widget.cpp:982
ChatForm::endCallNotification
void endCallNotification()
Group::setSelfName
void setSelfName(const QString &name)
Definition: group.cpp:195
ToxPk
This class represents a Tox Public Key, which is a part of Tox ID.
Definition: toxpk.h:26
Settings::setSplitterState
void setSplitterState(const QByteArray &value)
Definition: settings.cpp:1604
MessageProcessor::SharedParams
Definition: message.h:70
FriendListWidget::cycleContacts
void cycleContacts(GenericChatroomWidget *activeChatroomWidget, bool forward)
Definition: friendlistwidget.cpp:439
Friend
Definition: friend.h:31
Friend::setEventFlag
void setEventFlag(bool f) override
Definition: friend.cpp:146
Widget::groupWidgets
QMap< GroupId, GroupWidget * > groupWidgets
Definition: widget.h:353
AddFriendForm
Definition: addfriendform.h:37
Friend::setExtendedMessageSupport
void setExtendedMessageSupport(bool supported)
Definition: friend.cpp:195
CoreFile::fileReceiveRequested
void fileReceiveRequested(ToxFile file)
CoreFile::fileTransferInfo
void fileTransferInfo(ToxFile file)
Widget::newFriendMessageAlert
bool newFriendMessageAlert(const ToxPk &friendId, const QString &text, bool sound=true, QString filename=QString(), size_t filesize=0)
Definition: widget.cpp:1566
widget.h
ToxFile::INITIALIZING
@ INITIALIZING
Definition: toxfile.h:38
FilesForm::onFileUpdated
void onFileUpdated(const ToxFile &file)
Definition: filesform.cpp:492
Widget::icon
std::unique_ptr< QSystemTrayIcon > icon
Definition: widget.h:286
Widget::filterDisplayActivity
QAction * filterDisplayActivity
Definition: widget.h:306
Widget::moveEvent
void moveEvent(QMoveEvent *event) final
Definition: widget.cpp:642
ChatForm::rejectCall
void rejectCall(uint32_t friendId)
AddFriendForm::addFriendRequest
bool addFriendRequest(const QString &friendAddress, const QString &message)
Definition: addfriendform.cpp:181
Widget::ui
Ui::MainWindow * ui
Definition: widget.h:308
FriendListWidget::removeGroupWidget
void removeGroupWidget(GroupWidget *w)
Definition: friendlistwidget.cpp:364
FriendWidget::copyFriendIdToClipboard
void copyFriendIdToClipboard(const ToxPk &friendPk)
Widget::forceShow
void forceShow()
Definition: widget.cpp:856
Widget::newGroupMessageAlert
bool newGroupMessageAlert(const GroupId &groupId, const ToxPk &authorPk, const QString &message, bool notify)
Definition: widget.cpp:1622
GenericChatroomWidget::newWindowOpened
void newWindowOpened(GenericChatroomWidget *widget)
FriendListWidget::addGroupWidget
void addGroupWidget(GroupWidget *widget)
Definition: friendlistwidget.cpp:348
Widget::FilterCriteria::All
@ All
Friend::setStatusMessage
void setStatusMessage(const QString &message)
Definition: friend.cpp:93
Widget::removeGroup
void removeGroup(const GroupId &groupId)
Definition: widget.cpp:2102
groupinvite.h
Widget::groupInviteForm
GroupInviteForm * groupInviteForm
Definition: widget.h:313
maskablepixmapwidget.h
Widget::statusOnline
QAction * statusOnline
Definition: widget.h:288
Widget::onGroupPeerlistChanged
void onGroupPeerlistChanged(uint32_t groupnumber)
Definition: widget.cpp:2010
Widget::onFriendTypingChanged
void onFriendTypingChanged(uint32_t friendnumber, bool isTyping)
Definition: widget.cpp:2370
Group::setTitle
void setTitle(const QString &author, const QString &newTitle)
Definition: group.cpp:62
FilesForm::show
void show(ContentLayout *contentLayout)
Definition: filesform.cpp:484
Widget::windowStateChanged
void windowStateChanged(Qt::WindowStates states)
Widget::onDisconnected
void onDisconnected()
Definition: widget.cpp:741
ContentDialog::addFriendDialog
void addFriendDialog(Friend *frnd, ContentDialog *contentDialog)
Widget::actionQuit
QAction * actionQuit
Definition: widget.h:292
CoreFile::fileTransferCancelled
void fileTransferCancelled(ToxFile file)
CoreFile::fileTransferBrokenUnbroken
void fileTransferBrokenUnbroken(ToxFile file, bool broken)
GUI::themeReload
void themeReload()
FriendListWidget::addFriendWidget
void addFriendWidget(FriendWidget *w)
Definition: friendlistwidget.cpp:359
Status::Status::Away
@ Away
ToxFile::SENDING
@ SENDING
Definition: toxfile.h:50
ContentDialogManager::isContactActive
bool isContactActive(const ContactId &contactId)
Definition: contentdialogmanager.cpp:154
Widget::addFriendFailed
void addFriendFailed(const ToxPk &userId, const QString &errorInfo=QString())
Definition: widget.cpp:1244
friendlistwidget.h
Settings::getFriendActivity
QDateTime getFriendActivity(const ToxPk &id) const override
Definition: settings.cpp:1911
Widget::openNewDialog
void openNewDialog(GenericChatroomWidget *widget)
Definition: widget.cpp:1357
Widget::getFilterCriteria
FilterCriteria getFilterCriteria() const
Definition: widget.cpp:2545
filesform.h
Widget::openDialog
void openDialog(GenericChatroomWidget *widget, bool newWindow)
Definition: widget.cpp:1362
Settings::setFriendActivity
void setFriendActivity(const ToxPk &id, const QDateTime &date) override
Definition: settings.cpp:1921
Widget::acceptFileTransfer
void acceptFileTransfer(const ToxFile &file, const QString &path)
Definition: widget.cpp:112
ContentDialogManager::getGroupDialog
ContentDialog * getGroupDialog(const GroupId &friendPk) const
Definition: contentdialogmanager.cpp:169
Widget::filterFriendsAction
QAction * filterFriendsAction
Definition: widget.h:301
Group::getPersistentId
const GroupId & getPersistentId() const override
Definition: group.cpp:145
ContentDialog::connectFriendWidget
void connectFriendWidget(FriendWidget &friendWidget)
Core::usernameSet
void usernameSet(const QString &username)
Settings::getAutoGroupInvite
bool getAutoGroupInvite(const ToxPk &id) const override
Definition: settings.cpp:1334
GenericChatroomWidget::middleMouseClicked
void middleMouseClicked()
ChatForm::outgoingNotification
void outgoingNotification()
FriendListWidget
Definition: friendlistwidget.h:42
Widget::settingsWidget
QPointer< SettingsWidget > settingsWidget
Definition: widget.h:318
GroupList::removeGroup
static void removeGroup(const GroupId &groupId, bool fake=false)
Definition: grouplist.cpp:56
Core::requestFriendship
void requestFriendship(const ToxId &friendAddress, const QString &message)
Definition: core.cpp:1059
Translator::registerHandler
static void registerHandler(const std::function< void()> &, void *owner)
Register a function to be called when the UI needs to be retranslated.
Definition: translator.cpp:93
Core::setStatus
void setStatus(Status::Status status)
Definition: core.cpp:1347
GroupWidget
Definition: groupwidget.h:30
Widget::dispatchFileSendFailed
void dispatchFileSendFailed(uint32_t friendId, const QString &fileName)
Definition: widget.cpp:1146
GenericChatroomWidget::setAsActiveChatroom
virtual void setAsActiveChatroom()=0
Settings::getWindowState
QByteArray getWindowState() const
Definition: settings.cpp:1533
Widget::addFriendDialog
void addFriendDialog(const Friend *frnd, ContentDialog *dialog)
Definition: widget.cpp:1465
Contact::displayedNameChanged
void displayedNameChanged(const QString &newName)
ICoreSettings::ProxyType::ptNone
@ ptNone
Settings::getInstance
static Settings & getInstance()
Returns the singleton instance.
Definition: settings.cpp:88
Core::disconnected
void disconnected()
Widget::newMessageAlert
bool newMessageAlert(QWidget *currentWindow, bool isActive, bool sound=true, bool notify=true)
Definition: widget.cpp:1680
Widget::friendChatrooms
QMap< ToxPk, std::shared_ptr< FriendChatroom > > friendChatrooms
Definition: widget.h:349
ProfileForm::onSelfAvatarLoaded
void onSelfAvatarLoaded(const QPixmap &pic)
Definition: profileform.cpp:274
Core::groupPeerlistChanged
void groupPeerlistChanged(int groupnumber)
Core::removeGroup
void removeGroup(int groupId)
Definition: core.cpp:1194
Profile::getHistory
History * getHistory()
Get chat history.
Definition: profile.cpp:785
Nexus
Definition: nexus.h:43
FriendWidget::updateStatusLight
void updateStatusLight() final
Definition: friendwidget.cpp:309
GroupId
This class represents a long term persistent group identifier.
Definition: groupid.h:26
Group
Definition: group.h:34
CoreFile::fileTransferRemotePausedUnpaused
void fileTransferRemotePausedUnpaused(ToxFile file, bool paused)
Widget::onGroupClicked
void onGroupClicked()
Definition: widget.cpp:879
Widget::sharedMessageProcessorParams
std::unique_ptr< MessageProcessor::SharedParams > sharedMessageProcessorParams
Definition: widget.h:367
Widget::onReceiptReceived
void onReceiptReceived(int friendId, ReceiptNum receipt)
Definition: widget.cpp:1431
Widget::onStopNotification
void onStopNotification()
Widget::onStopNotification Stop the notification sound.
Definition: widget.cpp:1098
Widget::onGroupPeerNameChanged
void onGroupPeerNameChanged(uint32_t groupnumber, const ToxPk &peerPk, const QString &newName)
Definition: widget.cpp:2018
Widget::setStatusOnline
void setStatusOnline()
Definition: widget.cpp:2333
FriendList::clear
static void clear()
Definition: friendlist.cpp:72
Core::statusMessageSet
void statusMessageSet(const QString &message)
Settings::getNotifySound
bool getNotifySound() const override
Definition: settings.cpp:1054
Widget::onGroupTitleChanged
void onGroupTitleChanged(uint32_t groupnumber, const QString &author, const QString &title)
Definition: widget.cpp:2028
corefile.h
Widget::audioNotification
std::unique_ptr< IAudioSink > audioNotification
Definition: widget.h:337
Settings::groupchatPositionChanged
void groupchatPositionChanged(bool enabled)
Widget::setUsername
void setUsername(const QString &username)
Definition: widget.cpp:1013
Widget::statusBusy
QAction * statusBusy
Definition: widget.h:290
Widget::DialogType
DialogType
Definition: widget.h:101
Widget::filterGroups
static bool filterGroups(FilterCriteria index)
Definition: widget.cpp:2413
Widget::setStatusAway
void setStatusAway()
Definition: widget.cpp:2342
Settings::getThemeColor
int getThemeColor() const
Definition: settings.cpp:2140
ContentDialog::groupDialogShown
void groupDialogShown(Group *g)
ChatForm::updateFriendActivity
void updateFriendActivity(Friend &frnd)
Nexus::getDesktopGUI
static Widget * getDesktopGUI()
Get desktop GUI widget.
Definition: nexus.cpp:340
Settings::showSystemTrayChanged
void showSystemTrayChanged(bool enabled)
Settings::getCloseToTray
bool getCloseToTray() const
Definition: settings.cpp:976
Widget::trayMenu
QMenu * trayMenu
Definition: widget.h:287
Settings::getGroupAlwaysNotify
bool getGroupAlwaysNotify() const override
Definition: settings.cpp:1093
GenericChatroomWidget::chatroomWidgetClicked
void chatroomWidgetClicked(GenericChatroomWidget *widget)
contentlayout.h
Friend::getPublicKey
const ToxPk & getPublicKey() const
Definition: friend.cpp:131
GroupList::clear
static void clear()
Definition: grouplist.cpp:74
FriendWidget::contextMenuCalled
void contextMenuCalled(QContextMenuEvent *event)
Widget::onGroupSendFailed
void onGroupSendFailed(uint32_t groupnumber)
Definition: widget.cpp:2360
Core::createGroup
int createGroup(uint8_t type=TOX_CONFERENCE_TYPE_AV)
Definition: core.cpp:1659
Widget::friendChatLogs
QMap< ToxPk, std::shared_ptr< ChatHistory > > friendChatLogs
Definition: widget.h:348
settingswidget.h
Style::getStylesheet
static const QString getStylesheet(const QString &filename, const QFont &baseFont=QFont())
Definition: style.cpp:165
ChatForm::stopNotification
void stopNotification()
Widget::onGroupInviteReceived
void onGroupInviteReceived(const GroupInvite &inviteInfo)
Definition: widget.cpp:1960
Widget::FilterCriteria
FilterCriteria
Definition: widget.h:110
Widget::DialogType::AddDialog
@ AddDialog
Widget::changeDisplayMode
void changeDisplayMode()
Definition: widget.cpp:2521
Widget::profilePicture
MaskablePixmapWidget * profilePicture
Definition: widget.h:324
ContentDialog::removeFriend
void removeFriend(const ToxPk &friendPk) override
Definition: contentdialog.cpp:194
Settings::FriendListSortingMode::Activity
@ Activity
CoreFile::fileSendStarted
void fileSendStarted(ToxFile file)
Widget::timer
QTimer * timer
Definition: widget.h:327
Widget::onConnected
void onConnected()
Definition: widget.cpp:735
GroupInvite::getFriendId
uint32_t getFriendId() const
Definition: groupinvite.cpp:42
Widget::onGroupInviteAccepted
void onGroupInviteAccepted(const GroupInvite &inviteInfo)
Definition: widget.cpp:1990
GenericChatroomWidget::resetEventFlags
virtual void resetEventFlags()=0
Widget::activeChatroomWidget
GenericChatroomWidget * activeChatroomWidget
Definition: widget.h:322
Widget::retranslateUi
void retranslateUi()
Definition: widget.cpp:2649
ActivateDialog
Definition: activatedialog.h:24
friendchatroom.h
Widget::filterDisplayName
QAction * filterDisplayName
Definition: widget.h:305
GroupInviteForm::addGroupInvite
bool addGroupInvite(const GroupInvite &inviteInfo)
Adds group invite.
Definition: groupinviteform.cpp:117
Settings::getDesktopNotify
bool getDesktopNotify() const override
Definition: settings.cpp:1585
Widget::ActiveToolMenuButton::None
@ None
Widget::updateCheck
std::unique_ptr< UpdateCheck > updateCheck
Definition: widget.h:319
Status::Status::Negotiating
@ Negotiating
CoreFile::acceptFileRecvRequest
void acceptFileRecvRequest(uint32_t friendId, uint32_t fileId, QString path)
Definition: corefile.cpp:254
ContentDialogManager::addGroupToDialog
GroupWidget * addGroupToDialog(ContentDialog *dialog, std::shared_ptr< GroupChatroom > chatroom, GenericChatForm *form)
Definition: contentdialogmanager.cpp:77
IMessageDispatcher::messageReceived
void messageReceived(const ToxPk &sender, const Message &message)
Emitted when a message is received and processed.
Core::getExt
const CoreExt * getExt() const
Definition: core.cpp:733
Widget::cleanupNotificationSound
void cleanupNotificationSound()
Definition: widget.cpp:1070
Core::friendTypingChanged
void friendTypingChanged(uint32_t friendId, bool isTyping)
Widget::addGroupDialog
void addGroupDialog(Group *group, ContentDialog *dialog)
Definition: widget.cpp:1521
core.h
CircleWidget
Definition: circlewidget.h:27
Settings::savePersonal
void savePersonal()
Asynchronous, saves the current profile.
Definition: settings.cpp:717
Widget::onIconClick
void onIconClick(QSystemTrayIcon::ActivationReason)
Definition: widget.cpp:942
Widget::getUsername
QString getUsername()
Definition: widget.cpp:683
GroupList::findGroup
static Group * findGroup(const GroupId &groupId)
Definition: grouplist.cpp:42
Widget::createGroup
Group * createGroup(uint32_t groupnumber, const GroupId &groupId)
Definition: widget.cpp:2107
Widget::filesForm
FilesForm * filesForm
Definition: widget.h:320
Friend::setName
void setName(const QString &name) override
Friend::setName sets a new username for the friend.
Definition: friend.cpp:47
ContentLayout
Definition: contentlayout.h:25
Widget::onTransferClicked
void onTransferClicked()
Definition: widget.cpp:895
Widget::onChatroomWidgetClicked
void onChatroomWidgetClicked(GenericChatroomWidget *widget)
Definition: widget.cpp:1352
GroupList::getAllGroups
static QList< Group * > getAllGroups()
Definition: grouplist.cpp:64
ReceiptNum
NamedType< uint32_t, struct ReceiptNumTag, Orderable > ReceiptNum
Definition: receiptnum.h:27
ContentDialog::addGroupDialog
void addGroupDialog(Group *group, ContentDialog *contentDialog)
Widget::FilterCriteria::Offline
@ Offline
Settings::getFriendSortingMode
FriendListSortingMode getFriendSortingMode() const
Definition: settings.cpp:1953
ProfileForm::onLogoutClicked
void onLogoutClicked()
Definition: profileform.cpp:388
Settings::FriendListSortingMode::Name
@ Name
Widget::DialogType::GroupDialog
@ GroupDialog
ContactId::toString
QString toString() const
Converts the ContactId to a uppercase hex string.
Definition: contactid.cpp:78
Nexus::getInstance
static Nexus & getInstance()
Returns the singleton instance.
Definition: nexus.cpp:259
ContentDialogManager::addContentDialog
void addContentDialog(ContentDialog &dialog)
Definition: contentdialogmanager.cpp:183
Widget::connectFriendWidget
void connectFriendWidget(FriendWidget &friendWidget)
Definition: widget.cpp:2720
profileinfo.h
Core::getStatus
Status::Status getStatus() const
Returns our user status.
Definition: core.cpp:1320
CoreExt::extendedReceiptReceived
void extendedReceiptReceived(uint32_t friendId, uint64_t receiptId)
groupchatroom.h
MessageProcessor
Definition: message.h:62
Group::updateUsername
void updateUsername(ToxPk pk, const QString newName)
Definition: group.cpp:123
Core::getGroupAvEnabled
bool getGroupAvEnabled(int groupId) const override
Check, that group has audio or video stream.
Definition: core.cpp:1598
GroupList::addGroup
static Group * addGroup(Core &core, int groupId, const GroupId &persistentGroupId, const QString &name, bool isAvGroupchat, const QString &selfName)
Definition: grouplist.cpp:28
Widget::onStatusMessageChanged
void onStatusMessageChanged(const QString &newStatusMessage)
Definition: widget.cpp:1027
Friend::statusChanged
void statusChanged(const ToxPk &friendId, Status::Status status)
gui.h
Widget::closeEvent
void closeEvent(QCloseEvent *event) final
Definition: widget.cpp:652
Settings::compactLayoutChanged
void compactLayoutChanged(bool enabled)
CoreFile::fileTransferFinished
void fileTransferFinished(ToxFile file)
SessionChatLog::onMessageReceived
void onMessageReceived(const ToxPk &sender, const Message &message)
Inserts message data into the chatlog buffer.
Definition: sessionchatlog.cpp:381
Core::setStatusMessage
void setStatusMessage(const QString &message)
Definition: core.cpp:1327
Widget::actionLogout
QAction * actionLogout
Definition: widget.h:291
Core::friendStatusChanged
void friendStatusChanged(uint32_t friendId, Status::Status status)
ProfileForm::isShown
bool isShown() const
Definition: profileform.cpp:198
Widget::setWindowTitle
void setWindowTitle(const QString &title)
Definition: widget.cpp:844
Widget::searchContacts
void searchContacts()
Definition: widget.cpp:2510
SessionChatLog::onMessageComplete
void onMessageComplete(DispatchedMessageId id)
Marks the associated message as complete and notifies any listeners.
Definition: sessionchatlog.cpp:417
Widget::ActiveToolMenuButton::TransferButton
@ TransferButton
Widget::onFriendStatusChanged
void onFriendStatusChanged(const ToxPk &friendPk, Status::Status status)
Definition: widget.cpp:1281
Core::joinGroupchat
uint32_t joinGroupchat(const GroupInvite &inviteInfo)
Accept a groupchat invite.
Definition: core.cpp:1614
AddFriendForm::setMode
void setMode(Mode mode)
Definition: addfriendform.cpp:176
Widget::groupInvitesButton
QPushButton * groupInvitesButton
Definition: widget.h:332
Widget::init
void init()
Definition: widget.cpp:156
Core::groupSentFailed
void groupSentFailed(int groupId)
Widget::~Widget
~Widget() override
Definition: widget.cpp:590
Friend::getId
uint32_t getId() const override
Definition: friend.cpp:136
GenericChatroomWidget
Definition: genericchatroomwidget.h:32
Settings::setWindowState
void setWindowState(const QByteArray &value)
Definition: settings.cpp:1539
Core::removeFriend
void removeFriend(uint32_t friendId)
Definition: core.cpp:1179
FilesForm::isShown
bool isShown() const
Definition: filesform.cpp:474
ProfileInfo
Implement interface, that provides invormation about self profile. Also, provide methods to work with...
Definition: profileinfo.h:32
Status::getAssetSuffix
QString getAssetSuffix(Status status)
Definition: status.cpp:52
Status::isOnline
bool isOnline(Status status)
Definition: status.cpp:83
translator.h
CroppingLabel::clicked
void clicked()
Widget::DialogType::TransferDialog
@ TransferDialog
FriendListWidget::searchCircle
void searchCircle(CircleWidget &circleWidget)
FriendList::id2Key
static const ToxPk & id2Key(uint32_t friendId)
Definition: friendlist.cpp:57
Widget::showUpdateDownloadProgress
void showUpdateDownloadProgress()
Switches to the About settings page.
Definition: widget.cpp:636
Widget::outgoingNotification
void outgoingNotification()
Definition: widget.cpp:1084
Widget::onFriendUsernameChanged
void onFriendUsernameChanged(int friendId, const QString &username)
Definition: widget.cpp:1333
Widget::onFriendDisplayedNameChanged
void onFriendDisplayedNameChanged(const QString &displayed)
Definition: widget.cpp:1315
Widget::saveWindowGeometry
void saveWindowGeometry()
Definition: widget.cpp:2388
Core::getStatusMessage
QString getStatusMessage() const
Returns our status message, or an empty string on failure.
Definition: core.cpp:1302
removefrienddialog.h
ToxFile
Definition: toxfile.h:32
Widget::groupInvitesUpdate
void groupInvitesUpdate()
Definition: widget.cpp:2613
Settings::getAutoSaveEnabled
bool getAutoSaveEnabled() const
Definition: settings.cpp:963
Widget::groupInvitesClear
void groupInvitesClear()
Definition: widget.cpp:2631
Widget::groupAlertConnections
QMap< GroupId, QMetaObject::Connection > groupAlertConnections
Definition: widget.h:360
UpdateCheck
Definition: updatecheck.h:32
GroupInviteForm::groupInvitesSeen
void groupInvitesSeen()
ContentDialogManager::updateGroupStatus
void updateGroupStatus(const GroupId &friendPk)
Definition: contentdialogmanager.cpp:141
Core::friendUsernameChanged
void friendUsernameChanged(uint32_t friendId, const QString &username)
GenericChatroomWidget::updateStatusLight
virtual void updateStatusLight()=0
Widget::updateFilterText
void updateFilterText()
Definition: widget.cpp:2537
FriendListWidget::connectCircleWidget
void connectCircleWidget(CircleWidget &circleWidget)
SplitterRestorer
Restore splitter from saved state and reset to default.
Definition: splitterrestorer.h:26
CoreFile::fileSendFailed
void fileSendFailed(uint32_t friendId, const QString &fname)
splitterrestorer.h
Profile::selfAvatarChanged
void selfAvatarChanged(const QPixmap &pixmap)
groupwidget.h
friendwidget.h
CoreFile
Manages the file transfer service of toxcore.
Definition: corefile.h:46
nexus.h
Widget::onFailedToStartCore
void onFailedToStartCore()
Definition: widget.cpp:747
Widget::registerContentDialog
void registerContentDialog(ContentDialog &contentDialog) const
Definition: widget.cpp:1850
Friend::getUserName
QString getUserName() const
Definition: friend.cpp:126
Core::groupInviteReceived
void groupInviteReceived(const GroupInvite &inviteInfo)
Widget::groupMessageDispatchers
QMap< GroupId, std::shared_ptr< GroupMessageDispatcher > > groupMessageDispatchers
Definition: widget.h:354
ContentLayout::clear
void clear()
Definition: contentlayout.cpp:78
Widget::incomingNotification
void incomingNotification(uint32_t friendId)
Definition: widget.cpp:1075
Widget::groupsVisible
bool groupsVisible() const
Definition: widget.cpp:2570
CoreAV
Definition: coreav.h:47
Settings::getMaxAutoAcceptSize
size_t getMaxAutoAcceptSize() const
Definition: settings.cpp:1407
Widget::ActiveToolMenuButton::GroupButton
@ GroupButton
IMessageDispatcher::messageBroken
void messageBroken(DispatchedMessageId id, BrokenMessageReason reason)
Core::groupPeerNameChanged
void groupPeerNameChanged(int groupnumber, const ToxPk &peerPk, const QString &newName)
status.h
FriendWidget
Definition: friendwidget.h:33
Profile::friendAvatarSet
void friendAvatarSet(const ToxPk &friendPk, const QPixmap &pixmap)
CircleWidget::newContentDialog
void newContentDialog(ContentDialog &contentDialog)
GenericChatroomWidget::getFriend
virtual const Friend * getFriend() const
Definition: genericchatroomwidget.h:45
Widget::searchCircle
void searchCircle(CircleWidget &circleWidget)
Definition: widget.cpp:2561
groupinviteform.h
MaskablePixmapWidget::clicked
void clicked()
Widget::fromDialogType
static QString fromDialogType(DialogType type)
Definition: widget.cpp:1661
Group::titleChangedByUser
void titleChangedByUser(const QString &title)
Message
Definition: message.h:52
Widget::FilterCriteria::Online
@ Online
Widget::onSeparateWindowChanged
void onSeparateWindowChanged(bool separate, bool clicked)
Definition: widget.cpp:782
GenericChatroomWidget::getTitle
QString getTitle() const
Definition: genericchatroomwidget.cpp:149
Settings::getAudioOutDevEnabled
bool getAudioOutDevEnabled() const override
Definition: settings.cpp:1767
Core
Definition: core.h:59
Widget
Definition: widget.h:87
Widget::onFriendMessageReceived
void onFriendMessageReceived(uint32_t friendnumber, const QString &message, bool isAction)
Definition: widget.cpp:1420
FriendChatroom
Definition: friendchatroom.h:45
addfriendform.h
Widget::playNotificationSound
void playNotificationSound(IAudioSink::Sound sound, bool loop=false)
Plays a sound via the audioNotification AudioSink.
Definition: widget.cpp:1046
toxActivateEventHandler
bool toxActivateEventHandler(const QByteArray &)
Definition: widget.cpp:83
Settings::updateFriendAddress
void updateFriendAddress(const QString &newAddr)
Definition: settings.cpp:1869
Widget::onRejectCall
void onRejectCall(uint32_t friendId)
Definition: widget.cpp:1159
GenericChatroomWidget::getStatusMsg
QString getStatusMsg() const
Definition: genericchatroomwidget.cpp:144
Widget::chatForms
QMap< ToxPk, ChatForm * > chatForms
Definition: widget.h:350
Group::userLeft
void userLeft(const ToxPk &user, const QString &name)
RemoveFriendDialog::removeHistory
bool removeHistory()
Definition: removefrienddialog.h:34
Settings::getLightTrayIcon
bool getLightTrayIcon() const
Definition: settings.cpp:1002