diff options
author | Mahmoud Badri <mahmoud.badri@qt.io> | 2022-05-30 15:31:13 +0300 |
---|---|---|
committer | Mahmoud Badri <mahmoud.badri@qt.io> | 2022-05-31 08:57:43 +0000 |
commit | 175343e24ac83b24bc5fa97d857c7fd0cf7c6568 (patch) | |
tree | 11ea5cc04e7a9f995c7f062f64178da2b5149c8a | |
parent | 0a84ef4b2c4d0d044e6ebc99d8a1c4328b7b290c (diff) | |
download | qt-creator-175343e24ac83b24bc5fa97d857c7fd0cf7c6568.tar.gz |
QmlDesigner: Highlight material editor properties upon asset drag
When starting an asset drag in the assets view, highlight all
supported properties in the material editor.
Change-Id: I60935756e4c1384edcc284068163d08ebe529a05
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Samuel Ghinet <samuel.ghinet@qt.io>
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
11 files changed, 101 insertions, 53 deletions
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComboBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComboBox.qml index 48ec9fa470..b9d9f32316 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComboBox.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComboBox.qml @@ -41,6 +41,8 @@ StudioControls.ComboBox { onModelChanged: colorLogic.invalidate() + hasActiveDrag: comboBox.backendValue !== undefined && comboBox.backendValue.hasActiveDrag + // This is available in all editors. onValueTypeChanged: { @@ -83,16 +85,15 @@ StudioControls.ComboBox { onEntered: (drag) => { dropArea.assetPath = drag.getDataAsString(drag.keys[0]).split(",")[0] - - drag.accepted = comboBox.backendValue !== undefined && comboBox.backendValue.isSupportedDrop(dropArea.assetPath) - comboBox.hasActiveDrag = drag.accepted + drag.accepted = comboBox.backendValue !== undefined && comboBox.backendValue.hasActiveDrag + comboBox.hasActiveHoverDrag = drag.accepted } - onExited: comboBox.hasActiveDrag = false + onExited: comboBox.hasActiveHoverDrag = false onDropped: { comboBox.backendValue.commitDrop(dropArea.assetPath) - comboBox.hasActiveDrag = false + comboBox.hasActiveHoverDrag = false } } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBox.qml index fbd4f53062..70cbdf000e 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBox.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBox.qml @@ -39,7 +39,8 @@ T.ComboBox { && myComboBox.enabled property bool edit: myComboBox.activeFocus && myComboBox.editable property bool open: comboBoxPopup.opened - property bool hasActiveDrag: false + property bool hasActiveDrag: false // an item that can be dropped on the combobox is being dragged + property bool hasActiveHoverDrag: false // an item that can be dropped on the combobox is being hovered on the combobox property bool dirty: false // user modification flag @@ -49,6 +50,9 @@ T.ComboBox { property alias textInput: comboBoxInput + property int borderWidth: myComboBox.hasActiveHoverDrag ? StudioTheme.Values.borderHover + : StudioTheme.Values.border + signal compressedActivated(int index, int reason) enum ActivatedReason { EditingFinished, Other } @@ -57,7 +61,7 @@ T.ComboBox { height: StudioTheme.Values.defaultControlHeight leftPadding: actionIndicator.width - rightPadding: popupIndicator.width + StudioTheme.Values.border + rightPadding: popupIndicator.width + myComboBox.borderWidth font.pixelSize: StudioTheme.Values.myFontSize wheelEnabled: false @@ -87,6 +91,7 @@ T.ComboBox { myControl: myComboBox text: myComboBox.editText + borderWidth: myComboBox.borderWidth onEditingFinished: { comboBoxInput.deselect() @@ -108,16 +113,16 @@ T.ComboBox { myControl: myComboBox myPopup: myComboBox.popup x: comboBoxInput.x + comboBoxInput.width - y: StudioTheme.Values.border - width: StudioTheme.Values.checkIndicatorWidth - StudioTheme.Values.border - height: StudioTheme.Values.checkIndicatorHeight - (StudioTheme.Values.border * 2) + y: myComboBox.borderWidth + width: StudioTheme.Values.checkIndicatorWidth - myComboBox.borderWidth + height: StudioTheme.Values.checkIndicatorHeight - myComboBox.borderWidth * 2 } background: Rectangle { id: comboBoxBackground color: StudioTheme.Values.themeControlBackground border.color: StudioTheme.Values.themeControlOutline - border.width: StudioTheme.Values.border + border.width: myComboBox.borderWidth x: actionIndicator.width width: myComboBox.width - actionIndicator.width height: myComboBox.height @@ -144,7 +149,7 @@ T.ComboBox { width: comboBoxPopup.width - comboBoxPopup.leftPadding - comboBoxPopup.rightPadding - (comboBoxPopupScrollBar.visible ? comboBoxPopupScrollBar.contentItem.implicitWidth + 2 : 0) // TODO Magic number - height: StudioTheme.Values.height - 2 * StudioTheme.Values.border + height: StudioTheme.Values.height - 2 * myComboBox.borderWidth padding: 0 enabled: model.enabled === undefined ? true : model.enabled @@ -198,9 +203,9 @@ T.ComboBox { popup: T.Popup { id: comboBoxPopup - x: actionIndicator.width + StudioTheme.Values.border + x: actionIndicator.width + myComboBox.borderWidth y: myComboBox.height - width: myComboBox.width - actionIndicator.width - (StudioTheme.Values.border * 2) + width: myComboBox.width - actionIndicator.width - myComboBox.borderWidth * 2 // TODO Setting the height on the popup solved the problem with the popup of height 0, // but it has the problem that it sometimes extend over the border of the actual window // and is then cut off. @@ -208,7 +213,7 @@ T.ComboBox { + comboBoxPopup.bottomPadding, myComboBox.Window.height - topMargin - bottomMargin, StudioTheme.Values.maxComboBoxPopupHeight) - padding: StudioTheme.Values.border + padding: myComboBox.borderWidth margins: 0 // If not defined margin will be -1 closePolicy: T.Popup.CloseOnPressOutside | T.Popup.CloseOnPressOutsideParent | T.Popup.CloseOnEscape | T.Popup.CloseOnReleaseOutside @@ -252,8 +257,9 @@ T.ComboBox { PropertyChanges { target: comboBoxBackground color: StudioTheme.Values.themeControlBackground - border.color: hasActiveDrag ? StudioTheme.Values.themeInteraction - : StudioTheme.Values.themeControlOutline + border.color: myComboBox.hasActiveDrag ? StudioTheme.Values.themeInteraction + : StudioTheme.Values.themeControlOutline + border.width: myComboBox.borderWidth } }, // This state is intended for ComboBoxes which aren't editable, but have focus e.g. via diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBoxInput.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBoxInput.qml index de7dcc1f8c..c6b91dc1ad 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBoxInput.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBoxInput.qml @@ -34,6 +34,7 @@ TextInput { property bool edit: textInput.activeFocus property bool hover: mouseArea.containsMouse && textInput.enabled + property int borderWidth: StudioTheme.Values.border z: 2 font: myControl.font @@ -55,11 +56,11 @@ TextInput { Rectangle { id: textInputBackground - x: StudioTheme.Values.border - y: StudioTheme.Values.border + x: textInput.borderWidth + y: textInput.borderWidth z: -1 width: textInput.width - height: StudioTheme.Values.height - (StudioTheme.Values.border * 2) + height: StudioTheme.Values.height - textInput.borderWidth * 2 color: StudioTheme.Values.themeControlBackground border.width: 0 } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml index 75d21a8e29..d9bf43db74 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml @@ -86,6 +86,7 @@ QtObject { property real marginTopBottom: 4 property real border: 1 + property real borderHover: 3 property real maxComboBoxPopupHeight: Math.round(300 * values.scaleFactor) property real maxTextAreaPopupHeight: Math.round(150 * values.scaleFactor) diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp index 221f9ec0f4..7cf91158d6 100644 --- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp +++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp @@ -81,30 +81,20 @@ bool AssetsLibraryWidget::eventFilter(QObject *obj, QEvent *event) if (obj == m_assetsWidget.data()) QMetaObject::invokeMethod(m_assetsWidget->rootObject(), "handleViewFocusOut"); } else if (event->type() == QMouseEvent::MouseMove) { - if (!m_assetsToDrag.isEmpty()) { + if (!m_assetsToDrag.isEmpty() && !m_model.isNull()) { QMouseEvent *me = static_cast<QMouseEvent *>(event); if ((me->globalPos() - m_dragStartPoint).manhattanLength() > 10) { - auto drag = new QDrag(this); - drag->setPixmap(m_assetsIconProvider->requestPixmap(m_assetsToDrag[0], nullptr, {128, 128})); QMimeData *mimeData = new QMimeData; mimeData->setData(Constants::MIME_TYPE_ASSETS, m_assetsToDrag.join(',').toUtf8()); - drag->setMimeData(mimeData); - drag->exec(); - drag->deleteLater(); - + m_model->startDrag(mimeData, + m_assetsIconProvider->requestPixmap(m_assetsToDrag[0], nullptr, {128, 128})); m_assetsToDrag.clear(); } } } else if (event->type() == QMouseEvent::MouseButtonRelease) { m_assetsToDrag.clear(); - QWidget *view = QmlDesignerPlugin::instance()->viewManager().widget("Navigator"); - if (view) { - NavigatorWidget *navView = qobject_cast<NavigatorWidget *>(view); - if (navView) { - navView->setDragType(""); - navView->update(); - } - } + if (m_model) + m_model->endDrag(); } return QObject::eventFilter(obj, event); diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp b/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp index 1b4ce59fb5..d231ba1e51 100644 --- a/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp +++ b/src/plugins/qmldesigner/components/materialeditor/materialeditorview.cpp @@ -29,6 +29,7 @@ #include "materialeditorcontextobject.h" #include "propertyeditorvalue.h" #include "materialeditortransaction.h" +#include "assetslibrarywidget.h" #include <qmldesignerconstants.h> #include <qmltimeline.h> @@ -49,6 +50,7 @@ #include <coreplugin/messagebox.h> #include <designmodewidget.h> #include <qmldesignerplugin.h> +#include <utils/algorithm.h> #include <utils/fileutils.h> #include <utils/qtcassert.h> @@ -798,6 +800,42 @@ void MaterialEditorView::customNotification(const AbstractView *view, const QStr } } +void QmlDesigner::MaterialEditorView::highlightSupportedProperties(bool highlight) +{ + DesignerPropertyMap &propMap = m_qmlBackEnd->backendValuesPropertyMap(); + const QStringList propNames = propMap.keys(); + + for (const QString &propName : propNames) { + if (propName.endsWith("Map")) { + QObject *propEditorValObj = propMap.value(propName).value<QObject *>(); + PropertyEditorValue *propEditorVal = qobject_cast<PropertyEditorValue *>(propEditorValObj); + propEditorVal->setHasActiveDrag(highlight); + } + } +} + +void MaterialEditorView::dragStarted(QMimeData *mimeData) +{ + if (!mimeData->hasFormat(Constants::MIME_TYPE_ASSETS)) + return; + + const QStringList assetPaths = QString::fromUtf8(mimeData->data(Constants::MIME_TYPE_ASSETS)).split(','); + bool isImage = Utils::anyOf(assetPaths, [] (const QString &assetPath) { + QString assetType = AssetsLibraryWidget::getAssetTypeAndData(assetPath).first; + return assetType == Constants::MIME_TYPE_ASSET_IMAGE; + }); + + if (!isImage) // only image assets are dnd supported + return; + + highlightSupportedProperties(); +} + +void MaterialEditorView::dragEnded() +{ + highlightSupportedProperties(false); +} + // from model to material editor void MaterialEditorView::setValue(const QmlObjectNode &qmlObjectNode, const PropertyName &name, const QVariant &value) { diff --git a/src/plugins/qmldesigner/components/materialeditor/materialeditorview.h b/src/plugins/qmldesigner/components/materialeditor/materialeditorview.h index 8ab30a63f4..3e8632d26f 100644 --- a/src/plugins/qmldesigner/components/materialeditor/materialeditorview.h +++ b/src/plugins/qmldesigner/components/materialeditor/materialeditorview.h @@ -73,6 +73,9 @@ public: void customNotification(const AbstractView *view, const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> &data) override; + void dragStarted(QMimeData *mimeData) override; + void dragEnded() override; + void changeValue(const QString &name); void changeExpression(const QString &name); void exportPropertyAsAlias(const QString &name); @@ -93,6 +96,7 @@ private: static QString materialEditorResourcesPath(); void reloadQml(); + void highlightSupportedProperties(bool highlight = true); QString generateIdFromName(const QString &name); void ensureMaterialLibraryNode(); diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp index 8b1eea6dc9..1ef95365e1 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp @@ -274,6 +274,19 @@ bool PropertyEditorValue::isTranslated() const return false; } +bool PropertyEditorValue::hasActiveDrag() const +{ + return m_hasActiveDrag; +} + +void PropertyEditorValue::setHasActiveDrag(bool val) +{ + if (m_hasActiveDrag != val) { + m_hasActiveDrag = val; + emit hasActiveDragChanged(); + } +} + static bool isAllowedSubclassType(const QString &type, const QmlDesigner::NodeMetaInfo &metaInfo) { if (!metaInfo.isValid()) @@ -371,18 +384,6 @@ void PropertyEditorValue::setEnumeration(const QString &scope, const QString &na setValueWithEmit(QVariant::fromValue(newEnumeration)); } -bool PropertyEditorValue::isSupportedDrop(const QString &path) -{ - QString suffix = "*." + QFileInfo(path).suffix().toLower(); - - if (m_modelNode.isSubclassOf("QtQuick3D.Material") && nameAsQString().endsWith("Map")) - return QmlDesigner::AssetsLibraryModel::supportedImageSuffixes().contains(suffix); - - // TODO: handle support for other object properties dnd here (like image source) - - return false; -} - void PropertyEditorValue::exportPropertyAsAlias() { emit exportPropertyAsAliasRequested(nameAsQString()); diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.h b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.h index 2a2b09d5c8..4ae156dc92 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.h +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.h @@ -82,6 +82,7 @@ class PropertyEditorValue : public QObject Q_PROPERTY(bool isBound READ isBound NOTIFY isBoundChanged FINAL) Q_PROPERTY(bool isValid READ isValid NOTIFY isValidChanged FINAL) Q_PROPERTY(bool isTranslated READ isTranslated NOTIFY expressionChanged FINAL) + Q_PROPERTY(bool hasActiveDrag READ hasActiveDrag WRITE setHasActiveDrag NOTIFY hasActiveDragChanged FINAL) Q_PROPERTY(bool isIdList READ isIdList NOTIFY expressionChanged FINAL) Q_PROPERTY(QStringList expressionAsList READ getExpressionAsList NOTIFY expressionChanged FINAL) @@ -117,6 +118,9 @@ public: bool isTranslated() const; + bool hasActiveDrag() const; + void setHasActiveDrag(bool val); + bool isAvailable() const; QmlDesigner::PropertyName name() const; @@ -148,7 +152,6 @@ public: public slots: void resetValue(); void setEnumeration(const QString &scope, const QString &name); - bool isSupportedDrop(const QString &path); signals: void valueChanged(const QString &name, const QVariant&); @@ -164,6 +167,7 @@ signals: void isBoundChanged(); void isValidChanged(); void isExplicitChanged(); + void hasActiveDragChanged(); private: QStringList generateStringList(const QString &string) const; @@ -176,6 +180,7 @@ private: bool m_isInSubState; bool m_isInModel; bool m_isBound; + bool m_hasActiveDrag = false; bool m_isValid; // if the property value belongs to a non-existing complexProperty it is invalid PropertyEditorNodeWrapper *m_complexNode; }; diff --git a/src/plugins/qmldesigner/designercore/include/model.h b/src/plugins/qmldesigner/designercore/include/model.h index 9a2bc14fe6..6b8dfab431 100644 --- a/src/plugins/qmldesigner/designercore/include/model.h +++ b/src/plugins/qmldesigner/designercore/include/model.h @@ -35,6 +35,7 @@ #include <import.h> QT_BEGIN_NAMESPACE +class QPixmap; class QUrl; QT_END_NAMESPACE @@ -44,7 +45,7 @@ namespace Internal { class ModelPrivate; class WriteLocker; class NodeMetaInfoPrivate; -} //Internal +} // namespace Internal class AnchorLine; class ModelNode; @@ -130,7 +131,7 @@ public: QString generateNewId(const QString &prefixName) const; QString generateNewId(const QString &prefixName, const QString &fallbackPrefix) const; - void startDrag(QMimeData *mimeData, const QString iconPath = {}); + void startDrag(QMimeData *mimeData, const QPixmap &icon); void endDrag(); protected: @@ -140,4 +141,4 @@ private: Internal::ModelPrivate *d; }; -} +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/designercore/model/model.cpp b/src/plugins/qmldesigner/designercore/model/model.cpp index d879271c0d..4e38fb3cfb 100644 --- a/src/plugins/qmldesigner/designercore/model/model.cpp +++ b/src/plugins/qmldesigner/designercore/model/model.cpp @@ -1510,12 +1510,12 @@ QString Model::generateNewId(const QString &prefixName, const QString &fallbackP return newId; } -void Model::startDrag(QMimeData *mimeData, const QString iconPath) +void Model::startDrag(QMimeData *mimeData, const QPixmap &icon) { d->notifyDragStarted(mimeData); auto drag = new QDrag(this); - drag->setPixmap(iconPath); + drag->setPixmap(icon); drag->setMimeData(mimeData); drag->exec(); drag->deleteLater(); |