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

Nepomuk-Core

  • sources
  • kde-4.12
  • kdelibs
  • nepomuk-core
  • services
  • storage
classandpropertytree.cpp
Go to the documentation of this file.
1 /*
2  This file is part of the Nepomuk KDE project.
3  Copyright (C) 2010-2011 Sebastian Trueg <trueg@kde.org>
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Lesser General Public
7  License as published by the Free Software Foundation; either
8  version 2.1 of the License, or (at your option) version 3, or any
9  later version accepted by the membership of KDE e.V. (or its
10  successor approved by the membership of KDE e.V.), which shall
11  act as a proxy defined in Section 6 of version 3 of the license.
12 
13  This library is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  Lesser General Public License for more details.
17 
18  You should have received a copy of the GNU Lesser General Public
19  License along with this library. If not, see <http://www.gnu.org/licenses/>.
20 */
21 
22 #include "classandpropertytree.h"
23 #include "simpleresource.h"
24 #include "simpleresourcegraph.h"
25 
26 #include <QtCore/QSet>
27 #include <QtCore/QDir>
28 #include <QtCore/QFile>
29 #include <QtCore/QDateTime>
30 #include <QtCore/QMutexLocker>
31 
32 #include <Soprano/Node>
33 #include <Soprano/LiteralValue>
34 #include <Soprano/QueryResultIterator>
35 #include <Soprano/Model>
36 #include <Soprano/Vocabulary/RDF>
37 #include <Soprano/Vocabulary/RDFS>
38 #include <Soprano/Vocabulary/NAO>
39 #include <Soprano/Vocabulary/NRL>
40 #include <Soprano/Vocabulary/XMLSchema>
41 
42 #include <KDebug>
43 
44 using namespace Soprano;
45 using namespace Soprano::Vocabulary;
46 
47 Nepomuk2::ClassAndPropertyTree* Nepomuk2::ClassAndPropertyTree::s_self = 0;
48 
49 class Nepomuk2::ClassAndPropertyTree::ClassOrProperty
50 {
51 public:
52  ClassOrProperty()
53  : isProperty(false),
54  maxCardinality(0),
55  defining(0),
56  hasRdfsLiteralRange(false) {
57  }
58 
60  bool isProperty;
61 
63  QUrl uri;
64 
66  QSet<QUrl> directParents;
67 
69  QSet<QUrl> allParents;
70 
72  int maxCardinality;
73 
75  int defining;
76 
78  QUrl domain;
79  QUrl range;
80 
82  QVariant::Type literalType;
83  bool hasRdfsLiteralRange;
84 };
85 
86 Nepomuk2::ClassAndPropertyTree::ClassAndPropertyTree(QObject *parent)
87  : QObject(parent),
88  m_mutex(QMutex::Recursive)
89 {
90  Q_ASSERT(s_self == 0);
91  s_self = this;
92 }
93 
94 Nepomuk2::ClassAndPropertyTree::~ClassAndPropertyTree()
95 {
96  qDeleteAll(m_tree);
97  s_self = 0;
98 }
99 
100 bool Nepomuk2::ClassAndPropertyTree::isKnownClass(const QUrl &uri) const
101 {
102  QMutexLocker lock(&m_mutex);
103  if(const ClassOrProperty* cop = findClassOrProperty(uri))
104  return !cop->isProperty;
105  else
106  return false;
107 }
108 
109 QSet<QUrl> Nepomuk2::ClassAndPropertyTree::allParents(const QUrl &uri) const
110 {
111  QMutexLocker lock(&m_mutex);
112  if(const ClassOrProperty* cop = findClassOrProperty(uri))
113  return cop->allParents;
114  else
115  return QSet<QUrl>();
116 }
117 
118 QSet<QUrl> Nepomuk2::ClassAndPropertyTree::allParents(const QList< QUrl >& types) const
119 {
120  QSet<QUrl> all;
121  foreach(const QUrl& uri, types) {
122  all.unite( allParents(uri) );
123  all << uri;
124  }
125 
126  return all;
127 }
128 
129 
130 bool Nepomuk2::ClassAndPropertyTree::isChildOf(const QUrl &type, const QUrl &superClass) const
131 {
132  if( type == superClass )
133  return true;
134 
135  QMutexLocker lock(&m_mutex);
136  if(const ClassOrProperty* cop = findClassOrProperty(type))
137  return cop->allParents.contains(superClass);
138  else
139  return 0;
140 }
141 
142 bool Nepomuk2::ClassAndPropertyTree::isChildOf(const QList< QUrl >& types, const QUrl& superClass) const
143 {
144  if(superClass == RDFS::Resource()) {
145  return true;
146  }
147 
148  foreach( const QUrl & type, types ) {
149  if( isChildOf( type, superClass ) )
150  return true;
151  }
152  return false;
153 }
154 
155 int Nepomuk2::ClassAndPropertyTree::maxCardinality(const QUrl &type) const
156 {
157  QMutexLocker lock(&m_mutex);
158  if(const ClassOrProperty* cop = findClassOrProperty(type))
159  return cop->maxCardinality;
160  else
161  return 0;
162 }
163 
164 QUrl Nepomuk2::ClassAndPropertyTree::propertyDomain(const QUrl &uri) const
165 {
166  QMutexLocker lock(&m_mutex);
167  if(const ClassOrProperty* cop = findClassOrProperty(uri))
168  return cop->domain;
169  else
170  return QUrl();
171 }
172 
173 QUrl Nepomuk2::ClassAndPropertyTree::propertyRange(const QUrl &uri) const
174 {
175  QMutexLocker lock(&m_mutex);
176  if(const ClassOrProperty* cop = findClassOrProperty(uri))
177  return cop->range;
178  else
179  return QUrl();
180 }
181 
182 bool Nepomuk2::ClassAndPropertyTree::hasLiteralRange(const QUrl &uri) const
183 {
184  // TODO: this is a rather crappy check for literal range
185  QMutexLocker lock(&m_mutex);
186  if(const ClassOrProperty* cop = findClassOrProperty(uri))
187  return (cop->range.toString().startsWith(XMLSchema::xsdNamespace().toString() ) ||
188  cop->range == RDFS::Literal());
189  else
190  return false;
191 }
192 
193 bool Nepomuk2::ClassAndPropertyTree::isDefiningProperty(const QUrl &uri) const
194 {
195  QMutexLocker lock(&m_mutex);
196  if(const ClassOrProperty* cop = findClassOrProperty(uri))
197  return cop->defining == 1;
198  else
199  return true; // we default to true for unknown properties to ensure that we never perform invalid merges
200 }
201 
202 Soprano::Node Nepomuk2::ClassAndPropertyTree::variantToNode(const QVariant &value, const QUrl &property) const
203 {
204  QSet<Soprano::Node> nodes = variantListToNodeSet(QVariantList() << value, property);
205  if(nodes.isEmpty())
206  return Soprano::Node();
207  else
208  return *nodes.begin();
209 }
210 
211 QSet<Soprano::Node> Nepomuk2::ClassAndPropertyTree::variantListToNodeSet(const QVariantList &vl, const QUrl &property) const
212 {
213  clearError();
214 
215  QSet<Soprano::Node> nodes;
216  nodes.reserve( vl.size() );
217 
218  QUrl range;
219  QVariant::Type literalType;
220  bool hasRdfsLiteralRange = false;
221 
222  // Temporary scope for the locker
223  {
224  QMutexLocker lock(&m_mutex);
225  const ClassOrProperty* propertyNode = findClassOrProperty( property );
226  if( !propertyNode ) {
227  setError( QString::fromLatin1("Cannot set values for abstract property '%1'.")
228  .arg( Soprano::Node::resourceToN3( property ) ) );
229  return QSet<Soprano::Node>();
230  }
231 
232  range = propertyNode->range;
233  literalType = propertyNode->literalType;
234  hasRdfsLiteralRange = propertyNode->hasRdfsLiteralRange;
235  }
236 
237  //
238  // Special case: abstract properties - we do not allow setting them
239  //
240  if(range.isEmpty()) {
241  setError(QString::fromLatin1("Cannot set values for abstract property '%1'.").arg(property.toString()), Soprano::Error::ErrorInvalidArgument);
242  return QSet<Soprano::Node>();
243  }
244 
245  //
246  // Special case: rdfs:Literal
247  //
248  if( hasRdfsLiteralRange ) {
249  Q_FOREACH(const QVariant& value, vl) {
250  nodes.insert(Soprano::LiteralValue::createPlainLiteral(value.toString()));
251  }
252  return nodes;
253  }
254 
255  //
256  // Invalid Range - Probably a resource
257  //
258  if(literalType == QVariant::Invalid) {
259  Q_FOREACH(const QVariant& value, vl) {
260  // treat as a resource range for now
261  if(value.type() == QVariant::Url) {
262  QUrl url = value.toUrl();
263  if( url.scheme().isEmpty() && !url.toString().startsWith("_:") )
264  url.setScheme("file");
265  nodes.insert(url);
266  }
267  else if(value.type() == QVariant::String) {
268  QString s = value.toString();
269  if(!s.isEmpty()) {
270  // for convinience we support local file paths
271  if(s[0] == QDir::separator() && QFile::exists(s)) {
272  nodes.insert(QUrl::fromLocalFile(s));
273  }
274  else {
275  // treat it as a URI
276  nodes.insert(QUrl(s));
277  }
278  }
279  else {
280  // empty string
281  setError(QString::fromLatin1("Encountered an empty string where a resource URI was expected."), Soprano::Error::ErrorInvalidArgument);
282  return QSet<Soprano::Node>();
283  }
284  }
285  else {
286  // invalid type
287  setError(QString::fromLatin1("Encountered '%1' where a resource URI was expected.").arg(value.toString()), Soprano::Error::ErrorInvalidArgument);
288  return QSet<Soprano::Node>();
289  }
290  }
291 
292  return nodes;
293  }
294 
295  //
296  // The standard case
297  //
298  Q_FOREACH(const QVariant& value, vl) {
299  //
300  // Exiv data often contains floating point values encoded as a fraction
301  //
302  if((range == XMLSchema::xsdFloat() || range == XMLSchema::xsdDouble())
303  && value.type() == QVariant::String) {
304  int x = 0;
305  int y = 0;
306  if ( sscanf( value.toString().toLatin1().data(), "%d/%d", &x, &y ) == 2 && y != 0 ) {
307  const double v = double( x )/double( y );
308  nodes.insert(LiteralValue::fromVariant(v, range));
309  continue;
310  }
311  }
312 
313  //
314  // ID3 tags sometimes only contain the year of publication. We cover this
315  // special case here with a very dumb heuristic
316  //
317  else if(range == XMLSchema::dateTime()
318  && value.canConvert(QVariant::UInt)) {
319  bool ok = false;
320  const int t = value.toInt(&ok);
321  if(ok && t > 0 && t <= 9999) {
322  nodes.insert(LiteralValue(QDateTime(QDate(t, 1, 1), QTime(0, 0), Qt::UTC)));
323  continue;
324  }
325  }
326 
327  Soprano::LiteralValue v = Soprano::LiteralValue::fromVariant(value, range);
328  if(v.isValid()) {
329  nodes.insert(v);
330  }
331  else {
332  // failed literal conversion
333  setError(QString::fromLatin1("Failed to convert '%1' to literal of type '%2'.").arg(value.toString(), range.toString()), Soprano::Error::ErrorInvalidArgument);
334  return QSet<Soprano::Node>();
335  }
336  }
337 
338  return nodes;
339 }
340 
341 
342 namespace Soprano {
343  namespace Vocabulary {
344  namespace XMLSchema {
345  QUrl xsdDuration() {
346  return QUrl( Soprano::Vocabulary::XMLSchema::xsdNamespace().toString() +
347  QLatin1String("duration") );
348  }
349  }
350  }
351 }
352 
353 void Nepomuk2::ClassAndPropertyTree::rebuildTree(Soprano::Model* model)
354 {
355  QMutexLocker lock(&m_mutex);
356 
357  qDeleteAll(m_tree);
358  m_tree.clear();
359 
360  QString query
361  = QString::fromLatin1("select distinct ?r ?p ?v ?mc ?c ?domain ?range ?ct ?pt "
362  "where { "
363  "{ ?r a ?ct . FILTER(?ct=rdfs:Class) . "
364  "OPTIONAL { ?r rdfs:subClassOf ?p . ?p a rdfs:Class . } . } "
365  "UNION "
366  "{ ?r a ?pt . FILTER(?pt=rdf:Property) . "
367  "OPTIONAL { ?r rdfs:subPropertyOf ?p . ?p a rdf:Property . } . } "
368  "OPTIONAL { ?r %1 ?mc . } . "
369  "OPTIONAL { ?r %2 ?c . } . "
370  "OPTIONAL { ?r %3 ?domain . } . "
371  "OPTIONAL { ?r %4 ?range . } . "
372  "FILTER(?r!=%5) . "
373  "}" )
374  .arg(Soprano::Node::resourceToN3(NRL::maxCardinality()),
375  Soprano::Node::resourceToN3(NRL::cardinality()),
376  Soprano::Node::resourceToN3(RDFS::domain()),
377  Soprano::Node::resourceToN3(RDFS::range()),
378  Soprano::Node::resourceToN3(RDFS::Resource()));
379 // kDebug() << query;
380  Soprano::QueryResultIterator it
381  = model->executeQuery( query, Soprano::Query::QueryLanguageSparql );
382  while( it.next() ) {
383  const QUrl r = it["r"].uri();
384  const Soprano::Node p = it["p"];
385  const Soprano::Node v = it["v"];
386  int mc = it["mc"].literal().toInt();
387  int c = it["c"].literal().toInt();
388  const QUrl domain = it["domain"].uri();
389  const QUrl range = it["range"].uri();
390 
391  ClassOrProperty* r_cop = 0;
392  QHash<QUrl, ClassOrProperty*>::iterator copIt = m_tree.find(r);
393  if(copIt != m_tree.end()) {
394  r_cop = copIt.value();
395  }
396  else {
397  r_cop = new ClassOrProperty;
398  r_cop->uri = r;
399  m_tree.insert( r, r_cop );
400  }
401 
402  r_cop->isProperty = it["pt"].isValid();
403 
404  if(mc > 0 || c > 0) {
405  r_cop->maxCardinality = qMax(mc, c);
406  }
407 
408  if(!domain.isEmpty()) {
409  r_cop->domain = domain;
410  }
411 
412  if(!range.isEmpty()) {
413  r_cop->range = range;
414 
415  // Special handling for xsd:duration - Soprano doesn't handle it natively
416  if( range == XMLSchema::xsdDuration() )
417  r_cop->literalType = QVariant::UInt;
418  else if( range == RDFS::Literal() ) {
419  r_cop->literalType = QVariant::UserType;
420  r_cop->hasRdfsLiteralRange = true;
421  }
422  else
423  r_cop->literalType = Soprano::LiteralValue::typeFromDataTypeUri( range );
424  }
425  else {
426  // no range -> resource range
427  r_cop->defining = -1;
428  }
429 
430  if ( p.isResource() &&
431  p.uri() != r &&
432  p.uri() != RDFS::Resource() ) {
433  ClassOrProperty* p_cop = 0;
434  if ( !m_tree.contains( p.uri() ) ) {
435  p_cop = new ClassOrProperty;
436  p_cop->uri = p.uri();
437  m_tree.insert( p.uri(), p_cop );
438  }
439  r_cop->directParents.insert(p.uri());
440  }
441  }
442 
443  // although nao:identifier is actually an abstract property Nepomuk has been using
444  // it for very long to store string identifiers (instead of nao:personalIdentifier).
445  // Thus, we force its range to xsd:string for correct conversion in variantListToNodeSet()
446  if(m_tree.contains(NAO::identifier())) {
447  ClassOrProperty* cop = m_tree[NAO::identifier()];
448  cop->range = XMLSchema::string();
449  cop->literalType = QVariant::String;
450  }
451 
452  // add rdfs:Resource as parent for all top-level classes
453  ClassOrProperty* rdfsResourceNode = 0;
454  QHash<QUrl, ClassOrProperty*>::iterator rdfsResourceIt = m_tree.find(RDFS::Resource());
455  if( rdfsResourceIt == m_tree.end() ) {
456  rdfsResourceNode = new ClassOrProperty;
457  rdfsResourceNode->uri = RDFS::Resource();
458  m_tree.insert( RDFS::Resource(), rdfsResourceNode );
459  }
460  else {
461  rdfsResourceNode = rdfsResourceIt.value();
462  }
463  for ( QHash<QUrl, ClassOrProperty*>::iterator it = m_tree.begin();
464  it != m_tree.end(); ++it ) {
465  if( it.value() != rdfsResourceNode && it.value()->directParents.isEmpty() ) {
466  it.value()->directParents.insert( RDFS::Resource() );
467  }
468  }
469 
470  // complete the allParents lists
471  for ( QHash<QUrl, ClassOrProperty*>::iterator it = m_tree.begin();
472  it != m_tree.end(); ++it ) {
473  QSet<QUrl> visitedNodes;
474  getAllParents( it.value(), visitedNodes );
475  }
476 
477  // update all defining and non-defining properties
478  // by default all properties with a literal range are defining
479  // and all properties with a resource range are non-defining
480  query = QString::fromLatin1("select ?p ?t where { "
481  "?p a rdf:Property . "
482  "?p a ?t . FILTER(?t!=rdf:Property) . }");
483  it = model->executeQuery( query, Soprano::Query::QueryLanguageSparql );
484  while( it.next() ) {
485  const QUrl p = it["p"].uri();
486  const QUrl t = it["t"].uri();
487 
488  if(t == NRL::DefiningProperty()) {
489  m_tree[p]->defining = 1;
490  }
491  else if(t == NRL::NonDefiningProperty()) {
492  m_tree[p]->defining = -1;
493  }
494  }
495 
496  // rdf:type is defining by default
497  if(m_tree.contains(RDF::type()))
498  m_tree[RDF::type()]->defining = 1;
499 
500  // nao:hasSubResource is defining by default
501  if(m_tree.contains(NAO::hasSubResource()))
502  m_tree[NAO::hasSubResource()]->defining = 1;
503 
504  for ( QHash<QUrl, ClassOrProperty*>::iterator it = m_tree.begin();
505  it != m_tree.end(); ++it ) {
506  if(it.value()->isProperty) {
507  QSet<QUrl> visitedNodes;
508  updateDefining( it.value(), visitedNodes );
509  }
510  }
511 }
512 
513 const Nepomuk2::ClassAndPropertyTree::ClassOrProperty * Nepomuk2::ClassAndPropertyTree::findClassOrProperty(const QUrl &uri) const
514 {
515  QHash<QUrl, ClassOrProperty*>::const_iterator it = m_tree.constFind(uri);
516  if(it == m_tree.constEnd())
517  return 0;
518  else
519  return it.value();
520 }
521 
522 bool Nepomuk2::ClassAndPropertyTree::contains(const QUrl& uri) const
523 {
524  return m_tree.contains(uri);
525 }
526 
527 
532 int Nepomuk2::ClassAndPropertyTree::updateDefining( ClassOrProperty* cop, QSet<QUrl>& definingNodes )
533 {
534  if ( cop->defining != 0 ) {
535  return cop->defining;
536  }
537  else {
538  for ( QSet<QUrl>::iterator it = cop->directParents.begin();
539  it != cop->directParents.end(); ++it ) {
540  // avoid endless loops
541  if( definingNodes.contains(*it) )
542  continue;
543  definingNodes.insert(*it);
544  if ( updateDefining( m_tree[*it], definingNodes ) == 1 ) {
545  cop->defining = 1;
546  break;
547  }
548  }
549  if ( cop->defining == 0 ) {
550  // properties with a literal range default to defining
551  cop->defining = hasLiteralRange(cop->uri) ? 1 : -1;
552  }
553  //kDebug() << "Setting defining of" << cop->uri.toString() << ( cop->defining == 1 );
554  return cop->defining;
555  }
556 }
557 
558 QSet<QUrl> Nepomuk2::ClassAndPropertyTree::getAllParents(ClassOrProperty* cop, QSet<QUrl>& visitedNodes)
559 {
560  if(cop->allParents.isEmpty()) {
561  for ( QSet<QUrl>::iterator it = cop->directParents.begin();
562  it != cop->directParents.end(); ++it ) {
563  // avoid endless loops
564  if( visitedNodes.contains(*it) )
565  continue;
566  visitedNodes.insert( *it );
567  cop->allParents += getAllParents(m_tree[*it], visitedNodes);
568  }
569  cop->allParents += cop->directParents;
570 
571  // some cleanup to fix inheritance loops
572  cop->allParents << RDFS::Resource();
573  cop->allParents.remove(cop->uri);
574  }
575  return cop->allParents;
576 }
577 
578 
579 namespace {
580  Soprano::Node convertIfBlankNode( const Soprano::Node & n ) {
581  if( n.isResource() ) {
582  const QString uriString = n.uri().toString();
583  if( uriString.startsWith("_:") ) {
584  return Soprano::Node( uriString.mid(2) ); // "_:" take 2 characters
585  }
586  }
587  return n;
588  }
589 }
590 
591 Nepomuk2::ClassAndPropertyTree * Nepomuk2::ClassAndPropertyTree::self()
592 {
593  return s_self;
594 }
595 
596 #include "classandpropertytree.moc"
Nepomuk2::ClassAndPropertyTree::hasLiteralRange
bool hasLiteralRange(const QUrl &uri) const
Definition: classandpropertytree.cpp:182
Nepomuk2::ClassAndPropertyTree::propertyDomain
QUrl propertyDomain(const QUrl &uri) const
Definition: classandpropertytree.cpp:164
QHash
QObject
Nepomuk2::ClassAndPropertyTree
Definition: classandpropertytree.h:45
Nepomuk2::ClassAndPropertyTree::contains
bool contains(const QUrl &uri) const
Returns true if the uri is a Class or a Property.
Definition: classandpropertytree.cpp:522
Nepomuk2::ClassAndPropertyTree::propertyRange
QUrl propertyRange(const QUrl &uri) const
Definition: classandpropertytree.cpp:173
classandpropertytree.h
Nepomuk2::ClassAndPropertyTree::self
static ClassAndPropertyTree * self()
Definition: classandpropertytree.cpp:591
Nepomuk2::ClassAndPropertyTree::~ClassAndPropertyTree
~ClassAndPropertyTree()
Definition: classandpropertytree.cpp:94
simpleresource.h
Nepomuk2::ClassAndPropertyTree::isChildOf
bool isChildOf(const QUrl &type, const QUrl &superClass) const
Definition: classandpropertytree.cpp:130
simpleresourcegraph.h
Nepomuk2::ClassAndPropertyTree::rebuildTree
void rebuildTree(Soprano::Model *model)
Definition: classandpropertytree.cpp:353
Soprano::Vocabulary::XMLSchema::xsdDuration
QUrl xsdDuration()
Definition: classandpropertytree.cpp:345
Nepomuk2::ClassAndPropertyTree::allParents
QSet< QUrl > allParents(const QUrl &uri) const
Definition: classandpropertytree.cpp:109
Nepomuk2::ClassAndPropertyTree::variantToNode
Soprano::Node variantToNode(const QVariant &value, const QUrl &property) const
will try very hard to convert a variant into a node. Supports literal XML types and QUrl ...
Definition: classandpropertytree.cpp:202
Nepomuk2::ClassAndPropertyTree::isDefiningProperty
bool isDefiningProperty(const QUrl &uri) const
Definition: classandpropertytree.cpp:193
Nepomuk2::ClassAndPropertyTree::ClassAndPropertyTree
ClassAndPropertyTree(QObject *parent=0)
Definition: classandpropertytree.cpp:86
Nepomuk2::ClassAndPropertyTree::variantListToNodeSet
QSet< Soprano::Node > variantListToNodeSet(const QVariantList &vl, const QUrl &property) const
Definition: classandpropertytree.cpp:211
Nepomuk2::ClassAndPropertyTree::maxCardinality
int maxCardinality(const QUrl &type) const
Definition: classandpropertytree.cpp:155
Nepomuk2::ClassAndPropertyTree::isKnownClass
bool isKnownClass(const QUrl &uri) const
Definition: classandpropertytree.cpp:100
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:48:08 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

Nepomuk-Core

Skip menu "Nepomuk-Core"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • 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