aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--.qmake.conf2
-rw-r--r--examples/quickcontrols2/gallery/gallery.cpp1
-rw-r--r--examples/quickcontrols2/gallery/gallery.qml7
-rw-r--r--examples/quickcontrols2/gallery/pages/ComboBoxPage.qml25
-rw-r--r--examples/quickcontrols2/gallery/pages/DelayButtonPage.qml64
-rw-r--r--examples/quickcontrols2/quickcontrols2.pro2
-rw-r--r--examples/quickcontrols2/sidepanel/doc/images/qtquickcontrols2-sidepanel-landscape.pngbin0 -> 58907 bytes
-rw-r--r--examples/quickcontrols2/sidepanel/doc/images/qtquickcontrols2-sidepanel-portrait.pngbin0 -> 32492 bytes
-rw-r--r--examples/quickcontrols2/sidepanel/doc/src/qtquickcontrols2-sidepanel.qdoc81
-rw-r--r--examples/quickcontrols2/sidepanel/images/qt-logo.pngbin0 -> 2695 bytes
-rw-r--r--examples/quickcontrols2/sidepanel/images/qt-logo@2x.pngbin0 -> 5521 bytes
-rw-r--r--examples/quickcontrols2/sidepanel/images/qt-logo@3x.pngbin0 -> 8166 bytes
-rw-r--r--examples/quickcontrols2/sidepanel/images/qt-logo@4x.pngbin0 -> 11600 bytes
-rw-r--r--examples/quickcontrols2/sidepanel/sidepanel.cpp55
-rw-r--r--examples/quickcontrols2/sidepanel/sidepanel.pro13
-rw-r--r--examples/quickcontrols2/sidepanel/sidepanel.qml170
-rw-r--r--examples/quickcontrols2/swipetoremove/doc/images/qtquickcontrols2-swipetoremove.pngbin0 -> 23387 bytes
-rw-r--r--examples/quickcontrols2/swipetoremove/doc/src/qtquickcontrols2-swipetoremove.qdoc62
-rw-r--r--examples/quickcontrols2/swipetoremove/fonts/LICENSE.txt12
-rw-r--r--examples/quickcontrols2/swipetoremove/fonts/fontello.ttfbin0 -> 5164 bytes
-rw-r--r--examples/quickcontrols2/swipetoremove/swipetoremove.cpp58
-rw-r--r--examples/quickcontrols2/swipetoremove/swipetoremove.pro13
-rw-r--r--examples/quickcontrols2/swipetoremove/swipetoremove.qml167
-rw-r--r--src/imports/controls/AbstractButton.qml4
-rw-r--r--src/imports/controls/ApplicationWindow.qml8
-rw-r--r--src/imports/controls/BusyIndicator.qml21
-rw-r--r--src/imports/controls/Button.qml8
-rw-r--r--src/imports/controls/CheckBox.qml8
-rw-r--r--src/imports/controls/CheckDelegate.qml8
-rw-r--r--src/imports/controls/CheckIndicator.qml6
-rw-r--r--src/imports/controls/ComboBox.qml66
-rw-r--r--src/imports/controls/Container.qml4
-rw-r--r--src/imports/controls/Control.qml4
-rw-r--r--src/imports/controls/DelayButton.qml126
-rw-r--r--src/imports/controls/Dial.qml8
-rw-r--r--src/imports/controls/Dialog.qml8
-rw-r--r--src/imports/controls/DialogButtonBox.qml4
-rw-r--r--src/imports/controls/Drawer.qml8
-rw-r--r--src/imports/controls/Frame.qml8
-rw-r--r--src/imports/controls/GroupBox.qml8
-rw-r--r--src/imports/controls/ItemDelegate.qml8
-rw-r--r--src/imports/controls/Label.qml8
-rw-r--r--src/imports/controls/Menu.qml8
-rw-r--r--src/imports/controls/MenuItem.qml8
-rw-r--r--src/imports/controls/MenuSeparator.qml8
-rw-r--r--src/imports/controls/Page.qml8
-rw-r--r--src/imports/controls/PageIndicator.qml8
-rw-r--r--src/imports/controls/Pane.qml8
-rw-r--r--src/imports/controls/Popup.qml8
-rw-r--r--src/imports/controls/ProgressBar.qml18
-rw-r--r--src/imports/controls/RadioButton.qml8
-rw-r--r--src/imports/controls/RadioDelegate.qml8
-rw-r--r--src/imports/controls/RadioIndicator.qml6
-rw-r--r--src/imports/controls/RangeSlider.qml8
-rw-r--r--src/imports/controls/RoundButton.qml8
-rw-r--r--src/imports/controls/ScrollBar.qml8
-rw-r--r--src/imports/controls/ScrollIndicator.qml8
-rw-r--r--src/imports/controls/Slider.qml8
-rw-r--r--src/imports/controls/SpinBox.qml10
-rw-r--r--src/imports/controls/StackView.qml6
-rw-r--r--src/imports/controls/SwipeDelegate.qml26
-rw-r--r--src/imports/controls/SwipeView.qml6
-rw-r--r--src/imports/controls/Switch.qml8
-rw-r--r--src/imports/controls/SwitchDelegate.qml8
-rw-r--r--src/imports/controls/SwitchIndicator.qml6
-rw-r--r--src/imports/controls/TabBar.qml12
-rw-r--r--src/imports/controls/TabButton.qml8
-rw-r--r--src/imports/controls/TextArea.qml11
-rw-r--r--src/imports/controls/TextField.qml11
-rw-r--r--src/imports/controls/ToolBar.qml8
-rw-r--r--src/imports/controls/ToolButton.qml8
-rw-r--r--src/imports/controls/ToolSeparator.qml8
-rw-r--r--src/imports/controls/ToolTip.qml8
-rw-r--r--src/imports/controls/Tumbler.qml8
-rw-r--r--src/imports/controls/controls.pri11
-rw-r--r--src/imports/controls/doc/images/qtquickcontrols2-delaybutton-custom.pngbin0 -> 7340 bytes
-rw-r--r--src/imports/controls/doc/images/qtquickcontrols2-delaybutton.gifbin0 -> 12595 bytes
-rw-r--r--src/imports/controls/doc/images/qtquickcontrols2-scrollbar-nosnap.gifbin0 -> 5271 bytes
-rw-r--r--src/imports/controls/doc/images/qtquickcontrols2-scrollbar-snapalways.gifbin0 -> 4707 bytes
-rw-r--r--src/imports/controls/doc/images/qtquickcontrols2-scrollbar-snaponrelease.gifbin0 -> 5646 bytes
-rw-r--r--src/imports/controls/doc/snippets/qtquickcontrols2-swipedelegate-transition.qml37
-rw-r--r--src/imports/controls/doc/snippets/qtquickcontrols2-tumbler-listView.qml2
-rw-r--r--src/imports/controls/doc/snippets/screenshots/qtquickcontrols2-combobox-custom.qml4
-rw-r--r--src/imports/controls/doc/snippets/screenshots/qtquickcontrols2-delaybutton-custom.qml82
-rw-r--r--src/imports/controls/doc/src/includes/inputmethodhints.qdocinc38
-rw-r--r--src/imports/controls/doc/src/qtquickcontrols2-buttons.qdoc16
-rw-r--r--src/imports/controls/doc/src/qtquickcontrols2-customize.qdoc10
-rw-r--r--src/imports/controls/doc/src/qtquickcontrols2-delegates.qdoc1
-rw-r--r--src/imports/controls/doc/src/qtquickcontrols2-differences.qdoc2
-rw-r--r--src/imports/controls/doc/src/qtquickcontrols2-environment.qdoc6
-rw-r--r--src/imports/controls/doc/src/qtquickcontrols2-index.qdoc2
-rw-r--r--src/imports/controls/doc/src/qtquickcontrols2-input.qdoc1
-rw-r--r--src/imports/controls/doc/src/qtquickcontrols2-material.qdoc2
-rw-r--r--src/imports/controls/doc/src/qtquickcontrols2-qmltypes.qdoc4
-rw-r--r--src/imports/controls/doc/src/qtquickcontrols2-universal.qdoc2
-rw-r--r--src/imports/controls/images/double-arrow.pngbin1275 -> 491 bytes
-rw-r--r--src/imports/controls/images/double-arrow@2x.pngbin1690 -> 937 bytes
-rw-r--r--src/imports/controls/images/double-arrow@3x.pngbin2059 -> 1368 bytes
-rw-r--r--src/imports/controls/images/double-arrow@4x.pngbin2523 -> 1833 bytes
-rw-r--r--src/imports/controls/material/ApplicationWindow.qml6
-rw-r--r--src/imports/controls/material/BoxShadow.qml6
-rw-r--r--src/imports/controls/material/BusyIndicator.qml27
-rw-r--r--src/imports/controls/material/Button.qml8
-rw-r--r--src/imports/controls/material/CheckBox.qml8
-rw-r--r--src/imports/controls/material/CheckDelegate.qml8
-rw-r--r--src/imports/controls/material/CheckIndicator.qml6
-rw-r--r--src/imports/controls/material/ComboBox.qml63
-rw-r--r--src/imports/controls/material/CursorDelegate.qml65
-rw-r--r--src/imports/controls/material/DelayButton.qml126
-rw-r--r--src/imports/controls/material/Dial.qml8
-rw-r--r--src/imports/controls/material/Dialog.qml10
-rw-r--r--src/imports/controls/material/DialogButtonBox.qml10
-rw-r--r--src/imports/controls/material/Drawer.qml10
-rw-r--r--src/imports/controls/material/ElevationEffect.qml6
-rw-r--r--src/imports/controls/material/Frame.qml8
-rw-r--r--src/imports/controls/material/GroupBox.qml8
-rw-r--r--src/imports/controls/material/ItemDelegate.qml8
-rw-r--r--src/imports/controls/material/Label.qml6
-rw-r--r--src/imports/controls/material/Menu.qml10
-rw-r--r--src/imports/controls/material/MenuItem.qml8
-rw-r--r--src/imports/controls/material/MenuSeparator.qml6
-rw-r--r--src/imports/controls/material/Page.qml6
-rw-r--r--src/imports/controls/material/PageIndicator.qml6
-rw-r--r--src/imports/controls/material/Pane.qml8
-rw-r--r--src/imports/controls/material/Popup.qml8
-rw-r--r--src/imports/controls/material/ProgressBar.qml18
-rw-r--r--src/imports/controls/material/RadioButton.qml8
-rw-r--r--src/imports/controls/material/RadioDelegate.qml8
-rw-r--r--src/imports/controls/material/RadioIndicator.qml6
-rw-r--r--src/imports/controls/material/RangeSlider.qml8
-rw-r--r--src/imports/controls/material/RoundButton.qml8
-rw-r--r--src/imports/controls/material/ScrollBar.qml6
-rw-r--r--src/imports/controls/material/ScrollIndicator.qml6
-rw-r--r--src/imports/controls/material/Slider.qml8
-rw-r--r--src/imports/controls/material/SliderHandle.qml6
-rw-r--r--src/imports/controls/material/SpinBox.qml37
-rw-r--r--src/imports/controls/material/StackView.qml4
-rw-r--r--src/imports/controls/material/SwipeDelegate.qml26
-rw-r--r--src/imports/controls/material/SwipeView.qml4
-rw-r--r--src/imports/controls/material/Switch.qml8
-rw-r--r--src/imports/controls/material/SwitchDelegate.qml8
-rw-r--r--src/imports/controls/material/SwitchIndicator.qml6
-rw-r--r--src/imports/controls/material/TabBar.qml16
-rw-r--r--src/imports/controls/material/TabButton.qml8
-rw-r--r--src/imports/controls/material/TextArea.qml38
-rw-r--r--src/imports/controls/material/TextField.qml37
-rw-r--r--src/imports/controls/material/ToolBar.qml8
-rw-r--r--src/imports/controls/material/ToolButton.qml8
-rw-r--r--src/imports/controls/material/ToolSeparator.qml6
-rw-r--r--src/imports/controls/material/ToolTip.qml6
-rw-r--r--src/imports/controls/material/Tumbler.qml10
-rw-r--r--src/imports/controls/material/images/drop-indicator.pngbin192 -> 205 bytes
-rw-r--r--src/imports/controls/material/images/drop-indicator@2x.pngbin221 -> 255 bytes
-rw-r--r--src/imports/controls/material/images/drop-indicator@3x.pngbin256 -> 306 bytes
-rw-r--r--src/imports/controls/material/images/drop-indicator@4x.pngbin289 -> 331 bytes
-rw-r--r--src/imports/controls/material/material.pri14
-rw-r--r--src/imports/controls/material/qmldir2
-rw-r--r--src/imports/controls/material/qquickmaterialbusyindicator.cpp229
-rw-r--r--src/imports/controls/material/qquickmaterialbusyindicator_p.h (renamed from src/imports/controls/material/qquickmaterialprogressring_p.h)31
-rw-r--r--src/imports/controls/material/qquickmaterialprogressbar.cpp (renamed from src/imports/controls/material/qquickmaterialprogressstrip.cpp)202
-rw-r--r--src/imports/controls/material/qquickmaterialprogressbar_p.h (renamed from src/imports/controls/material/qquickmaterialprogressstrip_p.h)27
-rw-r--r--src/imports/controls/material/qquickmaterialprogressring.cpp260
-rw-r--r--src/imports/controls/material/qquickmaterialripple.cpp335
-rw-r--r--src/imports/controls/material/qquickmaterialripple_p.h8
-rw-r--r--src/imports/controls/material/qquickmaterialstyle_p.h1
-rw-r--r--src/imports/controls/material/qtquickcontrols2materialstyleplugin.cpp16
-rw-r--r--src/imports/controls/qmldir2
-rw-r--r--src/imports/controls/qquickbusyindicatorring.cpp231
-rw-r--r--src/imports/controls/qquickdefaultbusyindicator.cpp168
-rw-r--r--src/imports/controls/qquickdefaultbusyindicator_p.h (renamed from src/imports/controls/qquickbusyindicatorring_p.h)28
-rw-r--r--src/imports/controls/qquickdefaultprogressbar.cpp272
-rw-r--r--src/imports/controls/qquickdefaultprogressbar_p.h (renamed from src/imports/controls/qquickprogressstrip_p.h)25
-rw-r--r--src/imports/controls/qquickprogressstrip.cpp315
-rw-r--r--src/imports/controls/qtquickcontrols2plugin.cpp26
-rw-r--r--src/imports/controls/universal/ApplicationWindow.qml8
-rw-r--r--src/imports/controls/universal/BusyIndicator.qml18
-rw-r--r--src/imports/controls/universal/Button.qml6
-rw-r--r--src/imports/controls/universal/CheckBox.qml8
-rw-r--r--src/imports/controls/universal/CheckDelegate.qml6
-rw-r--r--src/imports/controls/universal/CheckIndicator.qml8
-rw-r--r--src/imports/controls/universal/ComboBox.qml67
-rw-r--r--src/imports/controls/universal/DelayButton.qml96
-rw-r--r--src/imports/controls/universal/Dial.qml6
-rw-r--r--src/imports/controls/universal/Dialog.qml8
-rw-r--r--src/imports/controls/universal/DialogButtonBox.qml8
-rw-r--r--src/imports/controls/universal/Drawer.qml6
-rw-r--r--src/imports/controls/universal/Frame.qml6
-rw-r--r--src/imports/controls/universal/GroupBox.qml6
-rw-r--r--src/imports/controls/universal/ItemDelegate.qml6
-rw-r--r--src/imports/controls/universal/Label.qml6
-rw-r--r--src/imports/controls/universal/Menu.qml8
-rw-r--r--src/imports/controls/universal/MenuItem.qml6
-rw-r--r--src/imports/controls/universal/MenuSeparator.qml6
-rw-r--r--src/imports/controls/universal/Page.qml6
-rw-r--r--src/imports/controls/universal/PageIndicator.qml6
-rw-r--r--src/imports/controls/universal/Pane.qml6
-rw-r--r--src/imports/controls/universal/Popup.qml6
-rw-r--r--src/imports/controls/universal/ProgressBar.qml19
-rw-r--r--src/imports/controls/universal/RadioButton.qml8
-rw-r--r--src/imports/controls/universal/RadioDelegate.qml6
-rw-r--r--src/imports/controls/universal/RadioIndicator.qml4
-rw-r--r--src/imports/controls/universal/RangeSlider.qml6
-rw-r--r--src/imports/controls/universal/RoundButton.qml6
-rw-r--r--src/imports/controls/universal/ScrollBar.qml6
-rw-r--r--src/imports/controls/universal/ScrollIndicator.qml6
-rw-r--r--src/imports/controls/universal/Slider.qml6
-rw-r--r--src/imports/controls/universal/SpinBox.qml8
-rw-r--r--src/imports/controls/universal/StackView.qml6
-rw-r--r--src/imports/controls/universal/SwipeDelegate.qml24
-rw-r--r--src/imports/controls/universal/Switch.qml6
-rw-r--r--src/imports/controls/universal/SwitchDelegate.qml6
-rw-r--r--src/imports/controls/universal/SwitchIndicator.qml6
-rw-r--r--src/imports/controls/universal/TabBar.qml15
-rw-r--r--src/imports/controls/universal/TabButton.qml6
-rw-r--r--src/imports/controls/universal/TextArea.qml11
-rw-r--r--src/imports/controls/universal/TextField.qml11
-rw-r--r--src/imports/controls/universal/ToolBar.qml6
-rw-r--r--src/imports/controls/universal/ToolButton.qml6
-rw-r--r--src/imports/controls/universal/ToolSeparator.qml6
-rw-r--r--src/imports/controls/universal/ToolTip.qml6
-rw-r--r--src/imports/controls/universal/Tumbler.qml10
-rw-r--r--src/imports/controls/universal/images/downarrow.pngbin200 -> 233 bytes
-rw-r--r--src/imports/controls/universal/images/downarrow@2x.pngbin263 -> 325 bytes
-rw-r--r--src/imports/controls/universal/images/downarrow@3x.pngbin329 -> 387 bytes
-rw-r--r--src/imports/controls/universal/images/downarrow@4x.pngbin358 -> 423 bytes
-rw-r--r--src/imports/controls/universal/qmldir2
-rw-r--r--src/imports/controls/universal/qquickuniversalbusyindicator.cpp (renamed from src/imports/controls/universal/qquickuniversalprogressring.cpp)191
-rw-r--r--src/imports/controls/universal/qquickuniversalbusyindicator_p.h (renamed from src/imports/controls/universal/qquickuniversalprogressring_p.h)35
-rw-r--r--src/imports/controls/universal/qquickuniversalprogressbar.cpp (renamed from src/imports/controls/universal/qquickuniversalprogressstrip.cpp)219
-rw-r--r--src/imports/controls/universal/qquickuniversalprogressbar_p.h (renamed from src/imports/controls/universal/qquickuniversalprogressstrip_p.h)27
-rw-r--r--src/imports/controls/universal/qtquickcontrols2universalstyleplugin.cpp16
-rw-r--r--src/imports/controls/universal/universal.pri9
-rw-r--r--src/imports/platform/qquickplatformmenuitem.cpp2
-rw-r--r--src/imports/templates/qtquicktemplates2plugin.cpp23
-rw-r--r--src/quickcontrols2/qquickanimatednode.cpp163
-rw-r--r--src/quickcontrols2/qquickanimatednode_p.h112
-rw-r--r--src/quickcontrols2/qquickplaceholdertext.cpp73
-rw-r--r--src/quickcontrols2/qquickplaceholdertext_p.h74
-rw-r--r--src/quickcontrols2/qquickstyle.cpp55
-rw-r--r--src/quickcontrols2/qquickstyle.h1
-rw-r--r--src/quickcontrols2/qquickstyle_p.h1
-rw-r--r--src/quickcontrols2/qquickstyleselector_p_p.h1
-rw-r--r--src/quickcontrols2/qquicktumblerview.cpp2
-rw-r--r--src/quickcontrols2/quickcontrols2.pri4
-rw-r--r--src/quicktemplates2/qquickabstractbutton.cpp166
-rw-r--r--src/quicktemplates2/qquickabstractbutton_p.h14
-rw-r--r--src/quicktemplates2/qquickabstractbutton_p_p.h7
-rw-r--r--src/quicktemplates2/qquickbutton.cpp6
-rw-r--r--src/quicktemplates2/qquickbutton_p.h2
-rw-r--r--src/quicktemplates2/qquickcheckbox.cpp7
-rw-r--r--src/quicktemplates2/qquickcheckbox_p.h2
-rw-r--r--src/quicktemplates2/qquickcheckdelegate.cpp7
-rw-r--r--src/quicktemplates2/qquickcheckdelegate_p.h2
-rw-r--r--src/quicktemplates2/qquickcombobox.cpp524
-rw-r--r--src/quicktemplates2/qquickcombobox_p.h44
-rw-r--r--src/quicktemplates2/qquickcontrol.cpp2
-rw-r--r--src/quicktemplates2/qquickdelaybutton.cpp271
-rw-r--r--src/quicktemplates2/qquickdelaybutton_p.h98
-rw-r--r--src/quicktemplates2/qquickdial.cpp211
-rw-r--r--src/quicktemplates2/qquickdial_p.h8
-rw-r--r--src/quicktemplates2/qquickdialog.cpp1
-rw-r--r--src/quicktemplates2/qquickdialogbuttonbox.cpp1
-rw-r--r--src/quicktemplates2/qquickdrawer.cpp35
-rw-r--r--src/quicktemplates2/qquickdrawer_p.h5
-rw-r--r--src/quicktemplates2/qquickmenu_p_p.h1
-rw-r--r--src/quicktemplates2/qquickoverlay.cpp1
-rw-r--r--src/quicktemplates2/qquickpopup.cpp524
-rw-r--r--src/quicktemplates2/qquickpopup_p_p.h78
-rw-r--r--src/quicktemplates2/qquickpopupitem.cpp294
-rw-r--r--src/quicktemplates2/qquickpopupitem_p_p.h106
-rw-r--r--src/quicktemplates2/qquickpopuppositioner.cpp277
-rw-r--r--src/quicktemplates2/qquickpopuppositioner_p_p.h85
-rw-r--r--src/quicktemplates2/qquickrangeslider.cpp352
-rw-r--r--src/quicktemplates2/qquickrangeslider_p.h7
-rw-r--r--src/quicktemplates2/qquickscrollbar.cpp118
-rw-r--r--src/quicktemplates2/qquickscrollbar_p.h13
-rw-r--r--src/quicktemplates2/qquickslider.cpp223
-rw-r--r--src/quicktemplates2/qquickslider_p.h8
-rw-r--r--src/quicktemplates2/qquickspinbox.cpp78
-rw-r--r--src/quicktemplates2/qquickspinbox_p.h10
-rw-r--r--src/quicktemplates2/qquickstackelement.cpp292
-rw-r--r--src/quicktemplates2/qquickstackelement_p_p.h105
-rw-r--r--src/quicktemplates2/qquickstacktransition.cpp158
-rw-r--r--src/quicktemplates2/qquickstacktransition_p_p.h79
-rw-r--r--src/quicktemplates2/qquickstackview.cpp34
-rw-r--r--src/quicktemplates2/qquickstackview_p.cpp367
-rw-r--r--src/quicktemplates2/qquickstackview_p.h17
-rw-r--r--src/quicktemplates2/qquickstackview_p_p.h72
-rw-r--r--src/quicktemplates2/qquickswipe_p.h18
-rw-r--r--src/quicktemplates2/qquickswipedelegate.cpp249
-rw-r--r--src/quicktemplates2/qquickswipedelegate_p.h4
-rw-r--r--src/quicktemplates2/qquickswitch.cpp9
-rw-r--r--src/quicktemplates2/qquickswitch_p.h2
-rw-r--r--src/quicktemplates2/qquickswitchdelegate.cpp9
-rw-r--r--src/quicktemplates2/qquickswitchdelegate_p.h2
-rw-r--r--src/quicktemplates2/qquicktabbar.cpp180
-rw-r--r--src/quicktemplates2/qquicktabbar_p.h12
-rw-r--r--src/quicktemplates2/qquicktooltip.cpp4
-rw-r--r--src/quicktemplates2/qquicktumbler.cpp15
-rw-r--r--src/quicktemplates2/qquicktumbler_p.h4
-rw-r--r--src/quicktemplates2/quicktemplates2.pri10
-rw-r--r--tests/auto/controls/data/TumblerListView.qml2
-rw-r--r--tests/auto/controls/data/tst_abstractbutton.qml15
-rw-r--r--tests/auto/controls/data/tst_busyindicator.qml4
-rw-r--r--tests/auto/controls/data/tst_button.qml31
-rw-r--r--tests/auto/controls/data/tst_buttongroup.qml56
-rw-r--r--tests/auto/controls/data/tst_checkbox.qml43
-rw-r--r--tests/auto/controls/data/tst_checkdelegate.qml10
-rw-r--r--tests/auto/controls/data/tst_combobox.qml368
-rw-r--r--tests/auto/controls/data/tst_container.qml4
-rw-r--r--tests/auto/controls/data/tst_control.qml52
-rw-r--r--tests/auto/controls/data/tst_delaybutton.qml248
-rw-r--r--tests/auto/controls/data/tst_dial.qml231
-rw-r--r--tests/auto/controls/data/tst_dialog.qml35
-rw-r--r--tests/auto/controls/data/tst_dialogbuttonbox.qml21
-rw-r--r--tests/auto/controls/data/tst_drawer.qml7
-rw-r--r--tests/auto/controls/data/tst_frame.qml16
-rw-r--r--tests/auto/controls/data/tst_groupbox.qml16
-rw-r--r--tests/auto/controls/data/tst_itemdelegate.qml7
-rw-r--r--tests/auto/controls/data/tst_label.qml7
-rw-r--r--tests/auto/controls/data/tst_menuitem.qml11
-rw-r--r--tests/auto/controls/data/tst_page.qml28
-rw-r--r--tests/auto/controls/data/tst_pageindicator.qml12
-rw-r--r--tests/auto/controls/data/tst_pane.qml20
-rw-r--r--tests/auto/controls/data/tst_popup.qml80
-rw-r--r--tests/auto/controls/data/tst_progressbar.qml24
-rw-r--r--tests/auto/controls/data/tst_radiobutton.qml33
-rw-r--r--tests/auto/controls/data/tst_radiodelegate.qml10
-rw-r--r--tests/auto/controls/data/tst_rangeslider.qml278
-rw-r--r--tests/auto/controls/data/tst_roundbutton.qml4
-rw-r--r--tests/auto/controls/data/tst_scrollbar.qml101
-rw-r--r--tests/auto/controls/data/tst_scrollindicator.qml12
-rw-r--r--tests/auto/controls/data/tst_slider.qml345
-rw-r--r--tests/auto/controls/data/tst_spinbox.qml99
-rw-r--r--tests/auto/controls/data/tst_swipedelegate.qml299
-rw-r--r--tests/auto/controls/data/tst_swipeview.qml44
-rw-r--r--tests/auto/controls/data/tst_switch.qml46
-rw-r--r--tests/auto/controls/data/tst_switchdelegate.qml31
-rw-r--r--tests/auto/controls/data/tst_tabbar.qml67
-rw-r--r--tests/auto/controls/data/tst_tabbutton.qml7
-rw-r--r--tests/auto/controls/data/tst_textarea.qml90
-rw-r--r--tests/auto/controls/data/tst_textfield.qml86
-rw-r--r--tests/auto/controls/data/tst_toolbar.qml16
-rw-r--r--tests/auto/controls/data/tst_toolbutton.qml15
-rw-r--r--tests/auto/controls/data/tst_toolseparator.qml8
-rw-r--r--tests/auto/controls/data/tst_tooltip.qml8
-rw-r--r--tests/auto/controls/data/tst_tumbler.qml82
-rw-r--r--tests/auto/controls/default/tst_default.cpp1
-rw-r--r--tests/auto/controls/material/tst_material.cpp1
-rw-r--r--tests/auto/controls/universal/tst_universal.cpp1
-rw-r--r--tests/auto/drawer/tst_drawer.cpp57
-rw-r--r--tests/auto/qquickstyle/tst_qquickstyle.cpp8
-rw-r--r--tests/auto/revisions/tst_revisions.cpp10
-rw-r--r--tests/auto/sanity/BLACKLIST8
-rw-r--r--tests/auto/sanity/tst_sanity.cpp2
-rw-r--r--tests/auto/shared/util.h2
-rw-r--r--tests/benchmarks/creationtime/tst_creationtime.cpp2
-rw-r--r--tests/benchmarks/objectcount/tst_objectcount.cpp2
-rw-r--r--tests/manual/gifs/data/qtquickcontrols2-delaybutton.qml56
-rw-r--r--tests/manual/gifs/data/qtquickcontrols2-scrollbar-snap.qml61
-rw-r--r--tests/manual/gifs/tst_gifs.cpp79
362 files changed, 10010 insertions, 4580 deletions
diff --git a/.gitignore b/.gitignore
index 24170d65..dac53591 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,6 +14,8 @@
/examples/quickcontrols2/contactlist/contactlist
/examples/quickcontrols2/flatstyle/flatstyle
/examples/quickcontrols2/gallery/gallery
+/examples/quickcontrols2/sidepanel/sidepanel
+/examples/quickcontrols2/swipetoremove/swipetoremove
/examples/quickcontrols2/texteditor/texteditor
/tests/auto/accessibility/tst_accessibility
diff --git a/.qmake.conf b/.qmake.conf
index 3a95d267..8114dfd7 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -4,4 +4,4 @@ DEFINES += QT_NO_FOREACH
QQC2_SOURCE_TREE = $$PWD
-MODULE_VERSION = 5.8.1
+MODULE_VERSION = 5.9.0
diff --git a/examples/quickcontrols2/gallery/gallery.cpp b/examples/quickcontrols2/gallery/gallery.cpp
index bbf95a0d..02801bec 100644
--- a/examples/quickcontrols2/gallery/gallery.cpp
+++ b/examples/quickcontrols2/gallery/gallery.cpp
@@ -60,6 +60,7 @@ int main(int argc, char *argv[])
QQuickStyle::setStyle(settings.value("style").toString());
QQmlApplicationEngine engine;
+ engine.rootContext()->setContextProperty("availableStyles", QQuickStyle::availableStyles());
engine.load(QUrl("qrc:/gallery.qml"));
if (engine.rootObjects().isEmpty())
return -1;
diff --git a/examples/quickcontrols2/gallery/gallery.qml b/examples/quickcontrols2/gallery/gallery.qml
index 343ed0e2..4e2c05d6 100644
--- a/examples/quickcontrols2/gallery/gallery.qml
+++ b/examples/quickcontrols2/gallery/gallery.qml
@@ -40,7 +40,7 @@
import QtQuick 2.6
import QtQuick.Layouts 1.3
-import QtQuick.Controls 2.1
+import QtQuick.Controls 2.2
import QtQuick.Controls.Material 2.1
import QtQuick.Controls.Universal 2.1
import Qt.labs.settings 1.0
@@ -131,7 +131,7 @@ ApplicationWindow {
id: drawer
width: Math.min(window.width, window.height) / 3 * 2
height: window.height
- dragMargin: stackView.depth > 1 ? 0 : undefined
+ interactive: stackView.depth === 1
ListView {
id: listView
@@ -156,6 +156,7 @@ ApplicationWindow {
ListElement { title: "Button"; source: "qrc:/pages/ButtonPage.qml" }
ListElement { title: "CheckBox"; source: "qrc:/pages/CheckBoxPage.qml" }
ListElement { title: "ComboBox"; source: "qrc:/pages/ComboBoxPage.qml" }
+ ListElement { title: "DelayButton"; source: "qrc:/pages/DelayButtonPage.qml" }
ListElement { title: "Dial"; source: "qrc:/pages/DialPage.qml" }
ListElement { title: "Dialog"; source: "qrc:/pages/DialogPage.qml" }
ListElement { title: "Delegates"; source: "qrc:/pages/DelegatePage.qml" }
@@ -254,7 +255,7 @@ ApplicationWindow {
ComboBox {
id: styleBox
property int styleIndex: -1
- model: ["Default", "Material", "Universal"]
+ model: availableStyles
Component.onCompleted: {
styleIndex = find(settings.style, Qt.MatchFixedString)
if (styleIndex !== -1)
diff --git a/examples/quickcontrols2/gallery/pages/ComboBoxPage.qml b/examples/quickcontrols2/gallery/pages/ComboBoxPage.qml
index 65824325..6b9c45da 100644
--- a/examples/quickcontrols2/gallery/pages/ComboBoxPage.qml
+++ b/examples/quickcontrols2/gallery/pages/ComboBoxPage.qml
@@ -39,7 +39,7 @@
****************************************************************************/
import QtQuick 2.6
-import QtQuick.Controls 2.1
+import QtQuick.Controls 2.2
ScrollablePage {
id: page
@@ -60,5 +60,28 @@ ScrollablePage {
model: ["First", "Second", "Third"]
anchors.horizontalCenter: parent.horizontalCenter
}
+
+ Label {
+ width: parent.width
+ wrapMode: Label.Wrap
+ horizontalAlignment: Qt.AlignHCenter
+ text: "ComboBox can be made \l editable. An editable combo box auto-"
+ + "completes its text based on what is available in the model."
+ }
+
+ ComboBox {
+ editable: true
+ model: ListModel {
+ id: model
+ ListElement { text: "Banana" }
+ ListElement { text: "Apple" }
+ ListElement { text: "Coconut" }
+ }
+ onAccepted: {
+ if (find(editText) === -1)
+ model.append({text: editText})
+ }
+ anchors.horizontalCenter: parent.horizontalCenter
+ }
}
}
diff --git a/examples/quickcontrols2/gallery/pages/DelayButtonPage.qml b/examples/quickcontrols2/gallery/pages/DelayButtonPage.qml
new file mode 100644
index 00000000..f662245e
--- /dev/null
+++ b/examples/quickcontrols2/gallery/pages/DelayButtonPage.qml
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples 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 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.6
+import QtQuick.Controls 2.2
+
+ScrollablePage {
+ id: page
+
+ Column {
+ spacing: 40
+ width: parent.width
+
+ Label {
+ width: parent.width
+ wrapMode: Label.Wrap
+ horizontalAlignment: Qt.AlignHCenter
+ text: "DelayButton is a checkable button that incorporates a delay before the "
+ + "button is activated. This delay prevents accidental presses."
+ }
+
+ DelayButton {
+ text: "DelayButton"
+ anchors.horizontalCenter: parent.horizontalCenter
+ }
+ }
+}
diff --git a/examples/quickcontrols2/quickcontrols2.pro b/examples/quickcontrols2/quickcontrols2.pro
index f9a4a7ab..3e145a41 100644
--- a/examples/quickcontrols2/quickcontrols2.pro
+++ b/examples/quickcontrols2/quickcontrols2.pro
@@ -4,4 +4,6 @@ SUBDIRS += \
chattutorial \
texteditor \
contactlist \
+ sidepanel \
+ swipetoremove \
flatstyle
diff --git a/examples/quickcontrols2/sidepanel/doc/images/qtquickcontrols2-sidepanel-landscape.png b/examples/quickcontrols2/sidepanel/doc/images/qtquickcontrols2-sidepanel-landscape.png
new file mode 100644
index 00000000..73ad4307
--- /dev/null
+++ b/examples/quickcontrols2/sidepanel/doc/images/qtquickcontrols2-sidepanel-landscape.png
Binary files differ
diff --git a/examples/quickcontrols2/sidepanel/doc/images/qtquickcontrols2-sidepanel-portrait.png b/examples/quickcontrols2/sidepanel/doc/images/qtquickcontrols2-sidepanel-portrait.png
new file mode 100644
index 00000000..ad23add5
--- /dev/null
+++ b/examples/quickcontrols2/sidepanel/doc/images/qtquickcontrols2-sidepanel-portrait.png
Binary files differ
diff --git a/examples/quickcontrols2/sidepanel/doc/src/qtquickcontrols2-sidepanel.qdoc b/examples/quickcontrols2/sidepanel/doc/src/qtquickcontrols2-sidepanel.qdoc
new file mode 100644
index 00000000..822b25a4
--- /dev/null
+++ b/examples/quickcontrols2/sidepanel/doc/src/qtquickcontrols2-sidepanel.qdoc
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example sidepanel
+ \title Qt Quick Controls 2 - Side Panel
+ \ingroup qtquickcontrols2-examples
+ \brief A non-closable persistent side panel with Drawer
+
+ This example demonstrates how \l Drawer can be used as a non-closable
+ persistent side panel.
+
+ \raw HTML
+ <div class="table"><table style="background:transparent; border:0px">
+ <tr><td style="border:0px">
+ \endraw
+ \image qtquickcontrols2-sidepanel-portrait.png
+ \caption An interactive Drawer in portrait mode
+ \raw HTML
+ </td><td style="border:0px">
+ \endraw
+ \image qtquickcontrols2-sidepanel-landscape.png
+ \caption A non-interactive Drawer in landscape mode
+ \raw HTML
+ </td></tr>
+ </table></div>
+ \endraw
+
+ When the application is in portrait mode, the drawer is an interactive
+ side panel that can be swiped open from the left edge. It appears on
+ top of the content, and blocks user interaction through its modal
+ background. When the application is in landscape mode, the drawer and
+ the content are laid out side by side.
+
+ The current orientation of the application is determined by comparing
+ the width and height of the window:
+
+ \snippet sidepanel/sidepanel.qml orientation
+
+ This is used to specify whether the drawer is \l {Popup::}{modal} and
+ \l {Drawer::}{interactive}, and to configure its \l {Drawer::}{position}
+ and \l {Popup::visible}{visibility} accordingly.
+
+ \quotefromfile sidepanel/sidepanel.qml
+ \skipto Drawer
+ \printline Drawer
+ \dots 8
+ \codeline
+ \skipto modal
+ \printuntil visible
+ \dots 8
+ \skipuntil ScrollIndicator
+ \skipuntil }
+ \printline }
+
+ \include examples-run.qdocinc
+*/
diff --git a/examples/quickcontrols2/sidepanel/images/qt-logo.png b/examples/quickcontrols2/sidepanel/images/qt-logo.png
new file mode 100644
index 00000000..90e6f905
--- /dev/null
+++ b/examples/quickcontrols2/sidepanel/images/qt-logo.png
Binary files differ
diff --git a/examples/quickcontrols2/sidepanel/images/qt-logo@2x.png b/examples/quickcontrols2/sidepanel/images/qt-logo@2x.png
new file mode 100644
index 00000000..22d111ad
--- /dev/null
+++ b/examples/quickcontrols2/sidepanel/images/qt-logo@2x.png
Binary files differ
diff --git a/examples/quickcontrols2/sidepanel/images/qt-logo@3x.png b/examples/quickcontrols2/sidepanel/images/qt-logo@3x.png
new file mode 100644
index 00000000..627746cd
--- /dev/null
+++ b/examples/quickcontrols2/sidepanel/images/qt-logo@3x.png
Binary files differ
diff --git a/examples/quickcontrols2/sidepanel/images/qt-logo@4x.png b/examples/quickcontrols2/sidepanel/images/qt-logo@4x.png
new file mode 100644
index 00000000..dc62286d
--- /dev/null
+++ b/examples/quickcontrols2/sidepanel/images/qt-logo@4x.png
Binary files differ
diff --git a/examples/quickcontrols2/sidepanel/sidepanel.cpp b/examples/quickcontrols2/sidepanel/sidepanel.cpp
new file mode 100644
index 00000000..acff3f34
--- /dev/null
+++ b/examples/quickcontrols2/sidepanel/sidepanel.cpp
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples 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 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[])
+{
+ QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+ QGuiApplication app(argc, argv);
+
+ QQmlApplicationEngine engine;
+ engine.load(QUrl("qrc:/sidepanel.qml"));
+ if (engine.rootObjects().isEmpty())
+ return -1;
+
+ return app.exec();
+}
diff --git a/examples/quickcontrols2/sidepanel/sidepanel.pro b/examples/quickcontrols2/sidepanel/sidepanel.pro
new file mode 100644
index 00000000..e2fc4aff
--- /dev/null
+++ b/examples/quickcontrols2/sidepanel/sidepanel.pro
@@ -0,0 +1,13 @@
+TEMPLATE = app
+TARGET = sidepanel
+QT += quick
+
+SOURCES += \
+ sidepanel.cpp
+
+RESOURCES += \
+ sidepanel.qml \
+ $$files(images/*.png)
+
+target.path = $$[QT_INSTALL_EXAMPLES]/quickcontrols2/sidepanel
+INSTALLS += target
diff --git a/examples/quickcontrols2/sidepanel/sidepanel.qml b/examples/quickcontrols2/sidepanel/sidepanel.qml
new file mode 100644
index 00000000..d35356e3
--- /dev/null
+++ b/examples/quickcontrols2/sidepanel/sidepanel.qml
@@ -0,0 +1,170 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples 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 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.6
+import QtQuick.Controls 2.2
+import QtQuick.Controls.Material 2.2
+
+ApplicationWindow {
+ id: window
+ width: 360
+ height: 520
+ visible: true
+ title: qsTr("Side Panel")
+
+ //! [orientation]
+ readonly property bool inPortrait: window.width < window.height
+ //! [orientation]
+
+ ToolBar {
+ id: overlayHeader
+
+ z: 1
+ width: parent.width
+ parent: window.overlay
+
+ Label {
+ id: label
+ anchors.centerIn: parent
+ text: "Qt Quick Controls 2"
+ }
+ }
+
+ Drawer {
+ id: drawer
+
+ y: overlayHeader.height
+ width: window.width / 2
+ height: window.height - overlayHeader.height
+
+ modal: inPortrait
+ interactive: inPortrait
+ position: inPortrait ? 0 : 1
+ visible: !inPortrait
+
+ ListView {
+ id: listView
+ anchors.fill: parent
+
+ headerPositioning: ListView.OverlayHeader
+ header: Pane {
+ id: header
+ z: 2
+ width: parent.width
+
+ contentHeight: logo.height
+
+ Image {
+ id: logo
+ width: parent.width
+ source: "images/qt-logo.png"
+ fillMode: implicitWidth > width ? Image.PreserveAspectFit : Image.Pad
+ }
+
+ MenuSeparator {
+ parent: header
+ width: parent.width
+ anchors.verticalCenter: parent.bottom
+ visible: !listView.atYBeginning
+ }
+ }
+
+ footer: ItemDelegate {
+ id: footer
+ text: qsTr("Footer")
+ width: parent.width
+
+ MenuSeparator {
+ parent: footer
+ width: parent.width
+ anchors.verticalCenter: parent.top
+ }
+ }
+
+ model: 10
+
+ delegate: ItemDelegate {
+ text: qsTr("Title %1").arg(index + 1)
+ width: parent.width
+ }
+
+ ScrollIndicator.vertical: ScrollIndicator { }
+ }
+ }
+
+ Flickable {
+ id: flickable
+
+ anchors.fill: parent
+ anchors.topMargin: overlayHeader.height
+ anchors.leftMargin: !inPortrait ? drawer.width : undefined
+
+ topMargin: 20
+ bottomMargin: 20
+ contentHeight: column.height
+
+ Column {
+ id: column
+ spacing: 20
+ anchors.margins: 20
+ anchors.left: parent.left
+ anchors.right: parent.right
+
+ Label {
+ font.pixelSize: 22
+ width: parent.width
+ elide: Label.ElideRight
+ horizontalAlignment: Qt.AlignHCenter
+ text: qsTr("Side Panel Example")
+ }
+
+ Label {
+ width: parent.width
+ wrapMode: Label.WordWrap
+ text: qsTr("This example demonstrates how Drawer can be used as a non-closable persistent side panel.\n\n" +
+ "When the application is in portrait mode, the drawer is an interactive side panel that can " +
+ "be swiped open from the left edge. When the application is in landscape mode, the drawer " +
+ "and the content are laid out side by side.\n\nThe application is currently in %1 mode.").arg(inPortrait ? qsTr("portrait") : qsTr("landscape"))
+ }
+ }
+
+ ScrollIndicator.vertical: ScrollIndicator { }
+ }
+}
diff --git a/examples/quickcontrols2/swipetoremove/doc/images/qtquickcontrols2-swipetoremove.png b/examples/quickcontrols2/swipetoremove/doc/images/qtquickcontrols2-swipetoremove.png
new file mode 100644
index 00000000..11005371
--- /dev/null
+++ b/examples/quickcontrols2/swipetoremove/doc/images/qtquickcontrols2-swipetoremove.png
Binary files differ
diff --git a/examples/quickcontrols2/swipetoremove/doc/src/qtquickcontrols2-swipetoremove.qdoc b/examples/quickcontrols2/swipetoremove/doc/src/qtquickcontrols2-swipetoremove.qdoc
new file mode 100644
index 00000000..84fd3873
--- /dev/null
+++ b/examples/quickcontrols2/swipetoremove/doc/src/qtquickcontrols2-swipetoremove.qdoc
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example swipetoremove
+ \title Qt Quick Controls 2 - Swipe to Remove
+ \ingroup qtquickcontrols2-examples
+ \brief Demonstrates removing list items by swipe.
+
+ This example demonstrates how \l SwipeDelegate can be used to implement
+ removal of list items by swipe. This UI pattern is often used in touch
+ user interfaces.
+
+ \image qtquickcontrols2-swipetoremove.png
+
+ Each list item can be swiped to the left, which reveals a label on the
+ \l {SwipeDelegate::swipe}{right} side indicating that the item will be
+ removed if the swipe is completed. The following snippet contains the
+ implementation of the side item.
+
+ \snippet swipetoremove/swipetoremove.qml delegate
+
+ The following snippet presents how the logic of removing items is
+ implemented. When the swipe is \l {SwipeDelegate::swipe}{completed}, it
+ starts a timer tha waits a few seconds to let the user undo the remove
+ action. Once the undo timer triggers, the item is removed from the list:
+
+ \snippet swipetoremove/swipetoremove.qml removal
+
+ Finally, the removal of an item triggers the following transitions. The
+ \l {ListView::} {remove} transition applies to the item that is removed,
+ and the \l {ListView::}{displaced} transition applies to the other items
+ that got displaced due to the removal:
+
+ \snippet swipetoremove/swipetoremove.qml transitions
+
+ \include examples-run.qdocinc
+*/
diff --git a/examples/quickcontrols2/swipetoremove/fonts/LICENSE.txt b/examples/quickcontrols2/swipetoremove/fonts/LICENSE.txt
new file mode 100644
index 00000000..7394a58d
--- /dev/null
+++ b/examples/quickcontrols2/swipetoremove/fonts/LICENSE.txt
@@ -0,0 +1,12 @@
+Font license info
+
+
+## Elusive
+
+ Copyright (C) 2013 by Aristeides Stathopoulos
+
+ Author: Aristeides Stathopoulos
+ License: SIL (http://scripts.sil.org/OFL)
+ Homepage: http://aristeides.com/
+
+
diff --git a/examples/quickcontrols2/swipetoremove/fonts/fontello.ttf b/examples/quickcontrols2/swipetoremove/fonts/fontello.ttf
new file mode 100644
index 00000000..553fd2ef
--- /dev/null
+++ b/examples/quickcontrols2/swipetoremove/fonts/fontello.ttf
Binary files differ
diff --git a/examples/quickcontrols2/swipetoremove/swipetoremove.cpp b/examples/quickcontrols2/swipetoremove/swipetoremove.cpp
new file mode 100644
index 00000000..10a43a24
--- /dev/null
+++ b/examples/quickcontrols2/swipetoremove/swipetoremove.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples 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 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>
+#include <QFontDatabase>
+
+int main(int argc, char *argv[])
+{
+ QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+ QGuiApplication app(argc, argv);
+
+ QFontDatabase::addApplicationFont(":/fonts/fontello.ttf");
+
+ QQmlApplicationEngine engine;
+ engine.load(QUrl("qrc:/swipetoremove.qml"));
+ if (engine.rootObjects().isEmpty())
+ return -1;
+
+ return app.exec();
+}
diff --git a/examples/quickcontrols2/swipetoremove/swipetoremove.pro b/examples/quickcontrols2/swipetoremove/swipetoremove.pro
new file mode 100644
index 00000000..8e6bd5f6
--- /dev/null
+++ b/examples/quickcontrols2/swipetoremove/swipetoremove.pro
@@ -0,0 +1,13 @@
+TEMPLATE = app
+TARGET = swipetoremove
+QT += qml
+
+SOURCES += \
+ swipetoremove.cpp
+
+RESOURCES += \
+ swipetoremove.qml \
+ fonts/fontello.ttf
+
+target.path = $$[QT_INSTALL_EXAMPLES]/quickcontrols2/swipetoremove
+INSTALLS += target
diff --git a/examples/quickcontrols2/swipetoremove/swipetoremove.qml b/examples/quickcontrols2/swipetoremove/swipetoremove.qml
new file mode 100644
index 00000000..5806423d
--- /dev/null
+++ b/examples/quickcontrols2/swipetoremove/swipetoremove.qml
@@ -0,0 +1,167 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples 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 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.8
+import QtQuick.Controls 2.2
+import QtQuick.Controls.Material 2.2
+
+ApplicationWindow {
+ id: window
+ width: 300
+ height: 400
+ visible: true
+ title: qsTr("Swipe to Remove")
+
+ ListView {
+ id: listView
+ anchors.fill: parent
+
+ delegate: SwipeDelegate {
+ id: delegate
+
+ text: modelData
+ width: parent.width
+
+ //! [delegate]
+ swipe.right: Rectangle {
+ width: parent.width
+ height: parent.height
+
+ clip: true
+ color: SwipeDelegate.pressed ? "#555" : "#666"
+
+ Label {
+ font.family: "Fontello"
+ text: delegate.swipe.complete ? "\ue805" // icon-cw-circled
+ : "\ue801" // icon-cancel-circled-1
+
+ padding: 20
+ anchors.fill: parent
+ horizontalAlignment: Qt.AlignRight
+ verticalAlignment: Qt.AlignVCenter
+
+ opacity: 2 * -delegate.swipe.position
+
+ color: Material.color(delegate.swipe.complete ? Material.Green : Material.Red, Material.Shade200)
+ Behavior on color { ColorAnimation { } }
+ }
+
+ Label {
+ text: qsTr("Removed")
+ color: "white"
+
+ padding: 20
+ anchors.fill: parent
+ horizontalAlignment: Qt.AlignLeft
+ verticalAlignment: Qt.AlignVCenter
+
+ opacity: delegate.swipe.complete ? 1 : 0
+ Behavior on opacity { NumberAnimation { } }
+ }
+
+ SwipeDelegate.onClicked: delegate.swipe.close()
+ SwipeDelegate.onPressedChanged: undoTimer.stop()
+ }
+ //! [delegate]
+
+ //! [removal]
+ Timer {
+ id: undoTimer
+ interval: 3600
+ onTriggered: listModel.remove(index)
+ }
+
+ swipe.onCompleted: undoTimer.start()
+ //! [removal]
+ }
+
+ model: ListModel {
+ id: listModel
+ ListElement { text: "Lorem ipsum dolor sit amet" }
+ ListElement { text: "Curabitur sit amet risus" }
+ ListElement { text: "Suspendisse vehicula nisi" }
+ ListElement { text: "Mauris imperdiet libero" }
+ ListElement { text: "Sed vitae dui aliquet augue" }
+ ListElement { text: "Praesent in elit eu nulla" }
+ ListElement { text: "Etiam vitae magna" }
+ ListElement { text: "Pellentesque eget elit euismod" }
+ ListElement { text: "Nulla at enim porta" }
+ ListElement { text: "Fusce tincidunt odio" }
+ ListElement { text: "Ut non ex a ligula molestie" }
+ ListElement { text: "Nam vitae justo scelerisque" }
+ ListElement { text: "Vestibulum pulvinar tellus" }
+ ListElement { text: "Quisque dignissim leo sed gravida" }
+ }
+
+ //! [transitions]
+ remove: Transition {
+ SequentialAnimation {
+ PauseAnimation { duration: 125 }
+ NumberAnimation { property: "height"; to: 0; easing.type: Easing.InOutQuad }
+ }
+ }
+
+ displaced: Transition {
+ SequentialAnimation {
+ PauseAnimation { duration: 125 }
+ NumberAnimation { property: "y"; easing.type: Easing.InOutQuad }
+ }
+ }
+ //! [transitions]
+
+ ScrollIndicator.vertical: ScrollIndicator { }
+ }
+
+ Label {
+ id: placeholder
+ text: qsTr("Swipe no more")
+
+ anchors.margins: 60
+ anchors.fill: parent
+
+ opacity: 0.5
+ visible: listView.count === 0
+
+ horizontalAlignment: Qt.AlignHCenter
+ verticalAlignment: Qt.AlignVCenter
+ wrapMode: Label.WordWrap
+ font.pixelSize: 18
+ }
+}
diff --git a/src/imports/controls/AbstractButton.qml b/src/imports/controls/AbstractButton.qml
index 55d8c370..96987cf2 100644
--- a/src/imports/controls/AbstractButton.qml
+++ b/src/imports/controls/AbstractButton.qml
@@ -34,8 +34,8 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
T.AbstractButton {
id: control
diff --git a/src/imports/controls/ApplicationWindow.qml b/src/imports/controls/ApplicationWindow.qml
index 6233bd83..1dd39279 100644
--- a/src/imports/controls/ApplicationWindow.qml
+++ b/src/imports/controls/ApplicationWindow.qml
@@ -34,11 +34,11 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
import QtQuick.Window 2.2
-import QtQuick.Templates 2.1 as T
+import QtQuick.Templates 2.2 as T
T.ApplicationWindow {
id: window
diff --git a/src/imports/controls/BusyIndicator.qml b/src/imports/controls/BusyIndicator.qml
index 2d961241..234c2e01 100644
--- a/src/imports/controls/BusyIndicator.qml
+++ b/src/imports/controls/BusyIndicator.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Templates 2.2 as T
T.BusyIndicator {
id: control
@@ -47,17 +47,12 @@ T.BusyIndicator {
padding: 6
- contentItem: BusyRing {
- id: ring
+ contentItem: BusyIndicatorImpl {
implicitWidth: 48
implicitHeight: 48
- opacity: control.running ? 1 : 0
-
- Behavior on opacity { OpacityAnimator { duration: 250 } }
- BusyRingAnimator {
- target: ring
- running: control.visible && control.running
- }
+ opacity: control.running ? 1 : 0
+ visible: control.running || animator.running
+ Behavior on opacity { OpacityAnimator { id: animator; duration: 250 } }
}
}
diff --git a/src/imports/controls/Button.qml b/src/imports/controls/Button.qml
index 61d2290e..6c150d5d 100644
--- a/src/imports/controls/Button.qml
+++ b/src/imports/controls/Button.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Templates 2.2 as T
T.Button {
id: control
diff --git a/src/imports/controls/CheckBox.qml b/src/imports/controls/CheckBox.qml
index 909da0d3..7945ca72 100644
--- a/src/imports/controls/CheckBox.qml
+++ b/src/imports/controls/CheckBox.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
T.CheckBox {
id: control
diff --git a/src/imports/controls/CheckDelegate.qml b/src/imports/controls/CheckDelegate.qml
index 0206071d..05a0baf6 100644
--- a/src/imports/controls/CheckDelegate.qml
+++ b/src/imports/controls/CheckDelegate.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
T.CheckDelegate {
id: control
diff --git a/src/imports/controls/CheckIndicator.qml b/src/imports/controls/CheckIndicator.qml
index 2b6c71bd..0be3e6cd 100644
--- a/src/imports/controls/CheckIndicator.qml
+++ b/src/imports/controls/CheckIndicator.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
Rectangle {
id: indicator
diff --git a/src/imports/controls/ComboBox.qml b/src/imports/controls/ComboBox.qml
index e131519d..60e2427b 100644
--- a/src/imports/controls/ComboBox.qml
+++ b/src/imports/controls/ComboBox.qml
@@ -34,11 +34,11 @@
**
****************************************************************************/
-import QtQuick 2.8
+import QtQuick 2.9
import QtQuick.Window 2.2
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
-import QtQuick.Templates 2.1 as T
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Templates 2.2 as T
T.ComboBox {
id: control
@@ -50,13 +50,11 @@ T.ComboBox {
indicator ? indicator.implicitHeight : 0) + topPadding + bottomPadding)
baselineOffset: contentItem.y + contentItem.baselineOffset
- spacing: 8
- padding: 6
- leftPadding: padding + 6
- rightPadding: padding + 6
+ leftPadding: padding + (!control.mirrored || !indicator || !indicator.visible ? 0 : indicator.width + spacing)
+ rightPadding: padding + (control.mirrored || !indicator || !indicator.visible ? 0 : indicator.width + spacing)
delegate: ItemDelegate {
- width: control.popup.width
+ width: parent.width
text: control.textRole ? (Array.isArray(control.model) ? modelData[control.textRole] : model[control.textRole]) : modelData
font.weight: control.currentIndex === index ? Font.DemiBold : Font.Normal
highlighted: control.highlightedIndex == index
@@ -64,47 +62,62 @@ T.ComboBox {
}
indicator: Image {
- x: control.mirrored ? control.leftPadding : control.width - width - control.rightPadding
+ x: control.mirrored ? control.padding : control.width - width - control.padding
y: control.topPadding + (control.availableHeight - height) / 2
- source: "image://default/double-arrow/" + (control.visualFocus ? Default.focusColor : Default.textColor)
+ source: "image://default/double-arrow/" + (!control.editable && control.visualFocus ? Default.focusColor : Default.textColor)
sourceSize.width: width
sourceSize.height: height
opacity: enabled ? 1 : 0.3
}
- contentItem: Text {
- leftPadding: control.mirrored && control.indicator ? control.indicator.width + control.spacing : 0
- rightPadding: !control.mirrored && control.indicator ? control.indicator.width + control.spacing : 0
+ contentItem: T.TextField {
+ leftPadding: !control.mirrored ? 12 : control.editable && activeFocus ? 3 : 1
+ rightPadding: control.mirrored ? 12 : control.editable && activeFocus ? 3 : 1
+ topPadding: 6 - control.padding
+ bottomPadding: 6 - control.padding
+
+ text: control.editable ? control.editText : control.displayText
+
+ enabled: control.editable
+ autoScroll: control.editable
+ readOnly: control.popup.visible
+ inputMethodHints: control.inputMethodHints
+ validator: control.validator
- text: control.displayText
font: control.font
- color: control.visualFocus ? Default.focusColor : Default.textColor
+ color: !control.editable && control.visualFocus ? Default.focusColor : Default.textColor
+ selectionColor: Default.focusColor
+ selectedTextColor: Default.textLightColor
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
- elide: Text.ElideRight
- opacity: enabled ? 1 : 0.3
+ opacity: control.enabled ? 1 : 0.3
+
+ background: Rectangle {
+ visible: control.editable && !control.flat
+ border.width: parent && parent.activeFocus ? 2 : 1
+ border.color: parent && parent.activeFocus ? Default.focusColor : Default.buttonColor
+ }
}
background: Rectangle {
implicitWidth: 120
implicitHeight: 40
- color: control.visualFocus ? (control.pressed ? Default.focusPressedColor : Default.focusLightColor) :
- (control.pressed || popup.visible ? Default.buttonPressedColor : Default.buttonColor)
+ color: !control.editable && control.visualFocus ? (control.pressed ? Default.focusPressedColor : Default.focusLightColor) :
+ (control.down || popup.visible ? Default.buttonPressedColor : Default.buttonColor)
border.color: Default.focusColor
- border.width: control.visualFocus ? 2 : 0
- visible: !control.flat || control.pressed
+ border.width: !control.editable && control.visualFocus ? 2 : 0
+ visible: !control.flat || control.down
}
popup: T.Popup {
- y: control.height - (control.visualFocus ? 0 : 1)
+ y: control.height
width: control.width
implicitHeight: contentItem.implicitHeight
topMargin: 6
bottomMargin: 6
contentItem: ListView {
- id: listview
clip: true
implicitHeight: contentHeight
model: control.popup.visible ? control.delegateModel : null
@@ -114,9 +127,8 @@ T.ComboBox {
Rectangle {
z: 10
- parent: listview
- width: listview.width
- height: listview.height
+ width: parent.width
+ height: parent.height
color: "transparent"
border.color: Default.frameLightColor
}
diff --git a/src/imports/controls/Container.qml b/src/imports/controls/Container.qml
index 2643a40d..5844e0a2 100644
--- a/src/imports/controls/Container.qml
+++ b/src/imports/controls/Container.qml
@@ -34,8 +34,8 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
T.Container {
id: control
diff --git a/src/imports/controls/Control.qml b/src/imports/controls/Control.qml
index e7d483e0..85f40ae5 100644
--- a/src/imports/controls/Control.qml
+++ b/src/imports/controls/Control.qml
@@ -34,8 +34,8 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
T.Control {
id: control
diff --git a/src/imports/controls/DelayButton.qml b/src/imports/controls/DelayButton.qml
new file mode 100644
index 00000000..4a569fcf
--- /dev/null
+++ b/src/imports/controls/DelayButton.qml
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Templates 2.2 as T
+
+T.DelayButton {
+ id: control
+
+ implicitWidth: Math.max(background ? background.implicitWidth : 0,
+ contentItem.implicitWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(background ? background.implicitHeight : 0,
+ contentItem.implicitHeight + topPadding + bottomPadding)
+ baselineOffset: contentItem.y + contentItem.baselineOffset
+
+ padding: 6
+ leftPadding: padding + 2
+ rightPadding: padding + 2
+
+ transition: Transition {
+ NumberAnimation {
+ duration: control.delay * (control.pressed ? 1.0 - control.progress : 0.3 * control.progress)
+ }
+ }
+
+ contentItem: Item {
+ implicitWidth: label.implicitWidth
+ implicitHeight: label.implicitHeight
+
+ Item {
+ x: -control.leftPadding + (control.progress * control.width)
+ width: (1.0 - control.progress) * control.width
+ height: parent.height
+
+ clip: control.progress > 0
+ visible: control.progress < 1
+
+ Text {
+ id: label
+ x: -parent.x
+ width: control.availableWidth
+ height: parent.height
+
+ text: control.text
+ font: control.font
+ opacity: enabled ? 1 : 0.3
+ color: control.visualFocus ? Default.focusColor : (control.down ? Default.textDarkColor : Default.textColor)
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ elide: Text.ElideRight
+ }
+ }
+
+ Item {
+ x: -control.leftPadding
+ width: control.progress * control.width
+ height: parent.height
+
+ clip: control.progress > 0
+ visible: control.progress > 0
+
+ Text {
+ x: control.leftPadding
+ width: control.availableWidth
+ height: parent.height
+
+ text: control.text
+ font: control.font
+ opacity: enabled ? 1 : 0.3
+ color: Default.textLightColor
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ elide: Text.ElideRight
+ }
+ }
+ }
+
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: control.visualFocus ? (control.down ? Default.focusPressedColor : Default.focusLightColor) : (control.down ? Default.buttonPressedColor : Default.buttonColor)
+ border.color: Default.focusColor
+ border.width: control.visualFocus ? 2 : 0
+
+ Rectangle {
+ width: control.progress * parent.width
+ height: parent.height
+ color: control.visualFocus ? (control.down ? Default.buttonCheckedFocusColor : Default.focusColor) : (control.down ? Default.buttonCheckedPressedColor : Default.textColor)
+ }
+ }
+}
diff --git a/src/imports/controls/Dial.qml b/src/imports/controls/Dial.qml
index 2a9202f4..affcfa62 100644
--- a/src/imports/controls/Dial.qml
+++ b/src/imports/controls/Dial.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Templates 2.2 as T
T.Dial {
id: control
diff --git a/src/imports/controls/Dialog.qml b/src/imports/controls/Dialog.qml
index e8d8285b..84c33b63 100644
--- a/src/imports/controls/Dialog.qml
+++ b/src/imports/controls/Dialog.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
T.Dialog {
id: control
diff --git a/src/imports/controls/DialogButtonBox.qml b/src/imports/controls/DialogButtonBox.qml
index 8ac39fa8..ba9fa52f 100644
--- a/src/imports/controls/DialogButtonBox.qml
+++ b/src/imports/controls/DialogButtonBox.qml
@@ -34,8 +34,8 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
T.DialogButtonBox {
id: control
diff --git a/src/imports/controls/Drawer.qml b/src/imports/controls/Drawer.qml
index 89c2c1a2..b3240ca3 100644
--- a/src/imports/controls/Drawer.qml
+++ b/src/imports/controls/Drawer.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Templates 2.2 as T
T.Drawer {
id: control
diff --git a/src/imports/controls/Frame.qml b/src/imports/controls/Frame.qml
index 360f3cb5..5add003f 100644
--- a/src/imports/controls/Frame.qml
+++ b/src/imports/controls/Frame.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Templates 2.2 as T
T.Frame {
id: control
diff --git a/src/imports/controls/GroupBox.qml b/src/imports/controls/GroupBox.qml
index 994100aa..ee81250b 100644
--- a/src/imports/controls/GroupBox.qml
+++ b/src/imports/controls/GroupBox.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Templates 2.2 as T
T.GroupBox {
id: control
diff --git a/src/imports/controls/ItemDelegate.qml b/src/imports/controls/ItemDelegate.qml
index e31fb7ca..6ee03ca2 100644
--- a/src/imports/controls/ItemDelegate.qml
+++ b/src/imports/controls/ItemDelegate.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Templates 2.2 as T
T.ItemDelegate {
id: control
diff --git a/src/imports/controls/Label.qml b/src/imports/controls/Label.qml
index a3e4ab78..d2052774 100644
--- a/src/imports/controls/Label.qml
+++ b/src/imports/controls/Label.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Templates 2.2 as T
T.Label {
id: control
diff --git a/src/imports/controls/Menu.qml b/src/imports/controls/Menu.qml
index 71dcf883..dc428629 100644
--- a/src/imports/controls/Menu.qml
+++ b/src/imports/controls/Menu.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Templates 2.2 as T
T.Menu {
id: control
diff --git a/src/imports/controls/MenuItem.qml b/src/imports/controls/MenuItem.qml
index bf6bab71..d2420d86 100644
--- a/src/imports/controls/MenuItem.qml
+++ b/src/imports/controls/MenuItem.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Templates 2.2 as T
T.MenuItem {
id: control
diff --git a/src/imports/controls/MenuSeparator.qml b/src/imports/controls/MenuSeparator.qml
index 7977d4a5..10f99322 100644
--- a/src/imports/controls/MenuSeparator.qml
+++ b/src/imports/controls/MenuSeparator.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Templates 2.2 as T
T.MenuSeparator {
id: control
diff --git a/src/imports/controls/Page.qml b/src/imports/controls/Page.qml
index 1ee064f2..64c16bf4 100644
--- a/src/imports/controls/Page.qml
+++ b/src/imports/controls/Page.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Templates 2.2 as T
T.Page {
id: control
diff --git a/src/imports/controls/PageIndicator.qml b/src/imports/controls/PageIndicator.qml
index 1a2e5fae..3ff7d0c1 100644
--- a/src/imports/controls/PageIndicator.qml
+++ b/src/imports/controls/PageIndicator.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Templates 2.2 as T
T.PageIndicator {
id: control
diff --git a/src/imports/controls/Pane.qml b/src/imports/controls/Pane.qml
index f95efa5f..7ed7f0d8 100644
--- a/src/imports/controls/Pane.qml
+++ b/src/imports/controls/Pane.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Templates 2.2 as T
T.Pane {
id: control
diff --git a/src/imports/controls/Popup.qml b/src/imports/controls/Popup.qml
index 132f4f78..2c68154a 100644
--- a/src/imports/controls/Popup.qml
+++ b/src/imports/controls/Popup.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Templates 2.2 as T
T.Popup {
id: control
diff --git a/src/imports/controls/ProgressBar.qml b/src/imports/controls/ProgressBar.qml
index 51292b42..eae6c019 100644
--- a/src/imports/controls/ProgressBar.qml
+++ b/src/imports/controls/ProgressBar.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
T.ProgressBar {
id: control
@@ -47,18 +47,12 @@ T.ProgressBar {
implicitHeight: Math.max(background ? background.implicitHeight : 0,
contentItem.implicitHeight + topPadding + bottomPadding)
- contentItem: ProgressStrip {
- id: strip
+ contentItem: ProgressBarImpl {
implicitHeight: 6
implicitWidth: 116
scale: control.mirrored ? -1 : 1
progress: control.position
- indeterminate: control.indeterminate
-
- ProgressStripAnimator {
- target: strip
- running: control.visible && control.indeterminate
- }
+ indeterminate: control.visible && control.indeterminate
}
background: Rectangle {
diff --git a/src/imports/controls/RadioButton.qml b/src/imports/controls/RadioButton.qml
index 618bab93..878a0fe3 100644
--- a/src/imports/controls/RadioButton.qml
+++ b/src/imports/controls/RadioButton.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Templates 2.2 as T
T.RadioButton {
id: control
diff --git a/src/imports/controls/RadioDelegate.qml b/src/imports/controls/RadioDelegate.qml
index 61bc230e..03cd83bd 100644
--- a/src/imports/controls/RadioDelegate.qml
+++ b/src/imports/controls/RadioDelegate.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Templates 2.2 as T
T.RadioDelegate {
id: control
diff --git a/src/imports/controls/RadioIndicator.qml b/src/imports/controls/RadioIndicator.qml
index 00b4c762..d9889fba 100644
--- a/src/imports/controls/RadioIndicator.qml
+++ b/src/imports/controls/RadioIndicator.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
Rectangle {
implicitWidth: 28
diff --git a/src/imports/controls/RangeSlider.qml b/src/imports/controls/RangeSlider.qml
index 6e126941..5f09d224 100644
--- a/src/imports/controls/RangeSlider.qml
+++ b/src/imports/controls/RangeSlider.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Templates 2.2 as T
T.RangeSlider {
id: control
diff --git a/src/imports/controls/RoundButton.qml b/src/imports/controls/RoundButton.qml
index 9df611c3..c16713b0 100644
--- a/src/imports/controls/RoundButton.qml
+++ b/src/imports/controls/RoundButton.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Templates 2.2 as T
T.RoundButton {
id: control
diff --git a/src/imports/controls/ScrollBar.qml b/src/imports/controls/ScrollBar.qml
index 16d45803..07ded9b5 100644
--- a/src/imports/controls/ScrollBar.qml
+++ b/src/imports/controls/ScrollBar.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Templates 2.2 as T
T.ScrollBar {
id: control
diff --git a/src/imports/controls/ScrollIndicator.qml b/src/imports/controls/ScrollIndicator.qml
index 2c3033dd..12ec2d40 100644
--- a/src/imports/controls/ScrollIndicator.qml
+++ b/src/imports/controls/ScrollIndicator.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Templates 2.2 as T
T.ScrollIndicator {
id: control
diff --git a/src/imports/controls/Slider.qml b/src/imports/controls/Slider.qml
index 17e98585..37145cad 100644
--- a/src/imports/controls/Slider.qml
+++ b/src/imports/controls/Slider.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Templates 2.2 as T
T.Slider {
id: control
diff --git a/src/imports/controls/SpinBox.qml b/src/imports/controls/SpinBox.qml
index 8323ecaa..9aca4d7c 100644
--- a/src/imports/controls/SpinBox.qml
+++ b/src/imports/controls/SpinBox.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Templates 2.2 as T
T.SpinBox {
id: control
@@ -76,7 +76,7 @@ T.SpinBox {
readOnly: !control.editable
validator: control.validator
- inputMethodHints: Qt.ImhDigitsOnly
+ inputMethodHints: control.inputMethodHints
Rectangle {
x: -6 - (down.indicator ? 1 : 0)
diff --git a/src/imports/controls/StackView.qml b/src/imports/controls/StackView.qml
index 6af30b04..6d52aaed 100644
--- a/src/imports/controls/StackView.qml
+++ b/src/imports/controls/StackView.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Templates 2.2 as T
T.StackView {
id: control
diff --git a/src/imports/controls/SwipeDelegate.qml b/src/imports/controls/SwipeDelegate.qml
index 7a3e65a0..d9f72da9 100644
--- a/src/imports/controls/SwipeDelegate.qml
+++ b/src/imports/controls/SwipeDelegate.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Templates 2.2 as T
T.SwipeDelegate {
id: control
@@ -52,6 +52,8 @@ T.SwipeDelegate {
padding: 12
spacing: 12
+ swipe.transition: Transition { SmoothedAnimation { velocity: 3; easing.type: Easing.InOutCubic } }
+
contentItem: Text {
leftPadding: control.mirrored ? (control.indicator ? control.indicator.width : 0) + control.spacing : 0
rightPadding: !control.mirrored ? (control.indicator ? control.indicator.width : 0) + control.spacing : 0
@@ -63,27 +65,11 @@ T.SwipeDelegate {
visible: control.text
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
-
- Behavior on x {
- enabled: !control.down
- NumberAnimation {
- easing.type: Easing.InOutCubic
- duration: 400
- }
- }
}
background: Rectangle {
color: control.visualFocus
? (control.down ? Default.focusPressedColor : Default.delegateFocusColor)
: (control.down ? Default.delegatePressedColor : Default.backgroundColor)
-
- Behavior on x {
- enabled: !control.down
- NumberAnimation {
- easing.type: Easing.InOutCubic
- duration: 400
- }
- }
}
}
diff --git a/src/imports/controls/SwipeView.qml b/src/imports/controls/SwipeView.qml
index 75df997b..df569721 100644
--- a/src/imports/controls/SwipeView.qml
+++ b/src/imports/controls/SwipeView.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Templates 2.2 as T
T.SwipeView {
id: control
diff --git a/src/imports/controls/Switch.qml b/src/imports/controls/Switch.qml
index 8db888b3..55b08039 100644
--- a/src/imports/controls/Switch.qml
+++ b/src/imports/controls/Switch.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
T.Switch {
id: control
diff --git a/src/imports/controls/SwitchDelegate.qml b/src/imports/controls/SwitchDelegate.qml
index f819fb02..6536ac53 100644
--- a/src/imports/controls/SwitchDelegate.qml
+++ b/src/imports/controls/SwitchDelegate.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
T.SwitchDelegate {
id: control
diff --git a/src/imports/controls/SwitchIndicator.qml b/src/imports/controls/SwitchIndicator.qml
index 797f7992..347b2293 100644
--- a/src/imports/controls/SwitchIndicator.qml
+++ b/src/imports/controls/SwitchIndicator.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
Item {
implicitWidth: 56
diff --git a/src/imports/controls/TabBar.qml b/src/imports/controls/TabBar.qml
index 24c0f101..6e6b7d74 100644
--- a/src/imports/controls/TabBar.qml
+++ b/src/imports/controls/TabBar.qml
@@ -34,23 +34,21 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
T.TabBar {
id: control
implicitWidth: Math.max(background ? background.implicitWidth : 0,
- contentItem.implicitWidth + leftPadding + rightPadding)
+ contentWidth + leftPadding + rightPadding)
implicitHeight: Math.max(background ? background.implicitHeight : 0,
- contentItem.implicitHeight + topPadding + bottomPadding)
+ contentHeight + topPadding + bottomPadding)
spacing: 1
+ contentHeight: 40
contentItem: ListView {
- implicitWidth: contentWidth
- implicitHeight: 40
-
model: control.contentModel
currentIndex: control.currentIndex
diff --git a/src/imports/controls/TabButton.qml b/src/imports/controls/TabButton.qml
index a6350bca..acdda056 100644
--- a/src/imports/controls/TabButton.qml
+++ b/src/imports/controls/TabButton.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Templates 2.2 as T
T.TabButton {
id: control
diff --git a/src/imports/controls/TextArea.qml b/src/imports/controls/TextArea.qml
index e3fe71dc..cbba5912 100644
--- a/src/imports/controls/TextArea.qml
+++ b/src/imports/controls/TextArea.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Templates 2.2 as T
T.TextArea {
id: control
@@ -57,7 +57,7 @@ T.TextArea {
selectionColor: Default.textSelectionColor
selectedTextColor: color
- Text {
+ PlaceholderText {
id: placeholder
x: control.leftPadding
y: control.topPadding
@@ -67,7 +67,6 @@ T.TextArea {
text: control.placeholderText
font: control.font
color: Default.textDisabledLightColor
- horizontalAlignment: control.horizontalAlignment
verticalAlignment: control.verticalAlignment
visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter)
elide: Text.ElideRight
diff --git a/src/imports/controls/TextField.qml b/src/imports/controls/TextField.qml
index e2002cf3..980ff172 100644
--- a/src/imports/controls/TextField.qml
+++ b/src/imports/controls/TextField.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Templates 2.2 as T
T.TextField {
id: control
@@ -58,7 +58,7 @@ T.TextField {
selectedTextColor: color
verticalAlignment: TextInput.AlignVCenter
- Text {
+ PlaceholderText {
id: placeholder
x: control.leftPadding
y: control.topPadding
@@ -68,7 +68,6 @@ T.TextField {
text: control.placeholderText
font: control.font
color: Default.textDisabledColor
- horizontalAlignment: control.horizontalAlignment
verticalAlignment: control.verticalAlignment
visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter)
elide: Text.ElideRight
diff --git a/src/imports/controls/ToolBar.qml b/src/imports/controls/ToolBar.qml
index 6d3b7e38..e3d4fec3 100644
--- a/src/imports/controls/ToolBar.qml
+++ b/src/imports/controls/ToolBar.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Templates 2.2 as T
T.ToolBar {
id: control
diff --git a/src/imports/controls/ToolButton.qml b/src/imports/controls/ToolButton.qml
index 7f815ed2..6199607a 100644
--- a/src/imports/controls/ToolButton.qml
+++ b/src/imports/controls/ToolButton.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Templates 2.2 as T
T.ToolButton {
id: control
diff --git a/src/imports/controls/ToolSeparator.qml b/src/imports/controls/ToolSeparator.qml
index 9c3eb3e1..d9a06a7c 100644
--- a/src/imports/controls/ToolSeparator.qml
+++ b/src/imports/controls/ToolSeparator.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Templates 2.2 as T
T.ToolSeparator {
id: control
diff --git a/src/imports/controls/ToolTip.qml b/src/imports/controls/ToolTip.qml
index fdccf5cb..587fc042 100644
--- a/src/imports/controls/ToolTip.qml
+++ b/src/imports/controls/ToolTip.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Templates 2.2 as T
T.ToolTip {
id: control
diff --git a/src/imports/controls/Tumbler.qml b/src/imports/controls/Tumbler.qml
index b0c423c7..3659e770 100644
--- a/src/imports/controls/Tumbler.qml
+++ b/src/imports/controls/Tumbler.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Templates 2.2 as T
T.Tumbler {
id: control
diff --git a/src/imports/controls/controls.pri b/src/imports/controls/controls.pri
index 79e03db5..04e31103 100644
--- a/src/imports/controls/controls.pri
+++ b/src/imports/controls/controls.pri
@@ -1,13 +1,13 @@
HEADERS += \
- $$PWD/qquickbusyindicatorring_p.h \
- $$PWD/qquickprogressstrip_p.h \
$$PWD/qquickdialring_p.h \
- $$PWD/qquickdefaultstyle_p.h
+ $$PWD/qquickdefaultbusyindicator_p.h \
+ $$PWD/qquickdefaultprogressbar_p.h \
+ $$PWD/qquickdefaultstyle_p.h \
SOURCES += \
- $$PWD/qquickbusyindicatorring.cpp \
- $$PWD/qquickprogressstrip.cpp \
$$PWD/qquickdialring.cpp \
+ $$PWD/qquickdefaultbusyindicator.cpp \
+ $$PWD/qquickdefaultprogressbar.cpp \
$$PWD/qquickdefaultstyle.cpp
QML_CONTROLS = \
@@ -21,6 +21,7 @@ QML_CONTROLS = \
ComboBox.qml \
Container.qml \
Control.qml \
+ DelayButton.qml \
Dial.qml \
Dialog.qml \
DialogButtonBox.qml \
diff --git a/src/imports/controls/doc/images/qtquickcontrols2-delaybutton-custom.png b/src/imports/controls/doc/images/qtquickcontrols2-delaybutton-custom.png
new file mode 100644
index 00000000..be7f2586
--- /dev/null
+++ b/src/imports/controls/doc/images/qtquickcontrols2-delaybutton-custom.png
Binary files differ
diff --git a/src/imports/controls/doc/images/qtquickcontrols2-delaybutton.gif b/src/imports/controls/doc/images/qtquickcontrols2-delaybutton.gif
new file mode 100644
index 00000000..16a198f9
--- /dev/null
+++ b/src/imports/controls/doc/images/qtquickcontrols2-delaybutton.gif
Binary files differ
diff --git a/src/imports/controls/doc/images/qtquickcontrols2-scrollbar-nosnap.gif b/src/imports/controls/doc/images/qtquickcontrols2-scrollbar-nosnap.gif
new file mode 100644
index 00000000..f61ac5b4
--- /dev/null
+++ b/src/imports/controls/doc/images/qtquickcontrols2-scrollbar-nosnap.gif
Binary files differ
diff --git a/src/imports/controls/doc/images/qtquickcontrols2-scrollbar-snapalways.gif b/src/imports/controls/doc/images/qtquickcontrols2-scrollbar-snapalways.gif
new file mode 100644
index 00000000..438d4a33
--- /dev/null
+++ b/src/imports/controls/doc/images/qtquickcontrols2-scrollbar-snapalways.gif
Binary files differ
diff --git a/src/imports/controls/doc/images/qtquickcontrols2-scrollbar-snaponrelease.gif b/src/imports/controls/doc/images/qtquickcontrols2-scrollbar-snaponrelease.gif
new file mode 100644
index 00000000..c2fa67b0
--- /dev/null
+++ b/src/imports/controls/doc/images/qtquickcontrols2-scrollbar-snaponrelease.gif
Binary files differ
diff --git a/src/imports/controls/doc/snippets/qtquickcontrols2-swipedelegate-transition.qml b/src/imports/controls/doc/snippets/qtquickcontrols2-swipedelegate-transition.qml
new file mode 100644
index 00000000..a5e81ab7
--- /dev/null
+++ b/src/imports/controls/doc/snippets/qtquickcontrols2-swipedelegate-transition.qml
@@ -0,0 +1,37 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+
+//! [1]
+SwipeDelegate {
+ swipe.transition: Transition {
+ SmoothedAnimation { velocity: 3; easing.type: Easing.InOutCubic }
+ }
+}
+//! [1]
diff --git a/src/imports/controls/doc/snippets/qtquickcontrols2-tumbler-listView.qml b/src/imports/controls/doc/snippets/qtquickcontrols2-tumbler-listView.qml
index d645b9c4..deffd408 100644
--- a/src/imports/controls/doc/snippets/qtquickcontrols2-tumbler-listView.qml
+++ b/src/imports/controls/doc/snippets/qtquickcontrols2-tumbler-listView.qml
@@ -39,7 +39,7 @@ Tumbler {
snapMode: ListView.SnapToItem
highlightRangeMode: ListView.StrictlyEnforceRange
preferredHighlightBegin: height / 2 - (height / tumbler.visibleItemCount / 2)
- preferredHighlightEnd: height / 2 + (height / tumbler.visibleItemCount / 2)
+ preferredHighlightEnd: height / 2 + (height / tumbler.visibleItemCount / 2)
clip: true
}
}
diff --git a/src/imports/controls/doc/snippets/screenshots/qtquickcontrols2-combobox-custom.qml b/src/imports/controls/doc/snippets/screenshots/qtquickcontrols2-combobox-custom.qml
index f4e4184c..0b3618b7 100644
--- a/src/imports/controls/doc/snippets/screenshots/qtquickcontrols2-combobox-custom.qml
+++ b/src/imports/controls/doc/snippets/screenshots/qtquickcontrols2-combobox-custom.qml
@@ -92,12 +92,12 @@ ComboBox {
popup: Popup {
y: control.height - 1
width: control.width
- implicitHeight: listview.contentHeight
+ implicitHeight: contentItem.implicitHeight
padding: 1
contentItem: ListView {
- id: listview
clip: true
+ implicitHeight: contentHeight
model: control.popup.visible ? control.delegateModel : null
currentIndex: control.highlightedIndex
diff --git a/src/imports/controls/doc/snippets/screenshots/qtquickcontrols2-delaybutton-custom.qml b/src/imports/controls/doc/snippets/screenshots/qtquickcontrols2-delaybutton-custom.qml
new file mode 100644
index 00000000..2453e2d6
--- /dev/null
+++ b/src/imports/controls/doc/snippets/screenshots/qtquickcontrols2-delaybutton-custom.qml
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [file]
+import QtQuick 2.6
+import QtQuick.Controls 2.2
+
+DelayButton {
+ id: control
+ checked: true
+ text: qsTr("Delay\nButton")
+
+ contentItem: Text {
+ text: control.text
+ font: control.font
+ opacity: enabled ? 1.0 : 0.3
+ color: "white"
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ elide: Text.ElideRight
+ }
+
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 100
+ opacity: enabled ? 1 : 0.3
+ color: control.down ? "#17a81a" : "#21be2b"
+ radius: size / 2
+
+ readonly property real size: Math.min(control.width, control.height)
+ width: size
+ height: size
+ anchors.centerIn: parent
+
+ Canvas {
+ id: canvas
+ anchors.fill: parent
+
+ Connections {
+ target: control
+ onProgressChanged: canvas.requestPaint()
+ }
+
+ onPaint: {
+ var ctx = getContext("2d")
+ ctx.clearRect(0, 0, width, height)
+ ctx.strokeStyle = "white"
+ ctx.lineWidth = parent.size / 20
+ ctx.beginPath()
+ var startAngle = Math.PI / 5 * 3
+ var endAngle = startAngle + control.progress * Math.PI / 5 * 9
+ ctx.arc(width / 2, height / 2, width / 2 - ctx.lineWidth / 2 - 2, startAngle, endAngle)
+ ctx.stroke()
+ }
+ }
+ }
+}
+//! [file]
diff --git a/src/imports/controls/doc/src/includes/inputmethodhints.qdocinc b/src/imports/controls/doc/src/includes/inputmethodhints.qdocinc
new file mode 100644
index 00000000..73710e1e
--- /dev/null
+++ b/src/imports/controls/doc/src/includes/inputmethodhints.qdocinc
@@ -0,0 +1,38 @@
+//! [flags]
+The value is a bit-wise combination of flags or \c Qt.ImhNone if no hints are set.
+
+Flags that alter behavior are:
+
+\list
+\li Qt.ImhHiddenText - Characters should be hidden, as is typically used when entering passwords.
+\li Qt.ImhSensitiveData - Typed text should not be stored by the active input method
+ in any persistent storage like predictive user dictionary.
+\li Qt.ImhNoAutoUppercase - The input method should not try to automatically switch to upper case
+ when a sentence ends.
+\li Qt.ImhPreferNumbers - Numbers are preferred (but not required).
+\li Qt.ImhPreferUppercase - Upper case letters are preferred (but not required).
+\li Qt.ImhPreferLowercase - Lower case letters are preferred (but not required).
+\li Qt.ImhNoPredictiveText - Do not use predictive text (i.e. dictionary lookup) while typing.
+
+\li Qt.ImhDate - The text editor functions as a date field.
+\li Qt.ImhTime - The text editor functions as a time field.
+\endlist
+
+Flags that restrict input (exclusive flags) are:
+
+\list
+\li Qt.ImhDigitsOnly - Only digits are allowed.
+\li Qt.ImhFormattedNumbersOnly - Only number input is allowed. This includes decimal point and minus sign.
+\li Qt.ImhUppercaseOnly - Only upper case letter input is allowed.
+\li Qt.ImhLowercaseOnly - Only lower case letter input is allowed.
+\li Qt.ImhDialableCharactersOnly - Only characters suitable for phone dialing are allowed.
+\li Qt.ImhEmailCharactersOnly - Only characters suitable for email addresses are allowed.
+\li Qt.ImhUrlCharactersOnly - Only characters suitable for URLs are allowed.
+\endlist
+
+Masks:
+
+\list
+\li Qt.ImhExclusiveInputMask - This mask yields nonzero if any of the exclusive flags are used.
+\endlist
+//! [flags]
diff --git a/src/imports/controls/doc/src/qtquickcontrols2-buttons.qdoc b/src/imports/controls/doc/src/qtquickcontrols2-buttons.qdoc
index a82755bf..c57f108f 100644
--- a/src/imports/controls/doc/src/qtquickcontrols2-buttons.qdoc
+++ b/src/imports/controls/doc/src/qtquickcontrols2-buttons.qdoc
@@ -41,7 +41,6 @@
\section1 Button Control
-
\l Button is a clickable control that starts an action, or opens or
closes a popup. A button usually has a text label but it can also
contain an icon.
@@ -100,6 +99,21 @@
\b {See also} \l CheckBox
+ \section1 DelayButton Control
+
+ \l DelayButton is a button that incorporates a delay before triggering an action.
+ This delay prevents accidental presses.
+
+ \image qtquickcontrols2-delaybutton.gif
+
+ Recommendations:
+ \list
+ \li Use in touch user interfaces.
+ \li Use for actions that must be triggered with care.
+ \endlist
+
+ \b {See also} \l Button and \l AbstractButton
+
\section1 RadioButton Control
\image qtquickcontrols2-radiobutton.gif
diff --git a/src/imports/controls/doc/src/qtquickcontrols2-customize.qdoc b/src/imports/controls/doc/src/qtquickcontrols2-customize.qdoc
index 2dd46b26..6ef019f6 100644
--- a/src/imports/controls/doc/src/qtquickcontrols2-customize.qdoc
+++ b/src/imports/controls/doc/src/qtquickcontrols2-customize.qdoc
@@ -419,6 +419,16 @@
\snippet qtquickcontrols2-combobox-custom.qml file
+ \section2 Customizing DelayButton
+
+ DelayButton consists of two visual items: \l {Control::background}{background}
+ and \l {Control::contentItem}{content item}.
+
+ \image qtquickcontrols2-delaybutton-custom.png
+
+ \snippet qtquickcontrols2-delaybutton-custom.qml file
+
+
\section2 Customizing Dial
Dial consists of two visual items: \l {Control::background}{background}
diff --git a/src/imports/controls/doc/src/qtquickcontrols2-delegates.qdoc b/src/imports/controls/doc/src/qtquickcontrols2-delegates.qdoc
index ff406230..057a5a2e 100644
--- a/src/imports/controls/doc/src/qtquickcontrols2-delegates.qdoc
+++ b/src/imports/controls/doc/src/qtquickcontrols2-delegates.qdoc
@@ -77,4 +77,3 @@
\li \l {Qt Quick Controls 2 Guidelines}
\endlist
*/
-
diff --git a/src/imports/controls/doc/src/qtquickcontrols2-differences.qdoc b/src/imports/controls/doc/src/qtquickcontrols2-differences.qdoc
index 2184af1a..3423e423 100644
--- a/src/imports/controls/doc/src/qtquickcontrols2-differences.qdoc
+++ b/src/imports/controls/doc/src/qtquickcontrols2-differences.qdoc
@@ -471,7 +471,7 @@
\li
\row
\li \l [QML QtQuickExtras] {DelayButton}
- \li \mdash
+ \li \l [QML QtQuickControls2] {DelayButton}
\li
\li
\row
diff --git a/src/imports/controls/doc/src/qtquickcontrols2-environment.qdoc b/src/imports/controls/doc/src/qtquickcontrols2-environment.qdoc
index 7313b13b..b037915f 100644
--- a/src/imports/controls/doc/src/qtquickcontrols2-environment.qdoc
+++ b/src/imports/controls/doc/src/qtquickcontrols2-environment.qdoc
@@ -47,6 +47,12 @@
\li Specifies a fallback style for \l {Creating a Custom Style}{custom styles}.
The value can be one of the built-in styles, for example \c "Material",
\row
+ \li \c QT_QUICK_CONTROLS_STYLE_PATH
+ \li Specifies a list of additional paths that are used to lookup \l {Styling Qt Quick Controls 2}
+ {Qt Quick Controls 2 styles}. Multiple path entries must be \l {QDir::listSeparator}{separated}
+ by \c ':' under Unix and \c ';' under Windows. By default, styles are looked up from
+ \c $QML2_IMPORT_PATH/QtQuick/Controls.2.
+ \row
\li \c QT_QUICK_CONTROLS_CONF
\li Specifies the location of the \l {Qt Quick Controls 2 configuration file}.
By default, the configuration file is loaded from the application's
diff --git a/src/imports/controls/doc/src/qtquickcontrols2-index.qdoc b/src/imports/controls/doc/src/qtquickcontrols2-index.qdoc
index 05ebcb16..d75aca43 100644
--- a/src/imports/controls/doc/src/qtquickcontrols2-index.qdoc
+++ b/src/imports/controls/doc/src/qtquickcontrols2-index.qdoc
@@ -41,7 +41,7 @@
application using the following import statement in your \c {.qml} file:
\code
- import QtQuick.Controls 2.1
+ import QtQuick.Controls 2.2
\endcode
The \l{Qt Quick Controls 2 C++ Classes}{C++ classes} can be included into
diff --git a/src/imports/controls/doc/src/qtquickcontrols2-input.qdoc b/src/imports/controls/doc/src/qtquickcontrols2-input.qdoc
index 42e0371b..469b546c 100644
--- a/src/imports/controls/doc/src/qtquickcontrols2-input.qdoc
+++ b/src/imports/controls/doc/src/qtquickcontrols2-input.qdoc
@@ -96,7 +96,6 @@
\l RangeSlider is used to select a range specified by two values,
by sliding each handle along a track.
-
\b {See also} \l {Slider Control}.
\section1 Tumbler Control
diff --git a/src/imports/controls/doc/src/qtquickcontrols2-material.qdoc b/src/imports/controls/doc/src/qtquickcontrols2-material.qdoc
index e0f3e83d..f5efe331 100644
--- a/src/imports/controls/doc/src/qtquickcontrols2-material.qdoc
+++ b/src/imports/controls/doc/src/qtquickcontrols2-material.qdoc
@@ -32,7 +32,7 @@
The Material Style is based on the Google Material Design Guidelines.
\l{detailed-desc-material}{More...}
- \styleimport {QtQuick.Controls.Material 2.1} {Qt 5.7}
+ \styleimport {QtQuick.Controls.Material 2.2} {Qt 5.7}
\section1 Attached Properties
diff --git a/src/imports/controls/doc/src/qtquickcontrols2-qmltypes.qdoc b/src/imports/controls/doc/src/qtquickcontrols2-qmltypes.qdoc
index 33c27113..04b1fff6 100644
--- a/src/imports/controls/doc/src/qtquickcontrols2-qmltypes.qdoc
+++ b/src/imports/controls/doc/src/qtquickcontrols2-qmltypes.qdoc
@@ -26,7 +26,7 @@
****************************************************************************/
/*!
- \qmlmodule QtQuick.Controls 2.1
+ \qmlmodule QtQuick.Controls 2.2
\title Qt Quick Controls 2 QML Types
\ingroup qmlmodules
\brief Provides QML types for user interfaces (Qt Quick Controls 2).
@@ -39,7 +39,7 @@
using the following import statement in your .qml file:
\badcode
- import QtQuick.Controls 2.1
+ import QtQuick.Controls 2.2
\endcode
\section1 QML Types
diff --git a/src/imports/controls/doc/src/qtquickcontrols2-universal.qdoc b/src/imports/controls/doc/src/qtquickcontrols2-universal.qdoc
index 997013ad..d115f741 100644
--- a/src/imports/controls/doc/src/qtquickcontrols2-universal.qdoc
+++ b/src/imports/controls/doc/src/qtquickcontrols2-universal.qdoc
@@ -32,7 +32,7 @@
The Universal Style is based on the Microsoft Universal Design Guidelines.
\l {detailed-desc-universal}{More...}
- \styleimport {QtQuick.Controls.Universal 2.1} {Qt 5.7}
+ \styleimport {QtQuick.Controls.Universal 2.2} {Qt 5.7}
\section1 Attached Properties
diff --git a/src/imports/controls/images/double-arrow.png b/src/imports/controls/images/double-arrow.png
index a6d84dbc..af403904 100644
--- a/src/imports/controls/images/double-arrow.png
+++ b/src/imports/controls/images/double-arrow.png
Binary files differ
diff --git a/src/imports/controls/images/double-arrow@2x.png b/src/imports/controls/images/double-arrow@2x.png
index 36ffd5fe..b63f5c57 100644
--- a/src/imports/controls/images/double-arrow@2x.png
+++ b/src/imports/controls/images/double-arrow@2x.png
Binary files differ
diff --git a/src/imports/controls/images/double-arrow@3x.png b/src/imports/controls/images/double-arrow@3x.png
index 5a2a59fe..c742e309 100644
--- a/src/imports/controls/images/double-arrow@3x.png
+++ b/src/imports/controls/images/double-arrow@3x.png
Binary files differ
diff --git a/src/imports/controls/images/double-arrow@4x.png b/src/imports/controls/images/double-arrow@4x.png
index 22977545..488a331d 100644
--- a/src/imports/controls/images/double-arrow@4x.png
+++ b/src/imports/controls/images/double-arrow@4x.png
Binary files differ
diff --git a/src/imports/controls/material/ApplicationWindow.qml b/src/imports/controls/material/ApplicationWindow.qml
index f4c9374e..82a0d135 100644
--- a/src/imports/controls/material/ApplicationWindow.qml
+++ b/src/imports/controls/material/ApplicationWindow.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
+import QtQuick 2.9
import QtQuick.Window 2.2
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
T.ApplicationWindow {
id: window
diff --git a/src/imports/controls/material/BoxShadow.qml b/src/imports/controls/material/BoxShadow.qml
index 5655c842..aa9fd0fa 100644
--- a/src/imports/controls/material/BoxShadow.qml
+++ b/src/imports/controls/material/BoxShadow.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls.Material 2.1
-import QtQuick.Controls.Material.impl 2.1
+import QtQuick 2.9
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
/*
A implementation of CSS's box-shadow, used by ElevationEffect for a Material Design
diff --git a/src/imports/controls/material/BusyIndicator.qml b/src/imports/controls/material/BusyIndicator.qml
index a04c7c91..f1cf8eb5 100644
--- a/src/imports/controls/material/BusyIndicator.qml
+++ b/src/imports/controls/material/BusyIndicator.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
-import QtQuick.Controls.Material.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
T.BusyIndicator {
id: control
@@ -47,24 +47,13 @@ T.BusyIndicator {
padding: 6
- contentItem: ProgressRing {
- id: ring
- x: control.leftPadding + (control.availableWidth - width) / 2
- y: control.topPadding + (control.availableHeight - height) / 2
+ contentItem: BusyIndicatorImpl {
implicitWidth: 48
implicitHeight: 48
- width: size
- height: size
- opacity: control.running ? 1 : 0
color: control.Material.accentColor
- readonly property real size: Math.min(control.availableWidth, control.availableHeight)
-
- Behavior on opacity { OpacityAnimator { duration: 250 } }
-
- RingAnimator {
- target: ring
- running: control.visible && control.running
- }
+ opacity: control.running ? 1 : 0
+ visible: control.running || animator.running
+ Behavior on opacity { OpacityAnimator { id: animator; duration: 250 } }
}
}
diff --git a/src/imports/controls/material/Button.qml b/src/imports/controls/material/Button.qml
index 312fcb1b..471ca8f2 100644
--- a/src/imports/controls/material/Button.qml
+++ b/src/imports/controls/material/Button.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
-import QtQuick.Controls.Material.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
T.Button {
id: control
diff --git a/src/imports/controls/material/CheckBox.qml b/src/imports/controls/material/CheckBox.qml
index f0ae3b78..e1c559da 100644
--- a/src/imports/controls/material/CheckBox.qml
+++ b/src/imports/controls/material/CheckBox.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
-import QtQuick.Controls.Material.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
T.CheckBox {
id: control
diff --git a/src/imports/controls/material/CheckDelegate.qml b/src/imports/controls/material/CheckDelegate.qml
index ee91ea7d..545ca64a 100644
--- a/src/imports/controls/material/CheckDelegate.qml
+++ b/src/imports/controls/material/CheckDelegate.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
-import QtQuick.Controls.Material.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
T.CheckDelegate {
id: control
diff --git a/src/imports/controls/material/CheckIndicator.qml b/src/imports/controls/material/CheckIndicator.qml
index 4c73974f..8fe860f0 100644
--- a/src/imports/controls/material/CheckIndicator.qml
+++ b/src/imports/controls/material/CheckIndicator.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls.Material 2.1
-import QtQuick.Controls.Material.impl 2.1
+import QtQuick 2.9
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
Rectangle {
id: indicatorItem
diff --git a/src/imports/controls/material/ComboBox.qml b/src/imports/controls/material/ComboBox.qml
index fbddb32c..2bdf9afa 100644
--- a/src/imports/controls/material/ComboBox.qml
+++ b/src/imports/controls/material/ComboBox.qml
@@ -34,12 +34,12 @@
**
****************************************************************************/
-import QtQuick 2.8
+import QtQuick 2.9
import QtQuick.Window 2.2
-import QtQuick.Controls 2.1
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
-import QtQuick.Controls.Material.impl 2.1
+import QtQuick.Controls 2.2
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
T.ComboBox {
id: control
@@ -51,11 +51,8 @@ T.ComboBox {
indicator ? indicator.implicitHeight : 0) + topPadding + bottomPadding)
baselineOffset: contentItem.y + contentItem.baselineOffset
- spacing: 6
- // external vertical padding is 6 (to increase touch area)
- padding: 12
- leftPadding: padding - 4
- rightPadding: padding - 4
+ leftPadding: padding + (!control.mirrored || !indicator || !indicator.visible ? 0 : indicator.width + spacing)
+ rightPadding: padding + (control.mirrored || !indicator || !indicator.visible ? 0 : indicator.width + spacing)
Material.elevation: flat ? control.pressed || control.hovered ? 2 : 0
: control.pressed ? 8 : 2
@@ -63,29 +60,40 @@ T.ComboBox {
Material.foreground: flat ? undefined : Material.primaryTextColor
delegate: MenuItem {
- width: control.popup.width
+ width: parent.width
text: control.textRole ? (Array.isArray(control.model) ? modelData[control.textRole] : model[control.textRole]) : modelData
- Material.foreground: control.currentIndex === index ? control.popup.Material.accent : control.popup.Material.foreground
+ Material.foreground: control.currentIndex === index ? parent.Material.accent : parent.Material.foreground
highlighted: control.highlightedIndex === index
hoverEnabled: control.hoverEnabled
}
indicator: Image {
- x: control.mirrored ? control.leftPadding : control.width - width - control.rightPadding
+ x: control.mirrored ? control.padding : control.width - width - control.padding
y: control.topPadding + (control.availableHeight - height) / 2
source: "image://material/drop-indicator/" + (control.enabled ? control.Material.foreground : control.Material.hintTextColor)
}
- contentItem: Text {
- leftPadding: control.mirrored && control.indicator ? control.indicator.width + control.spacing : 0
- rightPadding: !control.mirrored && control.indicator ? control.indicator.width + control.spacing : 0
+ contentItem: T.TextField {
+ padding: 6
+ leftPadding: control.editable ? 2 : control.mirrored ? 0 : 12
+ rightPadding: control.editable ? 2 : control.mirrored ? 12 : 0
+
+ text: control.editable ? control.editText : control.displayText
+
+ enabled: control.editable
+ autoScroll: control.editable
+ readOnly: control.popup.visible
+ inputMethodHints: control.inputMethodHints
+ validator: control.validator
- text: control.displayText
font: control.font
color: control.enabled ? control.Material.foreground : control.Material.hintTextColor
+ selectionColor: control.Material.accentColor
+ selectedTextColor: control.Material.primaryHighlightedTextColor
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
- elide: Text.ElideRight
+
+ cursorDelegate: CursorDelegate { }
}
background: Rectangle {
@@ -96,32 +104,43 @@ T.ComboBox {
y: 6
height: parent.height - 12
radius: control.flat ? 0 : 2
- color: control.Material.dialogColor
+ color: !control.editable ? control.Material.dialogColor : "transparent"
Behavior on color {
+ enabled: !control.editable
ColorAnimation {
duration: 400
}
}
- layer.enabled: control.enabled && control.Material.background.a > 0
+ layer.enabled: control.enabled && !control.editable && control.Material.background.a > 0
layer.effect: ElevationEffect {
elevation: control.Material.elevation
}
+ Rectangle {
+ visible: control.editable
+ y: parent.y + control.baselineOffset
+ width: parent.width
+ height: control.activeFocus ? 2 : 1
+ color: control.editable && control.activeFocus ? control.Material.accentColor : control.Material.hintTextColor
+ }
+
Ripple {
clip: control.flat
clipRadius: control.flat ? 0 : 2
- width: parent.width
+ x: control.editable && control.indicator ? control.indicator.x : 0
+ width: control.editable && control.indicator ? control.indicator.width : parent.width
height: parent.height
pressed: control.pressed
- anchor: control
+ anchor: control.editable && control.indicator ? control.indicator : control
active: control.pressed || control.visualFocus || control.hovered
color: control.Material.rippleColor
}
}
popup: T.Popup {
+ y: control.editable ? control.height - 5 : 0
width: control.width
implicitHeight: contentItem.implicitHeight
transformOrigin: Item.Top
diff --git a/src/imports/controls/material/CursorDelegate.qml b/src/imports/controls/material/CursorDelegate.qml
new file mode 100644
index 00000000..8795fe13
--- /dev/null
+++ b/src/imports/controls/material/CursorDelegate.qml
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Controls.Material 2.2
+
+Rectangle {
+ id: cursor
+
+ color: parent.Material.accentColor
+ width: 2
+ visible: parent.activeFocus && parent.selectionStart === parent.selectionEnd
+
+ Connections {
+ target: cursor.parent
+ onCursorPositionChanged: {
+ // keep a moving cursor visible
+ cursor.opacity = 1
+ timer.restart()
+ }
+ }
+
+ Timer {
+ id: timer
+ running: cursor.parent.activeFocus
+ repeat: true
+ interval: Qt.styleHints.cursorFlashTime / 2
+ onTriggered: cursor.opacity = !cursor.opacity ? 1 : 0
+ // force the cursor visible when gaining focus
+ onRunningChanged: cursor.opacity = 1
+ }
+}
diff --git a/src/imports/controls/material/DelayButton.qml b/src/imports/controls/material/DelayButton.qml
new file mode 100644
index 00000000..8bc48784
--- /dev/null
+++ b/src/imports/controls/material/DelayButton.qml
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
+
+T.DelayButton {
+ id: control
+
+ implicitWidth: Math.max(background ? background.implicitWidth : 0,
+ contentItem.implicitWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(background ? background.implicitHeight : 0,
+ contentItem.implicitHeight + topPadding + bottomPadding)
+ baselineOffset: contentItem.y + contentItem.baselineOffset
+
+ // external vertical padding is 6 (to increase touch area)
+ padding: 12
+ leftPadding: padding - 4
+ rightPadding: padding - 4
+
+ Material.elevation: control.down ? 8 : 2
+
+ transition: Transition {
+ NumberAnimation {
+ duration: control.delay * (control.pressed ? 1.0 - control.progress : 0.3 * control.progress)
+ }
+ }
+
+ contentItem: Text {
+ text: control.text
+ font: control.font
+ color: !control.enabled ? control.Material.hintTextColor : control.Material.foreground
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ elide: Text.ElideRight
+ }
+
+ // TODO: Add a proper ripple/ink effect for mouse/touch input and focus state
+ background: Rectangle {
+ implicitWidth: 64
+ implicitHeight: 48
+
+ // external vertical padding is 6 (to increase touch area)
+ y: 6
+ width: parent.width
+ height: parent.height - 12
+ radius: 2
+ color: !control.enabled ? control.Material.buttonDisabledColor : control.Material.buttonColor
+
+ PaddedRectangle {
+ y: parent.height - 4
+ width: parent.width
+ height: 4
+ radius: 2
+ topPadding: -2
+ clip: true
+ color: control.checked && control.enabled ? control.Material.accentColor : control.Material.secondaryTextColor
+
+ PaddedRectangle {
+ width: parent.width * control.progress
+ height: 4
+ radius: 2
+ topPadding: -2
+ rightPadding: Math.max(-2, width - parent.width)
+ clip: true
+ color: control.Material.accentColor
+ }
+ }
+
+ Behavior on color {
+ ColorAnimation {
+ duration: 400
+ }
+ }
+
+ layer.enabled: control.enabled && control.Material.buttonColor.a > 0
+ layer.effect: ElevationEffect {
+ elevation: control.Material.elevation
+ }
+
+ Ripple {
+ clipRadius: 2
+ width: parent.width
+ height: parent.height
+ pressed: control.pressed
+ anchor: control
+ active: control.down || control.visualFocus || control.hovered
+ color: control.Material.rippleColor
+ }
+ }
+}
diff --git a/src/imports/controls/material/Dial.qml b/src/imports/controls/material/Dial.qml
index abed2e93..e0632e62 100644
--- a/src/imports/controls/material/Dial.qml
+++ b/src/imports/controls/material/Dial.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
-import QtQuick.Controls.Material.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
T.Dial {
id: control
diff --git a/src/imports/controls/material/Dialog.qml b/src/imports/controls/material/Dialog.qml
index 7d73b057..a97cb2fd 100644
--- a/src/imports/controls/material/Dialog.qml
+++ b/src/imports/controls/material/Dialog.qml
@@ -34,11 +34,11 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls 2.1
-import QtQuick.Controls.Material 2.1
-import QtQuick.Controls.Material.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls 2.2
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
T.Dialog {
id: control
diff --git a/src/imports/controls/material/DialogButtonBox.qml b/src/imports/controls/material/DialogButtonBox.qml
index 668b7664..c36a7749 100644
--- a/src/imports/controls/material/DialogButtonBox.qml
+++ b/src/imports/controls/material/DialogButtonBox.qml
@@ -34,11 +34,11 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls 2.1
-import QtQuick.Controls.Material 2.1
-import QtQuick.Controls.Material.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls 2.2
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
T.DialogButtonBox {
id: control
diff --git a/src/imports/controls/material/Drawer.qml b/src/imports/controls/material/Drawer.qml
index b52c910b..dc06c895 100644
--- a/src/imports/controls/material/Drawer.qml
+++ b/src/imports/controls/material/Drawer.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
-import QtQuick.Controls.Material.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
T.Drawer {
id: control
@@ -58,7 +58,7 @@ T.Drawer {
enter: Transition { SmoothedAnimation { velocity: 5 } }
exit: Transition { SmoothedAnimation { velocity: 5 } }
- Material.elevation: 16
+ Material.elevation: !interactive && !dim ? 0 : 16
background: Rectangle {
color: control.Material.dialogColor
diff --git a/src/imports/controls/material/ElevationEffect.qml b/src/imports/controls/material/ElevationEffect.qml
index 9872c970..0d0c1992 100644
--- a/src/imports/controls/material/ElevationEffect.qml
+++ b/src/imports/controls/material/ElevationEffect.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls.Material 2.1
-import QtQuick.Controls.Material.impl 2.1
+import QtQuick 2.9
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
/*
An effect for standard Material Design elevation shadows. Useful for using as \c layer.effect.
diff --git a/src/imports/controls/material/Frame.qml b/src/imports/controls/material/Frame.qml
index 01ea19f6..760fc6d2 100644
--- a/src/imports/controls/material/Frame.qml
+++ b/src/imports/controls/material/Frame.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
-import QtQuick.Controls.Material.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
T.Frame {
id: control
diff --git a/src/imports/controls/material/GroupBox.qml b/src/imports/controls/material/GroupBox.qml
index de46466b..e7055404 100644
--- a/src/imports/controls/material/GroupBox.qml
+++ b/src/imports/controls/material/GroupBox.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
-import QtQuick.Controls.Material.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
T.GroupBox {
id: control
diff --git a/src/imports/controls/material/ItemDelegate.qml b/src/imports/controls/material/ItemDelegate.qml
index 6d20c933..59d51c36 100644
--- a/src/imports/controls/material/ItemDelegate.qml
+++ b/src/imports/controls/material/ItemDelegate.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
-import QtQuick.Controls.Material.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
T.ItemDelegate {
id: control
diff --git a/src/imports/controls/material/Label.qml b/src/imports/controls/material/Label.qml
index 5e0dfb70..4433e248 100644
--- a/src/imports/controls/material/Label.qml
+++ b/src/imports/controls/material/Label.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
T.Label {
id: control
diff --git a/src/imports/controls/material/Menu.qml b/src/imports/controls/material/Menu.qml
index d93d6401..3e76c81d 100644
--- a/src/imports/controls/material/Menu.qml
+++ b/src/imports/controls/material/Menu.qml
@@ -34,11 +34,11 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
-import QtQuick.Controls.Material.impl 2.1
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
T.Menu {
id: control
diff --git a/src/imports/controls/material/MenuItem.qml b/src/imports/controls/material/MenuItem.qml
index db7b83f0..5a136231 100644
--- a/src/imports/controls/material/MenuItem.qml
+++ b/src/imports/controls/material/MenuItem.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
-import QtQuick.Controls.Material.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
T.MenuItem {
id: control
diff --git a/src/imports/controls/material/MenuSeparator.qml b/src/imports/controls/material/MenuSeparator.qml
index 00d4feeb..fd0febbe 100644
--- a/src/imports/controls/material/MenuSeparator.qml
+++ b/src/imports/controls/material/MenuSeparator.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
T.MenuSeparator {
id: control
diff --git a/src/imports/controls/material/Page.qml b/src/imports/controls/material/Page.qml
index 9df31627..825b9f90 100644
--- a/src/imports/controls/material/Page.qml
+++ b/src/imports/controls/material/Page.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
T.Page {
id: control
diff --git a/src/imports/controls/material/PageIndicator.qml b/src/imports/controls/material/PageIndicator.qml
index 3e86d89e..15acae5e 100644
--- a/src/imports/controls/material/PageIndicator.qml
+++ b/src/imports/controls/material/PageIndicator.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
T.PageIndicator {
id: control
diff --git a/src/imports/controls/material/Pane.qml b/src/imports/controls/material/Pane.qml
index e0f19069..925778fa 100644
--- a/src/imports/controls/material/Pane.qml
+++ b/src/imports/controls/material/Pane.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
-import QtQuick.Controls.Material.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
T.Pane {
id: control
diff --git a/src/imports/controls/material/Popup.qml b/src/imports/controls/material/Popup.qml
index 7a49f231..04b58c2a 100644
--- a/src/imports/controls/material/Popup.qml
+++ b/src/imports/controls/material/Popup.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
-import QtQuick.Controls.Material.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
T.Popup {
id: control
diff --git a/src/imports/controls/material/ProgressBar.qml b/src/imports/controls/material/ProgressBar.qml
index 431b2b69..1bc03016 100644
--- a/src/imports/controls/material/ProgressBar.qml
+++ b/src/imports/controls/material/ProgressBar.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
-import QtQuick.Controls.Material.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
T.ProgressBar {
id: control
@@ -47,19 +47,13 @@ T.ProgressBar {
implicitHeight: Math.max(background ? background.implicitHeight : 0,
contentItem.implicitHeight + topPadding + bottomPadding)
- contentItem: ProgressStrip {
- id: strip
+ contentItem: ProgressBarImpl {
implicitHeight: 4
scale: control.mirrored ? -1 : 1
- indeterminate: control.indeterminate
color: control.Material.accentColor
progress: control.position
-
- StripAnimator {
- target: strip
- running: control.visible && control.indeterminate
- }
+ indeterminate: control.visible && control.indeterminate
}
background: Rectangle {
diff --git a/src/imports/controls/material/RadioButton.qml b/src/imports/controls/material/RadioButton.qml
index c21fe88c..d178654f 100644
--- a/src/imports/controls/material/RadioButton.qml
+++ b/src/imports/controls/material/RadioButton.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
-import QtQuick.Controls.Material.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
T.RadioButton {
id: control
diff --git a/src/imports/controls/material/RadioDelegate.qml b/src/imports/controls/material/RadioDelegate.qml
index 855b0936..fb4f33dc 100644
--- a/src/imports/controls/material/RadioDelegate.qml
+++ b/src/imports/controls/material/RadioDelegate.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
-import QtQuick.Controls.Material.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
T.RadioDelegate {
id: control
diff --git a/src/imports/controls/material/RadioIndicator.qml b/src/imports/controls/material/RadioIndicator.qml
index b611d145..82b01ad3 100644
--- a/src/imports/controls/material/RadioIndicator.qml
+++ b/src/imports/controls/material/RadioIndicator.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls.Material 2.1
-import QtQuick.Controls.Material.impl 2.1
+import QtQuick 2.9
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
Rectangle {
implicitWidth: 20
diff --git a/src/imports/controls/material/RangeSlider.qml b/src/imports/controls/material/RangeSlider.qml
index e90533d8..0b38ad6d 100644
--- a/src/imports/controls/material/RangeSlider.qml
+++ b/src/imports/controls/material/RangeSlider.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
-import QtQuick.Controls.Material.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
T.RangeSlider {
id: control
diff --git a/src/imports/controls/material/RoundButton.qml b/src/imports/controls/material/RoundButton.qml
index b06e936f..3ce3b39b 100644
--- a/src/imports/controls/material/RoundButton.qml
+++ b/src/imports/controls/material/RoundButton.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
-import QtQuick.Controls.Material.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
T.RoundButton {
id: control
diff --git a/src/imports/controls/material/ScrollBar.qml b/src/imports/controls/material/ScrollBar.qml
index f5cc1b36..140cb94d 100644
--- a/src/imports/controls/material/ScrollBar.qml
+++ b/src/imports/controls/material/ScrollBar.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
T.ScrollBar {
id: control
diff --git a/src/imports/controls/material/ScrollIndicator.qml b/src/imports/controls/material/ScrollIndicator.qml
index 64597dd6..effb18ad 100644
--- a/src/imports/controls/material/ScrollIndicator.qml
+++ b/src/imports/controls/material/ScrollIndicator.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
T.ScrollIndicator {
id: control
diff --git a/src/imports/controls/material/Slider.qml b/src/imports/controls/material/Slider.qml
index 7f855fd7..cb60dba6 100644
--- a/src/imports/controls/material/Slider.qml
+++ b/src/imports/controls/material/Slider.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
-import QtQuick.Controls.Material.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
T.Slider {
id: control
diff --git a/src/imports/controls/material/SliderHandle.qml b/src/imports/controls/material/SliderHandle.qml
index 2d564817..dd4de4a2 100644
--- a/src/imports/controls/material/SliderHandle.qml
+++ b/src/imports/controls/material/SliderHandle.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls.Material 2.1
-import QtQuick.Controls.Material.impl 2.1
+import QtQuick 2.9
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
Item {
id: root
diff --git a/src/imports/controls/material/SpinBox.qml b/src/imports/controls/material/SpinBox.qml
index f1575152..f0dfba08 100644
--- a/src/imports/controls/material/SpinBox.qml
+++ b/src/imports/controls/material/SpinBox.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
-import QtQuick.Controls.Material.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
T.SpinBox {
id: control
@@ -73,35 +73,12 @@ T.SpinBox {
selectedTextColor: control.Material.foreground
horizontalAlignment: Qt.AlignHCenter
verticalAlignment: Qt.AlignVCenter
- cursorDelegate: Rectangle {
- id: cursor
- color: control.Material.accentColor
- width: 2
- visible: control.activeFocus && contentItem.selectionStart === contentItem.selectionEnd
-
- Connections {
- target: contentItem
- onCursorPositionChanged: {
- // keep a moving cursor visible
- cursor.opacity = 1
- timer.restart()
- }
- }
-
- Timer {
- id: timer
- running: control.activeFocus
- repeat: true
- interval: Qt.styleHints.cursorFlashTime / 2
- onTriggered: cursor.opacity = !cursor.opacity ? 1 : 0
- // force the cursor visible when gaining focus
- onRunningChanged: cursor.opacity = 1
- }
- }
+
+ cursorDelegate: CursorDelegate { }
readOnly: !control.editable
validator: control.validator
- inputMethodHints: Qt.ImhDigitsOnly
+ inputMethodHints: control.inputMethodHints
}
up.indicator: Item {
diff --git a/src/imports/controls/material/StackView.qml b/src/imports/controls/material/StackView.qml
index f5f775b8..03cd384d 100644
--- a/src/imports/controls/material/StackView.qml
+++ b/src/imports/controls/material/StackView.qml
@@ -34,8 +34,8 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
T.StackView {
id: control
diff --git a/src/imports/controls/material/SwipeDelegate.qml b/src/imports/controls/material/SwipeDelegate.qml
index 457ba69c..d9014fcd 100644
--- a/src/imports/controls/material/SwipeDelegate.qml
+++ b/src/imports/controls/material/SwipeDelegate.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
-import QtQuick.Controls.Material.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
T.SwipeDelegate {
id: control
@@ -54,6 +54,8 @@ T.SwipeDelegate {
bottomPadding: 8
spacing: 16
+ swipe.transition: Transition { SmoothedAnimation { velocity: 3; easing.type: Easing.InOutCubic } }
+
contentItem: Text {
leftPadding: !control.mirrored ? (control.indicator ? control.indicator.width + control.spacing : 0) : 0
rightPadding: control.mirrored ? (control.indicator ? control.indicator.width + control.spacing : 0) : 0
@@ -65,14 +67,6 @@ T.SwipeDelegate {
visible: control.text
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
-
- Behavior on x {
- enabled: !control.down
- NumberAnimation {
- easing.type: Easing.InOutCubic
- duration: 400
- }
- }
}
background: Rectangle {
@@ -98,13 +92,5 @@ T.SwipeDelegate {
color: control.Material.rippleColor
enabled: control.swipe.position === 0
}
-
- Behavior on x {
- enabled: !control.down
- NumberAnimation {
- easing.type: Easing.InOutCubic
- duration: 400
- }
- }
}
}
diff --git a/src/imports/controls/material/SwipeView.qml b/src/imports/controls/material/SwipeView.qml
index 400ac571..77a7b9f6 100644
--- a/src/imports/controls/material/SwipeView.qml
+++ b/src/imports/controls/material/SwipeView.qml
@@ -34,8 +34,8 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
T.SwipeView {
id: control
diff --git a/src/imports/controls/material/Switch.qml b/src/imports/controls/material/Switch.qml
index e026c80e..c4f279ee 100644
--- a/src/imports/controls/material/Switch.qml
+++ b/src/imports/controls/material/Switch.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls.Material 2.1
-import QtQuick.Controls.Material.impl 2.1
-import QtQuick.Templates 2.1 as T
+import QtQuick 2.9
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
+import QtQuick.Templates 2.2 as T
T.Switch {
id: control
diff --git a/src/imports/controls/material/SwitchDelegate.qml b/src/imports/controls/material/SwitchDelegate.qml
index 16551519..717ee250 100644
--- a/src/imports/controls/material/SwitchDelegate.qml
+++ b/src/imports/controls/material/SwitchDelegate.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
-import QtQuick.Controls.Material.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
T.SwitchDelegate {
id: control
diff --git a/src/imports/controls/material/SwitchIndicator.qml b/src/imports/controls/material/SwitchIndicator.qml
index 753db60b..0ac7aee3 100644
--- a/src/imports/controls/material/SwitchIndicator.qml
+++ b/src/imports/controls/material/SwitchIndicator.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls.Material 2.1
-import QtQuick.Controls.Material.impl 2.1
+import QtQuick 2.9
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
Item {
id: indicator
diff --git a/src/imports/controls/material/TabBar.qml b/src/imports/controls/material/TabBar.qml
index c7577e79..db076447 100644
--- a/src/imports/controls/material/TabBar.qml
+++ b/src/imports/controls/material/TabBar.qml
@@ -34,25 +34,23 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
-import QtQuick.Controls.Material.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
T.TabBar {
id: control
implicitWidth: Math.max(background ? background.implicitWidth : 0,
- contentItem.implicitWidth + leftPadding + rightPadding)
+ contentWidth + leftPadding + rightPadding)
implicitHeight: Math.max(background ? background.implicitHeight : 0,
- contentItem.implicitHeight + topPadding + bottomPadding)
+ contentHeight + topPadding + bottomPadding)
spacing: 1
+ contentHeight: 48
contentItem: ListView {
- implicitWidth: contentWidth
- implicitHeight: 48
-
model: control.contentModel
currentIndex: control.currentIndex
diff --git a/src/imports/controls/material/TabButton.qml b/src/imports/controls/material/TabButton.qml
index bd068637..d83fc441 100644
--- a/src/imports/controls/material/TabButton.qml
+++ b/src/imports/controls/material/TabButton.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
-import QtQuick.Controls.Material.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
T.TabButton {
id: control
diff --git a/src/imports/controls/material/TextArea.qml b/src/imports/controls/material/TextArea.qml
index afca4aa8..34c633b6 100644
--- a/src/imports/controls/material/TextArea.qml
+++ b/src/imports/controls/material/TextArea.qml
@@ -34,9 +34,12 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
T.TextArea {
id: control
@@ -54,34 +57,10 @@ T.TextArea {
color: enabled ? Material.foreground : Material.hintTextColor
selectionColor: Material.accentColor
selectedTextColor: Material.primaryHighlightedTextColor
- cursorDelegate: Rectangle {
- id: cursor
- clip: true // TODO
- color: control.Material.accentColor
- width: 2
- visible: control.activeFocus && control.selectionStart === control.selectionEnd
- Connections {
- target: control
- onCursorPositionChanged: {
- // keep a moving cursor visible
- cursor.opacity = 1
- timer.restart()
- }
- }
+ cursorDelegate: CursorDelegate { }
- Timer {
- id: timer
- running: control.activeFocus
- repeat: true
- interval: Qt.styleHints.cursorFlashTime / 2
- onTriggered: cursor.opacity = !cursor.opacity ? 1 : 0
- // force the cursor visible when gaining focus
- onRunningChanged: cursor.opacity = 1
- }
- }
-
- Text {
+ PlaceholderText {
id: placeholder
x: control.leftPadding
y: control.topPadding
@@ -90,7 +69,6 @@ T.TextArea {
text: control.placeholderText
font: control.font
color: control.Material.hintTextColor
- horizontalAlignment: control.horizontalAlignment
verticalAlignment: control.verticalAlignment
elide: Text.ElideRight
visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter)
diff --git a/src/imports/controls/material/TextField.qml b/src/imports/controls/material/TextField.qml
index 4b4d24a9..f5c77f86 100644
--- a/src/imports/controls/material/TextField.qml
+++ b/src/imports/controls/material/TextField.qml
@@ -34,9 +34,12 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
T.TextField {
id: control
@@ -55,33 +58,10 @@ T.TextField {
selectionColor: Material.accentColor
selectedTextColor: Material.primaryHighlightedTextColor
verticalAlignment: TextInput.AlignVCenter
- cursorDelegate: Rectangle {
- id: cursor
- color: control.Material.accentColor
- width: 2
- visible: control.activeFocus && control.selectionStart === control.selectionEnd
- Connections {
- target: control
- onCursorPositionChanged: {
- // keep a moving cursor visible
- cursor.opacity = 1
- timer.restart()
- }
- }
+ cursorDelegate: CursorDelegate { }
- Timer {
- id: timer
- running: control.activeFocus
- repeat: true
- interval: Qt.styleHints.cursorFlashTime / 2
- onTriggered: cursor.opacity = !cursor.opacity ? 1 : 0
- // force the cursor visible when gaining focus
- onRunningChanged: cursor.opacity = 1
- }
- }
-
- Text {
+ PlaceholderText {
id: placeholder
x: control.leftPadding
y: control.topPadding
@@ -90,7 +70,6 @@ T.TextField {
text: control.placeholderText
font: control.font
color: control.Material.hintTextColor
- horizontalAlignment: control.horizontalAlignment
verticalAlignment: control.verticalAlignment
elide: Text.ElideRight
visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter)
diff --git a/src/imports/controls/material/ToolBar.qml b/src/imports/controls/material/ToolBar.qml
index b4c8f27b..228a2692 100644
--- a/src/imports/controls/material/ToolBar.qml
+++ b/src/imports/controls/material/ToolBar.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
-import QtQuick.Controls.Material.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
T.ToolBar {
id: control
diff --git a/src/imports/controls/material/ToolButton.qml b/src/imports/controls/material/ToolButton.qml
index cdb50746..eaff0b1c 100644
--- a/src/imports/controls/material/ToolButton.qml
+++ b/src/imports/controls/material/ToolButton.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
-import QtQuick.Controls.Material.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
+import QtQuick.Controls.Material.impl 2.2
T.ToolButton {
id: control
diff --git a/src/imports/controls/material/ToolSeparator.qml b/src/imports/controls/material/ToolSeparator.qml
index 7ad8d430..84c28441 100644
--- a/src/imports/controls/material/ToolSeparator.qml
+++ b/src/imports/controls/material/ToolSeparator.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
T.ToolSeparator {
id: control
diff --git a/src/imports/controls/material/ToolTip.qml b/src/imports/controls/material/ToolTip.qml
index 2f4830bc..a1c2b0ef 100644
--- a/src/imports/controls/material/ToolTip.qml
+++ b/src/imports/controls/material/ToolTip.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
T.ToolTip {
id: control
diff --git a/src/imports/controls/material/Tumbler.qml b/src/imports/controls/material/Tumbler.qml
index 09335101..9b1309ab 100644
--- a/src/imports/controls/material/Tumbler.qml
+++ b/src/imports/controls/material/Tumbler.qml
@@ -34,11 +34,11 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Material 2.1
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Material 2.2
T.Tumbler {
id: control
diff --git a/src/imports/controls/material/images/drop-indicator.png b/src/imports/controls/material/images/drop-indicator.png
index 08bb4855..0f61fbb7 100644
--- a/src/imports/controls/material/images/drop-indicator.png
+++ b/src/imports/controls/material/images/drop-indicator.png
Binary files differ
diff --git a/src/imports/controls/material/images/drop-indicator@2x.png b/src/imports/controls/material/images/drop-indicator@2x.png
index ccdfc2b1..8f555eee 100644
--- a/src/imports/controls/material/images/drop-indicator@2x.png
+++ b/src/imports/controls/material/images/drop-indicator@2x.png
Binary files differ
diff --git a/src/imports/controls/material/images/drop-indicator@3x.png b/src/imports/controls/material/images/drop-indicator@3x.png
index 00cae691..7fd2af1f 100644
--- a/src/imports/controls/material/images/drop-indicator@3x.png
+++ b/src/imports/controls/material/images/drop-indicator@3x.png
Binary files differ
diff --git a/src/imports/controls/material/images/drop-indicator@4x.png b/src/imports/controls/material/images/drop-indicator@4x.png
index 0a61cb01..7e81fdd8 100644
--- a/src/imports/controls/material/images/drop-indicator@4x.png
+++ b/src/imports/controls/material/images/drop-indicator@4x.png
Binary files differ
diff --git a/src/imports/controls/material/material.pri b/src/imports/controls/material/material.pri
index 3170a695..64d91442 100644
--- a/src/imports/controls/material/material.pri
+++ b/src/imports/controls/material/material.pri
@@ -1,16 +1,16 @@
HEADERS += \
+ $$PWD/qquickmaterialbusyindicator_p.h \
+ $$PWD/qquickmaterialprogressbar_p.h \
$$PWD/qquickmaterialripple_p.h \
$$PWD/qquickmaterialstyle_p.h \
- $$PWD/qquickmaterialtheme_p.h \
- $$PWD/qquickmaterialprogressring_p.h \
- $$PWD/qquickmaterialprogressstrip_p.h
+ $$PWD/qquickmaterialtheme_p.h
SOURCES += \
+ $$PWD/qquickmaterialbusyindicator.cpp \
+ $$PWD/qquickmaterialprogressbar.cpp \
$$PWD/qquickmaterialripple.cpp \
$$PWD/qquickmaterialstyle.cpp \
- $$PWD/qquickmaterialtheme.cpp \
- $$PWD/qquickmaterialprogressring.cpp \
- $$PWD/qquickmaterialprogressstrip.cpp
+ $$PWD/qquickmaterialtheme.cpp
QML_FILES += \
$$PWD/ApplicationWindow.qml \
@@ -21,6 +21,8 @@ QML_FILES += \
$$PWD/CheckDelegate.qml \
$$PWD/CheckIndicator.qml \
$$PWD/ComboBox.qml \
+ $$PWD/CursorDelegate.qml \
+ $$PWD/DelayButton.qml \
$$PWD/Dial.qml \
$$PWD/Dialog.qml \
$$PWD/DialogButtonBox.qml \
diff --git a/src/imports/controls/material/qmldir b/src/imports/controls/material/qmldir
index 27d1298a..839ca3af 100644
--- a/src/imports/controls/material/qmldir
+++ b/src/imports/controls/material/qmldir
@@ -1,4 +1,4 @@
module QtQuick.Controls.Material
plugin qtquickcontrols2materialstyleplugin
classname QtQuickControls2MaterialStylePlugin
-depends QtQuick.Controls 2.1
+depends QtQuick.Controls 2.2
diff --git a/src/imports/controls/material/qquickmaterialbusyindicator.cpp b/src/imports/controls/material/qquickmaterialbusyindicator.cpp
new file mode 100644
index 00000000..2c02e2ba
--- /dev/null
+++ b/src/imports/controls/material/qquickmaterialbusyindicator.cpp
@@ -0,0 +1,229 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickmaterialbusyindicator_p.h"
+
+#include <QtCore/qeasingcurve.h>
+#include <QtGui/qpainter.h>
+#include <QtQuick/qsgimagenode.h>
+#include <QtQuick/qquickwindow.h>
+#include <QtQuickControls2/private/qquickanimatednode_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ Relevant Android code:
+
+ - core/res/res/anim/progress_indeterminate_rotation_material.xml contains
+ the rotation animation data.
+ - core/res/res/anim/progress_indeterminate_material.xml contains the trim
+ animation data.
+ - core/res/res/interpolator/trim_start_interpolator.xml and
+ core/res/res/interpolator/trim_end_interpolator.xml contain the start
+ and end trim path interpolators.
+ - addCommand() in core/java/android/util/PathParser.java has a list of the
+ different path commands available.
+*/
+
+static const int SpanAnimationDuration = 700;
+static const int RotationAnimationDuration = SpanAnimationDuration * 6;
+static const int TargetRotation = 720;
+static const int OneDegree = 16;
+static const qreal MinSweepSpan = 10 * OneDegree;
+static const qreal MaxSweepSpan = 300 * OneDegree;
+
+class QQuickMaterialBusyIndicatorNode : public QQuickAnimatedNode
+{
+public:
+ QQuickMaterialBusyIndicatorNode(QQuickMaterialBusyIndicator *item);
+
+ void sync(QQuickItem *item) override;
+
+protected:
+ void updateCurrentTime(int time) override;
+
+private:
+ int m_lastStartAngle;
+ int m_lastEndAngle;
+ qreal m_width;
+ qreal m_height;
+ qreal m_devicePixelRatio;
+ QColor m_color;
+};
+
+QQuickMaterialBusyIndicatorNode::QQuickMaterialBusyIndicatorNode(QQuickMaterialBusyIndicator *item)
+ : QQuickAnimatedNode(item),
+ m_lastStartAngle(0),
+ m_lastEndAngle(0),
+ m_width(0),
+ m_height(0),
+ m_devicePixelRatio(1)
+{
+ setLoopCount(Infinite);
+ setCurrentTime(item->elapsed());
+ setDuration(RotationAnimationDuration);
+
+ QSGImageNode *textureNode = item->window()->createImageNode();
+ textureNode->setOwnsTexture(true);
+ appendChildNode(textureNode);
+
+ // A texture seems to be required here, but we don't have one yet, as we haven't drawn anything,
+ // so just use a blank image.
+ QImage blankImage(item->width(), item->height(), QImage::Format_ARGB32_Premultiplied);
+ blankImage.fill(Qt::transparent);
+ textureNode->setTexture(item->window()->createTextureFromImage(blankImage));
+}
+
+void QQuickMaterialBusyIndicatorNode::updateCurrentTime(int time)
+{
+ const qreal w = m_width;
+ const qreal h = m_height;
+ const qreal size = qMin(w, h);
+ const qreal dx = (w - size) / 2;
+ const qreal dy = (h - size) / 2;
+
+ QImage image(size * m_devicePixelRatio, size * m_devicePixelRatio, QImage::Format_ARGB32_Premultiplied);
+ image.fill(Qt::transparent);
+
+ QPainter painter(&image);
+ painter.setRenderHint(QPainter::Antialiasing);
+
+ QPen pen;
+ QSGImageNode *textureNode = static_cast<QSGImageNode *>(firstChild());
+ pen.setColor(m_color);
+ pen.setWidth(4 * m_devicePixelRatio);
+ painter.setPen(pen);
+
+ const qreal percentageComplete = time / qreal(RotationAnimationDuration);
+ const qreal spanPercentageComplete = (time % SpanAnimationDuration) / qreal(SpanAnimationDuration);
+ const int iteration = time / SpanAnimationDuration;
+ int startAngle = 0;
+ int endAngle = 0;
+
+ if (iteration % 2 == 0) {
+ if (m_lastStartAngle > 360 * OneDegree)
+ m_lastStartAngle -= 360 * OneDegree;
+
+ // The start angle is only affected by the rotation animation for the "grow" phase.
+ startAngle = m_lastStartAngle;
+ QEasingCurve angleCurve(QEasingCurve::OutQuad);
+ const qreal percentage = angleCurve.valueForProgress(spanPercentageComplete);
+ endAngle = m_lastStartAngle + MinSweepSpan + percentage * (MaxSweepSpan - MinSweepSpan);
+ m_lastEndAngle = endAngle;
+ } else {
+ // Both the start angle *and* the span are affected by the "shrink" phase.
+ QEasingCurve angleCurve(QEasingCurve::InQuad);
+ const qreal percentage = angleCurve.valueForProgress(spanPercentageComplete);
+ startAngle = m_lastEndAngle - MaxSweepSpan + percentage * (MaxSweepSpan - MinSweepSpan);
+ endAngle = m_lastEndAngle;
+ m_lastStartAngle = startAngle;
+ }
+
+ const int halfPen = pen.width() / 2;
+ const QRectF arcBounds = QRectF(halfPen, halfPen,
+ m_devicePixelRatio * size - pen.width(),
+ m_devicePixelRatio * size - pen.width());
+ // The current angle of the rotation animation.
+ const qreal rotation = OneDegree * percentageComplete * -TargetRotation;
+ startAngle -= rotation;
+ endAngle -= rotation;
+ const int angleSpan = endAngle - startAngle;
+ painter.drawArc(arcBounds, -startAngle, -angleSpan);
+ painter.end();
+
+ textureNode->setRect(QRectF(dx, dy, size, size));
+ textureNode->setTexture(window()->createTextureFromImage(image));
+}
+
+void QQuickMaterialBusyIndicatorNode::sync(QQuickItem *item)
+{
+ QQuickMaterialBusyIndicator *indicator = static_cast<QQuickMaterialBusyIndicator *>(item);
+ m_color = indicator->color();
+ m_width = indicator->width();
+ m_height = indicator->height();
+ m_devicePixelRatio = indicator->window()->effectiveDevicePixelRatio();
+}
+
+QQuickMaterialBusyIndicator::QQuickMaterialBusyIndicator(QQuickItem *parent) :
+ QQuickItem(parent)
+{
+ setFlag(ItemHasContents);
+}
+
+QColor QQuickMaterialBusyIndicator::color() const
+{
+ return m_color;
+}
+
+void QQuickMaterialBusyIndicator::setColor(QColor color)
+{
+ if (m_color == color)
+ return;
+
+ m_color = color;
+ update();
+}
+
+int QQuickMaterialBusyIndicator::elapsed() const
+{
+ return m_elapsed;
+}
+
+void QQuickMaterialBusyIndicator::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data)
+{
+ QQuickItem::itemChange(change, data);
+ if (change == ItemVisibleHasChanged)
+ update();
+}
+
+QSGNode *QQuickMaterialBusyIndicator::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
+{
+ QQuickMaterialBusyIndicatorNode *node = static_cast<QQuickMaterialBusyIndicatorNode *>(oldNode);
+ if (isVisible() && width() > 0 && height() > 0) {
+ if (!node) {
+ node = new QQuickMaterialBusyIndicatorNode(this);
+ node->start();
+ }
+ node->sync(this);
+ } else {
+ m_elapsed = node ? node->currentTime() : 0;
+ delete node;
+ node = nullptr;
+ }
+ return node;
+}
+
+QT_END_NAMESPACE
diff --git a/src/imports/controls/material/qquickmaterialprogressring_p.h b/src/imports/controls/material/qquickmaterialbusyindicator_p.h
index 004771d6..da84c7b1 100644
--- a/src/imports/controls/material/qquickmaterialprogressring_p.h
+++ b/src/imports/controls/material/qquickmaterialbusyindicator_p.h
@@ -34,8 +34,8 @@
**
****************************************************************************/
-#ifndef QQUICKMATERIALPROGRESSRING_P_H
-#define QQUICKMATERIALPROGRESSRING_P_H
+#ifndef QQUICKMATERIALBUSYINDICATOR_P_H
+#define QQUICKMATERIALBUSYINDICATOR_P_H
//
// W A R N I N G
@@ -50,44 +50,33 @@
#include <QtGui/qcolor.h>
#include <QtQuick/qquickitem.h>
-#include <QtQuick/private/qquickanimatorjob_p.h>
QT_BEGIN_NAMESPACE
-class QQuickMaterialProgressRing : public QQuickItem
+class QQuickMaterialBusyIndicator : public QQuickItem
{
Q_OBJECT
- Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged FINAL)
+ Q_PROPERTY(QColor color READ color WRITE setColor FINAL)
public:
- explicit QQuickMaterialProgressRing(QQuickItem *parent = nullptr);
- ~QQuickMaterialProgressRing();
+ explicit QQuickMaterialBusyIndicator(QQuickItem *parent = nullptr);
QColor color() const;
void setColor(QColor color);
-Q_SIGNALS:
- void colorChanged();
+ int elapsed() const;
protected:
+ void itemChange(ItemChange change, const ItemChangeData &data) override;
QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) override;
private:
+ int m_elapsed;
QColor m_color;
};
-class QQuickMaterialRingAnimator : public QQuickAnimator
-{
-public:
- QQuickMaterialRingAnimator(QObject *parent = nullptr);
-
-protected:
- QString propertyName() const override;
- QQuickAnimatorJob *createJob() const override;
-};
-
QT_END_NAMESPACE
-QML_DECLARE_TYPE(QQuickMaterialProgressRing)
+QML_DECLARE_TYPE(QQuickMaterialBusyIndicator)
-#endif // QQUICKMATERIALPROGRESSRING_P_H
+#endif // QQUICKMATERIALBUSYINDICATOR_P_H
diff --git a/src/imports/controls/material/qquickmaterialprogressstrip.cpp b/src/imports/controls/material/qquickmaterialprogressbar.cpp
index 4bb558b3..c1d36d3b 100644
--- a/src/imports/controls/material/qquickmaterialprogressstrip.cpp
+++ b/src/imports/controls/material/qquickmaterialprogressbar.cpp
@@ -34,15 +34,16 @@
**
****************************************************************************/
-#include "qquickmaterialprogressstrip_p.h"
+#include "qquickmaterialprogressbar_p.h"
#include <QtCore/qmath.h>
#include <QtCore/qeasingcurve.h>
#include <QtQuick/private/qquickitem_p.h>
-#include <QtQuick/private/qquickanimatorjob_p.h>
#include <QtQuick/private/qsgadaptationlayer_p.h>
#include <QtQuick/qsgrectanglenode.h>
#include <QtQuick/qsgimagenode.h>
+#include <QtQuick/qquickwindow.h>
+#include <QtQuickControls2/private/qquickanimatednode_p.h>
QT_BEGIN_NAMESPACE
@@ -50,43 +51,34 @@ static const int PauseDuration = 520;
static const int SlideDuration = 1240;
static const int TotalDuration = SlideDuration + PauseDuration;
-class QQuickMaterialProgressStripAnimatorJob : public QQuickAnimatorJob
+class QQuickMaterialProgressBarNode : public QQuickAnimatedNode
{
public:
- QQuickMaterialProgressStripAnimatorJob();
+ QQuickMaterialProgressBarNode(QQuickMaterialProgressBar *item);
- void initialize(QQuickAnimatorController *controller) override;
void updateCurrentTime(int time) override;
- void writeBack() override;
- void nodeWasDestroyed() override;
- void afterNodeSync() override;
+ void sync(QQuickItem *item) override;
+private:
void moveNode(QSGTransformNode *node, const QRectF &geometry, qreal progress);
-private:
- QSGNode *m_node;
+ bool m_indeterminate;
+ QEasingCurve m_easing;
};
-QQuickMaterialProgressStripAnimatorJob::QQuickMaterialProgressStripAnimatorJob() : m_node(nullptr)
-{
-}
-
-void QQuickMaterialProgressStripAnimatorJob::initialize(QQuickAnimatorController *controller)
+QQuickMaterialProgressBarNode::QQuickMaterialProgressBarNode(QQuickMaterialProgressBar *item)
+ : QQuickAnimatedNode(item),
+ m_indeterminate(false),
+ m_easing(QEasingCurve::OutCubic)
{
- QQuickAnimatorJob::initialize(controller);
- m_node = QQuickItemPrivate::get(m_target)->childContainerNode();
+ setLoopCount(Infinite);
+ setDuration(TotalDuration);
}
-void QQuickMaterialProgressStripAnimatorJob::updateCurrentTime(int time)
+void QQuickMaterialProgressBarNode::updateCurrentTime(int time)
{
- if (!m_node)
- return;
-
- QSGRectangleNode *geometryNode = static_cast<QSGRectangleNode *>(m_node->firstChild());
- Q_ASSERT(!geometryNode || geometryNode->type() == QSGNode::GeometryNodeType);
- if (!geometryNode)
- return;
-
+ QSGRectangleNode *geometryNode = static_cast<QSGRectangleNode *>(firstChild());
+ Q_ASSERT(geometryNode->type() == QSGNode::GeometryNodeType);
const QRectF geometry = geometryNode->rect();
QSGTransformNode *firstNode = static_cast<QSGTransformNode *>(geometryNode->firstChild());
@@ -106,21 +98,66 @@ void QQuickMaterialProgressStripAnimatorJob::updateCurrentTime(int time)
}
}
-void QQuickMaterialProgressStripAnimatorJob::writeBack()
+void QQuickMaterialProgressBarNode::sync(QQuickItem *item)
{
-}
+ QQuickMaterialProgressBar *bar = static_cast<QQuickMaterialProgressBar *>(item);
+ if (m_indeterminate != bar->isIndeterminate()) {
+ m_indeterminate = bar->isIndeterminate();
+ if (m_indeterminate)
+ start();
+ else
+ stop();
+ }
-void QQuickMaterialProgressStripAnimatorJob::nodeWasDestroyed()
-{
- m_node = nullptr;
-}
+ QQuickItemPrivate *d = QQuickItemPrivate::get(item);
-void QQuickMaterialProgressStripAnimatorJob::afterNodeSync()
-{
- m_node = QQuickItemPrivate::get(m_target)->childContainerNode();
+ QRectF bounds = item->boundingRect();
+ bounds.setHeight(item->implicitHeight());
+ bounds.moveTop((item->height() - bounds.height()) / 2.0);
+
+ QSGRectangleNode *geometryNode = static_cast<QSGRectangleNode *>(firstChild());
+ if (!geometryNode) {
+ geometryNode = item->window()->createRectangleNode();
+ geometryNode->setColor(Qt::transparent);
+ appendChildNode(geometryNode);
+ }
+ geometryNode->setRect(bounds);
+
+ const int count = m_indeterminate ? 2 : 1;
+ const qreal w = m_indeterminate ? 0 : bar->progress() * item->width();
+ const QRectF rect(0, bounds.y(), w, bounds.height());
+
+ QSGNode *transformNode = geometryNode->firstChild();
+ for (int i = 0; i < count; ++i) {
+ if (!transformNode) {
+ transformNode = new QSGTransformNode;
+ geometryNode->appendChildNode(transformNode);
+
+ QSGInternalRectangleNode *rectNode = d->sceneGraphContext()->createInternalRectangleNode();
+ rectNode->setAntialiasing(true);
+ transformNode->appendChildNode(rectNode);
+ }
+ Q_ASSERT(transformNode->type() == QSGNode::TransformNodeType);
+ static_cast<QSGTransformNode *>(transformNode)->setMatrix(QMatrix4x4());
+
+ QSGInternalRectangleNode *rectNode = static_cast<QSGInternalRectangleNode *>(transformNode->firstChild());
+ Q_ASSERT(rectNode->type() == QSGNode::GeometryNodeType);
+
+ rectNode->setRect(rect);
+ rectNode->setColor(bar->color());
+ rectNode->update();
+
+ transformNode = transformNode->nextSibling();
+ }
+
+ while (transformNode) {
+ QSGNode *nextSibling = transformNode->nextSibling();
+ delete transformNode;
+ transformNode = nextSibling;
+ }
}
-void QQuickMaterialProgressStripAnimatorJob::moveNode(QSGTransformNode *transformNode, const QRectF &geometry, qreal progress)
+void QQuickMaterialProgressBarNode::moveNode(QSGTransformNode *transformNode, const QRectF &geometry, qreal progress)
{
const qreal value = m_easing.valueForProgress(progress);
const qreal x = value * geometry.width();
@@ -138,36 +175,18 @@ void QQuickMaterialProgressStripAnimatorJob::moveNode(QSGTransformNode *transfor
rectNode->update();
}
-QQuickMaterialStripAnimator::QQuickMaterialStripAnimator(QObject *parent)
- : QQuickAnimator(parent)
-{
- setLoops(Infinite);
- setDuration(TotalDuration);
- setEasing(QEasingCurve::OutCubic);
-}
-
-QString QQuickMaterialStripAnimator::propertyName() const
-{
- return QString();
-}
-
-QQuickAnimatorJob *QQuickMaterialStripAnimator::createJob() const
-{
- return new QQuickMaterialProgressStripAnimatorJob;
-}
-
-QQuickMaterialProgressStrip::QQuickMaterialProgressStrip(QQuickItem *parent)
+QQuickMaterialProgressBar::QQuickMaterialProgressBar(QQuickItem *parent)
: QQuickItem(parent), m_color(Qt::black), m_progress(0.0), m_indeterminate(false)
{
setFlag(ItemHasContents);
}
-QColor QQuickMaterialProgressStrip::color() const
+QColor QQuickMaterialProgressBar::color() const
{
return m_color;
}
-void QQuickMaterialProgressStrip::setColor(const QColor &color)
+void QQuickMaterialProgressBar::setColor(const QColor &color)
{
if (color == m_color)
return;
@@ -176,12 +195,12 @@ void QQuickMaterialProgressStrip::setColor(const QColor &color)
update();
}
-qreal QQuickMaterialProgressStrip::progress() const
+qreal QQuickMaterialProgressBar::progress() const
{
return m_progress;
}
-void QQuickMaterialProgressStrip::setProgress(qreal progress)
+void QQuickMaterialProgressBar::setProgress(qreal progress)
{
if (progress == m_progress)
return;
@@ -190,12 +209,12 @@ void QQuickMaterialProgressStrip::setProgress(qreal progress)
update();
}
-bool QQuickMaterialProgressStrip::isIndeterminate() const
+bool QQuickMaterialProgressBar::isIndeterminate() const
{
return m_indeterminate;
}
-void QQuickMaterialProgressStrip::setIndeterminate(bool indeterminate)
+void QQuickMaterialProgressBar::setIndeterminate(bool indeterminate)
{
if (indeterminate == m_indeterminate)
return;
@@ -204,54 +223,25 @@ void QQuickMaterialProgressStrip::setIndeterminate(bool indeterminate)
update();
}
-QSGNode *QQuickMaterialProgressStrip::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
+void QQuickMaterialProgressBar::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data)
{
- QQuickItemPrivate *d = QQuickItemPrivate::get(this);
-
- QRectF bounds = boundingRect();
- bounds.setHeight(implicitHeight());
- bounds.moveTop((height() - bounds.height()) / 2.0);
-
- if (!oldNode) {
- oldNode = window()->createRectangleNode();
- static_cast<QSGRectangleNode *>(oldNode)->setColor(Qt::transparent);
- }
- static_cast<QSGRectangleNode *>(oldNode)->setRect(bounds);
-
- const int count = m_indeterminate ? 2 : 1;
- const qreal w = m_indeterminate ? 0 : m_progress * width();
- const QRectF rect(0, bounds.y(), w, bounds.height());
-
- QSGNode *transformNode = oldNode->firstChild();
- for (int i = 0; i < count; ++i) {
- if (!transformNode) {
- transformNode = new QSGTransformNode;
- oldNode->appendChildNode(transformNode);
-
- QSGInternalRectangleNode *rectNode = d->sceneGraphContext()->createInternalRectangleNode();
- rectNode->setAntialiasing(true);
- transformNode->appendChildNode(rectNode);
- }
- Q_ASSERT(transformNode->type() == QSGNode::TransformNodeType);
- static_cast<QSGTransformNode *>(transformNode)->setMatrix(QMatrix4x4());
-
- QSGInternalRectangleNode *rectNode = static_cast<QSGInternalRectangleNode *>(transformNode->firstChild());
- Q_ASSERT(rectNode->type() == QSGNode::GeometryNodeType);
-
- rectNode->setRect(rect);
- rectNode->setColor(m_color);
- rectNode->update();
-
- transformNode = transformNode->nextSibling();
- }
+ QQuickItem::itemChange(change, data);
+ if (change == ItemVisibleHasChanged)
+ update();
+}
- while (transformNode) {
- QSGNode *nextSibling = transformNode->nextSibling();
- delete transformNode;
- transformNode = nextSibling;
+QSGNode *QQuickMaterialProgressBar::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *)
+{
+ QQuickMaterialProgressBarNode *node = static_cast<QQuickMaterialProgressBarNode *>(oldNode);
+ if (isVisible() && width() > 0 && height() > 0) {
+ if (!node)
+ node = new QQuickMaterialProgressBarNode(this);
+ node->sync(this);
+ } else {
+ delete node;
+ node = nullptr;
}
-
- return oldNode;
+ return node;
}
QT_END_NAMESPACE
diff --git a/src/imports/controls/material/qquickmaterialprogressstrip_p.h b/src/imports/controls/material/qquickmaterialprogressbar_p.h
index affe0670..f481281d 100644
--- a/src/imports/controls/material/qquickmaterialprogressstrip_p.h
+++ b/src/imports/controls/material/qquickmaterialprogressbar_p.h
@@ -34,8 +34,8 @@
**
****************************************************************************/
-#ifndef QQUICKMATERIALPROGRESSSTRIP_P_H
-#define QQUICKMATERIALPROGRESSSTRIP_P_H
+#ifndef QQUICKMATERIALPROGRESSBAR_P_H
+#define QQUICKMATERIALPROGRESSBAR_P_H
//
// W A R N I N G
@@ -49,11 +49,10 @@
//
#include <QtQuick/qquickitem.h>
-#include <QtQuick/private/qquickanimator_p.h>
QT_BEGIN_NAMESPACE
-class QQuickMaterialProgressStrip : public QQuickItem
+class QQuickMaterialProgressBar : public QQuickItem
{
Q_OBJECT
Q_PROPERTY(QColor color READ color WRITE setColor FINAL)
@@ -61,7 +60,7 @@ class QQuickMaterialProgressStrip : public QQuickItem
Q_PROPERTY(bool indeterminate READ isIndeterminate WRITE setIndeterminate FINAL)
public:
- QQuickMaterialProgressStrip(QQuickItem *parent = nullptr);
+ explicit QQuickMaterialProgressBar(QQuickItem *parent = nullptr);
QColor color() const;
void setColor(const QColor &color);
@@ -73,6 +72,7 @@ public:
void setIndeterminate(bool indeterminate);
protected:
+ void itemChange(ItemChange change, const ItemChangeData &data) override;
QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) override;
private:
@@ -81,21 +81,8 @@ private:
bool m_indeterminate;
};
-class QQuickMaterialStripAnimator : public QQuickAnimator
-{
- Q_OBJECT
-
-public:
- QQuickMaterialStripAnimator(QObject *parent = nullptr);
-
-protected:
- QString propertyName() const override;
- QQuickAnimatorJob *createJob() const override;
-};
-
QT_END_NAMESPACE
-QML_DECLARE_TYPE(QQuickMaterialProgressStrip)
-QML_DECLARE_TYPE(QQuickMaterialStripAnimator)
+QML_DECLARE_TYPE(QQuickMaterialProgressBar)
-#endif // QQUICKMATERIALPROGRESSSTRIP_P_H
+#endif // QQUICKMATERIALPROGRESSBAR_P_H
diff --git a/src/imports/controls/material/qquickmaterialprogressring.cpp b/src/imports/controls/material/qquickmaterialprogressring.cpp
deleted file mode 100644
index 53ca68d2..00000000
--- a/src/imports/controls/material/qquickmaterialprogressring.cpp
+++ /dev/null
@@ -1,260 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL3$
-** 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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qquickmaterialprogressring_p.h"
-
-#include <cmath>
-
-#include <QtCore/qset.h>
-#include <QtGui/qpainter.h>
-#include <QtQuick/private/qquickitem_p.h>
-#include <QtQuick/qsgrectanglenode.h>
-#include <QtQuick/qsgimagenode.h>
-#include <QtQuick/qquickwindow.h>
-
-QT_BEGIN_NAMESPACE
-
-/*
- Relevant Android code:
-
- - core/res/res/anim/progress_indeterminate_rotation_material.xml contains
- the rotation animation data.
- - core/res/res/anim/progress_indeterminate_material.xml contains the trim
- animation data.
- - core/res/res/interpolator/trim_start_interpolator.xml and
- core/res/res/interpolator/trim_end_interpolator.xml contain the start
- and end trim path interpolators.
- - addCommand() in core/java/android/util/PathParser.java has a list of the
- different path commands available.
-*/
-
-class QQuickMaterialRingAnimatorJob : public QQuickAnimatorJob
-{
-public:
- QQuickMaterialRingAnimatorJob();
- ~QQuickMaterialRingAnimatorJob();
-
- void initialize(QQuickAnimatorController *controller) override;
- void updateCurrentTime(int time) override;
- void writeBack() override;
- void nodeWasDestroyed() override;
- void afterNodeSync() override;
-
-private:
- int m_lastStartAngle;
- int m_lastEndAngle;
- qreal m_devicePixelRatio;
- QSGNode *m_containerNode;
- QQuickWindow *m_window;
- QColor m_color;
-};
-
-QQuickMaterialProgressRing::QQuickMaterialProgressRing(QQuickItem *parent) :
- QQuickItem(parent)
-{
- setFlag(QQuickItem::ItemHasContents);
-}
-
-QQuickMaterialProgressRing::~QQuickMaterialProgressRing()
-{
-}
-
-QSGNode *QQuickMaterialProgressRing::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *)
-{
- if (!oldNode) {
- oldNode = window()->createRectangleNode();
- static_cast<QSGRectangleNode *>(oldNode)->setColor(Qt::transparent);
- }
- static_cast<QSGRectangleNode *>(oldNode)->setRect(boundingRect());
-
- QSGImageNode *textureNode = static_cast<QSGImageNode *>(oldNode->firstChild());
- if (!textureNode) {
- textureNode = window()->createImageNode();
- textureNode->setOwnsTexture(true);
- oldNode->appendChildNode(textureNode);
- }
-
- // A texture seems to be required here, but we don't have one yet, as we haven't drawn anything,
- // so just use a blank image.
- QImage blankImage(width(), height(), QImage::Format_ARGB32_Premultiplied);
- blankImage.fill(Qt::transparent);
- textureNode->setRect(boundingRect());
- textureNode->setTexture(window()->createTextureFromImage(blankImage));
-
- return oldNode;
-}
-
-QColor QQuickMaterialProgressRing::color() const
-{
- return m_color;
-}
-
-void QQuickMaterialProgressRing::setColor(QColor color)
-{
- if (m_color == color)
- return;
-
- m_color = color;
- update();
- emit colorChanged();
-}
-
-static const int spanAnimationDuration = 700;
-static const int rotationAnimationDuration = spanAnimationDuration * 6;
-static const int targetRotation = 720;
-static const int oneDegree = 16;
-static const qreal minSweepSpan = 10 * oneDegree;
-static const qreal maxSweepSpan = 300 * oneDegree;
-
-QQuickMaterialRingAnimator::QQuickMaterialRingAnimator(QObject *parent) :
- QQuickAnimator(parent)
-{
- setDuration(rotationAnimationDuration);
- setLoops(QQuickAnimator::Infinite);
-}
-
-QString QQuickMaterialRingAnimator::propertyName() const
-{
- return QString();
-}
-
-QQuickAnimatorJob *QQuickMaterialRingAnimator::createJob() const
-{
- return new QQuickMaterialRingAnimatorJob;
-}
-
-QQuickMaterialRingAnimatorJob::QQuickMaterialRingAnimatorJob() :
- m_lastStartAngle(0),
- m_lastEndAngle(0),
- m_devicePixelRatio(1.0),
- m_containerNode(nullptr),
- m_window(nullptr)
-{
-}
-
-QQuickMaterialRingAnimatorJob::~QQuickMaterialRingAnimatorJob()
-{
-}
-
-void QQuickMaterialRingAnimatorJob::initialize(QQuickAnimatorController *controller)
-{
- QQuickAnimatorJob::initialize(controller);
- m_containerNode = QQuickItemPrivate::get(m_target)->childContainerNode();
- m_window = m_target->window();
- m_devicePixelRatio = m_window->effectiveDevicePixelRatio();
-}
-
-void QQuickMaterialRingAnimatorJob::updateCurrentTime(int time)
-{
- if (!m_containerNode)
- return;
-
- QSGRectangleNode *rectNode = static_cast<QSGRectangleNode *>(m_containerNode->firstChild());
- if (!rectNode)
- return;
-
- Q_ASSERT(rectNode->type() == QSGNode::GeometryNodeType);
-
- const qreal width = rectNode->rect().width() * m_devicePixelRatio;
- const qreal height = rectNode->rect().height() * m_devicePixelRatio;
- QImage image(width, height, QImage::Format_ARGB32_Premultiplied);
- image.fill(Qt::transparent);
-
- QPainter painter(&image);
- painter.setRenderHint(QPainter::Antialiasing);
-
- QPen pen;
- QSGImageNode *textureNode = static_cast<QSGImageNode *>(rectNode->firstChild());
- pen.setColor(m_color);
- pen.setWidth(4 * m_devicePixelRatio);
- painter.setPen(pen);
-
- const qreal percentageComplete = time / qreal(rotationAnimationDuration);
- const qreal spanPercentageComplete = (time % spanAnimationDuration) / qreal(spanAnimationDuration);
- const int iteration = time / spanAnimationDuration;
- int startAngle = 0;
- int endAngle = 0;
-
- if (iteration % 2 == 0) {
- if (m_lastStartAngle > 360 * oneDegree) {
- m_lastStartAngle -= 360 * oneDegree;
- }
-
- // The start angle is only affected by the rotation animation for the "grow" phase.
- startAngle = m_lastStartAngle;
- QEasingCurve angleCurve(QEasingCurve::OutQuad);
- const qreal percentage = angleCurve.valueForProgress(spanPercentageComplete);
- endAngle = m_lastStartAngle + minSweepSpan + percentage * (maxSweepSpan - minSweepSpan);
- m_lastEndAngle = endAngle;
- } else {
- // Both the start angle *and* the span are affected by the "shrink" phase.
- QEasingCurve angleCurve(QEasingCurve::InQuad);
- const qreal percentage = angleCurve.valueForProgress(spanPercentageComplete);
- startAngle = m_lastEndAngle - maxSweepSpan + percentage * (maxSweepSpan - minSweepSpan);
- endAngle = m_lastEndAngle;
- m_lastStartAngle = startAngle;
- }
-
- const int halfPen = pen.width() / 2;
- const QRectF arcBounds = QRectF(halfPen, halfPen, width - pen.width(), height - pen.width());
- // The current angle of the rotation animation.
- const qreal rotation = oneDegree * percentageComplete * -targetRotation;
- startAngle -= rotation;
- endAngle -= rotation;
- const int angleSpan = endAngle - startAngle;
- painter.drawArc(arcBounds, -startAngle, -angleSpan);
- painter.end();
-
- textureNode->setTexture(m_window->createTextureFromImage(image));
-}
-
-void QQuickMaterialRingAnimatorJob::writeBack()
-{
-}
-
-void QQuickMaterialRingAnimatorJob::nodeWasDestroyed()
-{
- m_containerNode = nullptr;
- m_window = nullptr;
-}
-
-void QQuickMaterialRingAnimatorJob::afterNodeSync()
-{
- m_containerNode = QQuickItemPrivate::get(m_target)->childContainerNode();
- m_color = static_cast<QQuickMaterialProgressRing *>(m_target.data())->color();
-}
-
-QT_END_NAMESPACE
diff --git a/src/imports/controls/material/qquickmaterialripple.cpp b/src/imports/controls/material/qquickmaterialripple.cpp
index bd916f83..ac2fbc06 100644
--- a/src/imports/controls/material/qquickmaterialripple.cpp
+++ b/src/imports/controls/material/qquickmaterialripple.cpp
@@ -38,10 +38,8 @@
#include <QtCore/qmath.h>
#include <QtQuick/private/qquickitem_p.h>
-#include <QtQuick/private/qquickanimator_p.h>
-#include <QtQuick/private/qquickrectangle_p.h>
-#include <QtQuick/private/qquickanimatorjob_p.h>
#include <QtQuick/private/qsgadaptationlayer_p.h>
+#include <QtQuickControls2/private/qquickanimatednode_p.h>
#include <QtQuickTemplates2/private/qquickabstractbutton_p.h>
#include <QtQuickTemplates2/private/qquickabstractbutton_p_p.h>
@@ -54,157 +52,184 @@ namespace {
static const int RIPPLE_ENTER_DELAY = 80;
static const int OPACITY_ENTER_DURATION_FAST = 120;
static const int WAVE_OPACITY_DECAY_DURATION = 333;
-static const qreal WAVE_TOUCH_UP_ACCELERATION = 3400.0;
static const qreal WAVE_TOUCH_DOWN_ACCELERATION = 1024.0;
-class QQuickMaterialRippleAnimatorJob : public QQuickAnimatorJob
+class QQuickMaterialRippleWaveNode : public QQuickAnimatedNode
{
public:
- QQuickMaterialRippleAnimatorJob(WavePhase phase, const QPointF &anchor, const QRectF &bounds);
+ QQuickMaterialRippleWaveNode(QQuickMaterialRipple *ripple);
- void initialize(QQuickAnimatorController *controller) override;
+ void exit();
void updateCurrentTime(int time) override;
- void writeBack() override;
- void nodeWasDestroyed() override;
- void afterNodeSync() override;
+ void sync(QQuickItem *item) override;
private:
- qreal m_diameter;
+ qreal m_from;
+ qreal m_to;
+ qreal m_value;
WavePhase m_phase;
- QRectF m_bounds;
QPointF m_anchor;
- QSGTransformNode *m_itemNode;
- QSGOpacityNode *m_opacityNode;
- QSGInternalRectangleNode *m_rectNode;
+ QRectF m_bounds;
};
-QQuickMaterialRippleAnimatorJob::QQuickMaterialRippleAnimatorJob(WavePhase phase, const QPointF &anchor, const QRectF &bounds)
- : m_diameter(qSqrt(bounds.width() * bounds.width() + bounds.height() * bounds.height())),
- m_phase(phase),
- m_bounds(bounds),
- m_anchor(anchor),
- m_itemNode(nullptr),
- m_opacityNode(nullptr),
- m_rectNode(nullptr)
+QQuickMaterialRippleWaveNode::QQuickMaterialRippleWaveNode(QQuickMaterialRipple *ripple)
+ : QQuickAnimatedNode(ripple),
+ m_from(0),
+ m_to(0),
+ m_value(0),
+ m_phase(WaveEnter)
{
+ start(qRound(1000.0 * qSqrt(ripple->diameter() / 2.0 / WAVE_TOUCH_DOWN_ACCELERATION)));
+
+ QSGOpacityNode *opacityNode = new QSGOpacityNode;
+ appendChildNode(opacityNode);
+
+ QQuickItemPrivate *d = QQuickItemPrivate::get(ripple);
+ QSGInternalRectangleNode *rectNode = d->sceneGraphContext()->createInternalRectangleNode();
+ rectNode->setAntialiasing(true);
+ opacityNode->appendChildNode(rectNode);
}
-void QQuickMaterialRippleAnimatorJob::initialize(QQuickAnimatorController *controller)
+void QQuickMaterialRippleWaveNode::exit()
{
- QQuickAnimatorJob::initialize(controller);
- afterNodeSync();
+ m_phase = WaveExit;
+ m_from = m_value;
+ setDuration(WAVE_OPACITY_DECAY_DURATION);
+ restart();
+ connect(this, &QQuickAnimatedNode::stopped, this, &QObject::deleteLater);
}
-void QQuickMaterialRippleAnimatorJob::updateCurrentTime(int time)
+void QQuickMaterialRippleWaveNode::updateCurrentTime(int time)
{
- if (!m_itemNode || !m_rectNode)
- return;
-
- qreal duration = 0;
- if (m_phase == WaveEnter)
- duration = QQuickAnimatorJob::duration();
- else
- duration = 1000.0 * qSqrt((m_diameter - m_from) / 2.0 / (WAVE_TOUCH_UP_ACCELERATION + WAVE_TOUCH_DOWN_ACCELERATION));
-
qreal p = 1.0;
- if (!qFuzzyIsNull(duration) && time < duration)
- p = time / duration;
+ if (duration() > 0)
+ p = time / static_cast<qreal>(duration());
m_value = m_from + (m_to - m_from) * p;
- p = m_value / m_diameter;
+ p = m_value / m_to;
const qreal dx = (1.0 - p) * (m_anchor.x() - m_bounds.width() / 2);
const qreal dy = (1.0 - p) * (m_anchor.y() - m_bounds.height() / 2);
- m_rectNode->setRect(QRectF(0, 0, m_value, m_value));
- m_rectNode->setRadius(m_value / 2);
- m_rectNode->update();
-
QMatrix4x4 m;
m.translate((m_bounds.width() - m_value) / 2 + dx,
(m_bounds.height() - m_value) / 2 + dy);
- m_itemNode->setMatrix(m);
+ setMatrix(m);
- if (m_opacityNode) {
- qreal opacity = 1.0;
- if (m_phase == WaveExit)
- opacity -= static_cast<qreal>(time) / WAVE_OPACITY_DECAY_DURATION;
- m_opacityNode->setOpacity(opacity);
- }
-}
-
-void QQuickMaterialRippleAnimatorJob::writeBack()
-{
- if (m_target)
- m_target->setSize(QSizeF(m_value, m_value));
+ QSGOpacityNode *opacityNode = static_cast<QSGOpacityNode *>(firstChild());
+ Q_ASSERT(opacityNode->type() == QSGNode::OpacityNodeType);
+ qreal opacity = 1.0;
if (m_phase == WaveExit)
- m_target->deleteLater();
-}
+ opacity -= static_cast<qreal>(time) / WAVE_OPACITY_DECAY_DURATION;
+ opacityNode->setOpacity(opacity);
-void QQuickMaterialRippleAnimatorJob::nodeWasDestroyed()
-{
- m_itemNode = nullptr;
- m_opacityNode = nullptr;
- m_rectNode = nullptr;
+ QSGInternalRectangleNode *rectNode = static_cast<QSGInternalRectangleNode *>(opacityNode->firstChild());
+ Q_ASSERT(rectNode->type() == QSGNode::GeometryNodeType);
+ rectNode->setRect(QRectF(0, 0, m_value, m_value));
+ rectNode->setRadius(m_value / 2);
+ rectNode->update();
}
-void QQuickMaterialRippleAnimatorJob::afterNodeSync()
+void QQuickMaterialRippleWaveNode::sync(QQuickItem *item)
{
- m_itemNode = QQuickItemPrivate::get(m_target)->itemNode();
- m_opacityNode = QQuickItemPrivate::get(m_target)->opacityNode();
- m_rectNode = static_cast<QSGInternalRectangleNode *>(QQuickItemPrivate::get(m_target)->childContainerNode()->firstChild());
+ QQuickMaterialRipple *ripple = static_cast<QQuickMaterialRipple *>(item);
+ m_to = ripple->diameter();
+ m_anchor = ripple->anchorPoint();
+ m_bounds = ripple->boundingRect();
+
+ QSGOpacityNode *opacityNode = static_cast<QSGOpacityNode *>(firstChild());
+ Q_ASSERT(opacityNode->type() == QSGNode::OpacityNodeType);
+
+ QSGInternalRectangleNode *rectNode = static_cast<QSGInternalRectangleNode *>(opacityNode->firstChild());
+ Q_ASSERT(rectNode->type() == QSGNode::GeometryNodeType);
+ rectNode->setColor(ripple->color());
}
-class QQuickMaterialRippleAnimator : public QQuickAnimator
+class QQuickMaterialRippleBackgroundNode : public QQuickAnimatedNode
{
-public:
- QQuickMaterialRippleAnimator(const QPointF &anchor, const QRectF &bounds, QObject *parent = nullptr);
+ Q_OBJECT
- WavePhase phase() const;
- void setPhase(WavePhase phase);
+public:
+ QQuickMaterialRippleBackgroundNode(QQuickMaterialRipple *ripple);
-protected:
- QString propertyName() const override;
- QQuickAnimatorJob *createJob() const override;
+ void updateCurrentTime(int time) override;
+ void sync(QQuickItem *item) override;
private:
- QPointF m_anchor;
- QRectF m_bounds;
- WavePhase m_phase;
+ bool m_active;
};
-QQuickMaterialRippleAnimator::QQuickMaterialRippleAnimator(const QPointF &anchor, const QRectF &bounds, QObject *parent)
- : QQuickAnimator(parent), m_anchor(anchor), m_bounds(bounds), m_phase(WaveEnter)
+QQuickMaterialRippleBackgroundNode::QQuickMaterialRippleBackgroundNode(QQuickMaterialRipple *ripple)
+ : QQuickAnimatedNode(ripple),
+ m_active(false)
{
-}
+ setDuration(OPACITY_ENTER_DURATION_FAST);
-WavePhase QQuickMaterialRippleAnimator::phase() const
-{
- return m_phase;
+ QSGOpacityNode *opacityNode = new QSGOpacityNode;
+ opacityNode->setOpacity(0.0);
+ appendChildNode(opacityNode);
+
+ QQuickItemPrivate *d = QQuickItemPrivate::get(ripple);
+ QSGInternalRectangleNode *rectNode = d->sceneGraphContext()->createInternalRectangleNode();
+ rectNode->setAntialiasing(true);
+ opacityNode->appendChildNode(rectNode);
}
-void QQuickMaterialRippleAnimator::setPhase(WavePhase phase)
+void QQuickMaterialRippleBackgroundNode::updateCurrentTime(int time)
{
- if (m_phase == phase)
- return;
+ qreal opacity = time / static_cast<qreal>(duration());
+ if (!m_active)
+ opacity = 1.0 - opacity;
- m_phase = phase;
+ QSGOpacityNode *opacityNode = static_cast<QSGOpacityNode *>(firstChild());
+ Q_ASSERT(opacityNode->type() == QSGNode::OpacityNodeType);
+ opacityNode->setOpacity(opacity);
}
-QString QQuickMaterialRippleAnimator::propertyName() const
+void QQuickMaterialRippleBackgroundNode::sync(QQuickItem *item)
{
- return QString();
-}
+ QQuickMaterialRipple *ripple = static_cast<QQuickMaterialRipple *>(item);
+ if (m_active != ripple->isActive()) {
+ m_active = ripple->isActive();
+ setDuration(m_active ? OPACITY_ENTER_DURATION_FAST : WAVE_OPACITY_DECAY_DURATION);
+ restart();
+ }
-QQuickAnimatorJob *QQuickMaterialRippleAnimator::createJob() const
-{
- return new QQuickMaterialRippleAnimatorJob(m_phase, m_anchor, m_bounds);
+ QSGOpacityNode *opacityNode = static_cast<QSGOpacityNode *>(firstChild());
+ Q_ASSERT(opacityNode->type() == QSGNode::OpacityNodeType);
+
+ QSGInternalRectangleNode *rectNode = static_cast<QSGInternalRectangleNode *>(opacityNode->firstChild());
+ Q_ASSERT(rectNode->type() == QSGNode::GeometryNodeType);
+
+ const qreal w = ripple->width();
+ const qreal h = ripple->height();
+ const qreal sz = qSqrt(w * w + h * h);
+
+ QMatrix4x4 matrix;
+ if (qFuzzyIsNull(ripple->clipRadius())) {
+ matrix.translate((w - sz) / 2, (h - sz) / 2);
+ rectNode->setRect(QRectF(0, 0, sz, sz));
+ rectNode->setRadius(sz / 2);
+ } else {
+ rectNode->setRect(QRectF(0, 0, w, h));
+ rectNode->setRadius(ripple->clipRadius());
+ }
+
+ setMatrix(matrix);
+ rectNode->setColor(ripple->color());
+ rectNode->update();
}
QQuickMaterialRipple::QQuickMaterialRipple(QQuickItem *parent)
- : QQuickItem(parent), m_active(false), m_pressed(false), m_enterDelay(0), m_trigger(Press), m_clipRadius(0.0), m_anchor(nullptr), m_opacityAnimator(nullptr)
+ : QQuickItem(parent),
+ m_active(false),
+ m_pressed(false),
+ m_waves(0),
+ m_enterDelay(0),
+ m_trigger(Press),
+ m_clipRadius(0.0),
+ m_anchor(nullptr)
{
- setOpacity(0.0);
setFlag(ItemHasContents);
}
@@ -219,19 +244,7 @@ void QQuickMaterialRipple::setActive(bool active)
return;
m_active = active;
-
- if (!m_opacityAnimator) {
- m_opacityAnimator = new QQuickOpacityAnimator(this);
- m_opacityAnimator->setTargetItem(this);
- }
- m_opacityAnimator->setDuration(active ? OPACITY_ENTER_DURATION_FAST : WAVE_OPACITY_DECAY_DURATION);
-
- const int time = m_opacityAnimator->currentTime();
- m_opacityAnimator->stop();
- m_opacityAnimator->setFrom(opacity());
- m_opacityAnimator->setTo(active ? 1.0 : 0.0);
- m_opacityAnimator->setCurrentTime(time);
- m_opacityAnimator->start();
+ update();
}
QColor QQuickMaterialRipple::color() const
@@ -275,8 +288,10 @@ void QQuickMaterialRipple::setPressed(bool pressed)
m_pressed = pressed;
- if (!isEnabled())
+ if (!isEnabled()) {
+ exitWave();
return;
+ }
if (pressed) {
if (m_trigger == Press)
@@ -336,15 +351,16 @@ void QQuickMaterialRipple::setAnchor(QQuickItem *item)
m_anchor = item;
}
+qreal QQuickMaterialRipple::diameter() const
+{
+ const qreal w = width();
+ const qreal h = height();
+ return qSqrt(w * w + h * h);
+}
+
void QQuickMaterialRipple::itemChange(ItemChange change, const ItemChangeData &data)
{
QQuickItem::itemChange(change, data);
-
- if (change == ItemChildRemovedChange) {
- QQuickMaterialRippleAnimator *animator = data.item->findChild<QQuickMaterialRippleAnimator *>();
- if (animator)
- m_rippleAnimators.removeOne(animator);
- }
}
QSGNode *QQuickMaterialRipple::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
@@ -358,35 +374,41 @@ QSGNode *QQuickMaterialRipple::updatePaintNode(QSGNode *oldNode, UpdatePaintNode
clipNode->update();
}
- const qreal w = width();
- const qreal h = height();
- const qreal sz = qSqrt(w * w + h * h);
+ QSGNode *container = oldNode;
+ if (!container)
+ container = new QSGNode;
- QSGTransformNode *transformNode = static_cast<QSGTransformNode *>(oldNode);
- if (!transformNode)
- transformNode = new QSGTransformNode;
-
- QSGInternalRectangleNode *rectNode = static_cast<QSGInternalRectangleNode *>(transformNode->firstChild());
- if (!rectNode) {
- rectNode = d->sceneGraphContext()->createInternalRectangleNode();
- rectNode->setAntialiasing(true);
- transformNode->appendChildNode(rectNode);
+ QQuickMaterialRippleBackgroundNode *backgroundNode = static_cast<QQuickMaterialRippleBackgroundNode *>(container->firstChild());
+ if (!backgroundNode) {
+ backgroundNode = new QQuickMaterialRippleBackgroundNode(this);
+ backgroundNode->setObjectName(objectName());
+ container->appendChildNode(backgroundNode);
+ }
+ backgroundNode->sync(this);
+
+ // enter new waves
+ int i = m_waves;
+ QQuickMaterialRippleWaveNode *enterNode = static_cast<QQuickMaterialRippleWaveNode *>(backgroundNode->nextSibling());
+ while (i-- > 0) {
+ if (!enterNode) {
+ enterNode = new QQuickMaterialRippleWaveNode(this);
+ container->appendChildNode(enterNode);
+ }
+ enterNode->sync(this);
+ enterNode = static_cast<QQuickMaterialRippleWaveNode *>(enterNode->nextSibling());
}
- QMatrix4x4 matrix;
- if (qFuzzyIsNull(m_clipRadius)) {
- matrix.translate((w - sz) / 2, (h - sz) / 2);
- rectNode->setRect(QRectF(0, 0, sz, sz));
- rectNode->setRadius(sz / 2);
- } else {
- rectNode->setRect(QRectF(0, 0, w, h));
- rectNode->setRadius(m_clipRadius);
+ // exit old waves
+ int j = container->childCount() - 1 - m_waves;
+ while (j-- > 0) {
+ QQuickMaterialRippleWaveNode *exitNode = static_cast<QQuickMaterialRippleWaveNode *>(backgroundNode->nextSibling());
+ if (exitNode) {
+ exitNode->exit();
+ exitNode->sync(this);
+ }
}
- transformNode->setMatrix(matrix);
- rectNode->setColor(m_color);
- rectNode->update();
- return transformNode;
+ return container;
}
void QQuickMaterialRipple::timerEvent(QTimerEvent *event)
@@ -410,23 +432,8 @@ void QQuickMaterialRipple::enterWave()
m_enterDelay = 0;
}
- const qreal w = width();
- const qreal h = height();
- const qreal sz = qSqrt(w * w + h * h);
-
- QQuickRectangle *wave = new QQuickRectangle(this);
- wave->setPosition(QPointF((w - sz) / 2, (h - sz) / 2));
- wave->setSize(QSizeF(sz, sz));
- wave->setRadius(sz / 2);
- wave->setColor(color());
- wave->setOpacity(0.0);
-
- QQuickMaterialRippleAnimator *animator = new QQuickMaterialRippleAnimator(anchorPoint(), boundingRect(), wave);
- animator->setDuration(qRound(1000.0 * qSqrt(sz / 2.0 / WAVE_TOUCH_DOWN_ACCELERATION)));
- animator->setTargetItem(wave);
- animator->setTo(sz);
- animator->start();
- m_rippleAnimators += animator;
+ ++m_waves;
+ update();
}
void QQuickMaterialRipple::exitWave()
@@ -436,16 +443,12 @@ void QQuickMaterialRipple::exitWave()
m_enterDelay = 0;
}
- for (QQuickMaterialRippleAnimator *animator : m_rippleAnimators) {
- if (animator->phase() == WaveEnter) {
- animator->stop(); // -> writeBack() -> setSize()
- if (QQuickItem *wave = animator->targetItem())
- animator->setFrom(wave->width());
- animator->setDuration(WAVE_OPACITY_DECAY_DURATION);
- animator->setPhase(WaveExit);
- animator->restart();
- }
+ if (m_waves > 0) {
+ --m_waves;
+ update();
}
}
QT_END_NAMESPACE
+
+#include "qquickmaterialripple.moc"
diff --git a/src/imports/controls/material/qquickmaterialripple_p.h b/src/imports/controls/material/qquickmaterialripple_p.h
index 8e511bbb..712697da 100644
--- a/src/imports/controls/material/qquickmaterialripple_p.h
+++ b/src/imports/controls/material/qquickmaterialripple_p.h
@@ -53,9 +53,6 @@
QT_BEGIN_NAMESPACE
-class QQuickOpacityAnimator;
-class QQuickMaterialRippleAnimator;
-
class QQuickMaterialRipple : public QQuickItem
{
Q_OBJECT
@@ -92,6 +89,8 @@ public:
QQuickItem *anchor() const;
void setAnchor(QQuickItem *anchor);
+ qreal diameter() const;
+
protected:
void itemChange(ItemChange change, const ItemChangeData &data) override;
QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) override;
@@ -104,13 +103,12 @@ protected:
private:
bool m_active;
bool m_pressed;
+ int m_waves;
int m_enterDelay;
Trigger m_trigger;
qreal m_clipRadius;
QColor m_color;
QQuickItem *m_anchor;
- QQuickOpacityAnimator *m_opacityAnimator;
- QVector<QQuickMaterialRippleAnimator *> m_rippleAnimators;
};
QT_END_NAMESPACE
diff --git a/src/imports/controls/material/qquickmaterialstyle_p.h b/src/imports/controls/material/qquickmaterialstyle_p.h
index 839a4863..bb494697 100644
--- a/src/imports/controls/material/qquickmaterialstyle_p.h
+++ b/src/imports/controls/material/qquickmaterialstyle_p.h
@@ -63,7 +63,6 @@ class QQuickMaterialStyle : public QQuickStyleAttached
Q_PROPERTY(QVariant background READ background WRITE setBackground RESET resetBackground NOTIFY backgroundChanged FINAL)
Q_PROPERTY(int elevation READ elevation WRITE setElevation RESET resetElevation NOTIFY elevationChanged FINAL)
-
Q_PROPERTY(QColor primaryColor READ primaryColor NOTIFY primaryChanged FINAL) // TODO: remove?
Q_PROPERTY(QColor accentColor READ accentColor NOTIFY accentChanged FINAL) // TODO: remove?
Q_PROPERTY(QColor backgroundColor READ backgroundColor NOTIFY backgroundChanged FINAL)
diff --git a/src/imports/controls/material/qtquickcontrols2materialstyleplugin.cpp b/src/imports/controls/material/qtquickcontrols2materialstyleplugin.cpp
index 94941b4c..0deb429c 100644
--- a/src/imports/controls/material/qtquickcontrols2materialstyleplugin.cpp
+++ b/src/imports/controls/material/qtquickcontrols2materialstyleplugin.cpp
@@ -38,8 +38,8 @@
#include "qquickmaterialstyle_p.h"
#include "qquickmaterialtheme_p.h"
-#include "qquickmaterialprogressring_p.h"
-#include "qquickmaterialprogressstrip_p.h"
+#include "qquickmaterialbusyindicator_p.h"
+#include "qquickmaterialprogressbar_p.h"
#include "qquickmaterialripple_p.h"
#include <QtQuickControls2/private/qquickstyleselector_p.h>
@@ -78,8 +78,8 @@ QtQuickControls2MaterialStylePlugin::QtQuickControls2MaterialStylePlugin(QObject
void QtQuickControls2MaterialStylePlugin::registerTypes(const char *uri)
{
+ qmlRegisterModule(uri, 2, QT_VERSION_MINOR - 7); // Qt 5.7->2.0, 5.8->2.1, 5.9->2.2...
qmlRegisterUncreatableType<QQuickMaterialStyle>(uri, 2, 0, "Material", tr("Material is an attached property"));
- qmlRegisterRevision<QQuickMaterialStyle, 1>(uri, 2, 1);
}
void QtQuickControls2MaterialStylePlugin::initializeEngine(QQmlEngine *engine, const char *uri)
@@ -89,15 +89,15 @@ void QtQuickControls2MaterialStylePlugin::initializeEngine(QQmlEngine *engine, c
engine->addImageProvider(name(), new QQuickColorImageProvider(QStringLiteral(":/qt-project.org/imports/QtQuick/Controls.2/Material/images")));
QByteArray import = QByteArray(uri) + ".impl";
+ qmlRegisterModule(import, 2, QT_VERSION_MINOR - 7); // Qt 5.7->2.0, 5.8->2.1, 5.9->2.2...
+
qmlRegisterType<QQuickPaddedRectangle>(import, 2, 0, "PaddedRectangle");
- qmlRegisterRevision<QQuickPaddedRectangle, 1>(import, 2, 1);
- qmlRegisterType<QQuickMaterialProgressRing>(import, 2, 0, "ProgressRing");
- qmlRegisterType<QQuickMaterialProgressStrip>(import, 2, 0, "ProgressStrip");
- qmlRegisterType<QQuickMaterialRingAnimator>(import, 2, 0, "RingAnimator");
+ qmlRegisterType<QQuickMaterialBusyIndicator>(import, 2, 0, "BusyIndicatorImpl");
+ qmlRegisterType<QQuickMaterialProgressBar>(import, 2, 0, "ProgressBarImpl");
qmlRegisterType<QQuickMaterialRipple>(import, 2, 0, "Ripple");
- qmlRegisterType<QQuickMaterialStripAnimator>(import, 2, 0, "StripAnimator");
qmlRegisterType(typeUrl(QStringLiteral("BoxShadow.qml")), import, 2, 0, "BoxShadow");
qmlRegisterType(typeUrl(QStringLiteral("CheckIndicator.qml")), import, 2, 0, "CheckIndicator");
+ qmlRegisterType(typeUrl(QStringLiteral("CursorDelegate.qml")), import, 2, 0, "CursorDelegate");
qmlRegisterType(typeUrl(QStringLiteral("ElevationEffect.qml")), import, 2, 0, "ElevationEffect");
qmlRegisterType(typeUrl(QStringLiteral("RectangularGlow.qml")), import, 2, 0, "RectangularGlow");
qmlRegisterType(typeUrl(QStringLiteral("SliderHandle.qml")), import, 2, 0, "SliderHandle");
diff --git a/src/imports/controls/qmldir b/src/imports/controls/qmldir
index 8e5cca4f..32f0d20d 100644
--- a/src/imports/controls/qmldir
+++ b/src/imports/controls/qmldir
@@ -1,5 +1,5 @@
module QtQuick.Controls
plugin qtquickcontrols2plugin
classname QtQuickControls2Plugin
-depends QtQuick.Templates 2.1
+depends QtQuick.Templates 2.2
designersupported
diff --git a/src/imports/controls/qquickbusyindicatorring.cpp b/src/imports/controls/qquickbusyindicatorring.cpp
deleted file mode 100644
index 55d48b68..00000000
--- a/src/imports/controls/qquickbusyindicatorring.cpp
+++ /dev/null
@@ -1,231 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL3$
-** 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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qquickbusyindicatorring_p.h"
-
-#include <QtCore/qset.h>
-#include <QtGui/qpainter.h>
-#include <QtQuick/private/qquickitem_p.h>
-#include <QtQuick/qsgnode.h>
-#include <QtQuick/qquickwindow.h>
-#include <QtQuick/qsgrectanglenode.h>
-
-QT_BEGIN_NAMESPACE
-
-class QQuickBusyIndicatorAnimatorJob : public QQuickAnimatorJob
-{
-public:
- QQuickBusyIndicatorAnimatorJob();
- ~QQuickBusyIndicatorAnimatorJob();
-
- void initialize(QQuickAnimatorController *controller) override;
- void updateCurrentTime(int time) override;
- void writeBack() override;
- void nodeWasDestroyed() override;
- void afterNodeSync() override;
-
-private:
- QSGNode *m_node;
-};
-
-static const int circles = 10;
-static const int animationDuration = 100 * circles * 2;
-
-QQuickBusyIndicatorRing::QQuickBusyIndicatorRing(QQuickItem *parent) :
- QQuickItem(parent)
-{
- setFlag(QQuickItem::ItemHasContents);
- setImplicitWidth(116);
- setImplicitHeight(116);
-}
-
-QQuickBusyIndicatorRing::~QQuickBusyIndicatorRing()
-{
-}
-
-static QPointF moveBy(const QPointF &pos, qreal rotation, qreal distance)
-{
- return pos - QTransform().rotate(rotation).map(QPointF(0, distance));
-}
-
-QSGNode *QQuickBusyIndicatorRing::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *)
-{
- QQuickItemPrivate *d = QQuickItemPrivate::get(this);
-
- if (!oldNode) {
- oldNode = window()->createRectangleNode();
- static_cast<QSGRectangleNode *>(oldNode)->setColor(Qt::transparent);
- }
- static_cast<QSGRectangleNode *>(oldNode)->setRect(boundingRect());
-
- QSGTransformNode *rootTransformNode = static_cast<QSGTransformNode *>(oldNode->firstChild());
- if (!rootTransformNode) {
- rootTransformNode = new QSGTransformNode;
- oldNode->appendChildNode(rootTransformNode);
- }
- Q_ASSERT(rootTransformNode->type() == QSGNode::TransformNodeType);
-
- const qreal w = width();
- const qreal h = height();
- const qreal sz = qMin(w, h);
- const qreal dx = (w - sz) / 2;
- const qreal dy = (h - sz) / 2;
- const int circleRadius = sz / 12;
- const QColor color(0x35, 0x36, 0x37);
-
- QSGTransformNode *transformNode = static_cast<QSGTransformNode *>(rootTransformNode->firstChild());
- for (int i = 0; i < circles; ++i) {
- if (!transformNode) {
- transformNode = new QSGTransformNode;
- rootTransformNode->appendChildNode(transformNode);
-
- QSGOpacityNode *opacityNode = new QSGOpacityNode;
- transformNode->appendChildNode(opacityNode);
-
- QSGInternalRectangleNode *rectNode = d->sceneGraphContext()->createInternalRectangleNode();
- rectNode->setAntialiasing(true);
- rectNode->setColor(color);
- rectNode->setPenColor(color);
- opacityNode->appendChildNode(rectNode);
- }
-
- QSGNode *opacityNode = transformNode->firstChild();
- Q_ASSERT(opacityNode->type() == QSGNode::OpacityNodeType);
-
- QSGInternalRectangleNode *rectNode = static_cast<QSGInternalRectangleNode *>(opacityNode->firstChild());
- Q_ASSERT(rectNode->type() == QSGNode::GeometryNodeType);
-
- QPointF pos = QPointF(sz / 2 - circleRadius, sz / 2 - circleRadius);
- pos = moveBy(pos, 360 / circles * i, sz / 2 - circleRadius);
-
- QMatrix4x4 m;
- m.translate(dx + pos.x(), dy + pos.y());
- transformNode->setMatrix(m);
-
- rectNode->setRect(QRectF(QPointF(), QSizeF(circleRadius * 2, circleRadius * 2)));
- rectNode->setRadius(circleRadius);
- rectNode->update();
-
- transformNode = static_cast<QSGTransformNode *>(transformNode->nextSibling());
- }
-
- return oldNode;
-}
-
-QQuickBusyIndicatorAnimator::QQuickBusyIndicatorAnimator(QObject *parent) :
- QQuickAnimator(parent)
-{
- setDuration(animationDuration);
- setLoops(QQuickAnimator::Infinite);
-}
-
-QString QQuickBusyIndicatorAnimator::propertyName() const
-{
- return QString();
-}
-
-QQuickAnimatorJob *QQuickBusyIndicatorAnimator::createJob() const
-{
- return new QQuickBusyIndicatorAnimatorJob;
-}
-
-QQuickBusyIndicatorAnimatorJob::QQuickBusyIndicatorAnimatorJob() : m_node(nullptr)
-{
-}
-
-QQuickBusyIndicatorAnimatorJob::~QQuickBusyIndicatorAnimatorJob()
-{
-}
-
-void QQuickBusyIndicatorAnimatorJob::initialize(QQuickAnimatorController *controller)
-{
- QQuickAnimatorJob::initialize(controller);
- m_node = QQuickItemPrivate::get(m_target)->childContainerNode();
-}
-
-void QQuickBusyIndicatorAnimatorJob::updateCurrentTime(int time)
-{
- if (!m_node)
- return;
-
- QSGRectangleNode *rootRectNode = static_cast<QSGRectangleNode *>(m_node->firstChild());
- if (!rootRectNode)
- return;
-
- Q_ASSERT(rootRectNode->type() == QSGNode::GeometryNodeType);
-
- QSGTransformNode *rootTransformNode = static_cast<QSGTransformNode*>(rootRectNode->firstChild());
- Q_ASSERT(rootTransformNode->type() == QSGNode::TransformNodeType);
-
- const qreal percentageComplete = time / qreal(animationDuration);
- const qreal firstPhaseProgress = percentageComplete <= 0.5 ? percentageComplete * 2 : 0;
- const qreal secondPhaseProgress = percentageComplete > 0.5 ? (percentageComplete - 0.5) * 2 : 0;
-
- QSGTransformNode *transformNode = static_cast<QSGTransformNode*>(rootTransformNode->firstChild());
- const QColor color(0x35, 0x36, 0x37);
- const QColor transparent(Qt::transparent);
- Q_ASSERT(transformNode->type() == QSGNode::TransformNodeType);
- for (int i = 0; i < circles; ++i) {
- QSGOpacityNode *opacityNode = static_cast<QSGOpacityNode*>(transformNode->firstChild());
- Q_ASSERT(opacityNode->type() == QSGNode::OpacityNodeType);
-
- QSGInternalRectangleNode *rectNode = static_cast<QSGInternalRectangleNode*>(opacityNode->firstChild());
- Q_ASSERT(rectNode->type() == QSGNode::GeometryNodeType);
-
- const bool fill = (firstPhaseProgress > qreal(i) / circles) || (secondPhaseProgress > 0 && secondPhaseProgress < qreal(i) / circles);
- rectNode->setPenWidth(fill ? 0 : 1);
- rectNode->setColor(fill ? color : transparent);
- rectNode->update();
-
- transformNode = static_cast<QSGTransformNode*>(transformNode->nextSibling());
- }
-}
-
-void QQuickBusyIndicatorAnimatorJob::writeBack()
-{
-}
-
-void QQuickBusyIndicatorAnimatorJob::nodeWasDestroyed()
-{
- m_node = nullptr;
-}
-
-void QQuickBusyIndicatorAnimatorJob::afterNodeSync()
-{
- m_node = QQuickItemPrivate::get(m_target)->childContainerNode();
-}
-
-QT_END_NAMESPACE
diff --git a/src/imports/controls/qquickdefaultbusyindicator.cpp b/src/imports/controls/qquickdefaultbusyindicator.cpp
new file mode 100644
index 00000000..90ef5ff7
--- /dev/null
+++ b/src/imports/controls/qquickdefaultbusyindicator.cpp
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickdefaultbusyindicator_p.h"
+
+#include <QtQuick/private/qquickitem_p.h>
+#include <QtQuick/private/qsgadaptationlayer_p.h>
+#include <QtQuickControls2/private/qquickanimatednode_p.h>
+
+QT_BEGIN_NAMESPACE
+
+static const int CircleCount = 10;
+static const int TotalDuration = 100 * CircleCount * 2;
+static const QRgb TransparentColor = 0x00000000;
+static const QRgb FillColor = 0xFF353637;
+
+static QPointF moveCircle(const QPointF &pos, qreal rotation, qreal distance)
+{
+ return pos - QTransform().rotate(rotation).map(QPointF(0, distance));
+}
+
+class QQuickDefaultBusyIndicatorNode : public QQuickAnimatedNode
+{
+public:
+ QQuickDefaultBusyIndicatorNode(QQuickDefaultBusyIndicator *item);
+
+ void updateCurrentTime(int time) override;
+ void sync(QQuickItem *item) override;
+};
+
+QQuickDefaultBusyIndicatorNode::QQuickDefaultBusyIndicatorNode(QQuickDefaultBusyIndicator *item)
+ : QQuickAnimatedNode(item)
+{
+ setLoopCount(Infinite);
+ setDuration(TotalDuration);
+ setCurrentTime(item->elapsed());
+
+ for (int i = 0; i < CircleCount; ++i) {
+ QSGTransformNode *transformNode = new QSGTransformNode;
+ appendChildNode(transformNode);
+
+ QQuickItemPrivate *d = QQuickItemPrivate::get(item);
+ QSGInternalRectangleNode *rectNode = d->sceneGraphContext()->createInternalRectangleNode();
+ rectNode->setAntialiasing(true);
+ transformNode->appendChildNode(rectNode);
+ }
+}
+
+void QQuickDefaultBusyIndicatorNode::updateCurrentTime(int time)
+{
+ const qreal percentageComplete = time / qreal(TotalDuration);
+ const qreal firstPhaseProgress = percentageComplete <= 0.5 ? percentageComplete * 2 : 0;
+ const qreal secondPhaseProgress = percentageComplete > 0.5 ? (percentageComplete - 0.5) * 2 : 0;
+
+ QSGTransformNode *transformNode = static_cast<QSGTransformNode*>(firstChild());
+ Q_ASSERT(transformNode->type() == QSGNode::TransformNodeType);
+ for (int i = 0; i < CircleCount; ++i) {
+ QSGInternalRectangleNode *rectNode = static_cast<QSGInternalRectangleNode*>(transformNode->firstChild());
+ Q_ASSERT(rectNode->type() == QSGNode::GeometryNodeType);
+
+ const bool fill = (firstPhaseProgress > qreal(i) / CircleCount) || (secondPhaseProgress > 0 && secondPhaseProgress < qreal(i) / CircleCount);
+ rectNode->setColor(QColor::fromRgba(fill ? FillColor : TransparentColor));
+ rectNode->setPenWidth(fill ? 0 : 1);
+ rectNode->update();
+
+ transformNode = static_cast<QSGTransformNode*>(transformNode->nextSibling());
+ }
+}
+
+void QQuickDefaultBusyIndicatorNode::sync(QQuickItem *item)
+{
+ const qreal w = item->width();
+ const qreal h = item->height();
+ const qreal sz = qMin(w, h);
+ const qreal dx = (w - sz) / 2;
+ const qreal dy = (h - sz) / 2;
+ const int circleRadius = sz / 12;
+
+ QSGTransformNode *transformNode = static_cast<QSGTransformNode *>(firstChild());
+ for (int i = 0; i < CircleCount; ++i) {
+ Q_ASSERT(transformNode->type() == QSGNode::TransformNodeType);
+
+ QSGInternalRectangleNode *rectNode = static_cast<QSGInternalRectangleNode *>(transformNode->firstChild());
+ Q_ASSERT(rectNode->type() == QSGNode::GeometryNodeType);
+
+ QPointF pos = QPointF(sz / 2 - circleRadius, sz / 2 - circleRadius);
+ pos = moveCircle(pos, 360 / CircleCount * i, sz / 2 - circleRadius);
+
+ QMatrix4x4 m;
+ m.translate(dx + pos.x(), dy + pos.y());
+ transformNode->setMatrix(m);
+
+ rectNode->setRect(QRectF(QPointF(), QSizeF(circleRadius * 2, circleRadius * 2)));
+ rectNode->setRadius(circleRadius);
+
+ transformNode = static_cast<QSGTransformNode *>(transformNode->nextSibling());
+ }
+}
+
+QQuickDefaultBusyIndicator::QQuickDefaultBusyIndicator(QQuickItem *parent) :
+ QQuickItem(parent), m_elapsed(0)
+{
+ setFlag(ItemHasContents);
+}
+
+int QQuickDefaultBusyIndicator::elapsed() const
+{
+ return m_elapsed;
+}
+
+void QQuickDefaultBusyIndicator::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data)
+{
+ QQuickItem::itemChange(change, data);
+ if (change == ItemVisibleHasChanged)
+ update();
+}
+
+QSGNode *QQuickDefaultBusyIndicator::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *)
+{
+ QQuickDefaultBusyIndicatorNode *node = static_cast<QQuickDefaultBusyIndicatorNode *>(oldNode);
+ if (isVisible() && width() > 0 && height() > 0) {
+ if (!node) {
+ node = new QQuickDefaultBusyIndicatorNode(this);
+ node->start();
+ }
+ node->sync(this);
+ } else {
+ m_elapsed = node ? node->currentTime() : 0;
+ delete node;
+ node = nullptr;
+ }
+ return node;
+}
+
+QT_END_NAMESPACE
diff --git a/src/imports/controls/qquickbusyindicatorring_p.h b/src/imports/controls/qquickdefaultbusyindicator_p.h
index ee30909e..7daeabd1 100644
--- a/src/imports/controls/qquickbusyindicatorring_p.h
+++ b/src/imports/controls/qquickdefaultbusyindicator_p.h
@@ -34,8 +34,8 @@
**
****************************************************************************/
-#ifndef QQUICKBUSYINDICATORRING_P_H
-#define QQUICKBUSYINDICATORRING_P_H
+#ifndef QQUICKDEFAULTBUSYINDICATOR_P_H
+#define QQUICKDEFAULTBUSYINDICATOR_P_H
//
// W A R N I N G
@@ -49,34 +49,28 @@
//
#include <QtQuick/qquickitem.h>
-#include <QtQuick/private/qquickanimatorjob_p.h>
QT_BEGIN_NAMESPACE
-class QQuickBusyIndicatorRing : public QQuickItem
+class QQuickDefaultBusyIndicator : public QQuickItem
{
Q_OBJECT
public:
- explicit QQuickBusyIndicatorRing(QQuickItem *parent = nullptr);
- ~QQuickBusyIndicatorRing();
+ explicit QQuickDefaultBusyIndicator(QQuickItem *parent = nullptr);
+
+ int elapsed() const;
protected:
+ void itemChange(ItemChange change, const ItemChangeData &data) override;
QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) override;
-};
-
-class QQuickBusyIndicatorAnimator : public QQuickAnimator
-{
-public:
- QQuickBusyIndicatorAnimator(QObject *parent = nullptr);
-protected:
- QString propertyName() const override;
- QQuickAnimatorJob *createJob() const override;
+private:
+ int m_elapsed;
};
QT_END_NAMESPACE
-QML_DECLARE_TYPE(QQuickBusyIndicatorRing)
+QML_DECLARE_TYPE(QQuickDefaultBusyIndicator)
-#endif // QQUICKBUSYINDICATORRING_P_H
+#endif // QQUICKDEFAULTBUSYINDICATOR_P_H
diff --git a/src/imports/controls/qquickdefaultprogressbar.cpp b/src/imports/controls/qquickdefaultprogressbar.cpp
new file mode 100644
index 00000000..a91b7d3b
--- /dev/null
+++ b/src/imports/controls/qquickdefaultprogressbar.cpp
@@ -0,0 +1,272 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickdefaultprogressbar_p.h"
+
+#include <QtCore/qeasingcurve.h>
+#include <QtQuick/private/qquickitem_p.h>
+#include <QtQuick/private/qsgadaptationlayer_p.h>
+#include <QtQuickControls2/private/qquickanimatednode_p.h>
+
+QT_BEGIN_NAMESPACE
+
+static const int Blocks = 4;
+static const int BlockWidth = 16;
+static const int BlockRestingSpacing = 4;
+static const int BlockMovingSpacing = 48;
+static const int BlockSpan = Blocks * (BlockWidth + BlockRestingSpacing) - BlockRestingSpacing;
+static const int TotalDuration = 4000;
+static const int SecondPhaseStart = TotalDuration * 0.4;
+static const int ThirdPhaseStart = TotalDuration * 0.6;
+static const QRgb FillColor = 0x353637;
+
+static inline qreal blockStartX(int blockIndex)
+{
+ return ((blockIndex + 1) * -BlockWidth) - (blockIndex * BlockMovingSpacing);
+}
+
+static inline qreal blockRestX(int blockIndex, qreal availableWidth)
+{
+ const qreal spanRightEdgePos = availableWidth / 2 + BlockSpan / 2;
+ return spanRightEdgePos - (blockIndex + 1) * BlockWidth - (blockIndex * BlockRestingSpacing);
+}
+
+static inline qreal blockEndX(int blockIndex, qreal availableWidth)
+{
+ return availableWidth - blockStartX(Blocks - 1 - blockIndex) - BlockWidth;
+}
+
+class QQuickDefaultProgressBarNode : public QQuickAnimatedNode
+{
+public:
+ QQuickDefaultProgressBarNode(QQuickDefaultProgressBar *item);
+
+ void updateCurrentTime(int time) override;
+ void sync(QQuickItem *item) override;
+
+private:
+ bool m_indeterminate;
+ qreal m_pixelsPerSecond;
+};
+
+QQuickDefaultProgressBarNode::QQuickDefaultProgressBarNode(QQuickDefaultProgressBar *item)
+ : QQuickAnimatedNode(item),
+ m_indeterminate(false),
+ m_pixelsPerSecond(item->width())
+{
+ setLoopCount(Infinite);
+ setDuration(TotalDuration);
+}
+
+void QQuickDefaultProgressBarNode::updateCurrentTime(int time)
+{
+ QSGTransformNode *transformNode = static_cast<QSGTransformNode*>(firstChild());
+ for (int i = 0; i < Blocks; ++i) {
+ Q_ASSERT(transformNode->type() == QSGNode::TransformNodeType);
+
+ QMatrix4x4 m;
+ const qreal restX = blockRestX(i, m_pixelsPerSecond);
+ const qreal timeInSeconds = time / 1000.0;
+
+ if (time < SecondPhaseStart) {
+ // Move into the resting position for the first phase.
+ QEasingCurve easingCurve(QEasingCurve::InQuad);
+ const qreal easedCompletion = easingCurve.valueForProgress(time / qreal(SecondPhaseStart));
+ const qreal distance = m_pixelsPerSecond * (easedCompletion * (SecondPhaseStart / 1000.0));
+ const qreal position = blockStartX(i) + distance;
+ const qreal destination = restX;
+ m.translate(qMin(position, destination), 0);
+ } else if (time < ThirdPhaseStart) {
+ // Stay in the same position for the second phase.
+ m.translate(restX, 0);
+ } else {
+ // Move out of view for the third phase.
+ const int thirdPhaseSubKickoff = (BlockMovingSpacing / m_pixelsPerSecond) * 1000;
+ const int subphase = (time - ThirdPhaseStart) / thirdPhaseSubKickoff;
+ // If we're not at this subphase yet, don't try to animate movement,
+ // because it will be incorrect.
+ if (subphase < i)
+ return;
+
+ const qreal timeSinceSecondPhase = timeInSeconds - (ThirdPhaseStart / 1000.0);
+ // We only want to start keeping track of time once our subphase has started,
+ // otherwise we move too much because we account for time that has already elapsed.
+ // For example, if we were 60 milliseconds into the third subphase:
+ //
+ // 0 ..... 1 ..... 2 ...
+ // 100 100 60
+ //
+ // i == 0, timeSinceOurKickoff == 260
+ // i == 1, timeSinceOurKickoff == 160
+ // i == 2, timeSinceOurKickoff == 60
+ const qreal timeSinceOurKickoff = timeSinceSecondPhase - (thirdPhaseSubKickoff / 1000.0 * i);
+ const qreal position = restX + (m_pixelsPerSecond * (timeSinceOurKickoff));
+ const qreal destination = blockEndX(i, m_pixelsPerSecond);
+ m.translate(qMin(position, destination), 0);
+ }
+
+ transformNode->setMatrix(m);
+
+ transformNode = static_cast<QSGTransformNode*>(transformNode->nextSibling());
+ }
+}
+
+void QQuickDefaultProgressBarNode::sync(QQuickItem *item)
+{
+ QQuickDefaultProgressBar *bar = static_cast<QQuickDefaultProgressBar *>(item);
+ if (m_indeterminate != bar->isIndeterminate()) {
+ m_indeterminate = bar->isIndeterminate();
+ if (m_indeterminate)
+ start();
+ else
+ stop();
+ }
+ m_pixelsPerSecond = item->width();
+
+ QQuickItemPrivate *d = QQuickItemPrivate::get(item);
+
+ QMatrix4x4 m;
+ m.translate(0, (item->height() - item->implicitHeight()) / 2);
+ setMatrix(m);
+
+ if (m_indeterminate) {
+ if (childCount() != Blocks) {
+ // This was previously a regular progress bar; remove the old nodes.
+ removeAllChildNodes();
+ }
+
+ QSGTransformNode *transformNode = static_cast<QSGTransformNode*>(firstChild());
+ for (int i = 0; i < Blocks; ++i) {
+ if (!transformNode) {
+ transformNode = new QSGTransformNode;
+ appendChildNode(transformNode);
+ }
+
+ QSGInternalRectangleNode *rectNode = static_cast<QSGInternalRectangleNode*>(transformNode->firstChild());
+ if (!rectNode) {
+ rectNode = d->sceneGraphContext()->createInternalRectangleNode();
+ rectNode->setColor(FillColor);
+ transformNode->appendChildNode(rectNode);
+ }
+
+ QMatrix4x4 m;
+ m.translate(blockStartX(i), 0);
+ transformNode->setMatrix(m);
+
+ rectNode->setRect(QRectF(QPointF(0, 0), QSizeF(BlockWidth, item->implicitHeight())));
+ rectNode->update();
+
+ transformNode = static_cast<QSGTransformNode *>(transformNode->nextSibling());
+ }
+ } else {
+ if (childCount() > 1) {
+ // This was previously an indeterminate progress bar; remove the old nodes.
+ removeAllChildNodes();
+ }
+
+ QSGInternalRectangleNode *rectNode = static_cast<QSGInternalRectangleNode *>(firstChild());
+ if (!rectNode) {
+ rectNode = d->sceneGraphContext()->createInternalRectangleNode();
+ rectNode->setColor(FillColor);
+ appendChildNode(rectNode);
+ }
+
+ rectNode->setRect(QRectF(QPointF(0, 0), QSizeF(bar->progress() * item->width(), item->implicitHeight())));
+ rectNode->update();
+ }
+}
+
+QQuickDefaultProgressBar::QQuickDefaultProgressBar(QQuickItem *parent) :
+ QQuickItem(parent),
+ m_progress(0),
+ m_indeterminate(false)
+{
+ setFlag(ItemHasContents);
+}
+
+qreal QQuickDefaultProgressBar::progress() const
+{
+ return m_progress;
+}
+
+void QQuickDefaultProgressBar::setProgress(qreal progress)
+{
+ if (progress == m_progress)
+ return;
+
+ m_progress = progress;
+ update();
+ emit progressChanged();
+}
+
+bool QQuickDefaultProgressBar::isIndeterminate() const
+{
+ return m_indeterminate;
+}
+
+void QQuickDefaultProgressBar::setIndeterminate(bool indeterminate)
+{
+ if (indeterminate == m_indeterminate)
+ return;
+
+ m_indeterminate = indeterminate;
+ setClip(m_indeterminate);
+ update();
+ emit indeterminateChanged();
+}
+
+void QQuickDefaultProgressBar::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data)
+{
+ QQuickItem::itemChange(change, data);
+ if (change == ItemVisibleHasChanged)
+ update();
+}
+
+QSGNode *QQuickDefaultProgressBar::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *)
+{
+ QQuickDefaultProgressBarNode *node = static_cast<QQuickDefaultProgressBarNode *>(oldNode);
+ if (isVisible() && width() > 0 && height() > 0) {
+ if (!node)
+ node = new QQuickDefaultProgressBarNode(this);
+ node->sync(this);
+ } else {
+ delete node;
+ node = nullptr;
+ }
+ return node;
+}
+
+QT_END_NAMESPACE
diff --git a/src/imports/controls/qquickprogressstrip_p.h b/src/imports/controls/qquickdefaultprogressbar_p.h
index 62d775fb..4fb9ae0b 100644
--- a/src/imports/controls/qquickprogressstrip_p.h
+++ b/src/imports/controls/qquickdefaultprogressbar_p.h
@@ -34,8 +34,8 @@
**
****************************************************************************/
-#ifndef QQUICKPROGRESSSTRIP_P_H
-#define QQUICKPROGRESSSTRIP_P_H
+#ifndef QQUICKDEFAULTPROGRESSBAR_P_H
+#define QQUICKDEFAULTPROGRESSBAR_P_H
//
// W A R N I N G
@@ -49,19 +49,17 @@
//
#include <QtQuick/qquickitem.h>
-#include <QtQuick/private/qquickanimatorjob_p.h>
QT_BEGIN_NAMESPACE
-class QQuickProgressStrip : public QQuickItem
+class QQuickDefaultProgressBar : public QQuickItem
{
Q_OBJECT
Q_PROPERTY(bool indeterminate READ isIndeterminate WRITE setIndeterminate NOTIFY indeterminateChanged FINAL)
Q_PROPERTY(qreal progress READ progress WRITE setProgress NOTIFY progressChanged FINAL)
public:
- explicit QQuickProgressStrip(QQuickItem *parent = nullptr);
- ~QQuickProgressStrip();
+ explicit QQuickDefaultProgressBar(QQuickItem *parent = nullptr);
bool isIndeterminate() const;
void setIndeterminate(bool indeterminate);
@@ -74,6 +72,7 @@ Q_SIGNALS:
void indeterminateChanged();
protected:
+ void itemChange(ItemChange change, const ItemChangeData &data) override;
QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) override;
private:
@@ -81,16 +80,8 @@ private:
bool m_indeterminate;
};
-class QQuickProgressAnimator : public QQuickAnimator
-{
-public:
- QQuickProgressAnimator(QObject *parent = nullptr);
-
-protected:
- QString propertyName() const override;
- QQuickAnimatorJob *createJob() const override;
-};
-
QT_END_NAMESPACE
-#endif // QQUICKPROGRESSSTRIP_P_H
+QML_DECLARE_TYPE(QQuickDefaultProgressBar)
+
+#endif // QQUICKDEFAULTPROGRESSBAR_P_H
diff --git a/src/imports/controls/qquickprogressstrip.cpp b/src/imports/controls/qquickprogressstrip.cpp
deleted file mode 100644
index b5656b96..00000000
--- a/src/imports/controls/qquickprogressstrip.cpp
+++ /dev/null
@@ -1,315 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL3$
-** 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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qquickprogressstrip_p.h"
-
-#include <QtQuick/private/qquickitem_p.h>
-#include <QtQuick/qsgrectanglenode.h>
-
-QT_BEGIN_NAMESPACE
-
-class QQuickProgressAnimatorJob : public QQuickAnimatorJob
-{
-public:
- QQuickProgressAnimatorJob();
- ~QQuickProgressAnimatorJob();
-
- void initialize(QQuickAnimatorController *controller) override;
- void afterNodeSync() override;
- void updateCurrentTime(int time) override;
- void writeBack() override;
- void nodeWasDestroyed() override;
-
-private:
- QSGNode *m_node;
-};
-
-QQuickProgressStrip::QQuickProgressStrip(QQuickItem *parent) :
- QQuickItem(parent),
- m_progress(0),
- m_indeterminate(false)
-{
- setFlag(QQuickItem::ItemHasContents);
-}
-
-QQuickProgressStrip::~QQuickProgressStrip()
-{
-}
-
-qreal QQuickProgressStrip::progress() const
-{
- return m_progress;
-}
-
-void QQuickProgressStrip::setProgress(qreal progress)
-{
- if (progress == m_progress)
- return;
-
- m_progress = progress;
- update();
- emit progressChanged();
-}
-
-bool QQuickProgressStrip::isIndeterminate() const
-{
- return m_indeterminate;
-}
-
-void QQuickProgressStrip::setIndeterminate(bool indeterminate)
-{
- if (indeterminate == m_indeterminate)
- return;
-
- m_indeterminate = indeterminate;
- setClip(m_indeterminate);
- update();
- emit indeterminateChanged();
-}
-
-static const int blocks = 4;
-static const int blockWidth = 16;
-static const int blockRestingSpacing = 4;
-static const int blockMovingSpacing = 48;
-static const int blockSpan = blocks * (blockWidth + blockRestingSpacing) - blockRestingSpacing;
-static const int animationDuration = 4000;
-static const int secondPhaseStart = animationDuration * 0.4;
-static const int thirdPhaseStart = animationDuration * 0.6;
-
-static inline qreal blockStartX(int blockIndex)
-{
- return ((blockIndex + 1) * -blockWidth) - (blockIndex * blockMovingSpacing);
-}
-
-static inline qreal blockRestX(int blockIndex, qreal availableWidth)
-{
- const qreal spanRightEdgePos = availableWidth / 2 + blockSpan / 2;
- return spanRightEdgePos - (blockIndex + 1) * blockWidth - (blockIndex * blockRestingSpacing);
-}
-
-static inline qreal blockEndX(int blockIndex, qreal availableWidth)
-{
- return availableWidth - blockStartX(blocks - 1 - blockIndex) - blockWidth;
-}
-
-QSGNode *QQuickProgressStrip::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *)
-{
- QQuickItemPrivate *d = QQuickItemPrivate::get(this);
-
- if (!oldNode) {
- oldNode = window()->createRectangleNode();
- static_cast<QSGRectangleNode *>(oldNode)->setColor(Qt::transparent);
- }
- static_cast<QSGRectangleNode *>(oldNode)->setRect(boundingRect());
-
- QSGTransformNode *rootTransformNode = static_cast<QSGTransformNode *>(oldNode->firstChild());
- if (!rootTransformNode) {
- rootTransformNode = new QSGTransformNode;
- oldNode->appendChildNode(rootTransformNode);
- }
- Q_ASSERT(rootTransformNode->type() == QSGNode::TransformNodeType);
-
- const qreal y = (height() - implicitHeight()) / 2;
- const QColor color(0x35, 0x36, 0x37);
- if (m_indeterminate) {
- if (rootTransformNode->childCount() != blocks) {
- // This was previously a regular progress bar; remove the old nodes.
- rootTransformNode->removeAllChildNodes();
- }
-
- QSGTransformNode *transformNode = static_cast<QSGTransformNode*>(rootTransformNode->firstChild());
- for (int i = 0; i < blocks; ++i) {
- if (!transformNode) {
- transformNode = new QSGTransformNode;
- rootTransformNode->appendChildNode(transformNode);
- }
-
- QSGInternalRectangleNode *rectNode = static_cast<QSGInternalRectangleNode*>(transformNode->firstChild());
- if (!rectNode) {
- rectNode = d->sceneGraphContext()->createInternalRectangleNode();
- rectNode->setColor(color);
- transformNode->appendChildNode(rectNode);
- }
-
- QMatrix4x4 m;
- m.translate(blockStartX(i), 0);
- transformNode->setMatrix(m);
-
- rectNode->setRect(QRectF(QPointF(0, y), QSizeF(blockWidth, implicitHeight())));
- rectNode->update();
-
- transformNode = static_cast<QSGTransformNode *>(transformNode->nextSibling());
- }
- } else {
- if (rootTransformNode->childCount() > 1) {
- // This was previously an indeterminate progress bar; remove the old nodes.
- rootTransformNode->removeAllChildNodes();
- }
-
- QSGInternalRectangleNode *rectNode = static_cast<QSGInternalRectangleNode *>(rootTransformNode->firstChild());
- if (!rectNode) {
- rectNode = d->sceneGraphContext()->createInternalRectangleNode();
- rectNode->setColor(color);
- rootTransformNode->appendChildNode(rectNode);
- }
-
- rectNode->setRect(QRectF(QPointF(0, y), QSizeF(m_progress * width(), implicitHeight())));
- rectNode->update();
- }
-
- return oldNode;
-}
-
-QQuickProgressAnimator::QQuickProgressAnimator(QObject *parent) :
- QQuickAnimator(parent)
-{
- setDuration(animationDuration);
- setLoops(QQuickAnimator::Infinite);
-}
-
-QString QQuickProgressAnimator::propertyName() const
-{
- return QString();
-}
-
-QQuickAnimatorJob *QQuickProgressAnimator::createJob() const
-{
- return new QQuickProgressAnimatorJob;
-}
-
-QQuickProgressAnimatorJob::QQuickProgressAnimatorJob() :
- m_node(nullptr)
-{
-}
-
-QQuickProgressAnimatorJob::~QQuickProgressAnimatorJob()
-{
-}
-
-void QQuickProgressAnimatorJob::initialize(QQuickAnimatorController *controller)
-{
- QQuickAnimatorJob::initialize(controller);
- m_node = QQuickItemPrivate::get(m_target)->childContainerNode();
-}
-
-void QQuickProgressAnimatorJob::afterNodeSync()
-{
- m_node = QQuickItemPrivate::get(m_target)->childContainerNode();
-}
-
-void QQuickProgressAnimatorJob::updateCurrentTime(int time)
-{
- if (!m_node)
- return;
-
- QSGRectangleNode *rootRectNode = static_cast<QSGRectangleNode *>(m_node->firstChild());
- if (!rootRectNode)
- return;
- Q_ASSERT(rootRectNode->type() == QSGNode::GeometryNodeType);
-
- QSGTransformNode *rootTransformNode = static_cast<QSGTransformNode*>(rootRectNode->firstChild());
- Q_ASSERT(rootTransformNode->type() == QSGNode::TransformNodeType);
-
- QSGTransformNode *transformNode = static_cast<QSGTransformNode*>(rootTransformNode->firstChild());
- // This function can be called without the relevant nodes having been created yet,
- // which can happen if you set indeterminate to true at runtime.
- if (!transformNode || transformNode->type() != QSGNode::TransformNodeType)
- return;
-
- const qreal pixelsPerSecond = rootRectNode->rect().width();
-
- for (int i = 0; i < blocks; ++i) {
- QSGInternalRectangleNode *rectNode = static_cast<QSGInternalRectangleNode*>(transformNode->firstChild());
- Q_ASSERT(rectNode->type() == QSGNode::GeometryNodeType);
-
- QMatrix4x4 m;
- const qreal restX = blockRestX(i, rootRectNode->rect().width());
- const qreal timeInSeconds = time / 1000.0;
-
- if (time < secondPhaseStart) {
- // Move into the resting position for the first phase.
- QEasingCurve easingCurve(QEasingCurve::InQuad);
- const qreal easedCompletion = easingCurve.valueForProgress(time / qreal(secondPhaseStart));
- const qreal distance = pixelsPerSecond * (easedCompletion * (secondPhaseStart / 1000.0));
- const qreal position = blockStartX(i) + distance;
- const qreal destination = restX;
- m.translate(qMin(position, destination), 0);
- } else if (time < thirdPhaseStart) {
- // Stay in the same position for the second phase.
- m.translate(restX, 0);
- } else {
- // Move out of view for the third phase.
- const int thirdPhaseSubKickoff = (blockMovingSpacing / pixelsPerSecond) * 1000;
- const int subphase = (time - thirdPhaseStart) / thirdPhaseSubKickoff;
- // If we're not at this subphase yet, don't try to animate movement,
- // because it will be incorrect.
- if (subphase < i)
- return;
-
- const qreal timeSinceSecondPhase = timeInSeconds - (thirdPhaseStart / 1000.0);
- // We only want to start keeping track of time once our subphase has started,
- // otherwise we move too much because we account for time that has already elapsed.
- // For example, if we were 60 milliseconds into the third subphase:
- //
- // 0 ..... 1 ..... 2 ...
- // 100 100 60
- //
- // i == 0, timeSinceOurKickoff == 260
- // i == 1, timeSinceOurKickoff == 160
- // i == 2, timeSinceOurKickoff == 60
- const qreal timeSinceOurKickoff = timeSinceSecondPhase - (thirdPhaseSubKickoff / 1000.0 * i);
- const qreal position = restX + (pixelsPerSecond * (timeSinceOurKickoff));
- const qreal destination = blockEndX(i, rootRectNode->rect().width());
- m.translate(qMin(position, destination), 0);
- }
-
- transformNode->setMatrix(m);
- rectNode->update();
-
- transformNode = static_cast<QSGTransformNode*>(transformNode->nextSibling());
- }
-}
-
-void QQuickProgressAnimatorJob::writeBack()
-{
-}
-
-void QQuickProgressAnimatorJob::nodeWasDestroyed()
-{
- m_node = nullptr;
-}
-
-QT_END_NAMESPACE
diff --git a/src/imports/controls/qtquickcontrols2plugin.cpp b/src/imports/controls/qtquickcontrols2plugin.cpp
index 57724dd7..e7bedc73 100644
--- a/src/imports/controls/qtquickcontrols2plugin.cpp
+++ b/src/imports/controls/qtquickcontrols2plugin.cpp
@@ -36,17 +36,18 @@
#include <QtCore/private/qfileselector_p.h>
#include <QtQuickControls2/qquickstyle.h>
+#include <QtQuickControls2/private/qquickplaceholdertext_p.h>
#include <QtQuickControls2/private/qquickstyle_p.h>
#include <QtQuickControls2/private/qquickstyleplugin_p.h>
#include <QtQuickControls2/private/qquickstyleselector_p.h>
#include <QtQuickControls2/private/qquickcolorimageprovider_p.h>
-#include <QtQuickTemplates2/private/qquickbuttongroup_p.h>
#include <QtQuickControls2/private/qquicktumblerview_p.h>
+#include <QtQuickTemplates2/private/qquickbuttongroup_p.h>
-#include "qquickbusyindicatorring_p.h"
+#include "qquickdefaultbusyindicator_p.h"
+#include "qquickdefaultprogressbar_p.h"
#include "qquickdefaultstyle_p.h"
#include "qquickdialring_p.h"
-#include "qquickprogressstrip_p.h"
static inline void initResources()
{
@@ -84,7 +85,9 @@ void QtQuickControls2Plugin::registerTypes(const char *uri)
QQuickStyleSelector selector;
selector.setBaseUrl(typeUrl());
- // QtQuick.Controls 2.0 (Qt 5.7)
+ qmlRegisterModule(uri, 2, QT_VERSION_MINOR - 7); // Qt 5.7->2.0, 5.8->2.1, 5.9->2.2...
+
+ // QtQuick.Controls 2.0 (originally introduced in Qt 5.7)
qmlRegisterType(selector.select(QStringLiteral("AbstractButton.qml")), uri, 2, 0, "AbstractButton");
qmlRegisterType(selector.select(QStringLiteral("ApplicationWindow.qml")), uri, 2, 0, "ApplicationWindow");
qmlRegisterType(selector.select(QStringLiteral("BusyIndicator.qml")), uri, 2, 0, "BusyIndicator");
@@ -130,13 +133,16 @@ void QtQuickControls2Plugin::registerTypes(const char *uri)
qmlRegisterType(selector.select(QStringLiteral("ToolTip.qml")), uri, 2, 0, "ToolTip");
qmlRegisterType(selector.select(QStringLiteral("Tumbler.qml")), uri, 2, 0, "Tumbler");
- // QtQuick.Controls 2.1 (Qt 5.8)
+ // QtQuick.Controls 2.1 (new types in Qt 5.8)
qmlRegisterType<QQuickButtonGroup,1 >(uri, 2, 1, "ButtonGroup");
qmlRegisterType(selector.select(QStringLiteral("Dialog.qml")), uri, 2, 1, "Dialog");
qmlRegisterType(selector.select(QStringLiteral("DialogButtonBox.qml")), uri, 2, 1, "DialogButtonBox");
qmlRegisterType(selector.select(QStringLiteral("MenuSeparator.qml")), uri, 2, 1, "MenuSeparator");
qmlRegisterType(selector.select(QStringLiteral("RoundButton.qml")), uri, 2, 1, "RoundButton");
qmlRegisterType(selector.select(QStringLiteral("ToolSeparator.qml")), uri, 2, 1, "ToolSeparator");
+
+ // QtQuick.Controls 2.2 (new types in Qt 5.9)
+ qmlRegisterType(selector.select(QStringLiteral("DelayButton.qml")), uri, 2, 2, "DelayButton");
}
static QObject *styleSingleton(QQmlEngine *engine, QJSEngine *scriptEngine)
@@ -153,14 +159,14 @@ void QtQuickControls2Plugin::initializeEngine(QQmlEngine *engine, const char *ur
engine->addImageProvider(QStringLiteral("default"), new QQuickColorImageProvider(QStringLiteral(":/qt-project.org/imports/QtQuick/Controls.2/images")));
const QByteArray import = QByteArray(uri) + ".impl";
- qmlRegisterType<QQuickBusyIndicatorRing>(import, 2, 0, "BusyRing");
- qmlRegisterType<QQuickBusyIndicatorAnimator>(import, 2, 0, "BusyRingAnimator");
- qmlRegisterType<QQuickProgressStrip>(import, 2, 0, "ProgressStrip");
- qmlRegisterType<QQuickProgressAnimator>(import, 2, 0, "ProgressStripAnimator");
+ qmlRegisterModule(import, 2, QT_VERSION_MINOR - 7); // Qt 5.7->2.0, 5.8->2.1, 5.9->2.2...
+
+ qmlRegisterType<QQuickDefaultBusyIndicator>(import, 2, 0, "BusyIndicatorImpl");
+ qmlRegisterType<QQuickDefaultProgressBar>(import, 2, 0, "ProgressBarImpl");
qmlRegisterType<QQuickDialRing>(import, 2, 0, "DialRing");
+ qmlRegisterType<QQuickPlaceholderText>(import, 2, 2, "PlaceholderText");
qmlRegisterType<QQuickTumblerView>(import, 2, 1, "TumblerView");
qmlRegisterSingletonType<QQuickDefaultStyle>(import, 2, 1, "Default", styleSingleton);
-
qmlRegisterType(typeUrl(QStringLiteral("CheckIndicator.qml")), import, 2, 0, "CheckIndicator");
qmlRegisterType(typeUrl(QStringLiteral("RadioIndicator.qml")), import, 2, 0, "RadioIndicator");
qmlRegisterType(typeUrl(QStringLiteral("SwitchIndicator.qml")), import, 2, 0, "SwitchIndicator");
diff --git a/src/imports/controls/universal/ApplicationWindow.qml b/src/imports/controls/universal/ApplicationWindow.qml
index db1a71bf..a9d03c8c 100644
--- a/src/imports/controls/universal/ApplicationWindow.qml
+++ b/src/imports/controls/universal/ApplicationWindow.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
-import QtQuick.Controls.Universal.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
+import QtQuick.Controls.Universal.impl 2.2
T.ApplicationWindow {
id: window
diff --git a/src/imports/controls/universal/BusyIndicator.qml b/src/imports/controls/universal/BusyIndicator.qml
index 3295400b..8f0574fe 100644
--- a/src/imports/controls/universal/BusyIndicator.qml
+++ b/src/imports/controls/universal/BusyIndicator.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
-import QtQuick.Controls.Universal.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
+import QtQuick.Controls.Universal.impl 2.2
T.BusyIndicator {
id: control
@@ -45,9 +45,7 @@ T.BusyIndicator {
implicitWidth: contentItem.implicitWidth + leftPadding + rightPadding
implicitHeight: contentItem.implicitHeight + topPadding + bottomPadding
- contentItem: ProgressRing {
- id: ring
-
+ contentItem: BusyIndicatorImpl {
implicitWidth: 20
implicitHeight: 20
@@ -55,10 +53,6 @@ T.BusyIndicator {
count: size < 60 ? 5 : 6 // "Small" vs. "Large"
color: control.Universal.accent
-
- ProgressRingAnimator {
- target: ring
- running: control.visible && control.running
- }
+ visible: control.running
}
}
diff --git a/src/imports/controls/universal/Button.qml b/src/imports/controls/universal/Button.qml
index 5a2ad5f2..0bf3621b 100644
--- a/src/imports/controls/universal/Button.qml
+++ b/src/imports/controls/universal/Button.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
T.Button {
id: control
diff --git a/src/imports/controls/universal/CheckBox.qml b/src/imports/controls/universal/CheckBox.qml
index ad5700c1..8f4b248d 100644
--- a/src/imports/controls/universal/CheckBox.qml
+++ b/src/imports/controls/universal/CheckBox.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
-import QtQuick.Controls.Universal.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
+import QtQuick.Controls.Universal.impl 2.2
T.CheckBox {
id: control
diff --git a/src/imports/controls/universal/CheckDelegate.qml b/src/imports/controls/universal/CheckDelegate.qml
index b346a143..95ed29e0 100644
--- a/src/imports/controls/universal/CheckDelegate.qml
+++ b/src/imports/controls/universal/CheckDelegate.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
T.CheckDelegate {
id: control
diff --git a/src/imports/controls/universal/CheckIndicator.qml b/src/imports/controls/universal/CheckIndicator.qml
index 91cf7a6d..eac150e2 100644
--- a/src/imports/controls/universal/CheckIndicator.qml
+++ b/src/imports/controls/universal/CheckIndicator.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
Rectangle {
implicitWidth: 20
@@ -67,7 +67,7 @@ Rectangle {
x: (parent.width - width) / 2
y: (parent.height - height) / 2
width: partiallyChecked ? parent.width / 2 : parent.width
- height: partiallyChecked ? parent.height / 2 : parent.height
+ height: partiallyChecked ? parent.height / 2 : parent.height
visible: !control.pressed && control.hovered || partiallyChecked
color: !partiallyChecked ? "transparent" :
diff --git a/src/imports/controls/universal/ComboBox.qml b/src/imports/controls/universal/ComboBox.qml
index 11a6ae79..9ff31d1d 100644
--- a/src/imports/controls/universal/ComboBox.qml
+++ b/src/imports/controls/universal/ComboBox.qml
@@ -34,11 +34,11 @@
**
****************************************************************************/
-import QtQuick 2.8
+import QtQuick 2.9
import QtQuick.Window 2.2
-import QtQuick.Controls 2.1
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick.Controls 2.2
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
T.ComboBox {
id: control
@@ -50,39 +50,58 @@ T.ComboBox {
indicator ? indicator.implicitHeight : 0) + topPadding + bottomPadding)
baselineOffset: contentItem.y + contentItem.baselineOffset
- spacing: 10
- padding: 12
- topPadding: padding - 7
- rightPadding: padding - 2
- bottomPadding: padding - 5
+ leftPadding: padding + (!control.mirrored || !indicator || !indicator.visible ? 0 : indicator.width + spacing)
+ rightPadding: padding + (control.mirrored || !indicator || !indicator.visible ? 0 : indicator.width + spacing)
+
+ Universal.theme: editable && activeFocus ? Universal.Light : undefined
delegate: ItemDelegate {
- width: control.popup.width
+ width: parent.width
text: control.textRole ? (Array.isArray(control.model) ? modelData[control.textRole] : model[control.textRole]) : modelData
highlighted: control.highlightedIndex === index
hoverEnabled: control.hoverEnabled
}
indicator: Image {
- x: control.mirrored ? control.leftPadding : control.width - width - control.rightPadding
+ x: control.mirrored ? control.padding : control.width - width - control.padding
y: control.topPadding + (control.availableHeight - height) / 2
source: "image://universal/downarrow/" + (!control.enabled ? control.Universal.baseLowColor : control.Universal.baseMediumHighColor)
sourceSize.width: width
sourceSize.height: height
+
+ Rectangle {
+ z: -1
+ width: parent.width
+ height: parent.height
+ color: control.activeFocus ? control.Universal.accent :
+ control.pressed ? control.Universal.baseMediumLowColor :
+ control.hovered ? control.Universal.baseLowColor : "transparent"
+ visible: control.editable && !contentItem.hovered && (control.pressed || control.hovered)
+ opacity: control.activeFocus && !control.pressed ? 0.4 : 1.0
+ }
}
- contentItem: Text {
- leftPadding: control.mirrored && control.indicator ? control.indicator.width + control.spacing : 0
- rightPadding: !control.mirrored && control.indicator ? control.indicator.width + control.spacing : 0
+ contentItem: T.TextField {
+ leftPadding: control.mirrored ? 1 : 12
+ rightPadding: control.mirrored ? 10 : 1
+ topPadding: 5 - control.topPadding
+ bottomPadding: 7 - control.bottomPadding
+
+ text: control.editable ? control.editText : control.displayText
+
+ enabled: control.editable
+ autoScroll: control.editable
+ readOnly: control.popup.visible
+ inputMethodHints: control.inputMethodHints
+ validator: control.validator
- text: control.displayText
font: control.font
+ color: !control.enabled ? control.Universal.chromeDisabledLowColor :
+ control.editable && control.activeFocus ? control.Universal.chromeBlackHighColor : control.Universal.foreground
+ selectionColor: control.Universal.accent
+ selectedTextColor: control.Universal.chromeWhiteColor
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
- elide: Text.ElideRight
-
- opacity: enabled ? 1.0 : 0.2
- color: control.Universal.foreground
}
background: Rectangle {
@@ -91,11 +110,13 @@ T.ComboBox {
border.width: control.flat ? 0 : 2 // ComboBoxBorderThemeThickness
border.color: !control.enabled ? control.Universal.baseLowColor :
- control.pressed || popup.visible ? control.Universal.baseMediumLowColor :
+ control.editable && control.activeFocus ? control.Universal.accent :
+ control.down || popup.visible ? control.Universal.baseMediumLowColor :
control.hovered ? control.Universal.baseMediumColor : control.Universal.baseMediumLowColor
color: !control.enabled ? control.Universal.baseLowColor :
- control.pressed || popup.visible ? control.Universal.listMediumColor :
- control.flat && control.hovered ? control.Universal.listLowColor : control.Universal.altMediumLowColor
+ control.down ? control.Universal.listMediumColor :
+ control.flat && control.hovered ? control.Universal.listLowColor :
+ control.editable && control.activeFocus ? control.Universal.background : control.Universal.altMediumLowColor
visible: !control.flat || control.pressed || control.hovered || control.visualFocus
Rectangle {
@@ -104,7 +125,7 @@ T.ComboBox {
width: parent.width - 4
height: parent.height - 4
- visible: control.visualFocus
+ visible: control.visualFocus && !control.editable
color: control.Universal.accent
opacity: control.Universal.theme === Universal.Light ? 0.4 : 0.6
}
diff --git a/src/imports/controls/universal/DelayButton.qml b/src/imports/controls/universal/DelayButton.qml
new file mode 100644
index 00000000..9d43be44
--- /dev/null
+++ b/src/imports/controls/universal/DelayButton.qml
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
+
+T.DelayButton {
+ id: control
+
+ implicitWidth: Math.max(background ? background.implicitWidth : 0,
+ contentItem.implicitWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(background ? background.implicitHeight : 0,
+ contentItem.implicitHeight + topPadding + bottomPadding)
+ baselineOffset: contentItem.y + contentItem.baselineOffset
+
+ padding: 8
+ topPadding: padding - 4
+ bottomPadding: padding - 4
+
+ property bool useSystemFocusVisuals: true
+
+ transition: Transition {
+ NumberAnimation {
+ duration: control.delay * (control.pressed ? 1.0 - control.progress : 0.3 * control.progress)
+ }
+ }
+
+ contentItem: Text {
+ text: control.text
+ font: control.font
+ elide: Text.ElideRight
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+
+ opacity: enabled ? 1.0 : 0.2
+ color: control.Universal.foreground
+ }
+
+ background: Rectangle {
+ implicitWidth: 32
+ implicitHeight: 32
+
+ color: control.down ? control.Universal.baseMediumLowColor :
+ control.enabled && control.checked ? control.Universal.accent : control.Universal.baseLowColor
+
+ Rectangle {
+ visible: !control.checked
+ width: parent.width * control.progress
+ height: parent.height
+ color: control.Universal.accent
+ }
+
+ Rectangle {
+ width: parent.width
+ height: parent.height
+ color: "transparent"
+ visible: control.hovered
+ border.width: 2 // ButtonBorderThemeThickness
+ border.color: control.Universal.baseMediumLowColor
+ }
+ }
+}
diff --git a/src/imports/controls/universal/Dial.qml b/src/imports/controls/universal/Dial.qml
index 7eba1e19..2ffb4167 100644
--- a/src/imports/controls/universal/Dial.qml
+++ b/src/imports/controls/universal/Dial.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
T.Dial {
id: control
diff --git a/src/imports/controls/universal/Dialog.qml b/src/imports/controls/universal/Dialog.qml
index a70c1d2a..07ae56a6 100644
--- a/src/imports/controls/universal/Dialog.qml
+++ b/src/imports/controls/universal/Dialog.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls 2.1
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls 2.2
+import QtQuick.Controls.Universal 2.2
T.Dialog {
id: control
diff --git a/src/imports/controls/universal/DialogButtonBox.qml b/src/imports/controls/universal/DialogButtonBox.qml
index 8db91953..4ce41ad6 100644
--- a/src/imports/controls/universal/DialogButtonBox.qml
+++ b/src/imports/controls/universal/DialogButtonBox.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls 2.1
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls 2.2
+import QtQuick.Controls.Universal 2.2
T.DialogButtonBox {
id: control
diff --git a/src/imports/controls/universal/Drawer.qml b/src/imports/controls/universal/Drawer.qml
index d5311d15..3543887e 100644
--- a/src/imports/controls/universal/Drawer.qml
+++ b/src/imports/controls/universal/Drawer.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
T.Drawer {
id: control
diff --git a/src/imports/controls/universal/Frame.qml b/src/imports/controls/universal/Frame.qml
index 38d5a2e2..7d7d55a7 100644
--- a/src/imports/controls/universal/Frame.qml
+++ b/src/imports/controls/universal/Frame.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
T.Frame {
id: control
diff --git a/src/imports/controls/universal/GroupBox.qml b/src/imports/controls/universal/GroupBox.qml
index 8fcc518c..420cf22d 100644
--- a/src/imports/controls/universal/GroupBox.qml
+++ b/src/imports/controls/universal/GroupBox.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
T.GroupBox {
id: control
diff --git a/src/imports/controls/universal/ItemDelegate.qml b/src/imports/controls/universal/ItemDelegate.qml
index f6f0e9bd..69b2cd9d 100644
--- a/src/imports/controls/universal/ItemDelegate.qml
+++ b/src/imports/controls/universal/ItemDelegate.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
T.ItemDelegate {
id: control
diff --git a/src/imports/controls/universal/Label.qml b/src/imports/controls/universal/Label.qml
index 0f7b49ef..3cfa9317 100644
--- a/src/imports/controls/universal/Label.qml
+++ b/src/imports/controls/universal/Label.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
T.Label {
id: control
diff --git a/src/imports/controls/universal/Menu.qml b/src/imports/controls/universal/Menu.qml
index f0415670..0ca475f5 100644
--- a/src/imports/controls/universal/Menu.qml
+++ b/src/imports/controls/universal/Menu.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls 2.1
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
T.Menu {
id: control
diff --git a/src/imports/controls/universal/MenuItem.qml b/src/imports/controls/universal/MenuItem.qml
index 6d3ae444..35e2f2ba 100644
--- a/src/imports/controls/universal/MenuItem.qml
+++ b/src/imports/controls/universal/MenuItem.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
T.MenuItem {
id: control
diff --git a/src/imports/controls/universal/MenuSeparator.qml b/src/imports/controls/universal/MenuSeparator.qml
index 62ce03bb..18d12528 100644
--- a/src/imports/controls/universal/MenuSeparator.qml
+++ b/src/imports/controls/universal/MenuSeparator.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
T.MenuSeparator {
id: control
diff --git a/src/imports/controls/universal/Page.qml b/src/imports/controls/universal/Page.qml
index ef580ded..1f006f16 100644
--- a/src/imports/controls/universal/Page.qml
+++ b/src/imports/controls/universal/Page.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
T.Page {
id: control
diff --git a/src/imports/controls/universal/PageIndicator.qml b/src/imports/controls/universal/PageIndicator.qml
index 58b037f2..f6a6baa6 100644
--- a/src/imports/controls/universal/PageIndicator.qml
+++ b/src/imports/controls/universal/PageIndicator.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
T.PageIndicator {
id: control
diff --git a/src/imports/controls/universal/Pane.qml b/src/imports/controls/universal/Pane.qml
index 3307c3db..67a66c93 100644
--- a/src/imports/controls/universal/Pane.qml
+++ b/src/imports/controls/universal/Pane.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
T.Pane {
id: control
diff --git a/src/imports/controls/universal/Popup.qml b/src/imports/controls/universal/Popup.qml
index 6b87a9ae..2c582217 100644
--- a/src/imports/controls/universal/Popup.qml
+++ b/src/imports/controls/universal/Popup.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
T.Popup {
id: control
diff --git a/src/imports/controls/universal/ProgressBar.qml b/src/imports/controls/universal/ProgressBar.qml
index 64982c4d..58545d61 100644
--- a/src/imports/controls/universal/ProgressBar.qml
+++ b/src/imports/controls/universal/ProgressBar.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
-import QtQuick.Controls.Universal.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
+import QtQuick.Controls.Universal.impl 2.2
T.ProgressBar {
id: control
@@ -47,20 +47,13 @@ T.ProgressBar {
implicitHeight: Math.max(background ? background.implicitHeight : 0,
contentItem.implicitHeight + topPadding + bottomPadding)
- contentItem: ProgressStrip {
- id: strip
+ contentItem: ProgressBarImpl {
implicitHeight: 10
scale: control.mirrored ? -1 : 1
- indeterminate: control.indeterminate
color: control.Universal.accent
progress: control.position
- clip: control.indeterminate
-
- ProgressStripAnimator {
- target: strip
- running: control.visible && control.indeterminate
- }
+ indeterminate: control.visible && control.indeterminate
}
background: Rectangle {
diff --git a/src/imports/controls/universal/RadioButton.qml b/src/imports/controls/universal/RadioButton.qml
index f496b55f..5d778660 100644
--- a/src/imports/controls/universal/RadioButton.qml
+++ b/src/imports/controls/universal/RadioButton.qml
@@ -34,10 +34,10 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
-import QtQuick.Controls.Universal.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
+import QtQuick.Controls.Universal.impl 2.2
T.RadioButton {
id: control
diff --git a/src/imports/controls/universal/RadioDelegate.qml b/src/imports/controls/universal/RadioDelegate.qml
index 8710e03e..d314dbf0 100644
--- a/src/imports/controls/universal/RadioDelegate.qml
+++ b/src/imports/controls/universal/RadioDelegate.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
T.RadioDelegate {
id: control
diff --git a/src/imports/controls/universal/RadioIndicator.qml b/src/imports/controls/universal/RadioIndicator.qml
index ebfd1725..220983da 100644
--- a/src/imports/controls/universal/RadioIndicator.qml
+++ b/src/imports/controls/universal/RadioIndicator.qml
@@ -34,8 +34,8 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Controls.Universal 2.2
Rectangle {
implicitWidth: 20
diff --git a/src/imports/controls/universal/RangeSlider.qml b/src/imports/controls/universal/RangeSlider.qml
index 82a962ad..d2cf7a65 100644
--- a/src/imports/controls/universal/RangeSlider.qml
+++ b/src/imports/controls/universal/RangeSlider.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
T.RangeSlider {
id: control
diff --git a/src/imports/controls/universal/RoundButton.qml b/src/imports/controls/universal/RoundButton.qml
index d843b767..d70c4cda 100644
--- a/src/imports/controls/universal/RoundButton.qml
+++ b/src/imports/controls/universal/RoundButton.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
T.RoundButton {
id: control
diff --git a/src/imports/controls/universal/ScrollBar.qml b/src/imports/controls/universal/ScrollBar.qml
index 15254ade..434d8fb2 100644
--- a/src/imports/controls/universal/ScrollBar.qml
+++ b/src/imports/controls/universal/ScrollBar.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
T.ScrollBar {
id: control
diff --git a/src/imports/controls/universal/ScrollIndicator.qml b/src/imports/controls/universal/ScrollIndicator.qml
index 38eeb0ce..2f30ebe5 100644
--- a/src/imports/controls/universal/ScrollIndicator.qml
+++ b/src/imports/controls/universal/ScrollIndicator.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
T.ScrollIndicator {
id: control
diff --git a/src/imports/controls/universal/Slider.qml b/src/imports/controls/universal/Slider.qml
index 5febd52a..e02065e5 100644
--- a/src/imports/controls/universal/Slider.qml
+++ b/src/imports/controls/universal/Slider.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
T.Slider {
id: control
diff --git a/src/imports/controls/universal/SpinBox.qml b/src/imports/controls/universal/SpinBox.qml
index 632de5d6..0cbfdd16 100644
--- a/src/imports/controls/universal/SpinBox.qml
+++ b/src/imports/controls/universal/SpinBox.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
T.SpinBox {
id: control
@@ -79,7 +79,7 @@ T.SpinBox {
readOnly: !control.editable
validator: control.validator
- inputMethodHints: Qt.ImhDigitsOnly
+ inputMethodHints: control.inputMethodHints
}
up.indicator: Item {
diff --git a/src/imports/controls/universal/StackView.qml b/src/imports/controls/universal/StackView.qml
index c13047ec..071e1737 100644
--- a/src/imports/controls/universal/StackView.qml
+++ b/src/imports/controls/universal/StackView.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
T.StackView {
id: control
diff --git a/src/imports/controls/universal/SwipeDelegate.qml b/src/imports/controls/universal/SwipeDelegate.qml
index 7ada0b69..8caf7fb8 100644
--- a/src/imports/controls/universal/SwipeDelegate.qml
+++ b/src/imports/controls/universal/SwipeDelegate.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
T.SwipeDelegate {
id: control
@@ -54,6 +54,8 @@ T.SwipeDelegate {
topPadding: padding - 1
bottomPadding: padding + 1
+ swipe.transition: Transition { SmoothedAnimation { velocity: 3; easing.type: Easing.InOutCubic } }
+
contentItem: Text {
leftPadding: !control.mirrored ? (control.indicator ? control.indicator.width : 0) + control.spacing : 0
rightPadding: control.mirrored ? (control.indicator ? control.indicator.width : 0) + control.spacing : 0
@@ -68,14 +70,6 @@ T.SwipeDelegate {
opacity: enabled ? 1.0 : 0.2
color: control.Universal.foreground
-
- Behavior on x {
- enabled: !control.down
- NumberAnimation {
- easing.type: Easing.InOutCubic
- duration: 400
- }
- }
}
background: Rectangle {
@@ -94,13 +88,5 @@ T.SwipeDelegate {
opacity: control.Universal.theme === Universal.Light ? 0.4 : 0.6
}
}
-
- Behavior on x {
- enabled: !control.down
- NumberAnimation {
- easing.type: Easing.InOutCubic
- duration: 400
- }
- }
}
}
diff --git a/src/imports/controls/universal/Switch.qml b/src/imports/controls/universal/Switch.qml
index 635f2bf1..e3dde0dc 100644
--- a/src/imports/controls/universal/Switch.qml
+++ b/src/imports/controls/universal/Switch.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
T.Switch {
id: control
diff --git a/src/imports/controls/universal/SwitchDelegate.qml b/src/imports/controls/universal/SwitchDelegate.qml
index a3f9cda7..59b71817 100644
--- a/src/imports/controls/universal/SwitchDelegate.qml
+++ b/src/imports/controls/universal/SwitchDelegate.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
T.SwitchDelegate {
id: control
diff --git a/src/imports/controls/universal/SwitchIndicator.qml b/src/imports/controls/universal/SwitchIndicator.qml
index c9d062d9..1eb2f9b5 100644
--- a/src/imports/controls/universal/SwitchIndicator.qml
+++ b/src/imports/controls/universal/SwitchIndicator.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
Item {
implicitWidth: 44
diff --git a/src/imports/controls/universal/TabBar.qml b/src/imports/controls/universal/TabBar.qml
index f9c0619b..c0de7fb2 100644
--- a/src/imports/controls/universal/TabBar.qml
+++ b/src/imports/controls/universal/TabBar.qml
@@ -34,22 +34,21 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
T.TabBar {
id: control
implicitWidth: Math.max(background ? background.implicitWidth : 0,
- contentItem.implicitWidth + leftPadding + rightPadding)
+ contentWidth + leftPadding + rightPadding)
implicitHeight: Math.max(background ? background.implicitHeight : 0,
- contentItem.implicitHeight + topPadding + bottomPadding)
+ contentHeight + topPadding + bottomPadding)
- contentItem: PathView {
- implicitWidth: 200
- implicitHeight: 48
+ contentHeight: 48
+ contentItem: PathView {
model: control.contentModel
currentIndex: control.currentIndex
diff --git a/src/imports/controls/universal/TabButton.qml b/src/imports/controls/universal/TabButton.qml
index 4a92181d..ef982c60 100644
--- a/src/imports/controls/universal/TabButton.qml
+++ b/src/imports/controls/universal/TabButton.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
T.TabButton {
id: control
diff --git a/src/imports/controls/universal/TextArea.qml b/src/imports/controls/universal/TextArea.qml
index 829c6771..a173e676 100644
--- a/src/imports/controls/universal/TextArea.qml
+++ b/src/imports/controls/universal/TextArea.qml
@@ -34,9 +34,11 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Controls.Universal 2.2
T.TextArea {
id: control
@@ -60,7 +62,7 @@ T.TextArea {
selectionColor: Universal.accent
selectedTextColor: Universal.chromeWhiteColor
- Text {
+ PlaceholderText {
id: placeholder
x: control.leftPadding
y: control.topPadding
@@ -72,7 +74,6 @@ T.TextArea {
color: !control.enabled ? control.Universal.chromeDisabledLowColor :
control.activeFocus ? control.Universal.chromeBlackMediumLowColor : control.Universal.baseMediumColor
visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter)
- horizontalAlignment: control.horizontalAlignment
verticalAlignment: control.verticalAlignment
elide: Text.ElideRight
}
diff --git a/src/imports/controls/universal/TextField.qml b/src/imports/controls/universal/TextField.qml
index 1fc7039b..476630fd 100644
--- a/src/imports/controls/universal/TextField.qml
+++ b/src/imports/controls/universal/TextField.qml
@@ -34,9 +34,11 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
+import QtQuick.Controls.Universal 2.2
T.TextField {
id: control
@@ -61,7 +63,7 @@ T.TextField {
selectedTextColor: Universal.chromeWhiteColor
verticalAlignment: TextInput.AlignVCenter
- Text {
+ PlaceholderText {
id: placeholder
x: control.leftPadding
y: control.topPadding
@@ -73,7 +75,6 @@ T.TextField {
color: !control.enabled ? control.Universal.chromeDisabledLowColor :
control.activeFocus ? control.Universal.chromeBlackMediumLowColor : control.Universal.baseMediumColor
visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter)
- horizontalAlignment: control.horizontalAlignment
verticalAlignment: control.verticalAlignment
elide: Text.ElideRight
}
diff --git a/src/imports/controls/universal/ToolBar.qml b/src/imports/controls/universal/ToolBar.qml
index 3655c530..f6bec475 100644
--- a/src/imports/controls/universal/ToolBar.qml
+++ b/src/imports/controls/universal/ToolBar.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
T.ToolBar {
id: control
diff --git a/src/imports/controls/universal/ToolButton.qml b/src/imports/controls/universal/ToolButton.qml
index 55e9f285..9b07490f 100644
--- a/src/imports/controls/universal/ToolButton.qml
+++ b/src/imports/controls/universal/ToolButton.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
T.ToolButton {
id: control
diff --git a/src/imports/controls/universal/ToolSeparator.qml b/src/imports/controls/universal/ToolSeparator.qml
index 5041bc34..86b3aed3 100644
--- a/src/imports/controls/universal/ToolSeparator.qml
+++ b/src/imports/controls/universal/ToolSeparator.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
T.ToolSeparator {
id: control
diff --git a/src/imports/controls/universal/ToolTip.qml b/src/imports/controls/universal/ToolTip.qml
index b92fbbc1..6f8f27f4 100644
--- a/src/imports/controls/universal/ToolTip.qml
+++ b/src/imports/controls/universal/ToolTip.qml
@@ -34,9 +34,9 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
T.ToolTip {
id: control
diff --git a/src/imports/controls/universal/Tumbler.qml b/src/imports/controls/universal/Tumbler.qml
index 6a1647c9..45bcb6c8 100644
--- a/src/imports/controls/universal/Tumbler.qml
+++ b/src/imports/controls/universal/Tumbler.qml
@@ -34,11 +34,11 @@
**
****************************************************************************/
-import QtQuick 2.8
-import QtQuick.Templates 2.1 as T
-import QtQuick.Controls.Universal 2.1
-import QtQuick.Controls 2.1
-import QtQuick.Controls.impl 2.1
+import QtQuick 2.9
+import QtQuick.Templates 2.2 as T
+import QtQuick.Controls.Universal 2.2
+import QtQuick.Controls 2.2
+import QtQuick.Controls.impl 2.2
T.Tumbler {
id: control
diff --git a/src/imports/controls/universal/images/downarrow.png b/src/imports/controls/universal/images/downarrow.png
index fef7b0f2..9ac84a23 100644
--- a/src/imports/controls/universal/images/downarrow.png
+++ b/src/imports/controls/universal/images/downarrow.png
Binary files differ
diff --git a/src/imports/controls/universal/images/downarrow@2x.png b/src/imports/controls/universal/images/downarrow@2x.png
index eabf658a..8dafab94 100644
--- a/src/imports/controls/universal/images/downarrow@2x.png
+++ b/src/imports/controls/universal/images/downarrow@2x.png
Binary files differ
diff --git a/src/imports/controls/universal/images/downarrow@3x.png b/src/imports/controls/universal/images/downarrow@3x.png
index f9d39a2c..17ab1cf8 100644
--- a/src/imports/controls/universal/images/downarrow@3x.png
+++ b/src/imports/controls/universal/images/downarrow@3x.png
Binary files differ
diff --git a/src/imports/controls/universal/images/downarrow@4x.png b/src/imports/controls/universal/images/downarrow@4x.png
index b252b588..0e145e2d 100644
--- a/src/imports/controls/universal/images/downarrow@4x.png
+++ b/src/imports/controls/universal/images/downarrow@4x.png
Binary files differ
diff --git a/src/imports/controls/universal/qmldir b/src/imports/controls/universal/qmldir
index 1dde3a02..da4a89d6 100644
--- a/src/imports/controls/universal/qmldir
+++ b/src/imports/controls/universal/qmldir
@@ -1,4 +1,4 @@
module QtQuick.Controls.Universal
plugin qtquickcontrols2universalstyleplugin
classname QtQuickControls2UniversalStylePlugin
-depends QtQuick.Controls 2.1
+depends QtQuick.Controls 2.2
diff --git a/src/imports/controls/universal/qquickuniversalprogressring.cpp b/src/imports/controls/universal/qquickuniversalbusyindicator.cpp
index 7311add7..a3d09094 100644
--- a/src/imports/controls/universal/qquickuniversalprogressring.cpp
+++ b/src/imports/controls/universal/qquickuniversalbusyindicator.cpp
@@ -34,13 +34,13 @@
**
****************************************************************************/
-#include "qquickuniversalprogressring_p.h"
+#include "qquickuniversalbusyindicator_p.h"
#include <QtCore/qmath.h>
#include <QtCore/qeasingcurve.h>
#include <QtQuick/private/qquickitem_p.h>
-#include <QtQuick/private/qquickanimatorjob_p.h>
#include <QtQuick/private/qsgadaptationlayer_p.h>
+#include <QtQuickControls2/private/qquickanimatednode_p.h>
QT_BEGIN_NAMESPACE
@@ -48,16 +48,13 @@ static const int PhaseCount = 6;
static const int Interval = 167;
static const int TotalDuration = 4052;
-class QQuickUniversalProgressRingAnimatorJob : public QQuickAnimatorJob
+class QQuickUniversalBusyIndicatorNode : public QQuickAnimatedNode
{
public:
- QQuickUniversalProgressRingAnimatorJob();
+ QQuickUniversalBusyIndicatorNode(QQuickUniversalBusyIndicator *item);
- void initialize(QQuickAnimatorController *controller) override;
void updateCurrentTime(int time) override;
- void writeBack() override;
- void nodeWasDestroyed() override;
- void afterNodeSync() override;
+ void sync(QQuickItem *item) override;
private:
struct Phase {
@@ -69,12 +66,16 @@ private:
QEasingCurve curve;
};
- QSGNode *m_node;
Phase m_phases[PhaseCount];
};
-QQuickUniversalProgressRingAnimatorJob::QQuickUniversalProgressRingAnimatorJob() : m_node(nullptr)
+QQuickUniversalBusyIndicatorNode::QQuickUniversalBusyIndicatorNode(QQuickUniversalBusyIndicator *item)
+ : QQuickAnimatedNode(item)
{
+ setLoopCount(Infinite);
+ setDuration(TotalDuration);
+ setCurrentTime(item->elapsed());
+
m_phases[0] = Phase(433, -110, 10, QEasingCurve::BezierSpline);
m_phases[1] = Phase(767, 10, 93, QEasingCurve::Linear );
m_phases[2] = Phase(417, 93, 205, QEasingCurve::BezierSpline);
@@ -88,25 +89,11 @@ QQuickUniversalProgressRingAnimatorJob::QQuickUniversalProgressRingAnimatorJob()
m_phases[5].curve.addCubicBezierSegment(QPointF(0.00, 0.00), QPointF(0.95, 0.37), QPointF(1.00, 1.00));
}
-void QQuickUniversalProgressRingAnimatorJob::initialize(QQuickAnimatorController *controller)
-{
- QQuickAnimatorJob::initialize(controller);
- m_node = QQuickItemPrivate::get(m_target)->childContainerNode();
-}
-
-void QQuickUniversalProgressRingAnimatorJob::updateCurrentTime(int time)
+void QQuickUniversalBusyIndicatorNode::updateCurrentTime(int time)
{
- if (!m_node)
- return;
-
- QSGNode *containerNode = m_node->firstChild();
- Q_ASSERT(!containerNode || containerNode->type() == QSGNode::TransformNodeType);
- if (!containerNode)
- return;
-
int nodeIndex = 0;
- int count = containerNode->childCount();
- QSGTransformNode *transformNode = static_cast<QSGTransformNode *>(containerNode->firstChild());
+ int count = childCount();
+ QSGTransformNode *transformNode = static_cast<QSGTransformNode *>(firstChild());
while (transformNode) {
Q_ASSERT(transformNode->type() == QSGNode::TransformNodeType);
@@ -147,126 +134,118 @@ void QQuickUniversalProgressRingAnimatorJob::updateCurrentTime(int time)
}
}
-void QQuickUniversalProgressRingAnimatorJob::writeBack()
+void QQuickUniversalBusyIndicatorNode::sync(QQuickItem *item)
{
-}
+ QQuickUniversalBusyIndicator *indicator = static_cast<QQuickUniversalBusyIndicator *>(item);
+ QQuickItemPrivate *d = QQuickItemPrivate::get(item);
-void QQuickUniversalProgressRingAnimatorJob::nodeWasDestroyed()
-{
- m_node = nullptr;
-}
+ QMatrix4x4 matrix;
+ matrix.translate(item->width() / 2, item->height() / 2);
+ setMatrix(matrix);
-void QQuickUniversalProgressRingAnimatorJob::afterNodeSync()
-{
- m_node = QQuickItemPrivate::get(m_target)->childContainerNode();
-}
+ qreal size = qMin(item->width(), item->height());
+ qreal diameter = size / 10.0;
+ qreal radius = diameter / 2;
+ qreal offset = (size - diameter * 2) / M_PI;
+ const QRectF rect(offset, offset, diameter, diameter);
-QQuickUniversalProgressRingAnimator::QQuickUniversalProgressRingAnimator(QObject *parent)
- : QQuickAnimator(parent)
-{
- setDuration(TotalDuration);
- setLoops(QQuickAnimator::Infinite);
-}
+ int count = indicator->count();
+ QSGNode *transformNode = firstChild();
+ for (int i = 0; i < count; ++i) {
+ if (!transformNode) {
+ transformNode = new QSGTransformNode;
+ appendChildNode(transformNode);
-QString QQuickUniversalProgressRingAnimator::propertyName() const
-{
- return QString();
-}
+ QSGOpacityNode *opacityNode = new QSGOpacityNode;
+ transformNode->appendChildNode(opacityNode);
-QQuickAnimatorJob *QQuickUniversalProgressRingAnimator::createJob() const
-{
- return new QQuickUniversalProgressRingAnimatorJob;
+ QSGInternalRectangleNode *rectNode = d->sceneGraphContext()->createInternalRectangleNode();
+ rectNode->setAntialiasing(true);
+ opacityNode->appendChildNode(rectNode);
+ }
+
+ QSGNode *opacityNode = transformNode->firstChild();
+ Q_ASSERT(opacityNode->type() == QSGNode::OpacityNodeType);
+
+ QSGInternalRectangleNode *rectNode = static_cast<QSGInternalRectangleNode *>(opacityNode->firstChild());
+ Q_ASSERT(rectNode->type() == QSGNode::GeometryNodeType);
+
+ rectNode->setRect(rect);
+ rectNode->setColor(indicator->color());
+ rectNode->setRadius(radius);
+ rectNode->update();
+
+ transformNode = transformNode->nextSibling();
+ }
+
+ while (transformNode) {
+ QSGNode *nextSibling = transformNode->nextSibling();
+ delete transformNode;
+ transformNode = nextSibling;
+ }
}
-QQuickUniversalProgressRing::QQuickUniversalProgressRing(QQuickItem *parent)
- : QQuickItem(parent), m_count(5), m_color(Qt::black)
+QQuickUniversalBusyIndicator::QQuickUniversalBusyIndicator(QQuickItem *parent)
+ : QQuickItem(parent), m_count(5), m_elapsed(0), m_color(Qt::black)
{
setFlag(ItemHasContents);
}
-int QQuickUniversalProgressRing::count() const
+int QQuickUniversalBusyIndicator::count() const
{
return m_count;
}
-void QQuickUniversalProgressRing::setCount(int count)
+void QQuickUniversalBusyIndicator::setCount(int count)
{
if (m_count == count)
return;
m_count = count;
update();
- emit countChanged();
}
-QColor QQuickUniversalProgressRing::color() const
+QColor QQuickUniversalBusyIndicator::color() const
{
return m_color;
}
-void QQuickUniversalProgressRing::setColor(const QColor &color)
+void QQuickUniversalBusyIndicator::setColor(const QColor &color)
{
if (m_color == color)
return;
m_color = color;
update();
- emit colorChanged();
}
-QSGNode *QQuickUniversalProgressRing::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
+int QQuickUniversalBusyIndicator::elapsed() const
{
- QQuickItemPrivate *d = QQuickItemPrivate::get(this);
-
- if (!oldNode)
- oldNode = new QSGTransformNode;
- Q_ASSERT(oldNode->type() == QSGNode::TransformNodeType);
-
- QMatrix4x4 matrix;
- matrix.translate(width() / 2, height() / 2);
- static_cast<QSGTransformNode *>(oldNode)->setMatrix(matrix);
-
- qreal size = qMin(width(), height());
- qreal diameter = size / 10.0;
- qreal radius = diameter / 2;
- qreal offset = (size - diameter * 2) / M_PI;
- const QRectF rect(offset, offset, diameter, diameter);
-
- QSGNode *transformNode = oldNode->firstChild();
- for (int i = 0; i < m_count; ++i) {
- if (!transformNode) {
- transformNode = new QSGTransformNode;
- oldNode->appendChildNode(transformNode);
+ return m_elapsed;
+}
- QSGOpacityNode *opacityNode = new QSGOpacityNode;
- transformNode->appendChildNode(opacityNode);
+void QQuickUniversalBusyIndicator::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data)
+{
+ QQuickItem::itemChange(change, data);
+ if (change == ItemVisibleHasChanged)
+ update();
+}
- QSGInternalRectangleNode *rectNode = d->sceneGraphContext()->createInternalRectangleNode();
- rectNode->setAntialiasing(true);
- opacityNode->appendChildNode(rectNode);
+QSGNode *QQuickUniversalBusyIndicator::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
+{
+ QQuickUniversalBusyIndicatorNode *node = static_cast<QQuickUniversalBusyIndicatorNode *>(oldNode);
+ if (isVisible() && width() > 0 && height() > 0) {
+ if (!node) {
+ node = new QQuickUniversalBusyIndicatorNode(this);
+ node->start();
}
-
- QSGNode *opacityNode = transformNode->firstChild();
- Q_ASSERT(opacityNode->type() == QSGNode::OpacityNodeType);
-
- QSGInternalRectangleNode *rectNode = static_cast<QSGInternalRectangleNode *>(opacityNode->firstChild());
- Q_ASSERT(rectNode->type() == QSGNode::GeometryNodeType);
-
- rectNode->setRect(rect);
- rectNode->setColor(m_color);
- rectNode->setRadius(radius);
- rectNode->update();
-
- transformNode = transformNode->nextSibling();
+ node->sync(this);
+ } else {
+ m_elapsed = node ? node->currentTime() : 0;
+ delete node;
+ node = nullptr;
}
-
- while (transformNode) {
- QSGNode *nextSibling = transformNode->nextSibling();
- delete transformNode;
- transformNode = nextSibling;
- }
-
- return oldNode;
+ return node;
}
QT_END_NAMESPACE
diff --git a/src/imports/controls/universal/qquickuniversalprogressring_p.h b/src/imports/controls/universal/qquickuniversalbusyindicator_p.h
index e40e5085..22f27c29 100644
--- a/src/imports/controls/universal/qquickuniversalprogressring_p.h
+++ b/src/imports/controls/universal/qquickuniversalbusyindicator_p.h
@@ -34,8 +34,8 @@
**
****************************************************************************/
-#ifndef QQUICKUNIVERSALPROGRESSRING_P_H
-#define QQUICKUNIVERSALPROGRESSRING_P_H
+#ifndef QQUICKUNIVERSALBUSYINDICATOR_P_H
+#define QQUICKUNIVERSALBUSYINDICATOR_P_H
//
// W A R N I N G
@@ -49,18 +49,17 @@
//
#include <QtQuick/qquickitem.h>
-#include <QtQuick/private/qquickanimator_p.h>
QT_BEGIN_NAMESPACE
-class QQuickUniversalProgressRing : public QQuickItem
+class QQuickUniversalBusyIndicator : public QQuickItem
{
Q_OBJECT
- Q_PROPERTY(int count READ count WRITE setCount NOTIFY countChanged FINAL)
- Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged FINAL)
+ Q_PROPERTY(int count READ count WRITE setCount FINAL)
+ Q_PROPERTY(QColor color READ color WRITE setColor FINAL)
public:
- QQuickUniversalProgressRing(QQuickItem *parent = nullptr);
+ explicit QQuickUniversalBusyIndicator(QQuickItem *parent = nullptr);
int count() const;
void setCount(int count);
@@ -68,32 +67,20 @@ public:
QColor color() const;
void setColor(const QColor &color);
-Q_SIGNALS:
- void countChanged();
- void colorChanged();
+ int elapsed() const;
protected:
+ void itemChange(ItemChange change, const ItemChangeData &data) override;
QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) override;
private:
int m_count;
+ int m_elapsed;
QColor m_color;
};
-class QQuickUniversalProgressRingAnimator : public QQuickAnimator
-{
- Q_OBJECT
-
-public:
- QQuickUniversalProgressRingAnimator(QObject *parent = nullptr);
-
-protected:
- QString propertyName() const override;
- QQuickAnimatorJob *createJob() const override;
-};
-
QT_END_NAMESPACE
-QML_DECLARE_TYPE(QQuickUniversalProgressRing)
+QML_DECLARE_TYPE(QQuickUniversalBusyIndicator)
-#endif // QQUICKUNIVERSALPROGRESSRING_P_H
+#endif // QQUICKUNIVERSALBUSYINDICATOR_P_H
diff --git a/src/imports/controls/universal/qquickuniversalprogressstrip.cpp b/src/imports/controls/universal/qquickuniversalprogressbar.cpp
index 489b2737..25dfda6f 100644
--- a/src/imports/controls/universal/qquickuniversalprogressstrip.cpp
+++ b/src/imports/controls/universal/qquickuniversalprogressbar.cpp
@@ -34,14 +34,14 @@
**
****************************************************************************/
-#include "qquickuniversalprogressstrip_p.h"
+#include "qquickuniversalprogressbar_p.h"
#include <QtCore/qmath.h>
#include <QtCore/qeasingcurve.h>
#include <QtQuick/private/qquickitem_p.h>
-#include <QtQuick/private/qquickanimatorjob_p.h>
#include <QtQuick/private/qsgadaptationlayer_p.h>
#include <QtQuick/qsgrectanglenode.h>
+#include <QtQuickControls2/private/qquickanimatednode_p.h>
QT_BEGIN_NAMESPACE
@@ -57,16 +57,13 @@ static const qreal ContainerAnimationEndPosition = 0.435222; // relative
static const qreal EllipseAnimationWellPosition = 0.333333333333333; // relative
static const qreal EllipseAnimationEndPosition = 0.666666666666667; // relative
-class QQuickUniversalProgressStripAnimatorJob : public QQuickAnimatorJob
+class QQuickUniversalProgressBarNode : public QQuickAnimatedNode
{
public:
- QQuickUniversalProgressStripAnimatorJob();
+ QQuickUniversalProgressBarNode(QQuickUniversalProgressBar *item);
- void initialize(QQuickAnimatorController *controller) override;
void updateCurrentTime(int time) override;
- void writeBack() override;
- void nodeWasDestroyed() override;
- void afterNodeSync() override;
+ void sync(QQuickItem *item) override;
private:
struct Phase {
@@ -77,13 +74,18 @@ private:
qreal to;
};
- QSGNode *m_node;
+ bool m_indeterminate;
Phase m_borderPhases[PhaseCount];
Phase m_ellipsePhases[PhaseCount];
};
-QQuickUniversalProgressStripAnimatorJob::QQuickUniversalProgressStripAnimatorJob() : m_node(nullptr)
+QQuickUniversalProgressBarNode::QQuickUniversalProgressBarNode(QQuickUniversalProgressBar *item)
+ : QQuickAnimatedNode(item),
+ m_indeterminate(false)
{
+ setLoopCount(Infinite);
+ setDuration(TotalDuration);
+
m_borderPhases[0] = Phase( 500, -50, 0);
m_borderPhases[1] = Phase(1500, 0, 0);
m_borderPhases[2] = Phase(1000, 0, 100);
@@ -95,18 +97,9 @@ QQuickUniversalProgressStripAnimatorJob::QQuickUniversalProgressStripAnimatorJob
m_ellipsePhases[3] = Phase(1000, EllipseAnimationWellPosition, EllipseAnimationEndPosition);
}
-void QQuickUniversalProgressStripAnimatorJob::initialize(QQuickAnimatorController *controller)
-{
- QQuickAnimatorJob::initialize(controller);
- m_node = QQuickItemPrivate::get(m_target)->childContainerNode();
-}
-
-void QQuickUniversalProgressStripAnimatorJob::updateCurrentTime(int time)
+void QQuickUniversalProgressBarNode::updateCurrentTime(int time)
{
- if (!m_node)
- return;
-
- QSGRectangleNode *geometryNode = static_cast<QSGRectangleNode *>(m_node->firstChild());
+ QSGRectangleNode *geometryNode = static_cast<QSGRectangleNode *>(firstChild());
Q_ASSERT(!geometryNode || geometryNode->type() == QSGNode::GeometryNodeType);
if (!geometryNode)
return;
@@ -197,105 +190,37 @@ void QQuickUniversalProgressStripAnimatorJob::updateCurrentTime(int time)
}
}
-void QQuickUniversalProgressStripAnimatorJob::writeBack()
-{
-}
-
-void QQuickUniversalProgressStripAnimatorJob::nodeWasDestroyed()
-{
- m_node = nullptr;
-}
-
-void QQuickUniversalProgressStripAnimatorJob::afterNodeSync()
-{
- m_node = QQuickItemPrivate::get(m_target)->childContainerNode();
-}
-
-QQuickUniversalProgressStripAnimator::QQuickUniversalProgressStripAnimator(QObject *parent)
- : QQuickAnimator(parent)
-{
- setDuration(TotalDuration);
- setLoops(QQuickAnimator::Infinite);
-}
-
-QString QQuickUniversalProgressStripAnimator::propertyName() const
-{
- return QString();
-}
-
-QQuickAnimatorJob *QQuickUniversalProgressStripAnimator::createJob() const
-{
- return new QQuickUniversalProgressStripAnimatorJob;
-}
-
-QQuickUniversalProgressStrip::QQuickUniversalProgressStrip(QQuickItem *parent)
- : QQuickItem(parent), m_color(Qt::black), m_progress(0.0), m_indeterminate(false)
-{
- setFlag(ItemHasContents);
-}
-
-QColor QQuickUniversalProgressStrip::color() const
-{
- return m_color;
-}
-
-void QQuickUniversalProgressStrip::setColor(const QColor &color)
-{
- if (m_color == color)
- return;
-
- m_color = color;
- update();
-}
-
-qreal QQuickUniversalProgressStrip::progress() const
-{
- return m_progress;
-}
-
-void QQuickUniversalProgressStrip::setProgress(qreal progress)
-{
- if (progress == m_progress)
- return;
-
- m_progress = progress;
- update();
-}
-
-bool QQuickUniversalProgressStrip::isIndeterminate() const
-{
- return m_indeterminate;
-}
-
-void QQuickUniversalProgressStrip::setIndeterminate(bool indeterminate)
+void QQuickUniversalProgressBarNode::sync(QQuickItem *item)
{
- if (indeterminate == m_indeterminate)
- return;
-
- m_indeterminate = indeterminate;
- update();
-}
+ QQuickUniversalProgressBar *bar = static_cast<QQuickUniversalProgressBar *>(item);
+ if (m_indeterminate != bar->isIndeterminate()) {
+ m_indeterminate = bar->isIndeterminate();
+ if (m_indeterminate)
+ start();
+ else
+ stop();
+ }
-QSGNode *QQuickUniversalProgressStrip::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
-{
- QQuickItemPrivate *d = QQuickItemPrivate::get(this);
+ QQuickItemPrivate *d = QQuickItemPrivate::get(item);
- QRectF bounds = boundingRect();
- bounds.setHeight(implicitHeight());
- bounds.moveTop((height() - bounds.height()) / 2.0);
+ QRectF bounds = item->boundingRect();
+ bounds.setHeight(item->implicitHeight());
+ bounds.moveTop((item->height() - bounds.height()) / 2.0);
if (!m_indeterminate)
- bounds.setWidth(m_progress * bounds.width());
+ bounds.setWidth(bar->progress() * bounds.width());
- QSGRectangleNode *geometryNode = static_cast<QSGRectangleNode *>(oldNode);
- if (!geometryNode)
- geometryNode = window()->createRectangleNode();
+ QSGRectangleNode *geometryNode = static_cast<QSGRectangleNode *>(firstChild());
+ if (!geometryNode) {
+ geometryNode = item->window()->createRectangleNode();
+ appendChildNode(geometryNode);
+ }
geometryNode->setRect(bounds);
- geometryNode->setColor(m_indeterminate ? Qt::transparent : m_color);
+ geometryNode->setColor(m_indeterminate ? Qt::transparent : bar->color());
if (!m_indeterminate) {
while (QSGNode *node = geometryNode->firstChild())
delete node;
- return geometryNode;
+ return;
}
QSGTransformNode *gridNode = static_cast<QSGTransformNode *>(geometryNode->firstChild());
@@ -333,14 +258,82 @@ QSGNode *QQuickUniversalProgressStrip::updatePaintNode(QSGNode *oldNode, UpdateP
QSGInternalRectangleNode *rectNode = static_cast<QSGInternalRectangleNode *>(opacityNode->firstChild());
Q_ASSERT(rectNode->type() == QSGNode::GeometryNodeType);
- rectNode->setRect(QRectF((EllipseCount - i - 1) * (EllipseDiameter + EllipseOffset), (height() - EllipseDiameter) / 2, EllipseDiameter, EllipseDiameter));
- rectNode->setColor(m_color);
+ rectNode->setRect(QRectF((EllipseCount - i - 1) * (EllipseDiameter + EllipseOffset), (item->height() - EllipseDiameter) / 2, EllipseDiameter, EllipseDiameter));
+ rectNode->setColor(bar->color());
rectNode->update();
borderNode = borderNode->nextSibling();
}
+}
+
+QQuickUniversalProgressBar::QQuickUniversalProgressBar(QQuickItem *parent)
+ : QQuickItem(parent), m_color(Qt::black), m_progress(0.0), m_indeterminate(false)
+{
+ setFlag(ItemHasContents);
+}
+
+QColor QQuickUniversalProgressBar::color() const
+{
+ return m_color;
+}
+
+void QQuickUniversalProgressBar::setColor(const QColor &color)
+{
+ if (m_color == color)
+ return;
+
+ m_color = color;
+ update();
+}
- return geometryNode;
+qreal QQuickUniversalProgressBar::progress() const
+{
+ return m_progress;
+}
+
+void QQuickUniversalProgressBar::setProgress(qreal progress)
+{
+ if (progress == m_progress)
+ return;
+
+ m_progress = progress;
+ update();
+}
+
+bool QQuickUniversalProgressBar::isIndeterminate() const
+{
+ return m_indeterminate;
+}
+
+void QQuickUniversalProgressBar::setIndeterminate(bool indeterminate)
+{
+ if (indeterminate == m_indeterminate)
+ return;
+
+ m_indeterminate = indeterminate;
+ setClip(m_indeterminate);
+ update();
+}
+
+void QQuickUniversalProgressBar::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data)
+{
+ QQuickItem::itemChange(change, data);
+ if (change == ItemVisibleHasChanged)
+ update();
+}
+
+QSGNode *QQuickUniversalProgressBar::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *)
+{
+ QQuickUniversalProgressBarNode *node = static_cast<QQuickUniversalProgressBarNode *>(oldNode);
+ if (isVisible() && width() > 0 && height() > 0) {
+ if (!node)
+ node = new QQuickUniversalProgressBarNode(this);
+ node->sync(this);
+ } else {
+ delete node;
+ node = nullptr;
+ }
+ return node;
}
QT_END_NAMESPACE
diff --git a/src/imports/controls/universal/qquickuniversalprogressstrip_p.h b/src/imports/controls/universal/qquickuniversalprogressbar_p.h
index d4041d6a..f69fb87c 100644
--- a/src/imports/controls/universal/qquickuniversalprogressstrip_p.h
+++ b/src/imports/controls/universal/qquickuniversalprogressbar_p.h
@@ -34,8 +34,8 @@
**
****************************************************************************/
-#ifndef QQUICKUNIVERSALPROGRESSSTRIP_P_H
-#define QQUICKUNIVERSALPROGRESSSTRIP_P_H
+#ifndef QQUICKUNIVERSALPROGRESSBAR_P_H
+#define QQUICKUNIVERSALPROGRESSBAR_P_H
//
// W A R N I N G
@@ -49,11 +49,10 @@
//
#include <QtQuick/qquickitem.h>
-#include <QtQuick/private/qquickanimator_p.h>
QT_BEGIN_NAMESPACE
-class QQuickUniversalProgressStrip : public QQuickItem
+class QQuickUniversalProgressBar : public QQuickItem
{
Q_OBJECT
Q_PROPERTY(QColor color READ color WRITE setColor FINAL)
@@ -61,7 +60,7 @@ class QQuickUniversalProgressStrip : public QQuickItem
Q_PROPERTY(bool indeterminate READ isIndeterminate WRITE setIndeterminate FINAL)
public:
- QQuickUniversalProgressStrip(QQuickItem *parent = nullptr);
+ explicit QQuickUniversalProgressBar(QQuickItem *parent = nullptr);
QColor color() const;
void setColor(const QColor &color);
@@ -73,6 +72,7 @@ public:
void setIndeterminate(bool indeterminate);
protected:
+ void itemChange(ItemChange change, const ItemChangeData &data) override;
QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) override;
private:
@@ -81,21 +81,8 @@ private:
bool m_indeterminate;
};
-class QQuickUniversalProgressStripAnimator : public QQuickAnimator
-{
- Q_OBJECT
-
-public:
- QQuickUniversalProgressStripAnimator(QObject *parent = nullptr);
-
-protected:
- QString propertyName() const override;
- QQuickAnimatorJob *createJob() const override;
-};
-
QT_END_NAMESPACE
-QML_DECLARE_TYPE(QQuickUniversalProgressStrip)
-QML_DECLARE_TYPE(QQuickUniversalProgressStripAnimator)
+QML_DECLARE_TYPE(QQuickUniversalProgressBar)
-#endif // QQUICKUNIVERSALPROGRESSSTRIP_P_H
+#endif // QQUICKUNIVERSALPROGRESSBAR_P_H
diff --git a/src/imports/controls/universal/qtquickcontrols2universalstyleplugin.cpp b/src/imports/controls/universal/qtquickcontrols2universalstyleplugin.cpp
index 81d61169..29f2b7cc 100644
--- a/src/imports/controls/universal/qtquickcontrols2universalstyleplugin.cpp
+++ b/src/imports/controls/universal/qtquickcontrols2universalstyleplugin.cpp
@@ -36,9 +36,9 @@
#include <QtQuickControls2/private/qquickstyleplugin_p.h>
+#include "qquickuniversalbusyindicator_p.h"
#include "qquickuniversalfocusrectangle_p.h"
-#include "qquickuniversalprogressring_p.h"
-#include "qquickuniversalprogressstrip_p.h"
+#include "qquickuniversalprogressbar_p.h"
#include "qquickuniversalstyle_p.h"
#include "qquickuniversaltheme_p.h"
@@ -76,8 +76,8 @@ QtQuickControls2UniversalStylePlugin::QtQuickControls2UniversalStylePlugin(QObje
void QtQuickControls2UniversalStylePlugin::registerTypes(const char *uri)
{
+ qmlRegisterModule(uri, 2, QT_VERSION_MINOR - 7); // Qt 5.7->2.0, 5.8->2.1, 5.9->2.2...
qmlRegisterUncreatableType<QQuickUniversalStyle>(uri, 2, 0, "Universal", tr("Universal is an attached property"));
- qmlRegisterRevision<QQuickUniversalStyle, 1>(uri, 2, 1);
}
void QtQuickControls2UniversalStylePlugin::initializeEngine(QQmlEngine *engine, const char *uri)
@@ -87,13 +87,11 @@ void QtQuickControls2UniversalStylePlugin::initializeEngine(QQmlEngine *engine,
engine->addImageProvider(name(), new QQuickColorImageProvider(QStringLiteral(":/qt-project.org/imports/QtQuick/Controls.2/Universal/images")));
QByteArray import = QByteArray(uri) + ".impl";
- qmlRegisterType<QQuickUniversalFocusRectangle>(import, 2, 0, "FocusRectangle");
- qmlRegisterRevision<QQuickUniversalFocusRectangle, 1>(import, 2, 1);
- qmlRegisterType<QQuickUniversalProgressRing>(import, 2, 0, "ProgressRing");
- qmlRegisterType<QQuickUniversalProgressRingAnimator>(import, 2, 0, "ProgressRingAnimator");
- qmlRegisterType<QQuickUniversalProgressStrip>(import, 2, 0, "ProgressStrip");
- qmlRegisterType<QQuickUniversalProgressStripAnimator>(import, 2, 0, "ProgressStripAnimator");
+ qmlRegisterModule(import, 2, QT_VERSION_MINOR - 7); // Qt 5.7->2.0, 5.8->2.1, 5.9->2.2...
+ qmlRegisterType<QQuickUniversalFocusRectangle>(import, 2, 0, "FocusRectangle");
+ qmlRegisterType<QQuickUniversalBusyIndicator>(import, 2, 0, "BusyIndicatorImpl");
+ qmlRegisterType<QQuickUniversalProgressBar>(import, 2, 0, "ProgressBarImpl");
qmlRegisterType(typeUrl(QStringLiteral("RadioIndicator.qml")), import, 2, 0, "RadioIndicator");
qmlRegisterType(typeUrl(QStringLiteral("SwitchIndicator.qml")), import, 2, 0, "SwitchIndicator");
}
diff --git a/src/imports/controls/universal/universal.pri b/src/imports/controls/universal/universal.pri
index 3697a2a6..c80a2dfc 100644
--- a/src/imports/controls/universal/universal.pri
+++ b/src/imports/controls/universal/universal.pri
@@ -6,6 +6,7 @@ QML_FILES += \
$$PWD/CheckDelegate.qml \
$$PWD/CheckIndicator.qml \
$$PWD/ComboBox.qml \
+ $$PWD/DelayButton.qml \
$$PWD/Dial.qml \
$$PWD/Dialog.qml \
$$PWD/DialogButtonBox.qml \
@@ -47,15 +48,15 @@ QML_FILES += \
$$PWD/Tumbler.qml
HEADERS += \
+ $$PWD/qquickuniversalbusyindicator_p.h \
$$PWD/qquickuniversalfocusrectangle_p.h \
- $$PWD/qquickuniversalprogressring_p.h \
- $$PWD/qquickuniversalprogressstrip_p.h \
+ $$PWD/qquickuniversalprogressbar_p.h \
$$PWD/qquickuniversalstyle_p.h \
$$PWD/qquickuniversaltheme_p.h
SOURCES += \
+ $$PWD/qquickuniversalbusyindicator.cpp \
$$PWD/qquickuniversalfocusrectangle.cpp \
- $$PWD/qquickuniversalprogressring.cpp \
- $$PWD/qquickuniversalprogressstrip.cpp \
+ $$PWD/qquickuniversalprogressbar.cpp \
$$PWD/qquickuniversalstyle.cpp \
$$PWD/qquickuniversaltheme.cpp
diff --git a/src/imports/platform/qquickplatformmenuitem.cpp b/src/imports/platform/qquickplatformmenuitem.cpp
index ecd30e71..0fb92af8 100644
--- a/src/imports/platform/qquickplatformmenuitem.cpp
+++ b/src/imports/platform/qquickplatformmenuitem.cpp
@@ -404,7 +404,7 @@ void QQuickPlatformMenuItem::setChecked(bool checked)
\value MenuItem.AboutRole The item should be placed where the "About" menu item is in the application menu. The text of
the menu item will be set to "About <application name>". The application name is fetched from the
\c{Info.plist} file in the application's bundle (See \l{Qt for macOS - Deployment}).
- \value MenuItem.PreferencesRole The item should be placed where the "Preferences..." menu item is in the application menu.
+ \value MenuItem.PreferencesRole The item should be placed where the "Preferences..." menu item is in the application menu.
\value MenuItem.QuitRole The item should be placed where the Quit menu item is in the application menu.
Specifying the role only has effect on items that are in the immediate
diff --git a/src/imports/templates/qtquicktemplates2plugin.cpp b/src/imports/templates/qtquicktemplates2plugin.cpp
index a9abda85..3166afd9 100644
--- a/src/imports/templates/qtquicktemplates2plugin.cpp
+++ b/src/imports/templates/qtquicktemplates2plugin.cpp
@@ -46,6 +46,7 @@
#include <QtQuickTemplates2/private/qquickcombobox_p.h>
#include <QtQuickTemplates2/private/qquickcontrol_p.h>
#include <QtQuickTemplates2/private/qquickcontainer_p.h>
+#include <QtQuickTemplates2/private/qquickdelaybutton_p.h>
#include <QtQuickTemplates2/private/qquickdial_p.h>
#include <QtQuickTemplates2/private/qquickdialog_p.h>
#include <QtQuickTemplates2/private/qquickdialogbuttonbox_p.h>
@@ -132,7 +133,9 @@ QtQuickTemplates2Plugin::~QtQuickTemplates2Plugin()
void QtQuickTemplates2Plugin::registerTypes(const char *uri)
{
- // QtQuick.Templates 2.0 (Qt 5.7)
+ qmlRegisterModule(uri, 2, QT_VERSION_MINOR - 7); // Qt 5.7->2.0, 5.8->2.1, 5.9->2.2...
+
+ // QtQuick.Templates 2.0 (originally introduced in Qt 5.7)
qmlRegisterType<QQuickAbstractButton>(uri, 2, 0, "AbstractButton");
qmlRegisterType<QQuickApplicationWindow>(uri, 2, 0, "ApplicationWindow");
qmlRegisterType<QQuickApplicationWindowAttached>();
@@ -171,7 +174,7 @@ void QtQuickTemplates2Plugin::registerTypes(const char *uri)
qmlRegisterType<QQuickSpinBox>(uri, 2, 0, "SpinBox");
qmlRegisterType<QQuickSpinButton>();
qmlRegisterType<QQuickStackView>(uri, 2, 0, "StackView");
- qmlRegisterType<QQuickStackAttached>();
+ qmlRegisterType<QQuickStackViewAttached>();
qmlRegisterType<QQuickSwipeDelegate>(uri, 2, 0, "SwipeDelegate");
qmlRegisterType<QQuickSwipe>();
qmlRegisterType<QQuickSwipeViewAttached>();
@@ -198,7 +201,7 @@ void QtQuickTemplates2Plugin::registerTypes(const char *uri)
qmlRegisterRevision<QQuickTextInput, 7>(uri, 2, 0);
qmlRegisterRevision<QQuickTextEdit, 7>(uri, 2, 0);
- // QtQuick.Templates 2.1 (Qt 5.8)
+ // QtQuick.Templates 2.1 (new types and revisions in Qt 5.8)
qmlRegisterType<QQuickButtonGroup, 1>(uri, 2, 1, "ButtonGroup");
qmlRegisterType<QQuickComboBox, 1>(uri, 2, 1, "ComboBox");
qmlRegisterType<QQuickContainer, 1>(uri, 2, 1, "Container");
@@ -219,6 +222,20 @@ void QtQuickTemplates2Plugin::registerTypes(const char *uri)
qmlRegisterType<QQuickTextField, 1>(uri, 2, 1, "TextField");
qmlRegisterType<QQuickToolSeparator>(uri, 2, 1, "ToolSeparator");
qmlRegisterType<QQuickTumbler, 1>(uri, 2, 1, "Tumbler");
+
+ // QtQuick.Templates 2.2 (new types and revisions in Qt 5.9)
+ qmlRegisterRevision<QQuickAbstractButton, 2>(uri, 2, 2);
+ qmlRegisterType<QQuickComboBox, 2>(uri, 2, 2, "ComboBox");
+ qmlRegisterType<QQuickDelayButton>(uri, 2, 2, "DelayButton");
+ qmlRegisterType<QQuickDial, 2>(uri, 2, 2, "Dial");
+ qmlRegisterType<QQuickDrawer, 2>(uri, 2, 2, "Drawer");
+ qmlRegisterType<QQuickRangeSlider, 2>(uri, 2, 2, "RangeSlider");
+ qmlRegisterType<QQuickScrollBar, 2>(uri, 2, 2, "ScrollBar");
+ qmlRegisterType<QQuickSlider, 2>(uri, 2, 2, "Slider");
+ qmlRegisterType<QQuickSpinBox, 2>(uri, 2, 2, "SpinBox");
+ qmlRegisterType<QQuickSwipeDelegate, 2>(uri, 2, 2, "SwipeDelegate");
+ qmlRegisterType<QQuickTabBar, 2>(uri, 2, 2, "TabBar");
+ qmlRegisterType<QQuickTumbler, 2>(uri, 2, 2, "Tumbler");
}
QT_END_NAMESPACE
diff --git a/src/quickcontrols2/qquickanimatednode.cpp b/src/quickcontrols2/qquickanimatednode.cpp
new file mode 100644
index 00000000..2c5cdc67
--- /dev/null
+++ b/src/quickcontrols2/qquickanimatednode.cpp
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickanimatednode_p.h"
+
+#include <QtQuick/qquickitem.h>
+#include <QtQuick/qquickwindow.h>
+
+// based on qtdeclarative/examples/quick/scenegraph/threadedanimation
+
+QT_BEGIN_NAMESPACE
+
+QQuickAnimatedNode::QQuickAnimatedNode(QQuickItem *target)
+ : m_running(false),
+ m_duration(0),
+ m_loopCount(1),
+ m_currentTime(0),
+ m_currentLoop(0),
+ m_window(target->window())
+{
+}
+
+bool QQuickAnimatedNode::isRunning() const
+{
+ return m_running;
+}
+
+int QQuickAnimatedNode::currentTime() const
+{
+ int time = m_currentTime;
+ if (m_running)
+ time += m_timer.elapsed();
+ return time;
+}
+
+void QQuickAnimatedNode::setCurrentTime(int time)
+{
+ m_currentTime = time;
+ m_timer.restart();
+}
+
+int QQuickAnimatedNode::duration() const
+{
+ return m_duration;
+}
+
+void QQuickAnimatedNode::setDuration(int duration)
+{
+ m_duration = duration;
+}
+
+int QQuickAnimatedNode::loopCount() const
+{
+ return m_loopCount;
+}
+
+void QQuickAnimatedNode::setLoopCount(int count)
+{
+ m_loopCount = count;
+}
+
+void QQuickAnimatedNode::sync(QQuickItem *target)
+{
+ Q_UNUSED(target);
+}
+
+QQuickWindow *QQuickAnimatedNode::window() const
+{
+ return m_window;
+}
+
+void QQuickAnimatedNode::start(int duration)
+{
+ if (m_running)
+ return;
+
+ m_running = true;
+ m_currentLoop = 0;
+ m_timer.restart();
+ if (duration > 0)
+ m_duration = duration;
+ connect(m_window, &QQuickWindow::beforeRendering, this, &QQuickAnimatedNode::advance);
+ connect(m_window, &QQuickWindow::frameSwapped, this, &QQuickAnimatedNode::update);
+ emit started();
+}
+
+void QQuickAnimatedNode::restart()
+{
+ stop();
+ start();
+}
+
+void QQuickAnimatedNode::stop()
+{
+ if (!m_running)
+ return;
+
+ m_running = false;
+ disconnect(m_window, &QQuickWindow::beforeRendering, this, &QQuickAnimatedNode::advance);
+ disconnect(m_window, &QQuickWindow::frameSwapped, this, &QQuickAnimatedNode::update);
+ emit stopped();
+}
+
+void QQuickAnimatedNode::updateCurrentTime(int time)
+{
+ Q_UNUSED(time);
+}
+
+void QQuickAnimatedNode::advance()
+{
+ int time = currentTime();
+ if (time > m_duration) {
+ time = 0;
+ setCurrentTime(0);
+
+ if (m_loopCount > 0 && ++m_currentLoop >= m_loopCount) {
+ time = m_duration; // complete
+ stop();
+ }
+ }
+ updateCurrentTime(time);
+}
+
+void QQuickAnimatedNode::update()
+{
+ if (m_running)
+ m_window->update();
+}
+
+QT_END_NAMESPACE
diff --git a/src/quickcontrols2/qquickanimatednode_p.h b/src/quickcontrols2/qquickanimatednode_p.h
new file mode 100644
index 00000000..24b404c9
--- /dev/null
+++ b/src/quickcontrols2/qquickanimatednode_p.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKANIMATEDNODE_P_H
+#define QQUICKANIMATEDNODE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQuick/qsgnode.h>
+#include <QtCore/qelapsedtimer.h>
+#include <QtQuickControls2/private/qtquickcontrols2global_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickItem;
+class QQuickWindow;
+
+class Q_QUICKCONTROLS2_PRIVATE_EXPORT QQuickAnimatedNode : public QObject, public QSGTransformNode
+{
+ Q_OBJECT
+
+public:
+ explicit QQuickAnimatedNode(QQuickItem *target);
+
+ bool isRunning() const;
+
+ int currentTime() const;
+ void setCurrentTime(int time);
+
+ int duration() const;
+ void setDuration(int duration);
+
+ enum LoopCount { Infinite = -1 };
+
+ int loopCount() const;
+ void setLoopCount(int count);
+
+ virtual void sync(QQuickItem *target);
+
+ QQuickWindow *window() const;
+
+ // must be called from sync() or updatePaintNode()
+ void start(int duration = 0);
+ void restart();
+ void stop();
+
+Q_SIGNALS:
+ void started();
+ void stopped();
+
+protected:
+ virtual void updateCurrentTime(int time);
+
+private Q_SLOTS:
+ void advance();
+ void update();
+
+private:
+ bool m_running;
+ int m_duration;
+ int m_loopCount;
+ int m_currentTime;
+ int m_currentLoop;
+ QElapsedTimer m_timer;
+ QQuickWindow *m_window;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKANIMATEDNODE_P_H
diff --git a/src/quickcontrols2/qquickplaceholdertext.cpp b/src/quickcontrols2/qquickplaceholdertext.cpp
new file mode 100644
index 00000000..2fe6be07
--- /dev/null
+++ b/src/quickcontrols2/qquickplaceholdertext.cpp
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickplaceholdertext_p.h"
+
+#include <QtQuick/private/qquicktext_p_p.h>
+#include <QtQuick/private/qquicktextinput_p_p.h>
+#include <QtQuick/private/qquicktextedit_p_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QQuickPlaceholderText::QQuickPlaceholderText(QQuickItem *parent) : QQuickText(parent)
+{
+}
+
+void QQuickPlaceholderText::componentComplete()
+{
+ QQuickText::componentComplete();
+ connect(parentItem(), SIGNAL(effectiveHorizontalAlignmentChanged()), this, SLOT(updateAlignment()));
+ updateAlignment();
+}
+
+void QQuickPlaceholderText::updateAlignment()
+{
+ if (QQuickTextInput *input = qobject_cast<QQuickTextInput *>(parentItem())) {
+ if (QQuickTextInputPrivate::get(input)->hAlignImplicit)
+ resetHAlign();
+ else
+ setHAlign(static_cast<HAlignment>(input->hAlign()));
+ } else if (QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(parentItem())) {
+ if (QQuickTextEditPrivate::get(edit)->hAlignImplicit)
+ resetHAlign();
+ else
+ setHAlign(static_cast<HAlignment>(edit->hAlign()));
+ } else {
+ resetHAlign();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/quickcontrols2/qquickplaceholdertext_p.h b/src/quickcontrols2/qquickplaceholdertext_p.h
new file mode 100644
index 00000000..1e49286c
--- /dev/null
+++ b/src/quickcontrols2/qquickplaceholdertext_p.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKPLACEHOLDERTEXT_P_H
+#define QQUICKPLACEHOLDERTEXT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQuick/private/qquicktext_p.h>
+#include <QtQuickControls2/private/qtquickcontrols2global_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICKCONTROLS2_PRIVATE_EXPORT QQuickPlaceholderText : public QQuickText
+{
+ Q_OBJECT
+
+public:
+ explicit QQuickPlaceholderText(QQuickItem *parent = nullptr);
+
+protected:
+ void componentComplete() override;
+
+private Q_SLOTS:
+ void updateAlignment();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickPlaceholderText)
+
+#endif // QQUICKPLACEHOLDERTEXT_P_H
diff --git a/src/quickcontrols2/qquickstyle.cpp b/src/quickcontrols2/qquickstyle.cpp
index 5eb85701..f6539ffc 100644
--- a/src/quickcontrols2/qquickstyle.cpp
+++ b/src/quickcontrols2/qquickstyle.cpp
@@ -205,12 +205,11 @@ struct QQuickStyleSpec
if (QGuiApplication::instance()) {
if (!custom) {
- const QString targetPath = QStringLiteral("QtQuick/Controls.2");
- const QStringList importPaths = defaultImportPathList();
-
- for (const QString &importPath : importPaths) {
- QString stylePath = findStyle(importPath + QLatin1Char('/') + targetPath, style);
+ const QStringList stylePaths = QQuickStylePrivate::stylePaths();
+ for (const QString &path : stylePaths) {
+ QString stylePath = findStyle(path, style);
if (!stylePath.isEmpty()) {
+ custom = !stylePath.startsWith(baseUrl.toLocalFile());
style = stylePath;
resolved = true;
break;
@@ -254,6 +253,27 @@ struct QQuickStyleSpec
Q_GLOBAL_STATIC(QQuickStyleSpec, styleSpec)
+QStringList QQuickStylePrivate::stylePaths()
+{
+ // system/custom style paths
+ QStringList paths;
+ if (Q_UNLIKELY(!qEnvironmentVariableIsEmpty("QT_QUICK_CONTROLS_STYLE_PATH"))) {
+ const QByteArray value = qgetenv("QT_QUICK_CONTROLS_STYLE_PATH");
+ paths += QString::fromLatin1(value).split(QDir::listSeparator(), QString::SkipEmptyParts);
+ }
+
+ // built-in import paths
+ const QString targetPath = QStringLiteral("QtQuick/Controls.2");
+ const QStringList importPaths = defaultImportPathList();
+ for (const QString &importPath : importPaths) {
+ QDir dir(importPath);
+ if (dir.cd(targetPath))
+ paths += dir.absolutePath();
+ }
+
+ return paths;
+}
+
QString QQuickStylePrivate::fallbackStyle()
{
return styleSpec()->fallbackStyle;
@@ -354,4 +374,29 @@ void QQuickStyle::setFallbackStyle(const QString &style)
styleSpec()->setFallbackStyle(style, "QQuickStyle::setFallbackStyle()");
}
+/*!
+ \since 5.9
+ Returns the names of the available built-in styles.
+
+ \note The method must be called \b after creating an instance of QGuiApplication.
+*/
+QStringList QQuickStyle::availableStyles()
+{
+ QStringList styles;
+ if (!QGuiApplication::instance()) {
+ qWarning() << "ERROR: QQuickStyle::availableStyles() must be called after creating an instance of QGuiApplication.";
+ return styles;
+ }
+
+ const QStringList stylePaths = QQuickStylePrivate::stylePaths();
+ for (const QString &path : stylePaths) {
+ QDir dir(path);
+ styles += dir.entryList(QStringList(), QDir::Dirs | QDir::NoDotAndDotDot);
+ styles.removeAll(QStringLiteral("designer"));
+ }
+ styles.prepend(QStringLiteral("Default"));
+ styles.removeDuplicates();
+ return styles;
+}
+
QT_END_NAMESPACE
diff --git a/src/quickcontrols2/qquickstyle.h b/src/quickcontrols2/qquickstyle.h
index dfc7f053..ab79c3e0 100644
--- a/src/quickcontrols2/qquickstyle.h
+++ b/src/quickcontrols2/qquickstyle.h
@@ -50,6 +50,7 @@ public:
static QString path();
static void setStyle(const QString &style);
static void setFallbackStyle(const QString &style);
+ static QStringList availableStyles();
};
QT_END_NAMESPACE
diff --git a/src/quickcontrols2/qquickstyle_p.h b/src/quickcontrols2/qquickstyle_p.h
index dd1142e2..316783c4 100644
--- a/src/quickcontrols2/qquickstyle_p.h
+++ b/src/quickcontrols2/qquickstyle_p.h
@@ -56,6 +56,7 @@ QT_BEGIN_NAMESPACE
class Q_QUICKCONTROLS2_PRIVATE_EXPORT QQuickStylePrivate
{
public:
+ static QStringList stylePaths();
static QString fallbackStyle();
static bool isCustomStyle();
static void init(const QUrl &baseUrl);
diff --git a/src/quickcontrols2/qquickstyleselector_p_p.h b/src/quickcontrols2/qquickstyleselector_p_p.h
index a1e12310..b8f717c8 100644
--- a/src/quickcontrols2/qquickstyleselector_p_p.h
+++ b/src/quickcontrols2/qquickstyleselector_p_p.h
@@ -65,4 +65,3 @@ public:
QT_END_NAMESPACE
#endif // QQUICKSTYLESELECTOR_P_P_H
-
diff --git a/src/quickcontrols2/qquicktumblerview.cpp b/src/quickcontrols2/qquicktumblerview.cpp
index 2e379c6f..59f443d5 100644
--- a/src/quickcontrols2/qquicktumblerview.cpp
+++ b/src/quickcontrols2/qquicktumblerview.cpp
@@ -189,7 +189,7 @@ void QQuickTumblerView::updateView()
m_pathView->setDragMargin(width() / 2);
} else {
m_listView->setPreferredHighlightBegin(height() / 2 - (height() / m_tumbler->visibleItemCount() / 2));
- m_listView->setPreferredHighlightEnd(height() / 2 + (height() / m_tumbler->visibleItemCount() / 2));
+ m_listView->setPreferredHighlightEnd(height() / 2 + (height() / m_tumbler->visibleItemCount() / 2));
}
}
diff --git a/src/quickcontrols2/quickcontrols2.pri b/src/quickcontrols2/quickcontrols2.pri
index 8e4e0046..135318a7 100644
--- a/src/quickcontrols2/quickcontrols2.pri
+++ b/src/quickcontrols2/quickcontrols2.pri
@@ -1,5 +1,7 @@
HEADERS += \
+ $$PWD/qquickanimatednode_p.h \
$$PWD/qquickcolorimageprovider_p.h \
+ $$PWD/qquickplaceholdertext_p.h \
$$PWD/qquickproxytheme_p.h \
$$PWD/qquickstyle.h \
$$PWD/qquickstyle_p.h \
@@ -11,7 +13,9 @@ HEADERS += \
$$PWD/qquicktumblerview_p.h
SOURCES += \
+ $$PWD/qquickanimatednode.cpp \
$$PWD/qquickcolorimageprovider.cpp \
+ $$PWD/qquickplaceholdertext.cpp \
$$PWD/qquickproxytheme.cpp \
$$PWD/qquickstyle.cpp \
$$PWD/qquickstyleattached.cpp \
diff --git a/src/quicktemplates2/qquickabstractbutton.cpp b/src/quicktemplates2/qquickabstractbutton.cpp
index 6af8b00d..adc66da4 100644
--- a/src/quicktemplates2/qquickabstractbutton.cpp
+++ b/src/quicktemplates2/qquickabstractbutton.cpp
@@ -93,6 +93,13 @@ static const int AUTO_REPEAT_INTERVAL = 100;
*/
/*!
+ \since QtQuick.Controls 2.2
+ \qmlsignal QtQuick.Controls::AbstractButton::toggled()
+
+ This signal is emitted when a checkable button is interactively toggled by the user.
+*/
+
+/*!
\qmlsignal QtQuick.Controls::AbstractButton::pressAndHold()
This signal is emitted when the button is interactively pressed and held down by the user.
@@ -111,6 +118,70 @@ QQuickAbstractButtonPrivate::QQuickAbstractButtonPrivate() :
{
}
+void QQuickAbstractButtonPrivate::handlePress(const QPointF &point, Qt::MouseButton button, Qt::MouseButtons buttons)
+{
+ Q_Q(QQuickAbstractButton);
+ pressPoint = point;
+ q->setPressed(true);
+
+ emit q->pressed();
+
+ if (autoRepeat) {
+ startRepeatDelay();
+ repeatButton = button;
+ } else if (Qt::LeftButton == (buttons & Qt::LeftButton)) {
+ startPressAndHold();
+ } else {
+ stopPressAndHold();
+ }
+}
+
+void QQuickAbstractButtonPrivate::handleMove(const QPointF &point)
+{
+ Q_Q(QQuickAbstractButton);
+ q->setPressed(keepPressed || q->contains(point));
+
+ if (!pressed && autoRepeat)
+ stopPressRepeat();
+ else if (holdTimer > 0 && (!pressed || QLineF(pressPoint, point).length() > QGuiApplication::styleHints()->startDragDistance()))
+ stopPressAndHold();
+}
+
+void QQuickAbstractButtonPrivate::handleRelease(const QPointF &point)
+{
+ Q_Q(QQuickAbstractButton);
+ bool wasPressed = pressed;
+ q->setPressed(false);
+
+ if (!wasHeld && (keepPressed || q->contains(point)))
+ q->nextCheckState();
+
+ if (wasPressed) {
+ emit q->released();
+ if (!wasHeld)
+ emit q->clicked();
+ } else {
+ emit q->canceled();
+ }
+
+ if (autoRepeat)
+ stopPressRepeat();
+ else
+ stopPressAndHold();
+}
+
+void QQuickAbstractButtonPrivate::handleCancel()
+{
+ Q_Q(QQuickAbstractButton);
+ if (!pressed)
+ return;
+
+ q->setPressed(false);
+ stopPressRepeat();
+ stopPressAndHold();
+ emit q->canceled();
+}
+
bool QQuickAbstractButtonPrivate::isPressAndHoldConnected()
{
Q_Q(QQuickAbstractButton);
@@ -162,6 +233,15 @@ void QQuickAbstractButtonPrivate::stopPressRepeat()
}
}
+void QQuickAbstractButtonPrivate::toggle(bool value)
+{
+ Q_Q(QQuickAbstractButton);
+ const bool wasChecked = checked;
+ q->setChecked(value);
+ if (wasChecked != checked)
+ emit q->toggled();
+}
+
QQuickAbstractButton *QQuickAbstractButtonPrivate::findCheckedButton() const
{
Q_Q(const QQuickAbstractButton);
@@ -254,6 +334,7 @@ void QQuickAbstractButton::setText(const QString &text)
d->text = text;
setAccessibleName(text);
+ buttonChange(ButtonTextChange);
emit textChanged();
}
@@ -319,6 +400,7 @@ void QQuickAbstractButton::setPressed(bool isPressed)
d->pressed = isPressed;
setAccessibleProperty("pressed", isPressed);
emit pressedChanged();
+ buttonChange(ButtonPressedChanged);
if (!d->explicitDown) {
setDown(d->pressed);
@@ -350,7 +432,7 @@ void QQuickAbstractButton::setChecked(bool checked)
d->checked = checked;
setAccessibleProperty("checked", checked);
- checkStateSet();
+ buttonChange(ButtonCheckedChange);
emit checkedChanged();
}
@@ -383,7 +465,7 @@ void QQuickAbstractButton::setCheckable(bool checkable)
d->checkable = checkable;
setAccessibleProperty("checkable", checkable);
- checkableChange();
+ buttonChange(ButtonCheckableChange);
emit checkableChanged();
}
@@ -431,7 +513,7 @@ void QQuickAbstractButton::setAutoRepeat(bool repeat)
d->stopPressRepeat();
d->autoRepeat = repeat;
- autoRepeatChange();
+ buttonChange(ButtonAutoRepeatChange);
}
/*!
@@ -476,10 +558,7 @@ void QQuickAbstractButton::focusOutEvent(QFocusEvent *event)
{
Q_D(QQuickAbstractButton);
QQuickControl::focusOutEvent(event);
- if (d->pressed) {
- setPressed(false);
- emit canceled();
- }
+ d->handleCancel();
}
void QQuickAbstractButton::keyPressEvent(QKeyEvent *event)
@@ -519,55 +598,21 @@ void QQuickAbstractButton::mousePressEvent(QMouseEvent *event)
{
Q_D(QQuickAbstractButton);
QQuickControl::mousePressEvent(event);
- d->pressPoint = event->pos();
- setPressed(true);
-
- emit pressed();
-
- if (d->autoRepeat) {
- d->startRepeatDelay();
- d->repeatButton = event->button();
- } else if (Qt::LeftButton == (event->buttons() & Qt::LeftButton)) {
- d->startPressAndHold();
- } else {
- d->stopPressAndHold();
- }
+ d->handlePress(event->localPos(), event->button(), event->buttons());
}
void QQuickAbstractButton::mouseMoveEvent(QMouseEvent *event)
{
Q_D(QQuickAbstractButton);
QQuickControl::mouseMoveEvent(event);
- setPressed(d->keepPressed || contains(event->pos()));
-
- if (!d->pressed && d->autoRepeat)
- d->stopPressRepeat();
- else if (d->holdTimer > 0 && (!d->pressed || QLineF(d->pressPoint, event->localPos()).length() > QGuiApplication::styleHints()->startDragDistance()))
- d->stopPressAndHold();
+ d->handleMove(event->localPos());
}
void QQuickAbstractButton::mouseReleaseEvent(QMouseEvent *event)
{
Q_D(QQuickAbstractButton);
QQuickControl::mouseReleaseEvent(event);
- bool wasPressed = d->pressed;
- setPressed(false);
-
- if (!d->wasHeld && (d->keepPressed || contains(event->pos())))
- nextCheckState();
-
- if (wasPressed) {
- emit released();
- if (!d->wasHeld)
- emit clicked();
- } else {
- emit canceled();
- }
-
- if (d->autoRepeat)
- d->stopPressRepeat();
- else
- d->stopPressAndHold();
+ d->handleRelease(event->localPos());
}
void QQuickAbstractButton::mouseDoubleClickEvent(QMouseEvent *event)
@@ -580,12 +625,7 @@ void QQuickAbstractButton::mouseUngrabEvent()
{
Q_D(QQuickAbstractButton);
QQuickControl::mouseUngrabEvent();
- if (d->pressed) {
- setPressed(false);
- d->stopPressRepeat();
- d->stopPressAndHold();
- emit canceled();
- }
+ d->handleCancel();
}
void QQuickAbstractButton::timerEvent(QTimerEvent *event)
@@ -605,13 +645,19 @@ void QQuickAbstractButton::timerEvent(QTimerEvent *event)
}
}
-void QQuickAbstractButton::checkStateSet()
+void QQuickAbstractButton::buttonChange(ButtonChange change)
{
Q_D(QQuickAbstractButton);
- if (d->checked) {
- QQuickAbstractButton *button = d->findCheckedButton();
- if (button && button != this)
- button->setChecked(false);
+ switch (change) {
+ case ButtonCheckedChange:
+ if (d->checked) {
+ QQuickAbstractButton *button = d->findCheckedButton();
+ if (button && button != this)
+ button->setChecked(false);
+ }
+ break;
+ default:
+ break;
}
}
@@ -619,15 +665,7 @@ void QQuickAbstractButton::nextCheckState()
{
Q_D(QQuickAbstractButton);
if (d->checkable && (!d->checked || d->findCheckedButton() != this))
- setChecked(!d->checked);
-}
-
-void QQuickAbstractButton::checkableChange()
-{
-}
-
-void QQuickAbstractButton::autoRepeatChange()
-{
+ d->toggle(!d->checked);
}
#ifndef QT_NO_ACCESSIBILITY
diff --git a/src/quicktemplates2/qquickabstractbutton_p.h b/src/quicktemplates2/qquickabstractbutton_p.h
index f82c51c5..31b306af 100644
--- a/src/quicktemplates2/qquickabstractbutton_p.h
+++ b/src/quicktemplates2/qquickabstractbutton_p.h
@@ -102,6 +102,7 @@ Q_SIGNALS:
void released();
void canceled();
void clicked();
+ Q_REVISION(2) void toggled();
void pressAndHold();
void doubleClicked();
void textChanged();
@@ -125,11 +126,16 @@ protected:
void mouseUngrabEvent() override;
void timerEvent(QTimerEvent *event) override;
- virtual void checkStateSet();
- virtual void nextCheckState();
+ enum ButtonChange {
+ ButtonAutoRepeatChange,
+ ButtonCheckedChange,
+ ButtonCheckableChange,
+ ButtonPressedChanged,
+ ButtonTextChange
+ };
+ virtual void buttonChange(ButtonChange change);
- virtual void checkableChange();
- virtual void autoRepeatChange();
+ virtual void nextCheckState();
#ifndef QT_NO_ACCESSIBILITY
void accessibilityActiveChanged(bool active) override;
diff --git a/src/quicktemplates2/qquickabstractbutton_p_p.h b/src/quicktemplates2/qquickabstractbutton_p_p.h
index da40b4c8..cca7d200 100644
--- a/src/quicktemplates2/qquickabstractbutton_p_p.h
+++ b/src/quicktemplates2/qquickabstractbutton_p_p.h
@@ -67,6 +67,11 @@ public:
return button->d_func();
}
+ virtual void handlePress(const QPointF &point, Qt::MouseButton button, Qt::MouseButtons buttons);
+ virtual void handleMove(const QPointF &point);
+ virtual void handleRelease(const QPointF &point);
+ virtual void handleCancel();
+
bool isPressAndHoldConnected();
void startPressAndHold();
void stopPressAndHold();
@@ -78,6 +83,8 @@ public:
QQuickAbstractButton *findCheckedButton() const;
QList<QQuickAbstractButton *> findExclusiveButtons() const;
+ void toggle(bool value);
+
QString text;
bool down;
bool explicitDown;
diff --git a/src/quicktemplates2/qquickbutton.cpp b/src/quicktemplates2/qquickbutton.cpp
index d1252afd..5112547f 100644
--- a/src/quicktemplates2/qquickbutton.cpp
+++ b/src/quicktemplates2/qquickbutton.cpp
@@ -106,9 +106,11 @@ QQuickButton::QQuickButton(QQuickButtonPrivate &dd, QQuickItem *parent) :
The default value is \c false.
*/
-void QQuickButton::autoRepeatChange()
+void QQuickButton::buttonChange(ButtonChange change)
{
- emit autoRepeatChanged();
+ QQuickAbstractButton::buttonChange(change);
+ if (change == ButtonAutoRepeatChange)
+ emit autoRepeatChanged();
}
QFont QQuickButton::defaultFont() const
diff --git a/src/quicktemplates2/qquickbutton_p.h b/src/quicktemplates2/qquickbutton_p.h
index be0b7bbd..93fb3c14 100644
--- a/src/quicktemplates2/qquickbutton_p.h
+++ b/src/quicktemplates2/qquickbutton_p.h
@@ -78,7 +78,7 @@ Q_SIGNALS:
protected:
QQuickButton(QQuickButtonPrivate &dd, QQuickItem *parent);
- void autoRepeatChange() override;
+ void buttonChange(ButtonChange change) override;
QFont defaultFont() const override;
diff --git a/src/quicktemplates2/qquickcheckbox.cpp b/src/quicktemplates2/qquickcheckbox.cpp
index 4cdfcd28..dd36121e 100644
--- a/src/quicktemplates2/qquickcheckbox.cpp
+++ b/src/quicktemplates2/qquickcheckbox.cpp
@@ -173,9 +173,12 @@ QFont QQuickCheckBox::defaultFont() const
return QQuickControlPrivate::themeFont(QPlatformTheme::CheckBoxFont);
}
-void QQuickCheckBox::checkStateSet()
+void QQuickCheckBox::buttonChange(ButtonChange change)
{
- setCheckState(isChecked() ? Qt::Checked : Qt::Unchecked);
+ if (change == ButtonCheckedChange)
+ setCheckState(isChecked() ? Qt::Checked : Qt::Unchecked);
+ else
+ QQuickAbstractButton::buttonChange(change);
}
void QQuickCheckBox::nextCheckState()
diff --git a/src/quicktemplates2/qquickcheckbox_p.h b/src/quicktemplates2/qquickcheckbox_p.h
index b736894c..d4d66561 100644
--- a/src/quicktemplates2/qquickcheckbox_p.h
+++ b/src/quicktemplates2/qquickcheckbox_p.h
@@ -76,7 +76,7 @@ Q_SIGNALS:
protected:
QFont defaultFont() const override;
- void checkStateSet() override;
+ void buttonChange(ButtonChange change) override;
void nextCheckState() override;
#ifndef QT_NO_ACCESSIBILITY
diff --git a/src/quicktemplates2/qquickcheckdelegate.cpp b/src/quicktemplates2/qquickcheckdelegate.cpp
index a71cacbd..93b5eada 100644
--- a/src/quicktemplates2/qquickcheckdelegate.cpp
+++ b/src/quicktemplates2/qquickcheckdelegate.cpp
@@ -170,9 +170,12 @@ QFont QQuickCheckDelegate::defaultFont() const
return QQuickControlPrivate::themeFont(QPlatformTheme::ListViewFont);
}
-void QQuickCheckDelegate::checkStateSet()
+void QQuickCheckDelegate::buttonChange(ButtonChange change)
{
- setCheckState(isChecked() ? Qt::Checked : Qt::Unchecked);
+ if (change == ButtonCheckedChange)
+ setCheckState(isChecked() ? Qt::Checked : Qt::Unchecked);
+ else
+ QQuickAbstractButton::buttonChange(change);
}
void QQuickCheckDelegate::nextCheckState()
diff --git a/src/quicktemplates2/qquickcheckdelegate_p.h b/src/quicktemplates2/qquickcheckdelegate_p.h
index 3b8e7448..d50ddcc4 100644
--- a/src/quicktemplates2/qquickcheckdelegate_p.h
+++ b/src/quicktemplates2/qquickcheckdelegate_p.h
@@ -76,7 +76,7 @@ Q_SIGNALS:
protected:
QFont defaultFont() const override;
- void checkStateSet() override;
+ void buttonChange(ButtonChange change) override;
void nextCheckState() override;
#ifndef QT_NO_ACCESSIBILITY
diff --git a/src/quicktemplates2/qquickcombobox.cpp b/src/quicktemplates2/qquickcombobox.cpp
index 32a01b7b..d56c1a84 100644
--- a/src/quicktemplates2/qquickcombobox.cpp
+++ b/src/quicktemplates2/qquickcombobox.cpp
@@ -41,11 +41,15 @@
#include <QtCore/qregexp.h>
#include <QtCore/qabstractitemmodel.h>
+#include <QtGui/qinputmethod.h>
+#include <QtGui/qguiapplication.h>
#include <QtGui/qpa/qplatformtheme.h>
#include <QtQml/qjsvalue.h>
#include <QtQml/qqmlcontext.h>
+#include <QtQml/private/qlazilyallocated_p.h>
#include <QtQml/private/qqmldelegatemodel_p.h>
#include <QtQuick/private/qquickevents_p_p.h>
+#include <QtQuick/private/qquicktextinput_p.h>
QT_BEGIN_NAMESPACE
@@ -74,6 +78,30 @@ QT_BEGIN_NAMESPACE
}
\endcode
+ \section1 Editable ComboBox
+
+ ComboBox can be made \l editable. An editable combo box auto-completes
+ its text based on what is available in the model.
+
+ The following example demonstrates appending content to an editable
+ combo box by reacting to the \l accepted signal.
+
+ \code
+ ComboBox {
+ editable: true
+ model: ListModel {
+ id: model
+ ListElement { text: "Banana" }
+ ListElement { text: "Apple" }
+ ListElement { text: "Coconut" }
+ }
+ onAccepted: {
+ if (find(editText) === -1)
+ model.append({text: editText})
+ }
+ }
+ \endcode
+
\section1 ComboBox Model Roles
ComboBox is able to visualize standard \l {qml-data-models}{data models}
@@ -130,6 +158,19 @@ QT_BEGIN_NAMESPACE
\sa highlightedIndex
*/
+/*!
+ \since QtQuick.Controls 2.2
+ \qmlsignal void QtQuick.Controls::ComboBox::accepted()
+
+ This signal is emitted when the \uicontrol Return or \uicontrol Enter key is pressed
+ on an \l editable combo box. If the confirmed string is not currently in the model,
+ the \l currentIndex will be set to \c -1 and the \c currentText will be updated
+ accordingly.
+
+ \note If there is a \l validator set on the combo box, the signal will only be
+ emitted if the input is in an acceptable state.
+*/
+
namespace {
enum Activation { NoActivate, Activate };
enum Highlighting { NoHighlight, Highlight };
@@ -170,20 +211,26 @@ class QQuickComboBoxPrivate : public QQuickControlPrivate
Q_DECLARE_PUBLIC(QQuickComboBox)
public:
- QQuickComboBoxPrivate() : flat(false), pressed(false), ownModel(false), hasDisplayText(false), hasCurrentIndex(false),
- highlightedIndex(-1), currentIndex(-1), delegateModel(nullptr),
- delegate(nullptr), indicator(nullptr), popup(nullptr) { }
+ QQuickComboBoxPrivate();
bool isPopupVisible() const;
void showPopup();
void hidePopup(bool accept);
void togglePopup(bool accept);
+ void popupVisibleChanged();
void itemClicked();
void createdItem(int index, QObject *object);
+ void modelUpdated();
void countChanged();
+
+ void updateEditText();
void updateCurrentText();
+
+ void acceptInput();
+ QString tryComplete(const QString &inputText);
+
void incrementCurrentIndex();
void decrementCurrentIndex();
void setCurrentIndex(int index, Activation activate);
@@ -196,6 +243,8 @@ public:
void createDelegateModel();
bool flat;
+ bool down;
+ bool hasDown;
bool pressed;
bool ownModel;
bool hasDisplayText;
@@ -211,8 +260,42 @@ public:
QQmlComponent *delegate;
QQuickItem *indicator;
QQuickPopup *popup;
+
+ struct ExtraData {
+ ExtraData()
+ : editable(false),
+ accepting(false),
+ allowComplete(false),
+ inputMethodHints(Qt::ImhNone),
+ validator(nullptr) { }
+
+ bool editable;
+ bool accepting;
+ bool allowComplete;
+ Qt::InputMethodHints inputMethodHints;
+ QString editText;
+ QValidator *validator;
+ };
+ QLazilyAllocated<ExtraData> extra;
};
+QQuickComboBoxPrivate::QQuickComboBoxPrivate()
+ : flat(false),
+ down(false),
+ hasDown(false),
+ pressed(false),
+ ownModel(false),
+ hasDisplayText(false),
+ hasCurrentIndex(false),
+ highlightedIndex(-1),
+ currentIndex(-1),
+ delegateModel(nullptr),
+ delegate(nullptr),
+ indicator(nullptr),
+ popup(nullptr)
+{
+}
+
bool QQuickComboBoxPrivate::isPopupVisible() const
{
return popup && popup->isVisible();
@@ -246,6 +329,19 @@ void QQuickComboBoxPrivate::togglePopup(bool accept)
showPopup();
}
+void QQuickComboBoxPrivate::popupVisibleChanged()
+{
+ Q_Q(QQuickComboBox);
+ if (isPopupVisible())
+ QGuiApplication::inputMethod()->reset();
+
+ updateHighlightedIndex();
+ if (!hasDown) {
+ q->setDown(pressed || isPopupVisible());
+ hasDown = false;
+ }
+}
+
void QQuickComboBoxPrivate::itemClicked()
{
Q_Q(QQuickComboBox);
@@ -258,13 +354,26 @@ void QQuickComboBoxPrivate::itemClicked()
void QQuickComboBoxPrivate::createdItem(int index, QObject *object)
{
+ Q_Q(QQuickComboBox);
+ QQuickItem *item = qobject_cast<QQuickItem *>(object);
+ if (popup && item && !item->parentItem()) {
+ item->setParentItem(popup->contentItem());
+ QQuickItemPrivate::get(item)->setCulled(true);
+ }
+
QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(object);
if (button) {
button->setFocusPolicy(Qt::NoFocus);
connect(button, &QQuickAbstractButton::clicked, this, &QQuickComboBoxPrivate::itemClicked);
}
- if (index == currentIndex)
+ if (index == currentIndex && !q->isEditable())
+ updateCurrentText();
+}
+
+void QQuickComboBoxPrivate::modelUpdated()
+{
+ if (!extra.isAllocated() || !extra->accepting)
updateCurrentText();
}
@@ -276,6 +385,26 @@ void QQuickComboBoxPrivate::countChanged()
emit q->countChanged();
}
+void QQuickComboBoxPrivate::updateEditText()
+{
+ Q_Q(QQuickComboBox);
+ QQuickTextInput *input = qobject_cast<QQuickTextInput *>(contentItem);
+ if (!input)
+ return;
+
+ const QString text = input->text();
+
+ if (extra.isAllocated() && extra->allowComplete && !text.isEmpty()) {
+ const QString completed = tryComplete(text);
+ if (completed.length() > text.length()) {
+ input->setText(completed);
+ input->select(completed.length(), text.length());
+ return;
+ }
+ }
+ q->setEditText(text);
+}
+
void QQuickComboBoxPrivate::updateCurrentText()
{
Q_Q(QQuickComboBox);
@@ -290,6 +419,45 @@ void QQuickComboBoxPrivate::updateCurrentText()
displayText = text;
emit q->displayTextChanged();
}
+ if (!extra.isAllocated() || !extra->accepting)
+ q->setEditText(currentText);
+}
+
+void QQuickComboBoxPrivate::acceptInput()
+{
+ Q_Q(QQuickComboBox);
+ int idx = q->find(extra.value().editText, Qt::MatchFixedString);
+ if (idx > -1)
+ q->setCurrentIndex(idx);
+
+ extra.value().accepting = true;
+ emit q->accepted();
+
+ if (idx == -1)
+ q->setCurrentIndex(q->find(extra.value().editText, Qt::MatchFixedString));
+ extra.value().accepting = false;
+}
+
+QString QQuickComboBoxPrivate::tryComplete(const QString &input)
+{
+ Q_Q(QQuickComboBox);
+ QString match;
+
+ const int itemCount = q->count();
+ for (int idx = 0; idx < itemCount; ++idx) {
+ const QString text = q->textAt(idx);
+ if (!text.startsWith(input, Qt::CaseInsensitive))
+ continue;
+
+ // either the first or the shortest match
+ if (match.isEmpty() || text.length() < match.length())
+ match = text;
+ }
+
+ if (match.isEmpty())
+ return input;
+
+ return input + match.mid(input.length());
}
void QQuickComboBoxPrivate::setCurrentIndex(int index, Activation activate)
@@ -311,6 +479,8 @@ void QQuickComboBoxPrivate::setCurrentIndex(int index, Activation activate)
void QQuickComboBoxPrivate::incrementCurrentIndex()
{
Q_Q(QQuickComboBox);
+ if (extra.isAllocated())
+ extra->allowComplete = false;
if (isPopupVisible()) {
if (highlightedIndex < q->count() - 1)
setHighlightedIndex(highlightedIndex + 1, Highlight);
@@ -318,10 +488,14 @@ void QQuickComboBoxPrivate::incrementCurrentIndex()
if (currentIndex < q->count() - 1)
setCurrentIndex(currentIndex + 1, Activate);
}
+ if (extra.isAllocated())
+ extra->allowComplete = true;
}
void QQuickComboBoxPrivate::decrementCurrentIndex()
{
+ if (extra.isAllocated())
+ extra->allowComplete = false;
if (isPopupVisible()) {
if (highlightedIndex > 0)
setHighlightedIndex(highlightedIndex - 1, Highlight);
@@ -329,6 +503,8 @@ void QQuickComboBoxPrivate::decrementCurrentIndex()
if (currentIndex > 0)
setCurrentIndex(currentIndex - 1, Activate);
}
+ if (extra.isAllocated())
+ extra->allowComplete = true;
}
void QQuickComboBoxPrivate::updateHighlightedIndex()
@@ -415,7 +591,7 @@ void QQuickComboBoxPrivate::createDelegateModel()
QQmlInstanceModel* oldModel = delegateModel;
if (oldModel) {
disconnect(delegateModel, &QQmlInstanceModel::countChanged, this, &QQuickComboBoxPrivate::countChanged);
- disconnect(delegateModel, &QQmlInstanceModel::modelUpdated, this, &QQuickComboBoxPrivate::updateCurrentText);
+ disconnect(delegateModel, &QQmlInstanceModel::modelUpdated, this, &QQuickComboBoxPrivate::modelUpdated);
disconnect(delegateModel, &QQmlInstanceModel::createdItem, this, &QQuickComboBoxPrivate::createdItem);
}
@@ -435,7 +611,7 @@ void QQuickComboBoxPrivate::createDelegateModel()
if (delegateModel) {
connect(delegateModel, &QQmlInstanceModel::countChanged, this, &QQuickComboBoxPrivate::countChanged);
- connect(delegateModel, &QQmlInstanceModel::modelUpdated, this, &QQuickComboBoxPrivate::updateCurrentText);
+ connect(delegateModel, &QQmlInstanceModel::modelUpdated, this, &QQuickComboBoxPrivate::modelUpdated);
connect(delegateModel, &QQmlInstanceModel::createdItem, this, &QQuickComboBoxPrivate::createdItem);
}
@@ -451,6 +627,7 @@ QQuickComboBox::QQuickComboBox(QQuickItem *parent) :
setFocusPolicy(Qt::StrongFocus);
setFlag(QQuickItem::ItemIsFocusScope);
setAcceptedMouseButtons(Qt::LeftButton);
+ setInputMethodHints(Qt::ImhNoPredictiveText);
}
QQuickComboBox::~QQuickComboBox()
@@ -533,6 +710,48 @@ QQmlInstanceModel *QQuickComboBox::delegateModel() const
}
/*!
+ \since QtQuick.Controls 2.2
+ \qmlproperty bool QtQuick.Controls::ComboBox::editable
+
+ This property holds whether the combo box is editable.
+
+ The default value is \c false.
+
+ \sa validator
+*/
+bool QQuickComboBox::isEditable() const
+{
+ Q_D(const QQuickComboBox);
+ return d->extra.isAllocated() && d->extra->editable;
+}
+
+void QQuickComboBox::setEditable(bool editable)
+{
+ Q_D(QQuickComboBox);
+ if (editable == isEditable())
+ return;
+
+ if (d->contentItem) {
+ if (editable) {
+ d->contentItem->installEventFilter(this);
+ if (QQuickTextInput *input = qobject_cast<QQuickTextInput *>(d->contentItem)) {
+ QObjectPrivate::connect(input, &QQuickTextInput::textChanged, d, &QQuickComboBoxPrivate::updateEditText);
+ QObjectPrivate::connect(input, &QQuickTextInput::accepted, d, &QQuickComboBoxPrivate::acceptInput);
+ }
+ } else {
+ d->contentItem->removeEventFilter(this);
+ if (QQuickTextInput *input = qobject_cast<QQuickTextInput *>(d->contentItem)) {
+ QObjectPrivate::disconnect(input, &QQuickTextInput::textChanged, d, &QQuickComboBoxPrivate::updateEditText);
+ QObjectPrivate::disconnect(input, &QQuickTextInput::accepted, d, &QQuickComboBoxPrivate::acceptInput);
+ }
+ }
+ }
+
+ d->extra.value().editable = editable;
+ emit editableChanged();
+}
+
+/*!
\since QtQuick.Controls 2.1
\qmlproperty bool QtQuick.Controls::ComboBox::flat
@@ -563,9 +782,52 @@ void QQuickComboBox::setFlat(bool flat)
}
/*!
+ \since QtQuick.Controls 2.2
+ \qmlproperty bool QtQuick.Controls::ComboBox::down
+
+ This property holds whether the combo box button is visually down.
+
+ Unless explicitly set, this property is \c true when either \c pressed
+ or \c popup.visible is \c true. To return to the default value, set this
+ property to \c undefined.
+
+ \sa pressed, popup
+*/
+bool QQuickComboBox::isDown() const
+{
+ Q_D(const QQuickComboBox);
+ return d->down;
+}
+
+void QQuickComboBox::setDown(bool down)
+{
+ Q_D(QQuickComboBox);
+ d->hasDown = true;
+
+ if (d->down == down)
+ return;
+
+ d->down = down;
+ emit downChanged();
+}
+
+void QQuickComboBox::resetDown()
+{
+ Q_D(QQuickComboBox);
+ if (!d->hasDown)
+ return;
+
+ setDown(d->pressed || d->isPopupVisible());
+ d->hasDown = false;
+}
+
+/*!
\qmlproperty bool QtQuick.Controls::ComboBox::pressed
- This property holds whether the combo box button is pressed.
+ This property holds whether the combo box button is physically pressed.
+ A button can be pressed by either touch or key events.
+
+ \sa down
*/
bool QQuickComboBox::isPressed() const
{
@@ -581,6 +843,11 @@ void QQuickComboBox::setPressed(bool pressed)
d->pressed = pressed;
emit pressedChanged();
+
+ if (!d->hasDown) {
+ setDown(d->pressed || d->isPopupVisible());
+ d->hasDown = false;
+ }
}
/*!
@@ -683,6 +950,35 @@ void QQuickComboBox::resetDisplayText()
}
/*!
+ \since QtQuick.Controls 2.2
+ \qmlproperty string QtQuick.Controls::ComboBox::editText
+
+ This property holds the text in the text field of an editable combo box.
+
+ \sa editable
+*/
+QString QQuickComboBox::editText() const
+{
+ Q_D(const QQuickComboBox);
+ return d->extra.isAllocated() ? d->extra->editText : QString();
+}
+
+void QQuickComboBox::setEditText(const QString &text)
+{
+ Q_D(QQuickComboBox);
+ if (text == editText())
+ return;
+
+ d->extra.value().editText = text;
+ emit editTextChanged();
+}
+
+void QQuickComboBox::resetEditText()
+{
+ setEditText(QString());
+}
+
+/*!
\qmlproperty string QtQuick.Controls::ComboBox::textRole
This property holds the model role used for populating the combo box.
@@ -807,18 +1103,127 @@ void QQuickComboBox::setPopup(QQuickPopup *popup)
return;
if (d->popup)
- QObjectPrivate::disconnect(d->popup, &QQuickPopup::visibleChanged, d, &QQuickComboBoxPrivate::updateHighlightedIndex);
+ QObjectPrivate::disconnect(d->popup, &QQuickPopup::visibleChanged, d, &QQuickComboBoxPrivate::popupVisibleChanged);
d->deleteDelegate(d->popup);
if (popup) {
QQuickPopupPrivate::get(popup)->allowVerticalFlip = true;
popup->setClosePolicy(QQuickPopup::CloseOnEscape | QQuickPopup::CloseOnPressOutsideParent);
- QObjectPrivate::connect(popup, &QQuickPopup::visibleChanged, d, &QQuickComboBoxPrivate::updateHighlightedIndex);
+ QObjectPrivate::connect(popup, &QQuickPopup::visibleChanged, d, &QQuickComboBoxPrivate::popupVisibleChanged);
}
d->popup = popup;
emit popupChanged();
}
/*!
+ \since QtQuick.Controls 2.2
+ \qmlproperty Validator QtQuick.Controls::ComboBox::validator
+
+ This property holds an input text validator for an editable combo box.
+
+ When a validator is set, the text field will only accept input which
+ leaves the text property in an intermediate state. The \l accepted signal
+ will only be emitted if the text is in an acceptable state when the
+ \uicontrol Return or \uicontrol Enter key is pressed.
+
+ The currently supported validators are \l[QtQuick]{IntValidator},
+ \l[QtQuick]{DoubleValidator}, and \l[QtQuick]{RegExpValidator}. An
+ example of using validators is shown below, which allows input of
+ integers between \c 0 and \c 10 into the text field:
+
+ \code
+ ComboBox {
+ model: 10
+ editable: true
+ validator: IntValidator {
+ top: 9
+ bottom: 0
+ }
+ }
+ \endcode
+
+ \sa acceptableInput, accepted, editable
+*/
+QValidator *QQuickComboBox::validator() const
+{
+ Q_D(const QQuickComboBox);
+ return d->extra.isAllocated() ? d->extra->validator : nullptr;
+}
+
+void QQuickComboBox::setValidator(QValidator *validator)
+{
+ Q_D(QQuickComboBox);
+ if (validator == QQuickComboBox::validator())
+ return;
+
+ d->extra.value().validator = validator;
+ if (validator)
+ validator->setLocale(d->locale);
+ emit validatorChanged();
+}
+
+/*!
+ \since QtQuick.Controls 2.2
+ \qmlproperty flags QtQuick.Controls::ComboBox::inputMethodHints
+
+ Provides hints to the input method about the expected content of the combo box and how it
+ should operate.
+
+ The default value is \c Qt.ImhNoPredictiveText.
+
+ \include inputmethodhints.qdocinc
+*/
+Qt::InputMethodHints QQuickComboBox::inputMethodHints() const
+{
+ Q_D(const QQuickComboBox);
+ return d->extra.isAllocated() ? d->extra->inputMethodHints : Qt::ImhNoPredictiveText;
+}
+
+void QQuickComboBox::setInputMethodHints(Qt::InputMethodHints hints)
+{
+ Q_D(QQuickComboBox);
+ if (hints == inputMethodHints())
+ return;
+
+ d->extra.value().inputMethodHints = hints;
+ emit inputMethodHintsChanged();
+}
+
+/*!
+ \since QtQuick.Controls 2.2
+ \qmlproperty bool QtQuick.Controls::ComboBox::inputMethodComposing
+ \readonly
+
+ This property holds whether an editable combo box has partial text input from an input method.
+
+ While it is composing, an input method may rely on mouse or key events from the combo box to
+ edit or commit the partial text. This property can be used to determine when to disable event
+ handlers that may interfere with the correct operation of an input method.
+*/
+bool QQuickComboBox::isInputMethodComposing() const
+{
+ Q_D(const QQuickComboBox);
+ return d->contentItem && d->contentItem->property("inputMethodComposing").toBool();
+}
+
+/*!
+ \since QtQuick.Controls 2.2
+ \qmlproperty bool QtQuick.Controls::ComboBox::acceptableInput
+ \readonly
+
+ This property holds whether the combo box contains acceptable text in the editable text field.
+
+ If a validator has been set, the value is \c true only if the current text is acceptable
+ to the validator as a final string (not as an intermediate string).
+
+ \sa validator, accepted
+*/
+bool QQuickComboBox::hasAcceptableInput() const
+{
+ Q_D(const QQuickComboBox);
+ return d->contentItem && d->contentItem->property("acceptableInput").toBool();
+}
+
+/*!
\qmlmethod string QtQuick.Controls::ComboBox::textAt(int index)
Returns the text for the specified \a index, or an empty string
@@ -895,6 +1300,59 @@ void QQuickComboBox::decrementCurrentIndex()
d->decrementCurrentIndex();
}
+/*!
+ \since QtQuick.Controls 2.2
+ \qmlmethod void QtQuick.Controls::ComboBox::selectAll()
+
+ Selects all the text in the editable text field of the combo box.
+
+ \sa editText
+*/
+void QQuickComboBox::selectAll()
+{
+ Q_D(QQuickComboBox);
+ QQuickTextInput *input = qobject_cast<QQuickTextInput *>(d->contentItem);
+ if (!input)
+ return;
+ input->selectAll();
+}
+
+bool QQuickComboBox::eventFilter(QObject *object, QEvent *event)
+{
+ Q_D(QQuickComboBox);
+ switch (event->type()) {
+ case QEvent::MouseButtonRelease:
+ if (d->isPopupVisible())
+ d->hidePopup(false);
+ break;
+ case QEvent::KeyPress: {
+ const int key = static_cast<QKeyEvent *>(event)->key();
+ if (d->extra.isAllocated())
+ d->extra->allowComplete = key != Qt::Key_Backspace && key != Qt::Key_Delete;
+ break;
+ }
+ case QEvent::FocusOut:
+ d->hidePopup(false);
+ setPressed(false);
+ break;
+ case QEvent::InputMethod:
+ if (d->extra.isAllocated())
+ d->extra->allowComplete = !static_cast<QInputMethodEvent*>(event)->commitString().isEmpty();
+ break;
+ default:
+ break;
+ }
+ return QQuickControl::eventFilter(object, event);
+}
+
+void QQuickComboBox::focusInEvent(QFocusEvent *event)
+{
+ Q_D(QQuickComboBox);
+ QQuickControl::focusInEvent(event);
+ if (d->contentItem && isEditable())
+ d->contentItem->forceActiveFocus(event->reason());
+}
+
void QQuickComboBox::focusOutEvent(QFocusEvent *event)
{
Q_D(QQuickComboBox);
@@ -903,6 +1361,16 @@ void QQuickComboBox::focusOutEvent(QFocusEvent *event)
setPressed(false);
}
+void QQuickComboBox::inputMethodEvent(QInputMethodEvent *event)
+{
+ Q_D(QQuickComboBox);
+ QQuickControl::inputMethodEvent(event);
+ if (!isEditable() && !event->commitString().isEmpty())
+ d->keySearch(event->commitString());
+ else
+ event->ignore();
+}
+
void QQuickComboBox::keyPressEvent(QKeyEvent *event)
{
Q_D(QQuickComboBox);
@@ -948,7 +1416,7 @@ void QQuickComboBox::keyPressEvent(QKeyEvent *event)
event->accept();
break;
default:
- if (!event->text().isEmpty())
+ if (!isEditable() && !event->text().isEmpty())
d->keySearch(event->text());
else
event->ignore();
@@ -965,13 +1433,15 @@ void QQuickComboBox::keyReleaseEvent(QKeyEvent *event)
switch (event->key()) {
case Qt::Key_Space:
- d->togglePopup(true);
+ if (!isEditable())
+ d->togglePopup(true);
setPressed(false);
event->accept();
break;
case Qt::Key_Enter:
case Qt::Key_Return:
- d->hidePopup(d->isPopupVisible());
+ if (!isEditable() || d->isPopupVisible())
+ d->hidePopup(d->isPopupVisible());
setPressed(false);
event->accept();
break;
@@ -1044,6 +1514,36 @@ void QQuickComboBox::componentComplete()
}
}
+void QQuickComboBox::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem)
+{
+ Q_D(QQuickComboBox);
+ if (oldItem) {
+ oldItem->removeEventFilter(this);
+ if (QQuickTextInput *oldInput = qobject_cast<QQuickTextInput *>(oldItem)) {
+ QObjectPrivate::disconnect(oldInput, &QQuickTextInput::accepted, d, &QQuickComboBoxPrivate::acceptInput);
+ QObjectPrivate::disconnect(oldInput, &QQuickTextInput::textChanged, d, &QQuickComboBoxPrivate::updateEditText);
+ disconnect(oldInput, &QQuickTextInput::inputMethodComposingChanged, this, &QQuickComboBox::inputMethodComposingChanged);
+ disconnect(oldInput, &QQuickTextInput::acceptableInputChanged, this, &QQuickComboBox::acceptableInputChanged);
+ }
+ }
+ if (newItem && isEditable()) {
+ newItem->installEventFilter(this);
+ if (QQuickTextInput *newInput = qobject_cast<QQuickTextInput *>(newItem)) {
+ QObjectPrivate::connect(newInput, &QQuickTextInput::accepted, d, &QQuickComboBoxPrivate::acceptInput);
+ QObjectPrivate::connect(newInput, &QQuickTextInput::textChanged, d, &QQuickComboBoxPrivate::updateEditText);
+ connect(newInput, &QQuickTextInput::inputMethodComposingChanged, this, &QQuickComboBox::inputMethodComposingChanged);
+ connect(newInput, &QQuickTextInput::acceptableInputChanged, this, &QQuickComboBox::acceptableInputChanged);
+ }
+ }
+}
+
+void QQuickComboBox::localeChange(const QLocale &newLocale, const QLocale &oldLocale)
+{
+ QQuickControl::localeChange(newLocale, oldLocale);
+ if (QValidator *v = validator())
+ v->setLocale(newLocale);
+}
+
QFont QQuickComboBox::defaultFont() const
{
return QQuickControlPrivate::themeFont(QPlatformTheme::ComboMenuItemFont);
diff --git a/src/quicktemplates2/qquickcombobox_p.h b/src/quicktemplates2/qquickcombobox_p.h
index 4fda8cce..87453999 100644
--- a/src/quicktemplates2/qquickcombobox_p.h
+++ b/src/quicktemplates2/qquickcombobox_p.h
@@ -52,6 +52,7 @@
QT_BEGIN_NAMESPACE
+class QValidator;
class QQuickPopup;
class QQmlInstanceModel;
class QQuickComboBoxPrivate;
@@ -62,16 +63,23 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickComboBox : public QQuickControl
Q_PROPERTY(int count READ count NOTIFY countChanged FINAL)
Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged FINAL)
Q_PROPERTY(QQmlInstanceModel *delegateModel READ delegateModel NOTIFY delegateModelChanged FINAL)
+ Q_PROPERTY(bool editable READ isEditable WRITE setEditable NOTIFY editableChanged FINAL REVISION 2)
Q_PROPERTY(bool flat READ isFlat WRITE setFlat NOTIFY flatChanged FINAL REVISION 1)
- Q_PROPERTY(bool pressed READ isPressed WRITE setPressed NOTIFY pressedChanged FINAL)
+ Q_PROPERTY(bool down READ isDown WRITE setDown RESET resetDown NOTIFY downChanged FINAL REVISION 2)
+ Q_PROPERTY(bool pressed READ isPressed WRITE setPressed NOTIFY pressedChanged FINAL) // ### Qt 6: should not be writable
Q_PROPERTY(int highlightedIndex READ highlightedIndex NOTIFY highlightedIndexChanged FINAL)
Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged FINAL)
Q_PROPERTY(QString currentText READ currentText NOTIFY currentTextChanged FINAL)
Q_PROPERTY(QString displayText READ displayText WRITE setDisplayText RESET resetDisplayText NOTIFY displayTextChanged FINAL)
+ Q_PROPERTY(QString editText READ editText WRITE setEditText RESET resetEditText NOTIFY editTextChanged FINAL REVISION 2)
Q_PROPERTY(QString textRole READ textRole WRITE setTextRole NOTIFY textRoleChanged FINAL)
Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged FINAL)
Q_PROPERTY(QQuickItem *indicator READ indicator WRITE setIndicator NOTIFY indicatorChanged FINAL)
Q_PROPERTY(QQuickPopup *popup READ popup WRITE setPopup NOTIFY popupChanged FINAL)
+ Q_PROPERTY(QValidator *validator READ validator WRITE setValidator NOTIFY validatorChanged FINAL REVISION 2)
+ Q_PROPERTY(Qt::InputMethodHints inputMethodHints READ inputMethodHints WRITE setInputMethodHints NOTIFY inputMethodHintsChanged FINAL REVISION 2)
+ Q_PROPERTY(bool inputMethodComposing READ isInputMethodComposing NOTIFY inputMethodComposingChanged FINAL REVISION 2)
+ Q_PROPERTY(bool acceptableInput READ hasAcceptableInput NOTIFY acceptableInputChanged FINAL REVISION 2)
public:
explicit QQuickComboBox(QQuickItem *parent = nullptr);
@@ -83,9 +91,16 @@ public:
void setModel(const QVariant &model);
QQmlInstanceModel *delegateModel() const;
+ bool isEditable() const;
+ void setEditable(bool editable);
+
bool isFlat() const;
void setFlat(bool flat);
+ bool isDown() const;
+ void setDown(bool down);
+ void resetDown();
+
bool isPressed() const;
void setPressed(bool pressed);
@@ -100,6 +115,10 @@ public:
void setDisplayText(const QString &text);
void resetDisplayText();
+ QString editText() const;
+ void setEditText(const QString &text);
+ void resetEditText();
+
QString textRole() const;
void setTextRole(const QString &role);
@@ -112,33 +131,54 @@ public:
QQuickPopup *popup() const;
void setPopup(QQuickPopup *popup);
+ QValidator *validator() const;
+ void setValidator(QValidator *validator);
+
+ Qt::InputMethodHints inputMethodHints() const;
+ void setInputMethodHints(Qt::InputMethodHints hints);
+
+ bool isInputMethodComposing() const;
+ bool hasAcceptableInput() const;
+
Q_INVOKABLE QString textAt(int index) const;
Q_INVOKABLE int find(const QString &text, Qt::MatchFlags flags = Qt::MatchExactly) const;
public Q_SLOTS:
void incrementCurrentIndex();
void decrementCurrentIndex();
+ Q_REVISION(2) void selectAll();
Q_SIGNALS:
void countChanged();
void modelChanged();
void delegateModelChanged();
+ Q_REVISION(2) void editableChanged();
Q_REVISION(1) void flatChanged();
+ Q_REVISION(2) void downChanged();
void pressedChanged();
void highlightedIndexChanged();
void currentIndexChanged();
void currentTextChanged();
void displayTextChanged();
+ Q_REVISION(2) void editTextChanged();
void textRoleChanged();
void delegateChanged();
void indicatorChanged();
void popupChanged();
+ Q_REVISION(2) void validatorChanged();
+ Q_REVISION(2) void inputMethodHintsChanged();
+ Q_REVISION(2) void inputMethodComposingChanged();
+ Q_REVISION(2) void acceptableInputChanged();
void activated(int index);
void highlighted(int index);
+ Q_REVISION(2) void accepted();
protected:
+ bool eventFilter(QObject *object, QEvent *event) override;
+ void focusInEvent(QFocusEvent *event) override;
void focusOutEvent(QFocusEvent *event) override;
+ void inputMethodEvent(QInputMethodEvent *event) override;
void keyPressEvent(QKeyEvent *event) override;
void keyReleaseEvent(QKeyEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
@@ -148,6 +188,8 @@ protected:
void wheelEvent(QWheelEvent *event) override;
void componentComplete() override;
+ void contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) override;
+ void localeChange(const QLocale &newLocale, const QLocale &oldLocale) override;
QFont defaultFont() const override;
diff --git a/src/quicktemplates2/qquickcontrol.cpp b/src/quicktemplates2/qquickcontrol.cpp
index 6a9d4eb3..651afb59 100644
--- a/src/quicktemplates2/qquickcontrol.cpp
+++ b/src/quicktemplates2/qquickcontrol.cpp
@@ -46,7 +46,7 @@
#include "qquicktextfield_p.h"
#include "qquicktextfield_p_p.h"
#include "qquickpopup_p.h"
-#include "qquickpopup_p_p.h"
+#include "qquickpopupitem_p_p.h"
#include "qquickapplicationwindow_p.h"
#include <QtGui/private/qguiapplication_p.h>
diff --git a/src/quicktemplates2/qquickdelaybutton.cpp b/src/quicktemplates2/qquickdelaybutton.cpp
new file mode 100644
index 00000000..3c8eaeb0
--- /dev/null
+++ b/src/quicktemplates2/qquickdelaybutton.cpp
@@ -0,0 +1,271 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickdelaybutton_p.h"
+#include "qquickabstractbutton_p_p.h"
+
+#include <QtQuick/private/qquickanimation_p.h>
+#include <QtQuick/private/qquicktransition_p.h>
+#include <QtQuick/private/qquicktransitionmanager_p_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype DelayButton
+ \inherits AbstractButton
+ \instantiates QQuickDelayButton
+ \inqmlmodule QtQuick.Controls
+ \since 5.9
+ \ingroup qtquickcontrols2-buttons
+ \brief Check button that triggers when held down long enough.
+
+ \image qtquickcontrols2-delaybutton.gif
+
+ DelayButton is a checkable button that incorporates a delay before the
+ button becomes \l {AbstractButton::}{checked} and the \l activated()
+ signal is emitted. This delay prevents accidental presses.
+
+ The current progress is expressed as a decimal value between \c 0.0
+ and \c 1.0. The time it takes for \l activated() to be emitted is
+ measured in milliseconds, and can be set with the \l delay property.
+
+ The progress is indicated by a progress indicator on the button.
+
+ \sa {Customizing DelayButton}, {Button Controls}
+*/
+
+/*!
+ \qmlsignal QtQuick.Controls::DelayButton::activated()
+
+ This signal is emitted when \l progress reaches \c 1.0.
+*/
+
+class QQuickDelayTransitionManager;
+
+class QQuickDelayButtonPrivate : public QQuickAbstractButtonPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickDelayButton)
+
+public:
+ QQuickDelayButtonPrivate();
+
+ void beginTransition(qreal to);
+ void finishTransition();
+ void cancelTransition();
+
+ int delay;
+ qreal progress;
+ QQuickTransition *transition;
+ QScopedPointer<QQuickDelayTransitionManager> transitionManager;
+};
+
+class QQuickDelayTransitionManager : public QQuickTransitionManager
+{
+public:
+ QQuickDelayTransitionManager(QQuickDelayButton *button) : m_button(button) { }
+
+ void transition(QQuickTransition *transition, qreal progress);
+
+protected:
+ void finished() override;
+
+private:
+ QQuickDelayButton *m_button;
+};
+
+void QQuickDelayTransitionManager::transition(QQuickTransition *transition, qreal progress)
+{
+ qmlExecuteDeferred(transition);
+
+ QQmlProperty defaultTarget(m_button, QLatin1String("progress"));
+ QQmlListProperty<QQuickAbstractAnimation> animations = transition->animations();
+ const int count = animations.count(&animations);
+ for (int i = 0; i < count; ++i) {
+ QQuickAbstractAnimation *anim = animations.at(&animations, i);
+ anim->setDefaultTarget(defaultTarget);
+ }
+
+ QList<QQuickStateAction> actions;
+ actions << QQuickStateAction(m_button, QLatin1String("progress"), progress);
+ QQuickTransitionManager::transition(actions, transition, m_button);
+}
+
+void QQuickDelayTransitionManager::finished()
+{
+ if (qFuzzyCompare(m_button->progress(), 1.0))
+ emit m_button->activated();
+}
+
+QQuickDelayButtonPrivate::QQuickDelayButtonPrivate()
+ : delay(3000),
+ progress(0.0),
+ transition(nullptr)
+{
+}
+
+void QQuickDelayButtonPrivate::beginTransition(qreal to)
+{
+ Q_Q(QQuickDelayButton);
+ if (!transition) {
+ q->setProgress(to);
+ finishTransition();
+ return;
+ }
+
+ if (!transitionManager)
+ transitionManager.reset(new QQuickDelayTransitionManager(q));
+
+ transitionManager->transition(transition, to);
+}
+
+void QQuickDelayButtonPrivate::finishTransition()
+{
+ Q_Q(QQuickDelayButton);
+ if (qFuzzyCompare(progress, 1.0))
+ emit q->activated();
+}
+
+void QQuickDelayButtonPrivate::cancelTransition()
+{
+ if (transitionManager)
+ transitionManager->cancel();
+}
+
+QQuickDelayButton::QQuickDelayButton(QQuickItem *parent) :
+ QQuickAbstractButton(*(new QQuickDelayButtonPrivate), parent)
+{
+ setCheckable(true);
+}
+
+/*!
+ \qmlproperty int QtQuick.Controls::DelayButton::delay
+
+ This property holds the time it takes (in milliseconds) for \l progress
+ to reach \c 1.0 and emit \l activated().
+
+ The default value is \c 3000 ms.
+*/
+int QQuickDelayButton::delay() const
+{
+ Q_D(const QQuickDelayButton);
+ return d->delay;
+}
+
+void QQuickDelayButton::setDelay(int delay)
+{
+ Q_D(QQuickDelayButton);
+ if (d->delay == delay)
+ return;
+
+ d->delay = delay;
+ emit delayChanged();
+}
+
+/*!
+ \qmlproperty real QtQuick.Controls::DelayButton::progress
+ \readonly
+
+ This property holds the current progress as displayed by the progress
+ indicator, in the range \c 0.0 - \c 1.0.
+*/
+qreal QQuickDelayButton::progress() const
+{
+ Q_D(const QQuickDelayButton);
+ return d->progress;
+}
+
+void QQuickDelayButton::setProgress(qreal progress)
+{
+ Q_D(QQuickDelayButton);
+ if (qFuzzyCompare(d->progress, progress))
+ return;
+
+ d->progress = progress;
+ emit progressChanged();
+}
+
+/*!
+ \qmlproperty Transition QtQuick.Controls::DelayButton::transition
+
+ This property holds the transition that is applied on the \l progress
+ property when the button is pressed or released.
+*/
+QQuickTransition *QQuickDelayButton::transition() const
+{
+ Q_D(const QQuickDelayButton);
+ return d->transition;
+}
+
+void QQuickDelayButton::setTransition(QQuickTransition *transition)
+{
+ Q_D(QQuickDelayButton);
+ if (d->transition == transition)
+ return;
+
+ d->transition = transition;
+ emit transitionChanged();
+}
+
+void QQuickDelayButton::buttonChange(ButtonChange change)
+{
+ Q_D(QQuickDelayButton);
+ switch (change) {
+ case ButtonCheckedChange:
+ d->cancelTransition();
+ setProgress(d->checked ? 1.0 : 0.0);
+ break;
+ case ButtonPressedChanged:
+ if (!d->checked)
+ d->beginTransition(d->pressed ? 1.0 : 0.0);
+ break;
+ default:
+ QQuickAbstractButton::buttonChange(change);
+ break;
+ }
+}
+
+void QQuickDelayButton::nextCheckState()
+{
+ Q_D(QQuickDelayButton);
+ setChecked(!d->checked && qFuzzyCompare(d->progress, 1.0));
+}
+
+QFont QQuickDelayButton::defaultFont() const
+{
+ return QQuickControlPrivate::themeFont(QPlatformTheme::PushButtonFont);
+}
+
+QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickdelaybutton_p.h b/src/quicktemplates2/qquickdelaybutton_p.h
new file mode 100644
index 00000000..5ac0885d
--- /dev/null
+++ b/src/quicktemplates2/qquickdelaybutton_p.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKDELAYBUTTON_P_H
+#define QQUICKDELAYBUTTON_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQuickTemplates2/private/qquickabstractbutton_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickTransition;
+class QQuickDelayButtonPrivate;
+
+class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickDelayButton : public QQuickAbstractButton
+{
+ Q_OBJECT
+ Q_PROPERTY(int delay READ delay WRITE setDelay NOTIFY delayChanged FINAL)
+ Q_PROPERTY(qreal progress READ progress WRITE setProgress NOTIFY progressChanged FINAL)
+ Q_PROPERTY(QQuickTransition *transition READ transition WRITE setTransition NOTIFY transitionChanged FINAL)
+
+public:
+ explicit QQuickDelayButton(QQuickItem *parent = nullptr);
+
+ int delay() const;
+ void setDelay(int delay);
+
+ qreal progress() const;
+ void setProgress(qreal progress);
+
+ QQuickTransition *transition() const;
+ void setTransition(QQuickTransition *transition);
+
+Q_SIGNALS:
+ void activated();
+ void delayChanged();
+ void progressChanged();
+ void transitionChanged();
+
+protected:
+ void buttonChange(ButtonChange change) override;
+ void nextCheckState() override;
+
+ QFont defaultFont() const override;
+
+private:
+ Q_DISABLE_COPY(QQuickDelayButton)
+ Q_DECLARE_PRIVATE(QQuickDelayButton)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickDelayButton)
+
+#endif // QQUICKDELAYBUTTON_P_H
diff --git a/src/quicktemplates2/qquickdial.cpp b/src/quicktemplates2/qquickdial.cpp
index fbc73c2a..bb939dd9 100644
--- a/src/quicktemplates2/qquickdial.cpp
+++ b/src/quicktemplates2/qquickdial.cpp
@@ -77,6 +77,14 @@ QT_BEGIN_NAMESPACE
\sa {Customizing Dial}, {Input Controls}
*/
+/*!
+ \since QtQuick.Controls 2.2
+ \qmlsignal QtQuick.Controls::Dial::moved()
+
+ This signal is emitted when the dial has been interactively moved
+ by the user by either touch, mouse, or keys.
+*/
+
static const qreal startAngleRadians = (M_PI * 2.0) * (4.0 / 6.0);
static const qreal startAngle = -140;
static const qreal endAngleRadians = (M_PI * 2.0) * (5.0 / 6.0);
@@ -88,6 +96,7 @@ class QQuickDialPrivate : public QQuickControlPrivate
public:
QQuickDialPrivate() :
+ touchId(-1),
from(0),
to(1),
value(0),
@@ -97,17 +106,24 @@ public:
pressed(false),
snapMode(QQuickDial::NoSnap),
wrap(false),
+ live(false),
handle(nullptr)
{
}
qreal valueAt(qreal position) const;
qreal snapPosition(qreal position) const;
- qreal positionAt(const QPoint &point) const;
+ qreal positionAt(const QPointF &point) const;
void setPosition(qreal position);
void updatePosition();
- bool isLargeChange(const QPoint &eventPos, qreal proposedPosition) const;
+ bool isLargeChange(const QPointF &eventPos, qreal proposedPosition) const;
+
+ void handlePress(const QPointF &point);
+ void handleMove(const QPointF &point);
+ void handleRelease(const QPointF &point);
+ void handleUngrab();
+ int touchId;
qreal from;
qreal to;
qreal value;
@@ -115,9 +131,10 @@ public:
qreal angle;
qreal stepSize;
bool pressed;
- QPoint pressPoint;
+ QPointF pressPoint;
QQuickDial::SnapMode snapMode;
bool wrap;
+ bool live;
QQuickItem *handle;
};
@@ -139,7 +156,7 @@ qreal QQuickDialPrivate::snapPosition(qreal position) const
return qRound(position / effectiveStep) * effectiveStep;
}
-qreal QQuickDialPrivate::positionAt(const QPoint &point) const
+qreal QQuickDialPrivate::positionAt(const QPointF &point) const
{
qreal yy = height / 2.0 - point.y();
qreal xx = point.x() - width / 2.0;
@@ -175,11 +192,68 @@ void QQuickDialPrivate::updatePosition()
setPosition(pos);
}
-bool QQuickDialPrivate::isLargeChange(const QPoint &eventPos, qreal proposedPosition) const
+bool QQuickDialPrivate::isLargeChange(const QPointF &eventPos, qreal proposedPosition) const
{
return qAbs(proposedPosition - position) >= 0.5 && eventPos.y() >= height / 2;
}
+void QQuickDialPrivate::handlePress(const QPointF &point)
+{
+ Q_Q(QQuickDial);
+ pressPoint = point;
+ q->setPressed(true);
+}
+
+void QQuickDialPrivate::handleMove(const QPointF &point)
+{
+ Q_Q(QQuickDial);
+ if (!q->keepMouseGrab())
+ return;
+ const qreal oldPos = position;
+ qreal pos = positionAt(point);
+ if (snapMode == QQuickDial::SnapAlways)
+ pos = snapPosition(pos);
+
+ if (wrap || (!wrap && !isLargeChange(point, pos))) {
+ if (live)
+ q->setValue(valueAt(pos));
+ else
+ setPosition(pos);
+ if (!qFuzzyCompare(pos, oldPos))
+ emit q->moved();
+ }
+}
+
+void QQuickDialPrivate::handleRelease(const QPointF &point)
+{
+ Q_Q(QQuickDial);
+ if (q->keepMouseGrab()) {
+ const qreal oldPos = position;
+ qreal pos = positionAt(point);
+ if (snapMode != QQuickDial::NoSnap)
+ pos = snapPosition(pos);
+
+ if (wrap || (!wrap && !isLargeChange(point, pos)))
+ q->setValue(valueAt(pos));
+ if (!qFuzzyCompare(pos, oldPos))
+ emit q->moved();
+
+ q->setKeepMouseGrab(false);
+ }
+
+ q->setPressed(false);
+ pressPoint = QPointF();
+ touchId = -1;
+}
+
+void QQuickDialPrivate::handleUngrab()
+{
+ Q_Q(QQuickDial);
+ pressPoint = QPointF();
+ touchId = -1;
+ q->setPressed(false);
+}
+
QQuickDial::QQuickDial(QQuickItem *parent) :
QQuickControl(*(new QQuickDialPrivate), parent)
{
@@ -248,11 +322,12 @@ void QQuickDial::setTo(qreal to)
This property holds the value in the range \c from - \c to. The default
value is \c 0.0.
- Unlike the \l position property, the \c value is not updated while the
- handle is dragged. The value is updated after the value has been chosen
- and the dial has been released.
+ Unlike the \l position property, the \c value is not updated by default
+ while the handle is dragged. The value is updated after the value has
+ been chosen and the dial has been released. The \l live property can be
+ used to make the dial provide live updates for the \c value property.
- \sa position
+ \sa position, live
*/
qreal QQuickDial::value() const
{
@@ -447,6 +522,33 @@ void QQuickDial::setPressed(bool pressed)
}
/*!
+ \since QtQuick.Controls 2.2
+ \qmlproperty bool QtQuick.Controls::Dial::live
+
+ This property holds whether the dial provides live updates for the \l value
+ property while the handle is dragged.
+
+ The default value is \c false.
+
+ \sa value
+*/
+bool QQuickDial::live() const
+{
+ Q_D(const QQuickDial);
+ return d->live;
+}
+
+void QQuickDial::setLive(bool live)
+{
+ Q_D(QQuickDial);
+ if (d->live == live)
+ return;
+
+ d->live = live;
+ emit liveChanged();
+}
+
+/*!
\qmlmethod void QtQuick.Controls::Dial::increase()
Increases the value by \l stepSize, or \c 0.1 if stepSize is not defined.
@@ -505,6 +607,7 @@ void QQuickDial::setHandle(QQuickItem *handle)
void QQuickDial::keyPressEvent(QKeyEvent *event)
{
Q_D(QQuickDial);
+ const qreal oldValue = d->value;
switch (event->key()) {
case Qt::Key_Left:
case Qt::Key_Down:
@@ -539,6 +642,8 @@ void QQuickDial::keyPressEvent(QKeyEvent *event)
QQuickControl::keyPressEvent(event);
break;
}
+ if (!qFuzzyCompare(d->value, oldValue))
+ emit moved();
}
void QQuickDial::keyReleaseEvent(QKeyEvent *event)
@@ -551,8 +656,7 @@ void QQuickDial::mousePressEvent(QMouseEvent *event)
{
Q_D(QQuickDial);
QQuickControl::mousePressEvent(event);
- d->pressPoint = event->pos();
- setPressed(true);
+ d->handlePress(event->localPos());
}
void QQuickDial::mouseMoveEvent(QMouseEvent *event)
@@ -560,50 +664,87 @@ void QQuickDial::mouseMoveEvent(QMouseEvent *event)
Q_D(QQuickDial);
QQuickControl::mouseMoveEvent(event);
if (!keepMouseGrab()) {
- bool overXDragThreshold = QQuickWindowPrivate::dragOverThreshold(event->pos().x() - d->pressPoint.x(), Qt::XAxis, event);
+ bool overXDragThreshold = QQuickWindowPrivate::dragOverThreshold(event->localPos().x() - d->pressPoint.x(), Qt::XAxis, event);
setKeepMouseGrab(overXDragThreshold);
if (!overXDragThreshold) {
- bool overYDragThreshold = QQuickWindowPrivate::dragOverThreshold(event->pos().y() - d->pressPoint.y(), Qt::YAxis, event);
+ bool overYDragThreshold = QQuickWindowPrivate::dragOverThreshold(event->localPos().y() - d->pressPoint.y(), Qt::YAxis, event);
setKeepMouseGrab(overYDragThreshold);
}
}
- if (keepMouseGrab()) {
- qreal pos = d->positionAt(event->pos());
- if (d->snapMode == SnapAlways)
- pos = d->snapPosition(pos);
-
- if (d->wrap || (!d->wrap && !d->isLargeChange(event->pos(), pos)))
- d->setPosition(pos);
- }
+ d->handleMove(event->localPos());
}
void QQuickDial::mouseReleaseEvent(QMouseEvent *event)
{
Q_D(QQuickDial);
QQuickControl::mouseReleaseEvent(event);
+ d->handleRelease(event->localPos());
+}
- if (keepMouseGrab()) {
- qreal pos = d->positionAt(event->pos());
- if (d->snapMode != NoSnap)
- pos = d->snapPosition(pos);
+void QQuickDial::mouseUngrabEvent()
+{
+ Q_D(QQuickDial);
+ QQuickControl::mouseUngrabEvent();
+ d->handleUngrab();
+}
- if (d->wrap || (!d->wrap && !d->isLargeChange(event->pos(), pos)))
- setValue(d->valueAt(pos));
+void QQuickDial::touchEvent(QTouchEvent *event)
+{
+ Q_D(QQuickDial);
+ switch (event->type()) {
+ case QEvent::TouchBegin:
+ if (d->touchId == -1) {
+ const QTouchEvent::TouchPoint point = event->touchPoints().first();
+ d->touchId = point.id();
+ d->handlePress(point.pos());
+ } else {
+ event->ignore();
+ }
+ break;
- setKeepMouseGrab(false);
- }
+ case QEvent::TouchUpdate:
+ for (const QTouchEvent::TouchPoint &point : event->touchPoints()) {
+ if (point.id() != d->touchId)
+ continue;
+
+ if (!keepMouseGrab()) {
+ bool overXDragThreshold = QQuickWindowPrivate::dragOverThreshold(point.pos().x() - d->pressPoint.x(), Qt::XAxis, &point);
+ setKeepMouseGrab(overXDragThreshold);
+
+ if (!overXDragThreshold) {
+ bool overYDragThreshold = QQuickWindowPrivate::dragOverThreshold(point.pos().y() - d->pressPoint.y(), Qt::YAxis, &point);
+ setKeepMouseGrab(overYDragThreshold);
+ }
+ }
+ d->handleMove(point.pos());
+ }
+ break;
- setPressed(false);
- d->pressPoint = QPoint();
+ case QEvent::TouchEnd:
+ for (const QTouchEvent::TouchPoint &point : event->touchPoints()) {
+ if (point.id() != d->touchId)
+ continue;
+
+ d->handleRelease(point.pos());
+ }
+ break;
+
+ case QEvent::TouchCancel:
+ d->handleUngrab();
+ break;
+
+ default:
+ QQuickControl::touchEvent(event);
+ break;
+ }
}
-void QQuickDial::mouseUngrabEvent()
+void QQuickDial::touchUngrabEvent()
{
Q_D(QQuickDial);
- QQuickControl::mouseUngrabEvent();
- d->pressPoint = QPoint();
- setPressed(false);
+ QQuickControl::touchUngrabEvent();
+ d->handleUngrab();
}
void QQuickDial::wheelEvent(QWheelEvent *event)
diff --git a/src/quicktemplates2/qquickdial_p.h b/src/quicktemplates2/qquickdial_p.h
index 03d385fa..b42db960 100644
--- a/src/quicktemplates2/qquickdial_p.h
+++ b/src/quicktemplates2/qquickdial_p.h
@@ -69,6 +69,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickDial : public QQuickControl
Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged FINAL)
Q_PROPERTY(bool wrap READ wrap WRITE setWrap NOTIFY wrapChanged FINAL)
Q_PROPERTY(bool pressed READ isPressed NOTIFY pressedChanged FINAL)
+ Q_PROPERTY(bool live READ live WRITE setLive NOTIFY liveChanged FINAL REVISION 2)
Q_PROPERTY(QQuickItem *handle READ handle WRITE setHandle NOTIFY handleChanged FINAL)
public:
@@ -106,6 +107,9 @@ public:
bool isPressed() const;
void setPressed(bool pressed);
+ bool live() const;
+ void setLive(bool live);
+
QQuickItem *handle() const;
void setHandle(QQuickItem *handle);
@@ -123,7 +127,9 @@ Q_SIGNALS:
void snapModeChanged();
void wrapChanged();
void pressedChanged();
+ Q_REVISION(2) void liveChanged();
void handleChanged();
+ Q_REVISION(2) void moved();
protected:
void keyPressEvent(QKeyEvent *event) override;
@@ -132,6 +138,8 @@ protected:
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void mouseUngrabEvent() override;
+ void touchEvent(QTouchEvent *event) override;
+ void touchUngrabEvent() override;
void wheelEvent(QWheelEvent *event) override;
void mirrorChange() override;
diff --git a/src/quicktemplates2/qquickdialog.cpp b/src/quicktemplates2/qquickdialog.cpp
index 6d26dab8..4e239845 100644
--- a/src/quicktemplates2/qquickdialog.cpp
+++ b/src/quicktemplates2/qquickdialog.cpp
@@ -37,6 +37,7 @@
#include "qquickdialog_p.h"
#include "qquickdialog_p_p.h"
#include "qquickdialogbuttonbox_p.h"
+#include "qquickpopupitem_p_p.h"
QT_BEGIN_NAMESPACE
diff --git a/src/quicktemplates2/qquickdialogbuttonbox.cpp b/src/quicktemplates2/qquickdialogbuttonbox.cpp
index 0f362fcc..324a8399 100644
--- a/src/quicktemplates2/qquickdialogbuttonbox.cpp
+++ b/src/quicktemplates2/qquickdialogbuttonbox.cpp
@@ -359,7 +359,6 @@ QQuickDialogButtonBox::~QQuickDialogButtonBox()
{
}
-
/*!
\qmlproperty enumeration QtQuick.Controls::DialogButtonBox::position
diff --git a/src/quicktemplates2/qquickdrawer.cpp b/src/quicktemplates2/qquickdrawer.cpp
index 13d29bf4..91356b1d 100644
--- a/src/quicktemplates2/qquickdrawer.cpp
+++ b/src/quicktemplates2/qquickdrawer.cpp
@@ -36,6 +36,7 @@
#include "qquickdrawer_p.h"
#include "qquickdrawer_p_p.h"
+#include "qquickpopupitem_p_p.h"
#include <QtGui/qstylehints.h>
#include <QtGui/private/qguiapplication_p.h>
@@ -238,7 +239,7 @@ static bool dragOverThreshold(qreal d, Qt::Axis axis, QMouseEvent *event, int th
bool QQuickDrawerPrivate::startDrag(QQuickWindow *window, QMouseEvent *event)
{
- if (!window || dragMargin < 0.0 || qFuzzyIsNull(dragMargin))
+ if (!window || !interactive || dragMargin < 0.0 || qFuzzyIsNull(dragMargin))
return false;
bool drag = false;
@@ -271,7 +272,7 @@ bool QQuickDrawerPrivate::startDrag(QQuickWindow *window, QMouseEvent *event)
bool QQuickDrawerPrivate::grabMouse(QMouseEvent *event)
{
Q_Q(QQuickDrawer);
- if (!window || popupItem->keepMouseGrab())
+ if (!window || !interactive || popupItem->keepMouseGrab())
return false;
const QPointF movePoint = event->windowPos();
@@ -541,6 +542,8 @@ void QQuickDrawer::setPosition(qreal position)
prevents opening the drawer by dragging.
The default value is \c Qt.styleHints.startDragDistance.
+
+ \sa interactive
*/
qreal QQuickDrawer::dragMargin() const
{
@@ -563,6 +566,34 @@ void QQuickDrawer::resetDragMargin()
setDragMargin(QGuiApplication::styleHints()->startDragDistance());
}
+/*!
+ \since QtQuick.Controls 2.2
+ \qmlproperty bool QtQuick.Controls::Drawer::interactive
+
+ This property holds whether the drawer is interactive. A non-interactive
+ drawer does not react to swipes.
+
+ The default value is \c true.
+
+ \sa dragMargin
+*/
+bool QQuickDrawer::isInteractive() const
+{
+ Q_D(const QQuickDrawer);
+ return d->interactive;
+}
+
+void QQuickDrawer::setInteractive(bool interactive)
+{
+ Q_D(QQuickDrawer);
+ if (d->interactive == interactive)
+ return;
+
+ setFiltersChildMouseEvents(interactive);
+ d->interactive = interactive;
+ emit interactiveChanged();
+}
+
bool QQuickDrawer::childMouseEventFilter(QQuickItem *child, QEvent *event)
{
Q_D(QQuickDrawer);
diff --git a/src/quicktemplates2/qquickdrawer_p.h b/src/quicktemplates2/qquickdrawer_p.h
index ad64aed5..68b58362 100644
--- a/src/quicktemplates2/qquickdrawer_p.h
+++ b/src/quicktemplates2/qquickdrawer_p.h
@@ -60,6 +60,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickDrawer : public QQuickPopup
Q_PROPERTY(Qt::Edge edge READ edge WRITE setEdge NOTIFY edgeChanged FINAL)
Q_PROPERTY(qreal position READ position WRITE setPosition NOTIFY positionChanged FINAL)
Q_PROPERTY(qreal dragMargin READ dragMargin WRITE setDragMargin RESET resetDragMargin NOTIFY dragMarginChanged FINAL)
+ Q_PROPERTY(bool interactive READ isInteractive WRITE setInteractive NOTIFY interactiveChanged FINAL REVISION 2)
public:
explicit QQuickDrawer(QObject *parent = nullptr);
@@ -74,10 +75,14 @@ public:
void setDragMargin(qreal margin);
void resetDragMargin();
+ bool isInteractive() const;
+ void setInteractive(bool interactive);
+
Q_SIGNALS:
void edgeChanged();
void positionChanged();
void dragMarginChanged();
+ Q_REVISION(2) void interactiveChanged();
protected:
bool childMouseEventFilter(QQuickItem *child, QEvent *event) override;
diff --git a/src/quicktemplates2/qquickmenu_p_p.h b/src/quicktemplates2/qquickmenu_p_p.h
index f1aee427..504bc74d 100644
--- a/src/quicktemplates2/qquickmenu_p_p.h
+++ b/src/quicktemplates2/qquickmenu_p_p.h
@@ -98,4 +98,3 @@ public:
QT_END_NAMESPACE
#endif // QQUICKMENU_P_P_H
-
diff --git a/src/quicktemplates2/qquickoverlay.cpp b/src/quicktemplates2/qquickoverlay.cpp
index 12ecd284..94d3d86b 100644
--- a/src/quicktemplates2/qquickoverlay.cpp
+++ b/src/quicktemplates2/qquickoverlay.cpp
@@ -36,6 +36,7 @@
#include "qquickoverlay_p.h"
#include "qquickoverlay_p_p.h"
+#include "qquickpopupitem_p_p.h"
#include "qquickpopup_p_p.h"
#include "qquickdrawer_p_p.h"
#include "qquickapplicationwindow_p.h"
diff --git a/src/quicktemplates2/qquickpopup.cpp b/src/quicktemplates2/qquickpopup.cpp
index 3f3caf58..6690fac1 100644
--- a/src/quicktemplates2/qquickpopup.cpp
+++ b/src/quicktemplates2/qquickpopup.cpp
@@ -36,14 +36,13 @@
#include "qquickpopup_p.h"
#include "qquickpopup_p_p.h"
+#include "qquickpopupitem_p_p.h"
+#include "qquickpopuppositioner_p_p.h"
#include "qquickapplicationwindow_p.h"
-#include "qquickshortcutcontext_p_p.h"
#include "qquickoverlay_p_p.h"
#include "qquickcontrol_p_p.h"
#include "qquickdialog_p.h"
-#include <QtGui/private/qshortcutmap_p.h>
-#include <QtGui/private/qguiapplication_p.h>
#include <QtQml/qqmlinfo.h>
#include <QtQuick/qquickitem.h>
#include <QtQuick/private/qquicktransition_p.h>
@@ -188,13 +187,6 @@ QT_BEGIN_NAMESPACE
\sa opened
*/
-static const QQuickItemPrivate::ChangeTypes AncestorChangeTypes = QQuickItemPrivate::Geometry
- | QQuickItemPrivate::Parent
- | QQuickItemPrivate::Children;
-
-static const QQuickItemPrivate::ChangeTypes ItemChangeTypes = QQuickItemPrivate::Geometry
- | QQuickItemPrivate::Parent;
-
QQuickPopupPrivate::QQuickPopupPrivate()
: QObjectPrivate()
, focus(false)
@@ -217,6 +209,7 @@ QQuickPopupPrivate::QQuickPopupPrivate()
, allowVerticalResize(true)
, allowHorizontalResize(true)
, hadActiveFocusBeforeExitTransition(false)
+ , interactive(true)
, x(0)
, y(0)
, effectiveX(0)
@@ -236,7 +229,7 @@ QQuickPopupPrivate::QQuickPopupPrivate()
, enter(nullptr)
, exit(nullptr)
, popupItem(nullptr)
- , positioner(this)
+ , positioner(nullptr)
, transitionManager(this)
{
}
@@ -251,26 +244,30 @@ void QQuickPopupPrivate::init()
popupItem = new QQuickPopupItem(q);
q->setParentItem(qobject_cast<QQuickItem *>(parent));
QObject::connect(popupItem, &QQuickControl::paddingChanged, q, &QQuickPopup::paddingChanged);
+ positioner = new QQuickPopupPositioner(q);
}
-static void closeOrReject(QQuickPopup *popup)
+void QQuickPopupPrivate::closeOrReject()
{
- if (QQuickDialog *dialog = qobject_cast<QQuickDialog*>(popup))
+ Q_Q(QQuickPopup);
+ if (QQuickDialog *dialog = qobject_cast<QQuickDialog*>(q))
dialog->reject();
else
- popup->close();
+ q->close();
}
bool QQuickPopupPrivate::tryClose(QQuickItem *item, QMouseEvent *event)
{
- Q_Q(QQuickPopup);
+ if (!interactive)
+ return false;
+
const bool isPress = event->type() == QEvent::MouseButtonPress;
const bool onOutside = closePolicy.testFlag(isPress ? QQuickPopup::CloseOnPressOutside : QQuickPopup::CloseOnReleaseOutside);
const bool onOutsideParent = closePolicy.testFlag(isPress ? QQuickPopup::CloseOnPressOutsideParent : QQuickPopup::CloseOnReleaseOutsideParent);
if (onOutside || onOutsideParent) {
if (!popupItem->contains(item->mapToItem(popupItem, event->pos()))) {
if (!onOutsideParent || !parentItem || !parentItem->contains(item->mapToItem(parentItem, event->pos()))) {
- closeOrReject(q);
+ closeOrReject();
return true;
}
}
@@ -295,7 +292,7 @@ bool QQuickPopupPrivate::prepareEnterTransition()
visible = true;
transitionState = EnterTransition;
popupItem->setVisible(true);
- positioner.setParentItem(parentItem);
+ positioner->setParentItem(parentItem);
emit q->visibleChanged();
}
return true;
@@ -332,7 +329,7 @@ void QQuickPopupPrivate::finalizeEnterTransition()
void QQuickPopupPrivate::finalizeExitTransition()
{
Q_Q(QQuickPopup);
- positioner.setParentItem(nullptr);
+ positioner->setParentItem(nullptr);
popupItem->setParentItem(nullptr);
popupItem->setVisible(false);
@@ -433,314 +430,6 @@ void QQuickPopupPrivate::setWindow(QQuickWindow *newWindow)
emit q->windowChanged(newWindow);
}
-class QQuickPopupItemPrivate : public QQuickControlPrivate
-{
- Q_DECLARE_PUBLIC(QQuickPopupItem)
-
-public:
- QQuickPopupItemPrivate(QQuickPopup *popup);
-
- void implicitWidthChanged() override;
- void implicitHeightChanged() override;
-
- void resolveFont() override;
-
- QQuickItem *getContentItem() override;
-
- int backId;
- int escapeId;
- QQuickPopup *popup;
-};
-
-QQuickPopupItemPrivate::QQuickPopupItemPrivate(QQuickPopup *popup)
- : backId(0),
- escapeId(0),
- popup(popup)
-{
- isTabFence = true;
-}
-
-void QQuickPopupItemPrivate::implicitWidthChanged()
-{
- QQuickControlPrivate::implicitWidthChanged();
- emit popup->implicitWidthChanged();
-}
-
-void QQuickPopupItemPrivate::implicitHeightChanged()
-{
- QQuickControlPrivate::implicitHeightChanged();
- emit popup->implicitHeightChanged();
-}
-
-void QQuickPopupItemPrivate::resolveFont()
-{
- if (QQuickApplicationWindow *window = qobject_cast<QQuickApplicationWindow *>(popup->window()))
- inheritFont(window->font());
-}
-
-QQuickItem *QQuickPopupItemPrivate::getContentItem()
-{
- Q_Q(QQuickPopupItem);
- if (!contentItem)
- contentItem = new QQuickItem(q);
- return contentItem;
-}
-
-QQuickPopupItem::QQuickPopupItem(QQuickPopup *popup) :
- QQuickControl(*(new QQuickPopupItemPrivate(popup)), nullptr)
-{
- setParent(popup);
- setVisible(false);
- setFlag(ItemIsFocusScope);
- setAcceptedMouseButtons(Qt::AllButtons);
-
- // TODO: switch to QStyleHints::useHoverEffects in Qt 5.8
- setHoverEnabled(true);
- // setAcceptHoverEvents(QGuiApplication::styleHints()->useHoverEffects());
- // connect(QGuiApplication::styleHints(), &QStyleHints::useHoverEffectsChanged, this, &QQuickItem::setAcceptHoverEvents);
-}
-
-void QQuickPopupItem::updatePolish()
-{
- Q_D(QQuickPopupItem);
- return QQuickPopupPrivate::get(d->popup)->reposition();
-}
-
-void QQuickPopupItem::grabShortcut()
-{
-#ifndef QT_NO_SHORTCUT
- Q_D(QQuickPopupItem);
- QGuiApplicationPrivate *pApp = QGuiApplicationPrivate::instance();
- if (!d->backId)
- d->backId = pApp->shortcutMap.addShortcut(this, Qt::Key_Back, Qt::WindowShortcut, QQuickShortcutContext::matcher);
- if (!d->escapeId)
- d->escapeId = pApp->shortcutMap.addShortcut(this, Qt::Key_Escape, Qt::WindowShortcut, QQuickShortcutContext::matcher);
-#endif // QT_NO_SHORTCUT
-}
-
-void QQuickPopupItem::ungrabShortcut()
-{
-#ifndef QT_NO_SHORTCUT
- Q_D(QQuickPopupItem);
- QGuiApplicationPrivate *pApp = QGuiApplicationPrivate::instance();
- if (d->backId) {
- pApp->shortcutMap.removeShortcut(d->backId, this);
- d->backId = 0;
- }
- if (d->escapeId) {
- pApp->shortcutMap.removeShortcut(d->escapeId, this);
- d->escapeId = 0;
- }
-#endif // QT_NO_SHORTCUT
-}
-
-bool QQuickPopupItem::event(QEvent *event)
-{
- Q_D(QQuickPopupItem);
- if (event->type() == QEvent::Shortcut) {
- QShortcutEvent *se = static_cast<QShortcutEvent *>(event);
- if (se->shortcutId() == d->escapeId || se->shortcutId() == d->backId) {
- closeOrReject(d->popup);
- return true;
- }
- }
- return QQuickItem::event(event);
-}
-
-bool QQuickPopupItem::childMouseEventFilter(QQuickItem *child, QEvent *event)
-{
- Q_D(QQuickPopupItem);
- return d->popup->childMouseEventFilter(child, event);
-}
-
-void QQuickPopupItem::focusInEvent(QFocusEvent *event)
-{
- Q_D(QQuickPopupItem);
- d->popup->focusInEvent(event);
-}
-
-void QQuickPopupItem::focusOutEvent(QFocusEvent *event)
-{
- Q_D(QQuickPopupItem);
- d->popup->focusOutEvent(event);
-}
-
-void QQuickPopupItem::keyPressEvent(QKeyEvent *event)
-{
- Q_D(QQuickPopupItem);
- d->popup->keyPressEvent(event);
-}
-
-void QQuickPopupItem::keyReleaseEvent(QKeyEvent *event)
-{
- Q_D(QQuickPopupItem);
- d->popup->keyReleaseEvent(event);
-}
-
-void QQuickPopupItem::mousePressEvent(QMouseEvent *event)
-{
- Q_D(QQuickPopupItem);
- d->popup->mousePressEvent(event);
-}
-
-void QQuickPopupItem::mouseMoveEvent(QMouseEvent *event)
-{
- Q_D(QQuickPopupItem);
- d->popup->mouseMoveEvent(event);
-}
-
-void QQuickPopupItem::mouseReleaseEvent(QMouseEvent *event)
-{
- Q_D(QQuickPopupItem);
- d->popup->mouseReleaseEvent(event);
-}
-
-void QQuickPopupItem::mouseDoubleClickEvent(QMouseEvent *event)
-{
- Q_D(QQuickPopupItem);
- d->popup->mouseDoubleClickEvent(event);
-}
-
-void QQuickPopupItem::mouseUngrabEvent()
-{
- Q_D(QQuickPopupItem);
- d->popup->mouseUngrabEvent();
-}
-
-void QQuickPopupItem::wheelEvent(QWheelEvent *event)
-{
- Q_D(QQuickPopupItem);
- d->popup->wheelEvent(event);
-}
-
-void QQuickPopupItem::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem)
-{
- Q_D(QQuickPopupItem);
- QQuickControl::contentItemChange(newItem, oldItem);
- d->popup->contentItemChange(newItem, oldItem);
-}
-
-void QQuickPopupItem::fontChange(const QFont &newFont, const QFont &oldFont)
-{
- Q_D(QQuickPopupItem);
- QQuickControl::fontChange(newFont, oldFont);
- d->popup->fontChange(newFont, oldFont);
-}
-
-void QQuickPopupItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
-{
- Q_D(QQuickPopupItem);
- QQuickControl::geometryChanged(newGeometry, oldGeometry);
- d->popup->geometryChanged(newGeometry, oldGeometry);
-}
-
-void QQuickPopupItem::localeChange(const QLocale &newLocale, const QLocale &oldLocale)
-{
- Q_D(QQuickPopupItem);
- QQuickControl::localeChange(newLocale, oldLocale);
- d->popup->localeChange(newLocale, oldLocale);
-}
-
-void QQuickPopupItem::itemChange(ItemChange change, const ItemChangeData &data)
-{
- Q_D(QQuickPopupItem);
- QQuickControl::itemChange(change, data);
- d->popup->itemChange(change, data);
-}
-
-void QQuickPopupItem::paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding)
-{
- Q_D(QQuickPopupItem);
- QQuickControl::paddingChange(newPadding, oldPadding);
- d->popup->paddingChange(newPadding, oldPadding);
-}
-
-void QQuickPopupItem::spacingChange(qreal newSpacing, qreal oldSpacing)
-{
- Q_D(QQuickPopupItem);
- QQuickControl::spacingChange(newSpacing, oldSpacing);
- d->popup->spacingChange(newSpacing, oldSpacing);
-}
-
-QFont QQuickPopupItem::defaultFont() const
-{
- Q_D(const QQuickPopupItem);
- return d->popup->defaultFont();
-}
-
-#ifndef QT_NO_ACCESSIBILITY
-QAccessible::Role QQuickPopupItem::accessibleRole() const
-{
- Q_D(const QQuickPopupItem);
- return d->popup->accessibleRole();
-}
-
-void QQuickPopupItem::accessibilityActiveChanged(bool active)
-{
- Q_D(const QQuickPopupItem);
- QQuickControl::accessibilityActiveChanged(active);
- d->popup->accessibilityActiveChanged(active);
-}
-#endif // QT_NO_ACCESSIBILITY
-
-QQuickPopupPositioner::QQuickPopupPositioner(QQuickPopupPrivate *popup) :
- m_parentItem(nullptr),
- m_popup(popup)
-{
-}
-
-QQuickPopupPositioner::~QQuickPopupPositioner()
-{
- if (m_parentItem) {
- QQuickItemPrivate::get(m_parentItem)->removeItemChangeListener(this, ItemChangeTypes);
- removeAncestorListeners(m_parentItem->parentItem());
- }
-}
-
-QQuickItem *QQuickPopupPositioner::parentItem() const
-{
- return m_parentItem;
-}
-
-void QQuickPopupPositioner::setParentItem(QQuickItem *parent)
-{
- if (m_parentItem == parent)
- return;
-
- if (m_parentItem) {
- QQuickItemPrivate::get(m_parentItem)->removeItemChangeListener(this, ItemChangeTypes);
- removeAncestorListeners(m_parentItem->parentItem());
- }
-
- m_parentItem = parent;
-
- if (!parent)
- return;
-
- QQuickItemPrivate::get(parent)->addItemChangeListener(this, ItemChangeTypes);
- addAncestorListeners(parent->parentItem());
-
- if (m_popup->popupItem->isVisible())
- m_popup->reposition();
-}
-
-void QQuickPopupPositioner::itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &)
-{
- if (m_parentItem && m_popup->popupItem->isVisible())
- m_popup->reposition();
-}
-
-void QQuickPopupPositioner::itemParentChanged(QQuickItem *, QQuickItem *parent)
-{
- addAncestorListeners(parent);
-}
-
-void QQuickPopupPositioner::itemChildRemoved(QQuickItem *item, QQuickItem *child)
-{
- if (isAncestor(child))
- removeAncestorListeners(item);
-}
-
void QQuickPopupPrivate::itemDestroyed(QQuickItem *item)
{
Q_Q(QQuickPopup);
@@ -750,143 +439,7 @@ void QQuickPopupPrivate::itemDestroyed(QQuickItem *item)
void QQuickPopupPrivate::reposition()
{
- Q_Q(QQuickPopup);
- if (!popupItem->isVisible())
- return;
-
- if (positioning) {
- popupItem->polish();
- return;
- }
-
- const qreal w = popupItem->width();
- const qreal h = popupItem->height();
- const qreal iw = popupItem->implicitWidth();
- const qreal ih = popupItem->implicitHeight();
-
- bool widthAdjusted = false;
- bool heightAdjusted = false;
-
- QRectF rect(allowHorizontalMove ? x : popupItem->x(),
- allowVerticalMove ? y : popupItem->y(),
- !hasWidth && iw > 0 ? iw : w,
- !hasHeight && ih > 0 ? ih : h);
- if (parentItem) {
- rect = parentItem->mapRectToScene(rect);
-
- if (window) {
- const QMarginsF margins = getMargins();
- const QRectF bounds(qMax<qreal>(0.0, margins.left()),
- qMax<qreal>(0.0, margins.top()),
- window->width() - qMax<qreal>(0.0, margins.left()) - qMax<qreal>(0.0, margins.right()),
- window->height() - qMax<qreal>(0.0, margins.top()) - qMax<qreal>(0.0, margins.bottom()));
-
- // if the popup doesn't fit horizontally inside the window, try flipping it around (left <-> right)
- if (allowHorizontalFlip && (rect.left() < bounds.left() || rect.right() > bounds.right())) {
- const QRectF flipped = parentItem->mapRectToScene(QRectF(parentItem->width() - x - rect.width(), y, rect.width(), rect.height()));
- if (flipped.intersected(bounds).width() > rect.intersected(bounds).width())
- rect.moveLeft(flipped.left());
- }
-
- // if the popup doesn't fit vertically inside the window, try flipping it around (above <-> below)
- if (allowVerticalFlip && (rect.top() < bounds.top() || rect.bottom() > bounds.bottom())) {
- const QRectF flipped = parentItem->mapRectToScene(QRectF(x, parentItem->height() - y - rect.height(), rect.width(), rect.height()));
- if (flipped.intersected(bounds).height() > rect.intersected(bounds).height())
- rect.moveTop(flipped.top());
- }
-
- // push inside the margins if specified
- if (allowVerticalMove) {
- if (margins.top() >= 0 && rect.top() < bounds.top())
- rect.moveTop(margins.top());
- if (margins.bottom() >= 0 && rect.bottom() > bounds.bottom())
- rect.moveBottom(bounds.bottom());
- }
- if (allowHorizontalMove) {
- if (margins.left() >= 0 && rect.left() < bounds.left())
- rect.moveLeft(margins.left());
- if (margins.right() >= 0 && rect.right() > bounds.right())
- rect.moveRight(bounds.right());
- }
-
- if (iw > 0 && (rect.left() < bounds.left() || rect.right() > bounds.right())) {
- // neither the flipped or pushed geometry fits inside the window, choose
- // whichever side (left vs. right) fits larger part of the popup
- if (allowHorizontalMove && allowHorizontalFlip) {
- if (rect.left() < bounds.left() && bounds.left() + rect.width() <= bounds.right())
- rect.moveLeft(bounds.left());
- else if (rect.right() > bounds.right() && bounds.right() - rect.width() >= bounds.left())
- rect.moveRight(bounds.right());
- }
-
- // as a last resort, adjust the width to fit the window
- if (allowHorizontalResize) {
- if (rect.left() < bounds.left()) {
- rect.setLeft(bounds.left());
- widthAdjusted = true;
- }
- if (rect.right() > bounds.right()) {
- rect.setRight(bounds.right());
- widthAdjusted = true;
- }
- }
- } else if (iw > 0 && rect.left() >= bounds.left() && rect.right() <= bounds.right()
- && iw != w) {
- // restore original width
- rect.setWidth(iw);
- widthAdjusted = true;
- }
-
- if (ih > 0 && (rect.top() < bounds.top() || rect.bottom() > bounds.bottom())) {
- // neither the flipped or pushed geometry fits inside the window, choose
- // whichever side (above vs. below) fits larger part of the popup
- if (allowVerticalMove && allowVerticalFlip) {
- if (rect.top() < bounds.top() && bounds.top() + rect.height() <= bounds.bottom())
- rect.moveTop(bounds.top());
- else if (rect.bottom() > bounds.bottom() && bounds.bottom() - rect.height() >= bounds.top())
- rect.moveBottom(bounds.bottom());
- }
-
- // as a last resort, adjust the height to fit the window
- if (allowVerticalResize) {
- if (rect.top() < bounds.top()) {
- rect.setTop(bounds.top());
- heightAdjusted = true;
- }
- if (rect.bottom() > bounds.bottom()) {
- rect.setBottom(bounds.bottom());
- heightAdjusted = true;
- }
- }
- } else if (ih > 0 && rect.top() >= bounds.top() && rect.bottom() <= bounds.bottom()
- && ih != h) {
- // restore original height
- rect.setHeight(ih);
- heightAdjusted = true;
- }
- }
- }
-
- positioning = true;
-
- popupItem->setPosition(rect.topLeft());
-
- const QPointF effectivePos = parentItem ? parentItem->mapFromScene(rect.topLeft()) : rect.topLeft();
- if (!qFuzzyCompare(effectiveX, effectivePos.x())) {
- effectiveX = effectivePos.x();
- emit q->xChanged();
- }
- if (!qFuzzyCompare(effectiveY, effectivePos.y())) {
- effectiveY = effectivePos.y();
- emit q->yChanged();
- }
-
- if (!hasWidth && widthAdjusted && rect.width() > 0)
- popupItem->setWidth(rect.width());
- if (!hasHeight && heightAdjusted && rect.height() > 0)
- popupItem->setHeight(rect.height());
-
- positioning = false;
+ positioner->reposition();
}
void QQuickPopupPrivate::resizeOverlay()
@@ -899,45 +452,6 @@ void QQuickPopupPrivate::resizeOverlay()
dimmer->setSize(QSizeF(w, h));
}
-void QQuickPopupPositioner::removeAncestorListeners(QQuickItem *item)
-{
- if (item == m_parentItem)
- return;
-
- QQuickItem *p = item;
- while (p) {
- QQuickItemPrivate::get(p)->removeItemChangeListener(this, AncestorChangeTypes);
- p = p->parentItem();
- }
-}
-
-void QQuickPopupPositioner::addAncestorListeners(QQuickItem *item)
-{
- if (item == m_parentItem)
- return;
-
- QQuickItem *p = item;
- while (p) {
- QQuickItemPrivate::get(p)->addItemChangeListener(this, AncestorChangeTypes);
- p = p->parentItem();
- }
-}
-
-// TODO: use QQuickItem::isAncestorOf() in dev/5.7
-bool QQuickPopupPositioner::isAncestor(QQuickItem *item) const
-{
- if (!m_parentItem)
- return false;
-
- QQuickItem *parent = m_parentItem;
- while (parent) {
- if (parent == item)
- return true;
- parent = parent->parentItem();
- }
- return false;
-}
-
QQuickPopupTransitionManager::QQuickPopupTransitionManager(QQuickPopupPrivate *popup)
: QQuickTransitionManager(), popup(popup)
{
@@ -1719,8 +1233,8 @@ void QQuickPopup::setParentItem(QQuickItem *parent)
QQuickItemPrivate::get(d->parentItem)->removeItemChangeListener(d, QQuickItemPrivate::Destroyed);
}
d->parentItem = parent;
- if (d->positioner.parentItem())
- d->positioner.setParentItem(parent);
+ if (d->positioner->parentItem())
+ d->positioner->setParentItem(parent);
if (parent) {
QObjectPrivate::connect(parent, &QQuickItem::windowChanged, d, &QQuickPopupPrivate::setWindow);
QQuickItemPrivate::get(d->parentItem)->addItemChangeListener(d, QQuickItemPrivate::Destroyed);
@@ -2456,5 +1970,3 @@ bool QQuickPopup::setAccessibleProperty(const char *propertyName, const QVariant
}
QT_END_NAMESPACE
-
-#include "moc_qquickpopup_p.cpp"
diff --git a/src/quicktemplates2/qquickpopup_p_p.h b/src/quicktemplates2/qquickpopup_p_p.h
index 29c9f42e..084642ec 100644
--- a/src/quicktemplates2/qquickpopup_p_p.h
+++ b/src/quicktemplates2/qquickpopup_p_p.h
@@ -61,8 +61,9 @@ QT_BEGIN_NAMESPACE
class QQuickTransition;
class QQuickTransitionManager;
class QQuickPopup;
+class QQuickPopupItem;
class QQuickPopupPrivate;
-class QQuickPopupItemPrivate;
+class QQuickPopupPositioner;
class QQuickPopupTransitionManager : public QQuickTransitionManager
{
@@ -79,77 +80,6 @@ private:
QQuickPopupPrivate *popup;
};
-class QQuickPopupItem : public QQuickControl
-{
- Q_OBJECT
-
-public:
- explicit QQuickPopupItem(QQuickPopup *popup);
-
- void grabShortcut();
- void ungrabShortcut();
-
-protected:
- void updatePolish() override;
-
- bool event(QEvent *event) override;
- bool childMouseEventFilter(QQuickItem *child, QEvent *event) override;
- void focusInEvent(QFocusEvent *event) override;
- void focusOutEvent(QFocusEvent *event) override;
- void keyPressEvent(QKeyEvent *event) override;
- void keyReleaseEvent(QKeyEvent *event) override;
- void mousePressEvent(QMouseEvent *event) override;
- void mouseMoveEvent(QMouseEvent *event) override;
- void mouseReleaseEvent(QMouseEvent *event) override;
- void mouseDoubleClickEvent(QMouseEvent *event) override;
- void mouseUngrabEvent() override;
- void wheelEvent(QWheelEvent *event) override;
-
- void contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) override;
- void fontChange(const QFont &newFont, const QFont &oldFont) override;
- void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override;
- void localeChange(const QLocale &newLocale, const QLocale &oldLocale) override;
- void itemChange(ItemChange change, const ItemChangeData &data) override;
- void paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding) override;
- void spacingChange(qreal newSpacing, qreal oldSpacing) override;
-
- QFont defaultFont() const override;
-
-#ifndef QT_NO_ACCESSIBILITY
- QAccessible::Role accessibleRole() const override;
- void accessibilityActiveChanged(bool active) override;
-#endif
-
-private:
- Q_DECLARE_PRIVATE(QQuickPopupItem)
-
- friend class QQuickPopup;
-};
-
-class QQuickPopupPositioner : public QQuickItemChangeListener
-{
-public:
- explicit QQuickPopupPositioner(QQuickPopupPrivate *popup);
- ~QQuickPopupPositioner();
-
- QQuickItem *parentItem() const;
- void setParentItem(QQuickItem *parent);
-
-protected:
- void itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &) override;
- void itemParentChanged(QQuickItem *, QQuickItem *parent) override;
- void itemChildRemoved(QQuickItem *, QQuickItem *child) override;
-
-private:
- void removeAncestorListeners(QQuickItem *item);
- void addAncestorListeners(QQuickItem *item);
-
- bool isAncestor(QQuickItem *item) const;
-
- QQuickItem *m_parentItem;
- QQuickPopupPrivate *m_popup;
-};
-
class Q_AUTOTEST_EXPORT QQuickPopupPrivate : public QObjectPrivate, public QQuickItemChangeListener
{
Q_DECLARE_PUBLIC(QQuickPopup)
@@ -164,6 +94,7 @@ public:
}
void init();
+ void closeOrReject();
bool tryClose(QQuickItem *item, QMouseEvent *event);
virtual void reposition();
virtual void resizeOverlay();
@@ -207,6 +138,7 @@ public:
bool allowVerticalResize;
bool allowHorizontalResize;
bool hadActiveFocusBeforeExitTransition;
+ bool interactive;
qreal x;
qreal y;
qreal effectiveX;
@@ -226,7 +158,7 @@ public:
QQuickTransition *enter;
QQuickTransition *exit;
QQuickPopupItem *popupItem;
- QQuickPopupPositioner positioner;
+ QQuickPopupPositioner *positioner;
QList<QQuickStateAction> enterActions;
QList<QQuickStateAction> exitActions;
QQuickPopupTransitionManager transitionManager;
diff --git a/src/quicktemplates2/qquickpopupitem.cpp b/src/quicktemplates2/qquickpopupitem.cpp
new file mode 100644
index 00000000..8a84cc20
--- /dev/null
+++ b/src/quicktemplates2/qquickpopupitem.cpp
@@ -0,0 +1,294 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickpopupitem_p_p.h"
+#include "qquickapplicationwindow_p.h"
+#include "qquickshortcutcontext_p_p.h"
+#include "qquickcontrol_p_p.h"
+#include "qquickpopup_p_p.h"
+
+#include <QtGui/private/qshortcutmap_p.h>
+#include <QtGui/private/qguiapplication_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickPopupItemPrivate : public QQuickControlPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickPopupItem)
+
+public:
+ QQuickPopupItemPrivate(QQuickPopup *popup);
+
+ void implicitWidthChanged() override;
+ void implicitHeightChanged() override;
+
+ void resolveFont() override;
+
+ QQuickItem *getContentItem() override;
+
+ int backId;
+ int escapeId;
+ QQuickPopup *popup;
+};
+
+QQuickPopupItemPrivate::QQuickPopupItemPrivate(QQuickPopup *popup)
+ : backId(0),
+ escapeId(0),
+ popup(popup)
+{
+ isTabFence = true;
+}
+
+void QQuickPopupItemPrivate::implicitWidthChanged()
+{
+ QQuickControlPrivate::implicitWidthChanged();
+ emit popup->implicitWidthChanged();
+}
+
+void QQuickPopupItemPrivate::implicitHeightChanged()
+{
+ QQuickControlPrivate::implicitHeightChanged();
+ emit popup->implicitHeightChanged();
+}
+
+void QQuickPopupItemPrivate::resolveFont()
+{
+ if (QQuickApplicationWindow *window = qobject_cast<QQuickApplicationWindow *>(popup->window()))
+ inheritFont(window->font());
+}
+
+QQuickItem *QQuickPopupItemPrivate::getContentItem()
+{
+ Q_Q(QQuickPopupItem);
+ if (!contentItem)
+ contentItem = new QQuickItem(q);
+ return contentItem;
+}
+
+QQuickPopupItem::QQuickPopupItem(QQuickPopup *popup) :
+ QQuickControl(*(new QQuickPopupItemPrivate(popup)), nullptr)
+{
+ setParent(popup);
+ setVisible(false);
+ setFlag(ItemIsFocusScope);
+ setAcceptedMouseButtons(Qt::AllButtons);
+
+ // TODO: switch to QStyleHints::useHoverEffects in Qt 5.8
+ setHoverEnabled(true);
+ // setAcceptHoverEvents(QGuiApplication::styleHints()->useHoverEffects());
+ // connect(QGuiApplication::styleHints(), &QStyleHints::useHoverEffectsChanged, this, &QQuickItem::setAcceptHoverEvents);
+}
+
+void QQuickPopupItem::grabShortcut()
+{
+#ifndef QT_NO_SHORTCUT
+ Q_D(QQuickPopupItem);
+ QGuiApplicationPrivate *pApp = QGuiApplicationPrivate::instance();
+ if (!d->backId)
+ d->backId = pApp->shortcutMap.addShortcut(this, Qt::Key_Back, Qt::WindowShortcut, QQuickShortcutContext::matcher);
+ if (!d->escapeId)
+ d->escapeId = pApp->shortcutMap.addShortcut(this, Qt::Key_Escape, Qt::WindowShortcut, QQuickShortcutContext::matcher);
+#endif // QT_NO_SHORTCUT
+}
+
+void QQuickPopupItem::ungrabShortcut()
+{
+#ifndef QT_NO_SHORTCUT
+ Q_D(QQuickPopupItem);
+ QGuiApplicationPrivate *pApp = QGuiApplicationPrivate::instance();
+ if (d->backId) {
+ pApp->shortcutMap.removeShortcut(d->backId, this);
+ d->backId = 0;
+ }
+ if (d->escapeId) {
+ pApp->shortcutMap.removeShortcut(d->escapeId, this);
+ d->escapeId = 0;
+ }
+#endif // QT_NO_SHORTCUT
+}
+
+void QQuickPopupItem::updatePolish()
+{
+ Q_D(QQuickPopupItem);
+ return QQuickPopupPrivate::get(d->popup)->reposition();
+}
+
+bool QQuickPopupItem::event(QEvent *event)
+{
+ Q_D(QQuickPopupItem);
+ if (event->type() == QEvent::Shortcut) {
+ QShortcutEvent *se = static_cast<QShortcutEvent *>(event);
+ if (se->shortcutId() == d->escapeId || se->shortcutId() == d->backId) {
+ QQuickPopupPrivate *p = QQuickPopupPrivate::get(d->popup);
+ if (p->interactive) {
+ p->closeOrReject();
+ return true;
+ }
+ }
+ }
+ return QQuickItem::event(event);
+}
+
+bool QQuickPopupItem::childMouseEventFilter(QQuickItem *child, QEvent *event)
+{
+ Q_D(QQuickPopupItem);
+ return d->popup->childMouseEventFilter(child, event);
+}
+
+void QQuickPopupItem::focusInEvent(QFocusEvent *event)
+{
+ Q_D(QQuickPopupItem);
+ d->popup->focusInEvent(event);
+}
+
+void QQuickPopupItem::focusOutEvent(QFocusEvent *event)
+{
+ Q_D(QQuickPopupItem);
+ d->popup->focusOutEvent(event);
+}
+
+void QQuickPopupItem::keyPressEvent(QKeyEvent *event)
+{
+ Q_D(QQuickPopupItem);
+ d->popup->keyPressEvent(event);
+}
+
+void QQuickPopupItem::keyReleaseEvent(QKeyEvent *event)
+{
+ Q_D(QQuickPopupItem);
+ d->popup->keyReleaseEvent(event);
+}
+
+void QQuickPopupItem::mousePressEvent(QMouseEvent *event)
+{
+ Q_D(QQuickPopupItem);
+ d->popup->mousePressEvent(event);
+}
+
+void QQuickPopupItem::mouseMoveEvent(QMouseEvent *event)
+{
+ Q_D(QQuickPopupItem);
+ d->popup->mouseMoveEvent(event);
+}
+
+void QQuickPopupItem::mouseReleaseEvent(QMouseEvent *event)
+{
+ Q_D(QQuickPopupItem);
+ d->popup->mouseReleaseEvent(event);
+}
+
+void QQuickPopupItem::mouseDoubleClickEvent(QMouseEvent *event)
+{
+ Q_D(QQuickPopupItem);
+ d->popup->mouseDoubleClickEvent(event);
+}
+
+void QQuickPopupItem::mouseUngrabEvent()
+{
+ Q_D(QQuickPopupItem);
+ d->popup->mouseUngrabEvent();
+}
+
+void QQuickPopupItem::wheelEvent(QWheelEvent *event)
+{
+ Q_D(QQuickPopupItem);
+ d->popup->wheelEvent(event);
+}
+
+void QQuickPopupItem::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem)
+{
+ Q_D(QQuickPopupItem);
+ QQuickControl::contentItemChange(newItem, oldItem);
+ d->popup->contentItemChange(newItem, oldItem);
+}
+
+void QQuickPopupItem::fontChange(const QFont &newFont, const QFont &oldFont)
+{
+ Q_D(QQuickPopupItem);
+ QQuickControl::fontChange(newFont, oldFont);
+ d->popup->fontChange(newFont, oldFont);
+}
+
+void QQuickPopupItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ Q_D(QQuickPopupItem);
+ QQuickControl::geometryChanged(newGeometry, oldGeometry);
+ d->popup->geometryChanged(newGeometry, oldGeometry);
+}
+
+void QQuickPopupItem::localeChange(const QLocale &newLocale, const QLocale &oldLocale)
+{
+ Q_D(QQuickPopupItem);
+ QQuickControl::localeChange(newLocale, oldLocale);
+ d->popup->localeChange(newLocale, oldLocale);
+}
+
+void QQuickPopupItem::itemChange(ItemChange change, const ItemChangeData &data)
+{
+ Q_D(QQuickPopupItem);
+ QQuickControl::itemChange(change, data);
+ d->popup->itemChange(change, data);
+}
+
+void QQuickPopupItem::paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding)
+{
+ Q_D(QQuickPopupItem);
+ QQuickControl::paddingChange(newPadding, oldPadding);
+ d->popup->paddingChange(newPadding, oldPadding);
+}
+
+QFont QQuickPopupItem::defaultFont() const
+{
+ Q_D(const QQuickPopupItem);
+ return d->popup->defaultFont();
+}
+
+#ifndef QT_NO_ACCESSIBILITY
+QAccessible::Role QQuickPopupItem::accessibleRole() const
+{
+ Q_D(const QQuickPopupItem);
+ return d->popup->accessibleRole();
+}
+
+void QQuickPopupItem::accessibilityActiveChanged(bool active)
+{
+ Q_D(const QQuickPopupItem);
+ QQuickControl::accessibilityActiveChanged(active);
+ d->popup->accessibilityActiveChanged(active);
+}
+#endif // QT_NO_ACCESSIBILITY
+
+QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickpopupitem_p_p.h b/src/quicktemplates2/qquickpopupitem_p_p.h
new file mode 100644
index 00000000..c6d5e7d2
--- /dev/null
+++ b/src/quicktemplates2/qquickpopupitem_p_p.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKPOPUPITEM_P_P_H
+#define QQUICKPOPUPITEM_P_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qquickcontrol_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QQuickPopup;
+class QQuickPopupItemPrivate;
+
+class QQuickPopupItem : public QQuickControl
+{
+ Q_OBJECT
+
+public:
+ explicit QQuickPopupItem(QQuickPopup *popup);
+
+ void grabShortcut();
+ void ungrabShortcut();
+
+protected:
+ void updatePolish() override;
+
+ bool event(QEvent *event) override;
+ bool childMouseEventFilter(QQuickItem *child, QEvent *event) override;
+ void focusInEvent(QFocusEvent *event) override;
+ void focusOutEvent(QFocusEvent *event) override;
+ void keyPressEvent(QKeyEvent *event) override;
+ void keyReleaseEvent(QKeyEvent *event) override;
+ void mousePressEvent(QMouseEvent *event) override;
+ void mouseMoveEvent(QMouseEvent *event) override;
+ void mouseReleaseEvent(QMouseEvent *event) override;
+ void mouseDoubleClickEvent(QMouseEvent *event) override;
+ void mouseUngrabEvent() override;
+ void wheelEvent(QWheelEvent *event) override;
+
+ void contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) override;
+ void fontChange(const QFont &newFont, const QFont &oldFont) override;
+ void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override;
+ void localeChange(const QLocale &newLocale, const QLocale &oldLocale) override;
+ void itemChange(ItemChange change, const ItemChangeData &data) override;
+ void paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding) override;
+
+ QFont defaultFont() const override;
+
+#ifndef QT_NO_ACCESSIBILITY
+ QAccessible::Role accessibleRole() const override;
+ void accessibilityActiveChanged(bool active) override;
+#endif
+
+private:
+ Q_DISABLE_COPY(QQuickPopupItem)
+ Q_DECLARE_PRIVATE(QQuickPopupItem)
+ friend class QQuickPopup;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKPOPUPITEM_P_P_H
diff --git a/src/quicktemplates2/qquickpopuppositioner.cpp b/src/quicktemplates2/qquickpopuppositioner.cpp
new file mode 100644
index 00000000..762b6d30
--- /dev/null
+++ b/src/quicktemplates2/qquickpopuppositioner.cpp
@@ -0,0 +1,277 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickpopuppositioner_p_p.h"
+#include "qquickpopupitem_p_p.h"
+#include "qquickpopup_p_p.h"
+
+#include <QtQuick/private/qquickitem_p.h>
+
+QT_BEGIN_NAMESPACE
+
+static const QQuickItemPrivate::ChangeTypes AncestorChangeTypes = QQuickItemPrivate::Geometry
+ | QQuickItemPrivate::Parent
+ | QQuickItemPrivate::Children;
+
+static const QQuickItemPrivate::ChangeTypes ItemChangeTypes = QQuickItemPrivate::Geometry
+ | QQuickItemPrivate::Parent;
+
+QQuickPopupPositioner::QQuickPopupPositioner(QQuickPopup *popup) :
+ m_positioning(false),
+ m_parentItem(nullptr),
+ m_popup(popup)
+{
+}
+
+QQuickPopupPositioner::~QQuickPopupPositioner()
+{
+ if (m_parentItem) {
+ QQuickItemPrivate::get(m_parentItem)->removeItemChangeListener(this, ItemChangeTypes);
+ removeAncestorListeners(m_parentItem->parentItem());
+ }
+}
+
+QQuickItem *QQuickPopupPositioner::parentItem() const
+{
+ return m_parentItem;
+}
+
+void QQuickPopupPositioner::setParentItem(QQuickItem *parent)
+{
+ if (m_parentItem == parent)
+ return;
+
+ if (m_parentItem) {
+ QQuickItemPrivate::get(m_parentItem)->removeItemChangeListener(this, ItemChangeTypes);
+ removeAncestorListeners(m_parentItem->parentItem());
+ }
+
+ m_parentItem = parent;
+
+ if (!parent)
+ return;
+
+ QQuickItemPrivate::get(parent)->addItemChangeListener(this, ItemChangeTypes);
+ addAncestorListeners(parent->parentItem());
+
+ if (m_popup->popupItem()->isVisible())
+ reposition();
+}
+
+void QQuickPopupPositioner::reposition()
+{
+ QQuickItem *popupItem = m_popup->popupItem();
+ if (!popupItem->isVisible())
+ return;
+
+ if (m_positioning) {
+ popupItem->polish();
+ return;
+ }
+
+ const qreal w = popupItem->width();
+ const qreal h = popupItem->height();
+ const qreal iw = popupItem->implicitWidth();
+ const qreal ih = popupItem->implicitHeight();
+
+ bool widthAdjusted = false;
+ bool heightAdjusted = false;
+ QQuickPopupPrivate *p = QQuickPopupPrivate::get(m_popup);
+
+ QRectF rect(p->allowHorizontalMove ? p->x : popupItem->x(),
+ p->allowVerticalMove ? p->y : popupItem->y(),
+ !p->hasWidth && iw > 0 ? iw : w,
+ !p->hasHeight && ih > 0 ? ih : h);
+ if (m_parentItem) {
+ rect = m_parentItem->mapRectToScene(rect);
+
+ if (p->window) {
+ const QMarginsF margins = p->getMargins();
+ const QRectF bounds(qMax<qreal>(0.0, margins.left()),
+ qMax<qreal>(0.0, margins.top()),
+ p->window->width() - qMax<qreal>(0.0, margins.left()) - qMax<qreal>(0.0, margins.right()),
+ p->window->height() - qMax<qreal>(0.0, margins.top()) - qMax<qreal>(0.0, margins.bottom()));
+
+ // if the popup doesn't fit horizontally inside the window, try flipping it around (left <-> right)
+ if (p->allowHorizontalFlip && (rect.left() < bounds.left() || rect.right() > bounds.right())) {
+ const QRectF flipped = m_parentItem->mapRectToScene(QRectF(m_parentItem->width() - p->x - rect.width(), p->y, rect.width(), rect.height()));
+ if (flipped.intersected(bounds).width() > rect.intersected(bounds).width())
+ rect.moveLeft(flipped.left());
+ }
+
+ // if the popup doesn't fit vertically inside the window, try flipping it around (above <-> below)
+ if (p->allowVerticalFlip && (rect.top() < bounds.top() || rect.bottom() > bounds.bottom())) {
+ const QRectF flipped = m_parentItem->mapRectToScene(QRectF(p->x, m_parentItem->height() - p->y - rect.height(), rect.width(), rect.height()));
+ if (flipped.intersected(bounds).height() > rect.intersected(bounds).height())
+ rect.moveTop(flipped.top());
+ }
+
+ // push inside the margins if specified
+ if (p->allowVerticalMove) {
+ if (margins.top() >= 0 && rect.top() < bounds.top())
+ rect.moveTop(margins.top());
+ if (margins.bottom() >= 0 && rect.bottom() > bounds.bottom())
+ rect.moveBottom(bounds.bottom());
+ }
+ if (p->allowHorizontalMove) {
+ if (margins.left() >= 0 && rect.left() < bounds.left())
+ rect.moveLeft(margins.left());
+ if (margins.right() >= 0 && rect.right() > bounds.right())
+ rect.moveRight(bounds.right());
+ }
+
+ if (iw > 0 && (rect.left() < bounds.left() || rect.right() > bounds.right())) {
+ // neither the flipped or pushed geometry fits inside the window, choose
+ // whichever side (left vs. right) fits larger part of the popup
+ if (p->allowHorizontalMove && p->allowHorizontalFlip) {
+ if (rect.left() < bounds.left() && bounds.left() + rect.width() <= bounds.right())
+ rect.moveLeft(bounds.left());
+ else if (rect.right() > bounds.right() && bounds.right() - rect.width() >= bounds.left())
+ rect.moveRight(bounds.right());
+ }
+
+ // as a last resort, adjust the width to fit the window
+ if (p->allowHorizontalResize) {
+ if (rect.left() < bounds.left()) {
+ rect.setLeft(bounds.left());
+ widthAdjusted = true;
+ }
+ if (rect.right() > bounds.right()) {
+ rect.setRight(bounds.right());
+ widthAdjusted = true;
+ }
+ }
+ } else if (iw > 0 && rect.left() >= bounds.left() && rect.right() <= bounds.right()
+ && iw != w) {
+ // restore original width
+ rect.setWidth(iw);
+ widthAdjusted = true;
+ }
+
+ if (ih > 0 && (rect.top() < bounds.top() || rect.bottom() > bounds.bottom())) {
+ // neither the flipped or pushed geometry fits inside the window, choose
+ // whichever side (above vs. below) fits larger part of the popup
+ if (p->allowVerticalMove && p->allowVerticalFlip) {
+ if (rect.top() < bounds.top() && bounds.top() + rect.height() <= bounds.bottom())
+ rect.moveTop(bounds.top());
+ else if (rect.bottom() > bounds.bottom() && bounds.bottom() - rect.height() >= bounds.top())
+ rect.moveBottom(bounds.bottom());
+ }
+
+ // as a last resort, adjust the height to fit the window
+ if (p->allowVerticalResize) {
+ if (rect.top() < bounds.top()) {
+ rect.setTop(bounds.top());
+ heightAdjusted = true;
+ }
+ if (rect.bottom() > bounds.bottom()) {
+ rect.setBottom(bounds.bottom());
+ heightAdjusted = true;
+ }
+ }
+ } else if (ih > 0 && rect.top() >= bounds.top() && rect.bottom() <= bounds.bottom()
+ && ih != h) {
+ // restore original height
+ rect.setHeight(ih);
+ heightAdjusted = true;
+ }
+ }
+ }
+
+ m_positioning = true;
+
+ popupItem->setPosition(rect.topLeft());
+
+ const QPointF effectivePos = m_parentItem ? m_parentItem->mapFromScene(rect.topLeft()) : rect.topLeft();
+ if (!qFuzzyCompare(p->effectiveX, effectivePos.x())) {
+ p->effectiveX = effectivePos.x();
+ emit m_popup->xChanged();
+ }
+ if (!qFuzzyCompare(p->effectiveY, effectivePos.y())) {
+ p->effectiveY = effectivePos.y();
+ emit m_popup->yChanged();
+ }
+
+ if (!p->hasWidth && widthAdjusted && rect.width() > 0)
+ popupItem->setWidth(rect.width());
+ if (!p->hasHeight && heightAdjusted && rect.height() > 0)
+ popupItem->setHeight(rect.height());
+
+ m_positioning = false;
+}
+
+void QQuickPopupPositioner::itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &)
+{
+ if (m_parentItem && m_popup->popupItem()->isVisible())
+ reposition();
+}
+
+void QQuickPopupPositioner::itemParentChanged(QQuickItem *, QQuickItem *parent)
+{
+ addAncestorListeners(parent);
+}
+
+void QQuickPopupPositioner::itemChildRemoved(QQuickItem *item, QQuickItem *child)
+{
+ if (child->isAncestorOf(m_parentItem))
+ removeAncestorListeners(item);
+}
+
+void QQuickPopupPositioner::removeAncestorListeners(QQuickItem *item)
+{
+ if (item == m_parentItem)
+ return;
+
+ QQuickItem *p = item;
+ while (p) {
+ QQuickItemPrivate::get(p)->removeItemChangeListener(this, AncestorChangeTypes);
+ p = p->parentItem();
+ }
+}
+
+void QQuickPopupPositioner::addAncestorListeners(QQuickItem *item)
+{
+ if (item == m_parentItem)
+ return;
+
+ QQuickItem *p = item;
+ while (p) {
+ QQuickItemPrivate::get(p)->addItemChangeListener(this, AncestorChangeTypes);
+ p = p->parentItem();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickpopuppositioner_p_p.h b/src/quicktemplates2/qquickpopuppositioner_p_p.h
new file mode 100644
index 00000000..8d3c6386
--- /dev/null
+++ b/src/quicktemplates2/qquickpopuppositioner_p_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKPOPUPPOSITIONER_P_P_H
+#define QQUICKPOPUPPOSITIONER_P_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQuick/private/qquickitemchangelistener_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickItem;
+class QQuickPopup;
+
+class QQuickPopupPositioner : public QQuickItemChangeListener
+{
+public:
+ explicit QQuickPopupPositioner(QQuickPopup *popup);
+ ~QQuickPopupPositioner();
+
+ QQuickItem *parentItem() const;
+ void setParentItem(QQuickItem *parent);
+
+ virtual void reposition();
+
+protected:
+ void itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &) override;
+ void itemParentChanged(QQuickItem *, QQuickItem *parent) override;
+ void itemChildRemoved(QQuickItem *, QQuickItem *child) override;
+
+private:
+ void removeAncestorListeners(QQuickItem *item);
+ void addAncestorListeners(QQuickItem *item);
+
+ bool m_positioning;
+ QQuickItem *m_parentItem;
+ QQuickPopup *m_popup;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKPOPUPPOSITIONER_P_P_H
diff --git a/src/quicktemplates2/qquickrangeslider.cpp b/src/quicktemplates2/qquickrangeslider.cpp
index 4e350ef2..a5c1d747 100644
--- a/src/quicktemplates2/qquickrangeslider.cpp
+++ b/src/quicktemplates2/qquickrangeslider.cpp
@@ -92,7 +92,8 @@ public:
handle(nullptr),
slider(slider),
pressed(false),
- hovered(false)
+ hovered(false),
+ touchId(-1)
{
}
@@ -103,9 +104,6 @@ public:
static QQuickRangeSliderNodePrivate *get(QQuickRangeSliderNode *node);
-private:
- friend class QQuickRangeSlider;
-
qreal value;
bool isPendingValue;
qreal pendingValue;
@@ -114,6 +112,7 @@ private:
QQuickRangeSlider *slider;
bool pressed;
bool hovered;
+ int touchId;
};
bool QQuickRangeSliderNodePrivate::isFirst() const
@@ -316,6 +315,7 @@ class QQuickRangeSliderPrivate : public QQuickControlPrivate
public:
QQuickRangeSliderPrivate() :
+ live(false),
from(defaultFrom),
to(defaultTo),
stepSize(0),
@@ -326,27 +326,25 @@ public:
{
}
+ QQuickRangeSliderNode *pressedNode(int touchId = -1) const;
+ void handlePress(const QPointF &point, int touchId = -1);
+ void handleMove(const QPointF &point, int touchId = -1);
+ void handleRelease(const QPointF &point, int touchId = -1);
+ void handleUngrab();
+
void updateHover(const QPointF &pos);
+ bool live;
qreal from;
qreal to;
qreal stepSize;
QQuickRangeSliderNode *first;
QQuickRangeSliderNode *second;
- QPoint pressPoint;
+ QPointF pressPoint;
Qt::Orientation orientation;
QQuickRangeSlider::SnapMode snapMode;
};
-void QQuickRangeSliderPrivate::updateHover(const QPointF &pos)
-{
- Q_Q(QQuickRangeSlider);
- QQuickItem *firstHandle = first->handle();
- QQuickItem *secondHandle = second->handle();
- first->setHovered(firstHandle && firstHandle->isEnabled() && firstHandle->contains(q->mapToItem(firstHandle, pos)));
- second->setHovered(secondHandle && secondHandle->isEnabled() && secondHandle->contains(q->mapToItem(secondHandle, pos)));
-}
-
static qreal valueAt(const QQuickRangeSlider *slider, qreal position)
{
return slider->from() + (slider->to() - slider->from()) * position;
@@ -365,7 +363,7 @@ static qreal snapPosition(const QQuickRangeSlider *slider, qreal position)
return qRound(position / effectiveStep) * effectiveStep;
}
-static qreal positionAt(const QQuickRangeSlider *slider, QQuickItem *handle, const QPoint &point)
+static qreal positionAt(const QQuickRangeSlider *slider, QQuickItem *handle, const QPointF &point)
{
if (slider->orientation() == Qt::Horizontal) {
const qreal hw = handle ? handle->width() : 0;
@@ -386,6 +384,135 @@ static qreal positionAt(const QQuickRangeSlider *slider, QQuickItem *handle, con
return 0;
}
+QQuickRangeSliderNode *QQuickRangeSliderPrivate::pressedNode(int touchId) const
+{
+ if (touchId == -1)
+ return first->isPressed() ? first : (second->isPressed() ? second : nullptr);
+ if (QQuickRangeSliderNodePrivate::get(first)->touchId == touchId)
+ return first;
+ if (QQuickRangeSliderNodePrivate::get(second)->touchId == touchId)
+ return second;
+ return nullptr;
+}
+
+void QQuickRangeSliderPrivate::handlePress(const QPointF &point, int touchId)
+{
+ Q_Q(QQuickRangeSlider);
+ pressPoint = point;
+
+ QQuickItem *firstHandle = first->handle();
+ QQuickItem *secondHandle = second->handle();
+ const bool firstHit = firstHandle && !first->isPressed() && firstHandle->contains(q->mapToItem(firstHandle, point));
+ const bool secondHit = secondHandle && !second->isPressed() && secondHandle->contains(q->mapToItem(secondHandle, point));
+ QQuickRangeSliderNode *hitNode = nullptr;
+ QQuickRangeSliderNode *otherNode = nullptr;
+
+ if (firstHit && secondHit) {
+ // choose highest
+ hitNode = firstHandle->z() > secondHandle->z() ? first : second;
+ otherNode = firstHandle->z() > secondHandle->z() ? second : first;
+ } else if (firstHit) {
+ hitNode = first;
+ otherNode = second;
+ } else if (secondHit) {
+ hitNode = second;
+ otherNode = first;
+ } else {
+ // find the nearest
+ const qreal firstDistance = QLineF(firstHandle->boundingRect().center(),
+ q->mapToItem(firstHandle, point)).length();
+ const qreal secondDistance = QLineF(secondHandle->boundingRect().center(),
+ q->mapToItem(secondHandle, point)).length();
+
+ if (qFuzzyCompare(firstDistance, secondDistance)) {
+ // same distance => choose the one that can be moved towards the press position
+ const bool inverted = from > to;
+ const qreal pos = positionAt(q, firstHandle, point);
+ if ((!inverted && pos < first->position()) || (inverted && pos > first->position())) {
+ hitNode = first;
+ otherNode = second;
+ } else {
+ hitNode = second;
+ otherNode = first;
+ }
+ } else if (firstDistance < secondDistance) {
+ hitNode = first;
+ otherNode = second;
+ } else {
+ hitNode = second;
+ otherNode = first;
+ }
+ }
+
+ if (hitNode) {
+ hitNode->setPressed(true);
+ hitNode->handle()->setZ(1);
+ QQuickRangeSliderNodePrivate::get(hitNode)->touchId = touchId;
+ }
+ if (otherNode)
+ otherNode->handle()->setZ(0);
+}
+
+void QQuickRangeSliderPrivate::handleMove(const QPointF &point, int touchId)
+{
+ Q_Q(QQuickRangeSlider);
+ if (!q->keepMouseGrab())
+ return;
+ QQuickRangeSliderNode *pressedNode = QQuickRangeSliderPrivate::pressedNode(touchId);
+ if (pressedNode) {
+ qreal pos = positionAt(q, pressedNode->handle(), point);
+ if (snapMode == QQuickRangeSlider::SnapAlways)
+ pos = snapPosition(q, pos);
+ if (live)
+ pressedNode->setValue(valueAt(q, pos));
+ else
+ QQuickRangeSliderNodePrivate::get(pressedNode)->setPosition(pos);
+ }
+}
+
+void QQuickRangeSliderPrivate::handleRelease(const QPointF &point, int touchId)
+{
+ Q_Q(QQuickRangeSlider);
+ pressPoint = QPointF();
+
+ QQuickRangeSliderNode *pressedNode = QQuickRangeSliderPrivate::pressedNode(touchId);
+ if (!pressedNode)
+ return;
+ QQuickRangeSliderNodePrivate *pressedNodePrivate = QQuickRangeSliderNodePrivate::get(pressedNode);
+
+ if (q->keepMouseGrab()) {
+ qreal pos = positionAt(q, pressedNode->handle(), point);
+ if (snapMode != QQuickRangeSlider::NoSnap)
+ pos = snapPosition(q, pos);
+ qreal val = valueAt(q, pos);
+ if (!qFuzzyCompare(val, pressedNode->value()))
+ pressedNode->setValue(val);
+ else if (snapMode != QQuickRangeSlider::NoSnap)
+ pressedNodePrivate->setPosition(pos);
+ q->setKeepMouseGrab(false);
+ }
+ pressedNode->setPressed(false);
+ pressedNodePrivate->touchId = -1;
+}
+
+void QQuickRangeSliderPrivate::handleUngrab()
+{
+ pressPoint = QPointF();
+ first->setPressed(false);
+ second->setPressed(false);
+ QQuickRangeSliderNodePrivate::get(first)->touchId = -1;
+ QQuickRangeSliderNodePrivate::get(second)->touchId = -1;
+}
+
+void QQuickRangeSliderPrivate::updateHover(const QPointF &pos)
+{
+ Q_Q(QQuickRangeSlider);
+ QQuickItem *firstHandle = first->handle();
+ QQuickItem *secondHandle = second->handle();
+ first->setHovered(firstHandle && firstHandle->isEnabled() && firstHandle->contains(q->mapToItem(firstHandle, pos)));
+ second->setHovered(secondHandle && secondHandle->isEnabled() && secondHandle->contains(q->mapToItem(secondHandle, pos)));
+}
+
QQuickRangeSlider::QQuickRangeSlider(QQuickItem *parent) :
QQuickControl(*(new QQuickRangeSliderPrivate), parent)
{
@@ -474,8 +601,10 @@ void QQuickRangeSlider::setTo(qreal to)
If \l to is greater than \l from, the value of the first handle
must be greater than the second, and vice versa.
- Unlike \l {first.position}{position}, value is not updated while the
- handle is dragged, but rather when it has been released.
+ Unlike \l {first.position}{position}, value is not updated by default
+ while the handle is dragged, but rather when it has been released. The
+ \l live property can be used to make the slider provide live updates
+ for value.
The default value is \c 0.0.
\row
@@ -536,8 +665,10 @@ QQuickRangeSliderNode *QQuickRangeSlider::first() const
If \l to is greater than \l from, the value of the first handle
must be greater than the second, and vice versa.
- Unlike \l {second.position}{position}, value is not updated while the
- handle is dragged, but rather when it has been released.
+ Unlike \l {second.position}{position}, value is not updated by default
+ while the handle is dragged, but rather when it has been released. The
+ \l live property can be used to make the slider provide live updates
+ for value.
The default value is \c 0.0.
\row
@@ -657,6 +788,33 @@ void QQuickRangeSlider::setOrientation(Qt::Orientation orientation)
}
/*!
+ \since QtQuick.Controls 2.2
+ \qmlproperty bool QtQuick.Controls::RangeSlider::live
+
+ This property holds whether the slider provides live updates for the \l first.value
+ and \l second.value properties while the respective handles are dragged.
+
+ The default value is \c false.
+
+ \sa first.value, second.value
+*/
+bool QQuickRangeSlider::live() const
+{
+ Q_D(const QQuickRangeSlider);
+ return d->live;
+}
+
+void QQuickRangeSlider::setLive(bool live)
+{
+ Q_D(QQuickRangeSlider);
+ if (d->live == live)
+ return;
+
+ d->live = live;
+ emit liveChanged();
+}
+
+/*!
\qmlmethod void QtQuick.Controls::RangeSlider::setValues(real firstValue, real secondValue)
Sets \l first.value and \l second.value with the given arguments.
@@ -804,58 +962,7 @@ void QQuickRangeSlider::mousePressEvent(QMouseEvent *event)
{
Q_D(QQuickRangeSlider);
QQuickControl::mousePressEvent(event);
- d->pressPoint = event->pos();
-
- QQuickItem *firstHandle = d->first->handle();
- QQuickItem *secondHandle = d->second->handle();
- const bool firstHit = firstHandle && firstHandle->contains(mapToItem(firstHandle, d->pressPoint));
- const bool secondHit = secondHandle && secondHandle->contains(mapToItem(secondHandle, d->pressPoint));
- QQuickRangeSliderNode *hitNode = nullptr;
- QQuickRangeSliderNode *otherNode = nullptr;
-
- if (firstHit && secondHit) {
- // choose highest
- hitNode = firstHandle->z() > secondHandle->z() ? d->first : d->second;
- otherNode = firstHandle->z() > secondHandle->z() ? d->second : d->first;
- } else if (firstHit) {
- hitNode = d->first;
- otherNode = d->second;
- } else if (secondHit) {
- hitNode = d->second;
- otherNode = d->first;
- } else {
- // find the nearest
- const qreal firstDistance = QLineF(firstHandle->boundingRect().center(),
- mapToItem(firstHandle, event->pos())).length();
- const qreal secondDistance = QLineF(secondHandle->boundingRect().center(),
- mapToItem(secondHandle, event->pos())).length();
-
- if (qFuzzyCompare(firstDistance, secondDistance)) {
- // same distance => choose the one that can be moved towards the press position
- const bool inverted = d->from > d->to;
- const qreal pos = positionAt(this, firstHandle, event->pos());
- if ((!inverted && pos < d->first->position()) || (inverted && pos > d->first->position())) {
- hitNode = d->first;
- otherNode = d->second;
- } else {
- hitNode = d->second;
- otherNode = d->first;
- }
- } else if (firstDistance < secondDistance) {
- hitNode = d->first;
- otherNode = d->second;
- } else {
- hitNode = d->second;
- otherNode = d->first;
- }
- }
-
- if (hitNode) {
- hitNode->setPressed(true);
- hitNode->handle()->setZ(1);
- }
- if (otherNode)
- otherNode->handle()->setZ(0);
+ d->handlePress(event->localPos());
}
void QQuickRangeSlider::mouseMoveEvent(QMouseEvent *event)
@@ -864,53 +971,92 @@ void QQuickRangeSlider::mouseMoveEvent(QMouseEvent *event)
QQuickControl::mouseMoveEvent(event);
if (!keepMouseGrab()) {
if (d->orientation == Qt::Horizontal)
- setKeepMouseGrab(QQuickWindowPrivate::dragOverThreshold(event->pos().x() - d->pressPoint.x(), Qt::XAxis, event));
+ setKeepMouseGrab(QQuickWindowPrivate::dragOverThreshold(event->localPos().x() - d->pressPoint.x(), Qt::XAxis, event));
else
- setKeepMouseGrab(QQuickWindowPrivate::dragOverThreshold(event->pos().y() - d->pressPoint.y(), Qt::YAxis, event));
- }
- if (keepMouseGrab()) {
- QQuickRangeSliderNode *pressedNode = d->first->isPressed() ? d->first : (d->second->isPressed() ? d->second : nullptr);
- if (pressedNode) {
- qreal pos = positionAt(this, pressedNode->handle(), event->pos());
- if (d->snapMode == SnapAlways)
- pos = snapPosition(this, pos);
- QQuickRangeSliderNodePrivate::get(pressedNode)->setPosition(pos);
- }
+ setKeepMouseGrab(QQuickWindowPrivate::dragOverThreshold(event->localPos().y() - d->pressPoint.y(), Qt::YAxis, event));
}
+ d->handleMove(event->localPos());
}
void QQuickRangeSlider::mouseReleaseEvent(QMouseEvent *event)
{
Q_D(QQuickRangeSlider);
QQuickControl::mouseReleaseEvent(event);
+ d->handleRelease(event->localPos());
+}
- d->pressPoint = QPoint();
- if (!keepMouseGrab())
- return;
+void QQuickRangeSlider::mouseUngrabEvent()
+{
+ Q_D(QQuickRangeSlider);
+ QQuickControl::mouseUngrabEvent();
+ d->handleUngrab();
+}
- QQuickRangeSliderNode *pressedNode = d->first->isPressed() ? d->first : (d->second->isPressed() ? d->second : nullptr);
- if (!pressedNode)
- return;
+void QQuickRangeSlider::touchEvent(QTouchEvent *event)
+{
+ Q_D(QQuickRangeSlider);
+ switch (event->type()) {
+ case QEvent::TouchBegin:
+ if (!d->first->isPressed() || !d->second->isPressed()) {
+ const QTouchEvent::TouchPoint point = event->touchPoints().first();
+ d->handlePress(point.pos(), point.id());
+ } else {
+ event->ignore();
+ }
+ break;
+
+ case QEvent::TouchUpdate:
+ for (const QTouchEvent::TouchPoint &point : event->touchPoints()) {
+ switch (point.state()) {
+ case Qt::TouchPointPressed:
+ if (!d->first->isPressed() || !d->second->isPressed())
+ d->handlePress(point.pos(), point.id());
+ break;
+ case Qt::TouchPointMoved:
+ if (!keepMouseGrab()) {
+ if (d->orientation == Qt::Horizontal)
+ setKeepMouseGrab(QQuickWindowPrivate::dragOverThreshold(point.pos().x() - point.startPos().x(), Qt::XAxis, &point));
+ else
+ setKeepMouseGrab(QQuickWindowPrivate::dragOverThreshold(point.pos().y() - point.startPos().y(), Qt::YAxis, &point));
+ }
+ if (point.id() == QQuickRangeSliderNodePrivate::get(d->first)->touchId
+ || point.id() == QQuickRangeSliderNodePrivate::get(d->second)->touchId)
+ d->handleMove(point.pos(), point.id());
+ break;
+ case Qt::TouchPointReleased:
+ if (point.id() == QQuickRangeSliderNodePrivate::get(d->first)->touchId
+ || point.id() == QQuickRangeSliderNodePrivate::get(d->second)->touchId)
+ d->handleRelease(point.pos(), point.id());
+ break;
+ default:
+ break;
+ }
+ }
+ break;
- qreal pos = positionAt(this, pressedNode->handle(), event->pos());
- if (d->snapMode != NoSnap)
- pos = snapPosition(this, pos);
- qreal val = valueAt(this, pos);
- if (!qFuzzyCompare(val, pressedNode->value()))
- pressedNode->setValue(val);
- else if (d->snapMode != NoSnap)
- QQuickRangeSliderNodePrivate::get(pressedNode)->setPosition(pos);
- setKeepMouseGrab(false);
- pressedNode->setPressed(false);
+ case QEvent::TouchEnd:
+ for (const QTouchEvent::TouchPoint &point : event->touchPoints()) {
+ if (point.id() == QQuickRangeSliderNodePrivate::get(d->first)->touchId
+ || point.id() == QQuickRangeSliderNodePrivate::get(d->second)->touchId)
+ d->handleRelease(point.pos(), point.id());
+ }
+ break;
+
+ case QEvent::TouchCancel:
+ d->handleUngrab();
+ break;
+
+ default:
+ QQuickControl::touchEvent(event);
+ break;
+ }
}
-void QQuickRangeSlider::mouseUngrabEvent()
+void QQuickRangeSlider::touchUngrabEvent()
{
Q_D(QQuickRangeSlider);
- QQuickControl::mouseUngrabEvent();
- d->pressPoint = QPoint();
- d->first->setPressed(false);
- d->second->setPressed(false);
+ QQuickControl::touchUngrabEvent();
+ d->handleUngrab();
}
void QQuickRangeSlider::mirrorChange()
diff --git a/src/quicktemplates2/qquickrangeslider_p.h b/src/quicktemplates2/qquickrangeslider_p.h
index b7bf63fb..71b803f4 100644
--- a/src/quicktemplates2/qquickrangeslider_p.h
+++ b/src/quicktemplates2/qquickrangeslider_p.h
@@ -65,6 +65,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickRangeSlider : public QQuickControl
Q_PROPERTY(qreal stepSize READ stepSize WRITE setStepSize NOTIFY stepSizeChanged FINAL)
Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged FINAL)
Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged FINAL)
+ Q_PROPERTY(bool live READ live WRITE setLive NOTIFY liveChanged FINAL REVISION 2)
public:
explicit QQuickRangeSlider(QQuickItem *parent = nullptr);
@@ -94,6 +95,9 @@ public:
Qt::Orientation orientation() const;
void setOrientation(Qt::Orientation orientation);
+ bool live() const;
+ void setLive(bool live);
+
Q_INVOKABLE void setValues(qreal firstValue, qreal secondValue);
Q_SIGNALS:
@@ -102,6 +106,7 @@ Q_SIGNALS:
void stepSizeChanged();
void snapModeChanged();
void orientationChanged();
+ Q_REVISION(2) void liveChanged();
protected:
void focusInEvent(QFocusEvent *event) override;
@@ -114,6 +119,8 @@ protected:
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void mouseUngrabEvent() override;
+ void touchEvent(QTouchEvent *event) override;
+ void touchUngrabEvent() override;
void mirrorChange() override;
void componentComplete() override;
diff --git a/src/quicktemplates2/qquickscrollbar.cpp b/src/quicktemplates2/qquickscrollbar.cpp
index c17b3be6..e8c523f2 100644
--- a/src/quicktemplates2/qquickscrollbar.cpp
+++ b/src/quicktemplates2/qquickscrollbar.cpp
@@ -158,7 +158,7 @@ class QQuickScrollBarPrivate : public QQuickControlPrivate
public:
QQuickScrollBarPrivate() : size(0), position(0), stepSize(0), offset(0),
active(false), pressed(false), moving(false),
- orientation(Qt::Vertical)
+ orientation(Qt::Vertical), snapMode(QQuickScrollBar::NoSnap)
{
}
@@ -167,10 +167,16 @@ public:
return bar->d_func();
}
- qreal positionAt(const QPoint &point) const;
+ qreal snapPosition(qreal position) const;
+ qreal positionAt(const QPointF &point) const;
void updateActive();
void resizeContent() override;
+ void handlePress(const QPointF &point);
+ void handleMove(const QPointF &point);
+ void handleRelease(const QPointF &point);
+ void handleUngrab();
+
qreal size;
qreal position;
qreal stepSize;
@@ -179,9 +185,19 @@ public:
bool pressed;
bool moving;
Qt::Orientation orientation;
+ QQuickScrollBar::SnapMode snapMode;
};
-qreal QQuickScrollBarPrivate::positionAt(const QPoint &point) const
+qreal QQuickScrollBarPrivate::snapPosition(qreal position) const
+{
+ const qreal effectiveStep = stepSize * (1.0 - size);
+ if (qFuzzyIsNull(effectiveStep))
+ return position;
+
+ return qRound(position / effectiveStep) * effectiveStep;
+}
+
+qreal QQuickScrollBarPrivate::positionAt(const QPointF &point) const
{
Q_Q(const QQuickScrollBar);
if (orientation == Qt::Horizontal)
@@ -211,6 +227,42 @@ void QQuickScrollBarPrivate::resizeContent()
}
}
+void QQuickScrollBarPrivate::handlePress(const QPointF &point)
+{
+ Q_Q(QQuickScrollBar);
+ offset = positionAt(point) - position;
+ if (offset < 0 || offset > size)
+ offset = size / 2;
+ q->setPressed(true);
+}
+
+void QQuickScrollBarPrivate::handleMove(const QPointF &point)
+{
+ Q_Q(QQuickScrollBar);
+ qreal pos = qBound<qreal>(0.0, positionAt(point) - offset, 1.0 - size);
+ if (snapMode == QQuickScrollBar::SnapAlways)
+ pos = snapPosition(pos);
+ q->setPosition(pos);
+}
+
+void QQuickScrollBarPrivate::handleRelease(const QPointF &point)
+{
+ Q_Q(QQuickScrollBar);
+ qreal pos = qBound<qreal>(0.0, positionAt(point) - offset, 1.0 - size);
+ if (snapMode != QQuickScrollBar::NoSnap)
+ pos = snapPosition(pos);
+ q->setPosition(pos);
+ offset = 0.0;
+ q->setPressed(false);
+}
+
+void QQuickScrollBarPrivate::handleUngrab()
+{
+ Q_Q(QQuickScrollBar);
+ offset = 0.0;
+ q->setPressed(false);
+}
+
QQuickScrollBar::QQuickScrollBar(QQuickItem *parent) :
QQuickControl(*(new QQuickScrollBarPrivate), parent)
{
@@ -290,7 +342,7 @@ void QQuickScrollBar::setPosition(qreal position)
This property holds the step size. The default value is \c 0.0.
- \sa increase(), decrease()
+ \sa snapMode, increase(), decrease()
*/
qreal QQuickScrollBar::stepSize() const
{
@@ -390,6 +442,46 @@ void QQuickScrollBar::setOrientation(Qt::Orientation orientation)
}
/*!
+ \since QtQuick.Controls 2.2
+ \qmlproperty enumeration QtQuick.Controls::ScrollBar::snapMode
+
+ This property holds the snap mode.
+
+ Possible values:
+ \value ScrollBar.NoSnap The scrollbar does not snap (default).
+ \value ScrollBar.SnapAlways The scrollbar snaps while dragged.
+ \value ScrollBar.SnapOnRelease The scrollbar does not snap while being dragged, but only after released.
+
+ In the following table, the various modes are illustrated with animations.
+ The movement and the \l stepSize (\c 0.25) are identical in each animation.
+
+ \table
+ \header
+ \row \li \b Value \li \b Example
+ \row \li \c ScrollBar.NoSnap \li \image qtquickcontrols2-scrollbar-nosnap.gif
+ \row \li \c ScrollBar.SnapAlways \li \image qtquickcontrols2-scrollbar-snapalways.gif
+ \row \li \c ScrollBar.SnapOnRelease \li \image qtquickcontrols2-scrollbar-snaponrelease.gif
+ \endtable
+
+ \sa stepSize
+*/
+QQuickScrollBar::SnapMode QQuickScrollBar::snapMode() const
+{
+ Q_D(const QQuickScrollBar);
+ return d->snapMode;
+}
+
+void QQuickScrollBar::setSnapMode(SnapMode mode)
+{
+ Q_D(QQuickScrollBar);
+ if (d->snapMode == mode)
+ return;
+
+ d->snapMode = mode;
+ emit snapModeChanged();
+}
+
+/*!
\qmlmethod void QtQuick.Controls::ScrollBar::increase()
Increases the position by \l stepSize or \c 0.1 if stepSize is \c 0.0.
@@ -427,26 +519,28 @@ void QQuickScrollBar::mousePressEvent(QMouseEvent *event)
{
Q_D(QQuickScrollBar);
QQuickControl::mousePressEvent(event);
- d->offset = d->positionAt(event->pos()) - d->position;
- if (d->offset < 0 || d->offset > d->size)
- d->offset = d->size / 2;
- setPressed(true);
+ d->handlePress(event->localPos());
}
void QQuickScrollBar::mouseMoveEvent(QMouseEvent *event)
{
Q_D(QQuickScrollBar);
QQuickControl::mouseMoveEvent(event);
- setPosition(qBound<qreal>(0.0, d->positionAt(event->pos()) - d->offset, 1.0 - d->size));
+ d->handleMove(event->localPos());
}
void QQuickScrollBar::mouseReleaseEvent(QMouseEvent *event)
{
Q_D(QQuickScrollBar);
QQuickControl::mouseReleaseEvent(event);
- setPosition(qBound<qreal>(0.0, d->positionAt(event->pos()) - d->offset, 1.0 - d->size));
- d->offset = 0.0;
- setPressed(false);
+ d->handleRelease(event->localPos());
+}
+
+void QQuickScrollBar::mouseUngrabEvent()
+{
+ Q_D(QQuickScrollBar);
+ QQuickControl::mouseUngrabEvent();
+ d->handleUngrab();
}
void QQuickScrollBar::hoverChange()
diff --git a/src/quicktemplates2/qquickscrollbar_p.h b/src/quicktemplates2/qquickscrollbar_p.h
index 2d89ab72..535d091b 100644
--- a/src/quicktemplates2/qquickscrollbar_p.h
+++ b/src/quicktemplates2/qquickscrollbar_p.h
@@ -65,6 +65,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickScrollBar : public QQuickControl
Q_PROPERTY(bool active READ isActive WRITE setActive NOTIFY activeChanged FINAL)
Q_PROPERTY(bool pressed READ isPressed WRITE setPressed NOTIFY pressedChanged FINAL)
Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged FINAL)
+ Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged FINAL REVISION 2)
public:
explicit QQuickScrollBar(QQuickItem *parent = nullptr);
@@ -86,6 +87,16 @@ public:
Qt::Orientation orientation() const;
void setOrientation(Qt::Orientation orientation);
+ enum SnapMode {
+ NoSnap,
+ SnapAlways,
+ SnapOnRelease
+ };
+ Q_ENUM(SnapMode)
+
+ SnapMode snapMode() const;
+ void setSnapMode(SnapMode mode);
+
public Q_SLOTS:
void increase();
void decrease();
@@ -99,11 +110,13 @@ Q_SIGNALS:
void activeChanged();
void pressedChanged();
void orientationChanged();
+ void snapModeChanged();
protected:
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
+ void mouseUngrabEvent() override;
void hoverChange() override;
diff --git a/src/quicktemplates2/qquickslider.cpp b/src/quicktemplates2/qquickslider.cpp
index da352f36..d8992fa7 100644
--- a/src/quicktemplates2/qquickslider.cpp
+++ b/src/quicktemplates2/qquickslider.cpp
@@ -75,29 +75,44 @@ QT_BEGIN_NAMESPACE
\sa {Customizing Slider}, {Input Controls}
*/
+/*!
+ \since QtQuick.Controls 2.2
+ \qmlsignal QtQuick.Controls::Slider::moved()
+
+ This signal is emitted when the slider has been interactively moved
+ by the user by either touch, mouse, wheel, or keys.
+*/
+
class QQuickSliderPrivate : public QQuickControlPrivate
{
Q_DECLARE_PUBLIC(QQuickSlider)
public:
- QQuickSliderPrivate() : from(0), to(1), value(0), position(0), stepSize(0), pressed(false),
- orientation(Qt::Horizontal), snapMode(QQuickSlider::NoSnap),
+ QQuickSliderPrivate() : from(0), to(1), value(0), position(0), stepSize(0), live(false), pressed(false),
+ touchId(-1), orientation(Qt::Horizontal), snapMode(QQuickSlider::NoSnap),
handle(nullptr)
{
}
qreal snapPosition(qreal position) const;
- qreal positionAt(const QPoint &point) const;
+ qreal positionAt(const QPointF &point) const;
void setPosition(qreal position);
void updatePosition();
+ void handlePress(const QPointF &point);
+ void handleMove(const QPointF &point);
+ void handleRelease(const QPointF &point);
+ void handleUngrab();
+
qreal from;
qreal to;
qreal value;
qreal position;
qreal stepSize;
+ bool live;
bool pressed;
- QPoint pressPoint;
+ int touchId;
+ QPointF pressPoint;
Qt::Orientation orientation;
QQuickSlider::SnapMode snapMode;
QQuickItem *handle;
@@ -116,26 +131,28 @@ qreal QQuickSliderPrivate::snapPosition(qreal position) const
return qRound(position / effectiveStep) * effectiveStep;
}
-qreal QQuickSliderPrivate::positionAt(const QPoint &point) const
+qreal QQuickSliderPrivate::positionAt(const QPointF &point) const
{
Q_Q(const QQuickSlider);
+ qreal pos = 0.0;
if (orientation == Qt::Horizontal) {
const qreal hw = handle ? handle->width() : 0;
const qreal offset = hw / 2;
const qreal extent = q->availableWidth() - hw;
if (!qFuzzyIsNull(extent)) {
if (q->isMirrored())
- return (q->width() - point.x() - q->rightPadding() - offset) / extent;
- return (point.x() - q->leftPadding() - offset) / extent;
+ pos = (q->width() - point.x() - q->rightPadding() - offset) / extent;
+ else
+ pos = (point.x() - q->leftPadding() - offset) / extent;
}
} else {
const qreal hh = handle ? handle->height() : 0;
const qreal offset = hh / 2;
const qreal extent = q->availableHeight() - hh;
if (!qFuzzyIsNull(extent))
- return (q->height() - point.y() - q->bottomPadding() - offset) / extent;
+ pos = (q->height() - point.y() - q->bottomPadding() - offset) / extent;
}
- return 0;
+ return qBound<qreal>(0.0, pos, 1.0);
}
void QQuickSliderPrivate::setPosition(qreal pos)
@@ -158,6 +175,58 @@ void QQuickSliderPrivate::updatePosition()
setPosition(pos);
}
+void QQuickSliderPrivate::handlePress(const QPointF &point)
+{
+ Q_Q(QQuickSlider);
+ pressPoint = point;
+ q->setPressed(true);
+}
+
+void QQuickSliderPrivate::handleMove(const QPointF &point)
+{
+ Q_Q(QQuickSlider);
+ if (!q->keepMouseGrab())
+ return;
+ const qreal oldPos = position;
+ qreal pos = positionAt(point);
+ if (snapMode == QQuickSlider::SnapAlways)
+ pos = snapPosition(pos);
+ if (live)
+ q->setValue(q->valueAt(pos));
+ else
+ setPosition(pos);
+ if (!qFuzzyCompare(pos, oldPos))
+ emit q->moved();
+}
+
+void QQuickSliderPrivate::handleRelease(const QPointF &point)
+{
+ Q_Q(QQuickSlider);
+ touchId = -1;
+ pressPoint = QPointF();
+ const qreal oldPos = position;
+ qreal pos = positionAt(point);
+ if (snapMode != QQuickSlider::NoSnap)
+ pos = snapPosition(pos);
+ qreal val = q->valueAt(pos);
+ if (!qFuzzyCompare(val, value))
+ q->setValue(val);
+ else if (snapMode != QQuickSlider::NoSnap)
+ setPosition(pos);
+ if (!qFuzzyCompare(pos, oldPos))
+ emit q->moved();
+ q->setKeepMouseGrab(false);
+ q->setPressed(false);
+}
+
+void QQuickSliderPrivate::handleUngrab()
+{
+ Q_Q(QQuickSlider);
+ touchId = -1;
+ pressPoint = QPointF();
+ q->setPressed(false);
+}
+
QQuickSlider::QQuickSlider(QQuickItem *parent) :
QQuickControl(*(new QQuickSliderPrivate), parent)
{
@@ -225,12 +294,12 @@ void QQuickSlider::setTo(qreal to)
This property holds the value in the range \c from - \c to. The default value is \c 0.0.
- Unlike the \l position property, the \c value is not updated while the
- handle is dragged, but only after the value has been chosen and the slider
- has been released. The \l valueAt() method can be used to get continuous
- updates.
+ Unlike the \l position property, the \c value is not updated by default
+ while the handle is dragged, but only after the value has been chosen and
+ the slider has been released. The \l live property can be used to make the
+ slider provide live updates for the \c value property.
- \sa position, valueAt()
+ \sa position, live, valueAt()
*/
qreal QQuickSlider::value() const
{
@@ -259,9 +328,9 @@ void QQuickSlider::setValue(qreal value)
This property holds the logical position of the handle.
The position is expressed as a fraction of the control's size, in the range
- \c {0.0 - 1.0}. Unlike the \l value property, the \c position is
- continuously updated while the handle is dragged. For visualizing a
- slider, the right-to-left aware \l visualPosition should be used instead.
+ \c {0.0 - 1.0}. The \c position is continuously updated while the
+ handle is dragged. For visualizing a slider, the right-to-left aware
+ \l visualPosition should be used instead.
\sa value, visualPosition, valueAt()
*/
@@ -356,6 +425,33 @@ void QQuickSlider::setSnapMode(SnapMode mode)
}
/*!
+ \since QtQuick.Controls 2.2
+ \qmlproperty bool QtQuick.Controls::Slider::live
+
+ This property holds whether the slider provides live updates for the \l value
+ property while the handle is dragged.
+
+ The default value is \c false.
+
+ \sa value
+*/
+bool QQuickSlider::live() const
+{
+ Q_D(const QQuickSlider);
+ return d->live;
+}
+
+void QQuickSlider::setLive(bool live)
+{
+ Q_D(QQuickSlider);
+ if (d->live == live)
+ return;
+
+ d->live = live;
+ emit liveChanged();
+}
+
+/*!
\qmlproperty bool QtQuick.Controls::Slider::pressed
This property holds whether the slider is pressed.
@@ -479,6 +575,8 @@ void QQuickSlider::keyPressEvent(QKeyEvent *event)
{
Q_D(QQuickSlider);
QQuickControl::keyPressEvent(event);
+
+ const qreal oldValue = d->value;
if (d->orientation == Qt::Horizontal) {
if (event->key() == Qt::Key_Left) {
setPressed(true);
@@ -506,6 +604,8 @@ void QQuickSlider::keyPressEvent(QKeyEvent *event)
event->accept();
}
}
+ if (!qFuzzyCompare(d->value, oldValue))
+ emit moved();
}
void QQuickSlider::keyReleaseEvent(QKeyEvent *event)
@@ -518,8 +618,7 @@ void QQuickSlider::mousePressEvent(QMouseEvent *event)
{
Q_D(QQuickSlider);
QQuickControl::mousePressEvent(event);
- d->pressPoint = event->pos();
- setPressed(true);
+ d->handlePress(event->localPos());
}
void QQuickSlider::mouseMoveEvent(QMouseEvent *event)
@@ -528,41 +627,80 @@ void QQuickSlider::mouseMoveEvent(QMouseEvent *event)
QQuickControl::mouseMoveEvent(event);
if (!keepMouseGrab()) {
if (d->orientation == Qt::Horizontal)
- setKeepMouseGrab(QQuickWindowPrivate::dragOverThreshold(event->pos().x() - d->pressPoint.x(), Qt::XAxis, event));
+ setKeepMouseGrab(QQuickWindowPrivate::dragOverThreshold(event->localPos().x() - d->pressPoint.x(), Qt::XAxis, event));
else
- setKeepMouseGrab(QQuickWindowPrivate::dragOverThreshold(event->pos().y() - d->pressPoint.y(), Qt::YAxis, event));
- }
- if (keepMouseGrab()) {
- qreal pos = d->positionAt(event->pos());
- if (d->snapMode == SnapAlways)
- pos = d->snapPosition(pos);
- d->setPosition(pos);
+ setKeepMouseGrab(QQuickWindowPrivate::dragOverThreshold(event->localPos().y() - d->pressPoint.y(), Qt::YAxis, event));
}
+ d->handleMove(event->localPos());
}
void QQuickSlider::mouseReleaseEvent(QMouseEvent *event)
{
Q_D(QQuickSlider);
QQuickControl::mouseReleaseEvent(event);
- d->pressPoint = QPoint();
- qreal pos = d->positionAt(event->pos());
- if (d->snapMode != NoSnap)
- pos = d->snapPosition(pos);
- qreal val = valueAt(pos);
- if (!qFuzzyCompare(val, d->value))
- setValue(val);
- else if (d->snapMode != NoSnap)
- d->setPosition(pos);
- setKeepMouseGrab(false);
- setPressed(false);
+ d->handleRelease(event->localPos());
}
void QQuickSlider::mouseUngrabEvent()
{
Q_D(QQuickSlider);
QQuickControl::mouseUngrabEvent();
- d->pressPoint = QPoint();
- setPressed(false);
+ d->handleUngrab();
+}
+
+void QQuickSlider::touchEvent(QTouchEvent *event)
+{
+ Q_D(QQuickSlider);
+ switch (event->type()) {
+ case QEvent::TouchBegin:
+ if (d->touchId == -1) {
+ const QTouchEvent::TouchPoint point = event->touchPoints().first();
+ d->touchId = point.id();
+ d->handlePress(point.pos());
+ } else {
+ event->ignore();
+ }
+ break;
+
+ case QEvent::TouchUpdate:
+ for (const QTouchEvent::TouchPoint &point : event->touchPoints()) {
+ if (point.id() != d->touchId)
+ continue;
+
+ if (!keepMouseGrab()) {
+ if (d->orientation == Qt::Horizontal)
+ setKeepMouseGrab(QQuickWindowPrivate::dragOverThreshold(point.pos().x() - d->pressPoint.x(), Qt::XAxis, &point));
+ else
+ setKeepMouseGrab(QQuickWindowPrivate::dragOverThreshold(point.pos().y() - d->pressPoint.y(), Qt::YAxis, &point));
+ }
+ d->handleMove(point.pos());
+ }
+ break;
+
+ case QEvent::TouchEnd:
+ for (const QTouchEvent::TouchPoint &point : event->touchPoints()) {
+ if (point.id() != d->touchId)
+ continue;
+
+ d->handleRelease(point.pos());
+ }
+ break;
+
+ case QEvent::TouchCancel:
+ d->handleUngrab();
+ break;
+
+ default:
+ QQuickControl::touchEvent(event);
+ break;
+ }
+}
+
+void QQuickSlider::touchUngrabEvent()
+{
+ Q_D(QQuickSlider);
+ QQuickControl::touchUngrabEvent();
+ d->handleUngrab();
}
void QQuickSlider::wheelEvent(QWheelEvent *event)
@@ -575,7 +713,10 @@ void QQuickSlider::wheelEvent(QWheelEvent *event)
const qreal delta = (qFuzzyIsNull(angle.y()) ? angle.x() : (event->inverted() ? -angle.y() : angle.y())) / QWheelEvent::DefaultDeltasPerStep;
const qreal step = qFuzzyIsNull(d->stepSize) ? 0.1 : d->stepSize;
setValue(oldValue + step * delta);
- event->setAccepted(!qFuzzyCompare(d->value, oldValue));
+ const bool wasMoved = !qFuzzyCompare(d->value, oldValue);
+ if (wasMoved)
+ emit moved();
+ event->setAccepted(wasMoved);
}
}
diff --git a/src/quicktemplates2/qquickslider_p.h b/src/quicktemplates2/qquickslider_p.h
index d18a3c24..0b3847f0 100644
--- a/src/quicktemplates2/qquickslider_p.h
+++ b/src/quicktemplates2/qquickslider_p.h
@@ -64,6 +64,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickSlider : public QQuickControl
Q_PROPERTY(qreal visualPosition READ visualPosition NOTIFY visualPositionChanged FINAL)
Q_PROPERTY(qreal stepSize READ stepSize WRITE setStepSize NOTIFY stepSizeChanged FINAL)
Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged FINAL)
+ Q_PROPERTY(bool live READ live WRITE setLive NOTIFY liveChanged FINAL REVISION 2)
Q_PROPERTY(bool pressed READ isPressed WRITE setPressed NOTIFY pressedChanged FINAL)
Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged FINAL)
Q_PROPERTY(QQuickItem *handle READ handle WRITE setHandle NOTIFY handleChanged FINAL)
@@ -96,6 +97,9 @@ public:
SnapMode snapMode() const;
void setSnapMode(SnapMode mode);
+ bool live() const;
+ void setLive(bool live);
+
bool isPressed() const;
void setPressed(bool pressed);
@@ -119,9 +123,11 @@ Q_SIGNALS:
void visualPositionChanged();
void stepSizeChanged();
void snapModeChanged();
+ Q_REVISION(2) void liveChanged();
void pressedChanged();
void orientationChanged();
void handleChanged();
+ Q_REVISION(2) void moved();
protected:
void keyPressEvent(QKeyEvent *event) override;
@@ -130,6 +136,8 @@ protected:
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void mouseUngrabEvent() override;
+ void touchEvent(QTouchEvent *event) override;
+ void touchUngrabEvent() override;
void wheelEvent(QWheelEvent *event) override;
void mirrorChange() override;
diff --git a/src/quicktemplates2/qquickspinbox.cpp b/src/quicktemplates2/qquickspinbox.cpp
index f73457b5..54e2fa43 100644
--- a/src/quicktemplates2/qquickspinbox.cpp
+++ b/src/quicktemplates2/qquickspinbox.cpp
@@ -43,6 +43,7 @@
#include <QtQml/qqmlinfo.h>
#include <QtQml/private/qqmllocale_p.h>
#include <QtQml/private/qqmlengine_p.h>
+#include <QtQuick/private/qquicktextinput_p.h>
QT_BEGIN_NAMESPACE
@@ -92,13 +93,21 @@ static const int AUTO_REPEAT_INTERVAL = 100;
\sa Tumbler, {Customizing SpinBox}
*/
+/*!
+ \since QtQuick.Controls 2.2
+ \qmlsignal QtQuick.Controls::SpinBox::valueModified()
+
+ This signal is emitted when the spin box value has been interactively
+ modified by the user by either touch, mouse, wheel, or keys.
+*/
+
class QQuickSpinBoxPrivate : public QQuickControlPrivate
{
Q_DECLARE_PUBLIC(QQuickSpinBox)
public:
QQuickSpinBoxPrivate() : editable(false), from(0), to(99), value(0), stepSize(1),
- delayTimer(0), repeatTimer(0), up(nullptr), down(nullptr), validator(nullptr) { }
+ delayTimer(0), repeatTimer(0), up(nullptr), down(nullptr), validator(nullptr), inputMethodHints(Qt::ImhDigitsOnly) { }
int boundValue(int value) const;
void updateValue();
@@ -132,6 +141,7 @@ public:
QValidator *validator;
mutable QJSValue textFromValue;
mutable QJSValue valueFromText;
+ Qt::InputMethodHints inputMethodHints;
};
int QQuickSpinBoxPrivate::boundValue(int value) const
@@ -150,7 +160,10 @@ void QQuickSpinBoxPrivate::updateValue()
QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(engine);
QJSValue loc(v4, QQmlLocale::wrap(v4, locale));
QJSValue val = q->valueFromText().call(QJSValueList() << text.toString() << loc);
+ const int oldValue = value;
q->setValue(val.toInt());
+ if (oldValue != value)
+ emit q->valueModified();
}
}
}
@@ -262,6 +275,8 @@ bool QQuickSpinBoxPrivate::handleMouseReleaseEvent(QQuickItem *child, QMouseEven
Q_Q(QQuickSpinBox);
QQuickItem *ui = up->indicator();
QQuickItem *di = down->indicator();
+
+ int oldValue = value;
bool wasPressed = up->isPressed() || down->isPressed();
if (up->isPressed()) {
up->setPressed(false);
@@ -272,6 +287,8 @@ bool QQuickSpinBoxPrivate::handleMouseReleaseEvent(QQuickItem *child, QMouseEven
if (repeatTimer <= 0 && di && di->contains(di->mapFromItem(child, event->pos())))
q->decrease();
}
+ if (value != oldValue)
+ emit q->valueModified();
q->setAccessibleProperty("pressed", false);
stopPressRepeat();
@@ -594,6 +611,50 @@ QQuickSpinButton *QQuickSpinBox::down() const
}
/*!
+ \since QtQuick.Controls 2.2
+ \qmlproperty flags QtQuick.Controls::SpinBox::inputMethodHints
+
+ This property provides hints to the input method about the expected content
+ of the spin box and how it should operate.
+
+ The default value is \c Qt.ImhDigitsOnly.
+
+ \include inputmethodhints.qdocinc
+*/
+Qt::InputMethodHints QQuickSpinBox::inputMethodHints() const
+{
+ Q_D(const QQuickSpinBox);
+ return d->inputMethodHints;
+}
+
+void QQuickSpinBox::setInputMethodHints(Qt::InputMethodHints hints)
+{
+ Q_D(QQuickSpinBox);
+ if (d->inputMethodHints == hints)
+ return;
+
+ d->inputMethodHints = hints;
+ emit inputMethodHintsChanged();
+}
+
+/*!
+ \since QtQuick.Controls 2.2
+ \qmlproperty bool QtQuick.Controls::SpinBox::inputMethodComposing
+ \readonly
+
+ This property holds whether an editable spin box has partial text input from an input method.
+
+ While it is composing, an input method may rely on mouse or key events from the spin box to
+ edit or commit the partial text. This property can be used to determine when to disable event
+ handlers that may interfere with the correct operation of an input method.
+*/
+bool QQuickSpinBox::isInputMethodComposing() const
+{
+ Q_D(const QQuickSpinBox);
+ return d->contentItem && d->contentItem->property("inputMethodComposing").toBool();
+}
+
+/*!
\qmlmethod void QtQuick.Controls::SpinBox::increase()
Increases the value by \l stepSize, or \c 1 if stepSize is not defined.
@@ -646,6 +707,7 @@ void QQuickSpinBox::keyPressEvent(QKeyEvent *event)
Q_D(QQuickSpinBox);
QQuickControl::keyPressEvent(event);
+ const int oldValue = d->value;
switch (event->key()) {
case Qt::Key_Up:
if (d->upEnabled()) {
@@ -666,6 +728,8 @@ void QQuickSpinBox::keyPressEvent(QKeyEvent *event)
default:
break;
}
+ if (d->value != oldValue)
+ emit valueModified();
setAccessibleProperty("pressed", d->up->isPressed() || d->down->isPressed());
}
@@ -751,6 +815,8 @@ void QQuickSpinBox::wheelEvent(QWheelEvent *event)
const QPointF angle = event->angleDelta();
const qreal delta = (qFuzzyIsNull(angle.y()) ? angle.x() : angle.y()) / QWheelEvent::DefaultDeltasPerStep;
setValue(oldValue + qRound(d->effectiveStepSize() * delta));
+ if (d->value != oldValue)
+ emit valueModified();
event->setAccepted(d->value != oldValue);
}
}
@@ -773,9 +839,15 @@ void QQuickSpinBox::itemChange(ItemChange change, const ItemChangeData &value)
void QQuickSpinBox::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem)
{
- Q_UNUSED(oldItem);
- if (newItem)
+ if (QQuickTextInput *oldInput = qobject_cast<QQuickTextInput *>(oldItem))
+ disconnect(oldInput, &QQuickTextInput::inputMethodComposingChanged, this, &QQuickSpinBox::inputMethodComposingChanged);
+
+ if (newItem) {
newItem->setActiveFocusOnTab(true);
+
+ if (QQuickTextInput *newInput = qobject_cast<QQuickTextInput *>(newItem))
+ connect(newInput, &QQuickTextInput::inputMethodComposingChanged, this, &QQuickSpinBox::inputMethodComposingChanged);
+ }
}
QFont QQuickSpinBox::defaultFont() const
diff --git a/src/quicktemplates2/qquickspinbox_p.h b/src/quicktemplates2/qquickspinbox_p.h
index a2ea90f9..f49d9b01 100644
--- a/src/quicktemplates2/qquickspinbox_p.h
+++ b/src/quicktemplates2/qquickspinbox_p.h
@@ -71,6 +71,8 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickSpinBox : public QQuickControl
Q_PROPERTY(QJSValue valueFromText READ valueFromText WRITE setValueFromText NOTIFY valueFromTextChanged FINAL)
Q_PROPERTY(QQuickSpinButton *up READ up CONSTANT FINAL)
Q_PROPERTY(QQuickSpinButton *down READ down CONSTANT FINAL)
+ Q_PROPERTY(Qt::InputMethodHints inputMethodHints READ inputMethodHints WRITE setInputMethodHints NOTIFY inputMethodHintsChanged FINAL REVISION 2)
+ Q_PROPERTY(bool inputMethodComposing READ isInputMethodComposing NOTIFY inputMethodComposingChanged FINAL REVISION 2)
public:
explicit QQuickSpinBox(QQuickItem *parent = nullptr);
@@ -102,6 +104,11 @@ public:
QQuickSpinButton *up() const;
QQuickSpinButton *down() const;
+ Qt::InputMethodHints inputMethodHints() const;
+ void setInputMethodHints(Qt::InputMethodHints hints);
+
+ bool isInputMethodComposing() const;
+
public Q_SLOTS:
void increase();
void decrease();
@@ -115,6 +122,9 @@ Q_SIGNALS:
void validatorChanged();
void textFromValueChanged();
void valueFromTextChanged();
+ Q_REVISION(2) void valueModified();
+ Q_REVISION(2) void inputMethodHintsChanged();
+ Q_REVISION(2) void inputMethodComposingChanged();
protected:
bool childMouseEventFilter(QQuickItem *child, QEvent *event) override;
diff --git a/src/quicktemplates2/qquickstackelement.cpp b/src/quicktemplates2/qquickstackelement.cpp
new file mode 100644
index 00000000..8b31af30
--- /dev/null
+++ b/src/quicktemplates2/qquickstackelement.cpp
@@ -0,0 +1,292 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickstackelement_p_p.h"
+#include "qquickstackview_p_p.h"
+
+#include <QtQml/qqmlinfo.h>
+#include <QtQml/qqmlengine.h>
+#include <QtQml/qqmlcomponent.h>
+#include <QtQml/qqmlincubator.h>
+#include <QtQml/private/qv4qobjectwrapper_p.h>
+#include <QtQml/private/qqmlcomponent_p.h>
+#include <QtQml/private/qqmlengine_p.h>
+
+QT_BEGIN_NAMESPACE
+
+static QQuickStackViewAttached *attachedStackObject(QQuickStackElement *element)
+{
+ QQuickStackViewAttached *attached = qobject_cast<QQuickStackViewAttached *>(qmlAttachedPropertiesObject<QQuickStackView>(element->item, false));
+ if (attached)
+ QQuickStackViewAttachedPrivate::get(attached)->element = element;
+ return attached;
+}
+
+class QQuickStackIncubator : public QQmlIncubator
+{
+public:
+ QQuickStackIncubator(QQuickStackElement *element) : QQmlIncubator(Synchronous), element(element) { }
+
+protected:
+ void setInitialState(QObject *object) override { element->incubate(object); }
+
+private:
+ QQuickStackElement *element;
+};
+
+QQuickStackElement::QQuickStackElement() : QQuickItemViewTransitionableItem(nullptr),
+ index(-1), init(false), removal(false), ownItem(false), ownComponent(false), widthValid(false), heightValid(false),
+ context(nullptr), component(nullptr), view(nullptr),
+ status(QQuickStackView::Inactive)
+{
+}
+
+QQuickStackElement::~QQuickStackElement()
+{
+ if (item)
+ QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::Destroyed);
+
+ if (ownComponent)
+ delete component;
+
+ QQuickStackViewAttached *attached = attachedStackObject(this);
+ if (item) {
+ if (ownItem) {
+ item->setParentItem(nullptr);
+ item->deleteLater();
+ item = nullptr;
+ } else {
+ item->setVisible(false);
+ if (!widthValid)
+ item->resetWidth();
+ if (!heightValid)
+ item->resetHeight();
+ if (item->parentItem() != originalParent) {
+ item->setParentItem(originalParent);
+ } else {
+ if (attached)
+ QQuickStackViewAttachedPrivate::get(attached)->itemParentChanged(item, nullptr);
+ }
+ }
+ }
+
+ if (attached)
+ emit attached->removed();
+
+ delete context;
+}
+
+QQuickStackElement *QQuickStackElement::fromString(const QString &str, QQuickStackView *view)
+{
+ QQuickStackElement *element = new QQuickStackElement;
+ element->component = new QQmlComponent(qmlEngine(view), QUrl(str), view);
+ element->ownComponent = true;
+ return element;
+}
+
+QQuickStackElement *QQuickStackElement::fromObject(QObject *object, QQuickStackView *view)
+{
+ Q_UNUSED(view);
+ QQuickStackElement *element = new QQuickStackElement;
+ element->component = qobject_cast<QQmlComponent *>(object);
+ element->item = qobject_cast<QQuickItem *>(object);
+ if (element->item)
+ element->originalParent = element->item->parentItem();
+ return element;
+}
+
+bool QQuickStackElement::load(QQuickStackView *parent)
+{
+ setView(parent);
+ if (!item) {
+ ownItem = true;
+
+ if (component->isLoading()) {
+ QObject::connect(component, &QQmlComponent::statusChanged, [this](QQmlComponent::Status status) {
+ if (status == QQmlComponent::Ready)
+ load(view);
+ else if (status == QQmlComponent::Error)
+ qWarning() << qPrintable(component->errorString().trimmed());
+ });
+ return true;
+ }
+
+ QQmlContext *creationContext = component->creationContext();
+ if (!creationContext)
+ creationContext = qmlContext(parent);
+ context = new QQmlContext(creationContext);
+ context->setContextObject(parent);
+
+ QQuickStackIncubator incubator(this);
+ component->create(incubator, context);
+ if (component->isError())
+ qWarning() << qPrintable(component->errorString().trimmed());
+ } else {
+ initialize();
+ }
+ return item;
+}
+
+void QQuickStackElement::incubate(QObject *object)
+{
+ item = qmlobject_cast<QQuickItem *>(object);
+ if (item) {
+ QQmlEngine::setObjectOwnership(item, QQmlEngine::CppOwnership);
+ item->setParent(view);
+ initialize();
+ }
+}
+
+void QQuickStackElement::initialize()
+{
+ if (!item || init)
+ return;
+
+ QQuickItemPrivate *p = QQuickItemPrivate::get(item);
+ if (!(widthValid = p->widthValid))
+ item->setWidth(view->width());
+ if (!(heightValid = p->heightValid))
+ item->setHeight(view->height());
+ item->setParentItem(view);
+ p->addItemChangeListener(this, QQuickItemPrivate::Destroyed);
+
+ if (!properties.isUndefined()) {
+ QQmlEngine *engine = qmlEngine(view);
+ Q_ASSERT(engine);
+ QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(engine);
+ Q_ASSERT(v4);
+ QV4::Scope scope(v4);
+ QV4::ScopedValue ipv(scope, properties.value());
+ QV4::Scoped<QV4::QmlContext> qmlContext(scope, qmlCallingContext.value());
+ QV4::ScopedValue qmlObject(scope, QV4::QObjectWrapper::wrap(v4, item));
+ QQmlComponentPrivate::setInitialProperties(v4, qmlContext, qmlObject, ipv);
+ properties.clear();
+ }
+
+ init = true;
+}
+
+void QQuickStackElement::setIndex(int value)
+{
+ if (index == value)
+ return;
+
+ index = value;
+ QQuickStackViewAttached *attached = attachedStackObject(this);
+ if (attached)
+ emit attached->indexChanged();
+}
+
+void QQuickStackElement::setView(QQuickStackView *value)
+{
+ if (view == value)
+ return;
+
+ view = value;
+ QQuickStackViewAttached *attached = attachedStackObject(this);
+ if (attached)
+ emit attached->viewChanged();
+}
+
+void QQuickStackElement::setStatus(QQuickStackView::Status value)
+{
+ if (status == value)
+ return;
+
+ status = value;
+ QQuickStackViewAttached *attached = attachedStackObject(this);
+ if (!attached)
+ return;
+
+ switch (value) {
+ case QQuickStackView::Inactive:
+ emit attached->deactivated();
+ break;
+ case QQuickStackView::Deactivating:
+ emit attached->deactivating();
+ break;
+ case QQuickStackView::Activating:
+ emit attached->activating();
+ break;
+ case QQuickStackView::Active:
+ emit attached->activated();
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+
+ emit attached->statusChanged();
+}
+
+void QQuickStackElement::transitionNextReposition(QQuickItemViewTransitioner *transitioner, QQuickItemViewTransitioner::TransitionType type, bool asTarget)
+{
+ if (transitioner)
+ transitioner->transitionNextReposition(this, type, asTarget);
+}
+
+bool QQuickStackElement::prepareTransition(QQuickItemViewTransitioner *transitioner, const QRectF &viewBounds)
+{
+ if (transitioner) {
+ if (item) {
+ QQuickAnchors *anchors = QQuickItemPrivate::get(item)->_anchors;
+ // TODO: expose QQuickAnchorLine so we can test for other conflicting anchors
+ if (anchors && (anchors->fill() || anchors->centerIn()))
+ qmlInfo(item) << "StackView has detected conflicting anchors. Transitions may not execute properly.";
+ }
+
+ // TODO: add force argument to QQuickItemViewTransitionableItem::prepareTransition()?
+ nextTransitionToSet = true;
+ nextTransitionFromSet = true;
+ nextTransitionFrom += QPointF(1, 1);
+ return QQuickItemViewTransitionableItem::prepareTransition(transitioner, index, viewBounds);
+ }
+ return false;
+}
+
+void QQuickStackElement::startTransition(QQuickItemViewTransitioner *transitioner, QQuickStackView::Status status)
+{
+ setStatus(status);
+ if (transitioner)
+ QQuickItemViewTransitionableItem::startTransition(transitioner, index);
+}
+
+void QQuickStackElement::itemDestroyed(QQuickItem *)
+{
+ item = nullptr;
+}
+
+QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickstackelement_p_p.h b/src/quicktemplates2/qquickstackelement_p_p.h
new file mode 100644
index 00000000..638006a5
--- /dev/null
+++ b/src/quicktemplates2/qquickstackelement_p_p.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKSTACKELEMENT_P_P_H
+#define QQUICKSTACKELEMENT_P_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQuickTemplates2/private/qquickstackview_p.h>
+#include <QtQuickTemplates2/private/qquickcontrol_p_p.h>
+#include <QtQuick/private/qquickitemviewtransition_p.h>
+#include <QtQuick/private/qquickitemchangelistener_p.h>
+#include <QtQml/private/qv4persistent_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlContext;
+class QQmlComponent;
+struct QQuickStackTransition;
+
+class QQuickStackElement : public QQuickItemViewTransitionableItem, public QQuickItemChangeListener
+{
+ QQuickStackElement();
+
+public:
+ ~QQuickStackElement();
+
+ static QQuickStackElement *fromString(const QString &str, QQuickStackView *view);
+ static QQuickStackElement *fromObject(QObject *object, QQuickStackView *view);
+
+ bool load(QQuickStackView *parent);
+ void incubate(QObject *object);
+ void initialize();
+
+ void setIndex(int index);
+ void setView(QQuickStackView *view);
+ void setStatus(QQuickStackView::Status status);
+
+ void transitionNextReposition(QQuickItemViewTransitioner *transitioner, QQuickItemViewTransitioner::TransitionType type, bool asTarget);
+ bool prepareTransition(QQuickItemViewTransitioner *transitioner, const QRectF &viewBounds);
+ void startTransition(QQuickItemViewTransitioner *transitioner, QQuickStackView::Status status);
+
+ void itemDestroyed(QQuickItem *item) override;
+
+ int index;
+ bool init;
+ bool removal;
+ bool ownItem;
+ bool ownComponent;
+ bool widthValid;
+ bool heightValid;
+ QQmlContext *context;
+ QQmlComponent *component;
+ QQuickStackView *view;
+ QPointer<QQuickItem> originalParent;
+ QQuickStackView::Status status;
+ QV4::PersistentValue properties;
+ QV4::PersistentValue qmlCallingContext;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKSTACKELEMENT_P_P_H
diff --git a/src/quicktemplates2/qquickstacktransition.cpp b/src/quicktemplates2/qquickstacktransition.cpp
new file mode 100644
index 00000000..4cfbb888
--- /dev/null
+++ b/src/quicktemplates2/qquickstacktransition.cpp
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickstacktransition_p_p.h"
+#include "qquickstackelement_p_p.h"
+#include "qquickstackview_p_p.h"
+
+QT_BEGIN_NAMESPACE
+
+static QQuickStackTransition exitTransition(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view)
+{
+ QQuickStackTransition st;
+ st.status = QQuickStackView::Deactivating;
+ st.transition = nullptr;
+ st.element = element;
+
+ const QQuickItemViewTransitioner *transitioner = QQuickStackViewPrivate::get(view)->transitioner;
+
+ switch (operation) {
+ case QQuickStackView::PushTransition:
+ st.target = false;
+ st.type = QQuickItemViewTransitioner::AddTransition;
+ st.viewBounds = QRectF();
+ if (transitioner)
+ st.transition = transitioner->addDisplacedTransition;
+ break;
+ case QQuickStackView::ReplaceTransition:
+ st.target = false;
+ st.type = QQuickItemViewTransitioner::MoveTransition;
+ st.viewBounds = QRectF();
+ if (transitioner)
+ st.transition = transitioner->moveDisplacedTransition;
+ break;
+ case QQuickStackView::PopTransition:
+ st.target = true;
+ st.type = QQuickItemViewTransitioner::RemoveTransition;
+ st.viewBounds = view->boundingRect();
+ if (transitioner)
+ st.transition = transitioner->removeTransition;
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+
+ return st;
+}
+
+static QQuickStackTransition enterTransition(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view)
+{
+ QQuickStackTransition st;
+ st.status = QQuickStackView::Activating;
+ st.transition = nullptr;
+ st.element = element;
+
+ const QQuickItemViewTransitioner *transitioner = QQuickStackViewPrivate::get(view)->transitioner;
+
+ switch (operation) {
+ case QQuickStackView::PushTransition:
+ st.target = true;
+ st.type = QQuickItemViewTransitioner::AddTransition;
+ st.viewBounds = view->boundingRect();
+ if (transitioner)
+ st.transition = transitioner->addTransition;
+ break;
+ case QQuickStackView::ReplaceTransition:
+ st.target = true;
+ st.type = QQuickItemViewTransitioner::MoveTransition;
+ st.viewBounds = view->boundingRect();
+ if (transitioner)
+ st.transition = transitioner->moveTransition;
+ break;
+ case QQuickStackView::PopTransition:
+ st.target = false;
+ st.type = QQuickItemViewTransitioner::RemoveTransition;
+ st.viewBounds = QRectF();
+ if (transitioner)
+ st.transition = transitioner->removeDisplacedTransition;
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+
+ return st;
+}
+
+static QQuickStackView::Operation operationTransition(QQuickStackView::Operation operation, QQuickStackView::Operation transition)
+{
+ if (operation == QQuickStackView::Immediate || operation == QQuickStackView::Transition)
+ return transition;
+ return operation;
+}
+
+QQuickStackTransition QQuickStackTransition::popExit(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view)
+{
+ return exitTransition(operationTransition(operation, QQuickStackView::PopTransition), element, view);
+}
+
+QQuickStackTransition QQuickStackTransition::popEnter(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view)
+{
+ return enterTransition(operationTransition(operation, QQuickStackView::PopTransition), element, view);
+}
+
+QQuickStackTransition QQuickStackTransition::pushExit(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view)
+{
+ return exitTransition(operationTransition(operation, QQuickStackView::PushTransition), element, view);
+}
+
+QQuickStackTransition QQuickStackTransition::pushEnter(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view)
+{
+ return enterTransition(operationTransition(operation, QQuickStackView::PushTransition), element, view);
+}
+
+QQuickStackTransition QQuickStackTransition::replaceExit(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view)
+{
+ return exitTransition(operationTransition(operation, QQuickStackView::ReplaceTransition), element, view);
+}
+
+QQuickStackTransition QQuickStackTransition::replaceEnter(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view)
+{
+ return enterTransition(operationTransition(operation, QQuickStackView::ReplaceTransition), element, view);
+}
+
+QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickstacktransition_p_p.h b/src/quicktemplates2/qquickstacktransition_p_p.h
new file mode 100644
index 00000000..294a688a
--- /dev/null
+++ b/src/quicktemplates2/qquickstacktransition_p_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKSTACKTRANSITION_P_P_H
+#define QQUICKSTACKTRANSITION_P_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQuickTemplates2/private/qquickstackview_p.h>
+#include <QtQuick/private/qquickitemviewtransition_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickStackElement;
+
+struct QQuickStackTransition
+{
+ static QQuickStackTransition popExit(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view);
+ static QQuickStackTransition popEnter(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view);
+
+ static QQuickStackTransition pushExit(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view);
+ static QQuickStackTransition pushEnter(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view);
+
+ static QQuickStackTransition replaceExit(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view);
+ static QQuickStackTransition replaceEnter(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view);
+
+ bool target;
+ QQuickStackView::Status status;
+ QQuickItemViewTransitioner::TransitionType type;
+ QRectF viewBounds;
+ QQuickStackElement *element;
+ QQuickTransition *transition;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKSTACKTRANSITION_P_P_H
diff --git a/src/quicktemplates2/qquickstackview.cpp b/src/quicktemplates2/qquickstackview.cpp
index a7853df7..b185a2dc 100644
--- a/src/quicktemplates2/qquickstackview.cpp
+++ b/src/quicktemplates2/qquickstackview.cpp
@@ -36,6 +36,8 @@
#include "qquickstackview_p.h"
#include "qquickstackview_p_p.h"
+#include "qquickstackelement_p_p.h"
+#include "qquickstacktransition_p_p.h"
#include <QtQml/qjsvalue.h>
#include <QtQml/qqmlengine.h>
@@ -109,7 +111,7 @@ QT_BEGIN_NAMESPACE
Using StackView in an application is as simple as adding it as a child to
a Window. The stack is usually anchored to the edges of the window, except
at the top or bottom where it might be anchored to a status bar, or some
- other similar UI component. The stack can then be used by invoking its
+ other similar UI component. The stack can then be used by invoking its
navigation methods. The first item to show in the StackView is the one
that was assigned to \l initialItem, or the topmost item if \l initialItem
is not set.
@@ -312,9 +314,9 @@ QQuickStackView::~QQuickStackView()
qDeleteAll(d->elements);
}
-QQuickStackAttached *QQuickStackView::qmlAttachedProperties(QObject *object)
+QQuickStackViewAttached *QQuickStackView::qmlAttachedProperties(QObject *object)
{
- return new QQuickStackAttached(object);
+ return new QQuickStackViewAttached(object);
}
/*!
@@ -1010,9 +1012,9 @@ QAccessible::Role QQuickStackView::accessibleRole() const
}
#endif
-void QQuickStackAttachedPrivate::itemParentChanged(QQuickItem *item, QQuickItem *parent)
+void QQuickStackViewAttachedPrivate::itemParentChanged(QQuickItem *item, QQuickItem *parent)
{
- Q_Q(QQuickStackAttached);
+ Q_Q(QQuickStackViewAttached);
int oldIndex = element ? element->index : -1;
QQuickStackView *oldView = element ? element->view : nullptr;
QQuickStackView::Status oldStatus = element ? element->status : QQuickStackView::Inactive;
@@ -1031,10 +1033,10 @@ void QQuickStackAttachedPrivate::itemParentChanged(QQuickItem *item, QQuickItem
emit q->statusChanged();
}
-QQuickStackAttached::QQuickStackAttached(QObject *parent) :
- QObject(*(new QQuickStackAttachedPrivate), parent)
+QQuickStackViewAttached::QQuickStackViewAttached(QObject *parent) :
+ QObject(*(new QQuickStackViewAttachedPrivate), parent)
{
- Q_D(QQuickStackAttached);
+ Q_D(QQuickStackViewAttached);
QQuickItem *item = qobject_cast<QQuickItem *>(parent);
if (item) {
QQuickItemPrivate::get(item)->addItemChangeListener(d, QQuickItemPrivate::Parent);
@@ -1044,9 +1046,9 @@ QQuickStackAttached::QQuickStackAttached(QObject *parent) :
}
}
-QQuickStackAttached::~QQuickStackAttached()
+QQuickStackViewAttached::~QQuickStackViewAttached()
{
- Q_D(QQuickStackAttached);
+ Q_D(QQuickStackViewAttached);
QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent());
if (parentItem)
QQuickItemPrivate::get(parentItem)->removeItemChangeListener(d, QQuickItemPrivate::Parent);
@@ -1059,9 +1061,9 @@ QQuickStackAttached::~QQuickStackAttached()
This attached property holds the stack index of the item it's
attached to, or \c -1 if the item is not in a stack.
*/
-int QQuickStackAttached::index() const
+int QQuickStackViewAttached::index() const
{
- Q_D(const QQuickStackAttached);
+ Q_D(const QQuickStackViewAttached);
return d->element ? d->element->index : -1;
}
@@ -1072,9 +1074,9 @@ int QQuickStackAttached::index() const
This attached property holds the stack view of the item it's
attached to, or \c null if the item is not in a stack.
*/
-QQuickStackView *QQuickStackAttached::view() const
+QQuickStackView *QQuickStackViewAttached::view() const
{
- Q_D(const QQuickStackAttached);
+ Q_D(const QQuickStackViewAttached);
return d->element ? d->element->view : nullptr;
}
@@ -1091,9 +1093,9 @@ QQuickStackView *QQuickStackAttached::view() const
\value StackView.Activating The item is being activated (becoming the current item).
\value StackView.Active The item is active, that is, the current item.
*/
-QQuickStackView::Status QQuickStackAttached::status() const
+QQuickStackView::Status QQuickStackViewAttached::status() const
{
- Q_D(const QQuickStackAttached);
+ Q_D(const QQuickStackViewAttached);
return d->element ? d->element->status : QQuickStackView::Inactive;
}
diff --git a/src/quicktemplates2/qquickstackview_p.cpp b/src/quicktemplates2/qquickstackview_p.cpp
index 1eaaa9a4..441768f7 100644
--- a/src/quicktemplates2/qquickstackview_p.cpp
+++ b/src/quicktemplates2/qquickstackview_p.cpp
@@ -35,263 +35,17 @@
****************************************************************************/
#include "qquickstackview_p_p.h"
+#include "qquickstackelement_p_p.h"
+#include "qquickstacktransition_p_p.h"
-#include <QtQml/qqmlinfo.h>
#include <QtQml/qqmllist.h>
-#include <QtQml/qqmlengine.h>
-#include <QtQml/qqmlcomponent.h>
-#include <QtQml/qqmlincubator.h>
+#include <QtQml/private/qv4qmlcontext_p.h>
#include <QtQml/private/qv4qobjectwrapper_p.h>
-#include <QtQml/private/qqmlcomponent_p.h>
-#include <QtQml/private/qqmlengine_p.h>
#include <QtQuick/private/qquickanimation_p.h>
#include <QtQuick/private/qquicktransition_p.h>
-#include <QtQuick/private/qquickitemviewtransition_p.h>
QT_BEGIN_NAMESPACE
-static QQuickStackAttached *attachedStackObject(QQuickStackElement *element)
-{
- QQuickStackAttached *attached = qobject_cast<QQuickStackAttached *>(qmlAttachedPropertiesObject<QQuickStackView>(element->item, false));
- if (attached)
- QQuickStackAttachedPrivate::get(attached)->element = element;
- return attached;
-}
-
-class QQuickStackIncubator : public QQmlIncubator
-{
-public:
- QQuickStackIncubator(QQuickStackElement *element) : QQmlIncubator(Synchronous), element(element) { }
-
-protected:
- void setInitialState(QObject *object) override { element->incubate(object); }
-
-private:
- QQuickStackElement *element;
-};
-
-QQuickStackElement::QQuickStackElement() : QQuickItemViewTransitionableItem(nullptr),
- index(-1), init(false), removal(false), ownItem(false), ownComponent(false), widthValid(false), heightValid(false),
- context(nullptr), component(nullptr), view(nullptr),
- status(QQuickStackView::Inactive)
-{
-}
-
-QQuickStackElement::~QQuickStackElement()
-{
- if (item)
- QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::Destroyed);
-
- if (ownComponent)
- delete component;
-
- QQuickStackAttached *attached = attachedStackObject(this);
- if (item) {
- if (ownItem) {
- item->setParentItem(nullptr);
- item->deleteLater();
- item = nullptr;
- } else {
- item->setVisible(false);
- if (!widthValid)
- item->resetWidth();
- if (!heightValid)
- item->resetHeight();
- if (item->parentItem() != originalParent) {
- item->setParentItem(originalParent);
- } else {
- if (attached)
- QQuickStackAttachedPrivate::get(attached)->itemParentChanged(item, nullptr);
- }
- }
- }
-
- if (attached)
- emit attached->removed();
-
- delete context;
-}
-
-QQuickStackElement *QQuickStackElement::fromString(const QString &str, QQuickStackView *view)
-{
- QQuickStackElement *element = new QQuickStackElement;
- element->component = new QQmlComponent(qmlEngine(view), QUrl(str), view);
- element->ownComponent = true;
- return element;
-}
-
-QQuickStackElement *QQuickStackElement::fromObject(QObject *object, QQuickStackView *view)
-{
- Q_UNUSED(view);
- QQuickStackElement *element = new QQuickStackElement;
- element->component = qobject_cast<QQmlComponent *>(object);
- element->item = qobject_cast<QQuickItem *>(object);
- if (element->item)
- element->originalParent = element->item->parentItem();
- return element;
-}
-
-bool QQuickStackElement::load(QQuickStackView *parent)
-{
- setView(parent);
- if (!item) {
- ownItem = true;
-
- if (component->isLoading()) {
- QObject::connect(component, &QQmlComponent::statusChanged, [this](QQmlComponent::Status status) {
- if (status == QQmlComponent::Ready)
- load(view);
- else if (status == QQmlComponent::Error)
- qWarning() << qPrintable(component->errorString().trimmed());
- });
- return true;
- }
-
- QQmlContext *creationContext = component->creationContext();
- if (!creationContext)
- creationContext = qmlContext(parent);
- context = new QQmlContext(creationContext);
- context->setContextObject(parent);
-
- QQuickStackIncubator incubator(this);
- component->create(incubator, context);
- if (component->isError())
- qWarning() << qPrintable(component->errorString().trimmed());
- } else {
- initialize();
- }
- return item;
-}
-
-void QQuickStackElement::incubate(QObject *object)
-{
- item = qmlobject_cast<QQuickItem *>(object);
- if (item) {
- QQmlEngine::setObjectOwnership(item, QQmlEngine::CppOwnership);
- item->setParent(view);
- initialize();
- }
-}
-
-void QQuickStackElement::initialize()
-{
- if (!item || init)
- return;
-
- QQuickItemPrivate *p = QQuickItemPrivate::get(item);
- if (!(widthValid = p->widthValid))
- item->setWidth(view->width());
- if (!(heightValid = p->heightValid))
- item->setHeight(view->height());
- item->setParentItem(view);
- p->addItemChangeListener(this, QQuickItemPrivate::Destroyed);
-
- if (!properties.isUndefined()) {
- QQmlEngine *engine = qmlEngine(view);
- Q_ASSERT(engine);
- QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(engine);
- Q_ASSERT(v4);
- QV4::Scope scope(v4);
- QV4::ScopedValue ipv(scope, properties.value());
- QV4::Scoped<QV4::QmlContext> qmlContext(scope, qmlCallingContext.value());
- QV4::ScopedValue qmlObject(scope, QV4::QObjectWrapper::wrap(v4, item));
- QQmlComponentPrivate::setInitialProperties(v4, qmlContext, qmlObject, ipv);
- properties.clear();
- }
-
- init = true;
-}
-
-void QQuickStackElement::setIndex(int value)
-{
- if (index == value)
- return;
-
- index = value;
- QQuickStackAttached *attached = attachedStackObject(this);
- if (attached)
- emit attached->indexChanged();
-}
-
-void QQuickStackElement::setView(QQuickStackView *value)
-{
- if (view == value)
- return;
-
- view = value;
- QQuickStackAttached *attached = attachedStackObject(this);
- if (attached)
- emit attached->viewChanged();
-}
-
-void QQuickStackElement::setStatus(QQuickStackView::Status value)
-{
- if (status == value)
- return;
-
- status = value;
- QQuickStackAttached *attached = attachedStackObject(this);
- if (!attached)
- return;
-
- switch (value) {
- case QQuickStackView::Inactive:
- emit attached->deactivated();
- break;
- case QQuickStackView::Deactivating:
- emit attached->deactivating();
- break;
- case QQuickStackView::Activating:
- emit attached->activating();
- break;
- case QQuickStackView::Active:
- emit attached->activated();
- break;
- default:
- Q_UNREACHABLE();
- break;
- }
-
- emit attached->statusChanged();
-}
-
-void QQuickStackElement::transitionNextReposition(QQuickItemViewTransitioner *transitioner, QQuickItemViewTransitioner::TransitionType type, bool asTarget)
-{
- if (transitioner)
- transitioner->transitionNextReposition(this, type, asTarget);
-}
-
-bool QQuickStackElement::prepareTransition(QQuickItemViewTransitioner *transitioner, const QRectF &viewBounds)
-{
- if (transitioner) {
- if (item) {
- QQuickAnchors *anchors = QQuickItemPrivate::get(item)->_anchors;
- // TODO: expose QQuickAnchorLine so we can test for other conflicting anchors
- if (anchors && (anchors->fill() || anchors->centerIn()))
- qmlInfo(item) << "StackView has detected conflicting anchors. Transitions may not execute properly.";
- }
-
- // TODO: add force argument to QQuickItemViewTransitionableItem::prepareTransition()?
- nextTransitionToSet = true;
- nextTransitionFromSet = true;
- nextTransitionFrom += QPointF(1, 1);
- return QQuickItemViewTransitionableItem::prepareTransition(transitioner, index, viewBounds);
- }
- return false;
-}
-
-void QQuickStackElement::startTransition(QQuickItemViewTransitioner *transitioner, QQuickStackView::Status status)
-{
- setStatus(status);
- if (transitioner)
- QQuickItemViewTransitionableItem::startTransition(transitioner, index);
-}
-
-void QQuickStackElement::itemDestroyed(QQuickItem *)
-{
- item = nullptr;
-}
-
QQuickStackViewPrivate::QQuickStackViewPrivate() : busy(false), currentItem(nullptr), transitioner(nullptr)
{
}
@@ -513,119 +267,4 @@ void QQuickStackViewPrivate::setBusy(bool b)
emit q->busyChanged();
}
-static QQuickStackTransition exitTransition(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view)
-{
- QQuickStackTransition st;
- st.status = QQuickStackView::Deactivating;
- st.transition = nullptr;
- st.element = element;
-
- const QQuickItemViewTransitioner *transitioner = QQuickStackViewPrivate::get(view)->transitioner;
-
- switch (operation) {
- case QQuickStackView::PushTransition:
- st.target = false;
- st.type = QQuickItemViewTransitioner::AddTransition;
- st.viewBounds = QRectF();
- if (transitioner)
- st.transition = transitioner->addDisplacedTransition;
- break;
- case QQuickStackView::ReplaceTransition:
- st.target = false;
- st.type = QQuickItemViewTransitioner::MoveTransition;
- st.viewBounds = QRectF();
- if (transitioner)
- st.transition = transitioner->moveDisplacedTransition;
- break;
- case QQuickStackView::PopTransition:
- st.target = true;
- st.type = QQuickItemViewTransitioner::RemoveTransition;
- st.viewBounds = view->boundingRect();
- if (transitioner)
- st.transition = transitioner->removeTransition;
- break;
- default:
- Q_UNREACHABLE();
- break;
- }
-
- return st;
-}
-
-static QQuickStackTransition enterTransition(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view)
-{
- QQuickStackTransition st;
- st.status = QQuickStackView::Activating;
- st.transition = nullptr;
- st.element = element;
-
- const QQuickItemViewTransitioner *transitioner = QQuickStackViewPrivate::get(view)->transitioner;
-
- switch (operation) {
- case QQuickStackView::PushTransition:
- st.target = true;
- st.type = QQuickItemViewTransitioner::AddTransition;
- st.viewBounds = view->boundingRect();
- if (transitioner)
- st.transition = transitioner->addTransition;
- break;
- case QQuickStackView::ReplaceTransition:
- st.target = true;
- st.type = QQuickItemViewTransitioner::MoveTransition;
- st.viewBounds = view->boundingRect();
- if (transitioner)
- st.transition = transitioner->moveTransition;
- break;
- case QQuickStackView::PopTransition:
- st.target = false;
- st.type = QQuickItemViewTransitioner::RemoveTransition;
- st.viewBounds = QRectF();
- if (transitioner)
- st.transition = transitioner->removeDisplacedTransition;
- break;
- default:
- Q_UNREACHABLE();
- break;
- }
-
- return st;
-}
-
-static QQuickStackView::Operation operationTransition(QQuickStackView::Operation operation, QQuickStackView::Operation transition)
-{
- if (operation == QQuickStackView::Immediate || operation == QQuickStackView::Transition)
- return transition;
- return operation;
-}
-
-QQuickStackTransition QQuickStackTransition::popExit(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view)
-{
- return exitTransition(operationTransition(operation, QQuickStackView::PopTransition), element, view);
-}
-
-QQuickStackTransition QQuickStackTransition::popEnter(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view)
-{
- return enterTransition(operationTransition(operation, QQuickStackView::PopTransition), element, view);
-}
-
-QQuickStackTransition QQuickStackTransition::pushExit(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view)
-{
- return exitTransition(operationTransition(operation, QQuickStackView::PushTransition), element, view);
-}
-
-QQuickStackTransition QQuickStackTransition::pushEnter(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view)
-{
- return enterTransition(operationTransition(operation, QQuickStackView::PushTransition), element, view);
-}
-
-QQuickStackTransition QQuickStackTransition::replaceExit(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view)
-{
- return exitTransition(operationTransition(operation, QQuickStackView::ReplaceTransition), element, view);
-}
-
-QQuickStackTransition QQuickStackTransition::replaceEnter(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view)
-{
- return enterTransition(operationTransition(operation, QQuickStackView::ReplaceTransition), element, view);
-}
-
QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickstackview_p.h b/src/quicktemplates2/qquickstackview_p.h
index d305453c..eea59334 100644
--- a/src/quicktemplates2/qquickstackview_p.h
+++ b/src/quicktemplates2/qquickstackview_p.h
@@ -55,8 +55,9 @@ QT_BEGIN_NAMESPACE
class QQmlV4Function;
class QQuickTransition;
class QQuickStackElement;
-class QQuickStackAttached;
class QQuickStackViewPrivate;
+class QQuickStackViewAttached;
+class QQuickStackViewAttachedPrivate;
class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickStackView : public QQuickControl
{
@@ -76,7 +77,7 @@ public:
explicit QQuickStackView(QQuickItem *parent = nullptr);
~QQuickStackView();
- static QQuickStackAttached *qmlAttachedProperties(QObject *object);
+ static QQuickStackViewAttached *qmlAttachedProperties(QObject *object);
bool isBusy() const;
int depth() const;
@@ -161,9 +162,7 @@ private:
Q_DECLARE_PRIVATE(QQuickStackView)
};
-class QQuickStackAttachedPrivate;
-
-class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickStackAttached : public QObject
+class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickStackViewAttached : public QObject
{
Q_OBJECT
Q_PROPERTY(int index READ index NOTIFY indexChanged FINAL)
@@ -171,8 +170,8 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickStackAttached : public QObject
Q_PROPERTY(QQuickStackView::Status status READ status NOTIFY statusChanged FINAL)
public:
- explicit QQuickStackAttached(QObject *parent = nullptr);
- ~QQuickStackAttached();
+ explicit QQuickStackViewAttached(QObject *parent = nullptr);
+ ~QQuickStackViewAttached();
int index() const;
QQuickStackView *view() const;
@@ -189,8 +188,8 @@ Q_SIGNALS:
/*Q_REVISION(1)*/ void removed();
private:
- Q_DISABLE_COPY(QQuickStackAttached)
- Q_DECLARE_PRIVATE(QQuickStackAttached)
+ Q_DISABLE_COPY(QQuickStackViewAttached)
+ Q_DECLARE_PRIVATE(QQuickStackViewAttached)
};
QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickstackview_p_p.h b/src/quicktemplates2/qquickstackview_p_p.h
index 8a6b594d..915f4160 100644
--- a/src/quicktemplates2/qquickstackview_p_p.h
+++ b/src/quicktemplates2/qquickstackview_p_p.h
@@ -52,54 +52,13 @@
#include <QtQuickTemplates2/private/qquickcontrol_p_p.h>
#include <QtQuick/private/qquickitemviewtransition_p.h>
#include <QtQuick/private/qquickitemchangelistener_p.h>
-#include <QtQml/private/qv4persistent_p.h>
+#include <QtQml/private/qv4value_p.h>
QT_BEGIN_NAMESPACE
-class QQmlContext;
-class QQmlComponent;
+class QQuickStackElement;
struct QQuickStackTransition;
-class QQuickStackElement : public QQuickItemViewTransitionableItem, public QQuickItemChangeListener
-{
- QQuickStackElement();
-
-public:
- ~QQuickStackElement();
-
- static QQuickStackElement *fromString(const QString &str, QQuickStackView *view);
- static QQuickStackElement *fromObject(QObject *object, QQuickStackView *view);
-
- bool load(QQuickStackView *parent);
- void incubate(QObject *object);
- void initialize();
-
- void setIndex(int index);
- void setView(QQuickStackView *view);
- void setStatus(QQuickStackView::Status status);
-
- void transitionNextReposition(QQuickItemViewTransitioner *transitioner, QQuickItemViewTransitioner::TransitionType type, bool asTarget);
- bool prepareTransition(QQuickItemViewTransitioner *transitioner, const QRectF &viewBounds);
- void startTransition(QQuickItemViewTransitioner *transitioner, QQuickStackView::Status status);
-
- void itemDestroyed(QQuickItem *item) override;
-
- int index;
- bool init;
- bool removal;
- bool ownItem;
- bool ownComponent;
- bool widthValid;
- bool heightValid;
- QQmlContext *context;
- QQmlComponent *component;
- QQuickStackView *view;
- QPointer<QQuickItem> originalParent;
- QQuickStackView::Status status;
- QV4::PersistentValue properties;
- QV4::PersistentValue qmlCallingContext;
-};
-
class QQuickStackViewPrivate : public QQuickControlPrivate, public QQuickItemViewTransitionChangeListener
{
Q_DECLARE_PUBLIC(QQuickStackView)
@@ -138,33 +97,14 @@ public:
QQuickItemViewTransitioner *transitioner;
};
-struct QQuickStackTransition
-{
- static QQuickStackTransition popExit(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view);
- static QQuickStackTransition popEnter(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view);
-
- static QQuickStackTransition pushExit(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view);
- static QQuickStackTransition pushEnter(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view);
-
- static QQuickStackTransition replaceExit(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view);
- static QQuickStackTransition replaceEnter(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view);
-
- bool target;
- QQuickStackView::Status status;
- QQuickItemViewTransitioner::TransitionType type;
- QRectF viewBounds;
- QQuickStackElement *element;
- QQuickTransition *transition;
-};
-
-class QQuickStackAttachedPrivate : public QObjectPrivate, public QQuickItemChangeListener
+class QQuickStackViewAttachedPrivate : public QObjectPrivate, public QQuickItemChangeListener
{
- Q_DECLARE_PUBLIC(QQuickStackAttached)
+ Q_DECLARE_PUBLIC(QQuickStackViewAttached)
public:
- QQuickStackAttachedPrivate() : element(nullptr) { }
+ QQuickStackViewAttachedPrivate() : element(nullptr) { }
- static QQuickStackAttachedPrivate *get(QQuickStackAttached *attached)
+ static QQuickStackViewAttachedPrivate *get(QQuickStackViewAttached *attached)
{
return attached->d_func();
}
diff --git a/src/quicktemplates2/qquickswipe_p.h b/src/quicktemplates2/qquickswipe_p.h
index ea2ec3c5..62b0e903 100644
--- a/src/quicktemplates2/qquickswipe_p.h
+++ b/src/quicktemplates2/qquickswipe_p.h
@@ -50,25 +50,28 @@
#include <QtCore/qobject.h>
#include <QtQuickTemplates2/private/qtquicktemplates2global_p.h>
+#include <QtQuickTemplates2/private/qquickswipedelegate_p.h>
QT_BEGIN_NAMESPACE
class QQmlComponent;
class QQuickItem;
-class QQuickSwipeDelegate;
+class QQuickTransition;
class QQuickSwipePrivate;
class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickSwipe : public QObject
{
Q_OBJECT
- Q_PROPERTY(qreal position READ position NOTIFY positionChanged FINAL)
+ Q_PROPERTY(qreal position READ position WRITE setPosition NOTIFY positionChanged FINAL)
Q_PROPERTY(bool complete READ isComplete NOTIFY completeChanged FINAL)
+ Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged FINAL) // REVISION 2
Q_PROPERTY(QQmlComponent *left READ left WRITE setLeft NOTIFY leftChanged FINAL)
Q_PROPERTY(QQmlComponent *behind READ behind WRITE setBehind NOTIFY behindChanged FINAL)
Q_PROPERTY(QQmlComponent *right READ right WRITE setRight NOTIFY rightChanged FINAL)
Q_PROPERTY(QQuickItem *leftItem READ leftItem NOTIFY leftItemChanged FINAL)
Q_PROPERTY(QQuickItem *behindItem READ behindItem NOTIFY behindItemChanged FINAL)
Q_PROPERTY(QQuickItem *rightItem READ rightItem NOTIFY rightItemChanged FINAL)
+ Q_PROPERTY(QQuickTransition *transition READ transition WRITE setTransition NOTIFY transitionChanged FINAL) // REVISION 2
public:
explicit QQuickSwipe(QQuickSwipeDelegate *control);
@@ -79,6 +82,9 @@ public:
bool isComplete() const;
void setComplete(bool complete);
+ bool isEnabled() const;
+ void setEnabled(bool enabled);
+
QQmlComponent *left() const;
void setLeft(QQmlComponent *left);
@@ -97,18 +103,26 @@ public:
QQuickItem *rightItem() const;
void setRightItem(QQuickItem *item);
+ QQuickTransition *transition() const;
+ void setTransition(QQuickTransition *transition);
+
+ Q_REVISION(2) Q_INVOKABLE void open(QQuickSwipeDelegate::Side side);
Q_REVISION(1) Q_INVOKABLE void close();
Q_SIGNALS:
void positionChanged();
void completeChanged();
+ /*Q_REVISION(2)*/ void enabledChanged();
/*Q_REVISION(1)*/ void completed();
+ /*Q_REVISION(2)*/ void opened();
+ /*Q_REVISION(2)*/ void closed();
void leftChanged();
void behindChanged();
void rightChanged();
void leftItemChanged();
void behindItemChanged();
void rightItemChanged();
+ /*Q_REVISION(2)*/ void transitionChanged();
private:
Q_DISABLE_COPY(QQuickSwipe)
diff --git a/src/quicktemplates2/qquickswipedelegate.cpp b/src/quicktemplates2/qquickswipedelegate.cpp
index ae69937c..f8b2496c 100644
--- a/src/quicktemplates2/qquickswipedelegate.cpp
+++ b/src/quicktemplates2/qquickswipedelegate.cpp
@@ -44,6 +44,9 @@
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/qpa/qplatformtheme.h>
#include <QtQml/qqmlinfo.h>
+#include <QtQuick/private/qquickanimation_p.h>
+#include <QtQuick/private/qquicktransition_p.h>
+#include <QtQuick/private/qquicktransitionmanager_p_p.h>
QT_BEGIN_NAMESPACE
@@ -97,7 +100,7 @@ QT_BEGIN_NAMESPACE
\image qtquickcontrols2-swipedelegate-behind.gif
- \sa {Customizing SwipeDelegate}, {Delegate Controls}
+ \sa {Customizing SwipeDelegate}, {Delegate Controls}, {Qt Quick Controls 2 - Swipe to Remove}{Swipe to Remove Example}
*/
namespace {
@@ -113,6 +116,20 @@ namespace {
};
}
+class QQuickSwipeTransitionManager : public QQuickTransitionManager
+{
+public:
+ QQuickSwipeTransitionManager(QQuickSwipe *swipe);
+
+ void transition(QQuickTransition *transition, qreal position);
+
+protected:
+ void finished() override;
+
+private:
+ QQuickSwipe *m_swipe;
+};
+
class QQuickSwipePrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QQuickSwipe)
@@ -124,12 +141,15 @@ public:
position(0),
wasComplete(false),
complete(false),
+ enabled(true),
left(nullptr),
behind(nullptr),
right(nullptr),
leftItem(nullptr),
behindItem(nullptr),
- rightItem(nullptr)
+ rightItem(nullptr),
+ transition(nullptr),
+ transitionManager(nullptr)
{
}
@@ -151,6 +171,10 @@ public:
bool hasDelegates() const;
+ bool isTransitioning() const;
+ void beginTransition(qreal position);
+ void finishTransition();
+
QQuickSwipeDelegate *control;
// Same range as position, but is set before press events so that we can
// keep track of which direction the user must swipe when using left and right delegates.
@@ -160,6 +184,7 @@ public:
// before the last press event.
bool wasComplete;
bool complete;
+ bool enabled;
QQuickVelocityCalculator velocityCalculator;
QQmlComponent *left;
QQmlComponent *behind;
@@ -167,8 +192,37 @@ public:
QQuickItem *leftItem;
QQuickItem *behindItem;
QQuickItem *rightItem;
+ QQuickTransition *transition;
+ QScopedPointer<QQuickSwipeTransitionManager> transitionManager;
};
+QQuickSwipeTransitionManager::QQuickSwipeTransitionManager(QQuickSwipe *swipe)
+ : m_swipe(swipe)
+{
+}
+
+void QQuickSwipeTransitionManager::transition(QQuickTransition *transition, qreal position)
+{
+ qmlExecuteDeferred(transition);
+
+ QQmlProperty defaultTarget(m_swipe, QLatin1String("position"));
+ QQmlListProperty<QQuickAbstractAnimation> animations = transition->animations();
+ const int count = animations.count(&animations);
+ for (int i = 0; i < count; ++i) {
+ QQuickAbstractAnimation *anim = animations.at(&animations, i);
+ anim->setDefaultTarget(defaultTarget);
+ }
+
+ QList<QQuickStateAction> actions;
+ actions << QQuickStateAction(m_swipe, QLatin1String("position"), position);
+ QQuickTransitionManager::transition(actions, transition, m_swipe);
+}
+
+void QQuickSwipeTransitionManager::finished()
+{
+ QQuickSwipePrivate::get(m_swipe)->finishTransition();
+}
+
QQuickSwipePrivate *QQuickSwipePrivate::get(QQuickSwipe *swipe)
{
return swipe->d_func();
@@ -356,6 +410,36 @@ bool QQuickSwipePrivate::hasDelegates() const
return left || right || behind;
}
+bool QQuickSwipePrivate::isTransitioning() const
+{
+ return transitionManager && transitionManager->isRunning();
+}
+
+void QQuickSwipePrivate::beginTransition(qreal newPosition)
+{
+ Q_Q(QQuickSwipe);
+ if (!transition) {
+ q->setPosition(newPosition);
+ finishTransition();
+ return;
+ }
+
+ if (!transitionManager)
+ transitionManager.reset(new QQuickSwipeTransitionManager(q));
+
+ transitionManager->transition(transition, newPosition);
+}
+
+void QQuickSwipePrivate::finishTransition()
+{
+ Q_Q(QQuickSwipe);
+ q->setComplete(qFuzzyCompare(qAbs(position), 1.0));
+ if (complete)
+ emit q->opened();
+ else
+ emit q->closed();
+}
+
QQuickSwipe::QQuickSwipe(QQuickSwipeDelegate *control) :
QObject(*(new QQuickSwipePrivate(control)))
{
@@ -574,11 +658,62 @@ void QQuickSwipe::setComplete(bool complete)
emit completed();
}
+bool QQuickSwipe::isEnabled() const
+{
+ Q_D(const QQuickSwipe);
+ return d->enabled;
+}
+
+void QQuickSwipe::setEnabled(bool enabled)
+{
+ Q_D(QQuickSwipe);
+ if (enabled == d->enabled)
+ return;
+
+ d->enabled = enabled;
+ emit enabledChanged();
+}
+
+QQuickTransition *QQuickSwipe::transition() const
+{
+ Q_D(const QQuickSwipe);
+ return d->transition;
+}
+
+void QQuickSwipe::setTransition(QQuickTransition *transition)
+{
+ Q_D(QQuickSwipe);
+ if (transition == d->transition)
+ return;
+
+ d->transition = transition;
+ emit transitionChanged();
+}
+
+void QQuickSwipe::open(QQuickSwipeDelegate::Side side)
+{
+ Q_D(QQuickSwipe);
+ if (qFuzzyCompare(qAbs(d->position), 1.0))
+ return;
+
+ if ((side != QQuickSwipeDelegate::Left && side != QQuickSwipeDelegate::Right)
+ || (!d->left && !d->behind && side == QQuickSwipeDelegate::Left)
+ || (!d->right && !d->behind && side == QQuickSwipeDelegate::Right))
+ return;
+
+ d->beginTransition(side);
+ d->wasComplete = true;
+ d->velocityCalculator.reset();
+ d->positionBeforePress = d->position;
+}
+
void QQuickSwipe::close()
{
Q_D(QQuickSwipe);
- setPosition(0);
- setComplete(false);
+ if (qFuzzyIsNull(d->position))
+ return;
+
+ d->beginTransition(0.0);
d->wasComplete = false;
d->positionBeforePress = 0.0;
d->velocityCalculator.reset();
@@ -633,12 +768,17 @@ bool QQuickSwipeDelegatePrivate::handleMouseMoveEvent(QQuickItem *item, QMouseEv
stopPressAndHold();
}
+ // The delegate can still be pressed when swipe.enabled is false,
+ // but the mouse moving shouldn't have any effect on swipe.position.
+ QQuickSwipePrivate *swipePrivate = QQuickSwipePrivate::get(&swipe);
+ if (!swipePrivate->enabled)
+ return false;
+
// Protect against division by zero.
if (width == 0)
return false;
// Don't bother reacting to events if we don't have any delegates.
- QQuickSwipePrivate *swipePrivate = QQuickSwipePrivate::get(&swipe);
if (!swipePrivate->left && !swipePrivate->right && !swipePrivate->behind)
return false;
@@ -710,6 +850,8 @@ bool QQuickSwipeDelegatePrivate::handleMouseMoveEvent(QQuickItem *item, QMouseEv
position = distance > 0 ? normalizedDistance - 1.0 : normalizedDistance + 1.0;
}
+ if (swipePrivate->isTransitioning())
+ swipePrivate->transitionManager->cancel();
swipe.setPosition(position);
}
} else {
@@ -756,17 +898,14 @@ bool QQuickSwipeDelegatePrivate::handleMouseReleaseEvent(QQuickItem *item, QMous
const qreal swipeVelocity = swipePrivate->velocityCalculator.velocity().x();
if (swipePrivate->position > 0.5 ||
(swipePrivate->position > 0.0 && swipeVelocity > exposeVelocityThreshold)) {
- swipe.setPosition(1.0);
- swipe.setComplete(true);
+ swipePrivate->beginTransition(1.0);
swipePrivate->wasComplete = true;
} else if (swipePrivate->position < -0.5 ||
(swipePrivate->position < 0.0 && swipeVelocity < -exposeVelocityThreshold)) {
- swipe.setPosition(-1.0);
- swipe.setComplete(true);
+ swipePrivate->beginTransition(-1.0);
swipePrivate->wasComplete = true;
- } else {
- swipe.setPosition(0.0);
- swipe.setComplete(false);
+ } else if (!swipePrivate->isTransitioning()) {
+ swipePrivate->beginTransition(0.0);
swipePrivate->wasComplete = false;
}
@@ -820,6 +959,27 @@ QQuickSwipeDelegate::QQuickSwipeDelegate(QQuickItem *parent) :
}
/*!
+ \since QtQuick.Controls 2.2
+ \qmlmethod void QtQuick.Controls::SwipeDelegate::swipe.open(enumeration side)
+
+ This method sets the \c position of the swipe so that it opens
+ from the specified \a side.
+
+ Available values:
+ \value SwipeDelegate.Left The \c position is set to \c 1, which makes the swipe open
+ from the left. Either \c swipe.left or \c swipe.behind must
+ have been specified; otherwise the call is ignored.
+ \value SwipeDelegate.Right The \c position is set to \c -1, which makes the swipe open
+ from the right. Either \c swipe.right or \c swipe.behind must
+ have been specified; otherwise the call is ignored.
+
+ Any animations defined for the \l {Item::}{x} position of \l {Control::}{contentItem}
+ and \l {Control::}{background} will be triggered.
+
+ \sa swipe, swipe.close()
+*/
+
+/*!
\since QtQuick.Controls 2.1
\qmlmethod void QtQuick.Controls::SwipeDelegate::swipe.close()
@@ -827,6 +987,47 @@ QQuickSwipeDelegate::QQuickSwipeDelegate(QQuickItem *parent) :
defined for the \l {Item::}{x} position of \l {Control::}{contentItem}
and \l {Control::}{background} will be triggered.
+ \sa swipe, swipe.open()
+*/
+
+/*!
+ \since QtQuick.Controls 2.2
+ \qmlsignal void QtQuick.Controls::SwipeDelegate::swipe.opened()
+
+ This signal is emitted when the delegate has been swiped open
+ and the transition has finished.
+
+ It is useful for performing some action upon completion of a swipe.
+ For example, it can be used to remove the delegate from the list
+ that it is in.
+
+ \sa swipe, swipe.closed()
+*/
+
+/*!
+ \since QtQuick.Controls 2.2
+ \qmlsignal void QtQuick.Controls::SwipeDelegate::swipe.closed()
+
+ This signal is emitted when the delegate has been swiped to closed
+ and the transition has finished.
+
+ It is useful for performing some action upon cancellation of a swipe.
+ For example, it can be used to cancel the removal of the delegate from
+ the list that it is in.
+
+ \sa swipe, swipe.opened()
+*/
+
+/*!
+ \since QtQuick.Controls 2.1
+ \qmlsignal void QtQuick.Controls::SwipeDelegate::swipe.completed()
+
+ This signal is emitted when \c swipe.complete becomes \c true.
+
+ It is useful for performing some action upon completion of a swipe.
+ For example, it can be used to remove the delegate from the list
+ that it is in.
+
\sa swipe
*/
@@ -834,12 +1035,14 @@ QQuickSwipeDelegate::QQuickSwipeDelegate(QQuickItem *parent) :
\qmlpropertygroup QtQuick.Controls::SwipeDelegate::swipe
\qmlproperty real QtQuick.Controls::SwipeDelegate::swipe.position
\qmlproperty bool QtQuick.Controls::SwipeDelegate::swipe.complete
+ \qmlproperty bool QtQuick.Controls::SwipeDelegate::swipe.enabled
\qmlproperty Component QtQuick.Controls::SwipeDelegate::swipe.left
\qmlproperty Component QtQuick.Controls::SwipeDelegate::swipe.behind
\qmlproperty Component QtQuick.Controls::SwipeDelegate::swipe.right
\qmlproperty Item QtQuick.Controls::SwipeDelegate::swipe.leftItem
\qmlproperty Item QtQuick.Controls::SwipeDelegate::swipe.behindItem
\qmlproperty Item QtQuick.Controls::SwipeDelegate::swipe.rightItem
+ \qmlproperty Transition QtQuick.Controls::SwipeDelegate::swipe.transition
\table
\header
@@ -859,6 +1062,11 @@ QQuickSwipeDelegate::QQuickSwipeDelegate(QQuickItem *parent) :
When complete is \c true, any interactive items declared in \c left,
\c right, or \c behind will receive mouse events.
\row
+ \li enabled
+ \li This property determines whether or not the control can be swiped.
+
+ This property was added in QtQuick.Controls 2.2.
+ \row
\li left
\li This property holds the left delegate.
@@ -906,17 +1114,16 @@ QQuickSwipeDelegate::QQuickSwipeDelegate(QQuickItem *parent) :
If \c right has not been set, or the position hasn't changed since
creation of the SwipeDelegate, this property will be \c null.
\row
- \li completed()
- \li This signal is emitted when \c complete becomes \c true.
+ \li transition
+ \li This property holds the transition that is applied when a swipe is released,
+ or \l swipe.open() or \l swipe.close() is called.
- It is useful for performing some action upon completion of a swipe.
- For example, it can be used to remove the delegate from the list
- that it is in.
+ \snippet qtquickcontrols2-swipedelegate-transition.qml 1
- This signal was added in QtQuick.Controls 2.1.
+ This property was added in Qt Quick Controls 2.2.
\endtable
- \sa {Control::}{contentItem}, {Control::}{background}, swipe.close()
+ \sa {Control::}{contentItem}, {Control::}{background}, swipe.open(), swipe.close()
*/
QQuickSwipe *QQuickSwipeDelegate::swipe() const
{
@@ -978,7 +1185,11 @@ void QQuickSwipeDelegate::mousePressEvent(QMouseEvent *event)
{
Q_D(QQuickSwipeDelegate);
QQuickItemDelegate::mousePressEvent(event);
+
QQuickSwipePrivate *swipePrivate = QQuickSwipePrivate::get(&d->swipe);
+ if (!swipePrivate->enabled)
+ return;
+
swipePrivate->positionBeforePress = swipePrivate->position;
swipePrivate->velocityCalculator.startMeasuring(event->pos(), event->timestamp());
}
diff --git a/src/quicktemplates2/qquickswipedelegate_p.h b/src/quicktemplates2/qquickswipedelegate_p.h
index cb3978ad..36f82276 100644
--- a/src/quicktemplates2/qquickswipedelegate_p.h
+++ b/src/quicktemplates2/qquickswipedelegate_p.h
@@ -67,6 +67,9 @@ public:
QQuickSwipe *swipe() const;
+ enum Side { Left = 1, Right = -1 };
+ Q_ENUM(Side)
+
static QQuickSwipeDelegateAttached *qmlAttachedProperties(QObject *object);
protected:
@@ -112,5 +115,6 @@ QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickSwipeDelegate)
QML_DECLARE_TYPEINFO(QQuickSwipeDelegate, QML_HAS_ATTACHED_PROPERTIES)
+Q_DECLARE_METATYPE(QQuickSwipeDelegate::Side)
#endif // QQUICKSWIPEDELEGATE_P_H
diff --git a/src/quicktemplates2/qquickswitch.cpp b/src/quicktemplates2/qquickswitch.cpp
index fa1b5463..15f8c4ec 100644
--- a/src/quicktemplates2/qquickswitch.cpp
+++ b/src/quicktemplates2/qquickswitch.cpp
@@ -187,15 +187,18 @@ void QQuickSwitch::nextCheckState()
{
Q_D(QQuickSwitch);
if (keepMouseGrab())
- setChecked(d->position > 0.5);
+ d->toggle(d->position > 0.5);
else
QQuickAbstractButton::nextCheckState();
}
-void QQuickSwitch::checkStateSet()
+void QQuickSwitch::buttonChange(ButtonChange change)
{
Q_D(QQuickSwitch);
- setPosition(d->checked ? 1.0 : 0.0);
+ if (change == ButtonCheckedChange)
+ setPosition(d->checked ? 1.0 : 0.0);
+ else
+ QQuickAbstractButton::buttonChange(change);
}
QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickswitch_p.h b/src/quicktemplates2/qquickswitch_p.h
index 405e15f4..ccdb23a8 100644
--- a/src/quicktemplates2/qquickswitch_p.h
+++ b/src/quicktemplates2/qquickswitch_p.h
@@ -80,7 +80,7 @@ protected:
void mirrorChange() override;
void nextCheckState() override;
- void checkStateSet() override;
+ void buttonChange(ButtonChange change) override;
private:
Q_DISABLE_COPY(QQuickSwitch)
diff --git a/src/quicktemplates2/qquickswitchdelegate.cpp b/src/quicktemplates2/qquickswitchdelegate.cpp
index 72b4803d..9455e619 100644
--- a/src/quicktemplates2/qquickswitchdelegate.cpp
+++ b/src/quicktemplates2/qquickswitchdelegate.cpp
@@ -192,15 +192,18 @@ void QQuickSwitchDelegate::nextCheckState()
{
Q_D(QQuickSwitchDelegate);
if (keepMouseGrab())
- setChecked(d->position > 0.5);
+ d->toggle(d->position > 0.5);
else
QQuickItemDelegate::nextCheckState();
}
-void QQuickSwitchDelegate::checkStateSet()
+void QQuickSwitchDelegate::buttonChange(ButtonChange change)
{
Q_D(QQuickSwitchDelegate);
- setPosition(d->checked ? 1.0 : 0.0);
+ if (change == ButtonCheckedChange)
+ setPosition(d->checked ? 1.0 : 0.0);
+ else
+ QQuickAbstractButton::buttonChange(change);
}
QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickswitchdelegate_p.h b/src/quicktemplates2/qquickswitchdelegate_p.h
index f32bc695..f8cb33d8 100644
--- a/src/quicktemplates2/qquickswitchdelegate_p.h
+++ b/src/quicktemplates2/qquickswitchdelegate_p.h
@@ -81,7 +81,7 @@ protected:
void mirrorChange() override;
void nextCheckState() override;
- void checkStateSet() override;
+ void buttonChange(ButtonChange change) override;
private:
Q_DISABLE_COPY(QQuickSwitchDelegate)
diff --git a/src/quicktemplates2/qquicktabbar.cpp b/src/quicktemplates2/qquicktabbar.cpp
index b32e55d3..fd21b3e6 100644
--- a/src/quicktemplates2/qquicktabbar.cpp
+++ b/src/quicktemplates2/qquicktabbar.cpp
@@ -105,14 +105,26 @@ public:
void updateLayout();
void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff) override;
+ void itemImplicitWidthChanged(QQuickItem *item) override;
+ void itemImplicitHeightChanged(QQuickItem *item) override;
bool updatingLayout;
+ bool hasContentWidth;
+ bool hasContentHeight;
+ qreal contentWidth;
+ qreal contentHeight;
QQuickTabBar::Position position;
};
-QQuickTabBarPrivate::QQuickTabBarPrivate() : updatingLayout(false), position(QQuickTabBar::Header)
+QQuickTabBarPrivate::QQuickTabBarPrivate()
+ : updatingLayout(false),
+ hasContentWidth(false),
+ hasContentHeight(false),
+ contentWidth(0),
+ contentHeight(0),
+ position(QQuickTabBar::Header)
{
- changeTypes |= Geometry;
+ changeTypes |= Geometry | ImplicitWidth | ImplicitHeight;
}
void QQuickTabBarPrivate::updateCurrentItem()
@@ -134,34 +146,61 @@ void QQuickTabBarPrivate::updateLayout()
{
Q_Q(QQuickTabBar);
const int count = contentModel->count();
- if (count > 0 && contentItem) {
- qreal reservedWidth = 0;
- QVector<QQuickItem *> resizableItems;
- resizableItems.reserve(count);
-
- for (int i = 0; i < count; ++i) {
- QQuickItem *item = q->itemAt(i);
- if (item) {
- QQuickItemPrivate *p = QQuickItemPrivate::get(item);
- if (!p->widthValid)
- resizableItems += item;
- else
- reservedWidth += item->width();
+ if (count <= 0 || !contentItem)
+ return;
+
+ qreal maxHeight = 0;
+ qreal totalWidth = 0;
+ qreal reservedWidth = 0;
+
+ QVector<QQuickItem *> resizableItems;
+ resizableItems.reserve(count);
+
+ for (int i = 0; i < count; ++i) {
+ QQuickItem *item = q->itemAt(i);
+ if (item) {
+ QQuickItemPrivate *p = QQuickItemPrivate::get(item);
+ if (!p->widthValid) {
+ resizableItems += item;
+ totalWidth += item->implicitWidth();
+ } else {
+ reservedWidth += item->width();
+ totalWidth += item->width();
}
+ maxHeight = qMax(maxHeight, item->implicitHeight());
}
+ }
- if (!resizableItems.isEmpty()) {
- const qreal totalSpacing = qMax(0, count - 1) * spacing;
- const qreal itemWidth = (contentItem->width() - reservedWidth - totalSpacing) / resizableItems.count();
+ const qreal totalSpacing = qMax(0, count - 1) * spacing;
+ totalWidth += totalSpacing;
- updatingLayout = true;
- for (QQuickItem *item : qAsConst(resizableItems)) {
- item->setWidth(itemWidth);
- QQuickItemPrivate::get(item)->widthValid = false;
- }
- updatingLayout = false;
+ if (!resizableItems.isEmpty()) {
+ const qreal itemWidth = (contentItem->width() - reservedWidth - totalSpacing) / resizableItems.count();
+
+ updatingLayout = true;
+ for (QQuickItem *item : qAsConst(resizableItems)) {
+ item->setWidth(itemWidth);
+ QQuickItemPrivate::get(item)->widthValid = false;
}
+ updatingLayout = false;
+ }
+
+ bool contentWidthChange = false;
+ if (!hasContentWidth && !qFuzzyCompare(contentWidth, totalWidth)) {
+ contentWidth = totalWidth;
+ contentWidthChange = true;
+ }
+
+ bool contentHeightChange = false;
+ if (!hasContentHeight && !qFuzzyCompare(contentHeight, maxHeight)) {
+ contentHeight = maxHeight;
+ contentHeightChange = true;
}
+
+ if (contentWidthChange)
+ emit q->contentWidthChanged();
+ if (contentHeightChange)
+ emit q->contentHeightChanged();
}
void QQuickTabBarPrivate::itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &)
@@ -170,6 +209,18 @@ void QQuickTabBarPrivate::itemGeometryChanged(QQuickItem *, QQuickGeometryChange
updateLayout();
}
+void QQuickTabBarPrivate::itemImplicitWidthChanged(QQuickItem *)
+{
+ if (!updatingLayout && !hasContentWidth)
+ updateLayout();
+}
+
+void QQuickTabBarPrivate::itemImplicitHeightChanged(QQuickItem *)
+{
+ if (!updatingLayout && !hasContentHeight)
+ updateLayout();
+}
+
QQuickTabBar::QQuickTabBar(QQuickItem *parent) :
QQuickContainer(*(new QQuickTabBarPrivate), parent)
{
@@ -210,6 +261,87 @@ void QQuickTabBar::setPosition(Position position)
emit positionChanged();
}
+/*!
+ \since QtQuick.Controls 2.2
+ \qmlproperty real QtQuick.Controls::TabBar::contentWidth
+
+ This property holds the content width. It is used for calculating the total
+ implicit width of the tab bar.
+
+ Unless explicitly overridden, the content width is automatically calculated
+ based on the total implicit width of the tabs and the \l {Control::}{spacing}
+ of the tab bar.
+
+ \sa contentHeight
+*/
+qreal QQuickTabBar::contentWidth() const
+{
+ Q_D(const QQuickTabBar);
+ return d->contentWidth;
+}
+
+void QQuickTabBar::setContentWidth(qreal width)
+{
+ Q_D(QQuickTabBar);
+ d->hasContentWidth = true;
+ if (qFuzzyCompare(d->contentWidth, width))
+ return;
+
+ d->contentWidth = width;
+ emit contentWidthChanged();
+}
+
+void QQuickTabBar::resetContentWidth()
+{
+ Q_D(QQuickTabBar);
+ if (!d->hasContentWidth)
+ return;
+
+ d->hasContentWidth = false;
+ if (isComponentComplete())
+ d->updateLayout();
+}
+
+/*!
+ \since QtQuick.Controls 2.2
+ \qmlproperty real QtQuick.Controls::TabBar::contentHeight
+
+ This property holds the content height. It is used for calculating the total
+ implicit height of the tab bar.
+
+ Unless explicitly overridden, the content height is automatically calculated
+ based on the maximum implicit height of the tabs.
+
+ \sa contentWidth
+*/
+qreal QQuickTabBar::contentHeight() const
+{
+ Q_D(const QQuickTabBar);
+ return d->contentHeight;
+}
+
+void QQuickTabBar::setContentHeight(qreal height)
+{
+ Q_D(QQuickTabBar);
+ d->hasContentHeight = true;
+ if (qFuzzyCompare(d->contentHeight, height))
+ return;
+
+ d->contentHeight = height;
+ emit contentHeightChanged();
+}
+
+void QQuickTabBar::resetContentHeight()
+{
+ Q_D(QQuickTabBar);
+ if (!d->hasContentHeight)
+ return;
+
+ d->hasContentHeight = false;
+ if (isComponentComplete())
+ d->updateLayout();
+}
+
void QQuickTabBar::updatePolish()
{
Q_D(QQuickTabBar);
diff --git a/src/quicktemplates2/qquicktabbar_p.h b/src/quicktemplates2/qquicktabbar_p.h
index 31491b54..1d85d414 100644
--- a/src/quicktemplates2/qquicktabbar_p.h
+++ b/src/quicktemplates2/qquicktabbar_p.h
@@ -58,6 +58,8 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickTabBar : public QQuickContainer
{
Q_OBJECT
Q_PROPERTY(Position position READ position WRITE setPosition NOTIFY positionChanged FINAL)
+ Q_PROPERTY(qreal contentWidth READ contentWidth WRITE setContentWidth RESET resetContentWidth NOTIFY contentWidthChanged FINAL REVISION 2)
+ Q_PROPERTY(qreal contentHeight READ contentHeight WRITE setContentHeight RESET resetContentHeight NOTIFY contentHeightChanged FINAL REVISION 2)
public:
explicit QQuickTabBar(QQuickItem *parent = nullptr);
@@ -71,8 +73,18 @@ public:
Position position() const;
void setPosition(Position position);
+ qreal contentWidth() const;
+ void setContentWidth(qreal width);
+ void resetContentWidth();
+
+ qreal contentHeight() const;
+ void setContentHeight(qreal height);
+ void resetContentHeight();
+
Q_SIGNALS:
void positionChanged();
+ void contentWidthChanged();
+ void contentHeightChanged();
protected:
void updatePolish() override;
diff --git a/src/quicktemplates2/qquicktooltip.cpp b/src/quicktemplates2/qquicktooltip.cpp
index 3ce4c762..7a98ea58 100644
--- a/src/quicktemplates2/qquicktooltip.cpp
+++ b/src/quicktemplates2/qquicktooltip.cpp
@@ -107,7 +107,7 @@ QT_BEGIN_NAMESPACE
Should one need more fine-grained control over the tool tip position, or
multiple simultaneous tool tip instances are needed, it is also possible
to create local tool tip instances. This way, it is possible to
- \l {Customizing ToolTip}{customize} the tool tip, and the whole \l Popup
+ \l {Customizing ToolTip}{customize} the tool tip, and the whole \l Popup
API is available. The following example presents a tool tip that presents
the value of a slider when the handle is dragged.
@@ -345,7 +345,7 @@ QQuickToolTip *QQuickToolTipAttachedPrivate::instance(bool create) const
if (!tip && create) {
// TODO: a cleaner way to create the instance? QQml(Meta)Type?
QQmlComponent component(engine);
- component.setData("import QtQuick.Controls 2.1; ToolTip { }", QUrl());
+ component.setData("import QtQuick.Controls 2.2; ToolTip { }", QUrl());
QObject *object = component.create();
if (object)
diff --git a/src/quicktemplates2/qquicktumbler.cpp b/src/quicktemplates2/qquicktumbler.cpp
index 9091743c..7bf2c66f 100644
--- a/src/quicktemplates2/qquicktumbler.cpp
+++ b/src/quicktemplates2/qquicktumbler.cpp
@@ -439,6 +439,19 @@ void QQuickTumbler::resetWrap()
d->setWrapBasedOnCount();
}
+/*!
+ \qmlproperty bool QtQuick.Controls::Tumbler::moving
+ \since QtQuick.Controls 2.2
+
+ This property describes whether the tumbler is currently moving, due to
+ the user either dragging or flicking it.
+*/
+bool QQuickTumbler::isMoving() const
+{
+ Q_D(const QQuickTumbler);
+ return d->view && d->view->property("moving").toBool();
+}
+
QQuickTumblerAttached *QQuickTumbler::qmlAttachedProperties(QObject *object)
{
return new QQuickTumblerAttached(object);
@@ -505,6 +518,7 @@ void QQuickTumblerPrivate::disconnectFromView()
QObject::disconnect(view, SIGNAL(currentIndexChanged()), q, SLOT(_q_onViewCurrentIndexChanged()));
QObject::disconnect(view, SIGNAL(currentItemChanged()), q, SIGNAL(currentItemChanged()));
QObject::disconnect(view, SIGNAL(countChanged()), q, SLOT(_q_onViewCountChanged()));
+ QObject::disconnect(view, SIGNAL(movingChanged()), q, SIGNAL(movingChanged()));
QQuickItemPrivate *oldViewContentItemPrivate = QQuickItemPrivate::get(viewContentItem);
oldViewContentItemPrivate->removeItemChangeListener(this, QQuickItemPrivate::Children);
@@ -529,6 +543,7 @@ void QQuickTumblerPrivate::setupViewData(QQuickItem *newControlContentItem)
QObject::connect(view, SIGNAL(currentIndexChanged()), q, SLOT(_q_onViewCurrentIndexChanged()));
QObject::connect(view, SIGNAL(currentItemChanged()), q, SIGNAL(currentItemChanged()));
QObject::connect(view, SIGNAL(countChanged()), q, SLOT(_q_onViewCountChanged()));
+ QObject::connect(view, SIGNAL(movingChanged()), q, SIGNAL(movingChanged()));
QQuickItemPrivate *viewContentItemPrivate = QQuickItemPrivate::get(viewContentItem);
viewContentItemPrivate->addItemChangeListener(this, QQuickItemPrivate::Children);
diff --git a/src/quicktemplates2/qquicktumbler_p.h b/src/quicktemplates2/qquicktumbler_p.h
index 68644a5a..b71a7636 100644
--- a/src/quicktemplates2/qquicktumbler_p.h
+++ b/src/quicktemplates2/qquicktumbler_p.h
@@ -67,6 +67,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickTumbler : public QQuickControl
Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged FINAL)
Q_PROPERTY(int visibleItemCount READ visibleItemCount WRITE setVisibleItemCount NOTIFY visibleItemCountChanged FINAL)
Q_PROPERTY(bool wrap READ wrap WRITE setWrap RESET resetWrap NOTIFY wrapChanged FINAL REVISION 1)
+ Q_PROPERTY(bool moving READ isMoving NOTIFY movingChanged FINAL REVISION 2)
public:
explicit QQuickTumbler(QQuickItem *parent = nullptr);
@@ -91,6 +92,8 @@ public:
void setWrap(bool wrap);
void resetWrap();
+ bool isMoving() const;
+
static QQuickTumblerAttached *qmlAttachedProperties(QObject *object);
Q_SIGNALS:
@@ -101,6 +104,7 @@ Q_SIGNALS:
void delegateChanged();
void visibleItemCountChanged();
Q_REVISION(1) void wrapChanged();
+ Q_REVISION(2) void movingChanged();
protected:
void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override;
diff --git a/src/quicktemplates2/quicktemplates2.pri b/src/quicktemplates2/quicktemplates2.pri
index 4a128501..e8f02d62 100644
--- a/src/quicktemplates2/quicktemplates2.pri
+++ b/src/quicktemplates2/quicktemplates2.pri
@@ -15,6 +15,7 @@ HEADERS += \
$$PWD/qquickcontainer_p_p.h \
$$PWD/qquickcontrol_p.h \
$$PWD/qquickcontrol_p_p.h \
+ $$PWD/qquickdelaybutton_p.h \
$$PWD/qquickdial_p.h \
$$PWD/qquickdialog_p.h \
$$PWD/qquickdialog_p_p.h \
@@ -42,6 +43,8 @@ HEADERS += \
$$PWD/qquickpane_p_p.h \
$$PWD/qquickpopup_p.h \
$$PWD/qquickpopup_p_p.h \
+ $$PWD/qquickpopupitem_p_p.h \
+ $$PWD/qquickpopuppositioner_p_p.h \
$$PWD/qquickpresshandler_p_p.h \
$$PWD/qquickprogressbar_p.h \
$$PWD/qquickradiobutton_p.h \
@@ -53,6 +56,8 @@ HEADERS += \
$$PWD/qquickshortcutcontext_p_p.h \
$$PWD/qquickslider_p.h \
$$PWD/qquickspinbox_p.h \
+ $$PWD/qquickstackelement_p_p.h \
+ $$PWD/qquickstacktransition_p_p.h \
$$PWD/qquickstackview_p.h \
$$PWD/qquickstackview_p_p.h \
$$PWD/qquickswipe_p.h \
@@ -86,6 +91,7 @@ SOURCES += \
$$PWD/qquickcombobox.cpp \
$$PWD/qquickcontainer.cpp \
$$PWD/qquickcontrol.cpp \
+ $$PWD/qquickdelaybutton.cpp \
$$PWD/qquickdial.cpp \
$$PWD/qquickdialog.cpp \
$$PWD/qquickdialogbuttonbox.cpp \
@@ -103,6 +109,8 @@ SOURCES += \
$$PWD/qquickpagelayout.cpp \
$$PWD/qquickpane.cpp \
$$PWD/qquickpopup.cpp \
+ $$PWD/qquickpopupitem.cpp \
+ $$PWD/qquickpopuppositioner.cpp \
$$PWD/qquickpresshandler.cpp \
$$PWD/qquickprogressbar.cpp \
$$PWD/qquickradiobutton.cpp \
@@ -114,6 +122,8 @@ SOURCES += \
$$PWD/qquickshortcutcontext.cpp \
$$PWD/qquickslider.cpp \
$$PWD/qquickspinbox.cpp \
+ $$PWD/qquickstackelement.cpp \
+ $$PWD/qquickstacktransition.cpp \
$$PWD/qquickstackview.cpp \
$$PWD/qquickstackview_p.cpp \
$$PWD/qquickswipedelegate.cpp \
diff --git a/tests/auto/controls/data/TumblerListView.qml b/tests/auto/controls/data/TumblerListView.qml
index 4ab2918b..87623f8c 100644
--- a/tests/auto/controls/data/TumblerListView.qml
+++ b/tests/auto/controls/data/TumblerListView.qml
@@ -48,6 +48,6 @@ ListView {
snapMode: ListView.SnapToItem
highlightRangeMode: ListView.StrictlyEnforceRange
preferredHighlightBegin: height / 2 - (height / parent.visibleItemCount / 2)
- preferredHighlightEnd: height / 2 + (height / parent.visibleItemCount / 2)
+ preferredHighlightEnd: height / 2 + (height / parent.visibleItemCount / 2)
clip: true
}
diff --git a/tests/auto/controls/data/tst_abstractbutton.qml b/tests/auto/controls/data/tst_abstractbutton.qml
index b785b7a1..33ee5846 100644
--- a/tests/auto/controls/data/tst_abstractbutton.qml
+++ b/tests/auto/controls/data/tst_abstractbutton.qml
@@ -66,7 +66,7 @@ TestCase {
}
function test_text() {
- var control = button.createObject(testCase);
+ var control = createTemporaryObject(button, testCase);
verify(control);
compare(control.text, "");
@@ -74,21 +74,18 @@ TestCase {
compare(control.text, "Button");
control.text = "";
compare(control.text, "");
-
- control.destroy();
}
function test_baseline() {
- var control = button.createObject(testCase, {padding: 6})
+ var control = createTemporaryObject(button, testCase, {padding: 6})
verify(control)
compare(control.baselineOffset, 0)
control.contentItem = item.createObject(control, {baselineOffset: 12})
compare(control.baselineOffset, 18)
- control.destroy()
}
function test_implicitSize() {
- var control = button.createObject(testCase)
+ var control = createTemporaryObject(button, testCase)
verify(control)
compare(control.implicitWidth, 0)
@@ -105,12 +102,10 @@ TestCase {
control.padding = 100
compare(control.implicitWidth, 210)
compare(control.implicitHeight, 220)
-
- control.destroy()
}
function test_pressAndHold() {
- var control = button.createObject(testCase, {checkable: true})
+ var control = createTemporaryObject(button, testCase, {checkable: true})
verify(control)
var pressAndHoldSpy = signalSpy.createObject(control, {target: control, signalName: "pressAndHold"})
@@ -122,7 +117,5 @@ TestCase {
mouseRelease(control)
compare(control.checked, false)
-
- control.destroy()
}
}
diff --git a/tests/auto/controls/data/tst_busyindicator.qml b/tests/auto/controls/data/tst_busyindicator.qml
index 284554d4..f142f551 100644
--- a/tests/auto/controls/data/tst_busyindicator.qml
+++ b/tests/auto/controls/data/tst_busyindicator.qml
@@ -56,13 +56,11 @@ TestCase {
}
function test_running() {
- var control = busyIndicator.createObject(testCase)
+ var control = createTemporaryObject(busyIndicator, testCase)
verify(control)
compare(control.running, true)
control.running = false
compare(control.running, false)
-
- control.destroy()
}
}
diff --git a/tests/auto/controls/data/tst_button.qml b/tests/auto/controls/data/tst_button.qml
index 699f0e1e..c7e2d650 100644
--- a/tests/auto/controls/data/tst_button.qml
+++ b/tests/auto/controls/data/tst_button.qml
@@ -58,7 +58,7 @@ TestCase {
Component {
id: signalSequenceSpy
SignalSequenceSpy {
- signals: ["pressed", "released", "canceled", "clicked", "doubleClicked", "pressedChanged", "downChanged", "checkedChanged"]
+ signals: ["pressed", "released", "canceled", "clicked", "toggled", "doubleClicked", "pressedChanged", "downChanged", "checkedChanged"]
}
}
@@ -68,7 +68,7 @@ TestCase {
}
function test_text() {
- var control = button.createObject(testCase)
+ var control = createTemporaryObject(button, testCase)
verify(control)
compare(control.text, "")
@@ -76,12 +76,10 @@ TestCase {
compare(control.text, "Button")
control.text = ""
compare(control.text, "")
-
- control.destroy()
}
function test_mouse() {
- var control = button.createObject(testCase)
+ var control = createTemporaryObject(button, testCase)
verify(control)
var sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
@@ -148,12 +146,10 @@ TestCase {
"clicked"]
mouseDoubleClickSequence(control, control.width / 2, control.height / 2, Qt.LeftButton)
verify(sequenceSpy.success)
-
- control.destroy()
}
function test_keys() {
- var control = button.createObject(testCase)
+ var control = createTemporaryObject(button, testCase)
verify(control)
control.forceActiveFocus()
@@ -180,8 +176,6 @@ TestCase {
keyClick(keys[i])
verify(sequenceSpy.success)
}
-
- control.destroy()
}
function eventErrorMessage(actual, expected) {
@@ -189,7 +183,7 @@ TestCase {
}
function test_autoRepeat() {
- var control = button.createObject(testCase)
+ var control = createTemporaryObject(button, testCase)
verify(control)
compare(control.autoRepeat, false)
@@ -270,19 +264,16 @@ TestCase {
compare(clickSpy.count, 0)
compare(pressSpy.count, 0)
compare(releaseSpy.count, 0)
-
- control.destroy()
}
function test_baseline() {
- var control = button.createObject(testCase)
+ var control = createTemporaryObject(button, testCase)
verify(control)
compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset)
- control.destroy()
}
function test_checkable() {
- var control = button.createObject(testCase)
+ var control = createTemporaryObject(button, testCase)
verify(control)
verify(control.hasOwnProperty("checkable"))
verify(!control.checkable)
@@ -306,6 +297,7 @@ TestCase {
["pressedChanged", { "pressed": false }],
["downChanged", { "down": false }],
["checkedChanged", { "checked": true }],
+ "toggled",
"released",
"clicked"]
control.checkable = true
@@ -319,23 +311,20 @@ TestCase {
["pressedChanged", { "pressed": false }],
["downChanged", { "down": false }],
["checkedChanged", { "checked": false }],
+ "toggled",
"released",
"clicked"]
mouseClick(control)
verify(!control.checked)
verify(sequenceSpy.success)
-
- control.destroy()
}
function test_highlighted() {
- var control = button.createObject(testCase)
+ var control = createTemporaryObject(button, testCase)
verify(control)
verify(!control.highlighted)
control.highlighted = true
verify(control.highlighted)
-
- control.destroy()
}
}
diff --git a/tests/auto/controls/data/tst_buttongroup.qml b/tests/auto/controls/data/tst_buttongroup.qml
index 7d97614e..8ffdf74e 100644
--- a/tests/auto/controls/data/tst_buttongroup.qml
+++ b/tests/auto/controls/data/tst_buttongroup.qml
@@ -61,13 +61,11 @@ TestCase {
}
function test_null() {
- var group = buttonGroup.createObject(testCase)
+ var group = createTemporaryObject(buttonGroup, testCase)
verify(group)
group.addButton(null)
group.removeButton(null)
-
- group.destroy()
}
Component {
@@ -81,16 +79,16 @@ TestCase {
}
function test_current() {
- var group = buttonGroup.createObject(testCase)
+ var group = createTemporaryObject(buttonGroup, testCase)
verify(group)
- var checkedButtonSpy = signalSpy.createObject(testCase, {target: group, signalName: "checkedButtonChanged"})
+ var checkedButtonSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "checkedButtonChanged"})
verify(checkedButtonSpy.valid)
verify(!group.checkedButton)
- var button1 = button.createObject(testCase, {checked: true})
- var button2 = button.createObject(testCase, {checked: false})
- var button3 = button.createObject(testCase, {checked: true, objectName: "3"})
+ var button1 = createTemporaryObject(button, testCase, {checked: true})
+ var button2 = createTemporaryObject(button, testCase, {checked: false})
+ var button3 = createTemporaryObject(button, testCase, {checked: true, objectName: "3"})
// add checked
group.addButton(button1)
@@ -147,22 +145,20 @@ TestCase {
compare(button2.checked, false)
compare(button3.checked, false)
compare(checkedButtonSpy.count, 5)
-
- group.destroy()
}
function test_buttons() {
- var group = buttonGroup.createObject(testCase)
+ var group = createTemporaryObject(buttonGroup, testCase)
verify(group)
- var buttonsSpy = signalSpy.createObject(testCase, {target: group, signalName: "buttonsChanged"})
+ var buttonsSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "buttonsChanged"})
verify(buttonsSpy.valid)
compare(group.buttons.length, 0)
compare(group.checkedButton, null)
- var button1 = button.createObject(testCase, {checked: true})
- var button2 = button.createObject(testCase, {checked: false})
+ var button1 = createTemporaryObject(button, testCase, {checked: true})
+ var button2 = createTemporaryObject(button, testCase, {checked: false})
group.buttons = [button1, button2]
compare(group.buttons.length, 2)
@@ -171,7 +167,7 @@ TestCase {
compare(group.checkedButton, button1)
compare(buttonsSpy.count, 2)
- var button3 = button.createObject(testCase, {checked: true})
+ var button3 = createTemporaryObject(button, testCase, {checked: true})
group.addButton(button3)
compare(group.buttons.length, 3)
@@ -192,19 +188,17 @@ TestCase {
compare(group.buttons.length, 0)
tryCompare(group, "checkedButton", null)
compare(buttonsSpy.count, 5)
-
- group.destroy()
}
function test_clicked() {
- var group = buttonGroup.createObject(testCase)
+ var group = createTemporaryObject(buttonGroup, testCase)
verify(group)
- var clickedSpy = signalSpy.createObject(testCase, {target: group, signalName: "clicked"})
+ var clickedSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "clicked"})
verify(clickedSpy.valid)
- var button1 = button.createObject(testCase)
- var button2 = button.createObject(testCase)
+ var button1 = createTemporaryObject(button, testCase)
+ var button2 = createTemporaryObject(button, testCase)
group.addButton(button1)
group.addButton(button2)
@@ -216,10 +210,6 @@ TestCase {
button2.clicked()
compare(clickedSpy.count, 2)
compare(clickedSpy.signalArguments[1][0], button2)
-
- group.destroy()
- button1.destroy()
- button2.destroy()
}
Component {
@@ -276,7 +266,7 @@ TestCase {
}
function test_controls(data) {
- var container = data.component.createObject(testCase)
+ var container = createTemporaryObject(data.component, testCase)
verify(container)
verify(!container.group.checkedButton)
@@ -298,18 +288,16 @@ TestCase {
compare(container.control1.checked, false)
compare(container.control2.checked, false)
compare(container.control3.checked, true)
-
- container.destroy()
}
function test_buttonDestroyed() {
- var group = buttonGroup.createObject(testCase)
+ var group = createTemporaryObject(buttonGroup, testCase)
verify(group)
- var buttonsSpy = signalSpy.createObject(testCase, {target: group, signalName: "buttonsChanged"})
+ var buttonsSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "buttonsChanged"})
verify(buttonsSpy.valid)
- var button1 = button.createObject(testCase, {objectName: "button1", checked: true})
+ var button1 = createTemporaryObject(button, testCase, {objectName: "button1", checked: true})
group.addButton(button1)
compare(group.buttons.length, 1)
@@ -322,8 +310,6 @@ TestCase {
compare(group.buttons.length, 0)
compare(group.checkedButton, null)
compare(buttonsSpy.count, 2)
-
- group.destroy()
}
Component {
@@ -344,12 +330,10 @@ TestCase {
}
function test_repeater() {
- var container = repeater.createObject(testCase)
+ var container = createTemporaryObject(repeater, testCase)
verify(container)
verify(container.group.checkedButton)
compare(container.group.checkedButton.objectName, "0")
-
- container.destroy()
}
}
diff --git a/tests/auto/controls/data/tst_checkbox.qml b/tests/auto/controls/data/tst_checkbox.qml
index b93a8a21..2ed29aec 100644
--- a/tests/auto/controls/data/tst_checkbox.qml
+++ b/tests/auto/controls/data/tst_checkbox.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.1
+import QtQuick.Controls 2.2
TestCase {
id: testCase
@@ -58,12 +58,12 @@ TestCase {
Component {
id: signalSequenceSpy
SignalSequenceSpy {
- signals: ["pressed", "released", "canceled", "clicked", "pressedChanged", "checkedChanged", "checkStateChanged"]
+ signals: ["pressed", "released", "canceled", "clicked", "toggled", "pressedChanged", "checkedChanged", "checkStateChanged"]
}
}
function test_text() {
- var control = checkBox.createObject(testCase)
+ var control = createTemporaryObject(checkBox, testCase)
verify(control)
compare(control.text, "")
@@ -71,12 +71,10 @@ TestCase {
compare(control.text, "CheckBox")
control.text = ""
compare(control.text, "")
-
- control.destroy()
}
function test_checked() {
- var control = checkBox.createObject(testCase)
+ var control = createTemporaryObject(checkBox, testCase)
verify(control)
var sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
@@ -99,12 +97,10 @@ TestCase {
compare(control.checked, false)
compare(control.checkState, Qt.Unchecked)
verify(sequenceSpy.success)
-
- control.destroy()
}
function test_checkState() {
- var control = checkBox.createObject(testCase)
+ var control = createTemporaryObject(checkBox, testCase)
verify(control)
var sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
@@ -127,12 +123,10 @@ TestCase {
compare(control.checked, false)
compare(control.checkState, Qt.Unchecked)
verify(sequenceSpy.success)
-
- control.destroy()
}
function test_mouse() {
- var control = checkBox.createObject(testCase)
+ var control = createTemporaryObject(checkBox, testCase)
verify(control)
var sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
@@ -147,6 +141,7 @@ TestCase {
sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": false, "checkState": Qt.Unchecked }],
["checkStateChanged", { "pressed": false, "checked": true, "checkState": Qt.Checked }],
["checkedChanged", { "pressed": false, "checked": true, "checkState": Qt.Checked }],
+ "toggled",
"released",
"clicked"]
mouseRelease(control, control.width / 2, control.height / 2, Qt.LeftButton)
@@ -164,6 +159,7 @@ TestCase {
sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": true, "checkState": Qt.Checked }],
["checkStateChanged", { "pressed": false, "checked": false, "checkState": Qt.Unchecked }],
["checkedChanged", { "pressed": false, "checked": false, "checkState": Qt.Unchecked }],
+ "toggled",
"released",
"clicked"]
mouseRelease(control, control.width / 2, control.height / 2, Qt.LeftButton)
@@ -198,12 +194,10 @@ TestCase {
compare(control.checkState, Qt.Unchecked)
compare(control.pressed, false)
verify(sequenceSpy.success)
-
- control.destroy()
}
function test_keys() {
- var control = checkBox.createObject(testCase)
+ var control = createTemporaryObject(checkBox, testCase)
verify(control)
var sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
@@ -219,6 +213,7 @@ TestCase {
["pressedChanged", { "pressed": false, "checked": false, "checkState": Qt.Unchecked }],
["checkStateChanged", { "pressed": false, "checked": true, "checkState": Qt.Checked }],
["checkedChanged", { "pressed": false, "checked": true, "checkState": Qt.Checked }],
+ "toggled",
"released",
"clicked"]
keyClick(Qt.Key_Space)
@@ -232,6 +227,7 @@ TestCase {
["pressedChanged", { "pressed": false, "checked": true, "checkState": Qt.Checked }],
["checkStateChanged", { "pressed": false, "checked": false, "checkState": Qt.Unchecked }],
["checkedChanged", { "pressed": false, "checked": false, "checkState": Qt.Unchecked }],
+ "toggled",
"released",
"clicked"]
keyClick(Qt.Key_Space)
@@ -248,8 +244,6 @@ TestCase {
compare(control.checked, false)
verify(sequenceSpy.success)
}
-
- control.destroy()
}
Component {
@@ -261,7 +255,7 @@ TestCase {
}
function test_checked_binding() {
- var container = checkedBoundBoxes.createObject(testCase)
+ var container = createTemporaryObject(checkedBoundBoxes, testCase)
verify(container)
compare(container.cb1.checked, false)
@@ -280,8 +274,6 @@ TestCase {
compare(container.cb1.checkState, Qt.Unchecked)
compare(container.cb2.checked, false)
compare(container.cb2.checkState, Qt.Unchecked)
-
- container.destroy()
}
Component {
@@ -293,7 +285,7 @@ TestCase {
}
function test_checkState_binding() {
- var container = checkStateBoundBoxes.createObject(testCase)
+ var container = createTemporaryObject(checkStateBoundBoxes, testCase)
verify(container)
compare(container.cb1.checked, false)
@@ -324,12 +316,10 @@ TestCase {
compare(container.cb1.tristate, true)
compare(container.cb2.tristate, true)
-
- container.destroy()
}
function test_tristate() {
- var control = checkBox.createObject(testCase)
+ var control = createTemporaryObject(checkBox, testCase)
var sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
@@ -424,14 +414,11 @@ TestCase {
compare(control.checked, true)
compare(control.checkState, Qt.PartiallyChecked)
verify(sequenceSpy.success)
-
- control.destroy()
}
function test_baseline() {
- var control = checkBox.createObject(testCase)
+ var control = createTemporaryObject(checkBox, testCase)
verify(control)
compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset)
- control.destroy()
}
}
diff --git a/tests/auto/controls/data/tst_checkdelegate.qml b/tests/auto/controls/data/tst_checkdelegate.qml
index b014f696..a838702c 100644
--- a/tests/auto/controls/data/tst_checkdelegate.qml
+++ b/tests/auto/controls/data/tst_checkdelegate.qml
@@ -58,14 +58,13 @@ TestCase {
// TODO: data-fy tst_checkbox (rename to tst_check?) so we don't duplicate its tests here?
function test_defaults() {
- var control = checkDelegate.createObject(testCase);
+ var control = createTemporaryObject(checkDelegate, testCase);
verify(control);
verify(!control.checked);
- control.destroy();
}
function test_checked() {
- var control = checkDelegate.createObject(testCase);
+ var control = createTemporaryObject(checkDelegate, testCase);
verify(control);
mouseClick(control);
@@ -73,14 +72,11 @@ TestCase {
mouseClick(control);
verify(!control.checked);
-
- control.destroy();
}
function test_baseline() {
- var control = checkDelegate.createObject(testCase);
+ var control = createTemporaryObject(checkDelegate, testCase);
verify(control);
compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset);
- control.destroy();
}
}
diff --git a/tests/auto/controls/data/tst_combobox.qml b/tests/auto/controls/data/tst_combobox.qml
index 0cd2e258..4bcbd8b4 100644
--- a/tests/auto/controls/data/tst_combobox.qml
+++ b/tests/auto/controls/data/tst_combobox.qml
@@ -65,7 +65,7 @@ TestCase {
id: emptyBox
ComboBox {
delegate: ItemDelegate {
- width: popup.width
+ width: parent.width
}
}
}
@@ -713,6 +713,74 @@ TestCase {
control.destroy()
}
+ function test_down() {
+ var control = comboBox.createObject(testCase, {model: 3})
+ verify(control)
+
+ // some styles position the popup over the combo button. move it out
+ // of the way to avoid stealing mouse presses. we want to test the
+ // combinations of the button being pressed and the popup being visible.
+ control.popup.y = control.height
+
+ var downSpy = signalSpy.createObject(control, {target: control, signalName: "downChanged"})
+ verify(downSpy.valid)
+
+ var pressedSpy = signalSpy.createObject(control, {target: control, signalName: "pressedChanged"})
+ verify(pressedSpy.valid)
+
+ mousePress(control)
+ compare(control.popup.visible, false)
+ compare(control.pressed, true)
+ compare(control.down, true)
+ compare(downSpy.count, 1)
+ compare(pressedSpy.count, 1)
+
+ mouseRelease(control)
+ compare(control.popup.visible, true)
+ compare(control.pressed, false)
+ compare(control.down, true)
+ compare(downSpy.count, 3)
+ compare(pressedSpy.count, 2)
+
+ control.down = false
+ compare(control.down, false)
+ compare(downSpy.count, 4)
+
+ mousePress(control)
+ compare(control.popup.visible, true)
+ compare(control.pressed, true)
+ compare(control.down, false) // explicit false
+ compare(downSpy.count, 4)
+ compare(pressedSpy.count, 3)
+
+ control.down = undefined
+ compare(control.down, true)
+ compare(downSpy.count, 5)
+
+ mouseRelease(control)
+ tryCompare(control.popup, "visible", false)
+ compare(control.pressed, false)
+ compare(control.down, false)
+ compare(downSpy.count, 6)
+ compare(pressedSpy.count, 4)
+
+ control.popup.open()
+ compare(control.popup.visible, true)
+ compare(control.pressed, false)
+ compare(control.down, true)
+ compare(downSpy.count, 7)
+ compare(pressedSpy.count, 4)
+
+ control.popup.close()
+ tryCompare(control.popup, "visible", false)
+ compare(control.pressed, false)
+ compare(control.down, false)
+ compare(downSpy.count, 8)
+ compare(pressedSpy.count, 4)
+
+ control.destroy()
+ }
+
function test_focus() {
var control = comboBox.createObject(testCase, {model: 3})
verify(control)
@@ -1045,4 +1113,302 @@ TestCase {
closedSpy.target = null
control.destroy()
}
+
+ RegExpValidator {
+ id: regExpValidator
+ regExp: /(red|blue|green)?/
+ }
+
+ function test_validator() {
+ var control = comboBox.createObject(testCase, {editable: true, validator: regExpValidator})
+
+ control.editText = "blu"
+ compare(control.acceptableInput, false)
+ control.editText = "blue"
+ compare(control.acceptableInput, true)
+ control.editText = "bluee"
+ compare(control.acceptableInput, false)
+ control.editText = ""
+ compare(control.acceptableInput, true)
+ control.editText = ""
+ control.forceActiveFocus()
+ keyPress(Qt.Key_A)
+ compare(control.editText, "")
+ keyPress(Qt.Key_A)
+ compare(control.editText, "")
+ keyPress(Qt.Key_R)
+ compare(control.editText, "r")
+ keyPress(Qt.Key_A)
+ compare(control.editText, "r")
+ compare(control.acceptableInput, false)
+ keyPress(Qt.Key_E)
+ compare(control.editText, "re")
+ compare(control.acceptableInput, false)
+ keyPress(Qt.Key_D)
+ compare(control.editText, "red")
+ compare(control.acceptableInput, true)
+
+ control.destroy()
+ }
+
+ Component {
+ id: appendFindBox
+ ComboBox {
+ editable: true
+ model: ListModel {
+ ListElement { text:"first" }
+ }
+ onAccepted: {
+ if (find(editText) === -1)
+ model.append({text: editText})
+ }
+ }
+ }
+
+ function test_append_find() {
+ var control = appendFindBox.createObject(testCase)
+
+ compare(control.currentIndex, 0)
+ compare(control.currentText, "first")
+ control.forceActiveFocus()
+ compare(control.activeFocus, true)
+
+ control.selectAll()
+ keyPress(Qt.Key_T)
+ keyPress(Qt.Key_H)
+ keyPress(Qt.Key_I)
+ keyPress(Qt.Key_R)
+ keyPress(Qt.Key_D)
+ compare(control.count, 1)
+ compare(control.currentText, "first")
+ compare(control.editText, "third")
+
+ keyPress(Qt.Key_Enter)
+ compare(control.count, 2)
+ compare(control.currentIndex, 1)
+ compare(control.currentText, "third")
+
+ control.destroy()
+ }
+
+ function test_editable() {
+ var control = comboBox.createObject(testCase, {editable: true, model: ["Banana", "Coco", "Coconut", "Apple", "Cocomuffin"]})
+ verify(control)
+
+ control.forceActiveFocus()
+ verify(control.activeFocus)
+
+ var acceptCount = 0
+
+ var acceptSpy = signalSpy.createObject(control, {target: control, signalName: "accepted"})
+ verify(acceptSpy.valid)
+
+ compare(control.editText, "Banana")
+ compare(control.currentText, "Banana")
+ compare(control.currentIndex, 0)
+ compare(acceptSpy.count, 0)
+ control.editText = ""
+
+ keyPress(Qt.Key_C)
+ compare(control.editText, "coco")
+ compare(control.currentText, "Banana")
+ compare(control.currentIndex, 0)
+
+ keyPress(Qt.Key_Right)
+ keyPress(Qt.Key_N)
+ compare(control.editText, "coconut")
+ compare(control.currentText, "Banana")
+ compare(control.currentIndex, 0)
+
+ keyPress(Qt.Key_Enter) // Accept
+ compare(control.editText, "Coconut")
+ compare(control.currentText, "Coconut")
+ compare(control.currentIndex, 2)
+ compare(acceptSpy.count, ++acceptCount)
+
+ keyPress(Qt.Key_Backspace)
+ keyPress(Qt.Key_Backspace)
+ keyPress(Qt.Key_Backspace)
+ keyPress(Qt.Key_M)
+ compare(control.editText, "Cocomuffin")
+ compare(control.currentText, "Coconut")
+ compare(control.currentIndex, 2)
+
+ keyPress(Qt.Key_Enter) // Accept
+ compare(control.editText, "Cocomuffin")
+ compare(control.currentText, "Cocomuffin")
+ compare(control.currentIndex, 4)
+ compare(acceptSpy.count, ++acceptCount)
+
+ keyPress(Qt.Key_Return) // Accept
+ compare(control.editText, "Cocomuffin")
+ compare(control.currentText, "Cocomuffin")
+ compare(control.currentIndex, 4)
+ compare(acceptSpy.count, ++acceptCount)
+
+ control.editText = ""
+ compare(control.editText, "")
+ compare(control.currentText, "Cocomuffin")
+ compare(control.currentIndex, 4)
+
+ keyPress(Qt.Key_A)
+ compare(control.editText, "apple")
+ compare(control.currentText, "Cocomuffin")
+ compare(control.currentIndex, 4)
+
+ keyPress(Qt.Key_Return) // Accept
+ compare(control.editText, "Apple")
+ compare(control.currentText, "Apple")
+ compare(control.currentIndex, 3)
+ compare(acceptSpy.count, ++acceptCount)
+
+ control.editText = ""
+ keyPress(Qt.Key_A)
+ keyPress(Qt.Key_B)
+ compare(control.editText, "ab")
+ compare(control.currentText, "Apple")
+ compare(control.currentIndex, 3)
+
+ keyPress(Qt.Key_Return) // Accept
+ compare(control.editText, "ab")
+ compare(control.currentText, "")
+ compare(control.currentIndex, -1)
+ compare(acceptSpy.count, ++acceptCount)
+
+ control.editText = ""
+ compare(control.editText, "")
+ compare(control.currentText, "")
+ compare(control.currentIndex, -1)
+
+ keyPress(Qt.Key_C)
+ keyPress(Qt.Key_Return) // Accept
+ compare(control.editText, "Coco")
+ compare(control.currentText, "Coco")
+ compare(control.currentIndex, 1)
+ compare(acceptSpy.count, ++acceptCount)
+
+ keyPress(Qt.Key_Down)
+ compare(control.editText, "Coconut")
+ compare(control.currentText, "Coconut")
+ compare(control.currentIndex, 2)
+
+ keyPress(Qt.Key_Up)
+ compare(control.editText, "Coco")
+ compare(control.currentText, "Coco")
+ compare(control.currentIndex, 1)
+
+ control.editText = ""
+ compare(control.editText, "")
+ compare(control.currentText, "Coco")
+ compare(control.currentIndex, 1)
+
+ keyPress(Qt.Key_C)
+ keyPress(Qt.Key_O)
+ keyPress(Qt.Key_C) // autocompletes "coco"
+ keyPress(Qt.Key_Backspace)
+ keyPress(Qt.Key_Return) // Accept "coc"
+ compare(control.editText, "coc")
+ compare(control.currentText, "")
+ compare(control.currentIndex, -1)
+ compare(acceptSpy.count, ++acceptCount)
+
+ control.editText = ""
+ compare(control.editText, "")
+ compare(control.currentText, "")
+ compare(control.currentIndex, -1)
+
+ keyPress(Qt.Key_C)
+ keyPress(Qt.Key_O)
+ keyPress(Qt.Key_C) // autocompletes "coc"
+ keyPress(Qt.Key_Space)
+ keyPress(Qt.Key_Return) // Accept "coc "
+ compare(control.editText, "coc ")
+ compare(control.currentText, "")
+ compare(control.currentIndex, -1)
+ compare(acceptSpy.count, ++acceptCount)
+
+ control.destroy()
+ }
+
+ Component {
+ id: keysAttachedBox
+ ComboBox {
+ editable: true
+ property bool gotit: false
+ Keys.onPressed: {
+ if (!gotit && event.key === Qt.Key_B) {
+ gotit = true
+ event.accepted = true
+ }
+ }
+ }
+ }
+
+ function test_keys_attached() {
+ var control = keysAttachedBox.createObject(testCase)
+ verify(control)
+
+ control.forceActiveFocus()
+ verify(control.activeFocus)
+
+ verify(!control.gotit)
+ compare(control.editText, "")
+
+ keyPress(Qt.Key_A)
+ verify(control.activeFocus)
+ verify(!control.gotit)
+ compare(control.editText, "a")
+
+ keyPress(Qt.Key_B)
+ verify(control.activeFocus)
+ expectFail("", "An editable ComboBox does not yet support the Keys attached property.")
+ verify(control.gotit)
+ compare(control.editText, "a")
+
+ keyPress(Qt.Key_B)
+ verify(control.activeFocus)
+ verify(control.gotit)
+ compare(control.editText, "ab")
+
+ control.destroy()
+ }
+
+ function test_minusOneIndexResetsSelection_QTBUG_35794_data() {
+ return [
+ { tag: "editable", editable: true },
+ { tag: "non-editable", editable: false }
+ ]
+ }
+
+ function test_minusOneIndexResetsSelection_QTBUG_35794(data) {
+ var control = comboBox.createObject(testCase, {editable: data.editable, model: ["A", "B", "C"]})
+ verify(control)
+
+ compare(control.currentIndex, 0)
+ compare(control.currentText, "A")
+ control.currentIndex = -1
+ compare(control.currentIndex, -1)
+ compare(control.currentText, "")
+ control.currentIndex = 1
+ compare(control.currentIndex, 1)
+ compare(control.currentText, "B")
+
+ control.destroy()
+ }
+
+ function test_minusOneToZeroSelection_QTBUG_38036() {
+ var control = comboBox.createObject(testCase, {model: ["A", "B", "C"]})
+ verify(control)
+
+ compare(control.currentIndex, 0)
+ compare(control.currentText, "A")
+ control.currentIndex = -1
+ compare(control.currentIndex, -1)
+ compare(control.currentText, "")
+ control.currentIndex = 0
+ compare(control.currentIndex, 0)
+ compare(control.currentText, "A")
+
+ control.destroy()
+ }
}
diff --git a/tests/auto/controls/data/tst_container.qml b/tests/auto/controls/data/tst_container.qml
index bf6ec283..da77def2 100644
--- a/tests/auto/controls/data/tst_container.qml
+++ b/tests/auto/controls/data/tst_container.qml
@@ -62,7 +62,7 @@ TestCase {
}
function test_implicitSize() {
- var control = container.createObject(testCase)
+ var control = createTemporaryObject(container, testCase)
verify(control)
compare(control.implicitWidth, 0)
@@ -79,7 +79,5 @@ TestCase {
control.padding = 100
compare(control.implicitWidth, 210)
compare(control.implicitHeight, 220)
-
- control.destroy()
}
}
diff --git a/tests/auto/controls/data/tst_control.qml b/tests/auto/controls/data/tst_control.qml
index 9e41af7e..33802817 100644
--- a/tests/auto/controls/data/tst_control.qml
+++ b/tests/auto/controls/data/tst_control.qml
@@ -72,7 +72,7 @@ TestCase {
}
function test_padding() {
- var control = component.createObject(testCase)
+ var control = createTemporaryObject(component, testCase)
verify(control)
compare(control.padding, 0)
@@ -127,12 +127,10 @@ TestCase {
compare(control.leftPadding, 30)
compare(control.rightPadding, 40)
compare(control.bottomPadding, 50)
-
- control.destroy()
}
function test_availableSize() {
- var control = component.createObject(testCase)
+ var control = createTemporaryObject(component, testCase)
verify(control)
var availableWidthSpy = signalSpy.createObject(control, {target: control, signalName: "availableWidthChanged"})
@@ -199,12 +197,10 @@ TestCase {
compare(control.availableHeight, 0)
compare(availableWidthSpy.count, availableWidthChanges)
compare(availableHeightSpy.count, ++availableHeightChanges)
-
- control.destroy()
}
function test_mirrored() {
- var control = component.createObject(testCase)
+ var control = createTemporaryObject(component, testCase)
verify(control)
var mirroredSpy = signalSpy.createObject(control, {target: control, signalName: "mirroredChanged"})
@@ -230,12 +226,10 @@ TestCase {
control.LayoutMirroring.enabled = false
compare(control.mirrored, false)
compare(mirroredSpy.count, 2)
-
- control.destroy()
}
function test_background() {
- var control = component.createObject(testCase)
+ var control = createTemporaryObject(component, testCase)
verify(control)
control.background = component.createObject(control)
@@ -277,8 +271,6 @@ TestCase {
control.background.y = 10
control.height -= 20
verify(control.background.height !== control.height)
-
- control.destroy()
}
Component {
@@ -319,7 +311,7 @@ TestCase {
}
function test_font() {
- var control2 = component2.createObject(testCase)
+ var control2 = createTemporaryObject(component2, testCase)
verify(control2)
verify(control2.item2_2)
verify(control2.item2_3)
@@ -412,8 +404,6 @@ TestCase {
compare(control2.item2_6.font.family, "Arial")
compare(control2.item2_6.font.pointSize, 36)
compare(control2.item2_6.font.weight, Font.Black)
-
- control2.destroy()
}
Component {
@@ -464,7 +454,7 @@ TestCase {
}
function test_font_2() {
- var control3 = component3.createObject(testCase)
+ var control3 = createTemporaryObject(component3, testCase)
verify(control3)
verify(control3.item3_2)
verify(control3.item3_3)
@@ -551,8 +541,6 @@ TestCase {
compare(control3.item3_8.font.family, "Arial")
compare(control3.item3_8.font.pointSize, 36)
compare(control3.item3_8.font.weight, Font.Black)
-
- control3.destroy()
}
Component {
@@ -581,7 +569,7 @@ TestCase {
}
function test_font_3() {
- var control4 = component4.createObject(testCase)
+ var control4 = createTemporaryObject(component4, testCase)
verify(control4)
verify(control4.item4_2)
verify(control4.item4_3)
@@ -602,8 +590,6 @@ TestCase {
compare(control4.item4_2.font.pixelSize, control4.font.pixelSize + 15)
compare(control4.item4_3.font.pixelSize, control4.font.pixelSize - 1)
compare(control4.item4_4.font.pixelSize, control4.font.pixelSize + 15)
-
- control4.destroy()
}
function test_font_explicit_attributes_data() {
@@ -620,7 +606,7 @@ TestCase {
}
function test_font_explicit_attributes(data) {
- var control = component.createObject(testCase)
+ var control = createTemporaryObject(component, testCase)
verify(control)
var child = component.createObject(control)
@@ -645,12 +631,10 @@ TestCase {
compare(child.font[data.tag], defaultValue)
compare(childSpy.count, 0)
-
- control.destroy()
}
function test_locale() {
- var control = component.createObject(testCase)
+ var control = createTemporaryObject(component, testCase)
verify(control)
control.locale = Qt.locale("en_US")
@@ -658,8 +642,6 @@ TestCase {
control.locale = Qt.locale("nb_NO")
compare(control.locale.name, "nb_NO")
-
- control.destroy()
}
Component {
@@ -723,7 +705,7 @@ TestCase {
}
function test_locale_2() {
- var control = component5.createObject(testCase)
+ var control = createTemporaryObject(component5, testCase)
verify(control)
verify(control.item2_2)
verify(control.item2_3)
@@ -816,7 +798,7 @@ TestCase {
}
function test_locale_3() {
- var control = component6.createObject(testCase)
+ var control = createTemporaryObject(component6, testCase)
verify(control)
verify(control.item6_2)
verify(control.item6_3)
@@ -855,7 +837,7 @@ TestCase {
}
function test_hover(data) {
- var control = data.target.createObject(testCase, {width: 100, height: 100})
+ var control = createTemporaryObject(data.target, testCase, {width: 100, height: 100})
verify(control)
compare(control.hovered, false)
@@ -889,12 +871,10 @@ TestCase {
control.visible = false
compare(control.hovered, false)
-
- control.destroy()
}
function test_hoverEnabled() {
- var control = component.createObject(testCase)
+ var control = createTemporaryObject(component, testCase)
compare(control.hoverEnabled, Qt.styleHints.useHoverEffects)
var child = component.createObject(control)
@@ -925,12 +905,10 @@ TestCase {
compare(childExplicitHoverDisabled.hoverEnabled, false)
compare(grandChildExplicitHoverEnabled.hoverEnabled, true)
-
- control.destroy()
}
function test_implicitSize() {
- var control = component.createObject(testCase)
+ var control = createTemporaryObject(component, testCase)
verify(control)
compare(control.implicitWidth, 0)
@@ -947,7 +925,5 @@ TestCase {
control.padding = 100
compare(control.implicitWidth, 210)
compare(control.implicitHeight, 220)
-
- control.destroy()
}
}
diff --git a/tests/auto/controls/data/tst_delaybutton.qml b/tests/auto/controls/data/tst_delaybutton.qml
new file mode 100644
index 00000000..d5c9bd0c
--- /dev/null
+++ b/tests/auto/controls/data/tst_delaybutton.qml
@@ -0,0 +1,248 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite 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 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.2
+import QtTest 1.0
+import QtQuick.Controls 2.2
+
+TestCase {
+ id: testCase
+ width: 200
+ height: 200
+ visible: true
+ when: windowShown
+ name: "DelayButton"
+
+ Component {
+ id: delayButton
+ DelayButton {
+ delay: 200
+ }
+ }
+
+ Component {
+ id: signalSequenceSpy
+ SignalSequenceSpy {
+ signals: ["pressed", "released", "canceled", "clicked", "toggled", "doubleClicked", "pressedChanged", "downChanged", "checkedChanged", "activated"]
+ }
+ }
+
+ Component {
+ id: signalSpy
+ SignalSpy { }
+ }
+
+ function test_mouse() {
+ var control = createTemporaryObject(delayButton, testCase)
+ verify(control)
+
+ var sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
+
+ // click
+ sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true }],
+ ["downChanged", { "down": true }],
+ "pressed",
+ ["pressedChanged", { "pressed": false }],
+ ["downChanged", { "down": false }],
+ "released",
+ "clicked"]
+ mouseClick(control)
+ verify(sequenceSpy.success)
+
+ // check
+ sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true }],
+ ["downChanged", { "down": true }],
+ "pressed",
+ "activated"]
+ mousePress(control, control.width / 2, control.height / 2, Qt.LeftButton)
+ compare(control.pressed, true)
+ tryVerify(function() { return sequenceSpy.success})
+
+ sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": false }],
+ ["downChanged", { "down": false }],
+ ["checkedChanged", { "checked": true }],
+ "released",
+ "clicked"]
+ mouseRelease(control, control.width / 2, control.height / 2, Qt.LeftButton)
+ compare(control.pressed, false)
+ verify(sequenceSpy.success)
+
+ // uncheck
+ sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true }],
+ ["downChanged", { "down": true }],
+ "pressed"]
+ mousePress(control, control.width / 2, control.height / 2, Qt.LeftButton)
+ compare(control.pressed, true)
+ verify(sequenceSpy.success)
+
+ sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": false }],
+ ["downChanged", { "down": false }],
+ ["checkedChanged", { "checked": false }],
+ "released",
+ "clicked"]
+ mouseRelease(control, control.width / 2, control.height / 2, Qt.LeftButton)
+ compare(control.pressed, false)
+ verify(sequenceSpy.success)
+
+ // release outside
+ sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true }],
+ ["downChanged", { "down": true }],
+ "pressed"]
+ mousePress(control, control.width / 2, control.height / 2, Qt.LeftButton)
+ compare(control.pressed, true)
+ verify(sequenceSpy.success)
+
+ sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": false }],
+ ["downChanged", { "down": false }]]
+ mouseMove(control, control.width * 2, control.height * 2, 0, Qt.LeftButton)
+ compare(control.pressed, false)
+ verify(sequenceSpy.success)
+
+ sequenceSpy.expectedSequence = [["canceled", { "pressed": false }]]
+ mouseRelease(control, control.width * 2, control.height * 2, Qt.LeftButton)
+ compare(control.pressed, false)
+ verify(sequenceSpy.success)
+
+ // right button
+ sequenceSpy.expectedSequence = []
+ mousePress(control, control.width / 2, control.height / 2, Qt.RightButton)
+ compare(control.pressed, false)
+
+ mouseRelease(control, control.width / 2, control.height / 2, Qt.RightButton)
+ compare(control.pressed, false)
+ verify(sequenceSpy.success)
+
+ // double click
+ sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true }],
+ ["downChanged", { "down": true }],
+ "pressed",
+ ["pressedChanged", { "pressed": false }],
+ ["downChanged", { "down": false }],
+ "released",
+ "clicked",
+ ["pressedChanged", { "pressed": true }],
+ ["downChanged", { "down": true }],
+ "pressed",
+ "doubleClicked",
+ ["pressedChanged", { "pressed": false }],
+ ["downChanged", { "down": false }],
+ "released",
+ "clicked"]
+ mouseDoubleClickSequence(control, control.width / 2, control.height / 2, Qt.LeftButton)
+ verify(sequenceSpy.success)
+ }
+
+ function test_keys() {
+ var control = createTemporaryObject(delayButton, testCase)
+ verify(control)
+
+ control.forceActiveFocus()
+ verify(control.activeFocus)
+
+ var sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
+
+ // click
+ sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true }],
+ ["downChanged", { "down": true }],
+ "pressed",
+ ["pressedChanged", { "pressed": false }],
+ ["downChanged", { "down": false }],
+ "released",
+ "clicked"]
+ keyClick(Qt.Key_Space)
+ verify(sequenceSpy.success)
+
+ // check
+ sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true }],
+ ["downChanged", { "down": true }],
+ "pressed",
+ "activated"]
+ keyPress(Qt.Key_Space)
+ tryVerify(function() { return sequenceSpy.success})
+
+ sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": false }],
+ ["downChanged", { "down": false }],
+ ["checkedChanged", { "checked": true }],
+ "released",
+ "clicked"]
+ keyRelease(Qt.Key_Space)
+ verify(sequenceSpy.success)
+
+ // uncheck
+ sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true }],
+ ["downChanged", { "down": true }],
+ "pressed",
+ ["pressedChanged", { "pressed": false }],
+ ["downChanged", { "down": false }],
+ ["checkedChanged", { "checked": false }],
+ "released",
+ "clicked"]
+ keyClick(Qt.Key_Space)
+ verify(sequenceSpy.success)
+
+ // no change
+ sequenceSpy.expectedSequence = []
+ var keys = [Qt.Key_Enter, Qt.Key_Return, Qt.Key_Escape, Qt.Key_Tab]
+ for (var i = 0; i < keys.length; ++i) {
+ sequenceSpy.reset()
+ keyClick(keys[i])
+ verify(sequenceSpy.success)
+ }
+ }
+
+ function test_progress() {
+ var control = createTemporaryObject(delayButton, testCase)
+ verify(control)
+
+ var progressSpy = signalSpy.createObject(control, {target: control, signalName: "progressChanged"})
+ verify(progressSpy.valid)
+
+ compare(control.progress, 0.0)
+ mousePress(control)
+ tryCompare(control, "progress", 1.0)
+ verify(progressSpy.count > 0)
+ }
+
+ function test_baseline() {
+ var control = createTemporaryObject(delayButton, testCase)
+ verify(control)
+ compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset)
+ }
+}
diff --git a/tests/auto/controls/data/tst_dial.qml b/tests/auto/controls/data/tst_dial.qml
index 7998d4fc..f6b6a720 100644
--- a/tests/auto/controls/data/tst_dial.qml
+++ b/tests/auto/controls/data/tst_dial.qml
@@ -55,19 +55,14 @@ TestCase {
Dial {}
}
- property var dial: null
-
- function init() {
- dial = dialComponent.createObject(testCase);
- verify(dial, "Dial: failed to create an instance");
- }
-
- function cleanup() {
- if (dial)
- dial.destroy();
+ Component {
+ id: signalSpy
+ SignalSpy {}
}
function test_instance() {
+ var dial = createTemporaryObject(dialComponent, testCase);
+ verify(dial);
compare(dial.value, 0.0);
compare(dial.from, 0.0);
compare(dial.to, 1.0);
@@ -77,6 +72,8 @@ TestCase {
}
function test_value() {
+ var dial = createTemporaryObject(dialComponent, testCase);
+ verify(dial);
compare(dial.value, 0.0);
dial.value = 0.5;
@@ -93,6 +90,9 @@ TestCase {
}
function test_range() {
+ var dial = createTemporaryObject(dialComponent, testCase);
+ verify(dial);
+
dial.from = 0;
dial.to = 100;
dial.value = 50;
@@ -125,9 +125,8 @@ TestCase {
}
function test_inverted() {
- dial.destroy();
- dial = dialComponent.createObject(testCase, { from: 1.0, to: -1.0 });
- verify(dial, "Dial: failed to create an instance");
+ var dial = createTemporaryObject(dialComponent, testCase, { from: 1.0, to: -1.0 });
+ verify(dial);
compare(dial.from, 1.0);
compare(dial.to, -1.0);
compare(dial.value, 0.0);
@@ -152,6 +151,9 @@ TestCase {
}
function test_pressed() {
+ var dial = createTemporaryObject(dialComponent, testCase);
+ verify(dial);
+
pressSpy.target = dial;
verify(pressSpy.valid);
verify(!dial.pressed);
@@ -163,6 +165,15 @@ TestCase {
mouseRelease(dial, dial.width / 2, dial.height / 2);
verify(!dial.pressed);
compare(pressSpy.count, 2);
+
+ var touch = touchEvent(dial);
+ touch.press(0).commit();
+ verify(dial.pressed);
+ compare(pressSpy.count, 3);
+
+ touch.release(0).commit();
+ verify(!dial.pressed);
+ compare(pressSpy.count, 4);
}
SignalSpy {
@@ -172,47 +183,68 @@ TestCase {
function test_dragging_data() {
return [
- { tag: "default", from: 0, to: 1, leftValue: 0.20, topValue: 0.5, rightValue: 0.8, bottomValue: 1.0 },
- { tag: "scaled2", from: 0, to: 2, leftValue: 0.4, topValue: 1.0, rightValue: 1.6, bottomValue: 2.0 },
- { tag: "scaled1", from: -1, to: 0, leftValue: -0.8, topValue: -0.5, rightValue: -0.2, bottomValue: 0.0 }
+ { tag: "default", from: 0, to: 1, leftValue: 0.20, topValue: 0.5, rightValue: 0.8, bottomValue: 1.0, live: false },
+ { tag: "scaled2", from: 0, to: 2, leftValue: 0.4, topValue: 1.0, rightValue: 1.6, bottomValue: 2.0, live: false },
+ { tag: "scaled1", from: -1, to: 0, leftValue: -0.8, topValue: -0.5, rightValue: -0.2, bottomValue: 0.0, live: false },
+ { tag: "live", from: 0, to: 1, leftValue: 0.20, topValue: 0.5, rightValue: 0.8, bottomValue: 1.0, live: true }
]
}
function test_dragging(data) {
+ var dial = createTemporaryObject(dialComponent, testCase);
+ verify(dial);
+
dial.wrap = true;
verify(dial.wrap);
dial.from = data.from;
dial.to = data.to;
+ dial.live = data.live;
valueSpy.target = dial;
verify(valueSpy.valid);
+ var moveSpy = createTemporaryObject(signalSpy, testCase, {target: dial, signalName: "moved"});
+ verify(moveSpy.valid);
+
+ var minimumExpectedValueCount = data.live ? 2 : 1;
+
// drag to the left
mouseDrag(dial, dial.width / 2, dial.height / 2, -dial.width / 2, 0, Qt.LeftButton);
fuzzyCompare(dial.value, data.leftValue, 0.1);
- verify(valueSpy.count > 0);
+ verify(valueSpy.count >= minimumExpectedValueCount);
valueSpy.clear();
+ verify(moveSpy.count > 0);
+ moveSpy.clear();
// drag to the top
mouseDrag(dial, dial.width / 2, dial.height / 2, 0, -dial.height / 2, Qt.LeftButton);
fuzzyCompare(dial.value, data.topValue, 0.1);
- verify(valueSpy.count > 0);
+ verify(valueSpy.count >= minimumExpectedValueCount);
valueSpy.clear();
+ verify(moveSpy.count > 0);
+ moveSpy.clear();
// drag to the right
mouseDrag(dial, dial.width / 2, dial.height / 2, dial.width / 2, 0, Qt.LeftButton);
fuzzyCompare(dial.value, data.rightValue, 0.1);
- verify(valueSpy.count > 0);
+ verify(valueSpy.count >= minimumExpectedValueCount);
valueSpy.clear();
+ verify(moveSpy.count > 0);
+ moveSpy.clear();
// drag to the bottom (* 0.6 to ensure we don't go over to the minimum position)
mouseDrag(dial, dial.width / 2, dial.height / 2, 10, dial.height / 2, Qt.LeftButton);
fuzzyCompare(dial.value, data.bottomValue, 0.1);
- verify(valueSpy.count > 0);
+ verify(valueSpy.count >= minimumExpectedValueCount);
valueSpy.clear();
+ verify(moveSpy.count > 0);
+ moveSpy.clear();
}
function test_nonWrapping() {
+ var dial = createTemporaryObject(dialComponent, testCase);
+ verify(dial);
+
compare(dial.wrap, false);
dial.value = 0;
@@ -249,6 +281,90 @@ TestCase {
verify(dial.position > positionAtPress);
}
+ function test_touch() {
+ var dial = createTemporaryObject(dialComponent, testCase);
+ verify(dial);
+
+ var touch = touchEvent(dial);
+
+ // Ensure that dragging from bottom left to bottom right doesn't work.
+ var yPos = dial.height * 0.75;
+ touch.press(0, dial, dial.width * 0.25, yPos).commit();
+ var positionAtPress = dial.position;
+ touch.move(0, dial, dial.width * 0.5, yPos).commit();
+ compare(dial.position, positionAtPress);
+ touch.move(0, dial, dial.width * 0.75, yPos).commit();
+ compare(dial.position, positionAtPress);
+ touch.release(0, dial, dial.width * 0.75, yPos).commit();
+ compare(dial.position, positionAtPress);
+
+ // Try the same thing, but a bit higher.
+ yPos = dial.height * 0.6;
+ touch.press(0, dial, dial.width * 0.25, yPos).commit();
+ positionAtPress = dial.position;
+ touch.move(0, dial, dial.width * 0.5, yPos).commit();
+ compare(dial.position, positionAtPress);
+ touch.move(0, dial, dial.width * 0.75, yPos).commit();
+ compare(dial.position, positionAtPress);
+ touch.release(0, dial, dial.width * 0.75, yPos).commit();
+ compare(dial.position, positionAtPress);
+
+ // Going from below the center of the dial to above it should work (once it gets above the center).
+ touch.press(0, dial, dial.width * 0.25, dial.height * 0.75).commit();
+ positionAtPress = dial.position;
+ touch.move(0, dial, dial.width * 0.5, dial.height * 0.6).commit();
+ compare(dial.position, positionAtPress);
+ touch.move(0, dial, dial.width * 0.75, dial.height * 0.4).commit();
+ verify(dial.position > positionAtPress);
+ touch.release(0, dial, dial.width * 0.75, dial.height * 0.3).commit();
+ verify(dial.position > positionAtPress);
+ }
+
+ function test_multiTouch() {
+ var dial1 = createTemporaryObject(dialComponent, testCase);
+ verify(dial1);
+
+ var touch = touchEvent(dial1);
+ touch.press(0, dial1).commit().move(0, dial1, dial1.width / 4, dial1.height / 4).commit();
+ compare(dial1.pressed, true);
+ verify(dial1.position > 0.0);
+
+ var pos1Before = dial1.position;
+
+ // second touch point on the same control is ignored
+ touch.stationary(0).press(1, dial1, 0, 0).commit()
+ touch.stationary(0).move(1, dial1).commit()
+ touch.stationary(0).release(1).commit()
+ compare(dial1.pressed, true);
+ compare(dial1.position, pos1Before);
+
+ var dial2 = createTemporaryObject(dialComponent, testCase, {y: dial1.height});
+ verify(dial2);
+ waitForRendering(dial2);
+
+ // press the second dial
+ touch.stationary(0).press(2, dial2, 0, 0).commit();
+ compare(dial2.pressed, true);
+ compare(dial2.position, 0.0);
+
+ pos1Before = dial1.position;
+ var pos2Before = dial2.position;
+
+ // move both dials
+ touch.move(0, dial1).move(2, dial2, dial2.width / 4, dial2.height / 4).commit();
+ compare(dial1.pressed, true);
+ verify(dial1.position !== pos1Before);
+ compare(dial2.pressed, true);
+ verify(dial2.position !== pos2Before);
+
+ // release both dials
+ touch.release(0, dial1).release(2, dial2).commit();
+ compare(dial1.pressed, false);
+ compare(dial1.value, dial1.position);
+ compare(dial2.pressed, false);
+ compare(dial2.value, dial2.position);
+ }
+
property Component focusTest: Component {
FocusScope {
signal receivedKeyPress
@@ -264,13 +380,21 @@ TestCase {
}
function test_keyboardNavigation() {
- var focusScope = focusTest.createObject(testCase);
+ var dial = createTemporaryObject(dialComponent, testCase);
+ verify(dial);
+
+ var focusScope = createTemporaryObject(focusTest, testCase);
verify(focusScope);
+ var moveCount = 0;
+
// Tests that we've accepted events that we're interested in.
parentEventSpy.target = focusScope;
parentEventSpy.signalName = "receivedKeyPress";
+ var moveSpy = createTemporaryObject(signalSpy, testCase, {target: dial, signalName: "moved"});
+ verify(moveSpy.valid);
+
dial.parent = focusScope;
compare(dial.activeFocusOnTab, true);
compare(dial.value, 0);
@@ -281,45 +405,54 @@ TestCase {
keyClick(Qt.Key_Left);
compare(parentEventSpy.count, 0);
+ compare(moveSpy.count, moveCount);
compare(dial.value, 0);
-
+ var oldValue = 0.0;
var keyPairs = [[Qt.Key_Left, Qt.Key_Right], [Qt.Key_Down, Qt.Key_Up]];
for (var keyPairIndex = 0; keyPairIndex < 2; ++keyPairIndex) {
for (var i = 1; i <= 10; ++i) {
+ oldValue = dial.value;
keyClick(keyPairs[keyPairIndex][1]);
compare(parentEventSpy.count, 0);
+ if (oldValue !== dial.value)
+ compare(moveSpy.count, ++moveCount);
compare(dial.value, dial.stepSize * i);
}
compare(dial.value, dial.to);
for (i = 10; i > 0; --i) {
+ oldValue = dial.value;
keyClick(keyPairs[keyPairIndex][0]);
compare(parentEventSpy.count, 0);
+ if (oldValue !== dial.value)
+ compare(moveSpy.count, ++moveCount);
compare(dial.value, dial.stepSize * (i - 1));
}
}
+ dial.value = 0.5;
+
+ keyClick(Qt.Key_Home);
+ compare(parentEventSpy.count, 0);
+ compare(moveSpy.count, ++moveCount);
compare(dial.value, dial.from);
keyClick(Qt.Key_Home);
compare(parentEventSpy.count, 0);
+ compare(moveSpy.count, moveCount);
compare(dial.value, dial.from);
keyClick(Qt.Key_End);
compare(parentEventSpy.count, 0);
+ compare(moveSpy.count, ++moveCount);
compare(dial.value, dial.to);
keyClick(Qt.Key_End);
compare(parentEventSpy.count, 0);
+ compare(moveSpy.count, moveCount);
compare(dial.value, dial.to);
-
- keyClick(Qt.Key_Home);
- compare(parentEventSpy.count, 0);
- compare(dial.value, dial.from);
-
- focusScope.destroy();
}
function test_snapMode_data() {
@@ -336,7 +469,14 @@ TestCase {
]
}
- function test_snapMode(data) {
+ function test_snapMode_mouse_data() {
+ return test_snapMode_data()
+ }
+
+ function test_snapMode_mouse(data) {
+ var dial = createTemporaryObject(dialComponent, testCase);
+ verify(dial);
+
dial.snapMode = data.snapMode;
dial.from = data.from;
dial.to = data.to;
@@ -357,6 +497,35 @@ TestCase {
fuzzyCompare(dial.position, data.positions[2], fuzz);
}
+ function test_snapMode_touch_data() {
+ return test_snapMode_data()
+ }
+
+ function test_snapMode_touch(data) {
+ var dial = createTemporaryObject(dialComponent, testCase);
+ verify(dial);
+
+ dial.snapMode = data.snapMode;
+ dial.from = data.from;
+ dial.to = data.to;
+ dial.stepSize = 0.2;
+
+ var fuzz = 0.05;
+
+ var touch = touchEvent(dial);
+ touch.press(0, dial, dial.width * 0.25, dial.height * 0.75).commit()
+ compare(dial.value, data.values[0]);
+ compare(dial.position, data.positions[0]);
+
+ touch.move(0, dial, dial.width * 0.5, dial.height * 0.25).commit();
+ fuzzyCompare(dial.value, data.values[1], fuzz);
+ fuzzyCompare(dial.position, data.positions[1], fuzz);
+
+ touch.release(0, dial, dial.width * 0.5, dial.height * 0.25).commit();
+ fuzzyCompare(dial.value, data.values[2], fuzz);
+ fuzzyCompare(dial.position, data.positions[2], fuzz);
+ }
+
function test_wheel_data() {
return [
{ tag: "horizontal", orientation: Qt.Horizontal, dx: 120, dy: 0 },
@@ -365,7 +534,7 @@ TestCase {
}
function test_wheel(data) {
- var control = dialComponent.createObject(testCase, {wheelEnabled: true, orientation: data.orientation})
+ var control = createTemporaryObject(dialComponent, testCase, {wheelEnabled: true, orientation: data.orientation})
verify(control)
compare(control.value, 0.0)
@@ -400,7 +569,5 @@ TestCase {
mouseWheel(control, control.width / 2, control.height / 2, -data.dx, -data.dy)
compare(control.value, 2.5)
compare(control.position, 0.25)
-
- control.destroy()
}
}
diff --git a/tests/auto/controls/data/tst_dialog.qml b/tests/auto/controls/data/tst_dialog.qml
index c295c0c1..fe81a2fa 100644
--- a/tests/auto/controls/data/tst_dialog.qml
+++ b/tests/auto/controls/data/tst_dialog.qml
@@ -67,39 +67,36 @@ TestCase {
}
function test_defaults() {
- var control = dialog.createObject(testCase)
+ var control = createTemporaryObject(dialog, testCase)
verify(control)
verify(control.header)
verify(control.footer)
compare(control.standardButtons, 0)
- control.destroy()
}
function test_accept() {
- var control = dialog.createObject(testCase)
+ var control = createTemporaryObject(dialog, testCase)
control.open()
waitForRendering(control.contentItem)
verify(control.visible)
- var acceptedSpy = signalSpy.createObject(testCase, {target: control, signalName: "accepted"})
+ var acceptedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "accepted"})
verify(acceptedSpy.valid)
control.accept()
compare(acceptedSpy.count, 1)
tryCompare(control, "visible", false)
-
- control.destroy()
}
function test_reject() {
- var control = dialog.createObject(testCase)
+ var control = createTemporaryObject(dialog, testCase)
control.open()
waitForRendering(control.contentItem)
verify(control.visible)
- var rejectedSpy = signalSpy.createObject(testCase, {target: control, signalName: "rejected"})
+ var rejectedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "rejected"})
verify(rejectedSpy.valid)
control.reject()
compare(rejectedSpy.count, 1)
@@ -149,8 +146,6 @@ TestCase {
mouseRelease(testCase, 1, 1)
compare(rejectedSpy.count, 4)
tryCompare(control, "visible", false)
-
- control.destroy()
}
function test_buttonBox_data() {
@@ -161,7 +156,7 @@ TestCase {
}
function test_buttonBox(data) {
- var control = dialog.createObject(testCase)
+ var control = createTemporaryObject(dialog, testCase)
if (data.custom)
control.footer = buttonBox.createObject(testCase)
@@ -170,21 +165,19 @@ TestCase {
verify(box)
compare(box.standardButtons, Dialog.Ok | Dialog.Cancel)
- var acceptedSpy = signalSpy.createObject(testCase, {target: control, signalName: "accepted"})
+ var acceptedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "accepted"})
verify(acceptedSpy.valid)
box.accepted()
compare(acceptedSpy.count, 1)
- var rejectedSpy = signalSpy.createObject(testCase, {target: control, signalName: "rejected"})
+ var rejectedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "rejected"})
verify(rejectedSpy.valid)
box.rejected()
compare(rejectedSpy.count, 1)
-
- control.destroy()
}
function test_standardButtons() {
- var control = dialog.createObject(testCase)
+ var control = createTemporaryObject(dialog, testCase)
control.standardButtons = Dialog.Ok
@@ -217,12 +210,10 @@ TestCase {
control.standardButtons = 0
compare(box.count, 0)
-
- control.destroy()
}
function test_layout() {
- var control = dialog.createObject(testCase, {width: 100, height: 100})
+ var control = createTemporaryObject(dialog, testCase, {width: 100, height: 100})
verify(control)
control.open()
@@ -296,8 +287,6 @@ TestCase {
control.footer.implicitWidth = 160
compare(control.implicitWidth, control.footer.implicitWidth)
-
- control.destroy()
}
function test_spacing_data() {
@@ -313,7 +302,7 @@ TestCase {
}
function test_spacing(data) {
- var control = dialog.createObject(testCase, {spacing: 20, width: 100, height: 100})
+ var control = createTemporaryObject(dialog, testCase, {spacing: 20, width: 100, height: 100})
verify(control)
control.open()
@@ -340,7 +329,5 @@ TestCase {
compare(control.contentItem.height, control.availableHeight
- (data.header ? control.header.height + control.spacing : 0)
- (data.footer ? control.footer.height + control.spacing : 0))
-
- control.destroy()
}
}
diff --git a/tests/auto/controls/data/tst_dialogbuttonbox.qml b/tests/auto/controls/data/tst_dialogbuttonbox.qml
index 880d44c7..603b069b 100644
--- a/tests/auto/controls/data/tst_dialogbuttonbox.qml
+++ b/tests/auto/controls/data/tst_dialogbuttonbox.qml
@@ -66,17 +66,16 @@ TestCase {
}
function test_defaults() {
- var control = buttonBox.createObject(testCase)
+ var control = createTemporaryObject(buttonBox, testCase)
verify(control)
compare(control.count, 0)
verify(control.delegate)
compare(control.standardButtons, 0)
- control.destroy()
}
function test_standardButtons() {
- var control = buttonBox.createObject(testCase)
-
+ var control = createTemporaryObject(buttonBox, testCase)
+ verify(control)
compare(control.count, 0)
control.standardButtons = DialogButtonBox.Ok
@@ -107,12 +106,11 @@ TestCase {
control.standardButtons = 0
compare(control.count, 0)
-
- control.destroy()
}
function test_attached() {
- var control = buttonBox.createObject(testCase)
+ var control = createTemporaryObject(buttonBox, testCase)
+ verify(control)
control.standardButtons = DialogButtonBox.Ok
var okButton = control.itemAt(0)
@@ -125,7 +123,7 @@ TestCase {
saveButton.DialogButtonBox.buttonRole = DialogButtonBox.AcceptRole
compare(saveButton.DialogButtonBox.buttonRole, DialogButtonBox.AcceptRole)
- var closeButton = button.createObject(null, {text: "Save"})
+ var closeButton = createTemporaryObject(button, null, {text: "Save"})
compare(closeButton.DialogButtonBox.buttonBox, null)
compare(closeButton.DialogButtonBox.buttonRole, DialogButtonBox.InvalidRole)
closeButton.DialogButtonBox.buttonRole = DialogButtonBox.DestructiveRole
@@ -137,8 +135,6 @@ TestCase {
compare(okButton.DialogButtonBox.buttonBox, null)
compare(saveButton.DialogButtonBox.buttonBox, null)
compare(closeButton.DialogButtonBox.buttonBox, null)
-
- control.destroy()
}
function test_signals_data() {
@@ -165,7 +161,8 @@ TestCase {
}
function test_signals(data) {
- var control = buttonBox.createObject(testCase)
+ var control = createTemporaryObject(buttonBox, testCase)
+ verify(control)
control.standardButtons = data.standardButton
compare(control.count, 1)
@@ -182,7 +179,5 @@ TestCase {
compare(clickedSpy.count, 1)
compare(clickedSpy.signalArguments[0][0], button)
compare(roleSpy.count, !!data.signalName ? 1 : 0)
-
- control.destroy()
}
}
diff --git a/tests/auto/controls/data/tst_drawer.qml b/tests/auto/controls/data/tst_drawer.qml
index 91e934c4..887db22d 100644
--- a/tests/auto/controls/data/tst_drawer.qml
+++ b/tests/auto/controls/data/tst_drawer.qml
@@ -56,12 +56,11 @@ TestCase {
}
function test_defaults() {
- var control = drawer.createObject(testCase)
+ var control = createTemporaryObject(drawer, testCase)
compare(control.edge, Qt.LeftEdge)
compare(control.position, 0.0)
compare(control.dragMargin, Qt.styleHints.startDragDistance)
compare(control.parent, ApplicationWindow.overlay)
- control.destroy()
}
Component {
@@ -79,7 +78,7 @@ TestCase {
function test_swipeVelocity() {
skip("QTBUG-52003");
- var control = rectDrawer.createObject(testCase)
+ var control = createTemporaryObject(rectDrawer, testCase)
verify(control.contentItem)
compare(control.edge, Qt.LeftEdge)
compare(control.position, 0.0)
@@ -95,7 +94,5 @@ TestCase {
tryCompare(control, "position", distance / control.contentItem.width)
mouseRelease(control, distance, 0, Qt.LeftButton)
tryCompare(control, "position", 1.0)
-
- control.destroy()
}
}
diff --git a/tests/auto/controls/data/tst_frame.qml b/tests/auto/controls/data/tst_frame.qml
index 7d8ab7c3..2f4748c4 100644
--- a/tests/auto/controls/data/tst_frame.qml
+++ b/tests/auto/controls/data/tst_frame.qml
@@ -90,49 +90,41 @@ TestCase {
}
function test_empty() {
- var control = frame.createObject(testCase)
+ var control = createTemporaryObject(frame, testCase)
verify(control)
verify(control.contentItem)
compare(control.contentWidth, 0)
compare(control.contentHeight, 0)
-
- control.destroy()
}
function test_oneChild() {
- var control = oneChildFrame.createObject(testCase)
+ var control = createTemporaryObject(oneChildFrame, testCase)
verify(control)
compare(control.contentWidth, 100)
compare(control.contentHeight, 30)
verify(control.implicitWidth > 100)
verify(control.implicitHeight > 30)
-
- control.destroy()
}
function test_twoChildren() {
- var control = twoChildrenFrame.createObject(testCase)
+ var control = createTemporaryObject(twoChildrenFrame, testCase)
verify(control)
compare(control.contentWidth, 0)
compare(control.contentHeight, 0)
verify(control.implicitWidth > 0)
verify(control.implicitHeight > 0)
-
- control.destroy()
}
function test_contentItem() {
- var control = contentFrame.createObject(testCase)
+ var control = createTemporaryObject(contentFrame, testCase)
verify(control)
compare(control.contentWidth, 100)
compare(control.contentHeight, 30)
verify(control.implicitWidth > 100)
verify(control.implicitHeight > 30)
-
- control.destroy()
}
}
diff --git a/tests/auto/controls/data/tst_groupbox.qml b/tests/auto/controls/data/tst_groupbox.qml
index 05348ad5..1108ba4d 100644
--- a/tests/auto/controls/data/tst_groupbox.qml
+++ b/tests/auto/controls/data/tst_groupbox.qml
@@ -90,49 +90,41 @@ TestCase {
}
function test_empty() {
- var control = groupBox.createObject(testCase)
+ var control = createTemporaryObject(groupBox, testCase)
verify(control)
verify(control.contentItem)
compare(control.contentWidth, 0)
compare(control.contentHeight, 0)
-
- control.destroy()
}
function test_oneChild() {
- var control = oneChildBox.createObject(testCase)
+ var control = createTemporaryObject(oneChildBox, testCase)
verify(control)
compare(control.contentWidth, 100)
compare(control.contentHeight, 30)
verify(control.implicitWidth > 100)
verify(control.implicitHeight > 30)
-
- control.destroy()
}
function test_twoChildren() {
- var control = twoChildrenBox.createObject(testCase)
+ var control = createTemporaryObject(twoChildrenBox, testCase)
verify(control)
compare(control.contentWidth, 0)
compare(control.contentHeight, 0)
verify(control.implicitWidth > 0)
verify(control.implicitHeight > 0)
-
- control.destroy()
}
function test_contentItem() {
- var control = contentBox.createObject(testCase)
+ var control = createTemporaryObject(contentBox, testCase)
verify(control)
compare(control.contentWidth, 100)
compare(control.contentHeight, 30)
verify(control.implicitWidth > 100)
verify(control.implicitHeight > 30)
-
- control.destroy()
}
}
diff --git a/tests/auto/controls/data/tst_itemdelegate.qml b/tests/auto/controls/data/tst_itemdelegate.qml
index 3c5ee1cb..ac47ed45 100644
--- a/tests/auto/controls/data/tst_itemdelegate.qml
+++ b/tests/auto/controls/data/tst_itemdelegate.qml
@@ -56,20 +56,17 @@ TestCase {
}
function test_baseline() {
- var control = itemDelegate.createObject(testCase)
+ var control = createTemporaryObject(itemDelegate, testCase)
verify(control)
compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset)
- control.destroy()
}
function test_highlighted() {
- var control = itemDelegate.createObject(testCase)
+ var control = createTemporaryObject(itemDelegate, testCase)
verify(control)
verify(!control.highlighted)
control.highlighted = true
verify(control.highlighted)
-
- control.destroy()
}
}
diff --git a/tests/auto/controls/data/tst_label.qml b/tests/auto/controls/data/tst_label.qml
index 8dde8951..41faa1f7 100644
--- a/tests/auto/controls/data/tst_label.qml
+++ b/tests/auto/controls/data/tst_label.qml
@@ -61,9 +61,8 @@ TestCase {
}
function test_creation() {
- var control = label.createObject(testCase)
+ var control = createTemporaryObject(label, testCase)
verify(control)
- control.destroy()
}
function test_font_explicit_attributes_data() {
@@ -80,7 +79,7 @@ TestCase {
}
function test_font_explicit_attributes(data) {
- var control = label.createObject(testCase)
+ var control = createTemporaryObject(label, testCase)
verify(control)
var child = label.createObject(control)
@@ -105,7 +104,5 @@ TestCase {
compare(child.font[data.tag], defaultValue)
compare(childSpy.count, 0)
-
- control.destroy()
}
}
diff --git a/tests/auto/controls/data/tst_menuitem.qml b/tests/auto/controls/data/tst_menuitem.qml
index f00e229a..75fd3830 100644
--- a/tests/auto/controls/data/tst_menuitem.qml
+++ b/tests/auto/controls/data/tst_menuitem.qml
@@ -56,14 +56,13 @@ TestCase {
}
function test_baseline() {
- var control = menuItem.createObject(testCase)
+ var control = createTemporaryObject(menuItem, testCase)
verify(control)
compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset)
- control.destroy()
}
function test_checkable() {
- var control = menuItem.createObject(testCase)
+ var control = createTemporaryObject(menuItem, testCase)
verify(control)
verify(control.hasOwnProperty("checkable"))
verify(!control.checkable)
@@ -77,18 +76,14 @@ TestCase {
mouseClick(control)
verify(!control.checked)
-
- control.destroy()
}
function test_highlighted() {
- var control = menuItem.createObject(testCase)
+ var control = createTemporaryObject(menuItem, testCase)
verify(control)
verify(!control.highlighted)
control.highlighted = true
verify(control.highlighted)
-
- control.destroy()
}
}
diff --git a/tests/auto/controls/data/tst_page.qml b/tests/auto/controls/data/tst_page.qml
index 0388bc0a..52625382 100644
--- a/tests/auto/controls/data/tst_page.qml
+++ b/tests/auto/controls/data/tst_page.qml
@@ -95,65 +95,55 @@ TestCase {
}
function test_defaults() {
- var control = page.createObject(testCase)
+ var control = createTemporaryObject(page, testCase)
verify(control)
verify(control.contentItem)
compare(control.header, null)
compare(control.footer, null)
-
- control.destroy()
}
function test_empty() {
- var control = page.createObject(testCase)
+ var control = createTemporaryObject(page, testCase)
verify(control)
verify(control.contentItem)
compare(control.contentWidth, 0)
compare(control.contentHeight, 0)
-
- control.destroy()
}
function test_oneChild() {
- var control = oneChildPage.createObject(testCase)
+ var control = createTemporaryObject(oneChildPage, testCase)
verify(control)
compare(control.contentWidth, 100)
compare(control.contentHeight, 30)
compare(control.implicitWidth, 100 + control.leftPadding + control.rightPadding)
compare(control.implicitHeight, 30 + control.topPadding + control.bottomPadding)
-
- control.destroy()
}
function test_twoChildren() {
- var control = twoChildrenPage.createObject(testCase)
+ var control = createTemporaryObject(twoChildrenPage, testCase)
verify(control)
compare(control.contentWidth, 0)
compare(control.contentHeight, 0)
compare(control.implicitWidth, control.leftPadding + control.rightPadding)
compare(control.implicitHeight, control.topPadding + control.bottomPadding)
-
- control.destroy()
}
function test_contentItem() {
- var control = contentPage.createObject(testCase)
+ var control = createTemporaryObject(contentPage, testCase)
verify(control)
compare(control.contentWidth, 100)
compare(control.contentHeight, 30)
compare(control.implicitWidth, 100 + control.leftPadding + control.rightPadding)
compare(control.implicitHeight, 30 + control.topPadding + control.bottomPadding)
-
- control.destroy()
}
function test_layout() {
- var control = page.createObject(testCase, {width: 100, height: 100})
+ var control = createTemporaryObject(page, testCase, {width: 100, height: 100})
verify(control)
compare(control.width, 100)
@@ -223,8 +213,6 @@ TestCase {
control.footer.implicitWidth = 160
compare(control.implicitWidth, control.footer.implicitWidth + control.leftPadding + control.rightPadding)
-
- control.destroy()
}
function test_spacing_data() {
@@ -240,7 +228,7 @@ TestCase {
}
function test_spacing(data) {
- var control = page.createObject(testCase, {spacing: 20, width: 100, height: 100})
+ var control = createTemporaryObject(page, testCase, {spacing: 20, width: 100, height: 100})
verify(control)
control.contentItem.visible = data.content
@@ -263,7 +251,5 @@ TestCase {
compare(control.contentItem.height, control.availableHeight
- (data.header ? control.header.height + control.spacing : 0)
- (data.footer ? control.footer.height + control.spacing : 0))
-
- control.destroy()
}
}
diff --git a/tests/auto/controls/data/tst_pageindicator.qml b/tests/auto/controls/data/tst_pageindicator.qml
index 4094a293..4341d7b2 100644
--- a/tests/auto/controls/data/tst_pageindicator.qml
+++ b/tests/auto/controls/data/tst_pageindicator.qml
@@ -56,29 +56,25 @@ TestCase {
}
function test_count() {
- var control = pageIndicator.createObject(testCase)
+ var control = createTemporaryObject(pageIndicator, testCase)
verify(control)
compare(control.count, 0)
control.count = 3
compare(control.count, 3)
-
- control.destroy()
}
function test_currentIndex() {
- var control = pageIndicator.createObject(testCase)
+ var control = createTemporaryObject(pageIndicator, testCase)
verify(control)
compare(control.currentIndex, 0)
control.currentIndex = 5
compare(control.currentIndex, 5)
-
- control.destroy()
}
function test_interactive() {
- var control = pageIndicator.createObject(testCase, {count: 5})
+ var control = createTemporaryObject(pageIndicator, testCase, {count: 5})
verify(control)
verify(!control.interactive)
@@ -110,7 +106,5 @@ TestCase {
}
}
}
-
- control.destroy()
}
}
diff --git a/tests/auto/controls/data/tst_pane.qml b/tests/auto/controls/data/tst_pane.qml
index ec188afb..0c1b54db 100644
--- a/tests/auto/controls/data/tst_pane.qml
+++ b/tests/auto/controls/data/tst_pane.qml
@@ -103,54 +103,46 @@ TestCase {
}
function test_empty() {
- var control = pane.createObject(testCase)
+ var control = createTemporaryObject(pane, testCase)
verify(control)
verify(control.contentItem)
compare(control.contentWidth, 0)
compare(control.contentHeight, 0)
-
- control.destroy()
}
function test_oneChild() {
- var control = oneChildPane.createObject(testCase)
+ var control = createTemporaryObject(oneChildPane, testCase)
verify(control)
compare(control.contentWidth, 100)
compare(control.contentHeight, 30)
verify(control.implicitWidth > 100)
verify(control.implicitHeight > 30)
-
- control.destroy()
}
function test_twoChildren() {
- var control = twoChildrenPane.createObject(testCase)
+ var control = createTemporaryObject(twoChildrenPane, testCase)
verify(control)
compare(control.contentWidth, 0)
compare(control.contentHeight, 0)
verify(control.implicitWidth > 0)
verify(control.implicitHeight > 0)
-
- control.destroy()
}
function test_contentItem() {
- var control = contentPane.createObject(testCase)
+ var control = createTemporaryObject(contentPane, testCase)
verify(control)
compare(control.contentWidth, 100)
compare(control.contentHeight, 30)
verify(control.implicitWidth > 100)
verify(control.implicitHeight > 30)
-
- control.destroy()
}
function test_press() {
- var control = pressPane.createObject(testCase)
+ var control = createTemporaryObject(pressPane, testCase)
verify(control)
compare(control.pressCount, 0)
@@ -160,7 +152,5 @@ TestCase {
control.children[0].enabled = false
mouseClick(control)
compare(control.pressCount, 1)
-
- control.destroy()
}
}
diff --git a/tests/auto/controls/data/tst_popup.qml b/tests/auto/controls/data/tst_popup.qml
index ee98e2ae..1059ca82 100644
--- a/tests/auto/controls/data/tst_popup.qml
+++ b/tests/auto/controls/data/tst_popup.qml
@@ -78,22 +78,22 @@ TestCase {
}
function test_padding() {
- var control = popupTemplate.createObject(testCase)
+ var control = createTemporaryObject(popupTemplate, testCase)
verify(control)
- var paddingSpy = signalSpy.createObject(testCase, {target: control, signalName: "paddingChanged"})
+ var paddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "paddingChanged"})
verify(paddingSpy.valid)
- var topPaddingSpy = signalSpy.createObject(testCase, {target: control, signalName: "topPaddingChanged"})
+ var topPaddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "topPaddingChanged"})
verify(topPaddingSpy.valid)
- var leftPaddingSpy = signalSpy.createObject(testCase, {target: control, signalName: "leftPaddingChanged"})
+ var leftPaddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "leftPaddingChanged"})
verify(leftPaddingSpy.valid)
- var rightPaddingSpy = signalSpy.createObject(testCase, {target: control, signalName: "rightPaddingChanged"})
+ var rightPaddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "rightPaddingChanged"})
verify(rightPaddingSpy.valid)
- var bottomPaddingSpy = signalSpy.createObject(testCase, {target: control, signalName: "bottomPaddingChanged"})
+ var bottomPaddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "bottomPaddingChanged"})
verify(bottomPaddingSpy.valid)
var paddingChanges = 0
@@ -184,18 +184,16 @@ TestCase {
compare(leftPaddingSpy.count, leftPaddingChanges)
compare(rightPaddingSpy.count, rightPaddingChanges)
compare(bottomPaddingSpy.count, bottomPaddingChanges)
-
- control.destroy()
}
function test_availableSize() {
var control = popupTemplate.createObject(testCase)
verify(control)
- var availableWidthSpy = signalSpy.createObject(testCase, {target: control, signalName: "availableWidthChanged"})
+ var availableWidthSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "availableWidthChanged"})
verify(availableWidthSpy.valid)
- var availableHeightSpy = signalSpy.createObject(testCase, {target: control, signalName: "availableHeightChanged"})
+ var availableHeightSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "availableHeightChanged"})
verify(availableHeightSpy.valid)
var availableWidthChanges = 0
@@ -256,19 +254,17 @@ TestCase {
compare(control.availableHeight, 0)
compare(availableWidthSpy.count, availableWidthChanges)
compare(availableHeightSpy.count, ++availableHeightChanges)
-
- control.destroy()
}
function test_position() {
- var control = popupControl.createObject(testCase, {visible: true, leftMargin: 10, topMargin: 20, width: 100, height: 100})
+ var control = createTemporaryObject(popupControl, testCase, {visible: true, leftMargin: 10, topMargin: 20, width: 100, height: 100})
verify(control)
verify(control.visible)
- var xSpy = signalSpy.createObject(testCase, {target: control, signalName: "xChanged"})
+ var xSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "xChanged"})
verify(xSpy.valid)
- var ySpy = signalSpy.createObject(testCase, {target: control, signalName: "yChanged"})
+ var ySpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "yChanged"})
verify(ySpy.valid)
// moving outside margins does not trigger change notifiers
@@ -298,7 +294,7 @@ TestCase {
compare(ySpy.count, 1)
// re-parent and reset the position
- control.parent = rect.createObject(testCase, {color: "red", width: 100, height: 100})
+ control.parent = createTemporaryObject(rect, testCase, {color: "red", width: 100, height: 100})
control.x = 0
control.y = 0
compare(xSpy.count, 2)
@@ -314,12 +310,10 @@ TestCase {
compare(control.y, 60 + control.topMargin)
compare(xSpy.count, 3)
compare(ySpy.count, 3)
-
- control.destroy()
}
function test_resetSize() {
- var control = popupControl.createObject(testCase, {visible: true, margins: 0})
+ var control = createTemporaryObject(popupControl, testCase, {visible: true, margins: 0})
verify(control)
control.width = control.implicitWidth = testCase.width + 10
@@ -332,12 +326,10 @@ TestCase {
control.height = undefined
compare(control.width, testCase.width)
compare(control.height, testCase.height)
-
- control.destroy()
}
function test_negativeMargins() {
- var control = popupControl.createObject(testCase, {implicitWidth: testCase.width, implicitHeight: testCase.height})
+ var control = createTemporaryObject(popupControl, testCase, {implicitWidth: testCase.width, implicitHeight: testCase.height})
verify(control)
control.open()
@@ -356,12 +348,10 @@ TestCase {
control.y = -10
compare(control.x, 0)
compare(control.y, 0)
-
- control.destroy()
}
function test_margins() {
- var control = popupControl.createObject(testCase, {width: 100, height: 100})
+ var control = createTemporaryObject(popupControl, testCase, {width: 100, height: 100})
verify(control)
control.open()
@@ -444,12 +434,10 @@ TestCase {
compare(control.leftMargin, -1)
compare(control.contentItem.parent.x, -testCase.width)
compare(control.contentItem.parent.y, -testCase.height)
-
- control.destroy()
}
function test_background() {
- var control = popupTemplate.createObject(testCase)
+ var control = createTemporaryObject(popupTemplate, testCase)
verify(control)
control.background = rect.createObject(testCase)
@@ -491,8 +479,6 @@ TestCase {
control.background.y = 10
control.height -= 20
verify(control.background.height !== control.height)
-
- control.destroy()
}
function getChild(control, objname, idx) {
@@ -566,7 +552,7 @@ TestCase {
}
function test_font() { // QTBUG_50984, QTBUG-51696
- var window = component.createObject(testCase)
+ var window = createTemporaryObject(component, testCase)
verify(window)
compare(window.font.pixelSize, 40)
@@ -643,8 +629,6 @@ TestCase {
compare(window.popup.listview.contentItem.children[idx1].fontspy.count, 2)
compare(window.popup.listview.contentItem.children[idx2].font.pixelSize, 60)
compare(window.popup.listview.contentItem.children[idx2].fontspy.count, 2)
-
- window.destroy()
}
Component {
@@ -687,7 +671,7 @@ TestCase {
function test_locale() { // QTBUG_50984
// test looking up natural locale from ancestors
- var control = localeComponent.createObject(applicationWindow.contentItem)
+ var control = createTemporaryObject(localeComponent, applicationWindow.contentItem)
verify(control)
compare(control.locale.name, "en_US")
@@ -697,7 +681,6 @@ TestCase {
compare(control.popup.button2.locale.name, "nb_NO")
control.ApplicationWindow.window.locale = undefined
- control.destroy()
}
Component {
@@ -771,7 +754,7 @@ TestCase {
function test_locale_changes() { // QTBUG_50984
// test default locale and locale inheritance
- var control = localeChangeComponent.createObject(applicationWindow.contentItem)
+ var control = createTemporaryObject(localeChangeComponent, applicationWindow.contentItem)
verify(control)
var defaultLocale = Qt.locale()
@@ -937,12 +920,10 @@ TestCase {
compare(control.popup.button1.mirrorspy.count, 2)
compare(control.popup.button2.localespy.count, 5)
compare(control.popup.button2.mirrorspy.count, 2)
-
- control.destroy()
}
function test_size() {
- var control = popupControl.createObject(testCase)
+ var control = createTemporaryObject(popupControl, testCase)
verify(control)
control.open()
@@ -991,12 +972,10 @@ TestCase {
compare(control.implicitHeight, 40)
compare(control.height, 40)
compare(control.contentItem.height, control.height - control.topPadding - control.bottomPadding)
-
- control.destroy()
}
function test_visible() {
- var control = popupTemplate.createObject(testCase, {visible: true})
+ var control = createTemporaryObject(popupTemplate, testCase, {visible: true})
verify(control)
// QTBUG-51989
@@ -1005,8 +984,6 @@ TestCase {
// QTBUG-55347
control.parent = null
verify(!control.visible)
-
- control.destroy()
}
Component {
@@ -1070,7 +1047,7 @@ TestCase {
}
function test_overlay() {
- var window = overlayTest.createObject(testCase)
+ var window = createTemporaryObject(overlayTest, testCase)
verify(window)
window.requestActivate()
@@ -1168,12 +1145,10 @@ TestCase {
window.modalPopupWithoutDim.close()
tryCompare(window.modalPopupWithoutDim, "visible", false)
compare(window.overlay.children.length, 0) // popup + overlay removed
-
- window.destroy()
}
function test_attached_applicationwindow() {
- var control = popupControl.createObject(applicationWindow.contentItem)
+ var control = createTemporaryObject(popupControl, applicationWindow.contentItem)
verify(control)
var child = rect.createObject(control.contentItem)
@@ -1186,8 +1161,6 @@ TestCase {
compare(control.ApplicationWindow.window, null)
compare(control.contentItem.ApplicationWindow.window, null)
compare(child.ApplicationWindow.window, null)
-
- control.destroy()
}
SignalSpy {
@@ -1209,7 +1182,7 @@ TestCase {
}
function test_openedClosed() {
- var control = pausePopup.createObject(testCase)
+ var control = createTemporaryObject(pausePopup, testCase)
verify(control)
openedSpy.target = control
@@ -1226,8 +1199,6 @@ TestCase {
compare(closedSpy.count, 0)
tryCompare(closedSpy, "count", 1)
compare(control.visible, false)
-
- control.destroy()
}
Component {
@@ -1253,11 +1224,10 @@ TestCase {
}
function test_xyBindingLoop() {
- var window = xyBindingLoop.createObject(testCase)
+ var window = createTemporaryObject(xyBindingLoop, testCase)
var control = window.popup
waitForRendering(control.contentItem)
compare(control.x, (control.parent.width - control.width) / 2)
compare(control.y, (control.parent.height - control.height) / 2)
- window.destroy()
}
}
diff --git a/tests/auto/controls/data/tst_progressbar.qml b/tests/auto/controls/data/tst_progressbar.qml
index 8f73b367..a51e01eb 100644
--- a/tests/auto/controls/data/tst_progressbar.qml
+++ b/tests/auto/controls/data/tst_progressbar.qml
@@ -56,7 +56,7 @@ TestCase {
}
function test_value() {
- var control = progressBar.createObject(testCase)
+ var control = createTemporaryObject(progressBar, testCase)
verify(control)
compare(control.value, 0.0)
@@ -68,12 +68,10 @@ TestCase {
compare(control.value, 0.0)
control.value = 2.0
compare(control.value, 1.0)
-
- control.destroy()
}
function test_range() {
- var control = progressBar.createObject(testCase, {from: 0, to: 100, value: 50})
+ var control = createTemporaryObject(progressBar, testCase, {from: 0, to: 100, value: 50})
verify(control)
compare(control.from, 0)
@@ -102,12 +100,10 @@ TestCase {
control.value = 50
compare(control.value, 50)
compare(control.position, 0.5)
-
- control.destroy()
}
function test_inverted() {
- var control = progressBar.createObject(testCase, {from: 1.0, to: -1.0})
+ var control = createTemporaryObject(progressBar, testCase, {from: 1.0, to: -1.0})
verify(control)
compare(control.from, 1.0)
@@ -126,12 +122,10 @@ TestCase {
control.value = 0.0
compare(control.value, 0.0)
compare(control.position, 0.5)
-
- control.destroy()
}
function test_position() {
- var control = progressBar.createObject(testCase)
+ var control = createTemporaryObject(progressBar, testCase)
verify(control)
compare(control.value, 0)
@@ -144,12 +138,10 @@ TestCase {
control.value = 0.75
compare(control.value, 0.75)
compare(control.position, 0.75)
-
- control.destroy()
}
function test_visualPosition() {
- var control = progressBar.createObject(testCase)
+ var control = createTemporaryObject(progressBar, testCase)
verify(control)
compare(control.value, 0)
@@ -178,12 +170,10 @@ TestCase {
// LayoutMirroring
control.LayoutMirroring.enabled = true
compare(control.visualPosition, 0.75)
-
- control.destroy()
}
function test_indeterminate() {
- var control = progressBar.createObject(testCase)
+ var control = createTemporaryObject(progressBar, testCase)
verify(control)
compare(control.indeterminate, false)
@@ -192,7 +182,5 @@ TestCase {
wait(100)
// Shouldn't crash...
control.indeterminate = false
-
- control.destroy()
}
}
diff --git a/tests/auto/controls/data/tst_radiobutton.qml b/tests/auto/controls/data/tst_radiobutton.qml
index 046924c0..35f039b6 100644
--- a/tests/auto/controls/data/tst_radiobutton.qml
+++ b/tests/auto/controls/data/tst_radiobutton.qml
@@ -58,12 +58,12 @@ TestCase {
Component {
id: signalSequenceSpy
SignalSequenceSpy {
- signals: ["pressed", "released", "canceled", "clicked", "pressedChanged", "checkedChanged"]
+ signals: ["pressed", "released", "canceled", "clicked", "toggled", "pressedChanged", "checkedChanged"]
}
}
function test_text() {
- var control = radioButton.createObject(testCase)
+ var control = createTemporaryObject(radioButton, testCase)
verify(control)
compare(control.text, "")
@@ -71,12 +71,10 @@ TestCase {
compare(control.text, "RadioButton")
control.text = ""
compare(control.text, "")
-
- control.destroy()
}
function test_checked() {
- var control = radioButton.createObject(testCase)
+ var control = createTemporaryObject(radioButton, testCase)
verify(control)
var sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
@@ -94,12 +92,10 @@ TestCase {
control.checked = false
compare(control.checked, false)
verify(sequenceSpy.success)
-
- control.destroy()
}
function test_mouse() {
- var control = radioButton.createObject(testCase)
+ var control = createTemporaryObject(radioButton, testCase)
verify(control)
var sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
@@ -112,6 +108,7 @@ TestCase {
verify(sequenceSpy.success)
sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": false }],
["checkedChanged", { "pressed": false, "checked": true }],
+ "toggled",
"released",
"clicked"]
mouseRelease(control, control.width / 2, control.height / 2, Qt.LeftButton)
@@ -157,12 +154,10 @@ TestCase {
compare(control.checked, true)
compare(control.pressed, false)
verify(sequenceSpy.success)
-
- control.destroy()
}
function test_keys() {
- var control = radioButton.createObject(testCase)
+ var control = createTemporaryObject(radioButton, testCase)
verify(control)
var sequenceSpy = signalSequenceSpy.createObject(control, {target: control})
@@ -177,6 +172,7 @@ TestCase {
"pressed",
["pressedChanged", { "pressed": false, "checked": false }],
["checkedChanged", { "pressed": false, "checked": true }],
+ "toggled",
"released",
"clicked"]
keyClick(Qt.Key_Space)
@@ -202,12 +198,10 @@ TestCase {
compare(control.checked, true)
verify(sequenceSpy.success)
}
-
- control.destroy()
}
Component {
- id: twoRadioButtones
+ id: twoRadioButtons
Item {
property RadioButton rb1: RadioButton { id: rb1 }
property RadioButton rb2: RadioButton { id: rb2; checked: rb1.checked; enabled: false }
@@ -215,7 +209,7 @@ TestCase {
}
function test_binding() {
- var container = twoRadioButtones.createObject(testCase)
+ var container = createTemporaryObject(twoRadioButtons, testCase)
verify(container)
compare(container.rb1.checked, false)
@@ -228,8 +222,6 @@ TestCase {
container.rb1.checked = false
compare(container.rb1.checked, false)
compare(container.rb2.checked, false)
-
- container.destroy()
}
Component {
@@ -256,7 +248,7 @@ TestCase {
}
function test_autoExclusive() {
- var container = radioButtonGroup.createObject(testCase)
+ var container = createTemporaryObject(radioButtonGroup, testCase)
compare(container.children.length, 8)
var checkStates = [false, false, false, false, false, false, false, false]
@@ -311,14 +303,11 @@ TestCase {
checkStates[1] = false
for (i = 0; i < 8; ++i)
compare(container.children[i].checked, checkStates[i])
-
- container.destroy()
}
function test_baseline() {
- var control = radioButton.createObject(testCase)
+ var control = createTemporaryObject(radioButton, testCase)
verify(control)
compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset)
- control.destroy()
}
}
diff --git a/tests/auto/controls/data/tst_radiodelegate.qml b/tests/auto/controls/data/tst_radiodelegate.qml
index 8cc1d1f7..23446aa9 100644
--- a/tests/auto/controls/data/tst_radiodelegate.qml
+++ b/tests/auto/controls/data/tst_radiodelegate.qml
@@ -58,14 +58,13 @@ TestCase {
// TODO: data-fy tst_radiobutton (rename to tst_radio?) so we don't duplicate its tests here?
function test_defaults() {
- var control = radioDelegate.createObject(testCase);
+ var control = createTemporaryObject(radioDelegate, testCase);
verify(control);
verify(!control.checked);
- control.destroy();
}
function test_checked() {
- var control = radioDelegate.createObject(testCase);
+ var control = createTemporaryObject(radioDelegate, testCase);
verify(control);
mouseClick(control);
@@ -73,14 +72,11 @@ TestCase {
mouseClick(control);
verify(control.checked);
-
- control.destroy();
}
function test_baseline() {
- var control = radioDelegate.createObject(testCase);
+ var control = createTemporaryObject(radioDelegate, testCase);
verify(control);
compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset);
- control.destroy();
}
}
diff --git a/tests/auto/controls/data/tst_rangeslider.qml b/tests/auto/controls/data/tst_rangeslider.qml
index ba3a1c9e..b015b2de 100644
--- a/tests/auto/controls/data/tst_rangeslider.qml
+++ b/tests/auto/controls/data/tst_rangeslider.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.1
+import QtQuick.Controls 2.2
TestCase {
id: testCase
@@ -80,18 +80,16 @@ TestCase {
}
function test_defaults() {
- var control = sliderComponent.createObject(testCase)
+ var control = createTemporaryObject(sliderComponent, testCase)
verify(control)
compare(control.stepSize, 0)
compare(control.snapMode, RangeSlider.NoSnap)
compare(control.orientation, Qt.Horizontal)
-
- control.destroy()
}
function test_values() {
- var control = sliderComponent.createObject(testCase)
+ var control = createTemporaryObject(sliderComponent, testCase)
verify(control)
compare(control.first.value, 0.0)
@@ -113,12 +111,10 @@ TestCase {
compare(control.first.value, 0.5)
control.second.value = 0
compare(control.second.value, 0.5)
-
- control.destroy()
}
function test_range() {
- var control = sliderComponent.createObject(testCase, { from: 0, to: 100, "first.value": 50, "second.value": 100 })
+ var control = createTemporaryObject(sliderComponent, testCase, { from: 0, to: 100, "first.value": 50, "second.value": 100 })
verify(control)
compare(control.from, 0)
@@ -149,12 +145,10 @@ TestCase {
control.first.value = 50
compare(control.first.value, 50)
compare(control.first.position, 0.5)
-
- control.destroy()
}
function test_setValues() {
- var control = sliderComponent.createObject(testCase)
+ var control = createTemporaryObject(sliderComponent, testCase)
verify(control)
compare(control.from, 0)
@@ -176,12 +170,10 @@ TestCase {
compare(control.second.value, 200)
compare(control.first.position, 0.333333)
compare(control.second.position, 0.666666)
-
- control.destroy()
}
function test_inverted() {
- var control = sliderComponent.createObject(testCase, { from: 1.0, to: -1.0 })
+ var control = createTemporaryObject(sliderComponent, testCase, { from: 1.0, to: -1.0 })
verify(control)
compare(control.from, 1.0)
@@ -208,12 +200,10 @@ TestCase {
compare(control.first.position, 0.5)
compare(control.second.value, 0.0);
compare(control.second.position, 0.5);
-
- control.destroy()
}
function test_visualPosition() {
- var control = sliderComponent.createObject(testCase)
+ var control = createTemporaryObject(sliderComponent, testCase)
verify(control)
compare(control.first.value, 0.0)
@@ -255,12 +245,10 @@ TestCase {
control.LayoutMirroring.enabled = true
compare(control.first.visualPosition, 0.75)
compare(control.second.visualPosition, 0.0)
-
- control.destroy()
}
function test_orientation() {
- var control = sliderComponent.createObject(testCase)
+ var control = createTemporaryObject(sliderComponent, testCase)
verify(control)
compare(control.orientation, Qt.Horizontal)
@@ -268,19 +256,19 @@ TestCase {
control.orientation = Qt.Vertical
compare(control.orientation, Qt.Vertical)
verify(control.width < control.height)
-
- control.destroy()
}
function test_mouse_data() {
return [
- { tag: "horizontal", orientation: Qt.Horizontal },
- { tag: "vertical", orientation: Qt.Vertical }
+ { tag: "horizontal", orientation: Qt.Horizontal, live: false },
+ { tag: "vertical", orientation: Qt.Vertical, live: false },
+ { tag: "horizontal:live", orientation: Qt.Horizontal, live: true },
+ { tag: "vertical:live", orientation: Qt.Vertical, live: true }
]
}
function test_mouse(data) {
- var control = sliderComponent.createObject(testCase, { orientation: data.orientation })
+ var control = createTemporaryObject(sliderComponent, testCase, { orientation: data.orientation, live: data.live })
verify(control)
var firstPressedSpy = signalSpy.createObject(control, {target: control.first, signalName: "pressedChanged"})
@@ -366,7 +354,7 @@ TestCase {
compare(firstPressedSpy.count, 5)
compare(secondPressedSpy.count, 2)
compare(control.first.pressed, true)
- compare(control.first.value, 0.0)
+ compare(control.first.value, data.live ? 0.5 : 0.0)
compare(control.first.position, 0.5)
compare(control.first.visualPosition, 0.5)
compare(control.second.pressed, false)
@@ -385,12 +373,188 @@ TestCase {
compare(control.second.value, 1.0)
compare(control.second.position, 1.0)
compare(control.second.visualPosition, horizontal ? 1.0 : 0.0)
+ }
- control.destroy()
+ function test_touch_data() {
+ return [
+ { tag: "horizontal", orientation: Qt.Horizontal, live: false },
+ { tag: "vertical", orientation: Qt.Vertical, live: false },
+ { tag: "horizontal:live", orientation: Qt.Horizontal, live: true },
+ { tag: "vertical:live", orientation: Qt.Vertical, live: true }
+ ]
+ }
+
+ function test_touch(data) {
+ var control = createTemporaryObject(sliderComponent, testCase, { orientation: data.orientation, live: data.live })
+ verify(control)
+
+ var firstPressedSpy = signalSpy.createObject(control, {target: control.first, signalName: "pressedChanged"})
+ verify(firstPressedSpy.valid)
+
+ var secondPressedSpy = signalSpy.createObject(control, {target: control.second, signalName: "pressedChanged"})
+ verify(secondPressedSpy.valid)
+
+ var touch = touchEvent(control)
+ touch.press(0, control, control.width * 0.25, control.height * 0.75).commit()
+ compare(firstPressedSpy.count, 1)
+ compare(secondPressedSpy.count, 0)
+ compare(control.first.pressed, true)
+ compare(control.first.value, 0.0)
+ compare(control.first.position, 0.0)
+ compare(control.second.pressed, false)
+ compare(control.second.value, 1.0)
+ compare(control.second.position, 1.0)
+
+ touch.release(0, control, control.width * 0.25, control.height * 0.75).commit()
+ compare(firstPressedSpy.count, 2)
+ compare(secondPressedSpy.count, 0)
+ compare(control.first.pressed, false)
+ compare(control.first.value, 0.0)
+ compare(control.first.position, 0.0)
+ compare(control.second.pressed, false)
+ compare(control.second.value, 1.0)
+ compare(control.second.position, 1.0)
+
+ touch.press(0, control, control.width * 0.75, control.height * 0.25).commit()
+ compare(firstPressedSpy.count, 2)
+ compare(secondPressedSpy.count, 1)
+ compare(control.first.pressed, false)
+ compare(control.first.value, 0.0)
+ compare(control.first.position, 0.0)
+ compare(control.second.pressed, true)
+ compare(control.second.value, 1.0)
+ compare(control.second.position, 1.0)
+
+ touch.release(0, control, control.width * 0.75, control.height * 0.25).commit()
+ compare(firstPressedSpy.count, 2)
+ compare(secondPressedSpy.count, 2)
+ compare(control.first.pressed, false)
+ compare(control.first.value, 0.0)
+ compare(control.first.position, 0.0)
+ compare(control.second.pressed, false)
+ compare(control.second.value, 1.0)
+ compare(control.second.position, 1.0)
+
+ touch.press(0, control, 0, control.height).commit()
+ compare(firstPressedSpy.count, 3)
+ compare(secondPressedSpy.count, 2)
+ compare(control.first.pressed, true)
+ compare(control.first.value, 0.0)
+ compare(control.first.position, 0.0)
+ compare(control.second.pressed, false)
+ compare(control.second.value, 1.0)
+ compare(control.second.position, 1.0)
+
+ touch.release(0, control, 0, control.height).commit()
+ compare(firstPressedSpy.count, 4)
+ compare(secondPressedSpy.count, 2)
+ compare(control.first.pressed, false)
+ compare(control.first.value, 0.0)
+ compare(control.first.position, 0.0)
+ compare(control.second.pressed, false)
+ compare(control.second.value, 1.0)
+ compare(control.second.position, 1.0)
+
+ touch.press(0, control, control.first.handle.x, control.first.handle.y).commit()
+ compare(firstPressedSpy.count, 5)
+ compare(secondPressedSpy.count, 2)
+ compare(control.first.pressed, true)
+ compare(control.first.value, 0.0)
+ compare(control.first.position, 0.0)
+ compare(control.second.pressed, false)
+ compare(control.second.value, 1.0)
+ compare(control.second.position, 1.0)
+
+ var horizontal = control.orientation === Qt.Horizontal
+ var toX = horizontal ? control.width * 0.5 : control.first.handle.x
+ var toY = horizontal ? control.first.handle.y : control.height * 0.5
+ touch.move(0, control, toX, toY).commit()
+ compare(firstPressedSpy.count, 5)
+ compare(secondPressedSpy.count, 2)
+ compare(control.first.pressed, true)
+ compare(control.first.value, data.live ? 0.5 : 0.0)
+ compare(control.first.position, 0.5)
+ compare(control.first.visualPosition, 0.5)
+ compare(control.second.pressed, false)
+ compare(control.second.value, 1.0)
+ compare(control.second.position, 1.0)
+ compare(control.second.visualPosition, horizontal ? 1.0 : 0.0)
+
+ touch.release(0, control, toX, toY).commit()
+ compare(firstPressedSpy.count, 6)
+ compare(secondPressedSpy.count, 2)
+ compare(control.first.pressed, false)
+ compare(control.first.value, 0.5)
+ compare(control.first.position, 0.5)
+ compare(control.first.visualPosition, 0.5)
+ compare(control.second.pressed, false)
+ compare(control.second.value, 1.0)
+ compare(control.second.position, 1.0)
+ compare(control.second.visualPosition, horizontal ? 1.0 : 0.0)
+ }
+
+ function test_multiTouch() {
+ var control1 = createTemporaryObject(sliderComponent, testCase)
+ verify(control1)
+
+ // press and move the first handle of the first slider
+ var touch = touchEvent(control1)
+ touch.press(0, control1, 0, 0).commit().move(0, control1, control1.width / 2, control1.height / 2).commit()
+ compare(control1.first.pressed, true)
+ compare(control1.first.position, 0.5)
+ compare(control1.second.pressed, false)
+ compare(control1.second.position, 1.0)
+
+ // press and move the second handle of the first slider
+ touch.stationary(0).press(1, control1, control1.width, control1.height).commit()
+ touch.stationary(0).move(1, control1, control1.width / 2, control1.height / 2).commit()
+ compare(control1.first.pressed, true)
+ compare(control1.first.position, 0.5)
+ compare(control1.second.pressed, true)
+ compare(control1.second.position, 0.5)
+
+ var control2 = createTemporaryObject(sliderComponent, testCase, {y: control1.height})
+ verify(control2)
+ waitForRendering(control2)
+
+ // press and move the first handle of the second slider
+ touch.stationary(0).stationary(1).press(2, control2, 0, 0).commit()
+ touch.stationary(0).stationary(1).move(2, control2, control2.width / 2, control2.height / 2).commit()
+ compare(control1.first.pressed, true)
+ compare(control1.first.position, 0.5)
+ compare(control1.second.pressed, true)
+ compare(control1.second.position, 0.5)
+ compare(control2.first.pressed, true)
+ compare(control2.first.position, 0.5)
+ compare(control2.second.pressed, false)
+ compare(control2.second.position, 1.0)
+
+ // press and move the second handle of the second slider
+ touch.stationary(0).stationary(1).stationary(2).press(3, control2, control2.width, control2.height).commit()
+ touch.stationary(0).stationary(1).stationary(2).move(3, control2, control2.width / 2, control2.height / 2).commit()
+ compare(control1.first.pressed, true)
+ compare(control1.first.position, 0.5)
+ compare(control1.second.pressed, true)
+ compare(control1.second.position, 0.5)
+ compare(control2.first.pressed, true)
+ compare(control2.first.position, 0.5)
+ compare(control2.second.pressed, true)
+ compare(control2.second.position, 0.5)
+
+ // release the both handles of the both sliders
+ touch.release(0, control1).release(1, control1).release(2, control2).release(3, control2).commit()
+ compare(control1.first.pressed, false)
+ compare(control1.first.position, 0.5)
+ compare(control1.second.pressed, false)
+ compare(control1.second.position, 0.5)
+ compare(control2.first.pressed, false)
+ compare(control2.first.position, 0.5)
+ compare(control2.second.pressed, false)
+ compare(control2.second.position, 0.5)
}
function test_overlappingHandles() {
- var control = sliderComponent.createObject(testCase, { orientation: data.orientation })
+ var control = createTemporaryObject(sliderComponent, testCase, { orientation: data.orientation })
verify(control)
// By default, we force the second handle to be after the first in
@@ -436,8 +600,6 @@ TestCase {
verify(!control.first.pressed)
compare(control.first.handle.z, 1)
compare(control.second.handle.z, 0)
-
- control.destroy()
}
function test_keys_data() {
@@ -448,7 +610,7 @@ TestCase {
}
function test_keys(data) {
- var control = sliderComponent.createObject(testCase, { orientation: data.orientation })
+ var control = createTemporaryObject(sliderComponent, testCase, { orientation: data.orientation })
verify(control)
var pressedCount = 0
@@ -522,15 +684,13 @@ TestCase {
compare(control.second.pressed, false)
compare(secondPressedSpy.count, ++pressedCount)
}
-
- control.destroy()
}
function test_padding() {
// test with "unbalanced" paddings (left padding != right padding) to ensure
// that the slider position calculation is done taking padding into account
// ==> the position is _not_ 0.5 in the middle of the control
- var control = sliderComponent.createObject(testCase, { leftPadding: 10, rightPadding: 20 })
+ var control = createTemporaryObject(sliderComponent, testCase, { leftPadding: 10, rightPadding: 20 })
verify(control)
var firstPressedSpy = signalSpy.createObject(control, {target: control.first, signalName: "pressedChanged"})
@@ -595,8 +755,6 @@ TestCase {
compare(control.first.value, 0.5)
compare(control.first.position, 0.5)
compare(control.first.visualPosition, 0.5)
-
- control.destroy()
}
function test_snapMode_data() {
@@ -613,8 +771,12 @@ TestCase {
]
}
- function test_snapMode(data) {
- var control = sliderComponent.createObject(testCase, {snapMode: data.snapMode, from: data.from, to: data.to, stepSize: 0.2})
+ function test_snapMode_mouse_data() {
+ return test_snapMode_data()
+ }
+
+ function test_snapMode_mouse(data) {
+ var control = createTemporaryObject(sliderComponent, testCase, {snapMode: data.snapMode, from: data.from, to: data.to, stepSize: 0.2})
verify(control)
control.first.value = 0
@@ -638,12 +800,42 @@ TestCase {
compare(control.first.pressed, false)
verify(sliderCompare(control.first.value, data.values[2]))
verify(sliderCompare(control.first.position, data.positions[2]))
+ }
+
+ function test_snapMode_touch_data() {
+ return test_snapMode_data()
+ }
+
+ function test_snapMode_touch(data) {
+ var control = createTemporaryObject(sliderComponent, testCase, {snapMode: data.snapMode, from: data.from, to: data.to, stepSize: 0.2})
+ verify(control)
+
+ control.first.value = 0
+ control.second.value = data.to
- control.destroy()
+ function sliderCompare(left, right) {
+ return Math.abs(left - right) < 0.05
+ }
+
+ var touch = touchEvent(control)
+ touch.press(0, control, control.first.handle.x, control.first.handle.y).commit()
+ compare(control.first.pressed, true)
+ compare(control.first.value, data.values[0])
+ compare(control.first.position, data.positions[0])
+
+ touch.move(0, control, control.leftPadding + 0.15 * (control.availableWidth + control.first.handle.width / 2)).commit()
+ compare(control.first.pressed, true)
+ verify(sliderCompare(control.first.value, data.values[1]))
+ verify(sliderCompare(control.first.position, data.positions[1]))
+
+ touch.release(0, control, control.leftPadding + 0.15 * (control.availableWidth + control.first.handle.width / 2)).commit()
+ compare(control.first.pressed, false)
+ verify(sliderCompare(control.first.value, data.values[2]))
+ verify(sliderCompare(control.first.position, data.positions[2]))
}
function test_focus() {
- var control = sliderComponent.createObject(testCase)
+ var control = createTemporaryObject(sliderComponent, testCase)
verify(control)
waitForRendering(control)
@@ -672,8 +864,6 @@ TestCase {
compare(control.activeFocus, true)
compare(control.first.handle.activeFocus, false)
compare(control.second.handle.activeFocus, true)
-
- control.destroy()
}
function test_hover_data() {
@@ -686,7 +876,7 @@ TestCase {
}
function test_hover(data) {
- var control = sliderComponent.createObject(testCase, {hoverEnabled: data.hoverEnabled})
+ var control = createTemporaryObject(sliderComponent, testCase, {hoverEnabled: data.hoverEnabled})
verify(control)
var node = control[data.node]
@@ -699,7 +889,5 @@ TestCase {
mouseMove(control, node.handle.x - 1, node.handle.y - 1)
compare(node.hovered, false)
-
- control.destroy()
}
}
diff --git a/tests/auto/controls/data/tst_roundbutton.qml b/tests/auto/controls/data/tst_roundbutton.qml
index e3844523..4f90eea1 100644
--- a/tests/auto/controls/data/tst_roundbutton.qml
+++ b/tests/auto/controls/data/tst_roundbutton.qml
@@ -56,7 +56,7 @@ TestCase {
}
function test_radius() {
- var control = roundButton.createObject(testCase);
+ var control = createTemporaryObject(roundButton, testCase);
verify(control);
var implicitRadius = control.radius;
@@ -73,7 +73,5 @@ TestCase {
control.width = 10;
compare(control.radius, 5);
-
- control.destroy();
}
}
diff --git a/tests/auto/controls/data/tst_scrollbar.qml b/tests/auto/controls/data/tst_scrollbar.qml
index 92fe8496..8727b6da 100644
--- a/tests/auto/controls/data/tst_scrollbar.qml
+++ b/tests/auto/controls/data/tst_scrollbar.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.1
+import QtQuick.Controls 2.2
TestCase {
id: testCase
@@ -73,7 +73,7 @@ TestCase {
}
function test_attach() {
- var container = flickable.createObject(testCase)
+ var container = createTemporaryObject(flickable, testCase)
verify(container)
waitForRendering(container)
@@ -105,7 +105,7 @@ TestCase {
container.width += 10
compare(vertical.x, 123)
- var horizontal = scrollBar.createObject()
+ var horizontal = createTemporaryObject(scrollBar, null)
verify(!horizontal.parent)
compare(horizontal.size, 0.0)
compare(horizontal.position, 0.0)
@@ -170,8 +170,6 @@ TestCase {
container.width += 10
compare(horizontal.x, oldX - 10)
compare(horizontal.width, oldWidth)
-
- container.destroy()
}
function test_mouse_data() {
@@ -182,7 +180,7 @@ TestCase {
}
function test_mouse(data) {
- var control = scrollBar.createObject(testCase, data.properties)
+ var control = createTemporaryObject(scrollBar, testCase, data.properties)
verify(control)
var pressedSpy = signalSpy.createObject(control, {target: control, signalName: "pressedChanged"})
@@ -227,8 +225,6 @@ TestCase {
compare(pressedSpy.count, 4)
compare(control.pressed, false)
compare(control.position, 0.25)
-
- control.destroy()
}
function test_increase_decrease_data() {
@@ -241,7 +237,7 @@ TestCase {
}
function test_increase_decrease(data) {
- var control = scrollBar.createObject(testCase, {position: 0.5, active: data.active})
+ var control = createTemporaryObject(scrollBar, testCase, {position: 0.5, active: data.active})
verify(control)
if (data.increase) {
@@ -252,8 +248,6 @@ TestCase {
compare(control.position, 0.4)
}
compare(control.active, data.active)
-
- control.destroy()
}
function test_stepSize_data() {
@@ -265,7 +259,7 @@ TestCase {
}
function test_stepSize(data) {
- var control = scrollBar.createObject(testCase, {stepSize: data.stepSize})
+ var control = createTemporaryObject(scrollBar, testCase, {stepSize: data.stepSize})
verify(control)
compare(control.stepSize, data.stepSize)
@@ -290,8 +284,6 @@ TestCase {
}
control.decrease()
compare(control.position, 0.0)
-
- control.destroy()
}
function test_padding_data() {
@@ -302,14 +294,12 @@ TestCase {
}
function test_padding(data) {
- var control = scrollBar.createObject(testCase, data.properties)
+ var control = createTemporaryObject(scrollBar, testCase, data.properties)
mousePress(control, control.leftPadding + control.availableWidth * 0.5, control.topPadding + control.availableHeight * 0.5, Qt.LeftButton)
mouseRelease(control, control.leftPadding + control.availableWidth * 0.5, control.topPadding + control.availableHeight * 0.5, Qt.LeftButton)
compare(control.position, 0.5)
-
- control.destroy()
}
function test_warning() {
@@ -318,7 +308,7 @@ TestCase {
}
function test_mirrored() {
- var container = flickable.createObject(testCase)
+ var container = createTemporaryObject(flickable, testCase)
verify(container)
waitForRendering(container)
@@ -326,8 +316,6 @@ TestCase {
compare(container.ScrollBar.vertical.x, container.width - container.ScrollBar.vertical.width)
container.ScrollBar.vertical.locale = Qt.locale("ar_EG")
compare(container.ScrollBar.vertical.x, 0)
-
- container.destroy()
}
function test_hover_data() {
@@ -338,7 +326,7 @@ TestCase {
}
function test_hover(data) {
- var control = scrollBar.createObject(testCase, {hoverEnabled: data.hoverEnabled})
+ var control = createTemporaryObject(scrollBar, testCase, {hoverEnabled: data.hoverEnabled})
verify(control)
compare(control.hovered, false)
@@ -350,7 +338,76 @@ TestCase {
mouseMove(control, -1, -1)
compare(control.hovered, false)
compare(control.active, false)
+ }
+
+ function test_snapMode_data() {
+ return [
+ { tag: "NoSnap", snapMode: ScrollBar.NoSnap, stepSize: 0.1, size: 0.2, width: 100, steps: 80 }, /* 0.8*100 */
+ { tag: "NoSnap2", snapMode: ScrollBar.NoSnap, stepSize: 0.2, size: 0.1, width: 200, steps: 180 }, /* 0.9*200 */
+
+ { tag: "SnapAlways", snapMode: ScrollBar.SnapAlways, stepSize: 0.1, size: 0.2, width: 100, steps: 10 },
+ { tag: "SnapAlways2", snapMode: ScrollBar.SnapAlways, stepSize: 0.2, size: 0.1, width: 200, steps: 5 },
+
+ { tag: "SnapOnRelease", snapMode: ScrollBar.SnapOnRelease, stepSize: 0.1, size: 0.2, width: 100, steps: 80 }, /* 0.8*100 */
+ { tag: "SnapOnRelease2", snapMode: ScrollBar.SnapOnRelease, stepSize: 0.2, size: 0.1, width: 200, steps: 180 }, /* 0.9*200 */
+ ]
+ }
+
+ function test_snapMode_mouse_data() {
+ return test_snapMode_data()
+ }
+
+ function test_snapMode_mouse(data) {
+ var control = createTemporaryObject(scrollBar, testCase, {snapMode: data.snapMode, orientation: Qt.Horizontal, stepSize: data.stepSize, size: data.size, width: data.width})
+ verify(control)
+
+ function snappedPosition(pos) {
+ var effectiveStep = control.stepSize * (1.0 - control.size)
+ return Math.round(pos / effectiveStep) * effectiveStep
+ }
+
+ function boundPosition(pos) {
+ return Math.max(0, Math.min(pos, 1.0 - control.size))
+ }
+
+ mousePress(control, 0, 0)
+ compare(control.position, 0)
+
+ mouseMove(control, control.width * 0.3, 0)
+ var expectedMovePos = 0.3
+ if (control.snapMode === ScrollBar.SnapAlways) {
+ expectedMovePos = snappedPosition(expectedMovePos)
+ verify(expectedMovePos !== 0.3)
+ }
+ compare(control.position, expectedMovePos)
+
+ mouseRelease(control, control.width * 0.75, 0)
+ var expectedReleasePos = 0.75
+ if (control.snapMode !== ScrollBar.NoSnap) {
+ expectedReleasePos = snappedPosition(expectedReleasePos)
+ verify(expectedReleasePos !== 0.75)
+ }
+ compare(control.position, expectedReleasePos)
+
+ control.position = 0
+ mousePress(control, 0, 0)
+
+ var steps = 0
+ var prevPos = 0
+
+ for (var x = 0; x < control.width; ++x) {
+ mouseMove(control, x, 0)
+ expectedMovePos = boundPosition(x / control.width)
+ if (control.snapMode === ScrollBar.SnapAlways)
+ expectedMovePos = snappedPosition(expectedMovePos)
+ compare(control.position, expectedMovePos)
+
+ if (control.position !== prevPos)
+ ++steps
+ prevPos = control.position
+ }
+ compare(steps, data.steps)
- control.destroy()
+ mouseRelease(control, control.width - 1, 0)
}
}
diff --git a/tests/auto/controls/data/tst_scrollindicator.qml b/tests/auto/controls/data/tst_scrollindicator.qml
index 1f86311a..cf0c9a27 100644
--- a/tests/auto/controls/data/tst_scrollindicator.qml
+++ b/tests/auto/controls/data/tst_scrollindicator.qml
@@ -68,11 +68,11 @@ TestCase {
}
function test_attach() {
- var container = flickable.createObject(testCase)
+ var container = createTemporaryObject(flickable, testCase)
verify(container)
waitForRendering(container)
- var vertical = scrollIndicator.createObject()
+ var vertical = createTemporaryObject(scrollIndicator, null)
verify(!vertical.parent)
compare(vertical.size, 0.0)
compare(vertical.position, 0.0)
@@ -100,7 +100,7 @@ TestCase {
container.width += 10
compare(vertical.x, 123)
- var horizontal = scrollIndicator.createObject()
+ var horizontal = createTemporaryObject(scrollIndicator, null)
verify(!horizontal.parent)
compare(horizontal.size, 0.0)
compare(horizontal.position, 0.0)
@@ -165,8 +165,6 @@ TestCase {
container.width += 10
compare(horizontal.x, oldX - 10)
compare(horizontal.width, oldWidth)
-
- container.destroy()
}
function test_warning() {
@@ -175,7 +173,7 @@ TestCase {
}
function test_overshoot() {
- var container = flickable.createObject(testCase)
+ var container = createTemporaryObject(flickable, testCase)
verify(container)
waitForRendering(container)
@@ -204,7 +202,5 @@ TestCase {
horizontal.position = 0.8
compare(horizontal.contentItem.x, horizontal.leftPadding + 0.8 * horizontal.availableWidth)
compare(horizontal.contentItem.width, 0.2 * horizontal.availableWidth)
-
- container.destroy()
}
}
diff --git a/tests/auto/controls/data/tst_slider.qml b/tests/auto/controls/data/tst_slider.qml
index 92560001..1dec038e 100644
--- a/tests/auto/controls/data/tst_slider.qml
+++ b/tests/auto/controls/data/tst_slider.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.1
+import QtQuick.Controls 2.2
TestCase {
id: testCase
@@ -61,18 +61,16 @@ TestCase {
}
function test_defaults() {
- var control = slider.createObject(testCase)
+ var control = createTemporaryObject(slider, testCase)
verify(control)
compare(control.stepSize, 0)
compare(control.snapMode, Slider.NoSnap)
compare(control.orientation, Qt.Horizontal)
-
- control.destroy()
}
function test_value() {
- var control = slider.createObject(testCase)
+ var control = createTemporaryObject(slider, testCase)
verify(control)
compare(control.value, 0.0)
@@ -84,12 +82,10 @@ TestCase {
compare(control.value, 0.0)
control.value = 2.0
compare(control.value, 1.0)
-
- control.destroy()
}
function test_range() {
- var control = slider.createObject(testCase, {from: 0, to: 100, value: 50})
+ var control = createTemporaryObject(slider, testCase, {from: 0, to: 100, value: 50})
verify(control)
compare(control.from, 0)
@@ -118,12 +114,10 @@ TestCase {
control.value = 50
compare(control.value, 50)
compare(control.position, 0.5)
-
- control.destroy()
}
function test_inverted() {
- var control = slider.createObject(testCase, {from: 1.0, to: -1.0})
+ var control = createTemporaryObject(slider, testCase, {from: 1.0, to: -1.0})
verify(control)
compare(control.from, 1.0)
@@ -142,12 +136,10 @@ TestCase {
control.value = 0.0
compare(control.value, 0.0)
compare(control.position, 0.5)
-
- control.destroy()
}
function test_position() {
- var control = slider.createObject(testCase)
+ var control = createTemporaryObject(slider, testCase)
verify(control)
compare(control.value, 0.0)
@@ -160,12 +152,10 @@ TestCase {
control.value = 0.75
compare(control.value, 0.75)
compare(control.position, 0.75)
-
- control.destroy()
}
function test_visualPosition() {
- var control = slider.createObject(testCase)
+ var control = createTemporaryObject(slider, testCase)
verify(control)
compare(control.value, 0.0)
@@ -194,12 +184,10 @@ TestCase {
// LayoutMirroring
control.LayoutMirroring.enabled = true
compare(control.visualPosition, 0.75)
-
- control.destroy()
}
function test_orientation() {
- var control = slider.createObject(testCase)
+ var control = createTemporaryObject(slider, testCase)
verify(control)
compare(control.orientation, Qt.Horizontal)
@@ -207,70 +195,84 @@ TestCase {
control.orientation = Qt.Vertical
compare(control.orientation, Qt.Vertical)
verify(control.width < control.height)
-
- control.destroy()
}
function test_mouse_data() {
return [
- { tag: "horizontal", orientation: Qt.Horizontal },
- { tag: "vertical", orientation: Qt.Vertical }
+ { tag: "horizontal", orientation: Qt.Horizontal, live: false },
+ { tag: "vertical", orientation: Qt.Vertical, live: false },
+ { tag: "horizontal:live", orientation: Qt.Horizontal, live: true },
+ { tag: "vertical:live", orientation: Qt.Vertical, live: true }
]
}
function test_mouse(data) {
- var control = slider.createObject(testCase, {orientation: data.orientation})
+ var control = createTemporaryObject(slider, testCase, {orientation: data.orientation, live: data.live})
verify(control)
+ var pressedCount = 0
+ var movedCount = 0
+
var pressedSpy = signalSpy.createObject(control, {target: control, signalName: "pressedChanged"})
verify(pressedSpy.valid)
+ var movedSpy = signalSpy.createObject(control, {target: control, signalName: "moved"})
+ verify(movedSpy.valid)
+
mousePress(control, 0, 0, Qt.LeftButton)
- compare(pressedSpy.count, 1)
+ compare(pressedSpy.count, ++pressedCount)
+ compare(movedSpy.count, movedCount)
compare(control.pressed, true)
compare(control.value, 0.0)
compare(control.position, 0.0)
// mininum on the left in horizontal vs. at the bottom in vertical
mouseMove(control, -control.width, 2 * control.height, 0, Qt.LeftButton)
- compare(pressedSpy.count, 1)
+ compare(pressedSpy.count, pressedCount)
+ compare(movedSpy.count, movedCount)
compare(control.pressed, true)
compare(control.value, 0.0)
compare(control.position, 0.0)
mouseMove(control, control.width * 0.5, control.height * 0.5, 0, Qt.LeftButton)
- compare(pressedSpy.count, 1)
+ compare(pressedSpy.count, pressedCount)
+ compare(movedSpy.count, ++movedCount)
compare(control.pressed, true)
- compare(control.value, 0.0)
- verify(control.position, 0.5)
+ compare(control.value, data.live ? 0.5 : 0.0)
+ compare(control.position, 0.5)
mouseRelease(control, control.width * 0.5, control.height * 0.5, Qt.LeftButton)
- compare(pressedSpy.count, 2)
+ compare(pressedSpy.count, ++pressedCount)
+ compare(movedSpy.count, movedCount)
compare(control.pressed, false)
compare(control.value, 0.5)
compare(control.position, 0.5)
mousePress(control, control.width, control.height, Qt.LeftButton)
- compare(pressedSpy.count, 3)
+ compare(pressedSpy.count, ++pressedCount)
+ compare(movedSpy.count, movedCount)
compare(control.pressed, true)
compare(control.value, 0.5)
compare(control.position, 0.5)
// maximum on the right in horizontal vs. at the top in vertical
mouseMove(control, control.width * 2, -control.height, 0, Qt.LeftButton)
- compare(pressedSpy.count, 3)
+ compare(pressedSpy.count, pressedCount)
+ compare(movedSpy.count, ++movedCount)
compare(control.pressed, true)
- compare(control.value, 0.5)
+ compare(control.value, data.live ? 1.0 : 0.5)
compare(control.position, 1.0)
mouseMove(control, control.width * 0.75, control.height * 0.25, 0, Qt.LeftButton)
- compare(pressedSpy.count, 3)
+ compare(pressedSpy.count, pressedCount)
+ compare(movedSpy.count, ++movedCount)
compare(control.pressed, true)
- compare(control.value, 0.5)
+ compare(control.value, data.live ? control.position : 0.5)
verify(control.position >= 0.75)
mouseRelease(control, control.width * 0.25, control.height * 0.75, Qt.LeftButton)
- compare(pressedSpy.count, 4)
+ compare(pressedSpy.count, ++pressedCount)
+ compare(movedSpy.count, ++movedCount)
compare(control.pressed, false)
compare(control.value, control.position)
verify(control.value <= 0.25 && control.value >= 0.0)
@@ -278,11 +280,188 @@ TestCase {
// QTBUG-53846
mouseClick(control, control.width * 0.5, control.height * 0.5, Qt.LeftButton)
- compare(pressedSpy.count, 6)
+ compare(movedSpy.count, ++movedCount)
+ compare(pressedSpy.count, pressedCount += 2)
+ compare(control.value, 0.5)
+ compare(control.position, 0.5)
+ }
+
+ function test_touch_data() {
+ return [
+ { tag: "horizontal", orientation: Qt.Horizontal, live: false },
+ { tag: "vertical", orientation: Qt.Vertical, live: false },
+ { tag: "horizontal:live", orientation: Qt.Horizontal, live: true },
+ { tag: "vertical:live", orientation: Qt.Vertical, live: true }
+ ]
+ }
+
+ function test_touch(data) {
+ var control = createTemporaryObject(slider, testCase, {orientation: data.orientation, live: data.live})
+ verify(control)
+
+ var pressedCount = 0
+ var movedCount = 0
+
+ var pressedSpy = signalSpy.createObject(control, {target: control, signalName: "pressedChanged"})
+ verify(pressedSpy.valid)
+
+ var movedSpy = signalSpy.createObject(control, {target: control, signalName: "moved"})
+ verify(movedSpy.valid)
+
+ var touch = touchEvent(control)
+ touch.press(0, control, 0, 0).commit()
+ compare(pressedSpy.count, ++pressedCount)
+ compare(movedSpy.count, movedCount)
+ compare(control.pressed, true)
+ compare(control.value, 0.0)
+ compare(control.position, 0.0)
+
+ // mininum on the left in horizontal vs. at the bottom in vertical
+ touch.move(0, control, -control.width, 2 * control.height, 0).commit()
+ compare(pressedSpy.count, pressedCount)
+ compare(movedSpy.count, movedCount)
+ compare(control.pressed, true)
+ compare(control.value, 0.0)
+ compare(control.position, 0.0)
+
+ touch.move(0, control, control.width * 0.5, control.height * 0.5, 0).commit()
+ compare(pressedSpy.count, pressedCount)
+ compare(movedSpy.count, ++movedCount)
+ compare(control.pressed, true)
+ compare(control.value, data.live ? 0.5 : 0.0)
+ compare(control.position, 0.5)
+
+ touch.release(0, control, control.width * 0.5, control.height * 0.5).commit()
+ compare(pressedSpy.count, ++pressedCount)
+ compare(movedSpy.count, movedCount)
+ compare(control.pressed, false)
+ compare(control.value, 0.5)
+ compare(control.position, 0.5)
+
+ touch.press(0, control, control.width, control.height).commit()
+ compare(pressedSpy.count, ++pressedCount)
+ compare(movedSpy.count, movedCount)
+ compare(control.pressed, true)
+ compare(control.value, 0.5)
+ compare(control.position, 0.5)
+
+ // maximum on the right in horizontal vs. at the top in vertical
+ touch.move(0, control, control.width * 2, -control.height, 0).commit()
+ compare(pressedSpy.count, pressedCount)
+ compare(movedSpy.count, ++movedCount)
+ compare(control.pressed, true)
+ compare(control.value, data.live ? 1.0 : 0.5)
+ compare(control.position, 1.0)
+
+ touch.move(0, control, control.width * 0.75, control.height * 0.25, 0).commit()
+ compare(pressedSpy.count, pressedCount)
+ compare(movedSpy.count, ++movedCount)
+ compare(control.pressed, true)
+ compare(control.value, data.live ? control.position : 0.5)
+ verify(control.position >= 0.75)
+
+ touch.release(0, control, control.width * 0.25, control.height * 0.75).commit()
+ compare(pressedSpy.count, ++pressedCount)
+ compare(movedSpy.count, ++movedCount)
+ compare(control.pressed, false)
+ compare(control.value, control.position)
+ verify(control.value <= 0.25 && control.value >= 0.0)
+ verify(control.position <= 0.25 && control.position >= 0.0)
+
+ // QTBUG-53846
+ touch.press(0, control).commit().release(0, control).commit()
+ compare(movedSpy.count, ++movedCount)
+ compare(pressedSpy.count, pressedCount += 2)
compare(control.value, 0.5)
compare(control.position, 0.5)
+ }
+
+ function test_multiTouch() {
+ var control1 = createTemporaryObject(slider, testCase)
+ verify(control1)
+
+ var pressedCount1 = 0
+ var movedCount1 = 0
+
+ var pressedSpy1 = signalSpy.createObject(control1, {target: control1, signalName: "pressedChanged"})
+ verify(pressedSpy1.valid)
+
+ var movedSpy1 = signalSpy.createObject(control1, {target: control1, signalName: "moved"})
+ verify(movedSpy1.valid)
+
+ var touch = touchEvent(control1)
+ touch.press(0, control1, 0, 0).commit().move(0, control1, control1.width, control1.height).commit()
+
+ compare(pressedSpy1.count, ++pressedCount1)
+ compare(movedSpy1.count, ++movedCount1)
+ compare(control1.pressed, true)
+ compare(control1.position, 1.0)
+
+ // second touch point on the same control is ignored
+ touch.stationary(0).press(1, control1, 0, 0).commit()
+ touch.stationary(0).move(1, control1).commit()
+ touch.stationary(0).release(1).commit()
+
+ compare(pressedSpy1.count, pressedCount1)
+ compare(movedSpy1.count, movedCount1)
+ compare(control1.pressed, true)
+ compare(control1.position, 1.0)
+
+ var control2 = createTemporaryObject(slider, testCase, {y: control1.height})
+ verify(control2)
+ waitForRendering(control2)
+
+ var pressedCount2 = 0
+ var movedCount2 = 0
+
+ var pressedSpy2 = signalSpy.createObject(control2, {target: control2, signalName: "pressedChanged"})
+ verify(pressedSpy2.valid)
+
+ var movedSpy2 = signalSpy.createObject(control2, {target: control2, signalName: "moved"})
+ verify(movedSpy2.valid)
+
+ // press the second slider
+ touch.stationary(0).press(2, control2, 0, 0).commit()
+
+ compare(pressedSpy2.count, ++pressedCount2)
+ compare(movedSpy2.count, movedCount2)
+ compare(control2.pressed, true)
+ compare(control2.position, 0.0)
+
+ compare(pressedSpy1.count, pressedCount1)
+ compare(movedSpy1.count, movedCount1)
+ compare(control1.pressed, true)
+ compare(control1.position, 1.0)
+
+ // move both sliders
+ touch.move(0, control1).move(2, control2).commit()
+
+ compare(pressedSpy2.count, pressedCount2)
+ compare(movedSpy2.count, ++movedCount2)
+ compare(control2.pressed, true)
+ compare(control2.position, 0.5)
+ compare(control2.value, 0.0)
+
+ compare(pressedSpy1.count, pressedCount1)
+ compare(movedSpy1.count, ++movedCount1)
+ compare(control1.pressed, true)
+ compare(control1.position, 0.5)
+ compare(control1.value, 0.0)
+
+ // release both sliders
+ touch.release(0, control1).release(2, control2).commit()
+
+ compare(pressedSpy2.count, ++pressedCount2)
+ compare(movedSpy2.count, movedCount2)
+ compare(control2.pressed, false)
+ compare(control2.position, 0.5)
+ compare(control2.value, 0.5)
- control.destroy()
+ compare(pressedSpy1.count, ++pressedCount1)
+ compare(movedSpy1.count, movedCount1)
+ compare(control1.pressed, false)
+ compare(control1.position, 0.5)
+ compare(control1.value, 0.5)
}
function test_keys_data() {
@@ -293,23 +472,31 @@ TestCase {
}
function test_keys(data) {
- var control = slider.createObject(testCase, {orientation: data.orientation})
+ var control = createTemporaryObject(slider, testCase, {orientation: data.orientation})
verify(control)
var pressedCount = 0
+ var movedCount = 0
var pressedSpy = signalSpy.createObject(control, {target: control, signalName: "pressedChanged"})
verify(pressedSpy.valid)
+ var movedSpy = signalSpy.createObject(control, {target: control, signalName: "moved"})
+ verify(movedSpy.valid)
+
control.forceActiveFocus()
verify(control.activeFocus)
+ var oldValue = 0.0
control.value = 0.5
for (var d1 = 1; d1 <= 10; ++d1) {
+ oldValue = control.value
keyPress(data.decrease)
compare(control.pressed, true)
compare(pressedSpy.count, ++pressedCount)
+ if (oldValue !== control.value)
+ compare(movedSpy.count, ++movedCount)
compare(control.value, Math.max(0.0, 0.5 - d1 * 0.1))
compare(control.value, control.position)
@@ -317,12 +504,16 @@ TestCase {
keyRelease(data.decrease)
compare(control.pressed, false)
compare(pressedSpy.count, ++pressedCount)
+ compare(movedSpy.count, movedCount)
}
for (var i1 = 1; i1 <= 20; ++i1) {
+ oldValue = control.value
keyPress(data.increase)
compare(control.pressed, true)
compare(pressedSpy.count, ++pressedCount)
+ if (oldValue !== control.value)
+ compare(movedSpy.count, ++movedCount)
compare(control.value, Math.min(1.0, 0.0 + i1 * 0.1))
compare(control.value, control.position)
@@ -330,14 +521,18 @@ TestCase {
keyRelease(data.increase)
compare(control.pressed, false)
compare(pressedSpy.count, ++pressedCount)
+ compare(movedSpy.count, movedCount)
}
control.stepSize = 0.25
for (var d2 = 1; d2 <= 10; ++d2) {
+ oldValue = control.value
keyPress(data.decrease)
compare(control.pressed, true)
compare(pressedSpy.count, ++pressedCount)
+ if (oldValue !== control.value)
+ compare(movedSpy.count, ++movedCount)
compare(control.value, Math.max(0.0, 1.0 - d2 * 0.25))
compare(control.value, control.position)
@@ -345,12 +540,16 @@ TestCase {
keyRelease(data.decrease)
compare(control.pressed, false)
compare(pressedSpy.count, ++pressedCount)
+ compare(movedSpy.count, movedCount)
}
for (var i2 = 1; i2 <= 10; ++i2) {
+ oldValue = control.value
keyPress(data.increase)
compare(control.pressed, true)
compare(pressedSpy.count, ++pressedCount)
+ if (oldValue !== control.value)
+ compare(movedSpy.count, ++movedCount)
compare(control.value, Math.min(1.0, 0.0 + i2 * 0.25))
compare(control.value, control.position)
@@ -358,16 +557,15 @@ TestCase {
keyRelease(data.increase)
compare(control.pressed, false)
compare(pressedSpy.count, ++pressedCount)
+ compare(movedSpy.count, movedCount)
}
-
- control.destroy()
}
function test_padding() {
// test with "unbalanced" paddings (left padding != right padding) to ensure
// that the slider position calculation is done taking padding into account
// ==> the position is _not_ 0.5 in the middle of the control
- var control = slider.createObject(testCase, {leftPadding: 10, rightPadding: 20})
+ var control = createTemporaryObject(slider, testCase, {leftPadding: 10, rightPadding: 20})
verify(control)
var pressedSpy = signalSpy.createObject(control, {target: control, signalName: "pressedChanged"})
@@ -432,8 +630,6 @@ TestCase {
compare(control.value, 0.5)
compare(control.position, 0.5)
compare(control.visualPosition, 0.5)
-
- control.destroy()
}
function test_snapMode_data() {
@@ -450,8 +646,12 @@ TestCase {
]
}
- function test_snapMode(data) {
- var control = slider.createObject(testCase, {snapMode: data.snapMode, from: data.from, to: data.to, stepSize: 0.2})
+ function test_snapMode_mouse_data() {
+ return test_snapMode_data()
+ }
+
+ function test_snapMode_mouse(data) {
+ var control = createTemporaryObject(slider, testCase, {snapMode: data.snapMode, from: data.from, to: data.to, stepSize: 0.2})
verify(control)
function sliderCompare(left, right) {
@@ -470,8 +670,33 @@ TestCase {
mouseRelease(control, control.leftPadding + 0.15 * (control.availableWidth + control.handle.width / 2))
verify(sliderCompare(control.value, data.values[2]))
verify(sliderCompare(control.position, data.positions[2]))
+ }
+
+ function test_snapMode_touch_data() {
+ return test_snapMode_data()
+ }
+
+ function test_snapMode_touch(data) {
+ var control = createTemporaryObject(slider, testCase, {snapMode: data.snapMode, from: data.from, to: data.to, stepSize: 0.2})
+ verify(control)
+
+ function sliderCompare(left, right) {
+ return Math.abs(left - right) < 0.05
+ }
+
+ var touch = touchEvent(control)
+ touch.press(0, control, control.leftPadding).commit()
+ compare(control.value, data.values[0])
+ compare(control.position, data.positions[0])
+
+ touch.move(0, control, control.leftPadding + 0.15 * (control.availableWidth + control.handle.width / 2)).commit()
+
+ verify(sliderCompare(control.value, data.values[1]))
+ verify(sliderCompare(control.position, data.positions[1]))
- control.destroy()
+ touch.release(0, control, control.leftPadding + 0.15 * (control.availableWidth + control.handle.width / 2)).commit()
+ verify(sliderCompare(control.value, data.values[2]))
+ verify(sliderCompare(control.position, data.positions[2]))
}
function test_wheel_data() {
@@ -482,24 +707,37 @@ TestCase {
}
function test_wheel(data) {
- var control = slider.createObject(testCase, {wheelEnabled: true, orientation: data.orientation})
+ var control = createTemporaryObject(slider, testCase, {wheelEnabled: true, orientation: data.orientation})
verify(control)
+ var movedCount = 0
+ var movedSpy = signalSpy.createObject(control, {target: control, signalName: "moved"})
+ verify(movedSpy.valid)
+
compare(control.value, 0.0)
mouseWheel(control, control.width / 2, control.height / 2, data.dx, data.dy)
+ compare(movedSpy.count, ++movedCount)
compare(control.value, 0.1)
compare(control.position, 0.1)
control.stepSize = 0.2
mouseWheel(control, control.width / 2, control.height / 2, data.dx, data.dy)
+ compare(movedSpy.count, ++movedCount)
compare(control.value, 0.3)
compare(control.position, 0.3)
control.stepSize = 10.0
mouseWheel(control, control.width / 2, control.height / 2, -data.dx, -data.dy)
+ compare(movedSpy.count, ++movedCount)
+ compare(control.value, 0.0)
+ compare(control.position, 0.0)
+
+ // no change
+ mouseWheel(control, control.width / 2, control.height / 2, -data.dx, -data.dy)
+ compare(movedSpy.count, movedCount)
compare(control.value, 0.0)
compare(control.position, 0.0)
@@ -507,18 +745,19 @@ TestCase {
control.stepSize = 5.0
mouseWheel(control, control.width / 2, control.height / 2, data.dx, data.dy)
+ compare(movedSpy.count, ++movedCount)
compare(control.value, 5.0)
compare(control.position, 0.5)
mouseWheel(control, control.width / 2, control.height / 2, 0.5 * data.dx, 0.5 * data.dy)
+ compare(movedSpy.count, ++movedCount)
compare(control.value, 7.5)
compare(control.position, 0.75)
mouseWheel(control, control.width / 2, control.height / 2, -data.dx, -data.dy)
+ compare(movedSpy.count, ++movedCount)
compare(control.value, 2.5)
compare(control.position, 0.25)
-
- control.destroy()
}
function test_valueAt_data() {
@@ -530,14 +769,12 @@ TestCase {
}
function test_valueAt(data) {
- var control = slider.createObject(testCase, {from: data.from, to: data.to})
+ var control = createTemporaryObject(slider, testCase, {from: data.from, to: data.to})
verify(control)
compare(control.valueAt(0.0), data.values[0])
compare(control.valueAt(0.2), data.values[1])
compare(control.valueAt(0.5), data.values[2])
compare(control.valueAt(1.0), data.values[3])
-
- control.destroy()
}
}
diff --git a/tests/auto/controls/data/tst_spinbox.qml b/tests/auto/controls/data/tst_spinbox.qml
index 06426f40..850dd014 100644
--- a/tests/auto/controls/data/tst_spinbox.qml
+++ b/tests/auto/controls/data/tst_spinbox.qml
@@ -61,7 +61,7 @@ TestCase {
}
function test_defaults() {
- var control = spinBox.createObject(testCase)
+ var control = createTemporaryObject(spinBox, testCase)
verify(control)
compare(control.from, 0)
@@ -73,12 +73,10 @@ TestCase {
compare(control.up.indicator.enabled, true)
compare(control.down.pressed, false)
compare(control.down.indicator.enabled, false)
-
- control.destroy()
}
function test_value() {
- var control = spinBox.createObject(testCase)
+ var control = createTemporaryObject(spinBox, testCase)
verify(control)
compare(control.value, 0)
@@ -90,12 +88,10 @@ TestCase {
compare(control.value, 0)
control.value = 100
compare(control.value, 99)
-
- control.destroy()
}
function test_range() {
- var control = spinBox.createObject(testCase, {from: 0, to: 100, value: 50})
+ var control = createTemporaryObject(spinBox, testCase, {from: 0, to: 100, value: 50})
verify(control)
compare(control.from, 0)
@@ -135,12 +131,10 @@ TestCase {
compare(control.value, 40)
compare(control.up.indicator.enabled, false)
compare(control.down.indicator.enabled, true)
-
- control.destroy()
}
function test_inverted() {
- var control = spinBox.createObject(testCase, {from: 100, to: -100})
+ var control = createTemporaryObject(spinBox, testCase, {from: 100, to: -100})
verify(control)
compare(control.from, 100)
@@ -163,12 +157,10 @@ TestCase {
compare(control.value, 0)
compare(control.up.indicator.enabled, true)
compare(control.down.indicator.enabled, true)
-
- control.destroy()
}
function test_mouse() {
- var control = spinBox.createObject(testCase, {stepSize: 50})
+ var control = createTemporaryObject(spinBox, testCase, {stepSize: 50})
verify(control)
var upPressedSpy = signalSpy.createObject(control, {target: control.up, signalName: "pressedChanged"})
@@ -177,12 +169,16 @@ TestCase {
var downPressedSpy = signalSpy.createObject(control, {target: control.down, signalName: "pressedChanged"})
verify(downPressedSpy.valid)
+ var valueModifiedSpy = signalSpy.createObject(control, {target: control, signalName: "valueModified"})
+ verify(valueModifiedSpy.valid)
+
mousePress(control.up.indicator)
compare(upPressedSpy.count, 1)
compare(control.up.pressed, true)
compare(downPressedSpy.count, 0)
compare(control.down.pressed, false)
compare(control.value, 0)
+ compare(valueModifiedSpy.count, 0)
mouseRelease(control.up.indicator)
compare(upPressedSpy.count, 2)
@@ -190,6 +186,7 @@ TestCase {
compare(downPressedSpy.count, 0)
compare(control.down.pressed, false)
compare(control.value, 50)
+ compare(valueModifiedSpy.count, 1)
// Disable the up button and try again.
control.value = control.to
@@ -201,6 +198,7 @@ TestCase {
compare(downPressedSpy.count, 0)
compare(control.down.pressed, false)
compare(control.value, control.to)
+ compare(valueModifiedSpy.count, 1)
mouseRelease(control.up.indicator)
compare(upPressedSpy.count, 2)
@@ -208,6 +206,7 @@ TestCase {
compare(downPressedSpy.count, 0)
compare(control.down.pressed, false)
compare(control.value, control.to)
+ compare(valueModifiedSpy.count, 1)
control.value = 50;
mousePress(control.down.indicator)
@@ -216,6 +215,7 @@ TestCase {
compare(upPressedSpy.count, 2)
compare(control.up.pressed, false)
compare(control.value, 50)
+ compare(valueModifiedSpy.count, 1)
mouseRelease(control.down.indicator)
compare(downPressedSpy.count, 2)
@@ -223,6 +223,7 @@ TestCase {
compare(upPressedSpy.count, 2)
compare(control.up.pressed, false)
compare(control.value, 0)
+ compare(valueModifiedSpy.count, 2)
// Disable the down button and try again.
control.value = control.from
@@ -234,6 +235,7 @@ TestCase {
compare(upPressedSpy.count, 2)
compare(control.up.pressed, false)
compare(control.value, control.from)
+ compare(valueModifiedSpy.count, 2)
mouseRelease(control.down.indicator)
compare(downPressedSpy.count, 2)
@@ -241,16 +243,16 @@ TestCase {
compare(upPressedSpy.count, 2)
compare(control.up.pressed, false)
compare(control.value, control.from)
-
- control.destroy()
+ compare(valueModifiedSpy.count, 2)
}
function test_keys() {
- var control = spinBox.createObject(testCase)
+ var control = createTemporaryObject(spinBox, testCase)
verify(control)
var upPressedCount = 0
var downPressedCount = 0
+ var valueModifiedCount = 0
var upPressedSpy = signalSpy.createObject(control, {target: control.up, signalName: "pressedChanged"})
verify(upPressedSpy.valid)
@@ -258,6 +260,9 @@ TestCase {
var downPressedSpy = signalSpy.createObject(control, {target: control.down, signalName: "pressedChanged"})
verify(downPressedSpy.valid)
+ var valueModifiedSpy = signalSpy.createObject(control, {target: control, signalName: "valueModified"})
+ verify(valueModifiedSpy.valid)
+
control.forceActiveFocus()
verify(control.activeFocus)
@@ -269,6 +274,7 @@ TestCase {
compare(control.down.pressed, true)
compare(control.up.pressed, false)
compare(downPressedSpy.count, ++downPressedCount)
+ compare(valueModifiedSpy.count, ++valueModifiedCount)
compare(control.value, 50 - d1)
@@ -276,6 +282,7 @@ TestCase {
compare(control.down.pressed, false)
compare(control.up.pressed, false)
compare(downPressedSpy.count, ++downPressedCount)
+ compare(valueModifiedSpy.count, valueModifiedCount)
}
compare(control.value, 40)
@@ -284,6 +291,7 @@ TestCase {
compare(control.up.pressed, true)
compare(control.down.pressed, false)
compare(upPressedSpy.count, ++upPressedCount)
+ compare(valueModifiedSpy.count, ++valueModifiedCount)
compare(control.value, 40 + i1)
@@ -291,6 +299,7 @@ TestCase {
compare(control.down.pressed, false)
compare(control.up.pressed, false)
compare(upPressedSpy.count, ++upPressedCount)
+ compare(valueModifiedSpy.count, valueModifiedCount)
}
compare(control.value, 50)
@@ -302,9 +311,12 @@ TestCase {
keyPress(Qt.Key_Down)
compare(control.down.pressed, wasDownEnabled)
compare(control.up.pressed, false)
- if (wasDownEnabled)
+ if (wasDownEnabled) {
++downPressedCount
+ ++valueModifiedCount
+ }
compare(downPressedSpy.count, downPressedCount)
+ compare(valueModifiedSpy.count, valueModifiedCount)
compare(control.value, Math.max(0, 50 - d2 * 25))
@@ -314,6 +326,7 @@ TestCase {
if (wasDownEnabled)
++downPressedCount
compare(downPressedSpy.count, downPressedCount)
+ compare(valueModifiedSpy.count, valueModifiedCount)
}
compare(control.value, 0)
@@ -322,9 +335,12 @@ TestCase {
keyPress(Qt.Key_Up)
compare(control.up.pressed, wasUpEnabled)
compare(control.down.pressed, false)
- if (wasUpEnabled)
+ if (wasUpEnabled) {
++upPressedCount
+ ++valueModifiedCount
+ }
compare(upPressedSpy.count, upPressedCount)
+ compare(valueModifiedSpy.count, valueModifiedCount)
compare(control.value, Math.min(99, i2 * 25))
@@ -334,14 +350,13 @@ TestCase {
if (wasUpEnabled)
++upPressedCount
compare(upPressedSpy.count, upPressedCount)
+ compare(valueModifiedSpy.count, valueModifiedCount)
}
compare(control.value, 99)
-
- control.destroy()
}
function test_locale() {
- var control = spinBox.createObject(testCase)
+ var control = createTemporaryObject(spinBox, testCase)
verify(control)
control.locale = Qt.locale("ar_EG") // Arabic, Egypt
@@ -351,19 +366,16 @@ TestCase {
control.value = i
compare(control.contentItem.text, numbers[i])
}
-
- control.destroy()
}
function test_baseline() {
- var control = spinBox.createObject(testCase)
+ var control = createTemporaryObject(spinBox, testCase)
verify(control)
compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset)
- control.destroy()
}
function test_focus() {
- var control = spinBox.createObject(testCase, {from: 10, to: 1000, value: 100, focus: true})
+ var control = createTemporaryObject(spinBox, testCase, {from: 10, to: 1000, value: 100, focus: true})
verify(control)
control.forceActiveFocus()
@@ -379,12 +391,10 @@ TestCase {
compare(control.from, 10)
compare(control.to, 1000)
compare(control.value, 100)
-
- control.destroy()
}
function test_editable() {
- var control = spinBox.createObject(testCase)
+ var control = createTemporaryObject(spinBox, testCase)
verify(control)
control.contentItem.forceActiveFocus()
@@ -402,43 +412,48 @@ TestCase {
keyClick(Qt.Key_5)
keyClick(Qt.Key_Return)
compare(control.value, 5)
-
- control.destroy()
}
function test_wheel(data) {
- var control = spinBox.createObject(testCase, {wheelEnabled: true})
+ var control = createTemporaryObject(spinBox, testCase, {wheelEnabled: true})
verify(control)
+ var valueModifiedSpy = signalSpy.createObject(control, {target: control, signalName: "valueModified"})
+ verify(valueModifiedSpy.valid)
+
var delta = 120
compare(control.value, 0)
mouseWheel(control, control.width / 2, control.height / 2, delta, delta)
compare(control.value, 1)
+ compare(valueModifiedSpy.count, 1)
control.stepSize = 2
mouseWheel(control, control.width / 2, control.height / 2, delta, delta)
compare(control.value, 3)
+ compare(valueModifiedSpy.count, 2)
control.stepSize = 10
mouseWheel(control, control.width / 2, control.height / 2, -delta, -delta)
compare(control.value, 0)
+ compare(valueModifiedSpy.count, 3)
control.stepSize = 5
mouseWheel(control, control.width / 2, control.height / 2, delta, delta)
compare(control.value, 5)
+ compare(valueModifiedSpy.count, 4)
mouseWheel(control, control.width / 2, control.height / 2, 0.5 * delta, 0.5 * delta)
compare(control.value, 8)
+ compare(valueModifiedSpy.count, 5)
mouseWheel(control, control.width / 2, control.height / 2, -delta, -delta)
compare(control.value, 3)
-
- control.destroy()
+ compare(valueModifiedSpy.count, 6)
}
function test_initiallyDisabledIndicators_data() {
@@ -451,13 +466,11 @@ TestCase {
}
function test_initiallyDisabledIndicators(data) {
- var control = spinBox.createObject(testCase, { from: data.from, value: data.value, to: data.to })
+ var control = createTemporaryObject(spinBox, testCase, { from: data.from, value: data.value, to: data.to })
verify(control)
compare(control.up.indicator.enabled, data.upEnabled)
compare(control.down.indicator.enabled, data.downEnabled)
-
- control.destroy()
}
function test_hover_data() {
@@ -472,7 +485,7 @@ TestCase {
}
function test_hover(data) {
- var control = spinBox.createObject(testCase, {hoverEnabled: data.hoverEnabled, value: data.value})
+ var control = createTemporaryObject(spinBox, testCase, {hoverEnabled: data.hoverEnabled, value: data.value})
verify(control)
var button = control[data.button]
@@ -485,8 +498,6 @@ TestCase {
mouseMove(control, button.indicator.x - 1, button.indicator.y - 1)
compare(button.hovered, false)
-
- control.destroy()
}
function test_valueFromText_data() {
@@ -497,7 +508,7 @@ TestCase {
}
function test_valueFromText(data) {
- var control = spinBox.createObject(testCase, {editable: data.editable})
+ var control = createTemporaryObject(spinBox, testCase, {editable: data.editable})
verify(control)
control.forceActiveFocus()
@@ -517,12 +528,10 @@ TestCase {
control.focus = false
compare(valueFromTextCalls, data.editable ? 3 : 0)
-
- control.destroy()
}
function test_autoRepeat() {
- var control = spinBox.createObject(testCase)
+ var control = createTemporaryObject(spinBox, testCase)
verify(control)
compare(control.value, 0)
@@ -579,7 +588,5 @@ TestCase {
mouseRelease(control.up.indicator, -1, -1)
verify(!control.up.pressed)
-
- control.destroy()
}
}
diff --git a/tests/auto/controls/data/tst_swipedelegate.qml b/tests/auto/controls/data/tst_swipedelegate.qml
index 98c99438..a36a2770 100644
--- a/tests/auto/controls/data/tst_swipedelegate.qml
+++ b/tests/auto/controls/data/tst_swipedelegate.qml
@@ -40,7 +40,7 @@
import QtQuick 2.6
import QtTest 1.0
-import QtQuick.Controls 2.1
+import QtQuick.Controls 2.2
TestCase {
@@ -128,10 +128,8 @@ TestCase {
ignoreWarning(warningMessage);
- var control = data.component.createObject(testCase);
+ var control = createTemporaryObject(data.component, testCase);
verify(control.contentItem);
-
- control.destroy();
}
Component {
@@ -204,11 +202,11 @@ TestCase {
}
function test_settingDelegates() {
- var control = swipeDelegateComponent.createObject(testCase);
+ var control = createTemporaryObject(swipeDelegateComponent, testCase);
verify(control);
ignoreWarning(Qt.resolvedUrl("tst_swipedelegate.qml") +
- ":160:9: QML SwipeDelegate: cannot set both behind and left/right properties")
+ ":158:9: QML SwipeDelegate: cannot set both behind and left/right properties")
control.swipe.behind = itemComponent;
// Shouldn't be any warnings when unsetting delegates.
@@ -217,7 +215,7 @@ TestCase {
// right is still set.
ignoreWarning(Qt.resolvedUrl("tst_swipedelegate.qml") +
- ":160:9: QML SwipeDelegate: cannot set both behind and left/right properties")
+ ":158:9: QML SwipeDelegate: cannot set both behind and left/right properties")
control.swipe.behind = itemComponent;
control.swipe.right = null;
@@ -226,11 +224,11 @@ TestCase {
control.swipe.behind = itemComponent;
ignoreWarning(Qt.resolvedUrl("tst_swipedelegate.qml") +
- ":160:9: QML SwipeDelegate: cannot set both behind and left/right properties")
+ ":158:9: QML SwipeDelegate: cannot set both behind and left/right properties")
control.swipe.left = itemComponent;
ignoreWarning(Qt.resolvedUrl("tst_swipedelegate.qml") +
- ":160:9: QML SwipeDelegate: cannot set both behind and left/right properties")
+ ":158:9: QML SwipeDelegate: cannot set both behind and left/right properties")
control.swipe.right = itemComponent;
control.swipe.behind = null;
@@ -245,7 +243,7 @@ TestCase {
var oldLeft = control.swipe.left;
var oldLeftItem = control.swipe.leftItem;
ignoreWarning(Qt.resolvedUrl("tst_swipedelegate.qml") +
- ":160:9: QML SwipeDelegate: left/right/behind properties may only be set when swipe.position is 0")
+ ":158:9: QML SwipeDelegate: left/right/behind properties may only be set when swipe.position is 0")
control.swipe.left = null;
compare(control.swipe.left, oldLeft);
compare(control.swipe.leftItem, oldLeftItem);
@@ -256,7 +254,7 @@ TestCase {
var oldRight = control.swipe.right;
var oldRightItem = control.swipe.rightItem;
ignoreWarning(Qt.resolvedUrl("tst_swipedelegate.qml") +
- ":160:9: QML SwipeDelegate: left/right/behind properties may only be set when swipe.position is 0")
+ ":158:9: QML SwipeDelegate: left/right/behind properties may only be set when swipe.position is 0")
control.swipe.right = null;
compare(control.swipe.right, oldRight);
compare(control.swipe.rightItem, oldRightItem);
@@ -282,24 +280,20 @@ TestCase {
var oldBehind = control.swipe.behind;
var oldBehindItem = control.swipe.behindItem;
ignoreWarning(Qt.resolvedUrl("tst_swipedelegate.qml") +
- ":160:9: QML SwipeDelegate: left/right/behind properties may only be set when swipe.position is 0")
+ ":158:9: QML SwipeDelegate: left/right/behind properties may only be set when swipe.position is 0")
control.swipe.behind = null;
compare(control.swipe.behind, oldBehind);
compare(control.swipe.behindItem, oldBehindItem);
-
- control.destroy();
}
function test_defaults() {
- var control = swipeDelegateComponent.createObject(testCase);
+ var control = createTemporaryObject(swipeDelegateComponent, testCase);
verify(control);
compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset);
compare(control.swipe.position, 0);
verify(!control.pressed);
verify(!control.swipe.complete);
-
- control.destroy();
}
SignalSequenceSpy {
@@ -308,7 +302,7 @@ TestCase {
}
function test_swipe() {
- var control = swipeDelegateComponent.createObject(testCase);
+ var control = createTemporaryObject(swipeDelegateComponent, testCase);
verify(control);
var overDragDistance = Math.round(dragDistance * 1.1);
@@ -317,6 +311,14 @@ TestCase {
verify(completedSpy);
verify(completedSpy.valid);
+ var openedSpy = signalSpyComponent.createObject(control, { target: control.swipe, signalName: "opened" });
+ verify(openedSpy);
+ verify(openedSpy.valid);
+
+ var closedSpy = signalSpyComponent.createObject(control, { target: control.swipe, signalName: "closed" });
+ verify(closedSpy);
+ verify(closedSpy.valid);
+
mouseSignalSequenceSpy.target = control;
mouseSignalSequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true }], "pressed"];
mousePress(control, control.width / 2, control.height / 2);
@@ -324,6 +326,8 @@ TestCase {
compare(control.swipe.position, 0.0);
verify(!control.swipe.complete);
compare(completedSpy.count, 0);
+ compare(openedSpy.count, 0);
+ compare(closedSpy.count, 0);
verify(mouseSignalSequenceSpy.success);
verify(!control.swipe.leftItem);
verify(!control.swipe.rightItem);
@@ -334,6 +338,8 @@ TestCase {
compare(control.swipe.position, overDragDistance / control.width);
verify(!control.swipe.complete);
compare(completedSpy.count, 0);
+ compare(openedSpy.count, 0);
+ compare(closedSpy.count, 0);
verify(control.swipe.leftItem);
verify(control.swipe.leftItem.visible);
compare(control.swipe.leftItem.parent, control);
@@ -346,6 +352,8 @@ TestCase {
compare(control.swipe.position, 0.0);
verify(!control.swipe.complete);
compare(completedSpy.count, 0);
+ compare(openedSpy.count, 0);
+ compare(closedSpy.count, 0);
verify(control.swipe.leftItem);
verify(control.swipe.leftItem.visible);
compare(control.swipe.leftItem.parent, control);
@@ -359,6 +367,8 @@ TestCase {
compare(control.swipe.position, -overDragDistance / control.width);
verify(!control.swipe.complete);
compare(completedSpy.count, 0);
+ compare(openedSpy.count, 0);
+ compare(closedSpy.count, 0);
verify(control.swipe.leftItem);
verify(!control.swipe.leftItem.visible);
verify(control.swipe.rightItem);
@@ -372,6 +382,8 @@ TestCase {
compare(control.swipe.position, 0.6);
verify(!control.swipe.complete);
compare(completedSpy.count, 0);
+ compare(openedSpy.count, 0);
+ compare(closedSpy.count, 0);
verify(control.swipe.leftItem);
verify(control.swipe.leftItem.visible);
verify(control.swipe.rightItem);
@@ -380,9 +392,11 @@ TestCase {
mouseSignalSequenceSpy.expectedSequence = [["pressedChanged", { "pressed": false }], "canceled"];
mouseRelease(control, control.width / 2, control.height / 2);
verify(!control.pressed);
- compare(control.swipe.position, 1.0);
- verify(control.swipe.complete);
+ tryCompare(control.swipe, "position", 1.0);
+ tryCompare(control.swipe, "complete", true);
compare(completedSpy.count, 1);
+ compare(openedSpy.count, 1);
+ compare(closedSpy.count, 0);
verify(mouseSignalSequenceSpy.success);
verify(control.swipe.leftItem);
verify(control.swipe.leftItem.visible);
@@ -399,21 +413,27 @@ TestCase {
// haven't started grabbing behind's mouse events.
verify(control.swipe.complete);
compare(completedSpy.count, 1);
+ compare(openedSpy.count, 1);
+ compare(closedSpy.count, 0);
verify(mouseSignalSequenceSpy.success);
mouseMove(control, control.width / 2 - overDragDistance, control.height / 2);
verify(control.pressed);
verify(!control.swipe.complete);
compare(completedSpy.count, 1);
+ compare(openedSpy.count, 1);
+ compare(closedSpy.count, 0);
compare(control.swipe.position, 1.0 - overDragDistance / control.width);
// Since we went over the drag distance, we should expect canceled() to be emitted.
mouseSignalSequenceSpy.expectedSequence = [["pressedChanged", { "pressed": false }], "canceled"];
mouseRelease(control, control.width * 0.4, control.height / 2);
verify(!control.pressed);
- compare(control.swipe.position, 1.0);
- verify(control.swipe.complete);
+ tryCompare(control.swipe, "position", 1.0);
+ tryCompare(control.swipe, "complete", true);
compare(completedSpy.count, 2);
+ compare(openedSpy.count, 2);
+ compare(closedSpy.count, 0);
verify(mouseSignalSequenceSpy.success);
tryCompare(control.contentItem, "x", control.width + control.leftPadding);
@@ -424,24 +444,28 @@ TestCase {
compare(control.swipe.position, 1.0);
verify(control.swipe.complete);
compare(completedSpy.count, 2);
+ compare(openedSpy.count, 2);
+ compare(closedSpy.count, 0);
verify(mouseSignalSequenceSpy.success);
mouseMove(control, control.width * -0.1, control.height / 2);
verify(control.pressed);
verify(!control.swipe.complete);
compare(completedSpy.count, 2);
+ compare(openedSpy.count, 2);
+ compare(closedSpy.count, 0);
compare(control.swipe.position, 0.4);
mouseSignalSequenceSpy.expectedSequence = [["pressedChanged", { "pressed": false }], "canceled"];
mouseRelease(control, control.width * -0.1, control.height / 2);
verify(!control.pressed);
- compare(control.swipe.position, 0.0);
+ tryCompare(control.swipe, "position", 0.0);
verify(!control.swipe.complete);
compare(completedSpy.count, 2);
+ compare(openedSpy.count, 2);
+ tryCompare(closedSpy, "count", 1);
verify(mouseSignalSequenceSpy.success);
tryCompare(control.contentItem, "x", control.leftPadding);
-
- control.destroy();
}
function test_swipeVelocity_data() {
@@ -454,7 +478,7 @@ TestCase {
function test_swipeVelocity(data) {
skip("QTBUG-52003");
- var control = swipeDelegateComponent.createObject(testCase);
+ var control = createTemporaryObject(swipeDelegateComponent, testCase);
verify(control);
var distance = Math.round(dragDistance * 1.1);
@@ -514,8 +538,6 @@ TestCase {
verify(expectedVisibleItem.visible);
verify(!expectedHiddenItem);
tryCompare(control.contentItem, "x", expectedContentItemX);
-
- control.destroy();
}
Component {
@@ -532,9 +554,13 @@ TestCase {
}
function test_eventsToLeftAndRight() {
- var control = swipeDelegateWithButtonComponent.createObject(testCase);
+ var control = createTemporaryObject(swipeDelegateWithButtonComponent, testCase);
verify(control);
+ var closedSpy = signalSpyComponent.createObject(control, { target: control.swipe, signalName: "closed" });
+ verify(closedSpy);
+ verify(closedSpy.valid);
+
// The button should be pressed instead of the SwipeDelegate.
mouseDrag(control, control.width / 2, control.height / 2, -control.width, 0);
// Mouse has been released by this stage.
@@ -572,18 +598,17 @@ TestCase {
// Returning back to a position of 0 and pressing on the control should
// result in the control being pressed.
mouseDrag(control, control.width / 2, control.height / 2, control.width * 0.6, 0);
+ tryCompare(closedSpy, "count", 1);
compare(control.swipe.position, 0);
mousePress(control, control.width / 2, control.height / 2);
verify(control.pressed);
verify(!button.pressed);
mouseRelease(control, control.width / 2, control.height / 2);
verify(!control.pressed);
-
- control.destroy();
}
function test_mouseButtons() {
- var control = swipeDelegateComponent.createObject(testCase);
+ var control = createTemporaryObject(swipeDelegateComponent, testCase);
verify(control);
// click
@@ -644,8 +669,6 @@ TestCase {
mouseRelease(control);
compare(control.pressed, false);
verify(mouseSignalSequenceSpy.success);
-
- control.destroy();
}
Component {
@@ -709,7 +732,7 @@ TestCase {
}
function test_removableDelegates() {
- var listView = removableDelegatesComponent.createObject(testCase);
+ var listView = createTemporaryObject(removableDelegatesComponent, testCase);
verify(listView);
compare(listView.count, 3);
@@ -730,8 +753,8 @@ TestCase {
mouseRelease(listView, firstItem.width / 2, firstItem.height / 2);
verify(!firstItem.pressed);
- compare(firstItem.swipe.position, 1.0);
- verify(firstItem.swipe.complete);
+ tryCompare(firstItem.swipe, "position", 1.0);
+ tryCompare(firstItem.swipe, "complete", true);
compare(listView.count, 3);
// Wait for it to settle down.
@@ -767,8 +790,6 @@ TestCase {
break;
}
compare(listView.count, 2);
-
- listView.destroy();
}
Component {
@@ -825,7 +846,7 @@ TestCase {
}
function test_leadingTrailing(data) {
- var control = data.component.createObject(testCase);
+ var control = createTemporaryObject(data.component, testCase);
verify(control);
mousePress(control, control.width / 2, control.height / 2, Qt.LeftButton);
@@ -833,12 +854,10 @@ TestCase {
verify(control.swipe.leftItem);
compare(control.swipe.leftItem.x, -control.width / 2);
mouseRelease(control, control.width / 2, control.height / 2, Qt.LeftButton);
-
- control.destroy();
}
function test_minMaxPosition() {
- var control = leadingTrailingXComponent.createObject(testCase);
+ var control = createTemporaryObject(leadingTrailingXComponent, testCase);
verify(control);
// Should be limited within the range -1.0 to 1.0.
@@ -850,8 +869,6 @@ TestCase {
mouseMove(control, control.width * -1.6, control.height / 2, Qt.LeftButton);
compare(control.swipe.position, -1.0);
mouseRelease(control, control.width / 2, control.height / 2, Qt.LeftButton);
-
- control.destroy();
}
Component {
@@ -876,7 +893,7 @@ TestCase {
// swipe.position should be scaled to the width of the relevant delegate,
// and it shouldn't be possible to drag past the delegate (so that content behind the control is visible).
function test_delegateWidth() {
- var control = emptySwipeDelegateComponent.createObject(testCase);
+ var control = createTemporaryObject(emptySwipeDelegateComponent, testCase);
verify(control);
control.swipe.left = smallLeftComponent;
@@ -901,8 +918,6 @@ TestCase {
mouseRelease(control, control.width / 2 + control.swipe.leftItem.width, control.height / 2, Qt.LeftButton);
compare(control.swipe.position, 1.0);
tryCompare(control.background, "x", control.swipe.leftItem.width, 1000);
-
- control.destroy();
}
SignalSpy {
@@ -916,7 +931,7 @@ TestCase {
}
function test_positionAfterSwipeCompleted() {
- var control = swipeDelegateComponent.createObject(testCase);
+ var control = createTemporaryObject(swipeDelegateComponent, testCase);
verify(control);
// Ensure that both delegates are constructed.
@@ -960,8 +975,6 @@ TestCase {
compare(control.swipe.position, 1.0);
tryCompare(control.background, "x", control.swipe.leftItem.width, 1000);
mouseRelease(control, control.swipe.leftItem.width, control.height / 2, Qt.LeftButton);
-
- control.destroy();
}
// TODO: this somehow results in the behind item having a negative width
@@ -1012,7 +1025,7 @@ TestCase {
}
function test_leadingTrailingBehindItem() {
- var control = behindSwipeDelegateComponent.createObject(testCase);
+ var control = createTemporaryObject(behindSwipeDelegateComponent, testCase);
verify(control);
swipe(control, 0.0, 1.0);
@@ -1032,7 +1045,7 @@ TestCase {
mouseMove(control, control.width / 2 + control.swipe.behindItem.width * 0.8, control.height / 2, Qt.LeftButton);
compare(control.swipe.position, -0.2);
mouseRelease(control, control.width / 2 + control.swipe.behindItem.width * 0.8, control.height / 2, Qt.LeftButton);
- compare(control.swipe.position, 0.0);
+ tryCompare(control.swipe, "position", 0.0);
// Try wrapping the other way.
swipe(control, 0.0, -1.0);
@@ -1043,9 +1056,7 @@ TestCase {
mouseMove(control, control.width / 2 - control.swipe.behindItem.width * 0.8, control.height / 2, Qt.LeftButton);
compare(control.swipe.position, 0.2);
mouseRelease(control, control.width / 2 - control.swipe.behindItem.width * 0.8, control.height / 2, Qt.LeftButton);
- compare(control.swipe.position, 0.0);
-
- control.destroy();
+ tryCompare(control.swipe, "position", 0.0);
}
Component {
@@ -1065,9 +1076,13 @@ TestCase {
}
function test_close() {
- var control = closeSwipeDelegateComponent.createObject(testCase);
+ var control = createTemporaryObject(closeSwipeDelegateComponent, testCase);
verify(control);
+ var closedSpy = signalSpyComponent.createObject(control, { target: control.swipe, signalName: "closed" });
+ verify(closedSpy);
+ verify(closedSpy.valid);
+
swipe(control, 0.0, -1.0);
compare(control.swipe.rightItem.visible, true);
// Should animate, so it shouldn't change right away.
@@ -1079,12 +1094,11 @@ TestCase {
mouseRelease(control);
verify(!control.swipe.rightItem.SwipeDelegate.pressed);
- tryCompare(control.swipe, "position", 0);
+ tryCompare(closedSpy, "count", 1);
+ compare(control.swipe.position, 0);
// Swiping after closing should work as normal.
swipe(control, 0.0, -1.0);
-
- control.destroy();
}
Component {
@@ -1133,7 +1147,7 @@ TestCase {
// Tests that it's possible to have multiple non-interactive items in one delegate
// (e.g. left/right/behind) that can each receive clicks.
function test_multipleClickableActions() {
- var control = multiActionSwipeDelegateComponent.createObject(testCase);
+ var control = createTemporaryObject(multiActionSwipeDelegateComponent, testCase);
verify(control);
swipe(control, 0.0, -1.0);
@@ -1178,8 +1192,6 @@ TestCase {
compare(control.swipe.rightItem.secondAction.SwipeDelegate.pressed, false);
compare(secondClickedSpy.count, 1);
compare(control.swipe.rightItem.secondClickCount, 1);
-
- control.destroy();
}
// Pressing on a "side action" and then dragging should eventually
@@ -1187,7 +1199,7 @@ TestCase {
// When this happens, it will grab the mouse and hence we must clear
// that action's pressed state so that it doesn't stay pressed after releasing.
function test_dragSideAction() {
- var listView = removableDelegatesComponent.createObject(testCase);
+ var listView = createTemporaryObject(removableDelegatesComponent, testCase);
verify(listView);
var control = listView.itemAt(0, 0);
@@ -1208,15 +1220,13 @@ TestCase {
verify(listView.contentY !== 0);
compare(control.swipe.leftItem.SwipeDelegate.pressed, false);
-
- listView.destroy();
}
// When the width of a SwipeDelegate changes (as it does upon portrait => landscape
// rotation, for example), the positions of the contentItem and background items
// should be updated accordingly.
function test_contentItemPosOnWidthChanged() {
- var control = swipeDelegateComponent.createObject(testCase);
+ var control = createTemporaryObject(swipeDelegateComponent, testCase);
verify(control);
swipe(control, 0.0, 1.0);
@@ -1226,12 +1236,10 @@ TestCase {
control.width += 100;
compare(control.contentItem.x, oldContentItemX + 100);
compare(control.background.x, oldBackgroundX + 100);
-
- control.destroy();
}
function test_contentItemHeightOnHeightChanged() {
- var control = swipeDelegateComponent.createObject(testCase);
+ var control = createTemporaryObject(swipeDelegateComponent, testCase);
verify(control);
// Try when swipe.complete is false.
@@ -1250,8 +1258,6 @@ TestCase {
compare(control.contentItem.height, control.availableHeight);
verify(control.contentItem.height < originalContentItemHeight);
compare(control.contentItem.y, control.topPadding);
-
- control.destroy();
}
function test_releaseOutside_data() {
@@ -1262,7 +1268,7 @@ TestCase {
}
function test_releaseOutside(data) {
- var control = data.component.createObject(testCase);
+ var control = createTemporaryObject(data.component, testCase);
verify(control);
// Press and then release below the control.
@@ -1345,7 +1351,7 @@ TestCase {
}
function test_beginSwipeOverRightItem() {
- var control = leftRightWithLabelsComponent.createObject(testCase);
+ var control = createTemporaryObject(leftRightWithLabelsComponent, testCase);
verify(control);
// Swipe to the left, exposing the right item.
@@ -1364,8 +1370,146 @@ TestCase {
mouseRelease(rightLabel, rightLabel.width / 2 - overDragDistance, control.height / 2, Qt.LeftButton);
verify(!control.swipe.leftItem);
+ }
+
+ Component {
+ id: swipeDelegateDisabledComponent
+
+ SwipeDelegate {
+ id: swipeDelegate
+ text: "SwipeDelegate"
+ width: parent.width
+ height: checked ? implicitHeight * 2 : implicitHeight
+ checkable: true
+
+ swipe.enabled: false
+ swipe.right: Label {
+ text: swipeDelegate.checked ? qsTr("Expanded") : qsTr("Collapsed")
+ width: parent.width
+ height: parent.height
+ padding: 12
+ color: "white"
+ verticalAlignment: Label.AlignVCenter
+ horizontalAlignment: Label.AlignRight
+ }
+ }
+ }
+
+ function test_swipeEnabled() {
+ var control = createTemporaryObject(swipeDelegateDisabledComponent, testCase);
+
+ mousePress(control, control.width / 2, control.height / 2);
+ verify(control.pressed);
+ compare(control.swipe.position, 0.0);
+ verify(!control.swipe.complete);
+ verify(!control.swipe.leftItem);
+ verify(!control.swipe.rightItem);
+
+ // It shouldn't be possible to swipe.
+ var overDragDistance = Math.round(dragDistance * 1.1);
+ mouseMove(control, control.width / 2 - overDragDistance, control.height / 2);
+ verify(control.pressed);
+ compare(control.swipe.position, 0.0);
+ verify(!control.swipe.complete);
+ verify(!control.swipe.leftItem);
+ verify(!control.swipe.rightItem);
+
+ // Now move outside the right edge of the control and release.
+ mouseMove(control, control.width * 1.1, control.height / 2);
+ verify(control.pressed);
+ compare(control.swipe.position, 0.0);
+ verify(!control.swipe.complete);
+ verify(!control.swipe.leftItem);
+ verify(!control.swipe.rightItem);
+
+ mouseRelease(control, control.width / 2, control.height / 2);
+ verify(!control.pressed);
+ compare(control.swipe.position, 0.0);
+ verify(!control.swipe.complete);
+ verify(!control.swipe.leftItem);
+ verify(!control.swipe.rightItem);
+
+ // Now enabled swiping so that we can swipe to the left.
+ control.swipe.enabled = true;
+ swipe(control, 0, -1);
+ verify(control.swipe.complete);
+
+ // Now that the swipe is complete, disable swiping and then try to swipe again.
+ // It should stay at its position of -1.
+ control.swipe.enabled = false;
+
+ mousePress(control, control.width / 2, control.height / 2);
+ verify(control.pressed);
+ compare(control.swipe.position, -1.0);
+
+ mouseMove(control, control.width / 2 + overDragDistance, control.height / 2);
+ verify(control.pressed);
+ compare(control.swipe.position, -1.0);
+ verify(control.swipe.complete);
+
+ mouseRelease(control, control.width / 2 + overDragDistance, control.height / 2);
+ verify(!control.pressed);
+ compare(control.swipe.position, -1.0);
+ verify(control.swipe.complete);
+ }
+
+ function test_side() {
+ compare(SwipeDelegate.Left, 1.0);
+ compare(SwipeDelegate.Right, -1.0);
+ }
+
+ function test_open_side_data() {
+ return [
+ { tag: "left", side: SwipeDelegate.Left, position: 1, complete: true, left: greenLeftComponent, right: null, behind: null },
+ { tag: "right", side: SwipeDelegate.Right, position: -1, complete: true, left: null, right: redRightComponent, behind: null },
+ { tag: "behind,left", side: SwipeDelegate.Left, position: 1, complete: true, left: null, right: null, behind: greenLeftComponent },
+ { tag: "behind,right", side: SwipeDelegate.Right, position: -1, complete: true, left: null, right: null, behind: redRightComponent },
+ { tag: "left,behind", side: SwipeDelegate.Left, position: 1, complete: true, left: null, right: null, behind: greenLeftComponent },
+ { tag: "right,behind", side: SwipeDelegate.Right, position: -1, complete: true, left: null, right: null, behind: redRightComponent },
+ { tag: "left,null", side: SwipeDelegate.Left, position: 0, complete: false, left: null, right: null, behind: null },
+ { tag: "right,null", side: SwipeDelegate.Right, position: 0, complete: false, left: null, right: null, behind: null },
+ { tag: "invalid", side: 0, position: 0, complete: false, left: greenLeftComponent, right: null, behind: null }
+ ]
+ }
+
+ function test_open_side(data) {
+ var control = createTemporaryObject(emptySwipeDelegateComponent, testCase,
+ {"swipe.left": data.left, "swipe.right": data.right, "swipe.behind": data.behind});
+ verify(control);
+
+ control.swipe.open(data.side);
+ tryCompare(control.swipe, "position", data.position);
+ tryCompare(control.swipe, "complete", data.complete);
+ }
+
+ Component {
+ id: openSwipeDelegateComponent
+
+ SwipeDelegate {
+ text: "SwipeDelegate"
+ width: 150
- control.destroy();
+ onClicked: swipe.open(SwipeDelegate.Right)
+
+ swipe.right: Item {
+ width: parent.width
+ height: parent.height
+ }
+ }
+ }
+
+ function test_open() {
+ var control = createTemporaryObject(openSwipeDelegateComponent, testCase);
+ verify(control);
+
+ mouseClick(control);
+ tryCompare(control.swipe, "position", SwipeDelegate.Right);
+ tryCompare(control.background, "x", -control.background.width);
+
+ // Swiping after opening should work as normal.
+ swipe(control, SwipeDelegate.Right, 0.0);
+ tryCompare(control.swipe, "position", 0.0);
+ tryCompare(control.background, "x", 0);
}
Component {
@@ -1377,6 +1521,7 @@ TestCase {
width: 150
swipe.left: greenLeftComponent
swipe.right: redRightComponent
+ swipe.transition: null
property alias behavior: xBehavior
property alias animation: numberAnimation
@@ -1400,7 +1545,7 @@ TestCase {
function test_animations() {
// Test that animations are run when releasing from a drag.
- var control = animationSwipeDelegateComponent.createObject(testCase);
+ var control = createTemporaryObject(animationSwipeDelegateComponent, testCase);
verify(control);
mousePress(control, control.width / 2, control.height / 2, Qt.LeftButton);
@@ -1413,7 +1558,5 @@ TestCase {
verify(!control.down);
verify(control.behavior.enabled);
verify(control.animation.running);
-
- control.destroy();
}
}
diff --git a/tests/auto/controls/data/tst_swipeview.qml b/tests/auto/controls/data/tst_swipeview.qml
index 7fd0ab37..d330b73c 100644
--- a/tests/auto/controls/data/tst_swipeview.qml
+++ b/tests/auto/controls/data/tst_swipeview.qml
@@ -66,9 +66,9 @@ TestCase {
}
function test_current() {
- var control = swipeView.createObject(testCase)
+ var control = createTemporaryObject(swipeView, testCase)
- var currentItemChangedSpy = signalSpy.createObject(testCase, {target: control, signalName: "currentItemChanged"})
+ var currentItemChangedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "currentItemChanged"})
verify(currentItemChangedSpy.valid)
compare(control.count, 0)
@@ -112,8 +112,6 @@ TestCase {
compare(control.currentIndex, 2)
compare(control.currentItem.text, "2")
compare(currentItemChangedSpy.count, 5);
-
- control.destroy()
}
Component {
@@ -134,17 +132,15 @@ TestCase {
}
function test_initialCurrent() {
- var control = initialCurrentSwipeView.createObject(testCase)
+ var control = createTemporaryObject(initialCurrentSwipeView, testCase)
compare(control.count, 2)
compare(control.currentIndex, 1)
compare(control.currentItem, control.item1)
-
- control.destroy()
}
function test_addRemove() {
- var control = swipeView.createObject(testCase)
+ var control = createTemporaryObject(swipeView, testCase)
function verifyCurrentIndexCountDiff() {
verify(control.currentIndex < control.count)
@@ -152,7 +148,7 @@ TestCase {
control.currentIndexChanged.connect(verifyCurrentIndexCountDiff)
control.countChanged.connect(verifyCurrentIndexCountDiff)
- var currentItemChangedSpy = signalSpy.createObject(testCase, {target: control, signalName: "currentItemChanged"})
+ var currentItemChangedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "currentItemChanged"})
verify(currentItemChangedSpy.valid)
compare(control.count, 0)
@@ -238,8 +234,6 @@ TestCase {
compare(control.count, 0)
compare(control.currentIndex, -1)
compare(currentItemChangedSpy.count, 2)
-
- control.destroy()
}
Component {
@@ -254,7 +248,7 @@ TestCase {
}
function test_content() {
- var control = contentView.createObject(testCase)
+ var control = createTemporaryObject(contentView, testCase)
function compareObjectNames(content, names) {
if (content.length !== names.length)
@@ -284,8 +278,6 @@ TestCase {
control.removeItem(0)
verify(compareObjectNames(control.contentData, ["object", "page1", "timer", "page2", "", "page3"]))
verify(compareObjectNames(control.contentChildren, ["page2", "page1", "page3"]))
-
- control.destroy()
}
Component {
@@ -301,7 +293,7 @@ TestCase {
}
function test_repeater() {
- var control = repeated.createObject(testCase)
+ var control = createTemporaryObject(repeated, testCase)
verify(control)
var model = control.contentModel
@@ -332,8 +324,6 @@ TestCase {
compare(model.get(j), item2)
compare(repeater.itemAt(j), item2)
}
-
- control.destroy()
}
Component {
@@ -357,7 +347,7 @@ TestCase {
}
function test_order() {
- var control = ordered.createObject(testCase)
+ var control = createTemporaryObject(ordered, testCase)
verify(control)
compare(control.count, 7)
@@ -368,8 +358,6 @@ TestCase {
compare(control.itemAt(4).text, "static_4")
compare(control.itemAt(5).text, "dynamic_5")
compare(control.itemAt(6).text, "dynamic_6")
-
- control.destroy()
}
function test_move_data() {
@@ -420,7 +408,7 @@ TestCase {
}
function test_move(data) {
- var control = swipeView.createObject(testCase)
+ var control = createTemporaryObject(swipeView, testCase)
compare(control.count, 0)
var titles = ["1", "2", "3"]
@@ -464,8 +452,6 @@ TestCase {
compare(control.itemAt(i).SwipeView.isNextItem, i === data.currentAfter + 1)
compare(control.itemAt(i).SwipeView.isPreviousItem, i === data.currentAfter - 1)
}
-
- control.destroy()
}
Component {
@@ -482,7 +468,7 @@ TestCase {
}
function test_dynamic() {
- var control = dynamicView.createObject(testCase)
+ var control = createTemporaryObject(dynamicView, testCase)
// insertItem(), addItem(), createObject() and static page {}
compare(control.count, 4)
@@ -496,14 +482,12 @@ TestCase {
// tab.destroy()
// wait(0)
// compare(control.count, 4)
-
- control.destroy()
}
function test_attachedParent() {
- var control = swipeView.createObject(testCase);
+ var control = createTemporaryObject(swipeView, testCase);
- var page = pageAttached.createObject(testCase);
+ var page = createTemporaryObject(pageAttached, testCase);
compare(page.view, null);
compare(page.index, -1);
compare(page.isCurrentItem, false);
@@ -511,7 +495,7 @@ TestCase {
compare(page.isPreviousItem, false);
page.destroy();
- page = pageAttached.createObject(null);
+ page = createTemporaryObject(pageAttached, null);
compare(page.view, null);
compare(page.index, -1);
compare(page.isCurrentItem, false);
@@ -535,7 +519,5 @@ TestCase {
compare(page.isCurrentItem, false);
compare(page.isNextItem, false);
compare(page.isPreviousItem, false);
-
- control.destroy();
}
}
diff --git a/tests/auto/controls/data/tst_switch.qml b/tests/auto/controls/data/tst_switch.qml
index 314848c8..6cf7ec66 100644
--- a/tests/auto/controls/data/tst_switch.qml
+++ b/tests/auto/controls/data/tst_switch.qml
@@ -58,12 +58,12 @@ TestCase {
Component {
id: signalSequenceSpy
SignalSequenceSpy {
- signals: ["pressed", "released", "canceled", "clicked", "pressedChanged", "checkedChanged"]
+ signals: ["pressed", "released", "canceled", "clicked", "toggled", "pressedChanged", "checkedChanged"]
}
}
function test_text() {
- var control = swtch.createObject(testCase)
+ var control = createTemporaryObject(swtch, testCase)
verify(control)
compare(control.text, "")
@@ -71,12 +71,10 @@ TestCase {
compare(control.text, "Switch")
control.text = ""
compare(control.text, "")
-
- control.destroy()
}
function test_checked() {
- var control = swtch.createObject(testCase)
+ var control = createTemporaryObject(swtch, testCase)
verify(control)
compare(control.checked, false)
@@ -91,8 +89,6 @@ TestCase {
control.checked = false
compare(control.checked, false)
verify(spy.success)
-
- control.destroy()
}
function test_pressed_data() {
@@ -103,7 +99,7 @@ TestCase {
}
function test_pressed(data) {
- var control = swtch.createObject(testCase, {padding: 10})
+ var control = createTemporaryObject(swtch, testCase, {padding: 10})
verify(control)
// stays pressed when dragged outside
@@ -114,12 +110,10 @@ TestCase {
compare(control.pressed, true)
mouseRelease(control, -1, control.height / 2, Qt.LeftButton)
compare(control.pressed, false)
-
- control.destroy()
}
function test_mouse() {
- var control = swtch.createObject(testCase)
+ var control = createTemporaryObject(swtch, testCase)
verify(control)
// check
@@ -131,6 +125,7 @@ TestCase {
verify(spy.success)
spy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": false }],
["checkedChanged", { "pressed": false, "checked": true }],
+ "toggled",
"released",
"clicked"]
mouseRelease(control, control.width / 2, control.height / 2, Qt.LeftButton)
@@ -146,6 +141,7 @@ TestCase {
verify(spy.success)
spy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": true }],
["checkedChanged", { "pressed": false, "checked": false }],
+ "toggled",
"released",
"clicked"]
mouseRelease(control, control.width / 2, control.height / 2, Qt.LeftButton)
@@ -163,6 +159,7 @@ TestCase {
compare(control.pressed, true)
spy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": false }],
["checkedChanged", { "pressed": false, "checked": true }],
+ "toggled",
"released",
"clicked"]
mouseRelease(control, control.width * 2, control.height / 2, Qt.LeftButton)
@@ -180,6 +177,7 @@ TestCase {
compare(control.pressed, true)
spy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": true }],
["checkedChanged", { "pressed": false, "checked": false }],
+ "toggled",
"released",
"clicked"]
mouseRelease(control, -control.width, control.height / 2, Qt.LeftButton)
@@ -196,12 +194,10 @@ TestCase {
compare(control.checked, false)
compare(control.pressed, false)
verify(spy.success)
-
- control.destroy()
}
function test_drag() {
- var control = swtch.createObject(testCase, {leftPadding: 100, rightPadding: 100})
+ var control = createTemporaryObject(swtch, testCase, {leftPadding: 100, rightPadding: 100})
verify(control)
var spy = signalSequenceSpy.createObject(control, {target: control})
@@ -225,6 +221,7 @@ TestCase {
spy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": false }],
["checkedChanged", { "pressed": false, "checked": true }],
+ "toggled",
"released",
"clicked"]
mouseRelease(control.indicator, control.indicator.width)
@@ -259,6 +256,7 @@ TestCase {
spy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": true }],
["checkedChanged", { "pressed": false, "checked": false }],
+ "toggled",
"released",
"clicked"]
mouseRelease(control, control.width)
@@ -293,6 +291,7 @@ TestCase {
spy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": false }],
["checkedChanged", { "pressed": false, "checked": true }],
+ "toggled",
"released",
"clicked"]
mouseRelease(control, control.width)
@@ -300,12 +299,10 @@ TestCase {
compare(control.checked, true)
compare(control.pressed, false)
verify(spy.success)
-
- control.destroy()
}
function test_keys() {
- var control = swtch.createObject(testCase)
+ var control = createTemporaryObject(swtch, testCase)
verify(control)
control.forceActiveFocus()
@@ -317,6 +314,7 @@ TestCase {
"pressed",
["pressedChanged", { "pressed": false, "checked": false }],
["checkedChanged", { "pressed": false, "checked": true }],
+ "toggled",
"released",
"clicked"]
keyClick(Qt.Key_Space)
@@ -328,6 +326,7 @@ TestCase {
"pressed",
["pressedChanged", { "pressed": false, "checked": true }],
["checkedChanged", { "pressed": false, "checked": false }],
+ "toggled",
"released",
"clicked"]
keyClick(Qt.Key_Space)
@@ -342,8 +341,6 @@ TestCase {
compare(control.checked, false)
verify(spy.success)
}
-
- control.destroy()
}
Component {
@@ -355,7 +352,7 @@ TestCase {
}
function test_binding() {
- var container = twoSwitches.createObject(testCase)
+ var container = createTemporaryObject(twoSwitches, testCase)
verify(container)
compare(container.sw1.checked, false)
@@ -368,25 +365,20 @@ TestCase {
container.sw1.checked = false
compare(container.sw1.checked, false)
compare(container.sw2.checked, false)
-
- container.destroy()
}
function test_baseline() {
- var control = swtch.createObject(testCase)
+ var control = createTemporaryObject(swtch, testCase)
verify(control)
compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset)
- control.destroy()
}
function test_focus() {
- var control = swtch.createObject(testCase)
+ var control = createTemporaryObject(swtch, testCase)
verify(control)
verify(!control.activeFocus)
mouseClick(control.indicator)
verify(control.activeFocus)
-
- control.destroy()
}
}
diff --git a/tests/auto/controls/data/tst_switchdelegate.qml b/tests/auto/controls/data/tst_switchdelegate.qml
index 23117ce7..54b8c4b0 100644
--- a/tests/auto/controls/data/tst_switchdelegate.qml
+++ b/tests/auto/controls/data/tst_switchdelegate.qml
@@ -58,21 +58,20 @@ TestCase {
Component {
id: signalSequenceSpy
SignalSequenceSpy {
- signals: ["pressed", "released", "canceled", "clicked", "pressedChanged", "checkedChanged"]
+ signals: ["pressed", "released", "canceled", "clicked", "toggled", "pressedChanged", "checkedChanged"]
}
}
// TODO: data-fy tst_checkbox (rename to tst_check?) so we don't duplicate its tests here?
function test_defaults() {
- var control = switchDelegate.createObject(testCase);
+ var control = createTemporaryObject(switchDelegate, testCase);
verify(control);
verify(!control.checked);
- control.destroy();
}
function test_checked() {
- var control = switchDelegate.createObject(testCase);
+ var control = createTemporaryObject(switchDelegate, testCase);
verify(control);
mouseClick(control);
@@ -80,15 +79,12 @@ TestCase {
mouseClick(control);
verify(!control.checked);
-
- control.destroy();
}
function test_baseline() {
- var control = switchDelegate.createObject(testCase);
+ var control = createTemporaryObject(switchDelegate, testCase);
verify(control);
compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset);
- control.destroy();
}
function test_pressed_data() {
@@ -99,7 +95,7 @@ TestCase {
}
function test_pressed(data) {
- var control = switchDelegate.createObject(testCase, {padding: 10})
+ var control = createTemporaryObject(switchDelegate, testCase, {padding: 10})
verify(control)
// stays pressed when dragged outside
@@ -110,12 +106,10 @@ TestCase {
compare(control.pressed, true)
mouseRelease(control, -1, control.height / 2, Qt.LeftButton)
compare(control.pressed, false)
-
- control.destroy()
}
function test_mouse() {
- var control = switchDelegate.createObject(testCase)
+ var control = createTemporaryObject(switchDelegate, testCase)
verify(control)
// check
@@ -127,6 +121,7 @@ TestCase {
verify(spy.success)
spy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": false }],
["checkedChanged", { "pressed": false, "checked": true }],
+ "toggled",
"released",
"clicked"]
mouseRelease(control, control.width / 2, control.height / 2, Qt.LeftButton)
@@ -142,6 +137,7 @@ TestCase {
verify(spy.success)
spy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": true }],
["checkedChanged", { "pressed": false, "checked": false }],
+ "toggled",
"released",
"clicked"]
mouseRelease(control, control.width / 2, control.height / 2, Qt.LeftButton)
@@ -159,6 +155,7 @@ TestCase {
compare(control.pressed, true)
spy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": false }],
["checkedChanged", { "pressed": false, "checked": true }],
+ "toggled",
"released",
"clicked"]
mouseRelease(control, control.width * 2, control.height / 2, Qt.LeftButton)
@@ -176,6 +173,7 @@ TestCase {
compare(control.pressed, true)
spy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": true }],
["checkedChanged", { "pressed": false, "checked": false }],
+ "toggled",
"released",
"clicked"]
mouseRelease(control, -control.width, control.height / 2, Qt.LeftButton)
@@ -192,12 +190,10 @@ TestCase {
compare(control.checked, false)
compare(control.pressed, false)
verify(spy.success)
-
- control.destroy()
}
function test_drag() {
- var control = switchDelegate.createObject(testCase, {leftPadding: 100, rightPadding: 100})
+ var control = createTemporaryObject(switchDelegate, testCase, {leftPadding: 100, rightPadding: 100})
verify(control)
var spy = signalSequenceSpy.createObject(control, {target: control})
@@ -221,6 +217,7 @@ TestCase {
spy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": false }],
["checkedChanged", { "pressed": false, "checked": true }],
+ "toggled",
"released",
"clicked"]
mouseRelease(control.indicator, control.indicator.width)
@@ -255,6 +252,7 @@ TestCase {
spy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": true }],
["checkedChanged", { "pressed": false, "checked": false }],
+ "toggled",
"released",
"clicked"]
mouseRelease(control, control.width)
@@ -289,6 +287,7 @@ TestCase {
spy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": false }],
["checkedChanged", { "pressed": false, "checked": true }],
+ "toggled",
"released",
"clicked"]
mouseRelease(control, control.width)
@@ -296,7 +295,5 @@ TestCase {
compare(control.checked, true)
compare(control.pressed, false)
verify(spy.success)
-
- control.destroy()
}
}
diff --git a/tests/auto/controls/data/tst_tabbar.qml b/tests/auto/controls/data/tst_tabbar.qml
index ff3596f6..33df97ce 100644
--- a/tests/auto/controls/data/tst_tabbar.qml
+++ b/tests/auto/controls/data/tst_tabbar.qml
@@ -91,16 +91,15 @@ TestCase {
}
function test_defaults() {
- var control = tabBar.createObject(testCase)
+ var control = createTemporaryObject(tabBar, testCase)
verify(control)
compare(control.count, 0)
compare(control.currentIndex, -1)
compare(control.currentItem, null)
- control.destroy()
}
function test_current() {
- var control = tabBar.createObject(testCase)
+ var control = createTemporaryObject(tabBar, testCase)
compare(control.count, 0)
compare(control.currentIndex, -1)
@@ -143,32 +142,26 @@ TestCase {
compare(control.currentIndex, 2)
compare(control.currentItem.text, "2")
compare(control.currentItem.checked, true)
-
- control.destroy()
}
function test_current_static() {
- var control = tabBarStaticTabs.createObject(testCase)
+ var control = createTemporaryObject(tabBarStaticTabs, testCase)
compare(control.count, 2)
compare(control.currentIndex, 0)
compare(control.currentItem.text, "0")
compare(control.currentItem.checked, true)
- control.destroy()
-
- control = tabBarStaticTabsCurrent.createObject(testCase)
+ control = createTemporaryObject(tabBarStaticTabsCurrent, testCase)
compare(control.count, 2)
compare(control.currentIndex, 1)
compare(control.currentItem.text, "1")
compare(control.currentItem.checked, true)
-
- control.destroy()
}
function test_addRemove() {
- var control = tabBar.createObject(testCase)
+ var control = createTemporaryObject(tabBar, testCase)
function verifyCurrentIndexCountDiff() {
verify(control.currentIndex < control.count)
@@ -176,7 +169,7 @@ TestCase {
control.currentIndexChanged.connect(verifyCurrentIndexCountDiff)
control.countChanged.connect(verifyCurrentIndexCountDiff)
- var contentChildrenSpy = signalSpy.createObject(testCase, {target: control, signalName: "contentChildrenChanged"})
+ var contentChildrenSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "contentChildrenChanged"})
verify(contentChildrenSpy.valid)
compare(control.count, 0)
@@ -265,8 +258,6 @@ TestCase {
compare(control.count, 0)
compare(control.currentIndex, -1)
compare(contentChildrenSpy.count, 12)
-
- control.destroy()
}
Component {
@@ -281,7 +272,7 @@ TestCase {
}
function test_content() {
- var control = contentBar.createObject(testCase)
+ var control = createTemporaryObject(contentBar, testCase)
function compareObjectNames(content, names) {
if (content.length !== names.length)
@@ -293,7 +284,7 @@ TestCase {
return true
}
- var contentChildrenSpy = signalSpy.createObject(testCase, {target: control, signalName: "contentChildrenChanged"})
+ var contentChildrenSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "contentChildrenChanged"})
verify(contentChildrenSpy.valid)
verify(compareObjectNames(control.contentData, ["object", "button1", "timer", "button2", ""]))
@@ -318,8 +309,6 @@ TestCase {
verify(compareObjectNames(control.contentData, ["object", "button1", "timer", "button2", "", "button3"]))
verify(compareObjectNames(control.contentChildren, ["button2", "button1", "button3"]))
compare(contentChildrenSpy.count, 5)
-
- control.destroy()
}
Component {
@@ -335,7 +324,7 @@ TestCase {
}
function test_repeater() {
- var control = repeated.createObject(testCase)
+ var control = createTemporaryObject(repeated, testCase)
verify(control)
var model = control.contentModel
@@ -366,8 +355,6 @@ TestCase {
compare(model.get(j), item2)
compare(repeater.itemAt(j), item2)
}
-
- control.destroy()
}
Component {
@@ -391,7 +378,7 @@ TestCase {
}
function test_order() {
- var control = ordered.createObject(testCase)
+ var control = createTemporaryObject(ordered, testCase)
verify(control)
compare(control.count, 7)
@@ -402,8 +389,6 @@ TestCase {
compare(control.itemAt(4).text, "static_4")
compare(control.itemAt(5).text, "dynamic_5")
compare(control.itemAt(6).text, "dynamic_6")
-
- control.destroy()
}
function test_move_data() {
@@ -442,7 +427,7 @@ TestCase {
}
function test_move(data) {
- var control = tabBar.createObject(testCase)
+ var control = createTemporaryObject(tabBar, testCase)
compare(control.count, 0)
var titles = ["1", "2", "3"]
@@ -468,8 +453,6 @@ TestCase {
compare(control.count, titles.length)
for (i = 0; i < control.count; ++i)
compare(control.itemAt(i).text, titles[i])
-
- control.destroy()
}
Component {
@@ -486,7 +469,7 @@ TestCase {
}
function test_dynamic() {
- var control = dynamicBar.createObject(testCase)
+ var control = createTemporaryObject(dynamicBar, testCase)
// insertItem(), addItem(), createObject() and static TabButton {}
compare(control.count, 4)
@@ -500,8 +483,6 @@ TestCase {
// tab.destroy()
// wait(0)
// compare(control.count, 4)
-
- control.destroy()
}
function test_layout_data() {
@@ -513,29 +494,49 @@ TestCase {
}
function test_layout(data) {
- var control = tabBar.createObject(testCase, {spacing: data.spacing, width: 200})
+ var control = createTemporaryObject(tabBar, testCase, {spacing: data.spacing, width: 200})
+
+ // remove the implicit size from the background so that it won't affect
+ // the implicit size of the tabbar, so the implicit sizes tested below
+ // are entirely based on the content size
+ control.background.implicitWidth = 0
var tab1 = tabButton.createObject(control, {text: "First"})
control.addItem(tab1)
tryCompare(tab1, "width", control.width)
+ compare(control.contentWidth, tab1.implicitWidth)
+ compare(control.implicitWidth, control.contentWidth + control.leftPadding + control.rightPadding)
var tab2 = tabButton.createObject(control, {text: "Second"})
control.addItem(tab2)
tryCompare(tab1, "width", (control.width - data.spacing) / 2)
compare(tab2.width, (control.width - data.spacing) / 2)
+ compare(control.contentWidth, tab1.implicitWidth + tab2.implicitWidth + data.spacing)
+ compare(control.implicitWidth, control.contentWidth + control.leftPadding + control.rightPadding)
var tab3 = tabButton.createObject(control, {width: 50, text: "Third"})
control.addItem(tab3)
tryCompare(tab1, "width", (control.width - 2 * data.spacing - 50) / 2)
compare(tab2.width, (control.width - 2 * data.spacing - 50) / 2)
compare(tab3.width, 50)
+ compare(control.contentWidth, tab1.implicitWidth + tab2.implicitWidth + tab3.width + 2 * data.spacing)
+ compare(control.implicitWidth, control.contentWidth + control.leftPadding + control.rightPadding)
var expectedWidth = tab3.contentItem.implicitWidth + tab3.leftPadding + tab3.rightPadding
tab3.width = tab3.implicitWidth
tryCompare(tab1, "width", (control.width - 2 * data.spacing - expectedWidth) / 2)
tryCompare(tab2, "width", (control.width - 2 * data.spacing - expectedWidth) / 2)
compare(tab3.width, expectedWidth)
+ compare(control.contentWidth, tab1.implicitWidth + tab2.implicitWidth + tab3.implicitWidth + 2 * data.spacing)
+ compare(control.implicitWidth, control.contentWidth + control.leftPadding + control.rightPadding)
+
+ tab3.width = undefined
+ control.width = undefined
- control.destroy()
+ control.contentWidth = 300
+ expectedWidth = (control.contentWidth - 2 * data.spacing) / 3
+ tryCompare(tab1, "width", expectedWidth)
+ tryCompare(tab2, "width", expectedWidth)
+ tryCompare(tab3, "width", expectedWidth)
}
}
diff --git a/tests/auto/controls/data/tst_tabbutton.qml b/tests/auto/controls/data/tst_tabbutton.qml
index 98bb542a..72ea4e58 100644
--- a/tests/auto/controls/data/tst_tabbutton.qml
+++ b/tests/auto/controls/data/tst_tabbutton.qml
@@ -66,7 +66,7 @@ TestCase {
}
function test_autoExclusive() {
- var container = repeater.createObject(testCase)
+ var container = createTemporaryObject(repeater, testCase)
for (var i = 0; i < 3; ++i) {
container.children[i].checked = true
@@ -78,14 +78,11 @@ TestCase {
compare(container.children[j].checked, false)
}
}
-
- container.destroy()
}
function test_baseline() {
- var control = tabButton.createObject(testCase)
+ var control = createTemporaryObject(tabButton, testCase)
verify(control)
compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset)
- control.destroy()
}
}
diff --git a/tests/auto/controls/data/tst_textarea.qml b/tests/auto/controls/data/tst_textarea.qml
index e058ec19..de3e6854 100644
--- a/tests/auto/controls/data/tst_textarea.qml
+++ b/tests/auto/controls/data/tst_textarea.qml
@@ -70,13 +70,12 @@ TestCase {
}
function test_creation() {
- var control = textArea.createObject(testCase)
+ var control = createTemporaryObject(textArea, testCase)
verify(control)
- control.destroy()
}
function test_implicitSize() {
- var control = textArea.createObject(testCase)
+ var control = createTemporaryObject(textArea, testCase)
var implicitWidthSpy = signalSpy.createObject(control, { target: control, signalName: "implicitWidthChanged"} )
var implicitHeightSpy = signalSpy.createObject(control, { target: control, signalName: "implicitHeightChanged"} )
@@ -86,18 +85,65 @@ TestCase {
compare(control.implicitHeight, 200)
compare(implicitWidthSpy.count, 1)
compare(implicitHeightSpy.count, 1)
+ }
- control.destroy()
+ function test_alignment_data() {
+ return [
+ { tag: "empty", text: "", placeholderText: "", textAlignment: undefined, placeholderAlignment: Qt.AlignLeft },
+ { tag: "empty,left", text: "", placeholderText: "", textAlignment: Qt.AlignLeft, placeholderAlignment: Qt.AlignLeft },
+ { tag: "empty,center", text: "", placeholderText: "", textAlignment: Qt.AlignHCenter, placeholderAlignment: Qt.AlignHCenter },
+ { tag: "empty,right", text: "", placeholderText: "", textAlignment: Qt.AlignRight, placeholderAlignment: Qt.AlignRight },
+
+ { tag: "empty,ltr", text: "", placeholderText: "Search", textAlignment: undefined, placeholderAlignment: Qt.AlignLeft },
+ { tag: "empty,ltr,left", text: "", placeholderText: "Search", textAlignment: Qt.AlignLeft, placeholderAlignment: Qt.AlignLeft },
+ { tag: "empty,ltr,center", text: "", placeholderText: "Search", textAlignment: Qt.AlignHCenter, placeholderAlignment: Qt.AlignHCenter },
+ { tag: "empty,ltr,right", text: "", placeholderText: "Search", textAlignment: Qt.AlignRight, placeholderAlignment: Qt.AlignRight },
+
+ { tag: "empty,rtl", text: "", placeholderText: "بحث", textAlignment: undefined, placeholderAlignment: Qt.AlignRight },
+ { tag: "empty,rtl,left", text: "", placeholderText: "بحث", textAlignment: Qt.AlignLeft, placeholderAlignment: Qt.AlignLeft },
+ { tag: "empty,rtl,center", text: "", placeholderText: "بحث", textAlignment: Qt.AlignHCenter, placeholderAlignment: Qt.AlignHCenter },
+ { tag: "empty,rtl,right", text: "", placeholderText: "بحث", textAlignment: Qt.AlignRight, placeholderAlignment: Qt.AlignRight },
+
+ { tag: "ltr,empty", text: "Text", placeholderText: "", textAlignment: undefined, placeholderAlignment: Qt.AlignLeft },
+ { tag: "ltr,empty,left", text: "Text", placeholderText: "", textAlignment: Qt.AlignLeft, placeholderAlignment: Qt.AlignLeft },
+ { tag: "ltr,empty,center", text: "Text", placeholderText: "", textAlignment: Qt.AlignHCenter, placeholderAlignment: Qt.AlignHCenter },
+ { tag: "ltr,empty,right", text: "Text", placeholderText: "", textAlignment: Qt.AlignRight, placeholderAlignment: Qt.AlignRight },
+
+ { tag: "ltr,ltr", text: "Text", placeholderText: "Search", textAlignment: undefined, placeholderAlignment: Qt.AlignLeft },
+ { tag: "ltr,ltr,left", text: "Text", placeholderText: "Search", textAlignment: Qt.AlignLeft, placeholderAlignment: Qt.AlignLeft },
+ { tag: "ltr,ltr,center", text: "Text", placeholderText: "Search", textAlignment: Qt.AlignHCenter, placeholderAlignment: Qt.AlignHCenter },
+ { tag: "ltr,ltr,right", text: "Text", placeholderText: "Search", textAlignment: Qt.AlignRight, placeholderAlignment: Qt.AlignRight },
+
+ { tag: "ltr,rtl", text: "Text", placeholderText: "بحث", textAlignment: undefined, placeholderAlignment: Qt.AlignRight },
+ { tag: "ltr,rtl,left", text: "Text", placeholderText: "بحث", textAlignment: Qt.AlignLeft, placeholderAlignment: Qt.AlignLeft },
+ { tag: "ltr,rtl,center", text: "Text", placeholderText: "بحث", textAlignment: Qt.AlignHCenter, placeholderAlignment: Qt.AlignHCenter },
+ { tag: "ltr,rtl,right", text: "Text", placeholderText: "بحث", textAlignment: Qt.AlignRight, placeholderAlignment: Qt.AlignRight },
+
+ { tag: "rtl,empty", text: "نص", placeholderText: "", textAlignment: undefined, placeholderAlignment: Qt.AlignLeft },
+ { tag: "rtl,empty,left", text: "نص", placeholderText: "", textAlignment: Qt.AlignLeft, placeholderAlignment: Qt.AlignLeft },
+ { tag: "rtl,empty,center", text: "نص", placeholderText: "", textAlignment: Qt.AlignHCenter, placeholderAlignment: Qt.AlignHCenter },
+ { tag: "rtl,empty,right", text: "نص", placeholderText: "", textAlignment: Qt.AlignRight, placeholderAlignment: Qt.AlignRight },
+
+ { tag: "rtl,ltr", text: "نص", placeholderText: "Search", textAlignment: undefined, placeholderAlignment: Qt.AlignLeft },
+ { tag: "rtl,ltr,left", text: "نص", placeholderText: "Search", textAlignment: Qt.AlignLeft, placeholderAlignment: Qt.AlignLeft },
+ { tag: "rtl,ltr,center", text: "نص", placeholderText: "Search", textAlignment: Qt.AlignHCenter, placeholderAlignment: Qt.AlignHCenter },
+ { tag: "rtl,ltr,right", text: "نص", placeholderText: "Search", textAlignment: Qt.AlignRight, placeholderAlignment: Qt.AlignRight },
+
+ { tag: "rtl,rtl", text: "نص", placeholderText: "بحث", textAlignment: undefined, placeholderAlignment: Qt.AlignRight },
+ { tag: "rtl,rtl,left", text: "نص", placeholderText: "بحث", textAlignment: Qt.AlignLeft, placeholderAlignment: Qt.AlignLeft },
+ { tag: "rtl,rtl,center", text: "نص", placeholderText: "بحث", textAlignment: Qt.AlignHCenter, placeholderAlignment: Qt.AlignHCenter },
+ { tag: "rtl,rtl,right", text: "نص", placeholderText: "بحث", textAlignment: Qt.AlignRight, placeholderAlignment: Qt.AlignRight },
+ ]
}
- function test_alignment() {
- var control = textArea.createObject(testCase)
+ function test_alignment(data) {
+ var control = createTemporaryObject(textArea, testCase, {text: data.text, placeholderText: data.placeholderText, horizontalAlignment: data.textAlignment})
- control.horizontalAlignment = TextArea.AlignRight
- compare(control.horizontalAlignment, TextArea.AlignRight)
+ if (data.textAlignment !== undefined)
+ compare(control.horizontalAlignment, data.textAlignment)
for (var i = 0; i < control.children.length; ++i) {
if (control.children[i].hasOwnProperty("horizontalAlignment"))
- compare(control.children[i].horizontalAlignment, Text.AlignRight) // placeholder
+ compare(control.children[i].effectiveHorizontalAlignment, data.placeholderAlignment) // placeholder
}
control.verticalAlignment = TextArea.AlignBottom
@@ -106,8 +152,6 @@ TestCase {
if (control.children[j].hasOwnProperty("verticalAlignment"))
compare(control.children[j].verticalAlignment, Text.AlignBottom) // placeholder
}
-
- control.destroy()
}
function test_font_explicit_attributes_data() {
@@ -124,7 +168,7 @@ TestCase {
}
function test_font_explicit_attributes(data) {
- var control = textArea.createObject(testCase)
+ var control = createTemporaryObject(textArea, testCase)
verify(control)
var child = textArea.createObject(control)
@@ -149,12 +193,10 @@ TestCase {
compare(child.font[data.tag], defaultValue)
compare(childSpy.count, 0)
-
- control.destroy()
}
function test_flickable() {
- var control = flickable.createObject(testCase, {text:"line0", selectByMouse: true})
+ var control = createTemporaryObject(flickable, testCase, {text:"line0", selectByMouse: true})
verify(control)
var textArea = control.TextArea.flickable
@@ -190,8 +232,6 @@ TestCase {
verify(above > 0 && above < center)
mouseClick(textArea, control.width / 2, 0)
compare(textArea.cursorPosition, center) // no change
-
- control.destroy()
}
function test_warning() {
@@ -207,7 +247,7 @@ TestCase {
}
function test_hover(data) {
- var control = textArea.createObject(testCase, {text: "TextArea", hoverEnabled: data.hoverEnabled})
+ var control = createTemporaryObject(textArea, testCase, {text: "TextArea", hoverEnabled: data.hoverEnabled})
verify(control)
compare(control.hovered, false)
@@ -217,8 +257,6 @@ TestCase {
mouseMove(control, -1, -1)
compare(control.hovered, false)
-
- control.destroy()
}
function test_pressedReleased_data() {
@@ -274,7 +312,7 @@ TestCase {
}
function test_pressedReleased(data) {
- var mouseArea = mouseAreaComponent.createObject(testCase)
+ var mouseArea = createTemporaryObject(mouseAreaComponent, testCase)
verify(mouseArea)
var control = textArea.createObject(mouseArea, {text: "TextArea"})
verify(control)
@@ -321,8 +359,6 @@ TestCase {
mouseRelease(control, data.x, data.y, data.button)
compare(controlReleasedSpy.count, data.controlReleaseEvent ? 1 : 0)
compare(parentReleasedSpy.count, data.parentReleaseEvent ? 1 : 0)
-
- mouseArea.destroy()
}
Component {
@@ -346,7 +382,7 @@ TestCase {
}
function test_ignorePressRelease() {
- var mouseArea = mouseAreaComponent.createObject(testCase)
+ var mouseArea = createTemporaryObject(mouseAreaComponent, testCase)
verify(mouseArea)
var control = ignoreTextArea.createObject(mouseArea)
verify(control)
@@ -385,12 +421,10 @@ TestCase {
compare(parentReleasedSpy.count, 1)
control.onPressed.disconnect(checkEventAccepted)
control.onReleased.disconnect(checkEventIgnored)
-
- mouseArea.destroy()
}
function test_multiClick() {
- var control = textArea.createObject(testCase, {text: "Qt Quick Controls 2 TextArea", selectByMouse: true})
+ var control = createTemporaryObject(textArea, testCase, {text: "Qt Quick Controls 2 TextArea", selectByMouse: true})
verify(control)
waitForRendering(control)
@@ -404,7 +438,5 @@ TestCase {
// tripple click -> select whole line
mouseClick(control, rect.x + rect.width / 2, rect.y + rect.height / 2)
compare(control.selectedText, "Qt Quick Controls 2 TextArea")
-
- control.destroy()
}
}
diff --git a/tests/auto/controls/data/tst_textfield.qml b/tests/auto/controls/data/tst_textfield.qml
index 4847dffe..a6686a13 100644
--- a/tests/auto/controls/data/tst_textfield.qml
+++ b/tests/auto/controls/data/tst_textfield.qml
@@ -61,13 +61,12 @@ TestCase {
}
function test_creation() {
- var control = textField.createObject(testCase)
+ var control = createTemporaryObject(textField, testCase)
verify(control)
- control.destroy()
}
function test_implicitSize() {
- var control = textField.createObject(testCase)
+ var control = createTemporaryObject(textField, testCase)
verify(control.implicitWidth > control.leftPadding + control.rightPadding)
var implicitWidthSpy = signalSpy.createObject(control, { target: control, signalName: "implicitWidthChanged"} )
@@ -97,18 +96,65 @@ TestCase {
compare(control.implicitHeight, control.contentHeight + control.topPadding + control.bottomPadding)
compare(implicitWidthSpy.count, 4)
compare(implicitHeightSpy.count, 2)
+ }
- control.destroy()
+ function test_alignment_data() {
+ return [
+ { tag: "empty", text: "", placeholderText: "", textAlignment: undefined, placeholderAlignment: Qt.AlignLeft },
+ { tag: "empty,left", text: "", placeholderText: "", textAlignment: Qt.AlignLeft, placeholderAlignment: Qt.AlignLeft },
+ { tag: "empty,center", text: "", placeholderText: "", textAlignment: Qt.AlignHCenter, placeholderAlignment: Qt.AlignHCenter },
+ { tag: "empty,right", text: "", placeholderText: "", textAlignment: Qt.AlignRight, placeholderAlignment: Qt.AlignRight },
+
+ { tag: "empty,ltr", text: "", placeholderText: "Search", textAlignment: undefined, placeholderAlignment: Qt.AlignLeft },
+ { tag: "empty,ltr,left", text: "", placeholderText: "Search", textAlignment: Qt.AlignLeft, placeholderAlignment: Qt.AlignLeft },
+ { tag: "empty,ltr,center", text: "", placeholderText: "Search", textAlignment: Qt.AlignHCenter, placeholderAlignment: Qt.AlignHCenter },
+ { tag: "empty,ltr,right", text: "", placeholderText: "Search", textAlignment: Qt.AlignRight, placeholderAlignment: Qt.AlignRight },
+
+ { tag: "empty,rtl", text: "", placeholderText: "بحث", textAlignment: undefined, placeholderAlignment: Qt.AlignRight },
+ { tag: "empty,rtl,left", text: "", placeholderText: "بحث", textAlignment: Qt.AlignLeft, placeholderAlignment: Qt.AlignLeft },
+ { tag: "empty,rtl,center", text: "", placeholderText: "بحث", textAlignment: Qt.AlignHCenter, placeholderAlignment: Qt.AlignHCenter },
+ { tag: "empty,rtl,right", text: "", placeholderText: "بحث", textAlignment: Qt.AlignRight, placeholderAlignment: Qt.AlignRight },
+
+ { tag: "ltr,empty", text: "Text", placeholderText: "", textAlignment: undefined, placeholderAlignment: Qt.AlignLeft },
+ { tag: "ltr,empty,left", text: "Text", placeholderText: "", textAlignment: Qt.AlignLeft, placeholderAlignment: Qt.AlignLeft },
+ { tag: "ltr,empty,center", text: "Text", placeholderText: "", textAlignment: Qt.AlignHCenter, placeholderAlignment: Qt.AlignHCenter },
+ { tag: "ltr,empty,right", text: "Text", placeholderText: "", textAlignment: Qt.AlignRight, placeholderAlignment: Qt.AlignRight },
+
+ { tag: "ltr,ltr", text: "Text", placeholderText: "Search", textAlignment: undefined, placeholderAlignment: Qt.AlignLeft },
+ { tag: "ltr,ltr,left", text: "Text", placeholderText: "Search", textAlignment: Qt.AlignLeft, placeholderAlignment: Qt.AlignLeft },
+ { tag: "ltr,ltr,center", text: "Text", placeholderText: "Search", textAlignment: Qt.AlignHCenter, placeholderAlignment: Qt.AlignHCenter },
+ { tag: "ltr,ltr,right", text: "Text", placeholderText: "Search", textAlignment: Qt.AlignRight, placeholderAlignment: Qt.AlignRight },
+
+ { tag: "ltr,rtl", text: "Text", placeholderText: "بحث", textAlignment: undefined, placeholderAlignment: Qt.AlignRight },
+ { tag: "ltr,rtl,left", text: "Text", placeholderText: "بحث", textAlignment: Qt.AlignLeft, placeholderAlignment: Qt.AlignLeft },
+ { tag: "ltr,rtl,center", text: "Text", placeholderText: "بحث", textAlignment: Qt.AlignHCenter, placeholderAlignment: Qt.AlignHCenter },
+ { tag: "ltr,rtl,right", text: "Text", placeholderText: "بحث", textAlignment: Qt.AlignRight, placeholderAlignment: Qt.AlignRight },
+
+ { tag: "rtl,empty", text: "نص", placeholderText: "", textAlignment: undefined, placeholderAlignment: Qt.AlignLeft },
+ { tag: "rtl,empty,left", text: "نص", placeholderText: "", textAlignment: Qt.AlignLeft, placeholderAlignment: Qt.AlignLeft },
+ { tag: "rtl,empty,center", text: "نص", placeholderText: "", textAlignment: Qt.AlignHCenter, placeholderAlignment: Qt.AlignHCenter },
+ { tag: "rtl,empty,right", text: "نص", placeholderText: "", textAlignment: Qt.AlignRight, placeholderAlignment: Qt.AlignRight },
+
+ { tag: "rtl,ltr", text: "نص", placeholderText: "Search", textAlignment: undefined, placeholderAlignment: Qt.AlignLeft },
+ { tag: "rtl,ltr,left", text: "نص", placeholderText: "Search", textAlignment: Qt.AlignLeft, placeholderAlignment: Qt.AlignLeft },
+ { tag: "rtl,ltr,center", text: "نص", placeholderText: "Search", textAlignment: Qt.AlignHCenter, placeholderAlignment: Qt.AlignHCenter },
+ { tag: "rtl,ltr,right", text: "نص", placeholderText: "Search", textAlignment: Qt.AlignRight, placeholderAlignment: Qt.AlignRight },
+
+ { tag: "rtl,rtl", text: "نص", placeholderText: "بحث", textAlignment: undefined, placeholderAlignment: Qt.AlignRight },
+ { tag: "rtl,rtl,left", text: "نص", placeholderText: "بحث", textAlignment: Qt.AlignLeft, placeholderAlignment: Qt.AlignLeft },
+ { tag: "rtl,rtl,center", text: "نص", placeholderText: "بحث", textAlignment: Qt.AlignHCenter, placeholderAlignment: Qt.AlignHCenter },
+ { tag: "rtl,rtl,right", text: "نص", placeholderText: "بحث", textAlignment: Qt.AlignRight, placeholderAlignment: Qt.AlignRight },
+ ]
}
- function test_alignment() {
- var control = textField.createObject(testCase)
+ function test_alignment(data) {
+ var control = createTemporaryObject(textField, testCase, {text: data.text, placeholderText: data.placeholderText, horizontalAlignment: data.textAlignment})
- control.horizontalAlignment = TextField.AlignRight
- compare(control.horizontalAlignment, TextField.AlignRight)
+ if (data.textAlignment !== undefined)
+ compare(control.horizontalAlignment, data.textAlignment)
for (var i = 0; i < control.children.length; ++i) {
if (control.children[i].hasOwnProperty("horizontalAlignment"))
- compare(control.children[i].horizontalAlignment, Text.AlignRight) // placeholder
+ compare(control.children[i].effectiveHorizontalAlignment, data.placeholderAlignment) // placeholder
}
control.verticalAlignment = TextField.AlignBottom
@@ -117,8 +163,6 @@ TestCase {
if (control.children[j].hasOwnProperty("verticalAlignment"))
compare(control.children[j].verticalAlignment, Text.AlignBottom) // placeholder
}
-
- control.destroy()
}
function test_font_explicit_attributes_data() {
@@ -135,7 +179,7 @@ TestCase {
}
function test_font_explicit_attributes(data) {
- var control = textField.createObject(testCase)
+ var control = createTemporaryObject(textField, testCase)
verify(control)
var child = textField.createObject(control)
@@ -160,8 +204,6 @@ TestCase {
compare(child.font[data.tag], defaultValue)
compare(childSpy.count, 0)
-
- control.destroy()
}
function test_hover_data() {
@@ -172,7 +214,7 @@ TestCase {
}
function test_hover(data) {
- var control = textField.createObject(testCase, {hoverEnabled: data.hoverEnabled})
+ var control = createTemporaryObject(textField, testCase, {hoverEnabled: data.hoverEnabled})
verify(control)
compare(control.hovered, false)
@@ -182,8 +224,6 @@ TestCase {
mouseMove(control, -1, -1)
compare(control.hovered, false)
-
- control.destroy()
}
function test_pressedReleased_data() {
@@ -239,7 +279,7 @@ TestCase {
}
function test_pressedReleased(data) {
- var mouseArea = mouseAreaComponent.createObject(testCase)
+ var mouseArea = createTemporaryObject(mouseAreaComponent, testCase)
verify(mouseArea)
var control = textField.createObject(mouseArea)
verify(control)
@@ -286,8 +326,6 @@ TestCase {
mouseRelease(control, data.x, data.y, data.button)
compare(controlReleasedSpy.count, data.controlReleaseEvent ? 1 : 0)
compare(parentReleasedSpy.count, data.parentReleaseEvent ? 1 : 0)
-
- mouseArea.destroy()
}
Component {
@@ -311,7 +349,7 @@ TestCase {
}
function test_ignorePressRelease() {
- var mouseArea = mouseAreaComponent.createObject(testCase)
+ var mouseArea = createTemporaryObject(mouseAreaComponent, testCase)
verify(mouseArea)
var control = ignoreTextField.createObject(mouseArea)
verify(control)
@@ -350,12 +388,10 @@ TestCase {
compare(parentReleasedSpy.count, 1)
control.onPressed.disconnect(checkEventAccepted)
control.onReleased.disconnect(checkEventIgnored)
-
- mouseArea.destroy()
}
function test_multiClick() {
- var control = textField.createObject(testCase, {text: "Qt Quick Controls 2 TextArea", selectByMouse: true})
+ var control = createTemporaryObject(textField, testCase, {text: "Qt Quick Controls 2 TextArea", selectByMouse: true})
verify(control)
waitForRendering(control)
@@ -369,7 +405,5 @@ TestCase {
// tripple click -> select whole line
mouseClick(control, rect.x + rect.width / 2, rect.y + rect.height / 2)
compare(control.selectedText, "Qt Quick Controls 2 TextArea")
-
- control.destroy()
}
}
diff --git a/tests/auto/controls/data/tst_toolbar.qml b/tests/auto/controls/data/tst_toolbar.qml
index 49459b12..56d279ef 100644
--- a/tests/auto/controls/data/tst_toolbar.qml
+++ b/tests/auto/controls/data/tst_toolbar.qml
@@ -90,49 +90,41 @@ TestCase {
}
function test_empty() {
- var control = toolBar.createObject(testCase)
+ var control = createTemporaryObject(toolBar, testCase)
verify(control)
verify(control.contentItem)
compare(control.contentWidth, 0)
compare(control.contentHeight, 0)
-
- control.destroy()
}
function test_oneChild() {
- var control = oneChildBar.createObject(testCase)
+ var control = createTemporaryObject(oneChildBar, testCase)
verify(control)
compare(control.contentWidth, 100)
compare(control.contentHeight, 30)
verify(control.implicitWidth >= 100)
verify(control.implicitHeight >= 30)
-
- control.destroy()
}
function test_twoChildren() {
- var control = twoChildrenBar.createObject(testCase)
+ var control = createTemporaryObject(twoChildrenBar, testCase)
verify(control)
compare(control.contentWidth, 0)
compare(control.contentHeight, 0)
verify(control.implicitWidth >= 0)
verify(control.implicitHeight >= 0)
-
- control.destroy()
}
function test_contentItem() {
- var control = contentBar.createObject(testCase)
+ var control = createTemporaryObject(contentBar, testCase)
verify(control)
compare(control.contentWidth, 100)
compare(control.contentHeight, 30)
verify(control.implicitWidth >= 100)
verify(control.implicitHeight >= 30)
-
- control.destroy()
}
}
diff --git a/tests/auto/controls/data/tst_toolbutton.qml b/tests/auto/controls/data/tst_toolbutton.qml
index c00661f0..eef15d02 100644
--- a/tests/auto/controls/data/tst_toolbutton.qml
+++ b/tests/auto/controls/data/tst_toolbutton.qml
@@ -61,7 +61,7 @@ TestCase {
}
function test_text() {
- var control = toolButton.createObject(testCase)
+ var control = createTemporaryObject(toolButton, testCase)
verify(control)
compare(control.text, "")
@@ -69,12 +69,10 @@ TestCase {
compare(control.text, "ToolButton")
control.text = ""
compare(control.text, "")
-
- control.destroy()
}
function test_mouse() {
- var control = toolButton.createObject(testCase)
+ var control = createTemporaryObject(toolButton, testCase)
verify(control)
var pressedSpy = signalSpy.createObject(control, {target: control, signalName: "pressedChanged"})
@@ -140,12 +138,10 @@ TestCase {
compare(downSpy.count, 6)
compare(control.pressed, false)
compare(control.down, false)
-
- control.destroy()
}
function test_keys() {
- var control = toolButton.createObject(testCase)
+ var control = createTemporaryObject(toolButton, testCase)
verify(control)
var clickedSpy = signalSpy.createObject(control, {target: control, signalName: "clicked"})
@@ -168,14 +164,11 @@ TestCase {
keyClick(keys[i])
compare(clickedSpy.count, 2)
}
-
- control.destroy()
}
function test_baseline() {
- var control = toolButton.createObject(testCase)
+ var control = createTemporaryObject(toolButton, testCase)
verify(control)
compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset)
- control.destroy()
}
}
diff --git a/tests/auto/controls/data/tst_toolseparator.qml b/tests/auto/controls/data/tst_toolseparator.qml
index a87ca5a2..bd11bfb1 100644
--- a/tests/auto/controls/data/tst_toolseparator.qml
+++ b/tests/auto/controls/data/tst_toolseparator.qml
@@ -55,12 +55,10 @@ TestCase {
}
function test_size() {
- var control = toolSeparator.createObject(testCase);
+ var control = createTemporaryObject(toolSeparator, testCase);
verify(control);
verify(control.width > 1);
verify(control.height > 1);
-
- control.destroy();
}
Component {
@@ -69,7 +67,7 @@ TestCase {
}
function test_orientation() {
- var control = toolSeparator.createObject(testCase);
+ var control = createTemporaryObject(toolSeparator, testCase);
verify(control);
compare(control.horizontal, false);
compare(control.vertical, true);
@@ -93,7 +91,5 @@ TestCase {
compare(control.horizontal, false);
compare(control.vertical, true);
compare(orientationSpy.count, 2);
-
- control.destroy();
}
}
diff --git a/tests/auto/controls/data/tst_tooltip.qml b/tests/auto/controls/data/tst_tooltip.qml
index 3e50ee25..9529922b 100644
--- a/tests/auto/controls/data/tst_tooltip.qml
+++ b/tests/auto/controls/data/tst_tooltip.qml
@@ -69,6 +69,11 @@ TestCase {
id: object
}
+ SignalSpy {
+ id: sharedSpy
+ target: ToolTip.toolTip
+ }
+
function test_properties_data() {
return [
{tag: "text", property: "text", defaultValue: "", setValue: "Hello", signalName: "textChanged"},
@@ -119,8 +124,9 @@ TestCase {
verify(spy2.valid)
var sharedTip = ToolTip.toolTip
- var sharedSpy = signalSpy.createObject(testCase, {target: sharedTip, signalName: data.signalName})
+ sharedSpy.signalName = data.signalName
verify(sharedSpy.valid)
+ sharedSpy.clear()
// change attached properties while the shared tooltip is not visible
item1.ToolTip[data.property] = data.setValue
diff --git a/tests/auto/controls/data/tst_tumbler.qml b/tests/auto/controls/data/tst_tumbler.qml
index c200d733..d371c877 100644
--- a/tests/auto/controls/data/tst_tumbler.qml
+++ b/tests/auto/controls/data/tst_tumbler.qml
@@ -40,7 +40,7 @@
import QtQuick 2.2
import QtTest 1.0
-import QtQuick.Controls 2.1
+import QtQuick.Controls 2.2
TestCase {
id: testCase
@@ -51,9 +51,6 @@ TestCase {
name: "Tumbler"
property var tumbler: null
- // With the help of cleanup(), ensures that all items created during a test function
- // are destroyed if that test fails.
- property Item cleanupItem
readonly property real implicitTumblerWidth: 60
readonly property real implicitTumblerHeight: 200
readonly property real defaultImplicitDelegateHeight: implicitTumblerHeight / 3
@@ -77,23 +74,8 @@ TestCase {
}
}
- function init() {
- cleanupItem = itemComponent.createObject(testCase);
- verify(cleanupItem);
- }
-
- function cleanup() {
- cleanupItem.destroy();
- // Waiting until it's deleted before continuing makes debugging
- // test failures much easier, because there aren't unrelated items hanging around.
- tryVerify(function() { return !tumbler; });
- }
-
function createTumbler(args) {
- if (args === undefined)
- tumbler = tumblerComponent.createObject(cleanupItem);
- else
- tumbler = tumblerComponent.createObject(cleanupItem, args);
+ tumbler = createTemporaryObject(tumblerComponent, testCase, args);
verify(tumbler, "Tumbler: failed to create an instance");
tumblerView = findView(tumbler);
verify(tumblerView);
@@ -278,7 +260,7 @@ TestCase {
function test_currentIndexAtCreation(data) {
// Test setting currentIndex at creation time
- tumbler = data.component.createObject(cleanupItem);
+ tumbler = createTemporaryObject(data.component, testCase);
verify(tumbler);
// A "statically declared" currentIndex will be pending until the count has changed,
// which happens when the model is set, which happens on the TumblerView's next polish.
@@ -344,7 +326,7 @@ TestCase {
wait(tumblerView.highlightMoveDuration);
var firstItemCenterPos = itemCenterPos(1);
var firstItem = tumblerView.itemAt(firstItemCenterPos.x, firstItemCenterPos.y);
- var actualPos = cleanupItem.mapFromItem(firstItem, 0, 0);
+ var actualPos = testCase.mapFromItem(firstItem, 0, 0);
compare(actualPos.x, tumbler.leftPadding);
compare(actualPos.y, tumbler.topPadding + 40);
@@ -355,7 +337,7 @@ TestCase {
firstItem = tumblerView.itemAt(firstItemCenterPos.x, firstItemCenterPos.y);
verify(firstItem);
// Test QTBUG-40298.
- actualPos = cleanupItem.mapFromItem(firstItem, 0, 0);
+ actualPos = testCase.mapFromItem(firstItem, 0, 0);
compare(actualPos.x, tumbler.leftPadding);
compare(actualPos.y, tumbler.topPadding);
@@ -372,11 +354,11 @@ TestCase {
}
function test_focusPastTumbler() {
- tumbler = tumblerComponent.createObject(cleanupItem);
+ tumbler = createTemporaryObject(tumblerComponent, testCase);
verify(tumbler);
- var mouseArea = Qt.createQmlObject(
- "import QtQuick 2.2; TextInput { activeFocusOnTab: true; width: 50; height: 50 }", cleanupItem, "");
+ var mouseArea = createTemporaryQmlObject(
+ "import QtQuick 2.2; TextInput { activeFocusOnTab: true; width: 50; height: 50 }", testCase, "");
tumbler.forceActiveFocus();
verify(tumbler.activeFocus);
@@ -389,7 +371,7 @@ TestCase {
function test_datePicker() {
var component = Qt.createComponent("TumblerDatePicker.qml");
compare(component.status, Component.Ready, component.errorString());
- tumbler = component.createObject(cleanupItem);
+ tumbler = createTemporaryObject(component, testCase);
// Should not be any warnings.
tryCompare(tumbler.dayTumbler, "currentIndex", 0);
@@ -449,7 +431,7 @@ TestCase {
}
function test_listViewTimePicker() {
- var root = timePickerComponent.createObject(cleanupItem);
+ var root = createTemporaryObject(timePickerComponent, testCase);
verify(root);
mouseDrag(root.minuteTumbler, root.minuteTumbler.width / 2, root.minuteTumbler.height / 2, 0, 50);
@@ -566,7 +548,7 @@ TestCase {
}
function test_countWrap() {
- tumbler = tumblerComponent.createObject(cleanupItem);
+ tumbler = createTemporaryObject(tumblerComponent, testCase);
verify(tumbler);
// Check that a count that is less than visibleItemCount results in wrap being set to false.
@@ -578,7 +560,7 @@ TestCase {
function test_explicitlyNonwrapping() {
// Check that explicitly setting wrap to false works even when it was implicitly false.
- var explicitlyNonWrapping = twoItemTumbler.createObject(cleanupItem);
+ var explicitlyNonWrapping = createTemporaryObject(twoItemTumbler, testCase);
verify(explicitlyNonWrapping);
tryCompare(explicitlyNonWrapping, "wrap", false);
@@ -595,7 +577,7 @@ TestCase {
function test_explicitlyWrapping() {
// Check that explicitly setting wrap to true works even when it was implicitly true.
- var explicitlyWrapping = tenItemTumbler.createObject(cleanupItem);
+ var explicitlyWrapping = createTemporaryObject(tenItemTumbler, testCase);
verify(explicitlyWrapping);
compare(explicitlyWrapping.wrap, true);
@@ -623,7 +605,7 @@ TestCase {
snapMode: ListView.SnapToItem
highlightRangeMode: ListView.StrictlyEnforceRange
preferredHighlightBegin: height / 2 - (height / listViewTumbler.visibleItemCount / 2)
- preferredHighlightEnd: height / 2 + (height / listViewTumbler.visibleItemCount / 2)
+ preferredHighlightEnd: height / 2 + (height / listViewTumbler.visibleItemCount / 2)
clip: true
}
}
@@ -667,7 +649,7 @@ TestCase {
}
function test_customContentItemAtConstruction(data) {
- var tumbler = data.component.createObject(cleanupItem);
+ var tumbler = createTemporaryObject(data.component, testCase);
// Shouldn't assert.
tumbler.model = 5;
@@ -707,7 +689,7 @@ TestCase {
var contentItemComponent = Qt.createComponent(data.componentPath);
compare(contentItemComponent.status, Component.Ready);
- var customContentItem = contentItemComponent.createObject(tumbler);
+ var customContentItem = createTemporaryObject(contentItemComponent, tumbler);
tumbler.contentItem = customContentItem;
compare(tumbler.count, 5);
tumblerView = findView(tumbler);
@@ -921,7 +903,7 @@ TestCase {
}
function test_attachedProperties() {
- tumbler = tumblerComponent.createObject(cleanupItem);
+ tumbler = createTemporaryObject(tumblerComponent, testCase);
verify(tumbler);
// TODO: crashes somewhere in QML's guts
@@ -932,10 +914,10 @@ TestCase {
// tumbler.contentItem.offset += 1;
ignoreWarning("Tumbler: attached properties must be accessed through a delegate item that has a parent");
- noParentDelegateComponent.createObject(null);
+ createTemporaryObject(noParentDelegateComponent, null);
ignoreWarning("Tumbler: attempting to access attached property on item without an \"index\" property");
- var object = noParentDelegateComponent.createObject(cleanupItem);
+ var object = createTemporaryObject(noParentDelegateComponent, testCase);
verify(object);
}
@@ -1039,4 +1021,30 @@ TestCase {
++tumbler.currentIndex;
tryCompare(tumblerView, "offset", 4, tumblerView.highlightMoveDuration * 2);
}
+
+ function test_moving_data() {
+ return [
+ { tag: "wrap:true", wrap: true },
+ { tag: "wrap:false", wrap: false }
+ ]
+ }
+
+ function test_moving(data) {
+ createTumbler({wrap: data.wrap, model: 5})
+ compare(tumbler.wrap, data.wrap)
+ compare(tumbler.moving, false)
+
+ waitForRendering(tumbler)
+
+ mousePress(tumbler, tumbler.width / 2, tumbler.height / 2, Qt.LeftButton)
+ compare(tumbler.moving, false)
+
+ for (var y = tumbler.height / 2; y >= tumbler.height / 4; y -= 10)
+ mouseMove(tumbler, tumbler.width / 2, y, 1)
+ compare(tumbler.moving, true)
+
+ mouseRelease(tumbler, tumbler.width / 2, tumbler.height / 4, Qt.LeftButton)
+ compare(tumbler.moving, true)
+ tryCompare(tumbler, "moving", false)
+ }
}
diff --git a/tests/auto/controls/default/tst_default.cpp b/tests/auto/controls/default/tst_default.cpp
index 80ae5160..d21f13ad 100644
--- a/tests/auto/controls/default/tst_default.cpp
+++ b/tests/auto/controls/default/tst_default.cpp
@@ -40,5 +40,6 @@ int main(int argc, char *argv[])
{
QTEST_ADD_GPU_BLACKLIST_SUPPORT
QTEST_SET_MAIN_SOURCE_PATH
+ qputenv("QML_NO_TOUCH_COMPRESSION", "1");
return quick_test_main(argc, argv, "tst_controls::Default", TST_CONTROLS_DATA);
}
diff --git a/tests/auto/controls/material/tst_material.cpp b/tests/auto/controls/material/tst_material.cpp
index 5964abf8..7d1953c2 100644
--- a/tests/auto/controls/material/tst_material.cpp
+++ b/tests/auto/controls/material/tst_material.cpp
@@ -41,6 +41,7 @@ int main(int argc, char *argv[])
{
QTEST_ADD_GPU_BLACKLIST_SUPPORT
QTEST_SET_MAIN_SOURCE_PATH
+ qputenv("QML_NO_TOUCH_COMPRESSION", "1");
QQuickStyle::setStyle("Material");
return quick_test_main(argc, argv, "tst_controls::Material", TST_CONTROLS_DATA);
}
diff --git a/tests/auto/controls/universal/tst_universal.cpp b/tests/auto/controls/universal/tst_universal.cpp
index 8372aeba..d293dc4c 100644
--- a/tests/auto/controls/universal/tst_universal.cpp
+++ b/tests/auto/controls/universal/tst_universal.cpp
@@ -41,6 +41,7 @@ int main(int argc, char *argv[])
{
QTEST_ADD_GPU_BLACKLIST_SUPPORT
QTEST_SET_MAIN_SOURCE_PATH
+ qputenv("QML_NO_TOUCH_COMPRESSION", "1");
QQuickStyle::setStyle("Universal");
return quick_test_main(argc, argv, "tst_controls::Universal", TST_CONTROLS_DATA);
}
diff --git a/tests/auto/drawer/tst_drawer.cpp b/tests/auto/drawer/tst_drawer.cpp
index cfc403a2..251f5567 100644
--- a/tests/auto/drawer/tst_drawer.cpp
+++ b/tests/auto/drawer/tst_drawer.cpp
@@ -84,6 +84,9 @@ private slots:
void touch();
void grabber();
+
+ void interactive_data();
+ void interactive();
};
void tst_Drawer::visible_data()
@@ -799,6 +802,60 @@ void tst_Drawer::grabber()
QTRY_COMPARE(popupClosedSpy.count(), 1);
}
+void tst_Drawer::interactive_data()
+{
+ QTest::addColumn<QString>("source");
+ QTest::newRow("Window") << "window.qml";
+ QTest::newRow("ApplicationWindow") << "applicationwindow.qml";
+}
+
+void tst_Drawer::interactive()
+{
+ QFETCH(QString, source);
+ QQuickApplicationHelper helper(this, source);
+
+ QQuickWindow *window = helper.window;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowActive(window));
+
+ QQuickDrawer *drawer = window->property("drawer").value<QQuickDrawer*>();
+ QVERIFY(drawer);
+
+ drawer->setInteractive(false);
+
+ QSignalSpy openedSpy(drawer, SIGNAL(opened()));
+ QSignalSpy aboutToHideSpy(drawer, SIGNAL(aboutToHide()));
+ QVERIFY(openedSpy.isValid());
+ QVERIFY(aboutToHideSpy.isValid());
+
+ drawer->open();
+ QVERIFY(openedSpy.wait());
+
+ // click outside
+ QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, QPoint(300, 100));
+ QCOMPARE(aboutToHideSpy.count(), 0);
+
+ // drag inside
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(drawer->width(), 0));
+ QTest::mouseMove(window, QPoint(0, 0));
+ QCOMPARE(drawer->position(), 1.0);
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, QPoint(0, 0));
+ QCOMPARE(drawer->position(), 1.0);
+ QCOMPARE(aboutToHideSpy.count(), 0);
+
+ // drag outside
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(window->width() - 1, 0));
+ QTest::mouseMove(window, QPoint(0, 0));
+ QCOMPARE(drawer->position(), 1.0);
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, QPoint(0, 0));
+ QCOMPARE(drawer->position(), 1.0);
+ QCOMPARE(aboutToHideSpy.count(), 0);
+
+ // close on escape
+ QTest::keyClick(window, Qt::Key_Escape);
+ QCOMPARE(aboutToHideSpy.count(), 0);
+}
+
QTEST_MAIN(tst_Drawer)
#include "tst_drawer.moc"
diff --git a/tests/auto/qquickstyle/tst_qquickstyle.cpp b/tests/auto/qquickstyle/tst_qquickstyle.cpp
index cafe5df3..3487a21e 100644
--- a/tests/auto/qquickstyle/tst_qquickstyle.cpp
+++ b/tests/auto/qquickstyle/tst_qquickstyle.cpp
@@ -50,6 +50,7 @@ private slots:
void lookup();
void commandLineArgument();
void environmentVariables();
+ void availableStyles();
};
void tst_QQuickStyle::init()
@@ -94,6 +95,13 @@ void tst_QQuickStyle::environmentVariables()
QCOMPARE(QQuickStylePrivate::fallbackStyle(), QString("EnvVarFallbackStyle"));
}
+void tst_QQuickStyle::availableStyles()
+{
+ QStringList styles = QQuickStyle::availableStyles();
+ QVERIFY(!styles.isEmpty());
+ QCOMPARE(styles.first(), QString("Default"));
+}
+
QTEST_MAIN(tst_QQuickStyle)
#include "tst_qquickstyle.moc"
diff --git a/tests/auto/revisions/tst_revisions.cpp b/tests/auto/revisions/tst_revisions.cpp
index 0547941f..8a7a5d6e 100644
--- a/tests/auto/revisions/tst_revisions.cpp
+++ b/tests/auto/revisions/tst_revisions.cpp
@@ -52,12 +52,9 @@ void tst_revisions::revisions_data()
{
QTest::addColumn<int>("revision");
- // In theory, this could be done in a loop from 5.7 to QT_VERSION, but
- // the test would immediately fail when the Qt version was bumped up.
- // Therefore it is better to just add these lines by hand when adding
- // new revisions.
- QTest::newRow("2.0") << 0; // Qt 5.7
- QTest::newRow("2.1") << 1; // Qt 5.8
+ // Qt 5.7: 2.0, Qt 5.8: 2.1, Qt 5.9: 2.2...
+ for (int i = 0; i <= QT_VERSION_MINOR - 7; ++i)
+ QTest::newRow(qPrintable(QString("2.%1").arg(i))) << i;
}
void tst_revisions::revisions()
@@ -67,6 +64,7 @@ void tst_revisions::revisions()
QQmlEngine engine;
QQmlComponent component(&engine);
component.setData(QString("import QtQuick 2.0; \
+ import QtQuick.Templates 2.%1 as T; \
import QtQuick.Controls 2.%1; \
import QtQuick.Controls.impl 2.%1; \
import QtQuick.Controls.Material 2.%1; \
diff --git a/tests/auto/sanity/BLACKLIST b/tests/auto/sanity/BLACKLIST
index 768f3985..965790e7 100644
--- a/tests/auto/sanity/BLACKLIST
+++ b/tests/auto/sanity/BLACKLIST
@@ -1,10 +1,4 @@
-[signalHandlers:material/SpinBox.qml]
-*
-[signalHandlers:material/TextArea.qml]
-*
-[signalHandlers:material/TextField.qml]
-*
-[attachedObjects:controls/ComboBox.qml]
+[signalHandlers:material/CursorDelegate.qml]
*
[attachedObjects:material/ComboBox.qml]
*
diff --git a/tests/auto/sanity/tst_sanity.cpp b/tests/auto/sanity/tst_sanity.cpp
index 5168219b..8d3fee7b 100644
--- a/tests/auto/sanity/tst_sanity.cpp
+++ b/tests/auto/sanity/tst_sanity.cpp
@@ -314,7 +314,7 @@ void tst_Sanity::attachedObjects_data()
QTest::addColumn<QUrl>("url");
addTestRows(&engine, "calendar", "Qt/labs/calendar");
addTestRows(&engine, "controls", "QtQuick/Controls.2", QStringList() << "CheckIndicator" << "RadioIndicator" << "SwitchIndicator");
- addTestRows(&engine, "controls/material", "QtQuick/Controls.2/Material", QStringList() << "Ripple" << "SliderHandle" << "CheckIndicator" << "RadioIndicator" << "SwitchIndicator" << "BoxShadow" << "ElevationEffect");
+ addTestRows(&engine, "controls/material", "QtQuick/Controls.2/Material", QStringList() << "Ripple" << "SliderHandle" << "CheckIndicator" << "RadioIndicator" << "SwitchIndicator" << "BoxShadow" << "ElevationEffect" << "CursorDelegate");
addTestRows(&engine, "controls/universal", "QtQuick/Controls.2/Universal", QStringList() << "CheckIndicator" << "RadioIndicator" << "SwitchIndicator");
}
diff --git a/tests/auto/shared/util.h b/tests/auto/shared/util.h
index 43b6e690..4295d798 100644
--- a/tests/auto/shared/util.h
+++ b/tests/auto/shared/util.h
@@ -65,7 +65,7 @@ public:
inline QString dataDirectory() const { return m_dataDirectory; }
inline QUrl dataDirectoryUrl() const { return m_dataDirectoryUrl; }
- inline QString directory() const { return m_directory; }
+ inline QString directory() const { return m_directory; }
static inline QQmlDataTest *instance() { return m_instance; }
diff --git a/tests/benchmarks/creationtime/tst_creationtime.cpp b/tests/benchmarks/creationtime/tst_creationtime.cpp
index 8f88d906..4909f080 100644
--- a/tests/benchmarks/creationtime/tst_creationtime.cpp
+++ b/tests/benchmarks/creationtime/tst_creationtime.cpp
@@ -134,7 +134,7 @@ void tst_CreationTime::material()
void tst_CreationTime::material_data()
{
QTest::addColumn<QUrl>("url");
- addTestRows(&engine, "controls/material", "QtQuick/Controls.2/Material", QStringList() << "Ripple" << "SliderHandle" << "CheckIndicator" << "RadioIndicator" << "SwitchIndicator" << "BoxShadow" << "ElevationEffect");
+ addTestRows(&engine, "controls/material", "QtQuick/Controls.2/Material", QStringList() << "Ripple" << "SliderHandle" << "CheckIndicator" << "RadioIndicator" << "SwitchIndicator" << "BoxShadow" << "ElevationEffect" << "CursorDelegate");
}
void tst_CreationTime::universal()
diff --git a/tests/benchmarks/objectcount/tst_objectcount.cpp b/tests/benchmarks/objectcount/tst_objectcount.cpp
index 42368862..7f0610ac 100644
--- a/tests/benchmarks/objectcount/tst_objectcount.cpp
+++ b/tests/benchmarks/objectcount/tst_objectcount.cpp
@@ -190,7 +190,7 @@ void tst_ObjectCount::material()
void tst_ObjectCount::material_data()
{
QTest::addColumn<QUrl>("url");
- addTestRows(&engine, "controls/material", "QtQuick/Controls.2/Material", QStringList() << "Ripple" << "SliderHandle" << "CheckIndicator" << "RadioIndicator" << "SwitchIndicator" << "BoxShadow" << "ElevationEffect");
+ addTestRows(&engine, "controls/material", "QtQuick/Controls.2/Material", QStringList() << "Ripple" << "SliderHandle" << "CheckIndicator" << "RadioIndicator" << "SwitchIndicator" << "BoxShadow" << "ElevationEffect" << "CursorDelegate");
}
void tst_ObjectCount::universal()
diff --git a/tests/manual/gifs/data/qtquickcontrols2-delaybutton.qml b/tests/manual/gifs/data/qtquickcontrols2-delaybutton.qml
new file mode 100644
index 00000000..2fd25fc3
--- /dev/null
+++ b/tests/manual/gifs/data/qtquickcontrols2-delaybutton.qml
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite 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 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.6
+import QtQuick.Window 2.0
+import QtQuick.Controls 2.2
+
+Window {
+ width: button.width
+ height: button.height
+ visible: true
+
+ DelayButton {
+ id: button
+ progress: 0.69
+ text: "DelayButton"
+ anchors.centerIn: parent
+ }
+}
diff --git a/tests/manual/gifs/data/qtquickcontrols2-scrollbar-snap.qml b/tests/manual/gifs/data/qtquickcontrols2-scrollbar-snap.qml
new file mode 100644
index 00000000..cfb26696
--- /dev/null
+++ b/tests/manual/gifs/data/qtquickcontrols2-scrollbar-snap.qml
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite 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 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.7
+import QtQuick.Window 2.0
+import QtQuick.Controls 2.0
+
+Window {
+ width: 100
+ maximumHeight: 20
+ visible: true
+
+ property alias scrollbar: scrollbar
+
+ ScrollBar {
+ id: scrollbar
+ size: 0.2
+ stepSize: 0.25
+ active: true
+ width: parent.width
+ anchors.centerIn: parent
+ orientation: Qt.Horizontal
+ }
+}
diff --git a/tests/manual/gifs/tst_gifs.cpp b/tests/manual/gifs/tst_gifs.cpp
index 322dfe36..a665a678 100644
--- a/tests/manual/gifs/tst_gifs.cpp
+++ b/tests/manual/gifs/tst_gifs.cpp
@@ -69,6 +69,8 @@ private slots:
void dial_data();
void dial();
void scrollBar();
+ void scrollBarSnap_data();
+ void scrollBarSnap();
void scrollIndicator();
void progressBar_data();
void progressBar();
@@ -80,6 +82,7 @@ private slots:
void stackView_data();
void stackView();
void drawer();
+ void delayButton();
private:
void moveSmoothly(QQuickWindow *window, const QPoint &from, const QPoint &to, int movements,
@@ -861,6 +864,56 @@ void tst_Gifs::scrollBar()
gifRecorder.waitForFinish();
}
+void tst_Gifs::scrollBarSnap_data()
+{
+ QTest::addColumn<QString>("gifBaseName");
+ QTest::addColumn<int>("snapMode");
+ QTest::newRow("NoSnap") << "qtquickcontrols2-scrollbar-nosnap" << 0;
+ QTest::newRow("SnapAlways") << "qtquickcontrols2-scrollbar-snapalways" << 1;
+ QTest::newRow("SnapOnRelease") << "qtquickcontrols2-scrollbar-snaponrelease" << 2;
+}
+
+void tst_Gifs::scrollBarSnap()
+{
+ QFETCH(QString, gifBaseName);
+ QFETCH(int, snapMode);
+
+ GifRecorder gifRecorder;
+ gifRecorder.setDataDirPath(dataDirPath);
+ gifRecorder.setOutputDir(outputDir);
+ gifRecorder.setRecordingDuration(8);
+ gifRecorder.setHighQuality(true);
+ gifRecorder.setQmlFileName("qtquickcontrols2-scrollbar-snap.qml");
+ gifRecorder.setOutputFileBaseName(gifBaseName);
+
+ gifRecorder.start();
+
+ QQuickWindow *window = gifRecorder.window();
+ QQuickItem *scrollbar = window->property("scrollbar").value<QQuickItem*>();
+ QVERIFY(scrollbar);
+ QVERIFY(scrollbar->setProperty("snapMode", QVariant(snapMode)));
+ QCOMPARE(scrollbar->property("snapMode").toInt(), snapMode);
+
+ const QPoint startPos(scrollbar->property("leftPadding").toReal(), scrollbar->y() + scrollbar->height() / 2);
+ const int availableWidth = scrollbar->property("availableWidth").toReal();
+
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, startPos, 200);
+ const QPoint pos1 = startPos + QPoint(availableWidth * 0.3, 0);
+ moveSmoothly(window, startPos, pos1, pos1.x() - startPos.x(), QEasingCurve::OutQuint, 30);
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, pos1, 0);
+
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, pos1, 400);
+ const QPoint pos2 = startPos + QPoint(availableWidth * 0.6, 0);
+ moveSmoothly(window, pos1, pos2, pos2.x() - pos1.x(), QEasingCurve::OutQuint, 30);
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, pos2, 0);
+
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, pos2, 400);
+ moveSmoothly(window, pos2, startPos, pos2.x() - startPos.x(), QEasingCurve::OutQuint, 30);
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, startPos, 0);
+
+ gifRecorder.waitForFinish();
+}
+
void tst_Gifs::scrollIndicator()
{
GifRecorder gifRecorder;
@@ -966,6 +1019,32 @@ void tst_Gifs::drawer()
gifRecorder.waitForFinish();
}
+void tst_Gifs::delayButton()
+{
+ GifRecorder gifRecorder;
+ gifRecorder.setDataDirPath(dataDirPath);
+ gifRecorder.setOutputDir(outputDir);
+ gifRecorder.setRecordingDuration(9);
+ gifRecorder.setQmlFileName("qtquickcontrols2-delaybutton.qml");
+
+ gifRecorder.start();
+
+ QQuickWindow *window = gifRecorder.window();
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(window->width() / 2, window->height() / 2), 0);
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, QPoint(window->width() / 2, window->height() / 2), 1500);
+
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(window->width() / 2, window->height() / 2), 1000);
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, QPoint(window->width() / 2, window->height() / 2), 200);
+
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(window->width() / 2, window->height() / 2), 1500);
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, QPoint(window->width() / 2, window->height() / 2), 1730);
+
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(window->width() / 2, window->height() / 2), 1000);
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, QPoint(window->width() / 2, window->height() / 2), 2070); // 0.69 * 3000
+
+ gifRecorder.waitForFinish();
+}
+
QTEST_MAIN(tst_Gifs)
#include "tst_gifs.moc"