/*************************************************************************** qdom_add.cpp - description ------------------- begin : Wed Nov 21 2001 copyright : (C) 2001, 2002, 2003 by The KXMLEditor Team email : lvanek@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 file contains useful datatypes and functions in addition to the TQt DOM classes. */ #include "qdom_add.h" #include #include #include #include "kxmleditorfactory.h" #include "kxesearchdialog.h" TQPixmap g_iconElement( UserIcon("xml_element",KXMLEditorFactory::instance()) ); TQPixmap g_iconText( UserIcon("xml_text",KXMLEditorFactory::instance()) ); TQPixmap g_iconComment( UserIcon("xml_comment",KXMLEditorFactory::instance()) ); TQPixmap g_iconCDATASection( UserIcon("xml_cdata",KXMLEditorFactory::instance()) ); TQPixmap g_iconProcessingInstruction( UserIcon("xml_procinstr",KXMLEditorFactory::instance()) ); TQPixmap g_iconElement_b( UserIcon("xml_element_b",KXMLEditorFactory::instance()) ); TQPixmap g_iconText_b( UserIcon("xml_text_b",KXMLEditorFactory::instance()) ); TQPixmap g_iconComment_b( UserIcon("xml_comment_b",KXMLEditorFactory::instance()) ); TQPixmap g_iconCDATASection_b( UserIcon("xml_cdata_b",KXMLEditorFactory::instance()) ); TQPixmap g_iconProcessingInstruction_b( UserIcon("xml_procinstr_b",KXMLEditorFactory::instance()) ); TQPixmap g_iconUnknown; const TQPixmap & domTool_getIconForNodeType( TQDomNode::NodeType type, bool bBookmarked ) { if(!bBookmarked) { switch(type) { case TQDomNode::ElementNode: return g_iconElement; break; case TQDomNode::TextNode: return g_iconText; break; case TQDomNode::CDATASectionNode: return g_iconCDATASection; break; case TQDomNode::CommentNode: return g_iconComment; break; case TQDomNode::ProcessingInstructionNode: return g_iconProcessingInstruction; break; default: kdDebug() << "domTool_getIconForNodeType: unknown node type (" << type << ")" << endl; } } else { switch(type) { case TQDomNode::ElementNode: return g_iconElement_b; break; case TQDomNode::TextNode: return g_iconText_b; break; case TQDomNode::CDATASectionNode: return g_iconCDATASection_b; break; case TQDomNode::CommentNode: return g_iconComment_b; break; case TQDomNode::ProcessingInstructionNode: return g_iconProcessingInstruction_b; break; default: kdDebug() << "domTool_getIconForNodeType: unknown node type (" << type << ")" << endl; } } return g_iconUnknown; } // Obtain XPath for all nodes, instead of elements TQString domTool_getPath( const TQDomNode & node ) { if ( node.isNull() ) { kdDebug() << "domTool_getPath: elelent given" << endl; return TQString(); } if(node.isElement()) { kdDebug() << "use domTool_getPath( const TQDomElement & domElement ) for elements" << endl; } TQString strReturn; TQDomNode parentNode = node.parentNode(); if ( (!parentNode.isNull()) && (!parentNode.isDocument()) ) { strReturn = domTool_getPath( parentNode.toElement() ); // get the parent's path strReturn += "/"; // append slash strReturn += node.nodeName(); // append the given node's name } else strReturn = node.nodeName(); // set the given node's name (must be root element) return strReturn; } // Obtain XPath for elements TQString domTool_getPath( const TQDomElement & domElement ) { if ( domElement.isNull() ) { kdDebug() << "domTool_getPath: no node given" << endl; return TQString(); } TQString strReturn; TQDomNode parentNode = domElement.parentNode(); if ( (!parentNode.isNull()) && (!parentNode.isDocument()) ) { // calculate index - only for elements with the same name int i = 0; bool bUseIndex = false; // index is used only when exist sibling(s) with the same name // traverse previous sibling elements with same name and calculate index TQDomNode tmpNode = domElement.previousSibling(); while ( ! tmpNode.isNull() ) { if(tmpNode.isElement()) { TQDomElement domSiblingElement = tmpNode.toElement(); if(domElement.tagName() == domSiblingElement.tagName()) { i++; bUseIndex = true; } } tmpNode = tmpNode.previousSibling(); } if(bUseIndex == false) { // traverse next sibling elements with same name // and decide, if index is necessary TQDomNode tmpNode = domElement.nextSibling(); while ( ! tmpNode.isNull() ) { if(tmpNode.isElement()) { TQDomElement domSiblingElement = tmpNode.toElement(); if(domElement.tagName() == domSiblingElement.tagName()) bUseIndex = true; } tmpNode = tmpNode.nextSibling(); } } strReturn = domTool_getPath( parentNode.toElement() ); // get the parent's path strReturn += "/"; // append slash strReturn += domElement.nodeName(); // append the given node's name if(bUseIndex) { TQString strIndex; strIndex.setNum(i+1); strReturn += "[" + strIndex + "]"; // append the index } } else strReturn = domElement.nodeName(); // set the given node's name (must be root element) return strReturn; } unsigned int domTool_getLevel( const TQDomNode & node ) { if ( node.isNull() ) { kdDebug() << "domTool_getLevel: internal implementation error - the given node is an empty one" << endl; return 0; } unsigned int iLevel = 0; TQDomNode parentNode = node.parentNode(); while ( ! parentNode.isNull() ) { iLevel++; parentNode = parentNode.parentNode(); } return iLevel - 1; } TQString domTool_save( const TQDomNode & node, int iIndent ) { TQString strXML; TQTextStream ts( & strXML, IO_WriteOnly ); node.save(ts, iIndent); return strXML; } TQDomNode domTool_prevNode( const TQDomNode & node ) { if ( node.isNull() ) { kdDebug() << "domTool_prevNode: internal implementation error - the given node is an empty one" << endl; return TQDomNode(); } if ( ! node.previousSibling().isNull() ) // if there is a prev. sibling { // return its last grand child (if there is any) TQDomNode prevNode = node.previousSibling(); while ( ! prevNode.lastChild().isNull() ) prevNode = prevNode.lastChild(); return prevNode; } else // if there is no prev. sibling, return return node.parentNode(); // the nodes parent (if there is any) } TQDomNode domTool_nextNode( const TQDomNode & node ) { if ( node.isNull() ) { kdDebug() << "domTool_nextNode: internal implementation error - the given node is an empty one" << endl; return TQDomNode(); } // checking for a child if ( ! node.firstChild().isNull() ) return node.firstChild(); // there is no child -> checking for the next sibling if ( ! node.nextSibling().isNull() ) return node.nextSibling(); // there is no next sibling -> checking for parents' next sibling(s) TQDomNode nodeParent = node.parentNode(); while ( ! nodeParent.isNull() ) { if ( ! nodeParent.nextSibling().isNull() ) return nodeParent.nextSibling(); nodeParent = nodeParent.parentNode(); // parent has no sibling - try its parent } // parent has no parents anymore return TQDomNode(); // return empty node } TQDomNode domTool_matchingNode( const TQDomNode & node, const TQString & szPath ) { if(szPath.length() == 0) return TQDomNode(); // return void node TQString szNodePath = node.isDocument() ? TQString("") : domTool_getPath(node); if ( szPath == szNodePath ) // test if the strings match return node; /* L.V. those optimalizations disallow find proc. instr. at doc. level // we will find any node in root element subtree if ( szPath.length() <= szNodePath.length() ) // the given string must be longer return TQDomNode(); // otherwise we don't need to check the childs if ( szPath.left(szNodePath.length()) != szNodePath ) // the nodes path must be left part of the given path return TQDomNode(); // otherwise we don't need to check the childs */ // recursively check the childs TQDomNode nodeChild = node.firstChild(); TQDomNode nodeTmp; while ( ! nodeChild.isNull() ) { nodeTmp = domTool_matchingNode( nodeChild, szPath ); if ( ! nodeTmp.isNull() ) return nodeTmp; nodeChild = nodeChild.nextSibling(); } return TQDomNode(); // nothing found -> return empty node } bool domTool_match( TQDomNode node, const KXESearchDialog * const pConditions ) { if ( node.isNull() ) { kdDebug() << "domTool_match: internal implementation error - the given node is an empty one" << endl; return false; } if ( ! pConditions ) { kdDebug() << "domTool_match: internal implementation error - the given pointer is a null pointer" << endl; return false; } switch ( node.nodeType() ) { case TQDomNode::ElementNode: // ---------------------------------------- { if ( pConditions->getInElementNames() ) { if ( node.toElement().tagName().find( pConditions->getSearchString(), 0, pConditions->getMatchCase() ) >= 0 ) return true; } if ( ( pConditions->getInAttributeNames() ) || ( pConditions->getInAttributeValues() ) ) { TQDomNamedNodeMap list = node.toElement().attributes(); unsigned int iLength = list.length(); if ( iLength <= 0 ) return false; // no attributes for ( unsigned int iRow = 0; iRow < iLength; iRow++ ) { if ( pConditions->getInAttributeNames() ) if ( list.item(iRow).toAttr().name().find( pConditions->getSearchString(), 0, pConditions->getMatchCase() ) >= 0 ) return true; if ( pConditions->getInAttributeValues() ) if ( list.item(iRow).toAttr().value().find( pConditions->getSearchString(), 0, pConditions->getMatchCase() ) >= 0 ) return true; } return false; } return false; break; } case TQDomNode::TextNode: // ---------------------------------------- case TQDomNode::CDATASectionNode: case TQDomNode::CommentNode: { if ( pConditions->getInContents() ) { if ( node.toCharacterData().data().find( pConditions->getSearchString(), 0, pConditions->getMatchCase() ) >= 0 ) return true; else return false; } else return false; break; } // TODO implement this for the other node types (eg proc.instr.) default: kdDebug() << "domTool_match: unknown node type (" << node.nodeType() << ")" << endl; } return true; }