core: support root: and root:/ paths for the config root

This works everywhere urls are accepted and rewrites them from the
config root as a qsintercept url.
This commit is contained in:
outfoxxed 2024-05-29 15:07:10 -07:00
parent 33fac67798
commit 0519acf1d6
Signed by: outfoxxed
GPG key ID: 4C88A185FB89301E
7 changed files with 48 additions and 8 deletions

View file

@ -27,8 +27,10 @@
static QHash<QQmlEngine*, EngineGeneration*> g_generations; // NOLINT static QHash<QQmlEngine*, EngineGeneration*> g_generations; // NOLINT
EngineGeneration::EngineGeneration(QmlScanner scanner) EngineGeneration::EngineGeneration(const QDir& rootPath, QmlScanner scanner)
: scanner(std::move(scanner)) : rootPath(rootPath)
, scanner(std::move(scanner))
, urlInterceptor(this->rootPath)
, interceptNetFactory(this->scanner.qmldirIntercepts) , interceptNetFactory(this->scanner.qmldirIntercepts)
, engine(new QQmlEngine()) { , engine(new QQmlEngine()) {
g_generations.insert(this->engine, this); g_generations.insert(this->engine, this);

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <qcontainerfwd.h> #include <qcontainerfwd.h>
#include <qdir.h>
#include <qfilesystemwatcher.h> #include <qfilesystemwatcher.h>
#include <qobject.h> #include <qobject.h>
#include <qpair.h> #include <qpair.h>
@ -19,7 +20,7 @@ class EngineGeneration: public QObject {
Q_OBJECT; Q_OBJECT;
public: public:
explicit EngineGeneration(QmlScanner scanner); explicit EngineGeneration(const QDir& rootPath, QmlScanner scanner);
~EngineGeneration() override; ~EngineGeneration() override;
Q_DISABLE_COPY_MOVE(EngineGeneration); Q_DISABLE_COPY_MOVE(EngineGeneration);
@ -33,6 +34,7 @@ public:
static EngineGeneration* findObjectGeneration(QObject* object); static EngineGeneration* findObjectGeneration(QObject* object);
RootWrapper* wrapper = nullptr; RootWrapper* wrapper = nullptr;
QDir rootPath;
QmlScanner scanner; QmlScanner scanner;
QsUrlInterceptor urlInterceptor; QsUrlInterceptor urlInterceptor;
QsInterceptNetworkAccessManagerFactory interceptNetFactory; QsInterceptNetworkAccessManagerFactory interceptNetFactory;

View file

@ -16,7 +16,22 @@
Q_LOGGING_CATEGORY(logQsIntercept, "quickshell.interceptor", QtWarningMsg); Q_LOGGING_CATEGORY(logQsIntercept, "quickshell.interceptor", QtWarningMsg);
QUrl QsUrlInterceptor::intercept(const QUrl& url, QQmlAbstractUrlInterceptor::DataType type) { QUrl QsUrlInterceptor::intercept(
const QUrl& originalUrl,
QQmlAbstractUrlInterceptor::DataType type
) {
auto url = originalUrl;
if (url.scheme() == "root") {
url.setScheme("qsintercept");
auto path = url.path();
if (path.startsWith('/')) path = path.sliced(1);
url.setPath(this->configRoot.filePath(path));
qCDebug(logQsIntercept) << "Rewrote root intercept" << originalUrl << "to" << url;
}
// Some types such as Image take into account where they are loading from, and force // Some types such as Image take into account where they are loading from, and force
// asynchronous loading over a network. qsintercept is considered to be over a network. // asynchronous loading over a network. qsintercept is considered to be over a network.
if (type == QQmlAbstractUrlInterceptor::DataType::UrlString && url.scheme() == "qsintercept") { if (type == QQmlAbstractUrlInterceptor::DataType::UrlString && url.scheme() == "qsintercept") {

View file

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <qdir.h>
#include <qhash.h> #include <qhash.h>
#include <qloggingcategory.h> #include <qloggingcategory.h>
#include <qnetworkaccessmanager.h> #include <qnetworkaccessmanager.h>
@ -13,7 +14,12 @@ Q_DECLARE_LOGGING_CATEGORY(logQsIntercept);
class QsUrlInterceptor: public QQmlAbstractUrlInterceptor { class QsUrlInterceptor: public QQmlAbstractUrlInterceptor {
public: public:
QUrl intercept(const QUrl& url, QQmlAbstractUrlInterceptor::DataType type) override; explicit QsUrlInterceptor(const QDir& configRoot): configRoot(configRoot) {}
QUrl intercept(const QUrl& originalUrl, QQmlAbstractUrlInterceptor::DataType type) override;
private:
QDir configRoot;
}; };
class QsInterceptDataReply: public QNetworkReply { class QsInterceptDataReply: public QNetworkReply {

View file

@ -42,10 +42,11 @@ RootWrapper::~RootWrapper() {
} }
void RootWrapper::reloadGraph(bool hard) { void RootWrapper::reloadGraph(bool hard) {
auto scanner = QmlScanner(); auto rootPath = QFileInfo(this->rootPath).dir();
auto scanner = QmlScanner(rootPath);
scanner.scanQmlFile(this->rootPath); scanner.scanQmlFile(this->rootPath);
auto* generation = new EngineGeneration(std::move(scanner)); auto* generation = new EngineGeneration(rootPath, std::move(scanner));
generation->wrapper = this; generation->wrapper = this;
// todo: move into EngineGeneration // todo: move into EngineGeneration

View file

@ -103,7 +103,15 @@ bool QmlScanner::scanQmlFile(const QString& path) {
this->scanDir(currentdir.path()); this->scanDir(currentdir.path());
for (auto& import: imports) { for (auto& import: imports) {
auto ipath = currentdir.filePath(import); QString ipath;
if (import.startsWith("root:")) {
auto path = import.sliced(5);
if (path.startsWith('/')) path = path.sliced(1);
ipath = this->rootPath.filePath(path);
} else {
ipath = currentdir.filePath(import);
}
auto cpath = QFileInfo(ipath).canonicalFilePath(); auto cpath = QFileInfo(ipath).canonicalFilePath();
if (cpath.isEmpty()) { if (cpath.isEmpty()) {

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <qcontainerfwd.h> #include <qcontainerfwd.h>
#include <qdir.h>
#include <qhash.h> #include <qhash.h>
#include <qloggingcategory.h> #include <qloggingcategory.h>
#include <qvector.h> #include <qvector.h>
@ -10,6 +11,8 @@ Q_DECLARE_LOGGING_CATEGORY(logQmlScanner);
// expects canonical paths // expects canonical paths
class QmlScanner { class QmlScanner {
public: public:
QmlScanner(const QDir& rootPath): rootPath(rootPath) {}
void scanDir(const QString& path); void scanDir(const QString& path);
// returns if the file has a singleton // returns if the file has a singleton
bool scanQmlFile(const QString& path); bool scanQmlFile(const QString& path);
@ -17,4 +20,7 @@ public:
QVector<QString> scannedDirs; QVector<QString> scannedDirs;
QVector<QString> scannedFiles; QVector<QString> scannedFiles;
QHash<QString, QString> qmldirIntercepts; QHash<QString, QString> qmldirIntercepts;
private:
QDir rootPath;
}; };