QmlDesigner: Allow changing downloaded textures path

For now changing the path triggers the "restart needed" dialog. Some
refactoring (for future) is needed to make the change works right away.

Also added few missing ContentLibraryBackend uses.

Fixes: QDS-9233
Change-Id: I3a576d397b0452a70d9940edaaa38193c41af347
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
This commit is contained in:
Mahmoud Badri
2023-03-02 16:31:49 +02:00
parent db6046b456
commit a0df1fd61a
11 changed files with 325 additions and 248 deletions

View File

@@ -55,7 +55,7 @@ Item {
&& ContentLibraryBackend.rootView.hasMaterialLibrary && ContentLibraryBackend.rootView.hasMaterialLibrary
&& ContentLibraryBackend.materialsModel.hasRequiredQuick3DImport && ContentLibraryBackend.materialsModel.hasRequiredQuick3DImport
} else { // Textures / Environments tabs } else { // Textures / Environments tabs
texturesModel.texBundleExists ContentLibraryBackend.texturesModel.texBundleExists
} }
} }
@@ -106,7 +106,7 @@ Item {
id: texturesView id: texturesView
width: root.width width: root.width
model: texturesModel model: ContentLibraryBackend.texturesModel
searchBox: searchBox searchBox: searchBox
} }
@@ -115,7 +115,7 @@ Item {
id: environmentsView id: environmentsView
width: root.width width: root.width
model: environmentsModel model: ContentLibraryBackend.environmentsModel
searchBox: searchBox searchBox: searchBox
} }

View File

@@ -4,36 +4,34 @@
#include "contentlibrarytexturesmodel.h" #include "contentlibrarytexturesmodel.h"
#include "contentlibrarytexturescategory.h" #include "contentlibrarytexturescategory.h"
#include "qmldesignerplugin.h"
#include "utils/algorithm.h" #include "utils/filedownloader.h"
#include "utils/qtcassert.h" #include "utils/fileextractor.h"
#include <qmldesigner/utils/fileextractor.h> #include <qmldesignerbase/qmldesignerbaseplugin.h>
#include <qmldesigner/utils/filedownloader.h>
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
#include <QCoreApplication> #include <QCoreApplication>
#include <QDir> #include <QDir>
#include <QFile> #include <QFile>
#include <QFileInfo> #include <QFileInfo>
#include <QUrl>
#include <QQmlEngine> #include <QQmlEngine>
#include <QSize> #include <QSize>
#include <QStandardPaths> #include <QStandardPaths>
#include <QUrl>
namespace QmlDesigner { namespace QmlDesigner {
ContentLibraryTexturesModel::ContentLibraryTexturesModel(const QString &bundleSubPath, QObject *parent) ContentLibraryTexturesModel::ContentLibraryTexturesModel(const QString &category, QObject *parent)
: QAbstractListModel(parent) : QAbstractListModel(parent)
, m_bundleSubPath(bundleSubPath)
{ {
qmlRegisterType<QmlDesigner::FileDownloader>("WebFetcher", 1, 0, "FileDownloader"); qmlRegisterType<QmlDesigner::FileDownloader>("WebFetcher", 1, 0, "FileDownloader");
qmlRegisterType<QmlDesigner::FileExtractor>("WebFetcher", 1, 0, "FileExtractor"); qmlRegisterType<QmlDesigner::FileExtractor>("WebFetcher", 1, 0, "FileExtractor");
static const QString baseDownloadPath = m_category = category; // textures main category (ex: Textures, Environments)
QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)
+ "/QtDesignStudio/bundles";
m_downloadPath = baseDownloadPath + '/' + bundleSubPath;
} }
int ContentLibraryTexturesModel::rowCount(const QModelIndex &) const int ContentLibraryTexturesModel::rowCount(const QModelIndex &) const
@@ -99,39 +97,50 @@ QHash<int, QByteArray> ContentLibraryTexturesModel::roleNames() const
return roles; return roles;
} }
void ContentLibraryTexturesModel::loadTextureBundle(const QString &bundlePath, const QString &baseUrl, /**
const QVariantMap &metaData) * @brief Load the bundle categorized icons. Actual textures are downloaded on demand
*
* @param bundlePath local path to the bundle folder and icons
* @param metaData bundle textures metadata
*/
void ContentLibraryTexturesModel::loadTextureBundle(const QString &bundlePath, const QVariantMap &metaData)
{ {
QDir bundleDir = QDir(bundlePath); if (!m_bundleCategories.isEmpty())
return;
QDir bundleDir = QString("%1/%2").arg(bundlePath, 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." << bundlePath;
return; return;
} }
if (!m_bundleCategories.isEmpty()) QString remoteBaseUrl = QmlDesignerPlugin::settings()
return; .value(DesignerSettingsKey::DOWNLOADABLE_BUNDLES_URL).toString()
+ '/' + 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() + "/icon").entryInfoList(QDir::Files);
for (const QFileInfo &tex : texFiles) { for (const QFileInfo &tex : texFiles) {
QString zipPath = '/' + dir.fileName() + '/' + tex.baseName() + ".zip";
QString urlPath = baseUrl + zipPath; QString fullRemoteUrl = QString("%1/%2/%3.zip").arg(remoteBaseUrl, dir.fileName(),
QString downloadPath = m_downloadPath + '/' + dir.fileName(); tex.baseName());
QString fullZipPath = m_bundleSubPath + zipPath; QString localDownloadPath = QString("%1/%2/%3").arg(QmlDesignerBasePlugin::bundlesPathSetting(),
m_category, dir.fileName());
QString key = QString("%1/%2/%3.zip").arg(m_category, dir.fileName(), tex.baseName());
QString fileExt; QString fileExt;
QSize dimensions; QSize dimensions;
qint64 sizeInBytes = -1; qint64 sizeInBytes = -1;
if (metaData.contains(fullZipPath)) { if (metaData.contains(key)) {
QVariantMap dataMap = metaData[fullZipPath].toMap(); QVariantMap dataMap = metaData[key].toMap();
fileExt = '.' + dataMap.value("format").toString(); fileExt = '.' + dataMap.value("format").toString();
dimensions = QSize(dataMap.value("width").toInt(), dataMap.value("height").toInt()); dimensions = QSize(dataMap.value("width").toInt(), dataMap.value("height").toInt());
sizeInBytes = dataMap.value("size").toLongLong(); sizeInBytes = dataMap.value("size").toLongLong();
} }
category->addTexture(tex, downloadPath, urlPath, fileExt, dimensions, sizeInBytes); category->addTexture(tex, localDownloadPath, fullRemoteUrl, fileExt, dimensions, sizeInBytes);
} }
m_bundleCategories.append(category); m_bundleCategories.append(category);
} }

