diff --git a/qtox.pro b/qtox.pro index 68efea513..c4667ced5 100644 --- a/qtox.pro +++ b/qtox.pro @@ -489,7 +489,9 @@ SOURCES += \ src/persistence/settingsserializer.cpp \ src/widget/notificationscrollarea.cpp \ src/widget/notificationedgewidget.cpp \ - src/widget/circlewidget.cpp + src/widget/circlewidget.cpp \ + src/widget/genericchatitemwidget.cpp \ + src/widget/friendlistlayout.cpp HEADERS += \ src/audio/audio.h \ @@ -528,4 +530,6 @@ HEADERS += \ src/persistence/settingsserializer.h \ src/widget/notificationscrollarea.h \ src/widget/notificationedgewidget.h \ - src/widget/circlewidget.hpp + src/widget/circlewidget.h \ + src/widget/genericchatitemwidget.h \ + src/widget/friendlistlayout.h diff --git a/src/widget/circlewidget.cpp b/src/widget/circlewidget.cpp index b9cc66041..3d9ee26a0 100644 --- a/src/widget/circlewidget.cpp +++ b/src/widget/circlewidget.cpp @@ -12,7 +12,7 @@ See the COPYING file for more details. */ -#include "circlewidget.hpp" +#include "circlewidget.h" #include "src/misc/style.h" #include "src/misc/settings.h" #include "src/friendlist.h" @@ -29,20 +29,18 @@ #include +#include "friendlistlayout.h" + CircleWidget::CircleWidget(QWidget *parent) - : QFrame(parent) + : GenericChatItemWidget(parent) { - setProperty("compact", Settings::getInstance().getCompactLayout()); - - setProperty("active", false); - setStyleSheet(Style::getStylesheet(":/ui/chatroomWidgets/circleWidget.css")); QWidget *container = new QWidget(this); container->setObjectName("circleWidgetContainer"); container->setProperty("active", false); mainLayout = new QVBoxLayout(this); - groupLayout = new QVBoxLayout(this); + listLayout = new FriendListLayout(this); QHBoxLayout *layout = new QHBoxLayout(); QVBoxLayout *midLayout = new QVBoxLayout; QHBoxLayout *topLayout = new QHBoxLayout; @@ -119,15 +117,9 @@ CircleWidget::CircleWidget(QWidget *parent) setAcceptDrops(true); } -bool CircleWidget::isCompact() const +void CircleWidget::addFriendWidget(FriendWidget *w, Status s) { - return compact; -} - -void CircleWidget::setCompact(bool compact) -{ - this->compact = compact; - Style::repolish(this); + listLayout->addFriendWidget(w, s); } void CircleWidget::toggle() @@ -135,17 +127,17 @@ void CircleWidget::toggle() visible = !visible; if (visible) { - mainLayout->addLayout(groupLayout); + mainLayout->addLayout(listLayout); arrowLabel->setPixmap(QPixmap(":/ui/chatArea/scrollBarDownArrow.svg")); } else { - mainLayout->removeItem(groupLayout); + mainLayout->removeItem(listLayout); arrowLabel->setPixmap(QPixmap(":/ui/chatArea/scrollBarRightArrow.svg")); } } -void CircleWidget::mousePressEvent(QMouseEvent *event) +void CircleWidget::mousePressEvent(QMouseEvent*) { toggle(); } @@ -161,6 +153,9 @@ void CircleWidget::dropEvent(QDropEvent *event) { if (event->mimeData()->hasFormat("friend")) { + if (!visible) + toggle(); + int friendId = event->mimeData()->data("friend").toInt(); Friend *f = FriendList::findFriend(friendId); assert(f != nullptr); @@ -168,6 +163,6 @@ void CircleWidget::dropEvent(QDropEvent *event) FriendWidget *widget = f->getFriendWidget(); assert(widget != nullptr); - groupLayout->addWidget(widget); + listLayout->addFriendWidget(widget, f->getStatus()); } } diff --git a/src/widget/circlewidget.hpp b/src/widget/circlewidget.h similarity index 79% rename from src/widget/circlewidget.hpp rename to src/widget/circlewidget.h index 3bfc9b4c7..000e36449 100644 --- a/src/widget/circlewidget.hpp +++ b/src/widget/circlewidget.h @@ -15,25 +15,25 @@ #ifndef CIRCLEWIDGET_H #define CIRCLEWIDGET_H -#include +#include "genericchatitemwidget.h" +#include "src/core/corestructs.h" class QVBoxLayout; class QHBoxLayout; class QLabel; +class FriendListLayout; +class FriendWidget; -class CircleWidget : public QFrame +class CircleWidget : public GenericChatItemWidget { Q_OBJECT public: CircleWidget(QWidget *parent = 0); - bool isCompact() const; - void setCompact(bool compact); + void addFriendWidget(FriendWidget *w, Status s); void toggle(); - Q_PROPERTY(bool compact READ isCompact WRITE setCompact) - protected: void mousePressEvent(QMouseEvent *event) override; @@ -47,9 +47,8 @@ private: Online = 0, Offline = 1 }; - bool compact, visible = false; - QVBoxLayout *friendLayouts[2]; - QVBoxLayout *groupLayout; + bool visible = false; + FriendListLayout *listLayout; QVBoxLayout *mainLayout; QLabel *arrowLabel; }; diff --git a/src/widget/friendlistlayout.cpp b/src/widget/friendlistlayout.cpp new file mode 100644 index 000000000..9e7e338f7 --- /dev/null +++ b/src/widget/friendlistlayout.cpp @@ -0,0 +1,96 @@ +/* + This file is part of qTox, a Qt-based graphical interface for Tox. + + This program is libre software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the COPYING file for more details. +*/ + +#include "friendlistlayout.h" +#include "src/friend.h" +#include "src/friendlist.h" +#include "friendwidget.h" +#include + +FriendListLayout::FriendListLayout(QWidget *parent, bool groupsOnTop) + : QVBoxLayout(parent) +{ + setObjectName("FriendListLayout"); + setSpacing(0); + setMargin(0); + + groupLayout = new QVBoxLayout(); + groupLayout->setSpacing(0); + groupLayout->setMargin(0); + + friendLayouts[Online] = new QVBoxLayout(); + friendLayouts[Online]->setSpacing(0); + friendLayouts[Online]->setMargin(0); + + friendLayouts[Offline] = new QVBoxLayout(); + friendLayouts[Offline]->setSpacing(0); + friendLayouts[Offline]->setMargin(0); + + circleLayout = new QVBoxLayout(); + circleLayout->setSpacing(0); + circleLayout->setMargin(0); + + if (groupsOnTop) + { + QVBoxLayout::addLayout(groupLayout); + QVBoxLayout::addLayout(friendLayouts[Online]); + QVBoxLayout::addLayout(friendLayouts[Offline]); + } + else + { + QVBoxLayout::addLayout(friendLayouts[Online]); + QVBoxLayout::addLayout(groupLayout); + QVBoxLayout::addLayout(friendLayouts[Offline]); + } + QVBoxLayout::addLayout(circleLayout); +} + +void FriendListLayout::addFriendWidget(FriendWidget *w, Status s) +{ + QVBoxLayout* l = getFriendLayout(s); + l->removeWidget(w); // In case the widget is already in this layout. + Friend* g = FriendList::findFriend(w->friendId); + + // Binary search. + int min = 0, max = l->count(), mid; + while (min < max) + { + mid = (max - min) / 2 + min; + FriendWidget* w1 = dynamic_cast(l->itemAt(mid)->widget()); + assert(w1 != nullptr); + + Friend* f = FriendList::findFriend(w1->friendId); + int compareValue = f->getDisplayedName().localeAwareCompare(g->getDisplayedName()); + if (compareValue > 0) + { + max = mid; + } + else + { + min = mid + 1; + } + } + + l->insertWidget(min, w); +} + +void FriendListLayout::addItem(QLayoutItem *) +{ + // Must add items through addFriendWidget, addGroupWidget or addCircleWidget. +} + +QVBoxLayout* FriendListLayout::getFriendLayout(Status s) +{ + return s == Status::Offline ? friendLayouts[Offline] : friendLayouts[Online]; +} diff --git a/src/widget/friendlistlayout.h b/src/widget/friendlistlayout.h new file mode 100644 index 000000000..7dc0cb633 --- /dev/null +++ b/src/widget/friendlistlayout.h @@ -0,0 +1,50 @@ +/* + This file is part of qTox, a Qt-based graphical interface for Tox. + + This program is libre software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the COPYING file for more details. +*/ + +#ifndef GENERICFRIENDLISTWIDGET_H +#define GENERICFRIENDLISTWIDGET_H + +#include +#include "src/core/corestructs.h" + +class GroupWidget; +class CircleWidget; +class FriendWidget; + +class FriendListLayout : public QVBoxLayout +{ + Q_OBJECT +public: + explicit FriendListLayout(QWidget *parent, bool groupsOnTop = true); + + void addGroupWidget(GroupWidget *widget); + void addCircleWidget(CircleWidget *widget); + void addFriendWidget(FriendWidget *widget, Status s); + + virtual void addItem(QLayoutItem *) override; + +public: + QVBoxLayout* getFriendLayout(Status s); + + enum FriendLayoutType + { + Online = 0, + Offline = 1 + }; + QVBoxLayout *friendLayouts[2]; + QVBoxLayout *groupLayout; + QVBoxLayout *circleLayout; +}; + +#endif // GENERICFRIENDLISTWIDGET_H diff --git a/src/widget/friendlistwidget.cpp b/src/widget/friendlistwidget.cpp index 11f690bb7..61b0a6190 100644 --- a/src/widget/friendlistwidget.cpp +++ b/src/widget/friendlistwidget.cpp @@ -151,7 +151,7 @@ QList FriendListWidget::getAllFriends() for (int j = 0; j < subLayout->count(); ++j) { GenericChatroomWidget* widget = - reinterpret_cast(subLayout->itemAt(j)->widget()); + dynamic_cast(subLayout->itemAt(j)->widget()); if(!widget) continue; @@ -163,28 +163,32 @@ QList FriendListWidget::getAllFriends() return friends; } -void FriendListWidget::moveWidget(FriendWidget *w, Status s) +void FriendListWidget::moveWidget(QWidget *w, Status s) { QVBoxLayout* l = getFriendLayout(s); l->removeWidget(w); // In case the widget is already in this layout. - Friend* g = FriendList::findFriend(static_cast(w)->friendId); + Friend* g = FriendList::findFriend(dynamic_cast(w)->friendId); // Binary search. int min = 0, max = l->count(), mid; while (min < max) { mid = (max - min) / 2 + min; - FriendWidget* w1 = static_cast(l->itemAt(mid)->widget()); + FriendWidget* w1 = dynamic_cast(l->itemAt(mid)->widget()); assert(w1 != nullptr); Friend* f = FriendList::findFriend(w1->friendId); int compareValue = f->getDisplayedName().localeAwareCompare(g->getDisplayedName()); if (compareValue > 0) + { max = mid; + } else + { min = mid + 1; + } } - static_assert(std::is_same(), "The layout must only contain FriendWidget*"); + l->insertWidget(min, w); } diff --git a/src/widget/friendlistwidget.h b/src/widget/friendlistwidget.h index 19e3f8e8f..575679895 100644 --- a/src/widget/friendlistwidget.h +++ b/src/widget/friendlistwidget.h @@ -29,41 +29,40 @@ class QVBoxLayout; class QGridLayout; class QPixmap; -struct FriendWidget; +class FriendWidget; class GroupWidget; class CircleWidget; +class FriendListLayout; class FriendListWidget : public QWidget { Q_OBJECT public: - explicit FriendListWidget(QWidget *parent = 0, bool groupchatPosition = true); + explicit FriendListWidget(QWidget *parent = 0, bool groupsOnTop = true); + void addGroupWidget(GroupWidget *widget); void hideGroups(QString searchString, bool hideAll = false); - void addCircleWidget(CircleWidget *widget); - void hideFriends(QString searchString, Status status, bool hideAll = false); - QVBoxLayout* getFriendLayout(Status s); + void addCircleWidget(CircleWidget *widget); + + void hideFriends(QString searchString, Status status, bool hideAll = false); QList getAllFriends(); + void reDraw(); -signals: public slots: void onGroupchatPositionChanged(bool top); - void moveWidget(FriendWidget *w, Status s); + void moveWidget(FriendWidget *w, Status s, bool add = false); private: + QVBoxLayout* getFriendLayout(Status s); enum FriendLayoutType { Online = 0, Offline = 1 }; - QVBoxLayout *friendLayouts[2]; - QVBoxLayout *groupLayout; - QVBoxLayout *circleLayout; - QVBoxLayout *mainLayout; - QList circles; + FriendListLayout *listLayout; }; #endif // FRIENDLISTWIDGET_H diff --git a/src/widget/genericchatitemwidget.cpp b/src/widget/genericchatitemwidget.cpp new file mode 100644 index 000000000..6c9969934 --- /dev/null +++ b/src/widget/genericchatitemwidget.cpp @@ -0,0 +1,35 @@ +/* + This file is part of qTox, a Qt-based graphical interface for Tox. + + This program is libre software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the COPYING file for more details. +*/ + +#include "genericchatitemwidget.h" +#include "src/misc/style.h" +#include "src/misc/settings.h" +#include + +GenericChatItemWidget::GenericChatItemWidget(QWidget *parent) + : QFrame(parent) +{ + setProperty("compact", Settings::getInstance().getCompactLayout()); +} + +bool GenericChatItemWidget::isCompact() const +{ + return compact; +} + +void GenericChatItemWidget::setCompact(bool compact) +{ + this->compact = compact; + Style::repolish(this); +} diff --git a/src/widget/genericchatitemwidget.h b/src/widget/genericchatitemwidget.h new file mode 100644 index 000000000..e0337cacd --- /dev/null +++ b/src/widget/genericchatitemwidget.h @@ -0,0 +1,35 @@ +/* + This file is part of qTox, a Qt-based graphical interface for Tox. + + This program is libre software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the COPYING file for more details. +*/ + +#ifndef GENERICCHATITEMWIDGET_H +#define GENERICCHATITEMWIDGET_H + +#include + +class GenericChatItemWidget : public QFrame +{ + Q_OBJECT +public: + GenericChatItemWidget(QWidget *parent = 0); + + bool isCompact() const; + void setCompact(bool compact); + + Q_PROPERTY(bool compact READ isCompact WRITE setCompact) + +private: + bool compact; +}; + +#endif // GENERICCHATITEMWIDGET_H diff --git a/src/widget/genericchatroomwidget.cpp b/src/widget/genericchatroomwidget.cpp index 246747335..3ae6dde21 100644 --- a/src/widget/genericchatroomwidget.cpp +++ b/src/widget/genericchatroomwidget.cpp @@ -54,16 +54,16 @@ void GenericChatroomWidget::setCompact(bool _compact) compact = _compact; delete textLayout; // has to be first, deleted by layout - delete layout; + delete mainLayout; compact = _compact; - layout = new QHBoxLayout; + mainLayout = new QHBoxLayout; textLayout = new QVBoxLayout; - setLayout(layout); - layout->setSpacing(0); - layout->setMargin(0); + setLayout(mainLayout); + mainLayout->setSpacing(0); + mainLayout->setMargin(0); textLayout->setSpacing(0); textLayout->setMargin(0); setLayoutDirection(Qt::LeftToRight); // parent might have set Qt::RightToLeft @@ -73,15 +73,15 @@ void GenericChatroomWidget::setCompact(bool _compact) { setFixedHeight(25); avatar->setSize(QSize(20,20)); - layout->addSpacing(18); - layout->addWidget(avatar); - layout->addSpacing(5); - layout->addWidget(nameLabel); - layout->addWidget(statusMessageLabel); - layout->addSpacing(5); - layout->addWidget(&statusPic); - layout->addSpacing(5); - layout->activate(); + mainLayout->addSpacing(18); + mainLayout->addWidget(avatar); + mainLayout->addSpacing(5); + mainLayout->addWidget(nameLabel); + mainLayout->addWidget(statusMessageLabel); + mainLayout->addSpacing(5); + mainLayout->addWidget(&statusPic); + mainLayout->addSpacing(5); + mainLayout->activate(); statusMessageLabel->setFont(Style::getFont(Style::Small)); nameLabel->setFont(Style::getFont(Style::Medium)); } @@ -93,14 +93,14 @@ void GenericChatroomWidget::setCompact(bool _compact) textLayout->addWidget(nameLabel); textLayout->addWidget(statusMessageLabel); textLayout->addStretch(); - layout->addSpacing(20); - layout->addWidget(avatar); - layout->addSpacing(10); - layout->addLayout(textLayout); - layout->addSpacing(10); - layout->addWidget(&statusPic); - layout->addSpacing(10); - layout->activate(); + mainLayout->addSpacing(20); + mainLayout->addWidget(avatar); + mainLayout->addSpacing(10); + mainLayout->addLayout(textLayout); + mainLayout->addSpacing(10); + mainLayout->addWidget(&statusPic); + mainLayout->addSpacing(10); + mainLayout->activate(); statusMessageLabel->setFont(Style::getFont(Style::Medium)); nameLabel->setFont(Style::getFont(Style::Big)); } diff --git a/src/widget/genericchatroomwidget.h b/src/widget/genericchatroomwidget.h index 35ed49b4a..2211eb08a 100644 --- a/src/widget/genericchatroomwidget.h +++ b/src/widget/genericchatroomwidget.h @@ -20,7 +20,7 @@ #ifndef GENERICCHATROOMWIDGET_H #define GENERICCHATROOMWIDGET_H -#include +#include "genericchatitemwidget.h" #include #include @@ -36,6 +36,7 @@ class GenericChatroomWidget : public QFrame Q_OBJECT public: GenericChatroomWidget(QWidget *parent = 0); + void mouseReleaseEvent (QMouseEvent* event); virtual void setAsActiveChatroom(){;} virtual void setAsInactiveChatroom(){;} @@ -59,6 +60,7 @@ public: public slots: void setCompact(bool compact); + void onCompactChanged(bool compact); signals: void chatroomWidgetClicked(GenericChatroomWidget* widget); @@ -71,7 +73,7 @@ protected: protected: QColor lastColor; - QHBoxLayout* layout = nullptr; + QHBoxLayout* mainLayout = nullptr; QVBoxLayout* textLayout = nullptr; MaskablePixmapWidget* avatar; QLabel statusPic; diff --git a/src/widget/widget.cpp b/src/widget/widget.cpp index 34fa2563d..8d13d992e 100644 --- a/src/widget/widget.cpp +++ b/src/widget/widget.cpp @@ -68,7 +68,7 @@ #include #include -#include "circlewidget.hpp" +#include "circlewidget.h" #ifdef Q_OS_ANDROID #define IS_ON_DESKTOP_GUI 0