mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
fix(history): display broken messages UI with error icon
Allows users to still see their broken messages in the chatlog, but in a way that's clear that they haven't been delivered and won't be sent.
This commit is contained in:
parent
527c7d2d3c
commit
1a726b54cd
|
@ -290,6 +290,8 @@ set(${PROJECT_NAME}_SOURCES
|
||||||
src/chatlog/content/text.h
|
src/chatlog/content/text.h
|
||||||
src/chatlog/content/timestamp.cpp
|
src/chatlog/content/timestamp.cpp
|
||||||
src/chatlog/content/timestamp.h
|
src/chatlog/content/timestamp.h
|
||||||
|
src/chatlog/content/broken.cpp
|
||||||
|
src/chatlog/content/broken.h
|
||||||
src/chatlog/customtextdocument.cpp
|
src/chatlog/customtextdocument.cpp
|
||||||
src/chatlog/customtextdocument.h
|
src/chatlog/customtextdocument.h
|
||||||
src/chatlog/documentcache.cpp
|
src/chatlog/documentcache.cpp
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "content/spinner.h"
|
#include "content/spinner.h"
|
||||||
#include "content/text.h"
|
#include "content/text.h"
|
||||||
#include "content/timestamp.h"
|
#include "content/timestamp.h"
|
||||||
|
#include "content/broken.h"
|
||||||
#include "src/widget/style.h"
|
#include "src/widget/style.h"
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
@ -33,6 +34,7 @@
|
||||||
|
|
||||||
#include "src/persistence/settings.h"
|
#include "src/persistence/settings.h"
|
||||||
#include "src/persistence/smileypack.h"
|
#include "src/persistence/smileypack.h"
|
||||||
|
#include "src/persistence/history.h"
|
||||||
|
|
||||||
#define NAME_COL_WIDTH 90.0
|
#define NAME_COL_WIDTH 90.0
|
||||||
#define TIME_COL_WIDTH 90.0
|
#define TIME_COL_WIDTH 90.0
|
||||||
|
@ -43,7 +45,8 @@ ChatMessage::ChatMessage()
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatMessage::Ptr ChatMessage::createChatMessage(const QString& sender, const QString& rawMessage,
|
ChatMessage::Ptr ChatMessage::createChatMessage(const QString& sender, const QString& rawMessage,
|
||||||
MessageType type, bool isMe, const QDateTime& date, bool colorizeName)
|
MessageType type, bool isMe, MessageState state,
|
||||||
|
const QDateTime& date, bool colorizeName)
|
||||||
{
|
{
|
||||||
ChatMessage::Ptr msg = ChatMessage::Ptr(new ChatMessage);
|
ChatMessage::Ptr msg = ChatMessage::Ptr(new ChatMessage);
|
||||||
|
|
||||||
|
@ -105,12 +108,21 @@ ChatMessage::Ptr ChatMessage::createChatMessage(const QString& sender, const QSt
|
||||||
? QString("%1 %2").arg(sender, rawMessage)
|
? QString("%1 %2").arg(sender, rawMessage)
|
||||||
: rawMessage),
|
: rawMessage),
|
||||||
ColumnFormat(1.0, ColumnFormat::VariableSize));
|
ColumnFormat(1.0, ColumnFormat::VariableSize));
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case MessageState::complete:
|
||||||
|
msg->addColumn(new Timestamp(date, Settings::getInstance().getTimestampFormat(), baseFont),
|
||||||
|
ColumnFormat(TIME_COL_WIDTH, ColumnFormat::FixedSize, ColumnFormat::Right));
|
||||||
|
break;
|
||||||
|
case MessageState::pending:
|
||||||
msg->addColumn(new Spinner(Style::getImagePath("chatArea/spinner.svg"), QSize(16, 16), 360.0 / 1.6),
|
msg->addColumn(new Spinner(Style::getImagePath("chatArea/spinner.svg"), QSize(16, 16), 360.0 / 1.6),
|
||||||
ColumnFormat(TIME_COL_WIDTH, ColumnFormat::FixedSize, ColumnFormat::Right));
|
ColumnFormat(TIME_COL_WIDTH, ColumnFormat::FixedSize, ColumnFormat::Right));
|
||||||
|
break;
|
||||||
if (!date.isNull())
|
case MessageState::broken:
|
||||||
msg->markAsDelivered(date);
|
msg->addColumn(new Broken(Style::getImagePath("chatArea/error.svg"), QSize(16, 16)),
|
||||||
|
ColumnFormat(TIME_COL_WIDTH, ColumnFormat::FixedSize, ColumnFormat::Right));
|
||||||
|
break;
|
||||||
|
}
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
|
|
||||||
#include "chatline.h"
|
#include "chatline.h"
|
||||||
#include "src/core/toxfile.h"
|
#include "src/core/toxfile.h"
|
||||||
|
#include "src/persistence/history.h"
|
||||||
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
|
||||||
class QGraphicsScene;
|
class QGraphicsScene;
|
||||||
|
@ -48,8 +50,8 @@ public:
|
||||||
ChatMessage();
|
ChatMessage();
|
||||||
|
|
||||||
static ChatMessage::Ptr createChatMessage(const QString& sender, const QString& rawMessage,
|
static ChatMessage::Ptr createChatMessage(const QString& sender, const QString& rawMessage,
|
||||||
MessageType type, bool isMe,
|
MessageType type, bool isMe, MessageState state,
|
||||||
const QDateTime& date = QDateTime(), bool colorizeName = false);
|
const QDateTime& date, bool colorizeName = false);
|
||||||
static ChatMessage::Ptr createChatInfoMessage(const QString& rawMessage, SystemMessageType type,
|
static ChatMessage::Ptr createChatInfoMessage(const QString& rawMessage, SystemMessageType type,
|
||||||
const QDateTime& date);
|
const QDateTime& date);
|
||||||
static ChatMessage::Ptr createFileTransferMessage(const QString& sender, ToxFile file,
|
static ChatMessage::Ptr createFileTransferMessage(const QString& sender, ToxFile file,
|
||||||
|
|
61
src/chatlog/content/broken.cpp
Normal file
61
src/chatlog/content/broken.cpp
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
Copyright © 2019 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 "broken.h"
|
||||||
|
#include "src/chatlog/pixmapcache.h"
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
|
class QStyleOptionGraphicsItem;
|
||||||
|
|
||||||
|
Broken::Broken(const QString& img, QSize size)
|
||||||
|
: pmap{PixmapCache::getInstance().get(img, size)}
|
||||||
|
, size{size}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF Broken::boundingRect() const
|
||||||
|
{
|
||||||
|
return QRectF(QPointF(-size.width() / 2.0, -size.height() / 2.0), size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Broken::paint(QPainter* painter, const QStyleOptionGraphicsItem* option,
|
||||||
|
QWidget* widget)
|
||||||
|
{
|
||||||
|
painter->setRenderHint(QPainter::SmoothPixmapTransform);
|
||||||
|
painter->drawPixmap(0, 0, pmap);
|
||||||
|
|
||||||
|
Q_UNUSED(option)
|
||||||
|
Q_UNUSED(widget)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Broken::setWidth(qreal width)
|
||||||
|
{
|
||||||
|
Q_UNUSED(width);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Broken::visibilityChanged(bool visible)
|
||||||
|
{
|
||||||
|
Q_UNUSED(visible);
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal Broken::getAscent() const
|
||||||
|
{
|
||||||
|
return 0.0;
|
||||||
|
}
|
45
src/chatlog/content/broken.h
Normal file
45
src/chatlog/content/broken.h
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
Copyright © 2019 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BROKEN_H
|
||||||
|
#define BROKEN_H
|
||||||
|
|
||||||
|
#include "../chatlinecontent.h"
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QPixmap>
|
||||||
|
|
||||||
|
class Broken : public ChatLineContent
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
Broken(const QString& img, QSize size);
|
||||||
|
QRectF boundingRect() const override;
|
||||||
|
void paint(QPainter* painter, const QStyleOptionGraphicsItem* option,
|
||||||
|
QWidget* widget) override;
|
||||||
|
void setWidth(qreal width) override;
|
||||||
|
void visibilityChanged(bool visible) override;
|
||||||
|
qreal getAscent() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QSize size;
|
||||||
|
QPixmap pmap;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // BROKEN_H
|
|
@ -394,19 +394,23 @@ void ChatHistory::loadHistoryIntoSessionChatLog(ChatLogIdx start) const
|
||||||
std::find_if(dispatchedMessageRowIdMap.begin(), dispatchedMessageRowIdMap.end(),
|
std::find_if(dispatchedMessageRowIdMap.begin(), dispatchedMessageRowIdMap.end(),
|
||||||
[&](RowId dispatchedId) { return dispatchedId == message.id; });
|
[&](RowId dispatchedId) { return dispatchedId == message.id; });
|
||||||
|
|
||||||
MessageState messageState;
|
assert((message.state != MessageState::pending && dispatchedMessageIt == dispatchedMessageRowIdMap.end()) ||
|
||||||
if (dispatchedMessageIt == dispatchedMessageRowIdMap.end()) {
|
(message.state == MessageState::pending && dispatchedMessageIt != dispatchedMessageRowIdMap.end()));
|
||||||
messageState = MessageState::complete;
|
|
||||||
} else {
|
auto chatLogMessage = ChatLogMessage{message.state, processedMessage};
|
||||||
messageState = MessageState::pending;
|
switch (message.state) {
|
||||||
}
|
case MessageState::complete:
|
||||||
auto chatLogMessage = ChatLogMessage{messageState, processedMessage};
|
|
||||||
if (messageState == MessageState::complete) {
|
|
||||||
sessionChatLog.insertCompleteMessageAtIdx(currentIdx, sender, message.dispName,
|
sessionChatLog.insertCompleteMessageAtIdx(currentIdx, sender, message.dispName,
|
||||||
chatLogMessage);
|
chatLogMessage);
|
||||||
} else {
|
break;
|
||||||
|
case MessageState::pending:
|
||||||
sessionChatLog.insertIncompleteMessageAtIdx(currentIdx, sender, message.dispName,
|
sessionChatLog.insertIncompleteMessageAtIdx(currentIdx, sender, message.dispName,
|
||||||
chatLogMessage, dispatchedMessageIt.key());
|
chatLogMessage, dispatchedMessageIt.key());
|
||||||
|
break;
|
||||||
|
case MessageState::broken:
|
||||||
|
sessionChatLog.insertBrokenMessageAtIdx(currentIdx, sender, message.dispName,
|
||||||
|
chatLogMessage);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -324,6 +324,20 @@ void SessionChatLog::insertIncompleteMessageAtIdx(ChatLogIdx idx, const ToxPk& s
|
||||||
outgoingMessages.insert(dispatchId, idx);
|
outgoingMessages.insert(dispatchId, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SessionChatLog::insertBrokenMessageAtIdx(ChatLogIdx idx, const ToxPk& sender, const QString& senderName,
|
||||||
|
const ChatLogMessage& message)
|
||||||
|
{
|
||||||
|
auto item = ChatLogItem(sender, message);
|
||||||
|
|
||||||
|
if (!senderName.isEmpty()) {
|
||||||
|
item.setDisplayName(senderName);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(message.state == MessageState::broken);
|
||||||
|
|
||||||
|
items.emplace(idx, std::move(item));
|
||||||
|
}
|
||||||
|
|
||||||
void SessionChatLog::insertFileAtIdx(ChatLogIdx idx, const ToxPk& sender, const QString& senderName, const ChatLogFile& file)
|
void SessionChatLog::insertFileAtIdx(ChatLogIdx idx, const ToxPk& sender, const QString& senderName, const ChatLogFile& file)
|
||||||
{
|
{
|
||||||
auto item = ChatLogItem(sender, file);
|
auto item = ChatLogItem(sender, file);
|
||||||
|
|
|
@ -51,6 +51,8 @@ public:
|
||||||
const ChatLogMessage& message);
|
const ChatLogMessage& message);
|
||||||
void insertIncompleteMessageAtIdx(ChatLogIdx idx, const ToxPk& sender, const QString& senderName,
|
void insertIncompleteMessageAtIdx(ChatLogIdx idx, const ToxPk& sender, const QString& senderName,
|
||||||
const ChatLogMessage& message, DispatchedMessageId dispatchId);
|
const ChatLogMessage& message, DispatchedMessageId dispatchId);
|
||||||
|
void insertBrokenMessageAtIdx(ChatLogIdx idx, const ToxPk& sender, const QString& senderName,
|
||||||
|
const ChatLogMessage& message);
|
||||||
void insertFileAtIdx(ChatLogIdx idx, const ToxPk& sender, const QString& senderName, const ChatLogFile& file);
|
void insertFileAtIdx(ChatLogIdx idx, const ToxPk& sender, const QString& senderName, const ChatLogFile& file);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
|
@ -178,11 +178,9 @@ ChatMessage::Ptr createMessage(const QString& displayName, bool isSelf, bool col
|
||||||
messageType = ChatMessage::MessageType::ALERT;
|
messageType = ChatMessage::MessageType::ALERT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spinner is displayed by passing in an empty date
|
const auto timestamp = chatLogMessage.message.timestamp;
|
||||||
auto timestamp = chatLogMessage.state == MessageState::complete ? chatLogMessage.message.timestamp : QDateTime();
|
|
||||||
|
|
||||||
return ChatMessage::createChatMessage(displayName, chatLogMessage.message.content, messageType,
|
return ChatMessage::createChatMessage(displayName, chatLogMessage.message.content, messageType,
|
||||||
isSelf, timestamp, colorizeNames);
|
isSelf, chatLogMessage.state, timestamp, colorizeNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderMessage(const QString& displayName, bool isSelf, bool colorizeNames,
|
void renderMessage(const QString& displayName, bool isSelf, bool colorizeNames,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user