summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitch Curtis <mitch.curtis@digia.com>2014-01-14 16:53:59 +0100
committerMitch Curtis <mitch.curtis@digia.com>2014-01-17 10:43:33 +0100
commit22b25716e3e5b61ba79e615b7f956f972aa6ad00 (patch)
treeb6420372735ae17f9c21254a3d3abbda8885d54e
parentdfb401ea27b4bb5a9ab430cdeacb47256fc69451 (diff)
downloadqtquickcontrols-22b25716e3e5b61ba79e615b7f956f972aa6ad00.tar.gz
Convert QML CalendarModel to C++ QQuickCalendarModel.
This makes the model property private. The motivation behind this is: 1) We don't want to expose C++ classes in Qt Quick Controls. 2) Given 1), an alternative that allows users to use their own custom models for the Calendar involves: - Making the model property a var that accepts any type of model that provides a DateRole. - Having two functions in Calendar: indexAt(date) and dateAt(index), which any custom models have to implement if they use a different indexing system than QQuickCalendarModel's. - Forcing the user to populate their own dates. This shouldn't happen, as the code to do it is almost always going to be the same. It ends up being ugly. Instead, if users want to integrate things like events into their Calendar, they should store their own model for that separately; the styling code supports this. An example demonstrating this will be added later. Change-Id: I79ffb354ac26b42882f3352df4342d3fa1203832 Reviewed-by: Mitch Curtis <mitch.curtis@digia.com>
-rw-r--r--src/controls/Calendar.qml70
-rw-r--r--src/controls/CalendarHeaderModel.qml2
-rw-r--r--src/controls/CalendarModel.qml117
-rw-r--r--src/controls/Private/DateUtils.js78
-rw-r--r--src/controls/Private/private.pri2
-rw-r--r--src/controls/Private/qquickcalendarmodel.cpp242
-rw-r--r--src/controls/Private/qquickcalendarmodel_p.h91
-rw-r--r--src/controls/Private/qquickrangeddate_p.h9
-rw-r--r--src/controls/Styles/Base/CalendarStyle.qml3
-rw-r--r--src/controls/Styles/Desktop/CalendarStyle.qml3
-rw-r--r--src/controls/controls.pro1
-rw-r--r--src/controls/plugin.cpp3
-rw-r--r--tests/auto/controls/data/tst_calendar.qml22
13 files changed, 370 insertions, 273 deletions
diff --git a/src/controls/Calendar.qml b/src/controls/Calendar.qml
index 09d28f92..01169eca 100644
--- a/src/controls/Calendar.qml
+++ b/src/controls/Calendar.qml
@@ -43,8 +43,6 @@ import QtQuick.Controls 1.1
import QtQuick.Controls.Styles 1.1
import QtQuick.Controls.Private 1.0
-//import "Private/DateUtils.js" as DateUtils
-
/*!
\qmltype Calendar
\inqmlmodule QtQuick.Controls
@@ -55,9 +53,8 @@ import QtQuick.Controls.Private 1.0
Calendar allows selection of dates from a grid of days, similar to a typical
calendar. The selected date can be set through \l selectedDate, or with the
mouse and directional arrow keys. The current month displayed can be changed
- by clicking the previous and next month buttons, or pressing the left/right
- arrow keys when the selected date is the first or last visible date,
- respectively.
+ by clicking the previous and next month buttons, or by navigating with the
+ directional keys.
A minimum and maximum date can be set through \l minimumDate and
\l maximumDate. The earliest minimum date that can be set is 1 January, 1
@@ -67,7 +64,7 @@ import QtQuick.Controls.Private 1.0
is displayed according to \l locale, and it can be accessed through the
\l selectedDateText property.
- \sa CalendarModel, CalendarHeaderModel
+ \sa CalendarHeaderModel
*/
Control {
@@ -155,36 +152,20 @@ Control {
property var locale: Qt.locale()
/*!
- \qmlproperty enum Calendar::selectedDateFormat
- \qmlproperty string Calendar::selectedDateFormat
-
- The format to display \l selectedDateText in.
-
- This can be either one of the following enums, or a string:
-
- \list
- \li Locale.ShortFormat
- \li Locale.LongFormat
- \li Locale.NarrowFormat
- \endlist
-
- See QLocale::toString()/QLocale::toDateTime() for the full list of
- formatting options.
-
- The default value is \c "MMMM yyyy".
- */
- property var selectedDateFormat: "MMMM yyyy"
-
- /*!
The selected date converted to a string using \l locale.
*/
- readonly property string selectedDateText: selectedDate.toLocaleDateString(locale, selectedDateFormat)
+ property string selectedDateText: locale.standaloneMonthName(selectedDate.getMonth())
+ + selectedDate.toLocaleDateString(locale, " yyyy")
/*!
- This property holds the CalendarModel that will be used by the Calendar
- to populate the dates available to the user.
+ \internal
+
+ This property holds the model that will be used by the Calendar to
+ populate the dates available to the user.
*/
- property CalendarModel model: CalendarModel { locale: calendar.locale }
+ property CalendarModel __model: CalendarModel {
+ locale: calendar.locale
+ }
/*!
\qmlsignal Calendar::doubleClicked(date selectedDate)
@@ -249,19 +230,18 @@ Control {
// TODO: fix the reason behind + 1 stopping the flickableness..
// might have something to do with the header
height: cellHeight * (__style.weeksToShow + 1)
- model: calendar.model
+ model: calendar.__model
+
boundsBehavior: Flickable.StopAtBounds
KeyNavigation.tab: __panel.navigationBarItem
- property var previousDate
-
Keys.onLeftPressed: {
if (currentIndex != 0) {
// Be lazy and let the view determine which index we're moving
// to, then we can calculate the date from that.
moveCurrentIndexLeft();
// This will cause the index to be set again (to the same value).
- calendar.selectedDate = model.get(currentIndex).date;
+ calendar.selectedDate = model.dateAt(currentIndex);
} else {
// We're at the left edge of the calendar on the first row;
// this day is the first of the week and the month, so
@@ -276,17 +256,17 @@ Control {
Keys.onUpPressed: {
moveCurrentIndexUp();
- calendar.selectedDate = model.get(currentIndex).date;
+ calendar.selectedDate = model.dateAt(currentIndex);
}
Keys.onDownPressed: {
moveCurrentIndexDown();
- calendar.selectedDate = model.get(currentIndex).date;
+ calendar.selectedDate = model.dateAt(currentIndex);
}
Keys.onRightPressed: {
moveCurrentIndexRight();
- calendar.selectedDate = model.get(currentIndex).date;
+ calendar.selectedDate = model.dateAt(currentIndex);
}
Keys.onEscapePressed: {
@@ -294,7 +274,6 @@ Control {
}
Component.onCompleted: {
- repopulate();
dateChanged();
if (visible) {
@@ -309,20 +288,11 @@ Control {
function dateChanged() {
if (model !== undefined && model.locale !== undefined) {
- if (previousDate === undefined ||
- previousDate !== undefined &&
- previousDate.getMonth() != calendar.selectedDate.getMonth()) {
- repopulate();
- }
- previousDate = new Date(calendar.selectedDate);
- currentIndex = model.indexFromDate(calendar.selectedDate);
+ __model.selectedDate = calendar.selectedDate;
+ currentIndex = __model.indexAt(calendar.selectedDate);
}
}
- function repopulate() {
- model.populateFromDate(calendar.selectedDate);
- }
-
delegate: Loader {
sourceComponent: __style.dateDelegate
diff --git a/src/controls/CalendarHeaderModel.qml b/src/controls/CalendarHeaderModel.qml
index db8ae53d..9f204cc7 100644
--- a/src/controls/CalendarHeaderModel.qml
+++ b/src/controls/CalendarHeaderModel.qml
@@ -64,7 +64,7 @@ import QtQuick 2.0
\li \c Locale.Saturday
\endlist
- \sa Calendar, CalendarModel
+ \sa Calendar
*/
ListModel {
diff --git a/src/controls/CalendarModel.qml b/src/controls/CalendarModel.qml
deleted file mode 100644
index a7fca579..00000000
--- a/src/controls/CalendarModel.qml
+++ /dev/null
@@ -1,117 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the Qt Quick Controls module 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 Digia Plc and its Subsidiary(-ies) 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.0
-import QtQuick.Controls.Private 1.0
-
-/*!
- \qmltype CalendarModel
- \inqmlmodule QtQuick.Controls
- \since QtQuick.Controls 1.1
- \ingroup controls
- \brief A model that represents days in and surrounding a certain month
-
- The CalendarModel model provides a list of the days in and surrounding the
- month in which a given date lies.
-
- The only role provided by the model is \a date, a JavaScript \l Date object.
-
- \sa Calendar, CalendarHeaderModel
- */
-
-ListModel {
- id: root
-
- /*!
- The month that the calendar is currently displaying -
- regardless of whether the selected date is in the previous or
- next month.
-
- The month is zero-based, as it refers to the calendar's
- \l {Calendar::selectedDate}{selectedDate}, which is a JavaScript
- \l Date object.
- */
- property int month: 0
-
- /*!
- The first date that is visible on the calendar.
- */
- property date firstVisibleDate
- /*!
- The last date that is visible on the calendar.
- */
- property date lastVisibleDate
-
- /*!
- The locale that this model should be based on.
- This affects, for example, the first day of the week, and consequently
- the order in which dates are populated in the model.
- */
- property var locale: Qt.locale()
-
- /*!
- Populates the calendar with days from the month in \a date.
- */
- function populateFromDate(date) {
- month = date.getMonth();
-
- DateUtils.populateDatesOnACalendarMonth(root, date);
-
- firstVisibleDate = root.get(0).date;
- lastVisibleDate = root.get(root.count - 1).date;
- }
-
- /*!
- Returns the index of \a date into the view, or \c -1 if \a date is
- outside the range of visible dates.
- */
- function indexFromDate(date) {
- if (count == 0 || date.getTime() < firstVisibleDate.getTime()
- || date.getTime() > lastVisibleDate.getTime()) {
- return -1;
- }
-
- // The index of the selected date will be the days from the
- // previous month that we had to display before it, plus the
- // day of the selected date itself.
- var daysDifference = (date.getTime() - firstVisibleDate.getTime()) / DateUtils.msPerDay;
- return Math.abs(daysDifference);
- }
-}
diff --git a/src/controls/Private/DateUtils.js b/src/controls/Private/DateUtils.js
index d482cea6..6e1b2385 100644
--- a/src/controls/Private/DateUtils.js
+++ b/src/controls/Private/DateUtils.js
@@ -46,13 +46,6 @@ var daysInAWeek = 7;
// shown on a typical calendar.
var weeksOnACalendarMonth = 6;
-/*!
- The amount of days to populate the calendar with.
-*/
-var daysOnACalendarMonth = daysInAWeek * weeksOnACalendarMonth
-
-var msPerDay = 86400000;
-
// Can't create year 1 directly...
var minimumCalendarDate = new Date(-1, 0, 1);
minimumCalendarDate.setFullYear(minimumCalendarDate.getFullYear() + 2);
@@ -64,77 +57,6 @@ function daysInMonth(date) {
return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
}
-function dayNameFromDayOfWeek(locale, dayOfWeekFormat, dayOfWeek) {
- return locale.dayName(dayOfWeek, dayOfWeekFormat);
-}
-
-/*!
- Clears \a model, then populates it with dates (role: "date")
- that you'd see on a calendar for the given \a date.
-
- \a model - A ListModel. Should have the following property:
- locale - A JavaScript Locale object.
- \a date - The date that the calendar month is based on (only the year
- and month are relevant)
-*/
-function populateDatesOnACalendarMonth(model, date) {
- if (model.count < daysOnACalendarMonth) {
- var dummyDate = new Date(1970, 0, 1, 0, 0, 0, 0);
- while (model.count < daysOnACalendarMonth) {
- // We only want to fill the model once, to avoid having to actually
- // repopulate it. Instead, we just set properties.
- model.append({ date: dummyDate });
- }
- }
-
- // Ideally we'd display the 1st of the month as the first
- // day in the calendar, but typically it's not the first day of
- // the week, so we need to display some days before it.
-
- // The actual first (1st) day of the month.
- // Avoid issue where years like "1" can't be created using (years, months, days)
- // constructor by just using the milliseconds constructor.
- var firstDayOfMonthDate = new Date(date);
- firstDayOfMonthDate.setDate(1);
- // The first day to display, if not the 1st of the month, will be
- // before the first day of the month.
- var difference = Math.abs(firstDayOfMonthDate.getDay() - model.locale.firstDayOfWeek);
- // The first day before the 1st that is equal to this locale's firstDayOfWeek.
- var firstDateToDisplay = new Date(firstDayOfMonthDate);
-
- if (difference != 0) {
- firstDateToDisplay.setDate(firstDateToDisplay.getDate() - difference);
-
- for (var i = 1; i <= difference; ++i) {
- var earlierDate = new Date(firstDayOfMonthDate);
- earlierDate.setDate(earlierDate.getDate() - i);
-
- // Reverse through it since we're iterating back through time.
- model.set(difference - i, { date: earlierDate });
- }
- }
- // Else, the first day of the month is also the first day of the week;
- // it can be the first day in the calendar.
-
- i = difference;
- for (var d = firstDayOfMonthDate.getDate(); d <= daysInMonth(date); ++d, ++i) {
- var tmpDate = new Date(date);
- tmpDate.setDate(d);
- model.set(i, { date: tmpDate });
- }
-
- // Fill up the calendar with days from the next month.
- var firstDayOfNextMonth = new Date(firstDayOfMonthDate);
- firstDayOfNextMonth.setMonth(firstDayOfNextMonth.getMonth() + 1);
- var daysToFill = daysOnACalendarMonth - i;
- for (var offset = 0; offset < daysToFill; ++offset) {
- var nextMonthDate = new Date(firstDayOfNextMonth);
- nextMonthDate.setDate(nextMonthDate.getDate() + offset);
-
- model.set(i + offset, { date: nextMonthDate });
- }
-}
-
/*!
Returns a copy of \a date with its month set to \a month, keeping the same
day if possible. Does not modify \a date.
diff --git a/src/controls/Private/private.pri b/src/controls/Private/private.pri
index c717febf..ffbb4f75 100644
--- a/src/controls/Private/private.pri
+++ b/src/controls/Private/private.pri
@@ -1,4 +1,5 @@
HEADERS += \
+ $$PWD/qquickcalendarmodel_p.h \
$$PWD/qquicktooltip_p.h \
$$PWD/qquickspinboxvalidator_p.h \
$$PWD/qquickrangemodel_p.h \
@@ -11,6 +12,7 @@ HEADERS += \
$$PWD/qquickcontrolsprivate_p.h
SOURCES += \
+ $$PWD/qquickcalendarmodel.cpp \
$$PWD/qquicktooltip.cpp \
$$PWD/qquickspinboxvalidator.cpp \
$$PWD/qquickrangemodel.cpp \
diff --git a/src/controls/Private/qquickcalendarmodel.cpp b/src/controls/Private/qquickcalendarmodel.cpp
new file mode 100644
index 00000000..afaca713
--- /dev/null
+++ b/src/controls/Private/qquickcalendarmodel.cpp
@@ -0,0 +1,242 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Quick Controls module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickcalendarmodel_p.h"
+
+namespace {
+ static const int daysInAWeek = 7;
+
+ /*
+ Not the number of weeks per month, but the number of weeks that are
+ shown on a typical calendar.
+ */
+ static const int weeksOnACalendarMonth = 6;
+
+ /*
+ The amount of days to populate the calendar with.
+ */
+ static const int daysOnACalendarMonth = daysInAWeek * weeksOnACalendarMonth;
+}
+
+/*!
+ QQuickCalendarModel provides a model for the Calendar control.
+ It is responsible for populating itself with dates based on the
+ date that is selected in the Calendar's grid.
+
+ The model stores a list of dates whose indices map directly to the Calendar.
+ For example, the model would store the following dates when any day in
+ January 2015 is selected on the Calendar:
+
+ [30/12/2014][31/12/2014][01/01/2015]...[31/01/2015][01/02/2015]...[09/02/2015]
+
+ The Calendar would then display the dates in the same order within a grid:
+
+ January 2015
+
+ [30][31][01][02][03][04][05]
+ [06][07][08][09][10][11][12]
+ [13][14][15][16][17][18][19]
+ [20][21][22][23][24][25][26]
+ [27][28][29][30][31][01][02]
+ [03][04][05][06][07][08][09]
+*/
+
+QQuickCalendarModel::QQuickCalendarModel(QObject *parent) :
+ QAbstractListModel(parent)
+{
+}
+
+/*!
+ The date that determines which dates are stored.
+
+ We store all of the days in the month of selectedDate, as well as any days
+ in the previous or following month if there is enough space.
+*/
+QDate QQuickCalendarModel::selectedDate() const
+{
+ return mSelectedDate;
+}
+
+/*!
+ Sets the selected date to \a selectedDate.
+
+ If \a selectedDate is a valid date and is different than the previously
+ selected date, the selected date is changed and
+ populateFromSelectedDate() called.
+*/
+void QQuickCalendarModel::setSelectedDate(const QDate &date)
+{
+ if (date != mSelectedDate && date.isValid()) {
+ const QDate previousDate = mSelectedDate;
+ mSelectedDate = date;
+ populateFromSelectedDate(previousDate);
+ emit selectedDateChanged(date);
+ }
+}
+
+/*!
+ The locale set on the Calendar.
+
+ This affects which dates are stored for selectedDate(). For example, if
+ the locale is en_US, the first day of the week is Sunday. Therefore, if
+ selectedDate() is some day in January 2014, there will be three days
+ displayed before the 1st of January:
+
+
+ January 2014
+
+ [SO][MO][TU][WE][TH][FR][SA]
+ [29][30][31][01][02][03][04]
+ ...
+
+ If the locale is then changed to en_GB (with the same selectedDate()),
+ there will be 2 days before the 1st of January, because Monday is the
+ first day of the week for that locale:
+
+ January 2014
+
+ [MO][TU][WE][TH][FR][SA][SO]
+ [30][31][01][02][03][04][05]
+ ...
+*/
+QLocale QQuickCalendarModel::locale() const
+{
+ return mLocale;
+}
+
+/*!
+ Sets the locale to \a locale.
+*/
+void QQuickCalendarModel::setLocale(const QLocale &locale)
+{
+ if (locale != mLocale) {
+ mLocale = locale;
+ emit localeChanged(mLocale);
+ }
+}
+
+QVariant QQuickCalendarModel::data(const QModelIndex &index, int role) const
+{
+ if (role == DateRole) {
+ return mVisibleDates.at(index.row());
+ }
+ return QVariant();
+}
+
+int QQuickCalendarModel::rowCount(const QModelIndex &) const
+{
+ return mVisibleDates.isEmpty() ? 0 : weeksOnACalendarMonth * daysInAWeek;
+}
+
+QHash<int, QByteArray> QQuickCalendarModel::roleNames() const
+{
+ QHash<int, QByteArray> names;
+ names[DateRole] = QByteArrayLiteral("date");
+ return names;
+}
+
+/*!
+ Returns the date at \a index, or an invalid date if \a index is invalid.
+*/
+QDate QQuickCalendarModel::dateAt(int index) const
+{
+ return index >= 0 && index < mVisibleDates.size() ? mVisibleDates.at(index) : QDate();
+}
+
+/*!
+ Returns the index for \a date, or -1 if \a date is outside of our range.
+*/
+int QQuickCalendarModel::indexAt(const QDate &date)
+{
+ if (mVisibleDates.size() == 0 || date < mFirstVisibleDate || date > mLastVisibleDate) {
+ return -1;
+ }
+
+ // The index of the selected date will be the days from the
+ // previous month that we had to display before it, plus the
+ // day of the selected date itself.
+ return qMax(qint64(0), mFirstVisibleDate.daysTo(date));
+}
+
+/*!
+ Called before selectedDateChanged() is emitted.
+
+ This function is called even when just the day has changed, in which case
+ it does nothing.
+*/
+void QQuickCalendarModel::populateFromSelectedDate(const QDate &previousDate)
+{
+ // We don't need to populate if the year and month haven't changed.
+ if (mSelectedDate.year() == previousDate.year() && mSelectedDate.month() == previousDate.month())
+ return;
+
+ // Since our model is of a fixed size, we fill it once and assign values each time
+ // the month changes, instead of clearing and appending each time.
+ bool isEmpty = mVisibleDates.isEmpty();
+ if (isEmpty) {
+ beginResetModel();
+ mVisibleDates.fill(QDate(), daysOnACalendarMonth);
+ }
+
+ // Ideally we'd display the 1st of the month as the first
+ // day in the calendar, but typically it's not the first day of
+ // the week, so we need to display some days before it.
+
+ // The actual first (1st) day of the month.
+ QDate firstDayOfMonthDate(mSelectedDate.year(), mSelectedDate.month(), 1);
+ // The first day to display, if not the 1st of the month, will be
+ // before the first day of the month.
+ int difference = ((firstDayOfMonthDate.dayOfWeek() - mLocale.firstDayOfWeek()) + 7) % 7;
+ // The first day before the 1st that is equal to this locale's firstDayOfWeek.
+ QDate firstDateToDisplay = firstDayOfMonthDate.addDays(-difference);
+ for (int i = 0; i < daysOnACalendarMonth; ++i) {
+ mVisibleDates[i] = firstDateToDisplay.addDays(i);
+ }
+
+ mFirstVisibleDate = mVisibleDates.at(0);
+ mLastVisibleDate = mVisibleDates.at(mVisibleDates.size() - 1);
+
+ if (!isEmpty) {
+ emit dataChanged(index(0, 0), index(rowCount() - 1, 0));
+ } else {
+ endResetModel();
+ }
+}
diff --git a/src/controls/Private/qquickcalendarmodel_p.h b/src/controls/Private/qquickcalendarmodel_p.h
new file mode 100644
index 00000000..67239972
--- /dev/null
+++ b/src/controls/Private/qquickcalendarmodel_p.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Quick Controls module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKCALENDARMODEL_H
+#define QQUICKCALENDARMODEL_H
+
+#include <QObject>
+#include <QAbstractListModel>
+#include <QLocale>
+#include <QVariant>
+#include <QDate>
+
+class QQuickCalendarModel : public QAbstractListModel
+{
+ Q_OBJECT
+ Q_PROPERTY(QDate selectedDate READ selectedDate WRITE setSelectedDate NOTIFY selectedDateChanged)
+ Q_PROPERTY(QLocale locale READ locale WRITE setLocale NOTIFY localeChanged)
+public:
+ explicit QQuickCalendarModel(QObject *parent = 0);
+
+ enum {
+ // If this class is made public, this will have to be changed.
+ DateRole = Qt::UserRole + 1
+ };
+
+ QDate selectedDate() const;
+ void setSelectedDate(const QDate &selectedDate);
+
+ QLocale locale() const;
+ void setLocale(const QLocale &locale);
+
+ QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE;
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
+
+ QHash<int, QByteArray> roleNames() const Q_DECL_OVERRIDE;
+
+ Q_INVOKABLE QDate dateAt(int index) const;
+ Q_INVOKABLE int indexAt(const QDate &selectedDate);
+signals:
+ void selectedDateChanged(const QDate &selectedDate);
+ void localeChanged(const QLocale &locale);
+protected:
+ void populateFromSelectedDate(const QDate &previousDate);
+
+ QDate mSelectedDate;
+ QDate mFirstVisibleDate;
+ QDate mLastVisibleDate;
+ QVector<QDate> mVisibleDates;
+ QLocale mLocale;
+};
+
+#endif // QQUICKCALENDARMODEL_H
diff --git a/src/controls/Private/qquickrangeddate_p.h b/src/controls/Private/qquickrangeddate_p.h
index 53771539..f19ff16d 100644
--- a/src/controls/Private/qquickrangeddate_p.h
+++ b/src/controls/Private/qquickrangeddate_p.h
@@ -51,12 +51,9 @@ QT_BEGIN_NAMESPACE
class QQuickRangedDate : public QObject
{
Q_OBJECT
- Q_PROPERTY(QDate date READ date \
- WRITE setDate NOTIFY dateChanged RESET resetDate)
- Q_PROPERTY(QDate minimumDate READ minimumDate \
- WRITE setMinimumDate NOTIFY minimumDateChanged RESET resetMinimumDate)
- Q_PROPERTY(QDate maximumDate READ maximumDate \
- WRITE setMaximumDate NOTIFY maximumDateChanged RESET resetMaximumDate)
+ Q_PROPERTY(QDate date READ date WRITE setDate NOTIFY dateChanged RESET resetDate)
+ Q_PROPERTY(QDate minimumDate READ minimumDate WRITE setMinimumDate NOTIFY minimumDateChanged RESET resetMinimumDate)
+ Q_PROPERTY(QDate maximumDate READ maximumDate WRITE setMaximumDate NOTIFY maximumDateChanged RESET resetMaximumDate)
public:
QQuickRangedDate();
~QQuickRangedDate() {}
diff --git a/src/controls/Styles/Base/CalendarStyle.qml b/src/controls/Styles/Base/CalendarStyle.qml
index dae6c6ca..1710e71b 100644
--- a/src/controls/Styles/Base/CalendarStyle.qml
+++ b/src/controls/Styles/Base/CalendarStyle.qml
@@ -248,8 +248,7 @@ Style {
color: "white"
anchors.fill: parent
Text {
- text: DateUtils.dayNameFromDayOfWeek(control.locale,
- control.dayOfWeekFormat, dayOfWeek)
+ text: control.locale.dayName(dayOfWeek, control.dayOfWeekFormat)
anchors.centerIn: parent
}
}
diff --git a/src/controls/Styles/Desktop/CalendarStyle.qml b/src/controls/Styles/Desktop/CalendarStyle.qml
index 38ccfa73..85629d0e 100644
--- a/src/controls/Styles/Desktop/CalendarStyle.qml
+++ b/src/controls/Styles/Desktop/CalendarStyle.qml
@@ -135,8 +135,7 @@ Style {
color: __syspal.base
anchors.fill: parent
Text {
- text: DateUtils.dayNameFromDayOfWeek(control.locale,
- control.dayOfWeekFormat, dayOfWeek)
+ text: control.locale.dayName(dayOfWeek, control.dayOfWeekFormat)
anchors.centerIn: parent
}
}
diff --git a/src/controls/controls.pro b/src/controls/controls.pro
index f772c321..211b60f9 100644
--- a/src/controls/controls.pro
+++ b/src/controls/controls.pro
@@ -11,7 +11,6 @@ CONTROLS_QML_FILES = \
Button.qml \
BusyIndicator.qml \
Calendar.qml \
- CalendarModel.qml \
CalendarHeaderModel.qml \
CheckBox.qml \
ComboBox.qml \
diff --git a/src/controls/plugin.cpp b/src/controls/plugin.cpp
index 2ca21220..8f542c61 100644
--- a/src/controls/plugin.cpp
+++ b/src/controls/plugin.cpp
@@ -49,6 +49,7 @@
#include "qquickdesktopiconprovider_p.h"
#include "qquickselectionmode_p.h"
+#include "Private/qquickcalendarmodel_p.h"
#include "Private/qquickrangeddate_p.h"
#include "Private/qquickrangemodel_p.h"
#include "Private/qquickwheelarea_p.h"
@@ -72,7 +73,6 @@ static const struct {
{ "ApplicationWindow", 1, 0 },
{ "Button", 1, 0 },
{ "Calendar", 1, 1 },
- { "CalendarModel", 1, 1 },
{ "CalendarHeaderModel", 1, 1 },
{ "CheckBox", 1, 0 },
{ "ComboBox", 1, 0 },
@@ -131,6 +131,7 @@ void QtQuickControlsPlugin::initializeEngine(QQmlEngine *engine, const char *uri
// Register private API
const char *private_uri = "QtQuick.Controls.Private";
qmlRegisterType<QQuickAbstractStyle>(private_uri, 1, 0, "AbstractStyle");
+ qmlRegisterType<QQuickCalendarModel>(private_uri, 1, 0, "CalendarModel");
qmlRegisterType<QQuickPadding>();
qmlRegisterType<QQuickRangedDate>(private_uri, 1, 0, "RangedDate");
qmlRegisterType<QQuickRangeModel>(private_uri, 1, 0, "RangeModel");
diff --git a/tests/auto/controls/data/tst_calendar.qml b/tests/auto/controls/data/tst_calendar.qml
index 6fab0038..55d92e55 100644
--- a/tests/auto/controls/data/tst_calendar.qml
+++ b/tests/auto/controls/data/tst_calendar.qml
@@ -97,7 +97,8 @@ Item {
compare(calendar.dayOfWeekFormat, Locale.ShortFormat);
compare(calendar.locale, Qt.locale());
compare(calendar.selectedDateText,
- calendar.selectedDate.toLocaleDateString(calendar.locale, calendar.selectedDateFormat));
+ calendar.locale.standaloneMonthName(calendar.selectedDate.getMonth())
+ + calendar.selectedDate.toLocaleDateString(calendar.locale, " yyyy"));
}
function test_setAfterConstructed() {
@@ -114,7 +115,8 @@ Item {
compare(calendar.navigationBarVisible, false);
compare(calendar.locale, Qt.locale("de_DE"));
compare(calendar.selectedDateText,
- calendar.selectedDate.toLocaleDateString(calendar.locale, calendar.selectedDateFormat))
+ calendar.locale.standaloneMonthName(calendar.selectedDate.getMonth())
+ + calendar.selectedDate.toLocaleDateString(calendar.locale, " yyyy"));
}
function test_selectedDate() {
@@ -170,22 +172,12 @@ Item {
var locales = [Qt.locale().name, "en_AU", "en_GB", "en_US", "de_DE", "nb_NO",
"pl_PL", "zh_CN", "fr_FR", "it_IT", "pt_BR", "ru_RU", "es_ES"];
- var stringFormats = ["dd-MM-yyyy", "yyyy", "MM", "dd"];
- var enumFormats = [Locale.ShortFormat, Locale.NarrowFormat, Locale.LongFormat];
for (var i = 0; i < locales.length; ++i) {
calendar.locale = Qt.locale(locales[i]);
- for (var formatIndex = 0; formatIndex < stringFormats.length; ++formatIndex) {
- calendar.selectedDateFormat = stringFormats[formatIndex];
- compare(calendar.selectedDateText,
- calendar.selectedDate.toLocaleDateString(calendar.locale, calendar.selectedDateFormat));
- }
-
- for (formatIndex = 0; formatIndex < enumFormats.length; ++formatIndex) {
- calendar.selectedDateFormat = enumFormats[formatIndex];
- compare(calendar.selectedDateText,
- calendar.selectedDate.toLocaleDateString(calendar.locale, calendar.selectedDateFormat));
- }
+ compare(calendar.selectedDateText,
+ calendar.locale.standaloneMonthName(calendar.selectedDate.getMonth())
+ + calendar.selectedDate.toLocaleDateString(calendar.locale, " yyyy"));
}
}