diff options
Diffstat (limited to 'tests/manual/quickcontrols2/testbench/testbench.qml')
-rw-r--r-- | tests/manual/quickcontrols2/testbench/testbench.qml | 533 |
1 files changed, 533 insertions, 0 deletions
diff --git a/tests/manual/quickcontrols2/testbench/testbench.qml b/tests/manual/quickcontrols2/testbench/testbench.qml new file mode 100644 index 0000000000..8f0951adae --- /dev/null +++ b/tests/manual/quickcontrols2/testbench/testbench.qml @@ -0,0 +1,533 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick +import QtQuick.Window +import QtQuick.Layouts +import QtQuick.Controls +import Qt.labs.folderlistmodel +import Qt.labs.settings + +import Backend +import "." as Ui + +Ui.ApplicationWindow { + id: window + visible: true + width: 1000 + height: 750 + title: "Style Testbench - " + settings.style + " Style" + (usingImagineStyle ? imagineTitleText : "") + + readonly property bool usingImagineStyle: settings.style === "Imagine" + // Some controls should be visible regardless of whether or not custom assets are lacking for it, + // so we use the default assets in some cases. + readonly property string defaultImaginePath: "qrc:/qt-project.org/imports/QtQuick/Controls/Imagine/images/" + property bool settingsLoaded: false + readonly property string imagineTitleText: " - " + (settings.useCustomImaginePath ? settings.imaginePath : "Default Assets") + + LoggingCategory { + id: brief + name: "qt.quick.controls.tools.testbench.assetfixer.brief" + } + + Shortcut { + sequence: "Ctrl+F" + onActivated: searchTextField.forceActiveFocus() + } + + Shortcut { + sequence: "Ctrl+Q" + onActivated: Qt.quit() + } + + Action { + id: fixAssetsAction + text: qsTr("Fix Custom Assets") + shortcut: "Ctrl+Shift+X" + enabled: usingImagineStyle + onTriggered: assetFixer.manualFix() + } + + Action { + id: useCustomAssetsAction + text: qsTr("Use Custom Assets") + shortcut: "Ctrl+Shift+C" + enabled: usingImagineStyle + checkable: true + checked: settings.useCustomImaginePath + onTriggered: settings.useCustomImaginePath = !settings.useCustomImaginePath + } + + Action { + id: reloadAssetsAction + text: qsTr("Reload Assets") + shortcut: "Ctrl+R" + enabled: usingImagineStyle + onTriggered: assetFixer.reloadAssets() + } + + FontMetrics { + id: fontMetrics + } + + Settings { + id: settings + + property alias windowX: window.x + property alias windowY: window.y + property alias windowWidth: window.width + property alias windowHeight: window.height + + property string style: "Imagine" + + property bool useCustomImaginePath + property string imaginePath + property bool autoFixImagineAssets + property alias imagineDirLastModified: assetFixer.assetDirectoryLastModified + + Component.onCompleted: settingsLoaded = true + } + + Settings { + id: paletteSettings + + category: "Palette" + + property bool useCustomPalette + property string window + property string windowText + property string base + property string text + property string button + property string buttonText + property string brightText + property string toolTipBase + property string toolTipText + property string light + property string midlight + property string dark + property string mid + property string shadow + property string highlight + property string highlightedText + property string link + } + + header: Ui.ToolBar { + RowLayout { + anchors.fill: parent + + ToolButton { + text: "\uf0c9" + font.family: "fontawesome" + font.pixelSize: Qt.application.font.pixelSize * 1.6 + onClicked: drawer.open() + } + + ToolSeparator {} + + TextField { + id: searchTextField + placeholderText: "Search" + } + + Item { + Layout.fillWidth: true + } + + ToolButton { + id: optionsMenuButton + text: "\ue800" + font.family: "FontAwesome" + font.pixelSize: Qt.application.font.pixelSize * 1.6 + checked: optionsMenu.visible + checkable: true + + onClicked: optionsMenu.open() + + Ui.Menu { + id: optionsMenu + x: 1 + y: 1 + parent.height + visible: optionsMenuButton.checked + closePolicy: Popup.CloseOnPressOutsideParent + + MenuItem { + text: qsTr("Open Asset Directory") + onClicked: Qt.openUrlExternally(assetFixer.assetDirectoryUrl) + enabled: usingImagineStyle + } + + MenuItem { + action: reloadAssetsAction + } + + MenuItem { + action: useCustomAssetsAction + } + + MenuItem { + action: fixAssetsAction + } + + MenuSeparator {} + + MenuItem { + id: settingsMenuItem + text: qsTr("Settings") + onTriggered: settingsDialog.open() + } + + MenuSeparator {} + + MenuItem { + text: qsTr("Quit") + onTriggered: Qt.quit() + } + } + } + } + } + + SettingsDialog { + id: settingsDialog + } + + Drawer { + id: drawer + width: parent.width * 0.33 + height: window.height + focus: false + modal: false + + Label { + text: "Drawer contents go here" + anchors.centerIn: parent + } + } + + AssetFixer { + id: assetFixer + assetDirectory: settings.imaginePath + // Don't start watching until the settings have loaded, as AssetFixer can be completed before it. + // AssetFixer needs the settings in order to check the last modified time of the asset directory. + // Also, wait until the UI has been rendered for the first time so that we can show our busy indicators, etc. + shouldWatch: usingImagineStyle && settings.useCustomImaginePath && settingsLoaded && initialUiRenderDelayTimer.hasRun + shouldFix: (shouldWatch && settings.autoFixImagineAssets) || manuallyFixing + + onFixSuggested: autoFix() + onDelayedFixSuggested: assetFixerFileSystemDelayTimer.restart() + onReloadSuggested: reloadAssets() + + property bool manuallyFixing: false + + function reloadAssets() { + console.log(brief, "Reloading assets...") + // Clear the model, otherwise ListView will keep the old items around + // with the old assets, even after clearing the pixmap cache + listView.resettingModel = true + listView.model = null + window.Imagine.path = "" + assetReloadNextFrameTimer.start() + } + + function autoFix() { + // This is a bit of a hack, but I can't think of a nice way to solve it. + // The problem is that shouldWatch becomes true, causing startWatching() to be called. + // If a fix is suggested as a result of that, this function is called. + // However, the shouldFix binding hasn't been updated yet, so even though shouldWatch + // and settings.autoFixImagineAssets are both true (the properties that make up its binding), + // the if check below fails. So, we check for that case with effectiveShouldFix. + var effectiveShouldFix = shouldWatch && settings.autoFixImagineAssets; + if (shouldWatch && effectiveShouldFix && assetDirectory.length > 0) { + fixEmUp(); + } + } + + function manualFix() { + fixEmUp(true); + } + + function fixEmUp(manually) { + assetFixer.manuallyFixing = !!manually + + // Disable image caching if it hasn't already been done. + assetFixer.clearImageCache() + + busyIndicatorRow.visible = true + assetFixerAnimationDelayTimer.start() + } + } + + // The controls' assets don't always "reload" if the path is cleared and then set in the same frame, + // so we delay the setting to the next frame. + Timer { + id: assetReloadNextFrameTimer + interval: 0 + onTriggered: { + window.Imagine.path = Qt.binding(function() { + return settings.useCustomImaginePath && settings.imaginePath.length > 0 ? settings.imaginePath : undefined + }) + + infoToolTip.text = "Reloaded assets" + infoToolTip.timeout = 1500 + infoToolTip.open() + + listView.model = controlFolderListModel + listView.resettingModel = false + + console.log(brief, "... reloaded assets.") + } + } + + // When exporting or deleting a large amount of assets (not uncommon), + // the filesystem watcher seems to emit directoryChanged() every second or so, + // so rather than process hundreds of assets every time we get notified, delay + // it until we haven't been notified for a while. + Timer { + id: assetFixerFileSystemDelayTimer + interval: 2000 + onRunningChanged: { + if (running) { + infoToolTip.text = "Assets changed on disk - reloading in 2 seconds if no further changes are detected" + infoToolTip.timeout = 2000 + infoToolTip.open() + } + } + onTriggered: assetFixer.autoFix() + } + + // Gives the BusyIndicator animation a chance to start. + Timer { + id: assetFixerAnimationDelayTimer + interval: 100 + onTriggered: { + assetFixer.fixAssets() + busyIndicatorRow.visible = false + assetFixer.manuallyFixing = false + } + } + + // Gives the UI a chance to render before the initial fixup. + Timer { + id: initialUiRenderDelayTimer + interval: 300 + running: true + onTriggered: hasRun = true + + property bool hasRun: false + } + + function getControlElements(control) { + var props = []; + for (var p in control) { + if (p !== "component" && typeof control[p] === 'object') + props.push(p); + } + return props; + } + + Ui.ContentPane { + id: contentPane + anchors.fill: parent + + palette.window: effectiveColor(paletteSettings.window) + palette.windowText: effectiveColor(paletteSettings.windowText) + palette.base: effectiveColor(paletteSettings.base) + palette.text: effectiveColor(paletteSettings.text) + palette.button: effectiveColor(paletteSettings.button) + palette.buttonText: effectiveColor(paletteSettings.buttonText) + palette.brightText: effectiveColor(paletteSettings.brightText) + palette.toolTipBase: effectiveColor(paletteSettings.toolTipBase) + palette.toolTipText: effectiveColor(paletteSettings.toolTipText) + palette.light: effectiveColor(paletteSettings.light) + palette.midlight: effectiveColor(paletteSettings.midlight) + palette.dark: effectiveColor(paletteSettings.dark) + palette.mid: effectiveColor(paletteSettings.mid) + palette.shadow: effectiveColor(paletteSettings.shadow) + palette.highlight: effectiveColor(paletteSettings.highlight) + palette.highlightedText: effectiveColor(paletteSettings.highlightedText) + palette.link: effectiveColor(paletteSettings.link) + + function effectiveColor(paletteColorString) { + return paletteSettings.useCustomPalette && paletteColorString.length > 0 ? paletteColorString : undefined + } + + FolderListModel { + id: controlFolderListModel + folder: "qrc:/controls" + showDirs: false + nameFilters: searchTextField.text.length > 0 ? ["*" + searchTextField.text + "*.qml"] : [] + caseSensitive: false + } + + ListView { + id: listView + anchors.fill: parent + spacing: 30 + visible: !busyIndicatorRow.visible && !resettingModel + + property bool resettingModel: false + + ScrollBar.vertical: ScrollBar { + parent: contentPane + anchors.top: parent.top + anchors.right: parent.right + anchors.bottom: parent.bottom + } + + model: controlFolderListModel + delegate: ColumnLayout { + id: rootDelegate + width: listView.width + + MenuSeparator { + Layout.fillWidth: true + visible: index !== 0 + } + + Label { + text: customControlName.length === 0 ? model.fileBaseName : customControlName + font.pixelSize: Qt.application.font.pixelSize * 2 + } + + readonly property var controlName: model.fileBaseName + readonly property var controlMetaObject: controlMetaObjectLoader.item + readonly property string customControlName: controlMetaObject && controlMetaObject.hasOwnProperty("customControlName") + ? controlMetaObject.customControlName : "" + readonly property var supportedStates: rootDelegate.controlMetaObject.supportedStates + readonly property int maxStateCombinations: { + var largest = 0; + for (var i = 0; i < supportedStates.length; ++i) { + var combinations = supportedStates[i]; + if (combinations.length > largest) + largest = combinations.length; + } + return largest; + } + + Loader { + id: controlMetaObjectLoader + source: "qrc" + model.filePath + } + + Flow { + spacing: 10 + + Layout.fillWidth: true + + Repeater { + id: stateRepeater + model: rootDelegate.supportedStates + + ColumnLayout { + id: labelWithDelegatesColumn + spacing: 4 + + readonly property var states: modelData + readonly property string statesAsString: states.join("\n") + + Label { + text: statesAsString.length > 0 ? statesAsString : "normal" + + // 4 is the most states for any element (Button) + Layout.preferredHeight: (fontMetrics.lineSpacing) * (rootDelegate.maxStateCombinations + 1) + } + + ControlContainer { + id: controlContainer + objectName: controlName + "ControlContainer" + controlMetaObject: rootDelegate.controlMetaObject + states: labelWithDelegatesColumn.states + + Layout.alignment: Qt.AlignHCenter + } + } + } + } + + ExampleContainer { + id: exampleContainer + controlMetaObject: rootDelegate.controlMetaObject + visible: !!controlMetaObject.exampleComponent + + Layout.alignment: Qt.AlignHCenter + Layout.topMargin: visible ? 14 : 0 + Layout.fillWidth: true + Layout.preferredHeight: visible ? implicitHeight : 0 + } + } + } + } + + RowLayout { + id: busyIndicatorRow + anchors.centerIn: parent + visible: false + + BusyIndicator { + id: busyIndicator + running: visible + } + + Label { + text: qsTr("Fixing assets...") + font.pixelSize: Qt.application.font.pixelSize * 2 + } + } + + ToolTip { + id: infoToolTip + x: (parent.width - width) / 2 + y: parent.height - height - 40 + parent: window.contentItem + } +} + |