aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--demos/widgetsgallery/progressbarpage.cpp4
-rw-r--r--src/views/mprogressindicatorbarview.cpp235
-rw-r--r--src/views/mprogressindicatorbarview_p.h31
-rw-r--r--src/views/style/mprogressindicatorstyle.h18
4 files changed, 276 insertions, 12 deletions
diff --git a/demos/widgetsgallery/progressbarpage.cpp b/demos/widgetsgallery/progressbarpage.cpp
index 347914df..de34b1e2 100644
--- a/demos/widgetsgallery/progressbarpage.cpp
+++ b/demos/widgetsgallery/progressbarpage.cpp
@@ -55,7 +55,7 @@ void ProgressBarPage::createContent()
bar1 = new MProgressIndicator(centralWidget(), MProgressIndicator::barType);
// Since range's type is int, we want a fairly large number here, to get a smooth animation
- bar1->setRange(0, 99999);
+ bar1->setRange(0, 400);
bar1->setValue(0);
containerPolicy->addItem(bar1);
@@ -72,7 +72,7 @@ void ProgressBarPage::createContent()
animation->setLoopCount(-1);
// start and end value should match bar1's range
animation->setStartValue(0);
- animation->setEndValue(99999);
+ animation->setEndValue(400);
// 10 ms to fill the bar
animation->setDuration(10000);
animation->start();
diff --git a/src/views/mprogressindicatorbarview.cpp b/src/views/mprogressindicatorbarview.cpp
index 5e4d5fdb..05a4006d 100644
--- a/src/views/mprogressindicatorbarview.cpp
+++ b/src/views/mprogressindicatorbarview.cpp
@@ -40,11 +40,15 @@ MProgressIndicatorBarViewPrivate::MProgressIndicatorBarViewPrivate()
animation(0),
width(0)
{
+ backgroundPainter = new QPainter;
+ scalableBarImage = new MScalableImage;
}
MProgressIndicatorBarViewPrivate::~MProgressIndicatorBarViewPrivate()
{
+ delete backgroundPainter;
+ delete scalableBarImage;
}
void MProgressIndicatorBarViewPrivate::setPosition(qreal pos)
@@ -73,6 +77,57 @@ void MProgressIndicatorBarViewPrivate::animate(bool animate)
}
}
+void MProgressIndicatorBarViewPrivate::createMaskOnGeometry()
+{
+ Q_Q(MProgressIndicatorBarView);
+
+ const int height = q->rect().height();
+ const QPoint topLeft(0,0);
+ QPainter p;
+
+ /*
+ leftEnd barMask rightEnd
+ +-----+-------+---+--------+-----+
+ | | |///| | |
+ | | |///| | |
+ | | |///| | |
+ +-----+-------+---+--------+-----+
+ */
+
+ QPixmap canvas(q->rect().width(),height);
+ canvas.fill(Qt::transparent);
+
+ leftEndMask = QPixmap(leftWidth,height);
+ leftEndMask.fill(Qt::transparent);
+
+ rightEndMask = QPixmap(rightWidth,height);
+ rightEndMask.fill(Qt::transparent);
+
+ // first scale up and draw the entire mask image
+ p.begin( &canvas );
+ q->style()->maskImage()->draw(q->rect().toRect(), &p);
+ p.end();
+
+ // then cut out left end
+ p.begin(&leftEndMask);
+ p.drawPixmap( QRect(topLeft,leftEndMask.size()), canvas, QRect(topLeft,QSize(leftWidth,height)) );
+ p.end();
+
+ // and cut out right end
+ p.begin(&rightEndMask);
+ p.drawPixmap( QRect(topLeft,rightEndMask.size()), canvas, QRect(QPoint(q->rect().toRect().width()-rightWidth,0),QSize(rightWidth,height)) );
+ p.end();
+
+ barMask = QPixmap( QSize(q->style()->fillImage()->pixmap()->width(),height) );
+ barMask.fill(Qt::transparent);
+
+ // alpha blending is more correct in the middle
+ const QPoint centerTop( q->rect().center().x() - barMask.size().width()/2, q->rect().y() );
+ p.begin(&barMask);
+ p.drawPixmap( QRect(QPoint(0,0),barMask.size()), canvas, QRect(centerTop, barMask.size()) );
+ p.end();
+}
+
MProgressIndicatorBarView::MProgressIndicatorBarView(MProgressIndicator *controller) :
MWidgetView(controller),
d_ptr(new MProgressIndicatorBarViewPrivate)
@@ -102,12 +157,46 @@ MProgressIndicatorBarView::~MProgressIndicatorBarView()
delete d_ptr;
}
+void MProgressIndicatorBarViewPrivate::updateBarPosition()
+{
+ Q_Q(MProgressIndicatorBarView);
+
+ bool reverse = qApp->isRightToLeft();
+ QRect r(q->rect().toRect());
+ const qreal offset = (qreal)(q->model()->value() - q->model()->minimum()) / (qreal)(q->model()->maximum() - q->model()->minimum());
+
+ if (offset > 0) {
+ if (!reverse)
+ r.moveRight(offset * r.width());
+ else
+ r.moveLeft((1 - offset) * r.width());
+
+ if (q->style()->fillImage())
+ backgroundPainter->drawPixmap( r,barBody );
+ }
+}
+
void MProgressIndicatorBarView::updateData(const QList<const char *>& modifications)
{
MWidgetView::updateData(modifications);
Q_D(MProgressIndicatorBarView);
+ if(d->barBody.isNull()) {
+ d->figureOutSizes();
+ d->createMaskOnGeometry();
+ d->resetBarComposition();
+ d->setupBarBody();
+ }
+
+ if( d->previousValue > model()->value() ) {
+ d->resetBarComposition();
+ }
+
+ d->previousValue = model()->value();
+
+ d->updateBarPosition();
+
foreach(const char * member, modifications) {
if (member == MProgressIndicatorModel::UnknownDuration) {
if (model()->unknownDuration()) {
@@ -132,6 +221,122 @@ void MProgressIndicatorBarView::setupModel()
update();
}
+void MProgressIndicatorBarViewPrivate::figureOutSizes()
+{
+ Q_Q(MProgressIndicatorBarView);
+
+ q->style()->maskImage()->borders(&leftWidth,&rightWidth,&top,&bottom);
+
+ rightEndRect = QRectF( QPointF(0.0,0.0), QSizeF(
+ rightWidth,
+ q->rect().height() ) );
+
+ leftEndRect = QRectF( QPointF(0.0,0.0), QSizeF(
+ leftWidth,
+ q->rect().height() ) );
+}
+
+void MProgressIndicatorBarViewPrivate::setupBarBody()
+{
+ Q_Q(MProgressIndicatorBarView);
+
+ barBody = QPixmap( q->rect().size().toSize() );
+ barBody.fill(Qt::transparent);
+
+ q->style()->maskImage()->borders(&leftWidth,&rightWidth,&top,&bottom);
+
+ // draw the mask
+ QPainter painter(&barBody);
+ painter.drawPixmap(q->rect().toRect(), barMask);
+ painter.end();
+
+ // paint the filling onto the mask, in slices
+ painter.begin(&barBody);
+ painter.setCompositionMode(QPainter::CompositionMode_SourceIn);
+ const QRect sourceRect( QPoint(0,0), q->style()->fillImage()->pixmap()->size() );
+ const int step = sourceRect.width();
+ for(int i=0;i<q->rect().width();i+=step) {
+ const QRectF nextRect(i,0,step,q->rect().height());
+ if(q->style()->fillImageTiled())
+ painter.drawTiledPixmap( nextRect, *q->style()->fillImage()->pixmap());
+ else // stretched
+ painter.drawPixmap( nextRect, *q->style()->fillImage()->pixmap(), sourceRect);
+ }
+ painter.end();
+
+ // draw the right end
+ rightEndImage = QImage( rightEndRect.size().toSize(), QImage::Format_ARGB32 );
+qCritical() << q->style()->fillImageTiled();
+ painter.begin(&rightEndImage);
+ if(q->style()->fillImageTiled())
+ painter.drawTiledPixmap( rightEndRect.toRect(), *q->style()->fillImage()->pixmap() );
+ else // stretched
+ q->style()->fillImage()->draw( rightEndRect.toRect(), &painter );
+ painter.end();
+
+ painter.begin(&rightEndImage);
+ painter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
+ painter.drawPixmap( rightEndRect.toRect(), rightEndMask );
+ painter.end();
+
+ rightEnd = QPixmap::fromImage( rightEndImage );
+
+ // draw the left end
+ leftEndImage = QImage( leftEndRect.size().toSize(), QImage::Format_ARGB32 );
+
+ painter.begin(&leftEndImage);
+ q->style()->fillImage()->draw( leftEndRect.toRect(), &painter );
+ painter.end();
+
+ painter.begin(&leftEndImage);
+ painter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
+ painter.drawPixmap( leftEndRect.toRect(), leftEndMask );
+ painter.end();
+
+ leftEnd = QPixmap::fromImage(leftEndImage);
+}
+
+void MProgressIndicatorBarViewPrivate::compositeBarForUnknownDuration()
+{
+ Q_Q(MProgressIndicatorBarView);
+
+ QPainter painter;
+
+ const qreal bodyWidth = 100.0;
+ QRectF udLeftEndRect( QPointF(0,0), leftEndRect.size() );
+ QRectF udBodyRect( udLeftEndRect.topRight(), QSizeF(bodyWidth, q->rect().height()) );
+ QRectF udRightEndRect( udBodyRect.topRight(), rightEndRect.size() );
+
+ QRectF udBarRect( 0,0, leftWidth + bodyWidth + rightWidth, q->rect().height() );
+
+ QPixmap* activeImagePixmap = new QPixmap( udBarRect.size().toSize() );
+ activeImagePixmap->fill(Qt::transparent);
+
+ painter.begin(activeImagePixmap);
+ painter.drawImage( udLeftEndRect, leftEndImage );
+ painter.drawPixmap( udBodyRect.toRect(), barBody );
+ painter.drawImage( udRightEndRect, rightEndImage );
+ painter.end();
+
+ scalableBarImage = new MScalableImage( activeImagePixmap, leftWidth, rightWidth, top, bottom );
+}
+
+void MProgressIndicatorBarViewPrivate::resetBarComposition()
+{
+ Q_Q(MProgressIndicatorBarView);
+
+ if( backgroundPainter->isActive() )
+ backgroundPainter->end();
+
+ barComposition = QPixmap(q->rect().size().toSize());
+ barComposition.fill(Qt::transparent);
+
+ if(backgroundPainter->begin(&barComposition)) {
+ q->style()->inactiveImage()->draw( q->rect().toRect(), backgroundPainter );
+ backgroundPainter->setCompositionMode( QPainter::CompositionMode_SourceAtop );
+ }
+}
+
void MProgressIndicatorBarView::drawContents(QPainter *painter, const QStyleOptionGraphicsItem *option) const
{
Q_UNUSED(option);
@@ -152,15 +357,17 @@ void MProgressIndicatorBarView::drawContents(QPainter *painter, const QStyleOpti
qreal offset = (qreal)(model()->value() - model()->minimum()) / (qreal)(model()->maximum() - model()->minimum());
if (offset > 0) {
if (!reverse) {
- r.setRight(offset * r.width());
- if (r.width() < minimumScalableWidth)
- r.setRight(r.left() + minimumScalableWidth);
+ r.moveRight(offset * r.width());
} else {
- r.setLeft((1.0 - offset) * r.width());
- if (r.width() < minimumScalableWidth)
- r.setLeft(r.right() - minimumScalableWidth);
+ r.moveLeft((1 - offset) * r.width());
+ }
+
+ if (style()->fillImage()) {
+ painter->drawPixmap( 0,0, d->barComposition );
+ const int shift_left_to_avoid_flickering = 0;
+ const QRect rightEndRect(QPoint(r.topRight().x()-shift_left_to_avoid_flickering,0),d->rightEndRect.size().toSize());
+ painter->drawPixmap( rightEndRect, d->rightEnd );
}
- style()->activeImage()->draw(r, painter);
}
} else {
qreal distance = d->position * (qreal) r.width();
@@ -179,9 +386,9 @@ void MProgressIndicatorBarView::drawContents(QPainter *painter, const QStyleOpti
}
if (r.width() >= minimumScalableWidth)
- style()->activeImage()->draw(r, painter);
+ d->scalableBarImage->draw( r, painter );
if (r2.width() >= minimumScalableWidth)
- style()->activeImage()->draw(r2, painter);
+ d->scalableBarImage->draw( r2, painter );
} else {
// one draw call
@@ -196,7 +403,7 @@ void MProgressIndicatorBarView::drawContents(QPainter *painter, const QStyleOpti
if (r.width() < minimumScalableWidth)
r.setLeft(r.right() - minimumScalableWidth);
}
- style()->activeImage()->draw(r, painter);
+ d->scalableBarImage->draw( r, painter );
}
}
}
@@ -235,6 +442,14 @@ void MProgressIndicatorBarView::resizeEvent(QGraphicsSceneResizeEvent *event)
d->width = rect().width();
d->animation->setDuration(d->width * 1000 / style()->speed());
}
+
+ if(model()->unknownDuration()) {
+ d->figureOutSizes();
+ d->createMaskOnGeometry();
+ d->resetBarComposition();
+ d->setupBarBody();
+ d->compositeBarForUnknownDuration();
+ }
}
// bind controller widget and view widget together by registration macro
diff --git a/src/views/mprogressindicatorbarview_p.h b/src/views/mprogressindicatorbarview_p.h
index 6739ab5a..cf0e8e13 100644
--- a/src/views/mprogressindicatorbarview_p.h
+++ b/src/views/mprogressindicatorbarview_p.h
@@ -33,6 +33,15 @@ class MProgressIndicatorBarViewPrivate : public QObject
Q_OBJECT
Q_DECLARE_PUBLIC(MProgressIndicatorBarView)
+ QImage leftEndImage;
+ QImage rightEndImage;
+ QPixmap rightEndMask;
+ QPixmap leftEndMask;
+
+ QPixmap barMask;
+
+ int leftWidth, rightWidth, top, bottom;
+
protected:
MProgressIndicatorBarView *q_ptr;
@@ -40,6 +49,14 @@ public:
MProgressIndicatorBarViewPrivate();
~MProgressIndicatorBarViewPrivate();
+ void resetBarComposition();
+ void setupBarBody();
+ void updateBarPosition();
+ void createMaskOnGeometry();
+
+ void compositeBarForUnknownDuration();
+ void figureOutSizes();
+
Q_PROPERTY(qreal position READ getPosition WRITE setPosition)
qreal getPosition();
@@ -56,6 +73,20 @@ public:
QPropertyAnimation *animation;
int width;
+ QPixmap barBody;
+
+ QPixmap rightEnd;
+ QPixmap leftEnd;
+
+ QRectF rightEndRect;
+ QRectF leftEndRect;
+
+ QPixmap barComposition;
+ QPainter* backgroundPainter;
+ int previousValue;
+
+ MScalableImage* scalableBarImage;
+
#ifdef M_UNIT_TEST
M_UNIT_TEST;
#endif
diff --git a/src/views/style/mprogressindicatorstyle.h b/src/views/style/mprogressindicatorstyle.h
index 0c34a1ec..84dd0b1a 100644
--- a/src/views/style/mprogressindicatorstyle.h
+++ b/src/views/style/mprogressindicatorstyle.h
@@ -69,6 +69,24 @@ class M_EXPORT MProgressIndicatorStyle : public MWidgetStyle
\brief Distance between circle elements as a multiplier to element size.
*/
M_STYLE_ATTRIBUTE(qreal, elementDistance, ElementDistance)
+
+ /*!
+ \property MProgressIndicatorCandybarStyle::fillImage
+ \brief Mask for the progress image.
+ */
+ M_STYLE_PTR_ATTRIBUTE(MScalableImage*, fillImage, FillImage)
+
+ /*!
+ \property MProgressIndicator::maskImage
+ \brief mask of the progress image.
+ */
+ M_STYLE_PTR_ATTRIBUTE(MScalableImage*, maskImage, MaskImage)
+
+ /*!
+ \property MProgressIndicator::fillImageTiled
+ \brief stretched or tiled.
+ */
+ M_STYLE_ATTRIBUTE(bool, fillImageTiled, FillImageTiled)
};
/*!