Merge remote-tracking branch 'origin/8.0'

Reverts/comments out parts of 45f93a817a,
which needs to be resolved in a follow-up commit.

 Conflicts:
	cmake/QtCreatorIDEBranding.cmake
	qbs/modules/qtc/qtc.qbs
	qtcreator_ide_branding.pri
	share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp
	src/plugins/clangcodemodel/clangmodelmanagersupport.cpp
	src/plugins/cmakeprojectmanager/cmakesettingspage.cpp
	src/plugins/python/pythoneditor.cpp
	src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
	src/plugins/scxmleditor/common/colorsettings.cpp

Change-Id: I7f0f7b7120e75a9fc3a8886bc57c17345cbb501b
This commit is contained in:
Eike Ziller
2022-08-19 09:01:32 +02:00
81 changed files with 1673 additions and 545 deletions

23
dist/changes-8.0.1.md vendored
View File

@@ -13,8 +13,14 @@ the public Git repository. For example:
Editing Editing
------- -------
* Delayed context menu tooltip action creation
* Cached the last QIcon created from a Utils::Icon
### C++ ### C++
* Prevent opening unneeded generated ui header files in clangd
* Fixed documents getting opened in wrong clangd
Projects Projects
-------- --------
@@ -42,17 +48,34 @@ Platforms
### Baremetal ### Baremetal
* Fixed running and debugging applications (QTCREATORBUG-27972) * Fixed running and debugging applications (QTCREATORBUG-27972)
* Fixed bug when cloning jLink gdb server provider
Debugging
---------
* Fixed bitfield display with Python 3
Credits for these changes go to: Credits for these changes go to:
-------------------------------- --------------------------------
Alexander Akulich
Alibek Omarov Alibek Omarov
André Pönitz André Pönitz
Christian Kandeler Christian Kandeler
Christian Stenger
Cristian Adam Cristian Adam
David Schulz
Dmitry Kovalev
Eike Ziller Eike Ziller
Ivan Komissarov Ivan Komissarov
Jaroslaw Kobus Jaroslaw Kobus
Knud Dollereder
Mahmoud Badri Mahmoud Badri
Marcus Tillmanns
Mats Honkamaa Mats Honkamaa
Miikka Heikkinen
Orgad Shaneh
Oswald Buddenhagen Oswald Buddenhagen
Samuel Ghinet
Thomas Hartmann Thomas Hartmann
Vikas Pachdha

View File

@@ -165,6 +165,16 @@
To disable the Python language server, deselect To disable the Python language server, deselect
\uicontrol {Use Python Language Server}. \uicontrol {Use Python Language Server}.
\section2 Qml Language Server
Qt 6.4 ships with the qmlls language server that provides completions and warnings for QML.
It can be set up as a \l {Generic StdIO Language Server}, selecting \c {text/x-qml} and
\c {application/x-qt.ui+qml} as MIME Types, and \c {<Qt Installation>/bin/qmlls} as executable.
If the language server is used together with the QmlJSEditor plugin duplicate suggestions and
warnings might be shown. To avoid this you might want to disable it as described in
\l {Enabling and Disabling Plugins}.
\section1 Supported Locator Filters \section1 Supported Locator Filters
The locator enables you to browse not only files, but any items defined by The locator enables you to browse not only files, but any items defined by

View File

