From 6716492efa3c218da57a60c3937bb9777a20b25c Mon Sep 17 00:00:00 2001 From: David Kocik Date: Thu, 4 Mar 2021 21:56:07 +0100 Subject: [PATCH] Printhost upload progress bar notification --- src/slic3r/GUI/GUI_App.cpp | 5 ++ src/slic3r/GUI/GUI_App.hpp | 17 ++--- src/slic3r/GUI/NotificationManager.cpp | 87 +++++++++++++++++++++----- src/slic3r/GUI/NotificationManager.hpp | 37 +++++++++-- src/slic3r/GUI/PrintHostDialogs.cpp | 25 ++++++++ 5 files changed, 143 insertions(+), 28 deletions(-) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 2fde30cd1..ecc5f46a7 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -1978,6 +1978,11 @@ wxNotebook* GUI_App::tab_panel() const return mainframe->m_tabpanel; } +NotificationManager* GUI_App::notification_manager() +{ + return plater_->get_notification_manager(); +} + // extruders count from selected printer preset int GUI_App::extruders_cnt() const { diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 5572c5071..f1ee0746a 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -43,6 +43,7 @@ class ObjectSettings; class ObjectList; class ObjectLayers; class Plater; +class NotificationManager; struct GUI_InitParams; @@ -226,14 +227,14 @@ public: void MacOpenFiles(const wxArrayString &fileNames) override; #endif /* __APPLE */ - Sidebar& sidebar(); - ObjectManipulation* obj_manipul(); - ObjectSettings* obj_settings(); - ObjectList* obj_list(); - ObjectLayers* obj_layers(); - Plater* plater(); - Model& model(); - + Sidebar& sidebar(); + ObjectManipulation* obj_manipul(); + ObjectSettings* obj_settings(); + ObjectList* obj_list(); + ObjectLayers* obj_layers(); + Plater* plater(); + Model& model(); + NotificationManager* notification_manager(); // Parameters extracted from the command line to be passed to GUI after initialization. const GUI_InitParams* init_params { nullptr }; diff --git a/src/slic3r/GUI/NotificationManager.cpp b/src/slic3r/GUI/NotificationManager.cpp index 930174e3f..c9cf4d8cc 100644 --- a/src/slic3r/GUI/NotificationManager.cpp +++ b/src/slic3r/GUI/NotificationManager.cpp @@ -359,12 +359,14 @@ void NotificationManager::PopNotification::render_text(ImGuiWrapper& imgui, cons ImGui::SetCursorPosY(win_size.y / 2 - win_size.y / 6 - m_line_height / 2); imgui.text(m_text1.substr(0, m_endlines[0]).c_str()); // line2 - std::string line = m_text1.substr(m_endlines[0] + (m_text1[m_endlines[0]] == '\n' || m_text1[m_endlines[0]] == ' ' ? 1 : 0)); - cursor_y = win_size.y / 2 + win_size.y / 6 - m_line_height / 2; - ImGui::SetCursorPosX(x_offset); - ImGui::SetCursorPosY(cursor_y); - imgui.text(line.c_str()); - cursor_x = x_offset + ImGui::CalcTextSize(line.c_str()).x; + if (m_text1.length() > m_endlines[0]) { + std::string line = m_text1.substr(m_endlines[0] + (m_text1[m_endlines[0]] == '\n' || m_text1[m_endlines[0]] == ' ' ? 1 : 0)); + cursor_y = win_size.y / 2 + win_size.y / 6 - m_line_height / 2; + ImGui::SetCursorPosX(x_offset); + ImGui::SetCursorPosY(cursor_y); + imgui.text(line.c_str()); + cursor_x = x_offset + ImGui::CalcTextSize(line.c_str()).x; + } } else { ImGui::SetCursorPosX(x_offset); ImGui::SetCursorPosY(cursor_y); @@ -776,17 +778,52 @@ void NotificationManager::ProgressBarNotification::init() } void NotificationManager::ProgressBarNotification::render_text(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y) { - PopNotification::render_text(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y); + // line1 - we do not print any more text than what fits on line 1. Line 2 is bar. + ImGui::SetCursorPosX(m_left_indentation); + ImGui::SetCursorPosY(win_size_y / 2 - win_size_y / 6 - m_line_height / 2); + imgui.text(m_text1.substr(0, m_endlines[0]).c_str()); render_bar(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y); } void NotificationManager::ProgressBarNotification::render_bar(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y) { - ImVec4 orange_color = ImVec4(.99f, .313f, .0f, 1.0f); - float invisible_length = 0; - - ImVec2 lineEnd = ImVec2(win_pos_x - invisible_length - m_window_width_offset, win_pos_y + win_size_y/2 + m_line_height / 2); - ImVec2 lineStart = ImVec2(win_pos_x - win_size_x + m_left_indentation, win_pos_y + win_size_y/2 + m_line_height / 2); - ImGui::GetWindowDrawList()->AddLine(lineStart, lineEnd, IM_COL32((int)(orange_color.x * 255), (int)(orange_color.y * 255), (int)(orange_color.z * 255), (1.0f * 255.f)), m_line_height * 0.7f); + switch (m_pb_state) + { + case Slic3r::GUI::NotificationManager::ProgressBarNotification::ProgressBarState::PB_PROGRESS: + { + ImVec4 orange_color = ImVec4(.99f, .313f, .0f, 1.0f); + ImVec4 gray_color = ImVec4(.34f, .34f, .34f, 1.0f); + float invisible_length = 0; + ImVec2 lineEnd = ImVec2(win_pos_x - invisible_length - m_window_width_offset, win_pos_y + win_size_y / 2 + m_line_height / 2); + ImVec2 lineStart = ImVec2(win_pos_x - win_size_x + m_left_indentation, win_pos_y + win_size_y / 2 + m_line_height / 2); + float full_lenght = lineEnd.x - lineStart.x; + ImVec2 midPoint = ImVec2(lineStart.x + full_lenght * m_percentage, lineStart.y); + ImGui::GetWindowDrawList()->AddLine(lineStart, lineEnd, IM_COL32((int)(gray_color.x * 255), (int)(gray_color.y * 255), (int)(gray_color.z * 255), (1.0f * 255.f)), m_line_height * 0.7f); + ImGui::GetWindowDrawList()->AddLine(lineStart, midPoint, IM_COL32((int)(orange_color.x * 255), (int)(orange_color.y * 255), (int)(orange_color.z * 255), (1.0f * 255.f)), m_line_height * 0.7f); + break; + } + case Slic3r::GUI::NotificationManager::ProgressBarNotification::ProgressBarState::PB_ERROR: + { + ImGui::SetCursorPosX(m_left_indentation); + ImGui::SetCursorPosY(win_size_y / 2 + win_size_y / 6 - m_line_height / 2); + imgui.text(_u8L("ERROR")); + break; + } + case Slic3r::GUI::NotificationManager::ProgressBarNotification::ProgressBarState::PB_CANCELLED: + { + ImGui::SetCursorPosX(m_left_indentation); + ImGui::SetCursorPosY(win_size_y / 2 + win_size_y / 6 - m_line_height / 2); + imgui.text(_u8L("CANCELED")); + break; + } + case Slic3r::GUI::NotificationManager::ProgressBarNotification::ProgressBarState::PB_COMPLETED: + { + ImGui::SetCursorPosX(m_left_indentation); + ImGui::SetCursorPosY(win_size_y / 2 + win_size_y / 6 - m_line_height / 2); + imgui.text(_u8L("COMPLETED")); + break; + } + } + } //------NotificationManager-------- @@ -989,7 +1026,6 @@ void NotificationManager::set_progress_bar_percentage(const std::string& text, f for (std::unique_ptr& notification : m_pop_notifications) { if (notification->get_type() == NotificationType::ProgressBar && notification->compare_text(text)) { dynamic_cast(notification.get())->set_percentage(percentage); - // FIX ME: this is massive gpu eater (render every frame) wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0); found = true; } @@ -998,6 +1034,26 @@ void NotificationManager::set_progress_bar_percentage(const std::string& text, f push_progress_bar_notification(text, percentage); } } +void NotificationManager::progress_bar_show_canceled(const std::string& text) +{ + for (std::unique_ptr& notification : m_pop_notifications) { + if (notification->get_type() == NotificationType::ProgressBar && notification->compare_text(text)) { + dynamic_cast(notification.get())->cancel(); + wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0); + break; + } + } +} +void NotificationManager::progress_bar_show_error(const std::string& text) +{ + for (std::unique_ptr& notification : m_pop_notifications) { + if (notification->get_type() == NotificationType::ProgressBar && notification->compare_text(text)) { + dynamic_cast(notification.get())->error(); + wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0); + break; + } + } +} bool NotificationManager::push_notification_data(const NotificationData& notification_data, int timestamp) { return push_notification_data(std::make_unique(notification_data, m_id_provider, m_evt_handler), timestamp); @@ -1103,7 +1159,8 @@ bool NotificationManager::activate_existing(const NotificationManager::PopNotifi const std::string &new_text = notification->get_data().text1; for (auto it = m_pop_notifications.begin(); it != m_pop_notifications.end(); ++it) { if ((*it)->get_type() == new_type && !(*it)->is_finished()) { - if (new_type == NotificationType::CustomNotification || new_type == NotificationType::PlaterWarning) { + if (std::find(m_multiple_types.begin(), m_multiple_types.end(), new_type) != m_multiple_types.end()) { + //if (new_type == NotificationType::CustomNotification || new_type == NotificationType::PlaterWarning || new_type == NotificationType::ProgressBar) { if (!(*it)->compare_text(new_text)) continue; } else if (new_type == NotificationType::SlicingWarning) { diff --git a/src/slic3r/GUI/NotificationManager.hpp b/src/slic3r/GUI/NotificationManager.hpp index 768f941a7..2baaf7054 100644 --- a/src/slic3r/GUI/NotificationManager.hpp +++ b/src/slic3r/GUI/NotificationManager.hpp @@ -142,6 +142,8 @@ public: // notification with progress bar void push_progress_bar_notification(const std::string& text, float percentage = 0); void set_progress_bar_percentage(const std::string& text, float percentage); + void progress_bar_show_canceled(const std::string& text); + void progress_bar_show_error(const std::string& text); // Close old notification ExportFinished. void new_export_began(bool on_removable); // finds ExportFinished notification and closes it if it was to removable device @@ -228,7 +230,7 @@ private: bool is_hovered() const { return m_state == EState::Hovered; } // Call after every size change - void init(); + virtual void init(); // Part of init() virtual void count_spaces(); // Calculetes correct size but not se it in imgui! @@ -341,8 +343,28 @@ private: class ProgressBarNotification : public PopNotification { public: + enum class ProgressBarState + { + PB_PROGRESS, + PB_ERROR, + PB_CANCELLED, + PB_COMPLETED + }; ProgressBarNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler, float percentage) : PopNotification(n, id_provider, evt_handler) { set_percentage(percentage); } - void set_percentage(float percent) { m_percentage = percent; if (percent >= 1.0f) m_progress_complete = true; else m_progress_complete = false; } + void set_percentage(float percent) + { + if (m_pb_state == ProgressBarState::PB_CANCELLED) + return; + m_percentage = percent; + if (percent >= 1.0f) + m_pb_state = ProgressBarState::PB_COMPLETED; + else if (percent < 0.0f ) + m_pb_state = ProgressBarState::PB_ERROR; + else + m_pb_state = ProgressBarState::PB_PROGRESS; + } + void cancel() { m_pb_state = ProgressBarState::PB_CANCELLED; } + void error() { m_pb_state = ProgressBarState::PB_ERROR; } protected: virtual void init(); virtual void render_text(ImGuiWrapper& imgui, @@ -351,8 +373,12 @@ private: void render_bar(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y); - bool m_progress_complete{ false }; - float m_percentage; + float m_percentage; + ProgressBarState m_pb_state { ProgressBarState::PB_PROGRESS }; + }; + + class PrintHostUploadNotification : public ProgressBarNotification + { }; class ExportFinishedNotification : public PopNotification @@ -413,7 +439,8 @@ private: bool m_move_from_overlay { false }; // Timestamp of last rendering int64_t m_last_render { 0LL }; - + // Notification types that can be shown multiple types at once (compared by text) + const std::vector m_multiple_types = { NotificationType::CustomNotification, NotificationType::PlaterWarning, NotificationType::ProgressBar }; //prepared (basic) notifications const std::vector basic_notifications = { {NotificationType::Mouse3dDisconnected, NotificationLevel::RegularNotification, 10, _u8L("3D Mouse disconnected.") }, diff --git a/src/slic3r/GUI/PrintHostDialogs.cpp b/src/slic3r/GUI/PrintHostDialogs.cpp index a094b70e9..921337d4a 100644 --- a/src/slic3r/GUI/PrintHostDialogs.cpp +++ b/src/slic3r/GUI/PrintHostDialogs.cpp @@ -25,6 +25,7 @@ #include "wxExtensions.hpp" #include "MainFrame.hpp" #include "libslic3r/AppConfig.hpp" +#include "NotificationManager.hpp" namespace fs = boost::filesystem; @@ -280,6 +281,9 @@ void PrintHostQueueDialog::append_job(const PrintHostJob &job) job_list->AppendItem(fields, static_cast(ST_NEW)); // Both strings are UTF-8 encoded. upload_names.emplace_back(job.printhost->get_host(), job.upload_data.upload_path.string()); + + std::string notification_text = "[" + std::to_string(job_list->GetItemCount()) + "] " + job.upload_data.upload_path.string() + " -> " + job.printhost->get_host(); + wxGetApp().notification_manager()->push_progress_bar_notification(notification_text); } void PrintHostQueueDialog::on_dpi_changed(const wxRect &suggested_rect) @@ -345,6 +349,15 @@ void PrintHostQueueDialog::on_progress(Event &evt) } on_list_select(); + + if (evt.progress > 0) + { + wxVariant nm, hst; + job_list->GetValue(nm, evt.job_id, COL_FILENAME); + job_list->GetValue(hst, evt.job_id, COL_HOST); + std::string notification_text = "[" + std::to_string(evt.job_id + 1) + "] " + boost::nowide::narrow(nm.GetString()) + " -> " + boost::nowide::narrow(hst.GetString()); + wxGetApp().notification_manager()->set_progress_bar_percentage(notification_text, 100 / evt.progress); + } } void PrintHostQueueDialog::on_error(Event &evt) @@ -360,6 +373,12 @@ void PrintHostQueueDialog::on_error(Event &evt) on_list_select(); GUI::show_error(nullptr, errormsg); + + wxVariant nm, hst; + job_list->GetValue(nm, evt.job_id, COL_FILENAME); + job_list->GetValue(hst, evt.job_id, COL_HOST); + std::string notification_text = "[" + std::to_string(evt.job_id + 1) + "] " + boost::nowide::narrow(nm.GetString()) + " -> " + boost::nowide::narrow(hst.GetString()); + wxGetApp().notification_manager()->progress_bar_show_error(notification_text); } void PrintHostQueueDialog::on_cancel(Event &evt) @@ -370,6 +389,12 @@ void PrintHostQueueDialog::on_cancel(Event &evt) job_list->SetValue(wxVariant(0), evt.job_id, COL_PROGRESS); on_list_select(); + + wxVariant nm, hst; + job_list->GetValue(nm, evt.job_id, COL_FILENAME); + job_list->GetValue(hst, evt.job_id, COL_HOST); + std::string notification_text = "[" + std::to_string(evt.job_id + 1) + "] " + boost::nowide::narrow(nm.GetString()) + " -> " + boost::nowide::narrow(hst.GetString()); + wxGetApp().notification_manager()->progress_bar_show_canceled(notification_text); } void PrintHostQueueDialog::get_active_jobs(std::vector>& ret)