From 7645e9cb7a884a4722324b7b5a839424291299fb Mon Sep 17 00:00:00 2001
From: bubnikv <bubnikv@gmail.com>
Date: Tue, 15 May 2018 14:04:29 +0200
Subject: [PATCH 1/7] Added layer_num, layer_z variables to the end_gcode,
 end_filament_gcode, added min(.,.), max(.,.) functions to the placeholder
 parser syntax.

---
 t/custom_gcode.t                       |  6 +++-
 xs/src/libslic3r/GCode.cpp             | 19 +++++++-----
 xs/src/libslic3r/PlaceholderParser.cpp | 41 ++++++++++++++++++++++++++
 3 files changed, 58 insertions(+), 8 deletions(-)

diff --git a/t/custom_gcode.t b/t/custom_gcode.t
index 7c2a75f29..4c1c1b108 100644
--- a/t/custom_gcode.t
+++ b/t/custom_gcode.t
@@ -1,4 +1,4 @@
-use Test::More tests => 77;
+use Test::More tests => 81;
 use strict;
 use warnings;
 
@@ -71,6 +71,10 @@ use Slic3r::Test;
     is $parser->process('{2*foo*(3-12)}'), '0', 'math: 2*foo*(3-12)';
     is $parser->process('{2*bar*(3-12)}'), '-36', 'math: 2*bar*(3-12)';
     ok abs($parser->process('{2.5*bar*(3-12)}') - -45) < 1e-7, 'math: 2.5*bar*(3-12)';
+    is $parser->process('{min(12, 14)}'), '12', 'math: min(12, 14)';
+    is $parser->process('{max(12, 14)}'), '14', 'math: max(12, 14)';
+    is $parser->process('{min(13.4, -1238.1)}'), '-1238.1', 'math: min(13.4, -1238.1)';
+    is $parser->process('{max(13.4, -1238.1)}'), '13.4', 'math: max(13.4, -1238.1)';
 
     # Test the boolean expression parser.
     is $parser->evaluate_boolean_expression('12 == 12'), 1, 'boolean expression parser: 12 == 12';
diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp
index dc8e5d691..5e5b74efc 100644
--- a/xs/src/libslic3r/GCode.cpp
+++ b/xs/src/libslic3r/GCode.cpp
@@ -789,14 +789,19 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
     }
 
     // Process filament-specific gcode in extruder order.
-    if (print.config.single_extruder_multi_material) {
-        // Process the end_filament_gcode for the active filament only.
-        _writeln(file, this->placeholder_parser_process("end_filament_gcode", print.config.end_filament_gcode.get_at(m_writer.extruder()->id()), m_writer.extruder()->id()));
-    } else {
-        for (const std::string &end_gcode : print.config.end_filament_gcode.values)
-            _writeln(file, this->placeholder_parser_process("end_filament_gcode", end_gcode, (unsigned int)(&end_gcode - &print.config.end_filament_gcode.values.front())));
+    {
+        DynamicConfig config;
+        config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
+        config.set_key_value("layer_z",   new ConfigOptionFloat(m_writer.get_position().z - m_config.z_offset.value));
+        if (print.config.single_extruder_multi_material) {
+            // Process the end_filament_gcode for the active filament only.
+            _writeln(file, this->placeholder_parser_process("end_filament_gcode", print.config.end_filament_gcode.get_at(m_writer.extruder()->id()), m_writer.extruder()->id(), &config));
+        } else {
+            for (const std::string &end_gcode : print.config.end_filament_gcode.values)
+                _writeln(file, this->placeholder_parser_process("end_filament_gcode", end_gcode, (unsigned int)(&end_gcode - &print.config.end_filament_gcode.values.front(), &config)));
+        }
+        _writeln(file, this->placeholder_parser_process("end_gcode", print.config.end_gcode, m_writer.extruder()->id(), &config));
     }
-    _writeln(file, this->placeholder_parser_process("end_gcode", print.config.end_gcode, m_writer.extruder()->id()));
     _write(file, m_writer.update_progress(m_layer_count, m_layer_count, true)); // 100%
     _write(file, m_writer.postamble());
 
diff --git a/xs/src/libslic3r/PlaceholderParser.cpp b/xs/src/libslic3r/PlaceholderParser.cpp
index 62b516935..80740b20d 100644
--- a/xs/src/libslic3r/PlaceholderParser.cpp
+++ b/xs/src/libslic3r/PlaceholderParser.cpp
@@ -414,6 +414,7 @@ namespace client
             lhs.type = TYPE_BOOL;
             lhs.data.b = invert ? ! value : value;
         }
