diff --git a/qt/FileTreeItem.cc b/qt/FileTreeItem.cc index 7c52c8135..e5780ab2c 100644 --- a/qt/FileTreeItem.cc +++ b/qt/FileTreeItem.cc @@ -119,7 +119,7 @@ FileTreeItem::data (int column, int role) const if (role == Qt::DisplayRole) value.setValue (sizeString()); else - value.setValue (size ()); + value.setValue (size ()); break; case FileTreeModel::COL_PROGRESS: diff --git a/qt/FileTreeModel.cc b/qt/FileTreeModel.cc index 140ceff92..b9653c46f 100644 --- a/qt/FileTreeModel.cc +++ b/qt/FileTreeModel.cc @@ -9,11 +9,81 @@ #include -#include - #include "FileTreeItem.h" #include "FileTreeModel.h" +namespace +{ + class PathIteratorBase + { + protected: + PathIteratorBase(const QString& path, int slashIndex): + myPath (path), + mySlashIndex (slashIndex), + myToken () + { + myToken.reserve (path.size () / 2); + } + + protected: + const QString& myPath; + int mySlashIndex; + QString myToken; + + static const QChar SlashChar; + }; + + const QChar PathIteratorBase::SlashChar = QLatin1Char ('/'); + + class ForwardPathIterator: public PathIteratorBase + { + public: + ForwardPathIterator (const QString& path): + PathIteratorBase (path, path.size () - 1) + { + } + + bool hasNext () const + { + return mySlashIndex > 0; + } + + const QString& next () + { + int newSlashIndex = myPath.lastIndexOf (SlashChar, mySlashIndex); + myToken.truncate (0); + myToken += myPath.midRef (newSlashIndex + 1, mySlashIndex - newSlashIndex); + mySlashIndex = newSlashIndex - 1; + return myToken; + } + }; + + class BackwardPathIterator: public PathIteratorBase + { + public: + BackwardPathIterator (const QString& path): + PathIteratorBase (path, 0) + { + } + + bool hasNext () const + { + return mySlashIndex < myPath.size (); + } + + const QString& next () + { + int newSlashIndex = myPath.indexOf (SlashChar, mySlashIndex); + if (newSlashIndex == -1) + newSlashIndex = myPath.size (); + myToken.truncate (0); + myToken += myPath.midRef (mySlashIndex, newSlashIndex - mySlashIndex); + mySlashIndex = newSlashIndex + 1; + return myToken; + } + }; +} + FileTreeModel::FileTreeModel (QObject * parent, bool isEditable): QAbstractItemModel(parent), myIsEditable (isEditable), @@ -221,26 +291,25 @@ FileTreeModel::findItemForFileIndex (int fileIndex) const } void -FileTreeModel::addFile (int fileIndex, - const QString & filename, - bool wanted, - int priority, - uint64_t totalSize, - uint64_t have, - QList & rowsAdded, - bool updateFields) +FileTreeModel::addFile (int fileIndex, + const QString& filename, + bool wanted, + int priority, + uint64_t totalSize, + uint64_t have, + bool updateFields) { FileTreeItem * item; - QStringList tokens = filename.split (QChar::fromLatin1('/')); item = findItemForFileIndex (fileIndex); if (item) // this file is already in the tree, we've added this { QModelIndex indexWithChangedParents; - while (!tokens.isEmpty()) + ForwardPathIterator filenameIt (filename); + while (filenameIt.hasNext ()) { - const QString token = tokens.takeLast(); + const QString& token = filenameIt.next (); const std::pair changed = item->update (token, wanted, priority, have, updateFields); if (changed.first >= 0) { @@ -260,9 +329,10 @@ FileTreeModel::addFile (int fileIndex, bool added = false; item = myRootItem; - while (!tokens.isEmpty()) + BackwardPathIterator filenameIt (filename); + while (filenameIt.hasNext ()) { - const QString token = tokens.takeFirst(); + const QString& token = filenameIt.next (); FileTreeItem * child(item->child(token)); if (!child) { @@ -271,14 +341,12 @@ FileTreeModel::addFile (int fileIndex, const int n (item->childCount()); beginInsertRows (parentIndex, n, n); - if (tokens.isEmpty()) + if (!filenameIt.hasNext ()) child = new FileTreeItem (token, fileIndex, totalSize); else child = new FileTreeItem (token); item->appendChild (child); endInsertRows (); - - rowsAdded.append (indexOf(child, 0)); } item = child; } diff --git a/qt/FileTreeModel.h b/qt/FileTreeModel.h index 9f122209e..c79940a5b 100644 --- a/qt/FileTreeModel.h +++ b/qt/FileTreeModel.h @@ -53,7 +53,6 @@ class FileTreeModel: public QAbstractItemModel void addFile (int index, const QString& filename, bool wanted, int priority, uint64_t size, uint64_t have, - QList& rowsAdded, bool torrentChanged); QModelIndex parent (const QModelIndex& child, int column) const; diff --git a/qt/FileTreeView.cc b/qt/FileTreeView.cc index 6dfed35fa..d5e9f20cf 100644 --- a/qt/FileTreeView.cc +++ b/qt/FileTreeView.cc @@ -169,13 +169,37 @@ FileTreeView::keyPressEvent (QKeyEvent * event) void FileTreeView::update (const FileList& files, bool updateFields) { + const bool modelWasEmpty = myProxy->rowCount () == 0; + for (const TorrentFile& file: files) + myModel->addFile (file.index, file.filename, file.wanted, file.priority, file.size, file.have, updateFields); + + if (modelWasEmpty) { - QList added; - myModel->addFile (file.index, file.filename, file.wanted, file.priority, file.size, file.have, added, updateFields); - for (const QModelIndex& i: added) - expand (myProxy->mapFromSource(i)); + // expand up until the item with more than one expandable child + for (QModelIndex index = myProxy->index (0, 0); index.isValid ();) + { + const QModelIndex oldIndex = index; + + expand (oldIndex); + + index = QModelIndex (); + for (int i = 0, count = myProxy->rowCount (oldIndex); i < count; ++i) + { + const QModelIndex newIndex = myProxy->index (i, 0, oldIndex); + if (myProxy->rowCount (newIndex) == 0) + continue; + if (index.isValid ()) + { + index = QModelIndex (); + break; + } + index = newIndex; + } + } } + + myProxy->sort (header ()->sortIndicatorSection (), header ()->sortIndicatorOrder ()); } void