From 51b646efcf7aeae7cc5a7e4790b31fa8baf4bbe1 Mon Sep 17 00:00:00 2001 From: Lam Wei Lun Date: Tue, 25 Aug 2026 16:40:18 +0800 Subject: [PATCH] Better safety if publish workflow crashes. Cleanup on Button --- src/slic3r/GUI/Plater.cpp | 56 +++++++++++++++++++----------- src/slic3r/GUI/Widgets/Button.cpp | 21 ++++------- src/slic3r/GUI/Widgets/Button.hpp | 3 -- src/slic3r/GUI/Widgets/TabCtrl.cpp | 2 +- src/slic3r/GUI/Widgets/TabCtrl.hpp | 5 +-- 5 files changed, 45 insertions(+), 42 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 52d90623fe..bdca6b7c77 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -16323,29 +16323,43 @@ int Plater::export_published_3mf(const std::vector& published_keys, if (full_pathnames) save_strategy = save_strategy | SaveStrategy::FullPathSources; - const int ret = export_3mf(into_path(path), save_strategy, -1, nullptr); + // Restore the previous metadata state (both on success and on failure): a thrown export + // must not leave the published metadata on the in-memory project, or a later Save Project + // would write a hybrid file (full config + slicer tags + published metadata) that receivers + // silently load in published mode, skipping the project's own presets. + auto restore_metadata = [&]() { + if (!had_model_info) { + model.model_info = nullptr; + } else { + if (had_published) + model.model_info->metadata_items["published"] = prev_published; + else + model.model_info->metadata_items.erase("published"); + if (had_published_keys) + model.model_info->metadata_items["published_keys"] = prev_published_keys; + else + model.model_info->metadata_items.erase("published_keys"); + if (had_material_keys) + model.model_info->metadata_items["published_material_keys"] = prev_material_keys; + else + model.model_info->metadata_items.erase("published_material_keys"); + if (had_payload) + model.model_info->metadata_items["published_config"] = prev_payload; + else + model.model_info->metadata_items.erase("published_config"); + } + }; - // Restore the previous metadata state (both on success and on failure). - if (!had_model_info) { - model.model_info = nullptr; - } else { - if (had_published) - model.model_info->metadata_items["published"] = prev_published; - else - model.model_info->metadata_items.erase("published"); - if (had_published_keys) - model.model_info->metadata_items["published_keys"] = prev_published_keys; - else - model.model_info->metadata_items.erase("published_keys"); - if (had_material_keys) - model.model_info->metadata_items["published_material_keys"] = prev_material_keys; - else - model.model_info->metadata_items.erase("published_material_keys"); - if (had_payload) - model.model_info->metadata_items["published_config"] = prev_payload; - else - model.model_info->metadata_items.erase("published_config"); + int ret; + try { + ret = export_3mf(into_path(path), save_strategy, -1, nullptr); + } catch (...) { + restore_metadata(); + MessageDialog(this, _L("Failed to export the published 3MF file.\nPlease check whether the folder exists online or if other programs have the file open."), + _L("Publish"), wxOK | wxICON_WARNING).ShowModal(); + return wxID_CANCEL; } + restore_metadata(); if (ret < 0) { MessageDialog(this, _L("Failed to export the published 3MF file.\nPlease check whether the folder exists online or if other programs have the file open."), diff --git a/src/slic3r/GUI/Widgets/Button.cpp b/src/slic3r/GUI/Widgets/Button.cpp index 3129d608ca..5a5bd89403 100644 --- a/src/slic3r/GUI/Widgets/Button.cpp +++ b/src/slic3r/GUI/Widgets/Button.cpp @@ -80,7 +80,6 @@ bool Button::SetFont(const wxFont& font) void Button::SetIcon(const wxString& icon) { - custom_icon = wxNullBitmap; auto tmpBitmap = ScalableBitmap(this, icon.ToStdString(), this->active_icon.px_cnt()); if (!icon.IsEmpty()) { //BBS set button icon default size to 20 @@ -104,13 +103,6 @@ void Button::SetIcon(const wxBitmap& icon) Refresh(); } -void Button::SetBitmap(const wxBitmap& bitmap) -{ - custom_icon = bitmap; - messureSize(); - Refresh(); -} - void Button::SetMinSize(const wxSize& size) { minSize = size; @@ -310,8 +302,7 @@ void Button::render(wxDC& dc) } } auto szContent = textSize; - const bool has_custom_icon = custom_icon.IsOk(); - if (has_custom_icon || icon.bmp().IsOk()) { + if (icon.bmp().IsOk()) { if (szContent.y > 0) { //BBS norrow size between text and icon if (vertical) @@ -319,7 +310,7 @@ void Button::render(wxDC& dc) else szContent.x += spacing; } - szIcon = has_custom_icon ? custom_icon.GetSize() : icon.GetBmpSize(); + szIcon = icon.GetBmpSize(); if (vertical) { szContent.y += szIcon.y; if (szIcon.x > szContent.x) szContent.x = szIcon.x; @@ -342,12 +333,12 @@ void Button::render(wxDC& dc) } // start draw wxPoint pt = rcContent.GetLeftTop(); - if (has_custom_icon || icon.bmp().IsOk()) { + if (icon.bmp().IsOk()) { if (vertical) pt.x += (rcContent.width - szIcon.x) / 2; else pt.y += (rcContent.height - szIcon.y) / 2; - dc.DrawBitmap(has_custom_icon ? custom_icon : icon.bmp(), pt); + dc.DrawBitmap(icon.bmp(), pt); //BBS norrow size between text and icon if (vertical) { pt.y += szIcon.y + spacing; @@ -380,7 +371,7 @@ void Button::messureSize() wxClientDC dc(this); dc.GetTextExtent(GetLabel(), &textSize.width, &textSize.height, &textSize.x, &textSize.y); wxSize szContent = textSize.GetSize(); - if (custom_icon.IsOk() || this->active_icon.bmp().IsOk()) { + if (this->active_icon.bmp().IsOk()) { if (szContent.y > 0) { //BBS norrow size between text and icon if (vertical) @@ -388,7 +379,7 @@ void Button::messureSize() else szContent.x += 5; } - wxSize szIcon = custom_icon.IsOk() ? custom_icon.GetSize() : this->active_icon.GetBmpSize(); + wxSize szIcon = this->active_icon.GetBmpSize(); if (vertical) { szContent.y += szIcon.y; if (szIcon.x > szContent.x) szContent.x = szIcon.x; diff --git a/src/slic3r/GUI/Widgets/Button.hpp b/src/slic3r/GUI/Widgets/Button.hpp index 9ad0810804..19dcd24938 100644 --- a/src/slic3r/GUI/Widgets/Button.hpp +++ b/src/slic3r/GUI/Widgets/Button.hpp @@ -36,7 +36,6 @@ class Button : public StaticBox wxSize minSize; // set by outer wxSize paddingSize; ScalableBitmap active_icon; - wxBitmap custom_icon; StateColor text_color; @@ -63,8 +62,6 @@ public: void SetIcon(const wxString& icon); void SetIcon(const wxBitmap& icon); - void SetBitmap(const wxBitmap& bitmap); - void SetMinSize(const wxSize& size) override; void SetMaxSize(const wxSize& size) override; diff --git a/src/slic3r/GUI/Widgets/TabCtrl.cpp b/src/slic3r/GUI/Widgets/TabCtrl.cpp index 5c2eb2d693..7817c9111a 100644 --- a/src/slic3r/GUI/Widgets/TabCtrl.cpp +++ b/src/slic3r/GUI/Widgets/TabCtrl.cpp @@ -182,7 +182,7 @@ void TabCtrl::SetItemBitmap(unsigned int item, const wxBitmap& bitmap) { if (item >= btns.size()) return; - btns[item]->SetBitmap(bitmap); + btns[item]->SetIcon(bitmap); relayout(); } diff --git a/src/slic3r/GUI/Widgets/TabCtrl.hpp b/src/slic3r/GUI/Widgets/TabCtrl.hpp index 5631eeb6a7..5374a32a73 100644 --- a/src/slic3r/GUI/Widgets/TabCtrl.hpp +++ b/src/slic3r/GUI/Widgets/TabCtrl.hpp @@ -64,6 +64,9 @@ public: int GetNextVisible(int item) const; bool IsVisible(unsigned int item) const; + // Width of the tab strip that keeps every button visible (used to size the Publish dialog). + int buttons_best_width() const; + private: virtual void DoSetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO); @@ -73,8 +76,6 @@ private: void relayout(); - int buttons_best_width() const; - void buttonClicked(wxCommandEvent & event); void keyDown(wxKeyEvent &event);