forked from qt-creator/qt-creator
Download icons and metadata of textures at startup
Task-number: QDS-9397 Change-Id: If1bb4a5500896b70b4a9dbb82d2122c1232ee744 Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io> Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
This commit is contained in:
@@ -114,7 +114,7 @@ bool ContentLibraryMaterialsModel::fetchBundleIcons(const QDir &bundleDir)
|
||||
QString iconsPath = bundleDir.filePath("icons");
|
||||
|
||||
QDir iconsDir(iconsPath);
|
||||
if (iconsDir.exists() && iconsDir.entryList().length() > 0)
|
||||
if (iconsDir.exists() && iconsDir.entryList(QDir::NoDotAndDotDot).length() > 0)
|
||||
return true;
|
||||
|
||||
QString zipFileUrl = m_baseUrl + "/icons.zip";
|
||||
|
@@ -6,9 +6,6 @@
|
||||
#include "contentlibrarytexturescategory.h"
|
||||
#include "qmldesignerplugin.h"
|
||||
|
||||
#include "utils/filedownloader.h"
|
||||
#include "utils/fileextractor.h"
|
||||
|
||||
#include <qmldesignerbase/qmldesignerbaseplugin.h>
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
@@ -18,6 +15,7 @@
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QJsonDocument>
|
||||
#include <QQmlEngine>
|
||||
#include <QSize>
|
||||
#include <QStandardPaths>
|
||||
@@ -28,9 +26,6 @@ namespace QmlDesigner {
|
||||
ContentLibraryTexturesModel::ContentLibraryTexturesModel(const QString &category, QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
{
|
||||
qmlRegisterType<QmlDesigner::FileDownloader>("WebFetcher", 1, 0, "FileDownloader");
|
||||
qmlRegisterType<QmlDesigner::FileExtractor>("WebFetcher", 1, 0, "FileExtractor");
|
||||
|
||||
m_category = category; // textures main category (ex: Textures, Environments)
|
||||
}
|
||||
|
||||
@@ -103,28 +98,24 @@ QHash<int, QByteArray> ContentLibraryTexturesModel::roleNames() const
|
||||
* @param bundlePath local path to the bundle folder and icons
|
||||
* @param metaData bundle textures metadata
|
||||
*/
|
||||
void ContentLibraryTexturesModel::loadTextureBundle(const QString &bundlePath, const QVariantMap &metaData)
|
||||
void ContentLibraryTexturesModel::loadTextureBundle(const QString &remoteUrl, const QString &bundleIconPath,
|
||||
const QVariantMap &metaData)
|
||||
{
|
||||
if (!m_bundleCategories.isEmpty())
|
||||
return;
|
||||
|
||||
QDir bundleDir = QString("%1/%2").arg(bundlePath, m_category);
|
||||
QDir bundleDir = QString("%1/%2").arg(bundleIconPath, m_category);
|
||||
if (!bundleDir.exists()) {
|
||||
qWarning() << __FUNCTION__ << "textures bundle folder doesn't exist." << bundlePath;
|
||||
qWarning() << __FUNCTION__ << "textures bundle folder doesn't exist." << bundleDir.absolutePath();
|
||||
return;
|
||||
}
|
||||
|
||||
QString remoteBaseUrl = QmlDesignerPlugin::settings()
|
||||
.value(DesignerSettingsKey::DOWNLOADABLE_BUNDLES_URL).toString()
|
||||
+ "/textures/" + m_category;
|
||||
|
||||
const QFileInfoList dirs = bundleDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
|
||||
for (const QFileInfo &dir : dirs) {
|
||||
auto category = new ContentLibraryTexturesCategory(this, dir.fileName());
|
||||
const QFileInfoList texFiles = QDir(dir.filePath() + "/icon").entryInfoList(QDir::Files);
|
||||
const QFileInfoList texFiles = QDir(dir.filePath()).entryInfoList(QDir::Files);
|
||||
for (const QFileInfo &tex : texFiles) {
|
||||
|
||||
QString fullRemoteUrl = QString("%1/%2/%3.zip").arg(remoteBaseUrl, dir.fileName(),
|
||||
QString fullRemoteUrl = QString("%1/%2/%3.zip").arg(remoteUrl, dir.fileName(),
|
||||
tex.baseName());
|
||||
QString localDownloadPath = QString("%1/%2/%3").arg(QmlDesignerBasePlugin::bundlesPathSetting(),
|
||||
m_category, dir.fileName());
|
||||
@@ -145,6 +136,7 @@ void ContentLibraryTexturesModel::loadTextureBundle(const QString &bundlePath, c
|
||||
m_bundleCategories.append(category);
|
||||
}
|
||||
|
||||
resetModel();
|
||||
updateIsEmpty();
|
||||
}
|
||||
|
||||
|
@@ -33,7 +33,8 @@ public:
|
||||
void setHasSceneEnv(bool b);
|
||||
|
||||
void resetModel();
|
||||
void loadTextureBundle(const QString &bundlePath, const QVariantMap &metaData);
|
||||
void loadTextureBundle(const QString &remoteUrl, const QString &bundlePath,
|
||||
const QVariantMap &metaData);
|
||||
|
||||
signals:
|
||||
void isEmptyChanged();
|
||||
|
@@ -8,6 +8,9 @@
|
||||
#include "contentlibrarytexture.h"
|
||||
#include "contentlibrarytexturesmodel.h"
|
||||
|
||||
#include "utils/filedownloader.h"
|
||||
#include "utils/fileextractor.h"
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <qmldesignerconstants.h>
|
||||
#include <qmldesignerplugin.h>
|
||||
@@ -19,6 +22,7 @@
|
||||
#include <utils/hostosinfo.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QDir>
|
||||
#include <QJsonDocument>
|
||||
#include <QMimeData>
|
||||
#include <QMouseEvent>
|
||||
@@ -32,6 +36,8 @@
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
constexpr int TextureBundleMetadataVersion = 1;
|
||||
|
||||
static QString propertyEditorResourcesPath()
|
||||
{
|
||||
#ifdef SHARE_QML_PATH
|
||||
@@ -98,6 +104,9 @@ ContentLibraryWidget::ContentLibraryWidget()
|
||||
, m_texturesModel(new ContentLibraryTexturesModel("Textures", this))
|
||||
, m_environmentsModel(new ContentLibraryTexturesModel("Environments", this))
|
||||
{
|
||||
qmlRegisterType<QmlDesigner::FileDownloader>("WebFetcher", 1, 0, "FileDownloader");
|
||||
qmlRegisterType<QmlDesigner::FileExtractor>("WebFetcher", 1, 0, "FileExtractor");
|
||||
|
||||
setWindowTitle(tr("Content Library", "Title of content library widget"));
|
||||
setMinimumWidth(120);
|
||||
|
||||
@@ -106,15 +115,17 @@ ContentLibraryWidget::ContentLibraryWidget()
|
||||
m_quickWidget->engine()->addImportPath(propertyEditorResourcesPath() + "/imports");
|
||||
m_quickWidget->setClearColor(Theme::getColor(Theme::Color::DSpanelBackground));
|
||||
|
||||
QString textureBundlePath = findTextureBundlePath();
|
||||
m_baseUrl = QmlDesignerPlugin::settings()
|
||||
.value(DesignerSettingsKey::DOWNLOADABLE_BUNDLES_URL).toString()
|
||||
+ "/textures/v1";
|
||||
|
||||
QVariantMap metaData;
|
||||
QFile jsonFile(textureBundlePath + "/texture_bundle.json");
|
||||
if (jsonFile.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||
metaData = QJsonDocument::fromJson(jsonFile.readAll()).toVariant().toMap();
|
||||
m_texturesUrl = m_baseUrl + "/Textures";
|
||||
m_environmentsUrl = m_baseUrl + "/Environments";
|
||||
|
||||
m_texturesModel->loadTextureBundle(textureBundlePath, metaData);
|
||||
m_environmentsModel->loadTextureBundle(textureBundlePath, metaData);
|
||||
m_downloadPath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)
|
||||
+ "/QtDesignStudio/bundles";
|
||||
|
||||
loadTextureBundle();
|
||||
|
||||
Theme::setupTheme(m_quickWidget->engine());
|
||||
m_quickWidget->quickWidget()->installEventFilter(this);
|
||||
@@ -144,6 +155,115 @@ ContentLibraryWidget::ContentLibraryWidget()
|
||||
reloadQmlSource();
|
||||
}
|
||||
|
||||
QVariantMap ContentLibraryWidget::readBundleMetadata()
|
||||
{
|
||||
QVariantMap metaData;
|
||||
QFile jsonFile(m_downloadPath + "/texture_bundle.json");
|
||||
if (jsonFile.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||
metaData = QJsonDocument::fromJson(jsonFile.readAll()).toVariant().toMap();
|
||||
|
||||
int version = metaData["version"].toInt();
|
||||
if (version != TextureBundleMetadataVersion) {
|
||||
qWarning() << "Unrecognized texture metadata file version: " << version;
|
||||
return {};
|
||||
}
|
||||
|
||||
return metaData;
|
||||
}
|
||||
|
||||
void ContentLibraryWidget::loadTextureBundle()
|
||||
{
|
||||
QDir bundleDir{m_downloadPath};
|
||||
|
||||
if (fetchTextureBundleMetadata(bundleDir) && fetchTextureBundleIcons(bundleDir)) {
|
||||
QString bundleIconPath = m_downloadPath + "/TextureBundleIcons";
|
||||
QVariantMap metaData = readBundleMetadata();
|
||||
m_texturesModel->loadTextureBundle(m_texturesUrl, bundleIconPath, metaData);
|
||||
m_environmentsModel->loadTextureBundle(m_environmentsUrl, bundleIconPath, metaData);
|
||||
}
|
||||
}
|
||||
|
||||
bool ContentLibraryWidget::fetchTextureBundleMetadata(const QDir &bundleDir)
|
||||
{
|
||||
QString filePath = bundleDir.filePath("texture_bundle.json");
|
||||
|
||||
QFileInfo fi(filePath);
|
||||
if (fi.exists() && fi.size() > 0)
|
||||
return true;
|
||||
|
||||
QString metaFileUrl = m_baseUrl + "/texture_bundle.zip";
|
||||
FileDownloader *downloader = new FileDownloader(this);
|
||||
downloader->setUrl(metaFileUrl);
|
||||
downloader->setProbeUrl(false);
|
||||
downloader->setDownloadEnabled(true);
|
||||
|
||||
QObject::connect(downloader, &FileDownloader::finishedChanged, this, [=]() {
|
||||
FileExtractor *extractor = new FileExtractor(this);
|
||||
extractor->setArchiveName(downloader->completeBaseName());
|
||||
extractor->setSourceFile(downloader->outputFile());
|
||||
extractor->setTargetPath(bundleDir.absolutePath());
|
||||
extractor->setAlwaysCreateDir(false);
|
||||
extractor->setClearTargetPathContents(false);
|
||||
|
||||
QObject::connect(extractor, &FileExtractor::finishedChanged, this, [=]() {
|
||||
downloader->deleteLater();
|
||||
extractor->deleteLater();
|
||||
|
||||
if (fetchTextureBundleIcons(bundleDir)) {
|
||||
QString bundleIconPath = m_downloadPath + "/TextureBundleIcons";
|
||||
QVariantMap metaData = readBundleMetadata();
|
||||
m_texturesModel->loadTextureBundle(m_texturesUrl, bundleIconPath, metaData);
|
||||
m_environmentsModel->loadTextureBundle(m_environmentsUrl, bundleIconPath, metaData);
|
||||
}
|
||||
});
|
||||
|
||||
extractor->extract();
|
||||
});
|
||||
|
||||
downloader->start();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ContentLibraryWidget::fetchTextureBundleIcons(const QDir &bundleDir)
|
||||
{
|
||||
QString iconsPath = bundleDir.filePath("TextureBundleIcons");
|
||||
|
||||
QDir iconsDir(iconsPath);
|
||||
if (iconsDir.exists() && iconsDir.entryList(QDir::NoDotAndDotDot).length() > 0)
|
||||
return true;
|
||||
|
||||
QString zipFileUrl = m_baseUrl + "/icons.zip";
|
||||
|
||||
FileDownloader *downloader = new FileDownloader(this);
|
||||
downloader->setUrl(zipFileUrl);
|
||||
downloader->setProbeUrl(false);
|
||||
downloader->setDownloadEnabled(true);
|
||||
|
||||
QObject::connect(downloader, &FileDownloader::finishedChanged, this, [=]() {
|
||||
FileExtractor *extractor = new FileExtractor(this);
|
||||
extractor->setArchiveName(downloader->completeBaseName());
|
||||
extractor->setSourceFile(downloader->outputFile());
|
||||
extractor->setTargetPath(bundleDir.absolutePath());
|
||||
extractor->setAlwaysCreateDir(false);
|
||||
extractor->setClearTargetPathContents(false);
|
||||
|
||||
QObject::connect(extractor, &FileExtractor::finishedChanged, this, [=]() {
|
||||
downloader->deleteLater();
|
||||
extractor->deleteLater();
|
||||
|
||||
QString bundleIconPath = m_downloadPath + "/TextureBundleIcons";
|
||||
QVariantMap metaData = readBundleMetadata();
|
||||
m_texturesModel->loadTextureBundle(m_texturesUrl, bundleIconPath, metaData);
|
||||
m_environmentsModel->loadTextureBundle(m_environmentsUrl, bundleIconPath, metaData);
|
||||
});
|
||||
|
||||
extractor->extract();
|
||||
});
|
||||
|
||||
downloader->start();
|
||||
return false;
|
||||
}
|
||||
|
||||
QList<QToolButton *> ContentLibraryWidget::createToolBarWidgets()
|
||||
{
|
||||
return {};
|
||||
|
@@ -9,6 +9,7 @@
|
||||
#include <QPointer>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QDir;
|
||||
class QShortcut;
|
||||
class QToolButton;
|
||||
QT_END_NAMESPACE
|
||||
@@ -80,6 +81,10 @@ private:
|
||||
void updateSearch();
|
||||
void setIsDragging(bool val);
|
||||
QString findTextureBundlePath();
|
||||
void loadTextureBundle();
|
||||
QVariantMap readBundleMetadata();
|
||||
bool fetchTextureBundleMetadata(const QDir &bundleDir);
|
||||
bool fetchTextureBundleIcons(const QDir &bundleDir);
|
||||
|
||||
QScopedPointer<StudioQuickWidget> m_quickWidget;
|
||||
QPointer<ContentLibraryMaterialsModel> m_materialsModel;
|
||||
@@ -98,6 +103,10 @@ private:
|
||||
bool m_hasQuick3DImport = false;
|
||||
bool m_isDragging = false;
|
||||
bool m_anyTextureBeingDownloaded = false;
|
||||
QString m_baseUrl;
|
||||
QString m_texturesUrl;
|
||||
QString m_environmentsUrl;
|
||||
QString m_downloadPath;
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <QDir>
|
||||
#include <QQmlEngine>
|
||||
#include <QRandomGenerator>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
@@ -41,7 +42,8 @@ void FileDownloader::start()
|
||||
{
|
||||
emit downloadStarting();
|
||||
|
||||
QString tempFileName = QDir::tempPath() + "/.qds_download_" + url().fileName();
|
||||
auto uniqueText = QByteArray::number(QRandomGenerator::global()->generate(), 16);
|
||||
QString tempFileName = QDir::tempPath() + "/.qds_" + uniqueText + "_download_" + url().fileName();
|
||||
|
||||
m_outputFile.setFileName(tempFileName);
|
||||
m_outputFile.open(QIODevice::WriteOnly);
|
||||
|
Reference in New Issue
Block a user