DiffPresetDialog, non modal to compare two presets.

Added menu item "Window->Compare presets" to compare more than one type
of presets.
Code refactoring for PresetComboBox: Use suffix "modified" just for
PlaterPresetComboBox and TabPresetComboBox
Code refactoring. wxDataViewCtrl and related functions extracted from
DiffPresetDialog and UnsavedChangesDialog to the separate class
DiffViewCtrl
Code refactoring, Tab.cpp: Build all unregular pages on a first build of
the Printer Settings

Squashed commit of the following:

commit 91f45a8a2d97d252337c7306dd02db607fd79c00
Author: Vojtech Bubnik <bubnikv@gmail.com>
Date:   Thu Feb 4 09:34:29 2021 +0100

    Fixed after merge

commit 09aa502498b08c059ecdf334f5db1567739b4520
Merge: 6df8e83e1 0baa92fab
Author: Vojtech Bubnik <bubnikv@gmail.com>
Date:   Thu Feb 4 09:31:43 2021 +0100

    Merge remote-tracking branch 'remotes/origin/master' into ys_diff_dlg

commit 6df8e83e1af3ba096ac39d25985b6deb2e0a245b
Author: Vojtech Bubnik <bubnikv@gmail.com>
Date:   Thu Feb 4 09:29:53 2021 +0100

    Tiny beautification.

commit e781ceaaf7c39bc073476409cc02918d9f182930
Author: Vojtech Bubnik <bubnikv@gmail.com>
Date:   Wed Feb 3 18:05:19 2021 +0100

    Reworked copying of PresetBundles:
    1) Simplified by using the default copy constructors and copy operators.
    2) Made safer by not allowing PresetCollection and PhysicalPrinterPresetCollection
       to be copied or instantiated outside of PresetBundle.
    3) Fixed Preset::vendor pointers after copying PresetBundle.

commit a8f0b7aa5156465cdb3e3dbb86feb66a64bcebc0
Author: YuSanka <yusanka@gmail.com>
Date:   Mon Jan 25 16:13:53 2021 +0100

    DiffPresetsDialog: Show compatibility to print/printer presets selected in DiffPresetDialog

commit 597451f930a4330376966d8cf3350056d4f85a73
Merge: cce5b5710 59017a7da
Author: YuSanka <yusanka@gmail.com>
Date:   Thu Jan 21 12:14:48 2021 +0100

    Merge remote-tracking branch 'origin/master' into ys_diff_dlg

commit cce5b5710d1225c7eaa52d0abb4b3f66fbd3b6a1
Author: YuSanka <yusanka@gmail.com>
Date:   Thu Jan 21 12:11:40 2021 +0100

    DiffPresetDialog: Fixed crash on ASAN build

commit ad8d728d89d7a75c2ac136ea8cdbb730ab774cd9
Author: YuSanka <yusanka@gmail.com>
Date:   Wed Jan 20 16:38:28 2021 +0100

    FullCompareDialog improvements

commit 316bafbeec9bb63f731b653d296062d9e22dd02f
Author: YuSanka <yusanka@gmail.com>
Date:   Wed Jan 20 09:25:46 2021 +0100

    DiffPresetDialog improvements:
    * Update presets lists after save changes in edited preset or change printer_technology
    * Tab.cpp: Build all unregular pages on a first build of the Printer Settings

commit 01171c8ef50389d0801b0ccc5746ab0c3b731b11
Author: YuSanka <yusanka@gmail.com>
Date:   Tue Jan 19 17:26:28 2021 +0100

    DiffPresetDialog : improvements
    * This dialog is non-modal now
    * "Compare presets" menu item is moved from "View" to the "Window" menu group
    * Added info tooltips for the bitmap buttons between presets
    * Added "Show all presets" checkbox
    * Show full difference between printer presets with different count of extruders

commit 3d38b62f3c9de8aab352ed3bcff297d5c0239b2e
Merge: e50fe6de9 9a2310ae9
Author: YuSanka <yusanka@gmail.com>
Date:   Mon Jan 18 10:00:18 2021 +0100

    Merge remote-tracking branch 'origin/master' into ys_diff_dlg

commit e50fe6de984decadfef3d4b952f0eec8ab9e6670
Author: YuSanka <yusanka@gmail.com>
Date:   Sat Jan 16 02:27:24 2021 +0100

    DiffPresetDialog improvements
    Added menu item "View->Compare presets" to compare more than one type of presets

commit bf08b7c8c969ad0ca631b9eeac1bc231f474e72b
Author: YuSanka <yusanka@gmail.com>
Date:   Sat Jan 16 00:28:39 2021 +0100

    Code refactoring. wxDataViewCtrl and related functions extracted from DiffPresetDialog and UnsavedChangesDialog to the separate class DiffViewCtrl

commit 7aeb63032b0bc2bd06e60990c060008660a5c44f
Author: YuSanka <yusanka@gmail.com>
Date:   Fri Jan 15 21:35:43 2021 +0100

    DiffPresetDialog: first implementation

commit 2f23d5af9d6b5dd670dfb7d06eedbe0e6d2960c6
Author: YuSanka <yusanka@gmail.com>
Date:   Thu Jan 14 16:28:43 2021 +0100

    Code refactoring for PresetComboBox.
    Use suffix "modified" just for PlaterPresetComboBox and TabPresetComboBox
This commit is contained in:
Vojtech Bubnik 2021-02-04 09:42:32 +01:00
parent 0baa92fab8
commit 4cdcfe6005
17 changed files with 1150 additions and 315 deletions

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="compare_1_">
<g id="compare">
<path fill="#ED6B21" d="M7.87,2.23c-1.54-1.54-4.04-1.54-5.59,0s-1.54,4.04,0,5.59c1.43,1.43,3.69,1.53,5.24,0.31l1.33,1.33
c0,0-0.33,0.33,0,0.66c0.33,0.33,3.29,3.29,3.29,3.29s0.33,0.33,0.66,0c0.33-0.33,0.66-0.66,0.66-0.66s0.33-0.33,0-0.66
c-0.33-0.33-3.29-3.29-3.29-3.29c-0.33-0.33-0.66,0-0.66,0L8.18,7.47C9.41,5.92,9.3,3.67,7.87,2.23z M7.52,7.47
c-1.35,1.35-3.54,1.35-4.89,0s-1.35-3.54,0-4.89s3.54-1.35,4.89,0S8.87,6.12,7.52,7.47z"/>
</g>
<path fill="#808080" d="M7.49,4.35C7.43,4.16,7.36,3.97,7.26,3.8l0.18-0.54L6.85,2.67L6.31,2.85c-0.17-0.1-0.36-0.17-0.56-0.23
L5.5,2.11H4.66L4.41,2.62c-0.2,0.05-0.38,0.13-0.56,0.23L3.31,2.67L2.72,3.26L2.9,3.8C2.8,3.97,2.72,4.16,2.67,4.35L2.16,4.61v0.83
L2.67,5.7C2.72,5.9,2.8,6.08,2.9,6.26L2.72,6.8l0.59,0.59l0.54-0.18c0.17,0.1,0.36,0.17,0.56,0.23l0.26,0.51H5.5l0.26-0.51
c0.2-0.05,0.38-0.13,0.56-0.23l0.54,0.18L7.44,6.8L7.26,6.26C7.36,6.08,7.43,5.9,7.49,5.7L8,5.45V4.61L7.49,4.35z M5.08,6.33
c-0.72,0-1.3-0.58-1.3-1.3c0-0.72,0.58-1.3,1.3-1.3s1.3,0.58,1.3,1.3C6.38,5.75,5.8,6.33,5.08,6.33z"/>
<path fill="#808080" d="M14.56,4.45c-0.05-0.17-0.11-0.33-0.2-0.48l0.15-0.46l-0.51-0.51l-0.46,0.15c-0.15-0.08-0.31-0.15-0.48-0.2
l-0.22-0.44h-0.71l-0.22,0.44c-0.17,0.05-0.33,0.11-0.48,0.2l-0.46-0.15l-0.51,0.51l0.15,0.46c-0.08,0.15-0.15,0.31-0.2,0.48
L10,4.67v0.71l0.44,0.22c0.05,0.17,0.11,0.33,0.2,0.48l-0.15,0.46l0.51,0.51l0.46-0.15c0.15,0.08,0.31,0.15,0.48,0.2l0.22,0.44
h0.71l0.22-0.44c0.17-0.05,0.33-0.11,0.48-0.2l0.46,0.15l0.51-0.51l-0.15-0.46c0.08-0.15,0.15-0.31,0.2-0.48L15,5.39V4.67
L14.56,4.45z M12.5,6.14c-0.62,0-1.11-0.5-1.11-1.11c0-0.62,0.5-1.11,1.11-1.11s1.11,0.5,1.11,1.11
C13.61,5.64,13.11,6.14,12.5,6.14z"/>
<path fill="#808080" d="M7.14,11.91c-0.05-0.17-0.11-0.33-0.2-0.48l0.15-0.46l-0.51-0.51l-0.46,0.15c-0.15-0.08-0.31-0.15-0.48-0.2
L5.44,9.99H4.72L4.5,10.43c-0.17,0.05-0.33,0.11-0.48,0.2l-0.46-0.15l-0.51,0.51l0.15,0.46c-0.08,0.15-0.15,0.31-0.2,0.48
l-0.44,0.22v0.71l0.44,0.22c0.05,0.17,0.11,0.33,0.2,0.48L3.06,14l0.51,0.51l0.46-0.15c0.15,0.08,0.31,0.15,0.48,0.2l0.22,0.44
h0.71l0.22-0.44c0.17-0.05,0.33-0.11,0.48-0.2l0.46,0.15L7.1,14l-0.15-0.46c0.08-0.15,0.15-0.31,0.2-0.48l0.44-0.22v-0.71
L7.14,11.91z M5.08,13.6c-0.62,0-1.11-0.5-1.11-1.11c0-0.62,0.5-1.11,1.11-1.11s1.11,0.5,1.11,1.11C6.19,13.11,5.69,13.6,5.08,13.6
z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

