ConfigWizard refactoring

This commit is contained in:
Vojtech Kral 2019-02-07 20:50:34 +01:00
parent ee4ba72071
commit 392a3b9cb0
10 changed files with 1126 additions and 811 deletions

View File

@ -5,6 +5,7 @@
#include <queue>
#include <string>
#include <vector>
#include <boost/core/noncopyable.hpp>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>

View File

@ -5,6 +5,8 @@
#include "libslic3r.h"
namespace boost { namespace filesystem { class directory_entry; }}
namespace Slic3r {
extern void set_logging_level(unsigned int level);
@ -49,6 +51,12 @@ extern std::string normalize_utf8_nfc(const char *src);
// for a short while, so the file may not be movable. Retry while we see recoverable errors.
extern int rename_file(const std::string &from, const std::string &to);
// Ignore system and hidden files, which may be created by the DropBox synchronisation process.
// https://github.com/prusa3d/Slic3r/issues/1298
extern bool is_plain_file(const boost::filesystem::directory_entry &path);
extern bool is_ini_file(const boost::filesystem::directory_entry &path);
extern bool is_idx_file(const boost::filesystem::directory_entry &path);
// File path / name / extension splitting utilities, working with UTF-8,
// to be published to Perl.
namespace PerlUtils {

View File

@ -212,6 +212,30 @@ int rename_file(const std::string &from, const std::string &to)
return ec;
}
// Ignore system and hidden files, which may be created by the DropBox synchronisation process.
// https://github.com/prusa3d/Slic3r/issues/1298
bool is_plain_file(const boost::filesystem::directory_entry &dir_entry)
{
if (! boost::filesystem::is_regular_file(dir_entry.status()))
return false;
#ifdef _MSC_VER
DWORD attributes = GetFileAttributesW(boost::nowide::widen(dir_entry.path().string()).c_str());
return (attributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) == 0;
#else
return true;
#endif
}
bool is_ini_file(const boost::filesystem::directory_entry &dir_entry)
{
return is_plain_file(dir_entry) && strcasecmp(dir_entry.path().extension().string().c_str(), ".ini") == 0;
}
bool is_idx_file(const boost::filesystem::directory_entry &dir_entry)
{
return is_plain_file(dir_entry) && strcasecmp(dir_entry.path().extension().string().c_str(), ".idx") == 0;
}
} // namespace Slic3r
#include <xsinit.h>

File diff suppressed because it is too large Load Diff

View File

