diff --git a/resources/icons/X-MAX 3_thumbnail.png b/resources/icons/X-MAX 3_thumbnail.png
new file mode 100644
index 0000000..071cfdf
Binary files /dev/null and b/resources/icons/X-MAX 3_thumbnail.png differ
diff --git a/resources/icons/X-Plus 3_thumbnail.png b/resources/icons/X-Plus 3_thumbnail.png
new file mode 100644
index 0000000..72af6e0
Binary files /dev/null and b/resources/icons/X-Plus 3_thumbnail.png differ
diff --git a/resources/icons/X-smart 3_thumbnail.png b/resources/icons/X-smart 3_thumbnail.png
new file mode 100644
index 0000000..decd308
Binary files /dev/null and b/resources/icons/X-smart 3_thumbnail.png differ
diff --git a/resources/icons/arrow-left-s-line.svg b/resources/icons/arrow-left-s-line.svg
new file mode 100644
index 0000000..eb9c77f
--- /dev/null
+++ b/resources/icons/arrow-left-s-line.svg
@@ -0,0 +1,6 @@
+
+
+
diff --git a/resources/icons/arrow-right-s-line.svg b/resources/icons/arrow-right-s-line.svg
new file mode 100644
index 0000000..12db6f6
--- /dev/null
+++ b/resources/icons/arrow-right-s-line.svg
@@ -0,0 +1,6 @@
+
+
+
diff --git a/resources/icons/printer_state.svg b/resources/icons/printer_state.svg
new file mode 100644
index 0000000..b0ac56b
--- /dev/null
+++ b/resources/icons/printer_state.svg
@@ -0,0 +1,11 @@
+
+
+
diff --git a/resources/icons/refresh-line.svg b/resources/icons/refresh-line.svg
new file mode 100644
index 0000000..402400e
--- /dev/null
+++ b/resources/icons/refresh-line.svg
@@ -0,0 +1,8 @@
+
+
+
diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp
index 53f115e..f67127b 100644
--- a/src/slic3r/GUI/MainFrame.cpp
+++ b/src/slic3r/GUI/MainFrame.cpp
@@ -55,11 +55,17 @@
#include
#endif // _WIN32
+//B45
+#include
+
+
namespace Slic3r {
namespace GUI {
wxDEFINE_EVENT(EVT_LOAD_URL, wxCommandEvent);
wxDEFINE_EVENT(EVT_LOAD_PRINTER_URL, wxCommandEvent);
-int count = 0;
+
+
+
enum class ERescaleTarget
{
Mainframe,
@@ -886,6 +892,9 @@ void MainFrame::create_preset_tabs()
else
#endif
m_tabpanel->AddPage(m_guide_view, _L("Guide"));
+ //B45
+ m_tabpanel->Bind(wxCUSTOMEVT_NOTEBOOK_SEL_CHANGED, &MainFrame::OnTabPanelSelectionChanged, this);
+
}
@@ -2097,22 +2106,129 @@ void MainFrame::select_tab(Tab* tab)
page_idx++;
select_tab(size_t(page_idx));
}
+
+//B45
+void MainFrame::OnTabPanelSelectionChanged(wxCommandEvent &event)
+{
+
+ m_printer_view->PauseButton();
+ event.Skip();
+}
+
+
+
//B4
+//B45
void MainFrame::select_tab(size_t tab/* = size_t(-1)*/)
{
bool tabpanel_was_hidden = false;
// Controls on page are created on active page of active tab now.
// We should select/activate tab before its showing to avoid an UI-flickering
+ //B45
+
auto select = [this, tab](bool was_hidden) {
// when tab == -1, it means we should show the last selected tab
size_t new_selection = tab == (size_t)(-1) ? m_last_selected_tab : (m_layout == ESettingsLayout::Dlg && tab != 0) ? tab - 1 : tab;
//B4
if (m_tabpanel->GetSelection() == 4) {
if (const DynamicPrintConfig *cfg = wxGetApp().preset_bundle->physical_printers.get_selected_printer_config(); cfg) {
+ std::string select_name = wxGetApp().preset_bundle->physical_printers.get_selected_full_printer_name();
PresetBundle & preset_bundle = *wxGetApp().preset_bundle;
const PhysicalPrinter &pp = preset_bundle.physical_printers.get_selected_printer();
wxString host = pp.config.opt_string("print_host");
+ //B45
+ const PhysicalPrinterCollection &ph_printers = preset_bundle.physical_printers;
+ struct PhysicalPrinterPresetData
+ {
+ wxString lower_name; // just for sorting
+ std::string name; // preset_name
+ std::string fullname; // full name
+ bool selected; // is selected
+ };
+ std::vector preset_data;
+ for (PhysicalPrinterCollection::ConstIterator it = ph_printers.begin(); it != ph_printers.end(); ++it) {
+ for (const std::string &preset_name : it->get_preset_names()) {
+ preset_data.push_back({wxString::FromUTF8(it->get_full_name(preset_name)).Lower(), preset_name,
+ it->get_full_name(preset_name), ph_printers.is_selected(it, preset_name)});
+ }
+ }
+ m_collection = &preset_bundle.printers;
+ std::vector missingPresets;
+ std::vector m_buttons = (m_printer_view->GetButton());
+
+ for (auto it = m_buttons.begin(); it != m_buttons.end();) {
+ bool foundPreset = false;
+ for (const PhysicalPrinterPresetData &data : preset_data) {
+ if ((*it)->getLabel() == data.fullname) {
+ foundPreset = true;
+ break;
+ }
+ }
+ if (!foundPreset) {
+ (*it)->StopStatusThread();
+
+ delete *it;
+
+ it = m_buttons.erase(it);
+ m_printer_view->SetButtons(m_buttons);
+ m_printer_view->UpdateLayout();
+ } else {
+ ++it;
+ }
+ }
+
+
+
+
+
+ for (const PhysicalPrinterPresetData &data : preset_data) {
+ bool foundButton = false;
+ for (MachineListButton *button : m_buttons) {
+ if (button->getLabel() == data.fullname) {
+ foundButton = true;
+ break;
+ }
+ }
+ if (!foundButton) {
+ missingPresets.push_back(&data);
+ }
+ }
+ for (const PhysicalPrinterPresetData *data : missingPresets) {
+ Preset *preset = m_collection->find_preset(data->name);
+ if (!preset || !preset->is_visible)
+ continue;
+ //auto printer = preset_bundle.physical_printers.printer(count);
+
+ wxStringTokenizer tokenizer((data->fullname), " ");
+
+
+ auto *printer = preset_bundle.physical_printers.find_printer(std::string(tokenizer.GetNextToken().mb_str()));
+
+
+ //wxString host = printer.config.opt_string("print_host");
+ wxString host = (printer->config.opt_string("print_host"));
+
+ std::regex ipRegex(R"(\b(?:\d{1,3}\.){3}\d{1,3}\b)");
+ bool isValidIPAddress = std::regex_match(host.ToStdString(), ipRegex);
+
+ DynamicPrintConfig *cfg_t = &(printer->config);
+ if (isValidIPAddress) {
+ m_printer_view->AddButton(
+ data->fullname, "Name: " + data->fullname + "\nIp: " + host,
+ [host, this](wxMouseEvent &event) {
+ wxString formattedHost = wxString::Format("http://%s", host);
+ if (!host.Lower().starts_with("http"))
+ wxString formattedHost = wxString::Format("http://%s", host);
+ if (!formattedHost.Lower().ends_with("10088"))
+ formattedHost = wxString::Format("%s:10088", formattedHost);
+ this->m_printer_view->load_url(formattedHost);
+ },
+ (data->selected), cfg_t);
+ }
+ }
+ m_printer_view->ResumeButton();
+
if (host.empty()) {
tem_host = "";
host = wxString::Format("file://%s/web/qidi/missing_connection.html", from_u8(resources_dir()));
@@ -2124,10 +2240,10 @@ void MainFrame::select_tab(size_t tab/* = size_t(-1)*/)
host = wxString::Format("%s:10088", host);
}
if (tem_host != host) {
+ //B45
m_printer_view->load_url(host);
tem_host = host;
}
-
} else {
tem_host = "";
wxString url = wxString::Format("file://%s/web/qidi/missing_connection.html", from_u8(resources_dir()));
diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp
index f3e257e..6af9a81 100644
--- a/src/slic3r/GUI/MainFrame.hpp
+++ b/src/slic3r/GUI/MainFrame.hpp
@@ -196,6 +196,9 @@ public:
// When tab == -1, will be selected last selected tab
void select_tab(Tab* tab);
void select_tab(size_t tab = size_t(-1));
+ //B45
+ void OnTabPanelSelectionChanged(wxCommandEvent &event);
+
void select_view(const std::string& direction);
// Propagate changed configuration from the Tab to the Plater and save changes to the AppConfig
void on_config_changed(DynamicPrintConfig* cfg) const ;
@@ -220,6 +223,10 @@ public:
PrinterWebView * m_printer_view{nullptr};
//B28
GuideWebView * m_guide_view{nullptr};
+ //B45
+ PresetCollection *m_collection{nullptr};
+
+
wxBookCtrlBase * m_tabpanel{nullptr};
SettingsDialog m_settings_dialog;
DiffPresetDialog diff_dialog;
diff --git a/src/slic3r/GUI/PrinterWebView.cpp b/src/slic3r/GUI/PrinterWebView.cpp
index f23cfcf..0bbe1f8 100644
--- a/src/slic3r/GUI/PrinterWebView.cpp
+++ b/src/slic3r/GUI/PrinterWebView.cpp
@@ -17,12 +17,128 @@ namespace pt = boost::property_tree;
namespace Slic3r {
namespace GUI {
+
+
+wxBEGIN_EVENT_TABLE(MachineListButton, wxButton) EVT_PAINT(MachineListButton::OnPaint) EVT_ENTER_WINDOW(MachineListButton::OnMouseEnter)
+ EVT_LEAVE_WINDOW(MachineListButton::OnMouseLeave) EVT_LEFT_DOWN(MachineListButton::OnMouseLeftDown) EVT_LEFT_UP(MachineListButton::OnMouseLeftUp)
+ wxEND_EVENT_TABLE()
+
+void MachineListButton::OnPaint(wxPaintEvent &event)
+{
+ wxPaintDC dc(this);
+ //m_bitmap = get_bmp_bundle("X-MAX 3_thumbnail", 80)->GetBitmapFor(this);
+
+ if (m_isSimpleMode) {
+ dc.SetFont(wxFont(15, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD));
+ dc.SetTextForeground(wxColour(230, 230, 230));
+ dc.DrawText(m_name_text, 10 , 10);
+ } else {
+ dc.DrawBitmap(m_bitmap, 10, (GetSize().GetHeight() - m_bitmap.GetHeight()) / 2, true);
+
+ dc.SetFont(wxFont(15, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD));
+ dc.SetTextForeground(wxColour(230, 230, 230));
+ dc.DrawText(m_name_text, 10 + m_bitmap.GetWidth() + 10, 10);
+ dc.SetFont(wxFont(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD));
+ dc.SetTextForeground(wxColour(174, 174, 174));
+
+ dc.DrawText("IP:" + m_ip_text, 10 + m_bitmap.GetWidth() + 10, 40);
+
+ wxBitmap m_bitmap_state = get_bmp_bundle("printer_state", 20)->GetBitmapFor(this);
+ dc.DrawBitmap(m_bitmap_state, 10 + m_bitmap.GetWidth() + 10, 55, true);
+
+ dc.SetFont(wxFont(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD));
+ dc.SetTextForeground(wxColour(174, 174, 174));
+
+ dc.DrawText(m_state_text, 10 + m_bitmap.GetWidth() + m_bitmap_state.GetWidth() + 15, 60);
+ if (m_state_text == "printing") {
+ dc.SetFont(wxFont(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD));
+ dc.SetTextForeground(wxColour(33, 148, 239));
+ dc.DrawText(m_progress_text, 10 + m_bitmap.GetWidth() + m_bitmap_state.GetWidth() + 77, 62);
+ }
+ }
+
+}
+
+void MachineListButton::OnMouseEnter(wxMouseEvent &event)
+{
+ SetBackgroundColour(wxColour(100, 100, 105));
+ Refresh();
+}
+
+void MachineListButton::OnMouseLeave(wxMouseEvent &event)
+{
+ if (m_isSelected)
+ SetBackgroundColour(wxColour(100, 100, 105));
+ else
+ SetBackgroundColour(wxColour(67, 67, 71));
+ Refresh();
+}
+
+void MachineListButton::OnMouseLeftDown(wxMouseEvent &event)
+{
+ SetBackgroundColour(wxColour(120, 120, 125));
+ Refresh();
+}
+
+void MachineListButton::OnMouseLeftUp(wxMouseEvent &event)
+{
+ SetBackgroundColour(wxColour(100, 100, 105));
+ if (m_handlerl) {
+ m_handlerl(event);
+ }
+ Refresh();
+}
+
+
+//B45
PrinterWebView::PrinterWebView(wxWindow *parent)
: wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize)
{
- wxBoxSizer* topsizer = new wxBoxSizer(wxVERTICAL);
- // Create the webview
+ int leftsizerWidth = 300;
+ topsizer = new wxBoxSizer(wxHORIZONTAL);
+ leftScrolledWindow = new wxScrolledWindow(this, wxID_ANY);
+ leftScrolledWindow->SetBackgroundColour(wxColour(45, 45, 48));
+ leftsizer = new wxBoxSizer(wxVERTICAL);
+ wxFont font(wxFontInfo().Bold());
+
+ wxBoxSizer *titlesizer = new wxBoxSizer(wxHORIZONTAL);
+ wxStaticText *text = new wxStaticText(leftScrolledWindow, wxID_ANY, "MACHINE LIST", wxDefaultPosition, wxDefaultSize);
+ text->SetForegroundColour(wxColour(255, 255, 255));
+ text->SetFont(wxFont(wxFontInfo(18).Bold()));
+ titlesizer->Add(text, wxSizerFlags().Align(wxALIGN_LEFT).Border(wxALL, 5));
+ titlesizer->AddStretchSpacer();
+ //wxBU_EXACTFIT wxBORDER_NONE
+ wxButton *refresh_button = new wxButton(leftScrolledWindow, wxID_ANY, "", wxDefaultPosition, wxSize(20, 20), wxBORDER_NONE);
+ refresh_button->SetBackgroundColour(leftScrolledWindow->GetBackgroundColour());
+ refresh_button->SetForegroundColour(leftScrolledWindow->GetBackgroundColour());
+
+ refresh_button->SetMinSize(wxSize(40, -1));
+ refresh_button->SetBitmap(*get_bmp_bundle("refresh-line", 20));
+ //leftsizer->Add(button2, wxSizerFlags().Align(wxALIGN_RIGHT).Border(wxALL, 2));
+ titlesizer->Add(refresh_button, wxSizerFlags().Align(wxALIGN_LEFT).CenterVertical().Border(wxALL, 2));
+ refresh_button->Bind(wxEVT_BUTTON, &PrinterWebView::OnRightButtonClick, this);
+
+ arrow_button = new wxButton(leftScrolledWindow, wxID_ANY, "", wxDefaultPosition, wxSize(20, 20), wxBORDER_NONE);
+ arrow_button->SetFont(font);
+ arrow_button->SetBackgroundColour(leftScrolledWindow->GetBackgroundColour());
+ arrow_button->SetForegroundColour(leftScrolledWindow->GetBackgroundColour());
+ arrow_button->SetMinSize(wxSize(40, -1));
+ arrow_button->SetBitmap(*get_bmp_bundle("arrow-left-s-line", 20));
+ // leftsizer->Add(arrow_button, wxSizerFlags().Align(wxALIGN_RIGHT | wxALIGN_TOP).Border(wxALL, 2));
+ titlesizer->Add(arrow_button, wxSizerFlags().Align(wxALIGN_LEFT).CenterVertical().Border(wxALL, 2));
+ arrow_button->Bind(wxEVT_BUTTON, &PrinterWebView::OnLeftButtonClick, this);
+
+ titlesizer->Layout();
+
+ leftsizer->Add(titlesizer, wxSizerFlags().Expand().Align(wxALIGN_TOP).Border(wxALL, 0));
+
+ leftsizer->Layout();
+
+ leftScrolledWindow->SetSizer(leftsizer);
+ leftScrolledWindow->SetScrollRate(10, 10);
+ leftScrolledWindow->SetMinSize(wxSize(leftsizerWidth, -1));
+ leftScrolledWindow->FitInside();
m_browser = WebView::CreateWebView(this, "");
if (m_browser == nullptr) {
wxLogError("Could not init m_browser");
@@ -30,40 +146,240 @@ PrinterWebView::PrinterWebView(wxWindow *parent)
}
SetSizer(topsizer);
+ topsizer->Add(leftScrolledWindow, wxSizerFlags(0).Expand());
+ topsizer->Add(m_browser, wxSizerFlags(1).Expand().Border(wxALL, 0));
- topsizer->Add(m_browser, wxSizerFlags().Expand().Proportion(1));
-
- // Log backend information
- //if (wxGetApp().get_mode() == comDevelop) {
- // wxLogMessage(wxWebView::GetBackendVersionInfo().ToString());
- // wxLogMessage("Backend: %s Version: %s", m_browser->GetClassInfo()->GetClassName(),
- // wxWebView::GetBackendVersionInfo().ToString());
- // wxLogMessage("User Agent: %s", m_browser->GetUserAgent());
- //}
-
- //Zoom
+ // Zoom
m_zoomFactor = 100;
+ leftScrolledWindow->Bind(wxEVT_SCROLLWIN_TOP, &PrinterWebView::OnScroll, this);
+ leftScrolledWindow->Bind(wxEVT_SCROLLWIN_BOTTOM, &PrinterWebView::OnScroll, this);
+ leftScrolledWindow->Bind(wxEVT_SCROLLWIN_LINEUP, &PrinterWebView::OnScroll, this);
+ leftScrolledWindow->Bind(wxEVT_SCROLLWIN_LINEDOWN, &PrinterWebView::OnScroll, this);
+ leftScrolledWindow->Bind(wxEVT_SCROLLWIN_PAGEUP, &PrinterWebView::OnScroll, this);
+ leftScrolledWindow->Bind(wxEVT_SCROLLWIN_PAGEDOWN, &PrinterWebView::OnScroll, this);
+
+ //B45
+ Bind(wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED, &PrinterWebView::OnScriptMessage, this);
+
+
//Connect the idle events
Bind(wxEVT_CLOSE_WINDOW, &PrinterWebView::OnClose, this);
}
-PrinterWebView::~PrinterWebView()
-{
- BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " Start";
- SetEvtHandlerEnabled(false);
- BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " End";
+
+
+
+
+void PrinterWebView::AddButton(const wxString & buttonText,
+ const wxString & moreInfo,
+ const std::function &handler,
+ bool isSelected,
+ DynamicPrintConfig * cfg_t)
+ {
+
+ wxStringTokenizer tokenizer(moreInfo, " ");
+
+
+ tokenizer.GetNextToken();
+ wxString Name = tokenizer.GetNextToken();
+ tokenizer.GetNextToken();
+ wxString Machine_Type = tokenizer.GetNextToken();
+ wxString Machine_Count = tokenizer.GetNextToken();
+ tokenizer.GetNextToken();
+ tokenizer.GetNextToken();
+ wxString Machine_IP = tokenizer.GetNextToken();
+ wxString Machine_Name = Machine_Name.Format("%s %s%s", Machine_Type, Machine_Count, "_thumbnail");
+
+ MachineListButton *customButton = new MachineListButton(leftScrolledWindow, wxID_ANY, buttonText, wxDefaultPosition, wxDefaultSize, wxBORDER_DOUBLE,
+ wxDefaultValidator, wxButtonNameStr, isSelected);
+ customButton->SetMinSize(wxSize(80, -1));
+ customButton->SetBitmap(*get_bmp_bundle(std::string(Machine_Name.mb_str()), 80));
+ customButton->SetBitMap(get_bmp_bundle(std::string(Machine_Name.mb_str()), 80)->GetBitmapFor(this));
+ customButton->SetNameText(Name);
+ customButton->SetIPText(Machine_IP);
+ customButton->SetStateText("standby");
+ customButton->SetProgressText("(0%)");
+ customButton->SetMinSize(wxSize(200, -1));
+ customButton->SetClickHandler(handler);
+ customButton->SetStatusThread(std::move(customButton->CreatThread(buttonText, cfg_t)));
+ customButton->SetSimpleMode(false);
+
+ leftsizer->Add(customButton, wxSizerFlags().Border(wxALL, 1).Expand());
+ leftsizer->Layout();
+ m_buttons.push_back(customButton);
+ }
+
+ //B45
+ void PrinterWebView::PauseButton()
+ {
+ //BOOST_LOG_TRIVIAL(error) << " Pause";
+
+ if (m_buttons.empty()) {
+ BOOST_LOG_TRIVIAL(info) << " empty";
+ } else {
+ for (MachineListButton *button : m_buttons) {
+ button->PauseStatusThread();
+ }
+ }
+ }
+ //B45
+ void PrinterWebView::ResumeButton()
+ {
+ //BOOST_LOG_TRIVIAL(error) << " Resume";
+
+ if (m_buttons.empty()) {
+ BOOST_LOG_TRIVIAL(info) << " empty";
+ } else {
+ for (MachineListButton *button : m_buttons) {
+ button->ResumeStatusThread();
+ }
+ }
+ }
+
+
+ //B45
+ void PrinterWebView::DeleteButton()
+{
+ if (m_buttons.empty()) {
+ BOOST_LOG_TRIVIAL(info) <<" empty";
+ } else {
+ for (MachineListButton *button : m_buttons) {
+
+ button->StopStatusThread();
+
+ delete button;
+ }
+ m_buttons.clear();
+ }
}
+ // B45
+void PrinterWebView::SetButtons(std::vector buttons) { m_buttons = buttons; }
+
+ PrinterWebView::~PrinterWebView()
+{
+ BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " Start";
+ SetEvtHandlerEnabled(false);
+ BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " End";
+}
+
+void PrinterWebView::OnLeftButtonClick(wxCommandEvent &event)
+{
+ m_isSimpleMode = !m_isSimpleMode;
+
+ if (!m_isSimpleMode) {
+ leftScrolledWindow->SetMinSize(wxSize(300, -1));
+ arrow_button->SetBitmap(*get_bmp_bundle("arrow-left-s-line", 20));
+ for (MachineListButton *button : m_buttons) {
+ button->SetBitmap(*get_bmp_bundle(std::string("X-MAX 3_thumbnail"), 80));
+ button->SetSimpleMode(m_isSimpleMode);
+ }
+ }
+ else {
+ arrow_button->SetBitmap(*get_bmp_bundle("arrow-right-s-line", 20));
+
+ leftScrolledWindow->SetMinSize(wxSize(260, -1));
+ for (MachineListButton *button : m_buttons) {
+ button->SetBitmap(*get_bmp_bundle(std::string("X-MAX 3_thumbnail"), 30));
+ button->SetSimpleMode(m_isSimpleMode);
+ }
+ }
+
+ leftsizer->Layout();
+
+
+ leftScrolledWindow->Layout();
+
+ topsizer->Layout();
+}
+
+void PrinterWebView::OnRightButtonClick(wxCommandEvent &event)
+{
+ for (MachineListButton *button : m_buttons) {
+ button->ResumeStatusThread();
+ }
+}
+
+
+
+void PrinterWebView::SendRecentList(int images)
+{
+ boost::property_tree::wptree req;
+ boost::property_tree::wptree data;
+ //wxGetApp().mainframe->get_recent_projects(data, images);
+ req.put(L"sequence_id", "");
+ req.put(L"command", L"studio_set_mallurl");
+ //req.put_child(L"response", data);
+ std::wostringstream oss;
+ pt::write_json(oss, req, false);
+ RunScript(wxString::Format("window.postMessage(%s)", oss.str()));
+}
+
+
+
+void PrinterWebView::OnScriptMessage(wxWebViewEvent &evt)
+{
+
+ wxLogMessage("Script message received; value = %s, handler = %s", evt.GetString(), evt.GetMessageHandler());
+ //std::string response = wxGetApp().handle_web_request(evt.GetString().ToUTF8().data());
+ //if (response.empty())
+ // return;
+ SendRecentList(1);
+ ///* remove \n in response string */
+ //response.erase(std::remove(response.begin(), response.end(), '\n'), response.end());
+ //if (!response.empty()) {
+ // m_response_js = wxString::Format("window.postMessage('%s')", response);
+ // wxCommandEvent *event = new wxCommandEvent(EVT_RESPONSE_MESSAGE, this->GetId());
+ // wxQueueEvent(this, event);
+ //} else {
+ // m_response_js.clear();
+ //}
+}
+
+
+void PrinterWebView::UpdateLayout()
+{
+ //leftScrolledWindow->SetVirtualSize(leftsizer->GetMinSize());
+ leftScrolledWindow->FitInside();
+ topsizer->Layout();
+ if (!m_buttons.empty()) {
+ for (MachineListButton *button : m_buttons) {
+ button->Layout();
+ button->Refresh();
+ }
+ }
+}
+
+
+void PrinterWebView::OnScroll(wxScrollWinEvent &event)
+{
+ UpdateLayout();
+ event.Skip();
+}
+
+//B45
void PrinterWebView::load_url(wxString& url)
{
// this->Show();
// this->Raise();
if (m_browser == nullptr)
return;
+
+ for (MachineListButton *button : m_buttons) {
+
+ size_t pos = url.Find((button->getIPLabel()));
+ if (pos != wxString::npos) {
+ button->SetSelect(true);
+ } else {
+ button->SetSelect(false);
+ }
+ }
+
+
m_browser->LoadURL(url);
//m_browser->SetFocus();
UpdateState();
@@ -82,6 +398,14 @@ void PrinterWebView::OnClose(wxCloseEvent& evt)
this->Hide();
}
+void PrinterWebView::RunScript(const wxString &javascript)
+{
+ // Remember the script we run in any case, so the next time the user opens
+ // the "Run Script" dialog box, it is shown there for convenient updating.
+
+
+ WebView::RunScript(m_browser, javascript);
+}
} // GUI
diff --git a/src/slic3r/GUI/PrinterWebView.hpp b/src/slic3r/GUI/PrinterWebView.hpp
index e79cc3f..97f75bb 100644
--- a/src/slic3r/GUI/PrinterWebView.hpp
+++ b/src/slic3r/GUI/PrinterWebView.hpp
@@ -30,10 +30,166 @@
#include
#endif
+//B45
+#include "PrintHostDialogs.hpp"
+#include
namespace Slic3r {
namespace GUI {
+class MachineListButton : public wxButton
+{
+public:
+ MachineListButton(wxWindow * parent,
+ wxWindowID id,
+ const wxString & label,
+ const wxPoint & pos = wxDefaultPosition,
+ const wxSize & size = wxDefaultSize,
+ long style = wxBORDER_DOUBLE,
+ const wxValidator &validator = wxDefaultValidator,
+ const wxString & name = wxButtonNameStr,
+ bool isSelected = false)
+ : wxButton(parent, id, label, pos, size, style, validator, name)
+ {
+ full_label = label;
+ m_isSelected = isSelected;
+ if (isSelected)
+ SetBackgroundColour(wxColour(100, 100, 105));
+ else
+ SetBackgroundColour(wxColour(67, 67, 71));
+ //Bind(wxEVT_BUTTON, &MachineListButton::OnMouseLeftUp, this);
+ }
+ wxString getLabel() { return full_label; }
+ wxString getIPLabel() { return m_ip_text; }
+
+
+ void SetBitMap(const wxBitmap &bitmap)
+ {
+ m_bitmap = bitmap;
+ Refresh();
+ }
+
+
+ void SetNameText(const wxString &text)
+ {
+ m_name_text = text;
+ Refresh();
+ }
+ void SetIPText(const wxString &text)
+ {
+ m_ip_text = text;
+ Refresh();
+ }
+ void SetStateText(const wxString &text)
+ {
+ m_state_text = text;
+ Refresh();
+ }
+
+ void SetProgressText(const wxString &text)
+ {
+ m_progress_text = text;
+ Refresh();
+ }
+ void SetSelect(bool isselectd)
+ {
+ m_isSelected = isselectd;
+ if (m_isSelected)
+ SetBackgroundColour(wxColour(100, 100, 105));
+ else
+ SetBackgroundColour(wxColour(67, 67, 71));
+ Refresh();
+ }
+
+ void SetSimpleMode(bool issimplemode)
+ {
+ m_isSimpleMode = issimplemode;
+ //if (m_isSelected)
+ // SetBackgroundColour(wxColour(100, 100, 105));
+ //else
+ // SetBackgroundColour(wxColour(67, 67, 71));
+ Refresh();
+ }
+
+ void SetClickHandler(const std::function &handler) { m_handlerl = handler; }
+ void PauseStatusThread() { m_pauseThread = true; }
+ void ResumeStatusThread() { m_pauseThread = false; }
+ void StopStatusThread()
+ {
+ m_stopThread = true;
+ if (m_statusThread.joinable()) {
+ m_statusThread.join();
+ }
+ }
+ void OnPaint(wxPaintEvent &event);
+ void OnMouseEnter(wxMouseEvent &event);
+ void OnMouseLeave(wxMouseEvent &event);
+ void OnMouseLeftDown(wxMouseEvent &event);
+ void OnMouseLeftUp(wxMouseEvent &event);
+ void OnClickHandler(wxCommandEvent &event);
+ void SetStatusThread(std::thread thread) { m_statusThread = std::move(thread); }
+ std::thread CreatThread(const wxString &buttonText, DynamicPrintConfig *cfg_t)
+ {
+
+ std::thread thread([this, buttonText, cfg_t]() {
+ std::unique_ptr printhost(PrintHost::get_print_host(cfg_t));
+ if (!printhost) {
+ BOOST_LOG_TRIVIAL(error) << ("Could not get a valid Printer Host reference");
+ return;
+ }
+ wxString msg;
+ std::string state = "standby";
+ float progress = 0;
+ while (true) {
+ if (!m_pauseThread) {
+ state = printhost->get_status(msg);
+ if (state == "offline") {
+ //BOOST_LOG_TRIVIAL(error) << boost::format("%1%Got state: %2%") % buttonText % state;
+ m_pauseThread = true;
+ }
+ BOOST_LOG_TRIVIAL(info) << boost::format("%1%Got state: %2%") % buttonText % state;
+ SetStateText(state);
+ if (state == "printing") {
+ progress = (printhost->get_progress(msg)) * 100;
+ int progressInt = static_cast(progress);
+ SetStateText(state);
+ SetProgressText(wxString::Format(wxT("(%d%%)"), progressInt));
+ BOOST_LOG_TRIVIAL(info) << boost::format("%1%Got progress: %2%") % buttonText % progress;
+ }
+ ;
+ } else
+ std::this_thread::sleep_for(std::chrono::seconds(3));
+ if (m_stopThread)
+ break;
+ }
+ });
+ return thread;
+ }
+
+private:
+
+ std::atomic m_stopThread{false};
+ std::atomic m_pauseThread{false};
+
+ bool m_isSimpleMode;
+ bool m_isSelected;
+
+ std::thread m_statusThread;
+
+ wxBitmap m_bitmap;
+ bool m_isHovered;
+ wxString full_label;
+ wxString m_name_text;
+ wxString m_ip_text;
+ wxString m_state_text;
+ wxString m_progress_text;
+ std::function m_handlerl;
+ wxDECLARE_EVENT_TABLE();
+ //wxDECLARE_EVENT_TABLE();
+};
+
+
+
class PrinterWebView : public wxPanel {
public:
@@ -44,7 +200,41 @@ public:
void UpdateState();
void OnClose(wxCloseEvent& evt);
+ //B45
+ void OnLeftButtonClick(wxCommandEvent &event);
+ void OnRightButtonClick(wxCommandEvent &event);
+
+ void RunScript(const wxString &javascript);
+ //void OnScriptMessageReceived(wxWebViewEvent &event);
+ void OnScriptMessage(wxWebViewEvent &evt);
+
+ void UpdateLayout();
+ void OnScroll(wxScrollWinEvent &event);
+
+ //B45
+ void SendRecentList(int images);
+ void SetButtons(std::vector buttons);
+ void AddButton(const wxString & buttonText,
+ const wxString & moreInfo,
+ const std::function &handler,
+ bool isOnline,
+ DynamicPrintConfig * cfg_t);
+ void DeleteButton();
+ void PauseButton();
+ void ResumeButton();
+ std::vector GetButton() { return m_buttons; };
+
private:
+ //B45
+ wxBoxSizer *leftsizer;
+ wxBoxSizer *topsizer;
+ bool m_isSimpleMode = false;
+
+ wxButton *arrow_button;
+
+ wxScrolledWindow * leftScrolledWindow;
+
+ std::vector m_buttons;
wxWebView* m_browser;
long m_zoomFactor;
diff --git a/src/slic3r/Utils/AstroBox.hpp b/src/slic3r/Utils/AstroBox.hpp
index 72ab273..c6d33cc 100644
--- a/src/slic3r/Utils/AstroBox.hpp
+++ b/src/slic3r/Utils/AstroBox.hpp
@@ -21,6 +21,11 @@ public:
const char* get_name() const override;
bool test(wxString &curl_msg) const override;
+
+ //B45
+ virtual std::string get_status(wxString &curl_msg) const override { return "1"; };
+ virtual float get_progress(wxString &curl_msg) const override { return 1; };
+
wxString get_test_ok_msg () const override;
wxString get_test_failed_msg (wxString &msg) const override;
bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn, InfoFn info_fn) const override;
diff --git a/src/slic3r/Utils/Duet.hpp b/src/slic3r/Utils/Duet.hpp
index 2a91aa8..24c6c92 100644
--- a/src/slic3r/Utils/Duet.hpp
+++ b/src/slic3r/Utils/Duet.hpp
@@ -20,6 +20,10 @@ public:
const char* get_name() const override;
bool test(wxString &curl_msg) const override;
+ //B45
+ virtual std::string get_status(wxString &curl_msg) const override { return "1"; };
+ virtual float get_progress(wxString &curl_msg) const override { return 1; };
+
wxString get_test_ok_msg() const override;
wxString get_test_failed_msg(wxString &msg) const override;
bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn, InfoFn info_fn) const override;
diff --git a/src/slic3r/Utils/FlashAir.hpp b/src/slic3r/Utils/FlashAir.hpp
index ba60644..cd77e7f 100644
--- a/src/slic3r/Utils/FlashAir.hpp
+++ b/src/slic3r/Utils/FlashAir.hpp
@@ -21,6 +21,11 @@ public:
const char* get_name() const override;
bool test(wxString &curl_msg) const override;
+
+ //B45
+ virtual std::string get_status(wxString &curl_msg) const override { return "1"; };
+ virtual float get_progress(wxString &curl_msg) const override { return 1; };
+
wxString get_test_ok_msg() const override;
wxString get_test_failed_msg(wxString &msg) const override;
bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn, InfoFn info_fn) const override;
diff --git a/src/slic3r/Utils/MKS.hpp b/src/slic3r/Utils/MKS.hpp
index 79143fd..0c445a6 100644
--- a/src/slic3r/Utils/MKS.hpp
+++ b/src/slic3r/Utils/MKS.hpp
@@ -20,6 +20,11 @@ public:
const char* get_name() const override;
bool test(wxString& curl_msg) const override;
+
+ //B45
+ virtual std::string get_status(wxString &curl_msg) const override { return "1"; };
+ virtual float get_progress(wxString &curl_msg) const override { return 1; };
+
wxString get_test_ok_msg() const override;
wxString get_test_failed_msg(wxString& msg) const override;
bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn, InfoFn info_fn) const override;
diff --git a/src/slic3r/Utils/Moonraker.cpp b/src/slic3r/Utils/Moonraker.cpp
index d2d6ba4..7266b23 100644
--- a/src/slic3r/Utils/Moonraker.cpp
+++ b/src/slic3r/Utils/Moonraker.cpp
@@ -142,6 +142,129 @@ bool Moonraker::test(wxString& msg) const
return res;
}
+//B45
+std::string Moonraker::get_status(wxString &msg) const
+{
+ // GET /server/info
+
+ // Since the request is performed synchronously here,
+ // it is ok to refer to `msg` from within the closure
+ const char *name = get_name();
+
+ bool res = true;
+ std::string print_state = "standby";
+ auto url = make_url("printer/objects/query?print_stats=state");
+
+ BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Get version at: %2%") % name % url;
+
+ auto http = Http::get(std::move(url));
+ set_auth(http);
+ http.on_error([&](std::string body, std::string error, unsigned status) {
+ BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error getting version: %2%, HTTP %3%, body: `%4%`") % name % error % status %
+ body;
+ print_state = "offline";
+ msg = format_error(body, error, status);
+ })
+ .on_complete([&](std::string body, unsigned) {
+ BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: Got print_stats: %2%") % name % body;
+
+ try {
+ // All successful HTTP requests will return a json encoded object in the form of :
+ // {result: }
+ std::stringstream ss(body);
+ pt::ptree ptree;
+ pt::read_json(ss, ptree);
+ if (ptree.front().first != "result") {
+ msg = "Could not parse server response";
+ print_state = "offline";
+ return;
+ }
+ if (!ptree.front().second.get_optional("status")) {
+ msg = "Could not parse server response";
+ print_state = "offline";
+ return;
+ }
+ print_state = ptree.get("result.status.print_stats.state");
+ BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Got state: %2%") % name % print_state;
+ ;
+ } catch (const std::exception &) {
+ print_state = "offline";
+ msg = "Could not parse server response";
+ }
+ })
+#ifdef _WIN32
+ .ssl_revoke_best_effort(m_ssl_revoke_best_effort)
+ .on_ip_resolve([&](std::string address) {
+ // Workaround for Windows 10/11 mDNS resolve issue, where two mDNS resolves in succession fail.
+ // Remember resolved address to be reused at successive REST API call.
+ msg = GUI::from_u8(address);
+ })
+#endif // _WIN32
+ .perform_sync();
+
+ return print_state;
+}
+
+float Moonraker::get_progress(wxString &msg) const
+{
+ // GET /server/info
+
+ // Since the request is performed synchronously here,
+ // it is ok to refer to `msg` from within the closure
+ const char *name = get_name();
+
+ bool res = true;
+ auto url = make_url("printer/objects/query?display_status=progress");
+ float process = 0;
+ BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Get version at: %2%") % name % url;
+
+ auto http = Http::get(std::move(url));
+ set_auth(http);
+ http.on_error([&](std::string body, std::string error, unsigned status) {
+ BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error getting version: %2%, HTTP %3%, body: `%4%`") % name % error % status %
+ body;
+ res = false;
+ msg = format_error(body, error, status);
+ })
+ .on_complete([&](std::string body, unsigned) {
+ BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: Got display_status: %2%") % name % body;
+
+ try {
+ // All successful HTTP requests will return a json encoded object in the form of :
+ // {result: }
+ std::stringstream ss(body);
+ pt::ptree ptree;
+ pt::read_json(ss, ptree);
+ if (ptree.front().first != "result") {
+ msg = "Could not parse server response";
+ res = false;
+ return;
+ }
+ if (!ptree.front().second.get_optional("status")) {
+ msg = "Could not parse server response";
+ res = false;
+ return;
+ }
+ process = std::stof(ptree.get("result.status.display_status.progress"));
+ BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Got state: %2%") % name % process;
+ } catch (const std::exception &) {
+ res = false;
+ msg = "Could not parse server response";
+ }
+ })
+#ifdef _WIN32
+ .ssl_revoke_best_effort(m_ssl_revoke_best_effort)
+ .on_ip_resolve([&](std::string address) {
+ // Workaround for Windows 10/11 mDNS resolve issue, where two mDNS resolves in succession fail.
+ // Remember resolved address to be reused at successive REST API call.
+ msg = GUI::from_u8(address);
+ })
+#endif // _WIN32
+ .perform_sync();
+
+ return process;
+}
+
bool Moonraker::upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn, InfoFn info_fn) const
{
// POST /server/files/upload
diff --git a/src/slic3r/Utils/Moonraker.hpp b/src/slic3r/Utils/Moonraker.hpp
index 09a231f..509de27 100644
--- a/src/slic3r/Utils/Moonraker.hpp
+++ b/src/slic3r/Utils/Moonraker.hpp
@@ -25,6 +25,11 @@ public:
const char* get_name() const override;
virtual bool test(wxString &curl_msg) const override;
+
+ //B45
+ virtual std::string get_status(wxString &curl_msg) const override;
+ virtual float get_progress(wxString &curl_msg) const override;
+
wxString get_test_ok_msg () const override;
wxString get_test_failed_msg (wxString &msg) const override;
bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn, InfoFn info_fn) const override;
diff --git a/src/slic3r/Utils/OctoPrint.hpp b/src/slic3r/Utils/OctoPrint.hpp
index 3377cba..9577e7d 100644
--- a/src/slic3r/Utils/OctoPrint.hpp
+++ b/src/slic3r/Utils/OctoPrint.hpp
@@ -24,6 +24,10 @@ public:
const char* get_name() const override;
virtual bool test(wxString &curl_msg) const override;
+ //B45
+ virtual std::string get_status(wxString &curl_msg) const override { return "1"; };
+ virtual float get_progress(wxString &curl_msg) const override { return 1; };
+
wxString get_test_ok_msg () const override;
wxString get_test_failed_msg (wxString &msg) const override;
bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn, InfoFn info_fn) const override;
diff --git a/src/slic3r/Utils/PrintHost.hpp b/src/slic3r/Utils/PrintHost.hpp
index 1e00599..cd05e17 100644
--- a/src/slic3r/Utils/PrintHost.hpp
+++ b/src/slic3r/Utils/PrintHost.hpp
@@ -50,6 +50,9 @@ public:
virtual const char* get_name() const = 0;
virtual bool test(wxString &curl_msg) const = 0;
+ //B45
+ virtual std::string get_status(wxString &curl_msg) const = 0;
+ virtual float get_progress(wxString &curl_msg) const = 0;
virtual wxString get_test_ok_msg () const = 0;
virtual wxString get_test_failed_msg (wxString &msg) const = 0;
virtual bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn, InfoFn info_fn) const = 0;
diff --git a/src/slic3r/Utils/Repetier.hpp b/src/slic3r/Utils/Repetier.hpp
index 00bc929..02d6015 100644
--- a/src/slic3r/Utils/Repetier.hpp
+++ b/src/slic3r/Utils/Repetier.hpp
@@ -21,6 +21,9 @@ public:
const char* get_name() const override;
bool test(wxString &curl_msg) const override;
+ //B45
+ virtual std::string get_status(wxString &curl_msg) const override { return "1"; };
+ virtual float get_progress(wxString &curl_msg) const override { return 1; };
wxString get_test_ok_msg () const override;
wxString get_test_failed_msg (wxString &msg) const override;
bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn, InfoFn info_fn) const override;