diff --git a/qtox.pro b/qtox.pro index a66e3428d..37b701d48 100644 --- a/qtox.pro +++ b/qtox.pro @@ -481,7 +481,9 @@ SOURCES += \ src/core/toxid.cpp \ src/persistence/profile.cpp \ src/widget/translator.cpp \ - src/persistence/settingsserializer.cpp + src/persistence/settingsserializer.cpp \ + src/widget/notificationscrollarea.cpp \ + src/widget/notificationedgewidget.cpp HEADERS += \ src/audio/audio.h \ @@ -517,4 +519,6 @@ HEADERS += \ src/core/toxid.h \ src/persistence/profile.h \ src/widget/translator.h \ - src/persistence/settingsserializer.h + src/persistence/settingsserializer.h \ + src/widget/notificationscrollarea.h \ + src/widget/notificationedgewidget.h diff --git a/res.qrc b/res.qrc index 74ce71c24..a93e3bd71 100644 --- a/res.qrc +++ b/res.qrc @@ -119,5 +119,6 @@ ui/rejectCall/rejectCall.svg ui/volButton/volButtonDisabled.png img/login_logo.svg + ui/notificationEdge/notificationEdge.css diff --git a/src/mainwindow.ui b/src/mainwindow.ui index 240f10173..b2bb7c793 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -1045,7 +1045,7 @@ QSplitter:handle{ - + 0 @@ -1072,8 +1072,8 @@ QSplitter:handle{ 0 0 - 284 - 359 + 292 + 353 @@ -1838,7 +1838,7 @@ QSplitter:handle{ 0 0 775 - 19 + 22 @@ -1859,9 +1859,9 @@ QSplitter:handle{
src/widget/tool/croppinglabel.h
- AdjustingScrollArea + NotificationScrollArea QScrollArea -
src/widget/tool/adjustingscrollarea.h
+
src/widget/notificationscrollarea.h
1
diff --git a/src/widget/notificationedgewidget.cpp b/src/widget/notificationedgewidget.cpp new file mode 100644 index 000000000..0bd7e9131 --- /dev/null +++ b/src/widget/notificationedgewidget.cpp @@ -0,0 +1,56 @@ +/* + Copyright © 2015 by The qTox Project + + This file is part of qTox, a Qt-based graphical interface for Tox. + + qTox 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. + + qTox 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 + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with qTox. If not, see . +*/ + +#include "notificationedgewidget.h" +#include "style.h" +#include +#include + +#include + +NotificationEdgeWidget::NotificationEdgeWidget(Position position, QWidget *parent) + : QWidget(parent) +{ + setAttribute(Qt::WA_StyledBackground); // Show background. + setStyleSheet(Style::getStylesheet(":/ui/notificationEdge/notificationEdge.css")); + QHBoxLayout* layout = new QHBoxLayout(this); + layout->addStretch(); + + QLabel* textLabel = new QLabel(tr("Unread message(s)"), this); + textLabel->setMinimumHeight(textLabel->sizeHint().height()); // Prevent cut-off text. + layout->addWidget(textLabel); + + QLabel* arrowLabel = new QLabel(this); + + if (position == Top) + arrowLabel->setPixmap(QPixmap("://ui/chatArea/scrollBarUpArrow.svg")); + else + arrowLabel->setPixmap(QPixmap("://ui/chatArea/scrollBarDownArrow.svg")); + + layout->addWidget(arrowLabel); + layout->addStretch(); + + setCursor(Qt::PointingHandCursor); +} + +void NotificationEdgeWidget::mouseReleaseEvent(QMouseEvent *event) +{ + emit clicked(); + QWidget::mousePressEvent(event); +} diff --git a/src/widget/notificationedgewidget.h b/src/widget/notificationedgewidget.h new file mode 100644 index 000000000..474834967 --- /dev/null +++ b/src/widget/notificationedgewidget.h @@ -0,0 +1,44 @@ +/* + Copyright © 2015 by The qTox Project + + This file is part of qTox, a Qt-based graphical interface for Tox. + + qTox 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. + + qTox 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 + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with qTox. If not, see . +*/ + +#ifndef NOTIFICATIONEDGEWIDGET_H +#define NOTIFICATIONEDGEWIDGET_H + +#include + +class NotificationEdgeWidget final : public QWidget +{ + Q_OBJECT +public: + enum Position : uint8_t + { + Top, + Bottom + }; + + explicit NotificationEdgeWidget(Position position, QWidget *parent = 0); + +signals: + void clicked(); + +protected: + void mouseReleaseEvent(QMouseEvent* event) final override; +}; + +#endif // NOTIFICATIONEDGEWIDGET_H diff --git a/src/widget/notificationscrollarea.cpp b/src/widget/notificationscrollarea.cpp new file mode 100644 index 000000000..f98627582 --- /dev/null +++ b/src/widget/notificationscrollarea.cpp @@ -0,0 +1,204 @@ +/* + Copyright © 2015 by The qTox Project + + This file is part of qTox, a Qt-based graphical interface for Tox. + + qTox 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. + + qTox 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 + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with qTox. If not, see . +*/ +#include "notificationscrollarea.h" +#include "notificationedgewidget.h" +#include "genericchatroomwidget.h" +#include +#include + +#include +#include + +NotificationScrollArea::NotificationScrollArea(QWidget* parent) + : AdjustingScrollArea(parent) +{ + connect(verticalScrollBar(), &QAbstractSlider::valueChanged, this, &NotificationScrollArea::updateTracking); +} + +void NotificationScrollArea::trackWidget(GenericChatroomWidget* widget) +{ + if (trackedWidgets.find(widget) != trackedWidgets.end()) + return; + + Visibility visibility = widgetVisible(widget); + if (visibility != Visible) + { + if (visibility == Above) + { + if (referencesAbove++ == 0) + { + assert(topEdge == nullptr); + topEdge = new NotificationEdgeWidget(NotificationEdgeWidget::Top, this); + connect(topEdge, &NotificationEdgeWidget::clicked, this, &NotificationScrollArea::findPreviousWidget); + recalculateTopEdge(); + topEdge->show(); + } + } + else + { + if (referencesBelow++ == 0) + { + assert(bottomEdge == nullptr); + bottomEdge = new NotificationEdgeWidget(NotificationEdgeWidget::Bottom, this); + connect(bottomEdge, &NotificationEdgeWidget::clicked, this, &NotificationScrollArea::findNextWidget); + recalculateBottomEdge(); + bottomEdge->show(); + } + } + + trackedWidgets.insert(widget, visibility); + } + qDebug() << "VISIBLE?" << visibility; +} + +void NotificationScrollArea::updateTracking() +{ + QHash::iterator i = trackedWidgets.begin(); + while (i != trackedWidgets.end()) + { + if (widgetVisible(i.key()) == Visible) + { + if (i.value() == Above) + { + if (--referencesAbove == 0) + { + delete topEdge; + topEdge = nullptr; + } + } + else + { + if (--referencesBelow == 0) + { + delete bottomEdge; + bottomEdge = nullptr; + } + } + i = trackedWidgets.erase(i); + continue; + } + ++i; + } +} + +void NotificationScrollArea::resizeEvent(QResizeEvent *event) +{ + if (topEdge != nullptr) + recalculateTopEdge(); + if (bottomEdge != nullptr) + recalculateBottomEdge(); + + AdjustingScrollArea::resizeEvent(event); +} + +void NotificationScrollArea::findNextWidget() +{ + GenericChatroomWidget* next = nullptr; + int value; + QHash::iterator i = trackedWidgets.begin(); + + // Find the first next, to avoid nullptr. + for (; i != trackedWidgets.end(); ++i) + { + if (i.value() == Below) + { + next = i.key(); + value = next->mapTo(viewport(), QPoint()).y(); + break; + } + } + + // Try finding a closer one. + for (; i != trackedWidgets.end(); ++i) + { + if (i.value() == Below) + { + int y = i.key()->mapTo(viewport(), QPoint()).y(); + if (y < value) + { + next = i.key(); + value = y; + } + } + } + + if (next != nullptr) + ensureWidgetVisible(next, 0, referencesBelow != 1 ? bottomEdge->height() : 0); +} + +void NotificationScrollArea::findPreviousWidget() +{ + GenericChatroomWidget* next = nullptr; + int value; + QHash::iterator i = trackedWidgets.begin(); + + // Find the first next, to avoid nullptr. + for (; i != trackedWidgets.end(); ++i) + { + if (i.value() == Above) + { + next = i.key(); + value = next->mapTo(viewport(), QPoint()).y(); + break; + } + } + + // Try finding a closer one. + for (; i != trackedWidgets.end(); ++i) + { + if (i.value() == Above) + { + int y = i.key()->mapTo(viewport(), QPoint()).y(); + if (y > value) + { + next = i.key(); + value = y; + } + } + } + + if (next != nullptr) + ensureWidgetVisible(next, 0, referencesAbove != 1 ? topEdge->height() : 0); +} + +NotificationScrollArea::Visibility NotificationScrollArea::widgetVisible(QWidget *widget) const +{ + int y = widget->mapTo(viewport(), QPoint()).y(); + + if (y < 0) + return Above; + else if (y + widget->height() > viewport()->height()) + return Below; + + return Visible; +} + +void NotificationScrollArea::recalculateTopEdge() +{ + topEdge->move(viewport()->pos()); + topEdge->resize(viewport()->width(), topEdge->height()); +} + +void NotificationScrollArea::recalculateBottomEdge() +{ + QPoint position = viewport()->pos(); + position.setY(position.y() + viewport()->height() - bottomEdge->height()); + bottomEdge->move(position); + bottomEdge->resize(viewport()->width(), bottomEdge->height()); +} diff --git a/src/widget/notificationscrollarea.h b/src/widget/notificationscrollarea.h new file mode 100644 index 000000000..43b14787e --- /dev/null +++ b/src/widget/notificationscrollarea.h @@ -0,0 +1,63 @@ +/* + Copyright © 2015 by The qTox Project + + This file is part of qTox, a Qt-based graphical interface for Tox. + + qTox 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. + + qTox 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 + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with qTox. If not, see . +*/ + +#ifndef NOTIFICATIONSCROLLAREA_H +#define NOTIFICATIONSCROLLAREA_H + +#include "tool/adjustingscrollarea.h" +#include + +class GenericChatroomWidget; +class NotificationEdgeWidget; + +class NotificationScrollArea final : public AdjustingScrollArea +{ +public: + NotificationScrollArea(QWidget* parent = 0); + +public slots: + void trackWidget(GenericChatroomWidget* widget); + void updateTracking(); + +protected: + void resizeEvent(QResizeEvent *event) final override; + +private slots: + void findNextWidget(); + void findPreviousWidget(); + +private: + enum Visibility : uint8_t + { + Visible, + Above, + Below + }; + Visibility widgetVisible(QWidget* widget) const; + void recalculateTopEdge(); + void recalculateBottomEdge(); + + QHash trackedWidgets; + NotificationEdgeWidget* topEdge = nullptr; + NotificationEdgeWidget* bottomEdge = nullptr; + size_t referencesAbove = 0; + size_t referencesBelow = 0; +}; + +#endif // NOTIFICATIONSCROLLAREA_H diff --git a/src/widget/tool/adjustingscrollarea.h b/src/widget/tool/adjustingscrollarea.h index d3ef529b3..11f61c208 100644 --- a/src/widget/tool/adjustingscrollarea.h +++ b/src/widget/tool/adjustingscrollarea.h @@ -22,14 +22,14 @@ #include -class AdjustingScrollArea final : public QScrollArea +class AdjustingScrollArea : public QScrollArea { Q_OBJECT public: explicit AdjustingScrollArea(QWidget *parent = 0); protected: - virtual void resizeEvent(QResizeEvent *ev) final override; + virtual void resizeEvent(QResizeEvent *ev) override; virtual QSize sizeHint() const final override; }; diff --git a/src/widget/widget.cpp b/src/widget/widget.cpp index 99d78795f..75770c367 100644 --- a/src/widget/widget.cpp +++ b/src/widget/widget.cpp @@ -799,6 +799,8 @@ void Widget::newMessageAlert(GenericChatroomWidget* chat) Audio::playMono16Sound(sndData); } + + ui->friendList->trackWidget(chat); } void Widget::playRingtone() diff --git a/ui/notificationEdge/notificationEdge.css b/ui/notificationEdge/notificationEdge.css new file mode 100644 index 000000000..9676b81a7 --- /dev/null +++ b/ui/notificationEdge/notificationEdge.css @@ -0,0 +1,9 @@ +NotificationEdgeWidget +{ + background-color: #6bc260; +} + +NotificationEdgeWidget > QLabel +{ + color: white; +}