forked from qt-creator/qt-creator
QmlDesigner: Refactor out ContentLibraryMaterial from user bundle
Some tweaks and refactoring to get rid of ContentLibraryMaterial in the user section of the content library. The end goal is to unify the code for handling all Qml components in the user section (materials, 3d components, effects, 2D components. etc). Change-Id: I99d4fb64dae0b52265994ce478525e574e4bc658 Reviewed-by: Ali Kianian <ali.kianian@qt.io> Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
This commit is contained in:
@@ -2,9 +2,8 @@
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import HelperWidgets
|
||||
import QtQuick.Controls
|
||||
import HelperWidgets as HelperWidgets
|
||||
import StudioTheme as StudioTheme
|
||||
import ContentLibraryBackend
|
||||
|
||||
@@ -12,18 +11,20 @@ Item {
|
||||
id: root
|
||||
|
||||
signal showContextMenu()
|
||||
signal addToProject()
|
||||
|
||||
visible: modelData.bundleItemVisible
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
|
||||
enabled: !ContentLibraryBackend.rootView.importerRunning
|
||||
hoverEnabled: true
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
|
||||
onPressed: (mouse) => {
|
||||
if (mouse.button === Qt.LeftButton && !ContentLibraryBackend.rootView.importerRunning)
|
||||
if (mouse.button === Qt.LeftButton)
|
||||
ContentLibraryBackend.rootView.startDragItem(modelData, mapToGlobal(mouse.x, mouse.y))
|
||||
else if (mouse.button === Qt.RightButton)
|
||||
root.showContextMenu()
|
||||
@@ -67,6 +68,26 @@ Item {
|
||||
hoverEnabled: true
|
||||
}
|
||||
}
|
||||
|
||||
HelperWidgets.IconButton {
|
||||
id: addToProjectButton
|
||||
|
||||
icon: StudioTheme.Constants.plus
|
||||
tooltip: qsTr("Add an instance to project")
|
||||
buttonSize: 22
|
||||
property color c: "white"
|
||||
normalColor: Qt.hsla(c.hslHue, c.hslSaturation, c.hslLightness, .2)
|
||||
hoverColor: Qt.hsla(c.hslHue, c.hslSaturation, c.hslLightness, .3)
|
||||
pressColor: Qt.hsla(c.hslHue, c.hslSaturation, c.hslLightness, .4)
|
||||
anchors.right: img.right
|
||||
anchors.bottom: img.bottom
|
||||
enabled: !ContentLibraryBackend.rootView.importerRunning
|
||||
visible: containsMouse || mouseArea.containsMouse
|
||||
|
||||
onClicked: {
|
||||
root.addToProject()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
|
@@ -3,8 +3,7 @@
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import HelperWidgets
|
||||
import HelperWidgets as HelperWidgets
|
||||
import StudioTheme as StudioTheme
|
||||
import ContentLibraryBackend
|
||||
import WebFetcher
|
||||
@@ -12,9 +11,9 @@ import WebFetcher
|
||||
Item {
|
||||
id: root
|
||||
|
||||
// Download states: "" (ie default, not downloaded), "unavailable", "downloading", "downloaded",
|
||||
// "failed"
|
||||
property string downloadState: modelData.isDownloaded() ? "downloaded" : ""
|
||||
// Download states: "" (exists not downloaded), "unavailable", "downloading", "downloaded", "failed"
|
||||
property string downloadState: ContentLibraryBackend.materialsModel.isMaterialDownloaded(modelData)
|
||||
? "downloaded" : ""
|
||||
|
||||
signal showContextMenu()
|
||||
signal addToProject()
|
||||
@@ -24,20 +23,18 @@ Item {
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
|
||||
enabled: root.downloadState !== "downloading"
|
||||
enabled: !ContentLibraryBackend.rootView.importerRunning && root.downloadState == "downloaded"
|
||||
hoverEnabled: true
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
|
||||
onPressed: (mouse) => {
|
||||
if (mouse.button === Qt.LeftButton && !ContentLibraryBackend.rootView.importerRunning) {
|
||||
if (root.downloadState === "downloaded")
|
||||
if (mouse.button === Qt.LeftButton)
|
||||
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.showContextMenu()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
@@ -87,7 +84,7 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
IconButton {
|
||||
HelperWidgets.IconButton {
|
||||
icon: StudioTheme.Constants.plus
|
||||
tooltip: qsTr("Add an instance to project")
|
||||
buttonSize: 22
|
||||
@@ -106,7 +103,7 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
IconButton {
|
||||
HelperWidgets.IconButton {
|
||||
id: downloadIcon
|
||||
icon: root.downloadState === "unavailable"
|
||||
? StudioTheme.Constants.downloadUnavailable
|
||||
@@ -181,10 +178,10 @@ Item {
|
||||
MultiFileDownloader {
|
||||
id: downloader
|
||||
|
||||
baseUrl: modelData.bundleMaterialBaseWebUrl
|
||||
baseUrl: ContentLibraryBackend.materialsModel.baseWebUrl
|
||||
files: modelData.bundleMaterialFiles
|
||||
|
||||
targetDirPath: modelData.bundleMaterialDirPath
|
||||
targetDirPath: ContentLibraryBackend.materialsModel.bundlePath
|
||||
|
||||
onDownloadStarting: {
|
||||
root.downloadState = "downloading"
|
||||
|
@@ -106,7 +106,7 @@ HelperWidgets.ScrollView {
|
||||
|
||||
DelegateChoice {
|
||||
roleValue: "material"
|
||||
ContentLibraryMaterial {
|
||||
ContentLibraryItem {
|
||||
width: root.cellWidth
|
||||
height: root.cellHeight
|
||||
|
||||
@@ -124,7 +124,7 @@ HelperWidgets.ScrollView {
|
||||
}
|
||||
}
|
||||
DelegateChoice {
|
||||
roleValue: "item"
|
||||
roleValue: "3d"
|
||||
delegate: ContentLibraryItem {
|
||||
width: root.cellWidth
|
||||
height: root.cellHeight
|
||||
|
@@ -171,17 +171,14 @@ void ContentLibraryEffectsModel::loadBundle()
|
||||
TypeName type = QLatin1String("%1.%2")
|
||||
.arg(bundleType, qml.chopped(4)).toLatin1(); // chopped(4): remove .qml
|
||||
|
||||
auto bundleItem = new ContentLibraryItem(category, itemName, qml, type, icon, files);
|
||||
auto bundleItem = new ContentLibraryItem(category, itemName, qml, type, icon, files, "effect");
|
||||
|
||||
category->addBundleItem(bundleItem);
|
||||
}
|
||||
m_bundleCategories.append(category);
|
||||
}
|
||||
|
||||
m_bundleSharedFiles.clear();
|
||||
const QJsonArray sharedFilesArr = m_bundleObj.value("sharedFiles").toArray();
|
||||
for (const QJsonValueConstRef &file : sharedFilesArr)
|
||||
m_bundleSharedFiles.append(file.toString());
|
||||
m_bundleSharedFiles = m_bundleObj.value("sharedFiles").toVariant().toStringList();
|
||||
|
||||
m_bundlePath = bundleDir.path();
|
||||
m_bundleExists = true;
|
||||
|
@@ -10,8 +10,10 @@ ContentLibraryItem::ContentLibraryItem(QObject *parent,
|
||||
const QString &qml,
|
||||
const TypeName &type,
|
||||
const QUrl &icon,
|
||||
const QStringList &files)
|
||||
: QObject(parent), m_name(name), m_qml(qml), m_type(type), m_icon(icon), m_files(files)
|
||||
const QStringList &files,
|
||||
const QString &itemType)
|
||||
: QObject(parent), m_name(name), m_qml(qml), m_type(type), m_icon(icon), m_files(files),
|
||||
m_itemType(itemType)
|
||||
{
|
||||
m_allFiles = m_files;
|
||||
m_allFiles.push_back(m_qml);
|
||||
@@ -73,4 +75,9 @@ QStringList ContentLibraryItem::allFiles() const
|
||||
return m_allFiles;
|
||||
}
|
||||
|
||||
QString ContentLibraryItem::itemType() const
|
||||
{
|
||||
return m_itemType;
|
||||
}
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
@@ -19,7 +19,7 @@ class ContentLibraryItem : public QObject
|
||||
Q_PROPERTY(QStringList bundleItemFiles READ allFiles CONSTANT)
|
||||
Q_PROPERTY(bool bundleItemVisible MEMBER m_visible NOTIFY itemVisibleChanged)
|
||||
Q_PROPERTY(bool bundleItemImported READ imported WRITE setImported NOTIFY itemImportedChanged)
|
||||
Q_PROPERTY(QString itemType MEMBER m_itemType CONSTANT)
|
||||
Q_PROPERTY(QString itemType READ itemType CONSTANT)
|
||||
|
||||
public:
|
||||
ContentLibraryItem(QObject *parent,
|
||||
@@ -27,7 +27,8 @@ public:
|
||||
const QString &qml,
|
||||
const TypeName &type,
|
||||
const QUrl &icon,
|
||||
const QStringList &files);
|
||||
const QStringList &files,
|
||||
const QString &itemType);
|
||||
|
||||
bool filter(const QString &searchText);
|
||||
|
||||
@@ -37,6 +38,8 @@ public:
|
||||
QStringList files() const;
|
||||
bool visible() const;
|
||||
|
||||
QString itemType() const;
|
||||
|
||||
bool setImported(bool imported);
|
||||
bool imported() const;
|
||||
QStringList allFiles() const;
|
||||
@@ -56,7 +59,7 @@ private:
|
||||
bool m_imported = false;
|
||||
|
||||
QStringList m_allFiles;
|
||||
const QString m_itemType = "item";
|
||||
const QString m_itemType;
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
@@ -3,8 +3,6 @@
|
||||
|
||||
#include "contentlibrarymaterial.h"
|
||||
|
||||
#include <QFileInfo>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
ContentLibraryMaterial::ContentLibraryMaterial(QObject *parent,
|
||||
@@ -12,11 +10,8 @@ ContentLibraryMaterial::ContentLibraryMaterial(QObject *parent,
|
||||
const QString &qml,
|
||||
const TypeName &type,
|
||||
const QUrl &icon,
|
||||
const QStringList &files,
|
||||
const QString &downloadPath,
|
||||
const QString &baseWebUrl)
|
||||
const QStringList &files)
|
||||
: QObject(parent), m_name(name), m_qml(qml), m_type(type), m_icon(icon), m_files(files)
|
||||
, m_downloadPath(downloadPath), m_baseWebUrl(baseWebUrl)
|
||||
{
|
||||
m_allFiles = m_files;
|
||||
m_allFiles.push_back(m_qml);
|
||||
@@ -78,22 +73,6 @@ bool ContentLibraryMaterial::imported() const
|
||||
return m_imported;
|
||||
}
|
||||
|
||||
bool ContentLibraryMaterial::isDownloaded() const
|
||||
{
|
||||
QString fullPath = qmlFilePath();
|
||||
return QFileInfo(fullPath).isFile();
|
||||
}
|
||||
|
||||
QString ContentLibraryMaterial::qmlFilePath() const
|
||||
{
|
||||
return m_downloadPath + "/" + m_qml;
|
||||
}
|
||||
|
||||
QString ContentLibraryMaterial::dirPath() const
|
||||
{
|
||||
return m_downloadPath;
|
||||
}
|
||||
|
||||
QStringList ContentLibraryMaterial::allFiles() const
|
||||
{
|
||||
return m_allFiles;
|
||||
|
@@ -18,8 +18,6 @@ class ContentLibraryMaterial : public QObject
|
||||
Q_PROPERTY(QUrl bundleMaterialIcon MEMBER m_icon CONSTANT)
|
||||
Q_PROPERTY(bool bundleMaterialVisible MEMBER m_visible NOTIFY materialVisibleChanged)
|
||||
Q_PROPERTY(bool bundleItemImported READ imported WRITE setImported NOTIFY materialImportedChanged)
|
||||
Q_PROPERTY(QString bundleMaterialBaseWebUrl MEMBER m_baseWebUrl CONSTANT)
|
||||
Q_PROPERTY(QString bundleMaterialDirPath READ dirPath CONSTANT)
|
||||
Q_PROPERTY(QStringList bundleMaterialFiles READ allFiles CONSTANT)
|
||||
Q_PROPERTY(QString itemType MEMBER m_itemType CONSTANT)
|
||||
|
||||
@@ -29,25 +27,19 @@ public:
|
||||
const QString &qml,
|
||||
const TypeName &type,
|
||||
const QUrl &icon,
|
||||
const QStringList &files,
|
||||
const QString &downloadPath,
|
||||
const QString &baseWebUrl = {});
|
||||
const QStringList &files);
|
||||
|
||||
bool filter(const QString &searchText);
|
||||
|
||||
Q_INVOKABLE bool isDownloaded() const;
|
||||
|
||||
QString name() const;
|
||||
QUrl icon() const;
|
||||
QString qml() const;
|
||||
TypeName type() const;
|
||||
QStringList files() const;
|
||||
bool visible() const;
|
||||
QString qmlFilePath() const;
|
||||
|
||||
bool setImported(bool imported);
|
||||
bool imported() const;
|
||||
QString dirPath() const;
|
||||
QStringList allFiles() const;
|
||||
|
||||
signals:
|
||||
@@ -64,8 +56,6 @@ private:
|
||||
bool m_visible = true;
|
||||
bool m_imported = false;
|
||||
|
||||
QString m_downloadPath;
|
||||
QString m_baseWebUrl;
|
||||
QStringList m_allFiles;
|
||||
const QString m_itemType = "material";
|
||||
};
|
||||
|
@@ -19,7 +19,6 @@
|
||||
#include <utils/hostosinfo.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDir>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
@@ -33,7 +32,7 @@ ContentLibraryMaterialsModel::ContentLibraryMaterialsModel(ContentLibraryWidget
|
||||
: QAbstractListModel(parent)
|
||||
, m_widget(parent)
|
||||
{
|
||||
m_downloadPath = Paths::bundlesPathSetting() + "/Materials";
|
||||
m_bundlePath = Utils::FilePath::fromString(Paths::bundlesPathSetting() + "/Materials");
|
||||
|
||||
m_baseUrl = QmlDesignerPlugin::settings()
|
||||
.value(DesignerSettingsKey::DOWNLOADABLE_BUNDLES_URL)
|
||||
@@ -45,9 +44,8 @@ ContentLibraryMaterialsModel::ContentLibraryMaterialsModel(ContentLibraryWidget
|
||||
|
||||
void ContentLibraryMaterialsModel::loadBundle()
|
||||
{
|
||||
QDir bundleDir{m_downloadPath};
|
||||
if (fetchBundleMetadata(bundleDir) && fetchBundleIcons(bundleDir))
|
||||
loadMaterialBundle(bundleDir);
|
||||
if (fetchBundleMetadata() && fetchBundleIcons())
|
||||
loadMaterialBundle();
|
||||
}
|
||||
|
||||
int ContentLibraryMaterialsModel::rowCount(const QModelIndex &) const
|
||||
@@ -114,13 +112,14 @@ QHash<int, QByteArray> ContentLibraryMaterialsModel::roleNames() const
|
||||
return roles;
|
||||
}
|
||||
|
||||
bool ContentLibraryMaterialsModel::fetchBundleIcons(const QDir &bundleDir)
|
||||
bool ContentLibraryMaterialsModel::fetchBundleIcons()
|
||||
{
|
||||
QString iconsPath = bundleDir.filePath("icons");
|
||||
Utils::FilePath iconsFilePath = m_bundlePath.pathAppended("icons");
|
||||
|
||||
QDir iconsDir(iconsPath);
|
||||
if (iconsDir.exists() && iconsDir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot).length() > 0)
|
||||
if (iconsFilePath.exists() && iconsFilePath.dirEntries(QDir::Files | QDir::Dirs
|
||||
| QDir::NoDotAndDotDot).length() > 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
QString zipFileUrl = m_baseUrl + "/icons.zip";
|
||||
|
||||
@@ -130,20 +129,20 @@ bool ContentLibraryMaterialsModel::fetchBundleIcons(const QDir &bundleDir)
|
||||
downloader->setDownloadEnabled(true);
|
||||
|
||||
QObject::connect(downloader, &FileDownloader::finishedChanged, this,
|
||||
[this, downloader, bundleDir] {
|
||||
[this, downloader] {
|
||||
FileExtractor *extractor = new FileExtractor(this);
|
||||
extractor->setArchiveName(downloader->completeBaseName());
|
||||
extractor->setSourceFile(downloader->outputFile());
|
||||
extractor->setTargetPath(bundleDir.absolutePath());
|
||||
extractor->setTargetPath(m_bundlePath.toFSPathString());
|
||||
extractor->setAlwaysCreateDir(false);
|
||||
extractor->setClearTargetPathContents(false);
|
||||
|
||||
QObject::connect(extractor, &FileExtractor::finishedChanged, this,
|
||||
[this, downloader, bundleDir, extractor] {
|
||||
[this, downloader, extractor] {
|
||||
downloader->deleteLater();
|
||||
extractor->deleteLater();
|
||||
|
||||
loadMaterialBundle(bundleDir);
|
||||
loadMaterialBundle();
|
||||
});
|
||||
|
||||
extractor->extract();
|
||||
@@ -153,12 +152,11 @@ bool ContentLibraryMaterialsModel::fetchBundleIcons(const QDir &bundleDir)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ContentLibraryMaterialsModel::fetchBundleMetadata(const QDir &bundleDir)
|
||||
bool ContentLibraryMaterialsModel::fetchBundleMetadata()
|
||||
{
|
||||
QString matBundlePath = bundleDir.filePath("material_bundle.json");
|
||||
Utils::FilePath jsonFilePath = m_bundlePath.pathAppended("material_bundle.json");
|
||||
|
||||
QFileInfo fi(matBundlePath);
|
||||
if (fi.exists() && fi.size() > 0)
|
||||
if (jsonFilePath.exists() && jsonFilePath.fileSize() > 0)
|
||||
return true;
|
||||
|
||||
QString metaFileUrl = m_baseUrl + "/material_bundle.json";
|
||||
@@ -166,12 +164,12 @@ bool ContentLibraryMaterialsModel::fetchBundleMetadata(const QDir &bundleDir)
|
||||
downloader->setUrl(metaFileUrl);
|
||||
downloader->setProbeUrl(false);
|
||||
downloader->setDownloadEnabled(true);
|
||||
downloader->setTargetFilePath(matBundlePath);
|
||||
downloader->setTargetFilePath(m_bundlePath.toFSPathString());
|
||||
|
||||
QObject::connect(downloader, &FileDownloader::finishedChanged, this,
|
||||
[this, downloader, bundleDir] {
|
||||
if (fetchBundleIcons(bundleDir))
|
||||
loadMaterialBundle(bundleDir);
|
||||
[this, downloader] {
|
||||
if (fetchBundleIcons())
|
||||
loadMaterialBundle();
|
||||
downloader->deleteLater();
|
||||
});
|
||||
|
||||
@@ -179,7 +177,7 @@ bool ContentLibraryMaterialsModel::fetchBundleMetadata(const QDir &bundleDir)
|
||||
return false;
|
||||
}
|
||||
|
||||
void ContentLibraryMaterialsModel::downloadSharedFiles(const QDir &targetDir, const QStringList &)
|
||||
void ContentLibraryMaterialsModel::downloadSharedFiles()
|
||||
{
|
||||
QString metaFileUrl = m_baseUrl + "/shared_files.zip";
|
||||
FileDownloader *downloader = new FileDownloader(this);
|
||||
@@ -188,11 +186,11 @@ void ContentLibraryMaterialsModel::downloadSharedFiles(const QDir &targetDir, co
|
||||
downloader->setDownloadEnabled(true);
|
||||
|
||||
QObject::connect(downloader, &FileDownloader::finishedChanged, this,
|
||||
[this, downloader, targetDir] {
|
||||
[this, downloader] {
|
||||
FileExtractor *extractor = new FileExtractor(this);
|
||||
extractor->setArchiveName(downloader->completeBaseName());
|
||||
extractor->setSourceFile(downloader->outputFile());
|
||||
extractor->setTargetPath(targetDir.absolutePath());
|
||||
extractor->setTargetPath(m_bundlePath.toFSPathString());
|
||||
extractor->setAlwaysCreateDir(false);
|
||||
extractor->setClearTargetPathContents(false);
|
||||
|
||||
@@ -212,7 +210,7 @@ QString ContentLibraryMaterialsModel::bundleId() const
|
||||
return m_bundleId;
|
||||
}
|
||||
|
||||
void ContentLibraryMaterialsModel::loadMaterialBundle(const QDir &bundleDir)
|
||||
void ContentLibraryMaterialsModel::loadMaterialBundle()
|
||||
{
|
||||
auto compUtils = QmlDesignerPlugin::instance()->documentManager().generatedComponentUtils();
|
||||
|
||||
@@ -227,18 +225,18 @@ void ContentLibraryMaterialsModel::loadMaterialBundle(const QDir &bundleDir)
|
||||
m_bundleObj = {};
|
||||
m_bundleId.clear();
|
||||
|
||||
QString bundlePath = bundleDir.filePath("material_bundle.json");
|
||||
Utils::FilePath jsonFilePath = m_bundlePath.pathAppended("material_bundle.json");
|
||||
|
||||
QFile bundleFile(bundlePath);
|
||||
if (!bundleFile.open(QIODevice::ReadOnly)) {
|
||||
qWarning("Couldn't open material_bundle.json");
|
||||
Utils::expected_str<QByteArray> jsonContents = jsonFilePath.fileContents();
|
||||
if (!jsonContents.has_value()) {
|
||||
qWarning() << __FUNCTION__ << jsonContents.error();
|
||||
resetModel();
|
||||
return;
|
||||
}
|
||||
|
||||
QJsonDocument bundleJsonDoc = QJsonDocument::fromJson(bundleFile.readAll());
|
||||
QJsonDocument bundleJsonDoc = QJsonDocument::fromJson(jsonContents.value());
|
||||
if (bundleJsonDoc.isNull()) {
|
||||
qWarning("Invalid material_bundle.json file");
|
||||
qWarning() << __FUNCTION__ << "Invalid json file" << jsonFilePath;
|
||||
resetModel();
|
||||
return;
|
||||
}
|
||||
@@ -263,32 +261,24 @@ void ContentLibraryMaterialsModel::loadMaterialBundle(const QDir &bundleDir)
|
||||
for (const QJsonValueConstRef &asset : assetsArr)
|
||||
files.append(asset.toString());
|
||||
|
||||
QUrl icon = QUrl::fromLocalFile(bundleDir.filePath(matObj.value("icon").toString()));
|
||||
QUrl icon = m_bundlePath.pathAppended(matObj.value("icon").toString()).toUrl();
|
||||
QString qml = matObj.value("qml").toString();
|
||||
TypeName type = QLatin1String("%1.%2")
|
||||
.arg(bundleType, qml.chopped(4)).toLatin1(); // chopped(4): remove .qml
|
||||
TypeName type = QLatin1String("%1.%2").arg(bundleType, qml.chopped(4)).toLatin1(); // chopped(4): remove .qml
|
||||
|
||||
auto bundleMat = new ContentLibraryMaterial(category, matName, qml, type, icon, files,
|
||||
m_downloadPath, m_baseUrl);
|
||||
auto bundleMat = new ContentLibraryMaterial(category, matName, qml, type, icon, files);
|
||||
|
||||
category->addBundleMaterial(bundleMat);
|
||||
}
|
||||
m_bundleCategories.append(category);
|
||||
}
|
||||
|
||||
m_bundleSharedFiles.clear();
|
||||
const QJsonArray sharedFilesArr = m_bundleObj.value("sharedFiles").toArray();
|
||||
for (const QJsonValueConstRef &file : sharedFilesArr)
|
||||
m_bundleSharedFiles.append(file.toString());
|
||||
|
||||
QStringList missingSharedFiles;
|
||||
for (const QString &s : std::as_const(m_bundleSharedFiles)) {
|
||||
if (!QFileInfo::exists(bundleDir.filePath(s)))
|
||||
missingSharedFiles.push_back(s);
|
||||
m_bundleSharedFiles = m_bundleObj.value("sharedFiles").toVariant().toStringList();
|
||||
for (const QString &file : std::as_const(m_bundleSharedFiles)) {
|
||||
if (!m_bundlePath.pathAppended(file).exists()) {
|
||||
downloadSharedFiles();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (missingSharedFiles.length() > 0)
|
||||
downloadSharedFiles(bundleDir, missingSharedFiles);
|
||||
|
||||
m_bundleExists = true;
|
||||
updateIsEmpty();
|
||||
@@ -305,6 +295,11 @@ bool ContentLibraryMaterialsModel::matBundleExists() const
|
||||
return m_bundleExists;
|
||||
}
|
||||
|
||||
QString ContentLibraryMaterialsModel::bundlePath() const
|
||||
{
|
||||
return m_bundlePath.toFSPathString();
|
||||
}
|
||||
|
||||
void ContentLibraryMaterialsModel::setSearchText(const QString &searchText)
|
||||
{
|
||||
QString lowerSearchText = searchText.toLower();
|
||||
@@ -364,8 +359,8 @@ void ContentLibraryMaterialsModel::applyToSelected(ContentLibraryMaterial *mat,
|
||||
|
||||
void ContentLibraryMaterialsModel::addToProject(ContentLibraryMaterial *mat)
|
||||
{
|
||||
QString err = m_widget->importer()->importComponent(mat->dirPath(), mat->type(), mat->qml(),
|
||||
mat->files() + m_bundleSharedFiles);
|
||||
QString err = m_widget->importer()->importComponent(m_bundlePath.toFSPathString(), mat->type(),
|
||||
mat->qml(), mat->files() + m_bundleSharedFiles);
|
||||
|
||||
if (err.isEmpty())
|
||||
m_widget->setImporterRunning(true);
|
||||
@@ -383,4 +378,9 @@ void ContentLibraryMaterialsModel::removeFromProject(ContentLibraryMaterial *mat
|
||||
qWarning() << __FUNCTION__ << err;
|
||||
}
|
||||
|
||||
bool ContentLibraryMaterialsModel::isMaterialDownloaded(ContentLibraryMaterial *mat) const
|
||||
{
|
||||
return m_bundlePath.pathAppended(mat->qml()).exists();
|
||||
}
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
@@ -3,11 +3,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <utils/filepath.h>
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QJsonObject>
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QDir)
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
class ContentLibraryMaterial;
|
||||
@@ -21,6 +21,8 @@ class ContentLibraryMaterialsModel : public QAbstractListModel
|
||||
Q_PROPERTY(bool matBundleExists READ matBundleExists NOTIFY matBundleExistsChanged)
|
||||
Q_PROPERTY(bool isEmpty MEMBER m_isEmpty NOTIFY isEmptyChanged)
|
||||
Q_PROPERTY(bool hasRequiredQuick3DImport READ hasRequiredQuick3DImport NOTIFY hasRequiredQuick3DImportChanged)
|
||||
Q_PROPERTY(QString baseWebUrl MEMBER m_baseUrl CONSTANT)
|
||||
Q_PROPERTY(QString bundlePath READ bundlePath CONSTANT)
|
||||
|
||||
public:
|
||||
ContentLibraryMaterialsModel(ContentLibraryWidget *parent = nullptr);
|
||||
@@ -37,6 +39,8 @@ public:
|
||||
bool hasRequiredQuick3DImport() const;
|
||||
bool matBundleExists() const;
|
||||
|
||||
QString bundlePath() const;
|
||||
|
||||
void resetModel();
|
||||
void updateIsEmpty();
|
||||
void loadBundle();
|
||||
@@ -44,6 +48,7 @@ public:
|
||||
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 bool isMaterialDownloaded(QmlDesigner::ContentLibraryMaterial *mat) const;
|
||||
|
||||
QString bundleId() const;
|
||||
|
||||
@@ -55,11 +60,11 @@ signals:
|
||||
void matBundleExistsChanged();
|
||||
|
||||
private:
|
||||
void loadMaterialBundle(const QDir &matBundleDir);
|
||||
bool fetchBundleIcons(const QDir &bundleDir);
|
||||
bool fetchBundleMetadata(const QDir &bundleDir);
|
||||
void loadMaterialBundle();
|
||||
bool fetchBundleIcons();
|
||||
bool fetchBundleMetadata();
|
||||
bool isValidIndex(int idx) const;
|
||||
void downloadSharedFiles(const QDir &targetDir, const QStringList &files);
|
||||
void downloadSharedFiles();
|
||||
|
||||
ContentLibraryWidget *m_widget = nullptr;
|
||||
QString m_searchText;
|
||||
@@ -74,7 +79,7 @@ private:
|
||||
int m_quick3dMajorVersion = -1;
|
||||
int m_quick3dMinorVersion = -1;
|
||||
|
||||
QString m_downloadPath;
|
||||
Utils::FilePath m_bundlePath;
|
||||
QString m_baseUrl;
|
||||
};
|
||||
|
||||
|
@@ -5,8 +5,6 @@
|
||||
|
||||
#include "contentlibrarybundleimporter.h"
|
||||
#include "contentlibraryitem.h"
|
||||
#include "contentlibrarymaterial.h"
|
||||
#include "contentlibrarymaterialscategory.h"
|
||||
#include "contentlibrarytexture.h"
|
||||
#include "contentlibrarywidget.h"
|
||||
|
||||
@@ -84,7 +82,7 @@ QVariant ContentLibraryUserModel::data(const QModelIndex &index, int role) const
|
||||
|
||||
void ContentLibraryUserModel::updateNoMatchMaterials()
|
||||
{
|
||||
m_noMatchMaterials = Utils::allOf(m_userMaterials, [&](ContentLibraryMaterial *item) {
|
||||
m_noMatchMaterials = Utils::allOf(m_userMaterials, [&](ContentLibraryItem *item) {
|
||||
return !item->visible();
|
||||
});
|
||||
}
|
||||
@@ -111,8 +109,7 @@ void ContentLibraryUserModel::addMaterial(const QString &name, const QString &qm
|
||||
QString typePrefix = compUtils.userMaterialsBundleType();
|
||||
TypeName type = QLatin1String("%1.%2").arg(typePrefix, qml.chopped(4)).toLatin1();
|
||||
|
||||
auto libMat = new ContentLibraryMaterial(this, name, qml, type, icon, files,
|
||||
Paths::bundlesPathSetting().append("/User/materials"));
|
||||
auto libMat = new ContentLibraryItem(this, name, qml, type, icon, files, "material");
|
||||
m_userMaterials.append(libMat);
|
||||
|
||||
emit dataChanged(index(MaterialsSectionIdx), index(MaterialsSectionIdx));
|
||||
@@ -126,7 +123,7 @@ void ContentLibraryUserModel::add3DItem(const QString &name, const QString &qml,
|
||||
QString typePrefix = compUtils.user3DBundleType();
|
||||
TypeName type = QLatin1String("%1.%2").arg(typePrefix, qml.chopped(4)).toLatin1();
|
||||
|
||||
m_user3DItems.append(new ContentLibraryItem(this, name, qml, type, icon, files));
|
||||
m_user3DItems.append(new ContentLibraryItem(this, name, qml, type, icon, files, "3d"));
|
||||
}
|
||||
|
||||
void ContentLibraryUserModel::refreshSection(SectionIndex sectionIndex)
|
||||
@@ -184,20 +181,20 @@ void ContentLibraryUserModel::removeTexture(ContentLibraryTexture *tex)
|
||||
|
||||
void ContentLibraryUserModel::removeFromContentLib(QObject *item)
|
||||
{
|
||||
if (auto mat = qobject_cast<ContentLibraryMaterial *>(item))
|
||||
removeMaterialFromContentLib(mat);
|
||||
else if (auto itm = qobject_cast<ContentLibraryItem *>(item))
|
||||
remove3DFromContentLib(itm);
|
||||
auto castedItem = qobject_cast<ContentLibraryItem *>(item);
|
||||
|
||||
if (castedItem->itemType() == "material")
|
||||
removeMaterialFromContentLib(castedItem);
|
||||
else if (castedItem->itemType() == "3d")
|
||||
remove3DFromContentLib(castedItem);
|
||||
}
|
||||
|
||||
void ContentLibraryUserModel::removeMaterialFromContentLib(ContentLibraryMaterial *item)
|
||||
void ContentLibraryUserModel::removeMaterialFromContentLib(ContentLibraryItem *item)
|
||||
{
|
||||
auto bundlePath = Utils::FilePath::fromString(Paths::bundlesPathSetting() + "/User/materials/");
|
||||
|
||||
QJsonArray itemsArr = m_bundleObjMaterial.value("items").toArray();
|
||||
|
||||
// remove qml and icon files
|
||||
Utils::FilePath::fromString(item->qmlFilePath()).removeFile();
|
||||
m_bundlePathMaterial.pathAppended(item->qml()).removeFile();
|
||||
Utils::FilePath::fromUrl(item->icon()).removeFile();
|
||||
|
||||
// remove from the bundle json file
|
||||
@@ -209,7 +206,7 @@ void ContentLibraryUserModel::removeMaterialFromContentLib(ContentLibraryMateria
|
||||
}
|
||||
m_bundleObjMaterial.insert("items", itemsArr);
|
||||
|
||||
auto result = bundlePath.pathAppended(Constants::BUNDLE_JSON_FILENAME)
|
||||
auto result = m_bundlePathMaterial.pathAppended(Constants::BUNDLE_JSON_FILENAME)
|
||||
.writeFileContents(QJsonDocument(m_bundleObjMaterial).toJson());
|
||||
if (!result)
|
||||
qWarning() << __FUNCTION__ << result.error();
|
||||
@@ -222,7 +219,7 @@ void ContentLibraryUserModel::removeMaterialFromContentLib(ContentLibraryMateria
|
||||
const QStringList itemFiles = item->files();
|
||||
for (const QString &file : itemFiles) {
|
||||
if (allFiles.count(file) == 0) // only used by the deleted item
|
||||
bundlePath.pathAppended(file).removeFile();
|
||||
m_bundlePathMaterial.pathAppended(file).removeFile();
|
||||
}
|
||||
|
||||
// remove from model
|
||||
@@ -246,8 +243,8 @@ void ContentLibraryUserModel::remove3DFromContentLibByName(const QString &qmlFil
|
||||
|
||||
void ContentLibraryUserModel::removeMaterialFromContentLibByName(const QString &qmlFileName)
|
||||
{
|
||||
ContentLibraryMaterial *itemToRemove = Utils::findOr(m_userMaterials, nullptr,
|
||||
[&qmlFileName](ContentLibraryMaterial *item) {
|
||||
ContentLibraryItem *itemToRemove = Utils::findOr(m_userMaterials, nullptr,
|
||||
[&qmlFileName](ContentLibraryItem *item) {
|
||||
return item->qml() == qmlFileName;
|
||||
});
|
||||
|
||||
@@ -435,13 +432,9 @@ void ContentLibraryUserModel::loadMaterialBundle()
|
||||
QString qml = itemObj.value("qml").toString();
|
||||
TypeName type = QLatin1String("%1.%2").arg(typePrefix, qml.chopped(4)).toLatin1();
|
||||
QUrl icon = m_bundlePathMaterial.pathAppended(itemObj.value("icon").toString()).toUrl();
|
||||
QStringList files;
|
||||
const QJsonArray assetsArr = itemObj.value("files").toArray();
|
||||
for (const QJsonValueConstRef &asset : assetsArr)
|
||||
files.append(asset.toString());
|
||||
QStringList files = itemObj.value("files").toVariant().toStringList();
|
||||
|
||||
m_userMaterials.append(new ContentLibraryMaterial(this, name, qml, type, icon, files,
|
||||
m_bundlePathMaterial.path(), ""));
|
||||
m_userMaterials.append(new ContentLibraryItem(this, name, qml, type, icon, files, "material"));
|
||||
}
|
||||
|
||||
m_bundleMaterialSharedFiles.clear();
|
||||
@@ -515,12 +508,9 @@ void ContentLibraryUserModel::load3DBundle()
|
||||
QString qml = itemObj.value("qml").toString();
|
||||
TypeName type = QLatin1String("%1.%2").arg(typePrefix, qml.chopped(4)).toLatin1();
|
||||
QUrl icon = m_bundlePath3D.pathAppended(itemObj.value("icon").toString()).toUrl();
|
||||
QStringList files;
|
||||
const QJsonArray assetsArr = itemObj.value("files").toArray();
|
||||
for (const QJsonValueConstRef &asset : assetsArr)
|
||||
files.append(asset.toString());
|
||||
QStringList files = itemObj.value("files").toVariant().toStringList();
|
||||
|
||||
m_user3DItems.append(new ContentLibraryItem(nullptr, name, qml, type, icon, files));
|
||||
m_user3DItems.append(new ContentLibraryItem(nullptr, name, qml, type, icon, files, "3d"));
|
||||
}
|
||||
|
||||
m_bundle3DSharedFiles.clear();
|
||||
@@ -578,7 +568,7 @@ void ContentLibraryUserModel::setSearchText(const QString &searchText)
|
||||
|
||||
m_searchText = lowerSearchText;
|
||||
|
||||
for (ContentLibraryMaterial *item : std::as_const(m_userMaterials))
|
||||
for (ContentLibraryItem *item : std::as_const(m_userMaterials))
|
||||
item->filter(m_searchText);
|
||||
|
||||
for (ContentLibraryTexture *item : std::as_const(m_userTextures))
|
||||
@@ -596,7 +586,7 @@ void ContentLibraryUserModel::setSearchText(const QString &searchText)
|
||||
void ContentLibraryUserModel::updateMaterialsImportedState(const QStringList &importedItems)
|
||||
{
|
||||
bool changed = false;
|
||||
for (ContentLibraryMaterial *mat : std::as_const(m_userMaterials))
|
||||
for (ContentLibraryItem *mat : std::as_const(m_userMaterials))
|
||||
changed |= mat->setImported(importedItems.contains(mat->qml().chopped(4)));
|
||||
|
||||
if (changed)
|
||||
@@ -634,27 +624,25 @@ void ContentLibraryUserModel::resetModel()
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void ContentLibraryUserModel::applyToSelected(ContentLibraryMaterial *mat, bool add)
|
||||
void ContentLibraryUserModel::applyToSelected(ContentLibraryItem *mat, bool add)
|
||||
{
|
||||
emit applyToSelectedTriggered(mat, add);
|
||||
}
|
||||
|
||||
void ContentLibraryUserModel::addToProject(QObject *item)
|
||||
{
|
||||
auto castedItem = qobject_cast<ContentLibraryItem *>(item);
|
||||
QString bundleDir;
|
||||
TypeName type;
|
||||
QString qmlFile;
|
||||
QStringList files;
|
||||
if (auto mat = qobject_cast<ContentLibraryMaterial *>(item)) {
|
||||
bundleDir = mat->dirPath();
|
||||
type = mat->type();
|
||||
qmlFile = mat->qml();
|
||||
files = mat->files() + m_bundleMaterialSharedFiles;
|
||||
} else if (auto itm = qobject_cast<ContentLibraryItem *>(item)) {
|
||||
bundleDir = m_bundlePath3D.toString();
|
||||
type = itm->type();
|
||||
qmlFile = itm->qml();
|
||||
files = itm->files() + m_bundle3DSharedFiles;
|
||||
TypeName type = castedItem->type();
|
||||
QString qmlFile = castedItem->qml();
|
||||
QStringList files = castedItem->files();
|
||||
|
||||
if (castedItem->itemType() == "material") {
|
||||
bundleDir = m_bundlePathMaterial.toFSPathString();
|
||||
files << m_bundleMaterialSharedFiles;
|
||||
} else if (castedItem->itemType() == "3d") {
|
||||
bundleDir = m_bundlePath3D.toFSPathString();
|
||||
files << m_bundle3DSharedFiles;
|
||||
} else {
|
||||
qWarning() << __FUNCTION__ << "Unsupported Item";
|
||||
return;
|
||||
@@ -670,20 +658,8 @@ void ContentLibraryUserModel::addToProject(QObject *item)
|
||||
|
||||
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);
|
||||
auto castedItem = qobject_cast<ContentLibraryItem *>(item);
|
||||
QString err = m_widget->importer()->unimportComponent(castedItem->type(), castedItem->qml());
|
||||
|
||||
if (err.isEmpty())
|
||||
m_widget->setImporterRunning(true);
|
||||
|
@@ -13,7 +13,6 @@ QT_FORWARD_DECLARE_CLASS(QUrl)
|
||||
namespace QmlDesigner {
|
||||
|
||||
class ContentLibraryItem;
|
||||
class ContentLibraryMaterial;
|
||||
class ContentLibraryTexture;
|
||||
class ContentLibraryWidget;
|
||||
class NodeMetaInfo;
|
||||
@@ -25,7 +24,7 @@ class ContentLibraryUserModel : public QAbstractListModel
|
||||
Q_PROPERTY(bool matBundleExists READ matBundleExists NOTIFY matBundleExistsChanged)
|
||||
Q_PROPERTY(bool bundle3DExists MEMBER m_bundle3DExists NOTIFY bundle3DExistsChanged)
|
||||
Q_PROPERTY(bool hasRequiredQuick3DImport READ hasRequiredQuick3DImport NOTIFY hasRequiredQuick3DImportChanged)
|
||||
Q_PROPERTY(QList<ContentLibraryMaterial *> userMaterials MEMBER m_userMaterials NOTIFY userMaterialsChanged)
|
||||
Q_PROPERTY(QList<ContentLibraryItem *> userMaterials MEMBER m_userMaterials NOTIFY userMaterialsChanged)
|
||||
Q_PROPERTY(QList<ContentLibraryTexture *> userTextures MEMBER m_userTextures NOTIFY userTexturesChanged)
|
||||
Q_PROPERTY(QList<ContentLibraryItem *> user3DItems MEMBER m_user3DItems NOTIFY user3DItemsChanged)
|
||||
Q_PROPERTY(QList<ContentLibraryItem *> userEffects MEMBER m_userEffects NOTIFY userEffectsChanged)
|
||||
@@ -78,7 +77,7 @@ public:
|
||||
|
||||
void loadBundles();
|
||||
|
||||
Q_INVOKABLE void applyToSelected(QmlDesigner::ContentLibraryMaterial *mat, bool add = false);
|
||||
Q_INVOKABLE void applyToSelected(QmlDesigner::ContentLibraryItem *mat, bool add = false);
|
||||
Q_INVOKABLE void addToProject(QObject *item);
|
||||
Q_INVOKABLE void removeFromProject(QObject *item);
|
||||
Q_INVOKABLE void removeTexture(QmlDesigner::ContentLibraryTexture *tex);
|
||||
@@ -90,7 +89,7 @@ signals:
|
||||
void userTexturesChanged();
|
||||
void user3DItemsChanged();
|
||||
void userEffectsChanged();
|
||||
void applyToSelectedTriggered(QmlDesigner::ContentLibraryMaterial *mat, bool add = false);
|
||||
void applyToSelectedTriggered(QmlDesigner::ContentLibraryItem *mat, bool add = false);
|
||||
void matBundleExistsChanged();
|
||||
void bundle3DExistsChanged();
|
||||
|
||||
@@ -98,7 +97,7 @@ private:
|
||||
void loadMaterialBundle();
|
||||
void load3DBundle();
|
||||
void loadTextureBundle();
|
||||
void removeMaterialFromContentLib(ContentLibraryMaterial *mat);
|
||||
void removeMaterialFromContentLib(ContentLibraryItem *mat);
|
||||
void remove3DFromContentLib(ContentLibraryItem *item);
|
||||
|
||||
ContentLibraryWidget *m_widget = nullptr;
|
||||
@@ -110,7 +109,7 @@ private:
|
||||
Utils::FilePath m_bundlePathMaterial;
|
||||
Utils::FilePath m_bundlePath3D;
|
||||
|
||||
QList<ContentLibraryMaterial *> m_userMaterials;
|
||||
QList<ContentLibraryItem *> m_userMaterials;
|
||||
QList<ContentLibraryTexture *> m_userTextures;
|
||||
QList<ContentLibraryItem *> m_userEffects;
|
||||
QList<ContentLibraryItem *> m_user3DItems;
|
||||
|
@@ -120,7 +120,7 @@ WidgetInfo ContentLibraryView::widgetInfo()
|
||||
connect(m_widget->userModel(),
|
||||
&ContentLibraryUserModel::applyToSelectedTriggered,
|
||||
this,
|
||||
[&](ContentLibraryMaterial *bundleMat, bool add) {
|
||||
[&](ContentLibraryItem *bundleMat, bool add) {
|
||||
if (m_selectedModels.isEmpty())
|
||||
return;
|
||||
|
||||
|
@@ -84,7 +84,7 @@ bool ContentLibraryWidget::eventFilter(QObject *obj, QEvent *event)
|
||||
} else if (m_materialToDrag) {
|
||||
QMouseEvent *me = static_cast<QMouseEvent *>(event);
|
||||
if ((me->globalPosition().toPoint() - m_dragStartPoint).manhattanLength() > 20
|
||||
&& m_materialToDrag->isDownloaded()) {
|
||||
&& m_materialsModel->isMaterialDownloaded(m_materialToDrag)) {
|
||||
QByteArray data;
|
||||
QMimeData *mimeData = new QMimeData;
|
||||
QDataStream stream(&data, QIODevice::WriteOnly);
|
||||
|
Reference in New Issue
Block a user