Files
neochat/src/timeline/models/timelinemodel.h
James Graham 6a5a2e6144 Refactor TimelineView
Refactor TimelineView to make it more reliable and prepare for read marker choice. This is done by creating signalling from the mode when reset which can be used to move the scrollbar to the newest meassage.

Some of the spaghetti is also removed so there is no need for ChatBar and TimelineView to talk directly.

The code to mark messages as read if they are all visible after 10s has been removed infour of just marking as read on entry if all are visible. This is temporary until a follow up providing user options is finished (although it will be one of the options)
2025-06-14 12:16:39 +01:00

169 lines
4.3 KiB
C++

// SPDX-FileCopyrightText: 2022 James Graham <james.h.graham@protonmail.com>
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
#pragma once
#include <QAbstractListModel>
#include <QConcatenateTablesProxyModel>
#include <QQmlEngine>
#include "neochatroom.h"
#include "timelinemessagemodel.h"
/**
* @class TimelineBeginningModel
*
* A model to provide a delegate at the start of the timeline to show upgrades.
*/
class TimelineBeginningModel : public QAbstractListModel
{
Q_OBJECT
QML_ELEMENT
public:
/**
* @brief Defines the model roles.
*/
enum Roles {
DelegateTypeRole = TimelineMessageModel::DelegateTypeRole, /**< The delegate type of the message. */
};
Q_ENUM(Roles)
explicit TimelineBeginningModel(QObject *parent = nullptr);
/**
* @brief Set the room for the timeline.
*/
void setRoom(NeoChatRoom *room);
/**
* @brief Get the given role value at the given index.
*
* @sa QAbstractItemModel::data
*/
[[nodiscard]] QVariant data(const QModelIndex &idx, int role = Qt::DisplayRole) const override;
/**
* @brief 1, the answer is always 1.
*
* @sa QAbstractItemModel::rowCount
*/
[[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override;
/**
* @brief Returns a map with DelegateTypeRole it's the only one.
*
* @sa Roles, QAbstractItemModel::roleNames()
*/
[[nodiscard]] QHash<int, QByteArray> roleNames() const override;
private:
QPointer<NeoChatRoom> m_room = nullptr;
};
/**
* @class TimelineEndModel
*
* A model to provide a single delegate to mark the end of the timeline.
*
* The delegate will either be a loading delegate if more events are being loaded
* or a timeline end delegate if all history is loaded.
*/
class TimelineEndModel : public QAbstractListModel
{
Q_OBJECT
QML_ELEMENT
public:
/**
* @brief Defines the model roles.
*/
enum Roles {
DelegateTypeRole = TimelineMessageModel::DelegateTypeRole, /**< The delegate type of the message. */
};
Q_ENUM(Roles)
explicit TimelineEndModel(QObject *parent = nullptr);
/**
* @brief Set the room for the timeline.
*/
void setRoom(NeoChatRoom *room);
/**
* @brief Get the given role value at the given index.
*
* @sa QAbstractItemModel::data
*/
[[nodiscard]] QVariant data(const QModelIndex &idx, int role = Qt::DisplayRole) const override;
/**
* @brief 1, the answer is always 1.
*
* @sa QAbstractItemModel::rowCount
*/
[[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override;
/**
* @brief Returns a map with DelegateTypeRole it's the only one.
*
* @sa Roles, QAbstractItemModel::roleNames()
*/
[[nodiscard]] QHash<int, QByteArray> roleNames() const override;
private:
QPointer<NeoChatRoom> m_room = nullptr;
};
/**
* @class TimelineModel
*
* A model to visualise a room timeline.
*
* This model combines a TimelineMessageModel with a TimelineEndModel.
*
* @sa TimelineMessageModel, TimelineEndModel
*/
class TimelineModel : public QConcatenateTablesProxyModel
{
Q_OBJECT
QML_ELEMENT
/**
* @brief The current room that the model is getting its messages from.
*/
Q_PROPERTY(NeoChatRoom *room READ room WRITE setRoom NOTIFY roomChanged)
/**
* @brief The TimelineMessageModel for the timeline.
*/
Q_PROPERTY(TimelineMessageModel *timelineMessageModel READ timelineMessageModel CONSTANT)
public:
TimelineModel(QObject *parent = nullptr);
[[nodiscard]] NeoChatRoom *room() const;
void setRoom(NeoChatRoom *room);
TimelineMessageModel *timelineMessageModel() const;
/**
* @brief Returns a mapping from Role enum values to role names.
*
* @sa Roles, QAbstractProxyModel::roleNames()
*/
[[nodiscard]] QHash<int, QByteArray> roleNames() const override;
Q_SIGNALS:
void roomChanged();
void threadsEnabledChanged();
private:
TimelineMessageModel *m_timelineMessageModel = nullptr;
TimelineBeginningModel *m_timelineBeginningModel = nullptr;
TimelineEndModel *m_timelineEndModel = nullptr;
bool canFetchMore(const QModelIndex &parent) const override;
void fetchMore(const QModelIndex &parent) override;
};