prune stale plugin capability overrides (#14862)
Build all / build_linux (push) Waiting to run
Build all / Build Windows ${{ matrix.arch }} (push) Waiting to run
Build all / build_macos_arch (arm64) (push) Waiting to run
Build all / build_macos_arch (x86_64) (push) Waiting to run
Build all / Build macOS Universal (push) Blocked by required conditions
Build all / Linux x86_64 (push) Blocked by required conditions
Build all / Linux aarch64 (push) Blocked by required conditions
Build all / Windows x64 (push) Blocked by required conditions
Build all / Windows arm64 (push) Blocked by required conditions
Build all / macOS arm64 (push) Blocked by required conditions
Build all / Slice check (Linux ${{ vars.SELF_HOSTED && 'x86_64' || 'aarch64' }}) (push) Blocked by required conditions
Build all / Publish Test Results (push) Blocked by required conditions
Build all / Flatpak (map[arch:aarch64 runner:ubuntu-24.04-arm]) (push) Waiting to run
Build all / Flatpak (map[arch:x86_64 runner:ubuntu-24.04]) (push) Waiting to run
Build all / build_linux (push) Waiting to run
Build all / Build Windows ${{ matrix.arch }} (push) Waiting to run
Build all / build_macos_arch (arm64) (push) Waiting to run
Build all / build_macos_arch (x86_64) (push) Waiting to run
Build all / Build macOS Universal (push) Blocked by required conditions
Build all / Linux x86_64 (push) Blocked by required conditions
Build all / Linux aarch64 (push) Blocked by required conditions
Build all / Windows x64 (push) Blocked by required conditions
Build all / Windows arm64 (push) Blocked by required conditions
Build all / macOS arm64 (push) Blocked by required conditions
Build all / Slice check (Linux ${{ vars.SELF_HOSTED && 'x86_64' || 'aarch64' }}) (push) Blocked by required conditions
Build all / Publish Test Results (push) Blocked by required conditions
Build all / Flatpak (map[arch:aarch64 runner:ubuntu-24.04-arm]) (push) Waiting to run
Build all / Flatpak (map[arch:x86_64 runner:ubuntu-24.04]) (push) Waiting to run
* prune stale plugin capability overrides * fix: configure button still shows (n) modified configs after removing * fix: add slicing_pipeline_plugin to deep_diff
This commit is contained in:
@@ -3504,7 +3504,7 @@ inline t_config_option_keys deep_diff(const ConfigBase &config_this, const Confi
|
||||
if (this_opt != nullptr && other_opt != nullptr && *this_opt != *other_opt)
|
||||
{
|
||||
//BBS: add bed_exclude_area
|
||||
if (opt_key == "printable_area" || opt_key == "bed_exclude_area" || opt_key == "compatible_prints" || opt_key == "compatible_printers" || opt_key == "thumbnails" || opt_key == "wrapping_exclude_area") {
|
||||
if (opt_key == "printable_area" || opt_key == "bed_exclude_area" || opt_key == "compatible_prints" || opt_key == "compatible_printers" || opt_key == "thumbnails" || opt_key == "wrapping_exclude_area", "slicing_pipeline_plugin") {
|
||||
// Scalar variable, or a vector variable, which is independent from number of extruders,
|
||||
// thus the vector is presented to the user as a single input.
|
||||
diff.emplace_back(opt_key);
|
||||
|
||||
+12
-1
@@ -34,6 +34,7 @@
|
||||
#include "GUI_App.hpp"
|
||||
#include "GUI_ObjectList.hpp"
|
||||
#include "slic3r/Utils/PresetUpdater.hpp"
|
||||
#include "slic3r/plugin/PluginConfig.hpp"
|
||||
#include "Plater.hpp"
|
||||
#include "MainFrame.hpp"
|
||||
#include "format.hpp"
|
||||
@@ -1795,9 +1796,19 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value)
|
||||
|
||||
// Keep this preset's "plugins" manifest in sync when a plugin picker changes, so full_config() and
|
||||
// save_to_json() always find resolved "name;uuid;capability" references and rebuild it nowhere else.
|
||||
// Also drop any plugin_config_overrides entries for a capability the change just stopped
|
||||
// referencing (e.g. a plugin removed from slicing_pipeline_plugin), so a saved preset never
|
||||
// carries configuration for a capability it no longer names. The Configure button is a separate
|
||||
// field holding its own cached copy of that value, so it needs to be told explicitly, or it
|
||||
// keeps showing the stale count until something else happens to refresh it.
|
||||
if (const ConfigOptionDef* opt_def = m_config->def()->get(opt_key);
|
||||
opt_def && opt_def->is_plugin_backed())
|
||||
opt_def && opt_def->is_plugin_backed()) {
|
||||
m_config->update_plugin_manifest();
|
||||
if (prune_stale_plugin_overrides(*m_config)) {
|
||||
if (Field* overrides_field = get_field(PLUGIN_OVERRIDES_OPTION_KEY))
|
||||
overrides_field->set_value(boost::any(m_config->opt_string(PLUGIN_OVERRIDES_OPTION_KEY)), false);
|
||||
}
|
||||
}
|
||||
|
||||
if (opt_key == "gcode_flavor" && m_type == Preset::TYPE_PRINTER) {
|
||||
if (auto printer_tab = dynamic_cast<TabPrinter*>(this))
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
|
||||
#include <libslic3r/Config.hpp>
|
||||
#include <libslic3r/PresetBundle.hpp>
|
||||
#include <libslic3r/PrintConfig.hpp>
|
||||
#include <slic3r/GUI/GUI.hpp>
|
||||
@@ -164,6 +165,20 @@ bool CapabilityConfigDocument::erase(const PluginCapabilityId& id)
|
||||
return erased;
|
||||
}
|
||||
|
||||
bool CapabilityConfigDocument::prune_unreferenced(const std::set<std::pair<PluginCapabilityType, std::string>>& referenced)
|
||||
{
|
||||
bool changed = false;
|
||||
for (auto it = m_entries.begin(); it != m_entries.end();) {
|
||||
if (referenced.count({it->first.type, it->first.name}) != 0) {
|
||||
++it;
|
||||
} else {
|
||||
it = m_entries.erase(it);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
bool CapabilityConfigDocument::empty() const
|
||||
{
|
||||
return m_entries.empty() && m_opaque_entries.empty();
|
||||
@@ -342,6 +357,50 @@ std::string serialize_plugin_overrides(const CapabilityConfigDocument& document)
|
||||
return document.empty() ? std::string() : document.serialize_entries().dump();
|
||||
}
|
||||
|
||||
bool prune_stale_plugin_overrides(DynamicConfig& config)
|
||||
{
|
||||
const auto* overrides_opt = dynamic_cast<const ConfigOptionString*>(config.option(PLUGIN_OVERRIDES_OPTION_KEY));
|
||||
if (overrides_opt == nullptr || overrides_opt->value.empty())
|
||||
return false;
|
||||
|
||||
CapabilityConfigDocument overrides;
|
||||
std::string error;
|
||||
if (!parse_plugin_overrides(overrides_opt->value, overrides, error)) {
|
||||
// Malformed text is not ours to fix up here: leave it untouched rather than risk
|
||||
// discarding data the user might still be able to recover.
|
||||
BOOST_LOG_TRIVIAL(error) << "prune_stale_plugin_overrides: " << error;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Capability names currently referenced by a plugin-backed option's value(s) — e.g.
|
||||
// slicing_pipeline_plugin's ConfigOptionStrings entries name SlicingPipeline capabilities
|
||||
// directly, the same raw values save_plugin_collection() resolves into the "plugins" manifest.
|
||||
std::set<std::pair<PluginCapabilityType, std::string>> referenced;
|
||||
const ConfigDef* def = config.def();
|
||||
for (const std::string& opt_key : config.keys()) {
|
||||
const ConfigOptionDef* opt_def = def != nullptr ? def->get(opt_key) : nullptr;
|
||||
if (opt_def == nullptr || !opt_def->is_plugin_backed())
|
||||
continue;
|
||||
|
||||
const ConfigOption* opt = config.option(opt_key);
|
||||
const PluginCapabilityType type = plugin_capability_type_from_string(opt_def->plugin_type);
|
||||
if (const auto* string_opt = dynamic_cast<const ConfigOptionString*>(opt)) {
|
||||
if (!string_opt->value.empty())
|
||||
referenced.emplace(type, string_opt->value);
|
||||
} else if (const auto* vector_opt = dynamic_cast<const ConfigOptionVectorBase*>(opt)) {
|
||||
for (const std::string& value : vector_opt->vserialize())
|
||||
if (!value.empty())
|
||||
referenced.emplace(type, value);
|
||||
}
|
||||
}
|
||||
|
||||
if (!overrides.prune_unreferenced(referenced))
|
||||
return false;
|
||||
|
||||
config.set_key_value(PLUGIN_OVERRIDES_OPTION_KEY, new ConfigOptionString(serialize_plugin_overrides(overrides)));
|
||||
return true;
|
||||
}
|
||||
|
||||
EffectiveCapabilityConfig PresetPluginConfigService::get_effective_config(const CapabilityConfigDocument& overrides,
|
||||
const PluginCapabilityId& id) const
|
||||
{
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#define PLUGIN_CONFIG_DIR "config.json"
|
||||
@@ -16,6 +18,7 @@
|
||||
namespace Slic3r {
|
||||
|
||||
class Preset;
|
||||
class DynamicConfig;
|
||||
struct CapabilityConfigEntry
|
||||
{
|
||||
PluginCapabilityId id;
|
||||
@@ -35,6 +38,9 @@ public:
|
||||
bool contains(const PluginCapabilityId& id) const;
|
||||
bool upsert(CapabilityConfigEntry entry);
|
||||
bool erase(const PluginCapabilityId& id);
|
||||
// Drops every entry whose (type, name) is not in `referenced`, e.g. capabilities a preset's
|
||||
// plugin-backed options no longer name. Returns true if anything was removed.
|
||||
bool prune_unreferenced(const std::set<std::pair<PluginCapabilityType, std::string>>& referenced);
|
||||
bool empty() const;
|
||||
nlohmann::json serialize_entries() const;
|
||||
nlohmann::json root_json() const;
|
||||
@@ -50,6 +56,14 @@ std::string plugin_overrides_of(const Preset& preset);
|
||||
bool parse_plugin_overrides(const std::string& raw, CapabilityConfigDocument& document, std::string& error);
|
||||
std::string serialize_plugin_overrides(const CapabilityConfigDocument& document);
|
||||
|
||||
// Drops plugin_config_overrides entries for capabilities no longer named by any plugin-backed
|
||||
// option's current value in `config` (e.g. slicing_pipeline_plugin cleared or switched to a
|
||||
// different capability), and writes the result back if anything changed. Called wherever a
|
||||
// plugin-backed option's value changes, so a saved preset never carries configuration for a
|
||||
// capability it no longer references. Returns true if `config` was modified, so a caller holding a
|
||||
// GUI field over PLUGIN_OVERRIDES_OPTION_KEY knows it must refresh that field's displayed value.
|
||||
bool prune_stale_plugin_overrides(DynamicConfig& config);
|
||||
|
||||
struct EffectiveCapabilityConfig
|
||||
{
|
||||
PluginCapabilityId id;
|
||||
|
||||
Reference in New Issue
Block a user