QmlDesigner: Enable content lib user 3D context menu

Also some relevant tweaks.

Change-Id: I7bace9ce6bd7b45951cc18f7175b4646251196f0
Reviewed-by: Ali Kianian <ali.kianian@qt.io>
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
This commit is contained in:
Mahmoud Badri
2024-05-11 00:04:11 +03:00
parent e4bdb92d0f
commit 4f23a553d1
13 changed files with 184 additions and 121 deletions

View File

@@ -1,43 +1,50 @@
// Copyright (C) 2022 The Qt Company Ltd. // Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick 2.15 import QtQuick
import HelperWidgets 2.0 import StudioControls as StudioControls
import StudioControls 1.0 as StudioControls import StudioTheme as StudioTheme
import StudioTheme 1.0 as StudioTheme import ContentLibraryBackend
StudioControls.Menu { StudioControls.Menu {
id: root id: root
property var targetMaterial: null property var targetItem: null
property bool hasModelSelection: false property bool enableRemove: false // true: adds an option to remove targetItem
property bool importerRunning: false
property bool enableRemove: false // true: adds an option to remove targetMaterial
readonly property bool targetAvailable: targetMaterial && !importerRunning readonly property bool targetAvailable: targetItem && !ContentLibraryBackend.rootView.importerRunning
signal unimport(); signal unimport();
signal addToProject() signal addToProject()
signal applyToSelected(bool add) signal applyToSelected(bool add)
signal removeFromContentLib() signal removeFromContentLib()
function popupMenu(targetMaterial = null) function popupMenu(item = null)
{ {
this.targetMaterial = targetMaterial root.targetItem = item
let isMaterial = root.targetItem.itemType === "material"
applyToSelectedReplace.visible = isMaterial
applyToSelectedAdd.visible = isMaterial
popup() popup()
} }
closePolicy: StudioControls.Menu.CloseOnEscape | StudioControls.Menu.CloseOnPressOutside closePolicy: StudioControls.Menu.CloseOnEscape | StudioControls.Menu.CloseOnPressOutside
StudioControls.MenuItem { StudioControls.MenuItem {
id: applyToSelectedReplace
text: qsTr("Apply to selected (replace)") text: qsTr("Apply to selected (replace)")
enabled: root.targetAvailable && root.hasModelSelection height: visible ? implicitHeight : 0
enabled: root.targetAvailable && ContentLibraryBackend.rootView.hasModelSelection
onTriggered: root.applyToSelected(false) onTriggered: root.applyToSelected(false)
} }
StudioControls.MenuItem { StudioControls.MenuItem {
id: applyToSelectedAdd
text: qsTr("Apply to selected (add)") text: qsTr("Apply to selected (add)")
enabled: root.targetAvailable && root.hasModelSelection height: visible ? implicitHeight : 0
enabled: root.targetAvailable && ContentLibraryBackend.rootView.hasModelSelection
onTriggered: root.applyToSelected(true) onTriggered: root.applyToSelected(true)
} }
@@ -46,16 +53,12 @@ StudioControls.Menu {
StudioControls.MenuItem { StudioControls.MenuItem {
enabled: root.targetAvailable enabled: root.targetAvailable
text: qsTr("Add an instance to project") text: qsTr("Add an instance to project")
onTriggered: root.addToProject()
onTriggered: {
root.addToProject()
}
} }
StudioControls.MenuItem { StudioControls.MenuItem {
enabled: root.targetAvailable && root.targetMaterial.bundleMaterialImported enabled: root.targetAvailable && root.targetItem.bundleItemImported
text: qsTr("Remove from project") text: qsTr("Remove from project")
onTriggered: root.unimport() onTriggered: root.unimport()
} }

View File

@@ -16,8 +16,6 @@ Item {
// "failed" // "failed"
property string downloadState: modelData.isDownloaded() ? "downloaded" : "" property string downloadState: modelData.isDownloaded() ? "downloaded" : ""
property bool importerRunning: false
signal showContextMenu() signal showContextMenu()
signal addToProject() signal addToProject()
@@ -32,7 +30,7 @@ Item {
acceptedButtons: Qt.LeftButton | Qt.RightButton acceptedButtons: Qt.LeftButton | Qt.RightButton
onPressed: (mouse) => { onPressed: (mouse) => {
if (mouse.button === Qt.LeftButton && !root.importerRunning) { if (mouse.button === Qt.LeftButton && !ContentLibraryBackend.rootView.importerRunning) {
if (root.downloadState === "downloaded") if (root.downloadState === "downloaded")
ContentLibraryBackend.rootView.startDragMaterial(modelData, mapToGlobal(mouse.x, mouse.y)) ContentLibraryBackend.rootView.startDragMaterial(modelData, mapToGlobal(mouse.x, mouse.y))
} else if (mouse.button === Qt.RightButton && root.downloadState === "downloaded") { } else if (mouse.button === Qt.RightButton && root.downloadState === "downloaded") {
@@ -74,7 +72,7 @@ Item {
color: "#00ff00" color: "#00ff00"
border.color: "#555555" border.color: "#555555"
border.width: 1 border.width: 1
visible: modelData.bundleMaterialImported visible: modelData.bundleItemImported
ToolTip { ToolTip {
visible: indicatorMouseArea.containsMouse visible: indicatorMouseArea.containsMouse
@@ -99,7 +97,7 @@ Item {
pressColor: Qt.hsla(c.hslHue, c.hslSaturation, c.hslLightness, .4) pressColor: Qt.hsla(c.hslHue, c.hslSaturation, c.hslLightness, .4)
anchors.right: img.right anchors.right: img.right
anchors.bottom: img.bottom anchors.bottom: img.bottom
enabled: !root.importerRunning enabled: !ContentLibraryBackend.rootView.importerRunning
visible: root.downloadState === "downloaded" visible: root.downloadState === "downloaded"
&& (containsMouse || mouseArea.containsMouse) && (containsMouse || mouseArea.containsMouse)

View File

@@ -46,16 +46,13 @@ HelperWidgets.ScrollView {
} }
Column { Column {
ContentLibraryMaterialContextMenu { ContentLibraryItemContextMenu {
id: ctxMenu id: ctxMenu
hasModelSelection: root.materialsModel.hasModelSelection onApplyToSelected: (add) => root.materialsModel.applyToSelected(ctxMenu.targetItem, add)
importerRunning: ContentLibraryBackend.rootView.importerRunning
onApplyToSelected: (add) => root.materialsModel.applyToSelected(ctxMenu.targetMaterial, add) onUnimport: root.unimport(ctxMenu.targetItem)
onAddToProject: root.materialsModel.addToProject(ctxMenu.targetItem)
onUnimport: root.unimport(ctxMenu.targetMaterial)
onAddToProject: root.materialsModel.addToProject(ctxMenu.targetMaterial)
} }
Repeater { Repeater {
@@ -103,8 +100,6 @@ HelperWidgets.ScrollView {
width: root.cellWidth width: root.cellWidth
height: root.cellHeight height: root.cellHeight
importerRunning: ContentLibraryBackend.rootView.importerRunning
onShowContextMenu: ctxMenu.popupMenu(modelData) onShowContextMenu: ctxMenu.popupMenu(modelData)
onAddToProject: root.materialsModel.addToProject(modelData) onAddToProject: root.materialsModel.addToProject(modelData)
} }

View File

@@ -12,7 +12,7 @@ HelperWidgets.ScrollView {
id: root id: root
clip: true clip: true
interactive: !ctxMenuMaterial.opened && !ctxMenuTexture.opened interactive: !ctxMenuItem.opened && !ctxMenuTexture.opened
&& !ContentLibraryBackend.rootView.isDragging && !HelperWidgets.Controller.contextMenuOpened && !ContentLibraryBackend.rootView.isDragging && !HelperWidgets.Controller.contextMenuOpened
property real cellWidth: 100 property real cellWidth: 100
@@ -34,7 +34,7 @@ HelperWidgets.ScrollView {
signal removeFromContentLib(var bundleItem); signal removeFromContentLib(var bundleItem);
function closeContextMenu() { function closeContextMenu() {
ctxMenuMaterial.close() ctxMenuItem.close()
ctxMenuTexture.close() ctxMenuTexture.close()
} }
@@ -47,18 +47,16 @@ HelperWidgets.ScrollView {
} }
Column { Column {
ContentLibraryMaterialContextMenu { ContentLibraryItemContextMenu {
id: ctxMenuMaterial id: ctxMenuItem
enableRemove: true enableRemove: true
hasModelSelection: ContentLibraryBackend.userModel.hasModelSelection
importerRunning: ContentLibraryBackend.rootView.importerRunning
onApplyToSelected: (add) => ContentLibraryBackend.userModel.applyToSelected(ctxMenuMaterial.targetMaterial, add) onApplyToSelected: (add) => ContentLibraryBackend.userModel.applyToSelected(ctxMenuItem.targetItem, add)
onUnimport: root.unimport(ctxMenuMaterial.targetMaterial) onUnimport: root.unimport(ctxMenuItem.targetItem)
onAddToProject: ContentLibraryBackend.userModel.addToProject(ctxMenuMaterial.targetMaterial) onAddToProject: ContentLibraryBackend.userModel.addToProject(ctxMenuItem.targetItem)
onRemoveFromContentLib: root.removeFromContentLib(ctxMenuMaterial.targetMaterial) onRemoveFromContentLib: root.removeFromContentLib(ctxMenuItem.targetItem)
} }
ContentLibraryTextureContextMenu { ContentLibraryTextureContextMenu {
@@ -114,9 +112,7 @@ HelperWidgets.ScrollView {
width: root.cellWidth width: root.cellWidth
height: root.cellHeight height: root.cellHeight
importerRunning: ContentLibraryBackend.rootView.importerRunning onShowContextMenu: ctxMenuItem.popupMenu(modelData)
onShowContextMenu: ctxMenuMaterial.popupMenu(modelData)
onAddToProject: ContentLibraryBackend.userModel.addToProject(modelData) onAddToProject: ContentLibraryBackend.userModel.addToProject(modelData)
onVisibleChanged: { onVisibleChanged: {
@@ -139,7 +135,7 @@ HelperWidgets.ScrollView {
width: root.cellWidth width: root.cellWidth
height: root.cellHeight height: root.cellHeight
// onShowContextMenu: ctxMenuTexture.popupMenu(modelData) // TODO onShowContextMenu: ctxMenuItem.popupMenu(modelData)
} }
} }
} }

View File

@@ -36,7 +36,6 @@ public:
TypeName type() const; TypeName type() const;
QStringList files() const; QStringList files() const;
bool visible() const; bool visible() const;
QString qmlFilePath() const;
bool setImported(bool imported); bool setImported(bool imported);
bool imported() const; bool imported() const;

View File

@@ -17,7 +17,7 @@ class ContentLibraryMaterial : public QObject
Q_PROPERTY(QString bundleMaterialName MEMBER m_name CONSTANT) Q_PROPERTY(QString bundleMaterialName MEMBER m_name CONSTANT)
Q_PROPERTY(QUrl bundleMaterialIcon MEMBER m_icon CONSTANT) Q_PROPERTY(QUrl bundleMaterialIcon MEMBER m_icon CONSTANT)
Q_PROPERTY(bool bundleMaterialVisible MEMBER m_visible NOTIFY materialVisibleChanged) Q_PROPERTY(bool bundleMaterialVisible MEMBER m_visible NOTIFY materialVisibleChanged)
Q_PROPERTY(bool bundleMaterialImported READ imported WRITE setImported NOTIFY materialImportedChanged) Q_PROPERTY(bool bundleItemImported READ imported WRITE setImported NOTIFY materialImportedChanged)
Q_PROPERTY(QString bundleMaterialBaseWebUrl MEMBER m_baseWebUrl CONSTANT) Q_PROPERTY(QString bundleMaterialBaseWebUrl MEMBER m_baseWebUrl CONSTANT)
Q_PROPERTY(QString bundleMaterialDirPath READ dirPath CONSTANT) Q_PROPERTY(QString bundleMaterialDirPath READ dirPath CONSTANT)
Q_PROPERTY(QStringList bundleMaterialFiles READ allFiles CONSTANT) Q_PROPERTY(QStringList bundleMaterialFiles READ allFiles CONSTANT)

View File

@@ -383,18 +383,4 @@ void ContentLibraryMaterialsModel::removeFromProject(ContentLibraryMaterial *mat
qWarning() << __FUNCTION__ << err; qWarning() << __FUNCTION__ << err;
} }
bool ContentLibraryMaterialsModel::hasModelSelection() const
{
return m_hasModelSelection;
}
void ContentLibraryMaterialsModel::setHasModelSelection(bool b)
{
if (b == m_hasModelSelection)
return;
m_hasModelSelection = b;
emit hasModelSelectionChanged();
}
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -21,7 +21,6 @@ class ContentLibraryMaterialsModel : public QAbstractListModel
Q_PROPERTY(bool matBundleExists READ matBundleExists NOTIFY matBundleExistsChanged) Q_PROPERTY(bool matBundleExists READ matBundleExists NOTIFY matBundleExistsChanged)
Q_PROPERTY(bool isEmpty MEMBER m_isEmpty NOTIFY isEmptyChanged) Q_PROPERTY(bool isEmpty MEMBER m_isEmpty NOTIFY isEmptyChanged)
Q_PROPERTY(bool hasRequiredQuick3DImport READ hasRequiredQuick3DImport NOTIFY hasRequiredQuick3DImportChanged) Q_PROPERTY(bool hasRequiredQuick3DImport READ hasRequiredQuick3DImport NOTIFY hasRequiredQuick3DImportChanged)
Q_PROPERTY(bool hasModelSelection READ hasModelSelection NOTIFY hasModelSelectionChanged)
public: public:
ContentLibraryMaterialsModel(ContentLibraryWidget *parent = nullptr); ContentLibraryMaterialsModel(ContentLibraryWidget *parent = nullptr);
@@ -33,16 +32,11 @@ public:
void setSearchText(const QString &searchText); void setSearchText(const QString &searchText);
void updateImportedState(const QStringList &importedItems); void updateImportedState(const QStringList &importedItems);
void setQuick3DImportVersion(int major, int minor); void setQuick3DImportVersion(int major, int minor);
bool hasRequiredQuick3DImport() const; bool hasRequiredQuick3DImport() const;
bool matBundleExists() const; bool matBundleExists() const;
bool hasModelSelection() const;
void setHasModelSelection(bool b);
void resetModel(); void resetModel();
void updateIsEmpty(); void updateIsEmpty();
void loadBundle(); void loadBundle();
@@ -56,7 +50,6 @@ public:
signals: signals:
void isEmptyChanged(); void isEmptyChanged();
void hasRequiredQuick3DImportChanged(); void hasRequiredQuick3DImportChanged();
void hasModelSelectionChanged();
void materialVisibleChanged(); void materialVisibleChanged();
void applyToSelectedTriggered(QmlDesigner::ContentLibraryMaterial *mat, bool add = false); void applyToSelectedTriggered(QmlDesigner::ContentLibraryMaterial *mat, bool add = false);
void matBundleExistsChanged(); void matBundleExistsChanged();
@@ -77,7 +70,6 @@ private:
bool m_isEmpty = true; bool m_isEmpty = true;
bool m_bundleExists = false; bool m_bundleExists = false;
bool m_hasModelSelection = false;
int m_quick3dMajorVersion = -1; int m_quick3dMajorVersion = -1;
int m_quick3dMinorVersion = -1; int m_quick3dMinorVersion = -1;

View File

@@ -177,7 +177,15 @@ void ContentLibraryUserModel::removeTexture(ContentLibraryTexture *tex)
emit dataChanged(index(texSectionIdx), index(texSectionIdx)); emit dataChanged(index(texSectionIdx), index(texSectionIdx));
} }
void ContentLibraryUserModel::removeFromContentLib(ContentLibraryMaterial *mat) void ContentLibraryUserModel::removeFromContentLib(QObject *item)
{
if (auto mat = qobject_cast<ContentLibraryMaterial *>(item))
removeMaterialFromContentLib(mat);
else if (auto itm = qobject_cast<ContentLibraryItem *>(item))
remove3DFromContentLib(itm);
}
void ContentLibraryUserModel::removeMaterialFromContentLib(ContentLibraryMaterial *mat)
{ {
auto bundlePath = Utils::FilePath::fromString(Paths::bundlesPathSetting() + "/User/materials/"); auto bundlePath = Utils::FilePath::fromString(Paths::bundlesPathSetting() + "/User/materials/");
@@ -215,6 +223,48 @@ void ContentLibraryUserModel::removeFromContentLib(ContentLibraryMaterial *mat)
emit dataChanged(index(matSectionIdx), index(matSectionIdx)); emit dataChanged(index(matSectionIdx), index(matSectionIdx));
} }
void ContentLibraryUserModel::remove3DFromContentLib(ContentLibraryItem *item)
{
QJsonArray itemsArr = m_bundleObj3D.value("items").toArray();
// remove qml and icon files
m_bundlePath3D.pathAppended(item->qml()).removeFile();
Utils::FilePath::fromUrl(item->icon()).removeFile();
// remove from the bundle json file
for (int i = 0; i < itemsArr.size(); ++i) {
if (itemsArr.at(i).toObject().value("qml") == item->qml()) {
itemsArr.removeAt(i);
break;
}
}
m_bundleObj3D.insert("items", itemsArr);
auto result = m_bundlePath3D.pathAppended("user_3d_bundle.json")
.writeFileContents(QJsonDocument(m_bundleObj3D).toJson());
if (!result)
qWarning() << __FUNCTION__ << result.error();
// delete dependency files if they are only used by the deleted item
QStringList allFiles;
for (const QJsonValueConstRef &itemRef : std::as_const(itemsArr))
allFiles.append(itemRef.toObject().value("files").toVariant().toStringList());
const QStringList itemFiles = item->files();
for (const QString &file : itemFiles) {
if (allFiles.count(file) == 0) // only used by the deleted item
m_bundlePath3D.pathAppended(file).removeFile();
}
// remove from model
m_user3DItems.removeOne(item);
item->deleteLater();
// update model
int sectionIdx = 2;
emit dataChanged(index(sectionIdx), index(sectionIdx));
}
// returns unique library material's name and qml component // returns unique library material's name and qml component
QPair<QString, QString> ContentLibraryUserModel::getUniqueLibMaterialNameAndQml(const QString &defaultName) const QPair<QString, QString> ContentLibraryUserModel::getUniqueLibMaterialNameAndQml(const QString &defaultName) const
{ {
@@ -520,7 +570,7 @@ void ContentLibraryUserModel::setSearchText(const QString &searchText)
updateIsEmpty3D(); updateIsEmpty3D();
} }
void ContentLibraryUserModel::updateImportedState(const QStringList &importedItems) void ContentLibraryUserModel::updateMaterialsImportedState(const QStringList &importedItems)
{ {
bool changed = false; bool changed = false;
for (ContentLibraryMaterial *mat : std::as_const(m_userMaterials)) for (ContentLibraryMaterial *mat : std::as_const(m_userMaterials))
@@ -532,6 +582,18 @@ void ContentLibraryUserModel::updateImportedState(const QStringList &importedIte
} }
} }
void ContentLibraryUserModel::update3DImportedState(const QStringList &importedItems)
{
bool changed = false;
for (ContentLibraryItem *item : std::as_const(m_user3DItems))
changed |= item->setImported(importedItems.contains(item->qml().chopped(4)));
if (changed) {
int sectionIdx = 2;
emit dataChanged(index(sectionIdx), index(sectionIdx));
}
}
void ContentLibraryUserModel::setQuick3DImportVersion(int major, int minor) void ContentLibraryUserModel::setQuick3DImportVersion(int major, int minor)
{ {
bool oldRequiredImport = hasRequiredQuick3DImport(); bool oldRequiredImport = hasRequiredQuick3DImport();
@@ -561,39 +623,56 @@ void ContentLibraryUserModel::applyToSelected(ContentLibraryMaterial *mat, bool
emit applyToSelectedTriggered(mat, add); emit applyToSelectedTriggered(mat, add);
} }
void ContentLibraryUserModel::addToProject(ContentLibraryMaterial *mat) void ContentLibraryUserModel::addToProject(QObject *item)
{ {
QString err = m_widget->importer()->importComponent(mat->dirPath(), mat->type(), mat->qml(), QString bundleDir;
mat->files() + m_bundleMaterialSharedFiles); TypeName type;
QString qmlFile;
if (err.isEmpty()) QStringList files;
m_widget->setImporterRunning(true); if (auto mat = qobject_cast<ContentLibraryMaterial *>(item)) {
else bundleDir = mat->dirPath();
qWarning() << __FUNCTION__ << err; type = mat->type();
} qmlFile = mat->qml();
files = mat->files() + m_bundleMaterialSharedFiles;
void ContentLibraryUserModel::removeFromProject(ContentLibraryMaterial *mat) } else if (auto itm = qobject_cast<ContentLibraryItem *>(item)) {
{ bundleDir = m_bundlePath3D.toString();
QString err = m_widget->importer()->unimportComponent(mat->type(), mat->qml()); type = itm->type();
qmlFile = itm->qml();
if (err.isEmpty()) files = itm->files() + m_bundle3DSharedFiles;
m_widget->setImporterRunning(true); } else {
else qWarning() << __FUNCTION__ << "Unsupported Item";
qWarning() << __FUNCTION__ << err;
}
bool ContentLibraryUserModel::hasModelSelection() const
{
return m_hasModelSelection;
}
void ContentLibraryUserModel::setHasModelSelection(bool b)
{
if (b == m_hasModelSelection)
return; return;
}
m_hasModelSelection = b; QString err = m_widget->importer()->importComponent(bundleDir, type, qmlFile, files);
emit hasModelSelectionChanged();
if (err.isEmpty())
m_widget->setImporterRunning(true);
else
qWarning() << __FUNCTION__ << err;
}
void ContentLibraryUserModel::removeFromProject(QObject *item)
{
TypeName type;
QString qml;
if (auto mat = qobject_cast<ContentLibraryMaterial *>(item)) {
type = mat->type();
qml = mat->qml();
} else if (auto itm = qobject_cast<ContentLibraryItem *>(item)) {
type = itm->type();
qml = itm->qml();
} else {
qWarning() << __FUNCTION__ << "Unsupported Item";
return;
}
QString err = m_widget->importer()->unimportComponent(type, qml);
if (err.isEmpty())
m_widget->setImporterRunning(true);
else
qWarning() << __FUNCTION__ << err;
} }
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -27,7 +27,6 @@ class ContentLibraryUserModel : public QAbstractListModel
Q_PROPERTY(bool isEmptyMaterials MEMBER m_isEmptyMaterials NOTIFY isEmptyMaterialsChanged) Q_PROPERTY(bool isEmptyMaterials MEMBER m_isEmptyMaterials NOTIFY isEmptyMaterialsChanged)
Q_PROPERTY(bool isEmpty3D MEMBER m_isEmpty3D NOTIFY isEmpty3DChanged) Q_PROPERTY(bool isEmpty3D MEMBER m_isEmpty3D NOTIFY isEmpty3DChanged)
Q_PROPERTY(bool hasRequiredQuick3DImport READ hasRequiredQuick3DImport NOTIFY hasRequiredQuick3DImportChanged) Q_PROPERTY(bool hasRequiredQuick3DImport READ hasRequiredQuick3DImport NOTIFY hasRequiredQuick3DImportChanged)
Q_PROPERTY(bool hasModelSelection READ hasModelSelection NOTIFY hasModelSelectionChanged)
Q_PROPERTY(QList<ContentLibraryMaterial *> userMaterials MEMBER m_userMaterials NOTIFY userMaterialsChanged) Q_PROPERTY(QList<ContentLibraryMaterial *> userMaterials MEMBER m_userMaterials NOTIFY userMaterialsChanged)
Q_PROPERTY(QList<ContentLibraryTexture *> userTextures MEMBER m_userTextures NOTIFY userTexturesChanged) Q_PROPERTY(QList<ContentLibraryTexture *> userTextures MEMBER m_userTextures NOTIFY userTexturesChanged)
Q_PROPERTY(QList<ContentLibraryItem *> user3DItems MEMBER m_user3DItems NOTIFY user3DItemsChanged) Q_PROPERTY(QList<ContentLibraryItem *> user3DItems MEMBER m_user3DItems NOTIFY user3DItemsChanged)
@@ -41,7 +40,8 @@ public:
QHash<int, QByteArray> roleNames() const override; QHash<int, QByteArray> roleNames() const override;
void setSearchText(const QString &searchText); void setSearchText(const QString &searchText);
void updateImportedState(const QStringList &importedItems); void updateMaterialsImportedState(const QStringList &importedItems);
void update3DImportedState(const QStringList &importedItems);
QPair<QString, QString> getUniqueLibMaterialNameAndQml(const QString &defaultName = {}) const; QPair<QString, QString> getUniqueLibMaterialNameAndQml(const QString &defaultName = {}) const;
QString getUniqueLib3DQmlName(const QString &defaultName = {}) const; QString getUniqueLib3DQmlName(const QString &defaultName = {}) const;
@@ -52,9 +52,6 @@ public:
bool matBundleExists() const; bool matBundleExists() const;
bool hasModelSelection() const;
void setHasModelSelection(bool b);
void resetModel(); void resetModel();
void updateIsEmptyMaterials(); void updateIsEmptyMaterials();
void updateIsEmpty3D(); void updateIsEmpty3D();
@@ -73,23 +70,20 @@ public:
void loadBundles(); void loadBundles();
Q_INVOKABLE void applyToSelected(QmlDesigner::ContentLibraryMaterial *mat, bool add = false); Q_INVOKABLE void applyToSelected(QmlDesigner::ContentLibraryMaterial *mat, bool add = false);
Q_INVOKABLE void addToProject(QmlDesigner::ContentLibraryMaterial *mat); Q_INVOKABLE void addToProject(QObject *item);
Q_INVOKABLE void removeFromProject(QmlDesigner::ContentLibraryMaterial *mat); Q_INVOKABLE void removeFromProject(QObject *item);
Q_INVOKABLE void removeTexture(QmlDesigner::ContentLibraryTexture *tex); Q_INVOKABLE void removeTexture(QmlDesigner::ContentLibraryTexture *tex);
Q_INVOKABLE void removeFromContentLib(QmlDesigner::ContentLibraryMaterial *mat); Q_INVOKABLE void removeFromContentLib(QObject *item);
signals: signals:
void isEmptyMaterialsChanged(); void isEmptyMaterialsChanged();
void isEmpty3DChanged(); void isEmpty3DChanged();
void hasRequiredQuick3DImportChanged(); void hasRequiredQuick3DImportChanged();
void hasModelSelectionChanged();
void userMaterialsChanged(); void userMaterialsChanged();
void userTexturesChanged(); void userTexturesChanged();
void user3DItemsChanged(); void user3DItemsChanged();
void userEffectsChanged(); void userEffectsChanged();
void applyToSelectedTriggered(QmlDesigner::ContentLibraryMaterial *mat, bool add = false); void applyToSelectedTriggered(QmlDesigner::ContentLibraryMaterial *mat, bool add = false);
void matBundleExistsChanged(); void matBundleExistsChanged();
void bundle3DExistsChanged(); void bundle3DExistsChanged();
@@ -98,6 +92,8 @@ private:
void load3DBundle(); void load3DBundle();
void loadTextureBundle(); void loadTextureBundle();
bool isValidIndex(int idx) const; bool isValidIndex(int idx) const;
void removeMaterialFromContentLib(ContentLibraryMaterial *mat);
void remove3DFromContentLib(ContentLibraryItem *item);
ContentLibraryWidget *m_widget = nullptr; ContentLibraryWidget *m_widget = nullptr;
QString m_searchText; QString m_searchText;
@@ -120,7 +116,6 @@ private:
bool m_isEmpty3D = true; bool m_isEmpty3D = true;
bool m_matBundleExists = false; bool m_matBundleExists = false;
bool m_bundle3DExists = false; bool m_bundle3DExists = false;
bool m_hasModelSelection = false;
int m_quick3dMajorVersion = -1; int m_quick3dMajorVersion = -1;
int m_quick3dMinorVersion = -1; int m_quick3dMinorVersion = -1;

View File

@@ -306,8 +306,7 @@ void ContentLibraryView::selectedNodesChanged(const QList<ModelNode> &selectedNo
return node.metaInfo().isQtQuick3DModel(); return node.metaInfo().isQtQuick3DModel();
}); });
m_widget->materialsModel()->setHasModelSelection(!m_selectedModels.isEmpty()); m_widget->setHasModelSelection(!m_selectedModels.isEmpty());
m_widget->userModel()->setHasModelSelection(!m_selectedModels.isEmpty());
} }
void ContentLibraryView::customNotification(const AbstractView *view, void ContentLibraryView::customNotification(const AbstractView *view,
@@ -565,7 +564,7 @@ QStringList ContentLibraryView::writeLibItemQml(const ModelNode &node, const QSt
qmlString.prepend("import QtQuick\nimport QtQuick3D\n\n"); qmlString.prepend("import QtQuick\nimport QtQuick3D\n\n");
QString itemType = QLatin1String(node.metaInfo().isQtQuick3DMaterial() ? "material" : "3d"); QString itemType = QLatin1String(node.metaInfo().isQtQuick3DMaterial() ? "materials" : "3d");
auto qmlPath = Utils::FilePath::fromString(QLatin1String("%1/User/%2/%3") auto qmlPath = Utils::FilePath::fromString(QLatin1String("%1/User/%2/%3")
.arg(Paths::bundlesPathSetting(), itemType, qml)); .arg(Paths::bundlesPathSetting(), itemType, qml));
auto result = qmlPath.writeFileContents(qmlString.toUtf8()); auto result = qmlPath.writeFileContents(qmlString.toUtf8());

View File

@@ -231,7 +231,9 @@ void ContentLibraryWidget::updateImportedState(const QString &bundleId)
else if (bundleId == compUtils.effectsBundleId()) else if (bundleId == compUtils.effectsBundleId())
m_effectsModel->updateImportedState(importedItems); m_effectsModel->updateImportedState(importedItems);
else if (bundleId == compUtils.userMaterialsBundleId()) else if (bundleId == compUtils.userMaterialsBundleId())
m_userModel->updateImportedState(importedItems); m_userModel->updateMaterialsImportedState(importedItems);
else if (bundleId == compUtils.user3DBundleId())
m_userModel->update3DImportedState(importedItems);
} }
ContentLibraryBundleImporter *ContentLibraryWidget::importer() const ContentLibraryBundleImporter *ContentLibraryWidget::importer() const
@@ -865,4 +867,18 @@ QPointer<ContentLibraryUserModel> ContentLibraryWidget::userModel() const
return m_userModel; return m_userModel;
} }
bool ContentLibraryWidget::hasModelSelection() const
{
return m_hasModelSelection;
}
void ContentLibraryWidget::setHasModelSelection(bool b)
{
if (b == m_hasModelSelection)
return;
m_hasModelSelection = b;
emit hasModelSelectionChanged();
}
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -41,6 +41,7 @@ class ContentLibraryWidget : public QFrame
Q_PROPERTY(bool hasActive3DScene READ hasActive3DScene WRITE setHasActive3DScene NOTIFY hasActive3DSceneChanged) Q_PROPERTY(bool hasActive3DScene READ hasActive3DScene WRITE setHasActive3DScene NOTIFY hasActive3DSceneChanged)
Q_PROPERTY(bool isQt6Project READ isQt6Project NOTIFY isQt6ProjectChanged) Q_PROPERTY(bool isQt6Project READ isQt6Project NOTIFY isQt6ProjectChanged)
Q_PROPERTY(bool importerRunning READ importerRunning WRITE setImporterRunning NOTIFY importerRunningChanged) Q_PROPERTY(bool importerRunning READ importerRunning WRITE setImporterRunning NOTIFY importerRunningChanged)
Q_PROPERTY(bool hasModelSelection READ hasModelSelection NOTIFY hasModelSelectionChanged)
// Needed for a workaround for a bug where after drag-n-dropping an item, the ScrollView scrolls to a random position // Needed for a workaround for a bug where after drag-n-dropping an item, the ScrollView scrolls to a random position
Q_PROPERTY(bool isDragging MEMBER m_isDragging NOTIFY isDraggingChanged) Q_PROPERTY(bool isDragging MEMBER m_isDragging NOTIFY isDraggingChanged)
@@ -68,7 +69,8 @@ public:
bool importerRunning() const; bool importerRunning() const;
void setImporterRunning(bool b); void setImporterRunning(bool b);
Q_INVOKABLE void handleSearchFilterChanged(const QString &filterText); bool hasModelSelection() const;
void setHasModelSelection(bool b);
void setMaterialsModel(QPointer<ContentLibraryMaterialsModel> newMaterialsModel); void setMaterialsModel(QPointer<ContentLibraryMaterialsModel> newMaterialsModel);
void updateImportedState(const QString &bundleId); void updateImportedState(const QString &bundleId);
@@ -79,6 +81,7 @@ public:
QPointer<ContentLibraryEffectsModel> effectsModel() const; QPointer<ContentLibraryEffectsModel> effectsModel() const;
QPointer<ContentLibraryUserModel> userModel() const; QPointer<ContentLibraryUserModel> userModel() const;
Q_INVOKABLE void handleSearchFilterChanged(const QString &filterText);
Q_INVOKABLE void startDragItem(QmlDesigner::ContentLibraryItem *item, const QPointF &mousePos); Q_INVOKABLE void startDragItem(QmlDesigner::ContentLibraryItem *item, const QPointF &mousePos);
Q_INVOKABLE void startDragMaterial(QmlDesigner::ContentLibraryMaterial *mat, const QPointF &mousePos); Q_INVOKABLE void startDragMaterial(QmlDesigner::ContentLibraryMaterial *mat, const QPointF &mousePos);
Q_INVOKABLE void startDragTexture(QmlDesigner::ContentLibraryTexture *tex, const QPointF &mousePos); Q_INVOKABLE void startDragTexture(QmlDesigner::ContentLibraryTexture *tex, const QPointF &mousePos);
@@ -105,6 +108,7 @@ signals:
void isDraggingChanged(); void isDraggingChanged();
void isQt6ProjectChanged(); void isQt6ProjectChanged();
void importerRunningChanged(); void importerRunningChanged();
void hasModelSelectionChanged();
protected: protected:
bool eventFilter(QObject *obj, QEvent *event) override; bool eventFilter(QObject *obj, QEvent *event) override;
@@ -148,6 +152,7 @@ private:
bool m_isDragging = false; bool m_isDragging = false;
bool m_isQt6Project = false; bool m_isQt6Project = false;
bool m_importerRunning = false; bool m_importerRunning = false;
bool m_hasModelSelection = false;
QString m_textureBundleUrl; QString m_textureBundleUrl;
QString m_bundlePath; QString m_bundlePath;
}; };