View File

@@ -18,7 +18,7 @@ class ContentLibraryTexturesModel : public QAbstractListModel
Q_PROPERTY(bool hasSceneEnv READ hasSceneEnv NOTIFY hasSceneEnvChanged) Q_PROPERTY(bool hasSceneEnv READ hasSceneEnv NOTIFY hasSceneEnvChanged)
public: public:
ContentLibraryTexturesModel(const QString &bundleSubpath, QObject *parent = nullptr); ContentLibraryTexturesModel(const QString &category, QObject *parent = nullptr);
int rowCount(const QModelIndex &parent = QModelIndex()) const override; int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
@@ -33,8 +33,7 @@ public:
void setHasSceneEnv(bool b); void setHasSceneEnv(bool b);
void resetModel(); void resetModel();
void loadTextureBundle(const QString &bundlePath, const QString &baseUrl, void loadTextureBundle(const QString &bundlePath, const QVariantMap &metaData);
const QVariantMap &metaData);
signals: signals:
void isEmptyChanged(); void isEmptyChanged();
@@ -46,8 +45,7 @@ private:
void updateIsEmpty(); void updateIsEmpty();
QString m_searchText; QString m_searchText;
QString m_downloadPath; QString m_category;
QString m_bundleSubPath;
QList<ContentLibraryTexturesCategory *> m_bundleCategories; QList<ContentLibraryTexturesCategory *> m_bundleCategories;
bool m_isEmpty = true; bool m_isEmpty = true;

View File

@@ -106,19 +106,14 @@ ContentLibraryWidget::ContentLibraryWidget()
m_quickWidget->setClearColor(Theme::getColor(Theme::Color::DSpanelBackground)); m_quickWidget->setClearColor(Theme::getColor(Theme::Color::DSpanelBackground));
QString textureBundlePath = findTextureBundlePath(); QString textureBundlePath = findTextureBundlePath();
QString baseUrl = QmlDesignerPlugin::settings()
.value(DesignerSettingsKey::DOWNLOADABLE_BUNDLES_URL)
.toString();
QVariantMap metaData; QVariantMap metaData;
QFile jsonFile(textureBundlePath + "/texture_bundle.json"); QFile jsonFile(textureBundlePath + "/texture_bundle.json");
if (jsonFile.open(QIODevice::ReadOnly | QIODevice::Text)) if (jsonFile.open(QIODevice::ReadOnly | QIODevice::Text))
metaData = QJsonDocument::fromJson(jsonFile.readAll()).toVariant().toMap(); metaData = QJsonDocument::fromJson(jsonFile.readAll()).toVariant().toMap();
m_texturesModel->loadTextureBundle(textureBundlePath + "/Textures", m_texturesModel->loadTextureBundle(textureBundlePath, metaData);
baseUrl + "/Textures", metaData); m_environmentsModel->loadTextureBundle(textureBundlePath, metaData);
m_environmentsModel->loadTextureBundle(textureBundlePath + "/Environments",
baseUrl + "/Environments", metaData);
Theme::setupTheme(m_quickWidget->engine()); Theme::setupTheme(m_quickWidget->engine());
m_quickWidget->quickWidget()->installEventFilter(this); m_quickWidget->quickWidget()->installEventFilter(this);

View File

@@ -2,20 +2,21 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
#include "qmldesignerplugin.h" #include "qmldesignerplugin.h"
#include "coreplugin/iwizardfactory.h" #include "coreplugin/iwizardfactory.h"
#include "designmodecontext.h" #include "designmodecontext.h"
#include "designmodewidget.h" #include "designmodewidget.h"
#include "dynamiclicensecheck.h" #include "dynamiclicensecheck.h"
#include "exception.h" #include "exception.h"
#include "generateresource.h" #include "generateresource.h"
#include "nodeinstanceview.h"
#include "openuiqmlfiledialog.h" #include "openuiqmlfiledialog.h"
#include "qmldesignerconstants.h" #include "qmldesignerconstants.h"
#include "qmldesignerexternaldependencies.h" #include "qmldesignerexternaldependencies.h"
#include "qmldesignerprojectmanager.h" #include "qmldesignerprojectmanager.h"
#include "quick2propertyeditorview.h" #include "quick2propertyeditorview.h"
#include "settingspage.h" #include "settingspage.h"
#include <toolbar.h> #include "shortcutmanager.h"
#include "toolbar.h"
#include <colortool/colortool.h> #include <colortool/colortool.h>
#include <connectionview.h> #include <connectionview.h>

View File

@@ -5,7 +5,6 @@
#include "documentmanager.h" #include "documentmanager.h"
#include "qmldesigner_global.h" #include "qmldesigner_global.h"
#include "shortcutmanager.h"
#include <designersettings.h> #include <designersettings.h>
#include <viewmanager.h> #include <viewmanager.h>
@@ -13,6 +12,7 @@
#include <extensionsystem/iplugin.h> #include <extensionsystem/iplugin.h>
#include <qmldesignerbase/qmldesignerbaseplugin.h>
#include <QElapsedTimer> #include <QElapsedTimer>
@@ -114,6 +114,7 @@ private: // variables
QmlDesignerPluginPrivate *d = nullptr; QmlDesignerPluginPrivate *d = nullptr;
static QmlDesignerPlugin *m_instance; static QmlDesignerPlugin *m_instance;
QElapsedTimer m_usageTimer; QElapsedTimer m_usageTimer;
StudioConfigSettingsPage m_settingsPage;
}; };
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -5,10 +5,27 @@
#include "utils/designersettings.h" #include "utils/designersettings.h"
#include <coreplugin/coreconstants.h>
#include <coreplugin/dialogs/restartdialog.h>
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <utils/hostosinfo.h>
#include <QCheckBox>
#include <QGroupBox>
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QSpacerItem>
#include <QStandardPaths>
#include <QVBoxLayout>
namespace QmlDesigner { namespace QmlDesigner {
const char EXAMPLES_DOWNLOAD_PATH[] = "StudioConfig/ExamplesDownloadPath";
const char BUNDLES_DOWNLOAD_PATH[] = "StudioConfig/BundlesDownloadPath";
class QmlDesignerBasePlugin::Data class QmlDesignerBasePlugin::Data
{ {
public: public:
@@ -24,6 +41,12 @@ QmlDesignerBasePlugin::QmlDesignerBasePlugin()
global = this; global = this;
}; };
QmlDesignerBasePlugin *QmlDesignerBasePlugin::instance()
{
return global;
};
QmlDesignerBasePlugin::~QmlDesignerBasePlugin() = default; QmlDesignerBasePlugin::~QmlDesignerBasePlugin() = default;
DesignerSettings &QmlDesignerBasePlugin::settings() DesignerSettings &QmlDesignerBasePlugin::settings()
@@ -38,4 +61,212 @@ bool QmlDesignerBasePlugin::initialize(const QStringList &, QString *)
return true; return true;
} }
Utils::FilePath QmlDesignerBasePlugin::defaultExamplesPath()
{
QStandardPaths::StandardLocation location = Utils::HostOsInfo::isMacHost()
? QStandardPaths::HomeLocation
: QStandardPaths::DocumentsLocation;
return Utils::FilePath::fromString(QStandardPaths::writableLocation(location))
.pathAppended("QtDesignStudio/examples");
}
Utils::FilePath QmlDesignerBasePlugin::defaultBundlesPath()
{
QStandardPaths::StandardLocation location = Utils::HostOsInfo::isMacHost()
? QStandardPaths::HomeLocation
: QStandardPaths::DocumentsLocation;
return Utils::FilePath::fromString(QStandardPaths::writableLocation(location))
.pathAppended("QtDesignStudio/bundles");
}
QString QmlDesignerBasePlugin::examplesPathSetting()
{
return Core::ICore::settings()
->value(EXAMPLES_DOWNLOAD_PATH, defaultExamplesPath().toString())
.toString();
}
QString QmlDesignerBasePlugin::bundlesPathSetting()
{
return Core::ICore::settings()
->value(BUNDLES_DOWNLOAD_PATH, defaultBundlesPath().toString())
.toString();
}
static bool hideBuildMenuSetting()
{
return Core::ICore::settings()
->value(ProjectExplorer::Constants::SETTINGS_MENU_HIDE_BUILD, false)
.toBool();
}
static bool hideDebugMenuSetting()
{
return Core::ICore::settings()
->value(ProjectExplorer::Constants::SETTINGS_MENU_HIDE_DEBUG, false)
.toBool();
}
static bool hideAnalyzeMenuSetting()
{
return Core::ICore::settings()
->value(ProjectExplorer::Constants::SETTINGS_MENU_HIDE_ANALYZE, false)
.toBool();
}
static bool hideToolsMenuSetting()
{
return Core::ICore::settings()->value(Core::Constants::SETTINGS_MENU_HIDE_TOOLS, false).toBool();
}
void setSettingIfDifferent(const QString &key, bool value, bool &dirty)
{
QSettings *s = Core::ICore::settings();
if (s->value(key, false).toBool() != value) {
dirty = true;
s->setValue(key, value);
}
}
StudioSettingsPage::StudioSettingsPage()
: m_buildCheckBox(new QCheckBox(tr("Build")))
, m_debugCheckBox(new QCheckBox(tr("Debug")))
, m_analyzeCheckBox(new QCheckBox(tr("Analyze")))
, m_toolsCheckBox(new QCheckBox(tr("Tools")))
, m_pathChooserExamples(new Utils::PathChooser())
, m_pathChooserBundles(new Utils::PathChooser())
{
const QString toolTip = tr(
"Hide top-level menus with advanced functionality to simplify the UI. <b>Build</b> is "
"generally not required in the context of Qt Design Studio. <b>Debug</b> and "
"<b>Analyze</b> "
"are only required for debugging and profiling. <b>Tools</b> can be useful for bookmarks "
"and git integration.");
QVBoxLayout *boxLayout = new QVBoxLayout();
setLayout(boxLayout);
auto groupBox = new QGroupBox(tr("Hide Menu"));
groupBox->setToolTip(toolTip);
boxLayout->addWidget(groupBox);
auto verticalLayout = new QVBoxLayout();
groupBox->setLayout(verticalLayout);
m_buildCheckBox->setToolTip(toolTip);
m_debugCheckBox->setToolTip(toolTip);
m_analyzeCheckBox->setToolTip(toolTip);
m_toolsCheckBox->setToolTip(toolTip);
verticalLayout->addWidget(m_buildCheckBox);
verticalLayout->addWidget(m_debugCheckBox);
verticalLayout->addWidget(m_analyzeCheckBox);
verticalLayout->addWidget(m_toolsCheckBox);
verticalLayout->addSpacerItem(
new QSpacerItem(10, 10, QSizePolicy::Expanding, QSizePolicy::Minimum));
m_buildCheckBox->setChecked(hideBuildMenuSetting());
m_debugCheckBox->setChecked(hideDebugMenuSetting());
m_analyzeCheckBox->setChecked(hideAnalyzeMenuSetting());
m_toolsCheckBox->setChecked(hideToolsMenuSetting());
// Examples path setting
auto examplesGroupBox = new QGroupBox(tr("Examples"));
boxLayout->addWidget(examplesGroupBox);
auto examplesLayout = new QHBoxLayout(this);
examplesGroupBox->setLayout(examplesLayout);
auto examplesLabel = new QLabel(tr("Examples path:"));
m_pathChooserExamples->setFilePath(
Utils::FilePath::fromString(QmlDesignerBasePlugin::examplesPathSetting()));
auto examplesResetButton = new QPushButton(tr("Reset Path"));
connect(examplesResetButton, &QPushButton::clicked, this, [this]() {
m_pathChooserExamples->setFilePath(QmlDesignerBasePlugin::defaultExamplesPath());
});
examplesLayout->addWidget(examplesLabel);
examplesLayout->addWidget(m_pathChooserExamples);
examplesLayout->addWidget(examplesResetButton);
// Bundles path setting
auto bundlesGroupBox = new QGroupBox(tr("Bundles"));
boxLayout->addWidget(bundlesGroupBox);
auto bundlesLayout = new QHBoxLayout(this);
bundlesGroupBox->setLayout(bundlesLayout);
QLabel *bundlesLabel = new QLabel(tr("Bundles path:"));
m_pathChooserBundles->setFilePath(
Utils::FilePath::fromString(QmlDesignerBasePlugin::bundlesPathSetting()));
QPushButton *bundlesResetButton = new QPushButton(tr("Reset Path"));
connect(bundlesResetButton, &QPushButton::clicked, this, [this]() {
m_pathChooserBundles->setFilePath(QmlDesignerBasePlugin::defaultBundlesPath());
});
bundlesLayout->addWidget(bundlesLabel);
bundlesLayout->addWidget(m_pathChooserBundles);
bundlesLayout->addWidget(bundlesResetButton);
boxLayout->addSpacerItem(new QSpacerItem(10, 10, QSizePolicy::Expanding, QSizePolicy::Expanding));
}
void StudioSettingsPage::apply()
{
bool dirty = false;
setSettingIfDifferent(ProjectExplorer::Constants::SETTINGS_MENU_HIDE_BUILD,
m_buildCheckBox->isChecked(),
dirty);
setSettingIfDifferent(ProjectExplorer::Constants::SETTINGS_MENU_HIDE_DEBUG,
m_debugCheckBox->isChecked(),
dirty);
setSettingIfDifferent(ProjectExplorer::Constants::SETTINGS_MENU_HIDE_ANALYZE,
m_analyzeCheckBox->isChecked(),
dirty);
setSettingIfDifferent(Core::Constants::SETTINGS_MENU_HIDE_TOOLS,
m_toolsCheckBox->isChecked(),
dirty);
if (dirty) {
const QString restartText = tr("The menu visibility change will take effect after restart.");
Core::RestartDialog restartDialog(Core::ICore::dialogParent(), restartText);
restartDialog.exec();
}
QSettings *s = Core::ICore::settings();
const QString value = m_pathChooserExamples->filePath().toString();
if (s->value(EXAMPLES_DOWNLOAD_PATH, false).toString() != value) {
s->setValue(EXAMPLES_DOWNLOAD_PATH, value);
emit global->examplesDownloadPathChanged(value);
}
const QString bundlesPath = m_pathChooserBundles->filePath().toString();
if (s->value(BUNDLES_DOWNLOAD_PATH).toString() != bundlesPath) {
s->setValue(BUNDLES_DOWNLOAD_PATH, bundlesPath);
emit global->bundlesDownloadPathChanged(bundlesPath);
const QString restartText = tr("Changing bundle path will take effect after restart.");
Core::RestartDialog restartDialog(Core::ICore::dialogParent(), restartText);
restartDialog.exec();
}
}
StudioConfigSettingsPage::StudioConfigSettingsPage()
{
setId("Z.StudioConfig.Settings");
setDisplayName(tr("Qt Design Studio Configuration"));
setCategory(Core::Constants::SETTINGS_CATEGORY_CORE);
setWidgetCreator([] { return new StudioSettingsPage; });
}
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -5,12 +5,42 @@
#include "qmldesignerbase_global.h" #include "qmldesignerbase_global.h"
#include <coreplugin/dialogs/ioptionspage.h>
#include <extensionsystem/iplugin.h> #include <extensionsystem/iplugin.h>
#include <utils/pathchooser.h>
#include <memory> #include <memory>
QT_FORWARD_DECLARE_CLASS(QCheckBox)
namespace QmlDesigner { namespace QmlDesigner {
class StudioSettingsPage : public Core::IOptionsPageWidget
{
Q_OBJECT
public:
void apply() final;
StudioSettingsPage();
private:
QCheckBox *m_buildCheckBox;
QCheckBox *m_debugCheckBox;
QCheckBox *m_analyzeCheckBox;
QCheckBox *m_toolsCheckBox;
Utils::PathChooser *m_pathChooserExamples;
Utils::PathChooser *m_pathChooserBundles;
};
class QMLDESIGNERBASE_EXPORT StudioConfigSettingsPage : public Core::IOptionsPage
{
Q_OBJECT
public:
StudioConfigSettingsPage();
};
class QMLDESIGNERBASE_EXPORT QmlDesignerBasePlugin final : public ExtensionSystem::IPlugin class QMLDESIGNERBASE_EXPORT QmlDesignerBasePlugin final : public ExtensionSystem::IPlugin
{ {
Q_OBJECT Q_OBJECT
@@ -20,8 +50,19 @@ public:
QmlDesignerBasePlugin(); QmlDesignerBasePlugin();
~QmlDesignerBasePlugin(); ~QmlDesignerBasePlugin();
static QmlDesignerBasePlugin *instance();
static Utils::FilePath defaultExamplesPath();
static Utils::FilePath defaultBundlesPath();
static QString examplesPathSetting();
static QString bundlesPathSetting();
static class DesignerSettings &settings(); static class DesignerSettings &settings();
signals:
void examplesDownloadPathChanged(const QString &path);
void bundlesDownloadPathChanged(const QString &path);
private: private:
bool initialize(const QStringList &arguments, QString *errorMessage) override; bool initialize(const QStringList &arguments, QString *errorMessage) override;

View File

@@ -7,6 +7,8 @@
#include <coreplugin/documentmanager.h> #include <coreplugin/documentmanager.h>
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <qmldesignerbase/qmldesignerbaseplugin.h>
#include <utils/archive.h> #include <utils/archive.h>
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/networkaccessmanager.h> #include <utils/networkaccessmanager.h>
@@ -60,7 +62,7 @@ bool DataModelDownloader::downloadEnabled() const
QString DataModelDownloader::targetPath() const QString DataModelDownloader::targetPath() const
{ {
return StudioWelcome::Internal::StudioWelcomePlugin::examplesPathSetting(); return QmlDesigner::QmlDesignerBasePlugin::examplesPathSetting();
} }
static Utils::FilePath tempFilePath() static Utils::FilePath tempFilePath()
@@ -104,8 +106,8 @@ DataModelDownloader::DataModelDownloader(QObject * /* parent */)
auto studioWelcomePlugin = qobject_cast<StudioWelcome::Internal::StudioWelcomePlugin *>(plugin); auto studioWelcomePlugin = qobject_cast<StudioWelcome::Internal::StudioWelcomePlugin *>(plugin);
if (studioWelcomePlugin) { if (studioWelcomePlugin) {
QObject::connect(studioWelcomePlugin, QObject::connect(QmlDesigner::QmlDesignerBasePlugin::instance(),
&StudioWelcome::Internal::StudioWelcomePlugin::examplesDownloadPathChanged, &QmlDesigner::QmlDesignerBasePlugin::examplesDownloadPathChanged,
this, this,
&DataModelDownloader::targetPathMustChange); &DataModelDownloader::targetPathMustChange);
} }

View File

@@ -4,15 +4,14 @@
#include "studiowelcomeplugin.h" #include "studiowelcomeplugin.h"
#include "examplecheckout.h" #include "examplecheckout.h"
#include "projectexplorer/target.h"
#include "qdsnewdialog.h" #include "qdsnewdialog.h"
#include <app/app_version.h> #include <app/app_version.h>
#include <coreplugin/coreconstants.h> #include <coreplugin/coreconstants.h>
#include <coreplugin/dialogs/restartdialog.h> #include <coreplugin/dialogs/restartdialog.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/documentmanager.h> #include <coreplugin/documentmanager.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/helpmanager.h> #include <coreplugin/helpmanager.h>
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <coreplugin/imode.h> #include <coreplugin/imode.h>
@@ -20,8 +19,8 @@
#include <projectexplorer/jsonwizard/jsonwizardfactory.h> #include <projectexplorer/jsonwizard/jsonwizardfactory.h>
#include <projectexplorer/projectexplorer.h> #include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projectmanager.h> #include <projectexplorer/projectmanager.h>
#include "projectexplorer/target.h"
#include <qmlprojectmanager/projectfilecontenttools.h> #include <qmlprojectmanager/projectfilecontenttools.h>
#include <qmlprojectmanager/qmlproject.h> #include <qmlprojectmanager/qmlproject.h>
@@ -40,14 +39,11 @@
#include <QAbstractListModel> #include <QAbstractListModel>
#include <QApplication> #include <QApplication>
#include <QCheckBox>
#include <QDesktopServices> #include <QDesktopServices>
#include <QFileInfo> #include <QFileInfo>
#include <QFontDatabase> #include <QFontDatabase>
#include <QGroupBox>
#include <QMainWindow> #include <QMainWindow>
#include <QPointer> #include <QPointer>
#include <QPushButton>
#include <QQmlContext> #include <QQmlContext>
#include <QQmlEngine> #include <QQmlEngine>
#include <QQuickItem> #include <QQuickItem>
@@ -92,8 +88,6 @@ const char STATISTICS_COLLECTION_MODE[] = "StatisticsCollectionMode";
const char NO_TELEMETRY[] = "NoTelemetry"; const char NO_TELEMETRY[] = "NoTelemetry";
const char CRASH_REPORTER_SETTING[] = "CrashReportingEnabled"; const char CRASH_REPORTER_SETTING[] = "CrashReportingEnabled";
const char EXAMPLES_DOWNLOAD_PATH[] = "StudioWelcome/ExamplesDownloadPath";
QPointer<QQuickView> s_viewWindow = nullptr; QPointer<QQuickView> s_viewWindow = nullptr;
QPointer<QQuickWidget> s_viewWidget = nullptr; QPointer<QQuickWidget> s_viewWidget = nullptr;
static StudioWelcomePlugin *s_pluginInstance = nullptr; static StudioWelcomePlugin *s_pluginInstance = nullptr;
@@ -647,23 +641,6 @@ bool StudioWelcomePlugin::delayedInitialize()
return true; return true;
} }
Utils::FilePath StudioWelcomePlugin::defaultExamplesPath()
{
QStandardPaths::StandardLocation location = Utils::HostOsInfo::isMacHost()
? QStandardPaths::HomeLocation
: QStandardPaths::DocumentsLocation;
return Utils::FilePath::fromString(QStandardPaths::writableLocation(location))
.pathAppended("QtDesignStudio/examples");
}
QString StudioWelcomePlugin::examplesPathSetting()
{
return Core::ICore::settings()
->value(EXAMPLES_DOWNLOAD_PATH, defaultExamplesPath().toString())
.toString();
}
WelcomeMode::WelcomeMode() WelcomeMode::WelcomeMode()
{ {
setDisplayName(tr("Welcome")); setDisplayName(tr("Welcome"));
@@ -748,41 +725,6 @@ WelcomeMode::WelcomeMode()
[](const QString &path) { return QFileInfo::exists(path); })); [](const QString &path) { return QFileInfo::exists(path); }));
} }
static bool hideBuildMenuSetting()
{
return Core::ICore::settings()
->value(ProjectExplorer::Constants::SETTINGS_MENU_HIDE_BUILD, false)
.toBool();
}
static bool hideDebugMenuSetting()
{
return Core::ICore::settings()
->value(ProjectExplorer::Constants::SETTINGS_MENU_HIDE_DEBUG, false)
.toBool();
}
static bool hideAnalyzeMenuSetting()
{
return Core::ICore::settings()
->value(ProjectExplorer::Constants::SETTINGS_MENU_HIDE_ANALYZE, false)
.toBool();
}
static bool hideToolsMenuSetting()
{
return Core::ICore::settings()->value(Core::Constants::SETTINGS_MENU_HIDE_TOOLS, false).toBool();
}
void setSettingIfDifferent(const QString &key, bool value, bool &dirty)
{
QSettings *s = Core::ICore::settings();
if (s->value(key, false).toBool() != value) {
dirty = true;
s->setValue(key, value);
}
}
WelcomeMode::~WelcomeMode() WelcomeMode::~WelcomeMode()
{ {
delete m_modeWidget; delete m_modeWidget;
@@ -836,114 +778,6 @@ void WelcomeMode::createQuickWidget()
m_quickWidget->engine()->setOutputWarningsToStandardError(false); m_quickWidget->engine()->setOutputWarningsToStandardError(false);
} }
StudioSettingsPage::StudioSettingsPage()
: m_buildCheckBox(new QCheckBox(tr("Build")))
, m_debugCheckBox(new QCheckBox(tr("Debug")))
, m_analyzeCheckBox(new QCheckBox(tr("Analyze")))
, m_toolsCheckBox(new QCheckBox(tr("Tools")))
, m_pathChooser(new Utils::PathChooser())
{
const QString toolTip = tr(
"Hide top-level menus with advanced functionality to simplify the UI. <b>Build</b> is "
"generally not required in the context of Qt Design Studio. <b>Debug</b> and "
"<b>Analyze</b> "
"are only required for debugging and profiling. <b>Tools</b> can be useful for bookmarks "
"and git integration.");
QVBoxLayout *boxLayout = new QVBoxLayout();
setLayout(boxLayout);
auto groupBox = new QGroupBox(tr("Hide Menu"));
groupBox->setToolTip(toolTip);
boxLayout->addWidget(groupBox);
auto verticalLayout = new QVBoxLayout();
groupBox->setLayout(verticalLayout);
m_buildCheckBox->setToolTip(toolTip);
m_debugCheckBox->setToolTip(toolTip);
m_analyzeCheckBox->setToolTip(toolTip);
m_toolsCheckBox->setToolTip(toolTip);
verticalLayout->addWidget(m_buildCheckBox);
verticalLayout->addWidget(m_debugCheckBox);
verticalLayout->addWidget(m_analyzeCheckBox);
verticalLayout->addWidget(m_toolsCheckBox);
verticalLayout->addSpacerItem(
new QSpacerItem(10, 10, QSizePolicy::Expanding, QSizePolicy::Minimum));
m_buildCheckBox->setChecked(hideBuildMenuSetting());
m_debugCheckBox->setChecked(hideDebugMenuSetting());
m_analyzeCheckBox->setChecked(hideAnalyzeMenuSetting());
m_toolsCheckBox->setChecked(hideToolsMenuSetting());
auto examplesGroupBox = new QGroupBox(tr("Examples"));
boxLayout->addWidget(examplesGroupBox);
auto horizontalLayout = new QHBoxLayout();
examplesGroupBox->setLayout(horizontalLayout);
auto label = new QLabel(tr("Examples path:"));
m_pathChooser->setFilePath(
Utils::FilePath::fromString(StudioWelcomePlugin::examplesPathSetting()));
auto resetButton = new QPushButton(tr("Reset Path"));
connect(resetButton, &QPushButton::clicked, this, [this]() {
m_pathChooser->setFilePath(StudioWelcomePlugin::defaultExamplesPath());
});
horizontalLayout->addWidget(label);
horizontalLayout->addWidget(m_pathChooser);
horizontalLayout->addWidget(resetButton);
boxLayout->addSpacerItem(
new QSpacerItem(10, 10, QSizePolicy::Expanding, QSizePolicy::Expanding));
}
void StudioSettingsPage::apply()
{
bool dirty = false;
setSettingIfDifferent(ProjectExplorer::Constants::SETTINGS_MENU_HIDE_BUILD,
m_buildCheckBox->isChecked(),
dirty);
setSettingIfDifferent(ProjectExplorer::Constants::SETTINGS_MENU_HIDE_DEBUG,
m_debugCheckBox->isChecked(),
dirty);
setSettingIfDifferent(ProjectExplorer::Constants::SETTINGS_MENU_HIDE_ANALYZE,
m_analyzeCheckBox->isChecked(),
dirty);
setSettingIfDifferent(Core::Constants::SETTINGS_MENU_HIDE_TOOLS,
m_toolsCheckBox->isChecked(),
dirty);
if (dirty) {
const QString restartText = tr("The menu visibility change will take effect after restart.");
Core::RestartDialog restartDialog(Core::ICore::dialogParent(), restartText);
restartDialog.exec();
}
QSettings *s = Core::ICore::settings();
const QString value = m_pathChooser->filePath().toString();
if (s->value(EXAMPLES_DOWNLOAD_PATH, false).toString() != value) {
s->setValue(EXAMPLES_DOWNLOAD_PATH, value);
emit s_pluginInstance->examplesDownloadPathChanged(value);
}
}
StudioWelcomeSettingsPage::StudioWelcomeSettingsPage()
{
setId("Z.StudioWelcome.Settings");
setDisplayName(tr("Qt Design Studio Configuration"));
setCategory(Core::Constants::SETTINGS_CATEGORY_CORE);
setWidgetCreator([] { return new StudioSettingsPage; });
}
} // namespace Internal } // namespace Internal
} // namespace StudioWelcome } // namespace StudioWelcome

View File

@@ -5,40 +5,12 @@
#include <extensionsystem/iplugin.h> #include <extensionsystem/iplugin.h>
#include <coreplugin/dialogs/ioptionspage.h> #include <coreplugin/dialogs/ioptionspage.h>
#include <utils/pathchooser.h>
#include <QTimer> #include <QTimer>
QT_FORWARD_DECLARE_CLASS(QCheckBox)
namespace StudioWelcome { namespace StudioWelcome {
namespace Internal { namespace Internal {
class StudioSettingsPage : public Core::IOptionsPageWidget
{
Q_OBJECT
public:
void apply() final;
StudioSettingsPage();
private:
QCheckBox *m_buildCheckBox;
QCheckBox *m_debugCheckBox;
QCheckBox *m_analyzeCheckBox;
QCheckBox *m_toolsCheckBox;
Utils::PathChooser *m_pathChooser;
};
class StudioWelcomeSettingsPage : public Core::IOptionsPage
{
Q_OBJECT
public:
StudioWelcomeSettingsPage();
};
class StudioWelcomePlugin final : public ExtensionSystem::IPlugin class StudioWelcomePlugin final : public ExtensionSystem::IPlugin
{ {
Q_OBJECT Q_OBJECT
@@ -55,15 +27,8 @@ public:
void extensionsInitialized() override; void extensionsInitialized() override;
bool delayedInitialize() override; bool delayedInitialize() override;
static Utils::FilePath defaultExamplesPath();
static QString examplesPathSetting();
signals:
void examplesDownloadPathChanged(const QString &path);
private: private:
class WelcomeMode *m_welcomeMode = nullptr; class WelcomeMode *m_welcomeMode = nullptr;
StudioWelcomeSettingsPage m_settingsPage;
}; };
} // namespace Internal } // namespace Internal