diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 02a19f51ce..213e638d44 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -714,9 +714,9 @@ void MainFrame::init_tabpanel() }); m_plater = new Plater(this, this); + wxGetApp().plater_ = m_plater; m_plater->Hide(); - wxGetApp().plater_ = m_plater; if (wxGetApp().is_editor()) create_preset_tabs(); diff --git a/src/slic3r/GUI/PresetArchiveDatabase.cpp b/src/slic3r/GUI/PresetArchiveDatabase.cpp index ddb697448c..b76d6bc802 100644 --- a/src/slic3r/GUI/PresetArchiveDatabase.cpp +++ b/src/slic3r/GUI/PresetArchiveDatabase.cpp @@ -182,12 +182,15 @@ std::string escape_path_by_element(const std::string& path_string) return ret_val; } -void add_authorization_header(Http& http) +bool add_authorization_header(Http& http) { + if (wxApp::GetInstance() == nullptr || ! GUI::wxGetApp().plater()) + return false; const std::string access_token = GUI::wxGetApp().plater()->get_user_account()->get_access_token(); if (!access_token.empty()) { http.header("Authorization", "Bearer " + access_token); } + return true; } } @@ -204,7 +207,8 @@ bool OnlineArchiveRepository::get_file_inner(const std::string& url, const fs::p tmp_path.string()); auto http = Http::get(url); - add_authorization_header(http); + if (!add_authorization_header(http)) + return false; http .timeout_max(30) .on_progress([](Http::Progress, bool& cancel) { @@ -881,7 +885,8 @@ bool sync_inner(std::string& manifest, PresetUpdaterUIStatus* ui_status) bool ret = false; std::string url = Utils::ServiceConfig::instance().preset_repo_repos_url(); auto http = Http::get(std::move(url)); - add_authorization_header(http); + if (!add_authorization_header(http)) + return false; http .timeout_max(30) .on_error([&](std::string body, std::string error, unsigned http_status) { diff --git a/src/slic3r/GUI/ProjectDirtyStateManager.cpp b/src/slic3r/GUI/ProjectDirtyStateManager.cpp index 23addccdf2..ee95e4ca50 100644 --- a/src/slic3r/GUI/ProjectDirtyStateManager.cpp +++ b/src/slic3r/GUI/ProjectDirtyStateManager.cpp @@ -46,10 +46,13 @@ void ProjectDirtyStateManager::update_from_presets() void ProjectDirtyStateManager::update_from_preview() { + if (wxApp::GetInstance() == nullptr || wxGetApp().plater() == nullptr) + return; const bool is_dirty = m_initial_custom_gcode_per_print_z != wxGetApp().model().custom_gcode_per_print_z; if (m_custom_gcode_per_print_z_dirty != is_dirty) { m_custom_gcode_per_print_z_dirty = is_dirty; - wxGetApp().mainframe->update_title(); + if (wxApp::GetInstance() != nullptr) + wxGetApp().mainframe->update_title(); } } diff --git a/src/slic3r/Utils/AppUpdater.cpp b/src/slic3r/Utils/AppUpdater.cpp index e71f6c1260..4c7976f5f3 100644 --- a/src/slic3r/Utils/AppUpdater.cpp +++ b/src/slic3r/Utils/AppUpdater.cpp @@ -49,7 +49,8 @@ namespace { BOOST_LOG_TRIVIAL(error) << full_message; wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_APP_DOWNLOAD_FAILED); evt->SetString(full_message); - GUI::wxGetApp().QueueEvent(evt); + if (wxApp::GetInstance() != nullptr) + GUI::wxGetApp().QueueEvent(evt); } return res; } @@ -87,7 +88,7 @@ namespace { } #else bool run_file(const boost::filesystem::path& path) - { + { return false; } @@ -101,7 +102,7 @@ namespace { } return std::string(); } -#endif // _WIN32 / __apple__ / else +#endif // _WIN32 / __apple__ / else } // namespace wxDEFINE_EVENT(EVT_SLIC3R_VERSION_ONLINE, wxCommandEvent); @@ -130,10 +131,10 @@ struct AppUpdater::priv { // gets version file via http void version_check(const std::string& version_check_url); #if 0 - // parsing of Prusaslicer.version2 + // parsing of Prusaslicer.version2 void parse_version_string_old(const std::string& body) const; #endif - // parses ini tree of version file, saves to m_online_version_data and queue event(s) to UI + // parses ini tree of version file, saves to m_online_version_data and queue event(s) to UI void parse_version_string(const std::string& body); // thread std::thread m_thread; @@ -161,13 +162,13 @@ AppUpdater::priv::priv() : #else , m_default_dest_folder (boost::filesystem::path(data_dir()) / "cache") #endif //_WIN32 -{ +{ boost::filesystem::path downloads_path = boost::filesystem::path(get_downloads_path()); if (!downloads_path.empty()) { m_default_dest_folder = std::move(downloads_path); } BOOST_LOG_TRIVIAL(trace) << "App updater default download path: " << m_default_dest_folder; - + } bool AppUpdater::priv::http_get_file(const std::string& url, size_t size_limit, std::function progress_fn, std::function complete_fn, std::string& error_message) const @@ -176,7 +177,7 @@ bool AppUpdater::priv::http_get_file(const std::string& url, size_t size_limit, Http::get(url) .size_limit(size_limit) .on_progress([&, progress_fn](Http::Progress progress, bool& cancel) { - // progress function returns true as success (to continue) + // progress function returns true as success (to continue) cancel = (m_cancel ? true : !progress_fn(std::move(progress))); if (cancel) { // Lets keep error_message empty here - if there is need to show error dialog, the message will be probably shown by whatever caused the cancel. @@ -196,7 +197,7 @@ bool AppUpdater::priv::http_get_file(const std::string& url, size_t size_limit, res = complete_fn(body, error_message); }) .perform_sync(); - + return res; } @@ -215,7 +216,8 @@ boost::filesystem::path AppUpdater::priv::download_file(const DownloadAppData& d BOOST_LOG_TRIVIAL(error) << message; wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_APP_DOWNLOAD_FAILED); evt->SetString(message); - GUI::wxGetApp().QueueEvent(evt); + if (wxApp::GetInstance() != nullptr) + GUI::wxGetApp().QueueEvent(evt); return boost::filesystem::path(); } @@ -229,43 +231,49 @@ boost::filesystem::path AppUpdater::priv::download_file(const DownloadAppData& d std::string line2 = GUI::format(_u8L("Can't create file at %1%"), tmp_path.string()); std::string message = GUI::format("%1%\n%2%", line1, line2); BOOST_LOG_TRIVIAL(error) << message; - wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_APP_DOWNLOAD_FAILED); - evt->SetString(message); - GUI::wxGetApp().QueueEvent(evt); + if (wxApp::GetInstance() != nullptr) { + wxCommandEvent *evt = new wxCommandEvent(EVT_SLIC3R_APP_DOWNLOAD_FAILED); + evt->SetString(message); + GUI::wxGetApp().QueueEvent(evt); + } return boost::filesystem::path(); } std::string error_message; - bool res = http_get_file(data.url, 256 * 1024 * 1024 + bool res = http_get_file(data.url, 256 * 1024 * 1024 // on_progress , [&last_gui_progress, expected_size](Http::Progress progress) { // size check if (progress.dltotal > 0 && progress.dltotal > expected_size) { std::string message = GUI::format("Downloading new %1% has failed. The file has incorrect file size. Aborting download.\nExpected size: %2%\nDownload size: %3%", SLIC3R_APP_NAME, expected_size, progress.dltotal); BOOST_LOG_TRIVIAL(error) << message; - wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_APP_DOWNLOAD_FAILED); - evt->SetString(message); - GUI::wxGetApp().QueueEvent(evt); - return false; - } else if (progress.dltotal > 0 && progress.dltotal < expected_size) { + if (wxApp::GetInstance() != nullptr) { + wxCommandEvent *evt = new wxCommandEvent(EVT_SLIC3R_APP_DOWNLOAD_FAILED); + evt->SetString(message); + GUI::wxGetApp().QueueEvent(evt); + } + return false; + } else if (progress.dltotal > 0 && progress.dltotal < expected_size) { // This is possible error, but we cannot know until the download is finished. Somehow the total size can grow during the download. BOOST_LOG_TRIVIAL(info) << GUI::format("Downloading new %1% has incorrect size. The download will continue. \nExpected size: %2%\nDownload size: %3%", SLIC3R_APP_NAME, expected_size, progress.dltotal); - } + } // progress event size_t gui_progress = progress.dltotal > 0 ? 100 * progress.dlnow / progress.dltotal : 0; BOOST_LOG_TRIVIAL(debug) << "App download " << gui_progress << "% " << progress.dlnow << " of " << progress.dltotal; if (last_gui_progress < gui_progress && (last_gui_progress != 0 || gui_progress != 100)) { last_gui_progress = gui_progress; - wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_APP_DOWNLOAD_PROGRESS); - evt->SetString(GUI::from_u8(std::to_string(gui_progress))); - GUI::wxGetApp().QueueEvent(evt); - } + if (wxApp::GetInstance() != nullptr) { + wxCommandEvent *evt = new wxCommandEvent(EVT_SLIC3R_APP_DOWNLOAD_PROGRESS); + evt->SetString(GUI::from_u8(std::to_string(gui_progress))); + GUI::wxGetApp().QueueEvent(evt); + } + } return true; } // on_complete , [&file, dest_path, tmp_path, expected_size](std::string body, std::string& error_message){ // Size check. Does always 1 char == 1 byte? - size_t body_size = body.size(); + size_t body_size = body.size(); if (body_size != expected_size) { error_message = GUI::format(_u8L("Downloaded file has wrong size. Expected size: %1% Downloaded size: %2%"), expected_size, body_size); return false; @@ -292,23 +300,28 @@ boost::filesystem::path AppUpdater::priv::download_file(const DownloadAppData& d if (!res) { if (m_cancel) { - BOOST_LOG_TRIVIAL(info) << error_message; - wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_APP_DOWNLOAD_FAILED); // FAILED with empty msg only closes progress notification - GUI::wxGetApp().QueueEvent(evt); - } else { - std::string message = (error_message.empty() + BOOST_LOG_TRIVIAL(info) << error_message; + if (wxApp::GetInstance() != nullptr) { + wxCommandEvent *evt = new wxCommandEvent(EVT_SLIC3R_APP_DOWNLOAD_FAILED + ); // FAILED with empty msg only closes progress notification + GUI::wxGetApp().QueueEvent(evt); + } + } else { + std::string message = (error_message.empty() ? std::string() : GUI::format(_u8L("Downloading new %1% has failed:\n%2%"), SLIC3R_APP_NAME, error_message)); - wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_APP_DOWNLOAD_FAILED); - if (!message.empty()) { - BOOST_LOG_TRIVIAL(error) << message; - evt->SetString(message); - } - GUI::wxGetApp().QueueEvent(evt); - } + if (wxApp::GetInstance() != nullptr) { + wxCommandEvent *evt = new wxCommandEvent(EVT_SLIC3R_APP_DOWNLOAD_FAILED); + if (!message.empty()) { + BOOST_LOG_TRIVIAL(error) << message; + evt->SetString(message); + } + GUI::wxGetApp().QueueEvent(evt); + } + } return boost::filesystem::path(); } - + return dest_path; } @@ -318,7 +331,7 @@ bool AppUpdater::priv::run_downloaded_file(boost::filesystem::path path) return run_file(path); } -void AppUpdater::priv::version_check(const std::string& version_check_url) +void AppUpdater::priv::version_check(const std::string& version_check_url) { assert(!version_check_url.empty()); std::string error_message; @@ -336,7 +349,7 @@ void AppUpdater::priv::version_check(const std::string& version_check_url) if (!res) { std::string message = GUI::format("Downloading %1% version file has failed:\n%2%", SLIC3R_APP_NAME, error_message); BOOST_LOG_TRIVIAL(error) << message; - if (m_triggered_by_user) { + if (m_triggered_by_user && wxApp::GetInstance() != nullptr) { wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_APP_DOWNLOAD_FAILED); evt->SetString(message); GUI::wxGetApp().QueueEvent(evt); @@ -356,10 +369,12 @@ void AppUpdater::priv::parse_version_string(const std::string& body) BOOST_LOG_TRIVIAL(error) << "Could not find property tree in version file. Checking for application update has failed."; // Lets send event with current version, this way if user triggered this check, it will notify him about no new version online. std::string version = Semver().to_string(); - wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_VERSION_ONLINE); - evt->SetString(GUI::from_u8(version)); - GUI::wxGetApp().QueueEvent(evt); - return; + if (wxApp::GetInstance() != nullptr) { + wxCommandEvent *evt = new wxCommandEvent(EVT_SLIC3R_VERSION_ONLINE); + evt->SetString(GUI::from_u8(version)); + GUI::wxGetApp().QueueEvent(evt); + } + return; } std::string tree_string = body.substr(start); boost::property_tree::ptree tree; @@ -378,7 +393,7 @@ void AppUpdater::priv::parse_version_string(const std::string& body) std::string section_name = section.first; // online release version info - if (section_name == + if (section_name == #ifdef _WIN32 "release:win64" #elif __APPLE__ @@ -444,7 +459,7 @@ void AppUpdater::priv::parse_version_string(const std::string& body) } } // send prerelease version to UI layer - if (recent_version) { + if (recent_version && wxApp::GetInstance() != nullptr) { BOOST_LOG_TRIVIAL(info) << format("Got %1% online version: `%2%`. Sending to GUI thread...", SLIC3R_APP_NAME, version_string); wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_EXPERIMENTAL_VERSION_ONLINE); evt->SetString(GUI::from_u8(version_string)); @@ -459,9 +474,11 @@ void AppUpdater::priv::parse_version_string(const std::string& body) // send std::string version = new_data.version.get().to_string(); BOOST_LOG_TRIVIAL(info) << format("Got %1% online version: `%2%`. Sending to GUI thread...", SLIC3R_APP_NAME, version); - wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_VERSION_ONLINE); - evt->SetString(GUI::from_u8(version)); - GUI::wxGetApp().QueueEvent(evt); + if (wxApp::GetInstance() != nullptr) { + wxCommandEvent *evt = new wxCommandEvent(EVT_SLIC3R_VERSION_ONLINE); + evt->SetString(GUI::from_u8(version)); + GUI::wxGetApp().QueueEvent(evt); + } } #if 0 //lm:is this meant to be ressurected? //dk: it is code that parses PrusaSlicer.version2 in 2.4.0, It was deleted from PresetUpdater.cpp and I would keep it here for possible reference. @@ -481,9 +498,11 @@ void AppUpdater::priv::parse_version_string_old(const std::string& body) const return; } BOOST_LOG_TRIVIAL(info) << format("Got %1% online version: `%2%`. Sending to GUI thread...", SLIC3R_APP_NAME, version); - wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_VERSION_ONLINE); - evt->SetString(GUI::from_u8(version)); - GUI::wxGetApp().QueueEvent(evt); + if (wxApp::GetInstance() != nullptr) { + wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_VERSION_ONLINE); + evt->SetString(GUI::from_u8(version)); + GUI::wxGetApp().QueueEvent(evt); + } // alpha / beta version std::vector prerelease_versions; @@ -525,7 +544,7 @@ void AppUpdater::priv::parse_version_string_old(const std::string& body) const version = ver_string; } } - if (recent_version) { + if (recent_version && wxApp::GetInstance() != nullptr) { BOOST_LOG_TRIVIAL(info) << format("Got %1% online version: `%2%`. Sending to GUI thread...", SLIC3R_APP_NAME, version); wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_EXPERIMENTAL_VERSION_ONLINE); evt->SetString(GUI::from_u8(version)); diff --git a/src/slic3r/Utils/PresetUpdater.cpp b/src/slic3r/Utils/PresetUpdater.cpp index fcfc824305..f23ac74b11 100644 --- a/src/slic3r/Utils/PresetUpdater.cpp +++ b/src/slic3r/Utils/PresetUpdater.cpp @@ -1186,6 +1186,11 @@ PresetUpdater::UpdateResult PresetUpdater::config_update(const Semver& old_slic3 } } + if (!wxApp::GetInstance() || ! GUI::wxGetApp().plater()) { + // The main thread might have start killing the UI. + return R_NOOP; + } + // regular update if (params == UpdateParams::SHOW_NOTIFICATION) { p->set_waiting_updates(updates);