NEW: support multi device

JIRA: STUDIO-6072

Change-Id: Ic514c4097767b0a728368c9ea48ee103c031fbb0
Signed-off-by: Stone Li <stone.li@bambulab.com>
This commit is contained in:
Stone Li 2024-04-18 04:38:58 +08:00 committed by Lane.Wei
parent 72a1c9ba6e
commit e4288407b9
43 changed files with 6849 additions and 1185 deletions

View File

@ -0,0 +1,4 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.00019 3.16602C9.38756 3.16602 9.76582 3.20475 10.135 3.27539C10.315 3.30957 10.6317 3.41439 10.8049 3.7334C10.8505 3.81771 10.8869 3.90658 10.9097 4.00228L11.1216 4.87956C11.1535 5.01172 11.3768 5.1416 11.5067 5.10286L12.3726 4.84766C12.4637 4.82031 12.5572 4.80664 12.6506 4.80436C13.0174 4.79297 13.2658 5.01855 13.3866 5.15527C13.8902 5.72721 14.2775 6.39941 14.5236 7.12174C14.5829 7.29492 14.6512 7.61849 14.4621 7.92839C14.412 8.01042 14.3505 8.08789 14.2798 8.15625L13.6258 8.77832C13.5301 8.86947 13.5301 9.13151 13.6258 9.22266L14.2798 9.84473C14.3505 9.91309 14.412 9.99056 14.4621 10.0726C14.649 10.3825 14.5806 10.706 14.5236 10.8792C14.2775 11.6016 13.8902 12.2715 13.3866 12.8457C13.2658 12.9824 13.0152 13.208 12.6506 13.1966C12.5572 13.1943 12.4637 13.1784 12.3726 13.1533L11.5067 12.8958C11.3768 12.8571 11.1535 12.987 11.1216 13.1191L10.9097 13.9964C10.8869 14.0921 10.8505 14.1833 10.8049 14.2653C10.6294 14.5843 10.3127 14.6868 10.135 14.7233C9.76582 14.7939 9.38756 14.8327 9.00019 14.8327C8.61282 14.8327 8.23457 14.7939 7.86543 14.7233C7.68542 14.6891 7.36868 14.5843 7.19551 14.2653C7.14993 14.181 7.11348 14.0921 7.09069 13.9964L6.87877 13.1191C6.84687 12.987 6.62357 12.8571 6.49368 12.8958L5.6278 13.151C5.53665 13.1784 5.44323 13.1921 5.3498 13.1943C4.98294 13.2057 4.73457 12.9801 4.6138 12.8434C4.1125 12.2715 3.72285 11.5993 3.47676 10.8769C3.41751 10.7038 3.34915 10.3802 3.53828 10.0703C3.58841 9.98828 3.64993 9.91081 3.72057 9.84245L4.37454 9.22038C4.47025 9.12923 4.47025 8.86719 4.37454 8.77604L3.71829 8.15397C3.64766 8.08561 3.58613 8.00814 3.536 7.92611C3.34915 7.61621 3.41751 7.29264 3.47676 7.12174C3.72285 6.39941 4.11022 5.72949 4.6138 5.15527C4.73457 5.01855 4.98522 4.79297 5.3498 4.80436C5.44323 4.80664 5.53665 4.82259 5.6278 4.84766L6.49368 5.10286C6.62357 5.1416 6.84687 5.01172 6.87877 4.87956L7.09069 4.00228C7.11348 3.90658 7.14993 3.81543 7.19551 3.7334C7.37096 3.41439 7.68769 3.31185 7.86543 3.27539C8.23457 3.20475 8.61282 3.16602 9.00019 3.16602ZM8.13659 4.33724L7.9429 5.13704C7.76517 5.87305 6.91068 6.36523 6.18379 6.15332L5.39766 5.9209C5.02168 6.36068 4.72545 6.87109 4.53177 7.41797L5.12877 7.98535C5.67565 8.50488 5.67565 9.49381 5.12877 10.0133L4.53177 10.5807C4.72545 11.1276 5.02168 11.638 5.39766 12.0778L6.18607 11.8454C6.91068 11.6312 7.76745 12.1257 7.94518 12.8617L8.13887 13.6615C8.69941 13.764 9.30781 13.764 9.86836 13.6615L10.062 12.8617C10.2398 12.1257 11.0943 11.6335 11.8212 11.8454L12.6096 12.0778C12.9855 11.638 13.2818 11.1276 13.4755 10.5807L12.8784 10.0133C12.3316 9.49381 12.3316 8.50488 12.8784 7.98535L13.4755 7.41797C13.2818 6.87109 12.9855 6.36068 12.6096 5.9209L11.8212 6.15332C11.0965 6.36751 10.2398 5.87305 10.062 5.13704L9.86836 4.33724C9.30781 4.2347 8.69941 4.2347 8.13887 4.33724H8.13659Z" fill="white"/>
<path d="M6.75935 8.48777C6.67327 8.56784 6.62354 8.68031 6.62354 8.7985C6.62354 9.03298 6.81483 9.22361 7.05012 9.22361H8.15388V11.0537C8.15388 11.3911 8.42743 11.6637 8.76602 11.6637H9.37816C9.71675 11.6637 9.9903 11.3911 9.9903 11.0537V9.22361H11.0941C11.3294 9.22361 11.5207 9.03298 11.5207 8.7985C11.5207 8.68031 11.4709 8.56784 11.3848 8.48777L9.33607 6.58336C9.26338 6.51664 9.16965 6.47852 9.07209 6.47852C8.97453 6.47852 8.87889 6.51664 8.80811 6.58336L6.75935 8.48777Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -0,0 +1,4 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.1861 5.32812H15.3642V14.5094H8.01917V13.5548M11.6917 5.65603V8.60717M11.1517 11.5583H13.2656" stroke="white"/>
<path d="M6.30876 3.82009V6.77123M4.73482 9.72237H7.8827M2.63623 3.49219H9.98128V12.6735H2.63623V3.49219Z" stroke="white"/>
</svg>

After

Width:  |  Height:  |  Size: 351 B

View File

@ -0,0 +1,8 @@
<svg width="251" height="252" viewBox="0 0 251 252" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.53636 72.2536L67.482 9.08624" stroke="black" stroke-width="17.0079" stroke-miterlimit="10" stroke-linecap="round"/>
<path d="M128.055 72.2536L67.482 9.08624" stroke="black" stroke-width="17.0079" stroke-miterlimit="10" stroke-linecap="round"/>
<path d="M67.9763 243.004V8.79553" stroke="#161615" stroke-width="17.0079" stroke-miterlimit="10" stroke-linecap="round"/>
<path d="M239.519 180L180.573 243.167" stroke="black" stroke-width="17.0079" stroke-miterlimit="10" stroke-linecap="round"/>
<path d="M120 180L180.573 243.167" stroke="black" stroke-width="17.0079" stroke-miterlimit="10" stroke-linecap="round"/>
<path d="M182.91 242.655V8.79999" stroke="#161615" stroke-width="17.0079" stroke-miterlimit="10" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 854 B

View File

@ -178,6 +178,8 @@ void AppConfig::set_defaults()
if (get("show_hints").empty())
set_bool("show_hints", true);
//#endif
if (get("enable_multi_machine").empty())
set_bool("enable_multi_machine", false);
#ifdef _WIN32
@ -327,6 +329,14 @@ void AppConfig::set_defaults()
set("curr_bed_type", "1");
}
if (get("sending_interval").empty()) {
set("sending_interval", "60");
}
if (get("max_send").empty()) {
set("max_send", "10");
}
#if BBL_RELEASE_TO_PUBLIC
if (get("iot_environment").empty()) {
set("iot_environment", "3");

View File

@ -1846,7 +1846,8 @@ std::set<std::string> PresetBundle::get_printer_names_by_printer_type_and_nozzle
if (printer_it->name.find(nozzle_diameter_str) != std::string::npos) printer_names.insert(printer_it->name);
}
assert(printer_names.size() == 1);
//assert(printer_names.size() == 1);
for (auto& printer_name : printer_names) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " " << __LINE__ << " printer name: " << printer_name;

View File

