diff --git a/CMakeLists.txt b/CMakeLists.txt index 40b2a524c..5eb371f59 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -174,6 +174,9 @@ if (BUILD_TESTING) find_package(Qt6 ${QT_MIN_VERSION} NO_MODULE COMPONENTS Test) add_subdirectory(autotests) add_subdirectory(appiumtests) + if (NOT ANDROID) + add_subdirectory(memorytests) + endif() endif() if(KF6DocTools_FOUND) diff --git a/REUSE.toml b/REUSE.toml index fb6c0fcc1..435f12b14 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -82,3 +82,9 @@ path = "src/purpose/purposeplugin.json" precedence = "aggregate" SPDX-FileCopyrightText = "2023 Tobias Fella " SPDX-License-Identifier = "BSD-2-Clause" + +[[annotations]] +path = "memorytests/memtest-sync.json" +precedence = "aggregate" +SPDX-FileCopyrightText = "2024 James Graham " +SPDX-License-Identifier = "BSD-2-Clause" diff --git a/memorytests/CMakeLists.txt b/memorytests/CMakeLists.txt new file mode 100644 index 000000000..69dc03339 --- /dev/null +++ b/memorytests/CMakeLists.txt @@ -0,0 +1,34 @@ +# SPDX-FileCopyrightText: 2024 James Graham +# SPDX-License-Identifier: BSD-2-Clause + +add_definitions(-DDATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}" ) + +qt_add_executable(timeline-memtest + main.cpp +) + +target_link_libraries(timeline-memtest PRIVATE neochatplugin timelineplugin) +target_link_libraries(timeline-memtest PUBLIC + Qt::Core + Qt::Quick + Qt::Qml + Qt::Gui + Qt::QuickControls2 + KF6::Kirigami + QuotientQt6 + neochat +) + +ecm_add_qml_module(timeline-memtest URI org.kde.neochat.timeline-memtest GENERATE_PLUGIN_SOURCE + OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/src/org/kde/timeline-memtest + QML_FILES + Main.qml + SOURCES + memtesttimelinemodel.cpp + memtesttimelinemodel.h + DEPENDENCIES + QtCore + QtQuick + IMPORTS + org.kde.neochat +) diff --git a/memorytests/Main.qml b/memorytests/Main.qml new file mode 100644 index 000000000..a4f71869a --- /dev/null +++ b/memorytests/Main.qml @@ -0,0 +1,33 @@ +// SPDX-FileCopyrightText: 2024 James Graham +// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL + +import QtQuick +import QtQuick.Controls as QQC2 + +import org.kde.kirigami as Kirigami + +import org.kde.neochat + +QQC2.ApplicationWindow { + id: root + + title: "Timeline Memory Test" + + minimumWidth: Kirigami.Units.gridUnit * 30 + minimumHeight: Kirigami.Units.gridUnit * 30 + + visible: true + + QQC2.ScrollView { + width: root.width + height: root.height + + contentItem: ListView { + model: messageFilterModel + + delegate: EventDelegate { + room: memTestTimelineModel.room + } + } + } +} diff --git a/memorytests/main.cpp b/memorytests/main.cpp new file mode 100644 index 000000000..3ae04007a --- /dev/null +++ b/memorytests/main.cpp @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: 2024 James Graham +// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL + +#include +#include +#include + +#include + +#include "memtesttimelinemodel.h" +#include "models/messagefiltermodel.h" + +using namespace Qt::StringLiterals; + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + KLocalizedString::setApplicationDomain(QByteArrayLiteral("neochat")); + + QQmlApplicationEngine engine; + engine.loadFromModule("org.kde.neochat.timeline-memtest", "Main"); + + MemTestTimelineModel *memTestTimelineModel = new MemTestTimelineModel; + MessageFilterModel *messageFilterModel = new MessageFilterModel(nullptr, memTestTimelineModel); + engine.rootContext()->setContextProperty(u"memTestTimelineModel"_s, memTestTimelineModel); + engine.rootContext()->setContextProperty(u"messageFilterModel"_s, messageFilterModel); + + return app.exec(); +} diff --git a/memorytests/memtest-sync.json b/memorytests/memtest-sync.json new file mode 100644 index 000000000..c833461c8 --- /dev/null +++ b/memorytests/memtest-sync.json @@ -0,0 +1,655 @@ +{ + "ephemeral": { + "events": [ + { + "content": { + "$1000000000000:example.org": { + "m.read": { + "@alice:example.org": { + "ts": 1000000000000 + } + } + } + }, + "type": "m.receipt" + }, + { + "content": { + "$1000000000000:example.org": { + "m.read": { + "@bob:example.org": { + "ts": 1000000000000 + } + } + } + }, + "type": "m.receipt" + }, + { + "content": { + "$1000000000003:example.org": { + "m.read": { + "@tim:example.org": { + "ts": 1000000000000 + } + } + } + }, + "type": "m.receipt" + }, + { + "content": { + "$1000000000003:example.org": { + "m.read": { + "@example:example.org": { + "ts": 1000000000000 + } + } + } + }, + "type": "m.receipt" + }, + { + "content": { + "$1000000000003:example.org": { + "m.read": { + "@jeff:example.org": { + "ts": 1000000000000 + } + } + } + }, + "type": "m.receipt" + }, + { + "content": { + "$1000000000003:example.org": { + "m.read": { + "@tina:example.org": { + "ts": 1000000000000 + } + } + } + }, + "type": "m.receipt" + }, + { + "content": { + "$1000000000003:example.org": { + "m.read": { + "@sally:example.org": { + "ts": 1000000000000 + } + } + } + }, + "type": "m.receipt" + }, + { + "content": { + "$1000000000003:example.org": { + "m.read": { + "@fred:example.org": { + "ts": 1000000000000 + } + } + } + }, + "type": "m.receipt" + } + ] + }, + "state": { + "events": [ + { + "content": { + "avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF", + "displayname": "Example", + "membership": "join" + }, + "event_id": "$143273582555PhrSn:example.org", + "origin_server_ts": 1000000000000, + "room_id": "!jEsUZKDJdhlrceRyVU:example.org", + "sender": "example:example.org", + "state_key": "@example:example.org", + "type": "m.room.member", + "unsigned": { + "age": 1234 + } + }, + { + "content": { + "avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF", + "displayname": "Alice", + "membership": "join", + "reason": "Looking for support" + }, + "event_id": "$143273582443PhrSn:example.org", + "origin_server_ts": 1000000000000, + "room_id": "!jEsUZKDJdhlrceRyVU:example.org", + "sender": "alice:example.org", + "state_key": "@alice:example.org", + "type": "m.room.member", + "unsigned": { + "age": 1234 + } + }, + { + "content": { + "avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF", + "displayname": "Bob", + "membership": "join" + }, + "event_id": "$143273582443PhrSn:example.org", + "origin_server_ts": 1000000000000, + "room_id": "!jEsUZKDJdhlrceRyVU:example.org", + "sender": "bob:example.org", + "state_key": "@bob:example.org", + "type": "m.room.member", + "unsigned": { + "age": 1234 + } + }, + { + "content": { + "avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF", + "displayname": "Tim", + "membership": "join" + }, + "event_id": "$143273582443PhrSn:example.org", + "origin_server_ts": 1000000000000, + "room_id": "!jEsUZKDJdhlrceRyVU:example.org", + "sender": "tim:example.org", + "state_key": "@tim:example.org", + "type": "m.room.member", + "unsigned": { + "age": 1234 + } + }, + { + "content": { + "avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF", + "displayname": "Jeff", + "membership": "join" + }, + "event_id": "$143273582443PhrSn:example.org", + "origin_server_ts": 1000000000000, + "room_id": "!jEsUZKDJdhlrceRyVU:example.org", + "sender": "jeff:example.org", + "state_key": "@jeff:example.org", + "type": "m.room.member", + "unsigned": { + "age": 1234 + } + }, + { + "content": { + "avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF", + "displayname": "Tina", + "membership": "join" + }, + "event_id": "$143273582443PhrSn:example.org", + "origin_server_ts": 1000000000000, + "room_id": "!jEsUZKDJdhlrceRyVU:example.org", + "sender": "tina:example.org", + "state_key": "@tina:example.org", + "type": "m.room.member", + "unsigned": { + "age": 1234 + } + }, + { + "content": { + "avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF", + "displayname": "Sally", + "membership": "join" + }, + "event_id": "$143273582443PhrSn:example.org", + "origin_server_ts": 1000000000000, + "room_id": "!jEsUZKDJdhlrceRyVU:example.org", + "sender": "sally:example.org", + "state_key": "@sally:example.org", + "type": "m.room.member", + "unsigned": { + "age": 1234 + } + }, + { + "content": { + "avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF", + "displayname": "Fred", + "membership": "join" + }, + "event_id": "$143273582443PhrSn:example.org", + "origin_server_ts": 1000000000000, + "room_id": "!jEsUZKDJdhlrceRyVU:example.org", + "sender": "fred:example.org", + "state_key": "@fred:example.org", + "type": "m.room.member", + "unsigned": { + "age": 1234 + } + } + ] + }, + "timeline": { + "events": [ + { + "content": { + "body": "This is an example text message", + "format": "org.matrix.custom.html", + "formatted_body": "This is an example
text message", + "msgtype": "m.text" + }, + "event_id": "$1000000000000:example.org", + "origin_server_ts": 1000000000000, + "room_id": "!jEsUZKDJdhlrceRyVU:example.org", + "sender": "@example:example.org", + "type": "m.room.message", + "unsigned": { + "age": 1232 + } + }, + { + "content": { + "body": "This is a highlight @bob:example.org", + "msgtype": "m.text" + }, + "event_id": "$1000000000001:example.org", + "origin_server_ts": 1000000000001, + "room_id": "!jEsUZKDJdhlrceRyVU:example.org", + "sender": "@example:example.org", + "type": "m.room.message", + "unsigned": { + "age": 1233 + } + }, + { + "content": { + "m.relates_to": { + "event_id": "$1000000000001:example.org", + "key": "👍", + "rel_type": "m.annotation" + } + }, + "origin_server_ts": 1000000000002, + "room_id": "!jEsUZKDJdhlrceRyVU:example.org", + "sender": "@alice:example.org", + "type": "m.reaction", + "unsigned": { + "age": 390159120 + }, + "event_id": "$1000000000002:example.org", + "age": 390159120 + }, + { + "content": { + "body": "reply", + "format": "org.matrix.custom.html", + "formatted_body": "reply", + "m.relates_to": { + "m.in_reply_to": { + "event_id": "$1000000000000:example.org" + } + }, + "msgtype": "m.text" + }, + "origin_server_ts": 1000000000003, + "sender": "@alice:example.org", + "type": "m.room.message", + "unsigned": { + "age": 98 + }, + "event_id": "$1000000000003:example.org", + "room_id": "!jEsUZKDJdhlrceRyVU:example.org" + }, + { + "age": 96845207, + "content": { + "body": "Lat: 51.7035, Lon: -1.14394", + "geo_uri": "geo:51.7035,-1.14394", + "msgtype": "m.location", + "org.matrix.msc1767.text": "Lat: 51.7035, Lon: -1.14394", + "org.matrix.msc3488.asset": { + "type": "m.pin" + }, + "org.matrix.msc3488.location": { + "uri": "geo:51.7035,-1.14394" + } + }, + "event_id": "$1000000000004:example.org", + "origin_server_ts": 1000000000004, + "room_id": "!jEsUZKDJdhlrceRyVU:example.org", + "sender": "@example:example.org", + "type": "m.room.message", + "unsigned": { + "age": 96845207 + } + }, + { + "content": { + "body": "```cpp\nint main(int argc, char **argv)\n{\n QApplication app(argc, argv);\n\n KLocalizedString::setApplicationDomain(QByteArrayLiteral(\"neochat\"));\n\n QQmlApplicationEngine engine;\n engine.loadFromModule(\"org.kde.neochat.timeline-memtest\", \"Main\");\n\n return app.exec();\n}\n```", + "format": "org.matrix.custom.html", + "formatted_body": "
int main(int argc, char **argv)\n{\n    QApplication app(argc, argv);\n\n    KLocalizedString::setApplicationDomain(QByteArrayLiteral("neochat"));\n\n    QQmlApplicationEngine engine;\n    engine.loadFromModule("org.kde.neochat.timeline-memtest", "Main");\n\n    return app.exec();\n}\n
", + "msgtype": "m.text" + }, + "event_id": "$1000000000005:example.org", + "origin_server_ts": 1000000000005, + "room_id": "!jEsUZKDJdhlrceRyVU:example.org", + "sender": "@bob:example.org", + "type": "m.room.message", + "unsigned": { + "age": 1233 + } + }, + { + "content": { + "body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam sed fringilla risus, eget lacinia risus. Suspendisse at magna id justo sagittis suscipit. Maecenas eros quam, pulvinar a consequat sed, varius vitae risus. Cras congue est eget felis porttitor lobortis. Nam cursus, nulla ut finibus suscipit, tellus eros tincidunt ante, a volutpat velit lectus sit amet turpis. Morbi leo justo, fringilla sed rutrum a, suscipit a quam. Proin rhoncus neque eget ligula ullamcorper pellentesque. Mauris volutpat malesuada nunc. Nullam finibus enim eu nibh placerat imperdiet. Nullam in mi in diam luctus scelerisque dignissim non erat. ", + "msgtype": "m.text" + }, + "event_id": "$1000000000006:example.org", + "origin_server_ts": 1000000000006, + "room_id": "!jEsUZKDJdhlrceRyVU:example.org", + "sender": "@example:example.org", + "type": "m.room.message", + "unsigned": { + "age": 1232 + } + }, + { + "content": { + "body": "> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam sed fringilla risus, eget lacinia risus. Suspendisse at magna id justo sagittis suscipit. Maecenas eros quam, pulvinar a consequat sed, varius vitae risus. Cras congue est eget felis porttitor lobortis. Nam cursus, nulla ut finibus suscipit, tellus eros tincidunt ante, a volutpat velit lectus sit amet turpis. Morbi leo justo, fringilla sed rutrum a, suscipit a quam. Proin rhoncus neque eget ligula ullamcorper pellentesque. Mauris volutpat malesuada nunc. Nullam finibus enim eu nibh placerat imperdiet. Nullam in mi in diam luctus scelerisque dignissim non erat. ", + "format": "org.matrix.custom.html", + "formatted_body": "
\n

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam sed fringilla risus, eget lacinia risus. Suspendisse at magna id justo sagittis suscipit. Maecenas eros quam, pulvinar a consequat sed, varius vitae risus. Cras congue est eget felis porttitor lobortis. Nam cursus, nulla ut finibus suscipit, tellus eros tincidunt ante, a volutpat velit lectus sit amet turpis. Morbi leo justo, fringilla sed rutrum a, suscipit a quam. Proin rhoncus neque eget ligula ullamcorper pellentesque. Mauris volutpat malesuada nunc. Nullam finibus enim eu nibh placerat imperdiet. Nullam in mi in diam luctus scelerisque dignissim non erat.

