From 7f7dddaeede605f2a976a6bc965d52defd1a8c6c Mon Sep 17 00:00:00 2001 From: SoftFever Date: Sat, 20 Apr 2024 18:11:18 +0800 Subject: [PATCH 1/3] Fixed an regression bug where the sidebar would not appear when Orca Slicer was opened by double-clicking a model file. (#5089) Fixed an issue that sidebar didn't show when OrcaSlicer is opened with double clicking a model --- src/slic3r/GUI/Plater.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 384c6f0b74..c0014354b1 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -6019,10 +6019,12 @@ void Plater::priv::set_current_panel(wxPanel* panel, bool no_slice) preview->set_as_dirty(); }; - //BBS: add the collapse logic + // Add sidebar and toolbar collapse logic + if (panel == view3D || panel == preview) { + this->enable_sidebar(!q->only_gcode_mode()); + } if (panel == preview) { if (q->only_gcode_mode()) { - this->sidebar->collapse(true); preview->get_canvas3d()->enable_select_plate_toolbar(false); } else if (q->using_exported_file() && (q->m_valid_plates_count <= 1)) { preview->get_canvas3d()->enable_select_plate_toolbar(false); @@ -8517,6 +8519,7 @@ Plater::Plater(wxWindow *parent, MainFrame *main_frame) { // Initialization performed in the private c-tor enable_wireframe(true); + m_only_gcode = false; } bool Plater::Show(bool show) From 1101ed9955b5c1e3beafe0bd157d536e37902f70 Mon Sep 17 00:00:00 2001 From: SoftFever Date: Sat, 20 Apr 2024 19:14:38 +0800 Subject: [PATCH 2/3] Revert "Show dialog when opening 3mf files to choose whether to import settings. (#4110)" This reverts commit 8ce07d3e8e2c616acee96748510aac43be772af0. --- src/slic3r/GUI/Plater.cpp | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index c0014354b1..35ad74dfd0 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -10315,21 +10315,23 @@ bool Plater::open_3mf_file(const fs::path &file_path) } LoadType load_type = LoadType::Unknown; - - bool show_drop_project_dialog = true; - if (show_drop_project_dialog) { - ProjectDropDialog dlg(filename); - if (dlg.ShowModal() == wxID_OK) { - int choice = dlg.get_action(); - load_type = static_cast(choice); - wxGetApp().app_config->set("import_project_action", std::to_string(choice)); + if (!model().objects.empty()) { + bool show_drop_project_dialog = true; + if (show_drop_project_dialog) { + ProjectDropDialog dlg(filename); + if (dlg.ShowModal() == wxID_OK) { + int choice = dlg.get_action(); + load_type = static_cast(choice); + wxGetApp().app_config->set("import_project_action", std::to_string(choice)); - // BBS: jump to plater panel - wxGetApp().mainframe->select_tab(MainFrame::tp3DEditor); - } + // BBS: jump to plater panel + wxGetApp().mainframe->select_tab(MainFrame::tp3DEditor); + } + } else + load_type = static_cast( + std::clamp(std::stoi(wxGetApp().app_config->get("import_project_action")), static_cast(LoadType::OpenProject), static_cast(LoadType::LoadConfig))); } else - load_type = static_cast( - std::clamp(std::stoi(wxGetApp().app_config->get("import_project_action")), static_cast(LoadType::OpenProject), static_cast(LoadType::LoadConfig))); + load_type = LoadType::OpenProject; if (load_type == LoadType::Unknown) return false; From 2b4520b2df4aca149c212dee714098a664f8b19a Mon Sep 17 00:00:00 2001 From: noobydp Date: Sat, 20 Apr 2024 20:05:15 +0800 Subject: [PATCH 3/3] ENH: restore single instance (#4810) --- src/slic3r/CMakeLists.txt | 8 ++++---- src/slic3r/GUI/GUI_App.cpp | 37 +++++++++++++++++----------------- src/slic3r/GUI/GUI_App.hpp | 22 ++++++++++---------- src/slic3r/GUI/GUI_Init.cpp | 6 +++--- src/slic3r/GUI/MainFrame.cpp | 8 ++++---- src/slic3r/GUI/Plater.cpp | 13 ++++++------ src/slic3r/GUI/Preferences.cpp | 9 +++++++++ 7 files changed, 57 insertions(+), 46 deletions(-) diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index 94a3b53e98..fa808b4ac5 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -399,8 +399,8 @@ set(SLIC3R_GUI_SOURCES GUI/ObjectDataViewModel.hpp GUI/AuxiliaryDataViewModel.cpp GUI/AuxiliaryDataViewModel.hpp - #GUI/InstanceCheck.cpp - #GUI/InstanceCheck.hpp + GUI/InstanceCheck.cpp + GUI/InstanceCheck.hpp GUI/Search.cpp GUI/Search.hpp GUI/NotificationManager.cpp @@ -558,8 +558,8 @@ if (APPLE) GUI/RemovableDriveManagerMM.mm GUI/RemovableDriveManagerMM.h GUI/Mouse3DHandlerMac.mm - #GUI/InstanceCheckMac.mm - #GUI/InstanceCheckMac.h + GUI/InstanceCheckMac.mm + GUI/InstanceCheckMac.h GUI/wxMediaCtrl2.mm GUI/wxMediaCtrl2.h ) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index e10fb62c1c..09cf851f79 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -689,15 +689,15 @@ static void register_win32_device_notification_event() return false; }); - //wxWindow::MSWRegisterMessageHandler(WM_COPYDATA, [](wxWindow* win, WXUINT /* nMsg */, WXWPARAM wParam, WXLPARAM lParam) { - // COPYDATASTRUCT* copy_data_structure = { 0 }; - // copy_data_structure = (COPYDATASTRUCT*)lParam; - // if (copy_data_structure->dwData == 1) { - // LPCWSTR arguments = (LPCWSTR)copy_data_structure->lpData; - // Slic3r::GUI::wxGetApp().other_instance_message_handler()->handle_message(boost::nowide::narrow(arguments)); - // } - // return true; - // }); + wxWindow::MSWRegisterMessageHandler(WM_COPYDATA, [](wxWindow* win, WXUINT /* nMsg */, WXWPARAM wParam, WXLPARAM lParam) { + COPYDATASTRUCT* copy_data_structure = { 0 }; + copy_data_structure = (COPYDATASTRUCT*)lParam; + if (copy_data_structure->dwData == 1) { + LPCWSTR arguments = (LPCWSTR)copy_data_structure->lpData; + Slic3r::GUI::wxGetApp().other_instance_message_handler()->handle_message(boost::nowide::narrow(arguments)); + } + return true; + }); } #endif // WIN32 @@ -1065,10 +1065,10 @@ void GUI_App::post_init() } BOOST_LOG_TRIVIAL(info) << "finished post_init"; //BBS: remove the single instance currently -/*#ifdef _WIN32 +#ifdef _WIN32 // Sets window property to mainframe so other instances can indentify it. OtherInstanceMessageHandler::init_windows_properties(mainframe, m_instance_hash_int); -#endif //WIN32*/ +#endif //WIN32 } wxDEFINE_EVENT(EVT_ENTER_FORCE_UPGRADE, wxCommandEvent); @@ -1086,7 +1086,7 @@ GUI_App::GUI_App() , m_em_unit(10) , m_imgui(new ImGuiWrapper()) , m_removable_drive_manager(std::make_unique()) - //, m_other_instance_message_handler(std::make_unique()) + , m_other_instance_message_handler(std::make_unique()) { //app config initializes early becasuse it is used in instance checking in OrcaSlicer.cpp this->init_app_config(); @@ -2029,11 +2029,11 @@ std::string GUI_App::get_local_models_path() return local_path; } -/*void GUI_App::init_single_instance_checker(const std::string &name, const std::string &path) +void GUI_App::init_single_instance_checker(const std::string &name, const std::string &path) { BOOST_LOG_TRIVIAL(debug) << "init wx instance checker " << name << " "<< path; m_single_instance_checker = std::make_unique(boost::nowide::widen(name), boost::nowide::widen(path)); -}*/ +} bool GUI_App::OnInit() { @@ -2510,9 +2510,9 @@ bool GUI_App::on_init_inner() update_mode(); // update view mode after fix of the object_list size -//#ifdef __APPLE__ -// other_instance_message_handler()->bring_instance_forward(); -//#endif //__APPLE__ +#ifdef __APPLE__ + other_instance_message_handler()->bring_instance_forward(); +#endif //__APPLE__ Bind(EVT_HTTP_ERROR, &GUI_App::on_http_error, this); @@ -5737,7 +5737,8 @@ void GUI_App::MacOpenURL(const wxString& url) // wxWidgets override to get an event on open files. void GUI_App::MacOpenFiles(const wxArrayString &fileNames) { - if (m_post_initialized) { + bool single_instance = app_config->get("app", "single_instance") == "true"; + if (m_post_initialized && !single_instance) { bool has3mf = false; std::vector names; for (auto & n : fileNames) { diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 21a38862fb..2186b1ab53 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -265,10 +265,10 @@ private: std::unique_ptr m_imgui; std::unique_ptr m_printhost_job_queue; - //std::unique_ptr m_other_instance_message_handler; - //std::unique_ptr m_single_instance_checker; - //std::string m_instance_hash_string; - //size_t m_instance_hash_int; + std::unique_ptr m_other_instance_message_handler; + std::unique_ptr m_single_instance_checker; + std::string m_instance_hash_string; + size_t m_instance_hash_int; //BBS bool m_is_closing {false}; @@ -594,13 +594,13 @@ private: Tab* plate_tab; RemovableDriveManager* removable_drive_manager() { return m_removable_drive_manager.get(); } - //OtherInstanceMessageHandler* other_instance_message_handler() { return m_other_instance_message_handler.get(); } - //wxSingleInstanceChecker* single_instance_checker() {return m_single_instance_checker.get();} + OtherInstanceMessageHandler* other_instance_message_handler() { return m_other_instance_message_handler.get(); } + wxSingleInstanceChecker* single_instance_checker() {return m_single_instance_checker.get();} - //void init_single_instance_checker(const std::string &name, const std::string &path); - //void set_instance_hash (const size_t hash) { m_instance_hash_int = hash; m_instance_hash_string = std::to_string(hash); } - //std::string get_instance_hash_string () { return m_instance_hash_string; } - //size_t get_instance_hash_int () { return m_instance_hash_int; } + void init_single_instance_checker(const std::string &name, const std::string &path); + void set_instance_hash (const size_t hash) { m_instance_hash_int = hash; m_instance_hash_string = std::to_string(hash); } + std::string get_instance_hash_string () { return m_instance_hash_string; } + size_t get_instance_hash_int () { return m_instance_hash_int; } ImGuiWrapper* imgui() { return m_imgui.get(); } @@ -625,7 +625,7 @@ private: int GetSingleChoiceIndex(const wxString& message, const wxString& caption, const wxArrayString& choices, int initialSelection); #ifdef __WXMSW__ - // extend is stl/3mf/gcode/step etc + // extend is stl/3mf/gcode/step etc void associate_files(std::wstring extend); void disassociate_files(std::wstring extend); #endif // __WXMSW__ diff --git a/src/slic3r/GUI/GUI_Init.cpp b/src/slic3r/GUI/GUI_Init.cpp index 81918c58ef..002123f8b3 100644 --- a/src/slic3r/GUI/GUI_Init.cpp +++ b/src/slic3r/GUI/GUI_Init.cpp @@ -40,14 +40,14 @@ int GUI_Run(GUI_InitParams ¶ms) try { //GUI::GUI_App* gui = new GUI::GUI_App(params.start_as_gcodeviewer ? GUI::GUI_App::EAppMode::GCodeViewer : GUI::GUI_App::EAppMode::Editor); GUI::GUI_App* gui = new GUI::GUI_App(); - /*if (gui->get_app_mode() != GUI::GUI_App::EAppMode::GCodeViewer) { + //if (gui->get_app_mode() != GUI::GUI_App::EAppMode::GCodeViewer) { // G-code viewer is currently not performing instance check, a new G-code viewer is started every time. - bool gui_single_instance_setting = gui->app_config->get("single_instance") == "1"; + bool gui_single_instance_setting = gui->app_config->get("app", "single_instance") == "true"; if (Slic3r::instance_check(params.argc, params.argv, gui_single_instance_setting)) { //TODO: do we have delete gui and other stuff? return -1; } - //}*/ + //} // gui->autosave = m_config.opt_string("autosave"); GUI::GUI_App::SetInstance(gui); diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 9befbb77b3..c7a990734d 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -114,12 +114,12 @@ public: OrcaSlicerTaskBarIcon(wxTaskBarIconType iconType = wxTBI_DEFAULT_TYPE) : wxTaskBarIcon(iconType) {} wxMenu *CreatePopupMenu() override { wxMenu *menu = new wxMenu; - //if (wxGetApp().app_config->get("single_instance") == "false") { + if (wxGetApp().app_config->get("single_instance") == "false") { // Only allow opening a new PrusaSlicer instance on OSX if "single_instance" is disabled, // as starting new instances would interfere with the locking mechanism of "single_instance" support. append_menu_item(menu, wxID_ANY, _L("New Window"), _L("Open a new window"), [](wxCommandEvent&) { start_new_slicer(); }, "", nullptr); - //} + } // append_menu_item(menu, wxID_ANY, _L("G-code Viewer") + dots, _L("Open G-code Viewer"), // [](wxCommandEvent&) { start_new_gcodeviewer_open_file(); }, "", nullptr); return menu; @@ -885,7 +885,7 @@ void MainFrame::shutdown() // Stop the background thread of the removable drive manager, so that no new updates will be sent to the Plater. //wxGetApp().removable_drive_manager()->shutdown(); //stop listening for messages from other instances - //wxGetApp().other_instance_message_handler()->shutdown(this); + wxGetApp().other_instance_message_handler()->shutdown(this); // Save the slic3r.ini.Usually the ini file is saved from "on idle" callback, // but in rare cases it may not have been called yet. if(wxGetApp().app_config->dirty()) @@ -2180,7 +2180,7 @@ void MainFrame::init_menubar_as_editor() // New Window append_menu_item(fileMenu, wxID_ANY, _L("New Window"), _L("Start a new window"), [](wxCommandEvent&) { start_new_slicer(); }, "", nullptr, - []{ return true; }, this); + [this] { return m_plater != nullptr && wxGetApp().app_config->get("app", "single_instance") == "false"; }, this); #endif // New Project append_menu_item(fileMenu, wxID_ANY, _L("New Project") + "\t" + ctrl + "N", _L("Start a new project"), diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 35ad74dfd0..939bb29dbe 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -3092,7 +3092,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) //wxPostEvent(this->q, wxCommandEvent{EVT_RESTORE_PROJECT}); } - /*this->q->Bind(EVT_LOAD_MODEL_OTHER_INSTANCE, [this](LoadFromOtherInstanceEvent& evt) { + this->q->Bind(EVT_LOAD_MODEL_OTHER_INSTANCE, [this](LoadFromOtherInstanceEvent& evt) { BOOST_LOG_TRIVIAL(trace) << "Received load from other instance event."; wxArrayString input_files; for (size_t i = 0; i < evt.data.size(); ++i) { @@ -3103,8 +3103,8 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) }); this->q->Bind(EVT_INSTANCE_GO_TO_FRONT, [this](InstanceGoToFrontEvent &) { bring_instance_forward(); - });*/ - //wxGetApp().other_instance_message_handler()->init(this->q); + }); + wxGetApp().other_instance_message_handler()->init(this->q); // collapse sidebar according to saved value //if (wxGetApp().is_editor()) { @@ -7502,10 +7502,11 @@ void Plater::priv::set_project_name(const wxString& project_name) BOOST_LOG_TRIVIAL(trace) << __FUNCTION__ << __LINE__ << " project is:" << project_name; m_project_name = project_name; //update topbar title - wxGetApp().mainframe->SetTitle(m_project_name); #ifdef __WINDOWS__ + wxGetApp().mainframe->SetTitle(m_project_name + " - OrcaSlicer"); wxGetApp().mainframe->topbar()->SetTitle(m_project_name); #else + wxGetApp().mainframe->SetTitle(m_project_name); if (!m_project_name.IsEmpty()) wxGetApp().mainframe->update_title_colour_after_set_title(); #endif @@ -8409,10 +8410,10 @@ void Plater::priv::update_after_undo_redo(const UndoRedo::Snapshot& snapshot, bo void Plater::priv::bring_instance_forward() const { -/*#ifdef __APPLE__ +#ifdef __APPLE__ wxGetApp().other_instance_message_handler()->bring_instance_forward(); return; -#endif //__APPLE__*/ +#endif //__APPLE__ if (main_frame == nullptr) { BOOST_LOG_TRIVIAL(debug) << "Couldnt bring instance forward - mainframe is null"; return; diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index 05848d6ea7..bbca3a5a08 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -1021,6 +1021,14 @@ wxWindow* PreferencesDialog::create_general_page() std::vector Units = {_L("Metric") + " (mm, g)", _L("Imperial") + " (in, oz)"}; auto item_currency = create_item_combobox(_L("Units"), page, _L("Units"), "use_inches", Units); + auto item_single_instance = create_item_checkbox(_L("Allow only one OrcaSlicer instance"), page, + #if __APPLE__ + _L("On OSX there is always only one instance of app running by default. However it is allowed to run multiple instances " + "of same app from the command line. In such case this settings will allow only one instance."), + #else + _L("If this is enabled, when starting OrcaSlicer and another instance of the same OrcaSlicer is already running, that instance will be reactivated instead."), + #endif + 50, "single_instance"); std::vector DefaultPage = {_L("Home"), _L("Prepare")}; auto item_default_page = create_item_combobox(_L("Default Page"), page, _L("Set the page opened on startup."), "default_page", DefaultPage); @@ -1096,6 +1104,7 @@ wxWindow* PreferencesDialog::create_general_page() sizer_page->Add(item_currency, 0, wxTOP, FromDIP(3)); sizer_page->Add(item_default_page, 0, wxTOP, FromDIP(3)); sizer_page->Add(item_camera_navigation_style, 0, wxTOP, FromDIP(3)); + sizer_page->Add(item_single_instance, 0, wxTOP, FromDIP(3)); sizer_page->Add(item_mouse_zoom_settings, 0, wxTOP, FromDIP(3)); sizer_page->Add(item_use_free_camera_settings, 0, wxTOP, FromDIP(3)); sizer_page->Add(reverse_mouse_zoom, 0, wxTOP, FromDIP(3));