You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdeedu/kig/filters/drgeo-filter.cc

810 lines
29 KiB

// Copyright (C) 2004 Pino Toscano <toscano.pino@tiscali.it>
// Copyright (C) 2004 Dominique Devriese <devriese@kde.org>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
// 02110-1301, USA.
#include "drgeo-filter.h"
#include "drgeo-filter-chooser.h"
#include "filters-common.h"
#include "../kig/kig_document.h"
#include "../kig/kig_part.h"
#include "../misc/common.h"
#include "../misc/coordinate.h"
#include "../objects/angle_type.h"
#include "../objects/arc_type.h"
#include "../objects/bogus_imp.h"
#include "../objects/circle_imp.h"
#include "../objects/circle_type.h"
#include "../objects/conic_imp.h"
#include "../objects/conic_types.h"
#include "../objects/curve_imp.h"
#include "../objects/intersection_types.h"
#include "../objects/line_imp.h"
#include "../objects/line_type.h"
#include "../objects/object_calcer.h"
#include "../objects/object_drawer.h"
#include "../objects/object_factory.h"
#include "../objects/object_holder.h"
#include "../objects/object_type.h"
#include "../objects/other_imp.h"
#include "../objects/other_type.h"
#include "../objects/point_imp.h"
#include "../objects/point_type.h"
#include "../objects/polygon_type.h"
#include "../objects/transform_types.h"
#include "../objects/vector_type.h"
#include <math.h>
#include <tqfile.h>
#include <tqnamespace.h>
#include <tdelocale.h>
#undef DRGEO_DEBUG
//#define DRGEO_DEBUG
struct DrGeoHierarchyElement
{
TQString id;
std::vector<TQString> parents;
};
KigFilterDrgeo::KigFilterDrgeo()
{
}
KigFilterDrgeo::~KigFilterDrgeo()
{
}
bool KigFilterDrgeo::supportMime( const TQString& mime )
{
return mime == "application/x-drgeo";
}
KigDocument* KigFilterDrgeo::load( const TQString& file )
{
TQFile f( file );
if ( ! f.open( IO_ReadOnly ) )
{
fileNotFound( file );
return 0;
}
TQStringList figures;
TQDomDocument doc( "drgenius" );
if ( !doc.setContent( &f ) )
KIG_FILTER_PARSE_ERROR;
TQDomElement main = doc.documentElement();
int nmacros = 0;
// reading figures...
for ( TQDomNode n = main.firstChild(); ! n.isNull(); n = n.nextSibling() )
{
TQDomElement e = n.toElement();
if ( e.isNull() ) continue;
else if ( e.tagName() == "drgeo" )
figures.append( e.attribute( "name" ) );
else if ( e.tagName() == "macro" )
nmacros++;
}
if ( figures.isEmpty() ) {
if( nmacros > 0 )
warning( i18n( "The Dr. Geo file \"%1\" is a macro file so it contains no "
"figures." ).arg( file ) );
else
warning( i18n( "There are no figures in Dr. Geo file \"%1\"." ).arg( file ) );
return 0;
}
int nfig = figures.count();
// no figures, no party...
if ( nfig == 0 )
return 0;
int myfig = 0;
if ( nfig > 1 )
{
// Dr. Geo file has more than 1 figure, let the user choose one...
KigFilterDrgeoChooser* c = new KigFilterDrgeoChooser( figures );
myfig = c->exec();
delete c;
}
#ifdef DRGEO_DEBUG
kdDebug() << "drgeo file " << file << endl;
#endif
int curfig = -1;
for ( TQDomNode n = main.firstChild(); ! n.isNull(); n = n.nextSibling() )
{
TQDomElement e = n.toElement();
if ( e.isNull() ) continue;
else if ( e.tagName() == "drgeo" )
{
curfig += 1;
if ( curfig == myfig )
{
#ifdef DRGEO_DEBUG
kdDebug() << "- Figure: '" << e.attribute("name") << "'" << endl;
#endif
bool grid = !e.attribute( "grid" ).isEmpty() &&
( e.attribute( "grid" ) != "False" );
return importFigure( e.firstChild(), file, grid );
}
}
}
return 0;
}
int convertDrgeoIndex( const std::vector<DrGeoHierarchyElement> es, const TQString myid )
{
for ( uint i = 0; i < es.size(); ++i )
if ( es[i].id == myid )
return i;
return -1;
}
const Coordinate convertDrgeoLineParam( const double param, const LineData& line )
{
const double n = ( param - 0.5 ) * M_PI;
const Coordinate c = line.dir() / line.dir().length();
const Coordinate p = line.a + tan( n ) * c;
return p;
}
const Coordinate convertDrgeoHalflineParam( const double param, const LineData& line )
{
const double n = param * M_PI * 0.5;
const Coordinate c = line.dir() / line.dir().length();
const Coordinate p = line.a + tan( n ) * c;
return p;
}
KigDocument* KigFilterDrgeo::importFigure( TQDomNode f, const TQString& file, const bool grid )
{
KigDocument* ret = new KigDocument();
using namespace std;
std::vector<DrGeoHierarchyElement> elems;
int withoutid = 0;
// 1st: fetch relationships and build an appropriate structure
for (TQDomNode a = f; ! a.isNull(); a = a.nextSibling() )
{
TQDomElement domelem = a.toElement();
if ( domelem.isNull() ) continue;
else
{
DrGeoHierarchyElement elem;
#ifdef DRGEO_DEBUG
kdDebug() << " * " << domelem.tagName() << "(" << domelem.attribute("type") << ")" << endl;
#endif
for ( TQDomNode c = domelem.firstChild(); ! c.isNull(); c = c.nextSibling() )
{
TQDomElement ce = c.toElement();
if ( ce.isNull() ) continue;
else if ( ce.tagName() == "parent" )
elem.parents.push_back( ce.attribute( "ref" ) );
}
TQString curid = domelem.attribute( "id" );
elem.id = !curid.isNull() ? curid : TQString::number( withoutid++ ) ;
elems.push_back( elem );
}
}
#ifdef DRGEO_DEBUG
TQString x;
kdDebug() << "+++ elems" << endl;
for ( uint i = 0; i < elems.size(); ++i )
{
x = "";
for ( uint j = 0; j < elems[i].parents.size(); ++j )
{
x += elems[i].parents[j] + "_";
}
kdDebug() << " --> " << i << " - " << elems[i].id << " - " << x << endl;
}
#endif
// 2nd: let's draw!
int curid = 0;
const ObjectFactory* fact = ObjectFactory::instance();
std::vector<ObjectHolder*> holders;
std::vector<ObjectHolder*> holders2;
ObjectTypeCalcer* oc = 0;
ObjectCalcer* oc2 = 0;
int nignored = 0;
// there's no need to sort the objects because it seems that DrGeo objects
// appear in the right order... so let's go!
for (TQDomNode a = f; ! a.isNull(); a = a.nextSibling() )
{
#ifdef DRGEO_DEBUG
kdDebug() << "+++ id: " << curid << endl;
#endif
const DrGeoHierarchyElement& el = elems[curid];
std::vector<ObjectCalcer*> parents;
for ( uint j = 0; j < el.parents.size(); ++j )
{
int parentid = convertDrgeoIndex( elems, el.parents[j] );
if ( parentid == -1 )
KIG_FILTER_PARSE_ERROR;
parents.push_back( holders[parentid-nignored]->calcer() );
};
TQDomElement domelem = a.toElement();
#ifdef DRGEO_DEBUG
if ( parents.size() > 0 )
for ( uint j = 0; j < parents.size(); ++j )
{
kdDebug() << "+++++++++ parent[" << j << "]: " << parents[j] << " - "
<< parents[j]->imp()->type()->internalName() << endl;
}
else
kdDebug() << "+++++++++ parents: NO" << endl;
kdDebug() << "+++++++++ " << domelem.tagName() << " - " << domelem.attribute("type") << endl;
#endif
if ( domelem.isNull() ) continue;
else if ( domelem.tagName() == "point" )
{
TQString xs;
TQString ys;
TQString values;
for ( TQDomNode c = domelem.firstChild(); ! c.isNull(); c = c.nextSibling() )
{
TQDomElement ce = c.toElement();
if ( ce.isNull() ) continue;
else if ( ce.tagName() == "x" )
xs = ce.text();
else if ( ce.tagName() == "y" )
ys = ce.text();
else if ( ce.tagName() == "value" )
values = ce.text();
}
if ( domelem.attribute( "type" ) == "Free" )
{
bool ok;
bool ok2;
double x = xs.toDouble( &ok );
double y = ys.toDouble( &ok2 );
if ( ! ( ok && ok2 ) )
KIG_FILTER_PARSE_ERROR;
oc = fact->fixedPointCalcer( Coordinate( x, y ) );
}
else if ( domelem.attribute( "type" ) == "Middle_2pts" )
oc = new ObjectTypeCalcer( MidPointType::instance(), parents );
else if ( domelem.attribute( "type" ) == "Middle_segment" )
{
if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR;
if ( !parents[0]->imp()->inherits( SegmentImp::stype() ) )
KIG_FILTER_PARSE_ERROR;
ObjectPropertyCalcer* o1 = fact->propertyObjectCalcer( parents[0], "end-point-A" );
o1->calc( *ret );
ObjectPropertyCalcer* o2 = fact->propertyObjectCalcer( parents[0], "end-point-B" );
o2->calc( *ret );
std::vector<ObjectCalcer*> args;
args.push_back( o1 );
args.push_back( o2 );
oc = new ObjectTypeCalcer( MidPointType::instance(), args );
}
else if ( domelem.attribute( "type" ) == "On_curve" )
{
bool ok3;
double value = values.toDouble( &ok3 );
if ( ! ok3 )
KIG_FILTER_PARSE_ERROR;
if ( ( parents[0]->imp()->inherits( CircleImp::stype() ) ) ||
( parents[0]->imp()->inherits( SegmentImp::stype() ) ) )
oc = fact->constrainedPointCalcer( parents[0], value );
else if ( parents[0]->imp()->inherits( LineImp::stype() ) )
{
const LineData l = static_cast<const LineImp*>( parents[0]->imp() )->data();
const Coordinate p = convertDrgeoLineParam( value, l );
oc = fact->constrainedPointCalcer( parents[0], p, *ret );
}
else if ( parents[0]->imp()->inherits( RayImp::stype() ) )
{
const LineData l = static_cast<const RayImp*>( parents[0]->imp() )->data();
const Coordinate p = convertDrgeoHalflineParam( value, l );
oc = fact->constrainedPointCalcer( parents[0], p, *ret );
}
else if ( parents[0]->imp()->inherits( ArcImp::stype() ) )
oc = fact->constrainedPointCalcer( parents[0], 1 - value );
else
{
// oc = fact->constrainedPointCalcer( parents[0], value );
notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, "
"which Kig does not currently support." ).arg( domelem.tagName() ).arg(
domelem.attribute( "type" ) ) );
return 0;
}
}
else if ( domelem.attribute( "type" ) == "Intersection" )
{
if ( ( parents[0]->imp()->inherits( AbstractLineImp::stype() ) ) &&
( parents[1]->imp()->inherits( AbstractLineImp::stype() ) ) )
oc = new ObjectTypeCalcer( LineLineIntersectionType::instance(), parents );
else
{
bool ok;
int which = domelem.attribute( "extra" ).toInt( &ok );
if ( !ok ) KIG_FILTER_PARSE_ERROR;
if ( which == 1 ) which = -1;
else if ( which == 0 ) which = 1;
else KIG_FILTER_PARSE_ERROR;
std::vector<ObjectCalcer*> args = parents;
const ObjectType* type = 0;
args.push_back( new ObjectConstCalcer( new IntImp( which ) ) );
if ( ( parents[0]->imp()->inherits( CircleImp::stype() ) ) &&
( parents[1]->imp()->inherits( CircleImp::stype() ) ) )
type = CircleCircleIntersectionType::instance();
else if ( ( parents[0]->imp()->inherits( CircleImp::stype() ) &&
parents[1]->imp()->inherits( AbstractLineImp::stype() ) ) ||
( parents[1]->imp()->inherits( CircleImp::stype() ) &&
parents[0]->imp()->inherits( AbstractLineImp::stype() ) ) )
type = ConicLineIntersectionType::instance();
else if ( ( parents[0]->imp()->inherits( ArcImp::stype() ) &&
parents[1]->imp()->inherits( AbstractLineImp::stype() ) ) ||
( parents[1]->imp()->inherits( ArcImp::stype() ) &&
parents[0]->imp()->inherits( AbstractLineImp::stype() ) ) )
type = ArcLineIntersectionType::instance();
else
{
notSupported( file, i18n( "This Dr. Geo file contains an intersection type, "
"which Kig does not currently support." ) );
return 0;
}
oc = new ObjectTypeCalcer( type, args );
}
}
else if ( domelem.attribute( "type" ) == "Reflexion" )
oc = new ObjectTypeCalcer( LineReflectionType::instance(), parents );
else if ( domelem.attribute( "type" ) == "Symmetry" )
oc = new ObjectTypeCalcer( PointReflectionType::instance(), parents );
else if ( domelem.attribute( "type" ) == "Translation" )
oc = new ObjectTypeCalcer( TranslatedType::instance(), parents );
else if ( domelem.attribute( "type" ) == "Rotation" )
oc = new ObjectTypeCalcer( RotationType::instance(), parents );
else
{
notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, "
"which Kig does not currently support." ).arg( domelem.tagName() ).arg(
domelem.attribute( "type" ) ) );
return 0;
}
#ifdef DRGEO_DEBUG
kdDebug() << "+++++++++ oc:" << oc << endl;
#endif
}
else if( ( domelem.tagName() == "line" ) ||
( domelem.tagName() == "halfLine" ) ||
( domelem.tagName() == "segment" ) ||
( domelem.tagName() == "vector" ) ||
( domelem.tagName() == "circle" ) ||
( domelem.tagName() == "arcCircle" ) ||
( domelem.tagName() == "polygon" ) )
{
const ObjectType* type = 0;
if ( domelem.attribute( "type" ) == "2pts" )
{
if( domelem.tagName() == "line" )
type = LineABType::instance();
else if( domelem.tagName() == "halfLine" )
type = RayABType::instance();
else if( domelem.tagName() == "segment" )
type = SegmentABType::instance();
else if( domelem.tagName() == "vector" )
type = VectorType::instance();
else if( domelem.tagName() == "circle" )
type = CircleBCPType::instance();
else
{
notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, "
"which Kig does not currently support." ).arg( domelem.tagName() ).arg(
domelem.attribute( "type" ) ) );
return 0;
}
oc = new ObjectTypeCalcer( type, parents );
}
else if( domelem.attribute( "type" ) == "3pts" )
{
if( domelem.tagName() == "arcCircle" )
type = ArcBTPType::instance();
else
{
notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, "
"which Kig does not currently support." ).arg( domelem.tagName() ).arg(
domelem.attribute( "type" ) ) );
return 0;
}
oc = new ObjectTypeCalcer( type, parents );
}
else if( domelem.attribute( "type" ) == "segment" )
{
if( domelem.tagName() == "circle" )
{
type = CircleBPRType::instance();
ObjectPropertyCalcer* o = fact->propertyObjectCalcer( parents[1], "length" );
o->calc( *ret );
ObjectCalcer* a = parents[0];
parents.clear();
parents.push_back( a );
parents.push_back( o );
}
else
{
notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, "
"which Kig does not currently support." ).arg( domelem.tagName() ).arg(
domelem.attribute( "type" ) ) );
return 0;
}
oc = new ObjectTypeCalcer( type, parents );
}
else if( domelem.attribute( "type" ) == "npts" )
{
if( domelem.tagName() == "polygon" )
{
if ( parents.size() < 3 ) KIG_FILTER_PARSE_ERROR;
type = PolygonBNPType::instance();
}
else
{
notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, "
"which Kig does not currently support." ).arg( domelem.tagName() ).arg(
domelem.attribute( "type" ) ) );
return 0;
}
oc = new ObjectTypeCalcer( type, parents );
}
else if ( domelem.attribute( "type" ) == "perpendicular" )
oc = new ObjectTypeCalcer( LinePerpendLPType::instance(), parents );
else if ( domelem.attribute( "type" ) == "parallel" )
oc = new ObjectTypeCalcer( LineParallelLPType::instance(), parents );
else if ( domelem.attribute( "type" ) == "Reflexion" )
oc = new ObjectTypeCalcer( LineReflectionType::instance(), parents );
else if ( domelem.attribute( "type" ) == "Symmetry" )
oc = new ObjectTypeCalcer( PointReflectionType::instance(), parents );
else if ( domelem.attribute( "type" ) == "Translation" )
oc = new ObjectTypeCalcer( TranslatedType::instance(), parents );
else if ( domelem.attribute( "type" ) == "Rotation" )
oc = new ObjectTypeCalcer( RotationType::instance(), parents );
else
{
notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, "
"which Kig does not currently support." ).arg( domelem.tagName() ).arg(
domelem.attribute( "type" ) ) );
return 0;
}
#ifdef DRGEO_DEBUG
kdDebug() << "+++++++++ oc:" << oc << endl;
#endif
}
else if( ( domelem.tagName() == "numeric" ) ||
( domelem.tagName() == "equation" ) )
{
TQString xs;
TQString ys;
TQString value;
for ( TQDomNode c = domelem.firstChild(); ! c.isNull(); c = c.nextSibling() )
{
TQDomElement ce = c.toElement();
if ( ce.isNull() ) continue;
else if ( ce.tagName() == "x" )
xs = ce.text();
else if ( ce.tagName() == "y" )
ys = ce.text();
else if ( ce.tagName() == "value" )
value = ce.text();
}
bool ok;
bool ok2;
double x = xs.toDouble( &ok );
double y = ys.toDouble( &ok2 );
if ( ! ( ok && ok2 ) )
KIG_FILTER_PARSE_ERROR;
Coordinate m( x, y );
// types of 'numeric'
// ugly hack to show value numerics...
if ( domelem.attribute( "type" ) == "value" )
{
bool ok3;
double dvalue = value.toDouble( &ok3 );
if ( ok3 )
value = TQString( "%1" ).arg( dvalue, 0, 'g', 3 );
oc = fact->labelCalcer( value, m, false, std::vector<ObjectCalcer*>(), *ret );
}
else if ( domelem.attribute( "type" ) == "pt_abscissa" )
{
if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR;
oc = filtersConstructTextObject( m, parents[0], "coordinate-x", *ret, false );
}
else if ( domelem.attribute( "type" ) == "pt_ordinate" )
{
if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR;
oc = filtersConstructTextObject( m, parents[0], "coordinate-y", *ret, false );
}
else if ( domelem.attribute( "type" ) == "segment_length" )
{
if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR;
oc = filtersConstructTextObject( m, parents[0], "length", *ret, false );
}
else if ( domelem.attribute( "type" ) == "circle_perimeter" )
{
if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR;
oc = filtersConstructTextObject( m, parents[0], "circumference", *ret, false );
}
else if ( domelem.attribute( "type" ) == "arc_length" )
{
if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR;
oc = filtersConstructTextObject( m, parents[0], "arc-length", *ret, false );
}
else if ( domelem.attribute( "type" ) == "distance_2pts" )
{
if ( parents.size() != 2 ) KIG_FILTER_PARSE_ERROR;
ObjectTypeCalcer* so = new ObjectTypeCalcer( SegmentABType::instance(), parents );
so->calc( *ret );
oc = filtersConstructTextObject( m, so, "length", *ret, false );
}
else if ( domelem.attribute( "type" ) == "vector_norm" )
{
if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR;
oc = filtersConstructTextObject( m, parents[0], "length", *ret, false );
}
else if ( domelem.attribute( "type" ) == "vector_abscissa" )
{
if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR;
oc = filtersConstructTextObject( m, parents[0], "length-x", *ret, false );
}
else if ( domelem.attribute( "type" ) == "vector_ordinate" )
{
if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR;
oc = filtersConstructTextObject( m, parents[0], "length-y", *ret, false );
}
else if ( domelem.attribute( "type" ) == "slope" )
{
if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR;
oc = filtersConstructTextObject( m, parents[0], "slope", *ret, false );
}
else if ( domelem.attribute( "type" ) == "distance_pt_line" )
{
if ( parents.size() != 2 ) KIG_FILTER_PARSE_ERROR;
std::vector<ObjectCalcer*> args;
args.push_back( parents[1] );
args.push_back( parents[0] );
ObjectTypeCalcer* po = new ObjectTypeCalcer( LinePerpendLPType::instance(), args );
po->calc( *ret );
args.clear();
args.push_back( parents[1] );
args.push_back( po );
ObjectTypeCalcer* io = new ObjectTypeCalcer( LineLineIntersectionType::instance(), args );
io->calc( *ret );
args.clear();
args.push_back( parents[0] );
args.push_back( io );
ObjectTypeCalcer* so = new ObjectTypeCalcer( SegmentABType::instance(), args );
so->calc( *ret );
oc = filtersConstructTextObject( m, so, "length", *ret, false );
}
// types of 'equation'
else if ( domelem.attribute( "type" ) == "line" )
{
if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR;
oc = filtersConstructTextObject( m, parents[0], "equation", *ret, false );
}
else if ( domelem.attribute( "type" ) == "circle" )
{
if ( parents.size() != 1 ) KIG_FILTER_PARSE_ERROR;
oc = filtersConstructTextObject( m, parents[0], "simply-cartesian-equation", *ret, false );
}
else
{
notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, "
"which Kig does not currently support." ).arg( domelem.tagName() ).arg(
domelem.attribute( "type" ) ) );
return 0;
}
#ifdef DRGEO_DEBUG
kdDebug() << "+++++++++ oc:" << oc << endl;
#endif
}
else if ( domelem.tagName() == "angle" )
{
if ( domelem.attribute( "type" ) == "3pts" )
{
if ( parents.size() != 3 ) KIG_FILTER_PARSE_ERROR;
oc = new ObjectTypeCalcer( HalfAngleType::instance(), parents );
}
else
{
notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, "
"which Kig does not currently support." ).arg( domelem.tagName() ).arg(
domelem.attribute( "type" ) ) );
return 0;
}
#ifdef DRGEO_DEBUG
kdDebug() << "+++++++++ oc:" << oc << endl;
#endif
}
else if ( domelem.tagName() == "script" )
{
TQString xs;
TQString ys;
TQString text;
for ( TQDomNode c = domelem.firstChild(); ! c.isNull(); c = c.nextSibling() )
{
TQDomElement ce = c.toElement();
if ( ce.isNull() ) continue;
else if ( ce.tagName() == "x" )
xs = ce.text();
else if ( ce.tagName() == "y" )
ys = ce.text();
else if ( ce.tagName() == "code" )
text = ce.text();
}
bool ok;
bool ok2;
double x = xs.toDouble( &ok );
double y = ys.toDouble( &ok2 );
if ( ! ( ok && ok2 ) )
KIG_FILTER_PARSE_ERROR;
// since Kig doesn't support Guile scripts, it will write script's text
// in a label, so the user can freely see the code and make whatever
// he/she wants
// possible idea: construct a new script object with the parents of Guile
// one and the Guile code inserted commented... depends on a better
// handling of arguments in scripts?
if ( domelem.attribute( "type" ) == "nitems" )
oc = fact->labelCalcer( text, Coordinate( x, y ), false, std::vector<ObjectCalcer*>(), *ret );
else
{
notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, "
"which Kig does not currently support." ).arg( domelem.tagName() ).arg(
domelem.attribute( "type" ) ) );
return 0;
}
}
else if ( domelem.tagName() == "locus" )
{
if ( domelem.attribute( "type" ) == "None" )
oc = fact->locusCalcer( parents[0], parents[1] );
else
{
notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, "
"which Kig does not currently support." ).arg( domelem.tagName() ).arg(
domelem.attribute( "type" ) ) );
return 0;
}
#ifdef DRGEO_DEBUG
kdDebug() << "+++++++++ oc:" << oc << endl;
#endif
}
else if ( ( domelem.tagName() == "boundingBox" ) ||
( domelem.tagName() == "customUI" ) )
{
// ignoring these elements, since they are not useful to us...
nignored++;
}
else
{
#ifdef DRGEO_DEBUG
kdDebug() << ">>>>>>>>> UNKNOWN OBJECT" << endl;
#endif
notSupported( file, i18n( "This Dr. Geo file contains a \"%1 %2\" object, "
"which Kig does not currently support." ).arg( domelem.tagName() ).arg(
domelem.attribute( "type" ) ) );
return 0;
}
curid++;
if ( oc == 0 )
continue;
// reading color
TQColor co( domelem.attribute( "color" ) );
if ( ! co.isValid() )
if ( domelem.attribute( "color" ) == "Bordeaux" )
co.setRgb( 145, 0, 0 );
else
co = TQt::blue;
// reading width and style
// Dashed -> the little one
// Normal -> the medium
// Thick -> the biggest one
int w = -1;
Qt::PenStyle s = Qt::SolidLine;
if ( domelem.tagName() == "point" )
{
if ( domelem.attribute( "thickness" ) == "Normal" )
w = 7;
else if ( domelem.attribute( "thickness" ) == "Thick" )
w = 9;
}
else
{
if ( domelem.attribute( "thickness" ) == "Dashed" )
s = Qt::DotLine;
if ( domelem.attribute( "thickness" ) == "Thick" )
w = 2;
}
TQString ps = domelem.attribute( "style" );
int pointstyle = ObjectDrawer::pointStyleFromString( ps );
// show this object?
bool show = ( ( domelem.attribute( "masked" ) != "True" ) &&
( domelem.attribute( "masked" ) != "Alway" ) );
// costructing the ObjectDrawer*
ObjectDrawer* d = new ObjectDrawer( co, w, show, s, pointstyle );
// reading object name
TQString strname = domelem.attribute( "name" );
ObjectConstCalcer* name = new ObjectConstCalcer( new StringImp( strname ) );
// creating the ObjectHolder*
ObjectHolder* o = new ObjectHolder( oc, d, name );
holders.push_back( o );
// calc()
#ifdef DRGEO_DEBUG
kdDebug() << ">>>>>>>>> calc" << endl;
#endif
holders[curid-1-nignored]->calc( *ret );
if ( domelem.tagName() == "point" )
{
if ( !strname.isEmpty() )
{
std::vector<ObjectCalcer*> args2;
args2.push_back( o->nameCalcer() );
oc2 = fact->attachedLabelCalcer( TQString::fromLatin1( "%1" ), oc,
static_cast<const PointImp*>( oc->imp() )->coordinate(),
false, args2, *ret );
co = TQt::black;
}
}
else if ( domelem.tagName() == "angle" )
{
oc2 = filtersConstructTextObject(
static_cast<const PointImp*>( holders[curid-1-nignored]->calcer()->parents()[1]->imp() )->coordinate(),
holders[curid-1-nignored]->calcer(), "angle-degrees", *ret, false );
}
oc = 0;
if ( oc2 != 0 )
{
oc2->calc( *ret );
ObjectDrawer* d2 = new ObjectDrawer( co );
ObjectHolder* o2 = new ObjectHolder( oc2, d2 );
holders2.push_back( o2 );
oc2 = 0;
}
}
ret->addObjects( holders );
ret->addObjects( holders2 );
ret->setGrid( grid );
ret->setAxes( grid );
return ret;
}
KigFilterDrgeo* KigFilterDrgeo::instance()
{
static KigFilterDrgeo f;
return &f;
}