• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdelibs API Reference
  • KDE Home
  • Contact Us
 

KHTML

  • sources
  • kde-4.12
  • kdelibs
  • khtml
  • xpath
step.cpp
Go to the documentation of this file.
1 /*
2  * step.cc - Copyright 2005 Frerich Raabe <raabe@kde.org>
3  * Copyright 2010 Maksim Orlovich <maksim@kde.org>
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 #include "step.h"
27 
28 #include "dom/dom3_xpath.h"
29 #include "xml/dom_docimpl.h"
30 #include "xml/dom_nodeimpl.h"
31 #include "xml/dom_textimpl.h"
32 #include "xml/dom3_xpathimpl.h"
33 
34 #include "step.h"
35 
36 #include <QtDebug>
37 
38 using namespace DOM;
39 using namespace DOM::XPath;
40 using namespace khtml;
41 using namespace khtml::XPath;
42 
43 
44 static bool areAdjacentTextNodes( NodeImpl *n, NodeImpl *m )
45 {
46  if ( !n || !m ) {
47  return false;
48  }
49 
50  if ( n->nodeType() != Node::TEXT_NODE && n->nodeType() != Node::CDATA_SECTION_NODE ) {
51  return false;
52  }
53  if ( m->nodeType() != Node::TEXT_NODE && m->nodeType() != Node::CDATA_SECTION_NODE ) {
54  return false;
55  }
56 
57  // ###
58 #ifdef __GNUC__
59 #warning "Might need more generic adjacency -- check"
60 #endif
61 
62  return ( n->nextSibling() && ( n->nextSibling() == m ) ) ||
63  ( m->nextSibling() && ( m->nextSibling() == n ) );
64 }
65 
66 static DomNodeList compressTextNodes( const DomNodeList &nodes )
67 {
68  DomNodeList outNodes = new StaticNodeListImpl;
69 
70  for ( unsigned long n = 0; n < nodes->length(); ++n) {
71  NodeImpl* node = nodes->item( n );
72  NodeImpl* next = n+1 < nodes->length() ? nodes->item( n+1 ) : 0;
73 
74  if ( !next || !areAdjacentTextNodes( node, next ) ) {
75  outNodes->append( node );
76  } else if ( areAdjacentTextNodes( node, next ) ) {
77  QString s = node->nodeValue().string();
78 
79  // n2 is a potential successor, and is always in-range
80  unsigned long n2 = n+1;
81  while (n2 < nodes->length() && areAdjacentTextNodes( nodes->item( n2 ), nodes->item( n2-1) ) ) {
82  s += nodes->item( n2 )->nodeValue().string();
83  ++n2;
84  }
85  outNodes->append( node->document()->createTextNode( new DOMStringImpl( s.data(), s.length() ) ) );
86  }
87  }
88  return outNodes;
89 }
90 
91 QString Step::axisAsString( AxisType axis )
92 {
93  switch ( axis ) {
94  case AncestorAxis: return "ancestor";
95  case AncestorOrSelfAxis: return "ancestor-or-self";
96  case AttributeAxis: return "attribute";
97  case ChildAxis: return "child";
98  case DescendantAxis: return "descendant";
99  case DescendantOrSelfAxis: return "descendant-or-self";
100  case FollowingAxis: return "following";
101  case FollowingSiblingAxis: return "following-sibling";
102  case NamespaceAxis: return "namespace";
103  case ParentAxis: return "parent";
104  case PrecedingAxis: return "preceding";
105  case PrecedingSiblingAxis: return "preceding-sibling";
106  case SelfAxis: return "self";
107  }
108  return QString();
109 }
110 
111 Step::Step(): m_compileState( NotCompiled )
112 {
113 }
114 
115 Step::Step( AxisType axis, const DOMString &nodeTest,
116  const QList<Predicate *> &predicates )
117  : m_axis( axis ),
118  m_nodeTest( nodeTest ),
119  m_compileState( NotCompiled ),
120  m_predicates( predicates )
121 {
122 }
123 
124 Step::~Step()
125 {
126  qDeleteAll( m_predicates );
127 }
128 
129 DomNodeList Step::evaluate( NodeImpl *context ) const
130 {
131  assert( context );
132 #ifdef XPATH_VERBOSE
133  kDebug(6011) << "Evaluating step, axis='" << axisAsString( m_axis ) <<"'"
134  << ", nodetest='" << m_nodeTest << "'"
135  << ", " << m_predicates.count() << " predicates";
136  kDebug(6011) << DOM::getPrintableName( context->id() );
137 #endif
138 
139  DomNodeList inNodes = nodesInAxis( context ), outNodes;
140 
141  // ### optimization opportunity: can say DocumentOrder for most
142  StaticNodeListImpl::NormalizationKind known = StaticNodeListImpl::AxisOrder;
143  inNodes->setKnownNormalization(known);
144 
145 #ifdef XPATH_VERBOSE
146  kDebug(6011) << "Axis " << axisAsString( m_axis ) << " matches " << inNodes->length() << " nodes.";
147 #endif
148 
149  inNodes = nodeTestMatches( context, inNodes );
150  inNodes->setKnownNormalization(known); // nodeTest doesn't change order
151 
152 #ifdef XPATH_VERBOSE
153  kDebug(6011) << "\tNodetest " << m_nodeTest << " trims this number to " << inNodes->length();
154 #endif
155 
156  if ( m_predicates.isEmpty() )
157  return inNodes;
158 
159  foreach( Predicate *predicate, m_predicates ) {
160  outNodes = new StaticNodeListImpl;
161  Expression::evaluationContext().size = int(inNodes->length());
162  Expression::evaluationContext().position = 1;
163 
164  for ( unsigned long n = 0; n < inNodes->length(); ++n ) {
165  NodeImpl* node = inNodes->item( n );
166  Expression::evaluationContext().node = node;
167  EvaluationContext backupCtx = Expression::evaluationContext();
168 #ifdef XPATH_VERBOSE
169  kDebug() << Expression::evaluationContext().position << "/" << node;
170 #endif
171  if ( predicate->evaluate() ) {
172  outNodes->append( node );
173  }
174  Expression::evaluationContext() = backupCtx;
175  ++Expression::evaluationContext().position;
176  }
177 #ifdef XPATH_VERBOSE
178  kDebug(6011) << "\tPredicate trims this number to " << outNodes->length();
179 #endif
180  inNodes = outNodes;
181  inNodes->setKnownNormalization(known); // predicates don't change order
182  }
183 
184  return outNodes;
185 }
186 
187 DomNodeList Step::nodesInAxis( NodeImpl *context ) const
188 {
189  //assert(context);
190  DomNodeList nodes = new StaticNodeListImpl;
191  switch ( m_axis ) {
192  case ChildAxis: {
193  NodeImpl *n = xpathFirstChild( context );
194  while ( n ) {
195  nodes->append( n );
196  n = n->nextSibling();
197  }
198  return nodes;
199  }
200  case DescendantAxis: {
201  collectChildrenRecursively( nodes, context );
202  return nodes;
203  }
204  case ParentAxis: {
205  NodeImpl* p = xpathParentNode( context );
206 
207  if ( p )
208  nodes->append( p );
209  return nodes;
210  }
211  case AncestorAxis: {
212  NodeImpl *n = xpathParentNode( context );
213  while ( n ) {
214  nodes->append( n );
215  n = xpathParentNode( n );
216  }
217  return nodes;
218  }
219  case FollowingSiblingAxis: {
220  if ( context->nodeType() == Node::ATTRIBUTE_NODE ||
221  context->nodeType() == Node::XPATH_NAMESPACE_NODE ) {
222  return nodes; // empty
223  }
224 
225  NodeImpl *n = context->nextSibling();
226  while ( n ) {
227  nodes->append( n );
228  n = n->nextSibling();
229  }
230  return nodes;
231  }
232  case PrecedingSiblingAxis: {
233  if ( context->nodeType() == Node::ATTRIBUTE_NODE ||
234  context->nodeType() == Node::XPATH_NAMESPACE_NODE ) {
235  return nodes; // empty
236  }
237 
238  NodeImpl *n = context->previousSibling();
239  while ( n ) {
240  nodes->append( n );
241  n = n->previousSibling();
242  }
243  return nodes;
244  }
245  case FollowingAxis: {
246  NodeImpl *p = context;
247  while ( !isRootDomNode( p ) ) {
248  NodeImpl *n = nextSiblingForFollowing( p );
249  while ( n ) {
250  nodes->append( n );
251  collectChildrenRecursively( nodes, n );
252  n = n->nextSibling();
253  }
254  p = xpathParentNode( p );
255  }
256  return nodes;
257  }
258  case PrecedingAxis: {
259  NodeImpl *p = context;
260  while ( !isRootDomNode( p ) ) {
261  NodeImpl *n = p->previousSibling();
262  while ( n ) {
263  collectChildrenReverse( nodes, n );
264  nodes->append( n );
265  n = n->previousSibling();
266  }
267  p = xpathParentNode( p );
268  }
269  return nodes;
270  }
271  case AttributeAxis: {
272  if ( context->nodeType() != Node::ELEMENT_NODE ) {
273  return nodes; // empty
274  }
275 
276  NamedAttrMapImpl *attrs = static_cast<ElementImpl*>(context)->attributes( true /*read-only*/ );
277  if ( !attrs ) {
278  return nodes;
279  }
280 
281  for ( unsigned long i = 0; i < attrs->length(); ++i ) {
282  nodes->append( attrs->item( i ) );
283  }
284  return nodes;
285  }
286  case NamespaceAxis: {
287  // ### TODO: Need to implement this, but not a priority, since
288  // other impls don't.
289 #if 0
290  if ( context->nodeType() != Node::ELEMENT_NODE ) {
291  return nodes;
292  }
293 
294  bool foundXmlNsNode = false;
295  NodeImpl *node = context;
296  while ( node ) {
297  NamedAttrMapImpl *attrs =
298  node->isElementNode() ? static_cast<ElementImpl*>(node)->attributes() : 0;
299  if ( !attrs ) {
300  node = xpathParentNode( node );
301  continue;
302  }
303 
304  for ( unsigned long i = 0; i < attrs->length(); ++i ) {
305  NodeImpl *n = attrs->item( i );
306  if ( n->nodeName().string().startsWith( "xmlns:" ) ) {
307  nodes->append( n );
308  } else if ( n->nodeName() == "xmlns" &&
309  !foundXmlNsNode
310  ) {
311  foundXmlNsNode = true;
312  if ( !n->nodeValue().string().isEmpty() ) {
313  nodes->append( n );
314  }
315  }
316  }
317  node = xpathParentNode( node );
318  }
319 #endif
320  return nodes;
321  }
322  case SelfAxis:
323  nodes->append( context );
324  return nodes;
325  case DescendantOrSelfAxis:
326  nodes->append( context );
327  collectChildrenRecursively( nodes, context );
328  return nodes;
329  case AncestorOrSelfAxis: {
330  nodes->append( context );
331  NodeImpl *n = xpathParentNode( context );
332  while ( n ) {
333  nodes->append( n );
334  n = xpathParentNode( n );
335  }
336  return nodes;
337  }
338  default:
339  kWarning(6011) << "Unknown axis " << axisAsString( m_axis ) << " passed to Step::nodesInAxis";
340  }
341 
342  return nodes; // empty
343 }
344 
345 void Step::compileNodeTest(bool htmlCompat) const
346 {
347  m_compileState = htmlCompat ? CompiledForHTML : CompiledForXML;
348 
349  if ( m_nodeTest == "*" ) {
350  m_nodeTestType = NT_Star;
351  } else if ( m_nodeTest == "text()" ) {
352  m_nodeTestType = NT_Text;
353  } else if ( m_nodeTest == "comment()" ) {
354  m_nodeTestType = NT_Comment;
355  } else if ( m_nodeTest.startsWith( "processing-instruction" ) ) {
356  DOMString param;
357 
358  // ### is this right? (parens?)
359  const int space = m_nodeTest.find( ' ' );
360  if ( space > -1 ) {
361  param = m_nodeTest.substring( space + 1 );
362  }
363 
364  if ( param.isEmpty() ) {
365  m_nodeTestType = NT_PI;
366  } else {
367  m_nodeTestType = NT_PI_Lit;
368  m_piInfo = param;
369  }
370  } else if ( m_nodeTest == "node()" ) {
371  m_nodeTestType = NT_AnyNode;
372  } else {
373  // Some sort of name combo.
374  PrefixName prefix;
375  LocalName localName;
376 
377  splitPrefixLocalName( m_nodeTest, prefix, localName, htmlCompat );
378 
379  if ( prefix.id() == DOM::emptyPrefix ) {
380  // localname only
381  m_nodeTestType = NT_LocalName;
382  m_localName = localName;
383  } else if ( localName.toString() == "*" ) {
384  // namespace only
385  m_nodeTestType = NT_Namespace;
386  m_namespace = NamespaceName::fromString(namespaceFromNodetest( m_nodeTest ) );
387  } else {
388  // Both parts.
389  m_nodeTestType = NT_QName;
390  m_localName = localName;
391  m_namespace = NamespaceName::fromString(namespaceFromNodetest( m_nodeTest ) );
392  }
393  }
394 }
395 
396 DomNodeList Step::nodeTestMatches( NodeImpl* ctx, const DomNodeList &nodes ) const
397 {
398  CompileState desired = ctx->htmlCompat() ? CompiledForHTML : CompiledForXML;
399  if ( m_compileState != desired )
400  compileNodeTest( ctx->htmlCompat() );
401 
402  if ( m_nodeTestType == NT_AnyNode) // no need for a new set
403  return nodes;
404 
405  DomNodeList matches = new StaticNodeListImpl;
406 
407  // A lot of things can be handled by just checking the type,
408  // and maybe a hair more special handling
409  int matchType;
410  switch ( m_nodeTestType ) {
411  case NT_Star:
412  matchType = primaryNodeType( m_axis );
413  break;
414  case NT_Comment:
415  matchType = Node::COMMENT_NODE;
416  break;
417  case NT_Text:
418  matchType = Node::TEXT_NODE;
419  break;
420  case NT_PI:
421  case NT_PI_Lit:
422  matchType = Node::PROCESSING_INSTRUCTION_NODE;
423  break;
424  default:
425  matchType = -1;
426  }
427 
428  if ( matchType != -1 ) {
429  for ( unsigned long n = 0; n < nodes->length(); ++n ) {
430  NodeImpl *node = nodes->item( n );
431  int nodeType = node->nodeType();
432  if ( nodeType == matchType ) {
433  if ( m_nodeTestType == NT_PI_Lit && node->nodeName() != m_piInfo )
434  continue;
435 
436  matches->append( node );
437  }
438 
439  if ( matchType == NT_Text && nodeType == Node::CDATA_SECTION_NODE )
440  matches->append( node );
441  }
442  return matches;
443  }
444 
445  // Now we are checking by name. We always want to filter out
446  // the primary axis here
447  // ### CHECK: this used to have special handling for some axes.
448  matchType = primaryNodeType( m_axis );
449  for ( unsigned long n = 0; n < nodes->length(); ++n ) {
450  NodeImpl *node = nodes->item( n );
451  if ( node->nodeType() != matchType )
452  continue;
453 
454  if ( m_nodeTestType == NT_LocalName ) {
455  if ( localNamePart( node->id() ) == m_localName.id() )
456  matches->append( node );
457  } else if ( m_nodeTestType == NT_Namespace ) {
458  if ( namespacePart( node->id() ) == m_namespace.id() )
459  matches->append( node );
460  } else {
461  // NT_QName
462  if ( node->id() == makeId( m_namespace.id(), m_localName.id() ) )
463  matches->append( node );
464  }
465  }
466  return matches;
467 }
468 
469 void Step::optimize()
470 {
471  foreach( Predicate *predicate, m_predicates ) {
472  predicate->optimize();
473  }
474 }
475 
476 QString Step::dump() const
477 {
478  QString s = QString( "<step axis=\"%1\" nodetest=\"%2\">" ).arg( axisAsString( m_axis ) ).arg( m_nodeTest.string() );
479  foreach( Predicate *predicate, m_predicates ) {
480  s += predicate->dump();
481  }
482  s += "</step>";
483  return s;
484 }
485 
486 DOMString Step::namespaceFromNodetest( const DOMString &nodeTest ) const
487 {
488  int i = nodeTest.find( ':' );
489  if ( i == -1 ) {
490  return DOMString();
491  }
492 
493  DOMString prefix( nodeTest.substring( 0, i ) );
494  XPathNSResolverImpl *resolver = Expression::evaluationContext().resolver;
495 
496  DOM::DOMString ns;
497  if (resolver)
498  ns = resolver->lookupNamespaceURI( prefix );
499 
500  if ( ns.isNull() )
501  Expression::reportNamespaceErr();
502 
503  return ns;
504 }
505 
506 unsigned int Step::primaryNodeType( AxisType axis ) const
507 {
508  switch ( axis ) {
509  case AttributeAxis:
510  return Node::ATTRIBUTE_NODE;
511  case NamespaceAxis:
512  return Node::XPATH_NAMESPACE_NODE;
513  default:
514  return Node::ELEMENT_NODE;
515  }
516 }
517 
518 // kate: indent-width 4; replace-tabs off; tab-width 4; space-indent off;
step.h
areAdjacentTextNodes
static bool areAdjacentTextNodes(NodeImpl *n, NodeImpl *m)
Definition: step.cpp:44
khtml::XPath::Step::PrecedingAxis
Definition: step.h:49
khtml::XPath::Step::AncestorOrSelfAxis
Definition: step.h:46
param
QString param(const QString &t)
DOM::DOMString::length
uint length() const
Definition: dom_string.cpp:185
khtml::XPath::Step::dump
QString dump() const
Definition: step.cpp:476
assert
#define assert(x)
Definition: editor.cpp:43
khtml::XPath::Predicate::optimize
void optimize()
Definition: predicate.cpp:430
khtml::XPath::Step::~Step
~Step()
Definition: step.cpp:124
khtml::XPath::Step::axisAsString
static QString axisAsString(AxisType axis)
Definition: step.cpp:91
khtml::XPath::nextSiblingForFollowing
DOM::NodeImpl * nextSiblingForFollowing(DOM::NodeImpl *node)
Definition: util.cpp:140
DOM::DOMString::string
QString string() const
Definition: dom_string.cpp:236
QString
khtml::XPath::DomNodeList
SharedPtr< DOM::StaticNodeListImpl > DomNodeList
Definition: util.h:41
compressTextNodes
static DomNodeList compressTextNodes(const DomNodeList &nodes)
Definition: step.cpp:66
khtml::XPath::Predicate::dump
QString dump() const
Definition: predicate.cpp:435
kDebug
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
prefix
QString prefix()
khtml::XPath::Expression::reportNamespaceErr
static void reportNamespaceErr()
Definition: expression.cpp:293
DOM::DOMString::isEmpty
bool isEmpty() const
Definition: dom_string.cpp:315
khtml::XPath::isRootDomNode
bool isRootDomNode(NodeImpl *node)
Definition: util.cpp:35
DOM::Node::CDATA_SECTION_NODE
Definition: dom_node.h:385
khtml::XPath::Step::optimize
void optimize()
Definition: step.cpp:469
khtml::XPath::Predicate
Definition: predicate.h:148
DOM::DOMString::isNull
bool isNull() const
Definition: dom_string.h:121
khtml::XPath::Step::DescendantAxis
Definition: step.h:47
khtml::XPath::Step::ParentAxis
Definition: step.h:49
khtml::XPath::Expression::evaluationContext
static EvaluationContext & evaluationContext()
Definition: expression.cpp:212
khtml::XPath::EvaluationContext::node
DOM::NodeImpl * node
Definition: expression.h:59
khtml::XPath::Step::evaluate
DomNodeList evaluate(DOM::NodeImpl *context) const
Definition: step.cpp:129
khtml::XPath::EvaluationContext::position
unsigned long position
Definition: expression.h:61
khtml::XPath::Step::Step
Step()
Definition: step.cpp:111
khtml::XPath::Predicate::evaluate
bool evaluate() const
Definition: predicate.cpp:416
khtml::XPath::Step::FollowingAxis
Definition: step.h:48
DOM::DOMString
This class implements the basic string we use in the DOM.
Definition: dom_string.h:43
khtml::XPath::xpathFirstChild
DOM::NodeImpl * xpathFirstChild(DOM::NodeImpl *node)
Definition: util.cpp:124
khtml::XPath::Step::AncestorAxis
Definition: step.h:46
khtml::XPath::collectChildrenReverse
void collectChildrenReverse(SharedPtr< DOM::StaticNodeListImpl > out, DOM::NodeImpl *root)
Definition: util.cpp:86
khtml::XPath::EvaluationContext
Definition: expression.h:47
next
KAction * next(const QObject *recvr, const char *slot, QObject *parent)
DOM::DOMString::startsWith
bool startsWith(const DOMString &str) const
Definition: dom_string.cpp:287
dom3_xpath.h
DOM::DOMString::find
int find(const QChar c, int start=0) const
Definition: dom_string.cpp:154
khtml::XPath::EvaluationContext::size
unsigned long size
Definition: expression.h:60
khtml::XPath::Step::ChildAxis
Definition: step.h:47
khtml::XPath::EvaluationContext::resolver
XPathNSResolverImpl * resolver
Definition: expression.h:72
khtml::XPath::Step::AttributeAxis
Definition: step.h:46
DOM::DOMString::substring
DOMString substring(unsigned pos, unsigned len=UINT_MAX) const
Definition: dom_string.cpp:180
khtml::XPath::xpathParentNode
DOM::NodeImpl * xpathParentNode(DOM::NodeImpl *node)
Definition: util.cpp:112
khtml::XPath::Step::SelfAxis
Definition: step.h:50
khtml::XPath::collectChildrenRecursively
void collectChildrenRecursively(SharedPtr< DOM::StaticNodeListImpl > out, DOM::NodeImpl *root)
Definition: util.cpp:73
kWarning
static QDebug kWarning(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
DOM::Node::TEXT_NODE
Definition: dom_node.h:384
khtml::XPath::Step::NamespaceAxis
Definition: step.h:48
khtml::XPath::Step::DescendantOrSelfAxis
Definition: step.h:47
khtml::XPath::Step::AxisType
AxisType
Definition: step.h:45
khtml::XPath::Step::FollowingSiblingAxis
Definition: step.h:48
QList
khtml::XPath::Step::PrecedingSiblingAxis
Definition: step.h:49
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:51:22 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KHTML

Skip menu "KHTML"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  • kjsembed
  •   WTF
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Nepomuk-Core
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal