10#include "private/imageset_p.h"
11#include "private/svg_p.h"
18#include <QCoreApplication>
21#include <QRegularExpression>
22#include <QStringBuilder>
23#include <QXmlStreamReader>
24#include <QXmlStreamWriter>
26#include <KCompressionDevice>
27#include <KConfigGroup>
33size_t qHash(
const KSvg::SvgPrivate::CacheId &
id,
size_t seed)
35 std::array<size_t, 10> parts = {
38 ::qHash(
id.elementName),
41 ::qHash(
id.scaleFactor),
43 ::qHash(
id.styleSheet),
44 ::qHash(
id.extraFlags),
45 ::qHash(
id.lastModified),
47 return qHashRange(parts.begin(), parts.end(), seed);
52 std::vector<size_t> parts;
53 for (
const QColor &c : std::as_const(colors)) {
54 parts.push_back(::qHash(c.red()));
55 parts.push_back(::qHash(c.green()));
56 parts.push_back(::qHash(c.blue()));
57 parts.push_back(::qHash(c.alpha()));
59 return qHashRange(parts.begin(), parts.end(), seed);
64class SvgRectsCacheSingleton
70Q_GLOBAL_STATIC(SvgRectsCacheSingleton, privateSvgRectsCacheSelf)
72const size_t SvgRectsCache::s_seed = 0x9e3779b9;
74SharedSvgRenderer::SharedSvgRenderer(QObject *parent)
75 : QSvgRenderer(parent)
86 m_filename = filename;
87 m_styleSheet = styleSheet;
88 m_interestingElements = interestingElements;
89 load(file.readAll(), styleSheet, interestingElements);
95 load(contents, styleSheet, interestingElements);
98void SharedSvgRenderer::reload()
105 load(file.readAll(), m_styleSheet, m_interestingElements);
111 if (!styleSheet.
isEmpty() && contents.
contains(
"current-color-scheme")) {
116 QBuffer buffer(&processedContents);
119 while (!reader.atEnd()) {
123 writer.writeAttributes(reader.attributes());
124 writer.writeCharacters(styleSheet);
125 writer.writeEndElement();
130 writer.writeCurrentToken(reader);
144 Q_ASSERT(idExpr.isValid());
146 auto matchIt = idExpr.globalMatch(contentsAsString);
147 while (matchIt.hasNext()) {
148 auto match = matchIt.next();
151 QRectF elementRect = boundsOnElement(elementId);
153 interestingElements.
insert(elementId, elementRect);
160SvgRectsCache::SvgRectsCache(
QObject *parent)
166 m_configSyncTimer =
new QTimer(
this);
167 m_configSyncTimer->setSingleShot(
true);
168 m_configSyncTimer->setInterval(5000);
170 m_svgElementsCache->sync();
174SvgRectsCache *SvgRectsCache::instance()
176 return &privateSvgRectsCacheSelf()->self;
179void SvgRectsCache::insert(KSvg::SvgPrivate::CacheId cacheId,
const QRectF &rect,
unsigned int lastModified)
181 insert(
qHash(cacheId, SvgRectsCache::s_seed), cacheId.filePath, rect, lastModified);
184void SvgRectsCache::insert(
size_t id,
const QString &filePath,
const QRectF &rect,
unsigned int lastModified)
186 const unsigned int savedTime = lastModifiedTimeFromCache(filePath);
188 if (savedTime == lastModified && m_localRectCache.contains(
id)) {
192 m_localRectCache.insert(
id, rect);
194 KConfigGroup imageGroup(m_svgElementsCache, filePath);
199 m_invalidElements[filePath] << id;
200 imageGroup.writeEntry(
"Invalidelements", m_invalidElements[filePath].values());
205 if (savedTime != lastModified) {
206 m_lastModifiedTimes[filePath] = lastModified;
207 imageGroup.writeEntry(
"LastModified", lastModified);
208 Q_EMIT lastModifiedChanged(filePath, lastModified);
212bool SvgRectsCache::findElementRect(KSvg::SvgPrivate::CacheId cacheId,
QRectF &rect)
214 return findElementRect(
qHash(cacheId, SvgRectsCache::s_seed), cacheId.filePath, rect);
217bool SvgRectsCache::findElementRect(
size_t id,
QStringView filePath,
QRectF &rect)
219 auto it = m_localRectCache.find(
id);
221 if (it == m_localRectCache.end()) {
222 auto elements = m_invalidElements.value(filePath.
toString());
223 if (elements.contains(
id)) {
235bool SvgRectsCache::loadImageFromCache(
const QString &path, uint lastModified)
241 KConfigGroup imageGroup(m_svgElementsCache, path);
243 unsigned int savedTime = lastModifiedTimeFromCache(path);
246 if (lastModified != savedTime) {
247 imageGroup.deleteGroup();
252 auto &elements = m_invalidElements[
path];
253 if (elements.isEmpty()) {
254 auto list = imageGroup.readEntry(
"Invalidelements", QList<unsigned int>());
257 for (
const auto &key : imageGroup.keyList()) {
259 uint keyUInt = key.toUInt(&ok);
261 const QRectF rect = imageGroup.readEntry(key, QRectF());
262 m_localRectCache.insert(keyUInt, rect);
269void SvgRectsCache::dropImageFromCache(
const QString &path)
271 KConfigGroup imageGroup(m_svgElementsCache, path);
272 imageGroup.deleteGroup();
278 const QString pathId =
path % id;
280 auto it = m_sizeHintsForId.constFind(pathId);
281 if (it == m_sizeHintsForId.constEnd()) {
282 KConfigGroup imageGroup(m_svgElementsCache, path);
283 const QStringList &encoded = imageGroup.readEntry(
id, QStringList());
285 for (
const auto &token : encoded) {
286 const auto &parts = token.split(QLatin1Char(
'x'));
287 if (parts.size() != 2) {
290 QSize size = QSize(parts[0].toDouble(), parts[1].toDouble());
295 m_sizeHintsForId[pathId] = sizes;
302void SvgRectsCache::insertSizeHintForId(
const QString &path,
const QString &
id,
const QSizeF &size)
305 auto sizeListToString = [](
const QList<QSizeF> &
list) {
307 for (
const auto &s : list) {
313 KConfigGroup imageGroup(m_svgElementsCache, path);
314 imageGroup.writeEntry(
id, sizeListToString(m_sizeHintsForId[path %
id]));
318QString SvgRectsCache::iconThemePath()
320 if (!m_iconThemePath.isEmpty()) {
321 return m_iconThemePath;
324 KConfigGroup imageGroup(m_svgElementsCache, QStringLiteral(
"General"));
325 m_iconThemePath = imageGroup.readEntry(QStringLiteral(
"IconThemePath"), QString());
327 return m_iconThemePath;
330void SvgRectsCache::setIconThemePath(
const QString &path)
332 m_iconThemePath =
path;
333 KConfigGroup imageGroup(m_svgElementsCache, QStringLiteral(
"General"));
334 imageGroup.writeEntry(QStringLiteral(
"IconThemePath"), path);
338void SvgRectsCache::setNaturalSize(
const QString &path,
const QSizeF &size)
340 KConfigGroup imageGroup(m_svgElementsCache, path);
343 imageGroup.writeEntry(QStringLiteral(
"NaturalSize"), size);
349 KConfigGroup imageGroup(m_svgElementsCache, path);
352 return imageGroup.readEntry(QStringLiteral(
"NaturalSize"), QSizeF());
357 KConfigGroup imageGroup(m_svgElementsCache, path);
358 QStringList
list = imageGroup.keyList();
361 std::copy_if(
list.
begin(),
list.
end(), std::back_inserter(filtered), [](
const QString element) {
369unsigned int SvgRectsCache::lastModifiedTimeFromCache(
const QString &filePath)
371 const auto &i = m_lastModifiedTimes.constFind(filePath);
372 if (i != m_lastModifiedTimes.constEnd()) {
376 KConfigGroup imageGroup(m_svgElementsCache, filePath);
377 const unsigned int savedTime = imageGroup.readEntry(
"LastModified", 0);
378 m_lastModifiedTimes[filePath] = savedTime;
382void SvgRectsCache::updateLastModified(
const QString &filePath,
unsigned int lastModified)
384 KConfigGroup imageGroup(m_svgElementsCache, filePath);
385 const unsigned int savedTime = lastModifiedTimeFromCache(filePath);
387 if (savedTime != lastModified) {
388 m_lastModifiedTimes[filePath] = lastModified;
389 imageGroup.writeEntry(
"LastModified", lastModified);
391 Q_EMIT lastModifiedChanged(filePath, lastModified);
395SvgPrivate::SvgPrivate(Svg *svg)
400 , devicePixelRatio(1.0)
402 , multipleImages(false)
404 , fromCurrentImageSet(false)
405 , cacheRendering(true)
410SvgPrivate::~SvgPrivate()
415size_t SvgPrivate::paletteId(
const QPalette &palette,
const QColor &positive,
const QColor &neutral,
const QColor &negative)
const
417 std::array<size_t, 4> parts = {
419 ::qHash(positive.
rgba()),
420 ::qHash(neutral.
rgba()),
421 ::qHash(negative.
rgba()),
423 return qHashRange(parts.begin(), parts.end(), SvgRectsCache::s_seed);
427SvgPrivate::CacheId SvgPrivate::cacheId(
QStringView elementId)
const
429 auto idSize = size.
isValid() && size != naturalSize ? size :
QSizeF{-1.0, -1.0};
430 return CacheId{idSize.width(), idSize.height(),
path, elementId.
toString(),
status, devicePixelRatio, -1, 0, 0, lastModified};
436 std::vector<size_t> parts;
437 const auto colors = colorOverrides.values();
438 for (
const QColor &c : std::as_const(colors)) {
439 parts.push_back(::qHash(c.red()));
440 parts.push_back(::qHash(c.green()));
441 parts.push_back(::qHash(c.blue()));
442 parts.push_back(::qHash(c.alpha()));
444 const size_t colorsHash = qHashRange(parts.begin(), parts.end(), SvgRectsCache::s_seed);
446 auto cacheId = CacheId{double(size.
width()), double(size.
height()),
path, id,
status, devicePixelRatio, colorSet, colorsHash, 0, lastModified};
450bool SvgPrivate::setImagePath(
const QString &imagePath)
452 QString actualPath = imagePath;
457 isAbsoluteFile =
true;
464 isAbsoluteFile =
true;
467 bool isThemed = !actualPath.
isEmpty() && !isAbsoluteFile;
470 if (isThemed == themed && ((themed && themePath == actualPath) || (!themed && path == actualPath))) {
478 bool updateNeeded =
true;
486 bool oldfromCurrentImageSet = fromCurrentImageSet;
487 fromCurrentImageSet = isThemed && actualImageSet()->currentImageSetHasImage(imagePath);
489 if (fromCurrentImageSet != oldfromCurrentImageSet) {
490 Q_EMIT q->fromCurrentImageSetChanged(fromCurrentImageSet);
494 themePath = actualPath;
495 path = actualImageSet()->imagePath(themePath);
497 imageSetChangedConnection =
QObject::connect(actualImageSet(), &ImageSet::imageSetChanged, q, [
this]() {
501 imageSetChangedConnection =
QObject::connect(actualImageSet(), &ImageSet::imageSetChanged, q, [
this]() {
514 lastModifiedDate = info.lastModified();
518 const bool imageWasCached = SvgRectsCache::instance()->loadImageFromCache(path, lastModified);
520 if (!imageWasCached) {
521 std::shared_lock lock(s_renderersLock);
522 auto i = s_renderers.constBegin();
523 while (i != s_renderers.constEnd()) {
524 if (i.key().contains(path)) {
535 naturalSize = SvgRectsCache::instance()->naturalSize(path);
536 if (naturalSize.isEmpty()) {
538 naturalSize = renderer->defaultSize();
539 SvgRectsCache::instance()->setNaturalSize(path, naturalSize);
544 Q_EMIT q->imagePathChanged();
549ImageSet *SvgPrivate::actualImageSet()
566 const QList<QSizeF> elementSizeHints = SvgRectsCache::instance()->sizeHintsForId(path, elementId);
568 if (!elementSizeHints.
isEmpty()) {
571 for (
const auto &hint : elementSizeHints) {
573 && (!bestFit.isValid() || (bestFit.width() * bestFit.height()) > (
hint.width() *
hint.height()))) {
578 if (bestFit.isValid()) {
584 if (elementId.
isEmpty() || !q->hasElement(actualElementId)) {
585 actualElementId = elementId;
589 size = s.
toSize() * ratio;
591 size = elementRect(actualElementId).
size().
toSize() * ratio;
598 const QString id = cachePath(actualElementId, size);
601 if (cacheRendering && lastModified == SvgRectsCache::instance()->lastModifiedTimeFromCache(path) && actualImageSet()->d->findInCache(
id, p, lastModified)) {
609 QRectF finalRect = makeUniform(renderer->boundsOnElement(actualElementId),
QRect(
QPoint(0, 0), size));
618 if (actualElementId.
isEmpty()) {
619 renderer->render(&renderPainter, finalRect);
621 renderer->render(&renderPainter, actualElementId, finalRect);
627 if (cacheRendering) {
631 SvgRectsCache::instance()->updateLastModified(path, lastModified);
636void SvgPrivate::createRenderer()
644 path = actualImageSet()->imagePath(themePath);
647 qCWarning(LOG_KSVG) <<
"No image path found for" << themePath;
653 if (!colorOverrides.isEmpty()) {
654 if (stylesheetOverride.isEmpty()) {
655 stylesheetOverride = actualImageSet()->d->svgStyleSheet(q);
657 styleSheet = stylesheetOverride;
659 styleSheet = actualImageSet()->d->svgStyleSheet(q);
665 std::shared_lock lock(s_renderersLock);
668 if (it != s_renderers.constEnd()) {
669 renderer = it.value();
671 size = renderer->defaultSize();
678 renderer =
new SharedSvgRenderer();
681 renderer =
new SharedSvgRenderer(path, styleSheet, interestingElements);
688 while (i.hasNext()) {
690 const QString &elementId = i.key();
692 const QRectF &elementRect = i.value();
694 originalId.
replace(sizeHintedKeyExpr, QStringLiteral(
"\\3"));
695 SvgRectsCache::instance()->insertSizeHintForId(path, originalId, elementRect.
size().
toSize());
697 const CacheId cacheId{.width = -1.0,
700 .elementName = elementId,
702 .scaleFactor = devicePixelRatio,
706 .lastModified = lastModified};
707 SvgRectsCache::instance()->
insert(cacheId, elementRect, lastModified);
712 std::unique_lock lock(s_renderersLock);
713 s_renderers[styleCrc +
path] = renderer;
715 size = renderer->defaultSize();
720void SvgPrivate::eraseRenderer()
722 if (renderer && renderer->ref.loadRelaxed() == 2) {
724 std::unique_lock lock(s_renderersLock);
725 s_renderers.erase(s_renderers.find(styleCrc + path));
739 path = actualImageSet()->imagePath(themePath);
752 const CacheId cacheId = SvgPrivate::cacheId(elementId);
753 bool found = SvgRectsCache::instance()->findElementRect(cacheId, rect);
756 rect = findAndCacheElementRect(elementId);
765 const CacheId cacheId = SvgPrivate::cacheId(elementId);
769 auto elementIdString = elementId.
toString();
772 QRectF elementRect = renderer->elementExists(elementIdString)
773 ? renderer->transformForElement(elementIdString).map(renderer->boundsOnElement(elementIdString)).boundingRect()
776 naturalSize = renderer->defaultSize();
778 qreal dx = size.
width() / renderer->defaultSize().width();
779 qreal dy = size.
height() / renderer->defaultSize().height();
781 elementRect =
QRectF(elementRect.
x() * dx, elementRect.
y() * dy, elementRect.
width() * dx, elementRect.
height() * dy);
782 SvgRectsCache::instance()->insert(cacheId, elementRect, lastModified);
794qreal SvgPrivate::closestDistance(qreal to, qreal from)
797 if (qFuzzyCompare(to, from)) {
799 }
else if (to > from) {
800 qreal b = to - from - 1;
801 return (qAbs(a) > qAbs(b)) ? b : a;
803 qreal b = 1 + to - from;
804 return (qAbs(a) > qAbs(b)) ? b : a;
810 if (qFuzzyIsNull(orig.
x()) || qFuzzyIsNull(orig.
y())) {
818 qreal div_x = dst.
x() / orig.
x();
819 qreal div_y = dst.
y() / orig.
y();
822 if (!qFuzzyIsNull(div_x) && !qFuzzyCompare(div_w, div_x)) {
823 qreal rem_orig = orig.
x() - (floor(orig.
x()));
824 qreal rem_dst = dst.
x() - (floor(dst.
x()));
825 qreal offset = closestDistance(rem_dst, rem_orig);
826 res.translate(offset + offset * div_w, 0);
827 res.setWidth(res.width() + offset);
830 if (!qFuzzyIsNull(div_y) && !qFuzzyCompare(div_h, div_y)) {
831 qreal rem_orig = orig.
y() - (floor(orig.
y()));
832 qreal rem_dst = dst.
y() - (floor(dst.
y()));
833 qreal offset = closestDistance(rem_dst, rem_orig);
834 res.translate(0, offset + offset * div_h);
835 res.setHeight(res.height() + offset);
841void SvgPrivate::imageSetChanged()
843 if (q->imagePath().isEmpty()) {
850 setImagePath(currentPath);
854 Q_EMIT q->repaintNeeded();
855 Q_EMIT q->imageSetChanged(q->imageSet());
858void SvgPrivate::colorsChanged()
861 qCDebug(LOG_KSVG) <<
"repaint needed from colorsChanged";
863 Q_EMIT q->repaintNeeded();
866std::shared_mutex SvgPrivate::s_renderersLock;
872 , d(new SvgPrivate(this))
874 connect(SvgRectsCache::instance(), &SvgRectsCache::lastModifiedChanged,
this, [
this](
const QString &filePath,
unsigned int lastModified) {
875 if (d->lastModified != lastModified && filePath == d->path) {
876 d->lastModified = lastModified;
893 d->devicePixelRatio = ratio;
900 return d->devicePixelRatio;
905 if (elementID.
isNull() || d->multipleImages) {
906 return d->findInCache(elementID, d->devicePixelRatio, size());
908 return d->findInCache(elementID, d->devicePixelRatio);
914 QPixmap pix(d->findInCache(elementID, d->devicePixelRatio, size));
920 Q_ASSERT(painter->
device());
922 QPixmap pix((elementID.
isNull() || d->multipleImages) ? d->findInCache(elementID, ratio, size()) : d->findInCache(elementID, ratio));
938 Q_ASSERT(painter->
device());
940 QPixmap pix(d->findInCache(elementID, ratio, rect.
size()));
947 Q_ASSERT(painter->
device());
949 QPixmap pix(d->findInCache(elementID, ratio,
QSizeF(width, height)));
955 if (d->size.isEmpty()) {
956 d->size = d->naturalSize;
959 return {std::round(d->size.width()), std::round(d->size.height())};
969 if (qFuzzyCompare(size.width(), d->size.width()) && qFuzzyCompare(size.height(), d->size.height())) {
979 if (qFuzzyCompare(d->naturalSize.width(), d->size.width()) && qFuzzyCompare(d->naturalSize.height(), d->size.height())) {
983 d->size = d->naturalSize;
989 const QSizeF s = d->elementRect(elementId).size();
990 return {std::round(s.
width()), std::round(s.
height())};
995 const QSizeF s = d->elementRect(elementId).size();
996 return {std::round(s.
width()), std::round(s.
height())};
1001 return d->elementRect(elementId);
1006 return d->elementRect(elementId);
1016 if (elementId.
isEmpty() || (d->path.isNull() && d->themePath.isNull())) {
1020 return d->elementRect(elementId).isValid();
1025 if (d->path.isNull() && d->themePath.isNull()) {
1030 QSizeF naturalSize = SvgRectsCache::instance()->naturalSize(d->path);
1038 d->createRenderer();
1039 return d->renderer->
isValid();
1044 d->multipleImages = multiple;
1049 return d->multipleImages;
1054 if (d->setImagePath(svgFilePath)) {
1061 return d->themed ? d->themePath : d->path;
1066 d->cacheRendering = useCache;
1072 return d->cacheRendering;
1075bool Svg::fromCurrentImageSet()
const
1077 return d->fromCurrentImageSet;
1082 if (!theme || theme == d->theme.data()) {
1087 disconnect(d->theme.data(),
nullptr,
this,
nullptr);
1092 d->imageSetChanged();
1097 return d->actualImageSet();
1102 if (status == d->status) {
1112Svg::Status Svg::status()
const
1120 if (convertedSet == d->colorSet) {
1124 d->colorSet = convertedSet;
1130Svg::ColorSet Svg::colorSet()
const
1132 return Svg::ColorSet(d->colorSet);
1135QColor Svg::color(StyleSheetColor colorName)
const
1137 auto it = d->colorOverrides.constFind(colorName);
1138 if (it != d->colorOverrides.constEnd()) {
1141 return d->actualImageSet()->d->namedColor(colorName,
this);
1144void Svg::setColor(StyleSheetColor colorName,
const QColor &color)
1146 if (d->colorOverrides.value(colorName) == color) {
1150 if (color.isValid()) {
1151 d->colorOverrides[colorName] = color;
1153 d->colorOverrides.remove(colorName);
1155 d->stylesheetOverride.clear();
1161void Svg::clearColorOverrides()
1163 d->colorOverrides.clear();
1164 d->stylesheetOverride.clear();
1171#include "moc_svg.cpp"
1172#include "private/moc_svg_p.cpp"
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
Interface to the Svg image set.
virtual void setImagePath(const QString &svgFilePath)
This method sets the SVG file to render.
Q_INVOKABLE QImage image(const QSize &size, const QString &elementID=QString())
This method returns an image of the SVG represented by this object.
void statusChanged(KSvg::Svg::Status status)
This signal is emitted when the status has changed.
void setStatus(Svg::Status status)
This method sets the image in a selected status.
void setContainsMultipleImages(bool multiple)
This method sets whether the SVG contains a single image or multiple ones.
Q_INVOKABLE void resize()
This method resizes the rendered image to the natural size of the SVG.
void setColorSet(ColorSet colorSet)
This method sets a color set for the SVG.
Q_INVOKABLE QPixmap pixmap(const QString &elementID=QString())
This method returns a pixmap of the SVG represented by this object.
qreal devicePixelRatio() const
This method returns the device pixel ratio for this Svg.
bool containsMultipleImages() const
This method returns whether the SVG contains multiple images.
void setDevicePixelRatio(qreal factor)
This method sets the device pixel ratio for the Svg.
void colorSetChanged(KSvg::Svg::ColorSet colorSet)
This signal is emitted when the color set has changed.
Svg(QObject *parent=nullptr)
This method constructs an SVG object that implicitly shares and caches rendering.
void sizeChanged()
This signal is emitted whenever the size has changed.
Q_INVOKABLE QRectF elementRect(const QString &elementId) const
This method returns the bounding rect of a given element.
Q_INVOKABLE void paint(QPainter *painter, const QPointF &point, const QString &elementID=QString())
This method paints all or part of the SVG represented by this object.
ImageSet * imageSet() const
This method returns the KSvg::ImageSet used by this Svg object.
void repaintNeeded()
This signal is emitted whenever the SVG data has changed in such a way that a repaint is required.
void imageSetChanged(ImageSet *imageSet)
This signal is emitted when the image set has changed.
bool isUsingRenderingCache() const
Whether the rendering cache is being used.
Q_INVOKABLE bool hasElement(const QString &elementId) const
This method checks whether an element exists in the loaded SVG.
Q_INVOKABLE bool isValid() const
This method checks whether this object is backed by a valid SVG file.
Q_INVOKABLE QSizeF elementSize(const QString &elementId) const
This method returns the size of a given element.
void setUsingRenderingCache(bool useCache)
This method sets whether or not to cache the results of rendering to pixmaps.
void setImageSet(KSvg::ImageSet *theme)
This method sets the KSvg::ImageSet to use with this Svg object.
Q_SCRIPTABLE CaptureState status()
KCOREADDONS_EXPORT Result match(QStringView pattern, QStringView str)
QAction * hint(const QObject *recvr, const char *slot, QObject *parent)
QAction * load(const QObject *recvr, const char *slot, QObject *parent)
QString path(const QString &relativePath)
KIOCORE_EXPORT QStringList list(const QString &fileClass)
KTEXTEDITOR_EXPORT size_t qHash(KTextEditor::Cursor cursor, size_t seed=0) noexcept
const char * constData() const const
bool contains(QByteArrayView bv) const const
void reserve(qsizetype size)
qsizetype size() const const
bool isValid() const const
qint64 toSecsSinceEpoch() const const
bool isAbsolutePath(const QString &path)
bool exists(const QString &path)
iterator insert(const Key &key, const T &value)
bool isEmpty() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool disconnect(const QMetaObject::Connection &connection)
virtual bool eventFilter(QObject *watched, QEvent *event)
QObject * parent() const const
T qobject_cast(QObject *object)
qreal devicePixelRatio() const const
QPaintDevice * device() const const
void drawPixmap(const QPoint &point, const QPixmap &pixmap)
qint64 cacheKey() const const
void fill(const QColor &color)
bool isNull() const const
void setDevicePixelRatio(qreal scaleFactor)
QImage toImage() const const
qreal height() const const
bool isValid() const const
QSizeF size() const const
qreal width() const const
bool isEmpty() const const
qreal height() const const
bool isEmpty() const const
bool isValid() const const
QSize toSize() const const
qreal width() const const
QString writableLocation(StandardLocation type)
QString & append(QChar ch)
QString fromLatin1(QByteArrayView str)
QString & insert(qsizetype position, QChar ch)
bool isEmpty() const const
bool isNull() const const
QString number(double n, char format, int precision)
QString & remove(QChar ch, Qt::CaseSensitivity cs)
QString & replace(QChar before, QChar after, Qt::CaseSensitivity cs)
qsizetype size() const const
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
QByteArray toUtf8() const const
bool isEmpty() const const
QString toString() const const
bool load(QXmlStreamReader *contents)
QFuture< typename qValueType< Iterator >::value_type > filtered(Iterator begin, Iterator end, KeepFunctor &&filterFunction)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)