Fix system-tray...
[kdenetwork.git] / kget / ui / transfersviewdelegate.cpp
blobd21438ac2d3b76e10d3e3576bf25e1a6fc86257d
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; either
9 version 2 of the License, or (at your option) any later version.
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_status(None),
40 m_index(index),
41 m_timerId(-1),
42 m_iconSize(22),
43 m_gradientId(0)
47 void GroupStatusButton::checkStateSet()
49 // kDebug(5001) << "GroupStatusButton::checkStateSet";
51 QToolButton::checkStateSet();
53 if(isChecked())
55 if(m_status == None)
56 m_gradientId = 0.7;
57 m_status = Selecting;
59 else
61 if(m_status == None)
62 m_gradientId = 1;
63 m_status = Deselecting;
66 setMouseTracking(!isChecked());
68 if(m_timerId == -1)
69 m_timerId = startTimer(25);
72 void GroupStatusButton::enterEvent(QEvent * event)
74 Q_UNUSED(event);
75 if(!isChecked())
77 m_status = Blinking;
79 if(m_timerId == -1)
81 m_timerId = startTimer(25);
83 if(m_status == !BlinkingExiting)
84 m_gradientId = 1;
89 void GroupStatusButton::leaveEvent(QEvent * event)
91 Q_UNUSED(event);
92 if(m_status == Blinking)
93 m_status = BlinkingExiting;
96 void GroupStatusButton::paintEvent(QPaintEvent * event)
98 Q_UNUSED(event);
100 QPainter p(this);
102 int offset = (event->rect().width() - m_iconSize) / 2;
104 if(m_gradientId == 0)
105 m_gradientId = isChecked() ? 1 : 0.7;
107 QRadialGradient gradient(event->rect().topLeft() + QPoint(event->rect().width() / 2, event->rect().height() / 2), event->rect().width() / 2);
109 QPen pen;
111 if(KGet::selectionModel()->isSelected(m_index))
113 gradient.setColorAt(0, palette().color(QPalette::AlternateBase));
114 gradient.setColorAt(m_gradientId, palette().color(QPalette::Highlight));
115 gradient.setColorAt(1, palette().color(QPalette::Highlight));
116 pen.setColor(palette().color(QPalette::AlternateBase));
118 else
120 gradient.setColorAt(0, palette().color(QPalette::Highlight));
121 gradient.setColorAt(m_gradientId, Qt::transparent);
122 gradient.setColorAt(1, Qt::transparent);
123 pen.setColor(palette().color(QPalette::Highlight));
126 QRect r = event->rect();
127 r.adjust(0,0,0,-1);
129 p.fillRect(r, gradient);
131 p.setRenderHint(QPainter::Antialiasing);
133 if(isChecked())
135 pen.setWidth(1);
136 p.setPen(pen);
137 p.drawEllipse(event->rect().x()+5, event->rect().y()+5, event->rect().width()-10, event->rect().width()-10);
140 p.drawPixmap(event->rect().topLeft() + QPoint(offset, offset),
141 icon().pixmap(m_iconSize, isChecked() || m_status == Blinking ?
142 QIcon::Normal : QIcon::Disabled));
145 void GroupStatusButton::timerEvent(QTimerEvent *event)
147 Q_UNUSED(event);
149 if(m_status == Selecting)
151 m_gradientId+=0.05;
153 if(m_gradientId >= 1)
155 m_status = None;
156 m_gradientId = 1;
157 killTimer(m_timerId);
158 m_timerId = -1;
161 else if(m_status == Deselecting)
163 m_gradientId-=0.05;
165 if(m_gradientId <= 0.7)
167 m_status = None;
168 m_gradientId = 0.7;
169 killTimer(m_timerId);
170 m_timerId = -1;
173 else if(m_status == Blinking)
175 m_gradientId-=0.01;
177 if(m_gradientId <= 0.7)
179 m_gradientId = 1;
182 else if(m_status == BlinkingExiting)
184 m_gradientId-=0.01;
186 if(m_gradientId <= 0.7)
188 m_status = None;
189 m_gradientId = 0.7;
190 killTimer(m_timerId);
191 m_timerId = -1;
195 update();
198 GroupStatusEditor::GroupStatusEditor(const QModelIndex & index, const TransfersViewDelegate * delegate, QWidget * parent)
199 : QWidget(parent),
200 m_delegate(delegate),
201 m_index(index)
203 setMinimumWidth(80);
205 m_layout = new QHBoxLayout();
206 m_layout->addStretch();
207 setLayout(m_layout);
209 m_btGroup = new QButtonGroup(this);
210 m_btGroup->setExclusive(true);
212 m_startBt = new GroupStatusButton(m_index, this);
213 m_startBt->setCheckable(true);
214 m_startBt->setAutoRaise(true);
215 m_startBt->setIcon(KIcon("media-playback-start"));
216 m_startBt->setFixedSize(36, 36);
217 m_startBt->setIconSize(QSize(22, 22));
218 m_startBt->installEventFilter(const_cast<TransfersViewDelegate *>(delegate));
219 m_layout->addWidget(m_startBt);
220 m_btGroup->addButton(m_startBt);
222 m_stopBt = new GroupStatusButton(m_index, this);
223 m_stopBt->setCheckable(true);
224 m_stopBt->setAutoRaise(true);
225 m_stopBt->setIcon(KIcon("media-playback-pause"));
226 m_stopBt->setFixedSize(36, 36);
227 m_stopBt->setIconSize(QSize(22, 22));
228 m_stopBt->installEventFilter(const_cast<TransfersViewDelegate *>(delegate));
229 m_layout->addWidget(m_stopBt);
230 m_btGroup->addButton(m_stopBt);
232 m_stopBt->setChecked(true);
234 m_layout->addStretch();
235 m_layout->setMargin(1);
237 connect(m_startBt, SIGNAL(toggled(bool)),
238 this, SLOT(slotStatusChanged(bool)));
241 void GroupStatusEditor::setRunning(bool running)
243 if(running)
244 m_startBt->setChecked(true);
245 else
246 m_stopBt->setChecked(true);
249 bool GroupStatusEditor::isRunning()
251 return m_startBt->isChecked();
254 void GroupStatusEditor::slotStatusChanged(bool running)
256 Q_UNUSED(running);
258 emit const_cast<TransfersViewDelegate *>(m_delegate)->commitData(this);
261 TransfersViewDelegate::TransfersViewDelegate(QAbstractItemView *parent)
262 : KExtendableItemDelegate(parent), m_popup(0)
264 Q_ASSERT(qobject_cast<QAbstractItemView *>(parent));
265 setExtendIcon(SmallIcon("arrow-right"));
266 setContractIcon(SmallIcon("arrow-down"));
267 connect(parent, SIGNAL(clicked(QModelIndex)), this, SLOT(itemActivated(QModelIndex)));
270 void TransfersViewDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const
272 const TransferTreeModel * transferTreeModel = static_cast<const TransferTreeModel *>(index.model());
274 if(transferTreeModel->isTransferGroup(index))
276 painter->save();
278 if (option.state & QStyle::State_Selected)
281 else
283 QLinearGradient gradient(option.rect.x(), option.rect.y(),
284 option.rect.x(), (option.rect.y() + option.rect.height()));
285 gradient.setColorAt(0, QApplication::palette().color(QPalette::Base));
286 gradient.setColorAt(0.5, QApplication::palette().color(QPalette::AlternateBase).darker(110));
287 gradient.setColorAt(1, QApplication::palette().color(QPalette::Base));
289 painter->fillRect(option.rect, gradient);
292 QItemDelegate::paint(painter, option, index);
294 painter->restore();
296 else {
297 if (KGet::selectionModel()->isSelected(index))
298 painter->fillRect(option.rect, QApplication::palette().color(option.state & QStyle::State_Active ?
299 QPalette::Active : QPalette::Inactive,
300 QPalette::Highlight));
302 KExtendableItemDelegate::paint(painter, option, index);
304 if (index.column() == 3 && !isExtended(transferTreeModel->index(index.row(), 0, index.parent()))) { // the percent column
305 TransferHandler *transferHandler = static_cast<TransferHandler *>(index.internalPointer());
307 // following progressbar code has mostly been taken from Qt4 examples/network/torrent/mainview.cpp
308 // Set up a QStyleOptionProgressBar to precisely mimic the
309 // environment of a progress bar.
310 QStyleOptionProgressBar progressBarOption;
311 progressBarOption.state = QStyle::State_Enabled;
312 progressBarOption.direction = QApplication::layoutDirection();
313 progressBarOption.rect = option.rect;
314 progressBarOption.fontMetrics = QApplication::fontMetrics();
315 progressBarOption.minimum = 0;
316 progressBarOption.maximum = 100;
317 progressBarOption.textAlignment = Qt::AlignCenter;
318 progressBarOption.textVisible = true;
320 // Set the progress and text values of the style option.
321 int progress = transferHandler->percent();
322 if (progress >= 0 && progress <= 100) {
323 progressBarOption.progress = progress;
324 progressBarOption.text = QString().sprintf("%d%%", progressBarOption.progress);
325 } else {
326 progressBarOption.text = i18nc("not available", "n/a");
329 progressBarOption.rect.setY(progressBarOption.rect.y() +
330 (option.rect.height() - QApplication::fontMetrics().height()) / 2);
331 progressBarOption.rect.setHeight(QApplication::fontMetrics().height());
333 // Draw the progress bar onto the view.
334 QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter);
339 void TransfersViewDelegate::drawFocus(QPainter * painter, const QStyleOptionViewItem & option, const
340 QRect & rect) const
342 Q_UNUSED(painter);
343 Q_UNUSED(option);
344 Q_UNUSED(rect);
347 QSize TransfersViewDelegate::sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const
349 Q_UNUSED(option);
351 const TransferTreeModel * transferTreeModel = static_cast<const TransferTreeModel *>(index.model());
353 if(transferTreeModel->isTransferGroup(index))
355 return QSize(0, 35);
357 else {
358 QSize ret(KExtendableItemDelegate::sizeHint(option, index));
359 ret.rheight() += 8;
360 return ret;
364 QWidget * TransfersViewDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem & option , const QModelIndex & index) const
366 Q_UNUSED(option);
367 Q_UNUSED(index);
369 GroupStatusEditor * groupsStatusEditor = new GroupStatusEditor(index, this, parent);
371 return groupsStatusEditor;
374 bool TransfersViewDelegate::editorEvent(QEvent * event, QAbstractItemModel * model, const QStyleOptionViewItem & option, const QModelIndex & index)
376 Q_UNUSED(option);
378 QMouseEvent * mouseEvent = dynamic_cast<QMouseEvent *>(event);
380 if(mouseEvent)
382 if(mouseEvent->button() == Qt::RightButton)
384 // kDebug(5001) << "TransfersViewDelegate::editorEvent() -> rightClick";
386 if(m_popup)
388 delete(m_popup);
389 m_popup = 0;
392 TransferTreeModel * transferTreeModel = static_cast<TransferTreeModel *>(model);
394 if(transferTreeModel->isTransferGroup(index))
396 // kDebug(5001) << "isTransferGroup = true";
397 TransferGroupHandler * transferGroupHandler = static_cast<TransferGroupHandler *>(index.internalPointer());
399 m_popup = transferGroupHandler->popupMenu();
402 else
404 // kDebug(5001) << "isTransferGroup = false";
406 TransferHandler * transferHandler = static_cast<TransferHandler *>(index.internalPointer());
408 m_popup = transferHandler->popupMenu(KGet::selectedTransfers());
411 if(m_popup)
412 m_popup->popup( mouseEvent->globalPos() );
416 return false;
419 void TransfersViewDelegate::setEditorData(QWidget * editor, const QModelIndex & index) const
421 GroupStatusEditor * groupEditor = static_cast<GroupStatusEditor *>(editor);
423 groupEditor->setRunning((static_cast<TransferGroupHandler *>(index.internalPointer())->status()) == JobQueue::Running);
426 void TransfersViewDelegate::setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const
428 Q_UNUSED(model);
430 GroupStatusEditor * groupEditor = static_cast<GroupStatusEditor *>(editor);
432 TransferGroupHandler * groupHandler = static_cast<TransferGroupHandler *>(index.internalPointer());
434 if (groupEditor->isRunning())
435 groupHandler->start();
436 else
437 groupHandler->stop();
439 bool downloading = false;
440 foreach (TransferHandler *transfer, groupHandler->transfers())
442 if (transfer->status() == Job::Running)
443 downloading = true;
445 if (downloading)
446 KGet::setTrayDownloading(true);
449 void TransfersViewDelegate::closeExpandableDetails(const QModelIndex &transferIndex)
451 if(transferIndex.isValid()) {
452 contractItem(transferIndex);
453 m_editingIndexes.removeAll(transferIndex);
455 else {
456 foreach(const QModelIndex &index, m_editingIndexes) {
457 contractItem(index);
460 m_editingIndexes.clear();
464 QWidget *TransfersViewDelegate::getDetailsWidgetForTransfer(TransferHandler *handler)
466 QGroupBox *groupBox = new QGroupBox();
468 QVBoxLayout *layout = new QVBoxLayout(groupBox);
469 QLabel *title = new QLabel(i18n("Transfer details"));
471 layout->addWidget(title);
472 layout->addWidget(new TransferDetails(handler));
473 groupBox->setAutoFillBackground(false);
474 title->setStyleSheet(EXPANDABLE_TRANSFER_DETAILS_TITLE_STYLE.arg(QApplication::palette().color(QPalette::Foreground).name()));
475 title->setAlignment(Qt::AlignHCenter);
476 groupBox->setStyleSheet(EXPANDABLE_TRANSFER_DETAILS_STYLE.arg(QApplication::palette().color(QPalette::Background).lighter(200).name(), QApplication::palette().color(QPalette::Background).name()));
478 return groupBox;
481 void TransfersViewDelegate::itemActivated(QModelIndex index)
483 const TransferTreeModel * transferTreeModel = static_cast <const TransferTreeModel *> (index.model());
485 if(!transferTreeModel->isTransferGroup(index) && Settings::showExpandableTransferDetails() && index.column() == 0) {
486 if(!isExtended(index)) {
487 TransferHandler *handler = static_cast <TransferHandler *> (index.internalPointer());
488 QWidget *widget = getDetailsWidgetForTransfer(handler);
490 m_editingIndexes.append(index);
491 extendItem(widget, index);
493 else {
494 m_editingIndexes.removeAll(index);
495 contractItem(index);
500 #include "transfersviewdelegate.moc"