@ -191,6 +191,8 @@ set(SLIC3R_GUI_SOURCES
GUI/Plater.hpp
GUI/PartPlate.cpp
GUI/PartPlate.hpp
GUI/UserNotification.cpp
GUI/UserNotification.hpp
GUI/PresetComboBoxes.hpp
GUI/PresetComboBoxes.cpp
GUI/BitmapComboBox.hpp
@ -428,6 +430,24 @@ set(SLIC3R_GUI_SOURCES
Utils/json_diff.cpp
GUI/KBShortcutsDialog.hpp
GUI/KBShortcutsDialog.cpp
GUI/MultiMachine.hpp
GUI/MultiMachine.cpp
GUI/MultiMachinePage.hpp
GUI/MultiMachinePage.cpp
GUI/MultiMachineManagerPage.cpp
GUI/MultiMachineManagerPage.hpp
GUI/MultiPrintJob.cpp
GUI/MultiPrintJob.hpp
GUI/MultiSendMachineModel.hpp
GUI/MultiSendMachineModel.cpp
GUI/MultiTaskManagerPage.hpp
GUI/MultiTaskManagerPage.cpp
GUI/MultiTaskModel.hpp
GUI/MultiTaskModel.cpp
GUI/SendMultiMachinePage.hpp
GUI/SendMultiMachinePage.cpp
GUI/TaskManager.cpp
GUI/TaskManager.hpp
Utils/Http.cpp
Utils/Http.hpp
Utils/FixModelByWin10.cpp

View File

@ -412,6 +412,48 @@ void AmsMapingPopup::on_left_down(wxMouseEvent &evt)
}
}
void AmsMapingPopup::update_ams_data_multi_machines()
{
m_has_unmatch_filament = false;
for (auto& ams_container : m_amsmapping_container_list) {
ams_container->Hide();
}
for (wxWindow* mitem : m_mapping_item_list) {
mitem->Destroy();
mitem = nullptr;
}
m_mapping_item_list.clear();
if (m_amsmapping_container_sizer_list.size() > 0) {
for (wxBoxSizer* siz : m_amsmapping_container_sizer_list) {
siz->Clear(true);
}
}
int m_amsmapping_container_list_index = 0;
std::vector<TrayData> tray_datas;
for (int i = 0; i < 4; ++i) {
TrayData td;
td.id = i;
td.type = EMPTY;
td.colour = wxColour(166, 169, 170);
td.name = "";
td.filament_type = "";
td.ctype = 0;
tray_datas.push_back(td);
}
m_amsmapping_container_list[m_amsmapping_container_list_index]->Show();
add_ams_mapping(tray_datas, m_amsmapping_container_list[m_amsmapping_container_list_index], m_amsmapping_container_sizer_list[m_amsmapping_container_list_index]);
m_warning_text->Show(m_has_unmatch_filament);
Layout();
Fit();
}
void AmsMapingPopup::update_ams_data(std::map<std::string, Ams*> amsList)
{
m_has_unmatch_filament = false;

View File

@ -157,6 +157,7 @@ public:
void update_materials_list(std::vector<std::string> list);
void set_tag_texture(std::string texture);
void update_ams_data(std::map<std::string, Ams *> amsList);
void update_ams_data_multi_machines();
void add_ams_mapping(std::vector<TrayData> tray_data, wxWindow* container, wxBoxSizer* sizer);
void set_current_filament_id(int id){m_current_filament_id = id;};
int get_current_filament_id(){return m_current_filament_id;};

File diff suppressed because it is too large Load Diff

View File

@ -942,7 +942,7 @@ public:
int publish_json(std::string json_str, int qos = 0);
int cloud_publish_json(std::string json_str, int qos = 0);
int local_publish_json(std::string json_str, int qos = 0);
int parse_json(std::string payload);
int parse_json(std::string payload, bool key_filed_only = false);
int publish_gcode(std::string gcode_str);
std::string setting_id_to_type(std::string setting_id, std::string tray_type);
@ -963,8 +963,9 @@ class DeviceManager
{
private:
NetworkAgent* m_agent { nullptr };
public:
static bool EnableMultiMachine;
DeviceManager(NetworkAgent* agent = nullptr);
~DeviceManager();
void set_agent(NetworkAgent* agent);
@ -989,9 +990,14 @@ public:
bool set_selected_machine(std::string dev_id, bool need_disconnect = false);
MachineObject* get_selected_machine();
void add_user_subscribe();
void del_user_subscribe();
void subscribe_device_list(std::vector<std::string> dev_list);
/* return machine has access code and user machine if login*/
std::map<std::string, MachineObject*> get_my_machine_list();
std::map<std::string, MachineObject*> get_my_cloud_machine_list();
std::string get_first_online_user_machine();
void modify_device_name(std::string dev_id, std::string dev_name);
void update_user_machine_list_info();
@ -1008,6 +1014,11 @@ public:
std::map<std::string, MachineObject*> get_local_machine_list();
void load_last_machine();
std::vector<std::string> subscribe_list_cache;
static void set_key_field_parsing(bool enable) { DeviceManager::key_field_only = enable; }
static bool key_field_only;
static json function_table;
static json filaments_blacklist;

View File

@ -31,6 +31,8 @@ wxDEFINE_EVENT(EVT_GLTOOLBAR_EXPORT_ALL_SLICED_FILE, SimpleEvent);
wxDEFINE_EVENT(EVT_GLTOOLBAR_PRINT_SELECT, SimpleEvent);
wxDEFINE_EVENT(EVT_GLTOOLBAR_SEND_TO_PRINTER, SimpleEvent);
wxDEFINE_EVENT(EVT_GLTOOLBAR_SEND_TO_PRINTER_ALL, SimpleEvent);
wxDEFINE_EVENT(EVT_GLTOOLBAR_PRINT_MULTI_MACHINE, SimpleEvent);
wxDEFINE_EVENT(EVT_GLTOOLBAR_ADD, SimpleEvent);
wxDEFINE_EVENT(EVT_GLTOOLBAR_DELETE, SimpleEvent);

View File

@ -32,6 +32,8 @@ wxDECLARE_EVENT(EVT_GLTOOLBAR_EXPORT_ALL_SLICED_FILE, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_PRINT_SELECT, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_SEND_TO_PRINTER, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_SEND_TO_PRINTER_ALL, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_PRINT_MULTI_MACHINE, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_ADD, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_DELETE, SimpleEvent);

View File

@ -3,6 +3,7 @@
#include "GUI_Init.hpp"
#include "GUI_ObjectList.hpp"
#include "GUI_Factories.hpp"
#include "slic3r/GUI/TaskManager.hpp"
#include "format.hpp"
// Localization headers: include libslic3r version first so everything in this file
@ -149,6 +150,7 @@ class MainFrame;
void start_ping_test()
{
return;
wxArrayString output;
wxExecute("ping www.amazon.com", output, wxEXEC_NODISABLE);
@ -1943,6 +1945,22 @@ void GUI_App::init_networking_callbacks()
return;
BOOST_LOG_TRIVIAL(trace) << "static: server connected";
m_agent->set_user_selected_machine(m_agent->get_user_selected_machine());
if (this->is_enable_multi_machine()) {
auto evt = new wxCommandEvent(EVT_UPDATE_MACHINE_LIST);
wxQueueEvent(this, evt);
}
m_agent->set_user_selected_machine(m_agent->get_user_selected_machine());
//subscribe device
if (m_agent->is_user_login()) {
m_agent->start_device_subscribe();
/* resubscribe the cache dev list */
if (this->is_enable_multi_machine()) {
DeviceManager* dev = this->getDeviceManager();
if (dev && !dev->subscribe_list_cache.empty()) {
dev->subscribe_device_list(dev->subscribe_list_cache);
}
}
}
});
});
@ -1968,7 +1986,9 @@ void GUI_App::init_networking_callbacks()
obj->command_get_version();
obj->erase_user_access_code();
obj->command_get_access_code();
GUI::wxGetApp().sidebar().load_ams_list(obj->dev_id, obj);
if (!is_enable_multi_machine()) {
GUI::wxGetApp().sidebar().load_ams_list(obj->dev_id, obj);
}
}
});
});
@ -2064,11 +2084,21 @@ void GUI_App::init_networking_callbacks()
MachineObject* obj = this->m_device_manager->get_user_machine(dev_id);
if (obj) {
obj->is_ams_need_update = false;
obj->parse_json(msg);
auto sel = this->m_device_manager->get_selected_machine();
if ((sel == obj || sel == nullptr) && obj->is_ams_need_update) {
GUI::wxGetApp().sidebar().load_ams_list(obj->dev_id, obj);
if (sel && sel->dev_id == dev_id) {
obj->parse_json(msg);
}
else {
obj->parse_json(msg, true);
}
if (!this->is_enable_multi_machine()) {
if ((sel == obj || sel == nullptr) && obj->is_ams_need_update) {
GUI::wxGetApp().sidebar().load_ams_list(obj->dev_id, obj);
}
}
}
});
@ -2090,11 +2120,15 @@ void GUI_App::init_networking_callbacks()
}
if (obj) {
obj->parse_json(msg);
obj->parse_json(msg, DeviceManager::key_field_only);
if (this->m_device_manager->get_selected_machine() == obj && obj->is_ams_need_update) {
GUI::wxGetApp().sidebar().load_ams_list(obj->dev_id, obj);
}
}
obj = m_device_manager->get_local_machine(dev_id);
if (obj) {
obj->parse_json(msg, DeviceManager::key_field_only);
}
});
};
m_agent->set_on_local_message_fn(lan_message_arrive_fn);
@ -2713,6 +2747,7 @@ bool GUI_App::on_init_inner()
preset_bundle->set_default_suppressed(true);
Bind(EVT_SET_SELECTED_MACHINE, &GUI_App::on_set_selected_machine, this);
Bind(EVT_UPDATE_MACHINE_LIST, &GUI_App::on_update_machine_list, this);
Bind(EVT_USER_LOGIN, &GUI_App::on_user_login, this);
Bind(EVT_USER_LOGIN_HANDLE, &GUI_App::on_user_login_handle, this);
Bind(EVT_CHECK_PRIVACY_VER, &GUI_App::on_check_privacy_update, this);
@ -3028,6 +3063,17 @@ __retry:
else
m_device_manager->set_agent(m_agent);
if (this->is_enable_multi_machine()) {
if (!m_task_manager) {
m_task_manager = new Slic3r::TaskManager(m_agent);
m_task_manager->start();
}
m_agent->enable_multi_machine(true);
DeviceManager::EnableMultiMachine = true;
} else {
m_agent->enable_multi_machine(false);
DeviceManager::EnableMultiMachine = false;
}
//BBS set config dir
if (m_agent) {
@ -4108,7 +4154,7 @@ std::string GUI_App::handle_web_request(std::string cmd)
}
}
else if (command_str.compare("homepage_makerlab_get") == 0) {
if (mainframe->m_webview) { mainframe->m_webview->SendMakerlabList(); }
//if (mainframe->m_webview) { mainframe->m_webview->SendMakerlabList(); }
}
else if (command_str.compare("homepage_makerlab_open") == 0) {
if (root.get_child_optional("url") != boost::none) {
@ -4298,9 +4344,17 @@ void GUI_App::enable_user_preset_folder(bool enable)
void GUI_App::on_set_selected_machine(wxCommandEvent &evt)
{
DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
if (!dev || m_agent) return;
if (dev) {
dev->set_selected_machine(m_agent->get_user_selected_machine());
}
}
dev->set_selected_machine(m_agent->get_user_selected_machine());
void GUI_App::on_update_machine_list(wxCommandEvent &evt)
{
/* DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
if (dev) {
dev->add_user_subscribe();
}*/
}
void GUI_App::on_user_login_handle(wxCommandEvent &evt)
@ -4659,6 +4713,26 @@ void GUI_App::show_dialog(wxString msg)
}
}
void GUI_App::push_notification(wxString msg, wxString title, UserNotificationStyle style)
{
if (!this->is_enable_multi_machine()) {
if (style == UserNotificationStyle::UNS_NORMAL) {
if (m_info_dialog_content.empty()) {
wxCommandEvent* evt = new wxCommandEvent(EVT_SHOW_DIALOG);
evt->SetString(msg);
GUI::wxGetApp().QueueEvent(evt);
m_info_dialog_content = msg;
}
}
else if (style == UserNotificationStyle::UNS_WARNING_CONFIRM) {
GUI::wxGetApp().CallAfter([msg, title] {
GUI::MessageDialog msg_dlg(nullptr, msg, title, wxICON_WARNING | wxOK);
msg_dlg.ShowModal();
});
}
}
}
void GUI_App::reload_settings()
{
if (preset_bundle && m_agent) {

View File

@ -10,6 +10,7 @@
#include "libslic3r/PresetBundle.hpp"
#include "libslic3r/Color.hpp"
#include "slic3r/GUI/DeviceManager.hpp"
#include "slic3r/GUI/UserNotification.hpp"
#include "slic3r/Utils/NetworkAgent.hpp"
#include "slic3r/GUI/WebViewDialog.hpp"
#include "slic3r/GUI/WebUserLoginDialog.hpp"
@ -59,6 +60,7 @@ class ModelObject;
class Model;
class DeviceManager;
class NetworkAgent;
class TaskManager;
namespace GUI{
@ -275,6 +277,7 @@ private:
//BBS
bool m_is_closing {false};
Slic3r::DeviceManager* m_device_manager { nullptr };
Slic3r::TaskManager* m_task_manager { nullptr };
NetworkAgent* m_agent { nullptr };
std::vector<std::string> need_delete_presets; // store setting ids of preset
std::vector<bool> m_create_preset_blocked { false, false, false, false, false, false }; // excceed limit
@ -309,6 +312,7 @@ public:
bool OnInit() override;
int OnExit() override;
bool initialized() const { return m_initialized; }
inline bool is_enable_multi_machine() { return this->app_config&& this->app_config->get("enable_multi_machine") == "true"; }
std::map<std::string, bool> test_url_state;
@ -321,6 +325,7 @@ public:
void show_message_box(std::string msg) { wxMessageBox(msg); }
EAppMode get_app_mode() const { return m_app_mode; }
Slic3r::DeviceManager* getDeviceManager() { return m_device_manager; }
Slic3r::TaskManager* getTaskManager() { return m_task_manager; }
HMSQuery* get_hms_query() { return hms_query; }
NetworkAgent* getAgent() { return m_agent; }
bool is_editor() const { return m_app_mode == EAppMode::Editor; }
@ -434,6 +439,7 @@ public:
void handle_http_error(unsigned int status, std::string body);
void on_http_error(wxCommandEvent &evt);
void on_set_selected_machine(wxCommandEvent& evt);
void on_update_machine_list(wxCommandEvent& evt);
void on_user_login(wxCommandEvent &evt);
void on_user_login_handle(wxCommandEvent& evt);
void enable_user_preset_folder(bool enable);
@ -453,6 +459,7 @@ public:
static std::string format_display_version();
std::string format_IP(const std::string& ip);
void show_dialog(wxString msg);
void push_notification(wxString msg, wxString title = wxEmptyString, UserNotificationStyle style = UserNotificationStyle::UNS_NORMAL);
void reload_settings();
void remove_user_presets();
void sync_preset(Preset* preset);

View File

@ -79,6 +79,7 @@ wxDEFINE_EVENT(EVT_CHECK_PRIVACY_VER, wxCommandEvent);
wxDEFINE_EVENT(EVT_CHECK_PRIVACY_SHOW, wxCommandEvent);
wxDEFINE_EVENT(EVT_SHOW_IP_DIALOG, wxCommandEvent);
wxDEFINE_EVENT(EVT_SET_SELECTED_MACHINE, wxCommandEvent);
wxDEFINE_EVENT(EVT_UPDATE_MACHINE_LIST, wxCommandEvent);
wxDEFINE_EVENT(EVT_UPDATE_PRESET_CB, SimpleEvent);
@ -1147,13 +1148,20 @@ void MainFrame::init_tabpanel()
});
m_printer_view->Hide();
if (wxGetApp().is_enable_multi_machine()) {
m_multi_machine = new MultiMachinePage(m_tabpanel, wxID_ANY, wxDefaultPosition, wxDefaultSize);
m_multi_machine->SetBackgroundColour(*wxWHITE);
// TODO: change the bitmap
m_tabpanel->AddPage(m_multi_machine, _L("Multi-device"), std::string("tab_multi_active"), std::string("tab_multi_active"), false);
}
m_project = new ProjectPanel(m_tabpanel, wxID_ANY, wxDefaultPosition, wxDefaultSize);
m_project->SetBackgroundColour(*wxWHITE);
m_tabpanel->AddPage(m_project, _L("Project"), std::string("tab_auxiliary_avtice"), std::string("tab_auxiliary_avtice"), false);
m_calibration = new CalibrationPanel(m_tabpanel, wxID_ANY, wxDefaultPosition, wxDefaultSize);
m_calibration->SetBackgroundColour(*wxWHITE);
m_tabpanel->AddPage(m_calibration, _L("Calibration"), std::string("tab_monitor_active"), std::string("tab_monitor_active"), false);
m_tabpanel->AddPage(m_calibration, _L("Calibration"), std::string("tab_calibration_active"), std::string("tab_calibration_active"), false);
if (m_plater) {
// load initial config
@ -1603,7 +1611,7 @@ wxBoxSizer* MainFrame::create_side_tools()
m_print_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent& event)
{
//this->m_plater->select_view_3D("Preview");
if (m_print_select == ePrintAll || m_print_select == ePrintPlate)
if (m_print_select == ePrintAll || m_print_select == ePrintPlate || m_print_select == ePrintMultiMachine)
{
m_plater->apply_background_progress();
// check valid of print
@ -1614,6 +1622,8 @@ wxBoxSizer* MainFrame::create_side_tools()
wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_PRINT_ALL));
if (m_print_select == ePrintPlate)
wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_PRINT_PLATE));
if(m_print_select == ePrintMultiMachine)
wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_PRINT_MULTI_MACHINE));
}
}
else if (m_print_select == eExportGcode)
@ -1630,6 +1640,8 @@ wxBoxSizer* MainFrame::create_side_tools()
wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_SEND_TO_PRINTER));
else if (m_print_select == eSendToPrinterAll)
wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_SEND_TO_PRINTER_ALL));
/* else if (m_print_select == ePrintMultiMachine)
wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_PRINT_MULTI_MACHINE));*/
});
m_slice_option_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent& event)
@ -1723,6 +1735,9 @@ wxBoxSizer* MainFrame::create_side_tools()
SideButton* export_all_sliced_file_btn = new SideButton(p, _L("Export all sliced file"), "");
export_all_sliced_file_btn->SetCornerRadius(0);
SideButton* print_multi_machine_btn = new SideButton(p, _L("Send to Multi-device"), "");
print_multi_machine_btn->SetCornerRadius(0);
print_plate_btn->Bind(wxEVT_BUTTON, [this, p](wxCommandEvent&) {
m_print_btn->SetLabel(_L("Print plate"));
m_print_select = ePrintPlate;
@ -1781,12 +1796,23 @@ wxBoxSizer* MainFrame::create_side_tools()
p->Dismiss();
});
print_multi_machine_btn->Bind(wxEVT_BUTTON, [this, p](wxCommandEvent&) {
m_print_btn->SetLabel(_L("Send to Multi-device"));
m_print_select = ePrintMultiMachine;
m_print_enable = get_enable_print_status();
m_print_btn->Enable(m_print_enable);
this->Layout();
p->Dismiss();
});
p->append_button(print_plate_btn);
p->append_button(print_all_btn);
p->append_button(send_to_printer_btn);
p->append_button(send_to_printer_all_btn);
p->append_button(export_sliced_file_btn);
p->append_button(export_all_sliced_file_btn);
if (wxGetApp().is_enable_multi_machine())
p->append_button(print_multi_machine_btn);
}
p->Popup(m_print_btn);
@ -1928,6 +1954,14 @@ bool MainFrame::get_enable_print_status()
enable = false;
}
}
else if (m_print_select == ePrintMultiMachine)
{
if (!current_plate->is_slice_result_ready_for_print())
{
enable = false;
}
enable = enable && !is_all_plates;
}
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": m_print_select %1%, enable= %2% ")%m_print_select %enable;
@ -2048,6 +2082,7 @@ void MainFrame::on_dpi_changed(const wxRect& suggested_rect)
m_param_panel->msw_rescale();
m_project->msw_rescale();
m_monitor->msw_rescale();
m_multi_machine->msw_rescale();
m_calibration->msw_rescale();
// BBS
@ -3403,6 +3438,13 @@ void MainFrame::jump_to_monitor(std::string dev_id)
((MonitorPanel*)m_monitor)->select_machine(dev_id);
}
void MainFrame::jump_to_multipage()
{
m_tabpanel->SetSelection(tpMultiDevice);
((MultiMachinePage*)m_multi_machine)->jump_to_send_page();
}
//BBS GUI refactor: remove unused layout new/dlg
void MainFrame::select_tab(size_t tab/* = size_t(-1)*/)
{
@ -3769,6 +3811,10 @@ void MainFrame::update_side_preset_ui()
//BBS: update the preset
m_plater->sidebar().update_presets(Preset::TYPE_PRINTER);
m_plater->sidebar().update_presets(Preset::TYPE_FILAMENT);
//take off multi machine
if(m_multi_machine){m_multi_machine->clear_page();}
}
void MainFrame::on_select_default_preset(SimpleEvent& evt)

View File

@ -32,6 +32,7 @@
#include "BBLTopbar.hpp"
#include "PrinterWebView.hpp"
#include "calib_dlg.hpp"
#include "MultiMachinePage.hpp"
#define ENABEL_PRINT_ALL 0
@ -198,21 +199,6 @@ protected:
#endif
public:
//BBS GUI refactor
enum PrintSelectType
{
ePrintAll = 0,
ePrintPlate = 1,
eExportSlicedFile = 2,
eExportGcode = 3,
eSendGcode = 4,
eSendToPrinter = 5,
eSendToPrinterAll = 6,
eUploadGcode = 7,
eExportAllSlicedFile = 8
};
MainFrame();
~MainFrame() = default;
@ -223,10 +209,11 @@ public:
tp3DEditor = 1,
tpPreview = 2,
tpMonitor = 3,
tpProject = 4,
tpCalibration = 5,
tpAuxiliary = 6,
toDebugTool = 7,
tpMultiDevice = 4,
tpProject = 5,
tpCalibration = 6,
tpAuxiliary = 7,
toDebugTool = 8,
};
//BBS: add slice&&print status update logic
@ -239,6 +226,20 @@ public:
eEventPrintUpdate = 4
};
// BBS GUI refactor
enum PrintSelectType {
ePrintAll = 0,
ePrintPlate = 1,
eExportSlicedFile = 2,
eExportGcode = 3,
eSendGcode = 4,
eSendToPrinter = 5,
eSendToPrinterAll = 6,
eUploadGcode = 7,
eExportAllSlicedFile = 8,
ePrintMultiMachine = 9
};
void update_layout();
// Called when closing the application and when switching the application language.
@ -307,6 +308,7 @@ public:
void load_config(const DynamicPrintConfig& config);
//BBS: jump to monitor
void jump_to_monitor(std::string dev_id = "");
void jump_to_multipage();
//BBS: hint when jump to 3Deditor under preview only mode
bool preview_only_hint();
// Select tab in m_tabpanel
@ -360,6 +362,7 @@ public:
MonitorPanel* m_monitor{ nullptr };
//AuxiliaryPanel* m_auxiliary{ nullptr };
MultiMachinePage* m_multi_machine{ nullptr };
ProjectPanel* m_project{ nullptr };
CalibrationPanel* m_calibration{ nullptr };
@ -414,6 +417,7 @@ wxDECLARE_EVENT(EVT_CHECK_PRIVACY_VER, wxCommandEvent);
wxDECLARE_EVENT(EVT_CHECK_PRIVACY_SHOW, wxCommandEvent);
wxDECLARE_EVENT(EVT_SHOW_IP_DIALOG, wxCommandEvent);
wxDECLARE_EVENT(EVT_SET_SELECTED_MACHINE, wxCommandEvent);
wxDECLARE_EVENT(EVT_UPDATE_MACHINE_LIST, wxCommandEvent);
wxDECLARE_EVENT(EVT_UPDATE_PRESET_CB, SimpleEvent);

View File

