mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
Allow options to be selected in the GUI.
This commit is contained in:
48
lib/flags.cc
48
lib/flags.cc
@@ -55,31 +55,39 @@ static bool setFallbackFlag(
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const auto& configs : config.option())
|
||||
{
|
||||
if (path == configs.name())
|
||||
{
|
||||
if (configs.config().option_size() > 0)
|
||||
Error() << fmt::format(
|
||||
"option '{}' has an option inside it, which isn't "
|
||||
"allowed",
|
||||
path);
|
||||
if (configs.config().include_size() > 0)
|
||||
Error() << fmt::format(
|
||||
"option '{}' is trying to include something, which "
|
||||
"isn't allowed",
|
||||
path);
|
||||
|
||||
Logger() << fmt::format("OPTION: {}", configs.message());
|
||||
config.MergeFrom(configs.config());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (FlagGroup::applyOption(path))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Error() << "unrecognised flag; try --help";
|
||||
}
|
||||
|
||||
bool FlagGroup::applyOption(const std::string& option)
|
||||
{
|
||||
for (const auto& configs : config.option())
|
||||
{
|
||||
if (option == configs.name())
|
||||
{
|
||||
if (configs.config().option_size() > 0)
|
||||
Error() << fmt::format(
|
||||
"option '{}' has an option inside it, which isn't "
|
||||
"allowed",
|
||||
option);
|
||||
if (configs.config().include_size() > 0)
|
||||
Error() << fmt::format(
|
||||
"option '{}' is trying to include something, which "
|
||||
"isn't allowed",
|
||||
option);
|
||||
|
||||
Logger() << fmt::format("OPTION: {}", configs.message());
|
||||
config.MergeFrom(configs.config());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::string> FlagGroup::parseFlagsWithFilenames(int argc,
|
||||
const char* argv[],
|
||||
std::function<bool(const std::string&)> callback)
|
||||
|
||||
272
lib/flags.h
272
lib/flags.h
@@ -12,21 +12,42 @@ public:
|
||||
FlagGroup(std::initializer_list<FlagGroup*> groups);
|
||||
|
||||
public:
|
||||
void parseFlags(int argc, const char* argv[],
|
||||
std::function<bool(const std::string&)> callback =
|
||||
[](const auto&){ return false; });
|
||||
void parseFlags(
|
||||
int argc,
|
||||
const char* argv[],
|
||||
std::function<bool(const std::string&)> callback =
|
||||
[](const auto&)
|
||||
{
|
||||
return false;
|
||||
});
|
||||
std::vector<std::string> parseFlagsWithFilenames(
|
||||
int argc, const char* argv[],
|
||||
std::function<bool(const std::string&)> callback =
|
||||
[](const auto&){ return false; });
|
||||
void parseFlagsWithConfigFiles(int argc, const char* argv[],
|
||||
const std::map<std::string, std::string>& configFiles);
|
||||
static ConfigProto parseSingleConfigFile(
|
||||
const std::string& filename,
|
||||
const std::map<std::string, std::string>& configFiles);
|
||||
static void parseConfigFile(
|
||||
const std::string& filename,
|
||||
const std::map<std::string, std::string>& configFiles);
|
||||
int argc,
|
||||
const char* argv[],
|
||||
std::function<bool(const std::string&)> callback =
|
||||
[](const auto&)
|
||||
{
|
||||
return false;
|
||||
});
|
||||
void parseFlagsWithConfigFiles(int argc,
|
||||
const char* argv[],
|
||||
const std::map<std::string, std::string>& configFiles);
|
||||
|
||||
/* Load one config file (or internal config file), without expanding
|
||||
* includes. */
|
||||
|
||||
static ConfigProto parseSingleConfigFile(const std::string& filename,
|
||||
const std::map<std::string, std::string>& configFiles);
|
||||
|
||||
/* Load a top-level config file (or internal config file), expanding
|
||||
* includes. */
|
||||
|
||||
static void parseConfigFile(const std::string& filename,
|
||||
const std::map<std::string, std::string>& configFiles);
|
||||
|
||||
/* Modify the current config to engage the named option. */
|
||||
|
||||
static bool applyOption(const std::string& option);
|
||||
|
||||
void addFlag(Flag* flag);
|
||||
void checkInitialised() const;
|
||||
|
||||
@@ -40,14 +61,25 @@ class Flag
|
||||
{
|
||||
public:
|
||||
Flag(const std::vector<std::string>& names, const std::string helptext);
|
||||
virtual ~Flag() {};
|
||||
virtual ~Flag(){};
|
||||
|
||||
void checkInitialised() const
|
||||
{ _group.checkInitialised(); }
|
||||
{
|
||||
_group.checkInitialised();
|
||||
}
|
||||
|
||||
const std::string& name() const { return _names[0]; }
|
||||
const std::vector<std::string> names() const { return _names; }
|
||||
const std::string& helptext() const { return _helptext; }
|
||||
const std::string& name() const
|
||||
{
|
||||
return _names[0];
|
||||
}
|
||||
const std::vector<std::string> names() const
|
||||
{
|
||||
return _names;
|
||||
}
|
||||
const std::string& helptext() const
|
||||
{
|
||||
return _helptext;
|
||||
}
|
||||
|
||||
virtual bool hasArgument() const = 0;
|
||||
virtual const std::string defaultValueAsString() const = 0;
|
||||
@@ -62,15 +94,26 @@ private:
|
||||
class ActionFlag : Flag
|
||||
{
|
||||
public:
|
||||
ActionFlag(const std::vector<std::string>& names, const std::string helptext,
|
||||
std::function<void(void)> callback):
|
||||
ActionFlag(const std::vector<std::string>& names,
|
||||
const std::string helptext,
|
||||
std::function<void(void)> callback):
|
||||
Flag(names, helptext),
|
||||
_callback(callback)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
bool hasArgument() const { return false; }
|
||||
const std::string defaultValueAsString() const { return ""; }
|
||||
void set(const std::string& value) { _callback(); }
|
||||
bool hasArgument() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
const std::string defaultValueAsString() const
|
||||
{
|
||||
return "";
|
||||
}
|
||||
void set(const std::string& value)
|
||||
{
|
||||
_callback();
|
||||
}
|
||||
|
||||
private:
|
||||
const std::function<void(void)> _callback;
|
||||
@@ -79,16 +122,30 @@ private:
|
||||
class SettableFlag : public Flag
|
||||
{
|
||||
public:
|
||||
SettableFlag(const std::vector<std::string>& names, const std::string helptext):
|
||||
SettableFlag(
|
||||
const std::vector<std::string>& names, const std::string helptext):
|
||||
Flag(names, helptext)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{ checkInitialised(); return _value; }
|
||||
{
|
||||
checkInitialised();
|
||||
return _value;
|
||||
}
|
||||
|
||||
bool hasArgument() const { return false; }
|
||||
const std::string defaultValueAsString() const { return "false"; }
|
||||
void set(const std::string& value) { _value = true; }
|
||||
bool hasArgument() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
const std::string defaultValueAsString() const
|
||||
{
|
||||
return "false";
|
||||
}
|
||||
void set(const std::string& value)
|
||||
{
|
||||
_value = true;
|
||||
}
|
||||
|
||||
private:
|
||||
bool _value = false;
|
||||
@@ -98,72 +155,122 @@ template <typename T>
|
||||
class ValueFlag : public Flag
|
||||
{
|
||||
public:
|
||||
ValueFlag(const std::vector<std::string>& names, const std::string helptext,
|
||||
const T defaultValue,
|
||||
std::function<void(const T&)> callback = [](const T&) {}):
|
||||
ValueFlag(
|
||||
const std::vector<std::string>& names,
|
||||
const std::string helptext,
|
||||
const T defaultValue,
|
||||
std::function<void(const T&)> callback =
|
||||
[](const T&)
|
||||
{
|
||||
}):
|
||||
Flag(names, helptext),
|
||||
_defaultValue(defaultValue),
|
||||
_value(defaultValue),
|
||||
_callback(callback)
|
||||
{}
|
||||
_callback(callback)
|
||||
{
|
||||
}
|
||||
|
||||
const T& get() const
|
||||
{ checkInitialised(); return _value; }
|
||||
{
|
||||
checkInitialised();
|
||||
return _value;
|
||||
}
|
||||
|
||||
operator const T& () const
|
||||
{ return get(); }
|
||||
operator const T&() const
|
||||
{
|
||||
return get();
|
||||
}
|
||||
|
||||
bool isSet() const
|
||||
{ return _isSet; }
|
||||
bool isSet() const
|
||||
{
|
||||
return _isSet;
|
||||
}
|
||||
|
||||
void setDefaultValue(T value)
|
||||
{
|
||||
_value = _defaultValue = value;
|
||||
}
|
||||
|
||||
bool hasArgument() const { return true; }
|
||||
bool hasArgument() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
T _defaultValue;
|
||||
T _value;
|
||||
bool _isSet = false;
|
||||
std::function<void(const T&)> _callback;
|
||||
bool _isSet = false;
|
||||
std::function<void(const T&)> _callback;
|
||||
};
|
||||
|
||||
class StringFlag : public ValueFlag<std::string>
|
||||
{
|
||||
public:
|
||||
StringFlag(const std::vector<std::string>& names, const std::string helptext,
|
||||
const std::string defaultValue = "",
|
||||
std::function<void(const std::string&)> callback = [](const std::string&) {}):
|
||||
StringFlag(
|
||||
const std::vector<std::string>& names,
|
||||
const std::string helptext,
|
||||
const std::string defaultValue = "",
|
||||
std::function<void(const std::string&)> callback =
|
||||
[](const std::string&)
|
||||
{
|
||||
}):
|
||||
ValueFlag(names, helptext, defaultValue, callback)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
const std::string defaultValueAsString() const { return _defaultValue; }
|
||||
void set(const std::string& value) { _value = value; _callback(_value); _isSet = true; }
|
||||
const std::string defaultValueAsString() const
|
||||
{
|
||||
return _defaultValue;
|
||||
}
|
||||
void set(const std::string& value)
|
||||
{
|
||||
_value = value;
|
||||
_callback(_value);
|
||||
_isSet = true;
|
||||
}
|
||||
};
|
||||
|
||||
class IntFlag : public ValueFlag<int>
|
||||
{
|
||||
public:
|
||||
IntFlag(const std::vector<std::string>& names, const std::string helptext,
|
||||
int defaultValue = 0,
|
||||
std::function<void(const int&)> callback = [](const int&) {}):
|
||||
IntFlag(
|
||||
const std::vector<std::string>& names,
|
||||
const std::string helptext,
|
||||
int defaultValue = 0,
|
||||
std::function<void(const int&)> callback =
|
||||
[](const int&)
|
||||
{
|
||||
}):
|
||||
ValueFlag(names, helptext, defaultValue, callback)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
const std::string defaultValueAsString() const { return std::to_string(_defaultValue); }
|
||||
void set(const std::string& value) { _value = std::stoi(value); _callback(_value); _isSet = true; }
|
||||
const std::string defaultValueAsString() const
|
||||
{
|
||||
return std::to_string(_defaultValue);
|
||||
}
|
||||
void set(const std::string& value)
|
||||
{
|
||||
_value = std::stoi(value);
|
||||
_callback(_value);
|
||||
_isSet = true;
|
||||
}
|
||||
};
|
||||
|
||||
class HexIntFlag : public IntFlag
|
||||
{
|
||||
public:
|
||||
HexIntFlag(const std::vector<std::string>& names, const std::string helptext,
|
||||
int defaultValue = 0,
|
||||
std::function<void(const int&)> callback = [](const int&) {}):
|
||||
HexIntFlag(
|
||||
const std::vector<std::string>& names,
|
||||
const std::string helptext,
|
||||
int defaultValue = 0,
|
||||
std::function<void(const int&)> callback =
|
||||
[](const int&)
|
||||
{
|
||||
}):
|
||||
IntFlag(names, helptext, defaultValue, callback)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
const std::string defaultValueAsString() const;
|
||||
};
|
||||
@@ -171,26 +278,49 @@ public:
|
||||
class DoubleFlag : public ValueFlag<double>
|
||||
{
|
||||
public:
|
||||
DoubleFlag(const std::vector<std::string>& names, const std::string helptext,
|
||||
double defaultValue = 1.0,
|
||||
std::function<void(const double&)> callback = [](const double&) {}):
|
||||
DoubleFlag(
|
||||
const std::vector<std::string>& names,
|
||||
const std::string helptext,
|
||||
double defaultValue = 1.0,
|
||||
std::function<void(const double&)> callback =
|
||||
[](const double&)
|
||||
{
|
||||
}):
|
||||
ValueFlag(names, helptext, defaultValue, callback)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
const std::string defaultValueAsString() const { return std::to_string(_defaultValue); }
|
||||
void set(const std::string& value) { _value = std::stod(value); _callback(_value); _isSet = true; }
|
||||
const std::string defaultValueAsString() const
|
||||
{
|
||||
return std::to_string(_defaultValue);
|
||||
}
|
||||
void set(const std::string& value)
|
||||
{
|
||||
_value = std::stod(value);
|
||||
_callback(_value);
|
||||
_isSet = true;
|
||||
}
|
||||
};
|
||||
|
||||
class BoolFlag : public ValueFlag<bool>
|
||||
{
|
||||
public:
|
||||
BoolFlag(const std::vector<std::string>& names, const std::string helptext,
|
||||
bool defaultValue = false,
|
||||
std::function<void(const bool&)> callback = [](const bool&) {}):
|
||||
BoolFlag(
|
||||
const std::vector<std::string>& names,
|
||||
const std::string helptext,
|
||||
bool defaultValue = false,
|
||||
std::function<void(const bool&)> callback =
|
||||
[](const bool&)
|
||||
{
|
||||
}):
|
||||
ValueFlag(names, helptext, defaultValue, callback)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
const std::string defaultValueAsString() const { return _defaultValue ? "true" : "false"; }
|
||||
const std::string defaultValueAsString() const
|
||||
{
|
||||
return _defaultValue ? "true" : "false";
|
||||
}
|
||||
void set(const std::string& value);
|
||||
};
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ class MainWindow;
|
||||
extern void postToUiThread(std::function<void()> callback);
|
||||
extern void runOnUiThread(std::function<void()> callback);
|
||||
extern void runOnWorkerThread(std::function<void()> callback);
|
||||
extern bool isWorkerThread();
|
||||
|
||||
wxDECLARE_EVENT(UPDATE_STATE_EVENT, wxCommandEvent);
|
||||
|
||||
@@ -34,7 +35,8 @@ private:
|
||||
void OnExec(const ExecEvent& event);
|
||||
|
||||
public:
|
||||
bool IsWorkerThreadRunning() const;
|
||||
bool IsWorkerThread();
|
||||
bool IsWorkerThreadRunning();
|
||||
|
||||
protected:
|
||||
virtual wxThread::ExitCode Entry();
|
||||
|
||||
@@ -169,6 +169,13 @@ MainWindowGen::MainWindowGen( wxWindow* parent, wxWindowID id, const wxString& t
|
||||
fgSizer6->Fit( m_panel11 );
|
||||
fgSizer8->Add( m_panel11, 1, wxEXPAND | wxALL, 5 );
|
||||
|
||||
m_staticText232 = new wxStaticText( idlePanel, wxID_ANY, wxT("then select some options (if there are any):"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER_HORIZONTAL );
|
||||
m_staticText232->Wrap( -1 );
|
||||
fgSizer8->Add( m_staticText232, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 );
|
||||
|
||||
formatOptionsContainer = new wxPanel( idlePanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
|
||||
fgSizer8->Add( formatOptionsContainer, 1, wxALL|wxEXPAND, 5 );
|
||||
|
||||
m_staticText19 = new wxStaticText( idlePanel, wxID_ANY, wxT("and press one of:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText19->Wrap( -1 );
|
||||
fgSizer8->Add( m_staticText19, 0, wxALIGN_CENTER|wxALL, 5 );
|
||||
|
||||
@@ -1479,6 +1479,126 @@
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALIGN_CENTER_HORIZONTAL|wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxStaticText" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">then select some options (if there are any):</property>
|
||||
<property name="markup">0</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_staticText232</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style">wxALIGN_CENTER_HORIZONTAL</property>
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<property name="wrap">-1</property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL|wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxPanel" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">formatOptionsContainer</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style">wxTAB_TRAVERSAL</property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="0">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALIGN_CENTER|wxALL</property>
|
||||
|
||||
@@ -77,6 +77,8 @@ class MainWindowGen : public wxFrame
|
||||
wxPanel* m_panel11;
|
||||
wxChoice* formatChoice;
|
||||
wxButton* customConfigurationButton;
|
||||
wxStaticText* m_staticText232;
|
||||
wxPanel* formatOptionsContainer;
|
||||
wxStaticText* m_staticText19;
|
||||
wxButton* readButton;
|
||||
wxButton* writeButton;
|
||||
|
||||
@@ -115,7 +115,17 @@ void runOnWorkerThread(std::function<void()> callback)
|
||||
wxGetApp().RunOnWorkerThread(callback);
|
||||
}
|
||||
|
||||
bool FluxEngineApp::IsWorkerThreadRunning() const
|
||||
bool isWorkerThread()
|
||||
{
|
||||
return wxGetApp().IsWorkerThread();
|
||||
}
|
||||
|
||||
bool FluxEngineApp::IsWorkerThread()
|
||||
{
|
||||
return wxThread::GetCurrentId() != wxThread::GetMainId();
|
||||
}
|
||||
|
||||
bool FluxEngineApp::IsWorkerThreadRunning()
|
||||
{
|
||||
return !!_callback;
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ extern const std::map<std::string, std::string> formats;
|
||||
#define CONFIG_FORTYTRACK "FortyTrack"
|
||||
#define CONFIG_HIGHDENSITY "HighDensity"
|
||||
#define CONFIG_FORMAT "Format"
|
||||
#define CONFIG_FORMATOPTIONS "FormatOptions"
|
||||
#define CONFIG_EXTRACONFIG "ExtraConfig"
|
||||
#define CONFIG_FLUXIMAGE "FluxImage"
|
||||
#define CONFIG_DISKIMAGE "DiskImage"
|
||||
@@ -95,11 +96,16 @@ public:
|
||||
Logger::setLogger(
|
||||
[&](std::shared_ptr<const AnyLogMessage> message)
|
||||
{
|
||||
runOnUiThread(
|
||||
[message, this]()
|
||||
{
|
||||
OnLogMessage(message);
|
||||
});
|
||||
if (isWorkerThread())
|
||||
{
|
||||
runOnUiThread(
|
||||
[message, this]()
|
||||
{
|
||||
OnLogMessage(message);
|
||||
});
|
||||
}
|
||||
else
|
||||
OnLogMessage(message);
|
||||
});
|
||||
|
||||
_logWindow.reset(
|
||||
@@ -174,6 +180,7 @@ public:
|
||||
|
||||
LoadConfig();
|
||||
UpdateDevices();
|
||||
UpdateFormatOptions();
|
||||
}
|
||||
|
||||
void OnShowLogWindow(wxCommandEvent& event) override
|
||||
@@ -258,6 +265,7 @@ public:
|
||||
{
|
||||
SaveConfig();
|
||||
UpdateState();
|
||||
UpdateFormatOptions();
|
||||
}
|
||||
|
||||
void OnControlsChanged(wxFileDirPickerEvent& event) override
|
||||
@@ -1220,8 +1228,18 @@ public:
|
||||
Error() << "no format selected";
|
||||
|
||||
config.Clear();
|
||||
FlagGroup::parseConfigFile(
|
||||
_formatNames[formatChoice->GetSelection()], formats);
|
||||
auto formatName = _formatNames[formatChoice->GetSelection()];
|
||||
FlagGroup::parseConfigFile(formatName, formats);
|
||||
|
||||
/* Apply any format options. */
|
||||
|
||||
for (const auto& e : _formatOptions)
|
||||
{
|
||||
if (e.first == formatName)
|
||||
FlagGroup::applyOption(e.second);
|
||||
}
|
||||
|
||||
/* Merge in any custom config. */
|
||||
|
||||
for (auto setting : split(_extraConfiguration, '\n'))
|
||||
{
|
||||
@@ -1242,6 +1260,8 @@ public:
|
||||
FlagGroup::parseConfigFile(setting, formats);
|
||||
}
|
||||
|
||||
/* Locate the device, if any. */
|
||||
|
||||
auto serial = deviceCombo->GetValue().ToStdString();
|
||||
if (!serial.empty() && (serial[0] == '/'))
|
||||
setProtoByString(&config, "usb.greaseweazle.port", serial);
|
||||
@@ -1250,6 +1270,8 @@ public:
|
||||
|
||||
_logWindow->GetTextControl()->Clear();
|
||||
|
||||
/* Apply the source/destination. */
|
||||
|
||||
switch (_selectedSource)
|
||||
{
|
||||
case SELECTEDSOURCE_REAL:
|
||||
@@ -1476,6 +1498,24 @@ public:
|
||||
_config.Read(CONFIG_EXTRACONFIG, &s);
|
||||
_extraConfiguration = s;
|
||||
|
||||
/* Format options. */
|
||||
|
||||
_formatOptions.clear();
|
||||
s = "";
|
||||
_config.Read(CONFIG_FORMATOPTIONS, &s);
|
||||
for (auto combined : split(std::string(s), ','))
|
||||
{
|
||||
auto pair = split(combined, ':');
|
||||
try
|
||||
{
|
||||
auto key = std::make_pair(pair.at(0), pair.at(1));
|
||||
_formatOptions.insert(key);
|
||||
}
|
||||
catch (std::exception&)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/* Triggers SaveConfig */
|
||||
|
||||
_dontSaveConfig = false;
|
||||
@@ -1514,6 +1554,16 @@ public:
|
||||
_config.Write(CONFIG_FORMAT,
|
||||
formatChoice->GetString(formatChoice->GetSelection()));
|
||||
_config.Write(CONFIG_EXTRACONFIG, wxString(_extraConfiguration));
|
||||
|
||||
/* Format options. */
|
||||
|
||||
{
|
||||
std::vector<std::string> options;
|
||||
for (auto& e : _formatOptions)
|
||||
options.push_back(fmt::format("{}:{}", e.first, e.second));
|
||||
|
||||
_config.Write(CONFIG_FORMATOPTIONS, wxString(join(options, ",")));
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateState()
|
||||
@@ -1615,6 +1665,55 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateFormatOptions()
|
||||
{
|
||||
assert(!wxGetApp().IsWorkerThreadRunning());
|
||||
|
||||
formatOptionsContainer->DestroyChildren();
|
||||
auto* sizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
auto formatSelection = formatChoice->GetSelection();
|
||||
if (formatSelection == wxNOT_FOUND)
|
||||
sizer->Add(new wxStaticText(
|
||||
formatOptionsContainer, wxID_ANY, "(no format selected)"));
|
||||
else
|
||||
{
|
||||
config.Clear();
|
||||
std::string formatName = _formatNames[formatChoice->GetSelection()];
|
||||
FlagGroup::parseConfigFile(formatName, formats);
|
||||
|
||||
if (config.option().empty())
|
||||
sizer->Add(new wxStaticText(formatOptionsContainer,
|
||||
wxID_ANY,
|
||||
"(no options for this format)"));
|
||||
else
|
||||
for (auto& option : config.option())
|
||||
{
|
||||
auto* choice = new wxCheckBox(
|
||||
formatOptionsContainer, wxID_ANY, option.comment());
|
||||
auto key = std::make_pair(formatName, option.name());
|
||||
sizer->Add(choice);
|
||||
|
||||
if (_formatOptions.find(key) != _formatOptions.end())
|
||||
choice->SetValue(true);
|
||||
|
||||
choice->Bind(wxEVT_CHECKBOX,
|
||||
[this, choice, key](wxCommandEvent& e)
|
||||
{
|
||||
if (choice->GetValue())
|
||||
_formatOptions.insert(key);
|
||||
else
|
||||
_formatOptions.erase(key);
|
||||
|
||||
OnControlsChanged(e);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
formatOptionsContainer->SetSizerAndFit(sizer);
|
||||
idlePanel->Layout();
|
||||
}
|
||||
|
||||
void OnTrackSelection(TrackSelectionEvent& event)
|
||||
{
|
||||
(new FluxViewerWindow(this, event.trackFlux))->Show(true);
|
||||
@@ -1713,6 +1812,7 @@ private:
|
||||
int _explorerSide;
|
||||
bool _explorerUpdatePending;
|
||||
std::unique_ptr<const Fluxmap> _explorerFluxmap;
|
||||
std::set<std::pair<std::string, std::string>> _formatOptions;
|
||||
};
|
||||
|
||||
wxWindow* FluxEngineApp::CreateMainWindow()
|
||||
|
||||
Reference in New Issue
Block a user