diff options
author | Mitch Curtis <mitch.curtis@digia.com> | 2014-02-03 12:17:03 +0100 |
---|---|---|
committer | Mitch Curtis <mitch.curtis@digia.com> | 2014-02-03 15:19:56 +0100 |
commit | 9e9c84a67c543a887289a02f00e32451d72b45bc (patch) | |
tree | 6425d139945800458b3bbdb8c835414c5724fd6e | |
parent | 562daca758d3fce16f262b2de00573d4843d8043 (diff) | |
download | qtquickcontrols-9e9c84a67c543a887289a02f00e32451d72b45bc.tar.gz |
Add week numbers.
Change-Id: Ib413019da88c24bebf6169b60b2088b1920f1ae4
Reviewed-by: Mitch Curtis <mitch.curtis@digia.com>
-rw-r--r-- | src/controls/Calendar.qml | 10 | ||||
-rw-r--r-- | src/controls/Private/qquickcalendarmodel.cpp | 15 | ||||
-rw-r--r-- | src/controls/Private/qquickcalendarmodel_p.h | 3 | ||||
-rw-r--r-- | src/controls/Styles/Base/CalendarStyle.qml | 254 |
4 files changed, 186 insertions, 96 deletions
diff --git a/src/controls/Calendar.qml b/src/controls/Calendar.qml index 5d6fc3e4..58272d4e 100644 --- a/src/controls/Calendar.qml +++ b/src/controls/Calendar.qml @@ -64,6 +64,9 @@ import QtQuick.Controls.Private 1.0 Localization is supported through the \l locale property. The selected date is displayed according to \l locale, and it can be accessed through the \l selectedDateText property. + + Week numbers can be displayed by setting the weekNumbersVisible property to + \c true. */ Control { @@ -129,6 +132,13 @@ Control { property bool gridVisible: true /*! + This property determines the visibility of week numbers. + + The default value is \c false. + */ + property bool weekNumbersVisible: false + + /*! \qmlproperty enum Calendar::dayOfWeekFormat The format in which the days of the week (in the header) are displayed. diff --git a/src/controls/Private/qquickcalendarmodel.cpp b/src/controls/Private/qquickcalendarmodel.cpp index afaca713..4c72b2a0 100644 --- a/src/controls/Private/qquickcalendarmodel.cpp +++ b/src/controls/Private/qquickcalendarmodel.cpp @@ -197,6 +197,20 @@ int QQuickCalendarModel::indexAt(const QDate &date) } /*! + Returns the week number for the first day of the week corresponding to \a row, + or -1 if \a row is outside of our range. +*/ +int QQuickCalendarModel::weekNumberAt(int row) const +{ + const int index = row * daysInAWeek; + const QDate date = dateAt(index); + if (date.isValid()) { + return date.weekNumber(); + } + return -1; +} + +/*! Called before selectedDateChanged() is emitted. This function is called even when just the day has changed, in which case @@ -238,5 +252,6 @@ void QQuickCalendarModel::populateFromSelectedDate(const QDate &previousDate) emit dataChanged(index(0, 0), index(rowCount() - 1, 0)); } else { endResetModel(); + emit countChanged(rowCount()); } } diff --git a/src/controls/Private/qquickcalendarmodel_p.h b/src/controls/Private/qquickcalendarmodel_p.h index 67239972..02f40a77 100644 --- a/src/controls/Private/qquickcalendarmodel_p.h +++ b/src/controls/Private/qquickcalendarmodel_p.h @@ -53,6 +53,7 @@ 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) + Q_PROPERTY(int count READ rowCount NOTIFY countChanged) public: explicit QQuickCalendarModel(QObject *parent = 0); @@ -75,9 +76,11 @@ public: Q_INVOKABLE QDate dateAt(int index) const; Q_INVOKABLE int indexAt(const QDate &selectedDate); + Q_INVOKABLE int weekNumberAt(int row) const; signals: void selectedDateChanged(const QDate &selectedDate); void localeChanged(const QLocale &locale); + void countChanged(int count); protected: void populateFromSelectedDate(const QDate &previousDate); diff --git a/src/controls/Styles/Base/CalendarStyle.qml b/src/controls/Styles/Base/CalendarStyle.qml index 527f72cf..220e5161 100644 --- a/src/controls/Styles/Base/CalendarStyle.qml +++ b/src/controls/Styles/Base/CalendarStyle.qml @@ -201,7 +201,6 @@ Style { Label { id: dayDelegateText text: styleData.date.getDate() - font.pixelSize: 14 anchors.centerIn: parent horizontalAlignment: Text.AlignRight color: { @@ -231,6 +230,17 @@ Style { } } + /*! + The delegate that styles each week number. + */ + property Component weekNumberDelegate: Rectangle { + color: "white" + Label { + text: styleData.weekNumber + anchors.centerIn: parent + } + } + /*! \internal */ property Component panel: Item { id: panel @@ -259,7 +269,7 @@ Style { spacing: (control.gridVisible ? __gridLineWidth : 0) anchors.top: navigationBarLoader.bottom anchors.left: parent.left - anchors.leftMargin: (control.gridVisible ? __gridLineWidth : 0) + anchors.leftMargin: (control.weekNumbersVisible ? weekNumbersItem.width : 0) + (control.gridVisible ? __gridLineWidth : 0) anchors.right: parent.right height: 40 @@ -284,122 +294,174 @@ Style { } } - // Contains the grid lines and the grid itself. - Item { - id: viewContainer - width: panel.width - height: panel.height - navigationBarLoader.height - weekdayHeaderRow.height + Row { + id: gridRow + width: weekNumbersItem.width + viewContainer.width + height: viewContainer.height anchors.top: weekdayHeaderRow.bottom - Repeater { - id: verticalGridLineRepeater - model: view.columns + 1 - delegate: Rectangle { - // The last line will be an invalid index, so we must handle it - x: index < view.columns - ? CalendarUtils.cellRectAt(index, view.columns, view.rows, view.availableWidth, view.availableHeight).x - : CalendarUtils.cellRectAt(view.columns - 1, view.columns, view.rows, view.availableWidth, view.availableHeight).x - + CalendarUtils.cellRectAt(view.columns - 1, view.columns, view.rows, view.availableWidth, view.availableHeight).width - y: 0 - width: __gridLineWidth - height: viewContainer.height - color: gridColor - visible: control.gridVisible - } - } + Item { + id: weekNumbersItem + visible: control.weekNumbersVisible + width: 30 + height: viewContainer.height + + Repeater { + id: weekNumberRepeater + model: view.weeksToShow + + Loader { + id: weekNumberDelegateLoader + y: CalendarUtils.cellRectAt(index * view.columns, view.columns, view.rows, view.availableWidth, view.availableHeight).y + + (calendar.gridVisible ? __gridLineWidth : 0) + width: weekNumbersItem.width + // TODO: It seems the column doesn't reposition the items + // after the height recovers from being negative +// height: view.cellRects[index * view.columns].height + height: CalendarUtils.cellRectAt(index * view.columns, view.columns, view.rows, view.availableWidth, view.availableHeight).height + - (calendar.gridVisible ? __gridLineWidth : 0) + sourceComponent: weekNumberDelegate + + readonly property int __index: index + property int __weekNumber: control.__model.weekNumberAt(index) + + // Must handle this ourselves since it's not a notifiable property, but an invokable function. + // This will be called every time the selected date changes, but not the first time the calendar is loaded. + Connections { + target: control + onSelectedDateChanged: __weekNumber = control.__model.weekNumberAt(index) + } - Repeater { - id: horizontalGridLineRepeater - model: view.rows + 1 - delegate: Rectangle { - x: 0 - // The last line will be an invalid index, so we must handle it - y: index < view.columns - 1 - ? CalendarUtils.cellRectAt(index * view.columns, view.columns, view.rows, view.availableWidth, view.availableHeight).y - : CalendarUtils.cellRectAt((view.rows - 1) * view.columns, view.columns, view.rows, view.availableWidth, view.availableHeight).y - + CalendarUtils.cellRectAt((view.rows - 1) * view.columns, view.columns, view.rows, view.availableWidth, view.availableHeight).height - width: viewContainer.width - height: __gridLineWidth - color: gridColor - visible: control.gridVisible - } - } + // This handles the first time the calendar is shown. + Connections { + target: control.__model + onCountChanged: __weekNumber = control.__model.weekNumberAt(index) + } - Connections { - target: control - onSelectedDateChanged: view.dateChanged() + property QtObject styleData: QtObject { + readonly property alias index: weekNumberDelegateLoader.__index + readonly property int weekNumber: weekNumberDelegateLoader.__weekNumber + } + } + } } - Repeater { - id: view + // Contains the grid lines and the grid itself. + Item { + id: viewContainer + width: panel.width - (control.weekNumbersVisible ? weekNumbersItem.width : 0) + height: panel.height - navigationBarLoader.height - weekdayHeaderRow.height + + Repeater { + id: verticalGridLineRepeater + model: view.columns + 1 + delegate: Rectangle { + // The last line will be an invalid index, so we must handle it + x: index < view.columns + ? CalendarUtils.cellRectAt(index, view.columns, view.rows, view.availableWidth, view.availableHeight).x + : CalendarUtils.cellRectAt(view.columns - 1, view.columns, view.rows, view.availableWidth, view.availableHeight).x + + CalendarUtils.cellRectAt(view.columns - 1, view.columns, view.rows, view.availableWidth, view.availableHeight).width + y: 0 + width: __gridLineWidth + height: viewContainer.height + color: gridColor + visible: control.gridVisible + } + } - property int currentIndex: -1 + Repeater { + id: horizontalGridLineRepeater + model: view.rows + 1 + delegate: Rectangle { + x: 0 + // The last line will be an invalid index, so we must handle it + y: index < view.columns - 1 + ? CalendarUtils.cellRectAt(index * view.columns, view.columns, view.rows, view.availableWidth, view.availableHeight).y + : CalendarUtils.cellRectAt((view.rows - 1) * view.columns, view.columns, view.rows, view.availableWidth, view.availableHeight).y + + CalendarUtils.cellRectAt((view.rows - 1) * view.columns, view.columns, view.rows, view.availableWidth, view.availableHeight).height + width: viewContainer.width + height: __gridLineWidth + color: gridColor + visible: control.gridVisible + } + } - readonly property int weeksToShow: 6 - readonly property int rows: weeksToShow - readonly property int columns: CalendarUtils.daysInAWeek + Connections { + target: control + onSelectedDateChanged: view.dateChanged() + } - model: control.__model + Repeater { + id: view - Component.onCompleted: dateChanged() + property int currentIndex: -1 - function dateChanged() { - if (model !== undefined && model.locale !== undefined) { - model.selectedDate = control.selectedDate; - currentIndex = model.indexAt(control.selectedDate); - } - } + readonly property int weeksToShow: 6 + readonly property int rows: weeksToShow + readonly property int columns: CalendarUtils.daysInAWeek - // The combined available width and height to be shared amongst each cell. - readonly property real availableWidth: (viewContainer.width - (control.gridVisible ? __gridLineWidth : 0)) - readonly property real availableHeight: (viewContainer.height - (control.gridVisible ? __gridLineWidth : 0)) + model: control.__model - delegate: Loader { - id: delegateLoader + Component.onCompleted: dateChanged() - x: CalendarUtils.cellRectAt(index, view.columns, view.rows, view.availableWidth, view.availableHeight).x - + (control.gridVisible ? __gridLineWidth : 0) - y: CalendarUtils.cellRectAt(index, view.columns, view.rows, view.availableWidth, view.availableHeight).y - + (control.gridVisible ? __gridLineWidth : 0) - width: CalendarUtils.cellRectAt(index, view.columns, view.rows, view.availableWidth, view.availableHeight).width - - (control.gridVisible ? __gridLineWidth : 0) - height: CalendarUtils.cellRectAt(index, view.columns, view.rows, view.availableWidth, view.availableHeight).height - - (control.gridVisible ? __gridLineWidth : 0) + function dateChanged() { + if (model !== undefined && model.locale !== undefined) { + model.selectedDate = control.selectedDate; + currentIndex = model.indexAt(control.selectedDate); + } + } - sourceComponent: dateDelegate + // The combined available width and height to be shared amongst each cell. + readonly property real availableWidth: (viewContainer.width - (control.gridVisible ? __gridLineWidth : 0)) + readonly property real availableHeight: (viewContainer.height - (control.gridVisible ? __gridLineWidth : 0)) - readonly property int __index: index - readonly property var __model: model + delegate: Loader { + id: delegateLoader - property QtObject styleData: QtObject { - readonly property alias index: delegateLoader.__index - readonly property alias model: delegateLoader.__model - readonly property bool selected: view.currentIndex == index - readonly property date date: model.date - } + x: CalendarUtils.cellRectAt(index, view.columns, view.rows, view.availableWidth, view.availableHeight).x + + (control.gridVisible ? __gridLineWidth : 0) + y: CalendarUtils.cellRectAt(index, view.columns, view.rows, view.availableWidth, view.availableHeight).y + + (control.gridVisible ? __gridLineWidth : 0) + width: CalendarUtils.cellRectAt(index, view.columns, view.rows, view.availableWidth, view.availableHeight).width + - (control.gridVisible ? __gridLineWidth : 0) + height: CalendarUtils.cellRectAt(index, view.columns, view.rows, view.availableWidth, view.availableHeight).height + - (control.gridVisible ? __gridLineWidth : 0) - MouseArea { - anchors.fill: parent + sourceComponent: dateDelegate - function setDateIfValid(date) { - if (control.isValidDate(date)) { - control.selectedDate = date; - } - } + readonly property int __index: index + readonly property var __model: model - onClicked: { - setDateIfValid(date) + property QtObject styleData: QtObject { + readonly property alias index: delegateLoader.__index + readonly property alias model: delegateLoader.__model + readonly property bool selected: view.currentIndex == index + readonly property date date: model.date } - onDoubleClicked: { - if (date.getTime() === control.selectedDate.getTime()) { - // Only accept double clicks if the first click does not - // change the month displayed. This is because double- - // clicking on a date in the next month will first cause - // a single click which will change the month and the - // the release will be triggered on the same index but a - // different date (the date in the next month). - control.doubleClicked(date); + MouseArea { + anchors.fill: parent + + function setDateIfValid(date) { + if (control.isValidDate(date)) { + control.selectedDate = date; + } + + onClicked: { + setDateIfValid(date) + } + + onDoubleClicked: { + if (date.getTime() === control.selectedDate.getTime()) { + // Only accept double clicks if the first click does not + // change the month displayed. This is because double- + // clicking on a date in the next month will first cause + // a single click which will change the month and the + // the release will be triggered on the same index but a + // different date (the date in the next month). + control.doubleClicked(date); + } + } } } } |