diff options
Diffstat (limited to 'examples/labs/calendar')
-rw-r--r-- | examples/labs/calendar/DateTimePicker.qml | 176 | ||||
-rw-r--r-- | examples/labs/calendar/EventView.qml | 209 | ||||
-rw-r--r-- | examples/labs/calendar/TumblerDelegate.qml | 55 | ||||
-rw-r--r-- | examples/labs/calendar/calendar.pro | 19 | ||||
-rw-r--r-- | examples/labs/calendar/calendar.qrc | 8 | ||||
-rw-r--r-- | examples/labs/calendar/main.cpp | 233 | ||||
-rw-r--r-- | examples/labs/calendar/main.qml | 221 |
7 files changed, 921 insertions, 0 deletions
diff --git a/examples/labs/calendar/DateTimePicker.qml b/examples/labs/calendar/DateTimePicker.qml new file mode 100644 index 00000000..96da4175 --- /dev/null +++ b/examples/labs/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 Qt.labs.calendar 1.0 +import QtQuick.Controls 2.0 +import QtQuick.Templates 2.0 as T + +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 * (T.Tumbler.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 * (T.Tumbler.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 * (T.Tumbler.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 * (T.Tumbler.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 * (T.Tumbler.tumbler.activeFocus ? 2 : 1.25) + } + } + + Tumbler { + id: amPmTumbler + model: ["AM", "PM"] + delegate: TumblerDelegate { + font.pixelSize: fontMetrics.font.pixelSize * (T.Tumbler.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/labs/calendar/EventView.qml b/examples/labs/calendar/EventView.qml new file mode 100644 index 00000000..3991e5eb --- /dev/null +++ b/examples/labs/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/labs/calendar/TumblerDelegate.qml b/examples/labs/calendar/TumblerDelegate.qml new file mode 100644 index 00000000..e9c7a143 --- /dev/null +++ b/examples/labs/calendar/TumblerDelegate.qml @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** 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 +import QtQuick.Templates 2.0 as T + +Text { + text: isNaN(modelData) ? modelData : modelData + 1 + color: "#666666" + opacity: 0.4 + Math.max(0, 1 - Math.abs(T.Tumbler.displacement)) * 0.6 + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + Behavior on font.pixelSize { + NumberAnimation {} + } +} diff --git a/examples/labs/calendar/calendar.pro b/examples/labs/calendar/calendar.pro new file mode 100644 index 00000000..105e7fc9 --- /dev/null +++ b/examples/labs/calendar/calendar.pro @@ -0,0 +1,19 @@ +TEMPLATE = app +TARGET = calendar +QT += quick sql + +SOURCES += \ + main.cpp + +OTHER_FILES += \ + main.qml + +RESOURCES += \ + calendar.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/quickcalendar2/calendar +INSTALLS += target + +DISTFILES += \ + DateTimePicker.qml \ + EventView.qml diff --git a/examples/labs/calendar/calendar.qrc b/examples/labs/calendar/calendar.qrc new file mode 100644 index 00000000..d0f67b26 --- /dev/null +++ b/examples/labs/calendar/calendar.qrc @@ -0,0 +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/labs/calendar/main.cpp b/examples/labs/calendar/main.cpp new file mode 100644 index 00000000..651a51ec --- /dev/null +++ b/examples/labs/calendar/main.cpp @@ -0,0 +1,233 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include <QtGui> +#include <QtQml> +#include <QtSql> + +class Event : public QObject +{ + Q_OBJECT + 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 &description, QObject *parent = 0) : + QObject(parent), + description(description) + { + + } + + QString description; + QDateTime start; + QDateTime end; + +signals: + void descriptionChanged(); + void startChanged(); + void endChanged(); +}; + +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) : + 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 + { + QSqlQuery query(QStringLiteral("SELECT MIN(start) FROM Event")); + if (query.next()) + return QDateTime::fromMSecsSinceEpoch(query.value(0).toLongLong()).date(); + return QDate(); + } + + QDate max() const + { + QSqlQuery query(QStringLiteral("SELECT MAX(end) FROM Event")); + if (query.next()) + return QDateTime::fromMSecsSinceEpoch(query.value(0).toLongLong()).date(); + return QDate(); + } + + QDate date() const + { + return mDate; + } + + void setDate(const QDate &date) + { + 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(); + } + } + + enum { + DescriptionRole = Qt::UserRole, + StartDateRole, + EndDateRole + }; + + QHash<int,QByteArray> roleNames() const Q_DECL_OVERRIDE + { + QHash<int,QByteArray> names; + names[DescriptionRole] = "description"; + names[StartDateRole] = "start"; + names[EndDateRole] = "end"; + return names; + } + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE + { + if (role < Qt::UserRole) + return QSqlTableModel::data(index, role); + + 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[]) +{ + QGuiApplication app(argc, argv); + createDatabase(); + qmlRegisterType<SqlEventModel>("io.qt.examples.calendar", 1, 0, "SqlEventModel"); + QQmlApplicationEngine engine; + engine.load(QUrl("qrc:/main.qml")); + if (engine.rootObjects().isEmpty()) + return -1; + return app.exec(); +} + +#include "main.moc" diff --git a/examples/labs/calendar/main.qml b/examples/labs/calendar/main.qml new file mode 100644 index 00000000..ca23b166 --- /dev/null +++ b/examples/labs/calendar/main.qml @@ -0,0 +1,221 @@ +/**************************************************************************** +** +** 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 +import Qt.labs.calendar 1.0 +import QtQuick.Templates 2.0 as T +import QtQuick.Layouts 1.0 +import io.qt.examples.calendar 1.0 + +ApplicationWindow { + id: window + width: 640 + height: 400 + minimumWidth: 400 + minimumHeight: 300 + color: "#f4f4f4" + visible: true + title: "Qt Labs Calendar - Example" + + SqlEventModel { + id: eventModel + date: calendar.selectedDate + } + + StackView { + id: stackView + anchors.fill: parent + anchors.margins: 20 + + initialItem: flow + } + + Flow { + id: flow + spacing: 10 + layoutDirection: Qt.RightToLeft + + ListView { + id: calendar + property date selectedDate: new Date() + + clip: true + width: (parent.width > parent.height ? (parent.width - parent.spacing) * 0.6 : parent.width) + height: (parent.height > parent.width ? (parent.height - parent.spacing) * 0.6 : parent.height) + + model: CalendarModel { + id: model + from: eventModel.min + to: eventModel.max + } + + focus: true + currentIndex: model.indexOf(selectedDate.getFullYear(), selectedDate.getMonth() + 1) + snapMode: ListView.SnapOneItem + highlightMoveDuration: 250 + highlightRangeMode: ListView.StrictlyEnforceRange + orientation: parent.width > parent.height ? ListView.Vertical : ListView.Horizontal + + delegate: CalendarView { + id: delegate + + width: calendar.width + height: calendar.height + + month: model.month + year: model.year + + topPadding: title.height + Column { + id: title + x: delegate.contentItem.x + width: delegate.contentItem.width + spacing: 6 + Text { + width: parent.width + height: implicitHeight * 2 + text: delegate.title + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + font.pointSize: 18 + } + DayOfWeekRow { + width: parent.width + } + } + + leftPadding: weekNumbers.width + WeekNumberColumn { + id: weekNumbers + month: model.month + year: model.year + y: delegate.contentItem.y + height: delegate.contentItem.height + } + + onClicked: calendar.selectedDate = date + + delegate: Text { + text: model.day + opacity: model.month === delegate.month ? 1 : 0 + color: model.today ? Theme.accentColor : Theme.textColor + minimumPointSize: 8 + fontSizeMode: Text.Fit + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + Rectangle { + z: -1 + anchors.centerIn: parent + width: Math.min(parent.width * 0.6, parent.width * 0.6) + height: width + radius: width / 2 + opacity: 0.5 + color: pressed ? Theme.pressColor : "transparent"; + + SqlEventModel { + id: delegateEventModel + } + + border.color: delegateEventModel.rowCount > 0 ? Theme.accentColor : "transparent" + } + } + } + Rectangle { + z: -1 + parent: calendar + anchors.fill: parent + border.color: Theme.frameColor + } + } + + 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 + + onAddEventClicked: stackView.push(createEventComponent) + } + } + + Component { + id: createEventComponent + + ColumnLayout { + spacing: 10 + visible: T.StackView.index === stackView.currentIndex + + DateTimePicker { + id: dateTimePicker + anchors.horizontalCenter: parent.horizontalCenter + dateToShow: calendar.selectedDate + } + Frame { + Layout.fillWidth: true + + TextArea { + id: descriptionField + placeholder.text: "Description" + anchors.fill: parent + } + } + RowLayout { + Layout.fillWidth: true + + 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(); + } + } + } + } + } +} |