From 445f7c2691982b8cc9da26aaab5a746340c65cc0 Mon Sep 17 00:00:00 2001 From: Kuzuri Date: Fri, 11 Sep 2026 01:07:15 -0400 Subject: [PATCH] Open a project from a URL as a project, and fix the drop dialog default Two related problems when opening a model from Snapmaker Space while a project is already on the plate. First, the "Drop project file" dialog appears at all. Clicking "Open in Snapmaker Orca" already says which project to open, but the download is routed through Plater::load_files(const wxArrayString&), the drag-and-drop entry point, so open_3mf_file() escalates to the prompt whenever the plate is occupied. A cold launch opens the project without asking and a warm one interrogates the user, for the same action. The download path now passes from_url, which suppresses only that escalation. The global Load Behaviour setting is still honoured, so a user who chose "Always Ask" or "Load Geometry Only" still gets what they asked for, and load_project() still prompts about unsaved changes to the current project. Second, the dialog defaulted to the wrong action. It records the user's choice in "import_project_action" on OK but never read it back, because m_action was hardcoded to 2 (LoadGeometry). It now defaults to the stored choice, falling back to OpenProject rather than LoadGeometry: the dialog is shown for a project file, and importing geometry only silently discards the embedded printer, filament and process settings. The model still renders and slices, so the loss is invisible until the print comes out wrong, which is a poor default for the option a user is most likely to accept without reading. --- src/slic3r/GUI/Downloader.cpp | 3 ++- src/slic3r/GUI/Plater.cpp | 22 +++++++++++++++++----- src/slic3r/GUI/Plater.hpp | 8 +++++--- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/slic3r/GUI/Downloader.cpp b/src/slic3r/GUI/Downloader.cpp index 51796203f2d9..7830795562ba 100644 --- a/src/slic3r/GUI/Downloader.cpp +++ b/src/slic3r/GUI/Downloader.cpp @@ -265,7 +265,8 @@ void Downloader::on_complete(wxCommandEvent& event) set_download_state(event.GetInt(), DownloadState::DownloadDone); wxArrayString paths; paths.Add(event.GetString()); - wxGetApp().plater()->load_files(paths); + // from_url: the user clicked "Open in ..." on this specific project. + wxGetApp().plater()->load_files(paths, /* from_url */ true); } bool Downloader::user_action_callback(DownloaderUserAction action, int id) { diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index d7295307e3ba..4c8aad7923ce 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -19384,7 +19384,13 @@ ProjectDropDialog::ProjectDropDialog(const std::string &filename) wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX) - , m_action(2) + // Default to the action the user chose last time, which this dialog already records in + // "import_project_action" on OK. Falling back to LoadType::OpenProject rather than + // LoadGeometry: this dialog is shown for a *project* file, and importing geometry only + // silently discards the embedded printer, filament and process settings. + , m_action(std::max(1, std::min(2, wxGetApp().app_config->get("import_project_action").empty() + ? 1 + : std::atoi(wxGetApp().app_config->get("import_project_action").c_str())))) { // def setting SetBackgroundColour(m_def_color); @@ -19550,7 +19556,7 @@ void ProjectDropDialog::on_dpi_changed(const wxRect& suggested_rect) } //BBS: remove GCodeViewer as seperate APP logic -bool Plater::load_files(const wxArrayString& filenames) +bool Plater::load_files(const wxArrayString& filenames, bool from_url) { const std::regex pattern_drop(".*[.](stp|step|stl|oltp|obj|amf|3mf|svg|zip)", std::regex::icase); const std::regex pattern_gcode_drop(".*[.](gcode|g)", std::regex::icase); @@ -19659,7 +19665,7 @@ bool Plater::load_files(const wxArrayString& filenames) switch (loadfiles_type) { case LoadFilesType::Single3MF: - open_3mf_file(normal_paths[0]); + open_3mf_file(normal_paths[0], from_url); break; case LoadFilesType::SingleOther: { @@ -19742,7 +19748,7 @@ LoadType determine_load_type(std::string filename, std::string override_setting) } } -bool Plater::open_3mf_file(const fs::path &file_path) +bool Plater::open_3mf_file(const fs::path &file_path, bool from_url) { std::string filename = encode_path(file_path.filename().string().c_str()); if (!boost::algorithm::iends_with(filename, ".3mf")) { @@ -19751,7 +19757,13 @@ bool Plater::open_3mf_file(const fs::path &file_path) bool not_empty_plate = !model().objects.empty(); bool load_setting_ask_when_relevant = wxGetApp().app_config->get(SETTING_PROJECT_LOAD_BEHAVIOUR) == OPTION_PROJECT_LOAD_BEHAVIOUR_ASK_WHEN_RELEVANT; - LoadType load_type = determine_load_type(filename, (not_empty_plate && load_setting_ask_when_relevant) ? OPTION_PROJECT_LOAD_BEHAVIOUR_ALWAYS_ASK : ""); + // A project opened from a snapmaker-orca:// URL is not an ambiguous drop: the user + // clicked "Open in Snapmaker Orca" on that specific project, so do not escalate to the + // "Open as project / Import geometry only" prompt just because the plate is occupied. + // The global Load Behaviour setting is still honoured, and load_project() still asks + // about unsaved changes to the current project. + LoadType load_type = determine_load_type(filename, + (!from_url && not_empty_plate && load_setting_ask_when_relevant) ? OPTION_PROJECT_LOAD_BEHAVIOUR_ALWAYS_ASK : ""); if (load_type == LoadType::Unknown) return false; diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 4c79e678bcc8..06f6fb768418 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -335,7 +335,7 @@ class Plater: public wxPanel // BBS: check snapshot bool up_to_date(bool saved, bool backup); - bool open_3mf_file(const fs::path &file_path); + bool open_3mf_file(const fs::path &file_path, bool from_url = false); int get_3mf_file_count(std::vector paths); void add_file(); void add_model(bool imperial_units = false, std::string fname = ""); @@ -387,8 +387,10 @@ class Plater: public wxPanel std::vector load_files(const std::vector& input_files, LoadStrategy strategy = LoadStrategy::LoadModel | LoadStrategy::LoadConfig, bool ask_multi = false); // To be called when providing a list of files to the GUI slic3r on command line. std::vector load_files(const std::vector& input_files, LoadStrategy strategy = LoadStrategy::LoadModel | LoadStrategy::LoadConfig, bool ask_multi = false); - // to be called on drag and drop - bool load_files(const wxArrayString& filenames); + // to be called on drag and drop, or for a project downloaded from a + // snapmaker-orca:// URL, in which case from_url is true: the user has already + // said which project to open, so do not ask them again. + bool load_files(const wxArrayString& filenames, bool from_url = false); const wxString& get_last_loaded_gcode() const { return m_last_loaded_gcode; }