+        // Compare operators, store the result into lhs.
         static void equal    (expr &lhs, expr &rhs) { compare_op(lhs, rhs, '=', false); }
         static void not_equal(expr &lhs, expr &rhs) { compare_op(lhs, rhs, '=', true ); }
         static void lower    (expr &lhs, expr &rhs) { compare_op(lhs, rhs, '<', false); }
@@ -421,6 +422,40 @@ namespace client
         static void leq      (expr &lhs, expr &rhs) { compare_op(lhs, rhs, '>', true ); }
         static void geq      (expr &lhs, expr &rhs) { compare_op(lhs, rhs, '<', true ); }
 
+        enum Function2ParamsType {
+            FUNCTION_MIN,
+            FUNCTION_MAX,
+        };
+        // Store the result into param1.
+        static void function_2params(expr &param1, expr &param2, Function2ParamsType fun)
+        { 
+            const char *err_msg = "Not a numeric type.";
+            param1.throw_if_not_numeric(err_msg);
+            param2.throw_if_not_numeric(err_msg);
+            if (param1.type == TYPE_DOUBLE || param2.type == TYPE_DOUBLE) {
+                double d = 0.;
+                switch (fun) {
+                    case FUNCTION_MIN:  d = std::min(param1.as_d(), param2.as_d()); break;
+                    case FUNCTION_MAX:  d = std::max(param1.as_d(), param2.as_d()); break;
+                    default: param1.throw_exception("Internal error: invalid function");
+                }
+                param1.data.d = d;
+                param1.type = TYPE_DOUBLE;
+            } else {
+                int i = 0.;
+                switch (fun) {
+                    case FUNCTION_MIN:  i = std::min(param1.as_i(), param2.as_i()); break;
+                    case FUNCTION_MAX:  i = std::max(param1.as_i(), param2.as_i()); break;
+                    default: param1.throw_exception("Internal error: invalid function");
+                }
+                param1.data.i = i;
+                param1.type = TYPE_INT;
+            }
+        }
+        // Store the result into param1.
+        static void min(expr &param1, expr &param2) { function_2params(param1, param2, FUNCTION_MIN); }
+        static void max(expr &param1, expr &param2) { function_2params(param1, param2, FUNCTION_MAX); }
+
         static void regex_op(expr &lhs, boost::iterator_range<Iterator> &rhs, char op)
         {
             const std::string *subject  = nullptr;
@@ -1019,6 +1054,10 @@ namespace client
                 |   (lit('-')  > unary_expression(_r1)           )  [ px::bind(&FactorActions::minus_,  _1,     _val) ]
                 |   (lit('+')  > unary_expression(_r1) > iter_pos)  [ px::bind(&FactorActions::expr_,   _1, _2, _val) ]
                 |   ((kw["not"] | '!') > unary_expression(_r1) > iter_pos) [ px::bind(&FactorActions::not_, _1, _val) ]
+                |   (kw["min"] > '(' > conditional_expression(_r1) [_val = _1] > ',' > conditional_expression(_r1) > ')') 
+                                                                    [ px::bind(&expr<Iterator>::min, _val, _2) ]
+                |   (kw["max"] > '(' > conditional_expression(_r1) [_val = _1] > ',' > conditional_expression(_r1) > ')') 
+                                                                    [ px::bind(&expr<Iterator>::max, _val, _2) ]
                 |   (strict_double > iter_pos)                      [ px::bind(&FactorActions::double_, _1, _2, _val) ]
                 |   (int_      > iter_pos)                          [ px::bind(&FactorActions::int_,    _1, _2, _val) ]
                 |   (kw[bool_] > iter_pos)                          [ px::bind(&FactorActions::bool_,   _1, _2, _val) ]
@@ -1051,6 +1090,8 @@ namespace client
                 ("elsif")
                 ("endif")
                 ("false")
+                ("min")
+                ("max")
                 ("not")
                 ("or")
                 ("true");

From 4b87f71bbc46e2b974850fab2846c2dfadd70fd2 Mon Sep 17 00:00:00 2001
From: bubnikv <bubnikv@gmail.com>
Date: Tue, 15 May 2018 14:20:32 +0200
Subject: [PATCH 2/7] Fix of the previous commmit. gcc and clang rightfully
 complained about a typo.

---
 xs/src/libslic3r/GCode.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp
index 5e5b74efc..b581b3e76 100644
--- a/xs/src/libslic3r/GCode.cpp
+++ b/xs/src/libslic3r/GCode.cpp
@@ -798,7 +798,7 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
             _writeln(file, this->placeholder_parser_process("end_filament_gcode", print.config.end_filament_gcode.get_at(m_writer.extruder()->id()), m_writer.extruder()->id(), &config));
         } else {
             for (const std::string &end_gcode : print.config.end_filament_gcode.values)
-                _writeln(file, this->placeholder_parser_process("end_filament_gcode", end_gcode, (unsigned int)(&end_gcode - &print.config.end_filament_gcode.values.front(), &config)));
+                _writeln(file, this->placeholder_parser_process("end_filament_gcode", end_gcode, (unsigned int)(&end_gcode - &print.config.end_filament_gcode.values.front()), &config));
         }
         _writeln(file, this->placeholder_parser_process("end_gcode", print.config.end_gcode, m_writer.extruder()->id(), &config));
     }

