File indexing completed on 2024-05-12 16:27:33
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 "messagelinewidget.h" 0008 #if QT_VERSION > QT_VERSION_CHECK(6, 0, 0) 0009 #include "dialogs/createsoundmessagewizard.h" 0010 #include "dialogs/createvideomessagewizard.h" 0011 #endif 0012 #include "messagemaximumsizedialog/messagemaximumsizedialog.h" 0013 #include "messagetextedit.h" 0014 #include "misc/emoticonmenuwidget.h" 0015 #include "ownuser/ownuserpreferences.h" 0016 #include "rocketchataccount.h" 0017 #include "ruqolaglobalconfig.h" 0018 #include "ruqolaserverconfig.h" 0019 #include "ruqolawidgets_debug.h" 0020 0021 #include <KLocalizedString> 0022 #include <KMessageBox> 0023 #include <QMimeDatabase> 0024 0025 #include <KIO/Global> 0026 #include <QClipboard> 0027 #include <QDir> 0028 #include <QGuiApplication> 0029 #include <QHBoxLayout> 0030 #include <QImageWriter> 0031 #include <QMenu> 0032 #include <QMimeData> 0033 #include <QScreen> 0034 #include <QTemporaryFile> 0035 #include <QToolButton> 0036 #include <QWidgetAction> 0037 0038 MessageLineWidget::MessageLineWidget(QWidget *parent) 0039 : QWidget(parent) 0040 , mMessageTextEdit(new MessageTextEdit(this)) 0041 , mSendFileButton(new QToolButton(this)) 0042 , mEmoticonButton(new QToolButton(this)) 0043 , mSendMessageButton(new QToolButton(this)) 0044 , mVideoMessageButton(new QToolButton(this)) 0045 , mSoundMessageButton(new QToolButton(this)) 0046 { 0047 auto mainLayout = new QHBoxLayout(this); 0048 mainLayout->setObjectName(QStringLiteral("mainLayout")); 0049 mainLayout->setContentsMargins({}); 0050 mainLayout->setSpacing(0); 0051 0052 mMessageTextEdit->setObjectName(QStringLiteral("mMessageTextEdit")); 0053 mainLayout->addWidget(mMessageTextEdit); 0054 connect(mMessageTextEdit, &MessageTextEdit::sendMessage, this, &MessageLineWidget::slotSendMessage); 0055 connect(mMessageTextEdit, &MessageTextEdit::keyPressed, this, &MessageLineWidget::keyPressedInLineEdit); 0056 connect(mMessageTextEdit, &MessageTextEdit::textEditing, this, &MessageLineWidget::slotTextEditing); 0057 connect(mMessageTextEdit, &MessageTextEdit::textClicked, this, &MessageLineWidget::textEditClicked); 0058 0059 mSendFileButton->setAutoRaise(true); 0060 mSendFileButton->setObjectName(QStringLiteral("mSendFileButton")); 0061 mainLayout->addWidget(mSendFileButton); 0062 #ifndef QT_NO_ACCESSIBILITY 0063 mSendFileButton->setAccessibleName(i18n("Attach File")); 0064 #endif 0065 0066 mSendFileButton->setIcon(QIcon::fromTheme(QStringLiteral("document-send-symbolic"))); 0067 connect(mSendFileButton, &QToolButton::clicked, this, &MessageLineWidget::slotSendFile); 0068 0069 mVideoMessageButton->setAutoRaise(true); 0070 mVideoMessageButton->setObjectName(QStringLiteral("mVideoMessageButton")); 0071 #ifndef QT_NO_ACCESSIBILITY 0072 mVideoMessageButton->setAccessibleName(i18n("Video Message")); 0073 #endif 0074 0075 mainLayout->addWidget(mVideoMessageButton); 0076 mVideoMessageButton->setIcon(QIcon::fromTheme(QStringLiteral("camera-video"))); 0077 connect(mVideoMessageButton, &QToolButton::clicked, this, &MessageLineWidget::slotSendVideoMessage); 0078 0079 mSoundMessageButton->setAutoRaise(true); 0080 mSoundMessageButton->setObjectName(QStringLiteral("mSoundMessageButton")); 0081 #ifndef QT_NO_ACCESSIBILITY 0082 mSoundMessageButton->setAccessibleName(i18n("Sound Message")); 0083 #endif 0084 0085 mainLayout->addWidget(mSoundMessageButton); 0086 mSoundMessageButton->setIcon(QIcon::fromTheme(QStringLiteral("audio-input-microphone"))); 0087 connect(mSoundMessageButton, &QToolButton::clicked, this, &MessageLineWidget::slotSendSoundMessage); 0088 0089 mEmoticonButton->setAutoRaise(true); 0090 mEmoticonButton->setObjectName(QStringLiteral("mEmoticonButton")); 0091 mEmoticonButton->setIcon(QIcon::fromTheme(QStringLiteral("smiley-add"))); 0092 mEmoticonButton->setPopupMode(QToolButton::InstantPopup); 0093 #ifndef QT_NO_ACCESSIBILITY 0094 mEmoticonButton->setAccessibleName(i18n("Add Emoticon")); 0095 #endif 0096 mainLayout->addWidget(mEmoticonButton); 0097 0098 mSendMessageButton->setAutoRaise(true); 0099 mSendMessageButton->setObjectName(QStringLiteral("mSendMessageButton")); 0100 mSendMessageButton->setIcon(QIcon::fromTheme(QStringLiteral("mail-sent"))); 0101 #ifndef QT_NO_ACCESSIBILITY 0102 mSendMessageButton->setAccessibleName(i18n("Send Message")); 0103 #endif 0104 mainLayout->addWidget(mSendMessageButton); 0105 mSendMessageButton->setEnabled(false); 0106 connect(mSendMessageButton, &QToolButton::clicked, this, [this]() { 0107 slotSendMessage(mMessageTextEdit->text()); 0108 mMessageTextEdit->clear(); 0109 }); 0110 0111 auto emoticonMenu = new QMenu(this); 0112 auto action = new QWidgetAction(emoticonMenu); 0113 mEmoticonMenuWidget = new EmoticonMenuWidget(this); 0114 action->setDefaultWidget(mEmoticonMenuWidget); 0115 emoticonMenu->addAction(action); 0116 mEmoticonButton->setMenu(emoticonMenu); 0117 connect(emoticonMenu, &QMenu::aboutToShow, mEmoticonMenuWidget, &EmoticonMenuWidget::forceLineEditFocus); 0118 connect(mEmoticonMenuWidget, &EmoticonMenuWidget::insertEmojiIdentifier, mMessageTextEdit, &MessageTextEdit::insertEmoji); 0119 connect(mMessageTextEdit, &MessageTextEdit::handleMimeData, this, &MessageLineWidget::handleMimeData); 0120 0121 setFocusProxy(mMessageTextEdit); 0122 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0123 mVideoMessageButton->setVisible(false); 0124 mSoundMessageButton->setVisible(false); 0125 #endif 0126 } 0127 0128 MessageLineWidget::~MessageLineWidget() = default; 0129 0130 void MessageLineWidget::slotSendMessage(const QString &msg) 0131 { 0132 if (!msg.isEmpty()) { 0133 if (mMessageIdBeingEdited.isEmpty() && mQuotePermalink.isEmpty()) { 0134 if (msg.startsWith(QLatin1Char('/'))) { 0135 // a command ? 0136 if (mCurrentRocketChatAccount->runCommand(msg, roomId(), mThreadMessageId)) { 0137 setMode(MessageLineWidget::EditingMode::NewMessage); 0138 return; 0139 } 0140 } 0141 if (msg.size() > mCurrentRocketChatAccount->messageMaximumAllowedSize()) { 0142 if (mCurrentRocketChatAccount->messageAllowConvertLongMessagesToAttachment()) { 0143 if (KMessageBox::ButtonCode::PrimaryAction 0144 == KMessageBox::questionTwoActions(this, 0145 i18n("Do you want to convert this big text as attachment?"), 0146 i18nc("@title:window", "Message Too Big"), 0147 KStandardGuiItem::ok(), 0148 KStandardGuiItem::cancel())) { 0149 QPointer<MessageMaximumSizeDialog> dlg = new MessageMaximumSizeDialog(this); 0150 if (dlg->exec()) { 0151 QTemporaryFile tempFile(QDir::tempPath() + QStringLiteral("/XXXXXX.txt")); 0152 tempFile.setAutoRemove(false); 0153 if (tempFile.open()) { 0154 QTextStream stream(&tempFile); 0155 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0156 stream.setCodec("UTF-8"); 0157 #endif 0158 stream << msg; 0159 tempFile.close(); 0160 0161 QFile f(tempFile.fileName()); 0162 if (!f.rename(dlg->fileName())) { 0163 qCWarning(RUQOLAWIDGETS_LOG) << "Rename file failed" << tempFile.fileName() << " dlg->fileName()" << dlg->fileName(); 0164 } 0165 UploadFileDialog::UploadFileInfo uploadFileInfo; 0166 uploadFileInfo.description = dlg->description(); 0167 uploadFileInfo.fileUrl = QUrl::fromLocalFile(f.fileName()); 0168 uploadFileInfo.deleteTemporaryFile = true; 0169 sendFile(uploadFileInfo); 0170 } 0171 } 0172 delete dlg; 0173 // We need to send as file here. 0174 return; 0175 } else { 0176 return; 0177 } 0178 } else { 0179 return; 0180 } 0181 } 0182 if (mThreadMessageId.isEmpty()) { 0183 mCurrentRocketChatAccount->sendMessage(roomId(), msg); 0184 } else { 0185 mCurrentRocketChatAccount->replyOnThread(roomId(), mThreadMessageId, msg); 0186 if (!mReplyInThreadDialogBox) { 0187 setThreadMessageId({}); 0188 } 0189 } 0190 } else if (!mMessageIdBeingEdited.isEmpty()) { 0191 // TODO check message size 0192 mCurrentRocketChatAccount->updateMessage(roomId(), mMessageIdBeingEdited, msg); 0193 clearMessageIdBeingEdited(); 0194 } else if (!mQuotePermalink.isEmpty()) { 0195 const QString newMessage = QStringLiteral("[ ](%1) %2").arg(mQuotePermalink, msg); 0196 if (mThreadMessageId.isEmpty()) { 0197 mCurrentRocketChatAccount->sendMessage(roomId(), newMessage); 0198 } else { 0199 mCurrentRocketChatAccount->replyOnThread(roomId(), mThreadMessageId, newMessage); 0200 if (!mReplyInThreadDialogBox) { 0201 setThreadMessageId({}); 0202 } 0203 } 0204 setQuoteMessage({}, {}); 0205 clearMessageIdBeingEdited(); 0206 } 0207 setMode(MessageLineWidget::EditingMode::NewMessage); 0208 } 0209 } 0210 0211 void MessageLineWidget::sendFile(const UploadFileDialog::UploadFileInfo &uploadFileInfo) 0212 { 0213 RocketChatRestApi::UploadFileJob::UploadFileInfo info; 0214 info.description = uploadFileInfo.description; 0215 info.messageText = QString(); 0216 info.filenameUrl = uploadFileInfo.fileUrl; 0217 info.roomId = roomId(); 0218 info.threadMessageId = mThreadMessageId; 0219 info.fileName = uploadFileInfo.fileName; 0220 info.deleteTemporaryFile = uploadFileInfo.deleteTemporaryFile; 0221 0222 Q_EMIT createUploadJob(info); 0223 } 0224 0225 void MessageLineWidget::setQuoteMessage(const QString &permalink, const QString &text) 0226 { 0227 clearMessageIdBeingEdited(); 0228 mQuotePermalink = permalink; 0229 mQuoteText = text; 0230 Q_EMIT quoteMessageChanged(mQuotePermalink, text); 0231 } 0232 0233 void MessageLineWidget::clearEditingMode() 0234 { 0235 // Remove old mark as editing 0236 MessagesModel *model = messageModel(); 0237 const QModelIndex index = model->indexForMessage(mMessageIdBeingEdited); 0238 if (index.isValid()) { 0239 model->setData(index, false, MessagesModel::MessageInEditMode); 0240 } 0241 } 0242 0243 QString MessageLineWidget::quoteText() const 0244 { 0245 return mQuoteText; 0246 } 0247 0248 QString MessageLineWidget::quotePermalink() const 0249 { 0250 return mQuotePermalink; 0251 } 0252 0253 void MessageLineWidget::clearMessageIdBeingEdited() 0254 { 0255 MessagesModel *model = messageModel(); 0256 if (!mMessageIdBeingEdited.isEmpty()) { 0257 const QModelIndex index = model->indexForMessage(mMessageIdBeingEdited); 0258 if (index.isValid()) { 0259 model->setData(index, false, MessagesModel::MessageInEditMode); 0260 } 0261 mMessageIdBeingEdited.clear(); 0262 } 0263 mQuotePermalink.clear(); 0264 mQuoteText.clear(); 0265 setText(QString()); 0266 setMode(MessageLineWidget::EditingMode::NewMessage); 0267 } 0268 0269 void MessageLineWidget::setEditMessage(const QString &messageId, const QString &text) 0270 { 0271 // Remove old mark as editing 0272 clearEditingMode(); 0273 mMessageIdBeingEdited = messageId; 0274 if (!mMessageIdBeingEdited.isEmpty()) { 0275 MessagesModel *model = messageModel(); 0276 const QModelIndex index = model->indexForMessage(mMessageIdBeingEdited); 0277 if (index.isValid()) { 0278 model->setData(index, true, MessagesModel::MessageInEditMode); 0279 } 0280 } 0281 setMode(messageId.isEmpty() ? MessageLineWidget::EditingMode::NewMessage : MessageLineWidget::EditingMode::EditMessage); 0282 setText(text); 0283 setFocus(); 0284 } 0285 0286 void MessageLineWidget::slotPublicSettingChanged() 0287 { 0288 mSendFileButton->setVisible(mCurrentRocketChatAccount->uploadFileEnabled()); 0289 #if QT_VERSION > QT_VERSION_CHECK(6, 0, 0) 0290 mSoundMessageButton->setVisible(mCurrentRocketChatAccount->audioRecorderEnabled()); 0291 mVideoMessageButton->setVisible(mCurrentRocketChatAccount->videoRecorderEnabled()); 0292 #endif 0293 } 0294 0295 void MessageLineWidget::slotOwnUserPreferencesChanged() 0296 { 0297 mEmoticonButton->setVisible(mCurrentRocketChatAccount->ownUserPreferences().useEmojis()); 0298 } 0299 0300 void MessageLineWidget::slotPrivateSettingsChanged() 0301 { 0302 #if QT_VERSION > QT_VERSION_CHECK(6, 0, 0) 0303 mSoundMessageButton->setVisible(mCurrentRocketChatAccount->audioRecorderEnabled()); 0304 mVideoMessageButton->setVisible(mCurrentRocketChatAccount->videoRecorderEnabled()); 0305 #endif 0306 } 0307 0308 void MessageLineWidget::setCurrentRocketChatAccount(RocketChatAccount *account, bool threadMessageDialog) 0309 { 0310 if (mCurrentRocketChatAccount) { 0311 disconnect(mCurrentRocketChatAccount, &RocketChatAccount::privateSettingsChanged, this, &MessageLineWidget::slotPrivateSettingsChanged); 0312 } 0313 mCurrentRocketChatAccount = account; 0314 connect(mCurrentRocketChatAccount, &RocketChatAccount::privateSettingsChanged, this, &MessageLineWidget::slotPrivateSettingsChanged); 0315 mMessageTextEdit->setCurrentRocketChatAccount(account, threadMessageDialog); 0316 mEmoticonMenuWidget->setCurrentRocketChatAccount(account); 0317 } 0318 0319 void MessageLineWidget::setText(const QString &text) 0320 { 0321 mMessageTextEdit->changeText(text, text.length()); 0322 } 0323 0324 QString MessageLineWidget::text() const 0325 { 0326 return mMessageTextEdit->text(); 0327 } 0328 0329 MessageTextEdit *MessageLineWidget::messageTextEdit() const 0330 { 0331 return mMessageTextEdit; 0332 } 0333 0334 void MessageLineWidget::slotSendSoundMessage() 0335 { 0336 #if QT_VERSION > QT_VERSION_CHECK(6, 0, 0) 0337 QPointer<CreateSoundMessageWizard> dlg = new CreateSoundMessageWizard(mCurrentRocketChatAccount, this); 0338 if (dlg->exec()) { 0339 const CreateSoundMessageWizard::CreateSoundMessageInfo info = dlg->soundMessageInfo(); 0340 UploadFileDialog::UploadFileInfo result; 0341 result.description = info.mDescription; 0342 result.fileUrl = info.mFileUrl; 0343 result.fileName = info.mFileName; 0344 result.deleteTemporaryFile = true; 0345 sendFile(result); 0346 } 0347 delete dlg; 0348 #endif 0349 } 0350 0351 void MessageLineWidget::slotSendVideoMessage() 0352 { 0353 #if QT_VERSION > QT_VERSION_CHECK(6, 0, 0) 0354 QPointer<CreateVideoMessageWizard> dlg = new CreateVideoMessageWizard(mCurrentRocketChatAccount, this); 0355 if (dlg->exec()) { 0356 const CreateVideoMessageWizard::CreateVideoMessageInfo info = dlg->videoMessageInfo(); 0357 if (info.isValid()) { 0358 UploadFileDialog::UploadFileInfo result; 0359 result.description = info.mDescription; 0360 result.fileUrl = info.mFileUrl; 0361 result.deleteTemporaryFile = true; 0362 result.fileName = info.mFileName; 0363 sendFile(result); 0364 } 0365 } 0366 delete dlg; 0367 #endif 0368 } 0369 0370 void MessageLineWidget::slotSendFile() 0371 { 0372 QPointer<UploadFileDialog> dlg = new UploadFileDialog(this); 0373 QStringList whiteList = mCurrentRocketChatAccount->ruqolaServerConfig()->mediaWhiteList(); 0374 const QStringList blackList = mCurrentRocketChatAccount->ruqolaServerConfig()->mediaBlackList(); 0375 for (const auto &mediaType : blackList) { 0376 if (whiteList.contains(mediaType)) { 0377 whiteList.removeAll(mediaType); 0378 } 0379 } 0380 // Disable for the moment dlg->setAuthorizedMediaTypes(whiteList); 0381 // qDebug() << " whiteList " << whiteList << " blackList " << blackList; 0382 if (dlg->exec()) { 0383 const UploadFileDialog::UploadFileInfo result = dlg->fileInfo(); 0384 if (result.fileUrl.isLocalFile()) { 0385 const QFileInfo info(result.fileUrl.toLocalFile()); 0386 const qint64 maximumFileSize = mCurrentRocketChatAccount->ruqolaServerConfig()->fileMaxFileSize(); 0387 if (info.size() > maximumFileSize) { 0388 KMessageBox::error(this, i18n("File selected is too big (Maximum size %1)", KIO::convertSize(maximumFileSize)), i18n("File upload")); 0389 delete dlg; 0390 return; 0391 } 0392 auto invalidMedia = [this, dlg]() { 0393 KMessageBox::error(this, i18n("Server doesn't authorized this file (invalid mimetype)")); 0394 delete dlg; 0395 }; 0396 0397 QMimeDatabase mimeDatabase; 0398 const QString mimeTypeName = mimeDatabase.mimeTypeForFile(result.fileUrl.toLocalFile()).name(); 0399 #if 0 // Disable for the moment "image/*" is not a valid MIME type for example 0400 qDebug() << " mimeTypeName" << mimeTypeName << " whiteList " << whiteList; 0401 if (!whiteList.isEmpty()) { 0402 if (!whiteList.contains(mimeTypeName)) { 0403 invalidMedia(); 0404 return; 0405 } 0406 } 0407 #endif 0408 if (blackList.contains(mimeTypeName)) { 0409 invalidMedia(); 0410 return; 0411 } 0412 } 0413 0414 sendFile(result); 0415 } 0416 delete dlg; 0417 } 0418 0419 QString MessageLineWidget::threadMessageId() const 0420 { 0421 return mThreadMessageId; 0422 } 0423 0424 void MessageLineWidget::setThreadMessageId(const QString &threadMessageId, const QString &text, bool replyInDialogBox) 0425 { 0426 mReplyInThreadDialogBox = replyInDialogBox; 0427 0428 if (mThreadMessageId == threadMessageId) { 0429 return; 0430 } 0431 0432 mThreadMessageId = threadMessageId; 0433 Q_EMIT threadMessageIdChanged(mThreadMessageId, text); 0434 } 0435 0436 MessageLineWidget::EditingMode MessageLineWidget::mode() const 0437 { 0438 return mMode; 0439 } 0440 0441 void MessageLineWidget::setMode(EditingMode mode) 0442 { 0443 if (mMode != mode) { 0444 mMode = mode; 0445 switch (mMode) { 0446 case EditingMode::NewMessage: 0447 mSendMessageButton->setIcon(QIcon::fromTheme(QStringLiteral("mail-sent"))); 0448 break; 0449 case EditingMode::EditMessage: 0450 mSendMessageButton->setIcon(QIcon::fromTheme(QStringLiteral("edit-symbolic"))); 0451 break; 0452 } 0453 } 0454 } 0455 0456 void MessageLineWidget::slotTextEditing(bool clearNotification) 0457 { 0458 mSendMessageButton->setEnabled(!clearNotification); 0459 mCurrentRocketChatAccount->textEditing(roomId(), clearNotification); 0460 } 0461 0462 QString MessageLineWidget::messageIdBeingEdited() const 0463 { 0464 return mMessageIdBeingEdited; 0465 } 0466 0467 void MessageLineWidget::setMessageIdBeingEdited(const QString &messageIdBeingEdited) 0468 { 0469 mMessageIdBeingEdited = messageIdBeingEdited; 0470 } 0471 0472 QString MessageLineWidget::roomId() const 0473 { 0474 return mMessageTextEdit->roomId(); 0475 } 0476 0477 void MessageLineWidget::setRoomId(const QString &roomId) 0478 { 0479 mMessageTextEdit->setRoomId(roomId); 0480 } 0481 0482 bool MessageLineWidget::handleMimeData(const QMimeData *mimeData) 0483 { 0484 auto uploadFile = [this](const QUrl &url, const QPixmap &pix) { 0485 QPointer<UploadFileDialog> dlg = new UploadFileDialog(this); 0486 dlg->setFileUrl(url); 0487 dlg->setPixmap(pix); 0488 if (dlg->exec()) { 0489 const UploadFileDialog::UploadFileInfo uploadFileInfo = dlg->fileInfo(); 0490 sendFile(uploadFileInfo); 0491 } 0492 delete dlg; 0493 }; 0494 if (mimeData->hasUrls()) { 0495 const QList<QUrl> urls = mimeData->urls(); 0496 for (const QUrl &url : urls) { 0497 if (url.isLocalFile()) { 0498 uploadFile(url, QPixmap()); 0499 } 0500 } 0501 return true; 0502 } else if (mimeData->hasImage()) { 0503 QTemporaryFile tempFile(QDir::tempPath() + QLatin1String("/XXXXXX.png")); 0504 if (tempFile.open()) { 0505 const auto image = mimeData->imageData().value<QImage>(); 0506 QImageWriter writer(&tempFile, "PNG"); 0507 if (writer.write(image)) { 0508 const QUrl url = QUrl::fromLocalFile(tempFile.fileName()); 0509 tempFile.close(); 0510 const QSize pixmapAvatarSize = QSize(120, 120) * screen()->devicePixelRatio(); 0511 uploadFile(url, QPixmap::fromImage(image).scaled(pixmapAvatarSize, Qt::KeepAspectRatio)); 0512 return true; 0513 } 0514 } 0515 } 0516 return false; 0517 } 0518 0519 MessagesModel *MessageLineWidget::messageModel() const 0520 { 0521 MessagesModel *model = 0522 mThreadMessageId.isEmpty() ? mCurrentRocketChatAccount->messageModelForRoom(roomId()) : mCurrentRocketChatAccount->threadMessageModel(); 0523 Q_ASSERT(model); 0524 return model; 0525 } 0526 0527 void MessageLineWidget::keyPressedInLineEdit(QKeyEvent *ev) 0528 { 0529 const int key = ev->key(); 0530 if (key == Qt::Key_Escape) { 0531 if (!mMessageIdBeingEdited.isEmpty() || !mQuotePermalink.isEmpty()) { 0532 clearMessageIdBeingEdited(); 0533 ev->accept(); 0534 } else { 0535 Q_EMIT keyPressed(ev); 0536 } 0537 } else if (ev->matches(QKeySequence::Paste)) { 0538 const QMimeData *mimeData = qApp->clipboard()->mimeData(); 0539 if (handleMimeData(mimeData)) { 0540 ev->accept(); 0541 } 0542 } else if ((key == Qt::Key_Up || key == Qt::Key_Down) && ev->modifiers() & Qt::AltModifier) { 0543 MessagesModel *model = messageModel(); 0544 auto isEditable = [this](const Message &msg) { 0545 return mCurrentRocketChatAccount->isMessageEditable(msg); 0546 }; 0547 if (key == Qt::Key_Up) { 0548 const Message &msg = model->findLastMessageBefore(mMessageIdBeingEdited, isEditable); 0549 setEditMessage(msg.messageId(), msg.originalMessageOrAttachmentDescription()); 0550 } else { 0551 const Message &msg = model->findNextMessageAfter(mMessageIdBeingEdited, isEditable); 0552 setEditMessage(msg.messageId(), msg.originalMessageOrAttachmentDescription()); 0553 } 0554 ev->accept(); 0555 } else { 0556 Q_EMIT keyPressed(ev); 0557 } 0558 } 0559 0560 void MessageLineWidget::textEditClicked() 0561 { 0562 if (RuqolaGlobalConfig::self()->markAsReadOnTextClicked()) { 0563 mCurrentRocketChatAccount->markRoomAsRead(roomId()); 0564 } 0565 } 0566 0567 #include "moc_messagelinewidget.cpp"