|
|
|
/***************************************************************************
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|