Add settings object API
Documentation is in `docs/specs/Settings-Object-API.md`.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
#include "utils/setup.h"
|
||||
#include "settings/settings.h"
|
||||
#include "settings/settings_object.h"
|
||||
|
||||
INITIALIZE_EASYLOGGINGPP
|
||||
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
#pragma once
|
||||
#include <list>
|
||||
#include <easylogging++.h>
|
||||
|
||||
namespace settings
|
||||
{
|
||||
class SettingsObjectData
|
||||
{
|
||||
public:
|
||||
template <typename Value> void addValue( const Value value )
|
||||
{
|
||||
std::list<Value>& list = getListObject<Value>();
|
||||
|
||||
list.push_back( value );
|
||||
}
|
||||
|
||||
template <typename Value>
|
||||
Value getNextValueOrDefault( const Value defaultValue )
|
||||
{
|
||||
Value returnedValue = defaultValue;
|
||||
|
||||
std::list<Value>& list = getListObject<Value>();
|
||||
|
||||
if ( hasValuesOfType<Value>() )
|
||||
{
|
||||
returnedValue = list.front();
|
||||
list.pop_front();
|
||||
}
|
||||
|
||||
return returnedValue;
|
||||
}
|
||||
|
||||
template <typename Value> bool hasValuesOfType()
|
||||
{
|
||||
std::list<Value>& list = getListObject<Value>();
|
||||
|
||||
return !list.empty();
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename Value> std::list<Value>& getListObject()
|
||||
{
|
||||
using std::is_same;
|
||||
const auto isBool = is_same<bool, Value>::value;
|
||||
const auto isInt = is_same<int, Value>::value;
|
||||
const auto isDouble = is_same<double, Value>::value;
|
||||
const auto isString = is_same<std::string, Value>::value;
|
||||
|
||||
static_assert( isBool || isInt || isDouble || isString,
|
||||
"Type is not supported for the settings object." );
|
||||
|
||||
if constexpr ( isBool )
|
||||
{
|
||||
return m_boolValues;
|
||||
}
|
||||
else if constexpr ( isInt )
|
||||
{
|
||||
return m_intValues;
|
||||
}
|
||||
else if constexpr ( isDouble )
|
||||
{
|
||||
return m_doubleValues;
|
||||
}
|
||||
else if constexpr ( isString )
|
||||
{
|
||||
return m_stringValues;
|
||||
}
|
||||
}
|
||||
|
||||
std::list<bool> m_boolValues;
|
||||
std::list<int> m_intValues;
|
||||
std::list<double> m_doubleValues;
|
||||
std::list<std::string> m_stringValues;
|
||||
};
|
||||
} // namespace settings
|
||||
@@ -0,0 +1,197 @@
|
||||
#include <QSettings>
|
||||
#include "settings_object.h"
|
||||
|
||||
namespace settings
|
||||
{
|
||||
[[nodiscard]] QSettings& getQSettings();
|
||||
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename Value>
|
||||
std::list<Value> createListFromObject( settings::SettingsObjectData& obj )
|
||||
{
|
||||
std::list<Value> list;
|
||||
while ( obj.hasValuesOfType<Value>() )
|
||||
{
|
||||
list.push_back( obj.getNextValueOrDefault( Value{} ) );
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
template <typename Value>
|
||||
void addListToObject( std::list<Value>& list,
|
||||
settings::SettingsObjectData& obj )
|
||||
{
|
||||
while ( !list.empty() )
|
||||
{
|
||||
obj.addValue( list.front() );
|
||||
list.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Value>
|
||||
void saveListToDisk( std::list<Value> values,
|
||||
const std::string structName,
|
||||
const std::string typeName )
|
||||
{
|
||||
auto& s = settings::getQSettings();
|
||||
|
||||
s.beginGroup( structName.c_str() );
|
||||
s.beginWriteArray( typeName.c_str() );
|
||||
|
||||
for ( int i = 0; !values.empty(); ++i )
|
||||
{
|
||||
s.setArrayIndex( i );
|
||||
if constexpr ( std::is_same<std::string, Value>::value )
|
||||
{
|
||||
s.setValue( typeName.c_str(), values.front().c_str() );
|
||||
}
|
||||
else
|
||||
{
|
||||
s.setValue( typeName.c_str(), values.front() );
|
||||
}
|
||||
values.pop_front();
|
||||
}
|
||||
|
||||
s.endArray();
|
||||
s.endGroup();
|
||||
}
|
||||
template <typename Value>
|
||||
std::list<Value> loadListFromDisk( const std::string structName,
|
||||
const std::string typeName )
|
||||
{
|
||||
using std::is_same;
|
||||
const auto isBool = is_same<bool, Value>::value;
|
||||
const auto isInt = is_same<int, Value>::value;
|
||||
const auto isDouble = is_same<double, Value>::value;
|
||||
const auto isString = is_same<std::string, Value>::value;
|
||||
|
||||
static_assert( isBool || isInt || isDouble || isString,
|
||||
"Type is not supported for the settings object." );
|
||||
|
||||
auto& s = settings::getQSettings();
|
||||
|
||||
s.beginGroup( structName.c_str() );
|
||||
auto size = s.beginReadArray( typeName.c_str() );
|
||||
|
||||
std::list<Value> list;
|
||||
for ( int i = 0; i < size; ++i )
|
||||
{
|
||||
s.setArrayIndex( i );
|
||||
auto v = s.value( typeName.c_str() );
|
||||
|
||||
if constexpr ( isBool )
|
||||
{
|
||||
list.push_back( v.toBool() );
|
||||
}
|
||||
else if constexpr ( isInt )
|
||||
{
|
||||
list.push_back( v.toInt() );
|
||||
}
|
||||
else if constexpr ( isDouble )
|
||||
{
|
||||
list.push_back( v.toDouble() );
|
||||
}
|
||||
else if constexpr ( isString )
|
||||
{
|
||||
list.push_back( v.toString().toStdString() );
|
||||
}
|
||||
}
|
||||
|
||||
s.endArray();
|
||||
s.endGroup();
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
settings::SettingsObjectData loadSettingsObject( std::string objName )
|
||||
{
|
||||
settings::SettingsObjectData s;
|
||||
|
||||
auto boolValues = loadListFromDisk<bool>( objName, "bools" );
|
||||
addListToObject( boolValues, s );
|
||||
|
||||
auto intValues = loadListFromDisk<int>( objName, "ints" );
|
||||
addListToObject( intValues, s );
|
||||
|
||||
auto doubleValues = loadListFromDisk<double>( objName, "doubles" );
|
||||
addListToObject( doubleValues, s );
|
||||
|
||||
auto stringValues = loadListFromDisk<std::string>( objName, "strings" );
|
||||
addListToObject( stringValues, s );
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void saveSettingsObject( settings::SettingsObjectData& s, std::string objName )
|
||||
{
|
||||
auto boolValues = createListFromObject<bool>( s );
|
||||
saveListToDisk( boolValues, objName, "bools" );
|
||||
|
||||
auto intValues = createListFromObject<int>( s );
|
||||
saveListToDisk( intValues, objName, "ints" );
|
||||
|
||||
auto doubleValues = createListFromObject<double>( s );
|
||||
saveListToDisk( doubleValues, objName, "doubles" );
|
||||
|
||||
auto stringValues = createListFromObject<std::string>( s );
|
||||
saveListToDisk( stringValues, objName, "strings" );
|
||||
}
|
||||
|
||||
std::string appendSlotNumberToSettingsName( const std::string name,
|
||||
const int slot )
|
||||
{
|
||||
return name + "-" + std::to_string( slot );
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace settings
|
||||
{
|
||||
void saveObject( const ISettingsObject& obj )
|
||||
{
|
||||
auto s = obj.saveSettings();
|
||||
saveSettingsObject( s, obj.settingsName() );
|
||||
}
|
||||
|
||||
void loadObject( ISettingsObject& obj )
|
||||
|
||||
{
|
||||
auto s = loadSettingsObject( obj.settingsName() );
|
||||
obj.loadSettings( s );
|
||||
}
|
||||
|
||||
void saveNumberedObject( const ISettingsObject& obj, const int slot )
|
||||
{
|
||||
auto s = obj.saveSettings();
|
||||
saveSettingsObject(
|
||||
s, appendSlotNumberToSettingsName( obj.settingsName(), slot ) );
|
||||
}
|
||||
|
||||
void loadNumberedObject( ISettingsObject& obj, const int slot )
|
||||
{
|
||||
auto s = loadSettingsObject(
|
||||
appendSlotNumberToSettingsName( obj.settingsName(), slot ) );
|
||||
obj.loadSettings( s );
|
||||
}
|
||||
|
||||
int getAmountOfSavedObjects( ISettingsObject& obj )
|
||||
{
|
||||
auto& s = getQSettings();
|
||||
|
||||
auto groups = s.childGroups();
|
||||
|
||||
for ( int i = 1;; ++i )
|
||||
{
|
||||
const auto groupDoesNotContainSetting = !groups.contains(
|
||||
appendSlotNumberToSettingsName( obj.settingsName(), i ).c_str() );
|
||||
if ( groupDoesNotContainSetting )
|
||||
{
|
||||
return i - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace settings
|
||||
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
#include "internal/settings_object_data.h"
|
||||
|
||||
namespace settings
|
||||
{
|
||||
class ISettingsObject
|
||||
{
|
||||
public:
|
||||
virtual ~ISettingsObject() {}
|
||||
|
||||
virtual SettingsObjectData saveSettings() const = 0;
|
||||
virtual void loadSettings( SettingsObjectData& obj ) = 0;
|
||||
|
||||
virtual std::string settingsName() const = 0;
|
||||
};
|
||||
|
||||
void saveObject( const ISettingsObject& obj );
|
||||
|
||||
void loadObject( ISettingsObject& obj );
|
||||
|
||||
void saveNumberedObject( const ISettingsObject& obj, const int slot );
|
||||
|
||||
void loadNumberedObject( ISettingsObject& obj, const int slot );
|
||||
|
||||
int getAmountOfSavedObjects( ISettingsObject& obj );
|
||||
|
||||
} // namespace settings
|
||||
Reference in New Issue
Block a user