diff --git a/KDE5PORTING.html b/KDE5PORTING.html index cd5d0fac7f..e47ce5f26c 100644 --- a/KDE5PORTING.html +++ b/KDE5PORTING.html @@ -1,383 +1,385 @@ Guide to Porting Applications to KDE Frameworks 5

Porting Applications to KDE Frameworks 5

Note

This document contains the changes you have to apply to programs written for KDE 4.x when you want to port them to KDE Frameworks 5.

Table of Contents

Global Changes

Return to the Table of Contents

Changes in kdecore

Return to the Table of Contents

Changes in kdeui

Return to the Table of Contents

Changes in kio

Return to the Table of Contents

Changes in kparts

Return to the Table of Contents

Changes in libkarchive

Return to the Table of Contents

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()) { //