\n
", + "msgtype": "m.text" + }, + "event_id": "$1000000000007:example.org", + "origin_server_ts": 1000000000007, + "room_id": "!jEsUZKDJdhlrceRyVU:example.org", + "sender": "@example:example.org", + "type": "m.room.message", + "unsigned": { + "age": 1232 + } + }, + { + "content": { + "body": "This is an example text message", + "format": "org.matrix.custom.html", + "formatted_body": "This is an example
text message", + "msgtype": "m.text" + }, + "event_id": "$1000000000008:example.org", + "origin_server_ts": 1000000000008, + "room_id": "!jEsUZKDJdhlrceRyVU:example.org", + "sender": "@example:example.org", + "type": "m.room.message", + "unsigned": { + "age": 1232 + } + }, + { + "content": { + "body": "This is a highlight @bob:example.org", + "msgtype": "m.text" + }, + "event_id": "$1000000000009:example.org", + "origin_server_ts": 1000000000009, + "room_id": "!jEsUZKDJdhlrceRyVU:example.org", + "sender": "@example:example.org", + "type": "m.room.message", + "unsigned": { + "age": 1233 + } + }, + { + "content": { + "m.relates_to": { + "event_id": "$1000000000009:example.org", + "key": "👍", + "rel_type": "m.annotation" + } + }, + "origin_server_ts": 1000000000010, + "room_id": "!jEsUZKDJdhlrceRyVU:example.org", + "sender": "@alice:example.org", + "type": "m.reaction", + "unsigned": { + "age": 390159120 + }, + "event_id": "$1000000000010:example.org", + "age": 390159120 + }, + { + "content": { + "body": "reply", + "format": "org.matrix.custom.html", + "formatted_body": "reply", + "m.relates_to": { + "m.in_reply_to": { + "event_id": "$1000000000008:example.org" + } + }, + "msgtype": "m.text" + }, + "origin_server_ts": 1000000000011, + "sender": "@alice:example.org", + "type": "m.room.message", + "unsigned": { + "age": 98 + }, + "event_id": "$1000000000011:example.org", + "room_id": "!jEsUZKDJdhlrceRyVU:example.org" + }, + { + "age": 96845207, + "content": { + "body": "Lat: 51.7035, Lon: -1.14394", + "geo_uri": "geo:51.7035,-1.14394", + "msgtype": "m.location", + "org.matrix.msc1767.text": "Lat: 51.7035, Lon: -1.14394", + "org.matrix.msc3488.asset": { + "type": "m.pin" + }, + "org.matrix.msc3488.location": { + "uri": "geo:51.7035,-1.14394" + } + }, + "event_id": "$1000000000012:example.org", + "origin_server_ts": 1000000000012, + "room_id": "!jEsUZKDJdhlrceRyVU:example.org", + "sender": "@example:example.org", + "type": "m.room.message", + "unsigned": { + "age": 96845207 + } + }, + { + "content": { + "body": "```cpp\nint main(int argc, char **argv)\n{\n QApplication app(argc, argv);\n\n KLocalizedString::setApplicationDomain(QByteArrayLiteral(\"neochat\"));\n\n QQmlApplicationEngine engine;\n engine.loadFromModule(\"org.kde.neochat.timeline-memtest\", \"Main\");\n\n return app.exec();\n}\n```", + "format": "org.matrix.custom.html", + "formatted_body": "
int main(int argc, char **argv)\n{\n    QApplication app(argc, argv);\n\n    KLocalizedString::setApplicationDomain(QByteArrayLiteral("neochat"));\n\n    QQmlApplicationEngine engine;\n    engine.loadFromModule("org.kde.neochat.timeline-memtest", "Main");\n\n    return app.exec();\n}\n
", + "msgtype": "m.text" + }, + "event_id": "$1000000000013:example.org", + "origin_server_ts": 1000000000013, + "room_id": "!jEsUZKDJdhlrceRyVU:example.org", + "sender": "@bob:example.org", + "type": "m.room.message", + "unsigned": { + "age": 1233 + } + }, + { + "content": { + "body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam sed fringilla risus, eget lacinia risus. Suspendisse at magna id justo sagittis suscipit. Maecenas eros quam, pulvinar a consequat sed, varius vitae risus. Cras congue est eget felis porttitor lobortis. Nam cursus, nulla ut finibus suscipit, tellus eros tincidunt ante, a volutpat velit lectus sit amet turpis. Morbi leo justo, fringilla sed rutrum a, suscipit a quam. Proin rhoncus neque eget ligula ullamcorper pellentesque. Mauris volutpat malesuada nunc. Nullam finibus enim eu nibh placerat imperdiet. Nullam in mi in diam luctus scelerisque dignissim non erat. ", + "msgtype": "m.text" + }, + "event_id": "$1000000000014:example.org", + "origin_server_ts": 1000000000014, + "room_id": "!jEsUZKDJdhlrceRyVU:example.org", + "sender": "@example:example.org", + "type": "m.room.message", + "unsigned": { + "age": 1232 + } + }, + { + "content": { + "body": "> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam sed fringilla risus, eget lacinia risus. Suspendisse at magna id justo sagittis suscipit. Maecenas eros quam, pulvinar a consequat sed, varius vitae risus. Cras congue est eget felis porttitor lobortis. Nam cursus, nulla ut finibus suscipit, tellus eros tincidunt ante, a volutpat velit lectus sit amet turpis. Morbi leo justo, fringilla sed rutrum a, suscipit a quam. Proin rhoncus neque eget ligula ullamcorper pellentesque. Mauris volutpat malesuada nunc. Nullam finibus enim eu nibh placerat imperdiet. Nullam in mi in diam luctus scelerisque dignissim non erat. ", + "format": "org.matrix.custom.html", + "formatted_body": "
\n

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam sed fringilla risus, eget lacinia risus. Suspendisse at magna id justo sagittis suscipit. Maecenas eros quam, pulvinar a consequat sed, varius vitae risus. Cras congue est eget felis porttitor lobortis. Nam cursus, nulla ut finibus suscipit, tellus eros tincidunt ante, a volutpat velit lectus sit amet turpis. Morbi leo justo, fringilla sed rutrum a, suscipit a quam. Proin rhoncus neque eget ligula ullamcorper pellentesque. Mauris volutpat malesuada nunc. Nullam finibus enim eu nibh placerat imperdiet. Nullam in mi in diam luctus scelerisque dignissim non erat.

