Add TimelineDayRow and set it as header of timeline list

This is the equivalent control to Qt Quick Controls’ own DayOfWeekRow,
but for the number of each day in the visible range, instead of day of
the week.

Qt Quick Controls has this component written in C++, and also has a
separate, internal, model for the days in different formats, but i had
to implement the control in QML, because QtQuickControl is private.
However, as far as i understand, it is not much more than a container
for the delegate and the model that is used as a template.
This commit is contained in:
jordi fita mas 2025-01-08 09:54:13 +01:00
parent accc627ebd
commit c49135247a
7 changed files with 156 additions and 131 deletions

View File

@ -12,6 +12,7 @@ qt_add_qml_module(${PROJECT_NAME}
calendarlistmodel.cpp calendarlistmodel.h
database.cpp database.h
mnemonicattached.cpp mnemonicattached.h
timelinedaymodel.cpp timelinedaymodel.h
timelineview.cpp timelineview.h
QML_FILES
ErrorNotification.qml
@ -22,6 +23,7 @@ qt_add_qml_module(${PROJECT_NAME}
MnemonicLabel.qml
ReservationsPage.qml
SelectableLabel.qml
TimelineDayRow.qml
)
set_target_properties(${PROJECT_NAME} PROPERTIES

View File

@ -5,6 +5,12 @@ import QtQuick.Layouts
import Camper
Page {
id: page
property real dayWidth: 24
property date fromDate: "2024-11-01"
property date toDate: "2025-01-31"
title: qsTr("Reservations")
header: ToolBar {
@ -50,7 +56,7 @@ Page {
anchors.right: parent.right
anchors.top: parent.top
clip: true
contentWidth: 2184
contentWidth: headerItem.implicitWidth
flickableDirection: Flickable.AutoFlickDirection
headerPositioning: ListView.OverlayHeader
model: calendarList
@ -62,9 +68,10 @@ Page {
}
delegate: TimelineView {
fromDate: "2024-11-01"
dayWidth: page.dayWidth
fromDate: page.fromDate
height: 16
toDate: "2025-01-31"
toDate: page.toDate
viewportWidth: ListView.view.width
viewportX: ListView.view.contentX
@ -75,10 +82,14 @@ Page {
}
}
header: Pane {
leftPadding: 0
rightPadding: 0
z: 2
Label {
text: qsTr("Calendar")
TimelineDayRow {
dayWidth: page.dayWidth
fromDate: page.fromDate
toDate: page.toDate
}
}
}

35
src/TimelineDayRow.qml Normal file
View File

@ -0,0 +1,35 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls
Control {
id: control
property real dayWidth: 24
property alias fromDate: model.fromDate
property alias toDate: model.toDate
contentItem: Row {
Repeater {
model: model
delegate: Label {
required property string display
text: display
width: control.dayWidth
background: Rectangle {
border.color: "red"
border.width: 1
color: "yellow"
}
}
}
}
TimelineDayModel {
id: model
}
}

View File

@ -1,86 +0,0 @@
#include "calendarlistmodel.h"
#include <QSqlQuery>
#include <QVariant>
#include "database.h"
struct CalendarListModel::Calendar
{
QString name;
};
CalendarListModel::CalendarListModel(QObject *parent)
: QAbstractListModel{parent}
, m_calendars{}
{
fetch();
}
CalendarListModel::~CalendarListModel()
{
qDeleteAll(m_calendars);
}
QVariant CalendarListModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role != Qt::DisplayRole) {
return {};
}
return section;
}
int CalendarListModel::rowCount(const QModelIndex &parent) const
{
if (parent.isValid()) {
return 0;
}
return m_calendars.count();
}
QHash<int, QByteArray> CalendarListModel::roleNames() const
{
QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
roles[Name] = "name";
return roles;
}
void CalendarListModel::fetch()
{
Database::query([]() {
QSqlQuery query("select label from campsite order by label");
QVector<Calendar> calendars;
while (query.next()) {
Calendar calendar{query.value(0).toString()};
calendars.append(calendar);
}
return calendars;
}).then([this](const QVector<Calendar> &calendars) {
if (calendars.empty()) {
return;
}
beginInsertRows(QModelIndex(), 0, calendars.count() - 1);
for (const Calendar &calendar : calendars) {
m_calendars.append(new Calendar(calendar));
}
endInsertRows();
});
}
QVariant CalendarListModel::data(const QModelIndex &index, int role) const
{
if (!checkIndex(index,
QAbstractItemModel::CheckIndexOption::IndexIsValid
| QAbstractItemModel::CheckIndexOption::ParentIsInvalid)) {
return {};
}
Calendar *calendar = m_calendars.at(index.row());
switch (role) {
case Name:
return calendar->name;
}
return {};
}
#include "moc_calendarlistmodel.cpp"

View File

@ -1,40 +0,0 @@
#ifndef CALENDARLISTMODEL_H
#define CALENDARLISTMODEL_H
#include <QAbstractListModel>
#include <QtQmlIntegration>
class CalendarListModel : public QAbstractListModel
{
Q_OBJECT
QML_ELEMENT
public:
enum Roles {
Name = Qt::UserRole,
};
explicit CalendarListModel(QObject *parent = nullptr);
~CalendarListModel() override;
QVariant headerData(int section,
Qt::Orientation orientation,
int role = Qt::DisplayRole) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QHash<int, QByteArray> roleNames() const override;
private:
struct Calendar;
Q_DISABLE_COPY_MOVE(CalendarListModel)
void fetch();
QVector<Calendar *> m_calendars;
};
#endif // CALENDARLISTMODEL_H

65
src/timelinedaymodel.cpp Normal file
View File

@ -0,0 +1,65 @@
#include "timelinedaymodel.h"
#include <QVariant>
TimelineDayModel::TimelineDayModel(QObject *parent)
: QAbstractListModel(parent)
, m_fromDate()
, m_toDate()
{}
int TimelineDayModel::rowCount(const QModelIndex &parent) const
{
if (parent.isValid()) {
return 0;
}
return m_fromDate.daysTo(m_toDate) + 1;
}
QVariant TimelineDayModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid()) {
return {};
}
QDate date = m_fromDate.addDays(index.row());
switch (role) {
case Qt::DisplayRole:
return QString::number(date.day());
}
return {};
}
QDate TimelineDayModel::fromDate() const
{
return m_fromDate;
}
void TimelineDayModel::setFromDate(QDate date)
{
if (date == m_fromDate) {
return;
}
beginResetModel();
m_fromDate = date;
endResetModel();
emit fromDateChanged(m_fromDate);
}
QDate TimelineDayModel::toDate() const
{
return m_toDate;
}
void TimelineDayModel::setToDate(QDate date)
{
if (date == m_toDate) {
return;
}
beginResetModel();
m_toDate = date;
endResetModel();
emit toDateChanged(m_toDate);
}
#include "moc_timelinedaymodel.cpp"

38
src/timelinedaymodel.h Normal file
View File

@ -0,0 +1,38 @@
#ifndef TIMELINEDAYMODEL_H
#define TIMELINEDAYMODEL_H
#include <QAbstractListModel>
#include <QtQmlIntegration>
class TimelineDayModel : public QAbstractListModel
{
Q_OBJECT
QML_ELEMENT
Q_PROPERTY(QDate fromDate READ fromDate WRITE setFromDate NOTIFY fromDateChanged)
Q_PROPERTY(QDate toDate READ toDate WRITE setToDate NOTIFY toDateChanged)
public:
explicit TimelineDayModel(QObject *parent = nullptr);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
QDate fromDate() const;
void setFromDate(QDate date);
QDate toDate() const;
void setToDate(QDate date);
signals:
void fromDateChanged(QDate date);
void toDateChanged(QDate date);
private:
Q_DISABLE_COPY_MOVE(TimelineDayModel)
QDate m_fromDate;
QDate m_toDate;
};
#endif // TIMELINEDAYMODEL_H