forked from qt-creator/qt-creator
Core/ProjectExplorer: Deprecate QDom in favour of QXmlStream-classes.
Rewrite PersistentSettingsReader/Write and CommandsFile to use QXmlStreamReader/Writer. Files will now be written out using native line endings and contain proper XML version information. Keyboard schemes will contain empty shortcut elements for empty elements. Rubber-stamped-by: con
This commit is contained in:
@@ -36,12 +36,39 @@
|
||||
#include "command_p.h"
|
||||
|
||||
#include <coreplugin/uniqueidmanager.h>
|
||||
#include <coreplugin/coreconstants.h>
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QtCore/QFile>
|
||||
#include <QtXml/QDomDocument>
|
||||
#include <QtCore/QXmlStreamAttributes>
|
||||
#include <QtCore/QXmlStreamWriter>
|
||||
#include <QtCore/QXmlStreamReader>
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QDateTime>
|
||||
|
||||
using namespace Core;
|
||||
using namespace Core::Internal;
|
||||
namespace Core {
|
||||
namespace Internal {
|
||||
|
||||
struct Context // XML parsing context with strings.
|
||||
{
|
||||
Context();
|
||||
|
||||
const QString mappingElement;
|
||||
const QString shortCutElement;
|
||||
const QString idAttribute;
|
||||
const QString keyElement;
|
||||
const QString valueAttribute;
|
||||
};
|
||||
|
||||
Context::Context() :
|
||||
mappingElement(QLatin1String("mapping")),
|
||||
shortCutElement(QLatin1String("shortcut")),
|
||||
idAttribute(QLatin1String("id")),
|
||||
keyElement(QLatin1String("key")),
|
||||
valueAttribute(QLatin1String("value"))
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\class CommandsFile
|
||||
@@ -66,29 +93,36 @@ QMap<QString, QKeySequence> CommandsFile::importCommands() const
|
||||
QMap<QString, QKeySequence> result;
|
||||
|
||||
QFile file(m_filename);
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
if (!file.open(QIODevice::ReadOnly|QIODevice::Text))
|
||||
return result;
|
||||
|
||||
QDomDocument doc("KeyboardMappingScheme");
|
||||
if (!doc.setContent(&file))
|
||||
return result;
|
||||
Context ctx;
|
||||
QXmlStreamReader r(&file);
|
||||
|
||||
QDomElement root = doc.documentElement();
|
||||
if (root.nodeName() != QLatin1String("mapping"))
|
||||
return result;
|
||||
QString currentId;
|
||||
|
||||
QDomElement ks = root.firstChildElement();
|
||||
for (; !ks.isNull(); ks = ks.nextSiblingElement()) {
|
||||
if (ks.nodeName() == QLatin1String("shortcut")) {
|
||||
QString id = ks.attribute(QLatin1String("id"));
|
||||
QKeySequence shortcutkey;
|
||||
QDomElement keyelem = ks.firstChildElement("key");
|
||||
if (!keyelem.isNull())
|
||||
shortcutkey = QKeySequence(keyelem.attribute("value"));
|
||||
result.insert(id, shortcutkey);
|
||||
while (!r.atEnd()) {
|
||||
switch (r.readNext()) {
|
||||
case QXmlStreamReader::StartElement: {
|
||||
const QStringRef name = r.name();
|
||||
if (name == ctx.shortCutElement) {
|
||||
currentId = r.attributes().value(ctx.idAttribute).toString();
|
||||
} else if (name == ctx.keyElement) {
|
||||
QTC_ASSERT(!currentId.isEmpty(), return result; )
|
||||
const QXmlStreamAttributes attributes = r.attributes();
|
||||
if (attributes.hasAttribute(ctx.valueAttribute)) {
|
||||
const QString keyString = attributes.value(ctx.valueAttribute).toString();
|
||||
result.insert(currentId, QKeySequence(keyString));
|
||||
} else {
|
||||
result.insert(currentId, QKeySequence());
|
||||
}
|
||||
}
|
||||
|
||||
currentId.clear();
|
||||
} // if key element
|
||||
} // case QXmlStreamReader::StartElement
|
||||
default:
|
||||
break;
|
||||
} // switch
|
||||
} // while !atEnd
|
||||
file.close();
|
||||
return result;
|
||||
}
|
||||
@@ -96,29 +130,43 @@ QMap<QString, QKeySequence> CommandsFile::importCommands() const
|
||||
/*!
|
||||
...
|
||||
*/
|
||||
|
||||
bool CommandsFile::exportCommands(const QList<ShortcutItem *> &items)
|
||||
{
|
||||
UniqueIDManager *idmanager = UniqueIDManager::instance();
|
||||
const UniqueIDManager *idmanager = UniqueIDManager::instance();
|
||||
|
||||
QFile file(m_filename);
|
||||
if (!file.open(QIODevice::WriteOnly))
|
||||
if (!file.open(QIODevice::WriteOnly|QIODevice::Text))
|
||||
return false;
|
||||
|
||||
QDomDocument doc("KeyboardMappingScheme");
|
||||
QDomElement root = doc.createElement("mapping");
|
||||
doc.appendChild(root);
|
||||
|
||||
const Context ctx;
|
||||
QXmlStreamWriter w(&file);
|
||||
w.setAutoFormatting(true);
|
||||
w.setAutoFormattingIndent(1); // Historical, used to be QDom.
|
||||
w.writeStartDocument();
|
||||
w.writeDTD(QLatin1String("<!DOCTYPE KeyboardMappingScheme>"));
|
||||
w.writeComment(QString::fromAscii(" Written by Qt Creator %1, %2. ").
|
||||
arg(QLatin1String(Core::Constants::IDE_VERSION_LONG),
|
||||
QDateTime::currentDateTime().toString(Qt::ISODate)));
|
||||
w.writeStartElement(ctx.mappingElement);
|
||||
foreach (const ShortcutItem *item, items) {
|
||||
QDomElement ctag = doc.createElement("shortcut");
|
||||
ctag.setAttribute(QLatin1String("id"), idmanager->stringForUniqueIdentifier(item->m_cmd->id()));
|
||||
root.appendChild(ctag);
|
||||
|
||||
QDomElement ktag = doc.createElement("key");
|
||||
ktag.setAttribute(QLatin1String("value"), item->m_key.toString());
|
||||
ctag.appendChild(ktag);
|
||||
const QString id = idmanager->stringForUniqueIdentifier(item->m_cmd->id());
|
||||
if (item->m_key.isEmpty()) {
|
||||
w.writeEmptyElement(ctx.shortCutElement);
|
||||
w.writeAttribute(ctx.idAttribute, id);
|
||||
} else {
|
||||
w.writeStartElement(ctx.shortCutElement);
|
||||
w.writeAttribute(ctx.idAttribute, id);
|
||||
w.writeEmptyElement(ctx.keyElement);
|
||||
w.writeAttribute(ctx.valueAttribute, item->m_key.toString());
|
||||
w.writeEndElement(); // Shortcut
|
||||
}
|
||||
|
||||
file.write(doc.toByteArray());
|
||||
}
|
||||
w.writeEndElement();
|
||||
w.writeEndDocument();
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Core
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
TEMPLATE = lib
|
||||
TARGET = Core
|
||||
DEFINES += CORE_LIBRARY
|
||||
QT += xml \
|
||||
network \
|
||||
QT += network \
|
||||
script \
|
||||
sql
|
||||
CONFIG += help
|
||||
|
||||
@@ -63,7 +63,7 @@ int UniqueIDManager::uniqueIdentifier(const Id &id)
|
||||
return uid;
|
||||
}
|
||||
|
||||
QString UniqueIDManager::stringForUniqueIdentifier(int uid)
|
||||
QString UniqueIDManager::stringForUniqueIdentifier(int uid) const
|
||||
{
|
||||
return m_uniqueIdentifiers.key(uid);
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ public:
|
||||
|
||||
bool hasUniqueIdentifier(const Id &id) const;
|
||||
int uniqueIdentifier(const Id &id);
|
||||
QString stringForUniqueIdentifier(int uid);
|
||||
QString stringForUniqueIdentifier(int uid) const;
|
||||
|
||||
private:
|
||||
QHash<Id, int> m_uniqueIdentifiers;
|
||||
|
||||
@@ -33,19 +33,270 @@
|
||||
|
||||
#include "persistentsettings.h"
|
||||
|
||||
#include <coreplugin/coreconstants.h>
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QFile>
|
||||
#include <QtCore/QVariant>
|
||||
#include <QtXml/QDomDocument>
|
||||
#include <QtXml/QDomCDATASection>
|
||||
#include <QtXml/QDomElement>
|
||||
#include <QtCore/QStack>
|
||||
#include <QtCore/QXmlStreamAttributes>
|
||||
#include <QtCore/QXmlStreamReader>
|
||||
#include <QtCore/QXmlStreamWriter>
|
||||
#include <QtCore/QDateTime>
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
/*!
|
||||
\class ProjectExplorer::PersistentSettingsReader
|
||||
|
||||
\brief Reads a QVariantMap of arbitrary, nested data structures from a XML file.
|
||||
|
||||
Handles all string-serializable simple types and QVariantList and QVariantMap. Example:
|
||||
\code
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||
<value type="int">0</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
\endcode
|
||||
|
||||
When parsing the structure, a parse stack of ParseValueStackEntry is used for each
|
||||
<data> element. ParseValueStackEntry is a variant/union of:
|
||||
\list
|
||||
\o simple value
|
||||
\o map
|
||||
\o list
|
||||
\endlist
|
||||
|
||||
When entering a value element ( \c <value> / \c <valuelist> , \c <valuemap> ), entry is pushed
|
||||
accordingly. When leaving the element, the QVariant-value of the entry is taken off the stack
|
||||
and added to the stack entry below (added to list or inserted into map). The first element
|
||||
of the stack is the value of the <data> element.
|
||||
|
||||
\sa ProjectExplorer::PersistentSettingsWriter
|
||||
*/
|
||||
|
||||
namespace ProjectExplorer {
|
||||
|
||||
struct Context // Basic context containing element name string constants.
|
||||
{
|
||||
Context();
|
||||
|
||||
const QString qtCreatorElement;
|
||||
const QString dataElement;
|
||||
const QString variableElement;
|
||||
const QString typeAttribute;
|
||||
const QString valueElement;
|
||||
const QString valueListElement;
|
||||
const QString valueMapElement;
|
||||
const QString keyAttribute;
|
||||
};
|
||||
|
||||
Context::Context() :
|
||||
qtCreatorElement(QLatin1String("qtcreator")),
|
||||
dataElement(QLatin1String("data")),
|
||||
variableElement(QLatin1String("variable")),
|
||||
typeAttribute(QLatin1String("type")),
|
||||
valueElement(QLatin1String("value")),
|
||||
valueListElement(QLatin1String("valuelist")),
|
||||
valueMapElement(QLatin1String("valuemap")),
|
||||
keyAttribute(QLatin1String("key"))
|
||||
{
|
||||
}
|
||||
|
||||
struct ParseValueStackEntry
|
||||
{
|
||||
explicit ParseValueStackEntry(QVariant::Type t = QVariant::Invalid, const QString &k = QString()) : type(t), key(k) {}
|
||||
explicit ParseValueStackEntry(const QVariant &aSimpleValue, const QString &k);
|
||||
|
||||
QVariant value() const;
|
||||
void addChild(const QString &key, const QVariant &v);
|
||||
|
||||
QVariant::Type type;
|
||||
QString key;
|
||||
QVariant simpleValue;
|
||||
QVariantList listValue;
|
||||
QVariantMap mapValue;
|
||||
};
|
||||
|
||||
ParseValueStackEntry::ParseValueStackEntry(const QVariant &aSimpleValue, const QString &k) :
|
||||
type(aSimpleValue.type()), key(k), simpleValue(aSimpleValue)
|
||||
{
|
||||
QTC_ASSERT(simpleValue.isValid(), return ; )
|
||||
}
|
||||
|
||||
QVariant ParseValueStackEntry::value() const
|
||||
{
|
||||
switch (type) {
|
||||
case QVariant::Invalid:
|
||||
return QVariant();
|
||||
case QVariant::Map:
|
||||
return QVariant(mapValue);
|
||||
case QVariant::List:
|
||||
return QVariant(listValue);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return simpleValue;
|
||||
}
|
||||
|
||||
void ParseValueStackEntry::addChild(const QString &key, const QVariant &v)
|
||||
{
|
||||
switch (type) {
|
||||
case QVariant::Map:
|
||||
mapValue.insert(key, v);
|
||||
break;
|
||||
case QVariant::List:
|
||||
listValue.push_back(v);
|
||||
break;
|
||||
default:
|
||||
qWarning() << "ParseValueStackEntry::Internal error adding " << key << v << " to "
|
||||
<< QVariant::typeToName(type) << value();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
class ParseContext : public Context
|
||||
{
|
||||
public:
|
||||
QVariantMap parse(QFile &file);
|
||||
|
||||
private:
|
||||
enum Element { QtCreatorElement, DataElement, VariableElement,
|
||||
SimpleValueElement, ListValueElement, MapValueElement, UnknownElement };
|
||||
|
||||
Element element(const QStringRef &r) const;
|
||||
static inline bool isValueElement(Element e)
|
||||
{ return e == SimpleValueElement || e == ListValueElement || e == MapValueElement; }
|
||||
QVariant readSimpleValue(QXmlStreamReader &r, const QXmlStreamAttributes &attributes) const;
|
||||
|
||||
bool handleStartElement(QXmlStreamReader &r);
|
||||
bool handleEndElement(const QStringRef &name);
|
||||
|
||||
QStack<ParseValueStackEntry> m_valueStack;
|
||||
QVariantMap m_result;
|
||||
QString m_currentVariableName;
|
||||
};
|
||||
|
||||
QVariantMap ParseContext::parse(QFile &file)
|
||||
{
|
||||
QXmlStreamReader r(&file);
|
||||
|
||||
m_result.clear();
|
||||
m_currentVariableName.clear();
|
||||
|
||||
while (!r.atEnd()) {
|
||||
switch (r.readNext()) {
|
||||
case QXmlStreamReader::StartElement:
|
||||
if (handleStartElement(r))
|
||||
return m_result;
|
||||
break;
|
||||
case QXmlStreamReader::EndElement:
|
||||
if (handleEndElement(r.name()))
|
||||
return m_result;
|
||||
break;
|
||||
case QXmlStreamReader::Invalid:
|
||||
qWarning("Error reading %s:%d: %s", qPrintable(file.fileName()),
|
||||
int(r.lineNumber()), qPrintable(r.errorString()));
|
||||
return QVariantMap();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
} // switch token
|
||||
} // while (!r.atEnd())
|
||||
return m_result;
|
||||
}
|
||||
|
||||
bool ParseContext::handleStartElement(QXmlStreamReader &r)
|
||||
{
|
||||
const QStringRef name = r.name();
|
||||
const Element e = element(name);
|
||||
if (e == VariableElement) {
|
||||
m_currentVariableName = r.readElementText();
|
||||
return false;
|
||||
}
|
||||
if (!ParseContext::isValueElement(e))
|
||||
return false;
|
||||
|
||||
const QXmlStreamAttributes attributes = r.attributes();
|
||||
const QString key = attributes.hasAttribute(keyAttribute) ?
|
||||
attributes.value(keyAttribute).toString() : QString();
|
||||
switch (e) {
|
||||
case SimpleValueElement:
|
||||
// This reads away the end element, so, handle end element right here.
|
||||
m_valueStack.push_back(ParseValueStackEntry(readSimpleValue(r, attributes), key));
|
||||
return handleEndElement(name);
|
||||
case ListValueElement:
|
||||
m_valueStack.push_back(ParseValueStackEntry(QVariant::List, key));
|
||||
break;
|
||||
case MapValueElement:
|
||||
m_valueStack.push_back(ParseValueStackEntry(QVariant::Map, key));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ParseContext::handleEndElement(const QStringRef &name)
|
||||
{
|
||||
const Element e = element(name);
|
||||
if (ParseContext::isValueElement(e)) {
|
||||
QTC_ASSERT(!m_valueStack.isEmpty(), return true; )
|
||||
const ParseValueStackEntry top = m_valueStack.pop();
|
||||
if (m_valueStack.isEmpty()) { // Last element? -> Done with that variable.
|
||||
QTC_ASSERT(!m_currentVariableName.isEmpty(), return true; )
|
||||
m_result.insert(m_currentVariableName, top.value());
|
||||
m_currentVariableName.clear();
|
||||
return false;
|
||||
}
|
||||
m_valueStack.top().addChild(top.key, top.value());
|
||||
}
|
||||
return e == QtCreatorElement;
|
||||
}
|
||||
|
||||
ParseContext::Element ParseContext::element(const QStringRef &r) const
|
||||
{
|
||||
if (r == valueElement)
|
||||
return SimpleValueElement;
|
||||
if (r == valueListElement)
|
||||
return ListValueElement;
|
||||
if (r == valueMapElement)
|
||||
return MapValueElement;
|
||||
if (r == qtCreatorElement)
|
||||
return QtCreatorElement;
|
||||
if (r == dataElement)
|
||||
return DataElement;
|
||||
if (r == variableElement)
|
||||
return VariableElement;
|
||||
return UnknownElement;
|
||||
}
|
||||
|
||||
QVariant ParseContext::readSimpleValue(QXmlStreamReader &r, const QXmlStreamAttributes &attributes) const
|
||||
{
|
||||
// Simple value
|
||||
const QString type = attributes.value(typeAttribute).toString();
|
||||
const QString text = r.readElementText();
|
||||
if (type == QLatin1String("QChar")) { // Workaround: QTBUG-12345
|
||||
QTC_ASSERT(text.size() == 1, return QVariant(); )
|
||||
return QVariant(QChar(text.at(0)));
|
||||
}
|
||||
QVariant value;
|
||||
value.setValue(text);
|
||||
value.convert(QVariant::nameToType(type.toLatin1().data()));
|
||||
return value;
|
||||
}
|
||||
|
||||
// =================================== PersistentSettingsReader
|
||||
|
||||
PersistentSettingsReader::PersistentSettingsReader()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QVariant PersistentSettingsReader::restoreValue(const QString & variable) const
|
||||
@@ -65,152 +316,92 @@ bool PersistentSettingsReader::load(const QString & fileName)
|
||||
m_valueMap.clear();
|
||||
|
||||
QFile file(fileName);
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
if (!file.open(QIODevice::ReadOnly|QIODevice::Text))
|
||||
return false;
|
||||
|
||||
QDomDocument doc;
|
||||
if (!doc.setContent(&file))
|
||||
return false;
|
||||
|
||||
QDomElement root = doc.documentElement();
|
||||
if (root.nodeName() != QLatin1String("qtcreator"))
|
||||
return false;
|
||||
|
||||
QDomElement child = root.firstChildElement();
|
||||
for (; !child.isNull(); child = child.nextSiblingElement()) {
|
||||
if (child.nodeName() == QLatin1String("data"))
|
||||
readValues(child);
|
||||
}
|
||||
|
||||
ParseContext ctx;
|
||||
m_valueMap = ctx.parse(file);
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariant PersistentSettingsReader::readValue(const QDomElement &valElement) const
|
||||
{
|
||||
QString name = valElement.nodeName();
|
||||
QString type = valElement.attribute(QLatin1String("type"));
|
||||
QVariant v;
|
||||
/*!
|
||||
\class ProjectExplorer::PersistentSettingsWriter
|
||||
|
||||
if (name == QLatin1String("value")) {
|
||||
if(type == QLatin1String("QChar")) {
|
||||
//Workaround: QTBUG-12345
|
||||
v.setValue(QChar(valElement.text().at(0)));
|
||||
} else {
|
||||
v.setValue(valElement.text());
|
||||
v.convert(QVariant::nameToType(type.toLatin1().data()));
|
||||
}
|
||||
} else if (name == QLatin1String("valuelist")) {
|
||||
QDomElement child = valElement.firstChildElement();
|
||||
QList<QVariant> valList;
|
||||
for (; !child.isNull(); child = child.nextSiblingElement()) {
|
||||
valList << readValue(child);
|
||||
}
|
||||
v.setValue(valList);
|
||||
} else if (name == QLatin1String("valuemap")) {
|
||||
QDomElement child = valElement.firstChildElement();
|
||||
QMap<QString, QVariant> valMap;
|
||||
for (; !child.isNull(); child = child.nextSiblingElement()) {
|
||||
QString key = child.attribute(QLatin1String("key"));
|
||||
valMap.insert(key, readValue(child));
|
||||
}
|
||||
v.setValue(valMap);
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
void PersistentSettingsReader::readValues(const QDomElement &data)
|
||||
{
|
||||
QString variable;
|
||||
QVariant v;
|
||||
|
||||
QDomElement child = data.firstChildElement();
|
||||
for (; !child.isNull(); child = child.nextSiblingElement()) {
|
||||
if (child.nodeName() == QLatin1String("variable")) {
|
||||
variable = child.text();
|
||||
} else {
|
||||
v = readValue(child);
|
||||
}
|
||||
}
|
||||
|
||||
m_valueMap.insert(variable, v);
|
||||
}
|
||||
|
||||
///
|
||||
/// PersistentSettingsWriter
|
||||
///
|
||||
\brief Serializes a QVariantMap of arbitrary, nested data structures to a XML file.
|
||||
\sa ProjectExplorer::PersistentSettingsReader
|
||||
*/
|
||||
|
||||
PersistentSettingsWriter::PersistentSettingsWriter()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void PersistentSettingsWriter::writeValue(QDomElement &ps, const QVariant &variant)
|
||||
static void writeVariantValue(QXmlStreamWriter &w, const Context &ctx,
|
||||
const QVariant &variant, const QString &key = QString())
|
||||
{
|
||||
if (variant.type() == QVariant::StringList || variant.type() == QVariant::List) {
|
||||
QDomElement values = ps.ownerDocument().createElement("valuelist");
|
||||
values.setAttribute("type", QVariant::typeToName(QVariant::List));
|
||||
QList<QVariant> varList = variant.toList();
|
||||
foreach (const QVariant &var, varList) {
|
||||
writeValue(values, var);
|
||||
switch (variant.type()) {
|
||||
case QVariant::StringList:
|
||||
case QVariant::List:
|
||||
w.writeStartElement(ctx.valueListElement);
|
||||
w.writeAttribute(ctx.typeAttribute, QVariant::typeToName(QVariant::List));
|
||||
if (!key.isEmpty())
|
||||
w.writeAttribute(ctx.keyAttribute, key);
|
||||
foreach (const QVariant &var, variant.toList())
|
||||
writeVariantValue(w, ctx, var);
|
||||
w.writeEndElement();
|
||||
break;
|
||||
case QVariant::Map: {
|
||||
w.writeStartElement(ctx.valueMapElement);
|
||||
w.writeAttribute(ctx.typeAttribute, QVariant::typeToName(QVariant::Map));
|
||||
if (!key.isEmpty())
|
||||
w.writeAttribute(ctx.keyAttribute, key);
|
||||
const QVariantMap varMap = variant.toMap();
|
||||
const QVariantMap::const_iterator cend = varMap.constEnd();
|
||||
for (QVariantMap::const_iterator i = varMap.constBegin(); i != cend; ++i)
|
||||
writeVariantValue(w, ctx, i.value(), i.key());
|
||||
w.writeEndElement();
|
||||
}
|
||||
ps.appendChild(values);
|
||||
} else if (variant.type() == QVariant::Map) {
|
||||
QDomElement values = ps.ownerDocument().createElement("valuemap");
|
||||
values.setAttribute("type", QVariant::typeToName(QVariant::Map));
|
||||
|
||||
QMap<QString, QVariant> varMap = variant.toMap();
|
||||
QMap<QString, QVariant>::const_iterator i = varMap.constBegin();
|
||||
while (i != varMap.constEnd()) {
|
||||
writeValue(values, i.value());
|
||||
values.lastChild().toElement().
|
||||
setAttribute(QLatin1String("key"), i.key());
|
||||
++i;
|
||||
}
|
||||
|
||||
ps.appendChild(values);
|
||||
} else {
|
||||
QDomElement value = ps.ownerDocument().createElement("value");
|
||||
ps.appendChild(value);
|
||||
QDomText valueText = ps.ownerDocument().createTextNode(variant.toString());
|
||||
value.appendChild(valueText);
|
||||
value.setAttribute("type", variant.typeName());
|
||||
ps.appendChild(value);
|
||||
break;
|
||||
default:
|
||||
w.writeStartElement(ctx.valueElement);
|
||||
w.writeAttribute(ctx.typeAttribute, QLatin1String(variant.typeName()));
|
||||
if (!key.isEmpty())
|
||||
w.writeAttribute(ctx.keyAttribute, key);
|
||||
w.writeCharacters(variant.toString());
|
||||
w.writeEndElement();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void PersistentSettingsWriter::saveValue(const QString & variable, const QVariant &value)
|
||||
{
|
||||
m_valueMap[variable] = value;
|
||||
m_valueMap.insert(variable, value);
|
||||
}
|
||||
|
||||
bool PersistentSettingsWriter::save(const QString & fileName, const QString & docType)
|
||||
bool PersistentSettingsWriter::save(const QString & fileName, const QString &docType) const
|
||||
{
|
||||
QFile file(fileName);
|
||||
if (!file.open(QIODevice::WriteOnly))
|
||||
if (!file.open(QIODevice::WriteOnly|QIODevice::Text))
|
||||
return false;
|
||||
|
||||
QDomDocument doc(docType);
|
||||
|
||||
QDomElement root = doc.createElement("qtcreator");
|
||||
doc.appendChild(root);
|
||||
|
||||
QMap<QString, QVariant>::const_iterator i = m_valueMap.constBegin();
|
||||
while (i != m_valueMap.constEnd()) {
|
||||
QDomElement ps = doc.createElement("data");
|
||||
root.appendChild(ps);
|
||||
|
||||
QDomElement variable = doc.createElement("variable");
|
||||
ps.appendChild(variable);
|
||||
QDomText variableText = doc.createTextNode(i.key());
|
||||
variable.appendChild(variableText);
|
||||
|
||||
writeValue(ps, i.value());
|
||||
++i;
|
||||
const Context ctx;
|
||||
QXmlStreamWriter w(&file);
|
||||
w.setAutoFormatting(true);
|
||||
w.setAutoFormattingIndent(1); // Historical, used to be QDom.
|
||||
w.writeStartDocument();
|
||||
w.writeDTD(QLatin1String("<!DOCTYPE ") + docType + QLatin1Char('>'));
|
||||
w.writeComment(QString::fromAscii(" Written by Qt Creator %1, %2. ").
|
||||
arg(QLatin1String(Core::Constants::IDE_VERSION_LONG),
|
||||
QDateTime::currentDateTime().toString(Qt::ISODate)));
|
||||
w.writeStartElement(ctx.qtCreatorElement);
|
||||
const QVariantMap::const_iterator cend = m_valueMap.constEnd();
|
||||
for (QVariantMap::const_iterator it = m_valueMap.constBegin(); it != cend; ++it) {
|
||||
w.writeStartElement(ctx.dataElement);
|
||||
w.writeTextElement(ctx.variableElement, it.key());
|
||||
writeVariantValue(w, ctx, it.value());
|
||||
w.writeEndElement();
|
||||
}
|
||||
|
||||
file.write(doc.toByteArray());
|
||||
w.writeEndDocument();
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
} // namespace ProjectExplorer
|
||||
|
||||
@@ -39,10 +39,6 @@
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QVariant>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QDomElement;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace ProjectExplorer {
|
||||
|
||||
class PROJECTEXPLORER_EXPORT PersistentSettingsReader
|
||||
@@ -54,8 +50,6 @@ public:
|
||||
bool load(const QString & fileName);
|
||||
|
||||
private:
|
||||
QVariant readValue(const QDomElement &valElement) const;
|
||||
void readValues(const QDomElement &data);
|
||||
QMap<QString, QVariant> m_valueMap;
|
||||
};
|
||||
|
||||
@@ -64,10 +58,9 @@ class PROJECTEXPLORER_EXPORT PersistentSettingsWriter
|
||||
public:
|
||||
PersistentSettingsWriter();
|
||||
void saveValue(const QString & variable, const QVariant &value);
|
||||
bool save(const QString & fileName, const QString & docType);
|
||||
bool save(const QString & fileName, const QString & docType) const;
|
||||
|
||||
private:
|
||||
void writeValue(QDomElement &ps, const QVariant &value);
|
||||
QMap<QString, QVariant> m_valueMap;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
TEMPLATE = lib
|
||||
TARGET = ProjectExplorer
|
||||
QT += xml \
|
||||
script \
|
||||
QT += script \
|
||||
network
|
||||
include(../../qtcreatorplugin.pri)
|
||||
include(projectexplorer_dependencies.pri)
|
||||
|
||||
Reference in New Issue
Block a user