@ -0,0 +1,255 @@
#include "MultiMachine.hpp"
#include "I18N.hpp"
#include "GUI_App.hpp"
#include "MainFrame.hpp"
namespace Slic3r {
namespace GUI {
wxDEFINE_EVENT(EVT_MULTI_CLOUD_TASK_SELECTED, wxCommandEvent);
wxDEFINE_EVENT(EVT_MULTI_LOCAL_TASK_SELECTED, wxCommandEvent);
wxDEFINE_EVENT(EVT_MULTI_DEVICE_SELECTED, wxCommandEvent);
wxDEFINE_EVENT(EVT_MULTI_DEVICE_VIEW, wxCommandEvent);
DeviceItem::DeviceItem(wxWindow* parent, MachineObject* obj)
: wxWindow(parent, wxID_ANY)
, obj_(obj)
{
sync_state();
}
void DeviceItem::sync_state()
{
if (obj_) {
state_online = obj_->is_online();
state_dev_name = obj_->dev_name;
//printable
if (obj_->print_status == "IDLE") {
state_printable = 0;
}
else if (obj_->print_status == "FINISH") {
state_printable = 1;
}
else if (obj_->print_status == "FAILED") {
state_printable = 2;
}
else if (obj_->is_in_printing()) {
state_printable = 3;
}
else if (obj_->is_in_upgrading()) {
state_printable = 4;
}
else {
state_printable = 6;
}
if (is_blocking_printing(obj_)) {
state_printable = 5;
}
state_enable_ams = obj_->ams_exist_bits;
//device
if (obj_->print_status == "IDLE") {
state_device = 0;
}
else if (obj_->print_status == "FINISH") {
state_device = 1;
}
else if (obj_->print_status == "FAILED") {
state_device = 2;
}
else if (obj_->print_status == "RUNNING") {
state_device = 3;
}
else if (obj_->print_status == "PAUSE") {
state_device = 4;
}
else if (obj_->print_status == "PREPARE") {
state_device = 5;
}
else if (obj_->print_status == "SLICING") {
state_device = 6;
}
else {
state_device = 7;
}
}
}
void DeviceItem::selected()
{
if (state_selected != 2) {
state_selected = 1;
}
}
void DeviceItem::unselected()
{
if (state_selected != 2) {
state_selected = 0;
}
}
bool DeviceItem::is_blocking_printing(MachineObject* obj_)
{
DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
if (!dev) return true;
auto target_model = obj_->printer_type;
std::string source_model = "";
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
source_model = preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle);
if (source_model != target_model) {
std::vector<std::string> compatible_machine = dev->get_compatible_machine(target_model);
vector<std::string>::iterator it = find(compatible_machine.begin(), compatible_machine.end(), source_model);
if (it == compatible_machine.end()) {
return true;
}
}
return false;
}
void DeviceItem::update_item(const DeviceItem* item)
{
// Except for the selected status, everything else is updated
if (this == item)
return;
this->state_online = item->state_online;
this->state_printable = item->state_printable;
this->state_enable_ams = item->state_enable_ams;
this->state_device = item->state_device;
this->state_local_task = item->state_local_task;
}
wxString DeviceItem::get_state_printable()
{
//0-idle 1-finish 2-printing 3-upgrading 4-preset incompatible 5-unknown
std::vector<wxString> str_state_printable;
str_state_printable.push_back(_L("Idle"));
str_state_printable.push_back(_L("Idle"));
str_state_printable.push_back(_L("Idle"));
str_state_printable.push_back(_L("Printing"));
str_state_printable.push_back(_L("Upgrading"));
str_state_printable.push_back(_L("Incompatible"));
str_state_printable.push_back(_L("syncing"));
return str_state_printable[state_printable];
}
wxString DeviceItem::get_state_device()
{
//0-idle 1-finish 2-running 3-pause 4-failed 5-prepare
std::vector<wxString> str_state_device;
str_state_device.push_back(_L("Idle"));
str_state_device.push_back(_L("Printing Finish"));
str_state_device.push_back(_L("Printing Failed"));
str_state_device.push_back(_L("Printing"));
str_state_device.push_back(_L("PrintingPause"));
str_state_device.push_back(_L("Prepare"));
str_state_device.push_back(_L("Slicing"));
str_state_device.push_back(_L("syncing"));
return str_state_device[state_device];
}
wxString DeviceItem::get_local_state_task()
{
//0-padding 1-sending 2-sending finish 3-sending cancel 4-sending failed 5-Removed
std::vector<wxString> str_state_task;
str_state_task.push_back(_L("Pending"));
str_state_task.push_back(_L("Sending"));
str_state_task.push_back(_L("Sending Finish"));
str_state_task.push_back(_L("Sending Cancel"));
str_state_task.push_back(_L("Sending Failed"));
str_state_task.push_back(_L("Printing"));
str_state_task.push_back(_L("Print Success"));
str_state_task.push_back(_L("Print Failed"));
str_state_task.push_back(_L("Removed"));
str_state_task.push_back(_L("Idle"));
return str_state_task[state_local_task];
}
wxString DeviceItem::get_cloud_state_task()
{
//0-printing 1-printing finish 2-printing failed
std::vector<wxString> str_state_task;
str_state_task.push_back(_L("Printing"));
str_state_task.push_back(_L("Printing Finish"));
str_state_task.push_back(_L("Printing Failed"));
return str_state_task[state_cloud_task];
}
std::vector<DeviceItem*> selected_machines(const std::vector<DeviceItem*>& dev_item_list, std::string search_text)
{
std::vector<DeviceItem*> res;
for (const auto& item : dev_item_list) {
const MachineObject* dev = item->get_obj();
const std::string& dev_name = dev->dev_name;
const std::string& dev_ip = dev->dev_ip;
auto name_it = dev_name.find(search_text);
auto ip_it = dev_ip.find(search_text);
if (name_it != std::string::npos || ip_it != std::string::npos)
res.emplace_back(item);
}
return res;
}
SortItem::SortItem()
{
sort_map.emplace(std::make_pair(SortRule::SR_DEV_NAME, [this](const DeviceItem* d1, const DeviceItem* d2) {
return this->big ? d1->state_dev_name > d2->state_dev_name : d1->state_dev_name < d2->state_dev_name;
}));
sort_map.emplace(std::make_pair(SortRule::SR_ONLINE, [this](const DeviceItem* d1, const DeviceItem* d2) {
return this->big ? d1->state_online > d2->state_online : d1->state_online < d2->state_online;
}));
sort_map.emplace(std::make_pair(SortRule::SR_PRINTABLE, [this](const DeviceItem* d1, const DeviceItem* d2) {
return this->big ? d1->state_printable > d2->state_printable : d1->state_printable < d2->state_printable;
}));
sort_map.emplace(std::make_pair(SortRule::SR_EN_AMS, [this](const DeviceItem* d1, const DeviceItem* d2) {
return this->big ? d1->state_enable_ams > d2->state_enable_ams : d1->state_enable_ams < d2->state_enable_ams;
}));
sort_map.emplace(std::make_pair(SortRule::SR_DEV_STATE, [this](const DeviceItem* d1, const DeviceItem* d2) {
return this->big ? d1->state_device > d2->state_device : d1->state_device < d2->state_device;
}));
sort_map.emplace(std::make_pair(SortRule::SR_LOCAL_TASK_STATE, [this](const DeviceItem* d1, const DeviceItem* d2) {
return this->big ? d1->state_local_task > d2->state_local_task : d1->state_local_task < d2->state_local_task;
}));
sort_map.emplace(std::make_pair(SortRule::SR_CLOUD_TASK_STATE, [this](const DeviceItem* d1, const DeviceItem* d2) {
return this->big ? d1->state_cloud_task > d2->state_cloud_task : d1->state_cloud_task < d2->state_cloud_task;
}));
sort_map.emplace(std::make_pair(SortRule::SR_SEND_TIME, [this](const DeviceItem* d1, const DeviceItem* d2) {
return this->big ? d1->m_send_time > d2->m_send_time : d1->m_send_time < d2->m_send_time;
}));
}
SortItem::SortCallBack SortItem::get_call_back()
{
return sort_map[rule];
}
void SortItem::set_role(SortRule rule, bool big)
{
this->rule = rule;
this->big = big;
}
void SortItem::set_role(SortMultiMachineCB cb, SortRule rl, bool big)
{
this->cb = cb;
this->rule = rl;
this->big = big;
}
} // namespace GUI
} // namespace Slic3r

View File

@ -0,0 +1,118 @@
#ifndef slic3r_MultiMachine_hpp_
#define slic3r_MultiMachine_hpp_
#include "GUI_Utils.hpp"
#include "DeviceManager.hpp"
#include <functional>
namespace Slic3r {
namespace GUI {
#define DEVICE_ITEM_MAX_WIDTH 900
#define SEND_ITEM_MAX_HEIGHT 40
#define DEVICE_ITEM_MAX_HEIGHT 50
#define TABLE_HEAR_NORMAL_COLOUR wxColour(238, 238, 238)
#define TABLE_HEAD_PRESSED_COLOUR wxColour(150, 150, 150)
#define CTRL_BUTTON_NORMAL_COLOUR wxColour(255, 255, 255)
#define CTRL_BUTTON_PRESSEN_COLOUR wxColour(150, 150, 150)
#define TABLE_HEAD_FONT Label::Body_13
#define ICON_SIZE FromDIP(16)
class DeviceItem : public wxWindow
{
public:
MachineObject* obj_{nullptr};
int state_online = { 0 }; //0-Offline 1-Online
std::string state_dev_name; //device name
int state_printable{ 0 }; //0-idle 1-finish 2-failed 3-printing 4-upgrading 5-preset incompatible 6-unknown
int state_selected{ 0 }; //0-selected 1-unselected 2-un selectable
int state_enable_ams{ 0 };//0-no ams 1-enabled ams 2-not enabled ams
int state_device{ 0 }; //0-idle 1-finish 2-failed 3-running 4-pause 5-prepare 6-slicing 7-removed
int state_local_task{ 0 }; //0-padding 1-sending 2-sending finish 3-sending cancel 4-sending failed 5-TS_PRINT_SUCCESS 6- TS_PRINT_FAILED 7-TS_REMOVED 8-TS_IDLE
int state_cloud_task{ 0 }; //0-printing 1-printing finish 2-printing failed
int state_optional{0}; //0-Not optional 1-Optional
std::string m_send_time;
public:
DeviceItem(wxWindow* parent, MachineObject* obj);
~DeviceItem() {};
void sync_state();
wxString get_state_printable();
wxString get_state_device();
wxString get_local_state_task();
wxString get_cloud_state_task();
MachineObject* get_obj() const { return obj_; }
int get_state_online() const { return state_online; }
int get_state_printable() const { return state_printable; }
int get_state_selected() const { return state_selected; }
int get_state_enable_ams() const { return state_enable_ams; }
int get_state_device() const { return state_device; }
int get_state_local_task() const { return state_local_task; }
int get_state_cloud_task() const { return state_cloud_task; }
std::string get_state_dev_name() const { return state_dev_name; }
void selected();
void unselected();
bool is_blocking_printing(MachineObject* obj_);
void update_item(const DeviceItem* item);
};
std::vector<DeviceItem*> selected_machines(const std::vector<DeviceItem*>& dev_item_list, std::string search_text);
struct ObjState
{
std::string dev_id;
std::string state_dev_name;
int state_device{ 0 };
};
struct SortItem
{
typedef std::function<bool(DeviceItem*, DeviceItem*)> SortCallBack;
typedef std::function<bool(ObjState s1, ObjState s2) > SortMultiMachineCB;
enum SortRule : uint8_t
{
SR_None = 0,
SR_DEV_NAME = 1,
SR_ONLINE,
SR_PRINTABLE,
SR_EN_AMS,
SR_DEV_STATE,
SR_LOCAL_TASK_STATE,
SR_CLOUD_TASK_STATE,
SR_SEND_TIME,
SR_MACHINE_NAME,
SR_MACHINE_STATE,
SR_COUNT
};
SortRule rule{ SortRule::SR_None };
bool big{ true };
std::unordered_map<SortRule, SortCallBack> sort_map;
SortMultiMachineCB cb;
SortItem();
SortItem(SortRule sr) { rule = sr; }
SortCallBack get_call_back();
void set_role(SortRule rule, bool big);
void set_role(SortMultiMachineCB cb, SortRule rl, bool big);
SortMultiMachineCB get_machine_call_back() const { return cb; }
};
wxDECLARE_EVENT(EVT_MULTI_DEVICE_SELECTED, wxCommandEvent);
wxDECLARE_EVENT(EVT_MULTI_DEVICE_VIEW, wxCommandEvent);
wxDECLARE_EVENT(EVT_MULTI_CLOUD_TASK_SELECTED, wxCommandEvent);
wxDECLARE_EVENT(EVT_MULTI_LOCAL_TASK_SELECTED, wxCommandEvent);
} // namespace GUI
} // namespace Slic3r
#endif

View File

