Browse Source

Avoid creating unnecessary event loops

The `exec()` method will create another event loop and transfer
control over there which might introduce unexpected bugs.
adaptive-webui-19844
Chocobo1 6 years ago
parent
commit
3748b995ff
No known key found for this signature in database
GPG Key ID: 210D9C873253A68C
  1. 79
      src/gui/addnewtorrentdialog.cpp
  2. 25
      src/gui/categoryfilterwidget.cpp
  3. 2
      src/gui/categoryfilterwidget.h
  4. 7
      src/gui/fspathedit_p.cpp
  5. 12
      src/gui/mainwindow.cpp
  6. 2
      src/gui/mainwindow.h
  7. 7
      src/gui/optionsdialog.cpp
  8. 83
      src/gui/properties/peerlistwidget.cpp
  9. 151
      src/gui/properties/propertieswidget.cpp
  10. 4
      src/gui/properties/propertieswidget.h
  11. 5
      src/gui/properties/speedwidget.cpp
  12. 89
      src/gui/properties/trackerlistwidget.cpp
  13. 2
      src/gui/properties/trackerlistwidget.h
  14. 43
      src/gui/rss/automatedrssdownloader.cpp
  15. 62
      src/gui/rss/rsswidget.cpp
  16. 17
      src/gui/search/pluginselectdialog.cpp
  17. 2
      src/gui/search/pluginselectdialog.h
  18. 4
      src/gui/search/searchjobwidget.cpp
  19. 19
      src/gui/tagfilterwidget.cpp
  20. 29
      src/gui/transferlistfilterswidget.cpp
  21. 6
      src/gui/transferlistfilterswidget.h
  22. 269
      src/gui/transferlistwidget.cpp

79
src/gui/addnewtorrentdialog.cpp

@ -457,42 +457,57 @@ void AddNewTorrentDialog::populateSavePathComboBox()
void AddNewTorrentDialog::displayContentTreeMenu(const QPoint &) void AddNewTorrentDialog::displayContentTreeMenu(const QPoint &)
{ {
QMenu myFilesLlistMenu;
const QModelIndexList selectedRows = m_ui->contentTreeView->selectionModel()->selectedRows(0); const QModelIndexList selectedRows = m_ui->contentTreeView->selectionModel()->selectedRows(0);
QAction *actRename = nullptr;
if (selectedRows.size() == 1) { const auto applyPriorities = [this, selectedRows](const BitTorrent::DownloadPriority prio)
actRename = myFilesLlistMenu.addAction(GuiIconProvider::instance()->getIcon("edit-rename"), tr("Rename...")); {
myFilesLlistMenu.addSeparator();
}
QMenu subMenu;
subMenu.setTitle(tr("Priority"));
subMenu.addAction(m_ui->actionNotDownloaded);
subMenu.addAction(m_ui->actionNormal);
subMenu.addAction(m_ui->actionHigh);
subMenu.addAction(m_ui->actionMaximum);
myFilesLlistMenu.addMenu(&subMenu);
// Call menu
QAction *act = myFilesLlistMenu.exec(QCursor::pos());
if (act) {
if (act == actRename) {
m_ui->contentTreeView->renameSelectedFile(m_torrentInfo);
}
else {
BitTorrent::DownloadPriority prio = BitTorrent::DownloadPriority::Normal;
if (act == m_ui->actionHigh)
prio = BitTorrent::DownloadPriority::High;
else if (act == m_ui->actionMaximum)
prio = BitTorrent::DownloadPriority::Maximum;
else if (act == m_ui->actionNotDownloaded)
prio = BitTorrent::DownloadPriority::Ignored;
qDebug("Setting files priority");
for (const QModelIndex &index : selectedRows) { for (const QModelIndex &index : selectedRows) {
qDebug("Setting priority(%d) for file at row %d", static_cast<int>(prio), index.row()); m_contentModel->setData(
m_contentModel->setData(m_contentModel->index(index.row(), PRIORITY, index.parent()), static_cast<int>(prio)); m_contentModel->index(index.row(), PRIORITY, index.parent())
} , static_cast<int>(prio));
} }
};
QMenu *menu = new QMenu(this);
menu->setAttribute(Qt::WA_DeleteOnClose);
if (selectedRows.size() == 1) {
QAction *actRename = menu->addAction(GuiIconProvider::instance()->getIcon("edit-rename"), tr("Rename..."));
connect(actRename, &QAction::triggered, this, [this]() { m_ui->contentTreeView->renameSelectedFile(m_torrentInfo); });
menu->addSeparator();
} }
QMenu *subMenu = new QMenu(menu);
subMenu->setTitle(tr("Priority"));
connect(m_ui->actionNotDownloaded, &QAction::triggered, subMenu, [applyPriorities]()
{
applyPriorities(BitTorrent::DownloadPriority::Ignored);
});
subMenu->addAction(m_ui->actionNotDownloaded);
connect(m_ui->actionNormal, &QAction::triggered, subMenu, [applyPriorities]()
{
applyPriorities(BitTorrent::DownloadPriority::Normal);
});
subMenu->addAction(m_ui->actionNormal);
connect(m_ui->actionHigh, &QAction::triggered, subMenu, [applyPriorities]()
{
applyPriorities(BitTorrent::DownloadPriority::High);
});
subMenu->addAction(m_ui->actionHigh);
connect(m_ui->actionMaximum, &QAction::triggered, subMenu, [applyPriorities]()
{
applyPriorities(BitTorrent::DownloadPriority::Maximum);
});
subMenu->addAction(m_ui->actionMaximum);
menu->addMenu(subMenu);
menu->popup(QCursor::pos());
} }
void AddNewTorrentDialog::accept() void AddNewTorrentDialog::accept()

25
src/gui/categoryfilterwidget.cpp

@ -104,11 +104,12 @@ void CategoryFilterWidget::onCurrentRowChanged(const QModelIndex &current, const
emit categoryChanged(getCategoryFilter(static_cast<CategoryFilterProxyModel *>(model()), current)); emit categoryChanged(getCategoryFilter(static_cast<CategoryFilterProxyModel *>(model()), current));
} }
void CategoryFilterWidget::showMenu(QPoint) void CategoryFilterWidget::showMenu(const QPoint &)
{ {
QMenu menu(this); QMenu *menu = new QMenu(this);
menu->setAttribute(Qt::WA_DeleteOnClose);
QAction *addAct = menu.addAction( const QAction *addAct = menu->addAction(
GuiIconProvider::instance()->getIcon("list-add") GuiIconProvider::instance()->getIcon("list-add")
, tr("Add category...")); , tr("Add category..."));
connect(addAct, &QAction::triggered, this, &CategoryFilterWidget::addCategory); connect(addAct, &QAction::triggered, this, &CategoryFilterWidget::addCategory);
@ -116,46 +117,46 @@ void CategoryFilterWidget::showMenu(QPoint)
const auto selectedRows = selectionModel()->selectedRows(); const auto selectedRows = selectionModel()->selectedRows();
if (!selectedRows.empty() && !CategoryFilterModel::isSpecialItem(selectedRows.first())) { if (!selectedRows.empty() && !CategoryFilterModel::isSpecialItem(selectedRows.first())) {
if (BitTorrent::Session::instance()->isSubcategoriesEnabled()) { if (BitTorrent::Session::instance()->isSubcategoriesEnabled()) {
QAction *addSubAct = menu.addAction( const QAction *addSubAct = menu->addAction(
GuiIconProvider::instance()->getIcon("list-add") GuiIconProvider::instance()->getIcon("list-add")
, tr("Add subcategory...")); , tr("Add subcategory..."));
connect(addSubAct, &QAction::triggered, this, &CategoryFilterWidget::addSubcategory); connect(addSubAct, &QAction::triggered, this, &CategoryFilterWidget::addSubcategory);
} }
QAction *editAct = menu.addAction( const QAction *editAct = menu->addAction(
GuiIconProvider::instance()->getIcon("document-edit") GuiIconProvider::instance()->getIcon("document-edit")
, tr("Edit category...")); , tr("Edit category..."));
connect(editAct, &QAction::triggered, this, &CategoryFilterWidget::editCategory); connect(editAct, &QAction::triggered, this, &CategoryFilterWidget::editCategory);
QAction *removeAct = menu.addAction( const QAction *removeAct = menu->addAction(
GuiIconProvider::instance()->getIcon("list-remove") GuiIconProvider::instance()->getIcon("list-remove")
, tr("Remove category")); , tr("Remove category"));
connect(removeAct, &QAction::triggered, this, &CategoryFilterWidget::removeCategory); connect(removeAct, &QAction::triggered, this, &CategoryFilterWidget::removeCategory);
} }
QAction *removeUnusedAct = menu.addAction( const QAction *removeUnusedAct = menu->addAction(
GuiIconProvider::instance()->getIcon("list-remove") GuiIconProvider::instance()->getIcon("list-remove")
, tr("Remove unused categories")); , tr("Remove unused categories"));
connect(removeUnusedAct, &QAction::triggered, this, &CategoryFilterWidget::removeUnusedCategories); connect(removeUnusedAct, &QAction::triggered, this, &CategoryFilterWidget::removeUnusedCategories);
menu.addSeparator(); menu->addSeparator();
QAction *startAct = menu.addAction( const QAction *startAct = menu->addAction(
GuiIconProvider::instance()->getIcon("media-playback-start") GuiIconProvider::instance()->getIcon("media-playback-start")
, tr("Resume torrents")); , tr("Resume torrents"));
connect(startAct, &QAction::triggered, this, &CategoryFilterWidget::actionResumeTorrentsTriggered); connect(startAct, &QAction::triggered, this, &CategoryFilterWidget::actionResumeTorrentsTriggered);
QAction *pauseAct = menu.addAction( const QAction *pauseAct = menu->addAction(
GuiIconProvider::instance()->getIcon("media-playback-pause") GuiIconProvider::instance()->getIcon("media-playback-pause")
, tr("Pause torrents")); , tr("Pause torrents"));
connect(pauseAct, &QAction::triggered, this, &CategoryFilterWidget::actionPauseTorrentsTriggered); connect(pauseAct, &QAction::triggered, this, &CategoryFilterWidget::actionPauseTorrentsTriggered);
QAction *deleteTorrentsAct = menu.addAction( const QAction *deleteTorrentsAct = menu->addAction(
GuiIconProvider::instance()->getIcon("edit-delete") GuiIconProvider::instance()->getIcon("edit-delete")
, tr("Delete torrents")); , tr("Delete torrents"));
connect(deleteTorrentsAct, &QAction::triggered, this, &CategoryFilterWidget::actionDeleteTorrentsTriggered); connect(deleteTorrentsAct, &QAction::triggered, this, &CategoryFilterWidget::actionDeleteTorrentsTriggered);
menu.exec(QCursor::pos()); menu->popup(QCursor::pos());
} }
void CategoryFilterWidget::callUpdateGeometry() void CategoryFilterWidget::callUpdateGeometry()

