Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: ngscopeclient/scopehal-apps
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 40e2c17ac799
Choose a base ref
...
head repository: ngscopeclient/scopehal-apps
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 3752d10fc8a2
Choose a head ref
  • 2 commits
  • 7 files changed
  • 2 contributors

Commits on Oct 31, 2020

  1. Implemented enum preferences

    nshcat committed Oct 31, 2020
    Copy the full SHA
    3eced56 View commit details
  2. Merge pull request #267 from azonenberg/kathi_dev

    Implemented enum preferences
    azonenberg authored Oct 31, 2020
    Copy the full SHA
    3752d10 View commit details
59 changes: 56 additions & 3 deletions src/glscopeclient/Preference.cpp
Original file line number Diff line number Diff line change
@@ -87,7 +87,7 @@ void EnumMapping::AddEnumMember(const std::string& name, base_type value)
this->m_names.push_back(name);
}

const std::string& EnumMapping::GetName(base_type value)
const std::string& EnumMapping::GetName(base_type value) const
{
const auto it = this->m_backwardMap.find(value);

@@ -97,7 +97,17 @@ const std::string& EnumMapping::GetName(base_type value)
return it->second;
}

EnumMapping::base_type EnumMapping::GetValue(const std::string& name)
bool EnumMapping::HasNameFor(base_type value) const
{
return this->m_backwardMap.count(value) > 0;
}

bool EnumMapping::HasValueFor(const std::string& name) const
{
return this->m_forwardMap.count(name) > 0;
}

EnumMapping::base_type EnumMapping::GetValue(const std::string& name) const
{
const auto it = this->m_forwardMap.find(name);

@@ -107,7 +117,7 @@ EnumMapping::base_type EnumMapping::GetValue(const std::string& name)
return it->second;
}

const std::vector<std::string>& EnumMapping::GetNames()
const std::vector<std::string>& EnumMapping::GetNames() const
{
return this->m_names;
}
@@ -150,6 +160,14 @@ bool Preference::GetBool() const
return GetValueRaw<bool>();
}

std::int64_t Preference::GetEnumRaw() const
{
if(m_type != PreferenceType::Enum)
throw runtime_error("Preference type mismatch");

return GetValueRaw<std::int64_t>();
}

Gdk::Color Preference::GetColor() const
{
if(m_type != PreferenceType::Color)
@@ -215,6 +233,12 @@ string Preference::ToString() const
return to_string(GetReal());
case PreferenceType::Color:
return "Color";
case PreferenceType::Enum:
{
const auto& mapper = this->GetMapping();
const auto value = this->GetEnumRaw();
return mapper.GetName(value);
}
default:
throw runtime_error("tried to retrieve value from preference in moved-from state");
}
@@ -229,6 +253,7 @@ void Preference::MoveFrom(Preference& other)
m_isVisible = move(other.m_isVisible);
m_unit = move(other.m_unit);
m_hasValue = move(other.m_hasValue);
m_mapping = move(other.m_mapping);

if(m_hasValue)
{
@@ -249,6 +274,10 @@ void Preference::MoveFrom(Preference& other)
case PreferenceType::Color:
Construct<impl::Color>(move(other.GetValueRaw<impl::Color>()));
break;

case PreferenceType::Enum:
Construct<std::int64_t>(move(other.GetValueRaw<std::int64_t>()));
break;

default:
break;
@@ -276,6 +305,12 @@ void Preference::SetReal(double value)
Construct<double>(value);
}

void Preference::SetEnumRaw(std::int64_t value)
{
CleanUp();
Construct<std::int64_t>(value);
}

void Preference::SetString(string value)
{
CleanUp();
@@ -295,6 +330,16 @@ void Preference::SetColorRaw(const impl::Color& color)
Construct<impl::Color>(color);
}

const EnumMapping& Preference::GetMapping() const
{
return this->m_mapping;
}

void Preference::SetMapping(EnumMapping mapping)
{
this->m_mapping = std::move(mapping);
}

