diff --git a/src/slic3r/GUI/WCPDownloadManager.cpp b/src/slic3r/GUI/DownloadManager.cpp similarity index 85% rename from src/slic3r/GUI/WCPDownloadManager.cpp rename to src/slic3r/GUI/DownloadManager.cpp index a9d521aac3..30391441e5 100644 --- a/src/slic3r/GUI/WCPDownloadManager.cpp +++ b/src/slic3r/GUI/DownloadManager.cpp @@ -6,7 +6,7 @@ namespace Slic3r { namespace GUI { -size_t WCPDownloadManager::start_download(const std::string& file_url, +size_t DownloadManager::start_download(const std::string& file_url, const std::string& file_name, std::shared_ptr wcp_instance) { @@ -23,8 +23,8 @@ size_t WCPDownloadManager::start_download(const std::string& file_url, std::string dest_path = dest_file.string(); // Create task - auto task = std::make_shared(task_id, file_url, file_name, dest_path, wcp_instance); - task->state = WCPDownloadState::Downloading; + auto task = std::make_shared(task_id, file_url, file_name, dest_path, wcp_instance); + task->state = SMDownloadState::Downloading; m_tasks[task_id] = task; @@ -36,7 +36,7 @@ size_t WCPDownloadManager::start_download(const std::string& file_url, // Step 2: Set progress callback http.on_progress([this, task](Http::Progress progress, bool& cancel) { - if (task->state == WCPDownloadState::Canceled) { + if (task->state == SMDownloadState::Canceled) { cancel = true; return; } @@ -87,7 +87,7 @@ size_t WCPDownloadManager::start_download(const std::string& file_url, file.write(body.c_str(), body.size()); file.close(); - task->state = WCPDownloadState::Completed; + task->state = SMDownloadState::Completed; task->percent = 100; send_complete_update(task, task->dest_path); cleanup_task(task->task_id); @@ -101,7 +101,7 @@ size_t WCPDownloadManager::start_download(const std::string& file_url, // Step 4: Set error callback http.on_error([this, task](std::string body, std::string error, unsigned status) { wxGetApp().CallAfter([this, task, error, status]() { - task->state = WCPDownloadState::Error; + task->state = SMDownloadState::Error; task->error_message = error; send_error_update(task, error); cleanup_task(task->task_id); @@ -112,7 +112,7 @@ size_t WCPDownloadManager::start_download(const std::string& file_url, task->http_object = http.perform(); } catch (std::exception& e) { - task->state = WCPDownloadState::Error; + task->state = SMDownloadState::Error; task->error_message = e.what(); send_error_update(task, e.what()); cleanup_task(task->task_id); @@ -122,7 +122,7 @@ size_t WCPDownloadManager::start_download(const std::string& file_url, return task_id; } -bool WCPDownloadManager::cancel_download(size_t task_id) { +bool DownloadManager::cancel_download(size_t task_id) { std::shared_ptr wcp_to_destroy; { @@ -134,8 +134,8 @@ bool WCPDownloadManager::cancel_download(size_t task_id) { } auto task = it->second; - if (task->state == WCPDownloadState::Downloading) { - task->state = WCPDownloadState::Canceled; + if (task->state == SMDownloadState::Downloading) { + task->state = SMDownloadState::Canceled; if (task->http_object) { task->http_object->cancel(); } @@ -158,41 +158,41 @@ bool WCPDownloadManager::cancel_download(size_t task_id) { return true; } -bool WCPDownloadManager::pause_download(size_t task_id) { +bool DownloadManager::pause_download(size_t task_id) { // Pause functionality can be implemented if needed // Current Http module may not support pause, need to implement resume from breakpoint std::lock_guard lock(m_tasks_mutex); auto it = m_tasks.find(task_id); - if (it != m_tasks.end() && it->second->state == WCPDownloadState::Downloading) { - it->second->state = WCPDownloadState::Paused; + if (it != m_tasks.end() && it->second->state == SMDownloadState::Downloading) { + it->second->state = SMDownloadState::Paused; // Note: Http module doesn't support pause directly, would need breakpoint resume return true; } return false; } -bool WCPDownloadManager::resume_download(size_t task_id) { +bool DownloadManager::resume_download(size_t task_id) { // Resume functionality can be implemented if needed // Would require breakpoint resume support in Http module std::lock_guard lock(m_tasks_mutex); auto it = m_tasks.find(task_id); - if (it != m_tasks.end() && it->second->state == WCPDownloadState::Paused) { + if (it != m_tasks.end() && it->second->state == SMDownloadState::Paused) { // Would need to restart download with range header return false; // Not implemented yet } return false; } -WCPDownloadState WCPDownloadManager::get_task_state(size_t task_id) { +SMDownloadState DownloadManager::get_task_state(size_t task_id) { std::lock_guard lock(m_tasks_mutex); auto it = m_tasks.find(task_id); if (it != m_tasks.end()) { return it->second->state; } - return WCPDownloadState::Error; + return SMDownloadState::Error; } -std::shared_ptr WCPDownloadManager::get_task(size_t task_id) { +std::shared_ptr DownloadManager::get_task(size_t task_id) { std::lock_guard lock(m_tasks_mutex); auto it = m_tasks.find(task_id); if (it != m_tasks.end()) { @@ -201,7 +201,7 @@ std::shared_ptr WCPDownloadManager::get_task(size_t task_id) { return nullptr; } -void WCPDownloadManager::send_progress_update(std::shared_ptr task, +void DownloadManager::send_progress_update(std::shared_ptr task, int percent, size_t downloaded, size_t total) { @@ -227,7 +227,7 @@ void WCPDownloadManager::send_progress_update(std::shared_ptr t } } -void WCPDownloadManager::send_complete_update(std::shared_ptr task, +void DownloadManager::send_complete_update(std::shared_ptr task, const std::string& file_path) { if (auto wcp = task->wcp_instance.lock()) { json complete_data; @@ -247,7 +247,7 @@ void WCPDownloadManager::send_complete_update(std::shared_ptr t } } -void WCPDownloadManager::send_error_update(std::shared_ptr task, +void DownloadManager::send_error_update(std::shared_ptr task, const std::string& error) { if (auto wcp = task->wcp_instance.lock()) { json error_data; @@ -265,7 +265,7 @@ void WCPDownloadManager::send_error_update(std::shared_ptr task } } -void WCPDownloadManager::cleanup_task(size_t task_id) { +void DownloadManager::cleanup_task(size_t task_id) { std::lock_guard lock(m_tasks_mutex); m_tasks.erase(task_id); m_last_percent.erase(task_id); diff --git a/src/slic3r/GUI/WCPDownloadManager.hpp b/src/slic3r/GUI/DownloadManager.hpp similarity index 66% rename from src/slic3r/GUI/WCPDownloadManager.hpp rename to src/slic3r/GUI/DownloadManager.hpp index fda468f777..ebc0568b6d 100644 --- a/src/slic3r/GUI/WCPDownloadManager.hpp +++ b/src/slic3r/GUI/DownloadManager.hpp @@ -15,7 +15,7 @@ namespace Slic3r { namespace GUI { // Download task state -enum class WCPDownloadState { +enum class SMDownloadState { Pending, Downloading, Paused, @@ -25,28 +25,28 @@ enum class WCPDownloadState { }; // Download task information -struct WCPDownloadTask { +struct DownloadTask { size_t task_id; std::string file_url; std::string file_name; std::string dest_path; std::weak_ptr wcp_instance; // Associated WCP instance Http::Ptr http_object; // HTTP object for cancellation - WCPDownloadState state; + SMDownloadState state; int percent; std::string error_message; - WCPDownloadTask(size_t id, const std::string& url, const std::string& name, + DownloadTask(size_t id, const std::string& url, const std::string& name, const std::string& path, std::shared_ptr instance) - : task_id(id), file_url(url), file_name(name), dest_path(path), - wcp_instance(instance), state(WCPDownloadState::Pending), percent(0) {} + : task_id(id), file_url(url), file_name(name), dest_path(path), wcp_instance(instance), state(SMDownloadState::Pending), percent(0) + {} }; -// WCP Download Manager -class WCPDownloadManager { +// Download Manager +class DownloadManager { public: - static WCPDownloadManager& getInstance() { - static WCPDownloadManager instance; + static DownloadManager& getInstance() { + static DownloadManager instance; return instance; } @@ -65,19 +65,19 @@ public: bool resume_download(size_t task_id); // Get task state - WCPDownloadState get_task_state(size_t task_id); + SMDownloadState get_task_state(size_t task_id); // Get task information - std::shared_ptr get_task(size_t task_id); + std::shared_ptr get_task(size_t task_id); private: - WCPDownloadManager() = default; - ~WCPDownloadManager() = default; - WCPDownloadManager(const WCPDownloadManager&) = delete; - WCPDownloadManager& operator=(const WCPDownloadManager&) = delete; + DownloadManager() = default; + ~DownloadManager() = default; + DownloadManager(const DownloadManager&) = delete; + DownloadManager& operator=(const DownloadManager&) = delete; std::mutex m_tasks_mutex; - std::unordered_map> m_tasks; + std::unordered_map> m_tasks; std::atomic m_next_task_id{1}; // Track last progress update for throttling @@ -85,14 +85,14 @@ private: std::unordered_map m_last_update; // Send progress update to WCP - void send_progress_update(std::shared_ptr task, int percent, + void send_progress_update(std::shared_ptr task, int percent, size_t downloaded, size_t total); // Send completion message to WCP - void send_complete_update(std::shared_ptr task, const std::string& file_path); + void send_complete_update(std::shared_ptr task, const std::string& file_path); // Send error message to WCP - void send_error_update(std::shared_ptr task, const std::string& error); + void send_error_update(std::shared_ptr task, const std::string& error); // Clean up completed task void cleanup_task(size_t task_id); diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 47987430c0..a0a511887f 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -1066,7 +1066,7 @@ GUI_App::GUI_App() , m_imgui(new ImGuiWrapper()) , m_removable_drive_manager(std::make_unique()) , m_downloader(std::make_unique()) - , m_wcp_download_manager(&WCPDownloadManager::getInstance()) + , m_download_manager(&DownloadManager::getInstance()) , m_other_instance_message_handler(std::make_unique()) { //app config initializes early becasuse it is used in instance checking in Snapmaker_Orca.cpp @@ -6478,9 +6478,9 @@ Downloader* GUI_App::downloader() return m_downloader.get(); } -WCPDownloadManager* GUI_App::wcp_download_manager() +DownloadManager* GUI_App::download_manager() { - return m_wcp_download_manager; + return m_download_manager; } void GUI_App::load_url(wxString url) diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 38a950676a..7221430fbd 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -89,7 +89,7 @@ class Plater; class ParamsPanel; class NotificationManager; class Downloader; -class WCPDownloadManager; +class DownloadManager; struct GUI_InitParams; class ParamsDialog; class HMSQuery; @@ -298,7 +298,7 @@ private: size_t m_instance_hash_int; std::unique_ptr m_downloader; - WCPDownloadManager* m_wcp_download_manager; + DownloadManager* m_download_manager; //BBS bool m_is_closing {false}; @@ -686,7 +686,7 @@ private: Model& model(); NotificationManager * notification_manager(); Downloader* downloader(); - WCPDownloadManager* wcp_download_manager(); + DownloadManager* download_manager(); std::string m_mall_model_download_url; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 26f953ff49..905e8582f4 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -13685,18 +13685,6 @@ void Plater::send_gcode_legacy(int plate_idx, Export3mfProgressFn proFn, bool us islegal = (c_preset == connect_preset); - /* if (!islegal) { - MessageDialog msg_window(nullptr, - _L(" Your connected machine is ") + (connect_preset == "" ? "Unknown" : connect_preset) + _L("\nYour model's preset is ") + c_preset + _L("\nDo you want to continue?"), - L("machine check"), - wxICON_QUESTION | wxOK); - int res = msg_window.ShowModal(); - if (res != wxID_OK) { - return; - } - }*/ - - DynamicPrintConfig* physical_printer_config = &Slic3r::GUI::wxGetApp().preset_bundle->printers.get_edited_preset().config; if (! physical_printer_config || p->model.objects.empty()) return; @@ -13715,34 +13703,6 @@ void Plater::send_gcode_legacy(int plate_idx, Export3mfProgressFn proFn, bool us local_name.erase(std::remove(local_name.begin(), local_name.end(), '('), local_name.end()); local_name.erase(std::remove(local_name.begin(), local_name.end(), ')'), local_name.end()); - - /*if (wxGetApp().app_config->get("use_new_connect") == "true") { - upload_job = PrintHostJob(wxGetApp().get_host_config()); - } */ - - // if (local_name == "Snapmaker U1 0.4 nozzle" && devices.size() == 0) { - // MessageDialog msg_window(nullptr, _L("You don't have active machine, do you want to add one?"), _L("Info"), wxICON_QUESTION | wxOK | wxCANCEL); - - // int res = msg_window.ShowModal(); - // if (res == wxID_OK) { - // wxGetApp().mainframe->request_select_tab(MainFrame::TabPosition::tpMonitor); - // auto view = wxGetApp().mainframe->m_printer_view; - // if (view) { - // json msg; - // msg["head"] = json::object(); - // json payload = json::object(); - // payload["cmd"] = "devicepage_add_device"; - // payload["method"] = "call_flutter"; - // payload["params"] = json::object(); - // msg["payload"] = payload; - - // std::string str_msg = msg.dump(4, ' ', true); - // view->sendMessage(str_msg); - // } - // } - // return; - // } - if (wxGetApp().app_config->get("use_new_connect") == "true" || local_name == "Snapmaker U1 0.4 nozzle") { // 先不创建job,直接创建上传 / 上传下载对话框 // 获取默认文件名 @@ -13804,8 +13764,6 @@ void Plater::send_gcode_legacy(int plate_idx, Export3mfProgressFn proFn, bool us dialog->set_display_file_name(upload_job.upload_data.upload_path.string()); bool res = dialog->run(); - // wxGetApp().mainframe->m_printer_view->reload(); - if (dialog->is_finish()) { wxGetApp().mainframe->select_tab(MainFrame::TabPosition::tpMonitor); } diff --git a/src/slic3r/GUI/SSWCP.cpp b/src/slic3r/GUI/SSWCP.cpp index 33de5066f0..488072e504 100644 --- a/src/slic3r/GUI/SSWCP.cpp +++ b/src/slic3r/GUI/SSWCP.cpp @@ -3001,10 +3001,11 @@ void SSWCP_MachineOption_Instance::sw_FinishFilamentMapping() if (wxGetApp().get_web_preprint_dialog()) { WebPreprintDialog* dialog = dynamic_cast(wxGetApp().get_web_preprint_dialog()); if (dialog) { + // BBS: Use SafeEndModal to prevent duplicate EndModal calls if(dialog->is_finish()){ - dialog->EndModal(wxID_OK); + dialog->SafeEndModal(wxID_OK); }else{ - dialog->EndModal(wxID_CANCEL); + dialog->SafeEndModal(wxID_CANCEL); } } } @@ -4397,7 +4398,7 @@ void SSWCP_UserLogin_Instance::sw_DownloadFile() { } // Use WCP Download Manager - WCPDownloadManager* download_mgr = wxGetApp().wcp_download_manager(); + DownloadManager* download_mgr = wxGetApp().download_manager(); if (!download_mgr) { handle_general_fail(-1, "WCP Download Manager not available"); return; @@ -4432,7 +4433,7 @@ void SSWCP_UserLogin_Instance::sw_CancelDownload() { return; } - WCPDownloadManager* download_mgr = wxGetApp().wcp_download_manager(); + DownloadManager* download_mgr = wxGetApp().download_manager(); if (!download_mgr) { handle_general_fail(-1, "WCP Download Manager not available"); return; diff --git a/src/slic3r/GUI/WebPreprintDialog.cpp b/src/slic3r/GUI/WebPreprintDialog.cpp index 1ec1cfa56e..eb192a1f9c 100644 --- a/src/slic3r/GUI/WebPreprintDialog.cpp +++ b/src/slic3r/GUI/WebPreprintDialog.cpp @@ -96,6 +96,22 @@ void WebPreprintDialog::set_display_file_name(const std::string& filename) { void WebPreprintDialog::set_gcode_file_name(const std::string& filename) { m_gcode_file_name = filename; } +void WebPreprintDialog::set_finish(bool flag) +{ + m_finish = flag; + // BBS: Don't call EndModal here to avoid conflict with sw_FinishFilamentMapping() + // The external sw_FinishFilamentMapping() function will handle EndModal based on m_finish flag +} + +void WebPreprintDialog::SafeEndModal(int returnCode) +{ + // BBS: Prevent duplicate EndModal calls which can cause crashes + if (IsModal() && !m_modal_ended) { + m_modal_ended = true; + EndModal(returnCode); + } +} + void WebPreprintDialog::reload() { load_url(m_prePrint_url); @@ -123,8 +139,16 @@ bool WebPreprintDialog::run() } this->load_url(real_url); - if (this->ShowModal() == wxID_OK) { - return true; + + // BBS: Reset flags before showing modal + m_finish = false; + m_modal_ended = false; + + int result = this->ShowModal(); + + // BBS: Check finish flag to determine return value + if (result == wxID_OK || (result == wxID_CANCEL && m_finish)) { + return m_finish; } return false; } @@ -186,7 +210,15 @@ void WebPreprintDialog::OnClose(wxCloseEvent& evt) { auto noti_manager = wxGetApp().mainframe->plater()->get_notification_manager(); noti_manager->close_notification_of_type(NotificationType::PrintHostUpload); - evt.Skip(); + + // BBS: Use SafeEndModal to prevent duplicate EndModal calls + // This ensures consistency with sw_FinishFilamentMapping() and prevents crashes + SafeEndModal(wxID_CANCEL); + + // If not modal or already ended, skip the event + if (!IsModal() || m_modal_ended) { + evt.Skip(); + } } }} // namespace Slic3r::GUI \ No newline at end of file diff --git a/src/slic3r/GUI/WebPreprintDialog.hpp b/src/slic3r/GUI/WebPreprintDialog.hpp index c077d1204a..98ca1b7523 100644 --- a/src/slic3r/GUI/WebPreprintDialog.hpp +++ b/src/slic3r/GUI/WebPreprintDialog.hpp @@ -33,7 +33,10 @@ public: bool is_finish() { return m_finish; } - void set_finish(bool flag) { m_finish = flag; } + void set_finish(bool flag); + + // BBS: Safely end modal dialog, preventing duplicate EndModal calls + void SafeEndModal(int returnCode); private: void OnClose(wxCloseEvent& evt); @@ -53,6 +56,7 @@ private: bool m_switch_to_device = false; bool m_finish = false; + bool m_modal_ended = false; // BBS: Flag to prevent duplicate EndModal calls DECLARE_EVENT_TABLE() };