forked from qt-creator/qt-creator
QmlDesigner: Implement material bundle frontend
Fixes: QDS-7500 Change-Id: I60c512bb7664d13160f8c58ce063e1e87b6875ee Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2022 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtQuickDesignerTheme 1.0
|
||||
import HelperWidgets 2.0
|
||||
import StudioTheme 1.0 as StudioTheme
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
signal showContextMenu()
|
||||
|
||||
visible: modelData.bundleMaterialVisible
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
|
||||
onPressed: (mouse) => {
|
||||
if (mouse.button === Qt.LeftButton)
|
||||
rootView.startDragBundleMaterial(modelData, mapToGlobal(mouse.x, mouse.y))
|
||||
else if (mouse.button === Qt.RightButton)
|
||||
root.showContextMenu()
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
spacing: 1
|
||||
|
||||
Item { width: 1; height: 5 } // spacer
|
||||
|
||||
Image {
|
||||
id: img
|
||||
|
||||
width: root.width - 10
|
||||
height: img.width
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
source: modelData.bundleMaterialIcon
|
||||
cache: false
|
||||
}
|
||||
|
||||
TextInput {
|
||||
id: matName
|
||||
|
||||
text: modelData.bundleMaterialName
|
||||
|
||||
width: img.width
|
||||
clip: true
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
horizontalAlignment: TextInput.AlignHCenter
|
||||
|
||||
font.pixelSize: StudioTheme.Values.myFontSize
|
||||
|
||||
readOnly: true
|
||||
selectByMouse: !matName.readOnly
|
||||
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
selectionColor: StudioTheme.Values.themeTextSelectionColor
|
||||
selectedTextColor: StudioTheme.Values.themeTextSelectedTextColor
|
||||
}
|
||||
}
|
||||
}
|
@@ -38,13 +38,15 @@ Item {
|
||||
|
||||
property var currentMaterial: null
|
||||
property int currentMaterialIdx: 0
|
||||
property var currentBundleMaterial: null
|
||||
|
||||
property var matSectionsModel: []
|
||||
|
||||
// Called also from C++ to close context menu on focus out
|
||||
function closeContextMenu()
|
||||
{
|
||||
contextMenu.close()
|
||||
cxtMenu.close()
|
||||
cxtMenuBundle.close()
|
||||
}
|
||||
|
||||
// Called from C++ to refresh a preview material after it changes
|
||||
@@ -68,10 +70,15 @@ Item {
|
||||
|
||||
acceptedButtons: Qt.RightButton
|
||||
|
||||
onClicked: {
|
||||
if (!materialBrowserModel.hasMaterialRoot) {
|
||||
onClicked: (mouse) => {
|
||||
// root context-menu works only for user materials
|
||||
var userMatsSecBottom = mapFromItem(userMaterialsSection, 0, userMaterialsSection.y).y
|
||||
+ userMaterialsSection.height;
|
||||
|
||||
if (!materialBrowserModel.hasMaterialRoot && (!materialBrowserBundleModel.matBundleExists
|
||||
|| mouse.y < userMatsSecBottom)) {
|
||||
root.currentMaterial = null
|
||||
contextMenu.popup()
|
||||
cxtMenu.popup()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,7 +97,7 @@ Item {
|
||||
}
|
||||
|
||||
StudioControls.Menu {
|
||||
id: contextMenu
|
||||
id: cxtMenu
|
||||
|
||||
closePolicy: StudioControls.Menu.CloseOnEscape | StudioControls.Menu.CloseOnPressOutside
|
||||
|
||||
@@ -188,6 +195,32 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
StudioControls.Menu {
|
||||
id: cxtMenuBundle
|
||||
|
||||
closePolicy: StudioControls.Menu.CloseOnEscape | StudioControls.Menu.CloseOnPressOutside
|
||||
|
||||
StudioControls.MenuItem {
|
||||
text: qsTr("Apply to selected (replace)")
|
||||
enabled: root.currentBundleMaterial && materialBrowserModel.hasModelSelection
|
||||
onTriggered: materialBrowserBundleModel.applyToSelected(root.currentBundleMaterial, false)
|
||||
}
|
||||
|
||||
StudioControls.MenuItem {
|
||||
text: qsTr("Apply to selected (add)")
|
||||
enabled: root.currentBundleMaterial && materialBrowserModel.hasModelSelection
|
||||
onTriggered: materialBrowserBundleModel.applyToSelected(root.currentBundleMaterial, true)
|
||||
}
|
||||
|
||||
StudioControls.MenuSeparator {}
|
||||
|
||||
StudioControls.MenuItem {
|
||||
text: qsTr("Add to project")
|
||||
|
||||
onTriggered: materialBrowserBundleModel.addMaterial(root.currentBundleMaterial)
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
id: col
|
||||
y: 5
|
||||
@@ -215,23 +248,12 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
text: qsTr("No match found.");
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
font.pixelSize: StudioTheme.Values.baseFontSize
|
||||
leftPadding: 10
|
||||
visible: materialBrowserModel.hasQuick3DImport && materialBrowserModel.isEmpty
|
||||
&& !searchBox.isEmpty() && !materialBrowserModel.hasMaterialRoot
|
||||
}
|
||||
|
||||
Text {
|
||||
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
|
||||
""
|
||||
}
|
||||
@@ -252,31 +274,115 @@ Item {
|
||||
width: root.width
|
||||
height: root.height - searchBox.height
|
||||
clip: true
|
||||
visible: materialBrowserModel.hasQuick3DImport && !materialBrowserModel.hasMaterialRoot
|
||||
|
||||
Grid {
|
||||
id: grid
|
||||
Column {
|
||||
Section {
|
||||
id: userMaterialsSection
|
||||
|
||||
width: scrollView.width
|
||||
leftPadding: 5
|
||||
rightPadding: 5
|
||||
bottomPadding: 5
|
||||
columns: root.width / root.cellWidth
|
||||
width: root.width
|
||||
caption: qsTr("User materials")
|
||||
hideHeader: !materialBrowserBundleModel.matBundleExists
|
||||
|
||||
Repeater {
|
||||
id: gridRepeater
|
||||
Grid {
|
||||
id: grid
|
||||
|
||||
model: materialBrowserModel
|
||||
delegate: MaterialItem {
|
||||
width: root.cellWidth
|
||||
height: root.cellHeight
|
||||
width: scrollView.width
|
||||
leftPadding: 5
|
||||
rightPadding: 5
|
||||
bottomPadding: 5
|
||||
columns: root.width / root.cellWidth
|
||||
|
||||
onShowContextMenu: {
|
||||
if (searchBox.isEmpty()) {
|
||||
root.currentMaterial = model
|
||||
contextMenu.popup()
|
||||
Repeater {
|
||||
id: gridRepeater
|
||||
|
||||
model: materialBrowserModel
|
||||
delegate: MaterialItem {
|
||||
width: root.cellWidth
|
||||
height: root.cellHeight
|
||||
|
||||
onShowContextMenu: {
|
||||
if (searchBox.isEmpty()) {
|
||||
root.currentMaterial = model
|
||||
cxtMenu.popup()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
text: qsTr("No match found.");
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
font.pixelSize: StudioTheme.Values.baseFontSize
|
||||
leftPadding: 10
|
||||
visible: materialBrowserModel.isEmpty && !searchBox.isEmpty() && !materialBrowserModel.hasMaterialRoot
|
||||
}
|
||||
|
||||
Text {
|
||||
text:qsTr("There are no materials in this project.<br>Select '<b>+</b>' to create one.")
|
||||
visible: materialBrowserModel.isEmpty && searchBox.isEmpty()
|
||||
textFormat: Text.RichText
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
font.pixelSize: StudioTheme.Values.mediumFontSize
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.WordWrap
|
||||
width: root.width
|
||||
}
|
||||
}
|
||||
|
||||
Section {
|
||||
width: root.width
|
||||
caption: qsTr("Material Library")
|
||||
addTopPadding: noMatchText.visible
|
||||
visible: materialBrowserBundleModel.matBundleExists
|
||||
|
||||
Column {
|
||||
Repeater {
|
||||
model: materialBrowserBundleModel
|
||||
|
||||
delegate: Section {
|
||||
width: root.width
|
||||
caption: bundleCategory
|
||||
addTopPadding: false
|
||||
sectionBackgroundColor: "transparent"
|
||||
visible: bundleCategoryVisible
|
||||
|
||||
Grid {
|
||||
width: scrollView.width
|
||||
leftPadding: 5
|
||||
rightPadding: 5
|
||||
bottomPadding: 5
|
||||
columns: root.width / root.cellWidth
|
||||
|
||||
Repeater {
|
||||
model: bundleMaterialsModel
|
||||
|
||||
delegate: BundleMaterialItem {
|
||||
width: root.cellWidth
|
||||
height: root.cellHeight
|
||||
|
||||
onShowContextMenu: {
|
||||
if (searchBox.isEmpty()) {
|
||||
root.currentBundleMaterial = modelData
|
||||
cxtMenuBundle.popup()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
id: noMatchText
|
||||
text: qsTr("No match found.");
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
font.pixelSize: StudioTheme.Values.baseFontSize
|
||||
leftPadding: 10
|
||||
visible: materialBrowserBundleModel.isEmpty && !searchBox.isEmpty() && !materialBrowserModel.hasMaterialRoot
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -337,6 +337,9 @@ extend_qtc_plugin(QmlDesigner
|
||||
materialbrowserwidget.cpp materialbrowserwidget.h
|
||||
materialbrowsermodel.cpp materialbrowsermodel.h
|
||||
bundleimporter.cpp bundleimporter.h
|
||||
materialbrowserbundlemodel.cpp materialbrowserbundlemodel.h
|
||||
bundlematerial.cpp bundlematerial.h
|
||||
bundlematerialcategory.cpp bundlematerialcategory.h
|
||||
)
|
||||
|
||||
extend_qtc_plugin(QmlDesigner
|
||||
|
@@ -312,6 +312,8 @@ void Edit3DView::nodeAtPosReady(const ModelNode &modelNode, const QVector3D &pos
|
||||
assignMaterialTo3dModel(modelNode, m_droppedMaterial);
|
||||
});
|
||||
}
|
||||
} else if (m_nodeAtPosReqType == NodeAtPosReqType::BundleMaterialDrop) {
|
||||
emitCustomNotification("drop_bundle_material", {modelNode}); // To MaterialBrowserView
|
||||
}
|
||||
m_nodeAtPosReqType = NodeAtPosReqType::None;
|
||||
}
|
||||
@@ -713,4 +715,10 @@ void Edit3DView::dropMaterial(const ModelNode &matNode, const QPointF &pos)
|
||||
QmlDesignerPlugin::instance()->viewManager().nodeInstanceView()->view3DAction({View3DActionCommand::GetNodeAtPos, pos});
|
||||
}
|
||||
|
||||
void Edit3DView::dropBundleMaterial(const QPointF &pos)
|
||||
{
|
||||
m_nodeAtPosReqType = NodeAtPosReqType::BundleMaterialDrop;
|
||||
QmlDesignerPlugin::instance()->viewManager().nodeInstanceView()->view3DAction({View3DActionCommand::GetNodeAtPos, pos});
|
||||
}
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
@@ -80,12 +80,14 @@ public:
|
||||
void addQuick3DImport();
|
||||
void startContextMenu(const QPoint &pos);
|
||||
void dropMaterial(const ModelNode &matNode, const QPointF &pos);
|
||||
void dropBundleMaterial(const QPointF &pos);
|
||||
|
||||
private slots:
|
||||
void onEntriesChanged();
|
||||
|
||||
private:
|
||||
enum class NodeAtPosReqType {
|
||||
BundleMaterialDrop,
|
||||
MaterialDrop,
|
||||
ContextMenu,
|
||||
None
|
||||
|
@@ -331,7 +331,8 @@ void Edit3DWidget::dragEnterEvent(QDragEnterEvent *dragEnterEvent)
|
||||
const DesignerActionManager &actionManager = QmlDesignerPlugin::instance()
|
||||
->viewManager().designerActionManager();
|
||||
if (actionManager.externalDragHasSupportedAssets(dragEnterEvent->mimeData())
|
||||
|| dragEnterEvent->mimeData()->hasFormat(Constants::MIME_TYPE_MATERIAL)) {
|
||||
|| dragEnterEvent->mimeData()->hasFormat(Constants::MIME_TYPE_MATERIAL)
|
||||
|| dragEnterEvent->mimeData()->hasFormat(Constants::MIME_TYPE_BUNDLE_MATERIAL)) {
|
||||
dragEnterEvent->acceptProposedAction();
|
||||
}
|
||||
}
|
||||
@@ -351,6 +352,12 @@ void Edit3DWidget::dropEvent(QDropEvent *dropEvent)
|
||||
return;
|
||||
}
|
||||
|
||||
// handle dropping bundle materials
|
||||
if (dropEvent->mimeData()->hasFormat(Constants::MIME_TYPE_BUNDLE_MATERIAL)) {
|
||||
m_view->dropBundleMaterial(dropEvent->position());
|
||||
return;
|
||||
}
|
||||
|
||||
// handle dropping external assets
|
||||
const DesignerActionManager &actionManager = QmlDesignerPlugin::instance()
|
||||
->viewManager().designerActionManager();
|
||||
|
@@ -107,7 +107,7 @@ QString BundleImporter::importComponent(const QString &qmlFile,
|
||||
qmldirContent.append('\n');
|
||||
}
|
||||
|
||||
FilePath qmlSourceFile = FilePath::fromString(qmlFile);
|
||||
FilePath qmlSourceFile = bundleImportPath.resolvePath(FilePath::fromString(qmlFile));
|
||||
const bool qmlFileExists = qmlSourceFile.exists();
|
||||
const QString qmlType = qmlSourceFile.baseName();
|
||||
m_pendingTypes.append(QStringLiteral("%1.%2")
|
||||
|
@@ -0,0 +1,67 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2022 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "bundlematerial.h"
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
BundleMaterial::BundleMaterial(QObject *parent,
|
||||
const QString &name,
|
||||
const QString &qml,
|
||||
const QUrl &icon,
|
||||
const QStringList &files)
|
||||
: QObject(parent), m_name(name), m_qml(qml), m_icon(icon), m_files(files) {}
|
||||
|
||||
bool BundleMaterial::filter(const QString &searchText)
|
||||
{
|
||||
if (m_visible != m_name.contains(searchText, Qt::CaseInsensitive)) {
|
||||
m_visible = !m_visible;
|
||||
emit materialVisibleChanged();
|
||||
}
|
||||
|
||||
return m_visible;
|
||||
}
|
||||
|
||||
QUrl BundleMaterial::icon() const
|
||||
{
|
||||
return m_icon;
|
||||
}
|
||||
|
||||
QString BundleMaterial::qml() const
|
||||
{
|
||||
return m_qml;
|
||||
}
|
||||
|
||||
QStringList BundleMaterial::files() const
|
||||
{
|
||||
return m_files;
|
||||
}
|
||||
|
||||
bool BundleMaterial::visible() const
|
||||
{
|
||||
return m_visible;
|
||||
}
|
||||
|
||||
} // namespace QmlDesigner
|
@@ -0,0 +1,68 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2022 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QDataStream>
|
||||
#include <QObject>
|
||||
#include <QUrl>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
class BundleMaterial : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QString bundleMaterialName MEMBER m_name CONSTANT)
|
||||
Q_PROPERTY(QUrl bundleMaterialIcon MEMBER m_icon CONSTANT)
|
||||
Q_PROPERTY(bool bundleMaterialVisible MEMBER m_visible NOTIFY materialVisibleChanged)
|
||||
|
||||
public:
|
||||
BundleMaterial(QObject *parent,
|
||||
const QString &name,
|
||||
const QString &qml,
|
||||
const QUrl &icon,
|
||||
const QStringList &files);
|
||||
|
||||
bool filter(const QString &searchText);
|
||||
|
||||
QUrl icon() const;
|
||||
QString qml() const;
|
||||
QStringList files() const;
|
||||
bool visible() const;
|
||||
|
||||
signals:
|
||||
void materialVisibleChanged();
|
||||
|
||||
private:
|
||||
QString m_name;
|
||||
QString m_qml;
|
||||
QUrl m_icon;
|
||||
QStringList m_files;
|
||||
|
||||
bool m_visible = true;
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner
|
@@ -0,0 +1,70 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2022 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "bundlematerialcategory.h"
|
||||
|
||||
#include "bundlematerial.h"
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
BundleMaterialCategory::BundleMaterialCategory(QObject *parent, const QString &name)
|
||||
: QObject(parent), m_name(name) {}
|
||||
|
||||
void BundleMaterialCategory::addBundleMaterial(BundleMaterial *bundleMat)
|
||||
{
|
||||
m_categoryMaterials.append(bundleMat);
|
||||
}
|
||||
|
||||
bool BundleMaterialCategory::filter(const QString &searchText)
|
||||
{
|
||||
bool visible = false;
|
||||
for (BundleMaterial *mat : std::as_const(m_categoryMaterials))
|
||||
visible |= mat->filter(searchText);
|
||||
|
||||
if (visible != m_visible) {
|
||||
m_visible = visible;
|
||||
emit categoryVisibleChanged();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QString BundleMaterialCategory::name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
bool BundleMaterialCategory::visible() const
|
||||
{
|
||||
return m_visible;
|
||||
}
|
||||
|
||||
QList<BundleMaterial *> BundleMaterialCategory::categoryMaterials() const
|
||||
{
|
||||
return m_categoryMaterials;
|
||||
}
|
||||
|
||||
} // namespace QmlDesigner
|
@@ -0,0 +1,61 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2022 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
class BundleMaterial;
|
||||
|
||||
class BundleMaterialCategory : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QString categoryName MEMBER m_name CONSTANT)
|
||||
Q_PROPERTY(bool categoryVisible MEMBER m_visible NOTIFY categoryVisibleChanged)
|
||||
|
||||
public:
|
||||
BundleMaterialCategory(QObject *parent, const QString &name);
|
||||
|
||||
void addBundleMaterial(BundleMaterial *bundleMat);
|
||||
bool filter(const QString &searchText);
|
||||
|
||||
QString name() const;
|
||||
bool visible() const;
|
||||
QList<BundleMaterial *> categoryMaterials() const;
|
||||
|
||||
signals:
|
||||
void categoryVisibleChanged();
|
||||
|
||||
private:
|
||||
QString m_name;
|
||||
bool m_visible = true;
|
||||
|
||||
QList<BundleMaterial *> m_categoryMaterials;
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner
|
@@ -0,0 +1,219 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2022 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "materialbrowserbundlemodel.h"
|
||||
|
||||
#include "bundleimporter.h"
|
||||
#include "bundlematerial.h"
|
||||
#include "bundlematerialcategory.h"
|
||||
#include "utils/qtcassert.h"
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QUrl>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
MaterialBrowserBundleModel::MaterialBrowserBundleModel(QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
{
|
||||
loadMaterialBundle();
|
||||
}
|
||||
|
||||
int MaterialBrowserBundleModel::rowCount(const QModelIndex &) const
|
||||
{
|
||||
return m_bundleCategories.size();
|
||||
}
|
||||
|
||||
QVariant MaterialBrowserBundleModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
QTC_ASSERT(index.isValid() && index.row() < m_bundleCategories.count(), return {});
|
||||
QTC_ASSERT(roleNames().contains(role), return {});
|
||||
|
||||
QByteArray roleName = roleNames().value(role);
|
||||
if (roleName == "bundleCategory")
|
||||
return m_bundleCategories.at(index.row())->name();
|
||||
|
||||
if (roleName == "bundleCategoryVisible")
|
||||
return m_bundleCategories.at(index.row())->visible();
|
||||
|
||||
if (roleName == "bundleMaterialsModel")
|
||||
return QVariant::fromValue(m_bundleCategories.at(index.row())->categoryMaterials());
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
bool MaterialBrowserBundleModel::isValidIndex(int idx) const
|
||||
{
|
||||
return idx > -1 && idx < rowCount();
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> MaterialBrowserBundleModel::roleNames() const
|
||||
{
|
||||
static const QHash<int, QByteArray> roles {
|
||||
{Qt::UserRole + 1, "bundleCategory"},
|
||||
{Qt::UserRole + 2, "bundleCategoryVisible"},
|
||||
{Qt::UserRole + 3, "bundleMaterialsModel"}
|
||||
};
|
||||
return roles;
|
||||
}
|
||||
|
||||
void MaterialBrowserBundleModel::loadMaterialBundle()
|
||||
{
|
||||
if (m_matBundleExists)
|
||||
return;
|
||||
|
||||
QString bundlePath = qEnvironmentVariable("MATERIAL_BUNDLE_PATH");
|
||||
|
||||
if (bundlePath.isEmpty())
|
||||
return;
|
||||
|
||||
QString matBundlePath = bundlePath + "material_bundle.json";
|
||||
|
||||
if (m_matBundleObj.isEmpty()) {
|
||||
QFile matPropsFile(matBundlePath);
|
||||
|
||||
if (!matPropsFile.open(QIODevice::ReadOnly)) {
|
||||
qWarning("Couldn't open material_bundle.json");
|
||||
return;
|
||||
}
|
||||
|
||||
QJsonDocument matBundleJsonDoc = QJsonDocument::fromJson(matPropsFile.readAll());
|
||||
if (matBundleJsonDoc.isNull()) {
|
||||
qWarning("Invalid material_bundle.json file");
|
||||
return;
|
||||
} else {
|
||||
m_matBundleObj = matBundleJsonDoc.object();
|
||||
}
|
||||
}
|
||||
|
||||
m_matBundleExists = true;
|
||||
|
||||
const QJsonObject catsObj = m_matBundleObj.value("categories").toObject();
|
||||
const QStringList categories = catsObj.keys();
|
||||
for (const QString &cat : categories) {
|
||||
auto category = new BundleMaterialCategory(this, cat);
|
||||
|
||||
const QJsonObject matsObj = catsObj.value(cat).toObject();
|
||||
const QStringList mats = matsObj.keys();
|
||||
for (const QString &mat : mats) {
|
||||
const QJsonObject matObj = matsObj.value(mat).toObject();
|
||||
|
||||
QStringList files;
|
||||
const QJsonArray assetsArr = matObj.value("files").toArray();
|
||||
for (const QJsonValueRef &asset : assetsArr)
|
||||
files.append(asset.toString());
|
||||
|
||||
auto bundleMat = new BundleMaterial(category, mat, matObj.value("qml").toString(),
|
||||
QUrl::fromLocalFile(bundlePath + matObj.value("icon").toString()), files);
|
||||
|
||||
category->addBundleMaterial(bundleMat);
|
||||
}
|
||||
m_bundleCategories.append(category);
|
||||
}
|
||||
|
||||
QStringList sharedFiles;
|
||||
const QJsonArray sharedFilesArr = m_matBundleObj.value("sharedFiles").toArray();
|
||||
for (const QJsonValueRef &file : sharedFilesArr)
|
||||
sharedFiles.append(file.toString());
|
||||
|
||||
m_importer = new Internal::BundleImporter(bundlePath, "MaterialBundle", sharedFiles);
|
||||
connect(m_importer, &Internal::BundleImporter::importFinished, this, [&](const QmlDesigner::NodeMetaInfo &metaInfo) {
|
||||
if (metaInfo.isValid())
|
||||
emit addBundleMaterialToProjectRequested(metaInfo);
|
||||
});
|
||||
}
|
||||
|
||||
bool MaterialBrowserBundleModel::hasQuick3DImport() const
|
||||
{
|
||||
return m_hasQuick3DImport;
|
||||
}
|
||||
|
||||
void MaterialBrowserBundleModel::setHasQuick3DImport(bool b)
|
||||
{
|
||||
if (b == m_hasQuick3DImport)
|
||||
return;
|
||||
|
||||
m_hasQuick3DImport = b;
|
||||
emit hasQuick3DImportChanged();
|
||||
}
|
||||
|
||||
bool MaterialBrowserBundleModel::hasMaterialRoot() const
|
||||
{
|
||||
return m_hasMaterialRoot;
|
||||
}
|
||||
|
||||
void MaterialBrowserBundleModel::setHasMaterialRoot(bool b)
|
||||
{
|
||||
if (m_hasMaterialRoot == b)
|
||||
return;
|
||||
|
||||
m_hasMaterialRoot = b;
|
||||
emit hasMaterialRootChanged();
|
||||
}
|
||||
|
||||
void MaterialBrowserBundleModel::setSearchText(const QString &searchText)
|
||||
{
|
||||
QString lowerSearchText = searchText.toLower();
|
||||
|
||||
if (m_searchText == lowerSearchText)
|
||||
return;
|
||||
|
||||
m_searchText = lowerSearchText;
|
||||
|
||||
bool anyCatVisible = false;
|
||||
bool catVisibilityChanged = false;
|
||||
|
||||
for (BundleMaterialCategory *cat : std::as_const(m_bundleCategories)) {
|
||||
catVisibilityChanged |= cat->filter(m_searchText);
|
||||
anyCatVisible |= cat->visible();
|
||||
}
|
||||
|
||||
if (anyCatVisible == m_isEmpty) {
|
||||
m_isEmpty = !anyCatVisible;
|
||||
emit isEmptyChanged();
|
||||
}
|
||||
|
||||
if (catVisibilityChanged)
|
||||
resetModel();
|
||||
}
|
||||
|
||||
void MaterialBrowserBundleModel::resetModel()
|
||||
{
|
||||
beginResetModel();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void MaterialBrowserBundleModel::applyToSelected(BundleMaterial *mat, bool add)
|
||||
{
|
||||
emit applyToSelectedTriggered(mat, add);
|
||||
}
|
||||
|
||||
void MaterialBrowserBundleModel::addMaterial(BundleMaterial *mat)
|
||||
{
|
||||
m_importer->importComponent(mat->qml(), mat->files());
|
||||
}
|
||||
|
||||
} // namespace QmlDesigner
|
@@ -0,0 +1,97 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2022 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <modelnode.h>
|
||||
#include <qmlobjectnode.h>
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QJsonObject>
|
||||
#include <QObject>
|
||||
#include <QPointer>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
class BundleMaterial;
|
||||
class BundleMaterialCategory;
|
||||
|
||||
namespace Internal {
|
||||
class BundleImporter;
|
||||
}
|
||||
|
||||
class MaterialBrowserBundleModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(bool matBundleExists MEMBER m_matBundleExists CONSTANT)
|
||||
Q_PROPERTY(bool isEmpty MEMBER m_isEmpty NOTIFY isEmptyChanged)
|
||||
Q_PROPERTY(bool hasQuick3DImport READ hasQuick3DImport WRITE setHasQuick3DImport NOTIFY hasQuick3DImportChanged)
|
||||
Q_PROPERTY(bool hasMaterialRoot READ hasMaterialRoot WRITE setHasMaterialRoot NOTIFY hasMaterialRootChanged)
|
||||
|
||||
public:
|
||||
MaterialBrowserBundleModel(QObject *parent = nullptr);
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
void setSearchText(const QString &searchText);
|
||||
|
||||
bool hasQuick3DImport() const;
|
||||
void setHasQuick3DImport(bool b);
|
||||
|
||||
bool hasMaterialRoot() const;
|
||||
void setHasMaterialRoot(bool b);
|
||||
|
||||
void resetModel();
|
||||
|
||||
Q_INVOKABLE void applyToSelected(QmlDesigner::BundleMaterial *mat, bool add = false);
|
||||
Q_INVOKABLE void addMaterial(QmlDesigner::BundleMaterial *mat);
|
||||
|
||||
signals:
|
||||
void isEmptyChanged();
|
||||
void hasQuick3DImportChanged();
|
||||
void hasMaterialRootChanged();
|
||||
void materialVisibleChanged();
|
||||
void applyToSelectedTriggered(QmlDesigner::BundleMaterial *mat, bool add = false);
|
||||
void addBundleMaterialToProjectRequested(const QmlDesigner::NodeMetaInfo &metaInfo);
|
||||
|
||||
private:
|
||||
void loadMaterialBundle();
|
||||
bool isValidIndex(int idx) const;
|
||||
|
||||
QString m_searchText;
|
||||
QList<BundleMaterialCategory *> m_bundleCategories;
|
||||
QJsonObject m_matBundleObj;
|
||||
Internal::BundleImporter *m_importer = nullptr;
|
||||
|
||||
bool m_isEmpty = true;
|
||||
bool m_hasQuick3DImport = false;
|
||||
bool m_hasMaterialRoot = false;
|
||||
bool m_matBundleExists = false;
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner
|
@@ -235,6 +235,8 @@ void MaterialBrowserModel::setSearchText(const QString &searchText)
|
||||
isEmpty = !isValidIndex(m_selectedIndex + inc)
|
||||
&& !isValidIndex(m_selectedIndex - inc);
|
||||
}
|
||||
if (!isMaterialVisible(m_selectedIndex)) // handles the case of a single material
|
||||
isEmpty = true;
|
||||
}
|
||||
|
||||
if (isEmpty != m_isEmpty) {
|
||||
|
@@ -26,8 +26,10 @@
|
||||
#include "materialbrowserview.h"
|
||||
|
||||
#include "bindingproperty.h"
|
||||
#include "bundlematerial.h"
|
||||
#include "materialbrowserwidget.h"
|
||||
#include "materialbrowsermodel.h"
|
||||
#include "materialbrowserbundlemodel.h"
|
||||
#include "nodeabstractproperty.h"
|
||||
#include "nodemetainfo.h"
|
||||
#include "qmlobjectnode.h"
|
||||
@@ -36,9 +38,12 @@
|
||||
#include <coreplugin/icore.h>
|
||||
#include <designmodecontext.h>
|
||||
#include <nodeinstanceview.h>
|
||||
#include <nodelistproperty.h>
|
||||
#include <qmldesignerconstants.h>
|
||||
|
||||
#include <QQuickItem>
|
||||
#include <QRegularExpression>
|
||||
#include <QTimer>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
@@ -115,6 +120,80 @@ WidgetInfo MaterialBrowserView::widgetInfo()
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
connect(m_widget, &MaterialBrowserWidget::bundleMaterialDragStarted, this,
|
||||
[&] (QmlDesigner::BundleMaterial *bundleMat) {
|
||||
m_draggedBundleMaterial = bundleMat;
|
||||
});
|
||||
|
||||
MaterialBrowserBundleModel *matBrowserBundleModel = m_widget->materialBrowserBundleModel().data();
|
||||
|
||||
connect(matBrowserBundleModel, &MaterialBrowserBundleModel::applyToSelectedTriggered, this,
|
||||
[&] (BundleMaterial *material, bool add) {
|
||||
if (!m_selectedModel.isValid())
|
||||
return;
|
||||
|
||||
m_bundleMaterialDropTarget = m_selectedModel;
|
||||
m_bundleMaterialAddToSelected = add;
|
||||
m_widget->materialBrowserBundleModel()->addMaterial(material);
|
||||
});
|
||||
|
||||
connect(matBrowserBundleModel, &MaterialBrowserBundleModel::addBundleMaterialToProjectRequested, this,
|
||||
[&] (const QmlDesigner::NodeMetaInfo &metaInfo) {
|
||||
ModelNode matLib = materialLibraryNode();
|
||||
if (!matLib.isValid())
|
||||
return;
|
||||
|
||||
executeInTransaction("MaterialBrowserView::widgetInfo", [&] {
|
||||
ModelNode newMatNode = createModelNode(metaInfo.typeName(), metaInfo.majorVersion(),
|
||||
metaInfo.minorVersion());
|
||||
matLib.defaultNodeListProperty().reparentHere(newMatNode);
|
||||
|
||||
static QRegularExpression rgx("([A-Z])([a-z]*)");
|
||||
QString newName = QString::fromLatin1(metaInfo.simplifiedTypeName()).replace(rgx, " \\1\\2").trimmed();
|
||||
QString newId = model()->generateIdFromName(newName, "material");
|
||||
newMatNode.setIdWithRefactoring(newId);
|
||||
|
||||
VariantProperty objNameProp = newMatNode.variantProperty("objectName");
|
||||
objNameProp.setValue(newName);
|
||||
|
||||
if (m_bundleMaterialDropTarget.isValid()) {
|
||||
QmlObjectNode qmlObjNode(m_bundleMaterialDropTarget);
|
||||
if (m_bundleMaterialAddToSelected) {
|
||||
// TODO: unify this logic as it exist elsewhere also
|
||||
auto expToList = [](const QString &exp) {
|
||||
QString copy = exp;
|
||||
copy = copy.remove("[").remove("]");
|
||||
|
||||
QStringList tmp = copy.split(',', Qt::SkipEmptyParts);
|
||||
for (QString &str : tmp)
|
||||
str = str.trimmed();
|
||||
|
||||
return tmp;
|
||||
};
|
||||
|
||||
auto listToExp = [](QStringList &stringList) {
|
||||
if (stringList.size() > 1)
|
||||
return QString("[" + stringList.join(",") + "]");
|
||||
|
||||
if (stringList.size() == 1)
|
||||
return stringList.first();
|
||||
|
||||
return QString();
|
||||
};
|
||||
QStringList matList = expToList(qmlObjNode.expression("materials"));
|
||||
matList.append(newMatNode.id());
|
||||
QString updatedExp = listToExp(matList);
|
||||
qmlObjNode.setBindingProperty("materials", updatedExp);
|
||||
} else {
|
||||
qmlObjNode.setBindingProperty("materials", newMatNode.id());
|
||||
}
|
||||
m_bundleMaterialDropTarget = {};
|
||||
}
|
||||
|
||||
m_bundleMaterialAddToSelected = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return createWidgetInfo(m_widget.data(),
|
||||
@@ -185,24 +264,24 @@ void MaterialBrowserView::selectedNodesChanged(const QList<ModelNode> &selectedN
|
||||
{
|
||||
Q_UNUSED(lastSelectedNodeList)
|
||||
|
||||
ModelNode selectedModel;
|
||||
m_selectedModel = {};
|
||||
|
||||
for (const ModelNode &node : selectedNodeList) {
|
||||
if (node.isSubclassOf("QtQuick3D.Model")) {
|
||||
selectedModel = node;
|
||||
m_selectedModel = node;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_widget->materialBrowserModel()->setHasModelSelection(selectedModel.isValid());
|
||||
m_widget->materialBrowserModel()->setHasModelSelection(m_selectedModel.isValid());
|
||||
|
||||
if (!m_autoSelectModelMaterial)
|
||||
return;
|
||||
|
||||
if (selectedNodeList.size() > 1 || !selectedModel.isValid())
|
||||
if (selectedNodeList.size() > 1 || !m_selectedModel.isValid())
|
||||
return;
|
||||
|
||||
QmlObjectNode qmlObjNode(selectedModel);
|
||||
QmlObjectNode qmlObjNode(m_selectedModel);
|
||||
QString matExp = qmlObjNode.expression("materials");
|
||||
if (matExp.isEmpty())
|
||||
return;
|
||||
@@ -339,6 +418,10 @@ void MaterialBrowserView::customNotification(const AbstractView *view, const QSt
|
||||
});
|
||||
} else if (identifier == "delete_selected_material") {
|
||||
m_widget->materialBrowserModel()->deleteSelectedMaterial();
|
||||
} else if (identifier == "drop_bundle_material") {
|
||||
m_bundleMaterialDropTarget = nodeList.first();
|
||||
m_widget->materialBrowserBundleModel()->addMaterial(m_draggedBundleMaterial);
|
||||
m_draggedBundleMaterial = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -31,6 +31,7 @@
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
class BundleMaterial;
|
||||
class MaterialBrowserWidget;
|
||||
|
||||
class MaterialBrowserView : public AbstractView
|
||||
@@ -65,13 +66,17 @@ public:
|
||||
private:
|
||||
void refreshModel(bool updateImages);
|
||||
bool isMaterial(const ModelNode &node) const;
|
||||
void loadPropertyGroups();
|
||||
|
||||
QPointer<MaterialBrowserWidget> m_widget;
|
||||
ModelNode m_bundleMaterialDropTarget;
|
||||
ModelNode m_selectedModel; // first selected 3D model node
|
||||
BundleMaterial *m_draggedBundleMaterial = nullptr;
|
||||
bool m_bundleMaterialAddToSelected = false;
|
||||
bool m_hasQuick3DImport = false;
|
||||
bool m_autoSelectModelMaterial = false; // TODO: wire this to some action
|
||||
bool m_puppetResetPending = false;
|
||||
bool m_propertyGroupsLoaded = false;
|
||||
void loadPropertyGroups();
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
@@ -24,25 +24,29 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "materialbrowserwidget.h"
|
||||
|
||||
#include "bundlematerial.h"
|
||||
#include "materialbrowserbundlemodel.h"
|
||||
#include "materialbrowsermodel.h"
|
||||
#include "materialbrowserview.h"
|
||||
|
||||
#include <theme.h>
|
||||
|
||||
#include <designeractionmanager.h>
|
||||
#include <designermcumanager.h>
|
||||
#include <documentmanager.h>
|
||||
#include <qmldesignerconstants.h>
|
||||
#include <qmldesignerplugin.h>
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/stylehelper.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <theme.h>
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/stylehelper.h>
|
||||
|
||||
#include <QImageReader>
|
||||
#include <QMenu>
|
||||
#include <QMimeData>
|
||||
#include <QMouseEvent>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QQmlContext>
|
||||
#include <QQmlEngine>
|
||||
#include <QQuickImageProvider>
|
||||
@@ -113,7 +117,7 @@ bool MaterialBrowserWidget::eventFilter(QObject *obj, QEvent *event)
|
||||
|
||||
if (m_materialToDrag.isValid()) {
|
||||
QMouseEvent *me = static_cast<QMouseEvent *>(event);
|
||||
if ((me->globalPos() - m_dragStartPoint).manhattanLength() > 10) {
|
||||
if ((me->globalPos() - m_dragStartPoint).manhattanLength() > 20) {
|
||||
QByteArray data;
|
||||
QMimeData *mimeData = new QMimeData;
|
||||
QDataStream stream(&data, QIODevice::WriteOnly);
|
||||
@@ -125,6 +129,17 @@ bool MaterialBrowserWidget::eventFilter(QObject *obj, QEvent *event)
|
||||
QString::number(m_materialToDrag.internalId()), nullptr, {128, 128}));
|
||||
m_materialToDrag = {};
|
||||
}
|
||||
} else if (m_bundleMaterialToDrag != nullptr) {
|
||||
QMouseEvent *me = static_cast<QMouseEvent *>(event);
|
||||
if ((me->globalPos() - m_dragStartPoint).manhattanLength() > 20) {
|
||||
QMimeData *mimeData = new QMimeData;
|
||||
mimeData->setData(Constants::MIME_TYPE_BUNDLE_MATERIAL, {});
|
||||
mimeData->removeFormat("text/plain");
|
||||
|
||||
model->startDrag(mimeData, m_bundleMaterialToDrag->icon().toLocalFile());
|
||||
emit bundleMaterialDragStarted(m_bundleMaterialToDrag);
|
||||
m_bundleMaterialToDrag = {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,6 +149,7 @@ bool MaterialBrowserWidget::eventFilter(QObject *obj, QEvent *event)
|
||||
MaterialBrowserWidget::MaterialBrowserWidget(MaterialBrowserView *view)
|
||||
: m_materialBrowserView(view)
|
||||
, m_materialBrowserModel(new MaterialBrowserModel(this))
|
||||
, m_materialBrowserBundleModel(new MaterialBrowserBundleModel(this))
|
||||
, m_quickWidget(new QQuickWidget(this))
|
||||
, m_previewImageProvider(new PreviewImageProvider())
|
||||
{
|
||||
@@ -152,6 +168,7 @@ MaterialBrowserWidget::MaterialBrowserWidget(MaterialBrowserView *view)
|
||||
m_quickWidget->rootContext()->setContextProperties({
|
||||
{"rootView", QVariant::fromValue(this)},
|
||||
{"materialBrowserModel", QVariant::fromValue(m_materialBrowserModel.data())},
|
||||
{"materialBrowserBundleModel", QVariant::fromValue(m_materialBrowserBundleModel.data())},
|
||||
});
|
||||
|
||||
m_quickWidget->engine()->addImageProvider("materialBrowser", m_previewImageProvider);
|
||||
@@ -211,6 +228,12 @@ void MaterialBrowserWidget::startDragMaterial(int index, const QPointF &mousePos
|
||||
m_dragStartPoint = mousePos.toPoint();
|
||||
}
|
||||
|
||||
void MaterialBrowserWidget::startDragBundleMaterial(QmlDesigner::BundleMaterial *bundleMat, const QPointF &mousePos)
|
||||
{
|
||||
m_bundleMaterialToDrag = bundleMat;
|
||||
m_dragStartPoint = mousePos.toPoint();
|
||||
}
|
||||
|
||||
QString MaterialBrowserWidget::qmlSourcesPath()
|
||||
{
|
||||
#ifdef SHARE_QML_PATH
|
||||
@@ -238,6 +261,7 @@ void MaterialBrowserWidget::reloadQmlSource()
|
||||
void MaterialBrowserWidget::updateSearch()
|
||||
{
|
||||
m_materialBrowserModel->setSearchText(m_filterText);
|
||||
m_materialBrowserBundleModel->setSearchText(m_filterText);
|
||||
m_quickWidget->update();
|
||||
}
|
||||
|
||||
@@ -251,4 +275,10 @@ QPointer<MaterialBrowserModel> MaterialBrowserWidget::materialBrowserModel() con
|
||||
return m_materialBrowserModel;
|
||||
}
|
||||
|
||||
QPointer<MaterialBrowserBundleModel> MaterialBrowserWidget::materialBrowserBundleModel() const
|
||||
{
|
||||
return m_materialBrowserBundleModel;
|
||||
}
|
||||
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
@@ -33,6 +33,7 @@
|
||||
|
||||
#include <QFileIconProvider>
|
||||
#include <QFrame>
|
||||
#include <QJsonObject>
|
||||
#include <QPointF>
|
||||
#include <QQmlPropertyMap>
|
||||
#include <QQuickWidget>
|
||||
@@ -48,8 +49,10 @@ QT_END_NAMESPACE
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
class BundleMaterial;
|
||||
class MaterialBrowserView;
|
||||
class MaterialBrowserModel;
|
||||
class MaterialBrowserBundleModel;
|
||||
class PreviewImageProvider;
|
||||
|
||||
class MaterialBrowserWidget : public QFrame
|
||||
@@ -67,13 +70,18 @@ public:
|
||||
void clearSearchFilter();
|
||||
|
||||
QPointer<MaterialBrowserModel> materialBrowserModel() const;
|
||||
QPointer<MaterialBrowserBundleModel> materialBrowserBundleModel() const;
|
||||
void updateMaterialPreview(const ModelNode &node, const QPixmap &pixmap);
|
||||
|
||||
Q_INVOKABLE void handleSearchfilterChanged(const QString &filterText);
|
||||
Q_INVOKABLE void startDragMaterial(int index, const QPointF &mousePos);
|
||||
Q_INVOKABLE void startDragBundleMaterial(QmlDesigner::BundleMaterial *bundleMat, const QPointF &mousePos);
|
||||
|
||||
QQuickWidget *quickWidget() const;
|
||||
|
||||
signals:
|
||||
void bundleMaterialDragStarted(QmlDesigner::BundleMaterial *bundleMat);
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
|
||||
@@ -83,6 +91,7 @@ private:
|
||||
|
||||
QPointer<MaterialBrowserView> m_materialBrowserView;
|
||||
QPointer<MaterialBrowserModel> m_materialBrowserModel;
|
||||
QPointer<MaterialBrowserBundleModel> m_materialBrowserBundleModel;
|
||||
QScopedPointer<QQuickWidget> m_quickWidget;
|
||||
|
||||
QShortcut *m_qmlSourceUpdateShortcut = nullptr;
|
||||
@@ -92,6 +101,7 @@ private:
|
||||
QString m_filterText;
|
||||
|
||||
ModelNode m_materialToDrag;
|
||||
BundleMaterial *m_bundleMaterialToDrag = nullptr;
|
||||
QPoint m_dragStartPoint;
|
||||
};
|
||||
|
||||
|
@@ -96,6 +96,7 @@ const char MATERIAL_LIB_ID[] = "__materialLibrary__";
|
||||
const char MIME_TYPE_ITEM_LIBRARY_INFO[] = "application/vnd.qtdesignstudio.itemlibraryinfo";
|
||||
const char MIME_TYPE_ASSETS[] = "application/vnd.qtdesignstudio.assets";
|
||||
const char MIME_TYPE_MATERIAL[] = "application/vnd.qtdesignstudio.material";
|
||||
const char MIME_TYPE_BUNDLE_MATERIAL[] = "application/vnd.qtdesignstudio.bundlematerial";
|
||||
const char MIME_TYPE_ASSET_IMAGE[] = "application/vnd.qtdesignstudio.asset.image";
|
||||
const char MIME_TYPE_ASSET_FONT[] = "application/vnd.qtdesignstudio.asset.font";
|
||||
const char MIME_TYPE_ASSET_SHADER[] = "application/vnd.qtdesignstudio.asset.shader";
|
||||
|
@@ -687,6 +687,12 @@ Project {
|
||||
"itemlibrary/itemlibraryiconimageprovider.h",
|
||||
"materialbrowser/materialbrowsermodel.cpp",
|
||||
"materialbrowser/materialbrowsermodel.h",
|
||||
"materialbrowser/materialbrowserbundlemodel.cpp",
|
||||
"materialbrowser/materialbrowserbundlemodel.h",
|
||||
"materialbrowser/bundlematerial.cpp",
|
||||
"materialbrowser/bundlematerial.h",
|
||||
"materialbrowser/bundlematerialcategory.cpp",
|
||||
"materialbrowser/bundlematerialcategory.h",
|
||||
"materialbrowser/materialbrowserview.cpp",
|
||||
"materialbrowser/materialbrowserview.h",
|
||||
"materialbrowser/materialbrowserwidget.cpp",
|
||||
|
Reference in New Issue
Block a user