MythTV  master
configuration.cpp
Go to the documentation of this file.
1 // Program Name: configuration.cpp
3 // Created : Feb. 12, 2007
4 //
5 // Purpose : Configuration file Class
6 //
7 // Copyright (c) 2007 David Blain <dblain@mythtv.org>
8 //
9 // Licensed under the GPL v2 or later, see COPYING for details
10 //
12 
13 #include <unistd.h> // for fsync
14 
15 #include <iostream>
16 
17 #include <QDir>
18 #include <QFile>
19 #include <QTextStream>
20 
21 #include "configuration.h"
22 #include "mythlogging.h"
23 #include "mythdb.h"
24 #include "mythdirs.h"
25 #include "compat.h"
26 
28 //
30 
31 XmlConfiguration::XmlConfiguration( const QString &sFileName )
32 {
33  m_sPath = GetConfDir();
34  m_sFileName = sFileName;
35 
37 }
38 
40 //
42 
44 {
45  QString sName = m_sPath + '/' + m_sFileName;
46 
47  QFile file( sName );
48 
49  if (file.exists() && !m_sFileName.isEmpty()) // Ignore empty filenames
50  {
51 
52  if ( !file.open( QIODevice::ReadOnly ) )
53  return false;
54 
55  QString sErrMsg;
56  int nErrLine = 0;
57  int nErrCol = 0;
58  bool bSuccess = m_config.setContent(&file, false, &sErrMsg,
59  &nErrLine, &nErrCol );
60 
61  file.close();
62 
63  if (!bSuccess)
64  {
65  LOG(VB_GENERAL, LOG_ERR,
66  QString("Error parsing: %1 at line: %2 column: %3")
67  .arg( sName ) .arg( nErrLine ) .arg( nErrCol ));
68 
69  LOG(VB_GENERAL, LOG_ERR, QString("Error Msg: %1" ) .arg( sErrMsg ));
70  return false;
71  }
72 
73  m_rootNode = m_config.namedItem( "Configuration" );
74  }
75  else
76  {
77  m_rootNode = m_config.createElement( "Configuration" );
78  m_config.appendChild( m_rootNode );
79  }
80 
81  return true;
82 }
83 
85 //
87 
89 {
90  if (m_sFileName.isEmpty()) // Special case. No file is created
91  return true;
92 
93  QString config_temppath = m_sPath + '/' + m_sFileName + ".new";
94  QString config_filepath = m_sPath + '/' + m_sFileName;
95  QString config_origpath = m_sPath + '/' + m_sFileName + ".orig";
96 
97  QFile file(config_temppath);
98 
99  if (!file.exists())
100  {
101  QDir createDir(m_sPath);
102  if (!createDir.exists())
103  {
104  if (!createDir.mkdir(m_sPath))
105  {
106  LOG(VB_GENERAL, LOG_ERR,
107  QString("Could not create %1").arg(m_sPath));
108  return false;
109  }
110  }
111  }
112 
113  if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate))
114  {
115  LOG(VB_GENERAL, LOG_ERR,
116  QString("Could not open settings file %1 for writing")
117  .arg(config_temppath));
118 
119  return false;
120  }
121 
122  {
123  QTextStream ts(&file);
124  m_config.save(ts, 2);
125  }
126 
127  file.flush();
128 
129  fsync(file.handle());
130 
131  file.close();
132 
133  bool ok = true;
134  if (QFile::exists(config_filepath))
135  ok = QFile::rename(config_filepath, config_origpath);
136 
137  if (ok)
138  {
139  ok = file.rename(config_filepath);
140  if (ok)
141  {
142  if (!QFile::remove(config_origpath))
143  LOG(VB_GENERAL, LOG_WARNING, QString("Failed to remove '%1'").arg(config_origpath));
144  }
145  else if (QFile::exists(config_origpath))
146  {
147  if (!QFile::rename(config_origpath, config_filepath))
148  LOG(VB_GENERAL, LOG_WARNING, QString("Failed to rename '%1").arg(config_origpath));
149  }
150  }
151 
152  if (!ok)
153  {
154  LOG(VB_GENERAL, LOG_ERR,
155  QString("Could not save settings file %1").arg(config_filepath));
156  }
157 
158  return ok;
159 }
160 
162 //
164 
165 QDomNode XmlConfiguration::FindNode( const QString &sName, bool bCreate )
166 {
167 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
168  QStringList parts = sName.split('/', QString::SkipEmptyParts);
169 #else
170  QStringList parts = sName.split('/', Qt::SkipEmptyParts);
171 #endif
172 
173  return FindNode( parts, m_rootNode, bCreate );
174 
175 }
176 
178 //
180 
181 QDomNode XmlConfiguration::FindNode( QStringList &sParts, QDomNode &curNode, bool bCreate )
182 {
183  if (sParts.empty())
184  return curNode;
185 
186  QString sName = sParts.front();
187  sParts.pop_front();
188 
189  QDomNode child = curNode.namedItem( sName );
190 
191  if (child.isNull() )
192  {
193  if (bCreate)
194  {
195  QDomNode newNode = m_config.createElement( sName );
196  if (!curNode.isNull())
197  child = curNode.appendChild( newNode );
198  }
199  else
200  sParts.clear();
201  }
202 
203  return FindNode( sParts, child, bCreate );
204 }
205 
207 //
209 
210 int XmlConfiguration::GetValue( const QString &sSetting, int nDefault )
211 {
212  QDomNode node = FindNode( sSetting );
213 
214  if (!node.isNull())
215  {
216  // -=>TODO: This Always assumes firstChild is a Text Node... should change
217  QDomText oText = node.firstChild().toText();
218 
219  if (!oText.isNull())
220  return oText.nodeValue().toInt();
221  }
222 
223  return nDefault;
224 }
225 
227 //
229 
230 QString XmlConfiguration::GetValue( const QString &sSetting, const QString &sDefault )
231 {
232  QDomNode node = FindNode( sSetting );
233 
234  if (!node.isNull())
235  {
236  // -=>TODO: This Always assumes firstChild is a Text Node... should change
237  QDomText oText = node.firstChild().toText();
238 
239  if (!oText.isNull())
240  return oText.nodeValue();
241  }
242 
243  return sDefault;
244 }
245 
247 //
249 
250 void XmlConfiguration::SetValue( const QString &sSetting, int nValue )
251 {
252  QString sValue = QString::number( nValue );
253  QDomNode node = FindNode( sSetting, true );
254 
255  if (!node.isNull())
256  {
257  QDomText textNode;
258 
259  if (node.hasChildNodes())
260  {
261  // -=>TODO: This Always assumes only child is a Text Node... should change
262  textNode = node.firstChild().toText();
263  textNode.setNodeValue( sValue );
264  }
265  else
266  {
267  textNode = m_config.createTextNode( sValue );
268  node.appendChild( textNode );
269  }
270  }
271 }
272 
274 //
276 
277 void XmlConfiguration::SetValue( const QString &sSetting, const QString& sValue )
278 {
279  QDomNode node = FindNode( sSetting, true );
280 
281  if (!node.isNull())
282  {
283  QDomText textNode;
284 
285  if (node.hasChildNodes())
286  {
287  // -=>TODO: This Always assumes only child is a Text Node... should change
288  textNode = node.firstChild().toText();
289  textNode.setNodeValue( sValue );
290  }
291  else
292  {
293  textNode = m_config.createTextNode( sValue );
294  node.appendChild( textNode );
295  }
296  }
297 }
298 
300 //
302 
303 void XmlConfiguration::ClearValue( const QString &sSetting )
304 {
305  QDomNode node = FindNode(sSetting);
306  if (!node.isNull())
307  {
308  QDomNode parent = node.parentNode();
309  parent.removeChild(node);
310  while (parent.childNodes().count() == 0)
311  {
312  QDomNode next_parent = parent.parentNode();
313  next_parent.removeChild(parent);
314  parent = next_parent;
315  }
316  }
317 }
318 
321 //
322 // Uses MythContext to access settings in Database
323 //
326 
328 {
329  return true;
330 }
331 
333 //
335 
337 {
338  return true;
339 }
340 
342 //
344 
345 int DBConfiguration::GetValue( const QString &sSetting, int nDefault )
346 {
347  return GetMythDB()->GetNumSetting( sSetting, nDefault );
348 }
349 
351 //
353 
354 QString DBConfiguration::GetValue( const QString &sSetting, const QString& sDefault )
355 {
356  return GetMythDB()->GetSetting( sSetting, sDefault );
357 }
358 
360 //
362 
363 void DBConfiguration::SetValue( const QString &sSetting, int nValue )
364 {
365  GetMythDB()->SaveSetting( sSetting, nValue );
366 
367 }
368 
370 //
372 
373 void DBConfiguration::SetValue( const QString &sSetting, const QString& sValue )
374 {
375  GetMythDB()->SaveSetting( sSetting, sValue );
376 }
377 
379 //
381 
382 void DBConfiguration::ClearValue( const QString &sSetting )
383 {
384  GetMythDB()->ClearSetting( sSetting );
385 }
XmlConfiguration::Save
bool Save(void) override
Definition: configuration.cpp:88
XmlConfiguration::m_sFileName
QString m_sFileName
Definition: configuration.h:65
mythdb.h
XmlConfiguration::GetValue
int GetValue(const QString &sSetting, int Default) override
Definition: configuration.cpp:210
DBConfiguration::SetValue
void SetValue(const QString &sSetting, int value) override
Definition: configuration.cpp:363
DBConfiguration::GetValue
int GetValue(const QString &sSetting, int Default) override
Definition: configuration.cpp:345
DBConfiguration::Save
bool Save(void) override
Definition: configuration.cpp:336
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
XmlConfiguration::m_rootNode
QDomNode m_rootNode
Definition: configuration.h:68
GetMythDB
MythDB * GetMythDB(void)
Definition: mythdb.cpp:46
build_compdb.file
file
Definition: build_compdb.py:55
mythdirs.h
XmlConfiguration::m_config
QDomDocument m_config
Definition: configuration.h:67
mythlogging.h
GetConfDir
QString GetConfDir(void)
Definition: mythdirs.cpp:224
XmlConfiguration::SetValue
void SetValue(const QString &sSetting, int value) override
Definition: configuration.cpp:250
compat.h
DBConfiguration::ClearValue
void ClearValue(const QString &sSetting) override
Definition: configuration.cpp:382
DBConfiguration::Load
bool Load(void) override
Definition: configuration.cpp:327
XmlConfiguration::XmlConfiguration
XmlConfiguration(const QString &sFileName)
Definition: configuration.cpp:31
XmlConfiguration::FindNode
QDomNode FindNode(const QString &sName, bool bCreate=false)
Definition: configuration.cpp:165
XmlConfiguration::Load
bool Load(void) override
Definition: configuration.cpp:43
configuration.h
XmlConfiguration::ClearValue
void ClearValue(const QString &sSetting) override
Definition: configuration.cpp:303
fsync
#define fsync(FD)
Definition: compat.h:136
XmlConfiguration::m_sPath
QString m_sPath
Definition: configuration.h:64