Changeset 14557


Ignore:
Timestamp:
Aug 10, 2015, 7:40:58 PM (8 years ago)
Author:
mikedld
Message:

#5608: Enter file renaming mode with keyboard only, not on mouse double-click (Qt client)

Since double-click is usually used to open things, don't use it to enter
edit mode, use platform-specific keyboard shortcut instead (Return, F2,
etc).
Add context menu duplicating available actions, resembling that of Mac
client. This includes new "only check selected" action.
Speed up DND/priority change for large numbers of files at once. Make
DND/priority toggling more natural: if both parent and its child are
selected, only act on parent (with all its children following).

Location:
trunk/qt
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/qt/DetailsDialog.ui

    r14541 r14557  
    586586          <enum>Qt::ScrollBarAlwaysOff</enum>
    587587         </property>
     588         <property name="editTriggers">
     589          <set>QAbstractItemView::EditKeyPressed</set>
     590         </property>
    588591         <property name="alternatingRowColors">
    589592          <bool>true</bool>
     
    594597         <property name="verticalScrollMode">
    595598          <enum>QAbstractItemView::ScrollPerPixel</enum>
     599         </property>
     600         <property name="uniformRowHeights">
     601          <bool>true</bool>
    596602         </property>
    597603         <property name="sortingEnabled">
  • trunk/qt/FileTreeItem.cc

    r14551 r14557  
    305305}
    306306
    307 void
    308 FileTreeItem::twiddlePriority (QSet<int>& ids, int& p)
    309 {
    310   const int old(priority());
    311 
    312   if (old & LOW)
    313     p = TR_PRI_NORMAL;
    314   else if (old & NORMAL)
    315     p = TR_PRI_HIGH;
    316   else
    317     p = TR_PRI_LOW;
    318 
    319   setSubtreePriority (p, ids);
    320 }
    321 
    322307int
    323308FileTreeItem::isSubtreeWanted () const
     
    357342  for (FileTreeItem * const child: myChildren)
    358343    child->setSubtreeWanted (b, ids);
    359 }
    360 
    361 void
    362 FileTreeItem::twiddleWanted (QSet<int>& ids, bool& wanted)
    363 {
    364   wanted = isSubtreeWanted() != Qt::Checked;
    365   setSubtreeWanted (wanted, ids);
    366344}
    367345
  • trunk/qt/FileTreeItem.h

    r14541 r14557  
    2626
    2727  public:
     28    enum
     29    {
     30      LOW    = (1 << 0),
     31      NORMAL = (1 << 1),
     32      HIGH   = (1 << 2)
     33    };
     34
     35  public:
    2836    FileTreeItem (const QString& name = QString (), int fileIndex = -1, uint64_t size = 0):
    2937      myName (name),
     
    4856    QVariant data (int column, int role) const;
    4957    std::pair<int, int> update (const QString& name, bool want, int priority, uint64_t have, bool updateFields);
    50     void twiddleWanted (QSet<int>& fileIds, bool&);
    51     void twiddlePriority (QSet<int>& fileIds, int&);
     58    void setSubtreeWanted (bool, QSet<int>& fileIds);
     59    void setSubtreePriority (int priority, QSet<int>& fileIds);
    5260    int fileIndex () const { return myFileIndex; }
    5361    uint64_t totalSize () const { return myTotalSize; }
    5462    QString path () const;
    5563    bool isComplete () const;
     64    int priority () const;
     65    int isSubtreeWanted () const;
    5666
    5767  private:
    58     enum
    59     {
    60       LOW    = (1 << 0),
    61       NORMAL = (1 << 1),
    62       HIGH   = (1 << 2)
    63     };
    64 
    65   private:
    66     void setSubtreePriority (int priority, QSet<int>& fileIds);
    67     void setSubtreeWanted (bool, QSet<int>& fileIds);
    6868    QString priorityString () const;
    6969    QString sizeString () const;
    7070    void getSubtreeWantedSize (uint64_t& have, uint64_t& total) const;
    7171    double progress () const;
    72     int priority () const;
    7372    uint64_t size () const;
    74     int isSubtreeWanted () const;
    7573    const QHash<QString,int>& getMyChildRows();
    7674
  • trunk/qt/FileTreeModel.cc

    r14551 r14557  
    1010#include <cassert>
    1111
     12#include <libtransmission/transmission.h> // priorities
     13
    1214#include "FileTreeItem.h"
    1315#include "FileTreeModel.h"
     
    109111FileTreeModel::itemFromIndex (const QModelIndex& index) const
    110112{
     113  if (!index.isValid())
     114    return nullptr;
     115
     116  assert (index.model () == this);
    111117  return static_cast<FileTreeItem*>(index.internalPointer());
     118}
     119
     120QModelIndexList
     121FileTreeModel::getOrphanIndices (const QModelIndexList& indices) const
     122{
     123  QModelIndexList orphanIndices = indices;
     124
     125  qSort (orphanIndices);
     126
     127  for (QMutableListIterator<QModelIndex> it (orphanIndices); it.hasNext ();)
     128    {
     129      QModelIndex walk = it.next ();
     130
     131      for (;;)
     132        {
     133          walk = parent (walk, walk.column ());
     134          if (!walk.isValid ())
     135            break;
     136
     137          if (qBinaryFind (orphanIndices, walk) != orphanIndices.end ())
     138            {
     139              it.remove ();
     140              break;
     141            }
     142        }
     143    }
     144
     145  return orphanIndices;
    112146}
    113147
     
    314348          if (changed.first >= 0)
    315349            {
    316               dataChanged (indexOf (item, changed.first), indexOf (item, changed.second));
     350              emit dataChanged (indexOf (item, changed.first), indexOf (item, changed.second));
    317351              if (!indexWithChangedParents.isValid () &&
    318352                  changed.first <= COL_PRIORITY && changed.second >= COL_SIZE)
     
    323357      assert (item == myRootItem);
    324358      if (indexWithChangedParents.isValid ())
    325         parentsChanged (indexWithChangedParents, COL_SIZE, COL_PRIORITY);
     359        emitParentsChanged (indexWithChangedParents, COL_SIZE, COL_PRIORITY);
    326360    }
    327361  else // we haven't build the FileTreeItems for these tokens yet
     
    361395          const std::pair<int,int> changed = item->update (item->name(), wanted, priority, have, added || updateFields);
    362396          if (changed.first >= 0)
    363             dataChanged (indexOf (item, changed.first), indexOf (item, changed.second));
     397            emit dataChanged (indexOf (item, changed.first), indexOf (item, changed.second));
    364398        }
    365399    }
     
    367401
    368402void
    369 FileTreeModel::parentsChanged (const QModelIndex& index, int firstColumn, int lastColumn)
     403FileTreeModel::emitParentsChanged (const QModelIndex& index, int firstColumn, int lastColumn, QSet<QModelIndex> * visitedParentIndices)
    370404{
    371405  assert (firstColumn <= lastColumn);
     
    379413        break;
    380414
    381       dataChanged (walk, walk.sibling (walk.row (), lastColumn));
    382     }
    383 }
    384 
    385 void
    386 FileTreeModel::subtreeChanged (const QModelIndex& index, int firstColumn, int lastColumn)
     415      if (visitedParentIndices != nullptr)
     416        {
     417          if (visitedParentIndices->contains (walk))
     418            break;
     419          visitedParentIndices->insert (walk);
     420        }
     421
     422      emit dataChanged (walk, walk.sibling (walk.row (), lastColumn));
     423    }
     424}
     425
     426void
     427FileTreeModel::emitSubtreeChanged (const QModelIndex& index, int firstColumn, int lastColumn)
    387428{
    388429  assert (firstColumn <= lastColumn);
     
    392433    return;
    393434
    394   // tell everyone that this tier changed
    395   dataChanged (index.child (0, firstColumn), index.child (childCount - 1, lastColumn));
    396 
    397   // walk the subtiers
     435  // tell everyone that this item changed
     436  emit dataChanged (index.child (0, firstColumn), index.child (childCount - 1, lastColumn));
     437
     438  // walk the subitems
    398439  for (int i=0; i<childCount; ++i)
    399     subtreeChanged (index.child (i, 0), firstColumn, lastColumn);
    400 }
    401 
    402 void
    403 FileTreeModel::clicked (const QModelIndex& index)
    404 {
    405   const int column (index.column());
    406 
    407   if (!index.isValid())
     440    emitSubtreeChanged (index.child (i, 0), firstColumn, lastColumn);
     441}
     442
     443void
     444FileTreeModel::twiddleWanted (const QModelIndexList& indices)
     445{
     446  QMap<bool, QModelIndexList> wantedIndices;
     447  for (const QModelIndex& i: getOrphanIndices (indices))
     448    {
     449      const FileTreeItem * const item = itemFromIndex (i);
     450      wantedIndices[item->isSubtreeWanted () != Qt::Checked] << i;
     451    }
     452
     453  for (int i = 0; i <= 1; ++i)
     454    {
     455      if (wantedIndices.contains (i))
     456        setWanted (wantedIndices[i], i != 0);
     457    }
     458}
     459
     460void
     461FileTreeModel::twiddlePriority (const QModelIndexList& indices)
     462{
     463  QMap<int, QModelIndexList> priorityIndices;
     464  for (const QModelIndex& i: getOrphanIndices (indices))
     465    {
     466      const FileTreeItem * const item = itemFromIndex (i);
     467      int priority = item->priority ();
     468
     469      // ... -> normal -> high -> low -> normal -> ...; mixed -> normal
     470      if (priority == FileTreeItem::NORMAL)
     471        priority = TR_PRI_HIGH;
     472      else if (priority == FileTreeItem::HIGH)
     473        priority = TR_PRI_LOW;
     474      else
     475        priority = TR_PRI_NORMAL;
     476
     477      priorityIndices[priority] << i;
     478    }
     479
     480  for (int i = TR_PRI_LOW; i <= TR_PRI_HIGH; ++i)
     481    {
     482      if (priorityIndices.contains (i))
     483        setPriority (priorityIndices[i], i);
     484    }
     485}
     486
     487void
     488FileTreeModel::setWanted (const QModelIndexList& indices, bool wanted)
     489{
     490  if (indices.isEmpty ())
    408491    return;
    409492
    410   if (column == COL_WANTED)
    411     {
    412       bool want;
    413       QSet<int> file_ids;
    414       FileTreeItem * item;
    415 
    416       item = itemFromIndex (index);
    417       item->twiddleWanted (file_ids, want);
    418       emit wantedChanged (file_ids, want);
    419 
    420       dataChanged (index, index);
    421       parentsChanged (index, COL_SIZE, COL_WANTED);
    422       subtreeChanged (index, COL_WANTED, COL_WANTED);
    423     }
    424   else if (column == COL_PRIORITY)
    425     {
    426       int priority;
    427       QSet<int> file_ids;
    428       FileTreeItem * item;
    429 
    430       item = itemFromIndex (index);
    431       item->twiddlePriority (file_ids, priority);
    432       emit priorityChanged (file_ids, priority);
    433 
    434       dataChanged (index, index);
    435       parentsChanged (index, column, column);
    436       subtreeChanged (index, column, column);
    437     }
    438 }
    439 
    440 void
    441 FileTreeModel::doubleClicked (const QModelIndex& index)
    442 {
    443   if (!index.isValid())
     493  const QModelIndexList orphanIndices = getOrphanIndices (indices);
     494
     495  QSet<int> fileIds;
     496  for (const QModelIndex& i: orphanIndices)
     497    {
     498      FileTreeItem * const item = itemFromIndex (i);
     499      item->setSubtreeWanted (wanted, fileIds);
     500
     501      emit dataChanged (i, i);
     502      emitSubtreeChanged (i, COL_WANTED, COL_WANTED);
     503    }
     504
     505  // emit parent changes separately to avoid multiple updates for same items
     506  QSet<QModelIndex> parentIndices;
     507  for (const QModelIndex& i: orphanIndices)
     508    emitParentsChanged (i, COL_SIZE, COL_WANTED, &parentIndices);
     509
     510  if (!fileIds.isEmpty ())
     511    emit wantedChanged (fileIds, wanted);
     512}
     513
     514void
     515FileTreeModel::setPriority (const QModelIndexList& indices, int priority)
     516{
     517  if (indices.isEmpty ())
    444518    return;
    445519
    446   const int column (index.column());
    447   if (column == COL_WANTED || column == COL_PRIORITY)
    448     return;
    449 
    450   FileTreeItem * item = itemFromIndex (index);
    451 
    452   if (item->childCount () == 0 && item->isComplete ())
    453     emit openRequested (item->path ());
    454 }
     520  const QModelIndexList orphanIndices = getOrphanIndices (indices);
     521
     522  QSet<int> fileIds;
     523  for (const QModelIndex& i: orphanIndices)
     524    {
     525      FileTreeItem * const item = itemFromIndex (i);
     526      item->setSubtreePriority (priority, fileIds);
     527
     528      emit dataChanged (i, i);
     529      emitSubtreeChanged (i, COL_PRIORITY, COL_PRIORITY);
     530    }
     531
     532  // emit parent changes separately to avoid multiple updates for same items
     533  QSet<QModelIndex> parentIndices;
     534  for (const QModelIndex& i: orphanIndices)
     535    emitParentsChanged (i, COL_PRIORITY, COL_PRIORITY, &parentIndices);
     536
     537  if (!fileIds.isEmpty ())
     538    emit priorityChanged (fileIds, priority);
     539}
     540
     541bool
     542FileTreeModel::openFile (const QModelIndex& index)
     543{
     544  if (!index.isValid ())
     545    return false;
     546
     547  FileTreeItem * const item = itemFromIndex (index);
     548  if (item->childCount () != 0 || !item->isComplete ())
     549    return false;
     550
     551  emit openRequested (item->path ());
     552  return true;
     553}
  • trunk/qt/FileTreeModel.h

    r14551 r14557  
    5656                  bool torrentChanged);
    5757
     58    bool openFile (const QModelIndex& index);
     59
     60    void twiddleWanted (const QModelIndexList& indices);
     61    void twiddlePriority (const QModelIndexList& indices);
     62
     63    void setWanted (const QModelIndexList& indices, bool wanted);
     64    void setPriority (const QModelIndexList& indices, int priority);
     65
    5866    QModelIndex parent (const QModelIndex& child, int column) const;
    5967
     
    6876    virtual bool setData (const QModelIndex& index, const QVariant& value, int role = Qt::EditRole);
    6977
    70   public slots:
    71     void clicked (const QModelIndex& index);
    72     void doubleClicked (const QModelIndex& index);
    73 
    7478  signals:
    7579    void priorityChanged (const QSet<int>& fileIndices, int);
     
    8185    void clearSubtree (const QModelIndex&);
    8286    QModelIndex indexOf (FileTreeItem *, int column) const;
    83     void parentsChanged (const QModelIndex&, int firstColumn, int lastColumn);
    84     void subtreeChanged (const QModelIndex&, int firstColumn, int lastColumn);
     87    void emitParentsChanged (const QModelIndex&, int firstColumn, int lastColumn, QSet<QModelIndex> * visitedParentIndices = nullptr);
     88    void emitSubtreeChanged (const QModelIndex&, int firstColumn, int lastColumn);
    8589    FileTreeItem * findItemForFileIndex (int fileIndex) const;
    8690    FileTreeItem * itemFromIndex (const QModelIndex&) const;
     91    QModelIndexList getOrphanIndices (const QModelIndexList& indices) const;
    8792
    8893  private:
  • trunk/qt/FileTreeView.cc

    r14551 r14557  
    99
    1010#include <algorithm>
     11#include <cassert>
    1112
    1213#include <QHeaderView>
     14#include <QMenu>
     15#include <QQueue>
    1316#include <QResizeEvent>
    1417#include <QSortFilterProxyModel>
     18
     19#include <libtransmission/transmission.h> // priorities
    1520
    1621#include "FileTreeDelegate.h"
     
    2126#include "Utils.h"
    2227
     28#define PRIORITY_KEY "priority"
     29
    2330FileTreeView::FileTreeView (QWidget * parent, bool isEditable):
    2431  QTreeView (parent),
     
    4148           this, SLOT(onClicked(QModelIndex)));
    4249
    43   connect (this, SIGNAL(doubleClicked(QModelIndex)),
    44            this, SLOT(onDoubleClicked(QModelIndex)));
    45 
    4650  connect (myModel, SIGNAL(priorityChanged(QSet<int>, int)),
    4751           this,    SIGNAL(priorityChanged(QSet<int>, int)));
     
    5458
    5559  connect (myModel, SIGNAL (openRequested (QString)),
    56            this,    SLOT (onOpenRequested (QString)),
    57            Qt::QueuedConnection);
     60           this,    SIGNAL (openRequested (QString)));
    5861}
    5962
     
    6265{
    6366  const QModelIndex modelIndex = myProxy->mapToSource (proxyIndex);
    64   myModel->clicked (modelIndex);
    65 }
    66 
    67 void
    68 FileTreeView::onDoubleClicked (const QModelIndex& proxyIndex)
    69 {
    70   const QModelIndex modelIndex = myProxy->mapToSource (proxyIndex);
    71   myModel->doubleClicked (modelIndex);
    72 }
    73 
    74 void
    75 FileTreeView::onOpenRequested (const QString& path)
    76 {
    77   if (state () == EditingState)
    78     return;
    79 
    80   emit openRequested (path);
     67  if (modelIndex.column () == FileTreeModel::COL_WANTED)
     68    myModel->twiddleWanted (QModelIndexList () << modelIndex);
     69  else if (modelIndex.column () == FileTreeModel::COL_PRIORITY)
     70    myModel->twiddlePriority (QModelIndexList () << modelIndex);
    8171}
    8272
     
    142132FileTreeView::keyPressEvent (QKeyEvent * event)
    143133{
     134  if (state () != EditingState)
     135    {
     136      if (event->key () == Qt::Key_Space)
     137        {
     138          // handle using the keyboard to toggle the
     139          // wanted/unwanted state or the file priority
     140
     141          const Qt::KeyboardModifiers modifiers = event->modifiers ();
     142
     143          if (modifiers == Qt::NoModifier)
     144            {
     145              myModel->twiddleWanted (selectedSourceRows ());
     146              return;
     147            }
     148
     149          if (modifiers == Qt::ShiftModifier)
     150            {
     151              myModel->twiddlePriority (selectedSourceRows ());
     152              return;
     153            }
     154        }
     155    }
     156
    144157  QTreeView::keyPressEvent (event);
    145 
    146   // handle using the keyboard to toggle the
    147   // wanted/unwanted state or the file priority
    148 
    149   if (state () == EditingState)
     158}
     159
     160void
     161FileTreeView::mouseDoubleClickEvent (QMouseEvent * event)
     162{
     163  const QModelIndex index = currentIndex ();
     164  if (!index.isValid () || index.column () == FileTreeModel::COL_WANTED || index.column () == FileTreeModel::COL_PRIORITY)
    150165    return;
    151166
    152   if (event->key () == Qt::Key_Space)
    153     {
    154       int column;
    155 
    156       const Qt::KeyboardModifiers modifiers = event->modifiers ();
    157       if (modifiers == Qt::NoModifier)
    158         column = FileTreeModel::COL_WANTED;
    159       else if (modifiers == Qt::ShiftModifier)
    160         column = FileTreeModel::COL_PRIORITY;
    161       else
    162         return;
    163 
    164       for (const QModelIndex& i: selectionModel ()->selectedRows (column))
    165         clicked (i);
    166     }
     167  if (openSelectedItem ())
     168    return;
     169
     170  QTreeView::mouseDoubleClickEvent (event);
     171}
     172
     173void
     174FileTreeView::contextMenuEvent (QContextMenuEvent * event)
     175{
     176  const QModelIndex rootIndex = myModel->index (0, 0);
     177  if (!rootIndex.isValid ())
     178    return;
     179
     180  if (myContextMenu == nullptr)
     181    initContextMenu ();
     182  myContextMenu->popup (event->globalPos ());
    167183}
    168184
     
    214230  myModel->setEditable (editable);
    215231}
     232
     233bool
     234FileTreeView::edit (const QModelIndex& index, EditTrigger trigger, QEvent * event)
     235{
     236  if (selectionModel ()->selectedRows ().size () != 1)
     237    return false;
     238
     239  const QModelIndex nameIndex = index.sibling (index.row (), FileTreeModel::COL_NAME);
     240  if (editTriggers ().testFlag (trigger))
     241    selectionModel ()->setCurrentIndex (nameIndex, QItemSelectionModel::NoUpdate);
     242
     243  return QTreeView::edit (nameIndex, trigger, event);
     244}
     245
     246void
     247FileTreeView::checkSelectedItems ()
     248{
     249  myModel->setWanted (selectedSourceRows (), true);
     250}
     251
     252void
     253FileTreeView::uncheckSelectedItems ()
     254{
     255  myModel->setWanted (selectedSourceRows (), false);
     256}
     257
     258void
     259FileTreeView::onlyCheckSelectedItems ()
     260{
     261  const QModelIndex rootIndex = myModel->index (0, FileTreeModel::COL_WANTED);
     262  if (!rootIndex.isValid ())
     263    return;
     264
     265  QModelIndexList wantedIndices = selectedSourceRows (FileTreeModel::COL_WANTED);
     266  myModel->setWanted (wantedIndices, true);
     267
     268  qSort (wantedIndices);
     269
     270  QSet<QModelIndex> wantedIndicesParents;
     271  for (const QModelIndex& i: wantedIndices)
     272    {
     273      for (QModelIndex p = i.parent (); p.isValid (); p = p.parent ())
     274        wantedIndicesParents.insert (p.sibling (p.row (), FileTreeModel::COL_WANTED));
     275    }
     276
     277  QQueue<QModelIndex> parentsQueue;
     278  parentsQueue.enqueue (rootIndex);
     279  QModelIndexList unwantedIndices;
     280  while (!parentsQueue.isEmpty ())
     281    {
     282      const QModelIndex parentIndex = parentsQueue.dequeue ();
     283      if (qBinaryFind (wantedIndices, parentIndex) != wantedIndices.end ())
     284        continue;
     285
     286      for (int i = 0, count = myModel->rowCount (parentIndex); i < count; ++i)
     287        {
     288          const QModelIndex childIndex = parentIndex.child (i, FileTreeModel::COL_WANTED);
     289          const int childCheckState = childIndex.data ().toInt ();
     290          if (childCheckState == Qt::Unchecked || qBinaryFind (wantedIndices, childIndex) != wantedIndices.end ())
     291            continue;
     292
     293          if (childCheckState == Qt::Checked &&
     294              childIndex.sibling (childIndex.row (), FileTreeModel::COL_FILE_INDEX).data ().toInt () >= 0)
     295            {
     296              unwantedIndices << childIndex;
     297            }
     298          else
     299            {
     300              if (!wantedIndicesParents.contains (childIndex))
     301                unwantedIndices << childIndex;
     302              else
     303                parentsQueue.enqueue (childIndex);
     304            }
     305        }
     306    }
     307
     308  myModel->setWanted (unwantedIndices, false);
     309}
     310
     311void
     312FileTreeView::setSelectedItemsPriority ()
     313{
     314  QAction * action = qobject_cast<QAction *> (sender ());
     315  assert (action != nullptr);
     316  myModel->setPriority (selectedSourceRows (), action->property (PRIORITY_KEY).toInt ());
     317}
     318
     319bool
     320FileTreeView::openSelectedItem ()
     321{
     322  return myModel->openFile (myProxy->mapToSource (currentIndex ()));
     323}
     324
     325void
     326FileTreeView::renameSelectedItem ()
     327{
     328  QTreeView::edit (currentIndex ());
     329}
     330
     331void
     332FileTreeView::refreshContextMenuActionsSensitivity ()
     333{
     334  assert (myContextMenu != nullptr);
     335
     336  const QModelIndexList selectedRows = selectionModel ()->selectedRows (FileTreeModel::COL_WANTED);
     337
     338  QSet<int> checkStates;
     339  for (const QModelIndex& i: selectedRows)
     340    {
     341      checkStates.insert (i.data ().toInt ());
     342      if (checkStates.size() == 3)
     343        break;
     344    }
     345
     346  const bool haveSelection = !selectedRows.isEmpty ();
     347  const bool haveSingleSelection = selectedRows.size() == 1;
     348  const bool haveUnchecked = checkStates.contains (Qt::Unchecked) || checkStates.contains (Qt::PartiallyChecked);
     349  const bool haveChecked = checkStates.contains (Qt::Checked) || checkStates.contains (Qt::PartiallyChecked);
     350
     351  myCheckSelectedAction->setEnabled (haveUnchecked);
     352  myUncheckSelectedAction->setEnabled (haveChecked);
     353  myOnlyCheckSelectedAction->setEnabled (haveSelection);
     354  myPriorityMenu->setEnabled (haveSelection);
     355  myOpenAction->setEnabled (haveSingleSelection && myProxy->rowCount (selectedRows.first ()) == 0);
     356  myRenameAction->setEnabled (haveSingleSelection);
     357}
     358
     359void
     360FileTreeView::initContextMenu ()
     361{
     362  myContextMenu = new QMenu (this);
     363
     364  myCheckSelectedAction = myContextMenu->addAction (tr ("Check selected"), this, SLOT (checkSelectedItems ()));
     365  myUncheckSelectedAction = myContextMenu->addAction (tr ("Uncheck selected"), this, SLOT (uncheckSelectedItems ()));
     366  myOnlyCheckSelectedAction = myContextMenu->addAction (tr ("Only check selected"), this, SLOT (onlyCheckSelectedItems ()));
     367
     368  myContextMenu->addSeparator ();
     369
     370  myPriorityMenu = myContextMenu->addMenu (tr ("Priority"));
     371  myHighPriorityAction = myPriorityMenu->addAction (FileTreeItem::tr ("High"), this, SLOT (setSelectedItemsPriority ()));
     372  myNormalPriorityAction = myPriorityMenu->addAction (FileTreeItem::tr ("Normal"), this, SLOT (setSelectedItemsPriority ()));
     373  myLowPriorityAction = myPriorityMenu->addAction (FileTreeItem::tr ("Low"), this, SLOT (setSelectedItemsPriority ()));
     374
     375  myHighPriorityAction->setProperty (PRIORITY_KEY, TR_PRI_HIGH);
     376  myNormalPriorityAction->setProperty (PRIORITY_KEY, TR_PRI_NORMAL);
     377  myLowPriorityAction->setProperty (PRIORITY_KEY, TR_PRI_LOW);
     378
     379  myContextMenu->addSeparator ();
     380
     381  myOpenAction = myContextMenu->addAction (tr ("Open"), this, SLOT (openSelectedItem ()));
     382  myRenameAction = myContextMenu->addAction (tr ("Rename..."), this, SLOT (renameSelectedItem ()));
     383
     384  connect (myContextMenu, SIGNAL (aboutToShow ()), SLOT (refreshContextMenuActionsSensitivity ()));
     385}
     386
     387QModelIndexList
     388FileTreeView::selectedSourceRows (int column) const
     389{
     390  QModelIndexList indices;
     391  for (const QModelIndex& i: selectionModel ()->selectedRows (column))
     392    indices << myProxy->mapToSource (i);
     393  return indices;
     394}
  • trunk/qt/FileTreeView.h

    r14541 r14557  
    1616#include "Torrent.h" // FileList
    1717
     18class QAction;
     19class QMenu;
    1820class QSortFilterProxyModel;
    1921
     
    3335    void setEditable (bool editable);
    3436
    35   public slots:
    36     void onClicked (const QModelIndex& index);
    37     void onDoubleClicked (const QModelIndex& index);
    38     void onOpenRequested (const QString& path);
    39 
    4037  signals:
    4138    void priorityChanged (const QSet<int>& fileIndices, int priority);
     
    4845    virtual void resizeEvent (QResizeEvent * event);
    4946    virtual void keyPressEvent (QKeyEvent * event);
     47    virtual void mouseDoubleClickEvent (QMouseEvent * event);
     48    virtual void contextMenuEvent (QContextMenuEvent * event);
     49
     50    // QAbstractItemView
     51    virtual bool edit (const QModelIndex& index, EditTrigger trigger, QEvent * event);
     52
     53  private slots:
     54    void onClicked (const QModelIndex& index);
     55
     56    void checkSelectedItems ();
     57    void uncheckSelectedItems ();
     58    void onlyCheckSelectedItems ();
     59    void setSelectedItemsPriority ();
     60    bool openSelectedItem ();
     61    void renameSelectedItem ();
     62
     63    void refreshContextMenuActionsSensitivity ();
     64    QModelIndexList selectedSourceRows (int column = 0) const;
     65
     66  private:
     67    void initContextMenu ();
    5068
    5169  private:
     
    5371    QSortFilterProxyModel * myProxy;
    5472    FileTreeDelegate * myDelegate;
     73
     74    QMenu * myContextMenu = nullptr;
     75    QMenu * myPriorityMenu = nullptr;
     76    QAction * myCheckSelectedAction = nullptr;
     77    QAction * myUncheckSelectedAction = nullptr;
     78    QAction * myOnlyCheckSelectedAction = nullptr;
     79    QAction * myHighPriorityAction = nullptr;
     80    QAction * myNormalPriorityAction = nullptr;
     81    QAction * myLowPriorityAction = nullptr;
     82    QAction * myOpenAction = nullptr;
     83    QAction * myRenameAction = nullptr;
    5584};
    5685
Note: See TracChangeset for help on using the changeset viewer.