public void firstLayerSpeedEqualsAcceptableValue(PrinterSettings settings, PrinterSettingsLayer layer, string sourceFile)
        {
            string firstLayerSpeedString;

            if (!layer.TryGetValue(SettingsKey.first_layer_speed, out firstLayerSpeedString))
            {
                return;
            }

            double firstLayerSpeed;

            if (firstLayerSpeedString.Contains("%"))
            {
                string infillSpeedString = settings.GetValue(SettingsKey.infill_speed);
                double infillSpeed       = double.Parse(infillSpeedString);

                firstLayerSpeedString = firstLayerSpeedString.Replace("%", "");

                double FirstLayerSpeedPercent = double.Parse(firstLayerSpeedString);

                firstLayerSpeed = FirstLayerSpeedPercent * infillSpeed / 100.0;
            }
            else
            {
                firstLayerSpeed = double.Parse(firstLayerSpeedString);
            }

            Assert.Greater(firstLayerSpeed, 5, "Unexpected firstLayerSpeedEqualsAcceptableValue value: " + sourceFile);
        }
        private void MergeSettings(string settingsFilePath)
        {
            if (!string.IsNullOrEmpty(settingsFilePath) && File.Exists(settingsFilePath))
            {
                string importType = Path.GetExtension(settingsFilePath).ToLower();
                switch (importType)
                {
                case ProfileManager.ProfileExtension:
                    WizardWindow.ChangeToPage(new SelectPartsOfPrinterToImport(settingsFilePath, ActiveSliceSettings.Instance.UserLayer));
                    break;

                case ".slice":                         // old presets format
                case ".ini":
                    // create a scope for variables
                {
                    var settingsToImport = PrinterSettingsLayer.LoadFromIni(settingsFilePath);

                    bool containsValidSetting = false;
                    var  activeSettings       = ActiveSliceSettings.Instance;

                    foreach (var keyName in PrinterSettings.KnownSettings)
                    {
                        if (activeSettings.Contains(keyName))
                        {
                            containsValidSetting = true;
                            string currentValue = activeSettings.GetValue(keyName).Trim();

                            string newValue;
                            // Compare the value to import to the layer cascade value and only set if different
                            if (settingsToImport.TryGetValue(keyName, out newValue) &&
                                currentValue != newValue)
                            {
                                activeSettings.UserLayer[keyName] = newValue;
                            }
                        }
                    }
                    if (containsValidSetting)
                    {
                        activeSettings.Save();

                        UiThread.RunOnIdle(ApplicationController.Instance.ReloadAdvancedControlsPanel);
                    }
                    else
                    {
                        displayFailedToImportMessage(settingsFilePath);
                    }
                    WizardWindow.Close();
                }
                break;

                default:
                    WizardWindow.Close();
                    // Did not figure out what this file is, let the user know we don't understand it
                    StyledMessageBox.ShowMessageBox(null, "Oops! Unable to recognize settings file '{0}'.".Localize().FormatWith(Path.GetFileName(settingsFilePath)), "Unable to Import".Localize());
                    break;
                }
            }
            Invalidate();
        }