@@ -43,10 +43,8 @@
\section1 2D Assets \section1 2D Assets
You can use the Qt Installer to install \QB if you have a commercial You can use the Qt Installer to install \QB if you have a
\QDS license. You can also purchase a \QB license separately from the \QDS enterprise license.
\l{https://marketplace.qt.io/}{Qt Marketplace} and then install \QB using
the Qt Installer.
\table \table
\row \row

View File

@@ -30,10 +30,10 @@
\title Setting Up \QBPS \title Setting Up \QBPS
You can purchase a \QBPS license from the \l{https://marketplace.qt.io/} \QBPS is included in the
{Qt Marketplace}, and then use the Qt Installer to have the \QBPS \l{https://www.qt.io/pricing}{Qt Design Studio Enterprise license}.
installation package copied to the following path in your Qt installation You can use the Qt Installer to have the \QBPS plugin package copied to the
folder: following path in your Qt installation folder:
\list \list
\li On Windows: \c {Tools\QtDesignStudio\photoshop_bridge} \li On Windows: \c {Tools\QtDesignStudio\photoshop_bridge}

View File

@@ -30,10 +30,10 @@
\title Setting Up \QBSK \title Setting Up \QBSK
You can purchase a \QBSK license from the \l{https://marketplace.qt.io/} \QBSK is included in the
{Qt Marketplace}, and then use the Qt Installer to have the \QBSK \l{https://www.qt.io/pricing}{Qt Design Studio Enterprise license}.
plugin package copied to the following path in your Qt installation You can use the Qt Installer to have the \QBSK plugin package copied to the
folder: following path in your Qt installation folder:
\list \list
\li On Windows: \li On Windows:

View File

@@ -30,10 +30,10 @@
\title Setting Up \QBXD \title Setting Up \QBXD
You can purchase a \QBXD license from the \l{https://marketplace.qt.io/} \QBXD is included in the
{Qt Marketplace}, and then use the Qt Installer to have the \QBXD \l{https://www.qt.io/pricing}{Qt Design Studio Enterprise license}.
plugin package copied to the following path in your Qt installation You can use the Qt Installer to have the \QBXD plugin package copied to the
folder: following path in your Qt installation folder:
\list \list
\li On Windows: \li On Windows:

View File

@@ -16,6 +16,8 @@
<file>mockfiles/images/static_floor.png</file> <file>mockfiles/images/static_floor.png</file>
<file>mockfiles/images/spot.png</file> <file>mockfiles/images/spot.png</file>
<file>mockfiles/images/spot@2x.png</file> <file>mockfiles/images/spot@2x.png</file>
<file>mockfiles/images/preview_landscape.hdr</file>
<file>mockfiles/images/preview_studio.hdr</file>
<file>mockfiles/qt5/AdjustableArrow.qml</file> <file>mockfiles/qt5/AdjustableArrow.qml</file>
<file>mockfiles/qt5/AreaLightHandle.qml</file> <file>mockfiles/qt5/AreaLightHandle.qml</file>
<file>mockfiles/qt5/Arrow.qml</file> <file>mockfiles/qt5/Arrow.qml</file>

View File

@@ -18,6 +18,8 @@
<file>mockfiles/images/floor_tex.png</file> <file>mockfiles/images/floor_tex.png</file>
<file>mockfiles/images/spot.png</file> <file>mockfiles/images/spot.png</file>
<file>mockfiles/images/spot@2x.png</file> <file>mockfiles/images/spot@2x.png</file>
<file>mockfiles/images/preview_landscape.hdr</file>
<file>mockfiles/images/preview_studio.hdr</file>
<file>mockfiles/qt6/AdjustableArrow.qml</file> <file>mockfiles/qt6/AdjustableArrow.qml</file>
<file>mockfiles/qt6/AreaLightHandle.qml</file> <file>mockfiles/qt6/AreaLightHandle.qml</file>
<file>mockfiles/qt6/Arrow.qml</file> <file>mockfiles/qt6/Arrow.qml</file>

View File

@@ -29,8 +29,12 @@ View3D {
id: root id: root
anchors.fill: parent anchors.fill: parent
environment: sceneEnv environment: sceneEnv
camera: envMode === "SkyBox" && envValue === "preview_studio" ? studioCamera : defaultCamera
property Material previewMaterial property Material previewMaterial
property string envMode
property string envValue
property string modelSrc: "#Sphere"
function fitToViewPort(closeUp) function fitToViewPort(closeUp)
{ {
@@ -41,28 +45,59 @@ View3D {
id: sceneEnv id: sceneEnv
antialiasingMode: SceneEnvironment.MSAA antialiasingMode: SceneEnvironment.MSAA
antialiasingQuality: SceneEnvironment.High antialiasingQuality: SceneEnvironment.High
backgroundMode: envMode === "Color" ? SceneEnvironment.Color
: envMode === "SkyBox" ? SceneEnvironment.SkyBox
: SceneEnvironment.Transparent
clearColor: envMode === "Color" ? envValue : "#000000"
lightProbe: envMode === "SkyBox" ? skyBoxTex : null
Texture {
id: skyBoxTex
source: envMode === "SkyBox" ? "../images/" + envValue + ".hdr"
: ""
}
} }
Node { Node {
DirectionalLight { DirectionalLight {
eulerRotation.x: -26 eulerRotation.x: -26
eulerRotation.y: -57 eulerRotation.y: modelSrc === "#Cube" ? -10 : -50
brightness: envMode !== "SkyBox" ? 100 : 0
} }
PerspectiveCamera { PerspectiveCamera {
y: 125.331 id: defaultCamera
z: 120 y: 70
eulerRotation.x: -31 z: 200
eulerRotation.x: -5.71
clipNear: 1 clipNear: 1
clipFar: 1000 clipFar: 1000
} }
PerspectiveCamera {
id: studioCamera
y: 232
z: 85
eulerRotation.x: -64.98
clipNear: 1
clipFar: 1000
}
Node {
rotation: root.camera.rotation
y: 50
Node {
y: modelSrc === "#Cone" ? -40 : 10
eulerRotation.x: 35
Model { Model {
id: model id: model
source: modelSrc ? modelSrc : "#Sphere"
y: 50 eulerRotation.y: 45
source: "#Sphere"
materials: previewMaterial materials: previewMaterial
scale: !modelSrc || modelSrc === "#Sphere"
? Qt.vector3d(1.7, 1.7, 1.7) : Qt.vector3d(1.2, 1.2, 1.2)
}
}
} }
} }
} }

View File

@@ -50,25 +50,28 @@ Item {
view.destroy(); view.destroy();
} }
function createViewForObject(obj) function createViewForObject(obj, env, envValue, model)
{ {
if (obj instanceof Material) if (obj instanceof Material)
createViewForMaterial(obj); createViewForMaterial(obj, env, envValue, model);
else if (obj instanceof Model) else if (obj instanceof Model)
createViewForModel(obj); createViewForModel(obj);
else if (obj instanceof Node) else if (obj instanceof Node)
createViewForNode(obj); createViewForNode(obj);
} }
function createViewForMaterial(material) function createViewForMaterial(material, env, envValue, model)
{ {
if (!materialViewComponent) if (!materialViewComponent)
materialViewComponent = Qt.createComponent("MaterialNodeView.qml"); materialViewComponent = Qt.createComponent("MaterialNodeView.qml");
// Always recreate the view to ensure material is up to date // Always recreate the view to ensure material is up to date
if (materialViewComponent.status === Component.Ready) if (materialViewComponent.status === Component.Ready) {
view = materialViewComponent.createObject(viewRect, {"previewMaterial": material}); view = materialViewComponent.createObject(viewRect, {"previewMaterial": material,
"envMode": env,
"envValue": envValue,
"modelSrc": model});
}
previewObject = material; previewObject = material;
} }

View File

@@ -29,8 +29,12 @@ View3D {
id: root id: root
anchors.fill: parent anchors.fill: parent
environment: sceneEnv environment: sceneEnv
camera: envMode === "SkyBox" && envValue === "preview_studio" ? studioCamera : defaultCamera
property Material previewMaterial property Material previewMaterial
property string envMode
property string envValue
property string modelSrc: "#Sphere"
function fitToViewPort(closeUp) function fitToViewPort(closeUp)
{ {
@@ -41,30 +45,79 @@ View3D {
id: sceneEnv id: sceneEnv
antialiasingMode: SceneEnvironment.MSAA antialiasingMode: SceneEnvironment.MSAA
antialiasingQuality: SceneEnvironment.High antialiasingQuality: SceneEnvironment.High
backgroundMode: envMode === "Color" ? SceneEnvironment.Color
: envMode === "SkyBox" ? SceneEnvironment.SkyBox
: SceneEnvironment.Transparent
clearColor: envMode === "Color" ? envValue : "#000000"
lightProbe: envMode === "SkyBox" ? skyBoxTex : null
Texture {
id: skyBoxTex
source: envMode === "SkyBox" ? "../images/" + envValue + ".hdr"
: ""
}
} }
Node { Node {
DirectionalLight { DirectionalLight {
eulerRotation.x: -26 eulerRotation.x: -26
eulerRotation.y: -57 eulerRotation.y: modelSrc === "#Cube" ? -10 : -50
brightness: envMode !== "SkyBox" ? 1 : 0
} }
PerspectiveCamera { PerspectiveCamera {
y: 125.331 id: defaultCamera
z: 120 y: 70
eulerRotation.x: -31 z: 200
eulerRotation.x: -5.71
clipNear: 1 clipNear: 1
clipFar: 1000 clipFar: 1000
} }
PerspectiveCamera {
id: studioCamera
y: 232
z: 85
eulerRotation.x: -64.98
clipNear: 1
clipFar: 1000
}
Node {
rotation: root.camera.rotation
y: 50
Node {
y: modelSrc === "#Cone" ? -40 : 10
eulerRotation.x: 35
Model { Model {
id: model id: model
readonly property bool _edit3dLocked: true // Make this non-pickable readonly property bool _edit3dLocked: true // Make this non-pickable
source: modelSrc ? modelSrc : "#Sphere"
y: 50 eulerRotation.y: 45
source: "#Sphere"
materials: previewMaterial materials: previewMaterial
scale: !modelSrc || modelSrc === "#Sphere"
? Qt.vector3d(1.7, 1.7, 1.7) : Qt.vector3d(1.2, 1.2, 1.2)
}
}
}
Model {
id: floorModel
source: "#Rectangle"
scale.y: 8
scale.x: 8
eulerRotation.x: -60
visible: !envMode || envMode === "Default"
materials: floorMaterial
DefaultMaterial {
id: floorMaterial
diffuseMap: floorTex
Texture {
id: floorTex
source: "../images/floor_tex.png"
scaleU: floorModel.scale.x
scaleV: floorModel.scale.y
}
}
} }
} }
} }

View File

@@ -50,25 +50,31 @@ Item {
view.destroy(); view.destroy();
} }
function createViewForObject(obj) function createViewForObject(obj, env, envValue, model)
{ {
backgroundView3d.visible = true;
if (obj instanceof Material) if (obj instanceof Material)
createViewForMaterial(obj); createViewForMaterial(obj, env, envValue, model);
else if (obj instanceof Model) else if (obj instanceof Model)
createViewForModel(obj); createViewForModel(obj);
else if (obj instanceof Node) else if (obj instanceof Node)
createViewForNode(obj); createViewForNode(obj);
} }
function createViewForMaterial(material) function createViewForMaterial(material, env, envValue, model)
{ {
if (!materialViewComponent) if (!materialViewComponent)
materialViewComponent = Qt.createComponent("MaterialNodeView.qml"); materialViewComponent = Qt.createComponent("MaterialNodeView.qml");
// Always recreate the view to ensure material is up to date // Always recreate the view to ensure material is up to date
if (materialViewComponent.status === Component.Ready) if (materialViewComponent.status === Component.Ready) {
view = materialViewComponent.createObject(viewRect, {"previewMaterial": material}); view = materialViewComponent.createObject(viewRect, {"previewMaterial": material,
"envMode": env,
"envValue": envValue,
"modelSrc": model});
}
// Floor must be in same view as material so material can reflect it, so hide it in this one
backgroundView3d.visible = false;
previewObject = material; previewObject = material;
} }
@@ -129,6 +135,7 @@ Item {
// Use View3D instead of static image to make background look good on all resolutions // Use View3D instead of static image to make background look good on all resolutions
View3D { View3D {
id: backgroundView3d
anchors.fill: parent anchors.fill: parent
environment: sceneEnv environment: sceneEnv

View File

@@ -339,6 +339,22 @@ void Qt5InformationNodeInstanceServer::resolveImportSupport()
#endif #endif
} }
void Qt5InformationNodeInstanceServer::updateMaterialPreviewData(
const QVector<PropertyValueContainer> &valueChanges)
{
const PropertyName matPrevPrefix("matPrev");
for (const auto &container : valueChanges) {
if (container.instanceId() == 0) {
if (container.name() == "matPrevEnv")
m_materialPreviewData.env = container.value().toString();
else if (container.name() == "matPrevEnvValue")
m_materialPreviewData.envValue = container.value().toString();
else if (container.name() == "matPrevModel")
m_materialPreviewData.model = container.value().toString();
}
}
}
void Qt5InformationNodeInstanceServer::updateRotationBlocks( void Qt5InformationNodeInstanceServer::updateRotationBlocks(
[[maybe_unused]] const QVector<PropertyValueContainer> &valueChanges) [[maybe_unused]] const QVector<PropertyValueContainer> &valueChanges)
{ {
@@ -1176,7 +1192,10 @@ void Qt5InformationNodeInstanceServer::doRenderModelNode3DImageView(
} else { } else {
QMetaObject::invokeMethod( QMetaObject::invokeMethod(
m_modelNode3DImageViewData.rootItem, "createViewForObject", m_modelNode3DImageViewData.rootItem, "createViewForObject",
Q_ARG(QVariant, objectToVariant(instanceObj))); Q_ARG(QVariant, objectToVariant(instanceObj)),
Q_ARG(QVariant, m_materialPreviewData.env),
Q_ARG(QVariant, m_materialPreviewData.envValue),
Q_ARG(QVariant, m_materialPreviewData.model));
} }
// Need to render twice, first render updates spatial nodes // Need to render twice, first render updates spatial nodes
@@ -2010,6 +2029,7 @@ void Qt5InformationNodeInstanceServer::createScene(const CreateSceneCommand &com
if (ViewConfig::isQuick3DMode()) { if (ViewConfig::isQuick3DMode()) {
setup3DEditView(instanceList, command); setup3DEditView(instanceList, command);
updateRotationBlocks(command.auxiliaryChanges); updateRotationBlocks(command.auxiliaryChanges);
updateMaterialPreviewData(command.auxiliaryChanges);
} }
QObject::connect(&m_renderModelNodeImageViewTimer, &QTimer::timeout, QObject::connect(&m_renderModelNodeImageViewTimer, &QTimer::timeout,
@@ -2414,6 +2434,7 @@ void Qt5InformationNodeInstanceServer::requestModelNodePreviewImage(const Reques
void Qt5InformationNodeInstanceServer::changeAuxiliaryValues(const ChangeAuxiliaryCommand &command) void Qt5InformationNodeInstanceServer::changeAuxiliaryValues(const ChangeAuxiliaryCommand &command)
{ {
updateRotationBlocks(command.auxiliaryChanges); updateRotationBlocks(command.auxiliaryChanges);
updateMaterialPreviewData(command.auxiliaryChanges);
Qt5NodeInstanceServer::changeAuxiliaryValues(command); Qt5NodeInstanceServer::changeAuxiliaryValues(command);
render3DEditView(); render3DEditView();
} }

View File

@@ -145,6 +145,7 @@ private:
void updateLockedAndHiddenStates(const QSet<ServerNodeInstance> &instances); void updateLockedAndHiddenStates(const QSet<ServerNodeInstance> &instances);
void handleInputEvents(); void handleInputEvents();
void resolveImportSupport(); void resolveImportSupport();
void updateMaterialPreviewData(const QVector<PropertyValueContainer> &valueChanges);
void updateRotationBlocks(const QVector<PropertyValueContainer> &valueChanges); void updateRotationBlocks(const QVector<PropertyValueContainer> &valueChanges);
void removeRotationBlocks(const QVector<qint32> &instanceIds); void removeRotationBlocks(const QVector<qint32> &instanceIds);
@@ -191,6 +192,13 @@ private:
QObject *m_3dHelper = nullptr; QObject *m_3dHelper = nullptr;
int m_need3DEditViewRender = 0; int m_need3DEditViewRender = 0;
QSet<QObject *> m_dynamicObjectConstructors; QSet<QObject *> m_dynamicObjectConstructors;
struct PreviewData {
QString env;
QString envValue;
QString model;
};
PreviewData m_materialPreviewData;
}; };
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -39,6 +39,8 @@ Item {
property var currentMaterial: null property var currentMaterial: null
property int currentMaterialIdx: 0 property int currentMaterialIdx: 0
property var matSectionsModel: []
// Called also from C++ to close context menu on focus out // Called also from C++ to close context menu on focus out
function closeContextMenu() function closeContextMenu()
{ {
@@ -67,10 +69,12 @@ Item {
acceptedButtons: Qt.RightButton acceptedButtons: Qt.RightButton
onClicked: { onClicked: {
if (!materialBrowserModel.hasMaterialRoot) {
root.currentMaterial = null root.currentMaterial = null
contextMenu.popup() contextMenu.popup()
} }
} }
}
Connections { Connections {
target: materialBrowserModel target: materialBrowserModel
@@ -92,27 +96,77 @@ Item {
StudioControls.MenuItem { StudioControls.MenuItem {
text: qsTr("Apply to selected (replace)") text: qsTr("Apply to selected (replace)")
enabled: currentMaterial && materialBrowserModel.hasModelSelection enabled: root.currentMaterial && materialBrowserModel.hasModelSelection
onTriggered: materialBrowserModel.applyToSelected(currentMaterial.materialInternalId, false) onTriggered: materialBrowserModel.applyToSelected(root.currentMaterial.materialInternalId, false)
} }
StudioControls.MenuItem { StudioControls.MenuItem {
text: qsTr("Apply to selected (add)") text: qsTr("Apply to selected (add)")
enabled: currentMaterial && materialBrowserModel.hasModelSelection enabled: root.currentMaterial && materialBrowserModel.hasModelSelection
onTriggered: materialBrowserModel.applyToSelected(currentMaterial.materialInternalId, true) onTriggered: materialBrowserModel.applyToSelected(root.currentMaterial.materialInternalId, true)
}
StudioControls.MenuSeparator {
height: StudioTheme.Values.border
}
StudioControls.Menu {
title: qsTr("Copy properties")
enabled: root.currentMaterial
width: parent.width
onAboutToShow: {
root.matSectionsModel = ["All"];
switch (root.currentMaterial.materialType) {
case "DefaultMaterial":
root.matSectionsModel = root.matSectionsModel.concat(materialBrowserModel.defaultMaterialSections);
break;
case "PrincipledMaterial":
root.matSectionsModel = root.matSectionsModel.concat(materialBrowserModel.principledMaterialSections);
break;
case "CustomMaterial":
root.matSectionsModel = root.matSectionsModel.concat(materialBrowserModel.customMaterialSections);
break;
}
}
Repeater {
model: root.matSectionsModel
StudioControls.MenuItem {
text: modelData
enabled: root.currentMaterial
onTriggered: materialBrowserModel.copyMaterialProperties(root.currentMaterialIdx, modelData)
}
}
}
StudioControls.MenuItem {
text: qsTr("Paste properties")
enabled: root.currentMaterial && root.currentMaterial.materialType
=== materialBrowserModel.copiedMaterialType
onTriggered: materialBrowserModel.pasteMaterialProperties(root.currentMaterialIdx)
}
StudioControls.MenuSeparator {
height: StudioTheme.Values.border
} }
StudioControls.MenuItem { StudioControls.MenuItem {
text: qsTr("Duplicate") text: qsTr("Duplicate")
enabled: currentMaterial enabled: root.currentMaterial
onTriggered: materialBrowserModel.duplicateMaterial(currentMaterialIdx) onTriggered: materialBrowserModel.duplicateMaterial(root.currentMaterialIdx)
} }
StudioControls.MenuItem { StudioControls.MenuItem {
text: qsTr("Rename") text: qsTr("Rename")
enabled: currentMaterial enabled: root.currentMaterial
onTriggered: { onTriggered: {
var item = gridRepeater.itemAt(currentMaterialIdx); var item = gridRepeater.itemAt(root.currentMaterialIdx);
if (item) if (item)
item.startRename(); item.startRename();
} }
@@ -120,9 +174,9 @@ Item {
StudioControls.MenuItem { StudioControls.MenuItem {
text: qsTr("Delete") text: qsTr("Delete")
enabled: currentMaterial enabled: root.currentMaterial
onTriggered: materialBrowserModel.deleteMaterial(currentMaterialIdx) onTriggered: materialBrowserModel.deleteMaterial(root.currentMaterialIdx)
} }
StudioControls.MenuSeparator {} StudioControls.MenuSeparator {}
@@ -141,6 +195,7 @@ Item {
Row { Row {
width: root.width width: root.width
enabled: !materialBrowserModel.hasMaterialRoot && materialBrowserModel.hasQuick3DImport
SearchBox { SearchBox {
id: searchBox id: searchBox
@@ -165,22 +220,22 @@ Item {
color: StudioTheme.Values.themeTextColor color: StudioTheme.Values.themeTextColor
font.pixelSize: StudioTheme.Values.baseFontSize font.pixelSize: StudioTheme.Values.baseFontSize
leftPadding: 10 leftPadding: 10
visible: materialBrowserModel.hasQuick3DImport && materialBrowserModel.isEmpty && !searchBox.isEmpty() visible: materialBrowserModel.hasQuick3DImport && materialBrowserModel.isEmpty
&& !searchBox.isEmpty() && !materialBrowserModel.hasMaterialRoot
} }
Text { Text {
text: qsTr("There are no materials in this project.<br>Select '<b>+</b>' to create one.") text: {
textFormat: Text.RichText if (materialBrowserModel.hasMaterialRoot)
color: StudioTheme.Values.themeTextColor qsTr("<b>Material Browser</b> is disabled inside a material component.")
font.pixelSize: StudioTheme.Values.mediumFontSize else if (!materialBrowserModel.hasQuick3DImport)
horizontalAlignment: Text.AlignHCenter qsTr("To use <b>Material Browser</b>, first add the QtQuick3D module in the <b>Components</b> view.")
topPadding: 30 else if (materialBrowserModel.isEmpty && searchBox.isEmpty())
anchors.horizontalCenter: parent.horizontalCenter qsTr("There are no materials in this project.<br>Select '<b>+</b>' to create one.")
visible: materialBrowserModel.hasQuick3DImport && materialBrowserModel.isEmpty && searchBox.isEmpty() else
""
} }
Text {
text: qsTr("To use <b>Material Browser</b>, first add the QtQuick3D module in the <b>Components</b> view.");
textFormat: Text.RichText textFormat: Text.RichText
color: StudioTheme.Values.themeTextColor color: StudioTheme.Values.themeTextColor
font.pixelSize: StudioTheme.Values.mediumFontSize font.pixelSize: StudioTheme.Values.mediumFontSize
@@ -188,8 +243,7 @@ Item {
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
width: root.width width: root.width
anchors.horizontalCenter: parent.horizontalCenter visible: text !== ""
visible: !materialBrowserModel.hasQuick3DImport
} }
ScrollView { ScrollView {

View File

@@ -33,6 +33,12 @@ PropertyEditorPane {
id: root id: root
signal toolBarAction(int action) signal toolBarAction(int action)
signal previewEnvChanged(string env)
signal previewModelChanged(string model)
// Called from C++, dummy methods to avoid warnings
function closeContextMenu() {}
function initPreviewData(env, model) {}
Column { Column {
id: col id: col

View File

@@ -31,6 +31,8 @@ PropertyEditorPane {
id: itemPane id: itemPane
signal toolBarAction(int action) signal toolBarAction(int action)
signal previewEnvChanged(string env)
signal previewModelChanged(string model)
// invoked from C++ to refresh material preview image // invoked from C++ to refresh material preview image
function refreshPreview() function refreshPreview()
@@ -38,10 +40,43 @@ PropertyEditorPane {
topSection.refreshPreview() topSection.refreshPreview()
} }
// Called also from C++ to close context menu on focus out
function closeContextMenu()
{
topSection.closeContextMenu()
}
// Called from C++ to initialize preview menu checkmarks
function initPreviewData(env, model)
{
topSection.previewEnv = env;
topSection.previewModel = model
}
MaterialEditorTopSection { MaterialEditorTopSection {
id: topSection id: topSection
onToolBarAction: (action) => itemPane.toolBarAction(action) onToolBarAction: (action) => itemPane.toolBarAction(action)
onPreviewEnvChanged: itemPane.previewEnvChanged(previewEnv)
onPreviewModelChanged: itemPane.previewModelChanged(previewModel)
}
Item { width: 1; height: 10 }
Loader {
id: specificsTwo
property string theSource: specificQmlData
anchors.left: parent.left
anchors.right: parent.right
visible: theSource !== ""
sourceComponent: specificQmlComponent
onTheSourceChanged: {
active = false
active = true
}
} }
Item { width: 1; height: 10 } Item { width: 1; height: 10 }

View File

@@ -47,10 +47,10 @@ Rectangle {
IconButton { IconButton {
icon: StudioTheme.Constants.applyMaterialToSelected icon: StudioTheme.Constants.applyMaterialToSelected
normalColor: "transparent" normalColor: StudioTheme.Values.themeSectionHeadBackground
iconSize: StudioTheme.Values.bigIconFontSize iconSize: StudioTheme.Values.bigIconFontSize
buttonSize: root.height buttonSize: root.height
enabled: hasMaterial && hasModelSelection && hasQuick3DImport enabled: hasMaterial && hasModelSelection && hasQuick3DImport && !hasMaterialRoot
onClicked: root.toolBarAction(ToolBarAction.ApplyToSelected) onClicked: root.toolBarAction(ToolBarAction.ApplyToSelected)
tooltip: qsTr("Apply material to selected model.") tooltip: qsTr("Apply material to selected model.")
} }
@@ -58,10 +58,10 @@ Rectangle {
IconButton { IconButton {
icon: StudioTheme.Constants.newMaterial icon: StudioTheme.Constants.newMaterial
normalColor: "transparent" normalColor: StudioTheme.Values.themeSectionHeadBackground
iconSize: StudioTheme.Values.bigIconFontSize iconSize: StudioTheme.Values.bigIconFontSize
buttonSize: root.height buttonSize: root.height
enabled: hasQuick3DImport enabled: hasQuick3DImport && !hasMaterialRoot
onClicked: root.toolBarAction(ToolBarAction.AddNewMaterial) onClicked: root.toolBarAction(ToolBarAction.AddNewMaterial)
tooltip: qsTr("Create new material.") tooltip: qsTr("Create new material.")
} }
@@ -69,10 +69,10 @@ Rectangle {
IconButton { IconButton {
icon: StudioTheme.Constants.deleteMaterial icon: StudioTheme.Constants.deleteMaterial
normalColor: "transparent" normalColor: StudioTheme.Values.themeSectionHeadBackground
iconSize: StudioTheme.Values.bigIconFontSize iconSize: StudioTheme.Values.bigIconFontSize
buttonSize: root.height buttonSize: root.height
enabled: hasMaterial && hasQuick3DImport enabled: hasMaterial && hasQuick3DImport && !hasMaterialRoot
onClicked: root.toolBarAction(ToolBarAction.DeleteCurrentMaterial) onClicked: root.toolBarAction(ToolBarAction.DeleteCurrentMaterial)
tooltip: qsTr("Delete current material.") tooltip: qsTr("Delete current material.")
} }
@@ -80,10 +80,10 @@ Rectangle {
IconButton { IconButton {
icon: StudioTheme.Constants.openMaterialBrowser icon: StudioTheme.Constants.openMaterialBrowser
normalColor: "transparent" normalColor: StudioTheme.Values.themeSectionHeadBackground
iconSize: StudioTheme.Values.bigIconFontSize iconSize: StudioTheme.Values.bigIconFontSize
buttonSize: root.height buttonSize: root.height
enabled: hasMaterial && hasQuick3DImport enabled: hasMaterial && hasQuick3DImport && !hasMaterialRoot
onClicked: root.toolBarAction(ToolBarAction.OpenMaterialBrowser) onClicked: root.toolBarAction(ToolBarAction.OpenMaterialBrowser)
tooltip: qsTr("Open material browser.") tooltip: qsTr("Open material browser.")
} }

View File

@@ -29,6 +29,7 @@ import QtQuick.Layouts 1.15
import QtQuickDesignerTheme 1.0 import QtQuickDesignerTheme 1.0
import QtQuick.Templates 2.15 as T import QtQuick.Templates 2.15 as T
import HelperWidgets 2.0 import HelperWidgets 2.0
import StudioControls 1.0 as StudioControls
import StudioTheme 1.0 as StudioTheme import StudioTheme 1.0 as StudioTheme
Column { Column {
@@ -36,12 +37,22 @@ Column {
signal toolBarAction(int action) signal toolBarAction(int action)
property string previewEnv
property string previewModel
function refreshPreview() function refreshPreview()
{ {
materialPreview.source = "" materialPreview.source = ""
materialPreview.source = "image://materialEditor/preview" materialPreview.source = "image://materialEditor/preview"
} }
// Called from C++ to close context menu on focus out
function closeContextMenu()
{
modelMenu.close()
envMenu.close()
}
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
@@ -53,11 +64,96 @@ Column {
Item { width: 1; height: 10 } // spacer Item { width: 1; height: 10 } // spacer
StudioControls.Menu {
id: modelMenu
closePolicy: StudioControls.Menu.CloseOnEscape | StudioControls.Menu.CloseOnPressOutside
ListModel {
id: modelMenuModel
ListElement {
modelName: qsTr("Cone")
modelStr: "#Cone"
}
ListElement {
modelName: qsTr("Cube")
modelStr: "#Cube"
}
ListElement {
modelName: qsTr("Cylinder")
modelStr: "#Cylinder"
}
ListElement {
modelName: qsTr("Sphere")
modelStr: "#Sphere"
}
}
Repeater {
model: modelMenuModel
StudioControls.MenuItemWithIcon {
text: modelName
onClicked: {
// Force property change notifications to keep check mark when reselected
root.previewModel = ""
root.previewModel = modelStr
}
checkable: true
checked: root.previewModel === modelStr
}
}
}
StudioControls.Menu {
id: envMenu
closePolicy: StudioControls.Menu.CloseOnEscape | StudioControls.Menu.CloseOnPressOutside
ListModel {
id: envMenuModel
ListElement {
envName: qsTr("Default")
envStr: "Default"
}
ListElement {
envName: qsTr("Color")
envStr: "Color"
}
ListElement {
envName: qsTr("Studio")
envStr: "SkyBox=preview_studio"
}
ListElement {
envName: qsTr("Landscape")
envStr: "SkyBox=preview_landscape"
}
}
Repeater {
model: envMenuModel
StudioControls.MenuItemWithIcon {
text: envName
onClicked: {
// Force property change notifications to keep check mark when reselected
root.previewEnv = ""
root.previewEnv = envStr
}
checkable: true
checked: root.previewEnv === envStr
}
}
}
Item {
anchors.horizontalCenter: parent.horizontalCenter
width: parent.width
height: previewRect.height
Rectangle { Rectangle {
id: previewRect
anchors.horizontalCenter: parent.horizontalCenter
width: 152 width: 152
height: 152 height: 152
color: "#000000" color: "#000000"
anchors.horizontalCenter: parent.horizontalCenter
Image { Image {
id: materialPreview id: materialPreview
@@ -69,6 +165,34 @@ Column {
} }
} }
Item {
id: previewOptions
width: 40
height: previewRect.height
anchors.top: previewRect.top
anchors.left: previewRect.right
Column {
anchors.horizontalCenter: parent.horizontalCenter
IconButton {
icon: StudioTheme.Constants.materialPreviewEnvironment
iconSize: StudioTheme.Values.bigIconFontSize
buttonSize: previewOptions.width
tooltip: qsTr("Select preview environment.")
onClicked: envMenu.popup()
}
IconButton {
icon: StudioTheme.Constants.materialPreviewModel
iconSize: StudioTheme.Values.bigIconFontSize
buttonSize: previewOptions.width
tooltip: qsTr("Select preview model.")
onClicked: modelMenu.popup()
}
}
}
}
Section { Section {
// Section with hidden header is used so properties are aligned with the other sections' properties // Section with hidden header is used so properties are aligned with the other sections' properties
hideHeader: true hideHeader: true
@@ -103,17 +227,8 @@ Column {
Spacer { implicitWidth: StudioTheme.Values.actionIndicatorWidth } Spacer { implicitWidth: StudioTheme.Values.actionIndicatorWidth }
ComboBox { ComboBox {
currentIndex: { currentIndex: possibleTypeIndex
if (backendValues.__classNamePrivateInternal.value === "CustomMaterial") model: possibleTypes
return 2
if (backendValues.__classNamePrivateInternal.value === "PrincipledMaterial")
return 1
return 0
}
model: ["DefaultMaterial", "PrincipledMaterial", "CustomMaterial"]
showExtendedFunctionButton: false showExtendedFunctionButton: false
implicitWidth: StudioTheme.Values.singleControlColumnWidth implicitWidth: StudioTheme.Values.singleControlColumnWidth

View File

@@ -51,13 +51,6 @@ Rectangle {
: mouseArea.containsMouse ? hoverColor : mouseArea.containsMouse ? hoverColor
: normalColor : normalColor
Behavior on color {
ColorAnimation {
duration: 300
easing.type: Easing.OutQuad
}
}
Text { Text {
id: icon id: icon

View File

@@ -136,7 +136,7 @@ Item {
}, },
State { State {
name: "hover" name: "hover"
when: searchFilterText.hovered && !searchFilterText.activeFocus when: root.enabled && searchFilterText.hovered && !searchFilterText.activeFocus
PropertyChanges { PropertyChanges {
target: textFieldBackground target: textFieldBackground
color: StudioTheme.Values.themeControlBackgroundHover color: StudioTheme.Values.themeControlBackgroundHover

View File

@@ -122,72 +122,74 @@ QtObject {
readonly property string listView: "\u0075" readonly property string listView: "\u0075"
readonly property string lockOff: "\u0076" readonly property string lockOff: "\u0076"
readonly property string lockOn: "\u0077" readonly property string lockOn: "\u0077"
readonly property string mergeCells: "\u0078" readonly property string materialPreviewEnvironment: "\u0078"
readonly property string minus: "\u0079" readonly property string materialPreviewModel: "\u0079"
readonly property string mirror: "\u007A" readonly property string mergeCells: "\u007A"
readonly property string newMaterial: "\u007B" readonly property string minus: "\u007B"
readonly property string openMaterialBrowser: "\u007C" readonly property string mirror: "\u007C"
readonly property string orientation: "\u007D" readonly property string newMaterial: "\u007D"
readonly property string paddingEdge: "\u007E" readonly property string openMaterialBrowser: "\u007E"
readonly property string paddingFrame: "\u007F" readonly property string orientation: "\u007F"
readonly property string pasteStyle: "\u0080" readonly property string paddingEdge: "\u0080"
readonly property string pause: "\u0081" readonly property string paddingFrame: "\u0081"
readonly property string pin: "\u0082" readonly property string pasteStyle: "\u0082"
readonly property string play: "\u0083" readonly property string pause: "\u0083"
readonly property string plus: "\u0084" readonly property string pin: "\u0084"
readonly property string promote: "\u0085" readonly property string play: "\u0085"
readonly property string readOnly: "\u0086" readonly property string plus: "\u0086"
readonly property string redo: "\u0087" readonly property string promote: "\u0087"
readonly property string rotationFill: "\u0088" readonly property string readOnly: "\u0088"
readonly property string rotationOutline: "\u0089" readonly property string redo: "\u0089"
readonly property string search: "\u008A" readonly property string rotationFill: "\u008A"
readonly property string sectionToggle: "\u008B" readonly property string rotationOutline: "\u008B"
readonly property string splitColumns: "\u008C" readonly property string search: "\u008C"
readonly property string splitRows: "\u008D" readonly property string sectionToggle: "\u008D"
readonly property string startNode: "\u008E" readonly property string splitColumns: "\u008E"
readonly property string testIcon: "\u008F" readonly property string splitRows: "\u008F"
readonly property string textAlignBottom: "\u0090" readonly property string startNode: "\u0090"
readonly property string textAlignCenter: "\u0091" readonly property string testIcon: "\u0091"
readonly property string textAlignJustified: "\u0092" readonly property string textAlignBottom: "\u0092"
readonly property string textAlignLeft: "\u0093" readonly property string textAlignCenter: "\u0093"
readonly property string textAlignMiddle: "\u0094" readonly property string textAlignJustified: "\u0094"
readonly property string textAlignRight: "\u0095" readonly property string textAlignLeft: "\u0095"
readonly property string textAlignTop: "\u0096" readonly property string textAlignMiddle: "\u0096"
readonly property string textBulletList: "\u0097" readonly property string textAlignRight: "\u0097"
readonly property string textFullJustification: "\u0098" readonly property string textAlignTop: "\u0098"
readonly property string textNumberedList: "\u0099" readonly property string textBulletList: "\u0099"
readonly property string tickIcon: "\u009A" readonly property string textFullJustification: "\u009A"
readonly property string translationCreateFiles: "\u009B" readonly property string textNumberedList: "\u009B"
readonly property string translationCreateReport: "\u009D" readonly property string tickIcon: "\u009D"
readonly property string translationExport: "\u009E" readonly property string translationCreateFiles: "\u009E"
readonly property string translationImport: "\u009F" readonly property string translationCreateReport: "\u009F"
readonly property string translationSelectLanguages: "\u00A0" readonly property string translationExport: "\u00A0"
readonly property string translationTest: "\u00A1" readonly property string translationImport: "\u00A1"
readonly property string transparent: "\u00A2" readonly property string translationSelectLanguages: "\u00A2"
readonly property string triState: "\u00A3" readonly property string translationTest: "\u00A3"
readonly property string triangleArcA: "\u00A4" readonly property string transparent: "\u00A4"
readonly property string triangleArcB: "\u00A5" readonly property string triState: "\u00A5"
readonly property string triangleCornerA: "\u00A6" readonly property string triangleArcA: "\u00A6"
readonly property string triangleCornerB: "\u00A7" readonly property string triangleArcB: "\u00A7"
readonly property string unLinked: "\u00A8" readonly property string triangleCornerA: "\u00A8"
readonly property string undo: "\u00A9" readonly property string triangleCornerB: "\u00A9"
readonly property string unpin: "\u00AA" readonly property string unLinked: "\u00AA"
readonly property string upDownIcon: "\u00AB" readonly property string undo: "\u00AB"
readonly property string upDownSquare2: "\u00AC" readonly property string unpin: "\u00AC"
readonly property string visibilityOff: "\u00AE" readonly property string upDownIcon: "\u00AE"
readonly property string visibilityOn: "\u00AF" readonly property string upDownSquare2: "\u00AF"
readonly property string wildcard: "\u00B0" readonly property string visibilityOff: "\u00B0"
readonly property string wizardsAutomotive: "\u00B1" readonly property string visibilityOn: "\u00B1"
readonly property string wizardsDesktop: "\u00B2" readonly property string wildcard: "\u00B2"
readonly property string wizardsGeneric: "\u00B3" readonly property string wizardsAutomotive: "\u00B3"
readonly property string wizardsMcuEmpty: "\u00B4" readonly property string wizardsDesktop: "\u00B4"
readonly property string wizardsMcuGraph: "\u00B5" readonly property string wizardsGeneric: "\u00B5"
readonly property string wizardsMobile: "\u00B6" readonly property string wizardsMcuEmpty: "\u00B6"
readonly property string wizardsUnknown: "\u00B7" readonly property string wizardsMcuGraph: "\u00B7"
readonly property string zoomAll: "\u00B8" readonly property string wizardsMobile: "\u00B8"
readonly property string zoomIn: "\u00B9" readonly property string wizardsUnknown: "\u00B9"
readonly property string zoomOut: "\u00BA" readonly property string zoomAll: "\u00BA"
readonly property string zoomSelection: "\u00BB" readonly property string zoomIn: "\u00BB"
readonly property string zoomOut: "\u00BC"
readonly property string zoomSelection: "\u00BD"
readonly property font iconFont: Qt.font({ readonly property font iconFont: Qt.font({
"family": controlIcons.name, "family": controlIcons.name,

View File

@@ -318,8 +318,7 @@
}, },
{ {
"source": "Screen01.ui.qml.tpl", "source": "Screen01.ui.qml.tpl",
"target": "%{ProjectDirectory}/content/Screen01.ui.qml", "target": "%{ProjectDirectory}/content/Screen01.ui.qml"
"openInEditor": true
}, },
{ {
"source": "../common/fonts.txt", "source": "../common/fonts.txt",

View File

@@ -421,6 +421,7 @@ namespace ADS {
d->m_lastLocation = InvalidDockWidgetArea; d->m_lastLocation = InvalidDockWidgetArea;
// Move it over the target. // Move it over the target.
hide();
resize(target->size()); resize(target->size());
QPoint topLeft = target->mapToGlobal(target->rect().topLeft()); QPoint topLeft = target->mapToGlobal(target->rect().topLeft());
move(topLeft); move(topLeft);

View File

@@ -612,7 +612,7 @@ class UnsupportedTypesByVisualDesigner : public QStringList
{ {
public: public:
UnsupportedTypesByVisualDesigner() UnsupportedTypesByVisualDesigner()
: QStringList({"Timer", "Package", "Particles", "ApplicationWindow"}) : QStringList({"Package", "Particles", "ApplicationWindow"})
{} {}
}; };

View File

@@ -175,6 +175,11 @@ bool JLinkGdbServerProvider::operator==(const IDebugServerProvider &other) const
const auto p = static_cast<const JLinkGdbServerProvider *>(&other); const auto p = static_cast<const JLinkGdbServerProvider *>(&other);
return m_executableFile == p->m_executableFile return m_executableFile == p->m_executableFile
&& m_jlinkDevice == p->m_jlinkDevice
&& m_jlinkHost == p->m_jlinkHost
&& m_jlinkHostAddr == p->m_jlinkHostAddr
&& m_jlinkTargetIface == p->m_jlinkTargetIface
&& m_jlinkTargetIfaceSpeed == p->m_jlinkTargetIfaceSpeed
&& m_additionalArguments == p->m_additionalArguments; && m_additionalArguments == p->m_additionalArguments;
} }

View File

@@ -157,6 +157,20 @@ static void checkSystemForClangdSuitability()
Core::ICore::infoBar()->addInfo(info); Core::ICore::infoBar()->addInfo(info);
} }
static void updateParserConfig(ClangdClient *client)
{
if (!client->reachable())
return;
if (const auto editor = TextEditor::BaseTextEditor::currentTextEditor()) {
if (!client->documentOpen(editor->textDocument()))
return;
const Utils::FilePath filePath = editor->textDocument()->filePath();
if (const auto processor = ClangEditorDocumentProcessor::get(filePath.toString()))
client->updateParserConfig(filePath, processor->parserConfig());
}
}
ClangModelManagerSupport::ClangModelManagerSupport() ClangModelManagerSupport::ClangModelManagerSupport()
{ {
watchForExternalChanges(); watchForExternalChanges();
@@ -382,6 +396,13 @@ void ClangModelManagerSupport::updateLanguageClient(
if (Client * const oldClient = clientForProject(project)) if (Client * const oldClient = clientForProject(project))
LanguageClientManager::shutdownClient(oldClient); LanguageClientManager::shutdownClient(oldClient);
ClangdClient * const client = new ClangdClient(project, jsonDbDir); ClangdClient * const client = new ClangdClient(project, jsonDbDir);
connect(client, &Client::shadowDocumentSwitched, this, [](const Utils::FilePath &fp) {
ClangdClient::handleUiHeaderChange(fp.fileName());
});
connect(CppModelManager::instance(),
&CppModelManager::projectPartsUpdated,
client,
[client] { updateParserConfig(client); });
connect(client, &Client::initialized, this, [this, client, project, projectInfo, jsonDbDir] { connect(client, &Client::initialized, this, [this, client, project, projectInfo, jsonDbDir] {
using namespace ProjectExplorer; using namespace ProjectExplorer;
if (!SessionManager::hasProject(project)) if (!SessionManager::hasProject(project))
@@ -393,25 +414,15 @@ void ClangModelManagerSupport::updateLanguageClient(
if (!newProjectInfo || *newProjectInfo != *projectInfo) if (!newProjectInfo || *newProjectInfo != *projectInfo)
return; return;
const auto updateParserConfig = [client] {
if (const auto editor = TextEditor::BaseTextEditor::currentTextEditor()) {
if (!client->documentOpen(editor->textDocument()))
return;
const Utils::FilePath filePath = editor->textDocument()->filePath();
if (const auto processor = ClangEditorDocumentProcessor::get(
filePath.toString())) {
const CppEditor::BaseEditorDocumentParser::Configuration config
= processor->parserConfig();
client->updateParserConfig(filePath, config);
}
}
};
// Acquaint the client with all open C++ documents for this project. // Acquaint the client with all open C++ documents for this project.
bool hasDocuments = false; bool hasDocuments = false;
const ClangdSettings settings(ClangdProjectSettings(project).settings()); const ClangdSettings settings(ClangdProjectSettings(project).settings());
for (TextEditor::TextDocument * const doc : allCppDocuments()) { for (TextEditor::TextDocument * const doc : allCppDocuments()) {
Client * const currentClient = LanguageClientManager::clientForDocument(doc); Client * const currentClient = LanguageClientManager::clientForDocument(doc);
if (currentClient == client) {
hasDocuments = true;
continue;
}
if (!settings.sizeIsOkay(doc->filePath())) if (!settings.sizeIsOkay(doc->filePath()))
continue; continue;
const Project * const docProject = SessionManager::projectForFile(doc->filePath()); const Project * const docProject = SessionManager::projectForFile(doc->filePath());
@@ -440,17 +451,8 @@ void ClangModelManagerSupport::updateLanguageClient(
++it; ++it;
} }
} }
connect(client, &Client::shadowDocumentSwitched, this,
[](const Utils::FilePath &fp) {
ClangdClient::handleUiHeaderChange(fp.fileName());
});
if (client->state() == Client::Initialized) updateParserConfig(client);
updateParserConfig();
else
connect(client, &Client::initialized, client, updateParserConfig);
connect(CppModelManager::instance(), &CppModelManager::projectPartsUpdated,
client, updateParserConfig);
if (hasDocuments) if (hasDocuments)
return; return;

View File

@@ -66,7 +66,6 @@ void adjustFormatStyleForLineBreak(clang::format::FormatStyle &style,
if (replacementsToKeep == ReplacementsToKeep::IndentAndBefore) if (replacementsToKeep == ReplacementsToKeep::IndentAndBefore)
return; return;
style.DisableFormat = false;
style.ColumnLimit = 0; style.ColumnLimit = 0;
#ifdef KEEP_LINE_BREAKS_FOR_NON_EMPTY_LINES_BACKPORTED #ifdef KEEP_LINE_BREAKS_FOR_NON_EMPTY_LINES_BACKPORTED
style.KeepLineBreaksForNonEmptyLines = true; style.KeepLineBreaksForNonEmptyLines = true;

View File

@@ -435,7 +435,6 @@ public:
private: private:
void onBinaryPathEditingFinished(); void onBinaryPathEditingFinished();
void updateQchFilePath(); void updateQchFilePath();
void reload();
CMakeToolItemModel *m_model; CMakeToolItemModel *m_model;
QLineEdit *m_displayNameLineEdit; QLineEdit *m_displayNameLineEdit;
@@ -501,7 +500,6 @@ void CMakeToolItemConfigWidget::onBinaryPathEditingFinished()
{ {
updateQchFilePath(); updateQchFilePath();
store(); store();
reload();
} }
void CMakeToolItemConfigWidget::updateQchFilePath() void CMakeToolItemConfigWidget::updateQchFilePath()
@@ -510,18 +508,6 @@ void CMakeToolItemConfigWidget::updateQchFilePath()
m_qchFileChooser->setFilePath(CMakeTool::searchQchFile(m_binaryChooser->filePath())); m_qchFileChooser->setFilePath(CMakeTool::searchQchFile(m_binaryChooser->filePath()));
} }
void CMakeToolItemConfigWidget::reload()
{
if (!m_id.isValid())
return;
const CMakeToolTreeItem *item = m_model->cmakeToolItem(m_id);
if (!item)
return;
load(item);
}
void CMakeToolItemConfigWidget::load(const CMakeToolTreeItem *item) void CMakeToolItemConfigWidget::load(const CMakeToolTreeItem *item)
{ {
m_loadingItem = true; // avoid intermediate signal handling m_loadingItem = true; // avoid intermediate signal handling

View File

@@ -473,16 +473,16 @@ void CompilerOptionsBuilder::addLanguageVersionAndExtensions()
default: default:
break; break;
case LanguageVersion::CXX14: case LanguageVersion::CXX14:
option = "-clang:std=c++14"; option = "-clang:-std=c++14";
break; break;
case LanguageVersion::CXX17: case LanguageVersion::CXX17:
option = "-clang:std=c++17"; option = "-clang:-std=c++17";
break; break;
case LanguageVersion::CXX20: case LanguageVersion::CXX20:
option = "-clang:std=c++20"; option = "-clang:-std=c++20";
break; break;
case LanguageVersion::CXX2b: case LanguageVersion::CXX2b:
option = "-clang:std=c++2b"; option = "-clang:-std=c++2b";
break; break;
} }

View File

@@ -192,7 +192,7 @@ void CompilerOptionsBuilderTest::testLanguageVersionIsExplicitlySetIfNotProvided
UseTweakedHeaderPaths::No, UseLanguageDefines::Yes}; UseTweakedHeaderPaths::No, UseLanguageDefines::Yes};
compilerOptionsBuilder.build(ProjectFile::CXXSource, UsePrecompiledHeaders::No); compilerOptionsBuilder.build(ProjectFile::CXXSource, UsePrecompiledHeaders::No);
QVERIFY(compilerOptionsBuilder.options().contains("-clang:std=c++17")); QVERIFY(compilerOptionsBuilder.options().contains("-clang:-std=c++17"));
} }
void CompilerOptionsBuilderTest::testAddWordWidth() void CompilerOptionsBuilderTest::testAddWordWidth()
@@ -633,7 +633,7 @@ void CompilerOptionsBuilderTest::testBuildAllOptionsMsvc()
[&t](const QString &o) { return o.contains(t.toNative("wrappedQtHeaders/QtCore")); }); [&t](const QString &o) { return o.contains(t.toNative("wrappedQtHeaders/QtCore")); });
QCOMPARE(compilerOptionsBuilder.options(), QCOMPARE(compilerOptionsBuilder.options(),
(QStringList{"-nostdinc", "-nostdinc++", "--driver-mode=cl", "/Zs", "-m64", (QStringList{"-nostdinc", "-nostdinc++", "--driver-mode=cl", "/Zs", "-m64",
"--target=x86_64-apple-darwin10", "/TP", "-clang:std=c++17", "--target=x86_64-apple-darwin10", "/TP", "-clang:-std=c++17",
"-fms-compatibility-version=19.00", "-DprojectFoo=projectBar", "-fms-compatibility-version=19.00", "-DprojectFoo=projectBar",
"-D__FUNCSIG__=\"void __cdecl someLegalAndLongishFunctionNameThatWorksAroundQTCREATORBUG-24580(void)\"", "-D__FUNCSIG__=\"void __cdecl someLegalAndLongishFunctionNameThatWorksAroundQTCREATORBUG-24580(void)\"",
"-D__FUNCTION__=\"someLegalAndLongishFunctionNameThatWorksAroundQTCREATORBUG-24580\"", "-D__FUNCTION__=\"someLegalAndLongishFunctionNameThatWorksAroundQTCREATORBUG-24580\"",
@@ -662,7 +662,7 @@ void CompilerOptionsBuilderTest::testBuildAllOptionsMsvcWithExceptions()
[&t](const QString &o) { return o.contains(t.toNative("wrappedQtHeaders/QtCore")); }); [&t](const QString &o) { return o.contains(t.toNative("wrappedQtHeaders/QtCore")); });
QCOMPARE(compilerOptionsBuilder.options(), QCOMPARE(compilerOptionsBuilder.options(),
(QStringList{"-nostdinc", "-nostdinc++", "--driver-mode=cl", "/Zs", "-m64", (QStringList{"-nostdinc", "-nostdinc++", "--driver-mode=cl", "/Zs", "-m64",
"--target=x86_64-apple-darwin10", "/TP", "-clang:std=c++17", "-fcxx-exceptions", "--target=x86_64-apple-darwin10", "/TP", "-clang:-std=c++17", "-fcxx-exceptions",
"-fexceptions", "-fms-compatibility-version=19.00", "-fexceptions", "-fms-compatibility-version=19.00",
"-DprojectFoo=projectBar", "-DprojectFoo=projectBar",
"-D__FUNCSIG__=\"void __cdecl someLegalAndLongishFunctionNameThatWorksAroundQTCREATORBUG-24580(void)\"", "-D__FUNCSIG__=\"void __cdecl someLegalAndLongishFunctionNameThatWorksAroundQTCREATORBUG-24580(void)\"",

View File

@@ -378,7 +378,6 @@ SignalSlotType CppModelManager::getSignalSlotType(const FilePath &filePath,
QTextCursor cursor(&textDocument); QTextCursor cursor(&textDocument);
cursor.setPosition(position); cursor.setPosition(position);
// Are we at the second argument of a function call?
const QList<AST *> path = ASTPath(document)(cursor); const QList<AST *> path = ASTPath(document)(cursor);
if (path.isEmpty()) if (path.isEmpty())
return SignalSlotType::None; return SignalSlotType::None;
@@ -388,9 +387,27 @@ SignalSlotType CppModelManager::getSignalSlotType(const FilePath &filePath,
break; break;
} }
// Is the function called "connect" or "disconnect"?
if (!callAst || !callAst->base_expression) if (!callAst || !callAst->base_expression)
return SignalSlotType::None; return SignalSlotType::None;
const int argumentPosition = argumentPositionOf(path.last(), callAst);
if (argumentPosition != 2 && argumentPosition != 4)
return SignalSlotType::None;
const NameAST *nameAst = nullptr;
if (const IdExpressionAST * const idAst = callAst->base_expression->asIdExpression())
nameAst = idAst->name;
else if (const MemberAccessAST * const ast = callAst->base_expression->asMemberAccess())
nameAst = ast->member_name;
if (!nameAst || !nameAst->name)
return SignalSlotType::None;
const Identifier * const id = nameAst->name->identifier();
if (!id)
return SignalSlotType::None;
const QString funcName = QString::fromUtf8(id->chars(), id->size());
if (funcName != "connect" && funcName != "disconnect")
return SignalSlotType::None;
Scope *scope = document->globalNamespace(); Scope *scope = document->globalNamespace();
for (auto it = path.crbegin(); it != path.crend(); ++it) { for (auto it = path.crbegin(); it != path.crend(); ++it) {
if (const CompoundStatementAST * const stmtAst = (*it)->asCompoundStatement()) { if (const CompoundStatementAST * const stmtAst = (*it)->asCompoundStatement()) {
@@ -398,12 +415,8 @@ SignalSlotType CppModelManager::getSignalSlotType(const FilePath &filePath,
break; break;
} }
} }
const NameAST *nameAst = nullptr;
const LookupContext context(document, snapshot); const LookupContext context(document, snapshot);
if (const IdExpressionAST * const idAst = callAst->base_expression->asIdExpression()) { if (const MemberAccessAST * const ast = callAst->base_expression->asMemberAccess()) {
nameAst = idAst->name;
} else if (const MemberAccessAST * const ast = callAst->base_expression->asMemberAccess()) {
nameAst = ast->member_name;
TypeOfExpression exprType; TypeOfExpression exprType;
exprType.setExpandTemplates(true); exprType.setExpandTemplates(true);
exprType.init(document, snapshot); exprType.init(document, snapshot);
@@ -433,14 +446,6 @@ SignalSlotType CppModelManager::getSignalSlotType(const FilePath &filePath,
if (!scope) if (!scope)
return SignalSlotType::None; return SignalSlotType::None;
} }
if (!nameAst || !nameAst->name)
return SignalSlotType::None;
const Identifier * const id = nameAst->name->identifier();
if (!id)
return SignalSlotType::None;
const QString funcName = QString::fromUtf8(id->chars(), id->size());
if (funcName != "connect" && funcName != "disconnect")
return SignalSlotType::None;
// Is the function a member function of QObject? // Is the function a member function of QObject?
const QList<LookupItem> matches = context.lookup(nameAst->name, scope); const QList<LookupItem> matches = context.lookup(nameAst->name, scope);
@@ -463,9 +468,7 @@ SignalSlotType CppModelManager::getSignalSlotType(const FilePath &filePath,
expression = expressionUnderCursor(cursor); expression = expressionUnderCursor(cursor);
const int argumentPosition = argumentPositionOf(path.last(), callAst); if (expression.endsWith(QLatin1String("SIGNAL"))
if ((expression.endsWith(QLatin1String("SIGNAL"))
&& (argumentPosition == 2 || argumentPosition == 4))
|| (expression.endsWith(QLatin1String("SLOT")) && argumentPosition == 4)) || (expression.endsWith(QLatin1String("SLOT")) && argumentPosition == 4))
return SignalSlotType::OldStyleSignal; return SignalSlotType::OldStyleSignal;

View File

@@ -5247,10 +5247,12 @@ ExtractFunction::ExtractFunction(FunctionNameGetter functionNameGetter)
void ExtractFunction::match(const CppQuickFixInterface &interface, QuickFixOperations &result) void ExtractFunction::match(const CppQuickFixInterface &interface, QuickFixOperations &result)
{ {
const CppRefactoringFilePtr file = interface.currentFile(); const CppRefactoringFilePtr file = interface.currentFile();
if (CppModelManager::usesClangd(file->editor()->textDocument())
&& file->cppDocument()->languageFeatures().cxxEnabled) { // TODO: Fix upstream and uncomment; see QTCREATORBUG-28030.
return; // if (CppModelManager::usesClangd(file->editor()->textDocument())
} // && file->cppDocument()->languageFeatures().cxxEnabled) {
// return;
// }
QTextCursor cursor = file->cursor(); QTextCursor cursor = file->cursor();
if (!cursor.hasSelection()) if (!cursor.hasSelection())

View File

@@ -283,7 +283,17 @@ public:
QString m_displayName; QString m_displayName;
LanguageFilter m_languagFilter; LanguageFilter m_languagFilter;
QJsonObject m_initializationOptions; QJsonObject m_initializationOptions;
QMap<TextEditor::TextDocument *, QString> m_openedDocument; class OpenedDocument
{
public:
~OpenedDocument()
{
QObject::disconnect(contentsChangedConnection);
}
QMetaObject::Connection contentsChangedConnection;
QString documentContents;
};
QMap<TextEditor::TextDocument *, OpenedDocument> m_openedDocument;
// Used for build system artifacts (e.g. UI headers) that Qt Creator "live-generates" ahead of // Used for build system artifacts (e.g. UI headers) that Qt Creator "live-generates" ahead of
// the build. // the build.
@@ -618,8 +628,11 @@ void Client::openDocument(TextEditor::TextDocument *document)
} }
} }
d->m_openedDocument[document] = document->plainText(); d->m_openedDocument[document].documentContents = document->plainText();
connect(document, &TextDocument::contentsChangedWithPosition, this, d->m_openedDocument[document].contentsChangedConnection
= connect(document,
&TextDocument::contentsChangedWithPosition,
this,
[this, document](int position, int charsRemoved, int charsAdded) { [this, document](int position, int charsRemoved, int charsAdded) {
documentContentsChanged(document, position, charsRemoved, charsAdded); documentContentsChanged(document, position, charsRemoved, charsAdded);
}); });
@@ -1083,7 +1096,7 @@ void Client::documentContentsChanged(TextEditor::TextDocument *document,
} }
} }
if (append) { if (append) {
QTextDocument oldDoc(d->m_openedDocument[document]); QTextDocument oldDoc(d->m_openedDocument[document].documentContents);
QTextCursor cursor(&oldDoc); QTextCursor cursor(&oldDoc);
// Workaround https://bugreports.qt.io/browse/QTBUG-80662 // Workaround https://bugreports.qt.io/browse/QTBUG-80662
// The contentsChanged gives a character count that can be wrong for QTextCursor // The contentsChanged gives a character count that can be wrong for QTextCursor
@@ -1104,7 +1117,7 @@ void Client::documentContentsChanged(TextEditor::TextDocument *document,
d->m_documentsToUpdate[document] = { d->m_documentsToUpdate[document] = {
DidChangeTextDocumentParams::TextDocumentContentChangeEvent(document->plainText())}; DidChangeTextDocumentParams::TextDocumentContentChangeEvent(document->plainText())};
} }
d->m_openedDocument[document] = document->plainText(); d->m_openedDocument[document].documentContents = document->plainText();
} }
++d->m_documentVersions[document->filePath()]; ++d->m_documentVersions[document->filePath()];
@@ -1532,8 +1545,6 @@ bool ClientPrivate::reset()
m_dynamicCapabilities.reset(); m_dynamicCapabilities.reset();
if (m_diagnosticManager) if (m_diagnosticManager)
m_diagnosticManager->clearDiagnostics(); m_diagnosticManager->clearDiagnostics();
for (auto it = m_openedDocument.cbegin(); it != m_openedDocument.cend(); ++it)
it.key()->disconnect(this);
m_openedDocument.clear(); m_openedDocument.clear();
// temporary container needed since m_resetAssistProvider is changed in resetAssistProviders // temporary container needed since m_resetAssistProvider is changed in resetAssistProviders
for (TextEditor::TextDocument *document : m_resetAssistProvider.keys()) for (TextEditor::TextDocument *document : m_resetAssistProvider.keys())
@@ -1544,7 +1555,8 @@ bool ClientPrivate::reset()
qDeleteAll(m_documentHighlightsTimer); qDeleteAll(m_documentHighlightsTimer);
m_documentHighlightsTimer.clear(); m_documentHighlightsTimer.clear();
m_progressManager.reset(); m_progressManager.reset();
m_shadowDocuments.clear(); for (auto &doc : m_shadowDocuments)
doc.second.clear();
m_documentVersions.clear(); m_documentVersions.clear();
return true; return true;
} }

View File

@@ -117,13 +117,13 @@ public:
if (python.exists()) if (python.exists())
PyLSConfigureAssistant::openDocumentWithPython(python, this); PyLSConfigureAssistant::openDocumentWithPython(python, this);
}); });
connect(this, &PythonDocument::openFinishedSuccessfully,
this, &PythonDocument::checkForPyls);
} }
void setFilePath(const FilePath &filePath) override void checkForPyls()
{ {
TextEditor::TextDocument::setFilePath(filePath); const FilePath &python = detectPython(filePath());
const FilePath &python = detectPython(filePath);
if (!python.exists()) if (!python.exists())
return; return;

View File

@@ -595,7 +595,7 @@ extend_qtc_plugin(QmlDesigner
easingcurve.cpp easingcurve.h easingcurve.cpp easingcurve.h
easingcurvedialog.cpp easingcurvedialog.h easingcurvedialog.cpp easingcurvedialog.h
preseteditor.cpp preseteditor.h preseteditor.cpp preseteditor.h
setframevaluedialog.cpp setframevaluedialog.h setframevaluedialog.ui setframevaluedialog.cpp setframevaluedialog.h
splineeditor.cpp splineeditor.h splineeditor.cpp splineeditor.h
timeline.qrc timeline.qrc
timelineabstracttool.cpp timelineabstracttool.h timelineabstracttool.cpp timelineabstracttool.h

View File

@@ -129,11 +129,13 @@ void DesignerActionManager::polishActions() const
Core::Context qmlDesignerFormEditorContext(Constants::C_QMLFORMEDITOR); Core::Context qmlDesignerFormEditorContext(Constants::C_QMLFORMEDITOR);
Core::Context qmlDesignerEditor3DContext(Constants::C_QMLEDITOR3D); Core::Context qmlDesignerEditor3DContext(Constants::C_QMLEDITOR3D);
Core::Context qmlDesignerNavigatorContext(Constants::C_QMLNAVIGATOR); Core::Context qmlDesignerNavigatorContext(Constants::C_QMLNAVIGATOR);
Core::Context qmlDesignerMaterialBrowserContext(Constants::C_QMLMATERIALBROWSER);
Core::Context qmlDesignerUIContext; Core::Context qmlDesignerUIContext;
qmlDesignerUIContext.add(qmlDesignerFormEditorContext); qmlDesignerUIContext.add(qmlDesignerFormEditorContext);
qmlDesignerUIContext.add(qmlDesignerEditor3DContext); qmlDesignerUIContext.add(qmlDesignerEditor3DContext);
qmlDesignerUIContext.add(qmlDesignerNavigatorContext); qmlDesignerUIContext.add(qmlDesignerNavigatorContext);
qmlDesignerUIContext.add(qmlDesignerMaterialBrowserContext);
for (auto *action : actions) { for (auto *action : actions) {
if (!action->menuId().isEmpty()) { if (!action->menuId().isEmpty()) {

View File

@@ -130,6 +130,8 @@ public:
listView, listView,
lockOff, lockOff,
lockOn, lockOn,
materialPreviewEnvironment,
materialPreviewModel,
mergeCells, mergeCells,
minus, minus,
mirror, mirror,

View File

@@ -85,7 +85,7 @@ void ColorControl::mouseReleaseEvent(QMouseEvent *event)
event->accept(); event->accept();
if (color != m_color) { if (color.isValid() && color != m_color) {
m_color = color; m_color = color;
update(); update();
emit valueChanged(); emit valueChanged();

View File

@@ -27,7 +27,10 @@
#include "curveitem.h" #include "curveitem.h"
#include "handleitem.h" #include "handleitem.h"
#include <QApplication>
#include <QPainter> #include <QPainter>
#include <qnamespace.h>
#include <QGraphicsSceneMouseEvent>
#include <cmath> #include <cmath>
@@ -452,10 +455,22 @@ QVariant KeyframeItem::itemChange(QGraphicsItem::GraphicsItemChange change, cons
lseg.moveRightTo(position); lseg.moveRightTo(position);
rseg.moveLeftTo(position); rseg.moveLeftTo(position);
if (legalLeft() && legalRight()) if (legalLeft() && legalRight()) {
m_validPos = position; if (qApp->keyboardModifiers().testFlag(Qt::ShiftModifier) && m_validPos.has_value()) {
if (m_firstPos) {
auto firstToNow = QLineF(*m_firstPos, position);
if (std::abs(firstToNow.dx()) > std::abs(firstToNow.dy()))
m_validPos = QPointF(position.x(), m_firstPos->y());
else
m_validPos = QPointF(m_firstPos->x(), position.y());
}
return QVariant(m_transform.map(m_validPos)); } else {
m_validPos = position;
}
}
return QVariant(m_transform.map(*m_validPos));
} }
} }
} }
@@ -465,6 +480,11 @@ QVariant KeyframeItem::itemChange(QGraphicsItem::GraphicsItemChange change, cons
void KeyframeItem::mousePressEvent(QGraphicsSceneMouseEvent *event) void KeyframeItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{ {
bool ok;
m_firstPos = m_transform.inverted(&ok).map(event->scenePos());
if (!ok)
m_firstPos = Utils::nullopt;
SelectableItem::mousePressEvent(event); SelectableItem::mousePressEvent(event);
if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(parentItem())) if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(parentItem()))
curveItem->setHandleVisibility(false); curveItem->setHandleVisibility(false);
@@ -472,6 +492,7 @@ void KeyframeItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
void KeyframeItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) void KeyframeItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{ {
m_firstPos = Utils::nullopt;
SelectableItem::mouseReleaseEvent(event); SelectableItem::mouseReleaseEvent(event);
if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(parentItem())) if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(parentItem()))
curveItem->setHandleVisibility(true); curveItem->setHandleVisibility(true);

View File

@@ -30,6 +30,8 @@
#include "keyframe.h" #include "keyframe.h"
#include "selectableitem.h" #include "selectableitem.h"
#include <utils/optional.h>
#include <QGraphicsObject> #include <QGraphicsObject>
namespace QmlDesigner { namespace QmlDesigner {
@@ -133,7 +135,8 @@ private:
HandleItem *m_right; HandleItem *m_right;
QPointF m_validPos; Utils::optional< QPointF > m_firstPos;
Utils::optional< QPointF > m_validPos;
bool m_visibleOverride = true; bool m_visibleOverride = true;

View File

@@ -24,9 +24,13 @@
****************************************************************************/ ****************************************************************************/
#include "materialbrowsermodel.h" #include "materialbrowsermodel.h"
#include "variantproperty.h"
#include <bindingproperty.h>
#include <designmodewidget.h> #include <designmodewidget.h>
#include <qmldesignerplugin.h> #include <qmldesignerplugin.h>
#include <qmlobjectnode.h>
#include "variantproperty.h"
#include "utils/qtcassert.h"
namespace QmlDesigner { namespace QmlDesigner {
@@ -46,24 +50,27 @@ int MaterialBrowserModel::rowCount(const QModelIndex &) const
QVariant MaterialBrowserModel::data(const QModelIndex &index, int role) const QVariant MaterialBrowserModel::data(const QModelIndex &index, int role) const
{ {
if (!index.isValid() || index.row() >= m_materialList.count()) { QTC_ASSERT(index.isValid() && index.row() < m_materialList.count(), return {});
qWarning() << Q_FUNC_INFO << "invalid index requested"; QTC_ASSERT(roleNames().contains(role), return {});
return {};
}
if (roleNames().value(role) == "materialName") { QByteArray roleName = roleNames().value(role);
if (roleName == "materialName") {
QVariant objName = m_materialList.at(index.row()).variantProperty("objectName").value(); QVariant objName = m_materialList.at(index.row()).variantProperty("objectName").value();
return objName.isValid() ? objName : ""; return objName.isValid() ? objName : "";
} }
if (roleNames().value(role) == "materialInternalId") if (roleName == "materialInternalId")
return m_materialList.at(index.row()).internalId(); return m_materialList.at(index.row()).internalId();
if (roleNames().value(role) == "materialVisible") if (roleName == "materialVisible")
return isMaterialVisible(index.row()); return isMaterialVisible(index.row());
if (!roleNames().contains(role)) if (roleName == "materialType") {
qWarning() << Q_FUNC_INFO << "invalid role requested"; QString matType = QString::fromLatin1(m_materialList.at(index.row()).type());
if (matType.startsWith("QtQuick3D."))
matType.remove("QtQuick3D.");
return matType;
}
return {}; return {};
} }
@@ -82,12 +89,57 @@ bool MaterialBrowserModel::isValidIndex(int idx) const
return idx > -1 && idx < rowCount(); return idx > -1 && idx < rowCount();
} }
/**
* @brief Loads and parses propertyGroups.json from QtQuick3D module's designer folder
*
* propertyGroups.json contains lists of QtQuick3D objects' properties grouped by sections
*
* @param path path to propertyGroups.json file
*/
void MaterialBrowserModel::loadPropertyGroups(const QString &path)
{
bool ok = true;
if (m_propertyGroupsObj.isEmpty()) {
QFile matPropsFile(path);
if (!matPropsFile.open(QIODevice::ReadOnly)) {
qWarning("Couldn't open propertyGroups.json");
ok = false;
}
if (ok) {
QJsonDocument matPropsJsonDoc = QJsonDocument::fromJson(matPropsFile.readAll());
if (matPropsJsonDoc.isNull()) {
qWarning("Invalid propertyGroups.json file");
ok = false;
} else {
m_propertyGroupsObj = matPropsJsonDoc.object();
}
}
}
m_defaultMaterialSections.clear();
m_principledMaterialSections.clear();
m_customMaterialSections.clear();
if (ok) {
m_defaultMaterialSections.append(m_propertyGroupsObj.value("DefaultMaterial").toObject().keys());
m_principledMaterialSections.append(m_propertyGroupsObj.value("PrincipledMaterial").toObject().keys());
QStringList customMatSections = m_propertyGroupsObj.value("CustomMaterial").toObject().keys();
if (customMatSections.size() > 1) // as of now custom material has only 1 section, so we don't add it
m_customMaterialSections.append(customMatSections);
}
emit materialSectionsChanged();
}
QHash<int, QByteArray> MaterialBrowserModel::roleNames() const QHash<int, QByteArray> MaterialBrowserModel::roleNames() const
{ {
static const QHash<int, QByteArray> roles { static const QHash<int, QByteArray> roles {
{Qt::UserRole + 1, "materialName"}, {Qt::UserRole + 1, "materialName"},
{Qt::UserRole + 2, "materialInternalId"}, {Qt::UserRole + 2, "materialInternalId"},
{Qt::UserRole + 3, "materialVisible"}, {Qt::UserRole + 3, "materialVisible"},
{Qt::UserRole + 4, "materialType"}
}; };
return roles; return roles;
} }
@@ -120,6 +172,34 @@ void MaterialBrowserModel::setHasModelSelection(bool b)
emit hasModelSelectionChanged(); emit hasModelSelectionChanged();
} }
bool MaterialBrowserModel::hasMaterialRoot() const
{
return m_hasMaterialRoot;
}
void MaterialBrowserModel::setHasMaterialRoot(bool b)
{
if (m_hasMaterialRoot == b)
return;
m_hasMaterialRoot = b;
emit hasMaterialRootChanged();
}
QString MaterialBrowserModel::copiedMaterialType() const
{
return m_copiedMaterialType;
}
void MaterialBrowserModel::setCopiedMaterialType(const QString &matType)
{
if (matType == m_copiedMaterialType)
return;
m_copiedMaterialType = matType;
emit copiedMaterialTypeChanged();
}
QList<ModelNode> MaterialBrowserModel::materials() const QList<ModelNode> MaterialBrowserModel::materials() const
{ {
return m_materialList; return m_materialList;
@@ -201,6 +281,12 @@ void MaterialBrowserModel::removeMaterial(const ModelNode &material)
} }
} }
void MaterialBrowserModel::deleteSelectedMaterial()
{
if (isValidIndex(m_selectedIndex))
m_materialList[m_selectedIndex].destroy();
}
void MaterialBrowserModel::updateSelectedMaterial() void MaterialBrowserModel::updateSelectedMaterial()
{ {
selectMaterial(m_selectedIndex, true); selectMaterial(m_selectedIndex, true);
@@ -256,6 +342,42 @@ void MaterialBrowserModel::duplicateMaterial(int idx)
emit duplicateMaterialTriggered(m_materialList.at(idx)); emit duplicateMaterialTriggered(m_materialList.at(idx));
} }
void MaterialBrowserModel::copyMaterialProperties(int idx, const QString &section)
{
ModelNode mat = m_materialList.at(idx);
QString matType = QString::fromLatin1(mat.type());
if (matType.startsWith("QtQuick3D."))
matType.remove("QtQuick3D.");
setCopiedMaterialType(matType);
m_allPropsCopied = section == "All";
if (m_allPropsCopied || m_propertyGroupsObj.empty()) {
m_copiedMaterialProps = mat.properties();
} else {
QJsonObject propsSpecObj = m_propertyGroupsObj.value(m_copiedMaterialType).toObject();
if (propsSpecObj.contains(section)) { // should always be true
m_copiedMaterialProps.clear();
const QJsonArray propNames = propsSpecObj.value(section).toArray();
for (const QJsonValueRef &propName : propNames)
m_copiedMaterialProps.append(mat.property(propName.toString().toLatin1()));
if (section == "Base") { // add QtQuick3D.Material base props as well
QJsonObject propsMatObj = m_propertyGroupsObj.value("Material").toObject();
const QJsonArray propNames = propsMatObj.value("Base").toArray();
for (const QJsonValueRef &propName : propNames)
m_copiedMaterialProps.append(mat.property(propName.toString().toLatin1()));
}
}
}
}
void MaterialBrowserModel::pasteMaterialProperties(int idx)
{
emit pasteMaterialPropertiesTriggered(m_materialList.at(idx), m_copiedMaterialProps, m_allPropsCopied);
}
void MaterialBrowserModel::deleteMaterial(int idx) void MaterialBrowserModel::deleteMaterial(int idx)
{ {
m_materialList[idx].destroy(); m_materialList[idx].destroy();

View File

@@ -25,7 +25,9 @@
#pragma once #pragma once
#include "qjsonobject.h"
#include <modelnode.h> #include <modelnode.h>
#include <qmlobjectnode.h>
#include <QAbstractListModel> #include <QAbstractListModel>
#include <QObject> #include <QObject>
@@ -41,6 +43,11 @@ class MaterialBrowserModel : public QAbstractListModel
Q_PROPERTY(int selectedIndex MEMBER m_selectedIndex NOTIFY selectedIndexChanged) Q_PROPERTY(int selectedIndex MEMBER m_selectedIndex NOTIFY selectedIndexChanged)
Q_PROPERTY(bool hasQuick3DImport READ hasQuick3DImport WRITE setHasQuick3DImport NOTIFY hasQuick3DImportChanged) Q_PROPERTY(bool hasQuick3DImport READ hasQuick3DImport WRITE setHasQuick3DImport NOTIFY hasQuick3DImportChanged)
Q_PROPERTY(bool hasModelSelection READ hasModelSelection WRITE setHasModelSelection NOTIFY hasModelSelectionChanged) Q_PROPERTY(bool hasModelSelection READ hasModelSelection WRITE setHasModelSelection NOTIFY hasModelSelectionChanged)
Q_PROPERTY(bool hasMaterialRoot READ hasMaterialRoot WRITE setHasMaterialRoot NOTIFY hasMaterialRootChanged)
Q_PROPERTY(QString copiedMaterialType READ copiedMaterialType WRITE setCopiedMaterialType NOTIFY copiedMaterialTypeChanged)
Q_PROPERTY(QStringList defaultMaterialSections MEMBER m_defaultMaterialSections NOTIFY materialSectionsChanged)
Q_PROPERTY(QStringList principledMaterialSections MEMBER m_principledMaterialSections NOTIFY materialSectionsChanged)
Q_PROPERTY(QStringList customMaterialSections MEMBER m_customMaterialSections NOTIFY materialSectionsChanged)
public: public:
MaterialBrowserModel(QObject *parent = nullptr); MaterialBrowserModel(QObject *parent = nullptr);
@@ -58,18 +65,28 @@ public:
bool hasModelSelection() const; bool hasModelSelection() const;
void setHasModelSelection(bool b); void setHasModelSelection(bool b);
bool hasMaterialRoot() const;
void setHasMaterialRoot(bool b);
QString copiedMaterialType() const;
void setCopiedMaterialType(const QString &matType);
QList<ModelNode> materials() const; QList<ModelNode> materials() const;
void setMaterials(const QList<ModelNode> &materials, bool hasQuick3DImport); void setMaterials(const QList<ModelNode> &materials, bool hasQuick3DImport);
void removeMaterial(const ModelNode &material); void removeMaterial(const ModelNode &material);
void deleteSelectedMaterial();
void updateMaterialName(const ModelNode &material); void updateMaterialName(const ModelNode &material);
void updateSelectedMaterial(); void updateSelectedMaterial();
int materialIndex(const ModelNode &material) const; int materialIndex(const ModelNode &material) const;
ModelNode materialAt(int idx) const; ModelNode materialAt(int idx) const;
void loadPropertyGroups(const QString &path);
void resetModel(); void resetModel();
Q_INVOKABLE void selectMaterial(int idx, bool force = false); Q_INVOKABLE void selectMaterial(int idx, bool force = false);
Q_INVOKABLE void duplicateMaterial(int idx); Q_INVOKABLE void duplicateMaterial(int idx);
Q_INVOKABLE void copyMaterialProperties(int idx, const QString &section);
Q_INVOKABLE void pasteMaterialProperties(int idx);
Q_INVOKABLE void deleteMaterial(int idx); Q_INVOKABLE void deleteMaterial(int idx);
Q_INVOKABLE void renameMaterial(int idx, const QString &newName); Q_INVOKABLE void renameMaterial(int idx, const QString &newName);
Q_INVOKABLE void addNewMaterial(); Q_INVOKABLE void addNewMaterial();
@@ -80,11 +97,17 @@ signals:
void isEmptyChanged(); void isEmptyChanged();
void hasQuick3DImportChanged(); void hasQuick3DImportChanged();
void hasModelSelectionChanged(); void hasModelSelectionChanged();
void hasMaterialRootChanged();
void copiedMaterialTypeChanged();
void materialSectionsChanged();
void selectedIndexChanged(int idx); void selectedIndexChanged(int idx);
void renameMaterialTriggered(const QmlDesigner::ModelNode &material, const QString &newName); void renameMaterialTriggered(const QmlDesigner::ModelNode &material, const QString &newName);
void applyToSelectedTriggered(const QmlDesigner::ModelNode &material, bool add = false); void applyToSelectedTriggered(const QmlDesigner::ModelNode &material, bool add = false);
void addNewMaterialTriggered(); void addNewMaterialTriggered();
void duplicateMaterialTriggered(const QmlDesigner::ModelNode &material); void duplicateMaterialTriggered(const QmlDesigner::ModelNode &material);
void pasteMaterialPropertiesTriggered(const QmlDesigner::ModelNode &material,
const QList<QmlDesigner::AbstractProperty> &props,
bool all);
private: private:
bool isMaterialVisible(int idx) const; bool isMaterialVisible(int idx) const;
@@ -92,12 +115,20 @@ private:
QString m_searchText; QString m_searchText;
QList<ModelNode> m_materialList; QList<ModelNode> m_materialList;
QStringList m_defaultMaterialSections;
QStringList m_principledMaterialSections;
QStringList m_customMaterialSections;
QList<AbstractProperty> m_copiedMaterialProps;
QHash<qint32, int> m_materialIndexHash; // internalId -> index QHash<qint32, int> m_materialIndexHash; // internalId -> index
QJsonObject m_propertyGroupsObj;
int m_selectedIndex = 0; int m_selectedIndex = 0;
bool m_isEmpty = true; bool m_isEmpty = true;
bool m_hasQuick3DImport = false; bool m_hasQuick3DImport = false;
bool m_hasModelSelection = false; bool m_hasModelSelection = false;
bool m_hasMaterialRoot = false;
bool m_allPropsCopied = true;
QString m_copiedMaterialType;
}; };
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -24,12 +24,17 @@
****************************************************************************/ ****************************************************************************/
#include "materialbrowserview.h" #include "materialbrowserview.h"
#include "bindingproperty.h"
#include "materialbrowserwidget.h" #include "materialbrowserwidget.h"
#include "materialbrowsermodel.h" #include "materialbrowsermodel.h"
#include "nodeabstractproperty.h" #include "nodeabstractproperty.h"
#include "nodemetainfo.h"
#include "qmlobjectnode.h" #include "qmlobjectnode.h"
#include "variantproperty.h" #include "variantproperty.h"
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <designmodecontext.h>
#include <nodeinstanceview.h> #include <nodeinstanceview.h>
#include <qmldesignerconstants.h> #include <qmldesignerconstants.h>
@@ -39,7 +44,6 @@ namespace QmlDesigner {
MaterialBrowserView::MaterialBrowserView(QObject *parent) MaterialBrowserView::MaterialBrowserView(QObject *parent)
: AbstractView(parent) : AbstractView(parent)
{} {}
MaterialBrowserView::~MaterialBrowserView() MaterialBrowserView::~MaterialBrowserView()
@@ -53,7 +57,11 @@ bool MaterialBrowserView::hasWidget() const
WidgetInfo MaterialBrowserView::widgetInfo() WidgetInfo MaterialBrowserView::widgetInfo()
{ {
if (m_widget.isNull()) { if (m_widget.isNull()) {
m_widget = new MaterialBrowserWidget; m_widget = new MaterialBrowserWidget(this);
auto matEditorContext = new Internal::MaterialBrowserContext(m_widget.data());
Core::ICore::addContextObject(matEditorContext);
MaterialBrowserModel *matBrowserModel = m_widget->materialBrowserModel().data(); MaterialBrowserModel *matBrowserModel = m_widget->materialBrowserModel().data();
// custom notifications below are sent to the MaterialEditor // custom notifications below are sent to the MaterialEditor
@@ -81,6 +89,32 @@ WidgetInfo MaterialBrowserView::widgetInfo()
[&] (const ModelNode &material) { [&] (const ModelNode &material) {
emitCustomNotification("duplicate_material", {material}); emitCustomNotification("duplicate_material", {material});
}); });
connect(matBrowserModel, &MaterialBrowserModel::pasteMaterialPropertiesTriggered, this,
[&] (const ModelNode &material, const QList<AbstractProperty> &props, bool all) {
QmlObjectNode mat(material);
executeInTransaction(__FUNCTION__, [&] {
if (all) { // all material properties copied
// remove current properties
const PropertyNameList propNames = material.propertyNames();
for (const PropertyName &propName : propNames) {
if (propName != "objectName")
mat.removeProperty(propName);
}
}
// apply pasted properties
for (const AbstractProperty &prop : props) {
if (prop.name() == "objectName")
continue;
if (prop.isVariantProperty())
mat.setVariantProperty(prop.name(), prop.toVariantProperty().value());
else if (prop.isBindingProperty())
mat.setBindingProperty(prop.name(), prop.toBindingProperty().expression());
}
});
});
} }
return createWidgetInfo(m_widget.data(), return createWidgetInfo(m_widget.data(),
@@ -94,7 +128,12 @@ void MaterialBrowserView::modelAttached(Model *model)
{ {
AbstractView::modelAttached(model); AbstractView::modelAttached(model);
QString matPropsPath = model->metaInfo("QtQuick3D.Material").importDirectoryPath()
+ "/designer/propertyGroups.json";
m_widget->materialBrowserModel()->loadPropertyGroups(matPropsPath);
m_widget->clearSearchFilter(); m_widget->clearSearchFilter();
m_widget->materialBrowserModel()->setHasMaterialRoot(rootModelNode().isSubclassOf("QtQuick3D.Material"));
m_hasQuick3DImport = model->hasImport("QtQuick3D"); m_hasQuick3DImport = model->hasImport("QtQuick3D");
// Project load is already very busy and may even trigger puppet reset, so let's wait a moment // Project load is already very busy and may even trigger puppet reset, so let's wait a moment
@@ -130,7 +169,7 @@ void MaterialBrowserView::refreshModel(bool updateImages)
bool MaterialBrowserView::isMaterial(const ModelNode &node) const bool MaterialBrowserView::isMaterial(const ModelNode &node) const
{ {
if (!node.isValid() || node.isComponent()) if (!node.isValid())
return false; return false;
return node.isSubclassOf("QtQuick3D.Material"); return node.isSubclassOf("QtQuick3D.Material");
@@ -273,6 +312,12 @@ void MaterialBrowserView::customNotification(const AbstractView *view,
int idx = m_widget->materialBrowserModel()->materialIndex(nodeList.first()); int idx = m_widget->materialBrowserModel()->materialIndex(nodeList.first());
if (idx != -1) if (idx != -1)
m_widget->materialBrowserModel()->selectMaterial(idx); m_widget->materialBrowserModel()->selectMaterial(idx);
} else if (identifier == "refresh_material_browser") {
QTimer::singleShot(0, this, [this]() {
refreshModel(true);
});
} else if (identifier == "delete_selected_material") {
m_widget->materialBrowserModel()->deleteSelectedMaterial();
} }
} }

View File

@@ -25,6 +25,7 @@
#include "materialbrowserwidget.h" #include "materialbrowserwidget.h"
#include "materialbrowsermodel.h" #include "materialbrowsermodel.h"
#include "materialbrowserview.h"
#include <theme.h> #include <theme.h>
@@ -130,14 +131,20 @@ bool MaterialBrowserWidget::eventFilter(QObject *obj, QEvent *event)
return QObject::eventFilter(obj, event); return QObject::eventFilter(obj, event);
} }
MaterialBrowserWidget::MaterialBrowserWidget() MaterialBrowserWidget::MaterialBrowserWidget(MaterialBrowserView *view)
: m_materialBrowserModel(new MaterialBrowserModel(this)) : m_materialBrowserView(view)
, m_materialBrowserModel(new MaterialBrowserModel(this))
, m_quickWidget(new QQuickWidget(this)) , m_quickWidget(new QQuickWidget(this))
, m_previewImageProvider(new PreviewImageProvider()) , m_previewImageProvider(new PreviewImageProvider())
{ {
setWindowTitle(tr("Material Browser", "Title of material browser widget")); setWindowTitle(tr("Material Browser", "Title of material browser widget"));
setMinimumWidth(120); setMinimumWidth(120);
Core::Context context(Constants::C_QMLMATERIALBROWSER);
m_context = new Core::IContext(this);
m_context->setContext(context);
m_context->setWidget(this);
m_quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView); m_quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
m_quickWidget->engine()->addImportPath(propertyEditorResourcesPath() + "/imports"); m_quickWidget->engine()->addImportPath(propertyEditorResourcesPath() + "/imports");
m_quickWidget->setClearColor(Theme::getColor(Theme::Color::DSpanelBackground)); m_quickWidget->setClearColor(Theme::getColor(Theme::Color::DSpanelBackground));
@@ -182,6 +189,14 @@ QList<QToolButton *> MaterialBrowserWidget::createToolBarWidgets()
return {}; return {};
} }
void MaterialBrowserWidget::contextHelp(const Core::IContext::HelpCallback &callback) const
{
if (m_materialBrowserView)
m_materialBrowserView->contextHelp(callback);
else
callback({});
}
void MaterialBrowserWidget::handleSearchfilterChanged(const QString &filterText) void MaterialBrowserWidget::handleSearchfilterChanged(const QString &filterText)
{ {
if (filterText != m_filterText) { if (filterText != m_filterText) {

View File

@@ -25,20 +25,19 @@
#pragma once #pragma once
#include "itemlibraryinfo.h"
#include "import.h"
#include "modelnode.h" #include "modelnode.h"
#include <utils/fancylineedit.h> #include <coreplugin/icontext.h>
#include <utils/dropsupport.h> #include <utils/dropsupport.h>
#include <utils/fancylineedit.h>
#include <QFrame>
#include <QToolButton>
#include <QFileIconProvider> #include <QFileIconProvider>
#include <QQuickWidget> #include <QFrame>
#include <QQmlPropertyMap>
#include <QTimer>
#include <QPointF> #include <QPointF>
#include <QQmlPropertyMap>
#include <QQuickWidget>
#include <QTimer>
#include <QToolButton>
#include <memory> #include <memory>
@@ -49,6 +48,7 @@ QT_END_NAMESPACE
namespace QmlDesigner { namespace QmlDesigner {
class MaterialBrowserView;
class MaterialBrowserModel; class MaterialBrowserModel;
class PreviewImageProvider; class PreviewImageProvider;
@@ -57,10 +57,11 @@ class MaterialBrowserWidget : public QFrame
Q_OBJECT Q_OBJECT
public: public:
MaterialBrowserWidget(); MaterialBrowserWidget(MaterialBrowserView *view);
~MaterialBrowserWidget() = default; ~MaterialBrowserWidget() = default;
QList<QToolButton *> createToolBarWidgets(); QList<QToolButton *> createToolBarWidgets();
void contextHelp(const Core::IContext::HelpCallback &callback) const;
static QString qmlSourcesPath(); static QString qmlSourcesPath();
void clearSearchFilter(); void clearSearchFilter();
@@ -80,11 +81,13 @@ private:
void reloadQmlSource(); void reloadQmlSource();
void updateSearch(); void updateSearch();
QPointer<MaterialBrowserView> m_materialBrowserView;
QPointer<MaterialBrowserModel> m_materialBrowserModel; QPointer<MaterialBrowserModel> m_materialBrowserModel;
QScopedPointer<QQuickWidget> m_quickWidget; QScopedPointer<QQuickWidget> m_quickWidget;
QShortcut *m_qmlSourceUpdateShortcut = nullptr; QShortcut *m_qmlSourceUpdateShortcut = nullptr;
PreviewImageProvider *m_previewImageProvider = nullptr; PreviewImageProvider *m_previewImageProvider = nullptr;
Core::IContext *m_context = nullptr;
QString m_filterText; QString m_filterText;

View File

@@ -32,6 +32,7 @@
#include <qmlmodelnodeproxy.h> #include <qmlmodelnodeproxy.h>
#include <qmlobjectnode.h> #include <qmlobjectnode.h>
#include <qmltimeline.h> #include <qmltimeline.h>
#include <documentmanager.h>
#include <coreplugin/messagebox.h> #include <coreplugin/messagebox.h>
#include <utils/algorithm.h> #include <utils/algorithm.h>
@@ -47,12 +48,24 @@
namespace QmlDesigner { namespace QmlDesigner {
MaterialEditorContextObject::MaterialEditorContextObject(QObject *parent) MaterialEditorContextObject::MaterialEditorContextObject(QQmlContext *context, QObject *parent)
: QObject(parent) : QObject(parent)
, m_qmlContext(context)
{ {
qmlRegisterUncreatableType<MaterialEditorContextObject>("ToolBarAction", 1, 0, "ToolBarAction", "Enum type"); qmlRegisterUncreatableType<MaterialEditorContextObject>("ToolBarAction", 1, 0, "ToolBarAction", "Enum type");
} }
QQmlComponent *MaterialEditorContextObject::specificQmlComponent()
{
if (m_specificQmlComponent)
return m_specificQmlComponent;
m_specificQmlComponent = new QQmlComponent(m_qmlContext->engine(), this);
m_specificQmlComponent->setData(m_specificQmlData.toUtf8(), QUrl::fromLocalFile("specifics.qml"));
return m_specificQmlComponent;
}
QString MaterialEditorContextObject::convertColorToString(const QVariant &color) QString MaterialEditorContextObject::convertColorToString(const QVariant &color)
{ {
QString colorString; QString colorString;
@@ -159,8 +172,10 @@ void MaterialEditorContextObject::changeTypeName(const QString &typeName)
msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
msgBox.setDefaultButton(QMessageBox::Ok); msgBox.setDefaultButton(QMessageBox::Ok);
if (msgBox.exec() == QMessageBox::Cancel) if (msgBox.exec() == QMessageBox::Cancel) {
updatePossibleTypeIndex();
return; return;
}
for (const auto &p : std::as_const(incompatibleProperties)) for (const auto &p : std::as_const(incompatibleProperties))
m_selectedMaterial.removeProperty(p); m_selectedMaterial.removeProperty(p);
@@ -234,6 +249,20 @@ void MaterialEditorContextObject::setHasQuick3DImport(bool b)
emit hasQuick3DImportChanged(); emit hasQuick3DImportChanged();
} }
bool MaterialEditorContextObject::hasMaterialRoot() const
{
return m_hasMaterialRoot;
}
void MaterialEditorContextObject::setHasMaterialRoot(bool b)
{
if (b == m_hasMaterialRoot)
return;
m_hasMaterialRoot = b;
emit hasMaterialRootChanged();
}
bool MaterialEditorContextObject::hasModelSelection() const bool MaterialEditorContextObject::hasModelSelection() const
{ {
return m_hasModelSelection; return m_hasModelSelection;
@@ -262,6 +291,20 @@ void MaterialEditorContextObject::setSpecificsUrl(const QUrl &newSpecificsUrl)
emit specificsUrlChanged(); emit specificsUrlChanged();
} }
void MaterialEditorContextObject::setSpecificQmlData(const QString &newSpecificQmlData)
{
if (newSpecificQmlData == m_specificQmlData)
return;
m_specificQmlData = newSpecificQmlData;
delete m_specificQmlComponent;
m_specificQmlComponent = nullptr;
emit specificQmlComponentChanged();
emit specificQmlDataChanged();
}
void MaterialEditorContextObject::setStateName(const QString &newStateName) void MaterialEditorContextObject::setStateName(const QString &newStateName)
{ {
if (newStateName == m_stateName) if (newStateName == m_stateName)
@@ -280,6 +323,23 @@ void MaterialEditorContextObject::setAllStateNames(const QStringList &allStates)
emit allStateNamesChanged(); emit allStateNamesChanged();
} }
void MaterialEditorContextObject::setPossibleTypes(const QStringList &types)
{
if (types == m_possibleTypes)
return;
m_possibleTypes = types;
emit possibleTypesChanged();
updatePossibleTypeIndex();
}
void MaterialEditorContextObject::setCurrentType(const QString &type)
{
m_currentType = type.split('.').last();
updatePossibleTypeIndex();
}
void MaterialEditorContextObject::setIsBaseState(bool newIsBaseState) void MaterialEditorContextObject::setIsBaseState(bool newIsBaseState)
{ {
if (newIsBaseState == m_isBaseState) if (newIsBaseState == m_isBaseState)
@@ -326,6 +386,20 @@ void MaterialEditorContextObject::setHasAliasExport(bool hasAliasExport)
emit hasAliasExportChanged(); emit hasAliasExportChanged();
} }
void MaterialEditorContextObject::updatePossibleTypeIndex()
{
int newIndex = -1;
if (!m_currentType.isEmpty())
newIndex = m_possibleTypes.indexOf(m_currentType);
// Emit valid possible type index change even if the index doesn't change, as currentIndex on
// QML side will change to default internally if model is updated
if (m_possibleTypeIndex != -1 || m_possibleTypeIndex != newIndex) {
m_possibleTypeIndex = newIndex;
emit possibleTypeIndexChanged();
}
}
void MaterialEditorContextObject::hideCursor() void MaterialEditorContextObject::hideCursor()
{ {
if (QApplication::overrideCursor()) if (QApplication::overrideCursor())
@@ -390,4 +464,10 @@ bool MaterialEditorContextObject::isBlocked(const QString &propName) const
return false; return false;
} }
void MaterialEditorContextObject::goIntoComponent()
{
QTC_ASSERT(m_model, return);
DocumentManager::goIntoComponent(m_selectedMaterial);
}
} // QmlDesigner } // QmlDesigner

View File

@@ -43,9 +43,13 @@ class MaterialEditorContextObject : public QObject
Q_OBJECT Q_OBJECT
Q_PROPERTY(QUrl specificsUrl READ specificsUrl WRITE setSpecificsUrl NOTIFY specificsUrlChanged) Q_PROPERTY(QUrl specificsUrl READ specificsUrl WRITE setSpecificsUrl NOTIFY specificsUrlChanged)
Q_PROPERTY(QString specificQmlData READ specificQmlData WRITE setSpecificQmlData NOTIFY specificQmlDataChanged)
Q_PROPERTY(QQmlComponent *specificQmlComponent READ specificQmlComponent NOTIFY specificQmlComponentChanged)
Q_PROPERTY(QString stateName READ stateName WRITE setStateName NOTIFY stateNameChanged) Q_PROPERTY(QString stateName READ stateName WRITE setStateName NOTIFY stateNameChanged)
Q_PROPERTY(QStringList allStateNames READ allStateNames WRITE setAllStateNames NOTIFY allStateNamesChanged) Q_PROPERTY(QStringList allStateNames READ allStateNames WRITE setAllStateNames NOTIFY allStateNamesChanged)
Q_PROPERTY(QStringList possibleTypes READ possibleTypes WRITE setPossibleTypes NOTIFY possibleTypesChanged)
Q_PROPERTY(int possibleTypeIndex READ possibleTypeIndex NOTIFY possibleTypeIndexChanged)
Q_PROPERTY(bool isBaseState READ isBaseState WRITE setIsBaseState NOTIFY isBaseStateChanged) Q_PROPERTY(bool isBaseState READ isBaseState WRITE setIsBaseState NOTIFY isBaseStateChanged)
Q_PROPERTY(bool selectionChanged READ selectionChanged WRITE setSelectionChanged NOTIFY selectionChangedChanged) Q_PROPERTY(bool selectionChanged READ selectionChanged WRITE setSelectionChanged NOTIFY selectionChangedChanged)
@@ -56,15 +60,20 @@ class MaterialEditorContextObject : public QObject
Q_PROPERTY(bool hasActiveTimeline READ hasActiveTimeline NOTIFY hasActiveTimelineChanged) Q_PROPERTY(bool hasActiveTimeline READ hasActiveTimeline NOTIFY hasActiveTimelineChanged)
Q_PROPERTY(bool hasQuick3DImport READ hasQuick3DImport WRITE setHasQuick3DImport NOTIFY hasQuick3DImportChanged) Q_PROPERTY(bool hasQuick3DImport READ hasQuick3DImport WRITE setHasQuick3DImport NOTIFY hasQuick3DImportChanged)
Q_PROPERTY(bool hasModelSelection READ hasModelSelection WRITE setHasModelSelection NOTIFY hasModelSelectionChanged) Q_PROPERTY(bool hasModelSelection READ hasModelSelection WRITE setHasModelSelection NOTIFY hasModelSelectionChanged)
Q_PROPERTY(bool hasMaterialRoot READ hasMaterialRoot WRITE setHasMaterialRoot NOTIFY hasMaterialRootChanged)
Q_PROPERTY(QQmlPropertyMap *backendValues READ backendValues WRITE setBackendValues NOTIFY backendValuesChanged) Q_PROPERTY(QQmlPropertyMap *backendValues READ backendValues WRITE setBackendValues NOTIFY backendValuesChanged)
public: public:
MaterialEditorContextObject(QObject *parent = nullptr); MaterialEditorContextObject(QQmlContext *context, QObject *parent = nullptr);
QUrl specificsUrl() const { return m_specificsUrl; } QUrl specificsUrl() const { return m_specificsUrl; }
QString specificQmlData() const {return m_specificQmlData; }
QQmlComponent *specificQmlComponent();
QString stateName() const { return m_stateName; } QString stateName() const { return m_stateName; }
QStringList allStateNames() const { return m_allStateNames; } QStringList allStateNames() const { return m_allStateNames; }
QStringList possibleTypes() const { return m_possibleTypes; }
int possibleTypeIndex() const { return m_possibleTypeIndex; }
bool isBaseState() const { return m_isBaseState; } bool isBaseState() const { return m_isBaseState; }
bool selectionChanged() const { return m_selectionChanged; } bool selectionChanged() const { return m_selectionChanged; }
@@ -86,6 +95,7 @@ public:
Q_INVOKABLE QStringList allStatesForId(const QString &id); Q_INVOKABLE QStringList allStatesForId(const QString &id);
Q_INVOKABLE bool isBlocked(const QString &propName) const; Q_INVOKABLE bool isBlocked(const QString &propName) const;
Q_INVOKABLE void goIntoComponent();
enum ToolBarAction { enum ToolBarAction {
ApplyToSelected = 0, ApplyToSelected = 0,
@@ -105,6 +115,9 @@ public:
bool hasQuick3DImport() const; bool hasQuick3DImport() const;
void setHasQuick3DImport(bool b); void setHasQuick3DImport(bool b);
bool hasMaterialRoot() const;
void setHasMaterialRoot(bool b);
bool hasModelSelection() const; bool hasModelSelection() const;
void setHasModelSelection(bool b); void setHasModelSelection(bool b);
@@ -113,8 +126,11 @@ public:
void setSelectedMaterial(const ModelNode &matNode); void setSelectedMaterial(const ModelNode &matNode);
void setSpecificsUrl(const QUrl &newSpecificsUrl); void setSpecificsUrl(const QUrl &newSpecificsUrl);
void setSpecificQmlData(const QString &newSpecificQmlData);
void setStateName(const QString &newStateName); void setStateName(const QString &newStateName);
void setAllStateNames(const QStringList &allStates); void setAllStateNames(const QStringList &allStates);
void setPossibleTypes(const QStringList &types);
void setCurrentType(const QString &type);
void setIsBaseState(bool newIsBaseState); void setIsBaseState(bool newIsBaseState);
void setSelectionChanged(bool newSelectionChanged); void setSelectionChanged(bool newSelectionChanged);
void setBackendValues(QQmlPropertyMap *newBackendValues); void setBackendValues(QQmlPropertyMap *newBackendValues);
@@ -125,8 +141,12 @@ public:
signals: signals:
void specificsUrlChanged(); void specificsUrlChanged();
void specificQmlDataChanged();
void specificQmlComponentChanged();
void stateNameChanged(); void stateNameChanged();
void allStateNamesChanged(); void allStateNamesChanged();
void possibleTypesChanged();
void possibleTypeIndexChanged();
void isBaseStateChanged(); void isBaseStateChanged();
void selectionChangedChanged(); void selectionChangedChanged();
void backendValuesChanged(); void backendValuesChanged();
@@ -134,18 +154,26 @@ signals:
void hasAliasExportChanged(); void hasAliasExportChanged();
void hasActiveTimelineChanged(); void hasActiveTimelineChanged();
void hasQuick3DImportChanged(); void hasQuick3DImportChanged();
void hasMaterialRootChanged();
void hasModelSelectionChanged(); void hasModelSelectionChanged();
private: private:
void updatePossibleTypeIndex();
QUrl m_specificsUrl; QUrl m_specificsUrl;
QString m_specificQmlData;
QQmlComponent *m_specificQmlComponent = nullptr;
QQmlContext *m_qmlContext = nullptr;
QString m_stateName; QString m_stateName;
QStringList m_allStateNames; QStringList m_allStateNames;
QStringList m_possibleTypes;
int m_possibleTypeIndex = -1;
QString m_currentType;
int m_majorVersion = 1; int m_majorVersion = 1;
QQmlPropertyMap *m_backendValues = nullptr; QQmlPropertyMap *m_backendValues = nullptr;
QQmlComponent *m_qmlComponent = nullptr;
Model *m_model = nullptr; Model *m_model = nullptr;
QPoint m_lastPos; QPoint m_lastPos;
@@ -155,6 +183,7 @@ private:
bool m_aliasExport = false; bool m_aliasExport = false;
bool m_hasActiveTimeline = false; bool m_hasActiveTimeline = false;
bool m_hasQuick3DImport = false; bool m_hasQuick3DImport = false;
bool m_hasMaterialRoot = false;
bool m_hasModelSelection = false; bool m_hasModelSelection = false;
ModelNode m_selectedMaterial; ModelNode m_selectedMaterial;

View File

@@ -102,7 +102,7 @@ public:
MaterialEditorQmlBackend::MaterialEditorQmlBackend(MaterialEditorView *materialEditor) MaterialEditorQmlBackend::MaterialEditorQmlBackend(MaterialEditorView *materialEditor)
: m_view(new QQuickWidget) : m_view(new QQuickWidget)
, m_materialEditorTransaction(new MaterialEditorTransaction(materialEditor)) , m_materialEditorTransaction(new MaterialEditorTransaction(materialEditor))
, m_contextObject(new MaterialEditorContextObject()) , m_contextObject(new MaterialEditorContextObject(m_view->rootContext()))
, m_materialEditorImageProvider(new MaterialEditorImageProvider()) , m_materialEditorImageProvider(new MaterialEditorImageProvider())
{ {
m_view->setResizeMode(QQuickWidget::SizeRootObjectToView); m_view->setResizeMode(QQuickWidget::SizeRootObjectToView);

View File

@@ -51,6 +51,7 @@
#include <qmldesignerplugin.h> #include <qmldesignerplugin.h>
#include <utils/fileutils.h> #include <utils/fileutils.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <propertyeditorqmlbackend.h>
#include <QApplication> #include <QApplication>
#include <QDebug> #include <QDebug>
@@ -62,6 +63,7 @@
#include <QStackedWidget> #include <QStackedWidget>
#include <QShortcut> #include <QShortcut>
#include <QTimer> #include <QTimer>
#include <QColorDialog>
namespace QmlDesigner { namespace QmlDesigner {
@@ -82,6 +84,10 @@ MaterialEditorView::MaterialEditorView(QWidget *parent)
} }
}); });
m_typeUpdateTimer.setSingleShot(true);
m_typeUpdateTimer.setInterval(500);
connect(&m_typeUpdateTimer, &QTimer::timeout, this, &MaterialEditorView::updatePossibleTypes);
m_stackedWidget->setStyleSheet(Theme::replaceCssColors( m_stackedWidget->setStyleSheet(Theme::replaceCssColors(
QString::fromUtf8(Utils::FileReader::fetchQrc(":/qmldesigner/stylesheet.css")))); QString::fromUtf8(Utils::FileReader::fetchQrc(":/qmldesigner/stylesheet.css"))));
m_stackedWidget->setMinimumWidth(250); m_stackedWidget->setMinimumWidth(250);
@@ -420,12 +426,15 @@ void MaterialEditorView::handleToolBarAction(int action)
if (!model()) if (!model())
break; break;
executeInTransaction("MaterialEditorView:handleToolBarAction", [&] { executeInTransaction("MaterialEditorView:handleToolBarAction", [&] {
ModelNode matLib = materialLibraryNode();
if (!matLib.isValid())
return;
NodeMetaInfo metaInfo = model()->metaInfo("QtQuick3D.DefaultMaterial"); NodeMetaInfo metaInfo = model()->metaInfo("QtQuick3D.DefaultMaterial");
ModelNode newMatNode = createModelNode("QtQuick3D.DefaultMaterial", metaInfo.majorVersion(), ModelNode newMatNode = createModelNode("QtQuick3D.DefaultMaterial", metaInfo.majorVersion(),
metaInfo.minorVersion()); metaInfo.minorVersion());
renameMaterial(newMatNode, "New Material"); renameMaterial(newMatNode, "New Material");
matLib.defaultNodeListProperty().reparentHere(newMatNode);
materialLibraryNode().defaultNodeListProperty().reparentHere(newMatNode);
}); });
break; break;
} }
@@ -443,18 +452,110 @@ void MaterialEditorView::handleToolBarAction(int action)
} }
} }
void MaterialEditorView::handlePreviewEnvChanged(const QString &envAndValue)
{
// if (envAndValue.isEmpty() || m_initializingPreviewData)
// return;
// QTC_ASSERT(m_hasQuick3DImport, return);
// QTC_ASSERT(model(), return);
// QTC_ASSERT(model()->nodeInstanceView(), return);
// QStringList parts = envAndValue.split('=');
// QString env = parts[0];
// QString value;
// if (parts.size() > 1)
// value = parts[1];
// PropertyName matPrevEnvAuxProp("matPrevEnv");
// PropertyName matPrevEnvValueAuxProp("matPrevEnvValue");
// auto renderPreviews = [=](const QString &auxEnv, const QString &auxValue) {
// rootModelNode().setAuxiliaryData(matPrevEnvAuxProp, auxEnv);
// rootModelNode().setAuxiliaryData(matPrevEnvValueAuxProp, auxValue);
// QTimer::singleShot(0, this, &MaterialEditorView::requestPreviewRender);
// emitCustomNotification("refresh_material_browser", {});
// };
// if (env == "Color") {
// m_colorDialog.clear();
// // Store color to separate property to persist selection over non-color env changes
// PropertyName colorAuxProp("matPrevColor");
// QString oldColor = rootModelNode().auxiliaryData(colorAuxProp).toString();
// QString oldEnv = rootModelNode().auxiliaryData(matPrevEnvAuxProp).toString();
// QString oldValue = rootModelNode().auxiliaryData(matPrevEnvValueAuxProp).toString();
// m_colorDialog = new QColorDialog(Core::ICore::dialogParent());
// m_colorDialog->setModal(true);
// m_colorDialog->setAttribute(Qt::WA_DeleteOnClose);
// m_colorDialog->setCurrentColor(QColor(oldColor));
// m_colorDialog->show();
// QObject::connect(m_colorDialog, &QColorDialog::currentColorChanged,
// m_colorDialog, [=](const QColor &color) {
// renderPreviews(env, color.name());
// });
// QObject::connect(m_colorDialog, &QColorDialog::colorSelected,
// m_colorDialog, [=](const QColor &color) {
// renderPreviews(env, color.name());
// rootModelNode().setAuxiliaryData(colorAuxProp, color.name());
// });
// QObject::connect(m_colorDialog, &QColorDialog::rejected,
// m_colorDialog, [=]() {
// renderPreviews(oldEnv, oldValue);
// initPreviewData();
// });
// return;
// }
// renderPreviews(env, value);
}
void MaterialEditorView::handlePreviewModelChanged(const QString &modelStr)
{
// if (modelStr.isEmpty() || m_initializingPreviewData)
// return;
// QTC_ASSERT(m_hasQuick3DImport, return);
// QTC_ASSERT(model(), return);
// QTC_ASSERT(model()->nodeInstanceView(), return);
// rootModelNode().setAuxiliaryData("matPrevModel", modelStr);
// QTimer::singleShot(0, this, &MaterialEditorView::requestPreviewRender);
// emitCustomNotification("refresh_material_browser", {});
}
void MaterialEditorView::setupQmlBackend() void MaterialEditorView::setupQmlBackend()
{ {
QUrl qmlPaneUrl; QUrl qmlPaneUrl;
QUrl qmlSpecificsUrl; QUrl qmlSpecificsUrl;
QString specificQmlData;
QString currentTypeName;
if (m_selectedMaterial.isValid() && m_hasQuick3DImport) { if (m_selectedMaterial.isValid() && m_hasQuick3DImport) {
qmlPaneUrl = QUrl::fromLocalFile(materialEditorResourcesPath() + "/MaterialEditorPane.qml"); qmlPaneUrl = QUrl::fromLocalFile(materialEditorResourcesPath() + "/MaterialEditorPane.qml");
TypeName diffClassName;
NodeMetaInfo metaInfo = m_selectedMaterial.metaInfo(); NodeMetaInfo metaInfo = m_selectedMaterial.metaInfo();
QDir importDir(metaInfo.importDirectoryPath() + Constants::QML_DESIGNER_SUBFOLDER); if (metaInfo.isValid()) {
QString typeName = QString::fromUtf8(metaInfo.typeName().split('.').constLast()); diffClassName = metaInfo.typeName();
qmlSpecificsUrl = QUrl::fromLocalFile(importDir.absoluteFilePath(typeName + "Specifics.qml")); const QList<NodeMetaInfo> hierarchy = metaInfo.classHierarchy();
for (const NodeMetaInfo &metaInfo : hierarchy) {
if (PropertyEditorQmlBackend::checkIfUrlExists(qmlSpecificsUrl))
break;
qmlSpecificsUrl = PropertyEditorQmlBackend::getQmlFileUrl(metaInfo.typeName()
+ "Specifics", metaInfo);
diffClassName = metaInfo.typeName();
}
}
if (metaInfo.isValid() && diffClassName != m_selectedMaterial.type()) {
specificQmlData = PropertyEditorQmlBackend::templateGeneration(
metaInfo, model()->metaInfo(diffClassName), m_selectedMaterial);
}
currentTypeName = QString::fromLatin1(m_selectedMaterial.type());
} else { } else {
qmlPaneUrl = QUrl::fromLocalFile(materialEditorResourcesPath() + "/EmptyMaterialEditorPane.qml"); qmlPaneUrl = QUrl::fromLocalFile(materialEditorResourcesPath() + "/EmptyMaterialEditorPane.qml");
} }
@@ -473,17 +574,29 @@ void MaterialEditorView::setupQmlBackend()
currentQmlBackend->setSource(qmlPaneUrl); currentQmlBackend->setSource(qmlPaneUrl);
QObject::connect(currentQmlBackend->widget()->rootObject(), SIGNAL(toolBarAction(int)), QObject *rootObj = currentQmlBackend->widget()->rootObject();
QObject::connect(rootObj, SIGNAL(toolBarAction(int)),
this, SLOT(handleToolBarAction(int))); this, SLOT(handleToolBarAction(int)));
QObject::connect(rootObj, SIGNAL(previewEnvChanged(QString)),
this, SLOT(handlePreviewEnvChanged(QString)));
QObject::connect(rootObj, SIGNAL(previewModelChanged(QString)),
this, SLOT(handlePreviewModelChanged(QString)));
} else { } else {
currentQmlBackend->setup(m_selectedMaterial, currentStateName, qmlSpecificsUrl, this); currentQmlBackend->setup(m_selectedMaterial, currentStateName, qmlSpecificsUrl, this);
} }
currentQmlBackend->widget()->installEventFilter(this);
currentQmlBackend->contextObject()->setHasQuick3DImport(m_hasQuick3DImport); currentQmlBackend->contextObject()->setHasQuick3DImport(m_hasQuick3DImport);
currentQmlBackend->contextObject()->setHasMaterialRoot(m_hasMaterialRoot);
m_stackedWidget->setCurrentWidget(currentQmlBackend->widget()); currentQmlBackend->contextObject()->setSpecificQmlData(specificQmlData);
currentQmlBackend->contextObject()->setCurrentType(currentTypeName);
m_qmlBackEnd = currentQmlBackend; m_qmlBackEnd = currentQmlBackend;
delayedTypeUpdate();
initPreviewData();
m_stackedWidget->setCurrentWidget(m_qmlBackEnd->widget());
} }
void MaterialEditorView::commitVariantValueToModel(const PropertyName &propertyName, const QVariant &value) void MaterialEditorView::commitVariantValueToModel(const PropertyName &propertyName, const QVariant &value)
@@ -529,6 +642,75 @@ bool MaterialEditorView::noValidSelection() const
return !QmlObjectNode::isValidQmlObjectNode(m_selectedMaterial); return !QmlObjectNode::isValidQmlObjectNode(m_selectedMaterial);
} }
void MaterialEditorView::initPreviewData()
{
// if (model() && m_qmlBackEnd) {
// QString env = rootModelNode().auxiliaryData("matPrevEnv").toString();
// QString envValue = rootModelNode().auxiliaryData("matPrevEnvValue").toString();
// QString modelStr = rootModelNode().auxiliaryData("matPrevModel").toString();
// if (!envValue.isEmpty() && env != "Color" && env != "Default") {
// env += '=';
// env += envValue;
// }
// if (env.isEmpty())
// env = "Default";
// if (modelStr.isEmpty())
// modelStr = "#Sphere";
// m_initializingPreviewData = true;
// QMetaObject::invokeMethod(m_qmlBackEnd->widget()->rootObject(),
// "initPreviewData",
// Q_ARG(QVariant, env), Q_ARG(QVariant, modelStr));
// m_initializingPreviewData = false;
// }
}
void MaterialEditorView::delayedTypeUpdate()
{
m_typeUpdateTimer.start();
}
static Import entryToImport(const ItemLibraryEntry &entry)
{
if (entry.majorVersion() == -1 && entry.minorVersion() == -1)
return Import::createFileImport(entry.requiredImport());
return Import::createLibraryImport(entry.requiredImport(),
QString::number(entry.majorVersion()) + QLatin1Char('.') +
QString::number(entry.minorVersion()));
}
void MaterialEditorView::updatePossibleTypes()
{
QTC_ASSERT(model(), return);
if (!m_qmlBackEnd)
return;
// Ensure basic types are always first
static const QStringList basicTypes {"DefaultMaterial", "PrincipledMaterial", "CustomMaterial"};
QStringList allTypes = basicTypes;
const QList<ItemLibraryEntry> itemLibEntries = m_itemLibraryInfo->entries();
for (const ItemLibraryEntry &entry : itemLibEntries) {
NodeMetaInfo metaInfo = model()->metaInfo(entry.typeName());
bool valid = metaInfo.isValid()
&& (metaInfo.majorVersion() >= entry.majorVersion()
|| metaInfo.majorVersion() < 0);
if (valid && metaInfo.isSubclassOf("QtQuick3D.Material")) {
bool addImport = entry.requiredImport().isEmpty();
if (!addImport) {
Import import = entryToImport(entry);
addImport = model()->hasImport(import, true, true);
}
if (addImport) {
QString typeName = QString::fromLatin1(entry.typeName().split('.').last());
if (!allTypes.contains(typeName))
allTypes.append(typeName);
}
}
}
m_qmlBackEnd->contextObject()->setPossibleTypes(allTypes);
}
void MaterialEditorView::modelAttached(Model *model) void MaterialEditorView::modelAttached(Model *model)
{ {
AbstractView::modelAttached(model); AbstractView::modelAttached(model);
@@ -536,11 +718,27 @@ void MaterialEditorView::modelAttached(Model *model)
m_locked = true; m_locked = true;
m_hasQuick3DImport = model->hasImport("QtQuick3D"); m_hasQuick3DImport = model->hasImport("QtQuick3D");
m_hasMaterialRoot = rootModelNode().isSubclassOf("QtQuick3D.Material");
// Creating the material library node on model attach causes errors as long as the type information if (m_hasMaterialRoot) {
// not complete yet, so we keep checking until type info is complete. m_selectedMaterial = rootModelNode();
if (m_hasQuick3DImport) } else if (m_hasQuick3DImport) {
// Creating the material library node on model attach causes errors as long as the type
// information is not complete yet, so we keep checking until type info is complete.
m_ensureMatLibTimer.start(500); m_ensureMatLibTimer.start(500);
}
if (m_itemLibraryInfo.data() != model->metaInfo().itemLibraryInfo()) {
if (m_itemLibraryInfo) {
disconnect(m_itemLibraryInfo.data(), &ItemLibraryInfo::entriesChanged,
this, &MaterialEditorView::delayedTypeUpdate);
}
m_itemLibraryInfo = model->metaInfo().itemLibraryInfo();
if (m_itemLibraryInfo) {
connect(m_itemLibraryInfo.data(), &ItemLibraryInfo::entriesChanged,
this, &MaterialEditorView::delayedTypeUpdate);
}
}
if (!m_setupCompleted) { if (!m_setupCompleted) {
reloadQml(); reloadQml();
@@ -705,10 +903,20 @@ void MaterialEditorView::instancePropertyChanged(const QList<QPair<ModelNode, Pr
m_locked = false; m_locked = false;
} }
void MaterialEditorView::nodeTypeChanged(const ModelNode &node, const TypeName &, int, int) void MaterialEditorView::nodeTypeChanged(const ModelNode &node, const TypeName &typeName, int, int)
{ {
if (node == m_selectedMaterial) if (node == m_selectedMaterial) {
m_qmlBackEnd->contextObject()->setCurrentType(QString::fromLatin1(typeName));
delayedResetView(); delayedResetView();
}
}
void MaterialEditorView::rootNodeTypeChanged(const QString &type, int, int)
{
if (rootModelNode() == m_selectedMaterial) {
m_qmlBackEnd->contextObject()->setCurrentType(type);
delayedResetView();
}
} }
void MaterialEditorView::modelNodePreviewPixmapChanged(const ModelNode &node, const QPixmap &pixmap) void MaterialEditorView::modelNodePreviewPixmapChanged(const ModelNode &node, const QPixmap &pixmap)
@@ -752,6 +960,10 @@ void MaterialEditorView::duplicateMaterial(const ModelNode &material)
QmlObjectNode sourceMat(material); QmlObjectNode sourceMat(material);
executeInTransaction(__FUNCTION__, [&] { executeInTransaction(__FUNCTION__, [&] {
ModelNode matLib = materialLibraryNode();
if (!matLib.isValid())
return;
// create the duplicate material // create the duplicate material
NodeMetaInfo metaInfo = model()->metaInfo(matType); NodeMetaInfo metaInfo = model()->metaInfo(matType);
QmlObjectNode duplicateMat = createModelNode(matType, metaInfo.majorVersion(), metaInfo.minorVersion()); QmlObjectNode duplicateMat = createModelNode(matType, metaInfo.majorVersion(), metaInfo.minorVersion());
@@ -773,7 +985,7 @@ void MaterialEditorView::duplicateMaterial(const ModelNode &material)
duplicateMat.setBindingProperty(prop.name(), prop.toBindingProperty().expression()); duplicateMat.setBindingProperty(prop.name(), prop.toBindingProperty().expression());
} }
materialLibraryNode().defaultNodeListProperty().reparentHere(duplicateMat); matLib.defaultNodeListProperty().reparentHere(duplicateMat);
}); });
} }
@@ -783,8 +995,10 @@ void MaterialEditorView::customNotification([[maybe_unused]] const AbstractView
const QList<QVariant> &data) const QList<QVariant> &data)
{ {
if (identifier == "selected_material_changed") { if (identifier == "selected_material_changed") {
if (!m_hasMaterialRoot) {
m_selectedMaterial = nodeList.first(); m_selectedMaterial = nodeList.first();
QTimer::singleShot(0, this, &MaterialEditorView::resetView); QTimer::singleShot(0, this, &MaterialEditorView::resetView);
}
} else if (identifier == "apply_to_selected_triggered") { } else if (identifier == "apply_to_selected_triggered") {
applyMaterialToSelectedModels(nodeList.first(), data.first().toBool()); applyMaterialToSelectedModels(nodeList.first(), data.first().toBool());
} else if (identifier == "rename_material") { } else if (identifier == "rename_material") {
@@ -843,6 +1057,15 @@ void MaterialEditorView::setValue(const QmlObjectNode &qmlObjectNode, const Prop
m_locked = false; m_locked = false;
} }
bool MaterialEditorView::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::FocusOut) {
if (m_qmlBackEnd && m_qmlBackEnd->widget() == obj)
QMetaObject::invokeMethod(m_qmlBackEnd->widget()->rootObject(), "closeContextMenu");
}
return QObject::eventFilter(obj, event);
}
void MaterialEditorView::reloadQml() void MaterialEditorView::reloadQml()
{ {
m_qmlBackendHash.clear(); m_qmlBackendHash.clear();

View File

@@ -26,13 +26,17 @@
#pragma once #pragma once
#include <abstractview.h> #include <abstractview.h>
#include <itemlibraryinfo.h>
#include <QHash> #include <QHash>
#include <QPointer>
#include <QTimer> #include <QTimer>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QShortcut; class QShortcut;
class QStackedWidget; class QStackedWidget;
class QTimer; class QTimer;
class QColorDialog;
QT_END_NAMESPACE QT_END_NAMESPACE
namespace QmlDesigner { namespace QmlDesigner {
@@ -70,6 +74,7 @@ public:
void instancePropertyChanged(const QList<QPair<ModelNode, PropertyName> > &propertyList) override; void instancePropertyChanged(const QList<QPair<ModelNode, PropertyName> > &propertyList) override;
void nodeTypeChanged(const ModelNode& node, const TypeName &type, int majorVersion, int minorVersion) override; void nodeTypeChanged(const ModelNode& node, const TypeName &type, int majorVersion, int minorVersion) override;
void rootNodeTypeChanged(const QString &type, int majorVersion, int minorVersion) override;
void modelNodePreviewPixmapChanged(const ModelNode &node, const QPixmap &pixmap) override; void modelNodePreviewPixmapChanged(const ModelNode &node, const QPixmap &pixmap) override;
void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override; void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
void customNotification(const AbstractView *view, const QString &identifier, void customNotification(const AbstractView *view, const QString &identifier,
@@ -89,10 +94,13 @@ public:
public slots: public slots:
void handleToolBarAction(int action); void handleToolBarAction(int action);
void handlePreviewEnvChanged(const QString &envAndValue);
void handlePreviewModelChanged(const QString &modelStr);
protected: protected:
void timerEvent(QTimerEvent *event) override; void timerEvent(QTimerEvent *event) override;
void setValue(const QmlObjectNode &fxObjectNode, const PropertyName &name, const QVariant &value); void setValue(const QmlObjectNode &fxObjectNode, const PropertyName &name, const QVariant &value);
bool eventFilter(QObject *obj, QEvent *event) override;
private: private:
static QString materialEditorResourcesPath(); static QString materialEditorResourcesPath();
@@ -115,8 +123,13 @@ private:
bool noValidSelection() const; bool noValidSelection() const;
void initPreviewData();
void delayedTypeUpdate();
void updatePossibleTypes();
ModelNode m_selectedMaterial; ModelNode m_selectedMaterial;
QTimer m_ensureMatLibTimer; QTimer m_ensureMatLibTimer;
QTimer m_typeUpdateTimer;
QShortcut *m_updateShortcut = nullptr; QShortcut *m_updateShortcut = nullptr;
int m_timerId = 0; int m_timerId = 0;
QStackedWidget *m_stackedWidget = nullptr; QStackedWidget *m_stackedWidget = nullptr;
@@ -126,6 +139,11 @@ private:
bool m_locked = false; bool m_locked = false;
bool m_setupCompleted = false; bool m_setupCompleted = false;
bool m_hasQuick3DImport = false; bool m_hasQuick3DImport = false;
bool m_hasMaterialRoot = false;
bool m_initializingPreviewData = false;
QPointer<QColorDialog> m_colorDialog;
QPointer<ItemLibraryInfo> m_itemLibraryInfo;
}; };
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -65,7 +65,7 @@ QModelIndex StatesEditorModel::index(int row, int column, const QModelIndex &par
int internalNodeId = 0; int internalNodeId = 0;
if (row > 0 && row < rowCount() - 1) // first and last rows are base state, add state if (row > 0 && row < rowCount() - 1) // first and last rows are base state, add state
internalNodeId = m_statesEditorView->rootModelNode().nodeListProperty("states").at(row - 1).internalId(); internalNodeId = m_statesEditorView->acitveStatesGroupNode().nodeListProperty("states").at(row - 1).internalId();
return hasIndex(row, column, parent) ? createIndex(row, column, internalNodeId) : QModelIndex(); return hasIndex(row, column, parent) ? createIndex(row, column, internalNodeId) : QModelIndex();
} }
@@ -75,10 +75,10 @@ int StatesEditorModel::rowCount(const QModelIndex &parent) const
if (parent.isValid() || m_statesEditorView.isNull() || !m_statesEditorView->model()) if (parent.isValid() || m_statesEditorView.isNull() || !m_statesEditorView->model())
return 0; return 0;
if (!m_statesEditorView->rootModelNode().hasNodeListProperty("states")) if (!m_statesEditorView->acitveStatesGroupNode().hasNodeListProperty("states"))
return 2; // base state + add new state return 2; // base state + add new state
return m_statesEditorView->rootModelNode().nodeListProperty("states").count() + 2; // 2 = base state + add new state return m_statesEditorView->acitveStatesGroupNode().nodeListProperty("states").count() + 2; // 2 = base state + add new state
} }
void StatesEditorModel::reset() void StatesEditorModel::reset()

View File

@@ -85,6 +85,20 @@ void StatesEditorView::rootNodeTypeChanged(const QString &/*type*/, int /*majorV
checkForStatesAvailability(); checkForStatesAvailability();
} }
ModelNode StatesEditorView::acitveStatesGroupNode() const
{
return m_activeStatesGroupNode;
}
void StatesEditorView::setAcitveStatesGroupNode(const ModelNode &modelNode)
{
if (m_activeStatesGroupNode == modelNode)
return;
m_activeStatesGroupNode = modelNode;
resetModel();
}
void StatesEditorView::removeState(int nodeId) void StatesEditorView::removeState(int nodeId)
{ {
try { try {
@@ -193,12 +207,12 @@ void StatesEditorView::createNewState()
void StatesEditorView::addState() void StatesEditorView::addState()
{ {
// can happen when root node is e.g. a ListModel // can happen when root node is e.g. a ListModel
if (!QmlVisualNode::isValidQmlVisualNode(rootModelNode())) if (!QmlVisualNode::isValidQmlVisualNode(acitveStatesGroupNode()))
return; return;
QmlDesignerPlugin::emitUsageStatistics(Constants::EVENT_STATE_ADDED); QmlDesignerPlugin::emitUsageStatistics(Constants::EVENT_STATE_ADDED);
QStringList modelStateNames = rootStateGroup().names(); QStringList modelStateNames = activeStateGroup().names();
QString newStateName; QString newStateName;
int index = 1; int index = 1;
@@ -209,9 +223,9 @@ void StatesEditorView::addState()
} }
executeInTransaction("addState", [this, newStateName]() { executeInTransaction("addState", [this, newStateName]() {
rootModelNode().validId(); acitveStatesGroupNode().validId();
ModelNode newState = rootStateGroup().addState(newStateName); ModelNode newState = activeStateGroup().addState(newStateName);
setCurrentState(newState); setCurrentState(newState);
}); });
} }
@@ -244,7 +258,7 @@ void StatesEditorView::duplicateCurrentState()
newName = newName.left(match.capturedStart()); newName = newName.left(match.capturedStart());
int i = 1; int i = 1;
QStringList stateNames = rootStateGroup().names(); QStringList stateNames = activeStateGroup().names();
while (stateNames.contains(newName + QString::number(i))) while (stateNames.contains(newName + QString::number(i)))
i++; i++;
const QString newStateName = newName + QString::number(i); const QString newStateName = newName + QString::number(i);
@@ -258,7 +272,7 @@ void StatesEditorView::duplicateCurrentState()
void StatesEditorView::checkForStatesAvailability() void StatesEditorView::checkForStatesAvailability()
{ {
if (m_statesEditorWidget) { if (m_statesEditorWidget) {
const bool isVisual = QmlVisualNode::isValidQmlVisualNode(rootModelNode()); const bool isVisual = QmlVisualNode::isValidQmlVisualNode(acitveStatesGroupNode());
m_statesEditorWidget->showAddNewStatesButton(isVisual); m_statesEditorWidget->showAddNewStatesButton(isVisual);
} }
} }
@@ -277,16 +291,16 @@ QmlModelState StatesEditorView::baseState() const
return QmlModelState::createBaseState(this); return QmlModelState::createBaseState(this);
} }
QmlModelStateGroup StatesEditorView::rootStateGroup() const QmlModelStateGroup StatesEditorView::activeStateGroup() const
{ {
return QmlModelStateGroup(rootModelNode()); return QmlModelStateGroup(acitveStatesGroupNode());
} }
bool StatesEditorView::validStateName(const QString &name) const bool StatesEditorView::validStateName(const QString &name) const
{ {
if (name == tr("base state")) if (name == tr("base state"))
return false; return false;
const QList<QmlModelState> modelStates = rootStateGroup().allStates(); const QList<QmlModelState> modelStates = activeStateGroup().allStates();
for (const QmlModelState &state : modelStates) { for (const QmlModelState &state : modelStates) {
if (state.name() == name) if (state.name() == name)
return false; return false;
@@ -392,8 +406,8 @@ void StatesEditorView::resetDefaultState()
auto guard = qScopeGuard([&]() { m_block = false; }); auto guard = qScopeGuard([&]() { m_block = false; });
try { try {
if (rootModelNode().hasProperty("state")) if (acitveStatesGroupNode().hasProperty("state"))
rootModelNode().removeProperty("state"); acitveStatesGroupNode().removeProperty("state");
} catch (const RewritingException &e) { } catch (const RewritingException &e) {
e.showException(); e.showException();
@@ -402,7 +416,7 @@ void StatesEditorView::resetDefaultState()
bool StatesEditorView::hasDefaultState() const bool StatesEditorView::hasDefaultState() const
{ {
return rootModelNode().hasProperty("state"); return acitveStatesGroupNode().hasProperty("state");
} }
void StatesEditorView::setAnnotation(int internalNodeId) void StatesEditorView::setAnnotation(int internalNodeId)
@@ -475,6 +489,8 @@ void StatesEditorView::modelAttached(Model *model)
Q_ASSERT(model); Q_ASSERT(model);
AbstractView::modelAttached(model); AbstractView::modelAttached(model);
m_activeStatesGroupNode = rootModelNode();
if (m_statesEditorWidget) if (m_statesEditorWidget)
m_statesEditorWidget->setNodeInstanceView(nodeInstanceView()); m_statesEditorWidget->setNodeInstanceView(nodeInstanceView());
@@ -593,7 +609,7 @@ void StatesEditorView::instancesPreviewImageChanged(const QVector<ModelNode> &no
minimumIndex = qMin(minimumIndex, 0); minimumIndex = qMin(minimumIndex, 0);
maximumIndex = qMax(maximumIndex, 0); maximumIndex = qMax(maximumIndex, 0);
} else { } else {
int index = rootStateGroup().allStates().indexOf(QmlModelState(node)) + 1; int index = activeStateGroup().allStates().indexOf(QmlModelState(node)) + 1;
if (index > 0) { if (index > 0) {
minimumIndex = qMin(minimumIndex, index); minimumIndex = qMin(minimumIndex, index);
maximumIndex = qMax(maximumIndex, index); maximumIndex = qMax(maximumIndex, index);

View File

@@ -55,7 +55,7 @@ public:
QString currentStateName() const; QString currentStateName() const;
void setCurrentState(const QmlModelState &state); void setCurrentState(const QmlModelState &state);
QmlModelState baseState() const; QmlModelState baseState() const;
QmlModelStateGroup rootStateGroup() const; QmlModelStateGroup activeStateGroup() const;
// AbstractView // AbstractView
void modelAttached(Model *model) override; void modelAttached(Model *model) override;
@@ -87,6 +87,10 @@ public:
void rootNodeTypeChanged(const QString &type, int majorVersion, int minorVersion) override; void rootNodeTypeChanged(const QString &type, int majorVersion, int minorVersion) override;
ModelNode acitveStatesGroupNode() const;
void setAcitveStatesGroupNode(const ModelNode &modelNode);
public slots: public slots:
void synchonizeCurrentStateFromWidget(); void synchonizeCurrentStateFromWidget();
void createNewState(); void createNewState();
@@ -105,6 +109,7 @@ private:
int m_lastIndex; int m_lastIndex;
bool m_block = false; bool m_block = false;
QPointer<AnnotationEditor> m_editor; QPointer<AnnotationEditor> m_editor;
ModelNode m_activeStatesGroupNode;
}; };
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -24,47 +24,147 @@
****************************************************************************/ ****************************************************************************/
#include "setframevaluedialog.h" #include "setframevaluedialog.h"
#include "ui_setframevaluedialog.h" #include "timelinecontrols.h"
#include <QtGui/qvalidator.h> #include <QDoubleSpinBox>
#include <QSpinBox>
#include <QCheckBox>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QMetaType>
#include <QDialogButtonBox>
#include <qnamespace.h>
#include <limits>
namespace QmlDesigner { namespace QmlDesigner {
SetFrameValueDialog::SetFrameValueDialog(qreal frame, const QVariant &value, SetFrameValueDialog::SetFrameValueDialog(qreal frame, const QVariant &value,
const QString &propertyName, QWidget *parent) const QString &propertyName, QWidget *parent)
: QDialog(parent) : QDialog(parent, Qt::Tool)
, ui(new Ui::SetFrameValueDialog) , m_valueGetter()
, m_valueType(value.metaType())
, m_frameControl(new QSpinBox)
{ {
ui->setupUi(this);
setWindowTitle(tr("Edit Keyframe")); setWindowTitle(tr("Edit Keyframe"));
setFixedSize(size());
ui->lineEditFrame->setValidator(new QIntValidator(0, 99999, this)); auto frameLabelString = QString(tr("Frame"));
auto dv = new QDoubleValidator(this); auto labelWidth = fontMetrics().boundingRect(frameLabelString).width();
dv->setDecimals(2); if (auto tmp = fontMetrics().boundingRect(propertyName).width(); tmp > labelWidth)
ui->lineEditValue->setValidator(dv); labelWidth = tmp;
QLocale l; auto *frameLabel = new QLabel(frameLabelString);
ui->lineEditFrame->setText(l.toString(qRound(frame))); frameLabel->setAlignment(Qt::AlignRight);
ui->lineEditValue->setText(l.toString(value.toDouble(), 'f', 2)); frameLabel->setFixedWidth(labelWidth);
ui->labelValue->setText(propertyName);
auto *valueLabel = new QLabel(propertyName);
valueLabel->setAlignment(Qt::AlignRight);
valueLabel->setFixedWidth(labelWidth);
m_frameControl->setRange(std::numeric_limits<int>::min(), std::numeric_limits<int>::max());
m_frameControl->setValue(static_cast<int>(frame));
m_frameControl->setAlignment(Qt::AlignRight);
auto* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
auto* frameRow = new QHBoxLayout;
frameRow->addWidget(frameLabel);
frameRow->addWidget(m_frameControl);
auto* valueRow = new QHBoxLayout;
valueRow->addWidget(valueLabel);
valueRow->addWidget(createValueControl(value));
auto* hbox = new QVBoxLayout;
hbox->addLayout(frameRow);
hbox->addLayout(valueRow);
hbox->addStretch();
hbox->addWidget(buttons);
setLayout(hbox);
} }
SetFrameValueDialog::~SetFrameValueDialog() SetFrameValueDialog::~SetFrameValueDialog()
{ { }
delete ui;
}
qreal SetFrameValueDialog::frame() const qreal SetFrameValueDialog::frame() const
{ {
QLocale l; return static_cast<qreal>(m_frameControl->value());
return l.toDouble(ui->lineEditFrame->text());
} }
QVariant SetFrameValueDialog::value() const QVariant SetFrameValueDialog::value() const
{ {
QLocale l; if (m_valueGetter)
return QVariant(l.toDouble(ui->lineEditValue->text())); return m_valueGetter();
return QVariant(m_valueType);
}
QWidget* SetFrameValueDialog::createValueControl(const QVariant& value)
{
m_valueType = value.metaType();
switch (value.metaType().id())
{
case QMetaType::QColor: {
auto* widget = new ColorControl(value.value<QColor>());
m_valueGetter = [widget]() { return widget->value(); };
return widget;
}
case QMetaType::Bool: {
auto* widget = new QCheckBox;
widget->setChecked(value.toBool());
m_valueGetter = [widget]() { return widget->isChecked(); };
return widget;
}
case QMetaType::Int: {
auto* widget = new QSpinBox;
widget->setRange(std::numeric_limits<int>::min(), std::numeric_limits<int>::max());
widget->setAlignment(Qt::AlignRight);
widget->setValue(value.toInt());
m_valueGetter = [widget]() { return widget->value(); };
return widget;
}
case QMetaType::UInt: {
auto* widget = new QSpinBox;
widget->setRange(0, std::numeric_limits<int>::max());
widget->setAlignment(Qt::AlignRight);
widget->setValue(value.toUInt());
m_valueGetter = [widget]() { return static_cast<unsigned int>(widget->value()); };
return widget;
}
case QMetaType::Float: {
auto* widget = new QDoubleSpinBox;
widget->setRange(std::numeric_limits<float>::min(), std::numeric_limits<float>::max());
widget->setAlignment(Qt::AlignRight);
widget->setValue(value.toFloat());
m_valueGetter = [widget]() { return static_cast<float>(widget->value()); };
return widget;
}
case QMetaType::Double:
[[fallthrough]];
default: {
auto* widget = new QDoubleSpinBox;
widget->setRange(std::numeric_limits<double>::min(), std::numeric_limits<double>::max());
widget->setAlignment(Qt::AlignRight);
widget->setValue(value.toDouble());
m_valueGetter = [widget]() { return widget->value(); };
return widget;
}
}
m_valueGetter = nullptr;
return nullptr;
} }
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -27,14 +27,10 @@
#include <QDialog> #include <QDialog>
QT_FORWARD_DECLARE_CLASS(QLineEdit) QT_FORWARD_DECLARE_CLASS(QSpinBox)
namespace QmlDesigner { namespace QmlDesigner {
namespace Ui {
class SetFrameValueDialog;
}
class SetFrameValueDialog : public QDialog class SetFrameValueDialog : public QDialog
{ {
Q_OBJECT Q_OBJECT
@@ -48,7 +44,12 @@ public:
QVariant value() const; QVariant value() const;
private: private:
Ui::SetFrameValueDialog *ui; QWidget* createValueControl(const QVariant& value);
std::function<QVariant(void)> m_valueGetter;
QMetaType m_valueType;
QSpinBox *m_frameControl;
}; };
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -1,84 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QmlDesigner::SetFrameValueDialog</class>
<widget class="QDialog" name="QmlDesigner::SetFrameValueDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>212</width>
<height>148</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="labelFrame">
<property name="text">
<string>Frame</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="lineEditFrame"/>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="lineEditValue"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelValue">
<property name="text">
<string>Value</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>QmlDesigner::SetFrameValueDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>QmlDesigner::SetFrameValueDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -191,7 +191,7 @@ void ColorControl::mouseReleaseEvent(QMouseEvent *event)
event->accept(); event->accept();
if (color != m_color) { if (color.isValid() && color != m_color) {
m_color = color; m_color = color;
update(); update();
emit valueChanged(); emit valueChanged();

View File

@@ -1044,6 +1044,18 @@ bool shouldSendAuxiliary(const AuxiliaryDataKey &key)
} }
} // namespace } // namespace
bool parentIsBehavior(ModelNode node)
{
while (node.isValid() && !node.isRootNode()) {
if (!node.behaviorPropertyName().isEmpty())
return true;
node = node.parentProperty().parentModelNode();
}
return false;
}
CreateSceneCommand NodeInstanceView::createCreateSceneCommand() CreateSceneCommand NodeInstanceView::createCreateSceneCommand()
{ {
QList<ModelNode> nodeList = allModelNodes(); QList<ModelNode> nodeList = allModelNodes();
@@ -1103,7 +1115,7 @@ CreateSceneCommand NodeInstanceView::createCreateSceneCommand()
nodeMetaType, nodeMetaType,
nodeFlags); nodeFlags);
if (instance.modelNode().behaviorPropertyName().isEmpty()) if (!parentIsBehavior(instance.modelNode()))
instanceContainerList.append(container); instanceContainerList.append(container);
} }

View File

@@ -836,7 +836,7 @@ void AbstractView::changeRootNodeType(const TypeName &type, int majorVersion, in
void AbstractView::ensureMaterialLibraryNode() void AbstractView::ensureMaterialLibraryNode()
{ {
ModelNode matLib = modelNodeForId(Constants::MATERIAL_LIB_ID); ModelNode matLib = modelNodeForId(Constants::MATERIAL_LIB_ID);
if (matLib.isValid()) if (matLib.isValid() || rootModelNode().isSubclassOf("QtQuick3D.Material"))
return; return;
// Create material library node // Create material library node
@@ -865,13 +865,11 @@ void AbstractView::ensureMaterialLibraryNode()
} }
// Returns ModelNode for project's material library. // Returns ModelNode for project's material library.
// Since this calls ensureMaterialLibraryNode(), it should only be called within a transaction.
ModelNode AbstractView::materialLibraryNode() ModelNode AbstractView::materialLibraryNode()
{ {
ensureMaterialLibraryNode(); ensureMaterialLibraryNode();
ModelNode matLib = modelNodeForId(Constants::MATERIAL_LIB_ID); ModelNode matLib = modelNodeForId(Constants::MATERIAL_LIB_ID);
QTC_ASSERT(matLib.isValid(), return {});
return matLib; return matLib;
} }

View File

@@ -408,8 +408,12 @@ void ModelPrivate::notifyNodeInstanceViewLast(Callable call)
} }
for (const QPointer<AbstractView> &view : enabledViews()) { for (const QPointer<AbstractView> &view : enabledViews()) {
try {
if (!view->isBlockingNotifications()) if (!view->isBlockingNotifications())
call(view.data()); call(view.data());
} catch (const Exception &e) {
e.showException(tr("Exception thrown by view %1.").arg(view->widgetInfo().tabName));
}
} }
if (nodeInstanceView() && !nodeInstanceView()->isBlockingNotifications()) if (nodeInstanceView() && !nodeInstanceView()->isBlockingNotifications())

View File

@@ -88,6 +88,7 @@ RewriterView::RewriterView(DifferenceHandling differenceHandling, QObject *paren
m_textToModelMerger(new Internal::TextToModelMerger(this)) m_textToModelMerger(new Internal::TextToModelMerger(this))
{ {
m_amendTimer.setSingleShot(true); m_amendTimer.setSingleShot(true);
m_amendTimer.setInterval(800); m_amendTimer.setInterval(800);
connect(&m_amendTimer, &QTimer::timeout, this, &RewriterView::amendQmlText); connect(&m_amendTimer, &QTimer::timeout, this, &RewriterView::amendQmlText);
@@ -524,6 +525,10 @@ void RewriterView::applyChanges()
void RewriterView::amendQmlText() void RewriterView::amendQmlText()
{ {
if (!model()->rewriterView())
return;
emitCustomNotification(StartRewriterAmend); emitCustomNotification(StartRewriterAmend);
const QString newQmlText = m_textModifier->text(); const QString newQmlText = m_textModifier->text();

View File

@@ -525,13 +525,15 @@ public:
&& metaInfo.majorVersion() == majorVersion && metaInfo.majorVersion() == majorVersion
&& metaInfo.minorVersion() == minorVersion; && metaInfo.minorVersion() == minorVersion;
if (!ok) { if (!ok) {
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
qDebug() << astTypeNode->name.toString() << typeName; qDebug() << astTypeNode->name.toString() << typeName;
qDebug() << metaInfo.isValid() << metaInfo.typeName(); qDebug() << metaInfo.isValid() << metaInfo.typeName();
qDebug() << metaInfo.directSuperClass().typeName(); qDebug() << metaInfo.directSuperClass().typeName();
if (!typeName.startsWith("...")) if (!typeName.startsWith("...") && m_model == m_model->metaInfoProxyModel()
&& metaInfo.isValid())
throw RewritingException(__LINE__, __FUNCTION__, __FILE__, "test", "test"); throw RewritingException(__LINE__, __FUNCTION__, __FILE__, "test", "test");
} }
@@ -1715,7 +1717,7 @@ void TextToModelMerger::syncSignalDeclarationProperty(AbstractProperty &modelPro
const QString &signature, const QString &signature,
DifferenceHandler &differenceHandler) DifferenceHandler &differenceHandler)
{ {
if (modelProperty.isSignalHandlerProperty()) { if (modelProperty.isSignalDeclarationProperty()) {
SignalDeclarationProperty signalHandlerProperty = modelProperty.toSignalDeclarationProperty(); SignalDeclarationProperty signalHandlerProperty = modelProperty.toSignalDeclarationProperty();
if (signalHandlerProperty.signature() != signature) if (signalHandlerProperty.signature() != signature)
differenceHandler.signalDeclarationSignatureDiffer(signalHandlerProperty, signature); differenceHandler.signalDeclarationSignatureDiffer(signalHandlerProperty, signature);

View File

@@ -28,6 +28,7 @@
#include "designmodewidget.h" #include "designmodewidget.h"
#include "formeditorwidget.h" #include "formeditorwidget.h"
#include "edit3dwidget.h" #include "edit3dwidget.h"
#include "materialbrowserwidget.h"
#include "navigatorwidget.h" #include "navigatorwidget.h"
#include "texteditorwidget.h" #include "texteditorwidget.h"
@@ -70,6 +71,18 @@ void Editor3DContext::contextHelp(const HelpCallback &callback) const
qobject_cast<Edit3DWidget *>(m_widget)->contextHelp(callback); qobject_cast<Edit3DWidget *>(m_widget)->contextHelp(callback);
} }
MaterialBrowserContext::MaterialBrowserContext(QWidget *widget)
: IContext(widget)
{
setWidget(widget);
setContext(Core::Context(Constants::C_QMLMATERIALBROWSER, Constants::C_QT_QUICK_TOOLS_MENU));
}
void MaterialBrowserContext::contextHelp(const HelpCallback &callback) const
{
qobject_cast<MaterialBrowserWidget *>(m_widget)->contextHelp(callback);
}
NavigatorContext::NavigatorContext(QWidget *widget) NavigatorContext::NavigatorContext(QWidget *widget)
: IContext(widget) : IContext(widget)
{ {

View File

@@ -60,6 +60,15 @@ public:
void contextHelp(const Core::IContext::HelpCallback &callback) const override; void contextHelp(const Core::IContext::HelpCallback &callback) const override;
}; };
class MaterialBrowserContext : public Core::IContext
{
Q_OBJECT
public:
MaterialBrowserContext(QWidget *widget);
void contextHelp(const Core::IContext::HelpCallback &callback) const override;
};
class NavigatorContext : public Core::IContext class NavigatorContext : public Core::IContext
{ {
Q_OBJECT Q_OBJECT

View File

@@ -390,19 +390,26 @@ void DesignModeWidget::setup()
m_dockManager->initialize(); m_dockManager->initialize();
// Hide all floating widgets if the initial mode isn't design mode
if (Core::ModeManager::instance()->currentModeId() != Core::Constants::MODE_DESIGN) {
for (auto &floatingWidget : m_dockManager->floatingWidgets())
floatingWidget->hide();
}
connect(Core::ModeManager::instance(), connect(Core::ModeManager::instance(),
&Core::ModeManager::currentModeChanged, &Core::ModeManager::currentModeChanged,
this, this,
[this](Utils::Id mode, Utils::Id oldMode) { [this](Utils::Id mode, Utils::Id previousMode) {
if (mode == Core::Constants::MODE_DESIGN) { if (mode == Core::Constants::MODE_DESIGN) {
m_dockManager->reloadActiveWorkspace(); m_dockManager->reloadActiveWorkspace();
m_dockManager->setModeChangeState(false); m_dockManager->setModeChangeState(false);
} }
if (oldMode == Core::Constants::MODE_DESIGN && mode != Core::Constants::MODE_DESIGN) { if (previousMode == Core::Constants::MODE_DESIGN
&& mode != Core::Constants::MODE_DESIGN) {
m_dockManager->save(); m_dockManager->save();
m_dockManager->setModeChangeState(true); m_dockManager->setModeChangeState(true);
for (auto floatingWidget : m_dockManager->floatingWidgets()) for (auto &floatingWidget : m_dockManager->floatingWidgets())
floatingWidget->hide(); floatingWidget->hide();
} }
}); });

View File

@@ -37,6 +37,7 @@ const char C_QMLFORMEDITOR[] = "QmlDesigner::FormEditor";
const char C_QMLEDITOR3D[] = "QmlDesigner::Editor3D"; const char C_QMLEDITOR3D[] = "QmlDesigner::Editor3D";
const char C_QMLNAVIGATOR[] = "QmlDesigner::Navigator"; const char C_QMLNAVIGATOR[] = "QmlDesigner::Navigator";
const char C_QMLTEXTEDITOR[] = "QmlDesigner::TextEditor"; const char C_QMLTEXTEDITOR[] = "QmlDesigner::TextEditor";
const char C_QMLMATERIALBROWSER[] = "QmlDesigner::MaterialBrowser";
// Special context for preview menu, shared b/w designer and text editor // Special context for preview menu, shared b/w designer and text editor
const char C_QT_QUICK_TOOLS_MENU[] = "QmlDesigner::ToolsMenu"; const char C_QT_QUICK_TOOLS_MENU[] = "QmlDesigner::ToolsMenu";

View File

@@ -399,15 +399,18 @@ void QmlDesignerPlugin::integrateIntoQtCreator(QWidget *modeWidget)
Core::Context qmlDesignerFormEditorContext(Constants::C_QMLFORMEDITOR); Core::Context qmlDesignerFormEditorContext(Constants::C_QMLFORMEDITOR);
Core::Context qmlDesignerEditor3dContext(Constants::C_QMLEDITOR3D); Core::Context qmlDesignerEditor3dContext(Constants::C_QMLEDITOR3D);
Core::Context qmlDesignerNavigatorContext(Constants::C_QMLNAVIGATOR); Core::Context qmlDesignerNavigatorContext(Constants::C_QMLNAVIGATOR);
Core::Context qmlDesignerMaterialBrowserContext(Constants::C_QMLMATERIALBROWSER);
context->context().add(qmlDesignerMainContext); context->context().add(qmlDesignerMainContext);
context->context().add(qmlDesignerFormEditorContext); context->context().add(qmlDesignerFormEditorContext);
context->context().add(qmlDesignerEditor3dContext); context->context().add(qmlDesignerEditor3dContext);
context->context().add(qmlDesignerNavigatorContext); context->context().add(qmlDesignerNavigatorContext);
context->context().add(qmlDesignerMaterialBrowserContext);
context->context().add(ProjectExplorer::Constants::QMLJS_LANGUAGE_ID); context->context().add(ProjectExplorer::Constants::QMLJS_LANGUAGE_ID);
d->shortCutManager.registerActions(qmlDesignerMainContext, qmlDesignerFormEditorContext, d->shortCutManager.registerActions(qmlDesignerMainContext, qmlDesignerFormEditorContext,
qmlDesignerEditor3dContext, qmlDesignerNavigatorContext); qmlDesignerEditor3dContext, qmlDesignerNavigatorContext,
qmlDesignerMaterialBrowserContext);
const QStringList mimeTypes = { QmlJSTools::Constants::QML_MIMETYPE, const QStringList mimeTypes = { QmlJSTools::Constants::QML_MIMETYPE,
QmlJSTools::Constants::QMLUI_MIMETYPE }; QmlJSTools::Constants::QMLUI_MIMETYPE };

View File

@@ -1011,7 +1011,6 @@ Project {
"timelineeditor/preseteditor.h", "timelineeditor/preseteditor.h",
"timelineeditor/setframevaluedialog.cpp", "timelineeditor/setframevaluedialog.cpp",
"timelineeditor/setframevaluedialog.h", "timelineeditor/setframevaluedialog.h",
"timelineeditor/setframevaluedialog.ui",
"timelineeditor/splineeditor.cpp", "timelineeditor/splineeditor.cpp",
"timelineeditor/splineeditor.h", "timelineeditor/splineeditor.h",
"timelineeditor/timeline.qrc", "timelineeditor/timeline.qrc",

View File

@@ -77,8 +77,11 @@ ShortCutManager::ShortCutManager()
void ShortCutManager::registerActions(const Core::Context &qmlDesignerMainContext, void ShortCutManager::registerActions(const Core::Context &qmlDesignerMainContext,
const Core::Context &qmlDesignerFormEditorContext, const Core::Context &qmlDesignerFormEditorContext,
const Core::Context &qmlDesignerEditor3DContext, const Core::Context &qmlDesignerEditor3DContext,
const Core::Context &qmlDesignerNavigatorContext) const Core::Context &qmlDesignerNavigatorContext,
const Core::Context &qmlDesignerMaterialBrowserContext)
{ {
Q_UNUSED(qmlDesignerMaterialBrowserContext)
Core::ActionContainer *editMenu = Core::ActionManager::actionContainer(Core::Constants::M_EDIT); Core::ActionContainer *editMenu = Core::ActionManager::actionContainer(Core::Constants::M_EDIT);
Core::ActionContainer *fileMenu = Core::ActionManager::actionContainer(Core::Constants::M_FILE); Core::ActionContainer *fileMenu = Core::ActionManager::actionContainer(Core::Constants::M_FILE);
@@ -195,9 +198,12 @@ void ShortCutManager::registerActions(const Core::Context &qmlDesignerMainContex
m_pasteAction.setEnabled(true); m_pasteAction.setEnabled(true);
}); });
connect(Core::ICore::instance(), &Core::ICore::contextChanged, this, [&designerActionManager, this](const Core::Context &context){ connect(Core::ICore::instance(), &Core::ICore::contextChanged, this, [&](const Core::Context &context) {
if (!context.contains(Constants::C_QMLFORMEDITOR) && !context.contains(Constants::C_QMLEDITOR3D) && !context.contains(Constants::C_QMLNAVIGATOR)) { isMatBrowserActive = context.contains(Constants::C_QMLMATERIALBROWSER);
m_deleteAction.setEnabled(false);
if (!context.contains(Constants::C_QMLFORMEDITOR) && !context.contains(Constants::C_QMLEDITOR3D)
&& !context.contains(Constants::C_QMLNAVIGATOR)) {
m_deleteAction.setEnabled(isMatBrowserActive);
m_cutAction.setEnabled(false); m_cutAction.setEnabled(false);
m_copyAction.setEnabled(false); m_copyAction.setEnabled(false);
m_pasteAction.setEnabled(false); m_pasteAction.setEnabled(false);
@@ -249,8 +255,12 @@ void ShortCutManager::redo()
void ShortCutManager::deleteSelected() void ShortCutManager::deleteSelected()
{ {
if (currentDesignDocument()) if (isMatBrowserActive) {
DesignerActionManager &designerActionManager = QmlDesignerPlugin::instance()->viewManager().designerActionManager();
designerActionManager.view()->emitCustomNotification("delete_selected_material");
} else if (currentDesignDocument()) {
currentDesignDocument()->deleteSelected(); currentDesignDocument()->deleteSelected();
}
} }
void ShortCutManager::cutSelected() void ShortCutManager::cutSelected()

View File

@@ -47,7 +47,8 @@ public:
void registerActions(const Core::Context &qmlDesignerMainContext, void registerActions(const Core::Context &qmlDesignerMainContext,
const Core::Context &qmlDesignerFormEditorContext, const Core::Context &qmlDesignerFormEditorContext,
const Core::Context &qmlDesignerEditor3DContext, const Core::Context &qmlDesignerEditor3DContext,
const Core::Context &qmlDesignerNavigatorContext); const Core::Context &qmlDesignerNavigatorContext,
const Core::Context &qmlDesignerMaterialBrowserContext);
void connectUndoActions(DesignDocument *designDocument); void connectUndoActions(DesignDocument *designDocument);
void disconnectUndoActions(DesignDocument *designDocument); void disconnectUndoActions(DesignDocument *designDocument);
@@ -84,6 +85,8 @@ private:
QAction m_pasteAction; QAction m_pasteAction;
QAction m_selectAllAction; QAction m_selectAllAction;
QAction m_escapeAction; QAction m_escapeAction;
bool isMatBrowserActive = false;
}; };
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -1,18 +1,25 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2017 The Qt Company Ltd ** Copyright (C) 2017 The Qt Company Ltd.
** All rights reserved. ** Contact: https://www.qt.io/licensing/
** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us
** **
** This file is part of the Qt Enterprise QML Live Preview Add-on. ** This file is part of Qt Creator.
** **
** Licensees holding valid Qt Enterprise licenses may use this file in ** Commercial License Usage
** accordance with the Qt Enterprise License Agreement provided with the ** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in ** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. ** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** **
** If you have questions regarding the use of this file, please use ** GNU General Public License Usage
** contact form at http://www.qt.io/contact-us ** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
** **
****************************************************************************/ ****************************************************************************/

View File

@@ -1,18 +1,25 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2017 The Qt Company Ltd ** Copyright (C) 2017 The Qt Company Ltd.
** All rights reserved. ** Contact: https://www.qt.io/licensing/
** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us
** **
** This file is part of the Qt Enterprise QML Live Preview Add-on. ** This file is part of Qt Creator.
** **
** Licensees holding valid Qt Enterprise licenses may use this file in ** Commercial License Usage
** accordance with the Qt Enterprise License Agreement provided with the ** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in ** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. ** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
** **
** If you have questions regarding the use of this file, please use ** GNU General Public License Usage
** contact form at http://www.qt.io/contact-us ** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
** **
****************************************************************************/ ****************************************************************************/

View File

@@ -39,12 +39,6 @@ ColorSettings::ColorSettings(QWidget *parent)
m_ui.setupUi(this); m_ui.setupUi(this);
m_ui.m_colorThemeView->setEnabled(false); m_ui.m_colorThemeView->setEnabled(false);
connect(m_ui.m_comboColorThemes, &QComboBox::currentIndexChanged,
this, &ColorSettings::selectTheme);
connect(m_ui.m_colorThemeView, &ColorThemeView::colorChanged,
this, &ColorSettings::updateCurrentColors);
connect(m_ui.m_addColorTheme, &QToolButton::clicked, this, &ColorSettings::createTheme);
connect(m_ui.m_removeColorTheme, &QToolButton::clicked, this, &ColorSettings::removeTheme);
const QSettings *s = Core::ICore::settings(); const QSettings *s = Core::ICore::settings();
@@ -54,6 +48,14 @@ ColorSettings::ColorSettings(QWidget *parent)
for (auto it = m_colorThemes.cbegin(); it != m_colorThemes.cend(); ++it) for (auto it = m_colorThemes.cbegin(); it != m_colorThemes.cend(); ++it)
m_ui.m_comboColorThemes->addItem(it.key()); m_ui.m_comboColorThemes->addItem(it.key());
m_ui.m_comboColorThemes->setCurrentText(s->value(Constants::C_SETTINGS_COLORSETTINGS_CURRENTCOLORTHEME).toString()); m_ui.m_comboColorThemes->setCurrentText(s->value(Constants::C_SETTINGS_COLORSETTINGS_CURRENTCOLORTHEME).toString());
connect(m_ui.m_comboColorThemes,
&QComboBox::currentIndexChanged,
this,
&ColorSettings::selectTheme);
connect(m_ui.m_colorThemeView, &ColorThemeView::colorChanged, this, &ColorSettings::updateCurrentColors);
connect(m_ui.m_addColorTheme, &QToolButton::clicked, this, &ColorSettings::createTheme);
connect(m_ui.m_removeColorTheme, &QToolButton::clicked, this, &ColorSettings::removeTheme);
} }
void ColorSettings::save() void ColorSettings::save()

View File

@@ -456,21 +456,28 @@ DataModelDownloader::DataModelDownloader(QObject * /* parent */)
&FileDownloader::progressChanged, &FileDownloader::progressChanged,
this, this,
&DataModelDownloader::progressChanged); &DataModelDownloader::progressChanged);
connect(&m_fileDownloader,
&FileDownloader::downloadFailed,
this,
&DataModelDownloader::downloadFailed);
} }
void DataModelDownloader::start() bool DataModelDownloader::start()
{ {
if (!enableDownload()) { if (!enableDownload()) {
m_available = false; m_available = false;
emit availableChanged(); emit availableChanged();
return; return false;
} }
m_fileDownloader.setUrl(QUrl::fromUserInput( m_fileDownloader.setUrl(QUrl::fromUserInput(
"https://download.qt.io/learning/examples/qtdesignstudio/dataImports.zip")); "https://download.qt.io/learning/examples/qtdesignstudio/dataImports.zip"));
connect(&m_fileDownloader, &FileDownloader::availableChanged, this, [this]() { bool started = false;
connect(&m_fileDownloader, &FileDownloader::availableChanged, this, [this, &started]() {
m_available = m_fileDownloader.available(); m_available = m_fileDownloader.available();
@@ -484,6 +491,8 @@ void DataModelDownloader::start()
if (!m_forceDownload && (m_fileDownloader.lastModified() <= m_birthTime)) if (!m_forceDownload && (m_fileDownloader.lastModified() <= m_birthTime))
return; return;
started = true;
m_fileDownloader.start(); m_fileDownloader.start();
connect(&m_fileDownloader, &FileDownloader::finishedChanged, this, [this]() { connect(&m_fileDownloader, &FileDownloader::finishedChanged, this, [this]() {
if (m_fileDownloader.finished()) { if (m_fileDownloader.finished()) {
@@ -501,6 +510,7 @@ void DataModelDownloader::start()
} }
}); });
}); });
return started;
} }
bool DataModelDownloader::exists() const bool DataModelDownloader::exists() const

View File

@@ -163,7 +163,7 @@ class DataModelDownloader : public QObject
public: public:
explicit DataModelDownloader(QObject *parent = nullptr); explicit DataModelDownloader(QObject *parent = nullptr);
void start(); bool start();
bool exists() const; bool exists() const;
bool available() const; bool available() const;
Utils::FilePath targetFolder() const; Utils::FilePath targetFolder() const;
@@ -174,6 +174,7 @@ signals:
void finished(); void finished();
void availableChanged(); void availableChanged();
void progressChanged(); void progressChanged();
void downloadFailed();
private: private:
FileDownloader m_fileDownloader; FileDownloader m_fileDownloader;

View File

@@ -453,7 +453,11 @@ public:
~WelcomeMode() override; ~WelcomeMode() override;
private: private:
QQuickWidget *m_modeWidget = nullptr; void setupQuickWidget(const QString &welcomePagePath);
void createQuickWidget();
QQuickWidget *m_quickWidget = nullptr;
QWidget *m_modeWidget = nullptr;
DataModelDownloader *m_dataModelDownloader = nullptr; DataModelDownloader *m_dataModelDownloader = nullptr;
}; };
@@ -637,31 +641,31 @@ WelcomeMode::WelcomeMode()
QFontDatabase::addApplicationFont(":/studiofonts/TitilliumWeb-Regular.ttf"); QFontDatabase::addApplicationFont(":/studiofonts/TitilliumWeb-Regular.ttf");
ExampleCheckout::registerTypes(); ExampleCheckout::registerTypes();
m_modeWidget = new QQuickWidget; createQuickWidget();
m_modeWidget->setMinimumSize(640, 480);
m_modeWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
QmlDesigner::Theme::setupTheme(m_modeWidget->engine());
m_modeWidget->engine()->addImportPath("qrc:/studiofonts");
QmlDesigner::QmlDesignerPlugin::registerPreviewImageProvider(m_modeWidget->engine());
m_modeWidget->engine()->setOutputWarningsToStandardError(false);
if (forceDownLoad() || !readme.exists()) // Only downloads contain the readme if (forceDownLoad() || !readme.exists()) // Only downloads contain the readme
m_dataModelDownloader->setForceDownload(true); m_dataModelDownloader->setForceDownload(true);
connect(m_dataModelDownloader, &DataModelDownloader::progressChanged, this, [this](){ connect(m_dataModelDownloader, &DataModelDownloader::progressChanged, this, [this](){
m_modeWidget->rootObject()->setProperty("loadingProgress", m_dataModelDownloader->progress()); m_quickWidget->rootObject()->setProperty("loadingProgress", m_dataModelDownloader->progress());
}); });
connect(m_dataModelDownloader, &DataModelDownloader::finished, this, [this](){ m_quickWidget->setEnabled(false);
auto source = m_modeWidget->source();
m_modeWidget->engine()->clearComponentCache(); connect(m_dataModelDownloader, &DataModelDownloader::finished, this, [this, welcomePagePath]() {
m_modeWidget->setSource(source); delete m_quickWidget;
m_modeWidget->rootObject()->setProperty("loadingProgress", 100); createQuickWidget();
setupQuickWidget(welcomePagePath);
m_modeWidget->layout()->addWidget(m_quickWidget);
}); });
m_dataModelDownloader->start(); connect(m_dataModelDownloader, &DataModelDownloader::downloadFailed, this, [this]() {
m_quickWidget->setEnabled(true);
});
if (m_dataModelDownloader->start())
m_quickWidget->setEnabled(false);
/* /*
connect(Core::ModeManager::instance(), &Core::ModeManager::currentModeChanged, this, [this](Utils::Id mode){ connect(Core::ModeManager::instance(), &Core::ModeManager::currentModeChanged, this, [this](Utils::Id mode){
@@ -669,36 +673,14 @@ WelcomeMode::WelcomeMode()
m_modeWidget->rootObject()->setProperty("active", active); m_modeWidget->rootObject()->setProperty("active", active);
}); });
*/ */
setupQuickWidget(welcomePagePath);
if (!useNewWelcomePage()) { QVBoxLayout *boxLayout = new QVBoxLayout();
boxLayout->setContentsMargins(0, 0, 0, 0);
#ifdef QT_DEBUG
m_modeWidget->engine()->addImportPath(QLatin1String(STUDIO_QML_PATH)
+ "welcomepage/imports");
m_modeWidget->setSource(QUrl::fromLocalFile(QLatin1String(STUDIO_QML_PATH)
+ "welcomepage/main.qml"));
#else
m_modeWidget->engine()->addImportPath("qrc:/qml/welcomepage/imports");
m_modeWidget->setSource(QUrl("qrc:/qml/welcomepage/main.qml"));
#endif
} else {
m_modeWidget->engine()->addImportPath(Core::ICore::resourcePath("qmldesigner/propertyEditorQmlSources/imports").toString());
m_modeWidget->engine()->addImportPath(welcomePagePath + "/imports");
m_modeWidget->engine()->addImportPath(m_dataModelDownloader->targetFolder().toString());
m_modeWidget->setSource(QUrl::fromLocalFile(welcomePagePath + "/main.qml"));
QShortcut *updateShortcut = nullptr;
if (Utils::HostOsInfo::isMacHost())
updateShortcut = new QShortcut(QKeySequence(Qt::ALT | Qt::Key_F5), m_modeWidget);
else
updateShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_F5), m_modeWidget);
connect(updateShortcut, &QShortcut::activated, this, [this, welcomePagePath](){
m_modeWidget->setSource(QUrl::fromLocalFile(welcomePagePath + "/main.qml"));
});
}
m_modeWidget = new QWidget;
m_modeWidget->setLayout(boxLayout);
boxLayout->addWidget(m_quickWidget);
setWidget(m_modeWidget); setWidget(m_modeWidget);
QStringList designStudioQchPathes QStringList designStudioQchPathes
@@ -749,6 +731,51 @@ WelcomeMode::~WelcomeMode()
delete m_modeWidget; delete m_modeWidget;
} }
void WelcomeMode::setupQuickWidget(const QString &welcomePagePath)
{
if (!useNewWelcomePage()) {
#ifdef QT_DEBUG
m_quickWidget->engine()->addImportPath(QLatin1String(STUDIO_QML_PATH)
+ "welcomepage/imports");
m_quickWidget->setSource(
QUrl::fromLocalFile(QLatin1String(STUDIO_QML_PATH) + "welcomepage/main.qml"));
#else
m_quickWidget->engine()->addImportPath("qrc:/qml/welcomepage/imports");
m_quickWidget->setSource(QUrl("qrc:/qml/welcomepage/main.qml"));
#endif
} else {
m_quickWidget->engine()->addImportPath(Core::ICore::resourcePath("qmldesigner/propertyEditorQmlSources/imports").toString());
m_quickWidget->engine()->addImportPath(welcomePagePath + "/imports");
m_quickWidget->engine()->addImportPath(m_dataModelDownloader->targetFolder().toString());
m_quickWidget->setSource(QUrl::fromLocalFile(welcomePagePath + "/main.qml"));
QShortcut *updateShortcut = nullptr;
if (Utils::HostOsInfo::isMacHost())
updateShortcut = new QShortcut(QKeySequence(Qt::ALT | Qt::Key_F5), m_quickWidget);
else
updateShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_F5), m_quickWidget);
connect(updateShortcut, &QShortcut::activated, this, [this, welcomePagePath](){
m_quickWidget->setSource(QUrl::fromLocalFile(welcomePagePath + "/main.qml"));
});
}
}
void WelcomeMode::createQuickWidget()
{
m_quickWidget = new QQuickWidget;
m_quickWidget->setMinimumSize(640, 480);
m_quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
QmlDesigner::Theme::setupTheme(m_quickWidget->engine());
m_quickWidget->engine()->addImportPath("qrc:/studiofonts");
QmlDesigner::QmlDesignerPlugin::registerPreviewImageProvider(m_quickWidget->engine());
m_quickWidget->engine()->setOutputWarningsToStandardError(false);
}
StudioSettingsPage::StudioSettingsPage() StudioSettingsPage::StudioSettingsPage()
: m_buildCheckBox(new QCheckBox(tr("Build"))) : m_buildCheckBox(new QCheckBox(tr("Build")))
, m_debugCheckBox(new QCheckBox(tr("Debug"))) , m_debugCheckBox(new QCheckBox(tr("Debug")))