comparison sv/document/ESFileReader.cpp @ 19:2a6f70f97395

add - EasaierSessionManager - Easaier menus - Interval model
author lbajardsilogic
date Mon, 14 May 2007 13:13:59 +0000
parents
children 74d1b3bda5a3
comparison
equal deleted inserted replaced
18:d8e6709e9075 19:2a6f70f97395
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 /* Sound Access
4 EASAIER client application.
5 Silogic 2007. Laure Bajard.
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version. See the file
11 COPYING included with this distribution for more information.
12 */
13
14 #include <QString>
15 #include <QMessageBox>
16 #include <QFileDialog>
17 #include <QUrl>
18
19 #include <iostream>
20
21 #include "ESFileReader.h"
22
23 #include "layer/Layer.h"
24 #include "view/View.h"
25 #include "base/PlayParameters.h"
26 #include "base/PlayParameterRepository.h"
27 #include "base/TempDirectory.h"
28 #include "data/fileio/AudioFileReaderFactory.h"
29 #include "data/model/WaveFileModel.h"
30 #include "data/model/DenseThreeDimensionalModel.h"
31 #include "data/model/SparseOneDimensionalModel.h"
32 #include "data/model/SparseTimeValueModel.h"
33 #include "data/model/NoteModel.h"
34 #include "data/model/TextModel.h"
35 #include "view/Pane.h"
36 #include "document/Document.h"
37
38
39 ESFileReader::ESFileReader(Document *document,
40 ESFileReaderPaneCallback &callback) : QXmlDefaultHandler(),
41 m_document(document),
42 m_paneCallback(callback),
43 m_currentPane(0),
44 m_inView(false),
45 m_inData(false),
46 m_ok(false)
47 {}
48
49 void
50 ESFileReader::parse(const QString &xmlData)
51 {
52 QXmlInputSource inputSource;
53 inputSource.setData(xmlData);
54 parse(inputSource);
55 }
56
57 void
58 ESFileReader::parse(QXmlInputSource &inputSource)
59 {
60 QXmlSimpleReader reader;
61 reader.setContentHandler(this);
62 reader.setErrorHandler(this);
63 m_ok = reader.parse(inputSource);
64 }
65
66 bool
67 ESFileReader::isOK()
68 {
69 return m_ok;
70 }
71
72 ESFileReader::~ESFileReader()
73 {}
74
75 bool
76 ESFileReader::startElement(const QString &, const QString &,
77 const QString &qName,
78 const QXmlAttributes &attributes)
79 {
80 QString name = qName.toLower();
81
82 bool ok = false;
83
84 // Valid element names:
85 //
86 // easaiersession
87 // data
88 // easaierresources
89 // audio
90 // display
91 // window
92 // view
93 // layer
94
95 if (name == "easaiersession") {
96 // nothing needed
97 ok = true;
98
99 } else if (name == "data") {
100 // nothing needed
101 m_inData = true;
102 ok = true;
103
104 } else if (name == "easaierresources") {
105 // nothing needed
106 ok = true;
107
108 } else if (name == "audio") {
109 QString filename = attributes.value("value");
110 m_document->setAudioSourceInfoFileName(filename);
111
112 } else if (name == "display") {
113 // nothing needed
114 ok = true;
115
116 } else if (name == "window") {
117 ok = readWindow(attributes);
118
119 } else if (name == "view") {
120 m_inView = true;
121 ok = readView(attributes);
122
123 } else if (name == "layer") {
124 ok = readLayer(attributes);
125
126 }
127
128 if (!ok) {
129 std::cerr << "WARNING: Easaier Session-XML: Failed to completely process element \""
130 << name.toLocal8Bit().data() << "\"" << std::endl;
131 }
132
133 return true;
134 }
135
136 bool
137 ESFileReader::characters(const QString &text)
138 {
139 return true;
140 }
141
142 bool
143 ESFileReader::endElement(const QString &, const QString &,
144 const QString &qName)
145 {
146 QString name = qName.toLower();
147
148 if (name == "data") {
149
150 m_inData = false;
151
152 } else if (name == "view") {
153 m_inView = false;
154 }
155
156 return true;
157 }
158
159 bool
160 ESFileReader::error(const QXmlParseException &exception)
161 {
162 m_errorString =
163 QString("ERROR: Easaier Session-XML: %1 at line %2, column %3")
164 .arg(exception.message())
165 .arg(exception.lineNumber())
166 .arg(exception.columnNumber());
167 std::cerr << m_errorString.toLocal8Bit().data() << std::endl;
168 return QXmlDefaultHandler::error(exception);
169 }
170
171 bool
172 ESFileReader::fatalError(const QXmlParseException &exception)
173 {
174 m_errorString =
175 QString("FATAL ERROR: Easaier Session-XML: %1 at line %2, column %3")
176 .arg(exception.message())
177 .arg(exception.lineNumber())
178 .arg(exception.columnNumber());
179 std::cerr << m_errorString.toLocal8Bit().data() << std::endl;
180 return QXmlDefaultHandler::fatalError(exception);
181 }
182
183
184 #define READ_MANDATORY(TYPE, NAME, CONVERSION) \
185 TYPE NAME = attributes.value(#NAME).trimmed().CONVERSION(&ok); \
186 if (!ok) { \
187 std::cerr << "WARNING: Easaier Session-XML: Missing or invalid mandatory " #TYPE " attribute \"" #NAME "\"" << std::endl; \
188 return false; \
189 }
190
191 bool
192 ESFileReader::readWindow(const QXmlAttributes &attributes)
193 {
194 bool ok = false;
195
196 READ_MANDATORY(int, width, toInt);
197 READ_MANDATORY(int, height, toInt);
198
199 m_paneCallback.setWindowSize(width, height);
200 return true;
201 }
202
203 bool
204 ESFileReader::readView(const QXmlAttributes &attributes)
205 {
206 QString type = attributes.value("type");
207 m_currentPane = 0;
208
209 if (type != "pane") {
210 std::cerr << "WARNING: Easaier session-XML: Unexpected view type \""
211 << type.toLocal8Bit().data() << "\"" << std::endl;
212 return false;
213 }
214
215 m_currentPane = m_paneCallback.addPane();
216
217 if (!m_currentPane) {
218 std::cerr << "WARNING: Easaier session-XML: Internal error: Failed to add pane!"
219 << std::endl;
220 return false;
221 }
222
223 bool ok = false;
224
225 View *view = m_currentPane;
226
227 // The view properties first
228
229 READ_MANDATORY(size_t, centre, toUInt);
230 READ_MANDATORY(size_t, zoom, toUInt);
231 READ_MANDATORY(int, followPan, toInt);
232 READ_MANDATORY(int, followZoom, toInt);
233 QString tracking = attributes.value("tracking");
234
235 // Specify the follow modes before we set the actual values
236 view->setFollowGlobalPan(followPan);
237 view->setFollowGlobalZoom(followZoom);
238 view->setPlaybackFollow(tracking == "scroll" ? PlaybackScrollContinuous :
239 tracking == "page" ? PlaybackScrollPage
240 : PlaybackIgnore);
241
242 // Then set these values
243 view->setCentreFrame(centre);
244 view->setZoomLevel(zoom);
245
246 // And pane properties
247 READ_MANDATORY(int, centreLineVisible, toInt);
248 m_currentPane->setCentreLineVisible(centreLineVisible);
249
250 int height = attributes.value("height").toInt(&ok);
251 if (ok) {
252 m_currentPane->resize(m_currentPane->width(), height);
253 }
254
255 return true;
256 }
257
258 bool
259 ESFileReader::readLayer(const QXmlAttributes &attributes)
260 {
261 QString type = attributes.value("type");
262
263 int id;
264 bool ok = false;
265 id = attributes.value("id").trimmed().toInt(&ok);
266
267 if (!ok) {
268 std::cerr << "WARNING: Easaier session-XML: No layer id for layer of type \""
269 << type.toLocal8Bit().data()
270 << "\"" << std::endl;
271 return false;
272 }
273
274 Layer *layer = 0;
275 bool isNewLayer = false;
276
277 // Layers are expected to be defined in layer elements in the data
278 // section, and referred to in layer elements in the view
279 // sections. So if we're in the data section, we expect this
280 // layer not to exist already; if we're in the view section, we
281 // expect it to exist.
282
283 if (m_inData) {
284
285 if (m_layers.find(id) != m_layers.end()) {
286 std::cerr << "WARNING: Easaier session-XML: Ignoring duplicate layer id " << id
287 << " in data section" << std::endl;
288 return false;
289 }
290
291 layer = m_layers[id] = m_document->createLayer
292 (LayerFactory::getInstance()->getLayerTypeForName(type));
293
294 if (layer) {
295 m_layers[id] = layer;
296 isNewLayer = true;
297 }
298
299 } else {
300
301 if (!m_currentPane) {
302 std::cerr << "WARNING: Easaier session-XML: No current pane for layer " << id
303 << " in view section" << std::endl;
304 return false;
305 }
306
307 if (m_layers.find(id) != m_layers.end()) {
308
309 layer = m_layers[id];
310
311 } else {
312 layer = m_document->createLayer(LayerFactory::getInstance()->getLayerTypeForName(type));
313
314 if (layer) {
315 m_layers[id] = layer;
316 isNewLayer = true;
317 }
318 }
319 }
320
321 if (!layer) {
322 std::cerr << "WARNING: Easaier session-XML: Failed to add layer of type \""
323 << type.toLocal8Bit().data()
324 << "\"" << std::endl;
325 return false;
326 }
327
328 if (isNewLayer) {
329
330 QString name = attributes.value("name");
331 layer->setObjectName(name);
332
333 QString modelName = attributes.value("model");
334 int modelId = attributes.value("modelId").toInt();
335
336 layer->setModelName(modelName);
337 layer->setModelId(modelId);
338
339 layer->setProperties(attributes);
340 }
341
342 if (!m_inData && m_currentPane) {
343 m_document->addLayerToView(m_currentPane, layer);
344 }
345
346 return true;
347 }
348