diff --git a/resources/images/score_star_dark.svg b/resources/images/score_star_dark.svg
new file mode 100644
index 0000000000..d703eafb73
--- /dev/null
+++ b/resources/images/score_star_dark.svg
@@ -0,0 +1,3 @@
+
diff --git a/resources/images/score_star_light.svg b/resources/images/score_star_light.svg
new file mode 100644
index 0000000000..909390e078
--- /dev/null
+++ b/resources/images/score_star_light.svg
@@ -0,0 +1,3 @@
+
diff --git a/resources/images/single_little_photo.svg b/resources/images/single_little_photo.svg
new file mode 100644
index 0000000000..91fe146649
--- /dev/null
+++ b/resources/images/single_little_photo.svg
@@ -0,0 +1,6 @@
+
diff --git a/src/slic3r/GUI/StatusPanel.cpp b/src/slic3r/GUI/StatusPanel.cpp
index db7ae2d866..a4ca7e9163 100644
--- a/src/slic3r/GUI/StatusPanel.cpp
+++ b/src/slic3r/GUI/StatusPanel.cpp
@@ -15,6 +15,7 @@
#include "RecenterDialog.hpp"
#include "CalibUtils.hpp"
+#include
namespace Slic3r { namespace GUI {
@@ -109,6 +110,28 @@ static std::vector message_containing_done{
#define AXIS_MIN_SIZE (wxSize(FromDIP(220), FromDIP(220)))
#define EXTRUDER_IMAGE_SIZE (wxSize(FromDIP(48), FromDIP(76)))
+static void market_model_scoring_page(int design_id)
+{
+ std::string url;
+ std::string country_code = GUI::wxGetApp().app_config->get_country_code();
+ std::string model_http_url = GUI::wxGetApp().get_model_http_url(country_code);
+ if (GUI::wxGetApp().getAgent()->get_model_mall_detail_url(&url, std::to_string(design_id)) == 0) {
+ std::string user_id = GUI::wxGetApp().getAgent()->get_user_id();
+ boost::algorithm::replace_first(url, "models", "u/" + user_id + "/rating");
+ // Prevent user_id from containing design_id
+ size_t sign_in = url.find("/rating");
+ std::string sub_url = url.substr(0, sign_in + 7);
+ url.erase(0, sign_in + 7);
+ boost::algorithm::replace_first(url, std::to_string(design_id), "");
+ url = sub_url + url;
+ try {
+ if (!url.empty()) { wxLaunchDefaultBrowser(url); }
+ } catch (...) {
+ return;
+ }
+ }
+}
+
PrintingTaskPanel::PrintingTaskPanel(wxWindow* parent, PrintingTaskType type)
: wxPanel(parent, wxID_ANY,wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL)
{
@@ -347,28 +370,10 @@ void PrintingTaskPanel::create_panel(wxWindow* parent)
penel_bottons->SetSizer(bSizer_buttons);
penel_bottons->Layout();
- StateColor btn_bg_green(std::pair(AMS_CONTROL_DISABLE_COLOUR, StateColor::Disabled), std::pair(wxColour(27, 136, 68), StateColor::Pressed),
- std::pair(wxColour(61, 203, 115), StateColor::Hovered), std::pair(AMS_CONTROL_BRAND_COLOUR, StateColor::Normal));
- StateColor btn_bd_green(std::pair(AMS_CONTROL_WHITE_COLOUR, StateColor::Disabled), std::pair(AMS_CONTROL_BRAND_COLOUR, StateColor::Enabled));
-
- m_button_market_scoring = new Button(parent, _L("Immediately score"));
- m_button_market_scoring->SetBackgroundColor(btn_bg_green);
- m_button_market_scoring->SetBorderColor(btn_bd_green);
- m_button_market_scoring->SetTextColor(wxColour("#FFFFFE"));
- m_button_market_scoring->SetSize(wxSize(FromDIP(128), FromDIP(26)));
- m_button_market_scoring->SetMinSize(wxSize(-1, FromDIP(26)));
- m_button_market_scoring->SetCornerRadius(FromDIP(13));
-
- wxBoxSizer *bSizer_market_scoring = new wxBoxSizer(wxHORIZONTAL);
- bSizer_market_scoring->Add(m_button_market_scoring);
- bSizer_market_scoring->Add(0, 0, 1, wxEXPAND, 0);
- m_button_market_scoring->Hide();
-
bSizer_subtask_info->Add(0, 0, 0, wxEXPAND | wxTOP, FromDIP(14));
bSizer_subtask_info->Add(bSizer_task_name, 0, wxEXPAND|wxRIGHT, FromDIP(18));
bSizer_subtask_info->Add(m_staticText_profile_value, 0, wxEXPAND | wxTOP, FromDIP(5));
bSizer_subtask_info->Add(m_printing_stage_value, 0, wxEXPAND | wxTOP, FromDIP(5));
- bSizer_subtask_info->Add(bSizer_market_scoring, 0, wxEXPAND | wxTOP, FromDIP(5));
bSizer_subtask_info->Add(penel_bottons, 0, wxEXPAND | wxTOP, FromDIP(10));
bSizer_subtask_info->Add(m_panel_progress, 0, wxEXPAND|wxRIGHT, FromDIP(25));
@@ -422,6 +427,67 @@ void PrintingTaskPanel::create_panel(wxWindow* parent)
sizer->Add(m_panel_error_txt, 0, wxEXPAND | wxALL, 0);
sizer->Add(0, FromDIP(12), 0);
+ m_score_staticline = new wxPanel(parent, wxID_ANY);
+ m_score_staticline->SetBackgroundColour(wxColour(238, 238, 238));
+ m_score_staticline->Layout();
+ m_score_staticline->Hide();
+ sizer->Add(0, 0, 0, wxTOP, FromDIP(15));
+ sizer->Add(m_score_staticline, 0, wxEXPAND | wxALL, FromDIP(10));
+
+ m_score_subtask_info = new wxPanel(parent, wxID_ANY);
+ m_score_subtask_info->SetBackgroundColour(*wxWHITE);
+
+ wxBoxSizer * static_score_sizer = new wxBoxSizer(wxVERTICAL);
+ wxStaticText *static_score_text = new wxStaticText(m_score_subtask_info, wxID_ANY, "How do you like this printing file?", wxDefaultPosition, wxDefaultSize, 0);
+ static_score_text->Wrap(-1);
+ static_score_sizer->Add(static_score_text, 1, wxEXPAND | wxALL, FromDIP(10));
+
+ m_star_count = 0;
+ wxBoxSizer *static_score_star_sizer = new wxBoxSizer(wxHORIZONTAL);
+ m_score_star.resize(5);
+ for (int i = 0; i < m_score_star.size(); ++i) {
+ m_score_star[i] = new ScalableButton(m_score_subtask_info, wxID_ANY, "score_star_dark", wxEmptyString, wxSize(FromDIP(26), FromDIP(26)), wxDefaultPosition,
+ wxBU_EXACTFIT | wxNO_BORDER, true, 26);
+ m_score_star[i]->Bind(wxEVT_LEFT_DOWN, [this, i](auto &e) {
+ for (int j = 0; j < m_score_star.size(); ++j) {
+ ScalableBitmap light_star = ScalableBitmap(nullptr, "score_star_light", 26);
+ m_score_star[j]->SetBitmap(light_star.bmp());
+ if (m_score_star[j] == m_score_star[i]) {
+ m_star_count = j + 1;
+ break;
+ }
+ }
+ for (int k = m_star_count; k < m_score_star.size(); ++k) {
+ ScalableBitmap dark_star = ScalableBitmap(nullptr, "score_star_dark", 26);
+ m_score_star[k]->SetBitmap(dark_star.bmp());
+ }
+ });
+ static_score_star_sizer->Add(m_score_star[i], 0, wxEXPAND | wxLEFT, FromDIP(10));
+ }
+
+ StateColor btn_bg_green(std::pair(AMS_CONTROL_DISABLE_COLOUR, StateColor::Disabled), std::pair(wxColour(27, 136, 68), StateColor::Pressed),
+ std::pair(wxColour(61, 203, 115), StateColor::Hovered), std::pair(AMS_CONTROL_BRAND_COLOUR, StateColor::Normal));
+ StateColor btn_bd_green(std::pair(AMS_CONTROL_WHITE_COLOUR, StateColor::Disabled), std::pair(AMS_CONTROL_BRAND_COLOUR, StateColor::Enabled));
+
+ m_button_market_scoring = new Button(m_score_subtask_info, _L("Immediately score"));
+ m_button_market_scoring->SetBackgroundColor(btn_bg_green);
+ m_button_market_scoring->SetBorderColor(btn_bd_green);
+ m_button_market_scoring->SetTextColor(wxColour("#FFFFFE"));
+ m_button_market_scoring->SetSize(wxSize(FromDIP(128), FromDIP(26)));
+ m_button_market_scoring->SetMinSize(wxSize(-1, FromDIP(26)));
+ m_button_market_scoring->SetCornerRadius(FromDIP(13));
+
+ static_score_star_sizer->Add(0, 0, 1, wxEXPAND, 0);
+ static_score_star_sizer->Add(m_button_market_scoring, 0, wxEXPAND | wxRIGHT, FromDIP(10));
+ static_score_sizer->Add(static_score_star_sizer, 0, wxEXPAND, FromDIP(10));
+
+ m_score_subtask_info->SetSizer(static_score_sizer);
+ m_score_subtask_info->Layout();
+ m_score_subtask_info->Hide();
+
+ sizer->Add(m_score_subtask_info, 0, wxEXPAND | wxALL, 0);
+ sizer->Add(0, FromDIP(12), 0);
+
if (m_type == CALIBRATION) {
m_panel_printing_title->Hide();
m_bitmap_thumbnail->Hide();
@@ -611,6 +677,16 @@ void PrintingTaskPanel::show_profile_info(bool show, wxString profile /*= wxEmpt
}
}
+void PrintingTaskPanel::market_scoring_show() {
+ m_score_staticline->Show();
+ m_score_subtask_info->Show();
+}
+
+void PrintingTaskPanel::market_scoring_hide() {
+ m_score_staticline->Hide();
+ m_score_subtask_info->Hide();
+}
+
StatusBasePanel::StatusBasePanel(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size, long style, const wxString &name)
: wxScrolledWindow(parent, id, pos, size, wxHSCROLL | wxVSCROLL)
{
@@ -1433,6 +1509,8 @@ StatusPanel::StatusPanel(wxWindow *parent, wxWindowID id, const wxPoint &pos, co
m_buttons.push_back(m_bpButton_e_down_10);
obj = nullptr;
+ m_score_data = new ScoreData;
+ m_score_data->job_id = -1;
/* set default values */
m_switch_lamp->SetValue(false);
m_switch_printing_fan->SetValue(false);
@@ -1543,6 +1621,10 @@ StatusPanel::~StatusPanel()
if (sdcard_hint_dlg != nullptr)
delete sdcard_hint_dlg;
+
+ if (m_score_data != nullptr) {
+ delete m_score_data;
+ }
}
void StatusPanel::init_scaled_buttons()
@@ -1566,7 +1648,29 @@ void StatusPanel::init_scaled_buttons()
void StatusPanel::on_market_scoring(wxCommandEvent &event) {
if (obj && obj->get_modeltask() && obj->get_modeltask()->design_id > 0) {
- market_model_scoring_page(obj->get_modeltask()->design_id);
+ if (m_score_data && m_score_data->job_id == obj->get_modeltask()->job_id) {
+ ScoreDialog m_score_dlg(this, m_score_data);
+ int ret = m_score_dlg.ShowModal();
+
+ if (ret == wxID_OK) {
+ m_score_data->job_id = -1;
+ return;
+ }
+ if (m_score_data != nullptr) { delete m_score_data; }
+ m_score_data = new ScoreData(m_score_dlg.get_score_data());
+ } else {
+ ScoreDialog m_score_dlg(this, obj->get_modeltask()->design_id, obj->get_modeltask()->job_id, obj->get_modeltask()->model_id, obj->get_modeltask()->profile_id,
+ m_project_task_panel->get_star_count());
+ int ret = m_score_dlg.ShowModal();
+ if (ret == wxID_OK) {
+ m_score_data->job_id = -1;
+ return;
+ }
+ if (m_score_data != nullptr) { delete m_score_data; }
+ m_score_data = new ScoreData(m_score_dlg.get_score_data());
+ }
+
+
}
}
@@ -1793,28 +1897,6 @@ void StatusPanel::show_recenter_dialog() {
obj->command_go_home();
}
-void StatusPanel::market_model_scoring_page(int design_id)
-{
- std::string url;
- std::string country_code = GUI::wxGetApp().app_config->get_country_code();
- std::string model_http_url = GUI::wxGetApp().get_model_http_url(country_code);
- if (GUI::wxGetApp().getAgent()->get_model_mall_detail_url(&url, std::to_string(design_id)) == 0) {
- std::string user_id = GUI::wxGetApp().getAgent()->get_user_id();
- boost::algorithm::replace_first(url, "models", "u/" + user_id + "/rating");
- // Prevent user_id from containing design_id
- size_t sign_in = url.find("/rating");
- std::string sub_url = url.substr(0, sign_in + 7);
- url.erase(0, sign_in + 7);
- boost::algorithm::replace_first(url, std::to_string(design_id), "");
- url = sub_url + url;
- try {
- if (!url.empty()) { wxLaunchDefaultBrowser(url); }
- } catch (...) {
- return;
- }
- }
-}
-
void StatusPanel::show_error_message(MachineObject* obj, wxString msg, std::string print_error_str)
{
if (msg.IsEmpty()) {
@@ -2502,7 +2584,7 @@ void StatusPanel::update_subtask(MachineObject *obj)
reset_printing_values();
} else if (obj->is_in_printing() || obj->print_status == "FINISH") {
if (obj->is_in_prepare() || obj->print_status == "SLICING") {
- m_project_task_panel->get_market_scoring_button()->Hide();
+ m_project_task_panel->market_scoring_hide();
m_project_task_panel->enable_abort_button(false);
m_project_task_panel->enable_pause_resume_button(false, "pause_disable");
wxString prepare_text;
@@ -2553,11 +2635,11 @@ void StatusPanel::update_subtask(MachineObject *obj)
if (wxGetApp().has_model_mall()) {
bool is_market_task = obj->get_modeltask() && obj->get_modeltask()->design_id > 0;
if (is_market_task) {
- m_project_task_panel->get_market_scoring_button()->Show();
+ m_project_task_panel->market_scoring_show();
BOOST_LOG_TRIVIAL(info) << "SHOW_SCORE_BTU: design_id [" << obj->get_modeltask()->design_id << "] print_finish [" << m_print_finish << "]";
if (!m_print_finish && IsShownOnScreen()) {
m_print_finish = true;
- int job_id = obj->get_modeltask()->job_id;
+ /*int job_id = obj->get_modeltask()->job_id;
if (wxGetApp().app_config->get("not_show_score_dialog") != "1" && rated_model_id.find(job_id) == rated_model_id.end()) {
MessageDialog dlg(this, _L("Please give a score for your favorite Bambu Market model."), wxString(SLIC3R_APP_FULL_NAME) + " - " + _L("Score"),
wxYES_NO | wxYES_DEFAULT | wxCENTRE);
@@ -2569,15 +2651,15 @@ void StatusPanel::update_subtask(MachineObject *obj)
rated_model_id.insert(job_id);
BOOST_LOG_TRIVIAL(info) << "SHOW_SCORE_DLG: design_id [" << old_design_id << "] print_finish [" << m_print_finish << "] not_show ["
<< wxGetApp().app_config->get("not_show_score_dialog") << "] job_id [" << job_id << "]";
- }
+ }*/
}
} else {
- m_project_task_panel->get_market_scoring_button()->Hide();
+ m_project_task_panel->market_scoring_hide();
}
}
} else {
m_project_task_panel->enable_abort_button(true);
- m_project_task_panel->get_market_scoring_button()->Hide();
+ m_project_task_panel->market_scoring_hide();
if (m_print_finish) {
m_print_finish = false;
}
@@ -2682,7 +2764,7 @@ void StatusPanel::reset_printing_values()
m_project_task_panel->update_progress_percent(NA_STR, wxEmptyString);
- m_project_task_panel->get_market_scoring_button()->Hide();
+ m_project_task_panel->market_scoring_hide();
update_basic_print_data(false);
m_project_task_panel->update_left_time(NA_STR);
m_project_task_panel->update_layers_num(true, wxString::Format(_L("Layer: %s"), NA_STR));
@@ -3732,5 +3814,536 @@ void StatusPanel::msw_rescale()
Layout();
Refresh();
}
+static char *bbl_calc_md5_char(std::string &filename)
+{
+ unsigned char digest[16];
+ MD5_CTX ctx;
+ MD5_Init(&ctx);
+ boost::filesystem::ifstream ifs(filename, std::ios::binary);
+ std::string buf(64 * 1024, 0);
+ const std::size_t & size = boost::filesystem::file_size(filename);
+ std::size_t left_size = size;
+ while (ifs) {
+ ifs.read(buf.data(), buf.size());
+ int read_bytes = ifs.gcount();
+ MD5_Update(&ctx, (unsigned char *) buf.data(), read_bytes);
+ }
+ MD5_Final(digest, &ctx);
+ char *md5_str = new char[33];
+ for (int j = 0; j < 16; j++) { sprintf(&md5_str[j * 2], "%02X", (unsigned int) digest[j]); }
+ md5_str[32] = '\0';
+ return md5_str;
+}
-}} // namespace Slic3r::GUI
+ScoreDialog::ScoreDialog(wxWindow *parent,int design_id, int job_id, std::string model_id, int profile_id, int star_count)
+ : DPIDialog(parent, wxID_ANY, wxString(SLIC3R_APP_FULL_NAME) + " - " + _L("Scoring"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX | wxRESIZE_BORDER)
+ , m_design_id(design_id)
+ , m_job_id(job_id)
+ , m_model_id(model_id)
+ , m_profile_id(profile_id)
+ , m_star_count(star_count)
+ , m_upload_status_code(StatusCode::CODE_NUMBER)
+{
+ wxBoxSizer *m_main_sizer = get_main_sizer();
+
+ this->SetSizer(m_main_sizer);
+ Fit();
+ Layout();
+ wxGetApp().UpdateDlgDarkUI(this);
+}
+
+ScoreDialog::ScoreDialog(wxWindow *parent, ScoreData *score_data)
+ : DPIDialog(parent, wxID_ANY, wxString(SLIC3R_APP_FULL_NAME) + " - " + _L("Scoring"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX | wxRESIZE_BORDER)
+ , m_design_id(score_data->design_id)
+ , m_job_id(score_data->job_id)
+ , m_model_id(score_data->model_id)
+ , m_profile_id(score_data->profile_id)
+ , m_star_count(score_data->star_count)
+ , m_upload_status_code(StatusCode::CODE_NUMBER)
+{
+ wxBoxSizer *m_main_sizer = get_main_sizer(score_data->image,score_data->comment_text);
+ m_need_upload_images = score_data->need_upload_images;
+ m_image_url_paths = score_data->image_url_paths;
+ m_local_to_url_image = score_data->local_to_url_image;
+
+ for (auto image : m_image) {
+ wxString local_image_path = image.second.local_image_url;
+ if (m_need_upload_images.find(local_image_path) == m_need_upload_images.end()) {
+ image.second.is_uploaded = true;
+ }
+ }
+
+ this->SetSizer(m_main_sizer);
+ Fit();
+ Layout();
+ wxGetApp().UpdateDlgDarkUI(this);
+
+}
+
+ScoreDialog::~ScoreDialog() {}
+
+void ScoreDialog::on_dpi_changed(const wxRect &suggested_rect) {}
+
+void ScoreDialog::OnBitmapClicked(wxMouseEvent &event)
+{
+ wxStaticBitmap *clickedBitmap = dynamic_cast(event.GetEventObject());
+ if (m_image.find(clickedBitmap) != m_image.end()) {
+ if (!m_image[clickedBitmap].is_selected) {
+ for (auto panel : m_image[clickedBitmap].image_broad) {
+ panel->Show();
+ }
+ m_image[clickedBitmap].is_selected = true;
+ m_selected_image_list.insert(clickedBitmap);
+ } else {
+ for (auto panel : m_image[clickedBitmap].image_broad) {
+ panel->Hide();
+ }
+ m_image[clickedBitmap].is_selected = false;
+ m_selected_image_list.erase(clickedBitmap);
+ m_selected_image_list.erase(clickedBitmap);
+ }
+ }
+ if (m_selected_image_list.empty())
+ m_delete_photo->Hide();
+ else
+ m_delete_photo->Show();
+ Fit();
+ Layout();
+
+}
+
+void ScoreDialog::add_need_upload_imgs() {
+ for (auto bitmap : m_image) {
+ wxString local_image_path = bitmap.second.local_image_url;
+ if (!bitmap.second.is_uploaded) {
+ m_need_upload_images.insert(local_image_path);
+ } else {
+ if (m_need_upload_images.find(local_image_path) != m_need_upload_images.end()) {
+ m_need_upload_images.erase(local_image_path);
+ }
+ }
+ }
+}
+
+void ScoreDialog::init() {
+ SetBackgroundColour(*wxWHITE);
+ SetMinSize(wxSize(FromDIP(540), FromDIP(380)));
+
+ // icon
+ std::string icon_path = (boost::format("%1%/images/BambuStudio.ico") % resources_dir()).str();
+ SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO));
+}
+
+wxBoxSizer *ScoreDialog::get_score_sizer() {
+ wxBoxSizer *score_sizer = new wxBoxSizer(wxHORIZONTAL);
+ wxStaticText *static_score_text = new wxStaticText(this, wxID_ANY, _L("Scoring"), wxDefaultPosition, wxDefaultSize, 0);
+ static_score_text->Wrap(-1);
+ score_sizer->Add(static_score_text, 1, wxEXPAND | wxLEFT, FromDIP(24));
+ score_sizer->Add(0, 0, 1, wxEXPAND, 0);
+ return score_sizer;
+}
+
+wxBoxSizer *ScoreDialog::get_star_sizer()
+{
+ wxBoxSizer *static_score_star_sizer = new wxBoxSizer(wxHORIZONTAL);
+ m_score_star.resize(5);
+ for (int i = 0; i < m_score_star.size(); ++i) {
+ if (i < m_star_count) {
+ m_score_star[i] = new ScalableButton(this, wxID_ANY, "score_star_light", wxEmptyString, wxSize(FromDIP(26), FromDIP(26)), wxDefaultPosition,
+ wxBU_EXACTFIT | wxNO_BORDER, true, 26);
+ } else
+ m_score_star[i] = new ScalableButton(this, wxID_ANY, "score_star_dark", wxEmptyString, wxSize(FromDIP(26), FromDIP(26)), wxDefaultPosition,
+ wxBU_EXACTFIT | wxNO_BORDER, true, 26);
+
+ m_score_star[i]->Bind(wxEVT_LEFT_DOWN, [this, i](auto &e) {
+ for (int j = 0; j < m_score_star.size(); ++j) {
+ ScalableBitmap light_star = ScalableBitmap(nullptr, "score_star_light", 26);
+ m_score_star[j]->SetBitmap(light_star.bmp());
+ if (m_score_star[j] == m_score_star[i]) {
+ m_star_count = j + 1;
+ break;
+ }
+ }
+ for (int k = m_star_count; k < m_score_star.size(); ++k) {
+ ScalableBitmap dark_star = ScalableBitmap(nullptr, "score_star_dark", 26);
+ m_score_star[k]->SetBitmap(dark_star.bmp());
+ }
+ });
+ static_score_star_sizer->Add(m_score_star[i], 0, wxEXPAND | wxLEFT, FromDIP(20));
+ }
+
+ return static_score_star_sizer;
+}
+
+wxBoxSizer* ScoreDialog::get_comment_text_sizer() {
+ wxBoxSizer* m_comment_sizer = new wxBoxSizer(wxHORIZONTAL);
+ wxStaticText *static_comment_text = new wxStaticText(this, wxID_ANY, _L("Comment"), wxDefaultPosition, wxDefaultSize, 0);
+ static_comment_text->Wrap(-1);
+ m_comment_sizer->Add(static_comment_text, 1, wxEXPAND | wxLEFT, FromDIP(24));
+ m_comment_sizer->Add(0, 0, 1, wxEXPAND, 0);
+ return m_comment_sizer;
+}
+
+void ScoreDialog::create_comment_text(const wxString& comment) {
+ m_comment_text = new wxTextCtrl(this, wxID_ANY, "", wxDefaultPosition, wxSize(FromDIP(492), FromDIP(104)), wxTE_MULTILINE);
+ m_comment_text->SetLabelText(comment);
+ m_comment_text->SetHint(_L("Rate this print"));
+ m_comment_text->SetBackgroundColour(*wxWHITE);
+ m_comment_text->SetForegroundColour(wxColor("#BBBBBB"));
+ m_comment_text->SetMinSize(wxSize(FromDIP(492), FromDIP(104)));
+
+ m_comment_text->Bind(wxEVT_SET_FOCUS, [this](auto &event) {
+ if (wxGetApp().dark_mode()) {
+ m_comment_text->SetForegroundColour(wxColor(*wxWHITE));
+ } else
+ m_comment_text->SetForegroundColour(wxColor(*wxBLACK));
+ m_comment_text->Refresh();
+ event.Skip();
+ });
+}
+
+wxBoxSizer *ScoreDialog::get_photo_btn_sizer() {
+ wxBoxSizer * m_photo_sizer = new wxBoxSizer(wxHORIZONTAL);
+ ScalableBitmap little_photo = ScalableBitmap(this, "single_little_photo", 20);
+ wxStaticBitmap *little_photo_img = new wxStaticBitmap(this, wxID_ANY, little_photo.bmp(), wxDefaultPosition, wxSize(FromDIP(20), FromDIP(20)), 0);
+ m_photo_sizer->Add(little_photo_img, 0, wxEXPAND | wxLEFT, FromDIP(24));
+ m_add_photo = new Label(this, _L("Add Photo"));
+ m_add_photo->SetBackgroundColour(*wxWHITE);
+ m_add_photo->SetForegroundColour(wxColor("#898989"));
+ m_add_photo->SetSize(wxSize(-1, FromDIP(20)));
+ m_photo_sizer->Add(m_add_photo, 0, wxEXPAND | wxLEFT, FromDIP(12));
+
+ m_delete_photo = new Label(this, _L("Delete Photo"));
+ m_delete_photo->SetBackgroundColour(*wxWHITE);
+ m_delete_photo->SetForegroundColour(wxColor("#898989"));
+ m_delete_photo->SetSize(wxSize(-1, FromDIP(20)));
+ m_photo_sizer->Add(m_delete_photo, 0, wxEXPAND | wxLEFT, FromDIP(12));
+ m_delete_photo->Hide();
+ m_photo_sizer->Add(0, 0, 1, wxEXPAND, 0);
+
+ m_add_photo->Bind(wxEVT_LEFT_DOWN, [this](auto &e) {
+ // add photo logic
+ wxFileDialog openFileDialog(this, "Select Images", "", "", "Image files (*.bmp;*.png;*.jpg)|*.bmp;*.png;*.jpg", wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE);
+
+ if (openFileDialog.ShowModal() == wxID_CANCEL) return;
+
+ wxArrayString filePaths;
+ openFileDialog.GetPaths(filePaths);
+ wxArrayString filePaths_reduction;
+ for (int i = 0; i < filePaths.GetCount(); i++) { //It's ugly, but useful
+ bool is_repeat = false;
+ for (auto image : m_image) {
+ if (filePaths[i] == image.second.local_image_url) {
+ is_repeat = true;
+ continue;
+ }
+ }
+ if (!is_repeat) {
+ filePaths_reduction.push_back(filePaths[i]);
+ if (filePaths_reduction.size() + m_image.size() > m_photo_nums) {
+ break;
+ }
+ }
+
+ }
+
+ load_photo(filePaths_reduction);
+
+ m_image_sizer->Layout();
+ this->Fit();
+ this->Layout();
+ });
+
+ m_delete_photo->Bind(wxEVT_LEFT_DOWN, [this](auto &e) {
+ for (auto it = m_selected_image_list.begin(); it != m_selected_image_list.end();) {
+ auto bitmap = *it;
+ m_image_sizer->Detach(m_image[bitmap].image_tb_broad);
+ m_image[bitmap].image_tb_broad->DeleteWindows();
+ wxString local_image_path = m_image[bitmap].local_image_url;
+ if (m_need_upload_images.find(local_image_path) != m_need_upload_images.end()) { m_need_upload_images.erase(local_image_path); }
+ if (m_local_to_url_image.find(local_image_path) != m_local_to_url_image.end()) { m_local_to_url_image.erase(local_image_path); }
+
+ m_image.erase(bitmap);
+ it = m_selected_image_list.erase(it);
+ }
+ m_image_url_paths.clear();
+ for (auto local_to_url_image : m_local_to_url_image) { m_image_url_paths.push_back(local_to_url_image.second); }
+ m_delete_photo->Hide();
+ m_image_sizer->Layout();
+ Layout();
+ });
+
+ return m_photo_sizer;
+}
+
+wxBoxSizer *ScoreDialog::get_button_sizer()
+{
+ wxBoxSizer *bSizer_button = new wxBoxSizer(wxHORIZONTAL);
+ bSizer_button->Add(0, 0, 1, wxEXPAND, 0);
+
+ StateColor btn_bg_green(std::pair(wxColour(27, 136, 68), StateColor::Pressed), std::pair(wxColour(61, 203, 115), StateColor::Hovered),
+ std::pair(AMS_CONTROL_BRAND_COLOUR, StateColor::Normal));
+
+ m_button_ok = new Button(this, _L("OK"));
+ m_button_ok->SetBackgroundColor(btn_bg_green);
+ m_button_ok->SetBorderColor(*wxWHITE);
+ m_button_ok->SetTextColor(wxColour(0xFFFFFE));
+ m_button_ok->SetFont(Label::Body_12);
+ m_button_ok->SetSize(wxSize(FromDIP(58), FromDIP(24)));
+ m_button_ok->SetMinSize(wxSize(FromDIP(58), FromDIP(24)));
+ m_button_ok->SetCornerRadius(FromDIP(12));
+ bSizer_button->Add(m_button_ok, 0, wxRIGHT, FromDIP(24));
+
+ m_button_ok->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent &e) {
+ m_upload_status_code = StatusCode::UPLOAD_PROGRESS;
+
+ if (m_star_count == 0) {
+ MessageDialog dlg(this, _L("Please click on the star first."), wxString(SLIC3R_APP_FULL_NAME) + " - " + _L("InFo"), wxOK);
+ dlg.ShowModal();
+ return;
+ }
+
+ add_need_upload_imgs();
+
+ std::string comment = into_u8(m_comment_text->GetValue());
+ unsigned int http_code;
+ std::string http_error;
+ wxString error_info;
+
+ if (!m_need_upload_images.empty()) {
+ std::string config;
+ int ret = wxGetApp().getAgent()->get_oss_config(config, wxGetApp().app_config->get_country_code(), http_code, http_error);
+ if (ret == -1) {
+ error_info += into_u8(_L("Get oss config failed.")) + "\n\thttp code: " + std::to_string(http_code) + "\n\thttp error: " + http_error;
+ m_upload_status_code = StatusCode::UPLOAD_EXIST_ISSUE;
+ }
+ if (m_upload_status_code == StatusCode::UPLOAD_PROGRESS) {
+ int need_upload_nums = m_need_upload_images.size();
+ int upload_nums = 0;
+ int upload_failed_nums = 0;
+ ProgressDialog *progress_dialog = new ProgressDialog(_L("Upload Pictrues"), wxString("..."), need_upload_nums, this);
+ for (std::set::iterator it = m_need_upload_images.begin(); it != m_need_upload_images.end();) {
+ wxString need_upload = *it;
+ std::string need_upload_uf8 = into_u8(need_upload);
+ ret = wxGetApp().getAgent()->put_rating_picture_oss(config, need_upload_uf8, m_model_id, m_profile_id, http_code, http_error);
+ switch (ret) {
+ case 0:
+ upload_nums++;
+ m_image_url_paths.push_back(need_upload_uf8);
+ m_local_to_url_image[*it] = need_upload_uf8;
+ it = m_need_upload_images.erase(it);
+ progress_dialog->Update(upload_nums, _L("Number of images successfully uploaded") + ": " + std::to_string(upload_nums) + "/" + std::to_string(need_upload_nums));
+ progress_dialog->Fit();
+ BOOST_LOG_TRIVIAL(info) << "put_rating_picture_oss: model_id [" << m_model_id << "] profile_id [" << m_profile_id << "] http_code [" << http_code
+ << "] http_error [" << http_error << "] config [" << config << "] image_path [" << need_upload << "]";
+ break;
+ case -1:
+ error_info += need_upload + _L(" upload failed").ToUTF8().data() + "\n\thttp code:" + std::to_string(http_code) + "\n\thttp_error:" + http_error + "\n";
+ m_upload_status_code = StatusCode::UPLOAD_IMG_FAILED;
+ ++it;
+ break;
+ case BAMBU_NETWORK_ERR_PARSE_CONFIG_FAILED:
+ error_info += need_upload + _L("upload config prase failed\n").ToUTF8().data() + "\n";
+ m_upload_status_code = StatusCode::UPLOAD_IMG_FAILED;
+ ++it;
+ break;
+ case BAMBU_NETWORK_ERR_NO_CORRESPONDING_BUCKET:
+ error_info += need_upload + _L("No corresponding storage bucket\n").ToUTF8().data() + "\n";
+ m_upload_status_code = StatusCode::UPLOAD_IMG_FAILED;
+ ++it;
+ break;
+ case BAMBU_NETWORK_ERR_OPEN_FILE_FAILED:
+ error_info += need_upload + _L("can not be opened\n").ToUTF8().data() + "\n";
+ m_upload_status_code = StatusCode::UPLOAD_IMG_FAILED;
+ ++it;
+ break;
+ }
+ }
+ progress_dialog->Hide();
+ if (progress_dialog) {
+ delete progress_dialog;
+ }
+ for (auto bitmap : m_image) {
+ wxString local_image_path = bitmap.second.local_image_url;
+ if (m_local_to_url_image.find(local_image_path) != m_local_to_url_image.end()) {
+ m_image[bitmap.first].is_uploaded = true;
+ }
+ }
+
+ if (m_upload_status_code == StatusCode::UPLOAD_IMG_FAILED) {
+ std::string upload_failed_images = into_u8(_L("The following issues occurred during the process of uploading images. Do you want to ignore them?\n\n"));
+ MessageDialog dlg_info(this, upload_failed_images + error_info, wxString(_L("info")), wxOK | wxNO | wxCENTER);
+ if (dlg_info.ShowModal() == wxID_OK) { m_upload_status_code == StatusCode::UPLOAD_PROGRESS; }
+ }
+ }
+ }
+
+ if (m_upload_status_code == StatusCode::UPLOAD_PROGRESS) {
+ int ret = wxGetApp().getAgent()->put_model_mall_rating(m_job_id, m_star_count, comment, m_image_url_paths, http_code, http_error);
+ MessageDialog *dlg_info;
+ switch (ret) {
+ case 0: EndModal(wxID_OK); break;
+ case BAMBU_NETWORK_ERR_GET_RATING_ID_FAILED:
+ dlg_info = new MessageDialog(this, _L("Synchronizing the printing results. Please retry a few seconds later."), wxString(_L("info")), wxOK | wxCENTER);
+ dlg_info->ShowModal();
+ delete dlg_info;
+ break;
+ default: // Upload failed and obtaining instance_id failed
+ if (ret == -1)
+ error_info += _L("Upload failed\n").ToUTF8().data();
+ else
+ error_info += _L("obtaining instance_id failed\n").ToUTF8().data();
+ if (!error_info.empty()) { BOOST_LOG_TRIVIAL(info) << error_info; }
+
+ dlg_info = new MessageDialog(this, _L("Your comment result cannot be uploaded due to some reasons. Would you like to redirect to the webpage for storing?"),
+ wxString(_L("info")), wxOK | wxNO | wxCENTER);
+ if (dlg_info->ShowModal() == wxID_OK) {
+ market_model_scoring_page(m_design_id);
+ EndModal(wxID_OK);
+ }
+ delete dlg_info;
+ break;
+ }
+ } else if (m_upload_status_code == StatusCode::UPLOAD_IMG_FAILED) {
+ MessageDialog *dlg_info = new MessageDialog(this, _L("Some of your images failed to upload. Would you like to redirect to the webpage for storing?"),
+ wxString(_L("info")), wxOK | wxNO | wxCENTER);
+ if (dlg_info->ShowModal() == wxID_OK) {
+ market_model_scoring_page(m_design_id);
+ EndModal(wxID_OK);
+ }
+ delete dlg_info;
+ if (!error_info.empty()) { BOOST_LOG_TRIVIAL(info) << error_info; }
+ }
+ });
+
+ StateColor btn_bg_white(std::pair(wxColour(206, 206, 206), StateColor::Pressed), std::pair(wxColour(238, 238, 238), StateColor::Hovered),
+ std::pair(*wxWHITE, StateColor::Normal));
+
+ m_button_cancel = new Button(this, _L("Cancel"));
+ m_button_cancel->SetBackgroundColor(btn_bg_white);
+ m_button_cancel->SetBorderColor(wxColour(38, 46, 48));
+ m_button_cancel->SetFont(Label::Body_12);
+ m_button_cancel->SetSize(wxSize(FromDIP(58), FromDIP(24)));
+ m_button_cancel->SetMinSize(wxSize(FromDIP(58), FromDIP(24)));
+ m_button_cancel->SetCornerRadius(FromDIP(12));
+ bSizer_button->Add(m_button_cancel, 0, wxRIGHT, FromDIP(24));
+
+ m_button_cancel->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent &e) { EndModal(wxID_CANCEL); });
+
+ return bSizer_button;
+}
+
+void ScoreDialog::load_photo(const wxArrayString &filePaths)
+{
+ for (size_t i = 0; i < filePaths.GetCount(); ++i) {
+ if (m_image.size() < m_photo_nums) {
+ wxString filePath = filePaths[i];
+
+ ImageMsg cur_image_msg;
+ wxStaticBitmap *imageCtrl = new wxStaticBitmap(this, wxID_ANY, wxBitmap(wxImage(filePath, wxBITMAP_TYPE_ANY).Rescale(FromDIP(80), FromDIP(60))), wxDefaultPosition,
+ wxDefaultSize, 0);
+ imageCtrl->Bind(wxEVT_LEFT_DOWN, &ScoreDialog::OnBitmapClicked, this);
+ cur_image_msg.local_image_url = filePath;
+ cur_image_msg.is_uploaded = false;
+
+ // tb: top and bottom lr: left and right
+ auto m_image_tb_broad = new wxBoxSizer(wxVERTICAL);
+ auto line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1), wxTAB_TRAVERSAL);
+ line_top->SetBackgroundColour(wxColour(0xA6, 0xa9, 0xAA));
+ m_image_tb_broad->Add(line_top, 0, wxEXPAND, 0);
+ cur_image_msg.image_broad.push_back(line_top);
+ line_top->Hide();
+
+ auto m_image_lr_broad = new wxBoxSizer(wxHORIZONTAL);
+ auto line_left = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(1, -1), wxTAB_TRAVERSAL);
+ line_left->SetBackgroundColour(wxColour(0xA6, 0xa9, 0xAA));
+ m_image_lr_broad->Add(line_left, 0, wxEXPAND, 0);
+ cur_image_msg.image_broad.push_back(line_left);
+ line_left->Hide();
+
+ m_image_lr_broad->Add(imageCtrl, 0, wxALL, 5);
+
+ auto line_right = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(1, -1), wxTAB_TRAVERSAL);
+ line_right->SetBackgroundColour(wxColour(0xA6, 0xa9, 0xAA));
+ m_image_lr_broad->Add(line_right, 0, wxEXPAND, 0);
+ m_image_tb_broad->Add(m_image_lr_broad, 0, wxEXPAND, 0);
+ cur_image_msg.image_broad.push_back(line_right);
+ line_right->Hide();
+
+ auto line_bottom = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1), wxTAB_TRAVERSAL);
+ line_bottom->SetBackgroundColour(wxColour(0xA6, 0xa9, 0xAA));
+ m_image_tb_broad->Add(line_bottom, 0, wxEXPAND, 0);
+ cur_image_msg.image_broad.push_back(line_bottom);
+ line_bottom->Hide();
+
+ cur_image_msg.is_selected = false;
+ cur_image_msg.image_tb_broad = m_image_tb_broad;
+ m_image[imageCtrl] = cur_image_msg;
+ m_image_sizer->Add(m_image_tb_broad, 0, wxALL, 5);
+
+ } else {
+ MessageDialog *dlg_info_up_to_8 = new MessageDialog(this, _L("You can select up to 5 images."), wxString(_L("info")), wxOK | wxCENTER);
+ dlg_info_up_to_8->ShowModal();
+ break;
+ }
+
+ }
+}
+
+wxBoxSizer *ScoreDialog::get_main_sizer(const wxArrayString &images, const wxString &comment) {
+ init();
+ wxBoxSizer *m_main_sizer = new wxBoxSizer(wxVERTICAL);
+ // top line
+ auto m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1), wxTAB_TRAVERSAL);
+ m_line_top->SetBackgroundColour(wxColour(0xA6, 0xa9, 0xAA));
+ m_main_sizer->Add(m_line_top, 0, wxEXPAND, 0);
+ m_main_sizer->Add(0, 0, 0, wxTOP, FromDIP(32));
+
+ wxBoxSizer *score_sizer = get_score_sizer();
+ m_main_sizer->Add(score_sizer, 0, wxEXPAND, FromDIP(20));
+ m_main_sizer->Add(0, 0, 0, wxBOTTOM, FromDIP(8));
+
+ wxBoxSizer *static_score_star_sizer = get_star_sizer();
+ m_main_sizer->Add(static_score_star_sizer, 0, wxEXPAND | wxBOTTOM, FromDIP(20));
+
+ wxBoxSizer *m_comment_sizer = get_comment_text_sizer();
+ m_main_sizer->Add(m_comment_sizer, 0, wxEXPAND, FromDIP(20));
+ m_main_sizer->Add(0, 0, 0, wxBOTTOM, FromDIP(8));
+
+ create_comment_text(comment);
+ m_main_sizer->Add(m_comment_text, 0, wxLEFT, FromDIP(24));
+
+ wxBoxSizer *m_photo_sizer = get_photo_btn_sizer();
+ m_main_sizer->Add(m_photo_sizer, 0, wxEXPAND | wxTOP, FromDIP(8));
+
+ m_image_sizer = new wxBoxSizer(wxHORIZONTAL);
+ if (!images.empty()) {
+ load_photo(images);
+ }
+ m_main_sizer->Add(m_image_sizer, 0, wxEXPAND | wxLEFT, FromDIP(24));
+ m_main_sizer->Add(0, 0, 1, wxEXPAND, 0);
+
+ wxBoxSizer *bSizer_button = get_button_sizer();
+ m_main_sizer->Add(bSizer_button, 0, wxEXPAND | wxBOTTOM, FromDIP(24));
+
+ return m_main_sizer;
+}
+
+ScoreData ScoreDialog::get_score_data() {
+ ScoreData score_data;
+ score_data.design_id = m_design_id;
+ score_data.job_id = m_job_id;
+ score_data.model_id = m_model_id;
+ score_data.profile_id = m_profile_id;
+ score_data.star_count = m_star_count;
+ score_data.comment_text = m_comment_text->GetValue();
+ score_data.image_url_paths = m_image_url_paths;
+ score_data.need_upload_images = m_need_upload_images;
+ for (auto img : m_image) { score_data.image.push_back(img.second.local_image_url); }
+ score_data.local_to_url_image = m_local_to_url_image;
+
+ return score_data;
+}
+
+} // namespace GUI
+} // namespace Slic3r
\ No newline at end of file
diff --git a/src/slic3r/GUI/StatusPanel.hpp b/src/slic3r/GUI/StatusPanel.hpp
index 0b61cf3b9f..e0dcd39823 100644
--- a/src/slic3r/GUI/StatusPanel.hpp
+++ b/src/slic3r/GUI/StatusPanel.hpp
@@ -61,6 +61,84 @@ enum PrintingTaskType {
CALIBRATION,
};
+struct ScoreData
+{
+ int design_id;
+ int job_id;
+ std::string model_id;
+ int profile_id;
+ int star_count;
+ wxString comment_text;
+ std::vector image_url_paths;
+ std::set need_upload_images;
+ wxArrayString image;
+ std::unordered_map local_to_url_image;
+};
+
+class ScoreDialog : public GUI::DPIDialog
+{
+public:
+ ScoreDialog(wxWindow *parent, int design_id, int job_id, std::string model_id, int profile_id, int star_count = 0);
+ ScoreDialog(wxWindow *parent, ScoreData *score_data);
+ ~ScoreDialog();
+
+ int get_job_id() { return m_job_id;}
+ ScoreData get_score_data();
+
+protected:
+ enum StatusCode {
+ UPLOAD_PROGRESS = 0,
+ UPLOAD_EXIST_ISSUE,
+ UPLOAD_IMG_FAILED,
+ CODE_NUMBER
+ };
+
+ const int m_photo_nums = 5;
+ int m_design_id;
+ int m_job_id;
+ std::string m_model_id;
+ int m_profile_id;
+ int m_star_count;
+ std::vector m_image_url_paths;
+ std::set m_need_upload_images;
+ std::string m_upload_error_info;
+ StatusCode m_upload_status_code;
+
+ struct ImageMsg
+ {
+ wxString local_image_url;
+ vector image_broad;
+ bool is_selected;
+ bool is_uploaded;
+ wxBoxSizer * image_tb_broad = nullptr;
+ };
+
+ std::vector m_score_star;
+ wxTextCtrl * m_comment_text = nullptr;
+ Button * m_button_ok = nullptr;
+ Button * m_button_cancel = nullptr;
+ Label * m_add_photo = nullptr;
+ Label * m_delete_photo = nullptr;
+ wxBoxSizer * m_image_sizer = nullptr;
+ std::unordered_map m_image;
+ std::unordered_set m_selected_image_list;
+ std::unordered_map m_local_to_url_image;
+
+ void on_dpi_changed(const wxRect &suggested_rect) override;
+ void OnBitmapClicked(wxMouseEvent &event);
+ void add_need_upload_imgs();
+
+ void init();
+ wxBoxSizer *get_score_sizer();
+ wxBoxSizer *get_star_sizer();
+ wxBoxSizer *get_comment_text_sizer();
+ void create_comment_text(const wxString& comment = "");
+ wxBoxSizer *get_photo_btn_sizer();
+ wxBoxSizer *get_button_sizer();
+ void load_photo(const wxArrayString &filePaths);
+ wxBoxSizer *get_main_sizer(const wxArrayString &images = wxArrayString(), const wxString &comment = "");
+};
+
class PrintingTaskPanel : public wxPanel
{
public:
@@ -96,6 +174,10 @@ private:
ScalableButton* m_button_abort;
Button* m_button_market_scoring;
Button* m_button_clean;
+ wxPanel * m_score_subtask_info;
+ wxPanel * m_score_staticline;
+ int m_star_count;
+ std::vector m_score_star;
ProgressBar* m_gauge_progress;
Label* m_error_text;
@@ -120,6 +202,8 @@ public:
void update_layers_num(bool show, wxString num = wxEmptyString);
void show_priting_use_info(bool show, wxString time = wxEmptyString, wxString weight = wxEmptyString);
void show_profile_info(bool show, wxString profile = wxEmptyString);
+ void market_scoring_show();
+ void market_scoring_hide();
public:
ScalableButton* get_abort_button() {return m_button_abort;};
@@ -127,6 +211,7 @@ public:
Button* get_market_scoring_button() {return m_button_market_scoring;};
Button* get_clean_button() {return m_button_clean;};
wxStaticBitmap* get_bitmap_thumbnail() {return m_bitmap_thumbnail;};
+ int get_star_count() { return m_star_count; }
};
class StatusBasePanel : public wxScrolledWindow
@@ -370,6 +455,8 @@ protected:
std::map m_print_connect_types;
std::vector