10#include "private/imageset_p.h"
11#include "private/svg_p.h"
17#include <QCoreApplication>
20#include <QRegularExpression>
21#include <QStringBuilder>
22#include <QXmlStreamReader>
23#include <QXmlStreamWriter>
25#include <KCompressionDevice>
26#include <KConfigGroup>
32size_t qHash(
const KSvg::SvgPrivate::CacheId &
id,
size_t seed)
34 std::array<size_t, 10> parts = {
37 ::qHash(
id.elementName),
40 ::qHash(
id.scaleFactor),
42 ::qHash(
id.styleSheet),
43 ::qHash(
id.extraFlags),
44 ::qHash(
id.lastModified),
46 return qHashRange(parts.begin(), parts.end(), seed);
51 std::vector<size_t> parts;
52 for (
const QColor &c :
std::as_const(colors)) {
53 parts.push_back(::qHash(c.red()));
54 parts.push_back(::qHash(c.green()));
55 parts.push_back(::qHash(c.blue()));
56 parts.push_back(::qHash(c.alpha()));
58 return qHashRange(parts.begin(), parts.end(), seed);
63class SvgRectsCacheSingleton
69Q_GLOBAL_STATIC(SvgRectsCacheSingleton, privateSvgRectsCacheSelf)
71const size_t SvgRectsCache::s_seed = 0x9e3779b9;
73SharedSvgRenderer::SharedSvgRenderer(
QObject *parent)
85 m_filename = filename;
86 m_styleSheet = styleSheet;
87 m_interestingElements = interestingElements;
88 load(file.readAll(), styleSheet, interestingElements);
94 load(contents, styleSheet, interestingElements);
97void SharedSvgRenderer::reload()
104 load(file.readAll(), m_styleSheet, m_interestingElements);
110 if (!styleSheet.
isEmpty() && contents.
contains(
"current-color-scheme")) {
115 QBuffer buffer(&processedContents);
118 while (!reader.atEnd()) {
122 writer.writeAttributes(reader.attributes());
123 writer.writeCharacters(styleSheet);
124 writer.writeEndElement();
129 writer.writeCurrentToken(reader);
143 Q_ASSERT(idExpr.isValid());
145 auto matchIt = idExpr.globalMatch(contentsAsString);
146 while (matchIt.hasNext()) {
147 auto match = matchIt.next();
150 QRectF elementRect = boundsOnElement(elementId);
152 interestingElements.
insert(elementId, elementRect);
159SvgRectsCache::SvgRectsCache(
QObject *parent)
165 m_configSyncTimer =
new QTimer(
this);
166 m_configSyncTimer->setSingleShot(
true);
167 m_configSyncTimer->setInterval(5000);
169 m_svgElementsCache->sync();
173SvgRectsCache *SvgRectsCache::instance()
175 return &privateSvgRectsCacheSelf()->self;
178void SvgRectsCache::insert(KSvg::SvgPrivate::CacheId cacheId,
const QRectF &rect,
unsigned int lastModified)
180 insert(
qHash(cacheId, SvgRectsCache::s_seed), cacheId.filePath, rect, lastModified);
183void SvgRectsCache::insert(
size_t id,
const QString &filePath,
const QRectF &rect,
unsigned int lastModified)
185 const unsigned int savedTime = lastModifiedTimeFromCache(filePath);
187 if (savedTime == lastModified && m_localRectCache.contains(
id)) {
191 m_localRectCache.insert(
id, rect);
198 m_invalidElements[filePath] << id;
199 imageGroup.writeEntry(
"Invalidelements", m_invalidElements[filePath].values());
204 if (savedTime != lastModified) {
205 m_lastModifiedTimes[filePath] = lastModified;
206 imageGroup.writeEntry(
"LastModified", lastModified);
207 Q_EMIT lastModifiedChanged(filePath, lastModified);
211bool SvgRectsCache::findElementRect(KSvg::SvgPrivate::CacheId cacheId,
QRectF &rect)
213 return findElementRect(
qHash(cacheId, SvgRectsCache::s_seed), cacheId.filePath, rect);
216bool SvgRectsCache::findElementRect(
size_t id,
QStringView filePath,
QRectF &rect)
218 auto it = m_localRectCache.find(
id);
220 if (it == m_localRectCache.end()) {
221 auto elements = m_invalidElements.value(filePath.
toString());
222 if (elements.contains(
id)) {
234bool SvgRectsCache::loadImageFromCache(
const QString &path, uint lastModified)
242 unsigned int savedTime = lastModifiedTimeFromCache(path);
245 if (lastModified != savedTime) {
246 imageGroup.deleteGroup();
251 auto &elements = m_invalidElements[
path];
252 if (elements.isEmpty()) {
256 for (
const auto &key : imageGroup.keyList()) {
258 uint keyUInt = key.toUInt(&ok);
260 const QRectF rect = imageGroup.readEntry(key,
QRectF());
261 m_localRectCache.insert(keyUInt, rect);
268void SvgRectsCache::dropImageFromCache(
const QString &path)
271 imageGroup.deleteGroup();
279 auto it = m_sizeHintsForId.constFind(pathId);
280 if (it == m_sizeHintsForId.constEnd()) {
284 for (
const auto &token : encoded) {
286 if (parts.size() != 2) {
289 QSize size =
QSize(parts[0].toDouble(), parts[1].toDouble());
294 m_sizeHintsForId[pathId] = sizes;
301void SvgRectsCache::insertSizeHintForId(
const QString &path,
const QString &
id,
const QSize &size)
306 for (
const auto &s :
list) {
313 imageGroup.writeEntry(
id, sizeListToString(m_sizeHintsForId[path %
id]));
317QString SvgRectsCache::iconThemePath()
319 if (!m_iconThemePath.isEmpty()) {
320 return m_iconThemePath;
323 KConfigGroup imageGroup(m_svgElementsCache, QStringLiteral(
"General"));
324 m_iconThemePath = imageGroup.readEntry(QStringLiteral(
"IconThemePath"),
QString());
326 return m_iconThemePath;
329void SvgRectsCache::setIconThemePath(
const QString &path)
331 m_iconThemePath =
path;
332 KConfigGroup imageGroup(m_svgElementsCache, QStringLiteral(
"General"));
333 imageGroup.writeEntry(QStringLiteral(
"IconThemePath"), path);
337void SvgRectsCache::setNaturalSize(
const QString &path,
const QSizeF &size)
342 imageGroup.writeEntry(QStringLiteral(
"NaturalSize"), size);
351 return imageGroup.readEntry(QStringLiteral(
"NaturalSize"),
QSizeF());
368unsigned int SvgRectsCache::lastModifiedTimeFromCache(
const QString &filePath)
370 const auto &i = m_lastModifiedTimes.constFind(filePath);
371 if (i != m_lastModifiedTimes.constEnd()) {
376 const unsigned int savedTime = imageGroup.readEntry(
"LastModified", 0);
377 m_lastModifiedTimes[filePath] = savedTime;
381void SvgRectsCache::updateLastModified(
const QString &filePath,
unsigned int lastModified)
384 const unsigned int savedTime = lastModifiedTimeFromCache(filePath);
386 if (savedTime != lastModified) {
387 m_lastModifiedTimes[filePath] = lastModified;
388 imageGroup.writeEntry(
"LastModified", lastModified);
390 Q_EMIT lastModifiedChanged(filePath, lastModified);
394SvgPrivate::SvgPrivate(Svg *svg)
399 , devicePixelRatio(1.0)
401 , multipleImages(false)
403 , fromCurrentImageSet(false)
404 , cacheRendering(true)
409SvgPrivate::~SvgPrivate()
414size_t SvgPrivate::paletteId(
const QPalette &palette,
const QColor &positive,
const QColor &neutral,
const QColor &negative)
const
416 std::array<size_t, 4> parts = {
418 ::qHash(positive.
rgba()),
419 ::qHash(neutral.
rgba()),
420 ::qHash(negative.
rgba()),
422 return qHashRange(parts.begin(), parts.end(), SvgRectsCache::s_seed);
426SvgPrivate::CacheId SvgPrivate::cacheId(
QStringView elementId)
const
428 auto idSize = size.
isValid() && size != naturalSize ? size :
QSizeF{-1.0, -1.0};
429 return CacheId{idSize.
width(), idSize.height(),
path, elementId.
toString(),
status, devicePixelRatio, -1, 0, 0, lastModified};
435 std::vector<size_t> parts;
436 const auto colors = colorOverrides.values();
437 for (
const QColor &c :
std::as_const(colors)) {
439 parts.push_back(::qHash(c.green()));
440 parts.push_back(::qHash(c.blue()));
441 parts.push_back(::qHash(c.alpha()));
443 const size_t colorsHash = qHashRange(parts.begin(), parts.end(), SvgRectsCache::s_seed);
445 auto cacheId = CacheId{double(size.
width()), double(size.
height()),
path, id,
status, devicePixelRatio, colorSet, colorsHash, 0, lastModified};
449bool SvgPrivate::setImagePath(
const QString &imagePath)
451 QString actualPath = imagePath;
456 isAbsoluteFile =
true;
463 isAbsoluteFile =
true;
466 bool isThemed = !actualPath.
isEmpty() && !isAbsoluteFile;
469 if (isThemed == themed && ((themed && themePath == actualPath) || (!themed && path == actualPath))) {
477 bool updateNeeded =
true;
480 if (isThemed && !themed && s_systemColorsCache) {
490 bool oldfromCurrentImageSet = fromCurrentImageSet;
491 fromCurrentImageSet = isThemed && actualImageSet()->currentImageSetHasImage(imagePath);
493 if (fromCurrentImageSet != oldfromCurrentImageSet) {
494 Q_EMIT q->fromCurrentImageSetChanged(fromCurrentImageSet);
498 themePath = actualPath;
499 path = actualImageSet()->imagePath(themePath);
501 imageSetChangedConnection =
QObject::connect(actualImageSet(), &ImageSet::imageSetChanged, q, [
this]() {
505 imageSetChangedConnection =
QObject::connect(actualImageSet(), &ImageSet::imageSetChanged, q, [
this]() {
518 lastModifiedDate = info.lastModified();
522 const bool imageWasCached = SvgRectsCache::instance()->loadImageFromCache(path, lastModified);
524 if (!imageWasCached) {
525 auto i = s_renderers.constBegin();
526 while (i != s_renderers.constEnd()) {
527 if (i.key().contains(path)) {
538 naturalSize = SvgRectsCache::instance()->naturalSize(path);
539 if (naturalSize.isEmpty()) {
541 naturalSize = renderer->defaultSize();
542 SvgRectsCache::instance()->setNaturalSize(path, naturalSize);
547 Q_EMIT q->imagePathChanged();
552ImageSet *SvgPrivate::actualImageSet()
561ImageSet *SvgPrivate::cacheAndColorsImageSet()
564 return actualImageSet();
567 if (!s_systemColorsCache) {
569 s_systemColorsCache =
new KSvg::ImageSet(QStringLiteral(
"internal-system-colors"));
572 return s_systemColorsCache.data();
584 const QList<QSize> elementSizeHints = SvgRectsCache::instance()->sizeHintsForId(path, elementId);
586 if (!elementSizeHints.
isEmpty()) {
589 for (
const auto &hint : elementSizeHints) {
591 && (!bestFit.isValid() || (bestFit.width() * bestFit.height()) > (
hint.width() *
hint.height()))) {
596 if (bestFit.isValid()) {
602 if (elementId.
isEmpty() || !q->hasElement(actualElementId)) {
603 actualElementId = elementId;
607 size = s.
toSize() * ratio;
609 size = elementRect(actualElementId).
size().
toSize() * ratio;
616 const QString id = cachePath(actualElementId, size);
619 if (cacheRendering && lastModified == SvgRectsCache::instance()->lastModifiedTimeFromCache(path)
620 && cacheAndColorsImageSet()->d->findInCache(
id, p, lastModified)) {
628 QRectF finalRect = makeUniform(renderer->boundsOnElement(actualElementId),
QRect(
QPoint(0, 0), size));
637 if (actualElementId.
isEmpty()) {
638 renderer->render(&renderPainter, finalRect);
640 renderer->render(&renderPainter, actualElementId, finalRect);
646 if (cacheRendering) {
650 SvgRectsCache::instance()->updateLastModified(path, lastModified);
655void SvgPrivate::createRenderer()
663 path = actualImageSet()->imagePath(themePath);
666 qCWarning(LOG_KSVG) <<
"No image path found for" << themePath;
672 if (!colorOverrides.isEmpty()) {
673 if (stylesheetOverride.isEmpty()) {
674 stylesheetOverride = cacheAndColorsImageSet()->d->svgStyleSheet(q);
676 styleSheet = stylesheetOverride;
678 styleSheet = cacheAndColorsImageSet()->d->svgStyleSheet(q);
685 if (it != s_renderers.constEnd()) {
686 renderer = it.value();
689 renderer =
new SharedSvgRenderer();
692 renderer =
new SharedSvgRenderer(path, styleSheet, interestingElements);
699 while (i.hasNext()) {
701 const QString &elementId = i.key();
703 const QRectF &elementRect = i.value();
705 originalId.
replace(sizeHintedKeyExpr, QStringLiteral(
"\\3"));
706 SvgRectsCache::instance()->insertSizeHintForId(path, originalId, elementRect.
size().
toSize());
708 const CacheId cacheId{.width = -1.0,
711 .elementName = elementId,
713 .scaleFactor = devicePixelRatio,
717 .lastModified = lastModified};
718 SvgRectsCache::instance()->
insert(cacheId, elementRect, lastModified);
722 s_renderers[styleCrc +
path] = renderer;
726 size = renderer->defaultSize();
730void SvgPrivate::eraseRenderer()
732 if (renderer && renderer->ref.loadRelaxed() == 2) {
734 s_renderers.erase(s_renderers.find(styleCrc + path));
748 path = actualImageSet()->imagePath(themePath);
761 const CacheId cacheId = SvgPrivate::cacheId(elementId);
762 bool found = SvgRectsCache::instance()->findElementRect(cacheId, rect);
765 rect = findAndCacheElementRect(elementId);
774 const CacheId cacheId = SvgPrivate::cacheId(elementId);
778 auto elementIdString = elementId.
toString();
781 QRectF elementRect = renderer->elementExists(elementIdString)
782 ? renderer->transformForElement(elementIdString).map(renderer->boundsOnElement(elementIdString)).boundingRect()
785 naturalSize = renderer->defaultSize();
787 qreal dx = size.
width() / renderer->defaultSize().width();
788 qreal dy = size.
height() / renderer->defaultSize().height();
790 elementRect =
QRectF(elementRect.
x() * dx, elementRect.
y() * dy, elementRect.
width() * dx, elementRect.
height() * dy);
791 SvgRectsCache::instance()->insert(cacheId, elementRect, lastModified);
803qreal SvgPrivate::closestDistance(qreal to, qreal from)
806 if (qFuzzyCompare(to, from)) {
808 }
else if (to > from) {
809 qreal b = to - from - 1;
810 return (qAbs(a) > qAbs(b)) ? b : a;
812 qreal b = 1 + to - from;
813 return (qAbs(a) > qAbs(b)) ? b : a;
819 if (qFuzzyIsNull(orig.
x()) || qFuzzyIsNull(orig.
y())) {
827 qreal div_x = dst.
x() / orig.
x();
828 qreal div_y = dst.
y() / orig.
y();
831 if (!qFuzzyIsNull(div_x) && !qFuzzyCompare(div_w, div_x)) {
832 qreal rem_orig = orig.
x() - (floor(orig.
x()));
833 qreal rem_dst = dst.
x() - (floor(dst.
x()));
834 qreal offset = closestDistance(rem_dst, rem_orig);
835 res.translate(offset + offset * div_w, 0);
836 res.setWidth(res.width() + offset);
839 if (!qFuzzyIsNull(div_y) && !qFuzzyCompare(div_h, div_y)) {
840 qreal rem_orig = orig.
y() - (floor(orig.
y()));
841 qreal rem_dst = dst.
y() - (floor(dst.
y()));
842 qreal offset = closestDistance(rem_dst, rem_orig);
843 res.translate(0, offset + offset * div_h);
844 res.setHeight(res.height() + offset);
850void SvgPrivate::imageSetChanged()
852 if (q->imagePath().isEmpty()) {
859 setImagePath(currentPath);
863 Q_EMIT q->repaintNeeded();
864 Q_EMIT q->imageSetChanged(q->imageSet());
867void SvgPrivate::colorsChanged()
870 qCDebug(LOG_KSVG) <<
"repaint needed from colorsChanged";
872 Q_EMIT q->repaintNeeded();
880 , d(new SvgPrivate(this))
882 connect(SvgRectsCache::instance(), &SvgRectsCache::lastModifiedChanged,
this, [
this](
const QString &filePath,
unsigned int lastModified) {
883 if (d->lastModified != lastModified && filePath == d->path) {
884 d->lastModified = lastModified;
885 Q_EMIT repaintNeeded();
900 if (floor(d->devicePixelRatio) == floor(ratio)) {
904 if (
FrameSvg *f = qobject_cast<FrameSvg *>(
this)) {
908 d->devicePixelRatio = floor(ratio);
915 return d->devicePixelRatio;
920 if (elementID.
isNull() || d->multipleImages) {
921 return d->findInCache(elementID, d->devicePixelRatio, size());
923 return d->findInCache(elementID, d->devicePixelRatio);
929 QPixmap pix(d->findInCache(elementID, d->devicePixelRatio, size));
935 Q_ASSERT(painter->
device());
937 QPixmap pix((elementID.
isNull() || d->multipleImages) ? d->findInCache(elementID, ratio, size()) : d->findInCache(elementID, ratio));
953 Q_ASSERT(painter->
device());
955 QPixmap pix(d->findInCache(elementID, ratio, rect.
size()));
962 Q_ASSERT(painter->
device());
964 QPixmap pix(d->findInCache(elementID, ratio,
QSizeF(width, height)));
970 if (d->size.isEmpty()) {
971 d->size = d->naturalSize;
974 return {std::round(d->size.width()), std::round(d->size.height())};
984 if (qFuzzyCompare(size.
width(), d->size.width()) && qFuzzyCompare(size.
height(), d->size.height())) {
994 if (qFuzzyCompare(d->naturalSize.width(), d->size.width()) && qFuzzyCompare(d->naturalSize.height(), d->size.height())) {
998 d->size = d->naturalSize;
1004 const QSizeF s = d->elementRect(elementId).size();
1005 return {std::round(s.
width()), std::round(s.
height())};
1010 const QSizeF s = d->elementRect(elementId).size();
1011 return {std::round(s.
width()), std::round(s.
height())};
1016 return d->elementRect(elementId);
1021 return d->elementRect(elementId);
1031 if (elementId.
isEmpty() || (d->path.isNull() && d->themePath.isNull())) {
1035 return d->elementRect(elementId).isValid();
1040 if (d->path.isNull() && d->themePath.isNull()) {
1045 QSizeF naturalSize = SvgRectsCache::instance()->naturalSize(d->path);
1053 d->createRenderer();
1054 return d->renderer->isValid();
1059 d->multipleImages = multiple;
1064 return d->multipleImages;
1069 if (d->setImagePath(svgFilePath)) {
1076 return d->themed ? d->themePath : d->path;
1081 d->cacheRendering = useCache;
1087 return d->cacheRendering;
1090bool Svg::fromCurrentImageSet()
const
1092 return d->fromCurrentImageSet;
1097 if (!theme || theme == d->theme.data()) {
1102 disconnect(d->theme.data(),
nullptr,
this,
nullptr);
1107 d->imageSetChanged();
1112 return d->actualImageSet();
1117 if (
status == d->status) {
1127Svg::Status Svg::status()
const
1135 if (convertedSet == d->colorSet) {
1139 d->colorSet = convertedSet;
1145Svg::ColorSet Svg::colorSet()
const
1147 return Svg::ColorSet(d->colorSet);
1150QColor Svg::color(StyleSheetColor colorName)
const
1152 auto it = d->colorOverrides.constFind(colorName);
1153 if (it != d->colorOverrides.constEnd()) {
1156 return d->cacheAndColorsImageSet()->d->namedColor(colorName,
this);
1159void Svg::setColor(StyleSheetColor colorName,
const QColor &color)
1161 if (d->colorOverrides.value(colorName) == color) {
1166 d->colorOverrides[colorName] = color;
1168 d->colorOverrides.remove(colorName);
1170 d->stylesheetOverride.clear();
1176void Svg::clearColorOverrides()
1178 d->colorOverrides.clear();
1179 d->stylesheetOverride.clear();
1186#include "moc_svg.cpp"
1187#include "private/moc_svg_p.cpp"
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
Provides an SVG with borders.
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.
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()
bool insert(Part *part, qint64 *insertId=nullptr)
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
bool isValid() const const
qint64 toSecsSinceEpoch() const const
bool isAbsolutePath(const QString &path)
bool exists() const const
iterator insert(const Key &key, const T &value)
bool isEmpty() const const
void push_back(parameter_type value)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool disconnect(const QMetaObject::Connection &connection)
virtual bool eventFilter(QObject *watched, QEvent *event)
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)
void setDevicePixelRatio(qreal scaleFactor)
QImage toImage() const const
qreal height() const const
bool isValid() const const
QSizeF size() const const
QPointF topLeft() 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)