forked from qt-creator/qt-creator
Merge "Merge remote-tracking branch 'origin/8.0'"
This commit is contained in:
23
dist/changes-8.0.1.md
vendored
23
dist/changes-8.0.1.md
vendored
@@ -13,8 +13,14 @@ the public Git repository. For example:
|
||||
Editing
|
||||
-------
|
||||
|
||||
* Delayed context menu tooltip action creation
|
||||
* Cached the last QIcon created from a Utils::Icon
|
||||
|
||||
### C++
|
||||
|
||||
* Prevent opening unneeded generated ui header files in clangd
|
||||
* Fixed documents getting opened in wrong clangd
|
||||
|
||||
Projects
|
||||
--------
|
||||
|
||||
@@ -42,17 +48,34 @@ Platforms
|
||||
### Baremetal
|
||||
|
||||
* 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:
|
||||
--------------------------------
|
||||
Alexander Akulich
|
||||
Alibek Omarov
|
||||
André Pönitz
|
||||
Christian Kandeler
|
||||
Christian Stenger
|
||||
Cristian Adam
|
||||
David Schulz
|
||||
Dmitry Kovalev
|
||||
Eike Ziller
|
||||
Ivan Komissarov
|
||||
Jaroslaw Kobus
|
||||
Knud Dollereder
|
||||
Mahmoud Badri
|
||||
Marcus Tillmanns
|
||||
Mats Honkamaa
|
||||
Miikka Heikkinen
|
||||
Orgad Shaneh
|
||||
Oswald Buddenhagen
|
||||
Samuel Ghinet
|
||||
Thomas Hartmann
|
||||
Vikas Pachdha
|
||||
|
@@ -165,6 +165,16 @@
|
||||
To disable the Python language server, deselect
|
||||
\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
|
||||
|
||||
The locator enables you to browse not only files, but any items defined by
|
||||
|
@@ -43,10 +43,8 @@
|
||||
|
||||
\section1 2D Assets
|
||||
|
||||
You can use the Qt Installer to install \QB if you have a commercial
|
||||
\QDS license. You can also purchase a \QB license separately from the
|
||||
\l{https://marketplace.qt.io/}{Qt Marketplace} and then install \QB using
|
||||
the Qt Installer.
|
||||
You can use the Qt Installer to install \QB if you have a
|
||||
\QDS enterprise license.
|
||||
|
||||
\table
|
||||
\row
|
||||
|
@@ -30,10 +30,10 @@
|
||||
|
||||
\title Setting Up \QBPS
|
||||
|
||||
You can purchase a \QBPS license from the \l{https://marketplace.qt.io/}
|
||||
{Qt Marketplace}, and then use the Qt Installer to have the \QBPS
|
||||
installation package copied to the following path in your Qt installation
|
||||
folder:
|
||||
\QBPS is included in the
|
||||
\l{https://www.qt.io/pricing}{Qt Design Studio Enterprise license}.
|
||||
You can use the Qt Installer to have the \QBPS plugin package copied to the
|
||||
following path in your Qt installation folder:
|
||||
|
||||
\list
|
||||
\li On Windows: \c {Tools\QtDesignStudio\photoshop_bridge}
|
||||
|
@@ -30,10 +30,10 @@
|
||||
|
||||
\title Setting Up \QBSK
|
||||
|
||||
You can purchase a \QBSK license from the \l{https://marketplace.qt.io/}
|
||||
{Qt Marketplace}, and then use the Qt Installer to have the \QBSK
|
||||
plugin package copied to the following path in your Qt installation
|
||||
folder:
|
||||
\QBSK is included in the
|
||||
\l{https://www.qt.io/pricing}{Qt Design Studio Enterprise license}.
|
||||
You can use the Qt Installer to have the \QBSK plugin package copied to the
|
||||
following path in your Qt installation folder:
|
||||
|
||||
\list
|
||||
\li On Windows:
|
||||
|
@@ -30,10 +30,10 @@
|
||||
|
||||
\title Setting Up \QBXD
|
||||
|
||||
You can purchase a \QBXD license from the \l{https://marketplace.qt.io/}
|
||||
{Qt Marketplace}, and then use the Qt Installer to have the \QBXD
|
||||
plugin package copied to the following path in your Qt installation
|
||||
folder:
|
||||
\QBXD is included in the
|
||||
\l{https://www.qt.io/pricing}{Qt Design Studio Enterprise license}.
|
||||
You can use the Qt Installer to have the \QBXD plugin package copied to the
|
||||
following path in your Qt installation folder:
|
||||
|
||||
\list
|
||||
\li On Windows:
|
||||
|
@@ -16,6 +16,8 @@
|
||||
<file>mockfiles/images/static_floor.png</file>
|
||||
<file>mockfiles/images/spot.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/AreaLightHandle.qml</file>
|
||||
<file>mockfiles/qt5/Arrow.qml</file>
|
||||
|
@@ -18,6 +18,8 @@
|
||||
<file>mockfiles/images/floor_tex.png</file>
|
||||
<file>mockfiles/images/spot.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/AreaLightHandle.qml</file>
|
||||
<file>mockfiles/qt6/Arrow.qml</file>
|
||||
|
Binary file not shown.
Binary file not shown.
@@ -29,8 +29,12 @@ View3D {
|
||||
id: root
|
||||
anchors.fill: parent
|
||||
environment: sceneEnv
|
||||
camera: envMode === "SkyBox" && envValue === "preview_studio" ? studioCamera : defaultCamera
|
||||
|
||||
property Material previewMaterial
|
||||
property string envMode
|
||||
property string envValue
|
||||
property string modelSrc: "#Sphere"
|
||||
|
||||
function fitToViewPort(closeUp)
|
||||
{
|
||||
@@ -41,28 +45,59 @@ View3D {
|
||||
id: sceneEnv
|
||||
antialiasingMode: SceneEnvironment.MSAA
|
||||
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 {
|
||||
DirectionalLight {
|
||||
eulerRotation.x: -26
|
||||
eulerRotation.y: -57
|
||||
eulerRotation.y: modelSrc === "#Cube" ? -10 : -50
|
||||
brightness: envMode !== "SkyBox" ? 100 : 0
|
||||
}
|
||||
|
||||
PerspectiveCamera {
|
||||
y: 125.331
|
||||
z: 120
|
||||
eulerRotation.x: -31
|
||||
id: defaultCamera
|
||||
y: 70
|
||||
z: 200
|
||||
eulerRotation.x: -5.71
|
||||
clipNear: 1
|
||||
clipFar: 1000
|
||||
}
|
||||
|
||||
Model {
|
||||
id: model
|
||||
PerspectiveCamera {
|
||||
id: studioCamera
|
||||
y: 232
|
||||
z: 85
|
||||
eulerRotation.x: -64.98
|
||||
clipNear: 1
|
||||
clipFar: 1000
|
||||
}
|
||||
|
||||
Node {
|
||||
rotation: root.camera.rotation
|
||||
y: 50
|
||||
source: "#Sphere"
|
||||
materials: previewMaterial
|
||||
Node {
|
||||
y: modelSrc === "#Cone" ? -40 : 10
|
||||
eulerRotation.x: 35
|
||||
Model {
|
||||
id: model
|
||||
source: modelSrc ? modelSrc : "#Sphere"
|
||||
eulerRotation.y: 45
|
||||
materials: previewMaterial
|
||||
scale: !modelSrc || modelSrc === "#Sphere"
|
||||
? Qt.vector3d(1.7, 1.7, 1.7) : Qt.vector3d(1.2, 1.2, 1.2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -50,25 +50,28 @@ Item {
|
||||
view.destroy();
|
||||
}
|
||||
|
||||
function createViewForObject(obj)
|
||||
function createViewForObject(obj, env, envValue, model)
|
||||
{
|
||||
if (obj instanceof Material)
|
||||
createViewForMaterial(obj);
|
||||
createViewForMaterial(obj, env, envValue, model);
|
||||
else if (obj instanceof Model)
|
||||
createViewForModel(obj);
|
||||
else if (obj instanceof Node)
|
||||
createViewForNode(obj);
|
||||
}
|
||||
|
||||
function createViewForMaterial(material)
|
||||
function createViewForMaterial(material, env, envValue, model)
|
||||
{
|
||||
if (!materialViewComponent)
|
||||
materialViewComponent = Qt.createComponent("MaterialNodeView.qml");
|
||||
|
||||
// Always recreate the view to ensure material is up to date
|
||||
if (materialViewComponent.status === Component.Ready)
|
||||
view = materialViewComponent.createObject(viewRect, {"previewMaterial": material});
|
||||
|
||||
if (materialViewComponent.status === Component.Ready) {
|
||||
view = materialViewComponent.createObject(viewRect, {"previewMaterial": material,
|
||||
"envMode": env,
|
||||
"envValue": envValue,
|
||||
"modelSrc": model});
|
||||
}
|
||||
previewObject = material;
|
||||
}
|
||||
|
||||
|
@@ -29,8 +29,12 @@ View3D {
|
||||
id: root
|
||||
anchors.fill: parent
|
||||
environment: sceneEnv
|
||||
camera: envMode === "SkyBox" && envValue === "preview_studio" ? studioCamera : defaultCamera
|
||||
|
||||
property Material previewMaterial
|
||||
property string envMode
|
||||
property string envValue
|
||||
property string modelSrc: "#Sphere"
|
||||
|
||||
function fitToViewPort(closeUp)
|
||||
{
|
||||
@@ -41,30 +45,79 @@ View3D {
|
||||
id: sceneEnv
|
||||
antialiasingMode: SceneEnvironment.MSAA
|
||||
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 {
|
||||
DirectionalLight {
|
||||
eulerRotation.x: -26
|
||||
eulerRotation.y: -57
|
||||
eulerRotation.y: modelSrc === "#Cube" ? -10 : -50
|
||||
brightness: envMode !== "SkyBox" ? 1 : 0
|
||||
}
|
||||
|
||||
PerspectiveCamera {
|
||||
y: 125.331
|
||||
z: 120
|
||||
eulerRotation.x: -31
|
||||
id: defaultCamera
|
||||
y: 70
|
||||
z: 200
|
||||
eulerRotation.x: -5.71
|
||||
clipNear: 1
|
||||
clipFar: 1000
|
||||
}
|
||||
|
||||
Model {
|
||||
id: model
|
||||
readonly property bool _edit3dLocked: true // Make this non-pickable
|
||||
|
||||
y: 50
|
||||
source: "#Sphere"
|
||||
materials: previewMaterial
|
||||
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 {
|
||||
id: model
|
||||
readonly property bool _edit3dLocked: true // Make this non-pickable
|
||||
source: modelSrc ? modelSrc : "#Sphere"
|
||||
eulerRotation.y: 45
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -50,25 +50,31 @@ Item {
|
||||
view.destroy();
|
||||
}
|
||||
|
||||
function createViewForObject(obj)
|
||||
function createViewForObject(obj, env, envValue, model)
|
||||
{
|
||||
backgroundView3d.visible = true;
|
||||
if (obj instanceof Material)
|
||||
createViewForMaterial(obj);
|
||||
createViewForMaterial(obj, env, envValue, model);
|
||||
else if (obj instanceof Model)
|
||||
createViewForModel(obj);
|
||||
else if (obj instanceof Node)
|
||||
createViewForNode(obj);
|
||||
}
|
||||
|
||||
function createViewForMaterial(material)
|
||||
function createViewForMaterial(material, env, envValue, model)
|
||||
{
|
||||
if (!materialViewComponent)
|
||||
materialViewComponent = Qt.createComponent("MaterialNodeView.qml");
|
||||
|
||||
// Always recreate the view to ensure material is up to date
|
||||
if (materialViewComponent.status === Component.Ready)
|
||||
view = materialViewComponent.createObject(viewRect, {"previewMaterial": material});
|
||||
|
||||
if (materialViewComponent.status === Component.Ready) {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -129,6 +135,7 @@ Item {
|
||||
|
||||
// Use View3D instead of static image to make background look good on all resolutions
|
||||
View3D {
|
||||
id: backgroundView3d
|
||||
anchors.fill: parent
|
||||
environment: sceneEnv
|
||||
|
||||
|
@@ -339,6 +339,22 @@ void Qt5InformationNodeInstanceServer::resolveImportSupport()
|
||||
#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(
|
||||
[[maybe_unused]] const QVector<PropertyValueContainer> &valueChanges)
|
||||
{
|
||||
@@ -1176,7 +1192,10 @@ void Qt5InformationNodeInstanceServer::doRenderModelNode3DImageView(
|
||||
} else {
|
||||
QMetaObject::invokeMethod(
|
||||
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
|
||||
@@ -2010,6 +2029,7 @@ void Qt5InformationNodeInstanceServer::createScene(const CreateSceneCommand &com
|
||||
if (ViewConfig::isQuick3DMode()) {
|
||||
setup3DEditView(instanceList, command);
|
||||
updateRotationBlocks(command.auxiliaryChanges);
|
||||
updateMaterialPreviewData(command.auxiliaryChanges);
|
||||
}
|
||||
|
||||
QObject::connect(&m_renderModelNodeImageViewTimer, &QTimer::timeout,
|
||||
@@ -2414,6 +2434,7 @@ void Qt5InformationNodeInstanceServer::requestModelNodePreviewImage(const Reques
|
||||
void Qt5InformationNodeInstanceServer::changeAuxiliaryValues(const ChangeAuxiliaryCommand &command)
|
||||
{
|
||||
updateRotationBlocks(command.auxiliaryChanges);
|
||||
updateMaterialPreviewData(command.auxiliaryChanges);
|
||||
Qt5NodeInstanceServer::changeAuxiliaryValues(command);
|
||||
render3DEditView();
|
||||
}
|
||||
|
@@ -145,6 +145,7 @@ private:
|
||||
void updateLockedAndHiddenStates(const QSet<ServerNodeInstance> &instances);
|
||||
void handleInputEvents();
|
||||
void resolveImportSupport();
|
||||
void updateMaterialPreviewData(const QVector<PropertyValueContainer> &valueChanges);
|
||||
void updateRotationBlocks(const QVector<PropertyValueContainer> &valueChanges);
|
||||
void removeRotationBlocks(const QVector<qint32> &instanceIds);
|
||||
|
||||
@@ -191,6 +192,13 @@ private:
|
||||
QObject *m_3dHelper = nullptr;
|
||||
int m_need3DEditViewRender = 0;
|
||||
QSet<QObject *> m_dynamicObjectConstructors;
|
||||
|
||||
struct PreviewData {
|
||||
QString env;
|
||||
QString envValue;
|
||||
QString model;
|
||||
};
|
||||
PreviewData m_materialPreviewData;
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
@@ -39,6 +39,8 @@ Item {
|
||||
property var currentMaterial: null
|
||||
property int currentMaterialIdx: 0
|
||||
|
||||
property var matSectionsModel: []
|
||||
|
||||
// Called also from C++ to close context menu on focus out
|
||||
function closeContextMenu()
|
||||
{
|
||||
@@ -67,8 +69,10 @@ Item {
|
||||
acceptedButtons: Qt.RightButton
|
||||
|
||||
onClicked: {
|
||||
root.currentMaterial = null
|
||||
contextMenu.popup()
|
||||
if (!materialBrowserModel.hasMaterialRoot) {
|
||||
root.currentMaterial = null
|
||||
contextMenu.popup()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,27 +96,77 @@ Item {
|
||||
|
||||
StudioControls.MenuItem {
|
||||
text: qsTr("Apply to selected (replace)")
|
||||
enabled: currentMaterial && materialBrowserModel.hasModelSelection
|
||||
onTriggered: materialBrowserModel.applyToSelected(currentMaterial.materialInternalId, false)
|
||||
enabled: root.currentMaterial && materialBrowserModel.hasModelSelection
|
||||
onTriggered: materialBrowserModel.applyToSelected(root.currentMaterial.materialInternalId, false)
|
||||
}
|
||||
|
||||
StudioControls.MenuItem {
|
||||
text: qsTr("Apply to selected (add)")
|
||||
enabled: currentMaterial && materialBrowserModel.hasModelSelection
|
||||
onTriggered: materialBrowserModel.applyToSelected(currentMaterial.materialInternalId, true)
|
||||
enabled: root.currentMaterial && materialBrowserModel.hasModelSelection
|
||||
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 {
|
||||
text: qsTr("Duplicate")
|
||||
enabled: currentMaterial
|
||||
onTriggered: materialBrowserModel.duplicateMaterial(currentMaterialIdx)
|
||||
enabled: root.currentMaterial
|
||||
onTriggered: materialBrowserModel.duplicateMaterial(root.currentMaterialIdx)
|
||||
}
|
||||
|
||||
StudioControls.MenuItem {
|
||||
text: qsTr("Rename")
|
||||
enabled: currentMaterial
|
||||
enabled: root.currentMaterial
|
||||
onTriggered: {
|
||||
var item = gridRepeater.itemAt(currentMaterialIdx);
|
||||
var item = gridRepeater.itemAt(root.currentMaterialIdx);
|
||||
if (item)
|
||||
item.startRename();
|
||||
}
|
||||
@@ -120,9 +174,9 @@ Item {
|
||||
|
||||
StudioControls.MenuItem {
|
||||
text: qsTr("Delete")
|
||||
enabled: currentMaterial
|
||||
enabled: root.currentMaterial
|
||||
|
||||
onTriggered: materialBrowserModel.deleteMaterial(currentMaterialIdx)
|
||||
onTriggered: materialBrowserModel.deleteMaterial(root.currentMaterialIdx)
|
||||
}
|
||||
|
||||
StudioControls.MenuSeparator {}
|
||||
@@ -141,6 +195,7 @@ Item {
|
||||
|
||||
Row {
|
||||
width: root.width
|
||||
enabled: !materialBrowserModel.hasMaterialRoot && materialBrowserModel.hasQuick3DImport
|
||||
|
||||
SearchBox {
|
||||
id: searchBox
|
||||
@@ -165,22 +220,22 @@ Item {
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
font.pixelSize: StudioTheme.Values.baseFontSize
|
||||
leftPadding: 10
|
||||
visible: materialBrowserModel.hasQuick3DImport && materialBrowserModel.isEmpty && !searchBox.isEmpty()
|
||||
visible: materialBrowserModel.hasQuick3DImport && materialBrowserModel.isEmpty
|
||||
&& !searchBox.isEmpty() && !materialBrowserModel.hasMaterialRoot
|
||||
}
|
||||
|
||||
Text {
|
||||
text: qsTr("There are no materials in this project.<br>Select '<b>+</b>' to create one.")
|
||||
textFormat: Text.RichText
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
font.pixelSize: StudioTheme.Values.mediumFontSize
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
topPadding: 30
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
visible: materialBrowserModel.hasQuick3DImport && materialBrowserModel.isEmpty && searchBox.isEmpty()
|
||||
}
|
||||
text: {
|
||||
if (materialBrowserModel.hasMaterialRoot)
|
||||
qsTr("<b>Material Browser</b> is disabled inside a material component.")
|
||||
else if (!materialBrowserModel.hasQuick3DImport)
|
||||
qsTr("To use <b>Material Browser</b>, first add the QtQuick3D module in the <b>Components</b> view.")
|
||||
else if (materialBrowserModel.isEmpty && searchBox.isEmpty())
|
||||
qsTr("There are no materials in this project.<br>Select '<b>+</b>' to create one.")
|
||||
else
|
||||
""
|
||||
}
|
||||
|
||||
Text {
|
||||
text: qsTr("To use <b>Material Browser</b>, first add the QtQuick3D module in the <b>Components</b> view.");
|
||||
textFormat: Text.RichText
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
font.pixelSize: StudioTheme.Values.mediumFontSize
|
||||
@@ -188,8 +243,7 @@ Item {
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.WordWrap
|
||||
width: root.width
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
visible: !materialBrowserModel.hasQuick3DImport
|
||||
visible: text !== ""
|
||||
}
|
||||
|
||||
ScrollView {
|
||||
|
@@ -33,6 +33,12 @@ PropertyEditorPane {
|
||||
id: root
|
||||
|
||||
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 {
|
||||
id: col
|
||||
|
@@ -31,6 +31,8 @@ PropertyEditorPane {
|
||||
id: itemPane
|
||||
|
||||
signal toolBarAction(int action)
|
||||
signal previewEnvChanged(string env)
|
||||
signal previewModelChanged(string model)
|
||||
|
||||
// invoked from C++ to refresh material preview image
|
||||
function refreshPreview()
|
||||
@@ -38,10 +40,43 @@ PropertyEditorPane {
|
||||
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 {
|
||||
id: topSection
|
||||
|
||||
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 }
|
||||
|
@@ -47,10 +47,10 @@ Rectangle {
|
||||
IconButton {
|
||||
icon: StudioTheme.Constants.applyMaterialToSelected
|
||||
|
||||
normalColor: "transparent"
|
||||
normalColor: StudioTheme.Values.themeSectionHeadBackground
|
||||
iconSize: StudioTheme.Values.bigIconFontSize
|
||||
buttonSize: root.height
|
||||
enabled: hasMaterial && hasModelSelection && hasQuick3DImport
|
||||
enabled: hasMaterial && hasModelSelection && hasQuick3DImport && !hasMaterialRoot
|
||||
onClicked: root.toolBarAction(ToolBarAction.ApplyToSelected)
|
||||
tooltip: qsTr("Apply material to selected model.")
|
||||
}
|
||||
@@ -58,10 +58,10 @@ Rectangle {
|
||||
IconButton {
|
||||
icon: StudioTheme.Constants.newMaterial
|
||||
|
||||
normalColor: "transparent"
|
||||
normalColor: StudioTheme.Values.themeSectionHeadBackground
|
||||
iconSize: StudioTheme.Values.bigIconFontSize
|
||||
buttonSize: root.height
|
||||
enabled: hasQuick3DImport
|
||||
enabled: hasQuick3DImport && !hasMaterialRoot
|
||||
onClicked: root.toolBarAction(ToolBarAction.AddNewMaterial)
|
||||
tooltip: qsTr("Create new material.")
|
||||
}
|
||||
@@ -69,10 +69,10 @@ Rectangle {
|
||||
IconButton {
|
||||
icon: StudioTheme.Constants.deleteMaterial
|
||||
|
||||
normalColor: "transparent"
|
||||
normalColor: StudioTheme.Values.themeSectionHeadBackground
|
||||
iconSize: StudioTheme.Values.bigIconFontSize
|
||||
buttonSize: root.height
|
||||
enabled: hasMaterial && hasQuick3DImport
|
||||
enabled: hasMaterial && hasQuick3DImport && !hasMaterialRoot
|
||||
onClicked: root.toolBarAction(ToolBarAction.DeleteCurrentMaterial)
|
||||
tooltip: qsTr("Delete current material.")
|
||||
}
|
||||
@@ -80,10 +80,10 @@ Rectangle {
|
||||
IconButton {
|
||||
icon: StudioTheme.Constants.openMaterialBrowser
|
||||
|
||||
normalColor: "transparent"
|
||||
normalColor: StudioTheme.Values.themeSectionHeadBackground
|
||||
iconSize: StudioTheme.Values.bigIconFontSize
|
||||
buttonSize: root.height
|
||||
enabled: hasMaterial && hasQuick3DImport
|
||||
enabled: hasMaterial && hasQuick3DImport && !hasMaterialRoot
|
||||
onClicked: root.toolBarAction(ToolBarAction.OpenMaterialBrowser)
|
||||
tooltip: qsTr("Open material browser.")
|
||||
}
|
||||
|
@@ -29,6 +29,7 @@ import QtQuick.Layouts 1.15
|
||||
import QtQuickDesignerTheme 1.0
|
||||
import QtQuick.Templates 2.15 as T
|
||||
import HelperWidgets 2.0
|
||||
import StudioControls 1.0 as StudioControls
|
||||
import StudioTheme 1.0 as StudioTheme
|
||||
|
||||
Column {
|
||||
@@ -36,12 +37,22 @@ Column {
|
||||
|
||||
signal toolBarAction(int action)
|
||||
|
||||
property string previewEnv
|
||||
property string previewModel
|
||||
|
||||
function refreshPreview()
|
||||
{
|
||||
materialPreview.source = ""
|
||||
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.right: parent.right
|
||||
|
||||
@@ -53,20 +64,133 @@ Column {
|
||||
|
||||
Item { width: 1; height: 10 } // spacer
|
||||
|
||||
Rectangle {
|
||||
width: 152
|
||||
height: 152
|
||||
color: "#000000"
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
Image {
|
||||
id: materialPreview
|
||||
width: 150
|
||||
height: 150
|
||||
anchors.centerIn: parent
|
||||
source: "image://materialEditor/preview"
|
||||
cache: false
|
||||
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 {
|
||||
id: previewRect
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: 152
|
||||
height: 152
|
||||
color: "#000000"
|
||||
|
||||
Image {
|
||||
id: materialPreview
|
||||
width: 150
|
||||
height: 150
|
||||
anchors.centerIn: parent
|
||||
source: "image://materialEditor/preview"
|
||||
cache: false
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
@@ -103,17 +227,8 @@ Column {
|
||||
Spacer { implicitWidth: StudioTheme.Values.actionIndicatorWidth }
|
||||
|
||||
ComboBox {
|
||||
currentIndex: {
|
||||
if (backendValues.__classNamePrivateInternal.value === "CustomMaterial")
|
||||
return 2
|
||||
|
||||
if (backendValues.__classNamePrivateInternal.value === "PrincipledMaterial")
|
||||
return 1
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
model: ["DefaultMaterial", "PrincipledMaterial", "CustomMaterial"]
|
||||
currentIndex: possibleTypeIndex
|
||||
model: possibleTypes
|
||||
showExtendedFunctionButton: false
|
||||
implicitWidth: StudioTheme.Values.singleControlColumnWidth
|
||||
|
||||
|
@@ -51,13 +51,6 @@ Rectangle {
|
||||
: mouseArea.containsMouse ? hoverColor
|
||||
: normalColor
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: 300
|
||||
easing.type: Easing.OutQuad
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
id: icon
|
||||
|
||||
|
@@ -136,7 +136,7 @@ Item {
|
||||
},
|
||||
State {
|
||||
name: "hover"
|
||||
when: searchFilterText.hovered && !searchFilterText.activeFocus
|
||||
when: root.enabled && searchFilterText.hovered && !searchFilterText.activeFocus
|
||||
PropertyChanges {
|
||||
target: textFieldBackground
|
||||
color: StudioTheme.Values.themeControlBackgroundHover
|
||||
|
@@ -122,72 +122,74 @@ QtObject {
|
||||
readonly property string listView: "\u0075"
|
||||
readonly property string lockOff: "\u0076"
|
||||
readonly property string lockOn: "\u0077"
|
||||
readonly property string mergeCells: "\u0078"
|
||||
readonly property string minus: "\u0079"
|
||||
readonly property string mirror: "\u007A"
|
||||
readonly property string newMaterial: "\u007B"
|
||||
readonly property string openMaterialBrowser: "\u007C"
|
||||
readonly property string orientation: "\u007D"
|
||||
readonly property string paddingEdge: "\u007E"
|
||||
readonly property string paddingFrame: "\u007F"
|
||||
readonly property string pasteStyle: "\u0080"
|
||||
readonly property string pause: "\u0081"
|
||||
readonly property string pin: "\u0082"
|
||||
readonly property string play: "\u0083"
|
||||
readonly property string plus: "\u0084"
|
||||
readonly property string promote: "\u0085"
|
||||
readonly property string readOnly: "\u0086"
|
||||
readonly property string redo: "\u0087"
|
||||
readonly property string rotationFill: "\u0088"
|
||||
readonly property string rotationOutline: "\u0089"
|
||||
readonly property string search: "\u008A"
|
||||
readonly property string sectionToggle: "\u008B"
|
||||
readonly property string splitColumns: "\u008C"
|
||||
readonly property string splitRows: "\u008D"
|
||||
readonly property string startNode: "\u008E"
|
||||
readonly property string testIcon: "\u008F"
|
||||
readonly property string textAlignBottom: "\u0090"
|
||||
readonly property string textAlignCenter: "\u0091"
|
||||
readonly property string textAlignJustified: "\u0092"
|
||||
readonly property string textAlignLeft: "\u0093"
|
||||
readonly property string textAlignMiddle: "\u0094"
|
||||
readonly property string textAlignRight: "\u0095"
|
||||
readonly property string textAlignTop: "\u0096"
|
||||
readonly property string textBulletList: "\u0097"
|
||||
readonly property string textFullJustification: "\u0098"
|
||||
readonly property string textNumberedList: "\u0099"
|
||||
readonly property string tickIcon: "\u009A"
|
||||
readonly property string translationCreateFiles: "\u009B"
|
||||
readonly property string translationCreateReport: "\u009D"
|
||||
readonly property string translationExport: "\u009E"
|
||||
readonly property string translationImport: "\u009F"
|
||||
readonly property string translationSelectLanguages: "\u00A0"
|
||||
readonly property string translationTest: "\u00A1"
|
||||
readonly property string transparent: "\u00A2"
|
||||
readonly property string triState: "\u00A3"
|
||||
readonly property string triangleArcA: "\u00A4"
|
||||
readonly property string triangleArcB: "\u00A5"
|
||||
readonly property string triangleCornerA: "\u00A6"
|
||||
readonly property string triangleCornerB: "\u00A7"
|
||||
readonly property string unLinked: "\u00A8"
|
||||
readonly property string undo: "\u00A9"
|
||||
readonly property string unpin: "\u00AA"
|
||||
readonly property string upDownIcon: "\u00AB"
|
||||
readonly property string upDownSquare2: "\u00AC"
|
||||
readonly property string visibilityOff: "\u00AE"
|
||||
readonly property string visibilityOn: "\u00AF"
|
||||
readonly property string wildcard: "\u00B0"
|
||||
readonly property string wizardsAutomotive: "\u00B1"
|
||||
readonly property string wizardsDesktop: "\u00B2"
|
||||
readonly property string wizardsGeneric: "\u00B3"
|
||||
readonly property string wizardsMcuEmpty: "\u00B4"
|
||||
readonly property string wizardsMcuGraph: "\u00B5"
|
||||
readonly property string wizardsMobile: "\u00B6"
|
||||
readonly property string wizardsUnknown: "\u00B7"
|
||||
readonly property string zoomAll: "\u00B8"
|
||||
readonly property string zoomIn: "\u00B9"
|
||||
readonly property string zoomOut: "\u00BA"
|
||||
readonly property string zoomSelection: "\u00BB"
|
||||
readonly property string materialPreviewEnvironment: "\u0078"
|
||||
readonly property string materialPreviewModel: "\u0079"
|
||||
readonly property string mergeCells: "\u007A"
|
||||
readonly property string minus: "\u007B"
|
||||
readonly property string mirror: "\u007C"
|
||||
readonly property string newMaterial: "\u007D"
|
||||
readonly property string openMaterialBrowser: "\u007E"
|
||||
readonly property string orientation: "\u007F"
|
||||
readonly property string paddingEdge: "\u0080"
|
||||
readonly property string paddingFrame: "\u0081"
|
||||
readonly property string pasteStyle: "\u0082"
|
||||
readonly property string pause: "\u0083"
|
||||
readonly property string pin: "\u0084"
|
||||
readonly property string play: "\u0085"
|
||||
readonly property string plus: "\u0086"
|
||||
readonly property string promote: "\u0087"
|
||||
readonly property string readOnly: "\u0088"
|
||||
readonly property string redo: "\u0089"
|
||||
readonly property string rotationFill: "\u008A"
|
||||
readonly property string rotationOutline: "\u008B"
|
||||
readonly property string search: "\u008C"
|
||||
readonly property string sectionToggle: "\u008D"
|
||||
readonly property string splitColumns: "\u008E"
|
||||
readonly property string splitRows: "\u008F"
|
||||
readonly property string startNode: "\u0090"
|
||||
readonly property string testIcon: "\u0091"
|
||||
readonly property string textAlignBottom: "\u0092"
|
||||
readonly property string textAlignCenter: "\u0093"
|
||||
readonly property string textAlignJustified: "\u0094"
|
||||
readonly property string textAlignLeft: "\u0095"
|
||||
readonly property string textAlignMiddle: "\u0096"
|
||||
readonly property string textAlignRight: "\u0097"
|
||||
readonly property string textAlignTop: "\u0098"
|
||||
readonly property string textBulletList: "\u0099"
|
||||
readonly property string textFullJustification: "\u009A"
|
||||
readonly property string textNumberedList: "\u009B"
|
||||
readonly property string tickIcon: "\u009D"
|
||||
readonly property string translationCreateFiles: "\u009E"
|
||||
readonly property string translationCreateReport: "\u009F"
|
||||
readonly property string translationExport: "\u00A0"
|
||||
readonly property string translationImport: "\u00A1"
|
||||
readonly property string translationSelectLanguages: "\u00A2"
|
||||
readonly property string translationTest: "\u00A3"
|
||||
readonly property string transparent: "\u00A4"
|
||||
readonly property string triState: "\u00A5"
|
||||
readonly property string triangleArcA: "\u00A6"
|
||||
readonly property string triangleArcB: "\u00A7"
|
||||
readonly property string triangleCornerA: "\u00A8"
|
||||
readonly property string triangleCornerB: "\u00A9"
|
||||
readonly property string unLinked: "\u00AA"
|
||||
readonly property string undo: "\u00AB"
|
||||
readonly property string unpin: "\u00AC"
|
||||
readonly property string upDownIcon: "\u00AE"
|
||||
readonly property string upDownSquare2: "\u00AF"
|
||||
readonly property string visibilityOff: "\u00B0"
|
||||
readonly property string visibilityOn: "\u00B1"
|
||||
readonly property string wildcard: "\u00B2"
|
||||
readonly property string wizardsAutomotive: "\u00B3"
|
||||
readonly property string wizardsDesktop: "\u00B4"
|
||||
readonly property string wizardsGeneric: "\u00B5"
|
||||
readonly property string wizardsMcuEmpty: "\u00B6"
|
||||
readonly property string wizardsMcuGraph: "\u00B7"
|
||||
readonly property string wizardsMobile: "\u00B8"
|
||||
readonly property string wizardsUnknown: "\u00B9"
|
||||
readonly property string zoomAll: "\u00BA"
|
||||
readonly property string zoomIn: "\u00BB"
|
||||
readonly property string zoomOut: "\u00BC"
|
||||
readonly property string zoomSelection: "\u00BD"
|
||||
|
||||
readonly property font iconFont: Qt.font({
|
||||
"family": controlIcons.name,
|
||||
|
Binary file not shown.
@@ -318,8 +318,7 @@
|
||||
},
|
||||
{
|
||||
"source": "Screen01.ui.qml.tpl",
|
||||
"target": "%{ProjectDirectory}/content/Screen01.ui.qml",
|
||||
"openInEditor": true
|
||||
"target": "%{ProjectDirectory}/content/Screen01.ui.qml"
|
||||
},
|
||||
{
|
||||
"source": "../common/fonts.txt",
|
||||
|
@@ -421,6 +421,7 @@ namespace ADS {
|
||||
d->m_lastLocation = InvalidDockWidgetArea;
|
||||
|
||||
// Move it over the target.
|
||||
hide();
|
||||
resize(target->size());
|
||||
QPoint topLeft = target->mapToGlobal(target->rect().topLeft());
|
||||
move(topLeft);
|
||||
|
@@ -612,7 +612,7 @@ class UnsupportedTypesByVisualDesigner : public QStringList
|
||||
{
|
||||
public:
|
||||
UnsupportedTypesByVisualDesigner()
|
||||
: QStringList({"Timer", "Package", "Particles", "ApplicationWindow"})
|
||||
: QStringList({"Package", "Particles", "ApplicationWindow"})
|
||||
{}
|
||||
};
|
||||
|
||||
|
@@ -175,6 +175,11 @@ bool JLinkGdbServerProvider::operator==(const IDebugServerProvider &other) const
|
||||
|
||||
const auto p = static_cast<const JLinkGdbServerProvider *>(&other);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@@ -157,6 +157,20 @@ static void checkSystemForClangdSuitability()
|
||||
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()
|
||||
{
|
||||
watchForExternalChanges();
|
||||
@@ -382,6 +396,13 @@ void ClangModelManagerSupport::updateLanguageClient(
|
||||
if (Client * const oldClient = clientForProject(project))
|
||||
LanguageClientManager::shutdownClient(oldClient);
|
||||
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] {
|
||||
using namespace ProjectExplorer;
|
||||
if (!SessionManager::hasProject(project))
|
||||
@@ -393,25 +414,15 @@ void ClangModelManagerSupport::updateLanguageClient(
|
||||
if (!newProjectInfo || *newProjectInfo != *projectInfo)
|
||||
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.
|
||||
bool hasDocuments = false;
|
||||
const ClangdSettings settings(ClangdProjectSettings(project).settings());
|
||||
for (TextEditor::TextDocument * const doc : allCppDocuments()) {
|
||||
Client * const currentClient = LanguageClientManager::clientForDocument(doc);
|
||||
if (currentClient == client) {
|
||||
hasDocuments = true;
|
||||
continue;
|
||||
}
|
||||
if (!settings.sizeIsOkay(doc->filePath()))
|
||||
continue;
|
||||
const Project * const docProject = SessionManager::projectForFile(doc->filePath());
|
||||
@@ -440,17 +451,8 @@ void ClangModelManagerSupport::updateLanguageClient(
|
||||
++it;
|
||||
}
|
||||
}
|
||||
connect(client, &Client::shadowDocumentSwitched, this,
|
||||
[](const Utils::FilePath &fp) {
|
||||
ClangdClient::handleUiHeaderChange(fp.fileName());
|
||||
});
|
||||
|
||||
if (client->state() == Client::Initialized)
|
||||
updateParserConfig();
|
||||
else
|
||||
connect(client, &Client::initialized, client, updateParserConfig);
|
||||
connect(CppModelManager::instance(), &CppModelManager::projectPartsUpdated,
|
||||
client, updateParserConfig);
|
||||
updateParserConfig(client);
|
||||
|
||||
if (hasDocuments)
|
||||
return;
|
||||
|
@@ -66,7 +66,6 @@ void adjustFormatStyleForLineBreak(clang::format::FormatStyle &style,
|
||||
if (replacementsToKeep == ReplacementsToKeep::IndentAndBefore)
|
||||
return;
|
||||
|
||||
style.DisableFormat = false;
|
||||
style.ColumnLimit = 0;
|
||||
#ifdef KEEP_LINE_BREAKS_FOR_NON_EMPTY_LINES_BACKPORTED
|
||||
style.KeepLineBreaksForNonEmptyLines = true;
|
||||
|
@@ -435,7 +435,6 @@ public:
|
||||
private:
|
||||
void onBinaryPathEditingFinished();
|
||||
void updateQchFilePath();
|
||||
void reload();
|
||||
|
||||
CMakeToolItemModel *m_model;
|
||||
QLineEdit *m_displayNameLineEdit;
|
||||
@@ -501,7 +500,6 @@ void CMakeToolItemConfigWidget::onBinaryPathEditingFinished()
|
||||
{
|
||||
updateQchFilePath();
|
||||
store();
|
||||
reload();
|
||||
}
|
||||
|
||||
void CMakeToolItemConfigWidget::updateQchFilePath()
|
||||
@@ -510,18 +508,6 @@ void CMakeToolItemConfigWidget::updateQchFilePath()
|
||||
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)
|
||||
{
|
||||
m_loadingItem = true; // avoid intermediate signal handling
|
||||
|
@@ -473,16 +473,16 @@ void CompilerOptionsBuilder::addLanguageVersionAndExtensions()
|
||||
default:
|
||||
break;
|
||||
case LanguageVersion::CXX14:
|
||||
option = "-clang:std=c++14";
|
||||
option = "-clang:-std=c++14";
|
||||
break;
|
||||
case LanguageVersion::CXX17:
|
||||
option = "-clang:std=c++17";
|
||||
option = "-clang:-std=c++17";
|
||||
break;
|
||||
case LanguageVersion::CXX20:
|
||||
option = "-clang:std=c++20";
|
||||
option = "-clang:-std=c++20";
|
||||
break;
|
||||
case LanguageVersion::CXX2b:
|
||||
option = "-clang:std=c++2b";
|
||||
option = "-clang:-std=c++2b";
|
||||
break;
|
||||
}
|
||||
|
||||
|
@@ -192,7 +192,7 @@ void CompilerOptionsBuilderTest::testLanguageVersionIsExplicitlySetIfNotProvided
|
||||
UseTweakedHeaderPaths::No, UseLanguageDefines::Yes};
|
||||
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()
|
||||
@@ -633,7 +633,7 @@ void CompilerOptionsBuilderTest::testBuildAllOptionsMsvc()
|
||||
[&t](const QString &o) { return o.contains(t.toNative("wrappedQtHeaders/QtCore")); });
|
||||
QCOMPARE(compilerOptionsBuilder.options(),
|
||||
(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",
|
||||
"-D__FUNCSIG__=\"void __cdecl someLegalAndLongishFunctionNameThatWorksAroundQTCREATORBUG-24580(void)\"",
|
||||
"-D__FUNCTION__=\"someLegalAndLongishFunctionNameThatWorksAroundQTCREATORBUG-24580\"",
|
||||
@@ -662,7 +662,7 @@ void CompilerOptionsBuilderTest::testBuildAllOptionsMsvcWithExceptions()
|
||||
[&t](const QString &o) { return o.contains(t.toNative("wrappedQtHeaders/QtCore")); });
|
||||
QCOMPARE(compilerOptionsBuilder.options(),
|
||||
(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",
|
||||
"-DprojectFoo=projectBar",
|
||||
"-D__FUNCSIG__=\"void __cdecl someLegalAndLongishFunctionNameThatWorksAroundQTCREATORBUG-24580(void)\"",
|
||||
|
@@ -378,7 +378,6 @@ SignalSlotType CppModelManager::getSignalSlotType(const FilePath &filePath,
|
||||
QTextCursor cursor(&textDocument);
|
||||
cursor.setPosition(position);
|
||||
|
||||
// Are we at the second argument of a function call?
|
||||
const QList<AST *> path = ASTPath(document)(cursor);
|
||||
if (path.isEmpty())
|
||||
return SignalSlotType::None;
|
||||
@@ -388,9 +387,27 @@ SignalSlotType CppModelManager::getSignalSlotType(const FilePath &filePath,
|
||||
break;
|
||||
}
|
||||
|
||||
// Is the function called "connect" or "disconnect"?
|
||||
if (!callAst || !callAst->base_expression)
|
||||
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();
|
||||
for (auto it = path.crbegin(); it != path.crend(); ++it) {
|
||||
if (const CompoundStatementAST * const stmtAst = (*it)->asCompoundStatement()) {
|
||||
@@ -398,12 +415,8 @@ SignalSlotType CppModelManager::getSignalSlotType(const FilePath &filePath,
|
||||
break;
|
||||
}
|
||||
}
|
||||
const NameAST *nameAst = nullptr;
|
||||
const LookupContext context(document, snapshot);
|
||||
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 (const MemberAccessAST * const ast = callAst->base_expression->asMemberAccess()) {
|
||||
TypeOfExpression exprType;
|
||||
exprType.setExpandTemplates(true);
|
||||
exprType.init(document, snapshot);
|
||||
@@ -433,14 +446,6 @@ SignalSlotType CppModelManager::getSignalSlotType(const FilePath &filePath,
|
||||
if (!scope)
|
||||
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?
|
||||
const QList<LookupItem> matches = context.lookup(nameAst->name, scope);
|
||||
@@ -463,10 +468,8 @@ SignalSlotType CppModelManager::getSignalSlotType(const FilePath &filePath,
|
||||
|
||||
expression = expressionUnderCursor(cursor);
|
||||
|
||||
const int argumentPosition = argumentPositionOf(path.last(), callAst);
|
||||
if ((expression.endsWith(QLatin1String("SIGNAL"))
|
||||
&& (argumentPosition == 2 || argumentPosition == 4))
|
||||
|| (expression.endsWith(QLatin1String("SLOT")) && argumentPosition == 4))
|
||||
if (expression.endsWith(QLatin1String("SIGNAL"))
|
||||
|| (expression.endsWith(QLatin1String("SLOT")) && argumentPosition == 4))
|
||||
return SignalSlotType::OldStyleSignal;
|
||||
|
||||
if (argumentPosition == 2)
|
||||
|
@@ -5247,10 +5247,12 @@ ExtractFunction::ExtractFunction(FunctionNameGetter functionNameGetter)
|
||||
void ExtractFunction::match(const CppQuickFixInterface &interface, QuickFixOperations &result)
|
||||
{
|
||||
const CppRefactoringFilePtr file = interface.currentFile();
|
||||
if (CppModelManager::usesClangd(file->editor()->textDocument())
|
||||
&& file->cppDocument()->languageFeatures().cxxEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Fix upstream and uncomment; see QTCREATORBUG-28030.
|
||||
// if (CppModelManager::usesClangd(file->editor()->textDocument())
|
||||
// && file->cppDocument()->languageFeatures().cxxEnabled) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
QTextCursor cursor = file->cursor();
|
||||
if (!cursor.hasSelection())
|
||||
|
@@ -283,7 +283,17 @@ public:
|
||||
QString m_displayName;
|
||||
LanguageFilter m_languagFilter;
|
||||
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
|
||||
// the build.
|
||||
@@ -618,11 +628,14 @@ void Client::openDocument(TextEditor::TextDocument *document)
|
||||
}
|
||||
}
|
||||
|
||||
d->m_openedDocument[document] = document->plainText();
|
||||
connect(document, &TextDocument::contentsChangedWithPosition, this,
|
||||
[this, document](int position, int charsRemoved, int charsAdded) {
|
||||
documentContentsChanged(document, position, charsRemoved, charsAdded);
|
||||
});
|
||||
d->m_openedDocument[document].documentContents = document->plainText();
|
||||
d->m_openedDocument[document].contentsChangedConnection
|
||||
= connect(document,
|
||||
&TextDocument::contentsChangedWithPosition,
|
||||
this,
|
||||
[this, document](int position, int charsRemoved, int charsAdded) {
|
||||
documentContentsChanged(document, position, charsRemoved, charsAdded);
|
||||
});
|
||||
if (!d->m_documentVersions.contains(filePath))
|
||||
d->m_documentVersions[filePath] = 0;
|
||||
d->sendOpenNotification(filePath, document->mimeType(), document->plainText(),
|
||||
@@ -1083,7 +1096,7 @@ void Client::documentContentsChanged(TextEditor::TextDocument *document,
|
||||
}
|
||||
}
|
||||
if (append) {
|
||||
QTextDocument oldDoc(d->m_openedDocument[document]);
|
||||
QTextDocument oldDoc(d->m_openedDocument[document].documentContents);
|
||||
QTextCursor cursor(&oldDoc);
|
||||
// Workaround https://bugreports.qt.io/browse/QTBUG-80662
|
||||
// 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] = {
|
||||
DidChangeTextDocumentParams::TextDocumentContentChangeEvent(document->plainText())};
|
||||
}
|
||||
d->m_openedDocument[document] = document->plainText();
|
||||
d->m_openedDocument[document].documentContents = document->plainText();
|
||||
}
|
||||
|
||||
++d->m_documentVersions[document->filePath()];
|
||||
@@ -1532,8 +1545,6 @@ bool ClientPrivate::reset()
|
||||
m_dynamicCapabilities.reset();
|
||||
if (m_diagnosticManager)
|
||||
m_diagnosticManager->clearDiagnostics();
|
||||
for (auto it = m_openedDocument.cbegin(); it != m_openedDocument.cend(); ++it)
|
||||
it.key()->disconnect(this);
|
||||
m_openedDocument.clear();
|
||||
// temporary container needed since m_resetAssistProvider is changed in resetAssistProviders
|
||||
for (TextEditor::TextDocument *document : m_resetAssistProvider.keys())
|
||||
@@ -1544,7 +1555,8 @@ bool ClientPrivate::reset()
|
||||
qDeleteAll(m_documentHighlightsTimer);
|
||||
m_documentHighlightsTimer.clear();
|
||||
m_progressManager.reset();
|
||||
m_shadowDocuments.clear();
|
||||
for (auto &doc : m_shadowDocuments)
|
||||
doc.second.clear();
|
||||
m_documentVersions.clear();
|
||||
return true;
|
||||
}
|
||||
|
@@ -117,13 +117,13 @@ public:
|
||||
if (python.exists())
|
||||
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())
|
||||
return;
|
||||
|
||||
|
@@ -595,7 +595,7 @@ extend_qtc_plugin(QmlDesigner
|
||||
easingcurve.cpp easingcurve.h
|
||||
easingcurvedialog.cpp easingcurvedialog.h
|
||||
preseteditor.cpp preseteditor.h
|
||||
setframevaluedialog.cpp setframevaluedialog.h setframevaluedialog.ui
|
||||
setframevaluedialog.cpp setframevaluedialog.h
|
||||
splineeditor.cpp splineeditor.h
|
||||
timeline.qrc
|
||||
timelineabstracttool.cpp timelineabstracttool.h
|
||||
|
@@ -129,11 +129,13 @@ void DesignerActionManager::polishActions() const
|
||||
Core::Context qmlDesignerFormEditorContext(Constants::C_QMLFORMEDITOR);
|
||||
Core::Context qmlDesignerEditor3DContext(Constants::C_QMLEDITOR3D);
|
||||
Core::Context qmlDesignerNavigatorContext(Constants::C_QMLNAVIGATOR);
|
||||
Core::Context qmlDesignerMaterialBrowserContext(Constants::C_QMLMATERIALBROWSER);
|
||||
|
||||
Core::Context qmlDesignerUIContext;
|
||||
qmlDesignerUIContext.add(qmlDesignerFormEditorContext);
|
||||
qmlDesignerUIContext.add(qmlDesignerEditor3DContext);
|
||||
qmlDesignerUIContext.add(qmlDesignerNavigatorContext);
|
||||
qmlDesignerUIContext.add(qmlDesignerMaterialBrowserContext);
|
||||
|
||||
for (auto *action : actions) {
|
||||
if (!action->menuId().isEmpty()) {
|
||||
|
@@ -130,6 +130,8 @@ public:
|
||||
listView,
|
||||
lockOff,
|
||||
lockOn,
|
||||
materialPreviewEnvironment,
|
||||
materialPreviewModel,
|
||||
mergeCells,
|
||||
minus,
|
||||
mirror,
|
||||
|
@@ -85,7 +85,7 @@ void ColorControl::mouseReleaseEvent(QMouseEvent *event)
|
||||
|
||||
event->accept();
|
||||
|
||||
if (color != m_color) {
|
||||
if (color.isValid() && color != m_color) {
|
||||
m_color = color;
|
||||
update();
|
||||
emit valueChanged();
|
||||
|
@@ -27,7 +27,10 @@
|
||||
#include "curveitem.h"
|
||||
#include "handleitem.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QPainter>
|
||||
#include <qnamespace.h>
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
@@ -452,10 +455,22 @@ QVariant KeyframeItem::itemChange(QGraphicsItem::GraphicsItemChange change, cons
|
||||
lseg.moveRightTo(position);
|
||||
rseg.moveLeftTo(position);
|
||||
|
||||
if (legalLeft() && legalRight())
|
||||
m_validPos = position;
|
||||
if (legalLeft() && legalRight()) {
|
||||
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)
|
||||
{
|
||||
bool ok;
|
||||
m_firstPos = m_transform.inverted(&ok).map(event->scenePos());
|
||||
if (!ok)
|
||||
m_firstPos = Utils::nullopt;
|
||||
|
||||
SelectableItem::mousePressEvent(event);
|
||||
if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(parentItem()))
|
||||
curveItem->setHandleVisibility(false);
|
||||
@@ -472,6 +492,7 @@ void KeyframeItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||
|
||||
void KeyframeItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
m_firstPos = Utils::nullopt;
|
||||
SelectableItem::mouseReleaseEvent(event);
|
||||
if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(parentItem()))
|
||||
curveItem->setHandleVisibility(true);
|
||||
|
@@ -30,6 +30,8 @@
|
||||
#include "keyframe.h"
|
||||
#include "selectableitem.h"
|
||||
|
||||
#include <utils/optional.h>
|
||||
|
||||
#include <QGraphicsObject>
|
||||
|
||||
namespace QmlDesigner {
|
||||
@@ -133,7 +135,8 @@ private:
|
||||
|
||||
HandleItem *m_right;
|
||||
|
||||
QPointF m_validPos;
|
||||
Utils::optional< QPointF > m_firstPos;
|
||||
Utils::optional< QPointF > m_validPos;
|
||||
|
||||
bool m_visibleOverride = true;
|
||||
|
||||
|
@@ -24,9 +24,13 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "materialbrowsermodel.h"
|
||||
#include "variantproperty.h"
|
||||
|
||||
#include <bindingproperty.h>
|
||||
#include <designmodewidget.h>
|
||||
#include <qmldesignerplugin.h>
|
||||
#include <qmlobjectnode.h>
|
||||
#include "variantproperty.h"
|
||||
#include "utils/qtcassert.h"
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
@@ -46,24 +50,27 @@ int MaterialBrowserModel::rowCount(const QModelIndex &) const
|
||||
|
||||
QVariant MaterialBrowserModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid() || index.row() >= m_materialList.count()) {
|
||||
qWarning() << Q_FUNC_INFO << "invalid index requested";
|
||||
return {};
|
||||
}
|
||||
QTC_ASSERT(index.isValid() && index.row() < m_materialList.count(), return {});
|
||||
QTC_ASSERT(roleNames().contains(role), return {});
|
||||
|
||||
if (roleNames().value(role) == "materialName") {
|
||||
QByteArray roleName = roleNames().value(role);
|
||||
if (roleName == "materialName") {
|
||||
QVariant objName = m_materialList.at(index.row()).variantProperty("objectName").value();
|
||||
return objName.isValid() ? objName : "";
|
||||
}
|
||||
|
||||
if (roleNames().value(role) == "materialInternalId")
|
||||
if (roleName == "materialInternalId")
|
||||
return m_materialList.at(index.row()).internalId();
|
||||
|
||||
if (roleNames().value(role) == "materialVisible")
|
||||
if (roleName == "materialVisible")
|
||||
return isMaterialVisible(index.row());
|
||||
|
||||
if (!roleNames().contains(role))
|
||||
qWarning() << Q_FUNC_INFO << "invalid role requested";
|
||||
if (roleName == "materialType") {
|
||||
QString matType = QString::fromLatin1(m_materialList.at(index.row()).type());
|
||||
if (matType.startsWith("QtQuick3D."))
|
||||
matType.remove("QtQuick3D.");
|
||||
return matType;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
@@ -82,12 +89,57 @@ bool MaterialBrowserModel::isValidIndex(int idx) const
|
||||
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
|
||||
{
|
||||
static const QHash<int, QByteArray> roles {
|
||||
{Qt::UserRole + 1, "materialName"},
|
||||
{Qt::UserRole + 2, "materialInternalId"},
|
||||
{Qt::UserRole + 3, "materialVisible"},
|
||||
{Qt::UserRole + 4, "materialType"}
|
||||
};
|
||||
return roles;
|
||||
}
|
||||
@@ -120,6 +172,34 @@ void MaterialBrowserModel::setHasModelSelection(bool b)
|
||||
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
|
||||
{
|
||||
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()
|
||||
{
|
||||
selectMaterial(m_selectedIndex, true);
|
||||
@@ -256,6 +342,42 @@ void MaterialBrowserModel::duplicateMaterial(int idx)
|
||||
emit duplicateMaterialTriggered(m_materialList.at(idx));
|
||||
}
|
||||
|
||||
void MaterialBrowserModel::copyMaterialProperties(int idx, const QString §ion)
|
||||
{
|
||||
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)
|
||||
{
|
||||
m_materialList[idx].destroy();
|
||||
|
@@ -25,7 +25,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "qjsonobject.h"
|
||||
#include <modelnode.h>
|
||||
#include <qmlobjectnode.h>
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QObject>
|
||||
@@ -41,6 +43,11 @@ class MaterialBrowserModel : public QAbstractListModel
|
||||
Q_PROPERTY(int selectedIndex MEMBER m_selectedIndex NOTIFY selectedIndexChanged)
|
||||
Q_PROPERTY(bool hasQuick3DImport READ hasQuick3DImport WRITE setHasQuick3DImport NOTIFY hasQuick3DImportChanged)
|
||||
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:
|
||||
MaterialBrowserModel(QObject *parent = nullptr);
|
||||
@@ -58,18 +65,28 @@ public:
|
||||
bool hasModelSelection() const;
|
||||
void setHasModelSelection(bool b);
|
||||
|
||||
bool hasMaterialRoot() const;
|
||||
void setHasMaterialRoot(bool b);
|
||||
|
||||
QString copiedMaterialType() const;
|
||||
void setCopiedMaterialType(const QString &matType);
|
||||
|
||||
QList<ModelNode> materials() const;
|
||||
void setMaterials(const QList<ModelNode> &materials, bool hasQuick3DImport);
|
||||
void removeMaterial(const ModelNode &material);
|
||||
void deleteSelectedMaterial();
|
||||
void updateMaterialName(const ModelNode &material);
|
||||
void updateSelectedMaterial();
|
||||
int materialIndex(const ModelNode &material) const;
|
||||
ModelNode materialAt(int idx) const;
|
||||
void loadPropertyGroups(const QString &path);
|
||||
|
||||
void resetModel();
|
||||
|
||||
Q_INVOKABLE void selectMaterial(int idx, bool force = false);
|
||||
Q_INVOKABLE void duplicateMaterial(int idx);
|
||||
Q_INVOKABLE void copyMaterialProperties(int idx, const QString §ion);
|
||||
Q_INVOKABLE void pasteMaterialProperties(int idx);
|
||||
Q_INVOKABLE void deleteMaterial(int idx);
|
||||
Q_INVOKABLE void renameMaterial(int idx, const QString &newName);
|
||||
Q_INVOKABLE void addNewMaterial();
|
||||
@@ -80,11 +97,17 @@ signals:
|
||||
void isEmptyChanged();
|
||||
void hasQuick3DImportChanged();
|
||||
void hasModelSelectionChanged();
|
||||
void hasMaterialRootChanged();
|
||||
void copiedMaterialTypeChanged();
|
||||
void materialSectionsChanged();
|
||||
void selectedIndexChanged(int idx);
|
||||
void renameMaterialTriggered(const QmlDesigner::ModelNode &material, const QString &newName);
|
||||
void applyToSelectedTriggered(const QmlDesigner::ModelNode &material, bool add = false);
|
||||
void addNewMaterialTriggered();
|
||||
void duplicateMaterialTriggered(const QmlDesigner::ModelNode &material);
|
||||
void pasteMaterialPropertiesTriggered(const QmlDesigner::ModelNode &material,
|
||||
const QList<QmlDesigner::AbstractProperty> &props,
|
||||
bool all);
|
||||
|
||||
private:
|
||||
bool isMaterialVisible(int idx) const;
|
||||
@@ -92,12 +115,20 @@ private:
|
||||
|
||||
QString m_searchText;
|
||||
QList<ModelNode> m_materialList;
|
||||
QStringList m_defaultMaterialSections;
|
||||
QStringList m_principledMaterialSections;
|
||||
QStringList m_customMaterialSections;
|
||||
QList<AbstractProperty> m_copiedMaterialProps;
|
||||
QHash<qint32, int> m_materialIndexHash; // internalId -> index
|
||||
QJsonObject m_propertyGroupsObj;
|
||||
|
||||
int m_selectedIndex = 0;
|
||||
bool m_isEmpty = true;
|
||||
bool m_hasQuick3DImport = false;
|
||||
bool m_hasModelSelection = false;
|
||||
bool m_hasMaterialRoot = false;
|
||||
bool m_allPropsCopied = true;
|
||||
QString m_copiedMaterialType;
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
@@ -24,12 +24,17 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "materialbrowserview.h"
|
||||
|
||||
#include "bindingproperty.h"
|
||||
#include "materialbrowserwidget.h"
|
||||
#include "materialbrowsermodel.h"
|
||||
#include "nodeabstractproperty.h"
|
||||
#include "nodemetainfo.h"
|
||||
#include "qmlobjectnode.h"
|
||||
#include "variantproperty.h"
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <designmodecontext.h>
|
||||
#include <nodeinstanceview.h>
|
||||
#include <qmldesignerconstants.h>
|
||||
|
||||
@@ -39,7 +44,6 @@ namespace QmlDesigner {
|
||||
|
||||
MaterialBrowserView::MaterialBrowserView(QObject *parent)
|
||||
: AbstractView(parent)
|
||||
|
||||
{}
|
||||
|
||||
MaterialBrowserView::~MaterialBrowserView()
|
||||
@@ -53,7 +57,11 @@ bool MaterialBrowserView::hasWidget() const
|
||||
WidgetInfo MaterialBrowserView::widgetInfo()
|
||||
{
|
||||
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();
|
||||
|
||||
// custom notifications below are sent to the MaterialEditor
|
||||
@@ -81,6 +89,32 @@ WidgetInfo MaterialBrowserView::widgetInfo()
|
||||
[&] (const ModelNode &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(),
|
||||
@@ -94,7 +128,12 @@ void MaterialBrowserView::modelAttached(Model *model)
|
||||
{
|
||||
AbstractView::modelAttached(model);
|
||||
|
||||
QString matPropsPath = model->metaInfo("QtQuick3D.Material").importDirectoryPath()
|
||||
+ "/designer/propertyGroups.json";
|
||||
m_widget->materialBrowserModel()->loadPropertyGroups(matPropsPath);
|
||||
|
||||
m_widget->clearSearchFilter();
|
||||
m_widget->materialBrowserModel()->setHasMaterialRoot(rootModelNode().isSubclassOf("QtQuick3D.Material"));
|
||||
m_hasQuick3DImport = model->hasImport("QtQuick3D");
|
||||
|
||||
// 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
|
||||
{
|
||||
if (!node.isValid() || node.isComponent())
|
||||
if (!node.isValid())
|
||||
return false;
|
||||
|
||||
return node.isSubclassOf("QtQuick3D.Material");
|
||||
@@ -273,6 +312,12 @@ void MaterialBrowserView::customNotification(const AbstractView *view,
|
||||
int idx = m_widget->materialBrowserModel()->materialIndex(nodeList.first());
|
||||
if (idx != -1)
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "materialbrowserwidget.h"
|
||||
#include "materialbrowsermodel.h"
|
||||
#include "materialbrowserview.h"
|
||||
|
||||
#include <theme.h>
|
||||
|
||||
@@ -130,14 +131,20 @@ bool MaterialBrowserWidget::eventFilter(QObject *obj, QEvent *event)
|
||||
return QObject::eventFilter(obj, event);
|
||||
}
|
||||
|
||||
MaterialBrowserWidget::MaterialBrowserWidget()
|
||||
: m_materialBrowserModel(new MaterialBrowserModel(this))
|
||||
MaterialBrowserWidget::MaterialBrowserWidget(MaterialBrowserView *view)
|
||||
: m_materialBrowserView(view)
|
||||
, m_materialBrowserModel(new MaterialBrowserModel(this))
|
||||
, m_quickWidget(new QQuickWidget(this))
|
||||
, m_previewImageProvider(new PreviewImageProvider())
|
||||
{
|
||||
setWindowTitle(tr("Material Browser", "Title of material browser widget"));
|
||||
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->engine()->addImportPath(propertyEditorResourcesPath() + "/imports");
|
||||
m_quickWidget->setClearColor(Theme::getColor(Theme::Color::DSpanelBackground));
|
||||
@@ -182,6 +189,14 @@ QList<QToolButton *> MaterialBrowserWidget::createToolBarWidgets()
|
||||
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)
|
||||
{
|
||||
if (filterText != m_filterText) {
|
||||
|
@@ -25,20 +25,19 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "itemlibraryinfo.h"
|
||||
#include "import.h"
|
||||
#include "modelnode.h"
|
||||
|
||||
#include <utils/fancylineedit.h>
|
||||
#include <coreplugin/icontext.h>
|
||||
#include <utils/dropsupport.h>
|
||||
#include <utils/fancylineedit.h>
|
||||
|
||||
#include <QFrame>
|
||||
#include <QToolButton>
|
||||
#include <QFileIconProvider>
|
||||
#include <QQuickWidget>
|
||||
#include <QQmlPropertyMap>
|
||||
#include <QTimer>
|
||||
#include <QFrame>
|
||||
#include <QPointF>
|
||||
#include <QQmlPropertyMap>
|
||||
#include <QQuickWidget>
|
||||
#include <QTimer>
|
||||
#include <QToolButton>
|
||||
|
||||
#include <memory>
|
||||
|
||||
@@ -49,6 +48,7 @@ QT_END_NAMESPACE
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
class MaterialBrowserView;
|
||||
class MaterialBrowserModel;
|
||||
class PreviewImageProvider;
|
||||
|
||||
@@ -57,10 +57,11 @@ class MaterialBrowserWidget : public QFrame
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MaterialBrowserWidget();
|
||||
MaterialBrowserWidget(MaterialBrowserView *view);
|
||||
~MaterialBrowserWidget() = default;
|
||||
|
||||
QList<QToolButton *> createToolBarWidgets();
|
||||
void contextHelp(const Core::IContext::HelpCallback &callback) const;
|
||||
|
||||
static QString qmlSourcesPath();
|
||||
void clearSearchFilter();
|
||||
@@ -80,11 +81,13 @@ private:
|
||||
void reloadQmlSource();
|
||||
void updateSearch();
|
||||
|
||||
QPointer<MaterialBrowserView> m_materialBrowserView;
|
||||
QPointer<MaterialBrowserModel> m_materialBrowserModel;
|
||||
QScopedPointer<QQuickWidget> m_quickWidget;
|
||||
|
||||
QShortcut *m_qmlSourceUpdateShortcut = nullptr;
|
||||
PreviewImageProvider *m_previewImageProvider = nullptr;
|
||||
Core::IContext *m_context = nullptr;
|
||||
|
||||
QString m_filterText;
|
||||
|
||||
|
@@ -32,6 +32,7 @@
|
||||
#include <qmlmodelnodeproxy.h>
|
||||
#include <qmlobjectnode.h>
|
||||
#include <qmltimeline.h>
|
||||
#include <documentmanager.h>
|
||||
|
||||
#include <coreplugin/messagebox.h>
|
||||
#include <utils/algorithm.h>
|
||||
@@ -47,12 +48,24 @@
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
MaterialEditorContextObject::MaterialEditorContextObject(QObject *parent)
|
||||
MaterialEditorContextObject::MaterialEditorContextObject(QQmlContext *context, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_qmlContext(context)
|
||||
{
|
||||
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 colorString;
|
||||
@@ -159,8 +172,10 @@ void MaterialEditorContextObject::changeTypeName(const QString &typeName)
|
||||
msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
|
||||
msgBox.setDefaultButton(QMessageBox::Ok);
|
||||
|
||||
if (msgBox.exec() == QMessageBox::Cancel)
|
||||
if (msgBox.exec() == QMessageBox::Cancel) {
|
||||
updatePossibleTypeIndex();
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &p : std::as_const(incompatibleProperties))
|
||||
m_selectedMaterial.removeProperty(p);
|
||||
@@ -234,6 +249,20 @@ void MaterialEditorContextObject::setHasQuick3DImport(bool b)
|
||||
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
|
||||
{
|
||||
return m_hasModelSelection;
|
||||
@@ -262,6 +291,20 @@ void MaterialEditorContextObject::setSpecificsUrl(const QUrl &newSpecificsUrl)
|
||||
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)
|
||||
{
|
||||
if (newStateName == m_stateName)
|
||||
@@ -280,6 +323,23 @@ void MaterialEditorContextObject::setAllStateNames(const QStringList &allStates)
|
||||
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)
|
||||
{
|
||||
if (newIsBaseState == m_isBaseState)
|
||||
@@ -326,6 +386,20 @@ void MaterialEditorContextObject::setHasAliasExport(bool hasAliasExport)
|
||||
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()
|
||||
{
|
||||
if (QApplication::overrideCursor())
|
||||
@@ -390,4 +464,10 @@ bool MaterialEditorContextObject::isBlocked(const QString &propName) const
|
||||
return false;
|
||||
}
|
||||
|
||||
void MaterialEditorContextObject::goIntoComponent()
|
||||
{
|
||||
QTC_ASSERT(m_model, return);
|
||||
DocumentManager::goIntoComponent(m_selectedMaterial);
|
||||
}
|
||||
|
||||
} // QmlDesigner
|
||||
|
@@ -43,9 +43,13 @@ class MaterialEditorContextObject : public QObject
|
||||
Q_OBJECT
|
||||
|
||||
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(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 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 hasQuick3DImport READ hasQuick3DImport WRITE setHasQuick3DImport NOTIFY hasQuick3DImportChanged)
|
||||
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)
|
||||
|
||||
public:
|
||||
MaterialEditorContextObject(QObject *parent = nullptr);
|
||||
MaterialEditorContextObject(QQmlContext *context, QObject *parent = nullptr);
|
||||
|
||||
QUrl specificsUrl() const { return m_specificsUrl; }
|
||||
QString specificQmlData() const {return m_specificQmlData; }
|
||||
QQmlComponent *specificQmlComponent();
|
||||
QString stateName() const { return m_stateName; }
|
||||
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 selectionChanged() const { return m_selectionChanged; }
|
||||
@@ -86,6 +95,7 @@ public:
|
||||
Q_INVOKABLE QStringList allStatesForId(const QString &id);
|
||||
|
||||
Q_INVOKABLE bool isBlocked(const QString &propName) const;
|
||||
Q_INVOKABLE void goIntoComponent();
|
||||
|
||||
enum ToolBarAction {
|
||||
ApplyToSelected = 0,
|
||||
@@ -105,6 +115,9 @@ public:
|
||||
bool hasQuick3DImport() const;
|
||||
void setHasQuick3DImport(bool b);
|
||||
|
||||
bool hasMaterialRoot() const;
|
||||
void setHasMaterialRoot(bool b);
|
||||
|
||||
bool hasModelSelection() const;
|
||||
void setHasModelSelection(bool b);
|
||||
|
||||
@@ -113,8 +126,11 @@ public:
|
||||
void setSelectedMaterial(const ModelNode &matNode);
|
||||
|
||||
void setSpecificsUrl(const QUrl &newSpecificsUrl);
|
||||
void setSpecificQmlData(const QString &newSpecificQmlData);
|
||||
void setStateName(const QString &newStateName);
|
||||
void setAllStateNames(const QStringList &allStates);
|
||||
void setPossibleTypes(const QStringList &types);
|
||||
void setCurrentType(const QString &type);
|
||||
void setIsBaseState(bool newIsBaseState);
|
||||
void setSelectionChanged(bool newSelectionChanged);
|
||||
void setBackendValues(QQmlPropertyMap *newBackendValues);
|
||||
@@ -125,8 +141,12 @@ public:
|
||||
|
||||
signals:
|
||||
void specificsUrlChanged();
|
||||
void specificQmlDataChanged();
|
||||
void specificQmlComponentChanged();
|
||||
void stateNameChanged();
|
||||
void allStateNamesChanged();
|
||||
void possibleTypesChanged();
|
||||
void possibleTypeIndexChanged();
|
||||
void isBaseStateChanged();
|
||||
void selectionChangedChanged();
|
||||
void backendValuesChanged();
|
||||
@@ -134,18 +154,26 @@ signals:
|
||||
void hasAliasExportChanged();
|
||||
void hasActiveTimelineChanged();
|
||||
void hasQuick3DImportChanged();
|
||||
void hasMaterialRootChanged();
|
||||
void hasModelSelectionChanged();
|
||||
|
||||
private:
|
||||
void updatePossibleTypeIndex();
|
||||
|
||||
QUrl m_specificsUrl;
|
||||
QString m_specificQmlData;
|
||||
QQmlComponent *m_specificQmlComponent = nullptr;
|
||||
QQmlContext *m_qmlContext = nullptr;
|
||||
|
||||
QString m_stateName;
|
||||
QStringList m_allStateNames;
|
||||
QStringList m_possibleTypes;
|
||||
int m_possibleTypeIndex = -1;
|
||||
QString m_currentType;
|
||||
|
||||
int m_majorVersion = 1;
|
||||
|
||||
QQmlPropertyMap *m_backendValues = nullptr;
|
||||
QQmlComponent *m_qmlComponent = nullptr;
|
||||
Model *m_model = nullptr;
|
||||
|
||||
QPoint m_lastPos;
|
||||
@@ -155,6 +183,7 @@ private:
|
||||
bool m_aliasExport = false;
|
||||
bool m_hasActiveTimeline = false;
|
||||
bool m_hasQuick3DImport = false;
|
||||
bool m_hasMaterialRoot = false;
|
||||
bool m_hasModelSelection = false;
|
||||
|
||||
ModelNode m_selectedMaterial;
|
||||
|
@@ -102,7 +102,7 @@ public:
|
||||
MaterialEditorQmlBackend::MaterialEditorQmlBackend(MaterialEditorView *materialEditor)
|
||||
: m_view(new QQuickWidget)
|
||||
, m_materialEditorTransaction(new MaterialEditorTransaction(materialEditor))
|
||||
, m_contextObject(new MaterialEditorContextObject())
|
||||
, m_contextObject(new MaterialEditorContextObject(m_view->rootContext()))
|
||||
, m_materialEditorImageProvider(new MaterialEditorImageProvider())
|
||||
{
|
||||
m_view->setResizeMode(QQuickWidget::SizeRootObjectToView);
|
||||
|
@@ -51,6 +51,7 @@
|
||||
#include <qmldesignerplugin.h>
|
||||
#include <utils/fileutils.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <propertyeditorqmlbackend.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
@@ -62,6 +63,7 @@
|
||||
#include <QStackedWidget>
|
||||
#include <QShortcut>
|
||||
#include <QTimer>
|
||||
#include <QColorDialog>
|
||||
|
||||
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(
|
||||
QString::fromUtf8(Utils::FileReader::fetchQrc(":/qmldesigner/stylesheet.css"))));
|
||||
m_stackedWidget->setMinimumWidth(250);
|
||||
@@ -420,12 +426,15 @@ void MaterialEditorView::handleToolBarAction(int action)
|
||||
if (!model())
|
||||
break;
|
||||
executeInTransaction("MaterialEditorView:handleToolBarAction", [&] {
|
||||
ModelNode matLib = materialLibraryNode();
|
||||
if (!matLib.isValid())
|
||||
return;
|
||||
|
||||
NodeMetaInfo metaInfo = model()->metaInfo("QtQuick3D.DefaultMaterial");
|
||||
ModelNode newMatNode = createModelNode("QtQuick3D.DefaultMaterial", metaInfo.majorVersion(),
|
||||
metaInfo.minorVersion());
|
||||
renameMaterial(newMatNode, "New Material");
|
||||
|
||||
materialLibraryNode().defaultNodeListProperty().reparentHere(newMatNode);
|
||||
matLib.defaultNodeListProperty().reparentHere(newMatNode);
|
||||
});
|
||||
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()
|
||||
{
|
||||
QUrl qmlPaneUrl;
|
||||
QUrl qmlSpecificsUrl;
|
||||
QString specificQmlData;
|
||||
QString currentTypeName;
|
||||
|
||||
if (m_selectedMaterial.isValid() && m_hasQuick3DImport) {
|
||||
qmlPaneUrl = QUrl::fromLocalFile(materialEditorResourcesPath() + "/MaterialEditorPane.qml");
|
||||
|
||||
TypeName diffClassName;
|
||||
NodeMetaInfo metaInfo = m_selectedMaterial.metaInfo();
|
||||
QDir importDir(metaInfo.importDirectoryPath() + Constants::QML_DESIGNER_SUBFOLDER);
|
||||
QString typeName = QString::fromUtf8(metaInfo.typeName().split('.').constLast());
|
||||
qmlSpecificsUrl = QUrl::fromLocalFile(importDir.absoluteFilePath(typeName + "Specifics.qml"));
|
||||
if (metaInfo.isValid()) {
|
||||
diffClassName = metaInfo.typeName();
|
||||
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 {
|
||||
qmlPaneUrl = QUrl::fromLocalFile(materialEditorResourcesPath() + "/EmptyMaterialEditorPane.qml");
|
||||
}
|
||||
@@ -473,17 +574,29 @@ void MaterialEditorView::setupQmlBackend()
|
||||
|
||||
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)));
|
||||
QObject::connect(rootObj, SIGNAL(previewEnvChanged(QString)),
|
||||
this, SLOT(handlePreviewEnvChanged(QString)));
|
||||
QObject::connect(rootObj, SIGNAL(previewModelChanged(QString)),
|
||||
this, SLOT(handlePreviewModelChanged(QString)));
|
||||
} else {
|
||||
currentQmlBackend->setup(m_selectedMaterial, currentStateName, qmlSpecificsUrl, this);
|
||||
}
|
||||
|
||||
currentQmlBackend->widget()->installEventFilter(this);
|
||||
currentQmlBackend->contextObject()->setHasQuick3DImport(m_hasQuick3DImport);
|
||||
|
||||
m_stackedWidget->setCurrentWidget(currentQmlBackend->widget());
|
||||
currentQmlBackend->contextObject()->setHasMaterialRoot(m_hasMaterialRoot);
|
||||
currentQmlBackend->contextObject()->setSpecificQmlData(specificQmlData);
|
||||
currentQmlBackend->contextObject()->setCurrentType(currentTypeName);
|
||||
|
||||
m_qmlBackEnd = currentQmlBackend;
|
||||
|
||||
delayedTypeUpdate();
|
||||
initPreviewData();
|
||||
|
||||
m_stackedWidget->setCurrentWidget(m_qmlBackEnd->widget());
|
||||
}
|
||||
|
||||
void MaterialEditorView::commitVariantValueToModel(const PropertyName &propertyName, const QVariant &value)
|
||||
@@ -529,6 +642,75 @@ bool MaterialEditorView::noValidSelection() const
|
||||
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)
|
||||
{
|
||||
AbstractView::modelAttached(model);
|
||||
@@ -536,11 +718,27 @@ void MaterialEditorView::modelAttached(Model *model)
|
||||
m_locked = true;
|
||||
|
||||
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
|
||||
// not complete yet, so we keep checking until type info is complete.
|
||||
if (m_hasQuick3DImport)
|
||||
if (m_hasMaterialRoot) {
|
||||
m_selectedMaterial = rootModelNode();
|
||||
} 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);
|
||||
}
|
||||
|
||||
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) {
|
||||
reloadQml();
|
||||
@@ -705,10 +903,20 @@ void MaterialEditorView::instancePropertyChanged(const QList<QPair<ModelNode, Pr
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -752,6 +960,10 @@ void MaterialEditorView::duplicateMaterial(const ModelNode &material)
|
||||
QmlObjectNode sourceMat(material);
|
||||
|
||||
executeInTransaction(__FUNCTION__, [&] {
|
||||
ModelNode matLib = materialLibraryNode();
|
||||
if (!matLib.isValid())
|
||||
return;
|
||||
|
||||
// create the duplicate material
|
||||
NodeMetaInfo metaInfo = model()->metaInfo(matType);
|
||||
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());
|
||||
}
|
||||
|
||||
materialLibraryNode().defaultNodeListProperty().reparentHere(duplicateMat);
|
||||
matLib.defaultNodeListProperty().reparentHere(duplicateMat);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -783,8 +995,10 @@ void MaterialEditorView::customNotification([[maybe_unused]] const AbstractView
|
||||
const QList<QVariant> &data)
|
||||
{
|
||||
if (identifier == "selected_material_changed") {
|
||||
m_selectedMaterial = nodeList.first();
|
||||
QTimer::singleShot(0, this, &MaterialEditorView::resetView);
|
||||
if (!m_hasMaterialRoot) {
|
||||
m_selectedMaterial = nodeList.first();
|
||||
QTimer::singleShot(0, this, &MaterialEditorView::resetView);
|
||||
}
|
||||
} else if (identifier == "apply_to_selected_triggered") {
|
||||
applyMaterialToSelectedModels(nodeList.first(), data.first().toBool());
|
||||
} else if (identifier == "rename_material") {
|
||||
@@ -843,6 +1057,15 @@ void MaterialEditorView::setValue(const QmlObjectNode &qmlObjectNode, const Prop
|
||||
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()
|
||||
{
|
||||
m_qmlBackendHash.clear();
|
||||
|
@@ -26,13 +26,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <abstractview.h>
|
||||
#include <itemlibraryinfo.h>
|
||||
|
||||
#include <QHash>
|
||||
#include <QPointer>
|
||||
#include <QTimer>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QShortcut;
|
||||
class QStackedWidget;
|
||||
class QTimer;
|
||||
class QColorDialog;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace QmlDesigner {
|
||||
@@ -70,6 +74,7 @@ public:
|
||||
void instancePropertyChanged(const QList<QPair<ModelNode, PropertyName> > &propertyList) 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 importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
|
||||
void customNotification(const AbstractView *view, const QString &identifier,
|
||||
@@ -89,10 +94,13 @@ public:
|
||||
|
||||
public slots:
|
||||
void handleToolBarAction(int action);
|
||||
void handlePreviewEnvChanged(const QString &envAndValue);
|
||||
void handlePreviewModelChanged(const QString &modelStr);
|
||||
|
||||
protected:
|
||||
void timerEvent(QTimerEvent *event) override;
|
||||
void setValue(const QmlObjectNode &fxObjectNode, const PropertyName &name, const QVariant &value);
|
||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
|
||||
private:
|
||||
static QString materialEditorResourcesPath();
|
||||
@@ -115,8 +123,13 @@ private:
|
||||
|
||||
bool noValidSelection() const;
|
||||
|
||||
void initPreviewData();
|
||||
void delayedTypeUpdate();
|
||||
void updatePossibleTypes();
|
||||
|
||||
ModelNode m_selectedMaterial;
|
||||
QTimer m_ensureMatLibTimer;
|
||||
QTimer m_typeUpdateTimer;
|
||||
QShortcut *m_updateShortcut = nullptr;
|
||||
int m_timerId = 0;
|
||||
QStackedWidget *m_stackedWidget = nullptr;
|
||||
@@ -126,6 +139,11 @@ private:
|
||||
bool m_locked = false;
|
||||
bool m_setupCompleted = false;
|
||||
bool m_hasQuick3DImport = false;
|
||||
bool m_hasMaterialRoot = false;
|
||||
bool m_initializingPreviewData = false;
|
||||
|
||||
QPointer<QColorDialog> m_colorDialog;
|
||||
QPointer<ItemLibraryInfo> m_itemLibraryInfo;
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
@@ -65,7 +65,7 @@ QModelIndex StatesEditorModel::index(int row, int column, const QModelIndex &par
|
||||
|
||||
int internalNodeId = 0;
|
||||
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();
|
||||
}
|
||||
@@ -75,10 +75,10 @@ int StatesEditorModel::rowCount(const QModelIndex &parent) const
|
||||
if (parent.isValid() || m_statesEditorView.isNull() || !m_statesEditorView->model())
|
||||
return 0;
|
||||
|
||||
if (!m_statesEditorView->rootModelNode().hasNodeListProperty("states"))
|
||||
if (!m_statesEditorView->acitveStatesGroupNode().hasNodeListProperty("states"))
|
||||
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()
|
||||
|
@@ -85,6 +85,20 @@ void StatesEditorView::rootNodeTypeChanged(const QString &/*type*/, int /*majorV
|
||||
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)
|
||||
{
|
||||
try {
|
||||
@@ -193,12 +207,12 @@ void StatesEditorView::createNewState()
|
||||
void StatesEditorView::addState()
|
||||
{
|
||||
// can happen when root node is e.g. a ListModel
|
||||
if (!QmlVisualNode::isValidQmlVisualNode(rootModelNode()))
|
||||
if (!QmlVisualNode::isValidQmlVisualNode(acitveStatesGroupNode()))
|
||||
return;
|
||||
|
||||
QmlDesignerPlugin::emitUsageStatistics(Constants::EVENT_STATE_ADDED);
|
||||
|
||||
QStringList modelStateNames = rootStateGroup().names();
|
||||
QStringList modelStateNames = activeStateGroup().names();
|
||||
|
||||
QString newStateName;
|
||||
int index = 1;
|
||||
@@ -209,9 +223,9 @@ void StatesEditorView::addState()
|
||||
}
|
||||
|
||||
executeInTransaction("addState", [this, newStateName]() {
|
||||
rootModelNode().validId();
|
||||
acitveStatesGroupNode().validId();
|
||||
|
||||
ModelNode newState = rootStateGroup().addState(newStateName);
|
||||
ModelNode newState = activeStateGroup().addState(newStateName);
|
||||
setCurrentState(newState);
|
||||
});
|
||||
}
|
||||
@@ -244,7 +258,7 @@ void StatesEditorView::duplicateCurrentState()
|
||||
newName = newName.left(match.capturedStart());
|
||||
|
||||
int i = 1;
|
||||
QStringList stateNames = rootStateGroup().names();
|
||||
QStringList stateNames = activeStateGroup().names();
|
||||
while (stateNames.contains(newName + QString::number(i)))
|
||||
i++;
|
||||
const QString newStateName = newName + QString::number(i);
|
||||
@@ -258,7 +272,7 @@ void StatesEditorView::duplicateCurrentState()
|
||||
void StatesEditorView::checkForStatesAvailability()
|
||||
{
|
||||
if (m_statesEditorWidget) {
|
||||
const bool isVisual = QmlVisualNode::isValidQmlVisualNode(rootModelNode());
|
||||
const bool isVisual = QmlVisualNode::isValidQmlVisualNode(acitveStatesGroupNode());
|
||||
m_statesEditorWidget->showAddNewStatesButton(isVisual);
|
||||
}
|
||||
}
|
||||
@@ -277,16 +291,16 @@ QmlModelState StatesEditorView::baseState() const
|
||||
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
|
||||
{
|
||||
if (name == tr("base state"))
|
||||
return false;
|
||||
const QList<QmlModelState> modelStates = rootStateGroup().allStates();
|
||||
const QList<QmlModelState> modelStates = activeStateGroup().allStates();
|
||||
for (const QmlModelState &state : modelStates) {
|
||||
if (state.name() == name)
|
||||
return false;
|
||||
@@ -392,8 +406,8 @@ void StatesEditorView::resetDefaultState()
|
||||
auto guard = qScopeGuard([&]() { m_block = false; });
|
||||
|
||||
try {
|
||||
if (rootModelNode().hasProperty("state"))
|
||||
rootModelNode().removeProperty("state");
|
||||
if (acitveStatesGroupNode().hasProperty("state"))
|
||||
acitveStatesGroupNode().removeProperty("state");
|
||||
|
||||
} catch (const RewritingException &e) {
|
||||
e.showException();
|
||||
@@ -402,7 +416,7 @@ void StatesEditorView::resetDefaultState()
|
||||
|
||||
bool StatesEditorView::hasDefaultState() const
|
||||
{
|
||||
return rootModelNode().hasProperty("state");
|
||||
return acitveStatesGroupNode().hasProperty("state");
|
||||
}
|
||||
|
||||
void StatesEditorView::setAnnotation(int internalNodeId)
|
||||
@@ -475,6 +489,8 @@ void StatesEditorView::modelAttached(Model *model)
|
||||
Q_ASSERT(model);
|
||||
AbstractView::modelAttached(model);
|
||||
|
||||
m_activeStatesGroupNode = rootModelNode();
|
||||
|
||||
if (m_statesEditorWidget)
|
||||
m_statesEditorWidget->setNodeInstanceView(nodeInstanceView());
|
||||
|
||||
@@ -593,7 +609,7 @@ void StatesEditorView::instancesPreviewImageChanged(const QVector<ModelNode> &no
|
||||
minimumIndex = qMin(minimumIndex, 0);
|
||||
maximumIndex = qMax(maximumIndex, 0);
|
||||
} else {
|
||||
int index = rootStateGroup().allStates().indexOf(QmlModelState(node)) + 1;
|
||||
int index = activeStateGroup().allStates().indexOf(QmlModelState(node)) + 1;
|
||||
if (index > 0) {
|
||||
minimumIndex = qMin(minimumIndex, index);
|
||||
maximumIndex = qMax(maximumIndex, index);
|
||||
|
@@ -55,7 +55,7 @@ public:
|
||||
QString currentStateName() const;
|
||||
void setCurrentState(const QmlModelState &state);
|
||||
QmlModelState baseState() const;
|
||||
QmlModelStateGroup rootStateGroup() const;
|
||||
QmlModelStateGroup activeStateGroup() const;
|
||||
|
||||
// AbstractView
|
||||
void modelAttached(Model *model) override;
|
||||
@@ -87,6 +87,10 @@ public:
|
||||
|
||||
void rootNodeTypeChanged(const QString &type, int majorVersion, int minorVersion) override;
|
||||
|
||||
ModelNode acitveStatesGroupNode() const;
|
||||
void setAcitveStatesGroupNode(const ModelNode &modelNode);
|
||||
|
||||
|
||||
public slots:
|
||||
void synchonizeCurrentStateFromWidget();
|
||||
void createNewState();
|
||||
@@ -105,6 +109,7 @@ private:
|
||||
int m_lastIndex;
|
||||
bool m_block = false;
|
||||
QPointer<AnnotationEditor> m_editor;
|
||||
ModelNode m_activeStatesGroupNode;
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
@@ -24,47 +24,147 @@
|
||||
****************************************************************************/
|
||||
|
||||
#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 {
|
||||
|
||||
SetFrameValueDialog::SetFrameValueDialog(qreal frame, const QVariant &value,
|
||||
const QString &propertyName, QWidget *parent)
|
||||
: QDialog(parent)
|
||||
, ui(new Ui::SetFrameValueDialog)
|
||||
: QDialog(parent, Qt::Tool)
|
||||
, m_valueGetter()
|
||||
, m_valueType(value.metaType())
|
||||
, m_frameControl(new QSpinBox)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setWindowTitle(tr("Edit Keyframe"));
|
||||
setFixedSize(size());
|
||||
|
||||
ui->lineEditFrame->setValidator(new QIntValidator(0, 99999, this));
|
||||
auto dv = new QDoubleValidator(this);
|
||||
dv->setDecimals(2);
|
||||
ui->lineEditValue->setValidator(dv);
|
||||
auto frameLabelString = QString(tr("Frame"));
|
||||
auto labelWidth = fontMetrics().boundingRect(frameLabelString).width();
|
||||
if (auto tmp = fontMetrics().boundingRect(propertyName).width(); tmp > labelWidth)
|
||||
labelWidth = tmp;
|
||||
|
||||
QLocale l;
|
||||
ui->lineEditFrame->setText(l.toString(qRound(frame)));
|
||||
ui->lineEditValue->setText(l.toString(value.toDouble(), 'f', 2));
|
||||
ui->labelValue->setText(propertyName);
|
||||
auto *frameLabel = new QLabel(frameLabelString);
|
||||
frameLabel->setAlignment(Qt::AlignRight);
|
||||
frameLabel->setFixedWidth(labelWidth);
|
||||
|
||||
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()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
{ }
|
||||
|
||||
qreal SetFrameValueDialog::frame() const
|
||||
{
|
||||
QLocale l;
|
||||
return l.toDouble(ui->lineEditFrame->text());
|
||||
return static_cast<qreal>(m_frameControl->value());
|
||||
}
|
||||
|
||||
QVariant SetFrameValueDialog::value() const
|
||||
{
|
||||
QLocale l;
|
||||
return QVariant(l.toDouble(ui->lineEditValue->text()));
|
||||
if (m_valueGetter)
|
||||
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
|
||||
|
@@ -27,14 +27,10 @@
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QLineEdit)
|
||||
QT_FORWARD_DECLARE_CLASS(QSpinBox)
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
namespace Ui {
|
||||
class SetFrameValueDialog;
|
||||
}
|
||||
|
||||
class SetFrameValueDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -48,7 +44,12 @@ public:
|
||||
QVariant value() const;
|
||||
|
||||
private:
|
||||
Ui::SetFrameValueDialog *ui;
|
||||
QWidget* createValueControl(const QVariant& value);
|
||||
|
||||
std::function<QVariant(void)> m_valueGetter;
|
||||
|
||||
QMetaType m_valueType;
|
||||
QSpinBox *m_frameControl;
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
@@ -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>
|
@@ -191,7 +191,7 @@ void ColorControl::mouseReleaseEvent(QMouseEvent *event)
|
||||
|
||||
event->accept();
|
||||
|
||||
if (color != m_color) {
|
||||
if (color.isValid() && color != m_color) {
|
||||
m_color = color;
|
||||
update();
|
||||
emit valueChanged();
|
||||
|
@@ -1044,6 +1044,18 @@ bool shouldSendAuxiliary(const AuxiliaryDataKey &key)
|
||||
}
|
||||
} // 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()
|
||||
{
|
||||
QList<ModelNode> nodeList = allModelNodes();
|
||||
@@ -1103,7 +1115,7 @@ CreateSceneCommand NodeInstanceView::createCreateSceneCommand()
|
||||
nodeMetaType,
|
||||
nodeFlags);
|
||||
|
||||
if (instance.modelNode().behaviorPropertyName().isEmpty())
|
||||
if (!parentIsBehavior(instance.modelNode()))
|
||||
instanceContainerList.append(container);
|
||||
}
|
||||
|
||||
|
@@ -836,7 +836,7 @@ void AbstractView::changeRootNodeType(const TypeName &type, int majorVersion, in
|
||||
void AbstractView::ensureMaterialLibraryNode()
|
||||
{
|
||||
ModelNode matLib = modelNodeForId(Constants::MATERIAL_LIB_ID);
|
||||
if (matLib.isValid())
|
||||
if (matLib.isValid() || rootModelNode().isSubclassOf("QtQuick3D.Material"))
|
||||
return;
|
||||
|
||||
// Create material library node
|
||||
@@ -865,13 +865,11 @@ void AbstractView::ensureMaterialLibraryNode()
|
||||
}
|
||||
|
||||
// Returns ModelNode for project's material library.
|
||||
// Since this calls ensureMaterialLibraryNode(), it should only be called within a transaction.
|
||||
ModelNode AbstractView::materialLibraryNode()
|
||||
{
|
||||
ensureMaterialLibraryNode();
|
||||
|
||||
ModelNode matLib = modelNodeForId(Constants::MATERIAL_LIB_ID);
|
||||
QTC_ASSERT(matLib.isValid(), return {});
|
||||
|
||||
return matLib;
|
||||
}
|
||||
|
||||
|
@@ -408,8 +408,12 @@ void ModelPrivate::notifyNodeInstanceViewLast(Callable call)
|
||||
}
|
||||
|
||||
for (const QPointer<AbstractView> &view : enabledViews()) {
|
||||
if (!view->isBlockingNotifications())
|
||||
call(view.data());
|
||||
try {
|
||||
if (!view->isBlockingNotifications())
|
||||
call(view.data());
|
||||
} catch (const Exception &e) {
|
||||
e.showException(tr("Exception thrown by view %1.").arg(view->widgetInfo().tabName));
|
||||
}
|
||||
}
|
||||
|
||||
if (nodeInstanceView() && !nodeInstanceView()->isBlockingNotifications())
|
||||
|
@@ -88,6 +88,7 @@ RewriterView::RewriterView(DifferenceHandling differenceHandling, QObject *paren
|
||||
m_textToModelMerger(new Internal::TextToModelMerger(this))
|
||||
{
|
||||
m_amendTimer.setSingleShot(true);
|
||||
|
||||
m_amendTimer.setInterval(800);
|
||||
connect(&m_amendTimer, &QTimer::timeout, this, &RewriterView::amendQmlText);
|
||||
|
||||
@@ -524,6 +525,10 @@ void RewriterView::applyChanges()
|
||||
|
||||
void RewriterView::amendQmlText()
|
||||
{
|
||||
|
||||
if (!model()->rewriterView())
|
||||
return;
|
||||
|
||||
emitCustomNotification(StartRewriterAmend);
|
||||
|
||||
const QString newQmlText = m_textModifier->text();
|
||||
|
@@ -525,13 +525,15 @@ public:
|
||||
&& metaInfo.majorVersion() == majorVersion
|
||||
&& metaInfo.minorVersion() == minorVersion;
|
||||
|
||||
|
||||
if (!ok) {
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
qDebug() << astTypeNode->name.toString() << typeName;
|
||||
qDebug() << metaInfo.isValid() << metaInfo.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");
|
||||
}
|
||||
|
||||
@@ -1715,7 +1717,7 @@ void TextToModelMerger::syncSignalDeclarationProperty(AbstractProperty &modelPro
|
||||
const QString &signature,
|
||||
DifferenceHandler &differenceHandler)
|
||||
{
|
||||
if (modelProperty.isSignalHandlerProperty()) {
|
||||
if (modelProperty.isSignalDeclarationProperty()) {
|
||||
SignalDeclarationProperty signalHandlerProperty = modelProperty.toSignalDeclarationProperty();
|
||||
if (signalHandlerProperty.signature() != signature)
|
||||
differenceHandler.signalDeclarationSignatureDiffer(signalHandlerProperty, signature);
|
||||
|
@@ -28,6 +28,7 @@
|
||||
#include "designmodewidget.h"
|
||||
#include "formeditorwidget.h"
|
||||
#include "edit3dwidget.h"
|
||||
#include "materialbrowserwidget.h"
|
||||
#include "navigatorwidget.h"
|
||||
#include "texteditorwidget.h"
|
||||
|
||||
@@ -70,6 +71,18 @@ void Editor3DContext::contextHelp(const HelpCallback &callback) const
|
||||
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)
|
||||
: IContext(widget)
|
||||
{
|
||||
|
@@ -60,6 +60,15 @@ public:
|
||||
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
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@@ -390,19 +390,26 @@ void DesignModeWidget::setup()
|
||||
|
||||
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(),
|
||||
&Core::ModeManager::currentModeChanged,
|
||||
this,
|
||||
[this](Utils::Id mode, Utils::Id oldMode) {
|
||||
[this](Utils::Id mode, Utils::Id previousMode) {
|
||||
if (mode == Core::Constants::MODE_DESIGN) {
|
||||
m_dockManager->reloadActiveWorkspace();
|
||||
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->setModeChangeState(true);
|
||||
for (auto floatingWidget : m_dockManager->floatingWidgets())
|
||||
for (auto &floatingWidget : m_dockManager->floatingWidgets())
|
||||
floatingWidget->hide();
|
||||
}
|
||||
});
|
||||
|
@@ -32,11 +32,12 @@ const char C_BACKSPACE[] = "QmlDesigner.Backspace";
|
||||
const char C_DELETE[] = "QmlDesigner.Delete";
|
||||
|
||||
// Context
|
||||
const char C_QMLDESIGNER[] = "QmlDesigner::QmlDesignerMain";
|
||||
const char C_QMLFORMEDITOR[] = "QmlDesigner::FormEditor";
|
||||
const char C_QMLEDITOR3D[] = "QmlDesigner::Editor3D";
|
||||
const char C_QMLNAVIGATOR[] = "QmlDesigner::Navigator";
|
||||
const char C_QMLTEXTEDITOR[] = "QmlDesigner::TextEditor";
|
||||
const char C_QMLDESIGNER[] = "QmlDesigner::QmlDesignerMain";
|
||||
const char C_QMLFORMEDITOR[] = "QmlDesigner::FormEditor";
|
||||
const char C_QMLEDITOR3D[] = "QmlDesigner::Editor3D";
|
||||
const char C_QMLNAVIGATOR[] = "QmlDesigner::Navigator";
|
||||
const char C_QMLTEXTEDITOR[] = "QmlDesigner::TextEditor";
|
||||
const char C_QMLMATERIALBROWSER[] = "QmlDesigner::MaterialBrowser";
|
||||
|
||||
// Special context for preview menu, shared b/w designer and text editor
|
||||
const char C_QT_QUICK_TOOLS_MENU[] = "QmlDesigner::ToolsMenu";
|
||||
|
@@ -399,15 +399,18 @@ void QmlDesignerPlugin::integrateIntoQtCreator(QWidget *modeWidget)
|
||||
Core::Context qmlDesignerFormEditorContext(Constants::C_QMLFORMEDITOR);
|
||||
Core::Context qmlDesignerEditor3dContext(Constants::C_QMLEDITOR3D);
|
||||
Core::Context qmlDesignerNavigatorContext(Constants::C_QMLNAVIGATOR);
|
||||
Core::Context qmlDesignerMaterialBrowserContext(Constants::C_QMLMATERIALBROWSER);
|
||||
|
||||
context->context().add(qmlDesignerMainContext);
|
||||
context->context().add(qmlDesignerFormEditorContext);
|
||||
context->context().add(qmlDesignerEditor3dContext);
|
||||
context->context().add(qmlDesignerNavigatorContext);
|
||||
context->context().add(qmlDesignerMaterialBrowserContext);
|
||||
context->context().add(ProjectExplorer::Constants::QMLJS_LANGUAGE_ID);
|
||||
|
||||
d->shortCutManager.registerActions(qmlDesignerMainContext, qmlDesignerFormEditorContext,
|
||||
qmlDesignerEditor3dContext, qmlDesignerNavigatorContext);
|
||||
qmlDesignerEditor3dContext, qmlDesignerNavigatorContext,
|
||||
qmlDesignerMaterialBrowserContext);
|
||||
|
||||
const QStringList mimeTypes = { QmlJSTools::Constants::QML_MIMETYPE,
|
||||
QmlJSTools::Constants::QMLUI_MIMETYPE };
|
||||
|
@@ -1011,7 +1011,6 @@ Project {
|
||||
"timelineeditor/preseteditor.h",
|
||||
"timelineeditor/setframevaluedialog.cpp",
|
||||
"timelineeditor/setframevaluedialog.h",
|
||||
"timelineeditor/setframevaluedialog.ui",
|
||||
"timelineeditor/splineeditor.cpp",
|
||||
"timelineeditor/splineeditor.h",
|
||||
"timelineeditor/timeline.qrc",
|
||||
|
@@ -77,8 +77,11 @@ ShortCutManager::ShortCutManager()
|
||||
void ShortCutManager::registerActions(const Core::Context &qmlDesignerMainContext,
|
||||
const Core::Context &qmlDesignerFormEditorContext,
|
||||
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 *fileMenu = Core::ActionManager::actionContainer(Core::Constants::M_FILE);
|
||||
|
||||
@@ -195,9 +198,12 @@ void ShortCutManager::registerActions(const Core::Context &qmlDesignerMainContex
|
||||
m_pasteAction.setEnabled(true);
|
||||
});
|
||||
|
||||
connect(Core::ICore::instance(), &Core::ICore::contextChanged, this, [&designerActionManager, this](const Core::Context &context){
|
||||
if (!context.contains(Constants::C_QMLFORMEDITOR) && !context.contains(Constants::C_QMLEDITOR3D) && !context.contains(Constants::C_QMLNAVIGATOR)) {
|
||||
m_deleteAction.setEnabled(false);
|
||||
connect(Core::ICore::instance(), &Core::ICore::contextChanged, this, [&](const Core::Context &context) {
|
||||
isMatBrowserActive = context.contains(Constants::C_QMLMATERIALBROWSER);
|
||||
|
||||
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_copyAction.setEnabled(false);
|
||||
m_pasteAction.setEnabled(false);
|
||||
@@ -249,8 +255,12 @@ void ShortCutManager::redo()
|
||||
|
||||
void ShortCutManager::deleteSelected()
|
||||
{
|
||||
if (currentDesignDocument())
|
||||
if (isMatBrowserActive) {
|
||||
DesignerActionManager &designerActionManager = QmlDesignerPlugin::instance()->viewManager().designerActionManager();
|
||||
designerActionManager.view()->emitCustomNotification("delete_selected_material");
|
||||
} else if (currentDesignDocument()) {
|
||||
currentDesignDocument()->deleteSelected();
|
||||
}
|
||||
}
|
||||
|
||||
void ShortCutManager::cutSelected()
|
||||
|
@@ -47,7 +47,8 @@ public:
|
||||
void registerActions(const Core::Context &qmlDesignerMainContext,
|
||||
const Core::Context &qmlDesignerFormEditorContext,
|
||||
const Core::Context &qmlDesignerEditor3DContext,
|
||||
const Core::Context &qmlDesignerNavigatorContext);
|
||||
const Core::Context &qmlDesignerNavigatorContext,
|
||||
const Core::Context &qmlDesignerMaterialBrowserContext);
|
||||
|
||||
void connectUndoActions(DesignDocument *designDocument);
|
||||
void disconnectUndoActions(DesignDocument *designDocument);
|
||||
@@ -84,6 +85,8 @@ private:
|
||||
QAction m_pasteAction;
|
||||
QAction m_selectAllAction;
|
||||
QAction m_escapeAction;
|
||||
|
||||
bool isMatBrowserActive = false;
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
@@ -1,18 +1,25 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2017 The Qt Company Ltd
|
||||
** All rights reserved.
|
||||
** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us
|
||||
** Copyright (C) 2017 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** 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
|
||||
** accordance with the Qt Enterprise License Agreement provided with the
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company.
|
||||
** 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
|
||||
** contact form at http://www.qt.io/contact-us
|
||||
** GNU General Public License Usage
|
||||
** 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.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
@@ -1,18 +1,25 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2017 The Qt Company Ltd
|
||||
** All rights reserved.
|
||||
** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us
|
||||
** Copyright (C) 2017 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** 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
|
||||
** accordance with the Qt Enterprise License Agreement provided with the
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company.
|
||||
** 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
|
||||
** contact form at http://www.qt.io/contact-us
|
||||
** GNU General Public License Usage
|
||||
** 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.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
@@ -39,12 +39,6 @@ ColorSettings::ColorSettings(QWidget *parent)
|
||||
m_ui.setupUi(this);
|
||||
|
||||
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();
|
||||
|
||||
@@ -54,6 +48,14 @@ ColorSettings::ColorSettings(QWidget *parent)
|
||||
for (auto it = m_colorThemes.cbegin(); it != m_colorThemes.cend(); ++it)
|
||||
m_ui.m_comboColorThemes->addItem(it.key());
|
||||
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()
|
||||
|
@@ -456,21 +456,28 @@ DataModelDownloader::DataModelDownloader(QObject * /* parent */)
|
||||
&FileDownloader::progressChanged,
|
||||
this,
|
||||
&DataModelDownloader::progressChanged);
|
||||
|
||||
connect(&m_fileDownloader,
|
||||
&FileDownloader::downloadFailed,
|
||||
this,
|
||||
&DataModelDownloader::downloadFailed);
|
||||
}
|
||||
|
||||
void DataModelDownloader::start()
|
||||
bool DataModelDownloader::start()
|
||||
{
|
||||
|
||||
if (!enableDownload()) {
|
||||
m_available = false;
|
||||
emit availableChanged();
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_fileDownloader.setUrl(QUrl::fromUserInput(
|
||||
"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();
|
||||
|
||||
@@ -484,6 +491,8 @@ void DataModelDownloader::start()
|
||||
if (!m_forceDownload && (m_fileDownloader.lastModified() <= m_birthTime))
|
||||
return;
|
||||
|
||||
started = true;
|
||||
|
||||
m_fileDownloader.start();
|
||||
connect(&m_fileDownloader, &FileDownloader::finishedChanged, this, [this]() {
|
||||
if (m_fileDownloader.finished()) {
|
||||
@@ -501,6 +510,7 @@ void DataModelDownloader::start()
|
||||
}
|
||||
});
|
||||
});
|
||||
return started;
|
||||
}
|
||||
|
||||
bool DataModelDownloader::exists() const
|
||||
|
@@ -163,7 +163,7 @@ class DataModelDownloader : public QObject
|
||||
|
||||
public:
|
||||
explicit DataModelDownloader(QObject *parent = nullptr);
|
||||
void start();
|
||||
bool start();
|
||||
bool exists() const;
|
||||
bool available() const;
|
||||
Utils::FilePath targetFolder() const;
|
||||
@@ -174,6 +174,7 @@ signals:
|
||||
void finished();
|
||||
void availableChanged();
|
||||
void progressChanged();
|
||||
void downloadFailed();
|
||||
|
||||
private:
|
||||
FileDownloader m_fileDownloader;
|
||||
|
@@ -453,7 +453,11 @@ public:
|
||||
~WelcomeMode() override;
|
||||
|
||||
private:
|
||||
QQuickWidget *m_modeWidget = nullptr;
|
||||
void setupQuickWidget(const QString &welcomePagePath);
|
||||
void createQuickWidget();
|
||||
|
||||
QQuickWidget *m_quickWidget = nullptr;
|
||||
QWidget *m_modeWidget = nullptr;
|
||||
DataModelDownloader *m_dataModelDownloader = nullptr;
|
||||
};
|
||||
|
||||
@@ -637,31 +641,31 @@ WelcomeMode::WelcomeMode()
|
||||
QFontDatabase::addApplicationFont(":/studiofonts/TitilliumWeb-Regular.ttf");
|
||||
ExampleCheckout::registerTypes();
|
||||
|
||||
m_modeWidget = new QQuickWidget;
|
||||
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);
|
||||
createQuickWidget();
|
||||
|
||||
if (forceDownLoad() || !readme.exists()) // Only downloads contain the readme
|
||||
m_dataModelDownloader->setForceDownload(true);
|
||||
|
||||
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](){
|
||||
auto source = m_modeWidget->source();
|
||||
m_modeWidget->engine()->clearComponentCache();
|
||||
m_modeWidget->setSource(source);
|
||||
m_modeWidget->rootObject()->setProperty("loadingProgress", 100);
|
||||
m_quickWidget->setEnabled(false);
|
||||
|
||||
connect(m_dataModelDownloader, &DataModelDownloader::finished, this, [this, welcomePagePath]() {
|
||||
delete m_quickWidget;
|
||||
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){
|
||||
@@ -669,36 +673,14 @@ WelcomeMode::WelcomeMode()
|
||||
m_modeWidget->rootObject()->setProperty("active", active);
|
||||
});
|
||||
*/
|
||||
setupQuickWidget(welcomePagePath);
|
||||
|
||||
if (!useNewWelcomePage()) {
|
||||
|
||||
#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"));
|
||||
});
|
||||
}
|
||||
QVBoxLayout *boxLayout = new QVBoxLayout();
|
||||
boxLayout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
m_modeWidget = new QWidget;
|
||||
m_modeWidget->setLayout(boxLayout);
|
||||
boxLayout->addWidget(m_quickWidget);
|
||||
setWidget(m_modeWidget);
|
||||
|
||||
QStringList designStudioQchPathes
|
||||
@@ -749,6 +731,51 @@ WelcomeMode::~WelcomeMode()
|
||||
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()
|
||||
: m_buildCheckBox(new QCheckBox(tr("Build")))
|
||||
, m_debugCheckBox(new QCheckBox(tr("Debug")))
|
||||
|
Submodule src/shared/qbs updated: faac35b5b3...3e0553e465
Reference in New Issue
Block a user