bool QConfFileSettingsPrivate::writePlistFile(const QString &fileName, const ParsedSettingsMap &map) const { QVarLengthArray<QCFType<CFStringRef> > cfkeys(map.size()); QVarLengthArray<QCFType<CFPropertyListRef> > cfvalues(map.size()); int i = 0; ParsedSettingsMap::const_iterator j; for (j = map.constBegin(); j != map.constEnd(); ++j) { cfkeys[i] = macKey(j.key()); cfvalues[i] = macValue(j.value()); ++i; } QCFType<CFDictionaryRef> propertyList = CFDictionaryCreate(kCFAllocatorDefault, reinterpret_cast<const void **>(cfkeys.data()), reinterpret_cast<const void **>(cfvalues.data()), CFIndex(map.size()), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); QCFType<CFDataRef> xmlData = CFPropertyListCreateXMLData(kCFAllocatorDefault, propertyList); SInt32 code; return CFURLWriteDataAndPropertiesToResource(urlFromFileName(fileName), xmlData, 0, &code); }
static CFArrayRef macList(const QList<QVariant> &list) { int n = list.size(); QVarLengthArray<QCFType<CFPropertyListRef> > cfvalues(n); for (int i = 0; i < n; ++i) cfvalues[i] = macValue(list.at(i)); return CFArrayCreate(kCFAllocatorDefault, reinterpret_cast<const void **>(cfvalues.data()), CFIndex(n), &kCFTypeArrayCallBacks); }
void QMacSettingsPrivate::set(const QString &key, const QVariant &value) { CFPreferencesSetValue(macKey(key), macValue(value), domains[0].applicationOrSuiteId, domains[0].userName, hostName); }
static QCFType<CFPropertyListRef> macValue(const QVariant &value) { CFPropertyListRef result = 0; switch (value.type()) { case QVariant::ByteArray: { QByteArray ba = value.toByteArray(); result = CFDataCreate(kCFAllocatorDefault, reinterpret_cast<const UInt8 *>(ba.data()), CFIndex(ba.size())); } break; // should be same as below (look for LIST) case QVariant::List: case QVariant::StringList: case QVariant::Polygon: result = macList(value.toList()); break; case QVariant::Map: { /* QMap<QString, QVariant> is potentially a multimap, whereas CFDictionary is a single-valued map. To allow for multiple values with the same key, we store multiple values in a CFArray. To avoid ambiguities, we also wrap lists in a CFArray singleton. */ QMap<QString, QVariant> map = value.toMap(); QMap<QString, QVariant>::const_iterator i = map.constBegin(); int maxUniqueKeys = map.size(); int numUniqueKeys = 0; QVarLengthArray<QCFType<CFPropertyListRef> > cfkeys(maxUniqueKeys); QVarLengthArray<QCFType<CFPropertyListRef> > cfvalues(maxUniqueKeys); while (i != map.constEnd()) { const QString &key = i.key(); QList<QVariant> values; do { values << i.value(); ++i; } while (i != map.constEnd() && i.key() == key); bool singleton = (values.count() == 1); if (singleton) { switch (values.first().type()) { // should be same as above (look for LIST) case QVariant::List: case QVariant::StringList: case QVariant::Polygon: singleton = false; default: ; } } cfkeys[numUniqueKeys] = QCFString::toCFStringRef(key); cfvalues[numUniqueKeys] = singleton ? macValue(values.first()) : macList(values); ++numUniqueKeys; } result = CFDictionaryCreate(kCFAllocatorDefault, reinterpret_cast<const void **>(cfkeys.data()), reinterpret_cast<const void **>(cfvalues.data()), CFIndex(numUniqueKeys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); } break; case QVariant::DateTime: { /* CFDate, unlike QDateTime, doesn't store timezone information. */ QDateTime dt = value.toDateTime(); if (dt.timeSpec() == Qt::LocalTime) { QDateTime reference; reference.setTime_t((uint)kCFAbsoluteTimeIntervalSince1970); result = CFDateCreate(kCFAllocatorDefault, CFAbsoluteTime(reference.secsTo(dt))); } else { goto string_case; } } break; case QVariant::Bool: result = value.toBool() ? kCFBooleanTrue : kCFBooleanFalse; break; case QVariant::Int: case QVariant::UInt: { int n = value.toInt(); result = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &n); } break; case QVariant::Double: { double n = value.toDouble(); result = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &n); } break; case QVariant::LongLong: case QVariant::ULongLong: { qint64 n = value.toLongLong(); result = CFNumberCreate(0, kCFNumberLongLongType, &n); } break; case QVariant::String: string_case: default: result = QCFString::toCFStringRef(QSettingsPrivate::variantToString(value)); } return result; }