From c684d31d02c7cd292848a96789625becda66d1e4 Mon Sep 17 00:00:00 2001 From: TheSpiritXIII Date: Mon, 22 Jun 2015 14:01:50 -0400 Subject: [PATCH] Multi-window: Alert window storing chat, add group widgets, update statuses and avatars --- src/group.cpp | 11 +- src/group.h | 5 + src/widget/contentdialog.cpp | 283 +++++++++++++++++++++++++-- src/widget/contentdialog.h | 38 +++- src/widget/form/chatform.cpp | 4 +- src/widget/friendwidget.cpp | 40 +++- src/widget/friendwidget.h | 4 +- src/widget/genericchatroomwidget.cpp | 10 + src/widget/genericchatroomwidget.h | 9 +- src/widget/groupwidget.cpp | 49 ++++- src/widget/groupwidget.h | 5 +- src/widget/widget.cpp | 158 +++++++++++---- src/widget/widget.h | 9 +- 13 files changed, 547 insertions(+), 78 deletions(-) diff --git a/src/group.cpp b/src/group.cpp index a9a9f68a1..893d08b32 100644 --- a/src/group.cpp +++ b/src/group.cpp @@ -84,6 +84,7 @@ void Group::updatePeer(int peerId, QString name) widget->onUserListChanged(); chatForm->onUserListChanged(); + emit userListChanged(getGroupWidget()); } void Group::setName(const QString& name) @@ -91,7 +92,14 @@ void Group::setName(const QString& name) chatForm->setName(name); if (widget->isActive()) - GUI::setWindowTitle(name); + GUI::setWindowTitle(name); + + emit titleChanged(this->getGroupWidget()); +} + +QString Group::getName() const +{ + return widget->getName(); } void Group::regeneratePeerList() @@ -117,6 +125,7 @@ void Group::regeneratePeerList() widget->onUserListChanged(); chatForm->onUserListChanged(); + emit userListChanged(getGroupWidget()); } bool Group::isAvGroupchat() const diff --git a/src/group.h b/src/group.h index 8ccde2497..8d029bf71 100644 --- a/src/group.h +++ b/src/group.h @@ -61,9 +61,14 @@ public: void updatePeer(int peerId, QString newName); void setName(const QString& name); + QString getName() const; QString resolveToxId(const ToxId &id) const; +signals: + void titleChanged(GroupWidget* widget); + void userListChanged(GroupWidget* widget); + private: GroupWidget* widget; GroupChatForm* chatForm; diff --git a/src/widget/contentdialog.cpp b/src/widget/contentdialog.cpp index 4ff894870..ac70759f1 100644 --- a/src/widget/contentdialog.cpp +++ b/src/widget/contentdialog.cpp @@ -20,16 +20,23 @@ #include "contentdialog.h" #include "contentlayout.h" #include "friendwidget.h" +#include "groupwidget.h" #include "style.h" +#include "widget.h" #include "tool/adjustingscrollarea.h" #include "src/persistence/settings.h" #include "src/friend.h" #include "src/friendlist.h" +#include "src/group.h" +#include "src/widget/form/chatform.h" +#include "src/core/core.h" #include #include +#include ContentDialog* ContentDialog::currentDialog = nullptr; QHash> ContentDialog::friendList; +QHash> ContentDialog::groupList; ContentDialog::ContentDialog(QWidget* parent) : QDialog(parent, Qt::Window) @@ -101,16 +108,66 @@ ContentDialog::~ContentDialog() } } -void ContentDialog::addFriend(int friendId, QString id) +FriendWidget* ContentDialog::addFriend(int friendId, QString id) { FriendWidget* friendWidget = new FriendWidget(friendId, id); friendLayout->insertWidget(friendLayout->count() - 1, friendWidget); - onChatroomWidgetClicked(friendWidget); + Friend* frnd = friendWidget->getFriend(); + onChatroomWidgetClicked(friendWidget, false); + + connect(frnd, &Friend::displayedNameChanged, this, &ContentDialog::updateFriendWidget); connect(friendWidget, &FriendWidget::chatroomWidgetClicked, this, &ContentDialog::onChatroomWidgetClicked); + connect(friendWidget, SIGNAL(chatroomWidgetClicked(GenericChatroomWidget*)), frnd->getChatForm(), SLOT(focusInput())); + connect(Core::getInstance(), &Core::friendAvatarChanged, friendWidget, &FriendWidget::onAvatarChange); + connect(Core::getInstance(), &Core::friendAvatarRemoved, friendWidget, &FriendWidget::onAvatarRemoved); friendList.insert(friendId, std::make_tuple(this, friendWidget)); + + return friendWidget; +} + +GroupWidget* ContentDialog::addGroup(int groupId, const QString& name) +{ + GroupWidget* groupWidget = new GroupWidget(groupId, name); + friendLayout->insertWidget(friendLayout->count() - 1, groupWidget); + + Group* group = groupWidget->getGroup(); + connect(group, &Group::titleChanged, this, &ContentDialog::updateGroupWidget); + connect(group, &Group::userListChanged, this, &ContentDialog::updateGroupWidget); + connect(groupWidget, &GroupWidget::chatroomWidgetClicked, this, &ContentDialog::onChatroomWidgetClicked); + + onChatroomWidgetClicked(groupWidget, false); + + groupList.insert(groupId, std::make_tuple(this, groupWidget)); + + return groupWidget; +} + +void ContentDialog::removeFriend(int friendId) +{ + remove(friendId, friendList); +} + +void ContentDialog::removeGroup(int groupId) +{ + remove(groupId, groupList); +} + +bool ContentDialog::hasFriendWidget(int friendId, GenericChatroomWidget* chatroomWidget) +{ + return hasWidget(friendId, chatroomWidget, friendList); +} + +bool ContentDialog::hasGroupWidget(int groupId, GenericChatroomWidget *chatroomWidget) +{ + return hasWidget(groupId, chatroomWidget, groupList); +} + +int ContentDialog::chatroomWidgetCount() const +{ + return friendLayout->count() - 1; // Don't include the stretch. } ContentDialog* ContentDialog::current() @@ -118,16 +175,81 @@ ContentDialog* ContentDialog::current() return currentDialog; } -bool ContentDialog::showChatroomWidget(int friendId) +bool ContentDialog::existsFriendWidget(int friendId, bool focus) { - auto widgetIt = friendList.find(friendId); - if (widgetIt == friendList.end()) - return false; + return existsWidget(friendId, focus, friendList); +} - std::get<0>(widgetIt.value())->activateWindow(); - std::get<0>(widgetIt.value())->onChatroomWidgetClicked(std::get<1>(widgetIt.value())); +bool ContentDialog::existsGroupWidget(int groupId, bool focus) +{ + return existsWidget(groupId, focus, groupList); +} - return true; +void ContentDialog::updateFriendStatus(int friendId) +{ + updateStatus(friendId, friendList); +} + +void ContentDialog::updateFriendStatusMessage(int friendId, const QString &message) +{ + auto iter = friendList.find(friendId); + + if (iter == friendList.end()) + return; + + std::get<1>(iter.value())->setStatusMsg(message); +} + +void ContentDialog::updateGroupStatus(int groupId) +{ + updateStatus(groupId, groupList); +} + +bool ContentDialog::isFriendWidgetActive(int friendId) +{ + return isWidgetActive(friendId, friendList); +} + +bool ContentDialog::isGroupWidgetActive(int groupId) +{ + return isWidgetActive(groupId, groupList); +} + +ContentDialog* ContentDialog::getFriendDialog(int friendId) +{ + return getDialog(friendId, friendList); +} + +ContentDialog* ContentDialog::getGroupDialog(int groupId) +{ + return getDialog(groupId, groupList); +} + +#include +#include +void ContentDialog::dragEnterEvent(QDragEnterEvent *event) +{ + if (event->mimeData()->hasFormat("friend")) + event->acceptProposedAction(); +} + +void ContentDialog::dropEvent(QDropEvent *event) +{ + if (event->mimeData()->hasFormat("friend")) + { + //int friendId = ev->mimeData()->data("friend").toInt(); + //Core::getInstance()->groupInviteFriend(friendId, groupId); + } +} + +void ContentDialog::changeEvent(QEvent *event) +{ + QWidget::changeEvent(event); + if (event->type() == QEvent::ActivationChange) + { + if (isActiveWindow()) + currentDialog = this; + } } void ContentDialog::resizeEvent(QResizeEvent* event) @@ -143,8 +265,27 @@ void ContentDialog::closeEvent(QCloseEvent* event) QWidget::closeEvent(event); } -void ContentDialog::onChatroomWidgetClicked(GenericChatroomWidget *widget) +void ContentDialog::onChatroomWidgetClicked(GenericChatroomWidget *widget, bool group) { + if (group) + { + ContentDialog* contentDialog = new ContentDialog(); + contentDialog->show(); + + if (widget->getFriend() != nullptr) + { + removeFriend(widget->getFriend()->getFriendID()); + Widget::getInstance()->addFriendDialog(widget->getFriend(), contentDialog); + } + else + { + removeGroup(widget->getGroup()->getGroupId()); + Widget::getInstance()->addGroupDialog(widget->getGroup(), contentDialog); + } + + return; + } + contentLayout->clear(); if (activeChatroomWidget != nullptr) @@ -153,14 +294,29 @@ void ContentDialog::onChatroomWidgetClicked(GenericChatroomWidget *widget) activeChatroomWidget = widget; widget->setChatForm(contentLayout); - setWindowTitle(widget->getName()); widget->setAsActiveChatroom(); widget->resetEventFlags(); widget->updateStatusLight(); - QString windowTitle = widget->getName(); - if (!widget->getStatusString().isNull()) - windowTitle += " (" + widget->getStatusString() + ")"; - setWindowTitle(windowTitle); + setWindowTitle(widget->getTitle()); + + if (widget->getFriend() != nullptr) + widget->getFriend()->getFriendWidget()->updateStatusLight(); + else + widget->getGroup()->getGroupWidget()->updateStatusLight(); +} + +void ContentDialog::updateFriendWidget(FriendWidget *w, Status s) +{ + // Note: This argument friend widget is not the one stored here! + Q_UNUSED(s); // Use it after friend list improvements are merged, to sort contacts here. + + std::get<1>(friendList.find(w->friendId).value())->setName(w->getName()); +} + +void ContentDialog::updateGroupWidget(GroupWidget *w) +{ + std::get<1>(groupList.find(w->groupId).value())->setName(w->getName()); + static_cast(std::get<1>(groupList.find(w->groupId).value()))->onUserListChanged(); } void ContentDialog::saveDialogGeometry() @@ -172,3 +328,100 @@ void ContentDialog::saveSplitterState() { Settings::getInstance().setDialogSplitterState(splitter->saveState()); } + +void ContentDialog::remove(int id, const QHash > &list) +{ + auto iter = list.find(id); + + if (iter == list.end()) + return; + + GenericChatroomWidget* chatroomWidget = std::get<1>(iter.value()); + + if (activeChatroomWidget == chatroomWidget) + { + // Need to find replacement to show here instead. + if (chatroomWidgetCount() > 0) + { + int index = friendLayout->indexOf(chatroomWidget) - 1; + + // Don't let it go below 0. If it does, then we're first. Go second. + if (index < 0) + index = 1; + + GenericChatroomWidget* chatroomWidget = static_cast(friendLayout->itemAt(index)->widget()); + onChatroomWidgetClicked(chatroomWidget, false); + } + else + { + contentLayout->clear(); + activeChatroomWidget = nullptr; + deleteLater(); + } + } + + friendLayout->removeWidget(chatroomWidget); + chatroomWidget->deleteLater(); + friendList.remove(id); + update(); +} + +bool ContentDialog::hasWidget(int id, GenericChatroomWidget* chatroomWidget, const QHash>& list) +{ + auto iter = list.find(id); + + if (iter == list.end() || std::get<0>(iter.value()) != this) + return false; + + return chatroomWidget == std::get<1>(iter.value()); +} + +bool ContentDialog::existsWidget(int id, bool focus, const QHash>& list) +{ + auto iter = list.find(id); + if (iter == list.end()) + return false; + + if (focus) + { + std::get<0>(iter.value())->raise(); + std::get<0>(iter.value())->activateWindow(); + std::get<0>(iter.value())->onChatroomWidgetClicked(std::get<1>(iter.value()), false); + } + + return true; +} + +void ContentDialog::updateStatus(int id, const QHash > &list) +{ + auto iter = list.find(id); + + if (iter == list.end()) + return; + + GenericChatroomWidget* chatroomWidget = std::get<1>(iter.value()); + chatroomWidget->updateStatusLight(); + + if(chatroomWidget->isActive()) + std::get<0>(iter.value())->setWindowTitle(chatroomWidget->getTitle()); +} + +bool ContentDialog::isWidgetActive(int id, const QHash > &list) +{ + auto iter = list.find(id); + + if (iter == list.end()) + return false; + + return std::get<0>(iter.value())->activeChatroomWidget == std::get<1>(iter.value()); +} + +ContentDialog* ContentDialog::getDialog(int id, const QHash>& list) +{ + auto iter = list.find(id); + + if (iter == list.end()) + return nullptr; + + return std::get<0>(iter.value()); +} diff --git a/src/widget/contentdialog.h b/src/widget/contentdialog.h index 44244d692..f242830ed 100644 --- a/src/widget/contentdialog.h +++ b/src/widget/contentdialog.h @@ -22,6 +22,7 @@ #include #include +#include "src/core/corestructs.h" template class QHash; @@ -29,6 +30,8 @@ class QSplitter; class QVBoxLayout; class ContentLayout; class GenericChatroomWidget; +class FriendWidget; +class GroupWidget; class ContentDialog : public QDialog { @@ -36,27 +39,56 @@ class ContentDialog : public QDialog public: ContentDialog(QWidget* parent = 0); ~ContentDialog(); - void addFriend(int friendId, QString id); + + FriendWidget* addFriend(int friendId, QString id); + GroupWidget* addGroup(int groupId, const QString& name); + void removeFriend(int friendId); + void removeGroup(int groupId); + bool hasFriendWidget(int friendId, GenericChatroomWidget* chatroomWidget); + bool hasGroupWidget(int groupId, GenericChatroomWidget* chatroomWidget); + int chatroomWidgetCount() const; + static ContentDialog* current(); - static bool showChatroomWidget(int friendId); + static bool existsFriendWidget(int friendId, bool focus); + static bool existsGroupWidget(int groupId, bool focus); + static void updateFriendStatus(int friendId); + static void updateFriendStatusMessage(int friendId, const QString &message); + static void updateGroupStatus(int groupId); + static bool isFriendWidgetActive(int friendId); + static bool isGroupWidgetActive(int groupId); + static ContentDialog* getFriendDialog(int friendId); + static ContentDialog* getGroupDialog(int groupId); protected: + void dragEnterEvent(QDragEnterEvent* event) final override; + void dropEvent(QDropEvent* event) final override; + void changeEvent(QEvent* event) override; void resizeEvent(QResizeEvent* event) override; void closeEvent(QCloseEvent* event) override; private slots: - void onChatroomWidgetClicked(GenericChatroomWidget* widget); + void onChatroomWidgetClicked(GenericChatroomWidget* widget, bool group); + void updateFriendWidget(FriendWidget* w, Status s); + void updateGroupWidget(GroupWidget* w); private: void saveDialogGeometry(); void saveSplitterState(); + void remove(int id, const QHash>& list); + bool hasWidget(int id, GenericChatroomWidget* chatroomWidget, const QHash>& list); + static bool existsWidget(int id, bool focus, const QHash>& list); + static void updateStatus(int id, const QHash>& list); + static bool isWidgetActive(int id, const QHash>& list); + static ContentDialog* getDialog(int id, const QHash>& list); + QSplitter* splitter; QVBoxLayout* friendLayout; ContentLayout* contentLayout; GenericChatroomWidget* activeChatroomWidget; static ContentDialog* currentDialog; static QHash> friendList; + static QHash> groupList; }; #endif // CONTENTDIALOG_H diff --git a/src/widget/form/chatform.cpp b/src/widget/form/chatform.cpp index b20e7480c..bb244af87 100644 --- a/src/widget/form/chatform.cpp +++ b/src/widget/form/chatform.cpp @@ -219,7 +219,7 @@ void ChatForm::onFileRecvRequest(ToxFile file) Widget* w = Widget::getInstance(); if (!w->isFriendWidgetCurActiveWidget(f)|| w->isMinimized() || !w->isActiveWindow()) { - w->newMessageAlert(f->getFriendWidget()); + w->newFriendMessageAlert(file.friendId); f->setEventFlag(true); f->getFriendWidget()->updateStatusLight(); } @@ -302,7 +302,7 @@ void ChatForm::onAvInvite(uint32_t FriendId, int CallId, bool video) Widget* w = Widget::getInstance(); if (!w->isFriendWidgetCurActiveWidget(f)|| w->isMinimized() || !w->isActiveWindow()) { - w->newMessageAlert(f->getFriendWidget()); + w->newFriendMessageAlert(FriendId); f->setEventFlag(true); f->getFriendWidget()->updateStatusLight(); } diff --git a/src/widget/friendwidget.cpp b/src/widget/friendwidget.cpp index fd298c72e..750c6d2a9 100644 --- a/src/widget/friendwidget.cpp +++ b/src/widget/friendwidget.cpp @@ -68,8 +68,22 @@ void FriendWidget::contextMenuEvent(QContextMenuEvent * event) ToxId id = FriendList::findFriend(friendId)->getToxId(); QString dir = Settings::getInstance().getAutoAcceptDir(id); QMenu menu; - menu.addAction(tr("Open Chat")); - menu.addAction(tr("Open Chat in New Window")); + QAction* openChat = menu.addAction(tr("Open chat")); + QAction* openChatWindow = nullptr; + QAction* removeChatWindow = nullptr; + + if (!Settings::getInstance().getSeparateWindow() || !Settings::getInstance().getDontGroupWindows()) + { + ContentDialog* contentDialog = ContentDialog::getFriendDialog(friendId); + bool notAlone = contentDialog != nullptr && contentDialog->chatroomWidgetCount() > 1; + + if (contentDialog == nullptr || notAlone) + openChatWindow = menu.addAction(tr("Open chat in new window")); + + if (notAlone && contentDialog->hasFriendWidget(friendId, this)) + removeChatWindow = menu.addAction(tr("Remove chat from this window")); + } + menu.addSeparator(); QMenu* inviteMenu = menu.addMenu(tr("Invite to group","Menu to invite a friend to a groupchat")); QMap groupActions; @@ -160,6 +174,22 @@ void FriendWidget::contextMenuEvent(QContextMenuEvent * event) emit removeFriend(friendId); return; } + else if (selectedItem == openChat) + { + emit chatroomWidgetClicked(this); + return; + } + else if (selectedItem == openChatWindow) + { + emit chatroomWidgetClicked(this, true); + return; + } + else if (selectedItem == removeChatWindow) + { + ContentDialog* contentDialog = ContentDialog::getFriendDialog(friendId); + contentDialog->removeFriend(friendId); + return; + } else if (selectedItem == autoAccept) { if (!autoAccept->isChecked()) @@ -282,7 +312,7 @@ void FriendWidget::updateStatusLight() statusPic.setMargin(0); } -QString FriendWidget::getStatusString() +QString FriendWidget::getStatusString() const { Friend* f = FriendList::findFriend(friendId); Status status = f->getStatus(); @@ -313,10 +343,10 @@ void FriendWidget::search(const QString &searchString, bool hide) circleWidget->search(searchString); } -bool FriendWidget::chatFormIsSet() const +bool FriendWidget::chatFormIsSet(bool focus) const { Friend* f = FriendList::findFriend(friendId); - return f->getChatForm()->isVisible() || ContentDialog::showChatroomWidget(friendId); + return ContentDialog::existsFriendWidget(friendId, focus) || f->getChatForm()->isVisible(); } void FriendWidget::setChatForm(ContentLayout* contentLayout) diff --git a/src/widget/friendwidget.h b/src/widget/friendwidget.h index 2ef2b26d2..351f10ab0 100644 --- a/src/widget/friendwidget.h +++ b/src/widget/friendwidget.h @@ -32,10 +32,10 @@ public: virtual void setAsActiveChatroom() override; virtual void setAsInactiveChatroom() override; virtual void updateStatusLight() override; - virtual bool chatFormIsSet() const override; + virtual bool chatFormIsSet(bool focus) const override; virtual void setChatForm(ContentLayout* contentLayout) override; virtual void resetEventFlags() override; - virtual QString getStatusString() override; + virtual QString getStatusString() const override; virtual Friend* getFriend() const override; void search(const QString &searchString, bool hide = false); diff --git a/src/widget/genericchatroomwidget.cpp b/src/widget/genericchatroomwidget.cpp index 09983df98..be25f919a 100644 --- a/src/widget/genericchatroomwidget.cpp +++ b/src/widget/genericchatroomwidget.cpp @@ -144,6 +144,16 @@ QString GenericChatroomWidget::getStatusMsg() const return statusMessageLabel->text(); } +QString GenericChatroomWidget::getTitle() const +{ + QString title = getName(); + + if (!getStatusString().isNull()) + title += QStringLiteral(" (") + getStatusString() + QStringLiteral(")"); + + return title; +} + void GenericChatroomWidget::reloadTheme() { QPalette p; diff --git a/src/widget/genericchatroomwidget.h b/src/widget/genericchatroomwidget.h index 73866c2c9..8132e5a9b 100644 --- a/src/widget/genericchatroomwidget.h +++ b/src/widget/genericchatroomwidget.h @@ -28,6 +28,7 @@ class QVBoxLayout; class QHBoxLayout; class ContentLayout; class Friend; +class Group; class GenericChatroomWidget : public GenericChatItemWidget { @@ -38,11 +39,12 @@ public: virtual void setAsActiveChatroom() = 0; virtual void setAsInactiveChatroom() = 0; virtual void updateStatusLight() = 0; - virtual bool chatFormIsSet() const = 0; + virtual bool chatFormIsSet(bool focus) const = 0; virtual void setChatForm(ContentLayout* contentLayout) = 0; virtual void resetEventFlags() = 0; - virtual QString getStatusString() = 0; + virtual QString getStatusString() const = 0; virtual Friend* getFriend() const{return nullptr;} + virtual Group* getGroup() const{return nullptr;} virtual bool eventFilter(QObject *, QEvent *) final override; @@ -52,6 +54,7 @@ public: void setName(const QString& name); void setStatusMsg(const QString& status); QString getStatusMsg() const; + QString getTitle() const; void reloadTheme(); @@ -59,7 +62,7 @@ public slots: void compactChange(bool compact); signals: - void chatroomWidgetClicked(GenericChatroomWidget* widget); + void chatroomWidgetClicked(GenericChatroomWidget* widget, bool group = false); protected: virtual void mouseReleaseEvent(QMouseEvent* event) override; diff --git a/src/widget/groupwidget.cpp b/src/widget/groupwidget.cpp index 36a32d174..adb420b52 100644 --- a/src/widget/groupwidget.cpp +++ b/src/widget/groupwidget.cpp @@ -19,8 +19,10 @@ #include "groupwidget.h" #include "maskablepixmapwidget.h" +#include "contentdialog.h" #include "src/grouplist.h" #include "src/group.h" +#include "src/persistence/settings.h" #include "form/groupchatform.h" #include "src/widget/style.h" #include "src/core/core.h" @@ -62,6 +64,25 @@ void GroupWidget::contextMenuEvent(QContextMenuEvent* event) installEventFilter(this); // Disable leave event. QMenu menu(this); + + QAction* openChat = menu.addAction(tr("Open chat")); + QAction* openChatWindow = nullptr; + QAction* removeChatWindow = nullptr; + + if (!Settings::getInstance().getSeparateWindow() || !Settings::getInstance().getDontGroupWindows()) + { + ContentDialog* contentDialog = ContentDialog::getGroupDialog(groupId); + bool notAlone = contentDialog != nullptr && contentDialog->chatroomWidgetCount() > 1; + + if (contentDialog == nullptr || notAlone) + openChatWindow = menu.addAction(tr("Open chat in new window")); + + if (notAlone && contentDialog->hasGroupWidget(groupId, this)) + removeChatWindow = menu.addAction(tr("Remove chat from this window")); + } + + menu.addSeparator(); + QAction* setTitle = menu.addAction(tr("Set title...")); QAction* quitGroup = menu.addAction(tr("Quit group","Menu to quit a groupchat")); @@ -78,6 +99,22 @@ void GroupWidget::contextMenuEvent(QContextMenuEvent* event) { emit removeGroup(groupId); } + else if (selectedItem == openChat) + { + emit chatroomWidgetClicked(this); + return; + } + else if (selectedItem == openChatWindow) + { + emit chatroomWidgetClicked(this, true); + return; + } + else if (selectedItem == removeChatWindow) + { + ContentDialog* contentDialog = ContentDialog::getGroupDialog(groupId); + contentDialog->removeGroup(groupId); + return; + } else if (selectedItem == setTitle) { editName(); @@ -122,7 +159,7 @@ void GroupWidget::updateStatusLight() } } -QString GroupWidget::getStatusString() +QString GroupWidget::getStatusString() const { Group *g = GroupList::findGroup(groupId); @@ -137,10 +174,16 @@ void GroupWidget::editName() nameLabel->editBegin(); } -bool GroupWidget::chatFormIsSet() const +Group* GroupWidget::getGroup() const { + return GroupList::findGroup(groupId); +} + +bool GroupWidget::chatFormIsSet(bool focus) const +{ + (void)focus; Group* g = GroupList::findGroup(groupId); - return g->getChatForm()->isVisible(); + return ContentDialog::existsGroupWidget(groupId, focus) || g->getChatForm()->isVisible(); } void GroupWidget::setChatForm(ContentLayout* contentLayout) diff --git a/src/widget/groupwidget.h b/src/widget/groupwidget.h index 5f7610f32..59a98e058 100644 --- a/src/widget/groupwidget.h +++ b/src/widget/groupwidget.h @@ -30,10 +30,11 @@ public: virtual void setAsInactiveChatroom() final override; virtual void setAsActiveChatroom() final override; virtual void updateStatusLight() final override; - virtual bool chatFormIsSet() const final override; + virtual bool chatFormIsSet(bool focus) const final override; virtual void setChatForm(ContentLayout* contentLayout) override; virtual void resetEventFlags() final override; - virtual QString getStatusString() final override; + virtual QString getStatusString() const final override; + virtual Group* getGroup() const override; void setName(const QString& name); void onUserListChanged(); void editName(); diff --git a/src/widget/widget.cpp b/src/widget/widget.cpp index 7320ae17f..03a50d6c5 100644 --- a/src/widget/widget.cpp +++ b/src/widget/widget.cpp @@ -332,13 +332,12 @@ void Widget::init() contentLayout = nullptr; onSeparateWindowChanged(Settings::getInstance().getSeparateWindow(), false); - if (contentLayout != nullptr) - onAddClicked(); - ui->addButton->setCheckable(true); ui->transferButton->setCheckable(true); ui->settingsButton->setCheckable(true); - setActiveToolMenuButton(Widget::AddButton); + + if (contentLayout != nullptr) + onAddClicked(); //restore window state restoreGeometry(Settings::getInstance().getWindowGeometry()); @@ -568,6 +567,7 @@ void Widget::onSeparateWindowChanged(bool separate, bool clicked) resize(ui->statusPanel->width(), height()); setWindowTitle(QString()); + setActiveToolMenuButton(None); } if (clicked) @@ -795,7 +795,7 @@ void Widget::addFriend(int friendId, const QString &userId) Core* core = Nexus::getCore(); connect(newfriend, &Friend::displayedNameChanged, this, &Widget::onFriendDisplayChanged); connect(settingsWidget, &SettingsWidget::compactToggled, newfriend->getFriendWidget(), &GenericChatroomWidget::compactChange); - connect(newfriend->getFriendWidget(), SIGNAL(chatroomWidgetClicked(GenericChatroomWidget*)), this, SLOT(onChatroomWidgetClicked(GenericChatroomWidget*))); + connect(newfriend->getFriendWidget(), SIGNAL(chatroomWidgetClicked(GenericChatroomWidget*,bool)), this, SLOT(onChatroomWidgetClicked(GenericChatroomWidget*,bool))); connect(newfriend->getFriendWidget(), SIGNAL(removeFriend(int)), this, SLOT(removeFriend(int))); connect(newfriend->getFriendWidget(), SIGNAL(copyFriendIdToClipboard(int)), this, SLOT(copyFriendIdToClipboard(int))); connect(newfriend->getFriendWidget(), SIGNAL(chatroomWidgetClicked(GenericChatroomWidget*)), newfriend->getChatForm(), SLOT(focusInput())); @@ -883,6 +883,8 @@ void Widget::onFriendStatusChanged(int friendId, Status status) setWindowTitle(windowTitle); } + ContentDialog::updateFriendStatus(friendId); + //won't print the message if there were no messages before if (!f->getChatForm()->isEmpty() && Settings::getInstance().getStatusChangeNotificationEnabled()) @@ -921,6 +923,8 @@ void Widget::onFriendStatusMessageChanged(int friendId, const QString& message) QString str = message; str.replace('\n', ' '); str.remove('\r'); str.remove(QChar((char)0)); // null terminator... f->setStatusMessage(str); + + ContentDialog::updateFriendStatusMessage(friendId, message); } void Widget::onFriendUsernameChanged(int friendId, const QString& username) @@ -948,39 +952,46 @@ void Widget::onFriendDisplayChanged(FriendWidget *friendWidget, Status s) } -void Widget::onChatroomWidgetClicked(GenericChatroomWidget *widget) +void Widget::onChatroomWidgetClicked(GenericChatroomWidget *widget, bool group) { - if (Settings::getInstance().getSeparateWindow()) + widget->resetEventFlags(); + widget->updateStatusLight(); + + if (widget->chatFormIsSet(true)) + return; + + if (Settings::getInstance().getSeparateWindow() || group) { - if (!widget->chatFormIsSet()) + ContentDialog* dialog = nullptr; + + if (!Settings::getInstance().getDontGroupWindows() && !group) + dialog = ContentDialog::current(); + + if (dialog == nullptr) + dialog = new ContentDialog(); + + dialog->show(); + Friend* frnd = widget->getFriend(); + + if (frnd != nullptr) { - ContentDialog* dialog = nullptr; - - if (!Settings::getInstance().getDontGroupWindows()) - dialog = ContentDialog::current(); - - if (dialog == nullptr) - dialog = new ContentDialog(); - - dialog->show(); - Friend* frnd = widget->getFriend(); - if (frnd != nullptr) - { - dialog->addFriend(frnd->getFriendID(), frnd->getDisplayedName()); - } + addFriendDialog(frnd, dialog); } + else + { + Group* group = widget->getGroup(); + addGroupDialog(group, dialog); + } + + dialog->raise(); + dialog->activateWindow(); } else { hideMainForms(widget); widget->setChatForm(contentLayout); widget->setAsActiveChatroom(); - widget->resetEventFlags(); - widget->updateStatusLight(); - QString windowTitle = widget->getName(); - if (!widget->getStatusString().isNull()) - windowTitle += " (" + widget->getStatusString() + ")"; - setWindowTitle(windowTitle); + setWindowTitle(widget->getTitle()); } } @@ -996,9 +1007,11 @@ void Widget::onFriendMessageReceived(int friendId, const QString& message, bool HistoryKeeper::getInstance()->addChatEntry(f->getToxId().publicKey, isAction ? "/me " + f->getDisplayedName() + " " + message : message, f->getToxId().publicKey, timestamp, true); - f->setEventFlag(f->getFriendWidget() != activeChatroomWidget); - newMessageAlert(f->getFriendWidget()); + f->setEventFlag(f->getFriendWidget() != activeChatroomWidget && !ContentDialog::isFriendWidgetActive(friendId)); + newFriendMessageAlert(friendId); f->getFriendWidget()->updateStatusLight(); + ContentDialog::updateFriendStatus(friendId); + if (f->getFriendWidget()->isActive()) { QString windowTitle = f->getFriendWidget()->getName(); @@ -1017,25 +1030,91 @@ void Widget::onReceiptRecieved(int friendId, int receipt) f->getChatForm()->getOfflineMsgEngine()->dischargeReceipt(receipt); } -void Widget::newMessageAlert(GenericChatroomWidget* chat) +void Widget::addFriendDialog(Friend *frnd, ContentDialog *dialog) +{ + FriendWidget* friendWidget = dialog->addFriend(frnd->getFriendID(), frnd->getDisplayedName()); + + friendWidget->setStatusMsg(frnd->getFriendWidget()->getStatusMsg()); + + connect(friendWidget, SIGNAL(removeFriend(int)), this, SLOT(removeFriend(int))); + connect(friendWidget, SIGNAL(copyFriendIdToClipboard(int)), this, SLOT(copyFriendIdToClipboard(int))); + + connect(Core::getInstance(), &Core::friendAvatarChanged, friendWidget, &FriendWidget::onAvatarChange); + connect(Core::getInstance(), &Core::friendAvatarRemoved, friendWidget, &FriendWidget::onAvatarRemoved); + + QPixmap avatar = Settings::getInstance().getSavedAvatar(frnd->getToxId().toString()); + if (!avatar.isNull()) + friendWidget->onAvatarChange(frnd->getFriendID(), avatar); +} + +void Widget::addGroupDialog(Group *group, ContentDialog *dialog) +{ + GroupWidget* groupWidget = dialog->addGroup(group->getGroupId(), group->getName()); + connect(groupWidget, SIGNAL(removeGroup(int)), this, SLOT(removeGroup(int))); + connect(groupWidget, SIGNAL(chatroomWidgetClicked(GenericChatroomWidget*)), group->getChatForm(), SLOT(focusInput())); +} + +void Widget::newFriendMessageAlert(int friendId) +{ + bool hasActive; + QWidget* currentWindow; + ContentDialog* contentDialog = ContentDialog::getFriendDialog(friendId); + + if (contentDialog != nullptr) + { + currentWindow = contentDialog->window(); + hasActive = ContentDialog::isFriendWidgetActive(friendId); + } + else + { + currentWindow = window(); + hasActive = activeChatroomWidget != nullptr && FriendList::findFriend(friendId)->getFriendWidget() == activeChatroomWidget; + } + + newMessageAlert(currentWindow, hasActive); +} + +void Widget::newGroupMessageAlert(int groupId) +{ + bool hasActive; + QWidget* currentWindow; + ContentDialog* contentDialog = ContentDialog::getGroupDialog(groupId); + + if (contentDialog != nullptr) + { + currentWindow = contentDialog->window(); + hasActive = ContentDialog::isGroupWidgetActive(groupId); + } + else + { + currentWindow = window(); + hasActive = activeChatroomWidget != nullptr && GroupList::findGroup(groupId)->getGroupWidget() == activeChatroomWidget; + } + + newMessageAlert(currentWindow, hasActive); +} + +void Widget::newMessageAlert(QWidget* currentWindow, bool isActive) { bool inactiveWindow = isMinimized() || !isActiveWindow(); - if (!inactiveWindow && activeChatroomWidget != nullptr && chat == activeChatroomWidget) + + if (!inactiveWindow && isActive) return; if (ui->statusButton->property("status").toString() == "busy") return; - QApplication::alert(this); + QApplication::alert(currentWindow); if (inactiveWindow) eventFlag = true; if (Settings::getInstance().getShowWindow()) { - show(); + currentWindow->activateWindow(); + currentWindow->show(); if (inactiveWindow && Settings::getInstance().getShowInFront()) - setWindowState(Qt::WindowActive); + currentWindow->setWindowState(Qt::WindowActive); } if (Settings::getInstance().getNotifySound()) @@ -1052,9 +1131,6 @@ void Widget::newMessageAlert(GenericChatroomWidget* chat) Audio::playMono16Sound(sndData); } - - if (activeChatroomWidget != chat) - ui->friendList->trackWidget(chat); } void Widget::playRingtone() @@ -1212,12 +1288,14 @@ void Widget::onGroupMessageReceived(int groupnumber, int peernumber, const QStri g->setEventFlag(static_cast(g->getGroupWidget()) != activeChatroomWidget); if (targeted || Settings::getInstance().getGroupAlwaysNotify()) - newMessageAlert(g->getGroupWidget()); + newGroupMessageAlert(g->getGroupId()); if (targeted) g->setMentionedFlag(true); // useful for highlighting line or desktop notifications g->getGroupWidget()->updateStatusLight(); + ContentDialog::updateGroupStatus(g->getGroupId()); + if (g->getGroupWidget()->isActive()) { QString windowTitle = g->getGroupWidget()->getName(); @@ -1325,7 +1403,7 @@ Group *Widget::createGroup(int groupId) newgroup->getGroupWidget()->updateStatusLight(); connect(settingsWidget, &SettingsWidget::compactToggled, newgroup->getGroupWidget(), &GenericChatroomWidget::compactChange); - connect(newgroup->getGroupWidget(), SIGNAL(chatroomWidgetClicked(GenericChatroomWidget*)), this, SLOT(onChatroomWidgetClicked(GenericChatroomWidget*))); + connect(newgroup->getGroupWidget(), SIGNAL(chatroomWidgetClicked(GenericChatroomWidget*,bool)), this, SLOT(onChatroomWidgetClicked(GenericChatroomWidget*,bool))); connect(newgroup->getGroupWidget(), SIGNAL(removeGroup(int)), this, SLOT(removeGroup(int))); connect(newgroup->getGroupWidget(), SIGNAL(chatroomWidgetClicked(GenericChatroomWidget*)), newgroup->getChatForm(), SLOT(focusInput())); connect(newgroup->getChatForm(), &GroupChatForm::sendMessage, core, &Core::sendGroupMessage); diff --git a/src/widget/widget.h b/src/widget/widget.h index 1957fc482..9f797a25e 100644 --- a/src/widget/widget.h +++ b/src/widget/widget.h @@ -52,6 +52,7 @@ class AddFriendForm; class CircleWidget; class QActionGroup; class ContentLayout; +class ContentDialog; class Widget final : public QMainWindow { @@ -64,7 +65,10 @@ public: QString getUsername(); Camera* getCamera(); static Widget* getInstance(); - void newMessageAlert(GenericChatroomWidget* chat); + void addFriendDialog(Friend* frnd, ContentDialog* dialog); + void addGroupDialog(Group* group, ContentDialog* dialog); + void newFriendMessageAlert(int friendId); + void newGroupMessageAlert(int groupId); bool isFriendWidgetCurActiveWidget(const Friend* f) const; bool getIsWindowMinimized(); void updateIcons(); @@ -147,8 +151,8 @@ private slots: void onTransferClicked(); void showProfile(); void onUsernameChanged(const QString& newUsername, const QString& oldUsername); + void onChatroomWidgetClicked(GenericChatroomWidget *, bool group); void onStatusMessageChanged(const QString& newStatusMessage); - void onChatroomWidgetClicked(GenericChatroomWidget *); void removeFriend(int friendId); void copyFriendIdToClipboard(int friendId); void removeGroup(int groupId); @@ -188,6 +192,7 @@ private: }; private: + void newMessageAlert(QWidget* currentWindow, bool isActive); void setActiveToolMenuButton(ActiveToolMenuButton newActiveButton); void hideMainForms(GenericChatroomWidget* chatroomWidget); Group *createGroup(int groupId);