don't regenerate frames when setting every property
Summary: give frameSvg the concept of repaintBlocked(), that enables and disables the regeneration of the frame data when a property is set. the use case is when often, a lot of properties are set one after the other (such as prefix, enabled borders, size) collapse the formely similar, but a bit different logic of frame regeneration is a single function for better maintanability. QML FrameSvgItem sets repaintblocked when it starts and releases it just on oncomponentCompleted Test Plan: plasmashell still starts, autotests still work, all frames are rendered correctly the destruction of old frames is cutted by 50%. in the qml profiler the creation time of a framesvgitem slightly improved, on this machine from around 26 msecs to around 21, can still be improved, but at least the code is a bit simpler Reviewers: #plasma Subscribers: davidedmundson, plasma-devel, #frameworks Tags: #plasma, #frameworks Differential Revision: https://phabricator.kde.org/D4414
This commit is contained in:
parent
50699af19a
commit
d8a1a9eb08
Binary file not shown.
@ -54,6 +54,23 @@ void FrameSvgTest::contentsRect()
|
||||
QCOMPARE(m_frameSvg->contentsRect(), QRectF(26, 26, 48, 48));
|
||||
}
|
||||
|
||||
void FrameSvgTest::repaintBlocked()
|
||||
{
|
||||
//check the properties to be correct even if set during a repaint blocked transaction
|
||||
m_frameSvg->setRepaintBlocked(true);
|
||||
QVERIFY(m_frameSvg->isRepaintBlocked());
|
||||
|
||||
m_frameSvg->setElementPrefix("prefix");
|
||||
m_frameSvg->setEnabledBorders(Plasma::FrameSvg::TopBorder|Plasma::FrameSvg::LeftBorder);
|
||||
m_frameSvg->resizeFrame(QSizeF(100,100));
|
||||
|
||||
m_frameSvg->setRepaintBlocked(false);
|
||||
|
||||
QCOMPARE(m_frameSvg->prefix(), QString("prefix"));
|
||||
QCOMPARE(m_frameSvg->enabledBorders(), Plasma::FrameSvg::TopBorder|Plasma::FrameSvg::LeftBorder);
|
||||
QCOMPARE(m_frameSvg->frameSize(), QSizeF(100,100));
|
||||
}
|
||||
|
||||
void FrameSvgTest::setTheme()
|
||||
{
|
||||
// Should not crash
|
||||
|
@ -38,6 +38,7 @@ private Q_SLOTS:
|
||||
void margins();
|
||||
void contentsRect();
|
||||
void setTheme();
|
||||
void repaintBlocked();
|
||||
|
||||
private:
|
||||
Plasma::FrameSvg *m_frameSvg;
|
||||
|
@ -516,10 +516,17 @@ QSGNode *FrameSvgItem::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaint
|
||||
return oldNode;
|
||||
}
|
||||
|
||||
void FrameSvgItem::classBegin()
|
||||
{
|
||||
QQuickItem::classBegin();
|
||||
m_frameSvg->setRepaintBlocked(true);
|
||||
}
|
||||
|
||||
void FrameSvgItem::componentComplete()
|
||||
{
|
||||
QQuickItem::componentComplete();
|
||||
m_frameSvg->resizeFrame(QSize(width(), height()));
|
||||
m_frameSvg->setRepaintBlocked(false);
|
||||
m_textureChanged = true;
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#define FRAMESVGITEM_P
|
||||
|
||||
#include <QQuickItem>
|
||||
#include <QQmlParserStatus>
|
||||
|
||||
#include <Plasma/FrameSvg>
|
||||
|
||||
@ -107,6 +108,7 @@ private:
|
||||
class FrameSvgItem : public QQuickItem
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(QQmlParserStatus)
|
||||
|
||||
/**
|
||||
* Theme relative path of the svg, like "widgets/background"
|
||||
@ -213,6 +215,7 @@ public:
|
||||
|
||||
|
||||
protected:
|
||||
void classBegin() Q_DECL_OVERRIDE;
|
||||
void componentComplete() Q_DECL_OVERRIDE;
|
||||
|
||||
/// @endcond
|
||||
|
@ -49,7 +49,9 @@ static const int MAX_FRAME_SIZE = 100000;
|
||||
FrameData::~FrameData()
|
||||
{
|
||||
for (auto it = references.constBegin(), end = references.constEnd(); it != end; ++it) {
|
||||
it.key()->d->frames.remove(prefix);
|
||||
if (it.key()->d->frame == this) {
|
||||
it.key()->d->frame = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,7 +61,7 @@ FrameSvg::FrameSvg(QObject *parent)
|
||||
d(new FrameSvgPrivate(this))
|
||||
{
|
||||
connect(this, SIGNAL(repaintNeeded()), this, SLOT(updateNeeded()));
|
||||
d->frames.insert(QString(), new FrameData(this, QString()));
|
||||
d->frame = new FrameData(this, QString());
|
||||
}
|
||||
|
||||
FrameSvg::~FrameSvg()
|
||||
@ -76,7 +78,7 @@ void FrameSvg::setImagePath(const QString &path)
|
||||
bool updateNeeded = true;
|
||||
clearCache();
|
||||
|
||||
FrameData *fd = d->frames[d->prefix];
|
||||
FrameData *fd = d->frame;
|
||||
if (fd->refcount() == 1) {
|
||||
// we're the only user of it, let's remove it from the shared keys
|
||||
// we don't want to deref it, however, as we'll still be using it
|
||||
@ -92,7 +94,7 @@ void FrameSvg::setImagePath(const QString &path)
|
||||
|
||||
if (!fd) {
|
||||
// we need to replace our frame, start by looking in the frame cache
|
||||
FrameData *oldFd = d->frames[d->prefix];
|
||||
FrameData *oldFd = d->frame;
|
||||
const QString key = d->cacheId(oldFd, d->prefix);
|
||||
fd = FrameSvgPrivate::s_sharedFrames[theme()->d].value(key);
|
||||
|
||||
@ -108,7 +110,7 @@ void FrameSvg::setImagePath(const QString &path)
|
||||
fd = new FrameData(*oldFd, this);
|
||||
}
|
||||
|
||||
d->frames.insert(d->prefix, fd);
|
||||
d->frame = fd;
|
||||
}
|
||||
|
||||
setContainsMultipleImages(true);
|
||||
@ -127,67 +129,20 @@ void FrameSvg::setImagePath(const QString &path)
|
||||
|
||||
void FrameSvg::setEnabledBorders(const EnabledBorders borders)
|
||||
{
|
||||
if (borders == d->frames[d->prefix]->enabledBorders) {
|
||||
if (borders == d->enabledBorders) {
|
||||
return;
|
||||
}
|
||||
|
||||
FrameData *fd = d->frames[d->prefix];
|
||||
d->enabledBorders = borders;
|
||||
|
||||
const QString oldKey = d->cacheId(fd, d->prefix);
|
||||
const EnabledBorders oldBorders = fd->enabledBorders;
|
||||
fd->enabledBorders = borders;
|
||||
const QString newKey = d->cacheId(fd, d->prefix);
|
||||
fd->enabledBorders = oldBorders;
|
||||
|
||||
//qCDebug(LOG_PLASMA) << "looking for" << newKey;
|
||||
FrameData *newFd = FrameSvgPrivate::s_sharedFrames[theme()->d].value(newKey);
|
||||
if (newFd) {
|
||||
//qCDebug(LOG_PLASMA) << "FOUND IT!" << newFd->refcount;
|
||||
// we've found a math, so insert that new one and ref it ..
|
||||
newFd->ref(this);
|
||||
d->frames.insert(d->prefix, newFd);
|
||||
|
||||
//.. then deref the old one and if it's no longer used, get rid of it
|
||||
if (fd->deref(this)) {
|
||||
//const QString oldKey = d->cacheId(fd, d->prefix);
|
||||
//qCDebug(LOG_PLASMA) << "1. Removing it" << oldKey << fd->refcount;
|
||||
FrameSvgPrivate::s_sharedFrames[fd->theme].remove(oldKey);
|
||||
delete fd;
|
||||
}
|
||||
|
||||
return;
|
||||
if (!d->repaintBlocked) {
|
||||
d->updateFrameData();
|
||||
}
|
||||
|
||||
if (fd->refcount() == 1) {
|
||||
// we're the only user of it, let's remove it from the shared keys
|
||||
// we don't want to deref it, however, as we'll still be using it
|
||||
FrameSvgPrivate::s_sharedFrames[fd->theme].remove(oldKey);
|
||||
} else {
|
||||
// others are using it, but we wish to change its size. so deref it,
|
||||
// then create a copy of it (we're automatically ref'd via the ctor),
|
||||
// then insert it into our frames.
|
||||
fd->deref(this);
|
||||
fd = new FrameData(*fd, this);
|
||||
d->frames.insert(d->prefix, fd);
|
||||
}
|
||||
|
||||
fd->enabledBorders = borders;
|
||||
d->updateAndSignalSizes();
|
||||
}
|
||||
|
||||
FrameSvg::EnabledBorders FrameSvg::enabledBorders() const
|
||||
{
|
||||
if (d->frames.isEmpty()) {
|
||||
return NoBorder;
|
||||
}
|
||||
|
||||
QHash<QString, FrameData *>::const_iterator it = d->frames.constFind(d->prefix);
|
||||
|
||||
if (it != d->frames.constEnd()) {
|
||||
return it.value()->enabledBorders;
|
||||
} else {
|
||||
return NoBorder;
|
||||
}
|
||||
return d->enabledBorders;
|
||||
}
|
||||
|
||||
void FrameSvg::setElementPrefix(Plasma::Types::Location location)
|
||||
@ -215,8 +170,6 @@ void FrameSvg::setElementPrefix(Plasma::Types::Location location)
|
||||
|
||||
void FrameSvg::setElementPrefix(const QString &prefix)
|
||||
{
|
||||
const QString oldPrefix(d->prefix);
|
||||
|
||||
if (!hasElement(prefix % QLatin1String("-center"))) {
|
||||
d->prefix.clear();
|
||||
} else {
|
||||
@ -227,64 +180,11 @@ void FrameSvg::setElementPrefix(const QString &prefix)
|
||||
}
|
||||
d->requestedPrefix = prefix;
|
||||
|
||||
FrameData *oldFrameData = d->frames.value(oldPrefix);
|
||||
if (oldPrefix == d->prefix && oldFrameData) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!d->frames.contains(d->prefix)) {
|
||||
if (oldFrameData) {
|
||||
FrameData *newFd = 0;
|
||||
if (!oldFrameData->frameSize.isEmpty()) {
|
||||
const QString key = d->cacheId(oldFrameData, d->prefix);
|
||||
newFd = FrameSvgPrivate::s_sharedFrames[theme()->d].value(key);
|
||||
if (newFd && newFd->devicePixelRatio != devicePixelRatio()) {
|
||||
newFd = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// we need to put this in the cache if we didn't find it in the shared frames
|
||||
// and we have a size; if we don't have a size, we'll catch it later
|
||||
const bool cache = !newFd && !oldFrameData->frameSize.isEmpty();
|
||||
if (newFd) {
|
||||
newFd->ref(this);
|
||||
} else {
|
||||
newFd = new FrameData(*oldFrameData, this);
|
||||
}
|
||||
|
||||
d->frames.insert(d->prefix, newFd);
|
||||
|
||||
if (cache) {
|
||||
// we have to cache after inserting the frame since the cacheId requires the
|
||||
// frame to be in the frames collection already
|
||||
const QString key = d->cacheId(oldFrameData, d->prefix);
|
||||
//qCDebug(LOG_PLASMA) << this << " 1. inserting as" << key;
|
||||
|
||||
FrameSvgPrivate::s_sharedFrames[theme()->d].insert(key, newFd);
|
||||
newFd->theme = theme()->d;
|
||||
}
|
||||
} else {
|
||||
// couldn't find anything useful, so we just create something here
|
||||
// we don't have a size for it yet, so don't bother trying to share it just yet
|
||||
FrameData *newFd = new FrameData(this, d->prefix);
|
||||
d->frames.insert(d->prefix, newFd);
|
||||
}
|
||||
|
||||
d->updateSizes();
|
||||
}
|
||||
|
||||
if (!d->cacheAll) {
|
||||
d->frames.remove(oldPrefix);
|
||||
if (oldFrameData) {
|
||||
if (oldFrameData->deref(this)) {
|
||||
const QString oldKey = d->cacheId(oldFrameData, oldPrefix);
|
||||
FrameSvgPrivate::s_sharedFrames[oldFrameData->theme].remove(oldKey);
|
||||
delete oldFrameData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
d->location = Types::Floating;
|
||||
|
||||
if (!d->repaintBlocked) {
|
||||
d->updateFrameData();
|
||||
}
|
||||
}
|
||||
|
||||
bool FrameSvg::hasElementPrefix(const QString &prefix) const
|
||||
@ -337,155 +237,108 @@ void FrameSvg::resizeFrame(const QSizeF &size)
|
||||
return;
|
||||
}
|
||||
|
||||
FrameData *fd = d->frames[d->prefix];
|
||||
if (size == fd->frameSize) {
|
||||
if (size.toSize() == d->frame->frameSize) {
|
||||
return;
|
||||
}
|
||||
d->pendingFrameSize = size.toSize();
|
||||
|
||||
const QString oldKey = d->cacheId(fd, d->prefix);
|
||||
const QSize currentSize = fd->frameSize;
|
||||
fd->frameSize = size.toSize();
|
||||
const QString newKey = d->cacheId(fd, d->prefix);
|
||||
fd->frameSize = currentSize;
|
||||
|
||||
//qCDebug(LOG_PLASMA) << "looking for" << newKey;
|
||||
FrameData *newFd = FrameSvgPrivate::s_sharedFrames[theme()->d].value(newKey);
|
||||
if (newFd) {
|
||||
//qCDebug(LOG_PLASMA) << "FOUND IT!" << newFd->refcount;
|
||||
// we've found a math, so insert that new one and ref it ..
|
||||
newFd->ref(this);
|
||||
d->frames.insert(d->prefix, newFd);
|
||||
|
||||
//.. then deref the old one and if it's no longer used, get rid of it
|
||||
if (fd->deref(this)) {
|
||||
//const QString oldKey = d->cacheId(fd, d->prefix);
|
||||
//qCDebug(LOG_PLASMA) << "1. Removing it" << oldKey << fd->refcount;
|
||||
FrameSvgPrivate::s_sharedFrames[fd->theme].remove(oldKey);
|
||||
delete fd;
|
||||
}
|
||||
|
||||
return;
|
||||
if (!d->repaintBlocked) {
|
||||
d->updateFrameData();
|
||||
}
|
||||
|
||||
if (fd->refcount() == 1) {
|
||||
// we're the only user of it, let's remove it from the shared keys
|
||||
// we don't want to deref it, however, as we'll still be using it
|
||||
FrameSvgPrivate::s_sharedFrames[fd->theme].remove(oldKey);
|
||||
} else {
|
||||
// others are using it, but we wish to change its size. so deref it,
|
||||
// then create a copy of it (we're automatically ref'd via the ctor),
|
||||
// then insert it into our frames.
|
||||
fd->deref(this);
|
||||
fd = new FrameData(*fd, this);
|
||||
d->frames.insert(d->prefix, fd);
|
||||
}
|
||||
|
||||
d->updateSizes();
|
||||
fd->frameSize = size.toSize();
|
||||
// we know it isn't in s_sharedFrames due to the check above, so insert it now
|
||||
FrameSvgPrivate::s_sharedFrames[theme()->d].insert(newKey, fd);
|
||||
fd->theme = theme()->d;
|
||||
}
|
||||
|
||||
QSizeF FrameSvg::frameSize() const
|
||||
{
|
||||
QHash<QString, FrameData *>::const_iterator it = d->frames.constFind(d->prefix);
|
||||
|
||||
if (it == d->frames.constEnd()) {
|
||||
if (!d->frame) {
|
||||
return QSize(-1, -1);
|
||||
} else {
|
||||
return d->frameSize(it.value());
|
||||
return d->frameSize(d->frame);
|
||||
}
|
||||
}
|
||||
|
||||
qreal FrameSvg::marginSize(const Plasma::Types::MarginEdge edge) const
|
||||
{
|
||||
if (d->frames[d->prefix]->noBorderPadding) {
|
||||
if (d->frame->noBorderPadding) {
|
||||
return .0;
|
||||
}
|
||||
|
||||
switch (edge) {
|
||||
case Plasma::Types::TopMargin:
|
||||
return d->frames[d->prefix]->topMargin;
|
||||
return d->frame->topMargin;
|
||||
break;
|
||||
|
||||
case Plasma::Types::LeftMargin:
|
||||
return d->frames[d->prefix]->leftMargin;
|
||||
return d->frame->leftMargin;
|
||||
break;
|
||||
|
||||
case Plasma::Types::RightMargin:
|
||||
return d->frames[d->prefix]->rightMargin;
|
||||
return d->frame->rightMargin;
|
||||
break;
|
||||
|
||||
//Plasma::BottomMargin
|
||||
default:
|
||||
return d->frames[d->prefix]->bottomMargin;
|
||||
return d->frame->bottomMargin;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
qreal FrameSvg::fixedMarginSize(const Plasma::Types::MarginEdge edge) const
|
||||
{
|
||||
if (d->frames[d->prefix]->noBorderPadding) {
|
||||
if (d->frame->noBorderPadding) {
|
||||
return .0;
|
||||
}
|
||||
|
||||
switch (edge) {
|
||||
case Plasma::Types::TopMargin:
|
||||
return d->frames[d->prefix]->fixedTopMargin;
|
||||
return d->frame->fixedTopMargin;
|
||||
break;
|
||||
|
||||
case Plasma::Types::LeftMargin:
|
||||
return d->frames[d->prefix]->fixedLeftMargin;
|
||||
return d->frame->fixedLeftMargin;
|
||||
break;
|
||||
|
||||
case Plasma::Types::RightMargin:
|
||||
return d->frames[d->prefix]->fixedRightMargin;
|
||||
return d->frame->fixedRightMargin;
|
||||
break;
|
||||
|
||||
//Plasma::BottomMargin
|
||||
default:
|
||||
return d->frames[d->prefix]->fixedBottomMargin;
|
||||
return d->frame->fixedBottomMargin;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void FrameSvg::getMargins(qreal &left, qreal &top, qreal &right, qreal &bottom) const
|
||||
{
|
||||
FrameData *frame = d->frames[d->prefix];
|
||||
|
||||
if (frame->noBorderPadding) {
|
||||
if (d->frame->noBorderPadding) {
|
||||
left = top = right = bottom = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
top = frame->topMargin;
|
||||
left = frame->leftMargin;
|
||||
right = frame->rightMargin;
|
||||
bottom = frame->bottomMargin;
|
||||
top = d->frame->topMargin;
|
||||
left = d->frame->leftMargin;
|
||||
right = d->frame->rightMargin;
|
||||
bottom = d->frame->bottomMargin;
|
||||
}
|
||||
|
||||
void FrameSvg::getFixedMargins(qreal &left, qreal &top, qreal &right, qreal &bottom) const
|
||||
{
|
||||
FrameData *frame = d->frames[d->prefix];
|
||||
|
||||
if (frame->noBorderPadding) {
|
||||
if (d->frame->noBorderPadding) {
|
||||
left = top = right = bottom = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
top = frame->fixedTopMargin;
|
||||
left = frame->fixedLeftMargin;
|
||||
right = frame->fixedRightMargin;
|
||||
bottom = frame->fixedBottomMargin;
|
||||
top = d->frame->fixedTopMargin;
|
||||
left = d->frame->fixedLeftMargin;
|
||||
right = d->frame->fixedRightMargin;
|
||||
bottom = d->frame->fixedBottomMargin;
|
||||
}
|
||||
|
||||
QRectF FrameSvg::contentsRect() const
|
||||
{
|
||||
FrameData* frame = d->frames.value(d->prefix);
|
||||
if (frame) {
|
||||
QRectF rect(QPoint(0,0), frame->frameSize);
|
||||
return rect.adjusted(frame->leftMargin, frame->topMargin, -frame->rightMargin, -frame->bottomMargin);
|
||||
if (d->frame) {
|
||||
QRectF rect(QPoint(0,0), d->frame->frameSize);
|
||||
return rect.adjusted(d->frame->leftMargin, d->frame->topMargin, -d->frame->rightMargin, -d->frame->bottomMargin);
|
||||
} else {
|
||||
return QRectF();
|
||||
}
|
||||
@ -499,16 +352,15 @@ QPixmap FrameSvg::alphaMask() const
|
||||
|
||||
QRegion FrameSvg::mask() const
|
||||
{
|
||||
FrameData *frame = d->frames[d->prefix];
|
||||
QString id = d->cacheId(frame, QString());
|
||||
QString id = d->cacheId(d->frame, QString());
|
||||
|
||||
QRegion* obj = frame->cachedMasks.object(id);
|
||||
QRegion* obj = d->frame->cachedMasks.object(id);
|
||||
QRegion result;
|
||||
|
||||
if (!obj) {
|
||||
obj = new QRegion(QBitmap(d->alphaMask().alphaChannel().createMaskFromColor(Qt::black)));
|
||||
result = *obj;
|
||||
frame->cachedMasks.insert(id, obj);
|
||||
d->frame->cachedMasks.insert(id, obj);
|
||||
}
|
||||
else {
|
||||
result = *obj;
|
||||
@ -532,59 +384,45 @@ bool FrameSvg::cacheAllRenderedFrames() const
|
||||
|
||||
void FrameSvg::clearCache()
|
||||
{
|
||||
FrameData *frame = d->frames[d->prefix];
|
||||
|
||||
// delete all the frames that aren't this one
|
||||
QMutableHashIterator<QString, FrameData *> it(d->frames);
|
||||
while (it.hasNext()) {
|
||||
FrameData *p = it.next().value();
|
||||
if (frame != p) {
|
||||
//TODO: should we clear from the Theme pixmap cache as well?
|
||||
if (p->deref(this)) {
|
||||
const QString key = d->cacheId(p, it.key());
|
||||
FrameSvgPrivate::s_sharedFrames[p->theme].remove(key);
|
||||
p->cachedBackground = QPixmap();
|
||||
}
|
||||
|
||||
it.remove();
|
||||
}
|
||||
if (d->frame) {
|
||||
d->frame->cachedBackground = QPixmap();
|
||||
}
|
||||
if (d->maskFrame) {
|
||||
d->maskFrame->cachedBackground = QPixmap();
|
||||
}
|
||||
}
|
||||
|
||||
QPixmap FrameSvg::framePixmap()
|
||||
{
|
||||
FrameData *frame = d->frames[d->prefix];
|
||||
if (frame->cachedBackground.isNull()) {
|
||||
d->generateBackground(frame);
|
||||
if (d->frame->cachedBackground.isNull()) {
|
||||
d->generateBackground(d->frame);
|
||||
}
|
||||
|
||||
return frame->cachedBackground;
|
||||
return d->frame->cachedBackground;
|
||||
}
|
||||
|
||||
void FrameSvg::paintFrame(QPainter *painter, const QRectF &target, const QRectF &source)
|
||||
{
|
||||
FrameData *frame = d->frames[d->prefix];
|
||||
if (frame->cachedBackground.isNull()) {
|
||||
d->generateBackground(frame);
|
||||
if (frame->cachedBackground.isNull()) {
|
||||
if (d->frame->cachedBackground.isNull()) {
|
||||
d->generateBackground(d->frame);
|
||||
if (d->frame->cachedBackground.isNull()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
painter->drawPixmap(target, frame->cachedBackground, source.isValid() ? source : target);
|
||||
painter->drawPixmap(target, d->frame->cachedBackground, source.isValid() ? source : target);
|
||||
}
|
||||
|
||||
void FrameSvg::paintFrame(QPainter *painter, const QPointF &pos)
|
||||
{
|
||||
FrameData *frame = d->frames[d->prefix];
|
||||
if (frame->cachedBackground.isNull()) {
|
||||
d->generateBackground(frame);
|
||||
if (frame->cachedBackground.isNull()) {
|
||||
if (d->frame->cachedBackground.isNull()) {
|
||||
d->generateBackground(d->frame);
|
||||
if (d->frame->cachedBackground.isNull()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
painter->drawPixmap(pos, frame->cachedBackground);
|
||||
painter->drawPixmap(pos, d->frame->cachedBackground);
|
||||
}
|
||||
|
||||
//#define DEBUG_FRAMESVG_CACHE
|
||||
@ -596,36 +434,27 @@ FrameSvgPrivate::~FrameSvgPrivate()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
QHashIterator<QString, FrameData *> it(frames);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
if (it.value()) {
|
||||
// we remove all references from this widget to the frame, and delete it if we're the
|
||||
// last user
|
||||
if (it.value()->removeRefs(q)) {
|
||||
const QString key = cacheId(it.value(), it.key());
|
||||
// we remove all references from this widget to the frame, and delete it if we're the
|
||||
// last user
|
||||
if (frame && frame->removeRefs(q)) {
|
||||
const QString key = cacheId(frame, frame->prefix);
|
||||
#ifdef DEBUG_FRAMESVG_CACHE
|
||||
#ifndef NDEBUG
|
||||
// qCDebug(LOG_PLASMA) << "2. Removing it" << key << it.value() << it.value()->refcount() << s_sharedFrames[theme()->d].contains(key);
|
||||
// qCDebug(LOG_PLASMA) << "2. Removing it" << key << frame << frame->refcount() << s_sharedFrames[theme()->d].contains(key);
|
||||
#endif
|
||||
#endif
|
||||
s_sharedFrames[it.value()->theme].remove(key);
|
||||
delete it.value();
|
||||
}
|
||||
#ifdef DEBUG_FRAMESVG_CACHE
|
||||
else {
|
||||
#ifndef NDEBUG
|
||||
// qCDebug(LOG_PLASMA) << "still shared:" << cacheId(it.value(), it.key()) << it.value() << it.value()->refcount() << it.value()->isUsed();
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
#ifndef NDEBUG
|
||||
// qCDebug(LOG_PLASMA) << "lost our value for" << it.key();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
s_sharedFrames[frame->theme].remove(key);
|
||||
delete frame;
|
||||
}
|
||||
|
||||
//same thing for maskFrame
|
||||
if (maskFrame && maskFrame->removeRefs(q)) {
|
||||
const QString key = cacheId(maskFrame, maskFrame->prefix);
|
||||
s_sharedFrames[maskFrame->theme].remove(key);
|
||||
delete maskFrame;
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG_FRAMESVG_CACHE
|
||||
QHashIterator<QString, FrameData *> it2(s_sharedFrames[theme()->d]);
|
||||
int shares = 0;
|
||||
@ -653,12 +482,12 @@ FrameSvgPrivate::~FrameSvgPrivate()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
frames.clear();
|
||||
frame = nullptr;
|
||||
maskFrame = nullptr;
|
||||
}
|
||||
|
||||
QPixmap FrameSvgPrivate::alphaMask()
|
||||
{
|
||||
FrameData *frame = frames[prefix];
|
||||
QString maskPrefix;
|
||||
|
||||
if (q->hasElement(QLatin1String("mask-") % prefix % QLatin1String("center"))) {
|
||||
@ -675,38 +504,38 @@ QPixmap FrameSvgPrivate::alphaMask()
|
||||
|
||||
return frame->cachedBackground;
|
||||
} else {
|
||||
QString oldPrefix = prefix;
|
||||
|
||||
// We are setting the prefix only temporary to generate
|
||||
// the needed mask image
|
||||
prefix = maskPrefix % oldPrefix;
|
||||
const QString maskRequestedPrefix = maskPrefix % requestedPrefix;
|
||||
maskPrefix = maskPrefix % prefix;
|
||||
|
||||
if (!frames.contains(prefix)) {
|
||||
const QString key = cacheId(frame, prefix);
|
||||
if (!maskFrame) {
|
||||
const QString key = cacheId(frame, maskPrefix);
|
||||
// see if we can find a suitable candidate in the shared frames
|
||||
// if successful, ref and insert, otherwise create a new one
|
||||
// and insert that into both the shared frames and our frames.
|
||||
FrameData *maskFrame = s_sharedFrames[q->theme()->d].value(key);
|
||||
maskFrame = s_sharedFrames[q->theme()->d].value(key);
|
||||
|
||||
if (maskFrame) {
|
||||
maskFrame->ref(q);
|
||||
} else {
|
||||
maskFrame = new FrameData(*frame, q);
|
||||
s_sharedFrames[q->theme()->d].insert(key, maskFrame);
|
||||
maskFrame->prefix = maskPrefix;
|
||||
maskFrame->requestedPrefix = maskRequestedPrefix;
|
||||
maskFrame->theme = q->theme()->d;
|
||||
s_sharedFrames[q->theme()->d].insert(key, maskFrame);
|
||||
}
|
||||
maskFrame->enabledBorders = frame->enabledBorders;
|
||||
|
||||
frames.insert(prefix, maskFrame);
|
||||
updateSizes();
|
||||
updateSizes(maskFrame);
|
||||
}
|
||||
|
||||
FrameData *maskFrame = frames[prefix];
|
||||
// maskFrame = frame;
|
||||
maskFrame->enabledBorders = frame->enabledBorders;
|
||||
if (maskFrame->cachedBackground.isNull() || maskFrame->frameSize != frameSize(frame)) {
|
||||
const QString oldKey = cacheId(maskFrame, prefix);
|
||||
const QString oldKey = cacheId(maskFrame, maskPrefix);
|
||||
maskFrame->frameSize = frameSize(frame).toSize();
|
||||
const QString newKey = cacheId(maskFrame, prefix);
|
||||
const QString newKey = cacheId(maskFrame, maskPrefix);
|
||||
if (s_sharedFrames[q->theme()->d].contains(oldKey)) {
|
||||
s_sharedFrames[q->theme()->d].remove(oldKey);
|
||||
s_sharedFrames[q->theme()->d].insert(newKey, maskFrame);
|
||||
@ -715,27 +544,27 @@ QPixmap FrameSvgPrivate::alphaMask()
|
||||
maskFrame->cachedBackground = QPixmap();
|
||||
|
||||
generateBackground(maskFrame);
|
||||
|
||||
if (maskFrame->cachedBackground.isNull()) {
|
||||
return QPixmap();
|
||||
}
|
||||
}
|
||||
|
||||
prefix = oldPrefix;
|
||||
return maskFrame->cachedBackground;
|
||||
}
|
||||
}
|
||||
|
||||
void FrameSvgPrivate::generateBackground(FrameData *frame)
|
||||
{
|
||||
if (!frame->cachedBackground.isNull() || !q->hasElementPrefix(q->prefix())) {
|
||||
if (!frame->cachedBackground.isNull() || !q->hasElementPrefix(frame->requestedPrefix)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const QString id = cacheId(frame, prefix);
|
||||
const QString id = cacheId(frame, frame->prefix);
|
||||
|
||||
bool frameCached = !frame->cachedBackground.isNull();
|
||||
bool overlayCached = false;
|
||||
const bool overlayAvailable = !prefix.startsWith(QLatin1String("mask-")) && q->hasElement(prefix % QLatin1String("overlay"));
|
||||
const bool overlayAvailable = !frame->prefix.startsWith(QLatin1String("mask-")) && q->hasElement(frame->prefix % QLatin1String("overlay"));
|
||||
QPixmap overlay;
|
||||
if (q->isUsingRenderingCache()) {
|
||||
frameCached = q->theme()->findInCache(id, frame->cachedBackground) && !frame->cachedBackground.isNull();
|
||||
@ -753,20 +582,20 @@ void FrameSvgPrivate::generateBackground(FrameData *frame)
|
||||
QSize overlaySize;
|
||||
QPoint actualOverlayPos = QPoint(0, 0);
|
||||
if (overlayAvailable && !overlayCached) {
|
||||
overlaySize = q->elementSize(prefix % QLatin1String("overlay"));
|
||||
overlaySize = q->elementSize(frame->prefix % QLatin1String("overlay"));
|
||||
|
||||
if (q->hasElement(prefix % QLatin1String("hint-overlay-pos-right"))) {
|
||||
if (q->hasElement(frame->prefix % QLatin1String("hint-overlay-pos-right"))) {
|
||||
actualOverlayPos.setX(frame->frameSize.width() - overlaySize.width());
|
||||
} else if (q->hasElement(prefix % QLatin1String("hint-overlay-pos-bottom"))) {
|
||||
} else if (q->hasElement(frame->prefix % QLatin1String("hint-overlay-pos-bottom"))) {
|
||||
actualOverlayPos.setY(frame->frameSize.height() - overlaySize.height());
|
||||
//Stretched or Tiled?
|
||||
} else if (q->hasElement(prefix % QLatin1String("hint-overlay-stretch"))) {
|
||||
} else if (q->hasElement(frame->prefix % QLatin1String("hint-overlay-stretch"))) {
|
||||
overlaySize = frameSize(frame).toSize();
|
||||
} else {
|
||||
if (q->hasElement(prefix % QLatin1String("hint-overlay-tile-horizontal"))) {
|
||||
if (q->hasElement(frame->prefix % QLatin1String("hint-overlay-tile-horizontal"))) {
|
||||
overlaySize.setWidth(frameSize(frame).width());
|
||||
}
|
||||
if (q->hasElement(prefix % QLatin1String("hint-overlay-tile-vertical"))) {
|
||||
if (q->hasElement(frame->prefix % QLatin1String("hint-overlay-tile-vertical"))) {
|
||||
overlaySize.setHeight(frameSize(frame).height());
|
||||
}
|
||||
}
|
||||
@ -775,23 +604,23 @@ void FrameSvgPrivate::generateBackground(FrameData *frame)
|
||||
QPainter overlayPainter(&overlay);
|
||||
overlayPainter.setCompositionMode(QPainter::CompositionMode_SourceIn);
|
||||
//Tiling?
|
||||
if (q->hasElement(prefix % QLatin1String("hint-overlay-tile-horizontal")) ||
|
||||
q->hasElement(prefix % QLatin1String("hint-overlay-tile-vertical"))) {
|
||||
if (q->hasElement(frame->prefix % QLatin1String("hint-overlay-tile-horizontal")) ||
|
||||
q->hasElement(frame->prefix % QLatin1String("hint-overlay-tile-vertical"))) {
|
||||
|
||||
QSize s = q->size();
|
||||
q->resize(q->elementSize(prefix % QLatin1String("overlay")));
|
||||
q->resize(q->elementSize(frame->prefix % QLatin1String("overlay")));
|
||||
|
||||
overlayPainter.drawTiledPixmap(QRect(QPoint(0, 0), overlaySize), q->pixmap(prefix % QLatin1String("overlay")));
|
||||
overlayPainter.drawTiledPixmap(QRect(QPoint(0, 0), overlaySize), q->pixmap(frame->prefix % QLatin1String("overlay")));
|
||||
q->resize(s);
|
||||
} else {
|
||||
q->paint(&overlayPainter, QRect(actualOverlayPos, overlaySize), prefix % QLatin1String("overlay"));
|
||||
q->paint(&overlayPainter, QRect(actualOverlayPos, overlaySize), frame->prefix % QLatin1String("overlay"));
|
||||
}
|
||||
|
||||
overlayPainter.end();
|
||||
}
|
||||
|
||||
if (!frameCached) {
|
||||
cacheFrame(prefix, frame->cachedBackground, overlayCached ? overlay : QPixmap());
|
||||
cacheFrame(frame->prefix, frame->cachedBackground, overlayCached ? overlay : QPixmap());
|
||||
}
|
||||
|
||||
if (!overlay.isNull()) {
|
||||
@ -832,11 +661,11 @@ void FrameSvgPrivate::generateFrameBackground(FrameData *frame)
|
||||
paintCorner(p, frame, FrameSvg::RightBorder|FrameSvg::BottomBorder, contentRect);
|
||||
|
||||
// Sides
|
||||
const int leftHeight = q->elementSize(prefix % QLatin1String("left")).height();
|
||||
const int leftHeight = q->elementSize(frame->prefix % QLatin1String("left")).height();
|
||||
paintBorder(p, frame, FrameSvg::LeftBorder, QSize(frame->leftWidth, leftHeight) * q->devicePixelRatio(), contentRect);
|
||||
paintBorder(p, frame, FrameSvg::RightBorder, QSize(frame->rightWidth, leftHeight) * q->devicePixelRatio(), contentRect);
|
||||
|
||||
const int topWidth = q->elementSize(prefix % QLatin1String("top")).width();
|
||||
const int topWidth = q->elementSize(frame->prefix % QLatin1String("top")).width();
|
||||
paintBorder(p, frame, FrameSvg::TopBorder, QSize(topWidth, frame->topHeight) * q->devicePixelRatio(), contentRect);
|
||||
paintBorder(p, frame, FrameSvg::BottomBorder, QSize(topWidth, frame->bottomHeight) * q->devicePixelRatio(), contentRect);
|
||||
p.end();
|
||||
@ -849,21 +678,89 @@ QRect FrameSvgPrivate::contentGeometry(FrameData* frame, const QSize& size) cons
|
||||
const QSize contentSize(size.width() - frame->leftWidth * q->devicePixelRatio() - frame->rightWidth * q->devicePixelRatio(),
|
||||
size.height() - frame->topHeight * q->devicePixelRatio() - frame->bottomHeight * q->devicePixelRatio());
|
||||
QRect contentRect(QPoint(0,0), contentSize);
|
||||
if (frame->enabledBorders & FrameSvg::LeftBorder && q->hasElement(prefix % QLatin1String("left"))) {
|
||||
if (frame->enabledBorders & FrameSvg::LeftBorder && q->hasElement(frame->prefix % QLatin1String("left"))) {
|
||||
contentRect.translate(frame->leftWidth * q->devicePixelRatio(), 0);
|
||||
}
|
||||
|
||||
// Corners
|
||||
if (frame->enabledBorders & FrameSvg::TopBorder && q->hasElement(prefix % QLatin1String("top"))) {
|
||||
if (frame->enabledBorders & FrameSvg::TopBorder && q->hasElement(frame->prefix % QLatin1String("top"))) {
|
||||
contentRect.translate(0, frame->topHeight * q->devicePixelRatio());
|
||||
}
|
||||
return contentRect;
|
||||
}
|
||||
|
||||
void FrameSvgPrivate::updateFrameData()
|
||||
{
|
||||
FrameData *fd = frame;
|
||||
|
||||
const QString oldKey = cacheId(fd, fd->prefix);
|
||||
|
||||
const FrameSvg::EnabledBorders oldBorders = fd->enabledBorders;
|
||||
const QSize currentSize = fd->frameSize;
|
||||
|
||||
fd->enabledBorders = enabledBorders;
|
||||
fd->frameSize = pendingFrameSize;
|
||||
|
||||
const QString newKey = cacheId(fd, prefix);
|
||||
|
||||
//reset frame to old values
|
||||
fd->enabledBorders = oldBorders;
|
||||
fd->frameSize = currentSize;
|
||||
|
||||
//FIXME: something more efficient than string comparison?
|
||||
if (oldKey == newKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
//qCDebug(LOG_PLASMA) << "looking for" << newKey;
|
||||
FrameData *newFd = FrameSvgPrivate::s_sharedFrames[q->theme()->d].value(newKey);
|
||||
if (newFd) {
|
||||
//qCDebug(LOG_PLASMA) << "FOUND IT!" << newFd->refcount;
|
||||
// we've found a math, so insert that new one and ref it ..
|
||||
newFd->ref(q);
|
||||
frame = newFd;
|
||||
|
||||
//.. then deref the old one and if it's no longer used, get rid of it
|
||||
if (fd->deref(q)) {
|
||||
//const QString oldKey = cacheId(fd, prefix);
|
||||
//qCDebug(LOG_PLASMA) << "1. Removing it" << oldKey << fd->refcount;
|
||||
FrameSvgPrivate::s_sharedFrames[fd->theme].remove(oldKey);
|
||||
|
||||
delete fd;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (fd->refcount() == 1) {
|
||||
// we're the only user of it, let's remove it from the shared keys
|
||||
// we don't want to deref it, however, as we'll still be using it
|
||||
FrameSvgPrivate::s_sharedFrames[fd->theme].remove(oldKey);
|
||||
} else {
|
||||
// others are using it, but we wish to change its size. so deref it,
|
||||
// then create a copy of it (we're automatically ref'd via the ctor),
|
||||
// then insert it into our frames.
|
||||
fd->deref(q);
|
||||
fd = new FrameData(*fd, q);
|
||||
}
|
||||
|
||||
frame = fd;
|
||||
fd->prefix = prefix;
|
||||
fd->requestedPrefix = requestedPrefix;
|
||||
//updateSizes();
|
||||
fd->enabledBorders = enabledBorders;
|
||||
fd->frameSize = pendingFrameSize;
|
||||
|
||||
// we know it isn't in s_sharedFrames due to the check above, so insert it now
|
||||
FrameSvgPrivate::s_sharedFrames[q->theme()->d].insert(newKey, fd);
|
||||
fd->theme = q->theme()->d;
|
||||
updateAndSignalSizes();
|
||||
}
|
||||
|
||||
void FrameSvgPrivate::paintCenter(QPainter& p, FrameData* frame, const QRect& contentRect, const QSize& fullSize)
|
||||
{
|
||||
if (!contentRect.isEmpty()) {
|
||||
const QString centerElementId = prefix % QLatin1String("center");
|
||||
const QString centerElementId = frame->prefix % QLatin1String("center");
|
||||
if (frame->tileCenter) {
|
||||
QSize centerTileSize = q->elementSize(centerElementId);
|
||||
QPixmap center(centerTileSize);
|
||||
@ -897,7 +794,7 @@ void FrameSvgPrivate::paintCenter(QPainter& p, FrameData* frame, const QRect& co
|
||||
|
||||
void FrameSvgPrivate::paintBorder(QPainter& p, FrameData* frame, const FrameSvg::EnabledBorders borders, const QSize& size, const QRect& contentRect) const
|
||||
{
|
||||
QString side = prefix % FrameSvgHelpers::borderToElementId(borders);
|
||||
QString side = frame->prefix % FrameSvgHelpers::borderToElementId(borders);
|
||||
if (frame->enabledBorders & borders && q->hasElement(side) && !size.isEmpty()) {
|
||||
if (frame->stretchBorders) {
|
||||
q->paint(&p, FrameSvgHelpers::sectionRect(borders, contentRect, frame->frameSize * q->devicePixelRatio()), side);
|
||||
@ -916,7 +813,7 @@ void FrameSvgPrivate::paintBorder(QPainter& p, FrameData* frame, const FrameSvg:
|
||||
|
||||
void FrameSvgPrivate::paintCorner(QPainter& p, FrameData* frame, Plasma::FrameSvg::EnabledBorders border, const QRect& contentRect) const
|
||||
{
|
||||
QString corner = prefix % FrameSvgHelpers::borderToElementId(border);
|
||||
QString corner = frame->prefix % FrameSvgHelpers::borderToElementId(border);
|
||||
if (frame->enabledBorders & border && q->hasElement(corner)) {
|
||||
q->paint(&p, FrameSvgHelpers::sectionRect(border, contentRect, frame->frameSize * q->devicePixelRatio()), corner);
|
||||
}
|
||||
@ -936,8 +833,6 @@ void FrameSvgPrivate::cacheFrame(const QString &prefixToSave, const QPixmap &bac
|
||||
}
|
||||
|
||||
//insert background
|
||||
FrameData *frame = frames.value(prefixToSave);
|
||||
|
||||
if (!frame) {
|
||||
return;
|
||||
}
|
||||
@ -954,10 +849,9 @@ void FrameSvgPrivate::cacheFrame(const QString &prefixToSave, const QPixmap &bac
|
||||
}
|
||||
}
|
||||
|
||||
void FrameSvgPrivate::updateSizes() const
|
||||
void FrameSvgPrivate::updateSizes(FrameData *frame) const
|
||||
{
|
||||
//qCDebug(LOG_PLASMA) << "!!!!!!!!!!!!!!!!!!!!!! updating sizes" << prefix;
|
||||
FrameData *frame = frames[prefix];
|
||||
Q_ASSERT(frame);
|
||||
|
||||
QSize s = q->size();
|
||||
@ -965,20 +859,20 @@ void FrameSvgPrivate::updateSizes() const
|
||||
frame->cachedBackground = QPixmap();
|
||||
|
||||
//This has the same size regardless the border is enabled or not
|
||||
frame->fixedTopHeight = q->elementSize(prefix % QLatin1String("top")).height();
|
||||
frame->fixedTopHeight = q->elementSize(frame->prefix % QLatin1String("top")).height();
|
||||
|
||||
if (q->hasElement(prefix % QLatin1String("hint-top-margin"))) {
|
||||
frame->fixedTopMargin = q->elementSize(prefix % QLatin1String("hint-top-margin")).height();
|
||||
if (q->hasElement(frame->prefix % QLatin1String("hint-top-margin"))) {
|
||||
frame->fixedTopMargin = q->elementSize(frame->prefix % QLatin1String("hint-top-margin")).height();
|
||||
} else {
|
||||
frame->fixedTopMargin = frame->fixedTopHeight;
|
||||
}
|
||||
|
||||
//The same, but its size depends from the margin being enabled
|
||||
if (frame->enabledBorders & FrameSvg::TopBorder) {
|
||||
frame->topHeight = q->elementSize(prefix % QLatin1String("top")).height();
|
||||
frame->topHeight = q->elementSize(frame->prefix % QLatin1String("top")).height();
|
||||
|
||||
if (q->hasElement(prefix % QLatin1String("hint-top-margin"))) {
|
||||
frame->topMargin = q->elementSize(prefix % QLatin1String("hint-top-margin")).height();
|
||||
if (q->hasElement(frame->prefix % QLatin1String("hint-top-margin"))) {
|
||||
frame->topMargin = q->elementSize(frame->prefix % QLatin1String("hint-top-margin")).height();
|
||||
} else {
|
||||
frame->topMargin = frame->topHeight;
|
||||
}
|
||||
@ -986,19 +880,19 @@ void FrameSvgPrivate::updateSizes() const
|
||||
frame->topMargin = frame->topHeight = 0;
|
||||
}
|
||||
|
||||
frame->fixedLeftWidth = q->elementSize(prefix % QLatin1String("left")).width();
|
||||
frame->fixedLeftWidth = q->elementSize(frame->prefix % QLatin1String("left")).width();
|
||||
|
||||
if (q->hasElement(prefix % QLatin1String("hint-left-margin"))) {
|
||||
frame->fixedLeftMargin = q->elementSize(prefix % QLatin1String("hint-left-margin")).width();
|
||||
if (q->hasElement(frame->prefix % QLatin1String("hint-left-margin"))) {
|
||||
frame->fixedLeftMargin = q->elementSize(frame->prefix % QLatin1String("hint-left-margin")).width();
|
||||
} else {
|
||||
frame->fixedLeftMargin = frame->fixedLeftWidth;
|
||||
}
|
||||
|
||||
if (frame->enabledBorders & FrameSvg::LeftBorder) {
|
||||
frame->leftWidth = q->elementSize(prefix % QLatin1String("left")).width();
|
||||
frame->leftWidth = q->elementSize(frame->prefix % QLatin1String("left")).width();
|
||||
|
||||
if (q->hasElement(prefix % QLatin1String("hint-left-margin"))) {
|
||||
frame->leftMargin = q->elementSize(prefix % QLatin1String("hint-left-margin")).width();
|
||||
if (q->hasElement(frame->prefix % QLatin1String("hint-left-margin"))) {
|
||||
frame->leftMargin = q->elementSize(frame->prefix % QLatin1String("hint-left-margin")).width();
|
||||
} else {
|
||||
frame->leftMargin = frame->leftWidth;
|
||||
}
|
||||
@ -1006,19 +900,19 @@ void FrameSvgPrivate::updateSizes() const
|
||||
frame->leftMargin = frame->leftWidth = 0;
|
||||
}
|
||||
|
||||
frame->fixedRightWidth = q->elementSize(prefix % QLatin1String("right")).width();
|
||||
frame->fixedRightWidth = q->elementSize(frame->prefix % QLatin1String("right")).width();
|
||||
|
||||
if (q->hasElement(prefix % QLatin1String("hint-right-margin"))) {
|
||||
frame->fixedRightMargin = q->elementSize(prefix % QLatin1String("hint-right-margin")).width();
|
||||
if (q->hasElement(frame->prefix % QLatin1String("hint-right-margin"))) {
|
||||
frame->fixedRightMargin = q->elementSize(frame->prefix % QLatin1String("hint-right-margin")).width();
|
||||
} else {
|
||||
frame->fixedRightMargin = frame->fixedRightWidth;
|
||||
}
|
||||
|
||||
if (frame->enabledBorders & FrameSvg::RightBorder) {
|
||||
frame->rightWidth = q->elementSize(prefix % QLatin1String("right")).width();
|
||||
frame->rightWidth = q->elementSize(frame->prefix % QLatin1String("right")).width();
|
||||
|
||||
if (q->hasElement(prefix % QLatin1String("hint-right-margin"))) {
|
||||
frame->rightMargin = q->elementSize(prefix % QLatin1String("hint-right-margin")).width();
|
||||
if (q->hasElement(frame->prefix % QLatin1String("hint-right-margin"))) {
|
||||
frame->rightMargin = q->elementSize(frame->prefix % QLatin1String("hint-right-margin")).width();
|
||||
} else {
|
||||
frame->rightMargin = frame->rightWidth;
|
||||
}
|
||||
@ -1026,19 +920,19 @@ void FrameSvgPrivate::updateSizes() const
|
||||
frame->rightMargin = frame->rightWidth = 0;
|
||||
}
|
||||
|
||||
frame->fixedBottomHeight = q->elementSize(prefix % QLatin1String("bottom")).height();
|
||||
frame->fixedBottomHeight = q->elementSize(frame->prefix % QLatin1String("bottom")).height();
|
||||
|
||||
if (q->hasElement(prefix % QLatin1String("hint-bottom-margin"))) {
|
||||
frame->fixedBottomMargin = q->elementSize(prefix % QLatin1String("hint-bottom-margin")).height();
|
||||
if (q->hasElement(frame->prefix % QLatin1String("hint-bottom-margin"))) {
|
||||
frame->fixedBottomMargin = q->elementSize(frame->prefix % QLatin1String("hint-bottom-margin")).height();
|
||||
} else {
|
||||
frame->fixedBottomMargin = frame->fixedBottomHeight;
|
||||
}
|
||||
|
||||
if (frame->enabledBorders & FrameSvg::BottomBorder) {
|
||||
frame->bottomHeight = q->elementSize(prefix % QLatin1String("bottom")).height();
|
||||
frame->bottomHeight = q->elementSize(frame->prefix % QLatin1String("bottom")).height();
|
||||
|
||||
if (q->hasElement(prefix % QLatin1String("hint-bottom-margin"))) {
|
||||
frame->bottomMargin = q->elementSize(prefix % QLatin1String("hint-bottom-margin")).height();
|
||||
if (q->hasElement(frame->prefix % QLatin1String("hint-bottom-margin"))) {
|
||||
frame->bottomMargin = q->elementSize(frame->prefix % QLatin1String("hint-bottom-margin")).height();
|
||||
} else {
|
||||
frame->bottomMargin = frame->bottomHeight;
|
||||
}
|
||||
@ -1046,14 +940,14 @@ void FrameSvgPrivate::updateSizes() const
|
||||
frame->bottomMargin = frame->bottomHeight = 0;
|
||||
}
|
||||
|
||||
frame->composeOverBorder = (q->hasElement(prefix % QLatin1String("hint-compose-over-border")) &&
|
||||
q->hasElement(QLatin1String("mask-") % prefix % QLatin1String("center")));
|
||||
frame->composeOverBorder = (q->hasElement(frame->prefix % QLatin1String("hint-compose-over-border")) &&
|
||||
q->hasElement(QLatin1String("mask-") % frame->prefix % QLatin1String("center")));
|
||||
|
||||
//since it's rectangular, topWidth and bottomWidth must be the same
|
||||
//the ones that don't have a prefix is for retrocompatibility
|
||||
frame->tileCenter = (q->hasElement(QStringLiteral("hint-tile-center")) || q->hasElement(prefix % QLatin1String("hint-tile-center")));
|
||||
frame->noBorderPadding = (q->hasElement(QStringLiteral("hint-no-border-padding")) || q->hasElement(prefix % QLatin1String("hint-no-border-padding")));
|
||||
frame->stretchBorders = (q->hasElement(QStringLiteral("hint-stretch-borders")) || q->hasElement(prefix % QLatin1String("hint-stretch-borders")));
|
||||
//the ones that don't have a frame->prefix is for retrocompatibility
|
||||
frame->tileCenter = (q->hasElement(QStringLiteral("hint-tile-center")) || q->hasElement(frame->prefix % QLatin1String("hint-tile-center")));
|
||||
frame->noBorderPadding = (q->hasElement(QStringLiteral("hint-no-border-padding")) || q->hasElement(frame->prefix % QLatin1String("hint-no-border-padding")));
|
||||
frame->stretchBorders = (q->hasElement(QStringLiteral("hint-stretch-borders")) || q->hasElement(frame->prefix % QLatin1String("hint-stretch-borders")));
|
||||
q->resize(s);
|
||||
}
|
||||
|
||||
@ -1061,19 +955,19 @@ void FrameSvgPrivate::updateNeeded()
|
||||
{
|
||||
q->setElementPrefix(requestedPrefix);
|
||||
q->clearCache();
|
||||
updateSizes();
|
||||
updateSizes(frame);
|
||||
}
|
||||
|
||||
void FrameSvgPrivate::updateAndSignalSizes()
|
||||
{
|
||||
updateSizes();
|
||||
updateSizes(frame);
|
||||
emit q->repaintNeeded();
|
||||
}
|
||||
|
||||
QSizeF FrameSvgPrivate::frameSize(FrameData *frame) const
|
||||
{
|
||||
if (!frame->frameSize.isValid()) {
|
||||
updateSizes();
|
||||
updateSizes(frame);
|
||||
frame->frameSize = q->size();
|
||||
}
|
||||
|
||||
@ -1118,6 +1012,20 @@ QString FrameSvg::actualPrefix() const
|
||||
return d->prefix;
|
||||
}
|
||||
|
||||
bool FrameSvg::isRepaintBlocked() const
|
||||
{
|
||||
return d->repaintBlocked;
|
||||
}
|
||||
|
||||
void FrameSvg::setRepaintBlocked(bool blocked)
|
||||
{
|
||||
d->repaintBlocked = blocked;
|
||||
|
||||
if (!blocked) {
|
||||
d->updateFrameData();
|
||||
}
|
||||
}
|
||||
|
||||
} // Plasma namespace
|
||||
|
||||
#include "moc_framesvg.cpp"
|
||||
|
@ -292,11 +292,28 @@ public:
|
||||
*/
|
||||
QString actualPrefix() const;
|
||||
|
||||
/**
|
||||
* @returns true if we are in a transaction of many changes at once
|
||||
* and we don't want to rebuild the generated graphics for each change yet
|
||||
* @since 5.31
|
||||
*/
|
||||
bool isRepaintBlocked() const;
|
||||
|
||||
/**
|
||||
* If we will do several changes at once in the frame properties,
|
||||
* such as prefix, enabled borders and size, in order to not regenerate
|
||||
* the graphics for each change, set this property to true, and set
|
||||
* it to false again after applying all the changes needed.
|
||||
* Note that any change will not be visible in the painted frame while this property is set to true.
|
||||
* @since 5.31
|
||||
*/
|
||||
void setRepaintBlocked(bool blocked);
|
||||
|
||||
private:
|
||||
FrameSvgPrivate *const d;
|
||||
friend class FrameData;
|
||||
|
||||
Q_PRIVATE_SLOT(d, void updateSizes())
|
||||
//Q_PRIVATE_SLOT(d, void updateSizes())
|
||||
Q_PRIVATE_SLOT(d, void updateNeeded())
|
||||
};
|
||||
|
||||
|
@ -88,6 +88,7 @@ public:
|
||||
int refcount() const;
|
||||
|
||||
QString prefix;
|
||||
QString requestedPrefix;
|
||||
FrameSvg::EnabledBorders enabledBorders;
|
||||
QPixmap cachedBackground;
|
||||
QCache<QString, QRegion> cachedMasks;
|
||||
@ -137,8 +138,12 @@ class FrameSvgPrivate
|
||||
public:
|
||||
FrameSvgPrivate(FrameSvg *psvg)
|
||||
: q(psvg),
|
||||
overlayPos(0, 0),
|
||||
frame(nullptr),
|
||||
maskFrame(nullptr),
|
||||
enabledBorders(FrameSvg::AllBorders),
|
||||
cacheAll(false),
|
||||
overlayPos(0, 0)
|
||||
repaintBlocked(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -150,7 +155,7 @@ public:
|
||||
void generateFrameBackground(FrameData *frame);
|
||||
QString cacheId(FrameData *frame, const QString &prefixToUse) const;
|
||||
void cacheFrame(const QString &prefixToSave, const QPixmap &background, const QPixmap &overlay);
|
||||
void updateSizes() const;
|
||||
void updateSizes(FrameData *frame) const;
|
||||
void updateNeeded();
|
||||
void updateAndSignalSizes();
|
||||
QSizeF frameSize(FrameData *frame) const;
|
||||
@ -158,6 +163,7 @@ public:
|
||||
void paintCorner(QPainter& p, FrameData* frame, Plasma::FrameSvg::EnabledBorders border, const QRect& output) const;
|
||||
void paintCenter(QPainter& p, FrameData* frame, const QRect& contentRect, const QSize& fullSize);
|
||||
QRect contentGeometry(FrameData* frame, const QSize& size) const;
|
||||
void updateFrameData();
|
||||
|
||||
Types::Location location;
|
||||
QString prefix;
|
||||
@ -167,12 +173,20 @@ public:
|
||||
|
||||
FrameSvg *q;
|
||||
|
||||
bool cacheAll : 1;
|
||||
QPoint overlayPos;
|
||||
|
||||
QHash<QString, FrameData *> frames;
|
||||
FrameData *frame;
|
||||
FrameData *maskFrame;
|
||||
|
||||
//those can differ from frame->enabledBorders if we are in a transition
|
||||
FrameSvg::EnabledBorders enabledBorders;
|
||||
//this can differ from frame->frameSize if we are in a transition
|
||||
QSize pendingFrameSize;
|
||||
|
||||
static QHash<ThemePrivate *, QHash<QString, FrameData *> > s_sharedFrames;
|
||||
|
||||
bool cacheAll : 1;
|
||||
bool repaintBlocked : 1;
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user