diff --git a/src/ChatPage.cc b/src/ChatPage.cc
index bd4d6568..b5012818 100644
--- a/src/ChatPage.cc
+++ b/src/ChatPage.cc
@@ -311,6 +311,8 @@ void ChatPage::changeTopRoomInfo(const QString &room_id)
void ChatPage::showUnreadMessageNotification(int count)
{
+ emit unreadMessages(count);
+
// TODO: Make the default title a const.
if (count == 0)
emit changeWindowTitle("nheko");
diff --git a/src/LoginPage.cc b/src/LoginPage.cc
index 4c63820c..02ab92c6 100644
--- a/src/LoginPage.cc
+++ b/src/LoginPage.cc
@@ -26,6 +26,8 @@ LoginPage::LoginPage(QSharedPointer<MatrixClient> client, QWidget *parent)
, login_settings_{nullptr}
, client_{client}
{
+ setStyleSheet("background-color: #f9f9f9");
+
top_layout_ = new QVBoxLayout();
top_bar_layout_ = new QHBoxLayout();
diff --git a/src/MainWindow.cc b/src/MainWindow.cc
index 9a3a44ef..4f813c07 100644
--- a/src/MainWindow.cc
+++ b/src/MainWindow.cc
@@ -20,6 +20,7 @@
#include <QLayout>
#include <QNetworkReply>
#include <QSettings>
+#include <QSystemTrayIcon>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
@@ -29,16 +30,18 @@ MainWindow::MainWindow(QWidget *parent)
QSizePolicy sizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
setSizePolicy(sizePolicy);
setWindowTitle("nheko");
+ setObjectName("MainWindow");
+ setStyleSheet("QWidget#MainWindow {background-color: #f9f9f9}");
resize(1066, 600); // 16:9 ratio
setMinimumSize(QSize(950, 600));
- setStyleSheet("background-color: #f9f9f9");
QFont font("Open Sans", 12);
font.setStyleStrategy(QFont::PreferAntialias);
setFont(font);
client_ = QSharedPointer<MatrixClient>(new MatrixClient("matrix.org"));
+ trayIcon_ = new TrayIcon(":/logos/nheko-32.png", this);
welcome_page_ = new WelcomePage(this);
login_page_ = new LoginPage(client_, this);
@@ -62,6 +65,12 @@ MainWindow::MainWindow(QWidget *parent)
connect(chat_page_, SIGNAL(close()), this, SLOT(showWelcomePage()));
connect(chat_page_, SIGNAL(changeWindowTitle(QString)), this, SLOT(setWindowTitle(QString)));
+ connect(chat_page_, SIGNAL(unreadMessages(int)), trayIcon_, SLOT(setUnreadCount(int)));
+
+ connect(trayIcon_,
+ SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
+ this,
+ SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
connect(client_.data(),
SIGNAL(initialSyncCompleted(const SyncResponse &)),
@@ -159,6 +168,29 @@ void MainWindow::showRegisterPage()
sliding_stack_->slideInIndex(index, SlidingStackWidget::AnimationDirection::RIGHT_TO_LEFT);
}
+void MainWindow::closeEvent(QCloseEvent *event)
+{
+ if (isVisible()) {
+ event->ignore();
+ hide();
+ }
+}
+
+void MainWindow::iconActivated(QSystemTrayIcon::ActivationReason reason)
+{
+ switch (reason) {
+ case QSystemTrayIcon::Trigger:
+ if (!isVisible()) {
+ show();
+ } else {
+ hide();
+ }
+ break;
+ default:
+ break;
+ }
+}
+
MainWindow::~MainWindow()
{
}
diff --git a/src/RegisterPage.cc b/src/RegisterPage.cc
index f4c35f2e..d5c60918 100644
--- a/src/RegisterPage.cc
+++ b/src/RegisterPage.cc
@@ -25,6 +25,8 @@ RegisterPage::RegisterPage(QSharedPointer<MatrixClient> client, QWidget *parent)
: QWidget(parent)
, client_(client)
{
+ setStyleSheet("background-color: #f9f9f9");
+
top_layout_ = new QVBoxLayout();
back_layout_ = new QHBoxLayout();
diff --git a/src/TrayIcon.cc b/src/TrayIcon.cc
new file mode 100644
index 00000000..4954044a
--- /dev/null
+++ b/src/TrayIcon.cc
@@ -0,0 +1,93 @@
+/*
+ * nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
+ *
+ * This program is free 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
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <QTimer>
+
+#include "TrayIcon.h"
+
+MsgCountComposedIcon::MsgCountComposedIcon(const QString &filename)
+ : QIconEngine()
+{
+ icon_ = QIcon(filename);
+}
+
+void MsgCountComposedIcon::paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state)
+{
+ icon_.paint(painter, rect, Qt::AlignCenter, mode, state);
+
+ if (msgCount <= 0)
+ return;
+
+ QColor backgroundColor("red");
+ QColor textColor("white");
+
+ QBrush brush;
+ brush.setStyle(Qt::SolidPattern);
+ brush.setColor(backgroundColor);
+
+ painter->setBrush(brush);
+ painter->setPen(Qt::NoPen);
+ painter->setFont(QFont("Open Sans", 7, QFont::Black));
+
+ QRectF bubble(rect.width() - BubbleDiameter,
+ rect.height() - BubbleDiameter,
+ BubbleDiameter,
+ BubbleDiameter);
+ painter->drawEllipse(bubble);
+ painter->setPen(QPen(textColor));
+ painter->setBrush(Qt::NoBrush);
+ painter->drawText(bubble, Qt::AlignCenter, QString::number(msgCount));
+}
+
+QIconEngine *MsgCountComposedIcon::clone() const
+{
+ return new MsgCountComposedIcon(*this);
+}
+
+TrayIcon::TrayIcon(const QString &filename, QWidget *parent)
+ : QSystemTrayIcon(parent)
+{
+ icon_ = new MsgCountComposedIcon(filename);
+ setIcon(QIcon(icon_));
+
+ QMenu *menu = new QMenu(parent);
+ viewAction_ = new QAction("Show", parent);
+ quitAction_ = new QAction("Quit", parent);
+
+ connect(viewAction_, SIGNAL(triggered()), parent, SLOT(show()));
+ connect(quitAction_, SIGNAL(triggered()), parent, SLOT(close()));
+
+ menu->addAction(viewAction_);
+ menu->addAction(quitAction_);
+
+ setContextMenu(menu);
+
+ // We wait a little for the icon to load.
+ QTimer::singleShot(500, this, [=]() {
+ show();
+ });
+}
+
+void TrayIcon::setUnreadCount(int count)
+{
+ MsgCountComposedIcon *tmp = static_cast<MsgCountComposedIcon *>(icon_->clone());
+ tmp->msgCount = count;
+
+ setIcon(QIcon(tmp));
+
+ icon_ = tmp;
+}
|