1 #include "optionstreereader.h"
2 
3 #include <QSize>
4 #include <QRect>
5 #include <QBuffer>
6 
7 #include "optionstree.h"
8 #include "varianttree.h"
9 
OptionsTreeReader(OptionsTree * options)10 OptionsTreeReader::OptionsTreeReader(OptionsTree* options)
11 	: options_(options)
12 {
13 	Q_ASSERT(options_);
14 }
15 
read(QIODevice * device)16 bool OptionsTreeReader::read(QIODevice* device)
17 {
18 	setDevice(device);
19 
20 	while (!atEnd()) {
21 		readNext();
22 
23 		if (isStartElement()) {
24 			readTree(&options_->tree_);
25 		}
26 	}
27 
28 	return !error();
29 }
30 
readTree(VariantTree * tree)31 void OptionsTreeReader::readTree(VariantTree* tree)
32 {
33 	Q_ASSERT(isStartElement());
34 	Q_ASSERT(tree);
35 
36 	while (!atEnd()) {
37 		readNext();
38 
39 		if (isEndElement())
40 			break;
41 
42 		if (isStartElement()) {
43 			if (!attributes().value("comment").isEmpty()) {
44 				tree->comments_[name().toString()] = attributes().value("comment").toString();
45 			}
46 
47 			if (attributes().value("type").isEmpty()) {
48 				if (!tree->trees_.contains(name().toString()))
49 					tree->trees_[name().toString()] = new VariantTree(tree);
50 				readTree(tree->trees_[name().toString()]);
51 			}
52 			else {
53 				QVariant v = readVariant(attributes().value("type").toString());
54 				if (v.isValid()) {
55 					tree->values_[name().toString()] = v;
56 				}
57 				else {
58 					tree->unknowns2_[name().toString()] = unknown_;
59 				}
60 			}
61 		}
62 	}
63 }
64 
readVariant(const QString & type)65 QVariant OptionsTreeReader::readVariant(const QString& type)
66 {
67 	QVariant result;
68 	if (type == "QStringList") {
69 		result = readStringList();
70 	}
71 	else if (type == "QVariantList") {
72 		result = readVariantList();
73 	}
74 	else if (type == "QSize") {
75 		result = readSize();
76 	}
77 	else if (type == "QRect") {
78 		result = readRect();
79 	}
80 	else if (type == "QByteArray") {
81 		result = QByteArray();
82 		result = QByteArray::fromBase64(readElementText().toLatin1());
83 	}
84 	else {
85 		QVariant::Type varianttype;
86 		bool known = true;
87 
88 		if (type=="QString") {
89 			varianttype = QVariant::String;
90 		} else if (type=="bool") {
91 			varianttype = QVariant::Bool;
92 		} else if (type=="int") {
93 			varianttype = QVariant::Int;
94 		} else if (type == "QKeySequence") {
95 			varianttype = QVariant::KeySequence;
96 		} else if (type == "QColor") {
97 			varianttype = QVariant::Color;
98 		} else {
99 			known = false;
100 		}
101 
102 		if (known) {
103 			result = readElementText();
104 			result.convert(varianttype);
105 		}
106 		else {
107 			QString result;
108 			QByteArray ba;
109 			QBuffer buffer(&ba);
110 			buffer.open(QIODevice::WriteOnly);
111 			QXmlStreamWriter writer;
112 			writer.setDevice(&buffer);
113 
114 			writer.writeStartDocument();
115 			readUnknownElement(&writer);
116 			writer.writeEndDocument();
117 			buffer.close();
118 
119 			// qWarning("ba: %d, '%s'", ba.length(), qPrintable(QString::fromUtf8(ba)));
120 			unknown_ = QString::fromUtf8(ba);
121 		}
122 	}
123 	return result;
124 }
125 
readStringList()126 QStringList OptionsTreeReader::readStringList()
127 {
128 	QStringList list;
129 	while (!atEnd()) {
130 		readNext();
131 
132 		if (isEndElement())
133 			break;
134 
135 		if (isStartElement()) {
136 			if (name() == "item") {
137 				list << readElementText();
138 			}
139 		}
140 	}
141 	return list;
142 }
143 
readVariantList()144 QVariantList OptionsTreeReader::readVariantList()
145 {
146 	QVariantList list;
147 	while (!atEnd()) {
148 		readNext();
149 
150 		if (isEndElement())
151 			break;
152 
153 		if (isStartElement()) {
154 			if (name() == "item") {
155 				list << readVariant(attributes().value("type").toString());
156 			}
157 		}
158 	}
159 	return list;
160 }
161 
readSize()162 QSize OptionsTreeReader::readSize()
163 {
164 	int width = 0, height = 0;
165 	while (!atEnd()) {
166 		readNext();
167 
168 		if (isEndElement())
169 			break;
170 
171 		if (isStartElement()) {
172 			if (name() == "width") {
173 				width = readElementText().toInt();
174 			}
175 			else if (name() == "height") {
176 				height = readElementText().toInt();
177 			}
178 		}
179 	}
180 	return QSize(width, height);
181 }
182 
readRect()183 QRect OptionsTreeReader::readRect()
184 {
185 	int x = 0, y = 0, width = 0, height = 0;
186 	while (!atEnd()) {
187 		readNext();
188 
189 		if (isEndElement())
190 			break;
191 
192 		if (isStartElement()) {
193 			if (name() == "width") {
194 				width = readElementText().toInt();
195 			}
196 			else if (name() == "height") {
197 				height = readElementText().toInt();
198 			}
199 			else if (name() == "x") {
200 				x = readElementText().toInt();
201 			}
202 			else if (name() == "y") {
203 				y = readElementText().toInt();
204 			}
205 		}
206 	}
207 	return QRect(x, y, width, height);
208 }
209 
readUnknownElement(QXmlStreamWriter * writer)210 void OptionsTreeReader::readUnknownElement(QXmlStreamWriter* writer)
211 {
212 	Q_ASSERT(isStartElement());
213 	writer->writeStartElement(name().toString());
214 	foreach(QXmlStreamAttribute attr, attributes()) {
215 		writer->writeAttribute(attr.name().toString(), attr.value().toString());
216 	}
217 
218 	while (!atEnd()) {
219 		writer->writeCharacters(text().toString());
220 		readNext();
221 
222 		if (isEndElement())
223 			break;
224 
225 		if (isStartElement())
226 			readUnknownElement(writer);
227 	}
228 
229 	writer->writeEndElement();
230 }
231