MCPcopy Create free account
hub / github.com/PlotJuggler/PlotJuggler / appendDataSourceElement

Method appendDataSourceElement

pj_app/src/MainWindow.cpp:3455–3554  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

3453}
3454
3455QDomElement MainWindow::appendDataSourceElement(QDomDocument& doc, const QDir& layout_dir) const {
3456 const auto& sources = session_->sessionManager().loadedSources();
3457 // Do not save a data-source reference after the catalog was cleared.
3458 if (sources.empty() || session_->catalogModel().isEmpty()) {
3459 return QDomElement();
3460 }
3461
3462 // Persist only sources that still back a live dataset. A dataset whose curves
3463 // were all removed (Remove Dataset, or trashing every topic) drops out of
3464 // datasets(), so its file is neither serialized here nor resurrected on the
3465 // next reload — while loaded_sources_ itself stays intact for the quick-reload
3466 // button (which keys off lastLoadedSource, not this list). FileLoader owns the
3467 // DatasetId->path link the engine's basename-only DatasetInfo can't provide.
3468 QSet<QString> live_paths;
3469 QHash<QString, DatasetId> dataset_for_path; // reverse of sourcePathForDataset, for offset lookup
3470 for (const auto& [id, name] : session_->catalogModel().datasets()) {
3471 (void)name;
3472 if (const QString src_path = file_loader_->sourcePathForDataset(id); !src_path.isEmpty()) {
3473 live_paths.insert(src_path);
3474 dataset_for_path.insert(src_path, id);
3475 }
3476 }
3477
3478 // Source Timeline arrangement: the bar's top-to-bottom slot, persisted per
3479 // file so the vertical order round-trips (re-bound by path on reload). Build
3480 // dataset -> slot once; absent => fall back to load order on restore.
3481 QHash<DatasetId, int> timeline_order;
3482 if (source_timeline_controller_ != nullptr) {
3483 const std::vector<DatasetId> order = source_timeline_controller_->currentTrackOrder();
3484 for (int i = 0; i < static_cast<int>(order.size()); ++i) {
3485 timeline_order.insert(order[static_cast<std::size_t>(i)], i);
3486 }
3487 }
3488
3489 QDomElement wrapper = doc.createElement(QStringLiteral("previouslyLoaded_Datafiles"));
3490
3491 // One <fileInfo> per loaded file, in load order, so a multi-file session
3492 // round-trips. Old PJ4 readers that only read the first child degrade to the
3493 // first file; new readers restore them all.
3494 for (const auto& src : sources) {
3495 if (!live_paths.contains(src.path)) {
3496 continue; // dataset removed since load; don't resurrect it on reload
3497 }
3498 QDomElement file_info = doc.createElement(QStringLiteral("fileInfo"));
3499
3500 const QFileInfo info(src.path);
3501 const QString abs = info.absoluteFilePath();
3502 const QString rel = layout_dir.relativeFilePath(abs);
3503 // Prefer the relative form when the data lives at or beneath the layout
3504 // dir; fall back to absolute when it escapes. This diverges from PJ3,
3505 // which always stores relative — PJ4 avoids brittle ../.. paths so that
3506 // moving a layout file doesn't silently break the data reference.
3507 // A relative path is a "subpath" only when Qt's relativeFilePath did
3508 // NOT emit a "../" prefix or the literal ".." path. The earlier check
3509 // (`!rel.startsWith("..")`) would misclassify legitimate filenames
3510 // like "..foo" or "..bar/data.csv" as escaping the dir.
3511 const bool is_subpath = rel != QStringLiteral("..") && !rel.startsWith(QStringLiteral("../"));
3512 file_info.setAttribute(QStringLiteral("filename"), is_subpath ? rel : abs);

Callers

nothing calls this directly

Calls 14

appendJsonAsCdataFunction · 0.85
datasetsMethod · 0.80
sourcePathForDatasetMethod · 0.80
currentTrackOrderMethod · 0.80
displayOffsetMethod · 0.80
sessionManagerMethod · 0.45
emptyMethod · 0.45
isEmptyMethod · 0.45
insertMethod · 0.45
sizeMethod · 0.45
containsMethod · 0.45
setAttributeMethod · 0.45

Tested by

no test coverage detected