diff options
Diffstat (limited to 'src/slic3r/GUI/GUI_App.cpp')
-rw-r--r-- | src/slic3r/GUI/GUI_App.cpp | 299 |
1 files changed, 154 insertions, 145 deletions
diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index bda7394ed..5ebd5300a 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -862,9 +862,9 @@ static boost::optional<Semver> parse_semver_from_ini(std::string path) void GUI_App::init_app_config() { // Profiles for the alpha are stored into the PrusaSlicer-alpha directory to not mix with the current release. -// SetAppName(SLIC3R_APP_KEY); + SetAppName(SLIC3R_APP_KEY); // SetAppName(SLIC3R_APP_KEY "-alpha"); - SetAppName(SLIC3R_APP_KEY "-beta"); +// SetAppName(SLIC3R_APP_KEY "-beta"); // SetAppDisplayName(SLIC3R_APP_NAME); // Set the Slic3r data directory at the Slic3r XS module. @@ -909,17 +909,18 @@ void GUI_App::init_app_config() "\n\n" + app_config->config_path() + "\n\n" + error); } } - // Save orig_version here, so its empty if no app_config existed before this run. - m_last_config_version = app_config->orig_version();//parse_semver_from_ini(app_config->config_path()); } } -// returns true if found newer version and user agreed to use it -bool GUI_App::check_older_app_config(Semver current_version, bool backup) +// returns old config path to copy from if such exists, +// returns an empty string if such config path does not exists or if it cannot be loaded. +std::string GUI_App::check_older_app_config(Semver current_version, bool backup) { + std::string older_data_dir_path; + // If the config folder is redefined - do not check if (m_datadir_redefined) - return false; + return {}; // find other version app config (alpha / beta / release) std::string config_path = app_config->config_path(); @@ -940,55 +941,57 @@ bool GUI_App::check_older_app_config(Semver current_version, bool backup) boost::optional<Semver>other_semver = parse_semver_from_ini(candidate.string()); if (other_semver && *other_semver > last_semver) { last_semver = *other_semver; - m_older_data_dir_path = candidate.parent_path().string(); + older_data_dir_path = candidate.parent_path().string(); } } } - if (m_older_data_dir_path.empty()) - return false; - BOOST_LOG_TRIVIAL(info) << "last app config file used: " << m_older_data_dir_path; + if (older_data_dir_path.empty()) + return {}; + BOOST_LOG_TRIVIAL(info) << "last app config file used: " << older_data_dir_path; // ask about using older data folder - RichMessageDialog msg(nullptr, backup ? - wxString::Format(_L("PrusaSlicer detected another configuration folder at %s." - "\nIts version is %s." - "\nLast version you used in current configuration folder is %s." - "\nPlease note that PrusaSlicer uses different folders to save configuration of alpha, beta and full release versions." - "\nWould you like to copy found configuration to your current configuration folder?" - - "\n\nIf you select yes, PrusaSlicer will copy all profiles and other files from found folder to the current one. Overwriting any existing file with matching name." - "\nIf you select no, you will continue with current configuration.") - , m_older_data_dir_path, last_semver.to_string(), current_version.to_string()) - : wxString::Format(_L("PrusaSlicer detected another configuration folder at %s." - "\nIts version is %s." - "\nThere is no configuration file in current configuration folder." - "\nPlease note that PrusaSlicer uses different folders to save configuration of alpha, beta and full release versions." - "\nWould you like to copy found configuration to your current configuration folder?" - - "\n\nIf you select yes, PrusaSlicer will copy all profiles and other files from found folder to the current one." - "\nIf you select no, you will start with clean installation with configuration wizard.") - , m_older_data_dir_path, last_semver.to_string()) - , _L("PrusaSlicer"), /*wxICON_QUESTION | */wxYES_NO); + + InfoDialog msg(nullptr + , format_wxstr(_L("You are opening %1% version %2%."), SLIC3R_APP_NAME, SLIC3R_VERSION) + , backup ? + format_wxstr(_L( + "The active configuration was created by <b>%1% %2%</b>," + "\nwhile a newer configuration was found in <b>%3%</b>" + "\ncreated by <b>%1% %4%</b>." + "\n\nShall the newer configuration be imported?" + "\nIf so, your active configuration will be backed up before importing the new configuration." + ) + , SLIC3R_APP_NAME, current_version.to_string(), older_data_dir_path, last_semver.to_string()) + : format_wxstr(_L( + "An existing configuration was found in <b>%3%</b>" + "\ncreated by <b>%1% %2%</b>." + "\n\nShall this configuration be imported?" + ) + , SLIC3R_APP_NAME, last_semver.to_string(), older_data_dir_path) + , true, wxYES_NO); + + if (backup) { + msg.SetButtonLabel(wxID_YES, _L("Import")); + msg.SetButtonLabel(wxID_NO, _L("Don't import")); + } + if (msg.ShowModal() == wxID_YES) { std::string snapshot_id; if (backup) { - // configuration snapshot - std::string comment; - if (const Config::Snapshot* snapshot = Config::take_config_snapshot_report_error( - *app_config, - Config::Snapshot::SNAPSHOT_USER, - comment); - snapshot != nullptr) - // Is thos correct? Save snapshot id for later, when new app config is loaded. + const Config::Snapshot* snapshot{ nullptr }; + if (! GUI::Config::take_config_snapshot_cancel_on_error(*app_config, Config::Snapshot::SNAPSHOT_USER, "", + _u8L("Continue and import newer configuration?"), &snapshot)) + return {}; + if (snapshot) { + // Save snapshot ID before loading the alternate AppConfig, as loading the alternate AppConfig may fail. snapshot_id = snapshot->id; - else - BOOST_LOG_TRIVIAL(error) << "Failed to take congiguration snapshot: "; + assert(! snapshot_id.empty()); + app_config->set("on_snapshot", snapshot_id); + } else + BOOST_LOG_TRIVIAL(error) << "Failed to take congiguration snapshot"; } - // This will tell later (when config folder structure is sure to exists) to copy files from m_older_data_dir_path - m_init_app_config_from_older = true; // load app config from older file - app_config->set_loading_path((boost::filesystem::path(m_older_data_dir_path) / filename).string()); - std::string error = app_config->load(); + std::string error = app_config->load((boost::filesystem::path(older_data_dir_path) / filename).string()); if (!error.empty()) { // Error while parsing config file. We'll customize the error message and rethrow to be displayed. if (is_editor()) { @@ -1007,14 +1010,9 @@ bool GUI_App::check_older_app_config(Semver current_version, bool backup) if (!snapshot_id.empty()) app_config->set("on_snapshot", snapshot_id); m_app_conf_exists = true; - return true; + return older_data_dir_path; } - return false; -} - -void GUI_App::copy_older_config() -{ - preset_bundle->copy_files(m_older_data_dir_path); + return {}; } void GUI_App::init_single_instance_checker(const std::string &name, const std::string &path) @@ -1035,6 +1033,9 @@ bool GUI_App::OnInit() bool GUI_App::on_init_inner() { + // Set initialization of image handlers before any UI actions - See GH issue #7469 + wxInitAllImageHandlers(); + #if defined(_WIN32) && ! defined(_WIN64) // Win32 32bit build. if (wxPlatformInfo::Get().GetArchName().substr(0, 2) == "64") { @@ -1077,6 +1078,42 @@ bool GUI_App::on_init_inner() // Slic3r::debugf "wxWidgets version %s, Wx version %s\n", wxVERSION_STRING, wxVERSION; + // !!! Initialization of UI settings as a language, application color mode, fonts... have to be done before first UI action. + // Like here, before the show InfoDialog in check_older_app_config() + + // If load_language() fails, the application closes. + load_language(wxString(), true); +#ifdef _MSW_DARK_MODE + bool init_dark_color_mode = app_config->get("dark_color_mode") == "1"; + bool init_sys_menu_enabled = app_config->get("sys_menu_enabled") == "1"; + NppDarkMode::InitDarkMode(init_dark_color_mode, init_sys_menu_enabled); +#endif + // initialize label colors and fonts + init_label_colours(); + init_fonts(); + + std::string older_data_dir_path; + if (m_app_conf_exists) { + if (app_config->orig_version().valid() && app_config->orig_version() < *Semver::parse(SLIC3R_VERSION)) + // Only copying configuration if it was saved with a newer slicer than the one currently running. + older_data_dir_path = check_older_app_config(app_config->orig_version(), true); + } else { + // No AppConfig exists, fresh install. Always try to copy from an alternate location, don't make backup of the current configuration. + older_data_dir_path = check_older_app_config(Semver(), false); + } + +#ifdef _MSW_DARK_MODE + // app_config can be updated in check_older_app_config(), so check if dark_color_mode and sys_menu_enabled was changed + if (bool new_dark_color_mode = app_config->get("dark_color_mode") == "1"; + init_dark_color_mode != new_dark_color_mode) { + NppDarkMode::SetDarkMode(new_dark_color_mode); + init_label_colours(); + update_label_colours_from_appconfig(); + } + if (bool new_sys_menu_enabled = app_config->get("sys_menu_enabled") == "1"; + init_sys_menu_enabled != new_sys_menu_enabled) + NppDarkMode::SetSystemMenuForApp(new_sys_menu_enabled); +#endif if (is_editor()) { std::string msg = Http::tls_global_init(); @@ -1098,24 +1135,6 @@ bool GUI_App::on_init_inner() } } - if (m_last_config_version) { - if (*m_last_config_version < *Semver::parse(SLIC3R_VERSION)) - check_older_app_config(*m_last_config_version, true); - } else { - check_older_app_config(Semver(), false); - } - - app_config->set("version", SLIC3R_VERSION); - app_config->save(); - - // If load_language() fails, the application closes. - load_language(wxString(), true); - - wxInitAllImageHandlers(); - -#ifdef _MSW_DARK_MODE - NppDarkMode::InitDarkMode(app_config->get("dark_color_mode") == "1", app_config->get("sys_menu_enabled") == "1"); -#endif SplashScreen* scrn = nullptr; if (app_config->get("show_splash_screen") == "1") { // make a bitmap with dark grey banner on the left side @@ -1139,17 +1158,18 @@ bool GUI_App::on_init_inner() scrn->SetText(_L("Loading configuration")+ dots); } - - preset_bundle = new PresetBundle(); // just checking for existence of Slic3r::data_dir is not enough : it may be an empty directory // supplied as argument to --datadir; in that case we should still run the wizard preset_bundle->setup_directories(); - - if (m_init_app_config_from_older) - copy_older_config(); + if (! older_data_dir_path.empty()) + preset_bundle->import_newer_configs(older_data_dir_path); + + // Save PrusaSlicer.ini after possibly copying the config from the alternate location and after all the configs from the alternate location were copied. + app_config->set("version", SLIC3R_VERSION); + app_config->save(); if (is_editor()) { #ifdef __WXMSW__ @@ -1198,10 +1218,6 @@ bool GUI_App::on_init_inner() #endif // __WXMSW__ } - // initialize label colors and fonts - init_label_colours(); - init_fonts(); - // Suppress the '- default -' presets. preset_bundle->set_default_suppressed(app_config->get("no_defaults") == "1"); try { @@ -1372,24 +1388,41 @@ void GUI_App::update_label_colours() tab->update_label_colours(); } +static bool is_focused(HWND hWnd) +{ + HWND hFocusedWnd = ::GetFocus(); + return hFocusedWnd && hWnd == hFocusedWnd; +} + void GUI_App::UpdateDarkUI(wxWindow* window, bool highlited/* = false*/, bool just_font/* = false*/) { #ifdef _WIN32 + bool is_focused_button = false; if (wxButton* btn = dynamic_cast<wxButton*>(window)) { if (!(btn->GetWindowStyle() & wxNO_BORDER)) { btn->SetWindowStyle(btn->GetWindowStyle() | wxNO_BORDER); highlited = true; } - // hovering for buttons + // button marking { - auto focus_button = [this, btn](const bool focus) { - btn->SetForegroundColour(focus ? m_color_hovered_btn_label : m_color_label_default); + auto mark_button = [this, btn, highlited](const bool mark) { + if (btn->GetLabel().IsEmpty()) + btn->SetBackgroundColour(mark ? m_color_selected_btn_bg : highlited ? m_color_highlight_default : m_color_window_default); + else + btn->SetForegroundColour(mark ? m_color_hovered_btn_label : m_color_label_default); btn->Refresh(); btn->Update(); }; - btn->Bind(wxEVT_ENTER_WINDOW, [focus_button](wxMouseEvent& event) { focus_button(true); event.Skip(); }); - btn->Bind(wxEVT_LEAVE_WINDOW, [focus_button](wxMouseEvent& event) { focus_button(false); event.Skip(); }); + // hovering + btn->Bind(wxEVT_ENTER_WINDOW, [mark_button](wxMouseEvent& event) { mark_button(true); event.Skip(); }); + btn->Bind(wxEVT_LEAVE_WINDOW, [mark_button, btn](wxMouseEvent& event) { mark_button(is_focused(btn->GetHWND())); event.Skip(); }); + // focusing + btn->Bind(wxEVT_SET_FOCUS, [mark_button](wxFocusEvent& event) { mark_button(true); event.Skip(); }); + btn->Bind(wxEVT_KILL_FOCUS, [mark_button](wxFocusEvent& event) { mark_button(false); event.Skip(); }); + + if (is_focused_button = is_focused(btn->GetHWND())) + mark_button(true); } } else if (wxTextCtrl* text = dynamic_cast<wxTextCtrl*>(window)) { @@ -1411,7 +1444,8 @@ void GUI_App::UpdateDarkUI(wxWindow* window, bool highlited/* = false*/, bool ju if (!just_font) window->SetBackgroundColour(highlited ? m_color_highlight_default : m_color_window_default); - window->SetForegroundColour(m_color_label_default); + if (!is_focused_button) + window->SetForegroundColour(m_color_label_default); #endif } @@ -1702,6 +1736,7 @@ void GUI_App::force_colors_update() if (WXHWND wxHWND = wxToolTip::GetToolTipCtrl()) NppDarkMode::SetDarkExplorerTheme((HWND)wxHWND); NppDarkMode::SetDarkTitleBar(mainframe->GetHWND()); + NppDarkMode::SetDarkTitleBar(mainframe->m_settings_dialog.GetHWND()); #endif //_MSW_DARK_MODE m_force_colors_update = true; } @@ -1718,9 +1753,18 @@ void GUI_App::update_ui_from_settings() m_force_colors_update = false; mainframe->force_color_changed(); mainframe->diff_dialog.force_color_changed(); + mainframe->preferences_dialog->force_color_changed(); mainframe->printhost_queue_dlg()->force_color_changed(); #ifdef _MSW_DARK_MODE update_scrolls(mainframe); + if (mainframe->is_dlg_layout()) { + // update for tabs bar + UpdateDarkUI(&mainframe->m_settings_dialog); + mainframe->m_settings_dialog.Fit(); + mainframe->m_settings_dialog.Refresh(); + // update scrollbars + update_scrolls(&mainframe->m_settings_dialog); + } #endif //_MSW_DARK_MODE } #endif @@ -2162,9 +2206,9 @@ void GUI_App::add_config_menu(wxMenuBar *menu) local_menu->Append(config_id_base + ConfigMenuLanguage, _L("&Language")); if (is_editor()) { local_menu->AppendSeparator(); - local_menu->Append(config_id_base + ConfigMenuFlashFirmware, _L("Flash printer &firmware"), _L("Upload a firmware image into an Arduino based printer")); + local_menu->Append(config_id_base + ConfigMenuFlashFirmware, _L("Flash Printer &Firmware"), _L("Upload a firmware image into an Arduino based printer")); // TODO: for when we're able to flash dictionaries - // local_menu->Append(config_id_base + FirmwareMenuDict, _L("Flash language file"), _L("Upload a language dictionary file into a Prusa printer")); + // local_menu->Append(config_id_base + FirmwareMenuDict, _L("Flash Language File"), _L("Upload a language dictionary file into a Prusa printer")); } local_menu->Bind(wxEVT_MENU, [this, config_id_base](wxEvent &event) { @@ -2230,40 +2274,7 @@ void GUI_App::add_config_menu(wxMenuBar *menu) break; case ConfigMenuPreferences: { - bool app_layout_changed = false; - { - // the dialog needs to be destroyed before the call to recreate_GUI() - // or sometimes the application crashes into wxDialogBase() destructor - // so we put it into an inner scope - PreferencesDialog dlg(mainframe); - dlg.ShowModal(); - app_layout_changed = dlg.settings_layout_changed(); - if (dlg.seq_top_layer_only_changed()) - this->plater_->refresh_print(); - - if (dlg.recreate_GUI()) { - recreate_GUI(_L("Restart application") + dots); - return; - } -#ifdef _WIN32 - if (is_editor()) { - if (app_config->get("associate_3mf") == "1") - associate_3mf_files(); - if (app_config->get("associate_stl") == "1") - associate_stl_files(); - } - else { - if (app_config->get("associate_gcode") == "1") - associate_gcode_files(); - } -#endif // _WIN32 - } - if (app_layout_changed) { - // hide full main_sizer for mainFrame - mainframe->GetSizer()->Show(false); - mainframe->update_layout(); - mainframe->select_tab(size_t(0)); - } + open_preferences(); break; } case ConfigMenuLanguage: @@ -2311,36 +2322,34 @@ void GUI_App::add_config_menu(wxMenuBar *menu) menu->Append(local_menu, _L("&Configuration")); } -void GUI_App::open_preferences(size_t open_on_tab, const std::string& highlight_option) +void GUI_App::open_preferences(const std::string& highlight_option /*= std::string()*/, const std::string& tab_name/*= std::string()*/) { - bool app_layout_changed = false; - { - // the dialog needs to be destroyed before the call to recreate_GUI() - // or sometimes the application crashes into wxDialogBase() destructor - // so we put it into an inner scope - PreferencesDialog dlg(mainframe, open_on_tab, highlight_option); - dlg.ShowModal(); - app_layout_changed = dlg.settings_layout_changed(); + mainframe->preferences_dialog->show(highlight_option, tab_name); + + if (mainframe->preferences_dialog->recreate_GUI()) + recreate_GUI(_L("Restart application") + dots); + #if ENABLE_GCODE_LINES_ID_IN_H_SLIDER - if (dlg.seq_top_layer_only_changed() || dlg.seq_seq_top_gcode_indices_changed()) + if (dlg.seq_top_layer_only_changed() || dlg.seq_seq_top_gcode_indices_changed()) #else - if (dlg.seq_top_layer_only_changed()) + if (mainframe->preferences_dialog->seq_top_layer_only_changed()) #endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER - this->plater_->refresh_print(); + this->plater_->refresh_print(); + #ifdef _WIN32 - if (is_editor()) { - if (app_config->get("associate_3mf") == "1") - associate_3mf_files(); - if (app_config->get("associate_stl") == "1") - associate_stl_files(); - } - else { - if (app_config->get("associate_gcode") == "1") - associate_gcode_files(); - } -#endif // _WIN32 + if (is_editor()) { + if (app_config->get("associate_3mf") == "1") + associate_3mf_files(); + if (app_config->get("associate_stl") == "1") + associate_stl_files(); } - if (app_layout_changed) { + else { + if (app_config->get("associate_gcode") == "1") + associate_gcode_files(); + } +#endif // _WIN32 + + if (mainframe->preferences_dialog->settings_layout_changed()) { // hide full main_sizer for mainFrame mainframe->GetSizer()->Show(false); mainframe->update_layout(); |