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:
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;
|
QVariant value;
|
||||||
|
|
||||||
if (column == FileTreeModel::COL_FILE_INDEX)
|
switch (role)
|
||||||
{
|
{
|
||||||
value.setValue (myFileIndex);
|
case FileTreeModel::FileIndexRole:
|
||||||
}
|
value.setValue (myFileIndex);
|
||||||
else if (role == Qt::EditRole)
|
break;
|
||||||
{
|
|
||||||
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::COL_SIZE:
|
case FileTreeModel::WantedRole:
|
||||||
if (role == Qt::DisplayRole)
|
value.setValue (isSubtreeWanted ());
|
||||||
value.setValue (sizeString());
|
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
|
else
|
||||||
value.setValue<quint64> (size ());
|
value = Utils::guessMimeIcon (name ());
|
||||||
break;
|
}
|
||||||
|
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 ());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
|
|
|
@ -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 ());
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Add table
Reference in a new issue