1 /* This file is part of the KDE project
2 
3    Copyright (C) 2006 Dario Massarin <nekkar@libero.it>
4    Copyright (C) 2009 Lukas Appelhans <l.appelhans@gmx.de>
5    Copyright (C) 2010 Matthias Fuchs <mat69@gmx.net>
6 
7    This program is free software; you can redistribute it and/or
8    modify it under the terms of the GNU General Public
9    License as published by the Free Software Foundation; either
10    version 2 of the License, or (at your option) any later version.
11 */
12 
13 #include "core/transfertreemodel.h"
14 
15 #include "core/kget.h"
16 #include "core/transfertreeselectionmodel.h"
17 #include "core/transfergrouphandler.h"
18 #include "core/transfergroup.h"
19 #include "core/transferhandler.h"
20 #include "core/transfer.h"
21 #include "transferadaptor.h"
22 #include "dbus/dbustransferwrapper.h"
23 #include "settings.h"
24 #include "transfergroupscheduler.h"
25 #include "kget_debug.h"
26 
27 #include <algorithm>
28 
29 #include <QDebug>
30 
31 #include <KLocalizedString>
32 #include <KIO/Global>
33 
ItemMimeData()34 ItemMimeData::ItemMimeData()
35   : QMimeData()
36 {
37 }
38 
~ItemMimeData()39 ItemMimeData::~ItemMimeData()
40 {
41 }
42 
appendTransfer(const QPointer<TransferHandler> & transfer)43 void ItemMimeData::appendTransfer(const QPointer<TransferHandler> &transfer)
44 {
45     m_transfers.append(transfer);
46 }
47 
transfers() const48 QList<QPointer<TransferHandler> > ItemMimeData::transfers() const
49 {
50     return m_transfers;
51 }
52 
ModelItem(Handler * handler)53 ModelItem::ModelItem(Handler * handler)
54   : QStandardItem(),
55     m_handler(handler)
56 {
57 }
58 
~ModelItem()59 ModelItem::~ModelItem()
60 {
61 }
62 
emitDataChanged()63 void ModelItem::emitDataChanged()
64 {
65     QStandardItem::emitDataChanged();
66 }
67 
handler()68 Handler * ModelItem::handler()
69 {
70     return m_handler;
71 }
72 
isGroup()73 bool ModelItem::isGroup()
74 {
75     return false;
76 }
77 
asGroup()78 GroupModelItem * ModelItem::asGroup()
79 {
80     return dynamic_cast<GroupModelItem*>(this);
81 }
82 
asTransfer()83 TransferModelItem * ModelItem::asTransfer()
84 {
85     return dynamic_cast<TransferModelItem*>(this);
86 }
87 
88 
TransferModelItem(TransferHandler * handler)89 TransferModelItem::TransferModelItem(TransferHandler *handler)
90   : ModelItem(handler),
91     m_transferHandler(handler)
92 {
93 }
94 
~TransferModelItem()95 TransferModelItem::~TransferModelItem()
96 {
97 }
98 
data(int role) const99 QVariant TransferModelItem::data(int role) const
100 {
101     if (role == Qt::DisplayRole)
102         return m_transferHandler->data(column());
103     else if (role == Qt::DecorationRole)
104     {
105         switch (column())
106         {
107             case 0: {
108                 //store the icon for speed improvements, KIconLoader should make sure, that
109                 //the icon data gets shared
110                 if (m_mimeType.isNull()) {
111                     m_mimeType = QIcon::fromTheme(KIO::iconNameForUrl(m_transferHandler->dest()));
112                 }
113 
114                 return m_mimeType;
115             }
116             case 1:
117                 return m_transferHandler->statusPixmap();
118         }
119     }
120     if (role == Qt::TextAlignmentRole)
121     {
122         switch (column())
123         {
124             case 0: // name
125                 return QVariant(Qt::AlignLeft | Qt::AlignVCenter);
126             default:
127                 return Qt::AlignCenter;
128         }
129     }
130     // KextendableItemDelegate::ShowExtensionIndicatorRole
131     // tells the KExtendableItemDelegate which column contains the extender icon
132     if (role == Qt::UserRole + 200)
133     {
134         if (column() == 0)
135             return true;
136         else
137             return false;
138     }
139     return QVariant();
140 }
141 
transferHandler()142 TransferHandler * TransferModelItem::transferHandler()
143 {
144     return m_transferHandler;
145 }
146 
147 
GroupModelItem(TransferGroupHandler * handler)148 GroupModelItem::GroupModelItem(TransferGroupHandler *handler)
149   : ModelItem(handler),
150     m_groupHandler(handler)
151 {
152 }
153 
~GroupModelItem()154 GroupModelItem::~GroupModelItem()
155 {
156 }
157 
data(int role) const158 QVariant GroupModelItem::data(int role) const
159 {
160     if (role == Qt::DisplayRole) {
161         return m_groupHandler->data(column());
162     }
163     if (role == Qt::TextAlignmentRole)
164     {
165         switch (column())
166         {
167             case 0: // name
168                 return Qt::AlignVCenter;
169             case 2: // size
170             case 3: // speed
171             case 4: //progress
172                 return Qt::AlignCenter;
173             default:
174                 return QVariant(Qt::AlignLeft | Qt::AlignBottom);
175         }
176     }
177     if (role == Qt::DecorationRole && column() == 0)
178         return m_groupHandler->pixmap();
179     return QVariant();
180 }
181 
groupHandler()182 TransferGroupHandler * GroupModelItem::groupHandler()
183 {
184     //qDebug() << m_groupHandler->name();
185     return m_groupHandler;
186 }
187 
isGroup()188 bool GroupModelItem::isGroup()
189 {
190     return true;
191 }
192 
193 
TransferTreeModel(Scheduler * scheduler)194 TransferTreeModel::TransferTreeModel(Scheduler * scheduler)
195     : QStandardItemModel(),
196       m_scheduler(scheduler),
197       m_timerId(-1)
198 {
199     m_transferGroups.clear();
200     m_transfers.clear();
201 }
202 
~TransferTreeModel()203 TransferTreeModel::~TransferTreeModel()
204 {
205 
206 }
207 
addGroup(TransferGroup * group)208 void TransferTreeModel::addGroup(TransferGroup * group)
209 {
210     QList<QStandardItem*> items;
211     for (int i = 0; i != group->handler()->columnCount(); i++)
212         items << new GroupModelItem(group->handler());
213 
214     appendRow(items);
215 
216     m_transferGroups.append(static_cast<GroupModelItem*>(items.first()));
217 
218     Q_EMIT groupAddedEvent(group->handler());
219 
220     KGet::m_scheduler->addQueue(group);
221 }
222 
delGroup(TransferGroup * group)223 void TransferTreeModel::delGroup(TransferGroup * group)
224 {
225     if (m_transferGroups.count() <= 1) //If there is only one group left, we should not remove it
226         return;
227     GroupModelItem *item = itemFromTransferGroupHandler(group->handler());
228     if (!item) {
229         return;
230     }
231 
232     QList<Transfer*> transfers;
233     JobQueue::iterator it;
234     JobQueue::iterator itEnd = group->end();
235     for (it = group->begin(); it != itEnd; ++it) {
236         transfers << static_cast<Transfer*>(*it);
237     }
238     delTransfers(transfers);
239 
240     m_transferGroups.removeAll(item);
241     removeRow(item->row());
242 
243     m_changedGroups.removeAll(group->handler());
244 
245     Q_EMIT groupRemovedEvent(group->handler());
246 
247     KGet::m_scheduler->delQueue(group);
248 }
249 
addTransfers(const QList<Transfer * > & transfers,TransferGroup * group)250 void TransferTreeModel::addTransfers(const QList<Transfer*> &transfers, TransferGroup *group)
251 {
252     ModelItem *parentItem = itemFromTransferGroupHandler(group->handler());
253     beginInsertRows(parentItem->index(), parentItem->rowCount(), parentItem->rowCount() + transfers.count() - 1);
254 
255     //HACK blocks all signals from the model when adding multiple items,
256     //that way rowsInserted gets only emitted once, and not constantly when doing appendRow
257     //change this once there is a better way to append many transfers at once
258     blockSignals(true);
259 
260     //now create and add the new items
261     QList<TransferHandler*> handlers;
262     group->append(transfers);
263     foreach (Transfer *transfer, transfers) {
264         TransferHandler *handler = transfer->handler();
265         handlers << handler;
266 
267         QList<QStandardItem*> items;
268         for (int i = 0; i != handler->columnCount(); ++i) {
269             items << new TransferModelItem(handler);
270         }
271 
272         parentItem->appendRow(items);
273 
274         m_transfers.append(static_cast<TransferModelItem*>(items.first()));
275 
276         auto * wrapper = new DBusTransferWrapper(handler);
277         new TransferAdaptor(wrapper);
278         QDBusConnection::sessionBus().registerObject(handler->dBusObjectPath(), wrapper);
279     }
280 
281     //notify the rest of the changes
282     blockSignals(false);
283     endInsertRows();
284     Q_EMIT transfersAddedEvent(handlers);
285 }
286 
delTransfers(const QList<Transfer * > & t)287 void TransferTreeModel::delTransfers(const QList<Transfer*> &t)
288 {
289     QList<Transfer*> transfers = t;
290     QList<TransferHandler*> handlers;
291 
292     //find all valid items and sort them according to their groups
293     QHash<TransferGroup*, QList<TransferModelItem*> > groups;
294     QHash<TransferGroup*, QList<Transfer*> > groupsTransfer;
295     {
296         QList<Transfer*>::iterator it;
297         QList<Transfer*>::iterator itEnd = transfers.end();
298         for (it = transfers.begin(); it != itEnd; ) {
299             TransferModelItem *item = itemFromTransferHandler((*it)->handler());
300             if (item) {
301                 handlers << (*it)->handler();
302                 groups[(*it)->group()] << item;
303                 groupsTransfer[(*it)->group()] << *it;
304                 ++it;
305             } else {
306                 it = transfers.erase(it);
307             }
308         }
309     }
310 
311     Q_EMIT transfersAboutToBeRemovedEvent(handlers);
312 
313     //remove the items from the model
314     {
315         QHash<TransferGroup*, QList<TransferModelItem*> >::iterator it;
316         QHash<TransferGroup*, QList<TransferModelItem*> >::iterator itEnd = groups.end();
317         for (it = groups.begin(); it != itEnd; ++it) {
318             const int numItems = (*it).count();
319             QStandardItem *parentItem = (*it).first()->parent();
320             QModelIndex parentIndex = parentItem->index();
321             if (numItems == parentItem->rowCount()) {
322                 for (int i = 0; i < numItems; ++i) {
323                     m_transfers.removeAll((*it)[i]);
324                 }
325                 removeRows(0, numItems, parentIndex);
326                 continue;
327             }
328 
329             int rowStart = (*it).first()->row();
330             int numRows = 1;
331             m_transfers.removeAll((*it).first());
332             for (int i = 1; i < numItems; ++i) {
333                 //previous item is neighbour
334                 if (rowStart + numRows == (*it)[i]->row()) {
335                     ++numRows;
336                 //no neighbour, so start again
337                 } else {
338                     removeRows(rowStart, numRows, parentIndex);
339                     rowStart = (*it)[i]->row();
340                     numRows = 1;
341                 }
342                 m_transfers.removeAll((*it)[i]);
343             }
344             //remove last items
345             removeRows(rowStart, numRows, parentIndex);
346         }
347     }
348 
349     foreach(Transfer *transfer, transfers) {
350         QDBusConnection::sessionBus().unregisterObject(transfer->handler()->dBusObjectPath());
351         m_changedTransfers.removeAll(transfer->handler());
352     }
353 
354     {
355         QHash<TransferGroup*, QList<Transfer*> >::iterator it;
356         QHash<TransferGroup*, QList<Transfer*> >::iterator itEnd = groupsTransfer.end();
357         for (it = groupsTransfer.begin(); it != itEnd; ++it) {
358             it.key()->remove(it.value());
359         }
360     }
361 
362     Q_EMIT transfersRemovedEvent(handlers);
363 }
364 
itemFromTransferHandler(TransferHandler * handler)365 TransferModelItem * TransferTreeModel::itemFromTransferHandler(TransferHandler * handler)
366 {
367     foreach (TransferModelItem * item, m_transfers)
368     {
369         if (handler == item->transferHandler())
370             return item;
371     }
372     return nullptr;
373 }
374 
itemFromTransferGroupHandler(TransferGroupHandler * handler)375 GroupModelItem * TransferTreeModel::itemFromTransferGroupHandler(TransferGroupHandler * handler)
376 {
377     foreach (GroupModelItem * item, m_transferGroups)
378     {
379         if (handler == item->groupHandler())
380             return item;
381     }
382     return nullptr;
383 }
384 
itemFromHandler(Handler * handler)385 ModelItem * TransferTreeModel::itemFromHandler(Handler * handler)
386 {
387     auto *transfer = qobject_cast<TransferHandler*>(handler);
388     if (transfer) {
389         return itemFromTransferHandler(transfer);
390     }
391     return itemFromTransferGroupHandler(qobject_cast<TransferGroupHandler*>(handler));
392 }
393 
itemFromIndex(const QModelIndex & index) const394 ModelItem * TransferTreeModel::itemFromIndex(const QModelIndex &index) const
395 {
396     QStandardItem *item = QStandardItemModel::itemFromIndex(index);
397     if (item)
398         return dynamic_cast<ModelItem*>(item);
399     return nullptr;
400 }
401 
moveTransfer(Transfer * transfer,TransferGroup * destGroup,Transfer * after)402 void TransferTreeModel::moveTransfer(Transfer * transfer, TransferGroup * destGroup, Transfer * after)
403 {
404     if( (after) && (destGroup != after->group()) )
405         return;
406 
407     int position = transfer->group()->indexOf(transfer);
408 
409     TransferGroup * oldGroup = transfer->group();
410 
411     bool sameGroup = false;
412 
413     if (destGroup == transfer->group())
414     {
415         sameGroup = true;
416         if (after)
417             destGroup->move(transfer, after);
418         else
419             destGroup->move(transfer, nullptr);
420     }
421     else
422     {
423         transfer->group()->remove(transfer);
424 
425         if (after)
426             destGroup->insert(transfer, after);
427         else
428             destGroup->prepend(transfer);
429 
430         transfer->m_jobQueue = destGroup;
431     }
432     QList<QStandardItem*> items = itemFromHandler(oldGroup->handler())->takeRow(position);
433     itemFromHandler(destGroup->handler())->insertRow(destGroup->indexOf(transfer), items);
434 
435     if (!sameGroup)
436         Q_EMIT transferMovedEvent(transfer->handler(), destGroup->handler());
437 
438     KGet::selectionModel()->clearSelection();
439 }
440 
moveTransfer(TransferHandler * transfer,TransferGroupHandler * destGroup,TransferHandler * after)441 void TransferTreeModel::moveTransfer(TransferHandler *transfer, TransferGroupHandler *destGroup, TransferHandler *after)
442 {
443     Transfer *afterTransfer = nullptr;
444     if (after) {
445         afterTransfer = after->m_transfer;
446     }
447     moveTransfer(transfer->m_transfer, destGroup->m_group, afterTransfer);
448 }
449 
transferGroups()450 QList<TransferGroup *> TransferTreeModel::transferGroups()
451 {
452     QList<TransferGroup*> transferGroups;
453     foreach (GroupModelItem * item, m_transferGroups) {
454         transferGroups << item->groupHandler()->m_group;
455     }
456 
457     return transferGroups;
458 }
459 
findGroup(const QString & groupName)460 TransferGroup * TransferTreeModel::findGroup(const QString & groupName)
461 {
462     foreach (GroupModelItem * group, m_transferGroups)
463     {
464         if (group->groupHandler()->name() == groupName)
465             return group->groupHandler()->m_group;
466     }
467     return nullptr;
468 }
469 
findTransfer(const QUrl & src)470 Transfer * TransferTreeModel::findTransfer(const QUrl &src)
471 {
472     /*foreach (TransferGroup * group, transferGroups())
473     {
474         Transfer * t = group->findTransfer(src);
475         if (t)
476             return t;
477     }*/
478     foreach (TransferModelItem * transfer, m_transfers)
479     {
480         if (transfer->transferHandler()->source() == src)
481             return transfer->transferHandler()->m_transfer;
482     }
483     return nullptr;
484 }
485 
findTransferByDestination(const QUrl & dest)486 Transfer *TransferTreeModel::findTransferByDestination(const QUrl &dest)
487 {
488     /*foreach (TransferGroup * group, transferGroups())
489     {
490         Transfer * t = group->findTransferByDestination(dest);
491         if (t)
492             return t;
493     }*/
494     foreach (TransferModelItem * transfer, m_transfers)
495     {
496         if (transfer->transferHandler()->dest() == dest)
497             return transfer->transferHandler()->m_transfer;
498     }
499     return nullptr;
500 }
501 
findTransferByDBusObjectPath(const QString & dbusObjectPath)502 Transfer * TransferTreeModel::findTransferByDBusObjectPath(const QString & dbusObjectPath)
503 {
504     foreach (TransferModelItem * transfer, m_transfers)
505     {
506         if (transfer->transferHandler()->dBusObjectPath() == dbusObjectPath)
507             return transfer->transferHandler()->m_transfer;
508     }
509     return nullptr;
510 }
511 
postDataChangedEvent(TransferHandler * transfer)512 void TransferTreeModel::postDataChangedEvent(TransferHandler * transfer)
513 {
514     if(m_timerId == -1)
515         m_timerId = startTimer(500);
516 
517     m_changedTransfers.append(transfer);
518 }
519 
postDataChangedEvent(TransferGroupHandler * group)520 void TransferTreeModel::postDataChangedEvent(TransferGroupHandler * group)
521 {
522     if(m_timerId == -1)
523         m_timerId = startTimer(500);
524 
525     m_changedGroups.append(group);
526 }
527 
flags(const QModelIndex & index) const528 Qt::ItemFlags TransferTreeModel::flags (const QModelIndex & index) const
529 {
530 //     qCDebug(KGET_DEBUG) << "TransferTreeModel::flags()";
531     if (!index.isValid())
532         return Qt::ItemIsEnabled;
533 
534     Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
535 
536     if (!index.parent().isValid())
537     {
538         if(index.column() == 0)
539             flags |= Qt::ItemIsDropEnabled;
540     }
541     else
542         flags |= Qt::ItemIsDragEnabled;
543 
544     //flags |= Qt::ItemIsDropEnabled;
545 
546     // We can edit all the groups but the default one
547     if(index.row() > 0) {
548         flags |= Qt::ItemIsEditable;
549     }
550 
551     return flags;
552 }
553 
headerData(int section,Qt::Orientation orientation,int role) const554 QVariant TransferTreeModel::headerData(int section, Qt::Orientation orientation, int role) const
555 {
556     if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
557     {
558         return columnName(section);
559     }
560 
561     return QVariant();
562 }
563 
supportedDropActions() const564 Qt::DropActions TransferTreeModel::supportedDropActions() const
565 {
566     return Qt::CopyAction | Qt::MoveAction;
567 }
568 
mimeTypes() const569 QStringList TransferTreeModel::mimeTypes() const
570 {
571     QStringList types;
572     types << "kget/transfer_pointer";
573     return types;
574 }
575 
mimeData(const QModelIndexList & indexes) const576 QMimeData * TransferTreeModel::mimeData(const QModelIndexList &indexes) const
577 {
578     auto *mimeData = new ItemMimeData();
579 
580     QModelIndexList sortedIndexes = indexes;
581     std::sort(sortedIndexes.begin(), sortedIndexes.end(), [](const QModelIndex &a, const QModelIndex &b) { return b < a; });
582     foreach (const QModelIndex &index, sortedIndexes) {
583         if (index.isValid() && index.column() == 0 && index.parent().isValid()) {
584             ModelItem *item = itemFromIndex(index);
585             if (!item->isGroup()) {
586                 mimeData->appendTransfer(QPointer<TransferHandler>(item->asTransfer()->transferHandler()));
587             }
588         }
589     }
590 
591     mimeData->setData("kget/transfer_pointer", QByteArray());
592     return mimeData;
593 }
594 
dropMimeData(const QMimeData * mdata,Qt::DropAction action,int row,int column,const QModelIndex & parent)595 bool TransferTreeModel::dropMimeData(const QMimeData * mdata, Qt::DropAction action, int row, int column, const QModelIndex &parent)
596 {
597     if (action == Qt::IgnoreAction)
598         return true;
599 
600     const auto *itemData = qobject_cast<const ItemMimeData*>(mdata);
601     if (!itemData) {
602         qCWarning(KGET_DEBUG) << "Unsupported mime data dropped.";
603         return false;
604     }
605 
606     TransferGroup *destGroup = findGroup(data(parent, Qt::DisplayRole).toString());
607     if (!destGroup) {
608         qCWarning(KGET_DEBUG) << "No group could be found where the transfers should be inserted to.";
609         return false;
610     }
611 
612     if (parent.isValid())
613         qCDebug(KGET_DEBUG) << "TransferTreeModel::dropMimeData" << " " << row << " "
614                                                           << column;
615 
616     QList<QPointer<TransferHandler> > transfers = itemData->transfers();
617     qCDebug(KGET_DEBUG) << "TransferTreeModel::dropMimeData:" << transfers.count() << "transfers.";
618 
619     const bool droppedInsideGroup = parent.isValid();
620     Transfer * after = nullptr;
621     for (int i = 0; i < transfers.count(); ++i) {
622         bool b = destGroup->size() > row && row - 1 >= 0;
623         if (b)
624             qCDebug(KGET_DEBUG) << "TRANSFER AFTER:" << destGroup->operator[](row - 1)->source();
625         else
626             qCDebug(KGET_DEBUG) << "TRANSFER AFTER NOT EXISTING";
627 
628         if (!after) {
629             bool rowValid = (row - 1 >= 0) && (destGroup->size() >= row);
630             if (droppedInsideGroup && rowValid) {
631                 after = destGroup->operator[](row - 1);//insert at the correct position
632             }
633         }
634 
635         if (transfers[i].isNull()) {
636             qWarning() << "The moved transfer has been deleted inbetween.";
637         } else {
638             moveTransfer(transfers[i].data()->m_transfer, destGroup, after);
639         }
640     }
641     return true;
642 }
643 
columnName(int column)644 QString TransferTreeModel::columnName(int column)
645 {
646     switch(column) {
647         case 0:
648             return i18nc("name of download", "Name");
649         case 1:
650             return i18nc("status of download", "Status");
651         case 2:
652             return i18nc("size of download", "Size");
653         case 3:
654             return i18nc("progress of download", "Progress");
655         case 4:
656             return i18nc("speed of download", "Speed");
657         case 5:
658             return i18nc("remaining time of download", "Remaining Time");
659     }
660     return QString();
661 }
662 
column(Transfer::TransferChange flag)663 int TransferTreeModel::column(Transfer::TransferChange flag)
664 {
665     switch(flag) {
666         case Transfer::Tc_FileName:
667             return 0;
668         case Transfer::Tc_Status:
669             return 1;
670         case Transfer::Tc_TotalSize:
671             return 2;
672         case Transfer::Tc_Percent:
673             return 3;
674         case Transfer::Tc_DownloadSpeed:
675             return 4;
676         case Transfer::Tc_RemainingTime:
677             return 5;
678         default:
679             return -1;
680     }
681     return -1;
682 }
683 
column(TransferGroup::GroupChange flag)684 int TransferTreeModel::column(TransferGroup::GroupChange flag)
685 {
686     switch(flag) {
687         case TransferGroup::Gc_GroupName:
688             return 0;
689         case TransferGroup::Gc_Status:
690             return 1;
691         case TransferGroup::Gc_TotalSize:
692             return 2;
693         case TransferGroup::Gc_Percent:
694             return 3;
695         case TransferGroup::Gc_DownloadSpeed:
696             return 4;
697         default:
698             return -1;
699     }
700     return -1;
701 }
702 
timerEvent(QTimerEvent * event)703 void TransferTreeModel::timerEvent(QTimerEvent *event)
704 {
705     Q_UNUSED(event)
706 //     qCDebug(KGET_DEBUG) << "TransferTreeModel::timerEvent";
707 
708     QMap<TransferHandler *, Transfer::ChangesFlags> updatedTransfers;
709     QMap<TransferGroupHandler *, TransferGroup::ChangesFlags> updatedGroups;
710 
711     foreach (TransferHandler * transfer, m_changedTransfers)
712     {
713         if (!updatedTransfers.contains(transfer)) {
714             TransferGroupHandler * group = transfer->group();
715             ModelItem * item = itemFromHandler(group);
716             Transfer::ChangesFlags changesFlags = transfer->changesFlags();
717 
718             Q_EMIT transfer->transferChangedEvent(transfer, changesFlags);
719 
720             int row = group->indexOf(transfer);
721 
722 //             qCDebug(KGET_DEBUG) << "CHILD = " << item->child(row, column(Transfer::Tc_FileName));
723 
724             // Now, check that model child items already exist (there are some cases when the transfer
725             // can notify for changes before the gui has been correctly initialized)
726             if(item->child(row, 0)) {
727                 if (changesFlags & Transfer::Tc_FileName)
728                     static_cast<ModelItem*>(item->child(row, column(Transfer::Tc_FileName)))->emitDataChanged();
729                 if (changesFlags & Transfer::Tc_Status)
730                     static_cast<ModelItem*>(item->child(row, column(Transfer::Tc_Status)))->emitDataChanged();
731                 if (changesFlags & Transfer::Tc_TotalSize)
732                     static_cast<ModelItem*>(item->child(row, column(Transfer::Tc_TotalSize)))->emitDataChanged();
733                 if (changesFlags & Transfer::Tc_Percent)
734                     static_cast<ModelItem*>(item->child(row, column(Transfer::Tc_Percent)))->emitDataChanged();
735                 if (changesFlags & Transfer::Tc_DownloadSpeed)
736                     static_cast<ModelItem*>(item->child(row, column(Transfer::Tc_DownloadSpeed)))->emitDataChanged();
737                 if (changesFlags & Transfer::Tc_RemainingTime)
738                     static_cast<ModelItem*>(item->child(row, column(Transfer::Tc_RemainingTime)))->emitDataChanged();
739 
740                 transfer->resetChangesFlags();
741                 updatedTransfers.insert(transfer,changesFlags);
742             }
743         }
744     }
745 
746     if(!updatedTransfers.isEmpty())
747         Q_EMIT transfersChangedEvent(updatedTransfers);
748 
749     foreach(TransferGroupHandler * group, m_changedGroups)
750     {
751         if(!updatedGroups.contains(group))
752         {
753             TransferGroup::ChangesFlags changesFlags = group->changesFlags();
754 
755             Q_EMIT group->groupChangedEvent(group, changesFlags);
756 
757             int row = itemFromHandler(group)->row();
758 
759             if (changesFlags & TransferGroup::Gc_GroupName)
760                 static_cast<ModelItem*>(item(row, column(TransferGroup::Gc_GroupName)))->emitDataChanged();
761             if (changesFlags & TransferGroup::Gc_Status)
762                 static_cast<ModelItem*>(item(row, column(TransferGroup::Gc_Status)))->emitDataChanged();
763             if (changesFlags & TransferGroup::Gc_TotalSize)
764                 static_cast<ModelItem*>(item(row, column(TransferGroup::Gc_TotalSize)))->emitDataChanged();
765             if (changesFlags & TransferGroup::Gc_Percent)
766                 static_cast<ModelItem*>(item(row, column(TransferGroup::Gc_Percent)))->emitDataChanged();
767             if (changesFlags & TransferGroup::Gc_DownloadSpeed)
768                 static_cast<ModelItem*>(item(row, column(TransferGroup::Gc_DownloadSpeed)))->emitDataChanged();
769 
770             /*for(int i=0; i<8; i++)
771             {
772                 if(((changesFlags >> i) & 0x00000001))
773                 {
774                     QStandardItem *groupItem = itemFromHandler(group);
775                     dynamic_cast<ModelItem*>(invisibleRootItem()->child(groupItem->row(), i))->emitDataChanged();
776                     //QModelIndex index = createIndex(m_transferGroups.indexOf(group->m_group), i, group);
777                     //Q_EMIT dataChanged(index,index);
778                 }
779             }*/
780 
781             group->resetChangesFlags();
782             updatedGroups.insert(group, changesFlags);
783         }
784     }
785 
786     if(!updatedGroups.isEmpty())
787         Q_EMIT groupsChangedEvent(updatedGroups);
788 
789     m_changedTransfers.clear();
790     m_changedGroups.clear();
791 
792     killTimer(m_timerId);
793     m_timerId = -1;
794 }
795 
796 
797