diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index a8a7e5c86..8868b0445 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -33,8 +33,8 @@ namespace Slic3r { namespace GUI { MainFrame::MainFrame() : -DPIFrame(NULL, wxID_ANY, wxString(SLIC3R_BUILD_ID) + " " + _(L("based on Slic3r")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, "mainframe"), - m_printhost_queue_dlg(new PrintHostQueueDialog(this)) +DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, "mainframe"), + m_printhost_queue_dlg(new PrintHostQueueDialog(this)) { // Fonts were created by the DPIFrame constructor for the monitor, on which the window opened. wxGetApp().update_fonts(this); @@ -95,6 +95,8 @@ DPIFrame(NULL, wxID_ANY, wxString(SLIC3R_BUILD_ID) + " " + _(L("based on Slic3r" #endif Layout(); + update_title(); + // declare events Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent& event) { if (event.CanVeto() && !wxGetApp().check_unsaved_changes()) { @@ -136,6 +138,19 @@ DPIFrame(NULL, wxID_ANY, wxString(SLIC3R_BUILD_ID) + " " + _(L("based on Slic3r" update_ui_from_settings(); // FIXME (?) } +void MainFrame::update_title() +{ + wxString title = wxEmptyString; + if (m_plater != nullptr) + { + wxString project = from_path(into_path(m_plater->get_project_filename()).filename()); + if (!project.empty()) + title += (project + " - "); + } + title += (wxString(SLIC3R_BUILD_ID) + " " + _(L("based on Slic3r"))); + + SetTitle(title); +} void MainFrame::init_tabpanel() { @@ -206,6 +221,11 @@ void MainFrame::add_created_tab(Tab* panel) m_tabpanel->AddPage(panel, panel->title()); } +bool MainFrame::can_start_new_project() const +{ + return (m_plater != nullptr) && !m_plater->model().objects.empty(); +} + bool MainFrame::can_save() const { return (m_plater != nullptr) && !m_plater->model().objects.empty(); @@ -282,6 +302,11 @@ bool MainFrame::can_delete_all() const return (m_plater != nullptr) && !m_plater->model().objects.empty(); } +bool MainFrame::can_reslice() const +{ + return (m_plater != nullptr) && !m_plater->model().objects.empty(); +} + void MainFrame::on_dpi_changed(const wxRect &suggested_rect) { wxGetApp().update_fonts(); @@ -347,7 +372,8 @@ void MainFrame::init_menubar() wxMenu* fileMenu = new wxMenu; { append_menu_item(fileMenu, wxID_ANY, _(L("&New Project")) + "\tCtrl+N", _(L("Start a new project")), - [this](wxCommandEvent&) { if (m_plater) m_plater->new_project(); }, ""); + [this](wxCommandEvent&) { if (m_plater) m_plater->new_project(); }, "", nullptr, + [this](){return m_plater != nullptr && can_start_new_project(); }, this); append_menu_item(fileMenu, wxID_ANY, _(L("&Open Project")) + dots + "\tCtrl+O", _(L("Open a project file")), [this](wxCommandEvent&) { if (m_plater) m_plater->load_project(); }, menu_icon("open"), nullptr, [this](){return m_plater != nullptr; }, this); @@ -421,7 +447,8 @@ void MainFrame::init_menubar() fileMenu->AppendSeparator(); #endif m_menu_item_reslice_now = append_menu_item(fileMenu, wxID_ANY, _(L("(Re)Slice No&w")) + "\tCtrl+R", _(L("Start new slicing process")), - [this](wxCommandEvent&) { reslice_now(); }, menu_icon("re_slice")); + [this](wxCommandEvent&) { reslice_now(); }, menu_icon("re_slice"), nullptr, + [this](){return m_plater != nullptr && can_reslice(); }, this); fileMenu->AppendSeparator(); append_menu_item(fileMenu, wxID_ANY, _(L("&Repair STL file")) + dots, _(L("Automatically repair an STL file")), [this](wxCommandEvent&) { repair_stl(); }, menu_icon("wrench")); @@ -1038,6 +1065,5 @@ std::string MainFrame::get_dir_name(const wxString &full_name) const return boost::filesystem::path(full_name.wx_str()).parent_path().string(); } - } // GUI } // Slic3r diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp index b5d875cbf..a5de94738 100644 --- a/src/slic3r/GUI/MainFrame.hpp +++ b/src/slic3r/GUI/MainFrame.hpp @@ -61,6 +61,7 @@ class MainFrame : public DPIFrame void on_presets_changed(SimpleEvent&); void on_value_changed(wxCommandEvent&); + bool can_start_new_project() const; bool can_save() const; bool can_export_model() const; bool can_export_supports() const; @@ -71,6 +72,7 @@ class MainFrame : public DPIFrame bool can_deselect() const; bool can_delete() const; bool can_delete_all() const; + bool can_reslice() const; // MenuBar items changeable in respect to printer technology enum MenuItems @@ -91,6 +93,8 @@ public: Plater* plater() { return m_plater; } + void update_title(); + void init_tabpanel(); void create_preset_tabs(); void add_created_tab(Tab* panel); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 572b25c16..0e45f13ce 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1216,8 +1216,6 @@ struct Plater::priv GLToolbar view_toolbar; Preview *preview; - wxString project_filename; - BackgroundSlicingProcess background_process; bool arranging; bool rotoptimizing; @@ -1342,6 +1340,9 @@ struct Plater::priv void msw_rescale_object_menu(); + const wxString& get_project_filename() const; + void set_project_filename(const wxString& filename); + private: bool init_object_menu(); bool init_common_menu(wxMenu* menu, const bool is_part = false); @@ -1355,6 +1356,8 @@ private: void update_fff_scene(); void update_sla_scene(); + + wxString m_project_filename; }; const std::regex Plater::priv::pattern_bundle(".*[.](amf|amf[.]xml|zip[.]amf|3mf|prusa)", std::regex::icase); @@ -1381,12 +1384,12 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) })) , sidebar(new Sidebar(q)) , delayed_scene_refresh(false) - , project_filename(wxEmptyString) #if ENABLE_SVG_ICONS , view_toolbar(GLToolbar::Radio, "View") #else , view_toolbar(GLToolbar::Radio) #endif // ENABLE_SVG_ICONS + , m_project_filename(wxEmptyString) { this->q->SetFont(Slic3r::GUI::wxGetApp().normal_font()); @@ -1930,13 +1933,20 @@ wxString Plater::priv::get_export_file(GUI::FileType file_type) int obj_idx = selection.get_object_idx(); fs::path output_file; - // first try to get the file name from the current selection - if ((0 <= obj_idx) && (obj_idx < (int)this->model.objects.size())) - output_file = this->model.objects[obj_idx]->get_export_filename(); + if (file_type == FT_3MF) + // for 3mf take the path from the project filename, if any + output_file = into_path(get_project_filename()); if (output_file.empty()) - // Find the file name of the first printable object. - output_file = this->model.propose_export_file_name_and_path(); + { + // first try to get the file name from the current selection + if ((0 <= obj_idx) && (obj_idx < (int)this->model.objects.size())) + output_file = this->model.objects[obj_idx]->get_export_filename(); + + if (output_file.empty()) + // Find the file name of the first printable object. + output_file = this->model.propose_export_file_name_and_path(); + } wxString dlg_title; switch (file_type) { @@ -2064,7 +2074,7 @@ void Plater::priv::delete_object_from_model(size_t obj_idx) void Plater::priv::reset() { - project_filename.Clear(); + set_project_filename(wxEmptyString); // Prevent toolpaths preview from rendering while we modify the Print object preview->set_enabled(false); @@ -2932,6 +2942,17 @@ void Plater::priv::msw_rescale_object_menu() msw_rescale_menu(dynamic_cast(menu)); } +const wxString& Plater::priv::get_project_filename() const +{ + return m_project_filename; +} + +void Plater::priv::set_project_filename(const wxString& filename) +{ + m_project_filename = filename; + wxGetApp().mainframe->update_title(); +} + bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/) { if (is_part) { @@ -3243,6 +3264,7 @@ SLAPrint& Plater::sla_print() { return p->sla_print; } void Plater::new_project() { + wxPostEvent(p->view3D->get_wxglcanvas(), SimpleEvent(EVT_GLTOOLBAR_DELETE_ALL)); } void Plater::load_project() @@ -3254,7 +3276,7 @@ void Plater::load_project() return; p->reset(); - p->project_filename = input_file; + p->set_project_filename(input_file); std::vector input_paths; input_paths.push_back(into_path(input_file)); @@ -3608,7 +3630,9 @@ void Plater::export_3mf(const boost::filesystem::path& output_path) if (Slic3r::store_3mf(path_u8.c_str(), &p->model, export_config ? &cfg : nullptr)) { // Success p->statusbar()->set_status_text(wxString::Format(_(L("3MF file exported to %s")), path)); - } else { + p->set_project_filename(path); + } + else { // Failure p->statusbar()->set_status_text(wxString::Format(_(L("Error exporting 3MF file %s")), path)); } @@ -3801,7 +3825,7 @@ void Plater::on_activate() const wxString& Plater::get_project_filename() const { - return p->project_filename; + return p->get_project_filename(); } bool Plater::is_export_gcode_scheduled() const