aboutsummaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
authorMitch Curtis <mitch.curtis@theqtcompany.com>2015-07-16 12:00:55 +0200
committerMitch Curtis <mitch.curtis@theqtcompany.com>2015-08-06 11:43:48 +0000
commit293fc5e8f7df1b60a07d2e7e489e57059bb021bc (patch)
tree7ea3921797c2541c379cc91eb1f0c4f30d575fbc /examples
parent1448ee0d1c02280aa33424f992b2f26d74615a43 (diff)
Add support for ListView to Tumbler.
This enables creation of non-wrapping Tumblers. Change-Id: I0e21b860b84c456c0651923e87217cafc42c69b7 Reviewed-by: Mitch Curtis <mitch.curtis@theqtcompany.com>
Diffstat (limited to 'examples')
-rw-r--r--examples/quick/calendar/DateTimePicker.qml176
-rw-r--r--examples/quick/calendar/EventView.qml209
-rw-r--r--examples/quick/calendar/TumblerDelegate.qml54
-rw-r--r--examples/quick/calendar/calendar.pro4
-rw-r--r--examples/quick/calendar/calendar.qrc3
-rw-r--r--examples/quick/calendar/main.cpp178
-rw-r--r--examples/quick/calendar/main.qml139
7 files changed, 632 insertions, 131 deletions
diff --git a/examples/quick/calendar/DateTimePicker.qml b/examples/quick/calendar/DateTimePicker.qml
new file mode 100644
index 00000000..88238048
--- /dev/null
+++ b/examples/quick/calendar/DateTimePicker.qml
@@ -0,0 +1,176 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.6
+import QtQuick.Calendar 2.0
+import QtQuick.Controls 2.0
+import QtQuick.Extras 2.0
+
+Item {
+ id: dateTimePicker
+ enabled: dateToShow.getFullYear() >= fromYear || dateToShow.getFullYear() <= toYear
+ implicitWidth: row.implicitWidth
+ implicitHeight: row.implicitHeight
+
+ readonly property var days: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
+
+ readonly property int fromYear: 2000
+ readonly property int toYear: 2020
+
+ readonly property alias chosenDate: dateTimePicker.__date
+ property var __date: new Date(
+ fromYear + yearTumbler.currentIndex,
+ monthTumbler.currentIndex,
+ dayTumbler.currentIndex + 1,
+ hoursTumbler.currentIndex + (amPmTumbler.currentIndex == 0 ? 0 : 12),
+ minutesTumbler.currentIndex);
+
+ property date dateToShow: new Date()
+ onDateToShowChanged: {
+ yearTumbler.currentIndex = dateToShow.getFullYear() - fromYear;
+ monthTumbler.currentIndex = dateToShow.getMonth();
+ dayTumbler.currentIndex = dateToShow.getDate() - 1;
+ }
+
+ FontMetrics {
+ id: fontMetrics
+ }
+
+ Row {
+ id: row
+ spacing: 2
+
+ Frame {
+ padding: 0
+
+ Row {
+ Tumbler {
+ id: dayTumbler
+
+ delegate: TumblerDelegate {
+ text: modelData
+ font.pixelSize: fontMetrics.font.pixelSize * (AbstractTumbler.tumbler.activeFocus ? 2 : 1.25)
+ }
+
+ function updateModel() {
+ var previousIndex = dayTumbler.currentIndex;
+ var array = [];
+ var newDays = dateTimePicker.days[monthTumbler.currentIndex];
+ for (var i = 0; i < newDays; ++i) {
+ array.push(i + 1);
+ }
+ dayTumbler.model = array;
+ dayTumbler.currentIndex = Math.min(newDays - 1, previousIndex);
+ }
+
+ Component.onCompleted: updateModel()
+ }
+ Tumbler {
+ id: monthTumbler
+ model: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
+ delegate: TumblerDelegate {
+ text: modelData
+ font.pixelSize: fontMetrics.font.pixelSize * (AbstractTumbler.tumbler.activeFocus ? 2 : 1.25)
+ }
+ onCurrentIndexChanged: dayTumbler.updateModel()
+ }
+ Tumbler {
+ id: yearTumbler
+ width: 80
+ model: {
+ var years = [];
+ for (var i = fromYear; i <= toYear; ++i) {
+ years.push(i);
+ }
+ return years;
+ }
+ delegate: TumblerDelegate {
+ text: modelData
+ font.pixelSize: fontMetrics.font.pixelSize * (AbstractTumbler.tumbler.activeFocus ? 2 : 1.25)
+ }
+ }
+ }
+ }
+
+ Frame {
+ padding: 0
+
+ Row {
+ Tumbler {
+ id: hoursTumbler
+ model: 12
+ delegate: TumblerDelegate {
+ text: modelData.toString().length < 2 ? "0" + modelData : modelData
+ font.pixelSize: fontMetrics.font.pixelSize * (AbstractTumbler.tumbler.activeFocus ? 2 : 1.25)
+ }
+ }
+
+ Tumbler {
+ id: minutesTumbler
+ model: 60
+ delegate: TumblerDelegate {
+ text: modelData.toString().length < 2 ? "0" + modelData : modelData
+ font.pixelSize: fontMetrics.font.pixelSize * (AbstractTumbler.tumbler.activeFocus ? 2 : 1.25)
+ }
+ }
+
+ Tumbler {
+ id: amPmTumbler
+ model: ["AM", "PM"]
+ delegate: TumblerDelegate {
+ font.pixelSize: fontMetrics.font.pixelSize * (AbstractTumbler.tumbler.activeFocus ? 2 : 1.25)
+ }
+
+ contentItem: ListView {
+ anchors.fill: parent
+ model: amPmTumbler.model
+ delegate: amPmTumbler.delegate
+
+ snapMode: ListView.SnapToItem
+ highlightRangeMode: ListView.StrictlyEnforceRange
+ preferredHighlightBegin: height / 2 - (height / 3 / 2)
+ preferredHighlightEnd: height / 2 + (height / 3 / 2)
+ clip: true
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/examples/quick/calendar/EventView.qml b/examples/quick/calendar/EventView.qml
new file mode 100644
index 00000000..3991e5eb
--- /dev/null
+++ b/examples/quick/calendar/EventView.qml
@@ -0,0 +1,209 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.6
+import QtQuick.Controls 2.0
+
+Rectangle {
+ border.color: Theme.frameColor
+
+ property date selectedDate
+ property var locale
+ property var eventModel
+
+ signal addEventClicked
+
+ Component {
+ id: eventListHeader
+
+ Row {
+ id: eventDateRow
+ width: parent.width
+ height: eventDayLabel.height
+ spacing: 10
+
+ Label {
+ id: eventDayLabel
+ text: selectedDate.getDate()
+ font.pointSize: 35
+ }
+
+ Column {
+ height: eventDayLabel.height
+
+ Label {
+ readonly property var options: { weekday: "long" }
+ text: Qt.locale().standaloneDayName(selectedDate.getDay(), Locale.LongFormat)
+ font.pointSize: 18
+ }
+ Label {
+ text: Qt.locale().standaloneMonthName(selectedDate.getMonth())
+ + selectedDate.toLocaleDateString(Qt.locale(), " yyyy")
+ font.pointSize: 12
+ }
+ }
+ }
+ }
+
+ ListView {
+ id: eventsListView
+ spacing: 4
+ clip: true
+ header: eventListHeader
+ anchors.fill: parent
+ anchors.margins: 10
+ model: eventModel
+
+ delegate: Rectangle {
+ width: eventsListView.width
+ height: eventItemColumn.height
+ anchors.horizontalCenter: parent.horizontalCenter
+
+ Rectangle {
+ width: parent.width
+ height: 1
+ color: "#eee"
+ }
+
+ Column {
+ id: eventItemColumn
+ x: 4
+ y: 4
+ width: parent.width - 8
+ height: timeRow.height + descriptionLabel.height + 8
+
+ Label {
+ id: descriptionLabel
+ width: parent.width
+ wrapMode: Text.Wrap
+ text: description
+ }
+ Row {
+ id: timeRow
+ width: parent.width
+ Label {
+ text: start.toLocaleTimeString(locale, Locale.ShortFormat)
+ color: "#aaa"
+ }
+ Label {
+ text: "-" + end.toLocaleTimeString(locale, Locale.ShortFormat)
+ visible: start.getTime() !== end.getTime() && start.getDate() === end.getDate()
+ color: "#aaa"
+ }
+ }
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onPressAndHold: removeButton.opacity = 1
+ onClicked: removeButton.opacity = 0
+ }
+
+ Button {
+ id: removeButton
+ opacity: 0
+
+ Behavior on opacity {
+ NumberAnimation {
+ duration: 150
+ }
+ }
+
+ anchors.right: parent.right
+ anchors.rightMargin: 12
+ anchors.verticalCenter: parent.verticalCenter
+
+ onClicked: eventModel.removeEvent(index)
+
+ background: Rectangle {
+ implicitWidth: 32
+ implicitHeight: 32
+
+ radius: width / 2
+ color: Qt.tint(!addButton.enabled ? addButton.Theme.disabledColor :
+ addButton.activeFocus ? addButton.Theme.focusColor : "red",
+ addButton.pressed ? addButton.Theme.pressColor : "transparent")
+ }
+ }
+
+ // Don't want the white icon to change opacity.
+ Rectangle {
+ anchors.centerIn: removeButton
+ width: 18
+ height: 4
+ radius: 1
+ }
+ }
+ }
+
+ Button {
+ id: addButton
+
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ anchors.margins: 12
+
+ onClicked: addEventClicked()
+
+ background: Rectangle {
+ implicitWidth: 32
+ implicitHeight: 32
+
+ radius: width / 2
+ color: Qt.tint(!addButton.enabled ? addButton.Theme.disabledColor :
+ addButton.activeFocus ? addButton.Theme.focusColor : addButton.Theme.accentColor,
+ addButton.pressed ? addButton.Theme.pressColor : "transparent")
+ }
+
+ Rectangle {
+ anchors.centerIn: parent
+ width: 4
+ height: 18
+ radius: 1
+ }
+
+ Rectangle {
+ anchors.centerIn: parent
+ width: 18
+ height: 4
+ radius: 1
+ }
+ }
+}
diff --git a/examples/quick/calendar/TumblerDelegate.qml b/examples/quick/calendar/TumblerDelegate.qml
new file mode 100644
index 00000000..60d71f21
--- /dev/null
+++ b/examples/quick/calendar/TumblerDelegate.qml
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.6
+import QtQuick.Extras 2.0
+
+Text {
+ text: isNaN(modelData) ? modelData : modelData + 1
+ color: "#666666"
+ opacity: 0.4 + Math.max(0, 1 - Math.abs(AbstractTumbler.displacement)) * 0.6
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+
+ Behavior on font.pixelSize {
+ NumberAnimation {}
+ }
+}
diff --git a/examples/quick/calendar/calendar.pro b/examples/quick/calendar/calendar.pro
index f81d9e5a..105e7fc9 100644
--- a/examples/quick/calendar/calendar.pro
+++ b/examples/quick/calendar/calendar.pro
@@ -13,3 +13,7 @@ RESOURCES += \
target.path = $$[QT_INSTALL_EXAMPLES]/quickcalendar2/calendar
INSTALLS += target
+
+DISTFILES += \
+ DateTimePicker.qml \
+ EventView.qml
diff --git a/examples/quick/calendar/calendar.qrc b/examples/quick/calendar/calendar.qrc
index 5f6483ac..d0f67b26 100644
--- a/examples/quick/calendar/calendar.qrc
+++ b/examples/quick/calendar/calendar.qrc
@@ -1,5 +1,8 @@
<RCC>
<qresource prefix="/">
<file>main.qml</file>
+ <file>DateTimePicker.qml</file>
+ <file>TumblerDelegate.qml</file>
+ <file>EventView.qml</file>
</qresource>
</RCC>
diff --git a/examples/quick/calendar/main.cpp b/examples/quick/calendar/main.cpp
index ae41bdf0..1d739add 100644
--- a/examples/quick/calendar/main.cpp
+++ b/examples/quick/calendar/main.cpp
@@ -45,31 +45,84 @@
class Event : public QObject
{
Q_OBJECT
- Q_PROPERTY(QString name MEMBER name NOTIFY nameChanged)
+ Q_PROPERTY(QString description MEMBER description NOTIFY descriptionChanged)
Q_PROPERTY(QDateTime start MEMBER start NOTIFY startChanged)
Q_PROPERTY(QDateTime end MEMBER end NOTIFY endChanged)
public:
- explicit Event(const QString &name, QObject *parent = 0) : QObject(parent), name(name) { }
+ explicit Event(const QString &description, QObject *parent = 0) :
+ QObject(parent),
+ description(description)
+ {
+
+ }
- QString name;
+ QString description;
QDateTime start;
QDateTime end;
signals:
- void nameChanged();
+ void descriptionChanged();
void startChanged();
void endChanged();
};
-class SqlEventModel : public QSqlQueryModel
+static void addEvent(const QString &description, const QDateTime &start, qint64 duration = 0)
+{
+ QSqlQuery query;
+ QDateTime end = start.addSecs(duration);
+ if (!query.exec(QStringLiteral("INSERT INTO Event (description, start, end) VALUES ('%1', %2, %3)")
+ .arg(description).arg(start.toMSecsSinceEpoch()).arg(end.toMSecsSinceEpoch()))) {
+ qWarning() << query.lastError();
+ }
+}
+
+// create an in-memory SQLITE database
+static void createDatabase()
+{
+ QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
+ db.setDatabaseName(":memory:");
+ if (!db.open()) {
+ qFatal("Cannot open database");
+ return;
+ }
+
+ QSqlQuery query;
+ query.exec("CREATE TABLE IF NOT EXISTS Event (description TEXT, start BIGINT, end BIGINT)");
+
+ const QDate current = QDate::currentDate();
+ addEvent("Job interview", QDateTime(current.addDays(-19), QTime(12, 0)));
+ addEvent("Grocery shopping", QDateTime(current.addDays(-14), QTime(18, 0)));
+ addEvent("Ice skating", QDateTime(current.addDays(-14), QTime(20, 0)), 5400);
+ addEvent("Dentist''s appointment", QDateTime(current.addDays(-8), QTime(14, 0)), 1800);
+ addEvent("Cross-country skiing", QDateTime(current.addDays(1), QTime(19, 30)), 3600);
+ addEvent("Conference", QDateTime(current.addDays(10), QTime(9, 0)), 432000);
+ addEvent("Hairdresser", QDateTime(current.addDays(19), QTime(13, 0)));
+ addEvent("Doctor''s appointment", QDateTime(current.addDays(21), QTime(16, 0)));
+ addEvent("Vacation", QDateTime(current.addDays(35), QTime(0, 0)), 604800);
+}
+
+class SqlEventModel : public QSqlTableModel
{
Q_OBJECT
Q_PROPERTY(QDate min READ min CONSTANT)
Q_PROPERTY(QDate max READ max CONSTANT)
+ Q_PROPERTY(QDate date READ date WRITE setDate NOTIFY dateChanged FINAL)
+ Q_PROPERTY(int rowCount READ rowCount NOTIFY rowCountChanged)
public:
- SqlEventModel(QObject *parent = 0) : QSqlQueryModel(parent) { }
+ SqlEventModel(QObject *parent = 0) :
+ QSqlTableModel(parent, QSqlDatabase::database(":memory:"))
+ {
+ connect(this, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SIGNAL(rowCountChanged()));
+ connect(this, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SIGNAL(rowCountChanged()));
+
+ setTable("Event");
+ setEditStrategy(QSqlTableModel::OnManualSubmit);
+ select();
+
+ setDate(QDate::currentDate());
+ }
QDate min() const
{
@@ -87,58 +140,83 @@ public:
return QDate();
}
- Q_INVOKABLE QList<QObject*> eventsForDate(const QDate &date)
+ QDate date() const
+ {
+ return mDate;
+ }
+
+ void setDate(const QDate &date)
{
- qint64 from = QDateTime(date, QTime(0, 0)).toMSecsSinceEpoch();
- qint64 to = QDateTime(date, QTime(23, 59)).toMSecsSinceEpoch();
-
- QSqlQuery query;
- if (!query.exec(QStringLiteral("SELECT * FROM Event WHERE start <= %1 AND end >= %2").arg(to).arg(from)))
- qFatal("Query failed");
-
- QList<QObject*> events;
- while (query.next()) {
- Event *event = new Event(query.value("name").toString(), this);
- event->start = QDateTime::fromMSecsSinceEpoch(query.value("start").toLongLong());
- event->end = QDateTime::fromMSecsSinceEpoch(query.value("end").toLongLong());
- events.append(event);
+ if (date != mDate) {
+ mDate = date;
+
+ qint64 from = QDateTime(mDate, QTime(0, 0)).toMSecsSinceEpoch();
+ qint64 to = QDateTime(mDate, QTime(23, 59)).toMSecsSinceEpoch();
+
+ setFilter(QStringLiteral("start <= %1 AND end >= %2").arg(to).arg(from));
+
+ emit dateChanged();
}
- return events;
}
-};
-// create an in-memory SQLITE database
-static bool addEvent(QSqlQuery* query, const QString &name, const QDateTime &start, qint64 duration = 0)
-{
- QDateTime end = start.addSecs(duration);
- return query->exec(QStringLiteral("insert into Event values('%1', %2, %3)").arg(name)
- .arg(start.toMSecsSinceEpoch())
- .arg(end.toMSecsSinceEpoch()));
-}
+ enum {
+ DescriptionRole = Qt::UserRole,
+ StartDateRole,
+ EndDateRole
+ };
-static void createDatabase()
-{
- QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
- db.setDatabaseName(":memory:");
- if (!db.open()) {
- qFatal("Cannot open database");
- return;
+ QHash<int,QByteArray> roleNames() const Q_DECL_OVERRIDE
+ {
+ QHash<int,QByteArray> names;
+ names[DescriptionRole] = "description";
+ names[StartDateRole] = "start";
+ names[EndDateRole] = "end";
+ return names;
}
- QSqlQuery query;
- query.exec("create table if not exists Event (name TEXT, start BIGINT, end BIGINT)");
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE
+ {
+ if (role < Qt::UserRole)
+ return QSqlTableModel::data(index, role);
- const QDate current = QDate::currentDate();
- addEvent(&query, "Job interview", QDateTime(current.addDays(-19), QTime(12, 0)));
- addEvent(&query, "Grocery shopping", QDateTime(current.addDays(-14), QTime(18, 0)));
- addEvent(&query, "Ice skating", QDateTime(current.addDays(-14), QTime(20, 0)), 5400);
- addEvent(&query, "Dentist's appointment", QDateTime(current.addDays(-8), QTime(14, 0)), 1800);
- addEvent(&query, "Cross-country skiing", QDateTime(current.addDays(1), QTime(19, 30)), 3600);
- addEvent(&query, "Conference", QDateTime(current.addDays(10), QTime(9, 0)), 432000);
- addEvent(&query, "Hairdresser", QDateTime(current.addDays(19), QTime(13, 0)));
- addEvent(&query, "Doctor's appointment", QDateTime(current.addDays(21), QTime(16, 0)));
- addEvent(&query, "Vacation", QDateTime(current.addDays(35), QTime(0, 0)), 604800);
-}
+ int columnIndex = role - DescriptionRole;
+ QModelIndex modelIndex = this->index(index.row(), columnIndex);
+ QVariant eventData = QSqlTableModel::data(modelIndex, Qt::DisplayRole);
+ if (role == DescriptionRole)
+ return eventData;
+
+ return QDateTime::fromMSecsSinceEpoch(eventData.toLongLong());
+ }
+
+ Q_INVOKABLE void addEvent(const QString &description, const QDateTime &date)
+ {
+ const int row = rowCount();
+ insertRows(row, 1);
+ setData(index(row, 0), description);
+ setData(index(row, 1), date.toMSecsSinceEpoch());
+ setData(index(row, 2), date.toMSecsSinceEpoch());
+ submitAll();
+ }
+
+ Q_INVOKABLE void removeEvent(int modelRow)
+ {
+ if (modelRow < 0 || modelRow >= rowCount()) {
+ qWarning() << "Invalid model row:" << modelRow;
+ return;
+ }
+
+ removeRows(modelRow, 1);
+ submitAll();
+ }
+
+signals:
+ void dateChanged();
+ void rowCountChanged();
+
+private:
+ // The date to show events for.
+ QDate mDate;
+};
int main(int argc, char *argv[])
{
diff --git a/examples/quick/calendar/main.qml b/examples/quick/calendar/main.qml
index db7c2561..3b36272f 100644
--- a/examples/quick/calendar/main.qml
+++ b/examples/quick/calendar/main.qml
@@ -41,6 +41,7 @@
import QtQuick 2.6
import QtQuick.Controls 2.0
import QtQuick.Calendar 2.0
+import QtQuick.Layouts 1.0
import io.qt.examples.calendar 1.0
ApplicationWindow {
@@ -55,12 +56,19 @@ ApplicationWindow {
SqlEventModel {
id: eventModel
+ date: calendar.selectedDate
}
- Flow {
- id: row
+ StackView {
+ id: stackView
anchors.fill: parent
anchors.margins: 20
+
+ initialItem: flow
+ }
+
+ Flow {
+ id: flow
spacing: 10
layoutDirection: Qt.RightToLeft
@@ -79,7 +87,7 @@ ApplicationWindow {
}
focus: true
- currentIndex: -1
+ currentIndex: model.indexOf(selectedDate.getFullYear(), selectedDate.getMonth() + 1)
snapMode: ListView.SnapOneItem
highlightMoveDuration: 250
highlightRangeMode: ListView.StrictlyEnforceRange
@@ -139,8 +147,13 @@ ApplicationWindow {
height: width
radius: width / 2
opacity: 0.5
- color: pressed ? Theme.pressColor : "transparent"
- border.color: eventModel.eventsForDate(model.date).length > 0 ? Theme.accentColor : "transparent"
+ color: pressed ? Theme.pressColor : "transparent";
+
+ SqlEventModel {
+ id: delegateEventModel
+ }
+
+ border.color: delegateEventModel.rowCount > 0 ? Theme.accentColor : "transparent"
}
}
}
@@ -152,89 +165,53 @@ ApplicationWindow {
}
}
- Component {
- id: eventListHeader
-
- Row {
- id: eventDateRow
- width: parent.width
- height: eventDayLabel.height
- spacing: 10
-
- Label {
- id: eventDayLabel
- text: calendar.selectedDate.getDate()
- font.pointSize: 35
- }
-
- Column {
- height: eventDayLabel.height
+ EventView {
+ width: (parent.width > parent.height ? (parent.width - parent.spacing) * 0.4 : parent.width)
+ height: (parent.height > parent.width ? (parent.height - parent.spacing) * 0.4 : parent.height)
+ selectedDate: calendar.selectedDate
+ eventModel: eventModel
+ locale: calendar.locale
- Label {
- readonly property var options: { weekday: "long" }
- text: Qt.locale().standaloneDayName(calendar.selectedDate.getDay(), Locale.LongFormat)
- font.pointSize: 18
- }
- Label {
- text: Qt.locale().standaloneMonthName(calendar.selectedDate.getMonth())
- + calendar.selectedDate.toLocaleDateString(Qt.locale(), " yyyy")
- font.pointSize: 12
- }
- }
- }
+ onAddEventClicked: stackView.push(createEventComponent)
}
+ }
- Rectangle {
- width: (parent.width > parent.height ? (parent.width - parent.spacing) * 0.4 : parent.width)
- height: (parent.height > parent.width ? (parent.height - parent.spacing) * 0.4 : parent.height)
- border.color: Theme.frameColor
+ Component {
+ id: createEventComponent
- ListView {
- id: eventsListView
- spacing: 4
- clip: true
- header: eventListHeader
- anchors.fill: parent
- anchors.margins: 10
- model: eventModel.eventsForDate(calendar.selectedDate)
+ ColumnLayout {
+ spacing: 10
+ visible: AbstractStackView.index === stackView.currentIndex
- delegate: Rectangle {
- width: eventsListView.width
- height: eventItemColumn.height
- anchors.horizontalCenter: parent.horizontalCenter
+ DateTimePicker {
+ id: dateTimePicker
+ anchors.horizontalCenter: parent.horizontalCenter
+ dateToShow: calendar.selectedDate
+ }
+ Frame {
+ Layout.fillWidth: true
- Rectangle {
- width: parent.width
- height: 1
- color: "#eee"
- }
+ TextArea {
+ id: descriptionField
+ placeholder.text: "Description"
+ anchors.fill: parent
+ }
+ }
+ RowLayout {
+ Layout.fillWidth: true
- Column {
- id: eventItemColumn
- x: 4
- y: 4
- width: parent.width - 8
- height: timeRow.height + nameLabel.height + 8
-
- Label {
- id: nameLabel
- width: parent.width
- wrapMode: Text.Wrap
- text: modelData.name
- }
- Row {
- id: timeRow
- width: parent.width
- Label {
- text: modelData.start.toLocaleTimeString(calendar.locale, Locale.ShortFormat)
- color: "#aaa"
- }
- Label {
- text: "-" + new Date(modelData.end).toLocaleTimeString(calendar.locale, Locale.ShortFormat)
- visible: modelData.start.getTime() !== modelData.end.getTime() && modelData.start.getDate() === modelData.end.getDate()
- color: "#aaa"
- }
- }
+ Button {
+ text: "Cancel"
+ Layout.fillWidth: true
+ onClicked: stackView.pop()
+ }
+ Button {
+ text: "Create"
+ enabled: dateTimePicker.enabled
+ Layout.fillWidth: true
+ onClicked: {
+ eventModel.addEvent(descriptionField.text, dateTimePicker.chosenDate);
+ stackView.pop();
}
}
}