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.
kxmleditor/part/qdom_add.cpp

353 lines
11 KiB

/***************************************************************************
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 <kiconloader.h>
#include <kdebug.h>
#include <tqtextstream.h>
#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;
}