diff options
Diffstat (limited to 'Swift/QtUI/QtWebKitChatView.cpp')
| -rw-r--r-- | Swift/QtUI/QtWebKitChatView.cpp | 64 |
1 files changed, 50 insertions, 14 deletions
diff --git a/Swift/QtUI/QtWebKitChatView.cpp b/Swift/QtUI/QtWebKitChatView.cpp index ea9a9c6..bca9e2e 100644 --- a/Swift/QtUI/QtWebKitChatView.cpp +++ b/Swift/QtUI/QtWebKitChatView.cpp @@ -1,22 +1,22 @@ /* - * Copyright (c) 2010-2017 Isode Limited. + * Copyright (c) 2010-2018 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include <Swift/QtUI/QtWebKitChatView.h> #include <QApplication> #include <QDesktopServices> #include <QDesktopWidget> #include <QEventLoop> #include <QFile> +#include <QFileDevice> #include <QFileDialog> #include <QFileInfo> -#include <QFileDevice> #include <QInputDialog> #include <QKeyEvent> #include <QMessageBox> #include <QStackedWidget> #include <QTimer> #include <QVBoxLayout> @@ -25,12 +25,14 @@ #include <QtDebug> #include <Swiften/Base/FileSize.h> #include <Swiften/Base/Log.h> #include <Swiften/StringCodecs/Base64.h> +#include <Swift/Controllers/SettingConstants.h> +#include <Swift/Controllers/Settings/SettingsProvider.h> #include <Swift/Controllers/UIEvents/JoinMUCUIEvent.h> #include <Swift/Controllers/UIEvents/UIEventStream.h> #include <Swift/QtUI/MessageSnippet.h> #include <Swift/QtUI/QtChatWindow.h> #include <Swift/QtUI/QtChatWindowJSBridge.h> @@ -48,18 +50,21 @@ const QString QtWebKitChatView::ButtonWhiteboardShowWindow = QString("whiteboard const QString QtWebKitChatView::ButtonFileTransferCancel = QString("filetransfer-cancel"); const QString QtWebKitChatView::ButtonFileTransferSetDescription = QString("filetransfer-setdescription"); const QString QtWebKitChatView::ButtonFileTransferSendRequest = QString("filetransfer-sendrequest"); const QString QtWebKitChatView::ButtonFileTransferAcceptRequest = QString("filetransfer-acceptrequest"); const QString QtWebKitChatView::ButtonFileTransferOpenFile = QString("filetransfer-openfile"); const QString QtWebKitChatView::ButtonMUCInvite = QString("mucinvite"); +const QString QtWebKitChatView::ButtonResendMessage = QString("resend-message"); +const QString QtWebKitChatView::ButtonResendPopup = QString("popup-resend"); + namespace { const double minimalFontScaling = 0.7; } -QtWebKitChatView::QtWebKitChatView(QtChatWindow* window, UIEventStream* eventStream, QtChatTheme* theme, QWidget* parent, bool disableAutoScroll) : QtChatView(parent), window_(window), eventStream_(eventStream), fontSizeSteps_(0), disableAutoScroll_(disableAutoScroll), previousMessageKind_(PreviosuMessageWasNone), previousMessageWasSelf_(false), showEmoticons_(false), insertingLastLine_(false), idCounter_(0) { +QtWebKitChatView::QtWebKitChatView(QtChatWindow* window, UIEventStream* eventStream, QtChatTheme* theme, QWidget* parent, SettingsProvider* settings, bool disableAutoScroll /*= false*/) : QtChatView(parent), window_(window), eventStream_(eventStream), fontSizeSteps_(0), disableAutoScroll_(disableAutoScroll), previousMessageKind_(PreviosuMessageWasNone), previousMessageWasSelf_(false), showEmoticons_(false), insertingLastLine_(false), idCounter_(0), settings_(settings) { theme_ = theme; QVBoxLayout* mainLayout = new QVBoxLayout(this); mainLayout->setSpacing(0); mainLayout->setContentsMargins(0,0,0,0); webView_ = new QtWebView(this); @@ -552,35 +557,39 @@ std::string QtWebKitChatView::addMessage( const boost::posix_time::ptime& time, const HighlightAction& highlight, ChatSnippet::Direction direction) { QString scaledAvatarPath = QtScaledAvatarCache(32).getScaledAvatarPath(avatarPath.c_str()); + std::string messageMarkingValue = ""; + QString htmlString; if (label) { + messageMarkingValue = label->getDisplayMarking(); htmlString = QString("<span style=\"border: thin dashed grey; padding-left: .5em; padding-right: .5em; color: %1; background-color: %2; font-size: 90%; margin-right: .5em; \" class='swift_label'>").arg(QtUtilities::htmlEscape(P2QSTRING(label->getForegroundColor()))).arg(QtUtilities::htmlEscape(P2QSTRING(label->getBackgroundColor()))); - htmlString += QString("%1</span> ").arg(QtUtilities::htmlEscape(P2QSTRING(label->getDisplayMarking()))); + htmlString += QString("%1</span> ").arg(QtUtilities::htmlEscape(P2QSTRING(messageMarkingValue))); } QString styleSpanStart = style == "" ? "" : "<span style=\"" + style + "\">"; QString styleSpanEnd = style == "" ? "" : "</span>"; bool highlightWholeMessage = highlight.getFrontColor() || highlight.getBackColor(); QString highlightSpanStart = highlightWholeMessage ? getHighlightSpanStart(highlight) : ""; QString highlightSpanEnd = highlightWholeMessage ? "</span>" : ""; htmlString += "<span class='swift_inner_message'>" + styleSpanStart + highlightSpanStart + message + highlightSpanEnd + styleSpanEnd + "</span>" ; - bool appendToPrevious = appendToPreviousCheck(PreviousMessageWasMessage, senderName, senderIsSelf); + bool appendToPrevious = appendToPreviousCheck(PreviousMessageWasMessage, senderName, senderIsSelf, label); QString qAvatarPath = scaledAvatarPath.isEmpty() ? "qrc:/icons/avatar.svg" : QUrl::fromLocalFile(scaledAvatarPath).toEncoded(); - std::string id = "id" + boost::lexical_cast<std::string>(idCounter_++); + std::string id = "id" + std::to_string(idCounter_++); addMessageBottom(std::make_shared<MessageSnippet>(htmlString, QtUtilities::htmlEscape(P2QSTRING(senderName)), B2QDATE(time), qAvatarPath, senderIsSelf, appendToPrevious, theme_, P2QSTRING(id), direction)); previousMessageWasSelf_ = senderIsSelf; previousSenderName_ = P2QSTRING(senderName); previousMessageKind_ = PreviousMessageWasMessage; + previousMessageDisplayMarking_ = messageMarkingValue; return id; } std::string QtWebKitChatView::addAction(const ChatWindow::ChatMessage& message, const std::string &senderName, bool senderIsSelf, std::shared_ptr<SecurityLabel> label, const std::string& avatarPath, const boost::posix_time::ptime& time) { return addMessage(" *" + chatMessageToHTML(message) + "*", senderName, senderIsSelf, label, avatarPath, "font-style:italic ", time, message.getHighlightActionSender(), ChatSnippet::getDirection(message)); } @@ -597,12 +606,16 @@ QString QtWebKitChatView::buildChatWindowButton(const QString& name, const QStri QRegExp regex("[A-Za-z][A-Za-z0-9\\-\\_]+"); Q_ASSERT(regex.exactMatch(id)); QString html = QString("<input id='%2' type='submit' value='%1' onclick='chatwindow.buttonClicked(\"%2\", \"%3\", \"%4\", \"%5\", \"%6\", \"%7\");' />").arg(name).arg(id).arg(encodeButtonArgument(arg1)).arg(encodeButtonArgument(arg2)).arg(encodeButtonArgument(arg3)).arg(encodeButtonArgument(arg4)).arg(encodeButtonArgument(arg5)); return html; } +QString QtWebKitChatView::buildChatWindowPopupImageButton(const QString& title, const QString& path, const QString& arg1, const QString& arg2, const QString& arg3, const QString& arg4, const QString& arg5) { + return QString("<div class=\"popup\" onclick='chatwindow.buttonClicked(\"%3\", \"%5\", \"6\", \"7\", \"8\", \"9\")' \"><img src='%1' title='%2'/><span class=\"popuptext\" id=\"resendPopup\" ><div class=\"resendButton\" onclick='chatwindow.buttonClicked(\"%4\", \"%5\", \"6\", \"7\", \"8\", \"9\")'>Resend</div></span></div>").arg(path).arg(title).arg(QtWebKitChatView::ButtonResendPopup).arg(QtWebKitChatView::ButtonResendMessage).arg(encodeButtonArgument(arg1)).arg(encodeButtonArgument(arg2)).arg(encodeButtonArgument(arg3)).arg(encodeButtonArgument(arg4)).arg(encodeButtonArgument(arg5)); +} + void QtWebKitChatView::resizeEvent(QResizeEvent* event) { // This code ensures that if the user is scrolled all to the bottom of a chat view, // the view stays scrolled to the bottom if the view is resized or if the message // input widget becomes multi line. if (isAtBottom_) { scrollToBottom(); @@ -642,13 +655,13 @@ std::string QtWebKitChatView::addFileTransfer(const std::string& senderName, con "</div>"; } bool appendToPrevious = appendToPreviousCheck(PreviousMessageWasFileTransfer, senderName, senderIsSelf); QString scaledAvatarPath = QtScaledAvatarCache(32).getScaledAvatarPath(avatarPath.c_str()); QString qAvatarPath = scaledAvatarPath.isEmpty() ? "qrc:/icons/avatar.svg" : QUrl::fromLocalFile(scaledAvatarPath).toEncoded(); - std::string id = "ftmessage" + boost::lexical_cast<std::string>(idCounter_++); + std::string id = "ftmessage" + std::to_string(idCounter_++); addMessageBottom(std::make_shared<MessageSnippet>(htmlString, QtUtilities::htmlEscape(P2QSTRING(senderName)), B2QDATE(boost::posix_time::second_clock::universal_time()), qAvatarPath, senderIsSelf, appendToPrevious, theme_, P2QSTRING(id), ChatSnippet::getDirection(actionText))); previousMessageWasSelf_ = senderIsSelf; previousSenderName_ = P2QSTRING(senderName); previousMessageKind_ = PreviousMessageWasFileTransfer; return Q2PSTRING(ft_id); @@ -676,13 +689,13 @@ std::string QtWebKitChatView::addWhiteboardRequest(const QString& contact, bool htmlString = "<div id='" + wb_id + "'>" + actionText.arg(QtUtilities::htmlEscape(contact)) + ": <br/>" + buildChatWindowButton(tr("Cancel"), ButtonWhiteboardSessionCancel, wb_id) + buildChatWindowButton(tr("Accept"), ButtonWhiteboardSessionAcceptRequest, wb_id) + "</div>"; } QString qAvatarPath = "qrc:/icons/avatar.svg"; - std::string id = "wbmessage" + boost::lexical_cast<std::string>(idCounter_++); + std::string id = "wbmessage" + std::to_string(idCounter_++); addMessageBottom(std::make_shared<MessageSnippet>(htmlString, QtUtilities::htmlEscape(contact), B2QDATE(boost::posix_time::second_clock::universal_time()), qAvatarPath, false, false, theme_, P2QSTRING(id), ChatSnippet::getDirection(actionText))); previousMessageWasSelf_ = false; previousSenderName_ = contact; return Q2PSTRING(wb_id); } @@ -795,15 +808,29 @@ void QtWebKitChatView::handleHTMLButtonClicked(QString id, QString encodedArgume else if (id.startsWith(ButtonMUCInvite)) { QString roomJID = arg1; QString password = arg2; QString elementID = arg3; QString isImpromptu = arg4; QString isContinuation = arg5; - eventStream_->send(std::make_shared<JoinMUCUIEvent>(Q2PSTRING(roomJID), Q2PSTRING(password), boost::optional<std::string>(), false, false, isImpromptu.contains("true"), isContinuation.contains("true"))); + eventStream_->send(std::make_shared<JoinMUCUIEvent>(Q2PSTRING(roomJID), Q2PSTRING(password), boost::optional<std::string>(), false, isImpromptu.contains("true"), isContinuation.contains("true"))); setMUCInvitationJoined(elementID); } + else if (id.startsWith(ButtonResendPopup)) { + QString chatID = arg1; + QWebElement message = document_.findFirst("#" + arg1); + if (!message.isNull()) { + QWebElement popuptext = message.findFirst("span#resendPopup.popuptext"); + if (!popuptext.isNull()) { + popuptext.toggleClass("show"); + } + } + } + else if (id.startsWith(ButtonResendMessage)) { + QString chatID = arg1; + window_->resendMessage(Q2PSTRING(chatID)); + } else { SWIFT_LOG(debug) << "Unknown HTML button! ( " << Q2PSTRING(id) << " )" << std::endl; } } void QtWebKitChatView::handleVerticalScrollBarPositionChanged(double position) { @@ -819,26 +846,26 @@ void QtWebKitChatView::handleVerticalScrollBarPositionChanged(double position) { void QtWebKitChatView::addErrorMessage(const ChatWindow::ChatMessage& errorMessage) { if (window_->isWidgetSelected()) { window_->onAllMessagesRead(); } QString errorMessageHTML(chatMessageToHTML(errorMessage)); - std::string id = "id" + boost::lexical_cast<std::string>(idCounter_++); + std::string id = "id" + std::to_string(idCounter_++); addMessageBottom(std::make_shared<SystemMessageSnippet>("<span class=\"error\">" + errorMessageHTML + "</span>", QDateTime::currentDateTime(), false, theme_, P2QSTRING(id), ChatSnippet::getDirection(errorMessage))); previousMessageWasSelf_ = false; previousMessageKind_ = PreviousMessageWasSystem; } std::string QtWebKitChatView::addSystemMessage(const ChatWindow::ChatMessage& message, ChatWindow::Direction direction) { if (window_->isWidgetSelected()) { window_->onAllMessagesRead(); } QString messageHTML = chatMessageToHTML(message); - std::string id = "id" + boost::lexical_cast<std::string>(idCounter_++); + std::string id = "id" + std::to_string(idCounter_++); addMessageBottom(std::make_shared<SystemMessageSnippet>(messageHTML, QDateTime::currentDateTime(), false, theme_, P2QSTRING(id), getActualDirection(message, direction))); previousMessageKind_ = PreviousMessageWasSystem; return id; } @@ -898,13 +925,13 @@ void QtWebKitChatView::replaceMessage(const QString& message, const std::string& void QtWebKitChatView::addPresenceMessage(const ChatWindow::ChatMessage& message, ChatWindow::Direction direction) { if (window_->isWidgetSelected()) { window_->onAllMessagesRead(); } QString messageHTML = chatMessageToHTML(message); - std::string id = "id" + boost::lexical_cast<std::string>(idCounter_++); + std::string id = "id" + std::to_string(idCounter_++); addMessageBottom(std::make_shared<SystemMessageSnippet>(messageHTML, QDateTime::currentDateTime(), false, theme_, P2QSTRING(id), getActualDirection(message, direction))); previousMessageKind_ = PreviousMessageWasPresence; } void QtWebKitChatView::replaceLastMessage(const ChatWindow::ChatMessage& message, const ChatWindow::TimestampBehaviour timestampBehaviour) { @@ -955,13 +982,15 @@ void QtWebKitChatView::setAckState(std::string const& id, ChatWindow::AckState s displayReceiptInfo(P2QSTRING(id), false); break; case ChatWindow::Received: xml = ""; displayReceiptInfo(P2QSTRING(id), true); break; - case ChatWindow::Failed: xml = "<img src='qrc:/icons/error.png' title='" + tr("This message may not have been transmitted.") + "'/>"; break; + case ChatWindow::Failed: + xml = buildChatWindowPopupImageButton(tr("This message may not have been sent. Click to resend."), "qrc:/icons/error.png", P2QSTRING(id)); + break; } setAckXML(P2QSTRING(id), xml); } void QtWebKitChatView::setMessageReceiptState(const std::string& id, ChatWindow::ReceiptState state) { QString xml; @@ -975,18 +1004,25 @@ void QtWebKitChatView::setMessageReceiptState(const std::string& id, ChatWindow: case ChatWindow::ReceiptFailed: xml = "<img src='qrc:/icons/delivery-failure.svg' title='" + tr("Failed to transmit message to the receipient(s).") + "'/>"; } setReceiptXML(P2QSTRING(id), xml); } -bool QtWebKitChatView::appendToPreviousCheck(PreviousMessageKind messageKind, const std::string& senderName, bool senderIsSelf) { +bool QtWebKitChatView::appendToPreviousCheck(PreviousMessageKind messageKind, const std::string& senderName, bool senderIsSelf, const std::shared_ptr<SecurityLabel>& label /*=nullptr*/) { bool result = previousMessageKind_ == messageKind && ((senderIsSelf && previousMessageWasSelf_) || (!senderIsSelf && !previousMessageWasSelf_&& previousSenderName_ == P2QSTRING(senderName))); if (insertingLastLine_) { insertingLastLine_ = false; return false; } + if (settings_->getSetting(SettingConstants::MUC_MARKING_ELISION)) { + if (label && label->getDisplayMarking() != previousMessageDisplayMarking_) { + if (label->getDisplayMarking() != "") { + return false; + } + } + } return result; } ChatSnippet::Direction QtWebKitChatView::getActualDirection(const ChatWindow::ChatMessage& message, ChatWindow::Direction direction) { if (direction == ChatWindow::DefaultDirection) { return QCoreApplication::translate("QApplication", "QT_LAYOUT_DIRECTION") == "RTL" ? ChatSnippet::RTL : ChatSnippet::LTR; |
Swift