Beispiel #3
0
        /// <summary>
        /// Calls the given delegate for each known printer, passing in a PrinterConfig object that has
        /// printer settings loaded into a SettingsLayer as well as state about the printer
        /// </summary>
        /// <param name="action">The action to invoke for each printer</param>
        private void ValidateOnAllPrinters(Action <PrinterConfig, PrinterSettings> action)
        {
            var ruleViolations = new List <string>();

            foreach (var printer in allPrinters)
            {
                printer.RuleViolated = false;

                PrinterSettingsLayer oemLayer = printer.PrinterSettings.OemLayer;

                action(printer, new PrinterSettings()
                {
                    OemLayer = oemLayer
                });

                if (printer.RuleViolated)
                {
                    ruleViolations.Add(printer.RelativeFilePath);
                }

                foreach (var layer in printer.PrinterSettings.MaterialLayers)
                {
                    printer.RuleViolated = false;

                    action(printer, new PrinterSettings()
                    {
                        BaseLayer = oemLayer, OemLayer = layer
                    });

                    if (printer.RuleViolated)
                    {
                        ruleViolations.Add(printer.RelativeFilePath + " -> " + layer.Name);
                    }
                }

                foreach (var layer in printer.PrinterSettings.QualityLayers)
                {
                    printer.RuleViolated = false;

                    action(printer, new PrinterSettings()
                    {
                        BaseLayer = oemLayer, OemLayer = layer
                    });

                    if (printer.RuleViolated)
                    {
                        ruleViolations.Add(printer.RelativeFilePath + " -> " + layer.Name);
                    }
                }
            }

            Assert.IsTrue(
                ruleViolations.Count == 0,                 /* Use == instead of Assert.AreEqual to better convey failure details */
                string.Format("One or more printers violate this rule: \r\n\r\n{0}\r\n", string.Join("\r\n", ruleViolations.ToArray())));
        }
        public void testFirstLayerBedTemperatureNotInStartGcode(PrinterSettingsLayer layer, string sourceFile)
        {
            string settingValue;

            if (!layer.TryGetValue(SettingsKey.start_gcode, out settingValue))
            {
                return;
            }

            Assert.False(settingValue.Contains(SettingsKey.first_layer_bed_temperature), "start_gcode should not contain first_layer_bed_temperature: " + sourceFile);
        }
        public void testBottomSolidLayersOneMM(PrinterSettingsLayer layer, string sourceFile)
        {
            string settingValue;

            if (!layer.TryGetValue(SettingsKey.bottom_solid_layers, out settingValue))
            {
                return;
            }

            Assert.AreEqual("1mm", settingValue, "bottom_solid_layers should be 1mm: " + sourceFile);
        }
        public void noCurlyBracketsInStartGcode(PrinterSettingsLayer layer, string sourceFile)
        {
            string settingValue;

            if (!layer.TryGetValue("start_gcode", out settingValue))
            {
                return;
            }

            Assert.IsFalse(settingValue.Contains("{"), "start_gcode should not contain braces: " + sourceFile);
        }
        public void testRetractLengthLessThanTwenty(PrinterSettingsLayer layer, string sourceFile)
        {
            string settingValue;

            if (!layer.TryGetValue(SettingsKey.retract_length, out settingValue))
            {
                return;
            }

            Assert.Less(float.Parse(settingValue, CultureInfo.InvariantCulture.NumberFormat), 20, "retract_length should be less than 20: " + sourceFile);
        }
        public void maxFanSpeedNotGreaterThanOneHundred(PrinterSettingsLayer layer, string sourceFile)
        {
            string settingValue;

            if (!layer.TryGetValue(SettingsKey.max_fan_speed, out settingValue))
            {
                return;
            }

            Assert.LessOrEqual(int.Parse(settingValue), 100, "max_fan_speed should be less than or equal to 100: " + sourceFile);
        }
        public void testExtruderCountGreaterThanZero(PrinterSettingsLayer layer, string sourceFile)
        {
            string settingValue;

            if (!layer.TryGetValue("extruder_count", out settingValue))
            {
                return;
            }

            Assert.Greater(int.Parse(settingValue), 0, "extruder_count should be greater than zero: " + sourceFile);
        }
        public void minimumFanSpeedLessThanOrEqualToOneHundred(PrinterSettingsLayer layer, string sourceFile)
        {
            string settingValue;

            if (!layer.TryGetValue("min_fan_speed", out settingValue))
            {
                return;
            }

            Assert.LessOrEqual(int.Parse(settingValue), 100, "min_fan_speed should be less than or equal to 100: " + sourceFile);
        }
        public void noCurlyBracketsInEndGcode(PrinterSettingsLayer layer, string sourceFile)
        {
            string settingValue;

            if (!layer.TryGetValue(SettingsKey.end_gcode, out settingValue))
            {
                return;
            }

            Assert.False(settingValue.Contains("{"), "end_gcode should not contain braces: " + sourceFile);
        }
        private void MergeSettings(string settingsFilePath)
        {
            if (!string.IsNullOrEmpty(settingsFilePath) && File.Exists(settingsFilePath))
            {
                string importType = Path.GetExtension(settingsFilePath).ToLower();
                switch (importType)
                {
                case ".printer":
                    WizardWindow.ChangeToPage(new SelectPartsOfPrinterToImport(settingsFilePath, ActiveSliceSettings.Instance.UserLayer));
                    break;

                case ".slice":                         // old presets format
                case ".ini":
                    var    settingsToImport = PrinterSettingsLayer.LoadFromIni(settingsFilePath);
                    string layerHeight;

                    bool isSlic3r = settingsToImport.TryGetValue(SettingsKey.layer_height, out layerHeight);
                    if (isSlic3r)
                    {
                        var activeSettings = ActiveSliceSettings.Instance;

                        foreach (var item in settingsToImport)
                        {
                            // Compare the value to import to the layer cascade value and only set if different
                            string currentValue = activeSettings.GetValue(item.Key, null).Trim();
                            if (currentValue != item.Value)
                            {
                                activeSettings.UserLayer[item.Key] = item.Value;
                            }
                        }

                        activeSettings.SaveChanges();

                        UiThread.RunOnIdle(ApplicationController.Instance.ReloadAdvancedControlsPanel);
                    }
                    else
                    {
                        // looks like a cura file
                        throw new NotImplementedException("need to import from 'cure.ini' files");
                    }
                    WizardWindow.Close();
                    break;

                default:
                    WizardWindow.Close();
                    // Did not figure out what this file is, let the user know we don't understand it
                    StyledMessageBox.ShowMessageBox(null, "Oops! Unable to recognize settings file '{0}'.".Localize().FormatWith(Path.GetFileName(settingsFilePath)), "Unable to Import".Localize());
                    break;
                }
            }
            Invalidate();
        }
        public void printCenterFormatSeparatedByComma(PrinterSettingsLayer layer, string sourceFile)
        {
            string settingValue;

            if (!layer.TryGetValue(SettingsKey.print_center, out settingValue))
            {
                return;
            }

            string[] settingValueToTest = settingValue.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

            Assert.AreEqual(2, settingValueToTest.Length, "print_center should have two values separated by a comma: " + sourceFile);
        }
 private static List <LayerInfo> LoadLayers(string layersDirectory, OemProfile oemProfile)
 {
     // The slice presets layer cascade contains the preset layer, with config.ini data as a parent
     return(Directory.Exists(layersDirectory) ?
            Directory.GetFiles(layersDirectory, "*.slice").Select(file => new LayerInfo()
     {
         RelativeFilePath = file.Substring(printerSettingsDirectory.Length + 1),
         PrinterSettings = new PrinterSettings()
         {
             OemLayer = PrinterSettingsLayer.LoadFromIni(file), BaseLayer = oemProfile.OemLayer
         }
     }).ToList()
                                 : new List <LayerInfo>());
 }
