diff --git a/autotests/eventhandlertest.cpp b/autotests/eventhandlertest.cpp index 2c9da178f..ff6dbfc06 100644 --- a/autotests/eventhandlertest.cpp +++ b/autotests/eventhandlertest.cpp @@ -40,7 +40,6 @@ private Q_SLOTS: void nullSingleLineDisplayName(); void time(); void nullTime(); - void timeString(); void highlighted(); void nullHighlighted(); void hidden(); @@ -100,12 +99,12 @@ void EventHandlerTest::time() { const auto event = room->messageEvents().at(0).get(); - QCOMPARE(EventHandler::time(room, event), QDateTime::fromMSecsSinceEpoch(1432735824654, QTimeZone(QTimeZone::UTC))); + QCOMPARE(EventHandler::dateTime(room, event), QDateTime::fromMSecsSinceEpoch(1432735824654, QTimeZone(QTimeZone::UTC))); const auto txID = room->postJson("m.room.message"_L1, event->fullJson()); QCOMPARE(room->pendingEvents().size(), 1); const auto pendingIt = room->findPendingEvent(txID); - QCOMPARE(EventHandler::time(room, pendingIt->event(), true), pendingIt->lastUpdated()); + QCOMPARE(EventHandler::dateTime(room, pendingIt->event(), true), pendingIt->lastUpdated()); room->discardMessage(txID); QCOMPARE(room->pendingEvents().size(), 0); @@ -114,40 +113,10 @@ void EventHandlerTest::time() void EventHandlerTest::nullTime() { QTest::ignoreMessage(QtWarningMsg, "time called with room set to nullptr."); - QCOMPARE(EventHandler::time(nullptr, nullptr), QDateTime()); + QCOMPARE(EventHandler::dateTime(nullptr, nullptr), QDateTime()); QTest::ignoreMessage(QtWarningMsg, "time called with event set to nullptr."); - QCOMPARE(EventHandler::time(room, nullptr), QDateTime()); -} - -void EventHandlerTest::timeString() -{ - const auto event = room->messageEvents().at(0).get(); - - KFormat format; - - QCOMPARE(EventHandler::timeString(room, event, false), - QLocale().toString(QDateTime::fromMSecsSinceEpoch(1432735824654, QTimeZone(QTimeZone::UTC)).toLocalTime().time(), QLocale::ShortFormat)); - QCOMPARE(EventHandler::timeString(room, event, true), - format.formatRelativeDate(QDateTime::fromMSecsSinceEpoch(1432735824654, QTimeZone(QTimeZone::UTC)).toLocalTime().date(), QLocale::ShortFormat)); - QCOMPARE(EventHandler::timeString(room, event, u"hh:mm"_s), - QDateTime::fromMSecsSinceEpoch(1432735824654, QTimeZone(QTimeZone::LocalTime)).toString(u"hh:mm"_s)); - - const auto txID = room->postJson("m.room.message"_L1, event->fullJson()); - QCOMPARE(room->pendingEvents().size(), 1); - const auto pendingIt = room->findPendingEvent(txID); - - QCOMPARE(EventHandler::timeString(room, pendingIt->event(), false, QLocale::ShortFormat, true), - QLocale().toString(pendingIt->lastUpdated().toLocalTime().time(), QLocale::ShortFormat)); - QCOMPARE(EventHandler::timeString(room, pendingIt->event(), true, QLocale::ShortFormat, true), - format.formatRelativeDate(pendingIt->lastUpdated().toLocalTime().date(), QLocale::ShortFormat)); - QCOMPARE(EventHandler::timeString(room, pendingIt->event(), false, QLocale::LongFormat, true), - QLocale().toString(pendingIt->lastUpdated().toLocalTime().time(), QLocale::LongFormat)); - QCOMPARE(EventHandler::timeString(room, pendingIt->event(), true, QLocale::LongFormat, true), - format.formatRelativeDate(pendingIt->lastUpdated().toLocalTime().date(), QLocale::LongFormat)); - - room->discardMessage(txID); - QCOMPARE(room->pendingEvents().size(), 0); + QCOMPARE(EventHandler::dateTime(room, nullptr), QDateTime()); } void EventHandlerTest::highlighted() diff --git a/src/libneochat/CMakeLists.txt b/src/libneochat/CMakeLists.txt index be18088b7..309d98927 100644 --- a/src/libneochat/CMakeLists.txt +++ b/src/libneochat/CMakeLists.txt @@ -17,6 +17,7 @@ target_sources(LibNeoChat PRIVATE filetransferpseudojob.cpp filetype.cpp linkpreviewer.cpp + neochatdatetime.cpp roomlastmessageprovider.cpp spacehierarchycache.cpp texthandler.cpp diff --git a/src/libneochat/eventhandler.cpp b/src/libneochat/eventhandler.cpp index 68fd31a01..9d8b41030 100644 --- a/src/libneochat/eventhandler.cpp +++ b/src/libneochat/eventhandler.cpp @@ -93,7 +93,7 @@ QString EventHandler::singleLineAuthorDisplayname(const NeoChatRoom *room, const return displayName; } -QDateTime EventHandler::time(const NeoChatRoom *room, const Quotient::RoomEvent *event, bool isPending) +NeoChatDateTime EventHandler::dateTime(const NeoChatRoom *room, const Quotient::RoomEvent *event, bool isPending) { if (room == nullptr) { qCWarning(EventHandling) << "time called with room set to nullptr."; @@ -114,25 +114,6 @@ QDateTime EventHandler::time(const NeoChatRoom *room, const Quotient::RoomEvent return event->originTimestamp(); } -QString EventHandler::timeString(const NeoChatRoom *room, const Quotient::RoomEvent *event, bool relative, QLocale::FormatType format, bool isPending) -{ - auto ts = time(room, event, isPending); - if (ts.isValid()) { - if (relative) { - KFormat formatter; - return formatter.formatRelativeDate(ts.toLocalTime().date(), format); - } else { - return QLocale().toString(ts.toLocalTime().time(), format); - } - } - return {}; -} - -QString EventHandler::timeString(const NeoChatRoom *room, const Quotient::RoomEvent *event, const QString &format, bool isPending) -{ - return time(room, event, isPending).toLocalTime().toString(format); -} - bool EventHandler::isHighlighted(const NeoChatRoom *room, const Quotient::RoomEvent *event) { if (room == nullptr) { diff --git a/src/libneochat/eventhandler.h b/src/libneochat/eventhandler.h index baee8d48c..d48f0dbf3 100644 --- a/src/libneochat/eventhandler.h +++ b/src/libneochat/eventhandler.h @@ -7,6 +7,8 @@ #include #include +#include "neochatdatetime.h" + namespace Quotient { namespace EventContent @@ -64,41 +66,7 @@ public: /** * @brief Return a QDateTime object for the event timestamp. */ - static QDateTime time(const NeoChatRoom *room, const Quotient::RoomEvent *event, bool isPending = false); - - /** - * @brief Return a QString for the event timestamp. - * - * This is intended to return a string that is read for display in the UI without - * any further manipulation required. - * - * @param relative whether the string is realtive to the current date, i.e. - * Yesterday or Wednesday, etc. - * @param format the QLocale::FormatType to use. - * @param isPending whether the event is pending as this cannot be derived from - * just the event object. - * @param lastUpdated the time the event was last updated locally as this cannot be - * obtained from the event. - */ - static QString timeString(const NeoChatRoom *room, - const Quotient::RoomEvent *event, - bool relative, - QLocale::FormatType format = QLocale::ShortFormat, - bool isPending = false); - - /** - * @brief Return a QString for the event timestamp. - * - * This is intended to return a string that is read for display in the UI without - * any further manipulation required. - * - * @param format the format to use as a string. - * @param isPending whether the event is pending as this cannot be derived from - * just the event object. - * @param lastUpdated the time the event was last updated locally as this cannot be - * obtained from the event. - */ - static QString timeString(const NeoChatRoom *room, const Quotient::RoomEvent *event, const QString &format, bool isPending = false); + static NeoChatDateTime dateTime(const NeoChatRoom *room, const Quotient::RoomEvent *event, bool isPending = false); /** * @brief Whether the event should be highlighted in the timeline. diff --git a/src/libneochat/neochatdatetime.cpp b/src/libneochat/neochatdatetime.cpp new file mode 100644 index 000000000..ae541a95c --- /dev/null +++ b/src/libneochat/neochatdatetime.cpp @@ -0,0 +1,48 @@ +// SPDX-FileCopyrightText: 2026 James Graham +// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL + +#include "neochatdatetime.h" + +#include + +using namespace Qt::Literals::StringLiterals; + +NeoChatDateTime::NeoChatDateTime(QDateTime dateTime) + : m_dateTime(dateTime) +{ +} + +QDateTime NeoChatDateTime::dateTime() const +{ + return m_dateTime; +} + +QString NeoChatDateTime::hourMinuteString() const +{ + return m_dateTime.toLocalTime().toString(u"hh:mm"_s); +} + +QString NeoChatDateTime::shortDateTime() const +{ + return QLocale().toString(m_dateTime.toLocalTime(), QLocale::ShortFormat); +} + +QString NeoChatDateTime::relativeDate() const +{ + KFormat formatter; + return formatter.formatRelativeDate(m_dateTime.toLocalTime().date(), QLocale::ShortFormat); +} + +QString NeoChatDateTime::relativeDateTime() const +{ + KFormat formatter; + const auto relativePart = formatter.formatRelativeDate(m_dateTime.toLocalTime().date(), QLocale::ShortFormat); + return u"%1, %2"_s.arg(relativePart, hourMinuteString()); +} + +bool NeoChatDateTime::operator==(const QDateTime &right) const +{ + return m_dateTime == right; +} + +#include "moc_neochatdatetime.cpp" diff --git a/src/libneochat/neochatdatetime.h b/src/libneochat/neochatdatetime.h new file mode 100644 index 000000000..94b5b11cf --- /dev/null +++ b/src/libneochat/neochatdatetime.h @@ -0,0 +1,86 @@ +// SPDX-FileCopyrightText: 2026 James Graham +// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL + +#pragma once + +#include +#include + +/** + * @class NeoChatDateTime + * + * This class is a helper for converting a QDateTime into the various format required in NeoChat. + * + * The intention is that this can be passed to QML and then the various Q_Properties + * can be called to get the date/time in the desired format reading for viewing in + * the UI. + */ +class NeoChatDateTime +{ + Q_GADGET + QML_ELEMENT + + /** + * @brief The base QDateTime used to generate the other values. + */ + Q_PROPERTY(QDateTime dateTime READ dateTime CONSTANT) + + /** + * @brief The time formatted as "hh:mm". + */ + Q_PROPERTY(QString hourMinuteString READ hourMinuteString CONSTANT) + + /** + * @brief The date and time formatted as per QLocale::ShortFormat for your locale. + */ + Q_PROPERTY(QString shortDateTime READ shortDateTime CONSTANT) + + /** + * @brief The date formatted as relative to now. + * + * If the date falls within one week before or after the current date + * then a relative date string will be returned, such as: + * - Yesterday + * - Today + * - Tomorrow + * - Last Tuesday + * - Next Wednesday + * + * If the date falls outside this period then the format QLocale::ShortFormat + * for your locale is used. + */ + Q_PROPERTY(QString relativeDate READ relativeDate CONSTANT) + + /** + * @brief The time and date formatted as relative to now. + * + * The format is "RelativeDate, hh::mm" + * + * If the date falls within one week before or after the current date + * then a relative date string will be returned, such as: + * - Yesterday + * - Today + * - Tomorrow + * - Last Tuesday + * - Next Wednesday + * + * If the date falls outside this period then the format QLocale::ShortFormat + * for your locale is used. + */ + Q_PROPERTY(QString relativeDateTime READ relativeDateTime CONSTANT) + +public: + NeoChatDateTime(QDateTime dateTime = {}); + + QDateTime dateTime() const; + + QString hourMinuteString() const; + QString shortDateTime() const; + QString relativeDate() const; + QString relativeDateTime() const; + + bool operator==(const QDateTime &right) const; + +private: + QDateTime m_dateTime; +}; diff --git a/src/messagecontent/AuthorComponent.qml b/src/messagecontent/AuthorComponent.qml index 381d8541c..ef1cd281b 100644 --- a/src/messagecontent/AuthorComponent.qml +++ b/src/messagecontent/AuthorComponent.qml @@ -27,14 +27,9 @@ RowLayout { required property var author /** - * @brief The timestamp of the message. + * @brief The timestamp of the event as a NeoChatDateTime. */ - required property var time - - /** - * @brief The timestamp of the message as a string. - */ - required property string timeString + required property NeoChatDateTime dateTime Layout.fillWidth: true Layout.maximumWidth: Message.maxContentWidth @@ -83,11 +78,11 @@ RowLayout { } QQC2.Label { id: timeLabel - text: root.timeString + text: root.dateTime.hourMinuteString horizontalAlignment: Text.AlignRight color: Kirigami.Theme.disabledTextColor QQC2.ToolTip.visible: timeHoverHandler.hovered - QQC2.ToolTip.text: root.time.toLocaleString(Qt.locale(), Locale.ShortFormat) + QQC2.ToolTip.text: root.dateTime.shortDateTime QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay HoverHandler { diff --git a/src/messagecontent/models/eventmessagecontentmodel.cpp b/src/messagecontent/models/eventmessagecontentmodel.cpp index 19dc47196..d01f34a19 100644 --- a/src/messagecontent/models/eventmessagecontentmodel.cpp +++ b/src/messagecontent/models/eventmessagecontentmodel.cpp @@ -16,6 +16,7 @@ #include "contentprovider.h" #include "eventhandler.h" #include "models/reactionmodel.h" +#include "neochatdatetime.h" #include "neochatroom.h" #include "texthandler.h" @@ -123,22 +124,13 @@ void EventMessageContentModel::initializeModel() resetModel(); } -QDateTime EventMessageContentModel::time() const +NeoChatDateTime EventMessageContentModel::dateTime() const { const auto event = m_room->getEvent(m_eventId); if (event.first == nullptr) { - return MessageContentModel::time(); + return MessageContentModel::dateTime(); }; - return EventHandler::time(m_room, event.first, m_currentState == Pending); -} - -QString EventMessageContentModel::timeString() const -{ - const auto event = m_room->getEvent(m_eventId); - if (event.first == nullptr) { - return MessageContentModel::timeString(); - }; - return EventHandler::timeString(m_room, event.first, u"hh:mm"_s, m_currentState == Pending); + return EventHandler::dateTime(m_room, event.first, m_currentState == Pending); } QString EventMessageContentModel::authorId() const @@ -254,12 +246,7 @@ void EventMessageContentModel::resetModel() return; } - m_components += MessageComponent{MessageComponentType::Author, - QString(), - { - {u"time"_s, EventHandler::time(m_room, event.first, m_currentState == Pending)}, - {u"timeString"_s, EventHandler::timeString(m_room, event.first, u"hh:mm"_s, m_currentState == Pending)}, - }}; + m_components += MessageComponent{MessageComponentType::Author, {}, {}}; m_components += messageContentComponents(); endResetModel(); diff --git a/src/messagecontent/models/eventmessagecontentmodel.h b/src/messagecontent/models/eventmessagecontentmodel.h index 666e41a6c..3c677bc5a 100644 --- a/src/messagecontent/models/eventmessagecontentmodel.h +++ b/src/messagecontent/models/eventmessagecontentmodel.h @@ -52,8 +52,7 @@ Q_SIGNALS: private: void initializeModel(); - QDateTime time() const override; - QString timeString() const override; + NeoChatDateTime dateTime() const override; QString authorId() const override; QString threadRootId() const override; diff --git a/src/messagecontent/models/messagecontentmodel.cpp b/src/messagecontent/models/messagecontentmodel.cpp index fa79c5e43..016208307 100644 --- a/src/messagecontent/models/messagecontentmodel.cpp +++ b/src/messagecontent/models/messagecontentmodel.cpp @@ -10,6 +10,7 @@ #include "chatbarcache.h" #include "contentprovider.h" #include "neochatconnection.h" +#include "neochatdatetime.h" #include "texthandler.h" using namespace Quotient; @@ -79,16 +80,11 @@ QString MessageContentModel::eventId() const return m_eventId; } -QDateTime MessageContentModel::time() const +NeoChatDateTime MessageContentModel::dateTime() const { return QDateTime::currentDateTime(); } -QString MessageContentModel::timeString() const -{ - return time().toLocalTime().toString(u"hh:mm"_s); -} - QString MessageContentModel::authorId() const { return m_room->localMember().id(); @@ -136,11 +132,8 @@ QVariant MessageContentModel::data(const QModelIndex &index, int role) const if (role == EventIdRole) { return eventId(); } - if (role == TimeRole) { - return time(); - } - if (role == TimeStringRole) { - return timeString(); + if (role == DateTimeRole) { + return QVariant::fromValue(dateTime()); } if (role == AuthorRole) { return QVariant::fromValue(author()); @@ -199,8 +192,7 @@ QHash MessageContentModel::roleNamesStatic() roles[MessageContentModel::ComponentTypeRole] = "componentType"; roles[MessageContentModel::ComponentAttributesRole] = "componentAttributes"; roles[MessageContentModel::EventIdRole] = "eventId"; - roles[MessageContentModel::TimeRole] = "time"; - roles[MessageContentModel::TimeStringRole] = "timeString"; + roles[MessageContentModel::DateTimeRole] = "dateTime"; roles[MessageContentModel::AuthorRole] = "author"; roles[MessageContentModel::FileTransferInfoRole] = "fileTransferInfo"; roles[MessageContentModel::ItineraryModelRole] = "itineraryModel"; diff --git a/src/messagecontent/models/messagecontentmodel.h b/src/messagecontent/models/messagecontentmodel.h index b14dcc166..b6e07b3f3 100644 --- a/src/messagecontent/models/messagecontentmodel.h +++ b/src/messagecontent/models/messagecontentmodel.h @@ -21,6 +21,8 @@ #include "neochatroom.h" #include "neochatroommember.h" +class NeoChatDateTime; + /** * @class MessageContentModel * @@ -47,8 +49,7 @@ public: ComponentTypeRole = Qt::UserRole, /**< The type of component to visualise the message. */ ComponentAttributesRole, /**< The attributes of the component. */ EventIdRole, /**< The matrix event ID of the event. */ - TimeRole, /**< The timestamp for when the event was sent (as a QDateTime). */ - TimeStringRole, /**< The timestamp for when the event was sent as a string (in QLocale::ShortFormat). */ + DateTimeRole, /**< The timestamp for when the event was sent (as a NeoChatDateTime). */ AuthorRole, /**< The author of the event. */ FileTransferInfoRole, /**< FileTransferInfo for any downloading files. */ ItineraryModelRole, /**< The itinerary model for a file. */ @@ -125,18 +126,11 @@ protected: QString m_eventId; /** - * @brief QDateTime for the message. + * @brief NeoChatDateTime for the message. * * The default implementation returns the current time. */ - virtual QDateTime time() const; - - /** - * @brief Time for the message as a string in the from "hh:mm". - * - * The default implementation returns the current time. - */ - virtual QString timeString() const; + virtual NeoChatDateTime dateTime() const; /** * @brief The author of the message. diff --git a/src/timeline/MessageDelegate.qml b/src/timeline/MessageDelegate.qml index 67a34b83d..8637730f9 100644 --- a/src/timeline/MessageDelegate.qml +++ b/src/timeline/MessageDelegate.qml @@ -50,9 +50,9 @@ MessageDelegateBase { required property MessageContentModel contentModel /** - * @brief The date of the event as a string. + * @brief The timestamp of the event as a NeoChatDateTime. */ - required property string section + required property NeoChatDateTime dateTime /** * @brief A model with the first 5 other user read markers for this message. @@ -203,7 +203,7 @@ MessageDelegateBase { sectionComponent: Kirigami.ListSectionHeader { horizontalPadding: 0 - text: root.section + text: root.dateTime.relativeDate } readMarkerComponent: AvatarFlow { diff --git a/src/timeline/StateDelegate.qml b/src/timeline/StateDelegate.qml index 873f9c4f9..0a33c9f30 100644 --- a/src/timeline/StateDelegate.qml +++ b/src/timeline/StateDelegate.qml @@ -49,9 +49,9 @@ TimelineDelegate { required property bool showSection /** - * @brief The date of the event as a string. + * @brief The timestamp of the event as a NeoChatDateTime. */ - required property string section + required property NeoChatDateTime dateTime /** * @brief A model with the first 5 other user read markers for this message. @@ -80,7 +80,7 @@ TimelineDelegate { Layout.fillWidth: true visible: root.showSection horizontalPadding: 0 - text: root.section + text: root.dateTime.relativeDate } RowLayout { Layout.fillWidth: true diff --git a/src/timeline/models/mediamessagefiltermodel.cpp b/src/timeline/models/mediamessagefiltermodel.cpp index c1652d6d5..3a254b710 100644 --- a/src/timeline/models/mediamessagefiltermodel.cpp +++ b/src/timeline/models/mediamessagefiltermodel.cpp @@ -7,6 +7,7 @@ #include #include "messagefiltermodel.h" +#include "neochatdatetime.h" #include "timelinemessagemodel.h" using namespace Qt::StringLiterals; @@ -34,8 +35,9 @@ QVariant MediaMessageFilterModel::data(const QModelIndex &index, int role) const // We need to catch this one and return true if the next media object was // on a different day. if (role == TimelineMessageModel::ShowSectionRole) { - const auto day = mapToSource(index).data(TimelineMessageModel::TimeRole).toDateTime().toLocalTime().date(); - const auto previousEventDay = mapToSource(this->index(index.row() + 1, 0)).data(TimelineMessageModel::TimeRole).toDateTime().toLocalTime().date(); + const auto day = mapToSource(index).data(TimelineMessageModel::DateTimeRole).value().dateTime().toLocalTime().date(); + const auto previousEventDay = + mapToSource(this->index(index.row() + 1, 0)).data(TimelineMessageModel::DateTimeRole).value().dateTime().toLocalTime().date(); return day != previousEventDay; } diff --git a/src/timeline/models/messagefiltermodel.cpp b/src/timeline/models/messagefiltermodel.cpp index 6ae5a5b6b..82427cfe1 100644 --- a/src/timeline/models/messagefiltermodel.cpp +++ b/src/timeline/models/messagefiltermodel.cpp @@ -9,6 +9,7 @@ #include "enums/delegatetype.h" #include "messagemodel.h" #include "models/timelinemodel.h" +#include "neochatdatetime.h" using namespace Quotient; @@ -179,9 +180,13 @@ bool MessageFilterModel::showAuthor(QModelIndex index) const if (data(i, TimelineMessageModel::SpecialMarksRole) != EventStatus::Hidden && !itemData(i).empty()) { return data(i, TimelineMessageModel::AuthorRole) != data(index, TimelineMessageModel::AuthorRole) || data(i, TimelineMessageModel::DelegateTypeRole) == DelegateType::State - || data(i, TimelineMessageModel::TimeRole).toDateTime().msecsTo(data(index, TimelineMessageModel::TimeRole).toDateTime()) > 600000 - || data(i, TimelineMessageModel::TimeRole).toDateTime().toLocalTime().date().day() - != data(index, TimelineMessageModel::TimeRole).toDateTime().toLocalTime().date().day(); + || data(i, TimelineMessageModel::DateTimeRole) + .value() + .dateTime() + .msecsTo(data(index, TimelineMessageModel::DateTimeRole).value().dateTime()) + > 600000 + || data(i, TimelineMessageModel::DateTimeRole).value().dateTime().toLocalTime().date().day() + != data(index, TimelineMessageModel::DateTimeRole).value().dateTime().toLocalTime().date().day(); } } diff --git a/src/timeline/models/messagemodel.cpp b/src/timeline/models/messagemodel.cpp index 40f94a1e3..2fddc2575 100644 --- a/src/timeline/models/messagemodel.cpp +++ b/src/timeline/models/messagemodel.cpp @@ -17,8 +17,9 @@ #include "enums/messagecomponenttype.h" #include "eventhandler.h" #include "events/pollevent.h" -#include "models/reactionmodel.h" #include "models/eventmessagecontentmodel.h" +#include "models/reactionmodel.h" +#include "neochatdatetime.h" #include "neochatroommember.h" using namespace Quotient; @@ -110,11 +111,8 @@ QVariant MessageModel::data(const QModelIndex &idx, int role) const switch (role) { case DelegateTypeRole: return DelegateType::ReadMarker; - case TimeRole: { - const QDateTime eventDate = data(index(m_lastReadEventIndex.row() + 1, 0), TimeRole).toDateTime().toLocalTime(); - static const KFormat format; - return format.formatRelativeDateTime(eventDate, QLocale::ShortFormat); - } + case DateTimeRole: + return data(index(m_lastReadEventIndex.row() + 1, 0), DateTimeRole); case SpecialMarksRole: // Check if all the earlier events in the timeline are hidden. If so hide this. for (auto r = row - 1; r >= 0; --r) { @@ -230,12 +228,8 @@ QVariant MessageModel::data(const QModelIndex &idx, int role) const return {}; } - if (role == TimeRole) { - return EventHandler::time(eventRoom, &event.value().get(), isPending); - } - - if (role == SectionRole) { - return EventHandler::timeString(eventRoom, &event.value().get(), true, QLocale::ShortFormat, isPending); + if (role == DateTimeRole) { + return QVariant::fromValue(EventHandler::dateTime(eventRoom, &event.value().get(), isPending)); } if (role == IsThreadedRole) { @@ -267,8 +261,8 @@ QVariant MessageModel::data(const QModelIndex &idx, int role) const // While the row is removed the subsequent row indexes are not changed so we need to skip over the removed index. // See - https://doc.qt.io/qt-5/qabstractitemmodel.html#beginRemoveRows if (data(i, SpecialMarksRole) != EventStatus::Hidden && !itemData(i).empty()) { - const auto day = data(idx, TimeRole).toDateTime().toLocalTime().date().dayOfYear(); - const auto previousEventDay = data(i, TimeRole).toDateTime().toLocalTime().date().dayOfYear(); + const auto day = data(idx, DateTimeRole).value().dateTime().toLocalTime().date().dayOfYear(); + const auto previousEventDay = data(i, DateTimeRole).value().dateTime().toLocalTime().date().dayOfYear(); return day != previousEventDay; } } @@ -342,8 +336,7 @@ QHash MessageModel::roleNames() const QHash roles = QAbstractItemModel::roleNames(); roles[DelegateTypeRole] = "delegateType"; roles[EventIdRole] = "eventId"; - roles[TimeRole] = "time"; - roles[SectionRole] = "section"; + roles[DateTimeRole] = "dateTime"; roles[AuthorRole] = "author"; roles[HighlightRole] = "isHighlighted"; roles[SpecialMarksRole] = "marks"; diff --git a/src/timeline/models/messagemodel.h b/src/timeline/models/messagemodel.h index 6fb02c3c4..76f49a27c 100644 --- a/src/timeline/models/messagemodel.h +++ b/src/timeline/models/messagemodel.h @@ -60,8 +60,7 @@ public: enum EventRoles { DelegateTypeRole = Qt::UserRole + 1, /**< The delegate type of the message. */ EventIdRole, /**< The matrix event ID of the event. */ - TimeRole, /**< The timestamp for when the event was sent (as a QDateTime). */ - SectionRole, /**< The date of the event as a string. */ + DateTimeRole, /**< The timestamp for when the event was sent (as a NeoChatDateTime). */ AuthorRole, /**< The author of the event. */ HighlightRole, /**< Whether the event should be highlighted. */ SpecialMarksRole, /**< Whether the event is hidden or not. */