Skip to content
Snippets Groups Projects
Commit 34f5400e authored by Nicolas Werner's avatar Nicolas Werner
Browse files

Implement TextMessage delegate

Text selection over multiple items doesn't work yet
parent 56e27ced
No related branches found
No related tags found
No related merge requests found
import QtQuick 2.5
import QtQuick 2.6
import QtQuick.Controls 2.5
import QtQuick.Layouts 1.5
import com.github.nheko 1.0
Rectangle {
anchors.fill: parent
......@@ -26,20 +28,43 @@ Rectangle {
}
model: timelineManager.timeline
spacing: 4
delegate: RowLayout {
anchors.leftMargin: 52
anchors.left: parent.left
anchors.right: parent.right
anchors.rightMargin: scrollbar.width
Text {
Loader {
id: loader
Layout.fillWidth: true
height: contentHeight
text: "Event content"
height: item.height
Layout.alignment: Qt.AlignTop
source: switch(model.type) {
case MtxEvent.Aliases: return "delegates/Aliases.qml"
case MtxEvent.Avatar: return "delegates/Avatar.qml"
case MtxEvent.CanonicalAlias: return "delegates/CanonicalAlias.qml"
case MtxEvent.Create: return "delegates/Create.qml"
case MtxEvent.GuestAccess: return "delegates/GuestAccess.qml"
case MtxEvent.HistoryVisibility: return "delegates/HistoryVisibility.qml"
case MtxEvent.JoinRules: return "delegates/JoinRules.qml"
case MtxEvent.Member: return "delegates/Member.qml"
case MtxEvent.Name: return "delegates/Name.qml"
case MtxEvent.PowerLevels: return "delegates/PowerLevels.qml"
case MtxEvent.Topic: return "delegates/Topic.qml"
case MtxEvent.NoticeMessage: return "delegates/NoticeMessage.qml"
case MtxEvent.TextMessage: return "delegates/TextMessage.qml"
case MtxEvent.ImageMessage: return "delegates/ImageMessage.qml"
case MtxEvent.VideoMessage: return "delegates/VideoMessage.qml"
default: return "delegates/placeholder.qml"
}
property variant eventData: model
}
Button {
Layout.alignment: Qt.AlignRight
Layout.alignment: Qt.AlignRight | Qt.AlignTop
id: replyButton
flat: true
height: replyButtonImg.contentHeight
......@@ -54,7 +79,7 @@ Rectangle {
}
}
Button {
Layout.alignment: Qt.AlignRight
Layout.alignment: Qt.AlignRight | Qt.AlignTop
id: optionsButton
flat: true
height: optionsButtonImg.contentHeight
......@@ -90,7 +115,7 @@ Rectangle {
}
Text {
Layout.alignment: Qt.AlignRight
Layout.alignment: Qt.AlignRight | Qt.AlignTop
text: model.timestamp.toLocaleTimeString("HH:mm")
}
}
......@@ -98,13 +123,18 @@ Rectangle {
section {
property: "section"
delegate: Column {
topPadding: 4
bottomPadding: 4
spacing: 8
width: parent.width
height: dateBubble.visible ? dateBubble.height + userName.height : userName.height
Label {
id: dateBubble
anchors.horizontalCenter: parent.horizontalCenter
visible: section.includes(" ")
text: chat.model.formatDateSeparator(new Date(Number(section.split(" ")[1])))
height: contentHeight * 1.2
width: contentWidth * 1.2
horizontalAlignment: Text.AlignHCenter
......@@ -114,6 +144,7 @@ Rectangle {
}
}
Row {
height: userName.height
spacing: 4
Rectangle {
width: 48
......
import QtQuick 2.5
TextEdit {
text: eventData.formattedBody
textFormat: TextEdit.RichText
readOnly: true
wrapMode: Text.Wrap
width: parent.width
selectByMouse: true
}
......@@ -116,5 +116,6 @@
</qresource>
<qresource prefix="/">
<file>qml/TimelineView.qml</file>
<file>qml/delegates/TextMessage.qml</file>
</qresource>
</RCC>
#include "TimelineModel.h"
#include <type_traits>
#include <QRegularExpression>
#include "Logging.h"
......@@ -31,6 +33,119 @@ eventTimestamp(const T &event)
{
return QDateTime::fromMSecsSinceEpoch(event.origin_server_ts);
}
template<class T>
QString
eventFormattedBody(const mtx::events::Event<T> &)
{
return QString("");
}
template<class T>
auto
eventFormattedBody(const mtx::events::RoomEvent<T> &e)
-> std::enable_if_t<std::is_same<decltype(e.content.formatted_body), std::string>::value, QString>
{
auto temp = e.content.formatted_body;
if (!temp.empty()) {
auto pos = temp.find("<mx-reply>");
if (pos != std::string::npos)
temp.erase(pos, std::string("<mx-reply>").size());
pos = temp.find("</mx-reply>");
if (pos != std::string::npos)
temp.erase(pos, std::string("</mx-reply>").size());
return QString::fromStdString(temp);
} else
return QString::fromStdString(e.content.body);
}
template<class T>
qml_mtx_events::EventType
toRoomEventType(const mtx::events::Event<T> &e)
{
using mtx::events::EventType;
switch (e.type) {
case EventType::RoomKeyRequest:
return qml_mtx_events::EventType::KeyRequest;
case EventType::RoomAliases:
return qml_mtx_events::EventType::Aliases;
case EventType::RoomAvatar:
return qml_mtx_events::EventType::Avatar;
case EventType::RoomCanonicalAlias:
return qml_mtx_events::EventType::CanonicalAlias;
case EventType::RoomCreate:
return qml_mtx_events::EventType::Create;
case EventType::RoomEncrypted:
return qml_mtx_events::EventType::Encrypted;
case EventType::RoomEncryption:
return qml_mtx_events::EventType::Encryption;
case EventType::RoomGuestAccess:
return qml_mtx_events::EventType::GuestAccess;
case EventType::RoomHistoryVisibility:
return qml_mtx_events::EventType::HistoryVisibility;
case EventType::RoomJoinRules:
return qml_mtx_events::EventType::JoinRules;
case EventType::RoomMember:
return qml_mtx_events::EventType::Member;
case EventType::RoomMessage:
return qml_mtx_events::EventType::UnknownMessage;
case EventType::RoomName:
return qml_mtx_events::EventType::Name;
case EventType::RoomPowerLevels:
return qml_mtx_events::EventType::PowerLevels;
case EventType::RoomTopic:
return qml_mtx_events::EventType::Topic;
case EventType::RoomTombstone:
return qml_mtx_events::EventType::Tombstone;
case EventType::RoomRedaction:
return qml_mtx_events::EventType::Redaction;
case EventType::RoomPinnedEvents:
return qml_mtx_events::EventType::PinnedEvents;
case EventType::Sticker:
return qml_mtx_events::EventType::Sticker;
case EventType::Tag:
return qml_mtx_events::EventType::Tag;
case EventType::Unsupported:
default:
return qml_mtx_events::EventType::Unsupported;
}
}
qml_mtx_events::EventType
toRoomEventType(const mtx::events::Event<mtx::events::msg::Audio> &)
{
return qml_mtx_events::EventType::AudioMessage;
}
qml_mtx_events::EventType
toRoomEventType(const mtx::events::Event<mtx::events::msg::Emote> &)
{
return qml_mtx_events::EventType::EmoteMessage;
}
qml_mtx_events::EventType
toRoomEventType(const mtx::events::Event<mtx::events::msg::File> &)
{
return qml_mtx_events::EventType::FileMessage;
}
qml_mtx_events::EventType
toRoomEventType(const mtx::events::Event<mtx::events::msg::Image> &)
{
return qml_mtx_events::EventType::ImageMessage;
}
qml_mtx_events::EventType
toRoomEventType(const mtx::events::Event<mtx::events::msg::Notice> &)
{
return qml_mtx_events::EventType::NoticeMessage;
}
qml_mtx_events::EventType
toRoomEventType(const mtx::events::Event<mtx::events::msg::Text> &)
{
return qml_mtx_events::EventType::TextMessage;
}
qml_mtx_events::EventType
toRoomEventType(const mtx::events::Event<mtx::events::msg::Video> &)
{
return qml_mtx_events::EventType::VideoMessage;
}
// ::EventType::Type toRoomEventType(const Event<mtx::events::msg::Location> &e) { return
// ::EventType::LocationMessage; }
}
TimelineModel::TimelineModel(QString room_id, QObject *parent)
......@@ -105,6 +220,14 @@ TimelineModel::data(const QModelIndex &index, int role) const
case Timestamp:
return QVariant(boost::apply_visitor(
[](const auto &e) -> QDateTime { return eventTimestamp(e); }, events.value(id)));
case Type:
return QVariant(boost::apply_visitor(
[](const auto &e) -> qml_mtx_events::EventType { return toRoomEventType(e); },
events.value(id)));
case FormattedBody:
return QVariant(utils::replaceEmoji(boost::apply_visitor(
[](const auto &e) -> QString { return eventFormattedBody(e); },
events.value(id))));
default:
return QVariant();
}
......
......@@ -7,6 +7,65 @@
#include <mtx/responses.hpp>
namespace qml_mtx_events {
Q_NAMESPACE
enum EventType
{
// Unsupported event
Unsupported,
/// m.room_key_request
KeyRequest,
/// m.room.aliases
Aliases,
/// m.room.avatar
Avatar,
/// m.room.canonical_alias
CanonicalAlias,
/// m.room.create
Create,
/// m.room.encrypted.
Encrypted,
/// m.room.encryption.
Encryption,
/// m.room.guest_access
GuestAccess,
/// m.room.history_visibility
HistoryVisibility,
/// m.room.join_rules
JoinRules,
/// m.room.member
Member,
/// m.room.name
Name,
/// m.room.power_levels
PowerLevels,
/// m.room.tombstone
Tombstone,
/// m.room.topic
Topic,
/// m.room.redaction
Redaction,
/// m.room.pinned_events
PinnedEvents,
// m.sticker
Sticker,
// m.tag
Tag,
/// m.room.message
AudioMessage,
EmoteMessage,
FileMessage,
ImageMessage,
LocationMessage,
NoticeMessage,
TextMessage,
VideoMessage,
UnknownMessage,
};
Q_ENUM_NS(EventType)
}
class TimelineModel : public QAbstractListModel
{
Q_OBJECT
......@@ -26,8 +85,8 @@ public:
};
QHash<int, QByteArray> roleNames() const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
Q_INVOKABLE QColor userColor(QString id, QColor background);
Q_INVOKABLE QString displayName(QString id) const;
......@@ -40,6 +99,7 @@ public slots:
private slots:
// Add old events at the top of the timeline.
void addBackwardsEvents(const mtx::responses::Messages &msgs);
signals:
......@@ -57,4 +117,4 @@ private:
QHash<QString, QColor> userColors;
};
......@@ -7,6 +7,13 @@
TimelineViewManager::TimelineViewManager(QWidget *parent)
{
qmlRegisterUncreatableMetaObject(qml_mtx_events::staticMetaObject,
"com.github.nheko",
1,
0,
"MtxEvent",
"Can't instantiate enum!");
view = new QQuickView();
container = QWidget::createWindowContainer(view, parent);
container->setMinimumSize(200, 200);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment