aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/extensionmanager
diff options
context:
space:
mode:
authorMarcus Tillmanns <[email protected]>2025-03-06 11:09:00 +0100
committerMarcus Tillmanns <[email protected]>2025-03-06 12:04:29 +0000
commit7df8102cec707c7081bcbe797015de082990f921 (patch)
treeb0fa96bccabcc82c55beccef67e654aea82e1ba6 /src/plugins/extensionmanager
parent2793470a2c111c186abc4a1d12b77077fb1b0e04 (diff)
ExtensionManager: Add RemoteSpec to simplify data access
RemoteSpec stores all the data about a remote plugin or pack. It uses the PluginSpec::readMetaData mechanism to parse the metadata information. Change-Id: I1d0c90615f0c0e54876cbfeb5d0a2a72be8796e8 Reviewed-by: Alessandro Portale <[email protected]>
Diffstat (limited to 'src/plugins/extensionmanager')
-rw-r--r--src/plugins/extensionmanager/CMakeLists.txt2
-rw-r--r--src/plugins/extensionmanager/extensionmanager.qbs2
-rw-r--r--src/plugins/extensionmanager/extensionmanagerwidget.cpp13
-rw-r--r--src/plugins/extensionmanager/extensionsmodel.cpp231
-rw-r--r--src/plugins/extensionmanager/extensionsmodel.h1
-rw-r--r--src/plugins/extensionmanager/remotespec.cpp214
-rw-r--r--src/plugins/extensionmanager/remotespec.h84
7 files changed, 423 insertions, 124 deletions
diff --git a/src/plugins/extensionmanager/CMakeLists.txt b/src/plugins/extensionmanager/CMakeLists.txt
index 56236df9fb7..8340de04149 100644
--- a/src/plugins/extensionmanager/CMakeLists.txt
+++ b/src/plugins/extensionmanager/CMakeLists.txt
@@ -13,6 +13,8 @@ add_qtc_plugin(ExtensionManager
extensionsbrowser.h
extensionsmodel.cpp
extensionsmodel.h
+ remotespec.cpp
+ remotespec.h
)
extend_qtc_plugin(ExtensionManager
diff --git a/src/plugins/extensionmanager/extensionmanager.qbs b/src/plugins/extensionmanager/extensionmanager.qbs
index 994d75f7366..fd41974a8b1 100644
--- a/src/plugins/extensionmanager/extensionmanager.qbs
+++ b/src/plugins/extensionmanager/extensionmanager.qbs
@@ -21,6 +21,8 @@ QtcPlugin {
"extensionsbrowser.h",
"extensionsmodel.cpp",
"extensionsmodel.h",
+ "remotespec.cpp",
+ "remotespec.h",
]
QtcTestFiles {
diff --git a/src/plugins/extensionmanager/extensionmanagerwidget.cpp b/src/plugins/extensionmanager/extensionmanagerwidget.cpp
index bb07cf34d25..ffea1964f28 100644
--- a/src/plugins/extensionmanager/extensionmanagerwidget.cpp
+++ b/src/plugins/extensionmanager/extensionmanagerwidget.cpp
@@ -7,6 +7,7 @@
#include "extensionmanagertr.h"
#include "extensionsbrowser.h"
#include "extensionsmodel.h"
+#include "remotespec.h"
#include <coreplugin/coreconstants.h>
#include <coreplugin/coreplugintr.h>
@@ -452,6 +453,8 @@ private:
QString m_currentDownloadUrl;
QString m_currentId;
Tasking::TaskTreeRunner m_dlTaskTreeRunner;
+
+ std::unique_ptr<RemoteSpec> m_remoteSpec;
};
static QWidget *descriptionPlaceHolder()
@@ -525,6 +528,12 @@ ExtensionManagerWidget::ExtensionManagerWidget()
m_packExtensionsTitle = sectionTitle(h6TF, Tr::tr("Extensions in pack"));
m_packExtensions = new QLabel;
applyTf(m_packExtensions, contentTF, false);
+
+ m_packExtensions->setTextInteractionFlags(Qt::LinksAccessibleByMouse);
+ connect(m_packExtensions, &QLabel::linkActivated, this, [this](const QString &link) {
+ m_extensionBrowser->selectIndex(m_extensionModel->indexOfId(link));
+ });
+
m_pluginStatus = new PluginStatusWidget;
auto secondary = new QWidget;
@@ -637,7 +646,9 @@ void ExtensionManagerWidget::updateView(const QModelIndex &current)
auto idToDisplayName = [this](const QString &id) {
const QModelIndex dependencyIndex = m_extensionModel->indexOfId(id);
- const QString displayName = dependencyIndex.data(RoleName).toString();
+ QString displayName = dependencyIndex.data(RoleName).toString();
+ if (displayName.isEmpty())
+ displayName = id;
return QString("<a href=\"%1\">%2</a>").arg(id).arg(displayName);
};
diff --git a/src/plugins/extensionmanager/extensionsmodel.cpp b/src/plugins/extensionmanager/extensionsmodel.cpp
index e31b3960ac2..e7c52ba2b90 100644
--- a/src/plugins/extensionmanager/extensionsmodel.cpp
+++ b/src/plugins/extensionmanager/extensionsmodel.cpp
@@ -4,6 +4,7 @@
#include "extensionsmodel.h"
#include "extensionmanagertr.h"
+#include "remotespec.h"
#include <utils/algorithm.h>
#include <utils/hostosinfo.h>
@@ -28,8 +29,6 @@ using namespace Utils;
namespace ExtensionManager::Internal {
-const char EXTENSION_KEY_ID[] = "id";
-
Q_LOGGING_CATEGORY(modelLog, "qtc.extensionmanager.model", QtWarningMsg)
class ExtensionsModelPrivate
@@ -37,27 +36,24 @@ class ExtensionsModelPrivate
public:
void addUnlistedLocalPlugins();
- static QVariant dataFromRemotePack(const QJsonObject &json, int role);
- static QVariant dataFromRemotePlugin(const QJsonObject &json, int role);
+ static QVariant dataFromRemotePack(const RemoteSpec *spec, int role);
+ static QVariant dataFromRemotePlugin(const RemoteSpec *spec, int role);
QVariant dataFromRemoteExtension(int index, int role) const;
QVariant dataFromLocalPlugin(int index, int role) const;
- QJsonArray responseItems;
+ //QJsonArray responseItems;
PluginSpecs localPlugins;
+ std::vector<std::unique_ptr<RemoteSpec>> remotePlugins;
};
void ExtensionsModelPrivate::addUnlistedLocalPlugins()
{
- QSet<QString> responseExtensions;
- for (const QJsonValueConstRef &responseItem : qAsConst(responseItems))
- responseExtensions << responseItem.toObject().value("id").toString();
-
- localPlugins.clear();
- for (PluginSpec *plugin : PluginManager::plugins())
- if (!responseExtensions.contains(plugin->id()))
- localPlugins.append(plugin);
+ QSet<QString> remoteIds = Utils::transform<QSet>(remotePlugins, &RemoteSpec::id);
+ localPlugins = Utils::filtered(PluginManager::plugins(), [&remoteIds](const PluginSpec *plugin) {
+ return !remoteIds.contains(plugin->id());
+ });
- qCDebug(modelLog) << "Number of extensions from JSON:" << responseExtensions.count();
+ qCDebug(modelLog) << "Number of extensions from JSON:" << remotePlugins.size();
qCDebug(modelLog) << "Number of added local plugins:" << localPlugins.count();
}
@@ -85,128 +81,79 @@ QString descriptionWithLinks(const QString &description, const QString &url,
return fragments.join("\n\n");
}
-QVariant ExtensionsModelPrivate::dataFromRemotePack(const QJsonObject &json, int role)
-{
- switch (role) {
- case RoleDescriptionLong:
- return joinedStringList(json.value("long_description"));
- case RoleDescriptionShort:
- return joinedStringList(json.value("description"));
- case RoleItemType:
- return ItemTypePack;
- case RolePlugins:
- return json.value("plugins").toVariant().toStringList();
- default:
- break;
- }
-
- return {};
-}
-
-QVariant ExtensionsModelPrivate::dataFromRemotePlugin(const QJsonObject &json, int role)
+QVariant ExtensionsModelPrivate::dataFromRemoteExtension(int index, int role) const
{
- const QJsonObject metaData = json.value("metadata").toObject();
+ QTC_ASSERT(index >= 0 && size_t(index) < remotePlugins.size(), return {});
+ RemoteSpec *remoteSpec = remotePlugins.at(index).get();
switch (role) {
+ case Qt::DisplayRole:
+ case RoleName:
+ return remoteSpec->displayName();
+ case RoleDownloadCount:
+ return remoteSpec->downloads();
+ case RoleId:
+ return remoteSpec->id();
+ case RoleDateUpdated:
+ return remoteSpec->updatedAt();
+ case RoleStatus:
+ return remoteSpec->statusString();
+ case RoleTags:
+ return remoteSpec->tags();
+ case RoleVendor:
+ return remoteSpec->vendor();
+ case RoleVendorId:
+ return remoteSpec->vendorId();
case RoleCopyright:
- return metaData.value("Copyright");
+ return remoteSpec->copyright();
case RoleDownloadUrl: {
- const QJsonArray sources = json.value("sources").toArray();
- const QString thisPlatform = customOsTypeToString(HostOsInfo::hostOs());
- const QString thisArch = QSysInfo::currentCpuArchitecture();
- for (const QJsonValue &source : sources) {
- const QJsonObject sourceObject = source.toObject();
- const QJsonObject platform = sourceObject.value("platform").toObject();
- if (platform.isEmpty() // Might be a Lua plugin
- || (platform.value("name").toString() == thisPlatform
- && platform.value("architecture") == thisArch))
- return sourceObject.value("url").toString();
+ for (const auto &source : remoteSpec->sources()) {
+ if (!source.platform)
+ return source.url;
+
+ if (source.platform->os == HostOsInfo::hostOs()
+ && source.platform->architecture == HostOsInfo::hostArchitecture())
+ return source.url;
}
- break;
+ return {};
}
case RoleDependencies: {
- QStringList dependencies;
-
- const QJsonArray dependenciesArray = metaData.value("Dependencies").toArray();
- for (const auto &dependency : dependenciesArray) {
- const QJsonObject dependencyObject = dependency.toObject();
- dependencies.append(dependencyObject.value("Id").toString());
- }
-
+ QStringList dependencies
+ = Utils::transform(remoteSpec->dependencies(), &PluginDependency::id);
return dependencies;
}
case RolePlatforms: {
- QSet<QString> platforms;
- const QJsonArray sources = json.value("sources").toArray();
- for (const QJsonValue &source : sources) {
- // {"name": "Windows", "architecture": "x86" }
- const QJsonObject platform = source.toObject().value("platform").toObject();
- if (!platform.isEmpty()) {
- const QString name = customOsTypeToString(
- osTypeFromString(platform.value("name").toString()).value_or(OsTypeOther));
- const QString architecture = platform.value("architecture").toString();
- platforms.insert(name + " " + architecture);
- } else {
- platforms.insert(Tr::tr("Platform agnostic"));
- }
- }
-
- return platforms.values();
+ QStringList platforms
+ = Utils::transform<QStringList>(remoteSpec->sources(), [](const Source &s) -> QString {
+ if (!s.platform)
+ return Tr::tr("Platform agnostic");
+
+ const QString name = customOsTypeToString(s.platform->os);
+ const QString architecture = customOsArchToString(s.platform->architecture);
+ return name + " " + architecture;
+ });
+ platforms.sort(Qt::CaseInsensitive);
+ return Utils::filteredUnique(platforms);
}
case RoleVersion:
- return metaData.value("Version");
+ return remoteSpec->version();
case RoleItemType:
+ if (remoteSpec->isPack())
+ return ItemTypePack;
+
return ItemTypeExtension;
case RoleDescriptionLong: {
- const QString description = joinedStringList(metaData.value("LongDescription"));
- const QString url = metaData.value("Url").toString();
- const QString documentationUrl = metaData.value("DocumentationUrl").toString();
+ const QString description = remoteSpec->longDescription();
+ const QString url = remoteSpec->url();
+ const QString documentationUrl = remoteSpec->documentationUrl();
return descriptionWithLinks(description, url, documentationUrl);
}
case RoleDescriptionShort:
- return joinedStringList(metaData.value("Description"));
- default:
- break;
- }
-
- return {};
-}
-
-QVariant ExtensionsModelPrivate::dataFromRemoteExtension(int index, int role) const
-{
- const QJsonObject json = responseItems.at(index).toObject();
-
- switch (role) {
- case Qt::DisplayRole:
- case RoleName:
- return json.value("display_name");
- case RoleDownloadCount:
- break; // TODO: Reinstate download numbers when they have more substance
- // return json.value("downloads");
- case RoleId:
- return json.value(EXTENSION_KEY_ID);
- case RoleDateUpdated:
- return QDate::fromString(json.value("updated_at").toString(), Qt::ISODate);
- case RoleStatus:
- return json.value("status");
- case RoleTags:
- return json.value("tags").toVariant().toStringList();
- case RoleVendor:
- return json.value("display_vendor");
- case RoleVendorId:
- return json.value("vendor_id");
- default:
- break;
+ return remoteSpec->description();
+ case RolePlugins:
+ return remoteSpec->packPluginIds();
}
- const QJsonObject pluginObject = json.value("plugin").toObject();
- if (!pluginObject.isEmpty())
- return dataFromRemotePlugin(pluginObject, role);
-
- const QJsonObject packObject = json.value("pack").toObject();
- if (!packObject.isEmpty())
- return dataFromRemotePack(packObject, role);
-
return {};
}
@@ -270,7 +217,7 @@ ExtensionsModel::~ExtensionsModel()
int ExtensionsModel::rowCount([[maybe_unused]] const QModelIndex &parent) const
{
- return d->responseItems.count() + d->localPlugins.count();
+ return d->remotePlugins.size() + d->localPlugins.count();
}
static QString badgeText(const QModelIndex &index)
@@ -324,8 +271,8 @@ QVariant ExtensionsModel::data(const QModelIndex &index, int role) const
break;
}
- const bool isRemoteExtension = index.row() < d->responseItems.count();
- const int itemIndex = index.row() - (isRemoteExtension ? 0 : d->responseItems.count());
+ const bool isRemoteExtension = size_t(index.row()) < d->remotePlugins.size();
+ const int itemIndex = index.row() - (isRemoteExtension ? 0 : d->remotePlugins.size());
return isRemoteExtension ? d->dataFromRemoteExtension(itemIndex, role)
: d->dataFromLocalPlugin(itemIndex, role);
@@ -335,10 +282,11 @@ QModelIndex ExtensionsModel::indexOfId(const QString &extensionId) const
{
const int localIndex = indexOf(d->localPlugins, equal(&PluginSpec::id, extensionId));
if (localIndex >= 0)
- return index(d->responseItems.count() + localIndex);
+ return index(d->remotePlugins.size() + localIndex);
- for (int remoteIndex = 0; const QJsonValueConstRef &value : std::as_const(d->responseItems)) {
- if (value.toObject().value(EXTENSION_KEY_ID) == extensionId)
+ for (int remoteIndex = 0;
+ const std::unique_ptr<RemoteSpec> &spec : std::as_const(d->remotePlugins)) {
+ if (spec->id() == extensionId)
return index(remoteIndex);
++remoteIndex;
}
@@ -351,8 +299,22 @@ void ExtensionsModel::setExtensionsJson(const QByteArray &json)
beginResetModel();
QJsonParseError error;
const QJsonObject jsonObj = QJsonDocument::fromJson(json, &error).object();
+ d->remotePlugins.clear();
+
qCDebug(modelLog) << "QJsonParseError:" << error.errorString();
- d->responseItems = jsonObj.value("items").toArray();
+ QJsonArray responseItems = jsonObj.value("items").toArray();
+
+ for (const QJsonValue &item : responseItems) {
+ const QJsonObject itemObject = item.toObject();
+ std::unique_ptr<RemoteSpec> remoteSpec(new RemoteSpec());
+ auto result = remoteSpec->fromJson(itemObject);
+ if (!result) {
+ qCWarning(modelLog) << "Failed to read remote extension:" << result.error();
+ continue;
+ }
+ d->remotePlugins.push_back(std::move(remoteSpec));
+ }
+
d->addUnlistedLocalPlugins();
endResetModel();
}
@@ -374,9 +336,32 @@ QString customOsTypeToString(OsType osType)
}
}
+QString customOsArchToString(OsArch osArch)
+{
+ switch (osArch) {
+ case OsArchX86:
+ return "x86";
+ case OsArchAMD64:
+ return "x86_64";
+ case OsArchItanium:
+ return "ia64";
+ case OsArchArm:
+ return "arm";
+ case OsArchArm64:
+ return "arm64";
+ case OsArchUnknown:
+ break;
+ }
+
+ return "Unknown";
+}
+
PluginSpec *pluginSpecForId(const QString &pluginId)
{
- return findOrDefault(PluginManager::plugins(), equal(&PluginSpec::id, pluginId));
+ PluginSpec *spec = findOrDefault(PluginManager::plugins(), equal(&PluginSpec::id, pluginId));
+ if (spec)
+ return spec;
+ return nullptr;
}
QString statusDisplayString(const QModelIndex &index)
diff --git a/src/plugins/extensionmanager/extensionsmodel.h b/src/plugins/extensionmanager/extensionsmodel.h
index 87b4a6d73b6..bd973852398 100644
--- a/src/plugins/extensionmanager/extensionsmodel.h
+++ b/src/plugins/extensionmanager/extensionsmodel.h
@@ -66,6 +66,7 @@ private:
};
QString customOsTypeToString(Utils::OsType osType);
+QString customOsArchToString(Utils::OsArch osArch);
ExtensionSystem::PluginSpec *pluginSpecForId(const QString &pluginId);
QString statusDisplayString(const QModelIndex &index);
diff --git a/src/plugins/extensionmanager/remotespec.cpp b/src/plugins/extensionmanager/remotespec.cpp
new file mode 100644
index 00000000000..e546ce7831a
--- /dev/null
+++ b/src/plugins/extensionmanager/remotespec.cpp
@@ -0,0 +1,214 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "remotespec.h"
+
+#include <utils/stringutils.h>
+
+#include <QJsonArray>
+#include <QJsonDocument>
+
+using namespace Utils;
+
+namespace ExtensionManager::Internal {
+bool RemoteSpec::loadLibrary()
+{
+ return false;
+};
+bool RemoteSpec::initializePlugin()
+{
+ return false;
+};
+bool RemoteSpec::initializeExtensions()
+{
+ return false;
+};
+bool RemoteSpec::delayedInitialize()
+{
+ return false;
+};
+ExtensionSystem::IPlugin::ShutdownFlag RemoteSpec::stop()
+{
+ return ExtensionSystem::IPlugin::SynchronousShutdown;
+};
+
+void RemoteSpec::kill() {};
+
+ExtensionSystem::IPlugin *RemoteSpec::plugin() const
+{
+ return nullptr;
+};
+
+FilePath RemoteSpec::installLocation(bool inUserFolder) const
+{
+ Q_UNUSED(inUserFolder);
+ return {};
+};
+
+Result RemoteSpec::fromJson(const QJsonObject &remoteJsonData)
+{
+ m_remoteJsonData = remoteJsonData;
+
+ const QJsonObject plugin = pluginObject();
+
+ if (!plugin.isEmpty()) {
+ auto res = ExtensionSystem::PluginSpec::readMetaData(plugin.value("metadata").toObject());
+ if (!res)
+ return Result::Error(res.error());
+ if (hasError())
+ return Result::Error(errorString());
+ return Result::Ok;
+ }
+
+ m_isPack = true;
+
+ return Result::Ok;
+}
+
+const QList<Source> RemoteSpec::sources() const
+{
+ const auto obj = pluginObject();
+ if (obj.isEmpty())
+ return {};
+
+ QList<Source> sources;
+ for (const QJsonValue &source : obj.value("sources").toArray()) {
+ Source s;
+ const QJsonObject platform = source.toObject().value("platform").toObject();
+ if (!platform.isEmpty()) {
+ s.platform = Source::Platform{
+ osTypeFromString(platform.value("name").toString()).value_or(OsTypeOther),
+ osArchFromString(platform.value("architecture").toString()).value_or(OsArchUnknown)};
+ }
+ s.url = source.toObject().value("url").toString();
+ sources.append(s);
+ }
+ return sources;
+}
+
+QList<QString> RemoteSpec::tags() const
+{
+ return m_remoteJsonData.value("tags").toVariant().toStringList();
+}
+QDateTime RemoteSpec::createdAt() const
+{
+ return QDateTime::fromString(m_remoteJsonData.value("created_at").toString(), Qt::ISODate);
+}
+QDateTime RemoteSpec::updatedAt() const
+{
+ return QDateTime::fromString(m_remoteJsonData.value("updated_at").toString(), Qt::ISODate);
+}
+QDateTime RemoteSpec::releasedAt() const
+{
+ return QDateTime::fromString(m_remoteJsonData.value("released_at").toString(), Qt::ISODate);
+}
+int RemoteSpec::downloads() const
+{
+ return m_remoteJsonData.value("downloads").toInt();
+}
+QString RemoteSpec::icon() const
+{
+ return m_remoteJsonData.value("icon").toString();
+}
+QString RemoteSpec::smallIcon() const
+{
+ return m_remoteJsonData.value("small_icon").toString();
+}
+bool RemoteSpec::isLatest() const
+{
+ return m_remoteJsonData.value("is_latest").toBool();
+}
+Status RemoteSpec::status() const
+{
+ const QString status = m_remoteJsonData.value("status").toString();
+ if (status == "published") {
+ return Status::Published;
+ } else if (status == "unpublished") {
+ return Status::Unpublished;
+ }
+ return Status::Published;
+}
+
+QString RemoteSpec::uid() const
+{
+ return m_remoteJsonData.value("uid").toString();
+}
+
+QString RemoteSpec::statusString() const
+{
+ return m_remoteJsonData.value("status").toString();
+}
+QJsonObject RemoteSpec::packObject() const
+{
+ return m_remoteJsonData.value("pack").toObject();
+}
+QJsonObject RemoteSpec::pluginObject() const
+{
+ return m_remoteJsonData.value("plugin").toObject();
+}
+bool RemoteSpec::isPack() const
+{
+ return m_isPack;
+}
+QString RemoteSpec::description() const
+{
+ if (isPack()) {
+ QString result;
+ if (readMultiLineString(packObject().value("description"), &result))
+ return result;
+ return {};
+ }
+
+ return PluginSpec::description();
+}
+
+QString RemoteSpec::longDescription() const
+{
+ if (isPack()) {
+ QString result;
+ if (readMultiLineString(packObject().value("long_description"), &result))
+ return result;
+ return {};
+ }
+
+ return PluginSpec::longDescription();
+}
+
+QStringList RemoteSpec::packPluginIds() const
+{
+ return packObject().value("plugins").toVariant().toStringList();
+}
+
+QString RemoteSpec::id() const
+{
+ if (isPack())
+ return m_remoteJsonData.value("id").toString();
+
+ return PluginSpec::id();
+}
+
+QString RemoteSpec::displayName() const
+{
+ if (isPack())
+ return m_remoteJsonData.value("display_name").toString();
+
+ return PluginSpec::displayName();
+}
+
+QString RemoteSpec::vendor() const
+{
+ if (isPack())
+ return m_remoteJsonData.value("vendor").toString();
+
+ return PluginSpec::vendor();
+}
+
+QString RemoteSpec::vendorId() const
+{
+ if (isPack())
+ return m_remoteJsonData.value("vendor_id").toString();
+
+ return PluginSpec::vendorId();
+}
+
+} // namespace ExtensionManager::Internal
diff --git a/src/plugins/extensionmanager/remotespec.h b/src/plugins/extensionmanager/remotespec.h
new file mode 100644
index 00000000000..b9bac9b1197
--- /dev/null
+++ b/src/plugins/extensionmanager/remotespec.h
@@ -0,0 +1,84 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#pragma once
+
+#include <extensionsystem/iplugin.h>
+#include <extensionsystem/pluginspec.h>
+
+#include <utils/hostosinfo.h>
+
+#include <QJsonObject>
+
+namespace ExtensionManager::Internal {
+
+class Source
+{
+public:
+ struct Platform
+ {
+ Utils::OsType os;
+ Utils::OsArch architecture;
+ };
+ QString url;
+ std::optional<Platform> platform;
+};
+
+enum class Status {
+ Published,
+ Unpublished,
+};
+
+class RemoteSpec : public ExtensionSystem::PluginSpec
+{
+public:
+ QString description() const override;
+ QString longDescription() const override;
+
+ bool loadLibrary() override;
+ bool initializePlugin() override;
+ bool initializeExtensions() override;
+ bool delayedInitialize() override;
+ ExtensionSystem::IPlugin::ShutdownFlag stop() override;
+ void kill() override;
+ ExtensionSystem::IPlugin *plugin() const override;
+ Utils::FilePath installLocation(bool inUserFolder) const override;
+
+ Utils::Result fromJson(const QJsonObject &remoteJsonData);
+
+ QString id() const override;
+ QString displayName() const override;
+ QString vendor() const override;
+ QString vendorId() const override;
+
+ const QList<Source> sources() const;
+
+ QList<QString> tags() const;
+
+ QDateTime createdAt() const;
+ QDateTime updatedAt() const;
+ QDateTime releasedAt() const;
+
+ int downloads() const;
+ QString icon() const;
+ QString smallIcon() const;
+
+ bool isLatest() const;
+ // ?? QString license() const {}
+ Status status() const;
+ QString statusString() const;
+ QString uid() const;
+
+ bool isPack() const;
+
+ QJsonObject pluginObject() const;
+ QJsonObject packObject() const;
+
+ QStringList packPluginIds() const;
+
+private:
+ QJsonObject m_remoteJsonData;
+ bool m_isPack = false;
+};
+
+} // namespace ExtensionManager::Internal