1 /* This file is part of the KDE project
3 Copyright (C) 2006 Dario Massarin <nekkar@libero.it>
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
11 #include "core/transfertreemodel.h"
13 #include "core/kget.h"
14 #include "core/transfertreeselectionmodel.h"
15 #include "core/transfergrouphandler.h"
16 #include "core/transfergroup.h"
17 #include "core/transferhandler.h"
18 #include "core/transfer.h"
23 #include <kio/netaccess.h>
24 #include <kiconloader.h>
26 #include <qmimedata.h>
28 TransferTreeModel::TransferTreeModel(Scheduler
* scheduler
)
29 : QAbstractItemModel(),
30 m_scheduler(scheduler
),
36 TransferTreeModel::~TransferTreeModel()
41 void TransferTreeModel::addGroup(TransferGroup
* group
)
43 beginInsertRows(QModelIndex(), m_transferGroups
.size(), m_transferGroups
.size());
45 m_transferGroups
.append(group
);
50 void TransferTreeModel::delGroup(TransferGroup
* group
)
52 beginRemoveRows(QModelIndex(), m_transferGroups
.indexOf(group
), m_transferGroups
.indexOf(group
));
54 m_transferGroups
.removeAll(group
);
55 m_changedGroups
.removeAll(group
->handler());
60 void TransferTreeModel::addTransfer(Transfer
* transfer
, TransferGroup
* group
)
62 beginInsertRows(createIndex(m_transferGroups
.indexOf(group
), 0, group
->handler()), group
->size(), group
->size());
64 group
->append(transfer
);
69 void TransferTreeModel::delTransfer(Transfer
* transfer
)
71 TransferGroup
* group
= transfer
->group();
73 // Remove index corresponding to when it's created.
74 int remove_index
= group
->indexOf(transfer
);
75 beginRemoveRows(createIndex(m_transferGroups
.indexOf(group
), 0, group
->handler()), remove_index
, remove_index
);
77 group
->remove(transfer
);
78 m_changedTransfers
.removeAll(transfer
->handler());
83 void TransferTreeModel::moveTransfer(Transfer
* transfer
, TransferGroup
* destGroup
, Transfer
* after
)
85 if( (after
) && (destGroup
!= after
->group()) )
88 int removePosition
= transfer
->group()->indexOf(transfer
);
89 int insertPosition
= destGroup
->size();
90 int groupIndex
= m_transferGroups
.indexOf(destGroup
);
92 beginRemoveRows(createIndex(groupIndex
, 0, destGroup
->handler()), removePosition
, removePosition
);
94 beginInsertRows(createIndex(m_transferGroups
.indexOf(destGroup
), 0, destGroup
->handler()), insertPosition
, insertPosition
);
96 if(destGroup
== transfer
->group())
99 destGroup
->move(transfer
, after
);
101 destGroup
->move(transfer
, static_cast<Transfer
*>(destGroup
->last()));
105 transfer
->group()->remove(transfer
);
107 if(destGroup
->size() != 0)
108 destGroup
->insert(transfer
, static_cast<Transfer
*>(destGroup
->last()));
110 destGroup
->append(transfer
);
112 transfer
->m_jobQueue
= destGroup
;
118 KGet::selectionModel()->clearSelection();
121 const QList
<TransferGroup
*> & TransferTreeModel::transferGroups()
123 return m_transferGroups
;
126 TransferGroup
* TransferTreeModel::findGroup(const QString
& groupName
)
128 QList
<TransferGroup
*>::iterator it
= m_transferGroups
.begin();
129 QList
<TransferGroup
*>::iterator itEnd
= m_transferGroups
.end();
131 for(; it
!=itEnd
; ++it
)
133 if( (*it
)->name() == groupName
)
141 Transfer
* TransferTreeModel::findTransfer(const KUrl
&src
)
143 QList
<TransferGroup
*>::iterator it
= m_transferGroups
.begin();
144 QList
<TransferGroup
*>::iterator itEnd
= m_transferGroups
.end();
148 for(; it
!=itEnd
; ++it
)
150 if( ( t
= (*it
)->findTransfer(src
) ) )
156 Transfer
*TransferTreeModel::findTransferByDestination(const KUrl
&dest
)
158 QList
<TransferGroup
*>::iterator it
= m_transferGroups
.begin();
159 QList
<TransferGroup
*>::iterator itEnd
= m_transferGroups
.end();
162 for(; it
!=itEnd
; ++it
) {
163 if((t
= (*it
)->findTransferByDestination(dest
))) {
171 bool TransferTreeModel::isTransferGroup(const QModelIndex
& index
) const
173 // kDebug(5001) << "TransferTreeModel::isTransferGroup()";
175 void * pointer
= index
.internalPointer();
177 Handler
*ph
= static_cast<Handler
*>(pointer
);
178 if (dynamic_cast<TransferGroupHandler
*>(ph
))
185 void TransferTreeModel::postDataChangedEvent(TransferHandler
* transfer
)
188 m_timerId
= startTimer(500);
190 m_changedTransfers
.append(transfer
);
193 void TransferTreeModel::postDataChangedEvent(TransferGroupHandler
* group
)
196 m_timerId
= startTimer(500);
198 m_changedGroups
.append(group
);
201 QModelIndex
TransferTreeModel::createIndex(int row
, int column
, void * ptr
) const
207 // kDebug(5001) << "TransferTreeModel::createIndex() " << i;
209 return QAbstractItemModel::createIndex(row
, column
, ptr
);
212 int TransferTreeModel::rowCount(const QModelIndex
& parent
) const{
213 // kDebug(5001) << "TransferTreeModel::rowCount()";
215 if(!parent
.isValid())
217 // kDebug(5001) << " (ROOT) -> return " << m_transferGroups.size();
218 return m_transferGroups
.size();
221 if(isTransferGroup(parent
))
223 void * pointer
= parent
.internalPointer();
225 TransferGroupHandler
* group
= static_cast<TransferGroupHandler
*>(pointer
);
227 // kDebug(5001) << " (GROUP:" << group->name() << ") -> return " << group->size();
229 return group
->size();
235 int TransferTreeModel::columnCount(const QModelIndex
& parent
) const
237 // kDebug(5001) << "TransferTreeModel::columnCount()";
239 if(!parent
.isValid())
241 //Here we should return rootItem->columnCount(); .. but we don't
242 //have a root Item... bah
246 void * pointer
= parent
.internalPointer();
248 if(isTransferGroup(parent
))
250 //The given index refers to a group object
251 TransferGroupHandler
* group
= static_cast<TransferGroupHandler
*>(pointer
);
252 return group
->columnCount();
255 //The given index refers to a group object
256 TransferHandler
* transfer
= static_cast<TransferHandler
*>(pointer
);
257 return transfer
->columnCount();
261 Qt::ItemFlags
TransferTreeModel::flags (const QModelIndex
& index
) const
263 // kDebug(5001) << "TransferTreeModel::flags()";
264 if (!index
.isValid())
265 return Qt::ItemIsEnabled
;
267 Qt::ItemFlags flags
= Qt::ItemIsEnabled
| Qt::ItemIsSelectable
;
269 if(isTransferGroup(index
))
271 if(index
.column() == 0)
272 flags
|= Qt::ItemIsDropEnabled
;
275 flags
|= Qt::ItemIsDragEnabled
;
277 //flags |= Qt::ItemIsDropEnabled;
279 // We can edit all the groups but the default one
280 if(index
.row() > 0) {
281 flags
|= Qt::ItemIsEditable
;
287 QVariant
TransferTreeModel::headerData(int section
, Qt::Orientation orientation
, int role
) const
289 if (orientation
== Qt::Horizontal
&& role
== Qt::DisplayRole
)
294 return i18nc("name of download", "Name");
296 return i18nc("status of download", "Status");
298 return i18nc("size of download", "Size");
300 return i18nc("progress of download", "Progress");
302 return i18nc("speed of download", "Speed");
304 return i18nc("remaining time of download", "Remaining Time");
313 QVariant
TransferTreeModel::data(const QModelIndex
& index
, int role
) const
315 // kDebug(5001) << "TransferTreeModel::data()";
317 if (!index
.isValid())
319 // kDebug(5001) << " (ROOT)";
323 // KextendableItemDelegate::ShowExtensionIndicatorRole
324 // tells the KExtendableItemDelegate which column contains the extender icon
325 if (role
== Qt::UserRole
+ 200 && !isTransferGroup(index
)) {
326 if (index
.column () == 0 && Settings::showExpandableTransferDetails()) {
334 if (role
== Qt::DisplayRole
|| role
== Qt::DecorationRole
)
336 void * pointer
= index
.internalPointer();
338 if(isTransferGroup(index
))
340 TransferGroupHandler
* group
= static_cast<TransferGroupHandler
*>(pointer
);
341 if (role
== Qt::DisplayRole
)
343 // kDebug(5001) << " (GROUP)";
344 //The given index refers to a group object
345 return group
->data(index
.column());
347 else //Qt::DecorationRole -> icon
349 if (index
.column() == 0)
350 return group
->pixmap();
356 // kDebug(5001) << " (TRANSFER)";
358 //The given index refers to a transfer object
359 TransferHandler
* transfer
= static_cast<TransferHandler
*>(pointer
);
361 if (role
== Qt::DisplayRole
)
362 return transfer
->data(index
.column());
363 else //Qt::DecorationRole -> icon
365 switch (index
.column())
368 return KIO::pixmapForUrl(transfer
->dest(), 0, KIconLoader::Desktop
, 16);
370 return transfer
->statusPixmap();
377 if (role
== Qt::TextAlignmentRole
)
379 if(isTransferGroup(index
))
381 switch (index
.column())
384 return Qt::AlignVCenter
;
386 return Qt::AlignCenter
;
388 return Qt::AlignCenter
;
390 return Qt::AlignCenter
;
392 return QVariant(Qt::AlignLeft
| Qt::AlignBottom
);
396 switch (index
.column())
399 return QVariant(Qt::AlignLeft
| Qt::AlignVCenter
);
401 return Qt::AlignCenter
;
403 return Qt::AlignCenter
;
405 return Qt::AlignCenter
;
407 return Qt::AlignCenter
;
414 QModelIndex
TransferTreeModel::index(int row
, int column
, const QModelIndex
& parent
) const
416 // kDebug(5001) << "TransferTreeModel::index() ( " << row << " , " << column << " )";
418 if(!parent
.isValid())
420 // kDebug(5001) << "TransferTreeModel::index() -> group ( " << row << " , " << column << " ) Groups=" << m_transferGroups.size();
421 //Look for the specific group
422 if(row
< m_transferGroups
.size() && row
>= 0)
424 return createIndex(row
, column
, m_transferGroups
[row
]->handler());
428 return QModelIndex();
431 if(isTransferGroup(parent
))
433 //The given parent refers to a TransferGroupHandler object
434 void * pointer
= parent
.internalPointer();
435 TransferGroupHandler
* group
= static_cast<TransferGroupHandler
*>(pointer
);
437 //Look for the specific transfer
438 if(row
< group
->size() && row
>= 0)
440 // kDebug(5001) << "aa row=" << row;
442 // kDebug(5001) << "bb";
443 // return (*group)[row]->index(column);
444 return createIndex(row
, column
, (*group
)[row
]);
447 return QModelIndex();
450 //If here, the given parent is a Transfer object which hasn't any child
451 return QModelIndex();
454 QModelIndex
TransferTreeModel::parent(const QModelIndex
& index
) const
456 // kDebug(5001) << "TransferTreeModel::parent()";
459 return QModelIndex();
461 if(!isTransferGroup(index
))
463 //The given index refers to a Transfer item
464 void * pointer
= index
.internalPointer();
465 TransferGroupHandler
* group
= static_cast<TransferHandler
*>(pointer
)->group();
466 return createIndex(m_transferGroups
.indexOf(group
->m_group
), 0, group
);
469 return QModelIndex();
472 Qt::DropActions
TransferTreeModel::supportedDropActions() const
474 return Qt::CopyAction
| Qt::MoveAction
;
477 QStringList
TransferTreeModel::mimeTypes() const
480 types
<< "application/vnd.text.list";
484 QMimeData
* TransferTreeModel::mimeData(const QModelIndexList
&indexes
) const
486 QMimeData
* mimeData
= new QMimeData();
487 QByteArray encodedData
;
489 QDataStream
stream(&encodedData
, QIODevice::WriteOnly
);
491 foreach (const QModelIndex
&index
, indexes
)
495 if(index
.column() == 0 && index
.parent().isValid())
497 stream
<< data(index
.parent(), Qt::DisplayRole
).toString();
498 stream
<< QString::number((qulonglong
) index
.internalPointer(),16);
503 mimeData
->setData("application/vnd.text.list", encodedData
);
507 bool TransferTreeModel::dropMimeData(const QMimeData
* mdata
, Qt::DropAction action
, int row
, int column
, const QModelIndex
&parent
)
509 if (action
== Qt::IgnoreAction
)
512 if (!mdata
->hasFormat("application/vnd.text.list"))
518 if (parent
.isValid())
519 kDebug(5001) << "TransferTreeModel::dropMimeData" << " " << row
<< " "
522 QByteArray encodedData
= mdata
->data("application/vnd.text.list");
523 QDataStream
stream(&encodedData
, QIODevice::ReadOnly
);
524 QStringList stringList
;
527 while (!stream
.atEnd())
535 kDebug(5001) << "TransferTreeModel::dropMimeData DATA:";
536 kDebug(5001) << stringList
;
539 for(int i
=0; i
< rows
; i
++)
541 // TransferGroup * group = findGroup(stringList[i]);
543 // TransferGroup * destGroup = static_cast<TransferGroup *>(index(row, column, parent).internalPointer());
545 TransferGroup
* destGroup
= findGroup(data(parent
, Qt::DisplayRole
).toString());
547 TransferHandler
* transferHandler
= (TransferHandler
*) stringList
[++i
].toInt(0, 16);
550 moveTransfer(transferHandler
->m_transfer
, destGroup
);
555 QString
TransferTreeModel::columnName(int column
)
558 case TransferTreeModel::Name
:
560 case TransferTreeModel::Status
:
561 return i18n("Status");
562 case TransferTreeModel::Size
:
564 case TransferTreeModel::Progress
:
565 return i18n("Progress");
566 case TransferTreeModel::Speed
:
567 return i18n("Speed");
568 case TransferTreeModel::RemainingTime
:
569 return i18n("Remaining Time");
575 void TransferTreeModel::timerEvent(QTimerEvent
*event
)
578 // kDebug(5001) << "TransferTreeModel::timerEvent";
580 QList
<TransferHandler
*> updatedTransfers
;
581 QList
<TransferGroupHandler
*> updatedGroups
;
583 foreach(TransferHandler
* transfer
, m_changedTransfers
)
585 if(!updatedTransfers
.contains(transfer
))
587 TransferGroupHandler
* group
= transfer
->group();
588 Transfer::ChangesFlags changesFlags
= transfer
->changesFlags(0);
590 for(int i
=0; i
<8; i
++)//Check the 8 most right bits of the flag
592 if (((changesFlags
>> i
) & 0x00000001))//remove the ith bit(s) from the right and check if the rest is 0x00000001...
594 QModelIndex index
= createIndex(group
->indexOf(transfer
), i
, transfer
);
595 emit
dataChanged(index
,index
);
599 transfer
->resetChangesFlags(0);
600 updatedTransfers
.append(transfer
);
604 foreach(TransferGroupHandler
* group
, m_changedGroups
)
606 if(!updatedGroups
.contains(group
))
608 TransferGroup::ChangesFlags changesFlags
= group
->changesFlags(0);
610 for(int i
=0; i
<8; i
++)
612 if(((changesFlags
>> i
) & 0x00000001))
614 QModelIndex index
= createIndex(m_transferGroups
.indexOf(group
->m_group
), i
, group
);
615 emit
dataChanged(index
,index
);
619 group
->resetChangesFlags(0);
620 updatedGroups
.append(group
);
624 m_changedTransfers
.clear();
625 m_changedGroups
.clear();
627 killTimer(m_timerId
);
631 #include "transfertreemodel.moc"