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"