File indexing completed on 2024-12-01 07:42:31

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"