QmlDesigner: Implement adding an image to the content library

Also some cleanups in same files.

Fixes: QDS-12506
Change-Id: I0c211206b6b7c29857a30f18d6077c2ddd76849c
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
Reviewed-by: Qt CI Patch Build Bot <ci_patchbuild_bot@qt.io>
This commit is contained in:
Mahmoud Badri
2024-04-20 00:25:43 +03:00
parent cbc617d2ad
commit a369d075ad
15 changed files with 160 additions and 67 deletions

View File

@@ -94,7 +94,7 @@ Item {
anchors.fill: parent anchors.fill: parent
acceptedButtons: Qt.RightButton acceptedButtons: Qt.RightButton
onClicked: { onClicked: {
if (assetsModel.haveFiles) { if (assetsModel.hasFiles) {
function onFolderCreated(path) { function onFolderCreated(path) {
assetsView.addCreatedFolder(path) assetsView.addCreatedFolder(path)
} }
@@ -182,13 +182,13 @@ Item {
leftPadding: 10 leftPadding: 10
color: StudioTheme.Values.themeTextColor color: StudioTheme.Values.themeTextColor
font.pixelSize: StudioTheme.Values.baseFont font.pixelSize: StudioTheme.Values.baseFont
visible: !assetsModel.haveFiles && !root.__searchBoxEmpty visible: !assetsModel.hasFiles && !root.__searchBoxEmpty
} }
Item { // placeholder when the assets library is empty Item { // placeholder when the assets library is empty
width: parent.width width: parent.width
height: parent.height - toolbar.height - column.spacing height: parent.height - toolbar.height - column.spacing
visible: !assetsModel.haveFiles && root.__searchBoxEmpty visible: !assetsModel.hasFiles && root.__searchBoxEmpty
clip: true clip: true
MouseArea { // right clicking the empty area of the view MouseArea { // right clicking the empty area of the view

View File

@@ -83,7 +83,7 @@ StudioControls.Menu {
root.__selectedAssetPathsList = selectedAssetPathsList root.__selectedAssetPathsList = selectedAssetPathsList
root.__fileIndex = fileIndex root.__fileIndex = fileIndex
root.__dirIndex = dirModelIndex root.__dirIndex = dirModelIndex
root.__dirPath = AssetsLibraryBackend.assetsModel.filePath(dirModelIndex) root.__dirPath = root.assetsModel.filePath(dirModelIndex)
root.__isDirectory = false root.__isDirectory = false
root.popup() root.popup()
} }
@@ -124,9 +124,9 @@ StudioControls.Menu {
id: addTexturesItem id: addTexturesItem
text: qsTr("Add Texture") text: qsTr("Add Texture")
enabled: rootView.hasMaterialLibrary enabled: rootView.hasMaterialLibrary
visible: root.__fileIndex && AssetsLibraryBackend.assetsModel.allFilePathsAreTextures(root.__selectedAssetPathsList) visible: root.__fileIndex && root.assetsModel.allFilePathsAreTextures(root.__selectedAssetPathsList)
height: addTexturesItem.visible ? addTexturesItem.implicitHeight : 0 height: addTexturesItem.visible ? addTexturesItem.implicitHeight : 0
onTriggered: AssetsLibraryBackend.rootView.addTextures(root.__selectedAssetPathsList) onTriggered: root.rootView.addTextures(root.__selectedAssetPathsList)
} }
StudioControls.MenuItem { StudioControls.MenuItem {
@@ -134,7 +134,7 @@ StudioControls.Menu {
text: qsTr("Add Light Probe") text: qsTr("Add Light Probe")
enabled: rootView.hasMaterialLibrary && rootView.hasSceneEnv enabled: rootView.hasMaterialLibrary && rootView.hasSceneEnv
visible: root.__fileIndex && root.__selectedAssetPathsList.length === 1 visible: root.__fileIndex && root.__selectedAssetPathsList.length === 1
&& AssetsLibraryBackend.assetsModel.allFilePathsAreTextures(root.__selectedAssetPathsList) && root.assetsModel.allFilePathsAreTextures(root.__selectedAssetPathsList)
height: addLightProbes.visible ? addLightProbes.implicitHeight : 0 height: addLightProbes.visible ? addLightProbes.implicitHeight : 0
onTriggered: rootView.addLightProbe(root.__selectedAssetPathsList[0]) onTriggered: rootView.addLightProbe(root.__selectedAssetPathsList[0])
} }
@@ -145,7 +145,7 @@ StudioControls.Menu {
visible: root.__fileIndex visible: root.__fileIndex
height: deleteFileItem.visible ? deleteFileItem.implicitHeight : 0 height: deleteFileItem.visible ? deleteFileItem.implicitHeight : 0
onTriggered: { onTriggered: {
let deleted = AssetsLibraryBackend.assetsModel.requestDeleteFiles(root.__selectedAssetPathsList) let deleted = root.assetsModel.requestDeleteFiles(root.__selectedAssetPathsList)
if (!deleted) if (!deleted)
confirmDeleteFiles.open() confirmDeleteFiles.open()
} }
@@ -182,7 +182,7 @@ StudioControls.Menu {
StudioControls.MenuItem { StudioControls.MenuItem {
text: qsTr("New Folder") text: qsTr("New Folder")
visible: AssetsLibraryBackend.assetsModel.haveFiles visible: root.assetsModel.hasFiles
height: visible ? implicitHeight : 0 height: visible ? implicitHeight : 0
NewFolderDialog { NewFolderDialog {
@@ -209,11 +209,11 @@ StudioControls.Menu {
} }
onTriggered: { onTriggered: {
if (!AssetsLibraryBackend.assetsModel.hasChildren(root.__dirIndex)) { if (!root.assetsModel.hasChildren(root.__dirIndex)) {
// NOTE: the folder may still not be empty -- it doesn't have files visible to the // NOTE: the folder may still not be empty -- it doesn't have files visible to the
// user, but that doesn't mean that there are no other files (e.g. files of unknown // user, but that doesn't mean that there are no other files (e.g. files of unknown
// types) on disk in this directory. // types) on disk in this directory.
AssetsLibraryBackend.assetsModel.deleteFolderRecursively(root.__dirIndex) root.assetsModel.deleteFolderRecursively(root.__dirIndex)
} else { } else {
confirmDeleteFolderDialog.open() confirmDeleteFolderDialog.open()
} }
@@ -222,7 +222,7 @@ StudioControls.Menu {
StudioControls.MenuItem { StudioControls.MenuItem {
text: qsTr("New Effect") text: qsTr("New Effect")
visible: rootView.canCreateEffects() visible: root.rootView.canCreateEffects()
height: visible ? implicitHeight : 0 height: visible ? implicitHeight : 0
NewEffectDialog { NewEffectDialog {
@@ -235,15 +235,22 @@ StudioControls.Menu {
} }
StudioControls.MenuItem { StudioControls.MenuItem {
text: rootView.showInGraphicalShellMsg() text: root.rootView.showInGraphicalShellMsg()
enabled: root.__showInGraphicalShellEnabled enabled: root.__showInGraphicalShellEnabled
onTriggered: { onTriggered: {
if (!root.__fileIndex || root.__selectedAssetPathsList.length > 1) if (!root.__fileIndex || root.__selectedAssetPathsList.length > 1)
rootView.showInGraphicalShell(root.__dirPath) root.rootView.showInGraphicalShell(root.__dirPath)
else else
rootView.showInGraphicalShell(root.__selectedAssetPathsList[0]) root.rootView.showInGraphicalShell(root.__selectedAssetPathsList[0])
} }
} }
StudioControls.MenuItem {
text: qsTr("Add to Content Library")
visible: root.rootView.userBundleEnabled() && root.__fileIndex && root.assetsModel.allFilePathsAreTextures(root.__selectedAssetPathsList)
height: visible ? implicitHeight : 0
onTriggered: root.rootView.addAssetsToContentLibrary(root.__selectedAssetPathsList)
}
} }

View File

@@ -70,9 +70,9 @@ TreeView {
model: assetsModel model: assetsModel
onRowsChanged: { onRowsChanged: {
if (root.rows > root.rootPathRow + 1 && !assetsModel.haveFiles || if (root.rows > root.rootPathRow + 1 && !assetsModel.hasFiles ||
root.rows <= root.rootPathRow + 1 && assetsModel.haveFiles) { root.rows <= root.rootPathRow + 1 && assetsModel.hasFiles) {
assetsModel.syncHaveFiles() assetsModel.syncHasFiles()
} }
root.updateRows() root.updateRows()
@@ -366,7 +366,7 @@ TreeView {
function moveSelection(amount) function moveSelection(amount)
{ {
if (!assetsModel.haveFiles || !amount) if (!assetsModel.hasFiles || !amount)
return return
let index = root.currentFilePath ? assetsModel.indexForPath(root.currentFilePath) let index = root.currentFilePath ? assetsModel.indexForPath(root.currentFilePath)

View File

@@ -2,9 +2,8 @@
// 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
#include "assetslibraryiconprovider.h" #include "assetslibraryiconprovider.h"
#include "asset.h"
#include "modelnodeoperations.h"
#include <modelnodeoperations.h>
#include <theme.h> #include <theme.h>
#include <utils/hdrimage.h> #include <utils/hdrimage.h>
#include <utils/ktximage.h> #include <utils/ktximage.h>

View File

@@ -3,12 +3,11 @@
#pragma once #pragma once
#include <asset.h>
#include <synchronousimagecache.h> #include <synchronousimagecache.h>
#include <QQuickImageProvider> #include <QQuickImageProvider>
#include "asset.h"
namespace QmlDesigner { namespace QmlDesigner {
struct Thumbnail struct Thumbnail

View File

@@ -1,21 +1,19 @@
// Copyright (C) 2022 The Qt Company Ltd. // Copyright (C) 2022 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
#include <QCheckBox>
#include <QFileInfo>
#include <QFileSystemModel>
#include <QMessageBox>
#include <QSortFilterProxyModel>
#include "asset.h"
#include "assetslibrarymodel.h" #include "assetslibrarymodel.h"
#include <asset.h>
#include <modelnodeoperations.h> #include <modelnodeoperations.h>
#include <qmldesignerplugin.h> #include <qmldesignerplugin.h>
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/qtcassert.h> #include <utils/filesystemwatcher.h>
#include <QFileInfo>
#include <QFileSystemModel>
#include <QMessageBox>
namespace QmlDesigner { namespace QmlDesigner {
@@ -38,7 +36,7 @@ void AssetsLibraryModel::createBackendModel()
QObject::connect(m_sourceFsModel, &QFileSystemModel::directoryLoaded, this, QObject::connect(m_sourceFsModel, &QFileSystemModel::directoryLoaded, this,
[this]([[maybe_unused]] const QString &dir) { [this]([[maybe_unused]] const QString &dir) {
syncHaveFiles(); syncHasFiles();
}); });
m_fileWatcher = new Utils::FileSystemWatcher(parent()); m_fileWatcher = new Utils::FileSystemWatcher(parent());
@@ -207,7 +205,7 @@ bool AssetsLibraryModel::filterAcceptsRow(int sourceRow, const QModelIndex &sour
} }
} }
bool AssetsLibraryModel::checkHaveFiles(const QModelIndex &parentIdx) const bool AssetsLibraryModel::checkHasFiles(const QModelIndex &parentIdx) const
{ {
if (!parentIdx.isValid()) if (!parentIdx.isValid())
return false; return false;
@@ -218,30 +216,30 @@ bool AssetsLibraryModel::checkHaveFiles(const QModelIndex &parentIdx) const
if (!isDirectory(newIdx)) if (!isDirectory(newIdx))
return true; return true;
if (checkHaveFiles(newIdx)) if (checkHasFiles(newIdx))
return true; return true;
} }
return false; return false;
} }
void AssetsLibraryModel::setHaveFiles(bool value) void AssetsLibraryModel::setHasFiles(bool value)
{ {
if (m_haveFiles != value) { if (m_hasFiles != value) {
m_haveFiles = value; m_hasFiles = value;
emit haveFilesChanged(); emit hasFilesChanged();
} }
} }
bool AssetsLibraryModel::checkHaveFiles() const bool AssetsLibraryModel::checkHasFiles() const
{ {
auto rootIdx = indexForPath(m_rootPath); auto rootIdx = indexForPath(m_rootPath);
return checkHaveFiles(rootIdx); return checkHasFiles(rootIdx);
} }
void AssetsLibraryModel::syncHaveFiles() void AssetsLibraryModel::syncHasFiles()
{ {
setHaveFiles(checkHaveFiles()); setHasFiles(checkHasFiles());
} }
QString AssetsLibraryModel::getUniqueName(const QString &oldName) { QString AssetsLibraryModel::getUniqueName(const QString &oldName) {

View File

@@ -3,12 +3,13 @@
#pragma once #pragma once
#include <QFileInfo>
#include <QFileSystemModel>
#include <QSortFilterProxyModel> #include <QSortFilterProxyModel>
#include <utils/filesystemwatcher.h> namespace Utils {
#include <utils/qtcassert.h> class FileSystemWatcher;
}
QT_FORWARD_DECLARE_CLASS(QFileSystemModel)
namespace QmlDesigner { namespace QmlDesigner {
@@ -22,7 +23,7 @@ public:
void setRootPath(const QString &newPath); void setRootPath(const QString &newPath);
void setSearchText(const QString &searchText); void setSearchText(const QString &searchText);
Q_PROPERTY(bool haveFiles READ haveFiles NOTIFY haveFilesChanged); Q_PROPERTY(bool hasFiles READ hasFiles NOTIFY hasFilesChanged)
Q_INVOKABLE QString rootPath() const; Q_INVOKABLE QString rootPath() const;
Q_INVOKABLE QString filePath(const QModelIndex &index) const; Q_INVOKABLE QString filePath(const QModelIndex &index) const;
@@ -35,7 +36,7 @@ public:
Q_INVOKABLE QModelIndex parentDirIndex(const QString &path) const; Q_INVOKABLE QModelIndex parentDirIndex(const QString &path) const;
Q_INVOKABLE QModelIndex parentDirIndex(const QModelIndex &index) const; Q_INVOKABLE QModelIndex parentDirIndex(const QModelIndex &index) const;
Q_INVOKABLE QString parentDirPath(const QString &path) const; Q_INVOKABLE QString parentDirPath(const QString &path) const;
Q_INVOKABLE void syncHaveFiles(); Q_INVOKABLE void syncHasFiles();
Q_INVOKABLE QList<QModelIndex> parentIndices(const QModelIndex &index) const; Q_INVOKABLE QList<QModelIndex> parentIndices(const QModelIndex &index) const;
Q_INVOKABLE bool indexIsValid(const QModelIndex &index) const; Q_INVOKABLE bool indexIsValid(const QModelIndex &index) const;
@@ -55,30 +56,30 @@ public:
return std::min(result, 1); return std::min(result, 1);
} }
bool haveFiles() const { return m_haveFiles; } bool hasFiles() const { return m_hasFiles; }
QString getUniqueName(const QString &oldName); QString getUniqueName(const QString &oldName);
signals: signals:
void directoryLoaded(const QString &path); void directoryLoaded(const QString &path);
void rootPathChanged(); void rootPathChanged();
void haveFilesChanged(); void hasFilesChanged();
void fileChanged(const QString &path); void fileChanged(const QString &path);
void effectsDeleted(const QStringList &effectNames); void effectsDeleted(const QStringList &effectNames);
private: private:
void setHaveFiles(bool value); void setHasFiles(bool value);
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
void resetModel(); void resetModel();
void createBackendModel(); void createBackendModel();
void destroyBackendModel(); void destroyBackendModel();
bool checkHaveFiles(const QModelIndex &parentIdx) const; bool checkHasFiles(const QModelIndex &parentIdx) const;
bool checkHaveFiles() const; bool checkHasFiles() const;
QString m_searchText; QString m_searchText;
QString m_rootPath; QString m_rootPath;
QFileSystemModel *m_sourceFsModel = nullptr; QFileSystemModel *m_sourceFsModel = nullptr;
bool m_haveFiles = false; bool m_hasFiles = false;
Utils::FileSystemWatcher *m_fileWatcher = nullptr; Utils::FileSystemWatcher *m_fileWatcher = nullptr;
}; };

View File

@@ -3,20 +3,22 @@
#include "assetslibrarywidget.h" #include "assetslibrarywidget.h"
#include "asset.h"
#include "assetslibraryiconprovider.h" #include "assetslibraryiconprovider.h"
#include "assetslibrarymodel.h" #include "assetslibrarymodel.h"
#include "assetslibraryview.h" #include "assetslibraryview.h"
#include "designeractionmanager.h"
#include "import.h"
#include "modelnodeoperations.h"
#include "nodemetainfo.h"
#include "qmldesignerconstants.h"
#include "qmldesignerplugin.h"
#include "theme.h"
#include <utils3d.h>
#include <asset.h>
#include <designeractionmanager.h>
#include <designerpaths.h>
#include <hdrimage.h>
#include <import.h>
#include <modelnodeoperations.h>
#include <nodemetainfo.h>
#include <qmldesignerconstants.h>
#include <qmldesignerplugin.h>
#include <studioquickwidget.h> #include <studioquickwidget.h>
#include <theme.h>
#include <utils3d.h>
#include <coreplugin/fileutils.h> #include <coreplugin/fileutils.h>
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
@@ -376,7 +378,7 @@ QList<QToolButton *> AssetsLibraryWidget::createToolBarWidgets()
void AssetsLibraryWidget::handleSearchFilterChanged(const QString &filterText) void AssetsLibraryWidget::handleSearchFilterChanged(const QString &filterText)
{ {
if (filterText == m_filterText || (!m_assetsModel->haveFiles() if (filterText == m_filterText || (!m_assetsModel->hasFiles()
&& filterText.contains(m_filterText, Qt::CaseInsensitive))) && filterText.contains(m_filterText, Qt::CaseInsensitive)))
return; return;
@@ -645,4 +647,15 @@ void AssetsLibraryWidget::addResources(const QStringList &files, bool showDialog
} }
} }
bool AssetsLibraryWidget::userBundleEnabled() const
{
// TODO: this method is to be removed after user bundle implementation is complete
return Core::ICore::settings()->value("QML/Designer/UseExperimentalFeatures45", false).toBool();
}
void AssetsLibraryWidget::addAssetsToContentLibrary(const QStringList &assetPaths)
{
m_assetsView->emitCustomNotification("add_assets_to_content_lib", {}, {assetPaths});
}
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -98,6 +98,8 @@ public:
Q_INVOKABLE void showInGraphicalShell(const QString &path); Q_INVOKABLE void showInGraphicalShell(const QString &path);
Q_INVOKABLE QString showInGraphicalShellMsg() const; Q_INVOKABLE QString showInGraphicalShellMsg() const;
Q_INVOKABLE bool userBundleEnabled() const;
Q_INVOKABLE void addAssetsToContentLibrary(const QStringList &assetPaths);
signals: signals:
void itemActivated(const QString &itemName); void itemActivated(const QString &itemName);

View File

@@ -94,7 +94,30 @@ void ContentLibraryUserModel::addMaterial(const QString &name, const QString &qm
m_userMaterials.append(libMat); m_userMaterials.append(libMat);
int matSectionIdx = 0; int matSectionIdx = 0;
emit dataChanged(index(matSectionIdx, 0), index(matSectionIdx, 0)); emit dataChanged(index(matSectionIdx), index(matSectionIdx));
}
void ContentLibraryUserModel::addTextures(const QStringList &paths)
{
QDir bundleDir{Paths::bundlesPathSetting() + "/User/textures"};
bundleDir.mkpath(".");
bundleDir.mkdir("icons");
for (const QString &path : paths) {
QFileInfo fileInfo(path);
QString suffix = '.' + fileInfo.suffix();
auto iconFileInfo = QFileInfo(fileInfo.path().append("/icons/").append(fileInfo.baseName() + ".png"));
QPair<QSize, qint64> info = ImageUtils::imageInfo(path);
QString dirPath = fileInfo.path();
QSize imgDims = info.first;
qint64 imgFileSize = info.second;
auto tex = new ContentLibraryTexture(this, iconFileInfo, dirPath, suffix, imgDims, imgFileSize);
m_userTextures.append(tex);
}
int texSectionIdx = 1;
emit dataChanged(index(texSectionIdx), index(texSectionIdx));
} }
// returns unique library material's name and qml component // returns unique library material's name and qml component
@@ -273,10 +296,10 @@ void ContentLibraryUserModel::loadTextureBundle()
const QFileInfoList fileInfos = bundleDir.entryInfoList(QDir::Files); const QFileInfoList fileInfos = bundleDir.entryInfoList(QDir::Files);
for (const QFileInfo &fileInfo : fileInfos) { for (const QFileInfo &fileInfo : fileInfos) {
auto iconFileInfo = QFileInfo(fileInfo.path().append("/icons/").append(fileInfo.fileName())); QString suffix = '.' + fileInfo.suffix();
auto iconFileInfo = QFileInfo(fileInfo.path().append("/icons/").append(fileInfo.baseName() + ".png"));
QPair<QSize, qint64> info = ImageUtils::imageInfo(fileInfo.path()); QPair<QSize, qint64> info = ImageUtils::imageInfo(fileInfo.path());
QString dirPath = fileInfo.path(); QString dirPath = fileInfo.path();
QString suffix = '.' + fileInfo.suffix();
QSize imgDims = info.first; QSize imgDims = info.first;
qint64 imgFileSize = info.second; qint64 imgFileSize = info.second;

View File

@@ -62,6 +62,7 @@ public:
void updateIsEmpty(); void updateIsEmpty();
void addMaterial(const QString &name, const QString &qml, const QUrl &icon, const QStringList &files); void addMaterial(const QString &name, const QString &qml, const QUrl &icon, const QStringList &files);
void addTextures(const QStringList &paths);
void setBundleObj(const QJsonObject &newBundleObj); void setBundleObj(const QJsonObject &newBundleObj);
QJsonObject &bundleJsonObjectRef(); QJsonObject &bundleJsonObjectRef();

View File

@@ -397,6 +397,8 @@ void ContentLibraryView::customNotification(const AbstractView *view,
QTC_ASSERT(nodeList.size() == 1 && data.size() == 1, return); QTC_ASSERT(nodeList.size() == 1 && data.size() == 1, return);
addLibMaterial(nodeList.first(), data.first().value<QPixmap>()); addLibMaterial(nodeList.first(), data.first().value<QPixmap>());
} else if (identifier == "add_assets_to_content_lib") {
addLibAssets(data.first().toStringList());
} }
} }
@@ -655,6 +657,33 @@ QPair<QString, QSet<QString>> ContentLibraryView::modelNodeToQmlString(const Mod
return {qml, assets}; return {qml, assets};
} }
void ContentLibraryView::addLibAssets(const QStringList &paths)
{
auto bundlePath = Utils::FilePath::fromString(Paths::bundlesPathSetting() + "/User/textures");
QStringList pathsInBundle;
for (const QString &path : paths) {
Asset asset(path);
auto assetPath = Utils::FilePath::fromString(path);
// save icon
QString iconSavePath = bundlePath.pathAppended("icons/" + assetPath.baseName() + ".png").toString();
QPixmap icon = asset.pixmap({120, 120});
bool iconSaved = icon.save(iconSavePath);
if (!iconSaved)
qWarning() << __FUNCTION__ << "icon save failed";
// save asset
auto result = assetPath.copyFile(bundlePath.pathAppended(asset.fileName()));
if (!result)
qWarning() << __FUNCTION__ << result.error();
pathsInBundle.append(bundlePath.pathAppended(asset.fileName()).toString());
}
m_widget->userModel()->addTextures(pathsInBundle);
}
ModelNode ContentLibraryView::getBundleMaterialDefaultInstance(const TypeName &type) ModelNode ContentLibraryView::getBundleMaterialDefaultInstance(const TypeName &type)
{ {
ModelNode matLib = Utils3D::materialLibraryNode(this); ModelNode matLib = Utils3D::materialLibraryNode(this);

View File

@@ -55,6 +55,7 @@ private:
void updateBundleEffectsImportedState(); void updateBundleEffectsImportedState();
void updateBundlesQuick3DVersion(); void updateBundlesQuick3DVersion();
void addLibMaterial(const ModelNode &mat, const QPixmap &icon); void addLibMaterial(const ModelNode &mat, const QPixmap &icon);
void addLibAssets(const QStringList &paths);
QStringList writeLibMaterialQml(const ModelNode &mat, const QString &qml); QStringList writeLibMaterialQml(const ModelNode &mat, const QString &qml);
QPair<QString, QSet<QString>> modelNodeToQmlString(const ModelNode &node, QStringList &depListIds, QPair<QString, QSet<QString>> modelNodeToQmlString(const ModelNode &node, QStringList &depListIds,
int depth = 0); int depth = 0);

View File

@@ -3,7 +3,10 @@
#include "asset.h" #include "asset.h"
#include "hdrimage.h"
#include <QImageReader> #include <QImageReader>
#include <QPixmap>
namespace QmlDesigner { namespace QmlDesigner {
@@ -106,6 +109,19 @@ bool Asset::isSupported(const QString &path)
return supportedSuffixes().contains(path); return supportedSuffixes().contains(path);
} }
QPixmap Asset::pixmap(const QSize &size) const
{
if (!isImage() && !isHdrFile())
return {};
QPixmap icon = isHdrFile() ? HdrImage{m_filePath}.toPixmap() : QPixmap{m_filePath};
if (size.isValid())
icon = icon.scaled(size, Qt::KeepAspectRatio);
return icon;
}
Asset::Type Asset::type() const Asset::Type Asset::type() const
{ {
return m_type; return m_type;

View File

@@ -3,8 +3,11 @@
#pragma once #pragma once
#include <QSize>
#include <QString> #include <QString>
QT_FORWARD_DECLARE_CLASS(QPixmap)
namespace QmlDesigner { namespace QmlDesigner {
class Asset class Asset
@@ -39,6 +42,7 @@ public:
const QString id() const; const QString id() const;
const QString fileName() const; const QString fileName() const;
bool hasSuffix() const; bool hasSuffix() const;
QPixmap pixmap(const QSize &size = {}) const;
Type type() const; Type type() const;
bool isImage() const; bool isImage() const;