1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2025-03-04 10:38:13 +00:00

Simplify and speed up actions connected to file tree popup menu

This commit is contained in:
Mike Gelfand 2015-08-16 22:07:09 +00:00
parent 7f45029f18
commit 63e4700a10
5 changed files with 113 additions and 81 deletions

View file

@ -94,21 +94,32 @@ FileTreeItem::data (int column, int role) const
{ {
QVariant value; QVariant value;
if (column == FileTreeModel::COL_FILE_INDEX) switch (role)
{ {
case FileTreeModel::FileIndexRole:
value.setValue (myFileIndex); value.setValue (myFileIndex);
} break;
else if (role == Qt::EditRole)
{ case FileTreeModel::WantedRole:
if (column == 0) value.setValue (isSubtreeWanted ());
break;
case FileTreeModel::CompleteRole:
value.setValue (isComplete ());
break;
case Qt::EditRole:
if (column == FileTreeModel::COL_NAME)
value.setValue (name ()); value.setValue (name ());
} break;
else if ((role == Qt::TextAlignmentRole) && column == FileTreeModel::COL_SIZE)
{ case Qt::TextAlignmentRole:
if (column == FileTreeModel::COL_SIZE)
value = Qt::AlignRight + Qt::AlignVCenter; value = Qt::AlignRight + Qt::AlignVCenter;
} break;
else if (role == Qt::DisplayRole || role == FileTreeModel::SortRole)
{ case Qt::DisplayRole:
case FileTreeModel::SortRole:
switch (column) switch (column)
{ {
case FileTreeModel::COL_NAME: case FileTreeModel::COL_NAME:
@ -137,14 +148,18 @@ FileTreeItem::data (int column, int role) const
value.setValue (priority ()); value.setValue (priority ());
break; break;
} }
} break;
else if (role == Qt::DecorationRole && column == FileTreeModel::COL_NAME)
case Qt::DecorationRole:
if (column == FileTreeModel::COL_NAME)
{ {
if (childCount () > 0) if (myFileIndex < 0)
value = qApp->style ()->standardIcon (QStyle::SP_DirOpenIcon); value = qApp->style ()->standardIcon (QStyle::SP_DirOpenIcon);
else else
value = Utils::guessMimeIcon (name ()); value = Utils::guessMimeIcon (name ());
} }
break;
}
return value; return value;
} }

View file

@ -545,7 +545,7 @@ FileTreeModel::openFile (const QModelIndex& index)
return false; return false;
FileTreeItem * const item = itemFromIndex (index); FileTreeItem * const item = itemFromIndex (index);
if (item->childCount () != 0 || !item->isComplete ()) if (item->fileIndex () < 0 || !item->isComplete ())
return false; return false;
emit openRequested (item->path ()); emit openRequested (item->path ());

View file

@ -27,20 +27,20 @@ class FileTreeModel: public QAbstractItemModel
enum enum
{ {
COL_NAME, COL_NAME,
FIRST_VISIBLE_COLUMN = COL_NAME,
COL_SIZE, COL_SIZE,
COL_PROGRESS, COL_PROGRESS,
COL_WANTED, COL_WANTED,
COL_PRIORITY, COL_PRIORITY,
LAST_VISIBLE_COLUMN = COL_PRIORITY,
COL_FILE_INDEX,
NUM_COLUMNS NUM_COLUMNS
}; };
enum Role enum Role
{ {
SortRole = Qt::UserRole SortRole = Qt::UserRole,
FileIndexRole,
WantedRole,
CompleteRole
}; };
public: public:

View file

