From 44fe3b8a005e5b2aca940aef6ef59d4abb3c6663 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Tue, 24 Nov 2020 13:35:43 +0100 Subject: [PATCH 1/2] Tech ENABLE_DRAG_AND_DROP_FIX -> Apply dialog implemented with 808c43cb4b05b4e61abe07deee934bf63918bd22 also to drag and drop of project files into application executable --- src/libslic3r/Technologies.hpp | 7 + src/slic3r/GUI/GUI_App.cpp | 1 - src/slic3r/GUI/Plater.cpp | 225 +++++++++++++++++++++++++++++++-- src/slic3r/GUI/Plater.hpp | 4 + 4 files changed, 223 insertions(+), 14 deletions(-) diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 66258fe62..42061df71 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -74,4 +74,11 @@ #define ENABLE_SHOW_OPTION_POINT_LAYERS (1 && ENABLE_GCODE_VIEWER && ENABLE_2_3_0_ALPHA4) +//=================== +// 2.3.0.beta1 techs +//=================== +#define ENABLE_2_3_0_BETA1 1 + +#define ENABLE_DRAG_AND_DROP_FIX (1 && ENABLE_2_3_0_BETA1) + #endif // _prusaslicer_technologies_h_ diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 694cd7103..fa913f6b5 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -542,7 +542,6 @@ static void register_win32_device_notification_event() }); 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) { diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 763a906f5..5df1e5e17 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1351,17 +1351,20 @@ std::string& Sidebar::get_search_line() class PlaterDropTarget : public wxFileDropTarget { public: - PlaterDropTarget(Plater *plater) : plater(plater) { this->SetDefaultAction(wxDragCopy); } + PlaterDropTarget(Plater* plater) : m_plater(plater) { this->SetDefaultAction(wxDragCopy); } virtual bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &filenames); private: - Plater *plater; + Plater* m_plater; +#if !ENABLE_DRAG_AND_DROP_FIX static const std::regex pattern_drop; static const std::regex pattern_gcode_drop; +#endif // !ENABLE_DRAG_AND_DROP_FIX }; +#if !ENABLE_DRAG_AND_DROP_FIX const std::regex PlaterDropTarget::pattern_drop(".*[.](stl|obj|amf|3mf|prusa)", std::regex::icase); const std::regex PlaterDropTarget::pattern_gcode_drop(".*[.](gcode|g)", std::regex::icase); @@ -1428,16 +1431,22 @@ void ProjectDropDialog::on_dpi_changed(const wxRect& suggested_rect) Fit(); Refresh(); } +#endif // !ENABLE_DRAG_AND_DROP_FIX bool PlaterDropTarget::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &filenames) { +#if !ENABLE_DRAG_AND_DROP_FIX std::vector paths; +#endif // !ENABLE_DRAG_AND_DROP_FIX #ifdef WIN32 // hides the system icon this->MSWUpdateDragImageOnLeave(); #endif // WIN32 +#if ENABLE_DRAG_AND_DROP_FIX + return (m_plater != nullptr) ? m_plater->load_files(filenames) : false; +#else // gcode viewer section if (wxGetApp().is_gcode_viewer()) { for (const auto& filename : filenames) { @@ -1447,12 +1456,12 @@ bool PlaterDropTarget::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &fi } if (paths.size() > 1) { - wxMessageDialog((wxWindow*)plater, _L("You can open only one .gcode file at a time."), + wxMessageDialog((wxWindow*)m_plater, _L("You can open only one .gcode file at a time."), wxString(SLIC3R_APP_NAME) + " - " + _L("Drag and drop G-code file"), wxCLOSE | wxICON_WARNING | wxCENTRE).ShowModal(); return false; } else if (paths.size() == 1) { - plater->load_gcode(from_path(paths.front())); + m_plater->load_gcode(from_path(paths.front())); return true; } return false; @@ -1477,7 +1486,7 @@ bool PlaterDropTarget::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &fi std::string filename = (*it).filename().string(); if (boost::algorithm::iends_with(filename, ".3mf") || boost::algorithm::iends_with(filename, ".amf")) { LoadType load_type = LoadType::Unknown; - if (!plater->model().objects.empty()) { + if (!m_plater->model().objects.empty()) { if (wxGetApp().app_config->get("show_drop_project_dialog") == "1") { ProjectDropDialog dlg(filename); if (dlg.ShowModal() == wxID_OK) { @@ -1498,20 +1507,20 @@ bool PlaterDropTarget::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &fi switch (load_type) { case LoadType::OpenProject: { - plater->load_project(from_path(*it)); + m_plater->load_project(from_path(*it)); break; } case LoadType::LoadGeometry: { - Plater::TakeSnapshot snapshot(plater, _L("Import Object")); + Plater::TakeSnapshot snapshot(m_plater, _L("Import Object")); std::vector in_paths; in_paths.emplace_back(*it); - plater->load_files(in_paths, true, false); + m_plater->load_files(in_paths, true, false); break; } case LoadType::LoadConfig: { std::vector in_paths; in_paths.emplace_back(*it); - plater->load_files(in_paths, false, true); + m_plater->load_files(in_paths, false, true); break; } } @@ -1537,10 +1546,11 @@ bool PlaterDropTarget::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &fi snapshot_label += wxString::FromUTF8(paths[i].filename().string().c_str()); } } - Plater::TakeSnapshot snapshot(plater, snapshot_label); - plater->load_files(paths); + Plater::TakeSnapshot snapshot(m_plater, snapshot_label); + m_plater->load_files(paths); return true; +#endif // ENABLE_DRAG_AND_DROP_FIX } // State to manage showing after export notifications and device ejecting @@ -2113,11 +2123,22 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) // Initialize the Undo / Redo stack with a first snapshot. this->take_snapshot(_L("New Project")); - this->q->Bind(EVT_LOAD_MODEL_OTHER_INSTANCE, [this](LoadFromOtherInstanceEvent &evt) { +#if ENABLE_DRAG_AND_DROP_FIX + this->q->Bind(EVT_LOAD_MODEL_OTHER_INSTANCE, [this](LoadFromOtherInstanceEvent& evt) { + BOOST_LOG_TRIVIAL(debug) << "received load from other instance event "; + wxArrayString input_files; + for (size_t i = 0; i < evt.data.size(); ++i) { + input_files.push_back(from_u8(evt.data[i].string())); + } + this->q->load_files(input_files); + }); +#else + this->q->Bind(EVT_LOAD_MODEL_OTHER_INSTANCE, [this](LoadFromOtherInstanceEvent &evt) { BOOST_LOG_TRIVIAL(debug) << "received load from other instance event "; this->load_files(evt.data, true, true); }); - this->q->Bind(EVT_INSTANCE_GO_TO_FRONT, [this](InstanceGoToFrontEvent &) { +#endif // ENABLE_DRAG_AND_DROP_FIX + this->q->Bind(EVT_INSTANCE_GO_TO_FRONT, [this](InstanceGoToFrontEvent &) { bring_instance_forward(); }); wxGetApp().other_instance_message_handler()->init(this->q); @@ -4786,6 +4807,184 @@ std::vector Plater::load_files(const std::vector& input_fil return p->load_files(paths, load_model, load_config, imperial_units); } +#if ENABLE_DRAG_AND_DROP_FIX +enum class LoadType : unsigned char +{ + Unknown, + OpenProject, + LoadGeometry, + LoadConfig +}; + +class ProjectDropDialog : public DPIDialog +{ + wxRadioBox* m_action{ nullptr }; +public: + ProjectDropDialog(const std::string& filename); + + int get_action() const { return m_action->GetSelection() + 1; } + +protected: + void on_dpi_changed(const wxRect& suggested_rect) override; +}; + +ProjectDropDialog::ProjectDropDialog(const std::string& filename) + : DPIDialog((wxWindow*)wxGetApp().mainframe, wxID_ANY, + from_u8((boost::format(_utf8(L("%s - Drop project file"))) % SLIC3R_APP_NAME).str()), wxDefaultPosition, + wxDefaultSize, wxDEFAULT_DIALOG_STYLE) +{ + SetFont(wxGetApp().normal_font()); + + wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL); + + const wxString choices[] = { _L("Open as project"), + _L("Import geometry only"), + _L("Import config only") }; + + main_sizer->Add(new wxStaticText(this, wxID_ANY, + _L("Select an action to apply to the file") + ": " + from_u8(filename)), 0, wxEXPAND | wxALL, 10); + m_action = new wxRadioBox(this, wxID_ANY, _L("Action"), wxDefaultPosition, wxDefaultSize, + WXSIZEOF(choices), choices, 0, wxRA_SPECIFY_ROWS); + int action = std::clamp(std::stoi(wxGetApp().app_config->get("drop_project_action")), + static_cast(LoadType::OpenProject), static_cast(LoadType::LoadConfig)) - 1; + m_action->SetSelection(action); + main_sizer->Add(m_action, 1, wxEXPAND | wxRIGHT | wxLEFT, 10); + + wxBoxSizer* bottom_sizer = new wxBoxSizer(wxHORIZONTAL); + wxCheckBox* check = new wxCheckBox(this, wxID_ANY, _L("Don't show again")); + check->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent& evt) { + wxGetApp().app_config->set("show_drop_project_dialog", evt.IsChecked() ? "0" : "1"); + }); + + bottom_sizer->Add(check, 0, wxEXPAND | wxRIGHT, 5); + bottom_sizer->Add(CreateStdDialogButtonSizer(wxOK | wxCANCEL), 0, wxEXPAND | wxLEFT, 5); + main_sizer->Add(bottom_sizer, 0, wxEXPAND | wxALL, 10); + + SetSizer(main_sizer); + main_sizer->SetSizeHints(this); +} + +void ProjectDropDialog::on_dpi_changed(const wxRect& suggested_rect) +{ + const int em = em_unit(); + SetMinSize(wxSize(65 * em, 30 * em)); + Fit(); + Refresh(); +} + +bool Plater::load_files(const wxArrayString& filenames) +{ + const std::regex pattern_drop(".*[.](stl|obj|amf|3mf|prusa)", std::regex::icase); + const std::regex pattern_gcode_drop(".*[.](gcode|g)", std::regex::icase); + + std::vector paths; + + // gcode viewer section + if (wxGetApp().is_gcode_viewer()) { + for (const auto& filename : filenames) { + fs::path path(into_path(filename)); + if (std::regex_match(path.string(), pattern_gcode_drop)) + paths.push_back(std::move(path)); + } + + if (paths.size() > 1) { + wxMessageDialog((wxWindow*)this, _L("You can open only one .gcode file at a time."), + wxString(SLIC3R_APP_NAME) + " - " + _L("Drag and drop G-code file"), wxCLOSE | wxICON_WARNING | wxCENTRE).ShowModal(); + return false; + } + else if (paths.size() == 1) { + load_gcode(from_path(paths.front())); + return true; + } + return false; + } + + // editor section + for (const auto& filename : filenames) { + fs::path path(into_path(filename)); + if (std::regex_match(path.string(), pattern_drop)) + paths.push_back(std::move(path)); + else if (std::regex_match(path.string(), pattern_gcode_drop)) + start_new_gcodeviewer(&filename); + else + return false; + } + if (paths.empty()) + // Likely all paths processed were gcodes, for which a G-code viewer instance has hopefully been started. + return false; + + // searches for project files + for (std::vector::const_reverse_iterator it = paths.rbegin(); it != paths.rend(); ++it) { + std::string filename = (*it).filename().string(); + if (boost::algorithm::iends_with(filename, ".3mf") || boost::algorithm::iends_with(filename, ".amf")) { + LoadType load_type = LoadType::Unknown; + if (!model().objects.empty()) { + if (wxGetApp().app_config->get("show_drop_project_dialog") == "1") { + ProjectDropDialog dlg(filename); + if (dlg.ShowModal() == wxID_OK) { + int choice = dlg.get_action(); + load_type = static_cast(choice); + wxGetApp().app_config->set("drop_project_action", std::to_string(choice)); + } + } + else + load_type = static_cast(std::clamp(std::stoi(wxGetApp().app_config->get("drop_project_action")), + static_cast(LoadType::OpenProject), static_cast(LoadType::LoadConfig))); + } + else + load_type = LoadType::OpenProject; + + if (load_type == LoadType::Unknown) + return false; + + switch (load_type) { + case LoadType::OpenProject: { + load_project(from_path(*it)); + break; + } + case LoadType::LoadGeometry: { + Plater::TakeSnapshot snapshot(this, _L("Import Object")); + std::vector in_paths; + in_paths.emplace_back(*it); + load_files(in_paths, true, false); + break; + } + case LoadType::LoadConfig: { + std::vector in_paths; + in_paths.emplace_back(*it); + load_files(in_paths, false, true); + break; + } + } + + return true; + } + } + + // other files + wxString snapshot_label; + assert(!paths.empty()); + if (paths.size() == 1) { + snapshot_label = _L("Load File"); + snapshot_label += ": "; + snapshot_label += wxString::FromUTF8(paths.front().filename().string().c_str()); + } + else { + snapshot_label = _L("Load Files"); + snapshot_label += ": "; + snapshot_label += wxString::FromUTF8(paths.front().filename().string().c_str()); + for (size_t i = 1; i < paths.size(); ++i) { + snapshot_label += ", "; + snapshot_label += wxString::FromUTF8(paths[i].filename().string().c_str()); + } + } + Plater::TakeSnapshot snapshot(this, snapshot_label); + load_files(paths); + + return true; +} +#endif // ENABLE_DRAG_AND_DROP_FIX + void Plater::update() { p->update(); } void Plater::stop_jobs() { p->m_ui_jobs.stop_all(); } diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 0c1d48bc3..971f9c9c1 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -149,6 +149,10 @@ public: std::vector load_files(const std::vector& input_files, bool load_model = true, bool load_config = true, bool imperial_units = 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, bool load_model = true, bool load_config = true, bool imperial_units = false); +#if ENABLE_DRAG_AND_DROP_FIX + // to be called on drag and drop + bool load_files(const wxArrayString& filenames); +#endif // ENABLE_DRAG_AND_DROP_FIX void update(); void stop_jobs(); From 3d78ae9271f401838d3886716e3b61bbd591cf48 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Wed, 25 Nov 2020 12:28:10 +0100 Subject: [PATCH 2/2] Instance check on windows: concider whole window name when searching for another instance --- src/slic3r/GUI/InstanceCheck.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/InstanceCheck.cpp b/src/slic3r/GUI/InstanceCheck.cpp index aaf3ba3c6..d4dfa1f35 100644 --- a/src/slic3r/GUI/InstanceCheck.cpp +++ b/src/slic3r/GUI/InstanceCheck.cpp @@ -79,7 +79,7 @@ namespace instance_check_internal return true; std::wstring classNameString(className); std::wstring wndTextString(wndText); - if (wndTextString.find(L"PrusaSlicer") == 0 && classNameString == L"wxWindowNR") { + if (wndTextString.find(L"PrusaSlicer") != std::wstring::npos && classNameString == L"wxWindowNR") { //check if other instances has same instance hash //if not it is not same version(binary) as this version HANDLE handle = GetProp(hwnd, L"Instance_Hash_Minor");