moved kdeaccessibility kdeaddons kdeadmin kdeartwork kdebindings kdeedu kdegames...
[kdeedu.git] / kig / filters / drgeo-filter.cc
blobf1f6f9760a016d032758ca932ce4c368d32ca413
1 // Copyright (C) 2004 Pino Toscano <toscano.pino@tiscali.it>
2 // Copyright (C) 2004 Dominique Devriese <devriese@kde.org>
4 // This program is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public License
6 // as published by the Free Software Foundation; either version 2
7 // of the License, or (at your option) any later version.
9 // This program 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
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
17 // 02111-1307, USA.
19 #include "drgeo-filter.h"
21 #include "drgeo-filter-chooser.h"
22 #include "filters-common.h"
24 #include "../kig/kig_document.h"
25 #include "../kig/kig_part.h"
26 #include "../misc/common.h"
27 #include "../misc/coordinate.h"
28 #include "../objects/angle_type.h"
29 #include "../objects/arc_type.h"
30 #include "../objects/bogus_imp.h"
31 #include "../objects/circle_imp.h"
32 #include "../objects/circle_type.h"
33 #include "../objects/conic_imp.h"
34 #include "../objects/conic_types.h"
35 #include "../objects/curve_imp.h"
36 #include "../objects/intersection_types.h"
37 #include "../objects/line_imp.h"
38 #include "../objects/line_type.h"
39 #include "../objects/object_calcer.h"
40 #include "../objects/object_drawer.h"
41 #include "../objects/object_factory.h"
42 #include "../objects/object_holder.h"
43 #include "../objects/object_type.h"
44 #include "../objects/other_imp.h"
45 #include "../objects/other_type.h"
46 #include "../objects/point_imp.h"
47 #include "../objects/point_type.h"
48 #include "../objects/polygon_type.h"
49 #include "../objects/transform_types.h"
50 #include "../objects/vector_type.h"
52 #include <math.h>
54 #include <qfile.h>
55 #include <qnamespace.h>
57 #include <klocale.h>
59 #undef DRGEO_DEBUG
60 //#define DRGEO_DEBUG
62 struct DrGeoHierarchyElement
64 QString id;
65 std::vector<QString> parents;
68 KigFilterDrgeo::KigFilterDrgeo()
72 KigFilterDrgeo::~KigFilterDrgeo()
76 bool KigFilterDrgeo::supportMime( const QString& mime )
78 return mime == "application/x-drgeo";
81 KigDocument* KigFilterDrgeo::load( const QString& file )
83 QFile f( file );
84 if ( ! f.open( IO_ReadOnly ) )
86 fileNotFound( file );
87 return 0;
90 QStringList figures;
91 QDomDocument doc( "drgenius" );
92 if ( !doc.setContent( &f ) )
93 KIG_FILTER_PARSE_ERROR;
94 QDomElement main = doc.documentElement();
95 int nmacros = 0;
96 // reading figures...
97 for ( QDomNode n = main.firstChild(); ! n.isNull(); n = n.nextSibling() )
99 QDomElement e = n.toElement();
100 if ( e.isNull() ) continue;
101 else if ( e.tagName() == "drgeo" )
102 figures.append( e.attribute( "name" ) );
103 else if ( e.tagName() == "macro" )
104 nmacros++;
106 if ( figures.isEmpty() ) {
107 if( nmacros > 0 )
108 warning( i18n( "The Dr. Geo file \"%1\" is a macro file so it contains no "
109 "figures." ).arg( file ) );
110 else
111 warning( i18n( "There are no figures in Dr. Geo file \"%1\"." ).arg( file ) );
112 return false;
115 int nfig = figures.count();
116 // no figures, no party...
117 if ( nfig == 0 )
118 return 0;
120 int myfig = 0;
122 if ( nfig > 1 )
124 // Dr. Geo file has more than 1 figure, let the user choose one...
125 KigFilterDrgeoChooser* c = new KigFilterDrgeoChooser( figures );
126 myfig = c->exec();
127 delete c;
130 #ifdef DRGEO_DEBUG
131 kdDebug() << "drgeo file " << file << endl;
132 #endif
133 int curfig = -1;
135 for ( QDomNode n = main.firstChild(); ! n.isNull(); n = n.nextSibling() )
137 QDomElement e = n.toElement();
138 if ( e.isNull() ) continue;
139 else if ( e.tagName() == "drgeo" )
141 curfig += 1;
142 if ( curfig == myfig )
144 #ifdef DRGEO_DEBUG
145 kdDebug() << "- Figure: '" << e.attribute("name") << "'" << endl;
146 #endif
147 bool grid = !e.attribute( "grid" ).isEmpty() &&
148 ( e.attribute( "grid" ) != "False" );
149 return importFigure( e.firstChild(), file, grid );
154 return 0;
157 int convertDrgeoIndex( const std::vector<DrGeoHierarchyElement> es, const QString myid )
159 for ( uint i = 0; i < es.size(); ++i )
160 if ( es[i].id == myid )
161 return i;
162 return -1;
165 const Coordinate convertDrgeoLineParam( const double param, const LineData& line )
167 const double n = ( param - 0.5 ) * M_PI;
168 const Coordinate c = line.dir() / line.dir().length();
169 const Coordinate p = line.a + tan( n ) * c;
170 return p;
173 const Coordinate convertDrgeoHalflineParam( const double param, const LineData& line )
175 const double n = param * M_PI * 0.5;
176 const Coordinate c = line.dir() / line.dir().length();
177 const Coordinate p = line.a + tan( n ) * c;
178 return p;
181 KigDocument* KigFilterDrgeo::importFigure( QDomNode f, const QString& file, const bool grid )
183 KigDocument* ret = new KigDocument();
185 using namespace std;
186 std::vector<DrGeoHierarchyElement> elems;
187 int withoutid = 0;
189 // 1st: fetch relationships and build an appropriate structure
190 for (QDomNode a = f; ! a.isNull(); a = a.nextSibling() )
192 QDomElement domelem = a.toElement();
193 if ( domelem.isNull() ) continue;
194 else
196 DrGeoHierarchyElement elem;
197 #ifdef DRGEO_DEBUG
198 kdDebug() << " * " << domelem.tagName() << "(" << domelem.attribute("type") << ")" << endl;
199 #endif
200 for ( QDomNode c = domelem.firstChild(); ! c.isNull(); c = c.nextSibling() )
202 QDomElement ce = c.toElement();
203 if ( ce.isNull() ) continue;
204 else if ( ce.tagName() == "parent" )
205 elem.parents.push_back( ce.attribute( "ref" ) );
207 QString curid = domelem.attribute( "id" );
208 elem.id = !curid.isNull() ? curid : QString::number( withoutid++ ) ;
209 elems.push_back( elem );
213 #ifdef DRGEO_DEBUG
214 QString x;
215 kdDebug() << "+++ elems" << endl;
216 for ( uint i = 0; i < elems.size(); ++i )
218 x = "";
219 for ( uint j = 0; j < elems[i].parents.size(); ++j )
221 x += elems[i].parents[j] + "_";
223 kdDebug() << " --> " << i << " - " << elems[i].id << " - " << x << endl;
225 #endif
227 // 2nd: let's draw!
228 int curid = 0;
229 const ObjectFactory* fact = ObjectFactory::instance();
230 std::vector<ObjectHolder*> holders;
231 std::vector<ObjectHolder*> holders2;
232 ObjectTypeCalcer* oc = 0;
233 ObjectCalcer* oc2 = 0;
234 int nignored = 0;
236 // there's no need to sort the objects because it seems that DrGeo objects
237 // appear in the right order... so let's go!
238 for (QDomNode a = f; ! a.isNull(); a = a.nextSibling() )
240 #ifdef DRGEO_DEBUG
241 kdDebug() << "+++ id: " << curid << endl;
242 #endif
243 const DrGeoHierarchyElement& el = elems[curid];
244 std::vector<ObjectCalcer*> parents;
245 for ( uint j = 0; j < el.parents.size(); ++j )
247 int parentid = convertDrgeoIndex( elems, el.parents[j] );
248 if ( parentid == -1 )
249 KIG_FILTER_PARSE_ERROR;
250 parents.push_back( holders[parentid-nignored]->calcer() );
252 QDomElement domelem = a.toElement();
254 #ifdef DRGEO_DEBUG
255 if ( parents.size() > 0 )
256 for ( uint j = 0; j < parents.size(); ++j )
258 kdDebug() << "+++++++++ parent[" << j << "]: " << parents[j] << " - "
259 << parents[j]->imp()->type()->internalName() << endl;
261 else
262 kdDebug() << "+++++++++ parents: NO" << endl;
263 kdDebug() << "+++++++++ " << domelem.tagName() << " - " << domelem.attribute("type") << endl;
264 #endif
266 if ( domelem.isNull() ) continue;
267 else if ( domelem.tagName() == "point" )
269 QString xs;
270 QString ys;
271 QString values;
272 for ( QDomNode c = domelem.firstChild(); ! c.isNull(); c = c.nextSibling() )
274 QDomElement ce = c.toElement();
275 if ( ce.isNull() ) continue;
276 else if ( ce.tagName() == "x" )
277 xs = ce.text();
278 else if ( ce.tagName() == "y" )
279 ys = ce.text();
280 else if ( ce.tagName() == "value" )
281 values = ce.text();
283 if ( domelem.attribute( "type" ) == "Free" )
285 bool ok;
286 bool ok2;
287 double x = xs.toDouble( &ok );
288 double y = ys.toDouble( &ok2 );
289 if ( ! ( ok && ok2 ) )
290 KIG_FILTER_PARSE_ERROR;
291 oc = fact->fixedPointCalcer( Coordinate( x, y ) );
293 else if ( domelem.attribute( "type" ) == "Middle_2pts" )
294 oc = new ObjectTypeCalcer( MidPointType::instance(), parents );
295 else if ( domelem.attribute( "type" ) == "Middle_segment" )
297 if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR;
298 if ( !parents[0]->imp()->inherits( SegmentImp::stype() ) )
299 KIG_FILTER_PARSE_ERROR;
300 ObjectPropertyCalcer* o1 = fact->propertyObjectCalcer( parents[0], "end-point-A" );
301 o1->calc( *ret );
302 ObjectPropertyCalcer* o2 = fact->propertyObjectCalcer( parents[0], "end-point-B" );
303 o2->calc( *ret );
304 std::vector<ObjectCalcer*> args;
305 args.push_back( o1 );
306 args.push_back( o2 );
307 oc = new ObjectTypeCalcer( MidPointType::instance(), args );
309 else if ( domelem.attribute( "type" ) == "On_curve" )
311 bool ok3;
312 double value = values.toDouble( &ok3 );
313 if ( ! ok3 )
314 KIG_FILTER_PARSE_ERROR;
315 if ( ( parents[0]->imp()->inherits( CircleImp::stype() ) ) ||
316 ( parents[0]->imp()->inherits( SegmentImp::stype() ) ) )
317 oc = fact->constrainedPointCalcer( parents[0], value );
318 else if ( parents[0]->imp()->inherits( LineImp::stype() ) )
320 const LineData l = static_cast<const LineImp*>( parents[0]->imp() )->data();
321 const Coordinate p = convertDrgeoLineParam( value, l );
322 oc = fact->constrainedPointCalcer( parents[0], p, *ret );
324 else if ( parents[0]->imp()->inherits( RayImp::stype() ) )
326 const LineData l = static_cast<const RayImp*>( parents[0]->imp() )->data();
327 const Coordinate p = convertDrgeoHalflineParam( value, l );
328 oc = fact->constrainedPointCalcer( parents[0], p, *ret );
330 else if ( parents[0]->imp()->inherits( ArcImp::stype() ) )
331 oc = fact->constrainedPointCalcer( parents[0], 1 - value );
332 else
334 // oc = fact->constrainedPointCalcer( parents[0], value );
335 notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, "
336 "which Kig does not currently support." ).arg( domelem.tagName() ).arg(
337 domelem.attribute( "type" ) ) );
338 return false;
341 else if ( domelem.attribute( "type" ) == "Intersection" )
343 if ( ( parents[0]->imp()->inherits( AbstractLineImp::stype() ) ) &&
344 ( parents[1]->imp()->inherits( AbstractLineImp::stype() ) ) )
345 oc = new ObjectTypeCalcer( LineLineIntersectionType::instance(), parents );
346 else
348 bool ok;
349 int which = domelem.attribute( "extra" ).toInt( &ok );
350 if ( !ok ) KIG_FILTER_PARSE_ERROR;
351 if ( which == 1 ) which = -1;
352 else if ( which == 0 ) which = 1;
353 else KIG_FILTER_PARSE_ERROR;
354 std::vector<ObjectCalcer*> args = parents;
355 const ObjectType* type = 0;
356 args.push_back( new ObjectConstCalcer( new IntImp( which ) ) );
357 if ( ( parents[0]->imp()->inherits( CircleImp::stype() ) ) &&
358 ( parents[1]->imp()->inherits( CircleImp::stype() ) ) )
359 type = CircleCircleIntersectionType::instance();
360 else if ( ( parents[0]->imp()->inherits( CircleImp::stype() ) &&
361 parents[1]->imp()->inherits( AbstractLineImp::stype() ) ) ||
362 ( parents[1]->imp()->inherits( CircleImp::stype() ) &&
363 parents[0]->imp()->inherits( AbstractLineImp::stype() ) ) )
364 type = ConicLineIntersectionType::instance();
365 else if ( ( parents[0]->imp()->inherits( ArcImp::stype() ) &&
366 parents[1]->imp()->inherits( AbstractLineImp::stype() ) ) ||
367 ( parents[1]->imp()->inherits( ArcImp::stype() ) &&
368 parents[0]->imp()->inherits( AbstractLineImp::stype() ) ) )
369 type = ArcLineIntersectionType::instance();
370 else
372 notSupported( file, i18n( "This Dr. Geo file contains an intersection type, "
373 "which Kig does not currently support." ) );
374 return false;
376 oc = new ObjectTypeCalcer( type, args );
379 else if ( domelem.attribute( "type" ) == "Reflexion" )
380 oc = new ObjectTypeCalcer( LineReflectionType::instance(), parents );
381 else if ( domelem.attribute( "type" ) == "Symmetry" )
382 oc = new ObjectTypeCalcer( PointReflectionType::instance(), parents );
383 else if ( domelem.attribute( "type" ) == "Translation" )
384 oc = new ObjectTypeCalcer( TranslatedType::instance(), parents );
385 else if ( domelem.attribute( "type" ) == "Rotation" )
386 oc = new ObjectTypeCalcer( RotationType::instance(), parents );
387 else
389 notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, "
390 "which Kig does not currently support." ).arg( domelem.tagName() ).arg(
391 domelem.attribute( "type" ) ) );
392 return false;
394 #ifdef DRGEO_DEBUG
395 kdDebug() << "+++++++++ oc:" << oc << endl;
396 #endif
398 else if( ( domelem.tagName() == "line" ) ||
399 ( domelem.tagName() == "halfLine" ) ||
400 ( domelem.tagName() == "segment" ) ||
401 ( domelem.tagName() == "vector" ) ||
402 ( domelem.tagName() == "circle" ) ||
403 ( domelem.tagName() == "arcCircle" ) ||
404 ( domelem.tagName() == "polygon" ) )
406 const ObjectType* type = 0;
407 if ( domelem.attribute( "type" ) == "2pts" )
409 if( domelem.tagName() == "line" )
410 type = LineABType::instance();
411 else if( domelem.tagName() == "halfLine" )
412 type = RayABType::instance();
413 else if( domelem.tagName() == "segment" )
414 type = SegmentABType::instance();
415 else if( domelem.tagName() == "vector" )
416 type = VectorType::instance();
417 else if( domelem.tagName() == "circle" )
418 type = CircleBCPType::instance();
419 else
421 notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, "
422 "which Kig does not currently support." ).arg( domelem.tagName() ).arg(
423 domelem.attribute( "type" ) ) );
424 return false;
426 oc = new ObjectTypeCalcer( type, parents );
428 else if( domelem.attribute( "type" ) == "3pts" )
430 if( domelem.tagName() == "arcCircle" )
431 type = ArcBTPType::instance();
432 else
434 notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, "
435 "which Kig does not currently support." ).arg( domelem.tagName() ).arg(
436 domelem.attribute( "type" ) ) );
437 return false;
439 oc = new ObjectTypeCalcer( type, parents );
441 else if( domelem.attribute( "type" ) == "segment" )
443 if( domelem.tagName() == "circle" )
445 type = CircleBPRType::instance();
446 ObjectPropertyCalcer* o = fact->propertyObjectCalcer( parents[1], "length" );
447 o->calc( *ret );
448 ObjectCalcer* a = parents[0];
449 parents.clear();
450 parents.push_back( a );
451 parents.push_back( o );
453 else
455 notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, "
456 "which Kig does not currently support." ).arg( domelem.tagName() ).arg(
457 domelem.attribute( "type" ) ) );
458 return false;
460 oc = new ObjectTypeCalcer( type, parents );
462 else if( domelem.attribute( "type" ) == "npts" )
464 if( domelem.tagName() == "polygon" )
466 if ( parents.size() < 3 ) KIG_FILTER_PARSE_ERROR;
467 type = PolygonBNPType::instance();
469 else
471 notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, "
472 "which Kig does not currently support." ).arg( domelem.tagName() ).arg(
473 domelem.attribute( "type" ) ) );
474 return false;
476 oc = new ObjectTypeCalcer( type, parents );
478 else if ( domelem.attribute( "type" ) == "perpendicular" )
479 oc = new ObjectTypeCalcer( LinePerpendLPType::instance(), parents );
480 else if ( domelem.attribute( "type" ) == "parallel" )
481 oc = new ObjectTypeCalcer( LineParallelLPType::instance(), parents );
482 else if ( domelem.attribute( "type" ) == "Reflexion" )
483 oc = new ObjectTypeCalcer( LineReflectionType::instance(), parents );
484 else if ( domelem.attribute( "type" ) == "Symmetry" )
485 oc = new ObjectTypeCalcer( PointReflectionType::instance(), parents );
486 else if ( domelem.attribute( "type" ) == "Translation" )
487 oc = new ObjectTypeCalcer( TranslatedType::instance(), parents );
488 else if ( domelem.attribute( "type" ) == "Rotation" )
489 oc = new ObjectTypeCalcer( RotationType::instance(), parents );
490 else
492 notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, "
493 "which Kig does not currently support." ).arg( domelem.tagName() ).arg(
494 domelem.attribute( "type" ) ) );
495 return false;
497 #ifdef DRGEO_DEBUG
498 kdDebug() << "+++++++++ oc:" << oc << endl;
499 #endif
501 else if( ( domelem.tagName() == "numeric" ) ||
502 ( domelem.tagName() == "equation" ) )
504 QString xs;
505 QString ys;
506 QString value;
507 for ( QDomNode c = domelem.firstChild(); ! c.isNull(); c = c.nextSibling() )
509 QDomElement ce = c.toElement();
510 if ( ce.isNull() ) continue;
511 else if ( ce.tagName() == "x" )
512 xs = ce.text();
513 else if ( ce.tagName() == "y" )
514 ys = ce.text();
515 else if ( ce.tagName() == "value" )
516 value = ce.text();
518 bool ok;
519 bool ok2;
520 double x = xs.toDouble( &ok );
521 double y = ys.toDouble( &ok2 );
522 if ( ! ( ok && ok2 ) )
523 KIG_FILTER_PARSE_ERROR;
524 Coordinate m( x, y );
525 // types of 'numeric'
526 // ugly hack to show value numerics...
527 if ( domelem.attribute( "type" ) == "value" )
529 bool ok3;
530 double dvalue = value.toDouble( &ok3 );
531 if ( ok3 )
532 value = QString( "%1" ).arg( dvalue, 0, 'g', 3 );
533 oc = fact->labelCalcer( value, m, false, std::vector<ObjectCalcer*>(), *ret );
535 else if ( domelem.attribute( "type" ) == "pt_abscissa" )
537 if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR;
538 oc = filtersConstructTextObject( m, parents[0], "coordinate-x", *ret, false );
540 else if ( domelem.attribute( "type" ) == "pt_ordinate" )
542 if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR;
543 oc = filtersConstructTextObject( m, parents[0], "coordinate-y", *ret, false );
545 else if ( domelem.attribute( "type" ) == "segment_length" )
547 if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR;
548 oc = filtersConstructTextObject( m, parents[0], "length", *ret, false );
550 else if ( domelem.attribute( "type" ) == "circle_perimeter" )
552 if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR;
553 oc = filtersConstructTextObject( m, parents[0], "circumference", *ret, false );
555 else if ( domelem.attribute( "type" ) == "arc_length" )
557 if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR;
558 oc = filtersConstructTextObject( m, parents[0], "arc-length", *ret, false );
560 else if ( domelem.attribute( "type" ) == "distance_2pts" )
562 if ( parents.size() != 2 ) KIG_FILTER_PARSE_ERROR;
563 ObjectTypeCalcer* so = new ObjectTypeCalcer( SegmentABType::instance(), parents );
564 so->calc( *ret );
565 oc = filtersConstructTextObject( m, so, "length", *ret, false );
567 else if ( domelem.attribute( "type" ) == "vector_norm" )
569 if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR;
570 oc = filtersConstructTextObject( m, parents[0], "length", *ret, false );
572 else if ( domelem.attribute( "type" ) == "vector_abscissa" )
574 if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR;
575 oc = filtersConstructTextObject( m, parents[0], "length-x", *ret, false );
577 else if ( domelem.attribute( "type" ) == "vector_ordinate" )
579 if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR;
580 oc = filtersConstructTextObject( m, parents[0], "length-y", *ret, false );
582 else if ( domelem.attribute( "type" ) == "slope" )
584 if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR;
585 oc = filtersConstructTextObject( m, parents[0], "slope", *ret, false );
587 else if ( domelem.attribute( "type" ) == "distance_pt_line" )
589 if ( parents.size() != 2 ) KIG_FILTER_PARSE_ERROR;
590 std::vector<ObjectCalcer*> args;
591 args.push_back( parents[1] );
592 args.push_back( parents[0] );
593 ObjectTypeCalcer* po = new ObjectTypeCalcer( LinePerpendLPType::instance(), args );
594 po->calc( *ret );
595 args.clear();
596 args.push_back( parents[1] );
597 args.push_back( po );
598 ObjectTypeCalcer* io = new ObjectTypeCalcer( LineLineIntersectionType::instance(), args );
599 io->calc( *ret );
600 args.clear();
601 args.push_back( parents[0] );
602 args.push_back( io );
603 ObjectTypeCalcer* so = new ObjectTypeCalcer( SegmentABType::instance(), args );
604 so->calc( *ret );
605 oc = filtersConstructTextObject( m, so, "length", *ret, false );
607 // types of 'equation'
608 else if ( domelem.attribute( "type" ) == "line" )
610 if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR;
611 oc = filtersConstructTextObject( m, parents[0], "equation", *ret, false );
613 else if ( domelem.attribute( "type" ) == "circle" )
615 if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR;
616 oc = filtersConstructTextObject( m, parents[0], "simply-cartesian-equation", *ret, false );
618 else
620 notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, "
621 "which Kig does not currently support." ).arg( domelem.tagName() ).arg(
622 domelem.attribute( "type" ) ) );
623 return false;
625 #ifdef DRGEO_DEBUG
626 kdDebug() << "+++++++++ oc:" << oc << endl;
627 #endif
629 else if ( domelem.tagName() == "angle" )
631 if ( domelem.attribute( "type" ) == "3pts" )
633 if ( parents.size() != 3 ) KIG_FILTER_PARSE_ERROR;
634 oc = new ObjectTypeCalcer( HalfAngleType::instance(), parents );
636 else
638 notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, "
639 "which Kig does not currently support." ).arg( domelem.tagName() ).arg(
640 domelem.attribute( "type" ) ) );
641 return false;
643 #ifdef DRGEO_DEBUG
644 kdDebug() << "+++++++++ oc:" << oc << endl;
645 #endif
647 else if ( domelem.tagName() == "script" )
649 QString xs;
650 QString ys;
651 QString text;
652 for ( QDomNode c = domelem.firstChild(); ! c.isNull(); c = c.nextSibling() )
654 QDomElement ce = c.toElement();
655 if ( ce.isNull() ) continue;
656 else if ( ce.tagName() == "x" )
657 xs = ce.text();
658 else if ( ce.tagName() == "y" )
659 ys = ce.text();
660 else if ( ce.tagName() == "code" )
661 text = ce.text();
663 bool ok;
664 bool ok2;
665 double x = xs.toDouble( &ok );
666 double y = ys.toDouble( &ok2 );
667 if ( ! ( ok && ok2 ) )
668 KIG_FILTER_PARSE_ERROR;
669 // since Kig doesn't support Guile scripts, it will write script's text
670 // in a label, so the user can freely see the code and make whatever
671 // he/she wants
672 // possible idea: construct a new script object with the parents of Guile
673 // one and the Guile code inserted commented... depends on a better
674 // handling of arguments in scripts?
675 if ( domelem.attribute( "type" ) == "nitems" )
676 oc = fact->labelCalcer( text, Coordinate( x, y ), false, std::vector<ObjectCalcer*>(), *ret );
677 else
679 notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, "
680 "which Kig does not currently support." ).arg( domelem.tagName() ).arg(
681 domelem.attribute( "type" ) ) );
682 return false;
685 else if ( domelem.tagName() == "locus" )
687 if ( domelem.attribute( "type" ) == "None" )
688 oc = fact->locusCalcer( parents[0], parents[1] );
689 else
691 notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, "
692 "which Kig does not currently support." ).arg( domelem.tagName() ).arg(
693 domelem.attribute( "type" ) ) );
694 return false;
696 #ifdef DRGEO_DEBUG
697 kdDebug() << "+++++++++ oc:" << oc << endl;
698 #endif
700 else if ( ( domelem.tagName() == "boundingBox" ) ||
701 ( domelem.tagName() == "customUI" ) )
703 // ignoring these elements, since they are not useful to us...
704 nignored++;
706 else
708 #ifdef DRGEO_DEBUG
709 kdDebug() << ">>>>>>>>> UNKNOWN OBJECT" << endl;
710 #endif
711 notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, "
712 "which Kig does not currently support." ).arg( domelem.tagName() ).arg(
713 domelem.attribute( "type" ) ) );
714 return false;
716 curid++;
717 if ( oc == 0 )
718 continue;
720 // reading color
721 QColor co( domelem.attribute( "color" ) );
722 if ( ! co.isValid() )
723 if ( domelem.attribute( "color" ) == "Bordeaux" )
724 co.setRgb( 145, 0, 0 );
725 else
726 co = Qt::blue;
727 // reading width and style
728 // Dashed -> the little one
729 // Normal -> the medium
730 // Thick -> the biggest one
731 int w = -1;
732 Qt::PenStyle s = Qt::SolidLine;
733 if ( domelem.tagName() == "point" )
735 if ( domelem.attribute( "thickness" ) == "Normal" )
736 w = 7;
737 else if ( domelem.attribute( "thickness" ) == "Thick" )
738 w = 9;
740 else
742 if ( domelem.attribute( "thickness" ) == "Dashed" )
743 s = Qt::DotLine;
744 if ( domelem.attribute( "thickness" ) == "Thick" )
745 w = 2;
747 QString ps = domelem.attribute( "style" );
748 int pointstyle = ObjectDrawer::pointStyleFromString( ps );
749 // show this object?
750 bool show = ( ( domelem.attribute( "masked" ) != "True" ) &&
751 ( domelem.attribute( "masked" ) != "Alway" ) );
752 // costructing the ObjectDrawer*
753 ObjectDrawer* d = new ObjectDrawer( co, w, show, s, pointstyle );
754 // reading object name
755 QString strname = domelem.attribute( "name" );
756 ObjectConstCalcer* name = new ObjectConstCalcer( new StringImp( strname ) );
758 // creating the ObjectHolder*
759 ObjectHolder* o = new ObjectHolder( oc, d, name );
760 holders.push_back( o );
761 // calc()
762 #ifdef DRGEO_DEBUG
763 kdDebug() << ">>>>>>>>> calc" << endl;
764 #endif
765 holders[curid-1-nignored]->calc( *ret );
767 if ( domelem.tagName() == "point" )
769 if ( !strname.isEmpty() )
771 std::vector<ObjectCalcer*> args2;
772 args2.push_back( o->nameCalcer() );
773 oc2 = fact->attachedLabelCalcer( QString::fromLatin1( "%1" ), oc,
774 static_cast<const PointImp*>( oc->imp() )->coordinate(),
775 false, args2, *ret );
776 co = Qt::black;
779 else if ( domelem.tagName() == "angle" )
781 oc2 = filtersConstructTextObject(
782 static_cast<const PointImp*>( holders[curid-1-nignored]->calcer()->parents()[1]->imp() )->coordinate(),
783 holders[curid-1-nignored]->calcer(), "angle-degrees", *ret, false );
786 oc = 0;
788 if ( oc2 != 0 )
790 oc2->calc( *ret );
791 ObjectDrawer* d2 = new ObjectDrawer( co );
792 ObjectHolder* o2 = new ObjectHolder( oc2, d2 );
793 holders2.push_back( o2 );
794 oc2 = 0;
798 ret->addObjects( holders );
799 ret->addObjects( holders2 );
800 ret->setGrid( grid );
801 ret->setAxes( grid );
802 return ret;
805 KigFilterDrgeo* KigFilterDrgeo::instance()
807 static KigFilterDrgeo f;
808 return &f;