mirror of
https://github.com/logos-co/logos-basecamp.git
synced 2026-08-27 14:51:07 +00:00
feat(shell): ship main_ui as a plugin that links no logos runtime
Measured on the built artefact: main_ui.dylib DEFINES zero and IMPORTS zero of
TokenManager, StoreRegistry, LogosAPI, LogosAPIClient and logos_core_*, out of
3410 symbols read. It links Qt and nothing else from this workspace, which
nix/symbol-gate.nix enforces across the in-process image set.
Getting there needed the last non-Qt types off the boundary: the model
properties cross as QAbstractItemModel*, catalogInstallStageChanged carries an
int rather than InstallStage::Value, and the two prebuilt AppsFilterProxy
instances are declared in QML instead of owned by MainUIBackend. That last one
removes a real inversion -- PackageCoordinator called setRequiredPackages() on
a proxy the host held a pointer to; it now emits requiredPackagesResolved() and
QML binds to the republished property.
Window resolves the plugin, qobject_casts it to IShellView, checks
hostAbiVersion() against IShellHost_abi, and calls createShell(IShellHost*).
No error-label fallback widget: that degraded to something that looked like a
working app with an empty window.
Filter proxies read role constants off host-side models and InstallEnums is
used by nine host files, so app/interfaces/ gains the contract headers both
sides compile against -- the models inherit the role structs, leaving every
AppsModel::NameRole call site unchanged. The plugin's include path is
app/interfaces only, so including a host header does not compile.
Four things only running it finds:
* Logos::DesignSystem may be linked by exactly ONE image -- both linked it
and the app aborted with "Cannot add multiple registrations for
Logos.Icons"; QML module registration is process-global
* qmltyperegistrar emits no #include for a SOURCES header given as an
absolute path outside the project
* each qt_add_qml_module is its own target and inherits no include dirs
* AUTOMOC pairs header<->cpp by same-basename-same-DIRECTORY, which the
split breaks
tst_AppManagerView.qml grows five tests for the QML binding, checked with a
negative control: breaking one assertion fails qml-tests, so they run.
This commit is contained in:
committed by
Dario Lipicar
parent
9c3d023062
commit
9b8cf6e47e
+21
-13
@@ -1,5 +1,4 @@
|
||||
#include "MainUIBackend.h"
|
||||
#include "AppsFilterProxy.h"
|
||||
#include "AppsModel.h"
|
||||
#include "CoreModuleManager.h"
|
||||
#include "ModuleInstanceModel.h"
|
||||
@@ -37,20 +36,9 @@ MainUIBackend::MainUIBackend(LogosAPI* logosAPI, logos::qt::QtLogosCore* core, Q
|
||||
|
||||
m_appsModel = new AppsModel(this);
|
||||
|
||||
m_uiAppsProxy = new AppsFilterProxy(this);
|
||||
m_uiAppsProxy->setSourceModel(m_appsModel);
|
||||
m_uiAppsProxy->setTypeFilter(QStringLiteral("ui_qml"));
|
||||
m_uiAppsProxy->setExcludeMainUi(true);
|
||||
|
||||
m_requiredPackagesModel = new AppsFilterProxy(this);
|
||||
m_requiredPackagesModel->setSourceModel(m_appsModel);
|
||||
m_requiredPackagesModel->setExcludeMainUi(false);
|
||||
m_requiredPackagesModel->setInstallStateFilter(QString());
|
||||
|
||||
m_coreModuleManager = new CoreModuleManager(m_logosAPI, m_core, this);
|
||||
m_uiPluginManager = new UIPluginManager(m_logosAPI, m_coreModuleManager, this);
|
||||
m_packageCoordinator = new PackageCoordinator(m_logosAPI, m_coreModuleManager, m_uiPluginManager, m_appsModel, this);
|
||||
m_packageCoordinator->setRequiredPackagesModel(m_requiredPackagesModel);
|
||||
m_appsModel->setInstallRegistry(m_packageCoordinator->installRegistry());
|
||||
|
||||
// Setter-injection closes the cycle — UIPluginManager queries
|
||||
@@ -125,8 +113,23 @@ MainUIBackend::MainUIBackend(LogosAPI* logosAPI, logos::qt::QtLogosCore* core, Q
|
||||
this, &MainUIBackend::addApplicationDataUpdated);
|
||||
connect(m_packageCoordinator, &PackageCoordinator::launchAppRequested,
|
||||
this, &MainUIBackend::launchAppRequested);
|
||||
// The resolver's required packages are cached here and published as a
|
||||
// property; QML binds a shell-declared AppsFilterProxy to it. Nothing on
|
||||
// this side holds a pointer to that proxy.
|
||||
connect(m_packageCoordinator, &PackageCoordinator::requiredPackagesResolved,
|
||||
this, [this](const QVariantList& entries) {
|
||||
if (m_requiredPackages == entries) return;
|
||||
m_requiredPackages = entries;
|
||||
emit requiredPackagesChanged();
|
||||
});
|
||||
|
||||
// Widened to int at this hop rather than connected signal-to-signal, so
|
||||
// the conversion is written down instead of relying on the implicit
|
||||
// enum-to-int the connect check would otherwise permit silently.
|
||||
connect(m_packageCoordinator, &PackageCoordinator::catalogInstallStageChanged,
|
||||
this, &MainUIBackend::catalogInstallStageChanged);
|
||||
this, [this](const QString& name, InstallStage::Value stage) {
|
||||
emit catalogInstallStageChanged(name, static_cast<int>(stage));
|
||||
});
|
||||
connect(m_packageCoordinator, &PackageCoordinator::catalogInstallFinished,
|
||||
this, &MainUIBackend::catalogInstallFinished);
|
||||
connect(m_packageCoordinator, &PackageCoordinator::catalogInstallFailed,
|
||||
@@ -166,6 +169,11 @@ MainUIBackend::MainUIBackend(LogosAPI* logosAPI, logos::qt::QtLogosCore* core, Q
|
||||
|
||||
MainUIBackend::~MainUIBackend() = default;
|
||||
|
||||
QAbstractItemModel* MainUIBackend::appsModel() const
|
||||
{
|
||||
return m_appsModel;
|
||||
}
|
||||
|
||||
void MainUIBackend::beginShutdown()
|
||||
{
|
||||
if (m_uiPluginManager) {
|
||||
|
||||
Reference in New Issue
Block a user