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 "command_p.h"
|
||||||
|
|
||||||
#include <coreplugin/uniqueidmanager.h>
|
#include <coreplugin/uniqueidmanager.h>
|
||||||
|
#include <coreplugin/coreconstants.h>
|
||||||
|
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
#include <QtCore/QFile>
|
#include <QtCore/QFile>
|
||||||
#include <QtXml/QDomDocument>
|
#include <QtCore/QXmlStreamAttributes>
|
||||||
|
#include <QtCore/QXmlStreamWriter>
|
||||||
|
#include <QtCore/QXmlStreamReader>
|
||||||
|
#include <QtCore/QDebug>
|
||||||
|
#include <QtCore/QDateTime>
|
||||||
|
|
||||||
using namespace Core;
|
namespace Core {
|
||||||
using namespace Core::Internal;
|
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
|
\class CommandsFile
|
||||||
@@ -66,29 +93,36 @@ QMap<QString, QKeySequence> CommandsFile::importCommands() const
|
|||||||
QMap<QString, QKeySequence> result;
|
QMap<QString, QKeySequence> result;
|
||||||
|
|
||||||
QFile file(m_filename);
|
QFile file(m_filename);
|
||||||
if (!file.open(QIODevice::ReadOnly))
|
if (!file.open(QIODevice::ReadOnly|QIODevice::Text))
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
QDomDocument doc("KeyboardMappingScheme");
|
Context ctx;
|
||||||
if (!doc.setContent(&file))
|
QXmlStreamReader r(&file);
|
||||||
return result;
|
|
||||||
|
|
||||||
QDomElement root = doc.documentElement();
|
QString currentId;
|
||||||
if (root.nodeName() != QLatin1String("mapping"))
|
|
||||||
return result;
|
|
||||||
|
|
||||||
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();
|
file.close();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -96,29 +130,43 @@ QMap<QString, QKeySequence> CommandsFile::importCommands() const
|
|||||||
/*!
|
/*!
|
||||||
...
|
...
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool CommandsFile::exportCommands(const QList<ShortcutItem *> &items)
|
bool CommandsFile::exportCommands(const QList<ShortcutItem *> &items)
|
||||||
{
|
{
|
||||||
UniqueIDManager *idmanager = UniqueIDManager::instance();
|
const UniqueIDManager *idmanager = UniqueIDManager::instance();
|
||||||
|
|
||||||
QFile file(m_filename);
|
QFile file(m_filename);
|
||||||
if (!file.open(QIODevice::WriteOnly))
|
if (!file.open(QIODevice::WriteOnly|QIODevice::Text))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
QDomDocument doc("KeyboardMappingScheme");
|
const Context ctx;
|
||||||
QDomElement root = doc.createElement("mapping");
|
QXmlStreamWriter w(&file);
|
||||||
doc.appendChild(root);
|
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) {
|
foreach (const ShortcutItem *item, items) {
|
||||||
QDomElement ctag = doc.createElement("shortcut");
|
const QString id = idmanager->stringForUniqueIdentifier(item->m_cmd->id());
|
||||||
ctag.setAttribute(QLatin1String("id"), idmanager->stringForUniqueIdentifier(item->m_cmd->id()));
|
if (item->m_key.isEmpty()) {
|
||||||
root.appendChild(ctag);
|
w.writeEmptyElement(ctx.shortCutElement);
|
||||||
|
w.writeAttribute(ctx.idAttribute, id);
|
||||||
QDomElement ktag = doc.createElement("key");
|
} else {
|
||||||
ktag.setAttribute(QLatin1String("value"), item->m_key.toString());
|
w.writeStartElement(ctx.shortCutElement);
|
||||||
ctag.appendChild(ktag);
|
w.writeAttribute(ctx.idAttribute, id);
|
||||||
|
w.writeEmptyElement(ctx.keyElement);
|
||||||
|
w.writeAttribute(ctx.valueAttribute, item->m_key.toString());
|
||||||
|
w.writeEndElement(); // Shortcut
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
w.writeEndElement();
|
||||||
file.write(doc.toByteArray());
|
w.writeEndDocument();
|
||||||
file.close();
|
file.close();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Core
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
TEMPLATE = lib
|
TEMPLATE = lib
|
||||||
TARGET = Core
|
TARGET = Core
|
||||||
DEFINES += CORE_LIBRARY
|
DEFINES += CORE_LIBRARY
|
||||||
QT += xml \
|
QT += network \
|
||||||
network \
|
|
||||||
script \
|
script \
|
||||||
sql
|
sql
|
||||||
CONFIG += help
|
CONFIG += help
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ int UniqueIDManager::uniqueIdentifier(const Id &id)
|
|||||||
return uid;
|
return uid;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString UniqueIDManager::stringForUniqueIdentifier(int uid)
|
QString UniqueIDManager::stringForUniqueIdentifier(int uid) const
|
||||||
{
|
{
|
||||||
return m_uniqueIdentifiers.key(uid);
|
return m_uniqueIdentifiers.key(uid);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ public:
|
|||||||
|
|
||||||
bool hasUniqueIdentifier(const Id &id) const;
|
bool hasUniqueIdentifier(const Id &id) const;
|
||||||
int uniqueIdentifier(const Id &id);
|
int uniqueIdentifier(const Id &id);
|
||||||
QString stringForUniqueIdentifier(int uid);
|
QString stringForUniqueIdentifier(int uid) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QHash<Id, int> m_uniqueIdentifiers;
|
QHash<Id, int> m_uniqueIdentifiers;
|
||||||
|
|||||||
@@ -33,19 +33,270 @@
|
|||||||
|
|
||||||
#include "persistentsettings.h"
|
#include "persistentsettings.h"
|
||||||
|
|
||||||
|
#include <coreplugin/coreconstants.h>
|
||||||
|
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
#include <QtCore/QFile>
|
#include <QtCore/QFile>
|
||||||
#include <QtCore/QVariant>
|
#include <QtCore/QVariant>
|
||||||
#include <QtXml/QDomDocument>
|
#include <QtCore/QStack>
|
||||||
#include <QtXml/QDomCDATASection>
|
#include <QtCore/QXmlStreamAttributes>
|
||||||
#include <QtXml/QDomElement>
|
#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()
|
PersistentSettingsReader::PersistentSettingsReader()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant PersistentSettingsReader::restoreValue(const QString & variable) const
|
QVariant PersistentSettingsReader::restoreValue(const QString & variable) const
|
||||||
@@ -65,152 +316,92 @@ bool PersistentSettingsReader::load(const QString & fileName)
|
|||||||
m_valueMap.clear();
|
m_valueMap.clear();
|
||||||
|
|
||||||
QFile file(fileName);
|
QFile file(fileName);
|
||||||
if (!file.open(QIODevice::ReadOnly))
|
if (!file.open(QIODevice::ReadOnly|QIODevice::Text))
|
||||||
return false;
|
return false;
|
||||||
|
ParseContext ctx;
|
||||||
QDomDocument doc;
|
m_valueMap = ctx.parse(file);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
file.close();
|
file.close();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant PersistentSettingsReader::readValue(const QDomElement &valElement) const
|
/*!
|
||||||
{
|
\class ProjectExplorer::PersistentSettingsWriter
|
||||||
QString name = valElement.nodeName();
|
|
||||||
QString type = valElement.attribute(QLatin1String("type"));
|
|
||||||
QVariant v;
|
|
||||||
|
|
||||||
if (name == QLatin1String("value")) {
|
\brief Serializes a QVariantMap of arbitrary, nested data structures to a XML file.
|
||||||
if(type == QLatin1String("QChar")) {
|
\sa ProjectExplorer::PersistentSettingsReader
|
||||||
//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
|
|
||||||
///
|
|
||||||
|
|
||||||
PersistentSettingsWriter::PersistentSettingsWriter()
|
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) {
|
switch (variant.type()) {
|
||||||
QDomElement values = ps.ownerDocument().createElement("valuelist");
|
case QVariant::StringList:
|
||||||
values.setAttribute("type", QVariant::typeToName(QVariant::List));
|
case QVariant::List:
|
||||||
QList<QVariant> varList = variant.toList();
|
w.writeStartElement(ctx.valueListElement);
|
||||||
foreach (const QVariant &var, varList) {
|
w.writeAttribute(ctx.typeAttribute, QVariant::typeToName(QVariant::List));
|
||||||
writeValue(values, var);
|
if (!key.isEmpty())
|
||||||
}
|
w.writeAttribute(ctx.keyAttribute, key);
|
||||||
ps.appendChild(values);
|
foreach (const QVariant &var, variant.toList())
|
||||||
} else if (variant.type() == QVariant::Map) {
|
writeVariantValue(w, ctx, var);
|
||||||
QDomElement values = ps.ownerDocument().createElement("valuemap");
|
w.writeEndElement();
|
||||||
values.setAttribute("type", QVariant::typeToName(QVariant::Map));
|
break;
|
||||||
|
case QVariant::Map: {
|
||||||
QMap<QString, QVariant> varMap = variant.toMap();
|
w.writeStartElement(ctx.valueMapElement);
|
||||||
QMap<QString, QVariant>::const_iterator i = varMap.constBegin();
|
w.writeAttribute(ctx.typeAttribute, QVariant::typeToName(QVariant::Map));
|
||||||
while (i != varMap.constEnd()) {
|
if (!key.isEmpty())
|
||||||
writeValue(values, i.value());
|
w.writeAttribute(ctx.keyAttribute, key);
|
||||||
values.lastChild().toElement().
|
const QVariantMap varMap = variant.toMap();
|
||||||
setAttribute(QLatin1String("key"), i.key());
|
const QVariantMap::const_iterator cend = varMap.constEnd();
|
||||||
++i;
|
for (QVariantMap::const_iterator i = varMap.constBegin(); i != cend; ++i)
|
||||||
}
|
writeVariantValue(w, ctx, i.value(), i.key());
|
||||||
|
w.writeEndElement();
|
||||||
ps.appendChild(values);
|
}
|
||||||
} else {
|
break;
|
||||||
QDomElement value = ps.ownerDocument().createElement("value");
|
default:
|
||||||
ps.appendChild(value);
|
w.writeStartElement(ctx.valueElement);
|
||||||
QDomText valueText = ps.ownerDocument().createTextNode(variant.toString());
|
w.writeAttribute(ctx.typeAttribute, QLatin1String(variant.typeName()));
|
||||||
value.appendChild(valueText);
|
if (!key.isEmpty())
|
||||||
value.setAttribute("type", variant.typeName());
|
w.writeAttribute(ctx.keyAttribute, key);
|
||||||
ps.appendChild(value);
|
w.writeCharacters(variant.toString());
|
||||||
|
w.writeEndElement();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PersistentSettingsWriter::saveValue(const QString & variable, const QVariant &value)
|
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);
|
QFile file(fileName);
|
||||||
if (!file.open(QIODevice::WriteOnly))
|
if (!file.open(QIODevice::WriteOnly|QIODevice::Text))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
QDomDocument doc(docType);
|
const Context ctx;
|
||||||
|
QXmlStreamWriter w(&file);
|
||||||
QDomElement root = doc.createElement("qtcreator");
|
w.setAutoFormatting(true);
|
||||||
doc.appendChild(root);
|
w.setAutoFormattingIndent(1); // Historical, used to be QDom.
|
||||||
|
w.writeStartDocument();
|
||||||
QMap<QString, QVariant>::const_iterator i = m_valueMap.constBegin();
|
w.writeDTD(QLatin1String("<!DOCTYPE ") + docType + QLatin1Char('>'));
|
||||||
while (i != m_valueMap.constEnd()) {
|
w.writeComment(QString::fromAscii(" Written by Qt Creator %1, %2. ").
|
||||||
QDomElement ps = doc.createElement("data");
|
arg(QLatin1String(Core::Constants::IDE_VERSION_LONG),
|
||||||
root.appendChild(ps);
|
QDateTime::currentDateTime().toString(Qt::ISODate)));
|
||||||
|
w.writeStartElement(ctx.qtCreatorElement);
|
||||||
QDomElement variable = doc.createElement("variable");
|
const QVariantMap::const_iterator cend = m_valueMap.constEnd();
|
||||||
ps.appendChild(variable);
|
for (QVariantMap::const_iterator it = m_valueMap.constBegin(); it != cend; ++it) {
|
||||||
QDomText variableText = doc.createTextNode(i.key());
|
w.writeStartElement(ctx.dataElement);
|
||||||
variable.appendChild(variableText);
|
w.writeTextElement(ctx.variableElement, it.key());
|
||||||
|
writeVariantValue(w, ctx, it.value());
|
||||||
writeValue(ps, i.value());
|
w.writeEndElement();
|
||||||
++i;
|
|
||||||
}
|
}
|
||||||
|
w.writeEndDocument();
|
||||||
file.write(doc.toByteArray());
|
|
||||||
file.close();
|
file.close();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
} // namespace ProjectExplorer
|
||||||
|
|||||||
@@ -39,10 +39,6 @@
|
|||||||
#include <QtCore/QMap>
|
#include <QtCore/QMap>
|
||||||
#include <QtCore/QVariant>
|
#include <QtCore/QVariant>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
class QDomElement;
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
namespace ProjectExplorer {
|
namespace ProjectExplorer {
|
||||||
|
|
||||||
class PROJECTEXPLORER_EXPORT PersistentSettingsReader
|
class PROJECTEXPLORER_EXPORT PersistentSettingsReader
|
||||||
@@ -54,8 +50,6 @@ public:
|
|||||||
bool load(const QString & fileName);
|
bool load(const QString & fileName);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QVariant readValue(const QDomElement &valElement) const;
|
|
||||||
void readValues(const QDomElement &data);
|
|
||||||
QMap<QString, QVariant> m_valueMap;
|
QMap<QString, QVariant> m_valueMap;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -64,10 +58,9 @@ class PROJECTEXPLORER_EXPORT PersistentSettingsWriter
|
|||||||
public:
|
public:
|
||||||
PersistentSettingsWriter();
|
PersistentSettingsWriter();
|
||||||
void saveValue(const QString & variable, const QVariant &value);
|
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:
|
private:
|
||||||
void writeValue(QDomElement &ps, const QVariant &value);
|
|
||||||
QMap<QString, QVariant> m_valueMap;
|
QMap<QString, QVariant> m_valueMap;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
TEMPLATE = lib
|
TEMPLATE = lib
|
||||||
TARGET = ProjectExplorer
|
TARGET = ProjectExplorer
|
||||||
QT += xml \
|
QT += script \
|
||||||
script \
|
|
||||||
network
|
network
|
||||||
include(../../qtcreatorplugin.pri)
|
include(../../qtcreatorplugin.pri)
|
||||||
include(projectexplorer_dependencies.pri)
|
include(projectexplorer_dependencies.pri)
|
||||||
|
|||||||
Reference in New Issue
Block a user