openMSX
SettingsConfig.cc
Go to the documentation of this file.
1 #include "SettingsConfig.hh"
2 #include "XMLLoader.hh"
3 #include "File.hh"
4 #include "FileContext.hh"
5 #include "FileException.hh"
6 #include "CliComm.hh"
7 #include "HotKey.hh"
8 #include "CommandException.hh"
10 #include "TclObject.hh"
11 #include "outer.hh"
12 
13 using std::string;
14 using std::vector;
15 
16 namespace openmsx {
17 
19  GlobalCommandController& globalCommandController,
20  HotKey& hotKey_)
21  : commandController(globalCommandController)
22  , saveSettingsCommand(commandController)
23  , loadSettingsCommand(commandController)
24  , settingsManager(globalCommandController)
25  , hotKey(hotKey_)
26  , mustSaveSettings(false)
27 {
28 }
29 
31 {
32  if (mustSaveSettings) {
33  try {
34  saveSetting();
35  } catch (FileException& e) {
36  commandController.getCliComm().printWarning(
37  "Auto-saving of settings failed: ", e.getMessage());
38  }
39  }
40 }
41 
43 {
44  xmlElement = XMLLoader::load(context.resolve(filename), "settings.dtd");
45  getSettingsManager().loadSettings(xmlElement);
46  hotKey.loadBindings(xmlElement);
47 
48  // only set saveName after file was successfully parsed
49  setSaveFilename(context, filename);
50 }
51 
53 {
54  saveName = context.resolveCreate(filename);
55 }
56 
58 {
59  string_view name = filename.empty() ? saveName : filename;
60  if (name.empty()) return;
61 
62  // Normally the following isn't needed. Only when there was no
63  // settings.xml in either the user or the system directory (so an
64  // incomplete openMSX installation!!) the top level element will have
65  // an empty name. And we shouldn't write an invalid xml file.
66  xmlElement.setName("settings");
67 
68  // settings are kept up-to-date
69  hotKey.saveBindings(xmlElement);
70 
71  File file(name, File::TRUNCATE);
72  string data = "<!DOCTYPE settings SYSTEM 'settings.dtd'>\n" +
73  xmlElement.dump();
74  file.write(data.data(), data.size());
75 }
76 
77 
78 // class SaveSettingsCommand
79 
80 SettingsConfig::SaveSettingsCommand::SaveSettingsCommand(
81  CommandController& commandController_)
82  : Command(commandController_, "save_settings")
83 {
84 }
85 
86 void SettingsConfig::SaveSettingsCommand::execute(
87  span<const TclObject> tokens, TclObject& /*result*/)
88 {
89  checkNumArgs(tokens, Between{1, 2}, Prefix{1}, "?filename?");
90  auto& settingsConfig = OUTER(SettingsConfig, saveSettingsCommand);
91  try {
92  switch (tokens.size()) {
93  case 1:
94  settingsConfig.saveSetting();
95  break;
96  case 2:
97  settingsConfig.saveSetting(tokens[1].getString());
98  break;
99  }
100  } catch (FileException& e) {
101  throw CommandException(std::move(e).getMessage());
102  }
103 }
104 
105 string SettingsConfig::SaveSettingsCommand::help(const vector<string>& /*tokens*/) const
106 {
107  return "Save the current settings.";
108 }
109 
110 void SettingsConfig::SaveSettingsCommand::tabCompletion(vector<string>& tokens) const
111 {
112  if (tokens.size() == 2) {
113  completeFileName(tokens, systemFileContext());
114  }
115 }
116 
117 
118 // class LoadSettingsCommand
119 
120 SettingsConfig::LoadSettingsCommand::LoadSettingsCommand(
121  CommandController& commandController_)
122  : Command(commandController_, "load_settings")
123 {
124 }
125 
126 void SettingsConfig::LoadSettingsCommand::execute(
127  span<const TclObject> tokens, TclObject& /*result*/)
128 {
129  checkNumArgs(tokens, 2, "filename");
130  auto& settingsConfig = OUTER(SettingsConfig, loadSettingsCommand);
131  settingsConfig.loadSetting(systemFileContext(), tokens[1].getString());
132 }
133 
134 string SettingsConfig::LoadSettingsCommand::help(const vector<string>& /*tokens*/) const
135 {
136  return "Load settings from given file.";
137 }
138 
139 void SettingsConfig::LoadSettingsCommand::tabCompletion(vector<string>& tokens) const
140 {
141  if (tokens.size() == 2) {
142  completeFileName(tokens, systemFileContext());
143  }
144 }
145 
146 } // namespace openmsx
std::string resolveCreate(string_view filename) const
Definition: FileContext.cc:84
const std::string & getMessage() const &
Definition: MSXException.hh:23
void setName(std::string name_)
Definition: XMLElement.hh:31
FileContext systemFileContext()
Definition: FileContext.cc:148
Definition: span.hh:34
void loadSettings(const XMLElement &config)
std::string dump() const
Definition: XMLElement.cc:252
std::string resolve(string_view filename) const
Definition: FileContext.cc:76
SettingsManager & getSettingsManager()
constexpr auto data(C &c) -> decltype(c.data())
Definition: span.hh:69
void loadBindings(const XMLElement &config)
Definition: HotKey.cc:173
std::unique_ptr< Context > context
Definition: GLContext.cc:9
void setSaveFilename(const FileContext &context, string_view filename)
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
XMLElement load(string_view filename, string_view systemID)
Definition: XMLLoader.cc:31
void loadSetting(const FileContext &context, string_view filename)
SettingsConfig(GlobalCommandController &globalCommandController, HotKey &hotKey)
bool empty() const
Definition: string_view.hh:45
This class implements a (close approximation) of the std::string_view class.
Definition: string_view.hh:16
virtual CliComm & getCliComm()=0
void write(const void *buffer, size_t num)
Write to file.
Definition: File.cc:88
void saveBindings(XMLElement &config) const
Definition: HotKey.cc:213
#define OUTER(type, member)
Definition: outer.hh:38
void printWarning(string_view message)
Definition: CliComm.cc:20
void saveSetting(string_view filename={})