@ -16,30 +16,30 @@ namespace GUI {
class ConfigWizard: public wxDialog
{
public:
// Why is the Wizard run
enum RunReason {
RR_DATA_EMPTY, // No or empty datadir
RR_DATA_LEGACY, // Pre-updating datadir
RR_DATA_INCOMPAT, // Incompatible datadir - Slic3r downgrade situation
RR_USER, // User requested the Wizard from the menus
};
// Why is the Wizard run
enum RunReason {
RR_DATA_EMPTY, // No or empty datadir
RR_DATA_LEGACY, // Pre-updating datadir
RR_DATA_INCOMPAT, // Incompatible datadir - Slic3r downgrade situation
RR_USER, // User requested the Wizard from the menus
};
ConfigWizard(wxWindow *parent, RunReason run_reason);
ConfigWizard(ConfigWizard &&) = delete;
ConfigWizard(const ConfigWizard &) = delete;
ConfigWizard &operator=(ConfigWizard &&) = delete;
ConfigWizard &operator=(const ConfigWizard &) = delete;
~ConfigWizard();
ConfigWizard(wxWindow *parent, RunReason run_reason);
ConfigWizard(ConfigWizard &&) = delete;
ConfigWizard(const ConfigWizard &) = delete;
ConfigWizard &operator=(ConfigWizard &&) = delete;
ConfigWizard &operator=(const ConfigWizard &) = delete;
~ConfigWizard();
// Run the Wizard. Return whether it was completed.
bool run(PresetBundle *preset_bundle, const PresetUpdater *updater);
// Run the Wizard. Return whether it was completed.
bool run(PresetBundle *preset_bundle, const PresetUpdater *updater);
static const wxString& name();
static const wxString& name(const bool from_menu = false);
private:
struct priv;
std::unique_ptr<priv> p;
struct priv;
std::unique_ptr<priv> p;
friend class ConfigWizardPage;
friend struct ConfigWizardPage;
};

View File

@ -6,6 +6,7 @@
#include <vector>
#include <set>
#include <unordered_map>
#include <functional>
#include <boost/filesystem.hpp>
#include <wx/sizer.h>
@ -13,9 +14,11 @@
#include <wx/button.h>
#include <wx/choice.h>
#include <wx/spinctrl.h>
#include <wx/textctrl.h>
#include "libslic3r/PrintConfig.hpp"
#include "slic3r/Utils/PresetUpdater.hpp"
#include "GUI.hpp"
#include "AppConfig.hpp"
#include "Preset.hpp"
#include "BedShapeDialog.hpp"
@ -26,211 +29,261 @@ namespace Slic3r {
namespace GUI {
enum {
WRAP_WIDTH = 500,
MODEL_MIN_WRAP = 150,
WRAP_WIDTH = 500,
MODEL_MIN_WRAP = 150,
DIALOG_MARGIN = 15,
INDEX_MARGIN = 40,
BTN_SPACING = 10,
INDENT_SPACING = 30,
VERTICAL_SPACING = 10,
DIALOG_MARGIN = 15,
INDEX_MARGIN = 40,
BTN_SPACING = 10,
INDENT_SPACING = 30,
VERTICAL_SPACING = 10,
MAX_COLS = 4,
ROW_SPACING = 75,
};
typedef std::function<bool(const VendorProfile::PrinterModel&)> ModelFilter;
struct PrinterPicker: wxPanel
{
struct Checkbox : wxCheckBox
{
Checkbox(wxWindow *parent, const wxString &label, const std::string &model, const std::string &variant) :
wxCheckBox(parent, wxID_ANY, label),
model(model),
variant(variant)
{}
struct Checkbox : wxCheckBox
{
Checkbox(wxWindow *parent, const wxString &label, const std::string &model, const std::string &variant) :
wxCheckBox(parent, wxID_ANY, label),
model(model),
variant(variant)
{}
std::string model;
std::string variant;
};
std::string model;
std::string variant;
};
const std::string vendor_id;
std::vector<Checkbox*> cboxes;
unsigned variants_checked;
const std::string vendor_id;
std::vector<Checkbox*> cboxes;
std::vector<Checkbox*> cboxes_alt;
PrinterPicker(wxWindow *parent, const VendorProfile &vendor, const AppConfig &appconfig_vendors);
PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxString title, size_t max_cols, const AppConfig &appconfig_vendors, const ModelFilter &filter);
PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxString title, size_t max_cols, const AppConfig &appconfig_vendors);
void select_all(bool select);
void select_one(size_t i, bool select);
void on_checkbox(const Checkbox *cbox, bool checked);
void select_all(bool select);
void select_one(size_t i, bool select);
void on_checkbox(const Checkbox *cbox, bool checked);
};
struct ConfigWizardPage: wxPanel
{
ConfigWizard *parent;
const wxString shortname;
wxBoxSizer *content;
ConfigWizard *parent;
const wxString shortname;
wxBoxSizer *content;
const unsigned indent;
ConfigWizardPage(ConfigWizard *parent, wxString title, wxString shortname);
ConfigWizardPage(ConfigWizard *parent, wxString title, wxString shortname, unsigned indent = 0);
virtual ~ConfigWizardPage();
virtual ~ConfigWizardPage();
template<class T>
void append(T *thing, int proportion = 0, int flag = wxEXPAND|wxTOP|wxBOTTOM, int border = 10)
{
content->Add(thing, proportion, flag, border);
}
ConfigWizardPage* page_prev() const { return p_prev; }
ConfigWizardPage* page_next() const { return p_next; }
ConfigWizardPage* chain(ConfigWizardPage *page);
void append_text(wxString text);
void append_spacer(int space);
template<class T>
void append(T *thing, int proportion = 0, int flag = wxEXPAND|wxTOP|wxBOTTOM, int border = 10)
{
content->Add(thing, proportion, flag, border);
}
ConfigWizard::priv *wizard_p() const { return parent->p.get(); }
void append_text(wxString text);
void append_spacer(int space);
ConfigWizard::priv *wizard_p() const { return parent->p.get(); }
virtual bool Show(bool show = true);
virtual bool Hide() { return Show(false); }
virtual wxPanel* extra_buttons() { return nullptr; }
virtual void on_page_set() {}
virtual void apply_custom_config(DynamicPrintConfig &config) {}
void enable_next(bool enable);
private:
ConfigWizardPage *p_prev;
ConfigWizardPage *p_next;
virtual void apply_custom_config(DynamicPrintConfig &config) {}
};
struct PageWelcome: ConfigWizardPage
{
PrinterPicker *printer_picker;
wxPanel *others_buttons;
wxCheckBox *cbox_reset;
wxCheckBox *cbox_reset;
PageWelcome(ConfigWizard *parent, bool check_first_variant);
PageWelcome(ConfigWizard *parent);
virtual wxPanel* extra_buttons() { return others_buttons; }
virtual void on_page_set();
bool reset_user_profile() const { return cbox_reset != nullptr ? cbox_reset->GetValue() : false; }
};
bool reset_user_profile() const { return cbox_reset != nullptr ? cbox_reset->GetValue() : false; }
void on_variant_checked();
struct PagePrinters: ConfigWizardPage
{
std::vector<PrinterPicker *> printer_pickers;
PagePrinters(ConfigWizard *parent, wxString title, wxString shortname, const VendorProfile &vendor, unsigned indent);
void select_all(bool select);
};
struct PageCustom: ConfigWizardPage
{
PageCustom(ConfigWizard *parent);
bool custom_wanted() const { return cb_custom->GetValue(); }
std::string profile_name() const { return into_u8(tc_profile_name->GetValue()); }
private:
static const char* default_profile_name;
wxCheckBox *cb_custom;
wxTextCtrl *tc_profile_name;
wxString profile_name_prev;
};
struct PageUpdate: ConfigWizardPage
{
bool version_check;
bool preset_update;
bool version_check;
bool preset_update;
PageUpdate(ConfigWizard *parent);
PageUpdate(ConfigWizard *parent);
};
struct PageVendors: ConfigWizardPage
{
std::vector<PrinterPicker*> pickers;
std::vector<PrinterPicker*> pickers;
PageVendors(ConfigWizard *parent);
PageVendors(ConfigWizard *parent);
virtual void on_page_set();
void on_vendor_pick(size_t i);
void on_variant_checked();
void on_vendor_pick(size_t i);
};
struct PageFirmware: ConfigWizardPage
{
const ConfigOptionDef &gcode_opt;
wxChoice *gcode_picker;
const ConfigOptionDef &gcode_opt;
wxChoice *gcode_picker;
PageFirmware(ConfigWizard *parent);
virtual void apply_custom_config(DynamicPrintConfig &config);
PageFirmware(ConfigWizard *parent);
virtual void apply_custom_config(DynamicPrintConfig &config);
};
struct PageBedShape: ConfigWizardPage
{
BedShapePanel *shape_panel;
BedShapePanel *shape_panel;
PageBedShape(ConfigWizard *parent);
virtual void apply_custom_config(DynamicPrintConfig &config);
PageBedShape(ConfigWizard *parent);
virtual void apply_custom_config(DynamicPrintConfig &config);
};
struct PageDiameters: ConfigWizardPage
{
wxSpinCtrlDouble *spin_nozzle;
wxSpinCtrlDouble *spin_filam;
wxSpinCtrlDouble *spin_nozzle;
wxSpinCtrlDouble *spin_filam;
PageDiameters(ConfigWizard *parent);
virtual void apply_custom_config(DynamicPrintConfig &config);
PageDiameters(ConfigWizard *parent);
virtual void apply_custom_config(DynamicPrintConfig &config);
};
struct PageTemperatures: ConfigWizardPage
{
wxSpinCtrlDouble *spin_extr;
wxSpinCtrlDouble *spin_bed;
wxSpinCtrlDouble *spin_extr;
wxSpinCtrlDouble *spin_bed;
PageTemperatures(ConfigWizard *parent);
virtual void apply_custom_config(DynamicPrintConfig &config);
PageTemperatures(ConfigWizard *parent);
virtual void apply_custom_config(DynamicPrintConfig &config);
};
class ConfigWizardIndex: public wxPanel
{
public:
ConfigWizardIndex(wxWindow *parent);
ConfigWizardIndex(wxWindow *parent);
void load_items(ConfigWizardPage *firstpage);
void set_active(ConfigWizardPage *page);
void add_page(ConfigWizardPage *page);
void add_label(wxString label, unsigned indent = 0);
size_t active_item() const { return item_active; }
ConfigWizardPage* active_page() const;
bool active_is_last() const { return item_active < items.size() && item_active == last_page; }
void go_prev();
void go_next();
void go_to(size_t i);
void go_to(ConfigWizardPage *page);
void clear();
// XXX
// void load_items(ConfigWizardPage *firstpage);
// void set_active(ConfigWizardPage *page);
private:
const wxBitmap bg;
const wxBitmap bullet_black;
const wxBitmap bullet_blue;
const wxBitmap bullet_white;
int text_height;
// enum {
// // Units in em
// MARGIN = 1,
// SPACING = 1,
// };
std::vector<wxString> items;
std::vector<wxString>::const_iterator item_active;
struct Item
{
wxString label;
unsigned indent;
ConfigWizardPage *page; // nullptr page => label-only item
void on_paint(wxPaintEvent &evt);
// bool operator==(const wxString &label) const { return this->label == label; }
bool operator==(ConfigWizardPage *page) const { return this->page == page; }
};
int em;
int em_h;
const wxBitmap bg;
const wxBitmap bullet_black;
const wxBitmap bullet_blue;
const wxBitmap bullet_white;
std::vector<Item> items;
// std::vector<Item>::const_iterator item_active;
size_t item_active;
ssize_t item_hover;
size_t last_page;
int item_height() const { return std::max(bullet_black.GetSize().GetHeight(), em) + em; }
void on_paint(wxPaintEvent &evt);
void on_mouse_move(wxMouseEvent &evt);
};
wxDEFINE_EVENT(EVT_INDEX_PAGE, wxCommandEvent);
struct ConfigWizard::priv
{
ConfigWizard *q;
ConfigWizard::RunReason run_reason;
AppConfig appconfig_vendors;
std::unordered_map<std::string, VendorProfile> vendors;
std::unordered_map<std::string, std::string> vendors_rsrc;
std::unique_ptr<DynamicPrintConfig> custom_config;
ConfigWizard *q;
ConfigWizard::RunReason run_reason;
AppConfig appconfig_vendors;
std::unordered_map<std::string, VendorProfile> vendors;
std::unordered_map<std::string, std::string> vendors_rsrc;
std::unique_ptr<DynamicPrintConfig> custom_config;
wxScrolledWindow *hscroll = nullptr;
wxBoxSizer *hscroll_sizer = nullptr;
wxBoxSizer *btnsizer = nullptr;
ConfigWizardPage *page_current = nullptr;
ConfigWizardIndex *index = nullptr;
wxButton *btn_prev = nullptr;
wxButton *btn_next = nullptr;
wxButton *btn_finish = nullptr;
wxButton *btn_cancel = nullptr;
wxScrolledWindow *hscroll = nullptr;
wxBoxSizer *hscroll_sizer = nullptr;
wxBoxSizer *btnsizer = nullptr;
ConfigWizardPage *page_current = nullptr;
ConfigWizardIndex *index = nullptr;
wxButton *btn_prev = nullptr;
wxButton *btn_next = nullptr;
wxButton *btn_finish = nullptr;
wxButton *btn_cancel = nullptr;
PageWelcome *page_welcome = nullptr;
PageUpdate *page_update = nullptr;
PageVendors *page_vendors = nullptr;
PageFirmware *page_firmware = nullptr;
PageBedShape *page_bed = nullptr;
PageDiameters *page_diams = nullptr;
PageTemperatures *page_temps = nullptr;
PageWelcome *page_welcome = nullptr;
PagePrinters *page_fff = nullptr;
PageCustom *page_custom = nullptr;
PageUpdate *page_update = nullptr;
PageVendors *page_vendors = nullptr; // XXX: ?
priv(ConfigWizard *q) : q(q) {}
// Custom setup pages
PageFirmware *page_firmware = nullptr;
PageBedShape *page_bed = nullptr;
PageDiameters *page_diams = nullptr;
PageTemperatures *page_temps = nullptr;
void load_vendors();
void add_page(ConfigWizardPage *page);
void index_refresh();
void set_page(ConfigWizardPage *page);
void layout_fit();
void go_prev() { if (page_current != nullptr) { set_page(page_current->page_prev()); } }
void go_next() { if (page_current != nullptr) { set_page(page_current->page_next()); } }
void enable_next(bool enable);
priv(ConfigWizard *q) : q(q) {}
void on_other_vendors();
void on_custom_setup();
void load_pages(bool custom_setup);
void apply_config(AppConfig *app_config, PresetBundle *preset_bundle, const PresetUpdater *updater);
bool check_first_variant() const;
void load_vendors();
void add_page(ConfigWizardPage *page);
void enable_next(bool enable);
void on_custom_setup(bool custom_wanted);
void apply_config(AppConfig *app_config, PresetBundle *preset_bundle, const PresetUpdater *updater);
};

View File

@ -794,6 +794,12 @@ wxString from_u8(const std::string &str)
return wxString::FromUTF8(str.c_str());
}
std::string into_u8(const wxString &str)
{
auto buffer_utf8 = str.utf8_str();
return std::string(buffer_utf8.data());
}
void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFlexGridSizer* preset_sizer)
{
@ -1034,6 +1040,21 @@ void restore_window_size(wxTopLevelWindow *window, const std::string &name)
}
}
void on_window_geometry(wxTopLevelWindow *tlw, std::function<void()> callback)
{
tlw->Bind(wxEVT_CREATE, [=](wxWindowCreateEvent &event) {
#ifdef __linux__
// On Linux, the geometry is only available after wxEVT_CREATE + CallAfter
// cf. https://groups.google.com/forum/?pli=1#!topic/wx-users/fERSXdpVwAI
tlw->CallAfter([=]() {
#endif
callback();
#ifdef __linux__
});
#endif
event.Skip();
});
}
void about()
{

View File

@ -169,7 +169,8 @@ int combochecklist_get_flags(wxComboCtrl* comboCtrl);
wxString L_str(const std::string &str);
// Return wxString from std::string in UTF8
wxString from_u8(const std::string &str);
// std::string in UTF8 from wxString
std::string into_u8(const wxString &str);
void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFlexGridSizer* preset_sizer);
@ -190,6 +191,8 @@ void save_window_size(wxTopLevelWindow *window, const std::string &name);
// Restore the above
void restore_window_size(wxTopLevelWindow *window, const std::string &name);
void on_window_geometry(wxTopLevelWindow *tlw, std::function<void()> callback);
// Display an About dialog
extern void about();
// Ask the destop to open the datadir using the default file explorer.

