Compare commits
2 Commits
00255f67a0
...
c49135247a
Author | SHA1 | Date |
---|---|---|
|
c49135247a | |
|
accc627ebd |
|
@ -12,6 +12,7 @@ qt_add_qml_module(${PROJECT_NAME}
|
||||||
calendarlistmodel.cpp calendarlistmodel.h
|
calendarlistmodel.cpp calendarlistmodel.h
|
||||||
database.cpp database.h
|
database.cpp database.h
|
||||||
mnemonicattached.cpp mnemonicattached.h
|
mnemonicattached.cpp mnemonicattached.h
|
||||||
|
timelinedaymodel.cpp timelinedaymodel.h
|
||||||
timelineview.cpp timelineview.h
|
timelineview.cpp timelineview.h
|
||||||
QML_FILES
|
QML_FILES
|
||||||
ErrorNotification.qml
|
ErrorNotification.qml
|
||||||
|
@ -22,6 +23,7 @@ qt_add_qml_module(${PROJECT_NAME}
|
||||||
MnemonicLabel.qml
|
MnemonicLabel.qml
|
||||||
ReservationsPage.qml
|
ReservationsPage.qml
|
||||||
SelectableLabel.qml
|
SelectableLabel.qml
|
||||||
|
TimelineDayRow.qml
|
||||||
)
|
)
|
||||||
|
|
||||||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||||
|
|
|
@ -5,6 +5,12 @@ import QtQuick.Layouts
|
||||||
import Camper
|
import Camper
|
||||||
|
|
||||||
Page {
|
Page {
|
||||||
|
id: page
|
||||||
|
|
||||||
|
property real dayWidth: 24
|
||||||
|
property date fromDate: "2024-11-01"
|
||||||
|
property date toDate: "2025-01-31"
|
||||||
|
|
||||||
title: qsTr("Reservations")
|
title: qsTr("Reservations")
|
||||||
|
|
||||||
header: ToolBar {
|
header: ToolBar {
|
||||||
|
@ -50,7 +56,7 @@ Page {
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
clip: true
|
clip: true
|
||||||
contentWidth: 2184
|
contentWidth: headerItem.implicitWidth
|
||||||
flickableDirection: Flickable.AutoFlickDirection
|
flickableDirection: Flickable.AutoFlickDirection
|
||||||
headerPositioning: ListView.OverlayHeader
|
headerPositioning: ListView.OverlayHeader
|
||||||
model: calendarList
|
model: calendarList
|
||||||
|
@ -62,9 +68,10 @@ Page {
|
||||||
|
|
||||||
}
|
}
|
||||||
delegate: TimelineView {
|
delegate: TimelineView {
|
||||||
fromDate: "2024-11-01"
|
dayWidth: page.dayWidth
|
||||||
|
fromDate: page.fromDate
|
||||||
height: 16
|
height: 16
|
||||||
toDate: "2025-01-31"
|
toDate: page.toDate
|
||||||
viewportWidth: ListView.view.width
|
viewportWidth: ListView.view.width
|
||||||
viewportX: ListView.view.contentX
|
viewportX: ListView.view.contentX
|
||||||
|
|
||||||
|
@ -75,10 +82,14 @@ Page {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
header: Pane {
|
header: Pane {
|
||||||
|
leftPadding: 0
|
||||||
|
rightPadding: 0
|
||||||
z: 2
|
z: 2
|
||||||
|
|
||||||
Label {
|
TimelineDayRow {
|
||||||
text: qsTr("Calendar")
|
dayWidth: page.dayWidth
|
||||||
|
fromDate: page.fromDate
|
||||||
|
toDate: page.toDate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -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"
|
|
|
@ -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
|
|
|
@ -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"
|
|
@ -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
|
|
@ -2,9 +2,9 @@
|
||||||
#include <QQmlContext>
|
#include <QQmlContext>
|
||||||
#include <QQmlInfo>
|
#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)
|
: item(&qitem)
|
||||||
, day(day)
|
, day(day)
|
||||||
{
|
{
|
||||||
|
@ -14,7 +14,7 @@ struct TimelineViewItem
|
||||||
item->setVisible(true);
|
item->setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
~TimelineViewItem()
|
~Item()
|
||||||
{
|
{
|
||||||
item->setVisible(false);
|
item->setVisible(false);
|
||||||
item->setParent(nullptr);
|
item->setParent(nullptr);
|
||||||
|
@ -150,7 +150,7 @@ void TimelineView::componentComplete()
|
||||||
populate();
|
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(
|
QQuickItem *item = m_reusableItems.isEmpty() ? qobject_cast<QQuickItem *>(m_delegate->create(
|
||||||
m_delegate->creationContext()))
|
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");
|
qmlWarning(m_delegate) << TimelineView::tr("Delegate must be of Item type");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
auto *viewItem = new TimelineViewItem(day, len, *item, *this);
|
auto *viewItem = new TimelineView::Item(day, len, *item, *this);
|
||||||
return viewItem;
|
return viewItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineView::releaseItem(TimelineViewItem *item)
|
void TimelineView::releaseItem(TimelineView::Item *item)
|
||||||
{
|
{
|
||||||
if (!item) {
|
if (!item) {
|
||||||
return;
|
return;
|
||||||
|
@ -201,7 +201,7 @@ void TimelineView::populate()
|
||||||
if (m_viewportX > m_prevViewportX) {
|
if (m_viewportX > m_prevViewportX) {
|
||||||
// Delete from the left
|
// Delete from the left
|
||||||
while (!m_items.isEmpty()) {
|
while (!m_items.isEmpty()) {
|
||||||
TimelineViewItem *item = m_items.first();
|
TimelineView::Item *item = m_items.first();
|
||||||
if (item->right() >= m_viewportX) {
|
if (item->right() >= m_viewportX) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -215,7 +215,7 @@ void TimelineView::populate()
|
||||||
lastDay = qMax(-1, qFloor((m_viewportX - (len * m_dayWidth)) / m_dayWidth));
|
lastDay = qMax(-1, qFloor((m_viewportX - (len * m_dayWidth)) / m_dayWidth));
|
||||||
day > lastDay;
|
day > lastDay;
|
||||||
day -= len) {
|
day -= len) {
|
||||||
TimelineViewItem *viewItem = createItem(day, len);
|
TimelineView::Item *viewItem = createItem(day, len);
|
||||||
if (!viewItem) {
|
if (!viewItem) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -227,7 +227,7 @@ void TimelineView::populate()
|
||||||
if (currentRight < prevRight) {
|
if (currentRight < prevRight) {
|
||||||
// Delete from the right
|
// Delete from the right
|
||||||
while (!m_items.isEmpty()) {
|
while (!m_items.isEmpty()) {
|
||||||
TimelineViewItem *item = m_items.last();
|
TimelineView::Item *item = m_items.last();
|
||||||
if (item->left() < currentRight) {
|
if (item->left() < currentRight) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -241,7 +241,7 @@ void TimelineView::populate()
|
||||||
lastDay = qFloor((currentRight + (len * m_dayWidth)) / m_dayWidth);
|
lastDay = qFloor((currentRight + (len * m_dayWidth)) / m_dayWidth);
|
||||||
day < lastDay;
|
day < lastDay;
|
||||||
day += len) {
|
day += len) {
|
||||||
TimelineViewItem *viewItem = createItem(day, len);
|
TimelineView::Item *viewItem = createItem(day, len);
|
||||||
if (!viewItem) {
|
if (!viewItem) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#include <QQmlComponent>
|
#include <QQmlComponent>
|
||||||
#include <QQuickItem>
|
#include <QQuickItem>
|
||||||
|
|
||||||
struct TimelineViewItem;
|
|
||||||
class TimelineView : public QQuickItem
|
class TimelineView : public QQuickItem
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -54,8 +53,10 @@ protected:
|
||||||
private:
|
private:
|
||||||
Q_DISABLE_COPY_MOVE(TimelineView)
|
Q_DISABLE_COPY_MOVE(TimelineView)
|
||||||
|
|
||||||
TimelineViewItem *createItem(qint64 day, qint64 len);
|
struct Item;
|
||||||
void releaseItem(TimelineViewItem *item);
|
|
||||||
|
Item *createItem(qint64 day, qint64 len);
|
||||||
|
void releaseItem(Item *item);
|
||||||
void drainItems();
|
void drainItems();
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
@ -65,7 +66,7 @@ private:
|
||||||
qreal m_dayWidth;
|
qreal m_dayWidth;
|
||||||
QQmlComponent *m_delegate;
|
QQmlComponent *m_delegate;
|
||||||
QDate m_fromDate;
|
QDate m_fromDate;
|
||||||
QList<TimelineViewItem *> m_items;
|
QList<Item *> m_items;
|
||||||
QList<QQuickItem *> m_reusableItems;
|
QList<QQuickItem *> m_reusableItems;
|
||||||
QDate m_toDate;
|
QDate m_toDate;
|
||||||
qreal m_viewportX;
|
qreal m_viewportX;
|
||||||
|
|
Loading…
Reference in New Issue