Logo Search packages:      
Sourcecode: kdewebdev version File versions

kafkacommon.h

/***************************************************************************
                               kafkacommon.h
                             -------------------

    copyright            : (C) 2003, 2004 - Nicolas Deschildre
    email                : ndeschildre@kdewebdev.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 KAFKACOMMON_H
#define KAFKACOMMON_H

#include <qvaluelist.h>
#include <dom/dom_node.h>

namespace DOM
{
      class Document;
}
class Node;
class NodeModifsSet;
class Document;
struct DTDStruct;

/**
 * For heavy debug including Node Tree in stdout printing, a DOM::Node tree widget.
 */
//#define HEAVY_DEBUG

/**
 * Light debugging, including functions name in stdout printing.
 */
//#define LIGHT_DEBUG


/** This class gathers all the basic functions needed by kafka. 
 * It's very useful for manipulating nodes.
 */

00048 class kafkaCommon
{
public:
      kafkaCommon() {}
      ~kafkaCommon() {}

      /** ----------------------- NODE & DOM::NODE TREE NAVIGATION -------------------------------------*/

      /**
       * This function returns the next Node after node : the first child of
       * node if available, else its next sibling if available, else the next
       * available next sibling of a parent of node.
       * @param _node It is the Node from which we want the next Node.
       * @param goUp This boolean specifies if we should go up (torwards the root Node)
       * i.e. not looking at the childs of node, or make a standart iteration.
       * For a normal use, It must be set to false at the
       * beginning and then the same boolean must be used when using
       * several times this function.
       * @param endNode Specifies at which Node the search should end.
       * @return Returns the next Node.
       */
      static Node* getNextNode(Node *node, bool &goUp, Node *endNode = 0L);

      /**
       * It behaves essentially like the above function except that it will skip empty Nodes.
       */
      static Node* getNextNodeNE(Node *node, bool &goUp, Node *endNode = 0L);

      /**
       * This function returns the prev Node after node.
       */
      static Node* getPrevNode(Node *node, Node *endNode = 0L);

      /**
       * It behaves essentially like the above function except that it will skip empty Nodes.
       */
      static Node* getPrevNodeNE(Node *node, Node *endNode = 0L);

      /**
       * This function returns the next DOM::Node after node : the first child of
       * DOM::Node if available, else its next sibling if available, else the next
       * available next sibling of a parent of node.
       * @param node The DOM::Node the search starts from.
       * @param goUp This boolean specifies if we should go up or down in the tree.
       * For a normal use, It must be set to false at the
       * beginning and then the same boolean must be used when using
       * several times this function.
       * @param returnParentNode Specifies if there are no child and next sibling, if
       * we should return the parent.
       * @param endNode Specifies at which DOM::Node the search should end. It is useful
       * when setting returnParentNode to false.
       * @return the next Node.
       */
      static DOM::Node getNextDomNode(DOM::Node node, bool &goUp, bool returnParentNode = false,
            DOM::Node endNode = DOM::Node());

      /**
       * This function returns the previous Node after node.
       * @return Returns the previous DOM::Node of node.
       */
      static DOM::Node getPrevDomNode(DOM::Node node, DOM::Node endNode = DOM::Node());


      /** ----------------------- NODE INDENTATION STUFF -------------------------------------*/

      /**
       * This function takes care to modify the current node or/and the next sibling in order to have a nice
       * indentation. WARNING it doesn't create the necessary Nodes. Call fitIndentationNodes first.
       * @param node Apply nice indentation to this Node.
       * @param nbOfSpaces Specifies the number of spaces the minimal indentation must be.
       * @param nbOfTabs Specifies the number of tabs the minimal indentation must be.
       */
      static void applyIndentation(Node *node, int nbOfSpaces, int nbOfTabs);

      /**
       * Create/Delete the necessary Empty Nodes between n1 and n2 so that a nice indentation can be
       * generated by the undoRedo system. The undoRedo system can't create itself these Nodes
       * because it will create them only during the synchronization, making all the QValueList<int>
       * Nodes location wrong.
       * WARNING n1 and n2 must be siblings or parent-child. If there are sibling and n1 is a XmlTag,
       * n1 should not have non empty childs.
       * @param n1 The start node.
       * @param n2 The end node.
       */
      static void fitIndentationNodes(Node *n1, Node *n2);

      /**
       * Fits the Nodes positions after a change in the Node tree.
       * @param startNode The Node where the update of the Node positions starts.
       * @param colMovement The number of columns that should be
       * added/retrieved from the column position. It is the difference of the new last char col position and the
       * old last char col position.
       * @param lineMovement The number of lines that should be
       * added/retrieved from the line position. It is the difference of the number of lines of the new tag string
       * and the number of lines of the old tag string.
       * @param colEnd The column position where the update should stop.
       * @param lineEnd The line position where the update should stop.
       */
      static void fitsNodesPosition(Node* startNode, int colMovement, int lineMovement = 0,
            int colEnd = -2, int lineEnd = -2);

      /**
       * Get the display type of a Node. NOT an official list, more a little hack to
       * handle the indentation. Text are inline. The rest return an error.
       * @param closingNodeToo Specifies if we consider that closing Node have the same type as
       * their opening tag.
       * @return Returns the type.
       */
      static int getNodeDisplay(Node *node, bool closingNodeToo);

      //the enumeration of the different display types
      enum nodeDisplay
      {
            noneDisplay = 0,
            inlineDisplay,
            blockDisplay,
            errorDisplay
      };

      /**
       * Remove the indentation whitespaces in a string
       * e.g. this function returns : " a b  cd " for parameter: "     a b  cd     "
       * @param string The text to modify.
       * @param removeAllSpacesAtTheLeft Specifies if it should remove ALL spaces in the left
       * unlike the above example.
       * @param removeAllSpacesAtTheRight Specifies if it should remove ALL spaces in the right
       * unlike the above example.
       * @return Returns the modified string.
       */
      static QString removeUnnecessaryWhitespaces(const QString &string,
            bool removeAllSpacesAtTheLeft = false, bool removeAllSpacesAtTheRight = false);


      /** ----------------------- NODE TREE MODIFICATIONS -------------------------------------*/

      /**
       * Create a simple Node, without taking care of building the closing Node.
       * @param nodeName The name of the Node.
       * @param tagString The String of the tag as it will appears in the editor.
       * @param nodeType The node type, cf Tag::TokenType
       * @param doc The document the Node will belong to.
       * @return Returns the newly created node.
       */
      static Node* createNode(const QString &nodeName, const QString &tagString, int nodeType,
            Document *doc);

      /**
       * Create a !doctype Node with all the necessary attributes. It has a child and a closing Node.
       * @param doc It needs the document where the !doctype node will be inserted in order to
       * build the right attributes.
       */
      static Node *createDoctypeNode(Document *doc);

      /**
       * Create a <?xml ... ?> Node. It has a child and a closing Node.
       * @param doc It needs the document where the xml node will be inserted.
       * @param encoding The encoding to use (usually get it with quantaApp->defaultEncoding())
       */
      static Node *createXmlDeclarationNode(Document *doc, const QString &encoding);

      /**
       * Create a node subtree which contains the mandatory Nodes in order to be DTD compliant.
       * e.g. TABLE alone isn't DTD compliant, this function will return TABLE->TR->TD.
       * WARNING : it won't log change thus node must NOT be in the Node tree.
       * @param node The root Node of the Node subtree.
       * @param doc The document the Node subtree will belong to.
       * @return Returns the last Node of the subtree or node if there was nothing to add.
       */
      static Node* createMandatoryNodeSubtree(Node *node, Document *doc);

      /**
       * Insert node in the tree. WARNING This function will log that node was added.
       * WARNING : baseNode is used as the rootNode.
       * It will also try to merge text/Empty Nodes.
       * @param node The node to insert.
       * @param parentNode This Node will be the parent of node.
       * @param nextSibling This Node will be the next Sibling of Node. If null, node will be appended at
       * the child list of parentNode.
       * TODO: @param rootNode The rootNode of the tree we want to insert the Node (usually &baseNode).
       * @param modifs The changes made are logged into modifs. Put 0L if you don't want to log
       * and if you know what you're doing!
       * @param merge Try to merge with the siblings if possible.
       * @return Returns a pointer to the node inserted.
       */
      static Node* insertNode(Node *node, Node* parentNode, Node* nextSibling,
            NodeModifsSet *modifs/**, Node **rootNode*/, bool merge = true);

      /**
       * It behaves essentially like the above function except that it can "surround" a set of Nodes with the
       * new Node. Thus, the closing Node is created if necessary.
       * nextSibling and nextEndSibling MUST have the same parent. If not, use the
       * DTDinsertNode.
       * This function does not try to know if the location of the new Node is DTD valid.
       * @param newNode The new Node to insert.
       * @param parent The parent of the Node.
       * @param nextSibling The next sibling of the Node.
       * @param nextEndSibling The next sibling of the closing Node if created. If nextEndSibling ==
       * nextSibling, the closing Node will be placed at the right of the newly created Node.
       * All the Nodes between the new Node and its closing Tag will be moved as childs of the new Node.
       * @param modifs The changes made are logged into modifs.
       * @return Returns a pointer to the node inserted.
       */
      static Node *insertNode(Node *newNode, Node *parent, Node *nextSibling, Node *nextEndSibling,
            NodeModifsSet *modifs, bool merge = true);

      /**
       * It behaves essentially like the above function except that it can split the endNodeToSurround and
       * startNodeToSurround if necessary, according to the offsets.
       * startNodeToSurround et endNodeToSurround MUST have the same parent. If not, use the last
       * DTDinsertNode.
       * This function does not try to know if the location of the new Node is valid.
       * @param startNodeToSurround The first Node which will be enclosed by the new Node.
       * @param endNodeToSurround The last Node which will be enclosed by the new Node.
       * @param startOffset The first Node will be splitted at offset startOffset, the right part will be enclosed.
       * @param endOffset The last Node will be splitted at offset endOffset, the left part will be enclosed.
       */
      static Node* insertNode(Node *newNode, Node *parent, Node *startNodeToSurround,
            Node *endNodeToSurround, int startOffset, int endOffset, NodeModifsSet *modifs);

      /**
       * It behaves essentially like the above function except that it will insert the new Node only
       * if the DTD allows it. The new Tag can surround any subtree. If
       * necessary, several copies of the Node will be used.
       * This function takes care of the DTD validity of the Nodes created.
       * It will build the necessary mandatory Nodes (e.g. insertion of TABLE will also insert TR and TD).
       * This is the key function making the toolbars working.
       * @param startNode The first Node which must be surrounded by the new Node.
       * @param startOffset If firstNode is a text, specify at which offset the new Node must begin to surround.
       * @param endNode The last Node which must be surrounded by the new Node.
       * @param endOffset If endNode is a text, specify at which offset the new Node must stop to surround.
       * @param doc The document is needed in order to build the mandatory Node tree if necessary.
       * <TEMPORARY> : We want to keep track of the cursor position. TODO : cursor class
       * @param cursorNode The cursor is inside cursorNode.
       * @param cursorOffset The offset of the cursor inside cursorNode.
       * </TEMPORARY>
       * @return Returns false if it wasn't possible to insert the tag because e.g. of an invalid parent.
       */
      static bool DTDinsertNode(Node *newNode, Node *startNode, int startOffset, Node *endNode,
            int endOffset, Document *doc, Node **cursorNode, int &cursorOffset, NodeModifsSet *modifs);

      /**
       * It behaves essentially like the above function except that it will try first to remove newNode
       * from the area, by calling DTDExtractNode. If newNode wasn't present, it will then insert it by
       * calling DTDinsertNode.
       * This is the key function making the toolbars working.
         * @return Returns true if a modification was done (Node inserted/removed)
       */
      static bool DTDinsertRemoveNode(Node *newNode, Node *startNode, int startOffset, Node *endNode,
            int endOffset, Document *doc, Node **cursorNode, int &cursorOffset, NodeModifsSet *modifs);

      /**
       * Insert a node subtree in the tree. WARNING This function will log that the nodes were added.
       * WARNING : baseNode is used as the rootNode.
       * It will also try to merge text/Empty Nodes.
       * @param node The root node of the Node subtree to insert.
       * @param parentNode This Node will be the parent of node.
       * @param nextSibling This Node will be the next Sibling of Node. If null, node will be appended at
       * the child list of parentNode.
       * @param modifs The changes made are logged into modifs. Put 0L if you don't want to log
       * and if you know what you're doing!
       * @param merge Try to merge with the siblings if possible.
       * @return Returns a pointer to the node inserted.
       */
      static Node* insertNodeSubtree(Node *node, Node* parentNode, Node* nextSibling,
            NodeModifsSet *modifs, bool merge = true);

      /**
       * It behaves essentially like the above function except that it can "surround" a set of Nodes with the
       * new Node. Thus, the closing Node is created if necessary.
       * nextSibling and nextEndSibling MUST have the same parent. If not, use the
       * DTDinsertNode.
       * The Node Subtree MUST be a single-Node-per-parent subtree.
       * This function does not try to know if the location of the new Node is DTD valid.
       * @param node The root node of the Node subtree to insert.
       * @param parent The parent of the Node.
       * @param nextSibling The next sibling of the Node.
       * @param nextEndSibling The next sibling of the closing Node if created. If nextEndSibling ==
       * nextSibling, the closing Node will be placed at the right of the newly created Node.
       * All the Nodes between the new Node and its closing Tag will be moved as childs of the
       * last Node of the Node subtree..
       * @param modifs The changes made are logged into modifs.
       * @return Returns a pointer to the node inserted.
       */
      static Node* insertNodeSubtree(Node *node, Node* parentNode, Node* nextSibling,
            Node* nextEndSibling, NodeModifsSet *modifs, bool merge = true);

      /**
       * Create a Node of name nodeName, of type nodeType, (see tag.h) connected to the document doc,
       * and nextSibling as Node's next sibling.
       * This function does not try to know if the location of the new Node is valid.
       * @param nodeName The node's name of the node to create.
       * @param tagString The string of the tag.
       * @param nodeType The type of the Node cf Tag::TokenType.
       * @param doc The Node belongs to this Document.
       * @param parent The parent of the Node.
       * @param nextSibling The next sibling of the Node.
       * @return Returns a pointer to the newly created Node.
       */
      static Node *createAndInsertNode(const QString &nodeName, const QString &tagString, int nodeType,
            Document *doc, Node* parent, Node* nextSibling, NodeModifsSet *modifs, bool merge = true);

      /**
       * It behaves essentially like the above function except that it reate its closing Node if necessary
       *  and then insert them with parent as Node's parent.
       * nextSibling and nextEndSibling MUST have the same parent. If not, use the
       * DTDcreateAndInsertNode.
       * @param nextEndSibling The next sibling of the closing Node if created. If nextEndSibling ==
       * nextSibling, the closing Node will be placed at the right of the newly created Node.
       * All the Nodes between the new Node and its closing Tag will be moved as childs of the new Node.
       * @param modifs The changes made are logged into modifs.
       */
      static Node *createAndInsertNode(const QString &nodeName, const QString &tagString, int nodeType,
            Document *doc, Node *parent, Node *nextSibling, Node *nextEndSibling, NodeModifsSet *modifs);

      /**
       * It behaves essentially like the above function except that if necessary, it will split the Nodes.
       * startNodeToSurround et endNodeToSurround MUST have the same parent. If not, use the
       * DTDcreateAndInsertNode.
       * This function does not try to know if the location of the new Node is valid.
       * @param startNodeToSurround The first Node which will be enclosed by the new Node.
       * @param endNodeToSurround The last Node which will be enclosed by the new Node.
       * @param startOffset The first Node will be splitted at offset startOffset, the right part will be enclosed.
       * @param endOffset The last Node will be splitted at offset endOffset, the left part will be enclosed.
       */
      static Node *createAndInsertNode(const QString &nodeName, const QString &tagString,
            int nodeType, Document *doc, Node *parent, Node *startNodeToSurround,
            Node *endNodeToSurround, int startOffset, int endOffset, NodeModifsSet *modifs);

      /**
       * It behaves essentially like the above function except that it will insert the new Node only
       * if the DTD allows it. The new Tag can surround any subtree. If
       * necessary, several copies of the Node will be used.
       * This function takes care of the DTD validity of the Nodes created.
       * It will build the necessary mandatory Nodes (e.g. insertion of TABLE will also insert TR and TD).
       * This is the key function making the toolbars working.
       * @param startNode The first Node which must be surrounded by the new Node.
       * @param startOffset If firstNode is a text, specify at which offset the new Node must begin to surround.
       * @param endNode The last Node which must be surrounded by the new Node.
       * @param endOffset If endNode is a text, specify at which offset the new Node must stop to surround.
       * @return Returns false if it wasn't possible to insert the tag because e.g. of an invalid parent.
       */
      static bool DTDcreateAndInsertNode(const QString &nodeName, const QString &tagString, int nodeType,
            Document *doc, Node *startNode, int startOffset, Node *endNode, int endOffset,
            Node **cursorNode, int &cursorOffset, NodeModifsSet *modifs);

      /**
       * For internal use. From startNode to endNode, it add where possible/necessary a new Node in order
       * to surround the maximum of Nodes. This is used by the above function. This function calls itself.
       * @param newNode The root Node of the node subtree to insert.
       * @param leafNode The leaf Node of the node subtree to insert.
       * @param startExaminationNode It will start examine Nodes from startExaminationNode.
       * @param endExaminationNode It will stop examine Nodes from endExaminationNode.
       * @param startNode This function will start adding newNode from startNode.
       * @param endNode This function will stop adding newNode at endNode.
       * @param currentNode This node is currently examined.
       * @param examinationStarted Specifies if we have begun to examine the Nodes.
       * @param addingStarted Specifies if we have begun to add the new Node.
         * @param nodeInserted Returns true if newNode was inserted at least once. Set to false before calling the function.
       * @level The relative level of the current Node Sibling (level 0 : root Node, level 1 : childs, and so on...)
       * MUST BE set to 0.
       */
      static bool addNodeRecursively(Node *newNode, Node *leafNode, Node *startExaminationNode,
            Node *endExaminationNode, Node* startNode, Node *endNode, Node* currentNode,
            bool &examinationStarted, bool &addingStarted, bool &nodeInserted, int level, NodeModifsSet *modifs);

      /**
       * Create a copy of Node. It use the Node copy operator and add some kafka-specific flags :
       * It set the cleanStrBuilt to false;
       * @param node The node to duplicate.
       * @return Returns the duplicated Node. I wonder if i should always write so obvious things ;-)
       */
      static Node *duplicateNode(Node *node);

      /**
       * It behaves essentially like the above function except that it can handle a node Subtree.
       * INNEFICIENT for bi
       */
      static Node *duplicateNodeSubtree(Node *node);

      /**
       * Extract a Node from the Node Tree. WARNING this will log that the Node was removed.
       * This mean that the undo/redo system will delete it when necessary so don't reuse it!!!!
       * @param node The node to delete.
       * @param modifs The changes made are logged into modifs.
       * @param deleteChilds If we remove or move up the children. WARNING: it don't check
       * if the children of node are legal childs of the parent of node.
       * @param removeClosingTag Delete the closingTag if node isn't single and is Tag::XmlTag.
       * TODO: @param removeEmbeddedTags Specifies if we delete the embedded Nodes e.g.
       * <a href="<? boo ?>" > : the PHP block is an embedded block.
       * @return Returns the node extracted with its childs
       */
      static Node* extractNode(Node *node, NodeModifsSet *modifs, bool removeChildren = true,
            bool removeClosingTag = false/**, bool removeEmbeddedTags = false*/);

      /**
       * It behaves essentially the above function.
       * Extract and BUT NOT DELETE RIGHT NOW node from the Tree. The undo/redo system will delete it
       * when necessary.
       * TODO: remove it, and use extractNode instead.
       * @param deleteClosingTag Delete the closingTag if node isn't single.
       */
      static void extractAndDeleteNode(Node *node, NodeModifsSet *modifs, bool deleteChildren = true,
            bool deleteClosingTag = true, bool mergeAndFormat = true);

      /**
       * An enumeration of all the possible return states of DTDExtractNode
       */
00455       enum extractNodeStatus
      {
            //The node to extract was not found.
            nothingExtracted = 0,
            //The extract operation stopped because of a DTD error : if the node was removed, the child
            //weren't able to be childs of the node's parent, according to the DTD. Should not occur
            //except really bad HTML.
            extractionStoppedDueToBadNodes,
            //everything has gone fine
            extractionDone,
            //Invalid start or end position, or the given Node was a block.
            extractionBadParameters
      };

      /**
       * This function will try to extract the node nodeName (of type XmlTag) from a given subtree,
       * according to the DTD. If the DTD don't allow it, it won't remove it.
       * This function is only interesting for the removal of Inline Nodes thus it will return an error if
       * a block nodeName is submitted.
       * TODO: AVOID splitting of Node when the DTD don't allow the removal.
       * @param nodeName The name of the Node to remove (must be inline).
       * @param doc It is needed to get the DTD informations.
       * @param startNode The node from which we start the removal.
       * @param startOffset The offset of startNode from which we start the removal.
       * @param endNode The node from which we end the removal.
       * @param endOffset The offset of endNode from which we end the removal.
       * <TEMPORARY> : We want to keep track of the cursor position. TODO : cursor class
       * @param cursorNode The cursor is inside cursorNode.
       * @param cursorOffset The offset of the cursor inside cursorNode.
       * </TEMPORARY>
       * @param modifs The usual modifs to log the modifications made for the undo/redo system.
       * @return Returns a kafkaCommon::extractNodeStatus.
       */
      static int DTDExtractNode(const QString &nodeName, Document *doc, Node *startNode,
            int startOffset, Node *endNode, int endOffset, Node **cursorNode, int &cursorOffset,
            NodeModifsSet *modifs);

      /**
       * Moves a Node somewhere else.
       * @param nodeToMove The node to move :-)
       * @param newParent The new parent of nodeToMove.
       * @param newNextSibling The new next Sibling of nodeToMove.
       * @param modifs The changes made are logged into modifs.
       * @param merge Specifies if it should try to merge the Node at its new location.
       */
      static void moveNode(Node *nodeToMove, Node *newParent, Node *newNextSibling,
            NodeModifsSet *modifs, bool merge = true);

      /**
       * Split a Text Node at offset offset. If offset or n is invalid, nothing is done.
       * @param n The Node to split.
       * @param offset Where to split the node.
       * @param modifs The change made are logged into modifs.
       * @return Returns if the node was splitted.
       */
      static bool splitNode(Node *n, int offset, NodeModifsSet *modifs);

      /**
       * If n and n2 are both Text or Empty Nodes, merge them into one.
       * WARNING if merging occurs, n2 is deleted.
       * @param modifs The changes made are logged into modifs
       * @param mergeTextOnly Specify if we should only merge text Nodes, not empty ones.
       * @return Returns true if the Nodes were merged, else false.
       */
      static bool mergeNodes(Node *n, Node *n2, NodeModifsSet *modifs, bool mergeTextOnly = false);

      /**
       * This function will navigate through the Nodes from startNode to endNode and
       * merge identical inline Nodes as well as text Nodes.
       * @param startNode The node from which the merge starts.
       * @param endNode The node from which the merge ends.
       * @param modifs The usual modifs, to log the changes.
       * <TEMPORARY> : We want to keep track of the cursor position. TODO : cursor class
       * @param cursorNode The cursor is inside cursorNode.
       * @param cursorOffset The offset of the cursor inside cursorNode.
       * </TEMPORARY>
       */
      static void mergeInlineNode(Node *startNode, Node *endNode, Node **cursorNode,
            int &cursorOffset, NodeModifsSet *modifs);


      /** ----------------------- NODE MODIFICATIONS -------------------------------------*/

      /**
       * Computes the end position of a string starting at pos (bLine, bCol).
       * @param tagString The tagString, representing usually a tag string ;-)
       * @param bLine The line of the first letter of tagString.
       * @param bCol The column of the first letter of tagString.
       * @param eLine Returns the line of the last letter of tagString.
       * @param eCol Returns the col of the last letter of tagString.
       */
      static void getEndPosition(const QString & tagString, int bLine, int bCol, int &eLine, int &eCol);

      /**
       * It behaves essentially like the above function except that the string is the Tag String of Node.
       * @param node The tag string is taken from node.
       */
      static void getEndPosition(Node *node, int bLine, int bCol, int &eLine, int &eCol);

      /**
       * Set the tag string of node, and update the start/end position of the Node.
       * @param node The node which get the new tag string.
       * @param newTagString The new tag String :-)
       */
      static void setTagString(Node *node, const QString &newTagString);

      /**
       * This function behaves essentially like the above function except that all the others Nodes' position
       * are updated too.
       */
      static void setTagStringAndFitsNodes(Node *node, const QString &newTagString);

      /**
       * Gets the location of a Node in a pointer-independant suit of ints e.g. 1,3,5 means
       * that the node is the fifth child of the third child of the root Node. Efficient when
       * deleting the Node tree and rebuilding it when switching between Documents.
       * @param node The Node we want the location.
       * @return Returns the location.
       */
      static QValueList<int> getLocation(Node* node);

      /**
       * It behaves essentially like the above function except that it operate on DOM::Nodes.
       */
      static QValueList<int> getLocation(DOM::Node domNode);

      /**
       * Get the node corresponding to a location. See the above function.
       * @param loc We want the Node from this location.
       * @return Returns the Node at location loc.
       */
      static Node* getNodeFromLocation(QValueList<int> loc);

      /**
       * It behaves essentially like the above function except that it operate on DOM::Nodes.
       * @rootNode It needs the root Node of the DOM::Node Tree i.e. the document() Node.
       */
      static DOM::Node getNodeFromLocation(QValueList<int> loc, DOM::Node rootNode);

      /**
       * Get the node corresponding to a sublocation.
       * @param loc A location of a Node.
       * @locOffset We want the (totalNumberOfParent - locOffset)th parent of Node.
       * @return Returns a parent of the node pointed by loc.
       */
      static Node* getNodeFromSubLocation(QValueList<int> loc, int locOffset);

      /**
       * A enumeration for kafkaCommon::compareNodePosition().
       */
00605       enum position
      {
            //It means that it is a previous sibling (not the dom/dom_node.h definition, but rather
            // the node.h definition)
            isBefore = 0,
            //It is the same Node.
            isAtTheSamePosition,
            //It means that it is a next sibling (in the node.h way).
            isAfter,
            //guess what?
            positionError
      };

      /**
       * Compare the position of two Nodes.
       * e.g. (pos1)->next = (pos2); compareNodePosition(n1, n2) == kafkaCommon::before.
       * @param pos1 The location of the Node to compare.
       * @param pos2 The location of the Node to be compared to.
       * @return Return a kafkaCommon::position flag.
       */
      static int compareNodePosition(QValueList<int> pos1, QValueList<int> pos2);

      /**
       * It behave essentially like the above function except that it is based on Nodes.
       */
      static int compareNodePosition(Node *n1, Node *n2);

      /**
       * Compare n1 and n2's node type, node name, and node attributes.
       * @return Returns true if there are indentical.
       */
      static bool compareNodes(Node *n1, Node *n2);

      /**
       * Get the node's depth in the tree.
       * @param node The node we want the depth.
       * @return Returns the depth of node. It is basically the number of parents of node.
       * It will return 0 if node has no parent Nodes, and -1 if node doesn't exists.
       */
      static int nodeDepth(Node *node);

      /**
       * Looks if node has a parent which is named name.
       * @return Returns the first parent which is named name or 0L if not found.
       */
      static Node* hasParent(Node *node, const QString &name);


      /** ----------------- DOM::NODE TREE MODIFICATIONS --------------------*/

      /**
       * Insert a DOM::Node in the DOM::Node tree. It takes care to handle the exceptions.
       * WARNING : The postEnhancement is not done (cf htmlenhancer.h)
       * Prefer using KafkaDocument::insertDomNode()
       * @param node The node to insert.
       * @param parent The new parent of node. If null, insert node at the top level.
       * @param nextSibling The new next sibling of node. If null, append node at the end of the child list.
       * @param rootNode The root DOM::Node of the DOM::Node tree. Useful when no parent is provided.
       * @return Returns true if the operation was successfull.
       */
      static bool insertDomNode(DOM::Node node, DOM::Node parent = DOM::Node(),
            DOM::Node nextSibling = DOM::Node(), DOM::Node rootNode = DOM::Node());


      /**
       * Removes a DOM::Node from the DOM::Node Tree. It takes care to handle the exceptions.
       * WARNING : The postUnenhancement is not done (cf htmlenhancer.h)
       * Prefer using KafkaDocument::removeDomNode()
       * @param node The Node to remove from the tree.
       * @retun Returns true if the operation was successfull..
       */
      static bool removeDomNode(DOM::Node node);


      /** --------------------- DOM::NODE MODIFICATIONS ---------------------- */

      /**
       * Create a new DOM::Node. It takes care to check if nodeName is valid.
       * @param nodeName The DOM::Node's name.
       * @param dtd The currently used dtd.
       * @param rootNode The rootNode is needed in order to create a new DOM::Node.
       * @return Returns the DOM::Node created or a null DOM::Node if nodeName is invalid.
       */
      static DOM::Node createDomNode(const QString &nodeName, const DTDStruct* dtd, DOM::Document rootNode);

      /**
       * It behaves essentially like the above function.
       * @param node The DOM::Node will be created with node's name.
       */
      static DOM::Node createDomNode(Node *node, DOM::Document rootNode);

      /**
       * Create a new Text Node.
       * @param textString The text inside the new text DOM::Node.
       * @param rootNode The rootNode is needed in order to create a new Text DOM::Node.
       * @return a new text DOM::Node.
       */
      static DOM::Node createTextDomNode(const QString &textString, DOM::Document rootNode);

      /**
       * Create a new attribute and check if the attrName can have this attribute.
       * @param nodeName The node name of the DOM::Node which will get this attribute.
       * @param dtd The currently used dtd.
       * @param attrName The name of the new attribute.
       * @param attrValue The value of the new attribute.
       * @param rootNode The rootNode is needed in order to create a new Attribute.
       * @return Returns the new Attribute or a null DOM::Node if attrName is invalid.
       */
      static DOM::Node createDomNodeAttribute(const QString &nodeName, const DTDStruct* dtd,
            const QString &attrName, const QString &attrValue, DOM::Document rootNode);

      /**
       * It behaves essentially like the above function.
       * @param node The corresponding DOM::Node of node will get the attribute. It don't add the attribute.
       */
      static DOM::Node createDomNodeAttribute(Node* node, const QString &attrName, DOM::Document rootNode);

      /**
       * It behaves essentially like the above function except that it use the DOM::Node->Node* link to get the
       * corresponding Node. So be sure that the link is set.
       * @param node The node which will get the attribute. It don't add the attribute.
       */
      //static DOM::node createDomNodeAttribute(DOM::Node node, const QString &attrName,
      //    DOM::Document rootNode);

      /**
       * Append a new attribute to a DOM::Node.
       * @param node The node which will get the new attribute.
       * @param attr The new attribute to add.
       * @return Returns if the operation was successfull.
       */
      static bool insertDomNodeAttribute(DOM::Node node, DOM::Node attr);

      /**
       * It behaves essentially like the above function except that if the attribute doesn't exist, it will create it,
       * and then it fills the attribute with attrValue.
       * @param nodeName The name of the Node corresponding to node.
       * @param dtd The currently used DTD.
       * @param attrName The name of the (new) Attribute.
       * @param attrValue The value of the new Attribute.
       * @param rootNode The rootNode is needed in order to create a new Attribute.
       * @return Returns if the operation was successfull.
       */
      static bool editDomNodeAttribute(DOM::Node node, const QString &nodeName, const DTDStruct* dtd,
            const QString &attrName, const QString &attrValue, DOM::Document rootNode);

      /**
       * It behaves essentially like the above function.
       * @param node The DOM::Node comes from this node.
       */
      static bool editDomNodeAttribute(DOM::Node domNode, Node* node,
            const QString &attrName, const QString &attrValue, DOM::Document rootNode);
      
    /**
       * Looks if domNode has a parent which is named name.
       * @return Returns the first parent which is named name or an empty DOM::Node if not found.
       */
      static DOM::Node hasParent(DOM::Node domNode, const QString &name);

      /**
       * Returns the position of the child domNode.
       * @param domNode This is the DOM::Node we want the position.
       * @return Returns the position of domNode inside domNode's parent's children or -1 if not found.
       */
      static int childPosition(DOM::Node domNode);

      /**
       * Returns the position'th child of parentNode.
       * @param parentNode The parent Node of the node to return.
       * @param position We return the position'th child Node.
       * @param fallback If set to true, it will always return a valid Node (except if there is no child!!)
       */
      static DOM::Node getChildNode(DOM::Node parentNode, int position, bool fallback = false);

      /**
       * Specify if a DOM::Node is inline (as specified in isInline()) or text.
       * @return true if it is an inline Node.
       */
      static bool isInline(DOM::Node domNode);

      /**
       * Specify if parent supports the siblings DOM::Nodes starting from startNode to endNode
       * according to the DTD dtd.
       */
      static bool parentSupports(DOM::Node parent, DOM::Node startNode, DOM::Node endNode,
            const DTDStruct* dtd);
    

      /** ----------------------- MISCELLANEOUS -------------------------------------*/

      /**
       * TEMPORARY, HTML specific
       * @return Returns true if it is a inline Node. Official DTD List, unlike getNodeDisplay().
       */
       static bool isInline(const QString &nodename);

      /**
       * Prints in stdout the current DOM::Node tree.
       * @param rootNode The root Node of the DOM::Node Tree (usually document())
       * @param indent The indentation.
       */
      static void coutDomTree(DOM::Node rootNode, int indent);

      /**
       * Prints in stdout the current Node tree.
       * @param node The startNode
       * @param indent The number of little dots per parent relationship.
       */
      static void coutTree(Node *node, int indent);


};

#endif

Generated by  Doxygen 1.6.0   Back to index