diff --git a/src/QIDIStudio.cpp b/src/QIDIStudio.cpp index 5790ffb..1fb68bf 100644 --- a/src/QIDIStudio.cpp +++ b/src/QIDIStudio.cpp @@ -3556,6 +3556,16 @@ int CLI::run(int argc, char **argv) BOOST_LOG_TRIVIAL(info) << boost::format("downward_check: printable size{%1%,%2%, %3%}, exclude area{%4%, %5%: %6% x %7%}") %printer_plate.printable_width %printer_plate.printable_depth %printer_plate.printable_height %printer_plate.exclude_x %printer_plate.exclude_y %printer_plate.exclude_width %printer_plate.exclude_depth; + + //1.9.7.52 + if (config.option("extruder_clearance_height_to_lid")) + printer_plate.height_to_lid = config.opt_float("extruder_clearance_height_to_lid"); + + if (config.option("extruder_clearance_height_to_rod")) + printer_plate.height_to_rod = config.opt_float("extruder_clearance_height_to_rod"); + + if (config.option("extruder_clearance_max_radius")) + printer_plate.cleareance_radius = config.opt_float("extruder_clearance_max_radius"); downward_check_printers.push_back(std::move(printer_plate)); } } @@ -3575,6 +3585,10 @@ int CLI::run(int argc, char **argv) Slic3r::GUI::PartPlate* cur_plate = (Slic3r::GUI::PartPlate *)partplate_list.get_plate(index); Vec3d size = plate_obj_size_infos[index].obj_bbox.size(); + //1.9.7.52 + bool is_sequence = false; + get_print_sequence(cur_plate, m_print_config, is_sequence); + for (int index2 = 0; index2 < downward_check_size; index2 ++) { if (failed_count == downward_check_size) { @@ -3583,6 +3597,29 @@ int CLI::run(int argc, char **argv) if (downward_check_status[index2]) continue; printer_plate_info_t& plate_info = downward_check_printers[index2]; + + //1.9.7.52 + if (is_sequence) { + if ((plate_info.cleareance_radius > 0.f) && (plate_info.height_to_rod > 0.f) && (plate_info.height_to_lid > 0.f)) { + if ((cleareance_radius < plate_info.cleareance_radius) + || (height_to_rod > plate_info.height_to_rod) + || (height_to_lid > plate_info.height_to_lid)) + { + BOOST_LOG_TRIVIAL(info) << boost::format("plate %1%, downward_check index %2%, name %3%, sequence print, original clearance{%4%, %5%, %6%} exceeds new {%7%, %8%, %9%}") + %(index+1) %(index2+1) %plate_info.printer_name %cleareance_radius %height_to_rod %height_to_lid %plate_info.cleareance_radius %plate_info.height_to_rod %plate_info.height_to_lid; + downward_check_status[index2] = true; + failed_count ++; + continue; + } + } + else { + BOOST_LOG_TRIVIAL(info) << boost::format("plate %1%, downward_check index %2%, name %3%, sequence print, can not get cleareance params, set to false") + %(index+1) %(index2+1) %plate_info.printer_name; + downward_check_status[index2] = true; + failed_count ++; + continue; + } + } if ((size.z() > plate_info.printable_height) || (size.y() > plate_info.printable_depth) || (size.x() > plate_info.printable_width)) { BOOST_LOG_TRIVIAL(info) << boost::format("plate %1%, downward_check index %2%, name %3%, bbox {%4%, %5%, %6%} exceeds printer size {%7%, %8%, %9%}") %(index+1) %(index2+1) %plate_info.printer_name @@ -3977,7 +4014,8 @@ int CLI::run(int argc, char **argv) need_arrange = true; } - if ((!need_arrange) && is_qdt_3mf && !shrink_to_new_bed && (plate_to_slice > 0)) + //1.9.7.52 + if ((!need_arrange) && is_qdt_3mf && !shrink_to_new_bed && (plate_to_slice > 0) && !new_printer_system_name.empty() && (new_printer_system_name!= current_printer_system_name)) { if (((old_height_to_rod != 0.f) && (old_height_to_rod != height_to_rod)) || ((old_height_to_lid != 0.f) && (old_height_to_lid != height_to_lid)) diff --git a/src/QIDIStudio.hpp b/src/QIDIStudio.hpp index 259a37d..6a6cd7b 100644 --- a/src/QIDIStudio.hpp +++ b/src/QIDIStudio.hpp @@ -85,6 +85,10 @@ typedef struct _printer_plate_info { int exclude_depth{0}; int exclude_x{0}; int exclude_y{0}; + //1.9.7.52 + float height_to_lid{0.f}; + float height_to_rod{0.f}; + float cleareance_radius{0.f}; }printer_plate_info_t; typedef struct _plate_obj_size_info { diff --git a/src/libslic3r/AppConfig.cpp b/src/libslic3r/AppConfig.cpp index 771148b..2537358 100644 --- a/src/libslic3r/AppConfig.cpp +++ b/src/libslic3r/AppConfig.cpp @@ -329,6 +329,11 @@ void AppConfig::set_defaults() set_bool("backup_switch", true); } + //1.9.7.52 + if (get("liveview", "auto_stop_liveview").empty()) { + set("liveview", "auto_stop_liveview", true); + } + if (get("backup_interval").empty()) { set("backup_interval", "10"); } diff --git a/src/libslic3r/ExtrusionEntity.cpp b/src/libslic3r/ExtrusionEntity.cpp index b169c46..a659aaa 100644 --- a/src/libslic3r/ExtrusionEntity.cpp +++ b/src/libslic3r/ExtrusionEntity.cpp @@ -66,6 +66,20 @@ void ExtrusionPath::polygons_covered_by_spacing(Polygons &out, const float scale polygons_append(out, offset(this->polyline, 0.5f * float(flow.scaled_spacing()) + scaled_epsilon)); } +//1.9.7.52 +bool ExtrusionPath::can_merge(const ExtrusionPath& other) +{ + return overhang_degree == other.overhang_degree && + curve_degree==other.curve_degree && + mm3_per_mm == other.mm3_per_mm && + width == other.width && + height == other.height && + m_can_reverse == other.m_can_reverse && + m_role == other.m_role && + m_no_extrusion == other.m_no_extrusion && + smooth_speed == other.smooth_speed; +} + void ExtrusionMultiPath::reverse() { for (ExtrusionPath &path : this->paths) diff --git a/src/libslic3r/ExtrusionEntity.hpp b/src/libslic3r/ExtrusionEntity.hpp index 3c753af..6a543a8 100644 --- a/src/libslic3r/ExtrusionEntity.hpp +++ b/src/libslic3r/ExtrusionEntity.hpp @@ -285,6 +285,9 @@ public: void set_reverse() override { m_can_reverse = false; } bool can_reverse() const override { return m_can_reverse; } + //1.9.7.52 + bool can_merge(const ExtrusionPath& other); + private: void _inflate_collection(const Polylines &polylines, ExtrusionEntityCollection* collection) const; bool m_can_reverse = true; diff --git a/src/libslic3r/Flow.cpp b/src/libslic3r/Flow.cpp index 907e1fb..cb1acfe 100644 --- a/src/libslic3r/Flow.cpp +++ b/src/libslic3r/Flow.cpp @@ -5,6 +5,7 @@ #include #include +#include // Mark string for localization and translate. #define L(s) Slic3r::I18N::translate(s) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index faea877..8da9b34 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -511,6 +511,11 @@ static std::vector get_path_of_change_filament(const Print& print) config.set_key_value("flush_length", new ConfigOptionFloat(purge_length)); int flush_count = std::min(g_max_flush_count, (int)std::round(purge_volume / g_purge_volume_one_time)); + + //1.9.7.52 + // handle cases for very small purge + if (flush_count == 0 && purge_volume > 0) + flush_count += 1; float flush_unit = purge_length / flush_count; int flush_idx = 0; for (; flush_idx < flush_count; flush_idx++) { @@ -1269,7 +1274,8 @@ void GCode::do_export(Print* print, const char* path, GCodeProcessorResult* resu break; } } - + //1.9.7.52 + m_processor.set_filaments(m_writer.extruders()); m_processor.finalize(true); // DoExport::update_print_estimated_times_stats(m_processor, print->m_print_statistics); DoExport::update_print_estimated_stats(m_processor, m_writer.extruders(), print->m_print_statistics); @@ -1304,13 +1310,16 @@ void GCode::do_export(Print* print, const char* path, GCodeProcessorResult* resu // free functions called by GCode::_do_export() namespace DoExport { - static void init_gcode_processor(const PrintConfig& config, GCodeProcessor& processor, bool& silent_time_estimator_enabled) + //1.9.7.52 + static void init_gcode_processor(const PrintConfig& config, GCodeProcessor& processor, bool& silent_time_estimator_enabled,const std::vector& filaments) { silent_time_estimator_enabled = (config.gcode_flavor == gcfMarlinLegacy || config.gcode_flavor == gcfMarlinFirmware) && config.silent_mode; processor.reset(); processor.apply_config(config); processor.enable_stealth_time_estimator(silent_time_estimator_enabled); + //1.9.7.52 + processor.set_filaments(filaments); } #if 0 @@ -1586,7 +1595,8 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato PROFILE_FUNC(); // modifies m_silent_time_estimator_enabled - DoExport::init_gcode_processor(print.config(), m_processor, m_silent_time_estimator_enabled); + //1.9.7.52 + DoExport::init_gcode_processor(print.config(), m_processor, m_silent_time_estimator_enabled, m_writer.extruders()); // resets analyzer's tracking data m_last_height = 0.f; m_last_layer_z = 0.f; @@ -1669,6 +1679,15 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato //file.write_format(";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Estimated_Printing_Time_Placeholder).c_str()); //QDS: total layer number file.write_format(";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Total_Layer_Number_Placeholder).c_str()); + + //1.9.7.52 + //QDS: total filament used in mm + file.write_format(";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Used_Filament_Length_Placeholder).c_str()); + //QDS: total filament used in cm3 + file.write_format(";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Used_Filament_Volume_Placeholder).c_str()); + //QDS: total filament used in g + file.write_format(";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Used_Filament_Weight_Placeholder).c_str()); + //QDS: judge whether support skipping, if yes, list all label_object_id with sorted order here if (print.num_object_instances() <= g_max_label_object && //Don't support too many objects on one plate (print.num_object_instances() > 1) && //Don't support skipping single object @@ -2399,12 +2418,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato has_wipe_tower, print.wipe_tower_data(), m_writer.extruders(), // Modifies - print.m_print_statistics)); - file.write("\n");*/ - //file.write_format("; total filament weight [g] = %.2lf\n", print.m_print_statistics.total_weight); - //file.write_format("; total filament cost = %.2lf\n", print.m_print_statistics.total_cost); - //if (print.m_print_statistics.total_toolchanges > 0) - // file.write_format("; total filament change = %i\n", print.m_print_statistics.total_toolchanges); + print.m_print_statistics));*/ bool activate_air_filtration = false; for (const auto& extruder : m_writer.extruders()) @@ -4677,41 +4691,38 @@ ExtrusionPaths GCode::split_and_mapping_speed(double &other_path_v, double &fina ExtrusionPaths GCode::merge_same_speed_paths(const ExtrusionPaths &paths) { ExtrusionPaths output_paths; + //1.9.7.52 + std::optional merged_path; - size_t path_idx = 0; - int merge_start = 0; - ExtrusionPath merge_path; - for (; path_idx < paths.size(); path_idx++) { + for(size_t path_idx=0;path_idxcan_merge(path)){ + merged_path->polyline.append(path.polyline); + } + else{ + output_paths.push_back(std::move(*merged_path)); + merged_path = path; } } - if (!merge_path.empty() && merge_start < paths.size()) - output_paths.push_back(std::move(merge_path)); + if(merged_path.has_value()) + output_paths.push_back(std::move(*merged_path)); return output_paths; } @@ -5594,6 +5605,10 @@ std::string GCode::set_extruder(unsigned int extruder_id, double print_z, bool b dyn_config.set_key_value("flush_length", new ConfigOptionFloat(wipe_length)); int flush_count = std::min(g_max_flush_count, (int)std::round(wipe_volume / g_purge_volume_one_time)); + //1.9.7.52 + // handle cases for very small purge + if (flush_count == 0 && wipe_volume > 0) + flush_count += 1; float flush_unit = wipe_length / flush_count; int flush_idx = 0; for (; flush_idx < flush_count; flush_idx++) { diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 8a64dcb..2e7f618 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -61,7 +61,11 @@ const std::vector GCodeProcessor::Reserved_Tags = { "_GP_ESTIMATED_PRINTING_TIME_PLACEHOLDER", "_GP_TOTAL_LAYER_NUMBER_PLACEHOLDER", " WIPE_TOWER_START", - " WIPE_TOWER_END" + //1.9.7.52 + " WIPE_TOWER_END", + "_GP_FILAMENT_USED_WEIGHT_PLACEHOLDER", + "_GP_FILAMENT_USED_VOLUME_PLACEHOLDER", + "_GP_FILAMENT_USED_LENGTH_PLACEHOLDER" }; const std::string GCodeProcessor::Flush_Start_Tag = " FLUSH_START"; @@ -370,7 +374,8 @@ void GCodeProcessor::TimeProcessor::reset() machines[static_cast(PrintEstimatedStatistics::ETimeMode::Normal)].enabled = true; } -void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, std::vector& moves, std::vector& lines_ends, size_t total_layer_num) +//1.9.7.52 +void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, std::vector& moves, std::vector& lines_ends, const TimeProcessContext& context) { FilePtr in{ boost::nowide::fopen(filename.c_str(), "rb") }; if (in.f == nullptr) @@ -447,6 +452,20 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st // gcode_line is in/out parameter, to reduce expensive memory allocation auto process_placeholders = [&](std::string& gcode_line) { unsigned int extra_lines_count = 0; + //1.9.7.52 + auto format_filament_used_info = [](const std::string& info, std::mapval_per_extruder) { + auto double_to_fmt_string = [](double num) -> std::string { + char buf[20]; + sprintf(buf, "%.2f", num); + return std::string(buf); + }; + std::string buf = "; " + info + " : "; + size_t idx = 0; + for (auto item : val_per_extruder) + buf += (idx++ == 0 ? double_to_fmt_string(item.second) : "," + double_to_fmt_string(item.second)); + buf += '\n'; + return buf; + }; // remove trailing '\n' auto line = std::string_view(gcode_line).substr(0, gcode_line.length() - 1); @@ -486,11 +505,12 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st sprintf(buf, "; estimated printing time (normal mode) = %s\n", get_time_dhms(machine.time).c_str()); ret += buf; - } else { + } + else { // QDS estimator sprintf(buf, "; model printing time: %s; total estimated time: %s\n", - get_time_dhms(machine.time - machine.prepare_time).c_str(), - get_time_dhms(machine.time).c_str()); + get_time_dhms(machine.time - machine.prepare_time).c_str(), + get_time_dhms(machine.time).c_str()); ret += buf; } } @@ -499,9 +519,49 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st //QDS: write total layer number else if (line == reserved_tag(ETags::Total_Layer_Number_Placeholder)) { char buf[128]; - sprintf(buf, "; total layer number: %zd\n", total_layer_num); + sprintf(buf, "; total layer number: %zd\n", context.total_layer_num); ret += buf; } + //1.9.7.52 + else if (line == reserved_tag(ETags::Used_Filament_Weight_Placeholder)) { + std::maptotal_weight_per_extruder; + for (const auto& pair : context.used_filaments.total_volumes_per_extruder) { + auto filament_id = pair.first; + auto volume = pair.second; + auto iter = std::find_if(context.filament_lists.begin(), context.filament_lists.end(), [filament_id](const Extruder& filament) { return filament.id() == filament_id; }); + if (iter == context.filament_lists.end()) + continue; + double weight = volume * iter->filament_density() * 0.001; + total_weight_per_extruder[filament_id] += weight; + } + + ret += format_filament_used_info("total filament weight [g]", total_weight_per_extruder); + } + else if (line == reserved_tag(ETags::Used_Filament_Volume_Placeholder)) { + std::maptotal_volume_per_extruder; + for (const auto& pair : context.used_filaments.total_volumes_per_extruder) { + auto filament_id = pair.first; + auto volume = pair.second; + auto iter = std::find_if(context.filament_lists.begin(), context.filament_lists.end(), [filament_id](const Extruder& filament) { return filament.id() == filament_id; }); + if (iter == context.filament_lists.end()) + continue; + total_volume_per_extruder[filament_id] += volume; + } + ret += format_filament_used_info("total filament volume [cm^3]", total_volume_per_extruder); + } + else if (line == reserved_tag(ETags::Used_Filament_Length_Placeholder)) { + std::maptotal_length_per_extruder; + for (const auto& pair : context.used_filaments.total_volumes_per_extruder) { + auto filament_id = pair.first; + auto volume = pair.second; + auto iter = std::find_if(context.filament_lists.begin(), context.filament_lists.end(), [filament_id](const Extruder& filament) { return filament.id() == filament_id; }); + if (iter == context.filament_lists.end()) + continue; + double length = volume / (PI * sqr(0.5 * iter->filament_diameter())); + total_length_per_extruder[filament_id] += length; + } + ret += format_filament_used_info("total filament length [mm]", total_length_per_extruder); + } } if (! ret.empty()) @@ -1583,7 +1643,9 @@ void GCodeProcessor::finalize(bool post_process) m_width_compare.output(); #endif // ENABLE_GCODE_VIEWER_DATA_CHECKING if (post_process){ - m_time_processor.post_process(m_result.filename, m_result.moves, m_result.lines_ends, m_layer_id); + //1.9.7.52 + TimeProcessContext context(m_layer_id,m_filament_lists,m_used_filaments); + m_time_processor.post_process(m_result.filename, m_result.moves, m_result.lines_ends, context); } #if ENABLE_GCODE_VIEWER_STATISTICS m_result.time = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - m_start_time).count(); diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index 45c25da..9691d85 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -6,6 +6,7 @@ #include "libslic3r/ExtrusionEntity.hpp" #include "libslic3r/PrintConfig.hpp" #include "libslic3r/CustomGCode.hpp" +#include "libslic3r/Extruder.hpp" #include #include @@ -285,6 +286,10 @@ namespace Slic3r { Total_Layer_Number_Placeholder, Wipe_Tower_Start, Wipe_Tower_End, + //1.9.7.52 + Used_Filament_Weight_Placeholder, + Used_Filament_Volume_Placeholder, + Used_Filament_Length_Placeholder }; static const std::string& reserved_tag(ETags tag) { return Reserved_Tags[static_cast(tag)]; } @@ -460,38 +465,6 @@ namespace Slic3r { void calculate_time(size_t keep_last_n_blocks = 0, float additional_time = 0.0f); }; - struct TimeProcessor - { - struct Planner - { - // Size of the firmware planner queue. The old 8-bit Marlins usually just managed 16 trapezoidal blocks. - // Let's be conservative and plan for newer boards with more memory. - static constexpr size_t queue_size = 64; - // The firmware recalculates last planner_queue_size trapezoidal blocks each time a new block is added. - // We are not simulating the firmware exactly, we calculate a sequence of blocks once a reasonable number of blocks accumulate. - static constexpr size_t refresh_threshold = queue_size * 4; - }; - - // extruder_id is currently used to correctly calculate filament load / unload times into the total print time. - // This is currently only really used by the MK3 MMU2: - // extruder_unloaded = true means no filament is loaded yet, all the filaments are parked in the MK3 MMU2 unit. - bool extruder_unloaded; - // allow to skip the lines M201/M203/M204/M205 generated by GCode::print_machine_envelope() for non-Normal time estimate mode - bool machine_envelope_processing_enabled; - MachineEnvelopeConfig machine_limits; - // Additional load / unload times for a filament exchange sequence. - float filament_load_times; - float filament_unload_times; - - std::array(PrintEstimatedStatistics::ETimeMode::Count)> machines; - - void reset(); - - // post process the file with the given filename to add remaining time lines M73 - // and updates moves' gcode ids accordingly - void post_process(const std::string& filename, std::vector& moves, std::vector& lines_ends, size_t total_layer_num); - }; - struct UsedFilaments // filaments per ColorChange { double color_change_cache; @@ -534,6 +507,49 @@ namespace Slic3r { friend class GCodeProcessor; }; + //1.9.7.52 + struct TimeProcessContext + { + size_t total_layer_num; + std::vector filament_lists; + UsedFilaments used_filaments; + TimeProcessContext( size_t total_layer_num_, + const std::vector& filament_lists_, + const UsedFilaments& used_filaments_) + :total_layer_num(total_layer_num_), filament_lists(filament_lists_), used_filaments(used_filaments_) {} + }; + + struct TimeProcessor + { + struct Planner + { + // Size of the firmware planner queue. The old 8-bit Marlins usually just managed 16 trapezoidal blocks. + // Let's be conservative and plan for newer boards with more memory. + static constexpr size_t queue_size = 64; + // The firmware recalculates last planner_queue_size trapezoidal blocks each time a new block is added. + // We are not simulating the firmware exactly, we calculate a sequence of blocks once a reasonable number of blocks accumulate. + static constexpr size_t refresh_threshold = queue_size * 4; + }; + + // extruder_id is currently used to correctly calculate filament load / unload times into the total print time. + // This is currently only really used by the MK3 MMU2: + // extruder_unloaded = true means no filament is loaded yet, all the filaments are parked in the MK3 MMU2 unit. + bool extruder_unloaded; + // allow to skip the lines M201/M203/M204/M205 generated by GCode::print_machine_envelope() for non-Normal time estimate mode + bool machine_envelope_processing_enabled; + MachineEnvelopeConfig machine_limits; + // Additional load / unload times for a filament exchange sequence. + float filament_load_times; + float filament_unload_times; + + std::array(PrintEstimatedStatistics::ETimeMode::Count)> machines; + + void reset(); + + // post process the file with the given filename to add remaining time lines M73 + // and updates moves' gcode ids accordingly + void post_process(const std::string& filename, std::vector& moves, std::vector& lines_ends, const TimeProcessContext& context); + }; public: class SeamsDetector { @@ -677,6 +693,8 @@ namespace Slic3r { bool m_flushing; bool m_wipe_tower; float m_remaining_volume; + //1.9.7.52 + std::vector m_filament_lists; //QDS: x, y offset for gcode generated double m_x_offset{ 0 }; @@ -750,6 +768,9 @@ namespace Slic3r { GCodeProcessor(); void apply_config(const PrintConfig& config); + //1.9.7.52 + void set_filaments(const std::vector&filament_lists) { m_filament_lists=filament_lists;} + void enable_stealth_time_estimator(bool enabled); bool is_stealth_time_estimator_enabled() const { return m_time_processor.machines[static_cast(PrintEstimatedStatistics::ETimeMode::Stealth)].enabled; diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index 30ad920..b4b590b 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include "libslic3r/AABBTreeLines.hpp" static const int overhang_sampling_number = 6; diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 03f6a44..7c397e5 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -559,7 +559,7 @@ void PrintConfigDef::init_fff_params() // Maximum extruder temperature, bumped to 1500 to support printing of glass. //w24 - const int max_temp = 350; + const int max_temp = 370; def = this->add("reduce_crossing_wall", coBool); def->label = L("Avoid crossing wall"); diff --git a/src/slic3r/GUI/CalibrationWizardPresetPage.cpp b/src/slic3r/GUI/CalibrationWizardPresetPage.cpp index 04039ef..b063f71 100644 --- a/src/slic3r/GUI/CalibrationWizardPresetPage.cpp +++ b/src/slic3r/GUI/CalibrationWizardPresetPage.cpp @@ -806,6 +806,9 @@ void CalibrationPresetPage::set_cali_method(CalibrationMethod method) m_cali_stage_panel->Show(false); if (m_custom_range_panel) { + wxArrayString values; + values.push_back(wxString::Format(wxT("%.0f"), 1.0)); + m_custom_range_panel->set_values(values); m_custom_range_panel->Show(false); } } diff --git a/src/slic3r/GUI/DeviceManager.cpp b/src/slic3r/GUI/DeviceManager.cpp index a804588..fa2be18 100644 --- a/src/slic3r/GUI/DeviceManager.cpp +++ b/src/slic3r/GUI/DeviceManager.cpp @@ -518,11 +518,12 @@ void MachineObject::reload_printer_settings() parse_json("{}"); } -// y21 -MachineObject::MachineObject(std::string name, std::string url, std::string ip) +// y40 +MachineObject::MachineObject(std::string name, std::string url, std::string ip, std::string apikey) :dev_name(name), dev_url(url), dev_ip(ip), + dev_apikey(apikey), subtask_(nullptr), model_task(nullptr), slice_info(nullptr), diff --git a/src/slic3r/GUI/DeviceManager.hpp b/src/slic3r/GUI/DeviceManager.hpp index 1c2c6f4..0003155 100644 --- a/src/slic3r/GUI/DeviceManager.hpp +++ b/src/slic3r/GUI/DeviceManager.hpp @@ -415,6 +415,7 @@ public: std::string dev_url; std::string dev_ip; std::string dev_id; + std::string dev_apikey; bool local_use_ssl_for_mqtt { true }; bool local_use_ssl_for_ftp { true }; float nozzle_diameter { 0.0f }; @@ -811,8 +812,8 @@ public: bool is_recording_enable(); bool is_recording(); - // y21 - MachineObject(std::string name, std::string url, std::string ip); + // y40 + MachineObject(std::string name, std::string url, std::string ip, std::string apikey = ""); MachineObject(NetworkAgent* agent, std::string name, std::string id, std::string ip); ~MachineObject(); diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index da0ad41..ad04293 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -4191,6 +4191,8 @@ void GCodeViewer::render_all_plates_stats(const std::vector flushed_volume_of_extruders_all_plates; // map std::map wipe_tower_volume_of_extruders_all_plates; // map std::map support_volume_of_extruders_all_plates; // map + //1.9.7.52 + std::map plate_time; // map std::vector model_used_filaments_m_all_plates; std::vector model_used_filaments_g_all_plates; std::vector flushed_filaments_m_all_plates; @@ -4201,6 +4203,8 @@ void GCodeViewer::render_all_plates_stats(const std::vector support_used_filaments_g_all_plates; float total_time_all_plates = 0.0f; float total_cost_all_plates = 0.0f; + //1.9.7.52 + double unit_conver = imperial_units ? GizmoObjectManipulation::oz_to_g : 1.0; struct ColumnData { enum { Model = 1, @@ -4236,13 +4240,15 @@ void GCodeViewer::render_all_plates_stats(const std::vector>& columns_offsets) + //1.9.7.52 + auto append_item = [icon_size, &imgui, imperial_units, &window_padding, &draw_list, this](bool draw_icon, const Color& color, const std::vector>& columns_offsets) { // render icon ImVec2 pos = ImVec2(ImGui::GetCursorScreenPos().x + window_padding * 3, ImGui::GetCursorScreenPos().y); - - draw_list->AddRectFilled({ pos.x + 1.0f * m_scale, pos.y + 3.0f * m_scale }, { pos.x + icon_size - 1.0f * m_scale, pos.y + icon_size + 1.0f * m_scale }, - ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f })); + //1.9.7.52 + if (draw_icon) + draw_list->AddRectFilled({ pos.x + 1.0f * m_scale, pos.y + 3.0f * m_scale }, { pos.x + icon_size - 1.0f * m_scale, pos.y + icon_size + 1.0f * m_scale }, + ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f })); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(20.0 * m_scale, 6.0 * m_scale)); @@ -4252,7 +4258,8 @@ void GCodeViewer::render_all_plates_stats(const std::vector(m_time_estimate_mode)]; + //1.9.7.52 + plate_time.insert_or_assign(plate->get_index(), plate_time_mode.time); total_time_all_plates += plate_time_mode.time; Print* print; @@ -4394,7 +4403,6 @@ void GCodeViewer::render_all_plates_stats(const std::vectorfirst + 1), offsets[_u8L("Filament")]}); char buf[64]; - double unit_conver = imperial_units ? GizmoObjectManipulation::oz_to_g : 1.0; float column_sum_m = 0.0f; float column_sum_g = 0.0f; @@ -4430,29 +4438,118 @@ void GCodeViewer::render_all_plates_stats(const std::vectorfirst], columns_offsets); + append_item(true, filament_colors[it->first], columns_offsets); } i++; } - ImGui::Dummy(ImVec2(0.0f, ImGui::GetFontSize() * 0.1)); - ImGui::Dummy({ window_padding, window_padding }); - ImGui::SameLine(); - imgui.title(_u8L("Total Estimation")); + //1.9.7.52 + // Sum of all rows + char buf[64]; + if (model_volume_of_extruders_all_plates.size() > 1) { + // Separator + ImGuiWindow *window = ImGui::GetCurrentWindow(); + const ImRect separator(ImVec2(window->Pos.x + window_padding * 3, window->DC.CursorPos.y), + ImVec2(window->Pos.x + window->Size.x - window_padding * 3, window->DC.CursorPos.y + 1.0f)); + ImGui::ItemSize(ImVec2(0.0f, 0.0f)); + const bool item_visible = ImGui::ItemAdd(separator, 0); + window->DrawList->AddLine(separator.Min, ImVec2(separator.Max.x, separator.Min.y), ImGui::GetColorU32(ImGuiCol_Separator)); - ImGui::Dummy({ window_padding, window_padding }); - ImGui::SameLine(); - imgui.text(_u8L("Total time") + ":"); - ImGui::SameLine(); - imgui.text(short_time(get_time_dhms(total_time_all_plates))); + std::vector> columns_offsets; + columns_offsets.push_back({_u8L("Total"), offsets[_u8L("Filament")]}); + double total_model_used_filament_m = 0; + double total_model_used_filament_g = 0; + double total_support_used_filament_m = 0; + double total_support_used_filament_g = 0; + double total_flushed_filament_m = 0; + double total_flushed_filament_g = 0; + double total_wipe_tower_used_filament_m = 0; + double total_wipe_tower_used_filament_g = 0; + if (displayed_columns & ColumnData::Model) { + std::for_each(model_used_filaments_m_all_plates.begin(), model_used_filaments_m_all_plates.end(), [&total_model_used_filament_m](double value) { + total_model_used_filament_m += value; + }); + std::for_each(model_used_filaments_g_all_plates.begin(), model_used_filaments_g_all_plates.end(), [&total_model_used_filament_g](double value) { + total_model_used_filament_g += value; + }); + if ((displayed_columns & ~ColumnData::Model) > 0) + ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", total_model_used_filament_m, total_model_used_filament_g / unit_conver); + else + ::sprintf(buf, imperial_units ? "%.2f in %.2f oz" : "%.2f m %.2f g", total_model_used_filament_m, total_model_used_filament_g / unit_conver); + columns_offsets.push_back({buf, offsets[_u8L("Model")]}); + } + if (displayed_columns & ColumnData::Support) { + std::for_each(model_used_filaments_m_all_plates.begin(), model_used_filaments_m_all_plates.end(), [&total_support_used_filament_m](double value) { + total_support_used_filament_m += value; + }); + std::for_each(model_used_filaments_g_all_plates.begin(), model_used_filaments_g_all_plates.end(), [&total_support_used_filament_g](double value) { + total_support_used_filament_g += value; + }); + ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", total_support_used_filament_m, total_support_used_filament_g / unit_conver); + columns_offsets.push_back({buf, offsets[_u8L("Support")]}); + } + if (displayed_columns & ColumnData::Flushed) { + std::for_each(flushed_filaments_m_all_plates.begin(), flushed_filaments_m_all_plates.end(), [&total_flushed_filament_m](double value) { + total_flushed_filament_m += value; + }); + std::for_each(flushed_filaments_g_all_plates.begin(), flushed_filaments_g_all_plates.end(), [&total_flushed_filament_g](double value) { + total_flushed_filament_g += value; + }); + ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", total_flushed_filament_m, total_flushed_filament_g / unit_conver); + columns_offsets.push_back({buf, offsets[_u8L("Flushed")]}); + } + if (displayed_columns & ColumnData::WipeTower) { + std::for_each(wipe_tower_used_filaments_m_all_plates.begin(), wipe_tower_used_filaments_m_all_plates.end(), [&total_wipe_tower_used_filament_m](double value) { + total_wipe_tower_used_filament_m += value; + }); + std::for_each(wipe_tower_used_filaments_g_all_plates.begin(), wipe_tower_used_filaments_g_all_plates.end(), [&total_wipe_tower_used_filament_g](double value) { + total_wipe_tower_used_filament_g += value; + }); + ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", total_wipe_tower_used_filament_m, total_wipe_tower_used_filament_g / unit_conver); + columns_offsets.push_back({buf, offsets[_u8L("Tower")]}); + } + if ((displayed_columns & ~ColumnData::Model) > 0) { + ::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", + total_model_used_filament_m + total_support_used_filament_m + total_flushed_filament_m + total_wipe_tower_used_filament_m, + (total_model_used_filament_g + total_support_used_filament_g + total_flushed_filament_g + total_wipe_tower_used_filament_g) / unit_conver); + columns_offsets.push_back({buf, offsets[_u8L("Total")]}); + } + append_item(false, m_tools.m_tool_colors[0], columns_offsets); + } ImGui::Dummy({ window_padding, window_padding }); ImGui::SameLine(); imgui.text(_u8L("Total cost") + ":"); ImGui::SameLine(); - char buf[64]; ::sprintf(buf, "%.2f", total_cost_all_plates); imgui.text(buf); + + //1.9.7.52 + ImGui::Dummy(ImVec2(0.0f, ImGui::GetFontSize() * 0.1)); + ImGui::Dummy({ window_padding, window_padding }); + ImGui::SameLine(); + imgui.title(_u8L("Time Estimation")); + + for (auto it = plate_time.begin(); it != plate_time.end(); it++) { + std::vector> columns_offsets; + columns_offsets.push_back({ _u8L("Plate") + " " + std::to_string(it->first), offsets[_u8L("Filament")]}); + columns_offsets.push_back({ short_time(get_time_dhms(it->second)), offsets[_u8L("Model")] }); + append_item(false, m_tools.m_tool_colors[0], columns_offsets); + } + + if (plate_time.size() > 1) { + // Separator + ImGuiWindow* window = ImGui::GetCurrentWindow(); + const ImRect separator(ImVec2(window->Pos.x + window_padding * 3, window->DC.CursorPos.y), + ImVec2(window->Pos.x + window->Size.x - window_padding * 3, window->DC.CursorPos.y + 1.0f)); + ImGui::ItemSize(ImVec2(0.0f, 0.0f)); + const bool item_visible = ImGui::ItemAdd(separator, 0); + window->DrawList->AddLine(separator.Min, ImVec2(separator.Max.x, separator.Min.y), ImGui::GetColorU32(ImGuiCol_Separator)); + std::vector> columns_offsets; + columns_offsets.push_back({ _u8L("Total"), offsets[_u8L("Filament")] }); + columns_offsets.push_back({ short_time(get_time_dhms(total_time_all_plates)), offsets[_u8L("Model")] }); + append_item(false, m_tools.m_tool_colors[0], columns_offsets); + } } ImGui::End(); ImGui::PopStyleColor(6); diff --git a/src/slic3r/GUI/MediaPlayCtrl.cpp b/src/slic3r/GUI/MediaPlayCtrl.cpp index 3591320..b31c892 100644 --- a/src/slic3r/GUI/MediaPlayCtrl.cpp +++ b/src/slic3r/GUI/MediaPlayCtrl.cpp @@ -60,7 +60,8 @@ MediaPlayCtrl::MediaPlayCtrl(wxWindow *parent, wxMediaCtrl2 *media_ctrl, const w m_media_ctrl->Bind(EVT_MEDIA_CTRL_STAT, [this](auto & e) { #if !QDT_RELEASE_TO_PUBLIC wxSize size = m_media_ctrl->GetVideoSize(); - m_label_stat->SetLabel(e.GetString() + wxString::Format(" VS:%ix%i", size.x, size.y)); + //1.9.7.52 + m_label_stat->SetLabel(e.GetString() + wxString::Format(" VS:%ix%i LD:%i", size.x, size.y, m_load_duration)); #endif wxString str = e.GetString(); m_stat.clear(); @@ -182,10 +183,27 @@ void MediaPlayCtrl::SetMachineObject(MachineObject* obj) agent->get_camera_url(machine, [](auto) {}); m_last_user_play = wxDateTime::Now(); } - //1.9.5 - if (m_last_state == wxMediaState::wxMEDIASTATE_PLAYING && SecondsSinceLastInput() > 900) { // 15 minutes - m_next_retry = wxDateTime(); - Stop(_L("Temporarily closed because there is no operating for a long time.")); + //1.9.7.52 + if (m_last_state == wxMediaState::wxMEDIASTATE_PLAYING) { + auto now = std::chrono::system_clock::now(); + if (m_play_timer <= now) { + m_play_timer = now + 1min; + if (SecondsSinceLastInput() >= 900) { // 15 min + auto close = wxGetApp().app_config->get("liveview", "auto_stop_liveview") == "true"; + if (close) { + m_next_retry = wxDateTime(); + Stop(_L("Temporarily closed because there is no operating for a long time.")); + return; + } + } + auto obj = wxGetApp().getDeviceManager()->get_selected_machine(); + if (obj && obj->is_in_printing()) { + m_print_idle = 0; + } else if (++m_print_idle >= 5) { + m_next_retry = wxDateTime(); + Stop(_L("Temporarily closed because there is no printing for a while.")); + } + } } return; } @@ -324,6 +342,7 @@ void MediaPlayCtrl::Play() m_label_stat->SetLabel({}); SetStatus(_L("Initializing...")); + m_play_timer = std::chrono::system_clock::now(); if (agent) { agent->get_camera_url(m_machine, @@ -389,7 +408,7 @@ void MediaPlayCtrl::Stop(wxString const &msg) #endif SetStatus(msg2); } else - SetStatus(_L("Stopped."), false); + SetStatus(_L("Video Stopped."), false); m_last_state = MEDIASTATE_IDLE; bool auto_retry = wxGetApp().app_config->get("liveview", "auto_retry") != "false"; if (!auto_retry || m_failed_code >= 100 || m_failed_code == 1) // not keep retry on local error or EOS @@ -628,7 +647,12 @@ void MediaPlayCtrl::onStateChanged(wxMediaEvent &event) m_last_state = state; m_failed_code = 0; SetStatus(_L("Playing..."), false); - + //1.9.7.52 + m_print_idle = 0; + auto now = std::chrono::system_clock::now(); + m_load_duration = std::chrono::duration_cast(now - m_play_timer).count(); + m_play_timer = now + 1min; + // track event json j; j["stage"] = std::to_string(m_last_state); diff --git a/src/slic3r/GUI/MediaPlayCtrl.h b/src/slic3r/GUI/MediaPlayCtrl.h index 8593a88..b431ef4 100644 --- a/src/slic3r/GUI/MediaPlayCtrl.h +++ b/src/slic3r/GUI/MediaPlayCtrl.h @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -102,7 +103,11 @@ private: std::set m_last_failed_codes; wxDateTime m_last_user_play; wxDateTime m_next_retry; - + //1.9.7.52 + std::chrono::system_clock::time_point m_play_timer; + int m_print_idle = 0; + int m_load_duration = 0; + ::Button *m_button_play; ::Label * m_label_stat; ::Label * m_label_status; diff --git a/src/slic3r/GUI/NotificationManager.cpp b/src/slic3r/GUI/NotificationManager.cpp index 5d52165..af99dba 100644 --- a/src/slic3r/GUI/NotificationManager.cpp +++ b/src/slic3r/GUI/NotificationManager.cpp @@ -2552,19 +2552,10 @@ void NotificationManager::qdt_close_preview_only_notification() } } -void NotificationManager::qdt_show_objectsinfo_notification(const std::string &text, bool is_warning, bool is_hidden) +//1.9.7.52 +void NotificationManager::qdt_show_objectsinfo_notification(const std::string &text, bool is_warning, bool is_hidden, const std::string hypertext, std::function callback) { - std::string hyper_text; - auto callback = std::function(); - if (is_warning) { - callback =[](wxEvtHandler *) { - wxCommandEvent *evt = new wxCommandEvent(EVT_REPAIR_MODEL); - wxQueueEvent(wxGetApp().plater(), evt); - return false; - }; - hyper_text = _u8L(" (Repair)"); - } - NotificationData data{NotificationType::QDTObjectInfo, NotificationLevel::PrintInfoNotificationLevel, QDT_NOTICE_MAX_INTERVAL, text, hyper_text, callback}; + NotificationData data{NotificationType::QDTObjectInfo, NotificationLevel::PrintInfoNotificationLevel, QDT_NOTICE_MAX_INTERVAL, text, hypertext, callback}; if (is_warning) data.use_warn_color = true; diff --git a/src/slic3r/GUI/NotificationManager.hpp b/src/slic3r/GUI/NotificationManager.hpp index 1a858b3..a5071f5 100644 --- a/src/slic3r/GUI/NotificationManager.hpp +++ b/src/slic3r/GUI/NotificationManager.hpp @@ -315,7 +315,9 @@ public: void qdt_close_plugin_install_notification(); //QDS--Objects Info - void qdt_show_objectsinfo_notification(const std::string &text, bool is_warning, bool is_hidden); + //1.9.7.52 + void qdt_show_objectsinfo_notification(const std::string &text, bool is_warning, bool is_hidden, + const std::string hypertext = "", std::function callback = std::function()); void qdt_close_objectsinfo_notification(); void qdt_show_seqprintinfo_notification(const std::string &text); diff --git a/src/slic3r/GUI/PhysicalPrinterDialog.cpp b/src/slic3r/GUI/PhysicalPrinterDialog.cpp index a1cf5f8..e63bd41 100644 --- a/src/slic3r/GUI/PhysicalPrinterDialog.cpp +++ b/src/slic3r/GUI/PhysicalPrinterDialog.cpp @@ -117,10 +117,17 @@ PhysicalPrinterDialog::PhysicalPrinterDialog(wxWindow* parent, wxString printer_ m_printer = PhysicalPrinter("Default Name", m_printer.config, sel_preset); m_config = &m_printer.config; + //y40 if (printer) + { m_config->set_key_value("print_host", new ConfigOptionString(printer->config.opt_string("print_host"))); + m_config->set_key_value("printhost_apikey", new ConfigOptionString(printer->config.opt_string("printhost_apikey"))); + } else + { m_config->set_key_value("print_host", new ConfigOptionString("")); + m_config->set_key_value("printhost_apikey", new ConfigOptionString("")); + } m_optgroup = new ConfigOptionsGroup(this, _L("Print Host upload"), m_config); auto button_sizer = new wxBoxSizer(wxHORIZONTAL); @@ -248,6 +255,11 @@ void PhysicalPrinterDialog::build_printhost_settings(ConfigOptionsGroup* m_optgr host_line.append_widget(print_host_test); m_optgroup->append_line(host_line); + //y40 + option = m_optgroup->get_option("printhost_apikey"); + option.opt.width = 15; + m_optgroup->append_single_option_line(option); + m_optgroup->activate(); Field* printhost_field = m_optgroup->get_field("print_host"); @@ -488,10 +500,12 @@ void PhysicalPrinterDialog::OnOK(wxMouseEvent& event) // y3 m_printer_name = into_u8(m_input_ctrl->GetValue()); m_printer_host = boost::any_cast(m_optgroup->get_field("print_host")->get_value()); + std::string m_apikey = boost::any_cast(m_optgroup->get_field("printhost_apikey")->get_value()); m_config->set_key_value("name", new ConfigOptionString(into_u8(m_input_ctrl->GetValue()))); m_config->set_key_value("preset_name", new ConfigOptionString(into_u8(pret_combobox->GetValue()))); m_config->set_key_value("preset_names", new ConfigOptionString(into_u8(pret_combobox->GetValue()))); m_config->set_key_value("print_host", new ConfigOptionString(m_printer_host)); + m_config->set_key_value("printhost_apikey", new ConfigOptionString(m_apikey)); PhysicalPrinterCollection& printers = wxGetApp().preset_bundle->physical_printers; m_printer.set_name(m_printer_name); if(!old_name.empty()) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 1116c4d..886834c 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1307,8 +1307,23 @@ void Sidebar::update_all_preset_comboboxes() cb->update(); } - if (p->combo_printer) + //w13 + if (p->combo_printer) { p->combo_printer->update(); + bool get_seal_status =wxGetApp().enable_seal(); + auto print_config = &wxGetApp().preset_bundle->printers.get_edited_preset().config; + AppConfig* config = wxGetApp().app_config; + if (get_seal_status) { + print_config->set_key_value("seal", new ConfigOptionBool(true)); + config->set_seal(true); + wxGetApp().set_seal_an(true); + } + else { + print_config->set_key_value("seal", new ConfigOptionBool(false)); + config->set_seal(false); + wxGetApp().set_seal_an(false); + } + } } void Sidebar::update_presets(Preset::Type preset_type) @@ -1830,7 +1845,8 @@ void Sidebar::sync_ams_list() add_button(wxID_OK, true, _L("Sync")); add_button(wxID_YES, false, _L("Resync")); } - add_button(wxID_CANCEL, false, _L("Cancel")); + //1.9.7.52 + add_button(wxID_CANCEL, false, _L("No")); } } dlg(this, ams_filament_ids.empty()); auto res = dlg.ShowModal(); @@ -7095,22 +7111,37 @@ void Plater::priv::on_action_print_plate(SimpleEvent&) } //QDS - //y30 + //y40 wxString title = "Send print job to"; SelectMachineDialog* dlg = new SelectMachineDialog(q, title); if (dlg->ShowModal() == wxID_YES) { std::string send_ip = dlg->get_machine_url(); std::string show_ip = dlg->get_machine_ip(); - PrintHostJob upload_job(send_ip, show_ip); + std::string send_apikey = dlg->get_machine_apikey(); std::string project_name = dlg->get_project_name(); if (project_name.find(".gcode") == std::string::npos) { project_name += ".gcode"; } - upload_job.upload_data.upload_path = project_name; - upload_job.upload_data.post_action = PrintHostPostUploadAction::StartPrint; - export_gcode(fs::path(), false, std::move(upload_job)); + if (send_apikey.empty()) + { + PrintHostJob upload_job(send_ip, show_ip); + upload_job.upload_data.upload_path = project_name; + upload_job.upload_data.post_action = PrintHostPostUploadAction::StartPrint; + export_gcode(fs::path(), false, std::move(upload_job)); + } + else + { + DynamicPrintConfig cfg_t; + cfg_t.set_key_value("print_host", new ConfigOptionString(send_ip)); + cfg_t.set_key_value("host_type", new ConfigOptionString("ptfff")); + cfg_t.set_key_value("printhost_apikey", new ConfigOptionString(send_apikey)); + PrintHostJob upload_job(&cfg_t); + upload_job.upload_data.upload_path = project_name; + upload_job.upload_data.post_action = PrintHostPostUploadAction::StartPrint; + export_gcode(fs::path(), false, std::move(upload_job)); + } } //if (!m_select_machine_dlg) m_select_machine_dlg = new SelectMachineDialog(q); //m_select_machine_dlg->set_print_type(PrintFromType::FROM_NORMAL); @@ -7122,7 +7153,7 @@ void Plater::priv::on_action_print_plate(SimpleEvent&) void Plater::priv::on_action_send_to_multi_machine(SimpleEvent&) { - // y21 + //y40 // if (!m_send_multi_dlg) // m_send_multi_dlg = new SendMultiMachinePage(q); // m_send_multi_dlg->prepare(partplate_list.get_curr_plate_index()); @@ -7139,29 +7170,55 @@ void Plater::priv::on_action_send_to_multi_machine(SimpleEvent&) std::map> send_machine_info = m_send_multi_dlg->get_selected_machine_info(); for (auto it = send_machine_info.begin(); it != send_machine_info.end(); it++) { - std::string send_ip = it->second[0]; - std::string show_ip = it->second[1]; - PrintHostJob upload_job(send_ip, show_ip); - if (project_name.find(".gcode") == std::string::npos) { project_name += ".gcode"; } - upload_job.upload_data.upload_path = project_name; - upload_job.upload_data.post_action = PrintHostPostUploadAction::None; - upload_job.create_time = std::chrono::system_clock::now(); - if (diff.count() < 0) - upload_job.sendinginterval = count / std::stoi(wxGetApp().app_config->get("max_send")) * - std::stoi(wxGetApp().app_config->get("sending_interval")) * 60 - - diff.count() + 4; - else - upload_job.sendinginterval = count / std::stoi(wxGetApp().app_config->get("max_send")) * - std::stoi(wxGetApp().app_config->get("sending_interval")) * 60; - std::chrono::seconds seconds_to_add(upload_job.sendinginterval); + std::string send_ip = it->second[0]; + std::string show_ip = it->second[1]; + std::string apikey = it->second[2]; + if (apikey.empty()) + { + PrintHostJob upload_job(send_ip, show_ip); + upload_job.upload_data.upload_path = project_name; + upload_job.upload_data.post_action = PrintHostPostUploadAction::None; + upload_job.create_time = std::chrono::system_clock::now(); + if (diff.count() < 0) + upload_job.sendinginterval = count / std::stoi(wxGetApp().app_config->get("max_send")) * + std::stoi(wxGetApp().app_config->get("sending_interval")) * 60 - + diff.count() + 4; + else + upload_job.sendinginterval = count / std::stoi(wxGetApp().app_config->get("max_send")) * + std::stoi(wxGetApp().app_config->get("sending_interval")) * 60; + std::chrono::seconds seconds_to_add(upload_job.sendinginterval); - m_time_p = upload_job.create_time + seconds_to_add; - export_gcode(fs::path(), false, std::move(upload_job)); - count++; + m_time_p = upload_job.create_time + seconds_to_add; + export_gcode(fs::path(), false, std::move(upload_job)); + count++; + } + else + { + DynamicPrintConfig cfg_t; + cfg_t.set_key_value("print_host", new ConfigOptionString(send_ip)); + cfg_t.set_key_value("host_type", new ConfigOptionString("ptfff")); + cfg_t.set_key_value("printhost_apikey", new ConfigOptionString(apikey)); + PrintHostJob upload_job(&cfg_t); + upload_job.upload_data.upload_path = project_name; + upload_job.upload_data.post_action = PrintHostPostUploadAction::None; + upload_job.create_time = std::chrono::system_clock::now(); + if (diff.count() < 0) + upload_job.sendinginterval = count / std::stoi(wxGetApp().app_config->get("max_send")) * + std::stoi(wxGetApp().app_config->get("sending_interval")) * 60 - + diff.count() + 4; + else + upload_job.sendinginterval = count / std::stoi(wxGetApp().app_config->get("max_send")) * + std::stoi(wxGetApp().app_config->get("sending_interval")) * 60; + std::chrono::seconds seconds_to_add(upload_job.sendinginterval); + + m_time_p = upload_job.create_time + seconds_to_add; + export_gcode(fs::path(), false, std::move(upload_job)); + count++; + } } } } @@ -7277,22 +7334,38 @@ void Plater::priv::on_action_export_to_sdcard(SimpleEvent&) // BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ":received export sliced file event\n"; // q->send_to_printer(); // } - //y30 + //y40 wxString title = "Send to Printer SD card"; SelectMachineDialog* dlg = new SelectMachineDialog(q, title); if (dlg->ShowModal() == wxID_YES) { std::string send_ip = dlg->get_machine_url(); std::string show_ip = dlg->get_machine_ip(); - PrintHostJob upload_job(send_ip, show_ip); + std::string send_apikey = dlg->get_machine_apikey(); std::string project_name = dlg->get_project_name(); if (project_name.find(".gcode") == std::string::npos) { project_name += ".gcode"; } - upload_job.upload_data.upload_path = project_name; - upload_job.upload_data.post_action = PrintHostPostUploadAction::None; - export_gcode(fs::path(), false, std::move(upload_job)); + if (send_apikey.empty()) + { + PrintHostJob upload_job(send_ip, show_ip); + upload_job.upload_data.upload_path = project_name; + upload_job.upload_data.post_action = PrintHostPostUploadAction::None; + export_gcode(fs::path(), false, std::move(upload_job)); + } + else + { + DynamicPrintConfig cfg_t; + cfg_t.set_key_value("print_host", new ConfigOptionString(send_ip)); + cfg_t.set_key_value("host_type", new ConfigOptionString("ptfff")); + cfg_t.set_key_value("printhost_apikey", new ConfigOptionString(send_apikey)); + PrintHostJob upload_job(&cfg_t); + upload_job.upload_data.upload_path = project_name; + upload_job.upload_data.post_action = PrintHostPostUploadAction::None; + export_gcode(fs::path(), false, std::move(upload_job)); + } + } } @@ -8240,6 +8313,8 @@ void Plater::priv::on_create_filament(SimpleEvent &) CreatePresetSuccessfulDialog success_dlg(wxGetApp().mainframe, SuccessType::FILAMENT); int res = success_dlg.ShowModal(); } + //1.9.7.52 + wxGetApp().run_wizard(ConfigWizard::RR_USER, ConfigWizard::SP_FILAMENTS); } void Plater::priv::on_modify_filament(SimpleEvent &evt) @@ -8267,7 +8342,8 @@ void Plater::priv::on_modify_filament(SimpleEvent &evt) tab->select_preset(need_edit_preset->name); // when some preset have modified, if the printer is not need_edit_preset_name compatible printer, the preset will jump to other preset, need select again if (!need_edit_preset->is_compatible) tab->select_preset(need_edit_preset->name); - } + } else + wxGetApp().run_wizard(ConfigWizard::RR_USER, ConfigWizard::SP_FILAMENTS); //1.9.7.52 } @@ -13032,7 +13108,7 @@ int Plater::send_gcode(int plate_idx, Export3mfProgressFn proFn) return -1; } - SaveStrategy strategy = SaveStrategy::Silence | SaveStrategy::SkipModel | SaveStrategy::WithGcode; + SaveStrategy strategy = SaveStrategy::Silence | SaveStrategy::SkipModel | SaveStrategy::WithGcode | SaveStrategy::SkipAuxiliary; //1.9.7.52 #if !QDT_RELEASE_TO_PUBLIC //only save model in QA environment std::string sel = get_app_config()->get("iot_environment"); @@ -14531,16 +14607,38 @@ void Plater::show_object_info() wxString info_manifold; int non_manifold_edges = 0; auto mesh_errors = p->sidebar->obj_list()->get_mesh_errors_info(&info_manifold, &non_manifold_edges); + //1.9.7.52 + bool warning = non_manifold_edges > 0; + wxString hyper_text; + std::function callback; + if (warning) { + hyper_text = _L(" (Repair)"); + callback = [](wxEvtHandler*) { + wxCommandEvent* evt = new wxCommandEvent(EVT_REPAIR_MODEL); + wxQueueEvent(wxGetApp().plater(), evt); + return false; + }; + } #ifndef __WINDOWS__ if (non_manifold_edges > 0) { - info_manifold += into_u8("\n" + _L("Tips:") + "\n" +_L("\"Fix Model\" feature is currently only on Windows. Please repair the model on QIDI Studio(windows) or CAD softwares.")); + //1.9.7.52 + info_manifold += into_u8("\n" + _L("Tips:") + "\n" +_L("\"Fix Model\" feature is currently only on Windows. Please use a third-party tool to repair the model before importing it into QIDI Studio, such as ")); + } + if (warning) { + std::string repair_url = "https://www.formware.co/onlinestlrepair"; + hyper_text = repair_url + "."; + callback = [repair_url](wxEvtHandler*) { + wxGetApp().open_browser_with_warning_dialog(repair_url); + return false; + }; } #endif //APPLE & LINUX info_manifold = "" + info_manifold + ""; info_text += into_u8(info_manifold); - notify_manager->qdt_show_objectsinfo_notification(info_text, is_windows10()&&(non_manifold_edges > 0), !(p->current_panel == p->view3D)); + //1.9.7.52 + notify_manager->qdt_show_objectsinfo_notification(info_text, warning, !(p->current_panel == p->view3D), into_u8(hyper_text), callback); } bool Plater::show_publish_dialog(bool show) diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index 1795668..18ffada 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -167,6 +167,10 @@ wxBoxSizer *PreferencesDialog::create_item_language_combobox( else if (vlist[i] == wxLocale::GetLanguageInfo(wxLANGUAGE_TURKISH)) { language_name = wxString::FromUTF8("\x54\xC3\xBC\x72\x6B\xC3\xA7\x65"); } + //1.9.7.52 + else if (vlist[i] == wxLocale::GetLanguageInfo(wxLANGUAGE_POLISH)) { + language_name = wxString::FromUTF8("Polski"); + } if (language == vlist[i]->CanonicalName) { m_current_language_selected = i; @@ -631,8 +635,9 @@ wxBoxSizer *PreferencesDialog::create_item_checkbox(wxString title, wxWindow *pa //ZY2 /*if (param == "privacyuse") { checkbox->SetValue((app_config->get("firstguide", param) == "true") ? true : false); - } - else { + } else if (param == "auto_stop_liveview") { + checkbox->SetValue((app_config->get("liveview", param) == "true") ? false : true); + } else { checkbox->SetValue((app_config->get(param) == "true") ? true : false); }*/ checkbox->SetValue((app_config->get(param) == "true") ? true : false); @@ -664,6 +669,9 @@ wxBoxSizer *PreferencesDialog::create_item_checkbox(wxString title, wxWindow *pa } app_config->save(); } + else if (param == "auto_stop_liveview") { + app_config->set("liveview", param, !checkbox->GetValue()); + } else { app_config->set_bool(param, checkbox->GetValue()); app_config->save(); @@ -1000,7 +1008,8 @@ wxWindow* PreferencesDialog::create_general_page() wxLANGUAGE_CZECH, wxLANGUAGE_UKRAINIAN, wxLANGUAGE_PORTUGUESE_BRAZILIAN, - wxLANGUAGE_TURKISH + wxLANGUAGE_TURKISH, + wxLANGUAGE_POLISH }; auto translations = wxTranslations::Get()->GetAvailableTranslations(SLIC3R_APP_KEY); @@ -1084,8 +1093,9 @@ wxWindow* PreferencesDialog::create_general_page() auto item_backup_interval = create_item_backup_input(_L("every"), page, _L("The peroid of backup in seconds."), "backup_interval"); //downloads - auto title_downloads = create_item_title(_L("Downloads"), page, _L("Downloads")); + auto title_media = create_item_title(_L("Media"), page, _L("Media")); auto item_downloads = create_item_downloads(page,50,"download_path"); + // auto item_auto_stop_liveview = create_item_checkbox(_L("Keep liveview when printing."), page, _L("By default, Liveview will pause after 15 minutes of inactivity on the computer. Check this box to disable this feature during printing."), 50, "auto_stop_liveview"); //dark mode #ifdef _WIN32 @@ -1147,8 +1157,9 @@ wxWindow* PreferencesDialog::create_general_page() sizer_page->Add(item_backup, 0, wxTOP,FromDIP(3)); item_backup->Add(item_backup_interval, 0, wxLEFT, 0); - sizer_page->Add(title_downloads, 0, wxTOP| wxEXPAND, FromDIP(20)); + sizer_page->Add(title_media, 0, wxTOP| wxEXPAND, FromDIP(20)); sizer_page->Add(item_downloads, 0, wxEXPAND, FromDIP(3)); + // sizer_page->Add(item_auto_stop_liveview, 0, wxEXPAND, FromDIP(3)); #ifdef _WIN32 sizer_page->Add(title_darkmode, 0, wxTOP | wxEXPAND, FromDIP(20)); diff --git a/src/slic3r/GUI/PrintHostDialogs.cpp b/src/slic3r/GUI/PrintHostDialogs.cpp index 47606fb..956d8c5 100644 --- a/src/slic3r/GUI/PrintHostDialogs.cpp +++ b/src/slic3r/GUI/PrintHostDialogs.cpp @@ -441,18 +441,19 @@ void PrintHostQueueDialog::on_error(Event &evt) set_state(evt.job_id, ST_ERROR); std::string response_msg = into_u8(evt.error); - size_t pos_404 = evt.error.find("HTTP 404:"); wxString code_msg = ""; - if (pos_404 != std::string::npos) { - code_msg = _L("Network connection fails."); + //y40 + if (response_msg.find("HTTP 404:") != std::string::npos) { size_t isAws = response_msg.find("AWS"); - if(isAws != std::string::npos) - code_msg += _L("HTTP 404. Unable to get required resources from AWS server, please check your network settings."); + if (isAws != std::string::npos) + code_msg = _L("HTTP 404. Unable to get required resources from AWS server, please check your network settings."); else - code_msg += _L("HTTP 404. Unable to get required resources from Aliyun server, please check your network settings."); - } + code_msg = _L("HTTP 404. Unable to get required resources from Aliyun server, please check your network settings."); + } + else if (response_msg.find("HTTP 401:") != std::string::npos) + code_msg = _L("HTTP 401: Unauthorized. Please check whether your physical printer has added users. If a user exists, add the APIKEY when adding/editing the printer."); else - code_msg = _L("Network connection times out. Please check the device network Settings."); + code_msg = response_msg; auto errormsg = format_wxstr("%1%\n%2%", _L("Error uploading to print host") + ":", code_msg); 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 diff --git a/src/slic3r/GUI/Printer/PrinterFileSystem.cpp b/src/slic3r/GUI/Printer/PrinterFileSystem.cpp index 6d0f803..6ea6735 100644 --- a/src/slic3r/GUI/Printer/PrinterFileSystem.cpp +++ b/src/slic3r/GUI/Printer/PrinterFileSystem.cpp @@ -1239,6 +1239,9 @@ void PrinterFileSystem::Reconnect(boost::unique_lock &l, int resul if (c) c(result, r, nullptr); } m_messages.clear(); + //1.9.7.52 + if (result) + m_cond.timed_wait(l, boost::posix_time::seconds(10)); while (true) { while (m_stopped) { if (m_session.owner == nullptr) diff --git a/src/slic3r/GUI/PrinterWebView.cpp b/src/slic3r/GUI/PrinterWebView.cpp index 2d40cd8..0ad6276 100644 --- a/src/slic3r/GUI/PrinterWebView.cpp +++ b/src/slic3r/GUI/PrinterWebView.cpp @@ -287,14 +287,12 @@ wxBoxSizer *PrinterWebView::init_menu_bar(wxPanel *Panel) if (m_pauseThread) break; - BOOST_LOG_TRIVIAL(error) << "machine IP: " << (button->getIPLabel()); std::string printer_host = button->getIPLabel().ToStdString(); - if (printer_host.find(":10088") == std::string::npos) - printer_host += "10088"; DynamicPrintConfig cfg_t; cfg_t.set_key_value("print_host", new ConfigOptionString(printer_host)); cfg_t.set_key_value("host_type", new ConfigOptionString("ptfff")); + cfg_t.set_key_value("printhost_apikey", new ConfigOptionString(into_u8(button->GetApikey()))); std::unique_ptr printhost(PrintHost::get_print_host(&cfg_t)); if (!printhost) { BOOST_LOG_TRIVIAL(error) << ("Could not get a valid Printer Host reference"); @@ -303,13 +301,14 @@ wxBoxSizer *PrinterWebView::init_menu_bar(wxPanel *Panel) wxString msg; std::string state = "standby"; float progress = 0; - state = printhost->get_status(msg, into_u8(button->getNameLabel()), button->getIPLabel()); + std::pair state_progress = printhost->get_status_progress(msg); + state = state_progress.first; if ((button->GetStateText()).ToStdString() != state) button->SetStateText(state); if (state == "printing") { - progress = (printhost->get_progress(msg, into_u8(button->getNameLabel()), button->getIPLabel())) * 100; + progress = state_progress.second * 100; int progressInt = static_cast(progress); button->SetProgressText(wxString::Format(wxT("(%d%%)"), progressInt)); } @@ -324,10 +323,7 @@ wxBoxSizer *PrinterWebView::init_menu_bar(wxPanel *Panel) break; if (!m_net_buttons.empty()) { BOOST_LOG_TRIVIAL(error) << "machine IP: " << device.local_ip; - DynamicPrintConfig cfg_t; - cfg_t.set_key_value("print_host", new ConfigOptionString(device.url)); - cfg_t.set_key_value("host_type", new ConfigOptionString("ptfff")); - std::unique_ptr printhost(PrintHost::get_print_host(&cfg_t)); + std::unique_ptr printhost(PrintHost::get_print_host_url(device.url, device.local_ip)); if (!printhost) { BOOST_LOG_TRIVIAL(error) << ("Could not get a valid Printer Host reference"); return; @@ -335,14 +331,14 @@ wxBoxSizer *PrinterWebView::init_menu_bar(wxPanel *Panel) wxString msg; std::string state = "standby"; float progress = 0; - //y34 - state = printhost->get_status(msg, device.device_name, device.url); + std::pair state_progress = printhost->get_status_progress(msg); + state = state_progress.first; BOOST_LOG_TRIVIAL(error) << ("State:", state); if ((m_net_buttons[count]->GetStateText()).ToStdString() != state) m_net_buttons[count]->SetStateText(state); if (state == "printing") { - progress = (printhost->get_progress(msg, device.device_name, device.url)) * 100; + progress = state_progress.second * 100; int progressInt = static_cast(progress); m_net_buttons[count]->SetProgressText(wxString::Format(wxT("(%d%%)"), progressInt)); } @@ -372,6 +368,7 @@ wxBoxSizer *PrinterWebView::init_menu_bar(wxPanel *Panel) std::string actice_url = ""; for (PhysicalPrinterCollection::ConstIterator it = ph_printers.begin(); it != ph_printers.end(); ++it) { std::string host = (it->config.opt_string("print_host")); + std::string apikey = (it->config.opt_string("printhost_apikey")); std::string preset_name = (it->config.opt_string("preset_name")); bool isQIDI_printer = false; if (qidi_printers.find(preset_name) != qidi_printers.end()) @@ -404,7 +401,7 @@ wxBoxSizer *PrinterWebView::init_menu_bar(wxPanel *Panel) //BOOST_LOG_TRIVIAL(error) << (it->get_preset_name(full_name)); //BOOST_LOG_TRIVIAL(error) << model_id; AddButton((it->get_short_name(full_name)), host, model_id, full_name, is_selected, - (host_type == htOctoPrint)); + (host_type == htOctoPrint), apikey); m_machine.insert(std::make_pair((it->get_short_name(full_name)), *cfg_t)); //y25 m_exit_host.insert(host); @@ -418,31 +415,26 @@ wxBoxSizer *PrinterWebView::init_menu_bar(wxPanel *Panel) #endif CreatThread(); } - //y23 //y28 //y31 + //y40 + if(m_isNetMode) + ShowNetPrinterButton(); + else + ShowLocalPrinterButton(); + if (webisNetMode == isNetWeb) { - ShowNetPrinterButton(); for (DeviceButton* button : m_net_buttons) { if (button->getIPLabel().find(m_ip) != std::string::npos) { button->SetIsSelected(true); - wxCommandEvent event(wxEVT_BUTTON, button->GetId()); - wxPostEvent(button, event); break; } } - toggleBar->SetValue(true); - m_isNetMode = true; - wxGetApp().app_config->set("machine_list_net", "1"); } else if (webisNetMode == isLocalWeb) { - ShowLocalPrinterButton(); for (DeviceButton* button : m_buttons) { if (button->getIPLabel().find(m_ip) != std::string::npos) { button->SetIsSelected(true); break; } } - toggleBar->SetValue(false); - m_isNetMode = false; - wxGetApp().app_config->set("machine_list_net", "0"); } else { @@ -450,7 +442,6 @@ wxBoxSizer *PrinterWebView::init_menu_bar(wxPanel *Panel) if (m_isNetMode) { //y30 - ShowNetPrinterButton(); wxString url = wxString::Format("file://%s/web/qidi/link_missing_connection.html", from_u8(resources_dir())); if(strlang != "") url = wxString::Format("file://%s/web/qidi/link_missing_connection.html?lang=%s", from_u8(resources_dir()), strlang); @@ -458,7 +449,6 @@ wxBoxSizer *PrinterWebView::init_menu_bar(wxPanel *Panel) } else { - ShowLocalPrinterButton(); //y30 wxString url = wxString::Format("file://%s/web/qidi/missing_connection.html", from_u8(resources_dir())); if (strlang != "") @@ -517,7 +507,8 @@ wxBoxSizer *PrinterWebView::init_menu_bar(wxPanel *Panel) const wxString & machine_type, const wxString & fullname, bool isSelected, - bool isQIDI) + bool isQIDI, + const wxString& apikey) { wxString Machine_Name = Machine_Name.Format("%s%s", machine_type, "_thumbnail"); @@ -525,7 +516,7 @@ wxBoxSizer *PrinterWebView::init_menu_bar(wxPanel *Panel) std::pair(wxColour(76, 76, 80), StateColor::Hovered), std::pair(wxColour(67, 67, 71), StateColor::Normal)); - DeviceButton *machine_button = new DeviceButton(leftScrolledWindow, fullname, Machine_Name, wxBU_LEFT, wxSize(80, 80), device_name, ip); + DeviceButton *machine_button = new DeviceButton(leftScrolledWindow, fullname, Machine_Name, wxBU_LEFT, wxSize(80, 80), device_name, ip, apikey); machine_button->SetBackgroundColor(mac_btn_bg); machine_button->SetBorderColor(wxColour(57, 51, 55)); machine_button->SetCanFocus(false); @@ -618,31 +609,38 @@ wxBoxSizer *PrinterWebView::init_menu_bar(wxPanel *Panel) device_name, device.local_ip); machine_button->SetBackgroundColor(mac_btn_bg); + machine_button->SetBorderColor(wxColour(57, 51, 55)); machine_button->SetCanFocus(false); machine_button->SetIsSimpleMode(m_isSimpleMode); machine_button->Bind(wxEVT_BUTTON, [this, device](wxCommandEvent &event) { - //y34 //y35 std::string formattedHost; - if(wxGetApp().app_config->get("dark_color_mode") == "1") - formattedHost = device.link_url + "&theme=dark"; - else - formattedHost = device.link_url + "&theme=light"; - - std::string formattedHost1 = "http://fluidd_" + formattedHost; - std::string formattedHost2 = "http://fluidd2_" + formattedHost; - if (formattedHost1 == m_web || formattedHost2 == m_web) - return; - - if (m_isfluidd_1) + if (device.isSpecialMachine) { - formattedHost = "http://fluidd_" + formattedHost; - m_isfluidd_1 = false; + if(wxGetApp().app_config->get("dark_color_mode") == "1") + formattedHost = device.link_url + "&theme=dark"; + else + formattedHost = device.link_url + "&theme=light"; + + std::string formattedHost1 = "http://fluidd_" + formattedHost; + std::string formattedHost2 = "http://fluidd2_" + formattedHost; + if (formattedHost1 == m_web || formattedHost2 == m_web) + return; + + if (m_isfluidd_1) + { + formattedHost = "http://fluidd_" + formattedHost; + m_isfluidd_1 = false; + } + else + { + formattedHost = "http://fluidd2_" + formattedHost; + m_isfluidd_1 = true; + } } else { - formattedHost = "http://fluidd2_" + formattedHost; - m_isfluidd_1 = true; + formattedHost = "http://" + device.link_url; } load_net_url(formattedHost, device.local_ip); }); @@ -810,7 +808,7 @@ wxBoxSizer *PrinterWebView::init_menu_bar(wxPanel *Panel) vec1.clear(); vec2.clear(); bool result2 = true; - #if QDT_RELEASE_TO_PUBLIC +#if QDT_RELEASE_TO_PUBLIC wxString msg; QIDINetwork m_qidinetwork; m_qidinetwork.get_device_list(msg); diff --git a/src/slic3r/GUI/PrinterWebView.hpp b/src/slic3r/GUI/PrinterWebView.hpp index 6cb9d4f..8f47252 100644 --- a/src/slic3r/GUI/PrinterWebView.hpp +++ b/src/slic3r/GUI/PrinterWebView.hpp @@ -43,6 +43,9 @@ #include #include "./Widgets/SwitchButton.hpp" #include "./Widgets/DeviceButton.hpp" + +#include "OctoPrint.hpp" + namespace Slic3r { namespace GUI { @@ -90,7 +93,8 @@ public: const wxString & machine_type, const wxString & fullname, bool isSelected, - bool isQIDI); + bool isQIDI, + const wxString & apikey); void DeleteButton(); void UnSelectedButton(); void ShowNetPrinterButton(); @@ -106,11 +110,11 @@ public: { m_stopThread = true; //y36 - PrintHost::SetStop(true); + OctoPrint::SetStop(true); if (m_statusThread.joinable()) { m_statusThread.join(); } - PrintHost::SetStop(false); + OctoPrint::SetStop(false); }; void SetPauseThread(bool status) { m_pauseThread = status; }; void SetPresetChanged(bool status); diff --git a/src/slic3r/GUI/SelectMachine.cpp b/src/slic3r/GUI/SelectMachine.cpp index 44b5f38..77dbb6c 100644 --- a/src/slic3r/GUI/SelectMachine.cpp +++ b/src/slic3r/GUI/SelectMachine.cpp @@ -1212,7 +1212,7 @@ SelectMachineDialog::SelectMachineDialog(Plater *plater, wxString title) // y21 wxPanel* switch_button_panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxTAB_TRAVERSAL | wxBU_RIGHT); wxBoxSizer* printer_sizer = new wxBoxSizer(wxHORIZONTAL); - switch_button_panel->SetBackgroundColour(wxColor(255, 255, 255)); + switch_button_panel->SetBackgroundColour(StateColor::darkModeColorFor(wxColour("#FFFFFF"))); m_switch_button = new SwitchButton(switch_button_panel); m_switch_button->SetMaxSize(wxSize(100, 100)); m_switch_button->SetLabels(_L("Local"), _L("Link")); @@ -1982,8 +1982,14 @@ bool SelectMachineDialog::get_ams_mapping_result(std::string &mapping_array_str, } else { json j = json::array(); json mapping_info_json = json::array(); - - for (int i = 0; i < wxGetApp().preset_bundle->filament_presets.size(); i++) { + //1.9.7.52 + BOOST_LOG_TRIVIAL(info) << "filaments size = " << m_filaments.size(); + int mapping_size = wxGetApp().preset_bundle->filament_presets.size(); + for (size_t i = 0; i < m_ams_mapping_result.size(); i++) { + mapping_size = std::max(mapping_size, m_ams_mapping_result[i].id); + } + mapping_size = std::min(mapping_size, 16); + for (int i = 0; i <= mapping_size; i++) { int tray_id = -1; json mapping_item; mapping_item["ams"] = tray_id; @@ -1996,9 +2002,12 @@ bool SelectMachineDialog::get_ams_mapping_result(std::string &mapping_array_str, tray_id = m_ams_mapping_result[k].tray_id; mapping_item["ams"] = tray_id; mapping_item["filamentType"] = m_filaments[k].type; - auto it = wxGetApp().preset_bundle->filaments.find_preset(wxGetApp().preset_bundle->filament_presets[i]); - if (it != nullptr) { - mapping_item["filamentId"] = it->filament_id; + //1.9.7.52 + if (i >= 0 && i < wxGetApp().preset_bundle->filament_presets.size()) { + auto it = wxGetApp().preset_bundle->filaments.find_preset(wxGetApp().preset_bundle->filament_presets[i]); + if (it != nullptr) { + mapping_item["filamentId"] = it->filament_id; + } } //convert #RRGGBB to RRGGBBAA mapping_item["sourceColor"] = m_filaments[k].color; @@ -2534,6 +2543,7 @@ void SelectMachineDialog::on_ok_btn(wxCommandEvent &event) { machine_url = machine.url; machine_ip = machine.ip; + machine_apikey = machine.apikey; break; } } @@ -2547,6 +2557,7 @@ void SelectMachineDialog::on_ok_btn(wxCommandEvent &event) { machine_url = machine.url; machine_ip = machine.ip; + machine_apikey = ""; break; } } @@ -3163,6 +3174,7 @@ void SelectMachineDialog::update_user_printer() machine.ip = py_printer.config.opt_string("print_host"); machine.type = py_printer.config.opt_string("preset_name"); machine.display_name = machine.name + " (" + machine.ip + ")"; + machine.apikey = py_printer.config.opt_string("printhost_apikey"); machine_list_local.push_back(machine); } @@ -4195,6 +4207,8 @@ void SelectMachineDialog::reset_and_sync_ams_list() m_materialList.clear(); m_filaments.clear(); + BOOST_LOG_TRIVIAL(info) << "extruders = " << extruders.size(); + for (auto i = 0; i < extruders.size(); i++) { auto extruder = extruders[i] - 1; auto colour = wxGetApp().preset_bundle->project_config.opt_string("filament_colour", (unsigned int) extruder); diff --git a/src/slic3r/GUI/SelectMachine.hpp b/src/slic3r/GUI/SelectMachine.hpp index 5833adc..27e4c9f 100644 --- a/src/slic3r/GUI/SelectMachine.hpp +++ b/src/slic3r/GUI/SelectMachine.hpp @@ -68,6 +68,7 @@ struct Machine_info { std::string ip; std::string type; std::string display_name; + std::string apikey; }; @@ -381,6 +382,7 @@ private: std::string machine_name; std::string machine_url; std::string machine_ip; + std::string machine_apikey; Slic3r::DynamicPrintConfig m_required_data_config; Slic3r::Model m_required_data_model; @@ -561,6 +563,8 @@ public: std::string get_machine_ip() { return machine_ip; } std::string get_project_name() { return into_u8(m_current_project_name); } std::string NormalizeVendor(const std::string& str); + std::string get_machine_apikey() { return machine_apikey; } + }; wxDECLARE_EVENT(EVT_FINISHED_UPDATE_MACHINE_LIST, wxCommandEvent); diff --git a/src/slic3r/GUI/SendMultiMachinePage.cpp b/src/slic3r/GUI/SendMultiMachinePage.cpp index caf77e6..ba6bf88 100644 --- a/src/slic3r/GUI/SendMultiMachinePage.cpp +++ b/src/slic3r/GUI/SendMultiMachinePage.cpp @@ -383,9 +383,9 @@ void SendMultiMachinePage::refresh_user_device() const std::string name = py_printer.name; const std::string url = py_printer.config.opt_string("print_host"); const std::string ip = py_printer.config.opt_string("print_host"); - //y24 + const std::string apikey = py_printer.config.opt_string("printhost_apikey"); std::string display_name = name + " (" + ip + ")"; - MachineObject* obj = new MachineObject(display_name, url, ip); + MachineObject* obj = new MachineObject(display_name, url, ip, apikey); obj->printer_type = py_printer.config.opt_string("preset_name"); obj->print_status = "IDLE"; SendDeviceItem* di = new SendDeviceItem(scroll_macine_list, obj); @@ -637,9 +637,11 @@ void SendMultiMachinePage::on_send(wxCommandEvent& event) std::string name = obj->dev_name; std::string url = obj->dev_url; std::string ip = obj->dev_ip; + std::string apikey = obj->dev_apikey; std::vector host_vector; host_vector.push_back(url); host_vector.push_back(ip); + host_vector.push_back(apikey); m_machine_info.insert(std::make_pair(name, host_vector)); select_num++; } @@ -1050,7 +1052,7 @@ wxPanel* SendMultiMachinePage::create_page() m_table_head_panel = new wxPanel(main_page, wxID_ANY, wxDefaultPosition, wxDefaultSize); m_table_head_panel->SetMinSize(wxSize(FromDIP(DEVICE_ITEM_MAX_WIDTH), -1)); m_table_head_panel->SetMaxSize(wxSize(FromDIP(DEVICE_ITEM_MAX_WIDTH), -1)); - m_table_head_panel->SetBackgroundColour(TABLE_HEAR_NORMAL_COLOUR); + m_table_head_panel->SetBackgroundColour(StateColor::darkModeColorFor(TABLE_HEAR_NORMAL_COLOUR)); m_table_head_sizer = new wxBoxSizer(wxHORIZONTAL); m_select_checkbox = new CheckBox(m_table_head_panel, wxID_ANY); diff --git a/src/slic3r/GUI/WebGuideDialog.cpp b/src/slic3r/GUI/WebGuideDialog.cpp index d972454..74e18d5 100644 --- a/src/slic3r/GUI/WebGuideDialog.cpp +++ b/src/slic3r/GUI/WebGuideDialog.cpp @@ -988,10 +988,10 @@ int GuideFrame::GetFilamentInfo( std::string VendorDirectory, json & pFilaList, BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " GetFilamentInfo:VendorDirectory - " << VendorDirectory << ", Filepath - "<> jLocal; if (sVendor == "") { if (jLocal.contains("filament_vendor")) @@ -1259,186 +1259,6 @@ void StringReplace(string &strBase, string strSrc, string strDes) } } - -//int GuideFrame::LoadProfileFamily(std::string strVendor, std::string strFilePath) -//{ -// //wxString strFolder = strFilePath.BeforeLast(boost::filesystem::path::preferred_separator); -// boost::filesystem::path file_path(strFilePath); -// boost::filesystem::path vendor_dir = boost::filesystem::absolute(file_path.parent_path()/ strVendor).make_preferred(); -// BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", vendor path %1%.")% vendor_dir.string(); -// try { -// -// //wxLogMessage("GUIDE: json_path1 %s", w2s(strFilePath)); -// -// std::string contents; -// LoadFile(strFilePath, contents); -// //wxLogMessage("GUIDE: json_path1 content: %s", contents); -// json jLocal=json::parse(contents); -// //wxLogMessage("GUIDE: json_path1 Loaded"); -// -// // QDS:models -// json pmodels = jLocal["machine_model_list"]; -// int nsize = pmodels.size(); -// -// BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", got %1% machine models")%nsize; -// -// for (int n = 0; n < nsize; n++) { -// json OneModel = pmodels.at(n); -// -// OneModel["model"] = OneModel["name"]; -// OneModel.erase("name"); -// -// std::string s1 = OneModel["model"]; -// std::string s2 = OneModel["sub_path"]; -// -// boost::filesystem::path sub_path = boost::filesystem::absolute(vendor_dir / s2).make_preferred(); -// std::string sub_file = sub_path.string(); -// -// //wxLogMessage("GUIDE: json_path2 %s", w2s(ModelFilePath)); -// LoadFile(sub_file, contents); -// //wxLogMessage("GUIDE: json_path2 content: %s", contents); -// json pm=json::parse(contents); -// //wxLogMessage("GUIDE: json_path2 loaded"); -// -// OneModel["vendor"] = strVendor; -// std::string NozzleOpt = pm["nozzle_diameter"]; -// StringReplace(NozzleOpt, " ", ""); -// OneModel["nozzle_diameter"] = NozzleOpt; -// OneModel["materials"] = pm["default_materials"]; -// -// //wxString strCoverPath = wxString::Format("%s\\%s\\%s_cover.png", strFolder, strVendor, std::string(s1.mb_str())); -// std::string cover_file = s1+"_cover.png"; -// boost::filesystem::path cover_path = boost::filesystem::absolute(vendor_dir / cover_file).make_preferred(); -// OneModel["cover"] = cover_path.string(); -// -// OneModel["nozzle_selected"] = ""; -// -// m_ProfileJson["model"].push_back(OneModel); -// } -// -// // QDS:Machine -// json pmachine = jLocal["machine_list"]; -// nsize = pmachine.size(); -// BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", got %1% machines")%nsize; -// for (int n = 0; n < nsize; n++) { -// json OneMachine = pmachine.at(n); -// -// std::string s1 = OneMachine["name"]; -// std::string s2 = OneMachine["sub_path"]; -// -// //wxString ModelFilePath = wxString::Format("%s\\%s\\%s", strFolder, strVendor, s2); -// boost::filesystem::path sub_path = boost::filesystem::absolute(vendor_dir / s2).make_preferred(); -// std::string sub_file = sub_path.string(); -// LoadFile(sub_file, contents); -// json pm = json::parse(contents); -// -// std::string strInstant = pm["instantiation"]; -// if (strInstant.compare("true") == 0) { -// OneMachine["model"] = pm["printer_model"]; -// -// m_ProfileJson["machine"].push_back(OneMachine); -// } -// } -// -// // QDS:Filament -// json pFilament = jLocal["filament_list"]; -// nsize = pFilament.size(); -// -// int nFalse = 0; -// int nModel = 0; -// int nFinish = 0; -// BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", got %1% filaments")%nsize; -// for (int n = 0; n < nsize; n++) { -// json OneFF = pFilament.at(n); -// -// std::string s1 = OneFF["name"]; -// std::string s2 = OneFF["sub_path"]; -// -// if (!m_ProfileJson["filament"].contains(s1)) -// { -// //wxString ModelFilePath = wxString::Format("%s\\%s\\%s", strFolder, strVendor, s2); -// boost::filesystem::path sub_path = boost::filesystem::absolute(vendor_dir / s2).make_preferred(); -// std::string sub_file = sub_path.string(); -// LoadFile(sub_file, contents); -// json pm = json::parse(contents); -// -// std::string strInstant = pm["instantiation"]; -// if (strInstant == "true") { -// std::string sV; -// std::string sT; -// -// int nRet = GetFilamentInfo(sub_file, sV, sT); -// if (nRet != 0) continue; -// -// OneFF["vendor"] = sV; -// OneFF["type"] = sT; -// -// OneFF["models"] = ""; -// OneFF["selected"] = 0; -// } -// else -// continue; -// -// } else { -// OneFF = m_ProfileJson["filament"][s1]; -// } -// -// std::string vModel = ""; -// int nm = m_ProfileJson["model"].size(); -// int bFind = 0; -// for (int m = 0; m < nm; m++) { -// std::string strFF = m_ProfileJson["model"][m]["materials"]; -// strFF = (boost::format(";%1%;")%strFF).str(); -// std::string strTT = (boost::format(";%1%;")%s1).str(); -// if (strFF.find(strTT) != std::string::npos) { -// std::string sModel = m_ProfileJson["model"][m]["model"]; -// -// vModel = (boost::format("%1%[%2%]")%vModel %sModel).str(); -// bFind = 1; -// } -// } -// -// OneFF["models"] = vModel; -// -// m_ProfileJson["filament"][s1] = OneFF; -// } -// -// //process -// json pProcess = jLocal["process_list"]; -// nsize = pProcess.size(); -// BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", got %1% processes")%nsize; -// for (int n = 0; n < nsize; n++) { -// json OneProcess = pProcess.at(n); -// -// std::string s2 = OneProcess["sub_path"]; -// //wxString ModelFilePath = wxString::Format("%s\\%s\\%s", strFolder, strVendor, s2); -// boost::filesystem::path sub_path = boost::filesystem::absolute(vendor_dir / s2).make_preferred(); -// std::string sub_file = sub_path.string(); -// LoadFile(sub_file, contents); -// json pm = json::parse(contents); -// -// std::string bInstall = pm["instantiation"]; -// if (bInstall == "true") -// { -// m_ProfileJson["process"].push_back(OneProcess); -// } -// } -// -// } -// catch(nlohmann::detail::parse_error &err) { -// BOOST_LOG_TRIVIAL(error) << __FUNCTION__<< ": parse "<> jLocal; // QDS:models json pmodels = jLocal["machine_model_list"]; @@ -1471,12 +1289,10 @@ int GuideFrame::LoadProfileFamily(std::string strVendor, std::string strFilePath boost::filesystem::path sub_path = boost::filesystem::absolute(vendor_dir / s2).make_preferred(); std::string sub_file = sub_path.string(); - - // wxLogMessage("GUIDE: json_path2 %s", w2s(ModelFilePath)); - LoadFile(sub_file, contents); - // wxLogMessage("GUIDE: json_path2 content: %s", contents); - json pm = json::parse(contents); - // wxLogMessage("GUIDE: json_path2 loaded"); + //1.9.7.52 + boost::nowide::ifstream ifs(sub_file); + json pm; + ifs >> pm; OneModel["vendor"] = strVendor; std::string NozzleOpt = pm["nozzle_diameter"]; @@ -1507,8 +1323,10 @@ int GuideFrame::LoadProfileFamily(std::string strVendor, std::string strFilePath // wxString ModelFilePath = wxString::Format("%s\\%s\\%s", strFolder, strVendor, s2); boost::filesystem::path sub_path = boost::filesystem::absolute(vendor_dir / s2).make_preferred(); std::string sub_file = sub_path.string(); - LoadFile(sub_file, contents); - json pm = json::parse(contents); + //1.9.7.52 + boost::nowide::ifstream ifs(sub_file); + json pm; + ifs >> pm; std::string strInstant = pm["instantiation"]; if (strInstant.compare("true") == 0) { @@ -1548,8 +1366,10 @@ int GuideFrame::LoadProfileFamily(std::string strVendor, std::string strFilePath // wxString ModelFilePath = wxString::Format("%s\\%s\\%s", strFolder, strVendor, s2); boost::filesystem::path sub_path = boost::filesystem::absolute(vendor_dir / s2).make_preferred(); std::string sub_file = sub_path.string(); - LoadFile(sub_file, contents); - json pm = json::parse(contents); + //1.9.7.52 + boost::nowide::ifstream ifs(sub_file); + json pm; + ifs >> pm; std::string strInstant = pm["instantiation"]; BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "Load Filament:" << s1 << ",Path:" << sub_file << ",instantiation:" << strInstant; @@ -1606,8 +1426,9 @@ int GuideFrame::LoadProfileFamily(std::string strVendor, std::string strFilePath // wxString ModelFilePath = wxString::Format("%s\\%s\\%s", strFolder, strVendor, s2); boost::filesystem::path sub_path = boost::filesystem::absolute(vendor_dir / s2).make_preferred(); std::string sub_file = sub_path.string(); - LoadFile(sub_file, contents); - json pm = json::parse(contents); + boost::nowide::ifstream ifs(sub_file); + json pm; + ifs >> pm; std::string bInstall = pm["instantiation"]; if (bInstall == "true") { m_ProfileJson["process"].push_back(OneProcess); } @@ -1649,23 +1470,23 @@ void GuideFrame::GetStardardFilePath(std::string &FilePath) { StrReplace(FilePath, "\/", w2s(wxString::Format("%c", boost::filesystem::path::preferred_separator))); } -bool GuideFrame::LoadFile(std::string jPath, std::string &sContent) -{ - try { - boost::nowide::ifstream t(jPath); - std::stringstream buffer; - buffer << t.rdbuf(); - sContent=buffer.str(); - BOOST_LOG_TRIVIAL(trace) << __FUNCTION__ << boost::format(", load %1% into buffer")% jPath; - } - catch (std::exception &e) - { - BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ", got exception: "< + #include #include +#include #include #include @@ -512,6 +515,17 @@ void WebViewPanel::SendRecentList(int images) void WebViewPanel::SendDesignStaffpick(bool on) { + //1.9.7.52 + static long long StaffPickMs = 0; + + auto now = std::chrono::system_clock::now(); + long long TmpMs = std::chrono::duration_cast(now.time_since_epoch()).count(); + long long nInterval = TmpMs - StaffPickMs; + if (nInterval < 500) return; + StaffPickMs = TmpMs; + + BOOST_LOG_TRIVIAL(info) << "Begin SendDesignStaffpick: " << nInterval; + try { if (on) { std::string sguide = wxGetApp().app_config->get("firstguide", "finish"); @@ -1009,10 +1023,12 @@ void WebViewPanel::OnNewWindow(wxWebViewEvent& evt) if (wxGetApp().get_mode() == comDevelop) wxLogMessage("%s", "New window; url='" + evt.GetURL() + "'" + flag); - //If we handle new window events then just load them in this window as we - //are a single window browser - if (m_tools_handle_new_window->IsChecked()) - m_browser->LoadURL(evt.GetURL()); + //1.9.7.52 + //If we handle new window events then just load them in local browser + if (m_tools_handle_new_window->IsChecked()) + { + wxLaunchDefaultBrowser(evt.GetURL()); + } UpdateState(); } @@ -1421,7 +1437,7 @@ void WebViewPanel::SwitchLeftMenu(std::string strMenu) void WebViewPanel::OpenOneMakerlab(std::string url) { auto host = wxGetApp().get_model_http_url(wxGetApp().app_config->get_country_code()); - std::string LabUrl = (boost::format("%1%%2%") % host % url).str(); + std::string LabUrl = (boost::format("%1%%2%?from=qidistudio") % host % url).str(); wxString FinalUrl = LabUrl; NetworkAgent *agent = GUI::wxGetApp().getAgent(); diff --git a/src/slic3r/GUI/Widgets/DeviceButton.cpp b/src/slic3r/GUI/Widgets/DeviceButton.cpp index db79977..c1cb389 100644 --- a/src/slic3r/GUI/Widgets/DeviceButton.cpp +++ b/src/slic3r/GUI/Widgets/DeviceButton.cpp @@ -23,7 +23,8 @@ END_EVENT_TABLE() * calling Refresh()/Update(). */ -DeviceButton::DeviceButton(wxString name_text, wxString ip_text) : paddingSize(10, 8), m_name_text(name_text), m_ip_text(ip_text) +//y40 +DeviceButton::DeviceButton(wxString name_text, wxString ip_text, wxString apikey_text) : paddingSize(10, 8), m_name_text(name_text), m_ip_text(ip_text), m_apikey(apikey_text) { background_color = StateColor( std::make_pair(0x262629, (int) StateColor::Disabled), @@ -36,14 +37,16 @@ DeviceButton::DeviceButton(wxString name_text, wxString ip_text) : paddingSize(1 std::make_pair(*wxBLACK, (int) StateColor::Normal)); } +//y40 DeviceButton::DeviceButton(wxWindow *parent, wxString text, wxString icon, long style, wxSize iconSize /* = wxSize(16, 16)*/, wxString name_text, - wxString ip_text) - : DeviceButton(name_text,ip_text) + wxString ip_text, + wxString apikey_text) + : DeviceButton(name_text,ip_text, apikey_text) { Create(parent, text, icon, style, iconSize); } diff --git a/src/slic3r/GUI/Widgets/DeviceButton.hpp b/src/slic3r/GUI/Widgets/DeviceButton.hpp index 436932d..f1323fc 100644 --- a/src/slic3r/GUI/Widgets/DeviceButton.hpp +++ b/src/slic3r/GUI/Widgets/DeviceButton.hpp @@ -22,7 +22,8 @@ class DeviceButton : public StaticBox static const int buttonHeight = 50; public: - DeviceButton(wxString name_text, wxString ip_text); + //y40 + DeviceButton(wxString name_text, wxString ip_text, wxString apikey_text); DeviceButton(wxWindow *parent, wxString text, @@ -30,7 +31,8 @@ public: long style = 0, wxSize iconSize = wxSize(16, 16), wxString name_text = "", - wxString ip_text = ""); + wxString ip_text = "", + wxString apikey_text = ""); DeviceButton(wxWindow* parent, wxString icon, long style); @@ -77,7 +79,8 @@ public: wxString GetStateText() { return m_state_text; } wxString getNameLabel() { return m_name_text; } - + //y40 + wxString GetApikey() { return m_apikey; }; void Rescale(); @@ -110,6 +113,7 @@ private: wxString m_progress_text = "(0%)"; bool m_isSimpleMode = true; bool m_isSelected = false; + wxString m_apikey; DECLARE_EVENT_TABLE() }; diff --git a/src/slic3r/Utils/AstroBox.hpp b/src/slic3r/Utils/AstroBox.hpp index 15a8863..a7ceddc 100644 --- a/src/slic3r/Utils/AstroBox.hpp +++ b/src/slic3r/Utils/AstroBox.hpp @@ -21,6 +21,9 @@ public: const char* get_name() const override; bool test(wxString &curl_msg) const override; + virtual std::string get_status(wxString& curl_msg) const override { return "1"; }; + virtual float get_progress(wxString& curl_msg) const override { return 1; }; + virtual std::pair get_status_progress(wxString& curl_msg) const override { return std::make_pair("1", 1); }; wxString get_test_ok_msg () const override; wxString get_test_failed_msg (wxString &msg) const override; bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const override; diff --git a/src/slic3r/Utils/Duet.hpp b/src/slic3r/Utils/Duet.hpp index edca66c..7d9c25d 100644 --- a/src/slic3r/Utils/Duet.hpp +++ b/src/slic3r/Utils/Duet.hpp @@ -20,6 +20,9 @@ public: const char* get_name() const override; bool test(wxString &curl_msg) const override; + virtual std::string get_status(wxString& curl_msg) const override { return "1"; }; + virtual float get_progress(wxString& curl_msg) const override { return 1; }; + virtual std::pair get_status_progress(wxString& curl_msg) const override { return std::make_pair("1", 1); }; wxString get_test_ok_msg() const override; wxString get_test_failed_msg(wxString &msg) const override; bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const override; diff --git a/src/slic3r/Utils/FlashAir.hpp b/src/slic3r/Utils/FlashAir.hpp index 14e3f00..8cd1c3a 100644 --- a/src/slic3r/Utils/FlashAir.hpp +++ b/src/slic3r/Utils/FlashAir.hpp @@ -21,6 +21,9 @@ public: const char* get_name() const override; bool test(wxString &curl_msg) const override; + virtual std::string get_status(wxString& curl_msg) const override { return "1"; }; + virtual float get_progress(wxString& curl_msg) const override { return 1; }; + virtual std::pair get_status_progress(wxString& curl_msg) const override { return std::make_pair("1", 1); }; wxString get_test_ok_msg() const override; wxString get_test_failed_msg(wxString &msg) const override; bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const override; diff --git a/src/slic3r/Utils/Http.cpp b/src/slic3r/Utils/Http.cpp index 8f877a0..8098d95 100644 --- a/src/slic3r/Utils/Http.cpp +++ b/src/slic3r/Utils/Http.cpp @@ -15,7 +15,7 @@ #include -#include "../GUI/PrinterWebView.hpp" +#include "OctoPrint.hpp" #ifdef OPENSSL_CERT_OVERRIDE #include @@ -235,7 +235,7 @@ int Http::priv::xfercb(void *userp, curl_off_t dltotal, curl_off_t dlnow, curl_o auto self = static_cast(userp); bool cb_cancel = false; //y36 - if (PrintHost::GetStop()) + if (OctoPrint::GetStop()) cb_cancel = true; if (self->progressfn) { diff --git a/src/slic3r/Utils/MKS.hpp b/src/slic3r/Utils/MKS.hpp index 2245543..1bfa76c 100644 --- a/src/slic3r/Utils/MKS.hpp +++ b/src/slic3r/Utils/MKS.hpp @@ -20,6 +20,9 @@ public: const char* get_name() const override; bool test(wxString& curl_msg) const override; + virtual std::string get_status(wxString& curl_msg) const override { return "1"; }; + virtual float get_progress(wxString& curl_msg) const override { return 1; }; + virtual std::pair get_status_progress(wxString& curl_msg) const override { return std::make_pair("1", 1); }; wxString get_test_ok_msg() const override; wxString get_test_failed_msg(wxString& msg) const override; bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const override; diff --git a/src/slic3r/Utils/OctoPrint.cpp b/src/slic3r/Utils/OctoPrint.cpp index a81865c..b512cda 100644 --- a/src/slic3r/Utils/OctoPrint.cpp +++ b/src/slic3r/Utils/OctoPrint.cpp @@ -30,6 +30,9 @@ namespace pt = boost::property_tree; namespace Slic3r { +bool OctoPrint::m_isStop = false; + + #ifdef WIN32 // Workaround for Windows 10/11 mDNS resolve issue, where two mDNS resolves in succession fail. namespace { @@ -103,6 +106,7 @@ OctoPrint::OctoPrint(DynamicPrintConfig *config, bool add_port) config->opt_string("print_host") : config->opt_string("print_host")) , m_show_ip(config->opt_string("print_host")) + , m_apikey(config->opt_string("printhost_apikey")) { } @@ -244,6 +248,15 @@ bool OctoPrint::upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, Erro 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) { + //y40 + if (status == 404) + { + body = ("Network connection fails."); + if (body.find("AWS") != std::string::npos) + body += ("Unable to get required resources from AWS server, please check your network settings."); + else + body += ("Unable to get required resources from Aliyun server, please check your network settings."); + } 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; @@ -291,6 +304,226 @@ std::string OctoPrint::make_url(const std::string &path) const } } +//y40 +std::string OctoPrint::get_status(wxString& msg) const +{ + // GET /server/info + + // Since the request is performed synchronously here, + // it is ok to refer to `msg` from within the closure + const std::string name = get_name(); + bool res = true; + std::string print_state = "standby"; + auto url = make_url("printer/objects/query?print_stats=state"); + + BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Get version at: %2%") % name % url; + + auto http = Http::get(std::move(url)); + set_auth(http); + //y36 + http.timeout_connect(4) + .on_error([&](std::string body, std::string error, unsigned status) { + if (status == 404) + { + body = ("Network connection fails."); + if (body.find("AWS") != std::string::npos) + body += ("Unable to get required resources from AWS server, please check your network settings."); + else + body += ("Unable to get required resources from Aliyun server, please check your network settings."); + } + BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error getting version: %2%, HTTP %3%, body: `%4%`") % name % error % status % body; + print_state = "offline"; + msg = format_error(body, error, status); + }) + .on_complete([&](std::string body, unsigned) { + BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: Got print_stats: %2%") % name % body; + + try { + // All successful HTTP requests will return a json encoded object in the form of : + // {result: } + std::stringstream ss(body); + pt::ptree ptree; + pt::read_json(ss, ptree); + if (ptree.front().first != "result") { + msg = "Could not parse server response"; + print_state = "offline"; + return; + } + if (!ptree.front().second.get_optional("status")) { + msg = "Could not parse server response"; + print_state = "offline"; + return; + } + print_state = ptree.get("result.status.print_stats.state"); + BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Got state: %2%") % name % print_state; + ; + } + catch (const std::exception&) { + print_state = "offline"; + msg = "Could not parse server response"; + } + }) +#ifdef _WIN32 + .ssl_revoke_best_effort(m_ssl_revoke_best_effort) + .on_ip_resolve([&](std::string address) { + // Workaround for Windows 10/11 mDNS resolve issue, where two mDNS resolves in succession fail. + // Remember resolved address to be reused at successive REST API call. + msg = wxString::FromUTF8(address); + }) +#endif // _WIN32 + .perform_sync(); + + return print_state; +} + +//y40 +float OctoPrint::get_progress(wxString& msg) const +{ + // GET /server/info + + // Since the request is performed synchronously here, + // it is ok to refer to `msg` from within the closure + const std::string name = get_name(); + + bool res = true; + auto url = make_url("printer/objects/query?display_status=progress"); + float process = 0; + BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Get version at: %2%") % name % url; + + auto http = Http::get(std::move(url)); + set_auth(http); + http.timeout_connect(4) + .on_error([&](std::string body, std::string error, unsigned status) { + if (status == 404) + { + body = ("Network connection fails."); + if (body.find("AWS") != std::string::npos) + body += ("Unable to get required resources from AWS server, please check your network settings."); + else + body += ("Unable to get required resources from Aliyun server, please check your network settings."); + } + BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error getting version: %2%, HTTP %3%, body: `%4%`") % name % error % status % + body; + res = false; + msg = format_error(body, error, status); + }) + .on_complete([&](std::string body, unsigned) { + BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: Got display_status: %2%") % name % body; + + try { + // All successful HTTP requests will return a json encoded object in the form of : + // {result: } + std::stringstream ss(body); + pt::ptree ptree; + pt::read_json(ss, ptree); + if (ptree.front().first != "result") { + msg = "Could not parse server response"; + res = false; + return; + } + if (!ptree.front().second.get_optional("status")) { + msg = "Could not parse server response"; + res = false; + return; + } + process = std::stof(ptree.get("result.status.display_status.progress")); + BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Got state: %2%") % name % process; + } + catch (const std::exception&) { + res = false; + msg = "Could not parse server response"; + } + }) +#ifdef _WIN32 + .ssl_revoke_best_effort(m_ssl_revoke_best_effort) + .on_ip_resolve([&](std::string address) { + // Workaround for Windows 10/11 mDNS resolve issue, where two mDNS resolves in succession fail. + // Remember resolved address to be reused at successive REST API call. + msg = wxString::FromUTF8(address); + }) +#endif // _WIN32 + .perform_sync(); + + return process; +} + +std::pair OctoPrint::get_status_progress(wxString& msg) const +{ + // GET /server/info + + // Since the request is performed synchronously here, + // it is ok to refer to `msg` from within the closure + const char* name = get_name(); + + bool res = true; + std::string print_state = "standby"; + float process = 0; + auto url = make_url("printer/objects/query?print_stats=state&display_status=progress"); + + BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Get version at: %2%") % name % url; + + auto http = Http::get(std::move(url)); + set_auth(http); + // B64 //y6 + http.timeout_connect(4) + .on_error([&](std::string body, std::string error, unsigned status) { + // y1 + if (status == 404) { + body = ("Network connection fails."); + if (body.find("AWS") != std::string::npos) + body += ("Unable to get required resources from AWS server, please check your network settings."); + else + body += ("Unable to get required resources from Aliyun server, please check your network settings."); + } + BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error getting version: %2%, HTTP %3%, body: `%4%`") % name % error % status % + body; + print_state = "offline"; + msg = format_error(body, error, status); + }) + .on_complete([&](std::string body, unsigned) { + BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: Got print_stats and process: %2%") % name % body; + try { + // All successful HTTP requests will return a json encoded object in the form of : + // {result: } + std::stringstream ss(body); + pt::ptree ptree; + pt::read_json(ss, ptree); + if (ptree.front().first != "result") { + msg = "Could not parse server response"; + print_state = "offline"; + process = 0; + return; + } + if (!ptree.front().second.get_optional("status")) { + msg = "Could not parse server response"; + print_state = "offline"; + process = 0; + return; + } + print_state = ptree.get("result.status.print_stats.state"); + process = std::stof(ptree.get("result.status.display_status.progress")); + BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Got state: %2%") % name % print_state; + ; + } + catch (const std::exception&) { + print_state = "offline"; + process = 0; + 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 std::make_pair(print_state, process); +} + SL1Host::SL1Host(DynamicPrintConfig *config) : OctoPrint(config, true), m_authorization_type(dynamic_cast*>(config->option("printhost_authorization_type"))->value), diff --git a/src/slic3r/Utils/OctoPrint.hpp b/src/slic3r/Utils/OctoPrint.hpp index 90628f3..774b0f7 100644 --- a/src/slic3r/Utils/OctoPrint.hpp +++ b/src/slic3r/Utils/OctoPrint.hpp @@ -33,6 +33,14 @@ public: std::string get_host() const override { return m_show_ip; } const std::string& get_apikey() const { return m_apikey; } const std::string& get_cafile() const { return m_cafile; } + //y40 + virtual std::string get_status(wxString& curl_msg) const override; + virtual float get_progress(wxString& curl_msg) const override; + virtual std::pair get_status_progress(wxString& curl_msg) const override; + + static void SetStop(bool isStop) { m_isStop = isStop; }; + static bool GetStop() { return m_isStop; }; + static bool m_isStop; protected: std::string m_show_ip; diff --git a/src/slic3r/Utils/PrintHost.cpp b/src/slic3r/Utils/PrintHost.cpp index 531c419..d517077 100644 --- a/src/slic3r/Utils/PrintHost.cpp +++ b/src/slic3r/Utils/PrintHost.cpp @@ -27,8 +27,6 @@ using boost::optional; using Slic3r::GUI::PrintHostQueueDialog; namespace Slic3r { -//y36 -bool PrintHost::m_isStop = false; PrintHost::~PrintHost() {} @@ -73,148 +71,6 @@ wxString PrintHost::format_error(const std::string &body, const std::string &err } -//B52 -std::string PrintHost::make_url(const std::string &path, const std::string& m_host) 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(); - } -} - -//B45 -std::string PrintHost::get_status(wxString &msg, const wxString &buttonText, const wxString &ip) const -{ - // GET /server/info - - // Since the request is performed synchronously here, - // it is ok to refer to `msg` from within the closure - const std::string name = buttonText.ToStdString(); - bool res = true; - std::string print_state = "standby"; - std::string m_host = ip.ToStdString(); - auto url = make_url("printer/objects/query?print_stats=state", m_host); - - BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Get version at: %2%") % name % url; - - auto http = Http::get(std::move(url)); - // set_auth(http); - //y36 - http.timeout_connect(4) - .on_error([&](std::string body, std::string error, unsigned status) { - BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error getting version: %2%, HTTP %3%, body: `%4%`") % name % error % status % - body; - print_state = "offline"; - msg = format_error(body, error, status); - }) - .on_complete([&](std::string body, unsigned) { - BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: Got print_stats: %2%") % name % body; - - try { - // All successful HTTP requests will return a json encoded object in the form of : - // {result: } - std::stringstream ss(body); - pt::ptree ptree; - pt::read_json(ss, ptree); - if (ptree.front().first != "result") { - msg = "Could not parse server response"; - print_state = "offline"; - return; - } - if (!ptree.front().second.get_optional("status")) { - msg = "Could not parse server response"; - print_state = "offline"; - return; - } - print_state = ptree.get("result.status.print_stats.state"); - BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Got state: %2%") % name % print_state; - ; - } catch (const std::exception &) { - print_state = "offline"; - msg = "Could not parse server response"; - } - }) -#ifdef _WIN32 - .ssl_revoke_best_effort(m_ssl_revoke_best_effort) - .on_ip_resolve([&](std::string address) { - // Workaround for Windows 10/11 mDNS resolve issue, where two mDNS resolves in succession fail. - // Remember resolved address to be reused at successive REST API call. - msg = wxString::FromUTF8(address); - }) -#endif // _WIN32 - .perform_sync(); - - return print_state; -} - -float PrintHost::get_progress(wxString &msg, const wxString &buttonText, const wxString &ip) const -{ - // GET /server/info - - // Since the request is performed synchronously here, - // it is ok to refer to `msg` from within the closure - const std::string name = buttonText.ToStdString(); - - bool res = true; - auto url = make_url("printer/objects/query?display_status=progress", ip.ToStdString()); - float process = 0; - BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Get version at: %2%") % name % url; - - auto http = Http::get(std::move(url)); - // set_auth(http); - http.timeout_connect(4) - .on_error([&](std::string body, std::string error, unsigned status) { - BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error getting version: %2%, HTTP %3%, body: `%4%`") % name % error % status % - body; - res = false; - msg = format_error(body, error, status); - }) - .on_complete([&](std::string body, unsigned) { - BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: Got display_status: %2%") % name % body; - - try { - // All successful HTTP requests will return a json encoded object in the form of : - // {result: } - std::stringstream ss(body); - pt::ptree ptree; - pt::read_json(ss, ptree); - if (ptree.front().first != "result") { - msg = "Could not parse server response"; - res = false; - return; - } - if (!ptree.front().second.get_optional("status")) { - msg = "Could not parse server response"; - res = false; - return; - } - process = std::stof(ptree.get("result.status.display_status.progress")); - BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Got state: %2%") % name % process; - } catch (const std::exception &) { - res = false; - msg = "Could not parse server response"; - } - }) -#ifdef _WIN32 - .ssl_revoke_best_effort(m_ssl_revoke_best_effort) - .on_ip_resolve([&](std::string address) { - // Workaround for Windows 10/11 mDNS resolve issue, where two mDNS resolves in succession fail. - // Remember resolved address to be reused at successive REST API call. - msg = wxString::FromUTF8(address); - }) -#endif // _WIN32 - .perform_sync(); - - return process; -} - - struct PrintHostJobQueue::priv { // XXX: comment on how bg thread works diff --git a/src/slic3r/Utils/PrintHost.hpp b/src/slic3r/Utils/PrintHost.hpp index 755cd35..389364c 100644 --- a/src/slic3r/Utils/PrintHost.hpp +++ b/src/slic3r/Utils/PrintHost.hpp @@ -50,9 +50,9 @@ public: virtual bool test(wxString &curl_msg) const = 0; //B45 - std::string get_status(wxString &msg, const wxString &buttonText, const wxString &ip) const; - float get_progress(wxString &msg, const wxString &buttonText, const wxString &ip) const; - std::string make_url(const std::string &path, const std::string &m_host) const; + virtual std::string get_status(wxString& curl_msg) const = 0; + virtual float get_progress(wxString& curl_msg) const = 0; + virtual std::pair get_status_progress(wxString& curl_msg) const = 0; virtual wxString get_test_ok_msg () const = 0; virtual wxString get_test_failed_msg (wxString &msg) const = 0; virtual bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const = 0; @@ -72,14 +72,9 @@ public: virtual bool get_storage(wxArrayString& /*storage_path*/, wxArrayString& /*storage_name*/) const { return false; } static PrintHost *get_print_host_url(std::string url, std::string local_ip); static PrintHost* get_print_host(DynamicPrintConfig *config); - //y36 - static void SetStop(bool isStop) { m_isStop = isStop; }; - static bool GetStop() { return m_isStop; }; - static bool m_isStop; protected: virtual wxString format_error(const std::string &body, const std::string &error, unsigned status) const; - bool m_ssl_revoke_best_effort; }; diff --git a/src/slic3r/Utils/Repetier.hpp b/src/slic3r/Utils/Repetier.hpp index 6f33102..8336919 100644 --- a/src/slic3r/Utils/Repetier.hpp +++ b/src/slic3r/Utils/Repetier.hpp @@ -21,6 +21,9 @@ public: const char* get_name() const override; bool test(wxString &curl_msg) const override; + virtual std::string get_status(wxString& curl_msg) const override { return "1"; }; + virtual float get_progress(wxString& curl_msg) const override { return 1; }; + virtual std::pair get_status_progress(wxString& curl_msg) const override { return std::make_pair("1", 1); }; wxString get_test_ok_msg () const override; wxString get_test_failed_msg (wxString &msg) const override; bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const override;