src/cfg.cpp

changeset 20
a5457405cc9b
child 30
6b82f6a3ad53
equal deleted inserted replaced
19:c9b6dd9dd4cd 20:a5457405cc9b
1 /*
2 * ZanDemo: Zandronum demo launcher
3 * Copyright (C) 2013 Santeri Piippo
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <cassert>
20 #include <QDir>
21 #include <QTextStream>
22 #include <QSettings>
23 #include "main.h"
24 #include "config.h"
25
26 #define MAX_CONFIG 512
27
28 // =============================================================================
29 // -----------------------------------------------------------------------------
30 namespace cfg {
31 static struct {
32 void* ptr;
33 Type type;
34 const char* name;
35 QVariant def;
36 } g_configData[MAX_CONFIG];
37
38 static int g_cfgDataCursor = 0;
39
40 #define CASE(T) case T##Type: return QVariant (*(reinterpret_cast<T*> (ptr)));
41 static QVariant getConfigValue (void* ptr, Type type) {
42 switch (type) {
43 CASE (Int)
44 CASE (String)
45 CASE (Float)
46 CASE (Bool)
47 CASE (List)
48 CASE (Map)
49
50 case KeySeqType:
51 return QVariant (reinterpret_cast<KeySeq*> (ptr)->toString());
52 }
53
54 assert (false);
55 return QVariant();
56 }
57 #undef CASE
58
59 #define CASE(T, METHOD) case T##Type: (*(reinterpret_cast<T*> (ptr))) = val.METHOD(); return;
60 static void setConfigValue (void* ptr, Type type, const QVariant& val) {
61 switch (type) {
62 CASE (Int, toInt)
63 CASE (String, toString)
64 CASE (Float, toFloat)
65 CASE (Bool, toBool)
66 CASE (List, toList)
67 CASE (Map, toMap)
68
69 case KeySeqType:
70 reinterpret_cast<KeySeq*> (ptr)->fromString (val.toString());
71 break;
72 }
73 }
74
75 // =============================================================================
76 // Get the QSettings object.
77 // -----------------------------------------------------------------------------
78 static QSettings* getSettingsObject() {
79 return new QSettings;
80 }
81
82 // =============================================================================
83 // Load the configuration from file
84 // -----------------------------------------------------------------------------
85 bool load() {
86 QSettings* settings = getSettingsObject();
87 print ("config::load: Loading configuration file from %1\n", settings->fileName());
88
89 for (alias i : g_configData) {
90 if (i.name == null)
91 break;
92
93 setConfigValue (i.ptr, i.type, settings->value (i.name, i.def));
94 }
95
96 settings->deleteLater();
97 return true;
98 }
99
100 // =============================================================================
101 // Save the configuration to disk
102 // -----------------------------------------------------------------------------
103 bool save() {
104 QSettings* settings = getSettingsObject();
105 settings->clear();
106 print ("Saving configuration to %1...\n", settings->fileName());
107
108 for (alias i : g_configData) {
109 if (i.name == null)
110 break;
111
112 QVariant val = getConfigValue (i.ptr, i.type);
113
114 if (val == i.def)
115 continue;
116
117 settings->setValue (i.name, val);
118 }
119
120 settings->sync();
121 settings->deleteLater();
122 return true;
123 }
124
125 // =============================================================================
126 // Reset configuration defaults.
127 // -----------------------------------------------------------------------------
128 void reset() {
129 for (alias i : g_configData) {
130 if (i.name == null)
131 break;
132
133 setConfigValue (i.ptr, i.type, i.def);
134 }
135 }
136
137 // =============================================================================
138 // We cannot just add config objects to a list or vector because that would rely
139 // on the vector's c-tor being called before the configs' c-tors. With global
140 // variables we cannot assume that!! Therefore we need to use a C-style array here.
141 // -----------------------------------------------------------------------------
142 ConfigAdder::ConfigAdder (void* ptr, Type type, const char* name, QVariant def) {
143 if (g_cfgDataCursor == 0)
144 memset (g_configData, 0, sizeof g_configData);
145
146 assert (g_cfgDataCursor < MAX_CONFIG);
147 alias i = g_configData[g_cfgDataCursor++];
148 i.ptr = ptr;
149 i.type = type;
150 i.name = name;
151 i.def = def;
152 }
153 }

mercurial