Enqueue a load and pump the event loop until it completes. Single-instance loads run progressively on a worker thread, so completion is asynchronous (fileLoaded/fileLoadFailed); fanout / layout-reuse / failure complete synchronously inside loadFile (the signal fires before exec(), so done is already set and we skip the loop).
| 115 | // synchronously inside loadFile (the signal fires before exec(), so done is |
| 116 | // already set and we skip the loop). |
| 117 | [[nodiscard]] bool loadAndWait(const QString& path, const PJ::LoadHints& hints) { |
| 118 | QEventLoop loop; |
| 119 | bool ok = false; |
| 120 | bool done = false; |
| 121 | const auto on_loaded = QObject::connect( |
| 122 | loader_.get(), &PJ::FileLoader::fileLoaded, &loop, |
| 123 | [&](const QString&, const QString&, const QString&, const QString&) { |
| 124 | ok = true; |
| 125 | done = true; |
| 126 | loop.quit(); |
| 127 | }); |
| 128 | const auto on_failed = |
| 129 | QObject::connect(loader_.get(), &PJ::FileLoader::fileLoadFailed, &loop, [&](const QString&, const QString&) { |
| 130 | ok = false; |
| 131 | done = true; |
| 132 | loop.quit(); |
| 133 | }); |
| 134 | loader_->loadFile(path, nullptr, hints); |
| 135 | if (!done) { |
| 136 | QTimer::singleShot(10000, &loop, [&loop]() { loop.quit(); }); // safety: fail, don't hang CI |
| 137 | loop.exec(); |
| 138 | } |
| 139 | QObject::disconnect(on_loaded); |
| 140 | QObject::disconnect(on_failed); |
| 141 | return ok; |
| 142 | } |
| 143 | |
| 144 | [[nodiscard]] bool load(const QString& path) { |
| 145 | return loadAndWait(path, loadHints()); |