Mac: (temporarily?) drop support for QMultiMap in QSettings
In preparation for the QMap/QMultiMap split. The previous code had a workaround for storing multimaps, because the CF classes actually don't support it: build a dictionary from one key to a _list_ of values. Stop doing that. In principle, if QMultiMap support does get added to QVariant (which it probably should), then a similar workaround could be readded for QMultiMap support. [ChangeLog][Important Behavior Changes][QSettings] On Apple platforms, when using the native format, QSettings is no longer able to handle QVariantMap values which are actually multimaps. Since the native storage does not actually support multimaps, QSettings used to flatten and unflatten the maps. However, with QMap being changed to no longer allow for equivalent keys, flattening when writing does not make sense any more (there cannot be equivalent keys, because QMap in Qt 6 is a single-key map). Reading existing settings is supported by having a key in the map mapping to a QVariantList of values. Support for QMultiMap may be added back to QVariant and QSettings in a future version of Qt. Change-Id: Iaa9535100fe5ef55693f22a2068454a84180b4a6 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
76068d0114
commit
6d9ec41f6f
@ -122,52 +122,25 @@ static QCFType<CFPropertyListRef> macValue(const QVariant &value)
|
||||
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();
|
||||
const QVariantMap &map = value.toMap();
|
||||
const int mapSize = map.size();
|
||||
|
||||
int maxUniqueKeys = map.size();
|
||||
int numUniqueKeys = 0;
|
||||
QVarLengthArray<QCFType<CFPropertyListRef> > cfkeys(maxUniqueKeys);
|
||||
QVarLengthArray<QCFType<CFPropertyListRef> > cfvalues(maxUniqueKeys);
|
||||
QVarLengthArray<QCFType<CFPropertyListRef>> cfkeys;
|
||||
cfkeys.reserve(mapSize);
|
||||
std::transform(map.keyBegin(), map.keyEnd(),
|
||||
std::back_inserter(cfkeys),
|
||||
[](const auto &key) { return key.toCFString(); });
|
||||
|
||||
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.constFirst().type()) {
|
||||
// should be same as above (look for LIST)
|
||||
case QVariant::List:
|
||||
case QVariant::StringList:
|
||||
case QVariant::Polygon:
|
||||
singleton = false;
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
cfkeys[numUniqueKeys] = key.toCFString();
|
||||
cfvalues[numUniqueKeys] = singleton ? macValue(values.constFirst()) : macList(values);
|
||||
++numUniqueKeys;
|
||||
}
|
||||
QVarLengthArray<QCFType<CFPropertyListRef>> cfvalues;
|
||||
cfvalues.reserve(mapSize);
|
||||
std::transform(map.begin(), map.end(),
|
||||
std::back_inserter(cfvalues),
|
||||
[](const auto &value) { return macValue(value); });
|
||||
|
||||
result = CFDictionaryCreate(kCFAllocatorDefault,
|
||||
reinterpret_cast<const void **>(cfkeys.data()),
|
||||
reinterpret_cast<const void **>(cfvalues.data()),
|
||||
CFIndex(numUniqueKeys),
|
||||
CFIndex(mapSize),
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
}
|
||||
@ -283,15 +256,18 @@ static QVariant qtValue(CFPropertyListRef cfvalue)
|
||||
QVarLengthArray<CFPropertyListRef> values(size);
|
||||
CFDictionaryGetKeysAndValues(cfdict, keys.data(), values.data());
|
||||
|
||||
QMultiMap<QString, QVariant> map;
|
||||
QVariantMap map;
|
||||
for (int i = 0; i < size; ++i) {
|
||||
QString key = QString::fromCFString(static_cast<CFStringRef>(keys[i]));
|
||||
|
||||
if (CFGetTypeID(values[i]) == arrayTypeId) {
|
||||
CFArrayRef cfarray = static_cast<CFArrayRef>(values[i]);
|
||||
CFIndex arraySize = CFArrayGetCount(cfarray);
|
||||
for (CFIndex j = arraySize - 1; j >= 0; --j)
|
||||
map.insert(key, qtValue(CFArrayGetValueAtIndex(cfarray, j)));
|
||||
QVariantList list;
|
||||
list.reserve(arraySize);
|
||||
for (CFIndex j = 0; j < arraySize; ++j)
|
||||
list.append(qtValue(CFArrayGetValueAtIndex(cfarray, j)));
|
||||
map.insert(key, list);
|
||||
} else {
|
||||
map.insert(key, qtValue(values[i]));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user