kdecore has been split up into a number of independent libraries: libkarchive, libkauth, libkdbus, etc.
KUrl has been deprecated in favour of QUrl. Warning, look at the KUrl documentation for proper porting.
Do not just do a global search and replace, KUrl(QString) means "absolute local file or absolute url" while
QUrl(QString) means "relative url or absolute url". And KUrl::path() is not exactly the same as QUrl::path(), etc.
And in particular KUrl::isParentOf means "parent or equal" while QUrl::isParentOf is strictly "parent" (use QUrlPathInfo::isParentOfOrEqual instead).
KUrl::upUrl is now the static method KIO::upUrl
For the reason above, many signals with a KUrl have been replaced with a QUrl:
Remember to update your connect statements and your slots!
KMimeType::comment and KMimeType::iconName no longer take a KUrl argument. If you were passing such an argument
(to support .directory files in directories), port the code to KFileItem::mimeComment and KFileItem::iconName.
KSaveFile has been deprecated in favour of the new QSaveFile:
open() -> open(QIODevice::WriteOnly)
finalize() -> commit()
abort() -> cancelWriting()
close() -> do not call close, call commit or cancelWriting directly
the return value from write() calls does not need to be checked anymore, commit will cancel in case of a write error.
KComponentData:
dirs() has been removed. Use KGlobal::dirs() instead.
The only difference (for other KComponentData instances than the main one),
is the "appdata" resource, which would now point to the application name
rather than the component name. It's cleaner to use "data" anyway (or QStandardPaths::GenericDataLocation),
and prepend the component name to the searched file.
KStandardDirs: KDE applications can keep using it, but independent frameworks should use QStandardPaths instead.
The porting depends on the resource type:
If the resource is available in QStandardPaths (i.e. for all of the above), then the porting is simple:
KStandardDirs::locate("data", "kmyapp/my-data") -> QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kmyapp/my-data")
KStandardDirs::locate("services", "foo.desktop") -> QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kde5/services/foo.desktop")
dirs.findResource("data", relPath -> QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kmyapp/my-data")
dirs.findDirs("data", "kconf_update") -> QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, "kconf_update", QStandardPaths::LocateDirectory)
saveLocation -> writableLocation (note that you might have to mkpath it if it doesn't exist)
locateLocal(type, file) -> writableLocation(type) + '/' + file (you might have to mkpath the directory)
resourceDirs("xdgdata-apps") -> QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation) (no trailing slashes anymore though)
Otherwise, you need to use GenericDataLocation and add the subdirectory name manually.
dirs()->resourceDirs("xdgdata-icon") -> QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, "icons", QStandardPaths::LocateDirectory) // xdgata-icon is the "icons" subdir under the xdg data locations
dirs()->findAllResources("xdgdata-mime", file) -> QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, "mime/" + file)
Similarly, xdgconf-menu is QStandardPaths::ConfigLocation + "menus", and xdgconf-autostart is QStandardPaths::ConfigLocation + "autostart";
"xdgdata-dirs" is QStandardPaths::GenericDataLocation + "desktop-directories"
"templates" is QStandardPaths::GenericDataLocation + "templates"
"emoticons" is QStandardPaths::GenericDataLocation + "emoticons
"html" is QStandardPaths::GenericDataLocation + "doc/HTML"
"sound" is QStandardPaths::GenericDataLocation + "sounds" (note the additional 's')
"wallpaper" is QStandardPaths::GenericDataLocation + "wallpapers" (note the additional 's')
(see kstandarddirs.cpp line 119 ff for resources that are missing here)
When the code uses wildcard filters or the Recursive flag in findAllResources, you cannot port it to one line of QStandardPaths.
Either keep using KStandardDirs, or write your own filtering (QDir::entryList) or recursive listing (use QDirIterator with the Subdirectories flag).
Also, check for absolute paths first, findAllResources(res, "/absolute/path") returned the path, QStandardPaths doesn't.
If NoDuplicates was used, make a unique list of relative paths first, then use locate on each one (see autostart.cpp for an example).
Example using entryList:
KStandardDirs::findExe (and the use of the "exe" resource) can be ported to QStandardPaths::findExecutable, except when the executable comes from libexec, in which case the path should just be hardcoded using CMAKE_INSTALL_PREFIX "/" LIBEXEC_INSTALL_DIR.
The "lib" resource was not used directly in code (the linker finds shared libs, not the code).
The "module" resource, on the other hand, was used to locate plugins. KPluginLoader now uses QT_PLUGIN_PATH instead, and looks in the kf5 subdirectory.
Please email kde-frameworks-devel@kde.org if you would need public API for this.
A script is available in kdesdk/kde-dev-scripts/kf5/convert-kstandarddirs.pl to port some of this.
KConfig and KDesktopFile have been ported to QStandardPaths. This changes the "const char* resourceType" in the API into QStandardPaths::StandardLocation, and means that modifying the "config" resource before using KConfig has no effect on KConfig anymore.
KConfigBase::sync now returns a bool
KCoreConfigSkeleton::writeConfig now returns a bool
KCoreConfigSkeleton::usrWriteConfig now returns a bool
KTemporaryFile is deprecated, port to QTemporaryFile instead, see KTemporaryFile API documentation for details.
KTempDir is deprecated, port to QTemporaryDir instead, see KTempDir API documentation for details.
KToolInvocation::invokeHelp is now KHelpClient::invokeHelp, in the kwidgets framework.
KMD5 is deprecated, port to QCryptographicHash instead.
KMimeType is deprecated, port to QMimeType instead. Here's a porting guide:
QMimeDatabase db; // All the methods need a db instance, but it's very cheap to create, on stack is fine.
KMimeType::Ptr mime -> QMimeType mime
if (mime) -> if (mime.isValid())
KMimeType::mimeType(name) -> db.mimeTypeForName(name)
KMimeType::mimeType(name, DontResolveAlias) -> db.mimeTypeForName(name) // there is no separate mime object for the alias
KMimeType::findByUrl(url) -> db.mimeTypeForUrl(url)
KMimeType::findByUrl(url, 0, is_local, true) -> db.mimeTypeForFile(url.path(), QMimeDatabase::MatchExtension)
KMimeType::findByPath(path) -> db.mimeTypeForFile(path)
KMimeType::findByPath(path, 0, true) -> db.mimeTypeForFile(path, QMimeDatabase::MatchExtension)
(this is slightly different in case of conflicting globs though, findByPath used to return empty,
so that delayed mimetype determination could then refine this; mimeTypesForFileName can be useful
to detect this case. But for most applications this detail doesn't matter).
KMimeType::findByContent(data) -> db.mimeTypeForData(data)
KMimeType::findByNameAndContent(name, data_or_device) -> db.mimeTypeForNameAndData(name, data_or_device)
KMimeType::findByFileContent(path) -> db.mimeTypeForFile(path, QMimeDatabase::MatchContent)
mime->name() == KMimeType::defaultMimeType() -> mime.isDefault()
mime.allParentMimeTypes() -> mime.allAncestors()
KMimeType::extractKnownExtension(fileName) -> db.suffixForFileName(fileName)
KMimeType::iconNameForUrl(url) has additional logic on top of db.mimeTypeForUrl(url).iconName(), to
fallback to the protocol-specific icon (e.g. trash icon for trash:/, etc.). This logic has now
moved to KIO::iconNameForUrl.
KMimeType::patterns() -> QMimeType::globPatterns()
KMimeType::allMimeTypes() -> db.allMimeTypes()
KLocale has been splitted up: KLocale is now only about locale settings, while translation support has moved to KLocalizedString.
KCmdLineArgs uses K4AboutData rather than KAboutData: K4AboutData keeps the old mechanism for delayed translations
(I18N_NOOP), while KAboutData is the one used by plugins, which can use immediate translation (i18n).
KEncodingDetector is removed, port to KEncodingProber. Porting guide:
The following functions have been moved into khtml with the orignal KEncodingDetector class. khtml is the only user of them.
enum KEncodingDetector::EncodingChoiceSource -> removed
KEncodingDetector::setEncoding(encoding, choice) -> removed, implement it in khtml code
KEncodingDetector::encodingChoiceSource() -> removed
qtest_kde.h is deprecated. Port to <QtTest>, for core tests, or to <QtTestWidgets> for tests that use widgets, otherwise they'll crash in code that requires QApplication internally.
Call QApplication::setApplicationDisplayName(i18n("...")) for GUI programs
Use KDBusService for DBus registration, and optional "unique" behavior
KIntValidator: Use QIntValidator instead, the only difference was that KIntValidator attempted to
support non-decimal bases (but it was broken with prefix and suffix texts, and therefore unused in KDE SC)
KDoubleValidator: Use QDoubleValidator instead (as part of KLocale -> QLocale)
KFloatValidator: Use QDoubleValidator instead (drop-in replacement)
KSvgRenderer: Use QSvgRenderer instead (drop-in replacement)
KCursor: Use QCursor instead
KIdentityProxyModel: Removed, used QIdentityProxyModel instead (trivial search/replace)
Other proxy models: Moved to libitemmodels
KPassivePopup: standardView() now returns a QWidget* instead of a KVBox*. The QWidget has a QVBoxLayout, i.e., additional widgets can be appended by calling widget->layout()->addWidget().
KCodecAction: use enum KEncodingProber::ProberType instead of enum KEncodingDetector::AutoDetectScript
KXMessages: the "obsolete = false" argument has been removed from all methods, and int screen has a default value of -1 now. Remove the "-1, false" in all calls. The sendMessage and sendMessageX methods were apparently unused, and have been commented out. Email kde-frameworks-devel at kde.org if you need them back.
KGlobalSettings::contextMenuKey is gone, reimplement QWidget::contextMenuEvent() instead.
+
KGlobalSettings::*Font methods are deprecated. Use QFontsDatabase::systemFonts(). ::menuFont, ::taskBarFont and ::toolBarFont are not available now (they are provided by the QPA but not public API). If cases needing those arise we'll
+have to find an alternative
KMessageBox is no longer a class, but a namespace, as it only had static methods. The KMessageBox namespace spans now in three frameworks:
WId methods are now in kmessagebox_kiw.h from kinterprocesswindowing framework
Queued methds are now in kmessagebox_queued.h from kde4support framework
The remainder of the methods are now in kmessagebox.h from kwidgets
setDontShowAskAgainConfig was renamed to setDontShowAgainConfig
NOTE1: KMessageBox no longer uses notifications
NOTE2: Too long messages no longer trigger KSqueezedTextLabel usage. This is a temporary measure, though, to avoid dependencies on kdeui.
KMessageBoxMessageHandler moved to kde4support
KNotification: setComponentData(KComponentData) is now setComponentName(QString), only the component name was used.
KActionCollection and KXMLGUIClient: replace setComponentData with setComponentName and setComponentDisplayName
KAction changes
Shape and rocker gestures are now handled by KGestureMap. The existing KAction methods related to gesture handling delegate to KGestureMap.
KGestureMap changes:
addGesture renamed to setShapeGesture and setRockerGesture and now allow replacing existing gestures. When this occurs, a warning is traced with qDebug.
new setDefault[Shape|Rocker]Gesture methods allow defining default gestures for an action, providing the functionality removed from KAction.
new shapeGesture and defaultShapeGesture methods retrieves already defined shape gestures for a given action
new rockerGesture and defaultRockerGesture methods retrieves already defined rocker gestures for a given action
KAction global shortcut handling logic moved to KGlobalAccel. So the KAction::globalShortcutChanged signal was removed and a new corresponding KGlobalAccel::globalShortcutChanged has been added. The signal semantics have not changed.
KUndoStack: Use QUndoStack with KUndoActions::createUndoAction() and KUndoActions::createRedoAction() instead
KRichTextWidget: createActions() does not take any KActionCollection and returns a list of QAction instead. You could use KActionCollection.addActions(KRichTextWidget.createActions()) instead.
KTextBrowser: Use QTextBrowser instead. The only difference is QTextBrowser does not support "whatsthis:" urls.
The very common job->ui()->setWindow(widget) has to be ported to KJobWidgets::setWindow(job, widget), because job->ui() is now only a KJobUiDelegate.
The deprecated KIO::Job::showErrorDialog() has been removed, use KJobWidgets::setWindow(job, parent) and job->ui()->showErrorMessage()
The KFileItem API has been ported to QMimeType. As a consequence, mimeTypePtr() is now currentMimeType().
KFileItem::run(QWidget*) has disappeared, due to core/gui separation. Use new KRun(item.targetUrl(), widget) instead.
KFileItem::pixmap(size, state=0) has disappeared, due to core/gui separation. If you can, use KIcon(item.iconName(), 0, item.overlays()) instead.
If you really need a QPixmap, e.g. for showing in a QLabel, use this instead:
KIO::pixmapForUrl has moved from kio/global.h to kio/pixmaploader.h (so that global.h is core only)
KProtocolInfo::isHelperProtocol() and exec() no longer detect apps associated with x-scheme-handler/*. This has moved up to KRun. Therefore KProtocolInfo is again about .protocol files only.
KIO::RenameDialogPlugin was removed, it was unused for a long time anyway. The rename dialog uses KFileMetaDataWidget and PreviewJob instead.
When Job::setUiDelegate(0) is used on a CopyJob (KIO::copy or KIO::move), an extra call to setUiDelegateExtension(0) is probably necessary, to disable skip and rename dialogs.
KIO::Job::isInteractive() has been removed, use uiDelegate() or uiDelegateExtension() depending on what is meant (error messages, or rename/skip dialog).
With the port from KUrl to QUrl in APIs, the signature of the virtual method openUrl has changed, make sure
to port your reimplemented methods to QUrl!
diff --git a/kdeui/util/kglobalsettings.cpp b/kdeui/util/kglobalsettings.cpp
index ac7dabbb48..372f6cdcaa 100644
--- a/kdeui/util/kglobalsettings.cpp
+++ b/kdeui/util/kglobalsettings.cpp
@@ -1,1064 +1,942 @@
/* This file is part of the KDE libraries
Copyright (C) 2000, 2006 David Faure
Copyright 2008 Friedrich W. H. Kossebau
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "kglobalsettings.h"
#include
#include
#include
//#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
// next two needed so we can set their palettes
#include
#include
#ifdef Q_OS_WIN
#include
static QRgb qt_colorref2qrgb(COLORREF col)
{
return qRgb(GetRValue(col),GetGValue(col),GetBValue(col));
}
#endif
#include
#if HAVE_X11
#include
#include
#ifdef HAVE_XCURSOR // TODO NOT DEFINED ANYMORE. Can we drop X cursor themes?
#include
#endif
//#include "fixx11h.h"
#include
#endif
#include
#include
#include
//static QColor *_buttonBackground = 0;
static KGlobalSettings::GraphicEffects _graphicEffects = KGlobalSettings::NoEffects;
-// TODO: merge this with KGlobalSettings::Private
-//
-// F. Kossebau: KDE5: think to make all methods static and not expose an object,
-// making KGlobalSettings rather a namespace
-// D. Faure: how would people connect to signals, then?
-class KGlobalSettingsData
-{
- public:
- // if adding a new type here also add an entry to DefaultFontData
- enum FontTypes
- {
- GeneralFont = 0,
- FixedFont,
- ToolbarFont,
- MenuFont,
- WindowTitleFont,
- TaskbarFont ,
- SmallestReadableFont,
- FontTypesCount
- };
-
- public:
- KGlobalSettingsData();
- ~KGlobalSettingsData();
-
- public:
- static KGlobalSettingsData* self();
-
- public: // access, is not const due to caching
- QFont font( FontTypes fontType );
- QFont largeFont( const QString& text );
- KGlobalSettings::KMouseSettings& mouseSettings();
-
- public:
- void dropFontSettingsCache();
- void dropMouseSettingsCache();
-
- protected:
- QFont* mFonts[FontTypesCount];
- QFont* mLargeFont;
- KGlobalSettings::KMouseSettings* mMouseSettings;
-};
-
-KGlobalSettingsData::KGlobalSettingsData()
- : mLargeFont( 0 ),
- mMouseSettings( 0 )
-{
- for( int i=0; iobject;
}
KGlobalSettings::KGlobalSettings()
: QObject(0), d(new Private(this))
{
+ connect(this, SIGNAL(kdisplayFontChanged()), SIGNAL(appearanceChanged()));
}
KGlobalSettings::~KGlobalSettings()
{
delete d;
}
void KGlobalSettings::activate()
{
activate(ApplySettings | ListenForChanges);
}
void KGlobalSettings::activate(ActivateOptions options)
{
if (!d->activated) {
d->activated = true;
if (options & ListenForChanges) {
QDBusConnection::sessionBus().connect( QString(), "/KGlobalSettings", "org.kde.KGlobalSettings",
"notifyChange", this, SLOT(_k_slotNotifyChange(int,int)) );
QDBusConnection::sessionBus().connect( QString(), "/KIconLoader", "org.kde.KIconLoader",
"iconChanged", this, SLOT(_k_slotIconChange(int)) );
+ QDBusConnection::sessionBus().connect( QString(), "/KDEPlatformTheme", "org.kde.KDEPlatformTheme",
+ "fontsChanged", this, SLOT(kdisplayFontChanged()) );
}
if (options & ApplySettings) {
d->kdisplaySetStyle(); // implies palette setup
d->kdisplaySetFont();
d->propagateQtSettings();
}
}
}
// Qt5 TODO: implement QPlatformIntegration::styleHint so that it reads a Qt or KDE setting,
// so that apps can just use QApplication::startDragDistance().
int KGlobalSettings::dndEventDelay()
{
KConfigGroup g( KSharedConfig::openConfig(), "General" );
return g.readEntry("StartDragDist", QApplication::startDragDistance());
}
bool KGlobalSettings::singleClick()
{
KConfigGroup g( KSharedConfig::openConfig(), "KDE" );
return g.readEntry("SingleClick", KDE_DEFAULT_SINGLECLICK );
}
bool KGlobalSettings::changeCursorOverIcon()
{
KConfigGroup g( KSharedConfig::openConfig(), "KDE" );
return g.readEntry("ChangeCursor", KDE_DEFAULT_CHANGECURSOR);
}
int KGlobalSettings::autoSelectDelay()
{
KConfigGroup g( KSharedConfig::openConfig(), "KDE" );
return g.readEntry("AutoSelectDelay", KDE_DEFAULT_AUTOSELECTDELAY);
}
KGlobalSettings::Completion KGlobalSettings::completionMode()
{
int completion;
KConfigGroup g( KSharedConfig::openConfig(), "General" );
completion = g.readEntry("completionMode", -1);
if ((completion < (int) CompletionNone) ||
(completion > (int) CompletionPopupAuto))
{
completion = (int) CompletionPopup; // Default
}
- return (Completion) completion;
+ return (Completion) completion;
}
bool KGlobalSettings::showContextMenusOnPress ()
{
KConfigGroup g(KSharedConfig::openConfig(), "ContextMenus");
return g.readEntry("ShowOnPress", true);
}
// NOTE: keep this in sync with kdebase/workspace/kcontrol/colors/colorscm.cpp
QColor KGlobalSettings::inactiveTitleColor()
{
#ifdef Q_OS_WIN
return qt_colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTION));
#else
KConfigGroup g( KSharedConfig::openConfig(), "WM" );
return g.readEntry( "inactiveBackground", QColor(224,223,222) );
#endif
}
// NOTE: keep this in sync with kdebase/workspace/kcontrol/colors/colorscm.cpp
QColor KGlobalSettings::inactiveTextColor()
{
#ifdef Q_OS_WIN
return qt_colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTIONTEXT));
#else
KConfigGroup g( KSharedConfig::openConfig(), "WM" );
return g.readEntry( "inactiveForeground", QColor(75,71,67) );
#endif
}
// NOTE: keep this in sync with kdebase/workspace/kcontrol/colors/colorscm.cpp
QColor KGlobalSettings::activeTitleColor()
{
#ifdef Q_OS_WIN
return qt_colorref2qrgb(GetSysColor(COLOR_ACTIVECAPTION));
#else
KConfigGroup g( KSharedConfig::openConfig(), "WM" );
return g.readEntry( "activeBackground", QColor(48,174,232));
#endif
}
// NOTE: keep this in sync with kdebase/workspace/kcontrol/colors/colorscm.cpp
QColor KGlobalSettings::activeTextColor()
{
#ifdef Q_OS_WIN
return qt_colorref2qrgb(GetSysColor(COLOR_CAPTIONTEXT));
#else
KConfigGroup g( KSharedConfig::openConfig(), "WM" );
return g.readEntry( "activeForeground", QColor(255,255,255) );
#endif
}
int KGlobalSettings::contrast()
{
return KColorScheme::contrast();
}
qreal KGlobalSettings::contrastF(const KSharedConfigPtr &config)
{
return KColorScheme::contrastF(config);
}
bool KGlobalSettings::shadeSortColumn()
{
KConfigGroup g( KSharedConfig::openConfig(), "General" );
return g.readEntry( "shadeSortColumn", KDE_DEFAULT_SHADE_SORT_COLUMN );
}
bool KGlobalSettings::allowDefaultBackgroundImages()
{
KConfigGroup g( KSharedConfig::openConfig(), "General" );
return g.readEntry( "allowDefaultBackgroundImages", KDE_DEFAULT_ALLOW_DEFAULT_BACKGROUND_IMAGES );
}
-struct KFontData
-{
- const char* ConfigGroupKey;
- const char* ConfigKey;
- const char* FontName;
- int Size;
- int Weight;
- QFont::StyleHint StyleHint;
-};
-
-// NOTE: keep in sync with kdebase/workspace/kcontrol/fonts/fonts.cpp
-static const char GeneralId[] = "General";
-static const char DefaultFont[] = "Sans Serif";
-#ifdef Q_OS_MAC
-static const char DefaultMacFont[] = "Lucida Grande";
-#endif
-
-static const KFontData DefaultFontData[KGlobalSettingsData::FontTypesCount] =
-{
-#ifdef Q_OS_MAC
- { GeneralId, "font", DefaultMacFont, 13, -1, QFont::SansSerif },
- { GeneralId, "fixed", "Monaco", 10, -1, QFont::TypeWriter },
- { GeneralId, "toolBarFont", DefaultMacFont, 11, -1, QFont::SansSerif },
- { GeneralId, "menuFont", DefaultMacFont, 13, -1, QFont::SansSerif },
-#else
- { GeneralId, "font", DefaultFont, 9, -1, QFont::SansSerif },
- { GeneralId, "fixed", "Monospace", 9, -1, QFont::TypeWriter },
- { GeneralId, "toolBarFont", DefaultFont, 8, -1, QFont::SansSerif },
- { GeneralId, "menuFont", DefaultFont, 9, -1, QFont::SansSerif },
-#endif
- { "WM", "activeFont", DefaultFont, 8, -1, QFont::SansSerif },
- { GeneralId, "taskbarFont", DefaultFont, 9, -1, QFont::SansSerif },
- { GeneralId, "smallestReadableFont", DefaultFont, 8, -1, QFont::SansSerif }
-};
-
-QFont KGlobalSettingsData::font( FontTypes fontType )
+//inspired in old KGlobalSettingsData code
+QFont constructFontFromConfig(const char* groupKey, const char* configKey)
{
- QFont* cachedFont = mFonts[fontType];
-
- if (!cachedFont)
- {
- const KFontData& fontData = DefaultFontData[fontType];
- cachedFont = new QFont( fontData.FontName, fontData.Size, fontData.Weight );
- cachedFont->setStyleHint( fontData.StyleHint );
-
- const KConfigGroup configGroup( KSharedConfig::openConfig(), fontData.ConfigGroupKey );
- *cachedFont = configGroup.readEntry( fontData.ConfigKey, *cachedFont );
-
- mFonts[fontType] = cachedFont;
- }
-
- return *cachedFont;
+ const KConfigGroup configGroup( KSharedConfig::openConfig(), groupKey );
+ QFont ret;
+ ret.setStyleHint(QFont::SansSerif);
+ ret = configGroup.readEntry( configKey, ret );
+ return ret;
}
QFont KGlobalSettings::generalFont()
{
- return KGlobalSettingsData::self()->font( KGlobalSettingsData::GeneralFont );
+ return QFontDatabase::systemFont(QFontDatabase::GeneralFont);
}
QFont KGlobalSettings::fixedFont()
{
- return KGlobalSettingsData::self()->font( KGlobalSettingsData::FixedFont );
+ return QFontDatabase::systemFont(QFontDatabase::FixedFont);
}
-QFont KGlobalSettings::toolBarFont()
+QFont KGlobalSettings::windowTitleFont()
{
- return KGlobalSettingsData::self()->font( KGlobalSettingsData::ToolbarFont );
+ return QFontDatabase::systemFont(QFontDatabase::TitleFont);
}
-QFont KGlobalSettings::menuFont()
+QFont KGlobalSettings::smallestReadableFont()
{
- return KGlobalSettingsData::self()->font( KGlobalSettingsData::MenuFont );
+ return QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont);
}
-QFont KGlobalSettings::windowTitleFont()
+QFont KGlobalSettings::toolBarFont()
{
- return KGlobalSettingsData::self()->font( KGlobalSettingsData::WindowTitleFont );
+ return constructFontFromConfig("General", "toolBarFont");
}
-QFont KGlobalSettings::taskbarFont()
+QFont KGlobalSettings::menuFont()
{
- return KGlobalSettingsData::self()->font( KGlobalSettingsData::TaskbarFont );
+ return constructFontFromConfig("General", "menuFont");
}
-QFont KGlobalSettings::smallestReadableFont()
+QFont KGlobalSettings::taskbarFont()
{
- return KGlobalSettingsData::self()->font( KGlobalSettingsData::SmallestReadableFont );
+ return constructFontFromConfig("General", "taskbarFont");
}
-
-QFont KGlobalSettingsData::largeFont( const QString& text )
+QFont KGlobalSettings::Private::largeFont( const QString& text )
{
QFontDatabase db;
QStringList fam = db.families();
// Move a bunch of preferred fonts to the front.
// most preferred last
static const char* const PreferredFontNames[] =
{
"Arial",
"Sans Serif",
"Verdana",
"Tahoma",
"Lucida Sans",
"Lucidux Sans",
"Nimbus Sans",
"Gothic I"
};
static const unsigned int PreferredFontNamesCount = sizeof(PreferredFontNames)/sizeof(const char*);
for( unsigned int i=0; i0)
fam.prepend(fontName);
}
if (mLargeFont) {
fam.prepend(mLargeFont->family());
delete mLargeFont;
}
for(QStringList::ConstIterator it = fam.constBegin();
it != fam.constEnd(); ++it)
{
if (db.isSmoothlyScalable(*it) && !db.isFixedPitch(*it))
{
QFont font(*it);
font.setPixelSize(75);
QFontMetrics metrics(font);
int h = metrics.height();
if ((h < 60) || ( h > 90))
continue;
bool ok = true;
for(int i = 0; i < text.length(); i++)
{
if (!metrics.inFont(text[i]))
{
ok = false;
break;
}
}
if (!ok)
continue;
font.setPointSize(48);
mLargeFont = new QFont(font);
return *mLargeFont;
}
}
- mLargeFont = new QFont( font(GeneralFont) );
+ mLargeFont = new QFont( q->generalFont() );
mLargeFont->setPointSize(48);
return *mLargeFont;
}
-QFont KGlobalSettings::largeFont( const QString& text )
-{
- return KGlobalSettingsData::self()->largeFont( text );
-}
-void KGlobalSettingsData::dropFontSettingsCache()
+QFont KGlobalSettings::largeFont( const QString& text )
{
- for( int i=0; id->largeFont( text );
}
-KGlobalSettings::KMouseSettings& KGlobalSettingsData::mouseSettings()
+KGlobalSettings::KMouseSettings& KGlobalSettings::Private::mouseSettings()
{
if (!mMouseSettings)
{
mMouseSettings = new KGlobalSettings::KMouseSettings;
KGlobalSettings::KMouseSettings& s = *mMouseSettings; // for convenience
#ifndef Q_OS_WIN
KConfigGroup g( KSharedConfig::openConfig(), "Mouse" );
QString setting = g.readEntry("MouseButtonMapping");
if (setting == "RightHanded")
s.handed = KGlobalSettings::KMouseSettings::RightHanded;
else if (setting == "LeftHanded")
s.handed = KGlobalSettings::KMouseSettings::LeftHanded;
else
{
#if HAVE_X11
// get settings from X server
// This is a simplified version of the code in input/mouse.cpp
// Keep in sync !
s.handed = KGlobalSettings::KMouseSettings::RightHanded;
unsigned char map[20];
int num_buttons = XGetPointerMapping(QX11Info::display(), map, 20);
if( num_buttons == 2 )
{
if ( (int)map[0] == 1 && (int)map[1] == 2 )
s.handed = KGlobalSettings::KMouseSettings::RightHanded;
else if ( (int)map[0] == 2 && (int)map[1] == 1 )
s.handed = KGlobalSettings::KMouseSettings::LeftHanded;
}
else if( num_buttons >= 3 )
{
if ( (int)map[0] == 1 && (int)map[2] == 3 )
s.handed = KGlobalSettings::KMouseSettings::RightHanded;
else if ( (int)map[0] == 3 && (int)map[2] == 1 )
s.handed = KGlobalSettings::KMouseSettings::LeftHanded;
}
#else
// FIXME: Implement on other platforms
#endif
}
#endif //Q_OS_WIN
}
#ifdef Q_OS_WIN
//not cached
#ifndef _WIN32_WCE
mMouseSettings->handed = (GetSystemMetrics(SM_SWAPBUTTON) ?
KGlobalSettings::KMouseSettings::LeftHanded :
KGlobalSettings::KMouseSettings::RightHanded);
#else
// There is no mice under wince
mMouseSettings->handed =KGlobalSettings::KMouseSettings::RightHanded;
#endif
#endif
return *mMouseSettings;
}
// KDE5: make this a const return?
KGlobalSettings::KMouseSettings & KGlobalSettings::mouseSettings()
{
- return KGlobalSettingsData::self()->mouseSettings();
-}
-
-void KGlobalSettingsData::dropMouseSettingsCache()
-{
-#ifndef Q_OS_WIN
- delete mMouseSettings;
- mMouseSettings = 0;
-#endif
+ return self()->d->mouseSettings();
}
QString KGlobalSettings::desktopPath()
{
QString path = QStandardPaths::writableLocation( QStandardPaths::DesktopLocation );
return path.isEmpty() ? QDir::homePath() : path;
}
// This was the KDE-specific autostart folder in KDEHOME.
// KDE 5 : re-evaluate this, I'd say the xdg autostart spec supersedes this, and is sufficient
// (since there's a GUI for creating the necessary desktop files)
#if 0
QString KGlobalSettings::autostartPath()
{
QString s_autostartPath;
KConfigGroup g( KSharedConfig::openConfig(), "Paths" );
s_autostartPath = KGlobal::dirs()->localkdedir() + "Autostart/";
s_autostartPath = g.readPathEntry( "Autostart" , s_autostartPath );
s_autostartPath = QDir::cleanPath( s_autostartPath );
if ( !s_autostartPath.endsWith( '/' ) ) {
s_autostartPath.append( QLatin1Char( '/' ) );
}
return s_autostartPath;
}
#endif
QString KGlobalSettings::documentPath()
{
QString path = QStandardPaths::writableLocation( QStandardPaths::DocumentsLocation );
return path.isEmpty() ? QDir::homePath() : path;
}
QString KGlobalSettings::downloadPath()
{
QString path = QStandardPaths::writableLocation( QStandardPaths::DownloadLocation );
return path.isEmpty() ? QDir::homePath() : path;
}
QString KGlobalSettings::videosPath()
{
QString path = QStandardPaths::writableLocation( QStandardPaths::MoviesLocation );
return path.isEmpty() ? QDir::homePath() : path;
}
QString KGlobalSettings::picturesPath()
{
QString path = QStandardPaths::writableLocation( QStandardPaths::PicturesLocation );
return path.isEmpty() ? QDir::homePath() :path;
}
QString KGlobalSettings::musicPath()
{
QString path = QStandardPaths::writableLocation( QStandardPaths::MusicLocation );
return path.isEmpty() ? QDir::homePath() : path;
}
bool KGlobalSettings::isMultiHead()
{
#ifdef Q_OS_WIN
return GetSystemMetrics(SM_CMONITORS) > 1;
#else
QByteArray multiHead = qgetenv("KDE_MULTIHEAD");
if (!multiHead.isEmpty()) {
return (multiHead.toLower() == "true");
}
return false;
#endif
}
bool KGlobalSettings::wheelMouseZooms()
{
KConfigGroup g( KSharedConfig::openConfig(), "KDE" );
return g.readEntry( "WheelMouseZooms", KDE_DEFAULT_WHEEL_ZOOM );
}
QRect KGlobalSettings::splashScreenDesktopGeometry()
{
return QApplication::desktop()->screenGeometry(QCursor::pos());
}
QRect KGlobalSettings::desktopGeometry(const QPoint& point)
{
return QApplication::desktop()->screenGeometry(point);
}
QRect KGlobalSettings::desktopGeometry(const QWidget* w)
{
return QApplication::desktop()->screenGeometry(w);
}
bool KGlobalSettings::showIconsOnPushButtons()
{
KConfigGroup g( KSharedConfig::openConfig(), "KDE" );
return g.readEntry("ShowIconsOnPushButtons",
KDE_DEFAULT_ICON_ON_PUSHBUTTON);
}
bool KGlobalSettings::naturalSorting()
{
KConfigGroup g( KSharedConfig::openConfig(), "KDE" );
return g.readEntry("NaturalSorting",
KDE_DEFAULT_NATURAL_SORTING);
}
KGlobalSettings::GraphicEffects KGlobalSettings::graphicEffectsLevel()
{
// This variable stores whether _graphicEffects has the default value because it has not been
// loaded yet, or if it has been loaded from the user settings or defaults and contains a valid
// value.
static bool _graphicEffectsInitialized = false;
if (!_graphicEffectsInitialized) {
_graphicEffectsInitialized = true;
Private::reloadStyleSettings();
}
return _graphicEffects;
}
KGlobalSettings::GraphicEffects KGlobalSettings::graphicEffectsLevelDefault()
{
// For now, let always enable animations by default. The plan is to make
// this code a bit smarter. (ereslibre)
return ComplexAnimationEffects;
}
#ifndef KDE_NO_DEPRECATED
bool KGlobalSettings::showFilePreview(const QUrl &url)
{
KConfigGroup g(KSharedConfig::openConfig(), "PreviewSettings");
bool defaultSetting = url.isLocalFile(); // ## incorrect, use KProtocolInfo::showFilePreview instead
return g.readEntry(url.scheme(), defaultSetting );
}
#endif
bool KGlobalSettings::opaqueResize()
{
KConfigGroup g( KSharedConfig::openConfig(), "KDE" );
return g.readEntry("OpaqueResize", KDE_DEFAULT_OPAQUE_RESIZE);
}
int KGlobalSettings::buttonLayout()
{
KConfigGroup g( KSharedConfig::openConfig(), "KDE" );
return g.readEntry("ButtonLayout", KDE_DEFAULT_BUTTON_LAYOUT);
}
#if 0 // HAVE_X11 && QT_VERSION >= QT_VERSION_CHECK(5,0,0)
// Taken from Qt-4.x qt_x11_apply_settings_in_all_apps since Qt5 doesn't have it anymore.
// TODO: evaluate if this is still needed
// TODO: if yes, this code should be an invokable method of the qxcb platform plugin?
// TODO: it looks like the handling code for this in QPA is missing, too...
static void x11_apply_settings_in_all_apps()
{
QByteArray stamp;
QDataStream s(&stamp, QIODevice::WriteOnly);
s << QDateTime::currentDateTime();
QByteArray settings_atom_name("_QT_SETTINGS_TIMESTAMP_");
settings_atom_name += XDisplayString(QX11Info::display());
xcb_connection_t *xcb_conn = QX11Info::connection();
xcb_intern_atom_cookie_t cookie = xcb_intern_atom(xcb_conn, false, settings_atom_name.size(), settings_atom_name.constData());
xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(xcb_conn, cookie, 0);
xcb_atom_t atom = reply->atom;
free(reply);
xcb_change_property(xcb_conn, XCB_PROP_MODE_REPLACE, QX11Info::appRootWindow(), atom, XCB_ATOM_ATOM,
8, stamp.size(), (const void *)stamp.constData());
//XChangeProperty(QX11Info::display(), QX11Info::appRootWindow(0),
//ATOM(_QT_SETTINGS_TIMESTAMP), ATOM(_QT_SETTINGS_TIMESTAMP), 8,
//PropModeReplace, (unsigned char *)stamp.data(), stamp.size());
}
#endif
void KGlobalSettings::emitChange(ChangeType changeType, int arg)
{
switch (changeType) {
case IconChanged:
KIconLoader::emitChange(KIconLoader::Group(arg));
- break;
case ToolbarStyleChanged:
KToolBar::emitToolbarStyleChanged();
break;
- default:
+ case FontChanged: {
+ QDBusMessage message = QDBusMessage::createSignal("/KDEPlatformTheme", "org.kde.KDEPlatformTheme", "refreshFonts" );
+ QDBusConnection::sessionBus().send(message);
+ } break;
+ default: {
QDBusMessage message = QDBusMessage::createSignal("/KGlobalSettings", "org.kde.KGlobalSettings", "notifyChange" );
QList args;
args.append(static_cast(changeType));
args.append(arg);
message.setArguments(args);
QDBusConnection::sessionBus().send(message);
+ } break;
+
}
}
void KGlobalSettings::Private::_k_slotIconChange(int arg)
{
_k_slotNotifyChange(IconChanged, arg);
}
void KGlobalSettings::Private::_k_slotNotifyChange(int changeType, int arg)
{
switch(changeType) {
case StyleChanged:
if (activated) {
KSharedConfig::openConfig()->reparseConfiguration();
kdisplaySetStyle();
}
break;
case ToolbarStyleChanged:
KSharedConfig::openConfig()->reparseConfiguration();
emit q->toolbarAppearanceChanged(arg);
break;
case PaletteChanged:
if (activated) {
KSharedConfig::openConfig()->reparseConfiguration();
paletteCreated = false;
kdisplaySetPalette();
}
break;
case FontChanged:
- KSharedConfig::openConfig()->reparseConfiguration();
- KGlobalSettingsData::self()->dropFontSettingsCache();
- if (activated) {
- kdisplaySetFont();
- }
+ Q_ASSERT(false && "shouldn't get here now...");
break;
case SettingsChanged: {
KSharedConfig::openConfig()->reparseConfiguration();
SettingsCategory category = static_cast(arg);
if (category == SETTINGS_QT) {
if (activated) {
propagateQtSettings();
}
} else {
switch (category) {
case SETTINGS_STYLE:
reloadStyleSettings();
break;
case SETTINGS_MOUSE:
- KGlobalSettingsData::self()->dropMouseSettingsCache();
+ self()->d->dropMouseSettingsCache();
break;
case SETTINGS_LOCALE:
// QT5 TODO REPLACEMENT ? KLocale::global()->reparseConfiguration();
break;
default:
break;
}
emit q->settingsChanged(category);
}
break;
}
case IconChanged:
QPixmapCache::clear();
KSharedConfig::openConfig()->reparseConfiguration();
emit q->iconChanged(arg);
break;
case CursorChanged:
applyCursorTheme();
break;
case BlockShortcuts:
// FIXME KAccel port
//KGlobalAccel::blockShortcuts(arg);
emit q->blockShortcuts(arg); // see kwin
break;
case NaturalSortingChanged:
emit q->naturalSortingChanged();
break;
default:
qWarning() << "Unknown type of change in KGlobalSettings::slotNotifyChange: " << changeType;
}
}
// Set by KApplication
#pragma message("FIXME: KWidgets depends on KApplication")
KDEUI_EXPORT QString kde_overrideStyle;
void KGlobalSettings::Private::applyGUIStyle()
{
#if 0 // Disabled for KF5. TODO Qt5: check that the KDE style is correctly applied.
//Platform plugin only loaded on X11 systems
#if HAVE_X11
if (!kde_overrideStyle.isEmpty()) {
const QLatin1String currentStyleName(qApp->style()->metaObject()->className());
if (0 != kde_overrideStyle.compare(currentStyleName, Qt::CaseInsensitive) &&
0 != (QString(kde_overrideStyle + QLatin1String("Style"))).compare(currentStyleName, Qt::CaseInsensitive)) {
qApp->setStyle(kde_overrideStyle);
}
} else {
emit q->kdisplayStyleChanged();
}
#else
const QLatin1String currentStyleName(qApp->style()->metaObject()->className());
if (kde_overrideStyle.isEmpty()) {
const QString &defaultStyle = KStyle::defaultStyle();
const KConfigGroup pConfig(KSharedConfig::openConfig(), "General");
const QString &styleStr = pConfig.readEntry("widgetStyle", defaultStyle);
if (styleStr.isEmpty() ||
// check whether we already use the correct style to return then
// (workaround for Qt misbehavior to avoid double style initialization)
0 == (QString(styleStr + QLatin1String("Style"))).compare(currentStyleName, Qt::CaseInsensitive) ||
0 == styleStr.compare(currentStyleName, Qt::CaseInsensitive)) {
return;
}
QStyle* sp = QStyleFactory::create( styleStr );
if (sp && currentStyleName == sp->metaObject()->className()) {
delete sp;
return;
}
// If there is no default style available, try falling back any available style
if ( !sp && styleStr != defaultStyle)
sp = QStyleFactory::create( defaultStyle );
if ( !sp )
sp = QStyleFactory::create( QStyleFactory::keys().first() );
qApp->setStyle(sp);
} else if (0 != kde_overrideStyle.compare(currentStyleName, Qt::CaseInsensitive) &&
0 != (QString(kde_overrideStyle + QLatin1String("Style"))).compare(currentStyleName, Qt::CaseInsensitive)) {
qApp->setStyle(kde_overrideStyle);
}
emit q->kdisplayStyleChanged();
#endif //HAVE_X11
#endif
}
QPalette KGlobalSettings::createApplicationPalette(const KSharedConfigPtr &config)
{
return self()->d->createApplicationPalette(config);
}
QPalette KGlobalSettings::createNewApplicationPalette(const KSharedConfigPtr &config)
{
return self()->d->createNewApplicationPalette(config);
}
QPalette KGlobalSettings::Private::createApplicationPalette(const KSharedConfigPtr &config)
{
// This method is typically called once by KQGuiPlatformPlugin::palette and once again
// by kdisplaySetPalette(), so we cache the palette to save time.
if (config == KSharedConfig::openConfig() && paletteCreated) {
return applicationPalette;
}
return createNewApplicationPalette(config);
}
QPalette KGlobalSettings::Private::createNewApplicationPalette(const KSharedConfigPtr &config)
{
QPalette palette = KColorScheme::createApplicationPalette(config);
if (config == KSharedConfig::openConfig()) {
paletteCreated = true;
applicationPalette = palette;
}
return palette;
}
void KGlobalSettings::Private::kdisplaySetPalette()
{
#if !defined(Q_OS_WINCE)
if (!kdeFullSession) {
return;
}
QApplication::setPalette( q->createApplicationPalette() );
emit q->kdisplayPaletteChanged();
emit q->appearanceChanged();
#endif
}
void KGlobalSettings::Private::kdisplaySetFont()
{
#if !defined(Q_OS_WINCE)
if (!kdeFullSession) {
return;
}
- KGlobalSettingsData* data = KGlobalSettingsData::self();
-
- QApplication::setFont( data->font(KGlobalSettingsData::GeneralFont) );
- const QFont menuFont = data->font( KGlobalSettingsData::MenuFont );
- QApplication::setFont( menuFont, "QMenuBar" );
- QApplication::setFont( menuFont, "QMenu" );
- QApplication::setFont( menuFont, "KPopupTitle" );
- QApplication::setFont( data->font(KGlobalSettingsData::ToolbarFont), "QToolBar" );
emit q->kdisplayFontChanged();
- emit q->appearanceChanged();
#endif
}
void KGlobalSettings::Private::kdisplaySetStyle()
{
applyGUIStyle();
// Reread palette from config file.
kdisplaySetPalette();
}
void KGlobalSettings::Private::reloadStyleSettings()
{
KConfigGroup g( KSharedConfig::openConfig(), "KDE-Global GUI Settings" );
// Asking for hasKey we do not ask for graphicEffectsLevelDefault() that can
// contain some very slow code. If we can save that time, do it. (ereslibre)
if (g.hasKey("GraphicEffectsLevel")) {
_graphicEffects = ((GraphicEffects) g.readEntry("GraphicEffectsLevel", QVariant((int) NoEffects)).toInt());
return;
}
_graphicEffects = KGlobalSettings::graphicEffectsLevelDefault();
}
void KGlobalSettings::Private::applyCursorTheme()
{
#if HAVE_X11 && defined(HAVE_XCURSOR)
KConfig config("kcminputrc");
KConfigGroup g(&config, "Mouse");
QString theme = g.readEntry("cursorTheme", QString());
int size = g.readEntry("cursorSize", -1);
// Default cursor size is 16 points
if (size == -1)
{
QApplication *app = static_cast(QApplication::instance());
size = app->desktop()->screen(0)->logicalDpiY() * 16 / 72;
}
// Note that in X11R7.1 and earlier, calling XcursorSetTheme()
// with a NULL theme would cause Xcursor to use "default", but
// in 7.2 and later it will cause it to revert to the theme that
// was configured when the application was started.
XcursorSetTheme(QX11Info::display(), theme.isNull() ?
"default" : QFile::encodeName(theme));
XcursorSetDefaultSize(QX11Info::display(), size);
emit q->cursorChanged();
#endif
}
void KGlobalSettings::Private::propagateQtSettings()
{
KConfigGroup cg( KSharedConfig::openConfig(), "KDE" );
#ifndef Q_OS_WIN
int num = cg.readEntry("CursorBlinkRate", QApplication::cursorFlashTime());
if ((num != 0) && (num < 200))
num = 200;
if (num > 2000)
num = 2000;
QApplication::setCursorFlashTime(num);
#else
int num;
#endif
num = cg.readEntry("DoubleClickInterval", QApplication::doubleClickInterval());
QApplication::setDoubleClickInterval(num);
num = cg.readEntry("StartDragTime", QApplication::startDragTime());
QApplication::setStartDragTime(num);
num = cg.readEntry("StartDragDist", QApplication::startDragDistance());
QApplication::setStartDragDistance(num);
num = cg.readEntry("WheelScrollLines", QApplication::wheelScrollLines());
QApplication::setWheelScrollLines(num);
bool showIcons = cg.readEntry("ShowIconsInMenuItems", !QApplication::testAttribute(Qt::AA_DontShowIconsInMenus));
QApplication::setAttribute(Qt::AA_DontShowIconsInMenus, !showIcons);
// KDE5: this seems fairly pointless
emit q->settingsChanged(SETTINGS_QT);
}
+void KGlobalSettings::Private::dropMouseSettingsCache()
+{
+#ifndef Q_OS_WIN
+ delete self()->d->mMouseSettings;
+ self()->d->mMouseSettings = 0;
+#endif
+}
+
#include "moc_kglobalsettings.cpp"
diff --git a/khtml/css/cssstyleselector.cpp b/khtml/css/cssstyleselector.cpp
index b5eb37011f..ebc2e51171 100644
--- a/khtml/css/cssstyleselector.cpp
+++ b/khtml/css/cssstyleselector.cpp
@@ -1,4557 +1,4557 @@
/**
* This file is part of the CSS implementation for KDE.
*
* Copyright 1999-2003 Lars Knoll (knoll@kde.org)
* Copyright 2003-2004 Apple Computer, Inc.
* Copyright 2004-2010 Allan Sandfeld Jensen (kde@carewolf.com)
* Copyright 2004-2008 Germain Garand (germain@ebooksfrance.org)
* Copyright 2008 Vyacheslav Tokarev (tsjoker@gmail.com)
* (C) 2005, 2006, 2008 Apple Computer, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "css/cssstyleselector.h"
#include "rendering/render_style.h"
#include "css/css_stylesheetimpl.h"
#include "css/css_ruleimpl.h"
#include "css/css_valueimpl.h"
#include "css/csshelper.h"
#include "css/css_webfont.h"
#include "rendering/render_object.h"
#include "html/html_documentimpl.h"
#include "html/html_elementimpl.h"
#include "xml/dom_elementimpl.h"
#include "xml/dom_restyler.h"
#include "dom/css_rule.h"
#include "dom/css_value.h"
#include "khtml_global.h"
#include "khtmlpart_p.h"
using namespace khtml;
using namespace DOM;
#include "css/cssproperties.h"
#include "css/cssvalues.h"
#include "css/css_mediaquery.h"
#include "misc/khtmllayout.h"
#include "khtml_settings.h"
#include "misc/helper.h"
#include "misc/loader.h"
#include "rendering/font.h"
#include "khtmlview.h"
#include "khtml_part.h"
#include
-#include
#include
#include
#include
#include
+#include
+#include
#include
#include
#include
-#include
// keep in sync with html4.css'
#define KHTML_STYLE_VERSION 1
#undef PRELATIVE
#undef PABSOLUTE
// handle value "inherit" on a default inherited property
#define HANDLE_INHERIT_ON_INHERITED_PROPERTY(prop, Prop) \
if (isInherit) \
{\
style->set##Prop(parentStyle->prop());\
return;\
}
// handle value "inherit" on a default non-inherited property
#define HANDLE_INHERIT_ON_NONINHERITED_PROPERTY(prop, Prop) \
if (isInherit) \
{\
style->setInheritedNoninherited(true);\
style->set##Prop(parentStyle->prop());\
return;\
}
#define HANDLE_INITIAL(prop, Prop) \
if (isInitial) \
{\
style->set##Prop(RenderStyle::initial##Prop());\
return;\
}
#define HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(prop, Prop) \
HANDLE_INITIAL(prop, Prop) \
else \
HANDLE_INHERIT_ON_NONINHERITED_PROPERTY(prop, Prop)
#define HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(prop, Prop) \
HANDLE_INITIAL(prop, Prop) \
else \
HANDLE_INHERIT_ON_INHERITED_PROPERTY(prop, Prop)
// all non-inherited properties
#define HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \
HANDLE_INHERIT_ON_NONINHERITED_PROPERTY(prop, Prop) \
else if (isInitial) \
{\
style->set##Prop(RenderStyle::initial##Value());\
return;\
}
#define HANDLE_BACKGROUND_INHERIT_AND_INITIAL(prop, Prop) \
if (isInherit) { \
BackgroundLayer* currChild = style->accessBackgroundLayers(); \
BackgroundLayer* prevChild = 0; \
const BackgroundLayer* currParent = parentStyle->backgroundLayers(); \
while (currParent && currParent->is##Prop##Set()) { \
if (!currChild) { \
/* Need to make a new layer.*/ \
currChild = new BackgroundLayer(); \
prevChild->setNext(currChild); \
} \
currChild->set##Prop(currParent->prop()); \
prevChild = currChild; \
currChild = prevChild->next(); \
currParent = currParent->next(); \
} \
\
while (currChild) { \
/* Reset any remaining layers to not have the property set. */ \
currChild->clear##Prop(); \
currChild = currChild->next(); \
} \
} else if (isInitial) { \
BackgroundLayer* currChild = style->accessBackgroundLayers(); \
currChild->set##Prop(RenderStyle::initial##Prop()); \
for (currChild = currChild->next(); currChild; currChild = currChild->next()) \
currChild->clear##Prop(); \
}
#define HANDLE_BACKGROUND_VALUE(prop, Prop, value) { \
HANDLE_BACKGROUND_INHERIT_AND_INITIAL(prop, Prop) \
else { \
if (!value->isPrimitiveValue() && !value->isValueList()) \
return; \
BackgroundLayer* currChild = style->accessBackgroundLayers(); \
BackgroundLayer* prevChild = 0; \
if (value->isPrimitiveValue()) { \
map##Prop(currChild, value); \
currChild = currChild->next(); \
} \
else { \
/* Walk each value and put it into a layer, creating new layers as needed. */ \
CSSValueListImpl* valueList = static_cast(value); \
for (unsigned int i = 0; i < valueList->length(); i++) { \
if (!currChild) { \
/* Need to make a new layer to hold this value */ \
currChild = new BackgroundLayer(); \
prevChild->setNext(currChild); \
} \
map##Prop(currChild, valueList->item(i)); \
prevChild = currChild; \
currChild = currChild->next(); \
} \
} \
while (currChild) { \
/* Reset all remaining layers to not have the property set. */ \
currChild->clear##Prop(); \
currChild = currChild->next(); \
} \
} }
#define HANDLE_INHERIT_COND(propID, prop, Prop) \
if (id == propID) \
{\
style->set##Prop(parentStyle->prop());\
return;\
}
#define HANDLE_INHERIT_COND_WITH_BACKUP(propID, prop, propAlt, Prop) \
if (id == propID) { \
if (parentStyle->prop().isValid()) \
style->set##Prop(parentStyle->prop()); \
else \
style->set##Prop(parentStyle->propAlt()); \
return; \
}
#define HANDLE_INITIAL_COND(propID, Prop) \
if (id == propID) \
{\
style->set##Prop(RenderStyle::initial##Prop());\
return;\
}
#define HANDLE_INITIAL_COND_WITH_VALUE(propID, Prop, Value) \
if (id == propID) \
{\
style->set##Prop(RenderStyle::initial##Value());\
return;\
}
namespace khtml {
CSSStyleSelectorList *CSSStyleSelector::s_defaultStyle;
CSSStyleSelectorList *CSSStyleSelector::s_defaultQuirksStyle;
CSSStyleSelectorList *CSSStyleSelector::s_defaultNonCSSHintsStyle;
CSSStyleSelectorList *CSSStyleSelector::s_defaultPrintStyle;
CSSStyleSheetImpl *CSSStyleSelector::s_defaultSheet;
CSSStyleSheetImpl *CSSStyleSelector::s_defaultNonCSSHintsSheet;
RenderStyle* CSSStyleSelector::styleNotYetAvailable;
CSSStyleSheetImpl *CSSStyleSelector::s_quirksSheet;
enum PseudoState { PseudoUnknown, PseudoNone, PseudoLink, PseudoVisited};
static PseudoState pseudoState;
CSSStyleSelector::CSSStyleSelector( DocumentImpl* doc, QString userStyleSheet, StyleSheetListImpl *styleSheets,
const QUrl &url, bool _strictParsing )
{
KHTMLView* view = doc->view();
KHTMLPart* part = doc->part();
m_fontSelector = new CSSFontSelector( doc );
init(part ? part->settings() : 0, doc);
strictParsing = _strictParsing;
selectors = 0;
selectorCache = 0;
propertiesBuffer = 0;
nextPropertyIndexes = 0;
userStyle = 0;
userSheet = 0;
logicalDpiY = doc->logicalDpiY();
if(logicalDpiY) // this may be null, not everyone uses khtmlview (Niko)
computeFontSizes(logicalDpiY, part ? part->fontScaleFactor() : 100);
// build a limited default style suitable to evaluation of media queries
// containing relative constraints, like "screen and (max-width: 10em)"
setupDefaultRootStyle(doc);
if (view)
m_medium = new MediaQueryEvaluator(view->mediaType(), view->part(), m_rootDefaultStyle);
else
m_medium = new MediaQueryEvaluator("all", 0, m_rootDefaultStyle);
if ( !userStyleSheet.isEmpty() ) {
userSheet = new DOM::CSSStyleSheetImpl(doc);
userSheet->parseString( DOMString( userStyleSheet ) );
userStyle = new CSSStyleSelectorList();
userStyle->append( userSheet, m_medium, this );
}
// add stylesheets from document
authorStyle = 0;
implicitStyle = 0;
foreach (StyleSheetImpl* sh, styleSheets->styleSheets) {
if ( sh->isCSSStyleSheet() ) {
if ( static_cast(sh)->implicit() ) {
if (!implicitStyle)
implicitStyle = new CSSStyleSelectorList();
implicitStyle->append( static_cast( sh ), m_medium, this );
} else if ( sh->isCSSStyleSheet() && !sh->disabled()) {
if (!authorStyle)
authorStyle = new CSSStyleSelectorList();
authorStyle->append( static_cast( sh ), m_medium, this );
}
}
}
buildLists();
//kDebug( 6080 ) << "number of style sheets in document " << authorStyleSheets.count();
//kDebug( 6080 ) << "CSSStyleSelector: author style has " << authorStyle->count() << " elements";
QUrl u = url;
u.setQuery( QString() );
u.setFragment( QString() );
encodedurl.file = u.url();
int pos = encodedurl.file.lastIndexOf('/');
encodedurl.path = encodedurl.file;
if ( pos > 0 ) {
encodedurl.path.truncate( pos );
encodedurl.path += '/';
}
u.setPath( QString() );
encodedurl.host = u.url();
//kDebug() << "CSSStyleSelector::CSSStyleSelector encoded url " << encodedurl.path;
}
CSSStyleSelector::CSSStyleSelector( CSSStyleSheetImpl *sheet )
{
m_fontSelector = new CSSFontSelector( sheet->doc() );
init(0L, 0L);
KHTMLView *view = sheet->doc()->view();
setupDefaultRootStyle(sheet->doc());
if (view)
m_medium = new MediaQueryEvaluator(view->mediaType(), view->part(), m_rootDefaultStyle);
else
m_medium = new MediaQueryEvaluator("screen", 0, m_rootDefaultStyle);
if (sheet->implicit()) {
implicitStyle = new CSSStyleSelectorList();
implicitStyle->append( sheet, m_medium, this );
} else {
authorStyle = new CSSStyleSelectorList();
authorStyle->append( sheet, m_medium, this );
}
}
void CSSStyleSelector::init(const KHTMLSettings* _settings, DocumentImpl* doc)
{
element = 0;
settings = _settings;
logicalDpiY = 0;
if(!s_defaultStyle) loadDefaultStyle(settings, doc);
defaultStyle = s_defaultStyle;
defaultPrintStyle = s_defaultPrintStyle;
defaultQuirksStyle = s_defaultQuirksStyle;
defaultNonCSSHintsStyle = s_defaultNonCSSHintsStyle;
m_rootDefaultStyle = 0;
m_medium = 0;
}
CSSStyleSelector::~CSSStyleSelector()
{
clearLists();
delete authorStyle;
delete implicitStyle;
delete userStyle;
delete userSheet;
delete m_rootDefaultStyle;
delete m_medium;
delete m_fontSelector;
}
void CSSStyleSelector::addSheet( CSSStyleSheetImpl *sheet )
{
KHTMLView *view = sheet->doc()->view();
setupDefaultRootStyle(sheet->doc());
delete m_medium; m_medium = 0;
delete authorStyle; authorStyle = 0;
delete implicitStyle; implicitStyle = 0;
if (view)
m_medium = new MediaQueryEvaluator(view->mediaType(), view->part(), m_rootDefaultStyle);
else
m_medium = new MediaQueryEvaluator("screen", 0, m_rootDefaultStyle);
if (sheet->implicit()) {
if (!implicitStyle)
implicitStyle = new CSSStyleSelectorList();
implicitStyle->append( sheet, m_medium, this );
} else {
if (!authorStyle)
authorStyle = new CSSStyleSelectorList();
authorStyle->append( sheet, m_medium, this );
}
}
void CSSStyleSelector::loadDefaultStyle(const KHTMLSettings *s, DocumentImpl *doc)
{
if(s_defaultStyle) return;
MediaQueryEvaluator screenEval("screen");
MediaQueryEvaluator printEval("print");
{
QFile f(QStandardPaths::locate(QStandardPaths::GenericDataLocation, "khtml/css/html4.css" ) );
f.open(QIODevice::ReadOnly);
QByteArray file( f.size()+1, 0 );
int readbytes = f.read( file.data(), f.size() );
f.close();
if ( readbytes >= 0 )
file[readbytes] = '\0';
QString style = QLatin1String( file.data() );
QRegExp checkVersion( "KHTML_STYLE_VERSION:\\s*(\\d+)" );
checkVersion.setMinimal( true );
if (checkVersion.indexIn( style ) == -1 || checkVersion.cap(1).toInt() != KHTML_STYLE_VERSION) {
qFatal( "!!!!!!! ERROR !!!!!!! - KHTML default stylesheet version mismatch. Aborting. Check your installation. File used was: %s. Expected STYLE_VERSION %d\n",
QFileInfo( f ).absoluteFilePath().toLatin1().data(), KHTML_STYLE_VERSION );
}
if(s)
style += s->settingsToCSS();
DOMString str(style);
s_defaultSheet = new DOM::CSSStyleSheetImpl(doc);
s_defaultSheet->parseString( str );
// Collect only strict-mode rules.
s_defaultStyle = new CSSStyleSelectorList();
s_defaultStyle->append( s_defaultSheet, &screenEval, doc->styleSelector() );
s_defaultPrintStyle = new CSSStyleSelectorList();
s_defaultPrintStyle->append( s_defaultSheet, &printEval, doc->styleSelector() );
}
{
QFile f(QStandardPaths::locate(QStandardPaths::GenericDataLocation, "khtml/css/quirks.css" ) );
f.open(QIODevice::ReadOnly);
QByteArray file( f.size()+1, 0 );
int readbytes = f.read( file.data(), f.size() );
f.close();
if ( readbytes >= 0 )
file[readbytes] = '\0';
QString style = QLatin1String( file.data() );
DOMString str(style);
s_quirksSheet = new DOM::CSSStyleSheetImpl(doc);
s_quirksSheet->parseString( str );
// Collect only quirks-mode rules.
s_defaultQuirksStyle = new CSSStyleSelectorList();
s_defaultQuirksStyle->append( s_quirksSheet, &screenEval, doc->styleSelector() );
}
{
QFile f(QStandardPaths::locate(QStandardPaths::GenericDataLocation, "khtml/css/presentational.css" ) );
f.open(QIODevice::ReadOnly);
QByteArray file( f.size()+1, 0 );
int readbytes = f.read( file.data(), f.size() );
f.close();
if ( readbytes >= 0 )
file[readbytes] = '\0';
QString style = QLatin1String( file.data() );
DOMString str(style);
s_defaultNonCSSHintsSheet = new DOM::CSSStyleSheetImpl(doc);
s_defaultNonCSSHintsSheet->parseString( str );
s_defaultNonCSSHintsStyle = new CSSStyleSelectorList();
s_defaultNonCSSHintsStyle->append( s_defaultNonCSSHintsSheet, &screenEval, doc->styleSelector() );
}
//kDebug() << "CSSStyleSelector: default style has " << defaultStyle->count() << " elements";
}
void CSSStyleSelector::clear()
{
delete s_defaultStyle;
delete s_defaultQuirksStyle;
delete s_defaultPrintStyle;
delete s_defaultNonCSSHintsStyle;
delete s_defaultSheet;
delete s_defaultNonCSSHintsSheet;
delete styleNotYetAvailable;
s_defaultStyle = 0;
s_defaultQuirksStyle = 0;
s_defaultPrintStyle = 0;
s_defaultNonCSSHintsStyle = 0;
s_defaultSheet = 0;
s_defaultNonCSSHintsSheet = 0;
styleNotYetAvailable = 0;
}
void CSSStyleSelector::reparseConfiguration()
{
// nice leak, but best we can do right now. hopefully it is only rare.
s_defaultStyle = 0;
s_defaultQuirksStyle = 0;
s_defaultPrintStyle = 0;
s_defaultNonCSSHintsStyle = 0;
s_defaultSheet = 0;
}
#define MAXFONTSIZES 8
void CSSStyleSelector::computeFontSizes(int logicalDpiY, int zoomFactor)
{
computeFontSizesFor(logicalDpiY, zoomFactor, m_fontSizes, false);
computeFontSizesFor(logicalDpiY, zoomFactor, m_fixedFontSizes, true);
}
void CSSStyleSelector::computeFontSizesFor(int logicalDpiY, int zoomFactor, QVector& fontSizes, bool isFixed)
{
#ifdef APPLE_CHANGES
// We don't want to scale the settings by the dpi.
const float toPix = 1.0;
#else
Q_UNUSED( isFixed );
// ### get rid of float / double
float toPix = logicalDpiY/72.0f;
if (toPix < 96.0f/72.0f)
toPix = 96.0f/72.0f;
#endif // ######### fix isFixed code again.
fontSizes.resize( MAXFONTSIZES );
float scale = 1.0;
static const float fontFactors[] = {3.0f/5.0f, 3.0f/4.0f, 8.0f/9.0f, 1.0f, 6.0f/5.0f, 3.0f/2.0f, 2.0f, 3.0f};
static const float smallFontFactors[] = {3.0f/4.0f, 5.0f/6.0f, 8.0f/9.0f, 1.0f, 6.0f/5.0f, 3.0f/2.0f, 2.0f, 3.0f};
float mediumFontSize, minFontSize, factor;
if (!khtml::printpainter) {
scale *= zoomFactor / 100.0;
#ifdef APPLE_CHANGES
if (isFixed)
mediumFontSize = settings->mediumFixedFontSize() * toPix;
else
#endif
mediumFontSize = settings->mediumFontSize() * toPix;
minFontSize = settings->minFontSize() * toPix;
}
else {
// ### depending on something / configurable ?
mediumFontSize = 12;
minFontSize = 6;
}
const float* factors = scale*mediumFontSize >= 12.5 ? fontFactors : smallFontFactors;
for ( int i = 0; i < MAXFONTSIZES; i++ ) {
factor = scale*factors[i];
fontSizes[i] = int(qMax( mediumFontSize*factor +.5f, minFontSize));
//kDebug( 6080 ) << "index: " << i << " factor: " << factors[i] << " font pix size: " << int(qMax( mediumFontSize*factor +.5f, minFontSize));
}
}
#undef MAXFONTSIZES
RenderStyle* CSSStyleSelector::locateSimilarStyle()
{
ElementImpl *s=0, *t=0, *c=0;
if (!element) return 0;
// Check previous siblings.
unsigned count = 0;
NodeImpl* n = element;
do {
for (n = n->previousSibling(); n && !n->isElementNode(); n = n->previousSibling());
if (!n) break;
ElementImpl *e = static_cast(n);
if (++count > 10) break;
if (!s) s = e; // sibling match
if (e->id() != element->id()) continue;
if (!t) t = e; // tag match
if (element->hasClass()) {
if (!e->hasClass()) continue;
const DOMString& class1 = element->getAttribute(ATTR_CLASS);
const DOMString& class2 = e->getAttribute(ATTR_CLASS);
if (class1 != class2) continue;
}
if (!c) c = e; // class match
break;
} while(true);
// if possible return sibling that matches tag and class
if (c && c->renderer() && c->renderer()->style()) return c->renderer()->style();
// second best: return sibling that matches tag
if (t && t->renderer() && t->renderer()->style()) return t->renderer()->style();
// third best: return sibling element
if (s && s->renderer() && s->renderer()->style()) return s->renderer()->style();
// last attempt: return parent element
NodeImpl* p = element->parentNode();
if (p && p->renderer()) return p->renderer()->style();
return 0;
}
static inline void bubbleSort( CSSOrderedProperty **b, CSSOrderedProperty **e )
{
while( b < e ) {
bool swapped = false;
CSSOrderedProperty **y = e+1;
CSSOrderedProperty **x = e;
CSSOrderedProperty **swappedPos = 0;
do {
if ( !((**(--x)) < (**(--y))) ) {
swapped = true;
swappedPos = x;
CSSOrderedProperty *tmp = *y;
*y = *x;
*x = tmp;
}
} while( x != b );
if ( !swapped ) break;
b = swappedPos + 1;
}
}
RenderStyle *CSSStyleSelector::styleForElement(ElementImpl *e, RenderStyle* fallbackParentStyle)
{
if (!e->document()->haveStylesheetsLoaded() || !e->document()->view()) {
if (!styleNotYetAvailable) {
styleNotYetAvailable = new RenderStyle();
styleNotYetAvailable->setDisplay(NONE);
styleNotYetAvailable->ref();
}
return styleNotYetAvailable;
}
// set some variables we will need
pseudoState = PseudoUnknown;
element = e;
parentNode = e->parentNode();
parentStyle = ( parentNode && parentNode->renderer()) ?
parentNode->renderer()->style() : fallbackParentStyle;
view = element->document()->view();
part = view->part();
settings = part->settings();
logicalDpiY = element->document()->logicalDpiY();
// reset dynamic DOM dependencies
e->document()->dynamicDomRestyler().resetDependencies(e);
style = new RenderStyle();
if( parentStyle )
style->inheritFrom( parentStyle );
else
parentStyle = style;
// try to sort out most style rules as early as possible.
quint16 cssTagId = localNamePart(element->id());
int smatch = 0;
int schecked = 0;
// do aggressive selection of selectors to check
// instead of going over whole constructed list,
// skip selectors that won't match for sure (e.g. with different id or class)
QVarLengthArray selectorsForCheck;
// add unknown selectors to always be checked
for (unsigned int i = otherSelector; i < selectors_size; i = nextSimilarSelector[i])
selectorsForCheck.append(i);
// check if we got class attribute on element: add selectors with it to the list
if (e->hasClass()) {
const ClassNames& classNames = element->classNames();
for (unsigned int i = 0; i < classNames.size(); ++i) {
WTF::HashMap::iterator it = classSelector.find((quintptr)classNames[i].impl());
if (it != classSelector.end())
for (unsigned int j = it->second; j < selectors_size; j = nextSimilarSelector[j])
selectorsForCheck.append(j);
}
}
// check if we got id attribute on element: add selectors with it to the list
DOMStringImpl* idValue = element->getAttributeImplById(ATTR_ID);
if (idValue && idValue->length()) {
bool caseSensitive = (e->document()->htmlMode() == DocumentImpl::XHtml) || strictParsing;
AtomicString elementId = caseSensitive ? idValue : idValue->lower();
WTF::HashMap::iterator it = idSelector.find((quintptr)elementId.impl());
if (it != idSelector.end())
for (unsigned int j = it->second; j < selectors_size; j = nextSimilarSelector[j])
selectorsForCheck.append(j);
}
// add all selectors with given local tag
WTF::HashMap::iterator it = tagSelector.find(cssTagId);
if (it != tagSelector.end())
for (unsigned int j = it->second; j < selectors_size; j = nextSimilarSelector[j])
selectorsForCheck.append(j);
// build per-element cache summaries.
prepareToMatchElement(element, true);
propsToApply.clear();
pseudoProps.clear();
// now go over selectors that we prepared for check
// selectors yet in random order, so we store only matched selector indexes to sort after
unsigned amountOfMatchedSelectors = 0;
for (int k = 0; k < selectorsForCheck.size(); ++k) {
unsigned i = selectorsForCheck[k];
quint16 tag = selectors[i]->tagLocalName.id();
if (cssTagId == tag || tag == anyLocalName) {
++schecked;
checkSelector(i, e);
if (selectorCache[i].state == Applies || selectorCache[i].state == AppliesPseudo) {
selectorsForCheck[amountOfMatchedSelectors++] = i;
}
} else
selectorCache[i].state = Invalid;
}
// sort only matched selectors and then collect properties
qSort(selectorsForCheck.data(), selectorsForCheck.data() + amountOfMatchedSelectors);
for (unsigned k = 0; k < amountOfMatchedSelectors; ++k) {
unsigned i = selectorsForCheck[k];
if (selectorCache[i].state == Applies) {
++smatch;
for (unsigned p = selectorCache[i].firstPropertyIndex; p < properties_size; p = nextPropertyIndexes[p])
propsToApply.append(propertiesBuffer + p);
} else if (selectorCache[i].state == AppliesPseudo) {
for (unsigned p = selectorCache[i].firstPropertyIndex; p < properties_size; p = nextPropertyIndexes[p]) {
pseudoProps.append(propertiesBuffer + p);
propertiesBuffer[p].pseudoId = (RenderStyle::PseudoId) selectors[i]->pseudoId;
}
}
}
// clear selectorsForCheck, it shouldn't be used after
selectorsForCheck.clear();
// Inline style declarations, after all others.
// Non-css hints from presentational attributes will also be collected here
// receiving the proper priority so has to cascade from before author rules (cf.CSS 2.1-6.4.4).
addInlineDeclarations(e);
// qDebug( "styleForElement( %s )", e->tagName().string().toLatin1().constData() );
// qDebug( "%d selectors, %d checked, %d match, %d properties ( of %d )",
// selectors_size, schecked, smatch, numPropsToApply, properties_size );
if (propsToApply.size())
bubbleSort(propsToApply.data(), propsToApply.data() + propsToApply.size() - 1);
if (pseudoProps.size())
bubbleSort(pseudoProps.data(), pseudoProps.data() + pseudoProps.size() - 1);
// we can't apply style rules without a view() and a part. This
// tends to happen on delayed destruction of widget Renderobjects
if ( part ) {
fontDirty = false;
if (propsToApply.size()) {
CSSStyleSelector::style = style;
for (unsigned int i = 0; i < propsToApply.size(); ++i) {
if ( fontDirty && propsToApply[i]->priority >= (1 << 30) ) {
// we are past the font properties, time to update to the
// correct font
#ifdef APPLE_CHANGES
checkForGenericFamilyChange(style, parentStyle);
#endif
CSSStyleSelector::style->htmlFont().update( logicalDpiY );
fontDirty = false;
}
DOM::CSSProperty *prop = propsToApply[i]->prop;
// if (prop->m_id == CSS_PROP__KONQ_USER_INPUT) kDebug(6080) << "El: "<nodeName().string() << " user-input: "<<((CSSPrimitiveValueImpl *)prop->value())->getIdent();
// if (prop->m_id == CSS_PROP_TEXT_TRANSFORM) kDebug(6080) << "El: "<nodeName().string();
applyRule( prop->m_id, prop->value() );
}
if ( fontDirty ) {
#ifdef APPLE_CHANGES
checkForGenericFamilyChange(style, parentStyle);
#endif
CSSStyleSelector::style->htmlFont().update( logicalDpiY );
}
}
// Clean up our style object's display and text decorations (among other fixups).
adjustRenderStyle(style, e);
if (pseudoProps.size()) {
fontDirty = false;
//qDebug("%d applying %d pseudo props", e->cssTagId(), pseudoProps->count() );
for (unsigned int i = 0; i < pseudoProps.size(); ++i) {
if ( fontDirty && pseudoProps[i]->priority >= (1 << 30) ) {
// we are past the font properties, time to update to the
// correct font
//We have to do this for all pseudo styles
RenderStyle *pseudoStyle = style->pseudoStyle;
while ( pseudoStyle ) {
pseudoStyle->htmlFont().update( logicalDpiY );
pseudoStyle = pseudoStyle->pseudoStyle;
}
fontDirty = false;
}
RenderStyle *pseudoStyle;
pseudoStyle = style->getPseudoStyle(pseudoProps[i]->pseudoId);
if (!pseudoStyle)
{
pseudoStyle = style->addPseudoStyle(pseudoProps[i]->pseudoId);
if (pseudoStyle)
pseudoStyle->inheritFrom( style );
}
RenderStyle* oldStyle = style;
RenderStyle* oldParentStyle = parentStyle;
parentStyle = style;
style = pseudoStyle;
if ( pseudoStyle ) {
DOM::CSSProperty *prop = pseudoProps[i]->prop;
applyRule( prop->m_id, prop->value() );
}
style = oldStyle;
parentStyle = oldParentStyle;
}
if ( fontDirty ) {
RenderStyle *pseudoStyle = style->pseudoStyle;
while ( pseudoStyle ) {
pseudoStyle->htmlFont().update( logicalDpiY );
pseudoStyle = pseudoStyle->pseudoStyle;
}
}
}
}
// Now adjust all our pseudo-styles.
RenderStyle *pseudoStyle = style->pseudoStyle;
while (pseudoStyle) {
adjustRenderStyle(pseudoStyle, 0);
pseudoStyle = pseudoStyle->pseudoStyle;
}
// Try and share or partially share the style with our siblings
RenderStyle *commonStyle = locateSimilarStyle();
if (commonStyle)
style->compactWith(commonStyle);
// Now return the style.
return style;
}
void CSSStyleSelector::prepareToMatchElement(DOM::ElementImpl* e, bool withDeps)
{
rememberDependencies = withDeps;
element = e;
// build caches for element so it could be used in heuristic for descendant selectors
// go up the tree and cache possible tags, classes and ids
tagCache.clear();
idCache.clear();
classCache.clear();
ElementImpl* current = element;
while (true) {
NodeImpl* parent = current->parentNode();
if (!parent || !parent->isElementNode())
break;
current = static_cast(parent);
if (current->hasClass()) {
const ClassNames& classNames = current->classNames();
for (unsigned i = 0; i < classNames.size(); ++i)
classCache.add((quintptr)classNames[i].impl());
}
DOMStringImpl* idValue = current->getAttributeImplById(ATTR_ID);
if (idValue && idValue->length()) {
bool caseSensitive = (current->document()->htmlMode() == DocumentImpl::XHtml) || strictParsing;
AtomicString currentId = caseSensitive ? idValue : idValue->lower();
// though currentId is local and could be deleted from AtomicStringImpl cache right away
// don't care about that, cause selector values are stable and only they will be checked later
idCache.add((quintptr)currentId.impl());
}
tagCache.add(localNamePart(current->id()));
}
}
void CSSStyleSelector::adjustRenderStyle(RenderStyle* style, DOM::ElementImpl *e)
{
// Cache our original display.
style->setOriginalDisplay(style->display());
if (style->display() != NONE) {
// If we have a
that specifies a float property, in quirks mode we just drop the float
// property.
// Sites also commonly use display:inline/block on
s and
s. In quirks mode we force
// these tags to retain their display types.
if (!strictParsing && e) {
if (e->id() == ID_TD) {
style->setDisplay(TABLE_CELL);
style->setFloating(FNONE);
}
else if (e->id() == ID_TABLE)
style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE : TABLE);
}
// Table headers with a text-align of auto will change the text-align to center.
if (e && e->id() == ID_TH && style->textAlign() == TAAUTO)
style->setTextAlign(CENTER);
// Mutate the display to BLOCK or TABLE for certain cases, e.g., if someone attempts to
// position or float an inline, compact, or run-in. Cache the original display, since it
// may be needed for positioned elements that have to compute their static normal flow
// positions. We also force inline-level roots to be block-level.
if (style->display() != BLOCK && style->display() != TABLE /*&& style->display() != BOX*/ &&
(style->position() == PABSOLUTE || style->position() == PFIXED || style->floating() != FNONE ||
(e && e->document()->documentElement() == e))) {
if (style->display() == INLINE_TABLE)
style->setDisplay(TABLE);
// else if (style->display() == INLINE_BOX)
// style->setDisplay(BOX);
else if (style->display() == LIST_ITEM) {
// It is a WinIE bug that floated list items lose their bullets, so we'll emulate the quirk,
// but only in quirks mode.
if (!strictParsing && style->floating() != FNONE)
style->setDisplay(BLOCK);
}
else
style->setDisplay(BLOCK);
} else if (e && e->id() == ID_BUTTON && style->isOriginalDisplayInlineType()) {
//