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");
|
QString iconsPath = bundleDir.filePath("icons");
|
||||||
|
|
||||||
QDir iconsDir(iconsPath);
|
QDir iconsDir(iconsPath);
|
||||||
if (iconsDir.exists() && iconsDir.entryList().length() > 0)
|
if (iconsDir.exists() && iconsDir.entryList(QDir::NoDotAndDotDot).length() > 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
QString zipFileUrl = m_baseUrl + "/icons.zip";
|
QString zipFileUrl = m_baseUrl + "/icons.zip";
|
||||||
|
@@ -6,9 +6,6 @@
|
|||||||
#include "contentlibrarytexturescategory.h"
|
#include "contentlibrarytexturescategory.h"
|
||||||
#include "qmldesignerplugin.h"
|
#include "qmldesignerplugin.h"
|
||||||
|
|
||||||
#include "utils/filedownloader.h"
|
|
||||||
#include "utils/fileextractor.h"
|
|
||||||
|
|
||||||
#include <qmldesignerbase/qmldesignerbaseplugin.h>
|
#include <qmldesignerbase/qmldesignerbaseplugin.h>
|
||||||
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
@@ -18,6 +15,7 @@
|
|||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
#include <QJsonDocument>
|
||||||
#include <QQmlEngine>
|
#include <QQmlEngine>
|
||||||
#include <QSize>
|
#include <QSize>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
@@ -28,9 +26,6 @@ namespace QmlDesigner {
|
|||||||
ContentLibraryTexturesModel::ContentLibraryTexturesModel(const QString &category, QObject *parent)
|
ContentLibraryTexturesModel::ContentLibraryTexturesModel(const QString &category, QObject *parent)
|
||||||
: QAbstractListModel(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)
|
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 bundlePath local path to the bundle folder and icons
|
||||||
* @param metaData bundle textures metadata
|
* @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())
|
if (!m_bundleCategories.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QDir bundleDir = QString("%1/%2").arg(bundlePath, m_category);
|
QDir bundleDir = QString("%1/%2").arg(bundleIconPath, m_category);
|
||||||
if (!bundleDir.exists()) {
|
if (!bundleDir.exists()) {
|
||||||
qWarning() << __FUNCTION__ << "textures bundle folder doesn't exist." << bundlePath;
|
qWarning() << __FUNCTION__ << "textures bundle folder doesn't exist." << bundleDir.absolutePath();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString remoteBaseUrl = QmlDesignerPlugin::settings()
|
|
||||||
.value(DesignerSettingsKey::DOWNLOADABLE_BUNDLES_URL).toString()
|
|
||||||
+ "/textures/" + m_category;
|
|
||||||
|
|
||||||
const QFileInfoList dirs = bundleDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
|
const QFileInfoList dirs = bundleDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
|
||||||
for (const QFileInfo &dir : dirs) {
|
for (const QFileInfo &dir : dirs) {
|
||||||
auto category = new ContentLibraryTexturesCategory(this, dir.fileName());
|
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) {
|
for (const QFileInfo &tex : texFiles) {
|
||||||
|
QString fullRemoteUrl = QString("%1/%2/%3.zip").arg(remoteUrl, dir.fileName(),
|
||||||
QString fullRemoteUrl = QString("%1/%2/%3.zip").arg(remoteBaseUrl, dir.fileName(),
|
|
||||||
tex.baseName());
|
tex.baseName());
|
||||||
QString localDownloadPath = QString("%1/%2/%3").arg(QmlDesignerBasePlugin::bundlesPathSetting(),
|
QString localDownloadPath = QString("%1/%2/%3").arg(QmlDesignerBasePlugin::bundlesPathSetting(),
|
||||||
m_category, dir.fileName());
|
m_category, dir.fileName());
|
||||||
@@ -145,6 +136,7 @@ void ContentLibraryTexturesModel::loadTextureBundle(const QString &bundlePath, c
|
|||||||
m_bundleCategories.append(category);
|
m_bundleCategories.append(category);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resetModel();
|
||||||
updateIsEmpty();
|
updateIsEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -33,7 +33,8 @@ public:
|
|||||||
void setHasSceneEnv(bool b);
|
void setHasSceneEnv(bool b);
|
||||||
|
|
||||||
void resetModel();
|
void resetModel();
|
||||||
void loadTextureBundle(const QString &bundlePath, const QVariantMap &metaData);
|
void loadTextureBundle(const QString &remoteUrl, const QString &bundlePath,
|
||||||
|
const QVariantMap &metaData);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void isEmptyChanged();
|
void isEmptyChanged();
|
||||||
|
@@ -8,6 +8,9 @@
|
|||||||
#include "contentlibrarytexture.h"
|
#include "contentlibrarytexture.h"
|
||||||
#include "contentlibrarytexturesmodel.h"
|
#include "contentlibrarytexturesmodel.h"
|
||||||
|
|
||||||
|
#include "utils/filedownloader.h"
|
||||||
|
#include "utils/fileextractor.h"
|
||||||
|
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
#include <qmldesignerconstants.h>
|
#include <qmldesignerconstants.h>
|
||||||
#include <qmldesignerplugin.h>
|
#include <qmldesignerplugin.h>
|
||||||
@@ -19,6 +22,7 @@
|
|||||||
#include <utils/hostosinfo.h>
|
#include <utils/hostosinfo.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QMimeData>
|
#include <QMimeData>
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
@@ -32,6 +36,8 @@
|
|||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
constexpr int TextureBundleMetadataVersion = 1;
|
||||||
|
|
||||||
static QString propertyEditorResourcesPath()
|
static QString propertyEditorResourcesPath()
|
||||||
{
|
{
|
||||||
#ifdef SHARE_QML_PATH
|
#ifdef SHARE_QML_PATH
|
||||||
@@ -98,6 +104,9 @@ ContentLibraryWidget::ContentLibraryWidget()
|
|||||||
, m_texturesModel(new ContentLibraryTexturesModel("Textures", this))
|
, m_texturesModel(new ContentLibraryTexturesModel("Textures", this))
|
||||||
, m_environmentsModel(new ContentLibraryTexturesModel("Environments", 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"));
|
setWindowTitle(tr("Content Library", "Title of content library widget"));
|
||||||
setMinimumWidth(120);
|
setMinimumWidth(120);
|
||||||
|
|
||||||
@@ -106,15 +115,17 @@ ContentLibraryWidget::ContentLibraryWidget()
|
|||||||
m_quickWidget->engine()->addImportPath(propertyEditorResourcesPath() + "/imports");
|
m_quickWidget->engine()->addImportPath(propertyEditorResourcesPath() + "/imports");
|
||||||
m_quickWidget->setClearColor(Theme::getColor(Theme::Color::DSpanelBackground));
|
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;
|
m_texturesUrl = m_baseUrl + "/Textures";
|
||||||
QFile jsonFile(textureBundlePath + "/texture_bundle.json");
|
m_environmentsUrl = m_baseUrl + "/Environments";
|
||||||
if (jsonFile.open(QIODevice::ReadOnly | QIODevice::Text))
|
|
||||||
metaData = QJsonDocument::fromJson(jsonFile.readAll()).toVariant().toMap();
|
|
||||||
|
|
||||||
m_texturesModel->loadTextureBundle(textureBundlePath, metaData);
|
m_downloadPath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)
|
||||||
m_environmentsModel->loadTextureBundle(textureBundlePath, metaData);
|
+ "/QtDesignStudio/bundles";
|
||||||
|
|
||||||
|
loadTextureBundle();
|
||||||
|
|
||||||
Theme::setupTheme(m_quickWidget->engine());
|
Theme::setupTheme(m_quickWidget->engine());
|
||||||
m_quickWidget->quickWidget()->installEventFilter(this);
|
m_quickWidget->quickWidget()->installEventFilter(this);
|
||||||
@@ -144,6 +155,115 @@ ContentLibraryWidget::ContentLibraryWidget()
|
|||||||
reloadQmlSource();
|
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()
|
QList<QToolButton *> ContentLibraryWidget::createToolBarWidgets()
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
|
@@ -9,6 +9,7 @@
|
|||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QDir;
|
||||||
class QShortcut;
|
class QShortcut;
|
||||||
class QToolButton;
|
class QToolButton;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
@@ -80,6 +81,10 @@ private:
|
|||||||
void updateSearch();
|
void updateSearch();
|
||||||
void setIsDragging(bool val);
|
void setIsDragging(bool val);
|
||||||
QString findTextureBundlePath();
|
QString findTextureBundlePath();
|
||||||
|
void loadTextureBundle();
|
||||||
|
QVariantMap readBundleMetadata();
|
||||||
|
bool fetchTextureBundleMetadata(const QDir &bundleDir);
|
||||||
|
bool fetchTextureBundleIcons(const QDir &bundleDir);
|
||||||
|
|
||||||
QScopedPointer<StudioQuickWidget> m_quickWidget;
|
QScopedPointer<StudioQuickWidget> m_quickWidget;
|
||||||
QPointer<ContentLibraryMaterialsModel> m_materialsModel;
|
QPointer<ContentLibraryMaterialsModel> m_materialsModel;
|
||||||
@@ -98,6 +103,10 @@ private:
|
|||||||
bool m_hasQuick3DImport = false;
|
bool m_hasQuick3DImport = false;
|
||||||
bool m_isDragging = false;
|
bool m_isDragging = false;
|
||||||
bool m_anyTextureBeingDownloaded = false;
|
bool m_anyTextureBeingDownloaded = false;
|
||||||
|
QString m_baseUrl;
|
||||||
|
QString m_texturesUrl;
|
||||||
|
QString m_environmentsUrl;
|
||||||
|
QString m_downloadPath;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QQmlEngine>
|
#include <QQmlEngine>
|
||||||
|
#include <QRandomGenerator>
|
||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
@@ -41,7 +42,8 @@ void FileDownloader::start()
|
|||||||
{
|
{
|
||||||
emit downloadStarting();
|
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.setFileName(tempFileName);
|
||||||
m_outputFile.open(QIODevice::WriteOnly);
|
m_outputFile.open(QIODevice::WriteOnly);
|
||||||
|
Reference in New Issue
Block a user