summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNico Vertriest <nico.vertriest@qt.io>2018-08-03 14:21:05 +0200
committerNico Vertriest <nico.vertriest@qt.io>2018-09-26 10:10:15 +0000
commit1df70118583e069bde41d03bc9753cef949b3e39 (patch)
treedf65200e8588abe7fbca4db64f9dab517094f374
parentfe91a75b3eb615b74fd28a5c6ad403020005264b (diff)
downloadqtdoc-1df70118583e069bde41d03bc9753cef949b3e39.tar.gz
Doc: tutorial Get Started with Qt Quick
Task-number: QTBUG-68739 Change-Id: Ib14e4eb4c20583af2be9198539077f1be5ae471a Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Venugopal Shivashankar <Venugopal.Shivashankar@qt.io>
-rw-r--r--doc/config/qtdoc.qdocconf2
-rw-r--r--doc/src/getting-started/gettingstartedqml.qdoc1196
-rw-r--r--doc/src/images/addalarms.pngbin0 -> 5231 bytes
-rw-r--r--doc/src/images/alarms2.pngbin0 -> 24310 bytes
-rw-r--r--doc/src/images/alarms3.pngbin0 -> 14194 bytes
-rw-r--r--doc/src/images/detailscreen.pngbin0 -> 10657 bytes
-rw-r--r--doc/src/images/mainscreen.pngbin0 -> 7056 bytes
-rw-r--r--examples/tutorials/alarms/AlarmDelegate.qml142
-rw-r--r--examples/tutorials/alarms/AlarmDialog.qml168
-rw-r--r--examples/tutorials/alarms/AlarmModel.qml152
-rw-r--r--examples/tutorials/alarms/TumblerDelegate.qml62
-rw-r--r--examples/tutorials/alarms/alarms.pro29
-rw-r--r--examples/tutorials/alarms/main.cpp65
-rw-r--r--examples/tutorials/alarms/main.qml86
-rw-r--r--examples/tutorials/alarms/qml.qrc10
-rw-r--r--examples/tutorials/alarms/qtquickcontrols2.conf5
16 files changed, 915 insertions, 1002 deletions
diff --git a/doc/config/qtdoc.qdocconf b/doc/config/qtdoc.qdocconf
index 623cf0d6..5a346f4f 100644
--- a/doc/config/qtdoc.qdocconf
+++ b/doc/config/qtdoc.qdocconf
@@ -88,7 +88,7 @@ exampledirs += \
excludedirs += \
../src/snippets
-examplesinstallpath = demos
+examplesinstallpath =
qhp.projects = QtDoc
diff --git a/doc/src/getting-started/gettingstartedqml.qdoc b/doc/src/getting-started/gettingstartedqml.qdoc
index cd6cedf1..f66f1a01 100644
--- a/doc/src/getting-started/gettingstartedqml.qdoc
+++ b/doc/src/getting-started/gettingstartedqml.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
@@ -26,1063 +26,257 @@
****************************************************************************/
/*!
- \page gettingstartedqml.html
+ \example tutorials/gettingstartedqtquick
\title Getting Started Programming with Qt Quick
+ \brief A tutorial for Qt Quick based on an alarms application
+
+ This tutorial shows how to develop a simple alarm application as
+ an introduction to Qt Quick and Qt Quick Controls2.
+
+ This application is similar to the alarm application usually
+ found on an Android phone. Its features let you enter, edit,
+ or delete alarms. An alarm can trigger on a given date, and you
+ can set it to repeat on a series of subsequent days.
+
+ The main screen shows the list of saved alarms:
+
+ \image mainscreen.png "Alarms application"
+
+ The detail screen lets you edit or delete existing alarms:
+
+ \image detailscreen.png "Detail screen"
+
+ The dialog screen is used for adding new alarms. It pops up
+ when you click on the "+" RoundButton on the bottom of the main
+ screen:
+
+ \image addalarms.png "Add alarms"
+
+ The source files are located in the qtdoc repository.
+ You can either fetch the Qt 5 sources from the Qt Project,
+ or install them as part of Qt 5. The application is also available
+ in the example list of Qt Creator's Welcome mode.
+
+ \section1 Creating the Alarms Project
+
+ This section shows how to create the project in Qt Creator. It discusses
+ the files generated automatically by Qt Creator, and the two files
+ the programmer has to create in Qt Creator or some other editor.
+ The latter two files are included with the source code for this
+ tutorial.
+
+ \section1 Qt Creator
- Welcome to the world of \b QML, the declarative UI language. In this Getting
- Started guide, we will create a simple text editor application using QML.
- After reading this guide, you should be ready to develop your own applications
- using QML and Qt C++.
+ Setting up a new project in Qt Creator is aided by a wizard that
+ guides you step-by-step through the project creation process. The
+ wizard prompts you to enter the settings needed for that particular
+ type of project and creates the project for you.
+
+ To create the Alarms project, select \uicontrol{File} >
+ \uicontrol{New File or Project} > \uicontrol{Application} >
+ \uicontrol{Qt Quick Application - Empty} > \uicontrol{Choose}.
+ Type "alarms" in the \b{Name} field, and follow the instructions
+ of the wizard.
- \section1 QML to Build User Interfaces
+ \image alarms2.png "Qt Creator New File or Project dialog"
+
+ \image alarms3.png "Project Location"
- The application we are building is a simple text editor that will load, save,
- and perform some text manipulation. This guide will consist of two parts. The
- first part will involve designing the application layout and behaviors using
- declarative language in QML. For the second part, file loading and saving will
- be implemented using Qt C++. Using
- \l {The Meta-Object System}{Qt's Meta-Object System}, we can expose C++ functions
- as properties that \l{QML Object Types}{QML object types} can use. Utilizing QML and Qt C++, we can
- efficiently decouple the interface logic from the application logic.
+ The Qt Quick application wizard creates a project that contains
+ the following source files:
- \image qml-texteditor5_editmenu.png
+ \table
+ \header
+ \li Source file
+ \li Purpose
+ \row
+ \li alarms.pro
+ \li The project file
+ \row
+ \li main.cpp
+ \li The main C++ code file for the application.
+ \row
+ \li qml.qrc
+ \li The resource file, which contains the names of the
+ source files, except main.cpp and the project file.
+ \endtable
- The complete source code is in the \c{examples/quick/tutorials/gettingStartedQml}
- directory. If you wish to see how the finalized application looks like, you
- can skip to chapter \l {Running the Text Editor}.
+ The wizard generates the code in the main.cpp file below.
+ This code block enables High DPI scaling and declares \c app
+ and \c engine. The engine then loads our main QML file.
- The C++ portion of this tutorial assumes that the reader possesses basic knowledge of
- Qt's compilation procedures.
+ \quotefromfile tutorials/alarms/main.cpp
+ \skipto main
+ \printuntil }
- Tutorial chapters:
- \list 1
- \li \l {Defining a Button and a Menu}
- \li \l {Implementing a Menu Bar}
- \li \l {Building a Text Editor}
- \li \l {Decorating the Text Editor}
- \li \l {Extending QML using Qt C++}
- \endlist
+ \section1 Additional source files
- Information about QML, such as syntax and features, is included in the
- \l{The QML Reference}.
+ \table
+ \header
+ \li Source file
+ \li Purpose
+ \row
+ \li \c qtquickcontrols2.conf
+ \li Selects the \c Material style with the \c Dark theme.
+ \row
+ \li \c main.qml
+ \li The QML code that links AlarmDialog.qml, AlarmModel.qml,
+ AlarmDelegate.qml and TumblerDelegate.qml
+ \row
+ \li \c AlarmDialog.qml
+ \li Defines the dialog for adding new alarms.
+ \row
+ \li \c AlarmDelegate.qml
+ \li Defines the layout of the main screen of the app.
+ \row
+ \li \c AlarmModel.qml
+ \li Defines the ListModel used for storing the alarms' data.
+ \row
+ \li \c TumblerDelegate.qml
+ \li Defines the graphical layout of the Tumblers
+ \endtable
- \section1 Defining a Button and a Menu
- \section2 Basic Component - a Button
+ \section2 \c qtquickcontrols2.conf
- We start our text editor by building a button. Functionally, a button has a mouse
- sensitive area and a label. Buttons perform actions when a user presses the button.
+ The following snippet shows how to set the \c Dark theme in the
+ \c Material style:
- In QML, the basic visual item is the \l Rectangle type. The
- \c Rectangle \l{QML Object Types}{QML object type} has
- \l{Property Binding}{QML properties} to control its appearance and location.
+ \quotefile tutorials/alarms/qtquickcontrols2.conf
- \code
- import QtQuick 2.3
-
- Rectangle {
- id: simpleButton
- color: "grey"
- width: 150; height: 75
-
- Text {
- id: buttonLabel
- anchors.centerIn: parent
- text: "button label"
- }
- }
- \endcode
-
- First, the \c {import QtQuick 2.3} statement allows the
- \l{Prototyping with qmlscene}{qmlscene} tool to import the QML types we will later use.
- This line must exist for every QML file. Notice that the version of Qt modules is
- included in the import statement.
-
- This simple rectangle has a unique identifier, \c simpleButton, which is bound to the
- \c id property. The \c Rectangle object's properties are bound to values by listing the
- property, followed by a colon, then the value. In the code sample, the color \c grey
- is bound to the Rectangle's \c color property. Similarly, we bind the \c width
- and \c height of the Rectangle.
-
- The \l Text type is a non-editable text field. We name this object \c buttonLabel. To set
- the string content of the Text field, we bind a value to the \c text property. The label
- is contained within the Rectangle and in order to center it in the middle, we assign the
- \c anchors of the Text object to its parent, which is called \c simpleButton. Anchors may
- bind to other items' anchors, allowing layout assignments simpler.
-
- We shall save this code as \c SimpleButton.qml. Running \c qmlscene with the file as the
- argument will display the grey rectangle with a text label.
-
- \image qml-texteditor1_simplebutton.png
-
- To implement the button click functionality, we can use QML's event handling. QML's event
- handling is very similar to \l {Signals & Slots}{Qt's signal and slot} mechanism. Signals
- are emitted and the connected slot is called.
-
- \code
- Rectangle {
- id: simpleButton
- ...
-
- MouseArea {
- id: buttonMouseArea
-
- // Anchor all sides of the mouse area to the rectangle's anchors
- anchors.fill: parent
- // onClicked handles valid mouse button clicks
- onClicked: console.log(buttonLabel.text + " clicked")
- }
- }
- \endcode
-
- We include a \l MouseArea object in our simpleButton. \c MouseArea objects describe
- the interactive area where mouse movements are detected. For our button, we anchor the
- whole \c MouseArea to its parent, which is \c simpleButton. The \c anchors.fill syntax is
- one way of accessing a specific property called \c fill inside a group of properties
- called \c anchors. QML uses \l {Positioning with Anchors}{anchor-based layouts} where
- items can anchor to another item, creating robust layouts.
-
- The \c MouseArea has many signal handlers that are called during mouse movements within
- the specified \c MouseArea boundaries. One of them is \c onClicked and it is called
- whenever the acceptable mouse button is clicked, the left click being the default. We
- can bind actions to the onClicked handler. In our example, \c console.log() outputs text
- whenever the mouse area is clicked. The function \c console.log() is a useful tool for
- debugging purposes and for outputting text.
-
- The code in \c SimpleButton.qml is sufficient to display a button on the screen and
- output text whenever it is clicked with a mouse.
-
- \code
- Rectangle {
- id: button
- ...
-
- property color buttonColor: "lightblue"
- property color onHoverColor: "gold"
- property color borderColor: "white"
-
- signal buttonClick()
-
- onButtonClick: {
- console.log(buttonLabel.text + " clicked")
- }
-
- MouseArea{
- id: buttonMouseArea
- onClicked: buttonClick()
- hoverEnabled: true
- onEntered: parent.border.color = onHoverColor
- onExited: parent.border.color = borderColor
- }
-
- // Determines the color of the button by using the conditional operator
- color: buttonMouseArea.pressed ? Qt.darker(buttonColor, 1.5) : buttonColor
- }
- \endcode
-
- A fully functioning button is in \c Button.qml. The code snippets in this article
- have some code omitted, denoted by ellipses because they were either introduced
- earlier in the previous sections or irrelevant to the current code discussion.
-
- Custom properties are declared using the \c {property type name} syntax. In the
- code, the property \c buttonColor, of type \c color, is declared and bound to
- the value \c{"lightblue"}. The \c buttonColor is later used in a conditional
- operation to determine the button's fill color. Note that property value
- assignment is possible using the \c= equals sign, in addition to value binding
- using the \c : colon character. Custom properties allow internal items to be
- accessible outside of the Rectangle's scope. There are basic
- \l{QML Basic Types}{QML types} such as \c int, \c string, \c real, as well as
- a type called \c variant.
-
- By binding the \c onEntered and \c onExited signal handlers to colors, the
- button's border will turn yellow when the mouse hovers above the button and
- reverts the color when the mouse exits the mouse area.
-
- A \c buttonClick() signal is declared in \c Button.qml by placing the \c signal
- keyword in front of the signal name. All signals have their handlers automatically
- created, their names starting with \c on. As a result, the \c onButtonClick is
- \c buttonClick's handler. The \c onButtonClick is then assigned an action to
- perform. In our button example, the \c onClicked mouse handler will simply call
- \c onButtonClick, which displays a text. The \c onButtonClick enables outside
- objects to access the \c {Button}'s mouse area easily. For example, items may
- have more than one \c MouseArea declarations and a \c buttonClick signal can
- make the distinction between the several \c MouseArea signal handlers better.
-
- We now have the basic knowledge to implement items in QML that can handle
- basic mouse movements. We created a \c Text label inside a \c Rectangle,
- customized its properties, and implemented behaviors that respond to mouse
- movements. This idea of creating QML objects within objects is repeated
- throughout the text editor application.
-
- This button is not useful unless used as a component to perform an action.
- In the next section, we will soon create a menu containing several of these
- buttons.
-
- \image qml-texteditor1_button.png
-
- \section2 Creating a Menu Page
-
- Up to this stage, we covered how to create objects and assign behaviors inside
- a single QML file. In this section, we will cover how to import QML types and how
- to reuse some of the created components to build other components.
-
- Menus display the contents of a list, each item having the ability to perform an action.
- In QML, we can create a menu in several ways. First, we will create a menu containing
- buttons which will eventually perform different actions. The menu code is in
- \c FileMenu.qml.
-
- \code
- import QtQuick 2.3 // Import the main Qt QML module
- import "folderName" // import the contents of a folder
- import "script.js" as Script // Import a Javascript file and name it as Script
- \endcode
-
- The syntax shown above shows how to use the \c import keyword. This is required to
- use JavaScript files, or QML files that are not within the same directory. Since
- \c Button.qml is in the same directory as \c FileMenu.qml, we do not need to import
- the \c Button.qml file to use it. We can directly create a \c Button object by declaring
- \c Button{}, similar to a \c Rectangle{} declaration.
-
- \code
- In FileMenu.qml:
-
- Row {
- anchors.centerIn: parent
- spacing: parent.width / 6
-
- Button {
- id: loadButton
- buttonColor: "lightgrey"
- label: "Load"
- }
- Button {
- buttonColor: "grey"
- id: saveButton
- label: "Save"
- }
- Button {
- id: exitButton
- label: "Exit"
- buttonColor: "darkgrey"
-
- onButtonClick: Qt.quit()
- }
- }
- \endcode
-
- In \c FileMenu.qml, we declare three \c Button objects. They are declared
- inside a \l Row type, a positioner that will position its children
- along a vertical row. The \c Button declaration resides in Button.qml,
- which is the same as the one we used in the previous section.
- New property bindings can be declared within the newly created buttons,
- effectively overwriting the properties set in \c Button.qml. The button
- called \c exitButton will quit and close the window when it is clicked.
- Note that the signal handler \c onButtonClick in \c Button.qml will be
- called in addition to the \c onButtonClick handler in \c exitButton.
-
- \image qml-texteditor1_filemenu.png
-
- The \c Row declaration is declared in a \c Rectangle, creating a rectangle
- container for the row of buttons. This additional rectangle creates an indirect
- way of organizing the row of buttons inside a menu.
-
- The declaration of the edit menu is very similar at this stage. The menu has
- buttons that have the labels: \c Copy, \c Paste, and \c {Select All}.
-
- \image qml-texteditor1_editmenu.png
-
- Armed with our knowledge of importing and customizing previously made
- components, we may now combine these menu pages to create a menu bar,
- consisting of buttons to select the menu, and look at how we may structure
- data using QML.
-
- \section1 Implementing a Menu Bar
-
- Our text editor application will need a way to display menus using a menu bar.
- The menu bar will switch the different menus and the user can choose which menu
- to display. Menu switching implies that the menus need more structure than
- merely displaying them in a row. QML uses models and views to structure data
- and display the structured data.
-
- \section2 Using Data Models and Views
-
- QML has different \l{QML Data Models}{data views} that display
- \l{QML Data Models}{data models}. Our menu bar will display the menus in a list,
- with a header that displays a row of menu names. The list of menus are declared
- inside a \l ObjectModel. The \c ObjectModel type contains items that already are
- displayable, such as \c Rectangle objects. Other model types, like the
- \l ListModel type, need a delegate to display their data.
-
- We declare two visual items in the \c menuListModel, the \c FileMenu and the
- \c EditMenu. We customize the two menus and display them in a \l ListView.
- The \c MenuBar.qml file contains the QML declarations and a simple edit menu is
- defined in \c EditMenu.qml.
-
- \code
- ObjectModel {
- id: menuListModel
-
- FileMenu {
- width: menuListView.width
- height: menuBar.height
- color: fileColor
- }
-
- EditMenu {
- color: editColor
- width: menuListView.width
- height: menuBar.height
- }
- }
- \endcode
-
- The \l ListView type will display a model according to a delegate. The delegate
- can display the model items in a \c Row object or in a grid. Our \c menuListModel
- already has visible items, therefore, we do not need to declare a delegate.
-
- \code
- ListView {
- id: menuListView
-
- // Anchors are set to react to window anchors
- anchors.fill: parent
- anchors.bottom: parent.bottom
- width: parent.width
- height: parent.height
-
- // The model contains the data
- model: menuListModel
-
- // Control the movement of the menu switching
- snapMode: ListView.SnapOneItem
- orientation: ListView.Horizontal
- boundsBehavior: Flickable.StopAtBounds
- flickDeceleration: 5000
- highlightFollowsCurrentItem: true
- highlightMoveDuration: 240
- highlightRangeMode: ListView.StrictlyEnforceRange
- }
- \endcode
-
- Additionally, \c ListView inherits from \l Flickable, making the list respond
- to mouse drags and other gestures. The last portion of the code above sets
- \c Flickable properties to create the desired flicking movement to our view.
- In particular, the property \c highlightMoveDuration changes the duration of
- the flick transition. A higher \c highlightMoveDuration value results in
- slower menu switching.
-
- The \c ListView maintains the model items through an \c index and each visual
- item in the model is accessible through the \c index, in the order of the
- declaration. Changing the \c currentIndex effectively changes the highlighted
- item in the \c ListView. The header of our menu bar exemplifies this effect.
- There are two buttons in a row, both changing the current menu when clicked.
- The \c fileButton changes the current menu to the file menu when clicked,
- the \c index being \c 0 because \c FileMenu is declared first in the
- \c menuListModel. Similarly, the \c editButton will change the current
- menu to the \c EditMenu when clicked.
-
- The \c labelList rectangle has \c z value of \c 1, denoting that it is displayed
- at the front of the menu bar. Items with higher \c z values are displayed in front
- of items with lower \c z values. The default \c z value is \c 0.
-
- \code
- Rectangle {
- id: labelList
- ...
- z: 1
-
- Row {
- anchors.centerIn: parent
- spacing: 40
-
- Button {
- label: "File"
- id: fileButton
- ...
- onButtonClick: menuListView.currentIndex = 0
- }
-
- Button {
- id: editButton
- label: "Edit"
- ...
- onButtonClick: menuListView.currentIndex = 1
- }
- }
- }
- \endcode
-
- The menu bar we just created can be flicked to access the menus or by clicking
- on the menu names at the top. Switching menu screens feel intuitive and responsive.
-
- \image qml-texteditor2_menubar.png
-
- \section1 Building a Text Editor
-
- \section2 Declaring a TextArea
-
- Our text editor is not a text editor if it didn't contain an editable text area.
- QML's \l TextEdit type allows the declaration of a multi-line editable text area.
- \c TextEdit is different from the \l Text type, which doesn't allow the user to
- directly edit the text.
-
- \code
- TextEdit {
- id: textEditor
- anchors.fill: parent
- width: parent.width
- height: parent.height
- color: "midnightblue"
- focus: true
-
- wrapMode: TextEdit.Wrap
-
- onCursorRectangleChanged: flickArea.ensureVisible(cursorRectangle)
- }
- \endcode
-
- The editor has its font \c color property set and \c wrapMode set to wrap the text.
- The \c TextEdit area is inside a flickable item that will scroll the text if the
- text cursor is outside the visible area. The function \c ensureVisible() will
- check if the cursor rectangle is outside the visible boundaries and move the
- text area accordingly. QML uses Javascript syntax for its scripts, and as previously
- mentioned, Javascript files can be imported and used within a QML file.
-
- \code
- function ensureVisible(r) {
- if (contentX >= r.x)
- contentX = r.x;
- else if (contentX + width <= r.x + r.width)
- contentX = r.x + r.width - width;
- if (contentY >= r.y)
- contentY = r.y;
- else if (contentY + height <= r.y + r.height)
- contentY = r.y + r.height - height;
- }
- \endcode
-
- \section2 Combining Components for the Text Editor
-
- We are now ready to create the layout of our text editor using QML. The text
- editor has two components, the menu bar we created and the text area. QML allows
- us to reuse components, therefore making our code simpler, by importing components
- and customizing when necessary. Our text editor splits the window into two;
- one-third of the screen is dedicated to the menu bar and two-thirds of the screen
- displays the text area. The menu bar is displayed in front of any other objects.
-
- \code
- Rectangle {
- id: screen
- width: 1000
- height: 1000
-
- // The screen is partitioned into the MenuBar and TextArea.
- // One-third of the screen is assigned to the MenuBar
- property int partition: height / 3
-
- MenuBar {
- id: menuBar
- height: partition
- width: parent.width
- z: 1
- }
-
- TextArea {
- id: textArea
- anchors.bottom: parent.bottom
- y: partition
- color: "white"
- width: parent.width
- height: partition * 2
- }
- }
- \endcode
-
- By importing reusable components, our \c TextEditor code looks much simpler.
- We can then customize the main application, without worrying about properties
- that already have defined behaviors. Using this approach, application layouts
- and UI components can be created easily.
-
- \image qml-texteditor3_texteditor.png
-
- \section1 Decorating the Text Editor
- \section2 Implementing a Drawer Interface
-
- Our text editor looks simple and we need to decorate it. Using QML, we can declare
- transitions and animate our text editor. Our menu bar is occupying one-third of the
- screen and it would be nice to have it only appear when we want it.
-
- We can add a drawer interface, that will contract or expand the menu bar when clicked.
- In our implementation, we have a thin rectangle that responds to mouse clicks. The
- \c drawer, as well as the application, has two sates: the "drawer is open" state and
- the "drawer is closed" state. The \c drawer item is a strip of rectangle with a small
- height. There is a nested \l Image object declaring that an arrow icon will
- be centered inside the drawer. The drawer assigns a state to the whole application,
- with the identifier \c screen, whenever a user clicks the mouse area.
-
- \code
- Rectangle {
- id: drawer
- height: 15
-
- Image {
- id: arrowIcon
- source: "images/arrow.png"
- anchors.horizontalCenter: parent.horizontalCenter
- }
-
- MouseArea {
- id: drawerMouseArea
- anchors.fill: parent
-
- onClicked: {
- if (screen.state == "DRAWER_CLOSED")
- screen.state = "DRAWER_OPEN"
- else if (screen.state == "DRAWER_OPEN")
- screen.state = "DRAWER_CLOSED"
- }
- ...
- }
- }
- \endcode
-
- A state is simply a collection of configurations and it is declared with the
- \l State type. A list of states can be listed and bound to the \c states property.
- In our application, the two states are called \c DRAWER_CLOSED and \c DRAWER_OPEN.
- Item configurations are declared in \l PropertyChanges objects. In the
- \c DRAWER_OPEN state, there are four items that will receive property changes.
- The first target, \c menuBar, will change its \c y property to \c 0. Similarly,
- the \c textArea will lower to a new position when the state is \c DRAWER_OPEN.
- The \c textArea, the \c drawer, and the drawer's icon will undergo property
- changes to meet the current state.
-
- \code
- states:[
- State {
- name: "DRAWER_OPEN"
- PropertyChanges { target: menuBar; y: 0 }
- PropertyChanges { target: textArea; y: partition + drawer.height }
- PropertyChanges { target: drawer; y: partition }
- PropertyChanges { target: arrowIcon; rotation: 180 }
- },
- State {
- name: "DRAWER_CLOSED"
- PropertyChanges { target: menuBar; y: -height; }
- PropertyChanges { target: textArea; y: drawer.height; height: screen.height - drawer.height }
- PropertyChanges { target: drawer; y: 0 }
- PropertyChanges { target: arrowIcon; rotation: 0 }
- }
- ]
- \endcode
-
- State changes are abrupt and needs smoother transitions. Transitions between states
- are defined using the \l Transition type, which can then bind to the item's
- \c transitions property. Our text editor has a state transition whenever the state
- changes to either \c DRAWER_OPEN or \c DRAWER_CLOSED. Importantly, the transition
- needs a \c from and a \c to state but for our transitions, we can use the wild card
- \c * symbol to denote that the transition applies to all state changes.
-
- During transitions, we can assign animations to the property changes. Our \c menuBar
- switches position from \c {y: 0} to \c {y: -partition} and we can animate this
- transition using the \l NumberAnimation type. We declare that the targets'
- properties will animate for a certain duration of time and using a certain easing
- curve. An easing curve controls the animation rates and interpolation behavior
- during state transitions. The easing curve we chose is
- \l{PropertyAnimation::easing.type}{\c Easing.OutExpo}, which slows the movement near
- the end of the animation. For more information, see QML's
- \l {Animation and Transitions in Qt Quick}{animation} article.
-
- \code
- transitions: [
- Transition {
- to: "*"
- NumberAnimation { target: textArea; properties: "y, height"; duration: 100; easing.type:Easing.OutExpo }
- NumberAnimation { target: menuBar; properties: "y"; duration: 100; easing.type: Easing.OutExpo }
- NumberAnimation { target: drawer; properties: "y"; duration: 100; easing.type: Easing.OutExpo }
- }
- ]
- \endcode
-
- Another way of animating property changes is by declaring a \l Behavior
- type. A transition only works during state changes and \c Behavior can set an
- animation for a general property change. In the text editor, the arrow has a
- \c NumberAnimation animating its \c rotation property whenever the property changes.
-
- In \c {TextEditor.qml}:
-
- \code
- Behavior {
- NumberAnimation { property: "rotation"; easing.type: Easing.OutExpo }
- }
- \endcode
-
- Going back to our components with knowledge of states and animations, we can improve
- the appearances of the components. In \c Button.qml, we can add \c color and \c scale
- property changes when the button is clicked. Color types are animated using
- \l ColorAnimation and numbers are animated using \l NumberAnimation. The
- \c {on propertyName} syntax displayed below is helpful when targeting a single property.
-
- In \c {Button.qml}:
- \code
- ...
-
- color: buttonMouseArea.pressed ? Qt.darker(buttonColor, 1.5) : buttonColor
- Behavior on color { ColorAnimation{ duration: 55 } }
-
- scale: buttonMouseArea.pressed ? 1.1 : 1.0
- Behavior on scale { NumberAnimation{ duration: 55 } }
- \endcode
-
- Additionally, we can enhance the appearances of our QML components by adding color
- effects such as gradients and opacity effects. Declaring a \l Gradient object will
- override the \c color property. You may declare a color in the gradient using the
- \l GradientStop type. The gradient is positioned using a scale, between \c 0.0 and
- \c 1.0.
-
- In \c {MenuBar.qml}:
-
- \code
- gradient: Gradient {
- GradientStop { position: 0.0; color: "#8C8F8C" }
- GradientStop { position: 0.17; color: "#6A6D6A" }
- GradientStop { position: 0.98; color: "#3F3F3F" }
- GradientStop { position: 1.0; color: "#0e1B20" }
- }
- \endcode
-
- This gradient is used by the menu bar to display a gradient simulating depth.
- The first color starts at \c 0.0 and the last color is at \c 1.0.
-
- \section3 Where to Go from Here
+ \section2 \c main.qml
- We are finished building the user interface of a very simple text editor.
- Going forward, the user interface is complete, and we can implement the
- application logic using regular Qt and C++. QML works nicely as a prototyping
- tool, separating the application logic away from the UI design.
+ \c mainWindow, an ApplicationWindow QML type, is the root item in
+ this app.
- \image qml-texteditor4_texteditor.png
+ \quotefromfile tutorials/alarms/main.qml
+ \skipto ApplicationWindow
+ \printuntil visible
- \section2 Extending QML using Qt C++
+ The ListView \c alarmListView combines the data from \c alarmModel
+ with the layout defined in \c alarmDelegate.
- Now that we have our text editor layout, we may now implement the text editor
- functionalities in C++. Using QML with C++ enables us to create our application
- logic using Qt. We can create a QML context in a C++ application using
- \l {Integrating QML and C++}{Qt's Quick classes} and display the QML
- types using a QQuickView. Alternatively, we can export our C++ code into
- an extension plugin, and make it accessible to QML as a new
- \l {Identified Modules}{identified module}.
- When launching QML files with \l {Prototyping with qmlscene}{qmlscene},
- we only need to ensure our module is found under one of the
- \l {QML Import Path}{import paths} the QML engine searches for modules
- to import. For our application we shall the latter approach. This way, we can
- load the QML file directly with \c qmlscene instead of running an executable.
+ \quotefromfile tutorials/alarms/main.qml
+ \skipuntil visible
+ \printto RoundButton
- \section3 Exposing C++ Classes to QML
+ New alarms can be added by clicking RoundButton \c addAlarmButton.
+ Clicking it opens a \l {Dialog: QtQuickControls2}{dialog} screen \c alarmDialog.
- We will be implementing file loading and saving using Qt and C++. C++ classes
- and functions can be used in QML by registering them. They also needs to be
- compiled as a Qt plugin and then exposed as a QML module.
+ \printuntil alarmDialog.open
+ \printuntil alarmListView.model
+ \printline }
- For our application, we need to create the following items:
- \list 1
- \li \c Directory class that will handle directory related operations
- \li \c File class which is a QObject, simulating the list of files in a directory
- \li A plugin class that will register the classes to the QML context
- \li Qt project file that will compile the plugin
- \li A \l {Module Definition qmldir Files}{module definition qmldir file} that
- defines the identifier (import URI) and content (in this case, our plugin)
- to be made available by the QML module
- \endlist
-
- \note Since Qt 5.1, \l{Qt Quick Dialogs} module provides a file dialog component
- that you can use for choosing files from the local file system. For illustrative
- purposes, we write our own in this tutorial.
-
- \section3 Building a Qt Plugin
-
- To build a plugin, we need to set the following in a Qt project file. First,
- the necessary sources, headers, and Qt modules need to be added into our
- project file. All the C++ code and project files are in the \c filedialog
- directory.
-
- In \c {filedialog.pro}:
-
- \code
- TEMPLATE = lib
- CONFIG += qt plugin
- QT += qml
-
- DESTDIR += ../imports/FileDialog
- OBJECTS_DIR = tmp
- MOC_DIR = tmp
-
- TARGET = filedialogplugin
-
- HEADERS += \
- directory.h \
- file.h \
- dialogPlugin.h
-
- SOURCES += \
- directory.cpp \
- file.cpp \
- dialogPlugin.cpp
- \endcode
+ \section2 \c AlarmDialog.qml
- In particular, we link the project with the \c qml module and configure it as a
- \c plugin, using a \c lib template. We shall put the compiled plugin into the
- parent's \c {imports/FileDialog} directory.
+ This dialog screen has a RowLayout with a \l {Tumbler} each for hours
+ and minutes, and another RowLayout with a Tumbler each for day, month,
+ and year.
- \section3 Registering a Class into QML
+ \quotefromfile tutorials/alarms/AlarmDialog.qml
+ \skipto contentItem
+ \printuntil "model: years"
+ \printuntil }
- In \c {dialogPlugin.h}:
+ If you click on \b OK in the dialog, the entered data will be
+ added to \c alarmModel:
- \code
- #include <QtQml/QQmlExtensionPlugin>
+ \quotefromfile tutorials/alarms/AlarmDialog.qml
+ \skipto onAccepted
+ \printuntil onRejected
- class DialogPlugin : public QQmlExtensionPlugin
- {
- Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.QmlExtensionPlugin.FileDialog")
+ \section2 \c AlarmDelegate.qml
- public:
- // registerTypes is inherited from QQmlExtensionPlugin
- void registerTypes(const char *uri);
- };
+ Each alarm in the main screen is an ItemDelegate. The ItemDelegate
+ \c root contains all fields on the main screen and the detail
+ screen. The detail screen's fields are only visible after an alarm
+ has been clicked on, i.e. when \c root.checked is \c true.
- \endcode
+ \quotefromfile tutorials/alarms/AlarmDelegate.qml
+ \skipto ItemDelegate
+ \printuntil /^\}/
- We need to export the plugin using the \l {How To Create Qt Plugins}{Q_PLUGIN_METADATA} macro.
- Note that in our \c dialogPlugin.h file, we have the \l Q_OBJECT
- macro at the top of our class. As well, we need to run \c qmake on the project
- file to generate the necessary meta-object code.
+ \section2 \c AlarmModel.qml
- Our plugin class, \c {DialogPlugin}, is a subclass of \l{QQmlExtensionPlugin}.
- We need to implement the inherited function,
- \l {QQmlExtensionPlugin::registerTypes()}{registerTypes()}.
+ This QML file contains the definition of \c alarmModel, the ListModel
+ that manages the alarm data.
- In \c {DialogPlugin.cpp}:
+ It creates five \l {ListElement}{ListElements} with example alarms.
- \code
- #include "dialogPlugin.h"
- #include "directory.h"
- #include "file.h"
- #include <QtQml>
-
- void DialogPlugin::registerTypes(const char *uri)
- {
- // Register the class Directory into QML as a "Directory" type version 1.0
- // @uri FileDialog
- qmlRegisterType<Directory>(uri, 1, 0, "Directory");
- qmlRegisterType<File>(uri, 1, 0, "File");
- }
- \endcode
+ \quotefromfile tutorials/alarms/AlarmModel.qml
+ \skipto import
+ \printuntil /^\}/
- The \c registerTypes() function registers our File and Directory classes into
- QML. This function needs the class name for its template, a major version number,
- a minor version number, and a name for our classes.
- A \c {// @uri <module identifier>} comment allows Qt Creator to be aware of the
- registered types when editing QML files that import this module.
+ \section2 TumblerDelegate.qml
- \section3 Creating QML Properties in a C++ Class
+ TumblerDelegate defines the graphical properties of the Tumblers.
- We can create QML types and properties using C++ and
- \l {The Meta-Object System}{Qt's Meta-Object System}. We can implement
- properties using slots and signals, making Qt aware of these properties.
- These properties can then be used in QML.
+ \quotefromfile tutorials/alarms/TumblerDelegate.qml
+ \skipto import
+ \printuntil /^\}/
- For the text editor, we need to be able to load and save files. Typically,
- these features are contained in a file dialog. Fortunately, we can use
- \l QDir, \l QFile, and \l QTextStream to implement directory reading and
- input/output streams.
+ \section1 Entering new alarms
- \code
- class Directory : public QObject {
- Q_OBJECT
-
- Q_PROPERTY (int filesCount READ filesCount CONSTANT)
- Q_PROPERTY (QString filename READ filename WRITE setFilename NOTIFY filenameChanged)
- Q_PROPERTY (QString fileContent READ fileContent WRITE setFileContent NOTIFY fileContentChanged)
- Q_PROPERTY (QQmlListProperty<File> files READ files CONSTANT)
- ...
- \endcode
+ At the bottom of the startup screen, you can see a Button for adding
+ alarms. Click it to open the \b {Add new alarm} dialog.
- The \c Directory class uses Qt's Meta-Object System to register properties it
- needs to accomplish file handling. The \c Directory class is exported as a plugin
- and is useable in QML as the \c Directory type. Each of the listed properties
- using the \l Q_PROPERTY() macro is a QML property.
+ \quotefromfile tutorials/alarms/main.qml
+ \skipto RoundButton
+ \printto AlarmDialog
- The \l {Q_PROPERTY()}{Q_PROPERTY} declares a property as well as its read and
- write functions into Qt's Meta-Object System. For example, the \c filename
- property, of type \l QString, is readable using the \c filename()
- function and writable using the function \c setFilename(). Additionally, there
- is a signal associated to the filename property called \c {filenameChanged()},
- which is emitted whenever the property changes. The read and write functions
- are declared as \c public in the header file.
+ The dialog for new alarms:
- Similarly, we have the other properties declared according to their uses. The
- \c filesCount property indicates the number of files in a directory. The filename
- property is set to the currently selected file's name and the loaded/saved file
- content is stored in \c fileContent property.
+ \image addalarms.png "Add alarms"
- \code
- Q_PROPERTY(QQmlListProperty<File> files READ files CONSTANT)
- \endcode
+ All fields are entered using \l {Tumbler} QML types. If you press \c OK,
+ the values selected in the Tumblers are written to \c alarmModel.
- The \c files list property is a list of all the filtered files in a directory.
- The \c Directory class is implemented to filter out invalid text files; only
- files with a \c .txt extension are valid. Further, \l{QList}s can be
- used in QML files by declaring them as a QQmlListProperty in C++.
- The templated object needs to inherit from a QObject, therefore,
- the \c File class must also inherit from QObject. In the \c Directory class,
- the list of \c File objects is stored in a QList called \c m_fileList.
+ \quotefromfile tutorials/alarms/AlarmDialog.qml
+ \skipto contentItem
+ \printuntil " }"
- \code
- class File : public QObject{
+ \section1 Editing alarms
- Q_OBJECT
- Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
+ If you click on a particular alarm, you can edit it in the detail
+ screen.
- ...
- };
- \endcode
+ \image detailscreen.png
- The properties can then be used in QML as part of the \c Directory object's
- properties. Note that we do not have to create an identifier \c id property
- in our C++ code.
+ Clicking on an alarm sets \c root.checked to \c true, which makes
+ visible the fields of the detail screen.
\code
- Directory {
- id: directory
-
- filesCount
- filename
- fileContent
- files
-
- files[0].name
- }
+ visible: root.checked
\endcode
- Because QML uses Javascript's syntax and structure, we can iterate through
- the list of files and retrieve its properties. To retrieve the first file's
- name property, we can call \c {files[0].name}.
+ If you want the alarm to trigger also on other days, check \c alarmRepeat.
+ The Repeater will display a checkable RoundButton for each day of the week.
- Regular C++ functions are also accessible from QML. The file loading and saving
- functions are implemented in C++ and declared using the \l Q_INVOKABLE macro.
- Alternatively, we can declare the functions as a \c slot and the functions will
- be accessible from QML.
+ \quotefromfile tutorials/alarms/AlarmDelegate.qml
+ \skipto Flow
+ \printto TextField
- In \c {directory.h}:
+ If you modify the description of the alarm, it will be reflected in
+ the main screen afterwards.
- \code
- Q_INVOKABLE void saveFile();
- Q_INVOKABLE void loadFile();
- \endcode
+ \printto Button
- The \c Directory class also has to notify other objects whenever the directory
- contents change. This feature is performed using a \c signal. As previously
- mentioned, QML signals have a corresponding handler with their names prepended
- with \c on. The signal is called \c directoryChanged and it is emitted whenever
- there is a directory refresh. The refresh simply reloads the directory contents
- and updates the list of valid files in the directory. QML items can then be
- notified by attaching an action to the \c onDirectoryChanged signal handler.
-
- The \c list properties need to be explored further. This is because list
- properties use callbacks to access and modify the list contents. The list
- property is of type \c QQmlListProperty<File>. Whenever the list
- is accessed, the accessor function needs to return a
- \c QQmlListProperty<File>. The template type, \c File, needs to be a
- \c QObject derivative. Further, to create the
- \c QQmlListProperty, the list's accessor
- and modifiers need to be passed to the constructor as function pointers. The list,
- a \c QList in our case, also needs to be a list of \c File pointers.
-
- The constructor of \l QQmlListProperty is declared
- as follows:
- \code
- QQmlListProperty (QObject *object, void *data, AppendFunction append,
- CountFunction count = 0, AtFunction at = 0, ClearFunction clear = 0);
- \endcode
+ \section1 Deleting alarms
- It takes pointers to functions that will append the list, count
- the list, retrieve the item using an index, and empty the list. Only the \c append
- function is mandatory. Note that the function pointers must match the definition
- of \l {QQmlListProperty::AppendFunction}{AppendFunction},
- \l {QQmlListProperty::CountFunction}{CountFunction},
- \l {QQmlListProperty::AtFunction}{AtFunction}, or
- \l {QQmlListProperty::ClearFunction}{ClearFunction}.
+ The detail screen (see above) has a Button for deleting alarms.
+ When \c onClicked is emitted, the current ListElement is deleted
+ from \c alarmModel.
- The \c Directory class constructs a QQmlListProperty instance like this:
+ \printuntil alarmModel.remove
+ \printuntil }
- \code
- QQmlListProperty<File>(this, &m_fileList, &appendFiles, &filesSize, &fileAt, &clearFilesPtr);
- \endcode
-
- Where the parameters are pointers to following functions:
-
- \code
- void appendFiles(QQmlListProperty<File> *property, File *file);
- File* fileAt(QQmlListProperty<File> *property, int index);
- int filesSize(QQmlListProperty<File> *property);
- void clearFilesPtr(QQmlListProperty<File> *property);
- \endcode
+ \section2 Summary
- To simplify our file dialog, the \c Directory class filters out invalid text
- files, which are files that do not have a \c .txt extension. If a file name
- doesn't have the \c .txt extension, then it won't be seen in our file dialog.
- Also, the implementation makes sure that saved files have a \c .txt extension in
- the file name. \c Directory uses \l {QTextStream} to read the file and to output
- the file contents to a file.
+ The app has no code for adding sound or vibration to the alarm, nor does
+ it store the alarms in any format or database. Maybe it could be an
+ interesting coding project to add those features. Adding sound to this
+ program can be realized with \l{Qt Multimedia QML Types}. Storing the data
+ could be done quickly and easily in \l{JSON Support in Qt}{JSON format}.
- With our \c Directory object, we can retrieve the files as a list, know how many
- text files is in the application directory, get the file's name and content as a
- string, and be notified whenever there are changes in the directory contents.
-
- To build the plugin, run \c qmake on the \c filedialog.pro project file, then run
- \c make to build and transfer the plugin to the \c plugins directory.
-
-
- \section3 Importing a Plugin in QML
-
- The \c qmlscene tool imports files that are in the same directory as the
- application. We can also create a \c qmldir file containing the locations of
- content we wish to import. In this case, there is only the plugin, but other
- resources (QML types, JavaScript files) can be defined in a \c qmldir as well.
-
- Contents of the \c qmldir file:
- \code
- module FileDialog
- plugin filedialogplugin
- \endcode
-
- The module we just created is called \c FileDialog, and it makes available a plugin
- called \c filedialogplugin that matches the \c TARGET field in the project file.
- Because we did not specify a path for the plugin, the QML engine expects to find it
- in the same directory as the \c qmldir file.
-
- The QML types that are registered by our plugin can now be imported in QML:
-
- \code
- import FileDialog 1.0
-
- Directory {
- id: directory
- }
- ...
- \endcode
-
-
- \section3 Integrating a File Dialog into the File Menu
-
- Our \c FileMenu needs to display the \c FileDialog object, containing a list of
- the text files in a directory thus allowing the user to select the file by
- clicking on the list. We also need to assign the save, load, and new buttons
- to their respective actions. The FileMenu contains an editable text input to
- allow the user to type a file name using the keyboard.
-
- The \c Directory object is used in the \c FileMenu.qml file and it notifies the
- \c FileDialog object that the directory refreshed its contents. This notification
- is performed in the signal handler, \c onDirectoryChanged.
-
- In \c {FileMenu.qml}:
-
- \code
- Directory {
- id: directory
- filename: textInput.text
- onDirectoryChanged: fileDialog.notifyRefresh()
- }
- \endcode
-
- Keeping with the simplicity of our application, the file dialog will always be
- visible and will not display invalid text files, which do not have a \c .txt
- extension to their filenames.
-
- In \c {FileDialog.qml}:
-
- \code
- signal notifyRefresh()
- onNotifyRefresh: dirView.model = directory.files
- \endcode
-
- The \c FileDialog object will display the contents of a directory by reading its
- list property called \c files. The files are used as the model of a
- \l {GridView} object, which displays data items in a grid according
- to a delegate. The delegate handles the appearance of the model and our file
- dialog will simply create a grid with text centered in the middle. Clicking on
- the file name will result in the appearance of a rectangle to highlight the file
- name. The \c FileDialog is notified whenever the \c notifyRefresh signal is emitted,
- reloading the files in the directory.
-
- In \c {FileMenu.qml}:
-
- \code
- Button {
- id: newButton
- label: "New"
- onButtonClick: {
- textArea.textContent = ""
- }
- }
- Button {
- id: loadButton
- label: "Load"
- onButtonClick: {
- directory.filename = textInput.text
- directory.loadFile()
- textArea.textContent = directory.fileContent
- }
- }
- Button {
- id: saveButton
- label: "Save"
- onButtonClick: {
- directory.fileContent = textArea.textContent
- directory.filename = textInput.text
- directory.saveFile()
- }
- }
- Button {
- id: exitButton
- label: "Exit"
- onButtonClick: {
- Qt.quit()
- }
- }
- \endcode
-
- Our \c FileMenu can now connect to their respective actions. The \c saveButton
- will transfer the text from the \c TextEdit onto the directory's \c fileContent
- property, then copy its file name from the editable text input. Finally, the button
- calls the \c saveFile() function, saving the file. The \c loadButton has a similar
- execution. Also, the \c New action will empty the contents of the \c TextEdit.
-
- Further, the \c EditMenu buttons are connected to the \c TextEdit functions to copy,
- paste, and select all the text in the text editor.
-
- \image qml-texteditor5_filemenu.png
-
- \section2 Final Text Editor Application
-
- \image qml-texteditor5_newfile.png
-
- The application can function as a simple text editor, able to accept text
- and save it into a file. It can also load a file and perform text manipulation.
-
- \section1 Running the Text Editor
-
- We need to build the file dialog C++ plugin before the text editor can run.
- To build it, enter the \c filedialog directory, then run \c qmake and compile
- using \c make or \c nmake, depending on your platform.
-
- Run the text editor with \l{Prototyping with qmlscene}{qmlscene}, passing the
- imports directory as a parameter so that the QML engine knows where to look for
- the module that imports our file dialog plugin:
-
- \code
- qmlscene -I ./imports texteditor.qml
- \endcode
+ \sa {Qt Multimedia QML Types}, {JSON Support in Qt}
- The complete source code is in \c{examples/quick/tutorials/gettingStartedQml} directory.
-*/
diff --git a/doc/src/images/addalarms.png b/doc/src/images/addalarms.png
new file mode 100644
index 00000000..2874d2e6
--- /dev/null
+++ b/doc/src/images/addalarms.png
Binary files differ
diff --git a/doc/src/images/alarms2.png b/doc/src/images/alarms2.png
new file mode 100644
index 00000000..dbcb852c
--- /dev/null
+++ b/doc/src/images/alarms2.png
Binary files differ
diff --git a/doc/src/images/alarms3.png b/doc/src/images/alarms3.png
new file mode 100644
index 00000000..48abec6a
--- /dev/null
+++ b/doc/src/images/alarms3.png
Binary files differ
diff --git a/doc/src/images/detailscreen.png b/doc/src/images/detailscreen.png
new file mode 100644
index 00000000..bc0f0afb
--- /dev/null
+++ b/doc/src/images/detailscreen.png
Binary files differ
diff --git a/doc/src/images/mainscreen.png b/doc/src/images/mainscreen.png
new file mode 100644
index 00000000..e0c5e979
--- /dev/null
+++ b/doc/src/images/mainscreen.png
Binary files differ
diff --git a/examples/tutorials/alarms/AlarmDelegate.qml b/examples/tutorials/alarms/AlarmDelegate.qml
new file mode 100644
index 00000000..97ffc867
--- /dev/null
+++ b/examples/tutorials/alarms/AlarmDelegate.qml
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.11
+import QtQuick.Controls 2.4
+import QtQuick.Controls.Material 2.4
+import QtQuick.Layouts 1.11
+import QtQuick.Window 2.11
+
+ItemDelegate {
+ id: root
+ width: parent.width
+ checkable: true
+
+ onClicked: ListView.view.currentIndex = index
+
+ contentItem: ColumnLayout {
+ spacing: 0
+
+ RowLayout {
+ ColumnLayout {
+ id: dateColumn
+
+ readonly property date alarmDate: new Date(
+ model.year, model.month - 1, model.day, model.hour, model.minute)
+
+ Label {
+ id: timeLabel
+ font.pixelSize: Qt.application.font.pixelSize * 2
+ text: dateColumn.alarmDate.toLocaleTimeString(window.locale, Locale.ShortFormat)
+ }
+ RowLayout {
+ Label {
+ id: dateLabel
+ text: dateColumn.alarmDate.toLocaleDateString(window.locale, Locale.ShortFormat)
+ }
+ Label {
+ id: alarmAbout
+ text: "βΈ± " + model.label
+ visible: model.label.length > 0 && !root.checked
+ }
+ }
+ }
+ Item {
+ Layout.fillWidth: true
+ }
+ Switch {
+ checked: model.activated
+ Layout.alignment: Qt.AlignTop
+ onClicked: model.activated = checked
+ }
+ }
+ CheckBox {
+ id: alarmRepeat
+ text: qsTr("Repeat")
+ checked: model.repeat
+ visible: root.checked
+ onToggled: model.repeat = checked
+ }
+ Flow {
+ visible: root.checked && model.repeat
+ Layout.fillWidth: true
+
+ Repeater {
+ id: dayRepeater
+ model: daysToRepeat
+ delegate: RoundButton {
+ text: Qt.locale().dayName(model.dayOfWeek, Locale.NarrowFormat)
+ flat: true
+ checked: model.repeat
+ checkable: true
+ Material.background: checked ? Material.accent : "transparent"
+ onToggled: model.repeat = checked
+ }
+ }
+ }
+
+ TextField {
+ id: alarmDescriptionTextField
+ placeholderText: qsTr("Enter description here")
+ cursorVisible: true
+ visible: root.checked
+ text: model.label
+ onTextEdited: model.label = text
+ }
+ Button {
+ id: deleteAlarmButton
+ text: qsTr("Delete")
+ width: 40
+ height: 40
+ visible: root.checked
+ onClicked: alarmModel.remove(alarmListView.currentIndex, 1)
+ }
+ }
+}
diff --git a/examples/tutorials/alarms/AlarmDialog.qml b/examples/tutorials/alarms/AlarmDialog.qml
new file mode 100644
index 00000000..10e5a264
--- /dev/null
+++ b/examples/tutorials/alarms/AlarmDialog.qml
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.11
+import QtQuick.Controls 2.4
+import QtQuick.Layouts 1.11
+import QtQuick.Window 2.11
+
+Dialog {
+ id: alarmDialog
+ title: "Add new alarm"
+ modal: true
+ standardButtons: DialogButtonBox.Ok | DialogButtonBox.Cancel
+
+ property AlarmModel alarmModel
+
+ function formatNumber(number) {
+ return number < 10 && number >= 0 ? "0" + number : number.toString()
+ }
+
+ onAccepted: {
+ alarmModel.append({
+ "hour": hoursTumbler.currentIndex,
+ "minute": minutesTumbler.currentIndex,
+ "day": dayTumbler.currentIndex + 1,
+ "month": monthTumbler.currentIndex + 1,
+ "year": yearTumbler.years[yearTumbler.currentIndex],
+ "activated": true,
+ "label": "",
+ "repeat": false,
+ "daysToRepeat": [
+ { "dayOfWeek": 0, "repeat": false },
+ { "dayOfWeek": 1, "repeat": false },
+ { "dayOfWeek": 2, "repeat": false },
+ { "dayOfWeek": 3, "repeat": false },
+ { "dayOfWeek": 4, "repeat": false },
+ { "dayOfWeek": 5, "repeat": false },
+ { "dayOfWeek": 6, "repeat": false }
+ ],
+ })
+ }
+ onRejected: alarmDialog.close()
+
+ contentItem: RowLayout {
+ RowLayout {
+ id: rowTumbler
+
+ Tumbler {
+ id: hoursTumbler
+ model: 24
+ delegate: TumblerDelegate {
+ text: formatNumber(modelData)
+ }
+ }
+ Tumbler {
+ id: minutesTumbler
+ model: 60
+ delegate: TumblerDelegate {
+ text: formatNumber(modelData)
+ }
+ }
+ }
+
+ RowLayout {
+ id: datePicker
+
+ Layout.leftMargin: 20
+
+ property alias dayTumbler: dayTumbler
+ property alias monthTumbler: monthTumbler
+ property alias yearTumbler: yearTumbler
+
+ readonly property var days: [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
+
+ Tumbler {
+ id: dayTumbler
+
+ function updateModel() {
+ // Populate the model with days of the month. For example: [0, ..., 30]
+ var previousIndex = dayTumbler.currentIndex
+ var array = []
+ var newDays = datePicker.days[monthTumbler.currentIndex]
+ for (var i = 1; i <= newDays; ++i)
+ array.push(i)
+ dayTumbler.model = array
+ dayTumbler.currentIndex = Math.min(newDays - 1, previousIndex)
+ }
+
+ Component.onCompleted: updateModel()
+
+ delegate: TumblerDelegate {
+ text: formatNumber(modelData)
+ }
+ }
+ Tumbler {
+ id: monthTumbler
+
+ onCurrentIndexChanged: dayTumbler.updateModel()
+
+ model: 12
+ delegate: TumblerDelegate {
+ text: window.locale.standaloneMonthName(modelData, Locale.ShortFormat)
+ }
+ }
+ Tumbler {
+ id: yearTumbler
+
+ // This array is populated with the next three years. For example: [2018, 2019, 2020]
+ readonly property var years: (function() {
+ var currentYear = new Date().getFullYear()
+ return [0, 1, 2].map(function(value) { return value + currentYear; })
+ })()
+
+ model: years
+ delegate: TumblerDelegate {
+ text: formatNumber(modelData)
+ }
+ }
+ }
+ }
+}
diff --git a/examples/tutorials/alarms/AlarmModel.qml b/examples/tutorials/alarms/AlarmModel.qml
new file mode 100644
index 00000000..6afa5db7
--- /dev/null
+++ b/examples/tutorials/alarms/AlarmModel.qml
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.11
+
+// Populate the model with some sample data.
+ListModel {
+ id: alarmModel
+
+ ListElement {
+ hour: 6
+ minute: 0
+ day: 2
+ month: 8
+ year: 2018
+ activated: true
+ label: "Wake up"
+ repeat: true
+ daysToRepeat: [
+ ListElement { dayOfWeek: 0; repeat: false },
+ ListElement { dayOfWeek: 1; repeat: false },
+ ListElement { dayOfWeek: 2; repeat: false },
+ ListElement { dayOfWeek: 3; repeat: false },
+ ListElement { dayOfWeek: 4; repeat: false },
+ ListElement { dayOfWeek: 5; repeat: false },
+ ListElement { dayOfWeek: 6; repeat: false }
+ ]
+ }
+ ListElement {
+ hour: 6
+ minute: 0
+ day: 3
+ month: 8
+ year: 2018
+ activated: true
+ label: "Wake up"
+ repeat: true
+ daysToRepeat: [
+ ListElement { dayOfWeek: 0; repeat: true },
+ ListElement { dayOfWeek: 1; repeat: true },
+ ListElement { dayOfWeek: 2; repeat: true },
+ ListElement { dayOfWeek: 3; repeat: true },
+ ListElement { dayOfWeek: 4; repeat: true },
+ ListElement { dayOfWeek: 5; repeat: false },
+ ListElement { dayOfWeek: 6; repeat: false }
+ ]
+ }
+ ListElement {
+ hour: 7
+ minute: 0
+ day: 3
+ month: 8
+ year: 2018
+ activated: false
+ label: "Exercise"
+ repeat: true
+ daysToRepeat: [
+ ListElement { dayOfWeek: 0; repeat: true },
+ ListElement { dayOfWeek: 1; repeat: true },
+ ListElement { dayOfWeek: 2; repeat: true },
+ ListElement { dayOfWeek: 3; repeat: true },
+ ListElement { dayOfWeek: 4; repeat: true },
+ ListElement { dayOfWeek: 5; repeat: true },
+ ListElement { dayOfWeek: 6; repeat: true }
+ ]
+ }
+ ListElement {
+ hour: 5
+ minute: 15
+ day: 1
+ month: 9
+ year: 2018
+ activated: true
+ label: ""
+ repeat: false
+ daysToRepeat: [
+ ListElement { dayOfWeek: 0; repeat: false },
+ ListElement { dayOfWeek: 1; repeat: false },
+ ListElement { dayOfWeek: 2; repeat: false },
+ ListElement { dayOfWeek: 3; repeat: false },
+ ListElement { dayOfWeek: 4; repeat: false },
+ ListElement { dayOfWeek: 5; repeat: false },
+ ListElement { dayOfWeek: 6; repeat: false }
+ ]
+ }
+ ListElement {
+ hour: 5
+ minute: 45
+ day: 3
+ month: 9
+ year: 2018
+ activated: false
+ label: ""
+ repeat: false
+ daysToRepeat: [
+ ListElement { dayOfWeek: 0; repeat: false },
+ ListElement { dayOfWeek: 1; repeat: false },
+ ListElement { dayOfWeek: 2; repeat: false },
+ ListElement { dayOfWeek: 3; repeat: false },
+ ListElement { dayOfWeek: 4; repeat: false },
+ ListElement { dayOfWeek: 5; repeat: false },
+ ListElement { dayOfWeek: 6; repeat: false }
+ ]
+ }
+}
diff --git a/examples/tutorials/alarms/TumblerDelegate.qml b/examples/tutorials/alarms/TumblerDelegate.qml
new file mode 100644
index 00000000..88a35a5b
--- /dev/null
+++ b/examples/tutorials/alarms/TumblerDelegate.qml
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.11
+import QtQuick.Controls 2.4
+import QtQuick.Controls.Material 2.4
+
+Text {
+ text: modelData
+ color: Tumbler.tumbler.Material.foreground
+ font: Tumbler.tumbler.font
+ opacity: 1.0 - Math.abs(Tumbler.displacement) / (Tumbler.tumbler.visibleItemCount / 2)
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+}
diff --git a/examples/tutorials/alarms/alarms.pro b/examples/tutorials/alarms/alarms.pro
new file mode 100644
index 00000000..6c54c7f8
--- /dev/null
+++ b/examples/tutorials/alarms/alarms.pro
@@ -0,0 +1,29 @@
+QT += qml quick
+
+CONFIG += c++11
+
+SOURCES += main.cpp
+
+RESOURCES += qml.qrc
+
+# Additional import path used to resolve QML modules in Qt Creator's code model
+QML_IMPORT_PATH = $$PWD/imports
+
+# Additional import path used to resolve QML modules just for Qt Quick Designer
+QML_DESIGNER_IMPORT_PATH =
+
+# The following define makes your compiler emit warnings if you use
+# any feature of Qt which has been marked deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+TARGET = Alarms
+# You can also make your code fail to compile if you use deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
+
+# Default rules for deployment.
+qnx: target.path = /tmp/$${TARGET}/bin
+else: unix:!android: target.path = /opt/$${TARGET}/bin
+!isEmpty(target.path): INSTALLS += target
diff --git a/examples/tutorials/alarms/main.cpp b/examples/tutorials/alarms/main.cpp
new file mode 100644
index 00000000..3e1bdd84
--- /dev/null
+++ b/examples/tutorials/alarms/main.cpp
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QGuiApplication>
+#include <QQmlApplicationEngine>
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+
+ QGuiApplication app(argc, argv);
+
+ QQmlApplicationEngine engine;
+ engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
+ if (engine.rootObjects().isEmpty())
+ return -1;
+
+ return app.exec();
+}
diff --git a/examples/tutorials/alarms/main.qml b/examples/tutorials/alarms/main.qml
new file mode 100644
index 00000000..acd54168
--- /dev/null
+++ b/examples/tutorials/alarms/main.qml
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.11
+import QtQuick.Controls 2.4
+import QtQuick.Controls.Material 2.4
+import QtQuick.Layouts 1.11
+import QtQuick.Window 2.11
+import Qt.labs.calendar 1.0
+
+ApplicationWindow {
+ id: window
+ width: 400
+ height: 500
+ visible: true
+
+ ListView {
+ id: alarmListView
+ anchors.fill: parent
+ model: AlarmModel {}
+ delegate: AlarmDelegate {}
+ }
+
+ RoundButton {
+ id: addAlarmButton
+ text: "+"
+ anchors.bottom: alarmListView.bottom
+ anchors.bottomMargin: 8
+ anchors.horizontalCenter: parent.horizontalCenter
+ onClicked: alarmDialog.open()
+ }
+
+ AlarmDialog {
+ id: alarmDialog
+ x: Math.round((parent.width - width) / 2)
+ y: Math.round((parent.height - height) / 2)
+ alarmModel: alarmListView.model
+ }
+}
diff --git a/examples/tutorials/alarms/qml.qrc b/examples/tutorials/alarms/qml.qrc
new file mode 100644
index 00000000..ae9ac907
--- /dev/null
+++ b/examples/tutorials/alarms/qml.qrc
@@ -0,0 +1,10 @@
+<RCC>
+ <qresource prefix="/">
+ <file>main.qml</file>
+ <file>qtquickcontrols2.conf</file>
+ <file>TumblerDelegate.qml</file>
+ <file>AlarmModel.qml</file>
+ <file>AlarmDelegate.qml</file>
+ <file>AlarmDialog.qml</file>
+ </qresource>
+</RCC>
diff --git a/examples/tutorials/alarms/qtquickcontrols2.conf b/examples/tutorials/alarms/qtquickcontrols2.conf
new file mode 100644
index 00000000..3c676659
--- /dev/null
+++ b/examples/tutorials/alarms/qtquickcontrols2.conf
@@ -0,0 +1,5 @@
+[Controls]
+Style=Material
+[Material]
+Theme=Dark
+Accent=Red