• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdeedu API Reference
  • KDE Home
  • Contact Us
 

kig

  • sources
  • kde-4.12
  • kdeedu
  • kig
  • filters
native-filter.cc
Go to the documentation of this file.
1 // Copyright (C) 2003 Dominique Devriese <devriese@kde.org>
2 
3 // This program is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU General Public License
5 // as published by the Free Software Foundation; either version 2
6 // of the License, or (at your option) any later version.
7 
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
12 
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 // 02110-1301, USA.
17 
18 #include "native-filter.h"
19 
20 #include "../kig/kig_part.h"
21 #include "../kig/kig_document.h"
22 #include "../objects/bogus_imp.h"
23 #include "../objects/object_type.h"
24 #include "../objects/object_imp.h"
25 #include "../objects/object_calcer.h"
26 #include "../objects/object_drawer.h"
27 #include "../objects/object_holder.h"
28 #include "../objects/object_type_factory.h"
29 #include "../objects/object_imp_factory.h"
30 #include "../misc/calcpaths.h"
31 #include "../misc/coordinate_system.h"
32 
33 #include <config-kig.h>
34 
35 #include <qbytearray.h>
36 #include <qdom.h>
37 #include <qfile.h>
38 #include <qfont.h>
39 #include <qregexp.h>
40 #include <qtextstream.h>
41 
42 #include <karchive.h>
43 #include <kdebug.h>
44 #include <kglobal.h>
45 #include <kstandarddirs.h>
46 #include <ktar.h>
47 
48 #include <stdio.h>
49 
50 #include <vector>
51 #include <algorithm>
52 #include <map>
53 
54 struct HierElem
55 {
56  int id;
57  std::vector<int> parents;
58  QDomElement el;
59 };
60 
61 static void extendVect( std::vector<HierElem>& vect, uint size )
62 {
63  if ( size > vect.size() )
64  {
65  int osize = vect.size();
66  vect.resize( size );
67  for ( uint i = osize; i < size; ++i )
68  vect[i].id = i+1;
69  };
70 }
71 
72 static void visitElem( std::vector<HierElem>& ret,
73  const std::vector<HierElem>& elems,
74  std::vector<bool>& seen,
75  int i )
76 {
77  if ( !seen[i] )
78  {
79  for ( uint j = 0; j < elems[i].parents.size(); ++j )
80  visitElem( ret, elems, seen, elems[i].parents[j] - 1);
81  ret.push_back( elems[i] );
82  seen[i] = true;
83  };
84 }
85 
86 static std::vector<HierElem> sortElems( const std::vector<HierElem> elems )
87 {
88  std::vector<HierElem> ret;
89  std::vector<bool> seenElems( elems.size(), false );
90  for ( uint i = 0; i < elems.size(); ++i )
91  visitElem( ret, elems, seenElems, i );
92  return ret;
93 }
94 
95 KigFilterNative::KigFilterNative()
96 {
97 }
98 
99 KigFilterNative::~KigFilterNative()
100 {
101 }
102 
103 bool KigFilterNative::supportMime( const QString& mime )
104 {
105  return mime == "application/x-kig";
106 }
107 
108 KigDocument* KigFilterNative::load( const QString& file )
109 {
110  QFile ffile( file );
111  if ( ! ffile.open( QIODevice::ReadOnly ) )
112  {
113  fileNotFound( file );
114  return 0;
115  };
116 
117  QFile kigdoc( file );
118  bool iscompressed = false;
119  if ( !file.endsWith( ".kig", Qt::CaseInsensitive ) )
120  {
121  // the file is compressed, so we have to decompress it and fetch the
122  // kig file inside it...
123  iscompressed = true;
124 
125  QString tempdir = KGlobal::dirs()->saveLocation( "tmp" );
126  if ( tempdir.isEmpty() )
127  KIG_FILTER_PARSE_ERROR;
128 
129  QString tempname = file.section( '/', -1 );
130  if ( file.endsWith( ".kigz", Qt::CaseInsensitive ) )
131  {
132  tempname.remove( QRegExp( "\\.[Kk][Ii][Gg][Zz]$" ) );
133  }
134  else
135  KIG_FILTER_PARSE_ERROR;
136  // reading compressed file
137  KTar ark( file, "application/x-gzip" );
138  ark.open( QIODevice::ReadOnly );
139  const KArchiveDirectory* dir = ark.directory();
140 // assert( dir );
141  QStringList entries = dir->entries();
142  QStringList kigfiles = entries.filter( QRegExp( "\\.kig$" ) );
143  if ( kigfiles.count() != 1 )
144  // I throw a generic parse error here, but I should warn the user that
145  // this kig archive file doesn't contain one kig file (it contains no
146  // kig files or more than one).
147  KIG_FILTER_PARSE_ERROR;
148  const KArchiveEntry* kigz = dir->entry( kigfiles.at( 0 ) );
149  if ( !kigz->isFile() )
150  KIG_FILTER_PARSE_ERROR;
151  dynamic_cast<const KArchiveFile*>( kigz )->copyTo( tempdir );
152  kDebug() << "extracted file: " << tempdir + kigz->name()
153  << "exists: " << QFile::exists( tempdir + kigz->name() ) << endl;
154 
155  kigdoc.setFileName( tempdir + kigz->name() );
156  }
157 
158  if ( !kigdoc.open( QIODevice::ReadOnly ) )
159  KIG_FILTER_PARSE_ERROR;
160 
161  QDomDocument doc( "KigDocument" );
162  if ( !doc.setContent( &kigdoc ) )
163  KIG_FILTER_PARSE_ERROR;
164  kigdoc.close();
165 
166  // removing temp file
167  if ( iscompressed )
168  kigdoc.remove();
169 
170  QDomElement main = doc.documentElement();
171 
172  QString version = main.attribute( "CompatibilityVersion" );
173  if ( version.isEmpty() ) version = main.attribute( "Version" );
174  if ( version.isEmpty() ) version = main.attribute( "version" );
175  if ( version.isEmpty() )
176  KIG_FILTER_PARSE_ERROR;
177 
178  // matches 0.1, 0.2.0, 153.128.99 etc.
179  QRegExp versionre( "(\\d+)\\.(\\d+)(\\.(\\d+))?" );
180  if ( ! versionre.exactMatch( version ) )
181  KIG_FILTER_PARSE_ERROR;
182  bool ok = true;
183  int major = versionre.cap( 1 ).toInt( &ok );
184  bool ok2 = true;
185  int minor = versionre.cap( 2 ).toInt( &ok2 );
186  if ( ! ok || ! ok2 )
187  KIG_FILTER_PARSE_ERROR;
188 
189  // int minorminor = versionre.cap( 4 ).toInt( &ok );
190 
191  // we only support 0.[0-7] and 1.0.*
192  if ( major > 0 || minor > 9 )
193  {
194  notSupported( file, i18n( "This file was created by Kig version \"%1\", "
195  "which this version cannot open.", version ) );
196  return 0;
197  }
198  else if ( major == 0 && minor <= 3 )
199  {
200  notSupported( file, i18n( "This file was created by Kig version \"%1\".\n"
201  "Support for older Kig formats (pre-0.4) has been "
202  "removed from Kig.\n"
203  "You can try to open this file with an older Kig "
204  "version (0.4 to 0.6),\n"
205  "and then save it again, which will save it in the "
206  "new format.", version ) );
207  return 0;
208  }
209  else if ( major == 0 && minor <= 6 )
210  return load04( file, main );
211  else
212  return load07( file, main );
213 }
214 
215 KigDocument* KigFilterNative::load04( const QString& file, const QDomElement& docelem )
216 {
217  bool ok = true;
218 
219  KigDocument* ret = new KigDocument();
220 
221  for ( QDomNode n = docelem.firstChild(); ! n.isNull(); n = n.nextSibling() )
222  {
223  QDomElement e = n.toElement();
224  if ( e.isNull() ) continue;
225  if ( e.tagName() == "CoordinateSystem" )
226  {
227  const QByteArray type = e.text().toLatin1();
228  CoordinateSystem* s = CoordinateSystemFactory::build( type.data() );
229  if ( ! s )
230  {
231  warning( i18n( "This Kig file has a coordinate system "
232  "that this Kig version does not support.\n"
233  "A standard coordinate system will be used "
234  "instead." ) );
235  }
236  else ret->setCoordinateSystem( s );
237  }
238  else if ( e.tagName() == "Objects" )
239  {
240  std::vector<ObjectCalcer*> retcalcers;
241  std::vector<ObjectHolder*> retholders;
242 
243  // first pass: do a topological sort of the objects, to support
244  // randomly ordered files...
245  std::vector<HierElem> elems;
246  QDomElement objectselem = e;
247  for ( QDomNode o = objectselem.firstChild(); ! o.isNull(); o = o.nextSibling() )
248  {
249  e = o.toElement();
250  if ( e.isNull() ) continue;
251  uint id;
252  if ( e.tagName() == "Data" || e.tagName() == "Property" || e.tagName() == "Object" )
253  {
254  // fetch the id
255  QString tmp = e.attribute("id");
256  id = tmp.toInt(&ok);
257  if ( !ok ) KIG_FILTER_PARSE_ERROR;
258 
259  extendVect( elems, id );
260  elems[id-1].el = e;
261  }
262  else continue;
263 
264  for ( QDomNode p = e.firstChild(); !p.isNull(); p = p.nextSibling() )
265  {
266  QDomElement f = p.toElement();
267  if ( f.isNull() ) continue;
268  if ( f.tagName() == "Parent" )
269  {
270  QString tmp = f.attribute( "id" );
271  uint pid = tmp.toInt( &ok );
272  if ( ! ok ) KIG_FILTER_PARSE_ERROR;
273 
274  extendVect( elems, id );
275  elems[id-1].parents.push_back( pid );
276  }
277  }
278  };
279 
280  for ( uint i = 0; i < elems.size(); ++i )
281  if ( elems[i].el.isNull() )
282  KIG_FILTER_PARSE_ERROR;
283  elems = sortElems( elems );
284 
285  retcalcers.resize( elems.size(), 0 );
286 
287  for ( std::vector<HierElem>::iterator i = elems.begin();
288  i != elems.end(); ++i )
289  {
290  QDomElement e = i->el;
291  bool internal = e.attribute( "internal" ) == "true" ? true : false;
292  ObjectCalcer* o = 0;
293  if ( e.tagName() == "Data" )
294  {
295  QString tmp = e.attribute( "type" );
296  if ( tmp.isNull() )
297  KIG_FILTER_PARSE_ERROR;
298  QString error;
299  ObjectImp* imp = ObjectImpFactory::instance()->deserialize( tmp, e, error );
300  if ( ( !imp ) && !error.isEmpty() )
301  {
302  parseError( file, error );
303  return 0;
304  }
305  o = new ObjectConstCalcer( imp );
306  }
307  else if ( e.tagName() == "Property" )
308  {
309  QByteArray propname;
310  for ( QDomElement ec = e.firstChild().toElement(); !ec.isNull();
311  ec = ec.nextSibling().toElement() )
312  {
313  if ( ec.tagName() == "Property" )
314  propname = ec.text().toLatin1();
315  };
316 
317  if ( i->parents.size() != 1 ) KIG_FILTER_PARSE_ERROR;
318  ObjectCalcer* parent = retcalcers[i->parents[0] -1];
319  QByteArrayList propnames = parent->imp()->propertiesInternalNames();
320  int propid = propnames.indexOf( propname );
321  if ( propid == -1 )
322  KIG_FILTER_PARSE_ERROR;
323 
324  o = new ObjectPropertyCalcer( parent, propname );
325  }
326  else if ( e.tagName() == "Object" )
327  {
328  QString tmp = e.attribute( "type" );
329  if ( tmp.isNull() )
330  KIG_FILTER_PARSE_ERROR;
331 
332  const ObjectType* type =
333  ObjectTypeFactory::instance()->find( tmp.toLatin1() );
334  if ( !type )
335  {
336  notSupported( file, i18n( "This Kig file uses an object of type \"%1\", "
337  "which this Kig version does not support."
338  "Perhaps you have compiled Kig without support "
339  "for this object type,"
340  "or perhaps you are using an older Kig version.", tmp ) );
341  return 0;
342  };
343 
344  std::vector<ObjectCalcer*> parents;
345  for ( std::vector<int>::iterator j = i->parents.begin();
346  j != i->parents.end(); ++j )
347  parents.push_back( retcalcers[*j - 1] );
348 
349  o = new ObjectTypeCalcer( type, parents );
350  }
351  else continue;
352 
353  o->calc( *ret );
354  retcalcers[i->id - 1] = o;
355 
356  if ( ! internal )
357  {
358  QString tmp = e.attribute( "color" );
359  QColor color( tmp );
360  if ( !color.isValid() )
361  KIG_FILTER_PARSE_ERROR;
362 
363  tmp = e.attribute( "shown" );
364  bool shown = !( tmp == "false" || tmp == "no" );
365 
366  tmp = e.attribute( "width" );
367  int width = tmp.toInt( &ok );
368  if ( ! ok ) width = -1;
369 
370  ObjectDrawer* d = new ObjectDrawer( color, width, shown );
371  retholders.push_back( new ObjectHolder( o, d ) );
372  }
373  }
374  ret->addObjects( retholders );
375  }
376  else continue; // be forward-compatible..
377  };
378 
379  return ret;
380 }
381 
382 KigFilterNative* KigFilterNative::instance()
383 {
384  static KigFilterNative f;
385  return &f;
386 }
387 
388 static const char* obsoletemessage = I18N_NOOP(
389  "This Kig file uses an object of type \"%1\", "
390  "which is obsolete, you should save the construction with "
391  "a different name and check that it works as expected." );
392 
393 KigDocument* KigFilterNative::load07( const QString& file, const QDomElement& docelem )
394 {
395  KigDocument* ret = new KigDocument();
396 
397  bool ok = true;
398  std::vector<ObjectCalcer::shared_ptr> calcers;
399  std::vector<ObjectHolder*> holders;
400 
401  QString t = docelem.attribute( "grid" );
402  bool tmphide = ( t == "false" ) || ( t == "no" ) || ( t == "0" );
403  ret->setGrid( !tmphide );
404  t = docelem.attribute( "axes" );
405  tmphide = ( t == "false" ) || ( t == "no" ) || ( t == "0" );
406  ret->setAxes( !tmphide );
407 
408  for ( QDomElement subsectionelement = docelem.firstChild().toElement(); ! subsectionelement.isNull();
409  subsectionelement = subsectionelement.nextSibling().toElement() )
410  {
411  if ( subsectionelement.tagName() == "CoordinateSystem" )
412  {
413  QString tmptype = subsectionelement.text();
414  // compatibility code - to support Invisible coord system...
415  if ( tmptype == "Invisible" )
416  {
417  tmptype = "Euclidean";
418  ret->setGrid( false );
419  ret->setAxes( false );
420  }
421  const QByteArray type = tmptype.toLatin1();
422  CoordinateSystem* s = CoordinateSystemFactory::build( type.data() );
423  if ( ! s )
424  {
425  warning( i18n( "This Kig file has a coordinate system "
426  "that this Kig version does not support.\n"
427  "A standard coordinate system will be used "
428  "instead." ) );
429  }
430  else ret->setCoordinateSystem( s );
431  }
432  else if ( subsectionelement.tagName() == "Hierarchy" )
433  {
434  for ( QDomElement e = subsectionelement.firstChild().toElement(); ! e.isNull();
435  e = e.nextSibling().toElement() )
436  {
437  QString tmp = e.attribute( "id" );
438  uint id = tmp.toInt( &ok );
439  if ( id <= 0 ) KIG_FILTER_PARSE_ERROR;
440 
441  std::vector<ObjectCalcer*> parents;
442  for ( QDomElement parentel = e.firstChild().toElement(); ! parentel.isNull();
443  parentel = parentel.nextSibling().toElement() )
444  {
445  if ( parentel.tagName() != "Parent" ) continue;
446  QString tmp = parentel.attribute( "id" );
447  uint parentid = tmp.toInt( &ok );
448  if ( ! ok ) KIG_FILTER_PARSE_ERROR;
449  if ( parentid == 0 || parentid > calcers.size() ) KIG_FILTER_PARSE_ERROR;
450  ObjectCalcer* parent = calcers[parentid - 1].get();
451  if ( ! parent ) KIG_FILTER_PARSE_ERROR;
452  parents.push_back( parent );
453  }
454 
455  ObjectCalcer* o = 0;
456 
457  if ( e.tagName() == "Data" )
458  {
459  if ( !parents.empty() ) KIG_FILTER_PARSE_ERROR;
460  QString tmp = e.attribute( "type" );
461  QString error;
462  ObjectImp* imp = ObjectImpFactory::instance()->deserialize( tmp, e, error );
463  if ( ( !imp ) && !error.isEmpty() )
464  {
465  parseError( file, error );
466  return 0;
467  }
468  o = new ObjectConstCalcer( imp );
469  }
470  else if ( e.tagName() == "Property" )
471  {
472  if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR;
473  QByteArray propname = e.attribute( "which" ).toLatin1();
474 
475  ObjectCalcer* parent = parents[0];
476  int propid = parent->imp()->propertiesInternalNames().indexOf( propname );
477  if ( propid == -1 ) KIG_FILTER_PARSE_ERROR;
478 
479  o = new ObjectPropertyCalcer( parent, propname );
480  }
481  else if ( e.tagName() == "Object" )
482  {
483  QString tmp = e.attribute( "type" );
484  const ObjectType* type =
485  ObjectTypeFactory::instance()->find( tmp.toLatin1() );
486  if ( ! type )
487  {
488  if ( tmp == "MeasureTransport" && parents.size() == 3 )
489  {
490  warning( i18n( obsoletemessage, tmp ) );
491  type = ObjectTypeFactory::instance()->find( "TransportOfMeasure" );
492  ObjectCalcer* circle = parents[0];
493  ObjectCalcer* point = parents[1];
494  ObjectCalcer* segment = parents[2];
495  parents[0] = segment;
496  parents[1] = circle;
497  parents[2] = point;
498  } else if ( tmp == "InvertLine" )
499  {
500  warning( i18n( obsoletemessage, tmp ) );
501  type = ObjectTypeFactory::instance()->find( "CircularInversion" );
502  } else if ( tmp == "InvertSegment" )
503  {
504  warning( i18n( obsoletemessage, tmp ) );
505  type = ObjectTypeFactory::instance()->find( "CircularInversion" );
506  } else if ( tmp == "InvertCircle" )
507  {
508  warning( i18n( obsoletemessage, tmp ) );
509  type = ObjectTypeFactory::instance()->find( "CircularInversion" );
510  } else if ( tmp == "InvertArc" )
511  {
512  warning( i18n( obsoletemessage, tmp ) );
513  type = ObjectTypeFactory::instance()->find( "CircularInversion" );
514  } else if ( tmp == "ConicArcBTPC" )
515  {
516  warning( i18n( obsoletemessage, tmp ) );
517  type = ObjectTypeFactory::instance()->find( "ConicArcBCTP" );
518  //
519  // the only difference is in the order of parents
520  // entering the center first seems more useful, and allows
521  // for a better user interface
522  //
523  ObjectCalcer* point = parents[3];
524  parents[3] = parents[2];
525  parents[2] = parents[1];
526  parents[1] = parents[0];
527  parents[0] = point;
528  } else {
529  notSupported( file, i18n( "This Kig file uses an object of type \"%1\", "
530  "which this Kig version does not support."
531  "Perhaps you have compiled Kig without support "
532  "for this object type,"
533  "or perhaps you are using an older Kig version.", tmp ) );
534  return 0;
535  }
536  }
537 
538  // mp: (I take the responsibility for this!) explanation: the usual ObjectTypeCalcer
539  // constructor also "sortArgs" the parents. I believe that this *must not* be done
540  // when loading from a saved kig file for the following reasons:
541  // 1. the arguments should already be in their intended order, since the file was
542  // saved from a working hierarchy; furthermore we actually want to restore the original
543  // hierarchy, not really to also fix possible problems with the original hierarchy;
544  // 2. calling sortArgs could have undesirable side effects in particular situations,
545  // since kig actually allow an ObjectType to produce different type of ObjectImp's
546  // it may happen that the parents of an object do not satisfy the requirements
547  // enforced by sortArgs (while moving around the free objects) but still be
548  // perfectly valid
549  o = new ObjectTypeCalcer( type, parents, false );
550  }
551  else KIG_FILTER_PARSE_ERROR;
552 
553  o->calc( *ret );
554  calcers.resize( id, 0 );
555  calcers[id-1] = o;
556  }
557  }
558  else if ( subsectionelement.tagName() == "View" )
559  {
560  for ( QDomElement e = subsectionelement.firstChild().toElement(); ! e.isNull();
561  e = e.nextSibling().toElement() )
562  {
563  if ( e.tagName() != "Draw" ) KIG_FILTER_PARSE_ERROR;
564 
565  QString tmp = e.attribute( "object" );
566  uint id = tmp.toInt( &ok );
567  if ( !ok ) KIG_FILTER_PARSE_ERROR;
568  if ( id <= 0 || id > calcers.size() )
569  KIG_FILTER_PARSE_ERROR;
570  ObjectCalcer* calcer = calcers[id-1].get();
571 
572  tmp = e.attribute( "color" );
573  QColor color( tmp );
574  if ( !color.isValid() )
575  KIG_FILTER_PARSE_ERROR;
576 
577  tmp = e.attribute( "shown" );
578  bool shown = !( tmp == "false" || tmp == "no" );
579 
580  tmp = e.attribute( "width" );
581  int width = tmp.toInt( &ok );
582  if ( ! ok ) width = -1;
583 
584  tmp = e.attribute( "style" );
585  Qt::PenStyle style = ObjectDrawer::styleFromString( tmp );
586 
587  tmp = e.attribute( "point-style" );
588  int pointstyle = ObjectDrawer::pointStyleFromString( tmp );
589 
590  tmp = e.attribute( "font" );
591  QFont f;
592  if ( !tmp.isEmpty() )
593  f.fromString( tmp );
594 
595  ObjectConstCalcer* namecalcer = 0;
596  tmp = e.attribute( "namecalcer" );
597  if ( tmp != "none" && !tmp.isEmpty() )
598  {
599  int ncid = tmp.toInt( &ok );
600  if ( !ok ) KIG_FILTER_PARSE_ERROR;
601  if ( ncid <= 0 || ncid > static_cast<int>( calcers.size() ) )
602  KIG_FILTER_PARSE_ERROR;
603  if ( ! dynamic_cast<ObjectConstCalcer*>( calcers[ncid-1].get() ) )
604  KIG_FILTER_PARSE_ERROR;
605  namecalcer = static_cast<ObjectConstCalcer*>( calcers[ncid-1].get() );
606  }
607 
608  ObjectDrawer* drawer = new ObjectDrawer( color, width, shown, style, pointstyle, f );
609  holders.push_back( new ObjectHolder( calcer, drawer, namecalcer ) );
610  }
611  }
612  }
613 
614  ret->addObjects( holders );
615  return ret;
616 }
617 
618 bool KigFilterNative::save07( const KigDocument& kdoc, QTextStream& stream )
619 {
620  QDomDocument doc( "KigDocument" );
621 
622  QDomProcessingInstruction xmlpi = doc.createProcessingInstruction(
623  QString::fromLatin1( "xml" ), QString::fromLatin1( "version=\"1.0\" encoding=\"utf-8\"" ) );
624  doc.appendChild( xmlpi );
625 
626  QDomElement docelem = doc.createElement( "KigDocument" );
627  docelem.setAttribute( "Version", KIGVERSION );
628  docelem.setAttribute( "CompatibilityVersion", "0.7.0" );
629  docelem.setAttribute( "grid", kdoc.grid() );
630  docelem.setAttribute( "axes", kdoc.axes() );
631 
632  QDomElement cselem = doc.createElement( "CoordinateSystem" );
633  cselem.appendChild( doc.createTextNode( kdoc.coordinateSystem().type() ) );
634  docelem.appendChild( cselem );
635 
636  std::vector<ObjectHolder*> holders = kdoc.objects();
637  std::vector<ObjectCalcer*> calcers = getAllParents( getAllCalcers( holders ) );
638  calcers = calcPath( calcers );
639 
640  QDomElement hierelem = doc.createElement( "Hierarchy" );
641  std::map<const ObjectCalcer*, int> idmap;
642  for ( std::vector<ObjectCalcer*>::const_iterator i = calcers.begin();
643  i != calcers.end(); ++i )
644  idmap[*i] = ( i - calcers.begin() ) + 1;
645  int id = 1;
646 
647  for ( std::vector<ObjectCalcer*>::const_iterator i = calcers.begin(); i != calcers.end(); ++i )
648  {
649  QDomElement objectelem;
650  if ( dynamic_cast<ObjectConstCalcer*>( *i ) )
651  {
652  objectelem = doc.createElement( "Data" );
653  QString ser =
654  ObjectImpFactory::instance()->serialize( *(*i)->imp(), objectelem, doc );
655  objectelem.setAttribute( "type", ser );
656  }
657  else if ( dynamic_cast<const ObjectPropertyCalcer*>( *i ) )
658  {
659  const ObjectPropertyCalcer* o = static_cast<const ObjectPropertyCalcer*>( *i );
660  objectelem = doc.createElement( "Property" );
661 
662  QByteArray propname = o->parent()->imp()->getPropName( o->propGid() );
663  objectelem.setAttribute( "which", QString( propname ) );
664  }
665  else if ( dynamic_cast<const ObjectTypeCalcer*>( *i ) )
666  {
667  const ObjectTypeCalcer* o = static_cast<const ObjectTypeCalcer*>( *i );
668  objectelem = doc.createElement( "Object" );
669  objectelem.setAttribute( "type", o->type()->fullName() );
670  }
671  else assert( false );
672 
673  const std::vector<ObjectCalcer*> parents = ( *i )->parents();
674  for ( std::vector<ObjectCalcer*>::const_iterator i = parents.begin(); i != parents.end(); ++i )
675  {
676  std::map<const ObjectCalcer*,int>::const_iterator idp = idmap.find( *i );
677  assert( idp != idmap.end() );
678  int pid = idp->second;
679  QDomElement pel = doc.createElement( "Parent" );
680  pel.setAttribute( "id", pid );
681  objectelem.appendChild( pel );
682  }
683 
684  objectelem.setAttribute( "id", id++ );
685  hierelem.appendChild( objectelem );
686  }
687  docelem.appendChild( hierelem );
688 
689  QDomElement windowelem = doc.createElement( "View" );
690  for ( std::vector<ObjectHolder*>::iterator i = holders.begin(); i != holders.end(); ++i )
691  {
692  std::map<const ObjectCalcer*,int>::const_iterator idp = idmap.find( ( *i )->calcer() );
693  assert( idp != idmap.end() );
694  int id = idp->second;
695 
696  const ObjectDrawer* d = ( *i )->drawer();
697  QDomElement drawelem = doc.createElement( "Draw" );
698  drawelem.setAttribute( "object", id );
699  drawelem.setAttribute( "color", d->color().name() );
700  drawelem.setAttribute( "shown", QLatin1String( d->shown() ? "true" : "false" ) );
701  drawelem.setAttribute( "width", QString::number( d->width() ) );
702  drawelem.setAttribute( "style", d->styleToString() );
703  drawelem.setAttribute( "point-style", d->pointStyleToString() );
704  drawelem.setAttribute( "font", d->font().toString() );
705 
706  ObjectCalcer* namecalcer = ( *i )->nameCalcer();
707  if ( namecalcer )
708  {
709  std::map<const ObjectCalcer*,int>::const_iterator ncp = idmap.find( namecalcer );
710  assert( ncp != idmap.end() );
711  int ncid = ncp->second;
712  drawelem.setAttribute( "namecalcer", ncid );
713  }
714  else
715  {
716  drawelem.setAttribute( "namecalcer", "none" );
717  }
718 
719  windowelem.appendChild( drawelem );
720  };
721  docelem.appendChild( windowelem );
722 
723  doc.appendChild( docelem );
724  stream << doc.toString();
725  return true;
726 }
727 
728 bool KigFilterNative::save( const KigDocument& data, const QString& file )
729 {
730  return save07( data, file );
731 }
732 
733 bool KigFilterNative::save07( const KigDocument& data, const QString& outfile )
734 {
735  // we have an empty outfile, so we have to print all to stdout
736  if ( outfile.isEmpty() )
737  {
738  QTextStream stdoutstream( stdout, QIODevice::WriteOnly );
739  stdoutstream.setCodec( "UTF-8" );
740  return save07( data, stdoutstream );
741  }
742  if ( !outfile.endsWith( ".kig", Qt::CaseInsensitive ) )
743  {
744  // the user wants to save a compressed file, so we have to save our kig
745  // file to a temp file and then compress it...
746 
747  QString tempdir = KGlobal::dirs()->saveLocation( "tmp" );
748  if ( tempdir.isEmpty() )
749  return false;
750 
751  QString tempname = outfile.section( '/', -1 );
752  if ( outfile.endsWith( ".kigz", Qt::CaseInsensitive ) )
753  tempname.remove( QRegExp( "\\.[Kk][Ii][Gg][Zz]$" ) );
754  else
755  return false;
756 
757  QString tmpfile = tempdir + tempname + ".kig";
758  QFile ftmpfile( tmpfile );
759  if ( !ftmpfile.open( QIODevice::WriteOnly ) )
760  return false;
761  QTextStream stream( &ftmpfile );
762  stream.setCodec( "UTF-8" );
763  if ( !save07( data, stream ) )
764  return false;
765  ftmpfile.close();
766 
767  kDebug() << "tmp saved file: " << tmpfile;
768 
769  // creating the archive and adding our file
770  KTar ark( outfile, "application/x-gzip" );
771  ark.open( QIODevice::WriteOnly );
772  ark.addLocalFile( tmpfile, tempname + ".kig" );
773  ark.close();
774 
775  // finally, removing temp file
776  QFile::remove( tmpfile );
777 
778  return true;
779  }
780  else
781  {
782  QFile file( outfile );
783  if ( ! file.open( QIODevice::WriteOnly ) )
784  {
785  fileNotFound( outfile );
786  return false;
787  }
788  QTextStream stream( &file );
789  stream.setCodec( "UTF-8" );
790  return save07( data, stream );
791  }
792 
793  // we should never reach this point...
794  return false;
795 }
796 
797 /*
798 bool KigFilterNative::save( const KigDocument& data, QTextStream& stream )
799 {
800  return save07( data, stream );
801 }
802 */
ObjectImpFactory::instance
static const ObjectImpFactory * instance()
Definition: object_imp_factory.cc:37
CoordinateSystemFactory::build
static CoordinateSystem * build(int which)
Definition: coordinate_system.cpp:535
CoordinateSystem
a CoordinateSystem is what the user sees: it is kept by KigPart to show the user a grid...
Definition: coordinate_system.h:60
KigFilterNative::supportMime
bool supportMime(const QString &mime)
can the filter handle the mimetype mime ?
Definition: native-filter.cc:103
KigFilterNative::save
bool save(const KigDocument &data, const QString &file)
Definition: native-filter.cc:728
ObjectDrawer::pointStyleToString
QString pointStyleToString() const
return pointStyle transformed in a string
Definition: object_drawer.cc:184
ObjectConstCalcer
This is an ObjectCalcer that keeps an ObjectImp, and never calculates a new one.
Definition: object_calcer.h:232
sortElems
static std::vector< HierElem > sortElems(const std::vector< HierElem > elems)
Definition: native-filter.cc:86
ObjectDrawer::shown
bool shown() const
returns whether the object this ObjectDrawer is responsible for will be drawn or not.
Definition: object_drawer.cc:52
ObjectDrawer::font
QFont font() const
return the font
Definition: object_drawer.cc:149
KigDocument::grid
bool grid() const
Definition: kig_document.cc:186
main
int main(int argc, char **argv)
Definition: main.cpp:97
visitElem
static void visitElem(std::vector< HierElem > &ret, const std::vector< HierElem > &elems, std::vector< bool > &seen, int i)
Definition: native-filter.cc:72
getAllCalcers
std::vector< ObjectCalcer * > getAllCalcers(const std::vector< ObjectHolder * > &os)
get the calcers that the holders represent and their namecalcers
Definition: common.cc:21
KigDocument::addObjects
void addObjects(const std::vector< ObjectHolder * > &os)
Add the objects os to the document.
Definition: kig_document.cc:143
ObjectImp::propertiesInternalNames
virtual const QByteArrayList propertiesInternalNames() const
Definition: object_imp.cc:63
ObjectTypeCalcer
This is an ObjectCalcer that uses one of the various ObjectType's to calculate its ObjectImp...
Definition: object_calcer.h:183
KigFilterNative
Kig's native format.
Definition: native-filter.h:33
KigDocument::setCoordinateSystem
void setCoordinateSystem(CoordinateSystem *s)
sets the coordinate system to s , and deletes the old one.
Definition: kig_document.cc:56
KigDocument::setGrid
void setGrid(bool showgrid)
set to show/hide the grid.
Definition: kig_document.cc:181
obsoletemessage
static const char * obsoletemessage
Definition: native-filter.cc:388
extendVect
static void extendVect(std::vector< HierElem > &vect, uint size)
Definition: native-filter.cc:61
getAllParents
std::vector< ObjectCalcer * > getAllParents(const std::vector< ObjectCalcer * > &objs)
This function returns all objects above the given in the dependency graph.
Definition: calcpaths.cc:229
calcPath
std::vector< ObjectCalcer * > calcPath(const std::vector< ObjectCalcer * > &os)
This function sorts os such that they're in the right order for calc()-ing.
Definition: calcpaths.cc:48
KigFilter::parseError
void parseError(const QString &file, const QString &explanation=QString()) const
Definition: filter.cc:79
ObjectHolder
An ObjectHolder represents an object as it is known to the document.
Definition: object_holder.h:40
ObjectImpFactory::deserialize
ObjectImp * deserialize(const QString &type, const QDomElement &parent, QString &error) const
loads data from parent , and returns a new ObjectImp from the type string type .
Definition: object_imp_factory.cc:288
ObjectCalcer
An ObjectCalcer is an object that represents an algorithm for calculating an ObjectImp from other Obj...
Definition: object_calcer.h:66
ObjectTypeFactory::instance
static ObjectTypeFactory * instance()
Definition: object_type_factory.cc:51
KigFilter::notSupported
void notSupported(const QString &file, const QString &explanation) const
Definition: filter.cc:92
ObjectCalcer::calc
virtual void calc(const KigDocument &)=0
Makes the ObjectCalcer recalculate its ObjectImp from its parents.
ObjectPropertyCalcer
This is an ObjectCalcer that has a single parent, and gets a certain property from it in its calc() m...
Definition: object_calcer.h:276
native-filter.h
KigDocument::objects
const std::vector< ObjectHolder * > objects() const
Get a hold of the objects of this KigDocument.
Definition: kig_document.cc:46
KigFilterNative::instance
static KigFilterNative * instance()
Definition: native-filter.cc:382
ObjectDrawer::width
int width() const
return the width of the object
Definition: object_drawer.cc:134
ObjectType
The ObjectType class is a thing that represents the "behaviour" for a certain type.
Definition: object_type.h:32
ObjectTypeCalcer::type
const ObjectType * type() const
Definition: object_calcer.cc:132
ObjectDrawer::pointStyleFromString
static int pointStyleFromString(const QString &style)
Note that this returns a valid point style in every case, even if the given style string is unknown...
Definition: object_drawer.cc:169
ObjectImpFactory::serialize
QString serialize(const ObjectImp &d, QDomElement &parent, QDomDocument &doc) const
adds data to parent , and returns a type string.
Definition: object_imp_factory.cc:79
KigFilterNative::load
KigDocument * load(const QString &file)
load file fromfile and build a KigDocument from it.
Definition: native-filter.cc:108
ObjectImp::getPropName
const char * getPropName(int propgid) const
Definition: object_imp.cc:356
ObjectDrawer::styleToString
QString styleToString() const
return style transformed in a string
Definition: object_drawer.cc:215
ObjectDrawer
A class holding some information about how a certain object is drawn on the window.
Definition: object_drawer.h:47
KigDocument::setAxes
void setAxes(bool showaxes)
set to show/hide the grid.
Definition: kig_document.cc:191
ObjectDrawer::styleFromString
static Qt::PenStyle styleFromString(const QString &style)
Note that this returns a valid style in every case, even if the given style string is unknown...
Definition: object_drawer.cc:200
ObjectPropertyCalcer::propGid
int propGid() const
Definition: object_calcer.cc:357
KigDocument
KigDocument is the class holding the real data in a Kig document.
Definition: kig_document.h:36
ObjectCalcer::imp
virtual const ObjectImp * imp() const =0
Returns the ObjectImp of this ObjectCalcer.
ObjectDrawer::color
QColor color() const
returns the color that the object will be drawn in
Definition: object_drawer.cc:57
QByteArrayList
QList< QByteArray > QByteArrayList
Definition: objects/common.h:50
ObjectType::fullName
const char * fullName() const
Definition: object_type.cc:31
ObjectImp
The ObjectImp class represents the behaviour of an object after it is calculated. ...
Definition: object_imp.h:226
KIG_FILTER_PARSE_ERROR
#define KIG_FILTER_PARSE_ERROR
Definition: filter.h:53
KigDocument::axes
bool axes() const
Definition: kig_document.cc:206
KigDocument::coordinateSystem
const CoordinateSystem & coordinateSystem() const
Definition: kig_document.cc:40
KigFilter::warning
void warning(const QString &explanation) const
Definition: filter.cc:99
KigFilter::fileNotFound
void fileNotFound(const QString &file) const
Definition: filter.cc:70
CoordinateSystem::type
virtual const char * type() const =0
ObjectPropertyCalcer::parent
ObjectCalcer * parent() const
Definition: object_calcer.cc:306
ObjectTypeFactory::find
const ObjectType * find(const char *name) const
Definition: object_type_factory.cc:63
uint
unsigned int uint
Definition: object_imp.h:87
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:35:39 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kig

Skip menu "kig"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdeedu API Reference

Skip menu "kdeedu API Reference"
  • Analitza
  •     lib
  • kalgebra
  • kalzium
  •   libscience
  • kanagram
  • kig
  •   lib
  • klettres
  • kstars
  • libkdeedu
  •   keduvocdocument
  • marble
  • parley
  • rocs
  •   App
  •   RocsCore
  •   VisualEditor
  •   stepcore

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal