Changeset 14551


Ignore:
Timestamp:
Jul 12, 2015, 8:48:54 PM (7 years ago)
Author:
mikedld
Message:

Improve file tree population/update performance

Use simple tokenization instead of splitting the file path into
QStringList for each item. Don't expand each added item separetely
during population/update. Don't expand all the items but just up to the
point where parent has more than one expandable child.

Also, fix items order by sorting items after population/update. Fix
sorting by size on systems where uint64_t != quint64.

Location:
trunk/qt
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/qt/FileTreeItem.cc

    r14541 r14551  
    120120              value.setValue (sizeString());
    121121            else
    122               value.setValue (size ());
     122              value.setValue<quint64> (size ());
    123123            break;
    124124
  • trunk/qt/FileTreeModel.cc

    r14539 r14551  
    1010#include <cassert>
    1111
    12 #include <QStringList>
    13 
    1412#include "FileTreeItem.h"
    1513#include "FileTreeModel.h"
     14
     15namespace
     16{
     17  class PathIteratorBase
     18  {
     19    protected:
     20      PathIteratorBase(const QString& path, int slashIndex):
     21        myPath (path),
     22        mySlashIndex (slashIndex),
     23        myToken ()
     24      {
     25        myToken.reserve (path.size () / 2);
     26      }
     27
     28    protected:
     29      const QString& myPath;
     30      int mySlashIndex;
     31      QString myToken;
     32
     33      static const QChar SlashChar;
     34  };
     35
     36  const QChar PathIteratorBase::SlashChar = QLatin1Char ('/');
     37
     38  class ForwardPathIterator: public PathIteratorBase
     39  {
     40    public:
     41      ForwardPathIterator (const QString& path):
     42        PathIteratorBase (path, path.size () - 1)
     43      {
     44      }
     45
     46      bool hasNext () const
     47      {
     48        return mySlashIndex > 0;
     49      }
     50
     51      const QString& next ()
     52      {
     53        int newSlashIndex = myPath.lastIndexOf (SlashChar, mySlashIndex);
     54        myToken.truncate (0);
     55        myToken += myPath.midRef (newSlashIndex + 1, mySlashIndex - newSlashIndex);
     56        mySlashIndex = newSlashIndex - 1;
     57        return myToken;
     58      }
     59  };
     60
     61  class BackwardPathIterator: public PathIteratorBase
     62  {
     63    public:
     64      BackwardPathIterator (const QString& path):
     65        PathIteratorBase (path, 0)
     66      {
     67      }
     68
     69      bool hasNext () const
     70      {
     71        return mySlashIndex < myPath.size ();
     72      }
     73
     74      const QString& next ()
     75      {
     76        int newSlashIndex = myPath.indexOf (SlashChar, mySlashIndex);
     77        if (newSlashIndex == -1)
     78          newSlashIndex = myPath.size ();
     79        myToken.truncate (0);
     80        myToken += myPath.midRef (mySlashIndex, newSlashIndex - mySlashIndex);
     81        mySlashIndex = newSlashIndex + 1;
     82        return myToken;
     83      }
     84  };
     85}
    1686
    1787FileTreeModel::FileTreeModel (QObject * parent, bool isEditable):
     
    222292
    223293void
    224 FileTreeModel::addFile (int                   fileIndex,
    225                         const QString       & filename,
    226                         bool                  wanted,
    227                         int                   priority,
    228                         uint64_t              totalSize,
    229                         uint64_t              have,
    230                         QList<QModelIndex>  & rowsAdded,
    231                         bool                  updateFields)
     294FileTreeModel::addFile (int            fileIndex,
     295                        const QString& filename,
     296                        bool           wanted,
     297                        int            priority,
     298                        uint64_t       totalSize,
     299                        uint64_t       have,
     300                        bool           updateFields)
    232301{
    233302  FileTreeItem * item;
    234   QStringList tokens = filename.split (QChar::fromLatin1('/'));
    235303
    236304  item = findItemForFileIndex (fileIndex);
     
    239307    {
    240308      QModelIndex indexWithChangedParents;
    241       while (!tokens.isEmpty())
     309      ForwardPathIterator filenameIt (filename);
     310      while (filenameIt.hasNext ())
    242311        {
    243           const QString token = tokens.takeLast();
     312          const QString& token = filenameIt.next ();
    244313          const std::pair<int,int> changed = item->update (token, wanted, priority, have, updateFields);
    245314          if (changed.first >= 0)
     
    261330
    262331      item = myRootItem;
    263       while (!tokens.isEmpty())
     332      BackwardPathIterator filenameIt (filename);
     333      while (filenameIt.hasNext ())
    264334        {
    265           const QString token = tokens.takeFirst();
     335          const QString& token = filenameIt.next ();
    266336          FileTreeItem * child(item->child(token));
    267337          if (!child)
     
    272342
    273343              beginInsertRows (parentIndex, n, n);
    274               if (tokens.isEmpty())
     344              if (!filenameIt.hasNext ())
    275345                child = new FileTreeItem (token, fileIndex, totalSize);
    276346              else
     
    278348              item->appendChild (child);
    279349              endInsertRows ();
    280 
    281               rowsAdded.append (indexOf(child, 0));
    282350            }
    283351          item = child;
  • trunk/qt/FileTreeModel.h

    r14541 r14551  
    5454                  bool wanted, int priority,
    5555                  uint64_t size, uint64_t have,
    56                   QList<QModelIndex>& rowsAdded,
    5756                  bool torrentChanged);
    5857
  • trunk/qt/FileTreeView.cc

    r14541 r14551  
    170170FileTreeView::update (const FileList& files, bool updateFields)
    171171{
     172  const bool modelWasEmpty = myProxy->rowCount () == 0;
     173
    172174  for (const TorrentFile& file: files)
     175    myModel->addFile (file.index, file.filename, file.wanted, file.priority, file.size, file.have, updateFields);
     176
     177  if (modelWasEmpty)
    173178    {
    174       QList<QModelIndex> added;
    175       myModel->addFile (file.index, file.filename, file.wanted, file.priority, file.size, file.have, added, updateFields);
    176       for (const QModelIndex& i: added)
    177         expand (myProxy->mapFromSource(i));
     179      // expand up until the item with more than one expandable child
     180      for (QModelIndex index = myProxy->index (0, 0); index.isValid ();)
     181        {
     182          const QModelIndex oldIndex = index;
     183
     184          expand (oldIndex);
     185
     186          index = QModelIndex ();
     187          for (int i = 0, count = myProxy->rowCount (oldIndex); i < count; ++i)
     188            {
     189              const QModelIndex newIndex = myProxy->index (i, 0, oldIndex);
     190              if (myProxy->rowCount (newIndex) == 0)
     191                continue;
     192              if (index.isValid ())
     193                {
     194                  index = QModelIndex ();
     195                  break;
     196                }
     197              index = newIndex;
     198            }
     199        }
    178200    }
     201
     202  myProxy->sort (header ()->sortIndicatorSection (), header ()->sortIndicatorOrder ());
    179203}
    180204
Note: See TracChangeset for help on using the changeset viewer.