mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-07-22 00:29:53 +03:00
Compare commits
3 Commits
nightly-bu
...
fix/missin
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
83815d8d77 | ||
|
|
09580e1c29 | ||
|
|
2f07eb2cd6 |
@@ -585,7 +585,35 @@ 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]() { send_plugins(); }, title, message);
|
||||
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);
|
||||
}
|
||||
|
||||
void PluginsDialog::refresh_plugins()
|
||||
|
||||
@@ -68,6 +68,7 @@ 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);
|
||||
|
||||
@@ -120,8 +120,7 @@ bool delete_plugin_root(const boost::filesystem::path& resolved_root, const std:
|
||||
}
|
||||
|
||||
if (removed_count == 0) {
|
||||
error = "Plugin folder was not found: " + resolved_root.string();
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "Deleted plugin: " << plugin_id << " from " << resolved_root.string();
|
||||
|
||||
@@ -310,6 +310,7 @@ 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) {
|
||||
@@ -328,12 +329,47 @@ void PluginManager::merge_discovered_plugins(std::vector<PluginDescriptor> disco
|
||||
return;
|
||||
}
|
||||
|
||||
// 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(); });
|
||||
// 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);
|
||||
}
|
||||
|
||||
void PluginManager::unload_and_erase_if(const std::function<bool(const Plugin&)>& should_remove,
|
||||
|
||||
@@ -132,6 +132,11 @@ 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.
|
||||
@@ -264,6 +269,7 @@ 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