1//============================================================================
2//
3// SSSS tt lll lll
4// SS SS tt ll ll
5// SS tttttt eeee ll ll aaaa
6// SSSS tt ee ee ll ll aa
7// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
8// SS SS tt ee ll ll aa aa
9// SSSS ttt eeeee llll llll aaaaa
10//
11// Copyright (c) 1995-2019 by Bradford W. Mott, Stephen Anthony
12// and the Stella Team
13//
14// See the file "License.txt" for information on usage and redistribution of
15// this file, and for a DISCLAIMER OF ALL WARRANTIES.
16//============================================================================
17
18#ifndef SETTINGS_HXX
19#define SETTINGS_HXX
20
21#include <map>
22
23#include "Variant.hxx"
24#include "bspf.hxx"
25#include "repository/KeyValueRepository.hxx"
26
27/**
28 This class provides an interface for accessing all configurable options,
29 both from the settings file and from the commandline.
30
31 Note that options can be configured as 'permanent' or 'temporary'.
32 Permanent options are ones that the app registers with the system, and
33 always saves when the app exits. Temporary options are those that are
34 used when appropriate, but never saved to the settings file.
35
36 Each c'tor (both in the base class and in any derived classes) are
37 responsible for registering all options as either permanent or temporary.
38 If an option isn't registered as permanent, it will be considered
39 temporary and will not be saved.
40
41 @author Stephen Anthony
42*/
43class Settings
44{
45 public:
46 /**
47 Create a new settings abstract class
48 */
49 explicit Settings();
50 virtual ~Settings() = default;
51
52 using Options = std::map<string, Variant>;
53
54 public:
55 /**
56 This method should be called to display usage information.
57 */
58 void usage() const;
59
60 void setRepository(shared_ptr<KeyValueRepository> repository);
61
62 /**
63 This method is called to load settings from the settings file,
64 and apply commandline options specified by the given parameter.
65
66 @param options A list of options that overrides ones in the
67 settings file
68 */
69 void load(const Options& options);
70
71 /**
72 This method is called to save the current settings to the
73 settings file.
74 */
75 void save();
76
77 /**
78 Get the value assigned to the specified key.
79
80 @param key The key of the setting to lookup
81 @return The value of the setting; EmptyVariant if none exists
82 */
83 const Variant& value(const string& key) const;
84
85 /**
86 Set the value associated with the specified key.
87
88 @param key The key of the setting
89 @param value The value to assign to the key
90 */
91 void setValue(const string& key, const Variant& value, bool persist = true);
92
93 /**
94 Convenience methods to return specific types.
95
96 @param key The key of the setting to lookup
97 @return The specific type value of the variant
98 */
99 int getInt(const string& key) const { return value(key).toInt(); }
100 float getFloat(const string& key) const { return value(key).toFloat(); }
101 bool getBool(const string& key) const { return value(key).toBool(); }
102 const string& getString(const string& key) const { return value(key).toString(); }
103 const Common::Size getSize(const string& key) const { return value(key).toSize(); }
104 const Common::Point getPoint(const string& key) const { return value(key).toPoint(); }
105
106 protected:
107 /**
108 Add key/value pair to specified map. Note that these should only be called
109 directly within the c'tor, to register the 'key' and set it to the
110 appropriate 'value'. Elsewhere, any derived classes should call 'setValue',
111 and let it decide where the key/value pair will be saved.
112 */
113 void setPermanent(const string& key, const Variant& value);
114 void setTemporary(const string& key, const Variant& value);
115
116 // Trim leading and following whitespace from a string
117 static string trim(const string& str)
118 {
119 string::size_type first = str.find_first_not_of(' ');
120 return (first == string::npos) ? EmptyString :
121 str.substr(first, str.find_last_not_of(' ')-first+1);
122 }
123
124 // FIXME - Rework so that these aren't needed; hence no commenting added
125 const Options& getPermanentSettings() const
126 { return myPermanentSettings; }
127 const Options& getTemporarySettings() const
128 { return myTemporarySettings; }
129
130 private:
131 /**
132 This method must be called *after* settings have been fully loaded
133 to validate (and change, if necessary) any improper settings.
134 */
135 void validate();
136
137 private:
138 // Holds key/value pairs that are necessary for Stella to
139 // function and must be saved on each program exit.
140 Options myPermanentSettings;
141
142 // Holds auxiliary key/value pairs that shouldn't be saved on
143 // program exit.
144 Options myTemporarySettings;
145
146 shared_ptr<KeyValueRepository> myRespository;
147
148 private:
149 // Following constructors and assignment operators not supported
150 Settings(const Settings&) = delete;
151 Settings(Settings&&) = delete;
152 Settings& operator=(const Settings&) = delete;
153 Settings& operator=(Settings&&) = delete;
154};
155
156#endif
157