1 /*
2 For general Scribus (>=1.3.2) copyright and licensing information please refer
3 to the COPYING file provided with the program. Following this notice may exist
4 a copyright and/or license notice that predates the release of Scribus 1.3.2
5 for which a new license (GPL+exception) is in place.
6 */
7 #include "pdfoptionsio.h"
8 #include "scribusstructs.h"
9 
10 #include <QApplication>
11 #include <QList>
12 #include <QTextStream>
13 
14 #include "scclocale.h"
15 
16 const int PDFOptionsIO::formatVersion = 1300;
17 
PDFOptionsIO(PDFOptions & opts)18 PDFOptionsIO::PDFOptionsIO(PDFOptions& opts) :
19 	m_includePasswords(false),
20 	m_error()
21 {
22 	this->m_opts = &opts;
23 }
24 
25 // writeTo(QString) is implemented separately to writeTo(QTextStream)
26 // because we don't want to clobber the output file until we know the
27 // data has been generated ok, and we can't avoid clobbering the file
28 // to create a QTextStream().
writeTo(const QString & outFileName,bool includePasswords)29 bool PDFOptionsIO::writeTo(const QString& outFileName, bool includePasswords)
30 {
31 	m_includePasswords = includePasswords;
32 	QString xml(buildXMLString());
33 	if (xml.isNull())
34 		return false;
35 	QFile f(outFileName);
36 	if (!f.open(QIODevice::WriteOnly|QIODevice::Truncate))
37 	{
38 		m_error = QObject::tr("Could not open output file %1")
39 			.arg(qApp->translate("QFile",f.errorString().toLatin1().constData()));
40 		return false;
41 	}
42 	QTextStream ts(&f);
43 	ts.setCodec("UTF-8");
44 	ts << xml;
45 	m_includePasswords = false; // just to be paranoid
46 	m_error.clear();
47 	return true;
48 }
49 
writeTo(QIODevice & outDevice,bool includePasswords)50 bool PDFOptionsIO::writeTo(QIODevice& outDevice, bool includePasswords)
51 {
52 	m_includePasswords = includePasswords;
53 	if (!outDevice.isWritable())
54 	{
55 		m_error = QObject::tr("Output stream not writeable");
56 		return false;
57 	}
58 	QString xml = buildXMLString();
59 	if (xml.isNull())
60 		return false;
61 	QTextStream ts(&outDevice);
62 	ts.setCodec("UTF-8");
63 	ts << xml;
64 	m_includePasswords = false; // just to be paranoid
65 	m_error.clear();
66 	return true;
67 }
68 
69 // Construct and return an XML string representing the settings
buildXMLString()70 QString PDFOptionsIO::buildXMLString()
71 {
72 	// Verify to make sure our settings are sane
73 	QString vrfyError;
74 	// Make sure the options are sane
75 	PDFOptions::VerifyResults vr = m_opts->verify(&vrfyError);
76 	if (vr != PDFOptions::Verify_NoError)
77 	{
78 		m_error = QObject::tr("Verification of settings failed: %1").arg(vrfyError);
79 		return QString();
80 	}
81 	// Build the document. Initial implementation uses QDom.
82 	m_doc = QDomDocument();
83 	m_root = m_doc.createElement("ScribusPDFOptions");
84 	m_root.setAttribute("version", formatVersion);
85 	m_doc.appendChild(m_root);
86 	// Fill the guts of the document
87 	buildSettings();
88 	// We're done - return a string containing the document XML
89 	QString xml = m_doc.toString();
90 	xml.prepend(
91 		"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
92 		"<!DOCTYPE ScribusPDFOptions SYSTEM 'scribuspdfoptions.dtd'>\n"
93 		);
94 	return xml;
95 }
96 
97 // Build up the stored settings into the passed DOM objects
buildSettings()98 void PDFOptionsIO::buildSettings()
99 {
100 	addElem(m_root, "firstUse", m_opts->firstUse);
101 	addElem(m_root, "thumbnails", m_opts->Thumbnails);
102 	addElem(m_root, "articles", m_opts->Articles);
103 	addElem(m_root, "useLayers", m_opts->useLayers);
104 	addElem(m_root, "compress", m_opts->Compress);
105 	addElem(m_root, "compressMethod", m_opts->CompressMethod);
106 	addElem(m_root, "quality", m_opts->Quality);
107 	addElem(m_root, "recalcPic", m_opts->RecalcPic);
108 	addElem(m_root, "bookmarks", m_opts->Bookmarks);
109 	addElem(m_root, "picRes", m_opts->PicRes);
110 	addElem(m_root, "embedPDF", m_opts->embedPDF);
111 	QString pdfVersString;
112 	switch (m_opts->Version)
113 	{
114 		case PDFVersion::PDF_X1a:
115 			pdfVersString = "X1a";
116 			break;
117 		case PDFVersion::PDF_X3:
118 			pdfVersString = "X3";
119 			break;
120 		case PDFVersion::PDF_X4:
121 			pdfVersString = "X4";
122 			break;
123 		default:
124 			pdfVersString = QString::number(m_opts->Version);
125 			break;
126 	}
127 	addElem(m_root, "pdfVersion", pdfVersString);
128 	addElem(m_root, "resolution", m_opts->Resolution);
129 	addElem(m_root, "binding", m_opts->Binding);
130 	QString embeddingModeString;
131 	switch (m_opts->FontEmbedding)
132 	{
133 		case PDFOptions::OutlineFonts:
134 			embeddingModeString = "OutlineFonts";
135 			break;
136 		case PDFOptions::DontEmbed:
137 			embeddingModeString = "DontEmbed";
138 			break;
139 		default:
140 			embeddingModeString = "EmbedFonts";
141 			break;
142 	}
143 	addElem(m_root, "fontEmbedding", embeddingModeString);
144 	addList(m_root, "embedFonts", m_opts->EmbedList);
145 	addList(m_root, "subsetFonts", m_opts->SubsetList);
146 	addElem(m_root, "mirrorH", m_opts->MirrorH);
147 	addElem(m_root, "mirrorV", m_opts->MirrorV);
148 	addElem(m_root, "rotateDegrees", m_opts->RotateDeg);
149 	addElem(m_root, "presentMode", m_opts->PresentMode);
150 	// addPresentationData();
151 	addElem(m_root, "filename", m_opts->fileName);
152 	addElem(m_root, "isGrayscale", m_opts->isGrayscale);
153 	addElem(m_root, "useRGB", m_opts->UseRGB);
154 	addElem(m_root, "useProfiles", m_opts->UseProfiles);
155 	addElem(m_root, "useProfiles2", m_opts->UseProfiles2);
156 	addElem(m_root, "useLPI", m_opts->UseLPI);
157 	addElem(m_root, "useSpotColors", m_opts->UseSpotColors);
158 	addElem(m_root, "doMultiFile", m_opts->doMultiFile);
159 	addLPISettings();
160 	addElem(m_root, "solidProf", m_opts->SolidProf);
161 	addElem(m_root, "sComp", m_opts->SComp);
162 	addElem(m_root, "imageProf", m_opts->ImageProf);
163 	addElem(m_root, "embeddedI", m_opts->EmbeddedI);
164 	addElem(m_root, "intent2", m_opts->Intent2);
165 	addElem(m_root, "printProf", m_opts->PrintProf);
166 	addElem(m_root, "info", m_opts->Info);
167 	addElem(m_root, "intent", m_opts->Intent);
168 	addElem(m_root, "bleedTop", m_opts->bleeds.top());
169 	addElem(m_root, "bleedLeft", m_opts->bleeds.left());
170 	addElem(m_root, "bleedRight", m_opts->bleeds.right());
171 	addElem(m_root, "bleedBottom", m_opts->bleeds.bottom());
172 	addElem(m_root, "encrypt", m_opts->Encrypt);
173 	addElem(m_root, "passOwner", m_includePasswords ? m_opts->PassOwner : "");
174 	addElem(m_root, "passUser", m_includePasswords ? m_opts->PassUser : "");
175 	addElem(m_root, "permissions", m_opts->Permissions);
176 }
177 
178 // Convenience functions to add a single-attribute element
179 // of a particular type to the tree at a given point.
180 
addElem(QDomElement & addTo,const QString & name,bool value)181 void PDFOptionsIO::addElem(QDomElement& addTo, const QString& name, bool value)
182 {
183 	QDomElement elem = m_doc.createElement(name);
184 	elem.setAttribute("value", value ? "true" : "false" );
185 	addTo.appendChild(elem);
186 }
187 
addElem(QDomElement & addTo,const QString & name,const QString & value)188 void PDFOptionsIO::addElem(QDomElement& addTo, const QString& name, const QString& value)
189 {
190 	QDomElement elem = m_doc.createElement(name);
191 	elem.setAttribute("value",value);
192 	addTo.appendChild(elem);
193 }
194 
addElem(QDomElement & addTo,const QString & name,int value)195 void PDFOptionsIO::addElem(QDomElement& addTo, const QString& name, int value)
196 {
197 	QDomElement elem = m_doc.createElement(name);
198 	elem.setAttribute("value",value);
199 	addTo.appendChild(elem);
200 }
201 
addElem(QDomElement & addTo,const QString & name,double value)202 void PDFOptionsIO::addElem(QDomElement& addTo, const QString& name, double value)
203 {
204 	QDomElement elem = m_doc.createElement(name);
205 	elem.setAttribute("value",value);
206 	addTo.appendChild(elem);
207 }
208 
209 // Save a QValueList<String> or QStringList as a list of
210 // <item value=""> elements
addList(QDomElement & addTo,const QString & name,QList<QString> & value)211 void PDFOptionsIO::addList(QDomElement& addTo, const QString& name, QList<QString>& value)
212 {
213 	// List base element has no attributes, only children
214 	QDomElement listbase = m_doc.createElement(name);
215 	addTo.appendChild(listbase);
216 	QList<QString>::iterator it;
217 	for (it = value.begin(); it != value.end(); ++it)
218 		addElem(listbase, "item", *(it));
219 }
220 
221 // save PDFOptions::PresentVals
addPresentationData()222 void PDFOptionsIO::addPresentationData()
223 {
224 	// PDFOptions::PresentVals is a QValueList<PDFPresentationData>
225 	//
226 	// XML structure will be like this:
227 	// <presentationSettings>
228 	//   <presentationSettingsEntry>
229 	//     <pageEffectDuration value="0"/>
230 	//     <pageViewDuration value="0"/>
231 	//     <effectType value="0"/>
232 	//     <dm value="0"/>
233 	//     <m value="0"/>
234 	//     <di value="0"/>
235 	//   </presentationSettingsEntry>
236 	//   <presentationSettingsEntry>
237 	//     ...
238 	//   </presentationSettingsEntry>
239 	//   ...
240 	// </presentationSettings>
241 /*	QDomElement presentationSettings = m_doc.createElement("presentationSettings");
242 	m_root.appendChild(presentationSettings);
243 	QList<PDFPresentationData>::iterator it;
244 	for (it = m_opts->PresentVals.begin(); it != m_opts->PresentVals.end(); ++it)
245 	{
246 		// Settings entry has no attributes, only children
247 		QDomElement psEntry = m_doc.createElement("presentationSettingsEntry");
248 		presentationSettings.appendChild(psEntry);
249 		// Children:
250 		addElem(psEntry, "pageEffectDuration", (*it).pageEffectDuration);
251 		addElem(psEntry, "pageViewDuration", (*it).pageViewDuration);
252 		addElem(psEntry, "effectType", (*it).effectType);
253 		addElem(psEntry, "dm", (*it).Dm);
254 		addElem(psEntry, "m", (*it).M);
255 		addElem(psEntry, "di", (*it).Di);
256 	}*/
257 }
258 
259 // Save PDFOptions::LPISettings
addLPISettings()260 void PDFOptionsIO::addLPISettings()
261 {
262 	// PDFOptions::LPISettings is a QMap<QString,LPIData>
263 	//
264 	// XML structure will be like this:
265 	// <lpiSettings>
266 	//   <lpiSettingsEntry name="blah">
267 	//     <frequency value="0">
268 	//     <angle value="0">
269 	//     <spotFunc value="0">
270 	//   </lpiSettingsEntry>
271 	//   <lpiSettingsEntry name="blah2">
272 	//     ...
273 	//   </lpiSettingsEntry>
274 	//   ...
275 	// </lpiSettings>
276 	QDomElement lpiSettings = m_doc.createElement("lpiSettings");
277 	m_root.appendChild(lpiSettings);
278 	QMap<QString,LPIData>::iterator it;
279 	for (it = m_opts->LPISettings.begin(); it != m_opts->LPISettings.end(); ++it)
280 	{
281 		// Settings entry has no attributes, only children
282 		QDomElement lpiEntry = m_doc.createElement("lpiSettingsEntry");
283 		lpiEntry.setAttribute("name", it.key());
284 		lpiSettings.appendChild(lpiEntry);
285 		// Children:
286 		addElem(lpiEntry, "frequency", (*it).Frequency);
287 		addElem(lpiEntry, "angle", (*it).Angle);
288 		addElem(lpiEntry, "spotFunc", (*it).SpotFunc);
289 	}
290 
291 }
292 
293 // overload of bool readFrom(QTextStream& inStream)
readFrom(const QString & inFileName)294 bool PDFOptionsIO::readFrom(const QString& inFileName)
295 {
296 	QFile f(inFileName);
297 	if (!f.open(QIODevice::ReadOnly))
298 	{
299 		m_error = QObject::tr("Could not open input file %1")
300 			.arg(qApp->translate("QFile",f.errorString().toLatin1().constData()));
301 		return false;
302 	}
303 	return readFrom(f);
304 }
305 
readFrom(QIODevice & inDevice)306 bool PDFOptionsIO::readFrom(QIODevice& inDevice)
307 {
308 	if (!inDevice.isReadable())
309 		return false;
310 	QString domError;
311 	int errorLine, errorColumn;
312 	if (!m_doc.setContent(&inDevice, &domError, &errorLine, &errorColumn))
313 	{
314 		m_error = QObject::tr("Unable to read settings XML: %1")
315 			.arg(QObject::tr("%1 (line %2 col %3)", "Load PDF settings")
316 				.arg(domError).arg(errorLine).arg(errorColumn)
317 			);
318 		return false;
319 	}
320 	if (!readSettings())
321 		// m_error should already be set
322 		return false;
323 	m_error.clear();
324 	return true;
325 }
326 
327 // Helper for readFrom(...) to read settings from the DOM
readSettings()328 bool PDFOptionsIO::readSettings()
329 {
330 	// Get the root element
331 	m_root = m_doc.documentElement();
332 	if (m_root.isNull())
333 	{
334 		m_error = QObject::tr("Unable to read settings XML: %1")
335 			.arg(QObject::tr("null root node", "Load PDF settings"));
336 	}
337 	// and start processing elements
338 	if (!readElem(m_root, "firstUse", &m_opts->firstUse))
339 		return false;
340 	if (!readElem(m_root, "thumbnails", &m_opts->Thumbnails))
341 		return false;
342 	if (!readElem(m_root, "articles", &m_opts->Articles))
343 		return false;
344 	if (!readElem(m_root, "useLayers", &m_opts->useLayers))
345 		return false;
346 	if (!readElem(m_root, "compress", &m_opts->Compress))
347 		return false;
348 	if (!readElem(m_root, "compressMethod", (int*) &m_opts->CompressMethod))
349 		return false;
350 	if (!readElem(m_root, "quality", &m_opts->Quality))
351 		return false;
352 	if (!readElem(m_root, "recalcPic", &m_opts->RecalcPic))
353 		return false;
354 	if (!readElem(m_root, "bookmarks", &m_opts->Bookmarks))
355 		return false;
356 	if (!readElem(m_root, "picRes", &m_opts->PicRes))
357 		return false;
358 	if (!readElem(m_root, "embedPDF", &m_opts->embedPDF))
359 		m_opts->embedPDF = false;
360 	if (!readPDFVersion())
361 		return false;
362 	if (!readElem(m_root, "resolution", &m_opts->Resolution))
363 		return false;
364 	if (!readElem(m_root, "binding", &m_opts->Binding))
365 		return false;
366 	if (!readPDFFontEmbeddingMode())
367 		return false;
368 	if (!readList(m_root, "embedFonts", &m_opts->EmbedList))
369 		return false;
370 	if (!readList(m_root, "subsetFonts", &m_opts->SubsetList))
371 		return false;
372 	if (!readElem(m_root, "mirrorH", &m_opts->MirrorH))
373 		return false;
374 	if (!readElem(m_root, "mirrorV", &m_opts->MirrorV))
375 		return false;
376 	if (!readElem(m_root, "rotateDegrees", &m_opts->RotateDeg))
377 		return false;
378 	if (!readElem(m_root, "presentMode", &m_opts->PresentMode))
379 		return false;
380 	// if (!readPresentationData())
381 	// 	return false;
382 	if (!readElem(m_root, "filename", &m_opts->fileName))
383 		return false;
384 	if (!readElem(m_root, "isGrayscale", &m_opts->isGrayscale))
385 		return false;
386 	if (!readElem(m_root, "useRGB", &m_opts->UseRGB))
387 		return false;
388 	if (!readElem(m_root, "useProfiles", &m_opts->UseProfiles))
389 		return false;
390 	if (!readElem(m_root, "useProfiles2", &m_opts->UseProfiles2))
391 		return false;
392 	if (!readElem(m_root, "useLPI", &m_opts->UseLPI))
393 		return false;
394 	if (!readElem(m_root, "useSpotColors", &m_opts->UseSpotColors))
395 		return false;
396 	if (!readElem(m_root, "doMultiFile", &m_opts->doMultiFile))
397 		return false;
398 	if (!readLPISettings())
399 		return false;
400 	if (!readElem(m_root, "solidProf", &m_opts->SolidProf))
401 		return false;
402 	if (!readElem(m_root, "sComp", &m_opts->SComp))
403 		return false;
404 	if (!readElem(m_root, "imageProf", &m_opts->ImageProf))
405 		return false;
406 	if (!readElem(m_root, "embeddedI", &m_opts->EmbeddedI))
407 		return false;
408 	if (!readElem(m_root, "intent2", &m_opts->Intent2))
409 		return false;
410 	if (!readElem(m_root, "printProf", &m_opts->PrintProf))
411 		return false;
412 	if (!readElem(m_root, "info", &m_opts->Info))
413 		return false;
414 	if (!readElem(m_root, "intent", &m_opts->Intent))
415 		return false;
416 	double d=0.0;
417 	if (!readElem(m_root, "bleedTop", &d))
418 		return false;
419 	m_opts->bleeds.setTop(d);
420 	d=0.0;
421 	if (!readElem(m_root, "bleedLeft", &d))
422 		return false;
423 	m_opts->bleeds.setLeft(d);
424 	d=0.0;
425 	if (!readElem(m_root, "bleedBottom", &d))
426 		return false;
427 	m_opts->bleeds.setBottom(d);
428 	d=0.0;
429 	if (!readElem(m_root, "bleedRight", &d))
430 		return false;
431 	m_opts->bleeds.setRight(d);
432 	if (!readElem(m_root, "encrypt", &m_opts->Encrypt))
433 		return false;
434 	if (!readElem(m_root, "passOwner", &m_opts->PassOwner))
435 		return false;
436 	if (!readElem(m_root, "passUser", &m_opts->PassUser))
437 		return false;
438 	if (!readElem(m_root, "permissions", &m_opts->Permissions))
439 		return false;
440 	return true;
441 }
442 
readPDFVersion()443 bool PDFOptionsIO::readPDFVersion()
444 {
445 	QString pdfVersString;
446 	if (!readElem(m_root, "pdfVersion", &pdfVersString))
447 		return false;
448 	if (pdfVersString == "X1a")
449 	{
450 		m_opts->Version = PDFVersion::PDF_X1a;
451 		return true;
452 	}
453 	if (pdfVersString == "X3")
454 	{
455 		m_opts->Version = PDFVersion::PDF_X3;
456 		return true;
457 	}
458 	if (pdfVersString == "X4")
459 	{
460 		m_opts->Version = PDFVersion::PDF_X4;
461 		return true;
462 	}
463 	if (pdfVersString == "13")
464 	{
465 		m_opts->Version = PDFVersion::PDF_13;
466 		return true;
467 	}
468 	if (pdfVersString == "14")
469 	{
470 		m_opts->Version = PDFVersion::PDF_14;
471 		return true;
472 	}
473 	if (pdfVersString == "15")
474 	{
475 		m_opts->Version = PDFVersion::PDF_15;
476 		return true;
477 	}
478 	if (pdfVersString == "16")
479 	{
480 		m_opts->Version = PDFVersion::PDF_16;
481 		return true;
482 	}
483 	m_error = QObject::tr("Unable to read settings XML: %1").arg(QObject::tr("<pdfVersion> invalid", "Load PDF settings"));
484 	return false;
485 }
486 
readPDFFontEmbeddingMode()487 bool PDFOptionsIO::readPDFFontEmbeddingMode()
488 {
489 	QString embeddingMode;
490 	if (!readElem(m_root, "fontEmbedding", &embeddingMode))
491 		return false;
492 
493 	if (embeddingMode == "EmbedFonts")
494 	{
495 		m_opts->FontEmbedding = PDFOptions::EmbedFonts;
496 		return true;
497 	}
498 	if (embeddingMode == "OutlineFonts")
499 	{
500 		m_opts->FontEmbedding = PDFOptions::OutlineFonts;
501 		return true;
502 	}
503 	if (embeddingMode == "DontEmbed")
504 	{
505 		m_opts->FontEmbedding = PDFOptions::DontEmbed;
506 		return true;
507 	}
508 
509 	m_opts->FontEmbedding = PDFOptions::EmbedFonts;
510 	m_error = QObject::tr("Unable to read settings XML: %1")
511 			.arg(QObject::tr("<fontEmbedding> invalid", "Load PDF settings"));
512 	return false;
513 }
514 
515 // returns a null node on failure
getUniqueNode(QDomElement & parent,const QString & name)516 QDomNode PDFOptionsIO::getUniqueNode(QDomElement& parent, const QString& name)
517 {
518 	QDomNodeList nodes = parent.elementsByTagName(name);
519 	if (nodes.count() != 1)
520 	{
521 		m_error = QObject::tr("Unable to read settings XML: %1")
522 			.arg(QObject::tr("found %1 <%2> nodes, need 1.", "Load PDF settings")
523 				.arg(nodes.count()).arg(name)
524 			);
525 		return QDomNode();
526 	}
527 	return nodes.item(0);
528 }
529 
530 // Return the node as a QDomElement iff it is a QDomElement with
531 // a `value' attribute; otherwise return a null element.
getValueElement(QDomNode & node,const QString & name,bool isValue)532 QDomElement PDFOptionsIO::getValueElement(QDomNode& node, const QString& name, bool isValue)
533 {
534 	if (node.isNull())
535 	{
536 		m_error = QObject::tr("Unable to read settings XML: %1")
537 			.arg(QObject::tr("unexpected null <%1> node", "Load PDF settings")
538 				.arg(name)
539 			);
540 		return QDomNode().toElement();
541 	}
542 	if (!node.isElement())
543 	{
544 		m_error = QObject::tr("Unable to read settings XML: %1")
545 			.arg(QObject::tr("node <%1> not an element", "Load PDF settings")
546 				.arg(name)
547 			);
548 		return QDomNode().toElement();
549 	}
550 	QDomElement elem = node.toElement();
551 	if (elem.tagName() != name)
552 	{
553 		m_error = QObject::tr("Unable to read settings XML: %1")
554 			.arg(QString("Internal error: element named <%1> not expected <%2>")
555 					.arg(elem.tagName(), name)
556 			);
557 		return QDomNode().toElement();
558 	}
559 	if (isValue)
560 	{
561 		// We need to check that it has a `value' attribute
562 		if (!elem.hasAttribute("value"))
563 		{
564 			m_error = QObject::tr("Unable to read settings XML: %1")
565 				.arg(QObject::tr("element <%1> lacks `value' attribute", "Load PDF settings")
566 					.arg(name)
567 				);
568 			return QDomNode().toElement();
569 		}
570 	}
571 	return elem;
572 }
573 
readElem(QDomElement & parent,const QString & name,bool * value)574 bool PDFOptionsIO::readElem(QDomElement& parent, const QString& name, bool* value)
575 {
576 	QDomNode node = getUniqueNode(parent, name);
577 	QDomElement elem = getValueElement(node, name);
578 	if (elem.isNull())
579 		return false;
580 	QString elementText = elem.attribute("value");
581 	if (elementText == "true")
582 	{
583 		(*value) = true;
584 		return true;
585 	}
586 	if (elementText == "false")
587 	{
588 		(*value) = false;
589 		return true;
590 	}
591 	m_error = QObject::tr("Unable to read settings XML: %1").arg(QObject::tr("element <%1> value must be `true' or `false'", "Load PDF settings").arg(name));
592 	return false;
593 }
594 
readElem(QDomElement & parent,const QString & name,int * value)595 bool PDFOptionsIO::readElem(QDomElement& parent, const QString& name, int* value)
596 {
597 	QDomNode node = getUniqueNode(parent, name);
598 	QDomElement elem = getValueElement(node, name);
599 	if (elem.isNull())
600 		return false;
601 	bool ok = false;
602 	int result = elem.attribute("value").toInt(&ok);
603 	if (ok)
604 		(*value) = result;
605 	else
606 	{
607 		m_error = QObject::tr("Unable to read settings XML: %1").arg(QObject::tr("element <%1> value must be an integer", "Load PDF settings").arg(name));
608 		return false;
609 	}
610 	return ok;
611 }
612 
readElem(QDomElement & parent,const QString & name,double * value)613 bool PDFOptionsIO::readElem(QDomElement& parent, const QString& name, double* value)
614 {
615 	QDomNode node = getUniqueNode(parent, name);
616 	QDomElement elem = getValueElement(node, name);
617 	if (elem.isNull())
618 		return false;
619 	bool ok = false;
620 	double result = ScCLocale::toDoubleC(elem.attribute("value"), &ok);
621 	if (ok)
622 		(*value) = result;
623 	else
624 	{
625 		m_error = QObject::tr("Unable to read settings XML: %1").arg(QObject::tr("element <%1> value must be a double", "Load PDF settings").arg(name));
626 		return false;
627 	}
628 	return ok;
629 }
630 
readElem(QDomElement & parent,const QString & name,QString * value)631 bool PDFOptionsIO::readElem(QDomElement& parent, const QString& name, QString* value)
632 {
633 	QDomNode node = getUniqueNode(parent, name);
634 	QDomElement elem = getValueElement(node, name);
635 	if (elem.isNull())
636 		return false;
637 	QString result = elem.attribute("value");
638 	bool ok = !result.isNull();
639 	if (ok)
640 		(*value) = result;
641 	return ok;
642 }
643 
644 // Read a stringlist saved as a list of child <item value=""> elements
readList(QDomElement & parent,const QString & name,QList<QString> * value)645 bool PDFOptionsIO::readList(QDomElement& parent, const QString& name, QList<QString>* value)
646 {
647 	QDomNode basenode = getUniqueNode(parent, name);
648 	QDomElement listbase = getValueElement(basenode, name, false);
649 	if (listbase.isNull())
650 		return false;
651 	QList<QString> list;
652 	for (QDomNode node = listbase.firstChild(); !node.isNull(); node = node.nextSibling())
653 	{
654 		QDomElement elem = getValueElement(node, "item");
655 		if (elem.isNull())
656 			return false;
657 		list.append(elem.attribute("value"));
658 	}
659 	(*value) = list;
660 	return true;
661 }
662 
readPresentationData()663 bool PDFOptionsIO::readPresentationData()
664 {
665 	// XML structure will be like this:
666 	// <presentationSettings>
667 	//   <presentationSettingsEntry>
668 	//     <pageEffectDuration value="0"/>
669 	//     <pageViewDuration value="0"/>
670 	//     <effectType value="0"/>
671 	//     <dm value="0"/>
672 	//     <m value="0"/>
673 	//     <di value="0"/>
674 	//   </presentationSettingsEntry>
675 	//   <presentationSettingsEntry>
676 	//     ...
677 	//   </presentationSettingsEntry>
678 	//   ...
679 	// </presentationSettings>
680 	QDomNode basenode = getUniqueNode(m_root, "presentationSettings");
681 	QDomElement pSettings = getValueElement(basenode, "presentationSettings", false);
682 	if (pSettings.isNull())
683 		return false;
684 	QList<PDFPresentationData> pList;
685 	for (QDomNode node = pSettings.firstChild(); !node.isNull(); node = node.nextSibling())
686 	{
687 		QDomElement elem = getValueElement(node, "presentationSettingsEntry", false);
688 		if (elem.isNull())
689 			return false;
690 		PDFPresentationData pres;
691 		if (!readElem(elem, "pageEffectDuration", &pres.pageEffectDuration))
692 			return false;
693 		if (!readElem(elem, "pageViewDuration", &pres.pageViewDuration))
694 			return false;
695 		if (!readElem(elem, "effectType", &pres.effectType))
696 			return false;
697 		if (!readElem(elem, "dm", &pres.Dm))
698 			return false;
699 		if (!readElem(elem, "m", &pres.M))
700 			return false;
701 		if (!readElem(elem, "di", &pres.Di))
702 			return false;
703 		pList.append(pres);
704 	}
705 	return true;
706 }
707 
readLPISettings()708 bool PDFOptionsIO::readLPISettings()
709 {
710 	// XML structure will be like this:
711 	// <lpiSettings>
712 	//   <lpiSettingsEntry name="blah">
713 	//     <frequency value="0">
714 	//     <angle value="0">
715 	//     <spotFunc value="0">
716 	//   </lpiSettingsEntry>
717 	//   <lpiSettingsEntry name="blah2">
718 	//     ...
719 	//   </lpiSettingsEntry>
720 	//   ...
721 	// </lpiSettings>
722 	QDomNode basenode = getUniqueNode(m_root, "lpiSettings");
723 	QDomElement lpiSettings = getValueElement(basenode, "lpiSettings", false);
724 	if (lpiSettings.isNull())
725 		return false;
726 	QMap<QString,LPIData> lpiMap;
727 	for (QDomNode node = lpiSettings.firstChild(); !node.isNull(); node = node.nextSibling())
728 	{
729 		QDomElement elem = getValueElement(node, "lpiSettingsEntry", false);
730 		if (elem.isNull())
731 			return false;
732 		QString name (elem.attribute("name"));
733 		if (name.isNull())
734 		{
735 			m_error = QObject::tr("Unable to read settings XML: %1")
736 				.arg(QObject::tr("element <lpiSettingsEntry> lacks `name' attribute", "Load PDF settings")
737 					.arg(name)
738 				);
739 			return false;
740 		}
741 		LPIData lpi;
742 		if (!readElem(elem, "frequency", &lpi.Frequency))
743 			return false;
744 		if (!readElem(elem, "angle", &lpi.Angle))
745 			return false;
746 		if (!readElem(elem, "spotFunc", &lpi.SpotFunc))
747 			return false;
748 		lpiMap[name] = lpi;
749 	}
750 	return true;
751 }
752 
lastError() const753 const QString& PDFOptionsIO::lastError() const
754 {
755 	return m_error;
756 }
757