2
src/gui/categoryfilterwidget.h

@ -48,7 +48,7 @@ signals:
private slots: private slots:
void onCurrentRowChanged(const QModelIndex &current, const QModelIndex &previous); void onCurrentRowChanged(const QModelIndex &current, const QModelIndex &previous);
void showMenu(QPoint); void showMenu(const QPoint &);
void callUpdateGeometry(); void callUpdateGeometry();
void addCategory(); void addCategory();
void addSubcategory(); void addSubcategory();

7
src/gui/fspathedit_p.cpp

@ -284,13 +284,14 @@ void Private::FileLineEdit::keyPressEvent(QKeyEvent *e)
void Private::FileLineEdit::contextMenuEvent(QContextMenuEvent *event) void Private::FileLineEdit::contextMenuEvent(QContextMenuEvent *event)
{ {
QMenu *menu = createStandardContextMenu(); QMenu *menu = createStandardContextMenu();
menu->addSeparator(); menu->setAttribute(Qt::WA_DeleteOnClose);
if (m_browseAction) { if (m_browseAction) {
menu->addSeparator(); menu->addSeparator();
menu->addAction(m_browseAction); menu->addAction(m_browseAction);
} }
menu->exec(event->globalPos());
delete menu; menu->popup(event->globalPos());
} }
void Private::FileLineEdit::showCompletionPopup() void Private::FileLineEdit::showCompletionPopup()

12
src/gui/mainwindow.cpp

@ -578,12 +578,14 @@ void MainWindow::addToolbarContextMenu()
void MainWindow::manageCookies() void MainWindow::manageCookies()
{ {
CookiesDialog(this).exec(); auto *cookieDialog = new CookiesDialog(this);
cookieDialog->setAttribute(Qt::WA_DeleteOnClose);
cookieDialog->open();
} }
void MainWindow::toolbarMenuRequested(QPoint point) void MainWindow::toolbarMenuRequested(const QPoint &point)
{ {
m_toolbarMenu->exec(m_ui->toolBar->mapToGlobal(point)); m_toolbarMenu->popup(m_ui->toolBar->mapToGlobal(point));
} }
void MainWindow::toolbarIconsOnly() void MainWindow::toolbarIconsOnly()
@ -688,7 +690,9 @@ void MainWindow::showFilterContextMenu(const QPoint &)
const Preferences *pref = Preferences::instance(); const Preferences *pref = Preferences::instance();
QMenu *menu = m_searchFilter->createStandardContextMenu(); QMenu *menu = m_searchFilter->createStandardContextMenu();
menu->setAttribute(Qt::WA_DeleteOnClose);
menu->addSeparator(); menu->addSeparator();
QAction *useRegexAct = new QAction(tr("Use regular expressions"), menu); QAction *useRegexAct = new QAction(tr("Use regular expressions"), menu);
useRegexAct->setCheckable(true); useRegexAct->setCheckable(true);
useRegexAct->setChecked(pref->getRegexAsFilteringPatternForTransferList()); useRegexAct->setChecked(pref->getRegexAsFilteringPatternForTransferList());
@ -697,7 +701,7 @@ void MainWindow::showFilterContextMenu(const QPoint &)
connect(useRegexAct, &QAction::toggled, pref, &Preferences::setRegexAsFilteringPatternForTransferList); connect(useRegexAct, &QAction::toggled, pref, &Preferences::setRegexAsFilteringPatternForTransferList);
connect(useRegexAct, &QAction::toggled, this, [this]() { m_transferListWidget->applyNameFilter(m_searchFilter->text()); }); connect(useRegexAct, &QAction::toggled, this, [this]() { m_transferListWidget->applyNameFilter(m_searchFilter->text()); });
menu->exec(QCursor::pos()); menu->popup(QCursor::pos());
} }
void MainWindow::displaySearchTab(bool enable) void MainWindow::displaySearchTab(bool enable)

2
src/gui/mainwindow.h

@ -181,7 +181,7 @@ private slots:
#if defined(Q_OS_WIN) || defined(Q_OS_MAC) #if defined(Q_OS_WIN) || defined(Q_OS_MAC)
void checkProgramUpdate(); void checkProgramUpdate();
#endif #endif
void toolbarMenuRequested(QPoint); void toolbarMenuRequested(const QPoint &point);
void toolbarIconsOnly(); void toolbarIconsOnly();
void toolbarTextOnly(); void toolbarTextOnly();
void toolbarTextBeside(); void toolbarTextBeside();

7
src/gui/optionsdialog.cpp

@ -423,7 +423,12 @@ OptionsDialog::OptionsDialog(QWidget *parent)
connect(m_ui->checkSmartFilterDownloadRepacks, &QCheckBox::toggled, this, &OptionsDialog::enableApplyButton); connect(m_ui->checkSmartFilterDownloadRepacks, &QCheckBox::toggled, this, &OptionsDialog::enableApplyButton);
connect(m_ui->spinRSSRefreshInterval, qSpinBoxValueChanged, this, &OptionsDialog::enableApplyButton); connect(m_ui->spinRSSRefreshInterval, qSpinBoxValueChanged, this, &OptionsDialog::enableApplyButton);
connect(m_ui->spinRSSMaxArticlesPerFeed, qSpinBoxValueChanged, this, &OptionsDialog::enableApplyButton); connect(m_ui->spinRSSMaxArticlesPerFeed, qSpinBoxValueChanged, this, &OptionsDialog::enableApplyButton);
connect(m_ui->btnEditRules, &QPushButton::clicked, this, [this]() { AutomatedRssDownloader(this).exec(); }); connect(m_ui->btnEditRules, &QPushButton::clicked, this, [this]()
{
auto *downloader = new AutomatedRssDownloader(this);
downloader->setAttribute(Qt::WA_DeleteOnClose);
downloader->open();
});
// Disable apply Button // Disable apply Button
m_applyButton->setEnabled(false); m_applyButton->setEnabled(false);

83
src/gui/properties/peerlistwidget.cpp

@ -153,19 +153,22 @@ PeerListWidget::~PeerListWidget()
void PeerListWidget::displayToggleColumnsMenu(const QPoint &) void PeerListWidget::displayToggleColumnsMenu(const QPoint &)
{ {
QMenu hideshowColumn(this); QMenu *menu = new QMenu(this);
hideshowColumn.setTitle(tr("Column visibility")); menu->setAttribute(Qt::WA_DeleteOnClose);
QList<QAction *> actions; menu->setTitle(tr("Column visibility"));
for (int i = 0; i < PeerListDelegate::IP_HIDDEN; ++i) { for (int i = 0; i < PeerListDelegate::IP_HIDDEN; ++i) {
if ((i == PeerListDelegate::COUNTRY) && !Preferences::instance()->resolvePeerCountries()) { if ((i == PeerListDelegate::COUNTRY) && !Preferences::instance()->resolvePeerCountries())
actions.append(nullptr); // keep the index in sync
continue; continue;
}
QAction *myAct = hideshowColumn.addAction(m_listModel->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString()); QAction *myAct = menu->addAction(m_listModel->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString());
myAct->setCheckable(true); myAct->setCheckable(true);
myAct->setChecked(!isColumnHidden(i)); myAct->setChecked(!isColumnHidden(i));
actions.append(myAct); myAct->setData(i);
} }
connect(menu, &QMenu::triggered, this, [this](const QAction *action)
{
int visibleCols = 0; int visibleCols = 0;
for (int i = 0; i < PeerListDelegate::IP_HIDDEN; ++i) { for (int i = 0; i < PeerListDelegate::IP_HIDDEN; ++i) {
if (!isColumnHidden(i)) if (!isColumnHidden(i))
@ -175,19 +178,20 @@ void PeerListWidget::displayToggleColumnsMenu(const QPoint &)
break; break;
} }
// Call menu const int col = action->data().toInt();
QAction *act = hideshowColumn.exec(QCursor::pos());
if (act) {
int col = actions.indexOf(act);
Q_ASSERT(col >= 0);
Q_ASSERT(visibleCols > 0);
if (!isColumnHidden(col) && (visibleCols == 1)) if (!isColumnHidden(col) && (visibleCols == 1))
return; return;
setColumnHidden(col, !isColumnHidden(col)); setColumnHidden(col, !isColumnHidden(col));
if (!isColumnHidden(col) && (columnWidth(col) <= 5)) if (!isColumnHidden(col) && (columnWidth(col) <= 5))
resizeColumnToContents(col); resizeColumnToContents(col);
saveSettings(); saveSettings();
} });
menu->popup(QCursor::pos());
} }
void PeerListWidget::updatePeerHostNameResolutionState() void PeerListWidget::updatePeerHostNameResolutionState()
@ -222,35 +226,21 @@ void PeerListWidget::updatePeerCountryResolutionState()
void PeerListWidget::showPeerListMenu(const QPoint &) void PeerListWidget::showPeerListMenu(const QPoint &)
{ {
QMenu menu;
bool emptyMenu = true;
BitTorrent::TorrentHandle *const torrent = m_properties->getCurrentTorrent(); BitTorrent::TorrentHandle *const torrent = m_properties->getCurrentTorrent();
if (!torrent) return; if (!torrent) return;
QMenu *menu = new QMenu(this);
menu->setAttribute(Qt::WA_DeleteOnClose);
// Add Peer Action // Add Peer Action
QAction *addPeerAct = nullptr;
if (!torrent->isQueued() && !torrent->isChecking()) { if (!torrent->isQueued() && !torrent->isChecking()) {
addPeerAct = menu.addAction(GuiIconProvider::instance()->getIcon("user-group-new"), tr("Add a new peer...")); const QAction *addPeerAct = menu->addAction(GuiIconProvider::instance()->getIcon("user-group-new"), tr("Add a new peer..."));
emptyMenu = false; connect(addPeerAct, &QAction::triggered, this, [this, torrent]()
} {
QAction *banAct = nullptr;
QAction *copyPeerAct = nullptr;
if (!selectionModel()->selectedRows().isEmpty()) {
copyPeerAct = menu.addAction(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy IP:port"));
menu.addSeparator();
banAct = menu.addAction(GuiIconProvider::instance()->getIcon("user-group-delete"), tr("Ban peer permanently"));
emptyMenu = false;
}
if (emptyMenu) return;
QAction *act = menu.exec(QCursor::pos());
if (!act) return;
if (act == addPeerAct) {
const QList<BitTorrent::PeerAddress> peersList = PeersAdditionDialog::askForPeers(this); const QList<BitTorrent::PeerAddress> peersList = PeersAdditionDialog::askForPeers(this);
int peerCount = 0; int peerCount = 0;
for (const BitTorrent::PeerAddress &addr : peersList) { for (const BitTorrent::PeerAddress &addr : peersList) {
if (torrent->connectPeer(addr)) { if (torrent->connectPeer(addr)) {
qDebug("Adding peer %s...", qUtf8Printable(addr.ip.toString()));
Logger::instance()->addMessage(tr("Manually adding peer '%1'...").arg(addr.ip.toString())); Logger::instance()->addMessage(tr("Manually adding peer '%1'...").arg(addr.ip.toString()));
++peerCount; ++peerCount;
} }
@ -262,16 +252,23 @@ void PeerListWidget::showPeerListMenu(const QPoint &)
QMessageBox::information(this, tr("Peer addition"), tr("Some peers could not be added. Check the Log for details.")); QMessageBox::information(this, tr("Peer addition"), tr("Some peers could not be added. Check the Log for details."));
else if (peerCount > 0) else if (peerCount > 0)
QMessageBox::information(this, tr("Peer addition"), tr("The peers were added to this torrent.")); QMessageBox::information(this, tr("Peer addition"), tr("The peers were added to this torrent."));
return; });
}
if (act == banAct) {
banSelectedPeers();
return;
} }
if (act == copyPeerAct) {
copySelectedPeers(); if (!selectionModel()->selectedRows().isEmpty()) {
return; const QAction *copyPeerAct = menu->addAction(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy IP:port"));
connect(copyPeerAct, &QAction::triggered, this, &PeerListWidget::copySelectedPeers);
menu->addSeparator();
const QAction *banAct = menu->addAction(GuiIconProvider::instance()->getIcon("user-group-delete"), tr("Ban peer permanently"));
connect(banAct, &QAction::triggered, this, &PeerListWidget::banSelectedPeers);
} }
if (menu->isEmpty())
delete menu;
else
menu->popup(QCursor::pos());
} }
void PeerListWidget::banSelectedPeers() void PeerListWidget::banSelectedPeers()

151
src/gui/properties/propertieswidget.cpp

@ -582,96 +582,105 @@ void PropertiesWidget::displayFilesListMenu(const QPoint &)
const QModelIndexList selectedRows = m_ui->filesList->selectionModel()->selectedRows(0); const QModelIndexList selectedRows = m_ui->filesList->selectionModel()->selectedRows(0);
if (selectedRows.empty()) return; if (selectedRows.empty()) return;
QMenu myFilesListMenu; QMenu *menu = new QMenu(this);
QAction *actOpen = nullptr; menu->setAttribute(Qt::WA_DeleteOnClose);
QAction *actOpenContainingFolder = nullptr;
QAction *actRename = nullptr;
if (selectedRows.size() == 1) { if (selectedRows.size() == 1) {
actOpen = myFilesListMenu.addAction(GuiIconProvider::instance()->getIcon("folder-documents"), tr("Open")); const QModelIndex index = selectedRows[0];
actOpenContainingFolder = myFilesListMenu.addAction(GuiIconProvider::instance()->getIcon("inode-directory"), tr("Open Containing Folder"));
actRename = myFilesListMenu.addAction(GuiIconProvider::instance()->getIcon("edit-rename"), tr("Rename...")); const QAction *actOpen = menu->addAction(GuiIconProvider::instance()->getIcon("folder-documents"), tr("Open"));
myFilesListMenu.addSeparator(); connect(actOpen, &QAction::triggered, this, [this, index]() { openDoubleClickedFile(index); });
const QAction *actOpenContainingFolder = menu->addAction(GuiIconProvider::instance()->getIcon("inode-directory"), tr("Open Containing Folder"));
connect(actOpenContainingFolder, &QAction::triggered, this, [this, index]() { openFolder(index, true); });
const QAction *actRename = menu->addAction(GuiIconProvider::instance()->getIcon("edit-rename"), tr("Rename..."));
connect(actRename, &QAction::triggered, this, [this]() { m_ui->filesList->renameSelectedFile(m_torrent); });
menu->addSeparator();
} }
QMenu subMenu;
QMenu *subMenu = new QMenu(menu);
if (!m_torrent->isSeed()) { if (!m_torrent->isSeed()) {
subMenu.setTitle(tr("Priority")); subMenu->setTitle(tr("Priority"));
subMenu.addAction(m_ui->actionNotDownloaded);
subMenu.addAction(m_ui->actionNormal); const auto applyPriorities = [this, selectedRows](const BitTorrent::DownloadPriority prio)
subMenu.addAction(m_ui->actionHigh); {
subMenu.addAction(m_ui->actionMaximum); for (const QModelIndex &index : selectedRows) {
myFilesListMenu.addMenu(&subMenu); m_propListModel->setData(
m_propListModel->index(index.row(), PRIORITY, index.parent()), static_cast<int>(prio));
}
// Save changes
filteredFilesChanged();
};
connect(m_ui->actionNotDownloaded, &QAction::triggered, subMenu, [applyPriorities]()
{
applyPriorities(BitTorrent::DownloadPriority::Ignored);
});
subMenu->addAction(m_ui->actionNotDownloaded);
connect(m_ui->actionNormal, &QAction::triggered, subMenu, [applyPriorities]()
{
applyPriorities(BitTorrent::DownloadPriority::Normal);
});
subMenu->addAction(m_ui->actionNormal);
connect(m_ui->actionHigh, &QAction::triggered, subMenu, [applyPriorities]()
{
applyPriorities(BitTorrent::DownloadPriority::High);
});
subMenu->addAction(m_ui->actionHigh);
connect(m_ui->actionMaximum, &QAction::triggered, subMenu, [applyPriorities]()
{
applyPriorities(BitTorrent::DownloadPriority::Maximum);
});
subMenu->addAction(m_ui->actionMaximum);
menu->addMenu(subMenu);
} }
// The selected torrent might have disappeared during exec() // The selected torrent might have disappeared during exec()
// so we just close menu when an appropriate model is reset // so we just close menu when an appropriate model is reset
connect(m_ui->filesList->model(), &QAbstractItemModel::modelAboutToBeReset connect(m_ui->filesList->model(), &QAbstractItemModel::modelAboutToBeReset
, &myFilesListMenu, [&myFilesListMenu]() , menu, [&menu]()
{ {
myFilesListMenu.setActiveAction(nullptr); menu->setActiveAction(nullptr);
myFilesListMenu.close(); menu->close();
}); });
// Call menu
const QAction *act = myFilesListMenu.exec(QCursor::pos());
if (!act) return;
const QModelIndex index = selectedRows[0]; menu->popup(QCursor::pos());
if (act == actOpen) {
openDoubleClickedFile(index);
}
else if (act == actOpenContainingFolder) {
openFolder(index, true);
}
else if (act == actRename) {
m_ui->filesList->renameSelectedFile(m_torrent);
}
else {
BitTorrent::DownloadPriority prio = BitTorrent::DownloadPriority::Normal;
if (act == m_ui->actionHigh)
prio = BitTorrent::DownloadPriority::High;
else if (act == m_ui->actionMaximum)
prio = BitTorrent::DownloadPriority::Maximum;
else if (act == m_ui->actionNotDownloaded)
prio = BitTorrent::DownloadPriority::Ignored;
qDebug("Setting files priority");
for (const QModelIndex &index : selectedRows) {
qDebug("Setting priority(%d) for file at row %d", static_cast<int>(prio), index.row());
m_propListModel->setData(m_propListModel->index(index.row(), PRIORITY, index.parent()), static_cast<int>(prio));
}
// Save changes
filteredFilesChanged();
}
} }
void PropertiesWidget::displayWebSeedListMenu(const QPoint &) void PropertiesWidget::displayWebSeedListMenu(const QPoint &)
{ {
if (!m_torrent) return; if (!m_torrent) return;
QMenu seedMenu; const QModelIndexList rows = m_ui->listWebSeeds->selectionModel()->selectedRows();
QModelIndexList rows = m_ui->listWebSeeds->selectionModel()->selectedRows();
QAction *actAdd = seedMenu.addAction(GuiIconProvider::instance()->getIcon("list-add"), tr("New Web seed")); QMenu *menu = new QMenu(this);
QAction *actDel = nullptr; menu->setAttribute(Qt::WA_DeleteOnClose);
QAction *actCpy = nullptr;
QAction *actEdit = nullptr; const QAction *actAdd = menu->addAction(GuiIconProvider::instance()->getIcon("list-add"), tr("New Web seed"));
connect(actAdd, &QAction::triggered, this, &PropertiesWidget::askWebSeed);
if (!rows.isEmpty()) { if (!rows.isEmpty()) {
actDel = seedMenu.addAction(GuiIconProvider::instance()->getIcon("list-remove"), tr("Remove Web seed")); const QAction *actDel = menu->addAction(GuiIconProvider::instance()->getIcon("list-remove"), tr("Remove Web seed"));
seedMenu.addSeparator(); connect(actDel, &QAction::triggered, this, &PropertiesWidget::deleteSelectedUrlSeeds);
actCpy = seedMenu.addAction(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy Web seed URL"));
actEdit = seedMenu.addAction(GuiIconProvider::instance()->getIcon("edit-rename"), tr("Edit Web seed URL")); menu->addSeparator();
}
const QAction *actCpy = menu->addAction(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy Web seed URL"));
const QAction *act = seedMenu.exec(QCursor::pos()); connect(actCpy, &QAction::triggered, this, &PropertiesWidget::copySelectedWebSeedsToClipboard);
if (!act) return;
const QAction *actEdit = menu->addAction(GuiIconProvider::instance()->getIcon("edit-rename"), tr("Edit Web seed URL"));
if (act == actAdd) connect(actEdit, &QAction::triggered, this, &PropertiesWidget::editWebSeed);
askWebSeed(); }
else if (act == actDel)
deleteSelectedUrlSeeds(); menu->popup(QCursor::pos());
else if (act == actCpy)
copySelectedWebSeedsToClipboard();
else if (act == actEdit)
editWebSeed();
} }
void PropertiesWidget::openSelectedFile() void PropertiesWidget::openSelectedFile()

4
src/gui/properties/propertieswidget.h

@ -90,8 +90,8 @@ protected slots:
void deleteSelectedUrlSeeds(); void deleteSelectedUrlSeeds();
void copySelectedWebSeedsToClipboard() const; void copySelectedWebSeedsToClipboard() const;
void editWebSeed(); void editWebSeed();
void displayFilesListMenu(const QPoint &pos); void displayFilesListMenu(const QPoint &);
void displayWebSeedListMenu(const QPoint &pos); void displayWebSeedListMenu(const QPoint &);
void filteredFilesChanged(); void filteredFilesChanged();
void showPiecesDownloaded(bool show); void showPiecesDownloaded(bool show);
void showPiecesAvailability(bool show); void showPiecesAvailability(bool show);

5
src/gui/properties/speedwidget.cpp

@ -48,8 +48,9 @@ ComboBoxMenuButton::ComboBoxMenuButton(QWidget *parent, QMenu *menu)
void ComboBoxMenuButton::showPopup() void ComboBoxMenuButton::showPopup()
{ {
QPoint p = mapToGlobal(QPoint(0, height())); const QPoint p = mapToGlobal(QPoint(0, height()));
m_menu->exec(p); m_menu->popup(p);
QComboBox::hidePopup(); QComboBox::hidePopup();
} }

89
src/gui/properties/trackerlistwidget.cpp

@ -521,59 +521,45 @@ void TrackerListWidget::reannounceSelected()
loadTrackers(); loadTrackers();
} }
void TrackerListWidget::showTrackerListMenu(QPoint) void TrackerListWidget::showTrackerListMenu(const QPoint &)
{ {
BitTorrent::TorrentHandle *const torrent = m_properties->getCurrentTorrent(); BitTorrent::TorrentHandle *const torrent = m_properties->getCurrentTorrent();
if (!torrent) return; if (!torrent) return;
//QList<QTreeWidgetItem*> selected_items = getSelectedTrackerItems(); QMenu *menu = new QMenu(this);
QMenu menu; menu->setAttribute(Qt::WA_DeleteOnClose);
// Add actions // Add actions
QAction *addAct = menu.addAction(GuiIconProvider::instance()->getIcon("list-add"), tr("Add a new tracker...")); const QAction *addAct = menu->addAction(GuiIconProvider::instance()->getIcon("list-add"), tr("Add a new tracker..."));
QAction *copyAct = nullptr; connect(addAct, &QAction::triggered, this, &TrackerListWidget::askForTrackers);
QAction *delAct = nullptr;
QAction *editAct = nullptr;
if (!getSelectedTrackerItems().isEmpty()) { if (!getSelectedTrackerItems().isEmpty()) {
editAct = menu.addAction(GuiIconProvider::instance()->getIcon("edit-rename"),tr("Edit tracker URL...")); const QAction *editAct = menu->addAction(GuiIconProvider::instance()->getIcon("edit-rename"),tr("Edit tracker URL..."));
delAct = menu.addAction(GuiIconProvider::instance()->getIcon("list-remove"), tr("Remove tracker")); connect(editAct, &QAction::triggered, this, &TrackerListWidget::editSelectedTracker);
copyAct = menu.addAction(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy tracker URL"));
const QAction *delAct = menu->addAction(GuiIconProvider::instance()->getIcon("list-remove"), tr("Remove tracker"));
connect(delAct, &QAction::triggered, this, &TrackerListWidget::deleteSelectedTrackers);
const QAction *copyAct = menu->addAction(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy tracker URL"));
connect(copyAct, &QAction::triggered, this, &TrackerListWidget::copyTrackerUrl);
} }
QAction *reannounceSelAct = nullptr;
QAction *reannounceAllAct = nullptr;
if (!torrent->isPaused()) { if (!torrent->isPaused()) {
reannounceSelAct = menu.addAction(GuiIconProvider::instance()->getIcon("view-refresh"), tr("Force reannounce to selected trackers")); const QAction *reannounceSelAct = menu->addAction(GuiIconProvider::instance()->getIcon("view-refresh"), tr("Force reannounce to selected trackers"));
menu.addSeparator(); connect(reannounceSelAct, &QAction::triggered, this, &TrackerListWidget::reannounceSelected);
reannounceAllAct = menu.addAction(GuiIconProvider::instance()->getIcon("view-refresh"), tr("Force reannounce to all trackers"));
}
QAction *act = menu.exec(QCursor::pos());
if (act == nullptr) return;
if (act == addAct) { menu->addSeparator();
askForTrackers();
return; const QAction *reannounceAllAct = menu->addAction(GuiIconProvider::instance()->getIcon("view-refresh"), tr("Force reannounce to all trackers"));
} connect(reannounceAllAct, &QAction::triggered, this, [this]()
if (act == copyAct) { {
copyTrackerUrl();
return;
}
if (act == delAct) {
deleteSelectedTrackers();
return;
}
if (act == reannounceSelAct) {
reannounceSelected();
return;
}
if (act == reannounceAllAct) {
BitTorrent::TorrentHandle *h = m_properties->getCurrentTorrent(); BitTorrent::TorrentHandle *h = m_properties->getCurrentTorrent();
h->forceReannounce(); h->forceReannounce();
h->forceDHTAnnounce(); h->forceDHTAnnounce();
return; });
}
if (act == editAct) {
editSelectedTracker();
return;
} }
menu->popup(QCursor::pos());
} }
void TrackerListWidget::loadSettings() void TrackerListWidget::loadSettings()
@ -615,25 +601,32 @@ int TrackerListWidget::visibleColumnsCount() const
void TrackerListWidget::displayToggleColumnsMenu(const QPoint &) void TrackerListWidget::displayToggleColumnsMenu(const QPoint &)
{ {
QMenu hideshowColumn(this); QMenu *menu = new QMenu(this);
hideshowColumn.setTitle(tr("Column visibility")); menu->setAttribute(Qt::WA_DeleteOnClose);
menu->setTitle(tr("Column visibility"));
for (int i = 0; i < COL_COUNT; ++i) { for (int i = 0; i < COL_COUNT; ++i) {
QAction *myAct = hideshowColumn.addAction(headerLabels().at(i)); QAction *myAct = menu->addAction(headerLabels().at(i));
myAct->setCheckable(true); myAct->setCheckable(true);
myAct->setChecked(!isColumnHidden(i)); myAct->setChecked(!isColumnHidden(i));
myAct->setData(i); myAct->setData(i);
} }
// Call menu connect(menu, &QMenu::triggered, this, [this](const QAction *action)
QAction *act = hideshowColumn.exec(QCursor::pos()); {
if (!act) return; const int col = action->data().toInt();
int col = act->data().toInt();
Q_ASSERT(visibleColumnsCount() > 0); Q_ASSERT(visibleColumnsCount() > 0);
if (!isColumnHidden(col) && (visibleColumnsCount() == 1)) if (!isColumnHidden(col) && (visibleColumnsCount() == 1))
return; return;
setColumnHidden(col, !isColumnHidden(col)); setColumnHidden(col, !isColumnHidden(col));
if (!isColumnHidden(col) && (columnWidth(col) <= 5)) if (!isColumnHidden(col) && (columnWidth(col) <= 5))
resizeColumnToContents(col); resizeColumnToContents(col);
saveSettings(); saveSettings();
});
menu->popup(QCursor::pos());
} }

2
src/gui/properties/trackerlistwidget.h

@ -82,7 +82,7 @@ public slots:
void reannounceSelected(); void reannounceSelected();
void deleteSelectedTrackers(); void deleteSelectedTrackers();
void editSelectedTracker(); void editSelectedTracker();
void showTrackerListMenu(QPoint); void showTrackerListMenu(const QPoint &);
void displayToggleColumnsMenu(const QPoint &); void displayToggleColumnsMenu(const QPoint &);
void loadSettings(); void loadSettings();
void saveSettings() const; void saveSettings() const;

43
src/gui/rss/automatedrssdownloader.cpp

@ -468,37 +468,36 @@ void AutomatedRssDownloader::on_importBtn_clicked()
void AutomatedRssDownloader::displayRulesListMenu() void AutomatedRssDownloader::displayRulesListMenu()
{ {
QMenu menu; QMenu *menu = new QMenu(this);
QAction *addAct = menu.addAction(GuiIconProvider::instance()->getIcon("list-add"), tr("Add new rule...")); menu->setAttribute(Qt::WA_DeleteOnClose);
QAction *delAct = nullptr;
QAction *renameAct = nullptr; const QAction *addAct = menu->addAction(GuiIconProvider::instance()->getIcon("list-add"), tr("Add new rule..."));
QAction *clearAct = nullptr; connect(addAct, &QAction::triggered, this, &AutomatedRssDownloader::on_addRuleBtn_clicked);
const QList<QListWidgetItem *> selection = m_ui->listRules->selectedItems(); const QList<QListWidgetItem *> selection = m_ui->listRules->selectedItems();
if (!selection.isEmpty()) { if (!selection.isEmpty()) {
if (selection.count() == 1) { if (selection.count() == 1) {
delAct = menu.addAction(GuiIconProvider::instance()->getIcon("list-remove"), tr("Delete rule")); const QAction *delAct = menu->addAction(GuiIconProvider::instance()->getIcon("list-remove"), tr("Delete rule"));
menu.addSeparator(); connect(delAct, &QAction::triggered, this, &AutomatedRssDownloader::on_removeRuleBtn_clicked);
renameAct = menu.addAction(GuiIconProvider::instance()->getIcon("edit-rename"), tr("Rename rule..."));
menu->addSeparator();
const QAction *renameAct = menu->addAction(GuiIconProvider::instance()->getIcon("edit-rename"), tr("Rename rule..."));
connect(renameAct, &QAction::triggered, this, &AutomatedRssDownloader::renameSelectedRule);
} }
else { else {
delAct = menu.addAction(GuiIconProvider::instance()->getIcon("list-remove"), tr("Delete selected rules")); const QAction *delAct = menu->addAction(GuiIconProvider::instance()->getIcon("list-remove"), tr("Delete selected rules"));
} connect(delAct, &QAction::triggered, this, &AutomatedRssDownloader::on_removeRuleBtn_clicked);
menu.addSeparator();
clearAct = menu.addAction(GuiIconProvider::instance()->getIcon("edit-clear"), tr("Clear downloaded episodes..."));
} }
QAction *act = menu.exec(QCursor::pos()); menu->addSeparator();
if (!act) return;
const QAction *clearAct = menu->addAction(GuiIconProvider::instance()->getIcon("edit-clear"), tr("Clear downloaded episodes..."));
connect(clearAct, &QAction::triggered, this, &AutomatedRssDownloader::clearSelectedRuleDownloadedEpisodeList);
}
if (act == addAct) menu->popup(QCursor::pos());
on_addRuleBtn_clicked();
else if (act == delAct)
on_removeRuleBtn_clicked();
else if (act == renameAct)
renameSelectedRule();
else if (act == clearAct)
clearSelectedRuleDownloadedEpisodeList();
} }
void AutomatedRssDownloader::renameSelectedRule() void AutomatedRssDownloader::renameSelectedRule()

62
src/gui/rss/rsswidget.cpp

@ -147,38 +147,45 @@ void RSSWidget::displayRSSListMenu(const QPoint &pos)
if (!m_feedListWidget->indexAt(pos).isValid()) if (!m_feedListWidget->indexAt(pos).isValid())
// No item under the mouse, clear selection // No item under the mouse, clear selection
m_feedListWidget->clearSelection(); m_feedListWidget->clearSelection();
QMenu myRSSListMenu(this);
QList<QTreeWidgetItem *> selectedItems = m_feedListWidget->selectedItems(); QMenu *menu = new QMenu(this);
menu->setAttribute(Qt::WA_DeleteOnClose);
const QList<QTreeWidgetItem *> selectedItems = m_feedListWidget->selectedItems();
if (!selectedItems.isEmpty()) { if (!selectedItems.isEmpty()) {
myRSSListMenu.addAction(m_ui->actionUpdate); menu->addAction(m_ui->actionUpdate);
myRSSListMenu.addAction(m_ui->actionMarkItemsRead); menu->addAction(m_ui->actionMarkItemsRead);
myRSSListMenu.addSeparator(); menu->addSeparator();
if (selectedItems.size() == 1) { if (selectedItems.size() == 1) {
if (selectedItems.first() != m_feedListWidget->stickyUnreadItem()) { if (selectedItems.first() != m_feedListWidget->stickyUnreadItem()) {
myRSSListMenu.addAction(m_ui->actionRename); menu->addAction(m_ui->actionRename);
myRSSListMenu.addAction(m_ui->actionDelete); menu->addAction(m_ui->actionDelete);
myRSSListMenu.addSeparator(); menu->addSeparator();
if (m_feedListWidget->isFolder(selectedItems.first())) if (m_feedListWidget->isFolder(selectedItems.first()))
myRSSListMenu.addAction(m_ui->actionNewFolder); menu->addAction(m_ui->actionNewFolder);
} }
} }
else { else {
myRSSListMenu.addAction(m_ui->actionDelete); menu->addAction(m_ui->actionDelete);
myRSSListMenu.addSeparator(); menu->addSeparator();
} }
myRSSListMenu.addAction(m_ui->actionNewSubscription);
menu->addAction(m_ui->actionNewSubscription);
if (m_feedListWidget->isFeed(selectedItems.first())) { if (m_feedListWidget->isFeed(selectedItems.first())) {
myRSSListMenu.addSeparator(); menu->addSeparator();
myRSSListMenu.addAction(m_ui->actionCopyFeedURL); menu->addAction(m_ui->actionCopyFeedURL);
} }
} }
else { else {
myRSSListMenu.addAction(m_ui->actionNewSubscription); menu->addAction(m_ui->actionNewSubscription);
myRSSListMenu.addAction(m_ui->actionNewFolder); menu->addAction(m_ui->actionNewFolder);
myRSSListMenu.addSeparator(); menu->addSeparator();
myRSSListMenu.addAction(m_ui->actionUpdateAllFeeds); menu->addAction(m_ui->actionUpdateAllFeeds);
} }
myRSSListMenu.exec(QCursor::pos());
menu->popup(QCursor::pos());
} }
void RSSWidget::displayItemsListMenu(const QPoint &) void RSSWidget::displayItemsListMenu(const QPoint &)
@ -197,13 +204,16 @@ void RSSWidget::displayItemsListMenu(const QPoint &)
break; break;
} }
QMenu myItemListMenu(this); QMenu *myItemListMenu = new QMenu(this);
myItemListMenu->setAttribute(Qt::WA_DeleteOnClose);
if (hasTorrent) if (hasTorrent)
myItemListMenu.addAction(m_ui->actionDownloadTorrent); myItemListMenu->addAction(m_ui->actionDownloadTorrent);
if (hasLink) if (hasLink)
myItemListMenu.addAction(m_ui->actionOpenNewsURL); myItemListMenu->addAction(m_ui->actionOpenNewsURL);
if (hasTorrent || hasLink)
myItemListMenu.exec(QCursor::pos()); if (!myItemListMenu->isEmpty())
myItemListMenu->popup(QCursor::pos());
} }
void RSSWidget::askNewFolder() void RSSWidget::askNewFolder()
@ -516,7 +526,9 @@ void RSSWidget::updateRefreshInterval(uint val)
void RSSWidget::on_rssDownloaderBtn_clicked() void RSSWidget::on_rssDownloaderBtn_clicked()
{ {
AutomatedRssDownloader(this).exec(); auto *downloader = new AutomatedRssDownloader(this);
downloader->setAttribute(Qt::WA_DeleteOnClose);
downloader->open();
} }
void RSSWidget::handleSessionProcessingStateChanged(bool enabled) void RSSWidget::handleSessionProcessingStateChanged(bool enabled)

