filters

ooimpressexport.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2003 Percy Leonhardt
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18*/
19
20#include "ooimpressexport.h"
21
22#include <tqdom.h>
23#include <tqfile.h>
24#include <tqdatetime.h>
25
26#include <kdebug.h>
27#include <kgenericfactory.h>
28#include <KoFilterChain.h>
29#include <KoGlobal.h>
30#include <KoUnit.h>
31
32typedef KGenericFactory<OoImpressExport, KoFilter> OoImpressExportFactory;
33K_EXPORT_COMPONENT_FACTORY( libooimpressexport, OoImpressExportFactory( "kofficefilters" ) )
34
35
36OoImpressExport::OoImpressExport( KoFilter *, const char *, const TQStringList & )
37 : KoFilter()
38 , m_currentPage( 0 )
39 , m_objectIndex( 0 )
40 , m_pageHeight( 0 )
41 , m_activePage( 0 )
42 , m_gridX( -1.0 )
43 , m_gridY( -1.0 )
44 , m_snapToGrid( false )
45 , m_pictureIndex( 0 )
46 , m_storeinp( 0L )
47 , m_storeout( 0L )
48{
49}
50
51OoImpressExport::~OoImpressExport()
52{
53 delete m_storeout;
54 delete m_storeinp;
55}
56
57KoFilter::ConversionStatus OoImpressExport::convert( const TQCString & from,
58 const TQCString & to )
59{
60 kdDebug(30518) << "Entering Ooimpress Export filter: " << from << " - " << to << endl;
61
62 if ( ( to != "application/vnd.sun.xml.impress") || (from != "application/x-kpresenter" ) )
63 {
64 kdWarning(30518) << "Invalid mimetypes " << to << " " << from << endl;
65 return KoFilter::NotImplemented;
66 }
67
68 // read in the KPresenter file
69 KoFilter::ConversionStatus preStatus = openFile();
70
71 if ( preStatus != KoFilter::OK )
72 return preStatus;
73
74 TQDomImplementation impl;
75 TQDomDocument meta( impl.createDocumentType( "office:document-meta",
76 "-//OpenOffice.org//DTD OfficeDocument 1.0//EN",
77 "office.dtd" ) );
78
79 createDocumentMeta( meta );
80
81 // store document meta
82 m_storeout = KoStore::createStore( m_chain->outputFile(), KoStore::Write, "", KoStore::Zip );
83
84 if ( !m_storeout )
85 {
86 kdWarning(30518) << "Couldn't open the requested file." << endl;
87 return KoFilter::FileNotFound;
88 }
89
90 if ( !m_storeout->open( "meta.xml" ) )
91 {
92 kdWarning(30518) << "Couldn't open the file 'meta.xml'." << endl;
93 return KoFilter::CreationError;
94 }
95
96 TQCString metaString = meta.toCString();
97 //kdDebug(30518) << "meta :" << metaString << endl;
98 m_storeout->write( metaString , metaString.length() );
99 m_storeout->close();
100
101 TQDomDocument content( impl.createDocumentType( "office:document-content",
102 "-//OpenOffice.org//DTD OfficeDocument 1.0//EN",
103 "office.dtd" ) );
104
105 createDocumentContent( content );
106
107 // add the automatic styles
108 m_styleFactory.addAutomaticStyles( content, m_styles );
109
110 // store document content
111 if ( !m_storeout->open( "content.xml" ) )
112 {
113 kdWarning(30518) << "Couldn't open the file 'content.xml'." << endl;
114 return KoFilter::CreationError;
115 }
116
117 TQCString contentString = content.toCString();
118 //kdDebug(30518) << "content :" << contentString << endl;
119 m_storeout->write( contentString , contentString.length() );
120 m_storeout->close();
121
122 TQDomDocument settings( impl.createDocumentType( "office:document-content",
123 "-//OpenOffice.org//DTD OfficeDocument 1.0//EN",
124 "office.dtd" ) );
125
126 createDocumentSettings( settings );
127
128 // store document content
129 if ( !m_storeout->open( "settings.xml" ) )
130 {
131 kdWarning(30518) << "Couldn't open the file 'settings.xml'." << endl;
132 return KoFilter::CreationError;
133 }
134
135 TQCString settingsString = settings.toCString();
136 //kdDebug(30518) << "content :" << settingsString << endl;
137 m_storeout->write( settingsString , settingsString.length() );
138 m_storeout->close();
139
140
141 TQDomDocument styles( impl.createDocumentType( "office:document-styles",
142 "-//OpenOffice.org//DTD OfficeDocument 1.0//EN",
143 "office.dtd" ) );
144
145 createDocumentStyles( styles );
146
147 // store document styles
148 if ( !m_storeout->open( "styles.xml" ) )
149 {
150 kdWarning(30518) << "Couldn't open the file 'styles.xml'." << endl;
151 return KoFilter::CreationError;
152 }
153
154 TQCString stylesString = styles.toCString();
155 //kdDebug(30518) << "styles :" << stylesString << endl;
156 m_storeout->write( stylesString , stylesString.length() );
157 m_storeout->close();
158
159 TQDomDocument manifest( impl.createDocumentType( "manifest:manifest",
160 "-//OpenOffice.org//DTD Manifest 1.0//EN",
161 "Manifest.dtd" ) );
162
163 createDocumentManifest( manifest );
164
165 // store document manifest
166 m_storeout->enterDirectory( "META-INF" );
167 if ( !m_storeout->open( "manifest.xml" ) )
168 {
169 kdWarning(30518) << "Couldn't open the file 'META-INF/manifest.xml'." << endl;
170 return KoFilter::CreationError;
171 }
172
173 TQCString manifestString = manifest.toCString();
174 //kdDebug(30518) << "manifest :" << manifestString << endl;
175 m_storeout->write( manifestString , manifestString.length() );
176 m_storeout->close();
177
178 return KoFilter::OK;
179}
180
181KoFilter::ConversionStatus OoImpressExport::openFile()
182{
183 m_storeinp = KoStore::createStore( m_chain->inputFile(), KoStore::Read );
184
185 if ( !m_storeinp )
186 {
187 kdWarning(30518) << "Couldn't open the requested file." << endl;
188 return KoFilter::FileNotFound;
189 }
190
191 if ( !m_storeinp->open( "maindoc.xml" ) )
192 {
193 kdWarning(30518) << "This file doesn't seem to be a valid KPresenter file" << endl;
194 return KoFilter::WrongFormat;
195 }
196
197 m_maindoc.setContent( m_storeinp->device() );
198 m_storeinp->close();
199
200 if ( m_storeinp->open( "documentinfo.xml" ) )
201 {
202 m_documentinfo.setContent( m_storeinp->device() );
203 m_storeinp->close();
204 }
205 else
206 kdWarning(30518) << "Documentinfo do not exist!" << endl;
207
208 emit sigProgress( 10 );
209
210 return KoFilter::OK;
211}
212
213void OoImpressExport::createDocumentMeta( TQDomDocument & docmeta )
214{
215 docmeta.appendChild( docmeta.createProcessingInstruction( "xml","version=\"1.0\" encoding=\"UTF-8\"" ) );
216
217 TQDomElement content = docmeta.createElement( "office:document-meta" );
218 content.setAttribute( "xmlns:office", "http://openoffice.org/2000/office" );
219 content.setAttribute( "xmlns:xlink", "http://www.w3.org/1999/xlink" );
220 content.setAttribute( "xmlns:dc", "http://purl.org/dc/elements/1.1/" );
221 content.setAttribute( "xmlns:meta", "http://openoffice.org/2000/meta" );
222 content.setAttribute( "office:version", "1.0" );
223
224 TQDomNode meta = docmeta.createElement( "office:meta" );
225
226 TQDomElement generator = docmeta.createElement( "meta:generator" );
227 generator.appendChild( docmeta.createTextNode( "KPresenter 1.5" ) );
228 meta.appendChild( generator );
229
230 TQDomNode i = m_documentinfo.namedItem( "document-info" );
231 if ( !i.isNull() )
232 {
233 TQDomNode n = i.namedItem( "author" ).namedItem( "full-name" );
234 if ( !n.isNull() )
235 {
236 TQDomElement fullName = n.toElement();
237 TQDomElement creator = docmeta.createElement( "meta:initial-creator" );
238 creator.appendChild( docmeta.createTextNode( fullName.text() ) );
239 meta.appendChild( creator );
240
241 creator = docmeta.createElement( "meta:creator" );
242 creator.appendChild( docmeta.createTextNode( fullName.text() ) );
243 meta.appendChild( creator );
244 }
245 n = i.namedItem( "about" ).namedItem( "abstract" );
246 if ( !n.isNull() )
247 {
248 TQDomElement user = docmeta.createElement( "dc:description" );
249 user.appendChild( n.firstChild() );
250 meta.appendChild( user );
251 }
252 n = i.namedItem( "about" ).namedItem( "keyword" );
253 if ( !n.isNull() )
254 {
255 TQDomElement text = n.toElement();
256 TQDomElement key = docmeta.createElement( "meta:keywords" );
257 TQDomElement keyword = docmeta.createElement( "meta:keyword" );
258 key.appendChild( keyword );
259 keyword.appendChild( docmeta.createTextNode( text.text() ) );
260 meta.appendChild( key );
261 }
262 n = i.namedItem( "about" ).namedItem( "subject" );
263 if ( !n.isNull() )
264 {
265 TQDomElement text = n.toElement();
266 TQDomElement subjet = docmeta.createElement( "dc:subject" );
267 subjet.appendChild( docmeta.createTextNode( text.text() ) );
268 meta.appendChild( subjet );
269 }
270 n = i.namedItem( "about" ).namedItem( "title" );
271 if ( !n.isNull() )
272 {
273 TQDomElement text = n.toElement();
274 TQDomElement title = docmeta.createElement( "dc:title" );
275 title.appendChild( docmeta.createTextNode( text.text() ) );
276 meta.appendChild( title );
277 }
278 }
279
280// TQDomElement statistic = docmeta.createElement( "meta:document-statistic" );
281// statistic.setAttribute( "meta:object-count", 0 );
282// meta.appendChild( data );
283
284 content.appendChild( meta );
285 docmeta.appendChild( content );
286}
287
288void OoImpressExport::createDocumentStyles( TQDomDocument & docstyles )
289{
290 docstyles.appendChild( docstyles.createProcessingInstruction( "xml","version=\"1.0\" encoding=\"UTF-8\"" ) );
291
292 TQDomElement content = docstyles.createElement( "office:document-content" );
293 content.setAttribute( "xmlns:office", "http://openoffice.org/2000/office" );
294 content.setAttribute( "xmlns:style", "http://openoffice.org/2000/style" );
295 content.setAttribute( "xmlns:text", "http://openoffice.org/2000/text" );
296 content.setAttribute( "xmlns:table", "http://openoffice.org/2000/table" );
297 content.setAttribute( "xmlns:draw", "http://openoffice.org/2000/drawing" );
298 content.setAttribute( "xmlns:fo", "http://www.w3.org/1999/XSL/Format" );
299 content.setAttribute( "xmlns:xlink", "http://www.w3.org/1999/xlink" );
300 content.setAttribute( "xmlns:number", "http://openoffice.org/2000/datastyle" );
301 content.setAttribute( "xmlns:svg", "http://www.w3.org/2000/svg" );
302 content.setAttribute( "xmlns:chart", "http://openoffice.org/2000/chart" );
303 content.setAttribute( "xmlns:dr3d", "http://openoffice.org/2000/dr3d" );
304 content.setAttribute( "xmlns:math", "http://www.w3.org/1998/Math/MathML" );
305 content.setAttribute( "xmlns:form", "http://openoffice.org/2000/form" );
306 content.setAttribute( "xmlns:script", "http://openoffice.org/2000/script" );
307 content.setAttribute( "office:version", "1.0" );
308
309 // order important here!
310 TQDomElement styles = docstyles.createElement( "office:styles" );
311 m_styleFactory.addOfficeStyles( docstyles, styles );
312 content.appendChild( styles );
313
314 TQDomElement automatic = docstyles.createElement( "office:automatic-styles" );
315 m_styleFactory.addOfficeAutomatic( docstyles, automatic );
316 content.appendChild( automatic );
317
318 TQDomElement master = docstyles.createElement( "office:master-styles" );
319 m_styleFactory.addOfficeMaster( docstyles, master );
320 content.appendChild( master );
321
322 docstyles.appendChild( content );
323}
324
325void OoImpressExport::createDocumentSettings( TQDomDocument & docsetting )
326{
327 docsetting.appendChild( docsetting.createProcessingInstruction( "xml","version=\"1.0\" encoding=\"UTF-8\"" ) );
328
329 TQDomElement setting = docsetting.createElement( "office:document-settings" );
330 setting.setAttribute( "xmlns:office", "http://openoffice.org/2000/office");
331 setting.setAttribute( "xmlns:config", "http://openoffice.org/2001/config" );
332 setting.setAttribute( "office:class", "presentation" );
333 setting.setAttribute( "office:version", "1.0" );
334
335 TQDomElement begin = docsetting.createElement( "office:settings" );
336
337 TQDomElement configItem = docsetting.createElement("config:config-item-set" );
338 configItem.setAttribute( "config:name", "view-settings" );
339
340 TQDomElement mapIndexed = docsetting.createElement( "config:config-item-map-indexed" );
341 mapIndexed.setAttribute("config:name", "Views" );
342 configItem.appendChild( mapIndexed );
343
344 //<config:config-item-map-indexed config:name="Views">
345
346 TQDomElement mapItem = docsetting.createElement("config:config-item-map-entry" );
347
348 TQDomElement attribute = docsetting.createElement("config:config-item" );
349 attribute.setAttribute( "config:name", "SnapLinesDrawing" );
350 attribute.setAttribute( "config:type", "string" );
351 attribute.appendChild( docsetting.createTextNode( m_helpLine ) );
352 mapItem.appendChild( attribute );
353 //<config:config-item config:name="SnapLinesDrawing" config:type="string">H5983V700V10777H4518V27601P50000,9000P8021,2890</config:config-item>
354
355 attribute = docsetting.createElement("config:config-item" );
356 attribute.setAttribute( "config:name", "IsSnapToGrid" );
357 attribute.setAttribute( "config:type", "boolean" );
358 attribute.appendChild( docsetting.createTextNode( m_snapToGrid ? "true" : "false" ) );
359 mapItem.appendChild( attribute );
360
361 if ( m_gridX >=0 )
362 {
363 attribute = docsetting.createElement("config:config-item" );
364 attribute.setAttribute( "config:name", "GridFineWidth" );
365 attribute.setAttribute( "config:type", "int" );
366 attribute.appendChild( docsetting.createTextNode( TQString::number( ( int ) ( KoUnit::toMM( ( m_gridX ) )*100 ) ) ) );
367 mapItem.appendChild( attribute );
368 }
369
370 if ( m_gridY >=0 )
371 {
372 attribute = docsetting.createElement("config:config-item" );
373 attribute.setAttribute( "config:name", "GridFineHeight" );
374 attribute.setAttribute( "config:type", "int" );
375 attribute.appendChild( docsetting.createTextNode( TQString::number( ( int ) ( KoUnit::toMM( ( m_gridY ) )*100 ) ) ) );
376 mapItem.appendChild( attribute );
377 }
378
379 attribute = docsetting.createElement("config:config-item" );
380 attribute.setAttribute( "config:name", "SelectedPage" );
381 attribute.setAttribute( "config:type", "short" );
382 attribute.appendChild( docsetting.createTextNode( TQString::number( m_activePage ) ) );
383 mapItem.appendChild( attribute );
384
385
386 mapIndexed.appendChild( mapItem );
387
388 begin.appendChild( configItem );
389
390 setting.appendChild( begin );
391
392
393 docsetting.appendChild( setting );
394
395}
396
397void OoImpressExport::createDocumentContent( TQDomDocument & doccontent )
398{
399 doccontent.appendChild( doccontent.createProcessingInstruction( "xml","version=\"1.0\" encoding=\"UTF-8\"" ) );
400
401 TQDomElement content = doccontent.createElement( "office:document-content" );
402 content.setAttribute( "xmlns:office", "http://openoffice.org/2000/office");
403 content.setAttribute( "xmlns:style", "http://openoffice.org/2000/style" );
404 content.setAttribute( "xmlns:text", "http://openoffice.org/2000/text" );
405 content.setAttribute( "xmlns:table", "http://openoffice.org/2000/table" );
406 content.setAttribute( "xmlns:draw", "http://openoffice.org/2000/drawing" );
407 content.setAttribute( "xmlns:fo", "http://www.w3.org/1999/XSL/Format" );
408 content.setAttribute( "xmlns:xlink", "http://www.w3.org/1999/xlink" );
409 content.setAttribute( "xmlns:number", "http://openoffice.org/2000/datastyle" );
410 content.setAttribute( "xmlns:svg", "http://www.w3.org/2000/svg" );
411 content.setAttribute( "xmlns:chart", "http://openoffice.org/2000/chart" );
412 content.setAttribute( "xmlns:dr3d", "http://openoffice.org/2000/dr3d" );
413 content.setAttribute( "xmlns:math", "http://www.w3.org/1998/Math/MathML" );
414 content.setAttribute( "xmlns:form", "http://openoffice.org/2000/form" );
415 content.setAttribute( "xmlns:script", "http://openoffice.org/2000/script" );
416 content.setAttribute( "xmlns:presentation", "http://openoffice.org/2000/presentation" );
417 content.setAttribute( "office:class", "presentation" );
418 content.setAttribute( "office:version", "1.0" );
419
420 TQDomElement script = doccontent.createElement( "office:script" );
421 content.appendChild( script );
422
423 m_styles = doccontent.createElement( "office:automatic-styles" );
424 content.appendChild( m_styles );
425
426 TQDomElement body = doccontent.createElement( "office:body" );
427 exportBody( doccontent, body );
428 content.appendChild( body );
429
430 doccontent.appendChild( content );
431}
432
433void OoImpressExport::createDocumentManifest( TQDomDocument & docmanifest )
434{
435 docmanifest.appendChild( docmanifest.createProcessingInstruction( "xml","version=\"1.0\" encoding=\"UTF-8\"" ) );
436
437 TQDomElement manifest = docmanifest.createElement( "manifest:manifest" );
438 manifest.setAttribute( "xmlns:manifest", "http://openoffice.org/2001/manifest" );
439
440 TQDomElement entry = docmanifest.createElement( "manifest:file-entry" );
441 entry.setAttribute( "manifest:media-type", "application/vnd.sun.xml.impress" );
442 entry.setAttribute( "manifest:full-path", "/" );
443 manifest.appendChild( entry );
444
445 TQMap<TQString, TQString>::Iterator it;
446 for ( it = m_pictureLst.begin(); it != m_pictureLst.end(); ++it )
447 {
448 entry = docmanifest.createElement( "manifest:file-entry" );
449 entry.setAttribute( "manifest:media-type", it.data() );
450 entry.setAttribute( "manifest:full-path", it.key() );
451 manifest.appendChild( entry );
452 }
453
454 entry = docmanifest.createElement( "manifest:file-entry" );
455 entry.setAttribute( "manifest:media-type", "text/xml" );
456 entry.setAttribute( "manifest:full-path", "content.xml" );
457 manifest.appendChild( entry );
458
459 entry = docmanifest.createElement( "manifest:file-entry" );
460 entry.setAttribute( "manifest:media-type", "text/xml" );
461 entry.setAttribute( "manifest:full-path", "styles.xml" );
462 manifest.appendChild( entry );
463
464 entry = docmanifest.createElement( "manifest:file-entry" );
465 entry.setAttribute( "manifest:media-type", "text/xml" );
466 entry.setAttribute( "manifest:full-path", "meta.xml" );
467 manifest.appendChild( entry );
468
469 entry = docmanifest.createElement( "manifest:file-entry" );
470 entry.setAttribute( "manifest:media-type", "text/xml" );
471 entry.setAttribute( "manifest:full-path", "settings.xml" );
472 manifest.appendChild( entry );
473
474 docmanifest.appendChild( manifest );
475}
476
477TQString OoImpressExport::pictureKey( TQDomElement &elem )
478{
479 // Default date/time is the *nix epoch: 1970-01-01 00:00:00,000
480 int year=1970, month=1, day=1;
481 int hour=0, minute=0, second=0, msec=0; // We must initialize to zero, as not all compilers are C99-compliant
482 if ( elem.tagName() == "KEY" )
483 {
484 if( elem.hasAttribute( "year" ) )
485 year=elem.attribute( "year" ).toInt();
486 if( elem.hasAttribute( "month" ) )
487 month=elem.attribute( "month" ).toInt();
488 if( elem.hasAttribute( "day" ) )
489 day=elem.attribute( "day" ).toInt();
490 if( elem.hasAttribute( "hour" ) )
491 hour=elem.attribute( "hour" ).toInt();
492 if( elem.hasAttribute( "minute" ) )
493 minute=elem.attribute( "minute" ).toInt();
494 if( elem.hasAttribute( "second" ) )
495 second=elem.attribute( "second" ).toInt();
496 if( elem.hasAttribute( "msec" ) )
497 msec=elem.attribute( "msec" ).toInt();
498 }
499 TQDateTime key;
500 key.setDate( TQDate( year, month, day ) );
501 key.setTime( TQTime( hour, minute, second, msec ) );
502 return key.toString();
503}
504
505void OoImpressExport::createPictureList( TQDomNode &pictures )
506{
507 pictures = pictures.firstChild();
508 for( ; !pictures.isNull(); pictures = pictures.nextSibling() )
509 {
510 if ( pictures.isElement() )
511 {
512 TQDomElement element = pictures.toElement();
513 if ( element.tagName() == "KEY" )
514 {
515 //kdDebug(30518)<<"element.attribute( name ) :"<<element.attribute( "name" )<<endl;
516 m_kpresenterPictureLst.insert( pictureKey( element ), element.attribute( "name" ) );
517 }
518 else
519 kdDebug(30518)<<" Tag not recognize :"<<element.tagName()<<endl;
520 }
521 }
522}
523
524void OoImpressExport::createAttribute( TQDomNode &attributeValue )
525{
526 TQDomElement elem = attributeValue.toElement();
527 if(elem.hasAttribute("activePage"))
528 m_activePage=elem.attribute("activePage").toInt();
529 if(elem.hasAttribute("gridx"))
530 m_gridX = elem.attribute("gridx").toDouble();
531 if(elem.hasAttribute("gridy"))
532 m_gridY = elem.attribute("gridy").toDouble();
533 if(elem.hasAttribute("snaptogrid"))
534 m_snapToGrid = (bool)elem.attribute("snaptogrid").toInt();
535}
536
537void OoImpressExport::createHelpLine( TQDomNode &helpline )
538{
539 helpline = helpline.firstChild();
540 TQDomElement helplines;
541 for( ; !helpline.isNull(); helpline = helpline.nextSibling() )
542 {
543 if ( helpline.isElement() )
544 {
545 helplines = helpline.toElement();
546 if ( helplines.tagName()=="Vertical" )
547 {
548 int tmpX = ( int ) ( KoUnit::toMM( helplines.attribute("value").toDouble() )*100 );
549 m_helpLine+="V"+TQString::number( tmpX );
550 }
551 else if ( helplines.tagName()=="Horizontal" )
552 {
553 int tmpY = ( int ) ( KoUnit::toMM( helplines.attribute("value").toDouble() )*100 );
554 m_helpLine+="H"+TQString::number( tmpY );
555 }
556 else if ( helplines.tagName()=="HelpPoint" )
557 {
558 TQString str( "P%1,%2" );
559 int tmpX = ( int ) ( KoUnit::toMM( helplines.attribute("posX").toDouble() )*100 );
560 int tmpY = ( int ) ( KoUnit::toMM( helplines.attribute("posY").toDouble() )*100 );
561 m_helpLine+=str.arg( TQString::number( tmpX ) ).arg( TQString::number( tmpY ) );
562 }
563 }
564 }
565 //kdDebug(30518)<<"m_helpLine :"<<m_helpLine<<endl;
566}
567
568
569void OoImpressExport::exportBody( TQDomDocument & doccontent, TQDomElement & body )
570{
571 TQDomNode doc = m_maindoc.namedItem( "DOC" );
572 TQDomNode paper = doc.namedItem( "PAPER" );
573 TQDomNode background = doc.namedItem( "BACKGROUND" );
574 TQDomNode header = doc.namedItem( "HEADER" );
575 TQDomNode footer = doc.namedItem( "FOOTER" );
576 TQDomNode titles = doc.namedItem( "PAGETITLES" );
577 TQDomNode notes = doc.namedItem( "PAGENOTES" );
578 TQDomNode objects = doc.namedItem( "OBJECTS" );
579 TQDomNode pictures = doc.namedItem( "PICTURES" );
580 TQDomNode sounds = doc.namedItem( "SOUNDS" );
581 TQDomNode helpline = doc.namedItem( "HELPLINES" );
582 TQDomNode attributeValue = doc.namedItem( "ATTRIBUTES" );
583 TQDomNode infiniLoop = doc.namedItem( "INFINITLOOP" );
584 TQDomNode manualSwitch = doc.namedItem( "MANUALSWITCH" );
585 TQDomNode customSlideShow = doc.namedItem( "CUSTOMSLIDESHOWCONFIG" );
586 TQDomNode customSlideShowDefault = doc.namedItem( "DEFAULTCUSTOMSLIDESHOWNAME" );
587
588 TQDomNode bgpage = background.firstChild();
589
590 createPictureList( pictures );
591
592 createHelpLine( helpline );
593
594 createAttribute( attributeValue );
595
596 // store the paper settings
597 TQDomElement p = paper.toElement();
598 m_masterPageStyle = m_styleFactory.createPageMasterStyle( p );
599 m_pageHeight = p.attribute( "ptHeight" ).toFloat();
600
601 m_currentPage = 1;
602
603 // parse all pages
604 TQDomNode note = notes.firstChild();
605 for ( TQDomNode title = titles.firstChild(); !title.isNull() && !note.isNull();
606 title = title.nextSibling(), note = note.nextSibling() )
607 {
608 // create the page style and ignore the fact that there may
609 // be less backgrounds than pages
610 TQDomElement bg = bgpage.toElement();
611 TQString ps = m_styleFactory.createPageStyle( bg );
612 bgpage = bgpage.nextSibling();
613
614 TQDomElement t = title.toElement();
615 TQDomElement drawPage = doccontent.createElement( "draw:page" );
616 drawPage.setAttribute( "draw:name", t.attribute( "title" ) );
617 drawPage.setAttribute( "draw:style-name", ps );
618 drawPage.setAttribute( "draw:id", m_currentPage );
619 drawPage.setAttribute( "draw:master-page-name", m_masterPageStyle );
620
621 appendObjects( doccontent, objects, drawPage );
622
623 TQDomElement noteElement = note.toElement();
624 appendNote( doccontent, noteElement, drawPage );
625 body.appendChild( drawPage );
626 m_currentPage++;
627 }
628 int infiniLoopValue = -1;
629 int manualSwitchValue = -1;
630 if ( !infiniLoop.isNull() && infiniLoop.toElement().hasAttribute( "value" ))
631 {
632 bool ok;
633 int val = infiniLoop.toElement().attribute( "value" ).toInt( &ok );
634 if ( ok )
635 infiniLoopValue = val;
636 }
637 if ( !manualSwitch.isNull() && manualSwitch.toElement().hasAttribute( "value" ))
638 {
639 bool ok;
640 int val = manualSwitch.toElement().attribute( "value" ).toInt( &ok );
641 if ( ok )
642 manualSwitchValue = val;
643 }
644 if ( infiniLoopValue != -1 || manualSwitchValue != -1 || !customSlideShowDefault.isNull())
645 {
646 TQDomElement settings = doccontent.createElement( "presentation:settings" );
647 if ( infiniLoopValue !=-1 )
648 settings.setAttribute( "presentation:force-manual", ( manualSwitchValue==1 ) ? "true" : "false" );
649 if ( manualSwitchValue != -1 )
650 settings.setAttribute( "presentation:endless", ( infiniLoopValue==1 ) ? "true": "false" );
651 if ( !customSlideShowDefault.isNull() )
652 settings.setAttribute( "presentation:show", customSlideShowDefault.toElement().attribute( "name" ) );
653
654 if ( !customSlideShow.isNull() )
655 {
656 for ( TQDomNode customPage = customSlideShow.firstChild(); !customPage.isNull();
657 customPage = customPage.nextSibling() )
658 {
659 TQDomElement show = customPage.toElement();
660 if ( !show.isNull() && show.tagName()=="CUSTOMSLIDESHOW" )
661 {
662 TQDomElement showElement = doccontent.createElement( "presentation:show" );
663 showElement.setAttribute( "presentation:name",show.attribute( "name" ) );
664 showElement.setAttribute( "presentation:pages",show.attribute( "pages" ) );
665 settings.appendChild( showElement );
666 }
667 }
668 }
669 body.appendChild( settings );
670 }
671}
672
673
674void OoImpressExport::appendObjects(TQDomDocument & doccontent, TQDomNode &objects, TQDomElement &drawPage)
675{
676 // I am not sure if objects are always stored sorted so I parse all
677 // of them to find the ones belonging to a certain page.
678 for ( TQDomNode object = objects.firstChild(); !object.isNull();
679 object = object.nextSibling() )
680 {
681 TQDomElement o = object.toElement();
682
683 TQDomElement orig = o.namedItem( "ORIG" ).toElement();
684 float y = orig.attribute( "y" ).toFloat();
685
686 if ( y < m_pageHeight * ( m_currentPage - 1 ) ||
687 y >= m_pageHeight * m_currentPage )
688 continue; // object not on current page
689
690 switch( o.attribute( "type" ).toInt() )
691 {
692 case 0: // image
693 appendPicture( doccontent, o, drawPage );
694 break;
695 case 1: // line
696 appendLine( doccontent, o, drawPage );
697 break;
698 case 2: // rectangle
699 appendRectangle( doccontent, o, drawPage );
700 break;
701 case 3: // circle, ellipse
702 appendEllipse( doccontent, o, drawPage );
703 break;
704 case 4: // textbox
705 appendTextbox( doccontent, o, drawPage );
706 break;
707 case 5:
708 kdDebug(30518)<<" autoform not implemented\n";
709 break;
710 case 6:
711 kdDebug(30518)<<" clipart not implemented\n";
712 break;
713 case 8: // pie, chord, arc
714 appendEllipse( doccontent, o, drawPage, true );
715 break;
716 case 9: //part
717 kdDebug(30518)<<" part object not implemented \n";
718 break;
719 case 10:
720 appendGroupObject( doccontent, o, drawPage );
721 break;
722 case 11:
723 kdDebug(30518)<<" free hand not implemented\n";
724 break;
725 case 12: // polyline
726 appendPolyline( doccontent, o, drawPage );
727 break;
728 case 13: //OT_QUADRICBEZIERCURVE = 13
729 case 14: //OT_CUBICBEZIERCURVE = 14
730 //todo
731 // "draw:path"
732 break;
733 case 15: // polygon
734 case 16: // close polygone
735 appendPolyline( doccontent, o, drawPage, true /*polygon*/ );
736 break;
737 }
738 ++m_objectIndex;
739 }
740
741}
742
743void OoImpressExport::appendGroupObject( TQDomDocument & doc, TQDomElement & source, TQDomElement & target )
744{
745 TQDomElement groupElement = doc.createElement( "draw:g" );
746 TQDomNode objects = source.namedItem( "OBJECTS" );
747 appendObjects( doc, objects, groupElement);
748 target.appendChild( groupElement );
749}
750
751void OoImpressExport::appendNote( TQDomDocument & doc, TQDomElement & source, TQDomElement & target )
752{
753 TQString noteText = source.attribute("note");
754 //kdDebug(30518)<<"noteText :"<<noteText<<endl;
755 if ( noteText.isEmpty() )
756 return;
757 TQDomElement noteElement = doc.createElement( "presentation:notes" );
758 TQDomElement noteTextBox = doc.createElement( "draw:text-box" );
759
760 //TODO : add draw:text-box size :
761 //<draw:text-box draw:style-name="gr2" draw:text-style-name="P2" draw:layer="layout" svg:width="13.336cm" svg:height="56.288cm" svg:x="-0.54cm" svg:y="-14.846cm">
762
763 TQStringList text = TQStringList::split( "\n", noteText );
764 for ( TQStringList::Iterator it = text.begin(); it != text.end(); ++it ) {
765 TQDomElement tmp = doc.createElement( "text:p" );
766 tmp.appendChild( doc.createTextNode( *it ) );
767 noteTextBox.appendChild( tmp );
768 }
769 noteElement.appendChild( noteTextBox );
770 target.appendChild( noteElement );
771}
772
773void OoImpressExport::appendTextbox( TQDomDocument & doc, TQDomElement & source, TQDomElement & target )
774{
775 TQDomElement textbox = doc.createElement( "draw:text-box" );
776
777 TQDomNode textobject = source.namedItem( "TEXTOBJ" );
778
779 // create the graphic style
780 TQString gs = m_styleFactory.createGraphicStyle( source );
781 textbox.setAttribute( "draw:style-name", gs );
782
783 // set the geometry
784 set2DGeometry( source, textbox );
785
786 // parse every paragraph
787 for ( TQDomNode paragraph = textobject.firstChild(); !paragraph.isNull();
788 paragraph = paragraph.nextSibling() )
789 {
790 TQDomElement p = paragraph.toElement();
791 appendParagraph( doc, p, textbox );
792 }
793
794 target.appendChild( textbox );
795}
796
797void OoImpressExport::appendParagraph( TQDomDocument & doc, TQDomElement & source, TQDomElement & target )
798{
799 TQDomElement paragraph = doc.createElement( "text:p" );
800
801 // create the paragraph style
802 TQString ps = m_styleFactory.createParagraphStyle( source );
803 paragraph.setAttribute( "text:style-name", ps );
804
805 // parse every text element
806 for ( TQDomNode text = source.firstChild(); !text.isNull();
807 text = text.nextSibling() )
808 {
809 if ( text.nodeName() == "TEXT" )
810 {
811 TQDomElement t = text.toElement();
812 appendText( doc, t, paragraph );
813 }
814 }
815
816 // take care of lists
817 TQDomNode counter = source.namedItem( "COUNTER" );
818 if ( !counter.isNull() )
819 {
820 TQDomElement c = counter.toElement();
821 int type = c.attribute( "type" ).toInt();
822
823 int level = 1;
824 if ( c.hasAttribute( "depth" ) )
825 level = c.attribute( "depth" ).toInt() + 1;
826
827 TQDomElement endOfList = target;
828 for ( int l = 0; l < level; l++ )
829 {
830 TQDomElement list;
831 if ( type == 1 )
832 {
833 list = doc.createElement( "text:ordered-list" );
834 list.setAttribute( "text:continue-numbering", "true" );
835 }
836 else
837 list = doc.createElement( "text:unordered-list" );
838
839 if ( l == 0 )
840 {
841 // create the list style
842 TQString ls = m_styleFactory.createListStyle( c );
843 list.setAttribute( "text:style-name", ls );
844 }
845
846 TQDomElement item = doc.createElement( "text:list-item" );
847 list.appendChild( item );
848 endOfList.appendChild( list );
849 endOfList = item;
850 }
851
852 endOfList.appendChild( paragraph );
853 }
854 else
855 target.appendChild( paragraph );
856}
857
858void OoImpressExport::appendText( TQDomDocument & doc, TQDomElement & source, TQDomElement & target )
859{
860 TQDomElement textspan = doc.createElement( "text:span" );
861
862 // create the text style
863 TQString ts = m_styleFactory.createTextStyle( source );
864 textspan.setAttribute( "text:style-name", ts );
865
866 textspan.appendChild( doc.createTextNode( source.text() ) );
867 target.appendChild( textspan );
868}
869
870void OoImpressExport::appendPicture( TQDomDocument & doc, TQDomElement & source, TQDomElement & target )
871{
872 TQDomElement image = doc.createElement( "draw:image" );
873
874 // create the graphic style
875 TQString gs = m_styleFactory.createGraphicStyle( source );
876 image.setAttribute( "draw:style-name", gs );
877 TQDomElement key = source.namedItem( "KEY" ).toElement();
878
879 TQString pictureName = TQString( "Picture/Picture%1" ).arg( m_pictureIndex );
880
881 image.setAttribute( "xlink:type", "simple" );
882 image.setAttribute( "xlink:show", "embed" );
883 image.setAttribute( "xlink:actuate", "onLoad");
884
885 if ( !key.isNull() )
886 {
887 TQString str = pictureKey( key );
888 TQString returnstr = m_kpresenterPictureLst[str];
889 const int pos=returnstr.findRev('.');
890 if (pos!=-1)
891 {
892 const TQString extension( returnstr.mid(pos+1) );
893 pictureName +="."+extension;
894 }
895
896 if ( m_storeinp->open( returnstr ) )
897 {
898 if ( m_storeout->open( pictureName ) )
899 {
900 TQByteArray data(8*1024);
901 uint total = 0;
902 for ( int block = 0; ( block = m_storeinp->read(data.data(), data.size()) ) > 0;
903 total += block )
904 m_storeout->write(data.data(), data.size());
905 m_storeout->close();
906 m_storeinp->close();
907 }
908 }
909 }
910 image.setAttribute( "xlink:href", "#" + pictureName );
911
912// set the geometry
913 set2DGeometry( source, image );
914 target.appendChild( image );
915
916 m_pictureLst.insert( pictureName , "image/png" );
917
918 ++m_pictureIndex;
919}
920
921
922void OoImpressExport::appendLine( TQDomDocument & doc, TQDomElement & source, TQDomElement & target )
923{
924 TQDomElement line = doc.createElement( "draw:line" );
925
926 // create the graphic style
927 TQString gs = m_styleFactory.createGraphicStyle( source );
928 line.setAttribute( "draw:style-name", gs );
929
930 // set the geometry
931 setLineGeometry( source, line );
932
933 target.appendChild( line );
934}
935
936void OoImpressExport::appendRectangle( TQDomDocument & doc, TQDomElement & source, TQDomElement & target )
937{
938 TQDomElement rectangle = doc.createElement( "draw:rect" );
939
940 // create the graphic style
941 TQString gs = m_styleFactory.createGraphicStyle( source );
942 rectangle.setAttribute( "draw:style-name", gs );
943
944 // set the geometry
945 set2DGeometry( source, rectangle );
946
947 target.appendChild( rectangle );
948}
949
950void OoImpressExport::appendPolyline( TQDomDocument & doc, TQDomElement & source, TQDomElement & target, bool _poly)
951{
952 TQDomElement polyline = doc.createElement( _poly ? "draw:polygon" : "draw:polyline" );
953
954 // create the graphic style
955 TQString gs = m_styleFactory.createGraphicStyle( source );
956 polyline.setAttribute( "draw:style-name", gs );
957
958 // set the geometry
959 set2DGeometry( source, polyline, false, true /*multipoint*/ );
960
961 target.appendChild( polyline );
962}
963
964void OoImpressExport::appendEllipse( TQDomDocument & doc, TQDomElement & source, TQDomElement & target, bool pieObject )
965{
966 TQDomElement size = source.namedItem( "SIZE" ).toElement();
967
968 double width = size.attribute( "width" ).toDouble();
969 double height = size.attribute( "height" ).toDouble();
970
971 TQDomElement ellipse = doc.createElement( (width == height) ? "draw:circle" : "draw:ellipse" );
972
973 // create the graphic style
974 TQString gs = m_styleFactory.createGraphicStyle( source );
975 ellipse.setAttribute( "draw:style-name", gs );
976
977 // set the geometry
978 set2DGeometry( source, ellipse, pieObject );
979
980 target.appendChild( ellipse );
981}
982
983void OoImpressExport::set2DGeometry( TQDomElement & source, TQDomElement & target, bool pieObject, bool multiPoint )
984{
985 TQDomElement orig = source.namedItem( "ORIG" ).toElement();
986 TQDomElement size = source.namedItem( "SIZE" ).toElement();
987 TQDomElement name = source.namedItem( "OBJECTNAME").toElement();
988 float y = orig.attribute( "y" ).toFloat();
989 y -= m_pageHeight * ( m_currentPage - 1 );
990
991 TQDomElement angle = source.namedItem( "ANGLE").toElement();
992 if ( !angle.isNull() )
993 {
994 TQString returnAngle = rotateValue( angle.attribute( "value" ).toDouble() );
995 if ( !returnAngle.isEmpty() )
996 target.setAttribute("draw:transform",returnAngle );
997 }
998
999 target.setAttribute( "draw:id", TQString::number( m_objectIndex ) );
1000 target.setAttribute( "svg:x", StyleFactory::toCM( orig.attribute( "x" ) ) );
1001 target.setAttribute( "svg:y", TQString( "%1cm" ).arg( KoUnit::toCM( y ) ) );
1002 target.setAttribute( "svg:width", StyleFactory::toCM( size.attribute( "width" ) ) );
1003 target.setAttribute( "svg:height", StyleFactory::toCM( size.attribute( "height" ) ) );
1004 TQString nameStr = name.attribute("objectName");
1005 if( !nameStr.isEmpty() )
1006 target.setAttribute( "draw:name", nameStr );
1007 if ( pieObject )
1008 {
1009 TQDomElement pie = source.namedItem( "PIETYPE").toElement();
1010 if( !pie.isNull() )
1011 {
1012 int typePie = pie.attribute("value").toInt();
1013 switch( typePie )
1014 {
1015 case 0:
1016 target.setAttribute( "draw:kind", "section");
1017 break;
1018 case 1:
1019 target.setAttribute( "draw:kind", "arc");
1020 break;
1021 case 2:
1022 target.setAttribute( "draw:kind", "cut");
1023 break;
1024 default:
1025 kdDebug(30518)<<" type unknown : "<<typePie<<endl;
1026 break;
1027 }
1028 }
1029 else
1030 target.setAttribute( "draw:kind", "section");//by default
1031 TQDomElement pieAngle = source.namedItem( "PIEANGLE").toElement();
1032 int startangle = 45;
1033 if( !pieAngle.isNull() )
1034 {
1035 startangle = (pieAngle.attribute("value").toInt())/16;
1036 target.setAttribute( "draw:start-angle", startangle);
1037 }
1038 else
1039 {
1040 //default value take it into kppieobject
1041 target.setAttribute( "draw:start-angle", 45 );
1042 }
1043 TQDomElement pieLength = source.namedItem( "PIELENGTH").toElement();
1044 if( !pieLength.isNull() )
1045 {
1046 int value = pieLength.attribute("value").toInt();
1047 value = value /16;
1048 value = value + startangle;
1049 target.setAttribute( "draw:end-angle", value );
1050 }
1051 else
1052 {
1053 //default value take it into kppieobject
1054 //default is 90° into kpresenter
1055 target.setAttribute( "draw:end-angle", (90+startangle) );
1056 }
1057 }
1058 if ( multiPoint )
1059 {
1060 //loadPoint
1061 TQDomElement point = source.namedItem( "POINTS" ).toElement();
1062 if ( !point.isNull() ) {
1063 TQDomElement elemPoint = point.firstChild().toElement();
1064 TQString listOfPoint;
1065 int maxX=0;
1066 int maxY=0;
1067 while ( !elemPoint.isNull() ) {
1068 if ( elemPoint.tagName() == "Point" ) {
1069 int tmpX = 0;
1070 int tmpY = 0;
1071 if( elemPoint.hasAttribute( "point_x" ) )
1072 tmpX = ( int ) ( KoUnit::toMM( elemPoint.attribute( "point_x" ).toDouble() )*100 );
1073 if( elemPoint.hasAttribute( "point_y" ) )
1074 tmpY = ( int ) ( KoUnit::toMM(elemPoint.attribute( "point_y" ).toDouble() )*100 );
1075 if ( !listOfPoint.isEmpty() )
1076 listOfPoint += TQString( " %1,%2" ).arg( tmpX ).arg( tmpY );
1077 else
1078 listOfPoint = TQString( "%1,%2" ).arg( tmpX ).arg( tmpY );
1079 maxX = TQMAX( maxX, tmpX );
1080 maxY = TQMAX( maxY, tmpY );
1081 }
1082 elemPoint = elemPoint.nextSibling().toElement();
1083 }
1084 target.setAttribute( "draw:points", listOfPoint );
1085 target.setAttribute( "svg:viewBox", TQString( "0 0 %1 %2" ).arg( maxX ).arg( maxY ) );
1086 }
1087 }
1088}
1089
1090TQString OoImpressExport::rotateValue( double val )
1091{
1092 TQString str;
1093 if ( val!=0.0 )
1094 {
1095 double value = -1 * ( ( double )val* M_PI )/180.0;
1096 str=TQString( "rotate (%1)" ).arg( value );
1097 }
1098 return str;
1099}
1100
1101
1102void OoImpressExport::setLineGeometry( TQDomElement & source, TQDomElement & target )
1103{
1104 TQDomElement orig = source.namedItem( "ORIG" ).toElement();
1105 TQDomElement size = source.namedItem( "SIZE" ).toElement();
1106 TQDomElement linetype = source.namedItem( "LINETYPE" ).toElement();
1107 TQDomElement name = source.namedItem( "OBJECTNAME").toElement();
1108 TQDomElement angle = source.namedItem( "ANGLE").toElement();
1109 if ( !angle.isNull() )
1110 {
1111 TQString returnAngle = rotateValue( angle.attribute( "value" ).toDouble() );
1112 if ( !returnAngle.isEmpty() )
1113 target.setAttribute("draw:transform",returnAngle );
1114 }
1115 float x1 = orig.attribute( "x" ).toFloat();
1116 float y1 = orig.attribute( "y" ).toFloat();
1117 float x2 = size.attribute( "width" ).toFloat();
1118 float y2 = size.attribute( "height" ).toFloat();
1119 int type = 0;
1120 if ( !linetype.isNull() )
1121 type = linetype.attribute( "value" ).toInt();
1122 y1 -= m_pageHeight * ( m_currentPage - 1 );
1123 x2 += x1;
1124 y2 += y1;
1125
1126 target.setAttribute( "draw:id", TQString::number( m_objectIndex ) );
1127 TQString xpos1 = StyleFactory::toCM( orig.attribute( "x" ) );
1128 TQString xpos2 = TQString( "%1cm" ).arg( KoUnit::toCM( x2 ) );
1129
1130 if ( type == 0 )
1131 {
1132 target.setAttribute( "svg:y1", TQString( "%1cm" ).arg( KoUnit::toCM( y2/2.0 ) ) );
1133 target.setAttribute( "svg:y2", TQString( "%1cm" ).arg( KoUnit::toCM( y2/2.0 ) ) );
1134 }
1135 else if ( type == 1 )
1136 {
1137 target.setAttribute( "svg:y1", TQString( "%1cm" ).arg( KoUnit::toCM( y1 ) ) );
1138 target.setAttribute( "svg:y2", TQString( "%1cm" ).arg( KoUnit::toCM( y2 ) ) );
1139 xpos1 = TQString( "%1cm" ).arg( KoUnit::toCM( x1/2.0 ) );
1140 xpos2 = xpos1;
1141 }
1142 else if ( type == 3 ) // from left bottom to right top
1143 {
1144 target.setAttribute( "svg:y1", TQString( "%1cm" ).arg( KoUnit::toCM( y2 ) ) );
1145 target.setAttribute( "svg:y2", TQString( "%1cm" ).arg( KoUnit::toCM( y1 ) ) );
1146 }
1147 else // from left top to right bottom
1148 {
1149 target.setAttribute( "svg:y1", TQString( "%1cm" ).arg( KoUnit::toCM( y1 ) ) );
1150 target.setAttribute( "svg:y2", TQString( "%1cm" ).arg( KoUnit::toCM( y2 ) ) );
1151 }
1152 target.setAttribute( "svg:x1", xpos1 );
1153 target.setAttribute( "svg:x2", xpos2 );
1154
1155 TQString nameStr = name.attribute("objectName");
1156 if( !nameStr.isEmpty() )
1157 target.setAttribute( "draw:name", nameStr );
1158}
1159
1160#include "ooimpressexport.moc"