15
resources/icons/equal.svg Normal file
View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="121.805px" height="121.805px" viewBox="0 0 121.805 121.805" style="enable-background:new 0 0 121.805 121.805;"
xml:space="preserve">
<g>
<g>
<path fill="#808080" d="M7.308,85.264h107.188c4.037,0,7.309-3.271,7.309-7.31s-3.271-7.309-7.309-7.309H7.308C3.271,70.646,0,73.916,0,77.954
S3.271,85.264,7.308,85.264z"/>
<path fill="#808080" d="M7.308,51.158h107.188c4.037,0,7.309-3.272,7.309-7.309c0-4.037-3.271-7.308-7.309-7.308H7.308
C3.271,36.541,0,39.812,0,43.849C0,47.886,3.271,51.158,7.308,51.158z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 901 B

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="121.807px" height="121.807px" viewBox="0 0 121.807 121.807" style="enable-background:new 0 0 121.807 121.807;"
xml:space="preserve">
<g>
<g>
<path fill="#ED6B21" d="M7.308,75.519C3.271,75.519,0,78.789,0,82.827c0,4.036,3.271,7.31,7.308,7.31h18.897l-3.496,3.495
c-2.855,2.854-2.855,7.48,0,10.337c1.428,1.427,3.299,2.141,5.167,2.141c1.869,0,3.74-0.714,5.167-2.139l13.833-13.834h67.621
c4.037,0,7.31-3.272,7.31-7.31s-3.271-7.309-7.31-7.309H61.495L80.982,56.03h33.515c4.037,0,7.31-3.272,7.31-7.308
c0-4.037-3.271-7.309-7.31-7.309H95.602l13.24-13.24c2.854-2.855,2.854-7.481,0-10.336c-2.855-2.855-7.479-2.853-10.334,0
L74.932,41.414H7.308C3.271,41.414,0,44.685,0,48.723c0,4.036,3.271,7.308,7.308,7.308H60.31L40.821,75.519H7.308z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -616,10 +616,6 @@ PresetCollection::PresetCollection(Preset::Type type, const std::vector<std::str
m_edited_preset.config.apply(m_presets.front().config); m_edited_preset.config.apply(m_presets.front().config);
} }
PresetCollection::~PresetCollection()
{
}
void PresetCollection::reset(bool delete_files) void PresetCollection::reset(bool delete_files)
{ {
if (m_presets.size() > m_num_default_presets) { if (m_presets.size() > m_num_default_presets) {
@ -1278,6 +1274,18 @@ std::vector<std::string> PresetCollection::merge_presets(PresetCollection &&othe
return duplicates; return duplicates;
} }
void PresetCollection::update_vendor_ptrs_after_copy(const VendorMap &new_vendors)
{
for (Preset &preset : m_presets)
if (preset.vendor != nullptr) {
assert(! preset.is_default && ! preset.is_external);
// Re-assign a pointer to the vendor structure in the new PresetBundle.
auto it = new_vendors.find(preset.vendor->id);
assert(it != new_vendors.end());
preset.vendor = &it->second;
}
}
void PresetCollection::update_map_alias_to_profile_name() void PresetCollection::update_map_alias_to_profile_name()
{ {
m_map_alias_to_profile_name.clear(); m_map_alias_to_profile_name.clear();

View File

@ -115,13 +115,11 @@ public:
TYPE_COUNT, TYPE_COUNT,
}; };
Preset(Type type, const std::string &name, bool is_default = false) : type(type), is_default(is_default), name(name) {}
Type type = TYPE_INVALID; Type type = TYPE_INVALID;
// The preset represents a "default" set of properties, // The preset represents a "default" set of properties,
// pulled from the default values of the PrintConfig (see PrintConfigDef for their definitions). // pulled from the default values of the PrintConfig (see PrintConfigDef for their definitions).
bool is_default; bool is_default = false;
// External preset points to a configuration, which has been loaded but not imported // External preset points to a configuration, which has been loaded but not imported
// into the Slic3r default configuration location. // into the Slic3r default configuration location.
bool is_external = false; bool is_external = false;
@ -233,6 +231,9 @@ public:
static std::string remove_invalid_keys(DynamicPrintConfig &config, const DynamicPrintConfig &default_config); static std::string remove_invalid_keys(DynamicPrintConfig &config, const DynamicPrintConfig &default_config);
protected: protected:
Preset(Type type, const std::string &name, bool is_default = false) : type(type), is_default(is_default), name(name) {}
Preset() = default;
friend class PresetCollection; friend class PresetCollection;
friend class PresetBundle; friend class PresetBundle;
}; };
@ -256,7 +257,6 @@ class PresetCollection
public: public:
// Initialize the PresetCollection with the "- default -" preset. // Initialize the PresetCollection with the "- default -" preset.
PresetCollection(Preset::Type type, const std::vector<std::string> &keys, const Slic3r::StaticPrintConfig &defaults, const std::string &default_name = "- default -"); PresetCollection(Preset::Type type, const std::vector<std::string> &keys, const Slic3r::StaticPrintConfig &defaults, const std::string &default_name = "- default -");
~PresetCollection();
typedef std::deque<Preset>::iterator Iterator; typedef std::deque<Preset>::iterator Iterator;
typedef std::deque<Preset>::const_iterator ConstIterator; typedef std::deque<Preset>::const_iterator ConstIterator;
@ -460,6 +460,15 @@ public:
size_t num_default_presets() { return m_num_default_presets; } size_t num_default_presets() { return m_num_default_presets; }
protected: protected:
PresetCollection() = default;
// Copy constructor and copy operators are not to be used from outside PresetBundle,
// as the Profile::vendor points to an instance of VendorProfile stored at parent PresetBundle!
PresetCollection(const PresetCollection &other) = default;
PresetCollection& operator=(const PresetCollection &other) = default;
// After copying a collection with the default operators above, call this function
// to adjust Profile::vendor pointers.
void update_vendor_ptrs_after_copy(const VendorMap &vendors);
// Select a preset, if it exists. If it does not exist, select an invalid (-1) index. // Select a preset, if it exists. If it does not exist, select an invalid (-1) index.
// This is a temporary state, which shall be fixed immediately by the following step. // This is a temporary state, which shall be fixed immediately by the following step.
bool select_preset_by_name_strict(const std::string &name); bool select_preset_by_name_strict(const std::string &name);
@ -474,10 +483,6 @@ protected:
void update_map_system_profile_renamed(); void update_map_system_profile_renamed();
private: private:
PresetCollection();
PresetCollection(const PresetCollection &other);
PresetCollection& operator=(const PresetCollection &other);
// Find a preset position in the sorted list of presets. // Find a preset position in the sorted list of presets.
// The "-- default -- " preset is always the first, so it needs // The "-- default -- " preset is always the first, so it needs
// to be handled differently. // to be handled differently.
@ -507,9 +512,9 @@ private:
{ return const_cast<PresetCollection*>(this)->find_preset_renamed(name); } { return const_cast<PresetCollection*>(this)->find_preset_renamed(name); }
size_t update_compatible_internal(const PresetWithVendorProfile &active_printer, const PresetWithVendorProfile *active_print, PresetSelectCompatibleType unselect_if_incompatible); size_t update_compatible_internal(const PresetWithVendorProfile &active_printer, const PresetWithVendorProfile *active_print, PresetSelectCompatibleType unselect_if_incompatible);
public:
static std::vector<std::string> dirty_options(const Preset *edited, const Preset *reference, const bool is_printer_type = false); static std::vector<std::string> dirty_options(const Preset *edited, const Preset *reference, const bool is_printer_type = false);
private:
// Type of this PresetCollection: TYPE_PRINT, TYPE_FILAMENT or TYPE_PRINTER. // Type of this PresetCollection: TYPE_PRINT, TYPE_FILAMENT or TYPE_PRINTER.
Preset::Type m_type; Preset::Type m_type;
// List of presets, starting with the "- default -" preset. // List of presets, starting with the "- default -" preset.
@ -531,7 +536,7 @@ private:
// Path to the directory to store the config files into. // Path to the directory to store the config files into.
std::string m_dir_path; std::string m_dir_path;
// to access select_preset_by_name_strict() // to access select_preset_by_name_strict() and the default & copy constructors.
friend class PresetBundle; friend class PresetBundle;
}; };
@ -542,9 +547,17 @@ class PrinterPresetCollection : public PresetCollection
public: public:
PrinterPresetCollection(Preset::Type type, const std::vector<std::string> &keys, const Slic3r::StaticPrintConfig &defaults, const std::string &default_name = "- default -") : PrinterPresetCollection(Preset::Type type, const std::vector<std::string> &keys, const Slic3r::StaticPrintConfig &defaults, const std::string &default_name = "- default -") :
PresetCollection(type, keys, defaults, default_name) {} PresetCollection(type, keys, defaults, default_name) {}
const Preset& default_preset_for(const DynamicPrintConfig &config) const override; const Preset& default_preset_for(const DynamicPrintConfig &config) const override;
const Preset* find_by_model_id(const std::string &model_id) const; const Preset* find_by_model_id(const std::string &model_id) const;
private:
PrinterPresetCollection() = default;
PrinterPresetCollection(const PrinterPresetCollection &other) = default;
PrinterPresetCollection& operator=(const PrinterPresetCollection &other) = default;
friend class PresetBundle;
}; };
namespace PresetUtils { namespace PresetUtils {
@ -634,7 +647,6 @@ class PhysicalPrinterCollection
{ {
public: public:
PhysicalPrinterCollection(const std::vector<std::string>& keys); PhysicalPrinterCollection(const std::vector<std::string>& keys);
~PhysicalPrinterCollection() {}
typedef std::deque<PhysicalPrinter>::iterator Iterator; typedef std::deque<PhysicalPrinter>::iterator Iterator;
typedef std::deque<PhysicalPrinter>::const_iterator ConstIterator; typedef std::deque<PhysicalPrinter>::const_iterator ConstIterator;
@ -725,7 +737,9 @@ public:
const DynamicPrintConfig& default_config() const { return m_default_config; } const DynamicPrintConfig& default_config() const { return m_default_config; }
private: private:
PhysicalPrinterCollection& operator=(const PhysicalPrinterCollection& other); friend class PresetBundle;
PhysicalPrinterCollection() = default;
PhysicalPrinterCollection& operator=(const PhysicalPrinterCollection& other) = default;
// Find a physical printer position in the sorted list of printers. // Find a physical printer position in the sorted list of printers.
// The name of a printer should be unique and case insensitive // The name of a printer should be unique and case insensitive

View File

@ -105,8 +105,33 @@ PresetBundle::PresetBundle() :
this->project_config.apply_only(FullPrintConfig::defaults(), s_project_options); this->project_config.apply_only(FullPrintConfig::defaults(), s_project_options);
} }
PresetBundle::~PresetBundle() PresetBundle::PresetBundle(const PresetBundle &rhs)
{ {
*this = rhs;
}
PresetBundle& PresetBundle::operator=(const PresetBundle &rhs)
{
prints = rhs.prints;
sla_prints = rhs.sla_prints;
filaments = rhs.filaments;
sla_materials = rhs.sla_materials;
printers = rhs.printers;
physical_printers = rhs.physical_printers;
filament_presets = rhs.filament_presets;
project_config = rhs.project_config;
vendors = rhs.vendors;
obsolete_presets = rhs.obsolete_presets;
// Adjust Preset::vendor pointers to point to the copied vendors map.
prints .update_vendor_ptrs_after_copy(this->vendors);
sla_prints .update_vendor_ptrs_after_copy(this->vendors);
filaments .update_vendor_ptrs_after_copy(this->vendors);
sla_materials.update_vendor_ptrs_after_copy(this->vendors);
printers .update_vendor_ptrs_after_copy(this->vendors);
return *this;
} }
void PresetBundle::reset(bool delete_files) void PresetBundle::reset(bool delete_files)

View File

@ -15,7 +15,8 @@ class PresetBundle
{ {
public: public:
PresetBundle(); PresetBundle();
~PresetBundle(); PresetBundle(const PresetBundle &rhs);
PresetBundle& operator=(const PresetBundle &rhs);
// Remove all the presets but the "-- default --". // Remove all the presets but the "-- default --".
// Optionally remove all the files referenced by the presets from the user profile directory. // Optionally remove all the files referenced by the presets from the user profile directory.

View File

@ -37,6 +37,7 @@
#include <string_view> #include <string_view>
#include "GUI_App.hpp" #include "GUI_App.hpp"
#include "UnsavedChangesDialog.hpp"
#ifdef _WIN32 #ifdef _WIN32
#include <dbt.h> #include <dbt.h>
@ -1190,6 +1191,10 @@ void MainFrame::init_menubar_as_editor()
windowMenu->AppendSeparator(); windowMenu->AppendSeparator();
append_menu_item(windowMenu, wxID_ANY, _L("Open new instance") + "\tCtrl+Shift+I", _L("Open a new PrusaSlicer instance"), append_menu_item(windowMenu, wxID_ANY, _L("Open new instance") + "\tCtrl+Shift+I", _L("Open a new PrusaSlicer instance"),
[this](wxCommandEvent&) { start_new_slicer(); }, "", nullptr, [this]() {return m_plater != nullptr && wxGetApp().app_config->get("single_instance") != "1"; }, this); [this](wxCommandEvent&) { start_new_slicer(); }, "", nullptr, [this]() {return m_plater != nullptr && wxGetApp().app_config->get("single_instance") != "1"; }, this);
windowMenu->AppendSeparator();
append_menu_item(windowMenu, wxID_ANY, _L("Compare presets")/* + "\tCtrl+F"*/, _L("Compare presets"),
[this](wxCommandEvent&) { diff_dialog.show();}, "compare", nullptr, []() {return true; }, this);
} }
// View menu // View menu

View File

@ -16,6 +16,7 @@
#include "GUI_Utils.hpp" #include "GUI_Utils.hpp"
#include "Event.hpp" #include "Event.hpp"
#include "UnsavedChangesDialog.hpp"
class wxNotebook; class wxNotebook;
class wxProgressDialog; class wxProgressDialog;
@ -190,6 +191,7 @@ public:
Plater* m_plater { nullptr }; Plater* m_plater { nullptr };
wxNotebook* m_tabpanel { nullptr }; wxNotebook* m_tabpanel { nullptr };
SettingsDialog m_settings_dialog; SettingsDialog m_settings_dialog;
DiffPresetDialog diff_dialog;
wxWindow* m_plater_page{ nullptr }; wxWindow* m_plater_page{ nullptr };
wxProgressDialog* m_progress_dialog { nullptr }; wxProgressDialog* m_progress_dialog { nullptr };
PrintHostQueueDialog* m_printhost_queue_dlg; PrintHostQueueDialog* m_printhost_queue_dlg;

View File

@ -62,12 +62,12 @@ namespace GUI {
* control size calculation methods (virtual) are overridden. * control size calculation methods (virtual) are overridden.
**/ **/
PresetComboBox::PresetComboBox(wxWindow* parent, Preset::Type preset_type, const wxSize& size) : PresetComboBox::PresetComboBox(wxWindow* parent, Preset::Type preset_type, const wxSize& size, PresetBundle* preset_bundle/* = nullptr*/) :
wxBitmapComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, size, 0, nullptr, wxCB_READONLY), wxBitmapComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, size, 0, nullptr, wxCB_READONLY),
m_type(preset_type), m_type(preset_type),
m_last_selected(wxNOT_FOUND), m_last_selected(wxNOT_FOUND),
m_em_unit(em_unit(this)), m_em_unit(em_unit(this)),
m_preset_bundle(wxGetApp().preset_bundle) m_preset_bundle(preset_bundle ? preset_bundle : wxGetApp().preset_bundle)
{ {
SetFont(wxGetApp().normal_font()); SetFont(wxGetApp().normal_font());
#ifdef _WIN32 #ifdef _WIN32
@ -208,6 +208,21 @@ void PresetComboBox::update_selection()
#endif #endif
} }
static std::string suffix(const Preset& preset)
{
return (preset.is_dirty ? Preset::suffix_modified() : "");
}
static std::string suffix(Preset* preset)
{
return (preset->is_dirty ? Preset::suffix_modified() : "");
}
wxString PresetComboBox::get_preset_name(const Preset & preset)
{
return from_u8(preset.name/* + suffix(preset)*/);
}
void PresetComboBox::update(std::string select_preset_name) void PresetComboBox::update(std::string select_preset_name)
{ {
Freeze(); Freeze();
@ -226,7 +241,7 @@ void PresetComboBox::update(std::string select_preset_name)
for (size_t i = presets.front().is_visible ? 0 : m_collection->num_default_presets(); i < presets.size(); ++i) for (size_t i = presets.front().is_visible ? 0 : m_collection->num_default_presets(); i < presets.size(); ++i)
{ {
const Preset& preset = presets[i]; const Preset& preset = presets[i];
if (!preset.is_visible || !preset.is_compatible) if (!m_show_all && (!preset.is_visible || !preset.is_compatible))
continue; continue;
// marker used for disable incompatible printer models for the selected physical printer // marker used for disable incompatible printer models for the selected physical printer
@ -246,17 +261,17 @@ void PresetComboBox::update(std::string select_preset_name)
assert(bmp); assert(bmp);
if (!is_enabled) if (!is_enabled)
incomp_presets.emplace(wxString::FromUTF8((preset.name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()), bmp); incomp_presets.emplace(get_preset_name(preset), bmp);
else if (preset.is_default || preset.is_system) else if (preset.is_default || preset.is_system)
{ {
Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()), *bmp); Append(get_preset_name(preset), *bmp);
validate_selection(preset.name == select_preset_name); validate_selection(preset.name == select_preset_name);
} }
else else
{ {
nonsys_presets.emplace(wxString::FromUTF8((preset.name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()), std::pair<wxBitmap*, bool>(bmp, is_enabled)); nonsys_presets.emplace(get_preset_name(preset), std::pair<wxBitmap*, bool>(bmp, is_enabled));
if (preset.name == select_preset_name || (select_preset_name.empty() && is_enabled)) if (preset.name == select_preset_name || (select_preset_name.empty() && is_enabled))
selected = wxString::FromUTF8((preset.name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()); selected = get_preset_name(preset);
} }
if (i + 1 == m_collection->num_default_presets()) if (i + 1 == m_collection->num_default_presets())
set_label_marker(Append(separator(L("System presets")), wxNullBitmap)); set_label_marker(Append(separator(L("System presets")), wxNullBitmap));
@ -329,11 +344,22 @@ bool PresetComboBox::del_physical_printer(const wxString& note_string/* = wxEmpt
return true; return true;
} }
void PresetComboBox::show_all(bool show_all)
{
m_show_all = show_all;
update();
}
void PresetComboBox::update() void PresetComboBox::update()
{ {
this->update(into_u8(this->GetString(this->GetSelection()))); this->update(into_u8(this->GetString(this->GetSelection())));
} }
void PresetComboBox::update_from_bundle()
{
this->update(m_collection->get_selected_preset().name);
}
void PresetComboBox::msw_rescale() void PresetComboBox::msw_rescale()
{ {
m_em_unit = em_unit(this); m_em_unit = em_unit(this);
@ -745,6 +771,12 @@ void PlaterPresetComboBox::show_edit_menu()
wxGetApp().plater()->PopupMenu(menu); wxGetApp().plater()->PopupMenu(menu);
} }
wxString PlaterPresetComboBox::get_preset_name(const Preset& preset)
{
std::string name = preset.alias.empty() ? preset.name : preset.alias;
return from_u8(name + suffix(preset));
}
// Only the compatible presets are shown. // Only the compatible presets are shown.
// If an incompatible preset is selected, it is shown as well. // If an incompatible preset is selected, it is shown as well.
void PlaterPresetComboBox::update() void PlaterPresetComboBox::update()
@ -821,17 +853,17 @@ void PlaterPresetComboBox::update()
const std::string name = preset.alias.empty() ? preset.name : preset.alias; const std::string name = preset.alias.empty() ? preset.name : preset.alias;
if (preset.is_default || preset.is_system) { if (preset.is_default || preset.is_system) {
Append(wxString::FromUTF8((name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()), *bmp); Append(get_preset_name(preset), *bmp);
validate_selection(is_selected); validate_selection(is_selected);
if (is_selected) if (is_selected)
tooltip = wxString::FromUTF8(preset.name.c_str()); tooltip = from_u8(preset.name);
} }
else else
{ {
nonsys_presets.emplace(wxString::FromUTF8((name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()), bmp); nonsys_presets.emplace(get_preset_name(preset), bmp);
if (is_selected) { if (is_selected) {
selected_user_preset = wxString::FromUTF8((name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()); selected_user_preset = get_preset_name(preset);
tooltip = wxString::FromUTF8(preset.name.c_str()); tooltip = from_u8(preset.name);
} }
} }
if (i + 1 == m_collection->num_default_presets()) if (i + 1 == m_collection->num_default_presets())
@ -862,7 +894,7 @@ void PlaterPresetComboBox::update()
wxBitmap* bmp = get_bmp(main_icon_name, wide_icons, main_icon_name); wxBitmap* bmp = get_bmp(main_icon_name, wide_icons, main_icon_name);
assert(bmp); assert(bmp);
set_label_marker(Append(wxString::FromUTF8((it->get_full_name(preset_name) + (preset->is_dirty ? Preset::suffix_modified() : "")).c_str()), *bmp), LABEL_ITEM_PHYSICAL_PRINTER); set_label_marker(Append(from_u8(it->get_full_name(preset_name) + suffix(preset)), *bmp), LABEL_ITEM_PHYSICAL_PRINTER);
validate_selection(ph_printers.is_selected(it, preset_name)); validate_selection(ph_printers.is_selected(it, preset_name));
} }
} }
@ -946,6 +978,11 @@ TabPresetComboBox::TabPresetComboBox(wxWindow* parent, Preset::Type preset_type)
}); });
} }
wxString TabPresetComboBox::get_preset_name(const Preset& preset)
{
return from_u8(preset.name + suffix(preset));
}
// Update the choice UI from the list of presets. // Update the choice UI from the list of presets.
// If show_incompatible, all presets are shown, otherwise only the compatible presets are shown. // If show_incompatible, all presets are shown, otherwise only the compatible presets are shown.
// If an incompatible preset is selected, it is shown as well. // If an incompatible preset is selected, it is shown as well.
@ -991,7 +1028,7 @@ void TabPresetComboBox::update()
assert(bmp); assert(bmp);
if (preset.is_default || preset.is_system) { if (preset.is_default || preset.is_system) {
int item_id = Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()), *bmp); int item_id = Append(get_preset_name(preset), *bmp);
if (!is_enabled) if (!is_enabled)
set_label_marker(item_id, LABEL_ITEM_DISABLED); set_label_marker(item_id, LABEL_ITEM_DISABLED);
validate_selection(i == idx_selected); validate_selection(i == idx_selected);
@ -999,9 +1036,9 @@ void TabPresetComboBox::update()
else else
{ {
std::pair<wxBitmap*, bool> pair(bmp, is_enabled); std::pair<wxBitmap*, bool> pair(bmp, is_enabled);
nonsys_presets.emplace(wxString::FromUTF8((preset.name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()), std::pair<wxBitmap*, bool>(bmp, is_enabled)); nonsys_presets.emplace(get_preset_name(preset), std::pair<wxBitmap*, bool>(bmp, is_enabled));
if (i == idx_selected) if (i == idx_selected)
selected = wxString::FromUTF8((preset.name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()); selected = get_preset_name(preset);
} }
if (i + 1 == m_collection->num_default_presets()) if (i + 1 == m_collection->num_default_presets())
set_label_marker(Append(separator(L("System presets")), wxNullBitmap)); set_label_marker(Append(separator(L("System presets")), wxNullBitmap));
@ -1035,7 +1072,7 @@ void TabPresetComboBox::update()
wxBitmap* bmp = get_bmp(main_icon_name, main_icon_name, "", true, true, false); wxBitmap* bmp = get_bmp(main_icon_name, main_icon_name, "", true, true, false);
assert(bmp); assert(bmp);
set_label_marker(Append(wxString::FromUTF8((it->get_full_name(preset_name) + (preset->is_dirty ? Preset::suffix_modified() : "")).c_str()), *bmp), LABEL_ITEM_PHYSICAL_PRINTER); set_label_marker(Append(from_u8(it->get_full_name(preset_name) + suffix(preset)), *bmp), LABEL_ITEM_PHYSICAL_PRINTER);
validate_selection(ph_printers.is_selected(it, preset_name)); validate_selection(ph_printers.is_selected(it, preset_name));
} }
} }
@ -1082,15 +1119,15 @@ void TabPresetComboBox::update_dirty()
preset_name = PhysicalPrinter::get_preset_name(preset_name); preset_name = PhysicalPrinter::get_preset_name(preset_name);
} }
const Preset* preset = m_collection->find_preset(preset_name, false); Preset* preset = m_collection->find_preset(preset_name, false);
if (preset) { if (preset) {
std::string new_label = preset->is_dirty ? preset->name + Preset::suffix_modified() : preset->name; std::string new_label = preset->name + suffix(preset);
if (marker == LABEL_ITEM_PHYSICAL_PRINTER) if (marker == LABEL_ITEM_PHYSICAL_PRINTER)
new_label = ph_printer_name + PhysicalPrinter::separator() + new_label; new_label = ph_printer_name + PhysicalPrinter::separator() + new_label;
if (old_label != new_label) if (old_label != new_label)
SetString(ui_id, wxString::FromUTF8(new_label.c_str())); SetString(ui_id, from_u8(new_label));
} }
} }
#ifdef __APPLE__ #ifdef __APPLE__

View File

@ -30,8 +30,9 @@ class BitmapCache;
// BitmapComboBox used to presets list on Sidebar and Tabs // BitmapComboBox used to presets list on Sidebar and Tabs
class PresetComboBox : public wxBitmapComboBox class PresetComboBox : public wxBitmapComboBox
{ {
bool m_show_all { false };
public: public:
PresetComboBox(wxWindow* parent, Preset::Type preset_type, const wxSize& size = wxDefaultSize); PresetComboBox(wxWindow* parent, Preset::Type preset_type, const wxSize& size = wxDefaultSize, PresetBundle* preset_bundle = nullptr);
~PresetComboBox(); ~PresetComboBox();
enum LabelItemType { enum LabelItemType {
@ -58,11 +59,16 @@ public:
bool selection_is_changed_according_to_physical_printers(); bool selection_is_changed_according_to_physical_printers();
void update(std::string select_preset); void update(std::string select_preset);
// select preset which is selected in PreseBundle
void update_from_bundle();
void edit_physical_printer(); void edit_physical_printer();
void add_physical_printer(); void add_physical_printer();
bool del_physical_printer(const wxString& note_string = wxEmptyString); bool del_physical_printer(const wxString& note_string = wxEmptyString);
virtual wxString get_preset_name(const Preset& preset);
Preset::Type get_type() { return m_type; }
void show_all(bool show_all);
virtual void update(); virtual void update();
virtual void msw_rescale(); virtual void msw_rescale();
@ -158,6 +164,7 @@ public:
void show_add_menu(); void show_add_menu();
void show_edit_menu(); void show_edit_menu();
wxString get_preset_name(const Preset& preset) override;
void update() override; void update() override;
void msw_rescale() override; void msw_rescale() override;
@ -182,6 +189,7 @@ public:
show_incompatible = show_incompatible_presets; show_incompatible = show_incompatible_presets;
} }
wxString get_preset_name(const Preset& preset) override;
void update() override; void update() override;
void update_dirty(); void update_dirty();
void msw_rescale() override; void msw_rescale() override;

View File

@ -326,6 +326,53 @@ const Option& OptionsSearcher::get_option(const std::string& opt_key) const
return options[it - options.begin()]; return options[it - options.begin()];
} }
static Option create_option(const std::string& opt_key, const wxString& label, Preset::Type type, const GroupAndCategory& gc)
{
wxString suffix;
wxString suffix_local;
if (gc.category == "Machine limits") {
suffix = opt_key.back() == '1' ? L("Stealth") : L("Normal");
suffix_local = " " + _(suffix);
suffix = " " + suffix;
}
wxString category = gc.category;
if (type == Preset::TYPE_PRINTER && category.Contains("Extruder ")) {
std::string opt_idx = opt_key.substr(opt_key.find("#") + 1);
category = wxString::Format("%s %d", "Extruder", atoi(opt_idx.c_str()) + 1);
}
return Option{ boost::nowide::widen(opt_key), type,
(label + suffix).ToStdWstring(), (_(label) + suffix_local).ToStdWstring(),
gc.group.ToStdWstring(), _(gc.group).ToStdWstring(),
gc.category.ToStdWstring(), GUI::Tab::translate_category(category, type).ToStdWstring() };
}
Option OptionsSearcher::get_option(const std::string& opt_key, const wxString& label, Preset::Type type) const
{
auto it = std::lower_bound(options.begin(), options.end(), Option({ boost::nowide::widen(opt_key) }));
if(it->opt_key == boost::nowide::widen(opt_key))
return options[it - options.begin()];
if (groups_and_categories.find(opt_key) == groups_and_categories.end()) {
size_t pos = opt_key.find('#');
if (pos == std::string::npos)
return options[it - options.begin()];
std::string zero_opt_key = opt_key.substr(0, pos + 1) + "0";
if(groups_and_categories.find(zero_opt_key) == groups_and_categories.end())
return options[it - options.begin()];
return create_option(opt_key, label, type, groups_and_categories.at(zero_opt_key));
}
const GroupAndCategory& gc = groups_and_categories.at(opt_key);
if (gc.group.IsEmpty() || gc.category.IsEmpty())
return options[it - options.begin()];
return create_option(opt_key, label, type, gc);
}
void OptionsSearcher::add_key(const std::string& opt_key, const wxString& group, const wxString& category) void OptionsSearcher::add_key(const std::string& opt_key, const wxString& group, const wxString& category)
{ {
groups_and_categories[opt_key] = GroupAndCategory{group, category}; groups_and_categories[opt_key] = GroupAndCategory{group, category};

View File

@ -117,6 +117,7 @@ public:
const FoundOption& operator[](const size_t pos) const noexcept { return found[pos]; } const FoundOption& operator[](const size_t pos) const noexcept { return found[pos]; }
const Option& get_option(size_t pos_in_filter) const; const Option& get_option(size_t pos_in_filter) const;
const Option& get_option(const std::string& opt_key) const; const Option& get_option(const std::string& opt_key) const;
Option get_option(const std::string& opt_key, const wxString& label, Preset::Type type) const;
const std::vector<FoundOption>& found_options() { return found; } const std::vector<FoundOption>& found_options() { return found; }
const GroupAndCategory& get_group_and_category (const std::string& opt_key) { return groups_and_categories[opt_key]; } const GroupAndCategory& get_group_and_category (const std::string& opt_key) { return groups_and_categories[opt_key]; }

View File

@ -196,6 +196,7 @@ void Tab::create_preset_tab()
m_scaled_buttons.reserve(6); m_scaled_buttons.reserve(6);
m_scaled_buttons.reserve(2); m_scaled_buttons.reserve(2);
add_scaled_button(panel, &m_btn_compare_preset, "compare");
add_scaled_button(panel, &m_btn_save_preset, "save"); add_scaled_button(panel, &m_btn_save_preset, "save");
add_scaled_button(panel, &m_btn_delete_preset, "cross"); add_scaled_button(panel, &m_btn_delete_preset, "cross");
if (m_type == Preset::Type::TYPE_PRINTER) if (m_type == Preset::Type::TYPE_PRINTER)
@ -207,6 +208,7 @@ void Tab::create_preset_tab()
add_scaled_button(panel, &m_btn_hide_incompatible_presets, m_bmp_hide_incompatible_presets.name()); add_scaled_button(panel, &m_btn_hide_incompatible_presets, m_bmp_hide_incompatible_presets.name());
m_btn_compare_preset->SetToolTip(_L("Compare this preset with some another"));
// TRN "Save current Settings" // TRN "Save current Settings"
m_btn_save_preset->SetToolTip(from_u8((boost::format(_utf8(L("Save current %s"))) % m_title).str())); m_btn_save_preset->SetToolTip(from_u8((boost::format(_utf8(L("Save current %s"))) % m_title).str()));
m_btn_delete_preset->SetToolTip(_(L("Delete this preset"))); m_btn_delete_preset->SetToolTip(_(L("Delete this preset")));
@ -271,6 +273,9 @@ void Tab::create_preset_tab()
m_hsizer->Add(m_undo_btn, 0, wxALIGN_CENTER_VERTICAL); m_hsizer->Add(m_undo_btn, 0, wxALIGN_CENTER_VERTICAL);
m_hsizer->AddSpacer(int(32 * scale_factor)); m_hsizer->AddSpacer(int(32 * scale_factor));
m_hsizer->Add(m_search_btn, 0, wxALIGN_CENTER_VERTICAL); m_hsizer->Add(m_search_btn, 0, wxALIGN_CENTER_VERTICAL);
m_hsizer->AddSpacer(int(8*scale_factor));
m_hsizer->Add(m_btn_compare_preset, 0, wxALIGN_CENTER_VERTICAL);
m_hsizer->AddSpacer(int(16*scale_factor));
// m_hsizer->AddStretchSpacer(32); // m_hsizer->AddStretchSpacer(32);
// StretchSpacer has a strange behavior under OSX, so // StretchSpacer has a strange behavior under OSX, so
// There is used just additional sizer for m_mode_sizer with right alignment // There is used just additional sizer for m_mode_sizer with right alignment
@ -338,6 +343,7 @@ void Tab::create_preset_tab()
m_page_view->SetScrollbars(1, 20, 1, 2); m_page_view->SetScrollbars(1, 20, 1, 2);
m_hsizer->Add(m_page_view, 1, wxEXPAND | wxLEFT, 5); m_hsizer->Add(m_page_view, 1, wxEXPAND | wxLEFT, 5);
m_btn_compare_preset->Bind(wxEVT_BUTTON, ([this](wxCommandEvent e) { compare_preset(); }));
m_btn_save_preset->Bind(wxEVT_BUTTON, ([this](wxCommandEvent e) { save_preset(); })); m_btn_save_preset->Bind(wxEVT_BUTTON, ([this](wxCommandEvent e) { save_preset(); }));
m_btn_delete_preset->Bind(wxEVT_BUTTON, ([this](wxCommandEvent e) { delete_preset(); })); m_btn_delete_preset->Bind(wxEVT_BUTTON, ([this](wxCommandEvent e) { delete_preset(); }));
m_btn_hide_incompatible_presets->Bind(wxEVT_BUTTON, ([this](wxCommandEvent e) { m_btn_hide_incompatible_presets->Bind(wxEVT_BUTTON, ([this](wxCommandEvent e) {
@ -2066,11 +2072,18 @@ bool Tab::current_preset_is_dirty()
void TabPrinter::build() void TabPrinter::build()
{ {
m_presets = &m_preset_bundle->printers; m_presets = &m_preset_bundle->printers;
load_initial_data();
m_printer_technology = m_presets->get_selected_preset().printer_technology(); m_printer_technology = m_presets->get_selected_preset().printer_technology();
m_presets->get_selected_preset().printer_technology() == ptSLA ? build_sla() : build_fff(); // For DiffPresetDialog we use options list which is saved in Searcher class.
// Options for the Searcher is added in the moment of pages creation.
// So, build first of all printer pages for non-selected printer technology...
std::string def_preset_name = "- default " + std::string(m_printer_technology == ptSLA ? "FFF" : "SLA") + " -";
m_config = &m_presets->find_preset(def_preset_name)->config;
m_printer_technology == ptSLA ? build_fff() : build_sla();
// ... and than for selected printer technology
load_initial_data();
m_printer_technology == ptSLA ? build_sla() : build_fff();
} }
void TabPrinter::build_print_host_upload_group(Page* page) void TabPrinter::build_print_host_upload_group(Page* page)
@ -2105,7 +2118,8 @@ void TabPrinter::build_fff()
m_initial_extruders_count = m_extruders_count = nozzle_diameter->values.size(); m_initial_extruders_count = m_extruders_count = nozzle_diameter->values.size();
wxGetApp().sidebar().update_objects_list_extruder_column(m_initial_extruders_count); wxGetApp().sidebar().update_objects_list_extruder_column(m_initial_extruders_count);
const Preset* parent_preset = m_presets->get_selected_preset_parent(); const Preset* parent_preset = m_printer_technology == ptSLA ? nullptr // just for first build, if SLA printer preset is selected
: m_presets->get_selected_preset_parent();
m_sys_extruders_count = parent_preset == nullptr ? 0 : m_sys_extruders_count = parent_preset == nullptr ? 0 :
static_cast<const ConfigOptionFloats*>(parent_preset->config.option("nozzle_diameter"))->values.size(); static_cast<const ConfigOptionFloats*>(parent_preset->config.option("nozzle_diameter"))->values.size();
@ -2289,7 +2303,7 @@ void TabPrinter::build_fff()
build_preset_description_line(optgroup.get()); build_preset_description_line(optgroup.get());
build_unregular_pages(); build_unregular_pages(true);
} }
void TabPrinter::build_sla() void TabPrinter::build_sla()
@ -2395,7 +2409,9 @@ void TabPrinter::append_option_line(ConfigOptionsGroupShp optgroup, const std::s
auto option = optgroup->get_option(opt_key, 0); auto option = optgroup->get_option(opt_key, 0);
auto line = Line{ option.opt.full_label, "" }; auto line = Line{ option.opt.full_label, "" };
line.append_option(option); line.append_option(option);
if (m_use_silent_mode) if (m_use_silent_mode
|| m_printer_technology == ptSLA // just for first build, if SLA printer preset is selected
)
line.append_option(optgroup->get_option(opt_key, 1)); line.append_option(optgroup->get_option(opt_key, 1));
optgroup->append_line(line); optgroup->append_line(line);
} }
@ -2470,7 +2486,7 @@ PageShp TabPrinter::build_kinematics_page()
* but "Machine limits" and "Single extruder MM setup" too * but "Machine limits" and "Single extruder MM setup" too
* (These pages can changes according to the another values of a current preset) * (These pages can changes according to the another values of a current preset)
* */ * */
void TabPrinter::build_unregular_pages() void TabPrinter::build_unregular_pages(bool from_initial_build/* = false*/)
{ {
size_t n_before_extruders = 2; // Count of pages before Extruder pages size_t n_before_extruders = 2; // Count of pages before Extruder pages
bool is_marlin_flavor = m_config->option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value == gcfMarlin; bool is_marlin_flavor = m_config->option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value == gcfMarlin;
@ -2481,18 +2497,6 @@ void TabPrinter::build_unregular_pages()
* */ * */
Freeze(); Freeze();
#ifdef __WXMSW__
/* Workaround for correct layout of controls inside the created page:
* In some _strange_ way we should we should imitate page resizing.
*/
/* auto layout_page = [this](PageShp page)
{
const wxSize& sz = page->GetSize();
page->SetSize(sz.x + 1, sz.y + 1);
page->SetSize(sz);
};*/
#endif //__WXMSW__
// Add/delete Kinematics page according to is_marlin_flavor // Add/delete Kinematics page according to is_marlin_flavor
size_t existed_page = 0; size_t existed_page = 0;
for (size_t i = n_before_extruders; i < m_pages.size(); ++i) // first make sure it's not there already for (size_t i = n_before_extruders; i < m_pages.size(); ++i) // first make sure it's not there already
@ -2504,12 +2508,12 @@ void TabPrinter::build_unregular_pages()
break; break;
} }
if (existed_page < n_before_extruders && is_marlin_flavor) { if (existed_page < n_before_extruders && (is_marlin_flavor || from_initial_build)) {
auto page = build_kinematics_page(); auto page = build_kinematics_page();
#ifdef __WXMSW__ if (from_initial_build)
// layout_page(page); page->clear();
#endif else
m_pages.insert(m_pages.begin() + n_before_extruders, page); m_pages.insert(m_pages.begin() + n_before_extruders, page);
} }
if (is_marlin_flavor) if (is_marlin_flavor)
@ -2527,7 +2531,8 @@ void TabPrinter::build_unregular_pages()
} }
m_has_single_extruder_MM_page = false; m_has_single_extruder_MM_page = false;
} }
if (m_extruders_count > 1 && m_config->opt_bool("single_extruder_multi_material") && !m_has_single_extruder_MM_page) { if (from_initial_build ||
(m_extruders_count > 1 && m_config->opt_bool("single_extruder_multi_material") && !m_has_single_extruder_MM_page)) {
// create a page, but pretend it's an extruder page, so we can add it to m_pages ourselves // create a page, but pretend it's an extruder page, so we can add it to m_pages ourselves
auto page = add_options_page(L("Single extruder MM setup"), "printer", true); auto page = add_options_page(L("Single extruder MM setup"), "printer", true);
auto optgroup = page->new_optgroup(L("Single extruder multimaterial parameters")); auto optgroup = page->new_optgroup(L("Single extruder multimaterial parameters"));
@ -2536,8 +2541,12 @@ void TabPrinter::build_unregular_pages()
optgroup->append_single_option_line("parking_pos_retraction"); optgroup->append_single_option_line("parking_pos_retraction");
optgroup->append_single_option_line("extra_loading_move"); optgroup->append_single_option_line("extra_loading_move");
optgroup->append_single_option_line("high_current_on_filament_swap"); optgroup->append_single_option_line("high_current_on_filament_swap");
m_pages.insert(m_pages.end() - n_after_single_extruder_MM, page); if (from_initial_build)
m_has_single_extruder_MM_page = true; page->clear();
else {
m_pages.insert(m_pages.end() - n_after_single_extruder_MM, page);
m_has_single_extruder_MM_page = true;
}
} }
// Build missed extruder pages // Build missed extruder pages
@ -2642,10 +2651,6 @@ void TabPrinter::build_unregular_pages()
line = optgroup->create_single_option_line("extruder_colour", wxEmptyString, extruder_idx); line = optgroup->create_single_option_line("extruder_colour", wxEmptyString, extruder_idx);
line.append_widget(reset_to_filament_color); line.append_widget(reset_to_filament_color);
optgroup->append_line(line); optgroup->append_line(line);
#ifdef __WXMSW__
// layout_page(page);
#endif
} }
// # remove extra pages // # remove extra pages
@ -2656,6 +2661,10 @@ void TabPrinter::build_unregular_pages()
Thaw(); Thaw();
m_extruders_count_old = m_extruders_count; m_extruders_count_old = m_extruders_count;
if (m_printer_technology == ptSLA/*from_initial_build*/)
return; // next part of code is no needed to execute at this moment
rebuild_page_tree(); rebuild_page_tree();
// Reload preset pages with current configuration values // Reload preset pages with current configuration values
@ -3187,6 +3196,9 @@ void Tab::select_preset(std::string preset_name, bool delete_current /*=false*/,
load_current_preset(); load_current_preset();
} }
if (technology_changed)
wxGetApp().mainframe->diff_dialog.update_presets();
} }
// If the current preset is dirty, the user is asked whether the changes may be discarded. // If the current preset is dirty, the user is asked whether the changes may be discarded.
@ -3374,6 +3386,11 @@ void Tab::OnKeyDown(wxKeyEvent& event)
event.Skip(); event.Skip();
} }
void Tab::compare_preset()
{
wxGetApp().mainframe->diff_dialog.show(m_type);
}
// Save the current preset into file. // Save the current preset into file.
// This removes the "dirty" flag of the preset, possibly creates a new preset under a new name, // This removes the "dirty" flag of the preset, possibly creates a new preset under a new name,
// and activates the new preset. // and activates the new preset.
@ -3443,6 +3460,9 @@ void Tab::save_preset(std::string name /*= ""*/, bool detach)
for (Preset::Type preset_type : dependent) for (Preset::Type preset_type : dependent)
wxGetApp().get_tab(preset_type)->update_tab_ui(); wxGetApp().get_tab(preset_type)->update_tab_ui();
} }
// update preset comboboxes in DiffPresetDlg
wxGetApp().mainframe->diff_dialog.update_presets(m_type);
} }
// Called for a currently selected preset. // Called for a currently selected preset.

View File

@ -112,6 +112,7 @@ protected:
const wxString m_title; const wxString m_title;
TabPresetComboBox* m_presets_choice; TabPresetComboBox* m_presets_choice;
ScalableButton* m_search_btn; ScalableButton* m_search_btn;
ScalableButton* m_btn_compare_preset;
ScalableButton* m_btn_save_preset; ScalableButton* m_btn_save_preset;
ScalableButton* m_btn_delete_preset; ScalableButton* m_btn_delete_preset;
ScalableButton* m_btn_edit_ph_printer {nullptr}; ScalableButton* m_btn_edit_ph_printer {nullptr};
@ -290,6 +291,7 @@ public:
void OnTreeSelChange(wxTreeEvent& event); void OnTreeSelChange(wxTreeEvent& event);
void OnKeyDown(wxKeyEvent& event); void OnKeyDown(wxKeyEvent& event);
void compare_preset();
void save_preset(std::string name = std::string(), bool detach = false); void save_preset(std::string name = std::string(), bool detach = false);
void delete_preset(); void delete_preset();
void toggle_show_hide_incompatible(); void toggle_show_hide_incompatible();
@ -456,7 +458,7 @@ public:
void update_pages(); // update m_pages according to printer technology void update_pages(); // update m_pages according to printer technology
void extruders_count_changed(size_t extruders_count); void extruders_count_changed(size_t extruders_count);
PageShp build_kinematics_page(); PageShp build_kinematics_page();
void build_unregular_pages(); void build_unregular_pages(bool from_initial_build = false);
void on_preset_loaded() override; void on_preset_loaded() override;
void init_options_list() override; void init_options_list() override;
void msw_rescale() override; void msw_rescale() override;

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,7 @@
#include "GUI_Utils.hpp" #include "GUI_Utils.hpp"
#include "wxExtensions.hpp" #include "wxExtensions.hpp"
#include "libslic3r/Preset.hpp" #include "libslic3r/PresetBundle.hpp"
class ScalableButton; class ScalableButton;
class wxStaticText; class wxStaticText;
@ -16,10 +16,11 @@ namespace Slic3r {
namespace GUI{ namespace GUI{
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// ModelNode: a node inside UnsavedChangesModel // ModelNode: a node inside DiffModel
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
class ModelNode; class ModelNode;
class PresetComboBox;
using ModelNodePtrArray = std::vector<std::unique_ptr<ModelNode>>; using ModelNodePtrArray = std::vector<std::unique_ptr<ModelNode>>;
// On all of 3 different platforms Bitmap+Text icon column looks different // On all of 3 different platforms Bitmap+Text icon column looks different
@ -42,17 +43,6 @@ class ModelNode
wxString m_old_color; wxString m_old_color;
wxString m_new_color; wxString m_new_color;
// TODO/FIXME:
// the GTK version of wxDVC (in particular wxDataViewCtrlInternal::ItemAdded)
// needs to know in advance if a node is or _will be_ a container.
// Thus implementing:
// bool IsContainer() const
// { return m_children.size()>0; }
// doesn't work with wxGTK when UnsavedChangesModel::AddToClassical is called
// AND the classical node was removed (a new node temporary without children
// would be added to the control)
bool m_container {true};
#ifdef __linux__ #ifdef __linux__
wxIcon get_bitmap(const wxString& color); wxIcon get_bitmap(const wxString& color);
#else #else
@ -75,6 +65,17 @@ public:
wxString m_old_value; wxString m_old_value;
wxString m_new_value; wxString m_new_value;
// TODO/FIXME:
// the GTK version of wxDVC (in particular wxDataViewCtrlInternal::ItemAdded)
// needs to know in advance if a node is or _will be_ a container.
// Thus implementing:
// bool IsContainer() const
// { return m_children.size()>0; }
// doesn't work with wxGTK when DiffModel::AddToClassical is called
// AND the classical node was removed (a new node temporary without children
// would be added to the control)
bool m_container {true};
// preset(root) node // preset(root) node
ModelNode(Preset::Type preset_type, wxWindow* parent_win, const wxString& text, const std::string& icon_name); ModelNode(Preset::Type preset_type, wxWindow* parent_win, const wxString& text, const std::string& icon_name);
@ -107,13 +108,13 @@ public:
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// UnsavedChangesModel // DiffModel
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
class UnsavedChangesModel : public wxDataViewModel class DiffModel : public wxDataViewModel
{ {
wxWindow* m_parent_win { nullptr }; wxWindow* m_parent_win { nullptr };
std::vector<ModelNode*> m_preset_nodes; ModelNodePtrArray m_preset_nodes;
wxDataViewCtrl* m_ctrl{ nullptr }; wxDataViewCtrl* m_ctrl{ nullptr };
@ -143,8 +144,8 @@ public:
colMax colMax
}; };
UnsavedChangesModel(wxWindow* parent); DiffModel(wxWindow* parent);
~UnsavedChangesModel(); ~DiffModel() {}
void SetAssociatedControl(wxDataViewCtrl* ctrl) { m_ctrl = ctrl; } void SetAssociatedControl(wxDataViewCtrl* ctrl) { m_ctrl = ctrl; }
@ -159,6 +160,9 @@ public:
wxString GetColumnType(unsigned int col) const override; wxString GetColumnType(unsigned int col) const override;
void Rescale(); void Rescale();
wxDataViewItem Delete(const wxDataViewItem& item);
void Clear();
wxDataViewItem GetParent(const wxDataViewItem& item) const override; wxDataViewItem GetParent(const wxDataViewItem& item) const override;
unsigned int GetChildren(const wxDataViewItem& parent, wxDataViewItemArray& array) const override; unsigned int GetChildren(const wxDataViewItem& parent, wxDataViewItemArray& array) const override;
@ -173,14 +177,60 @@ public:
}; };
// ----------------------------------------------------------------------------
// DiffViewCtrl
// ----------------------------------------------------------------------------
class DiffViewCtrl : public wxDataViewCtrl
{
bool m_has_long_strings{ false };
bool m_empty_selection { false };
int m_em_unit;
struct ItemData
{
std::string opt_key;
wxString opt_name;
wxString old_val;
wxString new_val;
Preset::Type type;
bool is_long{ false };
};
// tree items related to the options
std::map<wxDataViewItem, ItemData> m_items_map;
std::map<unsigned int, int> m_columns_width;
public:
DiffViewCtrl(wxWindow* parent, wxSize size);
~DiffViewCtrl() {}
DiffModel* model{ nullptr };
void AppendBmpTextColumn(const wxString& label, unsigned model_column, int width, bool set_expander = false);
void AppendToggleColumn_(const wxString& label, unsigned model_column, int width);
void Rescale(int em = 0);
void Append(const std::string& opt_key, Preset::Type type, wxString category_name, wxString group_name, wxString option_name,
wxString old_value, wxString new_value, const std::string category_icon_name);
void Clear();
wxString get_short_string(wxString full_string);
bool has_selection() { return !m_empty_selection; }
void context_menu(wxDataViewEvent& event);
void item_value_changed(wxDataViewEvent& event);
void set_em_unit(int em) { m_em_unit = em; }
std::vector<std::string> unselected_options(Preset::Type type);
std::vector<std::string> selected_options();
};
//------------------------------------------ //------------------------------------------
// UnsavedChangesDialog // UnsavedChangesDialog
//------------------------------------------ //------------------------------------------
class UnsavedChangesDialog : public DPIDialog class UnsavedChangesDialog : public DPIDialog
{ {
wxDataViewCtrl* m_tree { nullptr }; DiffViewCtrl* m_tree { nullptr };
UnsavedChangesModel* m_tree_model { nullptr };
ScalableButton* m_save_btn { nullptr }; ScalableButton* m_save_btn { nullptr };
ScalableButton* m_transfer_btn { nullptr }; ScalableButton* m_transfer_btn { nullptr };
ScalableButton* m_discard_btn { nullptr }; ScalableButton* m_discard_btn { nullptr };
@ -188,7 +238,6 @@ class UnsavedChangesDialog : public DPIDialog
wxStaticText* m_info_line { nullptr }; wxStaticText* m_info_line { nullptr };
wxCheckBox* m_remember_choice { nullptr }; wxCheckBox* m_remember_choice { nullptr };
bool m_empty_selection { false };
bool m_has_long_strings { false }; bool m_has_long_strings { false };
int m_save_btn_id { wxID_ANY }; int m_save_btn_id { wxID_ANY };
int m_move_btn_id { wxID_ANY }; int m_move_btn_id { wxID_ANY };
@ -209,19 +258,6 @@ class UnsavedChangesDialog : public DPIDialog
// selected action after Dialog closing // selected action after Dialog closing
Action m_exit_action {Action::Undef}; Action m_exit_action {Action::Undef};
struct ItemData
{
std::string opt_key;
wxString opt_name;
wxString old_val;
wxString new_val;
Preset::Type type;
bool is_long {false};
};
// tree items related to the options
std::map<wxDataViewItem, ItemData> m_items_map;
// preset names which are modified in SavePresetDialog and related types // preset names which are modified in SavePresetDialog and related types
std::vector<std::pair<std::string, Preset::Type>> names_and_types; std::vector<std::pair<std::string, Preset::Type>> names_and_types;
@ -230,13 +266,9 @@ public:
UnsavedChangesDialog(Preset::Type type, PresetCollection* dependent_presets, const std::string& new_selected_preset); UnsavedChangesDialog(Preset::Type type, PresetCollection* dependent_presets, const std::string& new_selected_preset);
~UnsavedChangesDialog() {} ~UnsavedChangesDialog() {}
wxString get_short_string(wxString full_string);
void build(Preset::Type type, PresetCollection* dependent_presets, const std::string& new_selected_preset, const wxString& header = ""); void build(Preset::Type type, PresetCollection* dependent_presets, const std::string& new_selected_preset, const wxString& header = "");
void update(Preset::Type type, PresetCollection* dependent_presets, const std::string& new_selected_preset, const wxString& header); void update(Preset::Type type, PresetCollection* dependent_presets, const std::string& new_selected_preset, const wxString& header);
void update_tree(Preset::Type type, PresetCollection *presets); void update_tree(Preset::Type type, PresetCollection *presets);
void item_value_changed(wxDataViewEvent &event);
void context_menu(wxDataViewEvent &event);
void show_info_line(Action action, std::string preset_name = ""); void show_info_line(Action action, std::string preset_name = "");
void update_config(Action action); void update_config(Action action);
void close(Action action); void close(Action action);
@ -251,8 +283,8 @@ public:
// short version of the previous function, for the case, when just one preset is modified // short version of the previous function, for the case, when just one preset is modified
std::string get_preset_name() { return names_and_types[0].first; } std::string get_preset_name() { return names_and_types[0].first; }
std::vector<std::string> get_unselected_options(Preset::Type type); std::vector<std::string> get_unselected_options(Preset::Type type) { return m_tree->unselected_options(type); }
std::vector<std::string> get_selected_options(); std::vector<std::string> get_selected_options() { return m_tree->selected_options(); }
protected: protected:
void on_dpi_changed(const wxRect& suggested_rect) override; void on_dpi_changed(const wxRect& suggested_rect) override;
@ -270,6 +302,48 @@ public:
~FullCompareDialog() {} ~FullCompareDialog() {}
}; };
//------------------------------------------
// DiffPresetDialog
//------------------------------------------
class DiffPresetDialog : public DPIDialog
{
DiffViewCtrl* m_tree { nullptr };
wxStaticText* m_top_info_line { nullptr };
wxStaticText* m_bottom_info_line { nullptr };
wxCheckBox* m_show_all_presets { nullptr };
Preset::Type m_view_type { Preset::TYPE_INVALID };
PrinterTechnology m_pr_technology;
std::unique_ptr<PresetBundle> m_preset_bundle_left;
std::unique_ptr<PresetBundle> m_preset_bundle_right;
void update_tree();
void update_bundles_from_app();
void update_controls_visibility(Preset::Type type = Preset::TYPE_INVALID);
void update_compatibility(const std::string& preset_name, Preset::Type type, PresetBundle* preset_bundle);
struct DiffPresets
{
PresetComboBox* presets_left { nullptr };
ScalableButton* equal_bmp { nullptr };
PresetComboBox* presets_right { nullptr };
};
std::vector<DiffPresets> m_preset_combos;
public:
DiffPresetDialog();
~DiffPresetDialog() {}
void show(Preset::Type type = Preset::TYPE_INVALID);
void update_presets(Preset::Type type = Preset::TYPE_INVALID);
protected:
void on_dpi_changed(const wxRect& suggested_rect) override;
void on_sys_color_changed() override;
};
} }
} }