From 5c44453ced6a1b80061220bbc79d754a4f4a6b8e Mon Sep 17 00:00:00 2001
From: bubnikv <bubnikv@gmail.com>
Date: Wed, 16 May 2018 10:11:00 +0200
Subject: [PATCH 3/7] Fixed loading of configuration files after reverting to a
 snapshot storing the old configuration format.

---
 xs/src/slic3r/GUI/PresetBundle.cpp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/xs/src/slic3r/GUI/PresetBundle.cpp b/xs/src/slic3r/GUI/PresetBundle.cpp
index 63b6a4e0c..84fa3a92f 100644
--- a/xs/src/slic3r/GUI/PresetBundle.cpp
+++ b/xs/src/slic3r/GUI/PresetBundle.cpp
@@ -210,6 +210,10 @@ std::string PresetBundle::load_system_presets()
                 errors_cummulative += "\n";
             }
         }
+	if (first) {
+		// No config bundle loaded, reset.
+		this->reset(false);
+	}
     return errors_cummulative;
 }
 

From a97226ae54fc28c6bff790a51f45842868105478 Mon Sep 17 00:00:00 2001
From: Vojtech Kral <vojtech@kral.hk>
Date: Tue, 15 May 2018 12:14:26 +0200
Subject: [PATCH 4/7] PresetUpdater: Fix: Don't offer updates on legacy datadir

---
 xs/src/slic3r/Utils/PresetUpdater.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/xs/src/slic3r/Utils/PresetUpdater.cpp b/xs/src/slic3r/Utils/PresetUpdater.cpp
index 3b74b0c6b..fcbe20fb7 100644
--- a/xs/src/slic3r/Utils/PresetUpdater.cpp
+++ b/xs/src/slic3r/Utils/PresetUpdater.cpp
@@ -136,7 +136,7 @@ void PresetUpdater::priv::set_download_prefs(AppConfig *app_config)
 {
 	enabled_version_check = app_config->get("version_check") == "1";
 	version_check_url = app_config->version_check_url();
-	enabled_config_update = app_config->get("preset_update") == "1";
+	enabled_config_update = app_config->get("preset_update") == "1" && !app_config->legacy_datadir();
 }
 
 // Downloads a file (http get operation). Cancels if the Updater is being destroyed.

