forked from qt-creator/qt-creator
QmlDesigner: Add user texture bundle
Fixes: QDS-12390 Change-Id: I512a8748bbb6a282589f05293507c110162e7f1d Reviewed-by: Qt CI Patch Build Bot <ci_patchbuild_bot@qt.io> Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
// 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
|
import QtQuick
|
||||||
|
import Qt.labs.qmlmodels
|
||||||
import HelperWidgets as HelperWidgets
|
import HelperWidgets as HelperWidgets
|
||||||
import StudioControls as StudioControls
|
import StudioControls as StudioControls
|
||||||
import StudioTheme as StudioTheme
|
import StudioTheme as StudioTheme
|
||||||
@@ -99,17 +100,33 @@ HelperWidgets.ScrollView {
|
|||||||
id: repeater
|
id: repeater
|
||||||
model: categoryItems
|
model: categoryItems
|
||||||
|
|
||||||
delegate: ContentLibraryMaterial {
|
delegate: DelegateChooser {
|
||||||
width: root.cellWidth
|
role: "itemType"
|
||||||
height: root.cellHeight
|
|
||||||
|
|
||||||
importerRunning: ContentLibraryBackend.userModel.importerRunning
|
DelegateChoice {
|
||||||
|
roleValue: "material"
|
||||||
|
ContentLibraryMaterial {
|
||||||
|
width: root.cellWidth
|
||||||
|
height: root.cellHeight
|
||||||
|
|
||||||
onShowContextMenu: ctxMenu.popupMenu(modelData)
|
importerRunning: ContentLibraryBackend.userModel.importerRunning
|
||||||
onAddToProject: ContentLibraryBackend.userModel.addToProject(modelData)
|
|
||||||
|
|
||||||
onVisibleChanged: {
|
onShowContextMenu: ctxMenu.popupMenu(modelData)
|
||||||
section.numVisibleItem += visible ? 1 : -1
|
onAddToProject: ContentLibraryBackend.userModel.addToProject(modelData)
|
||||||
|
|
||||||
|
onVisibleChanged: {
|
||||||
|
section.numVisibleItem += visible ? 1 : -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DelegateChoice {
|
||||||
|
roleValue: "texture"
|
||||||
|
delegate: ContentLibraryTexture {
|
||||||
|
width: root.cellWidth
|
||||||
|
height: root.cellHeight
|
||||||
|
|
||||||
|
// onShowContextMenu: ctxMenu.popupMenu(modelData) // TODO
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -21,6 +21,7 @@ class ContentLibraryMaterial : public QObject
|
|||||||
Q_PROPERTY(QString bundleMaterialBaseWebUrl MEMBER m_baseWebUrl CONSTANT)
|
Q_PROPERTY(QString bundleMaterialBaseWebUrl MEMBER m_baseWebUrl CONSTANT)
|
||||||
Q_PROPERTY(QString bundleMaterialParentPath READ parentDirPath CONSTANT)
|
Q_PROPERTY(QString bundleMaterialParentPath READ parentDirPath CONSTANT)
|
||||||
Q_PROPERTY(QStringList bundleMaterialFiles READ allFiles CONSTANT)
|
Q_PROPERTY(QStringList bundleMaterialFiles READ allFiles CONSTANT)
|
||||||
|
Q_PROPERTY(QString itemType MEMBER m_itemType CONSTANT)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ContentLibraryMaterial(QObject *parent,
|
ContentLibraryMaterial(QObject *parent,
|
||||||
@@ -65,6 +66,7 @@ private:
|
|||||||
QString m_downloadPath;
|
QString m_downloadPath;
|
||||||
QString m_baseWebUrl;
|
QString m_baseWebUrl;
|
||||||
QStringList m_allFiles;
|
QStringList m_allFiles;
|
||||||
|
const QString m_itemType = "material";
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
@@ -12,10 +12,10 @@
|
|||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
ContentLibraryTexture::ContentLibraryTexture(QObject *parent, const QFileInfo &iconFileInfo,
|
ContentLibraryTexture::ContentLibraryTexture(QObject *parent, const QFileInfo &iconFileInfo,
|
||||||
const QString &dirPath, const QString &key,
|
const QString &dirPath, const QString &suffix,
|
||||||
const QString &textureUrl, const QString &iconUrl,
|
const QSize &dimensions, const qint64 sizeInBytes,
|
||||||
const QString &suffix, const QSize &dimensions,
|
const QString &key, const QString &textureUrl,
|
||||||
const qint64 sizeInBytes, bool hasUpdate, bool isNew)
|
const QString &iconUrl, bool hasUpdate, bool isNew)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
, m_iconPath(iconFileInfo.filePath())
|
, m_iconPath(iconFileInfo.filePath())
|
||||||
, m_dirPath(dirPath)
|
, m_dirPath(dirPath)
|
||||||
@@ -82,10 +82,10 @@ QString ContentLibraryTexture::resolveToolTipText()
|
|||||||
QString imageInfo;
|
QString imageInfo;
|
||||||
|
|
||||||
if (!m_isDownloaded && m_sizeInBytes > 0 && !m_dimensions.isNull()) {
|
if (!m_isDownloaded && m_sizeInBytes > 0 && !m_dimensions.isNull()) {
|
||||||
imageInfo = ImageUtils::imageInfo(m_dimensions, m_sizeInBytes);
|
imageInfo = ImageUtils::imageInfoString(m_dimensions, m_sizeInBytes);
|
||||||
} else {
|
} else {
|
||||||
QString fullDownloadPath = m_dirPath + '/' + fileName;
|
QString fullDownloadPath = m_dirPath + '/' + fileName;
|
||||||
imageInfo = ImageUtils::imageInfo(fullDownloadPath);
|
imageInfo = ImageUtils::imageInfoString(fullDownloadPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
return QString("%1\n%2").arg(fileName, imageInfo);
|
return QString("%1\n%2").arg(fileName, imageInfo);
|
||||||
|
@@ -24,12 +24,13 @@ class ContentLibraryTexture : public QObject
|
|||||||
Q_PROPERTY(bool textureHasUpdate WRITE setHasUpdate READ hasUpdate NOTIFY hasUpdateChanged)
|
Q_PROPERTY(bool textureHasUpdate WRITE setHasUpdate READ hasUpdate NOTIFY hasUpdateChanged)
|
||||||
Q_PROPERTY(bool textureIsNew MEMBER m_isNew CONSTANT)
|
Q_PROPERTY(bool textureIsNew MEMBER m_isNew CONSTANT)
|
||||||
Q_PROPERTY(QString textureKey MEMBER m_textureKey CONSTANT)
|
Q_PROPERTY(QString textureKey MEMBER m_textureKey CONSTANT)
|
||||||
|
Q_PROPERTY(QString itemType MEMBER m_itemType CONSTANT)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ContentLibraryTexture(QObject *parent, const QFileInfo &iconFileInfo, const QString &dirPath,
|
ContentLibraryTexture(QObject *parent, const QFileInfo &iconFileInfo, const QString &dirPath,
|
||||||
const QString &key, const QString &textureUrl, const QString &iconUrl,
|
|
||||||
const QString &suffix, const QSize &dimensions, const qint64 sizeInBytes,
|
const QString &suffix, const QSize &dimensions, const qint64 sizeInBytes,
|
||||||
bool hasUpdate = false, bool isNew = false);
|
const QString &key = {}, const QString &textureUrl = {},
|
||||||
|
const QString &iconUrl = {}, bool hasUpdate = false, bool isNew = false);
|
||||||
|
|
||||||
Q_INVOKABLE bool isDownloaded() const;
|
Q_INVOKABLE bool isDownloaded() const;
|
||||||
Q_INVOKABLE void setDownloaded();
|
Q_INVOKABLE void setDownloaded();
|
||||||
@@ -71,6 +72,7 @@ private:
|
|||||||
bool m_visible = true;
|
bool m_visible = true;
|
||||||
bool m_hasUpdate = false;
|
bool m_hasUpdate = false;
|
||||||
bool m_isNew = false;
|
bool m_isNew = false;
|
||||||
|
const QString m_itemType = "texture";
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
@@ -21,8 +21,8 @@ void ContentLibraryTexturesCategory::addTexture(const QFileInfo &texIcon, const
|
|||||||
bool hasUpdate, bool isNew)
|
bool hasUpdate, bool isNew)
|
||||||
{
|
{
|
||||||
m_categoryTextures.append(new ContentLibraryTexture(
|
m_categoryTextures.append(new ContentLibraryTexture(
|
||||||
this, texIcon, downloadPath, key, webTextureUrl, iconUrl,
|
this, texIcon, downloadPath, suffix, dimensions, sizeInBytes,
|
||||||
suffix, dimensions, sizeInBytes, hasUpdate, isNew));
|
key, webTextureUrl, iconUrl, hasUpdate, isNew));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ContentLibraryTexturesCategory::filter(const QString &searchText)
|
bool ContentLibraryTexturesCategory::filter(const QString &searchText)
|
||||||
|
@@ -37,7 +37,7 @@ public:
|
|||||||
void setHasSceneEnv(bool b);
|
void setHasSceneEnv(bool b);
|
||||||
|
|
||||||
void resetModel();
|
void resetModel();
|
||||||
void loadTextureBundle(const QString &m_textureBundleUrl, const QString &bundlePath,
|
void loadTextureBundle(const QString &textureBundleUrl, const QString &bundlePath,
|
||||||
const QVariantMap &metaData);
|
const QVariantMap &metaData);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
@@ -6,9 +6,11 @@
|
|||||||
#include "contentlibrarybundleimporter.h"
|
#include "contentlibrarybundleimporter.h"
|
||||||
#include "contentlibrarymaterial.h"
|
#include "contentlibrarymaterial.h"
|
||||||
#include "contentlibrarymaterialscategory.h"
|
#include "contentlibrarymaterialscategory.h"
|
||||||
|
#include "contentlibrarytexture.h"
|
||||||
#include "contentlibrarywidget.h"
|
#include "contentlibrarywidget.h"
|
||||||
|
|
||||||
#include <designerpaths.h>
|
#include <designerpaths.h>
|
||||||
|
#include <imageutils.h>
|
||||||
#include <qmldesignerplugin.h>
|
#include <qmldesignerplugin.h>
|
||||||
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
@@ -16,6 +18,7 @@
|
|||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
|
#include <QFileInfo>
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QQmlEngine>
|
#include <QQmlEngine>
|
||||||
@@ -28,9 +31,10 @@ ContentLibraryUserModel::ContentLibraryUserModel(ContentLibraryWidget *parent)
|
|||||||
: QAbstractListModel(parent)
|
: QAbstractListModel(parent)
|
||||||
, m_widget(parent)
|
, m_widget(parent)
|
||||||
{
|
{
|
||||||
m_userCategories = {tr("Materials")/*, tr("Textures"), tr("3D"), tr("Effects"), tr("2D components")*/}; // TODO
|
m_userCategories = {tr("Materials"), tr("Textures")/*, tr("3D"), tr("Effects"), tr("2D components")*/}; // TODO
|
||||||
|
|
||||||
loadMaterialBundle();
|
loadMaterialBundle();
|
||||||
|
loadTextureBundle();
|
||||||
}
|
}
|
||||||
|
|
||||||
int ContentLibraryUserModel::rowCount(const QModelIndex &) const
|
int ContentLibraryUserModel::rowCount(const QModelIndex &) const
|
||||||
@@ -262,6 +266,32 @@ void ContentLibraryUserModel::loadMaterialBundle()
|
|||||||
emit matBundleExistsChanged();
|
emit matBundleExistsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ContentLibraryUserModel::loadTextureBundle()
|
||||||
|
{
|
||||||
|
if (!m_userTextures.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
QDir bundleDir{Paths::bundlesPathSetting() + "/User/textures"};
|
||||||
|
bundleDir.mkpath(".");
|
||||||
|
bundleDir.mkdir("icons");
|
||||||
|
|
||||||
|
const QFileInfoList fileInfos = bundleDir.entryInfoList(QDir::Files);
|
||||||
|
for (const QFileInfo &fileInfo : fileInfos) {
|
||||||
|
auto iconFileInfo = QFileInfo(fileInfo.path().append("/icons/").append(fileInfo.fileName()));
|
||||||
|
QPair<QSize, qint64> info = ImageUtils::imageInfo(fileInfo.path());
|
||||||
|
QString dirPath = fileInfo.path();
|
||||||
|
QString suffix = '.' + fileInfo.suffix();
|
||||||
|
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, 0), index(texSectionIdx, 0));
|
||||||
|
}
|
||||||
|
|
||||||
bool ContentLibraryUserModel::hasRequiredQuick3DImport() const
|
bool ContentLibraryUserModel::hasRequiredQuick3DImport() const
|
||||||
{
|
{
|
||||||
return m_widget->hasQuick3DImport() && m_quick3dMajorVersion == 6 && m_quick3dMinorVersion >= 3;
|
return m_widget->hasQuick3DImport() && m_quick3dMajorVersion == 6 && m_quick3dMinorVersion >= 3;
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "nodemetainfo.h"
|
#include "modelfwd.h"
|
||||||
|
|
||||||
#include <QAbstractListModel>
|
#include <QAbstractListModel>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
@@ -16,6 +16,7 @@ class ContentLibraryEffect;
|
|||||||
class ContentLibraryMaterial;
|
class ContentLibraryMaterial;
|
||||||
class ContentLibraryTexture;
|
class ContentLibraryTexture;
|
||||||
class ContentLibraryWidget;
|
class ContentLibraryWidget;
|
||||||
|
class NodeMetaInfo;
|
||||||
|
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
class ContentLibraryBundleImporter;
|
class ContentLibraryBundleImporter;
|
||||||
@@ -94,6 +95,7 @@ signals:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void loadMaterialBundle();
|
void loadMaterialBundle();
|
||||||
|
void loadTextureBundle();
|
||||||
bool isValidIndex(int idx) const;
|
bool isValidIndex(int idx) const;
|
||||||
void createImporter(const QString &bundlePath, const QString &bundleId,
|
void createImporter(const QString &bundlePath, const QString &bundleId,
|
||||||
const QStringList &sharedFiles);
|
const QStringList &sharedFiles);
|
||||||
|
@@ -63,7 +63,7 @@ QVariant MaterialBrowserTexturesModel::data(const QModelIndex &index, int role)
|
|||||||
return tr("Texture has no source image.");
|
return tr("Texture has no source image.");
|
||||||
|
|
||||||
ModelNode texNode = m_textureList.at(index.row());
|
ModelNode texNode = m_textureList.at(index.row());
|
||||||
QString info = ImageUtils::imageInfo(source);
|
QString info = ImageUtils::imageInfoString(source);
|
||||||
|
|
||||||
if (info.isEmpty())
|
if (info.isEmpty())
|
||||||
return tr("Texture has no data.");
|
return tr("Texture has no data.");
|
||||||
|
@@ -1946,7 +1946,7 @@ QVariant NodeInstanceView::previewImageDataForImageNode(const ModelNode &modelNo
|
|||||||
imageData.pixmap = originalPixmap.scaled(dim, dim, Qt::KeepAspectRatio);
|
imageData.pixmap = originalPixmap.scaled(dim, dim, Qt::KeepAspectRatio);
|
||||||
imageData.pixmap.setDevicePixelRatio(ratio);
|
imageData.pixmap.setDevicePixelRatio(ratio);
|
||||||
imageData.time = modified;
|
imageData.time = modified;
|
||||||
imageData.info = ImageUtils::imageInfo(imageSource);
|
imageData.info = ImageUtils::imageInfoString(imageSource);
|
||||||
m_imageDataMap.insert(imageData.id, imageData);
|
m_imageDataMap.insert(imageData.id, imageData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
QString ImageUtils::imageInfo(const QSize &dimensions, qint64 sizeInBytes)
|
QString ImageUtils::imageInfoString(const QSize &dimensions, qint64 sizeInBytes)
|
||||||
{
|
{
|
||||||
return QLatin1String("%1 x %2\n%3")
|
return QLatin1String("%1 x %2\n%3")
|
||||||
.arg(QString::number(dimensions.width()),
|
.arg(QString::number(dimensions.width()),
|
||||||
@@ -20,7 +20,7 @@ QString ImageUtils::imageInfo(const QSize &dimensions, qint64 sizeInBytes)
|
|||||||
sizeInBytes, 2, QLocale::DataSizeTraditionalFormat));
|
sizeInBytes, 2, QLocale::DataSizeTraditionalFormat));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QmlDesigner::ImageUtils::imageInfo(const QString &path)
|
QPair<QSize, qint64> QmlDesigner::ImageUtils::imageInfo(const QString &path)
|
||||||
{
|
{
|
||||||
QFileInfo info(path);
|
QFileInfo info(path);
|
||||||
if (!info.exists())
|
if (!info.exists())
|
||||||
@@ -52,7 +52,13 @@ QString QmlDesigner::ImageUtils::imageInfo(const QString &path)
|
|||||||
if (width <= 0 || height <= 0)
|
if (width <= 0 || height <= 0)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
return imageInfo(QSize(width, height), info.size());
|
return {QSize(width, height), info.size()};
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ImageUtils::imageInfoString(const QString &path)
|
||||||
|
{
|
||||||
|
QPair<QSize, qint64> info = imageInfo(path);
|
||||||
|
return imageInfoString(info.first, info.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
@@ -12,8 +12,9 @@ class ImageUtils
|
|||||||
public:
|
public:
|
||||||
ImageUtils();
|
ImageUtils();
|
||||||
|
|
||||||
static QString imageInfo(const QSize &dimensions, qint64 sizeInBytes);
|
static QPair<QSize, qint64> imageInfo(const QString &path);
|
||||||
static QString imageInfo(const QString &path);
|
static QString imageInfoString(const QString &path);
|
||||||
|
static QString imageInfoString(const QSize &dimensions, qint64 sizeInBytes);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
Reference in New Issue
Block a user