Merge remote-tracking branch 'origin/master' into tm_pad_speedup
							
								
								
									
										
											BIN
										
									
								
								resources/icons/bed/mk2_4096_bottom.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 144 KiB | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/bed/mk2_4096_top.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 364 KiB | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/bed/mk2_8192_bottom.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 398 KiB | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/bed/mk2_8192_top.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 794 KiB | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/bed/mk3_4096_bottom.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 143 KiB | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/bed/mk3_4096_top.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 361 KiB | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/bed/mk3_8192_bottom.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 396 KiB | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/bed/mk3_8192_top.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 790 KiB | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/bed/sl1_4096_bottom.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 105 KiB | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/bed/sl1_4096_top.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 277 KiB | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/bed/sl1_8192_bottom.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 324 KiB | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/bed/sl1_8192_top.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 674 KiB | 
| Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 70 KiB | 
| Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 58 KiB | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/printers/PrusaResearch_MK2.5S.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 70 KiB | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/printers/PrusaResearch_MK2.5SMMU2S.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 58 KiB | 
| Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 65 KiB | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/printers/PrusaResearch_MK3S.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 65 KiB | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/printers/PrusaResearch_MK3SMMU2S.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 70 KiB | 
| Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 55 KiB | 
|  | @ -1333,6 +1333,8 @@ void Transformation::set_rotation(const Vec3d& rotation) | ||||||
| void Transformation::set_rotation(Axis axis, double rotation) | void Transformation::set_rotation(Axis axis, double rotation) | ||||||
| { | { | ||||||
|     rotation = angle_to_0_2PI(rotation); |     rotation = angle_to_0_2PI(rotation); | ||||||
|  |     if (is_approx(std::abs(rotation), 2.0 * (double)PI)) | ||||||
|  |         rotation = 0.0; | ||||||
| 
 | 
 | ||||||
|     if (m_rotation(axis) != rotation) |     if (m_rotation(axis) != rotation) | ||||||
|     { |     { | ||||||
|  |  | ||||||
|  | @ -1445,7 +1445,7 @@ int ModelVolume::extruder_id() const | ||||||
|     int extruder_id = -1; |     int extruder_id = -1; | ||||||
|     if (this->is_model_part()) { |     if (this->is_model_part()) { | ||||||
|         const ConfigOption *opt = this->config.option("extruder"); |         const ConfigOption *opt = this->config.option("extruder"); | ||||||
|         if (opt == nullptr) |         if ((opt == nullptr) || (opt->getInt() == 0)) | ||||||
|             opt = this->object->config.option("extruder"); |             opt = this->object->config.option("extruder"); | ||||||
|         extruder_id = (opt == nullptr) ? 0 : opt->getInt(); |         extruder_id = (opt == nullptr) ? 0 : opt->getInt(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -1137,6 +1137,9 @@ std::string Print::validate() const | ||||||
|                 // Apply the same transformations we apply to the actual meshes when slicing them.
 |                 // Apply the same transformations we apply to the actual meshes when slicing them.
 | ||||||
|                 object->model_object()->instances.front()->transform_polygon(&convex_hull); |                 object->model_object()->instances.front()->transform_polygon(&convex_hull); | ||||||
|                 // Grow convex hull with the clearance margin.
 |                 // Grow convex hull with the clearance margin.
 | ||||||
|  |                 // FIXME: Arrangement has different parameters for offsetting (jtMiter, limit 2)
 | ||||||
|  |                 // which causes that the warning will be showed after arrangement with the
 | ||||||
|  |                 // appropriate object distance. Even if I set this to jtMiter the warning still shows up.
 | ||||||
|                 convex_hull = offset(convex_hull, scale_(m_config.extruder_clearance_radius.value)/2, jtRound, scale_(0.1)).front(); |                 convex_hull = offset(convex_hull, scale_(m_config.extruder_clearance_radius.value)/2, jtRound, scale_(0.1)).front(); | ||||||
|                 // Now we check that no instance of convex_hull intersects any of the previously checked object instances.
 |                 // Now we check that no instance of convex_hull intersects any of the previously checked object instances.
 | ||||||
|                 for (const Point © : object->m_copies) { |                 for (const Point © : object->m_copies) { | ||||||
|  |  | ||||||
|  | @ -6,6 +6,7 @@ | ||||||
| #include <vector> | #include <vector> | ||||||
| #include <set> | #include <set> | ||||||
| #include <unordered_map> | #include <unordered_map> | ||||||
|  | #include <functional> | ||||||
| #include <boost/filesystem.hpp> | #include <boost/filesystem.hpp> | ||||||
| 
 | 
 | ||||||
| #include <wx/sizer.h> | #include <wx/sizer.h> | ||||||
|  | @ -13,6 +14,7 @@ | ||||||
| #include <wx/button.h> | #include <wx/button.h> | ||||||
| #include <wx/choice.h> | #include <wx/choice.h> | ||||||
| #include <wx/spinctrl.h> | #include <wx/spinctrl.h> | ||||||
|  | #include <wx/textctrl.h> | ||||||
| 
 | 
 | ||||||
| #include "libslic3r/PrintConfig.hpp" | #include "libslic3r/PrintConfig.hpp" | ||||||
| #include "slic3r/Utils/PresetUpdater.hpp" | #include "slic3r/Utils/PresetUpdater.hpp" | ||||||
|  | @ -34,8 +36,13 @@ enum { | ||||||
|     BTN_SPACING = 10, |     BTN_SPACING = 10, | ||||||
|     INDENT_SPACING = 30, |     INDENT_SPACING = 30, | ||||||
|     VERTICAL_SPACING = 10, |     VERTICAL_SPACING = 10, | ||||||
|  | 
 | ||||||
|  |     MAX_COLS = 4, | ||||||
|  |     ROW_SPACING = 75, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | typedef std::function<bool(const VendorProfile::PrinterModel&)> ModelFilter; | ||||||
|  | 
 | ||||||
| struct PrinterPicker: wxPanel | struct PrinterPicker: wxPanel | ||||||
| { | { | ||||||
|     struct Checkbox : wxCheckBox |     struct Checkbox : wxCheckBox | ||||||
|  | @ -52,13 +59,18 @@ struct PrinterPicker: wxPanel | ||||||
| 
 | 
 | ||||||
|     const std::string vendor_id; |     const std::string vendor_id; | ||||||
|     std::vector<Checkbox*> cboxes; |     std::vector<Checkbox*> cboxes; | ||||||
| 	unsigned variants_checked; |     std::vector<Checkbox*> cboxes_alt; | ||||||
| 
 | 
 | ||||||
| 	PrinterPicker(wxWindow *parent, const VendorProfile &vendor, const AppConfig &appconfig_vendors); |     PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxString title, size_t max_cols, const AppConfig &appconfig_vendors, const ModelFilter &filter); | ||||||
|  |     PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxString title, size_t max_cols, const AppConfig &appconfig_vendors); | ||||||
| 
 | 
 | ||||||
| 	void select_all(bool select); |     void select_all(bool select, bool alternates = false); | ||||||
|     void select_one(size_t i, bool select); |     void select_one(size_t i, bool select); | ||||||
|     void on_checkbox(const Checkbox *cbox, bool checked); |     void on_checkbox(const Checkbox *cbox, bool checked); | ||||||
|  | 
 | ||||||
|  |     int get_width() const { return width; } | ||||||
|  | private: | ||||||
|  |     int width; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct ConfigWizardPage: wxPanel | struct ConfigWizardPage: wxPanel | ||||||
|  | @ -66,15 +78,11 @@ struct ConfigWizardPage: wxPanel | ||||||
|     ConfigWizard *parent; |     ConfigWizard *parent; | ||||||
|     const wxString shortname; |     const wxString shortname; | ||||||
|     wxBoxSizer *content; |     wxBoxSizer *content; | ||||||
|  |     const unsigned indent; | ||||||
| 
 | 
 | ||||||
| 	ConfigWizardPage(ConfigWizard *parent, wxString title, wxString shortname); |     ConfigWizardPage(ConfigWizard *parent, wxString title, wxString shortname, unsigned indent = 0); | ||||||
| 
 |  | ||||||
|     virtual ~ConfigWizardPage(); |     virtual ~ConfigWizardPage(); | ||||||
| 
 | 
 | ||||||
| 	ConfigWizardPage* page_prev() const { return p_prev; } |  | ||||||
| 	ConfigWizardPage* page_next() const { return p_next; } |  | ||||||
| 	ConfigWizardPage* chain(ConfigWizardPage *page); |  | ||||||
| 
 |  | ||||||
|     template<class T> |     template<class T> | ||||||
|     void append(T *thing, int proportion = 0, int flag = wxEXPAND|wxTOP|wxBOTTOM, int border = 10) |     void append(T *thing, int proportion = 0, int flag = wxEXPAND|wxTOP|wxBOTTOM, int border = 10) | ||||||
|     { |     { | ||||||
|  | @ -86,31 +94,49 @@ struct ConfigWizardPage: wxPanel | ||||||
| 
 | 
 | ||||||
|     ConfigWizard::priv *wizard_p() const { return parent->p.get(); } |     ConfigWizard::priv *wizard_p() const { return parent->p.get(); } | ||||||
| 
 | 
 | ||||||
| 	virtual bool Show(bool show = true); |  | ||||||
| 	virtual bool Hide() { return Show(false); } |  | ||||||
| 	virtual wxPanel* extra_buttons() { return nullptr; } |  | ||||||
| 	virtual void on_page_set() {} |  | ||||||
|     virtual void apply_custom_config(DynamicPrintConfig &config) {} |     virtual void apply_custom_config(DynamicPrintConfig &config) {} | ||||||
| 
 |  | ||||||
| 	void enable_next(bool enable); |  | ||||||
| private: |  | ||||||
| 	ConfigWizardPage *p_prev; |  | ||||||
| 	ConfigWizardPage *p_next; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct PageWelcome: ConfigWizardPage | struct PageWelcome: ConfigWizardPage | ||||||
| { | { | ||||||
| 	PrinterPicker *printer_picker; |  | ||||||
| 	wxPanel *others_buttons; |  | ||||||
|     wxCheckBox *cbox_reset; |     wxCheckBox *cbox_reset; | ||||||
| 
 | 
 | ||||||
| 	PageWelcome(ConfigWizard *parent, bool check_first_variant); |     PageWelcome(ConfigWizard *parent); | ||||||
| 
 |  | ||||||
| 	virtual wxPanel* extra_buttons() { return others_buttons; } |  | ||||||
| 	virtual void on_page_set(); |  | ||||||
| 
 | 
 | ||||||
|     bool reset_user_profile() const { return cbox_reset != nullptr ? cbox_reset->GetValue() : false; } |     bool reset_user_profile() const { return cbox_reset != nullptr ? cbox_reset->GetValue() : false; } | ||||||
| 	void on_variant_checked(); | }; | ||||||
|  | 
 | ||||||
|  | struct PagePrinters: ConfigWizardPage | ||||||
|  | { | ||||||
|  |     enum Technology { | ||||||
|  |         // Bitflag equivalent of PrinterTechnology
 | ||||||
|  |         T_FFF = 0x1, | ||||||
|  |         T_SLA = 0x2, | ||||||
|  |         T_Any = ~0, | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     std::vector<PrinterPicker *> printer_pickers; | ||||||
|  | 
 | ||||||
|  |     PagePrinters(ConfigWizard *parent, wxString title, wxString shortname, const VendorProfile &vendor, unsigned indent, Technology technology); | ||||||
|  | 
 | ||||||
|  |     void select_all(bool select, bool alternates = false); | ||||||
|  |     int get_width() const; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct PageCustom: ConfigWizardPage | ||||||
|  | { | ||||||
|  |     PageCustom(ConfigWizard *parent); | ||||||
|  | 
 | ||||||
|  |     bool custom_wanted() const { return cb_custom->GetValue(); } | ||||||
|  |     std::string profile_name() const { return into_u8(tc_profile_name->GetValue()); } | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     static const char* default_profile_name; | ||||||
|  | 
 | ||||||
|  |     wxCheckBox *cb_custom; | ||||||
|  |     wxTextCtrl *tc_profile_name; | ||||||
|  |     wxString profile_name_prev; | ||||||
|  | 
 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct PageUpdate: ConfigWizardPage | struct PageUpdate: ConfigWizardPage | ||||||
|  | @ -127,10 +153,7 @@ struct PageVendors: ConfigWizardPage | ||||||
| 
 | 
 | ||||||
|     PageVendors(ConfigWizard *parent); |     PageVendors(ConfigWizard *parent); | ||||||
| 
 | 
 | ||||||
| 	virtual void on_page_set(); |  | ||||||
| 
 |  | ||||||
|     void on_vendor_pick(size_t i); |     void on_vendor_pick(size_t i); | ||||||
| 	void on_variant_checked(); |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct PageFirmware: ConfigWizardPage | struct PageFirmware: ConfigWizardPage | ||||||
|  | @ -174,21 +197,51 @@ class ConfigWizardIndex: public wxPanel | ||||||
| public: | public: | ||||||
|     ConfigWizardIndex(wxWindow *parent); |     ConfigWizardIndex(wxWindow *parent); | ||||||
| 
 | 
 | ||||||
| 	void load_items(ConfigWizardPage *firstpage); |     void add_page(ConfigWizardPage *page); | ||||||
| 	void set_active(ConfigWizardPage *page); |     void add_label(wxString label, unsigned indent = 0); | ||||||
|  | 
 | ||||||
|  |     size_t active_item() const { return item_active; } | ||||||
|  |     ConfigWizardPage* active_page() const; | ||||||
|  |     bool active_is_last() const { return item_active < items.size() && item_active == last_page; } | ||||||
|  | 
 | ||||||
|  |     void go_prev(); | ||||||
|  |     void go_next(); | ||||||
|  |     void go_to(size_t i); | ||||||
|  |     void go_to(ConfigWizardPage *page); | ||||||
|  | 
 | ||||||
|  |     void clear(); | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
|  |     struct Item | ||||||
|  |     { | ||||||
|  |         wxString label; | ||||||
|  |         unsigned indent; | ||||||
|  |         ConfigWizardPage *page;     // nullptr page => label-only item
 | ||||||
|  | 
 | ||||||
|  |         bool operator==(ConfigWizardPage *page) const { return this->page == page; } | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     int em; | ||||||
|  |     int em_h; | ||||||
|  | 
 | ||||||
|     const wxBitmap bg; |     const wxBitmap bg; | ||||||
|     const wxBitmap bullet_black; |     const wxBitmap bullet_black; | ||||||
|     const wxBitmap bullet_blue; |     const wxBitmap bullet_blue; | ||||||
|     const wxBitmap bullet_white; |     const wxBitmap bullet_white; | ||||||
| 	int text_height; |  | ||||||
| 
 | 
 | ||||||
| 	std::vector<wxString> items; |     std::vector<Item> items; | ||||||
| 	std::vector<wxString>::const_iterator item_active; |     size_t item_active; | ||||||
|  |     ssize_t item_hover; | ||||||
|  |     size_t last_page; | ||||||
|  | 
 | ||||||
|  |     int item_height() const { return std::max(bullet_black.GetSize().GetHeight(), em) + em; } | ||||||
| 
 | 
 | ||||||
|     void on_paint(wxPaintEvent &evt); |     void on_paint(wxPaintEvent &evt); | ||||||
|  |     void on_mouse_move(wxMouseEvent &evt); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | wxDEFINE_EVENT(EVT_INDEX_PAGE, wxCommandEvent); | ||||||
|  | 
 | ||||||
| struct ConfigWizard::priv | struct ConfigWizard::priv | ||||||
| { | { | ||||||
|     ConfigWizard *q; |     ConfigWizard *q; | ||||||
|  | @ -209,8 +262,13 @@ struct ConfigWizard::priv | ||||||
|     wxButton *btn_cancel = nullptr; |     wxButton *btn_cancel = nullptr; | ||||||
| 
 | 
 | ||||||
|     PageWelcome      *page_welcome = nullptr; |     PageWelcome      *page_welcome = nullptr; | ||||||
|  |     PagePrinters     *page_fff = nullptr; | ||||||
|  |     PagePrinters     *page_msla = nullptr; | ||||||
|  |     PageCustom       *page_custom = nullptr; | ||||||
|     PageUpdate       *page_update = nullptr; |     PageUpdate       *page_update = nullptr; | ||||||
| 	PageVendors      *page_vendors = nullptr; |     PageVendors      *page_vendors = nullptr;   // XXX: ?
 | ||||||
|  | 
 | ||||||
|  |     // Custom setup pages
 | ||||||
|     PageFirmware     *page_firmware = nullptr; |     PageFirmware     *page_firmware = nullptr; | ||||||
|     PageBedShape     *page_bed = nullptr; |     PageBedShape     *page_bed = nullptr; | ||||||
|     PageDiameters    *page_diams = nullptr; |     PageDiameters    *page_diams = nullptr; | ||||||
|  | @ -218,17 +276,14 @@ struct ConfigWizard::priv | ||||||
| 
 | 
 | ||||||
|     priv(ConfigWizard *q) : q(q) {} |     priv(ConfigWizard *q) : q(q) {} | ||||||
| 
 | 
 | ||||||
|  |     void load_pages(bool custom_setup); | ||||||
|  | 
 | ||||||
|  |     bool check_first_variant() const; | ||||||
|     void load_vendors(); |     void load_vendors(); | ||||||
|     void add_page(ConfigWizardPage *page); |     void add_page(ConfigWizardPage *page); | ||||||
| 	void index_refresh(); |  | ||||||
| 	void set_page(ConfigWizardPage *page); |  | ||||||
| 	void layout_fit(); |  | ||||||
| 	void go_prev() { if (page_current != nullptr) { set_page(page_current->page_prev()); } } |  | ||||||
| 	void go_next() { if (page_current != nullptr) { set_page(page_current->page_next()); } } |  | ||||||
|     void enable_next(bool enable); |     void enable_next(bool enable); | ||||||
| 
 | 
 | ||||||
| 	void on_other_vendors(); |     void on_custom_setup(bool custom_wanted); | ||||||
| 	void on_custom_setup(); |  | ||||||
| 
 | 
 | ||||||
|     void apply_config(AppConfig *app_config, PresetBundle *preset_bundle, const PresetUpdater *updater); |     void apply_config(AppConfig *app_config, PresetBundle *preset_bundle, const PresetUpdater *updater); | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -145,7 +145,11 @@ void Field::get_value_by_opt_type(wxString& str) | ||||||
| 		double val; | 		double val; | ||||||
| 		// Replace the first occurence of comma in decimal number.
 | 		// Replace the first occurence of comma in decimal number.
 | ||||||
| 		str.Replace(",", ".", false); | 		str.Replace(",", ".", false); | ||||||
| 		if(!str.ToCDouble(&val)) |         if (str == ".") | ||||||
|  |             val = 0.0; | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             if (!str.ToCDouble(&val)) | ||||||
|             { |             { | ||||||
|                 show_error(m_parent, _(L("Invalid numeric input."))); |                 show_error(m_parent, _(L("Invalid numeric input."))); | ||||||
|                 set_value(double_to_string(val), true); |                 set_value(double_to_string(val), true); | ||||||
|  | @ -157,6 +161,7 @@ void Field::get_value_by_opt_type(wxString& str) | ||||||
|                 if (val > m_opt.max) val = m_opt.max; |                 if (val > m_opt.max) val = m_opt.max; | ||||||
|                 set_value(double_to_string(val), true); |                 set_value(double_to_string(val), true); | ||||||
|             } |             } | ||||||
|  |         } | ||||||
|         m_value = val; |         m_value = val; | ||||||
| 		break; } | 		break; } | ||||||
| 	case coString: | 	case coString: | ||||||
|  | @ -459,7 +464,7 @@ void SpinCtrl::BUILD() { | ||||||
| // 		# As a workaround, we get the new value from $event->GetString and store
 | // 		# As a workaround, we get the new value from $event->GetString and store
 | ||||||
| // 		# here temporarily so that we can return it from $self->get_value
 | // 		# here temporarily so that we can return it from $self->get_value
 | ||||||
| 		std::string value = e.GetString().utf8_str().data(); | 		std::string value = e.GetString().utf8_str().data(); | ||||||
| 		if (is_matched(value, "^\\d+$")) |         if (is_matched(value, "^\\-?\\d+$")) | ||||||
| 			tmp_value = std::stoi(value); | 			tmp_value = std::stoi(value); | ||||||
|         else tmp_value = -9999; |         else tmp_value = -9999; | ||||||
| #ifdef __WXOSX__ | #ifdef __WXOSX__ | ||||||
|  | @ -475,7 +480,7 @@ void SpinCtrl::BUILD() { | ||||||
| 
 | 
 | ||||||
| void SpinCtrl::propagate_value() | void SpinCtrl::propagate_value() | ||||||
| { | { | ||||||
|     if (tmp_value < 0) |     if (tmp_value == -9999) | ||||||
|         on_kill_focus(); |         on_kill_focus(); | ||||||
|     else if (boost::any_cast<int>(m_value) != tmp_value) |     else if (boost::any_cast<int>(m_value) != tmp_value) | ||||||
|         on_change_field(); |         on_change_field(); | ||||||
|  | @ -867,8 +872,8 @@ void StaticText::BUILD() | ||||||
| 	if (m_opt.height >= 0) size.SetHeight(m_opt.height); | 	if (m_opt.height >= 0) size.SetHeight(m_opt.height); | ||||||
| 	if (m_opt.width >= 0) size.SetWidth(m_opt.width); | 	if (m_opt.width >= 0) size.SetWidth(m_opt.width); | ||||||
| 
 | 
 | ||||||
| 	wxString legend(static_cast<const ConfigOptionString*>(m_opt.default_value)->value); |     const wxString legend(static_cast<const ConfigOptionString*>(m_opt.default_value)->value); | ||||||
| 	auto temp = new wxStaticText(m_parent, wxID_ANY, legend, wxDefaultPosition, size); |     auto temp = new wxStaticText(m_parent, wxID_ANY, legend, wxDefaultPosition, size, wxST_ELLIPSIZE_MIDDLE); | ||||||
|     temp->SetFont(wxGetApp().bold_font()); |     temp->SetFont(wxGetApp().bold_font()); | ||||||
| 
 | 
 | ||||||
| 	// 	// recast as a wxWindow to fit the calling convention
 | 	// 	// recast as a wxWindow to fit the calling convention
 | ||||||
|  |  | ||||||
|  | @ -141,8 +141,8 @@ bool GeometryBuffer::set_from_triangles(const Polygons& triangles, float z, bool | ||||||
|             float inv_size_y = -1.0f / size_y; |             float inv_size_y = -1.0f / size_y; | ||||||
|             for (unsigned int i = 0; i < m_tex_coords.size(); i += 2) |             for (unsigned int i = 0; i < m_tex_coords.size(); i += 2) | ||||||
|             { |             { | ||||||
|                 m_tex_coords[i] *= inv_size_x; |                 m_tex_coords[i] = (m_tex_coords[i] - min_x) * inv_size_x; | ||||||
|                 m_tex_coords[i + 1] *= inv_size_y; |                 m_tex_coords[i + 1] = (m_tex_coords[i + 1] - min_y) * inv_size_y; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -595,11 +595,25 @@ void GLCanvas3D::Bed::_render_prusa(const std::string &key, float theta) const | ||||||
| #endif // ENABLE_PRINT_BED_MODELS
 | #endif // ENABLE_PRINT_BED_MODELS
 | ||||||
| { | { | ||||||
|     std::string tex_path = resources_dir() + "/icons/bed/" + key; |     std::string tex_path = resources_dir() + "/icons/bed/" + key; | ||||||
|  | 
 | ||||||
|  |     // use higher resolution images if graphic card allows
 | ||||||
|  |     GLint max_tex_size; | ||||||
|  |     ::glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_size); | ||||||
|  | 
 | ||||||
|  |     // temporary set to lowest resolution
 | ||||||
|  |     max_tex_size = 2048; | ||||||
|  | 
 | ||||||
|  |     if (max_tex_size >= 8192) | ||||||
|  |         tex_path += "_8192"; | ||||||
|  |     else if (max_tex_size >= 4096) | ||||||
|  |         tex_path += "_4096"; | ||||||
|  | 
 | ||||||
| #if ENABLE_PRINT_BED_MODELS | #if ENABLE_PRINT_BED_MODELS | ||||||
|     std::string model_path = resources_dir() + "/models/" + key; |     std::string model_path = resources_dir() + "/models/" + key; | ||||||
| #endif // ENABLE_PRINT_BED_MODELS
 | #endif // ENABLE_PRINT_BED_MODELS
 | ||||||
| 
 | 
 | ||||||
| #if ENABLE_ANISOTROPIC_FILTER_ON_BED_TEXTURES | #if ENABLE_ANISOTROPIC_FILTER_ON_BED_TEXTURES | ||||||
|  |     // use anisotropic filter if graphic card allows
 | ||||||
|     GLfloat max_anisotropy = 0.0f; |     GLfloat max_anisotropy = 0.0f; | ||||||
|     if (glewIsSupported("GL_EXT_texture_filter_anisotropic")) |     if (glewIsSupported("GL_EXT_texture_filter_anisotropic")) | ||||||
|         ::glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_anisotropy); |         ::glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_anisotropy); | ||||||
|  | @ -646,11 +660,17 @@ void GLCanvas3D::Bed::_render_prusa(const std::string &key, float theta) const | ||||||
|     { |     { | ||||||
|         filename = model_path + "_bed.stl"; |         filename = model_path + "_bed.stl"; | ||||||
|         if ((m_model.get_filename() != filename) && m_model.init_from_file(filename, useVBOs)) { |         if ((m_model.get_filename() != filename) && m_model.init_from_file(filename, useVBOs)) { | ||||||
|             Vec3d offset = m_bounding_box.center() - Vec3d(0.0, 0.0, 0.1 + 0.5 * m_model.get_bounding_box().size()(2)); |             Vec3d offset = m_bounding_box.center() - Vec3d(0.0, 0.0, 0.5 * m_model.get_bounding_box().size()(2)); | ||||||
|             if (key == "mk2") |             if (key == "mk2") | ||||||
|                 offset.y() += 15. / 2.; |                 // hardcoded value to match the stl model
 | ||||||
|  |                 offset += Vec3d(0.0, 7.5, -0.03); | ||||||
|             else if (key == "mk3") |             else if (key == "mk3") | ||||||
|                 offset += Vec3d(0., (19. - 8.) / 2., 2.); |                 // hardcoded value to match the stl model
 | ||||||
|  |                 offset += Vec3d(0.0, 5.5, 2.43); | ||||||
|  |             else if (key == "sl1") | ||||||
|  |                 // hardcoded value to match the stl model
 | ||||||
|  |                 offset += Vec3d(0.0, 0.0, -0.03); | ||||||
|  | 
 | ||||||
|             m_model.center_around(offset); |             m_model.center_around(offset); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -5790,7 +5810,7 @@ void GLCanvas3D::set_tooltip(const std::string& tooltip) const | ||||||
|             else |             else | ||||||
|                 t->SetTip(tooltip); |                 t->SetTip(tooltip); | ||||||
|         } |         } | ||||||
|         else |         else if (!tooltip.empty()) // Avoid "empty" tooltips => unset of the empty tooltip leads to application crash under OSX
 | ||||||
|             m_canvas->SetToolTip(tooltip); |             m_canvas->SetToolTip(tooltip); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -355,21 +355,6 @@ boost::filesystem::path into_path(const wxString &str) | ||||||
| 	return boost::filesystem::path(str.wx_str()); | 	return boost::filesystem::path(str.wx_str()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool get_current_screen_size(wxWindow *window, unsigned &width, unsigned &height) |  | ||||||
| { |  | ||||||
| 	const auto idx = wxDisplay::GetFromWindow(window); |  | ||||||
| 	if (idx == wxNOT_FOUND) { |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	wxDisplay display(idx); |  | ||||||
| 	const auto disp_size = display.GetClientArea(); |  | ||||||
| 	width = disp_size.GetWidth(); |  | ||||||
| 	height = disp_size.GetHeight(); |  | ||||||
| 
 |  | ||||||
| 	return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void about() | void about() | ||||||
| { | { | ||||||
|     AboutDialog dlg; |     AboutDialog dlg; | ||||||
|  |  | ||||||
|  | @ -71,9 +71,6 @@ wxString	from_path(const boost::filesystem::path &path); | ||||||
| // boost path from wxString
 | // boost path from wxString
 | ||||||
| boost::filesystem::path	into_path(const wxString &str); | boost::filesystem::path	into_path(const wxString &str); | ||||||
| 
 | 
 | ||||||
| // Returns the dimensions of the screen on which the main frame is displayed
 |  | ||||||
| bool get_current_screen_size(wxWindow *window, unsigned &width, unsigned &height); |  | ||||||
| 
 |  | ||||||
| // Display an About dialog
 | // Display an About dialog
 | ||||||
| extern void about(); | extern void about(); | ||||||
| // Ask the destop to open the datadir using the default file explorer.
 | // Ask the destop to open the datadir using the default file explorer.
 | ||||||
|  |  | ||||||
|  | @ -351,21 +351,10 @@ void GUI_App::persist_window_geometry(wxTopLevelWindow *window) | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     window_pos_restore(window, name); |     window_pos_restore(window, name); | ||||||
| #ifdef _WIN32 | 
 | ||||||
|     // On windows, the wxEVT_SHOW is not received if the window is created maximized
 |     on_window_geometry(window, [=]() { | ||||||
|     // cf. https://groups.google.com/forum/#!topic/wx-users/c7ntMt6piRI
 |  | ||||||
|     // so we sanitize the position right away
 |  | ||||||
|     window_pos_sanitize(window); |  | ||||||
| #else |  | ||||||
|     // On other platforms on the other hand it's needed to wait before the window is actually on screen
 |  | ||||||
|     // and some initial round of events is complete otherwise position / display index is not reported correctly.
 |  | ||||||
|     window->Bind(wxEVT_SHOW, [=](wxShowEvent &event) { |  | ||||||
|         CallAfter([=]() { |  | ||||||
|         window_pos_sanitize(window); |         window_pos_sanitize(window); | ||||||
|     }); |     }); | ||||||
|         event.Skip(); |  | ||||||
|     }); |  | ||||||
| #endif |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GUI_App::load_project(wxWindow *parent, wxString& input_file) | void GUI_App::load_project(wxWindow *parent, wxString& input_file) | ||||||
|  |  | ||||||
|  | @ -42,10 +42,9 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : | ||||||
| 
 | 
 | ||||||
|     // Objects(sub-objects) name
 |     // Objects(sub-objects) name
 | ||||||
|     def.label = L("Name"); |     def.label = L("Name"); | ||||||
|     // 	def.type = coString;
 |  | ||||||
|     def.gui_type = "legend"; |     def.gui_type = "legend"; | ||||||
|     def.tooltip = L("Object name"); |     def.tooltip = L("Object name"); | ||||||
|     def.full_width = true; |     def.width = 200; | ||||||
|     def.default_value = new ConfigOptionString{ " " }; |     def.default_value = new ConfigOptionString{ " " }; | ||||||
|     m_og->append_single_option_line(Option(def, "object_name")); |     m_og->append_single_option_line(Option(def, "object_name")); | ||||||
| 
 | 
 | ||||||
|  | @ -73,14 +72,8 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : | ||||||
|         def.default_value = new ConfigOptionFloat(0.0); |         def.default_value = new ConfigOptionFloat(0.0); | ||||||
|         def.width = 50; |         def.width = 50; | ||||||
| 
 | 
 | ||||||
|         if (option_name == "Rotation") |  | ||||||
|         { |  | ||||||
|             def.min = -360; |  | ||||||
|             def.max = 360; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // Add "uniform scaling" button in front of "Scale" option 
 |         // Add "uniform scaling" button in front of "Scale" option 
 | ||||||
|         else if (option_name == "Scale") { |         if (option_name == "Scale") { | ||||||
|             line.near_label_widget = [this](wxWindow* parent) { |             line.near_label_widget = [this](wxWindow* parent) { | ||||||
|                 auto btn = new PrusaLockButton(parent, wxID_ANY); |                 auto btn = new PrusaLockButton(parent, wxID_ANY); | ||||||
|                 btn->Bind(wxEVT_BUTTON, [btn, this](wxCommandEvent &event){ |                 btn->Bind(wxEVT_BUTTON, [btn, this](wxCommandEvent &event){ | ||||||
|  | @ -293,13 +286,13 @@ void ObjectManipulation::update_if_dirty() | ||||||
|         deg_rotation(i) = Geometry::rad2deg(m_new_rotation(i)); |         deg_rotation(i) = Geometry::rad2deg(m_new_rotation(i)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (m_cache.rotation(0) != m_new_rotation(0)) |     if ((m_cache.rotation(0) != m_new_rotation(0)) || (m_new_rotation(0) == 0.0)) | ||||||
|         m_og->set_value("rotation_x", double_to_string(deg_rotation(0), 2)); |         m_og->set_value("rotation_x", double_to_string(deg_rotation(0), 2)); | ||||||
| 
 | 
 | ||||||
|     if (m_cache.rotation(1) != m_new_rotation(1)) |     if ((m_cache.rotation(1) != m_new_rotation(1)) || (m_new_rotation(1) == 0.0)) | ||||||
|         m_og->set_value("rotation_y", double_to_string(deg_rotation(1), 2)); |         m_og->set_value("rotation_y", double_to_string(deg_rotation(1), 2)); | ||||||
| 
 | 
 | ||||||
|     if (m_cache.rotation(2) != m_new_rotation(2)) |     if ((m_cache.rotation(2) != m_new_rotation(2)) || (m_new_rotation(2) == 0.0)) | ||||||
|         m_og->set_value("rotation_z", double_to_string(deg_rotation(2), 2)); |         m_og->set_value("rotation_z", double_to_string(deg_rotation(2), 2)); | ||||||
| 
 | 
 | ||||||
|     m_cache.rotation = deg_rotation; |     m_cache.rotation = deg_rotation; | ||||||
|  |  | ||||||
|  | @ -26,6 +26,28 @@ wxTopLevelWindow* find_toplevel_parent(wxWindow *window) | ||||||
|     return nullptr; |     return nullptr; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void on_window_geometry(wxTopLevelWindow *tlw, std::function<void()> callback) | ||||||
|  | { | ||||||
|  | #ifdef _WIN32 | ||||||
|  |     // On windows, the wxEVT_SHOW is not received if the window is created maximized
 | ||||||
|  |     // cf. https://groups.google.com/forum/#!topic/wx-users/c7ntMt6piRI
 | ||||||
|  |     // OTOH the geometry is available very soon, so we can call the callback right away
 | ||||||
|  |     callback(); | ||||||
|  | #elif defined __linux__ | ||||||
|  |     tlw->Bind(wxEVT_SHOW, [=](wxShowEvent &evt) { | ||||||
|  |         // On Linux, the geometry is only available after wxEVT_SHOW + CallAfter
 | ||||||
|  |         // cf. https://groups.google.com/forum/?pli=1#!topic/wx-users/fERSXdpVwAI
 | ||||||
|  |         tlw->CallAfter([=]() { callback(); }); | ||||||
|  |         evt.Skip(); | ||||||
|  |     }); | ||||||
|  | #elif defined __APPLE__ | ||||||
|  |     tlw->Bind(wxEVT_SHOW, [=](wxShowEvent &evt) { | ||||||
|  |         callback(); | ||||||
|  |         evt.Skip(); | ||||||
|  |     }); | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| CheckboxFileDialog::ExtraPanel::ExtraPanel(wxWindow *parent) | CheckboxFileDialog::ExtraPanel::ExtraPanel(wxWindow *parent) | ||||||
|     : wxPanel(parent, wxID_ANY) |     : wxPanel(parent, wxID_ANY) | ||||||
|  |  | ||||||
|  | @ -4,6 +4,7 @@ | ||||||
| #include <memory> | #include <memory> | ||||||
| #include <string> | #include <string> | ||||||
| #include <ostream> | #include <ostream> | ||||||
|  | #include <functional> | ||||||
| 
 | 
 | ||||||
| #include <boost/optional.hpp> | #include <boost/optional.hpp> | ||||||
| 
 | 
 | ||||||
|  | @ -24,6 +25,8 @@ namespace GUI { | ||||||
| 
 | 
 | ||||||
| wxTopLevelWindow* find_toplevel_parent(wxWindow *window); | wxTopLevelWindow* find_toplevel_parent(wxWindow *window); | ||||||
| 
 | 
 | ||||||
|  | void on_window_geometry(wxTopLevelWindow *tlw, std::function<void()> callback); | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| class EventGuard | class EventGuard | ||||||
| { | { | ||||||
|  |  | ||||||
|  | @ -12,7 +12,6 @@ | ||||||
| 
 | 
 | ||||||
| #include <wx/sizer.h> | #include <wx/sizer.h> | ||||||
| #include <wx/stattext.h> | #include <wx/stattext.h> | ||||||
| #include <wx/notebook.h> |  | ||||||
| #include <wx/button.h> | #include <wx/button.h> | ||||||
| #include <wx/bmpcbox.h> | #include <wx/bmpcbox.h> | ||||||
| #include <wx/statbox.h> | #include <wx/statbox.h> | ||||||
|  | @ -1092,7 +1091,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) | ||||||
|     : q(q) |     : q(q) | ||||||
|     , main_frame(main_frame) |     , main_frame(main_frame) | ||||||
|     , config(Slic3r::DynamicPrintConfig::new_from_defaults_keys({ |     , config(Slic3r::DynamicPrintConfig::new_from_defaults_keys({ | ||||||
|         "bed_shape", "complete_objects", "extruder_clearance_radius", "skirts", "skirt_distance", |         "bed_shape", "complete_objects", "duplicate_distance", "extruder_clearance_radius", "skirts", "skirt_distance", | ||||||
|         "brim_width", "variable_layer_height", "serial_port", "serial_speed", "host_type", "print_host", |         "brim_width", "variable_layer_height", "serial_port", "serial_speed", "host_type", "print_host", | ||||||
|         "printhost_apikey", "printhost_cafile", "nozzle_diameter", "single_extruder_multi_material", |         "printhost_apikey", "printhost_cafile", "nozzle_diameter", "single_extruder_multi_material", | ||||||
|         "wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", |         "wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", | ||||||
|  | @ -1774,8 +1773,11 @@ void Plater::priv::arrange() | ||||||
|     // FIXME: I don't know how to obtain the minimum distance, it depends
 |     // FIXME: I don't know how to obtain the minimum distance, it depends
 | ||||||
|     // on printer technology. I guess the following should work but it crashes.
 |     // on printer technology. I guess the following should work but it crashes.
 | ||||||
|     double dist = 6; //PrintConfig::min_object_distance(config);
 |     double dist = 6; //PrintConfig::min_object_distance(config);
 | ||||||
|  |     if(printer_technology == ptFFF) { | ||||||
|  |         dist = PrintConfig::min_object_distance(config); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     auto min_obj_distance = static_cast<coord_t>(dist/SCALING_FACTOR); |     auto min_obj_distance = coord_t(dist/SCALING_FACTOR); | ||||||
| 
 | 
 | ||||||
|     const auto *bed_shape_opt = config->opt<ConfigOptionPoints>("bed_shape"); |     const auto *bed_shape_opt = config->opt<ConfigOptionPoints>("bed_shape"); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -11,8 +11,10 @@ | ||||||
|     #include <Windows.h> |     #include <Windows.h> | ||||||
| #endif /* _MSC_VER */ | #endif /* _MSC_VER */ | ||||||
| 
 | 
 | ||||||
|  | #include <algorithm> | ||||||
| #include <fstream> | #include <fstream> | ||||||
| #include <stdexcept> | #include <stdexcept> | ||||||
|  | #include <unordered_map> | ||||||
| #include <boost/format.hpp> | #include <boost/format.hpp> | ||||||
| #include <boost/filesystem.hpp> | #include <boost/filesystem.hpp> | ||||||
| #include <boost/filesystem/fstream.hpp> | #include <boost/filesystem/fstream.hpp> | ||||||
|  | @ -83,6 +85,16 @@ VendorProfile VendorProfile::from_ini(const boost::filesystem::path &path, bool | ||||||
|     return VendorProfile::from_ini(tree, path, load_all); |     return VendorProfile::from_ini(tree, path, load_all); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static const std::unordered_map<std::string, std::string> pre_family_model_map {{ | ||||||
|  |     { "MK3",        "MK3" }, | ||||||
|  |     { "MK3MMU2",    "MK3" }, | ||||||
|  |     { "MK2.5",      "MK2.5" }, | ||||||
|  |     { "MK2.5MMU2",  "MK2.5" }, | ||||||
|  |     { "MK2S",       "MK2" }, | ||||||
|  |     { "MK2SMM",     "MK2" }, | ||||||
|  |     { "SL1",        "SL1" }, | ||||||
|  | }}; | ||||||
|  | 
 | ||||||
| VendorProfile VendorProfile::from_ini(const ptree &tree, const boost::filesystem::path &path, bool load_all) | VendorProfile VendorProfile::from_ini(const ptree &tree, const boost::filesystem::path &path, bool load_all) | ||||||
| { | { | ||||||
|     static const std::string printer_model_key = "printer_model:"; |     static const std::string printer_model_key = "printer_model:"; | ||||||
|  | @ -128,11 +140,21 @@ VendorProfile VendorProfile::from_ini(const ptree &tree, const boost::filesystem | ||||||
|             VendorProfile::PrinterModel model; |             VendorProfile::PrinterModel model; | ||||||
|             model.id = section.first.substr(printer_model_key.size()); |             model.id = section.first.substr(printer_model_key.size()); | ||||||
|             model.name = section.second.get<std::string>("name", model.id); |             model.name = section.second.get<std::string>("name", model.id); | ||||||
|             auto technology_field = section.second.get<std::string>("technology", "FFF"); | 
 | ||||||
|  |             const char *technology_fallback = boost::algorithm::starts_with(model.id, "SL") ? "SLA" : "FFF"; | ||||||
|  | 
 | ||||||
|  |             auto technology_field = section.second.get<std::string>("technology", technology_fallback); | ||||||
|             if (! ConfigOptionEnum<PrinterTechnology>::from_string(technology_field, model.technology)) { |             if (! ConfigOptionEnum<PrinterTechnology>::from_string(technology_field, model.technology)) { | ||||||
|                 BOOST_LOG_TRIVIAL(error) << boost::format("Vendor bundle: `%1%`: Invalid printer technology field: `%2%`") % id % technology_field; |                 BOOST_LOG_TRIVIAL(error) << boost::format("Vendor bundle: `%1%`: Invalid printer technology field: `%2%`") % id % technology_field; | ||||||
|                 model.technology = ptFFF; |                 model.technology = ptFFF; | ||||||
|             } |             } | ||||||
|  | 
 | ||||||
|  |             model.family = section.second.get<std::string>("family", std::string()); | ||||||
|  |             if (model.family.empty() && res.name == "Prusa Research") { | ||||||
|  |                 // If no family is specified, it can be inferred for known printers
 | ||||||
|  |                 const auto from_pre_map = pre_family_model_map.find(model.id); | ||||||
|  |                 if (from_pre_map != pre_family_model_map.end()) { model.family = from_pre_map->second; } | ||||||
|  |             } | ||||||
| #if 0 | #if 0 | ||||||
| 			// Remove SLA printers from the initial alpha.
 | 			// Remove SLA printers from the initial alpha.
 | ||||||
| 			if (model.technology == ptSLA) | 			if (model.technology == ptSLA) | ||||||
|  | @ -157,6 +179,20 @@ VendorProfile VendorProfile::from_ini(const ptree &tree, const boost::filesystem | ||||||
|     return res; |     return res; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | std::vector<std::string> VendorProfile::families() const | ||||||
|  | { | ||||||
|  |     std::vector<std::string> res; | ||||||
|  |     unsigned num_familiies = 0; | ||||||
|  | 
 | ||||||
|  |     for (auto &model : models) { | ||||||
|  |         if (std::find(res.begin(), res.end(), model.family) == res.end()) { | ||||||
|  |             res.push_back(model.family); | ||||||
|  |             num_familiies++; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return res; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| // Suffix to be added to a modified preset name in the combo box.
 | // Suffix to be added to a modified preset name in the combo box.
 | ||||||
| static std::string g_suffix_modified = " (modified)"; | static std::string g_suffix_modified = " (modified)"; | ||||||
|  |  | ||||||
|  | @ -54,13 +54,16 @@ public: | ||||||
|         std::string                 id; |         std::string                 id; | ||||||
|         std::string                 name; |         std::string                 name; | ||||||
|         PrinterTechnology           technology; |         PrinterTechnology           technology; | ||||||
|  |         std::string                 family; | ||||||
|         std::vector<PrinterVariant> variants; |         std::vector<PrinterVariant> variants; | ||||||
|  | 
 | ||||||
|         PrinterVariant*       variant(const std::string &name) { |         PrinterVariant*       variant(const std::string &name) { | ||||||
|             for (auto &v : this->variants) |             for (auto &v : this->variants) | ||||||
|                 if (v.name == name) |                 if (v.name == name) | ||||||
|                     return &v; |                     return &v; | ||||||
|             return nullptr; |             return nullptr; | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|         const PrinterVariant* variant(const std::string &name) const { return const_cast<PrinterModel*>(this)->variant(name); } |         const PrinterVariant* variant(const std::string &name) const { return const_cast<PrinterModel*>(this)->variant(name); } | ||||||
|     }; |     }; | ||||||
|     std::vector<PrinterModel>          models; |     std::vector<PrinterModel>          models; | ||||||
|  | @ -72,6 +75,7 @@ public: | ||||||
|     static VendorProfile from_ini(const boost::property_tree::ptree &tree, const boost::filesystem::path &path, bool load_all=true); |     static VendorProfile from_ini(const boost::property_tree::ptree &tree, const boost::filesystem::path &path, bool load_all=true); | ||||||
| 
 | 
 | ||||||
|     size_t      num_variants() const { size_t n = 0; for (auto &model : models) n += model.variants.size(); return n; } |     size_t      num_variants() const { size_t n = 0; for (auto &model : models) n += model.variants.size(); return n; } | ||||||
|  |     std::vector<std::string> families() const; | ||||||
| 
 | 
 | ||||||
|     bool        operator< (const VendorProfile &rhs) const { return this->id <  rhs.id; } |     bool        operator< (const VendorProfile &rhs) const { return this->id <  rhs.id; } | ||||||
|     bool        operator==(const VendorProfile &rhs) const { return this->id == rhs.id; } |     bool        operator==(const VendorProfile &rhs) const { return this->id == rhs.id; } | ||||||
|  |  | ||||||
 tamasmeszaros
						tamasmeszaros