Add TimelineModel and use it to feed each TimelineView
I have my doubts whether this model should be QAbstractListModel-derived or not. At first i thought i could not be, because i need to be able to get a “view” (i.e., a [begin, end) pair of iterators) based on the segment of TimelineView that becomes exposed due to scroll. However, QAbstractItemModel::match returns a QModelIndexList, and that could also be used for the same purpose, except that there is no QDateRange…. Until i have more needs for this model, the current coupling between TimelineModel and TimelineView is OK, as i do not expect TimelineView to be used for anything else. I also renamed CalendarModel to TimelineListModel, since this is the important part—the timeline—, and there is no “calendar” thing anywhere in the application—at least, not what traditionally is understood as a calendar, that is.
This commit is contained in:
parent
c49135247a
commit
94b5faa9d8
|
@ -9,10 +9,11 @@ qt_add_qml_module(${PROJECT_NAME}
|
||||||
QtCore
|
QtCore
|
||||||
QtQuick
|
QtQuick
|
||||||
SOURCES
|
SOURCES
|
||||||
calendarlistmodel.cpp calendarlistmodel.h
|
|
||||||
database.cpp database.h
|
database.cpp database.h
|
||||||
mnemonicattached.cpp mnemonicattached.h
|
mnemonicattached.cpp mnemonicattached.h
|
||||||
timelinedaymodel.cpp timelinedaymodel.h
|
timelinedaymodel.cpp timelinedaymodel.h
|
||||||
|
timelinelistmodel.cpp timelinelistmodel.h
|
||||||
|
timelinemodel.cpp timelinemodel.h
|
||||||
timelineview.cpp timelineview.h
|
timelineview.cpp timelineview.h
|
||||||
QML_FILES
|
QML_FILES
|
||||||
ErrorNotification.qml
|
ErrorNotification.qml
|
||||||
|
|
|
@ -31,7 +31,7 @@ Page {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
headerPositioning: ListView.OverlayHeader
|
headerPositioning: ListView.OverlayHeader
|
||||||
model: calendarList
|
model: timelineListModel
|
||||||
width: 100
|
width: 100
|
||||||
|
|
||||||
delegate: Label {
|
delegate: Label {
|
||||||
|
@ -59,7 +59,7 @@ Page {
|
||||||
contentWidth: headerItem.implicitWidth
|
contentWidth: headerItem.implicitWidth
|
||||||
flickableDirection: Flickable.AutoFlickDirection
|
flickableDirection: Flickable.AutoFlickDirection
|
||||||
headerPositioning: ListView.OverlayHeader
|
headerPositioning: ListView.OverlayHeader
|
||||||
model: calendarList
|
model: timelineListModel
|
||||||
|
|
||||||
ScrollBar.horizontal: ScrollBar {
|
ScrollBar.horizontal: ScrollBar {
|
||||||
}
|
}
|
||||||
|
@ -68,9 +68,12 @@ Page {
|
||||||
|
|
||||||
}
|
}
|
||||||
delegate: TimelineView {
|
delegate: TimelineView {
|
||||||
|
required property TimelineModel timeline
|
||||||
|
|
||||||
dayWidth: page.dayWidth
|
dayWidth: page.dayWidth
|
||||||
fromDate: page.fromDate
|
fromDate: page.fromDate
|
||||||
height: 16
|
height: 16
|
||||||
|
model: timeline
|
||||||
toDate: page.toDate
|
toDate: page.toDate
|
||||||
viewportWidth: ListView.view.width
|
viewportWidth: ListView.view.width
|
||||||
viewportX: ListView.view.contentX
|
viewportX: ListView.view.contentX
|
||||||
|
@ -94,8 +97,8 @@ Page {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CalendarListModel {
|
TimelineListModel {
|
||||||
id: calendarList
|
id: timelineListModel
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,194 @@
|
||||||
|
#include "timelinelistmodel.h"
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QSqlQuery>
|
||||||
|
#include <QVariant>
|
||||||
|
#include "database.h"
|
||||||
|
#include "timelinemodel.h"
|
||||||
|
|
||||||
|
struct TimelineListModel::Item
|
||||||
|
{
|
||||||
|
Item(int id, const QString name, QObject *parent = nullptr)
|
||||||
|
: id(id)
|
||||||
|
, name(name)
|
||||||
|
, timeline(new TimelineModel(parent))
|
||||||
|
{}
|
||||||
|
|
||||||
|
~Item() { timeline->deleteLater(); }
|
||||||
|
|
||||||
|
int id;
|
||||||
|
QString name;
|
||||||
|
TimelineModel *timeline;
|
||||||
|
};
|
||||||
|
|
||||||
|
TimelineListModel::TimelineListModel(QObject *parent)
|
||||||
|
: QAbstractListModel{parent}
|
||||||
|
, m_items{}
|
||||||
|
{
|
||||||
|
fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
TimelineListModel::~TimelineListModel()
|
||||||
|
{
|
||||||
|
qDeleteAll(m_items);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant TimelineListModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||||
|
{
|
||||||
|
if (role != Qt::DisplayRole) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return section;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TimelineListModel::rowCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
if (parent.isValid()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_items.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
QHash<int, QByteArray> TimelineListModel::roleNames() const
|
||||||
|
{
|
||||||
|
QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
|
||||||
|
roles[NameRole] = "name";
|
||||||
|
roles[TimelineRole] = "timeline";
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex TimelineListModel::findIndexById(int id)
|
||||||
|
{
|
||||||
|
for (qsizetype row = 0; row < m_items.count(); ++row) {
|
||||||
|
if (m_items.at(row)->id == id) {
|
||||||
|
return index(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimelineListModel::fetch()
|
||||||
|
{
|
||||||
|
struct Lodging
|
||||||
|
{
|
||||||
|
int id;
|
||||||
|
QString label;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Results
|
||||||
|
{
|
||||||
|
QList<Lodging> lodgings;
|
||||||
|
QHash<int, QList<TimelineModel::Item *>> bookings;
|
||||||
|
};
|
||||||
|
|
||||||
|
Database::query([]() {
|
||||||
|
Results results;
|
||||||
|
{
|
||||||
|
QSqlQuery query("select campsite_id, label from campsite order by label, campsite_id");
|
||||||
|
while (query.next()) {
|
||||||
|
Lodging item{query.value(0).toInt(), query.value(1).toString()};
|
||||||
|
results.lodgings.append(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
QSqlQuery query(" select "
|
||||||
|
" campsite_id "
|
||||||
|
" , booking_id "
|
||||||
|
" , lower(booking_campsite.stay) "
|
||||||
|
" , upper(booking_campsite.stay) - lower(booking_campsite.stay)"
|
||||||
|
" , holder_name "
|
||||||
|
" , booking_status "
|
||||||
|
" , true"
|
||||||
|
" , true"
|
||||||
|
" from booking_campsite "
|
||||||
|
" join booking using (booking_id) "
|
||||||
|
" order by lower(booking_campsite.stay), booking_id "
|
||||||
|
"");
|
||||||
|
while (query.next()) {
|
||||||
|
int lodgingId = query.value(0).toInt();
|
||||||
|
auto *item = new TimelineModel::Item{
|
||||||
|
query.value(1).toInt(),
|
||||||
|
query.value(2).toDate(),
|
||||||
|
query.value(3).toInt(),
|
||||||
|
query.value(4).toString(),
|
||||||
|
query.value(5).toString(),
|
||||||
|
query.value(6).toBool(),
|
||||||
|
query.value(7).toBool(),
|
||||||
|
};
|
||||||
|
results.bookings[lodgingId].append(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}).then(this, [this](const Results &results) {
|
||||||
|
qsizetype itemsRow = 0;
|
||||||
|
qsizetype lodgingsRow = 0;
|
||||||
|
|
||||||
|
for (; itemsRow < m_items.count() && lodgingsRow < results.lodgings.count();
|
||||||
|
++itemsRow, ++lodgingsRow) {
|
||||||
|
Item *item = m_items.at(itemsRow);
|
||||||
|
const Lodging &lodging = results.lodgings.at(lodgingsRow);
|
||||||
|
|
||||||
|
if (lodging.id == item->id) {
|
||||||
|
if (lodging.label != item->name) {
|
||||||
|
item->name = lodging.label;
|
||||||
|
QModelIndex itemIndex = index(itemsRow);
|
||||||
|
emit dataChanged(itemIndex, itemIndex, {Qt::DisplayRole, NameRole});
|
||||||
|
};
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (QModelIndex itemIndex = findIndexById(lodging.id); itemIndex.isValid()) {
|
||||||
|
beginMoveRows({}, itemIndex.row(), itemIndex.row(), {}, itemsRow);
|
||||||
|
m_items.move(itemIndex.row(), itemsRow);
|
||||||
|
endMoveRows();
|
||||||
|
// Move one step backwards, and check change of label in next loop.
|
||||||
|
--itemsRow;
|
||||||
|
--lodgingsRow;
|
||||||
|
} else {
|
||||||
|
beginInsertRows({}, itemsRow, itemsRow);
|
||||||
|
m_items.insert(itemsRow, new Item(lodging.id, lodging.label, this));
|
||||||
|
endInsertRows();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (itemsRow < m_items.count()) {
|
||||||
|
beginRemoveRows({}, itemsRow, m_items.count() - 1);
|
||||||
|
m_items.remove(itemsRow, m_items.count() - itemsRow);
|
||||||
|
endRemoveRows();
|
||||||
|
}
|
||||||
|
if (lodgingsRow < results.lodgings.count()) {
|
||||||
|
beginInsertRows({},
|
||||||
|
m_items.count(),
|
||||||
|
m_items.count() + results.lodgings.count() - lodgingsRow - 1);
|
||||||
|
for (; lodgingsRow < results.lodgings.count(); ++lodgingsRow) {
|
||||||
|
const Lodging &lodging = results.lodgings.at(lodgingsRow);
|
||||||
|
m_items.append(new Item(lodging.id, lodging.label, this));
|
||||||
|
}
|
||||||
|
endInsertRows();
|
||||||
|
}
|
||||||
|
for (Item *item : m_items) {
|
||||||
|
item->timeline->update(results.bookings.value(item->id));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant TimelineListModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
if (!checkIndex(index,
|
||||||
|
QAbstractItemModel::CheckIndexOption::IndexIsValid
|
||||||
|
| QAbstractItemModel::CheckIndexOption::ParentIsInvalid)) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Item *item = m_items.at(index.row());
|
||||||
|
switch (role) {
|
||||||
|
case Qt::DisplayRole:
|
||||||
|
case NameRole:
|
||||||
|
return item->name;
|
||||||
|
case TimelineRole:
|
||||||
|
return QVariant::fromValue(item->timeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "moc_timelinelistmodel.cpp"
|
|
@ -0,0 +1,43 @@
|
||||||
|
#ifndef TIMELINELISTMODEL_H
|
||||||
|
#define TIMELINELISTMODEL_H
|
||||||
|
|
||||||
|
#include <QAbstractListModel>
|
||||||
|
#include <QList>
|
||||||
|
#include <QtQmlIntegration>
|
||||||
|
|
||||||
|
class TimelineListModel : public QAbstractListModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
QML_ELEMENT
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum Roles {
|
||||||
|
NameRole = Qt::UserRole,
|
||||||
|
TimelineRole,
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit TimelineListModel(QObject *parent = nullptr);
|
||||||
|
~TimelineListModel() 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:
|
||||||
|
Q_DISABLE_COPY_MOVE(TimelineListModel)
|
||||||
|
|
||||||
|
struct Item;
|
||||||
|
|
||||||
|
QModelIndex findIndexById(int id);
|
||||||
|
void fetch();
|
||||||
|
|
||||||
|
QList<Item *> m_items;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TIMELINELISTMODEL_H
|
|
@ -0,0 +1,77 @@
|
||||||
|
#include "timelinemodel.h"
|
||||||
|
|
||||||
|
TimelineModel::TimelineModel(QObject *parent)
|
||||||
|
: QObject{parent}
|
||||||
|
, m_items()
|
||||||
|
{}
|
||||||
|
|
||||||
|
TimelineModel::~TimelineModel()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimelineModel::update(const QList<Item *> &items)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
m_items.assign(items.begin(), items.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<qsizetype, qsizetype> TimelineModel::indexesOf(QDate from, QDate to) const
|
||||||
|
{
|
||||||
|
qsizetype begin = searchIndex(from);
|
||||||
|
if (begin == -1) {
|
||||||
|
return std::make_pair(begin, begin);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (begin > 0) {
|
||||||
|
--begin;
|
||||||
|
const Item *item = m_items.at(begin);
|
||||||
|
if (m_items.at(begin)->departure() < from) {
|
||||||
|
++begin;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (qsizetype end = begin + 1; end < m_items.count(); end++) {
|
||||||
|
if (m_items.at(end)->arrival >= to) {
|
||||||
|
return std::make_pair(begin, end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return std::make_pair(begin, m_items.count());
|
||||||
|
}
|
||||||
|
|
||||||
|
const TimelineModel::Item *TimelineModel::at(qsizetype index) const
|
||||||
|
{
|
||||||
|
return m_items.at(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimelineModel::clear()
|
||||||
|
{
|
||||||
|
qDeleteAll(m_items);
|
||||||
|
m_items.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
qsizetype TimelineModel::searchIndex(QDate date) const
|
||||||
|
{
|
||||||
|
if (m_items.isEmpty()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_items.last()->arrival < date) {
|
||||||
|
return m_items.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
qsizetype begin = 0;
|
||||||
|
qsizetype end = m_items.size() - 1;
|
||||||
|
qsizetype middle;
|
||||||
|
for (middle = end / 2; begin <= end; middle = (begin + end) / 2) {
|
||||||
|
if (m_items.at(middle)->arrival < date) {
|
||||||
|
begin = middle + 1;
|
||||||
|
} else {
|
||||||
|
end = middle - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return middle + (m_items.at(middle)->arrival < date ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "moc_timelinemodel.cpp"
|
|
@ -0,0 +1,48 @@
|
||||||
|
#ifndef TIMELINEMODEL_H
|
||||||
|
#define TIMELINEMODEL_H
|
||||||
|
|
||||||
|
#include <QDate>
|
||||||
|
#include <QList>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QtQmlIntegration>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
class TimelineModel : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
QML_ELEMENT
|
||||||
|
QML_UNCREATABLE("")
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct Item
|
||||||
|
{
|
||||||
|
int id;
|
||||||
|
QDate arrival;
|
||||||
|
int nights;
|
||||||
|
QString holder;
|
||||||
|
QString status;
|
||||||
|
bool hasBegin;
|
||||||
|
bool hasEnd;
|
||||||
|
QDate departure() const { return arrival.addDays(nights); }
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit TimelineModel(QObject *parent = nullptr);
|
||||||
|
~TimelineModel() override;
|
||||||
|
|
||||||
|
void update(const QList<Item *> &items);
|
||||||
|
|
||||||
|
std::pair<qsizetype, qsizetype> indexesOf(QDate from, QDate to) const;
|
||||||
|
const Item *at(qsizetype index) const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
private:
|
||||||
|
Q_DISABLE_COPY_MOVE(TimelineModel)
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
qsizetype searchIndex(QDate date) const;
|
||||||
|
|
||||||
|
QList<Item *> m_items;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TIMELINEMODEL_H
|
|
@ -31,10 +31,11 @@ TimelineView::TimelineView(QQuickItem *parent)
|
||||||
: QQuickItem(parent)
|
: QQuickItem(parent)
|
||||||
, m_dayWidth(24.0)
|
, m_dayWidth(24.0)
|
||||||
, m_delegate(nullptr)
|
, m_delegate(nullptr)
|
||||||
|
, m_toDate()
|
||||||
|
, m_model(nullptr)
|
||||||
, m_fromDate()
|
, m_fromDate()
|
||||||
, m_items()
|
, m_items()
|
||||||
, m_reusableItems()
|
, m_reusableItems()
|
||||||
, m_toDate()
|
|
||||||
, m_viewportX(0)
|
, m_viewportX(0)
|
||||||
, m_prevViewportX(0)
|
, m_prevViewportX(0)
|
||||||
, m_viewportWidth(0)
|
, m_viewportWidth(0)
|
||||||
|
@ -114,6 +115,22 @@ void TimelineView::setToDate(QDate date)
|
||||||
populate();
|
populate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TimelineModel *TimelineView::model() const
|
||||||
|
{
|
||||||
|
return m_model;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimelineView::setModel(TimelineModel *model)
|
||||||
|
{
|
||||||
|
if (model == m_model) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_model = model;
|
||||||
|
emit modelChanged(m_model);
|
||||||
|
clear();
|
||||||
|
populate();
|
||||||
|
}
|
||||||
|
|
||||||
qreal TimelineView::viewportX() const
|
qreal TimelineView::viewportX() const
|
||||||
{
|
{
|
||||||
return m_viewportX;
|
return m_viewportX;
|
||||||
|
@ -195,7 +212,7 @@ void TimelineView::clear()
|
||||||
|
|
||||||
void TimelineView::populate()
|
void TimelineView::populate()
|
||||||
{
|
{
|
||||||
if (!isComponentComplete() || !m_delegate) {
|
if (!isComponentComplete() || !m_delegate || !m_model) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (m_viewportX > m_prevViewportX) {
|
if (m_viewportX > m_prevViewportX) {
|
||||||
|
@ -209,13 +226,16 @@ void TimelineView::populate()
|
||||||
}
|
}
|
||||||
} else if (m_viewportX < m_prevViewportX) {
|
} else if (m_viewportX < m_prevViewportX) {
|
||||||
// Insert from the left
|
// Insert from the left
|
||||||
for (qint64 day = m_items.isEmpty() ? qCeil(m_prevViewportX / m_dayWidth) - 1
|
auto [begin, end] = m_model->indexesOf(m_fromDate.addDays(qFloor(m_viewportX / m_dayWidth)),
|
||||||
: m_items.first()->day - 1,
|
m_fromDate.addDays(
|
||||||
len = 1,
|
qCeil(m_prevViewportX / m_dayWidth)));
|
||||||
lastDay = qMax(-1, qFloor((m_viewportX - (len * m_dayWidth)) / m_dayWidth));
|
for (qsizetype i = end - 1; i >= begin; --i) {
|
||||||
day > lastDay;
|
const TimelineModel::Item *item = m_model->at(i);
|
||||||
day -= len) {
|
qint64 day = m_fromDate.daysTo(item->arrival);
|
||||||
TimelineView::Item *viewItem = createItem(day, len);
|
if (!m_items.isEmpty() && m_items.first()->day <= day) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
TimelineView::Item *viewItem = createItem(day, item->nights);
|
||||||
if (!viewItem) {
|
if (!viewItem) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -235,13 +255,15 @@ void TimelineView::populate()
|
||||||
}
|
}
|
||||||
} else if (currentRight > prevRight) {
|
} else if (currentRight > prevRight) {
|
||||||
// Insert from the right
|
// Insert from the right
|
||||||
for (qint64 day = m_items.isEmpty() ? qCeil(prevRight / m_dayWidth) - 1
|
auto [begin, end] = m_model->indexesOf(m_fromDate.addDays(qFloor(prevRight / m_dayWidth)),
|
||||||
: m_items.last()->day + 1,
|
m_fromDate.addDays(qCeil(currentRight / m_dayWidth)));
|
||||||
len = 1,
|
for (qsizetype i = begin; i < end; ++i) {
|
||||||
lastDay = qFloor((currentRight + (len * m_dayWidth)) / m_dayWidth);
|
const TimelineModel::Item *item = m_model->at(i);
|
||||||
day < lastDay;
|
qint64 day = m_fromDate.daysTo(item->arrival);
|
||||||
day += len) {
|
if (!m_items.isEmpty() && m_items.last()->day >= day) {
|
||||||
TimelineView::Item *viewItem = createItem(day, len);
|
continue;
|
||||||
|
}
|
||||||
|
TimelineView::Item *viewItem = createItem(day, item->nights);
|
||||||
if (!viewItem) {
|
if (!viewItem) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QQmlComponent>
|
#include <QQmlComponent>
|
||||||
#include <QQuickItem>
|
#include <QQuickItem>
|
||||||
|
#include "timelinemodel.h"
|
||||||
|
|
||||||
class TimelineView : public QQuickItem
|
class TimelineView : public QQuickItem
|
||||||
{
|
{
|
||||||
|
@ -13,6 +14,7 @@ class TimelineView : public QQuickItem
|
||||||
Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
|
Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
|
||||||
Q_PROPERTY(QDate fromDate READ fromDate WRITE setFromDate NOTIFY fromDateChanged)
|
Q_PROPERTY(QDate fromDate READ fromDate WRITE setFromDate NOTIFY fromDateChanged)
|
||||||
Q_PROPERTY(QDate toDate READ toDate WRITE setToDate NOTIFY toDateChanged)
|
Q_PROPERTY(QDate toDate READ toDate WRITE setToDate NOTIFY toDateChanged)
|
||||||
|
Q_PROPERTY(TimelineModel *model READ model WRITE setModel NOTIFY modelChanged)
|
||||||
Q_PROPERTY(qreal viewportX READ viewportX WRITE setViewportX NOTIFY viewportXChanged)
|
Q_PROPERTY(qreal viewportX READ viewportX WRITE setViewportX NOTIFY viewportXChanged)
|
||||||
Q_PROPERTY(
|
Q_PROPERTY(
|
||||||
qreal viewportWidth READ viewportWidth WRITE setViewportWidth NOTIFY viewportWidthChanged)
|
qreal viewportWidth READ viewportWidth WRITE setViewportWidth NOTIFY viewportWidthChanged)
|
||||||
|
@ -33,6 +35,9 @@ public:
|
||||||
QDate toDate() const;
|
QDate toDate() const;
|
||||||
void setToDate(QDate date);
|
void setToDate(QDate date);
|
||||||
|
|
||||||
|
TimelineModel *model() const;
|
||||||
|
void setModel(TimelineModel *model);
|
||||||
|
|
||||||
qreal viewportX() const;
|
qreal viewportX() const;
|
||||||
void setViewportX(qreal x);
|
void setViewportX(qreal x);
|
||||||
|
|
||||||
|
@ -44,6 +49,7 @@ signals:
|
||||||
void delegateChanged(QQmlComponent *delegate);
|
void delegateChanged(QQmlComponent *delegate);
|
||||||
void fromDateChanged(QDate date);
|
void fromDateChanged(QDate date);
|
||||||
void toDateChanged(QDate date);
|
void toDateChanged(QDate date);
|
||||||
|
void modelChanged(TimelineModel *model);
|
||||||
void viewportXChanged(qreal x);
|
void viewportXChanged(qreal x);
|
||||||
void viewportWidthChanged(qreal width);
|
void viewportWidthChanged(qreal width);
|
||||||
|
|
||||||
|
@ -66,9 +72,10 @@ private:
|
||||||
qreal m_dayWidth;
|
qreal m_dayWidth;
|
||||||
QQmlComponent *m_delegate;
|
QQmlComponent *m_delegate;
|
||||||
QDate m_fromDate;
|
QDate m_fromDate;
|
||||||
|
QDate m_toDate;
|
||||||
|
TimelineModel *m_model;
|
||||||
QList<Item *> m_items;
|
QList<Item *> m_items;
|
||||||
QList<QQuickItem *> m_reusableItems;
|
QList<QQuickItem *> m_reusableItems;
|
||||||
QDate m_toDate;
|
|
||||||
qreal m_viewportX;
|
qreal m_viewportX;
|
||||||
qreal m_prevViewportX;
|
qreal m_prevViewportX;
|
||||||
qreal m_viewportWidth;
|
qreal m_viewportWidth;
|
||||||
|
|
Loading…
Reference in New Issue