28 config* g_configPointers[MAX_CONFIG]; |
28 config* g_configPointers[MAX_CONFIG]; |
29 static ushort g_cfgPointerCursor = 0; |
29 static ushort g_cfgPointerCursor = 0; |
30 |
30 |
31 // ============================================================================= |
31 // ============================================================================= |
32 // Load the configuration from file |
32 // Load the configuration from file |
33 bool config::load() |
33 bool config::load() { |
34 { |
34 print ("config::load: Loading configuration file...\n"); |
35 print( "config::load: Loading configuration file...\n" ); |
35 print ("config::load: Path to configuration is %1\n", filepath()); |
36 print( "config::load: Path to configuration is %1\n", filepath() ); |
36 |
37 |
|
38 // Locale must be disabled for atof |
37 // Locale must be disabled for atof |
39 setlocale( LC_NUMERIC, "C" ); |
38 setlocale (LC_NUMERIC, "C"); |
40 |
39 |
41 File f( filepath(), File::Read ); |
40 File f (filepath(), File::Read); |
42 int ln = 0; |
41 int ln = 0; |
43 |
42 |
44 if( !f ) |
43 if (!f) |
45 return false; |
44 return false; |
46 |
45 |
47 // Read the values. |
46 // Read the values. |
48 for( str line : f ) |
47 for (str line : f) { |
49 { |
|
50 ln++; |
48 ln++; |
51 |
49 |
52 if( line.isEmpty() || line[0] == '#' ) |
50 if (line.isEmpty() || line[0] == '#') |
53 continue; // Empty line or comment. |
51 continue; // Empty line or comment. |
54 |
52 |
55 // Find the equals sign. |
53 // Find the equals sign. |
56 int equals = line.indexOf( '=' ); |
54 int equals = line.indexOf ('='); |
57 |
55 |
58 if( equals == -1 ) |
56 if (equals == -1) { |
59 { |
57 fprint (stderr, "couldn't find `=` sign in entry `%1`\n", line); |
60 fprint( stderr, "couldn't find `=` sign in entry `%1`\n", line ); |
|
61 continue; |
58 continue; |
62 } |
59 } |
63 |
60 |
64 str entry = line.left( equals ); |
61 str entry = line.left (equals); |
65 str valstring = line.right( line.length() - equals - 1 ); |
62 str valstring = line.right (line.length() - equals - 1); |
66 |
63 |
67 // Find the config entry for this. |
64 // Find the config entry for this. |
68 config* cfg = null; |
65 config* cfg = null; |
69 |
66 |
70 for( config* i : g_configPointers ) |
67 for (config* i : g_configPointers) { |
71 { |
68 if (!i) |
72 if( !i ) |
|
73 break; |
69 break; |
74 |
70 |
75 if( entry == i->name ) |
71 if (entry == i->name) |
76 cfg = i; |
72 cfg = i; |
77 } |
73 } |
78 |
74 |
79 if( !cfg ) |
75 if (!cfg) { |
80 { |
76 fprint (stderr, "unknown config `%1`\n", entry); |
81 fprint( stderr, "unknown config `%1`\n", entry ); |
|
82 continue; |
77 continue; |
83 } |
78 } |
84 |
79 |
85 switch( cfg->getType() ) |
80 switch (cfg->getType()) { |
86 { |
|
87 case Type_int: |
81 case Type_int: |
88 static_cast<intconfig*>( cfg )->value = valstring.toInt(); |
82 static_cast<intconfig*> (cfg)->value = valstring.toInt(); |
89 break; |
83 break; |
90 |
84 |
91 case Type_str: |
85 case Type_str: |
92 static_cast<strconfig*>( cfg )->value = valstring; |
86 static_cast<strconfig*> (cfg)->value = valstring; |
93 break; |
87 break; |
94 |
88 |
95 case Type_float: |
89 case Type_float: |
96 static_cast<floatconfig*>( cfg )->value = valstring.toFloat(); |
90 static_cast<floatconfig*> (cfg)->value = valstring.toFloat(); |
97 break; |
91 break; |
98 |
92 |
99 case Type_bool: |
93 case Type_bool: { |
100 { |
94 bool& val = static_cast<boolconfig*> (cfg)->value; |
101 bool& val = static_cast<boolconfig*>( cfg )->value; |
|
102 |
95 |
103 if( valstring.toUpper() == "TRUE" || valstring == "1" ) |
96 if (valstring.toUpper() == "TRUE" || valstring == "1") |
104 val = true; |
97 val = true; |
105 elif( valstring.toUpper() == "FALSE" || valstring == "0" ) |
98 elif (valstring.toUpper() == "FALSE" || valstring == "0") |
106 val = false; |
99 val = false; |
107 |
100 |
108 break; |
101 break; |
109 } |
102 } |
110 |
103 |
111 case Type_keyseq: |
104 case Type_keyseq: |
112 static_cast<keyseqconfig*>( cfg )->value = keyseq::fromString( valstring ); |
105 static_cast<keyseqconfig*> (cfg)->value = keyseq::fromString (valstring); |
113 break; |
106 break; |
114 |
107 |
115 default: |
108 default: |
116 break; |
109 break; |
117 } |
110 } |
119 |
112 |
120 f.close(); |
113 f.close(); |
121 return true; |
114 return true; |
122 } |
115 } |
123 |
116 |
124 extern_cfg( str, io_ldpath ); |
117 extern_cfg (str, io_ldpath); |
125 |
118 |
126 // ============================================================================= |
119 // ============================================================================= |
127 // Save the configuration to disk |
120 // Save the configuration to disk |
128 bool config::save() |
121 bool config::save() { |
129 { |
|
130 // The function will write floats, disable the locale now so that they |
122 // The function will write floats, disable the locale now so that they |
131 // are written properly. |
123 // are written properly. |
132 setlocale( LC_NUMERIC, "C" ); |
124 setlocale (LC_NUMERIC, "C"); |
133 |
125 |
134 // If the directory doesn't exist, create it now. |
126 // If the directory doesn't exist, create it now. |
135 if( QDir( dirpath() ).exists() == false ) |
127 if (QDir (dirpath()).exists() == false) { |
136 { |
128 fprint (stderr, "Creating config path %1...\n", dirpath()); |
137 fprint( stderr, "Creating config path %1...\n", dirpath() ); |
129 |
138 |
130 if (!QDir().mkpath (dirpath())) { |
139 if( !QDir().mkpath( dirpath() )) |
131 critical ("Failed to create the configuration directory. Configuration cannot be saved!\n"); |
140 { |
|
141 critical( "Failed to create the configuration directory. Configuration cannot be saved!\n" ); |
|
142 return false; |
132 return false; |
143 } |
133 } |
144 } |
134 } |
145 |
135 |
146 File f( filepath(), File::Write ); |
136 File f (filepath(), File::Write); |
147 print( "writing cfg to %1\n", filepath() ); |
137 print ("writing cfg to %1\n", filepath()); |
148 |
138 |
149 if( !f ) |
139 if (!f) { |
150 { |
140 critical (fmt (QObject::tr ("Cannot save configuration, cannot open %1 for writing: %2\n"), |
151 critical( fmt( QObject::tr( "Cannot save configuration, cannot open %1 for writing: %2\n" ), |
141 filepath(), strerror (errno))); |
152 filepath(), strerror( errno )) ); |
|
153 return false; |
142 return false; |
154 } |
143 } |
155 |
144 |
156 fprint( f, "# Configuration file for " APPNAME "\n" ); |
145 fprint (f, "# Configuration file for " APPNAME "\n"); |
157 |
146 str valstring; |
158 for( config * cfg : g_configPointers ) |
147 |
159 { |
148 for (config* cfg : g_configPointers) { |
160 if( !cfg ) |
149 if (!cfg) |
161 break; |
150 break; |
162 |
151 |
163 if( cfg->isDefault() ) |
152 if (cfg->isDefault()) |
164 continue; |
153 continue; |
165 |
154 |
166 str valstring; |
155 switch (cfg->getType()) { |
167 |
|
168 switch( cfg->getType() ) |
|
169 { |
|
170 case Type_int: |
156 case Type_int: |
171 valstring = fmt( "%1", static_cast<intconfig*>( cfg )->value ); |
157 valstring = fmt ("%1", static_cast<intconfig*> (cfg)->value); |
172 break; |
158 break; |
173 |
159 |
174 case Type_str: |
160 case Type_str: |
175 valstring = static_cast<strconfig*>( cfg )->value; |
161 valstring = static_cast<strconfig*> (cfg)->value; |
176 break; |
162 break; |
177 |
163 |
178 case Type_float: |
164 case Type_float: |
179 valstring = fmt( "%1", static_cast<floatconfig*>( cfg )->value ); |
165 valstring = fmt ("%1", static_cast<floatconfig*> (cfg)->value); |
180 break; |
166 break; |
181 |
167 |
182 case Type_bool: |
168 case Type_bool: |
183 valstring = ( static_cast<boolconfig*>( cfg )->value ) ? "true" : "false"; |
169 valstring = (static_cast<boolconfig*> (cfg)->value) ? "true" : "false"; |
184 break; |
170 break; |
185 |
171 |
186 case Type_keyseq: |
172 case Type_keyseq: |
187 valstring = static_cast<keyseqconfig*>( cfg )->value.toString(); |
173 valstring = static_cast<keyseqconfig*> (cfg)->value.toString(); |
188 break; |
174 break; |
189 |
175 |
190 default: |
176 default: |
191 break; |
177 break; |
192 } |
178 } |
193 |
179 |
194 // Write the entry now. |
180 // Write the entry now. |
195 fprint( f, "%1=%2\n", cfg->name, valstring ); |
181 fprint (f, "%1=%2\n", cfg->name, valstring); |
196 } |
182 } |
197 |
183 |
198 f.close(); |
184 f.close(); |
199 return true; |
185 return true; |
200 } |
186 } |
201 |
187 |
202 // ============================================================================= |
188 // ============================================================================= |
203 void config::reset() |
189 void config::reset() { |
204 { |
190 for (config* cfg : g_configPointers) { |
205 for( config * cfg : g_configPointers ) |
191 if (!cfg) |
206 { |
|
207 if( !cfg ) |
|
208 break; |
192 break; |
209 |
193 |
210 cfg->resetValue(); |
194 cfg->resetValue(); |
211 } |
195 } |
212 } |
196 } |
213 |
197 |
214 // ============================================================================= |
198 // ============================================================================= |
215 str config::filepath() |
199 str config::filepath() { |
216 { |
200 str path = fmt ("%1%2.cfg", dirpath(), str (APPNAME).toLower()); |
217 str path = fmt( "%1%2.cfg", dirpath(), |
|
218 str( APPNAME ).toLower() ); |
|
219 return path; |
201 return path; |
220 } |
202 } |
221 |
203 |
222 // ============================================================================= |
204 // ============================================================================= |
223 str config::dirpath() |
205 str config::dirpath() { |
224 { |
|
225 #ifndef _WIN32 |
206 #ifndef _WIN32 |
226 return fmt( "%1" DIRSLASH ".%2" DIRSLASH, |
207 return fmt ("%1" DIRSLASH ".%2" DIRSLASH, |
227 QDir::homePath(), str( APPNAME ).toLower() ); |
208 QDir::homePath(), str (APPNAME).toLower()); |
228 #else |
209 #else |
229 return fmt( "%1" DIRSLASH APPNAME DIRSLASH, QDir::homePath() ); |
210 return fmt ("%1" DIRSLASH APPNAME DIRSLASH, QDir::homePath()); |
230 #endif // _WIN32 |
211 #endif // _WIN32 |
231 } |
212 } |
232 |
213 |
233 void addConfig( config* ptr ) |
214 void addConfig (config* ptr) { |
234 { |
215 if (g_cfgPointerCursor == 0) |
235 if( g_cfgPointerCursor == 0 ) |
216 memset (g_configPointers, 0, sizeof g_configPointers); |
236 memset( g_configPointers, 0, sizeof g_configPointers ); |
217 |
237 |
218 assert (g_cfgPointerCursor < MAX_CONFIG); |
238 assert( g_cfgPointerCursor < MAX_CONFIG ); |
|
239 g_configPointers[g_cfgPointerCursor++] = ptr; |
219 g_configPointers[g_cfgPointerCursor++] = ptr; |
240 } |
220 } |