File indexing completed on 2024-12-01 04:37:06
0001 /* 0002 SPDX-FileCopyrightText: 2020-2024 Laurent Montel <montel@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "ruqolamainwidget.h" 0008 #include "bannerinfodialog/bannermessagewidget.h" 0009 #include "channellist/channellistview.h" 0010 #include "channellist/channellistwidget.h" 0011 #include "config-ruqola.h" 0012 #include "model/switchchannelhistorymodel.h" 0013 #include "needupdateversion/needupdateversionwidget.h" 0014 #include "rocketchataccount.h" 0015 #include "rocketchataccountsettings.h" 0016 #include "room/roomwidget.h" 0017 #include "ruqolawidgets_debug.h" 0018 0019 #include <KConfigGroup> 0020 #include <KSharedConfig> 0021 #include <QHBoxLayout> 0022 #include <QSplitter> 0023 0024 #include "model/roomfilterproxymodel.h" 0025 #include "model/roommodel.h" 0026 0027 #include <algorithm> 0028 0029 namespace 0030 { 0031 static const char myRuqolaMainWidgetGroupName[] = "RuqolaMainWidget"; 0032 } 0033 0034 RuqolaMainWidget::RuqolaMainWidget(QWidget *parent) 0035 : QWidget(parent) 0036 , mSplitter(new QSplitter(this)) 0037 , mChannelList(new ChannelListWidget(this)) 0038 , mStackedRoomWidget(new QStackedWidget(this)) 0039 , mRoomWidget(new RoomWidget(this)) 0040 , mEmptyRoomWidget(new QWidget(this)) 0041 , mTopLayout(new QVBoxLayout(this)) 0042 { 0043 mTopLayout->setContentsMargins({}); 0044 mTopLayout->setObjectName(QStringLiteral("topLayout")); 0045 0046 auto mainLayout = new QHBoxLayout; 0047 mainLayout->setContentsMargins({}); 0048 mainLayout->setObjectName(QStringLiteral("mainlayout")); 0049 0050 mTopLayout->addLayout(mainLayout); 0051 0052 mSplitter->setObjectName(QStringLiteral("mSplitter")); 0053 mSplitter->setChildrenCollapsible(false); 0054 mainLayout->addWidget(mSplitter); 0055 0056 mChannelList->setObjectName(QStringLiteral("mChannelList")); 0057 mChannelList->setLayoutSpacing(mSplitter->handleWidth()); 0058 mSplitter->addWidget(mChannelList); 0059 0060 mStackedRoomWidget->setObjectName(QStringLiteral("mStackedRoomWidget")); 0061 mSplitter->addWidget(mStackedRoomWidget); 0062 0063 mRoomWidget->setObjectName(QStringLiteral("mRoomWidget")); 0064 mRoomWidget->setLayoutSpacing(mSplitter->handleWidth()); 0065 mStackedRoomWidget->addWidget(mRoomWidget); 0066 connect(mRoomWidget, &RoomWidget::selectChannelRequested, this, [this](const QString &channelId) { 0067 mChannelList->channelListView()->selectChannelRequested(channelId, QString()); 0068 }); 0069 0070 mEmptyRoomWidget->setObjectName(QStringLiteral("mEmptyRoomWidget")); 0071 mStackedRoomWidget->addWidget(mEmptyRoomWidget); 0072 0073 mStackedRoomWidget->setCurrentWidget(mEmptyRoomWidget); 0074 0075 connect(mChannelList, &ChannelListWidget::roomSelected, this, &RuqolaMainWidget::selectChannelRoom); 0076 connect(mChannelList, &ChannelListWidget::roomPressed, this, &RuqolaMainWidget::slotRoomPressed); 0077 connect(mChannelList, &ChannelListWidget::selectMessageIdRequested, mRoomWidget, &RoomWidget::scrollToMessageId); 0078 0079 KConfigGroup group(KSharedConfig::openConfig(), QLatin1String(myRuqolaMainWidgetGroupName)); 0080 mSplitter->restoreState(group.readEntry("SplitterSizes", QByteArray())); 0081 if (NeedUpdateVersionUtils::checkVersion()) { 0082 const auto status = NeedUpdateVersionUtils::obsoleteVersionStatus(QLatin1String(RUQOLA_RELEASE_VERSION), QDate::currentDate()); 0083 if (status != NeedUpdateVersionUtils::ObsoleteVersion::NotObsoleteYet) { 0084 auto needUpdateVersionWidget = new NeedUpdateVersionWidget(this); 0085 needUpdateVersionWidget->setObjectName(QStringLiteral("needUpdateVersionWidget")); 0086 mTopLayout->insertWidget(0, needUpdateVersionWidget); 0087 needUpdateVersionWidget->setObsoleteVersion(status); 0088 } 0089 } 0090 } 0091 0092 RuqolaMainWidget::~RuqolaMainWidget() 0093 { 0094 KConfigGroup group(KSharedConfig::openConfig(), QLatin1String(myRuqolaMainWidgetGroupName)); 0095 group.writeEntry("SplitterSizes", mSplitter->saveState()); 0096 if (mCurrentRocketChatAccount) { 0097 mCurrentRocketChatAccount->settings()->setLastSelectedRoom(mRoomWidget->roomId()); 0098 } 0099 } 0100 0101 void RuqolaMainWidget::createBannerMessageWidget() 0102 { 0103 mBannerMessageWidget = new BannerMessageWidget(this); 0104 mBannerMessageWidget->setObjectName(QStringLiteral("mBannerMessageWidget")); 0105 mTopLayout->insertWidget(0, mBannerMessageWidget); 0106 connect(mBannerMessageWidget, &BannerMessageWidget::infoWasRead, this, &RuqolaMainWidget::slotMarkBannerAsRead); 0107 } 0108 0109 void RuqolaMainWidget::slotRoomPressed(const QString &roomId) 0110 { 0111 if (mRoomWidget->roomId() == roomId) { 0112 // force select lineedit 0113 mRoomWidget->forceLineEditFocus(); 0114 } 0115 } 0116 0117 void RuqolaMainWidget::selectChannelRoom(const ChannelListView::ChannelSelectedInfo &roomInfo) 0118 { 0119 if (mRoomWidget->roomId() == roomInfo.roomId) { 0120 return; 0121 } 0122 mCurrentRocketChatAccount->settings()->setLastSelectedRoom(roomInfo.roomId); 0123 mRoomWidget->setChannelSelected(roomInfo.roomId, roomInfo.roomType); 0124 mStackedRoomWidget->setCurrentWidget(mRoomWidget); 0125 const SwitchChannelHistoryModel::SwitchChannelInfo info{roomInfo.roomName, roomInfo.roomId, roomInfo.avatarInfo}; 0126 // TODO add icons 0127 mCurrentRocketChatAccount->switchChannelHistoryModel()->addHistory(info); 0128 Q_EMIT channelSelected(); 0129 } 0130 0131 void RuqolaMainWidget::selectNextUnreadChannel() 0132 { 0133 if (mChannelList && mChannelList->channelListView()) { 0134 mChannelList->channelListView()->selectNextUnreadChannel(); 0135 } 0136 } 0137 0138 Room *RuqolaMainWidget::room() const 0139 { 0140 return mRoomWidget->room(); 0141 } 0142 0143 QString RuqolaMainWidget::roomId() const 0144 { 0145 return mRoomWidget->roomId(); 0146 } 0147 0148 Room::RoomType RuqolaMainWidget::roomType() const 0149 { 0150 return mRoomWidget->roomType(); 0151 } 0152 0153 void RuqolaMainWidget::setCurrentRocketChatAccount(RocketChatAccount *account) 0154 { 0155 // Before switching rocketchataccount otherwise 0156 mRoomWidget->storeRoomSettings(); 0157 const auto previousRocketChatAccount = mCurrentRocketChatAccount; 0158 if (mCurrentRocketChatAccount) { 0159 mCurrentRocketChatAccount->settings()->setLastSelectedRoom(mRoomWidget->roomId()); 0160 disconnect(mCurrentRocketChatAccount, &RocketChatAccount::bannerInfoChanged, this, &RuqolaMainWidget::updateBannerInfo); 0161 } 0162 mCurrentRocketChatAccount = account; 0163 connect(mCurrentRocketChatAccount, &RocketChatAccount::bannerInfoChanged, this, &RuqolaMainWidget::updateBannerInfo); 0164 mChannelList->setCurrentRocketChatAccount(account); 0165 mRoomWidget->setCurrentRocketChatAccount(account); 0166 mStackedRoomWidget->setCurrentWidget(mEmptyRoomWidget); 0167 0168 // This is for switching between already-loaded accounts 0169 // On startup it's too early 0170 if (previousRocketChatAccount) { 0171 mChannelList->channelListView()->selectChannelRequested(mCurrentRocketChatAccount->settings()->lastSelectedRoom(), QString()); 0172 } 0173 0174 updateBannerInfo(); 0175 } 0176 0177 void RuqolaMainWidget::slotMarkBannerAsRead(const QString &identifier) 0178 { 0179 #if 1 0180 mCurrentRocketChatAccount->ddp()->bannerDismiss(identifier); 0181 // qDebug() << " identifier " << identifier; 0182 #else 0183 auto job = new RocketChatRestApi::BannersDismissJob(this); 0184 job->setBannerId(identifier); 0185 mCurrentRocketChatAccount->restApi()->initializeRestApiJob(job); 0186 connect(job, &RocketChatRestApi::BannersDismissJob::dimissBannerDone, this, &RuqolaMainWidget::slotBannerDismissDone); 0187 if (!job->start()) { 0188 qCWarning(RUQOLAWIDGETS_LOG) << "Impossible to start BannersDismissJob job"; 0189 } 0190 #endif 0191 } 0192 0193 void RuqolaMainWidget::slotBannerDismissDone() 0194 { 0195 qDebug() << "void RuqolaMainWidget::slotBannerDismissDone()"; 0196 } 0197 0198 void RuqolaMainWidget::updateBannerInfo() 0199 { 0200 if (!mBannerMessageWidget) { 0201 createBannerMessageWidget(); 0202 } 0203 const auto bannerUnreadInformations = mCurrentRocketChatAccount->bannerInfos().bannerUnreadInformations(); 0204 mBannerMessageWidget->setBannerInfos(std::move(bannerUnreadInformations)); 0205 } 0206 0207 void RuqolaMainWidget::showEvent(QShowEvent *event) 0208 { 0209 QWidget::showEvent(event); 0210 0211 // HACK: beautify the GUI by aligning a couple of items 0212 auto searchRoom = mChannelList->findChild<QWidget *>(QStringLiteral("mSearchRoom")); 0213 if (!searchRoom) { 0214 qCWarning(RUQOLAWIDGETS_LOG) << "Failed to find mSearchRoom" << searchRoom; 0215 return; 0216 } 0217 0218 auto messageLine = mRoomWidget->findChild<QWidget *>(QStringLiteral("mMessageLineWidget")); 0219 if (!messageLine) { 0220 qCWarning(RUQOLAWIDGETS_LOG) << "Failed to find mMessageLineWidget" << messageLine; 0221 return; 0222 } 0223 0224 auto align = [](QWidget *left, QWidget *right) { 0225 // the widgets on the right can be much taller, but usually are 0226 // just a few pixels shorter than the corresponding row on the left 0227 // so we just want to grow the right widget to the minimum height 0228 // of the left widget 0229 const auto minHeight = std::max(left->minimumSizeHint().height(), right->minimumSizeHint().height()); 0230 right->setMinimumHeight(minHeight); 0231 }; 0232 align(searchRoom, messageLine); 0233 } 0234 0235 #include "moc_ruqolamainwidget.cpp"