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:
Mahmoud Badri
2024-06-11 12:05:26 +03:00
parent f6ad2b76e6
commit de5a3b696d
14 changed files with 161 additions and 187 deletions

View File

@@ -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,33 +261,25 @@ 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();
resetModel();
@@ -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