diff --git a/resources/images/add.svg b/resources/images/add.svg deleted file mode 100644 index 37050d7481..0000000000 --- a/resources/images/add.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - diff --git a/resources/images/add_copies.svg b/resources/images/add_copies.svg deleted file mode 100644 index 45b1d27cf9..0000000000 --- a/resources/images/add_copies.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/resources/images/browse.svg b/resources/images/browse.svg deleted file mode 100644 index c4297c41da..0000000000 --- a/resources/images/browse.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index bd09ac7788..6407aab34e 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -724,13 +724,7 @@ static std::vector s_Preset_printer_options { "silent_mode", // BBS "scan_first_layer", "machine_load_filament_time", "machine_unload_filament_time", "machine_pause_gcode", - "nozzle_type", "auxiliary_fan", "nozzle_volume", - //SoftFever - "connection_moonraker_url","connection_port", "host_type", "print_host", "printhost_apikey", - "printhost_cafile","printhost_port","printhost_authorization_type", - "printhost_user", - "printhost_password", - "printhost_ssl_ignore_revoke" + "nozzle_type", "auxiliary_fan", "nozzle_volume" }; static std::vector s_Preset_sla_print_options { @@ -2525,16 +2519,6 @@ static std::vector s_PhysicalPrinter_opts { "preset_name", // temporary option to compatibility with older Slicer "preset_names", "printer_technology", - "host_type", - "print_host", - "printhost_apikey", - "printhost_cafile", - "printhost_port", - "printhost_authorization_type", - // HTTP digest authentization (RFC 2617) - "printhost_user", - "printhost_password", - "printhost_ssl_ignore_revoke" }; const std::vector& PhysicalPrinter::printer_options() @@ -2698,8 +2682,6 @@ void PhysicalPrinterCollection::load_printers( // see https://github.com/prusa3d/PrusaSlicer/issues/732 boost::filesystem::path dir = boost::filesystem::absolute(boost::filesystem::path(dir_path) / subdir).make_preferred(); m_dir_path = dir.string(); - if(!boost::filesystem::exists(dir)) - return; std::string errors_cummulative; // Store the loaded printers into a new vector, otherwise the binary search for already existing presets would be broken. std::deque printers_loaded; diff --git a/src/libslic3r/Preset.hpp b/src/libslic3r/Preset.hpp index 05b076ec69..a5a5217f2c 100644 --- a/src/libslic3r/Preset.hpp +++ b/src/libslic3r/Preset.hpp @@ -22,7 +22,6 @@ #define PRESET_SLA_MATERIALS_NAME "sla_materials" //BBS: iot preset type strings -#define PRESET_IOT_PHYSICAL_PRINTER_TYPE "physical_printer" #define PRESET_IOT_PRINTER_TYPE "printer" #define PRESET_IOT_FILAMENT_TYPE "filament" #define PRESET_IOT_PRINT_TYPE "print" diff --git a/src/libslic3r/PresetBundle.cpp b/src/libslic3r/PresetBundle.cpp index 1f69d8d884..145535eb0c 100644 --- a/src/libslic3r/PresetBundle.cpp +++ b/src/libslic3r/PresetBundle.cpp @@ -90,7 +90,7 @@ PresetBundle::PresetBundle() for (size_t i = 0; i < 1; ++i) { // The following ugly switch is to avoid printers.preset(0) to return the edited instance, as the 0th default is the current one. Preset &preset = this->printers.default_preset(i); - for (const char *key : {"printer_settings_id", "printer_model", "printer_variant","physical_printer_settings_id"}) preset.config.optptr(key, true); + for (const char *key : {"printer_settings_id", "printer_model", "printer_variant"}) preset.config.optptr(key, true); //if (i == 0) { preset.config.optptr("default_print_profile", true); preset.config.option("default_filament_profile", true); @@ -268,11 +268,6 @@ PresetsConfigSubstitutions PresetBundle::load_presets(AppConfig &config, Forward } catch (const std::runtime_error &err) { errors_cummulative += err.what(); } - try { - this->physical_printers.load_printers(dir_user_presets, "physical_printer", substitutions, substitution_rule); - } catch (const std::runtime_error &err) { - errors_cummulative += err.what(); - } this->update_multi_material_filament_presets(); this->update_compatible(PresetSelectCompatibleType::Never); if (! errors_cummulative.empty()) @@ -537,7 +532,7 @@ PresetsConfigSubstitutions PresetBundle::load_user_presets(AppConfig &config, st // First load the vendor specific system presets. PresetsConfigSubstitutions substitutions; std::string errors_cummulative; - bool process_added = false, filament_added = false, machine_added = false, physical_printer_added = false; + bool process_added = false, filament_added = false, machine_added = false; BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(" enter, substitution_rule %1%, preset toltal count %2%")%substitution_rule%my_presets.size(); BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(" print's selected_idx %1%, selected_name %2%") %prints.get_selected_idx() %prints.get_selected_preset_name(); @@ -567,11 +562,6 @@ PresetsConfigSubstitutions PresetBundle::load_user_presets(AppConfig &config, st preset_collection = &(this->printers); machine_added |= preset_collection->load_user_preset(name, value_map, substitutions, substitution_rule); } - else if(type_iter->second == PRESET_IOT_PHYSICAL_PRINTER_TYPE){ - preset_collection = &(this->printers); - physical_printer_added |= preset_collection->load_user_preset(name, value_map, substitutions, substitution_rule); - - } else { BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format("invalid type %1% for setting %2%") %type_iter->second %name; continue; @@ -655,6 +645,9 @@ void PresetBundle::update_system_preset_setting_ids(std::mapsecond == PRESET_IOT_PRINTER_TYPE) { preset_collection = &(this->printers); } + else if (type_iter->second == PRESET_IOT_PRINTER_TYPE) { + preset_collection = &(this->printers); + } else { BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format("invalid type %1% for setting %2%") %type_iter->second %name; continue; @@ -687,7 +680,7 @@ void PresetBundle::update_system_preset_setting_ids(std::map inherits_values; PrinterTechnology printer_technology = Preset::printer_technology(config); size_t num_extruders = (printer_technology == ptFFF) ? @@ -1184,7 +1177,7 @@ void PresetBundle::export_selections(AppConfig &config) // BBS //config.set("presets", "sla_print", sla_prints.get_selected_preset_name()); //config.set("presets", "sla_material", sla_materials.get_selected_preset_name()); - config.set("presets", "physical_printer", physical_printers.get_selected_full_printer_name()); + //config.set("presets", "physical_printer", physical_printers.get_selected_full_printer_name()); //BBS: add config related log BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": printer %1%, print %2%, filaments[0] %3% ")%printers.get_selected_preset_name() % prints.get_selected_preset_name() %filament_presets[0]; } @@ -1252,15 +1245,13 @@ DynamicPrintConfig PresetBundle::full_config() const DynamicPrintConfig PresetBundle::full_config_secure() const { DynamicPrintConfig config = this->full_config(); - //FIXME legacy, the keys should not be there after conversion to a Physical Printer profile. - config.erase("print_host"); - config.erase("printhost_apikey"); - config.erase("printhost_cafile"); return config; + //BBS example: config.erase("print_host"); + return config; } const std::set ignore_settings_list ={ "inherits", - "print_settings_id", "filament_settings_id", "printer_settings_id","physical_printer_settings_id" + "print_settings_id", "filament_settings_id", "printer_settings_id" }; DynamicPrintConfig PresetBundle::full_fff_config() const @@ -1441,7 +1432,6 @@ DynamicPrintConfig PresetBundle::full_fff_config() const out.option("filament_settings_id", true)->values = this->filament_presets; out.option("printer_settings_id", true)->value = this->printers.get_selected_preset_name(); out.option("filament_ids", true)->values = filament_ids; - // out.option("physical_printer_settings_id", true)->value = this->physical_printers.get_selected_printer_preset_name(); // Serialize the collected "compatible_printers_condition" and "inherits" fields. // There will be 1 + num_exturders fields for "inherits" and 2 + num_extruders for "compatible_printers_condition" stored. // The vector will not be stored if all fields are empty strings. @@ -1820,7 +1810,8 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool this->update_compatible(PresetSelectCompatibleType::Never); //BBS - const std::string &physical_printer = config.option("physical_printer_settings_id", true)->value; + //const std::string &physical_printer = config.option("physical_printer_settings_id", true)->value; + const std::string physical_printer; if (this->printers.get_edited_preset().is_external || physical_printer.empty()) { this->physical_printers.unselect_printer(); } else { diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 5a3da2a51f..9241cc2ebe 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -43,23 +43,6 @@ static t_config_enum_values s_keys_map_PrinterTechnology { }; CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(PrinterTechnology) -static t_config_enum_values s_keys_map_PrintHostType { - { "prusalink", htPrusaLink }, - { "octoprint", htOctoPrint }, - { "duet", htDuet }, - { "flashair", htFlashAir }, - { "astrobox", htAstroBox }, - { "repetier", htRepetier }, - { "mks", htMKS } -}; -CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(PrintHostType) - -static t_config_enum_values s_keys_map_AuthorizationType { - { "key", atKeyPassword }, - { "user", atUserPassword } -}; -CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(AuthorizationType) - static t_config_enum_values s_keys_map_GCodeFlavor { { "marlin", gcfMarlinLegacy }, { "reprap", gcfRepRapSprinter }, @@ -274,7 +257,6 @@ void PrintConfigDef::init_common_params() def = this->add("printable_area", coPoints); def->label = L("Printable area"); - //BBS def->mode = comDevelop; def->set_default_value(new ConfigOptionPoints{ Vec2d(0, 0), Vec2d(200, 0), Vec2d(200, 200), Vec2d(0, 200) }); @@ -322,98 +304,6 @@ void PrintConfigDef::init_common_params() def->mode = comDevelop; def->set_default_value(new ConfigOptionStrings()); - //SoftFever - def = this->add("connection_moonraker_url", coString); - def->label = L("Moonraker URL"); - //def->tooltip = L("Names of presets related to the physical printer"); - def->mode = comAdvanced; - def->set_default_value(new ConfigOptionString("http://")); - - def = this->add("connection_port", coString); - def->label = L("Connection port"); - //def->tooltip = L("Names of presets related to the physical printer"); - def->mode = comAdvanced; - def->set_default_value(new ConfigOptionString("7125")); - - - - def = this->add("print_host", coString); - def->label = L("Hostname, IP or URL"); - def->tooltip = L("Slic3r can upload G-code files to a printer host. This field should contain " - "the hostname, IP address or URL of the printer host instance. " - "Print host behind HAProxy with basic auth enabled can be accessed by putting the user name and password into the URL " - "in the following format: https://username:password@your-octopi-address/"); - def->mode = comAdvanced; - def->cli = ConfigOptionDef::nocli; - def->set_default_value(new ConfigOptionString("")); - - def = this->add("printhost_apikey", coString); - def->label = L("API Key / Password"); - def->tooltip = L("Slic3r can upload G-code files to a printer host. This field should contain " - "the API Key or the password required for authentication."); - def->mode = comAdvanced; - def->cli = ConfigOptionDef::nocli; - def->set_default_value(new ConfigOptionString("")); - - def = this->add("printhost_port", coString); - def->label = L("Printer"); - def->tooltip = L("Name of the printer"); - def->gui_type = ConfigOptionDef::GUIType::select_open; - def->mode = comAdvanced; - def->cli = ConfigOptionDef::nocli; - def->set_default_value(new ConfigOptionString("")); - - def = this->add("printhost_cafile", coString); - def->label = L("HTTPS CA File"); - def->tooltip = L("Custom CA certificate file can be specified for HTTPS OctoPrint connections, in crt/pem format. " - "If left blank, the default OS CA certificate repository is used."); - def->mode = comAdvanced; - def->cli = ConfigOptionDef::nocli; - def->set_default_value(new ConfigOptionString("")); - - // Options used by physical printers - - def = this->add("printhost_user", coString); - def->label = L("User"); -// def->tooltip = L(""); - def->mode = comAdvanced; - def->cli = ConfigOptionDef::nocli; - def->set_default_value(new ConfigOptionString("")); - - def = this->add("printhost_password", coString); - def->label = L("Password"); -// def->tooltip = L(""); - def->mode = comAdvanced; - def->cli = ConfigOptionDef::nocli; - def->set_default_value(new ConfigOptionString("")); - - // Only available on Windows. - def = this->add("printhost_ssl_ignore_revoke", coBool); - def->label = L("Ignore HTTPS certificate revocation checks"); - def->tooltip = L("Ignore HTTPS certificate revocation checks in case of missing or offline distribution points. " - "One may want to enable this option for self signed certificates if connection fails."); - def->mode = comAdvanced; - def->cli = ConfigOptionDef::nocli; - def->set_default_value(new ConfigOptionBool(false)); - - def = this->add("preset_names", coStrings); - def->label = L("Printer preset names"); - def->tooltip = L("Names of presets related to the physical printer"); - def->mode = comAdvanced; - def->set_default_value(new ConfigOptionStrings()); - - def = this->add("printhost_authorization_type", coEnum); - def->label = L("Authorization Type"); -// def->tooltip = L(""); - def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); - def->enum_values.push_back("key"); - def->enum_values.push_back("user"); - def->enum_labels.push_back(L("API key")); - def->enum_labels.push_back(L("HTTP digest")); - def->mode = comAdvanced; - def->cli = ConfigOptionDef::nocli; - def->set_default_value(new ConfigOptionEnum(atKeyPassword)); - // temporary workaround for compatibility with older Slicer { def = this->add("preset_name", coString); @@ -1734,30 +1624,6 @@ void PrintConfigDef::init_fff_params() def->mode = comDevelop; def->set_default_value(new ConfigOptionFloats { 0.4 }); - def = this->add("host_type", coEnum); - def->label = L("Host Type"); - def->tooltip = L("Slic3r can upload G-code files to a printer host. This field must contain " - "the kind of the host."); - def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); - def->enum_values.push_back("prusalink"); - def->enum_values.push_back("octoprint"); - def->enum_values.push_back("duet"); - def->enum_values.push_back("flashair"); - def->enum_values.push_back("astrobox"); - def->enum_values.push_back("repetier"); - def->enum_values.push_back("mks"); - def->enum_labels.push_back("PrusaLink"); - def->enum_labels.push_back("OctoPrint"); - def->enum_labels.push_back("Duet"); - def->enum_labels.push_back("FlashAir"); - def->enum_labels.push_back("AstroBox"); - def->enum_labels.push_back("Repetier"); - def->enum_labels.push_back("MKS"); - def->mode = comAdvanced; - def->cli = ConfigOptionDef::nocli; - def->set_default_value(new ConfigOptionEnum(htOctoPrint)); - - def = this->add("nozzle_volume", coFloat); def->label = L("Nozzle volume"); def->tooltip = L("Volume of nozzle between the cutter and the end of nozzle"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 05d35fe063..f08702299a 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -42,14 +42,6 @@ enum class FuzzySkinType { All, }; -enum PrintHostType { - htPrusaLink, htOctoPrint, htDuet, htFlashAir, htAstroBox, htRepetier, htMKS -}; - -enum AuthorizationType { - atKeyPassword, atUserPassword -}; - #define HAS_LIGHTNING_INFILL 0 enum InfillPattern : int { @@ -244,9 +236,6 @@ CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(BedType) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(DraftShield) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(ForwardCompatibilitySubstitutionRule) -CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(PrintHostType) -CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(AuthorizationType) - #undef CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS // Defines each and every confiuration option of Slic3r, including the properties of the GUI dialogs. @@ -766,10 +755,6 @@ PRINT_CONFIG_CLASS_DEFINE( //BBS ((ConfigOptionEnum, nozzle_type)) ((ConfigOptionBool, auxiliary_fan)) - //SoftFever - ((ConfigOptionString, connection_moonraker_url)) - ((ConfigOptionString, connection_port)) - ) // This object is mapped to Perl as Slic3r::Config::Print. diff --git a/src/minilzo/CMakeLists.txt b/src/minilzo/CMakeLists.txt index d23e871472..c5122ccf0f 100644 --- a/src/minilzo/CMakeLists.txt +++ b/src/minilzo/CMakeLists.txt @@ -1,5 +1,5 @@ project(minilzo) -cmake_minimum_required(VERSION 3.0) +cmake_minimum_required(VERSION 2.6) add_library(minilzo INTERFACE) diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index f4e122e00a..d85be22309 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -177,10 +177,6 @@ set(SLIC3R_GUI_SOURCES GUI/SavePresetDialog.cpp GUI/GUI_Colors.hpp GUI/GUI_Colors.cpp - GUI/PhysicalPrinterDialog.hpp - GUI/PhysicalPrinterDialog.cpp - GUI/PrintHostDialogs.cpp - GUI/PrintHostDialogs.hpp GUI/GUI_Factories.cpp GUI/GUI_Factories.hpp GUI/GUI_ObjectList.cpp @@ -352,8 +348,6 @@ set(SLIC3R_GUI_SOURCES GUI/Calibration.cpp GUI/PrintOptionsDialog.hpp GUI/PrintOptionsDialog.cpp - GUI/BonjourDialog.hpp - GUI/BonjourDialog.cpp Utils/json_diff.hpp Utils/json_diff.cpp GUI/KBShortcutsDialog.hpp @@ -381,22 +375,6 @@ set(SLIC3R_GUI_SOURCES Utils/ColorSpaceConvert.cpp Utils/NetworkAgent.cpp Utils/NetworkAgent.hpp - Utils/OctoPrint.cpp - Utils/OctoPrint.hpp - Utils/PrintHost.cpp - Utils/PrintHost.hpp - Utils/Serial.cpp - Utils/Serial.hpp - Utils/MKS.hpp - Utils/MKS.cpp - Utils/Duet.cpp - Utils/Duet.hpp - Utils/FlashAir.cpp - Utils/FlashAir.hpp - Utils/AstroBox.cpp - Utils/AstroBox.hpp - Utils/Repetier.cpp - Utils/Repetier.hpp ) if (APPLE) diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.cpp b/src/slic3r/GUI/BackgroundSlicingProcess.cpp index d906dd17d9..4ef4a0e074 100644 --- a/src/slic3r/GUI/BackgroundSlicingProcess.cpp +++ b/src/slic3r/GUI/BackgroundSlicingProcess.cpp @@ -227,9 +227,6 @@ void BackgroundSlicingProcess::process_fff() if (! m_export_path.empty()) { wxQueueEvent(GUI::wxGetApp().mainframe->m_plater, new wxCommandEvent(m_event_export_began_id)); finalize_gcode(); - } else if (! m_upload_job.empty()) { - wxQueueEvent(GUI::wxGetApp().mainframe->m_plater, new wxCommandEvent(m_event_export_began_id)); - prepare_upload(); } else { m_print->set_status(100, _utf8(L("Slicing complete"))); } @@ -687,19 +684,6 @@ void BackgroundSlicingProcess::schedule_export(const std::string &path, bool exp m_export_path_on_removable_media = export_path_on_removable_media; } -void BackgroundSlicingProcess::schedule_upload(Slic3r::PrintHostJob upload_job) -{ - assert(m_export_path.empty()); - if (! m_export_path.empty()) - return; - - // Guard against entering the export step before changing the export path. - std::scoped_lock lock(m_print->state_mutex()); - this->invalidate_step(bspsGCodeFinalize); - m_export_path.clear(); - m_upload_job = std::move(upload_job); -} - void BackgroundSlicingProcess::reset_export() { assert(! this->running()); @@ -816,45 +800,6 @@ void BackgroundSlicingProcess::finalize_gcode() m_print->set_status(100, (boost::format(_utf8(L("Succeed to export G-code to %1%"))) % export_path).str()); } -// A print host upload job has been scheduled, enqueue it to the printhost job queue -void BackgroundSlicingProcess::prepare_upload() -{ - // Generate a unique temp path to which the gcode/zip file is copied/exported - boost::filesystem::path source_path = boost::filesystem::temp_directory_path() - / boost::filesystem::unique_path("." SLIC3R_APP_KEY ".upload.%%%%-%%%%-%%%%-%%%%"); - - if (m_print == m_fff_print) { - m_print->set_status(95, _utf8(L("Running post-processing scripts"))); - std::string error_message; - if (copy_file(m_temp_output_path, source_path.string(), error_message) != SUCCESS) - throw Slic3r::RuntimeError(_utf8(L("Copying of the temporary G-code to the output G-code failed"))); - m_upload_job.upload_data.upload_path = m_fff_print->print_statistics().finalize_output_path(m_upload_job.upload_data.upload_path.string()); - // Make a copy of the source path, as run_post_process_scripts() is allowed to change it when making a copy of the source file - // (not here, but when the final target is a file). - std::string source_path_str = source_path.string(); - std::string output_name_str = m_upload_job.upload_data.upload_path.string(); - if (run_post_process_scripts(source_path_str, false, m_upload_job.printhost->get_name(), output_name_str, m_fff_print->full_print_config())) - m_upload_job.upload_data.upload_path = output_name_str; - } else { - m_upload_job.upload_data.upload_path = m_sla_print->print_statistics().finalize_output_path(m_upload_job.upload_data.upload_path.string()); - - ThumbnailsList thumbnails = this->render_thumbnails( - ThumbnailsParams{current_print()->full_print_config().option("thumbnails")->values, true, true, true, true}); - // true, false, true, true); // renders also supports and pad - Zipper zipper{source_path.string()}; - m_sla_archive.export_print(zipper, *m_sla_print, m_upload_job.upload_data.upload_path.string()); - for (const ThumbnailData& data : thumbnails) - if (data.is_valid()) - write_thumbnail(zipper, data); - zipper.finalize(); - } - - m_print->set_status(100, (boost::format(_utf8(L("Scheduling upload to `%1%`. See Window -> Print Host Upload Queue"))) % m_upload_job.printhost->get_host()).str()); - - m_upload_job.upload_data.source_path = std::move(source_path); - - GUI::wxGetApp().printhost_job_queue().enqueue(std::move(m_upload_job)); -} // Executed by the background thread, to start a task on the UI thread. ThumbnailsList BackgroundSlicingProcess::render_thumbnails(const ThumbnailsParams ¶ms) { diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.hpp b/src/slic3r/GUI/BackgroundSlicingProcess.hpp index d369b010bb..9a28cdab93 100644 --- a/src/slic3r/GUI/BackgroundSlicingProcess.hpp +++ b/src/slic3r/GUI/BackgroundSlicingProcess.hpp @@ -12,7 +12,6 @@ #include "libslic3r/PrintBase.hpp" #include "libslic3r/GCode/ThumbnailData.hpp" #include "libslic3r/Format/SL1.hpp" -#include "slic3r/Utils/PrintHost.hpp" #include "libslic3r/GCode/GCodeProcessor.hpp" #include "PartPlate.hpp" @@ -149,14 +148,10 @@ public: // Set the export path of the G-code. // Once the path is set, the G-code void schedule_export(const std::string &path, bool export_path_on_removable_media); - // Set print host upload job data to be enqueued to the PrintHostJobQueue - // after current print slicing is complete - void schedule_upload(Slic3r::PrintHostJob upload_job); // Clear m_export_path. void reset_export(); // Once the G-code export is scheduled, the apply() methods will do nothing. bool is_export_scheduled() const { return ! m_export_path.empty(); } - bool is_upload_scheduled() const { return ! m_upload_job.empty(); } enum State { // m_thread is not running yet, or it did not reach the STATE_IDLE yet (it does not wait on the condition yet). @@ -243,9 +238,6 @@ private: // but once set, it cannot be re-set. std::string m_export_path; bool m_export_path_on_removable_media = false; - // Print host upload job to schedule after slicing is complete, used by schedule_upload(), - // empty by default (ie. no upload to schedule) - PrintHostJob m_upload_job; // Thread, on which the background processing is executed. The thread will always be present // and ready to execute the slicing process. boost::thread m_thread; @@ -284,7 +276,6 @@ private: // If the background processing stop was requested, throw CanceledException. void throw_if_canceled() const { if (m_print->canceled()) throw CanceledException(); } void finalize_gcode(); - void prepare_upload(); // To be executed at the background thread. ThumbnailsList render_thumbnails(const ThumbnailsParams ¶ms); // Execute task from background thread on the UI thread synchronously. Returns true if processed, false if cancelled before executing the task. diff --git a/src/slic3r/GUI/BonjourDialog.cpp b/src/slic3r/GUI/BonjourDialog.cpp deleted file mode 100644 index 516b1ab4a5..0000000000 --- a/src/slic3r/GUI/BonjourDialog.cpp +++ /dev/null @@ -1,239 +0,0 @@ -#include "slic3r/Utils/Bonjour.hpp" // On Windows, boost needs to be included before wxWidgets headers - -#include "BonjourDialog.hpp" - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "slic3r/GUI/GUI.hpp" -#include "slic3r/GUI/GUI_App.hpp" -#include "slic3r/GUI/I18N.hpp" -#include "slic3r/Utils/Bonjour.hpp" - -namespace Slic3r { - - -class BonjourReplyEvent : public wxEvent -{ -public: - BonjourReply reply; - - BonjourReplyEvent(wxEventType eventType, int winid, BonjourReply &&reply) : - wxEvent(winid, eventType), - reply(std::move(reply)) - {} - - virtual wxEvent *Clone() const - { - return new BonjourReplyEvent(*this); - } -}; - -wxDEFINE_EVENT(EVT_BONJOUR_REPLY, BonjourReplyEvent); - -wxDECLARE_EVENT(EVT_BONJOUR_COMPLETE, wxCommandEvent); -wxDEFINE_EVENT(EVT_BONJOUR_COMPLETE, wxCommandEvent); - -class ReplySet: public std::set {}; - -struct LifetimeGuard -{ - std::mutex mutex; - BonjourDialog *dialog; - - LifetimeGuard(BonjourDialog *dialog) : dialog(dialog) {} -}; - -BonjourDialog::BonjourDialog(wxWindow *parent, Slic3r::PrinterTechnology tech) - : wxDialog(parent, wxID_ANY, _(L("Network lookup")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER) - , list(new wxListView(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT|wxSIMPLE_BORDER)) - , replies(new ReplySet) - , label(new wxStaticText(this, wxID_ANY, "")) - , timer(new wxTimer()) - , timer_state(0) - , tech(tech) -{ - const int em = GUI::wxGetApp().em_unit(); - list->SetMinSize(wxSize(80 * em, 30 * em)); - - wxBoxSizer *vsizer = new wxBoxSizer(wxVERTICAL); - - vsizer->Add(label, 0, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, em); - - list->SetSingleStyle(wxLC_SINGLE_SEL); - list->SetSingleStyle(wxLC_SORT_DESCENDING); - list->AppendColumn(_(L("Address")), wxLIST_FORMAT_LEFT, 5 * em); - list->AppendColumn(_(L("Hostname")), wxLIST_FORMAT_LEFT, 10 * em); - list->AppendColumn(_(L("Service name")), wxLIST_FORMAT_LEFT, 20 * em); - if (tech == ptFFF) { - list->AppendColumn(_(L("OctoPrint version")), wxLIST_FORMAT_LEFT, 5 * em); - } - - vsizer->Add(list, 1, wxEXPAND | wxALL, em); - - wxBoxSizer *button_sizer = new wxBoxSizer(wxHORIZONTAL); - button_sizer->Add(new wxButton(this, wxID_OK, "OK"), 0, wxALL, em); - button_sizer->Add(new wxButton(this, wxID_CANCEL, "Cancel"), 0, wxALL, em); - // ^ Note: The Ok/Cancel labels are translated by wxWidgets - - vsizer->Add(button_sizer, 0, wxALIGN_CENTER); - SetSizerAndFit(vsizer); - - Bind(EVT_BONJOUR_REPLY, &BonjourDialog::on_reply, this); - - Bind(EVT_BONJOUR_COMPLETE, [this](wxCommandEvent &) { - this->timer_state = 0; - }); - - Bind(wxEVT_TIMER, &BonjourDialog::on_timer, this); - GUI::wxGetApp().UpdateDlgDarkUI(this); -} - -BonjourDialog::~BonjourDialog() -{ - // Needed bacuse of forward defs -} - -bool BonjourDialog::show_and_lookup() -{ - Show(); // Because we need GetId() to work before ShowModal() - - timer->Stop(); - timer->SetOwner(this); - timer_state = 1; - timer->Start(1000); - on_timer_process(); - - // The background thread needs to queue messages for this dialog - // and for that it needs a valid pointer to it (mandated by the wxWidgets API). - // Here we put the pointer under a shared_ptr and protect it by a mutex, - // so that both threads can access it safely. - auto dguard = std::make_shared(this); - - // Note: More can be done here when we support discovery of hosts other than Octoprint and SL1 - Bonjour::TxtKeys txt_keys { "version", "model" }; - - bonjour = Bonjour("octoprint") - .set_txt_keys(std::move(txt_keys)) - .set_retries(3) - .set_timeout(4) - .on_reply([dguard](BonjourReply &&reply) { - std::lock_guard lock_guard(dguard->mutex); - auto dialog = dguard->dialog; - if (dialog != nullptr) { - auto evt = new BonjourReplyEvent(EVT_BONJOUR_REPLY, dialog->GetId(), std::move(reply)); - wxQueueEvent(dialog, evt); - } - }) - .on_complete([dguard]() { - std::lock_guard lock_guard(dguard->mutex); - auto dialog = dguard->dialog; - if (dialog != nullptr) { - auto evt = new wxCommandEvent(EVT_BONJOUR_COMPLETE, dialog->GetId()); - wxQueueEvent(dialog, evt); - } - }) - .lookup(); - - bool res = ShowModal() == wxID_OK && list->GetFirstSelected() >= 0; - { - // Tell the background thread the dialog is going away... - std::lock_guard lock_guard(dguard->mutex); - dguard->dialog = nullptr; - } - return res; -} - -wxString BonjourDialog::get_selected() const -{ - auto sel = list->GetFirstSelected(); - return sel >= 0 ? list->GetItemText(sel) : wxString(); -} - - -// Private - -void BonjourDialog::on_reply(BonjourReplyEvent &e) -{ - if (replies->find(e.reply) != replies->end()) { - // We already have this reply - return; - } - - // Filter replies based on selected technology - const auto model = e.reply.txt_data.find("model"); - const bool sl1 = model != e.reply.txt_data.end() && model->second == "SL1"; - if ((tech == ptFFF && sl1) || (tech == ptSLA && !sl1)) { - return; - } - - replies->insert(std::move(e.reply)); - - auto selected = get_selected(); - - wxWindowUpdateLocker freeze_guard(this); - (void)freeze_guard; - - list->DeleteAllItems(); - - // The whole list is recreated so that we benefit from it already being sorted in the set. - // (And also because wxListView's sorting API is bananas.) - for (const auto &reply : *replies) { - auto item = list->InsertItem(0, reply.full_address); - list->SetItem(item, 1, reply.hostname); - list->SetItem(item, 2, reply.service_name); - - if (tech == ptFFF) { - const auto it = reply.txt_data.find("version"); - if (it != reply.txt_data.end()) { - list->SetItem(item, 3, GUI::from_u8(it->second)); - } - } - } - - const int em = GUI::wxGetApp().em_unit(); - - for (int i = 0; i < list->GetColumnCount(); i++) { - list->SetColumnWidth(i, wxLIST_AUTOSIZE); - if (list->GetColumnWidth(i) < 10 * em) { list->SetColumnWidth(i, 10 * em); } - } - - if (!selected.IsEmpty()) { - // Attempt to preserve selection - auto hit = list->FindItem(-1, selected); - if (hit >= 0) { list->SetItemState(hit, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED); } - } -} - -void BonjourDialog::on_timer(wxTimerEvent &) -{ - on_timer_process(); -} - -// This is here so the function can be bound to wxEVT_TIMER and also called -// explicitly (wxTimerEvent should not be created by user code). -void BonjourDialog::on_timer_process() -{ - const auto search_str = _utf8(L("Searching for devices")); - - if (timer_state > 0) { - const std::string dots(timer_state, '.'); - label->SetLabel(GUI::from_u8((boost::format("%1% %2%") % search_str % dots).str())); - timer_state = (timer_state) % 3 + 1; - } else { - label->SetLabel(GUI::from_u8((boost::format("%1%: %2%") % search_str % (_utf8(L("Finished"))+".")).str())); - timer->Stop(); - } -} - - - - -} diff --git a/src/slic3r/GUI/BonjourDialog.hpp b/src/slic3r/GUI/BonjourDialog.hpp deleted file mode 100644 index def0838d7e..0000000000 --- a/src/slic3r/GUI/BonjourDialog.hpp +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef slic3r_BonjourDialog_hpp_ -#define slic3r_BonjourDialog_hpp_ - -#include - -#include - -#include "libslic3r/PrintConfig.hpp" - -class wxListView; -class wxStaticText; -class wxTimer; -class wxTimerEvent; - - -namespace Slic3r { - -class Bonjour; -class BonjourReplyEvent; -class ReplySet; - - -class BonjourDialog: public wxDialog -{ -public: - BonjourDialog(wxWindow *parent, Slic3r::PrinterTechnology); - BonjourDialog(BonjourDialog &&) = delete; - BonjourDialog(const BonjourDialog &) = delete; - BonjourDialog &operator=(BonjourDialog &&) = delete; - BonjourDialog &operator=(const BonjourDialog &) = delete; - ~BonjourDialog(); - - bool show_and_lookup(); - wxString get_selected() const; -private: - wxListView *list; - std::unique_ptr replies; - wxStaticText *label; - std::shared_ptr bonjour; - std::unique_ptr timer; - unsigned timer_state; - Slic3r::PrinterTechnology tech; - - void on_reply(BonjourReplyEvent &); - void on_timer(wxTimerEvent &); - void on_timer_process(); -}; - - - -} - -#endif diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index d2b45f6d0e..90d97ee43f 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -1225,9 +1225,7 @@ void Choice::set_value(const boost::any& value, bool change_event) // BBS case coEnums: { int val = boost::any_cast(value); - if (m_opt_id.compare("host_type") == 0 && val != 0 && - m_opt.enum_values.size() > field->GetCount()) // for case, when PrusaLink isn't used as a HostType - val--; + if (m_opt_id == "top_surface_pattern" || m_opt_id == "bottom_surface_pattern" || m_opt_id == "sparse_infill_pattern") { std::string key; @@ -1307,11 +1305,7 @@ boost::any& Choice::get_value() // BBS if (m_opt.type == coEnum || m_opt.type == coEnums) { - if (m_opt_id.compare("host_type") == 0 && m_opt.enum_values.size() > field->GetCount()) { - // for case, when PrusaLink isn't used as a HostType - m_value = field->GetSelection()+1; - } - else if (m_opt_id == "top_surface_pattern" || m_opt_id == "bottom_surface_pattern" || m_opt_id == "sparse_infill_pattern") { + if (m_opt_id == "top_surface_pattern" || m_opt_id == "bottom_surface_pattern" || m_opt_id == "sparse_infill_pattern") { const std::string& key = m_opt.enum_values[field->GetSelection()]; m_value = int(ConfigOptionEnum::get_enum_values().at(key)); } diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index a258ac6315..588bda8565 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -56,7 +56,6 @@ #include "GLCanvas3D.hpp" #include "../Utils/PresetUpdater.hpp" -#include "../Utils/PrintHost.hpp" #include "../Utils/Process.hpp" #include "../Utils/MacDarkMode.hpp" #include "../Utils/Http.hpp" @@ -71,7 +70,6 @@ #include "NotificationManager.hpp" #include "UnsavedChangesDialog.hpp" #include "SavePresetDialog.hpp" -#include "PrintHostDialogs.hpp" #include "DesktopIntegrationDialog.hpp" #include "SendSystemInfoDialog.hpp" #include "ParamsDialog.hpp" @@ -2083,8 +2081,6 @@ bool GUI_App::on_init_inner() plater_->init_notification_manager(); - m_printhost_job_queue.reset(new PrintHostJobQueue(mainframe->printhost_queue_dlg())); - if (is_gcode_viewer()) { mainframe->update_layout(); if (plater_ != nullptr) @@ -2600,7 +2596,6 @@ void GUI_App::recreate_GUI(const wxString& msg_name) old_main_frame->Destroy(); dlg.Update(80, _L("Loading current presets") + dots); - m_printhost_job_queue.reset(new PrintHostJobQueue(mainframe->printhost_queue_dlg())); load_current_presets(); mainframe->Show(true); //mainframe->refresh_plugin_tips(); @@ -4306,34 +4301,6 @@ bool GUI_App::can_load_project() return true; } -bool GUI_App::check_print_host_queue() -{ - wxString dirty; - std::vector> jobs; - // Get ongoing jobs from dialog - mainframe->m_printhost_queue_dlg->get_active_jobs(jobs); - if (jobs.empty()) - return true; - // Show dialog - wxString job_string = wxString(); - for (const auto& job : jobs) { - job_string += format_wxstr(" %1% : %2% \n", job.first, job.second); - } - wxString message; - message += _(L("The uploads are still ongoing")) + ":\n\n" + job_string +"\n" + _(L("Stop them and continue anyway?")); - //wxMessageDialog dialog(mainframe, - MessageDialog dialog(mainframe, - message, - wxString(SLIC3R_APP_NAME) + " - " + _(L("Ongoing uploads")), - wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT); - if (dialog.ShowModal() == wxID_YES) - return true; - - // TODO: If already shown, bring forward - mainframe->m_printhost_queue_dlg->Show(); - return false; -} - bool GUI_App::checked_tab(Tab* tab) { bool ret = true; diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index d02b0fe941..d88e1053fc 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -7,13 +7,11 @@ #include "ConfigWizard.hpp" #include "OpenGLManager.hpp" #include "libslic3r/Preset.hpp" -#include "wxExtensions.hpp" #include "libslic3r/PresetBundle.hpp" #include "slic3r/GUI/DeviceManager.hpp" #include "slic3r/Utils/NetworkAgent.hpp" #include "slic3r/GUI/WebViewDialog.hpp" #include "slic3r/GUI/Jobs/UpgradeNetworkJob.hpp" -#include "../Utils/PrintHost.hpp" #include #include @@ -44,7 +42,6 @@ class AppConfig; class PresetBundle; class PresetUpdater; class ModelObject; -// class PrintHostJobQueue; class Model; class DeviceManager; class NetworkAgent; @@ -247,7 +244,6 @@ private: //std::unique_ptr m_removable_drive_manager; std::unique_ptr m_imgui; - std::unique_ptr m_printhost_job_queue; //std::unique_ptr m_other_instance_message_handler; //std::unique_ptr m_single_instance_checker; //std::string m_instance_hash_string; @@ -420,7 +416,6 @@ public: void apply_keeped_preset_modifications(); bool check_and_keep_current_preset_changes(const wxString& caption, const wxString& header, int action_buttons, bool* postponed_apply_of_keeped_changes = nullptr); bool can_load_project(); - bool check_print_host_queue(); bool checked_tab(Tab* tab); //BBS: add preset combox re-active logic void load_current_presets(bool active_preset_combox = false, bool check_printer_presets = true); @@ -488,8 +483,6 @@ public: ImGuiWrapper* imgui() { return m_imgui.get(); } - PrintHostJobQueue& printhost_job_queue() { return *m_printhost_job_queue.get(); } - void open_web_page_localized(const std::string &http_address); bool may_switch_to_SLA_preset(const wxString& caption); bool run_wizard(ConfigWizard::RunReason reason, ConfigWizard::StartPage start_page = ConfigWizard::SP_WELCOME); diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index a63bef248f..fc0df06bce 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -25,7 +25,6 @@ #include "ProgressStatusBar.hpp" #include "3DScene.hpp" #include "ParamsDialog.hpp" -#include "PrintHostDialogs.hpp" #include "wxExtensions.hpp" #include "GUI_ObjectList.hpp" #include "Mouse3DController.hpp" @@ -150,7 +149,6 @@ wxDEFINE_EVENT(EVT_SYNC_CLOUD_PRESET, SimpleEvent); MainFrame::MainFrame() : DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_STYLE, "mainframe") - , m_printhost_queue_dlg(new PrintHostQueueDialog(this)) // BBS , m_recent_projects(9) , m_settings_dialog(this) @@ -401,10 +399,6 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_ BOOST_LOG_TRIVIAL(info) << __FUNCTION__<< "cancelled by close_with_confirm selection"; return; } - if (event.CanVeto() && !wxGetApp().check_print_host_queue()) { - event.Veto(); - return; - } #if 0 // BBS //if (m_plater != nullptr) { @@ -1111,15 +1105,6 @@ bool MainFrame::can_export_gcode() const return true; } -bool MainFrame::can_send_gcode() const -{ - if (m_plater && ! m_plater->model().objects.empty()) - if (const DynamicPrintConfig *cfg = wxGetApp().preset_bundle->physical_printers.get_selected_printer_config(); cfg) - if (const auto *print_host_opt = cfg->option("print_host"); print_host_opt) - return ! print_host_opt->value.empty(); - return false; -} - /*bool MainFrame::can_export_gcode_sd() const { if (m_plater == nullptr) diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp index 03314870c6..17ff07465d 100644 --- a/src/slic3r/GUI/MainFrame.hpp +++ b/src/slic3r/GUI/MainFrame.hpp @@ -40,7 +40,6 @@ namespace GUI { class Tab; -class PrintHostQueueDialog; class Plater; class MainFrame; class ParamsDialog; @@ -111,7 +110,6 @@ class MainFrame : public DPIFrame bool can_export_toolpaths() const; bool can_export_supports() const; bool can_export_gcode() const; - bool can_send_gcode() const; //bool can_export_gcode_sd() const; //bool can_eject() const; bool can_slice() const; @@ -307,7 +305,6 @@ public: // BBS. Replace title bar and menu bar with top bar. BBLTopbar* m_topbar{ nullptr }; - PrintHostQueueDialog* printhost_queue_dlg() { return m_printhost_queue_dlg; } Plater* m_plater { nullptr }; //BBS: GUI refactor MonitorPanel* m_monitor{ nullptr }; @@ -324,7 +321,6 @@ public: SettingsDialog m_settings_dialog; DiffPresetDialog diff_dialog; wxWindow* m_plater_page{ nullptr }; - PrintHostQueueDialog* m_printhost_queue_dlg; // BBS mutable int m_print_select{ ePrintAll }; diff --git a/src/slic3r/GUI/NotificationManager.cpp b/src/slic3r/GUI/NotificationManager.cpp index 5a921c0aef..d2683e4ccf 100644 --- a/src/slic3r/GUI/NotificationManager.cpp +++ b/src/slic3r/GUI/NotificationManager.cpp @@ -983,149 +983,6 @@ void NotificationManager::UpdatedItemsInfoNotification::add_type(InfoItemType ty update(data); } -//------PrintHostUploadNotification---------------- -void NotificationManager::PrintHostUploadNotification::init() -{ - ProgressBarNotification::init(); - if (m_state == EState::NotFading && m_uj_state == UploadJobState::PB_COMPLETED) - m_state = EState::Shown; -} -void NotificationManager::PrintHostUploadNotification::count_spaces() -{ - //determine line width - m_line_height = ImGui::CalcTextSize("A").y; - - m_left_indentation = m_line_height; - if (m_uj_state == UploadJobState::PB_ERROR) { - std::string text; - text = (m_data.level == NotificationLevel::ErrorNotificationLevel ? ImGui::ErrorMarker : ImGui::WarningMarker); - float picture_width = ImGui::CalcTextSize(text.c_str()).x; - m_left_indentation = picture_width + m_line_height / 2; - } - m_window_width_offset = m_line_height * 6; //(m_has_cancel_button ? 6 : 4); - m_window_width = m_line_height * 25; -} -bool NotificationManager::PrintHostUploadNotification::push_background_color() -{ - - if (m_uj_state == UploadJobState::PB_ERROR) { - ImVec4 backcolor = ImGui::GetStyleColorVec4(ImGuiCol_WindowBg); - backcolor.x += 0.3f; - push_style_color(ImGuiCol_WindowBg, backcolor, m_state == EState::FadingOut, m_current_fade_opacity); - return true; - } - return false; -} -void NotificationManager::PrintHostUploadNotification::set_percentage(float percent) -{ - m_percentage = percent; - if (percent >= 1.0f) { - m_uj_state = UploadJobState::PB_COMPLETED; - m_has_cancel_button = false; - init(); - } else if (percent < 0.0f) { - error(); - } else { - m_uj_state = UploadJobState::PB_PROGRESS; - m_has_cancel_button = true; - } -} -void NotificationManager::PrintHostUploadNotification::render_bar(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y) -{ - std::string text; - switch (m_uj_state) { - case Slic3r::GUI::NotificationManager::PrintHostUploadNotification::UploadJobState::PB_PROGRESS: - { - ProgressBarNotification::render_bar(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y); - float uploaded = m_file_size * m_percentage; - std::stringstream stream; - stream << std::fixed << std::setprecision(2) << (int)(m_percentage * 100) << "% - " << uploaded << " of " << m_file_size << "MB uploaded"; - text = stream.str(); - ImGui::SetCursorPosX(m_left_indentation); - ImGui::SetCursorPosY(win_size_y / 2 + win_size_y / 6 - (m_multiline ? 0 : m_line_height / 4)); - break; - } - case Slic3r::GUI::NotificationManager::PrintHostUploadNotification::UploadJobState::PB_ERROR: - text = _u8L("ERROR"); - ImGui::SetCursorPosX(m_left_indentation); - ImGui::SetCursorPosY(win_size_y / 2 + win_size_y / 6 - (m_multiline ? m_line_height / 4 : m_line_height / 2)); - break; - case Slic3r::GUI::NotificationManager::PrintHostUploadNotification::UploadJobState::PB_CANCELLED: - text = _u8L("CANCELED"); - ImGui::SetCursorPosX(m_left_indentation); - ImGui::SetCursorPosY(win_size_y / 2 + win_size_y / 6 - (m_multiline ? m_line_height / 4 : m_line_height / 2)); - break; - case Slic3r::GUI::NotificationManager::PrintHostUploadNotification::UploadJobState::PB_COMPLETED: - text = _u8L("COMPLETED"); - ImGui::SetCursorPosX(m_left_indentation); - ImGui::SetCursorPosY(win_size_y / 2 + win_size_y / 6 - (m_multiline ? m_line_height / 4 : m_line_height / 2)); - break; - } - - imgui.text(text.c_str()); - -} -void NotificationManager::PrintHostUploadNotification::render_left_sign(ImGuiWrapper& imgui) -{ - if (m_uj_state == UploadJobState::PB_ERROR) { - std::string text; - text = ImGui::ErrorMarker; - ImGui::SetCursorPosX(m_line_height / 3); - ImGui::SetCursorPosY(m_window_height / 2 - m_line_height); - imgui.text(text.c_str()); - } -} -void NotificationManager::PrintHostUploadNotification::render_cancel_button(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y) -{ - ImVec2 win_size(win_size_x, win_size_y); - ImVec2 win_pos(win_pos_x, win_pos_y); - ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f)); - push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity); - push_style_color(ImGuiCol_TextSelectedBg, ImVec4(0, .75f, .75f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f)); - - std::string button_text; - button_text = ImGui::CancelButton; - - if (ImGui::IsMouseHoveringRect(ImVec2(win_pos.x - m_line_height * 5.f, win_pos.y), - ImVec2(win_pos.x - m_line_height * 2.5f, win_pos.y + win_size.y), - true)) - { - button_text = ImGui::CancelHoverButton; - // tooltip - long time_now = wxGetLocalTime(); - if (m_hover_time > 0 && m_hover_time < time_now) { - ImGui::PushStyleColor(ImGuiCol_PopupBg, ImGuiWrapper::COL_WINDOW_BACKGROUND); - ImGui::BeginTooltip(); - imgui.text(_u8L("Cancel upload") + " " + GUI::shortkey_ctrl_prefix() + "T"); - ImGui::EndTooltip(); - ImGui::PopStyleColor(); - } - if (m_hover_time == 0) - m_hover_time = time_now; - } - else - m_hover_time = 0; - - ImVec2 button_pic_size = ImGui::CalcTextSize(button_text.c_str()); - ImVec2 button_size(button_pic_size.x * 1.25f, button_pic_size.y * 1.25f); - ImGui::SetCursorPosX(win_size.x - m_line_height * 5.0f); - ImGui::SetCursorPosY(win_size.y / 2 - button_size.y); - if (imgui.button(button_text.c_str(), button_size.x, button_size.y)) - { - wxGetApp().printhost_job_queue().cancel(m_job_id - 1); - } - - //invisible large button - ImGui::SetCursorPosX(win_size.x - m_line_height * 4.625f); - ImGui::SetCursorPosY(0); - if (imgui.button(" ", m_line_height * 2.f, win_size.y)) - { - wxGetApp().printhost_job_queue().cancel(m_job_id - 1); - } - ImGui::PopStyleColor(5); -} //------SlicingProgressNotification void NotificationManager::SlicingProgressNotification::init() { @@ -1739,59 +1596,6 @@ void NotificationManager::push_exporting_finished_notification(const std::string set_slicing_progress_hidden(); } -void NotificationManager::push_upload_job_notification(int id, float filesize, const std::string& filename, const std::string& host, float percentage) -{ - // find if upload with same id was not already in notification - // done by compare_jon_id not compare_text thus has to be performed here - for (std::unique_ptr& notification : m_pop_notifications) { - if (notification->get_type() == NotificationType::PrintHostUpload && dynamic_cast(notification.get())->compare_job_id(id)) { - return; - } - } - std::string text = PrintHostUploadNotification::get_upload_job_text(id, filename, host); - NotificationData data{ NotificationType::PrintHostUpload, NotificationLevel::ProgressBarNotificationLevel, 10, text }; - push_notification_data(std::make_unique(data, m_id_provider, m_evt_handler, 0, id, filesize), 0); -} -void NotificationManager::set_upload_job_notification_percentage(int id, const std::string& filename, const std::string& host, float percentage) -{ - for (std::unique_ptr& notification : m_pop_notifications) { - if (notification->get_type() == NotificationType::PrintHostUpload) { - PrintHostUploadNotification* phun = dynamic_cast(notification.get()); - if (phun->compare_job_id(id)) { - phun->set_percentage(percentage); - wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0); - break; - } - } - } -} -void NotificationManager::upload_job_notification_show_canceled(int id, const std::string& filename, const std::string& host) -{ - for (std::unique_ptr& notification : m_pop_notifications) { - if (notification->get_type() == NotificationType::PrintHostUpload) { - PrintHostUploadNotification* phun = dynamic_cast(notification.get()); - if (phun->compare_job_id(id)) { - phun->cancel(); - wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0); - break; - } - } - } -} -void NotificationManager::upload_job_notification_show_error(int id, const std::string& filename, const std::string& host) -{ - for (std::unique_ptr& notification : m_pop_notifications) { - if (notification->get_type() == NotificationType::PrintHostUpload) { - PrintHostUploadNotification* phun = dynamic_cast(notification.get()); - if(phun->compare_job_id(id)) { - phun->error(); - wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0); - break; - } - } - } -} - void NotificationManager::init_slicing_progress_notification(std::function cancel_callback) { for (std::unique_ptr& notification : m_pop_notifications) { diff --git a/src/slic3r/GUI/NotificationManager.hpp b/src/slic3r/GUI/NotificationManager.hpp index d1947a80dd..d758dbe061 100644 --- a/src/slic3r/GUI/NotificationManager.hpp +++ b/src/slic3r/GUI/NotificationManager.hpp @@ -182,11 +182,6 @@ public: void stop_delayed_notifications_of_type(const NotificationType type); // Creates Validate Error notification with a custom text and no fade out. void push_validate_error_notification(StringObjectException const & error); - // print host upload - void push_upload_job_notification(int id, float filesize, const std::string& filename, const std::string& host, float percentage = 0); - void set_upload_job_notification_percentage(int id, const std::string& filename, const std::string& host, float percentage); - void upload_job_notification_show_canceled(int id, const std::string& filename, const std::string& host); - void upload_job_notification_show_error(int id, const std::string& filename, const std::string& host); // Creates Slicing Error notification with a custom text and no fade out. void push_slicing_error_notification(const std::string& text); // Creates Slicing Warning notification with a custom text and no fade out. @@ -562,48 +557,6 @@ private: }; - class PrintHostUploadNotification : public ProgressBarNotification - { - public: - enum class UploadJobState - { - PB_PROGRESS, - PB_ERROR, - PB_CANCELLED, - PB_COMPLETED - }; - PrintHostUploadNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler, float percentage, int job_id, float filesize) - :ProgressBarNotification(n, id_provider, evt_handler) - , m_job_id(job_id) - , m_file_size(filesize) - { - m_has_cancel_button = true; - set_percentage(percentage); - } - static std::string get_upload_job_text(int id, const std::string& filename, const std::string& host) { return /*"[" + std::to_string(id) + "] " + */filename + " -> " + host; } - void set_percentage(float percent) override; - void cancel() { m_uj_state = UploadJobState::PB_CANCELLED; m_has_cancel_button = false; } - void error() { m_uj_state = UploadJobState::PB_ERROR; m_has_cancel_button = false; init(); } - bool compare_job_id(const int other_id) const { return m_job_id == other_id; } - bool compare_text(const std::string& text) const override { return false; } - protected: - void init() override; - void count_spaces() override; - bool push_background_color() override; - void render_bar(ImGuiWrapper& imgui, - const float win_size_x, const float win_size_y, - const float win_pos_x, const float win_pos_y) override; - void render_cancel_button(ImGuiWrapper& imgui, - const float win_size_x, const float win_size_y, - const float win_pos_x, const float win_pos_y) override; - void render_left_sign(ImGuiWrapper& imgui) override; - // Identifies job in cancel callback - int m_job_id; - // Size of uploaded size to be displayed in MB - float m_file_size; - long m_hover_time{ 0 }; - UploadJobState m_uj_state{ UploadJobState::PB_PROGRESS }; - }; class SlicingProgressNotification : public ProgressBarNotification { public: diff --git a/src/slic3r/GUI/PhysicalPrinterDialog.cpp b/src/slic3r/GUI/PhysicalPrinterDialog.cpp deleted file mode 100644 index a148a7ccfd..0000000000 --- a/src/slic3r/GUI/PhysicalPrinterDialog.cpp +++ /dev/null @@ -1,746 +0,0 @@ -#include "PhysicalPrinterDialog.hpp" -#include "PresetComboBoxes.hpp" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "libslic3r/libslic3r.h" -#include "libslic3r/PrintConfig.hpp" -#include "libslic3r/PresetBundle.hpp" - -#include "GUI.hpp" -#include "GUI_App.hpp" -#include "MainFrame.hpp" -#include "format.hpp" -#include "Tab.hpp" -#include "wxExtensions.hpp" -#include "PrintHostDialogs.hpp" -#include "../Utils/ASCIIFolding.hpp" -#include "../Utils/PrintHost.hpp" -#include "../Utils/FixModelByWin10.hpp" -#include "../Utils/UndoRedo.hpp" -#include "RemovableDriveManager.hpp" -#include "BitmapCache.hpp" -#include "BonjourDialog.hpp" -#include "MsgDialog.hpp" - -namespace Slic3r { -namespace GUI { - -#define BORDER_W 10 - -//------------------------------------------ -// PresetForPrinter -//------------------------------------------ - -PresetForPrinter::PresetForPrinter(PhysicalPrinterDialog* parent, const std::string& preset_name) : - m_parent(parent) -{ - m_sizer = new wxBoxSizer(wxVERTICAL); - - m_delete_preset_btn = new ScalableButton(parent, wxID_ANY, "cross"); - m_delete_preset_btn->SetFont(wxGetApp().normal_font()); - m_delete_preset_btn->SetToolTip(_L("Delete this preset from this printer device")); - m_delete_preset_btn->Bind(wxEVT_BUTTON, &PresetForPrinter::DeletePreset, this); - - m_presets_list = new PresetComboBox(parent, Preset::TYPE_PRINTER); - m_presets_list->set_printer_technology(parent->get_printer_technology()); - - m_presets_list->set_selection_changed_function([this](int selection) { - std::string selected_string = Preset::remove_suffix_modified(m_presets_list->GetString(selection).ToUTF8().data()); - Preset* preset = wxGetApp().preset_bundle->printers.find_preset(selected_string); - assert(preset); - Preset& edited_preset = wxGetApp().preset_bundle->printers.get_edited_preset(); - if (preset->name == edited_preset.name) - preset = &edited_preset; - - // // if created physical printer doesn't have any settings, use the settings from the selected preset - // if (m_parent->get_printer()->has_empty_config()) { - // // update Print Host upload from the selected preset - // m_parent->get_printer()->update_from_preset(*preset); - // // update values in parent (PhysicalPrinterDialog) - // m_parent->update(true); - - // } - - // update PrinterTechnology if it was changed - if (m_presets_list->set_printer_technology(preset->printer_technology())) - m_parent->set_printer_technology(preset->printer_technology()); - - update_full_printer_name(); - }); - m_presets_list->update(preset_name); - - m_info_line = new wxStaticText(parent, wxID_ANY, _L("This printer will be shown in the presets list as") + ":"); - - m_full_printer_name = new wxStaticText(parent, wxID_ANY, ""); - m_full_printer_name->SetFont(wxGetApp().bold_font()); - - wxBoxSizer* preset_sizer = new wxBoxSizer(wxHORIZONTAL); - preset_sizer->Add(m_presets_list , 1, wxEXPAND); - preset_sizer->Add(m_delete_preset_btn , 0, wxEXPAND | wxLEFT, BORDER_W); - - wxBoxSizer* name_sizer = new wxBoxSizer(wxHORIZONTAL); - name_sizer->Add(m_info_line, 0, wxEXPAND); - name_sizer->Add(m_full_printer_name, 0, wxEXPAND | wxLEFT, BORDER_W); - - m_sizer->Add(preset_sizer , 0, wxEXPAND); - m_sizer->Add(name_sizer, 0, wxEXPAND); -} - -PresetForPrinter::~PresetForPrinter() -{ - m_presets_list->Destroy(); - m_delete_preset_btn->Destroy(); - m_info_line->Destroy(); - m_full_printer_name->Destroy(); -} - -void PresetForPrinter::DeletePreset(wxEvent& event) -{ - m_parent->DeletePreset(this); -} - -void PresetForPrinter::update_full_printer_name() -{ - wxString printer_name = m_parent->get_printer_name(); - wxString preset_name = m_presets_list->GetString(m_presets_list->GetSelection()); - - m_full_printer_name->SetLabelText(printer_name + " * " + preset_name); -} - -std::string PresetForPrinter::get_preset_name() -{ - return into_u8(m_presets_list->GetString(m_presets_list->GetSelection())); -} - -void PresetForPrinter::SuppressDelete() -{ - m_delete_preset_btn->Enable(false); - - // this case means that now we have only one related preset for the printer - // So, allow any selection - m_presets_list->set_printer_technology(ptAny); - m_presets_list->update(); -} - -void PresetForPrinter::AllowDelete() -{ - if (!m_delete_preset_btn->IsEnabled()) - m_delete_preset_btn->Enable(); - - m_presets_list->set_printer_technology(m_parent->get_printer_technology()); - m_presets_list->update(); -} - -void PresetForPrinter::msw_rescale() -{ - m_presets_list->msw_rescale(); - m_delete_preset_btn->msw_rescale(); -} - - -//------------------------------------------ -// PhysicalPrinterDialog -//------------------------------------------ - -PhysicalPrinterDialog::PhysicalPrinterDialog(wxWindow* parent, wxString printer_name) : - DPIDialog(parent, wxID_ANY, _L("Physical Printer"), wxDefaultPosition, wxSize(45 * wxGetApp().em_unit(), -1), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER), - m_printer("", wxGetApp().preset_bundle->physical_printers.default_config()), - had_all_mk3(!printer_name.empty()) -{ - SetFont(wxGetApp().normal_font()); -#ifndef _WIN32 - SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); -#endif - m_default_name = _L("Type here the name of your printer device"); - bool new_printer = true; - - if (printer_name.IsEmpty()) - printer_name = m_default_name; - else { - std::string full_name = into_u8(printer_name); - printer_name = from_u8(PhysicalPrinter::get_short_name(full_name)); - new_printer = false; - } - - wxStaticText* label_top = new wxStaticText(this, wxID_ANY, _L("Descriptive name for the printer") + ":"); - - m_add_preset_btn = new ScalableButton(this, wxID_ANY, "add_copies"); - m_add_preset_btn->SetFont(wxGetApp().normal_font()); - m_add_preset_btn->SetToolTip(_L("Add preset for this printer device")); - m_add_preset_btn->Bind(wxEVT_BUTTON, &PhysicalPrinterDialog::AddPreset, this); - - m_printer_name = new wxTextCtrl(this, wxID_ANY, printer_name, wxDefaultPosition, wxDefaultSize); - wxGetApp().UpdateDarkUI(m_printer_name); - m_printer_name->Bind(wxEVT_TEXT, [this](wxEvent&) { this->update_full_printer_names(); }); - - PhysicalPrinterCollection& printers = wxGetApp().preset_bundle->physical_printers; - PhysicalPrinter* printer = printers.find_printer(into_u8(printer_name)); - if (!printer) { - const Preset& preset = wxGetApp().preset_bundle->printers.get_edited_preset(); - m_printer = PhysicalPrinter(into_u8(printer_name), m_printer.config, preset); - // if printer_name is empty it means that new printer is created, so enable all items in the preset list - m_presets.emplace_back(new PresetForPrinter(this, preset.name)); - } - else - { - m_printer = *printer; - const std::set& preset_names = printer->get_preset_names(); - for (const std::string& preset_name : preset_names) - m_presets.emplace_back(new PresetForPrinter(this, preset_name)); - } - - if (m_presets.size() == 1) - m_presets.front()->SuppressDelete(); - - update_full_printer_names(); - - m_config = &m_printer.config; - m_config = &wxGetApp().preset_bundle->printers.get_edited_preset().config; - m_optgroup = new ConfigOptionsGroup(this, _L("Print Host upload"), m_config); - build_printhost_settings(m_optgroup); - - wxStdDialogButtonSizer* btns = this->CreateStdDialogButtonSizer(wxOK | wxCANCEL); - wxButton* btnOK = static_cast(this->FindWindowById(wxID_OK, this)); - wxGetApp().UpdateDarkUI(btnOK); - btnOK->Bind(wxEVT_BUTTON, &PhysicalPrinterDialog::OnOK, this); - - wxGetApp().UpdateDarkUI(static_cast(this->FindWindowById(wxID_CANCEL, this))); - - wxBoxSizer* nameSizer = new wxBoxSizer(wxHORIZONTAL); - nameSizer->Add(m_printer_name, 1, wxEXPAND); - nameSizer->Add(m_add_preset_btn, 0, wxEXPAND | wxLEFT, BORDER_W); - - m_presets_sizer = new wxBoxSizer(wxVERTICAL); - for (PresetForPrinter* preset : m_presets) - m_presets_sizer->Add(preset->sizer(), 1, wxEXPAND | wxTOP, BORDER_W); - - wxBoxSizer* topSizer = new wxBoxSizer(wxVERTICAL); - - topSizer->Add(label_top , 0, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, BORDER_W); - topSizer->Add(nameSizer , 0, wxEXPAND | wxLEFT | wxRIGHT, BORDER_W); - topSizer->Add(m_presets_sizer , 0, wxEXPAND | wxLEFT | wxRIGHT, BORDER_W); - topSizer->Add(m_optgroup->sizer , 1, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, BORDER_W); - topSizer->Add(btns , 0, wxEXPAND | wxALL, BORDER_W); - - SetSizer(topSizer); - topSizer->SetSizeHints(this); - - if (new_printer) { - m_printer_name->SetFocus(); - m_printer_name->SelectAll(); - } - - this->CenterOnScreen(); -} - -PhysicalPrinterDialog::~PhysicalPrinterDialog() -{ - for (PresetForPrinter* preset : m_presets) { - delete preset; - preset = nullptr; - } -} - -void PhysicalPrinterDialog::update_printers() -{ - wxBusyCursor wait; - - std::unique_ptr host(PrintHost::get_print_host(m_config)); - - wxArrayString printers; - Field *rs = m_optgroup->get_field("printhost_port"); - try { - if (! host->get_printers(printers)) - printers.clear(); - } catch (const HostNetworkError &err) { - printers.clear(); - show_error(this, _L("Connection to printers connected via the print host failed.") + "\n\n" + from_u8(err.what())); - } - Choice *choice = dynamic_cast(rs); - choice->set_values(printers); - printers.empty() ? rs->disable() : rs->enable(); -} - -void PhysicalPrinterDialog::build_printhost_settings(ConfigOptionsGroup* m_optgroup) -{ - m_optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value) { - if (opt_key == "host_type" || opt_key == "printhost_authorization_type") - this->update(); - if (opt_key == "print_host") - this->update_printhost_buttons(); - }; - - m_optgroup->append_single_option_line("host_type"); - - auto create_sizer_with_btn = [](wxWindow* parent, ScalableButton** btn, const std::string& icon_name, const wxString& label) { - *btn = new ScalableButton(parent, wxID_ANY, icon_name, label, wxDefaultSize, wxDefaultPosition, wxBU_LEFT | wxBU_EXACTFIT); - (*btn)->SetFont(wxGetApp().normal_font()); - - auto sizer = new wxBoxSizer(wxHORIZONTAL); - sizer->Add(*btn); - return sizer; - }; - - auto printhost_browse = [=](wxWindow* parent) - { - auto sizer = create_sizer_with_btn(parent, &m_printhost_browse_btn, "browse", _L("Browse") + " " + dots); - m_printhost_browse_btn->Bind(wxEVT_BUTTON, [=](wxCommandEvent& e) { - BonjourDialog dialog(this, Preset::printer_technology(m_printer.config)); - if (dialog.show_and_lookup()) { - m_optgroup->set_value("print_host", dialog.get_selected(), true); - m_optgroup->get_field("print_host")->field_changed(); - } - }); - - return sizer; - }; - - auto print_host_test = [=](wxWindow* parent) { - auto sizer = create_sizer_with_btn(parent, &m_printhost_test_btn, "test", _L("Test")); - - m_printhost_test_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent& e) { - std::unique_ptr host(PrintHost::get_print_host(m_config)); - if (!host) { - const wxString text = _L("Could not get a valid Printer Host reference"); - show_error(this, text); - return; - } - wxString msg; - bool result; - { - // Show a wait cursor during the connection test, as it is blocking UI. - wxBusyCursor wait; - result = host->test(msg); - } - if (result) - show_info(this, host->get_test_ok_msg(), _L("Success!")); - else - show_error(this, host->get_test_failed_msg(msg)); - }); - - return sizer; - }; - - auto print_host_printers = [this, create_sizer_with_btn](wxWindow* parent) { - //add_scaled_button(parent, &m_printhost_port_browse_btn, "browse", _(L("Refresh Printers")), wxBU_LEFT | wxBU_EXACTFIT); - auto sizer = create_sizer_with_btn(parent, &m_printhost_port_browse_btn, "browse", _(L("Refresh Printers"))); - ScalableButton* btn = m_printhost_port_browse_btn; - btn->SetFont(Slic3r::GUI::wxGetApp().normal_font()); - btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent e) { update_printers(); }); - return sizer; - }; - - // Set a wider width for a better alignment - Option option = m_optgroup->get_option("print_host"); - option.opt.width = Field::def_width_wider(); - Line host_line = m_optgroup->create_single_option_line(option); - host_line.append_widget(printhost_browse); - host_line.append_widget(print_host_test); - m_optgroup->append_line(host_line); - - m_optgroup->append_single_option_line("printhost_authorization_type"); - - option = m_optgroup->get_option("printhost_apikey"); - option.opt.width = Field::def_width_wider(); - m_optgroup->append_single_option_line(option); - - option = m_optgroup->get_option("printhost_port"); - option.opt.width = Field::def_width_wider(); - Line port_line = m_optgroup->create_single_option_line(option); - port_line.append_widget(print_host_printers); - m_optgroup->append_line(port_line); - - const auto ca_file_hint = _u8L("HTTPS CA file is optional. It is only needed if you use HTTPS with a self-signed certificate."); - - if (Http::ca_file_supported()) { - option = m_optgroup->get_option("printhost_cafile"); - option.opt.width = Field::def_width_wider(); - Line cafile_line = m_optgroup->create_single_option_line(option); - - auto printhost_cafile_browse = [=](wxWindow* parent) { - auto sizer = create_sizer_with_btn(parent, &m_printhost_cafile_browse_btn, "browse", _L("Browse") + " " + dots); - m_printhost_cafile_browse_btn->Bind(wxEVT_BUTTON, [this, m_optgroup](wxCommandEvent e) { - static const auto filemasks = _L("Certificate files (*.crt, *.pem)|*.crt;*.pem|All files|*.*"); - wxFileDialog openFileDialog(this, _L("Open CA certificate file"), "", "", filemasks, wxFD_OPEN | wxFD_FILE_MUST_EXIST); - if (openFileDialog.ShowModal() != wxID_CANCEL) { - m_optgroup->set_value("printhost_cafile", openFileDialog.GetPath(), true); - m_optgroup->get_field("printhost_cafile")->field_changed(); - } - }); - - return sizer; - }; - - cafile_line.append_widget(printhost_cafile_browse); - m_optgroup->append_line(cafile_line); - - Line cafile_hint{ "", "" }; - cafile_hint.full_width = 1; - cafile_hint.widget = [ca_file_hint](wxWindow* parent) { - auto txt = new wxStaticText(parent, wxID_ANY, ca_file_hint); - auto sizer = new wxBoxSizer(wxHORIZONTAL); - sizer->Add(txt); - return sizer; - }; - m_optgroup->append_line(cafile_hint); - } - else { - - Line line{ "", "" }; - line.full_width = 1; - - line.widget = [ca_file_hint](wxWindow* parent) { - std::string info = _u8L("HTTPS CA File") + ":\n\t" + - (boost::format(_u8L("On this system, %s uses HTTPS certificates from the system Certificate Store or Keychain.")) % SLIC3R_APP_NAME).str() + - "\n\t" + _u8L("To use a custom CA file, please import your CA file into Certificate Store / Keychain."); - - //auto txt = new wxStaticText(parent, wxID_ANY, from_u8((boost::format("%1%\n\n\t%2%") % info % ca_file_hint).str())); - auto txt = new wxStaticText(parent, wxID_ANY, from_u8((boost::format("%1%\n\t%2%") % info % ca_file_hint).str())); - txt->SetFont(wxGetApp().normal_font()); - auto sizer = new wxBoxSizer(wxHORIZONTAL); - sizer->Add(txt, 1, wxEXPAND); - return sizer; - }; - m_optgroup->append_line(line); - } - - for (const std::string& opt_key : std::vector{ "printhost_user", "printhost_password" }) { - option = m_optgroup->get_option(opt_key); - option.opt.width = Field::def_width_wider(); - m_optgroup->append_single_option_line(option); - } - -#ifdef WIN32 - option = m_optgroup->get_option("printhost_ssl_ignore_revoke"); - option.opt.width = Field::def_width_wider(); - m_optgroup->append_single_option_line(option); -#endif - - m_optgroup->activate(); - - Field* printhost_field = m_optgroup->get_field("print_host"); - if (printhost_field) - { - wxTextCtrl* temp = dynamic_cast(printhost_field->getWindow()); - if (temp) - temp->Bind(wxEVT_TEXT, ([printhost_field, temp](wxEvent& e) - { -#ifndef __WXGTK__ - e.Skip(); - temp->GetToolTip()->Enable(true); -#endif // __WXGTK__ - // Remove all leading and trailing spaces from the input - std::string trimed_str, str = trimed_str = temp->GetValue().ToStdString(); - boost::trim(trimed_str); - if (trimed_str != str) - temp->SetValue(trimed_str); - - TextCtrl* field = dynamic_cast(printhost_field); - if (field) - field->propagate_value(); - }), temp->GetId()); - } - - // Always fill in the "printhost_port" combo box from the config and select it. - { - Choice* choice = dynamic_cast(m_optgroup->get_field("printhost_port")); - choice->set_values({ m_config->opt_string("printhost_port") }); - choice->set_selection(); - } - - update(); -} - -void PhysicalPrinterDialog::update_printhost_buttons() -{ - std::unique_ptr host(PrintHost::get_print_host(m_config)); - m_printhost_test_btn->Enable(!m_config->opt_string("print_host").empty() && host->can_test()); - m_printhost_browse_btn->Enable(host->has_auto_discovery()); -} - -void PhysicalPrinterDialog::update(bool printer_change) -{ - m_optgroup->reload_config(); - - const PrinterTechnology tech = Preset::printer_technology(*m_config); - // Only offer the host type selection for FFF, for SLA it's always the SL1 printer (at the moment) - bool supports_multiple_printers = false; - if (tech == ptFFF) { - update_host_type(printer_change); - const auto opt = m_config->option>("host_type"); - m_optgroup->show_field("host_type"); - if (opt->value == htPrusaLink) - { - m_optgroup->show_field("printhost_authorization_type"); - AuthorizationType auth_type = m_config->option>("printhost_authorization_type")->value; - m_optgroup->show_field("printhost_apikey", auth_type == AuthorizationType::atKeyPassword); - for (const char* opt_key : { "printhost_user", "printhost_password" }) - m_optgroup->show_field(opt_key, auth_type == AuthorizationType::atUserPassword); - } else { - m_optgroup->hide_field("printhost_authorization_type"); - m_optgroup->show_field("printhost_apikey", true); - for (const std::string& opt_key : std::vector{ "printhost_user", "printhost_password" }) - m_optgroup->hide_field(opt_key); - supports_multiple_printers = opt && opt->value == htRepetier; - } - - } - else { - m_optgroup->set_value("host_type", int(PrintHostType::htOctoPrint), false); - m_optgroup->hide_field("host_type"); - - m_optgroup->show_field("printhost_authorization_type"); - - AuthorizationType auth_type = m_config->option>("printhost_authorization_type")->value; - m_optgroup->show_field("printhost_apikey", auth_type == AuthorizationType::atKeyPassword); - - for (const char *opt_key : { "printhost_user", "printhost_password" }) - m_optgroup->show_field(opt_key, auth_type == AuthorizationType::atUserPassword); - } - - m_optgroup->show_field("printhost_port", supports_multiple_printers); - m_printhost_port_browse_btn->Show(supports_multiple_printers); - - update_printhost_buttons(); - - this->SetSize(this->GetBestSize()); - this->Layout(); -} - -void PhysicalPrinterDialog::update_host_type(bool printer_change) -{ - if (m_presets.empty()) - return; - bool all_presets_are_from_mk3_family = true; - - for (PresetForPrinter* prstft : m_presets) { - std::string preset_name = prstft->get_preset_name(); - if (Preset* preset = wxGetApp().preset_bundle->printers.find_preset(preset_name)) { - std::string model_id = preset->config.opt_string("printer_model"); - auto model_supports_prusalink = [](const std::string &model) { - return model.size() >= 3 && - ((boost::starts_with(model, "MK") && model[2] > '2' && model[2] <= '9') || - boost::starts_with(model, "MINI")); - }; - if (preset->vendor) { - if (preset->vendor->name == "Prusa Research") { - const std::vector& models = preset->vendor->models; - auto it = std::find_if(models.begin(), models.end(), - [model_id](const VendorProfile::PrinterModel& model) { return model.id == model_id; }); - if (it != models.end() && model_supports_prusalink(it->family)) - continue; - } - } else if (model_supports_prusalink(model_id)) - continue; - } - all_presets_are_from_mk3_family = false; - break; - } - - Field* ht = m_optgroup->get_field("host_type"); - - wxArrayString types; - // Append localized enum_labels - assert(ht->m_opt.enum_labels.size() == ht->m_opt.enum_values.size()); - for (size_t i = 0; i < ht->m_opt.enum_labels.size(); i++) { - if (ht->m_opt.enum_values[i] == "prusalink" && !all_presets_are_from_mk3_family) - continue; - types.Add(_(ht->m_opt.enum_labels[i])); - } - - Choice* choice = dynamic_cast(ht); - choice->set_values(types); - auto set_to_choice_and_config = [this, choice](PrintHostType type) { - choice->set_value(static_cast(type)); - m_config->set_key_value("host_type", new ConfigOptionEnum(type)); - }; - if ((printer_change && all_presets_are_from_mk3_family) || (!had_all_mk3 && all_presets_are_from_mk3_family)) - set_to_choice_and_config(htPrusaLink); - else if ((printer_change && !all_presets_are_from_mk3_family) || (!all_presets_are_from_mk3_family && m_config->option>("host_type")->value == htPrusaLink)) - set_to_choice_and_config(htOctoPrint); - else - choice->set_value(m_config->option("host_type")->getInt()); - had_all_mk3 = all_presets_are_from_mk3_family; -} - - -wxString PhysicalPrinterDialog::get_printer_name() -{ - return m_printer_name->GetValue(); -} - -void PhysicalPrinterDialog::update_full_printer_names() -{ - for (PresetForPrinter* preset : m_presets) - preset->update_full_printer_name(); - - this->Layout(); -} - -void PhysicalPrinterDialog::set_printer_technology(PrinterTechnology pt) -{ - m_config->set_key_value("printer_technology", new ConfigOptionEnum(pt)); - update(); -} - -PrinterTechnology PhysicalPrinterDialog::get_printer_technology() -{ - return m_printer.printer_technology(); -} - -void PhysicalPrinterDialog::on_dpi_changed(const wxRect& suggested_rect) -{ - const int& em = em_unit(); - - m_add_preset_btn->msw_rescale(); - m_printhost_browse_btn->msw_rescale(); - m_printhost_test_btn->msw_rescale(); - if (m_printhost_cafile_browse_btn) - m_printhost_cafile_browse_btn->msw_rescale(); - - m_optgroup->msw_rescale(); - - msw_buttons_rescale(this, em, { wxID_OK, wxID_CANCEL }); - - for (PresetForPrinter* preset : m_presets) - preset->msw_rescale(); - - const wxSize& size = wxSize(45 * em, 35 * em); - SetMinSize(size); - - Fit(); - Refresh(); -} - -void PhysicalPrinterDialog::OnOK(wxEvent& event) -{ - wxString printer_name = m_printer_name->GetValue(); - if (printer_name.IsEmpty()) { - warning_catcher(this, _L("The supplied name is empty. It can't be saved.")); - return; - } - if (printer_name == m_default_name) { - warning_catcher(this, _L("You should change the name of your printer device.")); - return; - } - - PhysicalPrinterCollection& printers = wxGetApp().preset_bundle->physical_printers; - const PhysicalPrinter* existing = printers.find_printer(into_u8(printer_name), false); - if (existing && into_u8(printer_name) != printers.get_selected_printer_name()) - { - wxString msg_text = from_u8((boost::format(_u8L("Printer with name \"%1%\" already exists.")) % existing->name/*printer_name*/).str()); - msg_text += "\n" + _L("Replace?"); - //wxMessageDialog dialog(nullptr, msg_text, _L("Warning"), wxICON_WARNING | wxYES | wxNO); - MessageDialog dialog(nullptr, msg_text, _L("Warning"), wxICON_WARNING | wxYES | wxNO); - - if (dialog.ShowModal() == wxID_NO) - return; - - m_printer.name = existing->name; - } - - std::set repeat_presets; - m_printer.reset_presets(); - for (PresetForPrinter* preset : m_presets) { - if (!m_printer.add_preset(preset->get_preset_name())) - repeat_presets.emplace(preset->get_preset_name()); - } - - if (!repeat_presets.empty()) - { - wxString repeatable_presets = "\n"; - int repeat_cnt = 0; - for (const std::string& preset_name : repeat_presets) { - repeatable_presets += " " + from_u8(preset_name) + "\n"; - repeat_cnt++; - } - repeatable_presets += "\n"; - - wxString msg_text = format_wxstr(_L_PLURAL("Following printer preset is duplicated:%1%" - "The above preset for printer \"%2%\" will be used just once.", - "Following printer presets are duplicated:%1%" - "The above presets for printer \"%2%\" will be used just once.", repeat_cnt), repeatable_presets, printer_name); - //wxMessageDialog dialog(nullptr, msg_text, _L("Warning"), wxICON_WARNING | wxOK | wxCANCEL); - MessageDialog dialog(nullptr, msg_text, _L("Warning"), wxICON_WARNING | wxOK | wxCANCEL); - if (dialog.ShowModal() == wxID_CANCEL) - return; - } - - std::string renamed_from; - // temporary save previous printer name if it was edited - if (m_printer.name != into_u8(m_default_name) && - m_printer.name != into_u8(printer_name)) - renamed_from = m_printer.name; - - //update printer name, if it was changed - m_printer.set_name(into_u8(printer_name)); - - // save new physical printer - printers.save_printer(m_printer, renamed_from); - - if (m_printer.preset_names.find(printers.get_selected_printer_preset_name()) == m_printer.preset_names.end()) { - // select first preset for this printer - printers.select_printer(m_printer); - // refresh preset list on Printer Settings Tab - wxGetApp().get_tab(Preset::TYPE_PRINTER)->select_preset(printers.get_selected_printer_preset_name()); - } - else - wxGetApp().get_tab(Preset::TYPE_PRINTER)->update_preset_choice(); - - event.Skip(); -} - -void PhysicalPrinterDialog::AddPreset(wxEvent& event) -{ - m_presets.emplace_back(new PresetForPrinter(this)); - // enable DELETE button for the first preset, if was disabled - m_presets.front()->AllowDelete(); - - m_presets_sizer->Add(m_presets.back()->sizer(), 1, wxEXPAND | wxTOP, BORDER_W); - update_full_printer_names(); - this->Fit(); - - update_host_type(true); -} - -void PhysicalPrinterDialog::DeletePreset(PresetForPrinter* preset_for_printer) -{ - if (m_presets.size() == 1) { - wxString msg_text = _L("It's not possible to delete the last related preset for the printer."); - //wxMessageDialog dialog(nullptr, msg_text, _L("Information"), wxICON_INFORMATION | wxOK); - MessageDialog dialog(nullptr, msg_text, _L("Information"), wxICON_INFORMATION | wxOK); - dialog.ShowModal(); - return; - } - - assert(preset_for_printer); - auto it = std::find(m_presets.begin(), m_presets.end(), preset_for_printer); - if (it == m_presets.end()) - return; - - const int remove_id = it - m_presets.begin(); - m_presets_sizer->Remove(remove_id); - delete preset_for_printer; - m_presets.erase(it); - - if (m_presets.size() == 1) - m_presets.front()->SuppressDelete(); - - this->Layout(); - this->Fit(); - - update_host_type(true); -} - -}} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/PhysicalPrinterDialog.hpp b/src/slic3r/GUI/PhysicalPrinterDialog.hpp deleted file mode 100644 index b153d15924..0000000000 --- a/src/slic3r/GUI/PhysicalPrinterDialog.hpp +++ /dev/null @@ -1,111 +0,0 @@ -#ifndef slic3r_PhysicalPrinterDialog_hpp_ -#define slic3r_PhysicalPrinterDialog_hpp_ - -#include - -#include - -#include "libslic3r/Preset.hpp" -#include "GUI_Utils.hpp" - -class wxString; -class wxTextCtrl; -class wxStaticText; -class ScalableButton; -class wxBoxSizer; - -namespace Slic3r { - -namespace GUI { - -class PresetComboBox; - -//------------------------------------------ -// PresetForPrinter -//------------------------------------------ -//static std::string g_info_string = " (modified)"; -class PhysicalPrinterDialog; -class PresetForPrinter -{ - PhysicalPrinterDialog* m_parent { nullptr }; - - PresetComboBox* m_presets_list { nullptr }; - ScalableButton* m_delete_preset_btn { nullptr }; - wxStaticText* m_info_line { nullptr }; - wxStaticText* m_full_printer_name { nullptr }; - - wxBoxSizer* m_sizer { nullptr }; - - void DeletePreset(wxEvent& event); - -public: - PresetForPrinter(PhysicalPrinterDialog* parent, const std::string& preset_name = ""); - ~PresetForPrinter(); - - wxBoxSizer* sizer() { return m_sizer; } - void update_full_printer_name(); - std::string get_preset_name(); - void SuppressDelete(); - void AllowDelete(); - - void msw_rescale(); - void on_sys_color_changed() {}; -}; - - -//------------------------------------------ -// PhysicalPrinterDialog -//------------------------------------------ - -class ConfigOptionsGroup; -class PhysicalPrinterDialog : public DPIDialog -{ - PhysicalPrinter m_printer; - wxString m_default_name; - DynamicPrintConfig* m_config { nullptr }; - - wxTextCtrl* m_printer_name { nullptr }; - std::vector m_presets; - - ConfigOptionsGroup* m_optgroup { nullptr }; - - ScalableButton* m_add_preset_btn {nullptr}; - ScalableButton* m_printhost_browse_btn {nullptr}; - ScalableButton* m_printhost_test_btn {nullptr}; - ScalableButton* m_printhost_cafile_browse_btn {nullptr}; - ScalableButton* m_printhost_client_cert_browse_btn {nullptr}; - ScalableButton* m_printhost_port_browse_btn {nullptr}; - - wxBoxSizer* m_presets_sizer {nullptr}; - - void build_printhost_settings(ConfigOptionsGroup* optgroup); - void OnOK(wxEvent& event); - void AddPreset(wxEvent& event); - -public: - PhysicalPrinterDialog(wxWindow* parent, wxString printer_name); - ~PhysicalPrinterDialog(); - - void update(bool printer_change = false); - void update_host_type(bool printer_change); - void update_printhost_buttons(); - void update_printers(); - wxString get_printer_name(); - void update_full_printer_names(); - PhysicalPrinter* get_printer() {return &m_printer; } - void set_printer_technology(PrinterTechnology pt); - PrinterTechnology get_printer_technology(); - - void DeletePreset(PresetForPrinter* preset_for_printer); -protected: - void on_dpi_changed(const wxRect& suggested_rect) override; - void on_sys_color_changed() override {}; - - bool had_all_mk3; -}; - - -} // namespace GUI -} // namespace Slic3r - -#endif diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 72d7be09e7..06d49d9bef 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -124,8 +124,6 @@ #include "libslic3r/Platform.hpp" #include "nlohmann/json.hpp" -#include "PhysicalPrinterDialog.hpp" - using boost::optional; namespace fs = boost::filesystem; using Slic3r::_3DScene; @@ -505,26 +503,12 @@ Sidebar::Sidebar(Plater *parent) combo_printer->edit_btn = edit_btn; p->combo_printer = combo_printer; - ScalableButton* connection_btn = new ScalableButton(p->m_panel_printer_content, wxID_ANY, "printer"); - connection_btn->SetBackgroundColour(wxColour(255, 255, 255)); - connection_btn->SetToolTip(_L("Print connection")); - connection_btn->Bind(wxEVT_BUTTON, [this, combo_printer](wxCommandEvent) - { - auto preset_name = into_u8(combo_printer->GetString(combo_printer->GetSelection())); - auto printer_name = from_u8(PhysicalPrinter::get_short_name(preset_name)+"-printer"); - PhysicalPrinterDialog dlg(this->GetParent(),printer_name); - dlg.ShowModal(); - // wxMessageBox("Connection support WIP", "INFO", wxOK | wxICON_INFORMATION); - }); - - wxBoxSizer *vsizer_printer = new wxBoxSizer(wxVERTICAL); - wxBoxSizer *hsizer_printer = new wxBoxSizer(wxHORIZONTAL); + wxBoxSizer* vsizer_printer = new wxBoxSizer(wxVERTICAL); + wxBoxSizer* hsizer_printer = new wxBoxSizer(wxHORIZONTAL); hsizer_printer->Add(combo_printer, 1, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(3)); hsizer_printer->Add(edit_btn, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(3)); hsizer_printer->Add(FromDIP(8), 0, 0, 0, 0); - hsizer_printer->Add(connection_btn, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(3)); - hsizer_printer->Add(FromDIP(8), 0, 0, 0, 0); vsizer_printer->Add(hsizer_printer, 0, wxEXPAND, 0); // Bed type selection diff --git a/src/slic3r/GUI/PrintHostDialogs.cpp b/src/slic3r/GUI/PrintHostDialogs.cpp deleted file mode 100644 index 09ba48b584..0000000000 --- a/src/slic3r/GUI/PrintHostDialogs.cpp +++ /dev/null @@ -1,520 +0,0 @@ -#include "PrintHostDialogs.hpp" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "GUI.hpp" -#include "GUI_App.hpp" -#include "MsgDialog.hpp" -#include "I18N.hpp" -#include "MainFrame.hpp" -#include "libslic3r/AppConfig.hpp" -#include "NotificationManager.hpp" -#include "ExtraRenderers.hpp" - -namespace fs = boost::filesystem; - -namespace Slic3r { -namespace GUI { - -static const char *CONFIG_KEY_PATH = "printhost_path"; -static const char *CONFIG_KEY_GROUP = "printhost_group"; - -PrintHostSendDialog::PrintHostSendDialog(const fs::path &path, PrintHostPostUploadActions post_actions, const wxArrayString &groups) - : MsgDialog(static_cast(wxGetApp().mainframe), _L("Send G-Code to printer host"), _L("Upload to Printer Host with the following filename:")) - , txt_filename(new wxTextCtrl(this, wxID_ANY)) - , combo_groups(!groups.IsEmpty() ? new wxComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, groups, wxCB_READONLY) : nullptr) - , post_upload_action(PrintHostPostUploadAction::None) -{ -#ifdef __APPLE__ - txt_filename->OSXDisableAllSmartSubstitutions(); -#endif - const AppConfig *app_config = wxGetApp().app_config; - - auto *label_dir_hint = new wxStaticText(this, wxID_ANY, _L("Use forward slashes ( / ) as a directory separator if needed.")); - label_dir_hint->Wrap(CONTENT_WIDTH * wxGetApp().em_unit()); - - content_sizer->Add(txt_filename, 0, wxEXPAND); - content_sizer->Add(label_dir_hint); - content_sizer->AddSpacer(VERT_SPACING); - - if (combo_groups != nullptr) { - // Repetier specific: Show a selection of file groups. - auto *label_group = new wxStaticText(this, wxID_ANY, _L("Group")); - content_sizer->Add(label_group); - content_sizer->Add(combo_groups, 0, wxBOTTOM, 2*VERT_SPACING); - wxString recent_group = from_u8(app_config->get("recent", CONFIG_KEY_GROUP)); - if (! recent_group.empty()) - combo_groups->SetValue(recent_group); - } - - wxString recent_path = from_u8(app_config->get("recent", CONFIG_KEY_PATH)); - if (recent_path.Length() > 0 && recent_path[recent_path.Length() - 1] != '/') { - recent_path += '/'; - } - const auto recent_path_len = recent_path.Length(); - recent_path += path.filename().wstring(); - wxString stem(path.stem().wstring()); - const auto stem_len = stem.Length(); - - txt_filename->SetValue(recent_path); - txt_filename->SetFocus(); - - m_valid_suffix = recent_path.substr(recent_path.find_last_of('.')); - // .gcode suffix control - auto validate_path = [this](const wxString &path) -> bool { - if (! path.Lower().EndsWith(m_valid_suffix.Lower())) { - MessageDialog msg_wingow(this, wxString::Format(_L("Upload filename doesn't end with \"%s\". Do you wish to continue?"), m_valid_suffix), wxString(SLIC3R_APP_NAME), wxYES | wxNO); - if (msg_wingow.ShowModal() == wxID_NO) - return false; - } - return true; - }; - - if (post_actions.has(PrintHostPostUploadAction::StartPrint)) { - auto* btn_print = add_button(wxID_YES, false, _L("Upload and Print")); - btn_print->Bind(wxEVT_BUTTON, [this, validate_path](wxCommandEvent&) { - if (validate_path(txt_filename->GetValue())) { - post_upload_action = PrintHostPostUploadAction::StartPrint; - EndDialog(wxID_OK); - } - }); - } - - if (post_actions.has(PrintHostPostUploadAction::StartSimulation)) { - // Using wxID_MORE as a button identifier to be different from the other buttons, wxID_MORE has no other meaning here. - auto* btn_simulate = add_button(wxID_MORE, false, _L("Upload and Simulate")); - btn_simulate->Bind(wxEVT_BUTTON, [this, validate_path](wxCommandEvent&) { - if (validate_path(txt_filename->GetValue())) { - post_upload_action = PrintHostPostUploadAction::StartSimulation; - EndDialog(wxID_OK); - } - }); - } - - add_button(wxID_CANCEL); - - if (auto* btn_ok = get_button(wxID_OK); btn_ok != NULL) { - btn_ok->SetLabel(_L("Upload")); - btn_ok->Bind(wxEVT_BUTTON, [this, validate_path](wxCommandEvent&) { - if (validate_path(txt_filename->GetValue())) { - post_upload_action = PrintHostPostUploadAction::None; - EndDialog(wxID_OK); - } - }); - } - finalize(); - -#ifdef __linux__ - // On Linux with GTK2 when text control lose the focus then selection (colored background) disappears but text color stay white - // and as a result the text is invisible with light mode - // see https://github.com/prusa3d/PrusaSlicer/issues/4532 - // Workaround: Unselect text selection explicitly on kill focus - txt_filename->Bind(wxEVT_KILL_FOCUS, [this](wxEvent& e) { - e.Skip(); - txt_filename->SetInsertionPoint(txt_filename->GetLastPosition()); - }, txt_filename->GetId()); -#endif /* __linux__ */ - - Bind(wxEVT_SHOW, [=](const wxShowEvent &) { - // Another similar case where the function only works with EVT_SHOW + CallAfter, - // this time on Mac. - CallAfter([=]() { - txt_filename->SetSelection(recent_path_len, recent_path_len + stem_len); - }); - }); -} - -fs::path PrintHostSendDialog::filename() const -{ - return into_path(txt_filename->GetValue()); -} - -PrintHostPostUploadAction PrintHostSendDialog::post_action() const -{ - return post_upload_action; -} - -std::string PrintHostSendDialog::group() const -{ - if (combo_groups == nullptr) { - return ""; - } else { - wxString group = combo_groups->GetValue(); - return into_u8(group); - } -} - -void PrintHostSendDialog::EndModal(int ret) -{ - if (ret == wxID_OK) { - // Persist path and print settings - wxString path = txt_filename->GetValue(); - int last_slash = path.Find('/', true); - if (last_slash == wxNOT_FOUND) - path.clear(); - else - path = path.SubString(0, last_slash); - - AppConfig *app_config = wxGetApp().app_config; - app_config->set("recent", CONFIG_KEY_PATH, into_u8(path)); - - if (combo_groups != nullptr) { - wxString group = combo_groups->GetValue(); - app_config->set("recent", CONFIG_KEY_GROUP, into_u8(group)); - } - } - - MsgDialog::EndModal(ret); -} - - - -wxDEFINE_EVENT(EVT_PRINTHOST_PROGRESS, PrintHostQueueDialog::Event); -wxDEFINE_EVENT(EVT_PRINTHOST_ERROR, PrintHostQueueDialog::Event); -wxDEFINE_EVENT(EVT_PRINTHOST_CANCEL, PrintHostQueueDialog::Event); - -PrintHostQueueDialog::Event::Event(wxEventType eventType, int winid, size_t job_id) - : wxEvent(winid, eventType) - , job_id(job_id) -{} - -PrintHostQueueDialog::Event::Event(wxEventType eventType, int winid, size_t job_id, int progress) - : wxEvent(winid, eventType) - , job_id(job_id) - , progress(progress) -{} - -PrintHostQueueDialog::Event::Event(wxEventType eventType, int winid, size_t job_id, wxString error) - : wxEvent(winid, eventType) - , job_id(job_id) - , error(std::move(error)) -{} - -wxEvent *PrintHostQueueDialog::Event::Clone() const -{ - return new Event(*this); -} - -PrintHostQueueDialog::PrintHostQueueDialog(wxWindow *parent) - : DPIDialog(parent, wxID_ANY, _L("Print host upload queue"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) - , on_progress_evt(this, EVT_PRINTHOST_PROGRESS, &PrintHostQueueDialog::on_progress, this) - , on_error_evt(this, EVT_PRINTHOST_ERROR, &PrintHostQueueDialog::on_error, this) - , on_cancel_evt(this, EVT_PRINTHOST_CANCEL, &PrintHostQueueDialog::on_cancel, this) -{ - const auto em = GetTextExtent("m").x; - - auto *topsizer = new wxBoxSizer(wxVERTICAL); - - std::vector widths; - widths.reserve(6); - if (!load_user_data(UDT_COLS, widths)) { - widths.clear(); - for (size_t i = 0; i < 6; i++) - widths.push_back(-1); - } - - job_list = new wxDataViewListCtrl(this, wxID_ANY); - - // MSW DarkMode: workaround for the selected item in the list - auto append_text_column = [this](const wxString& label, int width, wxAlignment align = wxALIGN_LEFT, - int flags = wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE) { -#ifdef _WIN32 - job_list->AppendColumn(new wxDataViewColumn(label, new TextRenderer(), job_list->GetColumnCount(), width, align, flags)); -#else - job_list->AppendTextColumn(label, wxDATAVIEW_CELL_INERT, width, align, flags); -#endif - }; - - // Note: Keep these in sync with Column - append_text_column(_L("ID"), widths[0]); - job_list->AppendProgressColumn(_L("Progress"), wxDATAVIEW_CELL_INERT, widths[1], wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE); - append_text_column(_L("Status"),widths[2]); - append_text_column(_L("Host"), widths[3]); - append_text_column(_CTX_utf8(L_CONTEXT("Size", "OfFile"), "OfFile"), widths[4]); - append_text_column(_L("Filename"), widths[5]); - append_text_column(_L("Error Message"), -1, wxALIGN_CENTER, wxDATAVIEW_COL_HIDDEN); - - auto *btnsizer = new wxBoxSizer(wxHORIZONTAL); - btn_cancel = new wxButton(this, wxID_DELETE, _L("Cancel selected")); - btn_cancel->Disable(); - btn_error = new wxButton(this, wxID_ANY, _L("Show error message")); - btn_error->Disable(); - // Note: The label needs to be present, otherwise we get accelerator bugs on Mac - auto *btn_close = new wxButton(this, wxID_CANCEL, _L("Close")); - btnsizer->Add(btn_cancel, 0, wxRIGHT, SPACING); - btnsizer->Add(btn_error, 0); - btnsizer->AddStretchSpacer(); - btnsizer->Add(btn_close); - - topsizer->Add(job_list, 1, wxEXPAND | wxBOTTOM, SPACING); - topsizer->Add(btnsizer, 0, wxEXPAND); - SetSizer(topsizer); - - wxGetApp().UpdateDlgDarkUI(this); - wxGetApp().UpdateDVCDarkUI(job_list); - - std::vector size; - SetSize(load_user_data(UDT_SIZE, size) ? wxSize(size[0] * em, size[1] * em) : wxSize(HEIGHT * em, WIDTH * em)); - - Bind(wxEVT_SIZE, [this](wxSizeEvent& evt) { - OnSize(evt); - save_user_data(UDT_SIZE | UDT_POSITION | UDT_COLS); - }); - - std::vector pos; - if (load_user_data(UDT_POSITION, pos)) - SetPosition(wxPoint(pos[0], pos[1])); - - Bind(wxEVT_MOVE, [this](wxMoveEvent& evt) { - save_user_data(UDT_SIZE | UDT_POSITION | UDT_COLS); - }); - - job_list->Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, [this](wxDataViewEvent&) { on_list_select(); }); - - btn_cancel->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { - int selected = job_list->GetSelectedRow(); - if (selected == wxNOT_FOUND) { return; } - - const JobState state = get_state(selected); - if (state < ST_ERROR) { - GUI::wxGetApp().printhost_job_queue().cancel(selected); - } - }); - - btn_error->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { - int selected = job_list->GetSelectedRow(); - if (selected == wxNOT_FOUND) { return; } - GUI::show_error(nullptr, job_list->GetTextValue(selected, COL_ERRORMSG)); - }); -} - -void PrintHostQueueDialog::append_job(const PrintHostJob &job) -{ - wxCHECK_RET(!job.empty(), "PrintHostQueueDialog: Attempt to append an empty job"); - - wxVector fields; - fields.push_back(wxVariant(wxString::Format("%d", job_list->GetItemCount() + 1))); - fields.push_back(wxVariant(0)); - fields.push_back(wxVariant(_L("Enqueued"))); - fields.push_back(wxVariant(job.printhost->get_host())); - boost::system::error_code ec; - boost::uintmax_t size_i = boost::filesystem::file_size(job.upload_data.source_path, ec); - std::stringstream stream; - if (ec) { - stream << "unknown"; - size_i = 0; - BOOST_LOG_TRIVIAL(error) << ec.message(); - } else - stream << std::fixed << std::setprecision(2) << ((float)size_i / 1024 / 1024) << "MB"; - fields.push_back(wxVariant(stream.str())); - fields.push_back(wxVariant(job.upload_data.upload_path.string())); - fields.push_back(wxVariant("")); - job_list->AppendItem(fields, static_cast(ST_NEW)); - // Both strings are UTF-8 encoded. - upload_names.emplace_back(job.printhost->get_host(), job.upload_data.upload_path.string()); - - wxGetApp().notification_manager()->push_upload_job_notification(job_list->GetItemCount(), (float)size_i / 1024 / 1024, job.upload_data.upload_path.string(), job.printhost->get_host()); -} - -void PrintHostQueueDialog::on_dpi_changed(const wxRect &suggested_rect) -{ - const int& em = em_unit(); - - msw_buttons_rescale(this, em, { wxID_DELETE, wxID_CANCEL, btn_error->GetId() }); - - SetMinSize(wxSize(HEIGHT * em, WIDTH * em)); - - Fit(); - Refresh(); - - save_user_data(UDT_SIZE | UDT_POSITION | UDT_COLS); -} - -void PrintHostQueueDialog::on_sys_color_changed() -{ -#ifdef _WIN32 - wxGetApp().UpdateDlgDarkUI(this); - wxGetApp().UpdateDVCDarkUI(job_list); -#endif -} - -PrintHostQueueDialog::JobState PrintHostQueueDialog::get_state(int idx) -{ - wxCHECK_MSG(idx >= 0 && idx < job_list->GetItemCount(), ST_ERROR, "Out of bounds access to job list"); - return static_cast(job_list->GetItemData(job_list->RowToItem(idx))); -} - -void PrintHostQueueDialog::set_state(int idx, JobState state) -{ - wxCHECK_RET(idx >= 0 && idx < job_list->GetItemCount(), "Out of bounds access to job list"); - job_list->SetItemData(job_list->RowToItem(idx), static_cast(state)); - - switch (state) { - case ST_NEW: job_list->SetValue(_L("Enqueued"), idx, COL_STATUS); break; - case ST_PROGRESS: job_list->SetValue(_L("Uploading"), idx, COL_STATUS); break; - case ST_ERROR: job_list->SetValue(_L("Error"), idx, COL_STATUS); break; - case ST_CANCELLING: job_list->SetValue(_L("Cancelling"), idx, COL_STATUS); break; - case ST_CANCELLED: job_list->SetValue(_L("Cancelled"), idx, COL_STATUS); break; - case ST_COMPLETED: job_list->SetValue(_L("Completed"), idx, COL_STATUS); break; - } - // This might be ambigous call, but user data needs to be saved time to time - save_user_data(UDT_SIZE | UDT_POSITION | UDT_COLS); -} - -void PrintHostQueueDialog::on_list_select() -{ - int selected = job_list->GetSelectedRow(); - if (selected != wxNOT_FOUND) { - const JobState state = get_state(selected); - btn_cancel->Enable(state < ST_ERROR); - btn_error->Enable(state == ST_ERROR); - Layout(); - } else { - btn_cancel->Disable(); - } -} - -void PrintHostQueueDialog::on_progress(Event &evt) -{ - wxCHECK_RET(evt.job_id < (size_t)job_list->GetItemCount(), "Out of bounds access to job list"); - - if (evt.progress < 100) { - set_state(evt.job_id, ST_PROGRESS); - job_list->SetValue(wxVariant(evt.progress), evt.job_id, COL_PROGRESS); - } else { - set_state(evt.job_id, ST_COMPLETED); - job_list->SetValue(wxVariant(100), evt.job_id, COL_PROGRESS); - } - - on_list_select(); - - if (evt.progress > 0) - { - wxVariant nm, hst; - job_list->GetValue(nm, evt.job_id, COL_FILENAME); - job_list->GetValue(hst, evt.job_id, COL_HOST); - wxGetApp().notification_manager()->set_upload_job_notification_percentage(evt.job_id + 1, boost::nowide::narrow(nm.GetString()), boost::nowide::narrow(hst.GetString()), evt.progress / 100.f); - } -} - -void PrintHostQueueDialog::on_error(Event &evt) -{ - wxCHECK_RET(evt.job_id < (size_t)job_list->GetItemCount(), "Out of bounds access to job list"); - - set_state(evt.job_id, ST_ERROR); - - auto errormsg = from_u8((boost::format("%1%\n%2%") % _utf8(L("Error uploading to print host:")) % std::string(evt.error.ToUTF8())).str()); - job_list->SetValue(wxVariant(0), evt.job_id, COL_PROGRESS); - job_list->SetValue(wxVariant(errormsg), evt.job_id, COL_ERRORMSG); // Stashes the error message into a hidden column for later - - on_list_select(); - - GUI::show_error(nullptr, errormsg); - - wxVariant nm, hst; - job_list->GetValue(nm, evt.job_id, COL_FILENAME); - job_list->GetValue(hst, evt.job_id, COL_HOST); - wxGetApp().notification_manager()->upload_job_notification_show_error(evt.job_id + 1, boost::nowide::narrow(nm.GetString()), boost::nowide::narrow(hst.GetString())); -} - -void PrintHostQueueDialog::on_cancel(Event &evt) -{ - wxCHECK_RET(evt.job_id < (size_t)job_list->GetItemCount(), "Out of bounds access to job list"); - - set_state(evt.job_id, ST_CANCELLED); - job_list->SetValue(wxVariant(0), evt.job_id, COL_PROGRESS); - - on_list_select(); - - wxVariant nm, hst; - job_list->GetValue(nm, evt.job_id, COL_FILENAME); - job_list->GetValue(hst, evt.job_id, COL_HOST); - wxGetApp().notification_manager()->upload_job_notification_show_canceled(evt.job_id + 1, boost::nowide::narrow(nm.GetString()), boost::nowide::narrow(hst.GetString())); -} - -void PrintHostQueueDialog::get_active_jobs(std::vector>& ret) -{ - int ic = job_list->GetItemCount(); - for (int i = 0; i < ic; i++) - { - auto item = job_list->RowToItem(i); - auto data = job_list->GetItemData(item); - JobState st = static_cast(data); - if(st == JobState::ST_NEW || st == JobState::ST_PROGRESS) - ret.emplace_back(upload_names[i]); - } - //job_list->data -} -void PrintHostQueueDialog::save_user_data(int udt) -{ - const auto em = GetTextExtent("m").x; - auto *app_config = wxGetApp().app_config; - if (udt & UserDataType::UDT_SIZE) { - - app_config->set("print_host_queue_dialog_height", std::to_string(this->GetSize().x / em)); - app_config->set("print_host_queue_dialog_width", std::to_string(this->GetSize().y / em)); - } - if (udt & UserDataType::UDT_POSITION) - { - app_config->set("print_host_queue_dialog_x", std::to_string(this->GetPosition().x)); - app_config->set("print_host_queue_dialog_y", std::to_string(this->GetPosition().y)); - } - if (udt & UserDataType::UDT_COLS) - { - for (size_t i = 0; i < job_list->GetColumnCount() - 1; i++) - { - app_config->set("print_host_queue_dialog_column_" + std::to_string(i), std::to_string(job_list->GetColumn(i)->GetWidth())); - } - } -} -bool PrintHostQueueDialog::load_user_data(int udt, std::vector& vector) -{ - auto* app_config = wxGetApp().app_config; - auto hasget = [app_config](const std::string& name, std::vector& vector)->bool { - if (app_config->has(name)) { - vector.push_back(std::stoi(app_config->get(name))); - return true; - } - return false; - }; - if (udt & UserDataType::UDT_SIZE) { - if (!hasget("print_host_queue_dialog_height",vector)) - return false; - if (!hasget("print_host_queue_dialog_width", vector)) - return false; - } - if (udt & UserDataType::UDT_POSITION) - { - if (!hasget("print_host_queue_dialog_x", vector)) - return false; - if (!hasget("print_host_queue_dialog_y", vector)) - return false; - } - if (udt & UserDataType::UDT_COLS) - { - for (size_t i = 0; i < 6; i++) - { - if (!hasget("print_host_queue_dialog_column_" + std::to_string(i), vector)) - return false; - } - } - return true; -} -}} diff --git a/src/slic3r/GUI/PrintHostDialogs.hpp b/src/slic3r/GUI/PrintHostDialogs.hpp deleted file mode 100644 index ff3eb60125..0000000000 --- a/src/slic3r/GUI/PrintHostDialogs.hpp +++ /dev/null @@ -1,130 +0,0 @@ -#ifndef slic3r_PrintHostSendDialog_hpp_ -#define slic3r_PrintHostSendDialog_hpp_ - -#include -#include -#include - -#include -#include -#include - -#include "GUI_Utils.hpp" -#include "MsgDialog.hpp" -#include "../Utils/PrintHost.hpp" - -class wxButton; -class wxTextCtrl; -class wxChoice; -class wxComboBox; -class wxDataViewListCtrl; - -namespace Slic3r { - -namespace GUI { - -class PrintHostSendDialog : public GUI::MsgDialog -{ -public: - PrintHostSendDialog(const boost::filesystem::path &path, PrintHostPostUploadActions post_actions, const wxArrayString& groups); - boost::filesystem::path filename() const; - PrintHostPostUploadAction post_action() const; - std::string group() const; - - virtual void EndModal(int ret) override; -private: - wxTextCtrl *txt_filename; - wxComboBox *combo_groups; - PrintHostPostUploadAction post_upload_action; - wxString m_valid_suffix; -}; - - -class PrintHostQueueDialog : public DPIDialog -{ -public: - class Event : public wxEvent - { - public: - size_t job_id; - int progress = 0; // in percent - wxString error; - - Event(wxEventType eventType, int winid, size_t job_id); - Event(wxEventType eventType, int winid, size_t job_id, int progress); - Event(wxEventType eventType, int winid, size_t job_id, wxString error); - - virtual wxEvent *Clone() const; - }; - - - PrintHostQueueDialog(wxWindow *parent); - - void append_job(const PrintHostJob &job); - void get_active_jobs(std::vector>& ret); - - virtual bool Show(bool show = true) override - { - if(!show) - save_user_data(UDT_SIZE | UDT_POSITION | UDT_COLS); - return DPIDialog::Show(show); - } -protected: - void on_dpi_changed(const wxRect &suggested_rect) override; - void on_sys_color_changed() override; - -private: - enum Column { - COL_ID, - COL_PROGRESS, - COL_STATUS, - COL_HOST, - COL_SIZE, - COL_FILENAME, - COL_ERRORMSG - }; - - enum JobState { - ST_NEW, - ST_PROGRESS, - ST_ERROR, - ST_CANCELLING, - ST_CANCELLED, - ST_COMPLETED, - }; - - enum { HEIGHT = 60, WIDTH = 30, SPACING = 5 }; - - enum UserDataType{ - UDT_SIZE = 1, - UDT_POSITION = 2, - UDT_COLS = 4 - }; - - wxButton *btn_cancel; - wxButton *btn_error; - wxDataViewListCtrl *job_list; - // Note: EventGuard prevents delivery of progress evts to a freed PrintHostQueueDialog - EventGuard on_progress_evt; - EventGuard on_error_evt; - EventGuard on_cancel_evt; - - JobState get_state(int idx); - void set_state(int idx, JobState); - void on_list_select(); - void on_progress(Event&); - void on_error(Event&); - void on_cancel(Event&); - // This vector keep adress and filename of uploads. It is used when checking for running uploads during exit. - std::vector> upload_names; - void save_user_data(int); - bool load_user_data(int, std::vector&); -}; - -wxDECLARE_EVENT(EVT_PRINTHOST_PROGRESS, PrintHostQueueDialog::Event); -wxDECLARE_EVENT(EVT_PRINTHOST_ERROR, PrintHostQueueDialog::Event); -wxDECLARE_EVENT(EVT_PRINTHOST_CANCEL, PrintHostQueueDialog::Event); - -}} - -#endif diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index ab0f644c66..925a7ae6a7 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -43,7 +43,6 @@ #include "MarkdownTip.hpp" #include "Search.hpp" -// #include "BonjourDialog.hpp" #ifdef WIN32 #include #endif // WIN32 @@ -2876,7 +2875,7 @@ void TabPrinter::build_fff() // build_preset_description_line(optgroup.get()); #endif - build_print_host_page(); + build_unregular_pages(true); } @@ -3039,256 +3038,6 @@ PageShp TabPrinter::build_kinematics_page() return page; } -void TabPrinter::update_printers() -{ - wxBusyCursor wait; - - std::unique_ptr host(PrintHost::get_print_host(m_config)); - - wxArrayString printers; - Field *rs = get_field("printhost_port"); - try { - if (! host->get_printers(printers)) - printers.clear(); - } catch (const HostNetworkError &err) { - printers.clear(); - show_error(this, _L("Connection to printers connected via the print host failed.") + "\n\n" + from_u8(err.what())); - } - Choice *choice = dynamic_cast(rs); - choice->set_values(printers); - printers.empty() ? rs->disable() : rs->enable(); -} - -void TabPrinter::update_host_type(bool printer_change) -{ - Field* ht = get_field("host_type"); - - wxArrayString types; - // Append localized enum_labels - assert(ht->m_opt.enum_labels.size() == ht->m_opt.enum_values.size()); - for (size_t i = 0; i < ht->m_opt.enum_labels.size(); i++) { - if (ht->m_opt.enum_values[i] == "prusalink") - continue; - types.Add(_(ht->m_opt.enum_labels[i])); - } - - Choice* choice = dynamic_cast(ht); - choice->set_values(types); - auto set_to_choice_and_config = [this, choice](PrintHostType type) { - choice->set_value(static_cast(type)); - m_config->set_key_value("host_type", new ConfigOptionEnum(type)); - }; - set_to_choice_and_config(htOctoPrint); -} - -void TabPrinter::update_printhost_buttons() -{ - std::unique_ptr host(PrintHost::get_print_host(m_config)); - m_printhost_test_btn->Enable(!m_config->opt_string("print_host").empty() && host->can_test()); - m_printhost_browse_btn->Enable(host->has_auto_discovery()); -} - - -PageShp TabPrinter::build_print_host_page() -{ - auto page = add_options_page(L("Connection"), "printer"); - #if 1 - auto optgroup = page->new_optgroup(L("Moonraker")); - Option option = optgroup->get_option("connection_moonraker_url"); - option.opt.full_width = true; - optgroup->append_single_option_line(option); - optgroup->append_single_option_line("connection_port"); - #else - auto optgroup = page->new_optgroup(L("Print Host upload")); - optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value) { - if (opt_key == "host_type" || opt_key == "printhost_authorization_type") - this->update(); - if (opt_key == "print_host") - this->update_printhost_buttons(); - }; - - optgroup->append_single_option_line("host_type"); - - auto create_sizer_with_btn = [](wxWindow* parent, ScalableButton** btn, const std::string& icon_name, const wxString& label) { - *btn = new ScalableButton(parent, wxID_ANY, icon_name, label, wxDefaultSize, wxDefaultPosition, wxBU_LEFT | wxBU_EXACTFIT); - (*btn)->SetFont(wxGetApp().normal_font()); - - auto sizer = new wxBoxSizer(wxHORIZONTAL); - sizer->Add(*btn); - return sizer; - }; - - auto printhost_browse = [=](wxWindow* parent) - { - auto sizer = create_sizer_with_btn(parent, &m_printhost_browse_btn, "browse", _L("Browse") + " " + dots); - // m_printhost_browse_btn->Bind(wxEVT_BUTTON, [=](wxCommandEvent& e) { - // BonjourDialog dialog(this, m_printer_technology); - // if (dialog.show_and_lookup()) { - // optgroup->set_value("print_host", dialog.get_selected(), true); - // optgroup->get_field("print_host")->field_changed(); - // } - // }); - - return sizer; - }; - - auto print_host_test = [=](wxWindow* parent) { - auto sizer = create_sizer_with_btn(parent, &m_printhost_test_btn, "test", _L("Test")); - - m_printhost_test_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent& e) { - std::unique_ptr host(PrintHost::get_print_host(m_config)); - if (!host) { - const wxString text = _L("Could not get a valid Printer Host reference"); - show_error(this, text); - return; - } - wxString msg; - bool result; - { - // Show a wait cursor during the connection test, as it is blocking UI. - wxBusyCursor wait; - result = host->test(msg); - } - if (result) - show_info(this, host->get_test_ok_msg(), _L("Success!")); - else - show_error(this, host->get_test_failed_msg(msg)); - }); - - return sizer; - }; - - auto print_host_printers = [this, create_sizer_with_btn](wxWindow* parent) { - //add_scaled_button(parent, &m_printhost_port_browse_btn, "browse", _(L("Refresh Printers")), wxBU_LEFT | wxBU_EXACTFIT); - auto sizer = create_sizer_with_btn(parent, &m_printhost_port_browse_btn, "browse", _(L("Refresh Printers"))); - ScalableButton* btn = m_printhost_port_browse_btn; - btn->SetFont(Slic3r::GUI::wxGetApp().normal_font()); - btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent e) { update_printers(); }); - return sizer; - }; - - // Set a wider width for a better alignment - Option option = optgroup->get_option("print_host"); - option.opt.width = Field::def_width_wider(); - Line host_line = optgroup->create_single_option_line(option); - host_line.append_widget(printhost_browse); - host_line.append_widget(print_host_test); - optgroup->append_line(host_line); - - optgroup->append_single_option_line("printhost_authorization_type"); - - option = optgroup->get_option("printhost_apikey"); - option.opt.width = Field::def_width_wider(); - optgroup->append_single_option_line(option); - - option = optgroup->get_option("printhost_port"); - option.opt.width = Field::def_width_wider(); - Line port_line = optgroup->create_single_option_line(option); - port_line.append_widget(print_host_printers); - optgroup->append_line(port_line); - - const auto ca_file_hint = _u8L("HTTPS CA file is optional. It is only needed if you use HTTPS with a self-signed certificate."); - - if (Http::ca_file_supported()) { - option = optgroup->get_option("printhost_cafile"); - option.opt.width = Field::def_width_wider(); - Line cafile_line = optgroup->create_single_option_line(option); - - auto printhost_cafile_browse = [=](wxWindow* parent) { - auto sizer = create_sizer_with_btn(parent, &m_printhost_cafile_browse_btn, "browse", _L("Browse") + " " + dots); - m_printhost_cafile_browse_btn->Bind(wxEVT_BUTTON, [this, optgroup](wxCommandEvent e) { - static const auto filemasks = _L("Certificate files (*.crt, *.pem)|*.crt;*.pem|All files|*.*"); - wxFileDialog openFileDialog(this, _L("Open CA certificate file"), "", "", filemasks, wxFD_OPEN | wxFD_FILE_MUST_EXIST); - if (openFileDialog.ShowModal() != wxID_CANCEL) { - optgroup->set_value("printhost_cafile", openFileDialog.GetPath(), true); - optgroup->get_field("printhost_cafile")->field_changed(); - } - }); - - return sizer; - }; - - cafile_line.append_widget(printhost_cafile_browse); - optgroup->append_line(cafile_line); - - Line cafile_hint{ "", "" }; - cafile_hint.full_width = 1; - cafile_hint.widget = [ca_file_hint](wxWindow* parent) { - auto txt = new wxStaticText(parent, wxID_ANY, ca_file_hint); - auto sizer = new wxBoxSizer(wxHORIZONTAL); - sizer->Add(txt); - return sizer; - }; - optgroup->append_line(cafile_hint); - } - else { - - Line line{ "", "" }; - line.full_width = 1; - - line.widget = [ca_file_hint](wxWindow* parent) { - std::string info = _u8L("HTTPS CA File") + ":\n\t" + - (boost::format(_u8L("On this system, %s uses HTTPS certificates from the system Certificate Store or Keychain.")) % SLIC3R_APP_NAME).str() + - "\n\t" + _u8L("To use a custom CA file, please import your CA file into Certificate Store / Keychain."); - - //auto txt = new wxStaticText(parent, wxID_ANY, from_u8((boost::format("%1%\n\n\t%2%") % info % ca_file_hint).str())); - auto txt = new wxStaticText(parent, wxID_ANY, from_u8((boost::format("%1%\n\t%2%") % info % ca_file_hint).str())); - txt->SetFont(wxGetApp().normal_font()); - auto sizer = new wxBoxSizer(wxHORIZONTAL); - sizer->Add(txt, 1, wxEXPAND); - return sizer; - }; - optgroup->append_line(line); - } - - for (const std::string& opt_key : std::vector{ "printhost_user", "printhost_password" }) { - option = optgroup->get_option(opt_key); - option.opt.width = Field::def_width_wider(); - optgroup->append_single_option_line(option); - } - -#ifdef WIN32 - option = optgroup->get_option("printhost_ssl_ignore_revoke"); - option.opt.width = Field::def_width_wider(); - optgroup->append_single_option_line(option); -#endif - - optgroup->activate(); - - Field* printhost_field = optgroup->get_field("print_host"); - if (printhost_field) - { - wxTextCtrl* temp = dynamic_cast(printhost_field->getWindow()); - if (temp) - temp->Bind(wxEVT_TEXT, ([printhost_field, temp](wxEvent& e) - { -#ifndef __WXGTK__ - e.Skip(); - temp->GetToolTip()->Enable(true); -#endif // __WXGTK__ - // Remove all leading and trailing spaces from the input - std::string trimed_str, str = trimed_str = temp->GetValue().ToStdString(); - boost::trim(trimed_str); - if (trimed_str != str) - temp->SetValue(trimed_str); - - TextCtrl* field = dynamic_cast(printhost_field); - if (field) - field->propagate_value(); - }), temp->GetId()); - } - - // Always fill in the "printhost_port" combo box from the config and select it. - { - Choice* choice = dynamic_cast(optgroup->get_field("printhost_port")); - // choice->set_values({ m_config->opt_string("printhost_port") }); - choice->set_selection(); - } - - // update(); - #endif - return page; -} /* Previous name build_extruder_pages(). * diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index b4879f0dcf..dfe8d1689c 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -547,14 +547,6 @@ private: std::vector m_pages_fff; std::vector m_pages_sla; - //SoftFever - ScalableButton* m_add_preset_btn {nullptr}; - ScalableButton* m_printhost_browse_btn {nullptr}; - ScalableButton* m_printhost_test_btn {nullptr}; - ScalableButton* m_printhost_cafile_browse_btn {nullptr}; - ScalableButton* m_printhost_port_browse_btn {nullptr}; - - wxBoxSizer* m_presets_sizer {nullptr}; public: ScalableButton* m_reset_to_filament_color = nullptr; @@ -593,13 +585,6 @@ public: //wxSizer* create_bed_shape_widget(wxWindow* parent); void cache_extruder_cnt(); bool apply_extruder_cnt_from_cache(); - - //SoftFever - void update_host_type(bool printer_change); - void update_printhost_buttons(); - void update_printers(); - PageShp build_print_host_page(); - }; class TabSLAMaterial : public Tab diff --git a/src/slic3r/Utils/AstroBox.cpp b/src/slic3r/Utils/AstroBox.cpp deleted file mode 100644 index 8781549a20..0000000000 --- a/src/slic3r/Utils/AstroBox.cpp +++ /dev/null @@ -1,173 +0,0 @@ -#include "AstroBox.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "libslic3r/PrintConfig.hpp" -#include "slic3r/GUI/I18N.hpp" -#include "slic3r/GUI/GUI.hpp" -#include "Http.hpp" - - -namespace fs = boost::filesystem; -namespace pt = boost::property_tree; - - -namespace Slic3r { - -AstroBox::AstroBox(DynamicPrintConfig *config) : - host(config->opt_string("print_host")), - apikey(config->opt_string("printhost_apikey")), - cafile(config->opt_string("printhost_cafile")) -{} - -const char* AstroBox::get_name() const { return "AstroBox"; } - -bool AstroBox::test(wxString &msg) const -{ - // Since the request is performed synchronously here, - // it is ok to refer to `msg` from within the closure - - const char *name = get_name(); - - bool res = true; - auto url = make_url("api/version"); - - BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Get version at: %2%") % name % url; - - auto http = Http::get(std::move(url)); - set_auth(http); - http.on_error([&](std::string body, std::string error, unsigned status) { - BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error getting version: %2%, HTTP %3%, body: `%4%`") % name % error % status % body; - res = false; - msg = format_error(body, error, status); - }) - .on_complete([&, this](std::string body, unsigned) { - BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: Got version: %2%") % name % body; - - try { - std::stringstream ss(body); - pt::ptree ptree; - pt::read_json(ss, ptree); - - if (! ptree.get_optional("api")) { - res = false; - return; - } - - const auto text = ptree.get_optional("text"); - res = validate_version_text(text); - if (! res) { - msg = GUI::from_u8((boost::format(_utf8(L("Mismatched type of print host: %s"))) % (text ? *text : "AstroBox")).str()); - } - } - catch (const std::exception &) { - res = false; - msg = "Could not parse server response"; - } - }) - .perform_sync(); - - return res; -} - -wxString AstroBox::get_test_ok_msg () const -{ - return _(L("Connection to AstroBox works correctly.")); -} - -wxString AstroBox::get_test_failed_msg (wxString &msg) const -{ - return GUI::from_u8((boost::format("%s: %s\n\n%s") - % _utf8(L("Could not connect to AstroBox")) - % std::string(msg.ToUTF8()) - % _utf8(L("Note: AstroBox version at least 1.1.0 is required."))).str()); -} - -bool AstroBox::upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const -{ - const char *name = get_name(); - - const auto upload_filename = upload_data.upload_path.filename(); - const auto upload_parent_path = upload_data.upload_path.parent_path(); - - wxString test_msg; - if (! test(test_msg)) { - error_fn(std::move(test_msg)); - return false; - } - - bool res = true; - - auto url = make_url("api/files/local"); - - BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Uploading file %2% at %3%, filename: %4%, path: %5%, print: %6%") - % name - % upload_data.source_path - % url - % upload_filename.string() - % upload_parent_path.string() - % (upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false"); - - auto http = Http::post(std::move(url)); - set_auth(http); - http.form_add("print", upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false") - .form_add("path", upload_parent_path.string()) // XXX: slashes on windows ??? - .form_add_file("file", upload_data.source_path.string(), upload_filename.string()) - .on_complete([&](std::string body, unsigned status) { - BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: File uploaded: HTTP %2%: %3%") % name % status % body; - }) - .on_error([&](std::string body, std::string error, unsigned status) { - BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error uploading file: %2%, HTTP %3%, body: `%4%`") % name % error % status % body; - error_fn(format_error(body, error, status)); - res = false; - }) - .on_progress([&](Http::Progress progress, bool &cancel) { - prorgess_fn(std::move(progress), cancel); - if (cancel) { - // Upload was canceled - BOOST_LOG_TRIVIAL(info) << "AstroBox: Upload canceled"; - res = false; - } - }) - .perform_sync(); - - return res; -} - -bool AstroBox::validate_version_text(const boost::optional &version_text) const -{ - return version_text ? boost::starts_with(*version_text, "AstroBox") : true; -} - -void AstroBox::set_auth(Http &http) const -{ - http.header("X-Api-Key", apikey); - - if (! cafile.empty()) { - http.ca_file(cafile); - } -} - -std::string AstroBox::make_url(const std::string &path) const -{ - if (host.find("http://") == 0 || host.find("https://") == 0) { - if (host.back() == '/') { - return (boost::format("%1%%2%") % host % path).str(); - } else { - return (boost::format("%1%/%2%") % host % path).str(); - } - } else { - return (boost::format("http://%1%/%2%") % host % path).str(); - } -} - -} diff --git a/src/slic3r/Utils/AstroBox.hpp b/src/slic3r/Utils/AstroBox.hpp deleted file mode 100644 index 15a8863a90..0000000000 --- a/src/slic3r/Utils/AstroBox.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef slic3r_AstroBox_hpp_ -#define slic3r_AstroBox_hpp_ - -#include -#include -#include - -#include "PrintHost.hpp" - -namespace Slic3r { - -class DynamicPrintConfig; -class Http; - -class AstroBox : public PrintHost -{ -public: - AstroBox(DynamicPrintConfig *config); - ~AstroBox() override = default; - - const char* get_name() const override; - - bool test(wxString &curl_msg) const override; - wxString get_test_ok_msg () const override; - wxString get_test_failed_msg (wxString &msg) const override; - bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const override; - bool has_auto_discovery() const override { return true; } - bool can_test() const override { return true; } - PrintHostPostUploadActions get_post_upload_actions() const override { return PrintHostPostUploadAction::StartPrint; } - std::string get_host() const override { return host; } - -protected: - bool validate_version_text(const boost::optional &version_text) const; - -private: - std::string host; - std::string apikey; - std::string cafile; - - void set_auth(Http &http) const; - std::string make_url(const std::string &path) const; -}; - -} - -#endif diff --git a/src/slic3r/Utils/Duet.cpp b/src/slic3r/Utils/Duet.cpp deleted file mode 100644 index 3293a3ff2b..0000000000 --- a/src/slic3r/Utils/Duet.cpp +++ /dev/null @@ -1,286 +0,0 @@ -#include "Duet.hpp" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "libslic3r/PrintConfig.hpp" -#include "slic3r/GUI/GUI.hpp" -#include "slic3r/GUI/I18N.hpp" -#include "slic3r/GUI/MsgDialog.hpp" -#include "Http.hpp" - -namespace fs = boost::filesystem; -namespace pt = boost::property_tree; - -namespace Slic3r { - -Duet::Duet(DynamicPrintConfig *config) : - host(config->opt_string("print_host")), - password(config->opt_string("printhost_apikey")) -{} - -const char* Duet::get_name() const { return "Duet"; } - -bool Duet::test(wxString &msg) const -{ - auto connectionType = connect(msg); - disconnect(connectionType); - - return connectionType != ConnectionType::error; -} - -wxString Duet::get_test_ok_msg () const -{ - return _(L("Connection to Duet works correctly.")); -} - -wxString Duet::get_test_failed_msg (wxString &msg) const -{ - return GUI::from_u8((boost::format("%s: %s") - % _utf8(L("Could not connect to Duet")) - % std::string(msg.ToUTF8())).str()); -} - -bool Duet::upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const -{ - wxString connect_msg; - auto connectionType = connect(connect_msg); - if (connectionType == ConnectionType::error) { - error_fn(std::move(connect_msg)); - return false; - } - - bool res = true; - bool dsf = (connectionType == ConnectionType::dsf); - - auto upload_cmd = get_upload_url(upload_data.upload_path.string(), connectionType); - BOOST_LOG_TRIVIAL(info) << boost::format("Duet: Uploading file %1%, filepath: %2%, post_action: %3%, command: %4%") - % upload_data.source_path - % upload_data.upload_path - % int(upload_data.post_action) - % upload_cmd; - - auto http = (dsf ? Http::put(std::move(upload_cmd)) : Http::post(std::move(upload_cmd))); - if (dsf) { - http.set_put_body(upload_data.source_path); - } else { - http.set_post_body(upload_data.source_path); - } - http.on_complete([&](std::string body, unsigned status) { - BOOST_LOG_TRIVIAL(debug) << boost::format("Duet: File uploaded: HTTP %1%: %2%") % status % body; - - int err_code = dsf ? (status == 201 ? 0 : 1) : get_err_code_from_body(body); - if (err_code != 0) { - BOOST_LOG_TRIVIAL(error) << boost::format("Duet: Request completed but error code was received: %1%") % err_code; - error_fn(format_error(body, L("Unknown error occured"), 0)); - res = false; - } else if (upload_data.post_action == PrintHostPostUploadAction::StartPrint) { - wxString errormsg; - res = start_print(errormsg, upload_data.upload_path.string(), connectionType, false); - if (! res) { - error_fn(std::move(errormsg)); - } - } else if (upload_data.post_action == PrintHostPostUploadAction::StartSimulation) { - wxString errormsg; - res = start_print(errormsg, upload_data.upload_path.string(), connectionType, true); - if (! res) { - error_fn(std::move(errormsg)); - } - } - }) - .on_error([&](std::string body, std::string error, unsigned status) { - BOOST_LOG_TRIVIAL(error) << boost::format("Duet: Error uploading file: %1%, HTTP %2%, body: `%3%`") % error % status % body; - error_fn(format_error(body, error, status)); - res = false; - }) - .on_progress([&](Http::Progress progress, bool &cancel) { - prorgess_fn(std::move(progress), cancel); - if (cancel) { - // Upload was canceled - BOOST_LOG_TRIVIAL(info) << "Duet: Upload canceled"; - res = false; - } - }) - .perform_sync(); - - disconnect(connectionType); - - return res; -} - -Duet::ConnectionType Duet::connect(wxString &msg) const -{ - auto res = ConnectionType::error; - auto url = get_connect_url(false); - - auto http = Http::get(std::move(url)); - http.on_error([&](std::string body, std::string error, unsigned status) { - auto dsfUrl = get_connect_url(true); - auto dsfHttp = Http::get(std::move(dsfUrl)); - dsfHttp.on_error([&](std::string body, std::string error, unsigned status) { - BOOST_LOG_TRIVIAL(error) << boost::format("Duet: Error connecting: %1%, HTTP %2%, body: `%3%`") % error % status % body; - msg = format_error(body, error, status); - }) - .on_complete([&](std::string body, unsigned) { - res = ConnectionType::dsf; - }) - .perform_sync(); - }) - .on_complete([&](std::string body, unsigned) { - BOOST_LOG_TRIVIAL(debug) << boost::format("Duet: Got: %1%") % body; - - int err_code = get_err_code_from_body(body); - switch (err_code) { - case 0: - res = ConnectionType::rrf; - break; - case 1: - msg = format_error(body, L("Wrong password"), 0); - break; - case 2: - msg = format_error(body, L("Could not get resources to create a new connection"), 0); - break; - default: - msg = format_error(body, L("Unknown error occured"), 0); - break; - } - - }) - .perform_sync(); - - return res; -} - -void Duet::disconnect(ConnectionType connectionType) const -{ - // we don't need to disconnect from DSF or if it failed anyway - if (connectionType != ConnectionType::rrf) { - return; - } - auto url = (boost::format("%1%rr_disconnect") - % get_base_url()).str(); - - auto http = Http::get(std::move(url)); - http.on_error([&](std::string body, std::string error, unsigned status) { - // we don't care about it, if disconnect is not working Duet will disconnect automatically after some time - BOOST_LOG_TRIVIAL(error) << boost::format("Duet: Error disconnecting: %1%, HTTP %2%, body: `%3%`") % error % status % body; - }) - .perform_sync(); -} - -std::string Duet::get_upload_url(const std::string &filename, ConnectionType connectionType) const -{ - assert(connectionType != ConnectionType::error); - - if (connectionType == ConnectionType::dsf) { - return (boost::format("%1%machine/file/gcodes/%2%") - % get_base_url() - % Http::url_encode(filename)).str(); - } else { - return (boost::format("%1%rr_upload?name=0:/gcodes/%2%&%3%") - % get_base_url() - % Http::url_encode(filename) - % timestamp_str()).str(); - } -} - -std::string Duet::get_connect_url(const bool dsfUrl) const -{ - if (dsfUrl) { - return (boost::format("%1%machine/status") - % get_base_url()).str(); - } else { - return (boost::format("%1%rr_connect?password=%2%&%3%") - % get_base_url() - % (password.empty() ? "reprap" : password) - % timestamp_str()).str(); - } -} - -std::string Duet::get_base_url() const -{ - if (host.find("http://") == 0 || host.find("https://") == 0) { - if (host.back() == '/') { - return host; - } else { - return (boost::format("%1%/") % host).str(); - } - } else { - return (boost::format("http://%1%/") % host).str(); - } -} - -std::string Duet::timestamp_str() const -{ - enum { BUFFER_SIZE = 32 }; - - auto t = std::time(nullptr); - auto tm = *std::localtime(&t); - - char buffer[BUFFER_SIZE]; - std::strftime(buffer, BUFFER_SIZE, "time=%Y-%m-%dT%H:%M:%S", &tm); - - return std::string(buffer); -} - -bool Duet::start_print(wxString &msg, const std::string &filename, ConnectionType connectionType, bool simulationMode) const -{ - assert(connectionType != ConnectionType::error); - - bool res = false; - bool dsf = (connectionType == ConnectionType::dsf); - - auto url = dsf - ? (boost::format("%1%machine/code") - % get_base_url()).str() - : (boost::format(simulationMode - ? "%1%rr_gcode?gcode=M37%%20P\"0:/gcodes/%2%\"" - : "%1%rr_gcode?gcode=M32%%20\"0:/gcodes/%2%\"") - % get_base_url() - % Http::url_encode(filename)).str(); - - auto http = (dsf ? Http::post(std::move(url)) : Http::get(std::move(url))); - if (dsf) { - http.set_post_body( - (boost::format(simulationMode - ? "M37 P\"0:/gcodes/%1%\"" - : "M32 \"0:/gcodes/%1%\"") - % filename).str() - ); - } - http.on_error([&](std::string body, std::string error, unsigned status) { - BOOST_LOG_TRIVIAL(error) << boost::format("Duet: Error starting print: %1%, HTTP %2%, body: `%3%`") % error % status % body; - msg = format_error(body, error, status); - }) - .on_complete([&](std::string body, unsigned) { - BOOST_LOG_TRIVIAL(debug) << boost::format("Duet: Got: %1%") % body; - res = true; - }) - .perform_sync(); - - return res; -} - -int Duet::get_err_code_from_body(const std::string &body) const -{ - pt::ptree root; - std::istringstream iss (body); // wrap returned json to istringstream - pt::read_json(iss, root); - - return root.get("err", 0); -} - -} diff --git a/src/slic3r/Utils/Duet.hpp b/src/slic3r/Utils/Duet.hpp deleted file mode 100644 index edca66ce0c..0000000000 --- a/src/slic3r/Utils/Duet.hpp +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef slic3r_Duet_hpp_ -#define slic3r_Duet_hpp_ - -#include -#include - -#include "PrintHost.hpp" - -namespace Slic3r { - -class DynamicPrintConfig; -class Http; - -class Duet : public PrintHost -{ -public: - explicit Duet(DynamicPrintConfig *config); - ~Duet() override = default; - - const char* get_name() const override; - - bool test(wxString &curl_msg) const override; - wxString get_test_ok_msg() const override; - wxString get_test_failed_msg(wxString &msg) const override; - bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const override; - bool has_auto_discovery() const override { return false; } - bool can_test() const override { return true; } - PrintHostPostUploadActions get_post_upload_actions() const override { return PrintHostPostUploadAction::StartPrint | PrintHostPostUploadAction::StartSimulation; } - std::string get_host() const override { return host; } - -private: - enum class ConnectionType { rrf, dsf, error }; - std::string host; - std::string password; - - std::string get_upload_url(const std::string &filename, ConnectionType connectionType) const; - std::string get_connect_url(const bool dsfUrl) const; - std::string get_base_url() const; - std::string timestamp_str() const; - ConnectionType connect(wxString &msg) const; - void disconnect(ConnectionType connectionType) const; - bool start_print(wxString &msg, const std::string &filename, ConnectionType connectionType, bool simulationMode) const; - int get_err_code_from_body(const std::string &body) const; -}; - -} - -#endif diff --git a/src/slic3r/Utils/FlashAir.cpp b/src/slic3r/Utils/FlashAir.cpp deleted file mode 100644 index 2337ac2904..0000000000 --- a/src/slic3r/Utils/FlashAir.cpp +++ /dev/null @@ -1,229 +0,0 @@ -#include "FlashAir.hpp" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "libslic3r/PrintConfig.hpp" -#include "slic3r/GUI/GUI.hpp" -#include "slic3r/GUI/I18N.hpp" -#include "slic3r/GUI/MsgDialog.hpp" -#include "Http.hpp" - -namespace fs = boost::filesystem; -namespace pt = boost::property_tree; - -namespace Slic3r { - -FlashAir::FlashAir(DynamicPrintConfig *config) : - host(config->opt_string("print_host")) -{} - -const char* FlashAir::get_name() const { return "FlashAir"; } - -bool FlashAir::test(wxString &msg) const -{ - // Since the request is performed synchronously here, - // it is ok to refer to `msg` from within the closure - - const char *name = get_name(); - - bool res = false; - auto url = make_url("command.cgi", "op", "118"); - - BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Get upload enabled at: %2%") % name % url; - - auto http = Http::get(std::move(url)); - http.on_error([&](std::string body, std::string error, unsigned status) { - BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error getting upload enabled: %2%, HTTP %3%, body: `%4%`") % name % error % status % body; - res = false; - msg = format_error(body, error, status); - }) - .on_complete([&](std::string body, unsigned) { - BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: Got upload enabled: %2%") % name % body; - - res = boost::starts_with(body, "1"); - if (! res) { - msg = _(L("Upload not enabled on FlashAir card.")); - } - }) - .perform_sync(); - - return res; -} - -wxString FlashAir::get_test_ok_msg () const -{ - return _(L("Connection to FlashAir works correctly and upload is enabled.")); -} - -wxString FlashAir::get_test_failed_msg (wxString &msg) const -{ - return GUI::from_u8((boost::format("%s: %s\n%s") - % _utf8(L("Could not connect to FlashAir")) - % std::string(msg.ToUTF8()) - % _utf8(L("Note: FlashAir with firmware 2.00.02 or newer and activated upload function is required."))).str()); -} - -bool FlashAir::upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const -{ - const char *name = get_name(); - - const auto upload_filename = upload_data.upload_path.filename(); - const auto upload_parent_path = upload_data.upload_path.parent_path(); - wxString test_msg; - if (! test(test_msg)) { - error_fn(std::move(test_msg)); - return false; - } - - bool res = false; - - std::string strDest = upload_parent_path.string(); - if (strDest.front()!='/') // Needs a leading / else root uploads fail. - { - strDest.insert(0,"/"); - } - - auto urlPrepare = make_url("upload.cgi", "WRITEPROTECT=ON&FTIME", timestamp_str()); - auto urlSetDir = make_url("upload.cgi","UPDIR",strDest); - auto urlUpload = make_url("upload.cgi"); - - BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Uploading file %2% at %3% / %4%, filename: %5%") - % name - % upload_data.source_path - % urlPrepare - % urlUpload - % upload_filename.string(); - - // set filetime for upload and make card writeprotect to prevent filesystem damage - auto httpPrepare = Http::get(std::move(urlPrepare)); - httpPrepare.on_error([&](std::string body, std::string error, unsigned status) { - BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error preparing upload: %2%, HTTP %3%, body: `%4%`") % name % error % status % body; - error_fn(format_error(body, error, status)); - res = false; - }) - .on_complete([&, this](std::string body, unsigned) { - BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: Got prepare result: %2%") % name % body; - res = boost::icontains(body, "SUCCESS"); - if (! res) { - BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Request completed but no SUCCESS message was received.") % name; - error_fn(format_error(body, L("Unknown error occured"), 0)); - } - }) - .perform_sync(); - - if(! res ) { - return res; - } - - // start file upload - auto httpDir = Http::get(std::move(urlSetDir)); - httpDir.on_error([&](std::string body, std::string error, unsigned status) { - BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error setting upload dir: %2%, HTTP %3%, body: `%4%`") % name % error % status % body; - error_fn(format_error(body, error, status)); - res = false; - }) - .on_complete([&, this](std::string body, unsigned) { - BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: Got dir select result: %2%") % name % body; - res = boost::icontains(body, "SUCCESS"); - if (! res) { - BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Request completed but no SUCCESS message was received.") % name; - error_fn(format_error(body, L("Unknown error occured"), 0)); - } - }) - .perform_sync(); - - if(! res ) { - return res; - } - - auto http = Http::post(std::move(urlUpload)); - http.form_add_file("file", upload_data.source_path.string(), upload_filename.string()) - .on_complete([&](std::string body, unsigned status) { - BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: File uploaded: HTTP %2%: %3%") % name % status % body; - res = boost::icontains(body, "SUCCESS"); - if (! res) { - BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Request completed but no SUCCESS message was received.") % name; - error_fn(format_error(body, L("Unknown error occured"), 0)); - } - }) - .on_error([&](std::string body, std::string error, unsigned status) { - BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error uploading file: %2%, HTTP %3%, body: `%4%`") % name % error % status % body; - error_fn(format_error(body, error, status)); - res = false; - }) - .on_progress([&](Http::Progress progress, bool &cancel) { - prorgess_fn(std::move(progress), cancel); - if (cancel) { - // Upload was canceled - BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Upload canceled") % name; - res = false; - } - }) - .perform_sync(); - - return res; -} - -std::string FlashAir::timestamp_str() const -{ - auto t = std::time(nullptr); - auto tm = *std::localtime(&t); - - unsigned long fattime = ((tm.tm_year - 80) << 25) | - ((tm.tm_mon + 1) << 21) | - (tm.tm_mday << 16) | - (tm.tm_hour << 11) | - (tm.tm_min << 5) | - (tm.tm_sec >> 1); - - return (boost::format("%1$#x") % fattime).str(); -} - -std::string FlashAir::make_url(const std::string &path) const -{ - if (host.find("http://") == 0 || host.find("https://") == 0) { - if (host.back() == '/') { - return (boost::format("%1%%2%") % host % path).str(); - } else { - return (boost::format("%1%/%2%") % host % path).str(); - } - } else { - if (host.back() == '/') { - return (boost::format("http://%1%%2%") % host % path).str(); - } else { - return (boost::format("http://%1%/%2%") % host % path).str(); - } - } -} - -std::string FlashAir::make_url(const std::string &path, const std::string &arg, const std::string &val) const -{ - if (host.find("http://") == 0 || host.find("https://") == 0) { - if (host.back() == '/') { - return (boost::format("%1%%2%?%3%=%4%") % host % path % arg % val).str(); - } else { - return (boost::format("%1%/%2%?%3%=%4%") % host % path % arg % val).str(); - } - } else { - if (host.back() == '/') { - return (boost::format("http://%1%%2%?%3%=%4%") % host % path % arg % val).str(); - } else { - return (boost::format("http://%1%/%2%?%3%=%4%") % host % path % arg % val).str(); - } - } -} - -} diff --git a/src/slic3r/Utils/FlashAir.hpp b/src/slic3r/Utils/FlashAir.hpp deleted file mode 100644 index 14e3f00156..0000000000 --- a/src/slic3r/Utils/FlashAir.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef slic3r_FlashAir_hpp_ -#define slic3r_FlashAir_hpp_ - -#include -#include - -#include "PrintHost.hpp" - - -namespace Slic3r { - -class DynamicPrintConfig; -class Http; - -class FlashAir : public PrintHost -{ -public: - FlashAir(DynamicPrintConfig *config); - ~FlashAir() override = default; - - const char* get_name() const override; - - bool test(wxString &curl_msg) const override; - wxString get_test_ok_msg() const override; - wxString get_test_failed_msg(wxString &msg) const override; - bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const override; - bool has_auto_discovery() const override { return false; } - bool can_test() const override { return true; } - PrintHostPostUploadActions get_post_upload_actions() const override { return {}; } - std::string get_host() const override { return host; } - -private: - std::string host; - - std::string timestamp_str() const; - std::string make_url(const std::string &path) const; - std::string make_url(const std::string &path, const std::string &arg, const std::string &val) const; -}; - -} - -#endif diff --git a/src/slic3r/Utils/MKS.cpp b/src/slic3r/Utils/MKS.cpp deleted file mode 100644 index 80a79537d5..0000000000 --- a/src/slic3r/Utils/MKS.cpp +++ /dev/null @@ -1,150 +0,0 @@ -#include "MKS.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "libslic3r/PrintConfig.hpp" -#include "slic3r/GUI/GUI.hpp" -#include "slic3r/GUI/I18N.hpp" -#include "slic3r/GUI/MsgDialog.hpp" -#include "Http.hpp" - -namespace fs = boost::filesystem; -namespace pt = boost::property_tree; - -namespace Slic3r { - -MKS::MKS(DynamicPrintConfig* config) : - m_host(config->opt_string("print_host")), m_console_port("8080") -{} - -const char* MKS::get_name() const { return "MKS"; } - -bool MKS::test(wxString& msg) const -{ - Utils::TCPConsole console(m_host, m_console_port); - - console.enqueue_cmd("M105"); - bool ret = console.run_queue(); - - if (!ret) - msg = wxString::FromUTF8(console.error_message().c_str()); - - return ret; -} - -wxString MKS::get_test_ok_msg() const -{ - return _(L("Connection to MKS works correctly.")); -} - -wxString MKS::get_test_failed_msg(wxString& msg) const -{ - return GUI::from_u8((boost::format("%s: %s") - % _utf8(L("Could not connect to MKS")) - % std::string(msg.ToUTF8())).str()); -} - -bool MKS::upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const -{ - bool res = true; - - auto upload_cmd = get_upload_url(upload_data.upload_path.string()); - BOOST_LOG_TRIVIAL(info) << boost::format("MKS: Uploading file %1%, filepath: %2%, print: %3%, command: %4%") - % upload_data.source_path - % upload_data.upload_path - % (upload_data.post_action == PrintHostPostUploadAction::StartPrint) - % upload_cmd; - - auto http = Http::post(std::move(upload_cmd)); - http.set_post_body(upload_data.source_path); - - http.on_complete([&](std::string body, unsigned status) { - BOOST_LOG_TRIVIAL(debug) << boost::format("MKS: File uploaded: HTTP %1%: %2%") % status % body; - - int err_code = get_err_code_from_body(body); - if (err_code != 0) { - BOOST_LOG_TRIVIAL(error) << boost::format("MKS: Request completed but error code was received: %1%") % err_code; - error_fn(format_error(body, L("Unknown error occured"), 0)); - res = false; - } - else if (upload_data.post_action == PrintHostPostUploadAction::StartPrint) { - wxString errormsg; - res = start_print(errormsg, upload_data.upload_path.string()); - if (!res) { - error_fn(std::move(errormsg)); - } - } - }) - .on_error([&](std::string body, std::string error, unsigned status) { - BOOST_LOG_TRIVIAL(error) << boost::format("MKS: Error uploading file: %1%, HTTP %2%, body: `%3%`") % error % status % body; - error_fn(format_error(body, error, status)); - res = false; - }) - .on_progress([&](Http::Progress progress, bool& cancel) { - prorgess_fn(std::move(progress), cancel); - if (cancel) { - // Upload was canceled - BOOST_LOG_TRIVIAL(info) << "MKS: Upload canceled"; - res = false; - } - }).perform_sync(); - - - return res; -} - -std::string MKS::get_upload_url(const std::string& filename) const -{ - return (boost::format("http://%1%/upload?X-Filename=%2%") - % m_host - % Http::url_encode(filename)).str(); -} - -bool MKS::start_print(wxString& msg, const std::string& filename) const -{ - // For some reason printer firmware does not want to respond on gcode commands immediately after file upload. - // So we just introduce artificial delay to workaround it. - // TODO: Inspect reasons - std::this_thread::sleep_for(std::chrono::milliseconds(1500)); - - Utils::TCPConsole console(m_host, m_console_port); - - console.enqueue_cmd(std::string("M23 ") + filename); - console.enqueue_cmd("M24"); - - bool ret = console.run_queue(); - - if (!ret) - msg = wxString::FromUTF8(console.error_message().c_str()); - - return ret; -} - -int MKS::get_err_code_from_body(const std::string& body) const -{ - pt::ptree root; - std::istringstream iss(body); // wrap returned json to istringstream - pt::read_json(iss, root); - - return root.get("err", 0); -} - -} // Slic3r diff --git a/src/slic3r/Utils/MKS.hpp b/src/slic3r/Utils/MKS.hpp deleted file mode 100644 index 22455436ae..0000000000 --- a/src/slic3r/Utils/MKS.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef slic3r_MKS_hpp_ -#define slic3r_MKS_hpp_ - -#include -#include - -#include "PrintHost.hpp" -#include "TCPConsole.hpp" - -namespace Slic3r { -class DynamicPrintConfig; -class Http; - -class MKS : public PrintHost -{ -public: - explicit MKS(DynamicPrintConfig* config); - ~MKS() override = default; - - const char* get_name() const override; - - bool test(wxString& curl_msg) const override; - wxString get_test_ok_msg() const override; - wxString get_test_failed_msg(wxString& msg) const override; - bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const override; - bool has_auto_discovery() const override { return false; } - bool can_test() const override { return true; } - PrintHostPostUploadActions get_post_upload_actions() const override { return PrintHostPostUploadAction::StartPrint; } - std::string get_host() const override { return m_host; } - -private: - std::string m_host; - std::string m_console_port; - - std::string get_upload_url(const std::string& filename) const; - bool start_print(wxString& msg, const std::string& filename) const; - int get_err_code_from_body(const std::string& body) const; -}; - -} - -#endif diff --git a/src/slic3r/Utils/OctoPrint.cpp b/src/slic3r/Utils/OctoPrint.cpp deleted file mode 100644 index 250b16b4ac..0000000000 --- a/src/slic3r/Utils/OctoPrint.cpp +++ /dev/null @@ -1,367 +0,0 @@ -#include "OctoPrint.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include "slic3r/GUI/GUI.hpp" -#include "slic3r/GUI/I18N.hpp" -#include "slic3r/GUI/GUI.hpp" -#include "Http.hpp" -#include "libslic3r/AppConfig.hpp" - - -namespace fs = boost::filesystem; -namespace pt = boost::property_tree; - - -namespace Slic3r { - -#ifdef WIN32 -// Workaround for Windows 10/11 mDNS resolve issue, where two mDNS resolves in succession fail. -namespace { -std::string substitute_host(const std::string& orig_addr, std::string sub_addr) -{ - // put ipv6 into [] brackets - if (sub_addr.find(':') != std::string::npos && sub_addr.at(0) != '[') - sub_addr = "[" + sub_addr + "]"; - -#if 0 - //URI = scheme ":"["//"[userinfo "@"] host [":" port]] path["?" query]["#" fragment] - std::string final_addr = orig_addr; - // http - size_t double_dash = orig_addr.find("//"); - size_t host_start = (double_dash == std::string::npos ? 0 : double_dash + 2); - // userinfo - size_t at = orig_addr.find("@"); - host_start = (at != std::string::npos && at > host_start ? at + 1 : host_start); - // end of host, could be port(:), subpath(/) (could be query(?) or fragment(#)?) - // or it will be ']' if address is ipv6 ) - size_t potencial_host_end = orig_addr.find_first_of(":/", host_start); - // if there are more ':' it must be ipv6 - if (potencial_host_end != std::string::npos && orig_addr[potencial_host_end] == ':' && orig_addr.rfind(':') != potencial_host_end) { - size_t ipv6_end = orig_addr.find(']', host_start); - // DK: Uncomment and replace orig_addr.length() if we want to allow subpath after ipv6 without [] parentheses. - potencial_host_end = (ipv6_end != std::string::npos ? ipv6_end + 1 : orig_addr.length()); //orig_addr.find('/', host_start)); - } - size_t host_end = (potencial_host_end != std::string::npos ? potencial_host_end : orig_addr.length()); - // now host_start and host_end should mark where to put resolved addr - // check host_start. if its nonsense, lets just use original addr (or resolved addr?) - if (host_start >= orig_addr.length()) { - return final_addr; - } - final_addr.replace(host_start, host_end - host_start, sub_addr); - return final_addr; -#else - // Using the new CURL API for handling URL. https://everything.curl.dev/libcurl/url - // If anything fails, return the input unchanged. - std::string out = orig_addr; - CURLU *hurl = curl_url(); - if (hurl) { - // Parse the input URL. - CURLUcode rc = curl_url_set(hurl, CURLUPART_URL, orig_addr.c_str(), 0); - if (rc == CURLUE_OK) { - // Replace the address. - rc = curl_url_set(hurl, CURLUPART_HOST, sub_addr.c_str(), 0); - if (rc == CURLUE_OK) { - // Extract a string fromt the CURL URL handle. - char *url; - rc = curl_url_get(hurl, CURLUPART_URL, &url, 0); - if (rc == CURLUE_OK) { - out = url; - curl_free(url); - } else - BOOST_LOG_TRIVIAL(error) << "OctoPrint substitute_host: failed to extract the URL after substitution"; - } else - BOOST_LOG_TRIVIAL(error) << "OctoPrint substitute_host: failed to substitute host " << sub_addr << " in URL " << orig_addr; - } else - BOOST_LOG_TRIVIAL(error) << "OctoPrint substitute_host: failed to parse URL " << orig_addr; - curl_url_cleanup(hurl); - } else - BOOST_LOG_TRIVIAL(error) << "OctoPrint substitute_host: failed to allocate curl_url"; - return out; -#endif -} -} //namespace -#endif // WIN32 - -OctoPrint::OctoPrint(DynamicPrintConfig *config) : - m_host(config->opt_string("print_host")), - m_apikey(config->opt_string("printhost_apikey")), - m_cafile(config->opt_string("printhost_cafile")), - m_ssl_revoke_best_effort(config->opt_bool("printhost_ssl_ignore_revoke")) -{} - -const char* OctoPrint::get_name() const { return "OctoPrint"; } - -bool OctoPrint::test(wxString &msg) const -{ - // Since the request is performed synchronously here, - // it is ok to refer to `msg` from within the closure - - const char *name = get_name(); - - bool res = true; - auto url = make_url("api/version"); - - BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Get version at: %2%") % name % url; - - auto http = Http::get(std::move(url)); - set_auth(http); - http.on_error([&](std::string body, std::string error, unsigned status) { - BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error getting version: %2%, HTTP %3%, body: `%4%`") % name % error % status % body; - res = false; - msg = format_error(body, error, status); - }) - .on_complete([&, this](std::string body, unsigned) { - BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: Got version: %2%") % name % body; - - try { - std::stringstream ss(body); - pt::ptree ptree; - pt::read_json(ss, ptree); - - if (! ptree.get_optional("api")) { - res = false; - return; - } - - const auto text = ptree.get_optional("text"); - res = validate_version_text(text); - if (! res) { - msg = GUI::from_u8((boost::format(_utf8(L("Mismatched type of print host: %s"))) % (text ? *text : "OctoPrint")).str()); - } - } - catch (const std::exception &) { - res = false; - msg = "Could not parse server response"; - } - }) -#ifdef WIN32 - .ssl_revoke_best_effort(m_ssl_revoke_best_effort) - .on_ip_resolve([&](std::string address) { - // Workaround for Windows 10/11 mDNS resolve issue, where two mDNS resolves in succession fail. - // Remember resolved address to be reused at successive REST API call. - msg = GUI::from_u8(address); - }) -#endif // WIN32 - .perform_sync(); - - return res; -} - -wxString OctoPrint::get_test_ok_msg () const -{ - return _(L("Connection to OctoPrint works correctly.")); -} - -wxString OctoPrint::get_test_failed_msg (wxString &msg) const -{ - return GUI::from_u8((boost::format("%s: %s\n\n%s") - % _utf8(L("Could not connect to OctoPrint")) - % std::string(msg.ToUTF8()) - % _utf8(L("Note: OctoPrint version at least 1.1.0 is required."))).str()); -} - -bool OctoPrint::upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const -{ - const char *name = get_name(); - - const auto upload_filename = upload_data.upload_path.filename(); - const auto upload_parent_path = upload_data.upload_path.parent_path(); - - // If test fails, test_msg_or_host_ip contains the error message. - // Otherwise on Windows it contains the resolved IP address of the host. - wxString test_msg_or_host_ip; - if (! test(test_msg_or_host_ip)) { - error_fn(std::move(test_msg_or_host_ip)); - return false; - } - - std::string url; - bool res = true; - -#ifdef WIN32 - // Workaround for Windows 10/11 mDNS resolve issue, where two mDNS resolves in succession fail. - if (m_host.find("https://") == 0 || test_msg_or_host_ip.empty() || GUI::get_app_config()->get("allow_ip_resolve") != "1") -#endif // _WIN32 - { - // If https is entered we assume signed ceritificate is being used - // IP resolving will not happen - it could resolve into address not being specified in cert - url = make_url("api/files/local"); - } -#ifdef WIN32 - else { - // Workaround for Windows 10/11 mDNS resolve issue, where two mDNS resolves in succession fail. - // Curl uses easy_getinfo to get ip address of last successful transaction. - // If it got the address use it instead of the stored in "host" variable. - // This new address returns in "test_msg_or_host_ip" variable. - // Solves troubles of uploades failing with name address. - // in original address (m_host) replace host for resolved ip - url = substitute_host(make_url("api/files/local"), GUI::into_u8(test_msg_or_host_ip)); - BOOST_LOG_TRIVIAL(info) << "Upload address after ip resolve: " << url; - } -#endif // _WIN32 - - BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Uploading file %2% at %3%, filename: %4%, path: %5%, print: %6%") - % name - % upload_data.source_path - % url - % upload_filename.string() - % upload_parent_path.string() - % (upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false"); - - auto http = Http::post(std::move(url)); - set_auth(http); - http.form_add("print", upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false") - .form_add("path", upload_parent_path.string()) // XXX: slashes on windows ??? - .form_add_file("file", upload_data.source_path.string(), upload_filename.string()) - .on_complete([&](std::string body, unsigned status) { - BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: File uploaded: HTTP %2%: %3%") % name % status % body; - }) - .on_error([&](std::string body, std::string error, unsigned status) { - BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error uploading file: %2%, HTTP %3%, body: `%4%`") % name % error % status % body; - error_fn(format_error(body, error, status)); - res = false; - }) - .on_progress([&](Http::Progress progress, bool &cancel) { - prorgess_fn(std::move(progress), cancel); - if (cancel) { - // Upload was canceled - BOOST_LOG_TRIVIAL(info) << "Octoprint: Upload canceled"; - res = false; - } - }) -#ifdef WIN32 - .ssl_revoke_best_effort(m_ssl_revoke_best_effort) -#endif - .perform_sync(); - - return res; -} - -bool OctoPrint::validate_version_text(const boost::optional &version_text) const -{ - return version_text ? boost::starts_with(*version_text, "OctoPrint") : true; -} - -void OctoPrint::set_auth(Http &http) const -{ - http.header("X-Api-Key", m_apikey); - - if (!m_cafile.empty()) { - http.ca_file(m_cafile); - } -} - -std::string OctoPrint::make_url(const std::string &path) const -{ - if (m_host.find("http://") == 0 || m_host.find("https://") == 0) { - if (m_host.back() == '/') { - return (boost::format("%1%%2%") % m_host % path).str(); - } else { - return (boost::format("%1%/%2%") % m_host % path).str(); - } - } else { - return (boost::format("http://%1%/%2%") % m_host % path).str(); - } -} - -SL1Host::SL1Host(DynamicPrintConfig *config) : - OctoPrint(config), - m_authorization_type(dynamic_cast*>(config->option("printhost_authorization_type"))->value), - m_username(config->opt_string("printhost_user")), - m_password(config->opt_string("printhost_password")) -{ -} - -// SL1Host -const char* SL1Host::get_name() const { return "SL1Host"; } - -wxString SL1Host::get_test_ok_msg () const -{ - return _(L("Connection to Prusa SL1 / SL1S works correctly.")); -} - -wxString SL1Host::get_test_failed_msg (wxString &msg) const -{ - return GUI::from_u8((boost::format("%s: %s") - % _utf8(L("Could not connect to Prusa SLA")) - % std::string(msg.ToUTF8())).str()); -} - -bool SL1Host::validate_version_text(const boost::optional &version_text) const -{ - return version_text ? boost::starts_with(*version_text, "Prusa SLA") : false; -} - -void SL1Host::set_auth(Http &http) const -{ - switch (m_authorization_type) { - case atKeyPassword: - http.header("X-Api-Key", get_apikey()); - break; - case atUserPassword: - http.auth_digest(m_username, m_password); - break; - } - - if (! get_cafile().empty()) { - http.ca_file(get_cafile()); - } -} - -// PrusaLink -PrusaLink::PrusaLink(DynamicPrintConfig* config) : - OctoPrint(config), - m_authorization_type(dynamic_cast*>(config->option("printhost_authorization_type"))->value), - m_username(config->opt_string("printhost_user")), - m_password(config->opt_string("printhost_password")) -{ -} - -const char* PrusaLink::get_name() const { return "PrusaLink"; } - -wxString PrusaLink::get_test_ok_msg() const -{ - return _(L("Connection to PrusaLink works correctly.")); -} - -wxString PrusaLink::get_test_failed_msg(wxString& msg) const -{ - return GUI::from_u8((boost::format("%s: %s") - % _utf8(L("Could not connect to PrusaLink")) - % std::string(msg.ToUTF8())).str()); -} - -bool PrusaLink::validate_version_text(const boost::optional& version_text) const -{ - return version_text ? (boost::starts_with(*version_text, "PrusaLink") || boost::starts_with(*version_text, "OctoPrint")) : false; -} - -void PrusaLink::set_auth(Http& http) const -{ - switch (m_authorization_type) { - case atKeyPassword: - http.header("X-Api-Key", get_apikey()); - break; - case atUserPassword: - http.auth_digest(m_username, m_password); - break; - } - - if (!get_cafile().empty()) { - http.ca_file(get_cafile()); - } -} - -} diff --git a/src/slic3r/Utils/OctoPrint.hpp b/src/slic3r/Utils/OctoPrint.hpp deleted file mode 100644 index 262efe9ff5..0000000000 --- a/src/slic3r/Utils/OctoPrint.hpp +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef slic3r_OctoPrint_hpp_ -#define slic3r_OctoPrint_hpp_ - -#include -#include -#include - -#include "PrintHost.hpp" -#include "libslic3r/PrintConfig.hpp" - - -namespace Slic3r { - -class DynamicPrintConfig; -class Http; - -class OctoPrint : public PrintHost -{ -public: - OctoPrint(DynamicPrintConfig *config); - ~OctoPrint() override = default; - - const char* get_name() const override; - - bool test(wxString &curl_msg) const override; - wxString get_test_ok_msg () const override; - wxString get_test_failed_msg (wxString &msg) const override; - bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const override; - bool has_auto_discovery() const override { return true; } - bool can_test() const override { return true; } - PrintHostPostUploadActions get_post_upload_actions() const override { return PrintHostPostUploadAction::StartPrint; } - std::string get_host() const override { return m_host; } - const std::string& get_apikey() const { return m_apikey; } - const std::string& get_cafile() const { return m_cafile; } - -protected: - virtual bool validate_version_text(const boost::optional &version_text) const; - -private: - std::string m_host; - std::string m_apikey; - std::string m_cafile; - bool m_ssl_revoke_best_effort; - - virtual void set_auth(Http &http) const; - std::string make_url(const std::string &path) const; -}; - -class SL1Host: public OctoPrint -{ -public: - SL1Host(DynamicPrintConfig *config); - ~SL1Host() override = default; - - const char* get_name() const override; - - wxString get_test_ok_msg() const override; - wxString get_test_failed_msg(wxString &msg) const override; - PrintHostPostUploadActions get_post_upload_actions() const override { return {}; } - -protected: - bool validate_version_text(const boost::optional &version_text) const override; - -private: - void set_auth(Http &http) const override; - - // Host authorization type. - AuthorizationType m_authorization_type; - // username and password for HTTP Digest Authentization (RFC RFC2617) - std::string m_username; - std::string m_password; -}; - -class PrusaLink : public OctoPrint -{ -public: - PrusaLink(DynamicPrintConfig* config); - ~PrusaLink() override = default; - - const char* get_name() const override; - - wxString get_test_ok_msg() const override; - wxString get_test_failed_msg(wxString& msg) const override; - PrintHostPostUploadActions get_post_upload_actions() const override { return PrintHostPostUploadAction::StartPrint; } - -protected: - bool validate_version_text(const boost::optional& version_text) const override; - -private: - void set_auth(Http& http) const override; - - // Host authorization type. - AuthorizationType m_authorization_type; - // username and password for HTTP Digest Authentization (RFC RFC2617) - std::string m_username; - std::string m_password; -}; - -} - -#endif diff --git a/src/slic3r/Utils/PrintHost.cpp b/src/slic3r/Utils/PrintHost.cpp deleted file mode 100644 index 86f6101b6d..0000000000 --- a/src/slic3r/Utils/PrintHost.cpp +++ /dev/null @@ -1,281 +0,0 @@ -#include "PrintHost.hpp" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "libslic3r/PrintConfig.hpp" -#include "libslic3r/Channel.hpp" -#include "OctoPrint.hpp" -#include "Duet.hpp" -#include "FlashAir.hpp" -#include "AstroBox.hpp" -#include "Repetier.hpp" -#include "MKS.hpp" -#include "../GUI/PrintHostDialogs.hpp" - -namespace fs = boost::filesystem; -using boost::optional; -using Slic3r::GUI::PrintHostQueueDialog; - -namespace Slic3r { - - -PrintHost::~PrintHost() {} - -PrintHost* PrintHost::get_print_host(DynamicPrintConfig *config) -{ - PrinterTechnology tech = ptFFF; - - { - const auto opt = config->option>("printer_technology"); - if (opt != nullptr) { - tech = opt->value; - } - } - - if (tech == ptFFF) { - const auto opt = config->option>("host_type"); - const auto host_type = opt != nullptr ? opt->value : htOctoPrint; - - switch (host_type) { - case htOctoPrint: return new OctoPrint(config); - case htDuet: return new Duet(config); - case htFlashAir: return new FlashAir(config); - case htAstroBox: return new AstroBox(config); - case htRepetier: return new Repetier(config); - case htPrusaLink: return new PrusaLink(config); - case htMKS: return new MKS(config); - default: return nullptr; - } - } else { - return new SL1Host(config); - } -} - -wxString PrintHost::format_error(const std::string &body, const std::string &error, unsigned status) const -{ - if (status != 0) { - auto wxbody = wxString::FromUTF8(body.data()); - return wxString::Format("HTTP %u: %s", status, wxbody); - } else { - return wxString::FromUTF8(error.data()); - } -} - - -struct PrintHostJobQueue::priv -{ - // XXX: comment on how bg thread works - - PrintHostJobQueue *q; - - Channel channel_jobs; - Channel channel_cancels; - size_t job_id = 0; - int prev_progress = -1; - fs::path source_to_remove; - - std::thread bg_thread; - bool bg_exit = false; - - PrintHostQueueDialog *queue_dialog; - - priv(PrintHostJobQueue *q) : q(q) {} - - void emit_progress(int progress); - void emit_error(wxString error); - void emit_cancel(size_t id); - void start_bg_thread(); - void stop_bg_thread(); - void bg_thread_main(); - void progress_fn(Http::Progress progress, bool &cancel); - void remove_source(const fs::path &path); - void remove_source(); - void perform_job(PrintHostJob the_job); -}; - -PrintHostJobQueue::PrintHostJobQueue(PrintHostQueueDialog *queue_dialog) - : p(new priv(this)) -{ - p->queue_dialog = queue_dialog; -} - -PrintHostJobQueue::~PrintHostJobQueue() -{ - if (p) { p->stop_bg_thread(); } -} - -void PrintHostJobQueue::priv::emit_progress(int progress) -{ - auto evt = new PrintHostQueueDialog::Event(GUI::EVT_PRINTHOST_PROGRESS, queue_dialog->GetId(), job_id, progress); - wxQueueEvent(queue_dialog, evt); -} - -void PrintHostJobQueue::priv::emit_error(wxString error) -{ - auto evt = new PrintHostQueueDialog::Event(GUI::EVT_PRINTHOST_ERROR, queue_dialog->GetId(), job_id, std::move(error)); - wxQueueEvent(queue_dialog, evt); -} - -void PrintHostJobQueue::priv::emit_cancel(size_t id) -{ - auto evt = new PrintHostQueueDialog::Event(GUI::EVT_PRINTHOST_CANCEL, queue_dialog->GetId(), id); - wxQueueEvent(queue_dialog, evt); -} - -void PrintHostJobQueue::priv::start_bg_thread() -{ - if (bg_thread.joinable()) { return; } - - std::shared_ptr p2 = q->p; - bg_thread = std::thread([p2]() { - p2->bg_thread_main(); - }); -} - -void PrintHostJobQueue::priv::stop_bg_thread() -{ - if (bg_thread.joinable()) { - bg_exit = true; - channel_jobs.push(PrintHostJob()); // Push an empty job to wake up bg_thread in case it's sleeping - bg_thread.detach(); // Let the background thread go, it should exit on its own - } -} - -void PrintHostJobQueue::priv::bg_thread_main() -{ - // bg thread entry point - - try { - // Pick up jobs from the job channel: - while (! bg_exit) { - auto job = channel_jobs.pop(); // Sleeps in a cond var if there are no jobs - if (job.empty()) { - // This happens when the thread is being stopped - break; - } - - source_to_remove = job.upload_data.source_path; - - BOOST_LOG_TRIVIAL(debug) << boost::format("PrintHostJobQueue/bg_thread: Received job: [%1%]: `%2%` -> `%3%`, cancelled: %4%") - % job_id - % job.upload_data.upload_path - % job.printhost->get_host() - % job.cancelled; - - if (! job.cancelled) { - perform_job(std::move(job)); - } - - remove_source(); - job_id++; - } - } catch (const std::exception &e) { - emit_error(e.what()); - } - - // Cleanup leftover files, if any - remove_source(); - auto jobs = channel_jobs.lock_rw(); - for (const PrintHostJob &job : *jobs) { - remove_source(job.upload_data.source_path); - } -} - -void PrintHostJobQueue::priv::progress_fn(Http::Progress progress, bool &cancel) -{ - if (cancel) { - // When cancel is true from the start, Http indicates request has been cancelled - emit_cancel(job_id); - return; - } - - if (bg_exit) { - cancel = true; - return; - } - - if (channel_cancels.size_hint() > 0) { - // Lock both queues - auto cancels = channel_cancels.lock_rw(); - auto jobs = channel_jobs.lock_rw(); - - for (size_t cancel_id : *cancels) { - if (cancel_id == job_id) { - cancel = true; - } else if (cancel_id > job_id) { - const size_t idx = cancel_id - job_id - 1; - if (idx < jobs->size()) { - jobs->at(idx).cancelled = true; - BOOST_LOG_TRIVIAL(debug) << boost::format("PrintHostJobQueue: Job id %1% cancelled") % cancel_id; - emit_cancel(cancel_id); - } - } - } - - cancels->clear(); - } - - if (! cancel) { - int gui_progress = progress.ultotal > 0 ? 100*progress.ulnow / progress.ultotal : 0; - if (gui_progress != prev_progress) { - emit_progress(gui_progress); - prev_progress = gui_progress; - } - } -} - -void PrintHostJobQueue::priv::remove_source(const fs::path &path) -{ - if (! path.empty()) { - boost::system::error_code ec; - fs::remove(path, ec); - if (ec) { - BOOST_LOG_TRIVIAL(error) << boost::format("PrintHostJobQueue: Error removing file `%1%`: %2%") % path % ec; - } - } -} - -void PrintHostJobQueue::priv::remove_source() -{ - remove_source(source_to_remove); - source_to_remove.clear(); -} - -void PrintHostJobQueue::priv::perform_job(PrintHostJob the_job) -{ - emit_progress(0); // Indicate the upload is starting - - bool success = the_job.printhost->upload(std::move(the_job.upload_data), - [this](Http::Progress progress, bool &cancel) { this->progress_fn(std::move(progress), cancel); }, - [this](wxString error) { - emit_error(std::move(error)); - } - ); - - if (success) { - emit_progress(100); - } -} - -void PrintHostJobQueue::enqueue(PrintHostJob job) -{ - p->start_bg_thread(); - p->queue_dialog->append_job(job); - p->channel_jobs.push(std::move(job)); -} - -void PrintHostJobQueue::cancel(size_t id) -{ - p->channel_cancels.push(id); -} - -} diff --git a/src/slic3r/Utils/PrintHost.hpp b/src/slic3r/Utils/PrintHost.hpp deleted file mode 100644 index dd22e60b7d..0000000000 --- a/src/slic3r/Utils/PrintHost.hpp +++ /dev/null @@ -1,129 +0,0 @@ -#ifndef slic3r_PrintHost_hpp_ -#define slic3r_PrintHost_hpp_ - -#include -#include -#include -#include -#include - -#include - -#include -#include "Http.hpp" - -class wxArrayString; - -namespace Slic3r { - -class DynamicPrintConfig; - -enum class PrintHostPostUploadAction { - None, - StartPrint, - StartSimulation -}; -using PrintHostPostUploadActions = enum_bitmask; -ENABLE_ENUM_BITMASK_OPERATORS(PrintHostPostUploadAction); - -struct PrintHostUpload -{ - boost::filesystem::path source_path; - boost::filesystem::path upload_path; - - std::string group; - - PrintHostPostUploadAction post_action { PrintHostPostUploadAction::None }; -}; - -class PrintHost -{ -public: - virtual ~PrintHost(); - - typedef Http::ProgressFn ProgressFn; - typedef std::function ErrorFn; - - virtual const char* get_name() const = 0; - - virtual bool test(wxString &curl_msg) const = 0; - virtual wxString get_test_ok_msg () const = 0; - virtual wxString get_test_failed_msg (wxString &msg) const = 0; - virtual bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const = 0; - virtual bool has_auto_discovery() const = 0; - virtual bool can_test() const = 0; - virtual PrintHostPostUploadActions get_post_upload_actions() const = 0; - // A print host usually does not support multiple printers, with the exception of Repetier server. - virtual bool supports_multiple_printers() const { return false; } - virtual std::string get_host() const = 0; - - // Support for Repetier server multiple groups & printers. Not supported by other print hosts. - // Returns false if not supported. May throw HostNetworkError. - virtual bool get_groups(wxArrayString & /* groups */) const { return false; } - virtual bool get_printers(wxArrayString & /* printers */) const { return false; } - - static PrintHost* get_print_host(DynamicPrintConfig *config); - -protected: - virtual wxString format_error(const std::string &body, const std::string &error, unsigned status) const; -}; - - -struct PrintHostJob -{ - PrintHostUpload upload_data; - std::unique_ptr printhost; - bool cancelled = false; - - PrintHostJob() {} - PrintHostJob(const PrintHostJob&) = delete; - PrintHostJob(PrintHostJob &&other) - : upload_data(std::move(other.upload_data)) - , printhost(std::move(other.printhost)) - , cancelled(other.cancelled) - {} - - PrintHostJob(DynamicPrintConfig *config) - : printhost(PrintHost::get_print_host(config)) - {} - - PrintHostJob& operator=(const PrintHostJob&) = delete; - PrintHostJob& operator=(PrintHostJob &&other) - { - upload_data = std::move(other.upload_data); - printhost = std::move(other.printhost); - cancelled = other.cancelled; - return *this; - } - - bool empty() const { return !printhost; } - operator bool() const { return !!printhost; } -}; - - -namespace GUI { class PrintHostQueueDialog; } - -class PrintHostJobQueue -{ -public: - PrintHostJobQueue(GUI::PrintHostQueueDialog *queue_dialog); - PrintHostJobQueue(const PrintHostJobQueue &) = delete; - PrintHostJobQueue(PrintHostJobQueue &&other) = delete; - ~PrintHostJobQueue(); - - PrintHostJobQueue& operator=(const PrintHostJobQueue &) = delete; - PrintHostJobQueue& operator=(PrintHostJobQueue &&other) = delete; - - void enqueue(PrintHostJob job); - void cancel(size_t id); - -private: - struct priv; - std::shared_ptr p; -}; - - - -} - -#endif diff --git a/src/slic3r/Utils/Repetier.cpp b/src/slic3r/Utils/Repetier.cpp deleted file mode 100644 index 0569d97fae..0000000000 --- a/src/slic3r/Utils/Repetier.cpp +++ /dev/null @@ -1,274 +0,0 @@ -#include "Repetier.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - - -#include "libslic3r/PrintConfig.hpp" -#include "slic3r/GUI/I18N.hpp" -#include "slic3r/GUI/GUI.hpp" -#include "slic3r/GUI/format.hpp" -#include "Http.hpp" - - -namespace fs = boost::filesystem; -namespace pt = boost::property_tree; - - -namespace Slic3r { - -Repetier::Repetier(DynamicPrintConfig *config) : - host(config->opt_string("print_host")), - apikey(config->opt_string("printhost_apikey")), - cafile(config->opt_string("printhost_cafile")), - port(config->opt_string("printhost_port")) -{} - -const char* Repetier::get_name() const { return "Repetier"; } - -bool Repetier::test(wxString &msg) const -{ - // Since the request is performed synchronously here, - // it is ok to refer to `msg` from within the closure - - const char *name = get_name(); - - bool res = true; - auto url = make_url("printer/info"); - - BOOST_LOG_TRIVIAL(info) << boost::format("%1%: List version at: %2%") % name % url; - - auto http = Http::get(std::move(url)); - set_auth(http); - - http.on_error([&](std::string body, std::string error, unsigned status) { - BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error getting version: %2%, HTTP %3%, body: `%4%`") % name % error % status % body; - res = false; - msg = format_error(body, error, status); - }) - .on_complete([&, this](std::string body, unsigned) { - BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: Got version: %2%") % name % body; - - try { - std::stringstream ss(body); - pt::ptree ptree; - pt::read_json(ss, ptree); - - const auto text = ptree.get_optional("name"); - res = validate_version_text(text); - if (! res) { - msg = GUI::from_u8((boost::format(_utf8(L("Mismatched type of print host: %s"))) % (text ? *text : "Repetier")).str()); - } - } - catch (const std::exception &) { - res = false; - msg = "Could not parse server response"; - } - }) - .perform_sync(); - - return res; -} - -wxString Repetier::get_test_ok_msg () const -{ - return _(L("Connection to Repetier works correctly.")); -} - -wxString Repetier::get_test_failed_msg (wxString &msg) const -{ - return GUI::from_u8((boost::format("%s: %s\n\n%s") - % _utf8(L("Could not connect to Repetier")) - % std::string(msg.ToUTF8()) - % _utf8(L("Note: Repetier version at least 0.90.0 is required."))).str()); -} - -bool Repetier::upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const -{ - const char *name = get_name(); - - const auto upload_filename = upload_data.upload_path.filename(); - const auto upload_parent_path = upload_data.upload_path.parent_path(); - - wxString test_msg; - if (! test(test_msg)) { - error_fn(std::move(test_msg)); - return false; - } - - bool res = true; - - auto url = upload_data.post_action == PrintHostPostUploadAction::StartPrint - ? make_url((boost::format("printer/job/%1%") % port).str()) - : make_url((boost::format("printer/model/%1%") % port).str()); - - BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Uploading file %2% at %3%, filename: %4%, path: %5%, print: %6%, group: %7%") - % name - % upload_data.source_path - % url - % upload_filename.string() - % upload_parent_path.string() - % (upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false") - % upload_data.group; - - auto http = Http::post(std::move(url)); - set_auth(http); - - if (! upload_data.group.empty() && upload_data.group != _utf8(L("Default"))) { - http.form_add("group", upload_data.group); - } - - if(upload_data.post_action == PrintHostPostUploadAction::StartPrint) { - http.form_add("name", upload_filename.string()); - } - - http.form_add("a", "upload") - .form_add_file("filename", upload_data.source_path.string(), upload_filename.string()) - .on_complete([&](std::string body, unsigned status) { - BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: File uploaded: HTTP %2%: %3%") % name % status % body; - }) - .on_error([&](std::string body, std::string error, unsigned status) { - BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error uploading file: %2%, HTTP %3%, body: `%4%`") % name % error % status % body; - error_fn(format_error(body, error, status)); - res = false; - }) - .on_progress([&](Http::Progress progress, bool &cancel) { - prorgess_fn(std::move(progress), cancel); - if (cancel) { - // Upload was canceled - BOOST_LOG_TRIVIAL(info) << "Repetier: Upload canceled"; - res = false; - } - }) - .perform_sync(); - - return res; -} - -bool Repetier::validate_version_text(const boost::optional &version_text) const -{ - return version_text ? boost::starts_with(*version_text, "Repetier") : true; -} - -void Repetier::set_auth(Http &http) const -{ - http.header("X-Api-Key", apikey); - - if (! cafile.empty()) { - http.ca_file(cafile); - } -} - -std::string Repetier::make_url(const std::string &path) const -{ - if (host.find("http://") == 0 || host.find("https://") == 0) { - if (host.back() == '/') { - return (boost::format("%1%%2%") % host % path).str(); - } else { - return (boost::format("%1%/%2%") % host % path).str(); - } - } else { - return (boost::format("http://%1%/%2%") % host % path).str(); - } -} - -bool Repetier::get_groups(wxArrayString& groups) const -{ - bool res = true; - - const char *name = get_name(); - auto url = make_url((boost::format("printer/api/%1%") % port).str()); - - BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Get groups at: %2%") % name % url; - - auto http = Http::get(std::move(url)); - set_auth(http); - http.form_add("a", "listModelGroups"); - http.on_error([&](std::string body, std::string error, unsigned status) { - BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error getting version: %2%, HTTP %3%, body: `%4%`") % name % error % status % body; - }) - .on_complete([&](std::string body, unsigned) { - BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: Got groups: %2%") % name % body; - - try { - std::stringstream ss(body); - pt::ptree ptree; - pt::read_json(ss, ptree); - - BOOST_FOREACH(boost::property_tree::ptree::value_type &v, ptree.get_child("groupNames.")) { - if (v.second.data() == "#") { - groups.push_back(_utf8(L("Default"))); - } else { - // Is it safe to assume that the data are utf-8 encoded? - groups.push_back(GUI::from_u8(v.second.data())); - } - } - } - catch (const std::exception &) { - //msg = "Could not parse server response"; - res = false; - } - }) - .perform_sync(); - - return res; -} - -bool Repetier::get_printers(wxArrayString& printers) const -{ - const char *name = get_name(); - - bool res = true; - auto url = make_url("printer/list"); - - BOOST_LOG_TRIVIAL(info) << boost::format("%1%: List printers at: %2%") % name % url; - - auto http = Http::get(std::move(url)); - set_auth(http); - - http.on_error([&](std::string body, std::string error, unsigned status) { - BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error listing printers: %2%, HTTP %3%, body: `%4%`") % name % error % status % body; - res = false; - }) - .on_complete([&](std::string body, unsigned http_status) { - BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: Got printers: %2%, HTTP status: %3%") % name % body % http_status; - - if (http_status != 200) - throw HostNetworkError(GUI::format(_L("HTTP status: %1%\nMessage body: \"%2%\""), http_status, body)); - - std::stringstream ss(body); - pt::ptree ptree; - try { - pt::read_json(ss, ptree); - } catch (const pt::ptree_error &err) { - throw HostNetworkError(GUI::format(_L("Parsing of host response failed.\nMessage body: \"%1%\"\nError: \"%2%\""), body, err.what())); - } - - const auto error = ptree.get_optional("error"); - if (error) - throw HostNetworkError(*error); - - try { - BOOST_FOREACH(boost::property_tree::ptree::value_type &v, ptree.get_child("data.")) { - const auto port = v.second.get("slug"); - printers.push_back(Slic3r::GUI::from_u8(port)); - } - } catch (const std::exception &err) { - throw HostNetworkError(GUI::format(_L("Enumeration of host printers failed.\nMessage body: \"%1%\"\nError: \"%2%\""), body, err.what())); - } - }) - .perform_sync(); - - return res; -} - -} diff --git a/src/slic3r/Utils/Repetier.hpp b/src/slic3r/Utils/Repetier.hpp deleted file mode 100644 index 6f33102604..0000000000 --- a/src/slic3r/Utils/Repetier.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef slic3r_Repetier_hpp_ -#define slic3r_Repetier_hpp_ - -#include -#include -#include - -#include "PrintHost.hpp" - -namespace Slic3r { - -class DynamicPrintConfig; -class Http; - -class Repetier : public PrintHost -{ -public: - Repetier(DynamicPrintConfig *config); - ~Repetier() override = default; - - const char* get_name() const override; - - bool test(wxString &curl_msg) const override; - wxString get_test_ok_msg () const override; - wxString get_test_failed_msg (wxString &msg) const override; - bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const override; - bool has_auto_discovery() const override { return false; } - bool can_test() const override { return true; } - PrintHostPostUploadActions get_post_upload_actions() const override { return PrintHostPostUploadAction::StartPrint; } - bool supports_multiple_printers() const override { return true; } - std::string get_host() const override { return host; } - - bool get_groups(wxArrayString &groups) const override; - bool get_printers(wxArrayString &printers) const override; - -protected: - virtual bool validate_version_text(const boost::optional &version_text) const; - -private: - std::string host; - std::string apikey; - std::string cafile; - std::string port; - - void set_auth(Http &http) const; - std::string make_url(const std::string &path) const; -}; - -} - -#endif diff --git a/src/slic3r/Utils/Serial.cpp b/src/slic3r/Utils/Serial.cpp deleted file mode 100644 index 4db1acc6b6..0000000000 --- a/src/slic3r/Utils/Serial.cpp +++ /dev/null @@ -1,504 +0,0 @@ -#include "Serial.hpp" - -#include "libslic3r/Exception.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#if _WIN32 - #include - #include - #include - #include - #include - // Undefine min/max macros incompatible with the standard library - // For example, std::numeric_limits::max() - // produces some weird errors - #ifdef min - #undef min - #endif - #ifdef max - #undef max - #endif - #include "boost/nowide/convert.hpp" - #pragma comment(lib, "user32.lib") -#elif __APPLE__ - #include - #include - #include - #include - #include - #include -#endif - -#ifndef _WIN32 - #include - #include - #include - #include -#endif - -#if defined(__APPLE__) || defined(__OpenBSD__) - #include -#elif defined __linux__ - #include - #include -#endif - -using boost::optional; - - -namespace Slic3r { -namespace Utils { - -static bool looks_like_printer(const std::string &friendly_name) -{ - return friendly_name.find("Original Prusa") != std::string::npos; -} - -#if _WIN32 -void parse_hardware_id(const std::string &hardware_id, SerialPortInfo &spi) -{ - unsigned vid, pid; - std::regex pattern("USB\\\\.*VID_([[:xdigit:]]+)&PID_([[:xdigit:]]+).*"); - std::smatch matches; - if (std::regex_match(hardware_id, matches, pattern)) { - vid = std::stoul(matches[1].str(), 0, 16); - pid = std::stoul(matches[2].str(), 0, 16); - spi.id_vendor = vid; - spi.id_product = pid; - } -} -#endif - -#ifdef __linux__ -optional sysfs_tty_prop(const std::string &tty_dev, const std::string &name) -{ - const auto prop_path = (boost::format("/sys/class/tty/%1%/device/../%2%") % tty_dev % name).str(); - std::ifstream file(prop_path); - std::string res; - - std::getline(file, res); - if (file.good()) { return res; } - else { return boost::none; } -} - -optional sysfs_tty_prop_hex(const std::string &tty_dev, const std::string &name) -{ - auto prop = sysfs_tty_prop(tty_dev, name); - if (!prop) { return boost::none; } - - try { return std::stoul(*prop, 0, 16); } - catch (const std::exception&) { return boost::none; } -} -#endif - -std::vector scan_serial_ports_extended() -{ - std::vector output; - -#ifdef _WIN32 - SP_DEVINFO_DATA devInfoData = { 0 }; - devInfoData.cbSize = sizeof(devInfoData); - // Get the tree containing the info for the ports. - HDEVINFO hDeviceInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_PORTS, 0, nullptr, DIGCF_PRESENT); - if (hDeviceInfo != INVALID_HANDLE_VALUE) { - // Iterate over all the devices in the tree. - for (int nDevice = 0; SetupDiEnumDeviceInfo(hDeviceInfo, nDevice, &devInfoData); ++ nDevice) { - SerialPortInfo port_info; - // Get the registry key which stores the ports settings. - HKEY hDeviceKey = SetupDiOpenDevRegKey(hDeviceInfo, &devInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE); - if (hDeviceKey) { - // Read in the name of the port. - wchar_t pszPortName[4096]; - DWORD dwSize = sizeof(pszPortName); - DWORD dwType = 0; - if (RegQueryValueEx(hDeviceKey, L"PortName", NULL, &dwType, (LPBYTE)pszPortName, &dwSize) == ERROR_SUCCESS) - port_info.port = boost::nowide::narrow(pszPortName); - RegCloseKey(hDeviceKey); - if (port_info.port.empty()) - continue; - } - - // Find the size required to hold the device info. - DWORD regDataType; - DWORD reqSize = 0; - SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_HARDWAREID, nullptr, nullptr, 0, &reqSize); - std::vector hardware_id(reqSize > 1 ? reqSize : 1); - // Now store it in a buffer. - if (! SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_HARDWAREID, ®DataType, (BYTE*)hardware_id.data(), reqSize, nullptr)) - continue; - parse_hardware_id(boost::nowide::narrow(hardware_id.data()), port_info); - - // Find the size required to hold the friendly name. - reqSize = 0; - SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_FRIENDLYNAME, nullptr, nullptr, 0, &reqSize); - std::vector friendly_name; - friendly_name.reserve(reqSize > 1 ? reqSize : 1); - // Now store it in a buffer. - if (! SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_FRIENDLYNAME, nullptr, (BYTE*)friendly_name.data(), reqSize, nullptr)) { - port_info.friendly_name = port_info.port; - } else { - port_info.friendly_name = boost::nowide::narrow(friendly_name.data()); - port_info.is_printer = looks_like_printer(port_info.friendly_name); - } - output.emplace_back(std::move(port_info)); - } - } -#elif __APPLE__ - // inspired by https://sigrok.org/wiki/Libserialport - CFMutableDictionaryRef classes = IOServiceMatching(kIOSerialBSDServiceValue); - if (classes != 0) { - io_iterator_t iter; - if (IOServiceGetMatchingServices(kIOMasterPortDefault, classes, &iter) == KERN_SUCCESS) { - io_object_t port; - while ((port = IOIteratorNext(iter)) != 0) { - CFTypeRef cf_property = IORegistryEntryCreateCFProperty(port, CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0); - if (cf_property) { - char path[PATH_MAX]; - Boolean result = CFStringGetCString((CFStringRef)cf_property, path, sizeof(path), kCFStringEncodingUTF8); - CFRelease(cf_property); - if (result) { - SerialPortInfo port_info; - port_info.port = path; - - // Attempt to read out the device friendly name - if ((cf_property = IORegistryEntrySearchCFProperty(port, kIOServicePlane, - CFSTR("USB Interface Name"), kCFAllocatorDefault, - kIORegistryIterateRecursively | kIORegistryIterateParents)) || - (cf_property = IORegistryEntrySearchCFProperty(port, kIOServicePlane, - CFSTR("USB Product Name"), kCFAllocatorDefault, - kIORegistryIterateRecursively | kIORegistryIterateParents)) || - (cf_property = IORegistryEntrySearchCFProperty(port, kIOServicePlane, - CFSTR("Product Name"), kCFAllocatorDefault, - kIORegistryIterateRecursively | kIORegistryIterateParents)) || - (cf_property = IORegistryEntryCreateCFProperty(port, - CFSTR(kIOTTYDeviceKey), kCFAllocatorDefault, 0))) { - // Description limited to 127 char, anything longer would not be user friendly anyway. - char description[128]; - if (CFStringGetCString((CFStringRef)cf_property, description, sizeof(description), kCFStringEncodingUTF8)) { - port_info.friendly_name = std::string(description) + " (" + port_info.port + ")"; - port_info.is_printer = looks_like_printer(port_info.friendly_name); - } - CFRelease(cf_property); - } - if (port_info.friendly_name.empty()) - port_info.friendly_name = port_info.port; - - // Attempt to read out the VID & PID - int vid, pid; - auto cf_vendor = IORegistryEntrySearchCFProperty(port, kIOServicePlane, CFSTR("idVendor"), - kCFAllocatorDefault, kIORegistryIterateRecursively | kIORegistryIterateParents); - auto cf_product = IORegistryEntrySearchCFProperty(port, kIOServicePlane, CFSTR("idProduct"), - kCFAllocatorDefault, kIORegistryIterateRecursively | kIORegistryIterateParents); - if (cf_vendor && cf_product) { - if (CFNumberGetValue((CFNumberRef)cf_vendor, kCFNumberIntType, &vid) && - CFNumberGetValue((CFNumberRef)cf_product, kCFNumberIntType, &pid)) { - port_info.id_vendor = vid; - port_info.id_product = pid; - } - } - if (cf_vendor) { CFRelease(cf_vendor); } - if (cf_product) { CFRelease(cf_product); } - - output.emplace_back(std::move(port_info)); - } - } - IOObjectRelease(port); - } - } - } -#else - // UNIX / Linux - std::initializer_list prefixes { "ttyUSB" , "ttyACM", "tty.", "cu.", "rfcomm" }; - for (auto &dir_entry : boost::filesystem::directory_iterator(boost::filesystem::path("/dev"))) { - std::string name = dir_entry.path().filename().string(); - for (const char *prefix : prefixes) { - if (boost::starts_with(name, prefix)) { - const auto path = dir_entry.path().string(); - SerialPortInfo spi; - spi.port = path; -#ifdef __linux__ - auto friendly_name = sysfs_tty_prop(name, "product"); - if (friendly_name) { - spi.is_printer = looks_like_printer(*friendly_name); - spi.friendly_name = (boost::format("%1% (%2%)") % *friendly_name % path).str(); - } else { - spi.friendly_name = path; - } - auto vid = sysfs_tty_prop_hex(name, "idVendor"); - auto pid = sysfs_tty_prop_hex(name, "idProduct"); - if (vid && pid) { - spi.id_vendor = *vid; - spi.id_product = *pid; - } -#else - spi.friendly_name = path; -#endif - output.emplace_back(std::move(spi)); - break; - } - } - } -#endif - - output.erase(std::remove_if(output.begin(), output.end(), - [](const SerialPortInfo &info) { - return boost::starts_with(info.port, "Bluetooth") || boost::starts_with(info.port, "FireFly"); - }), - output.end()); - return output; -} - -std::vector scan_serial_ports() -{ - std::vector ports = scan_serial_ports_extended(); - std::vector output; - output.reserve(ports.size()); - for (const SerialPortInfo &spi : ports) - output.emplace_back(std::move(spi.port)); - return output; -} - - - -// Class Serial - -namespace asio = boost::asio; -using boost::system::error_code; - -Serial::Serial(asio::io_service& io_service) : - asio::serial_port(io_service) -{} - -Serial::Serial(asio::io_service& io_service, const std::string &name, unsigned baud_rate) : - asio::serial_port(io_service, name) -{ - set_baud_rate(baud_rate); -} - -Serial::~Serial() {} - -void Serial::set_baud_rate(unsigned baud_rate) -{ - try { - // This does not support speeds > 115200 - set_option(boost::asio::serial_port_base::baud_rate(baud_rate)); - } catch (boost::system::system_error &) { - auto handle = native_handle(); - - auto handle_errno = [](int retval) { - if (retval != 0) { - throw Slic3r::RuntimeError( - (boost::format("Could not set baud rate: %1%") % strerror(errno)).str() - ); - } - }; - -#if __APPLE__ - termios ios; - handle_errno(::tcgetattr(handle, &ios)); - handle_errno(::cfsetspeed(&ios, baud_rate)); - speed_t newSpeed = baud_rate; - handle_errno(::ioctl(handle, IOSSIOSPEED, &newSpeed)); - handle_errno(::tcsetattr(handle, TCSANOW, &ios)); -#elif __linux__ - - /* The following definitions are kindly borrowed from: - /usr/include/asm-generic/termbits.h - Unfortunately we cannot just include that one because - it would redefine the "struct termios" already defined - the already included by Boost.ASIO. */ -#define K_NCCS 19 - struct termios2 { - tcflag_t c_iflag; - tcflag_t c_oflag; - tcflag_t c_cflag; - tcflag_t c_lflag; - cc_t c_line; - cc_t c_cc[K_NCCS]; - speed_t c_ispeed; - speed_t c_ospeed; - }; -#define BOTHER CBAUDEX - - termios2 ios; - handle_errno(::ioctl(handle, TCGETS2, &ios)); - ios.c_ispeed = ios.c_ospeed = baud_rate; - ios.c_cflag &= ~CBAUD; - ios.c_cflag |= BOTHER | CLOCAL | CREAD; - ios.c_cc[VMIN] = 1; // Minimum of characters to read, prevents eof errors when 0 bytes are read - ios.c_cc[VTIME] = 1; - handle_errno(::ioctl(handle, TCSETS2, &ios)); - -#elif __OpenBSD__ - struct termios ios; - handle_errno(::tcgetattr(handle, &ios)); - handle_errno(::cfsetspeed(&ios, baud_rate)); - handle_errno(::tcsetattr(handle, TCSAFLUSH, &ios)); -#else - throw Slic3r::RuntimeError("Custom baud rates are not currently supported on this OS"); -#endif - } -} - - -/* -void Serial::set_DTR(bool on) -{ - auto handle = native_handle(); -#if defined(_WIN32) && !defined(__SYMBIAN32__) - if (! EscapeCommFunction(handle, on ? SETDTR : CLRDTR)) { - throw Slic3r::RuntimeError("Could not set serial port DTR"); - } -#else - int status; - if (::ioctl(handle, TIOCMGET, &status) == 0) { - on ? status |= TIOCM_DTR : status &= ~TIOCM_DTR; - if (::ioctl(handle, TIOCMSET, &status) == 0) { - return; - } - } - - throw Slic3r::RuntimeError( - (boost::format("Could not set serial port DTR: %1%") % strerror(errno)).str() - ); -#endif -} - -void Serial::reset_line_num() -{ - // See https://github.com/MarlinFirmware/Marlin/wiki/M110 - write_string("M110 N0\n"); - m_line_num = 0; -} - -bool Serial::read_line(unsigned timeout, std::string &line, error_code &ec) -{ - auto& io_service = -#if BOOST_VERSION >= 107000 - //FIXME this is most certainly wrong! - (boost::asio::io_context&)this->get_executor().context(); - #else - this->get_io_service(); -#endif - asio::deadline_timer timer(io_service); - char c = 0; - bool fail = false; - - while (true) { - io_service.reset(); - - asio::async_read(*this, boost::asio::buffer(&c, 1), [&](const error_code &read_ec, size_t size) { - if (ec || size == 0) { - fail = true; - ec = read_ec; // FIXME: only if operation not aborted - } - timer.cancel(); // FIXME: ditto - }); - - if (timeout > 0) { - timer.expires_from_now(boost::posix_time::milliseconds(timeout)); - timer.async_wait([&](const error_code &ec) { - // Ignore timer aborts - if (!ec) { - fail = true; - this->cancel(); - } - }); - } - - io_service.run(); - - if (fail) { - return false; - } else if (c != '\n') { - line += c; - } else { - return true; - } - } -} - -void Serial::printer_setup() -{ - printer_reset(); - write_string("\r\r\r\r\r\r\r\r\r\r"); // Gets rid of line noise, if any -} - -size_t Serial::write_string(const std::string &str) -{ - // TODO: might be wise to timeout here as well - return asio::write(*this, asio::buffer(str)); -} - -bool Serial::printer_ready_wait(unsigned retries, unsigned timeout) -{ - std::string line; - error_code ec; - - for (; retries > 0; retries--) { - reset_line_num(); - - while (read_line(timeout, line, ec)) { - if (line == "ok") { - return true; - } - line.clear(); - } - - line.clear(); - } - - return false; -} - -size_t Serial::printer_write_line(const std::string &line, unsigned line_num) -{ - const auto formatted_line = Utils::Serial::printer_format_line(line, line_num); - return write_string(formatted_line); -} - -size_t Serial::printer_write_line(const std::string &line) -{ - m_line_num++; - return printer_write_line(line, m_line_num); -} - -void Serial::printer_reset() -{ - this->set_DTR(false); - std::this_thread::sleep_for(std::chrono::milliseconds(200)); - this->set_DTR(true); - std::this_thread::sleep_for(std::chrono::milliseconds(200)); - this->set_DTR(false); - std::this_thread::sleep_for(std::chrono::milliseconds(1000)); -} - -std::string Serial::printer_format_line(const std::string &line, unsigned line_num) -{ - const auto line_num_str = std::to_string(line_num); - - unsigned checksum = 'N'; - for (auto c : line_num_str) { checksum ^= c; } - checksum ^= ' '; - for (auto c : line) { checksum ^= c; } - - return (boost::format("N%1% %2%*%3%\n") % line_num_str % line % checksum).str(); -} -*/ - - -} // namespace Utils -} // namespace Slic3r diff --git a/src/slic3r/Utils/Serial.hpp b/src/slic3r/Utils/Serial.hpp deleted file mode 100644 index 8bad75b315..0000000000 --- a/src/slic3r/Utils/Serial.hpp +++ /dev/null @@ -1,97 +0,0 @@ -#ifndef slic3r_GUI_Utils_Serial_hpp_ -#define slic3r_GUI_Utils_Serial_hpp_ - -#include -#include -#include -#include - - -namespace Slic3r { -namespace Utils { - -struct SerialPortInfo { - std::string port; - unsigned id_vendor = -1; - unsigned id_product = -1; - std::string friendly_name; - bool is_printer = false; - - SerialPortInfo() {} - SerialPortInfo(std::string port) : port(port), friendly_name(std::move(port)) {} - - bool id_match(unsigned id_vendor, unsigned id_product) const { return id_vendor == this->id_vendor && id_product == this->id_product; } -}; - -inline bool operator==(const SerialPortInfo &sp1, const SerialPortInfo &sp2) -{ - return - sp1.port == sp2.port && - sp1.id_vendor == sp2.id_vendor && - sp1.id_product == sp2.id_product && - sp1.is_printer == sp2.is_printer; -} - -extern std::vector scan_serial_ports(); -extern std::vector scan_serial_ports_extended(); - - -class Serial : public boost::asio::serial_port -{ -public: - Serial(boost::asio::io_service &io_service); - Serial(boost::asio::io_service &io_service, const std::string &name, unsigned baud_rate); - Serial(const Serial &) = delete; - Serial &operator=(const Serial &) = delete; - ~Serial(); - - void set_baud_rate(unsigned baud_rate); - - // The Serial implementation is currently in disarray and therefore commented out. - // The boost implementation seems to have several problems, such as lack of support - // for custom baud rates, few weird implementation bugs and a history of API breakages. - // It's questionable whether it solves more problems than causes. Probably not. - // TODO: Custom implementation not based on asio. - // - // As of now, this class is only kept for the purpose of rebooting AVR109, - // see FirmwareDialog::priv::avr109_reboot() - -/* - void set_DTR(bool on); - - // Resets the line number both internally as well as with the firmware using M110 - void reset_line_num(); - - // Reads a line or times out, the timeout is in milliseconds - bool read_line(unsigned timeout, std::string &line, boost::system::error_code &ec); - - // Perform an initial setup for communicating with a printer - void printer_setup(); - - // Write data from a string - size_t write_string(const std::string &str); - - // Attempts to reset the line numer and waits until the printer says "ok" - bool printer_ready_wait(unsigned retries, unsigned timeout); - - // Write Marlin-formatted line, with a line number and a checksum - size_t printer_write_line(const std::string &line, unsigned line_num); - - // Same as above, but with internally-managed line number - size_t printer_write_line(const std::string &line); - - // Toggles DTR to reset the printer - void printer_reset(); - - // Formats a line Marlin-style, ie. with a sequential number and a checksum - static std::string printer_format_line(const std::string &line, unsigned line_num); -private: - unsigned m_line_num = 0; -*/ -}; - - -} // Utils -} // Slic3r - -#endif /* slic3r_GUI_Utils_Serial_hpp_ */