Beispiel #15
0
        public static bool CompareExpectedSliceSettingValueWithActualVaue(string sliceSetting, string expectedValue)
        {
            foreach (string iniPath in Directory.GetFiles(ApplicationDataStorage.Instance.GCodeOutputPath, "*.ini"))
            {
                var settings = PrinterSettingsLayer.LoadFromIni(iniPath);

                if (settings.TryGetValue(sliceSetting, out string currentValue))
                {
                    return(currentValue.Trim() == expectedValue);
                }
            }

            return(false);
        }
        public static bool CompareExpectedSliceSettingValueWithActualVaue(string sliceSetting, string expectedValue)
        {
            string fullPath = TestContext.CurrentContext.ResolveProjectPath(4, "Tests", "temp", runName, "Test0", "data", "gcode");

            foreach (string iniPath in Directory.GetFiles(fullPath, "*.ini"))
            {
                var settings = PrinterSettingsLayer.LoadFromIni(iniPath);

                string currentValue;

                if (settings.TryGetValue(sliceSetting, out currentValue))
                {
                    return(currentValue.Trim() == expectedValue);
                }
            }

            return(false);
        }
        public void firstLayerExtrusionWidthNotZero(PrinterSettingsLayer layer, string sourceFile)
        {
            string firstLayerExtrusionWidth;

            if (!layer.TryGetValue(SettingsKey.first_layer_extrusion_width, out firstLayerExtrusionWidth))
            {
                return;
            }

            float convertedFirstLayerExtrusionWidth;

            if (firstLayerExtrusionWidth.Contains("%"))
            {
                string reformatFirstLayerExtrusionWidth = firstLayerExtrusionWidth.Replace("%", " ");
                convertedFirstLayerExtrusionWidth = float.Parse(reformatFirstLayerExtrusionWidth);
            }
            else
            {
                convertedFirstLayerExtrusionWidth = float.Parse(firstLayerExtrusionWidth);
            }

            Assert.AreNotEqual(0, convertedFirstLayerExtrusionWidth, "Unexpected firstLayerExtrusionWidthNotZero value: " + sourceFile);
        }
        static ConfigIniTests()
        {
            allPrinters = (from configIni in new DirectoryInfo(printerSettingsDirectory).GetFiles("config.ini", System.IO.SearchOption.AllDirectories)
                           let oemProfile = new OemProfile(PrinterSettingsLayer.LoadFromIni(configIni.FullName))
                                            select new PrinterConfig
            {
                PrinterName = configIni.Directory.Name,
                Oem = configIni.Directory.Parent.Name,
                ConfigPath = configIni.FullName,
                ConfigIni = new LayerInfo()
                {
                    RelativeFilePath = configIni.FullName.Substring(printerSettingsDirectory.Length + 1),

                    // The config.ini layered profile only contains itself and does not fall back to or cascade to anything
                    PrinterSettings = new PrinterSettings()
                    {
                        OemLayer = oemProfile.OemLayer
                    },
                },
                MatterialLayers = LoadLayers(Path.Combine(configIni.Directory.FullName, "material"), oemProfile),
                QualityLayers = LoadLayers(Path.Combine(configIni.Directory.FullName, "quality"), oemProfile)
            }).ToList();
        }
        private void ImportToPreset(string settingsFilePath)
        {
            if (!string.IsNullOrEmpty(settingsFilePath) && File.Exists(settingsFilePath))
            {
                PrinterSettingsLayer newLayer;

                string sectionName = (newMaterialPresetButton.Checked) ? "Material".Localize() : "Quality".Localize();

                string importType = Path.GetExtension(settingsFilePath).ToLower();
                switch (importType)
                {
                case ".printer":
                    newLayer = new PrinterSettingsLayer();
                    newLayer["layer_name"] = Path.GetFileNameWithoutExtension(settingsFilePath);

                    if (newQualityPresetButton.Checked)
                    {
                        ActiveSliceSettings.Instance.QualityLayers.Add(newLayer);
                    }
                    else
                    {
                        // newMaterialPresetButton.Checked
                        ActiveSliceSettings.Instance.MaterialLayers.Add(newLayer);
                    }

                    // open a wizard to ask what to import to the preset
                    WizardWindow.ChangeToPage(new SelectPartsOfPrinterToImport(settingsFilePath, newLayer, sectionName));

                    break;

                case ".slice":                         // legacy presets file extension
                case ".ini":
                    var    settingsToImport = PrinterSettingsLayer.LoadFromIni(settingsFilePath);
                    string layerHeight;

                    bool isSlic3r = importType == ".slice" || settingsToImport.TryGetValue(SettingsKey.layer_height, out layerHeight);
                    if (isSlic3r)
                    {
                        newLayer      = new PrinterSettingsLayer();
                        newLayer.Name = Path.GetFileNameWithoutExtension(settingsFilePath);

                        // Only be the base and oem layers (not the user, quality or material layer)
                        var baseAndOEMCascade = new List <PrinterSettingsLayer>
                        {
                            ActiveSliceSettings.Instance.OemLayer,
                            ActiveSliceSettings.Instance.BaseLayer
                        };

                        foreach (var item in settingsToImport)
                        {
                            string currentValue = ActiveSliceSettings.Instance.GetValue(item.Key, baseAndOEMCascade).Trim();
                            // Compare the value to import to the layer cascade value and only set if different
                            if (currentValue != item.Value)
                            {
                                newLayer[item.Key] = item.Value;
                            }
                        }

                        if (newMaterialPresetButton.Checked)
                        {
                            ActiveSliceSettings.Instance.MaterialLayers.Add(newLayer);
                        }
                        else
                        {
                            ActiveSliceSettings.Instance.QualityLayers.Add(newLayer);
                        }

                        ActiveSliceSettings.Instance.SaveChanges();

                        WizardWindow.ChangeToPage(new ImportSucceeded(importSettingSuccessMessage.FormatWith(Path.GetFileNameWithoutExtension(settingsFilePath), sectionName))
                        {
                            WizardWindow = this.WizardWindow,
                        });
                    }
                    else
                    {
                        // looks like a cura file
#if DEBUG
                        throw new NotImplementedException("need to import from 'cure.ini' files");
#endif
                    }
                    break;

                default:
                    // Did not figure out what this file is, let the user know we don't understand it
                    StyledMessageBox.ShowMessageBox(null, "Oops! Unable to recognize settings file '{0}'.".Localize().FormatWith(Path.GetFileName(settingsFilePath)), "Unable to Import".Localize());
                    break;
                }
            }
            Invalidate();
        }
        public ImportSettingsPage(string settingsFilePath, PrinterConfig printer)
        {
            this.WindowTitle = "Import Wizard";
            this.HeaderText  = "Select What to Import".Localize();

            // TODO: Need to handle load failures for import attempts
            var settingsToImport = PrinterSettings.LoadFile(settingsFilePath);

            // if there are no settings to import
            if (settingsToImport.QualityLayers.Count == 0 && settingsToImport.MaterialLayers.Count == 0)
            {
                // Only main setting so don't ask what to merge just do it.
                UiThread.RunOnIdle(() =>
                {
                    DisplayFailedToImportMessage(settingsFilePath);
                    this.Parents <SystemWindow>().First().Close();
                });
            }

            this.settingsFilePath = settingsFilePath;

            var scrollWindow = new ScrollableWidget()
            {
                AutoScroll = true,
                HAnchor    = HAnchor.Stretch,
                VAnchor    = VAnchor.Stretch,
            };

            scrollWindow.ScrollArea.HAnchor = HAnchor.Stretch;
            contentRow.AddChild(scrollWindow);

            var container = new FlowLayoutWidget(FlowDirection.TopToBottom)
            {
                HAnchor = HAnchor.Stretch,
            };

            scrollWindow.AddChild(container);

            if (settingsToImport.QualityLayers.Count > 0)
            {
                container.AddChild(new TextWidget("Quality Presets:")
                {
                    TextColor = theme.TextColor,
                    Margin    = new BorderDouble(0, 3),
                });

                int buttonIndex = 0;
                foreach (var qualitySetting in settingsToImport.QualityLayers)
                {
                    var qualityButton = new RadioButton(string.IsNullOrEmpty(qualitySetting.Name) ? "no name" : qualitySetting.Name)
                    {
                        TextColor = theme.TextColor,
                        Margin    = new BorderDouble(5, 0, 0, 0),
                        HAnchor   = HAnchor.Left,
                    };
                    container.AddChild(qualityButton);

                    int localButtonIndex = buttonIndex;
                    qualityButton.CheckedStateChanged += (s, e) =>
                    {
                        if (qualityButton.Checked)
                        {
                            selectedQuality = localButtonIndex;
                        }
                        else
                        {
                            selectedQuality = -1;
                        }
                    };

                    buttonIndex++;
                }
            }

            if (settingsToImport.MaterialLayers.Count > 0)
            {
                container.AddChild(new TextWidget("Material Presets:")
                {
                    TextColor = theme.TextColor,
                    Margin    = new BorderDouble(0, 3, 0, 15),
                });

                int buttonIndex = 0;
                foreach (var materialSetting in settingsToImport.MaterialLayers)
                {
                    var materialButton = new RadioButton(string.IsNullOrEmpty(materialSetting.Name) ? "no name" : materialSetting.Name)
                    {
                        TextColor = theme.TextColor,
                        Margin    = new BorderDouble(5, 0),
                        HAnchor   = HAnchor.Left,
                    };

                    container.AddChild(materialButton);

                    int localButtonIndex = buttonIndex;
                    materialButton.CheckedStateChanged += (s, e) =>
                    {
                        if (materialButton.Checked)
                        {
                            selectedMaterial = localButtonIndex;
                        }
                        else
                        {
                            selectedMaterial = -1;
                        }
                    };

                    buttonIndex++;
                }
            }

            var mergeButton = theme.CreateDialogButton("Import".Localize());

            mergeButton.Name   = "Merge Profile";
            mergeButton.Click += (s, e) => UiThread.RunOnIdle(() =>
            {
                bool copyName = false;
                PrinterSettingsLayer sourceLayer = null;
                bool destIsMaterial = true;
                if (selectedMaterial > -1)
                {
                    sourceLayer = settingsToImport.MaterialLayers[selectedMaterial];
                    copyName    = true;
                }
                else if (selectedQuality > -1)
                {
                    destIsMaterial = false;
                    sourceLayer    = settingsToImport.QualityLayers[selectedQuality];
                    copyName       = true;
                }

                List <PrinterSettingsLayer> sourceFilter;

                if (selectedQuality == -1 && selectedMaterial == -1)
                {
                    sourceFilter = new List <PrinterSettingsLayer>()
                    {
                        settingsToImport.OemLayer,
                        settingsToImport.UserLayer
                    };
                }
                else
                {
                    sourceFilter = new List <PrinterSettingsLayer>()
                    {
                        sourceLayer
                    };
                }

                if (File.Exists(settingsFilePath))
                {
                    if (Path.GetExtension(settingsFilePath).ToLower() == ProfileManager.ProfileExtension)
                    {
                        var printerSettingsLayer = new PrinterSettingsLayer();
                        printer.Settings.Merge(printerSettingsLayer, settingsToImport, sourceFilter, copyName);

                        var layerName = (printerSettingsLayer.ContainsKey(SettingsKey.layer_name)) ? printerSettingsLayer[SettingsKey.layer_name] : "none";

                        string sectionName = destIsMaterial ? "Material".Localize() : "Quality".Localize();

                        string importSettingSuccessMessage = string.Format("You have successfully imported a new {0} setting. You can find '{1}' in your list of {0} settings.".Localize(), sectionName, layerName);

                        DialogWindow.ChangeToPage(
                            new ImportSucceeded(importSettingSuccessMessage)
                        {
                            DialogWindow = this.DialogWindow,
                        });

                        if (destIsMaterial)
                        {
                            printer.Settings.MaterialLayers.Add(printerSettingsLayer);
                        }
                        else
                        {
                            printer.Settings.QualityLayers.Add(printerSettingsLayer);
                        }
                    }
                    else
                    {
                        // Inform of unexpected extension type
                        StyledMessageBox.ShowMessageBox(
                            "Oops! Unable to recognize settings file '{0}'.".Localize().FormatWith(Path.GetFileName(settingsFilePath)),
                            "Unable to Import".Localize());
                    }
                }
            });

            this.AddPageAction(mergeButton);
        }
        public SelectPartsOfPrinterToImport(string settingsFilePath, PrinterSettingsLayer destinationLayer, string sectionName = null) :
            base(unlocalizedTextForTitle: "Import Wizard")
        {
            this.isMergeIntoUserLayer = destinationLayer == ActiveSliceSettings.Instance.UserLayer;
            this.destinationLayer     = destinationLayer;
            this.sectionName          = sectionName;

            // TODO: Need to handle load failures for import attempts
            settingsToImport = PrinterSettings.LoadFile(settingsFilePath);

            this.headerLabel.Text = "Select What to Import".Localize();

            this.settingsFilePath = settingsFilePath;

            var scrollWindow = new ScrollableWidget()
            {
                AutoScroll = true,
                HAnchor    = HAnchor.ParentLeftRight,
                VAnchor    = VAnchor.ParentBottomTop,
            };

            scrollWindow.ScrollArea.HAnchor = HAnchor.ParentLeftRight;
            contentRow.AddChild(scrollWindow);

            var container = new FlowLayoutWidget(FlowDirection.TopToBottom)
            {
                HAnchor = HAnchor.ParentLeftRight,
            };

            scrollWindow.AddChild(container);

            if (isMergeIntoUserLayer)
            {
                container.AddChild(new WrappedTextWidget(importMessage, textColor: ActiveTheme.Instance.PrimaryTextColor));
            }

            // add in the check boxes to select what to import
            container.AddChild(new TextWidget("Main Settings:")
            {
                TextColor = ActiveTheme.Instance.PrimaryTextColor,
                Margin    = new BorderDouble(0, 3, 0, isMergeIntoUserLayer ? 10 : 0),
            });

            var mainProfileRadioButton = new RadioButton("Printer Profile")
            {
                TextColor = ActiveTheme.Instance.PrimaryTextColor,
                Margin    = new BorderDouble(5, 0),
                HAnchor   = HAnchor.ParentLeft,
                Checked   = true,
            };

            container.AddChild(mainProfileRadioButton);

            if (settingsToImport.QualityLayers.Count > 0)
            {
                container.AddChild(new TextWidget("Quality Presets:")
                {
                    TextColor = ActiveTheme.Instance.PrimaryTextColor,
                    Margin    = new BorderDouble(0, 3, 0, 15),
                });

                int buttonIndex = 0;
                foreach (var qualitySetting in settingsToImport.QualityLayers)
                {
                    RadioButton qualityButton = new RadioButton(qualitySetting.Name)
                    {
                        TextColor = ActiveTheme.Instance.PrimaryTextColor,
                        Margin    = new BorderDouble(5, 0, 0, 0),
                        HAnchor   = HAnchor.ParentLeft,
                    };
                    container.AddChild(qualityButton);

                    int localButtonIndex = buttonIndex;
                    qualityButton.CheckedStateChanged += (s, e) =>
                    {
                        if (qualityButton.Checked)
                        {
                            selectedQuality = localButtonIndex;
                        }
                        else
                        {
                            selectedQuality = -1;
                        }
                    };

                    buttonIndex++;
                }
            }

            if (settingsToImport.MaterialLayers.Count > 0)
            {
                container.AddChild(new TextWidget("Material Presets:")
                {
                    TextColor = ActiveTheme.Instance.PrimaryTextColor,
                    Margin    = new BorderDouble(0, 3, 0, 15),
                });

                int buttonIndex = 0;
                foreach (var materialSetting in settingsToImport.MaterialLayers)
                {
                    RadioButton materialButton = new RadioButton(materialSetting.Name)
                    {
                        TextColor = ActiveTheme.Instance.PrimaryTextColor,
                        Margin    = new BorderDouble(5, 0),
                        HAnchor   = HAnchor.ParentLeft,
                    };

                    container.AddChild(materialButton);

                    int localButtonIndex = buttonIndex;
                    materialButton.CheckedStateChanged += (s, e) =>
                    {
                        if (materialButton.Checked)
                        {
                            selectedMaterial = localButtonIndex;
                        }
                        else
                        {
                            selectedMaterial = -1;
                        }
                    };

                    buttonIndex++;
                }
            }

            var mergeButtonTitle = this.isMergeIntoUserLayer ? "Merge".Localize() : "Import".Localize();
            var mergeButton      = textImageButtonFactory.Generate(mergeButtonTitle);

            mergeButton.Name   = "Merge Profile";
            mergeButton.Click += (s, e) => UiThread.RunOnIdle(Merge);
            footerRow.AddChild(mergeButton);

            footerRow.AddChild(new HorizontalSpacer());
            footerRow.AddChild(cancelButton);

            if (settingsToImport.QualityLayers.Count == 0 && settingsToImport.MaterialLayers.Count == 0)
            {
                // Only main setting so don't ask what to merge just do it.
                UiThread.RunOnIdle(Merge);
            }
        }
        void Merge()
        {
            var activeSettings = ActiveSliceSettings.Instance;

            var layerCascade = new List <PrinterSettingsLayer>
            {
                ActiveSliceSettings.Instance.OemLayer,
                ActiveSliceSettings.Instance.BaseLayer,
                destinationLayer,
            };

            PrinterSettingsLayer layerToImport = settingsToImport.BaseLayer;

            if (selectedMaterial > -1)
            {
                var material = settingsToImport.MaterialLayers[selectedMaterial];

                foreach (var item in material)
                {
                    if (!skipKeys.Contains(item.Key))
                    {
                        destinationLayer[item.Key] = item.Value;
                    }
                }

                if (!isMergeIntoUserLayer && material.ContainsKey(SettingsKey.layer_name))
                {
                    destinationLayer[SettingsKey.layer_name] = material[SettingsKey.layer_name];
                }
            }
            else if (selectedQuality > -1)
            {
                var quality = settingsToImport.QualityLayers[selectedQuality];

                foreach (var item in quality)
                {
                    if (!skipKeys.Contains(item.Key))
                    {
                        destinationLayer[item.Key] = item.Value;
                    }
                }

                if (!isMergeIntoUserLayer && quality.ContainsKey(SettingsKey.layer_name))
                {
                    destinationLayer[SettingsKey.layer_name] = quality[SettingsKey.layer_name];
                }
            }
            else
            {
                foreach (var item in layerToImport)
                {
                    // Compare the value to import to the layer cascade value and only set if different
                    string currentValue = activeSettings.GetValue(item.Key, layerCascade).Trim();
                    string importValue  = settingsToImport.GetValue(item.Key, layerCascade).Trim();
                    if (currentValue != item.Value)
                    {
                        destinationLayer[item.Key] = item.Value;
                    }
                }
            }

            activeSettings.Save();

            UiThread.RunOnIdle(ApplicationController.Instance.ReloadAdvancedControlsPanel);

            string successMessage = importPrinterSuccessMessage.FormatWith(Path.GetFileNameWithoutExtension(settingsFilePath));

            if (!isMergeIntoUserLayer)
            {
                string sourceName = isMergeIntoUserLayer ? Path.GetFileNameWithoutExtension(settingsFilePath) : destinationLayer[SettingsKey.layer_name];
                successMessage = ImportSettingsPage.importSettingSuccessMessage.FormatWith(sourceName, sectionName);
            }

            WizardWindow.ChangeToPage(new ImportSucceeded(successMessage)
            {
                WizardWindow = this.WizardWindow,
            });
        }
        private void ImportToPreset(string settingsFilePath)
        {
            if (!string.IsNullOrEmpty(settingsFilePath) && File.Exists(settingsFilePath))
            {
                PrinterSettingsLayer newLayer;

                string sectionName = (newMaterialPresetButton.Checked) ? "Material".Localize() : "Quality".Localize();

                string importType = Path.GetExtension(settingsFilePath).ToLower();
                switch (importType)
                {
                case ProfileManager.ProfileExtension:
                    newLayer = new PrinterSettingsLayer();
                    newLayer[SettingsKey.layer_name] = Path.GetFileNameWithoutExtension(settingsFilePath);

                    if (newQualityPresetButton.Checked)
                    {
                        ActiveSliceSettings.Instance.QualityLayers.Add(newLayer);
                    }
                    else
                    {
                        // newMaterialPresetButton.Checked
                        ActiveSliceSettings.Instance.MaterialLayers.Add(newLayer);
                    }

                    // open a wizard to ask what to import to the preset
                    WizardWindow.ChangeToPage(new SelectPartsOfPrinterToImport(settingsFilePath, newLayer, sectionName));

                    break;

                case ".slice":                         // legacy presets file extension
                case ".ini":
                    var settingsToImport = PrinterSettingsLayer.LoadFromIni(settingsFilePath);

                    bool containsValidSetting = false;
                    {
                        newLayer      = new PrinterSettingsLayer();
                        newLayer.Name = Path.GetFileNameWithoutExtension(settingsFilePath);

                        // Only be the base and oem layers (not the user, quality or material layer)
                        var baseAndOEMCascade = new List <PrinterSettingsLayer>
                        {
                            ActiveSliceSettings.Instance.OemLayer,
                            ActiveSliceSettings.Instance.BaseLayer
                        };

                        foreach (var keyName in PrinterSettings.KnownSettings)
                        {
                            if (ActiveSliceSettings.Instance.Contains(keyName))
                            {
                                containsValidSetting = true;
                                string currentValue = ActiveSliceSettings.Instance.GetValue(keyName, baseAndOEMCascade).Trim();
                                string newValue;
                                // Compare the value to import to the layer cascade value and only set if different
                                if (settingsToImport.TryGetValue(keyName, out newValue) &&
                                    currentValue != newValue)
                                {
                                    newLayer[keyName] = newValue;
                                }
                            }
                        }

                        if (containsValidSetting)
                        {
                            if (newMaterialPresetButton.Checked)
                            {
                                ActiveSliceSettings.Instance.MaterialLayers.Add(newLayer);
                            }
                            else
                            {
                                ActiveSliceSettings.Instance.QualityLayers.Add(newLayer);
                            }

                            ActiveSliceSettings.Instance.Save();

                            WizardWindow.ChangeToPage(new ImportSucceeded(importSettingSuccessMessage.FormatWith(Path.GetFileNameWithoutExtension(settingsFilePath), sectionName))
                            {
                                WizardWindow = this.WizardWindow,
                            });
                        }
                        else
                        {
                            displayFailedToImportMessage(settingsFilePath);
                        }
                    }

                    break;

                default:
                    // Did not figure out what this file is, let the user know we don't understand it
                    StyledMessageBox.ShowMessageBox(null, "Oops! Unable to recognize settings file '{0}'.".Localize().FormatWith(Path.GetFileName(settingsFilePath)), "Unable to Import".Localize());
                    break;
                }
            }
            Invalidate();
        }
        public SelectPartsOfPrinterToImport(string settingsFilePath, PrinterSettingsLayer destinationLayer, string sectionName = null) :
            base(unlocalizedTextForTitle: "Import Wizard")
        {
            this.isMergeIntoUserLayer = destinationLayer == ActiveSliceSettings.Instance.UserLayer;
            this.destinationLayer     = destinationLayer;
            this.sectionName          = sectionName;

            // TODO: Need to handle load failures for import attempts
            settingsToImport = PrinterSettings.LoadFile(settingsFilePath);

            this.headerLabel.Text = "Select What to Import".Localize();

            this.settingsFilePath = settingsFilePath;

            var scrollWindow = new ScrollableWidget()
            {
                AutoScroll = true,
                HAnchor    = HAnchor.ParentLeftRight,
                VAnchor    = VAnchor.ParentBottomTop,
            };

            scrollWindow.ScrollArea.HAnchor = HAnchor.ParentLeftRight;
            contentRow.AddChild(scrollWindow);

            var container = new FlowLayoutWidget(FlowDirection.TopToBottom)
            {
                HAnchor = HAnchor.ParentLeftRight,
            };

            scrollWindow.AddChild(container);

            if (isMergeIntoUserLayer)
            {
                container.AddChild(new WrappedTextWidget(importMessage, textColor: ActiveTheme.Instance.PrimaryTextColor));
            }

            // add in the check boxes to select what to import
            container.AddChild(new TextWidget("Main Settings:")
            {
                TextColor = ActiveTheme.Instance.PrimaryTextColor,
                Margin    = new BorderDouble(0, 3, 0, isMergeIntoUserLayer ? 10 : 0),
            });

            var mainProfileRadioButton = new RadioButton("Printer Profile")
            {
                TextColor = ActiveTheme.Instance.PrimaryTextColor,
                Margin    = new BorderDouble(5, 0),
                HAnchor   = HAnchor.ParentLeft,
                Checked   = true,
            };

            container.AddChild(mainProfileRadioButton);

            if (settingsToImport.QualityLayers.Count > 0)
            {
                container.AddChild(new TextWidget("Quality Presets:")
                {
                    TextColor = ActiveTheme.Instance.PrimaryTextColor,
                    Margin    = new BorderDouble(0, 3, 0, 15),
                });

                int buttonIndex = 0;
                foreach (var qualitySetting in settingsToImport.QualityLayers)
                {
                    RadioButton qualityButton = new RadioButton(qualitySetting.Name)
                    {
                        TextColor = ActiveTheme.Instance.PrimaryTextColor,
                        Margin    = new BorderDouble(5, 0, 0, 0),
                        HAnchor   = HAnchor.ParentLeft,
                    };
                    container.AddChild(qualityButton);

                    int localButtonIndex = buttonIndex;
                    qualityButton.CheckedStateChanged += (s, e) =>
                    {
                        if (qualityButton.Checked)
                        {
                            selectedQuality = localButtonIndex;
                        }
                        else
                        {
                            selectedQuality = -1;
                        }
                    };

                    buttonIndex++;
                }
            }

            if (settingsToImport.MaterialLayers.Count > 0)
            {
                container.AddChild(new TextWidget("Material Presets:")
                {
                    TextColor = ActiveTheme.Instance.PrimaryTextColor,
                    Margin    = new BorderDouble(0, 3, 0, 15),
                });

                int buttonIndex = 0;
                foreach (var materialSetting in settingsToImport.MaterialLayers)
                {
                    RadioButton materialButton = new RadioButton(materialSetting.Name)
                    {
                        TextColor = ActiveTheme.Instance.PrimaryTextColor,
                        Margin    = new BorderDouble(5, 0),
                        HAnchor   = HAnchor.ParentLeft,
                    };

                    container.AddChild(materialButton);

                    int localButtonIndex = buttonIndex;
                    materialButton.CheckedStateChanged += (s, e) =>
                    {
                        if (materialButton.Checked)
                        {
                            selectedMaterial = localButtonIndex;
                        }
                        else
                        {
                            selectedMaterial = -1;
                        }
                    };

                    buttonIndex++;
                }
            }

            var mergeButtonTitle = this.isMergeIntoUserLayer ? "Merge".Localize() : "Import".Localize();
            var mergeButton      = textImageButtonFactory.Generate(mergeButtonTitle);

            mergeButton.Name   = "Merge Profile";
            mergeButton.Click += (s, e) => UiThread.RunOnIdle(() =>
            {
                bool copyName = false;
                PrinterSettingsLayer sourceLayer = null;
                if (selectedMaterial > -1)
                {
                    sourceLayer = settingsToImport.MaterialLayers[selectedMaterial];
                    copyName    = true;
                }
                else if (selectedQuality > -1)
                {
                    sourceLayer = settingsToImport.QualityLayers[selectedQuality];
                    copyName    = true;
                }

                List <PrinterSettingsLayer> sourceFilter;

                if (selectedQuality == -1 && selectedMaterial == -1)
                {
                    sourceFilter = new List <PrinterSettingsLayer>()
                    {
                        settingsToImport.OemLayer,
                        settingsToImport.UserLayer
                    };
                }
                else
                {
                    sourceFilter = new List <PrinterSettingsLayer>()
                    {
                        sourceLayer
                    };
                }

                ActiveSliceSettings.Instance.Merge(destinationLayer, settingsToImport, sourceFilter, copyName);

                this.Parents <SystemWindow>().FirstOrDefault()?.CloseOnIdle();
            });

            footerRow.AddChild(mergeButton);

            footerRow.AddChild(new HorizontalSpacer());
            footerRow.AddChild(cancelButton);

            if (settingsToImport.QualityLayers.Count == 0 && settingsToImport.MaterialLayers.Count == 0)
            {
                // Only main setting so don't ask what to merge just do it.
                UiThread.RunOnIdle(() =>
                {
                    var sourceFilter = new List <PrinterSettingsLayer>()
                    {
                        settingsToImport.OemLayer ?? new PrinterSettingsLayer(),
                        settingsToImport.UserLayer ?? new PrinterSettingsLayer()
                    };

                    ActiveSliceSettings.Instance.Merge(destinationLayer, settingsToImport, sourceFilter, false);
                    UiThread.RunOnIdle(ApplicationController.Instance.ReloadAdvancedControlsPanel);

                    string successMessage = importPrinterSuccessMessage.FormatWith(Path.GetFileNameWithoutExtension(settingsFilePath));
                    if (!isMergeIntoUserLayer)
                    {
                        string sourceName = isMergeIntoUserLayer ? Path.GetFileNameWithoutExtension(settingsFilePath) : destinationLayer[SettingsKey.layer_name];
                        string importSettingSuccessMessage = "You have successfully imported a new {1} setting. You can find '{0}' in your list of {1} settings.".Localize();
                        successMessage = importSettingSuccessMessage.FormatWith(sourceName, sectionName);
                    }

                    WizardWindow.ChangeToPage(new ImportSucceeded(successMessage)
                    {
                        WizardWindow = this.WizardWindow,
                    });
                });
            }
        }
        public void firstLayerHeightLessThanNozzleDiameter(PrinterSettings printerSettings, PrinterSettingsLayer layer, string sourceFile)
        {
            string firstLayerHeight;

            if (!layer.TryGetValue(SettingsKey.first_layer_height, out firstLayerHeight))
            {
                return;
            }

            float convertedFirstLayerHeightValue;

            if (firstLayerHeight.Contains("%"))
            {
                string reFormatLayerHeight = firstLayerHeight.Replace("%", " ");
                convertedFirstLayerHeightValue = float.Parse(reFormatLayerHeight) / 100;
            }
            else
            {
                convertedFirstLayerHeightValue = float.Parse(firstLayerHeight);
            }

            string nozzleDiameter = printerSettings.GetValue(SettingsKey.nozzle_diameter);

            Assert.LessOrEqual(convertedFirstLayerHeightValue, float.Parse(nozzleDiameter), "Unexpected firstLayerHeightLessThanNozzleDiameter value: " + sourceFile);
        }
        public void firstLayerExtrusionWidthAcceptableValue(PrinterSettings printerSettings, PrinterSettingsLayer layer, string sourceFile)
        {
            string firstLayerExtrusionWidth;

            if (!layer.TryGetValue(SettingsKey.first_layer_extrusion_width, out firstLayerExtrusionWidth))
            {
                return;
            }

            float convertedFirstLayerExtrusionWidth;

            string nozzleDiameter  = printerSettings.GetValue(SettingsKey.nozzle_diameter);
            float  acceptableValue = float.Parse(nozzleDiameter) * 4;

            if (firstLayerExtrusionWidth.Contains("%"))
            {
                string reformatFirstLayerExtrusionWidth = firstLayerExtrusionWidth.Replace("%", " ");
                convertedFirstLayerExtrusionWidth = float.Parse(reformatFirstLayerExtrusionWidth) / 100;
            }
            else
            {
                convertedFirstLayerExtrusionWidth = float.Parse(firstLayerExtrusionWidth);
            }

            Assert.LessOrEqual(convertedFirstLayerExtrusionWidth, acceptableValue, "Unexpected firstLayerExtrusionWidthAcceptableValue value: " + sourceFile);
        }
        public void layerHeightLessThanNozzleDiameter(PrinterSettings printerSettings, PrinterSettingsLayer layer, string sourceFile)
        {
            string layerHeight;

            if (!layer.TryGetValue(SettingsKey.layer_height, out layerHeight))
            {
                return;
            }

            float convertedLayerHeight = float.Parse(layerHeight);

            string nozzleDiameter = printerSettings.GetValue(SettingsKey.nozzle_diameter);
            float  convertedNozzleDiameterValue = float.Parse(nozzleDiameter);

            Assert.LessOrEqual(convertedLayerHeight, convertedNozzleDiameterValue, "Unexpected layerHeightLessThanNozzleDiameter value: " + sourceFile);
        }