summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorMitch Curtis <mitch.curtis@digia.com>2013-07-15 22:57:52 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-02-14 13:13:53 +0100
commite023dd212c81a2ad4ba4b4db22df9cde65a502e8 (patch)
tree2c3521e8a4154d65a55fc3032254b58b181d957e /tests
parente88bdffe644e53912dfbce95117555cb6a87bfd2 (diff)
downloadqtquickcontrols-e023dd212c81a2ad4ba4b4db22df9cde65a502e8.tar.gz
Add Calendar to Qt Quick Controls.
Task-number: QTBUG-29948 [ChangeLog][QtQuickControls] Calendar was added. Calendar allows selection of dates from a grid of days, similar to QCalendarWidget. Change-Id: I279130e704bc0dfd8dfe114ec9b6b49e111faf96 Reviewed-by: Jens Bache-Wiig <jens.bache-wiig@digia.com>
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/controls/controls.pro2
-rw-r--r--tests/auto/controls/data/tst_calendar.qml798
-rw-r--r--tests/auto/controls/data/tst_rangeddate.qml178
3 files changed, 978 insertions, 0 deletions
diff --git a/tests/auto/controls/controls.pro b/tests/auto/controls/controls.pro
index ce3857a6..fedc36c4 100644
--- a/tests/auto/controls/controls.pro
+++ b/tests/auto/controls/controls.pro
@@ -15,6 +15,8 @@ TESTDATA = $$PWD/data/*
OTHER_FILES += \
$$PWD/data/tst_button.qml \
$$PWD/data/tst_busyindicator.qml \
+ $$PWD/data/tst_calendar.qml \
+ $$PWD/data/tst_rangeddate.qml \
$$PWD/data/tst_shortcuts.qml \
$$PWD/data/tst_spinbox.qml \
$$PWD/data/tst_tableview.qml \
diff --git a/tests/auto/controls/data/tst_calendar.qml b/tests/auto/controls/data/tst_calendar.qml
new file mode 100644
index 00000000..2032029f
--- /dev/null
+++ b/tests/auto/controls/data/tst_calendar.qml
@@ -0,0 +1,798 @@
+/****************************************************************************
+**
+** 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: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.2
+import QtQuick.Controls.Private 1.0
+import QtTest 1.0
+
+Item {
+ id: container
+ width: 300
+ height: 300
+
+ TestCase {
+ id: testcase
+ name: "Tests_Calendar"
+ when: windowShown
+ readonly property int navigationBarHeight: calendar !== undefined ? calendar.__panel.navigationBarItem.height : 0
+ readonly property int dayOfWeekHeaderRowHeight: calendar !== undefined ? calendar.__panel.dayOfWeekHeaderRowHeight : 0
+ readonly property int firstDateCellX: 0
+ readonly property int firstDateCellY: navigationBarHeight + dayOfWeekHeaderRowHeight
+ readonly property int previousMonthButtonX: navigationBarHeight / 2
+ readonly property int previousMonthButtonY: navigationBarHeight / 2
+ readonly property int nextMonthButtonX: calendar ? calendar.width - navigationBarHeight / 2 : 0
+ readonly property int nextMonthButtonY: navigationBarHeight / 2
+
+ property var calendar
+
+ SignalSpy {
+ id: hoveredSignalSpy
+ }
+
+ SignalSpy {
+ id: pressedSignalSpy
+ }
+
+ SignalSpy {
+ id: clickedSignalSpy
+ }
+
+ SignalSpy {
+ id: releasedSignalSpy
+ }
+
+ function init() {
+ calendar = Qt.createQmlObject("import QtQuick.Controls 1.2; " +
+ " Calendar { }", container, "");
+ calendar.width = 300;
+ calendar.height = 300;
+ }
+
+ function cleanup() {
+ hoveredSignalSpy.clear();
+ pressedSignalSpy.clear();
+ clickedSignalSpy.clear();
+ releasedSignalSpy.clear();
+ }
+
+ function toPixelsX(cellPosX) {
+ var cellRect = calendar.__style.__cellRectAt(cellPosX);
+ return firstDateCellX + cellRect.x + cellRect.width / 2;
+ }
+
+ function toPixelsY(cellPosY) {
+ var cellRect = calendar.__style.__cellRectAt(cellPosY * calendar.__panel.columns);
+ return firstDateCellY + cellRect.y + cellRect.height / 2;
+ }
+
+ function test_defaultConstructed() {
+ calendar.minimumDate = new Date(1, 0, 1);
+ calendar.maximumDate = new Date(4000, 0, 1);
+
+ compare(calendar.minimumDate, new Date(1, 0, 1));
+ compare(calendar.maximumDate, new Date(4000, 0, 1));
+ compare(calendar.selectedDate, new Date(new Date().setHours(0, 0, 0, 0)));
+ compare(calendar.gridVisible, true);
+ compare(calendar.dayOfWeekFormat, Locale.ShortFormat);
+ compare(calendar.__locale, Qt.locale());
+ }
+
+ function test_setAfterConstructed() {
+ calendar.minimumDate = new Date(1900, 0, 1);
+ calendar.maximumDate = new Date(1999, 11, 31);
+ calendar.selectedDate = new Date(1980, 0, 1);
+ calendar.gridVisible = false;
+ calendar.dayOfWeekFormat = Locale.NarrowFormat;
+ calendar.__locale = Qt.locale("de_DE");
+
+ compare(calendar.minimumDate, new Date(1900, 0, 1));
+ compare(calendar.maximumDate, new Date(1999, 11, 31));
+ compare(calendar.selectedDate, new Date(1980, 0, 1));
+ compare(calendar.gridVisible, false);
+ compare(calendar.__locale, Qt.locale("de_DE"));
+ }
+
+ function test_selectedDate() {
+ calendar.minimumDate = new Date(2012, 0, 1);
+ calendar.maximumDate = new Date(2013, 0, 1);
+
+ // Equal to minimumDate date.
+ calendar.selectedDate = new Date(calendar.minimumDate);
+ compare(calendar.selectedDate, calendar.minimumDate);
+
+ // Outside minimum date.
+ calendar.selectedDate.setDate(calendar.selectedDate.getDate() - 1);
+ compare(calendar.selectedDate, calendar.minimumDate);
+
+ // Equal to maximum date.
+ calendar.selectedDate = new Date(calendar.maximumDate);
+ compare(calendar.selectedDate, calendar.maximumDate);
+
+ // Outside maximumDate date.
+ calendar.selectedDate.setDate(calendar.selectedDate.getDate() - 1);
+ compare(calendar.selectedDate, calendar.maximumDate);
+
+ // Should not change.
+ calendar.selectedDate = undefined;
+ compare(calendar.selectedDate, calendar.maximumDate);
+ }
+
+ // Should be able to use the full JS date range.
+ function test_minMaxJsDateRange() {
+ skip("QTBUG-36846");
+
+ calendar.minimumDate = CalendarUtils.minimumCalendarDate;
+ calendar.maximumDate = CalendarUtils.maximumCalendarDate;
+
+ calendar.selectedDate = CalendarUtils.minimumCalendarDate;
+ compare(calendar.selectedDate.getTime(), CalendarUtils.minimumCalendarDate.getTime());
+
+ calendar.selectedDate = CalendarUtils.maximumCalendarDate;
+ compare(calendar.selectedDate.getTime(), CalendarUtils.maximumCalendarDate.getTime());
+ }
+
+ function test_minMaxUndefined() {
+
+ var expected = new Date(calendar.minimumDate);
+ calendar.minimumDate = undefined;
+ compare(calendar.minimumDate, expected);
+
+ expected = new Date(calendar.maximumDate);
+ calendar.maximumDate = undefined;
+ compare(calendar.maximumDate, expected);
+ }
+
+ function test_keyNavigation() {
+ calendar.forceActiveFocus();
+ calendar.selectedDate = new Date(2013, 0, 1);
+ // Set this to a certain locale, because days will be in different
+ // places depending on the system locale of the host machine.
+ calendar.__locale = Qt.locale("en_GB");
+
+ /* January 2013 December 2012
+ M T W T F S S M T W T F S S
+ 31 [1] 2 3 4 5 6 26 27 28 29 30 1 2
+ 7 8 9 10 11 12 13 3 4 5 6 7 8 9
+ 14 15 16 17 18 19 20 ==> 10 11 12 13 14 15 16
+ 21 22 23 24 25 26 27 17 18 19 20 21 22 23
+ 28 29 30 31 1 2 3 24 25 26 27 28 29 30
+ 4 5 6 7 8 9 10 [31] 1 2 3 4 5 6 */
+ keyPress(Qt.Key_Left);
+ compare(calendar.selectedDate, new Date(2012, 11, 31),
+ "Selecting a day from the previous month should select that date.");
+
+ /* December 2012 December 2012
+ M T W T F S S M T W T F S S
+ 26 27 28 29 30 1 2 26 27 28 29 30 1 2
+ 3 4 5 6 7 8 9 3 4 5 6 7 8 9
+ 10 11 12 13 14 15 16 ==> 10 11 12 13 14 15 16
+ 17 18 19 20 21 22 23 17 18 19 20 21 22 23
+ 24 25 26 27 28 29 30 24 25 26 27 28 29 [30]
+ [31] 1 2 3 4 5 6 31 1 2 3 4 5 6 */
+ keyPress(Qt.Key_Left);
+ compare(calendar.selectedDate, new Date(2012, 11, 30),
+ "Pressing the left key on the left edge should select the date "
+ + "1 row above on the right edge.");
+
+ /* December 2012 December 2012
+ M T W T F S S M T W T F S S
+ 26 27 28 29 30 1 2 26 27 28 29 30 1 2
+ 3 4 5 6 7 8 9 3 4 5 6 7 8 9
+ 10 11 12 13 14 15 16 ==> 10 11 12 13 14 15 16
+ 17 18 19 20 21 22 23 17 18 19 20 21 22 23
+ 24 25 26 27 28 29 [30] 24 25 26 27 28 29 30
+ 31 1 2 3 4 5 6 [31] 1 2 3 4 5 6 */
+ keyPress(Qt.Key_Right);
+ compare(calendar.selectedDate, new Date(2012, 11, 31),
+ "Pressing the right key on the right edge should select the date "
+ + "1 row below on the left edge.");
+
+ /* April 2013 March 2013
+ M T W T F S S M T W T F S S
+ [1] 2 3 4 5 6 7 25 26 27 28 1 2 3
+ 8 9 10 11 12 13 14 4 5 6 7 8 9 10
+ 15 16 17 18 19 20 21 ==> 11 12 13 14 15 16 17
+ 22 23 24 25 26 27 28 18 19 20 21 22 23 24
+ 29 30 31 1 2 3 4 25 26 27 28 29 30 [31]
+ 5 6 7 8 9 10 11 1 2 3 4 5 6 7 */
+ calendar.selectedDate = new Date(2013, 3, 1);
+ keyPress(Qt.Key_Left);
+ compare(calendar.selectedDate, new Date(2013, 2, 31),
+ "Pressing the left key on the left edge of the first row should "
+ + "select the last date of the previous month.");
+
+ /* January 2014 January 2014
+ M T W T F S S M T W T F S S
+ 30 31 [1] 2 3 4 5 30 31 1 2 3 4 5
+ 6 7 8 9 10 11 12 6 7 8 9 10 11 12
+ 13 14 15 16 17 18 19 ==> 13 14 15 16 17 18 19
+ 20 21 22 23 24 25 26 20 21 22 23 24 25 26
+ 27 28 29 30 31 1 2 27 28 29 30 [31] 1 2
+ 3 4 5 6 7 8 9 3 4 5 6 7 8 9 */
+ calendar.selectedDate = new Date(2014, 0, 1);
+ keyPress(Qt.Key_End);
+ compare(calendar.selectedDate, new Date(2014, 0, 31),
+ "Pressing the end key should select the last date in the same month.");
+
+ /* January 2014 January 2014
+ M T W T F S S M T W T F S S
+ 30 31 1 2 3 4 5 30 31 [1] 2 3 4 5
+ 6 7 8 9 10 11 12 6 7 8 9 10 11 12
+ 13 14 15 16 17 18 19 ==> 13 14 15 16 17 18 19
+ 20 21 22 23 24 25 26 20 21 22 23 24 25 26
+ 27 28 29 30 [31] 1 2 27 28 29 30 31 1 2
+ 3 4 5 6 7 8 9 3 4 5 6 7 8 9 */
+ calendar.selectedDate = new Date(2014, 0, 31);
+ keyPress(Qt.Key_Home);
+ compare(calendar.selectedDate, new Date(2014, 0, 1),
+ "Pressing the home key should select the first date in the same month.");
+
+ /* December 2013 November 2013
+ M T W T F S S M T W T F S S
+ 25 26 27 28 29 30 1 28 29 30 31 [1] 2 3
+ 2 3 4 5 6 7 8 4 5 6 7 8 9 10
+ 9 10 11 12 13 14 15 ==> 11 12 13 14 15 16 17
+ 16 17 18 19 20 21 22 18 19 20 21 22 23 24
+ 23 24 25 26 27 28 29 25 26 27 28 29 [30] 1
+ 30 [31] 1 2 3 4 5 2 3 4 5 6 7 8 */
+ calendar.selectedDate = new Date(2013, 11, 31);
+ keyPress(Qt.Key_PageUp);
+ compare(calendar.selectedDate, new Date(2013, 10, 30),
+ "Pressing the page up key should select the equivalent date in the previous month.");
+
+ /* November 2013 December 2013
+ M T W T F S S M T W T F S S
+ 28 29 30 31 [1] 2 3 25 26 27 28 29 30 1
+ 4 5 6 7 8 9 10 2 3 4 5 6 7 8
+ 11 12 13 14 15 16 17 ==> 9 10 11 12 13 14 15
+ 18 19 20 21 22 23 24 16 17 18 19 20 21 22
+ 25 26 27 28 29 [30] 1 23 24 25 26 27 28 29
+ 2 3 4 5 6 7 8 [30] 31 1 2 3 4 5 */
+ calendar.selectedDate = new Date(2013, 10, 30);
+ keyPress(Qt.Key_PageDown);
+ compare(calendar.selectedDate, new Date(2013, 11, 30),
+ "Pressing the page down key should select the equivalent date in the next month.");
+ }
+
+ function test_selectPreviousMonth() {
+ calendar.selectedDate = new Date(2013, 0, 1);
+ compare(calendar.selectedDate, new Date(2013, 0, 1));
+
+ calendar.__selectPreviousMonth();
+ compare(calendar.selectedDate, new Date(2012, 11, 1));
+ }
+
+ function test_showPreviousMonthWithMouse() {
+ calendar.selectedDate = new Date(2013, 1, 28);
+ compare(calendar.visibleMonth, 1);
+ compare(calendar.visibleYear, 2013);
+
+ mouseClick(calendar, previousMonthButtonX, previousMonthButtonY, Qt.LeftButton);
+ compare(calendar.visibleMonth, 0);
+ compare(calendar.visibleYear, 2013);
+
+ mouseClick(calendar, previousMonthButtonX, previousMonthButtonY, Qt.LeftButton);
+ compare(calendar.visibleMonth, 11);
+ compare(calendar.visibleYear, 2012);
+ }
+
+ function test_selectNextMonth() {
+ calendar.selectedDate = new Date(2013, 0, 31);
+ compare(calendar.selectedDate, new Date(2013, 0, 31));
+
+ calendar.__selectNextMonth();
+ compare(calendar.selectedDate, new Date(2013, 1, 28));
+
+ calendar.__selectNextMonth();
+ compare(calendar.selectedDate, new Date(2013, 2, 28));
+ }
+
+ function test_showNextMonthWithMouse() {
+ calendar.selectedDate = new Date(2013, 0, 31);
+ compare(calendar.visibleMonth, 0);
+ compare(calendar.visibleYear, 2013);
+
+ mouseClick(calendar, nextMonthButtonX, nextMonthButtonY, Qt.LeftButton);
+ compare(calendar.visibleMonth, 1);
+ compare(calendar.visibleYear, 2013);
+
+ mouseClick(calendar, nextMonthButtonX, nextMonthButtonY, Qt.LeftButton);
+ compare(calendar.visibleMonth, 2);
+ compare(calendar.visibleYear, 2013);
+ }
+
+ function test_selectDateWithMouse() {
+ /* January 2013
+ S M T W T F S
+ 30 31 [1] 2 3 4 5
+ 6 7 8 9 10 11 12
+ 13 14 15 16 17 18 19
+ 20 21 22 23 24 25 26
+ 27 28 29 30 31 1 2
+ 3 4 5 6 7 8 9 */
+
+ var startDate = new Date(2013, 0, 1);
+ calendar.selectedDate = startDate;
+ calendar.__locale = Qt.locale("en_US");
+ compare(calendar.selectedDate, startDate);
+
+ pressedSignalSpy.target = calendar;
+ pressedSignalSpy.signalName = "pressed";
+
+ clickedSignalSpy.target = calendar;
+ clickedSignalSpy.signalName = "clicked";
+
+ releasedSignalSpy.target = calendar;
+ releasedSignalSpy.signalName = "released";
+
+ // Clicking on header items should do nothing.
+ mousePress(calendar, 0, navigationBarHeight, Qt.LeftButton);
+ compare(calendar.selectedDate, startDate);
+ compare(calendar.__panel.pressedCellIndex, -1);
+ compare(pressedSignalSpy.count, 0);
+ compare(releasedSignalSpy.count, 0);
+ compare(clickedSignalSpy.count, 0);
+
+ mouseRelease(calendar, 0, navigationBarHeight, Qt.LeftButton);
+ compare(calendar.selectedDate, startDate);
+ compare(calendar.__panel.pressedCellIndex, -1);
+ compare(pressedSignalSpy.count, 0);
+ compare(releasedSignalSpy.count, 0);
+ compare(clickedSignalSpy.count, 0);
+
+ var firstVisibleDate = new Date(2012, 11, 30);
+ for (var week = 0; week < CalendarUtils.weeksOnACalendarMonth; ++week) {
+ for (var day = 0; day < CalendarUtils.daysInAWeek; ++day) {
+ var expectedDate = new Date(firstVisibleDate);
+ var cellIndex = (week * CalendarUtils.daysInAWeek + day);
+ expectedDate.setDate(expectedDate.getDate() + cellIndex);
+
+ mousePress(calendar, toPixelsX(day), toPixelsY(week), Qt.LeftButton);
+ compare(calendar.selectedDate, expectedDate);
+ compare(calendar.__panel.pressedCellIndex, cellIndex);
+ compare(pressedSignalSpy.count, 1);
+ compare(releasedSignalSpy.count, 0);
+ compare(clickedSignalSpy.count, 0);
+
+ mouseRelease(calendar, toPixelsX(day), toPixelsY(week), Qt.LeftButton);
+ compare(calendar.__panel.pressedCellIndex, -1);
+ compare(pressedSignalSpy.count, 1);
+ compare(releasedSignalSpy.count, 1);
+ compare(clickedSignalSpy.count, 1);
+
+ pressedSignalSpy.clear();
+ releasedSignalSpy.clear();
+ clickedSignalSpy.clear();
+
+ if (expectedDate.getMonth() != startDate.getMonth()) {
+ // A different month is being displayed as a result of the click;
+ // change back to the original month so our results are correct.
+ calendar.selectedDate = startDate;
+ compare(calendar.selectedDate, startDate);
+ }
+ }
+ }
+
+ // Ensure released event does not trigger date selection.
+ calendar.selectedDate = startDate;
+ mousePress(calendar, toPixelsX(1), toPixelsY(0), Qt.LeftButton);
+ compare(calendar.selectedDate, new Date(2012, 11, 31));
+ compare(calendar.__panel.pressedCellIndex, 1);
+ compare(pressedSignalSpy.count, 1);
+ compare(releasedSignalSpy.count, 0);
+ compare(clickedSignalSpy.count, 0);
+
+ pressedSignalSpy.clear();
+ releasedSignalSpy.clear();
+ clickedSignalSpy.clear();
+
+ mouseRelease(calendar, toPixelsX(1), toPixelsY(0), Qt.LeftButton);
+ compare(calendar.selectedDate, new Date(2012, 11, 31));
+ compare(calendar.__panel.pressedCellIndex, -1);
+ compare(pressedSignalSpy.count, 0);
+ compare(releasedSignalSpy.count, 1);
+ compare(clickedSignalSpy.count, 1);
+ }
+
+ function test_selectInvalidDateWithMouse() {
+ var startDate = new Date(2013, 0, 1);
+ calendar.minimumDate = new Date(2013, 0, 1);
+ calendar.selectedDate = new Date(startDate);
+ calendar.maximumDate = new Date(2013, 1, 5);
+ calendar.__locale = Qt.locale("no_NO");
+
+ pressedSignalSpy.target = calendar;
+ pressedSignalSpy.signalName = "pressed";
+
+ clickedSignalSpy.target = calendar;
+ clickedSignalSpy.signalName = "clicked";
+
+ releasedSignalSpy.target = calendar;
+ releasedSignalSpy.signalName = "released";
+
+ /* January 2013
+ M T W T F S S
+ [31] 1 2 3 4 5 6
+ 7 8 9 10 11 12 13
+ 14 15 16 17 18 19 20
+ 21 22 23 24 25 26 27
+ 28 29 30 31 1 2 3
+ 4 5 6 7 8 9 10 */
+ mousePress(calendar, toPixelsX(0), toPixelsY(0), Qt.LeftButton);
+ compare(calendar.__panel.pressedCellIndex, 0);
+ compare(calendar.selectedDate, startDate);
+ compare(pressedSignalSpy.count, 0);
+ compare(releasedSignalSpy.count, 0);
+ compare(clickedSignalSpy.count, 0);
+
+ mouseRelease(calendar, toPixelsX(0), toPixelsY(0), Qt.LeftButton);
+ compare(calendar.selectedDate, startDate);
+ compare(calendar.__panel.pressedCellIndex, -1);
+ compare(pressedSignalSpy.count, 0);
+ compare(releasedSignalSpy.count, 0);
+ compare(clickedSignalSpy.count, 0);
+
+ /* January 2013 December 2012
+ M T W T F S S M T W T F S S
+ 31 1 2 3 4 5 6 31 1 2 3 4 5 6
+ 7 8 9 10 11 12 13 7 8 9 10 11 12 13
+ 14 15 16 17 18 19 20 through 14 15 16 17 18 19 20
+ 21 22 23 24 25 26 27 to 21 22 23 24 25 26 27
+ 28 29 30 31 1 2 3 28 29 30 31 1 2 3
+ 4 5 [6] 7 8 9 10 4 5 6 7 8 9 [10] */
+ for (var x = 2; x < 7; ++x) {
+ mousePress(calendar, toPixelsX(x), toPixelsY(5), Qt.LeftButton);
+ compare(calendar.selectedDate, startDate);
+ compare(calendar.__panel.pressedCellIndex, 35 + x);
+ compare(pressedSignalSpy.count, 0);
+ compare(releasedSignalSpy.count, 0);
+ compare(clickedSignalSpy.count, 0);
+
+ mouseRelease(calendar, toPixelsX(x), toPixelsY(5), Qt.LeftButton);
+ compare(calendar.selectedDate, startDate);
+ compare(calendar.__panel.pressedCellIndex, -1);
+ compare(pressedSignalSpy.count, 0);
+ compare(releasedSignalSpy.count, 0);
+ compare(clickedSignalSpy.count, 0);
+ }
+ }
+
+ function test_daysCenteredVertically() {
+ /*
+ When the first day of the visible month is the first cell in
+ the calendar, we want to push it onto the next row to ensure
+ there is some balance between the days shown in the previous
+ and next months.
+
+ December 2014
+ M T W T F S S
+ 24 25 26 27 28 29 30
+ 1 2 3 4 5 6 7
+ 8 9 10 11 12 13 14
+ 15 16 17 18 19 20 21
+ 22 23 24 25 26 27 28
+ 29 30 31 1 2 3 4 */
+
+ calendar.__locale = Qt.locale("en_GB");
+ calendar.selectedDate = new Date(2014, 11, 1);
+ mousePress(calendar, toPixelsX(0), toPixelsY(0), Qt.LeftButton);
+ compare(calendar.selectedDate, new Date(2014, 10, 24));
+ mouseRelease(calendar, toPixelsX(0), toPixelsY(0), Qt.LeftButton);
+ }
+
+ function test_hovered() {
+ // Moving the mouse within the calendar once seems to be necessary for it
+ // to receive subsequent move events.
+ mouseMove(calendar, calendar.width, calendar.height, 100);
+
+ hoveredSignalSpy.target = calendar;
+ hoveredSignalSpy.signalName = "hovered";
+
+ var selectedDate = calendar.selectedDate;
+ var visibleMonth = calendar.visibleMonth;
+ var visibleYear = calendar.visibleYear;
+ for (var row = 0; row < CalendarUtils.weeksOnACalendarMonth; ++row) {
+ for (var col = 0; col < CalendarUtils.daysInAWeek; ++col) {
+ mouseMove(calendar, toPixelsX(col), toPixelsY(row));
+
+ compare(hoveredSignalSpy.count, 1);
+ compare(calendar.__panel.hoveredCellIndex, row * CalendarUtils.daysInAWeek + col);
+ compare(calendar.selectedDate, selectedDate);
+ compare(calendar.visibleMonth, visibleMonth);
+ compare(calendar.visibleYear, visibleYear);
+
+ hoveredSignalSpy.clear();
+ }
+ }
+
+ // Moving the mouse around over the same cell should only emit one hovered signal.
+ mouseMove(calendar, toPixelsX(0), toPixelsY(0));
+ compare(hoveredSignalSpy.count, 1);
+
+ mouseMove(calendar, toPixelsX(0) + 1, toPixelsY(0) + 1);
+ compare(hoveredSignalSpy.count, 1);
+
+ hoveredSignalSpy.clear();
+
+ // Moving the mouse outside the control should unset any hovered data.
+ mouseMove(calendar, -1, -1);
+ compare(calendar.__panel.hoveredCellIndex, -1);
+ compare(hoveredSignalSpy.count, 0);
+
+ // Moving it back in should set the hovered data.
+ mouseMove(calendar, toPixelsX(0), toPixelsY(0));
+ compare(hoveredSignalSpy.count, 1);
+ compare(calendar.__panel.hoveredCellIndex, 0);
+ }
+
+ function dragTo(cellX, cellY, expectedCellIndex, expectedDate) {
+ mouseMove(calendar, toPixelsX(cellX), toPixelsY(cellY), Qt.LeftButton);
+ compare(calendar.selectedDate, expectedDate);
+ compare(calendar.__panel.pressedCellIndex, expectedCellIndex);
+ compare(hoveredSignalSpy.count, 1);
+ compare(pressedSignalSpy.count, 1);
+ compare(releasedSignalSpy.count, 0);
+ compare(clickedSignalSpy.count, 0);
+
+ hoveredSignalSpy.clear();
+ pressedSignalSpy.clear();
+ releasedSignalSpy.clear();
+ clickedSignalSpy.clear();
+ }
+
+ function test_dragWhileMousePressed() {
+ calendar.minimumDate = new Date(2014, 1, 1);
+ calendar.selectedDate = new Date(2014, 1, 28);
+ calendar.maximumDate = new Date(2014, 2, 31);
+ calendar.__locale = Qt.locale("en_GB");
+
+ hoveredSignalSpy.target = calendar;
+ hoveredSignalSpy.signalName = "hovered";
+
+ pressedSignalSpy.target = calendar;
+ pressedSignalSpy.signalName = "pressed";
+
+ clickedSignalSpy.target = calendar;
+ clickedSignalSpy.signalName = "clicked";
+
+ releasedSignalSpy.target = calendar;
+ releasedSignalSpy.signalName = "released";
+
+ /*
+ This test drags across each row, alternating from left to right
+ when an edge is reached.
+
+ February 2014 February 2014
+ M T W T F S S M T W T F S S
+ 27 28 29 30 31 [1] 2 27 28 29 30 31 1 2
+ 3 4 5 6 7 8 9 3 4 5 6 7 8 9
+ 10 11 12 13 14 15 16 through 10 11 12 13 14 15 16
+ 17 18 19 20 21 22 23 to 17 18 19 20 21 22 23
+ 24 25 26 27 28 1 2 24 25 26 27 [28] 1 2
+ 3 4 5 6 7 8 9 3 4 5 6 7 8 9 */
+
+ mousePress(calendar, toPixelsX(5), toPixelsY(0), Qt.LeftButton);
+ compare(calendar.selectedDate, new Date(2014, 1, 1));
+ compare(calendar.__panel.pressedCellIndex, 5);
+ compare(hoveredSignalSpy.count, 1);
+ compare(pressedSignalSpy.count, 1);
+ compare(releasedSignalSpy.count, 0);
+ compare(clickedSignalSpy.count, 0);
+
+ hoveredSignalSpy.clear();
+ pressedSignalSpy.clear();
+ releasedSignalSpy.clear();
+ clickedSignalSpy.clear();
+
+ // The first row just has one drag.
+ dragTo(6, 0, 6, new Date(2014, 1, 2));
+
+ // Second row, right to left.
+ for (var x = 6, index = 13; index >= 7; --x, --index)
+ dragTo(x, Math.floor(index / CalendarUtils.daysInAWeek), index, new Date(2014, 1, 9 - (6 - x)));
+
+ // Third row, left to right.
+ for (x = 0, index = 14; index <= 20; ++x, ++index)
+ dragTo(x, Math.floor(index / CalendarUtils.daysInAWeek), index, new Date(2014, 1, 10 + x));
+
+ // Fourth row, right to left.
+ for (x = 6, index = 27; index >= 21; --x, --index) {
+ dragTo(x, Math.floor(index / CalendarUtils.daysInAWeek), index, new Date(2014, 1, 23 - (6 - x)));
+ }
+
+ // Fifth row, left to right. Stop at the last day of the month.
+ for (x = 0, index = 28; index <= 32; ++x, ++index) {
+ dragTo(x, Math.floor(index / CalendarUtils.daysInAWeek), index, new Date(2014, 1, 24 + x));
+ }
+
+ // Dragging into the next month should work.
+ var firstDateInNextMonth = new Date(2014, 2, 1);
+ dragTo(5, 4, 33, firstDateInNextMonth);
+
+ // Finish the drag.
+ mouseRelease(calendar, toPixelsX(5), toPixelsY(0), Qt.LeftButton);
+ compare(calendar.selectedDate, firstDateInNextMonth);
+ compare(calendar.__panel.pressedCellIndex, -1);
+ compare(hoveredSignalSpy.count, 0);
+ compare(pressedSignalSpy.count, 0);
+ compare(releasedSignalSpy.count, 1);
+ compare(clickedSignalSpy.count, 1);
+
+ hoveredSignalSpy.clear();
+ pressedSignalSpy.clear();
+ releasedSignalSpy.clear();
+ clickedSignalSpy.clear();
+
+ // Now try dragging into an invalid date.
+ calendar.selectedDate = calendar.minimumDate;
+ compare(calendar.visibleMonth, calendar.minimumDate.getMonth());
+
+ mouseMove(calendar, toPixelsX(4), toPixelsY(0), Qt.LeftButton);
+ compare(calendar.selectedDate, calendar.minimumDate);
+ compare(calendar.__panel.pressedCellIndex, -1);
+ compare(hoveredSignalSpy.count, 0);
+ compare(pressedSignalSpy.count, 0);
+ compare(releasedSignalSpy.count, 0);
+ compare(clickedSignalSpy.count, 0);
+ }
+
+ function ensureNoGapsBetweenCells(columns, rows, availableWidth, availableHeight) {
+ for (var row = 1; row < rows; ++row) {
+ for (var col = 1; col < columns; ++col) {
+ var lastHorizontalRect = CalendarUtils.cellRectAt((row - 1) * columns + col - 1, columns, rows, availableWidth, availableHeight);
+ var thisHorizontalRect = CalendarUtils.cellRectAt((row - 1) * columns + col, columns, rows, availableWidth, availableHeight);
+ compare (lastHorizontalRect.x + lastHorizontalRect.width, thisHorizontalRect.x,
+ "Gaps between column " + (col - 1) + " and " + col + " in a grid of " + columns + " columns and " + rows + " rows, "
+ + "with an availableWidth of " + availableWidth + " and availableHeight of " + availableHeight);
+
+ var lastVerticalRect = CalendarUtils.cellRectAt((row - 1) * columns + col - 1, columns, rows, availableWidth, availableHeight);
+ var thisVerticalRect = CalendarUtils.cellRectAt(row * columns + col - 1, columns, rows, availableWidth, availableHeight);
+ compare (lastVerticalRect.y + lastVerticalRect.height, thisVerticalRect.y,
+ "Gaps between row " + (row - 1) + " and " + row + " in a grid of " + columns + " columns and " + rows + " rows, "
+ + "with an availableWidth of " + availableWidth + " and availableHeight of " + availableHeight);
+ }
+ }
+ }
+
+ function test_cellRectCalculation() {
+ var columns = CalendarUtils.daysInAWeek;
+ var rows = CalendarUtils.weeksOnACalendarMonth;
+
+ // No extra space available.
+ var availableWidth = 10 * columns;
+ var availableHeight = 10 * rows;
+ var rect = CalendarUtils.cellRectAt(0, columns, rows, availableWidth, availableHeight);
+ compare(rect.x, 0);
+ compare(rect.y, 0);
+ compare(rect.width, 10);
+ compare(rect.height, 10);
+
+ rect = CalendarUtils.cellRectAt(columns - 1, columns, rows, availableWidth, availableHeight);
+ compare(rect.x, (columns - 1) * 10);
+ compare(rect.y, 0);
+ compare(rect.width, 10);
+ compare(rect.height, 10);
+
+ rect = CalendarUtils.cellRectAt(rows * columns - 1, columns, rows, availableWidth, availableHeight);
+ compare(rect.x, (columns - 1) * 10);
+ compare(rect.y, (rows - 1) * 10);
+ compare(rect.width, 10);
+ compare(rect.height, 10);
+
+ ensureNoGapsBetweenCells(columns, rows, availableWidth, availableHeight);
+
+ // 1 extra pixel of space in both width and height.
+ availableWidth = 10 * columns + 1;
+ availableHeight = 10 * rows + 1;
+ rect = CalendarUtils.cellRectAt(0, columns, rows, availableWidth, availableHeight);
+ compare(rect.x, 0);
+ compare(rect.y, 0);
+ compare(rect.width, 10 + 1);
+ compare(rect.height, 10 + 1);
+
+ rect = CalendarUtils.cellRectAt(columns - 1, columns, rows, availableWidth, availableHeight);
+ compare(rect.x, (columns - 1) * 10 + 1);
+ compare(rect.y, 0);
+ compare(rect.width, 10);
+ compare(rect.height, 10 + 1);
+
+ rect = CalendarUtils.cellRectAt(rows * columns - 1, columns, rows, availableWidth, availableHeight);
+ compare(rect.x, (columns - 1) * 10 + 1);
+ compare(rect.y, (rows - 1) * 10 + 1);
+ compare(rect.width, 10);
+ compare(rect.height, 10);
+
+ ensureNoGapsBetweenCells(columns, rows, availableWidth, availableHeight);
+
+ // 6 extra pixels in width, 5 in height.
+ availableWidth = 10 * columns + 6;
+ availableHeight = 10 * rows + 5;
+ rect = CalendarUtils.cellRectAt(0, columns, rows, availableWidth, availableHeight);
+ compare(rect.x, 0);
+ compare(rect.y, 0);
+ compare(rect.width, 10 + 1);
+ compare(rect.height, 10 + 1);
+
+ rect = CalendarUtils.cellRectAt(columns - 1, columns, rows, availableWidth, availableHeight);
+ compare(rect.x, (columns - 1) * 10 + 6);
+ compare(rect.y, 0);
+ compare(rect.width, 10);
+ compare(rect.height, 10 + 1);
+
+ rect = CalendarUtils.cellRectAt(rows * columns - 1, columns, rows, availableWidth, availableHeight);
+ compare(rect.x, (columns - 1) * 10 + 6);
+ compare(rect.y, (rows - 1) * 10 + 5);
+ compare(rect.width, 10);
+ compare(rect.height, 10);
+
+ ensureNoGapsBetweenCells(columns, rows, availableWidth, availableHeight);
+
+ availableWidth = 280;
+ availableHeight = 190;
+ ensureNoGapsBetweenCells(columns, rows, availableWidth, availableHeight);
+
+ for (var i = 0; i < columns; ++i) {
+ ++availableWidth;
+ ensureNoGapsBetweenCells(columns, rows, availableWidth, availableHeight);
+ }
+
+ for (i = 0; i < columns; ++i) {
+ ++availableHeight;
+ ensureNoGapsBetweenCells(columns, rows, availableWidth, availableHeight);
+ }
+ }
+
+ function test_cellIndexCalculation() {
+ var columns = CalendarUtils.daysInAWeek;
+ var rows = CalendarUtils.weeksOnACalendarMonth;
+
+ var availableWidth = 10 * columns;
+ var availableHeight = 10 * rows;
+ var rect = CalendarUtils.cellRectAt(0, columns, rows, availableWidth, availableHeight);
+
+ for (var row = 0; row < rows; ++row) {
+ for (var col = 0; col < columns; ++col) {
+ // Test against the center of each cell.
+ compare(CalendarUtils.cellIndexAt(col * 10 + 5, row * 10 + 5, columns, rows, availableWidth, availableHeight), row * columns + col);
+ }
+ }
+ }
+ }
+}
diff --git a/tests/auto/controls/data/tst_rangeddate.qml b/tests/auto/controls/data/tst_rangeddate.qml
new file mode 100644
index 00000000..ed58a685
--- /dev/null
+++ b/tests/auto/controls/data/tst_rangeddate.qml
@@ -0,0 +1,178 @@
+/****************************************************************************
+**
+** 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: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.2
+import QtQuick.Controls.Private 1.0
+import QtTest 1.0
+
+Item {
+ id: container
+
+ TestCase {
+ id: testcase
+ name: "Tests_RangedDate"
+ when: true
+
+ property var rangedDate
+ readonly property string importsStr: "import QtQuick.Controls 1.1; import QtQuick.Controls.Private 1.0; "
+
+ function init() {
+ rangedDate = Qt.createQmlObject(importsStr + " RangedDate {}", container, "");
+ }
+
+ function test_defaultConstruction() {
+ // rangedDate.date should be the current date.
+ compare(rangedDate.date.getTime(), new Date(Date.now()).setHours(0, 0, 0, 0));
+ }
+
+ function test_minMax() {
+ skip("QTBUG-36846");
+
+ rangedDate.minimumDate = CalendarUtils.minimumCalendarDate;
+ rangedDate.maximumDate = CalendarUtils.maximumCalendarDate;
+
+ compare(rangedDate.minimumDate.getTime(), CalendarUtils.minimumCalendarDate.getTime());
+ compare(rangedDate.maximumDate.getTime(), CalendarUtils.maximumCalendarDate.getTime());
+ }
+
+ function test_constructionPropertyOrder() {
+ // All values are valid; fine.
+ rangedDate = Qt.createQmlObject(importsStr + " RangedDate { "
+ + "date: new Date(1900, 0, 2); "
+ + "minimumDate: new Date(1900, 0, 1); "
+ + "maximumDate: new Date(1900, 0, 3); "
+ + " }", container, "");
+ compare(rangedDate.date.getTime(), new Date(1900, 0, 2).getTime());
+ compare(rangedDate.minimumDate.getTime(), new Date(1900, 0, 1).getTime());
+ compare(rangedDate.maximumDate.getTime(), new Date(1900, 0, 3).getTime());
+
+ // All values are the same; doesn't make sense, but is fine [1].
+ rangedDate = Qt.createQmlObject(importsStr + " RangedDate { "
+ + "date: new Date(1900, 0, 1);"
+ + "minimumDate: new Date(1900, 0, 1);"
+ + "maximumDate: new Date(1900, 0, 1);"
+ + " }", container, "");
+ compare(rangedDate.date.getTime(), new Date(1900, 0, 1).getTime());
+ compare(rangedDate.minimumDate.getTime(), new Date(1900, 0, 1).getTime());
+ compare(rangedDate.maximumDate.getTime(), new Date(1900, 0, 1).getTime());
+
+ // date is lower than min - should be clamped to min.
+ rangedDate = Qt.createQmlObject(importsStr + " RangedDate { "
+ + "date: new Date(1899, 0, 1);"
+ + "minimumDate: new Date(1900, 0, 1);"
+ + "maximumDate: new Date(1900, 0, 1);"
+ + " }", container, "");
+ compare(rangedDate.date.getTime(), new Date(1900, 0, 1).getTime());
+ compare(rangedDate.minimumDate.getTime(), new Date(1900, 0, 1).getTime());
+ compare(rangedDate.maximumDate.getTime(), new Date(1900, 0, 1).getTime());
+
+ // date is higher than max - should be clamped to max.
+ rangedDate = Qt.createQmlObject(importsStr + " RangedDate { "
+ + "date: new Date(1900, 0, 2);"
+ + "minimumDate: new Date(1900, 0, 1);"
+ + "maximumDate: new Date(1900, 0, 1);"
+ + " }", container, "");
+ compare(rangedDate.date.getTime(), new Date(1900, 0, 1).getTime());
+ compare(rangedDate.minimumDate.getTime(), new Date(1900, 0, 1).getTime());
+ compare(rangedDate.maximumDate.getTime(), new Date(1900, 0, 1).getTime());
+
+ // If the order of property construction is undefined (as it should be if it's declarative),
+ // then is min considered higher than max or max lower than min? Which should be changed?
+
+ // For now, max will always be the one that's changed. It will be set to min,
+ // as min may already be the largest possible date (See [1]).
+ rangedDate = Qt.createQmlObject(importsStr + " RangedDate { "
+ + "date: new Date(1900, 0, 1);"
+ + "minimumDate: new Date(1900, 0, 2);"
+ + "maximumDate: new Date(1900, 0, 1);"
+ + " }", container, "");
+ compare(rangedDate.date.getTime(), new Date(1900, 0, 2).getTime());
+ compare(rangedDate.minimumDate.getTime(), new Date(1900, 0, 2).getTime());
+ compare(rangedDate.maximumDate.getTime(), new Date(1900, 0, 2).getTime());
+
+ // [1] Do we want to enforce min and max being different? E.g. if min
+ // is (1900, 0, 1) and max is (1900, 0, 1), max should be set (1900, 0, 2).
+ // Another e.g.: if min is the largest possible date and max is the same,
+ // min should be set to the previous day, and vice versa.
+ // Currently, I'm assuming that it's fine for them to be the same,
+ // even if it means date can only ever be one value.
+ }
+
+ // "Flickering" is the effect that changing the min/max has on the date;
+ // setting the minimum to be higher than the date will force the date to
+ // be changed, and the same applies to the maximum.
+ function test_flickering() {
+ // MIN DATE MAX
+ // [ 1990 | 1995 | 1999 ]
+ rangedDate.date = new Date(1995, 0, 1);
+ compare(rangedDate.date.getTime(), new Date(1995, 0, 1).getTime());
+ rangedDate.minimumDate = new Date(1990, 0, 1);
+ compare(rangedDate.minimumDate.getTime(), new Date(1990, 0, 1).getTime());
+ rangedDate.maximumDate = new Date(1999, 0, 1);
+ compare(rangedDate.maximumDate.getTime(), new Date(1999, 0, 1).getTime());
+
+ // MIN DATE MAX
+ // [ 1996 | 1996 | 1999 ]
+ rangedDate.minimumDate = new Date(1996, 0, 1);
+ compare(rangedDate.date.getTime(), new Date(1996, 0, 1).getTime());
+ compare(rangedDate.minimumDate.getTime(), new Date(1996, 0, 1).getTime());
+
+ // MIN DATE MAX
+ // [ 1990 | 1996 | 1999 ]
+ rangedDate.minimumDate = new Date(1990, 0, 1);
+ compare(rangedDate.date.getTime(), new Date(1996, 0, 1).getTime());
+ compare(rangedDate.minimumDate.getTime(), new Date(1990, 0, 1).getTime());
+ }
+
+ function test_nullValues() {
+ var expected = new Date(rangedDate.date);
+ rangedDate.date = undefined;
+ compare(rangedDate.date.getTime(), expected.getTime());
+
+ expected = new Date(rangedDate.minimumDate);
+ rangedDate.minimumDate = undefined;
+ compare(rangedDate.minimumDate.getTime(), expected.getTime());
+
+ expected = new Date(rangedDate.maximumDate);
+ rangedDate.maximumDate = undefined;
+ compare(rangedDate.maximumDate.getTime(), expected.getTime());
+ }
+ }
+}