Improve gallery example

* Fix qmllint warnings
  * Added support for landscape mode
  * Updated docs

Fixes: QTBUG-110989
Change-Id: Id7422ad19b4336c64c866309dd07116d982ecff2
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
(cherry picked from commit 730c1d1630)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Santhosh Kumar 2023-02-22 09:53:32 +01:00 committed by Qt Cherry-pick Bot
parent b2f12ac245
commit 81e1b52042
10 changed files with 232 additions and 158 deletions

View File

@ -35,5 +35,16 @@
graphical appearance of a control, allows you to interact with the control, graphical appearance of a control, allows you to interact with the control,
and explains in which circumstances it is handy to use this control. and explains in which circumstances it is handy to use this control.
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, blocking 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 gallery/gallery.qml orientation
\include examples-run.qdocinc \include examples-run.qdocinc
*/ */

View File

@ -1,6 +1,8 @@
// Copyright (C) 2022 The Qt Company Ltd. // Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
pragma ComponentBehavior: Bound
import QtCore import QtCore
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
@ -15,6 +17,10 @@ ApplicationWindow {
visible: true visible: true
title: "Qt Quick Controls" title: "Qt Quick Controls"
//! [orientation]
readonly property bool portraitMode: window.width < window.height
//! [orientation]
function help() { function help() {
let displayingControl = listView.currentIndex !== -1 let displayingControl = listView.currentIndex !== -1
let currentControlName = displayingControl let currentControlName = displayingControl
@ -41,7 +47,7 @@ ApplicationWindow {
Shortcut { Shortcut {
sequence: StandardKey.HelpContents sequence: StandardKey.HelpContents
onActivated: help() onActivated: window.help()
} }
Action { Action {
@ -72,14 +78,16 @@ ApplicationWindow {
RowLayout { RowLayout {
spacing: 20 spacing: 20
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: !window.portraitMode ? drawer.width : undefined
ToolButton { ToolButton {
action: navigateBackAction action: navigateBackAction
visible: window.portraitMode
} }
Label { Label {
id: titleLabel id: titleLabel
text: listView.currentItem ? listView.currentItem.text : "Gallery" text: listView.currentItem ? (listView.currentItem as ItemDelegate).text : "Gallery"
font.pixelSize: 20 font.pixelSize: 20
elide: Label.ElideRight elide: Label.ElideRight
horizontalAlignment: Qt.AlignHCenter horizontalAlignment: Qt.AlignHCenter
@ -101,7 +109,7 @@ ApplicationWindow {
} }
Action { Action {
text: "Help" text: "Help"
onTriggered: help() onTriggered: window.help()
} }
Action { Action {
text: "About" text: "About"
@ -114,9 +122,13 @@ ApplicationWindow {
Drawer { Drawer {
id: drawer id: drawer
width: Math.min(window.width, window.height) / 3 * 2 width: Math.min(window.width, window.height) / 3 * 2
height: window.height height: window.height
interactive: stackView.depth === 1 modal: window.portraitMode
interactive: window.portraitMode ? (stackView.depth === 1) : false
position: window.portraitMode ? 0 : 1
visible: !window.portraitMode
ListView { ListView {
id: listView id: listView
@ -125,17 +137,6 @@ ApplicationWindow {
currentIndex: -1 currentIndex: -1
anchors.fill: parent anchors.fill: parent
delegate: ItemDelegate {
width: listView.width
text: model.title
highlighted: ListView.isCurrentItem
onClicked: {
listView.currentIndex = index
stackView.push(model.source)
drawer.close()
}
}
model: ListModel { model: ListModel {
ListElement { title: "BusyIndicator"; source: "qrc:/pages/BusyIndicatorPage.qml" } ListElement { title: "BusyIndicator"; source: "qrc:/pages/BusyIndicatorPage.qml" }
ListElement { title: "Button"; source: "qrc:/pages/ButtonPage.qml" } ListElement { title: "Button"; source: "qrc:/pages/ButtonPage.qml" }
@ -165,13 +166,34 @@ ApplicationWindow {
ListElement { title: "Tumbler"; source: "qrc:/pages/TumblerPage.qml" } ListElement { title: "Tumbler"; source: "qrc:/pages/TumblerPage.qml" }
} }
delegate: ItemDelegate {
id: delegateItem
width: ListView.view.width
text: title
highlighted: ListView.isCurrentItem
required property int index
required property var model
required property string title
required property string source
onClicked: {
listView.currentIndex = index
stackView.push(source)
if (window.portraitMode)
drawer.close()
}
}
ScrollIndicator.vertical: ScrollIndicator { } ScrollIndicator.vertical: ScrollIndicator { }
} }
} }
StackView { StackView {
id: stackView id: stackView
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: !window.portraitMode ? drawer.width : undefined
initialItem: Pane { initialItem: Pane {
id: pane id: pane
@ -203,6 +225,7 @@ ApplicationWindow {
source: "images/arrow.png" source: "images/arrow.png"
anchors.left: parent.left anchors.left: parent.left
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
visible: window.portraitMode
} }
} }
} }

View File

@ -1,6 +1,8 @@
// Copyright (C) 2017 The Qt Company Ltd. // Copyright (C) 2017 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
pragma ComponentBehavior: Bound
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls

View File

@ -33,16 +33,17 @@ ScrollablePage {
} }
ComboBox { ComboBox {
id: comboBox
editable: true editable: true
model: ListModel { model: ListModel {
id: model
ListElement { text: "Banana" } ListElement { text: "Banana" }
ListElement { text: "Apple" } ListElement { text: "Apple" }
ListElement { text: "Coconut" } ListElement { text: "Coconut" }
} }
onAccepted: { onAccepted: {
if (find(editText) === -1) if (find(editText) === -1)
model.append({text: editText}) comboBox.model.append({text: comboBox.editText})
} }
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
} }

View File

@ -6,89 +6,7 @@ import QtQuick.Layouts
import QtQuick.Controls import QtQuick.Controls
Pane { Pane {
padding: 0
property var delegateComponentMap: {
"ItemDelegate": itemDelegateComponent,
"SwipeDelegate": swipeDelegateComponent,
"CheckDelegate": checkDelegateComponent,
"RadioDelegate": radioDelegateComponent,
"SwitchDelegate": switchDelegateComponent
}
Component {
id: itemDelegateComponent
ItemDelegate {
text: labelText
width: parent.width
}
}
Component {
id: swipeDelegateComponent
SwipeDelegate {
id: swipeDelegate
text: labelText
width: parent.width
Component {
id: removeComponent
Rectangle {
color: SwipeDelegate.pressed ? "#333" : "#444"
width: parent.width
height: parent.height
clip: true
SwipeDelegate.onClicked: view.model.remove(ourIndex)
Label {
font.pixelSize: swipeDelegate.font.pixelSize
text: "Remove"
color: "white"
anchors.centerIn: parent
}
}
}
swipe.left: removeComponent
swipe.right: removeComponent
}
}
Component {
id: checkDelegateComponent
CheckDelegate {
text: labelText
}
}
ButtonGroup {
id: radioButtonGroup
}
Component {
id: radioDelegateComponent
RadioDelegate {
text: labelText
ButtonGroup.group: radioButtonGroup
}
}
Component {
id: switchDelegateComponent
SwitchDelegate {
text: labelText
}
}
ColumnLayout { ColumnLayout {
id: column
spacing: 40 spacing: 40
anchors.fill: parent anchors.fill: parent
anchors.topMargin: 20 anchors.topMargin: 20
@ -102,71 +20,181 @@ Pane {
ListView { ListView {
id: listView id: listView
Layout.fillWidth: true
Layout.fillHeight: true
clip: true clip: true
model: ListModel {
ListElement { type: "ItemDelegate"; text: "ItemDelegate" }
ListElement { type: "ItemDelegate"; text: "ItemDelegate" }
ListElement { type: "ItemDelegate"; text: "ItemDelegate" }
ListElement { type: "SwipeDelegate"; text: "SwipeDelegate" }
ListElement { type: "SwipeDelegate"; text: "SwipeDelegate" }
ListElement { type: "SwipeDelegate"; text: "SwipeDelegate" }
ListElement { type: "CheckDelegate"; text: "CheckDelegate" }
ListElement { type: "CheckDelegate"; text: "CheckDelegate" }
ListElement { type: "CheckDelegate"; text: "CheckDelegate" }
ListElement { type: "RadioDelegate"; text: "RadioDelegate" }
ListElement { type: "RadioDelegate"; text: "RadioDelegate" }
ListElement { type: "RadioDelegate"; text: "RadioDelegate" }
ListElement { type: "SwitchDelegate"; text: "SwitchDelegate" }
ListElement { type: "SwitchDelegate"; text: "SwitchDelegate" }
ListElement { type: "SwitchDelegate"; text: "SwitchDelegate" }
}
section.property: "type" section.property: "type"
section.delegate: Pane { section.delegate: Pane {
width: listView.width id: sectionPane
required property string section
width: ListView.view.width
height: sectionLabel.implicitHeight + 20 height: sectionLabel.implicitHeight + 20
Label { Label {
id: sectionLabel id: sectionLabel
text: section text: sectionPane.section
anchors.centerIn: parent anchors.centerIn: parent
} }
} }
Layout.fillWidth: true
Layout.fillHeight: true
readonly property var delegateComponentMap: {
"ItemDelegate": itemDelegateComponent,
"SwipeDelegate": swipeDelegateComponent,
"CheckDelegate": checkDelegateComponent,
"RadioDelegate": radioDelegateComponent,
"SwitchDelegate": switchDelegateComponent
}
Component {
id: itemDelegateComponent
ItemDelegate {
// qmllint disable unqualified
text: value
// qmllint enable unqualified
width: parent.width
}
}
Component {
id: swipeDelegateComponent
SwipeDelegate {
id: swipeDelegate
// qmllint disable unqualified
text: value
// qmllint enable unqualified
width: parent.width
Component {
id: removeComponent
Rectangle {
color: SwipeDelegate.pressed ? "#333" : "#444"
width: parent.width
height: parent.height
clip: true
SwipeDelegate.onClicked: {
// qmllint disable unqualified
view.model.remove(ourIndex)
// qmllint enable unqualified
}
Label {
// qmllint disable unqualified
font.pixelSize: swipeDelegate.font.pixelSize
// qmllint enable unqualified
text: "Remove"
color: "white"
anchors.centerIn: parent
}
}
}
SequentialAnimation {
id: removeAnimation
PropertyAction {
// qmllint disable unqualified
target: delegateItem
// qmllint enable unqualified
property: "ListView.delayRemove"
value: true
}
NumberAnimation {
// qmllint disable unqualified
target: delegateItem.item
// qmllint enable unqualified
property: "height"
to: 0
easing.type: Easing.InOutQuad
}
PropertyAction {
// qmllint disable unqualified
target: delegateItem
// qmllint enable unqualified
property: "ListView.delayRemove"
value: false
}
}
swipe.left: removeComponent
swipe.right: removeComponent
ListView.onRemove: removeAnimation.start()
}
}
Component {
id: checkDelegateComponent
CheckDelegate {
// qmllint disable unqualified
text: value
// qmllint enable unqualified
}
}
ButtonGroup {
id: radioButtonGroup
}
Component {
id: radioDelegateComponent
RadioDelegate {
// qmllint disable unqualified
text: value
ButtonGroup.group: radioButtonGroup
// qmllint enable unqualified
}
}
Component {
id: switchDelegateComponent
SwitchDelegate {
// qmllint disable unqualified
text: value
// qmllint enable unqualified
}
}
model: ListModel {
ListElement { type: "ItemDelegate"; value: "ItemDelegate1" }
ListElement { type: "ItemDelegate"; value: "ItemDelegate2" }
ListElement { type: "ItemDelegate"; value: "ItemDelegate3" }
ListElement { type: "SwipeDelegate"; value: "SwipeDelegate1" }
ListElement { type: "SwipeDelegate"; value: "SwipeDelegate2" }
ListElement { type: "SwipeDelegate"; value: "SwipeDelegate3" }
ListElement { type: "CheckDelegate"; value: "CheckDelegate1" }
ListElement { type: "CheckDelegate"; value: "CheckDelegate2" }
ListElement { type: "CheckDelegate"; value: "CheckDelegate3" }
ListElement { type: "RadioDelegate"; value: "RadioDelegate1" }
ListElement { type: "RadioDelegate"; value: "RadioDelegate2" }
ListElement { type: "RadioDelegate"; value: "RadioDelegate3" }
ListElement { type: "SwitchDelegate"; value: "SwitchDelegate1" }
ListElement { type: "SwitchDelegate"; value: "SwitchDelegate2" }
ListElement { type: "SwitchDelegate"; value: "SwitchDelegate3" }
}
delegate: Loader { delegate: Loader {
id: delegateLoader id: delegateLoader
width: listView.width width: ListView.view.width
sourceComponent: delegateComponentMap[text] // qmllint disable unqualified
sourceComponent: listView.delegateComponentMap[type]
// qmllint enable unqualified
property string labelText: text required property string value
required property string type
required property var model
required property int index
property Loader delegateItem: delegateLoader
// qmllint disable unqualified
property ListView view: listView property ListView view: listView
// qmllint enable unqualified
property int ourIndex: index property int ourIndex: index
// Can't find a way to do this in the SwipeDelegate component itself,
// so do it here instead.
SequentialAnimation {
id: removeAnimation
PropertyAction {
target: delegateLoader
property: "ListView.delayRemove"
value: true
}
NumberAnimation {
target: item
property: "height"
to: 0
easing.type: Easing.InOutQuad
}
PropertyAction {
target: delegateLoader
property: "ListView.delayRemove"
value: false
}
}
ListView.onRemove: removeAnimation.start()
} }
} }
} }

View File

@ -25,7 +25,7 @@ ScrollablePage {
Button { Button {
text: "Message" text: "Message"
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
width: buttonWidth width: page.buttonWidth
onClicked: messageDialog.open() onClicked: messageDialog.open()
Dialog { Dialog {
@ -46,7 +46,7 @@ ScrollablePage {
id: button id: button
text: "Confirmation" text: "Confirmation"
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
width: buttonWidth width: page.buttonWidth
onClicked: confirmationDialog.open() onClicked: confirmationDialog.open()
Dialog { Dialog {
@ -77,7 +77,7 @@ ScrollablePage {
Button { Button {
text: "Content" text: "Content"
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
width: buttonWidth width: page.buttonWidth
onClicked: contentDialog.open() onClicked: contentDialog.open()
Dialog { Dialog {
@ -139,7 +139,7 @@ ScrollablePage {
Button { Button {
text: "Input" text: "Input"
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
width: buttonWidth width: page.buttonWidth
onClicked: inputDialog.open() onClicked: inputDialog.open()
Dialog { Dialog {

View File

@ -1,6 +1,8 @@
// Copyright (C) 2017 The Qt Company Ltd. // Copyright (C) 2017 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
pragma ComponentBehavior: Bound
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
@ -43,6 +45,13 @@ StackView {
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
onClicked: stackView.pop() onClicked: stackView.pop()
} }
Label {
width: parent.width
wrapMode: Label.Wrap
horizontalAlignment: Qt.AlignHCenter
text: "Stack Depth: " + stackView.depth
}
} }
} }
} }

View File

@ -16,8 +16,8 @@ Pane {
model: 3 model: 3
Pane { Pane {
width: view.width width: SwipeView.view.width
height: view.height height: SwipeView.view.height
Column { Column {
spacing: 40 spacing: 40

View File

@ -16,8 +16,8 @@ Page {
model: 3 model: 3
Pane { Pane {
width: swipeView.width width: SwipeView.view.width
height: swipeView.height height: SwipeView.view.height
Column { Column {
spacing: 40 spacing: 40

View File

@ -19,7 +19,7 @@ ScrollablePage {
} }
TextArea { TextArea {
width: pane.availableWidth / 3 width: page.availableWidth / 3
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
wrapMode: TextArea.Wrap wrapMode: TextArea.Wrap