File indexing completed on 2024-12-01 04:36:50

0001 /*
0002  * SPDX-FileCopyrightText: 2020 Olivier de Gaalon <olivier.jg@gmail.com>
0003  *
0004  * SPDX-License-Identifier: LGPL-2.0-or-later
0005  *
0006  */
0007 
0008 #include "accountsoverviewwidget.h"
0009 
0010 #include "accountmanager.h"
0011 #include "model/rocketchataccountmodel.h"
0012 #include "rocketchataccount.h"
0013 #include "ruqola.h"
0014 
0015 #include <KLocalizedString>
0016 
0017 #include <QHBoxLayout>
0018 #include <QIcon>
0019 #include <QTabBar>
0020 
0021 namespace
0022 {
0023 struct UnreadAlert {
0024     int unread = 0;
0025     bool alert = false;
0026 };
0027 
0028 [[nodiscard]] QString currentLoginStatusText(RocketChatAccount *account)
0029 {
0030     if (!account->ddp()->isConnected()) {
0031         return i18n("Not connected");
0032     }
0033     switch (account->loginStatus()) {
0034     case DDPAuthenticationManager::Connecting:
0035         return i18n("Connecting");
0036     case DDPAuthenticationManager::LoginOtpAuthOngoing:
0037         return i18n("Login OTP code required");
0038     case DDPAuthenticationManager::LoginFailedInvalidUserOrPassword:
0039         return i18n("Login failed: invalid username or password");
0040     case DDPAuthenticationManager::LoginOngoing:
0041         return i18n("Logging in");
0042     case DDPAuthenticationManager::LoggedIn:
0043         return i18n("Logged in");
0044     case DDPAuthenticationManager::LoggedOut:
0045         return i18n("Logged out");
0046     case DDPAuthenticationManager::FailedToLoginPluginProblem:
0047         return i18n("Failed to login due to plugin problem");
0048     case DDPAuthenticationManager::GenericError:
0049         return i18n("Login failed: generic error");
0050     case DDPAuthenticationManager::LoginOtpRequired:
0051         return i18n("A one-time password is required to complete the login procedure.");
0052     case DDPAuthenticationManager::LoginFailedInvalidOtp:
0053         return i18n("Login failed: Invalid OTP code.");
0054     case DDPAuthenticationManager::LoginFailedUserNotActivated:
0055         return i18n("Login failed: User is not activated.");
0056     case DDPAuthenticationManager::LoginFailedLoginBlockForIp:
0057         return i18n("Login has been temporarily blocked For IP.");
0058     case DDPAuthenticationManager::LoginFailedLoginBlockedForUser:
0059         return i18n("Login has been temporarily blocked For User.");
0060     case DDPAuthenticationManager::LoginFailedLoginAppNotAllowedToLogin:
0061         return i18n("App user is not allowed to login.");
0062     case DDPAuthenticationManager::LogoutOngoing:
0063     case DDPAuthenticationManager::LogoutCleanUpOngoing:
0064     case DDPAuthenticationManager::LoggedOutAndCleanedUp:
0065         break;
0066     }
0067     return i18n("Unknown state");
0068 }
0069 
0070 [[nodiscard]] UnreadAlert currentUnreadAlert(RocketChatAccount *account)
0071 {
0072     UnreadAlert ua;
0073     account->roomModel()->getUnreadAlertFromAccount(ua.alert, ua.unread);
0074     return ua;
0075 }
0076 
0077 [[nodiscard]] QString currentText(RocketChatAccount *account)
0078 {
0079     QString text = account->displayName();
0080     if (text.isEmpty()) {
0081         text = i18n("(Unnamed)");
0082     }
0083 
0084     if (account->loginStatus() != DDPAuthenticationManager::LoggedIn) {
0085         text += QStringLiteral(": %1").arg(currentLoginStatusText(account));
0086     } else if (int unread = currentUnreadAlert(account).unread) {
0087         text += QStringLiteral(" (%1)").arg(unread);
0088     }
0089 
0090     return text;
0091 }
0092 }
0093 
0094 AccountsOverviewWidget::AccountsOverviewWidget(QWidget *parent)
0095     : QWidget(parent)
0096     , mTabBar(new QTabBar(this))
0097     , mAccountManager(Ruqola::self()->accountManager())
0098 {
0099     mTabBar->setShape(QTabBar::RoundedSouth);
0100     mTabBar->setObjectName(QStringLiteral("mTabBar"));
0101 
0102     auto mainLayout = new QHBoxLayout(this);
0103     mainLayout->setObjectName(QStringLiteral("mainLayout"));
0104     mainLayout->setContentsMargins({});
0105     mainLayout->addWidget(mTabBar);
0106 
0107     const auto model = mAccountManager->rocketChatAccountProxyModel();
0108     connect(model, &QAbstractItemModel::modelReset, this, &AccountsOverviewWidget::updateButtons);
0109     connect(model, &QAbstractItemModel::rowsInserted, this, &AccountsOverviewWidget::updateButtons);
0110     connect(model, &QAbstractItemModel::rowsRemoved, this, &AccountsOverviewWidget::updateButtons);
0111     connect(model, &QAbstractItemModel::rowsMoved, this, &AccountsOverviewWidget::updateButtons);
0112     updateButtons();
0113 
0114     connect(mAccountManager, &AccountManager::currentAccountChanged, this, &AccountsOverviewWidget::updateCurrentTab);
0115 
0116     connect(mTabBar, &QTabBar::currentChanged, this, [this](int i) {
0117         auto account = mTabBar->tabData(i).value<RocketChatAccount *>();
0118         mAccountManager->setCurrentAccount(account ? account->accountName() : QString());
0119     });
0120 }
0121 
0122 AccountsOverviewWidget::~AccountsOverviewWidget() = default;
0123 
0124 void AccountsOverviewWidget::updateButtons()
0125 {
0126     const auto model = mAccountManager->rocketChatAccountProxyModel();
0127     const auto count = model->rowCount();
0128 
0129     for (int i = 0; i < count; ++i) {
0130         if (i == mTabBar->count()) {
0131             mTabBar->addTab({});
0132         }
0133 
0134         auto index = model->index(i, 0);
0135         auto account = index.data(RocketChatAccountModel::Account).value<RocketChatAccount *>();
0136         disconnect(account, nullptr, this, nullptr);
0137         disconnect(account->roomModel(), nullptr, this, nullptr);
0138 
0139         mTabBar->setTabData(i, QVariant::fromValue(account));
0140         mTabBar->setTabVisible(i, account->accountEnabled());
0141 
0142         auto updateTabText = [this, i, account]() {
0143             mTabBar->setTabText(i, currentText(account));
0144         };
0145         auto updateTabToolTip = [this, i, account]() {
0146             mTabBar->setTabToolTip(i, currentLoginStatusText(account));
0147         };
0148         auto updateTabIcon = [this, i, account]() {
0149             QIcon icon;
0150             if (currentUnreadAlert(account).alert) {
0151                 icon = QIcon::fromTheme(QStringLiteral("message-new"));
0152             } else {
0153                 // qDebug() << " FAVICON URL " << account->urlForLink(account->ruqolaServerConfig()->faviconUrl()) << " ACCOUNTNAME " << account->accountName();
0154                 const QString iconFaviconUrl{account->attachmentUrlFromLocalCache(account->ruqolaServerConfig()->faviconUrl().url).toLocalFile()};
0155                 if (!iconFaviconUrl.isEmpty()) {
0156                     const QIcon iconFavicon{iconFaviconUrl};
0157                     if (!iconFavicon.isNull()) {
0158                         icon = std::move(iconFavicon);
0159                     }
0160                 }
0161             }
0162             mTabBar->setTabIcon(i, icon);
0163         };
0164         connect(account, &RocketChatAccount::accountNameChanged, this, updateTabText);
0165         connect(account, &RocketChatAccount::loginStatusChanged, this, [updateTabText, updateTabToolTip]() {
0166             updateTabText();
0167             updateTabToolTip();
0168         });
0169         connect(account->roomModel(), &RoomModel::needToUpdateNotification, this, [updateTabText, updateTabIcon]() {
0170             updateTabText();
0171             updateTabIcon();
0172         });
0173 
0174         updateTabText();
0175         updateTabToolTip();
0176         updateTabIcon();
0177     }
0178 
0179     while (mTabBar->count() > count) {
0180         mTabBar->removeTab(count);
0181     }
0182 
0183     updateCurrentTab();
0184 }
0185 
0186 void AccountsOverviewWidget::updateCurrentTab()
0187 {
0188     auto account = mAccountManager->account();
0189     auto tabIndex = [this, account]() {
0190         for (int i = 0, c = mTabBar->count(); i < c; ++i) {
0191             if (mTabBar->tabData(i).value<RocketChatAccount *>() == account) {
0192                 return i;
0193             }
0194         }
0195         return -1;
0196     };
0197     mTabBar->setCurrentIndex(tabIndex());
0198 }
0199 
0200 void AccountsOverviewWidget::showNextView()
0201 {
0202     goToView(mTabBar->currentIndex() + 1);
0203 }
0204 
0205 void AccountsOverviewWidget::showPreviousView()
0206 {
0207     goToView(mTabBar->currentIndex() - 1);
0208 }
0209 
0210 void AccountsOverviewWidget::goToView(int index)
0211 {
0212     if (index >= 0 && index < mTabBar->count()) {
0213         auto rocketChatAccount = mTabBar->tabData(index).value<RocketChatAccount *>();
0214         if (rocketChatAccount) {
0215             mAccountManager->setCurrentAccount(rocketChatAccount->accountName());
0216         }
0217     }
0218 }
0219 
0220 #include "moc_accountsoverviewwidget.cpp"