\n
", + "msgtype": "m.text" + }, + "event_id": "$1000000000015:example.org", + "origin_server_ts": 1000000000015, + "room_id": "!jEsUZKDJdhlrceRyVU:example.org", + "sender": "@example:example.org", + "type": "m.room.message", + "unsigned": { + "age": 1232 + } + }, + { + "content": { + "body": "This is an example text message", + "format": "org.matrix.custom.html", + "formatted_body": "This is an example
text message", + "msgtype": "m.text" + }, + "event_id": "$1000000000016:example.org", + "origin_server_ts": 1000000000016, + "room_id": "!jEsUZKDJdhlrceRyVU:example.org", + "sender": "@example:example.org", + "type": "m.room.message", + "unsigned": { + "age": 1232 + } + }, + { + "content": { + "body": "This is a highlight @bob:example.org", + "msgtype": "m.text" + }, + "event_id": "$1000000000017:example.org", + "origin_server_ts": 1000000000017, + "room_id": "!jEsUZKDJdhlrceRyVU:example.org", + "sender": "@example:example.org", + "type": "m.room.message", + "unsigned": { + "age": 1233 + } + }, + { + "content": { + "m.relates_to": { + "event_id": "$1000000000017:example.org", + "key": "👍", + "rel_type": "m.annotation" + } + }, + "origin_server_ts": 1000000000018, + "room_id": "!jEsUZKDJdhlrceRyVU:example.org", + "sender": "@alice:example.org", + "type": "m.reaction", + "unsigned": { + "age": 390159120 + }, + "event_id": "$1000000000018:example.org", + "age": 390159120 + }, + { + "content": { + "body": "reply", + "format": "org.matrix.custom.html", + "formatted_body": "reply", + "m.relates_to": { + "m.in_reply_to": { + "event_id": "$1000000000016:example.org" + } + }, + "msgtype": "m.text" + }, + "origin_server_ts": 1000000000019, + "sender": "@alice:example.org", + "type": "m.room.message", + "unsigned": { + "age": 98 + }, + "event_id": "$1000000000019:example.org", + "room_id": "!jEsUZKDJdhlrceRyVU:example.org" + }, + { + "age": 96845207, + "content": { + "body": "Lat: 51.7035, Lon: -1.14394", + "geo_uri": "geo:51.7035,-1.14394", + "msgtype": "m.location", + "org.matrix.msc1767.text": "Lat: 51.7035, Lon: -1.14394", + "org.matrix.msc3488.asset": { + "type": "m.pin" + }, + "org.matrix.msc3488.location": { + "uri": "geo:51.7035,-1.14394" + } + }, + "event_id": "$1000000000020:example.org", + "origin_server_ts": 1000000000020, + "room_id": "!jEsUZKDJdhlrceRyVU:example.org", + "sender": "@example:example.org", + "type": "m.room.message", + "unsigned": { + "age": 96845207 + } + }, + { + "content": { + "body": "```cpp\nint main(int argc, char **argv)\n{\n QApplication app(argc, argv);\n\n KLocalizedString::setApplicationDomain(QByteArrayLiteral(\"neochat\"));\n\n QQmlApplicationEngine engine;\n engine.loadFromModule(\"org.kde.neochat.timeline-memtest\", \"Main\");\n\n return app.exec();\n}\n```", + "format": "org.matrix.custom.html", + "formatted_body": "
int main(int argc, char **argv)\n{\n    QApplication app(argc, argv);\n\n    KLocalizedString::setApplicationDomain(QByteArrayLiteral("neochat"));\n\n    QQmlApplicationEngine engine;\n    engine.loadFromModule("org.kde.neochat.timeline-memtest", "Main");\n\n    return app.exec();\n}\n
", + "msgtype": "m.text" + }, + "event_id": "$1000000000021:example.org", + "origin_server_ts": 1000000000021, + "room_id": "!jEsUZKDJdhlrceRyVU:example.org", + "sender": "@bob:example.org", + "type": "m.room.message", + "unsigned": { + "age": 1233 + } + }, + { + "content": { + "body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam sed fringilla risus, eget lacinia risus. Suspendisse at magna id justo sagittis suscipit. Maecenas eros quam, pulvinar a consequat sed, varius vitae risus. Cras congue est eget felis porttitor lobortis. Nam cursus, nulla ut finibus suscipit, tellus eros tincidunt ante, a volutpat velit lectus sit amet turpis. Morbi leo justo, fringilla sed rutrum a, suscipit a quam. Proin rhoncus neque eget ligula ullamcorper pellentesque. Mauris volutpat malesuada nunc. Nullam finibus enim eu nibh placerat imperdiet. Nullam in mi in diam luctus scelerisque dignissim non erat. ", + "msgtype": "m.text" + }, + "event_id": "$1000000000022:example.org", + "origin_server_ts": 1000000000022, + "room_id": "!jEsUZKDJdhlrceRyVU:example.org", + "sender": "@example:example.org", + "type": "m.room.message", + "unsigned": { + "age": 1232 + } + }, + { + "content": { + "body": "> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam sed fringilla risus, eget lacinia risus. Suspendisse at magna id justo sagittis suscipit. Maecenas eros quam, pulvinar a consequat sed, varius vitae risus. Cras congue est eget felis porttitor lobortis. Nam cursus, nulla ut finibus suscipit, tellus eros tincidunt ante, a volutpat velit lectus sit amet turpis. Morbi leo justo, fringilla sed rutrum a, suscipit a quam. Proin rhoncus neque eget ligula ullamcorper pellentesque. Mauris volutpat malesuada nunc. Nullam finibus enim eu nibh placerat imperdiet. Nullam in mi in diam luctus scelerisque dignissim non erat. ", + "format": "org.matrix.custom.html", + "formatted_body": "
\n

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam sed fringilla risus, eget lacinia risus. Suspendisse at magna id justo sagittis suscipit. Maecenas eros quam, pulvinar a consequat sed, varius vitae risus. Cras congue est eget felis porttitor lobortis. Nam cursus, nulla ut finibus suscipit, tellus eros tincidunt ante, a volutpat velit lectus sit amet turpis. Morbi leo justo, fringilla sed rutrum a, suscipit a quam. Proin rhoncus neque eget ligula ullamcorper pellentesque. Mauris volutpat malesuada nunc. Nullam finibus enim eu nibh placerat imperdiet. Nullam in mi in diam luctus scelerisque dignissim non erat.

