/[svn]/gigedit/trunk/src/gigedit/Settings.cpp
ViewVC logotype

Contents of /gigedit/trunk/src/gigedit/Settings.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3831 - (show annotations) (download)
Thu Oct 15 18:08:49 2020 UTC (3 years, 6 months ago) by schoenebeck
File size: 13815 byte(s)
* Main Window: auto save & restore the vertical splitter position.

* Bumped version (1.1.1.svn33).

1 /*
2 Copyright (c) 2014-2020 Christian Schoenebeck
3
4 This file is part of "gigedit" and released under the terms of the
5 GNU General Public License version 2.
6 */
7
8 #include "global.h"
9 #include "Settings.h"
10 #ifdef GLIB_HEADER_FILE
11 # include GLIB_HEADER_FILE(glib.h)
12 #else
13 # include <glib.h>
14 #endif
15 #include <glibmm/keyfile.h>
16 #include <iostream>
17 #include <stdio.h>
18 #include <fstream>
19 #include <string.h>
20
21 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 40) || GTKMM_MAJOR_VERSION < 2
22 # define HAS_GLIB_KEYFILE_SAVE_TO_FILE 0
23 #else
24 # define HAS_GLIB_KEYFILE_SAVE_TO_FILE 1
25 #endif
26
27 static std::string configDir() {
28 //printf("configDir '%s'\n", g_get_user_config_dir());
29 return g_get_user_config_dir();
30 }
31
32 static std::string dirSep() {
33 //printf("sep '%s'\n", G_DIR_SEPARATOR_S);
34 return G_DIR_SEPARATOR_S;
35 }
36
37 static std::string configFile() {
38 return configDir() + dirSep() + "gigedit.conf";
39 }
40
41 static std::string groupName(Settings::Group_t group) {
42 switch (group) {
43 case Settings::GLOBAL: return "Global";
44 case Settings::MAIN_WINDOW: return "MainWindow";
45 case Settings::SCRIPT_EDITOR: return "ScriptEditor";
46 case Settings::DIMENSION_MANAGER: return "DimensionManager";
47 case Settings::SCRIPT_SLOTS: return "ScriptSlots";
48 case Settings::COMBINE_INSTRUMENTS: return "CombineInstruments";
49 case Settings::MIDI_RULES: return "MidiRules";
50 case Settings::FILE_PROPS: return "FileProps";
51 case Settings::INSTR_PROPS: return "InstrProps";
52 case Settings::SAMPLE_PROPS: return "SampleProps";
53 case Settings::SAMPLE_REFS: return "SampleRefs";
54 case Settings::MACRO_EDITOR: return "MacroEditor";
55 case Settings::MACROS_SETUP: return "MacrosSetup";
56 case Settings::MACROS: return "Macros";
57 }
58 return "Global";
59 }
60
61 #if !HAS_GLIB_KEYFILE_SAVE_TO_FILE
62
63 static bool saveToFile(Glib::KeyFile* keyfile, std::string filename) {
64 Glib::ustring s = keyfile->to_data();
65 std::ofstream out;
66 out.open(filename.c_str(), std::ios_base::out | std::ios_base::trunc);
67 out << s;
68 out.close();
69 return true;
70 }
71
72 #endif // ! HAS_GLIB_KEYFILE_SAVE_TO_FILE
73
74 static Settings* _instance = NULL;
75
76 Settings* Settings::singleton() {
77 if (!_instance) {
78 _instance = new Settings;
79 _instance->load();
80 }
81 return _instance;
82 }
83
84 Settings::Settings() : Glib::ObjectBase(typeid(Settings)),
85 warnUserOnExtensions(*this, GLOBAL, "warnUserOnExtensions", true),
86 syncSamplerInstrumentSelection(*this, GLOBAL, "syncSamplerInstrumentSelection", true),
87 moveRootNoteWithRegionMoved(*this, GLOBAL, "moveRootNoteWithRegionMoved", true),
88 autoRestoreWindowDimension(*this, GLOBAL, "autoRestoreWindowDimension", false),
89 saveWithTemporaryFile(*this, GLOBAL, "saveWithTemporaryFile", false),
90 showTooltips(*this, GLOBAL, "showNewbieTooltips", true),
91 instrumentDoubleClickOpensProps(*this, GLOBAL, "openInstrPropsByDoubleClick", true),
92 mainWindowX(*this, MAIN_WINDOW, "x", -1),
93 mainWindowY(*this, MAIN_WINDOW, "y", -1),
94 mainWindowW(*this, MAIN_WINDOW, "w", -1),
95 mainWindowH(*this, MAIN_WINDOW, "h", -1),
96 mainWindowSplitterPosX(*this, MAIN_WINDOW, "splitterPosX", -1),
97 scriptEditorWindowX(*this, SCRIPT_EDITOR, "x", -1),
98 scriptEditorWindowY(*this, SCRIPT_EDITOR, "y", -1),
99 scriptEditorWindowW(*this, SCRIPT_EDITOR, "w", -1),
100 scriptEditorWindowH(*this, SCRIPT_EDITOR, "h", -1),
101 scriptEditorFontSize(*this, SCRIPT_EDITOR, "fontSize", -1),
102 dimensionManagerWindowX(*this, DIMENSION_MANAGER, "x", -1),
103 dimensionManagerWindowY(*this, DIMENSION_MANAGER, "y", -1),
104 dimensionManagerWindowW(*this, DIMENSION_MANAGER, "w", -1),
105 dimensionManagerWindowH(*this, DIMENSION_MANAGER, "h", -1),
106 scriptSlotsWindowX(*this, SCRIPT_SLOTS, "x", -1),
107 scriptSlotsWindowY(*this, SCRIPT_SLOTS, "y", -1),
108 scriptSlotsWindowW(*this, SCRIPT_SLOTS, "w", -1),
109 scriptSlotsWindowH(*this, SCRIPT_SLOTS, "h", -1),
110 combineInstrumentsWindowX(*this, COMBINE_INSTRUMENTS, "x", -1),
111 combineInstrumentsWindowY(*this, COMBINE_INSTRUMENTS, "y", -1),
112 combineInstrumentsWindowW(*this, COMBINE_INSTRUMENTS, "w", -1),
113 combineInstrumentsWindowH(*this, COMBINE_INSTRUMENTS, "h", -1),
114 midiRulesWindowX(*this, MIDI_RULES, "x", -1),
115 midiRulesWindowY(*this, MIDI_RULES, "y", -1),
116 midiRulesWindowW(*this, MIDI_RULES, "w", -1),
117 midiRulesWindowH(*this, MIDI_RULES, "h", -1),
118 filePropsWindowX(*this, FILE_PROPS, "x", -1),
119 filePropsWindowY(*this, FILE_PROPS, "y", -1),
120 filePropsWindowW(*this, FILE_PROPS, "w", -1),
121 filePropsWindowH(*this, FILE_PROPS, "h", -1),
122 instrPropsWindowX(*this, INSTR_PROPS, "x", -1),
123 instrPropsWindowY(*this, INSTR_PROPS, "y", -1),
124 instrPropsWindowW(*this, INSTR_PROPS, "w", -1),
125 instrPropsWindowH(*this, INSTR_PROPS, "h", -1),
126 samplePropsWindowX(*this, SAMPLE_PROPS, "x", -1),
127 samplePropsWindowY(*this, SAMPLE_PROPS, "y", -1),
128 samplePropsWindowW(*this, SAMPLE_PROPS, "w", -1),
129 samplePropsWindowH(*this, SAMPLE_PROPS, "h", -1),
130 sampleRefsWindowX(*this, SAMPLE_REFS, "x", -1),
131 sampleRefsWindowY(*this, SAMPLE_REFS, "y", -1),
132 sampleRefsWindowW(*this, SAMPLE_REFS, "w", -1),
133 sampleRefsWindowH(*this, SAMPLE_REFS, "h", -1),
134 macroEditorWindowX(*this, MACRO_EDITOR, "x", -1),
135 macroEditorWindowY(*this, MACRO_EDITOR, "y", -1),
136 macroEditorWindowW(*this, MACRO_EDITOR, "w", -1),
137 macroEditorWindowH(*this, MACRO_EDITOR, "h", -1),
138 macrosSetupWindowX(*this, MACROS_SETUP, "x", -1),
139 macrosSetupWindowY(*this, MACROS_SETUP, "y", -1),
140 macrosSetupWindowW(*this, MACROS_SETUP, "w", -1),
141 macrosSetupWindowH(*this, MACROS_SETUP, "h", -1),
142 m_ignoreNotifies(false)
143 {
144 m_boolProps.push_back(&warnUserOnExtensions);
145 m_boolProps.push_back(&syncSamplerInstrumentSelection);
146 m_boolProps.push_back(&moveRootNoteWithRegionMoved);
147 m_boolProps.push_back(&autoRestoreWindowDimension);
148 m_boolProps.push_back(&saveWithTemporaryFile);
149 m_boolProps.push_back(&showTooltips);
150 m_boolProps.push_back(&instrumentDoubleClickOpensProps);
151 m_intProps.push_back(&mainWindowX);
152 m_intProps.push_back(&mainWindowY);
153 m_intProps.push_back(&mainWindowW);
154 m_intProps.push_back(&mainWindowH);
155 m_intProps.push_back(&mainWindowSplitterPosX);
156 m_intProps.push_back(&scriptEditorWindowX);
157 m_intProps.push_back(&scriptEditorWindowY);
158 m_intProps.push_back(&scriptEditorWindowW);
159 m_intProps.push_back(&scriptEditorWindowH);
160 m_intProps.push_back(&scriptEditorFontSize);
161 m_intProps.push_back(&dimensionManagerWindowX);
162 m_intProps.push_back(&dimensionManagerWindowY);
163 m_intProps.push_back(&dimensionManagerWindowW);
164 m_intProps.push_back(&dimensionManagerWindowH);
165 m_intProps.push_back(&scriptSlotsWindowX);
166 m_intProps.push_back(&scriptSlotsWindowY);
167 m_intProps.push_back(&scriptSlotsWindowW);
168 m_intProps.push_back(&scriptSlotsWindowH);
169 m_intProps.push_back(&combineInstrumentsWindowX);
170 m_intProps.push_back(&combineInstrumentsWindowY);
171 m_intProps.push_back(&combineInstrumentsWindowW);
172 m_intProps.push_back(&combineInstrumentsWindowH);
173 m_intProps.push_back(&midiRulesWindowX);
174 m_intProps.push_back(&midiRulesWindowY);
175 m_intProps.push_back(&midiRulesWindowW);
176 m_intProps.push_back(&midiRulesWindowH);
177 m_intProps.push_back(&filePropsWindowX);
178 m_intProps.push_back(&filePropsWindowY);
179 m_intProps.push_back(&filePropsWindowW);
180 m_intProps.push_back(&filePropsWindowH);
181 m_intProps.push_back(&instrPropsWindowX);
182 m_intProps.push_back(&instrPropsWindowY);
183 m_intProps.push_back(&instrPropsWindowW);
184 m_intProps.push_back(&instrPropsWindowH);
185 m_intProps.push_back(&samplePropsWindowX);
186 m_intProps.push_back(&samplePropsWindowY);
187 m_intProps.push_back(&samplePropsWindowW);
188 m_intProps.push_back(&samplePropsWindowH);
189 m_intProps.push_back(&sampleRefsWindowX);
190 m_intProps.push_back(&sampleRefsWindowY);
191 m_intProps.push_back(&sampleRefsWindowW);
192 m_intProps.push_back(&sampleRefsWindowH);
193 m_intProps.push_back(&macroEditorWindowX);
194 m_intProps.push_back(&macroEditorWindowY);
195 m_intProps.push_back(&macroEditorWindowW);
196 m_intProps.push_back(&macroEditorWindowH);
197 m_intProps.push_back(&macrosSetupWindowX);
198 m_intProps.push_back(&macrosSetupWindowY);
199 m_intProps.push_back(&macrosSetupWindowW);
200 m_intProps.push_back(&macrosSetupWindowH);
201 }
202
203 void Settings::onPropertyChanged(Glib::PropertyBase* pProperty, RawValueType_t type, Group_t group) {
204 if (m_ignoreNotifies) return;
205
206 //printf("Settings::onPropertyChanged(%s)\n", pProperty->get_name().c_str());
207
208 Glib::KeyFile file;
209 try {
210 bool ok = file.load_from_file(configFile());
211 if (!ok) {
212 std::cerr << "Could not load '" << configFile() << "'\n" << std::flush;
213 }
214 } catch (...) {
215 std::cerr << "Could not load '" << configFile() << "'\n" << std::flush;
216 }
217
218 switch (type) {
219 case BOOLEAN: {
220 Property<bool>* prop = static_cast<Property<bool>*>(pProperty);
221 //std::cout << "Saving bool setting '" << prop->get_name() << "'\n" << std::flush;
222 file.set_boolean(groupName(prop->group()), prop->get_name(), prop->get_value());
223 break;
224 }
225 case INTEGER: {
226 Property<int>* prop = static_cast<Property<int>*>(pProperty);
227 //std::cout << "Saving int setting '" << prop->get_name() << "'\n" << std::flush;
228 file.set_integer(groupName(prop->group()), prop->get_name(), prop->get_value());
229 break;
230 }
231 case UNKNOWN:
232 std::cerr << "BUG: Unknown setting raw type of property '" << pProperty->get_name() << "'\n" << std::flush;
233 return;
234 }
235
236 try {
237 #if HAS_GLIB_KEYFILE_SAVE_TO_FILE
238 bool ok = file.save_to_file(configFile());
239 #else
240 bool ok = saveToFile(&file, configFile());
241 #endif
242 if (!ok) {
243 std::cerr << "Failed saving gigedit config to '" << configFile() << "'\n" << std::flush;
244 } else {
245 //std::cout <<"gigedit CONFIG SAVED\n";
246 }
247 } catch (...) {
248 std::cerr << "Failed saving gigedit config to '" << configFile() << "'\n" << std::flush;
249 }
250 }
251
252 void Settings::load() {
253 Glib::KeyFile file;
254 try {
255 bool ok = file.load_from_file(configFile());
256 if (!ok) return;
257 } catch (...) {
258 std::cerr << "Could not load gigedit config file '" << configFile() << "'\n" << std::flush;
259 return;
260 }
261
262 // ignore onPropertyChanged() calls during updating the property values below
263 m_ignoreNotifies = true;
264
265 for (int i = 0; i < m_boolProps.size(); ++i) {
266 Property<bool>* prop = static_cast<Property<bool>*>(m_boolProps[i]);
267 try {
268 const std::string group = groupName(prop->group());
269 if (!file.has_group(group)) continue;
270 if (!file.has_key(group, prop->get_name())) continue;
271 const bool value = file.get_boolean(group, prop->get_name());
272 prop->set_value(value);
273 } catch (...) {
274 continue;
275 }
276 }
277
278 for (int i = 0; i < m_intProps.size(); ++i) {
279 Property<int>* prop = static_cast<Property<int>*>(m_intProps[i]);
280 try {
281 const std::string group = groupName(prop->group());
282 if (!file.has_group(group)) continue;
283 if (!file.has_key(group, prop->get_name())) continue;
284 const int value = file.get_integer(group, prop->get_name());
285 prop->set_value(value);
286 } catch (...) {
287 continue;
288 }
289 }
290
291 m_ignoreNotifies = false;
292 }
293
294 #define MACRO_LIST_NAME "srlzl"
295
296 void Settings::loadMacros(std::vector<Serialization::Archive>& macros) {
297 const std::string group = groupName(MACROS);
298 macros.clear();
299 Glib::KeyFile file;
300 try {
301 bool ok = file.load_from_file(configFile());
302 if (!ok) return;
303 } catch (...) {
304 std::cerr << "Could not load gigedit config file '" << configFile() << "'\n" << std::flush;
305 return;
306 }
307 if (!file.has_group(group)) return;
308 if (!file.has_key(group, MACRO_LIST_NAME))
309 return;
310 std::vector<Glib::ustring> v = file.get_string_list(group, MACRO_LIST_NAME);
311 for (int i = 0; i < v.size(); ++i) {
312 Serialization::Archive macro;
313 macro.decode((const uint8_t*)v[i].c_str(), v[i].length());
314 macros.push_back(macro);
315 }
316 }
317
318 void Settings::saveMacros(const std::vector<Serialization::Archive>& macros) {
319 const std::string group = groupName(MACROS);
320 Glib::KeyFile file;
321 try {
322 bool ok = file.load_from_file(configFile());
323 if (!ok) {
324 std::cerr << "Could not load '" << configFile() << "'\n" << std::flush;
325 }
326 } catch (...) {
327 std::cerr << "Could not load '" << configFile() << "'\n" << std::flush;
328 return;
329 }
330
331 std::vector<Glib::ustring> v;
332 for (int i = 0; i < macros.size(); ++i) {
333 const Serialization::RawData& rawData = const_cast<Serialization::Archive&>(macros[i]).rawData();
334 std::string s((const char*)&rawData[0], rawData.size());
335 v.push_back(s);
336 }
337
338 file.set_string_list(group, MACRO_LIST_NAME, v);
339
340 try {
341 #if HAS_GLIB_KEYFILE_SAVE_TO_FILE
342 bool ok = file.save_to_file(configFile());
343 #else
344 bool ok = saveToFile(&file, configFile());
345 #endif
346 if (!ok) {
347 std::cerr << "Failed saving gigedit config to '" << configFile() << "'\n" << std::flush;
348 } else {
349 //std::cout <<"gigedit CONFIG SAVED\n";
350 }
351 } catch (...) {
352 std::cerr << "Failed saving gigedit config to '" << configFile() << "'\n" << std::flush;
353 }
354
355 }

  ViewVC Help
Powered by ViewVC