- Update to 3.7.0:
* QSvgRenderer is used with a cache for SVG icons, so that LXQt's icon handling could not be broken by intruding icon engines that register themselves for "svg" (like kiconthemes 5.80). * Allow runtime overriding of detachment of processes by setting QTXDG_START_DETACH_TRULY. * XTerm is added as a runtime dependency. * Code cleanup. - Remove libqt5xdg-svg-render.patch: upstreamed OBS-URL: https://build.opensuse.org/package/show/X11:LXQt/libqt5xdg?expand=0&rev=20
This commit is contained in:
parent
cafe3cf97b
commit
23b023fff2
@ -1,249 +0,0 @@
|
||||
From 07bb4531fe90afed28785ae2ce1a5b3f8de1c022 Mon Sep 17 00:00:00 2001
|
||||
From: tsujan <tsujan2000@gmail.com>
|
||||
Date: Wed, 24 Mar 2021 14:24:55 +0430
|
||||
Subject: [PATCH] Use QSvgRenderer for SVG icons (#247)
|
||||
|
||||
* Use QSvgRenderer for SVG icons
|
||||
|
||||
`QSvgRenderer` is used with a cache for both ordinary and colorized SVG icons. In this way, LXQt's icon handling cannot be broken by intruding icon engines, which register themselves for "svg" (see https://github.com/lxqt/libqtxdg/issues/246). Moreover, it does not depend on a specific code structure of `qtsvg` or any other icon engine.
|
||||
|
||||
* Just removed a redundant computation
|
||||
|
||||
* Used the same key structure for SVG cache
|
||||
---
|
||||
src/xdgiconloader/xdgiconloader.cpp | 179 ++++++++++++++++------------
|
||||
1 file changed, 100 insertions(+), 79 deletions(-)
|
||||
|
||||
diff --git a/src/xdgiconloader/xdgiconloader.cpp b/src/xdgiconloader/xdgiconloader.cpp
|
||||
index aeabda8..66d3dd8 100644
|
||||
--- a/src/xdgiconloader/xdgiconloader.cpp
|
||||
+++ b/src/xdgiconloader/xdgiconloader.cpp
|
||||
@@ -53,6 +53,7 @@
|
||||
#include <QImageReader>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QFileSystemWatcher>
|
||||
+#include <QSvgRenderer>
|
||||
|
||||
#include <private/qhexstring_p.h>
|
||||
|
||||
@@ -787,121 +788,141 @@ QPixmap PixmapEntry::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State st
|
||||
return cachedPixmap;
|
||||
}
|
||||
|
||||
-// XXX: duplicated from qiconloader.cpp, because this symbol isn't exported :(
|
||||
+// NOTE: For SVG, QSvgRenderer is used to prevent our icon handling from
|
||||
+// being broken by icon engines that register themselves for SVG.
|
||||
QPixmap ScalableEntry::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state)
|
||||
{
|
||||
- if (svgIcon.isNull())
|
||||
- svgIcon = QIcon(filename);
|
||||
+ QPixmap pm;
|
||||
+ if (size.isEmpty())
|
||||
+ return pm;
|
||||
|
||||
- // Bypass QIcon API, as that will scale by device pixel ratio of the
|
||||
- // highest DPR screen since we're not passing on any QWindow.
|
||||
- if (QIconEngine *engine = svgIcon.data_ptr() ? svgIcon.data_ptr()->engine : nullptr)
|
||||
- return engine->pixmap(size, mode, state);
|
||||
+ QString key = QLatin1String("lxqt_")
|
||||
+ % filename
|
||||
+ % HexString<int>(mode)
|
||||
+ % HexString<int>(state)
|
||||
+ % HexString<int>(size.width())
|
||||
+ % HexString<int>(size.height());
|
||||
+ if (!QPixmapCache::find(key, &pm))
|
||||
+ {
|
||||
+ int icnSize = qMin(size.width(), size.height());
|
||||
+ pm = QPixmap(icnSize, icnSize);
|
||||
+ pm.fill(Qt::transparent);
|
||||
|
||||
- return QPixmap();
|
||||
+ QSvgRenderer renderer;
|
||||
+ if (renderer.load(filename))
|
||||
+ {
|
||||
+ QPainter p;
|
||||
+ p.begin(&pm);
|
||||
+ renderer.render(&p, QRect(0, 0, icnSize, icnSize));
|
||||
+ p.end();
|
||||
+ }
|
||||
+
|
||||
+ svgIcon = QIcon(pm);
|
||||
+ if (QIconEngine *engine = svgIcon.data_ptr() ? svgIcon.data_ptr()->engine : nullptr)
|
||||
+ pm = engine->pixmap(size, mode, state);
|
||||
+ QPixmapCache::insert(key, pm);
|
||||
+ }
|
||||
+
|
||||
+ return pm;
|
||||
}
|
||||
|
||||
static const QString STYLE = QStringLiteral("\n.ColorScheme-Text, .ColorScheme-NeutralText {color:%1;}\
|
||||
\n.ColorScheme-Background {color:%2;}\
|
||||
\n.ColorScheme-Highlight {color:%3;}");
|
||||
-// Note: Qt palette does not have any colors for positive/negative text
|
||||
+// NOTE: Qt palette does not have any colors for positive/negative text
|
||||
// .ColorScheme-PositiveText,ColorScheme-NegativeText {color:%4;}
|
||||
|
||||
QPixmap ScalableFollowsColorEntry::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state)
|
||||
{
|
||||
QPixmap pm;
|
||||
- // see ScalableEntry::pixmap() for the reason
|
||||
- if (QIconEngine *engine = svgIcon.data_ptr() ? svgIcon.data_ptr()->engine : nullptr)
|
||||
- pm = engine->pixmap(size, mode, state);
|
||||
+ if (size.isEmpty())
|
||||
+ return pm;
|
||||
|
||||
- // Note: not checking the QIcon::isNull(), because in Qt5.10 the isNull() is not reliable
|
||||
- // for svg icons desierialized from stream (see https://codereview.qt-project.org/#/c/216086/)
|
||||
- if (pm.isNull())
|
||||
+ const QPalette pal = qApp->palette();
|
||||
+ QString txtCol, bgCol, hCol;
|
||||
+ if (mode == QIcon::Disabled)
|
||||
+ {
|
||||
+ txtCol = pal.color(QPalette::Disabled, QPalette::WindowText).name();
|
||||
+ bgCol = pal.color(QPalette::Disabled, QPalette::Window).name();
|
||||
+ hCol = pal.color(QPalette::Disabled, QPalette::Highlight).name();
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ if (mode == QIcon::Selected)
|
||||
+ {
|
||||
+ txtCol = pal.highlightedText().color().name();
|
||||
+ bgCol = pal.highlight().color().name();
|
||||
+ }
|
||||
+ else // normal or active
|
||||
+ {
|
||||
+ txtCol = pal.windowText().color().name();
|
||||
+ bgCol = pal.window().color().name();
|
||||
+ }
|
||||
+ hCol = pal.highlight().color().name();
|
||||
+ }
|
||||
+ QString key = QLatin1String("lxqt_")
|
||||
+ % filename
|
||||
+ % HexString<int>(mode)
|
||||
+ % HexString<int>(state)
|
||||
+ % HexString<int>(size.width())
|
||||
+ % HexString<int>(size.height())
|
||||
+ % txtCol % bgCol % hCol;
|
||||
+ if (!QPixmapCache::find(key, &pm))
|
||||
{
|
||||
- // The following lines are adapted and updated from KDE's "kiconloader.cpp" ->
|
||||
- // KIconLoaderPrivate::processSvg() and KIconLoaderPrivate::createIconImage().
|
||||
- // They read the SVG color scheme of SVG icons and give images based on the icon mode.
|
||||
- QHash<int, QByteArray> svg_buffers;
|
||||
+ int icnSize = qMin(size.width(), size.height());
|
||||
+ pm = QPixmap(icnSize, icnSize);
|
||||
+ pm.fill(Qt::transparent);
|
||||
+
|
||||
QFile device{filename};
|
||||
if (device.open(QIODevice::ReadOnly))
|
||||
{
|
||||
- const QPalette pal = qApp->palette();
|
||||
- // Note: indexes are assembled as in qtsvg (QSvgIconEnginePrivate::hashKey())
|
||||
- QMap<int, QString> style_sheets;
|
||||
- style_sheets[(QIcon::Normal<<4)|QIcon::Off] = STYLE.arg(pal.windowText().color().name(), pal.window().color().name(), pal.highlight().color().name());
|
||||
- style_sheets[(QIcon::Selected<<4)|QIcon::Off] = STYLE.arg(pal.highlightedText().color().name(), pal.highlight().color().name(), pal.highlightedText().color().name());
|
||||
- QMap<int, QSharedPointer<QXmlStreamWriter> > writers;
|
||||
- for (auto i = style_sheets.cbegin(); i != style_sheets.cend(); ++i)
|
||||
- {
|
||||
- writers[i.key()].reset(new QXmlStreamWriter{&svg_buffers[i.key()]});
|
||||
- }
|
||||
-
|
||||
+ QString styleSheet = STYLE.arg(txtCol, bgCol, hCol);
|
||||
+ QByteArray svgBuffer;
|
||||
+ QXmlStreamWriter writer(&svgBuffer);
|
||||
QXmlStreamReader xmlReader(&device);
|
||||
while (!xmlReader.atEnd())
|
||||
{
|
||||
if (xmlReader.readNext() == QXmlStreamReader::StartElement
|
||||
- && xmlReader.qualifiedName() == QLatin1String("style")
|
||||
- && xmlReader.attributes().value(QLatin1String("id")) == QLatin1String("current-color-scheme"))
|
||||
+ && xmlReader.qualifiedName() == QLatin1String("style")
|
||||
+ && xmlReader.attributes().value(QLatin1String("id")) == QLatin1String("current-color-scheme"))
|
||||
{
|
||||
const auto attribs = xmlReader.attributes();
|
||||
// store original data/text of the <style> element
|
||||
- QString original_data;
|
||||
+ QString origData;
|
||||
while (xmlReader.tokenType() != QXmlStreamReader::EndElement)
|
||||
{
|
||||
if (xmlReader.tokenType() == QXmlStreamReader::Characters)
|
||||
- original_data += xmlReader.text();
|
||||
+ origData += xmlReader.text();
|
||||
xmlReader.readNext();
|
||||
}
|
||||
- for (auto i = style_sheets.cbegin(); i != style_sheets.cend(); ++i)
|
||||
- {
|
||||
- QXmlStreamWriter & writer = *writers[i.key()];
|
||||
- writer.writeStartElement(QLatin1String("style"));
|
||||
- writer.writeAttributes(attribs);
|
||||
- // Note: We're writting the original style text to leave
|
||||
- // there "defaults" for unknown/unsupported classes.
|
||||
- // Then appending our "overrides"
|
||||
- writer.writeCharacters(original_data);
|
||||
- writer.writeCharacters(*i);
|
||||
- writer.writeEndElement();
|
||||
- }
|
||||
- } else if (xmlReader.tokenType() != QXmlStreamReader::Invalid)
|
||||
- {
|
||||
- for (auto i = style_sheets.cbegin(); i != style_sheets.cend(); ++i)
|
||||
- {
|
||||
- writers[i.key()]->writeCurrentToken(xmlReader);
|
||||
- }
|
||||
+ writer.writeStartElement(QLatin1String("style"));
|
||||
+ writer.writeAttributes(attribs);
|
||||
+ writer.writeCharacters(origData);
|
||||
+ writer.writeCharacters(styleSheet);
|
||||
+ writer.writeEndElement();
|
||||
}
|
||||
+ else if (xmlReader.tokenType() != QXmlStreamReader::Invalid)
|
||||
+ writer.writeCurrentToken(xmlReader);
|
||||
+ }
|
||||
+
|
||||
+ if (!svgBuffer.isEmpty())
|
||||
+ {
|
||||
+ QSvgRenderer renderer;
|
||||
+ renderer.load(svgBuffer);
|
||||
+ QPainter p;
|
||||
+ p.begin(&pm);
|
||||
+ renderer.render(&p, QRect(0, 0, icnSize, icnSize));
|
||||
+ p.end();
|
||||
}
|
||||
- // duplicate the contets also for opposite state
|
||||
- svg_buffers[(QIcon::Normal<<4)|QIcon::On] = svg_buffers[(QIcon::Normal<<4)|QIcon::Off];
|
||||
- svg_buffers[(QIcon::Selected<<4)|QIcon::On] = svg_buffers[(QIcon::Selected<<4)|QIcon::Off];
|
||||
}
|
||||
- // use the QSvgIconEngine
|
||||
- // - assemble the content as it is done by the operator <<(QDataStream &s, const QIcon &icon)
|
||||
- // (the QSvgIconEngine::key() + QSvgIconEngine::write())
|
||||
- // - create the QIcon from the content by usage of the QIcon::operator >>(QDataStream &s, const QIcon &icon)
|
||||
- // (icon with the (QSvgIconEngine) will be used)
|
||||
- QByteArray icon_arr;
|
||||
- QDataStream str{&icon_arr, QIODevice::WriteOnly};
|
||||
- str.setVersion(QDataStream::Qt_4_4);
|
||||
- QHash<int, QString> filenames;
|
||||
- filenames[0] = filename; // Note: filenames are ignored in the QSvgIconEngine::read()
|
||||
- str << QStringLiteral("svg") << filenames << static_cast<int>(0)/*isCompressed*/ << svg_buffers << static_cast<int>(0)/*hasAddedPimaps*/;
|
||||
-
|
||||
- QDataStream str_read{&icon_arr, QIODevice::ReadOnly};
|
||||
- str_read.setVersion(QDataStream::Qt_4_4);
|
||||
-
|
||||
- str_read >> svgIcon;
|
||||
+
|
||||
+ // Do not use this pixmap directly but first get the icon
|
||||
+ // for QIcon::pixmap() to handle states and modes,
|
||||
+ // especially the disabled mode.
|
||||
+ svgIcon = QIcon(pm);
|
||||
if (QIconEngine *engine = svgIcon.data_ptr() ? svgIcon.data_ptr()->engine : nullptr)
|
||||
pm = engine->pixmap(size, mode, state);
|
||||
-
|
||||
- // load the icon directly from file, if still null
|
||||
- if (pm.isNull())
|
||||
- {
|
||||
- svgIcon = QIcon(filename);
|
||||
- if (QIconEngine *engine = svgIcon.data_ptr() ? svgIcon.data_ptr()->engine : nullptr)
|
||||
- pm = engine->pixmap(size, mode, state);
|
||||
- }
|
||||
+ QPixmapCache::insert(key, pm);
|
||||
}
|
||||
|
||||
return pm;
|
@ -1,3 +1,16 @@
|
||||
-------------------------------------------------------------------
|
||||
Fri Apr 16 06:31:20 UTC 2021 - Michael Vetter <mvetter@suse.com>
|
||||
|
||||
- Update to 3.7.0:
|
||||
* QSvgRenderer is used with a cache for SVG icons, so that LXQt's
|
||||
icon handling could not be broken by intruding icon engines
|
||||
that register themselves for "svg" (like kiconthemes 5.80).
|
||||
* Allow runtime overriding of detachment of processes by
|
||||
setting QTXDG_START_DETACH_TRULY.
|
||||
* XTerm is added as a runtime dependency.
|
||||
* Code cleanup.
|
||||
- Remove libqt5xdg-svg-render.patch: upstreamed
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Wed Mar 31 10:02:43 UTC 2021 - Michael Vetter <mvetter@suse.com>
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
%define _name libqtxdg
|
||||
Name: libqt5xdg
|
||||
Version: 3.6.0
|
||||
Version: 3.7.0
|
||||
Release: 0
|
||||
Summary: Qt implementation of xdg specs for lxqt
|
||||
License: GPL-3.0-only
|
||||
@ -27,14 +27,13 @@ URL: https://lxqt.org
|
||||
Source: https://github.com/lxqt/libqtxdg/releases/download/%{version}/%{_name}-%{version}.tar.xz
|
||||
Source1: https://github.com/lxqt/libqtxdg/releases/download/%{version}/%{_name}-%{version}.tar.xz.asc
|
||||
Source2: %{name}.keyring
|
||||
Patch0: libqt5xdg-svg-render.patch
|
||||
BuildRequires: cmake >= 3.1.0
|
||||
BuildRequires: fdupes
|
||||
BuildRequires: gcc-c++
|
||||
BuildRequires: libQt5Gui-private-headers-devel
|
||||
BuildRequires: lxqt-build-tools-devel >= 0.8.0
|
||||
BuildRequires: lxqt-build-tools-devel >= 0.9.0
|
||||
BuildRequires: pkgconfig
|
||||
BuildRequires: pkgconfig(Qt5Core) >= 5.10
|
||||
BuildRequires: pkgconfig(Qt5Core) >= 5.12
|
||||
BuildRequires: pkgconfig(Qt5DBus)
|
||||
BuildRequires: pkgconfig(Qt5Svg)
|
||||
BuildRequires: pkgconfig(Qt5Test)
|
||||
@ -89,7 +88,6 @@ Tools for QtXdg.
|
||||
|
||||
%prep
|
||||
%setup -q -n %{_name}-%{version}
|
||||
%patch0 -p1
|
||||
|
||||
%build
|
||||
%cmake
|
||||
|
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:0fefb362eac9120fccd401202f15d092a59fd1aaacfc4b885a33578cdd41cf42
|
||||
size 76028
|
@ -1,17 +0,0 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQJJBAABCAAzFiEEGd/fOleb1QnbtXLYvnkwB60i334FAl+inicVHHRzdWphbjIw
|
||||
MDBAZ21haWwuY29tAAoJEL55MAetIt9+0MUQANxt9szJ9nLEII02s3Wg0LXnkvIF
|
||||
VP3teGldyr197cKjXDucg4lM9aCNJ9kUC5CoLLZmKueSzml3iS1FMvb5XAsIAyqd
|
||||
BMWkmNC4dFvQtfEBwXNgPhBlnRSNy0JbHa+YZPpPuGFXcYBVN6/u3oVlW2T0ePFw
|
||||
F7CkluC2AayCbcrMaKSIHV0og9/XoXF1osA3jE4PhfwUQPA2bx8WbUXCyjCwB4wc
|
||||
WujkPYUxq7Ue+mRsTBbxrOshMDpw7dmnA/rx+itfh2AXil/oEVhQf2pnJ6DqZxPV
|
||||
y8vON7qiYKtTO8jKvCgAEUwga/n2kW9JOWmXPRGbgouyFZRh5jSBVclQgIjj6X7h
|
||||
F4XfqqBC0+52CuTrZYXpwb5V7hHDLsanQAlME814o7f+JioPWeEt96Ium38gD5dJ
|
||||
UTcEpr3FCsxsN5q8L8q4iZrcmy4jqp8TPpluVXEzdQieOiaDOADedoJ6i5LZ8AbB
|
||||
CFDsfI6+jkMQyxl/z4UsB85RakYabYD383wNm/6b/VFas58A0EgawUM5AhVYq9+D
|
||||
KhPWV5/Zbxqv8qZ5SrhEyKu9D7bYBeUWTC87ewuaykEqfrR6QWrsAQFOhIoRqMtR
|
||||
XzBY0w5SAVNdkyG/Yzli9sBVdUmpAq0kBWkmNnyCTVWnPZ2XoUvCKpiuJmkOOSW/
|
||||
ujOaVyiHCFrh/PWy
|
||||
=/ogB
|
||||
-----END PGP SIGNATURE-----
|
3
libqtxdg-3.7.0.tar.xz
Normal file
3
libqtxdg-3.7.0.tar.xz
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5bb8f67432726429966c5ceaf6b7ce4608adfe8e6f3a1c4a9e2c65d7dcf2eae0
|
||||
size 74756
|
17
libqtxdg-3.7.0.tar.xz.asc
Normal file
17
libqtxdg-3.7.0.tar.xz.asc
Normal file
@ -0,0 +1,17 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQJJBAABCAAzFiEEGd/fOleb1QnbtXLYvnkwB60i334FAmB4CwoVHHRzdWphbjIw
|
||||
MDBAZ21haWwuY29tAAoJEL55MAetIt9+CQQP/Ak82Cyedhqqco041joqIl7eO9tg
|
||||
IQPYF/PR0g7PvHGurJGsLXrwkJ4NofRGZzaPa8oWx7jw9KNRYGob93WmfLohFC5C
|
||||
8Vo2TlHivX16XaFFqnoYiC6Vx9+qALIqYa9yj9KDnJBTH4uIxwI6o+YtkXqw4Gzg
|
||||
V9/wNcDehJG8ZyurdgkihKUbeze7rfRV9x9HOG6Dku5n5v6zcXYhvjCHOlPKezf0
|
||||
GMKvNaGlJsbv3hOfd2n5LuwPs0uigMymuqwxtyOscZoaMrHobB2A7x/n1pBenJA9
|
||||
mBnDe3ZdJIGG0kkR6Vr86RWzoYduI8957FKrywfBFAPFKi9kQSAjKi+tInQe2Hak
|
||||
ZBAEduQUhVa80MVaPOBZ4hc7kgQv2Mrv4K4tey8Us+LI1tmRnWe5vsKvg7qfqDPi
|
||||
41fiDWAI1gj0xaZokbnOURiiFKI0DIgso1ez5Iu2MlGOz49oxMm2Wxeaxhz5SESy
|
||||
/up3eeeiAXN9XvZAlX9CickmUpmTZFEnCtSXIXpZdVyMUO/4P/zgp7gfJ2oc6miJ
|
||||
zhNpDRvk0wKCfFVnvHGUA8yQLBP+RoY4Z/TSOoWAzifA28hPD3Vj1HRuV2EgQnGC
|
||||
DLZPUqswcAstUCXcGgMtNZ+nEtuPVtlm9udEk0xiidWY37ht6m3RMihLDeIQNbPM
|
||||
/cRhq0B1Lr7J4kjE
|
||||
=vHzj
|
||||
-----END PGP SIGNATURE-----
|
Loading…
Reference in New Issue
Block a user