diff --git a/plasma/svgpanel.cpp b/plasma/svgpanel.cpp index cefd7d0384..37034fec97 100644 --- a/plasma/svgpanel.cpp +++ b/plasma/svgpanel.cpp @@ -1,335 +1,350 @@ /* * Copyright 2008 by Aaron Seigo * Copyright 2008 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "svgpanel.h" #include #include #include namespace Plasma { class SvgPanel::Private { public: Private() : bFlags(DrawAllBorders|ContentAtOrigin), cachedBackground(0) { } ~Private() { delete cachedBackground; } BorderFlags bFlags; QPixmap *cachedBackground; Svg *background; QSizeF panelSize; //measures int topHeight; int leftWidth; int rightWidth; int bottomHeight; //size of the svg where the size of the "center" //element is contentWidth x contentHeight bool noBorderPadding : 1; bool stretchBorders : 1; }; SvgPanel::SvgPanel(const QString& imagePath, QObject* parent) : QObject(parent), d(new Private) { d->background = new Svg(imagePath, this); connect(d->background, SIGNAL(repaintNeeded()), this, SLOT(updateSizes())); updateSizes(); d->panelSize = d->background->size(); } SvgPanel::~SvgPanel() { delete d; } void SvgPanel::setFile(const QString& imagePath) { if (imagePath == d->background->file()) { return; } delete d->cachedBackground; d->cachedBackground = 0; d->background->setFile(imagePath); updateSizes(); } QString SvgPanel::file() const { return d->background->file(); } void SvgPanel::setBorderFlags(const BorderFlags flags) { if (flags == d->bFlags) { return; } delete d->cachedBackground; d->cachedBackground = 0; d->bFlags = flags; updateSizes(); } SvgPanel::BorderFlags SvgPanel::borderFlags() const { return d->bFlags; } void SvgPanel::resize(const QSizeF& size) { if (!size.isValid() || size.width() < 1 || size.height() < 1 || size == d->panelSize) { return; } delete d->cachedBackground; d->cachedBackground = 0; d->panelSize = size; updateSizes(); } qreal SvgPanel::marginSize(const Plasma::MarginEdge edge) const { if (d->noBorderPadding) { return .0; } switch (edge) { case Plasma::TopMargin: return d->topHeight; break; case Plasma::LeftMargin: return d->leftWidth; break; case Plasma::RightMargin: return d->rightWidth; break; //Plasma::BottomMargin default: return d->bottomHeight; break; } } void SvgPanel::paint(QPainter* painter, const QRectF& rect) { + bool origined = d->bFlags & ContentAtOrigin; const int topWidth = d->background->elementSize("top").width(); const int leftHeight = d->background->elementSize("left").height(); - const int topOffset = d->bFlags & ContentAtOrigin ? 0 - d->topHeight : 0; - const int leftOffset = d->bFlags & ContentAtOrigin ? 0 - d->leftWidth : 0; + const int topOffset = origined ? 0 - d->topHeight : 0; + const int leftOffset = origined ? 0 - d->leftWidth : 0; if (!d->cachedBackground) { - const int contentTop = 0; - const int contentLeft = 0; const int contentWidth = d->panelSize.width() - d->leftWidth - d->rightWidth; const int contentHeight = d->panelSize.height() - d->topHeight - d->bottomHeight; - const int rightOffset = contentWidth; - const int bottomOffset = contentHeight; + int contentTop = 0; + int contentLeft = 0; + int rightOffset = contentWidth; + int bottomOffset = contentHeight; delete d->cachedBackground; d->cachedBackground = new QPixmap(d->leftWidth + contentWidth + d->rightWidth, d->topHeight + contentHeight + d->bottomHeight); d->cachedBackground->fill(Qt::transparent); QPainter p(d->cachedBackground); + p.setCompositionMode(QPainter::CompositionMode_Source); + p.setRenderHint(QPainter::SmoothPixmapTransform); - if (d->bFlags & ContentAtOrigin) { + if (origined) { p.translate(d->leftWidth, d->topHeight); } - p.setCompositionMode(QPainter::CompositionMode_Source); - p.setRenderHint(QPainter::SmoothPixmapTransform); - //FIXME: This is a hack to fix a drawing problems with svg files where a thin transparent border is drawn around the svg image. // the transparent border around the svg seems to vary in size depending on the size of the svg and as a result increasing the // svg image by 2 all around didn't resolve the issue. For now it resizes based on the border size. //CENTER if (contentHeight > 0 && contentWidth > 0) { QSizeF scaledSize = QSizeF(d->panelSize.width() - (d->leftWidth + d->rightWidth) + d->panelSize.width()*(((qreal)(d->leftWidth + d->rightWidth)) / d->panelSize.width()), d->panelSize.height() - (d->topHeight + d->bottomHeight) + d->panelSize.height()*(((qreal)(d->topHeight + d->bottomHeight)) / d->panelSize.height())); d->background->resize(scaledSize.width(), scaledSize.height()); d->background->paint(&p, QRect(contentLeft - d->leftWidth, contentTop - d->topHeight, contentWidth + d->leftWidth*2, contentHeight + d->topHeight*2), "center"); d->background->resize(); } - //EDGES + // Corners if (d->bFlags & DrawTopBorder) { + if (!origined) { + contentTop = d->topHeight; + bottomOffset += d->topHeight; + } + if (d->bFlags & DrawLeftBorder) { d->background->paint(&p, QRect(leftOffset, topOffset, d->leftWidth, d->topHeight), "topleft"); + + if (!origined) { + contentLeft = d->leftWidth; + rightOffset = contentWidth + d->leftWidth; + } } if (d->bFlags & DrawRightBorder) { d->background->paint(&p, QRect(rightOffset, topOffset, d->rightWidth, d->topHeight), "topright"); } } if (d->bFlags & DrawBottomBorder) { if (d->bFlags & DrawLeftBorder) { d->background->paint(&p, QRect(leftOffset, bottomOffset, d->leftWidth, d->bottomHeight), "bottomleft"); + + if (!origined) { + contentLeft = d->leftWidth; + rightOffset = contentWidth + d->leftWidth; + } } if (d->bFlags & DrawRightBorder) { d->background->paint(&p, QRect(rightOffset, bottomOffset, d->rightWidth, d->bottomHeight), "bottomright"); } } - //SIDES + // Sides if (d->stretchBorders) { if (d->bFlags & DrawLeftBorder) { d->background->paint(&p, QRect(leftOffset, contentTop, d->leftWidth, contentHeight), "left"); } if (d->bFlags & DrawRightBorder) { d->background->paint(&p, QRect(rightOffset, contentTop, d->rightWidth, contentHeight), "right"); } if (d->bFlags & DrawTopBorder) { d->background->paint(&p, QRect(contentLeft, topOffset, contentWidth, d->topHeight), "top"); } if (d->bFlags & DrawBottomBorder) { d->background->paint(&p, QRect(contentLeft, bottomOffset, contentWidth, d->bottomHeight), "bottom"); } } else { if (d->bFlags & DrawLeftBorder) { QPixmap left(d->leftWidth, leftHeight); left.fill(Qt::transparent); { QPainter sidePainter(&left); sidePainter.setCompositionMode(QPainter::CompositionMode_Source); d->background->paint(&sidePainter, QPoint(0, 0), "left"); } p.drawTiledPixmap(QRect(leftOffset, contentTop, d->leftWidth, contentHeight), left); } if (d->bFlags & DrawRightBorder) { QPixmap right(d->rightWidth, leftHeight); right.fill(Qt::transparent); { QPainter sidePainter(&right); sidePainter.setCompositionMode(QPainter::CompositionMode_Source); d->background->paint(&sidePainter, QPoint(0, 0), "right"); } p.drawTiledPixmap(QRect(rightOffset, contentTop, d->rightWidth, contentHeight), right); } if (d->bFlags & DrawTopBorder) { QPixmap top(topWidth, d->topHeight); top.fill(Qt::transparent); { QPainter sidePainter(&top); sidePainter.setCompositionMode(QPainter::CompositionMode_Source); d->background->paint(&sidePainter, QPoint(0, 0), "top"); } p.drawTiledPixmap(QRect(contentLeft, topOffset, contentWidth, d->topHeight), top); } if (d->bFlags & DrawBottomBorder) { QPixmap bottom(topWidth, d->bottomHeight); bottom.fill(Qt::transparent); { QPainter sidePainter(&bottom); sidePainter.setCompositionMode(QPainter::CompositionMode_Source); d->background->paint(&sidePainter, QPoint(0, 0), "bottom"); } p.drawTiledPixmap(QRect(contentLeft, bottomOffset, contentWidth, d->bottomHeight), bottom); } } // re-enable this once Qt's svg rendering is un-buggered //resize(contentWidth, contentHeight); //paint(&p, QRect(contentLeft, contentTop, contentWidth, contentHeight), "center"); } //p2->drawPixmap(paintRect, *cachedBackground, paintRect.translated(-leftOffset,-topOffset)); painter->drawPixmap(rect, *d->cachedBackground, rect.translated(-leftOffset, -topOffset)); } void SvgPanel::updateSizes() { d->background->resize(); if (d->bFlags & DrawTopBorder) { d->topHeight = d->background->elementSize("top").height(); } else { d->topHeight = 0; } if (d->bFlags & DrawLeftBorder) { d->leftWidth = d->background->elementSize("left").width(); } else { d->leftWidth = 0; } if (d->bFlags & DrawRightBorder) { d->rightWidth = d->background->elementSize("right").width(); } else { d->rightWidth = 0; } if (d->bFlags & DrawBottomBorder) { d->bottomHeight = d->background->elementSize("bottom").height(); } else { d->bottomHeight = 0; } //since it's rectangular, topWidth and bottomWidth must be the same d->noBorderPadding = d->background->elementExists("hint-no-border-padding"); d->stretchBorders = d->background->elementExists("hint-stretch-borders"); + emit repaintNeeded(); } - } // Plasma namespace #include "svgpanel.moc" diff --git a/plasma/svgpanel.h b/plasma/svgpanel.h index d5f5f6c8c2..674b290f79 100644 --- a/plasma/svgpanel.h +++ b/plasma/svgpanel.h @@ -1,133 +1,136 @@ /* * Copyright 2008 by Aaron Seigo * Copyright 2008 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef PLASMA_SVGPANEL_H #define PLASMA_SVGPANEL_H #include #include #include #include #include class QPainter; class QPoint; class QPointF; class QRect; class QRectF; class QSize; class QSizeF; class QMatrix; namespace Plasma { class PLASMA_EXPORT SvgPanel : public QObject { Q_OBJECT public: /** * These flags represents what borders should be drawn */ enum BorderFlag { DrawTopBorder = 1, DrawBottomBorder = 2, DrawLeftBorder = 4, DrawRightBorder = 8, ContentAtOrigin = 16, DrawAllBorders = DrawTopBorder | DrawBottomBorder | DrawLeftBorder | DrawRightBorder }; Q_DECLARE_FLAGS(BorderFlags, BorderFlag) /** * Constructs a new SvgPanel that paints the proper named subelements * as borders * * The size is initialized to be the SVG's native size. * * @arg imagePath the image to show. If a relative path is passed, then * Plasma::Theme is used to load the SVG. * @arg parent options QObject to parent this to * * @related Plasma::Theme */ explicit SvgPanel(const QString& imagePath = QString(), QObject* parent = 0); ~SvgPanel(); /** * Loads a new Svg * @arg imagePath the new file */ void setFile(const QString& imagePath); /** * Convenience method to get the svg filepath and name of svg. * @return the svg's filepath including name of the svg. */ QString file() const; /** * Sets what borders should be painted * @arg flags borders we want to paint */ void setBorderFlags(const BorderFlags flags); /** * Convenience method to get the border flags * @return what borders are painted */ BorderFlags borderFlags() const; /** * Resize the panel maintaining the same border size * @arg size the new size of the panel */ void resize(const QSizeF& size); /** * Returns the margin size given the margin edge we want * @arg edge the margin edge we want, top, bottom, left or right * @return the margin size */ qreal marginSize(const Plasma::MarginEdge edge) const; /** * Paints the loaded SVG with the elements that represents the border * @arg painter the QPainter to use * @arg rect the exposed rect to draw into */ Q_INVOKABLE void paint(QPainter* painter, const QRectF& rect); + Q_SIGNALS: + void repaintNeeded(); + private slots: //update sizes of the svg elements void updateSizes(); private: class Private; Private * const d; }; } // Plasma namespace Q_DECLARE_OPERATORS_FOR_FLAGS(Plasma::SvgPanel::BorderFlags) #endif // multiple inclusion guard