17
src/gui/search/pluginselectdialog.cpp

@ -165,17 +165,20 @@ void PluginSelectDialog::togglePluginState(QTreeWidgetItem *item, int)
void PluginSelectDialog::displayContextMenu(const QPoint &) void PluginSelectDialog::displayContextMenu(const QPoint &)
{ {
QMenu myContextMenu(this);
// Enable/disable pause/start action given the DL state // Enable/disable pause/start action given the DL state
QList<QTreeWidgetItem *> items = m_ui->pluginsTree->selectedItems(); const QList<QTreeWidgetItem *> items = m_ui->pluginsTree->selectedItems();
if (items.isEmpty()) return; if (items.isEmpty()) return;
QString firstID = items.first()->text(PLUGIN_ID); QMenu *myContextMenu = new QMenu(this);
myContextMenu->setAttribute(Qt::WA_DeleteOnClose);
const QString firstID = items.first()->text(PLUGIN_ID);
m_ui->actionEnable->setChecked(m_pluginManager->pluginInfo(firstID)->enabled); m_ui->actionEnable->setChecked(m_pluginManager->pluginInfo(firstID)->enabled);
myContextMenu.addAction(m_ui->actionEnable); myContextMenu->addAction(m_ui->actionEnable);
myContextMenu.addSeparator(); myContextMenu->addSeparator();
myContextMenu.addAction(m_ui->actionUninstall); myContextMenu->addAction(m_ui->actionUninstall);
myContextMenu.exec(QCursor::pos());
myContextMenu->popup(QCursor::pos());
} }
void PluginSelectDialog::on_closeButton_clicked() void PluginSelectDialog::on_closeButton_clicked()

2
src/gui/search/pluginselectdialog.h

@ -71,7 +71,7 @@ private slots:
void on_closeButton_clicked(); void on_closeButton_clicked();
void togglePluginState(QTreeWidgetItem*, int); void togglePluginState(QTreeWidgetItem*, int);
void setRowColor(int row, const QString &color); void setRowColor(int row, const QString &color);
void displayContextMenu(const QPoint &pos); void displayContextMenu(const QPoint &);
void enableSelection(bool enable); void enableSelection(bool enable);
void askForLocalPlugin(); void askForLocalPlugin();
void askForPluginUrl(); void askForPluginUrl();

4
src/gui/search/searchjobwidget.cpp

@ -358,7 +358,9 @@ void SearchJobWidget::showFilterContextMenu(const QPoint &)
const Preferences *pref = Preferences::instance(); const Preferences *pref = Preferences::instance();
QMenu *menu = m_lineEditSearchResultsFilter->createStandardContextMenu(); QMenu *menu = m_lineEditSearchResultsFilter->createStandardContextMenu();
menu->setAttribute(Qt::WA_DeleteOnClose);
menu->addSeparator(); menu->addSeparator();
QAction *useRegexAct = new QAction(tr("Use regular expressions"), menu); QAction *useRegexAct = new QAction(tr("Use regular expressions"), menu);
useRegexAct->setCheckable(true); useRegexAct->setCheckable(true);
useRegexAct->setChecked(pref->getRegexAsFilteringPatternForSearchJob()); useRegexAct->setChecked(pref->getRegexAsFilteringPatternForSearchJob());
@ -367,7 +369,7 @@ void SearchJobWidget::showFilterContextMenu(const QPoint &)
connect(useRegexAct, &QAction::toggled, pref, &Preferences::setRegexAsFilteringPatternForSearchJob); connect(useRegexAct, &QAction::toggled, pref, &Preferences::setRegexAsFilteringPatternForSearchJob);
connect(useRegexAct, &QAction::toggled, this, [this]() { filterSearchResults(m_lineEditSearchResultsFilter->text()); }); connect(useRegexAct, &QAction::toggled, this, [this]() { filterSearchResults(m_lineEditSearchResultsFilter->text()); });
menu->exec(QCursor::pos()); menu->popup(QCursor::pos());
} }
QString SearchJobWidget::statusText(SearchJobWidget::Status st) QString SearchJobWidget::statusText(SearchJobWidget::Status st)

19
src/gui/tagfilterwidget.cpp

