File indexing completed on 2024-12-01 04:37:02

0001 /*
0002    SPDX-FileCopyrightText: 2021-2024 Laurent Montel <montel@kde.org>
0003 
0004    SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "roomwidgetbase.h"
0008 #include "dialogs/createnewdiscussiondialog.h"
0009 #include "messagelinewidget.h"
0010 #include "messagetextedit.h"
0011 #include "readonlylineeditwidget.h"
0012 #include "rocketchataccount.h"
0013 #include "room.h"
0014 #include "roomquotemessagewidget.h"
0015 #include "roomreplythreadwidget.h"
0016 #include "roomutil.h"
0017 #include "uploadfilemanager.h"
0018 #include "uploadfileprogressstatuslistwidget.h"
0019 
0020 #include <QKeyEvent>
0021 #include <QStackedWidget>
0022 #include <QVBoxLayout>
0023 
0024 RoomWidgetBase::RoomWidgetBase(MessageListView::Mode mode, QWidget *parent)
0025     : QWidget(parent)
0026     , mUploadFileProgressStatusListWidget(new UploadFileProgressStatusListWidget(this))
0027     , mMessageListView(new MessageListView(nullptr, mode, this))
0028     , mRoomReplyThreadWidget(new RoomReplyThreadWidget(this))
0029     , mRoomQuoteMessageWidget(new RoomQuoteMessageWidget(this))
0030     , mStackedWidget(new QStackedWidget(this))
0031     , mMessageLineWidget(new MessageLineWidget(this))
0032     , mReadOnlyLineEditWidget(new ReadOnlyLineEditWidget(this))
0033     , mMainLayout(new QVBoxLayout(this))
0034 {
0035     mMainLayout->setObjectName(QStringLiteral("mainLayout"));
0036     mMainLayout->setContentsMargins({});
0037     mMainLayout->setSpacing(0);
0038 
0039     mUploadFileProgressStatusListWidget->setObjectName(QStringLiteral("mUploadFileProgressStatusListWidget"));
0040     mUploadFileProgressStatusListWidget->setVisible(false);
0041     mMainLayout->addWidget(mUploadFileProgressStatusListWidget);
0042     connect(mUploadFileProgressStatusListWidget, &UploadFileProgressStatusListWidget::cancelUpload, this, &RoomWidgetBase::slotCancelUpload);
0043 
0044     mMessageListView->setObjectName(QStringLiteral("mMessageListView"));
0045     mMessageListView->setProperty("_breeze_borders_sides", QVariant::fromValue(QFlags{Qt::TopEdge | Qt::BottomEdge}));
0046     mMainLayout->addWidget(mMessageListView, 1);
0047 
0048     mRoomReplyThreadWidget->setObjectName(QStringLiteral("mRoomReplyThreadWidget"));
0049     mRoomReplyThreadWidget->setVisible(false);
0050 
0051     connect(mRoomReplyThreadWidget, &RoomReplyThreadWidget::cancelReplyingInThread, this, [this] {
0052         mMessageLineWidget->setThreadMessageId({});
0053     });
0054 
0055     mRoomQuoteMessageWidget->setObjectName(QStringLiteral("mRoomQuoteMessageWidget"));
0056     mRoomQuoteMessageWidget->setVisible(false);
0057 
0058     connect(mRoomQuoteMessageWidget, &RoomQuoteMessageWidget::cancelQuoteMessage, this, [this] {
0059         mMessageLineWidget->setQuoteMessage({}, QString());
0060     });
0061 
0062     mMainLayout->addWidget(mRoomReplyThreadWidget);
0063     mMainLayout->addWidget(mRoomQuoteMessageWidget);
0064 
0065     mStackedWidget->setObjectName(QStringLiteral("mStackedWidget"));
0066     mMainLayout->addWidget(mStackedWidget);
0067 
0068     mMessageLineWidget->setObjectName(QStringLiteral("mMessageLineWidget"));
0069     mMessageLineWidget->setProperty("_breeze_borders_sides", QVariant::fromValue(QFlags{Qt::TopEdge}));
0070     mStackedWidget->addWidget(mMessageLineWidget);
0071 
0072     mReadOnlyLineEditWidget->setObjectName(QStringLiteral("mReadOnlyLineEditWidget"));
0073     mStackedWidget->addWidget(mReadOnlyLineEditWidget);
0074 
0075     mStackedWidget->setCurrentWidget(mMessageLineWidget);
0076 
0077     connect(mMessageLineWidget, &MessageLineWidget::keyPressed, this, &RoomWidgetBase::keyPressedInLineEdit);
0078     if (mode == MessageListView::Mode::Editing) {
0079         connect(mMessageLineWidget, &MessageLineWidget::threadMessageIdChanged, this, &RoomWidgetBase::slotShowThreadMessage);
0080     }
0081     connect(mMessageLineWidget, &MessageLineWidget::quoteMessageChanged, this, &RoomWidgetBase::slotShowQuoteMessage);
0082     connect(mMessageLineWidget, &MessageLineWidget::createUploadJob, this, &RoomWidgetBase::slotSendFile);
0083 
0084     connect(mMessageListView, &MessageListView::editMessageRequested, mMessageLineWidget, &MessageLineWidget::setEditMessage);
0085     connect(mMessageListView, &MessageListView::quoteMessageRequested, mMessageLineWidget, &MessageLineWidget::setQuoteMessage);
0086     connect(mMessageListView, &MessageListView::createNewDiscussion, this, &RoomWidgetBase::createNewDiscussion);
0087     connect(mMessageListView, &MessageListView::createPrivateConversation, this, &RoomWidgetBase::slotCreatePrivateDiscussion);
0088     connect(mMessageListView, &MessageListView::loadHistoryRequested, this, &RoomWidgetBase::loadHistory);
0089     connect(mMessageListView, &MessageListView::replyInThreadRequested, mMessageLineWidget, [this](const QString &messageId, const QString &text) {
0090         mMessageLineWidget->setThreadMessageId(messageId, text, false);
0091     });
0092 
0093     connect(mMessageListView, &MessageListView::textToSpeech, this, &RoomWidgetBase::textToSpeech);
0094 
0095     connect(mMessageListView, &MessageListView::errorMessage, this, &RoomWidgetBase::errorMessage);
0096     connect(mMessageListView, &MessageListView::successMessage, this, &RoomWidgetBase::successMessage);
0097     setAcceptDrops(true);
0098 }
0099 
0100 RoomWidgetBase::~RoomWidgetBase() = default;
0101 
0102 void RoomWidgetBase::slotSendFile(const RocketChatRestApi::UploadFileJob::UploadFileInfo &uploadFileInfo)
0103 {
0104     const int identifier = mCurrentRocketChatAccount->uploadFileManager()->addUpload(uploadFileInfo);
0105     if (identifier != -1) {
0106         mUploadFileProgressStatusListWidget->addProgressStatusWidget(identifier);
0107     }
0108 }
0109 
0110 void RoomWidgetBase::slotShowThreadMessage(const QString &threadMessageId, const QString &text)
0111 {
0112     mRoomReplyThreadWidget->setMessageText(text);
0113     mRoomReplyThreadWidget->setVisible(!threadMessageId.isEmpty());
0114 }
0115 
0116 void RoomWidgetBase::slotCancelUpload(int identifier)
0117 {
0118     mCurrentRocketChatAccount->uploadFileManager()->cancelJob(identifier);
0119 }
0120 
0121 MessageListView *RoomWidgetBase::messageListView() const
0122 {
0123     return mMessageListView;
0124 }
0125 
0126 MessageLineWidget *RoomWidgetBase::messageLineWidget() const
0127 {
0128     return mMessageLineWidget;
0129 }
0130 
0131 void RoomWidgetBase::slotShowQuoteMessage(const QString &permalink, const QString &text)
0132 {
0133     mRoomQuoteMessageWidget->setMessageText(text);
0134     mRoomQuoteMessageWidget->setVisible(!permalink.isEmpty());
0135 }
0136 
0137 void RoomWidgetBase::slotCreateNewDiscussion(const QString &messageId, const QString &originalMessage, const QString &channelName)
0138 {
0139     CreateNewDiscussionDialog dlg(mCurrentRocketChatAccount, this);
0140     dlg.setDiscussionName(originalMessage);
0141     dlg.setChannelInfo(channelName, mRoomId);
0142     dlg.setMessageId(messageId);
0143     dlg.exec();
0144 }
0145 
0146 void RoomWidgetBase::closeQuoteAndThreadInfo()
0147 {
0148     mRoomReplyThreadWidget->setVisible(false);
0149     mRoomQuoteMessageWidget->setVisible(false);
0150 }
0151 
0152 void RoomWidgetBase::slotCreatePrivateDiscussion(const QString &userName)
0153 {
0154     Q_EMIT mCurrentRocketChatAccount->openLinkRequested(RoomUtil::generateUserLink(userName));
0155 }
0156 
0157 void RoomWidgetBase::keyPressedInLineEdit(QKeyEvent *ev)
0158 {
0159     const int key = ev->key();
0160     if (key == Qt::Key_Escape) {
0161         if (mRoomReplyThreadWidget->isVisible()) {
0162             Q_EMIT mRoomReplyThreadWidget->cancelReplyingInThread();
0163         } else if (mRoomQuoteMessageWidget->isVisible()) {
0164             Q_EMIT mRoomQuoteMessageWidget->cancelQuoteMessage();
0165         } else {
0166             slotClearNotification();
0167         }
0168         ev->accept();
0169     } else if (ev->matches(QKeySequence::Copy) && mMessageLineWidget->messageTextEdit()->textCursor().selectedText().isEmpty()) {
0170         mMessageListView->copyMessageToClipboard();
0171         ev->accept();
0172     } else {
0173         mMessageListView->handleKeyPressEvent(ev);
0174     }
0175 }
0176 
0177 void RoomWidgetBase::slotUploadProgress(const RocketChatRestApi::UploadFileJob::UploadStatusInfo &info, int jobIdentifier, const QString &accountName)
0178 {
0179     mUploadFileProgressStatusListWidget->uploadProgress(info, jobIdentifier, accountName);
0180 }
0181 
0182 QString RoomWidgetBase::roomId() const
0183 {
0184     return mRoomId;
0185 }
0186 
0187 void RoomWidgetBase::setRoomId(const QString &roomId)
0188 {
0189     mRoomId = roomId;
0190 }
0191 
0192 void RoomWidgetBase::setCurrentRocketChatAccount(RocketChatAccount *account)
0193 {
0194     if (mCurrentRocketChatAccount) {
0195         disconnect(mCurrentRocketChatAccount, &RocketChatAccount::publicSettingChanged, mMessageLineWidget, &MessageLineWidget::slotPublicSettingChanged);
0196         disconnect(mCurrentRocketChatAccount->uploadFileManager(), &UploadFileManager::uploadProgress, this, &RoomWidgetBase::slotUploadProgress);
0197         disconnect(mCurrentRocketChatAccount,
0198                    &RocketChatAccount::ownUserPreferencesChanged,
0199                    mMessageLineWidget,
0200                    &MessageLineWidget::slotOwnUserPreferencesChanged);
0201         // hide it when we switch account.
0202         mUploadFileProgressStatusListWidget->setVisible(false);
0203     }
0204 
0205     mCurrentRocketChatAccount = account;
0206     connect(mCurrentRocketChatAccount, &RocketChatAccount::publicSettingChanged, mMessageLineWidget, &MessageLineWidget::slotPublicSettingChanged);
0207     connect(mCurrentRocketChatAccount->uploadFileManager(), &UploadFileManager::uploadProgress, this, &RoomWidgetBase::slotUploadProgress);
0208     connect(mCurrentRocketChatAccount, &RocketChatAccount::ownUserPreferencesChanged, mMessageLineWidget, &MessageLineWidget::slotOwnUserPreferencesChanged);
0209     mMessageListView->setCurrentRocketChatAccount(account);
0210     mMessageLineWidget->setCurrentRocketChatAccount(account, false);
0211     // When we switch we need to update it.
0212     mMessageLineWidget->slotPublicSettingChanged();
0213     mMessageLineWidget->slotOwnUserPreferencesChanged();
0214     mRoomId.clear(); // Clear it otherwise if we switch between two account with same roomId (as "GENERAL") we will see incorrect room.
0215 }
0216 
0217 void RoomWidgetBase::slotClearNotification()
0218 {
0219     if (!mRoomId.isEmpty()) {
0220         auto room = mCurrentRocketChatAccount->room(mRoomId);
0221         if (room && ((room->unread() > 0) || room->alert())) {
0222             mCurrentRocketChatAccount->markRoomAsRead(mRoomId);
0223         }
0224     }
0225 }
0226 
0227 void RoomWidgetBase::updateListView()
0228 {
0229     mMessageListView->clearTextDocumentCache();
0230     mMessageListView->viewport()->update();
0231 }
0232 
0233 void RoomWidgetBase::updateRoomReadOnly(Room *room)
0234 {
0235     if (room->roomMessageInfo().isEmpty()) {
0236         mStackedWidget->setCurrentWidget(mMessageLineWidget);
0237     } else {
0238         mStackedWidget->setCurrentWidget(mReadOnlyLineEditWidget);
0239         mReadOnlyLineEditWidget->setMessage(room->roomMessageInfo());
0240     }
0241 }
0242 
0243 #include "moc_roomwidgetbase.cpp"