mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-08-30 21:36:57 +00:00
Reset device selection on agent swap or unload (#124)
set_live_printer_agent centralizes the swap: deselect the machine, clear stale sidebar state and the previous agent's Other Devices, then install the new agent (or null when its provider vanished). Plugin load/unload callbacks refresh the dropdown and re-run agent selection. load_last_machine no longer falls back to the first available machine.
This commit is contained in:
@@ -496,6 +496,26 @@ namespace Slic3r
|
|||||||
OnSelectedMachineChanged(previous_selected_machine, selected_machine);
|
OnSelectedMachineChanged(previous_selected_machine, selected_machine);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DeviceManager::clear_other_devices()
|
||||||
|
{
|
||||||
|
// why: on agent swap, keep "My Devices" but drop the transient "Other Devices"
|
||||||
|
// Those belong to the previous agent's network scan; the new agent's start_discovery re-populates its own.
|
||||||
|
const auto my = get_my_machine_list();
|
||||||
|
for (auto it = localMachineList.begin(); it != localMachineList.end();)
|
||||||
|
{
|
||||||
|
if (my.find(it->first) == my.end())
|
||||||
|
{
|
||||||
|
// not a "My Device" -> an "Other Device"
|
||||||
|
delete it->second;
|
||||||
|
it = localMachineList.erase(it);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool DeviceManager::set_selected_machine(std::string dev_id)
|
bool DeviceManager::set_selected_machine(std::string dev_id)
|
||||||
{
|
{
|
||||||
BOOST_LOG_TRIVIAL(info) << "set_selected_machine=" << dev_id
|
BOOST_LOG_TRIVIAL(info) << "set_selected_machine=" << dev_id
|
||||||
@@ -558,7 +578,6 @@ namespace Slic3r
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Slic3r::GUI::wxGetApp().reset_unsigned_plugin_warning();
|
|
||||||
if (m_agent)
|
if (m_agent)
|
||||||
{
|
{
|
||||||
if (it->second->connection_type() != "lan" || it->second->connection_type().empty())
|
if (it->second->connection_type() != "lan" || it->second->connection_type().empty())
|
||||||
@@ -592,7 +611,6 @@ namespace Slic3r
|
|||||||
}
|
}
|
||||||
|
|
||||||
selected_machine = dev_id;
|
selected_machine = dev_id;
|
||||||
record_user_last_machine(selected_machine);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -851,44 +869,26 @@ namespace Slic3r
|
|||||||
int result = m_agent->get_user_print_info(&http_code, &body, provider);
|
int result = m_agent->get_user_print_info(&http_code, &body, provider);
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
{
|
{
|
||||||
parse_user_print_info(body);
|
// parse_user_print_info and on_machine_alive (SSDP for discovery) both mutate the same userMachineList map.
|
||||||
|
// on_machine_alive mutates the map on the UI thread, do the same for parse_user_print_info.
|
||||||
|
Slic3r::GUI::wxGetApp().CallAfter([this, body]() { parse_user_print_info(body); });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceManager::record_user_last_machine(const std::string& dev_id)
|
|
||||||
{
|
|
||||||
if (Slic3r::GUI::wxGetApp().app_config) {
|
|
||||||
Slic3r::GUI::wxGetApp().app_config->set("user_last_selected_machine", dev_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string DeviceManager::get_user_last_machine() const
|
|
||||||
{
|
|
||||||
if (Slic3r::GUI::wxGetApp().app_config) {
|
|
||||||
const auto& user_last_machine = Slic3r::GUI::wxGetApp().app_config->get("user_last_selected_machine");
|
|
||||||
if (!user_last_machine.empty()) {
|
|
||||||
return user_last_machine;
|
|
||||||
} else if (m_agent) {
|
|
||||||
return m_agent->get_user_selected_machine();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceManager::load_last_machine()
|
void DeviceManager::load_last_machine()
|
||||||
{
|
{
|
||||||
if (userMachineList.empty()) return;
|
// Get all available machines, include cloud machines and lan machines that have access right
|
||||||
else if (userMachineList.size() == 1) {
|
auto all_machines = get_my_machine_list();
|
||||||
this->set_selected_machine(userMachineList.begin()->second->get_dev_id());
|
if (all_machines.empty())
|
||||||
} else {
|
return;
|
||||||
const auto& last_monitor_machine = get_user_last_machine();
|
|
||||||
if (userMachineList.find(last_monitor_machine) != userMachineList.end()) {
|
// Reconnect the machine the user last selected, if it's still available.
|
||||||
set_selected_machine(last_monitor_machine);
|
// why: no first-available fallback - auto-connecting an arbitrary machine
|
||||||
} else {
|
// fights the agent-swap reset, which intentionally leaves nothing selected.
|
||||||
this->set_selected_machine(userMachineList.begin()->second->get_dev_id());
|
const std::string last_monitor_machine = m_agent ? m_agent->get_user_selected_machine() : "";
|
||||||
}
|
const auto last_machine = all_machines.find(last_monitor_machine);
|
||||||
}
|
if (last_machine != all_machines.end())
|
||||||
|
this->set_selected_machine(last_machine->second->get_dev_id());
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceManager::OnMachineBindStateChanged(MachineObject* obj, const std::string& new_state)
|
void DeviceManager::OnMachineBindStateChanged(MachineObject* obj, const std::string& new_state)
|
||||||
|
|||||||
@@ -48,8 +48,9 @@ public:
|
|||||||
MachineObject* get_selected_machine();
|
MachineObject* get_selected_machine();
|
||||||
bool set_selected_machine(std::string dev_id);
|
bool set_selected_machine(std::string dev_id);
|
||||||
|
|
||||||
void record_user_last_machine(const std::string& dev_id);
|
// why: clears stale sidebar sync-status / AMS visuals. Public so the printer-agent
|
||||||
std::string get_user_last_machine() const;
|
// swap path can reuse it instead of duplicating the two sidebar calls.
|
||||||
|
void OnSelectedMachineLost();
|
||||||
|
|
||||||
// local machine
|
// local machine
|
||||||
void set_local_selected_machine(std::string dev_id) { local_selected_machine = dev_id; };
|
void set_local_selected_machine(std::string dev_id) { local_selected_machine = dev_id; };
|
||||||
@@ -70,6 +71,8 @@ public:
|
|||||||
void erase_user_machine(std::string dev_id) { userMachineList.erase(dev_id); }
|
void erase_user_machine(std::string dev_id) { userMachineList.erase(dev_id); }
|
||||||
void clean_user_info(bool keep_local_selection = false);
|
void clean_user_info(bool keep_local_selection = false);
|
||||||
|
|
||||||
|
void clear_other_devices();
|
||||||
|
|
||||||
void load_last_machine();
|
void load_last_machine();
|
||||||
void update_user_machine_list_info(const std::string& provider);
|
void update_user_machine_list_info(const std::string& provider);
|
||||||
void parse_user_print_info(std::string body);
|
void parse_user_print_info(std::string body);
|
||||||
@@ -110,7 +113,6 @@ private:
|
|||||||
void check_pushing();
|
void check_pushing();
|
||||||
|
|
||||||
void OnMachineBindStateChanged(MachineObject* obj, const std::string& new_state);
|
void OnMachineBindStateChanged(MachineObject* obj, const std::string& new_state);
|
||||||
void OnSelectedMachineLost();
|
|
||||||
void OnSelectedMachineChanged(const std::string& pre_dev_id, const std::string& new_dev_id);
|
void OnSelectedMachineChanged(const std::string& pre_dev_id, const std::string& new_dev_id);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2809,16 +2809,58 @@ void GUI_App::init_plugin_gui_wiring()
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// why: a newly loaded plugin only adds a selectable agent
|
||||||
|
// refresh the dropdown and leave the live agent alone
|
||||||
|
auto refresh_printer_agent_dropdown_after_load = [](const std::string&)
|
||||||
|
{
|
||||||
|
if (!wxTheApp)
|
||||||
|
return;
|
||||||
|
|
||||||
|
GUI_App* app = &GUI::wxGetApp();
|
||||||
|
if (app->is_closing())
|
||||||
|
return;
|
||||||
|
|
||||||
|
app->CallAfter([app]
|
||||||
|
{
|
||||||
|
if (!app->is_closing())
|
||||||
|
app->refresh_printer_agent_dropdown();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// why: the unloaded plugin may have been the provider of the live agent
|
||||||
|
// re-run selection, where a now-missing agent will be cleared
|
||||||
|
// refresh dropdown after
|
||||||
|
auto switch_printer_agent_after_unload = [](const std::string&)
|
||||||
|
{
|
||||||
|
if (!wxTheApp)
|
||||||
|
return;
|
||||||
|
|
||||||
|
GUI_App* app = &GUI::wxGetApp();
|
||||||
|
if (app->is_closing())
|
||||||
|
return;
|
||||||
|
|
||||||
|
app->CallAfter([app] {
|
||||||
|
if (app->is_closing())
|
||||||
|
return;
|
||||||
|
|
||||||
|
app->switch_printer_agent();
|
||||||
|
app->refresh_printer_agent_dropdown();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
plugin_mgr.subscribe_on_unload_callback(PluginHostUi::close_windows_for_plugin);
|
plugin_mgr.subscribe_on_unload_callback(PluginHostUi::close_windows_for_plugin);
|
||||||
plugin_mgr.subscribe_on_load_callback([refresh_plugins_dialog](const std::string&) { refresh_plugins_dialog(); });
|
plugin_mgr.subscribe_on_load_callback([refresh_plugins_dialog](const std::string&) { refresh_plugins_dialog(); });
|
||||||
plugin_mgr.subscribe_on_unload_callback([refresh_plugins_dialog](const std::string&) { refresh_plugins_dialog(); });
|
plugin_mgr.subscribe_on_unload_callback([refresh_plugins_dialog](const std::string&) { refresh_plugins_dialog(); });
|
||||||
plugin_mgr.subscribe_on_load_callback(NetworkAgentFactory::register_python_plugin);
|
plugin_mgr.subscribe_on_load_callback(NetworkAgentFactory::register_python_plugin);
|
||||||
plugin_mgr.subscribe_on_unload_callback(NetworkAgentFactory::deregister_python_plugin);
|
plugin_mgr.subscribe_on_unload_callback(NetworkAgentFactory::deregister_python_plugin);
|
||||||
|
plugin_mgr.subscribe_on_load_callback(refresh_printer_agent_dropdown_after_load);
|
||||||
|
plugin_mgr.subscribe_on_unload_callback(switch_printer_agent_after_unload);
|
||||||
plugin_mgr.subscribe_on_capability_load_callback(
|
plugin_mgr.subscribe_on_capability_load_callback(
|
||||||
[refresh_plugins_dialog](const PluginCapabilityId& capability) {
|
[refresh_plugins_dialog, refresh_printer_agent_dropdown_after_load](const PluginCapabilityId& capability) {
|
||||||
if (capability.type == PluginCapabilityType::PrinterConnection)
|
if (capability.type == PluginCapabilityType::PrinterConnection)
|
||||||
NetworkAgentFactory::register_python_printer_agent(capability.plugin_key, capability.name);
|
NetworkAgentFactory::register_python_printer_agent(capability.plugin_key, capability.name);
|
||||||
refresh_plugins_dialog();
|
refresh_plugins_dialog();
|
||||||
|
refresh_printer_agent_dropdown_after_load(capability.plugin_key);
|
||||||
// A newly loaded capability may satisfy a missing-plugin notification; re-validate the
|
// A newly loaded capability may satisfy a missing-plugin notification; re-validate the
|
||||||
// current plate (on the UI thread) so the notification clears once its plugin is available.
|
// current plate (on the UI thread) so the notification clears once its plugin is available.
|
||||||
if (wxTheApp && !wxGetApp().is_closing())
|
if (wxTheApp && !wxGetApp().is_closing())
|
||||||
@@ -2828,10 +2870,11 @@ void GUI_App::init_plugin_gui_wiring()
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
plugin_mgr.subscribe_on_capability_unload_callback(
|
plugin_mgr.subscribe_on_capability_unload_callback(
|
||||||
[refresh_plugins_dialog](const PluginCapabilityId& capability) {
|
[refresh_plugins_dialog, switch_printer_agent_after_unload](const PluginCapabilityId& capability) {
|
||||||
if (capability.type == PluginCapabilityType::PrinterConnection)
|
if (capability.type == PluginCapabilityType::PrinterConnection)
|
||||||
NetworkAgentFactory::deregister_python_printer_agent(capability.plugin_key, capability.name);
|
NetworkAgentFactory::deregister_python_printer_agent(capability.plugin_key, capability.name);
|
||||||
refresh_plugins_dialog();
|
refresh_plugins_dialog();
|
||||||
|
switch_printer_agent_after_unload(capability.plugin_key);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3873,6 +3916,36 @@ unsigned GUI_App::get_colour_approx_luma(const wxColour &colour)
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GUI_App::refresh_printer_agent_dropdown()
|
||||||
|
{
|
||||||
|
if (Tab* tab = get_tab(Preset::TYPE_PRINTER))
|
||||||
|
{
|
||||||
|
if (auto* printer_tab = dynamic_cast<TabPrinter*>(tab))
|
||||||
|
printer_tab->refresh_printer_agent_dropdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GUI_App::set_live_printer_agent(std::shared_ptr<IPrinterAgent> agent)
|
||||||
|
{
|
||||||
|
if (!m_agent)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// why: tearing down the old machine selection is only ever the prefix of setting the live
|
||||||
|
// agent (to a new one, or to null when the selection is missing) - so it lives here, not as
|
||||||
|
// a standalone helper. Pass nullptr to clear the selection.
|
||||||
|
if (DeviceManager* dev = getDeviceManager())
|
||||||
|
{
|
||||||
|
dev->set_selected_machine(""); // why: empty id disconnects and deselects the current machine
|
||||||
|
m_agent->set_user_selected_machine("");
|
||||||
|
// note: belt-and-suspenders (precedent: DeviceManagerRefresher::on_timer)
|
||||||
|
dev->OnSelectedMachineLost(); // why: clear stale sidebar sync-status / AMS
|
||||||
|
dev->clear_other_devices(); // why: drop stale LAN discoveries; keep My Devices
|
||||||
|
}
|
||||||
|
|
||||||
|
m_agent->set_printer_agent(agent);
|
||||||
|
sidebar().update_all_preset_comboboxes();
|
||||||
|
}
|
||||||
|
|
||||||
std::string GUI_App::resolve_printer_agent_id(const std::string& stored_id)
|
std::string GUI_App::resolve_printer_agent_id(const std::string& stored_id)
|
||||||
{
|
{
|
||||||
if (!stored_id.empty())
|
if (!stored_id.empty())
|
||||||
@@ -3898,9 +3971,11 @@ void GUI_App::switch_printer_agent()
|
|||||||
// Check if agent is registered
|
// Check if agent is registered
|
||||||
const PrinterAgentInfo* agent_info_ptr = NetworkAgentFactory::get_printer_agent_info(effective_agent_id);
|
const PrinterAgentInfo* agent_info_ptr = NetworkAgentFactory::get_printer_agent_info(effective_agent_id);
|
||||||
if (!agent_info_ptr) {
|
if (!agent_info_ptr) {
|
||||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << ": unregistered agent ID '" << effective_agent_id
|
// why: the selected agent's provider is gone (e.g. plugin unloaded); leaving the old
|
||||||
<< "', keeping current agent";
|
// live agent up would keep talking to a machine the user can no longer select.
|
||||||
// Keep current agent, don't switch
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": agent ID '" << effective_agent_id
|
||||||
|
<< "' is unregistered; clearing live printer agent";
|
||||||
|
set_live_printer_agent(nullptr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const PrinterAgentInfo agent_info = *agent_info_ptr;
|
const PrinterAgentInfo agent_info = *agent_info_ptr;
|
||||||
@@ -3914,7 +3989,9 @@ void GUI_App::switch_printer_agent()
|
|||||||
NetworkAgentFactory::create_printer_agent_by_id(effective_agent_id, cloud_agent, log_dir);
|
NetworkAgentFactory::create_printer_agent_by_id(effective_agent_id, cloud_agent, log_dir);
|
||||||
|
|
||||||
if (!new_printer_agent) {
|
if (!new_printer_agent) {
|
||||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << ": failed to create agent '" << effective_agent_id << "', keeping current agent";
|
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << ": failed to create agent '" << effective_agent_id
|
||||||
|
<< "'; clearing live printer agent";
|
||||||
|
set_live_printer_agent(nullptr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3937,9 +4014,9 @@ void GUI_App::switch_printer_agent()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Swap the agent
|
// Swap the agent; set_live_printer_agent resets the device selection so the new
|
||||||
m_agent->set_printer_agent(new_printer_agent);
|
// agent starts clean (#124).
|
||||||
sidebar().update_all_preset_comboboxes();
|
set_live_printer_agent(new_printer_agent);
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": printer agent switched to " << effective_agent_id;
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": printer agent switched to " << effective_agent_id;
|
||||||
|
|
||||||
|
|||||||
@@ -803,6 +803,11 @@ private:
|
|||||||
void window_pos_center(wxTopLevelWindow *window);
|
void window_pos_center(wxTopLevelWindow *window);
|
||||||
bool select_language();
|
bool select_language();
|
||||||
|
|
||||||
|
// Dynamic printer agent selection - internal helpers for switch_printer_agent
|
||||||
|
// and the plugin load/unload callbacks (init_plugin_gui_wiring).
|
||||||
|
void refresh_printer_agent_dropdown();
|
||||||
|
void set_live_printer_agent(std::shared_ptr<IPrinterAgent> agent); // null clears the selection
|
||||||
|
|
||||||
bool config_wizard_startup();
|
bool config_wizard_startup();
|
||||||
void check_updates(const bool verbose);
|
void check_updates(const bool verbose);
|
||||||
|
|
||||||
|
|||||||
@@ -7907,6 +7907,24 @@ bool TabPrinter::apply_extruder_cnt_from_cache()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TabPrinter::refresh_printer_agent_dropdown() const
|
||||||
|
{
|
||||||
|
auto* choice = dynamic_cast<PrinterAgentChoice*>(get_field("printer_agent"));
|
||||||
|
if (!choice || !choice->getWindow())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto agents = NetworkAgentFactory::get_registered_printer_agents();
|
||||||
|
if (agents.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// why: rows live on PrinterAgentChoice now; rebuild them from the live registry and re-select the stored id.
|
||||||
|
const std::string selected_agent = wxGetApp().preset_bundle->printers.get_edited_preset()
|
||||||
|
.config.opt_string("printer_agent");
|
||||||
|
choice->reload_rows();
|
||||||
|
choice->set_value(selected_agent, false);
|
||||||
|
this->GetParent()->Layout();
|
||||||
|
}
|
||||||
|
|
||||||
bool Tab::validate_custom_gcodes()
|
bool Tab::validate_custom_gcodes()
|
||||||
{
|
{
|
||||||
if (m_type != Preset::TYPE_FILAMENT &&
|
if (m_type != Preset::TYPE_FILAMENT &&
|
||||||
|
|||||||
@@ -675,6 +675,7 @@ public:
|
|||||||
wxSizer* create_bed_shape_widget(wxWindow* parent);
|
wxSizer* create_bed_shape_widget(wxWindow* parent);
|
||||||
void cache_extruder_cnt(const DynamicPrintConfig* config = nullptr);
|
void cache_extruder_cnt(const DynamicPrintConfig* config = nullptr);
|
||||||
bool apply_extruder_cnt_from_cache();
|
bool apply_extruder_cnt_from_cache();
|
||||||
|
void refresh_printer_agent_dropdown() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TabSLAMaterial : public Tab
|
class TabSLAMaterial : public Tab
|
||||||
|
|||||||
Reference in New Issue
Block a user