mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-07-22 18:32:16 +00:00
Compare commits
6 Commits
revert/rev
...
fix/plugin
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bc6ae243ca | ||
|
|
b121051220 | ||
|
|
242e100feb | ||
|
|
2a46bd1384 | ||
|
|
ddbbc7f7f2 | ||
|
|
3a48086f5d |
@@ -201,9 +201,12 @@ if (WIN32)
|
|||||||
if(MSVC)
|
if(MSVC)
|
||||||
target_link_options(OrcaSlicer_app_gui PUBLIC "$<$<CONFIG:RELEASE>:/DEBUG>")
|
target_link_options(OrcaSlicer_app_gui PUBLIC "$<$<CONFIG:RELEASE>:/DEBUG>")
|
||||||
endif()
|
endif()
|
||||||
target_compile_definitions(OrcaSlicer_app_gui PRIVATE -DSLIC3R_WRAPPER_NOCONSOLE)
|
target_compile_definitions(OrcaSlicer_app_gui PRIVATE "$<$<NOT:$<CONFIG:RelWithDebInfo>>:SLIC3R_WRAPPER_NOCONSOLE>")
|
||||||
add_dependencies(OrcaSlicer_app_gui OrcaSlicer)
|
add_dependencies(OrcaSlicer_app_gui OrcaSlicer)
|
||||||
set_target_properties(OrcaSlicer_app_gui PROPERTIES OUTPUT_NAME "orca-slicer")
|
set_target_properties(OrcaSlicer_app_gui PROPERTIES
|
||||||
|
OUTPUT_NAME "orca-slicer"
|
||||||
|
WIN32_EXECUTABLE "$<NOT:$<CONFIG:RelWithDebInfo>>"
|
||||||
|
)
|
||||||
target_link_libraries(OrcaSlicer_app_gui PRIVATE boost_headeronly)
|
target_link_libraries(OrcaSlicer_app_gui PRIVATE boost_headeronly)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
|||||||
@@ -535,6 +535,7 @@ endif ()
|
|||||||
encoding_check(libslic3r)
|
encoding_check(libslic3r)
|
||||||
|
|
||||||
target_compile_definitions(libslic3r PUBLIC -DUSE_TBB -DTBB_USE_CAPTURED_EXCEPTION=0)
|
target_compile_definitions(libslic3r PUBLIC -DUSE_TBB -DTBB_USE_CAPTURED_EXCEPTION=0)
|
||||||
|
target_compile_definitions(libslic3r PRIVATE $<$<CONFIG:RelWithDebInfo>:SLIC3R_CONSOLE_LOG>)
|
||||||
target_include_directories(libslic3r PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
|
target_include_directories(libslic3r PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
target_include_directories(libslic3r SYSTEM PUBLIC ${EXPAT_INCLUDE_DIRS})
|
target_include_directories(libslic3r SYSTEM PUBLIC ${EXPAT_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
|||||||
@@ -197,6 +197,7 @@ std::string debug_out_path(const char *name, ...);
|
|||||||
// smaller level means less log. level=5 means saving all logs.
|
// smaller level means less log. level=5 means saving all logs.
|
||||||
void set_log_path_and_level(const std::string& file, unsigned int level);
|
void set_log_path_and_level(const std::string& file, unsigned int level);
|
||||||
void flush_logs();
|
void flush_logs();
|
||||||
|
void shutdown_console_logging();
|
||||||
boost::filesystem::path get_log_file_name();
|
boost::filesystem::path get_log_file_name();
|
||||||
|
|
||||||
// A special type for strings encoded in the local Windows 8-bit code page.
|
// A special type for strings encoded in the local Windows 8-bit code page.
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <locale>
|
#include <locale>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
|
#include <iostream>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@@ -50,14 +51,19 @@
|
|||||||
#include <boost/log/core.hpp>
|
#include <boost/log/core.hpp>
|
||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
#include <boost/log/expressions.hpp>
|
#include <boost/log/expressions.hpp>
|
||||||
|
#include <boost/log/sinks/async_frontend.hpp>
|
||||||
#include <boost/log/sinks/text_file_backend.hpp>
|
#include <boost/log/sinks/text_file_backend.hpp>
|
||||||
|
#include <boost/log/sinks/text_ostream_backend.hpp>
|
||||||
#include <boost/log/utility/setup/file.hpp>
|
#include <boost/log/utility/setup/file.hpp>
|
||||||
#include <boost/log/utility/setup/common_attributes.hpp>
|
#include <boost/log/utility/setup/common_attributes.hpp>
|
||||||
#include <boost/log/sources/severity_logger.hpp>
|
#include <boost/log/sources/severity_logger.hpp>
|
||||||
#include <boost/log/sources/record_ostream.hpp>
|
#include <boost/log/sources/record_ostream.hpp>
|
||||||
#include <boost/log/support/date_time.hpp>
|
#include <boost/log/support/date_time.hpp>
|
||||||
|
|
||||||
|
#include <boost/core/null_deleter.hpp>
|
||||||
#include <boost/locale.hpp>
|
#include <boost/locale.hpp>
|
||||||
|
#include <boost/make_shared.hpp>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
#include <boost/algorithm/string/predicate.hpp>
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
@@ -178,6 +184,7 @@ unsigned get_logging_level()
|
|||||||
}
|
}
|
||||||
|
|
||||||
boost::shared_ptr<boost::log::sinks::synchronous_sink<boost::log::sinks::text_file_backend>> g_log_sink;
|
boost::shared_ptr<boost::log::sinks::synchronous_sink<boost::log::sinks::text_file_backend>> g_log_sink;
|
||||||
|
boost::shared_ptr<boost::log::sinks::asynchronous_sink<boost::log::sinks::text_ostream_backend>> g_console_log_sink;
|
||||||
|
|
||||||
// Force set_logging_level(<=error) after loading of the DLL.
|
// Force set_logging_level(<=error) after loading of the DLL.
|
||||||
// This is currently only needed if libslic3r is loaded as a shared library into Perl interpreter
|
// This is currently only needed if libslic3r is loaded as a shared library into Perl interpreter
|
||||||
@@ -350,6 +357,19 @@ namespace src = boost::log::sources;
|
|||||||
namespace expr = boost::log::expressions;
|
namespace expr = boost::log::expressions;
|
||||||
namespace keywords = boost::log::keywords;
|
namespace keywords = boost::log::keywords;
|
||||||
namespace attrs = boost::log::attributes;
|
namespace attrs = boost::log::attributes;
|
||||||
|
namespace sinks = boost::log::sinks;
|
||||||
|
|
||||||
|
void shutdown_console_logging()
|
||||||
|
{
|
||||||
|
if (!g_console_log_sink)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto console_sink = g_console_log_sink;
|
||||||
|
boost::log::core::get()->remove_sink(console_sink);
|
||||||
|
console_sink->stop();
|
||||||
|
g_console_log_sink.reset();
|
||||||
|
}
|
||||||
|
|
||||||
void set_log_path_and_level(const std::string& file, unsigned int level)
|
void set_log_path_and_level(const std::string& file, unsigned int level)
|
||||||
{
|
{
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
@@ -381,6 +401,24 @@ void set_log_path_and_level(const std::string& file, unsigned int level)
|
|||||||
keywords::auto_flush = true
|
keywords::auto_flush = true
|
||||||
);
|
);
|
||||||
|
|
||||||
|
shutdown_console_logging();
|
||||||
|
|
||||||
|
#ifdef SLIC3R_CONSOLE_LOG
|
||||||
|
auto console_backend = boost::make_shared<sinks::text_ostream_backend>();
|
||||||
|
console_backend->add_stream(boost::shared_ptr<std::ostream>(&std::cout, boost::null_deleter()));
|
||||||
|
console_backend->auto_flush(true);
|
||||||
|
|
||||||
|
g_console_log_sink = boost::make_shared<sinks::asynchronous_sink<sinks::text_ostream_backend>>(console_backend);
|
||||||
|
g_console_log_sink->set_formatter(
|
||||||
|
expr::stream
|
||||||
|
<< "[" << expr::attr< logging::trivial::severity_level >("Severity") << "]\t"
|
||||||
|
<< expr::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d %H:%M:%S.%f") << " "
|
||||||
|
<<"[Thread " << expr::attr<attrs::current_thread_id::value_type>("ThreadID") << "]"
|
||||||
|
<< ": " << expr::smessage
|
||||||
|
);
|
||||||
|
boost::log::core::get()->add_sink(g_console_log_sink);
|
||||||
|
#endif
|
||||||
|
|
||||||
logging::add_common_attributes();
|
logging::add_common_attributes();
|
||||||
|
|
||||||
set_logging_level(level);
|
set_logging_level(level);
|
||||||
|
|||||||
@@ -2355,6 +2355,7 @@ GUI_App::~GUI_App()
|
|||||||
|
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__<< boost::format(": exit");
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__<< boost::format(": exit");
|
||||||
|
shutdown_console_logging();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GUI_App::is_blocking_printing(MachineObject *obj_)
|
bool GUI_App::is_blocking_printing(MachineObject *obj_)
|
||||||
|
|||||||
@@ -48,13 +48,14 @@ std::string plugin_defaults_user_script()
|
|||||||
return WebViewHostDialog::document_start_injector(css, "orca-plugin-defaults", "beforeend");
|
return WebViewHostDialog::document_start_injector(css, "orca-plugin-defaults", "beforeend");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Injected into every page at document start (before the plugin's own scripts).
|
// Injected into the top-level page at document start (before the plugin's own
|
||||||
// Defines window.orca as the only host surface the page may use. It references
|
// scripts). Defines window.orca as the only host surface the page may use. It
|
||||||
// window.wx lazily (at call time) so it never races the backend's deferred
|
// references window.wx lazily (at call time) so it never races the backend's
|
||||||
// registration of the "wx" message handler. Guarded against double-injection so
|
// deferred registration of the "wx" message handler. Guarded against
|
||||||
// it is harmless if also prepended.
|
// double-injection so it is harmless if also prepended.
|
||||||
constexpr char ORCA_BRIDGE_JS[] = R"JS(
|
constexpr char ORCA_BRIDGE_JS[] = R"JS(
|
||||||
(function () {
|
(function () {
|
||||||
|
if (window.top !== window.self) return;
|
||||||
if (window.orca) return;
|
if (window.orca) return;
|
||||||
var handlers = [];
|
var handlers = [];
|
||||||
function send(kind, data) {
|
function send(kind, data) {
|
||||||
|
|||||||
@@ -300,7 +300,12 @@ PluginAvailableActions evaluate_action_policy(const PluginDialogItem& item)
|
|||||||
|
|
||||||
add_action("open_folder", "Show in folder", has_local);
|
add_action("open_folder", "Show in folder", has_local);
|
||||||
|
|
||||||
add_action("reinstall_plugin", "Reinstall");
|
if (is_cloud) {
|
||||||
|
add_action("reinstall_plugin", "Reinstall");
|
||||||
|
} else {
|
||||||
|
add_action("reload_plugin", "Reload");
|
||||||
|
add_action("clear_cache_reload_plugin", "Delete cache and reload");
|
||||||
|
}
|
||||||
|
|
||||||
return available_actions;
|
return available_actions;
|
||||||
}
|
}
|
||||||
@@ -739,11 +744,13 @@ void PluginsDialog::handle_plugin_menu_action(const std::string& plugin_key, con
|
|||||||
unsubscribe_cloud_plugin(row_data);
|
unsubscribe_cloud_plugin(row_data);
|
||||||
} else if (action == "delete_mine_plugin") {
|
} else if (action == "delete_mine_plugin") {
|
||||||
delete_mine_local_and_cloud_plugin(plugin_key);
|
delete_mine_local_and_cloud_plugin(plugin_key);
|
||||||
|
} else if (action == "reload_plugin") {
|
||||||
|
reload_local_plugin(plugin_key, /*clear_cache=*/false);
|
||||||
|
} else if (action == "clear_cache_reload_plugin") {
|
||||||
|
reload_local_plugin(plugin_key, /*clear_cache=*/true);
|
||||||
} else if (action == "reinstall_plugin") {
|
} else if (action == "reinstall_plugin") {
|
||||||
if (row_data.is_cloud_plugin())
|
if (row_data.is_cloud_plugin())
|
||||||
reinstall_cloud_plugin(row_data);
|
reinstall_cloud_plugin(row_data);
|
||||||
else
|
|
||||||
reinstall_local_plugin(plugin_key);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1123,7 +1130,7 @@ void PluginsDialog::unsubscribe_cloud_plugin(const PluginDescriptor& plugin)
|
|||||||
_L("Unsubscribing plugin"), _L("Deleting local files and unsubscribing plugin..."));
|
_L("Unsubscribing plugin"), _L("Deleting local files and unsubscribing plugin..."));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PluginsDialog::reinstall_local_plugin(const std::string& plugin_key)
|
void PluginsDialog::reload_local_plugin(const std::string& plugin_key, bool clear_cache)
|
||||||
{
|
{
|
||||||
if (plugin_key.empty())
|
if (plugin_key.empty())
|
||||||
return;
|
return;
|
||||||
@@ -1132,11 +1139,34 @@ void PluginsDialog::reinstall_local_plugin(const std::string& plugin_key)
|
|||||||
std::pair<bool, std::string> reload_result{false, ""};
|
std::pair<bool, std::string> reload_result{false, ""};
|
||||||
try {
|
try {
|
||||||
reload_result = run_with_dialog_wait(
|
reload_result = run_with_dialog_wait(
|
||||||
[plugin_key, was_loaded]() -> std::pair<bool, std::string> {
|
[plugin_key, was_loaded, clear_cache]() -> std::pair<bool, std::string> {
|
||||||
PluginManager& manager = PluginManager::instance();
|
PluginManager& manager = PluginManager::instance();
|
||||||
|
|
||||||
|
boost::filesystem::path cache_dir;
|
||||||
|
if (clear_cache) {
|
||||||
|
PluginDescriptor descriptor;
|
||||||
|
if (!manager.try_get_plugin_descriptor(plugin_key, descriptor))
|
||||||
|
return {false, "Plugin not found."};
|
||||||
|
|
||||||
|
boost::filesystem::path resolved_root;
|
||||||
|
std::string resolve_error;
|
||||||
|
if (!resolve_allowed_plugin_root(descriptor, {get_orca_plugins_dir()},
|
||||||
|
"Refusing to clear a plugin cache outside the local plugin directory.",
|
||||||
|
resolved_root, resolve_error))
|
||||||
|
return {false, resolve_error};
|
||||||
|
cache_dir = resolved_root / "__whl_extracted__";
|
||||||
|
}
|
||||||
|
|
||||||
if (!manager.unload_plugin(plugin_key))
|
if (!manager.unload_plugin(plugin_key))
|
||||||
return {false, "Failed to unload plugin."};
|
return {false, "Failed to unload plugin."};
|
||||||
|
|
||||||
|
if (clear_cache) {
|
||||||
|
boost::system::error_code ec;
|
||||||
|
boost::filesystem::remove_all(cache_dir, ec);
|
||||||
|
if (ec)
|
||||||
|
return {false, "Failed to clear plugin cache: " + ec.message()};
|
||||||
|
}
|
||||||
|
|
||||||
manager.load_plugin(plugin_key, false);
|
manager.load_plugin(plugin_key, false);
|
||||||
std::string error;
|
std::string error;
|
||||||
if (!manager.wait_for_plugin_load(plugin_key, std::chrono::minutes(5), error) || !manager.is_plugin_loaded(plugin_key))
|
if (!manager.wait_for_plugin_load(plugin_key, std::chrono::minutes(5), error) || !manager.is_plugin_loaded(plugin_key))
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ private:
|
|||||||
void open_plugin_folder(const Slic3r::PluginDescriptor& plugin);
|
void open_plugin_folder(const Slic3r::PluginDescriptor& plugin);
|
||||||
void delete_local_plugin(const Slic3r::PluginDescriptor& plugin);
|
void delete_local_plugin(const Slic3r::PluginDescriptor& plugin);
|
||||||
void unsubscribe_cloud_plugin(const Slic3r::PluginDescriptor& plugin);
|
void unsubscribe_cloud_plugin(const Slic3r::PluginDescriptor& plugin);
|
||||||
void reinstall_local_plugin(const std::string& plugin_key);
|
void reload_local_plugin(const std::string& plugin_key, bool clear_cache);
|
||||||
void reinstall_cloud_plugin(const Slic3r::PluginDescriptor& plugin);
|
void reinstall_cloud_plugin(const Slic3r::PluginDescriptor& plugin);
|
||||||
void delete_mine_local_and_cloud_plugin(const std::string& plugin_key);
|
void delete_mine_local_and_cloud_plugin(const std::string& plugin_key);
|
||||||
|
|
||||||
|
|||||||
@@ -96,6 +96,9 @@ std::string WebViewHostDialog::document_start_injector(const std::string& markup
|
|||||||
const std::string literal = nlohmann::json(markup).dump();
|
const std::string literal = nlohmann::json(markup).dump();
|
||||||
std::string s;
|
std::string s;
|
||||||
s += "(function(){";
|
s += "(function(){";
|
||||||
|
// wxWebView's AddUserScript runs in child frames too (including cross-origin
|
||||||
|
// frames on WebView2). Host theme state belongs only to the top-level page.
|
||||||
|
s += "if(window.top!==window.self)return;";
|
||||||
s += prelude;
|
s += prelude;
|
||||||
s += "var css=" + literal + ";";
|
s += "var css=" + literal + ";";
|
||||||
s += "function inject(){";
|
s += "function inject(){";
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ struct PluginDescriptor
|
|||||||
std::string description; // Plugin description
|
std::string description; // Plugin description
|
||||||
std::string author; // Plugin author from manifest, if available
|
std::string author; // Plugin author from manifest, if available
|
||||||
std::string version; // Selected plugin version
|
std::string version; // Selected plugin version
|
||||||
std::string latest_version; // Latest available cloud version fallback when changelog is unavailable.
|
std::string latest_version; // Authoritative latest available cloud version.
|
||||||
std::string installed_version; // Locally installed package version. Preserved across cloud merges, which overwrite `version` with the latest cloud version. Empty when not installed.
|
std::string installed_version; // Locally installed package version. Preserved across cloud merges, which overwrite `version` with the latest cloud version. Empty when not installed.
|
||||||
std::vector<std::string> display_types; // Display-only "compatibility" labels (cloud: raw service labels; local: from real capabilities). Never used for dispatch.
|
std::vector<std::string> display_types; // Display-only "compatibility" labels (cloud: raw service labels; local: from real capabilities). Never used for dispatch.
|
||||||
std::string plugin_root; // Installed plugin directory, even when entry_path is invalid or ambiguous.
|
std::string plugin_root; // Installed plugin directory, even when entry_path is invalid or ambiguous.
|
||||||
@@ -113,10 +113,6 @@ struct PluginDescriptor
|
|||||||
bool is_unauthorized() const { return get_update_status() == PluginUpdateStatus::Unauthorized; }
|
bool is_unauthorized() const { return get_update_status() == PluginUpdateStatus::Unauthorized; }
|
||||||
std::string latest_available_version() const
|
std::string latest_available_version() const
|
||||||
{
|
{
|
||||||
for (const PluginChangelog& entry : changelog) {
|
|
||||||
if (!entry.version.empty())
|
|
||||||
return entry.version;
|
|
||||||
}
|
|
||||||
if (!latest_version.empty())
|
if (!latest_version.empty())
|
||||||
return latest_version;
|
return latest_version;
|
||||||
return version;
|
return version;
|
||||||
|
|||||||
@@ -52,6 +52,29 @@ print('ok')
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
TEST_CASE("plugin latest version uses the authoritative catalog field", "[PluginDescriptor]")
|
||||||
|
{
|
||||||
|
PluginDescriptor descriptor;
|
||||||
|
descriptor.version = "1.3.0";
|
||||||
|
descriptor.latest_version = "1.3.0";
|
||||||
|
PluginChangelog changelog;
|
||||||
|
changelog.version = "1.2.0";
|
||||||
|
descriptor.changelog.push_back(changelog);
|
||||||
|
|
||||||
|
CHECK(descriptor.latest_available_version() == "1.3.0");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("plugin latest version falls back to the descriptor version", "[PluginDescriptor]")
|
||||||
|
{
|
||||||
|
PluginDescriptor descriptor;
|
||||||
|
descriptor.version = "1.1.0";
|
||||||
|
PluginChangelog changelog;
|
||||||
|
changelog.version = "1.0.0";
|
||||||
|
descriptor.changelog.push_back(changelog);
|
||||||
|
|
||||||
|
CHECK(descriptor.latest_available_version() == "1.1.0");
|
||||||
|
}
|
||||||
|
|
||||||
// Regression: update_cloud_metadata() replaces a matched entry's descriptor wholesale with the
|
// Regression: update_cloud_metadata() replaces a matched entry's descriptor wholesale with the
|
||||||
// cloud catalog record (`entry = cloud_entry`). Configuration used to ride on the descriptor, so
|
// cloud catalog record (`entry = cloud_entry`). Configuration used to ride on the descriptor, so
|
||||||
// that overwrite silently wiped it and plugins fell back to their built-in defaults (found via
|
// that overwrite silently wiped it and plugins fell back to their built-in defaults (found via
|
||||||
|
|||||||
Reference in New Issue
Block a user