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

KHTML

khtml_settings.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE project
00002    Copyright (C) 1999 David Faure <faure@kde.org>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017    Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include "khtml_settings.h"
00021 #include "khtmldefaults.h"
00022 
00023 #include <kconfig.h>
00024 #include <kconfiggroup.h>
00025 #include <kdebug.h>
00026 #include <kglobal.h>
00027 #include <kglobalsettings.h>
00028 #include <klocale.h>
00029 #include <kmessagebox.h>
00030 #include <khtml_filter_p.h>
00031 #include <kstandarddirs.h>
00032 #include <kjob.h>
00033 #include <kio/job.h>
00034 
00035 #include <QFile>
00036 #include <QFileInfo>
00037 #include <QtGui/QFontDatabase>
00038 #include <QByteArray>
00039 
00044 struct KPerDomainSettings {
00045     bool m_bEnableJava : 1;
00046     bool m_bEnableJavaScript : 1;
00047     bool m_bEnablePlugins : 1;
00048     // don't forget to maintain the bitfields as the enums grow
00049     KHTMLSettings::KJSWindowOpenPolicy m_windowOpenPolicy : 2;
00050     KHTMLSettings::KJSWindowStatusPolicy m_windowStatusPolicy : 1;
00051     KHTMLSettings::KJSWindowFocusPolicy m_windowFocusPolicy : 1;
00052     KHTMLSettings::KJSWindowMovePolicy m_windowMovePolicy : 1;
00053     KHTMLSettings::KJSWindowResizePolicy m_windowResizePolicy : 1;
00054 
00055 #ifdef DEBUG_SETTINGS
00056     void dump(const QString &infix = QString()) const {
00057       kDebug() << "KPerDomainSettings " << infix << " @" << this << ":";
00058       kDebug() << "  m_bEnableJava: " << m_bEnableJava;
00059       kDebug() << "  m_bEnableJavaScript: " << m_bEnableJavaScript;
00060       kDebug() << "  m_bEnablePlugins: " << m_bEnablePlugins;
00061       kDebug() << "  m_windowOpenPolicy: " << m_windowOpenPolicy;
00062       kDebug() << "  m_windowStatusPolicy: " << m_windowStatusPolicy;
00063       kDebug() << "  m_windowFocusPolicy: " << m_windowFocusPolicy;
00064       kDebug() << "  m_windowMovePolicy: " << m_windowMovePolicy;
00065       kDebug() << "  m_windowResizePolicy: " << m_windowResizePolicy;
00066     }
00067 #endif
00068 };
00069 
00070 QString *KHTMLSettings::avFamilies = 0;
00071 typedef QMap<QString,KPerDomainSettings> PolicyMap;
00072 
00073 // The "struct" that contains all the data. Must be copiable (no pointers).
00074 class KHTMLSettingsData
00075 {
00076 public:
00077     bool m_bChangeCursor : 1;
00078     bool m_bOpenMiddleClick : 1;
00079     bool m_underlineLink : 1;
00080     bool m_hoverLink : 1;
00081     bool m_bEnableJavaScriptDebug : 1;
00082     bool m_bEnableJavaScriptErrorReporting : 1;
00083     bool enforceCharset : 1;
00084     bool m_bAutoLoadImages : 1;
00085     bool m_bUnfinishedImageFrame : 1;
00086     bool m_formCompletionEnabled : 1;
00087     bool m_autoDelayedActionsEnabled : 1;
00088     bool m_jsErrorsEnabled : 1;
00089     bool m_follow_system_colors : 1;
00090     bool m_allowTabulation : 1;
00091     bool m_autoSpellCheck : 1;
00092     bool m_adFilterEnabled : 1;
00093     bool m_hideAdsEnabled : 1;
00094     bool m_jsPopupBlockerPassivePopup : 1;
00095     bool m_accessKeysEnabled : 1;
00096 
00097     // the virtual global "domain"
00098     KPerDomainSettings global;
00099 
00100     int m_fontSize;
00101     int m_minFontSize;
00102     int m_maxFormCompletionItems;
00103     KHTMLSettings::KAnimationAdvice m_showAnimations;
00104     KHTMLSettings::KSmoothScrollingMode m_smoothScrolling;
00105     KHTMLSettings::KDNSPrefetch m_dnsPrefetch;
00106 
00107     QString m_encoding;
00108     QString m_userSheet;
00109 
00110     QColor m_textColor;
00111     QColor m_baseColor;
00112     QColor m_linkColor;
00113     QColor m_vLinkColor;
00114 
00115     PolicyMap domainPolicy;
00116     QStringList fonts;
00117     QStringList defaultFonts;
00118 
00119     khtml::FilterSet adBlackList;
00120     khtml::FilterSet adWhiteList;
00121     QList< QPair< QString, QChar > > m_fallbackAccessKeysAssignments;
00122 };
00123 
00124 class KHTMLSettingsPrivate : public QObject, public KHTMLSettingsData
00125 {
00126     Q_OBJECT
00127 public:
00128 
00129     void adblockFilterLoadList(const QString& filename)
00130     {
00131         kDebug(6000) << "Loading filter list from" << filename;
00133         QFile file(filename);
00134         if (file.open(QIODevice::ReadOnly)) {
00135             QTextStream ts(&file);
00136             QString line = ts.readLine();
00137 #ifndef NDEBUG /// only count when compiled for debugging
00138             int whiteCounter = 0, blackCounter = 0;
00139 #endif // NDEBUG
00140             while (!line.isEmpty()) {
00142                 if (line.startsWith(QLatin1String("@@")))
00143                 {
00144 #ifndef NDEBUG
00145                     ++whiteCounter;
00146 #endif // NDEBUG
00147                     adWhiteList.addFilter(line);
00148                 }
00149                 else
00150                 {
00151 #ifndef NDEBUG
00152                     ++blackCounter;
00153 #endif // NDEBUG
00154                     adBlackList.addFilter(line);
00155                 }
00156 
00157                 line = ts.readLine();
00158             }
00159             file.close();
00160 
00161 #ifndef NDEBUG
00162             kDebug(6000) << "Filter list loaded" << whiteCounter << "white list entries and" << blackCounter << "black list entries";
00163 #endif // NDEBUG
00164         }
00165     }
00166 
00167 public slots:
00168     void adblockFilterResult(KJob *job)
00169     {
00170       KIO::StoredTransferJob *tJob = qobject_cast<KIO::StoredTransferJob*>(job);
00171       Q_ASSERT(tJob);
00172 
00173       if ( tJob->error() ) {
00174           kDebug(6000) << "Failed to download" << tJob->url() << "with message:" << tJob->errorText();
00175       }
00176       else if ( tJob->isErrorPage() ) { // 4XX error code
00177           kDebug(6000) << "Failed to fetch filter list" << tJob->url();
00178       }
00179       else {
00180           const QByteArray byteArray = tJob->data();
00181           const QString localFileName = tJob->property( "khtmlsettings_adBlock_filename" ).toString();
00182 
00183           QFile file(localFileName);
00184           if ( file.open(QFile::WriteOnly) ) {
00185               bool success = file.write(byteArray) == byteArray.size();
00186               file.close();
00187               if ( success )
00188                   adblockFilterLoadList(localFileName);
00189               else
00190                   kDebug(6000) << "Could not write" << byteArray.size() << "to file" << localFileName;
00191           }
00192           else
00193               kDebug(6000) << "Cannot open file" << localFileName << "for filter list";
00194       }
00195 
00196     }
00197 };
00198 
00199 
00203 static KPerDomainSettings &setup_per_domain_policy(
00204                 KHTMLSettingsPrivate* const d,
00205                 const QString &domain) {
00206   if (domain.isEmpty()) {
00207     kWarning(6000) << "setup_per_domain_policy: domain is empty";
00208   }
00209   const QString ldomain = domain.toLower();
00210   PolicyMap::iterator it = d->domainPolicy.find(ldomain);
00211   if (it == d->domainPolicy.end()) {
00212     // simply copy global domain settings (they should have been initialized
00213     // by this time)
00214     it = d->domainPolicy.insert(ldomain,d->global);
00215   }
00216   return *it;
00217 }
00218 
00219 
00220 KHTMLSettings::KJavaScriptAdvice KHTMLSettings::strToAdvice(const QString& _str)
00221 {
00222     return static_cast<KJavaScriptAdvice>(KParts::HtmlSettingsInterface::textToJavascriptAdvice(_str));
00223 }
00224 
00225 const char* KHTMLSettings::adviceToStr(KJavaScriptAdvice _advice)
00226 {
00227     return KParts::HtmlSettingsInterface::javascriptAdviceToText(static_cast<KParts::HtmlSettingsInterface::JavaScriptAdvice>(_advice));
00228 }
00229 
00230 
00231 void KHTMLSettings::splitDomainAdvice(const QString& configStr, QString &domain,
00232                                       KJavaScriptAdvice &javaAdvice, KJavaScriptAdvice& javaScriptAdvice)
00233 {
00234     KParts::HtmlSettingsInterface::JavaScriptAdvice jAdvice, jsAdvice;
00235     KParts::HtmlSettingsInterface::splitDomainAdvice(configStr, domain, jAdvice, jsAdvice);
00236     javaAdvice = static_cast<KJavaScriptAdvice>(jAdvice);
00237     javaScriptAdvice = static_cast<KJavaScriptAdvice>(jsAdvice);
00238 }
00239 
00240 void KHTMLSettings::readDomainSettings(const KConfigGroup &config, bool reset,
00241     bool global, KPerDomainSettings &pd_settings) {
00242   QString jsPrefix = global ? QString()
00243                 : QString::fromLatin1("javascript.");
00244   QString javaPrefix = global ? QString()
00245                 : QString::fromLatin1("java.");
00246   QString pluginsPrefix = global ? QString()
00247                 : QString::fromLatin1("plugins.");
00248 
00249   // The setting for Java
00250   QString key = javaPrefix + QLatin1String("EnableJava");
00251   if ( (global && reset) || config.hasKey( key ) )
00252     pd_settings.m_bEnableJava = config.readEntry( key, false );
00253   else if ( !global )
00254     pd_settings.m_bEnableJava = d->global.m_bEnableJava;
00255 
00256   // The setting for Plugins
00257   key = pluginsPrefix + QLatin1String("EnablePlugins");
00258   if ( (global && reset) || config.hasKey( key ) )
00259     pd_settings.m_bEnablePlugins = config.readEntry( key, true );
00260   else if ( !global )
00261     pd_settings.m_bEnablePlugins = d->global.m_bEnablePlugins;
00262 
00263   // The setting for JavaScript
00264   key = jsPrefix + QLatin1String("EnableJavaScript");
00265   if ( (global && reset) || config.hasKey( key ) )
00266     pd_settings.m_bEnableJavaScript = config.readEntry( key, true );
00267   else if ( !global )
00268     pd_settings.m_bEnableJavaScript = d->global.m_bEnableJavaScript;
00269 
00270   // window property policies
00271   key = jsPrefix + QLatin1String("WindowOpenPolicy");
00272   if ( (global && reset) || config.hasKey( key ) )
00273     pd_settings.m_windowOpenPolicy = (KJSWindowOpenPolicy)
00274             config.readEntry( key, uint(KJSWindowOpenSmart) );
00275   else if ( !global )
00276     pd_settings.m_windowOpenPolicy = d->global.m_windowOpenPolicy;
00277 
00278   key = jsPrefix + QLatin1String("WindowMovePolicy");
00279   if ( (global && reset) || config.hasKey( key ) )
00280     pd_settings.m_windowMovePolicy = (KJSWindowMovePolicy)
00281             config.readEntry( key, uint(KJSWindowMoveAllow) );
00282   else if ( !global )
00283     pd_settings.m_windowMovePolicy = d->global.m_windowMovePolicy;
00284 
00285   key = jsPrefix + QLatin1String("WindowResizePolicy");
00286   if ( (global && reset) || config.hasKey( key ) )
00287     pd_settings.m_windowResizePolicy = (KJSWindowResizePolicy)
00288             config.readEntry( key, uint(KJSWindowResizeAllow) );
00289   else if ( !global )
00290     pd_settings.m_windowResizePolicy = d->global.m_windowResizePolicy;
00291 
00292   key = jsPrefix + QLatin1String("WindowStatusPolicy");
00293   if ( (global && reset) || config.hasKey( key ) )
00294     pd_settings.m_windowStatusPolicy = (KJSWindowStatusPolicy)
00295             config.readEntry( key, uint(KJSWindowStatusAllow) );
00296   else if ( !global )
00297     pd_settings.m_windowStatusPolicy = d->global.m_windowStatusPolicy;
00298 
00299   key = jsPrefix + QLatin1String("WindowFocusPolicy");
00300   if ( (global && reset) || config.hasKey( key ) )
00301     pd_settings.m_windowFocusPolicy = (KJSWindowFocusPolicy)
00302             config.readEntry( key, uint(KJSWindowFocusAllow) );
00303   else if ( !global )
00304     pd_settings.m_windowFocusPolicy = d->global.m_windowFocusPolicy;
00305 
00306 }
00307 
00308 
00309 KHTMLSettings::KHTMLSettings()
00310     :d (new KHTMLSettingsPrivate())
00311 {
00312   init();
00313 }
00314 
00315 KHTMLSettings::KHTMLSettings(const KHTMLSettings &other)
00316     :d(new KHTMLSettingsPrivate())
00317 {
00318   KHTMLSettingsData* data = d;
00319   *data = *other.d;
00320 }
00321 
00322 KHTMLSettings::~KHTMLSettings()
00323 {
00324   delete d;
00325 }
00326 
00327 bool KHTMLSettings::changeCursor() const
00328 {
00329   return d->m_bChangeCursor;
00330 }
00331 
00332 bool KHTMLSettings::underlineLink() const
00333 {
00334   return d->m_underlineLink;
00335 }
00336 
00337 bool KHTMLSettings::hoverLink() const
00338 {
00339   return d->m_hoverLink;
00340 }
00341 
00342 void KHTMLSettings::init()
00343 {
00344   KConfig global( "khtmlrc", KConfig::NoGlobals );
00345   init( &global, true );
00346 
00347   KSharedConfig::Ptr local = KGlobal::config();
00348   if ( !local )
00349     return;
00350 
00351   init( local.data(), false );
00352 }
00353 
00354 void KHTMLSettings::init( KConfig * config, bool reset )
00355 {
00356   KConfigGroup cg( config, "MainView Settings" );
00357   if (reset || cg.exists() )
00358   {
00359     if ( reset || cg.hasKey( "OpenMiddleClick" ) )
00360         d->m_bOpenMiddleClick = cg.readEntry( "OpenMiddleClick", true );
00361   }
00362 
00363   KConfigGroup cgAccess(config,"Access Keys" );
00364   if (reset || cgAccess.exists() ) {
00365       d->m_accessKeysEnabled = cgAccess.readEntry( "Enabled", true );
00366   }
00367 
00368   KConfigGroup cgFilter( config, "Filter Settings" );
00369 
00370   if (reset || cgFilter.exists() )
00371   {
00372       d->m_adFilterEnabled = cgFilter.readEntry("Enabled", false);
00373       d->m_hideAdsEnabled = cgFilter.readEntry("Shrink", false);
00374 
00375       d->adBlackList.clear();
00376       d->adWhiteList.clear();
00377 
00378       if (d->m_adFilterEnabled) {
00379 
00381           int htmlFilterListMaxAgeDays = cgFilter.readEntry(QString("HTMLFilterListMaxAgeDays")).toInt();
00382           if (htmlFilterListMaxAgeDays < 1)
00383               htmlFilterListMaxAgeDays = 1;
00384 
00385           QMap<QString,QString> entryMap = cgFilter.entryMap();
00386           QMap<QString,QString>::ConstIterator it;
00387           for( it = entryMap.constBegin(); it != entryMap.constEnd(); ++it )
00388           {
00389               int id = -1;
00390               QString name = it.key();
00391               QString url = it.value();
00392 
00393               if (name.startsWith("Filter"))
00394               {
00395                   if (url.startsWith(QLatin1String("@@")))
00396                       d->adWhiteList.addFilter(url);
00397                   else
00398                       d->adBlackList.addFilter(url);
00399               } else if (name.startsWith("HTMLFilterListName-") && (id = name.mid(19).toInt()) > 0)
00400               {
00402                   bool filterEnabled = cgFilter.readEntry(QString("HTMLFilterListEnabled-").append(QString::number(id))) != QLatin1String("false");
00403 
00405                   KUrl url(cgFilter.readEntry(QString("HTMLFilterListURL-").append(QString::number(id))));
00406 
00407                   if (filterEnabled && url.isValid()) {
00409                       QString localFile = cgFilter.readEntry(QString("HTMLFilterListLocalFilename-").append(QString::number(id)));
00410                       localFile = KStandardDirs::locateLocal("data", "khtml/" + localFile);
00411 
00413                       QFileInfo fileInfo(localFile);
00414 
00416                       if (fileInfo.exists())
00417                           d->adblockFilterLoadList( localFile );
00418 
00420                       if (!fileInfo.exists() || fileInfo.lastModified().daysTo(QDateTime::currentDateTime()) > htmlFilterListMaxAgeDays)
00421                       {
00423                           kDebug(6000) << "Asynchronously fetching filter list from" << url << "to" << localFile;
00424 
00425                           KIO::StoredTransferJob *job = KIO::storedGet( url, KIO::Reload, KIO::HideProgressInfo );
00426                           QObject::connect( job, SIGNAL(result(KJob*)), d, SLOT(adblockFilterResult(KJob*)) );
00428                           job->setProperty("khtmlsettings_adBlock_filename", localFile);
00429                       }
00430                   }
00431               }
00432           }
00433       }
00434 
00435   }
00436 
00437   KConfigGroup cgHtml( config, "HTML Settings" );
00438   if (reset || cgHtml.exists() )
00439   {
00440     // Fonts and colors
00441     if( reset ) {
00442         d->defaultFonts = QStringList();
00443         d->defaultFonts.append( cgHtml.readEntry( "StandardFont", KGlobalSettings::generalFont().family() ) );
00444         d->defaultFonts.append( cgHtml.readEntry( "FixedFont", KGlobalSettings::fixedFont().family() ) );
00445         d->defaultFonts.append( cgHtml.readEntry( "SerifFont", HTML_DEFAULT_VIEW_SERIF_FONT ) );
00446         d->defaultFonts.append( cgHtml.readEntry( "SansSerifFont", HTML_DEFAULT_VIEW_SANSSERIF_FONT ) );
00447         d->defaultFonts.append( cgHtml.readEntry( "CursiveFont", HTML_DEFAULT_VIEW_CURSIVE_FONT ) );
00448         d->defaultFonts.append( cgHtml.readEntry( "FantasyFont", HTML_DEFAULT_VIEW_FANTASY_FONT ) );
00449         d->defaultFonts.append( QString( "0" ) ); // font size adjustment
00450     }
00451 
00452     if ( reset || cgHtml.hasKey( "MinimumFontSize" ) )
00453         d->m_minFontSize = cgHtml.readEntry( "MinimumFontSize", HTML_DEFAULT_MIN_FONT_SIZE );
00454 
00455     if ( reset || cgHtml.hasKey( "MediumFontSize" ) )
00456         d->m_fontSize = cgHtml.readEntry( "MediumFontSize", 12 );
00457 
00458     d->fonts = cgHtml.readEntry( "Fonts", QStringList() );
00459 
00460     if ( reset || cgHtml.hasKey( "DefaultEncoding" ) )
00461         d->m_encoding = cgHtml.readEntry( "DefaultEncoding", "" );
00462 
00463     if ( reset || cgHtml.hasKey( "EnforceDefaultCharset" ) )
00464         d->enforceCharset = cgHtml.readEntry( "EnforceDefaultCharset", false );
00465 
00466     // Behavior
00467     if ( reset || cgHtml.hasKey( "ChangeCursor" ) )
00468         d->m_bChangeCursor = cgHtml.readEntry( "ChangeCursor", KDE_DEFAULT_CHANGECURSOR );
00469 
00470     if ( reset || cgHtml.hasKey("UnderlineLinks") )
00471         d->m_underlineLink = cgHtml.readEntry( "UnderlineLinks", true );
00472 
00473     if ( reset || cgHtml.hasKey( "HoverLinks" ) )
00474     {
00475         if ( (d->m_hoverLink = cgHtml.readEntry( "HoverLinks", false )))
00476             d->m_underlineLink = false;
00477     }
00478 
00479     if ( reset || cgHtml.hasKey( "AllowTabulation" ) )
00480         d->m_allowTabulation = cgHtml.readEntry( "AllowTabulation", false );
00481 
00482     if ( reset || cgHtml.hasKey( "AutoSpellCheck" ) )
00483         d->m_autoSpellCheck = cgHtml.readEntry( "AutoSpellCheck", true );
00484 
00485     // Other
00486     if ( reset || cgHtml.hasKey( "AutoLoadImages" ) )
00487       d->m_bAutoLoadImages = cgHtml.readEntry( "AutoLoadImages", true );
00488 
00489     if ( reset || cgHtml.hasKey( "UnfinishedImageFrame" ) )
00490       d->m_bUnfinishedImageFrame = cgHtml.readEntry( "UnfinishedImageFrame", true );
00491 
00492     if ( reset || cgHtml.hasKey( "ShowAnimations" ) )
00493     {
00494       QString value = cgHtml.readEntry( "ShowAnimations").toLower();
00495       if (value == "disabled")
00496          d->m_showAnimations = KAnimationDisabled;
00497       else if (value == "looponce")
00498          d->m_showAnimations = KAnimationLoopOnce;
00499       else
00500          d->m_showAnimations = KAnimationEnabled;
00501     }
00502 
00503     if ( reset || cgHtml.hasKey( "SmoothScrolling" ) )
00504     {
00505       QString value = cgHtml.readEntry( "SmoothScrolling", "whenefficient" ).toLower();
00506       if (value == "disabled")
00507          d->m_smoothScrolling = KSmoothScrollingDisabled;
00508       else if (value == "whenefficient")
00509          d->m_smoothScrolling = KSmoothScrollingWhenEfficient;
00510       else
00511          d->m_smoothScrolling = KSmoothScrollingEnabled;
00512     }
00513 
00514     if ( reset || cgHtml.hasKey( "DNSPrefetch" ) )
00515     {
00516       // Enabled, Disabled, OnlyWWWAndSLD
00517       QString value = cgHtml.readEntry( "DNSPrefetch", "Enabled" ).toLower();
00518       if (value == "enabled")
00519          d->m_dnsPrefetch = KDNSPrefetchEnabled;
00520       else if (value == "onlywwwandsld")
00521          d->m_dnsPrefetch = KDNSPrefetchOnlyWWWAndSLD;
00522       else
00523          d->m_dnsPrefetch = KDNSPrefetchDisabled;
00524     }
00525 
00526     if ( cgHtml.readEntry( "UserStyleSheetEnabled", false ) == true ) {
00527         if ( reset || cgHtml.hasKey( "UserStyleSheet" ) )
00528             d->m_userSheet = cgHtml.readEntry( "UserStyleSheet", "" );
00529     }
00530 
00531     d->m_formCompletionEnabled = cgHtml.readEntry("FormCompletion", true);
00532     d->m_maxFormCompletionItems = cgHtml.readEntry("MaxFormCompletionItems", 10);
00533     d->m_autoDelayedActionsEnabled = cgHtml.readEntry ("AutoDelayedActions", true);
00534     d->m_jsErrorsEnabled = cgHtml.readEntry("ReportJSErrors", true);
00535     const QStringList accesskeys = cgHtml.readEntry("FallbackAccessKeysAssignments", QStringList());
00536     d->m_fallbackAccessKeysAssignments.clear();
00537     for( QStringList::ConstIterator it = accesskeys.begin(); it != accesskeys.end(); ++it )
00538         if( (*it).length() > 2 && (*it)[ 1 ] == ':' )
00539             d->m_fallbackAccessKeysAssignments.append( qMakePair( (*it).mid( 2 ), (*it)[ 0 ] ));
00540   }
00541 
00542   // Colors
00543   //In which group ?????
00544   if ( reset || cg.hasKey( "FollowSystemColors" ) )
00545       d->m_follow_system_colors = cg.readEntry( "FollowSystemColors", false );
00546 
00547   KConfigGroup cgGeneral( config, "General" );
00548   if ( reset || cgGeneral.exists( ) )
00549   {
00550     if ( reset || cgGeneral.hasKey( "foreground" ) ) {
00551       QColor def(HTML_DEFAULT_TXT_COLOR);
00552       d->m_textColor = cgGeneral.readEntry( "foreground", def );
00553     }
00554 
00555     if ( reset || cgGeneral.hasKey( "linkColor" ) ) {
00556       QColor def(HTML_DEFAULT_LNK_COLOR);
00557       d->m_linkColor = cgGeneral.readEntry( "linkColor", def );
00558     }
00559 
00560     if ( reset || cgGeneral.hasKey( "visitedLinkColor" ) ) {
00561       QColor def(HTML_DEFAULT_VLNK_COLOR);
00562       d->m_vLinkColor = cgGeneral.readEntry( "visitedLinkColor", def);
00563     }
00564 
00565     if ( reset || cgGeneral.hasKey( "background" ) ) {
00566       QColor def(HTML_DEFAULT_BASE_COLOR);
00567       d->m_baseColor = cgGeneral.readEntry( "background", def);
00568     }
00569   }
00570 
00571   KConfigGroup cgJava( config, "Java/JavaScript Settings" );
00572   if( reset || cgJava.exists() )
00573   {
00574     // The global setting for JavaScript debugging
00575     // This is currently always enabled by default
00576     if ( reset || cgJava.hasKey( "EnableJavaScriptDebug" ) )
00577       d->m_bEnableJavaScriptDebug = cgJava.readEntry( "EnableJavaScriptDebug", false );
00578 
00579     // The global setting for JavaScript error reporting
00580     if ( reset || cgJava.hasKey( "ReportJavaScriptErrors" ) )
00581       d->m_bEnableJavaScriptErrorReporting = cgJava.readEntry( "ReportJavaScriptErrors", false );
00582 
00583     // The global setting for popup block passive popup
00584     if ( reset || cgJava.hasKey( "PopupBlockerPassivePopup" ) )
00585       d->m_jsPopupBlockerPassivePopup = cgJava.readEntry("PopupBlockerPassivePopup", true );
00586 
00587     // Read options from the global "domain"
00588     readDomainSettings(cgJava,reset,true,d->global);
00589 #ifdef DEBUG_SETTINGS
00590     d->global.dump("init global");
00591 #endif
00592 
00593     // The domain-specific settings.
00594 
00595     static const char *const domain_keys[] = {  // always keep order of keys
00596         "ECMADomains", "JavaDomains", "PluginDomains"
00597     };
00598     bool check_old_ecma_settings = true;
00599     bool check_old_java_settings = true;
00600     // merge all domains into one list
00601     QMap<QString,int> domainList;   // why can't Qt have a QSet?
00602     for (unsigned i = 0; i < sizeof domain_keys/sizeof domain_keys[0]; ++i) {
00603       if ( reset || cgJava.hasKey(domain_keys[i]) ) {
00604         if (i == 0) check_old_ecma_settings = false;
00605     else if (i == 1) check_old_java_settings = false;
00606         const QStringList dl = cgJava.readEntry( domain_keys[i], QStringList() );
00607     const QMap<QString,int>::Iterator notfound = domainList.end();
00608     QStringList::ConstIterator it = dl.begin();
00609     const QStringList::ConstIterator itEnd = dl.end();
00610     for (; it != itEnd; ++it) {
00611       const QString domain = (*it).toLower();
00612       QMap<QString,int>::Iterator pos = domainList.find(domain);
00613       if (pos == notfound) domainList.insert(domain,0);
00614     }/*next it*/
00615       }
00616     }/*next i*/
00617 
00618     if (reset)
00619       d->domainPolicy.clear();
00620 
00621     {
00622       QMap<QString,int>::ConstIterator it = domainList.constBegin();
00623       const QMap<QString,int>::ConstIterator itEnd = domainList.constEnd();
00624       for ( ; it != itEnd; ++it)
00625       {
00626         const QString domain = it.key();
00627         KConfigGroup cg( config, domain );
00628         readDomainSettings(cg,reset,false,d->domainPolicy[domain]);
00629 #ifdef DEBUG_SETTINGS
00630         d->domainPolicy[domain].dump("init "+domain);
00631 #endif
00632       }
00633     }
00634 
00635     bool check_old_java = true;
00636     if( ( reset || cgJava.hasKey( "JavaDomainSettings" ) )
00637         && check_old_java_settings )
00638     {
00639       check_old_java = false;
00640       const QStringList domainList = cgJava.readEntry( "JavaDomainSettings", QStringList() );
00641       QStringList::ConstIterator it = domainList.constBegin();
00642       const QStringList::ConstIterator itEnd = domainList.constEnd();
00643       for ( ; it != itEnd; ++it)
00644       {
00645         QString domain;
00646         KJavaScriptAdvice javaAdvice;
00647         KJavaScriptAdvice javaScriptAdvice;
00648         splitDomainAdvice(*it, domain, javaAdvice, javaScriptAdvice);
00649         setup_per_domain_policy(d,domain).m_bEnableJava =
00650         javaAdvice == KJavaScriptAccept;
00651 #ifdef DEBUG_SETTINGS
00652     setup_per_domain_policy(d,domain).dump("JavaDomainSettings 4 "+domain);
00653 #endif
00654       }
00655     }
00656 
00657     bool check_old_ecma = true;
00658     if( ( reset || cgJava.hasKey( "ECMADomainSettings" ) )
00659     && check_old_ecma_settings )
00660     {
00661       check_old_ecma = false;
00662       const QStringList domainList = cgJava.readEntry( "ECMADomainSettings", QStringList() );
00663       QStringList::ConstIterator it = domainList.constBegin();
00664       const QStringList::ConstIterator itEnd = domainList.constEnd();
00665       for ( ; it != itEnd; ++it)
00666       {
00667         QString domain;
00668         KJavaScriptAdvice javaAdvice;
00669         KJavaScriptAdvice javaScriptAdvice;
00670         splitDomainAdvice(*it, domain, javaAdvice, javaScriptAdvice);
00671         setup_per_domain_policy(d,domain).m_bEnableJavaScript =
00672             javaScriptAdvice == KJavaScriptAccept;
00673 #ifdef DEBUG_SETTINGS
00674     setup_per_domain_policy(d,domain).dump("ECMADomainSettings 4 "+domain);
00675 #endif
00676       }
00677     }
00678 
00679     if( ( reset || cgJava.hasKey( "JavaScriptDomainAdvice" ) )
00680              && ( check_old_java || check_old_ecma )
00681          && ( check_old_ecma_settings || check_old_java_settings ) )
00682     {
00683       const QStringList domainList = cgJava.readEntry( "JavaScriptDomainAdvice", QStringList() );
00684       QStringList::ConstIterator it = domainList.constBegin();
00685       const QStringList::ConstIterator itEnd = domainList.constEnd();
00686       for ( ; it != itEnd; ++it)
00687       {
00688         QString domain;
00689         KJavaScriptAdvice javaAdvice;
00690         KJavaScriptAdvice javaScriptAdvice;
00691         splitDomainAdvice(*it, domain, javaAdvice, javaScriptAdvice);
00692         if( check_old_java )
00693           setup_per_domain_policy(d,domain).m_bEnableJava =
00694             javaAdvice == KJavaScriptAccept;
00695         if( check_old_ecma )
00696           setup_per_domain_policy(d,domain).m_bEnableJavaScript =
00697             javaScriptAdvice == KJavaScriptAccept;
00698 #ifdef DEBUG_SETTINGS
00699     setup_per_domain_policy(d,domain).dump("JavaScriptDomainAdvice 4 "+domain);
00700 #endif
00701       }
00702 
00703       //save all the settings into the new keywords if they don't exist
00704 #if 0
00705       if( check_old_java )
00706       {
00707         QStringList domainConfig;
00708         PolicyMap::Iterator it;
00709         for( it = d->javaDomainPolicy.begin(); it != d->javaDomainPolicy.end(); ++it )
00710         {
00711           QByteArray javaPolicy = adviceToStr( it.value() );
00712           QByteArray javaScriptPolicy = adviceToStr( KJavaScriptDunno );
00713           domainConfig.append(QString::fromLatin1("%1:%2:%3").arg(it.key()).arg(javaPolicy).arg(javaScriptPolicy));
00714         }
00715         cg.writeEntry( "JavaDomainSettings", domainConfig );
00716       }
00717 
00718       if( check_old_ecma )
00719       {
00720         QStringList domainConfig;
00721         PolicyMap::Iterator it;
00722         for( it = d->javaScriptDomainPolicy.begin(); it != d->javaScriptDomainPolicy.end(); ++it )
00723         {
00724           QByteArray javaPolicy = adviceToStr( KJavaScriptDunno );
00725           QByteArray javaScriptPolicy = adviceToStr( it.value() );
00726           domainConfig.append(QString::fromLatin1("%1:%2:%3").arg(it.key()).arg(javaPolicy).arg(javaScriptPolicy));
00727         }
00728         cg.writeEntry( "ECMADomainSettings", domainConfig );
00729       }
00730 #endif
00731     }
00732   }
00733 }
00734 
00735 
00740 static const KPerDomainSettings &lookup_hostname_policy(
00741             const KHTMLSettingsPrivate* const d,
00742             const QString& hostname)
00743 {
00744 #ifdef DEBUG_SETTINGS
00745   kDebug() << "lookup_hostname_policy(" << hostname << ")";
00746 #endif
00747   if (hostname.isEmpty()) {
00748 #ifdef DEBUG_SETTINGS
00749     d->global.dump("global");
00750 #endif
00751     return d->global;
00752   }
00753 
00754   const PolicyMap::const_iterator notfound = d->domainPolicy.constEnd();
00755 
00756   // First check whether there is a perfect match.
00757   PolicyMap::const_iterator it = d->domainPolicy.find(hostname);
00758   if( it != notfound ) {
00759 #ifdef DEBUG_SETTINGS
00760     kDebug() << "perfect match";
00761     (*it).dump(hostname);
00762 #endif
00763     // yes, use it (unless dunno)
00764     return *it;
00765   }
00766 
00767   // Now, check for partial match.  Chop host from the left until
00768   // there's no dots left.
00769   QString host_part = hostname;
00770   int dot_idx = -1;
00771   while( (dot_idx = host_part.indexOf(QChar('.'))) >= 0 ) {
00772     host_part.remove(0,dot_idx);
00773     it = d->domainPolicy.find(host_part);
00774     Q_ASSERT(notfound == d->domainPolicy.end());
00775     if( it != notfound ) {
00776 #ifdef DEBUG_SETTINGS
00777       kDebug() << "partial match";
00778       (*it).dump(host_part);
00779 #endif
00780       return *it;
00781     }
00782     // assert(host_part[0] == QChar('.'));
00783     host_part.remove(0,1); // Chop off the dot.
00784   }
00785 
00786   // No domain-specific entry: use global domain
00787 #ifdef DEBUG_SETTINGS
00788   kDebug() << "no match";
00789   d->global.dump("global");
00790 #endif
00791   return d->global;
00792 }
00793 
00794 bool KHTMLSettings::isOpenMiddleClickEnabled()
00795 {
00796   return d->m_bOpenMiddleClick;
00797 }
00798 
00799 bool KHTMLSettings::isBackRightClickEnabled()
00800 {
00801   return false; // ## the feature moved to konqueror
00802 }
00803 
00804 bool KHTMLSettings::accessKeysEnabled() const
00805 {
00806     return d->m_accessKeysEnabled;
00807 }
00808 
00809 bool KHTMLSettings::isAdFilterEnabled() const
00810 {
00811     return d->m_adFilterEnabled;
00812 }
00813 
00814 bool KHTMLSettings::isHideAdsEnabled() const
00815 {
00816     return d->m_hideAdsEnabled;
00817 }
00818 
00819 bool KHTMLSettings::isAdFiltered( const QString &url ) const
00820 {
00821     if (d->m_adFilterEnabled)
00822     {
00823         if (!url.startsWith("data:"))
00824         {
00825             // Check the blacklist, and only if that matches, the whitelist
00826             return d->adBlackList.isUrlMatched(url) && !d->adWhiteList.isUrlMatched(url);
00827         }
00828     }
00829     return false;
00830 }
00831 
00832 QString KHTMLSettings::adFilteredBy( const QString &url, bool *isWhiteListed ) const
00833 {
00834     QString m = d->adWhiteList.urlMatchedBy(url);
00835     if (!m.isEmpty())
00836     {
00837         if (isWhiteListed != 0)
00838             *isWhiteListed = true;
00839         return (m);
00840     }
00841 
00842     m = d->adBlackList.urlMatchedBy(url);
00843     if (!m.isEmpty())
00844     {
00845         if (isWhiteListed != 0)
00846             *isWhiteListed = false;
00847         return (m);
00848     }
00849 
00850     return (QString());
00851 }
00852 
00853 void KHTMLSettings::addAdFilter( const QString &url )
00854 {
00855     KConfigGroup config = KSharedConfig::openConfig( "khtmlrc", KConfig::NoGlobals )->group( "Filter Settings" );
00856 
00857     QRegExp rx;
00858 
00859     // Try compiling to avoid invalid stuff. Only support the basic syntax here...
00860     // ### refactor somewhat
00861     if (url.length()>2 && url[0]=='/' && url[url.length()-1] == '/')
00862     {
00863         QString inside = url.mid(1, url.length()-2);
00864         rx.setPattern(inside);
00865     }
00866     else
00867     {
00868         rx.setPatternSyntax(QRegExp::Wildcard);
00869         rx.setPattern(url);
00870     }
00871 
00872     if (rx.isValid())
00873     {
00874         int last=config.readEntry("Count", 0);
00875         QString key = "Filter-" + QString::number(last);
00876         config.writeEntry(key, url);
00877         config.writeEntry("Count",last+1);
00878         config.sync();
00879         if (url.startsWith(QLatin1String("@@")))
00880              d->adWhiteList.addFilter(url);
00881         else
00882              d->adBlackList.addFilter(url);
00883     }
00884     else
00885     {
00886         KMessageBox::error(0,
00887                            rx.errorString(),
00888                            i18n("Filter error"));
00889     }
00890 }
00891 
00892 bool KHTMLSettings::isJavaEnabled( const QString& hostname ) const
00893 {
00894   return lookup_hostname_policy(d,hostname.toLower()).m_bEnableJava;
00895 }
00896 
00897 bool KHTMLSettings::isJavaScriptEnabled( const QString& hostname ) const
00898 {
00899   return lookup_hostname_policy(d,hostname.toLower()).m_bEnableJavaScript;
00900 }
00901 
00902 bool KHTMLSettings::isJavaScriptDebugEnabled( const QString& /*hostname*/ ) const
00903 {
00904   // debug setting is global for now, but could change in the future
00905   return d->m_bEnableJavaScriptDebug;
00906 }
00907 
00908 bool KHTMLSettings::isJavaScriptErrorReportingEnabled( const QString& /*hostname*/ ) const
00909 {
00910   // error reporting setting is global for now, but could change in the future
00911   return d->m_bEnableJavaScriptErrorReporting;
00912 }
00913 
00914 bool KHTMLSettings::isPluginsEnabled( const QString& hostname ) const
00915 {
00916   return lookup_hostname_policy(d,hostname.toLower()).m_bEnablePlugins;
00917 }
00918 
00919 KHTMLSettings::KJSWindowOpenPolicy KHTMLSettings::windowOpenPolicy(
00920                 const QString& hostname) const {
00921   return lookup_hostname_policy(d,hostname.toLower()).m_windowOpenPolicy;
00922 }
00923 
00924 KHTMLSettings::KJSWindowMovePolicy KHTMLSettings::windowMovePolicy(
00925                 const QString& hostname) const {
00926   return lookup_hostname_policy(d,hostname.toLower()).m_windowMovePolicy;
00927 }
00928 
00929 KHTMLSettings::KJSWindowResizePolicy KHTMLSettings::windowResizePolicy(
00930                 const QString& hostname) const {
00931   return lookup_hostname_policy(d,hostname.toLower()).m_windowResizePolicy;
00932 }
00933 
00934 KHTMLSettings::KJSWindowStatusPolicy KHTMLSettings::windowStatusPolicy(
00935                 const QString& hostname) const {
00936   return lookup_hostname_policy(d,hostname.toLower()).m_windowStatusPolicy;
00937 }
00938 
00939 KHTMLSettings::KJSWindowFocusPolicy KHTMLSettings::windowFocusPolicy(
00940                 const QString& hostname) const {
00941   return lookup_hostname_policy(d,hostname.toLower()).m_windowFocusPolicy;
00942 }
00943 
00944 int KHTMLSettings::mediumFontSize() const
00945 {
00946     return d->m_fontSize;
00947 }
00948 
00949 int KHTMLSettings::minFontSize() const
00950 {
00951   return d->m_minFontSize;
00952 }
00953 
00954 QString KHTMLSettings::settingsToCSS() const
00955 {
00956     // lets start with the link properties
00957     QString str = "a:link {\ncolor: ";
00958     str += d->m_linkColor.name();
00959     str += ';';
00960     if(d->m_underlineLink)
00961         str += "\ntext-decoration: underline;";
00962 
00963     if( d->m_bChangeCursor )
00964     {
00965         str += "\ncursor: pointer;";
00966         str += "\n}\ninput[type=image] { cursor: pointer;";
00967     }
00968     str += "\n}\n";
00969     str += "a:visited {\ncolor: ";
00970     str += d->m_vLinkColor.name();
00971     str += ';';
00972     if(d->m_underlineLink)
00973         str += "\ntext-decoration: underline;";
00974 
00975     if( d->m_bChangeCursor )
00976         str += "\ncursor: pointer;";
00977     str += "\n}\n";
00978 
00979     if(d->m_hoverLink)
00980         str += "a:link:hover, a:visited:hover { text-decoration: underline; }\n";
00981 
00982     return str;
00983 }
00984 
00985 const QString &KHTMLSettings::availableFamilies()
00986 {
00987     if ( !avFamilies ) {
00988         avFamilies = new QString;
00989         QFontDatabase db;
00990         QStringList families = db.families();
00991         QStringList s;
00992         QRegExp foundryExp(" \\[.+\\]");
00993 
00994         //remove foundry info
00995         QStringList::Iterator f = families.begin();
00996         const QStringList::Iterator fEnd = families.end();
00997 
00998         for ( ; f != fEnd; ++f ) {
00999                 (*f).replace( foundryExp, "");
01000                 if (!s.contains(*f))
01001                         s << *f;
01002         }
01003         s.sort();
01004 
01005         *avFamilies = ',' + s.join(",") + ',';
01006     }
01007 
01008   return *avFamilies;
01009 }
01010 
01011 QString KHTMLSettings::lookupFont(int i) const
01012 {
01013     QString font;
01014     if (d->fonts.count() > i)
01015        font = d->fonts[i];
01016     if (font.isEmpty())
01017         font = d->defaultFonts[i];
01018     return font;
01019 }
01020 
01021 QString KHTMLSettings::stdFontName() const
01022 {
01023     return lookupFont(0);
01024 }
01025 
01026 QString KHTMLSettings::fixedFontName() const
01027 {
01028     return lookupFont(1);
01029 }
01030 
01031 QString KHTMLSettings::serifFontName() const
01032 {
01033     return lookupFont(2);
01034 }
01035 
01036 QString KHTMLSettings::sansSerifFontName() const
01037 {
01038     return lookupFont(3);
01039 }
01040 
01041 QString KHTMLSettings::cursiveFontName() const
01042 {
01043     return lookupFont(4);
01044 }
01045 
01046 QString KHTMLSettings::fantasyFontName() const
01047 {
01048     return lookupFont(5);
01049 }
01050 
01051 void KHTMLSettings::setStdFontName(const QString &n)
01052 {
01053     while(d->fonts.count() <= 0)
01054         d->fonts.append(QString());
01055     d->fonts[0] = n;
01056 }
01057 
01058 void KHTMLSettings::setFixedFontName(const QString &n)
01059 {
01060     while(d->fonts.count() <= 1)
01061         d->fonts.append(QString());
01062     d->fonts[1] = n;
01063 }
01064 
01065 QString KHTMLSettings::userStyleSheet() const
01066 {
01067     return d->m_userSheet;
01068 }
01069 
01070 bool KHTMLSettings::isFormCompletionEnabled() const
01071 {
01072   return d->m_formCompletionEnabled;
01073 }
01074 
01075 int KHTMLSettings::maxFormCompletionItems() const
01076 {
01077   return d->m_maxFormCompletionItems;
01078 }
01079 
01080 const QString &KHTMLSettings::encoding() const
01081 {
01082   return d->m_encoding;
01083 }
01084 
01085 bool KHTMLSettings::followSystemColors() const
01086 {
01087     return d->m_follow_system_colors;
01088 }
01089 
01090 const QColor& KHTMLSettings::textColor() const
01091 {
01092   return d->m_textColor;
01093 }
01094 
01095 const QColor& KHTMLSettings::baseColor() const
01096 {
01097   return d->m_baseColor;
01098 }
01099 
01100 const QColor& KHTMLSettings::linkColor() const
01101 {
01102   return d->m_linkColor;
01103 }
01104 
01105 const QColor& KHTMLSettings::vLinkColor() const
01106 {
01107   return d->m_vLinkColor;
01108 }
01109 
01110 bool KHTMLSettings::autoLoadImages() const
01111 {
01112   return d->m_bAutoLoadImages;
01113 }
01114 
01115 bool KHTMLSettings::unfinishedImageFrame() const
01116 {
01117   return d->m_bUnfinishedImageFrame;
01118 }
01119 
01120 KHTMLSettings::KAnimationAdvice KHTMLSettings::showAnimations() const
01121 {
01122   return d->m_showAnimations;
01123 }
01124 
01125 KHTMLSettings::KSmoothScrollingMode KHTMLSettings::smoothScrolling() const
01126 {
01127   return d->m_smoothScrolling;
01128 }
01129 
01130 KHTMLSettings::KDNSPrefetch KHTMLSettings::dnsPrefetch() const
01131 {
01132   return d->m_dnsPrefetch;
01133 }
01134 
01135 bool KHTMLSettings::isAutoDelayedActionsEnabled() const
01136 {
01137   return d->m_autoDelayedActionsEnabled;
01138 }
01139 
01140 bool KHTMLSettings::jsErrorsEnabled() const
01141 {
01142   return d->m_jsErrorsEnabled;
01143 }
01144 
01145 void KHTMLSettings::setJSErrorsEnabled(bool enabled)
01146 {
01147   d->m_jsErrorsEnabled = enabled;
01148   // save it
01149   KConfigGroup cg( KGlobal::config(), "HTML Settings");
01150   cg.writeEntry("ReportJSErrors", enabled);
01151   cg.sync();
01152 }
01153 
01154 bool KHTMLSettings::allowTabulation() const
01155 {
01156     return d->m_allowTabulation;
01157 }
01158 
01159 bool KHTMLSettings::autoSpellCheck() const
01160 {
01161     return d->m_autoSpellCheck;
01162 }
01163 
01164 QList< QPair< QString, QChar > > KHTMLSettings::fallbackAccessKeysAssignments() const
01165 {
01166     return d->m_fallbackAccessKeysAssignments;
01167 }
01168 
01169 void KHTMLSettings::setJSPopupBlockerPassivePopup(bool enabled)
01170 {
01171     d->m_jsPopupBlockerPassivePopup = enabled;
01172     // save it
01173     KConfigGroup cg( KGlobal::config(), "Java/JavaScript Settings");
01174     cg.writeEntry("PopupBlockerPassivePopup", enabled);
01175     cg.sync();
01176 }
01177 
01178 bool KHTMLSettings::jsPopupBlockerPassivePopup() const
01179 {
01180     return d->m_jsPopupBlockerPassivePopup;
01181 }
01182 
01183 #include "khtml_settings.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2019 The KDE developers.
Generated on Mon Jan 21 2019 12:38:19 by doxygen 1.7.5.1 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-4.9.5 API Reference

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