diff options
Diffstat (limited to 'kpovmodeler/pminsertrulesystem.h')
-rw-r--r-- | kpovmodeler/pminsertrulesystem.h | 678 |
1 files changed, 678 insertions, 0 deletions
diff --git a/kpovmodeler/pminsertrulesystem.h b/kpovmodeler/pminsertrulesystem.h new file mode 100644 index 00000000..499cbc8e --- /dev/null +++ b/kpovmodeler/pminsertrulesystem.h @@ -0,0 +1,678 @@ +//-*-C++-*- +/* +************************************************************************** + 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. * +* * +**************************************************************************/ + +#ifndef PMINSERTRULESYSTEM_H +#define PMINSERTRULESYSTEM_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "pmobject.h" + +#include <qstringlist.h> +#include <qptrlist.h> +#include <qdict.h> +#include <qdom.h> + +class PMInsertRuleSystem; +class PMPrototypeManager; + +/** + * Base class for all object categories (class and group) + * for the insert rule system + */ +class PMRuleCategory +{ +public: + /** + * Default constructor + */ + PMRuleCategory( ) { } + /** + * Destructor + */ + virtual ~PMRuleCategory( ) { } + /** + * Returns true if the given class types matches the category. + */ + virtual bool matches( const QString& className ) = 0; +}; + +/** + * Represents a class for the insert rule system + */ +class PMRuleClass : public PMRuleCategory +{ +public: + /** + * Workaround to tell a created instance which + * prototype manager to use. + */ + static PMPrototypeManager* s_pPrototypeManager; + /** + * Reads the data from the QDomElement. + */ + PMRuleClass( QDomElement& e ); + /** */ + virtual bool matches( const QString& className ); +private: + QString m_className; + PMPrototypeManager* m_pPrototypeManager; +}; + +/** + * Groups together multiple classes or groups to form a new + * category for the insert rule system. + */ +class PMRuleDefineGroup +{ +public: + /** + * Reads the data from the QDomElement. + */ + PMRuleDefineGroup( QDomElement& e, QPtrList<PMRuleDefineGroup>& globalGroups, + QPtrList<PMRuleDefineGroup>& localGroups ); + /** + * Destructor + */ + virtual ~PMRuleDefineGroup( ); + /** + * Returns true if the given class types matches the category. + */ + virtual bool matches( const QString& className ); + /** + * Returns the group's name + */ + QString name( ) const { return m_name; } +private: + QPtrList<PMRuleCategory> m_categories; + QString m_name; +}; + +/** + * Represents a group for the insert rule system + */ +class PMRuleGroup : public PMRuleCategory +{ +public: + /** + * Reads the data from the QDomElement. + */ + PMRuleGroup( QDomElement& e, QPtrList<PMRuleDefineGroup>& globalGroups, + QPtrList<PMRuleDefineGroup>& localGroups ); + /** */ + bool matches( const QString& className ); +private: + PMRuleDefineGroup* m_pGroup; +}; + + +/** + * Base class for all nodes for the insert rule system + */ +class PMRuleBase +{ +public: + /** + * Default constructor. + */ + PMRuleBase( ) { } + /** + * Destructor + */ + virtual ~PMRuleBase( ); + /** + * Returns the node type. + */ + virtual QString type( ) const = 0; + /** + * Calls countChildProtected for this node and all child nodes + */ + void countChild( const QString& className, bool afterInsertPoint ); + /** + * Calls resetProtected for this node and all child nodes + */ + void reset( ); + /** + * Returns an iterator to all child nodes + */ + QPtrListIterator<PMRuleBase> childIterator( ) const + { + return QPtrListIterator<PMRuleBase>( m_children ); + } +protected: + /** + * Reimplement this method if the nodes value depends + * on already inserted child objects. + */ + virtual void countChildProtected( const QString&, bool ) { } + /** + * Reset all cached data (like counted child objects) here. + */ + virtual void resetProtected( ) { } + + /** + * Add all child nodes to this list. + */ + QPtrList<PMRuleBase> m_children; +}; + +/** + * Base class for values used by the rule system + */ +class PMRuleValue : public PMRuleBase +{ +public: + /** + * Default constructor + */ + PMRuleValue( ) : PMRuleBase( ) { } + /** + * Returns the node's value as variant. + * + * Reimplement this method in sub classes. + */ + virtual PMVariant evaluate( const PMObject* o ) = 0; +}; + + +/** + * Value node for object properties + */ +class PMRuleProperty : public PMRuleValue +{ +public: + /** + * Reads the data from the QDomElement. + */ + PMRuleProperty( QDomElement& e ); + /** */ + virtual QString type( ) const { return QString( "Property" ); } + /** */ + virtual PMVariant evaluate( const PMObject* o ); +private: + QString m_property; +}; + + +/** + * Simple constant + */ +class PMRuleConstant : public PMRuleValue +{ +public: + /** + * Reads the data from the QDomElement. + */ + PMRuleConstant( QDomElement& e ); + /** */ + virtual QString type( ) const { return QString( "Constant" ); } + /** */ + virtual PMVariant evaluate( const PMObject* ); + /** + * Converts the constant to the given type and returns true if + * successful. + */ + bool convertTo( PMVariant::PMVariantDataType type ); +private: + PMVariant m_value; +}; + +/** + * Rule that counts child objects of certaint types + */ +class PMRuleCount : public PMRuleValue +{ +public: + /** + * Reads the data from the QDomElement. + */ + PMRuleCount( QDomElement& e, QPtrList<PMRuleDefineGroup>& globalGroups, + QPtrList<PMRuleDefineGroup>& localGroups ); + /** + * Destructor + */ + virtual ~PMRuleCount( ); + /** */ + virtual QString type( ) const { return QString( "Count" ); } + /** */ + virtual PMVariant evaluate( const PMObject* ); +protected: + /** */ + virtual void countChildProtected( const QString& className, + bool afterInsertPoint ); + /** + * Reset all cached data (like counted child objects) here. + */ + virtual void resetProtected( ); +private: + QPtrList<PMRuleCategory> m_categories; + int m_number; +}; + +/** + * Base class for conditions + */ +class PMRuleCondition : public PMRuleBase +{ +public: + /** + * Default constructor + */ + PMRuleCondition( ) : PMRuleBase( ) { } + /** + * Returns the condition's value. + * + * Reimplement this method in sub classes. + */ + virtual bool evaluate( const PMObject* object ) = 0; +}; + + +/** + * Logical negation + */ +class PMRuleNot : public PMRuleCondition +{ +public: + /** + * Reads the data from the QDomElement. + */ + PMRuleNot( QDomElement& e, QPtrList<PMRuleDefineGroup>& globalGroups, + QPtrList<PMRuleDefineGroup>& localGroups ); + /** */ + virtual QString type( ) const { return QString( "Not" ); } + /** */ + virtual bool evaluate( const PMObject* object ); +private: + PMRuleCondition* m_pChild; +}; + + +/** + * Logical and + */ +class PMRuleAnd : public PMRuleCondition +{ +public: + /** + * Reads the data from the QDomElement. + */ + PMRuleAnd( QDomElement& e, QPtrList<PMRuleDefineGroup>& globalGroups, + QPtrList<PMRuleDefineGroup>& localGroups ); + /** */ + virtual QString type( ) const { return QString( "And" ); } + /** */ + virtual bool evaluate( const PMObject* object ); +private: + QPtrList<PMRuleCondition> m_conditions; +}; + +/** + * Logical or + */ +class PMRuleOr : public PMRuleCondition +{ +public: + /** + * Reads the data from the QDomElement. + */ + PMRuleOr( QDomElement& e, QPtrList<PMRuleDefineGroup>& globalGroups, + QPtrList<PMRuleDefineGroup>& localGroups ); + /** */ + virtual QString type( ) const { return QString( "Or" ); } + /** */ + virtual bool evaluate( const PMObject* object ); +private: + QPtrList<PMRuleCondition> m_conditions; +}; + +/** + * Condition. Value is true if the object already contains + * objects of certaint classes before the insert point. + */ +class PMRuleBefore : public PMRuleCondition +{ +public: + /** + * Reads the data from the QDomElement. + */ + PMRuleBefore( QDomElement& e, QPtrList<PMRuleDefineGroup>& globalGroups, + QPtrList<PMRuleDefineGroup>& localGroups ); + /** + * Destructor + */ + virtual ~PMRuleBefore( ); + /** */ + virtual QString type( ) const { return QString( "Before" ); } + /** */ + virtual bool evaluate( const PMObject* object ); +protected: + /** */ + virtual void countChildProtected( const QString& className, + bool afterInsertPoint ); + /** */ + virtual void resetProtected( ); +private: + QPtrList<PMRuleCategory> m_categories; + bool m_contains; +}; + +/** + * Condition. Value is true if the object already contains + * objects of certaint classes after the insert point. + */ +class PMRuleAfter : public PMRuleCondition +{ +public: + /** + * Reads the data from the QDomElement. + */ + PMRuleAfter( QDomElement& e, QPtrList<PMRuleDefineGroup>& globalGroups, + QPtrList<PMRuleDefineGroup>& localGroups ); + /** + * Destructor + */ + virtual ~PMRuleAfter( ); + /** */ + virtual QString type( ) const { return QString( "After" ); } + /** */ + virtual bool evaluate( const PMObject* object ); +protected: + /** */ + virtual void countChildProtected( const QString& className, + bool afterInsertPoint ); + /** */ + virtual void resetProtected( ); +private: + QPtrList<PMRuleCategory> m_categories; + bool m_contains; +}; + +/** + * Condition. Value is true if the object already contains + * objects of certaint classes. + */ +class PMRuleContains : public PMRuleCondition +{ +public: + /** + * Reads the data from the QDomElement. + */ + PMRuleContains( QDomElement& e, QPtrList<PMRuleDefineGroup>& globalGroups, + QPtrList<PMRuleDefineGroup>& localGroups ); + /** + * Destructor + */ + virtual ~PMRuleContains( ); + /** */ + virtual QString type( ) const { return QString( "Contains" ); } + /** */ + virtual bool evaluate( const PMObject* object ); +protected: + /** */ + virtual void countChildProtected( const QString& className, + bool afterInsertPoint ); + /** */ + virtual void resetProtected( ); +private: + QPtrList<PMRuleCategory> m_categories; + bool m_contains; +}; + +/** + * Base class for comparisons + */ +class PMRuleCompare : public PMRuleCondition +{ +public: + /** + * Reads the data from the QDomElement. + */ + PMRuleCompare( QDomElement& e, QPtrList<PMRuleDefineGroup>& globalGroups, + QPtrList<PMRuleDefineGroup>& localGroups ); + /** */ + virtual bool evaluate( const PMObject* object ); +protected: + /** + * Compares the two variants. The variants have the same type. + * + * Reimplement this method in sub classes. + */ + virtual bool compare( const PMVariant& v1, const PMVariant& v2 ) = 0; +private: + PMRuleValue* m_pValue[2]; +}; + +/** + * Less than comparison + */ +class PMRuleLess : public PMRuleCompare +{ +public: + /** + * Reads the data from the QDomElement. + */ + PMRuleLess( QDomElement& e, QPtrList<PMRuleDefineGroup>& globalGroups, + QPtrList<PMRuleDefineGroup>& localGroups ); + /** */ + virtual QString type( ) const { return QString( "Less" ); } +protected: + /** */ + virtual bool compare( const PMVariant& v1, const PMVariant& v2 ); +}; + +/** + * Greater than comparison + */ +class PMRuleGreater : public PMRuleCompare +{ +public: + /** + * Reads the data from the QDomElement. + */ + PMRuleGreater( QDomElement& e, QPtrList<PMRuleDefineGroup>& globalGroups, + QPtrList<PMRuleDefineGroup>& localGroups ); + /** */ + virtual QString type( ) const { return QString( "Greater" ); } +protected: + /** */ + virtual bool compare( const PMVariant& v1, const PMVariant& v2 ); +}; + +/** + * Equal comparison + */ +class PMRuleEqual : public PMRuleCompare +{ +public: + /** + * Reads the data from the QDomElement. + */ + PMRuleEqual( QDomElement& e, QPtrList<PMRuleDefineGroup>& globalGroups, + QPtrList<PMRuleDefineGroup>& localGroups ); + /** */ + virtual QString type( ) const { return QString( "Equal" ); } +protected: + /** */ + virtual bool compare( const PMVariant& v1, const PMVariant& v2 ); +}; + +class PMRule : public PMRuleBase +{ +public: + /** + * Reads the data from the QDomElement. + */ + PMRule( QDomElement& e, QPtrList<PMRuleDefineGroup>& globalGroups, + QPtrList<PMRuleDefineGroup>& localGroups ); + /** + * Destructor + */ + virtual ~PMRule( ); + /** */ + virtual QString type( ) const { return QString( "Rule" ); } + /** + * Returns true if this rule matches for the given class. + */ + bool matches( const QString& className ); + /** + * Returns the conditions value. + */ + bool evaluate( const PMObject* parent ); + +private: + QPtrList<PMRuleCategory> m_categories; + PMRuleCondition* m_pCondition; +}; + +/** + * Class used internally by the insert rule system + * + * Stores all rules for one class. + */ +class PMRuleTargetClass +{ +public: + /** + * Reads the data from the QDomElement. + */ + PMRuleTargetClass( QDomElement& e, + QPtrList<PMRuleDefineGroup>& globalGroups ); + /** + * Destructor + */ + ~PMRuleTargetClass( ); + + /** + * Reads rules and groups from the QDomELement and appends + * them to the local ones. + */ + void appendRules( QDomElement& e, QPtrList<PMRuleDefineGroup>& globalGroups ); + /** + * Returns an iterator to the rules + */ + QPtrListIterator<PMRule> rules( ) const + { + return QPtrListIterator<PMRule>( m_rules ); + } + /** + * Returns the class name + */ + QString name( ) const { return m_class; } + /** + * Returns a list of exceptions for this rule. + */ + QStringList exceptions( ) const { return m_exceptions; } +private: + QPtrList<PMRuleDefineGroup> m_groups; + QPtrList<PMRule> m_rules; + QString m_class; + QStringList m_exceptions; +}; + +/** + * Rule based system that checks which objects can be inserted as child + * into another object. + * + * The rules are defined in the file "pmbaseinsertrules.xml". + * The file "pminsertrules.dtd" is a DTD file that can be used + * to validate rule files. + * + * Plugins can add additional rules to the system. + */ +class PMInsertRuleSystem +{ +public: + /** + * Constructor + */ + PMInsertRuleSystem( PMPart* part ); + /** + * Destructor + */ + ~PMInsertRuleSystem( ); + + /** + * Tells the system to load the rules from a file. + * + * Rules are never loaded twice for the same file. It is save + * to call this method twice for the same file. + */ + void loadRules( const QString& fileName ); + + /** + * Returns true if an object of the given class can be inserted as child + * after the object after. + * + * The parser uses the third parameter for top level objects. These objects + * have to be treated as if they are inserted after the object after. + */ + bool canInsert( const PMObject* parentObject, const QString& className, + const PMObject* after, const PMObjectList* objectsBetween = 0 ); + + /** + * Returns true if the object can be inserted as child + * after the object after. + * + * The parser uses the third parameter for top level objects. These objects + * have to be treated as if they are inserted after the object after. + * + * Same as canInsert( parentObject, object->class( ), after, objectsBetween ) + */ + bool canInsert( const PMObject* parentObject, const PMObject* object, + const PMObject* after, const PMObjectList* objectsBetween = 0 ); + + /** + * Returns the number of objects that can be inserted at that position + */ + int canInsert( const PMObject* parentObject, const PMObjectList& list, + const PMObject* after ); + /** + * Returns the number of objects that can be inserted at that position + */ + int canInsert( const PMObject* parentObject, const QStringList& listOfClasses, + const PMObject* after ); + /** + * Returns a pointer to the part + */ + PMPart* part( ) const { return m_pPart; } + +private: + /** + * List of all rules. + */ + QPtrList<PMRuleTargetClass> m_classRules; + /** + * List of global groups + */ + QPtrList<PMRuleDefineGroup> m_groups; + /** + * Dictionary that maps from the class name + * to a list of rules that match. + */ + QDict<PMRuleTargetClass> m_rulesDict; + /** + * List of already loaded files + */ + QStringList m_loadedFiles; + PMPart* m_pPart; +}; + +#endif |