Changeset 14736 for trunk


Ignore:
Timestamp:
Apr 24, 2016, 7:56:41 AM (14 months ago)
Author:
mikedld
Message:

Reduce torrents model memory requirements (Qt client)

Keep torrents sorted by ID. This allows to remove ID to row/torrent mappings
(using binary search instead) and thus also reduce complexity a bit.

Location:
trunk/qt
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/qt/TorrentModel.cc

    r14554 r14736  
    1818#include "TorrentModel.h"
    1919
     20namespace
     21{
     22  struct TorrentIdLessThan
     23  {
     24    bool operator () (Torrent * left, Torrent * right) const
     25    {
     26      return left->id () < right->id ();
     27    }
     28
     29    bool operator () (int leftId, Torrent * right) const
     30    {
     31      return leftId < right->id ();
     32    }
     33
     34    bool operator () (Torrent * left, int rightId) const
     35    {
     36      return left->id () < rightId;
     37    }
     38  };
     39}
     40
    2041void
    2142TorrentModel::clear ()
     
    2344  beginResetModel ();
    2445
    25   myIdToRow.clear ();
    26   myIdToTorrent.clear ();
    2746  qDeleteAll (myTorrents);
    2847  myTorrents.clear ();
     
    7796TorrentModel::addTorrent (Torrent * t)
    7897{
    79   myIdToTorrent.insert (t->id (), t);
    80   myIdToRow.insert (t->id (), myTorrents.size ());
    81   myTorrents.append (t);
     98  const torrents_t::iterator torrentIt = qLowerBound (myTorrents.begin (), myTorrents.end (), t, TorrentIdLessThan ());
     99  const int row = torrentIt == myTorrents.end () ? myTorrents.size () : torrentIt - myTorrents.begin ();
     100
     101  beginInsertRows (QModelIndex(), row, row);
     102  myTorrents.insert (torrentIt, t);
     103  endInsertRows ();
     104}
     105
     106void
     107TorrentModel::addTorrents (torrents_t&& torrents, QSet<int>& addIds)
     108{
     109  if (myTorrents.isEmpty ())
     110    {
     111      qSort (torrents.begin (), torrents.end (), TorrentIdLessThan ());
     112
     113      beginInsertRows (QModelIndex (), 0, torrents.size () - 1);
     114      myTorrents.swap (torrents);
     115      endInsertRows ();
     116
     117      addIds += getIds ();
     118    }
     119  else
     120    {
     121      for (Torrent * const tor: torrents)
     122        {
     123          addTorrent (tor);
     124          addIds.insert (tor->id ());
     125        }
     126    }
    82127}
    83128
     
    99144TorrentModel::getTorrentFromId (int id)
    100145{
    101   id_to_torrent_t::iterator it (myIdToTorrent.find (id));
    102   return it == myIdToTorrent.end() ? 0 : it.value ();
     146  const torrents_t::const_iterator torrentIt = qBinaryFind (myTorrents.begin (), myTorrents.end (), id, TorrentIdLessThan ());
     147  return torrentIt == myTorrents.end () ? nullptr : *torrentIt;
    103148}
    104149
     
    106151TorrentModel::getTorrentFromId (int id) const
    107152{
    108   id_to_torrent_t::const_iterator it (myIdToTorrent.find (id));
    109   return it == myIdToTorrent.end() ? 0 : it.value ();
     153  const torrents_t::const_iterator torrentIt = qBinaryFind (myTorrents.begin (), myTorrents.end (), id, TorrentIdLessThan ());
     154  return torrentIt == myTorrents.end () ? nullptr : *torrentIt;
    110155}
    111156
     
    117162TorrentModel::onTorrentChanged (int torrentId)
    118163{
    119   const int row (myIdToRow.value (torrentId, -1));
    120   if (row >= 0)
    121     {
    122       QModelIndex qmi (index (row, 0));
    123       emit dataChanged (qmi, qmi);
    124     }
     164  const torrents_t::iterator torrentIt = qBinaryFind (myTorrents.begin (), myTorrents.end (), torrentId, TorrentIdLessThan ());
     165  if (torrentIt == myTorrents.end ())
     166    return;
     167
     168  const int row = torrentIt - myTorrents.begin ();
     169  const QModelIndex qmi (index (row, 0));
     170
     171  emit dataChanged (qmi, qmi);
    125172}
    126173
     
    141188TorrentModel::updateTorrents (tr_variant * torrents, bool isCompleteList)
    142189{
    143   QList<Torrent*> newTorrents;
     190  torrents_t newTorrents;
    144191  QSet<int> oldIds;
    145192  QSet<int> addIds;
    146193  QSet<int> newIds;
    147194
    148   if  (isCompleteList)
     195  if (isCompleteList)
    149196    oldIds = getIds ();
    150197
     
    158205          if (tr_variantDictFindInt (child, TR_KEY_id, &id))
    159206            {
    160               newIds.insert (id);
     207              if (isCompleteList)
     208                newIds.insert (id);
    161209
    162210              Torrent * tor = getTorrentFromId (id);
     
    184232
    185233  if (!newTorrents.isEmpty ())
    186     {
    187       const int oldCount (rowCount ());
    188       const int newCount (oldCount + newTorrents.size ());
    189       QSet<int> ids;
    190 
    191       beginInsertRows (QModelIndex(), oldCount, newCount - 1);
    192 
    193       for (Torrent * const tor: newTorrents)
    194         {
    195           addTorrent (tor);
    196           addIds.insert (tor->id ());
    197         }
    198 
    199       endInsertRows ();
    200     }
     234    addTorrents (std::move (newTorrents), addIds);
    201235
    202236  if (!addIds.isEmpty())
     
    215249TorrentModel::removeTorrent (int id)
    216250{
    217   const int row = myIdToRow.value (id, -1);
    218   if (row >= 0)
    219     {
    220       Torrent * tor = myIdToTorrent.value (id, 0);
    221 
    222       beginRemoveRows (QModelIndex(), row, row);
    223       // make the myIdToRow map consistent with list view/model
    224       for (auto i = myIdToRow.begin(); i != myIdToRow.end(); ++i)
    225         if (i.value() > row)
    226           --i.value();
    227       myIdToRow.remove (id);
    228       myIdToTorrent.remove (id);
    229       myTorrents.remove (myTorrents.indexOf (tor));
    230       endRemoveRows ();
    231 
    232       delete tor;
    233     }
     251  const torrents_t::iterator torrentIt = qBinaryFind (myTorrents.begin (), myTorrents.end (), id, TorrentIdLessThan ());
     252  if (torrentIt == myTorrents.end ())
     253    return;
     254
     255  Torrent * const tor = *torrentIt;
     256  const int row = torrentIt - myTorrents.begin ();
     257
     258  beginRemoveRows (QModelIndex(), row, row);
     259  myTorrents.remove (row);
     260  endRemoveRows ();
     261
     262  delete tor;
    234263}
    235264
  • trunk/qt/TorrentModel.h

    r14724 r14736  
    1111
    1212#include <QAbstractListModel>
    13 #include <QMap>
    1413#include <QSet>
    1514#include <QVector>
     
    6059
    6160  private:
    62     typedef QMap<int, int> id_to_row_t;
    63     typedef QMap<int, Torrent*> id_to_torrent_t;
    6461    typedef QVector<Torrent*> torrents_t;
    6562
    6663  private:
    6764    void addTorrent (Torrent *);
     65    void addTorrents (torrents_t&& torrents, QSet<int>& addIds);
    6866    QSet<int> getIds () const;
    6967
     
    7472    const Prefs& myPrefs;
    7573
    76     id_to_row_t myIdToRow;
    77     id_to_torrent_t myIdToTorrent;
    7874    torrents_t myTorrents;
    7975};
Note: See TracChangeset for help on using the changeset viewer.