Qt 4.8
qsettings_mac.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qsettings.h"
43 #include "qsettings_p.h"
44 #include "qdatetime.h"
45 #include "qdir.h"
46 #include "qvarlengtharray.h"
47 #include "private/qcore_mac_p.h"
48 #ifndef QT_BOOTSTRAPPED
49 #include "qcoreapplication.h"
50 #endif
51 #if __MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
52 #include <Security/SecCode.h>
53 #include <Security/SecRequirement.h>
54 #endif
55 
57 
58 static const CFStringRef hostNames[2] = { kCFPreferencesCurrentHost, kCFPreferencesAnyHost };
59 static const int numHostNames = 2;
60 
61 /*
62  On the Mac, it is more natural to use '.' as the key separator
63  than '/'. Therefore, it makes sense to replace '/' with '.' in
64  keys. Then we replace '.' with middle dots (which we can't show
65  here) and middle dots with '/'. A key like "4.0/BrowserCommand"
66  becomes "4<middot>0.BrowserCommand".
67 */
68 
69 enum RotateShift { Macify = 1, Qtify = 2 };
70 
72 {
73  static const int NumKnights = 3;
74  static const char knightsOfTheRoundTable[NumKnights] = { '/', '.', '\xb7' };
75  QString result = key;
76 
77  for (int i = 0; i < result.size(); ++i) {
78  for (int j = 0; j < NumKnights; ++j) {
79  if (result.at(i) == QLatin1Char(knightsOfTheRoundTable[j])) {
80  result[i] = QLatin1Char(knightsOfTheRoundTable[(j + shift) % NumKnights]).unicode();
81  break;
82  }
83  }
84  }
85  return result;
86 }
87 
89 {
91 }
92 
93 static QString qtKey(CFStringRef cfkey)
94 {
96 }
97 
98 static QCFType<CFPropertyListRef> macValue(const QVariant &value);
99 
100 static CFArrayRef macList(const QList<QVariant> &list)
101 {
102  int n = list.size();
104  for (int i = 0; i < n; ++i)
105  cfvalues[i] = macValue(list.at(i));
106  return CFArrayCreate(kCFAllocatorDefault, reinterpret_cast<const void **>(cfvalues.data()),
107  CFIndex(n), &kCFTypeArrayCallBacks);
108 }
109 
111 {
112  CFPropertyListRef result = 0;
113 
114  switch (value.type()) {
115  case QVariant::ByteArray:
116  {
117  QByteArray ba = value.toByteArray();
118  result = CFDataCreate(kCFAllocatorDefault, reinterpret_cast<const UInt8 *>(ba.data()),
119  CFIndex(ba.size()));
120  }
121  break;
122  // should be same as below (look for LIST)
123  case QVariant::List:
125  case QVariant::Polygon:
126  result = macList(value.toList());
127  break;
128  case QVariant::Map:
129  {
130  /*
131  QMap<QString, QVariant> is potentially a multimap,
132  whereas CFDictionary is a single-valued map. To allow
133  for multiple values with the same key, we store
134  multiple values in a CFArray. To avoid ambiguities,
135  we also wrap lists in a CFArray singleton.
136  */
139 
140  int maxUniqueKeys = map.size();
141  int numUniqueKeys = 0;
142  QVarLengthArray<QCFType<CFPropertyListRef> > cfkeys(maxUniqueKeys);
143  QVarLengthArray<QCFType<CFPropertyListRef> > cfvalues(maxUniqueKeys);
144 
145  while (i != map.constEnd()) {
146  const QString &key = i.key();
148 
149  do {
150  values << i.value();
151  ++i;
152  } while (i != map.constEnd() && i.key() == key);
153 
154  bool singleton = (values.count() == 1);
155  if (singleton) {
156  switch (values.first().type()) {
157  // should be same as above (look for LIST)
158  case QVariant::List:
160  case QVariant::Polygon:
161  singleton = false;
162  default:
163  ;
164  }
165  }
166 
167  cfkeys[numUniqueKeys] = QCFString::toCFStringRef(key);
168  cfvalues[numUniqueKeys] = singleton ? macValue(values.first()) : macList(values);
169  ++numUniqueKeys;
170  }
171 
172  result = CFDictionaryCreate(kCFAllocatorDefault,
173  reinterpret_cast<const void **>(cfkeys.data()),
174  reinterpret_cast<const void **>(cfvalues.data()),
175  CFIndex(numUniqueKeys),
176  &kCFTypeDictionaryKeyCallBacks,
177  &kCFTypeDictionaryValueCallBacks);
178  }
179  break;
180  case QVariant::DateTime:
181  {
182  /*
183  CFDate, unlike QDateTime, doesn't store timezone information.
184  */
185  QDateTime dt = value.toDateTime();
186  if (dt.timeSpec() == Qt::LocalTime) {
187  QDateTime reference;
188  reference.setTime_t((uint)kCFAbsoluteTimeIntervalSince1970);
189  result = CFDateCreate(kCFAllocatorDefault, CFAbsoluteTime(reference.secsTo(dt)));
190  } else {
191  goto string_case;
192  }
193  }
194  break;
195  case QVariant::Bool:
196  result = value.toBool() ? kCFBooleanTrue : kCFBooleanFalse;
197  break;
198  case QVariant::Int:
199  case QVariant::UInt:
200  {
201  int n = value.toInt();
202  result = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &n);
203  }
204  break;
205  case QVariant::Double:
206  {
207  double n = value.toDouble();
208  result = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &n);
209  }
210  break;
211  case QVariant::LongLong:
212  case QVariant::ULongLong:
213  {
214  qint64 n = value.toLongLong();
215  result = CFNumberCreate(0, kCFNumberLongLongType, &n);
216  }
217  break;
218  case QVariant::String:
219  string_case:
220  default:
222  }
223  return result;
224 }
225 
226 static QVariant qtValue(CFPropertyListRef cfvalue)
227 {
228  if (!cfvalue)
229  return QVariant();
230 
231  CFTypeID typeId = CFGetTypeID(cfvalue);
232 
233  /*
234  Sorted grossly from most to least frequent type.
235  */
236  if (typeId == CFStringGetTypeID()) {
237  return QSettingsPrivate::stringToVariant(QCFString::toQString(static_cast<CFStringRef>(cfvalue)));
238  } else if (typeId == CFNumberGetTypeID()) {
239  CFNumberRef cfnumber = static_cast<CFNumberRef>(cfvalue);
240  if (CFNumberIsFloatType(cfnumber)) {
241  double d;
242  CFNumberGetValue(cfnumber, kCFNumberDoubleType, &d);
243  return d;
244  } else {
245  int i;
246  qint64 ll;
247 
248  if (CFNumberGetValue(cfnumber, kCFNumberIntType, &i))
249  return i;
250  CFNumberGetValue(cfnumber, kCFNumberLongLongType, &ll);
251  return ll;
252  }
253  } else if (typeId == CFArrayGetTypeID()) {
254  CFArrayRef cfarray = static_cast<CFArrayRef>(cfvalue);
255  QList<QVariant> list;
256  CFIndex size = CFArrayGetCount(cfarray);
257  bool metNonString = false;
258  for (CFIndex i = 0; i < size; ++i) {
259  QVariant value = qtValue(CFArrayGetValueAtIndex(cfarray, i));
260  if (value.type() != QVariant::String)
261  metNonString = true;
262  list << value;
263  }
264  if (metNonString)
265  return list;
266  else
267  return QVariant(list).toStringList();
268  } else if (typeId == CFBooleanGetTypeID()) {
269  return (bool)CFBooleanGetValue(static_cast<CFBooleanRef>(cfvalue));
270  } else if (typeId == CFDataGetTypeID()) {
271  CFDataRef cfdata = static_cast<CFDataRef>(cfvalue);
272  return QByteArray(reinterpret_cast<const char *>(CFDataGetBytePtr(cfdata)),
273  CFDataGetLength(cfdata));
274  } else if (typeId == CFDictionaryGetTypeID()) {
275  CFDictionaryRef cfdict = static_cast<CFDictionaryRef>(cfvalue);
276  CFTypeID arrayTypeId = CFArrayGetTypeID();
277  int size = (int)CFDictionaryGetCount(cfdict);
280  CFDictionaryGetKeysAndValues(cfdict, keys.data(), values.data());
281 
283  for (int i = 0; i < size; ++i) {
284  QString key = QCFString::toQString(static_cast<CFStringRef>(keys[i]));
285 
286  if (CFGetTypeID(values[i]) == arrayTypeId) {
287  CFArrayRef cfarray = static_cast<CFArrayRef>(values[i]);
288  CFIndex arraySize = CFArrayGetCount(cfarray);
289  for (CFIndex j = arraySize - 1; j >= 0; --j)
290  map.insert(key, qtValue(CFArrayGetValueAtIndex(cfarray, j)));
291  } else {
292  map.insert(key, qtValue(values[i]));
293  }
294  }
295  return map;
296  } else if (typeId == CFDateGetTypeID()) {
297  QDateTime dt;
298  dt.setTime_t((uint)kCFAbsoluteTimeIntervalSince1970);
299  return dt.addSecs((int)CFDateGetAbsoluteTime(static_cast<CFDateRef>(cfvalue)));
300  }
301  return QVariant();
302 }
303 
304 static QString comify(const QString &organization)
305 {
306  for (int i = organization.size() - 1; i >= 0; --i) {
307  QChar ch = organization.at(i);
308  if (ch == QLatin1Char('.') || ch == QChar(0x3002) || ch == QChar(0xff0e)
309  || ch == QChar(0xff61)) {
310  QString suffix = organization.mid(i + 1).toLower();
311  if (suffix.size() == 2 || suffix == QLatin1String("com")
312  || suffix == QLatin1String("org") || suffix == QLatin1String("net")
313  || suffix == QLatin1String("edu") || suffix == QLatin1String("gov")
314  || suffix == QLatin1String("mil") || suffix == QLatin1String("biz")
315  || suffix == QLatin1String("info") || suffix == QLatin1String("name")
316  || suffix == QLatin1String("pro") || suffix == QLatin1String("aero")
317  || suffix == QLatin1String("coop") || suffix == QLatin1String("museum")) {
318  QString result = organization;
319  result.replace(QLatin1Char('/'), QLatin1Char(' '));
320  return result;
321  }
322  break;
323  }
324  int uc = ch.unicode();
325  if ((uc < 'a' || uc > 'z') && (uc < 'A' || uc > 'Z'))
326  break;
327  }
328 
329  QString domain;
330  for (int i = 0; i < organization.size(); ++i) {
331  QChar ch = organization.at(i);
332  int uc = ch.unicode();
333  if ((uc >= 'a' && uc <= 'z') || (uc >= '0' && uc <= '9')) {
334  domain += ch;
335  } else if (uc >= 'A' && uc <= 'Z') {
336  domain += ch.toLower();
337  } else {
338  domain += QLatin1Char(' ');
339  }
340  }
341  domain = domain.simplified();
342  domain.replace(QLatin1Char(' '), QLatin1Char('-'));
343  if (!domain.isEmpty())
344  domain.append(QLatin1String(".com"));
345  return domain;
346 }
347 
349 {
350 public:
351  QMacSettingsPrivate(QSettings::Scope scope, const QString &organization,
352  const QString &application);
353  QMacSettingsPrivate(CFStringRef bundleIdentifier);
355 
356  void remove(const QString &key);
357  void set(const QString &key, const QVariant &value);
358  bool get(const QString &key, QVariant *value) const;
359  QStringList children(const QString &prefix, ChildSpec spec) const;
360  void clear();
361  void sync();
362  void flush();
363  bool isWritable() const;
364  QString fileName() const;
365 
366 private:
368  {
371  };
372 
378 };
379 
381  const QString &application)
382  : QSettingsPrivate(QSettings::NativeFormat, scope, organization, application)
383 {
384  QString javaPackageName;
385  int curPos = 0;
386  int nextDot;
387 
388  QString domainName = comify(organization);
389  if (domainName.isEmpty()) {
391  domainName = QLatin1String("unknown-organization.trolltech.com");
392  }
393 
394  while ((nextDot = domainName.indexOf(QLatin1Char('.'), curPos)) != -1) {
395  javaPackageName.prepend(domainName.mid(curPos, nextDot - curPos));
396  javaPackageName.prepend(QLatin1Char('.'));
397  curPos = nextDot + 1;
398  }
399  javaPackageName.prepend(domainName.mid(curPos));
400  javaPackageName = javaPackageName.toLower();
401  if (curPos == 0)
402  javaPackageName.prepend(QLatin1String("com."));
403  suiteId = javaPackageName;
404 
405  if (scope == QSettings::SystemScope)
406  spec |= F_System;
407 
408  if (application.isEmpty()) {
409  spec |= F_Organization;
410  } else {
411  javaPackageName += QLatin1Char('.');
412  javaPackageName += application;
413  applicationId = javaPackageName;
414  }
415 
416  numDomains = 0;
417  for (int i = (spec & F_System) ? 1 : 0; i < 2; ++i) {
418  for (int j = (spec & F_Organization) ? 1 : 0; j < 3; ++j) {
419  SearchDomain &domain = domains[numDomains++];
420  domain.userName = (i == 0) ? kCFPreferencesCurrentUser : kCFPreferencesAnyUser;
421  if (j == 0)
423  else if (j == 1)
424  domain.applicationOrSuiteId = suiteId;
425  else
426  domain.applicationOrSuiteId = kCFPreferencesAnyApplication;
427  }
428  }
429 
430  hostName = (scope == QSettings::SystemScope) ? kCFPreferencesCurrentHost : kCFPreferencesAnyHost;
431  sync();
432 }
433 
435  : QSettingsPrivate(QSettings::NativeFormat, QSettings::UserScope, QString(), QString())
436 {
437  // applicationId and suiteId are QCFStrings and take ownership, retain to prevent double deletes.
438  CFRetain(bundleIdentifier);
439  applicationId = bundleIdentifier;
440  CFRetain(bundleIdentifier);
441  suiteId = bundleIdentifier;
442 
443  numDomains = 1;
444  domains[0].userName = kCFPreferencesCurrentUser;
445  domains[0].applicationOrSuiteId = bundleIdentifier;
446  hostName = kCFPreferencesAnyHost;
447  sync();
448 }
449 
451 {
452 }
453 
455 {
457 
458  // If i == -1, then delete "key" itself.
459  for (int i = -1; i < keys.size(); ++i) {
460  QString subKey = key;
461  if (i >= 0) {
462  subKey += QLatin1Char('/');
463  subKey += keys.at(i);
464  }
465  CFPreferencesSetValue(macKey(subKey), 0, domains[0].applicationOrSuiteId,
466  domains[0].userName, hostName);
467  }
468 }
469 
470 void QMacSettingsPrivate::set(const QString &key, const QVariant &value)
471 {
472  CFPreferencesSetValue(macKey(key), macValue(value), domains[0].applicationOrSuiteId,
473  domains[0].userName, hostName);
474 }
475 
476 bool QMacSettingsPrivate::get(const QString &key, QVariant *value) const
477 {
478  QCFString k = macKey(key);
479  for (int i = 0; i < numDomains; ++i) {
480  for (int j = 0; j < numHostNames; ++j) {
482  CFPreferencesCopyValue(k, domains[i].applicationOrSuiteId, domains[i].userName,
483  hostNames[j]);
484  if (ret) {
485  if (value)
486  *value = qtValue(ret);
487  return true;
488  }
489  }
490 
491  if (!fallbacks)
492  break;
493  }
494  return false;
495 }
496 
498 {
499  QMap<QString, QString> result;
500  int startPos = prefix.size();
501 
502  for (int i = 0; i < numDomains; ++i) {
503  for (int j = 0; j < numHostNames; ++j) {
504  QCFType<CFArrayRef> cfarray = CFPreferencesCopyKeyList(domains[i].applicationOrSuiteId,
505  domains[i].userName,
506  hostNames[j]);
507  if (cfarray) {
508  CFIndex size = CFArrayGetCount(cfarray);
509  for (CFIndex k = 0; k < size; ++k) {
510  QString currentKey =
511  qtKey(static_cast<CFStringRef>(CFArrayGetValueAtIndex(cfarray, k)));
512  if (currentKey.startsWith(prefix))
513  processChild(currentKey.mid(startPos), spec, result);
514  }
515  }
516  }
517 
518  if (!fallbacks)
519  break;
520  }
521  return result.keys();
522 }
523 
525 {
526  QCFType<CFArrayRef> cfarray = CFPreferencesCopyKeyList(domains[0].applicationOrSuiteId,
527  domains[0].userName, hostName);
528  CFPreferencesSetMultiple(0, cfarray, domains[0].applicationOrSuiteId, domains[0].userName,
529  hostName);
530 }
531 
533 {
534  for (int i = 0; i < numDomains; ++i) {
535  for (int j = 0; j < numHostNames; ++j) {
536  Boolean ok = CFPreferencesSynchronize(domains[i].applicationOrSuiteId,
537  domains[i].userName, hostNames[j]);
538  // only report failures for the primary file (the one we write to)
539  if (!ok && i == 0 && hostNames[j] == hostName && status == QSettings::NoError) {
540 #if 1
541  // work around what seems to be a bug in CFPreferences:
542  // don't report an error if there are no preferences for the application
543  QCFType<CFArrayRef> appIds = CFPreferencesCopyApplicationList(domains[i].userName,
544  hostNames[j]);
545 
546  // iterate through all the applications and see if we're there
547  CFIndex size = CFArrayGetCount(appIds);
548  for (CFIndex k = 0; k < size; ++k) {
549  const void *cfvalue = CFArrayGetValueAtIndex(appIds, k);
550  if (CFGetTypeID(cfvalue) == CFStringGetTypeID()) {
551  if (CFStringCompare(static_cast<CFStringRef>(cfvalue),
552  domains[i].applicationOrSuiteId,
553  kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
555  break;
556  }
557  }
558  }
559 #else
561 #endif
562  }
563  }
564  }
565 }
566 
568 {
569  sync();
570 }
571 
573 {
574  QMacSettingsPrivate *that = const_cast<QMacSettingsPrivate *>(this);
575  QString impossibleKey(QLatin1String("qt_internal/"));
576 
577  QSettings::Status oldStatus = that->status;
578  that->status = QSettings::NoError;
579 
580  that->set(impossibleKey, QVariant());
581  that->sync();
582  bool writable = (status == QSettings::NoError) && that->get(impossibleKey, 0);
583  that->remove(impossibleKey);
584  that->sync();
585 
586  that->status = oldStatus;
587  return writable;
588 }
589 
591 {
592  QString result;
593  if ((spec & F_System) == 0)
594  result = QDir::homePath();
595  result += QLatin1String("/Library/Preferences/");
596  result += QCFString::toQString(domains[0].applicationOrSuiteId);
597  result += QLatin1String(".plist");
598  return result;
599 }
600 
603  const QString &organization,
604  const QString &application)
605 {
606 #ifndef QT_BOOTSTRAPPED
607  static bool useAppLocalStorage = false;
608  static bool initialized = false;
609 
610  if (!initialized) {
611  bool inSandbox = false;
612 
613 #if __MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
614  // If we are running on at least 10.7.0 and have the com.apple.security.app-sandbox
615  // entitlement, we are in a sandbox
616  SInt32 version = 0;
617  Gestalt(gestaltSystemVersion, &version);
618  SecCodeRef secCodeSelf;
619  if (version >= 0x1070 && SecCodeCopySelf(kSecCSDefaultFlags, &secCodeSelf) == errSecSuccess) {
620  SecRequirementRef sandboxReq;
621  CFStringRef entitlement = CFSTR("entitlement [\"com.apple.security.app-sandbox\"]");
622  if (SecRequirementCreateWithString(entitlement, kSecCSDefaultFlags, &sandboxReq) == errSecSuccess) {
623  if (SecCodeCheckValidity(secCodeSelf, kSecCSDefaultFlags, sandboxReq) == errSecSuccess)
624  inSandbox = true;
625  CFRelease(sandboxReq);
626  }
627  CFRelease(secCodeSelf);
628  }
629 #endif
630 
631  bool forAppStore = false;
632  if (!inSandbox) {
633  CFTypeRef val = CFBundleGetValueForInfoDictionaryKey(CFBundleGetMainBundle(), CFSTR("ForAppStore"));
634  forAppStore = (val &&
635  CFGetTypeID(val) == CFStringGetTypeID() &&
636  CFStringCompare(CFStringRef(val), CFSTR("yes"), kCFCompareCaseInsensitive) == 0);
637  }
638 
639  useAppLocalStorage = inSandbox || forAppStore;
640  initialized = true;
641  }
642 
643  if (useAppLocalStorage) {
644  // Ensure that the global and app-local settings go to the same file, since that's
645  // what we really want
646  if (organization == QLatin1String("Trolltech") ||
647  organization.isEmpty() ||
648  (organization == qApp->organizationDomain() && application == qApp->applicationName()) ||
649  (organization == qApp->organizationName()) && application == qApp->applicationName())
650  {
651  CFStringRef bundleIdentifier = CFBundleGetIdentifier(CFBundleGetMainBundle());
652  if (!bundleIdentifier) {
653  qWarning("QSettingsPrivate::create: You must set the bundle identifier when using ForAppStore");
654  } else {
655  QSettingsPrivate* settings = new QMacSettingsPrivate(bundleIdentifier);
656  if (organization == QLatin1String("Trolltech"))
657  settings->beginGroupOrArray(QSettingsGroup("QtLibrarySettings"));
658  return settings;
659  }
660  }
661  }
662 #endif
663 
664  if (format == QSettings::NativeFormat) {
665  return new QMacSettingsPrivate(scope, organization, application);
666  } else {
667  return new QConfFileSettingsPrivate(format, scope, organization, application);
668  }
669 }
670 
672 {
673  return CFURLCreateWithFileSystemPath(kCFAllocatorDefault, QCFString(fileName),
674  kCFURLPOSIXPathStyle, false);
675 }
676 
678 {
679  QCFType<CFDataRef> resource;
680  SInt32 code;
681  if (!CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault, urlFromFileName(fileName),
682  &resource, 0, 0, &code))
683  return false;
684 
685  QCFString errorStr;
686  QCFType<CFPropertyListRef> propertyList =
687  CFPropertyListCreateFromXMLData(kCFAllocatorDefault, resource, kCFPropertyListImmutable,
688  &errorStr);
689 
690  if (!propertyList)
691  return true;
692  if (CFGetTypeID(propertyList) != CFDictionaryGetTypeID())
693  return false;
694 
695  CFDictionaryRef cfdict =
696  static_cast<CFDictionaryRef>(static_cast<CFPropertyListRef>(propertyList));
697  int size = (int)CFDictionaryGetCount(cfdict);
700  CFDictionaryGetKeysAndValues(cfdict, keys.data(), values.data());
701 
702  for (int i = 0; i < size; ++i) {
703  QString key = qtKey(static_cast<CFStringRef>(keys[i]));
704  map->insert(QSettingsKey(key, Qt::CaseSensitive), qtValue(values[i]));
705  }
706  return true;
707 }
708 
710  const ParsedSettingsMap &map) const
711 {
714  int i = 0;
716  for (j = map.constBegin(); j != map.constEnd(); ++j) {
717  cfkeys[i] = macKey(j.key());
718  cfvalues[i] = macValue(j.value());
719  ++i;
720  }
721 
722  QCFType<CFDictionaryRef> propertyList =
723  CFDictionaryCreate(kCFAllocatorDefault,
724  reinterpret_cast<const void **>(cfkeys.data()),
725  reinterpret_cast<const void **>(cfvalues.data()),
726  CFIndex(map.size()),
727  &kCFTypeDictionaryKeyCallBacks,
728  &kCFTypeDictionaryValueCallBacks);
729 
730  QCFType<CFDataRef> xmlData = CFPropertyListCreateXMLData(kCFAllocatorDefault, propertyList);
731 
732  SInt32 code;
733  return CFURLWriteDataAndPropertiesToResource(urlFromFileName(fileName), xmlData, 0, &code);
734 }
735 
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:92
The QMultiMap class is a convenience QMap subclass that provides multi-valued maps.
Definition: qcontainerfwd.h:59
Scope
) in file paths:
Definition: qsettings.h:115
QDateTime addSecs(int secs) const
Returns a QDateTime object containing a datetime s seconds later than the datetime of this object (or...
Definition: qdatetime.cpp:2869
SearchDomain domains[6]
bool get(const QString &key, QVariant *value) const
double d
Definition: qnumeric_p.h:62
void setStatus(QSettings::Status status) const
Definition: qsettings.cpp:410
const struct __CFString * CFStringRef
Status
The following status values are possible:
Definition: qsettings.h:86
static ShiftResult shift(const QBezier *orig, QBezier *shifted, qreal offset, qreal threshold)
Definition: qbezier.cpp:289
void set(const QString &key, const QVariant &value)
bool readPlistFile(const QString &fileName, ParsedSettingsMap *map) const
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
const Key key(const T &value) const
Returns the first key with value value.
Definition: qmap.h:844
char * data()
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:429
const QChar at(int i) const
Returns the character at the given index position in the string.
Definition: qstring.h:698
QMap< QString, QVariant > toMap() const
Returns the variant as a QMap<QString, QVariant> if the variant has type() Map ; otherwise returns an...
Definition: qvariant.cpp:2281
static QVariant qtValue(CFPropertyListRef cfvalue)
ushort unicode() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: qchar.h:251
The QSettings class provides persistent platform-independent application settings.
Definition: qsettings.h:73
static QString comify(const QString &organization)
QString & replace(int i, int len, QChar after)
Definition: qstring.cpp:2005
static QCFType< CFStringRef > macKey(const QString &key)
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
Format
This enum type specifies the storage format used by QSettings.
Definition: qsettings.h:92
QString & prepend(QChar c)
Definition: qstring.h:261
QMacSettingsPrivate(QSettings::Scope scope, const QString &organization, const QString &application)
RotateShift
static CFStringRef toCFStringRef(const QString &str)
Definition: qcore_mac.cpp:69
int size() const
Returns the number of (key, value) pairs in the map.
Definition: qmap.h:201
QDateTime toDateTime() const
Returns the variant as a QDateTime if the variant has type() DateTime , Date , or String ; otherwise ...
Definition: qvariant.cpp:2349
static QString toQString(CFStringRef cfstr)
Definition: qcore_mac.cpp:47
bool writePlistFile(const QString &fileName, const ParsedSettingsMap &map) const
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition: qstring.cpp:3734
QSettings::Scope scope
Definition: qsettings_p.h:259
QList< QVariant > toList() const
Returns the variant as a QVariantList if the variant has type() List or StringList ; otherwise return...
Definition: qvariant.cpp:2751
static QCFType< CFURLRef > urlFromFileName(const QString &fileName)
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
bool toBool() const
Returns the variant as a bool if the variant has type() Bool.
Definition: qvariant.cpp:2691
QString fileName() const
int count(const T &t) const
Returns the number of occurrences of value in the list.
Definition: qlist.h:891
void remove(const QString &key)
The QString class provides a Unicode character string.
Definition: qstring.h:83
static QSettingsPrivate * create(QSettings::Format format, QSettings::Scope scope, const QString &organization, const QString &application)
The QChar class provides a 16-bit Unicode character.
Definition: qchar.h:72
QStringList keys
QByteArray toByteArray() const
Returns the variant as a QByteArray if the variant has type() ByteArray or String (converted using QS...
Definition: qvariant.cpp:2383
int toInt(bool *ok=0) const
Returns the variant as an int if the variant has type() Int , Bool , ByteArray , Char ...
Definition: qvariant.cpp:2625
QStringList toStringList() const
Returns the variant as a QStringList if the variant has type() StringList, String ...
Definition: qvariant.cpp:2259
QFuture< void > map(Sequence &sequence, MapFunction function)
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
qlonglong toLongLong(bool *ok=0) const
Returns the variant as a long long int if the variant has type() LongLong , Bool , ByteArray , Char , Double , Int , String , UInt , or ULongLong ; otherwise returns 0.
Definition: qvariant.cpp:2659
static QCFType< CFPropertyListRef > macValue(const QVariant &value)
void setTime_t(uint secsSince1Jan1970UTC)
Sets the date and time given the number of seconds that have passed since 1970-01-01T00:00:00, Coordinated Universal Time (Qt::UTC).
Definition: qdatetime.cpp:2566
int size() const
Returns the number of characters in this string.
Definition: qstring.h:102
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
#define qApp
void beginGroupOrArray(const QSettingsGroup &group)
Definition: qsettings.cpp:396
static const int numHostNames
const T value(const Key &key) const
Returns the value associated with the key key.
Definition: qmap.h:499
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
int secsTo(const QDateTime &) const
Returns the number of seconds from this datetime to the other datetime.
Definition: qdatetime.cpp:2914
Q_CORE_EXPORT void qWarning(const char *,...)
unsigned int uint
Definition: qglobal.h:996
int indexOf(QChar c, int from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.cpp:2838
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal...
Definition: qstring.h:654
QList< Key > keys() const
Returns a list containing all the keys in the map in ascending order.
Definition: qmap.h:818
__int64 qint64
Definition: qglobal.h:942
static QString variantToString(const QVariant &v)
Definition: qsettings.cpp:464
quint16 values[128]
const_iterator constBegin() const
Returns a const STL-style iterator pointing to the first item in the map.
Definition: qmap.h:374
const void * CFTypeRef
ushort unicode() const
Converts a Latin-1 character to an 16-bit-encoded Unicode representation of the character.
Definition: qchar.h:64
static const CFStringRef hostNames[2]
T & first()
Returns a reference to the first item in the list.
Definition: qlist.h:282
QString mid(int position, int n=-1) const Q_REQUIRED_RESULT
Returns a string that contains n characters of this string, starting at the specified position index...
Definition: qstring.cpp:3706
static QString rotateSlashesDotsAndMiddots(const QString &key, int shift)
const_iterator constEnd() const
Returns a const STL-style iterator pointing to the imaginary item after the last item in the map...
Definition: qmap.h:380
QString & append(QChar c)
Definition: qstring.cpp:1777
The QDateTime class provides date and time functions.
Definition: qdatetime.h:216
QString simplified() const Q_REQUIRED_RESULT
Returns a string that has whitespace removed from the start and the end, and that has each sequence o...
Definition: qstring.cpp:4415
Type type() const
Returns the storage type of the value stored in the variant.
Definition: qvariant.cpp:1901
iterator insert(const Key &key, const T &value)
Inserts a new item with the key key and a value of value.
Definition: qmap.h:559
int key
QString toLower() const Q_REQUIRED_RESULT
Returns a lowercase copy of the string.
Definition: qstring.cpp:5389
Qt::TimeSpec timeSpec() const
Returns the time specification of the datetime.
Definition: qdatetime.cpp:2379
QByteArray suffix
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
int size() const
Returns the number of bytes in this byte array.
Definition: qbytearray.h:402
double toDouble(bool *ok=0) const
Returns the variant as a double if the variant has type() Double , QMetaType::Float ...
Definition: qvariant.cpp:2710
static QVariant stringToVariant(const QString &s)
Definition: qsettings.cpp:551
static CFArrayRef macList(const QList< QVariant > &list)
static QString qtKey(CFStringRef cfkey)
QSettings::Status status
Definition: qsettings_p.h:270
const struct __CFArray * CFArrayRef
static void processChild(QString key, ChildSpec spec, QMap< QString, QString > &result)
Definition: qsettings.cpp:380
QChar toLower() const
Returns the lowercase equivalent if the character is uppercase or titlecase; otherwise returns the ch...
Definition: qchar.cpp:1239
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
QStringList children(const QString &prefix, ChildSpec spec) const
bool isWritable() const
friend class const_iterator
Definition: qmap.h:369
static QString homePath()
Returns the absolute path of the user&#39;s home directory.
Definition: qdir.cpp:1942