version update

This commit is contained in:
QIDI TECH
2025-08-07 10:44:09 +08:00
parent 73f7cad391
commit cc57492e35
77 changed files with 4433 additions and 228 deletions

View File

@@ -289,8 +289,8 @@ AboutDialog::AboutDialog()
"<a href=\"https://qidi3d.com/\">%5%</a>"
"<br /><br />"
"%6%<br />"
"%11% &copy; 2023-2024 QIDI Technology. <br />"
"%7% &copy; 2016-2024 Prusa Research. <br />"
"%11% &copy; 2023-2025 QIDI Technology. <br />"
"%7% &copy; 2016-2025 Prusa Research. <br />"
"%8% &copy; 2011-2018 Alessandro Ranellucci. <br />"
"<a href=\"http://slic3r.org/\">Slic3r</a> %9% "
"<a href=\"http://www.gnu.org/licenses/agpl-3.0.html\">%10%</a>."

View File

@@ -137,6 +137,19 @@ Downloader::Downloader()
Bind(EVT_DWNLDR_FILE_CANCELED, &Downloader::on_canceled, this);
}
namespace {
bool is_any_subdomain(const std::string& url, const std::vector<std::string>& subdomains)
{
for (const std::string& sub : subdomains)
{
if(FileGet::is_subdomain(url, sub))
return true;
}
return false;
}
}
void Downloader::start_download(const std::string& full_url)
{
assert(m_initialized);
@@ -153,14 +166,14 @@ void Downloader::start_download(const std::string& full_url)
size_t id = get_next_id();
if (!boost::starts_with(escaped_url, "https://") || !FileGet::is_subdomain(escaped_url, "printables.com")) {
std::string msg = format(_L("Download won't start. Download URL doesn't point to https://printables.com : %1%"), escaped_url);
if (!boost::starts_with(escaped_url, "https://") || !is_any_subdomain(escaped_url, {"printables.com", "thingiverse.com"})) {
std::string msg = format(_L("Download won't start. Download URL doesn't point to allowed subdomains : %1%"), escaped_url);
BOOST_LOG_TRIVIAL(error) << msg;
NotificationManager* ntf_mngr = wxGetApp().notification_manager();
ntf_mngr->push_notification(NotificationType::CustomNotification, NotificationManager::NotificationLevel::RegularNotificationLevel, msg);
return;
}
m_downloads.emplace_back(std::make_unique<Download>(id, std::move(escaped_url), this, m_dest_folder, true));
NotificationManager* ntf_mngr = wxGetApp().notification_manager();
ntf_mngr->push_download_URL_progress_notification(id, m_downloads.back()->get_filename(), std::bind(&Downloader::user_action_callback, this, std::placeholders::_1, std::placeholders::_2));
@@ -199,7 +212,7 @@ void Downloader::on_progress(wxCommandEvent& event)
float percent = (float)std::stoi(into_u8(event.GetString())) / 100.f;
//BOOST_LOG_TRIVIAL(error) << "progress " << id << ": " << percent;
NotificationManager* ntf_mngr = wxGetApp().notification_manager();
BOOST_LOG_TRIVIAL(trace) << "Download "<< id << ": " << percent;
//BOOST_LOG_TRIVIAL(trace) << "Download "<< id << ": " << percent;
ntf_mngr->set_download_URL_progress(id, percent);
}
void Downloader::on_error(wxCommandEvent& event)
@@ -247,7 +260,9 @@ bool Downloader::user_action_callback(DownloaderUserAction action, int id)
void Downloader::on_name_change(wxCommandEvent& event)
{
size_t id = event.GetInt();
NotificationManager* ntf_mngr = wxGetApp().notification_manager();
ntf_mngr->set_download_URL_filename(id, into_u8(event.GetString()));
}
void Downloader::on_paused(wxCommandEvent& event)

View File

@@ -8,6 +8,7 @@
#include <boost/algorithm/string.hpp>
#include <boost/nowide/cstdio.hpp>
#include <iostream>
#include <regex>
#include "format.hpp"
#include "GUI.hpp"
@@ -64,6 +65,26 @@ unsigned get_current_pid()
return ::getpid();
#endif
}
std::string extract_filename_from_header(const std::string& headers) {
// Split the headers into lines
std::istringstream header_stream(headers);
std::string line;
while (std::getline(header_stream, line)) {
if (line.find("content-disposition") != std::string::npos) {
// Apply regex to extract filename from the content-disposition line
std::regex filename_regex("filename\\s*=\\s*\"([^\"]+)\"", std::regex::icase);
std::smatch match;
if (std::regex_search(line, match, filename_regex) && match.size() > 1) {
return match.str(1);
}
}
}
return {};
}
}
// int = DOWNLOAD ID; string = file path
@@ -107,6 +128,8 @@ FileGet::priv::priv(int ID, std::string&& url, const std::string& filename, wxEv
, m_dest_folder(dest_folder)
, m_load_after(load_after)
{
// Prevent ':' in filename
m_filename.erase(std::remove(m_filename.begin(), m_filename.end(), ':'), m_filename.end());
}
void FileGet::priv::get_perform()
@@ -125,7 +148,7 @@ void FileGet::priv::get_perform()
std::string extension = dest_path.extension().string();
std::string just_filename = m_filename.substr(0, m_filename.size() - extension.size());
std::string final_filename = just_filename;
// Find unsed filename
// Find unused filename
try {
size_t version = 0;
while (boost::filesystem::exists(m_dest_folder / (final_filename + extension)) || boost::filesystem::exists(m_dest_folder / (final_filename + extension + "." + std::to_string(get_current_pid()) + ".download")))
@@ -150,7 +173,6 @@ void FileGet::priv::get_perform()
}
m_filename = final_filename + extension;
m_tmp_path = m_dest_folder / (m_filename + "." + std::to_string(get_current_pid()) + ".download");
wxCommandEvent* evt = new wxCommandEvent(EVT_DWNLDR_FILE_NAME_CHANGE);
@@ -217,7 +239,12 @@ void FileGet::priv::get_perform()
m_evt_handler->QueueEvent(evt);
return;
}
wxCommandEvent* evt = new wxCommandEvent(EVT_DWNLDR_FILE_PROGRESS);
int percent_total = 100;
evt->SetString(std::to_string(percent_total));
evt->SetInt(m_id);
m_evt_handler->QueueEvent(evt);
if (m_absolute_size < progress.dltotal) {
m_absolute_size = progress.dltotal;
}
@@ -243,13 +270,48 @@ void FileGet::priv::get_perform()
m_written = written_previously + written_this_session;
}
wxCommandEvent* evt = new wxCommandEvent(EVT_DWNLDR_FILE_PROGRESS);
int percent_total = (written_previously + progress.dlnow) * 100 / m_absolute_size;
int percent_total = m_absolute_size == 0 ? 0 : (written_previously + progress.dlnow) * 100 / m_absolute_size;
evt->SetString(std::to_string(percent_total));
evt->SetInt(m_id);
m_evt_handler->QueueEvent(evt);
}
})
.on_headers([&](const std::string& headers) {
// we are looking for content-disposition header in response, to use it as correct filename
std::string new_filename = extract_filename_from_header(headers);
if (new_filename.empty()) {
return;
}
// Find unused filename
boost::filesystem::path temp_dest_path = m_dest_folder / new_filename;
std::string extension = temp_dest_path.extension().string();
std::string just_filename = new_filename.substr(0, new_filename.size() - extension.size());
std::string final_filename = just_filename;
try {
size_t version = 0;
while (boost::filesystem::exists(m_dest_folder / (final_filename + extension)))
{
++version;
if (version > 999) {
BOOST_LOG_TRIVIAL(error) << GUI::format("Failed to find suitable filename. Last name: %1%." , (m_dest_folder / (final_filename + extension)).string());
return;
}
final_filename = GUI::format("%1%(%2%)", just_filename, std::to_string(version));
}
} catch (const boost::filesystem::filesystem_error& e)
{
BOOST_LOG_TRIVIAL(error) << "Failed to resolved filename from headers.";
return;
}
m_filename = final_filename + extension;
dest_path = m_dest_folder / m_filename;
wxCommandEvent* evt = new wxCommandEvent(EVT_DWNLDR_FILE_NAME_CHANGE);
evt->SetString(from_u8(m_filename));
evt->SetInt(m_id);
m_evt_handler->QueueEvent(evt);
})
.on_error([&](std::string body, std::string error, unsigned http_status) {
if (file != NULL)
fclose(file);
@@ -264,15 +326,21 @@ void FileGet::priv::get_perform()
.on_complete([&](std::string body, unsigned /* http_status */) {
try
{
// If server is not sending Content-Length header, the progress function does not write all data to file.
// We need to write it now.
if (written_this_session < body.size()) {
std::string part_for_write = body.substr(written_this_session);
fwrite(part_for_write.c_str(), 1, part_for_write.size(), file);
}
fclose(file);
boost::filesystem::rename(m_tmp_path, dest_path);
}
catch (const std::exception& /*e*/)
catch (const std::exception& e)
{
//TODO: report?
//error_message = GUI::format("Failed to write and move %1% to %2%", tmp_path, dest_path);
wxCommandEvent* evt = new wxCommandEvent(EVT_DWNLDR_FILE_ERROR);
evt->SetString("Failed to write and move.");
evt->SetString(GUI::format("Failed to write and move %1% to %2%", m_tmp_path, dest_path));
evt->SetInt(m_id);
m_evt_handler->QueueEvent(evt);
return;

View File

@@ -688,7 +688,7 @@ wxWindow* CheckBox::GetNewWin(wxWindow* parent, const wxString& label /*= wxEmpt
if (wxGetApp().suppress_round_corners())
return new ::CheckBox(parent, label);
return new ::SwitchButton(parent, label);
return new ::DeviceSwitchButton(parent, label); //y25
}
void CheckBox::SetValue(wxWindow* win, bool value)
@@ -698,7 +698,7 @@ void CheckBox::SetValue(wxWindow* win, bool value)
ch_b->SetValue(value);
}
else {
if (::SwitchButton* ch_b = dynamic_cast<::SwitchButton*>(win))
if (::DeviceSwitchButton* ch_b = dynamic_cast<::DeviceSwitchButton*>(win)) //y25
ch_b->SetValue(value);
}
}
@@ -708,7 +708,7 @@ bool CheckBox::GetValue(wxWindow* win)
if (wxGetApp().suppress_round_corners())
return dynamic_cast<::CheckBox*>(win)->GetValue();
return dynamic_cast<::SwitchButton*>(win)->GetValue();
return dynamic_cast<::DeviceSwitchButton*>(win)->GetValue(); //y25
}
void CheckBox::Rescale(wxWindow* win)
@@ -716,13 +716,13 @@ void CheckBox::Rescale(wxWindow* win)
if (wxGetApp().suppress_round_corners())
dynamic_cast<::CheckBox*>(win)->Rescale();
else
dynamic_cast<::SwitchButton*>(win)->Rescale();
dynamic_cast<::DeviceSwitchButton*>(win)->Rescale(); //y25
}
void CheckBox::SysColorChanged(wxWindow* win)
{
if (!wxGetApp().suppress_round_corners())
dynamic_cast<::SwitchButton*>(win)->SysColorChange();
dynamic_cast<::DeviceSwitchButton*>(win)->SysColorChange(); //y25
}
void CheckBox::SetValue(bool value)
@@ -730,7 +730,7 @@ void CheckBox::SetValue(bool value)
if (wxGetApp().suppress_round_corners())
dynamic_cast<::CheckBox*>(window)->SetValue(value);
else
dynamic_cast<::SwitchButton*>(window)->SetValue(value);
dynamic_cast<::DeviceSwitchButton*>(window)->SetValue(value); //y25
}
bool CheckBox::GetValue()
@@ -738,7 +738,7 @@ bool CheckBox::GetValue()
if (wxGetApp().suppress_round_corners())
return dynamic_cast<::CheckBox*>(window)->GetValue();
return dynamic_cast<::SwitchButton*>(window)->GetValue();
return dynamic_cast<::DeviceSwitchButton*>(window)->GetValue(); //y25
}
void CheckBox::BUILD() {
@@ -831,7 +831,7 @@ void CheckBox::msw_rescale()
void CheckBox::sys_color_changed()
{
Field::sys_color_changed();
if (auto switch_btn = dynamic_cast<::SwitchButton*>(window))
if (auto switch_btn = dynamic_cast<::DeviceSwitchButton*>(window)) //y25
switch_btn->SysColorChange();
}

View File

@@ -16,6 +16,11 @@
#include "WipeTowerDialog.hpp"
//y25
#include "SyncBoxInfoDialog.hpp"
#include "Tab.hpp"
using Slic3r::Preset;
using Slic3r::GUI::format_wxstr;
@@ -303,12 +308,54 @@ FreqChangedParams::FreqChangedParams(wxWindow* parent)
m_og_filament->append_line(line);
m_og_filament->activate();
//y25
m_og_sync = std::make_shared<ConfigOptionsGroup>(parent, "");
DynamicPrintConfig* printer_config = &wxGetApp().preset_bundle->printers.get_edited_preset().config;
m_og_sync->set_config(printer_config);
m_og_sync->hide_labels();
auto add_sync_btn = [this](wxWindow* parent) {
//y26
auto sync_btn = new wxButton(parent, wxID_ANY, _L("Syn filament info from the box"), wxDefaultPosition, wxSize(200, 30), wxBU_EXACTFIT);
wxGetApp().UpdateDarkUI(sync_btn, true);
sync_btn->SetToolTip(_L("Click the sync button to synchronize the Box information to the filament column."));
auto sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(sync_btn, 0, wxALIGN_CENTER_VERTICAL);
sync_btn->Bind(wxEVT_BUTTON, [parent](wxCommandEvent& e){
//y25
std::string ph_host = "";
bool has_select_printer = wxGetApp().preset_bundle->physical_printers.has_selection();
if (has_select_printer) {
PhysicalPrinter& ph_printer = wxGetApp().preset_bundle->physical_printers.get_selected_printer();
ph_host = ph_printer.config.opt_string("print_host");
}
GetBoxInfoDialog dlg(wxGetApp().plater());
if(ph_host.empty()){
dlg.ShowModal();
}
else{
dlg.synchronize_by_ip(ph_host);
}
});
return sizer;
};
line = Line { "", "" };
line.append_only_widget(add_sync_btn);
m_og_sync->append_line(line);
m_og_sync->activate();
m_sizer = new wxBoxSizer(wxVERTICAL);
m_sizer->Add(m_og_fff->sizer, 0, wxEXPAND);
//Y26
m_sizer->Add(m_og_filament->sizer, 0, wxEXPAND);
m_sizer->Add(m_og_sla->sizer, 0, wxEXPAND);
//y25
m_sizer->Add(m_og_sync->sizer, 0, wxEXPAND);
}
void FreqChangedParams::msw_rescale()
@@ -339,7 +386,8 @@ void FreqChangedParams::Show(bool is_fff) const
//Y26
m_og_filament->Show(is_fff);
m_og_sla->Show(!is_fff);
//y25
m_og_sync->Show(is_fff);
// correct showing of the FreqChangedParams sizer when m_wiping_dialog_button is hidden
if (is_fff && !is_wdb_shown)
m_wiping_dialog_button->Hide();

View File

@@ -24,6 +24,8 @@ class FreqChangedParams
//Y26
std::shared_ptr<ConfigOptionsGroup> m_og_filament;
//y25
std::shared_ptr<ConfigOptionsGroup> m_og_sync;
std::shared_ptr<ConfigOptionsGroup> m_og_fff;
std::shared_ptr<ConfigOptionsGroup> m_og_sla;

View File

@@ -1473,7 +1473,8 @@ bool GLCanvas3D::check_volumes_outside_state(GLVolumeCollection& volumes, ModelI
//B52
for (unsigned int vol_idx : volumes_idxs) {
GLVolume* volume = volumes.volumes[vol_idx];
if (!volume->is_modifier && (volume->shader_outside_printer_detection_enabled || (!volume->is_wipe_tower() && volume->composite_id.volume_id >= 0))) {
//y25
if (!volume->is_modifier && (volume->shader_outside_printer_detection_enabled && (!volume->is_wipe_tower() && volume->composite_id.volume_id >= 0))) {
BuildVolume::ObjectState state;
int bed_idx = -1;
if (volume_below(*volume))

View File

@@ -880,8 +880,21 @@ void GLGizmoSlaSupports::draw_island_config() {
ImGui::SameLine();
ImGui::Text("head radius %.2f mm", unscale<float>(sample_config.head_radius));
bool exist_change = false;
// copied from SLAPrint::Steps::support_points()
const SLAPrintObject *po = m_c->selection_info()->print_object();
const SLAPrintObjectConfig &cfg = po->config();
float head_diameter = (cfg.support_tree_type == sla::SupportTreeType::Branching) ?
float(cfg.branchingsupport_head_front_diameter):
float(cfg.support_head_front_diameter); // SupportTreeType::Organic
std::string button_title = "apply " + std::to_string(head_diameter);
ImGui::SameLine();
if (ImGui::Button(button_title.c_str())) {
float density_relative = float(cfg.support_points_density_relative / 100.f);
sample_config = sla::SampleConfigFactory::apply_density(
sla::SampleConfigFactory::create(head_diameter), density_relative);
}
bool exist_change = false;
if (float max_for_one = unscale<float>(sample_config.max_length_for_one_support_point); // [in mm]
ImGui::InputFloat("One support", &max_for_one, .1f, 1.f, "%.2f mm")) {
sample_config.max_length_for_one_support_point = scale_(max_for_one);
@@ -1457,7 +1470,7 @@ SlaGizmoHelpDialog::SlaGizmoHelpDialog()
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
const wxString ctrl = GUI::shortkey_ctrl_prefix();
const wxString alt = GUI::shortkey_alt_prefix();
const wxString shift = wxString("Shift+");
// fonts
const wxFont& font = wxGetApp().small_font();
@@ -1484,9 +1497,9 @@ SlaGizmoHelpDialog::SlaGizmoHelpDialog()
shortcuts.push_back(std::make_pair(_L("Left click"), _L("Add point")));
shortcuts.push_back(std::make_pair(_L("Right click"), _L("Remove point")));
shortcuts.push_back(std::make_pair(_L("Drag"), _L("Move point")));
shortcuts.push_back(std::make_pair(ctrl+_L("Left click"), _L("Add point to selection")));
shortcuts.push_back(std::make_pair(shift+_L("Left click"), _L("Add point to selection")));
shortcuts.push_back(std::make_pair(alt+_L("Left click"), _L("Remove point from selection")));
shortcuts.push_back(std::make_pair(wxString("Shift+")+_L("Drag"), _L("Select by rectangle")));
shortcuts.push_back(std::make_pair(shift+_L("Drag"), _L("Select by rectangle")));
shortcuts.push_back(std::make_pair(alt+_(L("Drag")), _L("Deselect by rectangle")));
shortcuts.push_back(std::make_pair(ctrl+"A", _L("Select all points")));
shortcuts.push_back(std::make_pair("Delete", _L("Remove selected points")));

View File

@@ -0,0 +1,259 @@
///|/ Copyright (c) Prusa Research 2018 - 2023 Vojtěch Bubník @bubnikv, Lukáš Matěna @lukasmatena, Oleksandra Iushchenko @YuSanka, Enrico Turri @enricoturri1966, Tomáš Mészáros @tamasmeszaros, David Kocík @kocikdav, Lukáš Hejl @hejllukas, Pavel Mikuš @Godrak, Filip Sykala @Jony01, Vojtěch Král @vojtechkral
///|/ Copyright (c) 2022 Michael Kirsch
///|/ Copyright (c) 2021 Boleslaw Ciesielski
///|/ Copyright (c) 2019 John Drake @foxox
///|/
///|/ ported from lib/Slic3r/GUI/Plater.pm:
///|/ Copyright (c) Prusa Research 2016 - 2019 Vojtěch Bubník @bubnikv, Vojtěch Král @vojtechkral, Enrico Turri @enricoturri1966, Oleksandra Iushchenko @YuSanka, Lukáš Matěna @lukasmatena, Tomáš Mészáros @tamasmeszaros
///|/ Copyright (c) 2018 Martin Loidl @LoidlM
///|/ Copyright (c) 2017 Matthias Gazzari @qtux
///|/ Copyright (c) Slic3r 2012 - 2016 Alessandro Ranellucci @alranel
///|/ Copyright (c) 2017 Joseph Lenox @lordofhyphens
///|/ Copyright (c) 2015 Daren Schwenke
///|/ Copyright (c) 2014 Mark Hindess
///|/ Copyright (c) 2012 Mike Sheldrake @mesheldrake
///|/ Copyright (c) 2012 Henrik Brix Andersen @henrikbrixandersen
///|/ Copyright (c) 2012 Sam Wong
///|/
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
///|/
#include "LoadStepDialog.hpp"
#include <wx/window.h>
#include <wx/sizer.h>
#include <wx/stattext.h>
#include <wx/radiobut.h>
#include <wx/slider.h>
#include <vector>
#include <utility>
#include "GUI_App.hpp"
#include "format.hpp"
#include "MsgDialog.hpp"
#include "Widgets/CheckBox.hpp"
namespace Slic3r::GUI {
static std::vector<std::pair<std::string, PrecisionParams>> default_step_import_params = {
{"Low" , {0.005, 1. }},
{"Medium" , {0.003, 0.5 }},
{"High" , {0.001, 0.25}},
};
LoadStepDialog::LoadStepDialog(wxWindow* parent, const std::string& filename, double linear_precision, double angle_precision, bool multiple_loading)
: DPIDialog(parent, wxID_ANY, format_wxstr(_L("STEP import quality (%1%)"), filename), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER),
m_params({ linear_precision, angle_precision })
{
#ifdef _WIN32
wxGetApp().UpdateDarkUI(this);
#else
//SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
#endif
const wxFont& font = wxGetApp().normal_font();
SetFont(font);
// Call your custom function manually after constructing base
wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL); // Get the sizer
add_params(main_sizer);
main_sizer->Add(new StaticLine(this), 0, wxEXPAND | wxLEFT | wxRIGHT, em_unit());
wxBoxSizer* bottom_sizer = new wxBoxSizer(wxHORIZONTAL);
m_remember_chb = new ::CheckBox(this, _L("Remember my choice"));
bottom_sizer->Add(m_remember_chb, 0, wxEXPAND | wxRIGHT, 5);
bottom_sizer->AddStretchSpacer();
auto buttons_sizer = CreateStdDialogButtonSizer(wxOK | wxCANCEL);
if (multiple_loading) {
auto apply_btn = new wxButton(this, wxID_APPLY, _L("Apply to all"));
apply_btn->Bind(wxEVT_BUTTON, [this](wxEvent&) {
m_apply_to_all = true;
EndModal(wxID_OK);
});
buttons_sizer->Insert(0, apply_btn, 0, wxRIGHT, 5);
}
bottom_sizer->Add(buttons_sizer, 0, wxEXPAND | wxLEFT, 5);
main_sizer->Add(bottom_sizer, 0, wxEXPAND | wxALL, 10);
SetSizer(main_sizer);
main_sizer->SetSizeHints(this);
enable_customs(!m_default);
// Update DarkUi just for buttons
wxGetApp().UpdateDlgDarkUI(this, true);
}
void LoadStepDialog::add_params(wxSizer* sizer)
{
wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL);
main_sizer->Add(new wxStaticText(this, wxID_ANY, _L("Select requested quality of the mesh after import: ")));
// add radio buttons for selection default parameters
for (const auto& [name, params] : default_step_import_params) {
wxRadioButton* radio_def = new wxRadioButton(this, wxID_ANY, format_wxstr("%1%", _(name)));
radio_def->Bind(wxEVT_RADIOBUTTON, [params_copy = params, this](wxEvent&) {
m_params.linear = params_copy.linear;
m_params.angle = params_copy.angle;
enable_customs(false);
});
bool is_selected = m_params.linear == params.linear && m_params.angle == params.angle;
radio_def->SetValue(is_selected);
m_default |= is_selected;
main_sizer->Add(radio_def, 0, wxLEFT | wxTOP, em_unit());
}
// add radio buttons for set custom parameters
wxRadioButton* radio_custom = new wxRadioButton(this, wxID_ANY, _L("Custom"));
radio_custom->Bind(wxEVT_RADIOBUTTON, [&, this](wxEvent&) {
enable_customs(true);
#ifdef __linux__
this->Fit();
#endif // __linux__
m_params.linear = string_to_double_decimal_point(m_linear_precision_val->GetValue().ToStdString());
m_params.angle = string_to_double_decimal_point(m_angle_precision_val->GetValue().ToStdString());
});
main_sizer->Add(radio_custom, 0, wxLEFT | wxTOP, em_unit());
radio_custom->SetValue(!m_default);
long slyder_style = wxSL_HORIZONTAL | wxSL_TICKS;
long text_ctrl_style = wxTE_PROCESS_ENTER;
#ifdef _WIN32
text_ctrl_style |= wxBORDER_SIMPLE;
#endif
const wxSize def_slider_size = wxSize(15 * em_unit(), wxDefaultCoord);
const wxSize def_editor_size = wxSize(5 * em_unit(), wxDefaultCoord);
const int hgap = 5;
wxFlexGridSizer* grid_sizer = new wxFlexGridSizer(4, em_unit(), hgap);
grid_sizer->SetFlexibleDirection(wxBOTH);
grid_sizer->AddGrowableCol(1, 1);
grid_sizer->AddGrowableRow(0, 1);
grid_sizer->AddGrowableRow(1, 1);
wxBoxSizer* labels_sizer = new wxBoxSizer(wxHORIZONTAL);
{
const wxString left_text = _L("Lower quality");
const int left_text_gap = std::max(GetTextExtent(_L("Linear precision")).x, GetTextExtent(_L("Angle precision")).x) + 4 * hgap - GetTextExtent(left_text).x * 0.5;
const wxString right_text = _L("Higher quality");
const int right_text_gap = GetTextExtent(_L("mm")).x + def_editor_size.x + 4 * hgap - GetTextExtent(right_text).x * 0.5;
labels_sizer->Add(new wxStaticText(this, wxID_ANY, left_text), 0, wxLEFT, left_text_gap);
labels_sizer->Add(new wxStaticText(this, wxID_ANY, wxEmptyString), 1, wxEXPAND);
labels_sizer->Add(new wxStaticText(this, wxID_ANY, right_text), 0, wxRIGHT, right_text_gap);
}
auto high_vals = std::find_if(default_step_import_params.begin(), default_step_import_params.end(),
[](const std::pair<std::string, PrecisionParams>& val) { return val.first == "High"; });
auto low_vals = std::find_if(default_step_import_params.begin(), default_step_import_params.end(),
[](const std::pair<std::string, PrecisionParams>& val) { return val.first == "Low"; });
assert(high_vals != default_step_import_params.end() && low_vals != default_step_import_params.end());
m_linear_precision_sl.init(high_vals->second.linear, low_vals->second.linear, 0.001);
m_angle_precision_sl.init(high_vals->second.angle, low_vals->second.angle, 0.01);
auto process_value_change = [](double& precision, wxTextCtrl* text_ctrl, wxSlider* slider, const SliderHelper& sl_helper) -> void {
wxString str_val = text_ctrl->GetValue();
double val = string_to_double_decimal_point(str_val.ToStdString());
precision = sl_helper.adjust_to_region(val);
slider->SetValue(sl_helper.get_pos(precision));
if (wxString str_precision = format_wxstr("%1%", precision); str_precision != str_val)
text_ctrl->SetValue(str_precision);
};
auto tooltip = [](const SliderHelper& sl_helper) -> wxString {
// TRN %n% contain min, max and step values respectively
return format_wxstr(_L("Set value from the range [%1%; %2%] with %3% step"),
sl_helper.min_val, sl_helper.max_val, sl_helper.val_step);
};
// Add "Linear precision"
m_linear_precision_slider = new wxSlider(this, wxID_ANY, m_linear_precision_sl.get_pos(m_params.linear), m_linear_precision_sl.beg_sl_pos, m_linear_precision_sl.end_sl_pos, wxDefaultPosition, def_slider_size, slyder_style);
m_linear_precision_slider->SetTickFreq(1);
m_linear_precision_slider->Bind(wxEVT_SLIDER, [this](wxCommandEvent e) {
m_params.linear = m_linear_precision_sl.get_value(m_linear_precision_slider->GetValue());
m_linear_precision_val->SetValue(format_wxstr("%1%", m_params.linear));
});
m_linear_precision_val = new wxTextCtrl(this, wxID_ANY, format_wxstr("%1%", m_linear_precision_sl.adjust_to_region(m_params.linear)), wxDefaultPosition, def_editor_size, text_ctrl_style);
m_linear_precision_val->SetToolTip(tooltip(m_linear_precision_sl));
m_linear_precision_val->Bind(wxEVT_TEXT_ENTER, [process_value_change, this](wxCommandEvent& e) {
process_value_change(m_params.linear, m_linear_precision_val, m_linear_precision_slider, m_linear_precision_sl);
});
m_linear_precision_val->Bind(wxEVT_KILL_FOCUS, [process_value_change, this](wxFocusEvent& e) {
process_value_change(m_params.linear, m_linear_precision_val, m_linear_precision_slider, m_linear_precision_sl);
e.Skip();
});
grid_sizer->Add(new wxStaticText(this, wxID_ANY, _L("Linear precision") + ": "), 0, wxALIGN_CENTER_VERTICAL);
grid_sizer->Add(m_linear_precision_slider, 1, wxEXPAND);
grid_sizer->Add(m_linear_precision_val, 0, wxALIGN_CENTER_VERTICAL);
grid_sizer->Add(new wxStaticText(this, wxID_ANY, _L("mm")), 0, wxALIGN_CENTER_VERTICAL);
// Add "Angle precision"
m_angle_precision_slider = new wxSlider(this, wxID_ANY, m_angle_precision_sl.get_pos(m_params.angle), m_angle_precision_sl.beg_sl_pos, m_angle_precision_sl.end_sl_pos, wxDefaultPosition, def_slider_size, slyder_style);
m_angle_precision_slider->SetTickFreq(5);
m_angle_precision_slider->Bind(wxEVT_SLIDER, [this](wxCommandEvent e) {
m_params.angle = m_angle_precision_sl.get_value(m_angle_precision_slider->GetValue());
m_angle_precision_val->SetValue(format_wxstr("%1%", m_params.angle));
});
m_angle_precision_val = new wxTextCtrl(this, wxID_ANY, format_wxstr("%1%", m_angle_precision_sl.adjust_to_region(m_params.angle)), wxDefaultPosition, def_editor_size, text_ctrl_style);
m_angle_precision_val->SetToolTip(tooltip(m_angle_precision_sl));
m_angle_precision_val->Bind(wxEVT_TEXT_ENTER, [process_value_change, this](wxCommandEvent& e) {
process_value_change(m_params.angle, m_angle_precision_val, m_angle_precision_slider, m_angle_precision_sl);
});
m_angle_precision_val->Bind(wxEVT_KILL_FOCUS, [process_value_change, this](wxFocusEvent& e) {
process_value_change(m_params.angle, m_angle_precision_val, m_angle_precision_slider, m_angle_precision_sl);
e.Skip();
});
grid_sizer->Add(new wxStaticText(this, wxID_ANY, _L("Angle precision") + ": "), 0, wxALIGN_CENTER_VERTICAL);
grid_sizer->Add(m_angle_precision_slider, 1, wxEXPAND);
grid_sizer->Add(m_angle_precision_val, 0, wxALIGN_CENTER_VERTICAL);
grid_sizer->Add(new wxStaticText(this, wxID_ANY, _L("°")), 0, wxALIGN_CENTER_VERTICAL);
m_custom_sizer = new wxBoxSizer(wxVERTICAL);
m_custom_sizer->Add(labels_sizer, 0, wxEXPAND | wxBOTTOM | wxTOP, em_unit());
m_custom_sizer->Add(grid_sizer, 1, wxEXPAND);
main_sizer->Add(m_custom_sizer, 1, wxEXPAND | wxLEFT, 3 * em_unit());
sizer->Add(main_sizer, 1, wxEXPAND | wxALL, em_unit());
}
void LoadStepDialog::enable_customs(bool enable)
{
m_linear_precision_slider->Enable(enable);
m_linear_precision_val->Enable(enable);
m_angle_precision_slider->Enable(enable);
m_angle_precision_val->Enable(enable);
}
bool LoadStepDialog::IsCheckBoxChecked()
{
return m_remember_chb && m_remember_chb->GetValue();
}
bool LoadStepDialog::IsApplyToAllClicked()
{
return m_apply_to_all;
}
} // namespace Slic3r::GUI

View File

@@ -0,0 +1,100 @@
///|/ Copyright (c) Prusa Research 2018 - 2025 Oleksandra Iushchenko @YuSanka
///|/
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
///|/
#ifndef slic3r_LoadStepDialog_hpp_
#define slic3r_LoadStepDialog_hpp_
#include <string>
#include <wx/dialog.h>
#include "GUI_Utils.hpp"
class wxBoxSizer;
class wxTextCtrl;
class wxSlider;
class CheckBox;
namespace Slic3r::GUI {
struct PrecisionParams
{
double linear;
double angle;
};
struct SliderHelper
{
double min_val;
double max_val;
double val_step;
int beg_sl_pos;
int end_sl_pos;
void init(double min, double max, double step, int beg_pos = 1) {
assert(val_step != 0.);
min_val = min;
max_val = max;
val_step = step;
beg_sl_pos = beg_pos;
end_sl_pos = beg_sl_pos + int(double(max_val - min_val) / val_step);
}
double get_value(int pos) const {
return max_val - val_step * (pos - beg_sl_pos);
}
int get_pos(double value) const {
return beg_sl_pos + int((max_val - value) / val_step);
}
double adjust_to_region(double value) const {
return std::max(std::min(value, max_val), min_val);
}
};
class LoadStepDialog : public DPIDialog
{
public:
LoadStepDialog(wxWindow* parent, const std::string& filename, double linear_precision, double angle_precision, bool multiple_loading);
~LoadStepDialog() = default;
bool IsCheckBoxChecked();
bool IsApplyToAllClicked();
double get_linear_precision() { return m_params.linear; }
double get_angle_precision() { return m_params.angle; }
protected:
void on_dpi_changed(const wxRect& suggested_rect) override {}
void on_sys_color_changed() override {};
private:
void add_params(wxSizer* sizer);
void enable_customs(bool enable);
private:
PrecisionParams m_params;
::CheckBox* m_remember_chb { nullptr };
wxTextCtrl* m_linear_precision_val { nullptr };
wxTextCtrl* m_angle_precision_val { nullptr };
wxSlider* m_linear_precision_slider { nullptr };
wxSlider* m_angle_precision_slider { nullptr };
wxBoxSizer* m_custom_sizer { nullptr };
bool m_default { false };
bool m_apply_to_all { false };
SliderHelper m_linear_precision_sl;
SliderHelper m_angle_precision_sl;
};
} // namespace Slic3r::GUI
#endif

View File

@@ -1128,6 +1128,11 @@ void NotificationManager::URLDownloadWithPrintablesLinkNotification::render_text
}
//------URLDownloadNotification----------------
void NotificationManager::URLDownloadNotification::set_filename(const std::string& filename_line)
{
m_text1 = filename_line;
init();
}
void NotificationManager::URLDownloadNotification::render_close_button(const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
{
@@ -2642,6 +2647,19 @@ void NotificationManager::set_download_URL_progress(size_t id, float percentage)
}
}
}
void NotificationManager::set_download_URL_filename(size_t id, const std::string& filename)
{
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
if (notification->get_type() == NotificationType::URLDownload) {
URLDownloadNotification* ntf = dynamic_cast<URLDownloadNotification*>(notification.get());
if (ntf->get_download_id() != id)
continue;
ntf->set_filename(_u8L("Download") + ": " + filename);
wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0);
return;
}
}
}
void NotificationManager::set_download_URL_paused(size_t id)
{

View File

@@ -256,6 +256,7 @@ public:
void set_download_URL_paused(size_t id);
void set_download_URL_canceled(size_t id);
void set_download_URL_error(size_t id, const std::string& text);
void set_download_URL_filename(size_t id, const std::string& filename);
// slicing progress
void init_slicing_progress_notification(std::function<bool()> cancel_callback);
void set_slicing_progress_began();
@@ -563,6 +564,7 @@ private:
void set_paused(bool paused) { m_download_paused = paused; }
void set_error_message(const std::string& message) { m_error_message = message; }
bool compare_text(const std::string& text) const override { return false; };
void set_filename(const std::string& filename_line);
protected:
void render_close_button(const float win_size_x, const float win_size_y,
const float win_pos_x, const float win_pos_y) override;

View File

@@ -405,6 +405,14 @@ void OptionsGroup::activate_line(Line& line)
}
}
//y25
if (!line.get_only_widgets().empty()){
for (auto only_widget : line.get_only_widgets()) {
sizer->Add(only_widget(this->ctrl_parent()), 0, wxEXPAND);
}
return;
}
const std::vector<Option>& option_set = line.get_options();
bool is_legend_line = option_set.front().opt.gui_type == ConfigOptionDef::GUIType::legend;

View File

@@ -73,6 +73,12 @@ public:
void append_widget(const widget_t widget) {
m_extra_widgets.push_back(widget);
}
//y25
void append_only_widget(const widget_t widget) {
only_widgets.push_back(widget);
}
Line(wxString label, wxString tooltip) :
label(_(label)), label_tooltip(_(tooltip)) {}
Line() : m_is_separator(true) {}
@@ -90,9 +96,14 @@ public:
const std::vector<widget_t>& get_extra_widgets() const {return m_extra_widgets;}
const std::vector<Option>& get_options() const { return m_options; }
//y25
const std::vector<widget_t>& get_only_widgets() const {return only_widgets;}
private:
std::vector<Option> m_options;//! {std::vector<Option>()};
std::vector<widget_t> m_extra_widgets;//! {std::vector<widget_t>()};
//y25
std::vector<widget_t> only_widgets;//{std::vector<widget_t>()};
};
using column_t = std::function<wxWindow*(wxWindow* parent, const Line&)>;

View File

@@ -11,6 +11,7 @@
#include <string>
#include <regex>
#include <future>
#include <utility>
#include <boost/algorithm/string.hpp>
#include <boost/nowide/cstdio.hpp>
#include <boost/optional.hpp>
@@ -119,6 +120,7 @@
#include "ConfigWizardWebViewPage.hpp"
#include "PresetArchiveDatabase.hpp"
#include "BulkExportDialog.hpp"
#include "LoadStepDialog.hpp"
#include "libslic3r/ArrangeHelper.hpp"
@@ -315,6 +317,7 @@ struct Plater::priv
static const std::regex pattern_qidi;
static const std::regex pattern_zip;
static const std::regex pattern_printRequest;
static const std::regex pattern_step;
//y20
std::vector<ThumbnailData> thumbnails;
@@ -609,11 +612,13 @@ private:
bool show_warning_dialog { false };
};
// FIXME: Some of the regex patterns are wrong (missing [.] before file extension).
const std::regex Plater::priv::pattern_bundle(".*[.](amf|amf[.]xml|3mf)", std::regex::icase);
const std::regex Plater::priv::pattern_3mf(".*3mf", std::regex::icase);
const std::regex Plater::priv::pattern_any_amf(".*[.](amf|amf[.]xml|zip[.]amf)", std::regex::icase);
const std::regex Plater::priv::pattern_zip(".*zip", std::regex::icase);
const std::regex Plater::priv::pattern_printRequest(".*printRequest", std::regex::icase);
const std::regex Plater::priv::pattern_step(".*[.](step|stp)", std::regex::icase);
Plater::priv::priv(Plater* q, MainFrame* main_frame)
: q(q)
@@ -1287,6 +1292,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
int answer_convert_from_meters = wxOK_DEFAULT;
int answer_convert_from_imperial_units = wxOK_DEFAULT;
int answer_consider_as_multi_part_objects = wxOK_DEFAULT;
bool apply_step_import_parameters_to_all { false };
bool in_temp = false;
const fs::path temp_path = wxStandardPaths::Get().GetTempDir().utf8_str().data();
@@ -1302,7 +1308,26 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
const auto &path = input_files[i];
#endif // _WIN32
in_temp = (path.parent_path() == temp_path);
const auto filename = path.filename();
const boost::filesystem::path filename = path.filename();
const bool type_step = std::regex_match(path.string(), pattern_step);
if (type_step && !apply_step_import_parameters_to_all &&
wxGetApp().app_config->get_bool("show_step_import_parameters")) {
double linear_precision = string_to_double_decimal_point(wxGetApp().app_config->get("linear_precision"));
double angle_precision = string_to_double_decimal_point(wxGetApp().app_config->get("angle_precision"));
LoadStepDialog dlg(q, filename.string(), linear_precision, angle_precision, (input_files_size - i) > 1);
if (dlg.ShowModal() == wxID_OK) {
wxGetApp().app_config->set("linear_precision", float_to_string_decimal_point(dlg.get_linear_precision()));
wxGetApp().app_config->set("angle_precision", float_to_string_decimal_point(dlg.get_angle_precision()));
if (dlg.IsCheckBoxChecked())
wxGetApp().app_config->set("show_step_import_parameters", "0");
apply_step_import_parameters_to_all = dlg.IsApplyToAllClicked();
} else
continue;
}
if (progress_dlg) {
progress_dlg->Update(static_cast<int>(100.0f * static_cast<float>(i) / static_cast<float>(input_files.size())), _L("Loading file") + ": " + from_path(filename));
progress_dlg->Fit();
@@ -1350,7 +1375,14 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
model = FileReader::load_model_with_config(path.string(), &config_loaded, &config_substitutions, qidislicer_generator_version, FileReader::LoadAttribute::CheckVersion, &load_stats);
}
else if (load_model) {
model = FileReader::load_model(path.string(), FileReader::LoadAttributes{}, &load_stats);
if (type_step) {
double linear_precision = string_to_double_decimal_point(wxGetApp().app_config->get("linear_precision"));
double angle_precision = string_to_double_decimal_point(wxGetApp().app_config->get("angle_precision"));
model = FileReader::load_model(path.string(), FileReader::LoadAttributes{}, &load_stats,
std::make_pair(linear_precision, angle_precision));
}
else
model = FileReader::load_model(path.string(), FileReader::LoadAttributes{}, &load_stats);
}
} catch (const ConfigurationError &e) {
std::string message = GUI::format(_L("Failed loading file \"%1%\" due to an invalid configuration."), filename.string()) + "\n\n" + e.what();
@@ -7363,9 +7395,62 @@ void Plater::send_gcode()
only_link = true;
}
max_send_number = std::stoi(wxGetApp().app_config->get("max_send"));
std::string selected_printer_host = "";
bool has_select_printer = wxGetApp().preset_bundle->physical_printers.has_selection();
if (has_select_printer) {
PhysicalPrinter& ph_printer = wxGetApp().preset_bundle->physical_printers.get_selected_printer();
selected_printer_host = ph_printer.config.opt_string("print_host");
}
std::string sync_ip = box_msg.box_list_printer_ip;
bool has_diff = false;
if(sync_ip.empty()){
;
}
else if (selected_printer_host != sync_ip && !selected_printer_host.empty()){
WarningDialog(this, _L("Please note that the printer of the synchronous BOX does not match the currently selected printer.")).ShowModal();
}
#if QDT_RELEASE_TO_PUBLIC
else{
QIDINetwork qidi;
wxString msg = "";
GUI::Box_info filament_info;
filament_info = qidi.get_box_info(msg, sync_ip);
GUI::Box_info cur_box_info;
cur_box_info = get_cur_box_info();
if (filament_info.filament_index != cur_box_info.filament_index
|| filament_info.filament_vendor != cur_box_info.filament_vendor
|| filament_info.filament_color_index != cur_box_info.filament_color_index
|| filament_info.slot_state != cur_box_info.slot_state
|| filament_info.slot_id != cur_box_info.slot_id
|| filament_info.box_count != cur_box_info.box_count
|| filament_info.auto_reload_detect != cur_box_info.auto_reload_detect) {
has_diff = true;
}
#endif
}
if(has_diff){
WarningDialog(this, _L("The BOX information has been updated. Please resynchronize.")).ShowModal();
}
//B61 //y20
PrintHostSendDialog dlg(default_output_file, PrintHostPostUploadAction::StartPrint, groups, storage_paths, storage_names, this, only_link);
if (dlg.ShowModal() == wxID_OK) {
//y25
std::vector<int> activate_slot;
for (auto& temp_fila : wxGetApp().preset_bundle->filament_box_list) {
auto& dnyconfig = temp_fila.second;
std::string sold_id_t = dnyconfig.opt_string("slot_id", 0u);
activate_slot.push_back(std::stoi(sold_id_t));
}
//y16
bool is_jump = false;
@@ -7426,6 +7511,20 @@ void Plater::send_gcode()
//m_time_p = upload_job.create_time + seconds_to_add;
//y25
if (!activate_slot.empty() && upload_job.upload_data.post_action == PrintHostPostUploadAction::StartPrint) {
for (int i = 0; i < activate_slot.size(); i++) {
wxString check_status_msg = "";
wxString command = wxString::Format(
"SAVE_VARIABLE VARIABLE=value_t%d VALUE=\\\"'slot%d'\\\"",
i,
activate_slot[i]
);
bool success = upload_job.printhost->send_command_to_printer(check_status_msg, command);
}
}
p->export_gcode(fs::path(), false, std::move(upload_job));
UploadCount++;
@@ -7468,6 +7567,19 @@ void Plater::send_gcode()
return;
}
//y25
if (!activate_slot.empty() && upload_job.upload_data.post_action == PrintHostPostUploadAction::StartPrint) {
for (int i = 0; i < activate_slot.size(); i++) {
wxString check_status_msg = "";
wxString command = wxString::Format(
"SAVE_VARIABLE VARIABLE=value_t%d VALUE=\\\"'slot%d'\\\"",
i,
activate_slot[i]
);
bool success = upload_job.printhost->send_command_to_printer(check_status_msg, command);
}
}
p->export_gcode(fs::path(), false, std::move(upload_job));
UploadCount++;
@@ -7563,8 +7675,18 @@ bool Plater::update_filament_colors_in_full_config()
std::vector<std::string> filament_colors;
filament_colors.reserve(extruders_filaments.size());
for (const auto& extr_filaments : extruders_filaments)
filament_colors.push_back(filaments.find_preset(extr_filaments.get_selected_preset_name(), true)->config.opt_string("filament_colour", (unsigned)0));
//y25
if(wxGetApp().preset_bundle->filament_box_list.empty()){
for (const auto& extr_filaments : extruders_filaments)
filament_colors.push_back(filaments.find_preset(extr_filaments.get_selected_preset_name(), true)->config.opt_string("filament_colour", (unsigned)0));
}
else{
for(auto& fila : wxGetApp().preset_bundle->filament_box_list){
auto& tray = fila.second;
std::string color = tray.opt_string("filament_colour", 0u);
filament_colors.push_back(color);
}
}
p->config->option<ConfigOptionStrings>("filament_colour")->values = filament_colors;
return true;

View File

@@ -18,6 +18,10 @@
#include "slic3r/GUI/Camera.hpp"
#include "slic3r/Utils/PrintHost.hpp"
#if QDT_RELEASE_TO_PUBLIC
#include "../QIDI/QIDINetwork.hpp"
#endif
class wxString;
namespace Slic3r {
@@ -55,6 +59,19 @@ class UserAccount;
class PresetArchiveDatabase;
enum class ArrangeSelectionMode;
//y25
struct Box_msg {
std::vector<int> slot_state;
std::vector<int> slot_id;
std::vector<std::string> filament_id;
std::vector<std::string> filament_colors;
std::vector<std::string> filament_type;
std::string box_list_preset_name;
std::string box_list_printer_ip;
int box_count = 0;
int auto_reload_detect = 0;
};
class Plater: public wxPanel
{
public:
@@ -475,6 +492,14 @@ public:
m_sending_interval = 0;
};
//y25
Box_msg box_msg;
#if QDT_RELEASE_TO_PUBLIC
GUI::Box_info current_box_info;
GUI::Box_info get_cur_box_info() { return current_box_info; };
#endif
private:
std::optional<fs_path> get_default_output_file();
std::optional<wxString> check_output_path_has_error(const boost::filesystem::path& path) const;

View File

@@ -127,7 +127,7 @@ void PreferencesDialog::show(const std::string& highlight_opt_key /*= std::strin
downloader->set_path_name(app_config->get("url_downloader_dest"));
downloader->allow(!app_config->has("downloader_url_registered") || app_config->get_bool("downloader_url_registered"));
for (const std::string opt_key : {"suppress_hyperlinks", "downloader_url_registered", "show_login_button"})
for (const std::string opt_key : {"suppress_hyperlinks", "downloader_url_registered", "show_login_button", "show_step_import_parameters"})
m_optgroup_other->set_value(opt_key, app_config->get_bool(opt_key));
// by default "Log in" button is visible
if (!app_config->has("show_login_button"))
@@ -621,6 +621,11 @@ void PreferencesDialog::build()
// "If disabled, the descriptions of configuration parameters in settings tabs will work as hyperlinks."),
app_config->get_bool("suppress_hyperlinks"));
append_bool_option(m_optgroup_other, "show_step_import_parameters",
L("Show STEP file import parameters"),
L("If enabled, PrusaSlicer will show a dialog with quality selection when importing a STEP file."),
app_config->get_bool("show_step_import_parameters"));
append_bool_option(m_optgroup_other, "show_login_button",
L("Show \"Log in\" button in application top bar"),
L("If enabled, QIDISlicer will show up \"Log in\" button in application top bar."),

View File

@@ -1155,8 +1155,10 @@ void PlaterPresetComboBox::update()
tooltip = from_u8(preset.name);
}
}
} else {
}
else {
system_presets.push_back({ get_preset_name(preset), get_preset_name(preset).Lower(), bmp });
if (is_selected) {
selected_user_preset = get_preset_name(preset);
tooltip = from_u8(preset.name);
@@ -1333,19 +1335,22 @@ void TabPresetComboBox::OnSelect(wxCommandEvent &evt)
auto selected_item = evt.GetSelection();
auto marker = reinterpret_cast<Marker>(this->GetClientData(selected_item));
if (marker >= LABEL_ITEM_DISABLED && marker < LABEL_ITEM_MAX) {
this->SetSelection(m_last_selected);
if (marker == LABEL_ITEM_WIZARD_PRINTERS)
wxTheApp->CallAfter([this]() {
run_wizard(ConfigWizard::SP_PRINTERS);
// update combobox if its parent is a PhysicalPrinterDialog
PhysicalPrinterDialog* parent = dynamic_cast<PhysicalPrinterDialog*>(this->GetParent());
if (parent != nullptr)
update();
});
}
else if (on_selection_changed && (m_last_selected != selected_item || m_collection->current_is_dirty())) {
//y26
//if (marker >= LABEL_ITEM_DISABLED && marker < LABEL_ITEM_MAX) {
// this->SetSelection(m_last_selected);
// if (marker == LABEL_ITEM_WIZARD_PRINTERS)
// wxTheApp->CallAfter([this]() {
// run_wizard(ConfigWizard::SP_PRINTERS);
// // update combobox if its parent is a PhysicalPrinterDialog
// PhysicalPrinterDialog* parent = dynamic_cast<PhysicalPrinterDialog*>(this->GetParent());
// if (parent != nullptr)
// update();
// });
//}
//else if (on_selection_changed && (m_last_selected != selected_item || m_collection->current_is_dirty())) {
if (on_selection_changed && (m_last_selected != selected_item || m_collection->current_is_dirty())) {
m_last_selected = selected_item;
on_selection_changed(selected_item);
}
@@ -1431,7 +1436,23 @@ void TabPresetComboBox::update()
selected = get_preset_name(preset);
}
} else {
system_presets.push_back({get_preset_name(preset), get_preset_name(preset).Lower(), bmp, is_enabled});
//y25
if (m_type == Preset::TYPE_FILAMENT && !m_preset_bundle->filament_box_list.empty()) {
system_presets.push_back({ get_preset_name(preset), get_preset_name(preset).Lower(), bmp });
std::string preset_filament_id = preset.config.opt_string("filament_id", 0u);
for (auto& entry : m_preset_bundle->filament_box_list) {
auto& tray = entry.second;
std::string filament_id = tray.opt_string("filament_id", 0u);
if (preset_filament_id == filament_id) {
std::string box_preset_name = into_u8(get_preset_name(preset));
tray.set_key_value("preset_name", new ConfigOptionStrings{ box_preset_name });
}
}
}
else
system_presets.push_back({ get_preset_name(preset), get_preset_name(preset).Lower(), bmp });
if (i == idx_selected)
selected = get_preset_name(preset);
}

View File

@@ -77,7 +77,9 @@ PrinterWebView::PrinterWebView(wxWindow *parent) : wxPanel(parent, wxID_ANY, wxD
titlePanel->SetSizer(buttonSizer);
toggleBar = new SwitchButton(menuPanel);
//y25
toggleBar = new DeviceSwitchButton(menuPanel);
toggleBar->SetSize(327);
toggleBar->SetMaxSize({em_unit(this) * 40, -1});
//y3

View File

@@ -178,7 +178,7 @@ private:
DeviceButton * refresh_button;
DeviceButton * login_button;
bool m_isloginin;
SwitchButton * toggleBar;
DeviceSwitchButton * toggleBar; //y25
wxStaticBitmap * staticBitmap;
//y3
wxString m_ip;

View File

@@ -0,0 +1,365 @@
#include "SyncBoxInfoDialog.hpp"
#include "MainFrame.hpp"
#include "Widgets/ComboBox.hpp"
#include "Widgets/Label.hpp"
#include "I18N.hpp"
#include "Tab.hpp"
#include "libslic3r/Utils.hpp"
//y25
using namespace Slic3r;
using namespace Slic3r::GUI;
namespace Slic3r { namespace GUI {
GetBoxInfoDialog::GetBoxInfoDialog(Plater* plater)
: DPIDialog(static_cast<wxWindow*>(wxGetApp().mainframe), wxID_ANY, _L("Sync Box information"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX)
, m_plater(plater)
{
SetFont(wxGetApp().normal_font());
std::string icon_path = (boost::format("%1%/icons/QIDISlicer.ico") % resources_dir()).str();
SetIcon(wxIcon(icon_path.c_str(), wxBITMAP_TYPE_ICO));
Freeze();
SetBackgroundColour(m_colour_def_color);
m_sizer_main = new wxBoxSizer(wxVERTICAL);
m_sizer_main->SetMinSize(wxSize(0, -1));
wxPanel* m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1), wxTAB_TRAVERSAL);
m_line_top->SetBackgroundColour(wxColour(166, 169, 170));
wxStaticText* m_tips_text = new wxStaticText(this, wxID_ANY, _L("Please select the printer in the list to get box info."), wxDefaultPosition, wxSize(-1, -1), 0);
wxBoxSizer *m_sizer_printer = new wxBoxSizer(wxHORIZONTAL);
m_stext_printer_title = new wxStaticText(this, wxID_ANY, _L("Printer"), wxDefaultPosition, wxSize(-1, -1), 0);
m_stext_printer_title->SetFont(::Label::Head_14);
m_stext_printer_title->Wrap(-1);
m_stext_printer_title->SetForegroundColour(m_colour_bold_color);
m_stext_printer_title->SetBackgroundColour(m_colour_def_color);
m_comboBox_printer = new ::ComboBox(this, wxID_ANY, "", wxDefaultPosition, wxSize(FromDIP(250), 20), 0, nullptr, wxCB_READONLY);
m_sizer_printer->Add(m_stext_printer_title, 0, wxALIGN_CENTER | wxALL, FromDIP(5));
m_sizer_printer->Add(0, 0, 0, wxEXPAND | wxALIGN_CENTER | wxLEFT, FromDIP(12));
m_sizer_printer->Add(m_comboBox_printer, 1, wxEXPAND | wxALIGN_CENTER | wxALL, FromDIP(5));
wxPanel* switch_button_panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxTAB_TRAVERSAL | wxBU_RIGHT);
wxBoxSizer* sizer_switch_area = new wxBoxSizer(wxHORIZONTAL);
switch_button_panel->SetBackgroundColour((wxColour("#FFFFFF")));
m_switch_button = new SwitchButton(switch_button_panel);
m_switch_button->SetMaxSize(wxSize(100, 100));
m_switch_button->SetLabels(_L("Local"), _L("Link"));
m_switch_button->SetValue(m_isNetMode);
m_switch_button->Bind(wxEVT_TOGGLEBUTTON, [this](wxCommandEvent& evt) {
bool is_checked = evt.GetInt();
m_switch_button->SetValue(is_checked);
m_isNetMode = is_checked;
m_comboBox_printer->SetValue("");
m_comboBox_printer->Clear();
m_printer_ip.clear();
PresetBundle& preset_bundle = *wxGetApp().preset_bundle;
PhysicalPrinterCollection& ph_printers = wxGetApp().preset_bundle->physical_printers;
std::string preset_typename = NormalizeVendor(preset_bundle.printers.get_edited_preset().name);
if (!m_isNetMode){
for (PhysicalPrinterCollection::ConstIterator it = ph_printers.begin(); it != ph_printers.end(); ++it) {
std::string printer_preset = (it->config.opt_string("preset_name"));
std::string printer_name = it->name;
if (preset_typename.find(NormalizeVendor(printer_preset)) != std::string::npos) {
m_comboBox_printer->Append(from_u8(printer_name));
m_printer_ip.push_back((it->config.opt_string("print_host")));
}
}
m_comboBox_printer->SetSelection(0);
}
#if QDT_RELEASE_TO_PUBLIC
else{
if (wxGetApp().app_config->get("user_token") != ""){
auto m_devices = wxGetApp().get_devices();
for (const auto& device : m_devices) {
if (preset_typename.find(NormalizeVendor(device.machine_type)) != std::string::npos)
{
m_comboBox_printer->Append(from_u8(device.device_name));
m_printer_ip.push_back(device.url);
}
}
m_comboBox_printer->SetSelection(0);
}
}
#endif
if (m_comboBox_printer->GetValue().empty()){
m_button_sync->Disable();
}
else {
m_button_sync->Enable();
}
});
sizer_switch_area->Add(m_switch_button, 0, wxALIGN_CENTER);
switch_button_panel->SetSizer(sizer_switch_area);
switch_button_panel->Layout();
m_sizer_printer->Add(switch_button_panel, 0, wxALL | wxALIGN_CENTER, FromDIP(5));
wxBoxSizer* m_sizer_btn = new wxBoxSizer(wxHORIZONTAL);
btn_bg_enable = StateColor(
std::pair<wxColour, int>(wxColour(95, 82, 253), StateColor::Pressed),
std::pair<wxColour, int>(wxColour(129, 150, 255), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(68, 121, 251), StateColor::Normal));
m_button_sync = new wxButton(this, wxID_ANY, _L("Sync"), wxDefaultPosition, wxSize(60, 25), wxBU_EXACTFIT);
wxGetApp().UpdateDarkUI(m_button_sync, true);
m_button_sync->Bind(wxEVT_BUTTON, &GetBoxInfoDialog::synchronization, this);
m_button_cancel = new wxButton(this, wxID_ANY, _L("Cancel"), wxDefaultPosition, wxSize(60, 25), wxBU_EXACTFIT);
wxGetApp().UpdateDarkUI(m_button_cancel, true);
m_button_cancel->Bind(wxEVT_BUTTON, &GetBoxInfoDialog::cancel, this);
m_sizer_btn->AddStretchSpacer();
m_sizer_btn->Add(m_button_sync, 0, wxALIGN_RIGHT | wxALL, FromDIP(5));
m_sizer_btn->Add(m_button_cancel, 0, wxALIGN_RIGHT | wxALL, FromDIP(5));
m_sizer_main->Add(m_line_top, 0, wxEXPAND | wxTOP, FromDIP(0));
m_sizer_main->AddSpacer(FromDIP(10));
m_sizer_main->Add(m_tips_text, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(20));
m_sizer_main->AddSpacer(FromDIP(15));
m_sizer_main->Add(m_sizer_printer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(20));
m_sizer_main->AddSpacer(FromDIP(25));
m_sizer_main->Add(m_sizer_btn, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(20));
m_sizer_main->AddSpacer(FromDIP(10));
SetSizer(m_sizer_main);
init_printer_combox();
Layout();
Fit();
Thaw();
Centre(wxBOTH);
wxGetApp().UpdateDlgDarkUI(this);
}
GetBoxInfoDialog::~GetBoxInfoDialog() {}
void GetBoxInfoDialog::init_printer_combox()
{
m_isNetMode = wxGetApp().app_config->get("machine_list_net") == "1";
m_switch_button->SetValue(m_isNetMode);
wxCommandEvent event(wxEVT_TOGGLEBUTTON, m_switch_button->GetId());
event.SetEventObject(m_switch_button);
event.SetInt(m_switch_button->GetValue());
m_switch_button->GetEventHandler()->ProcessEvent(event);
}
void GetBoxInfoDialog::on_dpi_changed(const wxRect &suggested_rect)
{
Fit();
Refresh();
}
void GetBoxInfoDialog::synchronization(wxCommandEvent &event)
{
#if QDT_RELEASE_TO_PUBLIC
int selected_idx = m_comboBox_printer->GetSelection();
std::string printer_ip = m_printer_ip[selected_idx];
QIDINetwork qidi;
wxString msg = "";
bool has_box = qidi.get_box_state(msg, printer_ip);
if (!has_box) {
WarningDialog(this, _L("This Printer has not connect the box, please check.")).ShowModal();
}
else {
//Get Box_info
GUI::Box_info filament_info;
filament_info = qidi.get_box_info(msg, printer_ip);
m_plater->current_box_info = filament_info;
qidi.get_color_filament_str(msg, filament_info, printer_ip);
generate_filament_id(filament_info);
syn_box_info = std::move(filament_info);
update_filament_info(filament_info);
sync_box_list();
if(m_isNetMode)
wxGetApp().app_config->set("machine_list_net", "1");
else
wxGetApp().app_config->set("machine_list_net", "0");
this->EndModal(wxID_OK);
}
#endif
}
void GetBoxInfoDialog::synchronize_by_ip(std::string ip)
{
#if QDT_RELEASE_TO_PUBLIC
m_sync_printer_ip = ip;
QIDINetwork qidi;
wxString msg = "";
bool has_box = qidi.get_box_state(msg, m_sync_printer_ip);
if (!has_box) {
WarningDialog(this, _L("This Printer has not connect the box, please check.")).ShowModal();
}
else {
//Get Box_info
GUI::Box_info filament_info;
filament_info = qidi.get_box_info(msg, m_sync_printer_ip);
m_plater->current_box_info = filament_info;
qidi.get_color_filament_str(msg, filament_info, m_sync_printer_ip);
generate_filament_id(filament_info);
syn_box_info = filament_info;
update_filament_info(filament_info);
sync_box_list();
if(m_isNetMode)
wxGetApp().app_config->set("machine_list_net", "1");
else
wxGetApp().app_config->set("machine_list_net", "0");
this->EndModal(wxID_OK);
}
#endif
}
void GetBoxInfoDialog::generate_filament_id(GUI::Box_info& machine_filament_info)
{
std::string filament_id = "QD";
std::string box_id = wxGetApp().preset_bundle->printers.get_selected_preset().config.opt_string("box_id");
filament_id = filament_id + "_" + box_id;
for(int i = 0; i < machine_filament_info.box_count * 4; i++){
if (machine_filament_info.slot_state[i] == 0)
continue;
std::string temp_filament_id = filament_id;
temp_filament_id = temp_filament_id + "_" + std::to_string(machine_filament_info.filament_vendor[i]);
temp_filament_id = temp_filament_id + "_" + std::to_string(machine_filament_info.filament_index[i]);
machine_filament_info.filament_id[i] = temp_filament_id;
}
if(machine_filament_info.slot_state.back() != 0)
{
std::string temp_ext_filament_id = filament_id;
temp_ext_filament_id = temp_ext_filament_id + "_" + std::to_string(machine_filament_info.filament_vendor.back());
temp_ext_filament_id = temp_ext_filament_id + "_" + std::to_string(machine_filament_info.filament_index.back());
machine_filament_info.filament_id.back() = temp_ext_filament_id;
}
}
void GetBoxInfoDialog::update_filament_info(GUI::Box_info& machine_filament_info)
{
m_plater->box_msg.slot_state = std::move(machine_filament_info.slot_state);
m_plater->box_msg.filament_id = std::move(machine_filament_info.filament_id);
m_plater->box_msg.filament_colors = std::move(machine_filament_info.filament_colors);
m_plater->box_msg.box_count = std::move(machine_filament_info.box_count);
m_plater->box_msg.filament_type = std::move(machine_filament_info.filament_type);
m_plater->box_msg.slot_id = std::move(machine_filament_info.slot_id);
m_plater->box_msg.auto_reload_detect = std::move(machine_filament_info.auto_reload_detect);
PresetBundle &preset_bundle = *wxGetApp().preset_bundle;
std::string preset_name_box = NormalizeVendor(preset_bundle.printers.get_edited_preset().name);
m_plater->box_msg.box_list_preset_name = preset_name_box;
m_plater->box_msg.box_list_printer_ip = m_sync_printer_ip;
}
void GetBoxInfoDialog::cancel(wxCommandEvent &event)
{
this->EndModal(wxID_CANCEL);
}
std::string GetBoxInfoDialog::NormalizeVendor(const std::string& str)
{
std::string normalized;
for (char c : str) {
if (std::isalnum(c)) {
normalized += std::tolower(c);
}
}
return normalized;
}
void GetBoxInfoDialog::sync_box_list(){
load_box_list();
Tab* tab_print = wxGetApp().get_tab(Preset::TYPE_PRINT);
Tab* tab_printer = wxGetApp().get_tab(Preset::TYPE_PRINTER);
DynamicPrintConfig new_config_printer = wxGetApp().preset_bundle->printers.get_edited_preset().config;
DynamicPrintConfig new_config_prints = wxGetApp().preset_bundle->prints.get_edited_preset().config;
ConfigOptionFloats* nozzle_config = new ConfigOptionFloats();
//y26
for (int i = 0; i < wxGetApp().preset_bundle->filament_box_list.size(); i++) {
nozzle_config->values.push_back(new_config_printer.opt_float("nozzle_diameter", 0u));
}
new_config_printer.set_key_value("nozzle_diameter", nozzle_config);
new_config_printer.set_key_value("single_extruder_multi_material", new ConfigOptionBool(true));
new_config_prints.set_key_value("wipe_tower", new ConfigOptionBool(true));
tab_print->load_config(new_config_prints);
tab_printer->load_config(new_config_printer);
wxGetApp().load_current_presets();
int idx = 0;
for (auto& entry : wxGetApp().preset_bundle->filament_box_list) {
auto& tray = entry.second;
std::string preset_name = "";
//y26
if(tray.has("preset_name"))
preset_name = tray.opt_string("preset_name", 0u);
else {
std::string printer_preset_name = wxGetApp().preset_bundle->physical_printers.get_selected_printer_preset_name();
preset_name = "Generic PLA @" + printer_preset_name;
}
wxGetApp().preset_bundle->set_filament_preset(idx, preset_name);
dynamic_cast<TabFilament*>(wxGetApp().get_tab(Preset::TYPE_FILAMENT))->set_active_extruder(idx);
idx++;
}
wxGetApp().sidebar().update_all_filament_comboboxes();
std::vector<std::string> colors;
for (auto& filament : wxGetApp().preset_bundle->filament_box_list) {
auto info = filament.second;
std::string color = info.opt_string("filament_colour", 0u);
colors.push_back(color);
}
DynamicPrintConfig cfg_new = *wxGetApp().get_tab(Preset::TYPE_PRINTER)->get_config();
cfg_new.set_key_value("extruder_colour", new ConfigOptionStrings(colors));
wxGetApp().get_tab(Preset::TYPE_PRINTER)->load_config(cfg_new);
wxGetApp().plater()->on_config_change(cfg_new);
}
void GetBoxInfoDialog::load_box_list(){
std::map<int, DynamicPrintConfig> filament_box_list;
char n = 'A';
char t = 0;
int count = 0;
for (int i = 0; i < 16; i++) {
count++;
if (syn_box_info.slot_state[i] == 0)
continue;
DynamicPrintConfig tray_config;
tray_config.set_key_value("filament_id", new ConfigOptionStrings{ syn_box_info.filament_id[i] });
tray_config.set_key_value("tag_uid", new ConfigOptionStrings{ "" }); //clear
tray_config.set_key_value("filament_type", new ConfigOptionStrings{syn_box_info.filament_type[i]}); //clear
tray_config.set_key_value("slot_state", new ConfigOptionStrings{std::to_string(syn_box_info.slot_state[i])});
tray_config.set_key_value("slot_id", new ConfigOptionStrings{ std::to_string(syn_box_info.slot_id[i]) });
int group = i / 4 + 1;
char suffix = 'A' + (i % 4);
//std::string tray_name = "1" + std::string(1, 'A' + i);
std::string tray_name = std::to_string(group) + suffix;
tray_config.set_key_value("tray_name", new ConfigOptionStrings{ tray_name }); //1A 1B 1C
tray_config.set_key_value("filament_colour", new ConfigOptionStrings{ into_u8(wxColour(syn_box_info.filament_colors[i]).GetAsString(wxC2S_HTML_SYNTAX)) });//filament_color
tray_config.set_key_value("filament_exist", new ConfigOptionBools{ true }); //default
// tray_config.set_key_value("filament_multi_colors", new ConfigOptionStrings{});
// tray_config.opt<ConfigOptionStrings>("filament_multi_colors")->values.push_back(into_u8(wxColour(syn_box_info.filament_colors[i]).GetAsString(wxC2S_HTML_SYNTAX)));
filament_box_list.emplace('A' + i, std::move(tray_config));
}
wxGetApp().preset_bundle->filament_box_list = filament_box_list;
}
}} // namespace Slic3r

View File

@@ -0,0 +1,59 @@
#ifndef _SyncBoxInfoDialog_H_
#define _SyncBoxInfoDialog_H_
#include "GUI.hpp"
#include "GUI_App.hpp"
#include "GUI_Utils.hpp"
#include "Plater.hpp"
#include "Widgets/Button.hpp"
#include "Widgets/SwitchButton.hpp"
#include "Widgets/ComboBox.hpp"
#include "MainFrame.hpp"
#ifndef M_PI
#define M_PI 3.1415926535897932384626433832795
#endif
//y25
namespace Slic3r{
namespace GUI{
class GetBoxInfoDialog : public DPIDialog
{
public:
GetBoxInfoDialog(Plater* plater = nullptr);
~GetBoxInfoDialog();
void synchronization(wxCommandEvent &event);
void synchronize_by_ip(std::string ip);
void cancel(wxCommandEvent &event);
void on_dpi_changed(const wxRect& suggested_rect) override;
void init_printer_combox();
std::string NormalizeVendor(const std::string& str);
void generate_filament_id(GUI::Box_info& machine_filament_info);
void update_filament_info(GUI::Box_info& machine_filament_info);
void sync_box_list();
void load_box_list();
std::vector<std::string> m_printer_ip;
private:
Plater* m_plater{ nullptr };
wxBoxSizer* m_sizer_main;
wxStaticText* m_stext_printer_title;
ComboBox* m_comboBox_printer;
StateColor btn_bg_enable;
wxButton* m_button_sync;
wxButton* m_button_cancel;
wxColour m_colour_def_color{ wxColour(255, 255, 255) };
wxColour m_colour_bold_color{ wxColour(38, 46, 48) };
SwitchButton* m_switch_button;
bool m_isNetMode;
GUI::Box_info syn_box_info;
std::string m_sync_printer_ip;
};
}} // namespace Slic3r::GUI
#endif

View File

@@ -1464,17 +1464,17 @@ void TabPrint::build()
optgroup = page->new_optgroup(L("Advanced"));
optgroup->append_single_option_line("seam_position", category_path + "seam-position");
optgroup->append_single_option_line("seam_gap_distance", category_path + "seam-gap-distance");
optgroup->append_single_option_line("staggered_inner_seams", category_path + "staggered-inner-seams");
optgroup->append_single_option_line("seam_gap_distance", "print-settings/scarf-seam");
optgroup->append_single_option_line("staggered_inner_seams", "print-settings/scarf-seam");
const std::string scarf_seam_path{"seam-position_151069#"};
optgroup->append_single_option_line("scarf_seam_placement", scarf_seam_path + "scarf-joint-placement");
optgroup->append_single_option_line("scarf_seam_only_on_smooth", scarf_seam_path + "scarf-joint-only-on-smooth-perimeters");
optgroup->append_single_option_line("scarf_seam_start_height", scarf_seam_path + "scarf-start-height");
optgroup->append_single_option_line("scarf_seam_entire_loop", scarf_seam_path + "scarf-joint-around-entire-perimeter");
optgroup->append_single_option_line("scarf_seam_length", scarf_seam_path + "scarf-joint-length");
optgroup->append_single_option_line("scarf_seam_max_segment_length", scarf_seam_path + "max-scarf-joint-segment-length");
optgroup->append_single_option_line("scarf_seam_on_inner_perimeters", scarf_seam_path + "scarf-joint-on-inner-perimeters");
optgroup->append_single_option_line("scarf_seam_placement", "print-settings/scarf-seam");
optgroup->append_single_option_line("scarf_seam_only_on_smooth", "print-settings/scarf-seam");
optgroup->append_single_option_line("scarf_seam_start_height", "print-settings/scarf-seam");
optgroup->append_single_option_line("scarf_seam_entire_loop", "print-settings/scarf-seam");
optgroup->append_single_option_line("scarf_seam_length", "print-settings/scarf-seam");
optgroup->append_single_option_line("scarf_seam_max_segment_length", "print-settings/scarf-seam");
optgroup->append_single_option_line("scarf_seam_on_inner_perimeters", "print-settings/scarf-seam");
optgroup->append_single_option_line("external_perimeters_first", category_path + "external-perimeters-first");
optgroup->append_single_option_line("gap_fill_enabled", category_path + "fill-gaps");
@@ -2250,6 +2250,8 @@ void TabFilament::build()
Line line = { L("Nozzle"), "" };
line.append_option(optgroup->get_option("first_layer_temperature"));
line.append_option(optgroup->get_option("temperature"));
//Y30
line.append_option(optgroup->get_option("filament_flush_temp"));
optgroup->append_line(line);
line = { L("Bed"), "" };
@@ -2266,6 +2268,9 @@ void TabFilament::build()
line.append_option(optgroup->get_option("chamber_minimal_temperature"));
optgroup->append_line(line);
//Y30
optgroup->append_single_option_line("box_temperature");
page = add_options_page(L("Cooling"), "cooling");
std::string category_path = "filament-settings/cooling#";
optgroup = page->new_optgroup(L("Enable"));
@@ -2541,6 +2546,9 @@ void TabFilament::toggle_options()
new_conf.set_key_value("chamber_minimal_temperature", new ConfigOptionInts{0});
load_config(new_conf);
}
//Y30
bool box_temp = printer_config->opt_bool("box_temperature_control");
toggle_option("box_temperature", box_temp);
}
void TabFilament::update()
@@ -2940,6 +2948,8 @@ void TabPrinter::build_fff()
optgroup->append_single_option_line("chamber_fan");
optgroup->append_single_option_line("chamber_temperature_control");
optgroup->append_single_option_line("wipe_device");
//Y30
optgroup->append_single_option_line("box_temperature_control");
const int gcode_field_height = 15; // 150
const int notes_field_height = 25; // 250
@@ -4207,6 +4217,11 @@ bool Tab::may_discard_current_dirty_preset(PresetCollection* presets /*= nullptr
else
wxGetApp().get_tab(presets->type())->cache_config_diff(selected_options);
}
//y25
if (!wxGetApp().preset_bundle->filament_box_list.empty()) {
wxGetApp().preset_bundle->filament_box_list.clear();
}
return true;
}

View File

@@ -2,20 +2,27 @@
#include "../wxExtensions.hpp"
#include "../../Utils/MacDarkMode.hpp"
#include "StaticBox.hpp"
#include "Label.hpp"
#include <wx/dcgraph.h>
#include <wx/dcmemory.h>
#include <wx/dcclient.h>
//B64
SwitchButton::SwitchButton(wxWindow* parent, const wxString& name, wxWindowID id)
: BitmapToggleButton(parent, name, id)
, m_on(this, "toggle_on", 28, 16)
, m_off(this, "toggle_off", 28, 16)
, text_color(std::pair{ 0x4479FB, (int) StateColor::Checked}, std::pair{0x6B6B6B, (int) StateColor::Normal})
, track_color(0x333337)
, thumb_color(std::pair{0x4479FB, (int) StateColor::Checked}, std::pair{0x333337, (int) StateColor::Normal})
//y25
wxDEFINE_EVENT(wxCUSTOMEVT_SWITCH_POS, wxCommandEvent);
SwitchButton::SwitchButton(wxWindow* parent, wxWindowID id)
: wxBitmapToggleButton(parent, id, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE | wxBU_EXACTFIT)
, m_on(this, "toggle_on", 16)
, m_off(this, "toggle_off", 16)
, text_color(std::pair{0xfffffe, (int) StateColor::Checked}, std::pair{0x6B6B6B, (int) StateColor::Normal})
, track_color(0xD9D9D9)
, thumb_color(std::pair{0x4479FB, (int) StateColor::Checked}, std::pair{0xD9D9D9, (int) StateColor::Normal}) // y96
{
SetBackgroundColour(StaticBox::GetParentBackgroundColor(parent));
Bind(wxEVT_TOGGLEBUTTON, [this](auto& e) { update(); e.Skip(); });
SetFont(Label::Body_12);
Rescale();
}
@@ -31,6 +38,11 @@ void SwitchButton::SetTextColor(StateColor const& color)
text_color = color;
}
void SwitchButton::SetTextColor2(StateColor const &color)
{
text_color2 = color;
}
void SwitchButton::SetTrackColor(StateColor const& color)
{
track_color = color;
@@ -48,7 +60,315 @@ void SwitchButton::SetValue(bool value)
update();
}
void SwitchButton::SetSize(int size)
void SwitchButton::Rescale()
{
if (!labels[0].IsEmpty()) {
SetBackgroundColour(StaticBox::GetParentBackgroundColor(GetParent()));
#ifdef __WXOSX__
auto scale = Slic3r::GUI::mac_max_scaling_factor();
int BS = (int) scale;
#else
constexpr int BS = 1;
#endif
wxSize thumbSize;
wxSize trackSize;
wxClientDC dc(this);
#ifdef __WXOSX__
dc.SetFont(dc.GetFont().Scaled(scale));
#endif
wxSize textSize[2];
{
textSize[0] = dc.GetTextExtent(labels[0]);
textSize[1] = dc.GetTextExtent(labels[1]);
}
float fontScale = 0;
{
thumbSize = textSize[0];
auto size = textSize[1];
if (size.x > thumbSize.x) thumbSize.x = size.x;
else size.x = thumbSize.x;
thumbSize.x += BS * 12;
thumbSize.y += BS * 6;
trackSize.x = thumbSize.x + size.x + BS * 10;
trackSize.y = thumbSize.y + BS * 2;
auto maxWidth = GetMaxWidth();
#ifdef __WXOSX__
maxWidth *= scale;
#endif
if (trackSize.x > maxWidth) {
fontScale = float(maxWidth) / trackSize.x;
thumbSize.x -= (trackSize.x - maxWidth) / 2;
trackSize.x = maxWidth;
}
}
for (int i = 0; i < 2; ++i) {
wxMemoryDC memdc(&dc);
#ifdef __WXMSW__
wxBitmap bmp(trackSize.x, trackSize.y);
memdc.SelectObject(bmp);
memdc.SetBackground(wxBrush(GetBackgroundColour()));
memdc.Clear();
#else
wxImage image(trackSize);
image.InitAlpha();
memset(image.GetAlpha(), 0, trackSize.GetWidth() * trackSize.GetHeight());
wxBitmap bmp(std::move(image));
memdc.SelectObject(bmp);
#endif
memdc.SetFont(dc.GetFont());
if (fontScale) {
memdc.SetFont(dc.GetFont().Scaled(fontScale));
textSize[0] = memdc.GetTextExtent(labels[0]);
textSize[1] = memdc.GetTextExtent(labels[1]);
}
auto state = i == 0 ? StateColor::Enabled : (StateColor::Checked | StateColor::Enabled);
{
#ifdef __WXMSW__
wxGCDC dc2(memdc);
#else
wxDC &dc2(memdc);
#endif
dc2.SetBrush(wxBrush(track_color.colorForStates(state)));
dc2.SetPen(wxPen(track_color.colorForStates(state)));
dc2.DrawRoundedRectangle(wxRect({0, 0}, trackSize), trackSize.y / 2);
dc2.SetBrush(wxBrush(thumb_color.colorForStates(StateColor::Checked | StateColor::Enabled)));
dc2.SetPen(wxPen(thumb_color.colorForStates(StateColor::Checked | StateColor::Enabled)));
dc2.DrawRoundedRectangle(wxRect({ i == 0 ? BS : (trackSize.x - thumbSize.x - BS), BS}, thumbSize), thumbSize.y / 2);
}
memdc.SetTextForeground(text_color.colorForStates(state ^ StateColor::Checked));
auto text_y = BS + (thumbSize.y - textSize[0].y) / 2;
#ifdef __APPLE__
if (Slic3r::is_mac_version_15()) {
text_y -= FromDIP(2);
}
#endif
memdc.DrawText(labels[0], {BS + (thumbSize.x - textSize[0].x) / 2, text_y});
memdc.SetTextForeground(text_color2.count() == 0 ? text_color.colorForStates(state) : text_color2.colorForStates(state));
auto text_y_1 = BS + (thumbSize.y - textSize[1].y) / 2;
#ifdef __APPLE__
if (Slic3r::is_mac_version_15()) {
text_y_1 -= FromDIP(2);
}
#endif
memdc.DrawText(labels[1], {trackSize.x - thumbSize.x - BS + (thumbSize.x - textSize[1].x) / 2, text_y_1});
memdc.SelectObject(wxNullBitmap);
#ifdef __WXOSX__
bmp = wxBitmap(bmp.ConvertToImage(), -1, scale);
#endif
(i == 0 ? m_off : m_on).SetBitmap(bmp);
}
}
update();
}
void SwitchButton::update()
{
SetBitmap((GetValue() ? m_on : m_off).bmp());
}
SwitchBoard::SwitchBoard(wxWindow *parent, wxString leftL, wxString right, wxSize size)
: wxWindow(parent, wxID_ANY, wxDefaultPosition, size)
{
#ifdef __WINDOWS__
SetDoubleBuffered(true);
#endif //__WINDOWS__
SetBackgroundColour(*wxWHITE);
leftLabel = leftL;
rightLabel = right;
SetMinSize(size);
SetMaxSize(size);
Bind(wxEVT_PAINT, &SwitchBoard::paintEvent, this);
Bind(wxEVT_LEFT_DOWN, &SwitchBoard::on_left_down, this);
Bind(wxEVT_ENTER_WINDOW, [this](auto &e) { SetCursor(wxCURSOR_HAND); });
Bind(wxEVT_LEAVE_WINDOW, [this](auto &e) { SetCursor(wxCURSOR_ARROW); });
}
void SwitchBoard::updateState(wxString target)
{
if (target.empty()) {
switch_left = false;
switch_right = false;
} else {
if (target == "left") {
switch_left = true;
switch_right = false;
} else if (target == "right") {
switch_left = false;
switch_right = true;
}
}
Refresh();
}
void SwitchBoard::paintEvent(wxPaintEvent &evt)
{
wxPaintDC dc(this);
render(dc);
}
void SwitchBoard::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 SwitchBoard::doRender(wxDC &dc)
{
wxColour disable_color = wxColour(0xCECECE);
dc.SetPen(*wxTRANSPARENT_PEN);
if (is_enable) {dc.SetBrush(wxBrush(0xeeeeee));
} else {dc.SetBrush(disable_color);}
dc.DrawRoundedRectangle(0, 0, GetSize().x, GetSize().y, 8);
/*left*/
if (switch_left) {
is_enable ? dc.SetBrush(wxBrush(wxColour(68, 121, 251))) : dc.SetBrush(disable_color);
dc.DrawRoundedRectangle(0, 0, GetSize().x / 2, GetSize().y, 8);
}
if (switch_left) {
dc.SetTextForeground(*wxWHITE);
} else {
dc.SetTextForeground(0x333333);
}
dc.SetFont(::Label::Body_13);
auto left_txt_size = dc.GetTextExtent(leftLabel);
dc.DrawText(leftLabel, wxPoint((GetSize().x / 2 - left_txt_size.x) / 2, (GetSize().y - left_txt_size.y) / 2));
/*right*/
if (switch_right) {
if (is_enable) {dc.SetBrush(wxBrush(wxColour(68, 121, 251)));
} else {dc.SetBrush(disable_color);}
dc.DrawRoundedRectangle(GetSize().x / 2, 0, GetSize().x / 2, GetSize().y, 8);
}
auto right_txt_size = dc.GetTextExtent(rightLabel);
if (switch_right) {
dc.SetTextForeground(*wxWHITE);
} else {
dc.SetTextForeground(0x333333);
}
dc.DrawText(rightLabel, wxPoint((GetSize().x / 2 - right_txt_size.x) / 2 + GetSize().x / 2, (GetSize().y - right_txt_size.y) / 2));
}
void SwitchBoard::on_left_down(wxMouseEvent &evt)
{
if (!is_enable) {
return;
}
int index = -1;
auto pos = ClientToScreen(evt.GetPosition());
auto rect = ClientToScreen(wxPoint(0, 0));
if (pos.x > 0 && pos.x < rect.x + GetSize().x / 2) {
switch_left = true;
switch_right = false;
index = 1;
} else {
switch_left = false;
switch_right = true;
index = 0;
}
if (auto_disable_when_switch)
{
is_enable = false;// make it disable while switching
}
Refresh();
wxCommandEvent event(wxCUSTOMEVT_SWITCH_POS);
event.SetInt(index);
wxPostEvent(this, event);
}
void SwitchBoard::Enable()
{
if (is_enable == true)
{
return;
}
is_enable = true;
Refresh();
}
void SwitchBoard::Disable()
{
if (is_enable == false)
{
return;
}
is_enable = false;
Refresh();
}
//B64
DeviceSwitchButton::DeviceSwitchButton(wxWindow* parent, const wxString& name, wxWindowID id)
: BitmapToggleButton(parent, name, id)
, m_on(this, "toggle_on", 28, 16)
, m_off(this, "toggle_off", 28, 16)
, text_color(std::pair{ 0x4479FB, (int) StateColor::Checked}, std::pair{0x6B6B6B, (int) StateColor::Normal})
, track_color(0x333337)
, thumb_color(std::pair{0x4479FB, (int) StateColor::Checked}, std::pair{0x333337, (int) StateColor::Normal})
{
Rescale();
}
void DeviceSwitchButton::SetLabels(wxString const& lbl_on, wxString const& lbl_off)
{
labels[0] = lbl_on;
labels[1] = lbl_off;
Rescale();
}
void DeviceSwitchButton::SetTextColor(StateColor const& color)
{
text_color = color;
}
void DeviceSwitchButton::SetTrackColor(StateColor const& color)
{
track_color = color;
}
void DeviceSwitchButton::SetThumbColor(StateColor const& color)
{
thumb_color = color;
}
void DeviceSwitchButton::SetValue(bool value)
{
if (value != GetValue())
wxBitmapToggleButton::SetValue(value);
update();
}
void DeviceSwitchButton::SetSize(int size)
{
m_size = size;
update();
@@ -56,7 +376,7 @@ void SwitchButton::SetSize(int size)
}
//B64
void SwitchButton::Rescale()
void DeviceSwitchButton::Rescale()
{
if (!labels[0].IsEmpty()) {
#ifdef __WXOSX__
@@ -138,7 +458,7 @@ void SwitchButton::Rescale()
update();
}
void SwitchButton::SysColorChange()
void DeviceSwitchButton::SysColorChange()
{
m_on.sys_color_changed();
m_off.sys_color_changed();
@@ -146,7 +466,7 @@ void SwitchButton::SysColorChange()
update();
}
void SwitchButton::update()
void DeviceSwitchButton::update()
{
SetBitmap((GetValue() ? m_on : m_off).bmp());
update_size();

View File

@@ -6,11 +6,83 @@
#include "BitmapToggleButton.hpp"
class SwitchButton : public BitmapToggleButton
//y25
wxDECLARE_EVENT(wxCUSTOMEVT_SWITCH_POS, wxCommandEvent);
class SwitchButton : public wxBitmapToggleButton
{
public:
SwitchButton(wxWindow * parent = NULL, wxWindowID id = wxID_ANY);
public:
void SetLabels(wxString const & lbl_on, wxString const & lbl_off);
void SetTextColor(StateColor const &color);
void SetTextColor2(StateColor const &color);
void SetTrackColor(StateColor const &color);
void SetThumbColor(StateColor const &color);
void SetValue(bool value) override;
void Rescale();
protected:
void update();
private:
ScalableBitmap m_on;
ScalableBitmap m_off;
wxString labels[2];
StateColor text_color;
StateColor text_color2;
StateColor track_color;
StateColor thumb_color;
};
class SwitchBoard : public wxWindow
{
public:
SwitchBoard(wxWindow *parent = NULL, wxString leftL = "", wxString right = "", wxSize size = wxDefaultSize);
wxString leftLabel;
wxString rightLabel;
void updateState(wxString target);
bool switch_left{false};
bool switch_right{false};
bool is_enable {true};
void* client_data = nullptr;/*MachineObject* in StatusPanel*/
public:
void Enable();
void Disable();
bool IsEnabled(){return is_enable;};
void SetClientData(void* data) { client_data = data; };
void* GetClientData() { return client_data; };
void SetAutoDisableWhenSwitch() { auto_disable_when_switch = true; };
protected:
void paintEvent(wxPaintEvent& evt);
void render(wxDC& dc);
void doRender(wxDC& dc);
void on_left_down(wxMouseEvent& evt);
private:
bool auto_disable_when_switch = false;
};
class DeviceSwitchButton : public BitmapToggleButton
{
public:
//B64
SwitchButton(wxWindow * parent = NULL, const wxString& name = wxEmptyString, wxWindowID id = wxID_ANY);
DeviceSwitchButton(wxWindow * parent = NULL, const wxString& name = wxEmptyString, wxWindowID id = wxID_ANY);
public:
void SetLabels(wxString const & lbl_on, wxString const & lbl_off);

View File

@@ -283,7 +283,6 @@ WipingPanel::WipingPanel(wxWindow* parent, const std::vector<float>& matrix, con
for (size_t j = 0; j < m_number_of_extruders; ++j) {
if (i != j) {
double def_val = m_printer_purging_volume * m_filament_purging_multipliers[j] / 100.;
edit_boxes[j][i]->SetValue(wxString("") << int(def_val));
}
}
}

View File

@@ -52,7 +52,8 @@ public:
std::vector<float> read_matrix_values();
void format_sizer(wxSizer* sizer, wxPanel* page, wxGridSizer* grid_sizer, const wxString& table_title, int table_lshift=0);
private:
private:
std::vector<std::vector<wxTextCtrl*>> edit_boxes;
std::vector<wxColour> m_colours;
unsigned int m_number_of_extruders = 0;