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.
tdegraphics/kpovmodeler/pminsertrulesystem.cpp

1062 lines
30 KiB

/*
**************************************************************************
description
--------------------
copyright : (C) 2002-2003 by Andreas Zehender
email : zehender@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. *
* *
**************************************************************************/
#include "pminsertrulesystem.h"
#include "pmprototypemanager.h"
#include "pmpart.h"
#include "pmvariant.h"
#include "pmdebug.h"
#include <tqfile.h>
#include <kstandarddirs.h>
bool isCategory( TQDomElement& e )
{
return( e.tagName( ) == "class" || e.tagName( ) == "group" );
}
PMRuleCategory* newCategory( TQDomElement& e,
TQPtrList<PMRuleDefineGroup>& globalGroups,
TQPtrList<PMRuleDefineGroup>& localGroups )
{
if( e.tagName( ) == "class" )
return new PMRuleClass( e );
if( e.tagName( ) == "group" )
return new PMRuleGroup( e, globalGroups, localGroups );
return 0;
}
PMPrototypeManager* PMRuleClass::s_pPrototypeManager = 0;
PMRuleClass::PMRuleClass( TQDomElement& e )
: PMRuleCategory( )
{
m_pPrototypeManager = s_pPrototypeManager;
m_className = e.attribute( "name" );
if( m_className.isEmpty( ) )
kdError( PMArea ) << "RuleSystem: Invalid class name" << endl;
if( !m_pPrototypeManager->existsClass( m_className ) )
kdError( PMArea ) << "RuleSystem: Unknown class: "
<< m_className << endl;
}
bool PMRuleClass::matches( const TQString& className )
{
return m_pPrototypeManager->isA( className, m_className );
}
PMRuleGroup::PMRuleGroup( TQDomElement& e,
TQPtrList<PMRuleDefineGroup>& globalGroups,
TQPtrList<PMRuleDefineGroup>& localGroups )
: PMRuleCategory( )
{
m_pGroup = 0;
TQString groupName = e.attribute( "name" );
if( groupName.isEmpty( ) )
kdError( PMArea ) << "RuleSystem: Invalid group name" << endl;
// find group
TQPtrListIterator<PMRuleDefineGroup> lit( localGroups );
for( ; lit.current( ) && !m_pGroup; ++lit )
if( lit.current( )->name( ) == groupName )
m_pGroup = lit.current( );
TQPtrListIterator<PMRuleDefineGroup> git( globalGroups );
for( ; git.current( ) && !m_pGroup; ++git )
if( git.current( )->name( ) == groupName )
m_pGroup = git.current( );
if( !m_pGroup )
kdError( PMArea ) << "RuleSystem: Group not defined: "
<< groupName << endl;
}
bool PMRuleGroup::matches( const TQString& className )
{
if( m_pGroup )
return m_pGroup->matches( className );
return false;
}
PMRuleDefineGroup::PMRuleDefineGroup( TQDomElement& e,
TQPtrList<PMRuleDefineGroup>& globalGroups,
TQPtrList<PMRuleDefineGroup>& localGroups )
{
m_name = e.attribute( "name" );
if( m_name.isEmpty( ) )
kdError( PMArea ) << "RuleSystem: Invalid group name" << endl;
TQDomNode m = e.firstChild( );
while( !m.isNull( ) )
{
if( m.isElement( ) )
{
TQDomElement me = m.toElement( );
if( isCategory( me ) )
m_categories.append( newCategory( me, globalGroups, localGroups ) );
}
m = m.nextSibling( );
}
}
PMRuleDefineGroup::~PMRuleDefineGroup( )
{
m_categories.setAutoDelete( true );
m_categories.clear( );
}
bool PMRuleDefineGroup::matches( const TQString& className )
{
bool m = false;
TQPtrListIterator<PMRuleCategory> it( m_categories );
for( ; it.current( ) && !m; ++it )
m = it.current( )->matches( className );
return m;
}
bool isValue( TQDomElement& e )
{
return( e.tagName( ) == "property" || e.tagName( ) == "const" ||
e.tagName( ) == "count" );
}
bool isCondition( TQDomElement& e )
{
return( e.tagName( ) == "not" || e.tagName( ) == "and" ||
e.tagName( ) == "or" || e.tagName( ) == "before" ||
e.tagName( ) == "after" || e.tagName( ) == "contains" ||
e.tagName( ) == "greater" || e.tagName( ) == "less" ||
e.tagName( ) == "equal" );
}
PMRuleValue* newValue( TQDomElement& e,
TQPtrList<PMRuleDefineGroup>& globalGroups,
TQPtrList<PMRuleDefineGroup>& localGroups )
{
if( e.tagName( ) == "property" )
return new PMRuleProperty( e );
if( e.tagName( ) == "const" )
return new PMRuleConstant( e );
if( e.tagName( ) == "count" )
return new PMRuleCount( e, globalGroups, localGroups );
return 0;
}
PMRuleCondition* newCondition( TQDomElement& e,
TQPtrList<PMRuleDefineGroup>& globalGroups,
TQPtrList<PMRuleDefineGroup>& localGroups )
{
if( e.tagName( ) == "not" )
return new PMRuleNot( e, globalGroups, localGroups );
if( e.tagName( ) == "and" )
return new PMRuleAnd( e, globalGroups, localGroups );
if( e.tagName( ) == "or" )
return new PMRuleOr( e, globalGroups, localGroups );
if( e.tagName( ) == "before" )
return new PMRuleBefore( e, globalGroups, localGroups );
if( e.tagName( ) == "after" )
return new PMRuleAfter( e, globalGroups, localGroups );
if( e.tagName( ) == "contains" )
return new PMRuleContains( e, globalGroups, localGroups );
if( e.tagName( ) == "greater" )
return new PMRuleGreater( e, globalGroups, localGroups );
if( e.tagName( ) == "less" )
return new PMRuleLess( e, globalGroups, localGroups );
if( e.tagName( ) == "equal" )
return new PMRuleEqual( e, globalGroups, localGroups );
return 0;
}
PMRuleBase::~PMRuleBase( )
{
m_tqchildren.setAutoDelete( true );
m_tqchildren.clear( );
}
void PMRuleBase::countChild( const TQString& className, bool afterInsertPoint )
{
countChildProtected( className, afterInsertPoint );
TQPtrListIterator<PMRuleBase> it( m_tqchildren );
for( ; it.current( ); ++it )
it.current( )->countChild( className, afterInsertPoint );
}
void PMRuleBase::reset( )
{
resetProtected( );
TQPtrListIterator<PMRuleBase> it( m_tqchildren );
for( ; it.current( ); ++it )
it.current( )->reset( );
}
PMRuleProperty::PMRuleProperty( TQDomElement& e )
: PMRuleValue( )
{
m_property = e.attribute( "name" );
if( m_property.isNull( ) )
kdError( PMArea ) << "RuleSystem: Invalid property name" << endl;
}
PMVariant PMRuleProperty::evaluate( const PMObject* o )
{
PMVariant v = o->property( m_property );
if( v.isNull( ) )
kdError( PMArea ) << "RuleSystem: Invalid property name: "
<< m_property << endl;
return v;
}
PMRuleConstant::PMRuleConstant( TQDomElement& e )
: PMRuleValue( )
{
TQString v = e.attribute( "value" );
if( v.isNull( ) )
kdError( PMArea ) << "RuleSystem: Invalid value" << endl;
m_value = PMVariant( v );
}
PMVariant PMRuleConstant::evaluate( const PMObject* )
{
return m_value;
}
bool PMRuleConstant::convertTo( PMVariant::PMVariantDataType type )
{
return m_value.convertTo( type );
}
PMRuleCount::PMRuleCount( TQDomElement& e,
TQPtrList<PMRuleDefineGroup>& globalGroups,
TQPtrList<PMRuleDefineGroup>& localGroups )
: PMRuleValue( )
{
m_number = 0;
TQDomNode m = e.firstChild( );
while( !m.isNull( ) )
{
if( m.isElement( ) )
{
TQDomElement me = m.toElement( );
if( isCategory( me ) )
m_categories.append( newCategory( me, globalGroups, localGroups ) );
}
m = m.nextSibling( );
}
}
PMRuleCount::~PMRuleCount( )
{
m_categories.setAutoDelete( true );
m_categories.clear( );
}
PMVariant PMRuleCount::evaluate( const PMObject* )
{
return PMVariant( m_number );
}
void PMRuleCount::countChildProtected( const TQString& className, bool )
{
bool m = false;
TQPtrListIterator<PMRuleCategory> it( m_categories );
for( ; it.current( ) && !m; ++it )
m = it.current( )->matches( className );
if( m )
m_number++;
}
void PMRuleCount::resetProtected( )
{
m_number = 0;
}
PMRuleNot::PMRuleNot( TQDomElement& e,
TQPtrList<PMRuleDefineGroup>& globalGroups,
TQPtrList<PMRuleDefineGroup>& localGroups )
: PMRuleCondition( )
{
m_pChild = 0;
TQDomNode m = e.firstChild( );
while( !m.isNull( ) && !m_pChild )
{
if( m.isElement( ) )
{
TQDomElement me = m.toElement( );
if( isCondition( me ) )
{
m_pChild = newCondition( me, globalGroups, localGroups );
m_tqchildren.append( m_pChild );
}
}
m = m.nextSibling( );
}
}
bool PMRuleNot::evaluate( const PMObject* object )
{
if( m_pChild )
return !m_pChild->evaluate( object );
return true;
}
PMRuleAnd::PMRuleAnd( TQDomElement& e,
TQPtrList<PMRuleDefineGroup>& globalGroups,
TQPtrList<PMRuleDefineGroup>& localGroups )
: PMRuleCondition( )
{
TQDomNode m = e.firstChild( );
while( !m.isNull( ) )
{
if( m.isElement( ) )
{
TQDomElement me = m.toElement( );
if( isCondition( me ) )
{
PMRuleCondition* c = newCondition( me, globalGroups, localGroups );
m_tqchildren.append( c );
m_conditions.append( c );
}
}
m = m.nextSibling( );
}
}
bool PMRuleAnd::evaluate( const PMObject* object )
{
bool b = true;
TQPtrListIterator<PMRuleCondition> it( m_conditions );
for( ; it.current( ) && b; ++it )
b = it.current( )->evaluate( object );
return b;
}
PMRuleOr::PMRuleOr( TQDomElement& e,
TQPtrList<PMRuleDefineGroup>& globalGroups,
TQPtrList<PMRuleDefineGroup>& localGroups )
: PMRuleCondition( )
{
TQDomNode m = e.firstChild( );
while( !m.isNull( ) )
{
if( m.isElement( ) )
{
TQDomElement me = m.toElement( );
if( isCondition( me ) )
{
PMRuleCondition* c = newCondition( me, globalGroups, localGroups );
m_tqchildren.append( c );
m_conditions.append( c );
}
}
m = m.nextSibling( );
}
}
bool PMRuleOr::evaluate( const PMObject* object )
{
bool b = false;
TQPtrListIterator<PMRuleCondition> it( m_conditions );
for( ; it.current( ) && !b; ++it )
b = it.current( )->evaluate( object );
return b;
}
PMRuleBefore::PMRuleBefore( TQDomElement& e,
TQPtrList<PMRuleDefineGroup>& globalGroups,
TQPtrList<PMRuleDefineGroup>& localGroups )
: PMRuleCondition( )
{
m_contains = false;
TQDomNode m = e.firstChild( );
while( !m.isNull( ) )
{
if( m.isElement( ) )
{
TQDomElement me = m.toElement( );
if( isCategory( me ) )
m_categories.append( newCategory( me, globalGroups, localGroups ) );
}
m = m.nextSibling( );
}
}
PMRuleBefore::~PMRuleBefore( )
{
m_categories.setAutoDelete( true );
m_categories.clear( );
}
bool PMRuleBefore::evaluate( const PMObject* )
{
return m_contains;
}
void PMRuleBefore::countChildProtected( const TQString& className,
bool afterInsertPoint )
{
if( afterInsertPoint && !m_contains )
{
TQPtrListIterator<PMRuleCategory> it( m_categories );
for( ; it.current( ) && !m_contains; ++it )
m_contains = it.current( )->matches( className );
}
}
void PMRuleBefore::resetProtected( )
{
m_contains = false;
}
PMRuleAfter::PMRuleAfter( TQDomElement& e,
TQPtrList<PMRuleDefineGroup>& globalGroups,
TQPtrList<PMRuleDefineGroup>& localGroups )
: PMRuleCondition( )
{
m_contains = false;
TQDomNode m = e.firstChild( );
while( !m.isNull( ) )
{
if( m.isElement( ) )
{
TQDomElement me = m.toElement( );
if( isCategory( me ) )
m_categories.append( newCategory( me, globalGroups, localGroups ) );
}
m = m.nextSibling( );
}
}
PMRuleAfter::~PMRuleAfter( )
{
m_categories.setAutoDelete( true );
m_categories.clear( );
}
bool PMRuleAfter::evaluate( const PMObject* )
{
return m_contains;
}
void PMRuleAfter::countChildProtected( const TQString& className,
bool afterInsertPoint )
{
if( !afterInsertPoint && !m_contains )
{
TQPtrListIterator<PMRuleCategory> it( m_categories );
for( ; it.current( ) && !m_contains; ++it )
m_contains = it.current( )->matches( className );
}
}
void PMRuleAfter::resetProtected( )
{
m_contains = false;
}
PMRuleContains::PMRuleContains( TQDomElement& e,
TQPtrList<PMRuleDefineGroup>& globalGroups,
TQPtrList<PMRuleDefineGroup>& localGroups )
: PMRuleCondition( )
{
m_contains = false;
TQDomNode m = e.firstChild( );
while( !m.isNull( ) )
{
if( m.isElement( ) )
{
TQDomElement me = m.toElement( );
if( isCategory( me ) )
m_categories.append( newCategory( me, globalGroups, localGroups ) );
}
m = m.nextSibling( );
}
}
PMRuleContains::~PMRuleContains( )
{
m_categories.setAutoDelete( true );
m_categories.clear( );
}
bool PMRuleContains::evaluate( const PMObject* )
{
return m_contains;
}
void PMRuleContains::countChildProtected( const TQString& className, bool )
{
if( !m_contains )
{
TQPtrListIterator<PMRuleCategory> it( m_categories );
for( ; it.current( ) && !m_contains; ++it )
m_contains = it.current( )->matches( className );
}
}
void PMRuleContains::resetProtected( )
{
m_contains = false;
}
PMRuleCompare::PMRuleCompare( TQDomElement& e,
TQPtrList<PMRuleDefineGroup>& globalGroups,
TQPtrList<PMRuleDefineGroup>& localGroups )
: PMRuleCondition( )
{
m_pValue[0] = 0;
m_pValue[1] = 0;
int i = 0;
TQDomNode m = e.firstChild( );
while( !m.isNull( ) && !m_pValue[1] )
{
if( m.isElement( ) )
{
TQDomElement me = m.toElement( );
if( isValue( me ) )
{
m_pValue[i] = newValue( me, globalGroups, localGroups );
m_tqchildren.append( m_pValue[i] );
i++;
}
}
m = m.nextSibling( );
}
if( !m_pValue[1] )
kdError( PMArea ) << "RuleSystem: Comparison needs two values" << endl;
}
bool PMRuleCompare::evaluate( const PMObject* object )
{
if( !m_pValue[1] )
return false;
PMVariant v[2];
v[0] = m_pValue[0]->evaluate( object );
v[1] = m_pValue[1]->evaluate( object );
if( v[0].isNull( ) || v[1].isNull( ) )
return false;
bool convertError = false;
if( v[0].dataType( ) != v[1].dataType( ) )
{
if( m_pValue[1]->type( ) == "Constant" )
{
if( v[1].convertTo( v[0].dataType( ) ) )
( ( PMRuleConstant* ) m_pValue[1] )->convertTo( v[0].dataType( ) );
else
convertError = true;
}
else if( m_pValue[0]->type( ) == "Constant" )
{
if( v[0].convertTo( v[1].dataType( ) ) )
( ( PMRuleConstant* ) m_pValue[0] )->convertTo( v[1].dataType( ) );
else
convertError = true;
}
else
convertError = true;
}
if( convertError )
{
kdError( PMArea ) << "RuleSystem: Types in comparison must match" << endl;
return false;
}
return compare( v[0], v[1] );
}
PMRuleLess::PMRuleLess( TQDomElement& e,
TQPtrList<PMRuleDefineGroup>& globalGroups,
TQPtrList<PMRuleDefineGroup>& localGroups )
: PMRuleCompare( e, globalGroups, localGroups )
{
}
bool PMRuleLess::compare( const PMVariant& v1, const PMVariant& v2 )
{
bool c = false;
switch( v1.dataType( ) )
{
case PMVariant::Integer:
c = v1.intData( ) < v2.intData( );
break;
case PMVariant::Unsigned:
c = v1.unsignedData( ) < v2.unsignedData( );
break;
case PMVariant::Double:
c = v1.doubleData( ) < v2.doubleData( );
break;
case PMVariant::String:
c = v1.stringData( ) < v2.stringData( );
break;
case PMVariant::Bool:
kdError( PMArea ) << "RuleSystem: Less: Can't compare booleans" << endl;
break;
case PMVariant::ThreeState:
kdError( PMArea ) << "RuleSystem: Less: Can't compare ThreeStates" << endl;
break;
case PMVariant::Vector:
kdError( PMArea ) << "RuleSystem: Less: Can't compare vectors" << endl;
break;
case PMVariant::Color:
kdError( PMArea ) << "RuleSystem: Less: Can't compare colors" << endl;
break;
case PMVariant::ObjectPointer:
kdError( PMArea ) << "RuleSystem: Less: Can't compare object pointers" << endl;
break;
case PMVariant::None:
kdError( PMArea ) << "RuleSystem: Less: Value has type none" << endl;
break;
}
return c;
}
PMRuleGreater::PMRuleGreater( TQDomElement& e,
TQPtrList<PMRuleDefineGroup>& globalGroups,
TQPtrList<PMRuleDefineGroup>& localGroups )
: PMRuleCompare( e, globalGroups, localGroups )
{
}
bool PMRuleGreater::compare( const PMVariant& v1, const PMVariant& v2 )
{
bool c = false;
switch( v1.dataType( ) )
{
case PMVariant::Integer:
c = v1.intData( ) > v2.intData( );
break;
case PMVariant::Unsigned:
c = v1.unsignedData( ) > v2.unsignedData( );
break;
case PMVariant::Double:
c = v1.doubleData( ) > v2.doubleData( );
break;
case PMVariant::String:
c = v1.stringData( ) > v2.stringData( );
break;
case PMVariant::Bool:
kdError( PMArea ) << "RuleSystem: Greater: Can't compare booleans" << endl;
break;
case PMVariant::ThreeState:
kdError( PMArea ) << "RuleSystem: Greater: Can't compare ThreeStates" << endl;
break;
case PMVariant::Vector:
kdError( PMArea ) << "RuleSystem: Greater: Can't compare vectors" << endl;
break;
case PMVariant::Color:
kdError( PMArea ) << "RuleSystem: Greater: Can't compare colors" << endl;
break;
case PMVariant::ObjectPointer:
kdError( PMArea ) << "RuleSystem: Greater: Can't compare object pointers" << endl;
break;
case PMVariant::None:
kdError( PMArea ) << "RuleSystem: Greater: Value has type none" << endl;
break;
}
return c;
}
PMRuleEqual::PMRuleEqual( TQDomElement& e,
TQPtrList<PMRuleDefineGroup>& globalGroups,
TQPtrList<PMRuleDefineGroup>& localGroups )
: PMRuleCompare( e, globalGroups, localGroups )
{
}
bool PMRuleEqual::compare( const PMVariant& v1, const PMVariant& v2 )
{
bool c = false;
switch( v1.dataType( ) )
{
case PMVariant::Integer:
c = v1.intData( ) == v2.intData( );
break;
case PMVariant::Unsigned:
c = v1.unsignedData( ) == v2.unsignedData( );
break;
case PMVariant::Double:
c = v1.doubleData( ) == v2.doubleData( );
break;
case PMVariant::String:
c = v1.stringData( ) == v2.stringData( );
break;
case PMVariant::Bool:
c = v1.boolData( ) == v2.boolData( );
break;
case PMVariant::ThreeState:
c = v1.threeStateData( ) == v2.threeStateData( );
break;
case PMVariant::Vector:
kdError( PMArea ) << "RuleSystem: Equal: Can't compare vectors" << endl;
break;
case PMVariant::Color:
kdError( PMArea ) << "RuleSystem: Equal: Can't compare colors" << endl;
break;
case PMVariant::ObjectPointer:
kdError( PMArea ) << "RuleSystem: Equal: Can't compare object pointers" << endl;
break;
case PMVariant::None:
kdError( PMArea ) << "RuleSystem: Equal: Value has type none" << endl;
break;
}
return c;
}
PMRule::PMRule( TQDomElement& e,
TQPtrList<PMRuleDefineGroup>& globalGroups,
TQPtrList<PMRuleDefineGroup>& localGroups )
: PMRuleBase( )
{
m_pCondition = 0;
TQDomNode m = e.firstChild( );
while( !m.isNull( ) && !m_pCondition )
{
if( m.isElement( ) )
{
TQDomElement me = m.toElement( );
if( isCategory( me ) )
m_categories.append( newCategory( me, globalGroups, localGroups ) );
else if( isCondition( me ) )
{
m_pCondition = newCondition( me, globalGroups, localGroups );
m_tqchildren.append( m_pCondition );
}
}
m = m.nextSibling( );
}
}
PMRule::~PMRule( )
{
m_categories.setAutoDelete( true );
m_categories.clear( );
}
bool PMRule::matches( const TQString& className )
{
bool m = false;
TQPtrListIterator<PMRuleCategory> it( m_categories );
for( ; it.current( ) && !m; ++it )
m = it.current( )->matches( className );
return m;
}
bool PMRule::evaluate( const PMObject* parent )
{
if( !m_pCondition )
return true;
else
return m_pCondition->evaluate( parent );
}
PMRuleTargetClass::PMRuleTargetClass( TQDomElement& e,
TQPtrList<PMRuleDefineGroup>& globalGroups )
{
m_class = e.attribute( "name" );
if( m_class.isEmpty( ) )
kdError( PMArea ) << "RuleSystem: Invalid class name" << endl;
appendRules( e, globalGroups );
}
void PMRuleTargetClass::appendRules( TQDomElement& e,
TQPtrList<PMRuleDefineGroup>& globalGroups )
{
TQDomNode m = e.firstChild( );
while( !m.isNull( ) )
{
if( m.isElement( ) )
{
TQDomElement me = m.toElement( );
if( me.tagName( ) == "definegroup" )
m_groups.append( new PMRuleDefineGroup( me, globalGroups, m_groups ) );
if( me.tagName( ) == "rule" )
m_rules.append( new PMRule( me, globalGroups, m_groups ) );
if( me.tagName( ) == "exception" )
m_exceptions.append( me.attribute( "class" ) );
}
m = m.nextSibling( );
}
}
PMRuleTargetClass::~PMRuleTargetClass( )
{
m_groups.setAutoDelete( true );
m_groups.clear( );
m_rules.setAutoDelete( true );
m_rules.clear( );
}
PMInsertRuleSystem::PMInsertRuleSystem( PMPart* part )
{
m_pPart = part;
}
PMInsertRuleSystem::~PMInsertRuleSystem( )
{
m_groups.setAutoDelete( true );
m_groups.clear( );
m_classRules.setAutoDelete( true );
m_classRules.clear( );
}
void PMInsertRuleSystem::loadRules( const TQString& fileName )
{
PMRuleClass::s_pPrototypeManager = m_pPart->prototypeManager( );
if( m_loadedFiles.find( fileName ) != m_loadedFiles.end( ) )
return;
m_loadedFiles.push_back( fileName );
TQString ruleFile = locate( "data", TQString( "kpovmodeler/" + fileName ) );
if( ruleFile.isEmpty( ) )
{
kdError( PMArea ) << "Rule file 'kpovmodeler/" << fileName
<< "' not found." << endl;
return;
}
TQFile file( ruleFile );
if( !file.open( IO_ReadOnly ) )
{
kdError( PMArea ) << "Could not open rule file 'kpovmodeler/" << fileName
<< "'" << endl;
return;
}
TQDomDocument doc( "insertrules" );
doc.setContent( &file );
TQDomElement e = doc.documentElement( );
if( e.attribute( "format" ) != "1.0" )
kdError( PMArea ) << "Rule format " << e.attribute( "format" )
<< " not supported." << endl;
else
{
TQDomNode c = e.firstChild( );
TQPtrList<PMRuleDefineGroup> dummyLocalGroups;
while( !c.isNull( ) )
{
if( c.isElement( ) )
{
TQDomElement ce = c.toElement( );
if( ce.tagName( ) == "definegroup" )
m_groups.append( new PMRuleDefineGroup( ce, m_groups,
dummyLocalGroups ) );
else if( ce.tagName( ) == "targetclass" )
{
TQString className = ce.attribute( "name" );
// find a target class with the same name
PMRuleTargetClass* target = 0;
if( !m_rulesDict.isEmpty( ) )
target = m_rulesDict.find( className );
if( target )
target->appendRules( ce, m_groups );
else
{
target = new PMRuleTargetClass( ce, m_groups );
m_rulesDict.insert( className, target );
m_classRules.append( target );
}
}
}
c = c.nextSibling( );
}
}
file.close( );
PMRuleClass::s_pPrototypeManager = 0;
}
bool PMInsertRuleSystem::canInsert( const PMObject* parentObject,
const TQString& className,
const PMObject* after,
const PMObjectList* objectsBetween )
{
bool possible = false;
// find rules for target class
PMMetaObject* meta = parentObject->metaObject( );
for( ; meta && !possible; meta = meta->superClass( ) )
{
PMRuleTargetClass* tc = m_rulesDict.find( meta->className( ) );
if( tc )
{
// check the exception list
TQStringList exceptions = tc->exceptions( );
bool exceptionFound = false;
TQStringList::ConstIterator it;
for( it = exceptions.begin( );
it != exceptions.end( ) && !exceptionFound; ++it )
if( parentObject->isA( *it ) )
exceptionFound = true;
if( !exceptionFound )
{
TQPtrListIterator<PMRule> rit = tc->rules( );
// find matching rules for class name
for( ; rit.current( ) && !possible; ++rit )
{
PMRule* rule = rit.current( );
if( rule->matches( className ) )
{
// matching rule found
// reset the rule
rit.current( )->reset( );
// count already inserted child objects
bool afterInsertPoint = false;
PMObject* o = parentObject->firstChild( );
if( !after )
afterInsertPoint = true;
for( ; o; o = o->nextSibling( ) )
{
rule->countChild( o->className( ), afterInsertPoint );
if( o == after )
afterInsertPoint = true;
}
if( objectsBetween )
{
PMObjectListIterator it( *objectsBetween );
for( ; it.current( ); ++it )
rule->countChild( it.current( )->type( ), false );
}
// evaluate condition value
possible = rule->evaluate( parentObject );
}
}
}
}
}
return possible;
}
bool PMInsertRuleSystem::canInsert( const PMObject* parentObject,
const PMObject* object,
const PMObject* after,
const PMObjectList* objectsBetween )
{
return canInsert( parentObject, object->type( ), after, objectsBetween );
}
int PMInsertRuleSystem::canInsert( const PMObject* parentObject,
const PMObjectList& list,
const PMObject* after )
{
PMObjectListIterator it( list );
TQStringList classes;
for( ; it.current( ); ++it )
classes.append( it.current( )->type( ) );
return canInsert( parentObject, classes, after );
}
int PMInsertRuleSystem::canInsert( const PMObject* parentObject,
const TQStringList& list,
const PMObject* after )
{
if( list.size( ) == 1 )
{
// more efficient
if( canInsert( parentObject, list.first( ), after ) )
return 1;
else
return 0;
}
// find rules for target class
TQPtrList<PMRuleTargetClass> targetClassList;
PMMetaObject* meta = parentObject->metaObject( );
for( ; meta; meta = meta->superClass( ) )
{
PMRuleTargetClass* tc = m_rulesDict.find( meta->className( ) );
if( tc )
targetClassList.append( tc );
}
if( targetClassList.isEmpty( ) )
return 0; // not rules found
// count already inserted tqchildren
TQPtrListIterator<PMRuleTargetClass> tit( targetClassList );
for( ; tit.current( ); ++tit ) // ... for all target classes
{
TQPtrListIterator<PMRule> rit = tit.current( )->rules( );
for( ; rit.current( ); ++rit ) // ... and all rules
{
rit.current( )->reset( );
bool afterInsertPoint = false;
PMObject* o = parentObject->firstChild( );
if( !after )
afterInsertPoint = true;
for( ; o; o = o->nextSibling( ) )
{
rit.current( )->countChild( o->className( ), afterInsertPoint );
if( o == after )
afterInsertPoint = true;
}
}
}
int number = 0;
TQStringList::const_iterator oit;
for( oit = list.begin( ); oit != list.end( ); ++oit )
{
bool possible = false;
for( tit.toFirst( ); tit.current( ) && !possible; ++tit )
{
TQPtrListIterator<PMRule> rit = tit.current( )->rules( );
for( ; rit.current( ) && !possible; ++rit )
{
PMRule* rule = rit.current( );
if( rule->matches( *oit ) )
possible = rule->evaluate( parentObject );
}
}
if( possible )
{
// object can be inserted, count it
for( ; tit.current( ); ++tit )
{
TQPtrListIterator<PMRule> rit = tit.current( )->rules( );
for( ; rit.current( ); ++rit )
rit.current( )->countChild( *oit, false );
}
number++;
}
}
return number;
}