@ -104,47 +104,48 @@ void TagFilterWidget::onCurrentRowChanged(const QModelIndex &current, const QMod
void TagFilterWidget::showMenu(QPoint) void TagFilterWidget::showMenu(QPoint)
{ {
QMenu menu(this); QMenu *menu = new QMenu(this);
menu->setAttribute(Qt::WA_DeleteOnClose);
QAction *addAct = menu.addAction( const QAction *addAct = menu->addAction(
GuiIconProvider::instance()->getIcon("list-add") GuiIconProvider::instance()->getIcon("list-add")
, tr("Add tag...")); , tr("Add tag..."));
connect(addAct, &QAction::triggered, this, &TagFilterWidget::addTag); connect(addAct, &QAction::triggered, this, &TagFilterWidget::addTag);
const auto selectedRows = selectionModel()->selectedRows(); const auto selectedRows = selectionModel()->selectedRows();
if (!selectedRows.empty() && !TagFilterModel::isSpecialItem(selectedRows.first())) { if (!selectedRows.empty() && !TagFilterModel::isSpecialItem(selectedRows.first())) {
QAction *removeAct = menu.addAction( const QAction *removeAct = menu->addAction(
GuiIconProvider::instance()->getIcon("list-remove") GuiIconProvider::instance()->getIcon("list-remove")
, tr("Remove tag")); , tr("Remove tag"));
connect(removeAct, &QAction::triggered, this, &TagFilterWidget::removeTag); connect(removeAct, &QAction::triggered, this, &TagFilterWidget::removeTag);
} }
QAction *removeUnusedAct = menu.addAction( const QAction *removeUnusedAct = menu->addAction(
GuiIconProvider::instance()->getIcon("list-remove") GuiIconProvider::instance()->getIcon("list-remove")
, tr("Remove unused tags")); , tr("Remove unused tags"));
connect(removeUnusedAct, &QAction::triggered, this, &TagFilterWidget::removeUnusedTags); connect(removeUnusedAct, &QAction::triggered, this, &TagFilterWidget::removeUnusedTags);
menu.addSeparator(); menu->addSeparator();
QAction *startAct = menu.addAction( const QAction *startAct = menu->addAction(
GuiIconProvider::instance()->getIcon("media-playback-start") GuiIconProvider::instance()->getIcon("media-playback-start")
, tr("Resume torrents")); , tr("Resume torrents"));
connect(startAct, &QAction::triggered connect(startAct, &QAction::triggered
, this, &TagFilterWidget::actionResumeTorrentsTriggered); , this, &TagFilterWidget::actionResumeTorrentsTriggered);
QAction *pauseAct = menu.addAction( const QAction *pauseAct = menu->addAction(
GuiIconProvider::instance()->getIcon("media-playback-pause") GuiIconProvider::instance()->getIcon("media-playback-pause")
, tr("Pause torrents")); , tr("Pause torrents"));
connect(pauseAct, &QAction::triggered, this connect(pauseAct, &QAction::triggered, this
, &TagFilterWidget::actionPauseTorrentsTriggered); , &TagFilterWidget::actionPauseTorrentsTriggered);
QAction *deleteTorrentsAct = menu.addAction( const QAction *deleteTorrentsAct = menu->addAction(
GuiIconProvider::instance()->getIcon("edit-delete") GuiIconProvider::instance()->getIcon("edit-delete")
, tr("Delete torrents")); , tr("Delete torrents"));
connect(deleteTorrentsAct, &QAction::triggered, this connect(deleteTorrentsAct, &QAction::triggered, this
, &TagFilterWidget::actionDeleteTorrentsTriggered); , &TagFilterWidget::actionDeleteTorrentsTriggered);
menu.exec(QCursor::pos()); menu->popup(QCursor::pos());
} }
void TagFilterWidget::callUpdateGeometry() void TagFilterWidget::callUpdateGeometry()

29
src/gui/transferlistfilterswidget.cpp

@ -203,7 +203,7 @@ void StatusFilterWidget::updateTorrentNumbers()
item(TorrentFilter::Errored)->setData(Qt::DisplayRole, QVariant(tr("Errored (%1)").arg(report.nbErrored))); item(TorrentFilter::Errored)->setData(Qt::DisplayRole, QVariant(tr("Errored (%1)").arg(report.nbErrored)));
} }
void StatusFilterWidget::showMenu(QPoint) {} void StatusFilterWidget::showMenu(const QPoint &) {}
void StatusFilterWidget::applyFilter(int row) void StatusFilterWidget::applyFilter(int row)
{ {
@ -465,24 +465,21 @@ void TrackerFiltersList::handleFavicoDownloadFinished(const Net::DownloadResult
} }
} }
void TrackerFiltersList::showMenu(QPoint) void TrackerFiltersList::showMenu(const QPoint &)
{ {
QMenu menu(this); QMenu *menu = new QMenu(this);
QAction *startAct = menu.addAction(GuiIconProvider::instance()->getIcon("media-playback-start"), tr("Resume torrents")); menu->setAttribute(Qt::WA_DeleteOnClose);
QAction *pauseAct = menu.addAction(GuiIconProvider::instance()->getIcon("media-playback-pause"), tr("Pause torrents"));
QAction *deleteTorrentsAct = menu.addAction(GuiIconProvider::instance()->getIcon("edit-delete"), tr("Delete torrents"));
QAction *act = nullptr;
act = menu.exec(QCursor::pos());
if (!act) const QAction *startAct = menu->addAction(GuiIconProvider::instance()->getIcon("media-playback-start"), tr("Resume torrents"));
return; connect(startAct, &QAction::triggered, transferList, &TransferListWidget::startVisibleTorrents);
const QAction *pauseAct = menu->addAction(GuiIconProvider::instance()->getIcon("media-playback-pause"), tr("Pause torrents"));
connect(pauseAct, &QAction::triggered, transferList, &TransferListWidget::pauseVisibleTorrents);
const QAction *deleteTorrentsAct = menu->addAction(GuiIconProvider::instance()->getIcon("edit-delete"), tr("Delete torrents"));
connect(deleteTorrentsAct, &QAction::triggered, transferList, &TransferListWidget::deleteVisibleTorrents);
if (act == startAct) menu->popup(QCursor::pos());
transferList->startVisibleTorrents();
else if (act == pauseAct)
transferList->pauseVisibleTorrents();
else if (act == deleteTorrentsAct)
transferList->deleteVisibleTorrents();
} }
void TrackerFiltersList::applyFilter(int row) void TrackerFiltersList::applyFilter(int row)

6
src/gui/transferlistfilterswidget.h

@ -66,7 +66,7 @@ protected:
TransferListWidget *transferList; TransferListWidget *transferList;
private slots: private slots:
virtual void showMenu(QPoint) = 0; virtual void showMenu(const QPoint &) = 0;
virtual void applyFilter(int row) = 0; virtual void applyFilter(int row) = 0;
virtual void handleNewTorrent(BitTorrent::TorrentHandle *const) = 0; virtual void handleNewTorrent(BitTorrent::TorrentHandle *const) = 0;
virtual void torrentAboutToBeDeleted(BitTorrent::TorrentHandle *const) = 0; virtual void torrentAboutToBeDeleted(BitTorrent::TorrentHandle *const) = 0;
@ -87,7 +87,7 @@ private slots:
private: private:
// These 4 methods are virtual slots in the base class. // These 4 methods are virtual slots in the base class.
// No need to redeclare them here as slots. // No need to redeclare them here as slots.
void showMenu(QPoint) override; void showMenu(const QPoint &) override;
void applyFilter(int row) override; void applyFilter(int row) override;
void handleNewTorrent(BitTorrent::TorrentHandle *const) override; void handleNewTorrent(BitTorrent::TorrentHandle *const) override;
void torrentAboutToBeDeleted(BitTorrent::TorrentHandle *const) override; void torrentAboutToBeDeleted(BitTorrent::TorrentHandle *const) override;
@ -119,7 +119,7 @@ private slots:
private: private:
// These 4 methods are virtual slots in the base class. // These 4 methods are virtual slots in the base class.
// No need to redeclare them here as slots. // No need to redeclare them here as slots.
void showMenu(QPoint) override; void showMenu(const QPoint &) override;
void applyFilter(int row) override; void applyFilter(int row) override;
void handleNewTorrent(BitTorrent::TorrentHandle *const torrent) override; void handleNewTorrent(BitTorrent::TorrentHandle *const torrent) override;
void torrentAboutToBeDeleted(BitTorrent::TorrentHandle *const torrent) override; void torrentAboutToBeDeleted(BitTorrent::TorrentHandle *const torrent) override;

269
src/gui/transferlistwidget.cpp