\n
", + "msgtype": "m.text" + }, + "event_id": "$1000000000023:example.org", + "origin_server_ts": 1000000000023, + "room_id": "!jEsUZKDJdhlrceRyVU:example.org", + "sender": "@example:example.org", + "type": "m.room.message", + "unsigned": { + "age": 1232 + } + } + ], + "limited": true, + "prev_batch": "t34-23535_0_0" + } +} diff --git a/memorytests/memtesttimelinemodel.cpp b/memorytests/memtesttimelinemodel.cpp new file mode 100644 index 000000000..65484321b --- /dev/null +++ b/memorytests/memtesttimelinemodel.cpp @@ -0,0 +1,36 @@ +// SPDX-FileCopyrightText: 2024 James Graham +// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL + +#include "memtesttimelinemodel.h" + +#include +#include + +using namespace Quotient; + +MemTestTimelineModel::MemTestTimelineModel(QObject *parent) + : MessageModel(parent) +{ + beginResetModel(); + m_connection = Connection::makeMockConnection(u"@bob:example.org"_s); + m_room = new MemTestRoom(m_connection, u"#memtestroom:example.org"_s, u"memtest-sync.json"_s); + + for (const auto &eventIt : m_room->messageEvents()) { + Q_EMIT newEventAdded(eventIt.event()); + } + + endResetModel(); +} + +std::optional> MemTestTimelineModel::getEventForIndex(QModelIndex index) const +{ + return *m_room->messageEvents().at(index.row()).event(); +} + +int MemTestTimelineModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + return m_room->messageEvents().size(); +} + +#include "moc_memtesttimelinemodel.cpp" diff --git a/memorytests/memtesttimelinemodel.h b/memorytests/memtesttimelinemodel.h new file mode 100644 index 000000000..494dd75b5 --- /dev/null +++ b/memorytests/memtesttimelinemodel.h @@ -0,0 +1,75 @@ +// SPDX-FileCopyrightText: 2024 James Graham +// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL + +#pragma once + +#include +#include + +#include +#include + +#include "models/messagemodel.h" + +namespace Quotient +{ +class Connection; +} + +class NeoChatRoom; + +class MemTestRoom : public NeoChatRoom +{ +public: + MemTestRoom(Quotient::Connection *connection, const QString &roomName, const QString &syncFileName = {}) + : NeoChatRoom(connection, roomName, Quotient::JoinState::Join) + { + syncNewEvents(syncFileName); + } + + void update(Quotient::SyncRoomData &&data, bool fromCache = false) + { + Room::updateData(std::move(data), fromCache); + } + + void syncNewEvents(const QString &syncFileName) + { + if (!syncFileName.isEmpty()) { + QFile testSyncFile; + testSyncFile.setFileName(QStringLiteral(DATA_DIR) + u'/' + syncFileName); + testSyncFile.open(QIODevice::ReadOnly); + auto testSyncJson = QJsonDocument::fromJson(testSyncFile.readAll()).object(); + Quotient::SyncRoomData roomData(id(), Quotient::JoinState::Join, testSyncJson); + update(std::move(roomData)); + } + } +}; + +/** + * @class MemTestTimelineModel + * + * This is a special version of the MessageModel design to load an unchanging set + * of events from a json file so that timeline memory optimisations can be measured. + */ +class MemTestTimelineModel : public MessageModel +{ + Q_OBJECT + QML_ELEMENT + +public: + explicit MemTestTimelineModel(QObject *parent = nullptr); + + /** + * @brief Number of rows in the model. + * + * @sa QAbstractItemModel::rowCount + */ + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + +private: + QPointer m_connection; + + std::vector m_events; + + std::optional> getEventForIndex(QModelIndex index) const override; +}; diff --git a/src/models/messagefiltermodel.cpp b/src/models/messagefiltermodel.cpp index 2eede1c8c..1851e7ea3 100644 --- a/src/models/messagefiltermodel.cpp +++ b/src/models/messagefiltermodel.cpp @@ -14,7 +14,7 @@ using namespace Quotient; -MessageFilterModel::MessageFilterModel(QObject *parent, TimelineModel *sourceModel) +MessageFilterModel::MessageFilterModel(QObject *parent, QAbstractItemModel *sourceModel) : QSortFilterProxyModel(parent) { Q_ASSERT(sourceModel); diff --git a/src/models/messagefiltermodel.h b/src/models/messagefiltermodel.h index 0c9aa2881..de8fcdb5d 100644 --- a/src/models/messagefiltermodel.h +++ b/src/models/messagefiltermodel.h @@ -37,7 +37,7 @@ public: LastRole, // Keep this last }; - explicit MessageFilterModel(QObject *parent = nullptr, TimelineModel *sourceModel = nullptr); + explicit MessageFilterModel(QObject *parent = nullptr, QAbstractItemModel *sourceModel = nullptr); /** * @brief Custom filter function to remove hidden messages.