From 0b4a61a8bad7d507a6ad93314346a879682a2b5c Mon Sep 17 00:00:00 2001
From: bubnikv <bubnikv@gmail.com>
Date: Wed, 16 May 2018 12:16:30 +0200
Subject: [PATCH 5/7] Fix of https://github.com/prusa3d/Slic3r/issues/791 The
 preset names have to be set at the PlaceholderParser before querying Print
 for a recommended file name.

---
 lib/Slic3r/GUI/Plater.pm | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm
index eb655ae55..9d546db9d 100644
--- a/lib/Slic3r/GUI/Plater.pm
+++ b/lib/Slic3r/GUI/Plater.pm
@@ -1375,6 +1375,8 @@ sub export_gcode {
     };
     Slic3r::GUI::catch_error($self) and return;
     
+    # Copy the names of active presets into the placeholder parser.
+    wxTheApp->{preset_bundle}->export_selections_pp($self->{print}->placeholder_parser);
     # select output file
     if ($output_file) {
         $self->{export_gcode_output_file} = eval { $self->{print}->output_filepath($output_file) };
@@ -1666,6 +1668,8 @@ sub _get_export_file {
         $suffix = '.3mf';
         $wildcard = 'threemf';
     }
+    # Copy the names of active presets into the placeholder parser.
+    wxTheApp->{preset_bundle}->export_selections_pp($self->{print}->placeholder_parser);
     my $output_file = eval { $self->{print}->output_filepath($main::opt{output} // '') };
     Slic3r::GUI::catch_error($self) and return undef;
     $output_file =~ s/\.[gG][cC][oO][dD][eE]$/$suffix/;

From b8fe48c56339333f67b33c2d9cfa612997a96d09 Mon Sep 17 00:00:00 2001
From: YuSanka <yusanka@gmail.com>
Date: Wed, 16 May 2018 13:56:03 +0200
Subject: [PATCH 6/7] Modification of the AboutDialog to be correct showing on
 dark theme of Linux

---
 xs/src/slic3r/GUI/AboutDialog.cpp | 50 ++++++++++++++++++-------------
 xs/src/slic3r/GUI/Field.cpp       |  2 +-
 2 files changed, 31 insertions(+), 21 deletions(-)

diff --git a/xs/src/slic3r/GUI/AboutDialog.cpp b/xs/src/slic3r/GUI/AboutDialog.cpp
index e3c452872..0fed8d175 100644
--- a/xs/src/slic3r/GUI/AboutDialog.cpp
+++ b/xs/src/slic3r/GUI/AboutDialog.cpp
@@ -29,20 +29,27 @@ void AboutDialogLogo::onRepaint(wxEvent &event)
 }
 
 AboutDialog::AboutDialog()
-    : wxDialog(NULL, wxID_ANY, _(L("About Slic3r")), wxDefaultPosition, wxSize(600, 340), wxCAPTION)
+    : wxDialog(NULL, wxID_ANY, _(L("About Slic3r")), wxDefaultPosition, wxDefaultSize, wxCAPTION)
 {
-	SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)/**wxWHITE*/);
+	wxColour bgr_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
+	SetBackgroundColour(bgr_clr);
     wxBoxSizer* hsizer = new wxBoxSizer(wxHORIZONTAL);
-    this->SetSizer(hsizer);
+
+	auto main_sizer = new wxBoxSizer(wxVERTICAL);
+	main_sizer->Add(hsizer, 0, wxEXPAND | wxALL, 20);
 
     // logo
-//     AboutDialogLogo* logo = new AboutDialogLogo(this);
 	wxBitmap logo_bmp = wxBitmap(from_u8(Slic3r::var("Slic3r_192px.png")), wxBITMAP_TYPE_PNG);
 	auto *logo = new wxStaticBitmap(this, wxID_ANY, std::move(logo_bmp));
-    hsizer->Add(logo, 0, wxEXPAND | wxLEFT | wxRIGHT, 30);
+	hsizer->Add(logo, 1, wxALIGN_CENTRE_VERTICAL | wxEXPAND | wxTOP | wxBOTTOM, 35);
     
     wxBoxSizer* vsizer = new wxBoxSizer(wxVERTICAL);
-    hsizer->Add(vsizer, 1, wxEXPAND, 0);
+#ifdef __WXMSW__
+	int proportion = 2;
+#else
+	int proportion = 3;
+#endif
+    hsizer->Add(vsizer, proportion, wxEXPAND|wxLEFT, 20);
 
     // title
     {
@@ -52,7 +59,7 @@ AboutDialog::AboutDialog()
         title_font.SetFamily(wxFONTFAMILY_ROMAN);
         title_font.SetPointSize(24);
         title->SetFont(title_font);
-        vsizer->Add(title, 0, wxALIGN_LEFT | wxTOP, 30);
+        vsizer->Add(title, 0, wxALIGN_LEFT | wxTOP, 10);
     }
     
     // version
@@ -70,34 +77,34 @@ AboutDialog::AboutDialog()
     }
     
     // text
