Compare commits
No commits in common. "ff27ea89d92dca420ad7435c7a99883d5f7b445f" and "c795effd3d9eba0f85bb7904c5d77553eb1c7362" have entirely different histories.
ff27ea89d9
...
c795effd3d
|
@ -23,11 +23,8 @@ qt_add_qml_module(${PROJECT_NAME}
|
||||||
Main.qml
|
Main.qml
|
||||||
MnemonicAction.qml
|
MnemonicAction.qml
|
||||||
MnemonicLabel.qml
|
MnemonicLabel.qml
|
||||||
PermanentScrollBar.qml
|
|
||||||
ReservationsPage.qml
|
ReservationsPage.qml
|
||||||
ReservationsTimeline.qml
|
|
||||||
SelectableLabel.qml
|
SelectableLabel.qml
|
||||||
Separator.qml
|
|
||||||
TimelineDayRow.qml
|
TimelineDayRow.qml
|
||||||
TimelineMonthRow.qml
|
TimelineMonthRow.qml
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
import QtQuick.Controls
|
|
||||||
|
|
||||||
ScrollBar {
|
|
||||||
policy: size < 1 ? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff
|
|
||||||
}
|
|
|
@ -1,4 +1,5 @@
|
||||||
pragma ComponentBehavior: Bound
|
pragma ComponentBehavior: Bound
|
||||||
|
import QtQuick
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
import Camper
|
import Camper
|
||||||
|
@ -6,6 +7,10 @@ import Camper
|
||||||
Page {
|
Page {
|
||||||
id: 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 {
|
||||||
|
@ -18,15 +23,118 @@ Page {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReservationsTimeline {
|
ListView {
|
||||||
anchors.fill: parent
|
id: lodgingList
|
||||||
anchors.margins: 32
|
|
||||||
dayWidth: 24
|
|
||||||
|
|
||||||
model: TimelineListModel {
|
ScrollBar.vertical: verticalScroll
|
||||||
fromDate: "2024-11-01"
|
anchors.bottom: parent.bottom
|
||||||
toDate: "2025-01-31"
|
anchors.left: parent.left
|
||||||
|
anchors.top: parent.top
|
||||||
|
headerPositioning: ListView.OverlayHeader
|
||||||
|
model: timelineListModel
|
||||||
|
width: 100
|
||||||
|
|
||||||
|
delegate: Label {
|
||||||
|
required property string name
|
||||||
|
|
||||||
|
text: name
|
||||||
}
|
}
|
||||||
|
header: Pane {
|
||||||
|
height: timelineList.headerItem.height
|
||||||
|
z: 2
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr("Lodging")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ListView {
|
||||||
|
id: timelineList
|
||||||
|
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.left: lodgingList.right
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.top: parent.top
|
||||||
|
clip: true
|
||||||
|
contentWidth: headerItem.implicitWidth
|
||||||
|
flickableDirection: Flickable.AutoFlickDirection
|
||||||
|
headerPositioning: ListView.OverlayHeader
|
||||||
|
model: timelineListModel
|
||||||
|
|
||||||
|
ScrollBar.horizontal: ScrollBar {
|
||||||
|
}
|
||||||
|
ScrollBar.vertical: ScrollBar {
|
||||||
|
id: verticalScroll
|
||||||
|
|
||||||
|
}
|
||||||
|
delegate: TimelineView {
|
||||||
|
required property TimelineModel timeline
|
||||||
|
|
||||||
|
dayWidth: page.dayWidth
|
||||||
|
fromDate: page.fromDate
|
||||||
|
height: 16
|
||||||
|
model: timeline
|
||||||
|
toDate: page.toDate
|
||||||
|
viewportWidth: ListView.view.width
|
||||||
|
viewportX: ListView.view.contentX
|
||||||
|
|
||||||
|
delegate: Rectangle {
|
||||||
|
id: booking
|
||||||
|
|
||||||
|
required property string holder
|
||||||
|
required property string reservationStatus
|
||||||
|
|
||||||
|
function reservationStatusColor(status) {
|
||||||
|
switch (status) {
|
||||||
|
case "created":
|
||||||
|
return "#cbebff";
|
||||||
|
case "cancelled":
|
||||||
|
return "#ffbaa6";
|
||||||
|
case "confirmed":
|
||||||
|
return "#ffe673";
|
||||||
|
case "checked-in":
|
||||||
|
return "#9fefb9";
|
||||||
|
case "invoiced":
|
||||||
|
return "#e1dbd6";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
border.color: "black"
|
||||||
|
border.width: 1
|
||||||
|
color: reservationStatusColor(reservationStatus)
|
||||||
|
|
||||||
|
Label {
|
||||||
|
anchors.fill: parent
|
||||||
|
elide: Text.ElideRight
|
||||||
|
text: booking.holder
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
header: Pane {
|
||||||
|
leftPadding: 0
|
||||||
|
rightPadding: 0
|
||||||
|
z: 2
|
||||||
|
|
||||||
|
Column {
|
||||||
|
TimelineMonthRow {
|
||||||
|
dayWidth: page.dayWidth
|
||||||
|
fromDate: page.fromDate
|
||||||
|
toDate: page.toDate
|
||||||
|
}
|
||||||
|
|
||||||
|
TimelineDayRow {
|
||||||
|
dayWidth: page.dayWidth
|
||||||
|
fromDate: page.fromDate
|
||||||
|
toDate: page.toDate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TimelineListModel {
|
||||||
|
id: timelineListModel
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MnemonicAction {
|
MnemonicAction {
|
||||||
|
|
|
@ -1,235 +0,0 @@
|
||||||
pragma ComponentBehavior: Bound
|
|
||||||
import QtQuick
|
|
||||||
import QtQuick.Controls
|
|
||||||
import QtQuick.Controls.Fusion
|
|
||||||
|
|
||||||
Control {
|
|
||||||
id: control
|
|
||||||
|
|
||||||
required property real dayWidth
|
|
||||||
property date fromDate: model.fromDate
|
|
||||||
required property TimelineListModel model
|
|
||||||
property real rowHeight: 32
|
|
||||||
property date toDate: model.toDate
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: lodgingList
|
|
||||||
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.top: parent.top
|
|
||||||
border.color: Fusion.outline(control.palette)
|
|
||||||
color: control.palette.base
|
|
||||||
width: 100
|
|
||||||
|
|
||||||
ListView {
|
|
||||||
ScrollBar.vertical: verticalScroll
|
|
||||||
anchors.fill: parent
|
|
||||||
boundsBehavior: Flickable.StopAtBounds
|
|
||||||
clip: true
|
|
||||||
headerPositioning: ListView.OverlayHeader
|
|
||||||
model: control.model
|
|
||||||
|
|
||||||
delegate: Column {
|
|
||||||
required property string name
|
|
||||||
|
|
||||||
width: ListView.view.width
|
|
||||||
|
|
||||||
Label {
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.leftMargin: 6
|
|
||||||
anchors.right: parent.right
|
|
||||||
height: control.rowHeight - 1
|
|
||||||
text: parent.name
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
Separator {
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
palette: control.palette
|
|
||||||
}
|
|
||||||
}
|
|
||||||
header: Rectangle {
|
|
||||||
border.color: Fusion.outline(control.palette)
|
|
||||||
color: control.palette.base
|
|
||||||
height: timelineList.headerItem.height
|
|
||||||
width: parent.width
|
|
||||||
z: 2
|
|
||||||
|
|
||||||
Label {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
font.bold: true
|
|
||||||
text: qsTr("Lodging")
|
|
||||||
}
|
|
||||||
|
|
||||||
Separator {
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.bottomMargin: 1
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
palette: control.palette
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.left: lodgingList.right
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.top: parent.top
|
|
||||||
border.color: Fusion.outline(control.palette)
|
|
||||||
color: control.palette.base
|
|
||||||
|
|
||||||
ListView {
|
|
||||||
id: timelineList
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
boundsBehavior: Flickable.StopAtBounds
|
|
||||||
clip: true
|
|
||||||
contentWidth: headerItem.implicitWidth
|
|
||||||
flickableDirection: Flickable.AutoFlickDirection
|
|
||||||
headerPositioning: ListView.OverlayHeader
|
|
||||||
model: control.model
|
|
||||||
|
|
||||||
ScrollBar.horizontal: PermanentScrollBar {
|
|
||||||
}
|
|
||||||
ScrollBar.vertical: PermanentScrollBar {
|
|
||||||
id: verticalScroll
|
|
||||||
|
|
||||||
}
|
|
||||||
delegate: TimelineView {
|
|
||||||
property real contentWidth: ListView.view.contentWidth
|
|
||||||
required property TimelineModel timeline
|
|
||||||
|
|
||||||
dayWidth: control.dayWidth
|
|
||||||
fromDate: control.fromDate
|
|
||||||
height: control.rowHeight
|
|
||||||
model: timeline
|
|
||||||
toDate: control.toDate
|
|
||||||
viewportWidth: ListView.view.width
|
|
||||||
viewportX: ListView.view.contentX
|
|
||||||
|
|
||||||
delegate: Label {
|
|
||||||
id: reservation
|
|
||||||
|
|
||||||
required property string holder
|
|
||||||
required property string reservationStatus
|
|
||||||
|
|
||||||
elide: Text.ElideRight
|
|
||||||
padding: 2
|
|
||||||
text: holder
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
z: 1
|
|
||||||
|
|
||||||
background: Rectangle {
|
|
||||||
function backgroundColor(status) {
|
|
||||||
switch (status) {
|
|
||||||
case "created":
|
|
||||||
return "#cbebff";
|
|
||||||
case "cancelled":
|
|
||||||
return "#ffbaa6";
|
|
||||||
case "confirmed":
|
|
||||||
return "#ffe673";
|
|
||||||
case "checked-in":
|
|
||||||
return "#9fefb9";
|
|
||||||
case "invoiced":
|
|
||||||
return "#e1dbd6";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function borderColor(status) {
|
|
||||||
switch (status) {
|
|
||||||
case "created":
|
|
||||||
return "#6fc7fe";
|
|
||||||
case "cancelled":
|
|
||||||
return "#ff7851";
|
|
||||||
case "confirmed":
|
|
||||||
return "#ffd829";
|
|
||||||
case "checked-in":
|
|
||||||
return "#5ae387";
|
|
||||||
case "invoiced":
|
|
||||||
return "#bbaea3";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
border.color: borderColor(reservation.reservationStatus)
|
|
||||||
color: backgroundColor(reservation.reservationStatus)
|
|
||||||
radius: 5
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Separator {
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
palette: control.palette
|
|
||||||
}
|
|
||||||
}
|
|
||||||
header: Rectangle {
|
|
||||||
border.color: Fusion.outline(control.palette)
|
|
||||||
color: control.palette.base
|
|
||||||
implicitHeight: headerLayout.implicitHeight + 1
|
|
||||||
implicitWidth: headerLayout.implicitWidth
|
|
||||||
z: 2
|
|
||||||
|
|
||||||
Column {
|
|
||||||
id: headerLayout
|
|
||||||
|
|
||||||
TimelineMonthRow {
|
|
||||||
dayWidth: control.dayWidth
|
|
||||||
fromDate: control.fromDate
|
|
||||||
height: 24
|
|
||||||
toDate: control.toDate
|
|
||||||
}
|
|
||||||
|
|
||||||
Separator {
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
palette: control.palette
|
|
||||||
}
|
|
||||||
|
|
||||||
TimelineDayRow {
|
|
||||||
dayWidth: control.dayWidth
|
|
||||||
fromDate: control.fromDate
|
|
||||||
height: 24
|
|
||||||
toDate: control.toDate
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Separator {
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.bottomMargin: 1
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
palette: control.palette
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Row {
|
|
||||||
height: parent.height
|
|
||||||
parent: timelineList.contentItem
|
|
||||||
|
|
||||||
Repeater {
|
|
||||||
delegate: Rectangle {
|
|
||||||
color: "transparent"
|
|
||||||
height: parent.height
|
|
||||||
width: control.dayWidth
|
|
||||||
|
|
||||||
Separator {
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.top: parent.top
|
|
||||||
palette: control.palette
|
|
||||||
}
|
|
||||||
}
|
|
||||||
model: TimelineDayModel {
|
|
||||||
fromDate: control.fromDate
|
|
||||||
toDate: control.toDate
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
pragma ComponentBehavior: Bound
|
|
||||||
import QtQuick
|
|
||||||
import QtQuick.Controls.Fusion
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
required property Palette palette
|
|
||||||
|
|
||||||
Accessible.role: Accessible.Separator
|
|
||||||
color: Fusion.outline(palette)
|
|
||||||
implicitHeight: 1
|
|
||||||
implicitWidth: 1
|
|
||||||
}
|
|
|
@ -16,19 +16,13 @@ Control {
|
||||||
delegate: Label {
|
delegate: Label {
|
||||||
required property string display
|
required property string display
|
||||||
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.top: parent.top
|
|
||||||
font.bold: true
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
text: display
|
text: display
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
width: control.dayWidth
|
width: control.dayWidth
|
||||||
|
|
||||||
Separator {
|
background: Rectangle {
|
||||||
anchors.bottom: parent.bottom
|
border.color: "red"
|
||||||
anchors.right: parent.right
|
border.width: 1
|
||||||
anchors.top: parent.top
|
color: "yellow"
|
||||||
palette: control.palette
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
pragma ComponentBehavior: Bound
|
pragma ComponentBehavior: Bound
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
import QtQuick.Controls.Fusion
|
|
||||||
|
|
||||||
Control {
|
Control {
|
||||||
id: control
|
id: control
|
||||||
|
@ -15,32 +14,18 @@ Control {
|
||||||
model: model
|
model: model
|
||||||
|
|
||||||
delegate: Label {
|
delegate: Label {
|
||||||
id: label
|
|
||||||
|
|
||||||
required property int dayCount
|
required property int dayCount
|
||||||
required property string display
|
required property string display
|
||||||
required property int index
|
|
||||||
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.top: parent.top
|
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
font.bold: true
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
leftInset: index == 0 ? 1 : 0
|
|
||||||
text: display
|
text: display
|
||||||
topInset: 1
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
width: control.dayWidth * dayCount
|
width: control.dayWidth * dayCount
|
||||||
|
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
color: label.index % 2 ? control.palette.alternateBase : control.palette.base
|
border.color: "red"
|
||||||
}
|
border.width: 1
|
||||||
|
color: "lightgreen"
|
||||||
Separator {
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.top: parent.top
|
|
||||||
palette: control.palette
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,15 +89,4 @@ QFuture<void> Database::close()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::checkError(const QSqlQuery &query)
|
|
||||||
{
|
|
||||||
QSqlError lastError = query.lastError();
|
|
||||||
if (!lastError.isValid()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
QString errorMessage = lastError.text();
|
|
||||||
emit getInstance().errorOcurred(errorMessage);
|
|
||||||
throw std::runtime_error(errorMessage.toStdString());
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "moc_database.cpp"
|
#include "moc_database.cpp"
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
#include <QThreadPool>
|
#include <QThreadPool>
|
||||||
#include <QtConcurrent>
|
#include <QtConcurrent>
|
||||||
|
|
||||||
class QSqlQuery;
|
|
||||||
class Database : public QObject
|
class Database : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -28,8 +27,6 @@ public:
|
||||||
const QString &connectOptions);
|
const QString &connectOptions);
|
||||||
Q_INVOKABLE QFuture<void> close();
|
Q_INVOKABLE QFuture<void> close();
|
||||||
|
|
||||||
static void checkError(const QSqlQuery &query);
|
|
||||||
|
|
||||||
template<class Function>
|
template<class Function>
|
||||||
static auto query(Function &&f)
|
static auto query(Function &&f)
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,8 +5,6 @@
|
||||||
#include "database.h"
|
#include "database.h"
|
||||||
#include "timelinemodel.h"
|
#include "timelinemodel.h"
|
||||||
|
|
||||||
using namespace Qt::Literals::StringLiterals;
|
|
||||||
|
|
||||||
struct TimelineListModel::Item
|
struct TimelineListModel::Item
|
||||||
{
|
{
|
||||||
Item(int id, const QString name, QObject *parent = nullptr)
|
Item(int id, const QString name, QObject *parent = nullptr)
|
||||||
|
@ -25,9 +23,9 @@ struct TimelineListModel::Item
|
||||||
TimelineListModel::TimelineListModel(QObject *parent)
|
TimelineListModel::TimelineListModel(QObject *parent)
|
||||||
: QAbstractListModel{parent}
|
: QAbstractListModel{parent}
|
||||||
, m_items{}
|
, m_items{}
|
||||||
, m_fromDate{}
|
{
|
||||||
, m_toDate{}
|
fetch();
|
||||||
{}
|
}
|
||||||
|
|
||||||
TimelineListModel::~TimelineListModel()
|
TimelineListModel::~TimelineListModel()
|
||||||
{
|
{
|
||||||
|
@ -59,47 +57,6 @@ QHash<int, QByteArray> TimelineListModel::roleNames() const
|
||||||
return roles;
|
return roles;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineListModel::clear()
|
|
||||||
{
|
|
||||||
if (m_items.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
beginResetModel();
|
|
||||||
qDeleteAll(m_items);
|
|
||||||
m_items.clear();
|
|
||||||
endResetModel();
|
|
||||||
}
|
|
||||||
|
|
||||||
QDate TimelineListModel::fromDate() const
|
|
||||||
{
|
|
||||||
return m_fromDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimelineListModel::setFromDate(QDate date)
|
|
||||||
{
|
|
||||||
if (date == m_fromDate) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_fromDate = date;
|
|
||||||
emit fromDateChanged(m_fromDate);
|
|
||||||
refill();
|
|
||||||
}
|
|
||||||
|
|
||||||
QDate TimelineListModel::toDate() const
|
|
||||||
{
|
|
||||||
return m_toDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimelineListModel::setToDate(QDate date)
|
|
||||||
{
|
|
||||||
if (date == m_toDate) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_toDate = date;
|
|
||||||
emit toDateChanged(m_toDate);
|
|
||||||
refill();
|
|
||||||
}
|
|
||||||
|
|
||||||
QModelIndex TimelineListModel::findIndexById(int id)
|
QModelIndex TimelineListModel::findIndexById(int id)
|
||||||
{
|
{
|
||||||
for (qsizetype row = 0; row < m_items.count(); ++row) {
|
for (qsizetype row = 0; row < m_items.count(); ++row) {
|
||||||
|
@ -110,13 +67,8 @@ QModelIndex TimelineListModel::findIndexById(int id)
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineListModel::refill()
|
void TimelineListModel::fetch()
|
||||||
{
|
{
|
||||||
if (!m_fromDate.isValid() || !m_toDate.isValid()) {
|
|
||||||
clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Lodging
|
struct Lodging
|
||||||
{
|
{
|
||||||
int id;
|
int id;
|
||||||
|
@ -129,40 +81,29 @@ void TimelineListModel::refill()
|
||||||
QHash<int, QList<TimelineModel::Item *>> bookings;
|
QHash<int, QList<TimelineModel::Item *>> bookings;
|
||||||
};
|
};
|
||||||
|
|
||||||
QDate fromDate = m_fromDate;
|
Database::query([]() {
|
||||||
QDate toDate = m_toDate;
|
|
||||||
Database::query([fromDate, toDate]() {
|
|
||||||
Results results;
|
Results results;
|
||||||
{
|
{
|
||||||
QSqlQuery query("select campsite_id, label from campsite order by label, campsite_id");
|
QSqlQuery query("select campsite_id, label from campsite order by label, campsite_id");
|
||||||
Database::checkError(query);
|
|
||||||
while (query.next()) {
|
while (query.next()) {
|
||||||
Lodging item{query.value(0).toInt(), query.value(1).toString()};
|
Lodging item{query.value(0).toInt(), query.value(1).toString()};
|
||||||
results.lodgings.append(item);
|
results.lodgings.append(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
QSqlQuery query;
|
QSqlQuery query(" select "
|
||||||
query.setForwardOnly(true);
|
" campsite_id "
|
||||||
query.prepare(" select "
|
" , booking_id "
|
||||||
" campsite_id "
|
" , lower(booking_campsite.stay) "
|
||||||
" , booking_id "
|
" , upper(booking_campsite.stay) - lower(booking_campsite.stay)"
|
||||||
" , lower(booking_campsite.stay) "
|
" , holder_name "
|
||||||
" , upper(booking_campsite.stay) - lower(booking_campsite.stay)"
|
" , booking_status "
|
||||||
" , holder_name "
|
" , true"
|
||||||
" , booking_status "
|
" , true"
|
||||||
" , true"
|
" from booking_campsite "
|
||||||
" , true"
|
" join booking using (booking_id) "
|
||||||
" from booking_campsite "
|
" order by lower(booking_campsite.stay), booking_id "
|
||||||
" join booking using (booking_id) "
|
"");
|
||||||
" where booking_campsite.stay && daterange(:fromDate, :toDate)"
|
|
||||||
" order by lower(booking_campsite.stay), booking_id "
|
|
||||||
""_L1);
|
|
||||||
Database::checkError(query);
|
|
||||||
query.bindValue(":fromDate"_L1, fromDate);
|
|
||||||
query.bindValue(":toDate"_L1, toDate);
|
|
||||||
query.exec();
|
|
||||||
Database::checkError(query);
|
|
||||||
while (query.next()) {
|
while (query.next()) {
|
||||||
int lodgingId = query.value(0).toInt();
|
int lodgingId = query.value(0).toInt();
|
||||||
auto *item = new TimelineModel::Item{
|
auto *item = new TimelineModel::Item{
|
||||||
|
@ -211,7 +152,6 @@ void TimelineListModel::refill()
|
||||||
}
|
}
|
||||||
if (itemsRow < m_items.count()) {
|
if (itemsRow < m_items.count()) {
|
||||||
beginRemoveRows({}, itemsRow, m_items.count() - 1);
|
beginRemoveRows({}, itemsRow, m_items.count() - 1);
|
||||||
qDeleteAll(m_items.begin() + itemsRow, m_items.end());
|
|
||||||
m_items.remove(itemsRow, m_items.count() - itemsRow);
|
m_items.remove(itemsRow, m_items.count() - itemsRow);
|
||||||
endRemoveRows();
|
endRemoveRows();
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,6 @@ class TimelineListModel : public QAbstractListModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
QML_ELEMENT
|
QML_ELEMENT
|
||||||
Q_PROPERTY(QDate fromDate READ fromDate WRITE setFromDate NOTIFY fromDateChanged REQUIRED)
|
|
||||||
Q_PROPERTY(QDate toDate READ toDate WRITE setToDate NOTIFY toDateChanged REQUIRED)
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum Roles {
|
enum Roles {
|
||||||
|
@ -24,33 +22,22 @@ public:
|
||||||
QVariant headerData(int section,
|
QVariant headerData(int section,
|
||||||
Qt::Orientation orientation,
|
Qt::Orientation orientation,
|
||||||
int role = Qt::DisplayRole) const override;
|
int role = Qt::DisplayRole) const override;
|
||||||
|
|
||||||
QVariant data(const QModelIndex &index, 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;
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
|
||||||
QHash<int, QByteArray> roleNames() const override;
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
QDate fromDate() const;
|
|
||||||
void setFromDate(QDate date);
|
|
||||||
|
|
||||||
QDate toDate() const;
|
|
||||||
void setToDate(QDate date);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void fromDateChanged(QDate date);
|
|
||||||
void toDateChanged(QDate date);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Q_DISABLE_COPY_MOVE(TimelineListModel)
|
Q_DISABLE_COPY_MOVE(TimelineListModel)
|
||||||
|
|
||||||
struct Item;
|
struct Item;
|
||||||
|
|
||||||
QModelIndex findIndexById(int id);
|
QModelIndex findIndexById(int id);
|
||||||
void refill();
|
void fetch();
|
||||||
|
|
||||||
QList<Item *> m_items;
|
QList<Item *> m_items;
|
||||||
QDate m_fromDate;
|
|
||||||
QDate m_toDate;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TIMELINELISTMODEL_H
|
#endif // TIMELINELISTMODEL_H
|
||||||
|
|
|
@ -288,7 +288,7 @@ void TimelineView::populate()
|
||||||
|
|
||||||
void TimelineView::updateImplicitWidth()
|
void TimelineView::updateImplicitWidth()
|
||||||
{
|
{
|
||||||
setImplicitWidth(m_dayWidth * (m_fromDate.daysTo(m_toDate) + 1));
|
setImplicitWidth(m_dayWidth * m_fromDate.daysTo(m_toDate));
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "moc_timelineview.cpp"
|
#include "moc_timelineview.cpp"
|
||||||
|
|
Loading…
Reference in New Issue