forked from qt-creator/qt-creator
QmlDesigner: Allow removing a content library material
Fixes: QDS-12541 Change-Id: I8efdd5c5f6185961bd8440e06d0adb60ad9d79f2 Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
This commit is contained in:
@@ -130,10 +130,14 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
UnimportBundleMaterialDialog {
|
||||
UnimportBundleItemDialog {
|
||||
id: confirmUnimportDialog
|
||||
}
|
||||
|
||||
DeleteBundleItemDialog {
|
||||
id: confirmDeleteDialog
|
||||
}
|
||||
|
||||
StackLayout {
|
||||
id: stackLayout
|
||||
width: root.width
|
||||
@@ -246,6 +250,12 @@ Item {
|
||||
confirmUnimportDialog.open()
|
||||
}
|
||||
|
||||
onRemoveFromContentLib: (bundleItem) => {
|
||||
confirmDeleteDialog.targetBundleItem = bundleItem
|
||||
confirmDeleteDialog.targetBundleLabel = "material"
|
||||
confirmDeleteDialog.open()
|
||||
}
|
||||
|
||||
onCountChanged: root.responsiveResize(stackLayout.width, stackLayout.height)
|
||||
}
|
||||
}
|
||||
|
@@ -12,12 +12,14 @@ StudioControls.Menu {
|
||||
property var targetMaterial: null
|
||||
property bool hasModelSelection: false
|
||||
property bool importerRunning: false
|
||||
property bool enableRemove: false // true: adds an option to remove targetMaterial
|
||||
|
||||
readonly property bool targetAvailable: targetMaterial && !importerRunning
|
||||
|
||||
signal unimport();
|
||||
signal addToProject()
|
||||
signal applyToSelected(bool add)
|
||||
signal removeFromContentLib()
|
||||
|
||||
function popupMenu(targetMaterial = null)
|
||||
{
|
||||
@@ -56,4 +58,11 @@ StudioControls.Menu {
|
||||
|
||||
onTriggered: root.unimport()
|
||||
}
|
||||
|
||||
StudioControls.MenuItem {
|
||||
text: qsTr("Remove from Content Library")
|
||||
visible: root.enableRemove && root.targetAvailable
|
||||
height: visible ? implicitHeight : 0
|
||||
onTriggered: root.removeFromContentLib()
|
||||
}
|
||||
}
|
||||
|
@@ -31,6 +31,7 @@ HelperWidgets.ScrollView {
|
||||
required property var searchBox
|
||||
|
||||
signal unimport(var bundleItem);
|
||||
signal removeFromContentLib(var bundleItem);
|
||||
|
||||
function closeContextMenu() {
|
||||
ctxMenuMaterial.close()
|
||||
@@ -49,6 +50,7 @@ HelperWidgets.ScrollView {
|
||||
ContentLibraryMaterialContextMenu {
|
||||
id: ctxMenuMaterial
|
||||
|
||||
enableRemove: true
|
||||
hasModelSelection: ContentLibraryBackend.userModel.hasModelSelection
|
||||
importerRunning: ContentLibraryBackend.userModel.importerRunning
|
||||
|
||||
@@ -56,6 +58,7 @@ HelperWidgets.ScrollView {
|
||||
|
||||
onUnimport: root.unimport(ctxMenuMaterial.targetMaterial)
|
||||
onAddToProject: ContentLibraryBackend.userModel.addToProject(ctxMenuMaterial.targetMaterial)
|
||||
onRemoveFromContentLib: root.removeFromContentLib(ctxMenuMaterial.targetMaterial)
|
||||
}
|
||||
|
||||
ContentLibraryTextureContextMenu {
|
||||
|
@@ -0,0 +1,65 @@
|
||||
// Copyright (C) 2024 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import HelperWidgets
|
||||
import StudioControls as StudioControls
|
||||
import StudioTheme as StudioTheme
|
||||
import ContentLibraryBackend
|
||||
|
||||
StudioControls.Dialog {
|
||||
id: root
|
||||
|
||||
property var targetBundleItem
|
||||
property var targetBundleModel
|
||||
property string targetBundleLabel // "effect" or "material"
|
||||
|
||||
title: qsTr("Remove bundle %1").arg(root.targetBundleLabel)
|
||||
anchors.centerIn: parent
|
||||
closePolicy: Popup.CloseOnEscape
|
||||
implicitWidth: 300
|
||||
modal: true
|
||||
|
||||
onOpened: warningText.forceActiveFocus()
|
||||
|
||||
contentItem: Column {
|
||||
spacing: 20
|
||||
width: parent.width
|
||||
|
||||
Text {
|
||||
id: warningText
|
||||
|
||||
text: qsTr("Are you sure you? The action cannot be undone")
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
wrapMode: Text.WordWrap
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
leftPadding: 10
|
||||
rightPadding: 10
|
||||
|
||||
Keys.onEnterPressed: btnRemove.onClicked()
|
||||
Keys.onReturnPressed: btnRemove.onClicked()
|
||||
}
|
||||
|
||||
Row {
|
||||
anchors.right: parent.right
|
||||
Button {
|
||||
id: btnRemove
|
||||
|
||||
text: qsTr("Remove")
|
||||
|
||||
onClicked: {
|
||||
ContentLibraryBackend.userModel.removeFromContentLib(root.targetBundleItem)
|
||||
root.accept()
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
text: qsTr("Cancel")
|
||||
onClicked: root.reject()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -13,8 +13,8 @@ StudioControls.Dialog {
|
||||
id: root
|
||||
|
||||
property var targetBundleItem
|
||||
property var targetBundleLabel // "effect" or "material"
|
||||
property var targetBundleModel
|
||||
property string targetBundleLabel // "effect" or "material"
|
||||
|
||||
title: qsTr("Bundle %1 might be in use").arg(root.targetBundleLabel)
|
||||
anchors.centerIn: parent
|
@@ -32,6 +32,11 @@ bool ContentLibraryMaterial::filter(const QString &searchText)
|
||||
return m_visible;
|
||||
}
|
||||
|
||||
QString ContentLibraryMaterial::name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
QUrl ContentLibraryMaterial::icon() const
|
||||
{
|
||||
return m_icon;
|
||||
|
@@ -37,6 +37,7 @@ public:
|
||||
|
||||
Q_INVOKABLE bool isDownloaded() const;
|
||||
|
||||
QString name() const;
|
||||
QUrl icon() const;
|
||||
QString qml() const;
|
||||
TypeName type() const;
|
||||
|
@@ -33,9 +33,6 @@ ContentLibraryUserModel::ContentLibraryUserModel(ContentLibraryWidget *parent)
|
||||
, m_widget(parent)
|
||||
{
|
||||
m_userCategories = {tr("Materials"), tr("Textures")/*, tr("3D"), tr("Effects"), tr("2D components")*/}; // TODO
|
||||
|
||||
loadMaterialBundle();
|
||||
loadTextureBundle();
|
||||
}
|
||||
|
||||
int ContentLibraryUserModel::rowCount(const QModelIndex &) const
|
||||
@@ -136,6 +133,44 @@ void ContentLibraryUserModel::removeTexture(ContentLibraryTexture *tex)
|
||||
emit dataChanged(index(texSectionIdx), index(texSectionIdx));
|
||||
}
|
||||
|
||||
void ContentLibraryUserModel::removeFromContentLib(ContentLibraryMaterial *mat)
|
||||
{
|
||||
auto bundlePath = Utils::FilePath::fromString(Paths::bundlesPathSetting() + "/User/materials/");
|
||||
|
||||
QJsonObject matsObj = m_bundleObj.value("materials").toObject();
|
||||
|
||||
// remove qml and icon files
|
||||
Utils::FilePath::fromString(mat->qmlFilePath()).removeFile();
|
||||
Utils::FilePath::fromUrl(mat->icon()).removeFile();
|
||||
|
||||
// remove from the bundle json file
|
||||
matsObj.remove(mat->name());
|
||||
m_bundleObj.insert("materials", matsObj);
|
||||
auto result = bundlePath.pathAppended("user_materials_bundle.json")
|
||||
.writeFileContents(QJsonDocument(m_bundleObj).toJson());
|
||||
if (!result)
|
||||
qWarning() << __FUNCTION__ << result.error();
|
||||
|
||||
// delete dependency files if they are only used by the deleted material
|
||||
QStringList allFiles;
|
||||
for (const QJsonValueConstRef &mat : std::as_const(matsObj))
|
||||
allFiles.append(mat.toObject().value("files").toVariant().toStringList());
|
||||
|
||||
const QStringList matFiles = mat->files();
|
||||
for (const QString &matFile : matFiles) {
|
||||
if (allFiles.count(matFile) == 0) // only used by the deleted material
|
||||
bundlePath.pathAppended(matFile).removeFile();
|
||||
}
|
||||
|
||||
// remove from model
|
||||
m_userMaterials.removeOne(mat);
|
||||
mat->deleteLater();
|
||||
|
||||
// update model
|
||||
int matSectionIdx = 0;
|
||||
emit dataChanged(index(matSectionIdx), index(matSectionIdx));
|
||||
}
|
||||
|
||||
// returns unique library material's name and qml component
|
||||
QPair<QString, QString> ContentLibraryUserModel::getUniqueLibMaterialNameAndQml(const QString &matName) const
|
||||
{
|
||||
|
@@ -67,12 +67,16 @@ public:
|
||||
void setBundleObj(const QJsonObject &newBundleObj);
|
||||
QJsonObject &bundleJsonObjectRef();
|
||||
|
||||
void loadMaterialBundle();
|
||||
void loadTextureBundle();
|
||||
|
||||
Internal::ContentLibraryBundleImporter *bundleImporter() const;
|
||||
|
||||
Q_INVOKABLE void applyToSelected(QmlDesigner::ContentLibraryMaterial *mat, bool add = false);
|
||||
Q_INVOKABLE void addToProject(QmlDesigner::ContentLibraryMaterial *mat);
|
||||
Q_INVOKABLE void removeFromProject(QmlDesigner::ContentLibraryMaterial *mat);
|
||||
Q_INVOKABLE void removeTexture(QmlDesigner::ContentLibraryTexture *tex);
|
||||
Q_INVOKABLE void removeFromContentLib(QmlDesigner::ContentLibraryMaterial *mat);
|
||||
|
||||
signals:
|
||||
void isEmptyChanged();
|
||||
@@ -96,8 +100,6 @@ signals:
|
||||
void matBundleExistsChanged();
|
||||
|
||||
private:
|
||||
void loadMaterialBundle();
|
||||
void loadTextureBundle();
|
||||
bool isValidIndex(int idx) const;
|
||||
void createImporter(const QString &bundlePath, const QString &bundleId,
|
||||
const QStringList &sharedFiles);
|
||||
|
@@ -304,6 +304,9 @@ void ContentLibraryView::modelAttached(Model *model)
|
||||
|
||||
m_widget->effectsModel()->loadBundle();
|
||||
updateBundleEffectsImportedState();
|
||||
|
||||
m_widget->userModel()->loadMaterialBundle();
|
||||
m_widget->userModel()->loadTextureBundle();
|
||||
}
|
||||
|
||||
void ContentLibraryView::modelAboutToBeDetached(Model *model)
|
||||
|
Reference in New Issue
Block a user