mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-07-22 16:50:11 +03:00
Compare commits
2 Commits
fix/missin
...
fix/plugin
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4c2d9b4b18 | ||
|
|
28feb8480e |
@@ -585,35 +585,7 @@ bool PluginsDialog::get_descriptor(const std::string& plugin_key, PluginDescript
|
||||
|
||||
void PluginsDialog::refresh_plugin_metadata_async(const wxString& title, const wxString& message, bool fetch_cloud)
|
||||
{
|
||||
run_with_dialog([fetch_cloud]() { refresh_plugin_metadata_blocking(fetch_cloud); }, [this]() {
|
||||
prompt_for_missing_plugins();
|
||||
send_plugins();
|
||||
}, title, message);
|
||||
}
|
||||
|
||||
void PluginsDialog::prompt_for_missing_plugins()
|
||||
{
|
||||
PluginManager& manager = PluginManager::instance();
|
||||
const std::vector<PluginDescriptor> missing = manager.get_missing_plugin_descriptors();
|
||||
if (missing.empty())
|
||||
return;
|
||||
|
||||
wxString names;
|
||||
std::vector<std::string> keys;
|
||||
keys.reserve(missing.size());
|
||||
for (const PluginDescriptor& plugin : missing) {
|
||||
keys.push_back(plugin.plugin_key);
|
||||
names += "\n- ";
|
||||
names += plugin_display_name(plugin.plugin_key);
|
||||
}
|
||||
|
||||
const int result = wxMessageBox(
|
||||
wxString::Format(_L("The following installed plugins were not found on disk:\n%s\n\nRemove them from OrcaSlicer?"), names),
|
||||
_L("Missing Plugins"), wxYES_NO | wxNO_DEFAULT | wxICON_WARNING, this);
|
||||
restore_z_order();
|
||||
|
||||
if (result == wxYES)
|
||||
manager.remove_missing_plugins(keys);
|
||||
run_with_dialog([fetch_cloud]() { refresh_plugin_metadata_blocking(fetch_cloud); }, [this]() { send_plugins(); }, title, message);
|
||||
}
|
||||
|
||||
void PluginsDialog::refresh_plugins()
|
||||
|
||||
@@ -68,7 +68,6 @@ private:
|
||||
bool get_descriptor(const std::string& plugin_key, Slic3r::PluginDescriptor& descriptor) const;
|
||||
|
||||
void refresh_plugin_metadata_async(const wxString& title, const wxString& message, bool fetch_cloud);
|
||||
void prompt_for_missing_plugins();
|
||||
void refresh_plugins();
|
||||
void toggle_plugin(const std::string& plugin_key, bool enabled);
|
||||
void toggle_plugin_capability(const std::string& plugin_key, PluginCapabilityType type, const std::string& capability_name, bool enabled);
|
||||
|
||||
@@ -66,6 +66,10 @@ struct PluginDescriptor
|
||||
std::string error; // Blocking error message. Non-empty means the plugin is in an error state.
|
||||
std::optional<CloudPluginState> cloud; // Extra cloud state layered on top of a normal plugin descriptor.
|
||||
bool metadata_valid = false; // Manifest/package validity stays separate from the user-facing error field.
|
||||
// Whether the discovery pass successfully read .install_state.json. This is transient scan
|
||||
// metadata, used to distinguish an explicit enabled=false from a sidecar that was unavailable
|
||||
// during a live package replacement.
|
||||
bool install_state_valid = false;
|
||||
// Package auto-load flag, read from .install_state.json. Defaults to FALSE: a package with no
|
||||
// sidecar has never been installed through Orca and carries no auto-load intent, so it must not
|
||||
// be loaded at startup. Installing a package writes the sidecar with enabled = true.
|
||||
|
||||
@@ -120,7 +120,8 @@ bool delete_plugin_root(const boost::filesystem::path& resolved_root, const std:
|
||||
}
|
||||
|
||||
if (removed_count == 0) {
|
||||
return true;
|
||||
error = "Plugin folder was not found: " + resolved_root.string();
|
||||
return false;
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "Deleted plugin: " << plugin_id << " from " << resolved_root.string();
|
||||
@@ -171,7 +172,7 @@ void scan_plugin_directory(const std::string& dir_path, std::vector<PluginDescri
|
||||
// its error, rather than dropping it silently.
|
||||
if (entry_path.empty()) {
|
||||
descriptor.set_error(entry_error);
|
||||
read_install_state(plugin_dir, descriptor);
|
||||
descriptor.install_state_valid = read_install_state(plugin_dir, descriptor);
|
||||
assign_discovered_plugin_key(descriptor, plugin_dir);
|
||||
out.push_back(std::move(descriptor));
|
||||
BOOST_LOG_TRIVIAL(warning) << "Invalid plugin package: " << plugin_dir.string() << " - " << out.back().error;
|
||||
@@ -184,7 +185,7 @@ void scan_plugin_directory(const std::string& dir_path, std::vector<PluginDescri
|
||||
read_python_plugin_metadata(entry_path, descriptor, meta_error);
|
||||
if (!parsed) {
|
||||
descriptor.set_error(meta_error);
|
||||
read_install_state(plugin_dir, descriptor);
|
||||
descriptor.install_state_valid = read_install_state(plugin_dir, descriptor);
|
||||
assign_discovered_plugin_key(descriptor, entry_path);
|
||||
out.push_back(std::move(descriptor));
|
||||
BOOST_LOG_TRIVIAL(warning) << (is_wheel ? "Invalid wheel plugin: " : "Invalid .py plugin: ")
|
||||
@@ -198,7 +199,7 @@ void scan_plugin_directory(const std::string& dir_path, std::vector<PluginDescri
|
||||
|
||||
// Cloud identity and the package-level auto-load flag. plugin_key is always derived
|
||||
// below, never read from the sidecar.
|
||||
read_install_state(plugin_dir, descriptor);
|
||||
descriptor.install_state_valid = read_install_state(plugin_dir, descriptor);
|
||||
assign_discovered_plugin_key(descriptor, entry_path);
|
||||
|
||||
out.push_back(std::move(descriptor));
|
||||
@@ -734,11 +735,11 @@ bool extract_zip_to_directory(const boost::filesystem::path& zip_path, const boo
|
||||
return true;
|
||||
}
|
||||
|
||||
void read_install_state(const boost::filesystem::path& plugin_dir, PluginDescriptor& entry)
|
||||
bool read_install_state(const boost::filesystem::path& plugin_dir, PluginDescriptor& entry)
|
||||
{
|
||||
PluginInstallState state;
|
||||
if (!read_install_state(plugin_dir, state))
|
||||
return;
|
||||
return false;
|
||||
|
||||
// The cloud identity and the persisted installed version are read back. plugin_key
|
||||
// is always derived by the catalog scan (filename for local, the cloud uuid for
|
||||
@@ -755,6 +756,7 @@ void read_install_state(const boost::filesystem::path& plugin_dir, PluginDescrip
|
||||
// capability has no existence — and so no state — until it is materialized, at which point the
|
||||
// loader seeds the flag onto the capability itself.
|
||||
entry.enabled = state.enabled;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool read_install_state(const boost::filesystem::path& plugin_dir, PluginInstallState& out)
|
||||
|
||||
@@ -156,8 +156,9 @@ bool write_install_state(const boost::filesystem::path& plugin_dir, const Plugin
|
||||
// Convenience overload: write(dir, entry, /*enabled=*/true, /*capabilities=*/{}).
|
||||
bool write_install_state(const boost::filesystem::path& plugin_dir, const PluginDescriptor& entry);
|
||||
|
||||
// Reads only the cloud identity (uuid) back into the descriptor; plugin_key is always derived.
|
||||
void read_install_state(const boost::filesystem::path& plugin_dir, PluginDescriptor& entry);
|
||||
// Reads install state back into the descriptor; plugin_key is always derived. Returns whether the
|
||||
// sidecar was present and valid.
|
||||
bool read_install_state(const boost::filesystem::path& plugin_dir, PluginDescriptor& entry);
|
||||
// Full read of the sidecar; returns false if there is no/invalid sidecar.
|
||||
bool read_install_state(const boost::filesystem::path& plugin_dir, PluginInstallState& out);
|
||||
|
||||
|
||||
@@ -310,7 +310,6 @@ void PluginManager::merge_discovered_plugins(std::vector<PluginDescriptor> disco
|
||||
}
|
||||
|
||||
seen.push_back(descriptor.plugin_key);
|
||||
m_missing_plugin_keys.erase(descriptor.plugin_key);
|
||||
|
||||
Plugin* existing = find_plugin_locked(descriptor.plugin_key);
|
||||
if (existing == nullptr) {
|
||||
@@ -322,6 +321,8 @@ void PluginManager::merge_discovered_plugins(std::vector<PluginDescriptor> disco
|
||||
|
||||
// A manifest-only rescan has nothing to say about capabilities, so the live module and
|
||||
// instances are left alone.
|
||||
if (!descriptor.install_state_valid)
|
||||
descriptor.enabled = existing->descriptor.enabled;
|
||||
existing->descriptor = std::move(descriptor);
|
||||
}
|
||||
|
||||
@@ -329,47 +330,12 @@ void PluginManager::merge_discovered_plugins(std::vector<PluginDescriptor> disco
|
||||
return;
|
||||
}
|
||||
|
||||
// A package can be temporarily absent while an external side-loader replaces it. Keep the
|
||||
// descriptor and its persisted enable state until the user explicitly removes the missing
|
||||
// entry, or a later scan rediscovers it. In particular, do not unload here: the unload callback
|
||||
// would turn a transient filesystem gap into enabled=false in the sidecar.
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
for (const Plugin& plugin : m_plugins) {
|
||||
if (plugin.descriptor.has_local_package() &&
|
||||
std::find(seen.begin(), seen.end(), plugin.descriptor.plugin_key) == seen.end())
|
||||
m_missing_plugin_keys.insert(plugin.descriptor.plugin_key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<PluginDescriptor> PluginManager::get_missing_plugin_descriptors() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
std::vector<PluginDescriptor> result;
|
||||
result.reserve(m_missing_plugin_keys.size());
|
||||
for (const Plugin& plugin : m_plugins)
|
||||
if (m_missing_plugin_keys.count(plugin.descriptor.plugin_key) != 0)
|
||||
result.push_back(plugin.descriptor);
|
||||
return result;
|
||||
}
|
||||
|
||||
void PluginManager::remove_missing_plugins(const std::vector<std::string>& plugin_keys)
|
||||
{
|
||||
const std::unordered_set<std::string> requested(plugin_keys.begin(), plugin_keys.end());
|
||||
|
||||
// The predicate is evaluated only while m_mutex is held by unload_and_erase_if(). Checking the
|
||||
// current missing set here prevents a package that reappeared between the dialog and removal
|
||||
// from being erased.
|
||||
unload_and_erase_if([this, &requested](const Plugin& plugin) {
|
||||
return requested.count(plugin.descriptor.plugin_key) != 0 &&
|
||||
m_missing_plugin_keys.count(plugin.descriptor.plugin_key) != 0;
|
||||
});
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
for (const std::string& plugin_key : requested)
|
||||
m_missing_plugin_keys.erase(plugin_key);
|
||||
// Unloading may call Python and lifecycle subscribers may re-enter the manager, so never do it
|
||||
// while holding m_mutex. unload_and_erase_if() retries until no matching entry is loaded at the
|
||||
// moment of erase, in case another caller starts a load between the initial snapshot and the
|
||||
// teardown.
|
||||
unload_and_erase_if(
|
||||
[&seen](const Plugin& plugin) { return std::find(seen.begin(), seen.end(), plugin.descriptor.plugin_key) == seen.end(); });
|
||||
}
|
||||
|
||||
void PluginManager::unload_and_erase_if(const std::function<bool(const Plugin&)>& should_remove,
|
||||
|
||||
@@ -132,11 +132,6 @@ public:
|
||||
bool try_get_plugin_descriptor(const std::string& plugin_key, PluginDescriptor& out) const;
|
||||
// Same, but only for packages that are loadable (i.e. not an invalid package).
|
||||
bool try_get_valid_plugin_descriptor(const std::string& plugin_key, PluginDescriptor& out) const;
|
||||
// Packages that were present in the previous discovery pass but were not found on disk in the
|
||||
// latest rescan. They are retained until the user explicitly removes them or a later scan finds
|
||||
// them again.
|
||||
std::vector<PluginDescriptor> get_missing_plugin_descriptors() const;
|
||||
void remove_missing_plugins(const std::vector<std::string>& plugin_keys);
|
||||
// Packages whose .install_state.json marks them for auto-load.
|
||||
std::vector<std::string> get_enabled_plugin_keys() const;
|
||||
// The package owning a loaded capability, for the by-name dispatch path.
|
||||
@@ -269,7 +264,6 @@ private:
|
||||
|
||||
// Every discovered plugin, loaded or not. module == nullptr => not loaded.
|
||||
std::vector<Plugin> m_plugins;
|
||||
std::unordered_set<std::string> m_missing_plugin_keys;
|
||||
|
||||
std::unordered_set<std::string> m_load_in_progress;
|
||||
// Keys whose in-flight load has been cancelled. Cancellation does NOT remove the key from
|
||||
|
||||
Reference in New Issue
Block a user