cache svg icons from icon theme
cache as well svg icons from the icon theme (invalidating as well when the icon theme is updated) REVIEW:127260
This commit is contained in:
parent
ca98250d0c
commit
944c7e60dc
@ -45,6 +45,7 @@ PLASMA_UNIT_TESTS(
|
||||
pluginloadertest
|
||||
framesvgtest
|
||||
iconitemtest
|
||||
themetest
|
||||
# plasmoidpackagetest
|
||||
)
|
||||
|
||||
|
@ -0,0 +1,72 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="22" height="22" id="svg2" version="1.1" inkscape:version="0.91pre2 r" viewBox="0 0 22 22" sodipodi:docname="plasma.svg">
|
||||
<defs id="defs4">
|
||||
<style type="text/css" id="current-color-scheme">
|
||||
.ColorScheme-Text {
|
||||
color:#4d4d4d;
|
||||
}
|
||||
.ColorScheme-Background {
|
||||
color:#eff0f1;
|
||||
}
|
||||
.ColorScheme-Highlight {
|
||||
color:#3daee9;
|
||||
}
|
||||
.ColorScheme-ViewText {
|
||||
color:#31363b;
|
||||
}
|
||||
.ColorScheme-ViewBackground {
|
||||
color:#fcfcfc;
|
||||
}
|
||||
.ColorScheme-ViewHover {
|
||||
color:#93cee9;
|
||||
}
|
||||
.ColorScheme-ViewFocus{
|
||||
color:#3daee9;
|
||||
}
|
||||
.ColorScheme-ButtonText {
|
||||
color:#31363b;
|
||||
}
|
||||
.ColorScheme-ButtonBackground {
|
||||
color:#eff0f1;
|
||||
}
|
||||
.ColorScheme-ButtonHover {
|
||||
color:#93cee9;
|
||||
}
|
||||
.ColorScheme-ButtonFocus{
|
||||
color:#3daee9;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="22.627417" inkscape:cx="7.6662963" inkscape:cy="11.508125" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="true" units="px" inkscape:showpageshadow="false" inkscape:window-width="1366" inkscape:window-height="669" inkscape:window-x="-4" inkscape:window-y="25" inkscape:window-maximized="1" showguides="true">
|
||||
<inkscape:grid type="xygrid" id="grid4101"/>
|
||||
<sodipodi:guide position="2,20.000017" orientation="18,0" id="guide4107"/>
|
||||
<sodipodi:guide position="2,2.0000174" orientation="0,18" id="guide4109"/>
|
||||
<sodipodi:guide position="20,2.0000174" orientation="-18,0" id="guide4111"/>
|
||||
<sodipodi:guide position="20,20.000017" orientation="0,-18" id="guide4113"/>
|
||||
<sodipodi:guide position="3,19.000017" orientation="16,0" id="guide4115"/>
|
||||
<sodipodi:guide position="3,3.0000174" orientation="0,16" id="guide4117"/>
|
||||
<sodipodi:guide position="19,3.0000174" orientation="-16,0" id="guide4119"/>
|
||||
<sodipodi:guide position="19,19.000017" orientation="0,-16" id="guide4121"/>
|
||||
<sodipodi:guide position="10,6.0000174" orientation="-7,0" id="guide4162"/>
|
||||
<sodipodi:guide position="11,12.000017" orientation="5,0" id="guide4280"/>
|
||||
<sodipodi:guide position="11,7.0000174" orientation="0,5" id="guide4282"/>
|
||||
<sodipodi:guide position="16,7.0000174" orientation="-5,0" id="guide4284"/>
|
||||
<sodipodi:guide position="16,12.000017" orientation="0,-5" id="guide4286"/>
|
||||
<sodipodi:guide position="5,13.000017" orientation="6,0" id="guide4294"/>
|
||||
<sodipodi:guide position="5,7.0000174" orientation="0,6" id="guide4296"/>
|
||||
<sodipodi:guide position="11,7.0000174" orientation="-6,0" id="guide4298"/>
|
||||
</sodipodi:namedview>
|
||||
<metadata id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
||||
<dc:title/>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g inkscape:label="Capa 1" inkscape:groupmode="layer" id="layer1" transform="translate(0,-1030.3622)">
|
||||
<path style="opacity:1;fill:currentColor;fill-opacity:1;stroke:none" d="M 7 3 C 6.446 3 6 3.446 6 4 C 6 4.554 6.446 5 7 5 C 7.554 5 8 4.554 8 4 C 8 3.446 7.554 3 7 3 z M 14 3 L 12 5 L 15 8 L 12 11 L 14 13 L 17 10 L 19 8 L 14 3 z M 4.5 9 C 3.669 9 3 9.669 3 10.5 C 3 11.331 3.669 12 4.5 12 C 5.331 12 6 11.331 6 10.5 C 6 9.669 5.331 9 4.5 9 z M 9 15 C 7.892 15 7 15.892 7 17 C 7 18.108 7.892 19 9 19 C 10.108 19 11 18.108 11 17 C 11 15.892 10.108 15 9 15 z " transform="translate(0,1030.3622)" id="rect4231" class="ColorScheme-Text"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.0 KiB |
28
autotests/data/icons/test-theme-two/index.theme
Normal file
28
autotests/data/icons/test-theme-two/index.theme
Normal file
@ -0,0 +1,28 @@
|
||||
[Icon Theme]
|
||||
Name=Unittest Theme two
|
||||
|
||||
DisplayDepth=32
|
||||
|
||||
DesktopDefault=48
|
||||
DesktopSizes=16,22,32,48,64,128,256
|
||||
ToolbarDefault=22
|
||||
ToolbarSizes=16,22,32,48
|
||||
MainToolbarDefault=22
|
||||
MainToolbarSizes=16,22,32,48
|
||||
SmallDefault=16
|
||||
SmallSizes=16,22,32,48
|
||||
PanelDefault=32
|
||||
PanelSizes=16,22,32,48,64,128,256
|
||||
DialogDefault=32
|
||||
DialogSizes=16,22,32,48,64,128,256
|
||||
|
||||
########## Directories
|
||||
########## ordered by category and alphabetically
|
||||
|
||||
Directories=apps/22
|
||||
|
||||
[apps/22]
|
||||
Size=22
|
||||
Context=Applications
|
||||
Type=Fixed
|
||||
|
99
autotests/themetest.cpp
Normal file
99
autotests/themetest.cpp
Normal file
@ -0,0 +1,99 @@
|
||||
/********************************************************************************
|
||||
* Copyright 2016 Marco Martin <mart@kde.org> *
|
||||
* *
|
||||
* 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 "themetest.h"
|
||||
#include <QStandardPaths>
|
||||
#include <QApplication>
|
||||
|
||||
#include <KIconLoader>
|
||||
#include <KIconTheme>
|
||||
|
||||
#define QLSEP QLatin1Char('_')
|
||||
#define CACHE_ID_WITH_SIZE(size, id, devicePixelRatio) QString::number(int(size.width())) % QLSEP % QString::number(int(size.height())) % QLSEP % id % QLSEP % QLSEP % QString::number(int(devicePixelRatio))
|
||||
|
||||
void ThemeTest::initTestCase()
|
||||
{
|
||||
// make our theme in search path
|
||||
qputenv("XDG_DATA_DIRS",
|
||||
qgetenv("XDG_DATA_DIRS") + ":" + QFINDTESTDATA("data").toLocal8Bit());
|
||||
|
||||
// set default icon theme to test-theme
|
||||
QStandardPaths::setTestModeEnabled(true);
|
||||
|
||||
QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation);
|
||||
|
||||
if(!QDir(configPath).mkpath(QStringLiteral("."))) {
|
||||
qFatal("Failed to create test configuration directory.");
|
||||
}
|
||||
|
||||
QFile::remove(configPath);
|
||||
|
||||
QIcon::setThemeSearchPaths(QStringList()<<QFINDTESTDATA("data/icons"));
|
||||
|
||||
KConfigGroup cg(KSharedConfig::openConfig("kdeglobals"), "Icons");
|
||||
cg.writeEntry("Theme", "test-theme");
|
||||
KConfigGroup plasmaConfig(KSharedConfig::openConfig("plasmarc"), "Theme");
|
||||
plasmaConfig.writeEntry("name", "default");
|
||||
m_svg = new Plasma::Svg();
|
||||
}
|
||||
|
||||
void ThemeTest::cleanupTestCase()
|
||||
{
|
||||
// m_testIconsDir.removeRecursively();
|
||||
delete m_svg;
|
||||
}
|
||||
|
||||
void ThemeTest::loadSvgIcon()
|
||||
{
|
||||
const auto *iconTheme = KIconLoader::global()->theme();
|
||||
QString iconPath;
|
||||
if (iconTheme) {
|
||||
iconPath = iconTheme->iconPath(QLatin1String("konversation.svg"), 48, KIconLoader::MatchBest);
|
||||
}
|
||||
|
||||
m_svg->setImagePath(iconPath);
|
||||
QVERIFY(m_svg->isValid());
|
||||
|
||||
m_svg->pixmap(); //trigger the SVG being loaded
|
||||
|
||||
QString cacheId = CACHE_ID_WITH_SIZE(QSize(48, 48), iconPath, m_svg->devicePixelRatio()) % QLSEP % QString::number(m_svg->colorGroup());
|
||||
|
||||
QPixmap result;
|
||||
QVERIFY(m_svg->theme()->findInCache(cacheId, result));
|
||||
|
||||
QSignalSpy spy(m_svg, SIGNAL(repaintNeeded()));
|
||||
QVERIFY(spy.isValid());
|
||||
|
||||
KConfigGroup cg(KSharedConfig::openConfig("kdeglobals"), "Icons");
|
||||
cg.writeEntry("Theme", "test-theme-two");
|
||||
cg.sync();
|
||||
// KIconloader needs changesto be emitted manually, ouch.
|
||||
for (int i=0; i < KIconLoader::LastGroup; i++) {
|
||||
KIconLoader::emitChange(KIconLoader::Group(i));
|
||||
}
|
||||
|
||||
spy.wait();
|
||||
//Svg emitting repaintNeeded when something changes in KIconLoader means the svg loaded an icon
|
||||
QVERIFY(spy.count() == 1);
|
||||
|
||||
QVERIFY(!m_svg->theme()->findInCache(cacheId, result));
|
||||
}
|
||||
|
||||
QTEST_MAIN(ThemeTest)
|
||||
|
43
autotests/themetest.h
Normal file
43
autotests/themetest.h
Normal file
@ -0,0 +1,43 @@
|
||||
/******************************************************************************
|
||||
* Copyright 2016 Marco Martin <mart@kde.org> *
|
||||
* *
|
||||
* 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. *
|
||||
*******************************************************************************/
|
||||
#ifndef THEMETEST_H
|
||||
#define THEMETEST_H
|
||||
|
||||
#include <QtTest/QtTest>
|
||||
|
||||
#include "plasma/theme.h"
|
||||
#include "plasma/svg.h"
|
||||
|
||||
class ThemeTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public Q_SLOTS:
|
||||
void initTestCase();
|
||||
void cleanupTestCase();
|
||||
|
||||
private Q_SLOTS:
|
||||
void loadSvgIcon();
|
||||
|
||||
private:
|
||||
Plasma::Svg *m_svg;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -30,6 +30,8 @@
|
||||
|
||||
#include <kdirwatch.h>
|
||||
#include <kwindoweffects.h>
|
||||
#include <KIconLoader>
|
||||
#include <KIconTheme>
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
@ -120,6 +122,11 @@ ThemePrivate::ThemePrivate(QObject *parent)
|
||||
// ... but also remove/recreate cycles, like KConfig does it
|
||||
connect(KDirWatch::self(), &KDirWatch::created, this, &ThemePrivate::settingsFileChanged);
|
||||
|
||||
QObject::connect(KIconLoader::global(), &KIconLoader::iconChanged,
|
||||
this, [this]() {
|
||||
scheduleThemeChangeNotification(PixmapCache|SvgElementsCache);
|
||||
});
|
||||
|
||||
connect(KWindowSystem::self(), &KWindowSystem::compositingChanged, this, &ThemePrivate::compositingChanged);
|
||||
}
|
||||
|
||||
@ -172,6 +179,8 @@ bool ThemePrivate::useCache()
|
||||
}
|
||||
if (isRegularTheme) {
|
||||
themeMetadataPath = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QLatin1Literal(PLASMA_RELATIVE_DATA_INSTALL_DIR "/desktoptheme/") % themeName % QLatin1Literal("/metadata.desktop"));
|
||||
const auto *iconTheme = KIconLoader::global()->theme();
|
||||
iconThemeMetadataPath = iconTheme->dir() + "index.theme";
|
||||
|
||||
Q_ASSERT(!themeMetadataPath.isEmpty() || themeName.isEmpty());
|
||||
const QString cacheFileBase = cacheFile + QLatin1String("*.kcache");
|
||||
@ -194,6 +203,10 @@ bool ThemePrivate::useCache()
|
||||
QObject::connect(KDirWatch::self(), SIGNAL(dirty(QString)),
|
||||
this, SLOT(settingsFileChanged(QString)),
|
||||
Qt::UniqueConnection);
|
||||
|
||||
if (!iconThemeMetadataPath.isEmpty()) {
|
||||
KDirWatch::self()->addFile(iconThemeMetadataPath);
|
||||
}
|
||||
}
|
||||
|
||||
// now we check for, and remove if necessary, old caches
|
||||
@ -220,7 +233,10 @@ bool ThemePrivate::useCache()
|
||||
if (!cacheFilePath.isEmpty()) {
|
||||
const QFileInfo cacheFileInfo(cacheFilePath);
|
||||
const QFileInfo metadataFileInfo(themeMetadataPath);
|
||||
cachesTooOld = cacheFileInfo.lastModified().toTime_t() < metadataFileInfo.lastModified().toTime_t();
|
||||
const QFileInfo iconThemeMetadataFileInfo(iconThemeMetadataPath);
|
||||
|
||||
cachesTooOld = (cacheFileInfo.lastModified().toTime_t() < metadataFileInfo.lastModified().toTime_t()) ||
|
||||
(cacheFileInfo.lastModified().toTime_t() < iconThemeMetadataFileInfo.lastModified().toTime_t());
|
||||
}
|
||||
}
|
||||
|
||||
@ -248,6 +264,18 @@ bool ThemePrivate::useCache()
|
||||
|
||||
const QString svgElementsFile = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + '/' + svgElementsFileName;
|
||||
svgElementsCache = KSharedConfig::openConfig(svgElementsFile);
|
||||
QString currentIconThemePath;
|
||||
const auto *iconTheme = KIconLoader::global()->theme();
|
||||
if (iconTheme) {
|
||||
currentIconThemePath = iconTheme->dir();
|
||||
}
|
||||
KConfigGroup globalGroup(svgElementsCache, QLatin1String("Global"));
|
||||
const QString oldIconThemePath = globalGroup.readEntry("currentIconThemePath", QString());
|
||||
if (oldIconThemePath != currentIconThemePath) {
|
||||
discardCache(PixmapCache | SvgElementsCache);
|
||||
globalGroup.writeEntry("currentIconThemePath", currentIconThemePath);
|
||||
svgElementsCache = KSharedConfig::openConfig(svgElementsFile);
|
||||
}
|
||||
}
|
||||
|
||||
return cacheTheme;
|
||||
|
@ -140,6 +140,7 @@ public:
|
||||
CacheTypes cachesToDiscard;
|
||||
QString themeVersion;
|
||||
QString themeMetadataPath;
|
||||
QString iconThemeMetadataPath;
|
||||
|
||||
bool locolor : 1;
|
||||
bool compositingActive : 1;
|
||||
|
@ -36,6 +36,8 @@
|
||||
#include <QDebug>
|
||||
#include <kfilterdev.h>
|
||||
#include <kiconeffect.h>
|
||||
#include <KIconLoader>
|
||||
#include <KIconTheme>
|
||||
|
||||
#include "applet.h"
|
||||
#include "package.h"
|
||||
@ -182,8 +184,15 @@ bool SvgPrivate::setImagePath(const QString &imagePath)
|
||||
//length of file://
|
||||
actualPath = actualPath.mid(7);
|
||||
}
|
||||
const bool isThemed = !QDir::isAbsolutePath(actualPath);
|
||||
|
||||
bool isThemed = !QDir::isAbsolutePath(actualPath);
|
||||
bool inIconTheme = false;
|
||||
|
||||
//an absolute path.. let's try if this actually an *icon* theme
|
||||
if (!isThemed) {
|
||||
const auto *iconTheme = KIconLoader::global()->theme();
|
||||
isThemed = inIconTheme = iconTheme && actualPath.startsWith(iconTheme->dir());
|
||||
}
|
||||
// lets check to see if we're already set to this file
|
||||
if (isThemed == themed &&
|
||||
((themed && themePath == actualPath) ||
|
||||
@ -216,7 +225,11 @@ bool SvgPrivate::setImagePath(const QString &imagePath)
|
||||
emit q->fromCurrentThemeChanged(fromCurrentTheme);
|
||||
}
|
||||
|
||||
if (themed) {
|
||||
if (inIconTheme) {
|
||||
themePath = actualPath;
|
||||
path = actualPath;
|
||||
QObject::connect(actualTheme(), SIGNAL(themeChanged()), q, SLOT(themeChanged()));
|
||||
} else if (themed) {
|
||||
themePath = actualPath;
|
||||
path = actualTheme()->imagePath(themePath);
|
||||
themeFailed = path.isEmpty();
|
||||
|
Loading…
Reference in New Issue
Block a user