* Paint a styled progressbar instead of our home-brown one.
[kdenetwork.git] / kget / ui / transfersviewdelegate.cpp
blobb79aa3307411bf357ebf41a789f62c0a21723af3
1 /* This file is part of the KDE project
3 Copyright (C) 2006 Dario Massarin <nekkar@libero.it>
4 Adapt the kshortcutdialog use of the kextendableitemdelegate in kdelibs/kdeui/dialogs/
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public
8 License as published by the Free Software Foundation; version 2
9 of the License.
12 #include "ui/transfersviewdelegate.h"
14 #include "transferdetails.h"
15 #include "core/kget.h"
16 #include "core/transferhandler.h"
17 #include "core/transfergrouphandler.h"
18 #include "core/transfertreemodel.h"
19 #include "core/transfertreeselectionmodel.h"
20 #include "settings.h"
22 #include <kdebug.h>
23 #include <klocale.h>
24 #include <kmenu.h>
25 #include <kicon.h>
27 #include <QApplication>
28 #include <QPainter>
29 #include <QMouseEvent>
30 #include <QModelIndex>
31 #include <QButtonGroup>
32 #include <QHBoxLayout>
33 #include <QGroupBox>
34 #include <QLabel>
35 #include <QAbstractItemView>
37 GroupStatusButton::GroupStatusButton(const QModelIndex & index, QWidget * parent)
38 : QToolButton(parent),
39 m_index(index),
40 m_timerId(-1),
41 m_iconSize(22),
42 m_gradientId(0)
46 void GroupStatusButton::checkStateSet()
48 // kDebug(5001) << "GroupStatusButton::checkStateSet";
50 QToolButton::checkStateSet();
52 if(isChecked())
54 if(m_status == None)
55 m_gradientId = 0.7;
56 m_status = Selecting;
58 else
60 if(m_status == None)
61 m_gradientId = 1;
62 m_status = Deselecting;
65 setMouseTracking(!isChecked());
67 if(m_timerId == -1)
68 m_timerId = startTimer(25);
71 void GroupStatusButton::enterEvent(QEvent * event)
73 Q_UNUSED(event);
74 if(!isChecked())
76 m_status = Blinking;
78 if(m_timerId == -1)
80 m_timerId = startTimer(25);
82 if(m_status == !BlinkingExiting)
83 m_gradientId = 1;
88 void GroupStatusButton::leaveEvent(QEvent * event)
90 Q_UNUSED(event);
91 if(m_status == Blinking)
92 m_status = BlinkingExiting;
95 void GroupStatusButton::paintEvent(QPaintEvent * event)
97 Q_UNUSED(event);
99 QPainter p(this);
101 int offset = (event->rect().width() - m_iconSize) / 2;
103 if(m_gradientId == 0)
104 m_gradientId = isChecked() ? 1 : 0.7;
106 QRadialGradient gradient(event->rect().topLeft() + QPoint(event->rect().width() / 2, event->rect().height() / 2), event->rect().width() / 2);
108 QPen pen;
110 if(KGet::selectionModel()->isSelected(m_index))
112 gradient.setColorAt(0, palette().color(QPalette::AlternateBase));
113 gradient.setColorAt(m_gradientId, palette().color(QPalette::Highlight));
114 gradient.setColorAt(1, palette().color(QPalette::Highlight));
115 pen.setColor(palette().color(QPalette::AlternateBase));
117 else
119 gradient.setColorAt(0, palette().color(QPalette::Highlight));
120 gradient.setColorAt(m_gradientId, Qt::transparent);
121 gradient.setColorAt(1, Qt::transparent);
122 pen.setColor(palette().color(QPalette::Highlight));
125 QRect r = event->rect();
126 r.adjust(0,0,0,-1);
128 p.fillRect(r, gradient);
130 p.setRenderHint(QPainter::Antialiasing);
132 if(isChecked())
134 pen.setWidth(1);
135 p.setPen(pen);
136 p.drawEllipse(event->rect().x()+5, event->rect().y()+5, event->rect().width()-10, event->rect().width()-10);
139 p.drawPixmap(event->rect().topLeft() + QPoint(offset, offset),
140 icon().pixmap(m_iconSize, isChecked() || m_status == Blinking ?
141 QIcon::Normal : QIcon::Disabled));
144 void GroupStatusButton::timerEvent(QTimerEvent *event)
146 Q_UNUSED(event);
148 if(m_status == Selecting)
150 m_gradientId+=0.05;
152 if(m_gradientId >= 1)
154 m_status = None;
155 m_gradientId = 1;
156 killTimer(m_timerId);
157 m_timerId = -1;
160 else if(m_status == Deselecting)
162 m_gradientId-=0.05;
164 if(m_gradientId <= 0.7)
166 m_status = None;
167 m_gradientId = 0.7;
168 killTimer(m_timerId);
169 m_timerId = -1;
172 else if(m_status == Blinking)
174 m_gradientId-=0.01;
176 if(m_gradientId <= 0.7)
178 m_gradientId = 1;
181 else if(m_status == BlinkingExiting)
183 m_gradientId-=0.01;
185 if(m_gradientId <= 0.7)
187 m_status = None;
188 m_gradientId = 0.7;
189 killTimer(m_timerId);
190 m_timerId = -1;
194 update();
197 GroupStatusEditor::GroupStatusEditor(const QModelIndex & index, const TransfersViewDelegate * delegate, QWidget * parent)
198 : QWidget(parent),
199 m_delegate(delegate),
200 m_index(index)
202 setMinimumWidth(80);
204 m_layout = new QHBoxLayout();
205 m_layout->addStretch();
206 setLayout(m_layout);
208 m_btGroup = new QButtonGroup(this);
209 m_btGroup->setExclusive(true);
211 m_startBt = new GroupStatusButton(m_index, this);
212 m_startBt->setCheckable(true);
213 m_startBt->setAutoRaise(true);
214 m_startBt->setIcon(KIcon("media-playback-start"));
215 m_startBt->setFixedSize(36, 36);
216 m_startBt->setIconSize(QSize(22, 22));
217 m_startBt->installEventFilter(const_cast<TransfersViewDelegate *>(delegate));
218 m_layout->addWidget(m_startBt);
219 m_btGroup->addButton(m_startBt);
221 m_stopBt = new GroupStatusButton(m_index, this);
222 m_stopBt->setCheckable(true);
223 m_stopBt->setAutoRaise(true);
224 m_stopBt->setIcon(KIcon("media-playback-pause"));
225 m_stopBt->setFixedSize(36, 36);
226 m_stopBt->setIconSize(QSize(22, 22));
227 m_stopBt->installEventFilter(const_cast<TransfersViewDelegate *>(delegate));
228 m_layout->addWidget(m_stopBt);
229 m_btGroup->addButton(m_stopBt);
231 m_stopBt->setChecked(true);
233 m_layout->addStretch();
234 m_layout->setMargin(1);
236 connect(m_startBt, SIGNAL(toggled(bool)),
237 this, SLOT(slotStatusChanged(bool)));
240 void GroupStatusEditor::setRunning(bool running)
242 if(running)
243 m_startBt->setChecked(true);
244 else
245 m_stopBt->setChecked(true);
248 bool GroupStatusEditor::isRunning()
250 return m_startBt->isChecked();
253 void GroupStatusEditor::slotStatusChanged(bool running)
255 Q_UNUSED(running);
257 emit const_cast<TransfersViewDelegate *>(m_delegate)->commitData(this);
260 TransfersViewDelegate::TransfersViewDelegate(QAbstractItemView *parent)
261 : KExtendableItemDelegate(parent), m_popup(0)
263 Q_ASSERT(qobject_cast<QAbstractItemView *>(parent));
264 setExtendIcon(SmallIcon("arrow-right"));
265 setContractIcon(SmallIcon("arrow-down"));
266 connect(parent, SIGNAL(clicked(QModelIndex)), this, SLOT(itemActivated(QModelIndex)));
269 void TransfersViewDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const
271 const TransferTreeModel * transferTreeModel = static_cast<const TransferTreeModel *>(index.model());
273 if(transferTreeModel->isTransferGroup(index))
275 painter->save();
277 if (option.state & QStyle::State_Selected)
280 else
282 QLinearGradient gradient(option.rect.x(), option.rect.y(),
283 option.rect.x(), (option.rect.y() + option.rect.height()));
284 gradient.setColorAt(0, QApplication::palette().color(QPalette::Base));
285 gradient.setColorAt(0.5, QApplication::palette().color(QPalette::AlternateBase).darker(110));
286 gradient.setColorAt(1, QApplication::palette().color(QPalette::Base));
288 painter->fillRect(option.rect, gradient);
291 QItemDelegate::paint(painter, option, index);
293 painter->restore();
295 else {
296 if (KGet::selectionModel()->isSelected(index))
297 painter->fillRect(option.rect, QApplication::palette().color(option.state & QStyle::State_Active ?
298 QPalette::Active : QPalette::Inactive,
299 QPalette::Highlight));
301 KExtendableItemDelegate::paint(painter, option, index);
303 if (index.column() == 3 && !isExtended(index)) { // the percent column
304 TransferHandler *transferHandler = static_cast<TransferHandler *>(index.internalPointer());
306 // following progressbar code has mostly been taken from Qt4 examples/network/torrent/mainview.cpp
307 // Set up a QStyleOptionProgressBar to precisely mimic the
308 // environment of a progress bar.
309 QStyleOptionProgressBar progressBarOption;
310 progressBarOption.state = QStyle::State_Enabled;
311 progressBarOption.direction = QApplication::layoutDirection();
312 progressBarOption.rect = option.rect;
313 progressBarOption.fontMetrics = QApplication::fontMetrics();
314 progressBarOption.minimum = 0;
315 progressBarOption.maximum = 100;
316 progressBarOption.textAlignment = Qt::AlignCenter;
317 progressBarOption.textVisible = true;
319 // Set the progress and text values of the style option.
320 int progress = transferHandler->percent();
321 if (progress >= 0 && progress <= 100) {
322 progressBarOption.progress = progress;
323 progressBarOption.text = QString().sprintf("%d%%", progressBarOption.progress);
324 } else {
325 progressBarOption.text = i18nc("not available", "n/a");
328 progressBarOption.rect.setY(progressBarOption.rect.y() +
329 (option.rect.height() - QApplication::fontMetrics().height()) / 2);
330 progressBarOption.rect.setHeight(QApplication::fontMetrics().height());
332 // Draw the progress bar onto the view.
333 QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter);
338 void TransfersViewDelegate::drawFocus(QPainter * painter, const QStyleOptionViewItem & option, const
339 QRect & rect) const
341 Q_UNUSED(painter);
342 Q_UNUSED(option);
343 Q_UNUSED(rect);
346 QSize TransfersViewDelegate::sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const
348 Q_UNUSED(option);
350 const TransferTreeModel * transferTreeModel = static_cast<const TransferTreeModel *>(index.model());
352 if(transferTreeModel->isTransferGroup(index))
354 return QSize(0, 35);
356 else {
357 QSize ret(KExtendableItemDelegate::sizeHint(option, index));
358 ret.rheight() += 8;
359 return ret;
363 QWidget * TransfersViewDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem & option , const QModelIndex & index) const
365 Q_UNUSED(option);
366 Q_UNUSED(index);
368 GroupStatusEditor * groupsStatusEditor = new GroupStatusEditor(index, this, parent);
370 return groupsStatusEditor;
373 bool TransfersViewDelegate::editorEvent(QEvent * event, QAbstractItemModel * model, const QStyleOptionViewItem & option, const QModelIndex & index)
375 Q_UNUSED(option);
377 QMouseEvent * mouseEvent = dynamic_cast<QMouseEvent *>(event);
379 if(mouseEvent)
381 if(mouseEvent->button() == Qt::RightButton)
383 // kDebug(5001) << "TransfersViewDelegate::editorEvent() -> rightClick";
385 if(m_popup)
387 delete(m_popup);
388 m_popup = 0;
391 TransferTreeModel * transferTreeModel = static_cast<TransferTreeModel *>(model);
393 if(transferTreeModel->isTransferGroup(index))
395 // kDebug(5001) << "isTransferGroup = true";
396 TransferGroupHandler * transferGroupHandler = static_cast<TransferGroupHandler *>(index.internalPointer());
398 m_popup = transferGroupHandler->popupMenu();
401 else
403 // kDebug(5001) << "isTransferGroup = false";
405 TransferHandler * transferHandler = static_cast<TransferHandler *>(index.internalPointer());
407 m_popup = transferHandler->popupMenu(KGet::selectedTransfers());
410 if(m_popup)
411 m_popup->popup( mouseEvent->globalPos() );
415 return false;
418 void TransfersViewDelegate::setEditorData(QWidget * editor, const QModelIndex & index) const
420 GroupStatusEditor * groupEditor = static_cast<GroupStatusEditor *>(editor);
422 groupEditor->setRunning((static_cast<TransferGroupHandler *>(index.internalPointer())->status()) == JobQueue::Running);
425 void TransfersViewDelegate::setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const
427 Q_UNUSED(model);
429 GroupStatusEditor * groupEditor = static_cast<GroupStatusEditor *>(editor);
431 TransferGroupHandler * groupHandler = static_cast<TransferGroupHandler *>(index.internalPointer());
433 if(groupEditor->isRunning())
434 groupHandler->start();
435 else
436 groupHandler->stop();
439 void TransfersViewDelegate::closeExpandableDetails(const QModelIndex &transferIndex)
441 if(transferIndex.isValid()) {
442 contractItem(transferIndex);
443 m_editingIndexes.removeAll(transferIndex);
445 else {
446 foreach(const QModelIndex &index, m_editingIndexes) {
447 contractItem(index);
450 m_editingIndexes.clear();
454 QWidget *TransfersViewDelegate::getDetailsWidgetForTransfer(TransferHandler *handler)
456 QGroupBox *groupBox = new QGroupBox();
458 QVBoxLayout *layout = new QVBoxLayout(groupBox);
459 QLabel *title = new QLabel(i18n("Transfer details"));
461 layout->addWidget(title);
462 layout->addWidget(new TransferDetails(handler));
463 groupBox->setAutoFillBackground(false);
464 title->setStyleSheet(EXPANDABLE_TRANSFER_DETAILS_TITLE_STYLE);
465 title->setAlignment(Qt::AlignHCenter);
466 groupBox->setStyleSheet(EXPANDABLE_TRANSFER_DETAILS_STYLE);
468 return groupBox;
471 void TransfersViewDelegate::itemActivated(QModelIndex index)
473 const TransferTreeModel * transferTreeModel = static_cast <const TransferTreeModel *> (index.model());
475 if(!transferTreeModel->isTransferGroup(index) && Settings::showExpandableTransferDetails()) {
476 if(!isExtended(index)) {
477 TransferHandler *handler = static_cast <TransferHandler *> (index.internalPointer());
478 QWidget *widget = getDetailsWidgetForTransfer(handler);
480 m_editingIndexes.append(index);
481 extendItem(widget, index);
483 else {
484 m_editingIndexes.removeAll(index);
485 contractItem(index);
488 else {
489 closeExpandableDetails(QModelIndex());
493 #include "transfersviewdelegate.moc"