qt/{qtwayland,qtdeclarative,qtsvg}: finish 6.11.0->6.11.1 vendored bump
Same half-done bump as qtbase: recipe tar= was 6.11.1 but the vendored source/ trees stayed 6.11.0. These three carry no Redox port (0 __redox__ markers), so each is a clean pristine-6.11.1 re-lay: - qtwayland: pristine 6.11.1 (no patches) - qtdeclarative: pristine 6.11.1 + P1-skip-tools-crosscompile.patch - qtsvg: pristine 6.11.1; stale 6.11.0 source.tar replaced; CVE-2026-6210 patch dropped (the heap-overflow fix is already in upstream 6.11.1) Drops the injected line-duplication corruption present in the old trees.
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
set(QT_REPO_MODULE_VERSION "6.11.0")
|
||||
set(QT_REPO_MODULE_VERSION "6.11.1")
|
||||
set(QT_REPO_MODULE_PRERELEASE_VERSION_SEGMENT "alpha1")
|
||||
|
||||
set(QT_EXTRA_INTERNAL_TARGET_DEFINES
|
||||
"QT_LEAN_HEADERS=1"
|
||||
"QT_LEAN_HEADERS=2"
|
||||
"QT_NO_QASCONST=1"
|
||||
"QT_NO_FOREACH=1"
|
||||
"QT_NO_QPAIR=1"
|
||||
"QT_NO_QSNPRINTF=1"
|
||||
"QT_NO_URL_CAST_FROM_STRING=1"
|
||||
)
|
||||
|
||||
@@ -1 +1 @@
|
||||
a59ffcedd7cf65b8d2be249c9656f7d540a4a104
|
||||
e50599b560e38d5991de59020671c01a42d1d40e
|
||||
|
||||
@@ -14,6 +14,24 @@ gccsetup --cc gcc --cxx g++ --config "$BAUHAUS_CONFIG"
|
||||
cd "$CAFECC_BASEPATH"
|
||||
BAUHAUS_IR_COMPRESSION=none COMPILE_ONLY=1 cmake -G Ninja -DAXIVION_ANALYSIS_TOOLCHAIN_FILE=/home/qt/bauhaus-suite/profiles/cmake/axivion-launcher-toolchain.cmake -DCMAKE_PREFIX_PATH=/home/qt/work/qt/qtdeclarative/build -DCMAKE_PROJECT_INCLUDE_BEFORE=/home/qt/bauhaus-suite/profiles/cmake/axivion-before-project-hook.cmake -B build -S . --fresh
|
||||
cmake --build build -j4
|
||||
|
||||
ROOT_DIR=src
|
||||
MAGIC="Qt-Security score:critical"
|
||||
|
||||
INCLUDE_FILES=""
|
||||
|
||||
while IFS= read -r file; do
|
||||
if [ -z "$INCLUDE_FILES" ]; then
|
||||
INCLUDE_FILES="$file"
|
||||
else
|
||||
INCLUDE_FILES="$INCLUDE_FILES:$file"
|
||||
fi
|
||||
done <<EOF
|
||||
$(grep -rl "$MAGIC" "$ROOT_DIR")
|
||||
EOF
|
||||
|
||||
export INCLUDE_FILES
|
||||
|
||||
for MODULE in qtqml qtquick qtquickcontrols qtquickdialogs qtquicklayouts qtquicktest; do
|
||||
export MODULE
|
||||
export PLUGINS=""
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
dependencies:
|
||||
../qtbase:
|
||||
ref: 8ba7ea4b77a4b8f1948760221e264917ddc9e1c8
|
||||
ref: 59c81a3c2247b821b9b84b4eb8d939b77e07e276
|
||||
required: true
|
||||
../qtimageformats:
|
||||
ref: ade536558e868143d615512a6873daabb8e9195b
|
||||
ref: 77f35e5694885844c3eb3a737769b5ed290b8ccc
|
||||
required: false
|
||||
../qtlanguageserver:
|
||||
ref: fa86fa006217f26d742127a6ef96677c87315b5e
|
||||
ref: 7ef3bccd89cc163a664b46fe80a4bd56084b1983
|
||||
required: false
|
||||
../qtshadertools:
|
||||
ref: 1c7a78fd7480f11a49eb8135b44d138edb0f0df8
|
||||
ref: b3b8537b3c5ab01919e30b87d48d2f1ba1f2a3fe
|
||||
required: false
|
||||
../qtsvg:
|
||||
ref: 4126867385dc0b7a9404dcd69726c28ed0d5e10a
|
||||
ref: 2596f43da2dc72d2afecc084355b0f5f87922a6c
|
||||
required: false
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ plugins {
|
||||
|
||||
QtBuild {
|
||||
// Relative for Qt (Installer or MaintenanceTool) installations.
|
||||
qtPath = file('../../../../../../../6.11.0')
|
||||
qtPath = file('../../../../../../../6.11.1')
|
||||
projectPath = file('../../qtabstractitemmodel')
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
plugins {
|
||||
id 'com.android.application' version '8.10.1' apply false
|
||||
id 'com.android.application' version '9.0.0' apply false
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ plugins {
|
||||
//! [build.gradle QtBuild config]
|
||||
QtBuild {
|
||||
// Relative for Qt (Installer or MaintenanceTool) installations.
|
||||
qtPath = file("../../../../../../../6.11.0")
|
||||
qtPath = file("../../../../../../../6.11.1")
|
||||
projectPath = file("../../qtabstractlistmodel")
|
||||
}
|
||||
//! [build.gradle QtBuild config]
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ plugins {
|
||||
|
||||
QtBuild {
|
||||
// Relative for Qt (Installer or MaintenanceTool) installations.
|
||||
qtPath = file('../../../../../../6.11.0')
|
||||
qtPath = file('../../../../../../6.11.1')
|
||||
projectPath = file('../../qtquickview')
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
plugins {
|
||||
id 'com.android.application' version '8.10.1' apply false
|
||||
id 'com.android.application' version '9.0.0' apply false
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ plugins {
|
||||
|
||||
QtBuild {
|
||||
// Relative for Qt (Installer or MaintenanceTool) installations.
|
||||
qtPath = file("../../../../../../6.11.0")
|
||||
qtPath = file("../../../../../../6.11.1")
|
||||
projectPath = file("../../qtquickview")
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
plugins {
|
||||
id("com.android.application") version "8.10.1" apply false
|
||||
id("com.android.application") version "9.0.0" apply false
|
||||
id("org.jetbrains.kotlin.android") version "2.3.0" apply false
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@ qt_add_executable(animationexample
|
||||
main.cpp
|
||||
)
|
||||
|
||||
set_target_properties(animationexample PROPERTIES FOLDER "qtc_runnable")
|
||||
|
||||
target_link_libraries(animationexample PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
|
||||
@@ -16,6 +16,8 @@ qt_add_executable(draganddropexample
|
||||
main.cpp
|
||||
)
|
||||
|
||||
set_target_properties(draganddropexample PROPERTIES FOLDER "qtc_runnable")
|
||||
|
||||
qt_add_qml_module(draganddropexample
|
||||
URI draganddrop
|
||||
QML_FILES
|
||||
|
||||
Vendored
+1
@@ -7,6 +7,7 @@ import QtQuick.Layouts
|
||||
|
||||
Control {
|
||||
padding: 8
|
||||
width: 320; height: 240
|
||||
contentItem: ColumnLayout {
|
||||
component DragAndDropArea: Rectangle {
|
||||
id: item
|
||||
|
||||
+2
@@ -6,6 +6,8 @@
|
||||
\examplecategory {Data Processing & I/O}
|
||||
\brief A collection of QML local storage examples.
|
||||
\borderedimage qml-localstorage-example.png
|
||||
{Activity tracker with trip entries showing dates,
|
||||
descriptions, and distances}
|
||||
|
||||
\e{Local Storage} is a collection of small QML examples relating to
|
||||
Qt Quick's \l{local storage} functionality.
|
||||
|
||||
-1
@@ -5,7 +5,6 @@
|
||||
#define SONGDATAGENERATOR_H
|
||||
#include "mediaelement.h"
|
||||
|
||||
#include <QPair>
|
||||
#include <QStringList>
|
||||
|
||||
class SongDataGenerator
|
||||
|
||||
+2
@@ -14,6 +14,8 @@ qt_add_executable(itemswitcherexample WIN32 MACOSX_BUNDLE
|
||||
main.cpp
|
||||
)
|
||||
|
||||
set_target_properties(itemswitcherexample PROPERTIES FOLDER "qtc_runnable")
|
||||
|
||||
target_link_libraries(itemswitcherexample PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
|
||||
+2
@@ -14,6 +14,8 @@ qt_add_executable(neumorphicpanelexample WIN32 MACOSX_BUNDLE
|
||||
main.cpp
|
||||
)
|
||||
|
||||
set_target_properties(neumorphicpanelexample PROPERTIES FOLDER "qtc_runnable")
|
||||
|
||||
target_link_libraries(neumorphicpanelexample PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
|
||||
+2
@@ -14,6 +14,8 @@ qt_add_executable(testbedexample WIN32 MACOSX_BUNDLE
|
||||
main.cpp
|
||||
)
|
||||
|
||||
set_target_properties(testbedexample PROPERTIES FOLDER "qtc_runnable")
|
||||
|
||||
target_link_libraries(testbedexample PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
|
||||
+2
@@ -14,6 +14,8 @@ qt_add_executable(affectorsexample WIN32 MACOSX_BUNDLE
|
||||
main.cpp
|
||||
)
|
||||
|
||||
set_target_properties(affectorsexample PROPERTIES FOLDER "qtc_runnable")
|
||||
|
||||
target_link_libraries(affectorsexample PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
|
||||
@@ -14,6 +14,8 @@ qt_add_executable(emittersexample WIN32 MACOSX_BUNDLE
|
||||
main.cpp
|
||||
)
|
||||
|
||||
set_target_properties(emittersexample PROPERTIES FOLDER "qtc_runnable")
|
||||
|
||||
target_link_libraries(emittersexample PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
|
||||
+2
@@ -14,6 +14,8 @@ qt_add_executable(imageparticleexample WIN32 MACOSX_BUNDLE
|
||||
main.cpp
|
||||
)
|
||||
|
||||
set_target_properties(imageparticleexample PROPERTIES FOLDER "qtc_runnable")
|
||||
|
||||
target_link_libraries(imageparticleexample PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
|
||||
@@ -14,6 +14,8 @@ qt_add_executable(systemexample WIN32 MACOSX_BUNDLE
|
||||
main.cpp
|
||||
)
|
||||
|
||||
set_target_properties(systemexample PROPERTIES FOLDER "qtc_runnable")
|
||||
|
||||
target_link_libraries(systemexample PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
|
||||
@@ -12,6 +12,8 @@ add_subdirectory("../shared" "shared")
|
||||
|
||||
qt_add_executable(pointerhandlersexample WIN32 MACOSX_BUNDLE main.cpp)
|
||||
|
||||
set_target_properties(pointerhandlersexample PROPERTIES FOLDER "qtc_runnable")
|
||||
|
||||
target_link_libraries(pointerhandlersexample PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
|
||||
@@ -16,6 +16,8 @@ qt_add_executable(shapesexample
|
||||
main.cpp
|
||||
)
|
||||
|
||||
set_target_properties(shapesexample PROPERTIES FOLDER "qtc_runnable")
|
||||
|
||||
target_link_libraries(shapesexample PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
|
||||
+2
@@ -16,6 +16,8 @@ qt_add_executable(weatherforecastexample
|
||||
main.cpp
|
||||
)
|
||||
|
||||
set_target_properties(weatherforecastexample PROPERTIES FOLDER "qtc_runnable")
|
||||
|
||||
target_link_libraries(weatherforecastexample PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
|
||||
+2
-1
@@ -108,7 +108,8 @@ void MainWindow::createQuickWidgetsInTabs(QMdiArea *mdiArea)
|
||||
widget->setSource(QUrl("qrc:quickwidget/rotatingsquare.qml"));
|
||||
widget->setWindowTitle(QString::asprintf("Tab %d", i + 1));
|
||||
QPushButton *btn = new QPushButton(msgToTopLevel, widget);
|
||||
connect(btn, &QPushButton::clicked, widget, [=] {
|
||||
connect(btn, &QPushButton::clicked,
|
||||
widget, [this, widget, btn, tabWidget, msgFromTopLevel, msgToTopLevel] {
|
||||
if (widget->parent()) {
|
||||
widget->setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
widget->setParent(nullptr);
|
||||
|
||||
+10
@@ -167,6 +167,15 @@ void QuickRenderer::ensureTexture()
|
||||
qreal dpr = m_quickWindow->devicePixelRatio();
|
||||
QSize textureSize = m_quickWindow->size() * dpr;
|
||||
QOpenGLFunctions *f = m_context->functions();
|
||||
|
||||
if (m_textureId && m_textureSize != textureSize) {
|
||||
f->glDeleteTextures(1, &m_textureId);
|
||||
m_textureId = 0;
|
||||
}
|
||||
|
||||
if (m_textureId)
|
||||
return;
|
||||
|
||||
f->glGenTextures(1, &m_textureId);
|
||||
f->glBindTexture(GL_TEXTURE_2D, m_textureId);
|
||||
f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
@@ -174,6 +183,7 @@ void QuickRenderer::ensureTexture()
|
||||
f->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, textureSize.width(), textureSize.height(), 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
m_quickWindow->setRenderTarget(QQuickRenderTarget::fromOpenGLTexture(m_textureId, textureSize));
|
||||
m_textureSize = textureSize;
|
||||
}
|
||||
|
||||
void QuickRenderer::render(QMutexLocker<QMutex> *lock)
|
||||
|
||||
+1
@@ -62,6 +62,7 @@ private:
|
||||
QQuickRenderControl *m_renderControl;
|
||||
QRhi *m_rhi;
|
||||
uint m_textureId;
|
||||
QSize m_textureSize;
|
||||
CubeRenderer *m_cubeRenderer;
|
||||
QMutex m_quitMutex;
|
||||
bool m_quit;
|
||||
|
||||
@@ -16,6 +16,8 @@ qt_add_executable(textexample
|
||||
main.cpp
|
||||
)
|
||||
|
||||
set_target_properties(textexample PROPERTIES FOLDER "qtc_runnable")
|
||||
|
||||
target_link_libraries(textexample PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
|
||||
@@ -28,16 +28,19 @@ Rectangle {
|
||||
font.pixelSize: screen.pixelSize
|
||||
color: screen.textColor
|
||||
text: screen.text
|
||||
renderType: Text.CurveRendering
|
||||
}
|
||||
Text {
|
||||
font.pixelSize: screen.pixelSize
|
||||
color: screen.textColor
|
||||
text: screen.text
|
||||
renderType: Text.CurveRendering
|
||||
}
|
||||
Text {
|
||||
font.pixelSize: screen.pixelSize
|
||||
color: screen.textColor
|
||||
text: screen.text
|
||||
renderType: Text.CurveRendering
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ qt_add_executable(viewsexample
|
||||
main.cpp
|
||||
)
|
||||
|
||||
set_target_properties(viewsexample PROPERTIES FOLDER "qtc_runnable")
|
||||
|
||||
target_link_libraries(viewsexample PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
|
||||
@@ -16,6 +16,8 @@ qt_add_executable(windowexample
|
||||
main.cpp
|
||||
)
|
||||
|
||||
set_target_properties(windowexample PROPERTIES FOLDER "qtc_runnable")
|
||||
|
||||
target_link_libraries(windowexample PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
|
||||
+9
-4
@@ -34,16 +34,21 @@ Dialog {
|
||||
|
||||
focus: true
|
||||
modal: true
|
||||
title: qsTr("Add Contact")
|
||||
standardButtons: Dialog.Ok | Dialog.Cancel
|
||||
|
||||
contentItem: ContactForm {
|
||||
id: form
|
||||
Binding {
|
||||
target: dialog.standardButton(Dialog.Ok)
|
||||
property: "enabled"
|
||||
value: form.fullName.text
|
||||
&& form.address.text
|
||||
&& form.city.text
|
||||
&& form.number.text
|
||||
}
|
||||
}
|
||||
|
||||
onAccepted: {
|
||||
if (form.fullName.text && form.address.text && form.city.text && form.number.text) {
|
||||
finished(form.fullName.text, form.address.text, form.city.text, form.number.text);
|
||||
}
|
||||
finished(form.fullName.text, form.address.text, form.city.text, form.number.text);
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -68,5 +68,6 @@ GridLayout {
|
||||
Layout.minimumWidth: grid.minimumInputSize
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignBaseline
|
||||
placeholderText: grid.placeholderText
|
||||
inputMethodHints: Qt.ImhDigitsOnly
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -18,9 +18,9 @@ ApplicationWindow {
|
||||
id: contactDialog
|
||||
onFinished: function(fullName, address, city, number) {
|
||||
if (window.currentContact === -1)
|
||||
contactView.model.append(fullName, address, city, number)
|
||||
contactView.model.add(fullName, address, city, number)
|
||||
else
|
||||
contactView.model.set(window.currentContact, fullName, address, city, number)
|
||||
contactView.model.edit(window.currentContact, fullName, address, city, number)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-8
@@ -53,23 +53,20 @@ QVariantMap ContactModel::get(int row) const
|
||||
return { {"fullName", contact.fullName}, {"address", contact.address}, {"city", contact.city}, {"number", contact.number} };
|
||||
}
|
||||
|
||||
void ContactModel::append(const QString &fullName, const QString &address, const QString &city, const QString &number)
|
||||
void ContactModel::add(const QString &fullName, const QString &address, const QString &city, const QString &number)
|
||||
{
|
||||
int row = 0;
|
||||
while (row < m_contacts.count() && fullName > m_contacts.at(row).fullName)
|
||||
while (row < m_contacts.count() && (fullName.compare(m_contacts.at(row).fullName, Qt::CaseInsensitive) > 0))
|
||||
++row;
|
||||
beginInsertRows(QModelIndex(), row, row);
|
||||
m_contacts.insert(row, {fullName, address, city, number});
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void ContactModel::set(int row, const QString &fullName, const QString &address, const QString &city, const QString &number)
|
||||
void ContactModel::edit(int row, const QString &fullName, const QString &address, const QString &city, const QString &number)
|
||||
{
|
||||
if (row < 0 || row >= m_contacts.count())
|
||||
return;
|
||||
|
||||
m_contacts.replace(row, { fullName, address, city, number });
|
||||
dataChanged(index(row, 0), index(row, 0), { FullNameRole, AddressRole, CityRole, NumberRole });
|
||||
remove(row);
|
||||
add(fullName, address, city, number);
|
||||
}
|
||||
|
||||
void ContactModel::remove(int row)
|
||||
|
||||
+2
-2
@@ -28,8 +28,8 @@ public:
|
||||
QHash<int, QByteArray> roleNames() const;
|
||||
|
||||
Q_INVOKABLE QVariantMap get(int row) const;
|
||||
Q_INVOKABLE void append(const QString &fullName, const QString &address, const QString &city, const QString &number);
|
||||
Q_INVOKABLE void set(int row, const QString &fullName, const QString &address, const QString &city, const QString &number);
|
||||
Q_INVOKABLE void add(const QString &fullName, const QString &address, const QString &city, const QString &number);
|
||||
Q_INVOKABLE void edit(int row, const QString &fullName, const QString &address, const QString &city, const QString &number);
|
||||
Q_INVOKABLE void remove(int row);
|
||||
|
||||
private:
|
||||
|
||||
+3
-1
@@ -6,13 +6,15 @@ project(StyleKitExample VERSION 1.0 LANGUAGES CXX)
|
||||
|
||||
find_package(Qt6 6.11 REQUIRED Core Gui Qml Quick QuickControls2)
|
||||
find_program(QSB_EXECUTABLE qsb HINTS "${QT_HOST_PATH}/bin")
|
||||
if(NOT QSB_EXECUTABLE OR NOT EXISTS "${QSB_EXECUTABLE}")
|
||||
message(FATAL_ERROR "qsb not found. Please install Qt Shader Tools to build this example.")
|
||||
endif()
|
||||
|
||||
qt_standard_project_setup(REQUIRES 6.11)
|
||||
|
||||
set(STYLES
|
||||
styles/Plain.qml
|
||||
styles/Haze.qml
|
||||
styles/Experimental.qml
|
||||
styles/Vitrum.qml
|
||||
styles/CustomDelegates.qml
|
||||
)
|
||||
|
||||
-496
@@ -1,496 +0,0 @@
|
||||
// Copyright (C) 2025 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
import QtQuick
|
||||
import Qt.labs.StyleKit
|
||||
|
||||
Style {
|
||||
id: style
|
||||
|
||||
control {
|
||||
leftPadding: 10
|
||||
topPadding: 5
|
||||
rightPadding: 10
|
||||
bottomPadding: 5
|
||||
|
||||
background {
|
||||
implicitWidth: 100
|
||||
implicitHeight: 40
|
||||
shadow {
|
||||
opacity: 0.8
|
||||
scale: 1.1
|
||||
verticalOffset: 5
|
||||
horizontalOffset: 2
|
||||
}
|
||||
}
|
||||
|
||||
handle {
|
||||
implicitWidth: 25
|
||||
implicitHeight: 25
|
||||
radius: 25
|
||||
color: "lightslategray"
|
||||
}
|
||||
|
||||
indicator {
|
||||
foreground.margins: 2
|
||||
|
||||
// first.color: "green"
|
||||
// second.color: "yellow"
|
||||
// up.color: "red" // alias. Can control.indicator.up have control.indicator as alt?
|
||||
// down.color: "blue"
|
||||
}
|
||||
|
||||
text.color: "blue"
|
||||
|
||||
transition: Transition {
|
||||
StyleAnimation {
|
||||
animateColors: true
|
||||
animateBackgroundBorder: true
|
||||
duration: 300
|
||||
}
|
||||
}
|
||||
|
||||
hovered {
|
||||
transition: null
|
||||
background {
|
||||
border.width: 4
|
||||
}
|
||||
handle {
|
||||
border.width: 2
|
||||
}
|
||||
text.color: "yellow"
|
||||
}
|
||||
|
||||
pressed {
|
||||
background {
|
||||
scale: 0.95
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pane {
|
||||
background {
|
||||
border.width: 0
|
||||
implicitWidth: 200
|
||||
implicitHeight: 200
|
||||
shadow.visible: false
|
||||
}
|
||||
}
|
||||
|
||||
frame {
|
||||
background {
|
||||
border.width: 1
|
||||
shadow.visible: true
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
background {
|
||||
radius: 8
|
||||
opacity: 0.8
|
||||
|
||||
gradient: Gradient {
|
||||
GradientStop { position: 0.0; color: Qt.alpha("black", 0.0)}
|
||||
GradientStop { position: 1.0; color: Qt.alpha("black", 0.4)}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
radioButton {
|
||||
indicator {
|
||||
foreground {
|
||||
margins: 4
|
||||
radius: 25 / 2
|
||||
border.width: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
textInput {
|
||||
background {
|
||||
implicitWidth: 200
|
||||
}
|
||||
}
|
||||
|
||||
spinBox {
|
||||
padding: 0
|
||||
background {
|
||||
implicitWidth: 100
|
||||
}
|
||||
}
|
||||
|
||||
comboBox {
|
||||
background {
|
||||
implicitWidth: 200
|
||||
implicitHeight: 30
|
||||
gradient: null
|
||||
}
|
||||
indicator {
|
||||
foreground.scale: 0.5
|
||||
}
|
||||
pressed.background.scale: 1.0
|
||||
variations: [contextMenu, mini, alert, "dont crash"]
|
||||
}
|
||||
|
||||
StyleVariation {
|
||||
id: contextMenu
|
||||
itemDelegate {
|
||||
background {
|
||||
radius: 0
|
||||
border.width: 0
|
||||
shadow.color: "transparent"
|
||||
gradient: null
|
||||
}
|
||||
hovered.background.color: "pink"
|
||||
}
|
||||
|
||||
control.transition: null
|
||||
}
|
||||
|
||||
StyleVariation {
|
||||
id: mini
|
||||
control.background.implicitHeight: 10
|
||||
}
|
||||
|
||||
StyleVariation {
|
||||
id: alert
|
||||
control.background.color: "red"
|
||||
}
|
||||
|
||||
slider {
|
||||
background.implicitWidth: 180
|
||||
indicator {
|
||||
implicitHeight: 8
|
||||
radius: 8
|
||||
foreground {
|
||||
radius: 8
|
||||
}
|
||||
}
|
||||
handle {
|
||||
radius: 25
|
||||
first {
|
||||
topRightRadius: 0
|
||||
bottomRightRadius: 0
|
||||
color: "orange"
|
||||
}
|
||||
second {
|
||||
topLeftRadius: 0
|
||||
bottomLeftRadius: 0
|
||||
color: "yellow"
|
||||
}
|
||||
}
|
||||
vertical {
|
||||
handle {
|
||||
first {
|
||||
radius: 25
|
||||
topLeftRadius: 0
|
||||
bottomLeftRadius: 0
|
||||
}
|
||||
second {
|
||||
radius: 25
|
||||
topRightRadius: 0
|
||||
bottomRightRadius: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switchControl {
|
||||
indicator {
|
||||
implicitWidth: 60
|
||||
implicitHeight: 30
|
||||
radius: 5
|
||||
foreground.radius: 4
|
||||
}
|
||||
handle {
|
||||
leftMargin: 3
|
||||
rightMargin: 3
|
||||
}
|
||||
}
|
||||
|
||||
itemDelegate {
|
||||
background {
|
||||
radius: 0
|
||||
border.width: 0
|
||||
shadow.visible: false
|
||||
gradient: null
|
||||
}
|
||||
transition: null
|
||||
hovered {
|
||||
background.color: style.palette.highlight
|
||||
}
|
||||
}
|
||||
|
||||
// THEMES
|
||||
|
||||
light: Theme {
|
||||
control {
|
||||
background {
|
||||
border.color: "lightgray"
|
||||
shadow.color: "#808080"
|
||||
}
|
||||
|
||||
checked {
|
||||
background.shadow.color: "white"
|
||||
background.color: "blue"
|
||||
}
|
||||
|
||||
focused {
|
||||
background.border.color: "white"
|
||||
background.shadow.color: "white"
|
||||
}
|
||||
|
||||
hovered {
|
||||
background {
|
||||
border.color: "white"
|
||||
shadow.color: "white"
|
||||
}
|
||||
}
|
||||
|
||||
disabled {
|
||||
background {
|
||||
color: "#a7a7a7"
|
||||
shadow.color: "transparent"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
background.color: "lightgray"
|
||||
}
|
||||
|
||||
textField {
|
||||
variations: StyleVariation {
|
||||
button {
|
||||
background {
|
||||
radius: 0
|
||||
implicitWidth: 50
|
||||
implicitHeight: 20
|
||||
margins: 4
|
||||
color: "orange"
|
||||
shadow.color: "transparent"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
palettes {
|
||||
system.window: "#989898"
|
||||
textField.text: "#4e4e4e"
|
||||
button {
|
||||
buttonText: "white"
|
||||
highlightedText: "white"
|
||||
brightText: "#4e4e4e"
|
||||
disabled.buttonText: "#4e4e4e"
|
||||
disabled.highlightedText: "#4e4e4e"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dark: Theme {
|
||||
control {
|
||||
background {
|
||||
border.color: "#3d373b"
|
||||
shadow.color: "#404040"
|
||||
color: "#8e848a"
|
||||
}
|
||||
|
||||
handle {
|
||||
border.color: "black"
|
||||
}
|
||||
|
||||
focused {
|
||||
background {
|
||||
border.color: "white"
|
||||
shadow.color: "white"
|
||||
color: "#bbbbbb"
|
||||
}
|
||||
}
|
||||
|
||||
hovered {
|
||||
background {
|
||||
border.color: "white"
|
||||
shadow.color: "white"
|
||||
}
|
||||
}
|
||||
|
||||
disabled {
|
||||
background {
|
||||
color: "red"//"#766e73"
|
||||
shadow.color: "transparent"
|
||||
}
|
||||
checked.background.color: "green"
|
||||
}
|
||||
}
|
||||
|
||||
textField {
|
||||
variations: StyleVariation {
|
||||
button {
|
||||
background {
|
||||
radius: 0
|
||||
implicitWidth: 50
|
||||
implicitHeight: 20
|
||||
margins: 4
|
||||
color: "lightblue"
|
||||
shadow.color: "transparent"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
palettes {
|
||||
system.window: "#544e52"
|
||||
textField.text: "black"
|
||||
button {
|
||||
buttonText: "white"
|
||||
highlightedText: "white"
|
||||
brightText: "white"
|
||||
disabled.buttonText: "darkgray"
|
||||
disabled.highlightedText: "darkgray"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CustomTheme {
|
||||
name: "HighContrast"
|
||||
theme: Theme {
|
||||
control {
|
||||
background {
|
||||
border.color: "black"
|
||||
shadow.color: "transparent"
|
||||
color: "white"
|
||||
gradient: null
|
||||
}
|
||||
|
||||
indicator {
|
||||
implicitWidth: 30
|
||||
implicitHeight: 30
|
||||
}
|
||||
|
||||
handle {
|
||||
border.color: "black"
|
||||
implicitWidth: 30
|
||||
implicitHeight: 30
|
||||
radius: 30
|
||||
}
|
||||
|
||||
hovered {
|
||||
background {
|
||||
border.color: "red"
|
||||
border.width: 3
|
||||
}
|
||||
indicator {
|
||||
border.color: "red"
|
||||
border.width: 3
|
||||
}
|
||||
}
|
||||
|
||||
checked {
|
||||
background {
|
||||
border.color: "red"
|
||||
border.width: 3
|
||||
}
|
||||
}
|
||||
|
||||
disabled {
|
||||
background.color: "gray"
|
||||
}
|
||||
}
|
||||
|
||||
slider {
|
||||
indicator {
|
||||
implicitWidth: 180
|
||||
implicitHeight: 8
|
||||
}
|
||||
}
|
||||
|
||||
switchControl {
|
||||
spacing: 2
|
||||
indicator {
|
||||
implicitWidth: 60
|
||||
implicitHeight: 34
|
||||
}
|
||||
}
|
||||
|
||||
palettes {
|
||||
system.window: "white"
|
||||
textField.text: "black"
|
||||
button {
|
||||
buttonText: "black"
|
||||
highlightedText: "black"
|
||||
brightText: "black"
|
||||
disabled.buttonText: "white"
|
||||
disabled.highlightedText: "white"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CustomTheme {
|
||||
name: "Green"
|
||||
theme: Theme {
|
||||
control {
|
||||
background {
|
||||
border.color: "lightgray"
|
||||
shadow.color: "#404040"
|
||||
color: "#a0c0a0"
|
||||
}
|
||||
|
||||
handle {
|
||||
border.color: "lightgray"
|
||||
shadow.color: "#404040"
|
||||
color: "#a0c0a0"
|
||||
}
|
||||
|
||||
indicator {
|
||||
foreground.color: "lime"
|
||||
foreground.image.color: "black"
|
||||
}
|
||||
|
||||
hovered {
|
||||
background {
|
||||
border.color: "lightgreen"
|
||||
shadow.color: "lightgreen"
|
||||
color: "lightgreen"
|
||||
}
|
||||
handle {
|
||||
border.color: "lightgreen"
|
||||
shadow.color: "lightgreen"
|
||||
color: "lightgreen"
|
||||
}
|
||||
}
|
||||
|
||||
checked {
|
||||
background {
|
||||
shadow.color: "lightgreen"
|
||||
color: "lightgreen"
|
||||
}
|
||||
}
|
||||
|
||||
disabled {
|
||||
background {
|
||||
color: "#80a080"
|
||||
shadow.color: "transparent"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
palettes {
|
||||
system.window: "#547454"
|
||||
textField.text: "green"
|
||||
checkBox.buttonText: "white"
|
||||
button {
|
||||
buttonText: "black"
|
||||
highlightedText: "white"
|
||||
disabled.buttonText: "lightgray"
|
||||
disabled.highlightedText: "lightgray"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CustomTheme {
|
||||
name: "Empty"
|
||||
theme: Theme {}
|
||||
}
|
||||
}
|
||||
+18
-12
@@ -256,15 +256,6 @@ Style {
|
||||
}
|
||||
}
|
||||
|
||||
StyleVariation {
|
||||
name: "alert"
|
||||
abstractButton.background {
|
||||
color: "orchid"
|
||||
border.color: "orchid"
|
||||
shadow.color: "orchid"
|
||||
}
|
||||
}
|
||||
|
||||
/* You can also set one or more StyleVariations on a control type. Unlike Instance
|
||||
* variations—which apply only to specific control instances—type variations are applied
|
||||
* to *all* instances of a control type without requiring the application to use attached
|
||||
@@ -413,6 +404,15 @@ Style {
|
||||
}
|
||||
}
|
||||
|
||||
StyleVariation {
|
||||
name: "alert"
|
||||
abstractButton.background {
|
||||
color: "orchid"
|
||||
border.color: "orchid"
|
||||
shadow.color: "orchid"
|
||||
}
|
||||
}
|
||||
|
||||
CustomControl {
|
||||
controlType: fancyButton
|
||||
background {
|
||||
@@ -513,7 +513,6 @@ Style {
|
||||
}
|
||||
|
||||
scrollBar {
|
||||
background.color: "#8e848a"
|
||||
indicator.foreground.color: "white"
|
||||
}
|
||||
|
||||
@@ -534,6 +533,15 @@ Style {
|
||||
background.shadow.visible: false
|
||||
}
|
||||
|
||||
StyleVariation {
|
||||
name: "alert"
|
||||
abstractButton.background {
|
||||
color: "orchid"
|
||||
border.color: "orchid"
|
||||
shadow.color: "orchid"
|
||||
}
|
||||
}
|
||||
|
||||
CustomControl {
|
||||
controlType: fancyButton
|
||||
background {
|
||||
@@ -690,8 +698,6 @@ Style {
|
||||
background.implicitHeight: 15
|
||||
indicator.implicitWidth: 15
|
||||
indicator.implicitHeight: 15
|
||||
background.color: "#8e848a"
|
||||
background.border.width: 1
|
||||
indicator.border.width: 3
|
||||
indicator.foreground.margins: 3
|
||||
indicator.foreground.color: "lightgray"
|
||||
|
||||
+1
@@ -234,6 +234,7 @@ Style {
|
||||
scrollBar {
|
||||
padding: 2
|
||||
background.implicitHeight: 20
|
||||
background.visible: false
|
||||
indicator.implicitHeight: 20
|
||||
vertical {
|
||||
background.implicitWidth: 20
|
||||
|
||||
@@ -5,4 +5,5 @@ qt_commandline_subconfig(src/qml)
|
||||
qt_commandline_subconfig(src/qmlmodels)
|
||||
qt_commandline_subconfig(src/quick)
|
||||
qt_commandline_subconfig(src/quickcontrols)
|
||||
qt_commandline_subconfig(src/quickshapes)
|
||||
qt_commandline_subconfig(src/quicktemplates)
|
||||
|
||||
+12
@@ -6,6 +6,9 @@
|
||||
#include <QString>
|
||||
#include <wtf/ASCIICType.h>
|
||||
#include <wtf/unicode/Unicode.h>
|
||||
|
||||
#include <QtCore/qhashfunctions.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace WTF {
|
||||
@@ -27,6 +30,15 @@ public:
|
||||
bool operator!() const { return isEmpty(); }
|
||||
|
||||
void dump(PrintStream &) const {}
|
||||
|
||||
private:
|
||||
friend size_t qHash(const String &key, size_t seed = 0) noexcept
|
||||
{
|
||||
// delegate to qHash(QString)
|
||||
const QString &s = key;
|
||||
using QT_PREPEND_NAMESPACE(qHash);
|
||||
return qHash(s, seed);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
|
||||
-30
@@ -397,36 +397,6 @@ template <typename ResultType> struct ArithmeticOperations<unsigned, int, Result
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ResultType> struct ArithmeticOperations<unsigned, long, ResultType, false, true> {
|
||||
static inline bool add(unsigned lhs, long rhs, ResultType& result) WARN_UNUSED_RETURN
|
||||
{
|
||||
int64_t temp = static_cast<int64_t>(lhs) + static_cast<int64_t>(rhs);
|
||||
if (temp < std::numeric_limits<ResultType>::min()) return false;
|
||||
if (temp > std::numeric_limits<ResultType>::max()) return false;
|
||||
result = static_cast<ResultType>(temp);
|
||||
return true;
|
||||
}
|
||||
static inline bool sub(unsigned lhs, long rhs, ResultType& result) WARN_UNUSED_RETURN
|
||||
{
|
||||
int64_t temp = static_cast<int64_t>(lhs) - static_cast<int64_t>(rhs);
|
||||
if (temp < std::numeric_limits<ResultType>::min()) return false;
|
||||
if (temp > std::numeric_limits<ResultType>::max()) return false;
|
||||
result = static_cast<ResultType>(temp);
|
||||
return true;
|
||||
}
|
||||
static inline bool multiply(unsigned lhs, long rhs, ResultType& result) WARN_UNUSED_RETURN
|
||||
{
|
||||
int64_t temp = static_cast<int64_t>(lhs) * static_cast<int64_t>(rhs);
|
||||
if (temp < std::numeric_limits<ResultType>::min()) return false;
|
||||
if (temp > std::numeric_limits<ResultType>::max()) return false;
|
||||
result = static_cast<ResultType>(temp);
|
||||
return true;
|
||||
}
|
||||
static inline bool equals(unsigned lhs, long rhs)
|
||||
{
|
||||
return static_cast<int64_t>(lhs) == static_cast<int64_t>(rhs);
|
||||
}
|
||||
};
|
||||
template <typename U, typename V, typename R> static inline bool safeAdd(U lhs, V rhs, R& result)
|
||||
{
|
||||
return ArithmeticOperations<U, V, R>::add(lhs, rhs, result);
|
||||
|
||||
@@ -34,7 +34,7 @@ if(QT_FEATURE_qml_xmllistmodel)
|
||||
add_subdirectory(qmlxmllistmodel)
|
||||
endif()
|
||||
|
||||
if(TARGET Qt::Gui AND QT_FEATURE_qml_animation)
|
||||
if(TARGET Qt::Gui AND TARGET Qt::qsb AND QT_FEATURE_qml_animation)
|
||||
add_subdirectory(quick)
|
||||
add_subdirectory(quicklayouts)
|
||||
|
||||
@@ -117,7 +117,7 @@ if(QT_FEATURE_qml_network)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(TARGET Qt::Gui AND QT_FEATURE_qml_animation)
|
||||
if(TARGET Qt::Gui AND TARGET Qt::qsb AND QT_FEATURE_qml_animation)
|
||||
find_package(Qt6 ${PROJECT_VERSION} QUIET CONFIG OPTIONAL_COMPONENTS Test)
|
||||
if(QT_FEATURE_testlib AND TARGET Qt::Test)
|
||||
add_subdirectory(qmltest)
|
||||
|
||||
+2
-2
@@ -26,9 +26,9 @@
|
||||
//! [status-docs]
|
||||
|
||||
//! [request-docs]
|
||||
\qmlmethod \1::request()
|
||||
\qmlmethod void \1::request()
|
||||
|
||||
Requests the permission with its current properties.
|
||||
|
||||
\sa QCoreApplication::requestPermission
|
||||
\sa QCoreApplication::requestPermission()
|
||||
//! [request-docs]
|
||||
|
||||
@@ -67,6 +67,7 @@ Q_STATIC_LOGGING_CATEGORY(lcQuickEffect, "qt.quick.effects")
|
||||
\table 70%
|
||||
\row
|
||||
\li \image multieffect-example1.png
|
||||
{Qt logo in grayscale showing full desaturation effect}
|
||||
\li \qml
|
||||
import QtQuick
|
||||
import QtQuick.Effects
|
||||
@@ -97,6 +98,7 @@ Q_STATIC_LOGGING_CATEGORY(lcQuickEffect, "qt.quick.effects")
|
||||
\table 70%
|
||||
\row
|
||||
\li \image multieffect-example1.png
|
||||
{Qt logo in grayscale showing full desaturation effect}
|
||||
\li \qml
|
||||
import QtQuick
|
||||
import QtQuick.Effects
|
||||
@@ -120,6 +122,8 @@ Q_STATIC_LOGGING_CATEGORY(lcQuickEffect, "qt.quick.effects")
|
||||
\table 70%
|
||||
\row
|
||||
\li \image multieffect-example2.png
|
||||
{Qt logo with green glow showing brightness, saturation, and
|
||||
blur effects combined}
|
||||
\li \qml
|
||||
import QtQuick
|
||||
import QtQuick.Effects
|
||||
@@ -145,6 +149,8 @@ Q_STATIC_LOGGING_CATEGORY(lcQuickEffect, "qt.quick.effects")
|
||||
\table 70%
|
||||
\row
|
||||
\li \image multieffect-example3.png
|
||||
{Four stages of Qt logo fading with mask and colorization,
|
||||
from visible green to dissolved pink particles}
|
||||
\li \qml
|
||||
import QtQuick
|
||||
import QtQuick.Effects
|
||||
@@ -250,6 +256,8 @@ void QQuickMultiEffect::setSource(QQuickItem *item)
|
||||
Note that \l paddingRect is always added to the size.
|
||||
|
||||
\image multieffect-example4.png
|
||||
{Blurred images comparing autoPaddingEnabled true with extra
|
||||
space versus false with clipped edges}
|
||||
|
||||
\sa paddingRect
|
||||
|
||||
@@ -282,6 +290,8 @@ void QQuickMultiEffect::setAutoPaddingEnabled(bool enabled)
|
||||
false so that the shadow fits inside the MultiEffect item.
|
||||
|
||||
\image multieffect-example5.png
|
||||
{Two Qt logos with shadows comparing paddingRect values, showing
|
||||
clipped shadow at zero versus full shadow with padding}
|
||||
|
||||
\sa autoPaddingEnabled
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ QT_BEGIN_NAMESPACE
|
||||
\table 70%
|
||||
\row
|
||||
\li \image rectangularshadow-example-1.png
|
||||
{Rounded rectangle with soft shadow offset to upper left}
|
||||
\li \qml
|
||||
import QtQuick
|
||||
import QtQuick.Effects
|
||||
@@ -96,23 +97,31 @@ QT_BEGIN_NAMESPACE
|
||||
\li offset: (0, 0) \br
|
||||
blur: 20 \br
|
||||
spread: 0 \br
|
||||
\li \image rectangularshadow-css-1.png
|
||||
\li \image rectangularshadow-item-1.png
|
||||
\li \image rectangularshadow-css-1.png {CSS box-shadow with blur 20}
|
||||
\li \image rectangularshadow-item-1.png {RectangularShadow with blur 20}
|
||||
\li \image rectangularshadow-itemblur-1.png
|
||||
{RectangularShadow with blur 24 for closer CSS match}
|
||||
\row
|
||||
\li offset: (-10, -20) \br
|
||||
blur: 40 \br
|
||||
spread: 0 \br
|
||||
\li \image rectangularshadow-css-2.png
|
||||
{CSS box-shadow with offset and blur 40}
|
||||
\li \image rectangularshadow-item-2.png
|
||||
{RectangularShadow with offset and blur 40}
|
||||
\li \image rectangularshadow-itemblur-2.png
|
||||
{RectangularShadow with blur 48 for closer CSS match}
|
||||
\row
|
||||
\li offset: (-10, -20) \br
|
||||
blur: 40 \br
|
||||
spread: 10 \br
|
||||
\li \image rectangularshadow-css-3.png
|
||||
{CSS box-shadow with offset, blur 40, and spread 10}
|
||||
\li \image rectangularshadow-item-3.png
|
||||
{RectangularShadow with offset, blur 40, and spread 10}
|
||||
\li \image rectangularshadow-itemblur-3.png
|
||||
{RectangularShadow with blur 48 and spread 10 for closer CSS
|
||||
match}
|
||||
\endtable
|
||||
|
||||
|
||||
|
||||
@@ -128,6 +128,33 @@ Q_STATIC_LOGGING_CATEGORY(lcTableModel, "qt.qml.tablemodel")
|
||||
\l [QtQuickControls2]{TextField}, and so that delegate is declared
|
||||
last as a fallback.
|
||||
|
||||
\section1 Using the TableModel with External JSON Sources
|
||||
|
||||
If the structure of the data in a JSON object matches the structure defined
|
||||
by the TableModel, it can be assigned directly to the model using the rows
|
||||
property. All rows in the data must conform to the columns defined by the model.
|
||||
|
||||
For example, if the model is defined as:
|
||||
|
||||
\snippet main.qml model
|
||||
|
||||
The source has the required data but not necessarily in the
|
||||
required structure, you can download and parse it into a form that
|
||||
conforms to the structure that the model defines and assign the result directly.
|
||||
|
||||
\snippet main.qml parse
|
||||
|
||||
and the result can be assigned directly
|
||||
|
||||
\snippet main.qml assign
|
||||
|
||||
You can also provide the JSON object by importing a JavaScript file as a
|
||||
module. See the documentation for \l TreeModel for an example on how to do this.
|
||||
|
||||
\warning Ensure that the JSON data comes from a trusted source. Since the
|
||||
model dynamically populates its rows based on the input, malformed or
|
||||
untrusted JSON can lead to unexpected behavior or performance issues.
|
||||
|
||||
\sa TableModelColumn, TableView, QAbstractTableModel
|
||||
*/
|
||||
|
||||
|
||||
@@ -56,6 +56,42 @@ static const QString ROWS_PROPERTY_NAME = u"rows"_s;
|
||||
|
||||
To add new rows, use \l appendRow(). To modify existing rows, use
|
||||
\l setRow(), \l removeRow() and \l clear().
|
||||
|
||||
\section1 Using the TreeModel with External JSON Sources
|
||||
|
||||
While the intended use of the TreeModel is to define the JSON data in-place in
|
||||
the QML file, you can use any JSON object with the model as long as
|
||||
its structure matches the structure defined by the TreeModel. If all the rows
|
||||
of the JSON object conform to the columns defined by the model, you can
|
||||
assign it directly through the rows property.
|
||||
|
||||
The source of the JSON object can be a file. For example, if the model is
|
||||
defined as
|
||||
|
||||
\snippet setRowsViaJSON.qml model
|
||||
|
||||
and the JSON object stored in the file and looks like
|
||||
|
||||
\snippet TreeData.js file
|
||||
|
||||
then this object can be provided by importing the JavaScript file as a
|
||||
|
||||
module
|
||||
|
||||
\snippet setRowsViaJSON.qml import
|
||||
|
||||
and then it can be assigned directly
|
||||
|
||||
\snippet setRowsViaJSON.qml assignment
|
||||
|
||||
\warning Ensure that the JSON data comes from a trusted source. Since the
|
||||
model dynamically populates its rows based on the input, malformed or
|
||||
untrusted JSON can lead to unexpected behavior or performance issues.
|
||||
|
||||
See \l TableModel for an another example where a JSON object is parsed
|
||||
into and assigned as a JavaScript array.
|
||||
|
||||
\sa TableModelColumn, TreeView
|
||||
*/
|
||||
|
||||
QQmlTreeModel::QQmlTreeModel(QObject *parent)
|
||||
@@ -122,12 +158,21 @@ void QQmlTreeModel::setRowsPrivate(const QVariantList &rowsAsVariantList)
|
||||
|
||||
beginResetModel();
|
||||
|
||||
// In case the model is empty and we cannot insert any new rows in the loop below,
|
||||
// we don't want to emit rowsChanged
|
||||
const bool wasEmpty = mRows.empty();
|
||||
|
||||
// We don't clear the column or role data, because a TreeModel should not be reused in that way.
|
||||
// Once it has valid data, its columns and roles are fixed.
|
||||
mRows.clear();
|
||||
|
||||
for (const auto &rowAsVariant : rowsAsVariantList)
|
||||
mRows.push_back(std::make_unique<QQmlTreeRow>(rowAsVariant));
|
||||
for (const auto &rowAsVariant : rowsAsVariantList) {
|
||||
if (rowAsVariant.canConvert<QVariantMap>())
|
||||
mRows.push_back(std::make_unique<QQmlTreeRow>(rowAsVariant));
|
||||
else
|
||||
qmlWarning(this) << "Cannot create tree row as the row does not contain "
|
||||
<< "key-value pairs";
|
||||
}
|
||||
|
||||
// Gather metadata the first time rows is set.
|
||||
// If we call setrows on an empty model, mInitialRows will be empty, but mRows is not
|
||||
@@ -135,7 +180,14 @@ void QQmlTreeModel::setRowsPrivate(const QVariantList &rowsAsVariantList)
|
||||
fetchColumnMetadata();
|
||||
|
||||
endResetModel();
|
||||
emit rowsChanged();
|
||||
|
||||
// was empty, still empty => no emit
|
||||
// was empty, now non-empty => emit
|
||||
// was not empty, now empty => emit
|
||||
// was not empty, now non-empty => emit (there was a clear in-between)
|
||||
|
||||
if (!wasEmpty || !mRows.empty())
|
||||
emit rowsChanged();
|
||||
}
|
||||
|
||||
QVariant QQmlTreeModel::dataPrivate(const QModelIndex &index, const QString &roleName) const
|
||||
@@ -212,17 +264,23 @@ void QQmlTreeModel::appendRow(QModelIndex parent, const QVariant &row)
|
||||
qmlWarning(this) << "append: could not find any node at the specified index"
|
||||
<< " - the new row will be appended to root";
|
||||
|
||||
beginInsertRows(QModelIndex(),
|
||||
if (data.canConvert<QVariantMap>()) {
|
||||
beginInsertRows(QModelIndex(),
|
||||
static_cast<int>(mRows.size()),
|
||||
static_cast<int>(mRows.size()));
|
||||
|
||||
mRows.push_back(std::make_unique<QQmlTreeRow>(data));
|
||||
mRows.push_back(std::make_unique<QQmlTreeRow>(data));
|
||||
|
||||
// Gather metadata the first time a row is added.
|
||||
if (mColumnMetadata.isEmpty())
|
||||
fetchColumnMetadata();
|
||||
// Gather metadata the first time a row is added.
|
||||
if (mColumnMetadata.isEmpty())
|
||||
fetchColumnMetadata();
|
||||
|
||||
endInsertRows();
|
||||
endInsertRows();
|
||||
} else {
|
||||
qmlWarning(this) << "Cannot create tree row as the row does not contain "
|
||||
<< "key-value pairs";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
emit rowsChanged();
|
||||
@@ -415,6 +473,7 @@ QModelIndex QQmlTreeModel::index(int row, int column, const QModelIndex &parent)
|
||||
\table
|
||||
|
||||
\row \li \inlineimage treemodel.svg
|
||||
{Tree diagram showing nodes A through F with index paths}
|
||||
\li \list
|
||||
|
||||
\li The root of the tree is special, as it can be referenced by an invalid
|
||||
|
||||
@@ -20,7 +20,7 @@ QQmlTreeRow::QQmlTreeRow(QQmlTreeRow *parentItem)
|
||||
QQmlTreeRow::QQmlTreeRow(const QVariant &data, QQmlTreeRow *parentItem)
|
||||
: m_parent(parentItem)
|
||||
{
|
||||
QVariantMap variantMap = data.toJsonObject().toVariantMap();
|
||||
QVariantMap variantMap = data.toMap();
|
||||
unpackVariantMap(variantMap);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ QT_BEGIN_NAMESPACE
|
||||
The MenuItem type provides a QML API for native platform menu items.
|
||||
|
||||
\image qtlabsplatform-menu.png
|
||||
{Native menu with Zoom In and Zoom Out items}
|
||||
|
||||
A menu item consists of an \l icon, \l text, and \l shortcut.
|
||||
|
||||
|
||||
+1
@@ -18,6 +18,7 @@ QT_BEGIN_NAMESPACE
|
||||
that has the \l {MenuItem::}{separator} property set to \c true by default.
|
||||
|
||||
\image qtlabsplatform-menubar.png
|
||||
{Native menubar with Edit menu showing Cut, Copy, and Paste}
|
||||
|
||||
\labs
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ qt_internal_add_qml_module(LabsStyleKit
|
||||
IMPORTS QtQuick.Controls.Basic
|
||||
SOURCES
|
||||
qqstylekit_p.h qqstylekit.cpp
|
||||
qqstylekitanimation.cpp
|
||||
qqstylekitcontrol_p.h qqstylekitcontrol.cpp
|
||||
qqstylekitcontrols_p.h qqstylekitcontrols.cpp
|
||||
qqstylekitcontrolstate_p.h qqstylekitcontrolstate.cpp
|
||||
|
||||
@@ -37,72 +37,102 @@ T.ProgressBar {
|
||||
palette: control.palette
|
||||
}
|
||||
|
||||
contentItem: IndicatorDelegate {
|
||||
quickControl: control
|
||||
indicatorStyle: styleReader.indicator
|
||||
secondProgress: control.visualPosition
|
||||
StyleKitLayout {
|
||||
id: progressBarLayout
|
||||
container: control.contentItem
|
||||
layoutItems: [
|
||||
StyleKitLayoutItem {
|
||||
id: indicatorItem
|
||||
item: indicator
|
||||
margins {
|
||||
left: styleReader.indicator.leftMargin
|
||||
right: styleReader.indicator.rightMargin
|
||||
top: styleReader.indicator.topMargin
|
||||
bottom: styleReader.indicator.bottomMargin
|
||||
}
|
||||
alignment: styleReader.indicator.alignment
|
||||
fillWidth: styleReader.indicator.implicitWidth === Style.Stretch
|
||||
fillHeight: styleReader.indicator.implicitHeight === Style.Stretch
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: control
|
||||
function onIndeterminateChanged() {
|
||||
if (indeterminate) {
|
||||
control.contentItem.firstProgress = 0
|
||||
control.contentItem.secondProgress = 0
|
||||
control.contentItem.indeterminateAnim.restart()
|
||||
} else {
|
||||
control.contentItem.indeterminateAnim.stop()
|
||||
control.contentItem.firstProgress = 0
|
||||
control.contentItem.secondProgress = Qt.binding(()=>{ return control.visualPosition })
|
||||
contentItem: Item {
|
||||
implicitWidth: Math.max(indicator.implicitWidth, progressBarLayout.implicitWidth)
|
||||
implicitHeight: Math.max(indicator.implicitHeight, progressBarLayout.implicitHeight)
|
||||
|
||||
IndicatorDelegate {
|
||||
id: indicator
|
||||
quickControl: control
|
||||
indicatorStyle: styleReader.indicator
|
||||
secondProgress: control.visualPosition
|
||||
x: indicatorItem.x
|
||||
y: indicatorItem.y
|
||||
width: indicatorItem.width
|
||||
height: indicatorItem.height
|
||||
|
||||
Connections {
|
||||
target: control
|
||||
function onIndeterminateChanged() {
|
||||
if (indeterminate) {
|
||||
control.contentItem.firstProgress = 0
|
||||
control.contentItem.secondProgress = 0
|
||||
control.contentItem.indeterminateAnim.restart()
|
||||
} else {
|
||||
control.contentItem.indeterminateAnim.stop()
|
||||
control.contentItem.firstProgress = 0
|
||||
control.contentItem.secondProgress = Qt.binding(()=>{ return control.visualPosition })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on firstProgress {
|
||||
enabled: !control.indeterminate && !control.contentItem.indeterminateAnim.running
|
||||
NumberAnimation {
|
||||
duration: 100
|
||||
easing.type: Easing.Linear
|
||||
Behavior on firstProgress {
|
||||
enabled: !control.indeterminate && !indicator.indeterminateAnim.running
|
||||
NumberAnimation {
|
||||
duration: 100
|
||||
easing.type: Easing.Linear
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on secondProgress {
|
||||
enabled: !control.indeterminate && !control.contentItem.indeterminateAnim.running
|
||||
NumberAnimation {
|
||||
duration: 100
|
||||
easing.type: Easing.Linear
|
||||
Behavior on secondProgress {
|
||||
enabled: !control.indeterminate && !indicator.indeterminateAnim.running
|
||||
NumberAnimation {
|
||||
duration: 100
|
||||
easing.type: Easing.Linear
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
property Animation indeterminateAnim: SequentialAnimation {
|
||||
running: control.indeterminate
|
||||
loops: Animation.Infinite
|
||||
NumberAnimation {
|
||||
target: control.contentItem
|
||||
property: "secondProgress"
|
||||
to: 1
|
||||
duration: 300
|
||||
easing.type: Easing.Linear
|
||||
}
|
||||
NumberAnimation {
|
||||
target: control.contentItem
|
||||
property: "firstProgress"
|
||||
to: 0.95
|
||||
duration: 600
|
||||
easing.type: Easing.OutExpo
|
||||
}
|
||||
NumberAnimation {
|
||||
target: control.contentItem
|
||||
property: "firstProgress"
|
||||
to: 0
|
||||
duration: 300
|
||||
easing.type: Easing.Linear
|
||||
}
|
||||
NumberAnimation {
|
||||
target: control.contentItem
|
||||
property: "secondProgress"
|
||||
to: 0.05
|
||||
duration: 600
|
||||
easing.type: Easing.OutExpo
|
||||
property Animation indeterminateAnim: SequentialAnimation {
|
||||
running: control.indeterminate
|
||||
loops: Animation.Infinite
|
||||
NumberAnimation {
|
||||
target: indicator
|
||||
property: "secondProgress"
|
||||
to: 1
|
||||
duration: 300
|
||||
easing.type: Easing.Linear
|
||||
}
|
||||
NumberAnimation {
|
||||
target: indicator
|
||||
property: "firstProgress"
|
||||
to: 0.95
|
||||
duration: 600
|
||||
easing.type: Easing.OutExpo
|
||||
}
|
||||
NumberAnimation {
|
||||
target: indicator
|
||||
property: "firstProgress"
|
||||
to: 0
|
||||
duration: 300
|
||||
easing.type: Easing.Linear
|
||||
}
|
||||
NumberAnimation {
|
||||
target: indicator
|
||||
property: "secondProgress"
|
||||
to: 0.05
|
||||
duration: 600
|
||||
easing.type: Easing.OutExpo
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,9 @@
|
||||
// Copyright (C) 2025 The Qt Company Ltd.
|
||||
// Copyright (C) 2026 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
// Qt-Security score:significant reason:default
|
||||
|
||||
import QtQuick
|
||||
|
||||
/*!
|
||||
\qmltype StyleAnimation
|
||||
\inqmlmodule Qt.labs.StyleKit
|
||||
\inherits ParallelAnimation
|
||||
\brief Animates style property changes during state transitions.
|
||||
|
||||
\labs
|
||||
*/
|
||||
|
||||
ParallelAnimation {
|
||||
id: root
|
||||
property alias easing: colorAnimation.easing
|
||||
@@ -45,7 +36,6 @@ ParallelAnimation {
|
||||
readonly property string __geometryProps:
|
||||
"$.implicitWidth, $.implicitHeight, "
|
||||
+ "$.margins, $.leftMargin, $.rightMargin, $.topMargin, $.bottomMargin, "
|
||||
+ "$.leftPadding, $.rightPadding, $.topPadding, $.bottomPadding, "
|
||||
+ "$.minimumWidth, "
|
||||
readonly property string __colorProps:
|
||||
"$.color, $.border.color, $.image.color, $.shadow.color, "
|
||||
@@ -57,7 +47,6 @@ ParallelAnimation {
|
||||
"$.shadow.verticalOffset, $.shadow.horizontalOffset, "
|
||||
+ "$.shadow.scale, $.shadow.blur, "
|
||||
|
||||
|
||||
function __animateIndicators(doAnimate, anim, props) {
|
||||
if (!doAnimate)
|
||||
return
|
||||
|
||||
@@ -13,10 +13,7 @@ qhp.QtLabsStyleKit.virtualFolder = qtlabsstylekit
|
||||
qhp.QtLabsStyleKit.indexTitle = Qt Labs StyleKit
|
||||
qhp.QtLabsStyleKit.indexRoot =
|
||||
|
||||
qhp.QtLabsStyleKit.subprojects = manual qmltypes
|
||||
qhp.QtLabsStyleKit.subprojects.manual.title = Qt Labs StyleKit
|
||||
qhp.QtLabsStyleKit.subprojects.manual.indexTitle = Qt Labs StyleKit
|
||||
qhp.QtLabsStyleKit.subprojects.manual.selectors = group:none
|
||||
qhp.QtLabsStyleKit.subprojects = qmltypes
|
||||
|
||||
qhp.QtLabsStyleKit.subprojects.qmltypes.title = QML Types
|
||||
qhp.QtLabsStyleKit.subprojects.qmltypes.indexTitle = Qt Labs StyleKit QML Types
|
||||
|
||||
+18
-10
@@ -175,6 +175,11 @@ ApplicationWindow {
|
||||
color: "white"
|
||||
border.width: 0
|
||||
}
|
||||
variations: StyleVariation {
|
||||
toolBar.background.color: "cornflowerblue"
|
||||
toolButton.background.color: "skyblue"
|
||||
toolButton.background.border.color: "aliceblue"
|
||||
}
|
||||
}
|
||||
//! [page]
|
||||
|
||||
@@ -273,15 +278,9 @@ ApplicationWindow {
|
||||
scrollBar {
|
||||
padding: 0
|
||||
background {
|
||||
// For scroll bars, we typically don't want a background, only a
|
||||
// draggable indicator and a groove.
|
||||
visible: false
|
||||
// Note: even if the background is hidden, its implicit size is still used to
|
||||
// determine the overall size of the scroll bar. So we set implicitHeight equal to
|
||||
// the height of the indicator, to make it appear on the side of, and not on top
|
||||
// of, the content area in a ScrollView. For a horizontal scroll bar, on the other
|
||||
// hand, the width is automatically set by the view to match its own width.
|
||||
// Set the groove size and color
|
||||
implicitHeight: 10
|
||||
color: "white"
|
||||
}
|
||||
indicator {
|
||||
radius: 255
|
||||
@@ -289,6 +288,7 @@ ApplicationWindow {
|
||||
// view to be the relative size of the view's content that is currently visible.
|
||||
implicitHeight: 10
|
||||
color: "#c0c0c0"
|
||||
// The indicator is so simple that it doesn't need a foreground
|
||||
foreground.visible: false
|
||||
}
|
||||
vertical {
|
||||
@@ -303,8 +303,8 @@ ApplicationWindow {
|
||||
|
||||
//! [scrollIndicator]
|
||||
scrollIndicator {
|
||||
// For scroll indicators, we typically don't want a background, only a
|
||||
// sliding indicator
|
||||
// A scroll indicator typically has no groove, just a sliding
|
||||
// indicator. So hide the background, since it represents the groove.
|
||||
background.visible: false
|
||||
indicator {
|
||||
// For horizontal indicators, we only set the height. The width is set by the
|
||||
@@ -633,6 +633,14 @@ ApplicationWindow {
|
||||
width: 200
|
||||
text: "TextField"
|
||||
}
|
||||
|
||||
Page {
|
||||
header: ToolBar {
|
||||
ToolButton {
|
||||
text: "<"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
// Copyright (C) 2026 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
import QtQuick
|
||||
import Qt.labs.StyleKit
|
||||
|
||||
ApplicationWindow {
|
||||
id: app
|
||||
width: 1024
|
||||
height: 800
|
||||
visible: true
|
||||
|
||||
StyleKit.style:
|
||||
//! [custom control style]
|
||||
// MyStyle.qml
|
||||
|
||||
Style {
|
||||
id: style
|
||||
readonly property int myControlType: 0
|
||||
CustomControl {
|
||||
controlType: style.myControlType
|
||||
background {
|
||||
implicitWidth: 120
|
||||
implicitHeight: 30
|
||||
radius: 0
|
||||
}
|
||||
hovered.background.color: "lightslategray"
|
||||
pressed.background.color: "skyblue"
|
||||
}
|
||||
}
|
||||
//! [custom control style]
|
||||
|
||||
//! [custom control]
|
||||
// Main.qml
|
||||
|
||||
component MyControl : Rectangle {
|
||||
StyleReader {
|
||||
id: styleReader
|
||||
controlType: StyleKit.style.myControlType
|
||||
hovered: hoverHandler.hovered
|
||||
pressed: tapHandler.pressed
|
||||
palette: app.palette
|
||||
}
|
||||
|
||||
HoverHandler { id: hoverHandler }
|
||||
TapHandler { id: tapHandler }
|
||||
|
||||
implicitWidth: styleReader.background.implicitWidth
|
||||
implicitHeight: styleReader.background.implicitHeight
|
||||
color: styleReader.background.color
|
||||
radius: styleReader.background.radius
|
||||
|
||||
Text {
|
||||
font: styleReader.font
|
||||
anchors.centerIn: parent
|
||||
text: "ok"
|
||||
}
|
||||
}
|
||||
//! [custom control]
|
||||
|
||||
// The rest of the file is not a part of the docs. It just implements a small
|
||||
// UI to allow testing the style from the command line using the 'qml' app.
|
||||
|
||||
ScrollView {
|
||||
anchors.fill: parent
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 10
|
||||
spacing: 10
|
||||
|
||||
MyControl {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
// Copyright (C) 2026 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
import QtQuick
|
||||
import Qt.labs.StyleKit
|
||||
|
||||
ApplicationWindow {
|
||||
id: app
|
||||
width: 1024
|
||||
height: 800
|
||||
visible: true
|
||||
|
||||
StyleKit.style: Style {
|
||||
|
||||
//! [transition]
|
||||
comboBox {
|
||||
background.color: "lightgray"
|
||||
hovered.background.color: "plum"
|
||||
|
||||
indicator.color: "white"
|
||||
hovered.indicator.color: "pink"
|
||||
hovered.indicator.border.width: 4
|
||||
|
||||
transition: Transition {
|
||||
StyleAnimation {
|
||||
animateBackgroundColors: true
|
||||
animateIndicatorColors: true
|
||||
animateIndicatorBorder: true
|
||||
easing.type: Easing.OutQuad
|
||||
duration: 500
|
||||
}
|
||||
}
|
||||
}
|
||||
//! [transition]
|
||||
|
||||
//! [custom transition]
|
||||
checkBox {
|
||||
background.color: "lightgray"
|
||||
hovered.background.color: "plum"
|
||||
|
||||
indicator.color: "white"
|
||||
hovered.indicator.color: "pink"
|
||||
hovered.indicator.border.width: 4
|
||||
|
||||
transition: Transition {
|
||||
ColorAnimation {
|
||||
properties: "background.color, background.border.color, background.image.color, background.shadow.color"
|
||||
+ ", indicator.color, indicator.border.color, indicator.image.color, indicator.shadow.color"
|
||||
easing.type: Easing.OutQuad
|
||||
duration: 500
|
||||
}
|
||||
NumberAnimation {
|
||||
properties: "indicator.border.width"
|
||||
easing.type: Easing.OutQuad
|
||||
duration: 500
|
||||
}
|
||||
}
|
||||
}
|
||||
//! [custom transition]
|
||||
|
||||
//! [mixed transition]
|
||||
slider {
|
||||
handle.color: "white"
|
||||
hovered.handle.color: "seagreen"
|
||||
hovered.handle.border.width: 8
|
||||
|
||||
transition: Transition {
|
||||
StyleAnimation {
|
||||
animateHandleColors: true
|
||||
easing.type: Easing.OutQuad
|
||||
duration: 500
|
||||
}
|
||||
NumberAnimation {
|
||||
properties: "handle.border.width"
|
||||
easing.type: Easing.OutBounce
|
||||
duration: 1000
|
||||
}
|
||||
}
|
||||
}
|
||||
//! [mixed transition]
|
||||
}
|
||||
|
||||
// The rest of the file is not a part of the docs. It just implements a small
|
||||
// UI to allow testing the style from the command line using the 'qml' app.
|
||||
|
||||
ScrollView {
|
||||
anchors.fill: parent
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 10
|
||||
spacing: 10
|
||||
|
||||
ComboBox {
|
||||
model: ["apple", "banana", "orange"]
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
text: "CheckBox"
|
||||
}
|
||||
|
||||
Slider {
|
||||
width: 200
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
// Copyright (C) 2026 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
import QtQuick
|
||||
import Qt.labs.StyleKit
|
||||
|
||||
ApplicationWindow {
|
||||
id: app
|
||||
width: 1024
|
||||
height: 800
|
||||
visible: true
|
||||
|
||||
StyleKit.style: Style {
|
||||
button.pressed.background.color: "magenta"
|
||||
button.hovered.text.bold: true
|
||||
}
|
||||
//! [custom control]
|
||||
// Main.qml
|
||||
|
||||
component CustomButton : Rectangle {
|
||||
StyleReader {
|
||||
id: styleReader
|
||||
controlType: StyleReader.Button
|
||||
hovered: hoverHandler.hovered
|
||||
pressed: tapHandler.pressed
|
||||
palette: app.palette
|
||||
}
|
||||
|
||||
implicitWidth: styleReader.background.implicitWidth
|
||||
implicitHeight: styleReader.background.implicitHeight
|
||||
color: styleReader.background.color
|
||||
radius: styleReader.background.radius
|
||||
|
||||
HoverHandler { id: hoverHandler }
|
||||
TapHandler { id: tapHandler }
|
||||
|
||||
Text {
|
||||
font: styleReader.font
|
||||
anchors.centerIn: parent
|
||||
text: "ok"
|
||||
}
|
||||
}
|
||||
//! [custom control]
|
||||
|
||||
// The rest of the file is not a part of the docs. It just implements a small
|
||||
// UI to allow testing the style from the command line using the 'qml' app.
|
||||
|
||||
ScrollView {
|
||||
anchors.fill: parent
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 10
|
||||
spacing: 10
|
||||
|
||||
CustomButton {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
@@ -9,6 +9,7 @@
|
||||
\ingroup qtquickcontrols-examples
|
||||
|
||||
\image qtlabsstylekit-example.webp
|
||||
{StyleKit demo showing buttons, checkboxes, sliders, and settings}
|
||||
|
||||
This example shows how to style applications with \l {Qt Labs StyleKit}{StyleKit}.
|
||||
It includes several styles that each demonstrate different aspects of styling:
|
||||
@@ -38,4 +39,7 @@
|
||||
\sa {Qt Labs StyleKit}, Style, Theme
|
||||
|
||||
\include examples-run.qdocinc
|
||||
|
||||
\note This example requires Qt Shader Tools, an optional library available
|
||||
through the Qt Maintenance Tool.
|
||||
*/
|
||||
|
||||
+1
-1
@@ -18,5 +18,5 @@
|
||||
|
||||
\snippet ReferenceFallbackStyle.qml 1
|
||||
|
||||
\sa {Style::fallbackStyle}{Style.fallbackStyle}, {qtlabsstylekit-property-resolution.html}{Property Resolution}
|
||||
\sa {Style::fallbackStyle}{Style.fallbackStyle}
|
||||
*/
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
|
||||
/*!
|
||||
\qmlmodule Qt.labs.StyleKit
|
||||
\techpreview
|
||||
\preliminary
|
||||
\title Qt Labs StyleKit QML Types
|
||||
\ingroup qmlmodules
|
||||
\brief Provides QML types for declarative styling of Qt Quick Controls.
|
||||
|
||||
@@ -113,7 +113,7 @@ BaseStyle {
|
||||
}
|
||||
|
||||
comboBox {
|
||||
text.alignment: Qt.AlignVCenter
|
||||
text.alignment: Qt.AlignVCenter | Qt.AlignLeft
|
||||
background.implicitWidth: 150
|
||||
indicator {
|
||||
color: __transparent
|
||||
@@ -204,7 +204,6 @@ BaseStyle {
|
||||
padding: 0
|
||||
background {
|
||||
implicitHeight: 10
|
||||
visible: false
|
||||
}
|
||||
indicator {
|
||||
implicitHeight: 10
|
||||
|
||||
@@ -22,7 +22,7 @@ RectangularShadow {
|
||||
topRightRadius: delegateStyle.topRightRadius
|
||||
bottomLeftRadius: delegateStyle.bottomLeftRadius
|
||||
bottomRightRadius: delegateStyle.bottomRightRadius
|
||||
visible: delegateStyle.shadow.visible
|
||||
visible: delegateStyle.visible && delegateStyle.shadow.visible
|
||||
offset: Qt.vector2d(
|
||||
delegateStyle.shadow.horizontalOffset,
|
||||
delegateStyle.shadow.verticalOffset)
|
||||
|
||||
+20
-2
@@ -73,8 +73,24 @@ bool QQStyleKitDelegateContainer::usingDefaultDelegate() const
|
||||
|
||||
void QQStyleKitDelegateContainer::updateImplicitSize()
|
||||
{
|
||||
setImplicitWidth(m_delegateInstance ? m_delegateInstance->implicitWidth() : 0);
|
||||
setImplicitHeight(m_delegateInstance ? m_delegateInstance->implicitHeight() : 0);
|
||||
qreal implicitWidth = 0;
|
||||
qreal implicitHeight = 0;
|
||||
|
||||
if (m_delegateInstance) {
|
||||
/* The delegate instance is expected to bind its implicit size to the
|
||||
* value from the style, but may override it if needed. */
|
||||
implicitWidth = m_delegateInstance->implicitWidth();
|
||||
implicitHeight = m_delegateInstance->implicitHeight();
|
||||
} else if (m_delegateProperties) {
|
||||
/* The delegate instance may not exist yet (e.g. because it is hidden),
|
||||
* but the container should still report the style's implicit size so
|
||||
* that it reserves the correct space in a layout. */
|
||||
implicitWidth = qMax(m_delegateProperties->minimumWidth(), m_delegateProperties->implicitWidth());
|
||||
implicitHeight = m_delegateProperties->implicitHeight();
|
||||
}
|
||||
|
||||
setImplicitWidth(implicitWidth);
|
||||
setImplicitHeight(implicitHeight);
|
||||
}
|
||||
|
||||
void QQStyleKitDelegateContainer::maybeCreateDelegate()
|
||||
@@ -244,6 +260,8 @@ void QQStyleKitDelegateContainer::componentComplete()
|
||||
maybeCreateShadow();
|
||||
}
|
||||
});
|
||||
|
||||
updateImplicitSize();
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
@@ -58,15 +58,12 @@ static qreal vAlignY(QQStyleKitLayoutItem *li, qreal containerY, qreal container
|
||||
const auto itemHeight = height(li, containerHeight);
|
||||
const auto vAlign = li->alignment() & Qt::AlignVertical_Mask;
|
||||
const auto margins = li->margins();
|
||||
switch (vAlign) {
|
||||
case Qt::AlignTop:
|
||||
if (vAlign & Qt::AlignTop)
|
||||
return containerY + margins.top();
|
||||
case Qt::AlignBottom:
|
||||
if (vAlign & Qt::AlignBottom)
|
||||
return containerY + containerHeight - itemHeight - margins.bottom();
|
||||
default: // AlignVCenter
|
||||
return containerY + margins.top()
|
||||
+ (containerHeight - margins.top() - margins.bottom() - itemHeight) / 2.0;
|
||||
}
|
||||
return containerY + margins.top()
|
||||
+ (containerHeight - margins.top() - margins.bottom() - itemHeight) / 2.0;
|
||||
}
|
||||
|
||||
QQStyleKitLayoutItem::QQStyleKitLayoutItem(QObject *parent)
|
||||
|
||||
@@ -104,7 +104,7 @@ QQStyleKitAttached::QQStyleKitAttached(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
connect(QGuiApplication::styleHints(), &QStyleHints::colorSchemeChanged, this, [this](){
|
||||
if (m_style)
|
||||
if (m_style && QString::compare(m_style->themeName(), "System"_L1, Qt::CaseInsensitive) == 0)
|
||||
m_style->recreateTheme();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,229 @@
|
||||
// Copyright (C) 2026 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
\qmltype StyleAnimation
|
||||
\inqmlmodule Qt.labs.StyleKit
|
||||
\inherits ParallelAnimation
|
||||
\brief A convenience type for animating style properties.
|
||||
|
||||
StyleAnimation is an \l [QtQuick]{Animation} that animates style properties
|
||||
when a control changes \l {ControlStateStyle}{state}. For example, setting
|
||||
\l animateBackgroundColors to \c true will animate all color properties of
|
||||
the \l {ControlStyle::}{background}, such as \l {DelegateStyle::color}{background.color},
|
||||
\l {BorderStyle::color}{background.border.color}, \l {ImageStyle::color}{background.image.color},
|
||||
and \l {ShadowStyle::color}{background.shadow.color}. It is used inside a
|
||||
\l {ControlStyle::}{transition}:
|
||||
|
||||
\snippet StyleAnimationSnippets.qml transition
|
||||
|
||||
StyleAnimation is just a convenience \l [QtQuick]{Animation} that handles listing the
|
||||
affected style properties automatically. The snippet above could also be written as:
|
||||
|
||||
\snippet StyleAnimationSnippets.qml custom transition
|
||||
|
||||
A StyleAnimation can also be used together with other animations:
|
||||
|
||||
\snippet StyleAnimationSnippets.qml mixed transition
|
||||
|
||||
\labs
|
||||
|
||||
\sa {ControlStyleProperties::transition}{ControlStyle.transition}, ControlStyle
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty EasingCurve StyleAnimation::easing
|
||||
|
||||
The easing curve applied to the animation.
|
||||
|
||||
\sa duration, PropertyAnimation
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty int StyleAnimation::duration
|
||||
|
||||
The duration in milliseconds of the animation.
|
||||
|
||||
\sa easing, PropertyAnimation
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty bool StyleAnimation::animateColors
|
||||
|
||||
When \c true, animates all color properties across all delegates. This is a
|
||||
shorthand for enabling \l animateBackgroundColors, \l animateHandleColors,
|
||||
and \l animateIndicatorColors at once.
|
||||
|
||||
Note that \l ColorAnimation also animates all color properties that
|
||||
change during a transition when \l {PropertyAnimation::}{property} and
|
||||
\l {PropertyAnimation::}{properties} are both left unset. This makes it a
|
||||
an alternative to StyleAnimation when only colors need to be animated.
|
||||
|
||||
\sa animateBackgroundColors, animateHandleColors, animateIndicatorColors
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty bool StyleAnimation::animateControlGeometry
|
||||
|
||||
When \c true, animates the control's geometry properties, such as
|
||||
\l {ControlStyleProperties::spacing}{spacing} and
|
||||
\l {ControlStyleProperties::padding}{padding}.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty bool StyleAnimation::animateBackgroundColors
|
||||
|
||||
When \c true, animates the color properties of the
|
||||
\l {ControlStyleProperties::}{background} delegate,
|
||||
including \l {BorderStyle::color}{border} and \l {ShadowStyle::color}{shadow} colors.
|
||||
|
||||
\sa animateColors, animateBackgroundGeometry
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty bool StyleAnimation::animateBackgroundGeometry
|
||||
|
||||
When \c true, animates the geometry properties of the
|
||||
\l {ControlStyleProperties::}{background} delegate,
|
||||
such as \l {DelegateStyle::implicitWidth}{implicit size}
|
||||
and \l {DelegateStyle::}{margins}.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty bool StyleAnimation::animateBackgroundRadii
|
||||
|
||||
When \c true, animates the corner \l {DelegateStyle::radius}{radii} of the
|
||||
\l {ControlStyleProperties::}{background} delegate.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty bool StyleAnimation::animateBackgroundBorder
|
||||
|
||||
When \c true, animates the \l {BorderStyle::width}{border width} of the
|
||||
\l {ControlStyleProperties::}{background} delegate.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty bool StyleAnimation::animateBackgroundShadow
|
||||
|
||||
When \c true, animates the shadow properties of the
|
||||
\l {ControlStyleProperties::}{background} delegate,
|
||||
such as \l {ShadowStyle::verticalOffset}{vertical offset},
|
||||
\l {ShadowStyle::horizontalOffset}{horizontal offset},
|
||||
\l {ShadowStyle::scale}{scale}, and \l {ShadowStyle::blur}{blur}.
|
||||
The shadow \l {ShadowStyle::color}{color} is animated by \l animateHandleColors.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty bool StyleAnimation::animateBackgroundScaleAndRotation
|
||||
|
||||
When \c true, animates the and rotation of the
|
||||
\l {ControlStyleProperties::}{background} delegate.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty bool StyleAnimation::animateHandleColors
|
||||
|
||||
When \c true, animates the color properties of the
|
||||
\l {ControlStyleProperties::}{handle} delegate and its \l {HandleStyle}{sub-handles},
|
||||
including \l {BorderStyle::color}{border} and \l {ShadowStyle::color}{shadow} colors.
|
||||
|
||||
\sa animateColors, animateHandleGeometry
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty bool StyleAnimation::animateHandleGeometry
|
||||
|
||||
When \c true, animates the geometry properties of the
|
||||
\l {ControlStyleProperties::}{handle} delegate and its \l {HandleStyle}{sub-handles},
|
||||
such as \l {DelegateStyle::implicitWidth}{implicit size} and
|
||||
\l {DelegateStyle::}{margins}.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty bool StyleAnimation::animateHandleRadii
|
||||
|
||||
When \c true, animates the corner \l {DelegateStyle::radius}{radii} of the
|
||||
\l {ControlStyleProperties::}{handle} delegate and its \l {HandleStyle}{sub-handles}.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty bool StyleAnimation::animateHandleBorder
|
||||
|
||||
When \c true, animates the \l {BorderStyle::width}{border width} of the
|
||||
\l {ControlStyleProperties::}{handle} delegate and its \l {HandleStyle}{sub-handles}.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty bool StyleAnimation::animateHandleShadow
|
||||
|
||||
When \c true, animates the shadow properties of the
|
||||
\l {ControlStyleProperties::}{handle} delegate and its \l {HandleStyle}{sub-handles},
|
||||
such as \l {ShadowStyle::verticalOffset}{vertical offset},
|
||||
\l {ShadowStyle::horizontalOffset}{horizontal offset},
|
||||
\l {ShadowStyle::scale}{scale}, and \l {ShadowStyle::blur}{blur}.
|
||||
The shadow \l {ShadowStyle::color}{color} is animated by \l animateHandleColors.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty bool StyleAnimation::animateHandleScaleAndRotation
|
||||
|
||||
When \c true, animates the \l {DelegateStyle::}{scale} and \l {DelegateStyle::}{rotation} of the
|
||||
\l {ControlStyleProperties::}{handle} delegate and its \l {HandleStyle}{sub-handles}.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty bool StyleAnimation::animateIndicatorColors
|
||||
|
||||
When \c true, animates the color properties of the
|
||||
\l {ControlStyleProperties::}{indicator} delegate and its \l {IndicatorStyle}{sub-indicators},
|
||||
including \l {BorderStyle::color}{border} and \l {ShadowStyle::color}{shadow} colors.
|
||||
|
||||
\sa animateColors, animateIndicatorGeometry
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty bool StyleAnimation::animateIndicatorGeometry
|
||||
|
||||
When \c true, animates the geometry properties of the
|
||||
\l {ControlStyleProperties::}{indicator} delegate and its \l {IndicatorStyle}{sub-indicators},
|
||||
such as \l {DelegateStyle::implicitWidth}{implicit size} and \l {DelegateStyle::}{margins}.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty bool StyleAnimation::animateIndicatorRadii
|
||||
|
||||
When \c true, animates the corner \l {DelegateStyle::radius}{radii} of the
|
||||
\l {ControlStyleProperties::}{indicator} delegate and its \l {IndicatorStyle}{sub-indicators}.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty bool StyleAnimation::animateIndicatorBorder
|
||||
|
||||
When \c true, animates the \l {BorderStyle::width}{border width} of the
|
||||
\l {ControlStyleProperties::}{indicator} delegate and its \l {IndicatorStyle}{sub-indicators}.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty bool StyleAnimation::animateIndicatorShadow
|
||||
|
||||
When \c true, animates the shadow properties of the
|
||||
\l {ControlStyleProperties::}{indicator} delegate and its \l {IndicatorStyle}{sub-indicators},
|
||||
such as \l {ShadowStyle::verticalOffset}{vertical offset},
|
||||
\l {ShadowStyle::horizontalOffset}{horizontal offset},
|
||||
\l {ShadowStyle::scale}{scale}, and \l {ShadowStyle::blur}{blur}.
|
||||
The shadow \l {ShadowStyle::color}{color} is animated by \l animateHandleColors.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty bool StyleAnimation::animateIndicatorScaleAndRotation
|
||||
|
||||
When \c true, animates the scale and rotation of the
|
||||
\l {ControlStyleProperties::}{indicator} delegate and its \l {IndicatorStyle}{sub-indicators}.
|
||||
*/
|
||||
|
||||
QT_END_NAMESPACE
|
||||
+32
-130
@@ -9,131 +9,28 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
// ************* ControlStateStyle ****************
|
||||
// ************* ControlStyleProperties ****************
|
||||
|
||||
/*!
|
||||
\qmltype ControlStateStyle
|
||||
\qmltype ControlStyleProperties
|
||||
\inqmlmodule Qt.labs.StyleKit
|
||||
\brief Defines the style for a control in a given state.
|
||||
\brief Defines the stylable properties for a control.
|
||||
|
||||
A ControlStateStyle contains the properties that can be styled for each
|
||||
state a control can be in. This includes the visual building blocks
|
||||
\l background, \l indicator, \l handle, and \l text, along with
|
||||
layout properties such as \l padding and \l spacing, and more.
|
||||
ControlStyleProperties defines the stylable properties for a
|
||||
control: the visual building blocks \l background, \l indicator, \l handle,
|
||||
and \l text, as well as layout properties like \l padding, \l spacing,
|
||||
and \l transition.
|
||||
|
||||
A \l ControlStyle inherits ControlStateStyle, since it represents the
|
||||
\e normal state — that is, properties set directly on a
|
||||
ControlStyle describe how the control looks when no other state
|
||||
is active. State-specific overrides are set through nested states
|
||||
such as \l pressed, \l hovered, and \l checked, and can be
|
||||
animated by a \l transition.
|
||||
|
||||
Nested states are not mutually exclusive. Multiple states can be active at
|
||||
the same time — for example, a button can be both hovered and
|
||||
pressed simultaneously. When several states are active, all matching
|
||||
state overrides are applied. If the same property is set in multiple
|
||||
active states, conflicts are resolved using the following priority
|
||||
order: \l pressed, \l hovered, \l highlighted, \l focused,
|
||||
\l checked, \l vertical. So for example \c {pressed.background.color}
|
||||
wins over \c {checked.background.color} if the control is both
|
||||
\l pressed and \l checked.
|
||||
|
||||
The \l disabled state is an exception: a disabled control cannot
|
||||
be interacted with, so the \l pressed, \l hovered, \l highlighted,
|
||||
and \l focused states will not apply. However, \l disabled can
|
||||
still be combined with states like \l checked and \l vertical.
|
||||
|
||||
The more deeply nested a state is, the more qualified it is.
|
||||
For example, \c {hovered.pressed.background.color} takes precedence over
|
||||
\c {hovered.background.color} when both \l hovered and \l pressed are
|
||||
active. The nesting order does not matter:
|
||||
\c {hovered.pressed} and \c {pressed.hovered} are equivalent.
|
||||
However, if both forms are used at the same time, which one wins is
|
||||
undefined.
|
||||
|
||||
Deeper nesting of states can also be used to resolve conflicts. If the same property
|
||||
is set in both \l hovered and \l checked, the priority order means
|
||||
the \l hovered value wins. If you would rather have the checked value win, or
|
||||
use an altogether different value in that situation, you can override
|
||||
the property in \c {hovered.checked}, which then takes precedence over both.
|
||||
|
||||
The following snippet shows how to style a button differently
|
||||
depending on its state:
|
||||
|
||||
\snippet ControlStateStyle_states.qml States
|
||||
The style properties are accessed through inherited types such as
|
||||
\l ControlStyle and \l StyleReader.
|
||||
|
||||
\labs
|
||||
|
||||
\sa ControlStyle, DelegateStyle,
|
||||
{qtlabsstylekit-fallbackstyle.html}{FallbackStyle Reference}
|
||||
\sa ControlStyle, StyleReader, ControlStateStyle, DelegateStyle
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty ControlStateStyle ControlStateStyle::pressed
|
||||
|
||||
Style overrides applied when the control is pressed (e.g. the
|
||||
user is holding down a mouse button on it).
|
||||
|
||||
\sa hovered, highlighted, focused, checked, vertical, disabled
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty ControlStateStyle ControlStateStyle::hovered
|
||||
|
||||
Style overrides applied when the mouse cursor is over the control.
|
||||
|
||||
\sa pressed, highlighted, focused, checked, vertical, disabled
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty ControlStateStyle ControlStateStyle::highlighted
|
||||
|
||||
Style overrides applied when the control is highlighted. A control
|
||||
is typically highlighted in order to draw the user's attention towards it.
|
||||
|
||||
\sa pressed, hovered, focused, checked, vertical, disabled
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty ControlStateStyle ControlStateStyle::focused
|
||||
|
||||
Style overrides applied when the control has input focus.
|
||||
|
||||
\sa pressed, hovered, highlighted, checked, vertical, disabled
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty ControlStateStyle ControlStateStyle::checked
|
||||
|
||||
Style overrides applied when the control is in a checked or
|
||||
toggled-on state (e.g. a checked \l CheckBox or a toggled
|
||||
\l Button).
|
||||
|
||||
\sa pressed, hovered, highlighted, focused, vertical, disabled
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty ControlStateStyle ControlStateStyle::vertical
|
||||
|
||||
Style overrides applied when the control has a vertical
|
||||
orientation (e.g. a vertical \l Slider or \l ScrollBar).
|
||||
|
||||
\sa pressed, hovered, highlighted, focused, checked, disabled
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty ControlStateStyle ControlStateStyle::disabled
|
||||
|
||||
Style overrides applied when the control is disabled.
|
||||
|
||||
A disabled control cannot be interacted with, so \l pressed,
|
||||
\l hovered, \l highlighted, and \l focused will not be applied
|
||||
at the same time as disabled.
|
||||
|
||||
\sa pressed, hovered, highlighted, focused, checked, vertical
|
||||
*/
|
||||
/*!
|
||||
\qmlproperty DelegateStyle ControlStateStyle::background
|
||||
\qmlproperty DelegateStyle ControlStyleProperties::background
|
||||
|
||||
Grouped property for styling the background of a control.
|
||||
|
||||
@@ -153,7 +50,7 @@ QT_BEGIN_NAMESPACE
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty real ControlStateStyle::bottomPadding
|
||||
\qmlproperty real ControlStyleProperties::bottomPadding
|
||||
|
||||
The \l [QtQuickControls]{Control Layout}{bottom padding}
|
||||
of the control. If not set, falls back to \l padding.
|
||||
@@ -162,7 +59,7 @@ QT_BEGIN_NAMESPACE
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty HandleStyle ControlStateStyle::handle
|
||||
\qmlproperty HandleStyle ControlStyleProperties::handle
|
||||
|
||||
Grouped property for styling the handle of a control.
|
||||
|
||||
@@ -175,7 +72,7 @@ QT_BEGIN_NAMESPACE
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty IndicatorStyle ControlStateStyle::indicator
|
||||
\qmlproperty IndicatorStyle ControlStyleProperties::indicator
|
||||
|
||||
Grouped property for styling the indicator of a control. For a
|
||||
\l {AbstractStylableControls::}{checkBox}, the indicator is the
|
||||
@@ -187,7 +84,7 @@ QT_BEGIN_NAMESPACE
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty real ControlStateStyle::leftPadding
|
||||
\qmlproperty real ControlStyleProperties::leftPadding
|
||||
|
||||
The \l [QtQuickControls]{Control Layout}{left padding} of the control. If not set, falls back to
|
||||
\l padding.
|
||||
@@ -196,7 +93,7 @@ QT_BEGIN_NAMESPACE
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty real ControlStateStyle::padding
|
||||
\qmlproperty real ControlStyleProperties::padding
|
||||
|
||||
The uniform spacing between the
|
||||
\l [QtQuickControls]{Control Layout}{control's content area and the
|
||||
@@ -208,7 +105,7 @@ QT_BEGIN_NAMESPACE
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty real ControlStateStyle::rightPadding
|
||||
\qmlproperty real ControlStyleProperties::rightPadding
|
||||
|
||||
The \l [QtQuickControls]{Control Layout}{right padding} of the control.
|
||||
If not set, falls back to \l padding.
|
||||
@@ -217,20 +114,20 @@ QT_BEGIN_NAMESPACE
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty real ControlStateStyle::spacing
|
||||
\qmlproperty real ControlStyleProperties::spacing
|
||||
|
||||
The spacing between visual elements inside the control, for example
|
||||
between an indicator and a label.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty TextStyle ControlStateStyle::text
|
||||
\qmlproperty TextStyle ControlStyleProperties::text
|
||||
|
||||
Grouped property for styling the text label of a control.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty real ControlStateStyle::topPadding
|
||||
\qmlproperty real ControlStyleProperties::topPadding
|
||||
|
||||
The \l [QtQuickControls]{Control Layout}{top padding}
|
||||
of the control. If not set, falls back to \l padding.
|
||||
@@ -239,10 +136,11 @@ QT_BEGIN_NAMESPACE
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty Transition ControlStateStyle::transition
|
||||
\qmlproperty Transition ControlStyleProperties::transition
|
||||
|
||||
A \l [QtQuick]{Transition} used to animate style properties when the
|
||||
control enters a new state, such as \l hovered or \l pressed. If set
|
||||
control enters a new state, such as \l {ControlStateStyle::}{hovered}
|
||||
or \l {ControlStateStyle::}{pressed}. If set
|
||||
to \c null (the default), property changes are applied immediately
|
||||
without animation.
|
||||
|
||||
@@ -269,8 +167,8 @@ QT_BEGIN_NAMESPACE
|
||||
\brief Defines the visual appearance of an element within a control.
|
||||
|
||||
DelegateStyle describes the visual appearance of a visual element
|
||||
within a \l ControlStyle, such as its \l {ControlStateStyle::}{background},
|
||||
\l {ControlStateStyle::}{indicator}, or a sub-element like
|
||||
within a \l ControlStyle, such as its \l {ControlStyleProperties::}{background},
|
||||
\l {ControlStyleProperties::}{indicator}, or a sub-element like
|
||||
\l {IndicatorStyle::foreground}{indicator.foreground}.
|
||||
It provides properties for controlling
|
||||
\l {DelegateStyle::implicitWidth}{size},
|
||||
@@ -376,7 +274,8 @@ QT_BEGIN_NAMESPACE
|
||||
\l {Qt Quick Controls}{Qt Quick Control}.
|
||||
|
||||
The default value is \c null, in which case \l StyledItem is used
|
||||
for rendering instead.
|
||||
for rendering instead. If you want to hide the delegate altogether
|
||||
(and prevent if from being created), set \l visible to \c false.
|
||||
|
||||
The delegate needs to define the following required properties:
|
||||
\qml
|
||||
@@ -400,7 +299,7 @@ QT_BEGIN_NAMESPACE
|
||||
\note If a DelegateStyle has a \l {shadow}{drop shadow} defined, it will be
|
||||
drawn separately by a \l {ShadowStyle::delegate}{shadow delegate.}
|
||||
|
||||
\sa data, StyledItem
|
||||
\sa data, visible, StyledItem
|
||||
*/
|
||||
|
||||
/*!
|
||||
@@ -550,6 +449,9 @@ QT_BEGIN_NAMESPACE
|
||||
should not draw a background, such as \l [QtQuickControls]{CheckBox},
|
||||
\l [QtQuickControls]{RadioButton}, and \l [QtQuickControls]{Slider}.
|
||||
|
||||
When \c visible is \c false, the \l delegate will not be created. If you need
|
||||
a hidden delegate to be created, consider setting \l opacity to \c 0 instead.
|
||||
|
||||
\sa opacity
|
||||
*/
|
||||
|
||||
@@ -866,7 +768,7 @@ QT_BEGIN_NAMESPACE
|
||||
\l {TextStyle::}{italic}, and
|
||||
\l {TextStyle::pointSize}{font size}.
|
||||
|
||||
It is available as the \l {ControlStateStyle::text}{text}
|
||||
It is available as the \l {ControlStyleProperties::text}{text}
|
||||
grouped property on every \l ControlStateStyle.
|
||||
|
||||
\labs
|
||||
|
||||
+5
-4
@@ -148,7 +148,7 @@ signals:
|
||||
|
||||
// ************* QQStyleKitBorderProperties ****************
|
||||
|
||||
class QQStyleKitBorderProperties : public QQStyleKitPropertyGroup
|
||||
class Q_LABSSTYLEKIT_EXPORT QQStyleKitBorderProperties : public QQStyleKitPropertyGroup
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(qreal width READ width WRITE setWidth NOTIFY widthChanged FINAL)
|
||||
@@ -546,7 +546,7 @@ signals:
|
||||
* only be read), and if so, offer a storage for storing those values. That storage is typically
|
||||
* a map that stores _only_ the properties that are written to, and nothing else.
|
||||
*/
|
||||
class QQStyleKitControlProperties : public QQStyleKitPropertyGroup
|
||||
class Q_LABSSTYLEKIT_EXPORT QQStyleKitControlProperties : public QQStyleKitPropertyGroup
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing NOTIFY spacingChanged FINAL)
|
||||
@@ -560,8 +560,9 @@ class QQStyleKitControlProperties : public QQStyleKitPropertyGroup
|
||||
Q_PROPERTY(QQStyleKitIndicatorWithSubTypes *indicator READ indicator NOTIFY indicatorChanged FINAL)
|
||||
Q_PROPERTY(QQStyleKitTextProperties *text READ text NOTIFY textChanged FINAL)
|
||||
Q_PROPERTY(QQuickTransition *transition READ transition WRITE setTransition NOTIFY transitionChanged FINAL)
|
||||
// This type is merged with ControlState, from a QML API point of view
|
||||
QML_ANONYMOUS
|
||||
|
||||
QML_UNCREATABLE("This component can only be instantiated by StyleKit")
|
||||
QML_NAMED_ELEMENT(ControlStyleProperties)
|
||||
|
||||
public:
|
||||
QQStyleKitControlProperties(QQSK::PropertyGroup group, QObject *parent = nullptr);
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
#include "qqstylekitcontrols_p.h"
|
||||
#include "qqstylekitcontrol_p.h"
|
||||
#include "qqstylekitvariation_p.h"
|
||||
#include "qqstylekitcustomcontrol_p.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
@@ -63,7 +62,7 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
\snippet ControlsSnippets.qml abstractButton
|
||||
|
||||
\sa {qtlabsstylekit-controls.html}{Control Types}
|
||||
\sa {Qt Labs StyleKit}{Control Types}
|
||||
*/
|
||||
|
||||
/*!
|
||||
@@ -174,6 +173,13 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
Unset properties fall back to \l pane.
|
||||
|
||||
Note that the \l [QtQuickControls]{Page::header}{header} and
|
||||
\l [QtQuickControls]{Page::footer}{footer} of a \l [QtQuickControls]{Page} are
|
||||
typically set by the application to a \l [QtQuickControls]{ToolBar} or
|
||||
\l [QtQuickControls]{TabBar}, and those controls are styled separately.
|
||||
To give a \l [QtQuickControls]{ToolBar} alternative styling when used inside
|
||||
a \l [QtQuickControls]{Page}, use a \l StyleVariation:
|
||||
|
||||
\snippet ControlsSnippets.qml page
|
||||
*/
|
||||
|
||||
@@ -229,8 +235,8 @@ QT_BEGIN_NAMESPACE
|
||||
\qmlproperty ControlStyle AbstractStylableControls::scrollBar
|
||||
|
||||
Grouped property for styling \l [QtQuickControls]{ScrollBar}.
|
||||
For a scroll bar, the groove is styled through the indicator, while the handle is
|
||||
styled through the indicator's foreground.
|
||||
The groove is styled through \l {ControlStyleProperties::}{background}, and the
|
||||
handle through \l {ControlStyleProperties::}{indicator}.
|
||||
|
||||
Unset properties fall back to \l control.
|
||||
|
||||
@@ -241,6 +247,8 @@ QT_BEGIN_NAMESPACE
|
||||
\qmlproperty ControlStyle AbstractStylableControls::scrollIndicator
|
||||
|
||||
Grouped property for styling \l [QtQuickControls]{ScrollIndicator}.
|
||||
The groove is styled through \l {ControlStyleProperties::}{background}, and the
|
||||
handle through \l {ControlStyleProperties::}{indicator}.
|
||||
|
||||
Unset properties fall back to \l control.
|
||||
|
||||
@@ -407,17 +415,6 @@ QQStyleKitControl* QQStyleKitControls::getControl(QQStyleKitExtendableControlTyp
|
||||
return m_controls[controlType];
|
||||
}
|
||||
|
||||
|
||||
QList<QQStyleKitVariation *> QQStyleKitControls::variations() const
|
||||
{
|
||||
QList<QQStyleKitVariation *> list;
|
||||
for (auto *obj : children()) {
|
||||
if (auto *variation = qobject_cast<QQStyleKitVariation *>(obj))
|
||||
list.append(variation);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
#define IMPLEMENT_ACCESSORS(NAME, TYPE) \
|
||||
QQStyleKitControl *QQStyleKitControls::NAME() const \
|
||||
{ \
|
||||
|
||||
@@ -109,8 +109,6 @@ public:
|
||||
|
||||
Q_INVOKABLE QQStyleKitControl *getControl(QQStyleKitExtendableControlType controlType) const;
|
||||
|
||||
QList<QQStyleKitVariation *> variations() const;
|
||||
|
||||
QQmlListProperty<QObject> data();
|
||||
const QList<QObject *> children() const;
|
||||
|
||||
|
||||
@@ -6,6 +6,129 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
// ************* ControlStateStyle ****************
|
||||
|
||||
/*!
|
||||
\qmltype ControlStateStyle
|
||||
\inqmlmodule Qt.labs.StyleKit
|
||||
\inherits ControlStyleProperties
|
||||
\brief Describes the style of a control in a given state.
|
||||
|
||||
ControlStateStyle describes the style of a control in a particular state.
|
||||
A \l ControlStyle inherits ControlStateStyle, since it represents the
|
||||
\e normal state — properties set directly on a \l ControlStyle describe
|
||||
how the control looks when no other state is active. State-specific
|
||||
overrides are then set through nested states such as \l pressed,
|
||||
\l hovered, and \l checked.
|
||||
|
||||
Nested states are not mutually exclusive. Multiple states can be active at
|
||||
the same time — for example, a button can be both hovered and
|
||||
pressed simultaneously. When several states are active, all matching
|
||||
state overrides are applied. If the same property is set in multiple
|
||||
active states, conflicts are resolved using the following priority
|
||||
order: \l pressed, \l hovered, \l highlighted, \l focused,
|
||||
\l checked, \l vertical. So for example \c {pressed.background.color}
|
||||
wins over \c {checked.background.color} if the control is both
|
||||
\l pressed and \l checked.
|
||||
|
||||
The \l disabled state is an exception: a disabled control cannot
|
||||
be interacted with, so the \l pressed, \l hovered, \l highlighted,
|
||||
and \l focused states will not apply. However, \l disabled can
|
||||
still be combined with states like \l checked and \l vertical.
|
||||
|
||||
The more deeply nested a state is, the more qualified it is.
|
||||
For example, \c {hovered.pressed.background.color} takes precedence over
|
||||
\c {hovered.background.color} when both \l hovered and \l pressed are
|
||||
active. The nesting order does not matter:
|
||||
\c {hovered.pressed} and \c {pressed.hovered} are equivalent.
|
||||
However, if both forms are used at the same time, which one wins is
|
||||
undefined.
|
||||
|
||||
Deeper nesting of states can also be used to resolve conflicts. If the same property
|
||||
is set in both \l hovered and \l checked, the priority order means
|
||||
the \l hovered value wins. If you would rather have the checked value win, or
|
||||
use an altogether different value in that situation, you can override
|
||||
the property in \c {hovered.checked}, which then takes precedence over both.
|
||||
|
||||
The following snippet shows how to style a button differently
|
||||
depending on its state:
|
||||
|
||||
\snippet ControlStateStyle_states.qml States
|
||||
|
||||
\labs
|
||||
|
||||
\sa ControlStyle, DelegateStyle,
|
||||
{qtlabsstylekit-fallbackstyle.html}{FallbackStyle Reference}
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty ControlStateStyle ControlStateStyle::pressed
|
||||
|
||||
Style overrides applied when the control is \l {StyleReader::}{pressed}.
|
||||
|
||||
\sa hovered, highlighted, focused, checked, vertical, disabled,
|
||||
{StyleReader::pressed}{StyleReader.pressed}
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty ControlStateStyle ControlStateStyle::hovered
|
||||
|
||||
Style overrides applied when the control is \l {StyleReader::}{hovered}.
|
||||
|
||||
\sa pressed, highlighted, focused, checked, vertical, disabled,
|
||||
{StyleReader::hovered}{StyleReader.hovered}
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty ControlStateStyle ControlStateStyle::highlighted
|
||||
|
||||
Style overrides applied when the control is \l {StyleReader::}{highlighted}.
|
||||
|
||||
\sa pressed, hovered, focused, checked, vertical, disabled,
|
||||
{StyleReader::highlighted}{StyleReader.highlighted}
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty ControlStateStyle ControlStateStyle::focused
|
||||
|
||||
Style overrides applied when the control is \l {StyleReader::}{focused}.
|
||||
|
||||
\sa pressed, hovered, highlighted, checked, vertical, disabled,
|
||||
{StyleReader::focused}{StyleReader.focused}
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty ControlStateStyle ControlStateStyle::checked
|
||||
|
||||
Style overrides applied when the control is \l {StyleReader::}{checked}.
|
||||
|
||||
\sa pressed, hovered, highlighted, focused, vertical, disabled,
|
||||
{StyleReader::checked}{StyleReader.checked}
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty ControlStateStyle ControlStateStyle::vertical
|
||||
|
||||
Style overrides applied when the control is \l {StyleReader::}{vertical}
|
||||
(for example, a vertical \l Slider or \l ScrollBar).
|
||||
|
||||
\sa pressed, hovered, highlighted, focused, checked, disabled,
|
||||
{StyleReader::vertical}{StyleReader.vertical}
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty ControlStateStyle ControlStateStyle::disabled
|
||||
|
||||
Style overrides applied when the control is \l {StyleReader::}{disabled}.
|
||||
|
||||
A disabled control cannot be interacted with, so \l pressed,
|
||||
\l hovered, \l highlighted, and \l focused will not be applied
|
||||
at the same time as disabled.
|
||||
|
||||
\sa pressed, hovered, highlighted, focused, checked, vertical,
|
||||
{StyleReader::enabled}{StyleReader.enabled}
|
||||
*/
|
||||
|
||||
QQStyleKitControlState::QQStyleKitControlState(QObject *parent)
|
||||
: QQStyleKitControlProperties(QQSK::PropertyGroup::Control, parent)
|
||||
{
|
||||
|
||||
+40
-1
@@ -9,13 +9,52 @@ QT_BEGIN_NAMESPACE
|
||||
\qmltype CustomControl
|
||||
\inqmlmodule Qt.labs.StyleKit
|
||||
\inherits ControlStyle
|
||||
\brief Defines styling for a custom control type.
|
||||
\brief Defines styling for a custom (non-built-in) control.
|
||||
|
||||
CustomControl allows you to define and style controls that are not part of
|
||||
\l {Qt Quick Controls}. This is convenient if you have additional controls
|
||||
or components that should be styled according to the active \l Style and \l Theme.
|
||||
|
||||
Like the built-in control types (such as
|
||||
\l {AbstractStylableControls::}{abstractButton},
|
||||
\l {AbstractStylableControls::}{pane}, and
|
||||
\l {AbstractStylableControls::}{slider}), CustomControl inherits
|
||||
\l ControlStyle. Unlike built-in types, which are implicitly connected to
|
||||
their control type, a CustomControl requires \l controlType to be set
|
||||
explicitly. Apart from that, they work exactly the same way.
|
||||
|
||||
A \l Style or \l Theme can define as many custom controls as needed, and a
|
||||
CustomControl in a Theme can have the same \l controlType as one in the \l Style.
|
||||
That is no different from, for example, a \l {AbstractStylableControls::}{slider}
|
||||
being styled by both the \l Style and the \l Theme. The fallback logic is the same.
|
||||
|
||||
Any style properties not set on a CustomControl fall back to those set
|
||||
on a \l {AbstractStylableControls::}{control}.
|
||||
|
||||
The following snippet shows how to define styling for a custom control:
|
||||
|
||||
\snippet CustomControlSnippets.qml custom control style
|
||||
|
||||
And the following snippet shows an example on how to implement a custom
|
||||
control that uses it:
|
||||
|
||||
\snippet CustomControlSnippets.qml custom control
|
||||
|
||||
\labs
|
||||
|
||||
\sa StyleReader, ControlStyle, Style
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty int CustomControl::controlType
|
||||
|
||||
A unique integer identifying this custom control type. Set the same value
|
||||
on the \l {StyleReader::controlType}{StyleReader.controlType} in your
|
||||
custom control implementation to connect it to this style definition.
|
||||
|
||||
Custom control types must be in the range \c 0 to \c 100000.
|
||||
|
||||
\sa {StyleReader::controlType}{StyleReader.controlType}
|
||||
*/
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "qqstylekitcontrols_p.h"
|
||||
#include "qqstylekitstyle_p.h"
|
||||
#include "qqstylekittheme_p.h"
|
||||
#include "qqstylekitvariation_p.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
@@ -27,17 +28,18 @@ QT_BEGIN_NAMESPACE
|
||||
To start tracing, assign the \l{The id Attribute}{id} of a \l Control to the \l control property:
|
||||
|
||||
\code
|
||||
StyleKit.debug.control = myButton
|
||||
StyleKit.debug.control: myButton
|
||||
\endcode
|
||||
|
||||
Each resolved property is printed as a single line showing where the value
|
||||
came from and what it resolved to:
|
||||
|
||||
\code
|
||||
[read] StyleReader[Normal].button.background.color -> button[Normal] = #ff0000
|
||||
[read] StyleReader[Hovered].button.background.color -> MyStyle.Theme(Dark).button[Hovered] = #ff0000
|
||||
\endcode
|
||||
|
||||
Use \l filter to limit the output to properties of interest.
|
||||
Tracing the property reads of a StyleReader can produce a large amount of output. Use \l filter to
|
||||
limit the output to properties of interest.
|
||||
|
||||
\labs
|
||||
|
||||
@@ -47,7 +49,7 @@ QT_BEGIN_NAMESPACE
|
||||
/*!
|
||||
\qmlproperty Item StyleKitDebug::control
|
||||
|
||||
The \l{The id Attribute}{id} of the \l Control to trace.
|
||||
The \l{The id Attribute}{id} of the \l Control or \l StyleReader to trace.
|
||||
|
||||
When set, StyleKit logs all style property reads
|
||||
for this item to the debug output. Set to \c null to stop tracing.
|
||||
@@ -61,10 +63,21 @@ QT_BEGIN_NAMESPACE
|
||||
A regular expression used to filter the debug output. Only lines matching
|
||||
the pattern are printed. By default, all output is shown.
|
||||
|
||||
For example, to show only reads of the background color:
|
||||
For example, to only trace the background color:
|
||||
|
||||
\code
|
||||
StyleKit.debug.filter = "background.color"
|
||||
StyleKit.debug.filter: "background.color"
|
||||
\endcode
|
||||
|
||||
To trace all background colors, including properties
|
||||
such as \l {DelegateStyle::color}{background.color},
|
||||
\l {BorderStyle::color}{background.border.color},
|
||||
\l {ImageStyle::color}{background.image.color},
|
||||
and \l {ShadowStyle::color}{background.shadow.color},
|
||||
use a regular expression:
|
||||
|
||||
\code
|
||||
StyleKit.debug.filter: "background.*color"
|
||||
\endcode
|
||||
|
||||
\sa control
|
||||
@@ -85,6 +98,9 @@ QString QQStyleKitDebug::enumToString(EnumType enumValue)
|
||||
}
|
||||
|
||||
QString QQStyleKitDebug::objectName(const QObject *obj) {
|
||||
if (!obj->objectName().isEmpty())
|
||||
return obj->objectName();
|
||||
|
||||
QString str = QString::fromLatin1(obj->metaObject()->className());
|
||||
int idx = str.indexOf("_QMLTYPE"_L1);
|
||||
if (idx != -1)
|
||||
@@ -94,9 +110,7 @@ QString QQStyleKitDebug::objectName(const QObject *obj) {
|
||||
if (str.startsWith(prefix))
|
||||
str = str.mid(prefix.length());
|
||||
}
|
||||
const QString name = obj->objectName();
|
||||
if (!name.isEmpty())
|
||||
str = str + "("_L1 + name + ")"_L1;
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
@@ -123,16 +137,19 @@ QString QQStyleKitDebug::propertyPath(const QQStyleKitPropertyGroup *group, cons
|
||||
|
||||
QString QQStyleKitDebug::controlToString(const QQStyleKitControlProperties *control)
|
||||
{
|
||||
if (!control->objectName().isEmpty())
|
||||
return control->objectName();
|
||||
|
||||
const QObject *parentObj = control->parent();
|
||||
if (!parentObj)
|
||||
return "<no parent>"_L1;
|
||||
auto *controls = qobject_cast<const QQStyleKitControls *>(parentObj);
|
||||
if (!controls) {
|
||||
return "<"_L1 + QString::fromUtf8(parentObj->metaObject()->className()) + ">"_L1;
|
||||
}
|
||||
|
||||
const int startIndex = QQStyleKitControlProperties::staticMetaObject.propertyOffset();
|
||||
const int endIndex = QQStyleKitControlProperties::staticMetaObject.propertyCount();
|
||||
auto *controls = qobject_cast<const QQStyleKitControls *>(parentObj);
|
||||
if (!controls)
|
||||
return "<"_L1 + QString::fromUtf8(parentObj->metaObject()->className()) + ">"_L1;
|
||||
|
||||
const int startIndex = QQStyleKitControls::staticMetaObject.propertyOffset();
|
||||
const int endIndex = QQStyleKitControls::staticMetaObject.propertyCount();
|
||||
|
||||
const QMetaObject* parentMeta = parentObj->metaObject();
|
||||
for (int i = startIndex; i < endIndex; ++i) {
|
||||
@@ -145,7 +162,8 @@ QString QQStyleKitDebug::controlToString(const QQStyleKitControlProperties *cont
|
||||
if (propObj == control)
|
||||
return QString::fromUtf8(prop.name());
|
||||
}
|
||||
return "<unknown control: no property found>"_L1;
|
||||
|
||||
return "<unknown control>"_L1;
|
||||
}
|
||||
|
||||
QString QQStyleKitDebug::objectPath(const QQStyleKitControlProperties *properties, QObject *from)
|
||||
@@ -161,10 +179,9 @@ QString QQStyleKitDebug::objectPath(const QQStyleKitControlProperties *propertie
|
||||
path.prepend(theme->name() + kDot);
|
||||
} else if (auto *theme = qobject_cast<const QQStyleKitTheme *>(obj)) {
|
||||
// Note: only one theme is instantiated at a time
|
||||
if (auto style = theme->style())
|
||||
path.prepend(style->themeName());
|
||||
else
|
||||
path.prepend(objectName(obj));
|
||||
path.prepend("Theme("_L1 + theme->style()->m_effectiveThemeName + ")"_L1);
|
||||
} else if (auto *variation = qobject_cast<const QQStyleKitVariation *>(obj)) {
|
||||
path.prepend("StyleVariation("_L1 + variation->name() + ")"_L1);
|
||||
} else if (auto *control = qobject_cast<const QQStyleKitControl *>(obj)) {
|
||||
path.prepend(controlToString(control));
|
||||
} else if (auto *reader = qobject_cast<const QQStyleKitReader *>(obj)) {
|
||||
@@ -210,7 +227,7 @@ void QQStyleKitDebug::notifyPropertyRead(
|
||||
QString storagePath;
|
||||
if (storage->subclass() == QQSK::Subclass::QQStyleKitReader) {
|
||||
/* We read an interpolated value stored directly in the reader itself. While this
|
||||
* can be interesting to print out whe debugging the styling engine itself, it
|
||||
* can be interesting to print out when debugging the styling engine itself, it
|
||||
* comes across as noise when inspecting control-to-style mappings. Ignore. */
|
||||
#if 0
|
||||
storagePath = "[local storage] "_L1;
|
||||
|
||||
@@ -111,7 +111,7 @@ void QQStyleKitDelegate::updateImplicitSize()
|
||||
* 3. Zero
|
||||
* The implicit size is read-only because it's calculated in C++ from internal
|
||||
* child items that are intentionally not exposed to QML. */
|
||||
const qreal impWidthInStyle = m_delegateProperties->implicitWidth();
|
||||
const qreal impWidthInStyle = qMax(m_delegateProperties->minimumWidth(), m_delegateProperties->implicitWidth());
|
||||
const qreal impHeightInStyle = m_delegateProperties->implicitHeight();
|
||||
setImplicitWidth(impWidthInStyle > 0 || !m_imageOverlay ? impWidthInStyle : m_imageOverlay->implicitWidth());
|
||||
setImplicitHeight(impHeightInStyle > 0 || !m_imageOverlay ? impHeightInStyle : m_imageOverlay->implicitHeight());
|
||||
|
||||
+171
-171
@@ -113,11 +113,34 @@ void QQStyleKitPropertyResolver::cacheReaderState(QQSK::State state)
|
||||
s_cachedStateList.append(QQSK::StateFlag::Disabled);
|
||||
}
|
||||
|
||||
void QQStyleKitPropertyResolver::addVariationToReader(
|
||||
QQStyleKitReader *styleReader,
|
||||
QQStyleKitStyleAndThemeBase *styleOrTheme,
|
||||
QQStyleKitVariation *variation)
|
||||
{
|
||||
/* Add the variation to the StyleReader's list of effective variations.
|
||||
* A variation may appear more than once in a type variation list or in
|
||||
* an instance variation list, but it only needs to be added once - the
|
||||
* first in the list will shadow the other ones anyway. */
|
||||
if (!styleReader->m_effectiveVariations.contains(variation))
|
||||
styleReader->m_effectiveVariations.append(variation);
|
||||
|
||||
/* We also record in which Style or Theme the variation was found, so that
|
||||
* it only takes effect for that specific Style or Theme during property
|
||||
* propagation. Note that the same type variation can be used from both the
|
||||
* Style and the Theme (its ID can be added to several variation lists). */
|
||||
if (!variation->m_usageContext.contains(styleOrTheme))
|
||||
variation->m_usageContext.append(styleOrTheme);
|
||||
}
|
||||
|
||||
void QQStyleKitPropertyResolver::addTypeVariationsToReader(
|
||||
QQStyleKitReader *styleReader,
|
||||
const QQStyleKitExtendableControlType parentType,
|
||||
const QQStyleKitStyle *style)
|
||||
QQStyleKitStyleAndThemeBase *styleOrTheme,
|
||||
const AttachedVariationList &attachedVariations)
|
||||
{
|
||||
const QQStyleKitExtendableControlType styleReaderType = styleReader->controlType();
|
||||
const auto styleReaderBaseType = baseTypesForType(styleReaderType);
|
||||
|
||||
static PropertyPathIds ids;
|
||||
if (ids.property.property() == QQSK::Property::NoProperty) {
|
||||
/* ids is made static, since the 'variations' path will be the same for all
|
||||
@@ -129,40 +152,36 @@ void QQStyleKitPropertyResolver::addTypeVariationsToReader(
|
||||
ids.subTypeAlternative = PropertyPathId();
|
||||
}
|
||||
|
||||
const auto parentBaseTypes = baseTypesForType(parentType);
|
||||
const QVariant inStyleVariationsVar = readPropertyInStyle(ids, parentType, parentBaseTypes, style);
|
||||
if (!inStyleVariationsVar.isValid())
|
||||
return;
|
||||
for (const QQStyleKitVariationAttached *attached : attachedVariations) {
|
||||
const auto parentType = attached->controlType();
|
||||
const auto parentBaseTypes = baseTypesForType(parentType);
|
||||
|
||||
/* Inside each Type Variation, check if the control type that styleReader represents has
|
||||
* been defined. If so, it means that the variation might affect it, and should therefore be
|
||||
* added to the style readers list of effective variations. */
|
||||
const QQStyleKitExtendableControlType styleReaderType = styleReader->controlType();
|
||||
const auto styleReaderBaseType = baseTypesForType(styleReaderType);
|
||||
|
||||
const auto inStyleVariations = *qvariant_cast<QList<QQStyleKitVariation *> *>(inStyleVariationsVar);
|
||||
for (auto *variation : inStyleVariations) {
|
||||
if (!variation) {
|
||||
// This happens if the user adds non QQStyleKitVariation elements to the QML array
|
||||
/* Search for the 'variations' property set on the parentType, or any of its base
|
||||
* types, using normal propagation and fallback logic. Unlike when resolving other style
|
||||
* properties, we limit the search to the style or theme we're processing, since it matters which
|
||||
* style or theme a variation belongs when they're used to resolve other style properties later. */
|
||||
const QVariant typeVariationsVariant = readPropertyInRelevantControls(styleOrTheme, ids, parentType, parentBaseTypes);
|
||||
if (!typeVariationsVariant.isValid())
|
||||
continue;
|
||||
}
|
||||
/* Note: when we read the variations property from the style, it returns the varations
|
||||
* set in the most specific storage/state/control (because of propagation). And those
|
||||
* are the only ones that will take effect. This means that even if there are variations
|
||||
* in the fallback style for the requested type (control) that overrides some properties,
|
||||
* and the style/theme has variations that overrides something else, the variations in
|
||||
* the fallback style will, in that case, not be used. The properties not set in the
|
||||
* effective variation will instead propagate back to be read from the type in the theme
|
||||
* or the style. This approach is easier to understand and work with, since the propagation
|
||||
* always flow in one direction, and doesn't jump back and forth between variations, styles
|
||||
* and themes. */
|
||||
if (variation->getControl(styleReaderType)) {
|
||||
styleReader->m_effectiveInStyleVariations.append(variation);
|
||||
} else {
|
||||
for (int type : styleReaderBaseType) {
|
||||
if (variation->getControl(type)) {
|
||||
styleReader->m_effectiveInStyleVariations.append(variation);
|
||||
break;
|
||||
|
||||
const auto typeVariations = *qvariant_cast<QList<QQStyleKitVariation *> *>(typeVariationsVariant);
|
||||
|
||||
for (QQStyleKitVariation *variation : typeVariations) {
|
||||
/* Inside each type variation, check if the control type that styleReader represents has
|
||||
* been defined. If so, it means that the variation _might_ affect it, and should therefore
|
||||
* be added to the style readers list of effective variations. */
|
||||
if (!variation) {
|
||||
/* The variation will be nullptr if non-QQStyleKitVariation elements
|
||||
* are added to the 'variations' list from QML (such as strings). */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (variation->getControl(styleReaderType)) {
|
||||
addVariationToReader(styleReader, styleOrTheme, variation);
|
||||
} else {
|
||||
for (int type : styleReaderBaseType) {
|
||||
if (variation->getControl(type))
|
||||
addVariationToReader(styleReader, styleOrTheme, variation);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -170,8 +189,9 @@ void QQStyleKitPropertyResolver::addTypeVariationsToReader(
|
||||
}
|
||||
|
||||
void QQStyleKitPropertyResolver::addInstanceVariationsToReader(
|
||||
QQStyleKitReader *styleReader, const QStringList &inAppVariationNames,
|
||||
const QVarLengthArray<const QQStyleKitControls *, 6> &stylesAndThemes)
|
||||
QQStyleKitReader *styleReader,
|
||||
QQStyleKitStyleAndThemeBase *styleOrTheme,
|
||||
const AttachedVariationList &attachedVariations)
|
||||
{
|
||||
/* Add the variations set from the application to the list of effective variations
|
||||
* in the styleReader. But, to speed up property look-up later on, we only add the
|
||||
@@ -181,24 +201,22 @@ void QQStyleKitPropertyResolver::addInstanceVariationsToReader(
|
||||
const QQStyleKitExtendableControlType styleReaderType = styleReader->controlType();
|
||||
const auto styleReaderBaseTypes = baseTypesForType(styleReaderType);
|
||||
|
||||
for (const QString &attachedVariationName : inAppVariationNames) {
|
||||
for (const QQStyleKitControls *styleOrTheme : stylesAndThemes) {
|
||||
const QList<QQStyleKitVariation *> variationsInStyleOrTheme = styleOrTheme->variations();
|
||||
for (QQStyleKitVariation *variationInStyleOrTheme : variationsInStyleOrTheme) {
|
||||
if (variationInStyleOrTheme->name() != attachedVariationName)
|
||||
for (const QQStyleKitVariationAttached *attached : attachedVariations) {
|
||||
for (const QString &instanceVariationName : attached->variations()) {
|
||||
for (QQStyleKitVariation *variation : styleOrTheme->m_styleVariations) {
|
||||
if (variation->name() != instanceVariationName)
|
||||
continue;
|
||||
/* Invariant: we found a variation in a Style or a Theme with a name that matches
|
||||
|
||||
/* Invariant: we found a variation in the given Style or a Theme with a name that matches
|
||||
* a name in the attached variation list. Check if the found variation contains the
|
||||
* type, or the subtypes, of the style reader. If not, it doesn't affect it and can
|
||||
* therefore be skipped. */
|
||||
if (variationInStyleOrTheme->getControl(styleReaderType)) {
|
||||
styleReader->m_effectiveInAppVariations.append(variationInStyleOrTheme);
|
||||
if (variation->getControl(styleReaderType)) {
|
||||
addVariationToReader(styleReader, styleOrTheme, variation);
|
||||
} else {
|
||||
for (int baseType : styleReaderBaseTypes) {
|
||||
if (variationInStyleOrTheme->getControl(baseType)) {
|
||||
styleReader->m_effectiveInAppVariations.append(variationInStyleOrTheme);
|
||||
break;
|
||||
}
|
||||
if (variation->getControl(baseType))
|
||||
addVariationToReader(styleReader, styleOrTheme, variation);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -207,7 +225,7 @@ void QQStyleKitPropertyResolver::addInstanceVariationsToReader(
|
||||
}
|
||||
|
||||
void QQStyleKitPropertyResolver::rebuildVariationsForReader(
|
||||
QQStyleKitReader *styleReader, const QQStyleKitStyle *style)
|
||||
QQStyleKitReader *styleReader, QQStyleKitStyle *style)
|
||||
{
|
||||
/* Traverse up the parent chain of \a styleReader, and for each parent, look for an
|
||||
* instance of QQStyleKitVariationAttached. And for each attached object, check if it
|
||||
@@ -218,42 +236,32 @@ void QQStyleKitPropertyResolver::rebuildVariationsForReader(
|
||||
* latter should only affect descendant StyleKitReaders of a specific type. */
|
||||
Q_ASSERT(styleReader->m_effectiveVariationsDirty);
|
||||
styleReader->m_effectiveVariationsDirty = false;
|
||||
styleReader->m_effectiveInAppVariations.clear();
|
||||
styleReader->m_effectiveInStyleVariations.clear();
|
||||
styleReader->m_effectiveVariations.clear();
|
||||
|
||||
const bool hasInstanceVariations = QQStyleKitVariationAttached::s_instanceVariationCount > 0;
|
||||
const bool hasTypeVariations = QQStyleKitVariation::s_typeVariationCount > 0;
|
||||
if (!hasTypeVariations && !hasInstanceVariations) {
|
||||
/* No variations are defined in the current style or theme. In that case
|
||||
* it doesn't matter if the application has variations set - they
|
||||
* will anyway not map to any variations in the style. */
|
||||
if (!style->m_hasVariations)
|
||||
return;
|
||||
}
|
||||
|
||||
/* We need to search through all variations defined in either the style or the theme,
|
||||
* including the ones in the fallback styles, since the variation property propagates,
|
||||
* like all the other style properties. */
|
||||
QVarLengthArray<const QQStyleKitControls *, 6> stylesAndThemes;
|
||||
const QQStyleKitStyle *styleOrFallbackStyle = style;
|
||||
while (styleOrFallbackStyle) {
|
||||
if (const auto *theme = styleOrFallbackStyle->theme())
|
||||
stylesAndThemes.append(theme);
|
||||
stylesAndThemes.append(styleOrFallbackStyle);
|
||||
styleOrFallbackStyle = styleOrFallbackStyle->fallbackStyle();
|
||||
}
|
||||
|
||||
QObject *parentObj = styleReader;
|
||||
while (parentObj) {
|
||||
QObject *attachedObject = qmlAttachedPropertiesObject<QQStyleKitVariation>(parentObj, false);
|
||||
if (attachedObject) {
|
||||
auto *variationAtt = static_cast<QQStyleKitVariationAttached *>(attachedObject);
|
||||
if (hasInstanceVariations)
|
||||
addInstanceVariationsToReader(styleReader, variationAtt->variations(), stylesAndThemes);
|
||||
if (hasTypeVariations)
|
||||
addTypeVariationsToReader(styleReader, variationAtt->controlType(), style);
|
||||
/* Walk up the parent chain and collect all attached StyleVariation objects that
|
||||
* may affect this StyleReader. Their variation lists affect instance variations,
|
||||
* and their control type may affect type variations. */
|
||||
AttachedVariationList attachedVariations;
|
||||
for (QObject *current = styleReader; current; current = current->parent()) {
|
||||
if (const QObject *attachedObject = qmlAttachedPropertiesObject<QQStyleKitVariation>(current, false)) {
|
||||
const auto *attached = static_cast<const QQStyleKitVariationAttached *>(attachedObject);
|
||||
attachedVariations.append(attached);
|
||||
}
|
||||
}
|
||||
|
||||
parentObj = parentObj->parent();
|
||||
if (attachedVariations.isEmpty())
|
||||
return;
|
||||
|
||||
for (QQStyleKitStyle *current = style; current; current = current->fallbackStyle()) {
|
||||
if (QQStyleKitTheme *theme = current->theme()) {
|
||||
addInstanceVariationsToReader(styleReader, theme, attachedVariations);
|
||||
addTypeVariationsToReader(styleReader, theme, attachedVariations);
|
||||
}
|
||||
addInstanceVariationsToReader(styleReader, current, attachedVariations);
|
||||
addTypeVariationsToReader(styleReader, current, attachedVariations);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -444,44 +452,39 @@ QVariant QQStyleKitPropertyResolver::readPropertyInRelevantControls(
|
||||
return {};
|
||||
}
|
||||
|
||||
QVariant QQStyleKitPropertyResolver::readPropertyInStyle(
|
||||
QVariant QQStyleKitPropertyResolver::readPropertyInVariations(
|
||||
const QList<QPointer<QQStyleKitVariation>> &variations,
|
||||
const QQStyleKitStyleAndThemeBase *styleOrTheme,
|
||||
const PropertyPathIds &ids,
|
||||
const QQStyleKitExtendableControlType exactType,
|
||||
const QList<QQStyleKitExtendableControlType> baseTypes,
|
||||
const QQStyleKitStyle *style)
|
||||
const QList<QQStyleKitExtendableControlType> baseTypes)
|
||||
{
|
||||
QVariant value;
|
||||
|
||||
while (true) {
|
||||
value = readPropertyInRelevantControls(style->theme(), ids, exactType, baseTypes);
|
||||
if (value.isValid())
|
||||
break;
|
||||
value = readPropertyInRelevantControls(style, ids, exactType, baseTypes);
|
||||
if (value.isValid())
|
||||
break;
|
||||
|
||||
if (auto *fallbackStyle = style->fallbackStyle()) {
|
||||
/* Recurse into the fallback style, and search for the property there. If not
|
||||
* found, and the fallback style has a fallback style, the recursion continues. */
|
||||
fallbackStyle->syncFromQPalette(style->effectivePalette());
|
||||
value = readPropertyInStyle(ids, exactType, baseTypes, fallbackStyle);
|
||||
if (value.isValid())
|
||||
bool foundAtLeastOneVariation = false;
|
||||
for (const QPointer<QQStyleKitVariation> &variation : variations) {
|
||||
if (!variation)
|
||||
continue;
|
||||
if (!variation->m_usageContext.contains(styleOrTheme)) {
|
||||
if (foundAtLeastOneVariation) {
|
||||
/* Optimization: We have found at least one effective variation in the list, but this
|
||||
* one has a different usage context. This means that the remaining variations will also
|
||||
* have a different usage context, since the variations were added to the list sorted on context.
|
||||
* So we can end the iteration. */
|
||||
break;
|
||||
}
|
||||
/* The variations list is sorted on usage context. And the first variation in the list with
|
||||
* the correct usage context has yet to be found. So continue to the next variation. */
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
foundAtLeastOneVariation = true;
|
||||
const QVariant value = readPropertyInRelevantControls(variation, ids, exactType, baseTypes);
|
||||
if (value.isValid())
|
||||
return value;
|
||||
}
|
||||
|
||||
if (Q_UNLIKELY(QQStyleKitDebug::enabled())) {
|
||||
if (!value.isValid())
|
||||
QQStyleKitDebug::notifyPropertyNotResolved(ids.property);
|
||||
}
|
||||
|
||||
return value;
|
||||
return {};
|
||||
}
|
||||
|
||||
QVariant QQStyleKitPropertyResolver::readProperty(
|
||||
const PropertyPathIds &ids, QQStyleKitReader *styleReader, QQStyleKitStyle *style)
|
||||
QVariant QQStyleKitPropertyResolver::readPropertyInStyle(
|
||||
QQStyleKitStyle *style, const PropertyPathIds &ids, QQStyleKitReader *styleReader)
|
||||
{
|
||||
/* Sync the palette of the style with the palette of the current reader. Note
|
||||
* that this can cause palette bindings in the style to change, which will
|
||||
@@ -502,27 +505,30 @@ QVariant QQStyleKitPropertyResolver::readProperty(
|
||||
QVariant value;
|
||||
|
||||
while (true) {
|
||||
for (const QPointer<QQStyleKitVariation> &variation : std::as_const(styleReader->m_effectiveInAppVariations)) {
|
||||
if (!variation)
|
||||
continue;
|
||||
value = readPropertyInRelevantControls(variation, ids, exactType, baseTypes);
|
||||
if (value.isValid())
|
||||
break;
|
||||
}
|
||||
value = readPropertyInVariations(styleReader->m_effectiveVariations, style->theme(), ids, exactType, baseTypes);
|
||||
if (value.isValid())
|
||||
break;
|
||||
|
||||
for (const QPointer<QQStyleKitVariation> &variation : std::as_const(styleReader->m_effectiveInStyleVariations)) {
|
||||
if (!variation)
|
||||
continue;
|
||||
value = readPropertyInRelevantControls(variation, ids, exactType, baseTypes);
|
||||
if (value.isValid())
|
||||
break;
|
||||
}
|
||||
value = readPropertyInRelevantControls(style->theme(), ids, exactType, baseTypes);
|
||||
if (value.isValid())
|
||||
break;
|
||||
|
||||
value = readPropertyInStyle(ids, exactType, baseTypes, style);
|
||||
value = readPropertyInVariations(styleReader->m_effectiveVariations, style, ids, exactType, baseTypes);
|
||||
if (value.isValid())
|
||||
break;
|
||||
|
||||
value = readPropertyInRelevantControls(style, ids, exactType, baseTypes);
|
||||
if (value.isValid())
|
||||
break;
|
||||
|
||||
if (auto *fallbackStyle = style->fallbackStyle()) {
|
||||
/* Recurse into the fallback style, and search for the property there. If not
|
||||
* found, and the fallback style has a fallback style, the recursion continues. */
|
||||
value = readPropertyInStyle(fallbackStyle, ids, styleReader);
|
||||
if (value.isValid())
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -543,17 +549,16 @@ QVariant QQStyleKitPropertyResolver::readStyleProperty(
|
||||
const QQSK::PropertyPathFlags pathFlags = group->pathFlags();
|
||||
const QQSK::Subclass subclass = controlProperties->subclass();
|
||||
|
||||
if (subclass == QQSK::Subclass::QQStyleKitState) {
|
||||
if (subclass != QQSK::Subclass::QQStyleKitReader) {
|
||||
/* Due to propagation, we must know the reader’s state in order to resolve the value
|
||||
* of a given property. For example, the background delegate’s color may follow a
|
||||
* completely different lookup path—and therefore produce a different result—depending
|
||||
* on whether the reader is a Slider or a Button, and whether it is hovered, pressed, etc.
|
||||
* For this reason, when a property is accessed directly from a control (or one of its
|
||||
* states) within the StyleKit, full propagation cannot be supported: the necessary
|
||||
* reader context is unavailable.
|
||||
* For this reason, when a property is not read via a QQStyleKitReader, propagation and
|
||||
* fall back logic cannot be supported.
|
||||
* However, to still allow static (i.e., non-propagating) bindings between properties
|
||||
* inside a Style, we fall back to simply returning the value defined on the accessed
|
||||
* control itself. */
|
||||
* _inside_ a Style, we fall back to return the value set directly on the accessed control. */
|
||||
Q_ASSERT(subclass == QQSK::Subclass::QQStyleKitState);
|
||||
const QQStyleKitControlState *controlState = controlProperties->asQQStyleKitState();
|
||||
const QQStyleKitControl *control = controlState->control();
|
||||
const PropertyPathId propertyPathId = group->propertyPathId(property, PropertyPathId::Flag::IncludeSubtype);
|
||||
@@ -575,57 +580,52 @@ QVariant QQStyleKitPropertyResolver::readStyleProperty(
|
||||
return {};
|
||||
}
|
||||
|
||||
if (subclass == QQSK::Subclass::QQStyleKitReader) {
|
||||
QQStyleKitDebug::groupBeingRead = group;
|
||||
QQStyleKitReader *styleReader = controlProperties->asQQStyleKitReader();
|
||||
QQStyleKitDebug::groupBeingRead = group;
|
||||
QQStyleKitReader *styleReader = controlProperties->asQQStyleKitReader();
|
||||
|
||||
if (s_isReadingProperty) {
|
||||
if (!s_styleWarningsIssued) {
|
||||
s_styleWarningsIssued = true;
|
||||
qmlWarning(styleReader) << "The style property '" << property << "' was read "
|
||||
<< "before finishing the read of another style property. "
|
||||
<< "This is likely to cause a style glitch.";
|
||||
}
|
||||
if (s_isReadingProperty) {
|
||||
if (!s_styleWarningsIssued) {
|
||||
s_styleWarningsIssued = true;
|
||||
qmlWarning(styleReader) << "The style property '" << property << "' was read "
|
||||
<< "before finishing the read of another style property. "
|
||||
<< "This is likely to cause a style glitch.";
|
||||
}
|
||||
QScopedValueRollback rollback(s_isReadingProperty, true);
|
||||
}
|
||||
QScopedValueRollback rollback(s_isReadingProperty, true);
|
||||
|
||||
PropertyPathIds ids;
|
||||
ids.property = group->propertyPathId(property, PropertyPathId::Flag::ExcludeSubtype);
|
||||
ids.alternative = group->propertyPathId(alternative, PropertyPathId::Flag::ExcludeSubtype);
|
||||
const bool insideSubType = pathFlags &
|
||||
(QQSK::PropertyPathFlag::DelegateSubtype1 | QQSK::PropertyPathFlag::DelegateSubtype2);
|
||||
PropertyPathIds ids;
|
||||
ids.property = group->propertyPathId(property, PropertyPathId::Flag::ExcludeSubtype);
|
||||
ids.alternative = group->propertyPathId(alternative, PropertyPathId::Flag::ExcludeSubtype);
|
||||
const bool insideSubType = pathFlags &
|
||||
(QQSK::PropertyPathFlag::DelegateSubtype1 | QQSK::PropertyPathFlag::DelegateSubtype2);
|
||||
|
||||
if (insideSubType) {
|
||||
ids.subTypeProperty = group->propertyPathId(property, PropertyPathId::Flag::IncludeSubtype);
|
||||
ids.subTypeAlternative = group->propertyPathId(alternative, PropertyPathId::Flag::IncludeSubtype);
|
||||
} else {
|
||||
ids.subTypeProperty = PropertyPathId();
|
||||
ids.subTypeAlternative = PropertyPathId();
|
||||
}
|
||||
|
||||
if (!pathFlags.testFlag(QQSK::PropertyPathFlag::Global)) {
|
||||
/* A style reader can have a storage that contains local property overrides (that is,
|
||||
* interpolated values from an ongoing transition). When searching for a property, we
|
||||
* therefore need to check this storage first. The exception is if the property was read
|
||||
* inside the 'global' group, which means that we should read the values directly
|
||||
* from the style. */
|
||||
if (insideSubType) {
|
||||
ids.subTypeProperty = group->propertyPathId(property, PropertyPathId::Flag::IncludeSubtype);
|
||||
ids.subTypeAlternative = group->propertyPathId(alternative, PropertyPathId::Flag::IncludeSubtype);
|
||||
} else {
|
||||
ids.subTypeProperty = PropertyPathId();
|
||||
ids.subTypeAlternative = PropertyPathId();
|
||||
}
|
||||
|
||||
if (!pathFlags.testFlag(QQSK::PropertyPathFlag::Global)) {
|
||||
/* A style reader can have a storage that contains local property overrides (that is,
|
||||
* interpolated values from an ongoing transition). When searching for a property, we
|
||||
* therefore need to check this storage first. The exception is if the property was read
|
||||
* inside the 'global' group, which means that we should read the values directly
|
||||
* from the style. */
|
||||
if (insideSubType) {
|
||||
const QVariant value = readPropertyInStorageForState(
|
||||
ids.subTypeProperty, ids.subTypeAlternative, styleReader, QQSK::StateFlag::Normal);
|
||||
if (value.isValid())
|
||||
return value;
|
||||
}
|
||||
const QVariant value = readPropertyInStorageForState(
|
||||
ids.property, ids.alternative, styleReader, QQSK::StateFlag::Normal);
|
||||
ids.subTypeProperty, ids.subTypeAlternative, styleReader, QQSK::StateFlag::Normal);
|
||||
if (value.isValid())
|
||||
return value;
|
||||
}
|
||||
|
||||
return readProperty(ids, styleReader, style);
|
||||
const QVariant value = readPropertyInStorageForState(
|
||||
ids.property, ids.alternative, styleReader, QQSK::StateFlag::Normal);
|
||||
if (value.isValid())
|
||||
return value;
|
||||
}
|
||||
|
||||
Q_UNREACHABLE();
|
||||
return {};
|
||||
return readPropertyInStyle(style, ids, styleReader);
|
||||
}
|
||||
|
||||
bool QQStyleKitPropertyResolver::writeStyleProperty(
|
||||
|
||||
+26
-13
@@ -25,9 +25,15 @@ QT_BEGIN_NAMESPACE
|
||||
class QQStyleKitControl;
|
||||
class QQStyleKitControls;
|
||||
class QQStyleKitStyle;
|
||||
class QQStyleKitStyleAndThemeBase;
|
||||
class QQStyleKitReader;
|
||||
class QQStyleKitPropertyGroup;
|
||||
class QQStyleKitVariation;
|
||||
class QQStyleKitVariationAttached;
|
||||
|
||||
// The stack-allocated capacity should be large enough to cover the maximum expected
|
||||
// nesting depth of controls in the application, to avoid heap allocation.
|
||||
using AttachedVariationList = QVarLengthArray<const QQStyleKitVariationAttached *, 20>;
|
||||
class QQStyleKitPropertyResolver
|
||||
{
|
||||
Q_GADGET
|
||||
@@ -89,29 +95,36 @@ private:
|
||||
const QQStyleKitExtendableControlType exactType,
|
||||
const QList<QQStyleKitExtendableControlType> baseTypes);
|
||||
|
||||
static QVariant readPropertyInStyle(
|
||||
static QVariant readPropertyInVariations(
|
||||
const QList<QPointer<QQStyleKitVariation>> &variations,
|
||||
const QQStyleKitStyleAndThemeBase *styleOrTheme,
|
||||
const PropertyPathIds &ids,
|
||||
const QQStyleKitExtendableControlType exactType,
|
||||
const QList<QQStyleKitExtendableControlType> baseTypes,
|
||||
const QQStyleKitStyle *style);
|
||||
const QList<QQStyleKitExtendableControlType> baseTypes);
|
||||
|
||||
static QVariant readProperty(
|
||||
static QVariant readPropertyInStyle(
|
||||
QQStyleKitStyle *style,
|
||||
const PropertyPathIds &ids,
|
||||
QQStyleKitReader *styleReader,
|
||||
QQStyleKitStyle *style);
|
||||
QQStyleKitReader *styleReader);
|
||||
|
||||
static void cacheReaderState(QQSK::State state);
|
||||
|
||||
static inline void addVariationToReader(
|
||||
QQStyleKitReader *styleReader,
|
||||
QQStyleKitStyleAndThemeBase *styleOrTheme,
|
||||
QQStyleKitVariation *variation);
|
||||
|
||||
static void addInstanceVariationsToReader(
|
||||
QQStyleKitReader *styleReader,
|
||||
const QStringList &inAppVariationNames,
|
||||
const QVarLengthArray<const QQStyleKitControls *, 6> &stylesAndThemes);
|
||||
QQStyleKitStyleAndThemeBase *styleOrTheme,
|
||||
const AttachedVariationList &attachedVariations);
|
||||
|
||||
static void addTypeVariationsToReader(
|
||||
QQStyleKitReader *styleReader,
|
||||
const QQStyleKitExtendableControlType parentType,
|
||||
const QQStyleKitStyle *style);
|
||||
static void rebuildVariationsForReader(
|
||||
QQStyleKitReader *styleReader,
|
||||
const QQStyleKitStyle *style);
|
||||
QQStyleKitStyleAndThemeBase *styleOrTheme,
|
||||
const AttachedVariationList &attachedVariations);
|
||||
|
||||
static void rebuildVariationsForReader(QQStyleKitReader *styleReader, QQStyleKitStyle *style);
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
@@ -13,6 +13,215 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
\qmltype StyleReader
|
||||
\inqmlmodule Qt.labs.StyleKit
|
||||
\inherits ControlStyleProperties
|
||||
\brief Reads properties from the active Style for a specific control.
|
||||
|
||||
StyleReader is the bridge between a control in \l {Qt Quick Controls}
|
||||
and the \l {StyleKit::style}{active style}. It exposes all the style
|
||||
properties — \l {ControlStyleProperties::background}{backgrounds},
|
||||
\l {ControlStyleProperties::indicator}{indicators},
|
||||
\l {ControlStyleProperties::handle}{handles},
|
||||
\l {ControlStyleProperties::text}{text},
|
||||
\l {ControlStyleProperties::padding}{padding},
|
||||
and more — that a control, and its delegates, should bind to.
|
||||
All built-in \c StyleKit controls use a StyleReader
|
||||
internally for this purpose.
|
||||
|
||||
The state properties — \l hovered, \l pressed, \l focused, \l checked,
|
||||
\l highlighted, etc. — tell StyleReader which state the control is in.
|
||||
It uses these to resolve and read the correct property values from
|
||||
the \l Style, taking \l {Theme}{Themes}, \l {StyleVariation}{StyleVariations},
|
||||
\l {AbstractStylableControls}{fallback types}, and property propagation
|
||||
into account.
|
||||
|
||||
When implementing a \l CustomControl, you can follow the same approach as
|
||||
the built-in controls:
|
||||
|
||||
\snippet StyleReaderSnippets.qml custom control
|
||||
|
||||
\note The style properties inherited from \l ControlStyleProperties do not map
|
||||
directly to the \l Style. Instead, they reflect a cache of potentially interpolated
|
||||
values during an active \l {ControlStyle::}{transition}. Writing to them will \e not
|
||||
update the corresponding properties in the \l Style and may interfere with ongoing
|
||||
transitions. Write directly to the \l Style when you need to change a style property.
|
||||
|
||||
\labs
|
||||
|
||||
\sa CustomControl, Style, {StyleVariation::controlType}{StyleVariation.controlType}
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty enumeration StyleReader::controlType
|
||||
|
||||
Identifies which control type in the \l Style this reader reads
|
||||
properties from. This can either be set to one of the predefined values
|
||||
below, or to a \l {CustomControl::controlType}{custom control type} defined in the
|
||||
\l Style.
|
||||
|
||||
\value StyleReader.Button \l {Button}
|
||||
\value StyleReader.CheckBox \l {CheckBox}
|
||||
\value StyleReader.ComboBox \l {ComboBox}
|
||||
\value StyleReader.Frame \l {Frame}
|
||||
\value StyleReader.GroupBox \l {GroupBox}
|
||||
\value StyleReader.ItemDelegate \l {ItemDelegate}
|
||||
\value StyleReader.Label \l {Label}
|
||||
\value StyleReader.Menu \l {Menu}
|
||||
\value StyleReader.Dialog \l {Dialog}
|
||||
\value StyleReader.Page \l {Page}
|
||||
\value StyleReader.Pane \l {Pane}
|
||||
\value StyleReader.Popup \l {Popup}
|
||||
\value StyleReader.ProgressBar \l {ProgressBar}
|
||||
\value StyleReader.RadioButton \l {RadioButton}
|
||||
\value StyleReader.ScrollBar \l {ScrollBar}
|
||||
\value StyleReader.ScrollView \l {ScrollView}
|
||||
\value StyleReader.SearchField \l {SearchField}
|
||||
\value StyleReader.Slider \l {Slider}
|
||||
\value StyleReader.SpinBox \l {SpinBox}
|
||||
\value StyleReader.Switch \l {Switch}
|
||||
\value StyleReader.TabBar \l {TabBar}
|
||||
\value StyleReader.TabButton \l {TabButton}
|
||||
\value StyleReader.TextArea \l {TextArea}
|
||||
\value StyleReader.TextField \l {TextField}
|
||||
\value StyleReader.ToolBar \l {ToolBar}
|
||||
\value StyleReader.ToolButton \l {ToolButton}
|
||||
\value StyleReader.ToolSeparator \l {ToolSeparator}
|
||||
|
||||
\sa {StyleVariation::controlType}{StyleVariation.controlType}
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty bool StyleReader::enabled
|
||||
|
||||
Whether the control is enabled.
|
||||
|
||||
Bind this to the control's \l {Item::enabled}{enabled} property.
|
||||
|
||||
The default value is \c true.
|
||||
|
||||
\sa {ControlStateStyle::disabled}{ControlStateStyle.disabled}
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty bool StyleReader::hovered
|
||||
|
||||
Whether the control is hovered.
|
||||
|
||||
Bind this to the control's \l {Control::hovered}{hovered} property.
|
||||
|
||||
The default value is \c false.
|
||||
|
||||
\sa {ControlStateStyle::hovered}{ControlStateStyle.hovered}
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty bool StyleReader::pressed
|
||||
|
||||
Whether the control is pressed.
|
||||
|
||||
Bind this to the control's \l {AbstractButton::pressed}{pressed} property.
|
||||
|
||||
The default value is \c false.
|
||||
|
||||
\sa {ControlStateStyle::pressed}{ControlStateStyle.pressed}
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty bool StyleReader::focused
|
||||
|
||||
Whether the control has active focus.
|
||||
|
||||
Bind this to the control's \l {Item::activeFocus}{activeFocus} property.
|
||||
|
||||
The default value is \c false.
|
||||
|
||||
\sa {ControlStateStyle::focused}{ControlStateStyle.focused}
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty bool StyleReader::checked
|
||||
|
||||
Whether the control is checked.
|
||||
|
||||
Bind this to the control's \l {AbstractButton::checked}{checked} property.
|
||||
|
||||
The default value is \c false.
|
||||
|
||||
\sa {ControlStateStyle::checked}{ControlStateStyle.checked}
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty bool StyleReader::highlighted
|
||||
|
||||
Whether the control is highlighted.
|
||||
|
||||
Bind this to the control's \l {Button::highlighted}{highlighted} property.
|
||||
|
||||
The default value is \c false.
|
||||
|
||||
\sa {ControlStateStyle::highlighted}{ControlStateStyle.highlighted}
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty bool StyleReader::vertical
|
||||
|
||||
Whether the control is oriented vertically.
|
||||
|
||||
Bind this to the control's \l {Slider::orientation}{orientation}.
|
||||
|
||||
The default value is \c false.
|
||||
|
||||
\sa {ControlStateStyle::vertical}{ControlStateStyle.vertical}
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty palette StyleReader::palette
|
||||
|
||||
The palette of the control. StyleKit uses this to resolve color properties
|
||||
that bind the \l {Style::}{palette} in the \l Style.
|
||||
|
||||
Bind this to the control's \l {Control::palette}{palette} property.
|
||||
|
||||
\sa {Style::palette}{Style.palette}
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty font StyleReader::font
|
||||
\readonly
|
||||
|
||||
The effective font for this control type, as defined by the
|
||||
\l {AbstractStyle::fonts}{style}. This also takes into account any font
|
||||
overrides set in the \l {ControlStyle::}{text} properties of the style.
|
||||
|
||||
Bind the control's \l {Control::font}{font} property to this property.
|
||||
|
||||
\note Unlike properties such as \l hovered, \l pressed and \l palette — which
|
||||
is forwarded from the control to the StyleReader — \l font is an output. Bind the
|
||||
control's \l {Control::font}{font} property to this value, not the other way around.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty ControlStyleProperties StyleReader::global
|
||||
\readonly
|
||||
|
||||
Provides direct access to the style properties, bypassing any ongoing
|
||||
\l {ControlStyle::}{transition}.
|
||||
|
||||
While a state transition is ongoing, style properties read from a StyleReader
|
||||
may return interpolated values. By prepending \c global to the property path,
|
||||
you bypass the transition and get the end-state values immediately.
|
||||
|
||||
For example, when transitioning from \l hovered to \l pressed, \c {background.color}
|
||||
may return an interpolated value between the \l {DelegateStyle::}{color} in the
|
||||
\l {ControlStateStyle::}{hovered} state and the color in the
|
||||
\l {ControlStateStyle::}{pressed} state. \c {global.background.color}, on the
|
||||
other hand, returns the color in the pressed state directly.
|
||||
|
||||
\sa {StyleKit::transitionsEnabled}{transitionsEnabled}
|
||||
*/
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
|
||||
static const QString kAlternate1 = "A1"_L1;
|
||||
@@ -53,17 +262,7 @@ static quint64 textFontOverridesSignature(const QQStyleKitTextProperties *t)
|
||||
QList<QQStyleKitReader *> QQStyleKitReader::s_allReaders;
|
||||
QMap<QString, QQmlComponent *> QQStyleKitReader::s_propertyChangesComponents;
|
||||
|
||||
/*!
|
||||
\qmltype StyleReader
|
||||
\inqmlmodule Qt.labs.StyleKit
|
||||
\brief Provides access to control state and palette for styling.
|
||||
|
||||
\labs
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty palette StyleReader::palette
|
||||
*/
|
||||
|
||||
QQStyleKitReader::QQStyleKitReader(QObject *parent)
|
||||
: QQStyleKitControlProperties(QQSK::PropertyGroup::Control, parent)
|
||||
@@ -110,9 +309,9 @@ QQuickStateGroup *QQStyleKitReader::stateGroup()
|
||||
|
||||
QQmlComponent *QQStyleKitReader::createControlChangesComponent() const
|
||||
{
|
||||
static const QLatin1String propertyName("control"_L1);
|
||||
if (s_propertyChangesComponents.contains(propertyName))
|
||||
return s_propertyChangesComponents.value(propertyName);
|
||||
const auto key = u"control"_s;
|
||||
if (auto r = s_propertyChangesComponents.value(key, nullptr))
|
||||
return r;
|
||||
|
||||
const QString qmlControlCode = QString::fromUtf8(R"(
|
||||
import QtQuick
|
||||
@@ -140,14 +339,14 @@ QQmlComponent *QQStyleKitReader::createControlChangesComponent() const
|
||||
QQmlComponent *component = new QQmlComponent(qmlEngine(style()));
|
||||
component->setData(qmlControlCode.toUtf8(), QUrl());
|
||||
Q_ASSERT_X(!component->isError(), __FUNCTION__, component->errorString().toUtf8().constData());
|
||||
s_propertyChangesComponents.insert(propertyName, component);
|
||||
s_propertyChangesComponents.insert(key, component);
|
||||
return component;
|
||||
}
|
||||
|
||||
QQmlComponent *QQStyleKitReader::createDelegateChangesComponent(const QString &delegateName) const
|
||||
{
|
||||
if (s_propertyChangesComponents.contains(delegateName))
|
||||
return s_propertyChangesComponents.value(delegateName);
|
||||
if (auto r = s_propertyChangesComponents.value(delegateName, nullptr))
|
||||
return r;
|
||||
|
||||
static const QString qmlTemplateCode = QString::fromUtf8(R"(
|
||||
import QtQuick
|
||||
|
||||
@@ -29,7 +29,7 @@ class QQuickPalette;
|
||||
class QQStyleKitVariation;
|
||||
class QQStyleKitPropertyResolver;
|
||||
|
||||
class QQStyleKitReader : public QQStyleKitControlProperties
|
||||
class Q_LABSSTYLEKIT_EXPORT QQStyleKitReader : public QQStyleKitControlProperties
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QQStyleKitExtendableControlType controlType READ controlType WRITE setControlType NOTIFY controlTypeChanged FINAL)
|
||||
@@ -197,8 +197,7 @@ private:
|
||||
QQSK::Delegates m_trackedDelegates = QQSK::Delegate::NoDelegate;
|
||||
|
||||
QPointer<QQStyleKitReader> m_parentReader;
|
||||
QList<QPointer<QQStyleKitVariation>> m_effectiveInAppVariations;
|
||||
QList<QPointer<QQStyleKitVariation>> m_effectiveInStyleVariations;
|
||||
QList<QPointer<QQStyleKitVariation>> m_effectiveVariations;
|
||||
|
||||
QQStyleKitControlProperties m_global;
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "qqstylekit_p.h"
|
||||
#include "qqstylekitstyle_p.h"
|
||||
#include "qqstylekittheme_p.h"
|
||||
#include "qqstylekitvariation_p.h"
|
||||
#include "qqstylekitcustomtheme_p.h"
|
||||
#include "qqstylekitcontrolproperties_p.h"
|
||||
#include "qqstylekitpropertyresolver_p.h"
|
||||
@@ -51,7 +52,7 @@ QT_BEGIN_NAMESPACE
|
||||
\labs
|
||||
|
||||
\sa Theme, CustomTheme, StyleVariation, ControlStyle, DelegateStyle,
|
||||
CustomControl, {qtlabsstylekit-property-resolution.html}{Property Resolution}
|
||||
CustomControl
|
||||
*/
|
||||
|
||||
/*!
|
||||
@@ -91,7 +92,7 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
\snippet StyleSnippets.qml dark
|
||||
|
||||
\sa light, themeName, {qtlabsstylekit-theme.html}{Theme}
|
||||
\sa light, themeName
|
||||
*/
|
||||
|
||||
/*!
|
||||
@@ -110,8 +111,6 @@ QT_BEGIN_NAMESPACE
|
||||
you to set many more properties than otherwise needed. A
|
||||
reference implementation of a fallback style can be found
|
||||
\l {qtlabsstylekit-fallbackstyle.html}{here.}
|
||||
|
||||
\sa {qtlabsstylekit-property-resolution.html}{Property Resolution}
|
||||
*/
|
||||
|
||||
/*!
|
||||
@@ -123,7 +122,7 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
\snippet StyleSnippets.qml light
|
||||
|
||||
\sa dark, themeName, {qtlabsstylekit-theme.html}{Theme}
|
||||
\sa dark, themeName
|
||||
*/
|
||||
|
||||
/*!
|
||||
@@ -337,7 +336,8 @@ void QQStyleKitStyle::setThemeName(const QString &themeName)
|
||||
return;
|
||||
|
||||
m_themeName = themeName;
|
||||
recreateTheme();
|
||||
if (m_completed)
|
||||
recreateTheme();
|
||||
|
||||
emit themeNameChanged();
|
||||
}
|
||||
@@ -377,18 +377,15 @@ void QQStyleKitStyle::recreateTheme()
|
||||
qmlWarning(this) << "Custom theme '" << effectiveThemeName << "' has no theme component set";
|
||||
}
|
||||
|
||||
if (m_effectiveThemeName == effectiveThemeName) {
|
||||
// Switching theme name from e.g "System" to "Light" might not
|
||||
// actually change the currently effective theme.
|
||||
emit themeNameChanged();
|
||||
if (m_effectiveThemeName == effectiveThemeName)
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_theme) {
|
||||
m_theme->deleteLater();
|
||||
m_theme = nullptr;
|
||||
}
|
||||
|
||||
m_effectiveThemeName = effectiveThemeName;
|
||||
m_currentThemeComponent = effectiveThemeComponent;
|
||||
|
||||
if (effectiveThemeComponent) {
|
||||
@@ -426,9 +423,11 @@ void QQStyleKitStyle::recreateTheme()
|
||||
m_theme->fonts()->setFallbackFont(fonts());
|
||||
if (m_theme->palettes())
|
||||
m_theme->palettes()->setFallbackPalette(palettes());
|
||||
|
||||
if (this == current()) {
|
||||
m_theme->updateThemePalettes();
|
||||
m_theme->updateThemeFonts();
|
||||
QQStyleKitVariation::resetVariationsForStyle(this);
|
||||
QQStyleKitReader::resetAll();
|
||||
}
|
||||
|
||||
@@ -510,4 +509,3 @@ void QQStyleKitStyle::componentComplete()
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#include "moc_qqstylekitstyle_p.cpp"
|
||||
|
||||
|
||||
@@ -107,6 +107,7 @@ private:
|
||||
|
||||
bool m_completed = false;
|
||||
bool m_isUpdatingPalette = false;
|
||||
bool m_hasVariations = false;
|
||||
|
||||
QQuickDeferredPointer<QQStyleKitStyle> m_fallbackStyle;
|
||||
QPointer<QQmlComponent> m_light;
|
||||
@@ -124,6 +125,8 @@ private:
|
||||
friend class QQStyleKitAttached;
|
||||
friend class QQStyleKitPropertyGroup;
|
||||
friend class QQStyleKitPropertyResolver;
|
||||
friend class QQStyleKitDebug;
|
||||
friend class QQStyleKitVariation;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
+1
@@ -2,6 +2,7 @@
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#include "qqstylekitstyleandthemebase_p.h"
|
||||
#include "qqstylekitvariation_p.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
|
||||
+8
-1
@@ -23,6 +23,8 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QQStyleKitVariation;
|
||||
|
||||
class QQStyleKitStyleAndThemeBase : public QQStyleKitControls
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -41,12 +43,17 @@ signals:
|
||||
void fontsChanged();
|
||||
void palettesChanged();
|
||||
|
||||
private:
|
||||
protected:
|
||||
QList<QQStyleKitVariation *> m_styleVariations;
|
||||
|
||||
private:
|
||||
QQStyleKitFont m_fonts;
|
||||
QQStyleKitPalette m_palettes;
|
||||
|
||||
Q_DISABLE_COPY(QQStyleKitStyleAndThemeBase)
|
||||
|
||||
friend class QQStyleKitPropertyResolver;
|
||||
friend class QQStyleKitVariation;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
@@ -133,14 +133,15 @@ void QQStyleKitTheme::updateThemePalettes()
|
||||
// Apply from farthest fallback -> local
|
||||
for (int i = fbChain.size() - 1; i >= 0; --i) {
|
||||
const QQStyleKitPalette *fb = fbChain[i];
|
||||
if (fb->isSet(scope)) {
|
||||
if (auto *p = (fb->*getter)())
|
||||
result = p->toQPalette().resolve(result);
|
||||
}
|
||||
// Apply system palette first as a base, and override with scope-specific palette
|
||||
if (scope != QQuickTheme::System && fb->isSet(QQuickTheme::System)) {
|
||||
if (auto *sys = fb->system())
|
||||
result = sys->toQPalette().resolve(result);
|
||||
}
|
||||
if (fb->isSet(scope)) {
|
||||
if (auto *p = (fb->*getter)())
|
||||
result = p->toQPalette().resolve(result);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -185,12 +186,13 @@ void QQStyleKitTheme::updateThemeFonts()
|
||||
// Apply from farthest fallback -> local
|
||||
for (int i = fbChain.size() - 1; i >= 0; --i) {
|
||||
const QQStyleKitFont *fb = fbChain[i];
|
||||
if (fb->isSet(scope)) {
|
||||
result = fb->fontForScope(scope).resolve(result);
|
||||
}
|
||||
// Apply system font first as a base, and override with scope-specific font
|
||||
if (scope != QQuickTheme::System && fb->isSet(QQuickTheme::System)) {
|
||||
result = fb->fontForScope(QQuickTheme::System).resolve(result);
|
||||
}
|
||||
if (fb->isSet(scope)) {
|
||||
result = fb->fontForScope(scope).resolve(result);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#include "qqstylekitvariation_p.h"
|
||||
#include "qqstylekitstyleandthemebase_p.h"
|
||||
#include "qqstylekitstyle_p.h"
|
||||
#include "qqstylekittheme_p.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
@@ -122,28 +125,43 @@ QT_BEGIN_NAMESPACE
|
||||
/*!
|
||||
\qmlattachedproperty int StyleVariation::controlType
|
||||
|
||||
This property identifies the control type of the item it is attached to.
|
||||
This property identifies the \l {StyleReader::controlType}{control type} of
|
||||
the item it is attached to.
|
||||
|
||||
StyleKit uses it to resolve \l {Type Variations}{type variations} for descendant
|
||||
controls — if a parent item's \c controlType matches a control type that has
|
||||
\l {ControlStyle::}{variations} defined in the \l Style, those variations apply
|
||||
to all descendant controls.
|
||||
|
||||
Built-in StyleKit controls set this property automatically. Custom controls
|
||||
Built-in controls set this property automatically. Custom controls
|
||||
must set it explicitly to participate in type variation resolution.
|
||||
|
||||
\sa {ControlStyle::variations}{ControlStyle.variations}, StyleReader
|
||||
\sa {ControlStyle::variations}{ControlStyle.variations},
|
||||
{StyleReader::controlType}{StyleReader.controlType}
|
||||
*/
|
||||
|
||||
int QQStyleKitVariation::s_typeVariationCount = 0;
|
||||
int QQStyleKitVariationAttached::s_instanceVariationCount = 0;
|
||||
|
||||
QQStyleKitVariation::QQStyleKitVariation(QObject *parent)
|
||||
: QQStyleKitControls(parent)
|
||||
{
|
||||
/* As an optimization, keep track of how many type variations that are defined
|
||||
* inside the style. That way we can skip looking for them later if s_typeVariationCount == 0. */
|
||||
++s_typeVariationCount;
|
||||
}
|
||||
|
||||
void QQStyleKitVariation::componentComplete()
|
||||
{
|
||||
QQStyleKitControls::componentComplete();
|
||||
|
||||
/* Whenever there is a Style or Theme change, the list of StyleVariations that affects a
|
||||
* StyleReader needs to be rebuilt. And in order to know which StyleVariations that should
|
||||
* be taken into consideration, we need to know which Style each StyleVariation belongs to. */
|
||||
bool styleOrThemeFound = false;
|
||||
for (QObject *current = parent(); current; current = current->parent()) {
|
||||
if (auto *styleOrTheme = qobject_cast<QQStyleKitStyleAndThemeBase *>(current)) {
|
||||
styleOrTheme->m_styleVariations.append(this);
|
||||
styleOrThemeFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!styleOrThemeFound)
|
||||
qmlWarning(this) << "A StyleVariation needs to be a descendant of the Style it belongs to!";
|
||||
}
|
||||
|
||||
QQStyleKitVariationAttached *QQStyleKitVariation::qmlAttachedProperties(QObject *object)
|
||||
@@ -180,16 +198,11 @@ void QQStyleKitVariationAttached::setVariations(const QStringList &variations)
|
||||
if (m_variations == variations)
|
||||
return;
|
||||
|
||||
/* As an optimization, we count the number of instance variations set from the application.
|
||||
* That way, if s_instanceVariationCount == 1, for example, and we found a variation while
|
||||
* resolving the effective variations for a specific QQStyleReader, we can stop the search. */
|
||||
s_instanceVariationCount++;
|
||||
|
||||
m_variations = variations;
|
||||
emit variationsChanged();
|
||||
}
|
||||
|
||||
QQStyleKitExtendableControlType QQStyleKitVariationAttached::controlType()
|
||||
QQStyleKitExtendableControlType QQStyleKitVariationAttached::controlType() const
|
||||
{
|
||||
return m_controlType;
|
||||
}
|
||||
@@ -203,6 +216,39 @@ void QQStyleKitVariationAttached::setControlType(QQStyleKitExtendableControlType
|
||||
emit controlTypeChanged();
|
||||
}
|
||||
|
||||
void QQStyleKitVariation::resetVariationsForStyle(QQStyleKitStyle *style)
|
||||
{
|
||||
/* The usage context stored in a StyleVariation tells which Style or Theme uses it.
|
||||
* After a theme change, we therefore need to rebuild this context list, since the
|
||||
* old theme needs to be removed, and the new theme might need to be added.
|
||||
* Since we also need to update which variations will now be effective for the existing
|
||||
* StyleReaders, we simply clear the context here, and leave it to QQStyleKitPropertyResolver
|
||||
* to rebuild both the effective variations and the context in one pass later.
|
||||
* (QQStyleKitReader::resetReadersForStyle() will set the m_effectiveVariationsDirty
|
||||
* flag, which will trigger the rebuild).
|
||||
*
|
||||
* As an optimization, we also update m_hasVariations to reflect whether any variations
|
||||
* exist at all. If not, variations don't need to be taken into consideration during
|
||||
* style property look-up. */
|
||||
style->m_hasVariations = false;
|
||||
|
||||
for (QQStyleKitStyle *current = style; current; current = current->fallbackStyle()) {
|
||||
if (!current->m_styleVariations.isEmpty()) {
|
||||
style->m_hasVariations = true;
|
||||
for (QQStyleKitVariation *variation : current->m_styleVariations)
|
||||
variation->m_usageContext.clear();
|
||||
}
|
||||
|
||||
if (QQStyleKitTheme *theme = current->theme()) {
|
||||
if (!theme->m_styleVariations.isEmpty()) {
|
||||
style->m_hasVariations = true;
|
||||
for (QQStyleKitVariation *variation : theme->m_styleVariations)
|
||||
variation->m_usageContext.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#include "moc_qqstylekitvariation_p.cpp"
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QQStyleKitVariationAttached;
|
||||
class QQStyleKitStyleAndThemeBase;
|
||||
class QQStyleKitStyle;
|
||||
|
||||
class QQStyleKitVariation : public QQStyleKitControls
|
||||
{
|
||||
@@ -33,6 +35,8 @@ class QQStyleKitVariation : public QQStyleKitControls
|
||||
public:
|
||||
QQStyleKitVariation(QObject *parent = nullptr);
|
||||
|
||||
void componentComplete() override;
|
||||
|
||||
QString name() const;
|
||||
void setName(const QString &name);
|
||||
|
||||
@@ -44,11 +48,13 @@ Q_SIGNALS:
|
||||
private:
|
||||
Q_DISABLE_COPY(QQStyleKitVariation)
|
||||
|
||||
QString m_name;
|
||||
static void resetVariationsForStyle(QQStyleKitStyle *style);
|
||||
|
||||
static int s_typeVariationCount;
|
||||
QString m_name;
|
||||
QList<QPointer<const QQStyleKitStyleAndThemeBase>> m_usageContext;
|
||||
|
||||
friend class QQStyleKitPropertyResolver;
|
||||
friend class QQStyleKitStyle;
|
||||
};
|
||||
|
||||
class QQStyleKitVariationAttached : public QObject
|
||||
@@ -63,7 +69,7 @@ public:
|
||||
QStringList variations() const;
|
||||
void setVariations(const QStringList &variations);
|
||||
|
||||
QQStyleKitExtendableControlType controlType();
|
||||
QQStyleKitExtendableControlType controlType() const;
|
||||
void setControlType(QQStyleKitExtendableControlType type);
|
||||
|
||||
signals:
|
||||
@@ -74,8 +80,6 @@ public:
|
||||
QStringList m_variations;
|
||||
QQStyleKitExtendableControlType m_controlType = QQStyleKitReader::ControlType::Unspecified;
|
||||
|
||||
static int s_instanceVariationCount;
|
||||
|
||||
friend class QQStyleKit;
|
||||
friend class QQStyleKitPropertyResolver;
|
||||
};
|
||||
|
||||
@@ -94,6 +94,7 @@ public:
|
||||
\table
|
||||
\row
|
||||
\li \image qtlabs-wavefrontmesh.png
|
||||
{Torus shape with gradient texture coordinates}
|
||||
\li \qml
|
||||
import QtQuick 2.\1
|
||||
import Qt.labs.wavefrontmesh 1.\1
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#include <QtCore/qtconfigmacros.h>
|
||||
#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses
|
||||
|
||||
#include "qquickcumulativedirection_p.h"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (C) 2021 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#include <QtCore/qtconfigmacros.h>
|
||||
#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses
|
||||
|
||||
#include <QtQuick/private/qsgcontext_p.h>
|
||||
@@ -509,13 +510,13 @@ void fillUniformArrayFromImage(float* array, const QImage& img, int size)
|
||||
\table
|
||||
\row
|
||||
\li qrc:///particleresources/star.png
|
||||
\li \inlineimage particles/star.png
|
||||
\li \inlineimage particles/star.png {White star particle}
|
||||
\row
|
||||
\li qrc:///particleresources/glowdot.png
|
||||
\li \inlineimage particles/glowdot.png
|
||||
\li \inlineimage particles/glowdot.png {White glowing dot particle}
|
||||
\row
|
||||
\li qrc:///particleresources/fuzzydot.png
|
||||
\li \inlineimage particles/fuzzydot.png
|
||||
\li \inlineimage particles/fuzzydot.png {White fuzzy dot particle}
|
||||
\endtable
|
||||
|
||||
Note that the images are white and semi-transparent, to allow colorization
|
||||
|
||||
@@ -170,7 +170,7 @@ class Q_QUICKPARTICLES_EXPORT QQuickImageParticle : public QQuickParticlePainter
|
||||
Q_PROPERTY(qreal alpha READ alpha WRITE setAlpha NOTIFY alphaChanged RESET resetColor)
|
||||
Q_PROPERTY(qreal alphaVariation READ alphaVariation WRITE setAlphaVariation NOTIFY alphaVariationChanged RESET resetColor)
|
||||
|
||||
Q_PROPERTY(qreal rotation READ rotation WRITE setRotation NOTIFY rotationChanged RESET resetRotation)
|
||||
Q_PROPERTY(qreal rotation READ rotation WRITE setRotation NOTIFY rotationChanged RESET resetRotation OVERRIDE)
|
||||
Q_PROPERTY(qreal rotationVariation READ rotationVariation WRITE setRotationVariation NOTIFY rotationVariationChanged RESET resetRotation)
|
||||
Q_PROPERTY(qreal rotationVelocity READ rotationVelocity WRITE setRotationVelocity NOTIFY rotationVelocityChanged RESET resetRotation)
|
||||
Q_PROPERTY(qreal rotationVelocityVariation READ rotationVelocityVariation WRITE setRotationVelocityVariation NOTIFY rotationVelocityVariationChanged RESET resetRotation)
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#include <QtCore/qtconfigmacros.h>
|
||||
#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses
|
||||
|
||||
#include "qquickitemparticle_p.h"
|
||||
#include "qquickparticleemitter_p.h"
|
||||
#include <QtQuick/qsgnode.h>
|
||||
#include <QTimer>
|
||||
#include <QQmlComponent>
|
||||
@@ -293,9 +295,14 @@ QQuickItemParticleAttached *QQuickItemParticle::qmlAttachedProperties(QObject *o
|
||||
|
||||
bool QQuickItemParticle::clockShouldUpdate() const
|
||||
{
|
||||
QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent());
|
||||
return (m_system && m_system->isRunning() && !m_system->isPaused() && m_system->isEnabled()
|
||||
&& ((parentItem && parentItem->isEnabled()) || !parentItem) && isEnabled());
|
||||
// Determine if the QQuickItemParticle clock should stop by looking at the system running
|
||||
// state and any parent Emitter enabled state. Note that this enabled state is the overridden
|
||||
// QQuickParticleEmitter::enabled, and not the unrelated QQuickItem::enabled (which controls
|
||||
// if the item reacts to input events).
|
||||
QQuickParticleEmitter *parentEmitter = qobject_cast<QQuickParticleEmitter *>(parent());
|
||||
bool parentEmitterDisabled = parentEmitter && !parentEmitter->isEnabled();
|
||||
bool systemRunning = m_system && (m_system->isRunning() || m_system->isPaused());
|
||||
return systemRunning && !parentEmitterDisabled;
|
||||
}
|
||||
|
||||
void QQuickItemParticle::reconnectParent(QQuickItem *parentItem)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#include <QtCore/qtconfigmacros.h>
|
||||
#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses
|
||||
|
||||
#include "qquickparticleaffector_p.h"
|
||||
|
||||
@@ -29,7 +29,7 @@ class Q_QUICKPARTICLES_EXPORT QQuickParticleAffector : public QQuickItem
|
||||
Q_PROPERTY(QQuickParticleSystem* system READ system WRITE setSystem NOTIFY systemChanged)
|
||||
Q_PROPERTY(QStringList groups READ groups WRITE setGroups NOTIFY groupsChanged)
|
||||
Q_PROPERTY(QStringList whenCollidingWith READ whenCollidingWith WRITE setWhenCollidingWith NOTIFY whenCollidingWithChanged)
|
||||
Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
|
||||
Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged OVERRIDE)
|
||||
Q_PROPERTY(bool once READ onceOff WRITE setOnceOff NOTIFY onceChanged)
|
||||
Q_PROPERTY(QQuickParticleExtruder* shape READ shape WRITE setShape NOTIFY shapeChanged)
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#include <QtCore/qtconfigmacros.h>
|
||||
#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses
|
||||
|
||||
#include "qquickparticleemitter_p.h"
|
||||
|
||||
@@ -34,7 +34,7 @@ class Q_QUICKPARTICLES_EXPORT QQuickParticleEmitter : public QQuickItem
|
||||
Q_PROPERTY(QQuickParticleSystem* system READ system WRITE setSystem NOTIFY systemChanged)
|
||||
Q_PROPERTY(QString group READ group WRITE setGroup NOTIFY groupChanged)
|
||||
Q_PROPERTY(QQuickParticleExtruder* shape READ extruder WRITE setExtruder NOTIFY extruderChanged)
|
||||
Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
|
||||
Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged OVERRIDE)
|
||||
Q_PROPERTY(int startTime READ startTime WRITE setStartTime NOTIFY startTimeChanged)
|
||||
|
||||
Q_PROPERTY(qreal emitRate READ particlesPerSecond WRITE setParticlesPerSecond NOTIFY particlesPerSecondChanged)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#include <QtCore/qtconfigmacros.h>
|
||||
#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses
|
||||
|
||||
#include "qquickparticlegroup_p.h"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user