Merge branch 'dk_ys_memory_leaks'

This commit is contained in:
Lukas Matena 2025-02-06 13:18:55 +01:00
commit 88e9b91def
8 changed files with 85 additions and 62 deletions

View File

@ -694,11 +694,11 @@ void Plater::priv::init()
hsizer->Add(sidebar, 0, wxEXPAND | wxLEFT | wxRIGHT, 0); hsizer->Add(sidebar, 0, wxEXPAND | wxLEFT | wxRIGHT, 0);
q->SetSizer(hsizer); q->SetSizer(hsizer);
menus.init(q);
// Events:
if (wxGetApp().is_editor()) { if (wxGetApp().is_editor()) {
menus.init(q);
// Events:
// Preset change event // Preset change event
this->q->Bind(EVT_OBJ_LIST_OBJECT_SELECT, [this](wxEvent&) { priv::selection_changed(); }); this->q->Bind(EVT_OBJ_LIST_OBJECT_SELECT, [this](wxEvent&) { priv::selection_changed(); });
this->q->Bind(EVT_SCHEDULE_BACKGROUND_PROCESS, [this](SimpleEvent&) { this->schedule_background_process(); }); this->q->Bind(EVT_SCHEDULE_BACKGROUND_PROCESS, [this](SimpleEvent&) { this->schedule_background_process(); });

View File

@ -5507,9 +5507,9 @@ void TabSLAMaterial::build_tilt_group(Slic3r::GUI::PageShp page)
// TRN: 'Profile' in this context denotes a group of parameters used to configure // TRN: 'Profile' in this context denotes a group of parameters used to configure
// layer separation procedure for SLA printers. // layer separation procedure for SLA printers.
auto optgroup = page->new_optgroup(L("Profile settings")); auto optgroup = page->new_optgroup(L("Profile settings"));
optgroup->on_change = [this, optgroup](const t_config_option_key& key, boost::any value) optgroup->on_change = [this](const t_config_option_key& key, boost::any value)
{ {
if (key.find_first_of("use_tilt") == 0) if (key.find("use_tilt") == 0)
toggle_tilt_options(key == "use_tilt#0"); toggle_tilt_options(key == "use_tilt#0");
update_dirty(); update_dirty();

View File

@ -106,7 +106,7 @@ void TopBarMenus::UpdateAccountMenu()
void TopBarMenus::RemoveHideLoginItem() void TopBarMenus::RemoveHideLoginItem()
{ {
if (m_hide_login_item) if (m_hide_login_item)
account.Remove(m_hide_login_item); account.Destroy(m_hide_login_item);
} }
void TopBarMenus::Popup(TopBarItemsCtrl* popup_ctrl, wxMenu* menu, wxPoint pos) void TopBarMenus::Popup(TopBarItemsCtrl* popup_ctrl, wxMenu* menu, wxPoint pos)

View File

@ -177,8 +177,8 @@ UserAccountCommunication::UserAccountCommunication(wxEvtHandler* evt_handler, Ap
: wxEvtHandler() : wxEvtHandler()
, m_evt_handler(evt_handler) , m_evt_handler(evt_handler)
, m_app_config(app_config) , m_app_config(app_config)
, m_polling_timer(new wxTimer(this)) , m_polling_timer(std::make_unique<wxTimer>(this))
, m_token_timer(new wxTimer(this)) , m_token_timer(std::make_unique<wxTimer>(this))
{ {
Bind(wxEVT_TIMER, &UserAccountCommunication::on_token_timer, this, m_token_timer->GetId()); Bind(wxEVT_TIMER, &UserAccountCommunication::on_token_timer, this, m_token_timer->GetId());
Bind(wxEVT_TIMER, &UserAccountCommunication::on_polling_timer, this, m_polling_timer->GetId()); Bind(wxEVT_TIMER, &UserAccountCommunication::on_polling_timer, this, m_polling_timer->GetId());
@ -226,6 +226,7 @@ UserAccountCommunication::~UserAccountCommunication()
{ {
m_token_timer->Stop(); m_token_timer->Stop();
m_polling_timer->Stop(); m_polling_timer->Stop();
if (m_thread.joinable()) { if (m_thread.joinable()) {
// Stop the worker thread, if running. // Stop the worker thread, if running.
{ {

View File

@ -86,7 +86,7 @@ private:
bool m_thread_stop { false }; bool m_thread_stop { false };
bool m_thread_wakeup{ false }; bool m_thread_wakeup{ false };
bool m_window_is_active{ true }; bool m_window_is_active{ true };
wxTimer* m_polling_timer; std::unique_ptr<wxTimer> m_polling_timer;
std::string m_code_verifier; std::string m_code_verifier;
wxEvtHandler* m_evt_handler; wxEvtHandler* m_evt_handler;
@ -95,7 +95,7 @@ private:
std::string m_username; std::string m_username;
bool m_remember_session { true }; // if default is true, on every login Remember me will be checked. bool m_remember_session { true }; // if default is true, on every login Remember me will be checked.
wxTimer* m_token_timer; std::unique_ptr<wxTimer> m_token_timer;
std::time_t m_next_token_refresh_at{0}; std::time_t m_next_token_refresh_at{0};
void wakeup_session_thread(); void wakeup_session_thread();

View File

@ -117,6 +117,10 @@ wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const
entry->SetMenuItem(item); entry->SetMenuItem(item);
accelerator_entries_cache().push_back(entry); accelerator_entries_cache().push_back(entry);
} }
else {
delete entry;
entry = nullptr;
}
} }
#endif #endif

View File

@ -19,6 +19,7 @@ wxDEFINE_EVENT(EVT_CONFIG_UPDATER_SYNC_DONE, wxCommandEvent);
PresetUpdaterWrapper::PresetUpdaterWrapper() PresetUpdaterWrapper::PresetUpdaterWrapper()
: m_preset_updater(std::make_unique<PresetUpdater>()) : m_preset_updater(std::make_unique<PresetUpdater>())
, m_preset_archive_database(std::make_unique<PresetArchiveDatabase>()) , m_preset_archive_database(std::make_unique<PresetArchiveDatabase>())
, m_ui_status(std::make_unique<PresetUpdaterUIStatus>())
{ {
} }
PresetUpdaterWrapper::~PresetUpdaterWrapper() PresetUpdaterWrapper::~PresetUpdaterWrapper()
@ -35,27 +36,28 @@ bool PresetUpdaterWrapper::wizard_sync(const PresetBundle* preset_bundle, const
assert(!m_modal_thread.joinable()); assert(!m_modal_thread.joinable());
// Cancel sync before starting wizard to prevent two downloads at same time. // Cancel sync before starting wizard to prevent two downloads at same time.
cancel_worker_thread(); cancel_worker_thread();
PresetUpdaterUIStatus* ui_status = new PresetUpdaterUIStatus(PresetUpdaterUIStatus::PresetUpdaterRetryPolicy::PURP_5_TRIES);
Slic3r::ScopeGuard sg([ui_status]() { delete ui_status; }); m_ui_status->reset(PresetUpdaterUIStatus::PresetUpdaterRetryPolicy::PURP_5_TRIES);
GUI::ProgressUpdaterDialog* dialog = new GUI::ProgressUpdaterDialog(ui_status, parent, headline);
ui_status->set_handler(dialog); GUI::ProgressUpdaterDialog* dialog = new GUI::ProgressUpdaterDialog(m_ui_status.get(), parent, headline);
m_ui_status->set_handler(dialog);
VendorMap vendors_copy = preset_bundle->vendors; VendorMap vendors_copy = preset_bundle->vendors;
auto worker_body = [ui_status, this, vendors_copy, full_sync]() auto worker_body = [this, vendors_copy, full_sync]()
{ {
if (!m_preset_archive_database->sync_blocking(ui_status)) { if (!m_preset_archive_database->sync_blocking(m_ui_status.get())) {
ui_status->end(); m_ui_status->end();
return; return;
} }
if (ui_status->get_canceled()) { ui_status->end(); return; } if (m_ui_status->get_canceled()) { m_ui_status->end(); return; }
if (full_sync) { if (full_sync) {
// Since there might be new repos, we need to sync preset updater // Since there might be new repos, we need to sync preset updater
const SharedArchiveRepositoryVector &repos = m_preset_archive_database->get_selected_archive_repositories(); const SharedArchiveRepositoryVector &repos = m_preset_archive_database->get_selected_archive_repositories();
m_preset_updater->sync_blocking(vendors_copy, repos, ui_status); m_preset_updater->sync_blocking(vendors_copy, repos, m_ui_status.get());
if (ui_status->get_canceled()) { ui_status->end(); return; } if (m_ui_status->get_canceled()) { m_ui_status->end(); return; }
m_preset_updater->update_index_db(); m_preset_updater->update_index_db();
} }
ui_status->end(); m_ui_status->end();
}; };
m_modal_thread = std::thread(worker_body); m_modal_thread = std::thread(worker_body);
// We need to call ShowModal here instead of prompting it from event callback. // We need to call ShowModal here instead of prompting it from event callback.
@ -65,28 +67,28 @@ bool PresetUpdaterWrapper::wizard_sync(const PresetBundle* preset_bundle, const
m_modal_thread.join(); m_modal_thread.join();
parent->RemoveChild(dialog); parent->RemoveChild(dialog);
dialog->Destroy(); dialog->Destroy();
ui_status->set_handler(nullptr); m_ui_status->set_handler(nullptr);
// Only now it is possible to work with ui_status, that was previously used in worker thread. // Only now it is possible to work with ui_status, that was previously used in worker thread.
if (std::string s = ui_status->get_error(); !s.empty()) { if (std::string s = m_ui_status->get_error(); !s.empty()) {
std::string err_text = GUI::format(_u8L("Failed to download %1%"), ui_status->get_target()); std::string err_text = GUI::format(_u8L("Failed to download %1%"), m_ui_status->get_target());
GUI::ErrorDialog err_msg(nullptr, err_text + "\n\n" + s, false); GUI::ErrorDialog err_msg(nullptr, err_text + "\n\n" + s, false);
err_msg.ShowModal(); err_msg.ShowModal();
return false; return false;
} }
// Should m_preset_updater->config_update run even if there is cancel? // Should m_preset_updater->config_update run even if there is cancel?
if (ui_status->get_canceled() /*&& !full_sync*/) { if (m_ui_status->get_canceled() /*&& !full_sync*/) {
return false; return false;
} }
// Offer update installation. // Offer update installation.
if (full_sync) { if (full_sync) {
const SharedArchiveRepositoryVector &repos = m_preset_archive_database->get_selected_archive_repositories(); const SharedArchiveRepositoryVector &repos = m_preset_archive_database->get_selected_archive_repositories();
m_preset_updater->config_update(old_slic3r_version, PresetUpdater::UpdateParams::SHOW_TEXT_BOX_YES_NO, repos, ui_status); m_preset_updater->config_update(old_slic3r_version, PresetUpdater::UpdateParams::SHOW_TEXT_BOX_YES_NO, repos, m_ui_status.get());
} }
bool res = !ui_status->get_canceled(); bool res = !m_ui_status->get_canceled();
return res; return res;
} }
@ -94,28 +96,35 @@ PresetUpdater::UpdateResult PresetUpdaterWrapper::check_updates_on_user_request(
{ {
assert(!m_modal_thread.joinable()); assert(!m_modal_thread.joinable());
cancel_worker_thread(); cancel_worker_thread();
PresetUpdaterUIStatus* ui_status = new PresetUpdaterUIStatus(PresetUpdaterUIStatus::PresetUpdaterRetryPolicy::PURP_5_TRIES);
Slic3r::ScopeGuard sg([ui_status]() { delete ui_status; }); m_ui_status->reset(PresetUpdaterUIStatus::PresetUpdaterRetryPolicy::PURP_5_TRIES);
// TRN: Headline of Progress dialog // TRN: Headline of Progress dialog
GUI::ProgressUpdaterDialog* dialog = new GUI::ProgressUpdaterDialog(ui_status, parent, _L("Checking for Configuration Updates")); GUI::ProgressUpdaterDialog* dialog = new GUI::ProgressUpdaterDialog(m_ui_status.get(), parent, _L("Checking for Configuration Updates"));
ui_status->set_handler(dialog); m_ui_status->set_handler(dialog);
VendorMap vendors_copy = preset_bundle->vendors; VendorMap vendors_copy = preset_bundle->vendors;
std::string failed_paths; std::string failed_paths;
PresetUpdater::UpdateResult updater_result = PresetUpdater::UpdateResult::R_ALL_CANCELED; PresetUpdater::UpdateResult updater_result = PresetUpdater::UpdateResult::R_ALL_CANCELED;
auto worker_body = [ui_status, this, vendors_copy, &failed_paths]() auto worker_body = [this, vendors_copy, &failed_paths]()
{ {
if (!m_preset_archive_database->sync_blocking(ui_status)) { if (!m_preset_archive_database->sync_blocking(m_ui_status.get())) {
ui_status->end(); m_ui_status->end();
return;
}
if (m_ui_status->get_canceled()) {
m_ui_status->end();
return; return;
} }
if (ui_status->get_canceled()) { ui_status->end(); return; }
m_preset_archive_database->extract_archives_with_check(failed_paths); m_preset_archive_database->extract_archives_with_check(failed_paths);
const SharedArchiveRepositoryVector &repos = m_preset_archive_database->get_selected_archive_repositories(); const SharedArchiveRepositoryVector &repos = m_preset_archive_database->get_selected_archive_repositories();
m_preset_updater->sync_blocking(vendors_copy, repos, ui_status); m_preset_updater->sync_blocking(vendors_copy, repos, m_ui_status.get());
if (ui_status->get_canceled()) { ui_status->end(); return; } if (m_ui_status->get_canceled()) {
m_ui_status->end();
return;
}
m_preset_updater->update_index_db(); m_preset_updater->update_index_db();
ui_status->end(); m_ui_status->end();
}; };
m_modal_thread = std::thread(worker_body); m_modal_thread = std::thread(worker_body);
@ -126,18 +135,18 @@ PresetUpdater::UpdateResult PresetUpdaterWrapper::check_updates_on_user_request(
m_modal_thread.join(); m_modal_thread.join();
parent->RemoveChild(dialog); parent->RemoveChild(dialog);
dialog->Destroy(); dialog->Destroy();
ui_status->set_handler(nullptr); m_ui_status->set_handler(nullptr);
// Only now it is possible to work with ui_status, that was previously used in worker thread. // Only now it is possible to work with ui_status, that was previously used in worker thread.
if (std::string s = ui_status->get_error(); !s.empty()) { if (std::string s = m_ui_status->get_error(); !s.empty()) {
std::string err_text = GUI::format(_u8L("Failed to download %1%"), ui_status->get_target()); std::string err_text = GUI::format(_u8L("Failed to download %1%"), m_ui_status->get_target());
GUI::ErrorDialog err_msg(nullptr, s, false); GUI::ErrorDialog err_msg(nullptr, s, false);
err_msg.ShowModal(); err_msg.ShowModal();
return PresetUpdater::UpdateResult::R_ALL_CANCELED; return PresetUpdater::UpdateResult::R_ALL_CANCELED;
} }
if (ui_status->get_canceled()) { if (m_ui_status->get_canceled()) {
return PresetUpdater::UpdateResult::R_ALL_CANCELED; return PresetUpdater::UpdateResult::R_ALL_CANCELED;
} }
@ -150,7 +159,7 @@ PresetUpdater::UpdateResult PresetUpdaterWrapper::check_updates_on_user_request(
err_msg.ShowModal(); err_msg.ShowModal();
} }
// preset_updater::config_update does show wxDialog // preset_updater::config_update does show wxDialog
updater_result = m_preset_updater->config_update(old_slic3r_version, PresetUpdater::UpdateParams::SHOW_TEXT_BOX, m_preset_archive_database->get_selected_archive_repositories(), ui_status); updater_result = m_preset_updater->config_update(old_slic3r_version, PresetUpdater::UpdateParams::SHOW_TEXT_BOX, m_preset_archive_database->get_selected_archive_repositories(), m_ui_status.get());
return updater_result; return updater_result;
} }
@ -159,10 +168,11 @@ PresetUpdater::UpdateResult PresetUpdaterWrapper::check_updates_on_startup(const
if (m_modal_thread.joinable()) { if (m_modal_thread.joinable()) {
return PresetUpdater::UpdateResult::R_ALL_CANCELED; return PresetUpdater::UpdateResult::R_ALL_CANCELED;
} }
PresetUpdaterUIStatus ui_status(PresetUpdaterUIStatus::PresetUpdaterRetryPolicy::PURP_NO_RETRY); m_ui_status->reset(PresetUpdaterUIStatus::PresetUpdaterRetryPolicy::PURP_NO_RETRY);
// preset_updater::config_update does show wxDialog // preset_updater::config_update does show wxDialog
m_preset_updater->update_index_db(); m_preset_updater->update_index_db();
return m_preset_updater->config_update(old_slic3r_version, PresetUpdater::UpdateParams::SHOW_NOTIFICATION, m_preset_archive_database->get_selected_archive_repositories(), &ui_status); return m_preset_updater->config_update(old_slic3r_version, PresetUpdater::UpdateParams::SHOW_NOTIFICATION, m_preset_archive_database->get_selected_archive_repositories(), m_ui_status.get());
} }
void PresetUpdaterWrapper::on_update_notification_confirm() void PresetUpdaterWrapper::on_update_notification_confirm()
@ -170,29 +180,30 @@ void PresetUpdaterWrapper::on_update_notification_confirm()
if (m_modal_thread.joinable()) { if (m_modal_thread.joinable()) {
return; return;
} }
PresetUpdaterUIStatus ui_status(PresetUpdaterUIStatus::PresetUpdaterRetryPolicy::PURP_NO_RETRY); m_ui_status->reset(PresetUpdaterUIStatus::PresetUpdaterRetryPolicy::PURP_NO_RETRY);
// preset_updater::on_update_notification_confirm does show wxDialog // preset_updater::on_update_notification_confirm does show wxDialog
const SharedArchiveRepositoryVector &repos = m_preset_archive_database->get_selected_archive_repositories(); const SharedArchiveRepositoryVector &repos = m_preset_archive_database->get_selected_archive_repositories();
m_preset_updater->on_update_notification_confirm(repos, &ui_status); m_preset_updater->on_update_notification_confirm(repos, m_ui_status.get());
} }
bool PresetUpdaterWrapper::install_bundles_rsrc_or_cache_vendor(std::vector<std::string> bundles, bool snapshot/* = true*/) const bool PresetUpdaterWrapper::install_bundles_rsrc_or_cache_vendor(std::vector<std::string> bundles, bool snapshot/* = true*/) const
{ {
PresetUpdaterUIStatus ui_status(PresetUpdaterUIStatus::PresetUpdaterRetryPolicy::PURP_NO_RETRY); m_ui_status->reset(PresetUpdaterUIStatus::PresetUpdaterRetryPolicy::PURP_NO_RETRY);
const SharedArchiveRepositoryVector &repos = m_preset_archive_database->get_selected_archive_repositories(); const SharedArchiveRepositoryVector &repos = m_preset_archive_database->get_selected_archive_repositories();
return m_preset_updater->install_bundles_rsrc_or_cache_vendor(bundles, repos, &ui_status, snapshot); return m_preset_updater->install_bundles_rsrc_or_cache_vendor(bundles, repos, m_ui_status.get(), snapshot);
} }
void PresetUpdaterWrapper::sync_preset_updater(wxEvtHandler* end_evt_handler, const PresetBundle* preset_bundle) void PresetUpdaterWrapper::sync_preset_updater(wxEvtHandler* end_evt_handler, const PresetBundle* preset_bundle)
{ {
cancel_worker_thread(); cancel_worker_thread();
m_ui_status = new PresetUpdaterUIStatus(PresetUpdaterUIStatus::PresetUpdaterRetryPolicy::PURP_NO_RETRY); m_ui_status->reset(PresetUpdaterUIStatus::PresetUpdaterRetryPolicy::PURP_NO_RETRY);
VendorMap vendors_copy = preset_bundle->vendors; VendorMap vendors_copy = preset_bundle->vendors;
auto worker_body = [ this, vendors_copy, end_evt_handler]() auto worker_body = [ this, vendors_copy, end_evt_handler]()
{ {
const SharedArchiveRepositoryVector &repos = m_preset_archive_database->get_selected_archive_repositories(); const SharedArchiveRepositoryVector &repos = m_preset_archive_database->get_selected_archive_repositories();
m_preset_updater->sync_blocking(vendors_copy, repos, this->m_ui_status); m_preset_updater->sync_blocking(vendors_copy, repos, m_ui_status.get());
if (this->m_ui_status->get_canceled()) { return; } if (this->m_ui_status->get_canceled()) { return; }
wxCommandEvent* evt = new wxCommandEvent(EVT_CONFIG_UPDATER_SYNC_DONE); wxCommandEvent* evt = new wxCommandEvent(EVT_CONFIG_UPDATER_SYNC_DONE);
wxQueueEvent(end_evt_handler, evt); wxQueueEvent(end_evt_handler, evt);
@ -209,11 +220,6 @@ void PresetUpdaterWrapper::cancel_worker_thread()
} else assert(false); } else assert(false);
m_worker_thread.join(); m_worker_thread.join();
if (m_ui_status) {
delete m_ui_status;
m_ui_status = nullptr;
}
} }
} }
@ -221,7 +227,11 @@ const std::map<PresetUpdaterUIStatus::PresetUpdaterRetryPolicy, HttpRetryOpt> Pr
{PresetUpdaterUIStatus::PresetUpdaterRetryPolicy::PURP_5_TRIES, {500ms, 5s, 4}}, {PresetUpdaterUIStatus::PresetUpdaterRetryPolicy::PURP_5_TRIES, {500ms, 5s, 4}},
{PresetUpdaterUIStatus::PresetUpdaterRetryPolicy::PURP_NO_RETRY, {0ms}} {PresetUpdaterUIStatus::PresetUpdaterRetryPolicy::PURP_NO_RETRY, {0ms}}
}; };
PresetUpdaterUIStatus::PresetUpdaterUIStatus(PresetUpdaterUIStatus::PresetUpdaterRetryPolicy policy) PresetUpdaterUIStatus::PresetUpdaterUIStatus()
{
}
void PresetUpdaterUIStatus::reset(PresetUpdaterUIStatus::PresetUpdaterRetryPolicy policy)
{ {
if (auto it = policy_map.find(policy); it != policy_map.end()) { if (auto it = policy_map.find(policy); it != policy_map.end()) {
m_retry_policy = it->second; m_retry_policy = it->second;
@ -229,7 +239,13 @@ PresetUpdaterUIStatus::PresetUpdaterUIStatus(PresetUpdaterUIStatus::PresetUpdate
assert(false); assert(false);
m_retry_policy = {0ms}; m_retry_policy = {0ms};
} }
m_canceled = false;
m_evt_handler = nullptr;
m_error_msg.clear();
m_target.clear();
} }
bool PresetUpdaterUIStatus::on_attempt(int attempt, unsigned delay) bool PresetUpdaterUIStatus::on_attempt(int attempt, unsigned delay)
{ {
if (attempt == 1) { if (attempt == 1) {

View File

@ -40,10 +40,12 @@ public:
PURP_NO_RETRY, PURP_NO_RETRY,
}; };
// called from PresetUpdaterWrapper // called from PresetUpdaterWrapper
PresetUpdaterUIStatus(PresetUpdaterUIStatus::PresetUpdaterRetryPolicy policy); PresetUpdaterUIStatus();
~PresetUpdaterUIStatus(){} ~PresetUpdaterUIStatus(){}
void set_handler(wxEvtHandler* evt_handler) {m_evt_handler = evt_handler;} void set_handler(wxEvtHandler* evt_handler) {m_evt_handler = evt_handler;}
void reset(PresetUpdaterUIStatus::PresetUpdaterRetryPolicy policy);
// called from worker thread // called from worker thread
bool on_attempt(int attempt, unsigned delay); bool on_attempt(int attempt, unsigned delay);
void set_target(const std::string& target); void set_target(const std::string& target);
@ -152,7 +154,7 @@ private:
// m_worker_thread runs on background while m_modal_thread runs only when modal window exists. // m_worker_thread runs on background while m_modal_thread runs only when modal window exists.
std::thread m_worker_thread; std::thread m_worker_thread;
PresetUpdaterUIStatus* m_ui_status {nullptr}; std::unique_ptr<PresetUpdaterUIStatus> m_ui_status;
std::thread m_modal_thread; std::thread m_modal_thread;
}; };