mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-07-15 23:12:08 +00:00
212 lines
8.0 KiB
C++
212 lines
8.0 KiB
C++
#include "PluginsConfigDialog.hpp"
|
|
|
|
#include "GUI_App.hpp"
|
|
#include "I18N.hpp"
|
|
#include "format.hpp"
|
|
|
|
#include <libslic3r/Preset.hpp>
|
|
#include <libslic3r/PresetBundle.hpp>
|
|
#include <slic3r/plugin/PluginConfig.hpp>
|
|
#include <slic3r/plugin/PluginManager.hpp>
|
|
#include <slic3r/plugin/PluginResolver.hpp>
|
|
#include <slic3r/plugin/PythonInterpreter.hpp>
|
|
|
|
#include <boost/log/trivial.hpp>
|
|
|
|
namespace Slic3r { namespace GUI {
|
|
|
|
namespace {
|
|
|
|
wxString preset_type_title(Preset::Type type)
|
|
{
|
|
switch (type) {
|
|
case Preset::TYPE_PRINT: return _L("Process plugins");
|
|
case Preset::TYPE_FILAMENT: return _L("Filament plugins");
|
|
case Preset::TYPE_PRINTER: return _L("Printer plugins");
|
|
default: return _L("Plugins");
|
|
}
|
|
}
|
|
|
|
} // namespace
|
|
|
|
PluginsConfigDialog::PluginsConfigDialog(wxWindow* parent, Preset::Type type, const std::string& overrides_json)
|
|
: WebViewHostDialog(parent, wxID_ANY, preset_type_title(type))
|
|
, m_type(type)
|
|
{
|
|
// On failure the document stays empty and every row goes read-only (see m_parse_error), so a preset
|
|
// we cannot understand is never silently overwritten.
|
|
if (!parse_plugin_overrides(overrides_json, m_overrides, m_parse_error))
|
|
BOOST_LOG_TRIVIAL(error) << "Plugins Config dialog: " << m_parse_error;
|
|
|
|
create_webview("web/dialog/PluginsConfigDialog/index.html", preset_type_title(type), wxSize(820, 660),
|
|
wxSize(640, 520));
|
|
}
|
|
|
|
PluginsConfigDialog::~PluginsConfigDialog() = default;
|
|
|
|
const Preset* PluginsConfigDialog::current_preset() const
|
|
{
|
|
const PresetBundle* bundle = wxGetApp().preset_bundle;
|
|
if (bundle == nullptr)
|
|
return nullptr;
|
|
|
|
switch (m_type) {
|
|
case Preset::TYPE_PRINT: return &bundle->prints.get_edited_preset();
|
|
case Preset::TYPE_PRINTER: return &bundle->printers.get_edited_preset();
|
|
case Preset::TYPE_FILAMENT: return &bundle->filaments.get_edited_preset();
|
|
default: return nullptr;
|
|
}
|
|
}
|
|
|
|
PluginCapabilityIdentifier PluginsConfigDialog::identifier_from(const nlohmann::json& payload) const
|
|
{
|
|
return {plugin_capability_type_from_string(payload.value("capability_type", "")),
|
|
payload.value("capability_name", ""),
|
|
payload.value("plugin_key", "")};
|
|
}
|
|
|
|
void PluginsConfigDialog::on_script_message(const nlohmann::json& payload)
|
|
{
|
|
if (handle_common_script_command(payload))
|
|
return;
|
|
|
|
const std::string command = payload.value("command", "");
|
|
if (command == "request_capabilities") {
|
|
send_capabilities();
|
|
return;
|
|
}
|
|
|
|
const PluginCapabilityIdentifier id = identifier_from(payload);
|
|
|
|
if (command == "get_capability_config") {
|
|
send_capability_config(id);
|
|
} else if (command == "save_capability_config") {
|
|
if (!m_parse_error.empty()) {
|
|
send_save_error(id, m_parse_error);
|
|
return;
|
|
}
|
|
|
|
nlohmann::json value = payload.contains("config") ? payload.at("config") : nlohmann::json::object();
|
|
if (value.is_string()) {
|
|
value = nlohmann::json::parse(value.get<std::string>(), nullptr, /* allow_exceptions */ false);
|
|
if (value.is_discarded()) {
|
|
send_save_error(id, into_u8(_L("The configuration is not valid JSON. Your changes were not saved.")));
|
|
return;
|
|
}
|
|
}
|
|
|
|
const MutationResult result = m_service.set_preset_override(m_overrides, id, value);
|
|
if (!result.ok) {
|
|
send_save_error(id, result.error);
|
|
return;
|
|
}
|
|
send_capability_config(id);
|
|
show_status(_L("Configuration updated. Save the preset to persist it."), "success");
|
|
} else if (command == "remove_preset_override") {
|
|
// "Restore defaults" for a preset means holding no override at all: the capability falls back
|
|
// to the global configuration, not to the plugin's own get_default_config().
|
|
if (!m_parse_error.empty()) {
|
|
send_save_error(id, m_parse_error);
|
|
return;
|
|
}
|
|
|
|
const int rc = wxMessageBox(wxString::Format(_L("Restore the default configuration for \"%s\"?\n\n"
|
|
"This discards the preset's override and uses the global configuration."),
|
|
from_u8(id.name)),
|
|
_L("Restore defaults"), wxYES_NO | wxNO_DEFAULT | wxICON_WARNING, this);
|
|
if (rc != wxYES)
|
|
return;
|
|
|
|
const MutationResult result = m_service.remove_preset_override(m_overrides, id);
|
|
if (!result.ok) {
|
|
send_save_error(id, result.error);
|
|
return;
|
|
}
|
|
send_capability_config(id);
|
|
show_status(_L("Using global configuration. Save the preset to persist it."), "success");
|
|
}
|
|
}
|
|
|
|
void PluginsConfigDialog::send_capabilities()
|
|
{
|
|
const Preset* preset = current_preset();
|
|
if (preset == nullptr)
|
|
return;
|
|
|
|
nlohmann::json response;
|
|
response["command"] = "list_capabilities";
|
|
response["preset_type"] = static_cast<int>(m_type);
|
|
response["title"] = into_u8(preset_type_title(m_type));
|
|
response["preset_name"] = preset->name;
|
|
response["data"] = PluginConfig::capabilities_payload(capabilities_in_use(m_type, *preset));
|
|
|
|
BOOST_LOG_TRIVIAL(info) << "Prepared " << response["data"].size() << " capability rows for the Plugins Config dialog";
|
|
call_web_handler(response);
|
|
}
|
|
|
|
void PluginsConfigDialog::send_capability_config(const PluginCapabilityIdentifier& id)
|
|
{
|
|
const Preset* preset = current_preset();
|
|
|
|
nlohmann::json response;
|
|
response["command"] = "capability_config";
|
|
response["plugin_key"] = id.plugin_key;
|
|
response["capability_name"] = id.name;
|
|
response["capability_type"] = plugin_capability_type_to_string(id.type);
|
|
response["config"] = nlohmann::json::object();
|
|
response["custom_html"] = "";
|
|
response["error"] = "";
|
|
|
|
const auto cap = PluginManager::instance().get_loader().get_plugin_capability_by_name(id);
|
|
if (!cap || preset == nullptr) {
|
|
response["error"] = into_u8(_L("This capability is no longer available."));
|
|
call_web_handler(response);
|
|
return;
|
|
}
|
|
|
|
const EffectiveCapabilityConfig effective = m_service.get_effective_config(m_overrides, id);
|
|
response["config"] = effective.config;
|
|
response["source"] = plugin_config_source_to_string(effective.source);
|
|
response["has_preset_override"] = effective.has_preset_override;
|
|
response["has_base_config"] = effective.has_base_config;
|
|
response["stored_plugin_version"] = effective.stored_plugin_version;
|
|
response["running_plugin_version"] = effective.running_plugin_version;
|
|
response["read_only"] = !m_parse_error.empty();
|
|
if (!m_parse_error.empty())
|
|
response["error"] = m_parse_error;
|
|
|
|
if (cap->has_config_ui) {
|
|
try {
|
|
wxBusyCursor busy;
|
|
PythonGILState gil;
|
|
response["custom_html"] = cap->instance->get_config_ui();
|
|
} catch (const std::exception& ex) {
|
|
response["error"] = into_u8(GUI::format_wxstr(_L("The plugin's configuration UI failed to load (%1%). Showing the default editor."),
|
|
from_u8(ex.what())));
|
|
}
|
|
}
|
|
|
|
call_web_handler(response);
|
|
}
|
|
|
|
void PluginsConfigDialog::send_save_error(const PluginCapabilityIdentifier& id, const std::string& error)
|
|
{
|
|
call_web_handler({{"command", "capability_config_saved"},
|
|
{"plugin_key", id.plugin_key},
|
|
{"capability_name", id.name},
|
|
{"capability_type", plugin_capability_type_to_string(id.type)},
|
|
{"ok", false},
|
|
{"error", error}});
|
|
}
|
|
|
|
void PluginsConfigDialog::show_status(const wxString& message, const char* level)
|
|
{
|
|
nlohmann::json payload;
|
|
payload["command"] = "status_message";
|
|
payload["level"] = level;
|
|
payload["message"] = into_u8(message);
|
|
call_web_handler(payload);
|
|
}
|
|
|
|
}} // namespace Slic3r::GUI
|