From e9f2f7675b11ce36b3f66250156b78fae524a351 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Remko=20Tron=C3=A7on?= Date: Sun, 18 Nov 2012 19:46:50 +0100 Subject: RTL support in chat dialog. Change-Id: Id5604c65c6090783c79a45ee7c975ed4118a51f3 diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp index 68af288..1fb45a9 100644 --- a/Swift/Controllers/Chat/ChatController.cpp +++ b/Swift/Controllers/Chat/ChatController.cpp @@ -77,7 +77,7 @@ ChatController::ChatController(const JID& self, StanzaChannel* stanzaChannel, IQ lastShownStatus_ = theirPresence ? theirPresence->getShow() : StatusShow::None; chatStateNotifier_->setContactIsOnline(theirPresence && theirPresence->getType() == Presence::Available); startMessage += "."; - chatWindow_->addSystemMessage(startMessage); + chatWindow_->addSystemMessage(startMessage, ChatWindow::DefaultDirection); chatWindow_->onUserTyping.connect(boost::bind(&ChatStateNotifier::setUserIsTyping, chatStateNotifier_)); chatWindow_->onUserCancelsTyping.connect(boost::bind(&ChatStateNotifier::userCancelledNewMessage, chatStateNotifier_)); chatWindow_->onFileTransferStart.connect(boost::bind(&ChatController::handleFileTransferStart, this, _1, _2)); @@ -445,7 +445,7 @@ void ChatController::handlePresenceChange(boost::shared_ptr newPresenc if (lastWasPresence_) { chatWindow_->replaceLastMessage(newStatusChangeString); } else { - chatWindow_->addPresenceMessage(newStatusChangeString); + chatWindow_->addPresenceMessage(newStatusChangeString, ChatWindow::DefaultDirection); } lastStatusChangeString_ = newStatusChangeString; lastWasPresence_ = true; diff --git a/Swift/Controllers/Chat/ChatControllerBase.cpp b/Swift/Controllers/Chat/ChatControllerBase.cpp index b60162f..e469637 100644 --- a/Swift/Controllers/Chat/ChatControllerBase.cpp +++ b/Swift/Controllers/Chat/ChatControllerBase.cpp @@ -75,7 +75,7 @@ void ChatControllerBase::createDayChangeTimer() { void ChatControllerBase::handleDayChangeTick() { dateChangeTimer_->stop(); boost::posix_time::ptime now = boost::posix_time::second_clock::local_time(); - chatWindow_->addSystemMessage(str(format(QT_TRANSLATE_NOOP("", "The day is now %1%")) % std::string(boost::posix_time::to_iso_extended_string(now)).substr(0,10))); + chatWindow_->addSystemMessage(str(format(QT_TRANSLATE_NOOP("", "The day is now %1%")) % std::string(boost::posix_time::to_iso_extended_string(now)).substr(0,10)), ChatWindow::DefaultDirection); dayTicked(); createDayChangeTimer(); } @@ -238,7 +238,7 @@ void ChatControllerBase::handleIncomingMessage(boost::shared_ptr m boost::posix_time::ptime now = boost::posix_time::microsec_clock::universal_time(); std::ostringstream s; s << "The following message took " << (now - delayPayloads[i]->getStamp()).total_milliseconds() / 1000.0 << " seconds to be delivered from " << delayPayloads[i]->getFrom()->toString() << "."; - chatWindow_->addSystemMessage(std::string(s.str())); + chatWindow_->addSystemMessage(std::string(s.str()), ChatWindow::DefaultDirection); } boost::shared_ptr label = message->getPayload(); diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp index 03c8810..b964bad 100644 --- a/Swift/Controllers/Chat/MUCController.cpp +++ b/Swift/Controllers/Chat/MUCController.cpp @@ -226,7 +226,7 @@ const std::string& MUCController::getNick() { void MUCController::handleJoinTimeoutTick() { receivedActivity(); - chatWindow_->addSystemMessage(str(format(QT_TRANSLATE_NOOP("", "Room %1% is not responding. This operation may never complete.")) % toJID_.toString())); + chatWindow_->addSystemMessage(str(format(QT_TRANSLATE_NOOP("", "Room %1% is not responding. This operation may never complete.")) % toJID_.toString()), ChatWindow::DefaultDirection); } void MUCController::receivedActivity() { @@ -294,7 +294,7 @@ void MUCController::handleJoinComplete(const std::string& nick) { joined_ = true; std::string joinMessage = str(format(QT_TRANSLATE_NOOP("", "You have entered room %1% as %2%.")) % toJID_.toString() % nick); setNick(nick); - chatWindow_->addSystemMessage(joinMessage); + chatWindow_->addSystemMessage(joinMessage, ChatWindow::DefaultDirection); #ifdef SWIFT_EXPERIMENTAL_HISTORY addRecentLogs(); @@ -352,7 +352,6 @@ void MUCController::handleOccupantJoined(const MUCOccupant& occupant) { updateJoinParts(); } else { addPresenceMessage(joinString); - } } if (avatarManager_ != NULL) { @@ -362,7 +361,7 @@ void MUCController::handleOccupantJoined(const MUCOccupant& occupant) { void MUCController::addPresenceMessage(const std::string& message) { lastWasPresence_ = true; - chatWindow_->addPresenceMessage(message); + chatWindow_->addPresenceMessage(message, ChatWindow::DefaultDirection); } @@ -449,7 +448,7 @@ void MUCController::preHandleIncomingMessage(boost::shared_ptr mes joined_ = true; if (message->hasSubject() && message->getBody().empty()) { - chatWindow_->addSystemMessage(str(format(QT_TRANSLATE_NOOP("", "The room subject is now: %1%")) % message->getSubject()));; + chatWindow_->addSystemMessage(str(format(QT_TRANSLATE_NOOP("", "The room subject is now: %1%")) % message->getSubject()), ChatWindow::DefaultDirection);; chatWindow_->setSubject(message->getSubject()); doneGettingHistory_ = true; } @@ -486,7 +485,7 @@ void MUCController::handleOccupantRoleChanged(const std::string& nick, const MUC std::string group(roleToGroupName(occupant.getRole())); roster_->addContact(jid, realJID, nick, group, avatarManager_->getAvatarPath(jid).string()); roster_->getGroup(group)->setManualSort(roleToSortName(occupant.getRole())); - chatWindow_->addSystemMessage(str(format(QT_TRANSLATE_NOOP("", "%1% is now a %2%")) % nick % roleToFriendlyName(occupant.getRole()))); + chatWindow_->addSystemMessage(str(format(QT_TRANSLATE_NOOP("", "%1% is now a %2%")) % nick % roleToFriendlyName(occupant.getRole())), ChatWindow::DefaultDirection); if (nick == nick_) { setAvailableRoomActions(occupant.getAffiliation(), occupant.getRole()); } @@ -519,7 +518,7 @@ void MUCController::setOnline(bool online) { } else { if (shouldJoinOnReconnect_) { renameCounter_ = 0; - chatWindow_->addSystemMessage(str(format(QT_TRANSLATE_NOOP("", "Trying to enter room %1%")) % toJID_.toString())); + chatWindow_->addSystemMessage(str(format(QT_TRANSLATE_NOOP("", "Trying to enter room %1%")) % toJID_.toString()), ChatWindow::DefaultDirection); if (loginCheckTimer_) { loginCheckTimer_->start(); } diff --git a/Swift/Controllers/UIInterfaces/ChatWindow.h b/Swift/Controllers/UIInterfaces/ChatWindow.h index 93a1376..a845cbe 100644 --- a/Swift/Controllers/UIInterfaces/ChatWindow.h +++ b/Swift/Controllers/UIInterfaces/ChatWindow.h @@ -40,6 +40,8 @@ namespace Swift { enum FileTransferState {WaitingForAccept, Negotiating, Transferring, Canceled, Finished, FTFailed}; enum WhiteboardSessionState {WhiteboardAccepted, WhiteboardTerminated, WhiteboardRejected}; enum BlockingState {BlockingUnsupported, IsBlocked, IsUnblocked}; + enum Direction { UnknownDirection, DefaultDirection }; + ChatWindow() {} virtual ~ChatWindow() {} @@ -51,8 +53,10 @@ namespace Swift { * @return id of added message (for acks); */ virtual std::string addAction(const std::string& message, const std::string& senderName, bool senderIsSelf, boost::shared_ptr label, const std::string& avatarPath, const boost::posix_time::ptime& time, const HighlightAction& highlight) = 0; - virtual void addSystemMessage(const std::string& message) = 0; - virtual void addPresenceMessage(const std::string& message) = 0; + + virtual void addSystemMessage(const std::string& message, Direction direction) = 0; + virtual void addPresenceMessage(const std::string& message, Direction direction) = 0; + virtual void addErrorMessage(const std::string& message) = 0; virtual void replaceMessage(const std::string& message, const std::string& id, const boost::posix_time::ptime& time, const HighlightAction& highlight) = 0; virtual void replaceWithAction(const std::string& message, const std::string& id, const boost::posix_time::ptime& time, const HighlightAction& highlight) = 0; diff --git a/Swift/Controllers/UnitTest/MockChatWindow.h b/Swift/Controllers/UnitTest/MockChatWindow.h index 8af65f7..4eb3bb6 100644 --- a/Swift/Controllers/UnitTest/MockChatWindow.h +++ b/Swift/Controllers/UnitTest/MockChatWindow.h @@ -16,9 +16,9 @@ namespace Swift { virtual std::string addMessage(const std::string& message, const std::string& /*senderName*/, bool /*senderIsSelf*/, boost::shared_ptr /*label*/, const std::string& /*avatarPath*/, const boost::posix_time::ptime&, const HighlightAction&) {lastMessageBody_ = message; return "";} virtual std::string addAction(const std::string& message, const std::string& /*senderName*/, bool /*senderIsSelf*/, boost::shared_ptr /*label*/, const std::string& /*avatarPath*/, const boost::posix_time::ptime&, const HighlightAction&) {lastMessageBody_ = message; return "";} - virtual void addSystemMessage(const std::string& /*message*/) {} + virtual void addSystemMessage(const std::string& /*message*/, Direction) {} virtual void addErrorMessage(const std::string& /*message*/) {} - virtual void addPresenceMessage(const std::string& /*message*/) {} + virtual void addPresenceMessage(const std::string& /*message*/, Direction) {} // File transfer related stuff virtual std::string addFileTransfer(const std::string& /*senderName*/, bool /*senderIsSelf*/,const std::string& /*filename*/, const boost::uintmax_t /*sizeInBytes*/) { return 0; } diff --git a/Swift/QtUI/ChatSnippet.cpp b/Swift/QtUI/ChatSnippet.cpp index 4a0560b..666dd00 100644 --- a/Swift/QtUI/ChatSnippet.cpp +++ b/Swift/QtUI/ChatSnippet.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Kevin Smith + * Copyright (c) 2010-2013 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -7,6 +7,7 @@ #include #include "ChatSnippet.h" +#include namespace Swift { @@ -39,4 +40,46 @@ QString ChatSnippet::wrapResizable(const QString& text) { return "" + text + ""; } +QString ChatSnippet::directionToCSS(Direction direction) { + return direction == RTL ? QString("rtl") : QString("ltr"); +} + +ChatSnippet::Direction ChatSnippet::getDirection(const std::string& message) { + return getDirection(P2QSTRING(message)); +} + +ChatSnippet::Direction ChatSnippet::getDirection(const QString& message) { + /* + for (int i = 0; i < message.size(); ++i) { + switch (message.at(i).direction()) { + case QChar::DirL: + case QChar::DirLRE: + case QChar::DirLRO: + return ChatSnippet::LTR; + case QChar::DirR: + case QChar::DirAL: + case QChar::DirRLE: + case QChar::DirRLO: + return ChatSnippet::RTL; + case QChar::DirEN: + case QChar::DirES: + case QChar::DirET: + case QChar::DirAN: + case QChar::DirCS: + case QChar::DirB: + case QChar::DirWS: + case QChar::DirON: + case QChar::DirS: + case QChar::DirPDF: + case QChar::DirNSM: + case QChar::DirBN: + break; + } + } + return ChatSnippet::LTR; + */ + return message.isRightToLeft() ? ChatSnippet::RTL : ChatSnippet::LTR; +} + + } diff --git a/Swift/QtUI/ChatSnippet.h b/Swift/QtUI/ChatSnippet.h index 78e0b88..d43947f 100644 --- a/Swift/QtUI/ChatSnippet.h +++ b/Swift/QtUI/ChatSnippet.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Kevin Smith + * Copyright (c) 2010-2013 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -15,6 +15,11 @@ namespace Swift { class ChatSnippet { public: + enum Direction { + RTL, + LTR + }; + ChatSnippet(bool appendToPrevious); virtual ~ChatSnippet(); @@ -42,7 +47,12 @@ namespace Swift { static QString timeToEscapedString(const QDateTime& time); + static Direction getDirection(const std::string& message); + static Direction getDirection(const QString& message); + protected: + static QString directionToCSS(Direction direction); + QString wrapResizable(const QString& text); void setContinuationFallbackSnippet(boost::shared_ptr continuationFallback) { continuationFallback_ = continuationFallback; diff --git a/Swift/QtUI/MessageSnippet.cpp b/Swift/QtUI/MessageSnippet.cpp index 47aa9f8..28c44c4 100644 --- a/Swift/QtUI/MessageSnippet.cpp +++ b/Swift/QtUI/MessageSnippet.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Kevin Smith + * Copyright (c) 2010-2013 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -11,9 +11,9 @@ namespace Swift { -MessageSnippet::MessageSnippet(const QString& message, const QString& sender, const QDateTime& time, const QString& iconURI, bool isIncoming, bool appendToPrevious, QtChatTheme* theme, const QString& id) : ChatSnippet(appendToPrevious) { +MessageSnippet::MessageSnippet(const QString& message, const QString& sender, const QDateTime& time, const QString& iconURI, bool isIncoming, bool appendToPrevious, QtChatTheme* theme, const QString& id, Direction direction) : ChatSnippet(appendToPrevious) { if (appendToPrevious) { - setContinuationFallbackSnippet(boost::shared_ptr(new MessageSnippet(message, sender, time, iconURI, isIncoming, false, theme, id))); + setContinuationFallbackSnippet(boost::shared_ptr(new MessageSnippet(message, sender, time, iconURI, isIncoming, false, theme, id, direction))); } if (isIncoming) { if (appendToPrevious) { @@ -32,12 +32,13 @@ MessageSnippet::MessageSnippet(const QString& message, const QString& sender, co } } + content_.replace("%direction%", directionToCSS(direction)); content_.replace("%message%", wrapResizable("" + escape(message) + "")); content_.replace("%wrapped_sender%", wrapResizable(escape(sender))); content_.replace("%sender%", escape(sender)); content_.replace("%time%", wrapResizable("" + timeToEscapedString(time) + "")); content_.replace("%userIconPath%", escape(iconURI)); - content_ = "
" + content_ + "
"; + content_ = QString("
%2
").arg(id).arg(content_); content_ = "" + content_ + ""; } diff --git a/Swift/QtUI/MessageSnippet.h b/Swift/QtUI/MessageSnippet.h index 2a0ec6e..8186d19 100644 --- a/Swift/QtUI/MessageSnippet.h +++ b/Swift/QtUI/MessageSnippet.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Kevin Smith + * Copyright (c) 2010-2013 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -15,7 +15,7 @@ class QDateTime; namespace Swift { class MessageSnippet : public ChatSnippet { public: - MessageSnippet(const QString& message, const QString& sender, const QDateTime& time, const QString& iconURI, bool isIncoming, bool appendToPrevious, QtChatTheme* theme, const QString& id); + MessageSnippet(const QString& message, const QString& sender, const QDateTime& time, const QString& iconURI, bool isIncoming, bool appendToPrevious, QtChatTheme* theme, const QString& id, Direction direction); virtual ~MessageSnippet(); const QString& getContent() const { return content_; diff --git a/Swift/QtUI/QtChatView.cpp b/Swift/QtUI/QtChatView.cpp index ad3ba2a..18c6e91 100644 --- a/Swift/QtUI/QtChatView.cpp +++ b/Swift/QtUI/QtChatView.cpp @@ -142,6 +142,7 @@ QWebElement QtChatView::snippetToDOM(boost::shared_ptr snippet) { } void QtChatView::addToDOM(boost::shared_ptr snippet) { + //qDebug() << snippet->getContent(); rememberScrolledToBottom(); bool insert = snippet->getAppendToPrevious(); QWebElement continuationElement = lastElement_.findFirst("#insert"); @@ -164,6 +165,8 @@ void QtChatView::addToDOM(boost::shared_ptr snippet) { span.setStyleProperty("font-size", sizeString); } } + //qDebug() << "-----------------"; + //qDebug() << webPage_->mainFrame()->toHtml(); } void QtChatView::addLastSeenLine() { diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp index 237d78c..6dde1cc 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. */ @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -221,6 +222,15 @@ bool QtChatWindow::appendToPreviousCheck(QtChatWindow::PreviousMessageKind messa return previousMessageKind_ == messageKind && ((senderIsSelf && previousMessageWasSelf_) || (!senderIsSelf && !previousMessageWasSelf_&& previousSenderName_ == P2QSTRING(senderName))); } +ChatSnippet::Direction QtChatWindow::getActualDirection(const std::string& 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); } @@ -486,8 +496,19 @@ void QtChatWindow::updateTitleWithUnreadCount() { emit titleUpdated(); } -std::string QtChatWindow::addMessage(const std::string &message, const std::string &senderName, bool senderIsSelf, boost::shared_ptr label, const std::string& avatarPath, const boost::posix_time::ptime& time, const HighlightAction& highlight) { - return addMessage(linkimoticonify(P2QSTRING(message)), senderName, senderIsSelf, label, avatarPath, "", time, highlight); +std::string QtChatWindow::addMessage( + const std::string& message, + const std::string& senderName, + bool senderIsSelf, + boost::shared_ptr label, + const std::string& avatarPath, + const boost::posix_time::ptime& time, + const HighlightAction& highlight) { + return addMessage(linkimoticonify(message), senderName, senderIsSelf, label, avatarPath, "", time, highlight, ChatSnippet::getDirection(message)); +} + +QString QtChatWindow::linkimoticonify(const std::string& message) const { + return linkimoticonify(P2QSTRING(message)); } QString QtChatWindow::linkimoticonify(const QString& message) const { @@ -520,7 +541,17 @@ QString QtChatWindow::getHighlightSpanStart(const HighlightAction& highlight) { return QString("").arg(color).arg(background); } -std::string QtChatWindow::addMessage(const QString &message, const std::string &senderName, bool senderIsSelf, boost::shared_ptr label, const std::string& avatarPath, const QString& style, const boost::posix_time::ptime& time, const HighlightAction& highlight) { +std::string QtChatWindow::addMessage( + const QString& message, + const std::string& senderName, + bool senderIsSelf, + boost::shared_ptr label, + const std::string& avatarPath, + const QString& style, + const boost::posix_time::ptime& time, + const HighlightAction& highlight, + ChatSnippet::Direction direction) { + if (isWidgetSelected()) { onAllMessagesRead(); } @@ -547,7 +578,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(idCounter_++); - messageLog_->addMessageBottom(boost::shared_ptr(new MessageSnippet(htmlString, QtUtilities::htmlEscape(P2QSTRING(senderName)), B2QDATE(time), qAvatarPath, senderIsSelf, appendToPrevious, theme_, P2QSTRING(id)))); + messageLog_->addMessageBottom(boost::make_shared(htmlString, QtUtilities::htmlEscape(P2QSTRING(senderName)), B2QDATE(time), qAvatarPath, senderIsSelf, appendToPrevious, theme_, P2QSTRING(id), direction)); previousMessageWasSelf_ = senderIsSelf; previousSenderName_ = P2QSTRING(senderName); @@ -593,7 +624,7 @@ int QtChatWindow::getCount() { } std::string QtChatWindow::addAction(const std::string &message, const std::string &senderName, bool senderIsSelf, boost::shared_ptr label, const std::string& avatarPath, const boost::posix_time::ptime& time, const HighlightAction& highlight) { - return addMessage(" *" + linkimoticonify(P2QSTRING(message)) + "*", senderName, senderIsSelf, label, avatarPath, "font-style:italic ", time, highlight); + return addMessage(" *" + linkimoticonify(message) + "*", senderName, senderIsSelf, label, avatarPath, "font-style:italic ", time, highlight, ChatSnippet::getDirection(message)); } // FIXME: Move this to a different file @@ -627,11 +658,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(idCounter_++))); + QString actionText; QString htmlString; QString formattedFileSize = P2QSTRING(formatSize(sizeInBytes)); if (senderIsSelf) { // outgoing - htmlString = tr("Send file") + ": " + P2QSTRING(filename) + " ( " + formattedFileSize + ")
" + + actionText = tr("Send file"); + htmlString = actionText + ": " + P2QSTRING(filename) + " ( " + formattedFileSize + ")
" + "
" + buildChatWindowButton(tr("Cancel"), ButtonFileTransferCancel, ft_id) + buildChatWindowButton(tr("Set Description"), ButtonFileTransferSetDescription, ft_id) + @@ -639,7 +672,8 @@ std::string QtChatWindow::addFileTransfer(const std::string& senderName, bool se "
"; } else { // incoming - htmlString = tr("Receiving file") + ": " + P2QSTRING(filename) + " ( " + formattedFileSize + ")
" + + actionText = tr("Receiving file"); + htmlString = actionText + ": " + P2QSTRING(filename) + " ( " + formattedFileSize + ")
" + "
" + buildChatWindowButton(tr("Cancel"), ButtonFileTransferCancel, ft_id) + buildChatWindowButton(tr("Accept"), ButtonFileTransferAcceptRequest, ft_id, P2QSTRING(filename)) + @@ -657,7 +691,7 @@ std::string QtChatWindow::addFileTransfer(const std::string& senderName, bool se } QString qAvatarPath = "qrc:/icons/avatar.png"; std::string id = "ftmessage" + boost::lexical_cast(idCounter_++); - messageLog_->addMessageBottom(boost::shared_ptr(new MessageSnippet(htmlString, QtUtilities::htmlEscape(P2QSTRING(senderName)), B2QDATE(boost::posix_time::second_clock::local_time()), qAvatarPath, senderIsSelf, appendToPrevious, theme_, P2QSTRING(id)))); + messageLog_->addMessageBottom(boost::make_shared(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); @@ -676,12 +710,15 @@ void QtChatWindow::setFileTransferStatus(std::string id, const FileTransferState std::string QtChatWindow::addWhiteboardRequest(bool senderIsSelf) { QString wb_id = QString("wb%1").arg(P2QSTRING(boost::lexical_cast(idCounter_++))); QString htmlString; + QString actionText; if (senderIsSelf) { - htmlString = "
" + tr("Starting whiteboard chat") + "
"+ + actionText = tr("Starting whiteboard chat"); + htmlString = "
" + actionText + "
"+ buildChatWindowButton(tr("Cancel"), ButtonWhiteboardSessionCancel, wb_id) + "
"; } else { - htmlString = "
" + tr("%1 would like to start a whiteboard chat").arg(QtUtilities::htmlEscape(contact_)) + ":
" + + actionText = tr("%1 would like to start a whiteboard chat"); + htmlString = "
" + actionText.arg(QtUtilities::htmlEscape(contact_)) + ":
" + buildChatWindowButton(tr("Cancel"), ButtonWhiteboardSessionCancel, wb_id) + buildChatWindowButton(tr("Accept"), ButtonWhiteboardSessionAcceptRequest, wb_id) + "
"; @@ -695,7 +732,7 @@ std::string QtChatWindow::addWhiteboardRequest(bool senderIsSelf) { } QString qAvatarPath = "qrc:/icons/avatar.png"; std::string id = "wbmessage" + boost::lexical_cast(idCounter_++); - messageLog_->addMessageBottom(boost::shared_ptr(new MessageSnippet(htmlString, QtUtilities::htmlEscape(contact_), B2QDATE(boost::posix_time::second_clock::local_time()), qAvatarPath, false, false, theme_, P2QSTRING(id)))); + messageLog_->addMessageBottom(boost::make_shared(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_; @@ -770,32 +807,31 @@ void QtChatWindow::addErrorMessage(const std::string& errorMessage) { onAllMessagesRead(); } - QString errorMessageHTML(QtUtilities::htmlEscape(P2QSTRING(errorMessage))); + QString errorMessageHTML(linkimoticonify(errorMessage)); errorMessageHTML.replace("\n","
"); - messageLog_->addMessageBottom(boost::shared_ptr(new SystemMessageSnippet("" + errorMessageHTML + "", QDateTime::currentDateTime(), false, theme_))); + messageLog_->addMessageBottom(boost::make_shared("" + errorMessageHTML + "", QDateTime::currentDateTime(), false, theme_, ChatSnippet::getDirection(errorMessage))); previousMessageWasSelf_ = false; previousMessageKind_ = PreviousMessageWasSystem; } -void QtChatWindow::addSystemMessage(const std::string& message) { +void QtChatWindow::addSystemMessage(const std::string& message, Direction direction) { if (isWidgetSelected()) { onAllMessagesRead(); } - QString messageHTML(P2QSTRING(message)); - messageHTML = linkimoticonify(messageHTML); - messageLog_->addMessageBottom(boost::shared_ptr(new SystemMessageSnippet(messageHTML, QDateTime::currentDateTime(), false, theme_))); + QString messageHTML = linkimoticonify(message); + messageLog_->addMessageBottom(boost::make_shared(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, const HighlightAction& highlight) { - replaceMessage(" *" + linkimoticonify(P2QSTRING(message)) + "*", id, time, "font-style:italic ", highlight); + replaceMessage(" *" + linkimoticonify(message) + "*", id, time, "font-style:italic ", highlight); } void QtChatWindow::replaceMessage(const std::string& message, const std::string& id, const boost::posix_time::ptime& time, const HighlightAction& highlight) { - replaceMessage(linkimoticonify(P2QSTRING(message)), id, time, "", highlight); + replaceMessage(linkimoticonify(message), id, time, "", highlight); } void QtChatWindow::replaceMessage(const QString& message, const std::string& id, const boost::posix_time::ptime& time, const QString& style, const HighlightAction& highlight) { @@ -819,14 +855,13 @@ void QtChatWindow::replaceMessage(const QString& message, const std::string& id, } } -void QtChatWindow::addPresenceMessage(const std::string& message) { +void QtChatWindow::addPresenceMessage(const std::string& message, Direction direction) { if (isWidgetSelected()) { onAllMessagesRead(); } - QString messageHTML(P2QSTRING(message)); - messageHTML = linkimoticonify(messageHTML); - messageLog_->addMessageBottom(boost::shared_ptr(new SystemMessageSnippet(messageHTML, QDateTime::currentDateTime(), false, theme_))); + QString messageHTML = linkimoticonify(message); + messageLog_->addMessageBottom(boost::make_shared(messageHTML, QDateTime::currentDateTime(), false, theme_, getActualDirection(message, direction))); previousMessageKind_ = PreviousMessageWasPresence; } @@ -897,12 +932,13 @@ 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 message(Q2PSTRING(tr("Sending of multiple files at once isn't supported at this time."))); + addSystemMessage(message, DefaultDirection); } } void QtChatWindow::replaceLastMessage(const std::string& message) { - messageLog_->replaceLastMessage(linkimoticonify(P2QSTRING(message))); + messageLog_->replaceLastMessage(linkimoticonify(message)); } void QtChatWindow::setAvailableOccupantActions(const std::vector& actions) { @@ -1022,18 +1058,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())) + "
"; + 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)) + "
"; + htmlString += QObject::tr("Reason: %1").arg(P2QSTRING(reason)) + "\n"; } if (!direct) { - htmlString += QObject::tr("This person may not have really sent this invitation!") + "
"; + htmlString += QObject::tr("This person may not have really sent this invitation!") + "\n"; } + htmlString = linkimoticonify(htmlString); - QString id = QString(ButtonMUCInvite + "%1").arg(P2QSTRING(boost::lexical_cast(idCounter_++))); + QString id = QString(ButtonMUCInvite + "%1").arg(P2QSTRING(boost::lexical_cast(idCounter_++))); htmlString += "
" + - buildChatWindowButton(tr("Accept Invite"), ButtonMUCInvite, QtUtilities::htmlEscape(P2QSTRING(jid.toString())), QtUtilities::htmlEscape(P2QSTRING(password)), id) + + buildChatWindowButton(linkimoticonify(tr("Accept Invite")), ButtonMUCInvite, QtUtilities::htmlEscape(P2QSTRING(jid.toString())), QtUtilities::htmlEscape(P2QSTRING(password)), id) + "
"; bool appendToPrevious = appendToPreviousCheck(PreviousMessageWasMUCInvite, senderName, false); @@ -1045,7 +1083,7 @@ void QtChatWindow::addMUCInvitation(const std::string& senderName, const JID& ji } QString qAvatarPath = "qrc:/icons/avatar.png"; - messageLog_->addMessageBottom(boost::shared_ptr(new MessageSnippet(htmlString, QtUtilities::htmlEscape(P2QSTRING(senderName)), B2QDATE(boost::posix_time::second_clock::local_time()), qAvatarPath, false, appendToPrevious, theme_, id))); + messageLog_->addMessageBottom(boost::make_shared(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; diff --git a/Swift/QtUI/QtChatWindow.h b/Swift/QtUI/QtChatWindow.h index 3ccea31..a9600d4 100644 --- a/Swift/QtUI/QtChatWindow.h +++ b/Swift/QtUI/QtChatWindow.h @@ -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. */ @@ -10,6 +10,7 @@ #include #include #include +#include #include @@ -90,9 +91,11 @@ namespace Swift { ~QtChatWindow(); std::string addMessage(const std::string &message, const std::string &senderName, bool senderIsSelf, boost::shared_ptr label, const std::string& avatarPath, const boost::posix_time::ptime& time, const HighlightAction& highlight); std::string addAction(const std::string &message, const std::string &senderName, bool senderIsSelf, boost::shared_ptr label, const std::string& avatarPath, const boost::posix_time::ptime& time, const HighlightAction& highlight); - void addSystemMessage(const std::string& message); - void addPresenceMessage(const std::string& message); + + void addSystemMessage(const std::string& message, Direction direction); + void addPresenceMessage(const std::string& message, Direction direction); void addErrorMessage(const std::string& errorMessage); + void replaceMessage(const std::string& message, const std::string& id, const boost::posix_time::ptime& time, const HighlightAction& highlight); void replaceWithAction(const std::string& message, const std::string& id, const boost::posix_time::ptime& time, const HighlightAction& highlight); // File transfer related stuff @@ -193,10 +196,26 @@ namespace Swift { void beginCorrection(); void cancelCorrection(); void handleSettingChanged(const std::string& setting); - std::string addMessage(const QString& message, const std::string& senderName, bool senderIsSelf, boost::shared_ptr label, const std::string& avatarPath, const QString& style, const boost::posix_time::ptime& time, const HighlightAction& highlight); - void replaceMessage(const QString& message, const std::string& id, const boost::posix_time::ptime& time, const QString& style, const HighlightAction& highlight); + std::string addMessage( + const QString& message, + const std::string& senderName, + bool senderIsSelf, + boost::shared_ptr label, + const std::string& avatarPath, + const QString& style, + const boost::posix_time::ptime& time, + const HighlightAction& highlight, + ChatSnippet::Direction direction); + void replaceMessage( + const QString& message, + const std::string& id, + const boost::posix_time::ptime& time, + const QString& style, + const HighlightAction& highlight); void handleOccupantSelectionChanged(RosterItem* item); bool appendToPreviousCheck(PreviousMessageKind messageKind, const std::string& senderName, bool senderIsSelf) const; + static ChatSnippet::Direction getActualDirection(const std::string& message, Direction direction); + QString linkimoticonify(const std::string& message) const; QString linkimoticonify(const QString& message) const; QString getHighlightSpanStart(const HighlightAction& highlight); diff --git a/Swift/QtUI/QtHistoryWindow.cpp b/Swift/QtUI/QtHistoryWindow.cpp index 23621c6..6f22b76 100644 --- a/Swift/QtUI/QtHistoryWindow.cpp +++ b/Swift/QtUI/QtHistoryWindow.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Catalin Badea + * Copyright (c) 2012-2013 Catalin Badea * Licensed under the simplified BSD license. * See Documentation/Licenses/BSD-simplified.txt for more information. */ @@ -13,6 +13,7 @@ #include #include +#include #include #include @@ -20,6 +21,7 @@ #include #include #include +#include #include #include "QtUtilities.h" @@ -126,14 +128,14 @@ void QtHistoryWindow::addMessage(const std::string &message, const std::string & if (addAtTheTop) { bool appendToPrevious = ((senderIsSelf && previousTopMessageWasSelf_) || (!senderIsSelf && !previousTopMessageWasSelf_&& previousTopSenderName_ == P2QSTRING(senderName))); - conversation_->addMessageTop(boost::shared_ptr(new MessageSnippet(messageHTML, QtUtilities::htmlEscape(P2QSTRING(senderName)), qTime, qAvatarPath, senderIsSelf, appendToPrevious, theme_, P2QSTRING(id)))); + conversation_->addMessageTop(boost::shared_ptr(new MessageSnippet(messageHTML, QtUtilities::htmlEscape(P2QSTRING(senderName)), qTime, qAvatarPath, senderIsSelf, appendToPrevious, theme_, P2QSTRING(id), ChatSnippet::getDirection(message)))); previousTopMessageWasSelf_ = senderIsSelf; previousTopSenderName_ = P2QSTRING(senderName); } else { bool appendToPrevious = ((senderIsSelf && previousBottomMessageWasSelf_) || (!senderIsSelf && !previousBottomMessageWasSelf_&& previousBottomSenderName_ == P2QSTRING(senderName))); - conversation_->addMessageBottom(boost::shared_ptr(new MessageSnippet(messageHTML, QtUtilities::htmlEscape(P2QSTRING(senderName)), qTime, qAvatarPath, senderIsSelf, appendToPrevious, theme_, P2QSTRING(id)))); + conversation_->addMessageBottom(boost::make_shared(messageHTML, QtUtilities::htmlEscape(P2QSTRING(senderName)), qTime, qAvatarPath, senderIsSelf, appendToPrevious, theme_, P2QSTRING(id), ChatSnippet::getDirection(message))); previousBottomMessageWasSelf_ = senderIsSelf; previousBottomSenderName_ = P2QSTRING(senderName); } diff --git a/Swift/QtUI/SystemMessageSnippet.cpp b/Swift/QtUI/SystemMessageSnippet.cpp index c78fe36..39349bc 100644 --- a/Swift/QtUI/SystemMessageSnippet.cpp +++ b/Swift/QtUI/SystemMessageSnippet.cpp @@ -10,12 +10,13 @@ namespace Swift { -SystemMessageSnippet::SystemMessageSnippet(const QString& message, const QDateTime& time, bool appendToPrevious, QtChatTheme* theme) : ChatSnippet(appendToPrevious) { +SystemMessageSnippet::SystemMessageSnippet(const QString& message, const QDateTime& time, bool appendToPrevious, QtChatTheme* theme, Direction direction) : ChatSnippet(appendToPrevious) { if (appendToPrevious) { - setContinuationFallbackSnippet(boost::shared_ptr(new SystemMessageSnippet(message, time, false, theme))); + setContinuationFallbackSnippet(boost::shared_ptr(new SystemMessageSnippet(message, time, false, theme, direction))); } content_ = theme->getStatus(); + content_.replace("%direction%", directionToCSS(direction)); content_.replace("%message%", wrapResizable("" + escape(message) + "")); content_.replace("%shortTime%", wrapResizable(escape(time.toString("h:mm")))); content_.replace("%time%", wrapResizable("" + timeToEscapedString(time) + "")); diff --git a/Swift/QtUI/SystemMessageSnippet.h b/Swift/QtUI/SystemMessageSnippet.h index 69d231f..34b0d40 100644 --- a/Swift/QtUI/SystemMessageSnippet.h +++ b/Swift/QtUI/SystemMessageSnippet.h @@ -15,7 +15,7 @@ class QDateTime; namespace Swift { class SystemMessageSnippet : public ChatSnippet { public: - SystemMessageSnippet(const QString& message, const QDateTime& time, bool appendToPrevious, QtChatTheme* theme); + SystemMessageSnippet(const QString& message, const QDateTime& time, bool appendToPrevious, QtChatTheme* theme, Direction direction); virtual ~SystemMessageSnippet(); const QString& getContent() const {return content_;} diff --git a/Swift/resources/themes/Default/Incoming/Content.html b/Swift/resources/themes/Default/Incoming/Content.html index eb5bdea..fb4795f 100755 --- a/Swift/resources/themes/Default/Incoming/Content.html +++ b/Swift/resources/themes/Default/Incoming/Content.html @@ -11,7 +11,7 @@ - + %message%
%wrapped_sender% @ %time%
diff --git a/Swift/resources/themes/Default/Incoming/Context.html b/Swift/resources/themes/Default/Incoming/Context.html index b1aca27..c6fa61c 100755 --- a/Swift/resources/themes/Default/Incoming/Context.html +++ b/Swift/resources/themes/Default/Incoming/Context.html @@ -11,7 +11,7 @@ - + %message%
%sender% @ %time%
diff --git a/Swift/resources/themes/Default/Incoming/NextContent.html b/Swift/resources/themes/Default/Incoming/NextContent.html index 4aec8ab..aff669b 100755 --- a/Swift/resources/themes/Default/Incoming/NextContent.html +++ b/Swift/resources/themes/Default/Incoming/NextContent.html @@ -1,6 +1,6 @@
-
+
%message%
%time%
diff --git a/Swift/resources/themes/Default/Incoming/NextContext.html b/Swift/resources/themes/Default/Incoming/NextContext.html index 18b8dc4..c0a8846 100755 --- a/Swift/resources/themes/Default/Incoming/NextContext.html +++ b/Swift/resources/themes/Default/Incoming/NextContext.html @@ -1,5 +1,5 @@
-
+
%message%
%time%
diff --git a/Swift/resources/themes/Default/Outgoing/Content.html b/Swift/resources/themes/Default/Outgoing/Content.html index f855f56..87ca272 100755 --- a/Swift/resources/themes/Default/Outgoing/Content.html +++ b/Swift/resources/themes/Default/Outgoing/Content.html @@ -11,7 +11,7 @@ - + %message%
%wrapped_sender% @ %time%
diff --git a/Swift/resources/themes/Default/Outgoing/Context.html b/Swift/resources/themes/Default/Outgoing/Context.html index 7822cac..229c592 100755 --- a/Swift/resources/themes/Default/Outgoing/Context.html +++ b/Swift/resources/themes/Default/Outgoing/Context.html @@ -11,7 +11,7 @@ - + %message%
%sender% @ %time%
diff --git a/Swift/resources/themes/Default/Outgoing/NextContent.html b/Swift/resources/themes/Default/Outgoing/NextContent.html index 4367197..fe6490e 100755 --- a/Swift/resources/themes/Default/Outgoing/NextContent.html +++ b/Swift/resources/themes/Default/Outgoing/NextContent.html @@ -1,6 +1,6 @@
-
+
%message%
%time%
diff --git a/Swift/resources/themes/Default/Outgoing/NextContext.html b/Swift/resources/themes/Default/Outgoing/NextContext.html index 1f84771..f66aeeb 100755 --- a/Swift/resources/themes/Default/Outgoing/NextContext.html +++ b/Swift/resources/themes/Default/Outgoing/NextContext.html @@ -1,5 +1,5 @@
-
+
%message%
%time%
diff --git a/Swift/resources/themes/Default/Status.html b/Swift/resources/themes/Default/Status.html index b8168e8..e7add89 100755 --- a/Swift/resources/themes/Default/Status.html +++ b/Swift/resources/themes/Default/Status.html @@ -9,7 +9,7 @@ - + %message%
%time%
-- cgit v0.10.2-6-g49f6