mirror of
https://github.com/transmission/transmission
synced 2025-03-04 02:28:03 +00:00
Simplify and speed up actions connected to file tree popup menu
This commit is contained in:
parent
7f45029f18
commit
63e4700a10
5 changed files with 113 additions and 81 deletions
|
@ -94,56 +94,71 @@ FileTreeItem::data (int column, int role) const
|
|||
{
|
||||
QVariant value;
|
||||
|
||||
if (column == FileTreeModel::COL_FILE_INDEX)
|
||||
switch (role)
|
||||
{
|
||||
value.setValue (myFileIndex);
|
||||
}
|
||||
else if (role == Qt::EditRole)
|
||||
{
|
||||
if (column == 0)
|
||||
value.setValue (name());
|
||||
}
|
||||
else if ((role == Qt::TextAlignmentRole) && column == FileTreeModel::COL_SIZE)
|
||||
{
|
||||
value = Qt::AlignRight + Qt::AlignVCenter;
|
||||
}
|
||||
else if (role == Qt::DisplayRole || role == FileTreeModel::SortRole)
|
||||
{
|
||||
switch(column)
|
||||
{
|
||||
case FileTreeModel::COL_NAME:
|
||||
value.setValue (name());
|
||||
break;
|
||||
case FileTreeModel::FileIndexRole:
|
||||
value.setValue (myFileIndex);
|
||||
break;
|
||||
|
||||
case FileTreeModel::COL_SIZE:
|
||||
if (role == Qt::DisplayRole)
|
||||
value.setValue (sizeString());
|
||||
case FileTreeModel::WantedRole:
|
||||
value.setValue (isSubtreeWanted ());
|
||||
break;
|
||||
|
||||
case FileTreeModel::CompleteRole:
|
||||
value.setValue (isComplete ());
|
||||
break;
|
||||
|
||||
case Qt::EditRole:
|
||||
if (column == FileTreeModel::COL_NAME)
|
||||
value.setValue (name ());
|
||||
break;
|
||||
|
||||
case Qt::TextAlignmentRole:
|
||||
if (column == FileTreeModel::COL_SIZE)
|
||||
value = Qt::AlignRight + Qt::AlignVCenter;
|
||||
break;
|
||||
|
||||
case Qt::DisplayRole:
|
||||
case FileTreeModel::SortRole:
|
||||
switch (column)
|
||||
{
|
||||
case FileTreeModel::COL_NAME:
|
||||
value.setValue (name ());
|
||||
break;
|
||||
|
||||
case FileTreeModel::COL_SIZE:
|
||||
if (role == Qt::DisplayRole)
|
||||
value.setValue (sizeString ());
|
||||
else
|
||||
value.setValue<quint64> (size ());
|
||||
break;
|
||||
|
||||
case FileTreeModel::COL_PROGRESS:
|
||||
value.setValue (progress ());
|
||||
break;
|
||||
|
||||
case FileTreeModel::COL_WANTED:
|
||||
value.setValue (isSubtreeWanted ());
|
||||
break;
|
||||
|
||||
case FileTreeModel::COL_PRIORITY:
|
||||
if (role == Qt::DisplayRole)
|
||||
value.setValue (priorityString ());
|
||||
else
|
||||
value.setValue (priority ());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case Qt::DecorationRole:
|
||||
if (column == FileTreeModel::COL_NAME)
|
||||
{
|
||||
if (myFileIndex < 0)
|
||||
value = qApp->style ()->standardIcon (QStyle::SP_DirOpenIcon);
|
||||
else
|
||||
value.setValue<quint64> (size ());
|
||||
break;
|
||||
|
||||
case FileTreeModel::COL_PROGRESS:
|
||||
value.setValue (progress());
|
||||
break;
|
||||
|
||||
case FileTreeModel::COL_WANTED:
|
||||
value.setValue (isSubtreeWanted());
|
||||
break;
|
||||
|
||||
case FileTreeModel::COL_PRIORITY:
|
||||
if (role == Qt::DisplayRole)
|
||||
value.setValue (priorityString());
|
||||
else
|
||||
value.setValue (priority ());
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (role == Qt::DecorationRole && column == FileTreeModel::COL_NAME)
|
||||
{
|
||||
if (childCount () > 0)
|
||||
value = qApp->style ()->standardIcon (QStyle::SP_DirOpenIcon);
|
||||
else
|
||||
value = Utils::guessMimeIcon (name ());
|
||||
value = Utils::guessMimeIcon (name ());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return value;
|
||||
|
|
|
@ -545,7 +545,7 @@ FileTreeModel::openFile (const QModelIndex& index)
|
|||
return false;
|
||||
|
||||
FileTreeItem * const item = itemFromIndex (index);
|
||||
if (item->childCount () != 0 || !item->isComplete ())
|
||||
if (item->fileIndex () < 0 || !item->isComplete ())
|
||||
return false;
|
||||
|
||||
emit openRequested (item->path ());
|
||||
|
|
|
@ -27,20 +27,20 @@ class FileTreeModel: public QAbstractItemModel
|
|||
enum
|
||||
{
|
||||
COL_NAME,
|
||||
FIRST_VISIBLE_COLUMN = COL_NAME,
|
||||
COL_SIZE,
|
||||
COL_PROGRESS,
|
||||
COL_WANTED,
|
||||
COL_PRIORITY,
|
||||
LAST_VISIBLE_COLUMN = COL_PRIORITY,
|
||||
|
||||
COL_FILE_INDEX,
|
||||
NUM_COLUMNS
|
||||
};
|
||||
|
||||
enum Role
|
||||
{
|
||||
SortRole = Qt::UserRole
|
||||
SortRole = Qt::UserRole,
|
||||
FileIndexRole,
|
||||
WantedRole,
|
||||
CompleteRole
|
||||
};
|
||||
|
||||
public:
|
||||
|
|
|
@ -41,9 +41,6 @@ FileTreeView::FileTreeView (QWidget * parent, bool isEditable):
|
|||
setItemDelegate (myDelegate);
|
||||
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)),
|
||||
this, SLOT(onClicked(QModelIndex)));
|
||||
|
||||
|
@ -80,12 +77,10 @@ FileTreeView::resizeEvent (QResizeEvent * event)
|
|||
// space is left over...
|
||||
|
||||
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)
|
||||
continue;
|
||||
if (isColumnHidden (column))
|
||||
continue;
|
||||
|
||||
int minWidth = 0;
|
||||
|
||||
|
@ -258,11 +253,11 @@ FileTreeView::uncheckSelectedItems ()
|
|||
void
|
||||
FileTreeView::onlyCheckSelectedItems ()
|
||||
{
|
||||
const QModelIndex rootIndex = myModel->index (0, FileTreeModel::COL_WANTED);
|
||||
const QModelIndex rootIndex = myModel->index (0, 0);
|
||||
if (!rootIndex.isValid ())
|
||||
return;
|
||||
|
||||
QModelIndexList wantedIndices = selectedSourceRows (FileTreeModel::COL_WANTED);
|
||||
QModelIndexList wantedIndices = selectedSourceRows ();
|
||||
myModel->setWanted (wantedIndices, true);
|
||||
|
||||
qSort (wantedIndices);
|
||||
|
@ -271,7 +266,7 @@ FileTreeView::onlyCheckSelectedItems ()
|
|||
for (const QModelIndex& i: wantedIndices)
|
||||
{
|
||||
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;
|
||||
|
@ -285,13 +280,12 @@ FileTreeView::onlyCheckSelectedItems ()
|
|||
|
||||
for (int i = 0, count = myModel->rowCount (parentIndex); i < count; ++i)
|
||||
{
|
||||
const QModelIndex childIndex = parentIndex.child (i, FileTreeModel::COL_WANTED);
|
||||
const int childCheckState = childIndex.data ().toInt ();
|
||||
const QModelIndex childIndex = parentIndex.child (i, 0);
|
||||
const int childCheckState = childIndex.data (FileTreeModel::WantedRole).toInt ();
|
||||
if (childCheckState == Qt::Unchecked || qBinaryFind (wantedIndices, childIndex) != wantedIndices.end ())
|
||||
continue;
|
||||
|
||||
if (childCheckState == Qt::Checked &&
|
||||
childIndex.sibling (childIndex.row (), FileTreeModel::COL_FILE_INDEX).data ().toInt () >= 0)
|
||||
if (childCheckState == Qt::Checked && childIndex.data (FileTreeModel::FileIndexRole).toInt () >= 0)
|
||||
{
|
||||
unwantedIndices << childIndex;
|
||||
}
|
||||
|
@ -333,26 +327,21 @@ FileTreeView::refreshContextMenuActionsSensitivity ()
|
|||
{
|
||||
assert (myContextMenu != nullptr);
|
||||
|
||||
const QModelIndexList selectedRows = selectionModel ()->selectedRows (FileTreeModel::COL_WANTED);
|
||||
|
||||
QSet<int> checkStates;
|
||||
for (const QModelIndex& i: selectedRows)
|
||||
{
|
||||
checkStates.insert (i.data ().toInt ());
|
||||
if (checkStates.size() == 3)
|
||||
break;
|
||||
}
|
||||
const QModelIndexList selectedRows = selectionModel ()->selectedRows ();
|
||||
const Qt::CheckState checkState = getCumulativeCheckState (selectedRows);
|
||||
|
||||
const bool haveSelection = !selectedRows.isEmpty ();
|
||||
const bool haveSingleSelection = selectedRows.size() == 1;
|
||||
const bool haveUnchecked = checkStates.contains (Qt::Unchecked) || checkStates.contains (Qt::PartiallyChecked);
|
||||
const bool haveChecked = checkStates.contains (Qt::Checked) || checkStates.contains (Qt::PartiallyChecked);
|
||||
const bool haveUnchecked = checkState == Qt::Unchecked || checkState == Qt::PartiallyChecked;
|
||||
const bool haveChecked = checkState == Qt::Checked || checkState == Qt::PartiallyChecked;
|
||||
|
||||
myCheckSelectedAction->setEnabled (haveUnchecked);
|
||||
myUncheckSelectedAction->setEnabled (haveChecked);
|
||||
myOnlyCheckSelectedAction->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);
|
||||
}
|
||||
|
||||
|
@ -361,9 +350,9 @@ FileTreeView::initContextMenu ()
|
|||
{
|
||||
myContextMenu = new QMenu (this);
|
||||
|
||||
myCheckSelectedAction = myContextMenu->addAction (tr ("Check selected"), this, SLOT (checkSelectedItems ()));
|
||||
myUncheckSelectedAction = myContextMenu->addAction (tr ("Uncheck selected"), this, SLOT (uncheckSelectedItems ()));
|
||||
myOnlyCheckSelectedAction = myContextMenu->addAction (tr ("Only check selected"), this, SLOT (onlyCheckSelectedItems ()));
|
||||
myCheckSelectedAction = myContextMenu->addAction (tr ("Check Selected"), this, SLOT (checkSelectedItems ()));
|
||||
myUncheckSelectedAction = myContextMenu->addAction (tr ("Uncheck Selected"), this, SLOT (uncheckSelectedItems ()));
|
||||
myOnlyCheckSelectedAction = myContextMenu->addAction (tr ("Only Check Selected"), this, SLOT (onlyCheckSelectedItems ()));
|
||||
|
||||
myContextMenu->addSeparator ();
|
||||
|
||||
|
@ -392,3 +381,29 @@ FileTreeView::selectedSourceRows (int column) const
|
|||
indices << myProxy->mapToSource (i);
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -61,10 +61,12 @@ class FileTreeView: public QTreeView
|
|||
void renameSelectedItem ();
|
||||
|
||||
void refreshContextMenuActionsSensitivity ();
|
||||
QModelIndexList selectedSourceRows (int column = 0) const;
|
||||
|
||||
private:
|
||||
void initContextMenu ();
|
||||
QModelIndexList selectedSourceRows (int column = 0) const;
|
||||
|
||||
static Qt::CheckState getCumulativeCheckState (const QModelIndexList& indices);
|
||||
|
||||
private:
|
||||
FileTreeModel * myModel;
|
||||
|
|
Loading…
Add table
Reference in a new issue