Compare commits

...

2 Commits

Author SHA1 Message Date
jordi fita mas c49135247a 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.
2025-01-08 09:54:13 +01:00
jordi fita mas accc627ebd Rename struct TimelineViewItem to TimelineView::Item 2025-01-07 17:46:50 +01:00
9 changed files with 171 additions and 145 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

View File

@ -2,9 +2,9 @@
#include <QQmlContext>
#include <QQmlInfo>
struct TimelineViewItem
struct TimelineView::Item
{
TimelineViewItem(qint64 day, qint64 len, QQuickItem &qitem, TimelineView &view)
Item(qint64 day, qint64 len, QQuickItem &qitem, TimelineView &view)
: item(&qitem)
, day(day)
{
@ -14,7 +14,7 @@ struct TimelineViewItem
item->setVisible(true);
}
~TimelineViewItem()
~Item()
{
item->setVisible(false);
item->setParent(nullptr);
@ -150,7 +150,7 @@ void TimelineView::componentComplete()
populate();
}
TimelineViewItem *TimelineView::createItem(qint64 day, qint64 len)
TimelineView::Item *TimelineView::createItem(qint64 day, qint64 len)
{
QQuickItem *item = m_reusableItems.isEmpty() ? qobject_cast<QQuickItem *>(m_delegate->create(
m_delegate->creationContext()))
@ -159,11 +159,11 @@ TimelineViewItem *TimelineView::createItem(qint64 day, qint64 len)
qmlWarning(m_delegate) << TimelineView::tr("Delegate must be of Item type");
return nullptr;
}
auto *viewItem = new TimelineViewItem(day, len, *item, *this);
auto *viewItem = new TimelineView::Item(day, len, *item, *this);
return viewItem;
}
void TimelineView::releaseItem(TimelineViewItem *item)
void TimelineView::releaseItem(TimelineView::Item *item)
{
if (!item) {
return;
@ -201,7 +201,7 @@ void TimelineView::populate()
if (m_viewportX > m_prevViewportX) {
// Delete from the left
while (!m_items.isEmpty()) {
TimelineViewItem *item = m_items.first();
TimelineView::Item *item = m_items.first();
if (item->right() >= m_viewportX) {
break;
}
@ -215,7 +215,7 @@ void TimelineView::populate()
lastDay = qMax(-1, qFloor((m_viewportX - (len * m_dayWidth)) / m_dayWidth));
day > lastDay;
day -= len) {
TimelineViewItem *viewItem = createItem(day, len);
TimelineView::Item *viewItem = createItem(day, len);
if (!viewItem) {
break;
}
@ -227,7 +227,7 @@ void TimelineView::populate()
if (currentRight < prevRight) {
// Delete from the right
while (!m_items.isEmpty()) {
TimelineViewItem *item = m_items.last();
TimelineView::Item *item = m_items.last();
if (item->left() < currentRight) {
break;
}
@ -241,7 +241,7 @@ void TimelineView::populate()
lastDay = qFloor((currentRight + (len * m_dayWidth)) / m_dayWidth);
day < lastDay;
day += len) {
TimelineViewItem *viewItem = createItem(day, len);
TimelineView::Item *viewItem = createItem(day, len);
if (!viewItem) {
break;
}

View File

@ -5,7 +5,6 @@
#include <QQmlComponent>
#include <QQuickItem>
struct TimelineViewItem;
class TimelineView : public QQuickItem
{
Q_OBJECT
@ -54,8 +53,10 @@ protected:
private:
Q_DISABLE_COPY_MOVE(TimelineView)
TimelineViewItem *createItem(qint64 day, qint64 len);
void releaseItem(TimelineViewItem *item);
struct Item;
Item *createItem(qint64 day, qint64 len);
void releaseItem(Item *item);
void drainItems();
void clear();
@ -65,7 +66,7 @@ private:
qreal m_dayWidth;
QQmlComponent *m_delegate;
QDate m_fromDate;
QList<TimelineViewItem *> m_items;
QList<Item *> m_items;
QList<QQuickItem *> m_reusableItems;
QDate m_toDate;
qreal m_viewportX;