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;
+}