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

KDEWebKit

kwebpage.cpp
Go to the documentation of this file.
00001 /*
00002  * This file is part of the KDE project.
00003  *
00004  * Copyright (C) 2008 Dirk Mueller <mueller@kde.org>
00005  * Copyright (C) 2008 Urs Wolfer <uwolfer @ kde.org>
00006  * Copyright (C) 2008 Michael Howell <mhowell123@gmail.com>
00007  * Copyright (C) 2009,2010 Dawit Alemayehu <adawit@kde.org>
00008  *
00009  * This library is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Library General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 2 of the License, or (at your option) any later version.
00013  *
00014  * This library is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Library General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Library General Public License
00020  * along with this library; see the file COPYING.LIB.  If not, write to
00021  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00022  * Boston, MA 02110-1301, USA.
00023  *
00024  */
00025 
00026 // Own
00027 #include "kwebpage.h"
00028 #include "kwebwallet.h"
00029 
00030 // Local
00031 #include "kwebpluginfactory.h"
00032 
00033 // KDE
00034 #include <kaction.h>
00035 #include <kfiledialog.h>
00036 #include <kprotocolmanager.h>
00037 #include <kjobuidelegate.h>
00038 #include <krun.h>
00039 #include <kstandarddirs.h>
00040 #include <kstandardshortcut.h>
00041 #include <kurl.h>
00042 #include <kdebug.h>
00043 #include <kshell.h>
00044 #include <kmimetypetrader.h>
00045 #include <klocalizedstring.h>
00046 #include <ktemporaryfile.h>
00047 #include <kio/accessmanager.h>
00048 #include <kio/job.h>
00049 #include <kio/copyjob.h>
00050 #include <kio/jobuidelegate.h>
00051 #include <kio/renamedialog.h>
00052 #include <kparts/browseropenorsavequestion.h>
00053 
00054 // Qt
00055 #include <QtCore/QPointer>
00056 #include <QtCore/QFileInfo>
00057 #include <QtCore/QCoreApplication>
00058 #include <QtWebKit/QWebFrame>
00059 #include <QtNetwork/QNetworkReply>
00060 
00061 
00062 #define QL1S(x)  QLatin1String(x)
00063 #define QL1C(x)  QLatin1Char(x)
00064 
00065 static void reloadRequestWithoutDisposition (QNetworkReply* reply)
00066 {
00067     QNetworkRequest req (reply->request());
00068     req.setRawHeader("x-kdewebkit-ignore-disposition", "true");
00069 
00070     QWebFrame* frame = qobject_cast<QWebFrame*> (req.originatingObject());
00071     if (!frame)
00072         return;
00073 
00074     frame->load(req);
00075 }
00076 
00077 static bool isMimeTypeAssociatedWithSelf(const KService::Ptr &offer)
00078 {
00079     if (!offer)
00080         return false;
00081 
00082     kDebug(800) << offer->desktopEntryName();
00083 
00084     const QString& appName = QCoreApplication::applicationName();
00085 
00086     if (appName == offer->desktopEntryName() || offer->exec().trimmed().startsWith(appName))
00087         return true;
00088 
00089     // konqueror exception since it uses kfmclient to open html content...
00090     if (appName == QL1S("konqueror") && offer->exec().trimmed().startsWith(QL1S("kfmclient")))
00091         return true;
00092 
00093     return false;
00094 }
00095 
00096 static void extractMimeType(const QNetworkReply* reply, QString& mimeType)
00097 {
00098     mimeType.clear();
00099     const KIO::MetaData& metaData = reply->attribute(static_cast<QNetworkRequest::Attribute>(KIO::AccessManager::MetaData)).toMap();
00100     if (metaData.contains(QL1S("content-type")))
00101         mimeType = metaData.value(QL1S("content-type"));
00102 
00103     if (!mimeType.isEmpty())
00104         return;
00105 
00106     if (!reply->hasRawHeader("Content-Type"))
00107         return;
00108 
00109     const QString value (QL1S(reply->rawHeader("Content-Type").simplified().constData()));
00110     const int index = value.indexOf(QL1C(';'));
00111     mimeType = ((index == -1) ? value : value.left(index));
00112 }
00113 
00114 static bool downloadResource (const KUrl& srcUrl, const QString& suggestedName = QString(),
00115                               QWidget* parent = 0, const KIO::MetaData& metaData = KIO::MetaData())
00116 {
00117     const QString fileName = suggestedName.isEmpty() ? srcUrl.fileName() : suggestedName;
00118     // convert filename to URL using fromPath to avoid trouble with ':' in filenames (#184202)
00119     KUrl destUrl = KFileDialog::getSaveFileName(KUrl::fromPath(fileName), QString(), parent);
00120     if (!destUrl.isValid())
00121         return false;
00122 
00123     // Using KIO::copy rather than file_copy, to benefit from "dest already exists" dialogs.
00124     KIO::Job *job = KIO::copy(srcUrl, destUrl);
00125 
00126     if (!metaData.isEmpty())
00127         job->setMetaData(metaData);
00128 
00129     job->addMetaData(QL1S("MaxCacheSize"), QL1S("0")); // Don't store in http cache.
00130     job->addMetaData(QL1S("cache"), QL1S("cache")); // Use entry from cache if available.
00131     job->ui()->setWindow((parent ? parent->window() : 0));
00132     job->ui()->setAutoErrorHandlingEnabled(true);
00133     return true;
00134 }
00135 
00136 static bool isReplyStatusOk(const QNetworkReply* reply)
00137 {
00138     if (!reply || reply->error() != QNetworkReply::NoError)
00139         return false;
00140 
00141     // Check HTTP status code only for http and webdav protocols...
00142     const QString scheme = reply->url().scheme();
00143     if (scheme.startsWith(QLatin1String("http"), Qt::CaseInsensitive) ||
00144         scheme.startsWith(QLatin1String("webdav"), Qt::CaseInsensitive)) {
00145         bool ok = false;
00146         const int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(&ok);
00147         if (!ok || statusCode < 200 || statusCode > 299)
00148             return false;
00149     }
00150 
00151     return true;
00152 }
00153 
00154 class KWebPage::KWebPagePrivate
00155 {
00156 public:
00157     KWebPagePrivate() : inPrivateBrowsingMode(false) {}
00158     void _k_copyResultToTempFile(KJob * job)
00159     {
00160         if ( job->error() ) {
00161             job->uiDelegate()->showErrorMessage();
00162             return;
00163         }
00164         // Same as KRun::foundMimeType but with a different URL
00165         (void)KRun::runUrl(static_cast<KIO::FileCopyJob *>(job)->destUrl(), mimeType, window);
00166     }
00167 
00168     QPointer<QWidget> window;
00169     QString mimeType;
00170     QPointer<KWebWallet> wallet;
00171     bool inPrivateBrowsingMode;
00172 };
00173 
00174 static void setActionIcon(QAction* action, const QIcon& icon)
00175 {
00176     if (action) {
00177         action->setIcon(icon);
00178     }
00179 }
00180 
00181 static void setActionShortcut(QAction* action, const KShortcut& shortcut)
00182 {
00183     if (action) {
00184         action->setShortcuts(shortcut.toList());
00185     }
00186 }
00187 
00188 KWebPage::KWebPage(QObject *parent, Integration flags)
00189          :QWebPage(parent), d(new KWebPagePrivate)
00190 { 
00191     // KDE KParts integration for <embed> tag...
00192     if (!flags || (flags & KPartsIntegration))
00193         setPluginFactory(new KWebPluginFactory(this));
00194 
00195     QWidget *parentWidget = qobject_cast<QWidget*>(parent);
00196     QWidget *window = parentWidget ? parentWidget->window() : 0;
00197 
00198     // KDE IO (KIO) integration...
00199     if (!flags || (flags & KIOIntegration)) {
00200         KIO::Integration::AccessManager *manager = new KIO::Integration::AccessManager(this);
00201         // Disable QtWebKit's internal cache to avoid duplication with the one in KIO...
00202         manager->setCache(0);
00203         manager->setWindow(window);
00204         manager->setEmitReadyReadOnMetaDataChange(true);
00205         setNetworkAccessManager(manager);
00206     }
00207 
00208     // KWallet integration...
00209     if (!flags || (flags & KWalletIntegration)) {
00210         setWallet(new KWebWallet(0, (window ? window->winId() : 0) ));
00211     }
00212 
00213     setActionIcon(action(Back), KIcon("go-previous"));
00214     setActionIcon(action(Forward), KIcon("go-next"));
00215     setActionIcon(action(Reload), KIcon("view-refresh"));
00216     setActionIcon(action(Stop), KIcon("process-stop"));
00217     setActionIcon(action(Cut), KIcon("edit-cut"));
00218     setActionIcon(action(Copy), KIcon("edit-copy"));
00219     setActionIcon(action(Paste), KIcon("edit-paste"));
00220     setActionIcon(action(Undo), KIcon("edit-undo"));
00221     setActionIcon(action(Redo), KIcon("edit-redo"));
00222     setActionIcon(action(InspectElement), KIcon("view-process-all"));
00223     setActionIcon(action(OpenLinkInNewWindow), KIcon("window-new"));
00224     setActionIcon(action(OpenFrameInNewWindow), KIcon("window-new"));
00225     setActionIcon(action(OpenImageInNewWindow), KIcon("window-new"));
00226     setActionIcon(action(CopyLinkToClipboard), KIcon("edit-copy"));
00227     setActionIcon(action(CopyImageToClipboard), KIcon("edit-copy"));
00228     setActionIcon(action(ToggleBold), KIcon("format-text-bold"));
00229     setActionIcon(action(ToggleItalic), KIcon("format-text-italic"));
00230     setActionIcon(action(ToggleUnderline), KIcon("format-text-underline"));
00231     setActionIcon(action(DownloadLinkToDisk), KIcon("document-save"));
00232     setActionIcon(action(DownloadImageToDisk), KIcon("document-save"));
00233 
00234     settings()->setWebGraphic(QWebSettings::MissingPluginGraphic, KIcon("preferences-plugin").pixmap(32, 32));
00235     settings()->setWebGraphic(QWebSettings::MissingImageGraphic, KIcon("image-missing").pixmap(32, 32));
00236     settings()->setWebGraphic(QWebSettings::DefaultFrameIconGraphic, KIcon("applications-internet").pixmap(32, 32));
00237 
00238     setActionShortcut(action(Back), KStandardShortcut::back());
00239     setActionShortcut(action(Forward), KStandardShortcut::forward());
00240     setActionShortcut(action(Reload), KStandardShortcut::reload());
00241     setActionShortcut(action(Stop), KShortcut(QKeySequence(Qt::Key_Escape)));
00242     setActionShortcut(action(Cut), KStandardShortcut::cut());
00243     setActionShortcut(action(Copy), KStandardShortcut::copy());
00244     setActionShortcut(action(Paste), KStandardShortcut::paste());
00245     setActionShortcut(action(Undo), KStandardShortcut::undo());
00246     setActionShortcut(action(Redo), KStandardShortcut::redo());
00247     setActionShortcut(action(SelectAll), KStandardShortcut::selectAll());
00248 }
00249 
00250 KWebPage::~KWebPage()
00251 {
00252     delete d;
00253 }
00254 
00255 bool KWebPage::isExternalContentAllowed() const
00256 {
00257     KIO::AccessManager *manager = qobject_cast<KIO::AccessManager*>(networkAccessManager());
00258     if (manager)
00259         return manager->isExternalContentAllowed();
00260     return true;
00261 }
00262 
00263 KWebWallet *KWebPage::wallet() const
00264 {
00265     return d->wallet;
00266 }
00267 
00268 void KWebPage::setAllowExternalContent(bool allow)
00269 {
00270     KIO::AccessManager *manager = qobject_cast<KIO::AccessManager*>(networkAccessManager());
00271     if (manager)
00272       manager->setExternalContentAllowed(allow);
00273 }
00274 
00275 void KWebPage::setWallet(KWebWallet* wallet)
00276 {
00277     // Delete the current wallet if this object is its parent...
00278     if (d->wallet && this == d->wallet->parent())
00279         delete d->wallet;
00280 
00281     d->wallet = wallet;
00282 
00283     if (d->wallet)
00284         d->wallet->setParent(this);
00285 }
00286 
00287 void KWebPage::downloadRequest(const QNetworkRequest &request)
00288 {
00289     downloadResource(request.url(), QString(), view(),
00290                      request.attribute(static_cast<QNetworkRequest::Attribute>(KIO::AccessManager::MetaData)).toMap());
00291 }
00292 
00293 void KWebPage::downloadUrl(const KUrl &url)
00294 {
00295     downloadResource(url, QString(), view());
00296 }
00297 
00298 void KWebPage::downloadResponse(QNetworkReply *reply)
00299 {
00300     Q_ASSERT(reply);
00301 
00302     if (!reply)
00303         return;
00304 
00305     // Put the job on hold only for the protocols we know about (read: http).
00306     KIO::Integration::AccessManager::putReplyOnHold(reply);
00307 
00308     QString mimeType;
00309     KIO::MetaData metaData;
00310 
00311     if (handleReply(reply, &mimeType, &metaData)) {
00312         return;
00313     }
00314 
00315     const KUrl replyUrl (reply->url());
00316     QWidget* topLevelWindow = view() ? view()->window() : 0;
00317 
00318     // Ask KRun to handle the response when mimetype is unknown
00319     if (mimeType.isEmpty()) {
00320         (void)new KRun(replyUrl, topLevelWindow, 0 , replyUrl.isLocalFile());
00321         return;
00322     }
00323 
00324     // Ask KRun::runUrl to handle the response when mimetype is inode/*
00325     if (mimeType.startsWith(QL1S("inode/"), Qt::CaseInsensitive) &&
00326         KRun::runUrl(replyUrl, mimeType, topLevelWindow, false, false,
00327                      metaData.value(QL1S("content-disposition-filename")))) {
00328         return;
00329     }
00330 }
00331 
00332 QString KWebPage::sessionMetaData(const QString &key) const
00333 {
00334     QString value;
00335 
00336     KIO::Integration::AccessManager *manager = qobject_cast<KIO::Integration::AccessManager *>(networkAccessManager());
00337     if (manager)
00338         value = manager->sessionMetaData().value(key);
00339 
00340     return value;
00341 }
00342 
00343 QString KWebPage::requestMetaData(const QString &key) const
00344 {
00345     QString value;
00346 
00347     KIO::Integration::AccessManager *manager = qobject_cast<KIO::Integration::AccessManager *>(networkAccessManager());
00348     if (manager)
00349         value = manager->requestMetaData().value(key);
00350 
00351     return value;
00352 }
00353 
00354 void KWebPage::setSessionMetaData(const QString &key, const QString &value)
00355 {
00356     KIO::Integration::AccessManager *manager = qobject_cast<KIO::Integration::AccessManager *>(networkAccessManager());
00357     if (manager)
00358         manager->sessionMetaData()[key] = value;
00359 }
00360 
00361 void KWebPage::setRequestMetaData(const QString &key, const QString &value)
00362 {
00363     KIO::Integration::AccessManager *manager = qobject_cast<KIO::Integration::AccessManager *>(networkAccessManager());
00364     if (manager)
00365         manager->requestMetaData()[key] = value;
00366 }
00367 
00368 void KWebPage::removeSessionMetaData(const QString &key)
00369 {
00370     KIO::Integration::AccessManager *manager = qobject_cast<KIO::Integration::AccessManager *>(networkAccessManager());
00371     if (manager)
00372         manager->sessionMetaData().remove(key);
00373 }
00374 
00375 void KWebPage::removeRequestMetaData(const QString &key)
00376 {
00377     KIO::Integration::AccessManager *manager = qobject_cast<KIO::Integration::AccessManager *>(networkAccessManager());
00378     if (manager)
00379         manager->requestMetaData().remove(key);
00380 }
00381 
00382 QString KWebPage::userAgentForUrl(const QUrl& _url) const
00383 {
00384     const KUrl url(_url);
00385     const QString userAgent = KProtocolManager::userAgentForHost((url.isLocalFile() ? QL1S("localhost") : url.host()));
00386 
00387     if (userAgent == KProtocolManager::defaultUserAgent())
00388         return QWebPage::userAgentForUrl(_url);
00389 
00390     return userAgent;
00391 }
00392 
00393 static void setDisableCookieJarStorage(QNetworkAccessManager* manager, bool status)
00394 {
00395     if (manager) {
00396         KIO::Integration::CookieJar *cookieJar = manager ? qobject_cast<KIO::Integration::CookieJar*>(manager->cookieJar()) : 0;
00397         if (cookieJar) {
00398             //kDebug(800) << "Store cookies ?" << !status;
00399             cookieJar->setDisableCookieStorage(status);
00400         }
00401     }
00402 }
00403 
00404 bool KWebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, NavigationType type)
00405 {
00406     kDebug(800) << "url:" << request.url() << ", type:" << type << ", frame:" << frame;
00407 
00408     if (frame && d->wallet && type == QWebPage::NavigationTypeFormSubmitted)
00409         d->wallet->saveFormData(frame);
00410 
00411     // Make sure nothing is cached when private browsing mode is enabled...
00412     if (settings()->testAttribute(QWebSettings::PrivateBrowsingEnabled)) {
00413         if (!d->inPrivateBrowsingMode) {
00414             setDisableCookieJarStorage(networkAccessManager(), true);
00415             setSessionMetaData(QL1S("no-cache"), QL1S("true"));
00416             d->inPrivateBrowsingMode = true;
00417         }
00418     } else  {
00419         if (d->inPrivateBrowsingMode) {
00420             setDisableCookieJarStorage(networkAccessManager(), false);
00421             removeSessionMetaData(QL1S("no-cache"));
00422             d->inPrivateBrowsingMode = false;
00423         }
00424     }
00425 
00426     /*
00427       If the navigation request is from the main frame, set the cross-domain
00428       meta-data value to the current url for proper integration with KCookieJar...
00429     */
00430     if (frame == mainFrame() && type != QWebPage::NavigationTypeReload)
00431         setSessionMetaData(QL1S("cross-domain"), request.url().toString());
00432 
00433     return QWebPage::acceptNavigationRequest(frame, request, type);
00434 }
00435 
00436 bool KWebPage::handleReply(QNetworkReply* reply, QString* contentType, KIO::MetaData* metaData)
00437 {
00438     // Reply url...
00439     const KUrl replyUrl (reply->url());
00440 
00441     // Get the top level window...
00442     QWidget* topLevelWindow = view() ? view()->window() : 0;
00443 
00444     // Get suggested file name...
00445     const KIO::MetaData& data = reply->attribute(static_cast<QNetworkRequest::Attribute>(KIO::AccessManager::MetaData)).toMap();
00446     const QString suggestedFileName = data.value(QL1S("content-disposition-filename"));
00447     if (metaData) {
00448         *metaData = data;
00449     }
00450 
00451     // Get the mime-type...
00452     QString mimeType;
00453     extractMimeType(reply, mimeType);
00454     if (contentType) {
00455         *contentType = mimeType;
00456     }
00457 
00458     // Let the calling function deal with handling empty or inode/* mimetypes...
00459     if (mimeType.isEmpty() || mimeType.startsWith(QL1S("inode/"), Qt::CaseInsensitive)) {
00460         return false;
00461     }
00462 
00463     // Convert executable text files to plain text...
00464     if (KParts::BrowserRun::isTextExecutable(mimeType))
00465         mimeType = QL1S("text/plain");
00466 
00467     //kDebug(800) << "Content-disposition:" << suggestedFileName;
00468     //kDebug(800) << "Got unsupported content of type:" << mimeType << "URL:" << replyUrl;
00469     //kDebug(800) << "Error code:" << reply->error() << reply->errorString();
00470 
00471     if (isReplyStatusOk(reply)) {
00472         KParts::BrowserOpenOrSaveQuestion::Result result;
00473         KParts::BrowserOpenOrSaveQuestion dlg(topLevelWindow, replyUrl, mimeType);
00474         dlg.setSuggestedFileName(suggestedFileName);
00475         dlg.setFeatures(KParts::BrowserOpenOrSaveQuestion::ServiceSelection);
00476         result = dlg.askOpenOrSave();
00477 
00478         switch (result) {
00479         case KParts::BrowserOpenOrSaveQuestion::Open:
00480             // Handle Post operations that return content...
00481             if (reply->operation() == QNetworkAccessManager::PostOperation) {
00482                 d->mimeType = mimeType;
00483                 d->window = topLevelWindow;
00484                 QFileInfo finfo (suggestedFileName.isEmpty() ? replyUrl.fileName() : suggestedFileName);
00485                 KTemporaryFile tempFile;
00486                 tempFile.setSuffix(QL1C('.') + finfo.suffix());
00487                 tempFile.setAutoRemove(false);
00488                 tempFile.open();
00489                 KUrl destUrl;
00490                 destUrl.setPath(tempFile.fileName());
00491                 KIO::Job *job = KIO::file_copy(replyUrl, destUrl, 0600, KIO::Overwrite);
00492                 job->ui()->setWindow(topLevelWindow);
00493                 job->ui()->setAutoErrorHandlingEnabled(true);
00494                 connect(job, SIGNAL(result(KJob*)),
00495                         this, SLOT(_k_copyResultToTempFile(KJob*)));
00496                 return true;
00497             }
00498 
00499             // Ask before running any executables...
00500             if (KParts::BrowserRun::allowExecution(mimeType, replyUrl)) {
00501                 KService::Ptr offer = dlg.selectedService();
00502                 // HACK: The check below is necessary to break an infinite
00503                 // recursion that occurs whenever this function is called as a result
00504                 // of receiving content that can be rendered by the app using this engine.
00505                 // For example a text/html header that containing a content-disposition
00506                 // header is received by the app using this class.
00507                 if (isMimeTypeAssociatedWithSelf(offer)) {
00508                     reloadRequestWithoutDisposition(reply);
00509                 } else {
00510                     KUrl::List list;
00511                     list.append(replyUrl);
00512                     bool success = false;
00513                     // kDebug(800) << "Suggested file name:" << suggestedFileName;
00514                     if (offer) {
00515                         success = KRun::run(*offer, list, topLevelWindow , false, suggestedFileName);
00516                     } else {
00517                         success = KRun::displayOpenWithDialog(list, topLevelWindow, false, suggestedFileName);
00518                     }
00519                     // For non KIO apps and cancelled Open With dialog, remove slave on hold.
00520                     if (!success || (offer && !offer->categories().contains(QL1S("KDE")))) {
00521                         KIO::SimpleJob::removeOnHold(); // Remove any slave-on-hold...
00522                     }
00523                 }
00524                 return true;
00525             }
00526             // TODO: Instead of silently failing when allowExecution fails, notify
00527             // the user why the requested action cannot be fulfilled...
00528             break;
00529         case KParts::BrowserOpenOrSaveQuestion::Save:
00530             // Do not download local files...
00531             if (!replyUrl.isLocalFile()) {
00532                 QString downloadCmd (reply->property("DownloadManagerExe").toString());
00533                 if (!downloadCmd.isEmpty()) {
00534                     downloadCmd += QLatin1Char(' ');
00535                     downloadCmd += KShell::quoteArg(replyUrl.url());
00536                     if (!suggestedFileName.isEmpty()) {
00537                         downloadCmd += QLatin1Char(' ');
00538                         downloadCmd += KShell::quoteArg(suggestedFileName);
00539                     }
00540                     // kDebug(800) << "download command:" << downloadCmd;
00541                     if (KRun::runCommand(downloadCmd, view()))
00542                         return true;
00543                 }
00544                 return downloadResource(replyUrl, suggestedFileName, topLevelWindow);
00545             }
00546             return true;
00547         case KParts::BrowserOpenOrSaveQuestion::Cancel:
00548         default:
00549             return true;
00550         }
00551     } else {
00552         KService::Ptr offer = KMimeTypeTrader::self()->preferredService(mimeType);
00553         if (isMimeTypeAssociatedWithSelf(offer)) {
00554             reloadRequestWithoutDisposition(reply);
00555             return true;
00556         }
00557     }
00558 
00559     return false;
00560 }
00561 
00562 #include "kwebpage.moc"
00563 
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Wed May 2 2012 18:47:57 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDEWebKit

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

kdelibs-4.8.3 API Reference

Skip menu "kdelibs-4.8.3 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