View File

@ -5,6 +5,7 @@
#include "AppConfig.hpp"
#include "BitmapCache.hpp"
#include <algorithm>
#include <fstream>
#include <stdexcept>
#include <boost/format.hpp>
@ -139,6 +140,20 @@ VendorProfile VendorProfile::from_ini(const ptree &tree, const boost::filesystem
return res;
}
std::vector<std::string> VendorProfile::families() const
{
std::vector<std::string> res;
unsigned num_familiies = 0;
for (auto &model : models) {
if (std::find(res.begin(), res.end(), model.family) == res.end()) {
res.push_back(model.family);
num_familiies++;
}
}
return res;
}
// Suffix to be added to a modified preset name in the combo box.
static std::string g_suffix_modified = " (modified)";

View File

@ -52,6 +52,7 @@ public:
PrinterModel() {}
std::string id;
std::string name;
std::string family;
std::vector<PrinterVariant> variants;
PrinterVariant* variant(const std::string &name) {
for (auto &v : this->variants)
@ -70,6 +71,7 @@ public:
static VendorProfile from_ini(const boost::property_tree::ptree &tree, const boost::filesystem::path &path, bool load_all=true);
size_t num_variants() const { size_t n = 0; for (auto &model : models) n += model.variants.size(); return n; }
std::vector<std::string> families() const;
bool operator< (const VendorProfile &rhs) const { return this->id < rhs.id; }
bool operator==(const VendorProfile &rhs) const { return this->id == rhs.id; }