impl::PreferenceBuilder Preference::Real(std::string identifier, double defaultValue)
{
Preference pref(PreferenceType::Real, std::move(identifier));
@@ -329,3 +374,11 @@ impl::PreferenceBuilder Preference::Color(std::string identifier, const Gdk::Col
return impl::PreferenceBuilder{ std::move(pref) };
}

impl::PreferenceBuilder Preference::EnumRaw(std::string identifier, std::int64_t defaultValue)
{
Preference pref(PreferenceType::Enum, std::move(identifier));
pref.Construct<std::int64_t>(defaultValue);

return impl::PreferenceBuilder{ std::move(pref) };
}

56 changes: 47 additions & 9 deletions src/glscopeclient/Preference.h
Original file line number Diff line number Diff line change
@@ -58,6 +58,7 @@ enum class PreferenceType
String,
Real,
Color,
Enum,
None // Only for moved-from values
};

@@ -79,7 +80,7 @@ namespace impl

class EnumMapping
{
using base_type = signed long long;
using base_type = std::int64_t;

public:
EnumMapping()
@@ -89,17 +90,19 @@ class EnumMapping

public:
void AddEnumMember(const std::string& name, base_type value);
const std::string& GetName(base_type value);
base_type GetValue(const std::string& name);
const std::vector<std::string>& GetNames();
const std::string& GetName(base_type value) const;
base_type GetValue(const std::string& name) const;
const std::vector<std::string>& GetNames() const;
bool HasNameFor(base_type value) const;
bool HasValueFor(const std::string& name) const;

public:
template<
typename E,
typename E/*,
typename = typename std::enable_if<
std::is_convertible<E, base_type>::value &&
not std::is_same<E, base_type>::value
>::type
>::type*/
>
void AddEnumMember(const std::string& name, E value)
{
@@ -119,8 +122,8 @@ class Preference

private:
using PreferenceValue = typename std::aligned_union<
max(sizeof(impl::Color), max(max(sizeof(bool), sizeof(double)), sizeof(std::string))),
bool, std::string, double, impl::Color
max(sizeof(std::int64_t), max(sizeof(impl::Color), max(max(sizeof(bool), sizeof(double)), sizeof(std::string)))),
bool, std::string, double, impl::Color, std::int64_t
>::type;

public:
@@ -154,6 +157,8 @@ class Preference
const std::string& GetIdentifier() const;
const std::string& GetLabel() const;
const std::string& GetDescription() const;
std::int64_t GetEnumRaw() const;
void SetEnumRaw(std::int64_t value);
PreferenceType GetType() const;
bool GetBool() const;
double GetReal() const;
@@ -171,14 +176,33 @@ class Preference
void SetDescription(std::string description);
bool HasUnit();
Unit& GetUnit();
const EnumMapping& GetMapping() const;

template< typename E >
E GetEnum() const
{
return static_cast<E>(this->GetEnumRaw());
}

template< typename E >
void SetEnum(E value)
{
this->SetEnumRaw(static_cast<std::int64_t>(value));
}

public:
static impl::PreferenceBuilder Real(std::string identifier, double defaultValue);
static impl::PreferenceBuilder Bool(std::string identifier, bool defaultValue);
static impl::PreferenceBuilder String(std::string identifier, std::string defaultValue);
static impl::PreferenceBuilder Color(std::string identifier, const Gdk::Color& defaultValue);

static impl::PreferenceBuilder EnumRaw(std::string identifier, std::int64_t defaultValue);

template< typename E >
static impl::PreferenceBuilder Enum(std::string identifier, E defaultValue);

private:
void SetMapping(EnumMapping mapping);

template<typename T>
const T& GetValueRaw() const
{
@@ -211,6 +235,7 @@ class Preference
bool m_isVisible{true};
Unit m_unit{Unit::UNIT_COUNTS};
bool m_hasValue{false};
EnumMapping m_mapping;
};

namespace impl
@@ -227,9 +252,22 @@ namespace impl
PreferenceBuilder Unit(Unit::UnitType type) &&;
Preference Build() &&;

template< typename E >
PreferenceBuilder EnumValue(const std::string& name, E value) &&
{
this->m_pref.m_mapping.AddEnumMember<E>(name, value);
return std::move(*this);
}

protected:
Preference m_pref;
};
}

template< typename E >
impl::PreferenceBuilder Preference::Enum(std::string identifier, E defaultValue)
{
return EnumRaw(std::move(identifier), static_cast<std::int64_t>(defaultValue));
}

#endif // Preference_h
66 changes: 66 additions & 0 deletions src/glscopeclient/PreferenceDialog.cpp
Original file line number Diff line number Diff line change
@@ -52,6 +52,35 @@ PreferencePage::PreferencePage(PreferenceCategory& category)
CreateWidgets();
}

