diff --git a/src/widgets/CMakeLists.txt b/src/widgets/CMakeLists.txt
--- a/src/widgets/CMakeLists.txt
+++ b/src/widgets/CMakeLists.txt
@@ -90,6 +90,7 @@
set(Ruqola_misc_widget_SRCS
misc/accountmenu.cpp
+ misc/accountsoverviewwidget.cpp
misc/emoticonmenuwidget.cpp
misc/emoticonselectorwidget.cpp
)
diff --git a/src/widgets/misc/accountsoverviewwidget.h b/src/widgets/misc/accountsoverviewwidget.h
new file mode 100644
--- /dev/null
+++ b/src/widgets/misc/accountsoverviewwidget.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2020 Olivier de Gaalon
+ *
+ * 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 2 of
+ * the License or (at your option) version 3 or any later version
+ * accepted by the membership of KDE e.V. (or its successor approved
+ * by the membership of KDE e.V.), which shall act as a proxy
+ * defined in Section 14 of version 3 of the license.
+ *
+ * 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 .
+ *
+ */
+
+#pragma once
+
+#include
+#include
+
+class AccountButton;
+
+class AccountsOverviewWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ AccountsOverviewWidget(QWidget *parent = nullptr);
+
+private:
+ void updateButtons();
+
+private:
+ QVector mAccounts;
+};
diff --git a/src/widgets/misc/accountsoverviewwidget.cpp b/src/widgets/misc/accountsoverviewwidget.cpp
new file mode 100644
--- /dev/null
+++ b/src/widgets/misc/accountsoverviewwidget.cpp
@@ -0,0 +1,216 @@
+/*
+ * Copyright 2020 Olivier de Gaalon
+ *
+ * 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 2 of
+ * the License or (at your option) version 3 or any later version
+ * accepted by the membership of KDE e.V. (or its successor approved
+ * by the membership of KDE e.V.), which shall act as a proxy
+ * defined in Section 14 of version 3 of the license.
+ *
+ * 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 .
+ *
+ */
+
+#include "accountsoverviewwidget.h"
+
+#include "accountmanager.h"
+#include "model/rocketchataccountmodel.h"
+#include "rocketchataccount.h"
+#include "ruqola.h"
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+constexpr const double PAD = 0.2;
+
+class AccountButton : public QAbstractButton
+{
+ struct UnreadAlert
+ {
+ int unread;
+ bool alert;
+ };
+
+public:
+ AccountButton(QWidget *parent = nullptr)
+ : QAbstractButton(parent)
+ , mAccount(nullptr)
+ {
+ setMouseTracking(true);
+ setFocusPolicy(Qt::NoFocus);
+ setAttribute(Qt::WA_Hover);
+ }
+
+ void setAccount(RocketChatAccount *acct)
+ {
+ if (mAccount)
+ {
+ mAccount->disconnect(this);
+ mAccount->roomModel()->disconnect(this);
+ this->disconnect(acct);
+ }
+
+ mAccount = acct;
+
+ if (mAccount)
+ {
+ auto updateFont = [this]{
+ QFont f = font();
+ f.setBold(currentUnreadAlert().alert);
+ setFont(f);
+ };
+ connect(acct, &RocketChatAccount::accountNameChanged, this, &AccountButton::updateGeometry);
+ connect(acct, &RocketChatAccount::loginStatusChanged, this, &AccountButton::updateGeometry);
+ connect(acct, &RocketChatAccount::loginStatusChanged, this, &AccountButton::updateTooltip);
+ connect(acct->roomModel(), &RoomModel::needToUpdateNotification, this, updateFont);
+ connect(this, &AccountButton::clicked, acct, [acct]{
+ Ruqola::self()->accountManager()->setCurrentAccount(acct->accountName());
+ });
+
+ updateFont();
+ }
+ update();
+ }
+
+ QSize sizeHint() const override
+ {
+ const double height = fontMetrics().height();
+ const double padding = height * PAD;
+ const QSize text = fontMetrics().boundingRect(currentText()).size();
+ return QSize(text.width() + padding * 2, height + padding * 2);
+ }
+
+protected:
+ void enterEvent(QEvent *event) override
+ {
+ if (isEnabled())
+ update();
+ QAbstractButton::enterEvent(event);
+ }
+
+ void leaveEvent(QEvent *event) override
+ {
+ if (isEnabled())
+ update();
+ QAbstractButton::leaveEvent(event);
+ }
+
+ void paintEvent(QPaintEvent *) override
+ {
+ if (!mAccount)
+ return;
+
+ QPainter p(this);
+
+ {
+ QStyleOption opt;
+ opt.init(this);
+ if (isDown())
+ opt.state |= QStyle::State_Sunken;
+ style()->drawPrimitive(QStyle::PE_PanelButtonTool, &opt, &p, this);
+ }
+
+ p.setPen(palette().color(QPalette::WindowText));
+ p.setFont(font());
+ p.drawText(rect(), Qt::AlignCenter, currentText());
+ }
+
+private:
+ QString currentText() const
+ {
+ QString text = mAccount->accountName();
+ if (text.isEmpty())
+ text = i18n("(Unnamed)");
+
+ if (mAccount->loginStatus() != DDPClient::LoggedIn)
+ text += QStringLiteral(": %1").arg(currentLoginStatusText());
+ else if (int unread = currentUnreadAlert().unread)
+ text += QStringLiteral(" (%1)").arg(unread);
+
+ return text;
+ }
+
+ UnreadAlert currentUnreadAlert() const
+ {
+ UnreadAlert ua = {0, false};
+ mAccount->roomModel()->getUnreadAlertFromAccount(ua.alert, ua.unread);
+ return ua;
+ }
+
+ QString currentLoginStatusText() const
+ {
+ if (mAccount)
+ {
+ switch (mAccount->loginStatus())
+ {
+ case DDPClient::NotConnected:
+ return i18n("Not connected");
+ case DDPClient::LoginCodeRequired:
+ return i18n("Login code required");
+ case DDPClient::LoginFailed:
+ return i18n("Login failed");
+ case DDPClient::LoggingIn:
+ return i18n("Logging in");
+ case DDPClient::LoggedIn:
+ return i18n("Logged in");
+ case DDPClient::LoggedOut:
+ return i18n("Logged out");
+ case DDPClient::FailedToLoginPluginProblem:
+ return i18n("Failed to login due to plugin problem");
+ }
+ }
+ return i18n("Unknown state");
+ }
+
+ void updateTooltip()
+ {
+ setToolTip(currentLoginStatusText());
+ }
+
+ QPointer mAccount;
+};
+
+AccountsOverviewWidget::AccountsOverviewWidget(QWidget *parent)
+ : QWidget(parent)
+{
+ setLayout(new QHBoxLayout);
+ const auto model = Ruqola::self()->accountManager()->rocketChatAccountModel();
+ connect(model, &RocketChatAccountModel::rowsInserted, this, &AccountsOverviewWidget::updateButtons);
+ connect(model, &RocketChatAccountModel::rowsRemoved, this, &AccountsOverviewWidget::updateButtons);
+ connect(model, &RocketChatAccountModel::modelReset, this, &AccountsOverviewWidget::updateButtons);
+ updateButtons();
+}
+
+void AccountsOverviewWidget::updateButtons()
+{
+ const auto model = Ruqola::self()->accountManager()->rocketChatAccountModel();
+ const auto count = model->rowCount();
+ for (int i = 0; i < count; ++i)
+ {
+ if (i >= mAccounts.size())
+ {
+ mAccounts.append(new AccountButton(this));
+ layout()->addWidget(mAccounts.last());
+ }
+ mAccounts[i]->setAccount(model->account(i));
+ }
+ for (int i = count; i < mAccounts.size(); ++i)
+ {
+ mAccounts[i]->deleteLater();
+ }
+ mAccounts.resize(count);
+}
diff --git a/src/widgets/ruqolamainwindow.cpp b/src/widgets/ruqolamainwindow.cpp
--- a/src/widgets/ruqolamainwindow.cpp
+++ b/src/widgets/ruqolamainwindow.cpp
@@ -26,6 +26,7 @@
#include "ruqolamainwindow.h"
#include "ruqolacentralwidget.h"
#include "misc/accountmenu.h"
+#include "misc/accountsoverviewwidget.h"
#include "dialogs/serverinfodialog.h"
#include "dialogs/searchchanneldialog.h"
#include "dialogs/createnewchanneldialog.h"
@@ -86,6 +87,7 @@
mStatusBarTypingMessage->setTextFormat(Qt::RichText);
mStatusBarTypingMessage->setObjectName(QStringLiteral("mStatusBarTypingMessage"));
statusBar()->addPermanentWidget(mStatusBarTypingMessage);
+ statusBar()->addPermanentWidget(new AccountsOverviewWidget(this));
}
void RuqolaMainWindow::slotAccountChanged()