diff options
Diffstat (limited to 'Swift/QtUI/QtChatWindow.cpp')
-rw-r--r-- | Swift/QtUI/QtChatWindow.cpp | 268 |
1 files changed, 192 insertions, 76 deletions
diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp index 28549f8..d81de61 100644 --- a/Swift/QtUI/QtChatWindow.cpp +++ b/Swift/QtUI/QtChatWindow.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2012 Kevin Smith + * Copyright (c) 2010-2013 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -25,14 +25,17 @@ #include <Swift/Controllers/UIEvents/SendFileUIEvent.h> #include <Swift/Controllers/UIEvents/JoinMUCUIEvent.h> #include "QtChatWindowJSBridge.h" +#include "QtUtilities.h" #include <boost/cstdint.hpp> #include <boost/format.hpp> +#include <boost/smart_ptr/make_shared.hpp> #include <boost/lexical_cast.hpp> #include <QLabel> #include <qdebug.h> #include <QMessageBox> +#include <QMimeData> #include <QInputDialog> #include <QApplication> #include <QBoxLayout> @@ -45,6 +48,7 @@ #include <QTextEdit> #include <QTime> #include <QUrl> +#include <QToolButton> #include <QPushButton> #include <QFileDialog> #include <QMenu> @@ -64,7 +68,7 @@ const QString QtChatWindow::ButtonFileTransferAcceptRequest = QString("filetrans const QString QtChatWindow::ButtonMUCInvite = QString("mucinvite"); -QtChatWindow::QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventStream* eventStream, SettingsProvider* settings, QMap<QString, QString> emoticons) : QtTabbable(), contact_(contact), previousMessageWasSelf_(false), previousMessageKind_(PreviosuMessageWasNone), eventStream_(eventStream), emoticons_(emoticons) { +QtChatWindow::QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventStream* eventStream, SettingsProvider* settings) : QtTabbable(), contact_(contact), previousMessageWasSelf_(false), previousMessageKind_(PreviosuMessageWasNone), eventStream_(eventStream), blockingState_(BlockingUnsupported) { settings_ = settings; unreadCount_ = 0; idCounter_ = 0; @@ -103,21 +107,18 @@ QtChatWindow::QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventSt alertLabel_->setStyleSheet(alertStyleSheet_); alertWidget_->hide(); - QBoxLayout* subjectLayout = new QBoxLayout(QBoxLayout::LeftToRight); + subjectLayout_ = new QBoxLayout(QBoxLayout::LeftToRight); subject_ = new QLineEdit(this); - subjectLayout->addWidget(subject_); + subjectLayout_->addWidget(subject_); setSubject(""); subject_->setReadOnly(true); - actionButton_ = new QPushButton(this); + QPushButton* actionButton_ = new QPushButton(this); actionButton_->setIcon(QIcon(":/icons/actions.png")); connect(actionButton_, SIGNAL(clicked()), this, SLOT(handleActionButtonClicked())); - subjectLayout->addWidget(actionButton_); - subject_->hide(); - actionButton_->hide(); - layout->addLayout(subjectLayout); + layout->addLayout(subjectLayout_); logRosterSplitter_ = new QSplitter(this); logRosterSplitter_->setAutoFillBackground(true); @@ -150,13 +151,19 @@ QtChatWindow::QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventSt QHBoxLayout* inputBarLayout = new QHBoxLayout(); inputBarLayout->setContentsMargins(0,0,0,0); inputBarLayout->setSpacing(2); - input_ = new QtTextEdit(this); + input_ = new QtTextEdit(settings_, this); input_->setAcceptRichText(false); inputBarLayout->addWidget(midBar_); inputBarLayout->addWidget(input_); correctingLabel_ = new QLabel(tr("Correcting"), this); inputBarLayout->addWidget(correctingLabel_); correctingLabel_->hide(); + + // using an extra layout to work around Qt margin glitches on OS X + QHBoxLayout* actionLayout = new QHBoxLayout(); + actionLayout->addWidget(actionButton_); + + inputBarLayout->addLayout(actionLayout); layout->addLayout(inputBarLayout); inputClearing_ = false; @@ -215,6 +222,15 @@ bool QtChatWindow::appendToPreviousCheck(QtChatWindow::PreviousMessageKind messa return previousMessageKind_ == messageKind && ((senderIsSelf && previousMessageWasSelf_) || (!senderIsSelf && !previousMessageWasSelf_&& previousSenderName_ == P2QSTRING(senderName))); } +ChatSnippet::Direction QtChatWindow::getActualDirection(const ChatMessage& message, Direction direction) { + if (direction == DefaultDirection) { + return QCoreApplication::translate("QApplication", "QT_LAYOUT_DIRECTION") == "RTL" ? ChatSnippet::RTL : ChatSnippet::LTR; + } + else { + return ChatSnippet::getDirection(message); + } +} + void QtChatWindow::handleFontResized(int fontSizeSteps) { messageLog_->resizeFont(fontSizeSteps); } @@ -413,7 +429,6 @@ void QtChatWindow::convertToMUC() { setAcceptDrops(false); treeWidget_->show(); subject_->show(); - actionButton_->show(); } void QtChatWindow::qAppFocusChanged(QWidget* /*old*/, QWidget* /*now*/) { @@ -481,28 +496,95 @@ void QtChatWindow::updateTitleWithUnreadCount() { emit titleUpdated(); } -std::string QtChatWindow::addMessage(const std::string &message, const std::string &senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const std::string& avatarPath, const boost::posix_time::ptime& time) { - return addMessage(linkimoticonify(P2QSTRING(message)), senderName, senderIsSelf, label, avatarPath, "", time); +std::string QtChatWindow::addMessage( + const ChatMessage& message, + const std::string& senderName, + bool senderIsSelf, + boost::shared_ptr<SecurityLabel> label, + const std::string& avatarPath, + const boost::posix_time::ptime& time, + const HighlightAction& highlight) { + return addMessage(chatMessageToHTML(message), senderName, senderIsSelf, label, avatarPath, "", time, highlight, ChatSnippet::getDirection(message)); +} + +QString QtChatWindow::chatMessageToHTML(const ChatMessage& message) { + QString result; + foreach (boost::shared_ptr<ChatMessagePart> part, message.getParts()) { + boost::shared_ptr<ChatTextMessagePart> textPart; + boost::shared_ptr<ChatURIMessagePart> uriPart; + boost::shared_ptr<ChatEmoticonMessagePart> emoticonPart; + boost::shared_ptr<ChatHighlightingMessagePart> highlightPart; + + if ((textPart = boost::dynamic_pointer_cast<ChatTextMessagePart>(part))) { + QString text = QtUtilities::htmlEscape(P2QSTRING(textPart->text)); + text.replace("\n","<br/>"); + result += text; + continue; + } + if ((uriPart = boost::dynamic_pointer_cast<ChatURIMessagePart>(part))) { + QString uri = QtUtilities::htmlEscape(P2QSTRING(uriPart->target)); + result += "<a href='" + uri + "' >" + uri + "</a>"; + continue; + } + if ((emoticonPart = boost::dynamic_pointer_cast<ChatEmoticonMessagePart>(part))) { + QString textStyle = showEmoticons_ ? "style='display:none'" : ""; + QString imageStyle = showEmoticons_ ? "" : "style='display:none'"; + result += "<span class='swift_emoticon_image' " + imageStyle + "><img src='" + P2QSTRING(emoticonPart->imagePath) + "'/></span><span class='swift_emoticon_text' " + textStyle + ">" + QtUtilities::htmlEscape(P2QSTRING(emoticonPart->alternativeText)) + "</span>"; + continue; + } + if ((highlightPart = boost::dynamic_pointer_cast<ChatHighlightingMessagePart>(part))) { + //FIXME: Maybe do something here. Anything, really. + continue; + } + + } + return result; +} + +/*QString QtChatWindow::linkimoticonify(const std::string& message) const { + return linkimoticonify(P2QSTRING(message)); } QString QtChatWindow::linkimoticonify(const QString& message) const { QString messageHTML(message); - messageHTML = Qt::escape(messageHTML); + messageHTML = QtUtilities::htmlEscape(messageHTML); QMapIterator<QString, QString> it(emoticons_); - QString textStyle = showEmoticons_ ? "style='display:none'" : ""; - QString imageStyle = showEmoticons_ ? "" : "style='display:none'"; + if (messageHTML.length() < 500) { while (it.hasNext()) { it.next(); - messageHTML.replace(it.key(), "<span class='swift_emoticon_image' " + imageStyle + "><img src='" + it.value() + "'/></span><span class='swift_emoticon_text' " + textStyle + ">"+it.key() + "</span>"); + messageHTML.replace(it.key(), ); } messageHTML = P2QSTRING(Linkify::linkify(Q2PSTRING(messageHTML))); } messageHTML.replace("\n","<br/>"); return messageHTML; +}*/ + +QString QtChatWindow::getHighlightSpanStart(const HighlightAction& highlight) { + QString color = QtUtilities::htmlEscape(P2QSTRING(highlight.getTextColor())); + QString background = QtUtilities::htmlEscape(P2QSTRING(highlight.getTextBackground())); + if (color.isEmpty()) { + color = "black"; + } + if (background.isEmpty()) { + background = "yellow"; + } + + return QString("<span style=\"color: %1; background: %2\">").arg(color).arg(background); } -std::string QtChatWindow::addMessage(const QString &message, const std::string &senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const std::string& avatarPath, const QString& style, const boost::posix_time::ptime& time) { +std::string QtChatWindow::addMessage( + const QString& message, + const std::string& senderName, + bool senderIsSelf, + boost::shared_ptr<SecurityLabel> label, + const std::string& avatarPath, + const QString& style, + const boost::posix_time::ptime& time, + const HighlightAction& highlight, + ChatSnippet::Direction direction) { + if (isWidgetSelected()) { onAllMessagesRead(); } @@ -510,13 +592,15 @@ std::string QtChatWindow::addMessage(const QString &message, const std::string & QString htmlString; if (label) { - 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(Qt::escape(P2QSTRING(label->getForegroundColor()))).arg(Qt::escape(P2QSTRING(label->getBackgroundColor()))); - htmlString += QString("%1</span> ").arg(Qt::escape(P2QSTRING(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()))); } - QString messageHTML(message); + QString styleSpanStart = style == "" ? "" : "<span style=\"" + style + "\">"; QString styleSpanEnd = style == "" ? "" : "</span>"; - htmlString += "<span class='swift_inner_message'>" + styleSpanStart + messageHTML + styleSpanEnd + "</span>" ; + QString highlightSpanStart = highlight.highlightText() ? getHighlightSpanStart(highlight) : ""; + QString highlightSpanEnd = highlight.highlightText() ? "</span>" : ""; + htmlString += "<span class='swift_inner_message'>" + styleSpanStart + highlightSpanStart + message + highlightSpanEnd + styleSpanEnd + "</span>" ; bool appendToPrevious = appendToPreviousCheck(PreviousMessageWasMessage, senderName, senderIsSelf); if (lastLineTracker_.getShouldMoveLastLine()) { @@ -527,7 +611,7 @@ std::string QtChatWindow::addMessage(const QString &message, const std::string & } QString qAvatarPath = scaledAvatarPath.isEmpty() ? "qrc:/icons/avatar.png" : QUrl::fromLocalFile(scaledAvatarPath).toEncoded(); std::string id = "id" + boost::lexical_cast<std::string>(idCounter_++); - messageLog_->addMessageBottom(boost::shared_ptr<ChatSnippet>(new MessageSnippet(htmlString, Qt::escape(P2QSTRING(senderName)), B2QDATE(time), qAvatarPath, senderIsSelf, appendToPrevious, theme_, P2QSTRING(id)))); + messageLog_->addMessageBottom(boost::make_shared<MessageSnippet>(htmlString, QtUtilities::htmlEscape(P2QSTRING(senderName)), B2QDATE(time), qAvatarPath, senderIsSelf, appendToPrevious, theme_, P2QSTRING(id), direction)); previousMessageWasSelf_ = senderIsSelf; previousSenderName_ = P2QSTRING(senderName); @@ -572,10 +656,11 @@ int QtChatWindow::getCount() { return unreadCount_; } -std::string QtChatWindow::addAction(const std::string &message, const std::string &senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const std::string& avatarPath, const boost::posix_time::ptime& time) { - return addMessage(" *" + linkimoticonify(P2QSTRING(message)) + "*", senderName, senderIsSelf, label, avatarPath, "font-style:italic ", time); +std::string QtChatWindow::addAction(const ChatMessage& message, const std::string &senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const std::string& avatarPath, const boost::posix_time::ptime& time, const HighlightAction& highlight) { + return addMessage(" *" + chatMessageToHTML(message) + "*", senderName, senderIsSelf, label, avatarPath, "font-style:italic ", time, highlight, ChatSnippet::getDirection(message)); } +// FIXME: Move this to a different file std::string formatSize(const boost::uintmax_t bytes) { static const char *siPrefix[] = {"k", "M", "G", "T", "P", "E", "Z", "Y", NULL}; int power = 0; @@ -587,11 +672,11 @@ std::string formatSize(const boost::uintmax_t bytes) { return str( boost::format("%.1lf %sB") % engBytes % (power > 0 ? siPrefix[power-1] : "") ); } -QString encodeButtonArgument(const QString& str) { - return Qt::escape(P2QSTRING(Base64::encode(createByteArray(Q2PSTRING(str))))); +static QString encodeButtonArgument(const QString& str) { + return QtUtilities::htmlEscape(P2QSTRING(Base64::encode(createByteArray(Q2PSTRING(str))))); } -QString decodeButtonArgument(const QString& str) { +static QString decodeButtonArgument(const QString& str) { return P2QSTRING(byteArrayToString(Base64::decode(Q2PSTRING(str)))); } @@ -606,11 +691,13 @@ std::string QtChatWindow::addFileTransfer(const std::string& senderName, bool se SWIFT_LOG(debug) << "addFileTransfer" << std::endl; QString ft_id = QString("ft%1").arg(P2QSTRING(boost::lexical_cast<std::string>(idCounter_++))); + QString actionText; QString htmlString; QString formattedFileSize = P2QSTRING(formatSize(sizeInBytes)); if (senderIsSelf) { // outgoing - htmlString = tr("Send file") + ": " + P2QSTRING(filename) + " ( " + formattedFileSize + ") <br/>" + + actionText = tr("Send file"); + htmlString = actionText + ": " + P2QSTRING(filename) + " ( " + formattedFileSize + ") <br/>" + "<div id='" + ft_id + "'>" + buildChatWindowButton(tr("Cancel"), ButtonFileTransferCancel, ft_id) + buildChatWindowButton(tr("Set Description"), ButtonFileTransferSetDescription, ft_id) + @@ -618,7 +705,8 @@ std::string QtChatWindow::addFileTransfer(const std::string& senderName, bool se "</div>"; } else { // incoming - htmlString = tr("Receiving file") + ": " + P2QSTRING(filename) + " ( " + formattedFileSize + ") <br/>" + + actionText = tr("Receiving file"); + htmlString = actionText + ": " + P2QSTRING(filename) + " ( " + formattedFileSize + ") <br/>" + "<div id='" + ft_id + "'>" + buildChatWindowButton(tr("Cancel"), ButtonFileTransferCancel, ft_id) + buildChatWindowButton(tr("Accept"), ButtonFileTransferAcceptRequest, ft_id, P2QSTRING(filename)) + @@ -636,7 +724,7 @@ std::string QtChatWindow::addFileTransfer(const std::string& senderName, bool se } QString qAvatarPath = "qrc:/icons/avatar.png"; std::string id = "ftmessage" + boost::lexical_cast<std::string>(idCounter_++); - messageLog_->addMessageBottom(boost::shared_ptr<ChatSnippet>(new MessageSnippet(htmlString, Qt::escape(P2QSTRING(senderName)), B2QDATE(boost::posix_time::second_clock::local_time()), qAvatarPath, senderIsSelf, appendToPrevious, theme_, P2QSTRING(id)))); + messageLog_->addMessageBottom(boost::make_shared<MessageSnippet>(htmlString, QtUtilities::htmlEscape(P2QSTRING(senderName)), B2QDATE(boost::posix_time::second_clock::local_time()), qAvatarPath, senderIsSelf, appendToPrevious, theme_, P2QSTRING(id), ChatSnippet::getDirection(actionText))); previousMessageWasSelf_ = senderIsSelf; previousSenderName_ = P2QSTRING(senderName); @@ -645,22 +733,25 @@ std::string QtChatWindow::addFileTransfer(const std::string& senderName, bool se } void QtChatWindow::setFileTransferProgress(std::string id, const int percentageDone) { - messageLog_->setFileTransferProgress(QString::fromStdString(id), percentageDone); + messageLog_->setFileTransferProgress(P2QSTRING(id), percentageDone); } void QtChatWindow::setFileTransferStatus(std::string id, const FileTransferState state, const std::string& msg) { - messageLog_->setFileTransferStatus(QString::fromStdString(id), state, QString::fromStdString(msg)); + messageLog_->setFileTransferStatus(P2QSTRING(id), state, P2QSTRING(msg)); } std::string QtChatWindow::addWhiteboardRequest(bool senderIsSelf) { QString wb_id = QString("wb%1").arg(P2QSTRING(boost::lexical_cast<std::string>(idCounter_++))); QString htmlString; + QString actionText; if (senderIsSelf) { - htmlString = "<div id='" + wb_id + "'>" + tr("Starting whiteboard chat") + "<br />"+ + actionText = tr("Starting whiteboard chat"); + htmlString = "<div id='" + wb_id + "'>" + actionText + "<br />"+ buildChatWindowButton(tr("Cancel"), ButtonWhiteboardSessionCancel, wb_id) + "</div>"; } else { - htmlString = "<div id='" + wb_id + "'>" + tr("%1 would like to start a whiteboard chat").arg(Qt::escape(contact_)) + ": <br/>" + + actionText = tr("%1 would like to start a whiteboard chat"); + htmlString = "<div id='" + wb_id + "'>" + actionText.arg(QtUtilities::htmlEscape(contact_)) + ": <br/>" + buildChatWindowButton(tr("Cancel"), ButtonWhiteboardSessionCancel, wb_id) + buildChatWindowButton(tr("Accept"), ButtonWhiteboardSessionAcceptRequest, wb_id) + "</div>"; @@ -674,7 +765,7 @@ std::string QtChatWindow::addWhiteboardRequest(bool senderIsSelf) { } QString qAvatarPath = "qrc:/icons/avatar.png"; std::string id = "wbmessage" + boost::lexical_cast<std::string>(idCounter_++); - messageLog_->addMessageBottom(boost::shared_ptr<ChatSnippet>(new MessageSnippet(htmlString, Qt::escape(contact_), B2QDATE(boost::posix_time::second_clock::local_time()), qAvatarPath, false, false, theme_, P2QSTRING(id)))); + messageLog_->addMessageBottom(boost::make_shared<MessageSnippet>(htmlString, QtUtilities::htmlEscape(contact_), B2QDATE(boost::posix_time::second_clock::local_time()), qAvatarPath, false, false, theme_, P2QSTRING(id), ChatSnippet::getDirection(actionText))); previousMessageWasSelf_ = false; previousSenderName_ = contact_; @@ -682,7 +773,7 @@ std::string QtChatWindow::addWhiteboardRequest(bool senderIsSelf) { } void QtChatWindow::setWhiteboardSessionStatus(std::string id, const ChatWindow::WhiteboardSessionState state) { - messageLog_->setWhiteboardSessionStatus(QString::fromStdString(id), state); + messageLog_->setWhiteboardSessionStatus(P2QSTRING(id), state); } void QtChatWindow::handleHTMLButtonClicked(QString id, QString encodedArgument1, QString encodedArgument2, QString encodedArgument3) { @@ -719,12 +810,12 @@ void QtChatWindow::handleHTMLButtonClicked(QString id, QString encodedArgument1, } else if (id.startsWith(ButtonWhiteboardSessionAcceptRequest)) { QString id = arg1; - messageLog_->setWhiteboardSessionStatus(QString::fromStdString(Q2PSTRING(id)), ChatWindow::WhiteboardAccepted); + messageLog_->setWhiteboardSessionStatus(id, ChatWindow::WhiteboardAccepted); onWhiteboardSessionAccept(); } else if (id.startsWith(ButtonWhiteboardSessionCancel)) { QString id = arg1; - messageLog_->setWhiteboardSessionStatus(QString::fromStdString(Q2PSTRING(id)), ChatWindow::WhiteboardTerminated); + messageLog_->setWhiteboardSessionStatus(id, ChatWindow::WhiteboardTerminated); onWhiteboardSessionCancel(); } else if (id.startsWith(ButtonWhiteboardShowWindow)) { @@ -744,40 +835,39 @@ void QtChatWindow::handleHTMLButtonClicked(QString id, QString encodedArgument1, } } -void QtChatWindow::addErrorMessage(const std::string& errorMessage) { +void QtChatWindow::addErrorMessage(const ChatMessage& errorMessage) { if (isWidgetSelected()) { onAllMessagesRead(); } - QString errorMessageHTML(Qt::escape(P2QSTRING(errorMessage))); - errorMessageHTML.replace("\n","<br/>"); - messageLog_->addMessageBottom(boost::shared_ptr<ChatSnippet>(new SystemMessageSnippet("<span class=\"error\">" + errorMessageHTML + "</span>", QDateTime::currentDateTime(), false, theme_))); + QString errorMessageHTML(chatMessageToHTML(errorMessage)); + + messageLog_->addMessageBottom(boost::make_shared<SystemMessageSnippet>("<span class=\"error\">" + errorMessageHTML + "</span>", QDateTime::currentDateTime(), false, theme_, ChatSnippet::getDirection(errorMessage))); previousMessageWasSelf_ = false; previousMessageKind_ = PreviousMessageWasSystem; } -void QtChatWindow::addSystemMessage(const std::string& message) { +void QtChatWindow::addSystemMessage(const ChatMessage& message, Direction direction) { if (isWidgetSelected()) { onAllMessagesRead(); } - QString messageHTML(P2QSTRING(message)); - messageHTML = linkimoticonify(messageHTML); - messageLog_->addMessageBottom(boost::shared_ptr<ChatSnippet>(new SystemMessageSnippet(messageHTML, QDateTime::currentDateTime(), false, theme_))); + QString messageHTML = chatMessageToHTML(message); + messageLog_->addMessageBottom(boost::make_shared<SystemMessageSnippet>(messageHTML, QDateTime::currentDateTime(), false, theme_, getActualDirection(message, direction))); previousMessageKind_ = PreviousMessageWasSystem; } -void QtChatWindow::replaceWithAction(const std::string& message, const std::string& id, const boost::posix_time::ptime& time) { - replaceMessage(" *" + linkimoticonify(P2QSTRING(message)) + "*", id, time, "font-style:italic "); +void QtChatWindow::replaceWithAction(const ChatMessage& message, const std::string& id, const boost::posix_time::ptime& time, const HighlightAction& highlight) { + replaceMessage(" *" + chatMessageToHTML(message) + "*", id, time, "font-style:italic ", highlight); } -void QtChatWindow::replaceMessage(const std::string& message, const std::string& id, const boost::posix_time::ptime& time) { - replaceMessage(linkimoticonify(P2QSTRING(message)), id, time, ""); +void QtChatWindow::replaceMessage(const ChatMessage& message, const std::string& id, const boost::posix_time::ptime& time, const HighlightAction& highlight) { + replaceMessage(chatMessageToHTML(message), id, time, "", highlight); } -void QtChatWindow::replaceMessage(const QString& message, const std::string& id, const boost::posix_time::ptime& time, const QString& style) { +void QtChatWindow::replaceMessage(const QString& message, const std::string& id, const boost::posix_time::ptime& time, const QString& style, const HighlightAction& highlight) { if (!id.empty()) { if (isWidgetSelected()) { onAllMessagesRead(); @@ -787,7 +877,9 @@ void QtChatWindow::replaceMessage(const QString& message, const std::string& id, QString styleSpanStart = style == "" ? "" : "<span style=\"" + style + "\">"; QString styleSpanEnd = style == "" ? "" : "</span>"; - messageHTML = styleSpanStart + messageHTML + styleSpanEnd; + QString highlightSpanStart = highlight.highlightText() ? getHighlightSpanStart(highlight) : ""; + QString highlightSpanEnd = highlight.highlightText() ? "</span>" : ""; + messageHTML = styleSpanStart + highlightSpanStart + messageHTML + highlightSpanEnd + styleSpanEnd; messageLog_->replaceMessage(messageHTML, P2QSTRING(id), B2QDATE(time)); } @@ -796,14 +888,13 @@ void QtChatWindow::replaceMessage(const QString& message, const std::string& id, } } -void QtChatWindow::addPresenceMessage(const std::string& message) { +void QtChatWindow::addPresenceMessage(const ChatMessage& message, Direction direction) { if (isWidgetSelected()) { onAllMessagesRead(); } - QString messageHTML(P2QSTRING(message)); - messageHTML = linkimoticonify(messageHTML); - messageLog_->addMessageBottom(boost::shared_ptr<ChatSnippet>(new SystemMessageSnippet(messageHTML, QDateTime::currentDateTime(), false, theme_))); + QString messageHTML = chatMessageToHTML(message); + messageLog_->addMessageBottom(boost::make_shared<SystemMessageSnippet>(messageHTML, QDateTime::currentDateTime(), false, theme_, getActualDirection(message, direction))); previousMessageKind_ = PreviousMessageWasPresence; } @@ -874,12 +965,15 @@ void QtChatWindow::dropEvent(QDropEvent *event) { if (event->mimeData()->urls().size() == 1) { onSendFileRequest(Q2PSTRING(event->mimeData()->urls().at(0).toLocalFile())); } else { - addSystemMessage("Sending of multiple files at once isn't supported at this time."); + std::string messageText(Q2PSTRING(tr("Sending of multiple files at once isn't supported at this time."))); + ChatMessage message; + message.append(boost::make_shared<ChatTextMessagePart>(messageText)); + addSystemMessage(message, DefaultDirection); } } -void QtChatWindow::replaceLastMessage(const std::string& message) { - messageLog_->replaceLastMessage(linkimoticonify(P2QSTRING(message))); +void QtChatWindow::replaceLastMessage(const ChatMessage& message) { + messageLog_->replaceLastMessage(chatMessageToHTML(message)); } void QtChatWindow::setAvailableOccupantActions(const std::vector<OccupantAction>& actions) { @@ -901,15 +995,26 @@ void QtChatWindow::handleActionButtonClicked() { QAction* destroy = NULL; QAction* invite = NULL; - foreach(ChatWindow::RoomAction availableAction, availableRoomActions_) - { - switch(availableAction) + QAction* block = NULL; + QAction* unblock = NULL; + + if (availableRoomActions_.empty()) { + if (blockingState_ == IsBlocked) { + unblock = contextMenu.addAction(tr("Unblock")); + } else if (blockingState_ == IsUnblocked) { + block = contextMenu.addAction(tr("Block")); + } + } else { + foreach(ChatWindow::RoomAction availableAction, availableRoomActions_) { - case ChatWindow::ChangeSubject: changeSubject = contextMenu.addAction(tr("Change subject…")); break; - case ChatWindow::Configure: configure = contextMenu.addAction(tr("Configure room…")); break; - case ChatWindow::Affiliations: affiliations = contextMenu.addAction(tr("Edit affiliations…")); break; - case ChatWindow::Destroy: destroy = contextMenu.addAction(tr("Destroy room")); break; - case ChatWindow::Invite: invite = contextMenu.addAction(tr("Invite person to this room…")); break; + switch(availableAction) + { + case ChatWindow::ChangeSubject: changeSubject = contextMenu.addAction(tr("Change subject…")); break; + case ChatWindow::Configure: configure = contextMenu.addAction(tr("Configure room…")); break; + case ChatWindow::Affiliations: affiliations = contextMenu.addAction(tr("Edit affiliations…")); break; + case ChatWindow::Destroy: destroy = contextMenu.addAction(tr("Destroy room")); break; + case ChatWindow::Invite: invite = contextMenu.addAction(tr("Invite person to this room…")); break; + } } } @@ -949,6 +1054,12 @@ void QtChatWindow::handleActionButtonClicked() { else if (result == invite) { onInvitePersonToThisMUCRequest(); } + else if (result == block) { + onBlockUserRequest(); + } + else if (result == unblock) { + onUnblockUserRequest(); + } } void QtChatWindow::handleAffiliationEditorAccepted() { @@ -960,11 +1071,14 @@ void QtChatWindow::setAffiliations(MUCOccupant::Affiliation affiliation, const s affiliationEditor_->setAffiliations(affiliation, jids); } -void QtChatWindow::setAvailableRoomActions(const std::vector<RoomAction> &actions) -{ +void QtChatWindow::setAvailableRoomActions(const std::vector<RoomAction>& actions) { availableRoomActions_ = actions; } +void QtChatWindow::setBlockingState(BlockingState state) { + blockingState_ = state; +} + void QtChatWindow::showRoomConfigurationForm(Form::ref form) { if (mucConfigurationWindow_) { delete mucConfigurationWindow_.data(); @@ -979,18 +1093,20 @@ void QtChatWindow::addMUCInvitation(const std::string& senderName, const JID& ji onAllMessagesRead(); } - QString htmlString = QObject::tr("You've been invited to enter the %1 room.").arg(P2QSTRING(jid.toString())) + " <br/>"; + QString message = QObject::tr("You've been invited to enter the %1 room.").arg(P2QSTRING(jid.toString())) + "\n"; + QString htmlString = message; if (!reason.empty()) { - htmlString += QObject::tr("Reason: %1").arg(P2QSTRING(reason)) + "<br/>"; + htmlString += QObject::tr("Reason: %1").arg(P2QSTRING(reason)) + "\n"; } if (!direct) { - htmlString += QObject::tr("This person may not have really sent this invitation!") + "<br/>"; + htmlString += QObject::tr("This person may not have really sent this invitation!") + "\n"; } + htmlString = chatMessageToHTML(ChatMessage(Q2PSTRING(htmlString))); - QString id = QString(ButtonMUCInvite + "%1").arg(P2QSTRING(boost::lexical_cast<std::string>(idCounter_++))); + QString id = QString(ButtonMUCInvite + "%1").arg(P2QSTRING(boost::lexical_cast<std::string>(idCounter_++))); htmlString += "<div id='" + id + "'>" + - buildChatWindowButton(tr("Accept Invite"), ButtonMUCInvite, Qt::escape(P2QSTRING(jid.toString())), Qt::escape(P2QSTRING(password)), id) + + buildChatWindowButton(chatMessageToHTML(ChatMessage(Q2PSTRING((tr("Accept Invite"))))), ButtonMUCInvite, QtUtilities::htmlEscape(P2QSTRING(jid.toString())), QtUtilities::htmlEscape(P2QSTRING(password)), id) + "</div>"; bool appendToPrevious = appendToPreviousCheck(PreviousMessageWasMUCInvite, senderName, false); @@ -1002,7 +1118,7 @@ void QtChatWindow::addMUCInvitation(const std::string& senderName, const JID& ji } QString qAvatarPath = "qrc:/icons/avatar.png"; - messageLog_->addMessageBottom(boost::shared_ptr<ChatSnippet>(new MessageSnippet(htmlString, Qt::escape(P2QSTRING(senderName)), B2QDATE(boost::posix_time::second_clock::local_time()), qAvatarPath, false, appendToPrevious, theme_, id))); + messageLog_->addMessageBottom(boost::make_shared<MessageSnippet>(htmlString, QtUtilities::htmlEscape(P2QSTRING(senderName)), B2QDATE(boost::posix_time::second_clock::local_time()), qAvatarPath, false, appendToPrevious, theme_, id, ChatSnippet::getDirection(message))); previousMessageWasSelf_ = false; previousSenderName_ = P2QSTRING(senderName); previousMessageKind_ = PreviousMessageWasMUCInvite; |