@ -41,9 +41,6 @@ FileTreeView::FileTreeView (QWidget * parent, bool isEditable):
setItemDelegate (myDelegate); setItemDelegate (myDelegate);
sortByColumn (FileTreeModel::COL_NAME, Qt::AscendingOrder); sortByColumn (FileTreeModel::COL_NAME, Qt::AscendingOrder);
for (int i=0; i<FileTreeModel::NUM_COLUMNS; ++i)
setColumnHidden (i, (i<FileTreeModel::FIRST_VISIBLE_COLUMN) || (FileTreeModel::LAST_VISIBLE_COLUMN<i));
connect (this, SIGNAL(clicked(QModelIndex)), connect (this, SIGNAL(clicked(QModelIndex)),
this, SLOT(onClicked(QModelIndex))); this, SLOT(onClicked(QModelIndex)));
@ -80,12 +77,10 @@ FileTreeView::resizeEvent (QResizeEvent * event)
// space is left over... // space is left over...
int left = event->size ().width () - 1; int left = event->size ().width () - 1;
for (int column = FileTreeModel::FIRST_VISIBLE_COLUMN; column <= FileTreeModel::LAST_VISIBLE_COLUMN; ++column) for (int column = 0; column < FileTreeModel::NUM_COLUMNS; ++column)
{ {
if (column == FileTreeModel::COL_NAME) if (column == FileTreeModel::COL_NAME)
continue; continue;
if (isColumnHidden (column))
continue;
int minWidth = 0; int minWidth = 0;
@ -258,11 +253,11 @@ FileTreeView::uncheckSelectedItems ()
void void
FileTreeView::onlyCheckSelectedItems () FileTreeView::onlyCheckSelectedItems ()
{ {
const QModelIndex rootIndex = myModel->index (0, FileTreeModel::COL_WANTED); const QModelIndex rootIndex = myModel->index (0, 0);
if (!rootIndex.isValid ()) if (!rootIndex.isValid ())
return; return;
QModelIndexList wantedIndices = selectedSourceRows (FileTreeModel::COL_WANTED); QModelIndexList wantedIndices = selectedSourceRows ();
myModel->setWanted (wantedIndices, true); myModel->setWanted (wantedIndices, true);
qSort (wantedIndices); qSort (wantedIndices);
@ -271,7 +266,7 @@ FileTreeView::onlyCheckSelectedItems ()
for (const QModelIndex& i: wantedIndices) for (const QModelIndex& i: wantedIndices)
{ {
for (QModelIndex p = i.parent (); p.isValid (); p = p.parent ()) for (QModelIndex p = i.parent (); p.isValid (); p = p.parent ())
wantedIndicesParents.insert (p.sibling (p.row (), FileTreeModel::COL_WANTED)); wantedIndicesParents.insert (p);
} }
QQueue<QModelIndex> parentsQueue; QQueue<QModelIndex> parentsQueue;
@ -285,13 +280,12 @@ FileTreeView::onlyCheckSelectedItems ()
for (int i = 0, count = myModel->rowCount (parentIndex); i < count; ++i) for (int i = 0, count = myModel->rowCount (parentIndex); i < count; ++i)
{ {
const QModelIndex childIndex = parentIndex.child (i, FileTreeModel::COL_WANTED); const QModelIndex childIndex = parentIndex.child (i, 0);
const int childCheckState = childIndex.data ().toInt (); const int childCheckState = childIndex.data (FileTreeModel::WantedRole).toInt ();
if (childCheckState == Qt::Unchecked || qBinaryFind (wantedIndices, childIndex) != wantedIndices.end ()) if (childCheckState == Qt::Unchecked || qBinaryFind (wantedIndices, childIndex) != wantedIndices.end ())
continue; continue;
if (childCheckState == Qt::Checked && if (childCheckState == Qt::Checked && childIndex.data (FileTreeModel::FileIndexRole).toInt () >= 0)
childIndex.sibling (childIndex.row (), FileTreeModel::COL_FILE_INDEX).data ().toInt () >= 0)
{ {
unwantedIndices << childIndex; unwantedIndices << childIndex;
} }
@ -333,26 +327,21 @@ FileTreeView::refreshContextMenuActionsSensitivity ()
{ {
assert (myContextMenu != nullptr); assert (myContextMenu != nullptr);
const QModelIndexList selectedRows = selectionModel ()->selectedRows (FileTreeModel::COL_WANTED); const QModelIndexList selectedRows = selectionModel ()->selectedRows ();
const Qt::CheckState checkState = getCumulativeCheckState (selectedRows);
QSet<int> checkStates;
for (const QModelIndex& i: selectedRows)
{
checkStates.insert (i.data ().toInt ());
if (checkStates.size() == 3)
break;
}
const bool haveSelection = !selectedRows.isEmpty (); const bool haveSelection = !selectedRows.isEmpty ();
const bool haveSingleSelection = selectedRows.size() == 1; const bool haveSingleSelection = selectedRows.size() == 1;
const bool haveUnchecked = checkStates.contains (Qt::Unchecked) || checkStates.contains (Qt::PartiallyChecked); const bool haveUnchecked = checkState == Qt::Unchecked || checkState == Qt::PartiallyChecked;
const bool haveChecked = checkStates.contains (Qt::Checked) || checkStates.contains (Qt::PartiallyChecked); const bool haveChecked = checkState == Qt::Checked || checkState == Qt::PartiallyChecked;
myCheckSelectedAction->setEnabled (haveUnchecked); myCheckSelectedAction->setEnabled (haveUnchecked);
myUncheckSelectedAction->setEnabled (haveChecked); myUncheckSelectedAction->setEnabled (haveChecked);
myOnlyCheckSelectedAction->setEnabled (haveSelection); myOnlyCheckSelectedAction->setEnabled (haveSelection);
myPriorityMenu->setEnabled (haveSelection); myPriorityMenu->setEnabled (haveSelection);
myOpenAction->setEnabled (haveSingleSelection && myProxy->rowCount (selectedRows.first ()) == 0); myOpenAction->setEnabled (haveSingleSelection &&
selectedRows.first ().data (FileTreeModel::FileIndexRole).toInt () >= 0 &&
selectedRows.first ().data (FileTreeModel::CompleteRole).toBool ());
myRenameAction->setEnabled (haveSingleSelection); myRenameAction->setEnabled (haveSingleSelection);
} }
@ -361,9 +350,9 @@ FileTreeView::initContextMenu ()
{ {
myContextMenu = new QMenu (this); myContextMenu = new QMenu (this);
myCheckSelectedAction = myContextMenu->addAction (tr ("Check selected"), this, SLOT (checkSelectedItems ())); myCheckSelectedAction = myContextMenu->addAction (tr ("Check Selected"), this, SLOT (checkSelectedItems ()));
myUncheckSelectedAction = myContextMenu->addAction (tr ("Uncheck selected"), this, SLOT (uncheckSelectedItems ())); myUncheckSelectedAction = myContextMenu->addAction (tr ("Uncheck Selected"), this, SLOT (uncheckSelectedItems ()));
myOnlyCheckSelectedAction = myContextMenu->addAction (tr ("Only check selected"), this, SLOT (onlyCheckSelectedItems ())); myOnlyCheckSelectedAction = myContextMenu->addAction (tr ("Only Check Selected"), this, SLOT (onlyCheckSelectedItems ()));
myContextMenu->addSeparator (); myContextMenu->addSeparator ();
@ -392,3 +381,29 @@ FileTreeView::selectedSourceRows (int column) const
indices << myProxy->mapToSource (i); indices << myProxy->mapToSource (i);
return indices; return indices;
} }
Qt::CheckState
FileTreeView::getCumulativeCheckState (const QModelIndexList& indices)
{
bool haveChecked = false, haveUnchecked = false;
for (const QModelIndex& i: indices)
{
switch (i.data (FileTreeModel::WantedRole).toInt ())
{
case Qt::Checked:
haveChecked = true;
break;
case Qt::Unchecked:
haveUnchecked = true;
break;
case Qt::PartiallyChecked:
return Qt::PartiallyChecked;
}
if (haveChecked && haveUnchecked)
return Qt::PartiallyChecked;
}
return haveChecked ? Qt::Checked : Qt::Unchecked;
}

View file

@ -61,10 +61,12 @@ class FileTreeView: public QTreeView
void renameSelectedItem (); void renameSelectedItem ();
void refreshContextMenuActionsSensitivity (); void refreshContextMenuActionsSensitivity ();
QModelIndexList selectedSourceRows (int column = 0) const;
private: private:
void initContextMenu (); void initContextMenu ();
QModelIndexList selectedSourceRows (int column = 0) const;
static Qt::CheckState getCumulativeCheckState (const QModelIndexList& indices);
private: private:
FileTreeModel * myModel; FileTreeModel * myModel;