-    wxHtmlWindow* html = new wxHtmlWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHW_SCROLLBAR_NEVER);
+    wxHtmlWindow* html = new wxHtmlWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHW_SCROLLBAR_AUTO/*NEVER*/);
     {
         wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
-        #ifdef __WXMSW__
-            int size[] = {8,8,8,8,8,8,8};
-        #else
-            int size[] = {11,11,11,11,11,11,11};
-        #endif
+        const auto text_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
+		auto text_clr_str = wxString::Format(wxT("#%02X%02X%02X"), text_clr.Red(), text_clr.Green(), text_clr.Blue());
+		auto bgr_clr_str = wxString::Format(wxT("#%02X%02X%02X"), bgr_clr.Red(), bgr_clr.Green(), bgr_clr.Blue());
+
+		const int fs = font.GetPointSize()-1;
+        int size[] = {fs,fs,fs,fs,fs,fs,fs};
         html->SetFonts(font.GetFaceName(), font.GetFaceName(), size);
-		html->SetHTMLBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
         html->SetBorders(2);
-        const char* text =
+		const auto text = wxString::Format(
             "<html>"
-            "<body bgcolor=\"#ffffff\" link=\"#808080\">"
-            "<font color=\"#808080\">"
+            "<body bgcolor= %s link= %s>"
+            "<font color=%s>"
             "Copyright &copy; 2016-2018 Prusa Research. <br />"
             "Copyright &copy; 2011-2017 Alessandro Ranellucci. <br />"
             "<a href=\"http://slic3r.org/\">Slic3r</a> is licensed under the "
             "<a href=\"http://www.gnu.org/licenses/agpl-3.0.html\">GNU Affero General Public License, version 3</a>."
-            "<br /><br /><br />"
+            "<br /><br />"
             "Contributions by Henrik Brix Andersen, Nicolas Dandrimont, Mark Hindess, Petr Ledvina, Joseph Lenox, Y. Sapir, Mike Sheldrake, Vojtech Bubnik and numerous others. "
             "Manual by Gary Hodgson. Inspired by the RepRap community. <br />"
             "Slic3r logo designed by Corey Daniels, <a href=\"http://www.famfamfam.com/lab/icons/silk/\">Silk Icon Set</a> designed by Mark James. "
             "</font>"
             "</body>"
-            "</html>";
+            "</html>", bgr_clr_str, text_clr_str, text_clr_str);
         html->SetPage(text);
-        vsizer->Add(html, 1, wxEXPAND | wxALIGN_LEFT | wxRIGHT | wxBOTTOM, 20);
+        vsizer->Add(html, 1, wxEXPAND | wxBOTTOM, 10);
         html->Bind(wxEVT_HTML_LINK_CLICKED, &AboutDialog::onLinkClicked, this);
     }
     
@@ -108,6 +115,9 @@ AboutDialog::AboutDialog()
     
     this->Bind(wxEVT_LEFT_DOWN, &AboutDialog::onCloseDialog, this);
     logo->Bind(wxEVT_LEFT_DOWN, &AboutDialog::onCloseDialog, this);
+
+	SetSizer(main_sizer);
+	main_sizer->SetSizeHints(this);
 }
 
 void AboutDialog::onLinkClicked(wxHtmlLinkEvent &event)
