| 560 | } |
| 561 | |
| 562 | bool PlotWidget::xmlLoadState(const QDomElement& plot_element, bool autozoom) { |
| 563 | if (plot_element.isNull() || plot_element.tagName() != QStringLiteral("plot")) { |
| 564 | return false; |
| 565 | } |
| 566 | |
| 567 | setStateId(plot_element.attribute(QStringLiteral("id"))); |
| 568 | setModeXY(plot_element.attribute(QStringLiteral("mode")) == QStringLiteral("XYPlot")); |
| 569 | // Line width is plot-level. New layouts store the chosen width on the <plot>. |
| 570 | // Older layouts kept the plot-level value at the stale default ("1.0") and the |
| 571 | // real width per-curve, so when the plot value is absent/default fall back to |
| 572 | // the first saved curve's pixel width. New layouts no longer write a per-curve |
| 573 | // line_width, so the fallback only fires for genuinely old files. |
| 574 | const QString plot_line_width = plot_element.attribute(QStringLiteral("line_width")); |
| 575 | const QDomElement first_curve = plot_element.firstChildElement(QStringLiteral("curve")); |
| 576 | if ((plot_line_width.isEmpty() || plot_line_width == QStringLiteral("1.0")) && |
| 577 | first_curve.hasAttribute(QStringLiteral("line_width"))) { |
| 578 | setLineWidth(lineWidthFromPixels(first_curve.attribute(QStringLiteral("line_width")).toDouble())); |
| 579 | } else { |
| 580 | setLineWidth(lineWidthFromString(plot_line_width.isEmpty() ? QStringLiteral("1.0") : plot_line_width)); |
| 581 | } |
| 582 | // Style is plot-level. New layouts store it on the <plot>; for older layouts |
| 583 | // that stored it per <curve>, fall back to the first saved curve. setDefaultStyle |
| 584 | // restyles the plot and is inherited by curves added after the load. |
| 585 | QString style_attr = plot_element.attribute(QStringLiteral("style")); |
| 586 | if (style_attr.isEmpty()) { |
| 587 | style_attr = first_curve.attribute(QStringLiteral("style"), QStringLiteral("Lines")); |
| 588 | } |
| 589 | setDefaultStyle(curveStyleFromString(style_attr)); |
| 590 | setTrackerEnabled( |
| 591 | plot_element.attribute(QStringLiteral("tracker_enabled"), QStringLiteral("true")) == QStringLiteral("true")); |
| 592 | qwtPlot()->setTitle(plot_element.attribute(QStringLiteral("title"))); |
| 593 | |
| 594 | const bool was_loading_state = loading_state_; |
| 595 | loading_state_ = true; |
| 596 | |
| 597 | std::set<QString> desired_keys; |
| 598 | for (QDomElement curve_element = plot_element.firstChildElement(QStringLiteral("curve")); !curve_element.isNull(); |
| 599 | curve_element = curve_element.nextSiblingElement(QStringLiteral("curve"))) { |
| 600 | if (isXYPlot() && curve_element.hasAttribute(QStringLiteral("curve_x")) && |
| 601 | curve_element.hasAttribute(QStringLiteral("curve_y"))) { |
| 602 | desired_keys.insert(curveKey( |
| 603 | curve_element.attribute(QStringLiteral("name")), curve_element.attribute(QStringLiteral("curve_x")), |
| 604 | curve_element.attribute(QStringLiteral("curve_y")))); |
| 605 | } else { |
| 606 | desired_keys.insert(curveKey(curve_element.attribute(QStringLiteral("name")))); |
| 607 | } |
| 608 | } |
| 609 | |
| 610 | QStringList remove_titles; |
| 611 | for (const CurveInfo& info : curveList()) { |
| 612 | if (info.curve == nullptr) { |
| 613 | continue; |
| 614 | } |
| 615 | QString existing_key = curveKey(info.source_name); |
| 616 | if (auto* xy_series = dynamic_cast<PointSeriesXY*>(info.curve->data())) { |
| 617 | existing_key = curveKey(info.source_name, xy_series->xSource().name, xy_series->ySource().name); |
| 618 | } |
| 619 | if (desired_keys.find(existing_key) == desired_keys.end()) { |
no test coverage detected