@ -0,0 +1,605 @@
#include "MultiMachineManagerPage.hpp"
#include "GUI_App.hpp"
#include "MainFrame.hpp"
namespace Slic3r {
namespace GUI {
MultiMachineItem::MultiMachineItem(wxWindow* parent, MachineObject* obj)
: DeviceItem(parent, obj)
{
SetBackgroundColour(*wxWHITE);
SetMinSize(wxSize(FromDIP(DEVICE_ITEM_MAX_WIDTH), FromDIP(DEVICE_ITEM_MAX_HEIGHT)));
SetMaxSize(wxSize(FromDIP(DEVICE_ITEM_MAX_WIDTH), FromDIP(DEVICE_ITEM_MAX_HEIGHT)));
Bind(wxEVT_PAINT, &MultiMachineItem::paintEvent, this);
Bind(wxEVT_ENTER_WINDOW, &MultiMachineItem::OnEnterWindow, this);
Bind(wxEVT_LEAVE_WINDOW, &MultiMachineItem::OnLeaveWindow, this);
Bind(wxEVT_LEFT_DOWN, &MultiMachineItem::OnLeftDown, this);
Bind(wxEVT_MOTION, &MultiMachineItem::OnMove, this);
Bind(EVT_MULTI_DEVICE_VIEW, [this, obj](auto& e) {
wxGetApp().mainframe->jump_to_monitor(obj->dev_id);
});
wxGetApp().UpdateDarkUIWin(this);
}
void MultiMachineItem::OnEnterWindow(wxMouseEvent& evt)
{
m_hover = true;
Refresh();
}
void MultiMachineItem::OnLeaveWindow(wxMouseEvent& evt)
{
m_hover = false;
Refresh();
}
void MultiMachineItem::OnLeftDown(wxMouseEvent& evt)
{
int left = FromDIP(DEVICE_LEFT_PADDING_LEFT +
DEVICE_LEFT_DEV_NAME +
DEVICE_LEFT_PRO_NAME +
DEVICE_LEFT_PRO_INFO);
auto mouse_pos = ClientToScreen(evt.GetPosition());
auto item = this->ClientToScreen(wxPoint(0, 0));
if (mouse_pos.x > (item.x + left) &&
mouse_pos.x < (item.x + left + FromDIP(90)) &&
mouse_pos.y > item.y &&
mouse_pos.y < (item.y + DEVICE_ITEM_MAX_HEIGHT)) {
post_event(wxCommandEvent(EVT_MULTI_DEVICE_VIEW));
}
}
void MultiMachineItem::OnMove(wxMouseEvent& evt)
{
int left = FromDIP(DEVICE_LEFT_PADDING_LEFT +
DEVICE_LEFT_DEV_NAME +
DEVICE_LEFT_PRO_NAME +
DEVICE_LEFT_PRO_INFO);
auto mouse_pos = ClientToScreen(evt.GetPosition());
auto item = this->ClientToScreen(wxPoint(0, 0));
if (mouse_pos.x > (item.x + left) &&
mouse_pos.x < (item.x + left + FromDIP(90)) &&
mouse_pos.y > item.y &&
mouse_pos.y < (item.y + DEVICE_ITEM_MAX_HEIGHT)) {
SetCursor(wxCURSOR_HAND);
}
else {
SetCursor(wxCURSOR_ARROW);
}
}
void MultiMachineItem::paintEvent(wxPaintEvent& evt)
{
wxPaintDC dc(this);
render(dc);
}
void MultiMachineItem::render(wxDC& dc)
{
#ifdef __WXMSW__
wxSize size = GetSize();
wxMemoryDC memdc;
wxBitmap bmp(size.x, size.y);
memdc.SelectObject(bmp);
memdc.Blit({ 0, 0 }, size, &dc, { 0, 0 });
{
wxGCDC dc2(memdc);
doRender(dc2);
}
memdc.SelectObject(wxNullBitmap);
dc.DrawBitmap(bmp, 0, 0);
#else
doRender(dc);
#endif
}
void MultiMachineItem::DrawTextWithEllipsis(wxDC& dc, const wxString& text, int maxWidth, int left, int top) {
wxSize size = GetSize();
wxFont font = dc.GetFont();
wxSize textSize = dc.GetTextExtent(text);
dc.SetTextForeground(StateColor::darkModeColorFor(wxColour(50, 58, 61)));
int textWidth = textSize.GetWidth();
if (textWidth > maxWidth) {
wxString truncatedText = text;
int ellipsisWidth = dc.GetTextExtent("...").GetWidth();
int numChars = text.length();
for (int i = numChars - 1; i >= 0; --i) {
truncatedText = text.substr(0, i) + "...";
int truncatedWidth = dc.GetTextExtent(truncatedText).GetWidth();
if (truncatedWidth <= maxWidth - ellipsisWidth) {
break;
}
}
if (top == 0) {
dc.DrawText(truncatedText, left, (size.y - textSize.y) / 2);
}
else {
dc.DrawText(truncatedText, left, (size.y - textSize.y) / 2 - top);
}
}
else {
if (top == 0) {
dc.DrawText(text, left, (size.y - textSize.y) / 2);
}
else {
dc.DrawText(text, left, (size.y - textSize.y) / 2 - top);
}
}
}
void MultiMachineItem::doRender(wxDC& dc)
{
wxSize size = GetSize();
dc.SetPen(wxPen(*wxBLACK));
int left = FromDIP(DEVICE_LEFT_PADDING_LEFT);
if (obj_) {
//dev name
wxString dev_name = wxString::FromUTF8(obj_->dev_name);
if (!obj_->is_online()) {
dev_name = dev_name + "(" + _L("Offline") + ")";
}
dc.SetFont(Label::Body_13);
DrawTextWithEllipsis(dc, dev_name, FromDIP(DEVICE_LEFT_DEV_NAME), left);
left += FromDIP(DEVICE_LEFT_DEV_NAME);
//project name
wxString project_name = _L("No task");
if (obj_->is_in_printing()) {
project_name = wxString::Format("%s", GUI::from_u8(obj_->subtask_name));
}
dc.SetFont(Label::Body_13);
DrawTextWithEllipsis(dc, project_name, FromDIP(DEVICE_LEFT_PRO_NAME), left);
left += FromDIP(DEVICE_LEFT_PRO_NAME);
//state
dc.SetFont(Label::Body_13);
if (state_device == 0) {
dc.SetTextForeground(*wxBLACK);
DrawTextWithEllipsis(dc, get_state_device(), FromDIP(DEVICE_LEFT_PRO_INFO), left);
}
else if (state_device == 1) {
dc.SetTextForeground(wxColour(0,174,66));
DrawTextWithEllipsis(dc, get_state_device(), FromDIP(DEVICE_LEFT_PRO_INFO), left);
}
else if (state_device == 2)
{
dc.SetTextForeground(wxColour(208,27,27));
DrawTextWithEllipsis(dc, get_state_device(), FromDIP(DEVICE_LEFT_PRO_INFO), left);
}
else if (state_device > 2 && state_device < 7) {
dc.SetFont(Label::Body_12);
dc.SetTextForeground(wxColour(0, 174, 66));
if (obj_->get_curr_stage().IsEmpty() && obj_->subtask_) {
//wxString layer_info = wxString::Format(_L("Layer: %d/%d"), obj_->curr_layer, obj_->total_layers);
wxString progress_info = wxString::Format("%d", obj_->subtask_->task_progress);
wxString left_time = wxString::Format("%s", get_left_time(obj_->mc_left_time));
DrawTextWithEllipsis(dc, progress_info + "% | " + left_time, FromDIP(DEVICE_LEFT_PRO_INFO), left, FromDIP(10));
dc.SetPen(wxPen(wxColour(233,233,233)));
dc.SetBrush(wxBrush(wxColour(233,233,233)));
dc.DrawRoundedRectangle(left, FromDIP(30), FromDIP(DEVICE_LEFT_PRO_INFO), FromDIP(10), 2);
dc.SetPen(wxPen(wxColour(0, 174, 66)));
dc.SetBrush(wxBrush(wxColour(0, 174, 66)));
dc.DrawRoundedRectangle(left, FromDIP(30), FromDIP(DEVICE_LEFT_PRO_INFO) * (static_cast<float>(obj_->subtask_->task_progress) / 100.0f), FromDIP(10), 2);
}
else {
DrawTextWithEllipsis(dc, obj_->get_curr_stage(), FromDIP(DEVICE_LEFT_PRO_INFO), left);
}
}
else {
dc.SetTextForeground(*wxBLACK);
DrawTextWithEllipsis(dc, get_state_device(), FromDIP(DEVICE_LEFT_PRO_INFO), left);
}
left += FromDIP(DEVICE_LEFT_PRO_INFO);
//button
dc.SetPen(wxPen(wxColour(38, 46, 48)));
dc.SetBrush(wxBrush(wxColour(*wxWHITE)));
dc.DrawRoundedRectangle(left, (size.y - FromDIP(38)) / 2, FromDIP(90), FromDIP(38), 6);
dc.SetFont(Label::Body_14);
dc.SetTextForeground(*wxBLACK);
dc.DrawText(_L("View"),left + FromDIP(90) / 2 - dc.GetTextExtent(_L("View")).x / 2, (size.y -dc.GetTextExtent(_L("View")).y) / 2);
}
if (m_hover) {
dc.SetPen(wxPen(wxColour(0, 174, 66)));
dc.SetBrush(*wxTRANSPARENT_BRUSH);
dc.DrawRoundedRectangle(0, 0, size.x, size.y, 3);
}
}
void MultiMachineItem::post_event(wxCommandEvent&& event)
{
event.SetEventObject(this);
event.SetString(obj_->dev_id);
event.SetInt(state_selected);
wxPostEvent(this, event);
}
void MultiMachineItem::DoSetSize(int x, int y, int width, int height, int sizeFlags /*= wxSIZE_AUTO*/)
{
wxWindow::DoSetSize(x, y, width, height, sizeFlags);
}
wxString MultiMachineItem::get_left_time(int mc_left_time)
{
// update gcode progress
std::string left_time;
wxString left_time_text = _L("N/A");
try {
left_time = get_bbl_monitor_time_dhm(mc_left_time);
}
catch (...) {
;
}
if (!left_time.empty()) left_time_text = wxString::Format("-%s", left_time);
return left_time_text;
}
MultiMachineManagerPage::MultiMachineManagerPage(wxWindow* parent)
: wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL)
{
#ifdef __WINDOWS__
SetDoubleBuffered(true);
#endif //__WINDOWS__
SetBackgroundColour(wxColour(0xEEEEEE));
m_main_panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
m_main_panel->SetBackgroundColour(*wxWHITE);
m_main_sizer = new wxBoxSizer(wxVERTICAL);
StateColor head_bg(
std::pair<wxColour, int>(TABLE_HEAD_PRESSED_COLOUR, StateColor::Pressed),
std::pair<wxColour, int>(TABLE_HEAR_NORMAL_COLOUR, StateColor::Normal)
);
m_table_head_panel = new wxPanel(m_main_panel, wxID_ANY, wxDefaultPosition, wxDefaultSize);
m_table_head_panel->SetMinSize(wxSize(FromDIP(DEVICE_ITEM_MAX_WIDTH), -1));
m_table_head_panel->SetMaxSize(wxSize(FromDIP(DEVICE_ITEM_MAX_WIDTH), -1));
m_table_head_panel->SetBackgroundColour(TABLE_HEAR_NORMAL_COLOUR);
m_table_head_sizer = new wxBoxSizer(wxHORIZONTAL);
m_printer_name = new Button(m_table_head_panel, _L("Device Name"), "toolbar_double_directional_arrow", wxNO_BORDER, ICON_SIZE);
m_printer_name->SetBackgroundColor(head_bg);
m_printer_name->SetFont(TABLE_HEAD_FONT);
m_printer_name->SetCornerRadius(0);
m_printer_name->SetMinSize(wxSize(FromDIP(DEVICE_LEFT_DEV_NAME), FromDIP(DEVICE_ITEM_MAX_HEIGHT)));
m_printer_name->SetMaxSize(wxSize(FromDIP(DEVICE_LEFT_DEV_NAME), FromDIP(DEVICE_ITEM_MAX_HEIGHT)));
m_printer_name->SetCenter(false);
m_printer_name->Bind(wxEVT_ENTER_WINDOW, [&](wxMouseEvent& evt) {
SetCursor(wxCURSOR_HAND);
});
m_printer_name->Bind(wxEVT_LEAVE_WINDOW, [&](wxMouseEvent& evt) {
SetCursor(wxCURSOR_ARROW);
});
m_printer_name->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& evt) {
device_dev_name_big = !device_dev_name_big;
auto sortcb = [this](ObjState s1, ObjState s2) {
return device_dev_name_big ? s1.state_dev_name > s2.state_dev_name : s1.state_dev_name < s2.state_dev_name;
};
this->m_sort.set_role(sortcb, SortItem::SR_MACHINE_NAME, device_dev_name_big);
this->refresh_user_device();
});
m_task_name = new Button(m_table_head_panel, _L("Task Name"), "", wxNO_BORDER, ICON_SIZE);
m_task_name->SetBackgroundColor(TABLE_HEAR_NORMAL_COLOUR);
m_task_name->SetFont(TABLE_HEAD_FONT);
m_task_name->SetCornerRadius(0);
m_task_name->SetMinSize(wxSize(FromDIP(DEVICE_LEFT_DEV_NAME), FromDIP(DEVICE_ITEM_MAX_HEIGHT)));
m_task_name->SetMaxSize(wxSize(FromDIP(DEVICE_LEFT_DEV_NAME), FromDIP(DEVICE_ITEM_MAX_HEIGHT)));
m_task_name->SetCenter(false);
m_status = new Button(m_table_head_panel, _L("Device Status"), "toolbar_double_directional_arrow", wxNO_BORDER, ICON_SIZE);
m_status->SetBackgroundColor(head_bg);
m_status->SetFont(TABLE_HEAD_FONT);
m_status->SetCornerRadius(0);
m_status->SetMinSize(wxSize(FromDIP(DEVICE_LEFT_PRO_INFO), FromDIP(DEVICE_ITEM_MAX_HEIGHT)));
m_status->SetMaxSize(wxSize(FromDIP(DEVICE_LEFT_PRO_INFO), FromDIP(DEVICE_ITEM_MAX_HEIGHT)));
m_status->SetCenter(false);
m_status->Bind(wxEVT_ENTER_WINDOW, [&](wxMouseEvent& evt) {
SetCursor(wxCURSOR_HAND);
});
m_status->Bind(wxEVT_LEAVE_WINDOW, [&](wxMouseEvent& evt) {
SetCursor(wxCURSOR_ARROW);
});
m_status->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& evt) {
device_state_big = !device_state_big;
auto sortcb = [this](ObjState s1, ObjState s2) {
return device_state_big ? s1.state_device > s2.state_device : s1.state_device < s2.state_device;
};
this->m_sort.set_role(sortcb, SortItem::SortRule::SR_MACHINE_STATE, device_state_big);
this->refresh_user_device();
});
m_action = new Button(m_table_head_panel, _L("Actions"), "", wxNO_BORDER, ICON_SIZE, false);
m_action->SetBackgroundColor(TABLE_HEAR_NORMAL_COLOUR);
m_action->SetFont(TABLE_HEAD_FONT);
m_action->SetCornerRadius(0);
m_action->SetMinSize(wxSize(FromDIP(DEVICE_LEFT_PRO_NAME), FromDIP(DEVICE_ITEM_MAX_HEIGHT)));
m_action->SetMaxSize(wxSize(FromDIP(DEVICE_LEFT_PRO_NAME), FromDIP(DEVICE_ITEM_MAX_HEIGHT)));
m_action->SetCenter(false);
m_table_head_sizer->AddSpacer(FromDIP(DEVICE_LEFT_PADDING_LEFT));
m_table_head_sizer->Add(m_printer_name, 0, wxALIGN_CENTER_VERTICAL, 0);
m_table_head_sizer->Add(m_task_name, 0, wxALIGN_CENTER_VERTICAL, 0);
m_table_head_sizer->Add(m_status, 0, wxALIGN_CENTER_VERTICAL, 0);
m_table_head_sizer->Add(m_action, 0, wxLEFT, 0);
m_table_head_panel->SetSizer(m_table_head_sizer);
m_table_head_panel->Layout();
m_tip_text = new wxStaticText(m_main_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER);
m_tip_text->SetMinSize(wxSize(FromDIP(DEVICE_ITEM_MAX_WIDTH), -1));
m_tip_text->SetMaxSize(wxSize(FromDIP(DEVICE_ITEM_MAX_WIDTH), -1));
m_tip_text->SetLabel(_L("Unconnected device"));
m_tip_text->SetForegroundColour(wxColour(50, 58, 61));
m_tip_text->SetFont(::Label::Head_24);
m_tip_text->Wrap(-1);
m_machine_list = new wxScrolledWindow(m_main_panel, wxID_ANY, wxDefaultPosition, wxDefaultSize);
m_machine_list->SetBackgroundColour(*wxWHITE);
m_machine_list->SetScrollRate(0, 5);
m_machine_list->SetMinSize(wxSize(FromDIP(DEVICE_ITEM_MAX_WIDTH), 10 * FromDIP(DEVICE_ITEM_MAX_HEIGHT)));
m_machine_list->SetMaxSize(wxSize(FromDIP(DEVICE_ITEM_MAX_WIDTH), 10 * FromDIP(DEVICE_ITEM_MAX_HEIGHT)));
m_sizer_machine_list = new wxBoxSizer(wxVERTICAL);
m_machine_list->SetSizer(m_sizer_machine_list);
m_machine_list->Layout();
// add flipping page
m_flipping_panel = new wxPanel(m_main_panel, wxID_ANY, wxDefaultPosition, wxDefaultSize);
m_flipping_panel->SetMinSize(wxSize(FromDIP(DEVICE_ITEM_MAX_WIDTH), -1));
m_flipping_panel->SetMaxSize(wxSize(FromDIP(DEVICE_ITEM_MAX_WIDTH), -1));
m_flipping_panel->SetBackgroundColour(*wxWHITE);
m_flipping_page_sizer = new wxBoxSizer(wxHORIZONTAL);
m_page_sizer = new wxBoxSizer(wxVERTICAL);
btn_last_page = new Button(m_flipping_panel, "", "go_last_plate", 0, ICON_SIZE);
btn_last_page->SetMinSize(wxSize(ICON_SIZE, ICON_SIZE));
btn_last_page->SetMaxSize(wxSize(ICON_SIZE, ICON_SIZE));
btn_last_page->SetBackgroundColor(head_bg);
btn_last_page->Bind(wxEVT_LEFT_DOWN, [&](wxMouseEvent& evt) {
btn_last_page->Enable(false);
btn_next_page->Enable(false);
start_timer();
m_current_page--;
if (m_current_page < 0)
m_current_page = 0;
refresh_user_device();
update_page_number();
});
btn_next_page = new Button(m_flipping_panel, "", "go_next_plate", 0, ICON_SIZE);
btn_next_page->SetMinSize(wxSize(ICON_SIZE, ICON_SIZE));
btn_next_page->SetMaxSize(wxSize(ICON_SIZE, ICON_SIZE));
btn_next_page->SetBackgroundColor(head_bg);
btn_next_page->Bind(wxEVT_LEFT_DOWN, [&](wxMouseEvent& evt) {
btn_last_page->Enable(false);
btn_next_page->Enable(false);
start_timer();
m_current_page++;
if (m_current_page > m_total_count)
m_current_page = m_total_count;
refresh_user_device();
update_page_number();
});
st_page_number = new wxStaticText(m_flipping_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize);
m_flipping_page_sizer->Add(0, 0, 1, wxEXPAND, 0);
m_flipping_page_sizer->Add(btn_last_page, 0, wxALIGN_CENTER, 0);
m_flipping_page_sizer->Add(st_page_number, 0, wxALIGN_CENTER, 0);
m_flipping_page_sizer->Add(btn_next_page, 0, wxALIGN_CENTER, 0);
m_page_sizer->Add(m_flipping_page_sizer, 0, wxALIGN_CENTER_HORIZONTAL, FromDIP(5));
m_flipping_panel->SetSizer(m_page_sizer);
m_flipping_panel->Layout();
m_main_sizer->AddSpacer(FromDIP(50));
m_main_sizer->Add(m_table_head_panel, 0, wxALIGN_CENTER_HORIZONTAL, 0);
m_main_sizer->Add(m_tip_text, 0, wxALIGN_CENTER_HORIZONTAL | wxTOP, FromDIP(50));
m_main_sizer->Add(m_machine_list, 0, wxALIGN_CENTER_HORIZONTAL, 0);
m_main_sizer->Add(m_flipping_panel, 0, wxALIGN_CENTER_HORIZONTAL, 0);
m_main_panel->SetSizer(m_main_sizer);
m_main_panel->Layout();
page_sizer = new wxBoxSizer(wxVERTICAL);
page_sizer->Add(m_main_panel, 1, wxALL | wxEXPAND, FromDIP(25));
SetSizer(page_sizer);
Layout();
Fit();
Bind(wxEVT_TIMER, &MultiMachineManagerPage::on_timer, this);
}
void MultiMachineManagerPage::update_page()
{
for (int i = 0; i < m_device_items.size(); i++) {
m_device_items[i]->sync_state();
m_device_items[i]->Refresh();
}
}
void MultiMachineManagerPage::refresh_user_device(bool clear)
{
m_sizer_machine_list->Clear(true);
m_device_items.clear();
if(clear) return;
Slic3r::DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
if (!dev) return;
auto user_machine = dev->get_my_cloud_machine_list();
m_total_count = user_machine.size();
m_state_objs.clear();
for (auto it = user_machine.begin(); it != user_machine.end(); ++it) {
sync_state(it->second);
}
//sort
if (m_sort.rule != SortItem::SortRule::SR_None) {
std::sort(m_state_objs.begin(), m_state_objs.end(), m_sort.get_machine_call_back());
}
double result = static_cast<double>(user_machine.size()) / m_count_page_item;
m_total_page = std::ceil(result);
std::vector<ObjState> sort_devices = extractRange(m_state_objs, m_current_page * m_count_page_item, (m_current_page + 1) * m_count_page_item - 1 );
std::vector<std::string> subscribe_list;
for (auto i = 0; i < sort_devices.size(); ++i) {
auto dev_id = sort_devices[i].dev_id;
auto machine = user_machine[dev_id];
MultiMachineItem* di = new MultiMachineItem(m_machine_list, machine);
m_device_items.push_back(di);
m_sizer_machine_list->Add(m_device_items[i], 0, wxALL | wxEXPAND, 0);
subscribe_list.push_back(dev_id);
}
dev->subscribe_device_list(subscribe_list);
m_tip_text->Show(m_device_items.empty());
update_page_number();
m_flipping_panel->Show(m_total_page > 1);
m_sizer_machine_list->Layout();
Layout();
}
std::vector<ObjState> MultiMachineManagerPage::extractRange(const std::vector<ObjState>& source, int start, int end) {
std::vector<ObjState> result;
if (start < 0 || start > end || source.size() <= 0) {
return result;
}
if ( end >= source.size() ) {
end = source.size();
}
auto startIter = source.begin() + start;
auto endIter = source.begin() + end;
result.assign(startIter, endIter);
return result;
}
void MultiMachineManagerPage::sync_state(MachineObject* obj_)
{
ObjState state_obj;
if (obj_) {
state_obj.dev_id = obj_->dev_id;
state_obj.state_dev_name = obj_->dev_name;
if (obj_->print_status == "IDLE") {
state_obj.state_device = 0;
}
else if (obj_->print_status == "FINISH") {
state_obj.state_device = 1;
}
else if (obj_->print_status == "FAILED") {
state_obj.state_device = 2;
}
else if (obj_->print_status == "RUNNING") {
state_obj.state_device = 3;
}
else if (obj_->print_status == "PAUSE") {
state_obj.state_device = 4;
}
else if (obj_->print_status == "PREPARE") {
state_obj.state_device = 5;
}
else if (obj_->print_status == "SLICING") {
state_obj.state_device = 6;
}
else {
state_obj.state_device = 7;
}
}
m_state_objs.push_back(state_obj);
}
bool MultiMachineManagerPage::Show(bool show)
{
if (show) {
refresh_user_device();
}
else {
Slic3r::DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
if (dev) {
dev->subscribe_device_list(std::vector<std::string>());
}
}
return wxPanel::Show(show);
}
void MultiMachineManagerPage::start_timer()
{
if (m_flipping_timer) {
m_flipping_timer->Stop();
}
else {
m_flipping_timer = new wxTimer();
}
m_flipping_timer->SetOwner(this);
m_flipping_timer->Start(1000);
wxPostEvent(this, wxTimerEvent());
}
void MultiMachineManagerPage::update_page_number()
{
double result = static_cast<double>(m_total_count) / m_count_page_item;
m_total_page = std::ceil(result);
wxString number = wxString(std::to_string(m_current_page + 1)) + " / " + wxString(std::to_string(m_total_page));
st_page_number->SetLabel(number);
m_current_page <= 0 ? btn_last_page->Enable(false) : btn_last_page->Enable(true);
m_current_page >= (m_total_page - 1) ? btn_next_page->Enable(false) : btn_next_page->Enable(true);
}
void MultiMachineManagerPage::on_timer(wxTimerEvent& event)
{
m_flipping_timer->Stop();
if (btn_last_page)
btn_last_page->Enable(true);
if (btn_next_page)
btn_next_page->Enable(true);
}
void MultiMachineManagerPage::clear_page()
{
}
} // namespace GUI
} // namespace Slic3r