@ -886,59 +886,59 @@ void TransferListWidget::displayListMenu(const QPoint&)
if (selectedIndexes.isEmpty()) return; if (selectedIndexes.isEmpty()) return;
// Create actions // Create actions
QAction actionStart(GuiIconProvider::instance()->getIcon("media-playback-start"), tr("Resume", "Resume/start the torrent"), nullptr); QAction *actionStart = new QAction(GuiIconProvider::instance()->getIcon("media-playback-start"), tr("Resume", "Resume/start the torrent"), this);
connect(&actionStart, &QAction::triggered, this, &TransferListWidget::startSelectedTorrents); connect(actionStart, &QAction::triggered, this, &TransferListWidget::startSelectedTorrents);
QAction actionPause(GuiIconProvider::instance()->getIcon("media-playback-pause"), tr("Pause", "Pause the torrent"), nullptr); QAction *actionPause = new QAction(GuiIconProvider::instance()->getIcon("media-playback-pause"), tr("Pause", "Pause the torrent"), this);
connect(&actionPause, &QAction::triggered, this, &TransferListWidget::pauseSelectedTorrents); connect(actionPause, &QAction::triggered, this, &TransferListWidget::pauseSelectedTorrents);
QAction actionForceStart(GuiIconProvider::instance()->getIcon("media-seek-forward"), tr("Force Resume", "Force Resume/start the torrent"), nullptr); QAction *actionForceStart = new QAction(GuiIconProvider::instance()->getIcon("media-seek-forward"), tr("Force Resume", "Force Resume/start the torrent"), this);
connect(&actionForceStart, &QAction::triggered, this, &TransferListWidget::forceStartSelectedTorrents); connect(actionForceStart, &QAction::triggered, this, &TransferListWidget::forceStartSelectedTorrents);
QAction actionDelete(GuiIconProvider::instance()->getIcon("edit-delete"), tr("Delete", "Delete the torrent"), nullptr); QAction *actionDelete = new QAction(GuiIconProvider::instance()->getIcon("edit-delete"), tr("Delete", "Delete the torrent"), this);
connect(&actionDelete, &QAction::triggered, this, &TransferListWidget::softDeleteSelectedTorrents); connect(actionDelete, &QAction::triggered, this, &TransferListWidget::softDeleteSelectedTorrents);
QAction actionPreviewFile(GuiIconProvider::instance()->getIcon("view-preview"), tr("Preview file..."), nullptr); QAction *actionPreviewFile = new QAction(GuiIconProvider::instance()->getIcon("view-preview"), tr("Preview file..."), this);
connect(&actionPreviewFile, &QAction::triggered, this, &TransferListWidget::previewSelectedTorrents); connect(actionPreviewFile, &QAction::triggered, this, &TransferListWidget::previewSelectedTorrents);
QAction actionSetMaxRatio(QIcon(QLatin1String(":/icons/skin/ratio.svg")), tr("Limit share ratio..."), nullptr); QAction *actionSetMaxRatio = new QAction(QIcon(QLatin1String(":/icons/skin/ratio.svg")), tr("Limit share ratio..."), this);
connect(&actionSetMaxRatio, &QAction::triggered, this, &TransferListWidget::setMaxRatioSelectedTorrents); connect(actionSetMaxRatio, &QAction::triggered, this, &TransferListWidget::setMaxRatioSelectedTorrents);
QAction actionSetUploadLimit(GuiIconProvider::instance()->getIcon("kt-set-max-upload-speed"), tr("Limit upload rate..."), nullptr); QAction *actionSetUploadLimit = new QAction(GuiIconProvider::instance()->getIcon("kt-set-max-upload-speed"), tr("Limit upload rate..."), this);
connect(&actionSetUploadLimit, &QAction::triggered, this, &TransferListWidget::setUpLimitSelectedTorrents); connect(actionSetUploadLimit, &QAction::triggered, this, &TransferListWidget::setUpLimitSelectedTorrents);
QAction actionSetDownloadLimit(GuiIconProvider::instance()->getIcon("kt-set-max-download-speed"), tr("Limit download rate..."), nullptr); QAction *actionSetDownloadLimit = new QAction(GuiIconProvider::instance()->getIcon("kt-set-max-download-speed"), tr("Limit download rate..."), this);
connect(&actionSetDownloadLimit, &QAction::triggered, this, &TransferListWidget::setDlLimitSelectedTorrents); connect(actionSetDownloadLimit, &QAction::triggered, this, &TransferListWidget::setDlLimitSelectedTorrents);
QAction actionOpenDestinationFolder(GuiIconProvider::instance()->getIcon("inode-directory"), tr("Open destination folder"), nullptr); QAction *actionOpenDestinationFolder = new QAction(GuiIconProvider::instance()->getIcon("inode-directory"), tr("Open destination folder"), this);
connect(&actionOpenDestinationFolder, &QAction::triggered, this, &TransferListWidget::openSelectedTorrentsFolder); connect(actionOpenDestinationFolder, &QAction::triggered, this, &TransferListWidget::openSelectedTorrentsFolder);
QAction actionIncreasePriority(GuiIconProvider::instance()->getIcon("go-up"), tr("Move up", "i.e. move up in the queue"), nullptr); QAction *actionIncreasePriority = new QAction(GuiIconProvider::instance()->getIcon("go-up"), tr("Move up", "i.e. move up in the queue"), this);
connect(&actionIncreasePriority, &QAction::triggered, this, &TransferListWidget::increasePrioSelectedTorrents); connect(actionIncreasePriority, &QAction::triggered, this, &TransferListWidget::increasePrioSelectedTorrents);
QAction actionDecreasePriority(GuiIconProvider::instance()->getIcon("go-down"), tr("Move down", "i.e. Move down in the queue"), nullptr); QAction *actionDecreasePriority = new QAction(GuiIconProvider::instance()->getIcon("go-down"), tr("Move down", "i.e. Move down in the queue"), this);
connect(&actionDecreasePriority, &QAction::triggered, this, &TransferListWidget::decreasePrioSelectedTorrents); connect(actionDecreasePriority, &QAction::triggered, this, &TransferListWidget::decreasePrioSelectedTorrents);
QAction actionTopPriority(GuiIconProvider::instance()->getIcon("go-top"), tr("Move to top", "i.e. Move to top of the queue"), nullptr); QAction *actionTopPriority = new QAction(GuiIconProvider::instance()->getIcon("go-top"), tr("Move to top", "i.e. Move to top of the queue"), this);
connect(&actionTopPriority, &QAction::triggered, this, &TransferListWidget::topPrioSelectedTorrents); connect(actionTopPriority, &QAction::triggered, this, &TransferListWidget::topPrioSelectedTorrents);
QAction actionBottomPriority(GuiIconProvider::instance()->getIcon("go-bottom"), tr("Move to bottom", "i.e. Move to bottom of the queue"), nullptr); QAction *actionBottomPriority = new QAction(GuiIconProvider::instance()->getIcon("go-bottom"), tr("Move to bottom", "i.e. Move to bottom of the queue"), this);
connect(&actionBottomPriority, &QAction::triggered, this, &TransferListWidget::bottomPrioSelectedTorrents); connect(actionBottomPriority, &QAction::triggered, this, &TransferListWidget::bottomPrioSelectedTorrents);
QAction actionSetTorrentPath(GuiIconProvider::instance()->getIcon("inode-directory"), tr("Set location..."), nullptr); QAction *actionSetTorrentPath = new QAction(GuiIconProvider::instance()->getIcon("inode-directory"), tr("Set location..."), this);
connect(&actionSetTorrentPath, &QAction::triggered, this, &TransferListWidget::setSelectedTorrentsLocation); connect(actionSetTorrentPath, &QAction::triggered, this, &TransferListWidget::setSelectedTorrentsLocation);
QAction actionForceRecheck(GuiIconProvider::instance()->getIcon("document-edit-verify"), tr("Force recheck"), nullptr); QAction *actionForceRecheck = new QAction(GuiIconProvider::instance()->getIcon("document-edit-verify"), tr("Force recheck"), this);
connect(&actionForceRecheck, &QAction::triggered, this, &TransferListWidget::recheckSelectedTorrents); connect(actionForceRecheck, &QAction::triggered, this, &TransferListWidget::recheckSelectedTorrents);
QAction actionForceReannounce(GuiIconProvider::instance()->getIcon("document-edit-verify"), tr("Force reannounce"), nullptr); QAction *actionForceReannounce = new QAction(GuiIconProvider::instance()->getIcon("document-edit-verify"), tr("Force reannounce"), this);
connect(&actionForceReannounce, &QAction::triggered, this, &TransferListWidget::reannounceSelectedTorrents); connect(actionForceReannounce, &QAction::triggered, this, &TransferListWidget::reannounceSelectedTorrents);
QAction actionCopyMagnetLink(GuiIconProvider::instance()->getIcon("kt-magnet"), tr("Copy magnet link"), nullptr); QAction *actionCopyMagnetLink = new QAction(GuiIconProvider::instance()->getIcon("kt-magnet"), tr("Copy magnet link"), this);
connect(&actionCopyMagnetLink, &QAction::triggered, this, &TransferListWidget::copySelectedMagnetURIs); connect(actionCopyMagnetLink, &QAction::triggered, this, &TransferListWidget::copySelectedMagnetURIs);
QAction actionCopyName(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy name"), nullptr); QAction *actionCopyName = new QAction(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy name"), this);
connect(&actionCopyName, &QAction::triggered, this, &TransferListWidget::copySelectedNames); connect(actionCopyName, &QAction::triggered, this, &TransferListWidget::copySelectedNames);
QAction actionCopyHash(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy hash"), nullptr); QAction *actionCopyHash = new QAction(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy hash"), this);
connect(&actionCopyHash, &QAction::triggered, this, &TransferListWidget::copySelectedHashes); connect(actionCopyHash, &QAction::triggered, this, &TransferListWidget::copySelectedHashes);
QAction actionSuperSeedingMode(tr("Super seeding mode"), nullptr); QAction *actionSuperSeedingMode = new QAction(tr("Super seeding mode"), this);
actionSuperSeedingMode.setCheckable(true); actionSuperSeedingMode->setCheckable(true);
connect(&actionSuperSeedingMode, &QAction::triggered, this, &TransferListWidget::toggleSelectedTorrentsSuperSeeding); connect(actionSuperSeedingMode, &QAction::triggered, this, &TransferListWidget::toggleSelectedTorrentsSuperSeeding);
QAction actionRename(GuiIconProvider::instance()->getIcon("edit-rename"), tr("Rename..."), nullptr); QAction *actionRename = new QAction(GuiIconProvider::instance()->getIcon("edit-rename"), tr("Rename..."), this);
connect(&actionRename, &QAction::triggered, this, &TransferListWidget::renameSelectedTorrent); connect(actionRename, &QAction::triggered, this, &TransferListWidget::renameSelectedTorrent);
QAction actionSequentialDownload(tr("Download in sequential order"), nullptr); QAction *actionSequentialDownload = new QAction(tr("Download in sequential order"), this);
actionSequentialDownload.setCheckable(true); actionSequentialDownload->setCheckable(true);
connect(&actionSequentialDownload, &QAction::triggered, this, &TransferListWidget::toggleSelectedTorrentsSequentialDownload); connect(actionSequentialDownload, &QAction::triggered, this, &TransferListWidget::toggleSelectedTorrentsSequentialDownload);
QAction actionFirstLastPiecePrio(tr("Download first and last pieces first"), nullptr); QAction *actionFirstLastPiecePrio = new QAction(tr("Download first and last pieces first"), this);
actionFirstLastPiecePrio.setCheckable(true); actionFirstLastPiecePrio->setCheckable(true);
connect(&actionFirstLastPiecePrio, &QAction::triggered, this, &TransferListWidget::toggleSelectedFirstLastPiecePrio); connect(actionFirstLastPiecePrio, &QAction::triggered, this, &TransferListWidget::toggleSelectedFirstLastPiecePrio);
QAction actionAutoTMM(tr("Automatic Torrent Management"), nullptr); QAction *actionAutoTMM = new QAction(tr("Automatic Torrent Management"), this);
actionAutoTMM.setCheckable(true); actionAutoTMM->setCheckable(true);
actionAutoTMM.setToolTip(tr("Automatic mode means that various torrent properties(eg save path) will be decided by the associated category")); actionAutoTMM->setToolTip(tr("Automatic mode means that various torrent properties(eg save path) will be decided by the associated category"));
connect(&actionAutoTMM, &QAction::triggered, this, &TransferListWidget::setSelectedAutoTMMEnabled); connect(actionAutoTMM, &QAction::triggered, this, &TransferListWidget::setSelectedAutoTMMEnabled);
// End of actions // End of actions
// Enable/disable pause/start action given the DL state // Enable/disable pause/start action given the DL state
@ -956,12 +956,10 @@ void TransferListWidget::displayListMenu(const QPoint&)
QSet<QString> tagsInAny; QSet<QString> tagsInAny;
QSet<QString> tagsInAll; QSet<QString> tagsInAll;
BitTorrent::TorrentHandle *torrent;
qDebug("Displaying menu");
for (const QModelIndex &index : selectedIndexes) { for (const QModelIndex &index : selectedIndexes) {
// Get the file name // Get the file name
// Get handle and pause the torrent // Get handle and pause the torrent
torrent = m_listModel->torrentHandle(mapToSource(index)); const BitTorrent::TorrentHandle *torrent = m_listModel->torrentHandle(mapToSource(index));
if (!torrent) continue; if (!torrent) continue;
if (firstCategory.isEmpty() && first) if (firstCategory.isEmpty() && first)
@ -1023,46 +1021,70 @@ void TransferListWidget::displayListMenu(const QPoint&)
break; break;
} }
} }
QMenu listMenu(this);
QMenu *listMenu = new QMenu(this);
listMenu->setAttribute(Qt::WA_DeleteOnClose);
if (needsStart) if (needsStart)
listMenu.addAction(&actionStart); listMenu->addAction(actionStart);
if (needsPause) if (needsPause)
listMenu.addAction(&actionPause); listMenu->addAction(actionPause);
if (needsForce) if (needsForce)
listMenu.addAction(&actionForceStart); listMenu->addAction(actionForceStart);
listMenu.addSeparator(); listMenu->addSeparator();
listMenu.addAction(&actionDelete); listMenu->addAction(actionDelete);
listMenu.addSeparator(); listMenu->addSeparator();
listMenu.addAction(&actionSetTorrentPath); listMenu->addAction(actionSetTorrentPath);
if (selectedIndexes.size() == 1) if (selectedIndexes.size() == 1)
listMenu.addAction(&actionRename); listMenu->addAction(actionRename);
// Category Menu // Category Menu
QStringList categories = BitTorrent::Session::instance()->categories().keys(); QStringList categories = BitTorrent::Session::instance()->categories().keys();
std::sort(categories.begin(), categories.end(), Utils::String::naturalLessThan<Qt::CaseInsensitive>); std::sort(categories.begin(), categories.end(), Utils::String::naturalLessThan<Qt::CaseInsensitive>);
QList<QAction*> categoryActions;
QMenu *categoryMenu = listMenu.addMenu(GuiIconProvider::instance()->getIcon("view-categories"), tr("Category")); QMenu *categoryMenu = listMenu->addMenu(GuiIconProvider::instance()->getIcon("view-categories"), tr("Category"));
categoryActions << categoryMenu->addAction(GuiIconProvider::instance()->getIcon("list-add"), tr("New...", "New category..."));
categoryActions << categoryMenu->addAction(GuiIconProvider::instance()->getIcon("edit-clear"), tr("Reset", "Reset category")); const QAction *newCategoryAction = categoryMenu->addAction(GuiIconProvider::instance()->getIcon("list-add"), tr("New...", "New category..."));
connect(newCategoryAction, &QAction::triggered, this, &TransferListWidget::askNewCategoryForSelection);
const QAction *resetCategoryAction = categoryMenu->addAction(GuiIconProvider::instance()->getIcon("edit-clear"), tr("Reset", "Reset category"));
connect(resetCategoryAction, &QAction::triggered, this, [this]() { setSelectionCategory(""); });
categoryMenu->addSeparator(); categoryMenu->addSeparator();
for (QString category : asConst(categories)) {
category.replace('&', "&&"); // avoid '&' becomes accelerator key for (const QString &category : asConst(categories)) {
QAction *cat = new QAction(GuiIconProvider::instance()->getIcon("inode-directory"), category, categoryMenu); const QString escapedCategory = QString(category).replace('&', "&&"); // avoid '&' becomes accelerator key
QAction *cat = new QAction(GuiIconProvider::instance()->getIcon("inode-directory"), escapedCategory, categoryMenu);
if (allSameCategory && (category == firstCategory)) { if (allSameCategory && (category == firstCategory)) {
cat->setCheckable(true); cat->setCheckable(true);
cat->setChecked(true); cat->setChecked(true);
} }
categoryMenu->addAction(cat); categoryMenu->addAction(cat);
categoryActions << cat; connect(cat, &QAction::triggered, this, [this, category]() { setSelectionCategory(category); });
} }
// Tag Menu // Tag Menu
QStringList tags(BitTorrent::Session::instance()->tags().toList()); QStringList tags(BitTorrent::Session::instance()->tags().toList());
std::sort(tags.begin(), tags.end(), Utils::String::naturalLessThan<Qt::CaseInsensitive>); std::sort(tags.begin(), tags.end(), Utils::String::naturalLessThan<Qt::CaseInsensitive>);
QList<QAction *> tagsActions;
QMenu *tagsMenu = listMenu.addMenu(GuiIconProvider::instance()->getIcon("view-categories"), tr("Tags")); QMenu *tagsMenu = listMenu->addMenu(GuiIconProvider::instance()->getIcon("view-categories"), tr("Tags"));
tagsActions << tagsMenu->addAction(GuiIconProvider::instance()->getIcon("list-add"), tr("Add...", "Add / assign multiple tags..."));
tagsActions << tagsMenu->addAction(GuiIconProvider::instance()->getIcon("edit-clear"), tr("Remove All", "Remove all tags")); const QAction *addTagAction = tagsMenu->addAction(GuiIconProvider::instance()->getIcon("list-add"), tr("Add...", "Add / assign multiple tags..."));
connect(addTagAction, &QAction::triggered, this, &TransferListWidget::askAddTagsForSelection);
const QAction *removeTagsAction = tagsMenu->addAction(GuiIconProvider::instance()->getIcon("edit-clear"), tr("Remove All", "Remove all tags"));
connect(removeTagsAction, &QAction::triggered, this, [this]()
{
if (Preferences::instance()->confirmRemoveAllTags())
confirmRemoveAllTagsForSelection();
else
clearSelectionTags();
});
tagsMenu->addSeparator(); tagsMenu->addSeparator();
for (const QString &tag : asConst(tags)) { for (const QString &tag : asConst(tags)) {
const Qt::CheckState initialState = tagsInAll.contains(tag) ? Qt::Checked const Qt::CheckState initialState = tagsInAll.contains(tag) ? Qt::Checked
: tagsInAny.contains(tag) ? Qt::PartiallyChecked : tagsInAny.contains(tag) ? Qt::PartiallyChecked
@ -1081,89 +1103,60 @@ void TransferListWidget::displayListMenu(const QPoint&)
} }
if (allSameAutoTMM) { if (allSameAutoTMM) {
actionAutoTMM.setChecked(firstAutoTMM); actionAutoTMM->setChecked(firstAutoTMM);
listMenu.addAction(&actionAutoTMM); listMenu->addAction(actionAutoTMM);
} }
listMenu.addSeparator(); listMenu->addSeparator();
if (oneNotSeed) if (oneNotSeed)
listMenu.addAction(&actionSetDownloadLimit); listMenu->addAction(actionSetDownloadLimit);
listMenu.addAction(&actionSetUploadLimit); listMenu->addAction(actionSetUploadLimit);
listMenu.addAction(&actionSetMaxRatio); listMenu->addAction(actionSetMaxRatio);
if (!oneNotSeed && allSameSuperSeeding && oneHasMetadata) { if (!oneNotSeed && allSameSuperSeeding && oneHasMetadata) {
actionSuperSeedingMode.setChecked(superSeedingMode); actionSuperSeedingMode->setChecked(superSeedingMode);
listMenu.addAction(&actionSuperSeedingMode); listMenu->addAction(actionSuperSeedingMode);
} }
listMenu.addSeparator(); listMenu->addSeparator();
bool addedPreviewAction = false; bool addedPreviewAction = false;
if (needsPreview) { if (needsPreview) {
listMenu.addAction(&actionPreviewFile); listMenu->addAction(actionPreviewFile);
addedPreviewAction = true; addedPreviewAction = true;
} }
if (oneNotSeed) { if (oneNotSeed) {
if (allSameSequentialDownloadMode) { if (allSameSequentialDownloadMode) {
actionSequentialDownload.setChecked(sequentialDownloadMode); actionSequentialDownload->setChecked(sequentialDownloadMode);
listMenu.addAction(&actionSequentialDownload); listMenu->addAction(actionSequentialDownload);
addedPreviewAction = true; addedPreviewAction = true;
} }
if (allSamePrioFirstlast) { if (allSamePrioFirstlast) {
actionFirstLastPiecePrio.setChecked(prioritizeFirstLast); actionFirstLastPiecePrio->setChecked(prioritizeFirstLast);
listMenu.addAction(&actionFirstLastPiecePrio); listMenu->addAction(actionFirstLastPiecePrio);
addedPreviewAction = true; addedPreviewAction = true;
} }
} }
if (addedPreviewAction) if (addedPreviewAction)
listMenu.addSeparator(); listMenu->addSeparator();
if (oneHasMetadata) { if (oneHasMetadata) {
listMenu.addAction(&actionForceRecheck); listMenu->addAction(actionForceRecheck);
listMenu.addAction(&actionForceReannounce); listMenu->addAction(actionForceReannounce);
listMenu.addSeparator(); listMenu->addSeparator();
} }
listMenu.addAction(&actionOpenDestinationFolder); listMenu->addAction(actionOpenDestinationFolder);
if (BitTorrent::Session::instance()->isQueueingSystemEnabled() && oneNotSeed) { if (BitTorrent::Session::instance()->isQueueingSystemEnabled() && oneNotSeed) {
listMenu.addSeparator(); listMenu->addSeparator();
QMenu *prioMenu = listMenu.addMenu(tr("Priority")); QMenu *prioMenu = listMenu->addMenu(tr("Priority"));
prioMenu->addAction(&actionTopPriority); prioMenu->addAction(actionTopPriority);
prioMenu->addAction(&actionIncreasePriority); prioMenu->addAction(actionIncreasePriority);
prioMenu->addAction(&actionDecreasePriority); prioMenu->addAction(actionDecreasePriority);
prioMenu->addAction(&actionBottomPriority); prioMenu->addAction(actionBottomPriority);
} }
listMenu.addSeparator(); listMenu->addSeparator();
listMenu.addAction(&actionCopyName); listMenu->addAction(actionCopyName);
listMenu.addAction(&actionCopyHash); listMenu->addAction(actionCopyHash);
listMenu.addAction(&actionCopyMagnetLink); listMenu->addAction(actionCopyMagnetLink);
// Call menu
QAction *act = nullptr; listMenu->popup(QCursor::pos());
act = listMenu.exec(QCursor::pos());
if (act) {
// Parse category & tag actions only (others have slots assigned)
int i = categoryActions.indexOf(act);
if (i >= 0) {
// Category action
if (i == 0) {
// New Category
askNewCategoryForSelection();
}
else {
QString category = "";
if (i > 1)
category = categories.at(i - 2);
// Update Category
setSelectionCategory(category);
}
}
i = tagsActions.indexOf(act);
if (i == 0) {
askAddTagsForSelection();
}
else if (i == 1) {
if (Preferences::instance()->confirmRemoveAllTags())
confirmRemoveAllTagsForSelection();
else
clearSelectionTags();
}
}
} }
void TransferListWidget::currentChanged(const QModelIndex &current, const QModelIndex&) void TransferListWidget::currentChanged(const QModelIndex &current, const QModelIndex&)

Loading…
Cancel
Save