diff --git a/xs/src/slic3r/GUI/Field.cpp b/xs/src/slic3r/GUI/Field.cpp
index 4febae362..64f3426c4 100644
--- a/xs/src/slic3r/GUI/Field.cpp
+++ b/xs/src/slic3r/GUI/Field.cpp
@@ -106,7 +106,7 @@ namespace Slic3r { namespace GUI {
 			}
 			double val;
 			str.ToCDouble(&val);
-			if (m_opt.min > val && val > m_opt.max)
+			if (m_opt.min > val || val > m_opt.max)
 			{
 				show_error(m_parent, _(L("Input value is out of range")));
 				if (m_opt.min > val) val = m_opt.min;

From 687c91d6e965065af4e39589c7713df23a9cd078 Mon Sep 17 00:00:00 2001
From: bubnikv <bubnikv@gmail.com>
Date: Wed, 16 May 2018 16:34:07 +0200
Subject: [PATCH 7/7] Parsing of obsolete presets from Config Bundle to remove
 them from user's profile when upgrading to a new configuration structure.

---
 resources/profiles/PrusaResearch.ini |  5 +++++
 xs/src/slic3r/GUI/PresetBundle.cpp   | 24 +++++++++++++++++++++++-
 xs/src/slic3r/GUI/PresetBundle.hpp   |  7 +++++++
 3 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/resources/profiles/PrusaResearch.ini b/resources/profiles/PrusaResearch.ini
index ba8e55ad4..a28405921 100644
--- a/resources/profiles/PrusaResearch.ini
+++ b/resources/profiles/PrusaResearch.ini
@@ -1030,3 +1030,8 @@ max_print_height = 210
 start_gcode = M115 U3.1.1-RC5 ; tell printer latest fw version\nM201 X1000 Y1000 Z200 E5000 ; sets maximum accelerations, mm/sec^2\nM203 X200 Y200 Z12 E120 ; sets maximum feedrates, mm/sec\nM204 S1250 T1250 ; sets acceleration (S) and retract acceleration (T)\nM205 X10 Y10 Z0.4 E2.5 ; sets the jerk limits, mm/sec\nM205 S0 T0 ; sets the minimum extruding and travel feed rate, mm/sec\nM83  ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0  F1000.0 ; intro line\nG1 X100.0 E12.5  F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height==0.05}100{else}95{endif}
 printer_model = MK3
 default_print_profile = 0.15mm OPTIMAL 0.6 nozzle MK3
+
+# The obsolete presets will be removed when upgrading from the legacy configuration structure (up to Slic3r 1.39.2) to 1.40.0 and newer.
+[obsolete_presets]
+print="0.05mm DETAIL 0.25 nozzle";"0.05mm DETAIL MK3";"0.05mm DETAIL";"0.20mm NORMAL MK3";"0.35mm FAST MK3"
+filament="ColorFabb Brass Bronze  1.75mm";"ColorFabb HT 1.75mm";"ColorFabb nGen 1.75mm";"ColorFabb Woodfil 1.75mm";"ColorFabb XT 1.75mm";"ColorFabb XT-CF20 1.75mm";"E3D PC-ABS 1.75mm";"Fillamentum ABS 1.75mm";"Fillamentum ASA 1.75mm";"Generic ABS 1.75mm";"Generic PET 1.75mm";"Generic PLA 1.75mm";"Prusa ABS 1.75mm";"Prusa HIPS 1.75mm";"Prusa PET 1.75mm";"Prusa PLA 1.75mm";"Taulman Bridge 1.75mm";"Taulman T-Glase 1.75mm"
diff --git a/xs/src/slic3r/GUI/PresetBundle.cpp b/xs/src/slic3r/GUI/PresetBundle.cpp
index 84fa3a92f..ef48eb6d4 100644
--- a/xs/src/slic3r/GUI/PresetBundle.cpp
+++ b/xs/src/slic3r/GUI/PresetBundle.cpp
@@ -104,6 +104,9 @@ void PresetBundle::reset(bool delete_files)
     this->printers .reset(delete_files);
     this->filament_presets.clear();
     this->filament_presets.emplace_back(this->filaments.get_selected_preset().name);
+    this->obsolete_presets.prints.clear();
+    this->obsolete_presets.filaments.clear();
+    this->obsolete_presets.printers.clear();
 }
 
 void PresetBundle::setup_directories()