View File

@ -0,0 +1,107 @@
#ifndef slic3r_MultiMachineMangerPage_hpp_
#define slic3r_MultiMachineMangerPage_hpp_
#include "GUI_Utils.hpp"
#include "MultiMachine.hpp"
namespace Slic3r {
namespace GUI {
#define DEVICE_LEFT_PADDING_LEFT 15
#define DEVICE_LEFT_DEV_NAME 180
#define DEVICE_LEFT_PRO_NAME 180
#define DEVICE_LEFT_PRO_INFO 250
class MultiMachineItem : public DeviceItem
{
public:
MultiMachineItem(wxWindow* parent, MachineObject* obj);
~MultiMachineItem() {};
void OnEnterWindow(wxMouseEvent& evt);
void OnLeaveWindow(wxMouseEvent& evt);
void OnLeftDown(wxMouseEvent& evt);
void OnMove(wxMouseEvent& evt);
void paintEvent(wxPaintEvent& evt);
void render(wxDC& dc);
void DrawTextWithEllipsis(wxDC& dc, const wxString& text, int maxWidth, int left, int top = 0);
void doRender(wxDC& dc);
void post_event(wxCommandEvent&& event);
virtual void DoSetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO);
public:
bool m_hover{ false };
ScalableBitmap m_bitmap_check_disable;
ScalableBitmap m_bitmap_check_off;
ScalableBitmap m_bitmap_check_on;
wxString get_left_time(int mc_left_time);
};
class MultiMachineManagerPage : public wxPanel
{
public:
MultiMachineManagerPage(wxWindow* parent);
~MultiMachineManagerPage() {};
void update_page();
void refresh_user_device(bool clear = false);
void sync_state(MachineObject* obj_);
bool Show(bool show);
std::vector<ObjState> extractRange(const std::vector<ObjState>& source, int start, int end);
void start_timer();
void update_page_number();
void on_timer(wxTimerEvent& event);
void clear_page();
private:
std::vector<ObjState> m_state_objs;
std::vector<MultiMachineItem*> m_device_items;
SortItem m_sort;
bool device_dev_name_big{ true };
bool device_state_big{ true };
wxBoxSizer* page_sizer{ nullptr };
wxPanel* m_main_panel{ nullptr };
wxBoxSizer* m_main_sizer{nullptr};
wxBoxSizer* m_sizer_machine_list{nullptr};
wxScrolledWindow* m_machine_list{ nullptr };
wxStaticText* m_selected_num{ nullptr };
// table head
wxPanel* m_table_head_panel{ nullptr };
wxBoxSizer* m_table_head_sizer{ nullptr };
Button* m_printer_name{ nullptr };
Button* m_task_name{ nullptr };
Button* m_status{ nullptr };
Button* m_action{ nullptr };
Button* m_stop_all_botton{nullptr};
// tip when no device
wxStaticText* m_tip_text{ nullptr };
// Flipping pages
int m_current_page{ 0 };
int m_total_page{ 0 };
int m_total_count{ 0 };
int m_count_page_item{ 10 };
bool prev{ false };
bool next{ false };
Button* btn_last_page{ nullptr };
Button* btn_next_page{ nullptr };
wxStaticText* st_page_number{ nullptr };
wxBoxSizer* m_flipping_page_sizer{ nullptr };
wxBoxSizer* m_page_sizer{ nullptr };
wxPanel* m_flipping_panel{ nullptr };
wxTimer* m_flipping_timer{ nullptr };
};
} // namespace GUI
} // namespace Slic3r
#endif

View File

@ -0,0 +1,103 @@
#include "MultiMachinePage.hpp"
namespace Slic3r {
namespace GUI {
MultiMachinePage::MultiMachinePage(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
: wxPanel(parent, id, pos, size, style)
{
init_tabpanel();
m_main_sizer = new wxBoxSizer(wxHORIZONTAL);
m_main_sizer->Add(m_tabpanel, 1, wxEXPAND | wxLEFT, 0);
SetSizerAndFit(m_main_sizer);
Layout();
Fit();
wxGetApp().UpdateDarkUIWin(this);
init_timer();
Bind(wxEVT_TIMER, &MultiMachinePage::on_timer, this);
}
MultiMachinePage::~MultiMachinePage()
{
if (m_refresh_timer)
m_refresh_timer->Stop();
delete m_refresh_timer;
}
void MultiMachinePage::jump_to_send_page()
{
m_tabpanel->SetSelection(1);
}
void MultiMachinePage::on_sys_color_changed()
{
}
void MultiMachinePage::msw_rescale()
{
}
bool MultiMachinePage::Show(bool show)
{
if (show) {
m_refresh_timer->Stop();
m_refresh_timer->SetOwner(this);
m_refresh_timer->Start(4000);
wxPostEvent(this, wxTimerEvent());
}
else {
m_refresh_timer->Stop();
}
auto page = m_tabpanel->GetCurrentPage();
if (page)
page->Show(show);
return wxPanel::Show(show);
}
void MultiMachinePage::init_tabpanel()
{
auto m_side_tools = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(220), FromDIP(18)));
wxBoxSizer* sizer_side_tools = new wxBoxSizer(wxHORIZONTAL);
sizer_side_tools->Add(m_side_tools, 1, wxEXPAND, 0);
m_tabpanel = new Tabbook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, sizer_side_tools, wxNB_LEFT | wxTAB_TRAVERSAL | wxNB_NOPAGETHEME);
m_tabpanel->SetBackgroundColour(wxColour("#FEFFFF"));
m_tabpanel->Bind(wxEVT_BOOKCTRL_PAGE_CHANGED, [this](wxBookCtrlEvent& e) {; });
m_local_task_manager = new LocalTaskManagerPage(m_tabpanel);
m_cloud_task_manager = new CloudTaskManagerPage(m_tabpanel);
m_machine_manager = new MultiMachineManagerPage(m_tabpanel);
m_tabpanel->AddPage(m_machine_manager, _L("Device"), "", true);
m_tabpanel->AddPage(m_local_task_manager, _L("Task Sending"), "", false);
m_tabpanel->AddPage(m_cloud_task_manager, _L("Task Sent"), "", false);
}
void MultiMachinePage::init_timer()
{
m_refresh_timer = new wxTimer();
//m_refresh_timer->SetOwner(this);
//m_refresh_timer->Start(8000);
//wxPostEvent(this, wxTimerEvent());
}
void MultiMachinePage::on_timer(wxTimerEvent& event)
{
m_local_task_manager->update_page();
m_cloud_task_manager->update_page();
m_machine_manager->update_page();
}
void MultiMachinePage::clear_page()
{
m_local_task_manager->refresh_user_device(true);
m_cloud_task_manager->refresh_user_device(true);
m_machine_manager->refresh_user_device(true);
}
} // namespace GUI
} // namespace Slic3r

View File

@ -0,0 +1,45 @@
#ifndef slic3r_MultiMachinePage_hpp_
#define slic3r_MultiMachinePage_hpp_
#include "libslic3r/libslic3r.h"
#include "GUI_App.hpp"
#include "GUI_Utils.hpp"
#include "MultiTaskManagerPage.hpp"
#include "MultiMachineManagerPage.hpp"
#include "Tabbook.hpp"
#include "wx/button.h"
namespace Slic3r {
namespace GUI {
class MultiMachinePage : public wxPanel
{
private:
wxTimer* m_refresh_timer = nullptr;
wxSizer* m_main_sizer{ nullptr };
LocalTaskManagerPage* m_local_task_manager{ nullptr };
CloudTaskManagerPage* m_cloud_task_manager{ nullptr };
MultiMachineManagerPage* m_machine_manager{ nullptr };
Tabbook* m_tabpanel{ nullptr };
public:
MultiMachinePage(wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxTAB_TRAVERSAL);
~MultiMachinePage();
void jump_to_send_page();
void on_sys_color_changed();
void msw_rescale();
bool Show(bool show);
void init_tabpanel();
void init_timer();
void on_timer(wxTimerEvent& event);
void clear_page();
};
} // namespace GUI
} // namespace Slic3r
#endif

View File

@ -0,0 +1,7 @@
#include "MultiPrintJob.hpp"
namespace Slic3r {
namespace GUI {
} // namespace GUI
} // namespace Slic3r

View File

@ -0,0 +1,10 @@
#ifndef slic3r_MultiPrintJob_hpp_
#define slic3r_MultiPrintJob_hpp_
namespace Slic3r {
namespace GUI {
} // namespace GUI
} // namespace Slic3r
#endif

View File

@ -0,0 +1,33 @@
#include "MultiSendMachineModel.hpp"
namespace Slic3r {
namespace GUI {
MultiSendMachineModel::MultiSendMachineModel()
{
;
}
MultiSendMachineModel::~MultiSendMachineModel()
{
;
}
void MultiSendMachineModel::Init()
{
;
}
wxDataViewItem MultiSendMachineModel::AddMachine(MachineObject* obj)
{
wxString name = from_u8(obj->dev_name);
wxDataViewItem new_item;
// TODO
return new_item;
}
} // namespace GUI
} // namespace Slic3r

View File

