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

KParts

  • kparts
browserrun.cpp
Go to the documentation of this file.
1 /* This file is part of the KDE project
2  *
3  * Copyright (C) 2002 David Faure <faure@kde.org>
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License version 2, as published by the Free Software Foundation.
7  *
8  * This library is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11  * Library General Public License for more details.
12  *
13  * You should have received a copy of the GNU Library General Public License
14  * along with this library; see the file COPYING.LIB. If not, write to
15  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16  * Boston, MA 02110-1301, USA.
17  */
18 
19 #include "browserrun.h"
20 #include "browserrun_p.h"
21 
22 #include <kmessagebox.h>
23 #include <kfiledialog.h>
24 #include <kio/job.h>
25 #include <kio/jobuidelegate.h>
26 #include <kio/scheduler.h>
27 #include <kio/copyjob.h>
28 #include <klocale.h>
29 #include <kshell.h>
30 #include <kstringhandler.h>
31 #include <kmimetypetrader.h>
32 #include <ktemporaryfile.h>
33 #include <kdebug.h>
34 #include <kde_file.h>
35 #include <kstandarddirs.h>
36 #include <kdatetime.h>
37 #include "browseropenorsavequestion.h"
38 #include <kprotocolmanager.h>
39 
40 using namespace KParts;
41 
42 class BrowserRun::BrowserRunPrivate
43 {
44 public:
45  bool m_bHideErrorDialog;
46  bool m_bRemoveReferrer;
47  bool m_bTrustedSource;
48  KParts::OpenUrlArguments m_args;
49  KParts::BrowserArguments m_browserArgs;
50 
51  KParts::ReadOnlyPart *m_part; // QGuardedPtr?
52  QPointer<QWidget> m_window;
53  QString m_mimeType;
54  QString m_contentDisposition;
55 };
56 
57 BrowserRun::BrowserRun( const KUrl& url, const KParts::OpenUrlArguments& args,
58  const KParts::BrowserArguments& browserArgs,
59  KParts::ReadOnlyPart *part, QWidget* window,
60  bool removeReferrer, bool trustedSource, bool hideErrorDialog )
61  : KRun( url, window, 0 /*mode*/, false /*is_local_file known*/, false /* no GUI */ ),
62  d(new BrowserRunPrivate)
63 {
64  d->m_bHideErrorDialog = hideErrorDialog;
65  d->m_bRemoveReferrer = removeReferrer;
66  d->m_bTrustedSource = trustedSource;
67  d->m_args = args;
68  d->m_browserArgs = browserArgs;
69  d->m_part = part;
70  d->m_window = window;
71 }
72 
73 BrowserRun::~BrowserRun()
74 {
75  delete d;
76 }
77 
78 KParts::ReadOnlyPart* BrowserRun::part() const
79 {
80  return d->m_part;
81 }
82 
83 KUrl BrowserRun::url() const
84 {
85  return KRun::url();
86 }
87 
88 void BrowserRun::init()
89 {
90  if ( d->m_bHideErrorDialog )
91  {
92  // ### KRun doesn't call a virtual method when it finds out that the URL
93  // is either malformed, or points to a non-existing local file...
94  // So we need to reimplement some of the checks, to handle d->m_bHideErrorDialog
95  if ( !KRun::url().isValid() ) {
96  redirectToError( KIO::ERR_MALFORMED_URL, KRun::url().url() );
97  return;
98  }
99  if ( !isLocalFile() && !hasError() && KRun::url().isLocalFile() )
100  setIsLocalFile( true );
101 
102  if ( isLocalFile() ) {
103  KDE_struct_stat buff;
104  if ( KDE::stat( KRun::url().toLocalFile(), &buff ) == -1 )
105  {
106  kDebug(1000) << KRun::url().toLocalFile() << "doesn't exist.";
107  redirectToError( KIO::ERR_DOES_NOT_EXIST, KRun::url().toLocalFile() );
108  return;
109  }
110  setMode( buff.st_mode ); // while we're at it, save it for KRun::init() to use it
111  }
112  }
113  KRun::init();
114 }
115 
116 void BrowserRun::scanFile()
117 {
118  kDebug(1000) << KRun::url();
119 
120  // Let's check for well-known extensions
121  // Not when there is a query in the URL, in any case.
122  // Optimization for http/https, findByURL doesn't trust extensions over http.
123  QString protocol = KRun::url().protocol();
124 
125  if (!KProtocolInfo::proxiedBy(protocol).isEmpty()) {
126  QString dummy;
127  protocol = KProtocolManager::slaveProtocol(KRun::url(), dummy);
128  }
129 
130  if ( KRun::url().query().isEmpty() && !protocol.startsWith(QLatin1String("http")))
131  {
132  KMimeType::Ptr mime = KMimeType::findByUrl( KRun::url() );
133  Q_ASSERT( mime );
134  if ( !mime->isDefault() || isLocalFile() )
135  {
136  kDebug(1000) << "MIME TYPE is" << mime->name();
137  mimeTypeDetermined( mime->name() );
138  return;
139  }
140  }
141 
142  QMap<QString, QString>& metaData = d->m_args.metaData();
143  if ( d->m_part ) {
144  const QString proto = d->m_part->url().protocol();
145 
146  if (proto == "https" || proto == "webdavs") {
147  metaData.insert("main_frame_request", "TRUE" );
148  metaData.insert("ssl_was_in_use", "TRUE" );
149  // metaData.insert("ssl_activate_warnings", "TRUE" );
150  } else if (proto == "http" || proto == "webdav") {
151  // metaData.insert("ssl_activate_warnings", "TRUE" );
152  metaData.insert("ssl_was_in_use", "FALSE" );
153  }
154 
155  // Set the PropagateHttpHeader meta-data if it has not already been set...
156  if (!metaData.contains("PropagateHttpHeader"))
157  metaData.insert("PropagateHttpHeader", "TRUE");
158  }
159 
160  KIO::TransferJob *job;
161  if ( d->m_browserArgs.doPost() && KRun::url().protocol().startsWith(QLatin1String("http"))) {
162  job = KIO::http_post( KRun::url(), d->m_browserArgs.postData, KIO::HideProgressInfo );
163  job->addMetaData( "content-type", d->m_browserArgs.contentType() );
164  } else {
165  job = KIO::get(KRun::url(),
166  d->m_args.reload() ? KIO::Reload : KIO::NoReload,
167  KIO::HideProgressInfo);
168  }
169 
170  if ( d->m_bRemoveReferrer )
171  metaData.remove("referrer");
172 
173  job->addMetaData( metaData );
174  job->ui()->setWindow( d->m_window );
175  connect( job, SIGNAL(result(KJob*)),
176  this, SLOT(slotBrowserScanFinished(KJob*)));
177  connect( job, SIGNAL(mimetype(KIO::Job*,QString)),
178  this, SLOT(slotBrowserMimetype(KIO::Job*,QString)));
179  setJob( job );
180 }
181 
182 void BrowserRun::slotBrowserScanFinished(KJob *job)
183 {
184  kDebug(1000) << job->error();
185  if ( job->error() == KIO::ERR_IS_DIRECTORY )
186  {
187  // It is in fact a directory. This happens when HTTP redirects to FTP.
188  // Due to the "protocol doesn't support listing" code in BrowserRun, we
189  // assumed it was a file.
190  kDebug(1000) << "It is in fact a directory!";
191  // Update our URL in case of a redirection
192  KRun::setUrl( static_cast<KIO::TransferJob *>(job)->url() );
193  setJob( 0 );
194  mimeTypeDetermined( "inode/directory" );
195  }
196  else
197  {
198  if ( job->error() )
199  handleError( job );
200  else
201  KRun::slotScanFinished(job);
202  }
203 }
204 
205 static KMimeType::Ptr fixupMimeType (const QString& mimeType, const QString& fileName)
206 {
207  KMimeType::Ptr mime = KMimeType::mimeType(mimeType);
208  if ((!mime || mime->isDefault()) && !fileName.isEmpty()) {
209  mime = KMimeType::findByUrl(fileName, 0, false, true);
210  }
211  return mime;
212 }
213 
214 void BrowserRun::slotBrowserMimetype( KIO::Job *_job, const QString &type )
215 {
216  Q_ASSERT( _job == KRun::job() ); Q_UNUSED(_job)
217  KIO::TransferJob *job = static_cast<KIO::TransferJob *>(KRun::job());
218  // Update our URL in case of a redirection
219  //kDebug(1000) << "old URL=" << KRun::url();
220  //kDebug(1000) << "new URL=" << job->url();
221  setUrl( job->url() );
222 
223  if (job->isErrorPage()) {
224  d->m_mimeType = type;
225  handleError(job);
226  setJob( 0 );
227  } else {
228  kDebug(1000) << "found" << type << "for" << KRun::url();
229 
230  // Suggested filename given by the server (e.g. HTTP content-disposition)
231  // When set, we should really be saving instead of embedding
232  const QString suggestedFileName = job->queryMetaData("content-disposition-filename");
233  setSuggestedFileName(suggestedFileName); // store it (in KRun)
234  //kDebug(1000) << "suggestedFileName=" << suggestedFileName;
235  d->m_contentDisposition = job->queryMetaData("content-disposition-type");
236 
237  const QString modificationTime = job->queryMetaData("content-disposition-modification-date");
238  if (!modificationTime.isEmpty()) {
239  d->m_args.metaData().insert(QLatin1String("content-disposition-modification-date"), modificationTime);
240  }
241 
242  QMapIterator<QString,QString> it (job->metaData());
243  while (it.hasNext()) {
244  it.next();
245  if (it.key().startsWith(QLatin1String("ssl_"), Qt::CaseInsensitive))
246  d->m_args.metaData().insert(it.key(), it.value());
247  }
248 
249  // Make a copy to avoid a dead reference
250  QString _type = type;
251  job->putOnHold();
252  setJob( 0 );
253 
254  // If the current mime-type is the default mime-type, then attempt to
255  // determine the "real" mimetype from the file name.
256  KMimeType::Ptr mimePtr = fixupMimeType(_type, suggestedFileName.isEmpty() ? url().fileName() : suggestedFileName);
257  if (mimePtr && mimePtr->name() != _type) {
258  _type = mimePtr->name();
259  }
260 
261  mimeTypeDetermined( _type );
262  }
263 }
264 
265 BrowserRun::NonEmbeddableResult BrowserRun::handleNonEmbeddable(const QString& mimeType)
266 {
267  return handleNonEmbeddable(mimeType, NULL);
268 }
269 
270 BrowserRun::NonEmbeddableResult BrowserRun::handleNonEmbeddable(const QString& _mimeType, KService::Ptr* selectedService)
271 {
272  QString mimeType( _mimeType );
273  Q_ASSERT( !hasFinished() ); // only come here if the mimetype couldn't be embedded
274  // Support for saving remote files.
275  if ( mimeType != "inode/directory" && // dirs can't be saved
276  !KRun::url().isLocalFile() )
277  {
278  if ( isTextExecutable(mimeType) )
279  mimeType = QLatin1String("text/plain"); // view, don't execute
280  // ... -> ask whether to save
281  BrowserOpenOrSaveQuestion question(d->m_window, KRun::url(), mimeType);
282  question.setSuggestedFileName(suggestedFileName());
283  if (selectedService)
284  question.setFeatures(BrowserOpenOrSaveQuestion::ServiceSelection);
285  BrowserOpenOrSaveQuestion::Result res = question.askOpenOrSave();
286  if (res == BrowserOpenOrSaveQuestion::Save) {
287  save( KRun::url(), suggestedFileName() );
288  kDebug(1000) << "Save: returning Handled";
289  setFinished( true );
290  return Handled;
291  }
292  else if (res == BrowserOpenOrSaveQuestion::Cancel) {
293  // saving done or canceled
294  kDebug(1000) << "Cancel: returning Handled";
295  setFinished( true );
296  return Handled;
297  }
298  else // "Open" chosen (done by KRun::foundMimeType, called when returning NotHandled)
299  {
300  // If we were in a POST, we can't just pass a URL to an external application.
301  // We must save the data to a tempfile first.
302  if ( d->m_browserArgs.doPost() )
303  {
304  kDebug(1000) << "request comes from a POST, can't pass a URL to another app, need to save";
305  d->m_mimeType = mimeType;
306  QString extension;
307  QString fileName = suggestedFileName().isEmpty() ? KRun::url().fileName() : suggestedFileName();
308  int extensionPos = fileName.lastIndexOf( '.' );
309  if ( extensionPos != -1 )
310  extension = fileName.mid( extensionPos ); // keep the '.'
311  KTemporaryFile tempFile;
312  tempFile.setSuffix(extension);
313  tempFile.setAutoRemove(false);
314  tempFile.open();
315  KUrl destURL;
316  destURL.setPath( tempFile.fileName() );
317  KIO::Job *job = KIO::file_copy( KRun::url(), destURL, 0600, KIO::Overwrite );
318  job->ui()->setWindow(d->m_window);
319  connect( job, SIGNAL(result(KJob*)),
320  this, SLOT(slotCopyToTempFileResult(KJob*)) );
321  return Delayed; // We'll continue after the job has finished
322  }
323  if (selectedService && question.selectedService()) {
324  *selectedService = question.selectedService();
325  // KRun will use this when starting an app
326  KRun::setPreferredService(question.selectedService()->desktopEntryName());
327  }
328  }
329  }
330 
331  // Check if running is allowed
332  if ( !d->m_bTrustedSource && // ... and untrusted source...
333  !allowExecution( mimeType, KRun::url() ) ) // ...and the user said no (for executables etc.)
334  {
335  setFinished( true );
336  return Handled;
337  }
338 
339  KIO::Scheduler::publishSlaveOnHold(); // publish any slave on hold so it can be reused.
340  return NotHandled;
341 }
342 
343 //static
344 bool BrowserRun::allowExecution( const QString &mimeType, const KUrl &url )
345 {
346  if ( !KRun::isExecutable( mimeType ) )
347  return true;
348 
349  if ( !url.isLocalFile() ) // Don't permit to execute remote files
350  return false;
351 
352  return ( KMessageBox::warningContinueCancel( 0,
353  i18n( "Do you really want to execute '%1'?", url.prettyUrl() ),
354  i18n("Execute File?"), KGuiItem(i18n("Execute")) ) == KMessageBox::Continue );
355 }
356 
357 //static, deprecated
358 #ifndef KDE_NO_DEPRECATED
359 BrowserRun::AskSaveResult BrowserRun::askSave( const KUrl & url, KService::Ptr offer, const QString& mimeType, const QString & suggestedFileName )
360 {
361  Q_UNUSED(offer);
362  BrowserOpenOrSaveQuestion question(0, url, mimeType);
363  question.setSuggestedFileName(suggestedFileName);
364  const BrowserOpenOrSaveQuestion::Result result = question.askOpenOrSave();
365  return result == BrowserOpenOrSaveQuestion::Save ? Save
366  : BrowserOpenOrSaveQuestion::Open ? Open
367  : Cancel;
368 }
369 #endif
370 
371 //static, deprecated
372 #ifndef KDE_NO_DEPRECATED
373 BrowserRun::AskSaveResult BrowserRun::askEmbedOrSave( const KUrl & url, const QString& mimeType, const QString & suggestedFileName, int flags )
374 {
375  BrowserOpenOrSaveQuestion question(0, url, mimeType);
376  question.setSuggestedFileName(suggestedFileName);
377  const BrowserOpenOrSaveQuestion::Result result = question.askEmbedOrSave(flags);
378  return result == BrowserOpenOrSaveQuestion::Save ? Save
379  : BrowserOpenOrSaveQuestion::Embed ? Open
380  : Cancel;
381 }
382 #endif
383 
384 // Default implementation, overridden in KHTMLRun
385 void BrowserRun::save( const KUrl & url, const QString & suggestedFileName )
386 {
387  saveUrl(url, suggestedFileName, d->m_window, d->m_args);
388 }
389 
390 // static
391 void BrowserRun::simpleSave( const KUrl & url, const QString & suggestedFileName,
392  QWidget* window )
393 {
394  saveUrl(url, suggestedFileName, window, KParts::OpenUrlArguments());
395 }
396 
397 void KParts::BrowserRun::saveUrl(const KUrl & url, const QString & suggestedFileName,
398  QWidget* window, const KParts::OpenUrlArguments& args)
399 {
400  // DownloadManager <-> konqueror integration
401  // find if the integration is enabled
402  // the empty key means no integration
403  // only use the downloadmanager for non-local urls
404  if ( !url.isLocalFile() )
405  {
406  KConfigGroup cfg = KSharedConfig::openConfig("konquerorrc", KConfig::NoGlobals)->group("HTML Settings");
407  QString downloadManger = cfg.readPathEntry("DownloadManager", QString());
408  if (!downloadManger.isEmpty())
409  {
410  // then find the download manager location
411  kDebug(1000) << "Using: "<<downloadManger <<" as Download Manager";
412  QString cmd=KStandardDirs::findExe(downloadManger);
413  if (cmd.isEmpty())
414  {
415  QString errMsg=i18n("The Download Manager (%1) could not be found in your $PATH ", downloadManger);
416  QString errMsgEx= i18n("Try to reinstall it \n\nThe integration with Konqueror will be disabled.");
417  KMessageBox::detailedSorry(0,errMsg,errMsgEx);
418  cfg.writePathEntry("DownloadManager",QString());
419  cfg.sync ();
420  }
421  else
422  {
423  // ### suggestedFileName not taken into account. Fix this (and
424  // the duplicated code) with shiny new KDownload class for 3.2 (pfeiffer)
425  // Until the shiny new class comes about, send the suggestedFileName
426  // along with the actual URL to download. (DA)
427  cmd += ' ' + KShell::quoteArg(url.url());
428  if ( !suggestedFileName.isEmpty() )
429  cmd += ' ' + KShell::quoteArg(suggestedFileName);
430 
431  kDebug(1000) << "Calling command" << cmd;
432  // slave is already on hold (slotBrowserMimetype())
433  KIO::Scheduler::publishSlaveOnHold();
434  KRun::runCommand(cmd, window);
435  return;
436  }
437  }
438  }
439 
440  // no download manager available, let's do it ourself
441  KFileDialog *dlg = new KFileDialog( QString(), QString() /*all files*/,
442  window);
443  dlg->setOperationMode( KFileDialog::Saving );
444  dlg->setCaption(i18n("Save As"));
445  dlg->setConfirmOverwrite(true);
446 
447  QString name;
448  if ( !suggestedFileName.isEmpty() )
449  name = suggestedFileName;
450  else
451  name = url.fileName(KUrl::ObeyTrailingSlash); // can be empty, e.g. in case http://www.kde.org/
452 
453  dlg->setSelection(name);
454  if ( dlg->exec() )
455  {
456  KUrl destURL( dlg->selectedUrl() );
457  if ( destURL.isValid() )
458  {
459  saveUrlUsingKIO(url, destURL, window, args.metaData());
460  }
461  }
462  delete dlg;
463 }
464 
465 void BrowserRun::saveUrlUsingKIO(const KUrl & srcUrl, const KUrl& destUrl,
466  QWidget* window, const QMap<QString, QString> &metaData)
467 {
468  KIO::FileCopyJob *job = KIO::file_copy(srcUrl, destUrl, -1, KIO::Overwrite);
469 
470  const QString modificationTime = metaData[QLatin1String("content-disposition-modification-date")];
471  if (!modificationTime.isEmpty()) {
472  job->setModificationTime(KDateTime::fromString(modificationTime, KDateTime::RFCDate).dateTime());
473  }
474  job->setMetaData(metaData);
475  job->addMetaData("MaxCacheSize", "0"); // Don't store in http cache.
476  job->addMetaData("cache", "cache"); // Use entry from cache if available.
477  job->ui()->setWindow(window);
478  job->ui()->setAutoErrorHandlingEnabled( true );
479  new DownloadJobWatcher(job, metaData);
480 }
481 
482 void BrowserRun::slotStatResult( KJob *job )
483 {
484  if ( job->error() ) {
485  kDebug(1000) << job->errorString();
486  handleError( job );
487  } else
488  KRun::slotStatResult( job );
489 }
490 
491 void BrowserRun::handleError( KJob * job )
492 {
493  if ( !job ) { // Shouldn't happen, see docu.
494  kWarning(1000) << "handleError called with job=0! hideErrorDialog=" << d->m_bHideErrorDialog;
495  return;
496  }
497 
498  KIO::TransferJob *tjob = qobject_cast<KIO::TransferJob *>(job);
499  if (tjob && tjob->isErrorPage() && !job->error()) {
500  // The default handling of error pages is to show them like normal pages
501  // But this is done here in handleError so that KHTMLRun can reimplement it
502  tjob->putOnHold();
503  setJob(0);
504  if (!d->m_mimeType.isEmpty())
505  mimeTypeDetermined(d->m_mimeType);
506  return;
507  }
508 
509  if (d->m_bHideErrorDialog && job->error() != KIO::ERR_NO_CONTENT)
510  {
511  redirectToError( job->error(), job->errorText() );
512  return;
513  }
514 
515  // Reuse code in KRun, to benefit from d->m_showingError etc.
516  KRun::slotStatResult( job );
517 }
518 
519 // static
520 KUrl BrowserRun::makeErrorUrl(int error, const QString& errorText, const QString& initialUrl)
521 {
522  /*
523  * The format of the error:/ URL is error:/?query#url,
524  * where two variables are passed in the query:
525  * error = int kio error code, errText = QString error text from kio
526  * The sub-url is the URL that we were trying to open.
527  */
528  KUrl newURL(QString("error:/?error=%1&errText=%2")
529  .arg( error )
530  .arg( QString::fromUtf8( QUrl::toPercentEncoding( errorText ) ) ) );
531 
532  QString cleanedOrigUrl = initialUrl;
533  KUrl runURL = cleanedOrigUrl;
534  if (runURL.isValid()) {
535  runURL.setPass( QString() ); // don't put the password in the error URL
536  cleanedOrigUrl = runURL.url();
537  }
538 
539  newURL.setFragment(cleanedOrigUrl);
540  return newURL;
541 
542  // The kde3 approach broke with invalid urls, now that they become empty in qt4.
543  //KUrl::List lst;
544  //lst << newURL << runURL;
545  //return KUrl::join(lst);
546 }
547 
548 void BrowserRun::redirectToError( int error, const QString& errorText )
549 {
555  KRun::setUrl(makeErrorUrl(error, errorText, url().url()));
556  setJob( 0 );
557  mimeTypeDetermined( "text/html" );
558 }
559 
560 void BrowserRun::slotCopyToTempFileResult(KJob *job)
561 {
562  if ( job->error() ) {
563  job->uiDelegate()->showErrorMessage();
564  } else {
565  // Same as KRun::foundMimeType but with a different URL
566  (void) (KRun::runUrl( static_cast<KIO::FileCopyJob *>(job)->destUrl(), d->m_mimeType, d->m_window ));
567  }
568  setError( true ); // see above
569  setFinished( true );
570 }
571 
572 bool BrowserRun::isTextExecutable( const QString &mimeType )
573 {
574  return ( mimeType == "application/x-desktop" ||
575  mimeType == "application/x-shellscript" );
576 }
577 
578 bool BrowserRun::hideErrorDialog() const
579 {
580  return d->m_bHideErrorDialog;
581 }
582 
583 QString BrowserRun::contentDisposition() const
584 {
585  return d->m_contentDisposition;
586 }
587 
588 bool BrowserRun::serverSuggestsSave() const
589 {
590  // RfC 2183, section 2.8:
591  // Unrecognized disposition types should be treated as `attachment'.
592  return !contentDisposition().isEmpty() && (contentDisposition() != "inline");
593 }
594 
595 KParts::OpenUrlArguments& KParts::BrowserRun::arguments()
596 {
597  return d->m_args;
598 }
599 
600 KParts::BrowserArguments& KParts::BrowserRun::browserArguments()
601 {
602  return d->m_browserArgs;
603 }
604 
605 #include "browserrun.moc"
606 #include "browserrun_p.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2013 The KDE developers.
Generated on Tue Jul 16 2013 17:51:38 by doxygen 1.8.1.1 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KParts

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

kdelibs-4.10.5 API Reference

Skip menu "kdelibs-4.10.5 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
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
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