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