@ -0,0 +1,25 @@
#ifndef slic3r_MultiSendMachineModel_hpp_
#define slic3r_MultiSendMachineModel_hpp_
#include "DeviceManager.hpp"
namespace Slic3r {
namespace GUI {
class MultiSendMachineModel : public wxDataViewModel
{
public:
MultiSendMachineModel();
~MultiSendMachineModel();
void Init();
wxDataViewItem AddMachine(MachineObject* obj);
private:
};
} // namespace GUI
} // namespace Slic3r
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,202 @@
#ifndef slic3r_MultiTaskManagerPage_hpp_
#define slic3r_MultiTaskManagerPage_hpp_
#include "GUI_App.hpp"
#include "GUI_Utils.hpp"
#include "MultiMachine.hpp"
#include "DeviceManager.hpp"
#include "TaskManager.hpp"
#include "Widgets/Label.hpp"
#include "Widgets/Button.hpp"
#include "Widgets/CheckBox.hpp"
#include "Widgets/ComboBox.hpp"
#include "Widgets/ScrolledWindow.hpp"
#include "Widgets/PopupWindow.hpp"
#include "Widgets/TextInput.hpp"
namespace Slic3r {
namespace GUI {
#define CLOUD_TASK_ITEM_MAX_WIDTH 1100
#define TASK_ITEM_MAX_WIDTH 900
#define TASK_LEFT_PADDING_LEFT 15
#define TASK_LEFT_PRINTABLE 40
#define TASK_LEFT_PRO_NAME 180
#define TASK_LEFT_DEV_NAME 150
#define TASK_LEFT_PRO_STATE 170
#define TASK_LEFT_PRO_INFO 230
#define TASK_LEFT_SEND_TIME 180
class MultiTaskItem : public DeviceItem
{
public:
MultiTaskItem(wxWindow* parent, MachineObject* obj, int type);
~MultiTaskItem() {};
void OnEnterWindow(wxMouseEvent& evt);
void OnLeaveWindow(wxMouseEvent& evt);
void OnSelectedDevice(wxCommandEvent& evt);
void OnLeftDown(wxMouseEvent& evt);
void OnMove(wxMouseEvent& evt);
void paintEvent(wxPaintEvent& evt);
void render(wxDC& dc);
void doRender(wxDC& dc);
void DrawTextWithEllipsis(wxDC& dc, const wxString& text, int maxWidth, int left, int top = 0);
void post_event(wxCommandEvent&& event);
virtual void DoSetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO);
bool m_hover{ false };
wxString get_left_time(int mc_left_time);
ScalableBitmap m_bitmap_check_disable;
ScalableBitmap m_bitmap_check_off;
ScalableBitmap m_bitmap_check_on;
int m_sending_percent{0};
int m_task_type{0}; //0-local 1-cloud
wxString m_project_name;
wxString m_dev_name;
std::string m_dev_id;
TaskStateInfo* task_obj { nullptr };
std::string m_job_id;
//std::string m_sent_time;
Button* m_button_resume{ nullptr };
Button* m_button_cancel{ nullptr };
Button* m_button_pause{ nullptr };
Button* m_button_stop{ nullptr };
void update_info();
void onPause();
void onResume();
void onStop();
void onCancel();
};
class LocalTaskManagerPage : public wxPanel
{
public:
LocalTaskManagerPage(wxWindow* parent);
~LocalTaskManagerPage() {};
void update_page();
void refresh_user_device(bool clear = false);
bool Show(bool show);
void cancel_all(wxCommandEvent& evt);
private:
SortItem m_sort;
std::map<std::string, MultiTaskItem*> m_task_items;
bool device_name_big{ true };
bool device_state_big{ true };
bool device_send_time{ true };
wxPanel* m_main_panel{ nullptr };
wxBoxSizer* m_main_sizer{ nullptr };
wxBoxSizer* page_sizer{ nullptr };
wxBoxSizer* m_sizer_task_list{ nullptr };
wxScrolledWindow* m_task_list{ nullptr };
wxStaticText* m_selected_num{ nullptr };
// table head
wxPanel* m_table_head_panel{ nullptr };
wxBoxSizer* m_table_head_sizer{ nullptr };
CheckBox* m_select_checkbox{ nullptr };
Button* m_task_name{ nullptr };
Button* m_printer_name{ nullptr };
Button* m_status{ nullptr };
Button* m_info{ nullptr };
Button* m_send_time{ nullptr };
Button* m_action{ nullptr };
// ctrl button for all
int m_sel_number{0};
wxPanel* m_ctrl_btn_panel{ nullptr };
wxBoxSizer* m_btn_sizer{ nullptr };
Button* btn_stop_all{ nullptr };
wxStaticText* m_sel_text{ nullptr };
// tip when no device
wxStaticText* m_tip_text{ nullptr };
};
class CloudTaskManagerPage : public wxPanel
{
public:
CloudTaskManagerPage(wxWindow* parent);
~CloudTaskManagerPage();
void update_page();
void refresh_user_device(bool clear = false);
std::string utc_time_to_date(std::string utc_time);
bool Show(bool show);
void update_page_number();
void start_timer();
void on_timer(wxTimerEvent& event);
void pause_all(wxCommandEvent& evt);
void resume_all(wxCommandEvent& evt);
void stop_all(wxCommandEvent& evt);
private:
SortItem m_sort;
bool device_name_big{ true };
bool device_state_big{ true };
bool device_send_time{ true };
/* job_id -> sel */
std::map <std::string, MultiTaskItem*> m_task_items;
wxPanel* m_main_panel{ nullptr };
wxBoxSizer* page_sizer{ nullptr };
wxBoxSizer* m_sizer_task_list{ nullptr };
wxBoxSizer* m_main_sizer{ nullptr };
wxScrolledWindow* m_task_list{ nullptr };
wxStaticText* m_selected_num{ nullptr };
// Flipping pages
int m_current_page{ 0 };
int m_total_page{0};
int m_total_count{ 0 };
int m_count_page_item{ 10 };
bool prev{ false };
bool next{ false };
Button* btn_last_page{ nullptr };
Button* btn_next_page{ nullptr };
wxStaticText* st_page_number{ nullptr };
wxBoxSizer* m_flipping_page_sizer{ nullptr };
wxBoxSizer* m_page_sizer{ nullptr };
wxPanel* m_flipping_panel{ nullptr };
wxTimer* m_flipping_timer{ nullptr };
// table head
wxPanel* m_table_head_panel{ nullptr };
wxBoxSizer* m_table_head_sizer{ nullptr };
CheckBox* m_select_checkbox{ nullptr };
Button* m_task_name{ nullptr };
Button* m_printer_name{ nullptr };
Button* m_status{ nullptr };
Button* m_info{ nullptr };
Button* m_send_time{ nullptr };
Button* m_action{ nullptr };
// ctrl button for all
int m_sel_number;
wxPanel* m_ctrl_btn_panel{ nullptr };
wxBoxSizer* m_btn_sizer{ nullptr };
Button* btn_pause_all{ nullptr };
Button* btn_continue_all{ nullptr };
Button* btn_stop_all{ nullptr };
wxStaticText* m_sel_text{ nullptr };
// tip when no device
wxStaticText* m_tip_text{ nullptr };
};
} // namespace GUI
} // namespace Slic3r
#endif

View File

@ -0,0 +1,6 @@
namespace Slic3r {
namespace GUI {
} // namespace GUI
} // namespace Slic3r

View File

@ -0,0 +1,11 @@
#ifndef slic3r_MultiTaskModel_hpp_
#define slic3r_MultiTaskModel_hpp_
namespace Slic3r {
namespace GUI {
} // namespace GUI
} // namespace Slic3r
#endif

View File

