00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "kcapacitybar.h"
00022 #include <kstyle.h>
00023
00024 #include <math.h>
00025
00026 #include <QtGui/QApplication>
00027 #include <QtGui/QLabel>
00028 #include <QtGui/QStyle>
00029 #include <QtGui/QPainter>
00030 #include <QtGui/QBoxLayout>
00031 #include <QtGui/QPaintEvent>
00032 #include <QtGui/QPainterPath>
00033 #include <QtGui/QLinearGradient>
00034 #include <QtGui/QStyleOptionFrame>
00035
00036 #include <kcolorscheme.h>
00037
00038 #define ROUND_MARGIN 6
00039 #define VERTICAL_SPACING 1
00040
00041 class KCapacityBar::Private
00042 {
00043 public:
00044 Private(KCapacityBar::DrawTextMode drawTextMode)
00045 : value(0)
00046 , fillFullBlocks(true)
00047 , continuous(true)
00048 , barHeight(12)
00049 , horizontalTextAlignment(Qt::AlignCenter)
00050 , drawTextMode(drawTextMode) {}
00051
00052 ~Private() {}
00053
00054 int value;
00055 QString text;
00056 bool fillFullBlocks;
00057 bool continuous;
00058 int barHeight;
00059 Qt::Alignment horizontalTextAlignment;
00060 QStyle::ControlElement ce_capacityBar;
00061
00062 KCapacityBar::DrawTextMode drawTextMode;
00063 };
00064
00065 KCapacityBar::KCapacityBar(KCapacityBar::DrawTextMode drawTextMode, QWidget *parent)
00066 : QWidget(parent)
00067 , d(new Private(drawTextMode))
00068 {
00069 d->ce_capacityBar = KStyle::customControlElement("CE_CapacityBar", this);
00070 }
00071
00072 KCapacityBar::~KCapacityBar()
00073 {
00074 delete d;
00075 }
00076
00077 void KCapacityBar::setValue(int value)
00078 {
00079 d->value = value;
00080 update();
00081 }
00082
00083 int KCapacityBar::value() const
00084 {
00085 return d->value;
00086 }
00087
00088 void KCapacityBar::setText(const QString &text)
00089 {
00090 bool updateGeom = d->text.isEmpty() || text.isEmpty();
00091 d->text = text;
00092 if (updateGeom) {
00093 updateGeometry();
00094 }
00095 update();
00096 }
00097
00098 QString KCapacityBar::text() const
00099 {
00100 return d->text;
00101 }
00102
00103 void KCapacityBar::setFillFullBlocks(bool fillFullBlocks)
00104 {
00105 d->fillFullBlocks = fillFullBlocks;
00106 update();
00107 }
00108
00109 bool KCapacityBar::fillFullBlocks() const
00110 {
00111 return d->fillFullBlocks;
00112 }
00113
00114 void KCapacityBar::setContinuous(bool continuous)
00115 {
00116 d->continuous = continuous;
00117 update();
00118 }
00119
00120 bool KCapacityBar::continuous() const
00121 {
00122 return d->continuous;
00123 }
00124
00125 void KCapacityBar::setBarHeight(int barHeight)
00126 {
00127
00128
00129 d->barHeight = (barHeight % 2) ? barHeight + 1 : barHeight;
00130 updateGeometry();
00131 }
00132
00133 int KCapacityBar::barHeight() const
00134 {
00135 return d->barHeight;
00136 }
00137
00138 void KCapacityBar::setHorizontalTextAlignment(Qt::Alignment horizontalTextAlignment)
00139 {
00140 Qt::Alignment alignment = horizontalTextAlignment;
00141
00142
00143 alignment &= ~Qt::AlignTop;
00144 alignment &= ~Qt::AlignBottom;
00145 alignment &= ~Qt::AlignVCenter;
00146
00147 d->horizontalTextAlignment = alignment;
00148 update();
00149 }
00150
00151 Qt::Alignment KCapacityBar::horizontalTextAlignment() const
00152 {
00153 return d->horizontalTextAlignment;
00154 }
00155
00156 void KCapacityBar::setDrawTextMode(DrawTextMode mode)
00157 {
00158 d->drawTextMode = mode;
00159 update();
00160 }
00161
00162 KCapacityBar::DrawTextMode KCapacityBar::drawTextMode() const
00163 {
00164 return d->drawTextMode;
00165 }
00166
00167 void KCapacityBar::drawCapacityBar(QPainter *p, const QRect &rect) const
00168 {
00169 if (d->ce_capacityBar)
00170 {
00171 QStyleOptionProgressBar opt;
00172 opt.initFrom(this);
00173 opt.rect = rect;
00174 opt.minimum = 0;
00175 opt.maximum = 100;
00176 opt.progress = d->value;
00177 opt.text = d->text;
00178 opt.textAlignment = Qt::AlignCenter;
00179 opt.textVisible = true;
00180 style()->drawControl(d->ce_capacityBar, &opt, p, this);
00181
00182 return;
00183 }
00184
00185 p->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
00186
00187 p->save();
00188
00189 QRect drawRect(rect);
00190
00191 if (d->drawTextMode == DrawTextOutline) {
00192 drawRect.setHeight(d->barHeight);
00193 }
00194
00195 QPainterPath outline;
00196 outline.moveTo(rect.left() + ROUND_MARGIN / 4 + 1, rect.top());
00197 outline.lineTo(rect.left() + drawRect.width() - ROUND_MARGIN / 4 - 1, rect.top());
00198 outline.quadTo(rect.left() + drawRect.width() + ROUND_MARGIN / 2, drawRect.height() / 2 + rect.top(), rect.left() + drawRect.width() - ROUND_MARGIN / 4 - 1, drawRect.height() + rect.top());
00199 outline.lineTo(rect.left() + ROUND_MARGIN / 4 + 1, drawRect.height() + rect.top());
00200 outline.quadTo(-ROUND_MARGIN / 2 + rect.left(), drawRect.height() / 2 + rect.top(), rect.left() + ROUND_MARGIN / 4 + 1, rect.top());
00201 const QColor fillColor = KColorScheme::shade(palette().window().color(), KColorScheme::DarkShade);
00202 p->fillPath(outline, QColor(fillColor.red(), fillColor.green(), fillColor.blue(), 50));
00203
00204 QRadialGradient bottomGradient(QPointF(rect.width() / 2, drawRect.bottom() + 1), rect.width() / 2);
00205 bottomGradient.setColorAt(0, KColorScheme::shade(palette().window().color(), KColorScheme::LightShade));
00206 bottomGradient.setColorAt(1, Qt::transparent);
00207 p->fillRect(QRect(rect.left(), drawRect.bottom() + rect.top(), rect.width(), 1), bottomGradient);
00208
00209 p->translate(rect.left() + 2, rect.top() + 1);
00210
00211 drawRect.setWidth(drawRect.width() - 4);
00212 drawRect.setHeight(drawRect.height() - 2);
00213
00214 QPainterPath path;
00215 path.moveTo(ROUND_MARGIN / 4, 0);
00216 path.lineTo(drawRect.width() - ROUND_MARGIN / 4, 0);
00217 path.quadTo(drawRect.width() + ROUND_MARGIN / 2, drawRect.height() / 2, drawRect.width() - ROUND_MARGIN / 4, drawRect.height());
00218 path.lineTo(ROUND_MARGIN / 4, drawRect.height());
00219 path.quadTo(-ROUND_MARGIN / 2, drawRect.height() / 2, ROUND_MARGIN / 4, 0);
00220
00221 QLinearGradient linearGradient(0, 0, 0, drawRect.height());
00222 linearGradient.setColorAt(0.5, KColorScheme::shade(palette().window().color(), KColorScheme::MidShade));
00223 linearGradient.setColorAt(1, KColorScheme::shade(palette().window().color(), KColorScheme::LightShade));
00224 p->fillPath(path, linearGradient);
00225
00226 p->setBrush(Qt::NoBrush);
00227 p->setPen(Qt::NoPen);
00228
00229 if (d->continuous || !d->fillFullBlocks) {
00230 int start = (layoutDirection() == Qt::LeftToRight) ? -1
00231 : (drawRect.width() + 2) - (drawRect.width() + 2) * (d->value / 100.0);
00232
00233 p->setClipRect(QRect(start, 0, (drawRect.width() + 2) * (d->value / 100.0), drawRect.height()), Qt::IntersectClip);
00234 }
00235
00236 int left = (layoutDirection() == Qt::LeftToRight) ? 0
00237 : drawRect.width();
00238
00239 int right = (layoutDirection() == Qt::LeftToRight) ? drawRect.width()
00240 : 0;
00241
00242 int roundMargin = (layoutDirection() == Qt::LeftToRight) ? ROUND_MARGIN
00243 : -ROUND_MARGIN;
00244
00245 int spacing = 2;
00246 int verticalSpacing = VERTICAL_SPACING;
00247 int slotWidth = 6;
00248 int start = roundMargin / 4;
00249
00250 QPainterPath internalBar;
00251 internalBar.moveTo(left + roundMargin / 4, 0);
00252 internalBar.lineTo(right - roundMargin / 4, 0);
00253 internalBar.quadTo(right + roundMargin / 2, drawRect.height() / 2, right - roundMargin / 4, drawRect.height());
00254 internalBar.lineTo(left + roundMargin / 4, drawRect.height());
00255 internalBar.quadTo(left - roundMargin / 2, drawRect.height() / 2, left + roundMargin / 4, 0);
00256
00257 QLinearGradient fillInternalBar(left, 0, right, 0);
00258 fillInternalBar.setColorAt(0, KColorScheme::shade(palette().highlight().color(), KColorScheme::MidShade));
00259 fillInternalBar.setColorAt(0.5, KColorScheme::shade(palette().highlight().color(), KColorScheme::LightShade));
00260 fillInternalBar.setColorAt(1, KColorScheme::shade(palette().highlight().color(), KColorScheme::MidShade));
00261
00262 if (d->drawTextMode == KCapacityBar::DrawTextInline) {
00263 p->save();
00264 p->setOpacity(p->opacity() * 0.7);
00265 }
00266
00267 if (!d->continuous) {
00268 int numSlots = (drawRect.width() - ROUND_MARGIN - ((slotWidth + spacing) * 2)) / (slotWidth + spacing);
00269 int stopSlot = floor((numSlots + 2) * (d->value / 100.0));
00270
00271 int plusOffset = d->fillFullBlocks ? ((drawRect.width() - ROUND_MARGIN - ((slotWidth + spacing) * 2)) - (numSlots * (slotWidth + spacing))) / 2.0
00272 : 0;
00273
00274 if (!d->fillFullBlocks || stopSlot) {
00275 QPainterPath firstSlot;
00276 firstSlot.moveTo(left + roundMargin / 4, verticalSpacing);
00277 firstSlot.lineTo(left + slotWidth + roundMargin / 4 + plusOffset, verticalSpacing);
00278 firstSlot.lineTo(left + slotWidth + roundMargin / 4 + plusOffset, drawRect.height() - verticalSpacing);
00279 firstSlot.lineTo(left + roundMargin / 4, drawRect.height() - verticalSpacing);
00280 firstSlot.quadTo(left, drawRect.height() / 2, left + roundMargin / 4, verticalSpacing);
00281 p->fillPath(firstSlot, fillInternalBar);
00282 start += slotWidth + spacing + plusOffset;
00283
00284 bool stopped = false;
00285 for (int i = 0; i < numSlots + 1; i++) {
00286 if (d->fillFullBlocks && (i == (stopSlot + 1))) {
00287 stopped = true;
00288 break;
00289 }
00290 p->fillRect(QRect(rect.left() + start, rect.top() + verticalSpacing, slotWidth, drawRect.height() - verticalSpacing * 2), fillInternalBar);
00291 start += slotWidth + spacing;
00292 }
00293
00294 if (!d->fillFullBlocks || (!stopped && (stopSlot != (numSlots + 1)) && (stopSlot != numSlots))) {
00295 QPainterPath lastSlot;
00296 lastSlot.moveTo(start, verticalSpacing);
00297 lastSlot.lineTo(start, drawRect.height() - verticalSpacing);
00298 lastSlot.lineTo(start + slotWidth + plusOffset, drawRect.height() - verticalSpacing);
00299 lastSlot.quadTo(start + roundMargin, drawRect.height() / 2, start + slotWidth + plusOffset, verticalSpacing);
00300 lastSlot.lineTo(start, verticalSpacing);
00301 p->fillPath(lastSlot, fillInternalBar);
00302 }
00303 }
00304 } else {
00305 p->fillPath(internalBar, fillInternalBar);
00306 }
00307
00308 if (d->drawTextMode == KCapacityBar::DrawTextInline) {
00309 p->restore();
00310 }
00311
00312 p->save();
00313 p->setClipping(false);
00314 QRadialGradient topGradient(QPointF(rect.width() / 2, drawRect.top()), rect.width() / 2);
00315 const QColor fillTopColor = KColorScheme::shade(palette().window().color(), KColorScheme::LightShade);
00316 topGradient.setColorAt(0, QColor(fillTopColor.red(), fillTopColor.green(), fillTopColor.blue(), 127));
00317 topGradient.setColorAt(1, Qt::transparent);
00318 p->fillRect(QRect(rect.left(), rect.top() + drawRect.top(), rect.width(), 2), topGradient);
00319 p->restore();
00320
00321 p->save();
00322 p->setClipRect(QRect(-1, 0, rect.width(), drawRect.height() / 2), Qt::ReplaceClip);
00323 QLinearGradient glassGradient(0, -5, 0, drawRect.height());
00324 const QColor fillGlassColor = palette().base().color();
00325 glassGradient.setColorAt(0, QColor(fillGlassColor.red(), fillGlassColor.green(), fillGlassColor.blue(), 255));
00326 glassGradient.setColorAt(1, Qt::transparent);
00327 p->fillPath(internalBar, glassGradient);
00328 p->restore();
00329
00330 p->restore();
00331
00332 if (d->drawTextMode == KCapacityBar::DrawTextInline) {
00333 QRect rect(drawRect);
00334 rect.setHeight(rect.height() + 4);
00335 p->drawText(rect, Qt::AlignCenter, fontMetrics().elidedText(d->text, Qt::ElideRight, drawRect.width() - 2 * ROUND_MARGIN));
00336 } else {
00337 p->drawText(rect, Qt::AlignBottom | d->horizontalTextAlignment, fontMetrics().elidedText(d->text, Qt::ElideRight, drawRect.width()));
00338 }
00339 }
00340
00341 void KCapacityBar::changeEvent(QEvent *event)
00342 {
00343 if (event->type() == QEvent::StyleChange) {
00344 d->ce_capacityBar = KStyle::customControlElement("CE_CapacityBar", this);
00345 }
00346
00347 QWidget::changeEvent(event);
00348 }
00349
00350 QSize KCapacityBar::minimumSizeHint() const
00351 {
00352 int width = (d->drawTextMode == KCapacityBar::DrawTextInline) ?
00353 fontMetrics().width(d->text) + ROUND_MARGIN * 2 :
00354 fontMetrics().width(d->text);
00355
00356 int height = (d->drawTextMode == KCapacityBar::DrawTextInline) ?
00357 qMax(fontMetrics().height(), d->barHeight) :
00358 (d->text.isEmpty() ? 0 : fontMetrics().height() + VERTICAL_SPACING * 2) + d->barHeight;
00359
00360 if (height % 2) {
00361 height++;
00362 }
00363
00364 return QSize(width, height);
00365 }
00366
00367 void KCapacityBar::paintEvent(QPaintEvent *event)
00368 {
00369 QPainter p(this);
00370 drawCapacityBar(&p, event->rect());
00371 p.end();
00372 }
00373
00374 #include "kcapacitybar.moc"