@@ -224,7 +227,10 @@ std::vector<std::string> PresetBundle::merge_presets(PresetBundle &&other)
     std::vector<std::string> duplicate_prints    = this->prints   .merge_presets(std::move(other.prints),    this->vendors);
     std::vector<std::string> duplicate_filaments = this->filaments.merge_presets(std::move(other.filaments), this->vendors);
     std::vector<std::string> duplicate_printers  = this->printers .merge_presets(std::move(other.printers),  this->vendors);
-    append(duplicate_prints, std::move(duplicate_filaments));
+	append(this->obsolete_presets.prints,    std::move(other.obsolete_presets.prints));
+	append(this->obsolete_presets.filaments, std::move(other.obsolete_presets.filaments));
+	append(this->obsolete_presets.printers,  std::move(other.obsolete_presets.printers));
+	append(duplicate_prints, std::move(duplicate_filaments));
     append(duplicate_prints, std::move(duplicate_printers));
     return duplicate_prints;
 }
@@ -365,6 +371,7 @@ DynamicPrintConfig PresetBundle::full_config() const
     } else {
         // Retrieve filament presets and build a single config object for them.
         // First collect the filament configurations based on the user selection of this->filament_presets.
+        // Here this->filaments.find_preset() and this->filaments.first_visible() return the edited copy of the preset if active.
         std::vector<const DynamicPrintConfig*> filament_configs;
         for (const std::string &filament_preset_name : this->filament_presets)
             filament_configs.emplace_back(&this->filaments.find_preset(filament_preset_name, true)->config);
@@ -760,6 +767,7 @@ size_t PresetBundle::load_configbundle(const std::string &path, unsigned int fla
     flatten_configbundle_hierarchy(tree);
 
     // 2) Parse the property_tree, extract the active preset names and the profiles, save them into local config files.
+    // Parse the obsolete preset names, to be deleted when upgrading from the old configuration structure.
     std::vector<std::string> loaded_prints;
     std::vector<std::string> loaded_filaments;
     std::vector<std::string> loaded_printers;
@@ -799,6 +807,20 @@ size_t PresetBundle::load_configbundle(const std::string &path, unsigned int fla
                     active_printer = kvp.second.data();
                 }
             }
+        } else if (section.first == "obsolete_presets") {
+            // Parse the names of obsolete presets. These presets will be deleted from user's
+            // profile directory on installation of this vendor preset.
+            for (auto &kvp : section.second) {
+                std::vector<std::string> *dst = nullptr;
+                if (kvp.first == "print")
+                    dst = &this->obsolete_presets.prints;
+                else if (kvp.first == "filament")
+                    dst = &this->obsolete_presets.filaments;
+                else if (kvp.first == "printer")
+                    dst = &this->obsolete_presets.printers;
+                if (dst)
+                    unescape_strings_cstyle(kvp.second.data(), *dst);
+            }
         } else if (section.first == "settings") {
             // Load the settings.
             for (auto &kvp : section.second) {
diff --git a/xs/src/slic3r/GUI/PresetBundle.hpp b/xs/src/slic3r/GUI/PresetBundle.hpp
index 9f2afbead..a5c5682f9 100644
--- a/xs/src/slic3r/GUI/PresetBundle.hpp
+++ b/xs/src/slic3r/GUI/PresetBundle.hpp
@@ -54,6 +54,13 @@ public:
     // and the system profiles will point to the VendorProfile instances owned by PresetBundle::vendors.
     std::set<VendorProfile>     vendors;
 
+    struct ObsoletePresets {
+        std::vector<std::string> prints;
+        std::vector<std::string> filaments;
+        std::vector<std::string> printers;
+    };
+    ObsoletePresets             obsolete_presets;
+
     bool                        has_defauls_only() const 
         { return prints.size() <= 1 && filaments.size() <= 1 && printers.size() <= 1; }