File indexing completed on 2024-05-12 16:27:35

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