EnumRow::EnumRow(const Preference& pref)
{
const auto& mapper = pref.GetMapping();

this->m_refTreeModel = Gtk::ListStore::create(this->m_columns);
this->m_value.set_model(this->m_refTreeModel);

for(const auto& name: mapper.GetNames())
{
Gtk::TreeModel::Row row = *(m_refTreeModel->append());
row[this->m_columns.m_col_name] = name.c_str();
const auto value = mapper.GetValue(name);

if(pref.GetEnumRaw() == value)
this->m_value.set_active(row);
}

this->m_value.pack_start(this->m_columns.m_col_name);
}

std::string EnumRow::GetActiveName()
{
Gtk::TreeModel::iterator iter = this->m_value.get_active();
Gtk::TreeModel::Row row = *iter;

Glib::ustring str = row[this->m_columns.m_col_name];
return (std::string)str;
}

void PreferencePage::CreateWidgets()
{
Gtk::Widget* last = nullptr;
@@ -72,6 +101,29 @@ void PreferencePage::CreateWidgets()

switch(preference.GetType())
{
case PreferenceType::Enum:
{
auto row = unique_ptr<EnumRow>{ new EnumRow(preference) };
row->m_identifier = preference.GetIdentifier();
row->m_label.set_label(preference.GetLabel());
row->m_label.set_halign(Gtk::ALIGN_START);
row->m_value.set_halign(Gtk::ALIGN_CENTER);
row->m_label.set_tooltip_text(preference.GetDescription());
row->m_value.set_tooltip_text(preference.GetDescription());

if(!last)
attach(row->m_label, 0, 0, 1, 1);
else
attach_next_to(row->m_label, *last, Gtk::POS_BOTTOM, 1, 1);

attach_next_to(row->m_value, row->m_label, Gtk::POS_RIGHT, 1, 1);

last = &(row->m_label);
m_enumRows.push_back(std::move(row));

break;
}

case PreferenceType::Boolean:
{
auto row = unique_ptr<BooleanRow>{ new BooleanRow() };
@@ -197,6 +249,20 @@ void PreferencePage::SaveChanges()
break;
}

case PreferenceType::Enum:
{
// This will always succeed
const auto it = find_if(m_enumRows.begin(), m_enumRows.end(),
[&preference](const unique_ptr<EnumRow>& x) -> bool
{
return x->m_identifier == preference.GetIdentifier();
});

const auto& mapping = preference.GetMapping();
preference.SetEnumRaw(mapping.GetValue((*it)->GetActiveName()));
break;
}

case PreferenceType::Boolean:
{
// This will always succeed
25 changes: 25 additions & 0 deletions src/glscopeclient/PreferenceDialog.h
Original file line number Diff line number Diff line change
@@ -64,6 +64,30 @@ struct ColorRow
Gtk::ColorButton m_colorbutton;
};

struct EnumRow
{
struct ModelColumns
: public Gtk::TreeModel::ColumnRecord
{
ModelColumns()
{
add(m_col_name);
}

Gtk::TreeModelColumn<Glib::ustring> m_col_name;
};

EnumRow(const Preference& pref);

std::string GetActiveName();

ModelColumns m_columns;
Glib::RefPtr<Gtk::ListStore> m_refTreeModel;
std::string m_identifier;
Gtk::Label m_label;
Gtk::ComboBox m_value;
};

class PreferencePage : public Gtk::Grid
{

@@ -81,6 +105,7 @@ class PreferencePage : public Gtk::Grid
std::vector<std::unique_ptr<BooleanRow>> m_booleanRows;
std::vector<std::unique_ptr<StringRealRow>> m_stringRealRows;
std::vector<std::unique_ptr<ColorRow>> m_colorRows;
std::vector<std::unique_ptr<EnumRow>> m_enumRows;
};


6 changes: 6 additions & 0 deletions src/glscopeclient/PreferenceManager.h
Original file line number Diff line number Diff line change
@@ -69,6 +69,12 @@ class PreferenceManager
bool GetBool(const std::string& path) const;
Gdk::Color GetColor(const std::string& path) const;

template< typename E >
E GetEnum(const std::string& path) const
{
return this->GetPreference(path).GetEnum<E>();
}

private:
// Internal helpers
void DeterminePath();
Loading