1
0
mirror of https://github.com/qTox/qTox.git synced 2024-03-22 14:00:36 +08:00
qTox/src/chatlog/chatmessage.cpp

268 lines
8.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
Copyright © 2014-2015 by The qTox Project Contributors
This file is part of qTox, a Qt-based graphical interface for Tox.
qTox is libre software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
qTox is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with qTox. If not, see <http://www.gnu.org/licenses/>.
*/
#include "chatmessage.h"
#include "chatlinecontentproxy.h"
#include "textformatter.h"
#include "content/filetransferwidget.h"
#include "content/image.h"
#include "content/notificationicon.h"
#include "content/spinner.h"
#include "content/text.h"
#include "content/timestamp.h"
#include <QDebug>
#include "src/persistence/settings.h"
#include "src/persistence/smileypack.h"
#define NAME_COL_WIDTH 90.0
#define TIME_COL_WIDTH 90.0
ChatMessage::ChatMessage()
{
}
ChatMessage::Ptr ChatMessage::createChatMessage(const QString& sender, const QString& rawMessage,
MessageType type, bool isMe, const QDateTime& date)
{
ChatMessage::Ptr msg = ChatMessage::Ptr(new ChatMessage);
QString text = rawMessage.toHtmlEscaped();
QString senderText = sender;
const QColor actionColor =
QColor("#1818FF"); // has to match the color in innerStyle.css (div.action)
// smileys
if (Settings::getInstance().getUseEmoticons())
text = SmileyPack::getInstance().smileyfied(text);
// quotes (green text)
text = detectQuotes(text, type);
// text styling
Settings::StyleType styleType = Settings::getInstance().getStylePreference();
if (styleType != Settings::StyleType::NONE) {
TextFormatter tf = TextFormatter(text);
text = tf.applyStyling(styleType == Settings::StyleType::WITH_CHARS);
}
switch (type) {
case NORMAL:
text = wrapDiv(text, "msg");
break;
case ACTION:
senderText = "*";
text = wrapDiv(QString("%1 %2").arg(sender.toHtmlEscaped(), text), "action");
msg->setAsAction();
break;
case ALERT:
text = wrapDiv(text, "alert");
break;
}
// Note: Eliding cannot be enabled for RichText items. (QTBUG-17207)
QFont baseFont = Settings::getInstance().getChatMessageFont();
QFont authorFont = baseFont;
if (isMe)
authorFont.setBold(true);
msg->addColumn(new Text(senderText, authorFont, true, sender,
type == ACTION ? actionColor : Qt::black),
ColumnFormat(NAME_COL_WIDTH, ColumnFormat::FixedSize, ColumnFormat::Right));
msg->addColumn(new Text(text, baseFont, false, ((type == ACTION) && isMe)
? QString("%1 %2").arg(sender, rawMessage)
: rawMessage),
ColumnFormat(1.0, ColumnFormat::VariableSize));
msg->addColumn(new Spinner(":/ui/chatArea/spinner.svg", QSize(16, 16), 360.0 / 1.6),
ColumnFormat(TIME_COL_WIDTH, ColumnFormat::FixedSize, ColumnFormat::Right));
if (!date.isNull())
msg->markAsSent(date);
return msg;
}
ChatMessage::Ptr ChatMessage::createChatInfoMessage(const QString& rawMessage,
SystemMessageType type, const QDateTime& date)
{
ChatMessage::Ptr msg = ChatMessage::Ptr(new ChatMessage);
QString text = rawMessage.toHtmlEscaped();
QString img;
switch (type) {
case INFO:
img = ":/ui/chatArea/info.svg";
break;
case ERROR:
img = ":/ui/chatArea/error.svg";
break;
case TYPING:
img = ":/ui/chatArea/typing.svg";
break;
}
QFont baseFont = Settings::getInstance().getChatMessageFont();
msg->addColumn(new Image(QSize(18, 18), img),
ColumnFormat(NAME_COL_WIDTH, ColumnFormat::FixedSize, ColumnFormat::Right));
msg->addColumn(new Text("<b>" + text + "</b>", baseFont, false, ""),
ColumnFormat(1.0, ColumnFormat::VariableSize, ColumnFormat::Left));
msg->addColumn(new Timestamp(date, Settings::getInstance().getTimestampFormat(), baseFont),
ColumnFormat(TIME_COL_WIDTH, ColumnFormat::FixedSize, ColumnFormat::Right));
return msg;
}
ChatMessage::Ptr ChatMessage::createFileTransferMessage(const QString& sender, ToxFile file,
bool isMe, const QDateTime& date)
{
ChatMessage::Ptr msg = ChatMessage::Ptr(new ChatMessage);
QFont baseFont = Settings::getInstance().getChatMessageFont();
QFont authorFont = baseFont;
if (isMe)
authorFont.setBold(true);
msg->addColumn(new Text(sender, authorFont, true),
ColumnFormat(NAME_COL_WIDTH, ColumnFormat::FixedSize, ColumnFormat::Right));
msg->addColumn(new ChatLineContentProxy(new FileTransferWidget(0, file), 320, 0.6f),
ColumnFormat(1.0, ColumnFormat::VariableSize));
msg->addColumn(new Timestamp(date, Settings::getInstance().getTimestampFormat(), baseFont),
ColumnFormat(TIME_COL_WIDTH, ColumnFormat::FixedSize, ColumnFormat::Right));
return msg;
}
ChatMessage::Ptr ChatMessage::createTypingNotification()
{
ChatMessage::Ptr msg = ChatMessage::Ptr(new ChatMessage);
QFont baseFont = Settings::getInstance().getChatMessageFont();
// Note: "[user]..." is just a placeholder. The actual text is set in
// ChatForm::setFriendTyping()
//
// FIXME: Due to circumstances, placeholder is being used in a case where
// user received typing notifications constantly since contact came online.
// This causes "[user]..." to be displayed in place of user nick, as long
// as user will keep typing. Issue #1280
msg->addColumn(new NotificationIcon(QSize(18, 18)),
ColumnFormat(NAME_COL_WIDTH, ColumnFormat::FixedSize, ColumnFormat::Right));
msg->addColumn(new Text("[user]...", baseFont, false, ""),
ColumnFormat(1.0, ColumnFormat::VariableSize, ColumnFormat::Left));
return msg;
}
/**
* @brief Create message placeholder while chatform restructures text
*
* It can take a while for chatform to resize large amounts of text, thus
* a message placeholder is needed to inform users about it.
*
* @return created message
*/
ChatMessage::Ptr ChatMessage::createBusyNotification()
{
ChatMessage::Ptr msg = ChatMessage::Ptr(new ChatMessage);
QFont baseFont = Settings::getInstance().getChatMessageFont();
baseFont.setPixelSize(baseFont.pixelSize() + 2);
baseFont.setBold(true);
msg->addColumn(new Text(QObject::tr("Reformatting text in progress.."), baseFont, false, ""),
ColumnFormat(1.0, ColumnFormat::VariableSize, ColumnFormat::Center));
return msg;
}
void ChatMessage::markAsSent(const QDateTime& time)
{
QFont baseFont = Settings::getInstance().getChatMessageFont();
// remove the spinner and replace it by $time
replaceContent(2, new Timestamp(time, Settings::getInstance().getTimestampFormat(), baseFont));
}
QString ChatMessage::toString() const
{
ChatLineContent* c = getContent(1);
if (c)
return c->getText();
return QString();
}
bool ChatMessage::isAction() const
{
return action;
}
void ChatMessage::setAsAction()
{
action = true;
}
void ChatMessage::hideSender()
{
ChatLineContent* c = getContent(0);
if (c)
c->hide();
}
void ChatMessage::hideDate()
{
ChatLineContent* c = getContent(2);
if (c)
c->hide();
}
QString ChatMessage::detectQuotes(const QString& str, MessageType type)
{
// detect text quotes
QStringList messageLines = str.split("\n");
QString quotedText;
for (int i = 0; i < messageLines.size(); ++i) {
// don't quote first line in action message. This makes co-existence of
// quotes and action messages possible, since only first line can cause
// problems in case where there is quote in it used.
if (QRegExp("^(&gt;|).*").exactMatch(messageLines[i])) {
if (i > 0 || type != ACTION)
quotedText += "<span class=quote>" + messageLines[i] + "</span>";
else
quotedText += messageLines[i];
} else {
quotedText += messageLines[i];
}
if (i < messageLines.size() - 1) {
quotedText += '\n';
}
}
return quotedText;
}
QString ChatMessage::wrapDiv(const QString& str, const QString& div)
{
return QString("<p class=%1>%2</p>").arg(div, /*QChar(0x200E) + */ QString(str));
}