@ -89,6 +89,7 @@
#include "Jobs/NotificationProgressIndicator.hpp"
#include "BackgroundSlicingProcess.hpp"
#include "SelectMachine.hpp"
#include "SendMultiMachinePage.hpp"
#include "SendToPrinter.hpp"
#include "PublishDialog.hpp"
#include "ModelMall.hpp"
@ -2153,6 +2154,7 @@ struct Plater::priv
MenuFactory menus;
SelectMachineDialog* m_select_machine_dlg = nullptr;
SendMultiMachinePage* m_send_multi_dlg = nullptr;
SendToPrinterDialog* m_send_to_sdcard_dlg = nullptr;
PublishDialog *m_publish_dlg = nullptr;
@ -2664,6 +2666,7 @@ struct Plater::priv
//BBS: add popup object table logic
bool PopupObjectTable(int object_id, int volume_id, const wxPoint& position);
void on_action_send_to_printer(bool isall = false);
void on_action_send_to_multi_machine(SimpleEvent&);
int update_print_required_data(Slic3r::DynamicPrintConfig config, Slic3r::Model model, Slic3r::PlateDataPtrs plate_data_list, std::string file_name, std::string file_path);
private:
bool layers_height_allowed() const;
@ -2704,7 +2707,6 @@ private:
//record print preset
void record_start_print_preset(std::string action);
};
const std::regex Plater::priv::pattern_bundle(".*[.](amf|amf[.]xml|zip[.]amf|3mf)", std::regex::icase);
@ -3028,6 +3030,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
q->Bind(EVT_GLTOOLBAR_EXPORT_ALL_SLICED_FILE, &priv::on_action_export_all_sliced_file, this);
q->Bind(EVT_GLTOOLBAR_SEND_TO_PRINTER, &priv::on_action_export_to_sdcard, this);
q->Bind(EVT_GLTOOLBAR_SEND_TO_PRINTER_ALL, &priv::on_action_export_to_sdcard_all, this);
q->Bind(EVT_GLTOOLBAR_PRINT_MULTI_MACHINE, &priv::on_action_send_to_multi_machine, this);
q->Bind(EVT_GLCANVAS_PLATE_SELECT, &priv::on_plate_selected, this);
q->Bind(EVT_DOWNLOAD_PROJECT, &priv::on_action_download_project, this);
q->Bind(EVT_IMPORT_MODEL_ID, &priv::on_action_request_model_id, this);
@ -6949,6 +6952,14 @@ void Plater::priv::on_action_print_plate(SimpleEvent&)
record_start_print_preset("print_plate");
}
void Plater::priv::on_action_send_to_multi_machine(SimpleEvent&)
{
if (!m_send_multi_dlg)
m_send_multi_dlg = new SendMultiMachinePage(q);
m_send_multi_dlg->prepare(partplate_list.get_curr_plate_index());
m_send_multi_dlg->ShowModal();
}
void Plater::priv::on_action_print_plate_from_sdcard(SimpleEvent&)
{
if (q != nullptr) {
@ -6981,6 +6992,7 @@ void Plater::priv::on_action_send_to_printer(bool isall)
m_send_to_sdcard_dlg->ShowModal();
}
void Plater::priv::on_action_select_sliced_plate(wxCommandEvent &evt)
{
if (q != nullptr) {
@ -7051,7 +7063,6 @@ void Plater::priv::on_action_export_to_sdcard_all(SimpleEvent&)
}
}
//BBS: add plate select logic
void Plater::priv::on_plate_selected(SimpleEvent&)
{

View File

@ -1038,6 +1038,7 @@ wxWindow* PreferencesDialog::create_general_page()
//auto item_hints = create_item_checkbox(_L("Show \"Tip of the day\" notification after start"), page, _L("If enabled, useful hints are displayed at startup."), 50, "show_hints");
auto item_calc_mode = create_item_checkbox(_L("Flushing volumes: Auto-calculate every time when the color is changed."), page, _L("If enabled, auto-calculate every time when the color is changed."), 50, "auto_calculate");
auto item_calc_in_long_retract = create_item_checkbox(_L("Flushing volumes: Auto-calculate every time when the filament is changed."), page, _L("If enabled, auto-calculate every time when filament is changed"), 50, "auto_calculate_when_filament_change");
auto item_multi_machine = create_item_checkbox(_L("Multi-device Management(Take effect after restarting Studio)."), page, _L("With this option enabled, you can send a task to multiple devices at the same time and manage multiple devices."), 50, "enable_multi_machine");
auto title_presets = create_item_title(_L("Presets"), page, _L("Presets"));
auto item_user_sync = create_item_checkbox(_L("Auto sync user presets(Printer/Filament/Process)"), page, _L("User Sync"), 50, "sync_user_preset");
auto item_system_sync = create_item_checkbox(_L("Update built-in Presets automatically."), page, _L("System Sync"), 50, "sync_system_preset");
@ -1105,6 +1106,7 @@ wxWindow* PreferencesDialog::create_general_page()
//sizer_page->Add(item_hints, 0, wxTOP, FromDIP(3));
sizer_page->Add(item_calc_mode, 0, wxTOP, FromDIP(3));
sizer_page->Add(item_calc_in_long_retract, 0, wxTOP, FromDIP(3));
sizer_page->Add(item_multi_machine, 0, wxTOP, FromDIP(3));
sizer_page->Add(title_presets, 0, wxTOP | wxEXPAND, FromDIP(20));
sizer_page->Add(item_user_sync, 0, wxTOP, FromDIP(3));
sizer_page->Add(item_system_sync, 0, wxTOP, FromDIP(3));

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,207 @@
#ifndef slic3r_SendMultiMachinePage_hpp_
#define slic3r_SendMultiMachinePage_hpp_
#include "GUI_Utils.hpp"
#include "MultiMachine.hpp"
#include "DeviceManager.hpp"
#include "Widgets/Label.hpp"
#include "Widgets/Button.hpp"
#include "Widgets/CheckBox.hpp"
#include "Widgets/ComboBox.hpp"
#include "Widgets/ScrolledWindow.hpp"
#include "Widgets/PopupWindow.hpp"
#include "Widgets/TextInput.hpp"
#include "AmsMappingPopup.hpp"
#include "SelectMachine.hpp"
namespace Slic3r {
namespace GUI {
#define SEND_LEFT_PADDING_LEFT 15
#define SEND_LEFT_PRINTABLE 40
#define SEND_LEFT_DEV_NAME 250
#define SEND_LEFT_DEV_STATUS 250
#define SEND_LEFT_TAKS_STATUS 180
#define DESIGN_SELECTOR_NOMORE_COLOR wxColour(248, 248, 248)
#define DESIGN_GRAY900_COLOR wxColour(38, 46, 48)
#define DESIGN_GRAY800_COLOR wxColour(50, 58, 61)
#define DESIGN_GRAY600_COLOR wxColour(144, 144, 144)
#define DESIGN_GRAY400_COLOR wxColour(166, 169, 170)
#define DESIGN_RESOUTION_PREFERENCES wxSize(FromDIP(540), -1)
#define DESIGN_COMBOBOX_SIZE wxSize(FromDIP(140), -1)
#define DESIGN_LARGE_COMBOBOX_SIZE wxSize(FromDIP(160), -1)
#define DESIGN_INPUT_SIZE wxSize(FromDIP(50), -1)
#define MATERIAL_ITEM_SIZE wxSize(FromDIP(64), FromDIP(34))
#define MATERIAL_ITEM_REAL_SIZE wxSize(FromDIP(62), FromDIP(32))
#define MAPPING_ITEM_REAL_SIZE wxSize(FromDIP(48), FromDIP(45))
#define THUMBNAIL_SIZE FromDIP(128)
class RadioBox;
class AmsRadioSelector
{
public:
wxString m_param_name;
int m_groupid;
RadioBox* m_radiobox;
bool m_selected = false;
};
WX_DECLARE_LIST(AmsRadioSelector, AmsRadioSelectorList);
class SendDeviceItem : public DeviceItem
{
public:
SendDeviceItem(wxWindow* parent, MachineObject* obj);
~SendDeviceItem() {};
void DrawTextWithEllipsis(wxDC& dc, const wxString& text, int maxWidth, int left, int top = 0);
void OnEnterWindow(wxMouseEvent& evt);
void OnLeaveWindow(wxMouseEvent& evt);
void OnSelectedDevice(wxCommandEvent& evt);
void OnLeftDown(wxMouseEvent& evt);
void OnMove(wxMouseEvent& evt);
void paintEvent(wxPaintEvent& evt);
void render(wxDC& dc);
void doRender(wxDC& dc);
void post_event(wxCommandEvent&& event);
virtual void DoSetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO);
public:
bool m_hover{false};
ScalableBitmap m_bitmap_check_disable;
ScalableBitmap m_bitmap_check_off;
ScalableBitmap m_bitmap_check_on;
};
class Plater;
class SendMultiMachinePage : public DPIDialog
{
private:
/* dev_id -> device_item */
std::map<std::string, SendDeviceItem*> m_device_items;
wxTimer* m_refresh_timer = nullptr;
// sort
SortItem m_sort;
bool device_name_big{ true };
bool device_printable_big{ true };
bool device_en_ams_big{ true };
Button* m_button_send{ nullptr };
wxScrolledWindow* scroll_macine_list{ nullptr };
wxBoxSizer* sizer_machine_list{ nullptr };
Plater* m_plater{ nullptr };
int m_print_plate_idx;
bool m_is_canceled{ false };
bool m_export_3mf_cancel{ false };
AppConfig* app_config;
wxPanel* m_main_page{ nullptr };
wxScrolledWindow* m_main_scroll{ nullptr };
wxBoxSizer* m_sizer_body{ nullptr };
wxGridSizer* m_ams_list_sizer{ nullptr };
AmsMapingPopup* m_mapping_popup{ nullptr };
AmsRadioSelectorList m_radio_group;
MaterialHash m_material_list;
std::map<std::string, CheckBox*> m_checkbox_map;
std::map<std::string, TextInput*> m_input_map;
std::vector<FilamentInfo> m_filaments;
std::vector<FilamentInfo> m_ams_mapping_result;
int m_current_filament_id{ 0 };
StateColor btn_bg_enable;
// table head
wxPanel* m_table_head_panel{ nullptr };
wxBoxSizer* m_table_head_sizer{ nullptr };
CheckBox* m_select_checkbox{ nullptr };
Button* m_printer_name{ nullptr };
Button* m_device_status{ nullptr };
//Button* m_task_status{ nullptr };
Button* m_ams{ nullptr };
Button* m_refresh_button{ nullptr };
// rename
wxSimplebook* m_rename_switch_panel{ nullptr };
wxPanel* m_rename_normal_panel{ nullptr };
wxPanel* m_rename_edit_panel{ nullptr };
TextInput* m_rename_input{ nullptr };
ScalableButton* m_rename_button{ nullptr };
wxBoxSizer* rename_sizer_v{ nullptr };
wxBoxSizer* rename_sizer_h{ nullptr };
wxStaticText* m_task_name{ nullptr };
wxString m_current_project_name;
bool m_is_rename_mode{ false };
// title and thumbnail
wxPanel* m_title_panel{ nullptr };
wxBoxSizer* m_title_sizer{ nullptr };
wxBoxSizer* m_text_sizer{ nullptr };
ScalableBitmap* m_print_time{ nullptr };
wxStaticBitmap* m_time_img{ nullptr };
wxStaticText* m_stext_time{ nullptr };
wxStaticText* m_stext_weight{ nullptr };
wxStaticBitmap* timeimg{ nullptr };
ScalableBitmap* print_time{ nullptr };
wxStaticBitmap* weightimg{ nullptr };
ScalableBitmap* print_weight{ nullptr };
wxBoxSizer* m_thumbnail_sizer{ nullptr };
ThumbnailPanel* m_thumbnail_panel{nullptr};
// tip when no device
wxStaticText* m_tip_text{ nullptr };
public:
SendMultiMachinePage(Plater* plater = nullptr);
~SendMultiMachinePage();
void prepare(int plate_idx);
void on_dpi_changed(const wxRect& suggested_rect);
void on_sys_color_changed();
void refresh_user_device();
void on_send(wxCommandEvent& event);
bool Show(bool show);
BBL::PrintParams request_params(MachineObject* obj);
bool get_ams_mapping_result(std::string& mapping_array_str, std::string& ams_mapping_info);
wxBoxSizer* create_item_title(wxString title, wxWindow* parent, wxString tooltip);
wxBoxSizer* create_item_checkbox(wxString title, wxWindow* parent, wxString tooltip, int padding_left, std::string param);
wxBoxSizer* create_item_input(wxString str_before, wxString str_after, wxWindow* parent, wxString tooltip, std::string param);
wxBoxSizer* create_item_radiobox(wxString title, wxWindow* parent, wxString tooltip, int groupid, std::string param);
wxPanel* create_page();
void sync_ams_list();
void set_default_normal(const ThumbnailData& data);
void set_default();
void on_rename_enter();
void check_fcous_state(wxWindow* window);
void check_focus(wxWindow* window);
protected:
void OnSelectRadio(wxMouseEvent& event);
void on_select_radio(std::string param);
bool get_value_radio(std::string param);
void on_set_finish_mapping(wxCommandEvent& evt);
void on_rename_click(wxCommandEvent& event);
void on_timer(wxTimerEvent& event);
void init_timer();
private:
};
} // namespace GUI
} // namespace Slic3r
#endif

View File

@ -0,0 +1,378 @@
#include "TaskManager.hpp"
#include "libslic3r/Thread.hpp"
#include "nlohmann/json.hpp"
using namespace nlohmann;
namespace Slic3r {
int TaskManager::MaxSendingAtSameTime = 5;
int TaskManager::SendingInterval = 180;
std::string get_task_state_enum_str(TaskState ts)
{
switch (ts) {
case TaskState::TS_PENDING:
return "task pending";
case TaskState::TS_SENDING:
return "task sending";
case TaskState::TS_SEND_COMPLETED:
return "task sending completed";
case TaskState::TS_SEND_CANCELED:
return "task sending canceled";
case TaskState::TS_SEND_FAILED:
return "task sending failed";
case TaskState::TS_PRINTING:
return "task printing";
case TaskState::TS_PRINT_SUCCESS:
return "task print success";
case TaskState::TS_PRINT_FAILED:
return "task print failed";
case TaskState::TS_IDLE:
return "task idle";
case TaskState::TS_REMOVED:
return "task removed";
default:
assert(false);
}
return "unknown task state";
}
TaskState parse_task_status(int status)
{
switch (status)
{
case 1:
return TaskState::TS_PRINTING;
case 2:
return TaskState::TS_PRINT_SUCCESS;
case 3:
return TaskState::TS_PRINT_FAILED;
case 4:
return TaskState::TS_PRINTING;
default:
return TaskState::TS_PRINTING;
}
return TaskState::TS_PRINTING;
}
int TaskStateInfo::g_task_info_id = 0;
TaskStateInfo::TaskStateInfo(BBL::PrintParams param)
: m_state(TaskState::TS_PENDING)
, m_params(param)
, m_sending_percent(0)
, m_state_changed_fn(nullptr)
, m_cancel(false)
{
task_info_id = ++TaskStateInfo::g_task_info_id;
this->set_task_name(param.project_name);
this->set_device_name(param.dev_name);
cancel_fn = [this]() {
return m_cancel;
};
update_status_fn = [this](int stage, int code, std::string msg) {
const int StagePercentPoint[(int)PrintingStageFinished + 1] = {
10, // PrintingStageCreate
25, // PrintingStageUpload
70, // PrintingStageWaiting
75, // PrintingStageRecord
90, // PrintingStageSending
95, // PrintingStageFinished
100 // PrintingStageFinished
};
BOOST_LOG_TRIVIAL(trace) << "task_manager: update task, " << m_params.dev_id << ", stage = " << stage << "code = " << code;
// update current percnet
int curr_percent = 0;
if (stage >= 0 && stage <= (int)PrintingStageFinished) {
curr_percent = StagePercentPoint[stage];
if ((stage == BBL::SendingPrintJobStage::PrintingStageUpload
|| stage == BBL::SendingPrintJobStage::PrintingStageRecord)
&& (code > 0 && code <= 100)) {
curr_percent = (StagePercentPoint[stage + 1] - StagePercentPoint[stage]) * code / 100 + StagePercentPoint[stage];
BOOST_LOG_TRIVIAL(trace) << "task_manager: percent = " << curr_percent;
}
}
BOOST_LOG_TRIVIAL(trace) << "task_manager: update task, curr_percent = " << curr_percent;
update_sending_percent(curr_percent);
};
wait_fn = [this](int status, std::string job_info) {
BOOST_LOG_TRIVIAL(info) << "task_manager: get_job_info = " << job_info;
m_job_id = job_info;
return true;
};
}
void TaskStateInfo::cancel()
{
m_cancel = true;
if (m_state == TaskState::TS_PENDING)
m_state = TaskState::TS_REMOVED;
update();
}
bool TaskGroup::need_schedule(std::chrono::system_clock::time_point last, TaskStateInfo* task)
{
/* only pending task will be scheduled */
if (task->state() != TaskState::TS_PENDING)
return false;
std::chrono::system_clock::time_point curr_time = std::chrono::system_clock::now();
auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(curr_time - last);
if (diff.count() > TaskManager::SendingInterval * 1000) {
BOOST_LOG_TRIVIAL(trace) << "task_manager: diff count = " << diff.count() << " milliseconds";
return true;
}
return false;
}
void TaskManager::set_max_send_at_same_time(int count)
{
TaskManager::MaxSendingAtSameTime = count;
}
TaskManager::TaskManager(NetworkAgent* agent)
:m_agent(agent)
{
;
}
int TaskManager::start_print(const std::vector<BBL::PrintParams>& params, TaskSettings* settings)
{
BOOST_LOG_TRIVIAL(info) << "task_manager: start_print size = " << params.size();
TaskManager::MaxSendingAtSameTime = settings->max_sending_at_same_time;
TaskManager::SendingInterval = settings->sending_interval;
m_map_mutex.lock();
TaskGroup task_group(*settings);
task_group.tasks.reserve(params.size());
for (auto it = params.begin(); it != params.end(); it++) {
TaskStateInfo* new_item = new TaskStateInfo(*it);
task_group.append(new_item);
}
m_cache_map.push_back(task_group);
m_map_mutex.unlock();
return 0;
}
static int start_print_test(BBL::PrintParams& params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn)
{
int tick = 2;
for (int i = 0; i < 100 * tick; i++) {
boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
if (cancel_fn) {
if (cancel_fn()) {
return -1;
}
}
if (i == tick) {
if (update_fn) update_fn(PrintingStageCreate, 0, "");
}
if (i >= 20 * tick && i <= 70 * tick) {
int percent = (i - 20 * tick) * 2 / tick;
if (update_fn) update_fn(PrintingStageUpload, percent, "");
}
if (i == 80 * tick)
if (update_fn) update_fn(PrintingStageSending, 0, "");
if (i == 99 * tick)
if (update_fn) update_fn(PrintingStageFinished, 0, "");
}
return 0;
}
int TaskManager::schedule(TaskStateInfo* task)
{
if (!m_agent) {
assert(false);
return -1;
}
if (task->state() != TaskState::TS_PENDING)
return 0;
assert(task->state() == TaskState::TS_PENDING);
task->set_state(TaskState::TS_SENDING);
BOOST_LOG_TRIVIAL(trace) << "task_manager: schedule a task to dev_id = " << task->params().dev_id;
boost::thread* new_sending_thread = new boost::thread();
*new_sending_thread = Slic3r::create_thread(
[this, task] {
if (!m_agent) {
BOOST_LOG_TRIVIAL(trace) << "task_manager: NetworkAgent is nullptr";
return;
}
assert(m_agent);
// DEBUG FOR TEST
#if 0
int result = start_print_test(task->get_params(), task->update_status_fn, task->cancel_fn, task->wait_fn);
#else
int result = m_agent->start_print(task->get_params(), task->update_status_fn, task->cancel_fn, task->wait_fn);
#endif
if (result == 0) {
last_sent_timestamp = std::chrono::system_clock::now();
task->set_sent_time(last_sent_timestamp);
task->set_state(TaskState::TS_SEND_COMPLETED);
}
else {
if (!task->is_canceled()) {
task->set_state(TaskState::TS_SEND_FAILED);
} else {
task->set_state(TaskState::TS_SEND_CANCELED);
}
}
/* remove from sending task list */
m_scedule_mutex.lock();
auto it = std::find(m_scedule_list.begin(), m_scedule_list.end(), task);
if (it != m_scedule_list.end()) {
BOOST_LOG_TRIVIAL(trace) << "task_manager: schedule, scedule task has removed from list";
m_scedule_list.erase(it);
}
else {
/*assert(false);*/
}
m_scedule_mutex.unlock();
}
);
m_sending_thread_list.push_back(new_sending_thread);
return 0;
}
void TaskManager::start()
{
if (m_started) {
return;
}
m_started = true;
m_scedule_thread = Slic3r::create_thread(
[this] {
BOOST_LOG_TRIVIAL(trace) << "task_manager: thread start()";
while (m_started) {
m_map_mutex.lock();
for (auto it = m_cache_map.begin(); it != m_cache_map.end(); it++) {
for (auto iter = it->tasks.begin(); iter != it->tasks.end(); iter++) {
m_scedule_mutex.lock();
if (m_scedule_list.size() < TaskManager::MaxSendingAtSameTime
&& it->need_schedule(last_sent_timestamp, *iter)) {
m_scedule_list.push_back(*iter);
}
m_scedule_mutex.unlock();
}
}
m_map_mutex.unlock();
if (!m_scedule_list.empty()) {
//BOOST_LOG_TRIVIAL(trace) << "task_manager: need scedule task count = " << m_scedule_list.size();
m_scedule_mutex.lock();
for (auto it = m_scedule_list.begin(); it != m_scedule_list.end(); it++) {
this->schedule(*it);
}
m_scedule_mutex.unlock();
}
boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
}
BOOST_LOG_TRIVIAL(trace) << "task_manager: thread exit()";
});
}
void TaskManager::stop()
{
m_started = false;
if (m_scedule_thread.joinable())
m_scedule_thread.join();
}
std::map<std::string, TaskStateInfo*> TaskManager::get_local_task_list()
{
std::map<std::string, TaskStateInfo*> out;
m_map_mutex.lock();
for (auto it = m_cache_map.begin(); it != m_cache_map.end(); it++) {
for (auto iter = (*it).tasks.begin(); iter != (*it).tasks.end(); iter++) {
if ((*iter)->state() == TaskState::TS_PENDING
|| (*iter)->state() == TaskState::TS_SENDING
|| (*iter)->state() == TaskState::TS_SEND_CANCELED
|| (*iter)->state() == TaskState::TS_SEND_COMPLETED
|| (*iter)->state() == TaskState::TS_SEND_FAILED) {
out.insert(std::make_pair(std::to_string((*iter)->task_info_id), *iter));
}
}
}
m_map_mutex.unlock();
return out;
}
std::map<std::string, TaskStateInfo> TaskManager::get_task_list(int curr_page, int page_count, int& total)
{
std::map<std::string, TaskStateInfo> out;
if (m_agent) {
BBL::TaskQueryParams task_query_params;
task_query_params.limit = page_count;
task_query_params.offset = curr_page * page_count;
std::string task_info;
int result = m_agent->get_user_tasks(task_query_params, &task_info);
BOOST_LOG_TRIVIAL(trace) << "task_manager: get_task_list task_info=" << task_info;
if (result == 0) {
try {
json j = json::parse(task_info);
if (j.contains("total")) {
total = j["total"].get<int>();
}
if (!j.contains("hits")) {
return out;
}
BOOST_LOG_TRIVIAL(trace) << "task_manager: get_task_list task count =" << j["hits"].size();
for (auto& hit : j["hits"]) {
TaskStateInfo task_info;
if (hit.contains("title"))
task_info.set_task_name(hit["title"].get<std::string>());
if (hit.contains("deviceName"))
task_info.set_device_name(hit["deviceName"].get<std::string>());
if (hit.contains("deviceId"))
task_info.params().dev_id = hit["deviceId"].get<std::string>();
if (hit.contains("id"))
task_info.set_job_id(std::to_string(hit["id"].get<int64_t>()));
if (hit.contains("status"))
task_info.set_state(parse_task_status(hit["status"].get<int>()));
if (hit.contains("cover"))
task_info.thumbnail_url = hit["cover"].get<std::string>();
if (hit.contains("startTime"))
task_info.start_time = hit["startTime"].get<std::string>();
if (hit.contains("endTime"))
task_info.end_time = hit["endTime"].get<std::string>();
if (hit.contains("profileId"))
task_info.profile_id = std::to_string(hit["profileId"].get<int64_t>());
if (!task_info.get_job_id().empty())
out.insert(std::make_pair(task_info.get_job_id(), task_info));
}
}
catch(...) {
}
}
}
return out;
}
TaskState TaskManager::query_task_state(std::string dev_id)
{
/* priority: TS_SENDING > TS_PENDING > TS_IDLE */
TaskState ts = TaskState::TS_IDLE;
m_map_mutex.lock();
for (auto& task_group : m_cache_map) {
for (auto it = task_group.tasks.begin(); it != task_group.tasks.end(); it++) {
if ((*it)->params().dev_id == dev_id) {
if ((*it)->state() == TS_SENDING) {
m_map_mutex.unlock();
return TS_SENDING;
} else if ((*it)->state() == TS_PENDING) {
ts = TS_PENDING;
}
}
}
}
m_map_mutex.unlock();
return ts;
}
} // namespace Slic3r

View File

@ -0,0 +1,180 @@
#ifndef slic3r_TaskManager_hpp_
#define slic3r_TaskManager_hpp_
#include "DeviceManager.hpp"
#include <boost/date_time/posix_time/posix_time.hpp>
namespace Slic3r {
enum TaskState
{
TS_PENDING = 0,
TS_SENDING,
TS_SEND_COMPLETED,
TS_SEND_CANCELED,
TS_SEND_FAILED,
TS_PRINTING,
/* queray in Machine Object: IDLE, PREPARE, RUNNING, PAUSE, FINISH, FAILED, SLICING */
TS_PRINT_SUCCESS,
TS_PRINT_FAILED,
TS_REMOVED,
TS_IDLE,
};
std::string get_task_state_enum_str(TaskState ts);
class TaskStateInfo
{
public:
static int g_task_info_id;
typedef std::function<void(TaskState state, int percent)> StateChangedFn;
TaskStateInfo(const BBL::PrintParams param);
TaskStateInfo() {
task_info_id = ++TaskStateInfo::g_task_info_id;
}
TaskState state() { return m_state; }
void set_state(TaskState ts) {
BOOST_LOG_TRIVIAL(trace) << "TaskStateInfo set state = " << get_task_state_enum_str(ts);
m_state = ts;
if (m_state_changed_fn) {
m_state_changed_fn(m_state, m_sending_percent);
}
}
BBL::PrintParams get_params() { return m_params; }
BBL::PrintParams& params() { return m_params; }
std::string get_job_id(){return profile_id;}
void update_sending_percent(int percent) {
m_sending_percent = percent;
update();
}
void set_sent_time(std::chrono::system_clock::time_point time) {
sent_time = time;
update();
}
void set_state_changed_fn(StateChangedFn fn) {
m_state_changed_fn = fn;
update();
}
void set_cancel_fn(WasCancelledFn fn) {
cancel_fn = fn;
}
void set_task_name(std::string name) { m_task_name = name; }
void set_device_name(std::string name) { m_device_name = name; }
void set_job_id(std::string job_id) { m_job_id = job_id; }
void update() {
if (m_state_changed_fn) {
m_state_changed_fn(m_state, m_sending_percent);
}
}
void cancel();
bool is_canceled() { return m_cancel; }
std::string get_device_name() {return m_device_name;};
std::string get_task_name() {return m_task_name;};
std::string get_sent_time() {
std::time_t time = std::chrono::system_clock::to_time_t(sent_time);
std::tm* timeInfo = std::localtime(&time);
std::stringstream ss;
ss << std::put_time(timeInfo, "%Y-%m-%d %H:%M:%S");
std::string str = ss.str();
return str;
};
/* sending timelapse */
std::chrono::system_clock::time_point sent_time;
WasCancelledFn cancel_fn;
OnUpdateStatusFn update_status_fn;
OnWaitFn wait_fn;
std::string thumbnail_url;
std::string start_time;
std::string end_time;
std::string profile_id;
int task_info_id;
private:
bool m_cancel;
TaskState m_state;
std::string m_task_name;
std::string m_device_name;
BBL::PrintParams m_params;
int m_sending_percent;
std::string m_job_id;
StateChangedFn m_state_changed_fn;
};
class TaskSettings
{
public:
int sending_interval { 180 }; /* sending a job every 60 seconds */
int max_sending_at_same_time { 1 };
};
class TaskGroup
{
public:
std::vector<TaskStateInfo*> tasks;
TaskSettings settings;
TaskGroup(TaskSettings s)
: settings(s)
{
}
void append(TaskStateInfo* task) {
this->tasks.push_back(task);
}
bool need_schedule(std::chrono::system_clock::time_point last, TaskStateInfo* task);
};
class TaskManager
{
public:
static int MaxSendingAtSameTime;
static int SendingInterval;
TaskManager(NetworkAgent* agent);
int start_print(const std::vector<BBL::PrintParams>& params, TaskSettings* settings = nullptr);
static void set_max_send_at_same_time(int count);
void start();
void stop();
std::map<std::string, TaskStateInfo*> get_local_task_list();
/* curr_page is start with 0 */
std::map<std::string, TaskStateInfo> get_task_list(int curr_page, int page_count, int& total);
TaskState query_task_state(std::string dev_id);
private:
int schedule(TaskStateInfo* task);
boost::thread m_scedule_thread;
std::vector<TaskGroup> m_cache_map;
std::mutex m_map_mutex;
/* sending task list */
std::vector<TaskStateInfo*> m_scedule_list;
std::vector<boost::thread*> m_sending_thread_list;
std::mutex m_scedule_mutex;
bool m_started { false };
NetworkAgent* m_agent { nullptr };
std::chrono::system_clock::time_point last_sent_timestamp;
};
} // namespace Slic3r
#endif

View File

@ -0,0 +1,5 @@
#include "UserNotification.hpp"
namespace Slic3r {
} // namespace Slic3r

View File

@ -0,0 +1,20 @@
#ifndef slic3r_UserNotification_hpp_
#define slic3r_UserNotification_hpp_
namespace Slic3r {
enum class UserNotificationStyle {
UNS_NORMAL,
UNS_WARNING_CONFIRM,
};
class UserNotification
{
public:
UserNotification() {}
};
} // namespace Slic3r
#endif

View File

@ -144,6 +144,11 @@ void Button::SetValue(bool state)
bool Button::GetValue() const { return state_handler.states() & StateHandler::Checked; }
void Button::SetCenter(bool isCenter)
{
this->isCenter = isCenter;
}
void Button::Rescale()
{
if (this->active_icon.bmp().IsOk())
@ -200,9 +205,11 @@ void Button::render(wxDC& dc)
}
// move to center
wxRect rcContent = { {0, 0}, size };
wxSize offset = (size - szContent) / 2;
if (offset.x < 0) offset.x = 0;
rcContent.Deflate(offset.x, offset.y);
if (isCenter) {
wxSize offset = (size - szContent) / 2;
if (offset.x < 0) offset.x = 0;
rcContent.Deflate(offset.x, offset.y);
}
// start draw
wxPoint pt = rcContent.GetLeftTop();
if (icon.bmp().IsOk()) {

View File

@ -17,6 +17,7 @@ class Button : public StaticBox
bool pressedDown = false;
bool m_selected = true;
bool canFocus = true;
bool isCenter = true;
static const int buttonWidth = 200;
static const int buttonHeight = 50;
@ -54,6 +55,8 @@ public:
bool GetValue() const;
void SetCenter(bool isCenter);
void Rescale();
protected:

View File

@ -52,6 +52,11 @@ func_is_server_connected NetworkAgent::is_server_connected_ptr = null
func_refresh_connection NetworkAgent::refresh_connection_ptr = nullptr;
func_start_subscribe NetworkAgent::start_subscribe_ptr = nullptr;
func_stop_subscribe NetworkAgent::stop_subscribe_ptr = nullptr;
func_add_subscribe NetworkAgent::add_subscribe_ptr = nullptr;
func_del_subscribe NetworkAgent::del_subscribe_ptr = nullptr;
func_enable_multi_machine NetworkAgent::enable_multi_machine_ptr = nullptr;
func_start_device_subscribe NetworkAgent::start_device_subscribe_ptr = nullptr;
func_stop_device_subscribe NetworkAgent::stop_device_subscribe_ptr = nullptr;
func_send_message NetworkAgent::send_message_ptr = nullptr;
func_connect_printer NetworkAgent::connect_printer_ptr = nullptr;
func_disconnect_printer NetworkAgent::disconnect_printer_ptr = nullptr;
@ -88,6 +93,7 @@ func_set_extra_http_header NetworkAgent::set_extra_http_header_ptr = nu
func_get_my_message NetworkAgent::get_my_message_ptr = nullptr;
func_check_user_task_report NetworkAgent::check_user_task_report_ptr = nullptr;
func_get_user_print_info NetworkAgent::get_user_print_info_ptr = nullptr;
func_get_user_tasks NetworkAgent::get_user_tasks_ptr = nullptr;
func_get_printer_firmware NetworkAgent::get_printer_firmware_ptr = nullptr;
func_get_task_plate_index NetworkAgent::get_task_plate_index_ptr = nullptr;
func_get_user_info NetworkAgent::get_user_info_ptr = nullptr;
@ -215,6 +221,11 @@ int NetworkAgent::initialize_network_module(bool using_backup)
refresh_connection_ptr = reinterpret_cast<func_refresh_connection>(get_network_function("bambu_network_refresh_connection"));
start_subscribe_ptr = reinterpret_cast<func_start_subscribe>(get_network_function("bambu_network_start_subscribe"));
stop_subscribe_ptr = reinterpret_cast<func_stop_subscribe>(get_network_function("bambu_network_stop_subscribe"));
add_subscribe_ptr = reinterpret_cast<func_add_subscribe>(get_network_function("bambu_network_add_subscribe"));
del_subscribe_ptr = reinterpret_cast<func_del_subscribe>(get_network_function("bambu_network_del_subscribe"));
enable_multi_machine_ptr = reinterpret_cast<func_enable_multi_machine>(get_network_function("bambu_network_enable_multi_machine"));
start_device_subscribe_ptr = reinterpret_cast<func_start_device_subscribe>(get_network_function("bambu_network_start_device_subscribe"));
stop_device_subscribe_ptr = reinterpret_cast<func_stop_device_subscribe>(get_network_function("bambu_network_stop_device_subscribe"));
send_message_ptr = reinterpret_cast<func_send_message>(get_network_function("bambu_network_send_message"));
connect_printer_ptr = reinterpret_cast<func_connect_printer>(get_network_function("bambu_network_connect_printer"));
disconnect_printer_ptr = reinterpret_cast<func_disconnect_printer>(get_network_function("bambu_network_disconnect_printer"));
@ -251,6 +262,7 @@ int NetworkAgent::initialize_network_module(bool using_backup)
get_my_message_ptr = reinterpret_cast<func_get_my_message>(get_network_function("bambu_network_get_my_message"));
check_user_task_report_ptr = reinterpret_cast<func_check_user_task_report>(get_network_function("bambu_network_check_user_task_report"));
get_user_print_info_ptr = reinterpret_cast<func_get_user_print_info>(get_network_function("bambu_network_get_user_print_info"));
get_user_tasks_ptr = reinterpret_cast<func_get_user_tasks>(get_network_function("bambu_network_get_user_tasks"));
get_printer_firmware_ptr = reinterpret_cast<func_get_printer_firmware>(get_network_function("bambu_network_get_printer_firmware"));
get_task_plate_index_ptr = reinterpret_cast<func_get_task_plate_index>(get_network_function("bambu_network_get_task_plate_index"));
get_user_info_ptr = reinterpret_cast<func_get_user_info>(get_network_function("bambu_network_get_user_info"));
@ -369,6 +381,7 @@ int NetworkAgent::unload_network_module()
get_my_message_ptr = nullptr;
check_user_task_report_ptr = nullptr;
get_user_print_info_ptr = nullptr;
get_user_tasks_ptr = nullptr;
get_printer_firmware_ptr = nullptr;
get_task_plate_index_ptr = nullptr;
get_user_info_ptr = nullptr;
@ -721,6 +734,57 @@ int NetworkAgent::stop_subscribe(std::string module)
return ret;
}
int NetworkAgent::add_subscribe(std::vector<std::string> dev_list)
{
int ret = 0;
if (network_agent && add_subscribe_ptr) {
ret = add_subscribe_ptr(network_agent, dev_list);
if (ret)
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%") % network_agent % ret;
}
return ret;
}
int NetworkAgent::del_subscribe(std::vector<std::string> dev_list)
{
int ret = 0;
if (network_agent && del_subscribe_ptr) {
ret = del_subscribe_ptr(network_agent, dev_list);
if (ret)
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%") % network_agent % ret;
}
return ret;
}
void NetworkAgent::enable_multi_machine(bool enable)
{
if (network_agent && enable_multi_machine_ptr) {
enable_multi_machine_ptr(network_agent, enable);
}
}
int NetworkAgent::start_device_subscribe()
{
int ret = 0;
if (network_agent && start_device_subscribe_ptr) {
ret = start_device_subscribe_ptr(network_agent);
if (ret)
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%") % network_agent % ret;
}
return ret;
}
int NetworkAgent::stop_device_subscribe()
{
int ret = 0;
if (network_agent && stop_device_subscribe_ptr) {
ret = stop_device_subscribe_ptr(network_agent);
if (ret)
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%") % network_agent % ret;
}
return ret;
}
int NetworkAgent::send_message(std::string dev_id, std::string json_str, int qos)
{
int ret = 0;
@ -959,13 +1023,13 @@ int NetworkAgent::start_local_print_with_record(PrintParams params, OnUpdateStat
int NetworkAgent::start_send_gcode_to_sdcard(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn)
{
int ret = 0;
if (network_agent && start_send_gcode_to_sdcard_ptr) {
ret = start_send_gcode_to_sdcard_ptr(network_agent, params, update_fn, cancel_fn, wait_fn);
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(" : network_agent=%1%, ret=%2%, dev_id=%3%, task_name=%4%, project_name=%5%")
% network_agent % ret % params.dev_id % params.task_name % params.project_name;
}
return ret;
int ret = 0;
if (network_agent && start_send_gcode_to_sdcard_ptr) {
ret = start_send_gcode_to_sdcard_ptr(network_agent, params, update_fn, cancel_fn, wait_fn);
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(" : network_agent=%1%, ret=%2%, dev_id=%3%, task_name=%4%, project_name=%5%")
% network_agent % ret % params.dev_id % params.task_name % params.project_name;
}
return ret;
}
int NetworkAgent::start_local_print(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn)
@ -1095,6 +1159,16 @@ int NetworkAgent::get_user_print_info(unsigned int* http_code, std::string* http
return ret;
}
int NetworkAgent::get_user_tasks(TaskQueryParams params, std::string* http_body)
{
int ret = 0;
if (network_agent && get_user_tasks_ptr) {
ret = get_user_tasks_ptr(network_agent, params, http_body);
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%, http_body=%3%") % network_agent % ret % (*http_body);
}
return ret;
}
int NetworkAgent::get_printer_firmware(std::string dev_id, unsigned* http_code, std::string* http_body)
{
int ret = 0;

View File

@ -32,6 +32,11 @@ typedef bool (*func_is_server_connected)(void *agent);
typedef int (*func_refresh_connection)(void *agent);
typedef int (*func_start_subscribe)(void *agent, std::string module);
typedef int (*func_stop_subscribe)(void *agent, std::string module);
typedef int (*func_add_subscribe)(void *agent, std::vector<std::string> dev_list);
typedef int (*func_del_subscribe)(void *agent, std::vector<std::string> dev_list);
typedef void (*func_enable_multi_machine)(void *agent, bool enable);
typedef int (*func_start_device_subscribe)(void* agent);
typedef int (*func_stop_device_subscribe)(void* agent);
typedef int (*func_send_message)(void *agent, std::string dev_id, std::string json_str, int qos);
typedef int (*func_connect_printer)(void *agent, std::string dev_id, std::string dev_ip, std::string username, std::string password, bool use_ssl);
typedef int (*func_disconnect_printer)(void *agent);
@ -68,6 +73,7 @@ typedef int (*func_set_extra_http_header)(void *agent, std::map<std::string, std
typedef int (*func_get_my_message)(void *agent, int type, int after, int limit, unsigned int* http_code, std::string* http_body);
typedef int (*func_check_user_task_report)(void *agent, int* task_id, bool* printable);
typedef int (*func_get_user_print_info)(void *agent, unsigned int* http_code, std::string* http_body);
typedef int (*func_get_user_tasks)(void *agent, TaskQueryParams params, std::string* http_body);
typedef int (*func_get_printer_firmware)(void *agent, std::string dev_id, unsigned* http_code, std::string* http_body);
typedef int (*func_get_task_plate_index)(void *agent, std::string task_id, int* plate_index);
typedef int (*func_get_user_info)(void *agent, int* identifier);
@ -139,6 +145,11 @@ public:
int refresh_connection();
int start_subscribe(std::string module);
int stop_subscribe(std::string module);
int add_subscribe(std::vector<std::string> dev_list);
int del_subscribe(std::vector<std::string> dev_list);
void enable_multi_machine(bool enable);
int start_device_subscribe();
int stop_device_subscribe();
int send_message(std::string dev_id, std::string json_str, int qos);
int connect_printer(std::string dev_id, std::string dev_ip, std::string username, std::string password, bool use_ssl);
int disconnect_printer();
@ -175,6 +186,7 @@ public:
int get_my_message(int type, int after, int limit, unsigned int* http_code, std::string* http_body);
int check_user_task_report(int* task_id, bool* printable);
int get_user_print_info(unsigned int* http_code, std::string* http_body);
int get_user_tasks(TaskQueryParams params, std::string* http_body);
int get_printer_firmware(std::string dev_id, unsigned* http_code, std::string* http_body);
int get_task_plate_index(std::string task_id, int* plate_index);
int get_user_info(int* identifier);
@ -236,6 +248,11 @@ private:
static func_refresh_connection refresh_connection_ptr;
static func_start_subscribe start_subscribe_ptr;
static func_stop_subscribe stop_subscribe_ptr;
static func_add_subscribe add_subscribe_ptr;
static func_del_subscribe del_subscribe_ptr;
static func_enable_multi_machine enable_multi_machine_ptr;
static func_start_device_subscribe start_device_subscribe_ptr;
static func_stop_device_subscribe stop_device_subscribe_ptr;
static func_send_message send_message_ptr;
static func_connect_printer connect_printer_ptr;
static func_disconnect_printer disconnect_printer_ptr;
@ -272,6 +289,7 @@ private:
static func_get_my_message get_my_message_ptr;
static func_check_user_task_report check_user_task_report_ptr;
static func_get_user_print_info get_user_print_info_ptr;
static func_get_user_tasks get_user_tasks_ptr;
static func_get_printer_firmware get_printer_firmware_ptr;
static func_get_task_plate_index get_task_plate_index_ptr;
static func_get_user_info get_user_info_ptr;

View File

@ -193,6 +193,7 @@ struct PrintParams {
std::string origin_model_id;
std::string print_type;
std::string dst_file;
std::string dev_name;
/* access options */
std::string dev_ip;
@ -212,6 +213,14 @@ struct PrintParams {
std::string extra_options;
};
struct TaskQueryParams
{
std::string dev_id;
int status = 0;
int offset = 0;
int limit = 20;
};
struct PublishParams {
std::string project_name;
std::string project_3mf_file;