1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the Qt Components project.
9 ** $QT_BEGIN_LICENSE:BSD$
10 ** You may use this file under the terms of the BSD license as follows:
12 ** "Redistribution and use in source and binary forms, with or without
13 ** modification, are permitted provided that the following conditions are
15 ** * Redistributions of source code must retain the above copyright
16 ** notice, this list of conditions and the following disclaimer.
17 ** * Redistributions in binary form must reproduce the above copyright
18 ** notice, this list of conditions and the following disclaimer in
19 ** the documentation and/or other materials provided with the
21 ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
22 ** the names of its contributors may be used to endorse or promote
23 ** products derived from this software without specific prior written
26 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
39 ****************************************************************************/
42 import com.nokia.meego 1.0
43 import "constants.js" as C
44 import "TumblerIndexHelper.js" as TH
47 Class: DatePickerDialog
48 Dialog that shows a date picker.
56 * [string] If not null, it will be used as the title text for the dialog.
57 * If further customization is needed, use property title instead
59 property alias titleText: title.text
63 * [int] The displayed year.
65 property int year: dateTime.currentYear()
69 * [int] The displayed month.
75 * [int] The displayed day.
80 * Property: minimumYear
81 * [int] Optional, the minimum year shown on the tumbler. This property should
82 * only be set once during construction. If the value is not specified,
83 * it is default to current year - 1.
85 property int minimumYear: dateTime.currentYear() - 1
88 * Property: maximumYear
89 * [int] Optional, the maximum year shown on the tumbler. This property should
90 * only be set once during construction. If the value is not specified,
91 * it is default to current year + 20.
93 property int maximumYear: dateTime.currentYear() + 20
96 * Property: acceptButtonText
97 * [string] Optional, the button text for the accept button.
99 property alias acceptButtonText: confirmButton.text
102 * Property: rejectButtonText
103 * [string] Optional, the button text for the reject button.
105 property alias rejectButtonText: rejectButton.text
107 // TODO do not dismiss the dialog when empty area is clicked
110 leftMargin: screen.currentOrientation == Screen.Portrait || screen.currentOrientation == Screen.PortraitInverted ? 16 : 215
111 rightMargin: screen.currentOrientation == Screen.Portrait || screen.currentOrientation == Screen.PortraitInverted ? 16 : 215
117 visible: text.length > 0
118 color: theme.selectionColor
119 font { pixelSize: 32; family: C.FONT_FAMILY_BOLD }
120 elide: Text.ElideRight
130 function _handleTumblerChanges(index) {
131 if (index == 1 || index == 2) {
132 var curYear = yearColumn.selectedIndex + yearList.get(0).value;
133 var curMonth = monthColumn.selectedIndex + 1;
135 var d = dateTime.daysInMonth(curYear, curMonth);
136 if (dayColumn.selectedIndex >= d)
137 dayColumn.selectedIndex = d - 1
138 while (dayList.count > d)
139 dayList.remove(dayList.count - 1)
140 while (dayList.count < d)
141 dayList.append({"value" : dayList.count + 1})
145 columns: [dayColumn, monthColumn, yearColumn]
147 _handleTumblerChanges(index);
150 privateDelayInit: true
158 selectedIndex: root.day - (root.day > 0 ? 1 : 0)
167 selectedIndex: root.month - (root.month > 0 ? 1 : 0)
176 selectedIndex: yearList.length > 0 ? internal.year - yearList.get(0).value : 0
182 anchors.horizontalCenter: parent.horizontalCenter
188 width: (root.width / 2) - 3
189 style: ButtonStyle { inverted: true }
195 width: (root.width / 2) - 3
196 platformStyle: ButtonStyle { inverted: true }
199 onMinimumYearChanged: {
200 if (!internal.surpassUpdate) {
201 internal.year = root.year
202 internal.minYear = root.minimumYear
204 if (internal.minYear < 0)
205 internal.minYear = dateTime.currentYear() - 1;
206 else if (internal.minYear > root.maximumYear)
207 internal.minYear = root.maximumYear;
209 internal.updateYearList()
210 internal.validateDate()
211 internal.year = internal.year < internal.minYear ? internal.minYear :
212 (internal.year > root.maximumYear ? root.maximumYear :internal.year)
215 onMaximumYearChanged: {
216 internal.minYear = root.minimumYear
218 if (root.maximumYear < 0)
219 root.maximumYear = dateTime.currentYear() + 20;
220 else if (root.maximumYear < internal.minYear)
221 root.maximumYear = internal.minYear;
223 internal.updateYearList()
224 internal.validateDate()
225 internal.year = internal.year > root.maximumYear ? root.maximumYear :
226 (internal.year < internal.minYear ? internal.minYear : internal.year)
227 if (internal.minYear < 0)
228 root.minimumYear = dateTime.currentYear() - 1
231 if (status == DialogStatus.Opening) {
232 TH.saveIndex(tumbler);
233 if (!internal.initialized)
234 internal.initializeDataModels();
235 if (internal.year > 0)
236 yearColumn.selectedIndex = internal.year - yearList.get(0).value;
237 tumbler._handleTumblerChanges(2);
238 dayColumn.selectedIndex = root.day - 1;
240 if (status == DialogStatus.Closing) {
241 internal.surpassUpdate = true
242 if (internal.surpassUpdate) {
243 root.year = internal.year
244 root.minimumYear = internal.minYear
246 internal.surpassUpdate = false
250 internal.validateDate()
251 if (dayColumn.items.length > root.day - 1)
252 dayColumn.selectedIndex = root.day - 1
255 internal.validateDate()
256 monthColumn.selectedIndex = root.month - 1
259 if (!internal.surpassUpdate) {
260 internal.year = root.year
261 internal.validateDate()
262 internal.year = internal.year < internal.minYear ? internal.minYear :
263 (internal.year > root.maximumYear ? root.maximumYear : internal.year)
265 if (internal.initialized)
266 yearColumn.selectedIndex = internal.year - yearList.get(0).value
270 tumbler.privateForceUpdate();
271 root.year = yearColumn.selectedIndex + yearList.get(0).value;
272 root.month = monthColumn.selectedIndex + 1;
273 root.day = dayColumn.selectedIndex + 1;
276 TH.restoreIndex(tumbler);
282 property variant initialized: false
285 property bool surpassUpdate: false
287 function initializeDataModels() {
288 var currentYear = new Date().getFullYear();
289 minimumYear = minimumYear ? minimumYear : currentYear - 1;
290 maximumYear = maximumYear ? maximumYear : currentYear + 20;
292 for (var y = minimumYear; y <= maximumYear; ++y)
293 yearList.append({"value" : y}) // year
295 var nDays = dateTime.daysInMonth(internal.year, root.month);
296 for (var d = 1; d <= nDays; ++d)
297 dayList.append({"value" : d}) // day
298 for (var m = 1; m <= 12; ++m)
299 monthList.append({"value" : dateTime.shortMonthName(m)});
301 tumbler.privateInitialize();
302 internal.initialized = true;
305 function updateYearList() {
306 if (internal.initialized) {
307 var tmp = yearColumn.selectedIndex;
309 for (var i = internal.minYear; i <= root.maximumYear; ++i)
310 yearList.append({"value" : i})
311 if (tmp < yearList.count) {
312 yearColumn.selectedIndex = 0;
313 yearColumn.selectedIndex = tmp;
318 function validateDate() {
319 if (internal.year < 1){
320 internal.year = new Date().getFullYear()
321 if (maximumYear < internal.year)
322 root.maximumYear = dateTime.currentYear() + 20;
323 if (minimumYear > internal.year)
324 internal.minYear = dateTime.currentYear() - 1;
327 root.month = Math.max(1, Math.min(12, root.month))
328 var d = dateTime.daysInMonth(internal.year, root.month);
329 root.day = Math.max(1, Math.min(d, root.day))