Changeset 14345


Ignore:
Timestamp:
Nov 30, 2014, 6:12:28 PM (8 years ago)
Author:
mikedld
Message:

#5827: Improve torrent files tree updating performance

Do not unnecessarily emit dataChanged signals for items which didn't change.
Cache file item indices to speedup lookup.
As a bonus, this also fixes wrong file progress display in rare cases.

Location:
trunk/qt
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/qt/file-tree.cc

    r14315 r14345  
    232232    }
    233233
    234   if (myHaveSize != haveSize)
    235     {
    236       myHaveSize = haveSize;
    237       changed_columns[changed_count++] = COL_PROGRESS;
    238     }
    239 
    240   if (fileIndex() != -1)
    241     {
     234  if (fileIndex () != -1)
     235    {
     236      if (myHaveSize != haveSize)
     237        {
     238          myHaveSize = haveSize;
     239          changed_columns[changed_count++] = COL_PROGRESS;
     240        }
     241
    242242      if (updateFields)
    243243        {
     
    417417  QAbstractItemModel(parent),
    418418  myRootItem (new FileTreeItem),
     419  myIndexCache (),
    419420  myIsEditable (isEditable)
    420421{
     
    587588    clearSubtree(index(--i, 0, top));
    588589
    589   delete static_cast<FileTreeItem*>(itemFromIndex(top));
     590  FileTreeItem * const item = itemFromIndex (top);
     591  if (item == 0)
     592    return;
     593
     594  if (item->fileIndex () != -1)
     595    myIndexCache.remove (item->fileIndex ());
     596
     597  delete item;
    590598}
    591599
     
    596604  clearSubtree (QModelIndex());
    597605  endResetModel ();
     606
     607  assert (myIndexCache.isEmpty ());
    598608}
    599609
     
    601611FileTreeModel :: findItemForFileIndex (int fileIndex) const
    602612{
    603   FileTreeItem * ret = 0;
    604 
    605   QModelIndexList indices = match (index (0,COL_FILE_INDEX),
    606                                    Qt::DisplayRole,
    607                                    fileIndex,
    608                                    1,
    609                                    Qt::MatchFlags (Qt::MatchExactly | Qt::MatchRecursive));
    610 
    611   if (!indices.isEmpty ())
    612     {
    613       QModelIndex& index = indices.front ();
    614       if (index.isValid())
    615         ret = itemFromIndex (index);
    616     }
    617 
    618   return ret;
     613  return myIndexCache.value (fileIndex, 0);
    619614}
    620615
     
    637632  if (item) // this file is already in the tree, we've added this
    638633    {
     634      QModelIndex indexWithChangedParents;
    639635      while (!tokens.isEmpty())
    640636        {
     
    642638          const std::pair<int,int> changed = item->update (token, wanted, priority, have, updateFields);
    643639          if (changed.first >= 0)
    644             dataChanged (indexOf (item, changed.first), indexOf (item, changed.second));
     640            {
     641              dataChanged (indexOf (item, changed.first), indexOf (item, changed.second));
     642              if (!indexWithChangedParents.isValid () &&
     643                  changed.first <= COL_PRIORITY && changed.second >= COL_SIZE)
     644                indexWithChangedParents = indexOf (item, 0);
     645            }
    645646          item = item->parent();
    646647        }
    647648      assert (item == myRootItem);
     649      if (indexWithChangedParents.isValid ())
     650        parentsChanged (indexWithChangedParents, COL_SIZE, COL_PRIORITY);
    648651    }
    649652  else // we haven't build the FileTreeItems for these tokens yet
     
    678681          assert (item->totalSize() == totalSize);
    679682
     683          myIndexCache[fileIndex] = item;
     684
    680685          const std::pair<int,int> changed = item->update (item->name(), wanted, priority, have, added || updateFields);
    681686          if (changed.first >= 0)
     
    686691
    687692void
    688 FileTreeModel :: parentsChanged (const QModelIndex& index, int column)
    689 {
     693FileTreeModel :: parentsChanged (const QModelIndex& index, int firstColumn, int lastColumn)
     694{
     695  assert (firstColumn <= lastColumn);
     696
    690697  QModelIndex walk = index;
    691698
    692699  for (;;)
    693700    {
    694       walk = parent(walk, column);
    695       if(!walk.isValid())
     701      walk = parent (walk, firstColumn);
     702      if (!walk.isValid ())
    696703        break;
    697704
    698       dataChanged(walk, walk);
    699     }
    700 }
    701 
    702 void
    703 FileTreeModel :: subtreeChanged (const QModelIndex& index, int column)
    704 {
     705      dataChanged (walk, walk.sibling (walk.row (), lastColumn));
     706    }
     707}
     708
     709void
     710FileTreeModel :: subtreeChanged (const QModelIndex& index, int firstColumn, int lastColumn)
     711{
     712  assert (firstColumn <= lastColumn);
     713
    705714  const int childCount = rowCount (index);
    706715  if (!childCount)
     
    708717
    709718  // tell everyone that this tier changed
    710   dataChanged (index.child(0,column), index.child(childCount-1,column));
     719  dataChanged (index.child (0, firstColumn), index.child (childCount - 1, lastColumn));
    711720
    712721  // walk the subtiers
    713722  for (int i=0; i<childCount; ++i)
    714     subtreeChanged (index.child(i,column), column);
     723    subtreeChanged (index.child (i, 0), firstColumn, lastColumn);
    715724}
    716725
     
    733742      emit wantedChanged (file_ids, want);
    734743
    735       // this changes the name column's parenthetical size-wanted string too...
    736       QModelIndex nameSibling = index.sibling (index.row(), COL_SIZE);
    737       dataChanged (nameSibling, nameSibling);
    738       parentsChanged (nameSibling, COL_SIZE);
    739 
    740744      dataChanged (index, index);
    741       parentsChanged (index, column);
    742       subtreeChanged (index, column);
     745      parentsChanged (index, COL_SIZE, COL_WANTED);
     746      subtreeChanged (index, COL_WANTED, COL_WANTED);
    743747    }
    744748  else if (column == COL_PRIORITY)
     
    752756      emit priorityChanged (file_ids, priority);
    753757
    754       dataChanged(index, index);
    755       parentsChanged(index, column);
    756       subtreeChanged(index, column);
     758      dataChanged (index, index);
     759      parentsChanged (index, column, column);
     760      subtreeChanged (index, column, column);
    757761    }
    758762}
  • trunk/qt/file-tree.h

    r14241 r14345  
    1616#include <QList>
    1717#include <QHash>
     18#include <QMap>
    1819#include <QSet>
    1920#include <QSize>
     
    128129    void clearSubtree (const QModelIndex &);
    129130    QModelIndex indexOf (FileTreeItem *, int column) const;
    130     void parentsChanged (const QModelIndex &, int column);
    131     void subtreeChanged (const QModelIndex &, int column);
     131    void parentsChanged (const QModelIndex &, int firstColumn, int lastColumn);
     132    void subtreeChanged (const QModelIndex &, int firstColumn, int lastColumn);
    132133    FileTreeItem * findItemForFileIndex (int fileIndex) const;
    133134    FileTreeItem * itemFromIndex (const QModelIndex&) const;
     
    135136  private:
    136137    FileTreeItem * myRootItem;
     138    QMap<int, FileTreeItem *> myIndexCache;
    137139    const bool myIsEditable;
    138140
Note: See TracChangeset for help on using the changeset viewer.