diff --git a/src/gui/addnewtorrentdialog.cpp b/src/gui/addnewtorrentdialog.cpp index cb077db9d..c063bcf18 100644 --- a/src/gui/addnewtorrentdialog.cpp +++ b/src/gui/addnewtorrentdialog.cpp @@ -457,42 +457,57 @@ void AddNewTorrentDialog::populateSavePathComboBox() void AddNewTorrentDialog::displayContentTreeMenu(const QPoint &) { - QMenu myFilesLlistMenu; const QModelIndexList selectedRows = m_ui->contentTreeView->selectionModel()->selectedRows(0); - QAction *actRename = nullptr; - if (selectedRows.size() == 1) { - 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) { - qDebug("Setting priority(%d) for file at row %d", static_cast(prio), index.row()); - m_contentModel->setData(m_contentModel->index(index.row(), PRIORITY, index.parent()), static_cast(prio)); - } + + const auto applyPriorities = [this, selectedRows](const BitTorrent::DownloadPriority prio) + { + for (const QModelIndex &index : selectedRows) { + m_contentModel->setData( + m_contentModel->index(index.row(), PRIORITY, index.parent()) + , static_cast(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() diff --git a/src/gui/categoryfilterwidget.cpp b/src/gui/categoryfilterwidget.cpp index fda482e95..ba0867e57 100644 --- a/src/gui/categoryfilterwidget.cpp +++ b/src/gui/categoryfilterwidget.cpp @@ -104,11 +104,12 @@ void CategoryFilterWidget::onCurrentRowChanged(const QModelIndex ¤t, const emit categoryChanged(getCategoryFilter(static_cast(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") , tr("Add category...")); connect(addAct, &QAction::triggered, this, &CategoryFilterWidget::addCategory); @@ -116,46 +117,46 @@ void CategoryFilterWidget::showMenu(QPoint) const auto selectedRows = selectionModel()->selectedRows(); if (!selectedRows.empty() && !CategoryFilterModel::isSpecialItem(selectedRows.first())) { if (BitTorrent::Session::instance()->isSubcategoriesEnabled()) { - QAction *addSubAct = menu.addAction( + const QAction *addSubAct = menu->addAction( GuiIconProvider::instance()->getIcon("list-add") , tr("Add subcategory...")); connect(addSubAct, &QAction::triggered, this, &CategoryFilterWidget::addSubcategory); } - QAction *editAct = menu.addAction( + const QAction *editAct = menu->addAction( GuiIconProvider::instance()->getIcon("document-edit") , tr("Edit category...")); connect(editAct, &QAction::triggered, this, &CategoryFilterWidget::editCategory); - QAction *removeAct = menu.addAction( + const QAction *removeAct = menu->addAction( GuiIconProvider::instance()->getIcon("list-remove") , tr("Remove category")); connect(removeAct, &QAction::triggered, this, &CategoryFilterWidget::removeCategory); } - QAction *removeUnusedAct = menu.addAction( + const QAction *removeUnusedAct = menu->addAction( GuiIconProvider::instance()->getIcon("list-remove") , tr("Remove unused categories")); 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") , tr("Resume torrents")); connect(startAct, &QAction::triggered, this, &CategoryFilterWidget::actionResumeTorrentsTriggered); - QAction *pauseAct = menu.addAction( + const QAction *pauseAct = menu->addAction( GuiIconProvider::instance()->getIcon("media-playback-pause") , tr("Pause torrents")); connect(pauseAct, &QAction::triggered, this, &CategoryFilterWidget::actionPauseTorrentsTriggered); - QAction *deleteTorrentsAct = menu.addAction( + const QAction *deleteTorrentsAct = menu->addAction( GuiIconProvider::instance()->getIcon("edit-delete") , tr("Delete torrents")); connect(deleteTorrentsAct, &QAction::triggered, this, &CategoryFilterWidget::actionDeleteTorrentsTriggered); - menu.exec(QCursor::pos()); + menu->popup(QCursor::pos()); } void CategoryFilterWidget::callUpdateGeometry() diff --git a/src/gui/categoryfilterwidget.h b/src/gui/categoryfilterwidget.h index da9af5dca..1e0539092 100644 --- a/src/gui/categoryfilterwidget.h +++ b/src/gui/categoryfilterwidget.h @@ -48,7 +48,7 @@ signals: private slots: void onCurrentRowChanged(const QModelIndex ¤t, const QModelIndex &previous); - void showMenu(QPoint); + void showMenu(const QPoint &); void callUpdateGeometry(); void addCategory(); void addSubcategory(); diff --git a/src/gui/fspathedit_p.cpp b/src/gui/fspathedit_p.cpp index 4153e1787..1b8891618 100644 --- a/src/gui/fspathedit_p.cpp +++ b/src/gui/fspathedit_p.cpp @@ -284,13 +284,14 @@ void Private::FileLineEdit::keyPressEvent(QKeyEvent *e) void Private::FileLineEdit::contextMenuEvent(QContextMenuEvent *event) { QMenu *menu = createStandardContextMenu(); - menu->addSeparator(); + menu->setAttribute(Qt::WA_DeleteOnClose); + if (m_browseAction) { menu->addSeparator(); menu->addAction(m_browseAction); } - menu->exec(event->globalPos()); - delete menu; + + menu->popup(event->globalPos()); } void Private::FileLineEdit::showCompletionPopup() diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index b886fb258..f529629e0 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -578,12 +578,14 @@ void MainWindow::addToolbarContextMenu() 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() @@ -688,7 +690,9 @@ void MainWindow::showFilterContextMenu(const QPoint &) const Preferences *pref = Preferences::instance(); QMenu *menu = m_searchFilter->createStandardContextMenu(); + menu->setAttribute(Qt::WA_DeleteOnClose); menu->addSeparator(); + QAction *useRegexAct = new QAction(tr("Use regular expressions"), menu); useRegexAct->setCheckable(true); useRegexAct->setChecked(pref->getRegexAsFilteringPatternForTransferList()); @@ -697,7 +701,7 @@ void MainWindow::showFilterContextMenu(const QPoint &) connect(useRegexAct, &QAction::toggled, pref, &Preferences::setRegexAsFilteringPatternForTransferList); 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) diff --git a/src/gui/mainwindow.h b/src/gui/mainwindow.h index b11f82482..ad1566f8d 100644 --- a/src/gui/mainwindow.h +++ b/src/gui/mainwindow.h @@ -181,7 +181,7 @@ private slots: #if defined(Q_OS_WIN) || defined(Q_OS_MAC) void checkProgramUpdate(); #endif - void toolbarMenuRequested(QPoint); + void toolbarMenuRequested(const QPoint &point); void toolbarIconsOnly(); void toolbarTextOnly(); void toolbarTextBeside(); diff --git a/src/gui/optionsdialog.cpp b/src/gui/optionsdialog.cpp index 952646dbd..6d957a714 100644 --- a/src/gui/optionsdialog.cpp +++ b/src/gui/optionsdialog.cpp @@ -423,7 +423,12 @@ OptionsDialog::OptionsDialog(QWidget *parent) connect(m_ui->checkSmartFilterDownloadRepacks, &QCheckBox::toggled, this, &OptionsDialog::enableApplyButton); connect(m_ui->spinRSSRefreshInterval, 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 m_applyButton->setEnabled(false); diff --git a/src/gui/properties/peerlistwidget.cpp b/src/gui/properties/peerlistwidget.cpp index 5cbfe5111..5682b840c 100644 --- a/src/gui/properties/peerlistwidget.cpp +++ b/src/gui/properties/peerlistwidget.cpp @@ -153,41 +153,45 @@ PeerListWidget::~PeerListWidget() void PeerListWidget::displayToggleColumnsMenu(const QPoint &) { - QMenu hideshowColumn(this); - hideshowColumn.setTitle(tr("Column visibility")); - QList actions; + QMenu *menu = new QMenu(this); + menu->setAttribute(Qt::WA_DeleteOnClose); + menu->setTitle(tr("Column visibility")); + for (int i = 0; i < PeerListDelegate::IP_HIDDEN; ++i) { - if ((i == PeerListDelegate::COUNTRY) && !Preferences::instance()->resolvePeerCountries()) { - actions.append(nullptr); // keep the index in sync + if ((i == PeerListDelegate::COUNTRY) && !Preferences::instance()->resolvePeerCountries()) 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->setChecked(!isColumnHidden(i)); - actions.append(myAct); + myAct->setData(i); } - int visibleCols = 0; - for (int i = 0; i < PeerListDelegate::IP_HIDDEN; ++i) { - if (!isColumnHidden(i)) - ++visibleCols; - if (visibleCols > 1) - break; - } + connect(menu, &QMenu::triggered, this, [this](const QAction *action) + { + int visibleCols = 0; + for (int i = 0; i < PeerListDelegate::IP_HIDDEN; ++i) { + if (!isColumnHidden(i)) + ++visibleCols; + + if (visibleCols > 1) + break; + } + + const int col = action->data().toInt(); - // Call menu - 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)) return; + setColumnHidden(col, !isColumnHidden(col)); + if (!isColumnHidden(col) && (columnWidth(col) <= 5)) resizeColumnToContents(col); + saveSettings(); - } + }); + + menu->popup(QCursor::pos()); } void PeerListWidget::updatePeerHostNameResolutionState() @@ -222,56 +226,49 @@ void PeerListWidget::updatePeerCountryResolutionState() void PeerListWidget::showPeerListMenu(const QPoint &) { - QMenu menu; - bool emptyMenu = true; BitTorrent::TorrentHandle *const torrent = m_properties->getCurrentTorrent(); if (!torrent) return; + QMenu *menu = new QMenu(this); + menu->setAttribute(Qt::WA_DeleteOnClose); + // Add Peer Action - QAction *addPeerAct = nullptr; if (!torrent->isQueued() && !torrent->isChecking()) { - addPeerAct = menu.addAction(GuiIconProvider::instance()->getIcon("user-group-new"), tr("Add a new peer...")); - emptyMenu = false; - } - 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 peersList = PeersAdditionDialog::askForPeers(this); - int peerCount = 0; - for (const BitTorrent::PeerAddress &addr : peersList) { - if (torrent->connectPeer(addr)) { - qDebug("Adding peer %s...", qUtf8Printable(addr.ip.toString())); - Logger::instance()->addMessage(tr("Manually adding peer '%1'...").arg(addr.ip.toString())); - ++peerCount; - } - else { - Logger::instance()->addMessage(tr("The peer '%1' could not be added to this torrent.").arg(addr.ip.toString()), Log::WARNING); + const QAction *addPeerAct = menu->addAction(GuiIconProvider::instance()->getIcon("user-group-new"), tr("Add a new peer...")); + connect(addPeerAct, &QAction::triggered, this, [this, torrent]() + { + const QList peersList = PeersAdditionDialog::askForPeers(this); + int peerCount = 0; + for (const BitTorrent::PeerAddress &addr : peersList) { + if (torrent->connectPeer(addr)) { + Logger::instance()->addMessage(tr("Manually adding peer '%1'...").arg(addr.ip.toString())); + ++peerCount; + } + else { + Logger::instance()->addMessage(tr("The peer '%1' could not be added to this torrent.").arg(addr.ip.toString()), Log::WARNING); + } } - } - if (peerCount < peersList.length()) - QMessageBox::information(this, tr("Peer addition"), tr("Some peers could not be added. Check the Log for details.")); - else if (peerCount > 0) - QMessageBox::information(this, tr("Peer addition"), tr("The peers were added to this torrent.")); - return; - } - if (act == banAct) { - banSelectedPeers(); - return; + if (peerCount < peersList.length()) + QMessageBox::information(this, tr("Peer addition"), tr("Some peers could not be added. Check the Log for details.")); + else if (peerCount > 0) + QMessageBox::information(this, tr("Peer addition"), tr("The peers were added to this torrent.")); + }); } - if (act == copyPeerAct) { - copySelectedPeers(); - return; + + if (!selectionModel()->selectedRows().isEmpty()) { + 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() diff --git a/src/gui/properties/propertieswidget.cpp b/src/gui/properties/propertieswidget.cpp index 2796740f8..196d2fa68 100644 --- a/src/gui/properties/propertieswidget.cpp +++ b/src/gui/properties/propertieswidget.cpp @@ -582,96 +582,105 @@ void PropertiesWidget::displayFilesListMenu(const QPoint &) const QModelIndexList selectedRows = m_ui->filesList->selectionModel()->selectedRows(0); if (selectedRows.empty()) return; - QMenu myFilesListMenu; - QAction *actOpen = nullptr; - QAction *actOpenContainingFolder = nullptr; - QAction *actRename = nullptr; + QMenu *menu = new QMenu(this); + menu->setAttribute(Qt::WA_DeleteOnClose); + if (selectedRows.size() == 1) { - actOpen = myFilesListMenu.addAction(GuiIconProvider::instance()->getIcon("folder-documents"), tr("Open")); - actOpenContainingFolder = myFilesListMenu.addAction(GuiIconProvider::instance()->getIcon("inode-directory"), tr("Open Containing Folder")); - actRename = myFilesListMenu.addAction(GuiIconProvider::instance()->getIcon("edit-rename"), tr("Rename...")); - myFilesListMenu.addSeparator(); + const QModelIndex index = selectedRows[0]; + + const QAction *actOpen = menu->addAction(GuiIconProvider::instance()->getIcon("folder-documents"), tr("Open")); + 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()) { - subMenu.setTitle(tr("Priority")); - subMenu.addAction(m_ui->actionNotDownloaded); - subMenu.addAction(m_ui->actionNormal); - subMenu.addAction(m_ui->actionHigh); - subMenu.addAction(m_ui->actionMaximum); - myFilesListMenu.addMenu(&subMenu); + subMenu->setTitle(tr("Priority")); + + const auto applyPriorities = [this, selectedRows](const BitTorrent::DownloadPriority prio) + { + for (const QModelIndex &index : selectedRows) { + m_propListModel->setData( + m_propListModel->index(index.row(), PRIORITY, index.parent()), static_cast(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() // so we just close menu when an appropriate model is reset connect(m_ui->filesList->model(), &QAbstractItemModel::modelAboutToBeReset - , &myFilesListMenu, [&myFilesListMenu]() + , menu, [&menu]() { - myFilesListMenu.setActiveAction(nullptr); - myFilesListMenu.close(); + menu->setActiveAction(nullptr); + menu->close(); }); - // Call menu - const QAction *act = myFilesListMenu.exec(QCursor::pos()); - if (!act) return; - const QModelIndex index = selectedRows[0]; - 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(prio), index.row()); - m_propListModel->setData(m_propListModel->index(index.row(), PRIORITY, index.parent()), static_cast(prio)); - } - // Save changes - filteredFilesChanged(); - } + menu->popup(QCursor::pos()); } void PropertiesWidget::displayWebSeedListMenu(const QPoint &) { if (!m_torrent) return; - QMenu seedMenu; - QModelIndexList rows = m_ui->listWebSeeds->selectionModel()->selectedRows(); - QAction *actAdd = seedMenu.addAction(GuiIconProvider::instance()->getIcon("list-add"), tr("New Web seed")); - QAction *actDel = nullptr; - QAction *actCpy = nullptr; - QAction *actEdit = nullptr; + const QModelIndexList rows = m_ui->listWebSeeds->selectionModel()->selectedRows(); + + QMenu *menu = new QMenu(this); + menu->setAttribute(Qt::WA_DeleteOnClose); + + const QAction *actAdd = menu->addAction(GuiIconProvider::instance()->getIcon("list-add"), tr("New Web seed")); + connect(actAdd, &QAction::triggered, this, &PropertiesWidget::askWebSeed); if (!rows.isEmpty()) { - actDel = seedMenu.addAction(GuiIconProvider::instance()->getIcon("list-remove"), tr("Remove Web seed")); - seedMenu.addSeparator(); - 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")); + const QAction *actDel = menu->addAction(GuiIconProvider::instance()->getIcon("list-remove"), tr("Remove Web seed")); + connect(actDel, &QAction::triggered, this, &PropertiesWidget::deleteSelectedUrlSeeds); + + menu->addSeparator(); + + const QAction *actCpy = menu->addAction(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy Web seed URL")); + connect(actCpy, &QAction::triggered, this, &PropertiesWidget::copySelectedWebSeedsToClipboard); + + const QAction *actEdit = menu->addAction(GuiIconProvider::instance()->getIcon("edit-rename"), tr("Edit Web seed URL")); + connect(actEdit, &QAction::triggered, this, &PropertiesWidget::editWebSeed); } - const QAction *act = seedMenu.exec(QCursor::pos()); - if (!act) return; - - if (act == actAdd) - askWebSeed(); - else if (act == actDel) - deleteSelectedUrlSeeds(); - else if (act == actCpy) - copySelectedWebSeedsToClipboard(); - else if (act == actEdit) - editWebSeed(); + menu->popup(QCursor::pos()); } void PropertiesWidget::openSelectedFile() diff --git a/src/gui/properties/propertieswidget.h b/src/gui/properties/propertieswidget.h index 7d4265c55..3fa9b3474 100644 --- a/src/gui/properties/propertieswidget.h +++ b/src/gui/properties/propertieswidget.h @@ -90,8 +90,8 @@ protected slots: void deleteSelectedUrlSeeds(); void copySelectedWebSeedsToClipboard() const; void editWebSeed(); - void displayFilesListMenu(const QPoint &pos); - void displayWebSeedListMenu(const QPoint &pos); + void displayFilesListMenu(const QPoint &); + void displayWebSeedListMenu(const QPoint &); void filteredFilesChanged(); void showPiecesDownloaded(bool show); void showPiecesAvailability(bool show); diff --git a/src/gui/properties/speedwidget.cpp b/src/gui/properties/speedwidget.cpp index b3a1d3b3a..9b337c3fa 100644 --- a/src/gui/properties/speedwidget.cpp +++ b/src/gui/properties/speedwidget.cpp @@ -48,8 +48,9 @@ ComboBoxMenuButton::ComboBoxMenuButton(QWidget *parent, QMenu *menu) void ComboBoxMenuButton::showPopup() { - QPoint p = mapToGlobal(QPoint(0, height())); - m_menu->exec(p); + const QPoint p = mapToGlobal(QPoint(0, height())); + m_menu->popup(p); + QComboBox::hidePopup(); } diff --git a/src/gui/properties/trackerlistwidget.cpp b/src/gui/properties/trackerlistwidget.cpp index 72dffd7e1..4146e4182 100644 --- a/src/gui/properties/trackerlistwidget.cpp +++ b/src/gui/properties/trackerlistwidget.cpp @@ -521,59 +521,45 @@ void TrackerListWidget::reannounceSelected() loadTrackers(); } -void TrackerListWidget::showTrackerListMenu(QPoint) +void TrackerListWidget::showTrackerListMenu(const QPoint &) { BitTorrent::TorrentHandle *const torrent = m_properties->getCurrentTorrent(); if (!torrent) return; - //QList selected_items = getSelectedTrackerItems(); - QMenu menu; + QMenu *menu = new QMenu(this); + menu->setAttribute(Qt::WA_DeleteOnClose); + // Add actions - QAction *addAct = menu.addAction(GuiIconProvider::instance()->getIcon("list-add"), tr("Add a new tracker...")); - QAction *copyAct = nullptr; - QAction *delAct = nullptr; - QAction *editAct = nullptr; + const QAction *addAct = menu->addAction(GuiIconProvider::instance()->getIcon("list-add"), tr("Add a new tracker...")); + connect(addAct, &QAction::triggered, this, &TrackerListWidget::askForTrackers); + if (!getSelectedTrackerItems().isEmpty()) { - editAct = menu.addAction(GuiIconProvider::instance()->getIcon("edit-rename"),tr("Edit tracker URL...")); - delAct = menu.addAction(GuiIconProvider::instance()->getIcon("list-remove"), tr("Remove tracker")); - copyAct = menu.addAction(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy tracker URL")); + const QAction *editAct = menu->addAction(GuiIconProvider::instance()->getIcon("edit-rename"),tr("Edit tracker URL...")); + connect(editAct, &QAction::triggered, this, &TrackerListWidget::editSelectedTracker); + + 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()) { - reannounceSelAct = menu.addAction(GuiIconProvider::instance()->getIcon("view-refresh"), tr("Force reannounce to selected trackers")); - menu.addSeparator(); - reannounceAllAct = menu.addAction(GuiIconProvider::instance()->getIcon("view-refresh"), tr("Force reannounce to all trackers")); + const QAction *reannounceSelAct = menu->addAction(GuiIconProvider::instance()->getIcon("view-refresh"), tr("Force reannounce to selected trackers")); + connect(reannounceSelAct, &QAction::triggered, this, &TrackerListWidget::reannounceSelected); + + menu->addSeparator(); + + const QAction *reannounceAllAct = menu->addAction(GuiIconProvider::instance()->getIcon("view-refresh"), tr("Force reannounce to all trackers")); + connect(reannounceAllAct, &QAction::triggered, this, [this]() + { + BitTorrent::TorrentHandle *h = m_properties->getCurrentTorrent(); + h->forceReannounce(); + h->forceDHTAnnounce(); + }); } - QAction *act = menu.exec(QCursor::pos()); - if (act == nullptr) return; - if (act == addAct) { - askForTrackers(); - return; - } - if (act == copyAct) { - copyTrackerUrl(); - return; - } - if (act == delAct) { - deleteSelectedTrackers(); - return; - } - if (act == reannounceSelAct) { - reannounceSelected(); - return; - } - if (act == reannounceAllAct) { - BitTorrent::TorrentHandle *h = m_properties->getCurrentTorrent(); - h->forceReannounce(); - h->forceDHTAnnounce(); - return; - } - if (act == editAct) { - editSelectedTracker(); - return; - } + menu->popup(QCursor::pos()); } void TrackerListWidget::loadSettings() @@ -615,25 +601,32 @@ int TrackerListWidget::visibleColumnsCount() const void TrackerListWidget::displayToggleColumnsMenu(const QPoint &) { - QMenu hideshowColumn(this); - hideshowColumn.setTitle(tr("Column visibility")); + QMenu *menu = new QMenu(this); + menu->setAttribute(Qt::WA_DeleteOnClose); + menu->setTitle(tr("Column visibility")); + 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->setChecked(!isColumnHidden(i)); myAct->setData(i); } - // Call menu - QAction *act = hideshowColumn.exec(QCursor::pos()); - if (!act) return; + connect(menu, &QMenu::triggered, this, [this](const QAction *action) + { + const int col = action->data().toInt(); + Q_ASSERT(visibleColumnsCount() > 0); - int col = act->data().toInt(); - Q_ASSERT(visibleColumnsCount() > 0); - if (!isColumnHidden(col) && (visibleColumnsCount() == 1)) - return; - setColumnHidden(col, !isColumnHidden(col)); - if (!isColumnHidden(col) && (columnWidth(col) <= 5)) - resizeColumnToContents(col); - saveSettings(); + if (!isColumnHidden(col) && (visibleColumnsCount() == 1)) + return; + + setColumnHidden(col, !isColumnHidden(col)); + + if (!isColumnHidden(col) && (columnWidth(col) <= 5)) + resizeColumnToContents(col); + + saveSettings(); + }); + + menu->popup(QCursor::pos()); } diff --git a/src/gui/properties/trackerlistwidget.h b/src/gui/properties/trackerlistwidget.h index 7ea25d4fd..d892b4a38 100644 --- a/src/gui/properties/trackerlistwidget.h +++ b/src/gui/properties/trackerlistwidget.h @@ -82,7 +82,7 @@ public slots: void reannounceSelected(); void deleteSelectedTrackers(); void editSelectedTracker(); - void showTrackerListMenu(QPoint); + void showTrackerListMenu(const QPoint &); void displayToggleColumnsMenu(const QPoint &); void loadSettings(); void saveSettings() const; diff --git a/src/gui/rss/automatedrssdownloader.cpp b/src/gui/rss/automatedrssdownloader.cpp index 09112f244..9555a6e16 100644 --- a/src/gui/rss/automatedrssdownloader.cpp +++ b/src/gui/rss/automatedrssdownloader.cpp @@ -468,37 +468,36 @@ void AutomatedRssDownloader::on_importBtn_clicked() void AutomatedRssDownloader::displayRulesListMenu() { - QMenu menu; - QAction *addAct = menu.addAction(GuiIconProvider::instance()->getIcon("list-add"), tr("Add new rule...")); - QAction *delAct = nullptr; - QAction *renameAct = nullptr; - QAction *clearAct = nullptr; + QMenu *menu = new QMenu(this); + menu->setAttribute(Qt::WA_DeleteOnClose); + + const QAction *addAct = menu->addAction(GuiIconProvider::instance()->getIcon("list-add"), tr("Add new rule...")); + connect(addAct, &QAction::triggered, this, &AutomatedRssDownloader::on_addRuleBtn_clicked); + const QList selection = m_ui->listRules->selectedItems(); if (!selection.isEmpty()) { if (selection.count() == 1) { - delAct = menu.addAction(GuiIconProvider::instance()->getIcon("list-remove"), tr("Delete rule")); - menu.addSeparator(); - renameAct = menu.addAction(GuiIconProvider::instance()->getIcon("edit-rename"), tr("Rename rule...")); + const QAction *delAct = menu->addAction(GuiIconProvider::instance()->getIcon("list-remove"), tr("Delete rule")); + connect(delAct, &QAction::triggered, this, &AutomatedRssDownloader::on_removeRuleBtn_clicked); + + menu->addSeparator(); + + const QAction *renameAct = menu->addAction(GuiIconProvider::instance()->getIcon("edit-rename"), tr("Rename rule...")); + connect(renameAct, &QAction::triggered, this, &AutomatedRssDownloader::renameSelectedRule); } 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...")); + + menu->addSeparator(); + + const QAction *clearAct = menu->addAction(GuiIconProvider::instance()->getIcon("edit-clear"), tr("Clear downloaded episodes...")); + connect(clearAct, &QAction::triggered, this, &AutomatedRssDownloader::clearSelectedRuleDownloadedEpisodeList); } - QAction *act = menu.exec(QCursor::pos()); - if (!act) return; - - if (act == addAct) - on_addRuleBtn_clicked(); - else if (act == delAct) - on_removeRuleBtn_clicked(); - else if (act == renameAct) - renameSelectedRule(); - else if (act == clearAct) - clearSelectedRuleDownloadedEpisodeList(); + menu->popup(QCursor::pos()); } void AutomatedRssDownloader::renameSelectedRule() diff --git a/src/gui/rss/rsswidget.cpp b/src/gui/rss/rsswidget.cpp index 552702c89..e1613e4ed 100644 --- a/src/gui/rss/rsswidget.cpp +++ b/src/gui/rss/rsswidget.cpp @@ -147,38 +147,45 @@ void RSSWidget::displayRSSListMenu(const QPoint &pos) if (!m_feedListWidget->indexAt(pos).isValid()) // No item under the mouse, clear selection m_feedListWidget->clearSelection(); - QMenu myRSSListMenu(this); - QList selectedItems = m_feedListWidget->selectedItems(); + + QMenu *menu = new QMenu(this); + menu->setAttribute(Qt::WA_DeleteOnClose); + + const QList selectedItems = m_feedListWidget->selectedItems(); if (!selectedItems.isEmpty()) { - myRSSListMenu.addAction(m_ui->actionUpdate); - myRSSListMenu.addAction(m_ui->actionMarkItemsRead); - myRSSListMenu.addSeparator(); + menu->addAction(m_ui->actionUpdate); + menu->addAction(m_ui->actionMarkItemsRead); + menu->addSeparator(); + if (selectedItems.size() == 1) { if (selectedItems.first() != m_feedListWidget->stickyUnreadItem()) { - myRSSListMenu.addAction(m_ui->actionRename); - myRSSListMenu.addAction(m_ui->actionDelete); - myRSSListMenu.addSeparator(); + menu->addAction(m_ui->actionRename); + menu->addAction(m_ui->actionDelete); + menu->addSeparator(); if (m_feedListWidget->isFolder(selectedItems.first())) - myRSSListMenu.addAction(m_ui->actionNewFolder); + menu->addAction(m_ui->actionNewFolder); } } else { - myRSSListMenu.addAction(m_ui->actionDelete); - myRSSListMenu.addSeparator(); + menu->addAction(m_ui->actionDelete); + menu->addSeparator(); } - myRSSListMenu.addAction(m_ui->actionNewSubscription); + + menu->addAction(m_ui->actionNewSubscription); + if (m_feedListWidget->isFeed(selectedItems.first())) { - myRSSListMenu.addSeparator(); - myRSSListMenu.addAction(m_ui->actionCopyFeedURL); + menu->addSeparator(); + menu->addAction(m_ui->actionCopyFeedURL); } } else { - myRSSListMenu.addAction(m_ui->actionNewSubscription); - myRSSListMenu.addAction(m_ui->actionNewFolder); - myRSSListMenu.addSeparator(); - myRSSListMenu.addAction(m_ui->actionUpdateAllFeeds); + menu->addAction(m_ui->actionNewSubscription); + menu->addAction(m_ui->actionNewFolder); + menu->addSeparator(); + menu->addAction(m_ui->actionUpdateAllFeeds); } - myRSSListMenu.exec(QCursor::pos()); + + menu->popup(QCursor::pos()); } void RSSWidget::displayItemsListMenu(const QPoint &) @@ -197,13 +204,16 @@ void RSSWidget::displayItemsListMenu(const QPoint &) break; } - QMenu myItemListMenu(this); + QMenu *myItemListMenu = new QMenu(this); + myItemListMenu->setAttribute(Qt::WA_DeleteOnClose); + if (hasTorrent) - myItemListMenu.addAction(m_ui->actionDownloadTorrent); + myItemListMenu->addAction(m_ui->actionDownloadTorrent); if (hasLink) - myItemListMenu.addAction(m_ui->actionOpenNewsURL); - if (hasTorrent || hasLink) - myItemListMenu.exec(QCursor::pos()); + myItemListMenu->addAction(m_ui->actionOpenNewsURL); + + if (!myItemListMenu->isEmpty()) + myItemListMenu->popup(QCursor::pos()); } void RSSWidget::askNewFolder() @@ -516,7 +526,9 @@ void RSSWidget::updateRefreshInterval(uint val) 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) diff --git a/src/gui/search/pluginselectdialog.cpp b/src/gui/search/pluginselectdialog.cpp index c558c95e4..f803b0c4f 100644 --- a/src/gui/search/pluginselectdialog.cpp +++ b/src/gui/search/pluginselectdialog.cpp @@ -163,19 +163,22 @@ 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 - QList items = m_ui->pluginsTree->selectedItems(); + const QList items = m_ui->pluginsTree->selectedItems(); 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); - myContextMenu.addAction(m_ui->actionEnable); - myContextMenu.addSeparator(); - myContextMenu.addAction(m_ui->actionUninstall); - myContextMenu.exec(QCursor::pos()); + myContextMenu->addAction(m_ui->actionEnable); + myContextMenu->addSeparator(); + myContextMenu->addAction(m_ui->actionUninstall); + + myContextMenu->popup(QCursor::pos()); } void PluginSelectDialog::on_closeButton_clicked() diff --git a/src/gui/search/pluginselectdialog.h b/src/gui/search/pluginselectdialog.h index c8bf18c25..4406d0092 100644 --- a/src/gui/search/pluginselectdialog.h +++ b/src/gui/search/pluginselectdialog.h @@ -71,7 +71,7 @@ private slots: void on_closeButton_clicked(); void togglePluginState(QTreeWidgetItem*, int); void setRowColor(int row, const QString &color); - void displayContextMenu(const QPoint &pos); + void displayContextMenu(const QPoint &); void enableSelection(bool enable); void askForLocalPlugin(); void askForPluginUrl(); diff --git a/src/gui/search/searchjobwidget.cpp b/src/gui/search/searchjobwidget.cpp index 87413921c..25206a8d2 100644 --- a/src/gui/search/searchjobwidget.cpp +++ b/src/gui/search/searchjobwidget.cpp @@ -358,7 +358,9 @@ void SearchJobWidget::showFilterContextMenu(const QPoint &) const Preferences *pref = Preferences::instance(); QMenu *menu = m_lineEditSearchResultsFilter->createStandardContextMenu(); + menu->setAttribute(Qt::WA_DeleteOnClose); menu->addSeparator(); + QAction *useRegexAct = new QAction(tr("Use regular expressions"), menu); useRegexAct->setCheckable(true); useRegexAct->setChecked(pref->getRegexAsFilteringPatternForSearchJob()); @@ -367,7 +369,7 @@ void SearchJobWidget::showFilterContextMenu(const QPoint &) connect(useRegexAct, &QAction::toggled, pref, &Preferences::setRegexAsFilteringPatternForSearchJob); connect(useRegexAct, &QAction::toggled, this, [this]() { filterSearchResults(m_lineEditSearchResultsFilter->text()); }); - menu->exec(QCursor::pos()); + menu->popup(QCursor::pos()); } QString SearchJobWidget::statusText(SearchJobWidget::Status st) diff --git a/src/gui/tagfilterwidget.cpp b/src/gui/tagfilterwidget.cpp index d9548373c..8366fd61f 100644 --- a/src/gui/tagfilterwidget.cpp +++ b/src/gui/tagfilterwidget.cpp @@ -104,47 +104,48 @@ void TagFilterWidget::onCurrentRowChanged(const QModelIndex ¤t, const QMod 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") , tr("Add tag...")); connect(addAct, &QAction::triggered, this, &TagFilterWidget::addTag); const auto selectedRows = selectionModel()->selectedRows(); if (!selectedRows.empty() && !TagFilterModel::isSpecialItem(selectedRows.first())) { - QAction *removeAct = menu.addAction( + const QAction *removeAct = menu->addAction( GuiIconProvider::instance()->getIcon("list-remove") , tr("Remove tag")); connect(removeAct, &QAction::triggered, this, &TagFilterWidget::removeTag); } - QAction *removeUnusedAct = menu.addAction( + const QAction *removeUnusedAct = menu->addAction( GuiIconProvider::instance()->getIcon("list-remove") , tr("Remove unused tags")); 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") , tr("Resume torrents")); connect(startAct, &QAction::triggered , this, &TagFilterWidget::actionResumeTorrentsTriggered); - QAction *pauseAct = menu.addAction( + const QAction *pauseAct = menu->addAction( GuiIconProvider::instance()->getIcon("media-playback-pause") , tr("Pause torrents")); connect(pauseAct, &QAction::triggered, this , &TagFilterWidget::actionPauseTorrentsTriggered); - QAction *deleteTorrentsAct = menu.addAction( + const QAction *deleteTorrentsAct = menu->addAction( GuiIconProvider::instance()->getIcon("edit-delete") , tr("Delete torrents")); connect(deleteTorrentsAct, &QAction::triggered, this , &TagFilterWidget::actionDeleteTorrentsTriggered); - menu.exec(QCursor::pos()); + menu->popup(QCursor::pos()); } void TagFilterWidget::callUpdateGeometry() diff --git a/src/gui/transferlistfilterswidget.cpp b/src/gui/transferlistfilterswidget.cpp index 580dbca25..ff21019e6 100644 --- a/src/gui/transferlistfilterswidget.cpp +++ b/src/gui/transferlistfilterswidget.cpp @@ -203,7 +203,7 @@ void StatusFilterWidget::updateTorrentNumbers() 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) { @@ -465,24 +465,21 @@ void TrackerFiltersList::handleFavicoDownloadFinished(const Net::DownloadResult } } -void TrackerFiltersList::showMenu(QPoint) +void TrackerFiltersList::showMenu(const QPoint &) { - QMenu menu(this); - QAction *startAct = menu.addAction(GuiIconProvider::instance()->getIcon("media-playback-start"), tr("Resume torrents")); - 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()); + QMenu *menu = new QMenu(this); + menu->setAttribute(Qt::WA_DeleteOnClose); - if (!act) - return; + const QAction *startAct = menu->addAction(GuiIconProvider::instance()->getIcon("media-playback-start"), tr("Resume torrents")); + 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) - transferList->startVisibleTorrents(); - else if (act == pauseAct) - transferList->pauseVisibleTorrents(); - else if (act == deleteTorrentsAct) - transferList->deleteVisibleTorrents(); + menu->popup(QCursor::pos()); } void TrackerFiltersList::applyFilter(int row) diff --git a/src/gui/transferlistfilterswidget.h b/src/gui/transferlistfilterswidget.h index dcdf99300..b3d42acb3 100644 --- a/src/gui/transferlistfilterswidget.h +++ b/src/gui/transferlistfilterswidget.h @@ -66,7 +66,7 @@ protected: TransferListWidget *transferList; private slots: - virtual void showMenu(QPoint) = 0; + virtual void showMenu(const QPoint &) = 0; virtual void applyFilter(int row) = 0; virtual void handleNewTorrent(BitTorrent::TorrentHandle *const) = 0; virtual void torrentAboutToBeDeleted(BitTorrent::TorrentHandle *const) = 0; @@ -87,7 +87,7 @@ private slots: private: // These 4 methods are virtual slots in the base class. // No need to redeclare them here as slots. - void showMenu(QPoint) override; + void showMenu(const QPoint &) override; void applyFilter(int row) override; void handleNewTorrent(BitTorrent::TorrentHandle *const) override; void torrentAboutToBeDeleted(BitTorrent::TorrentHandle *const) override; @@ -119,7 +119,7 @@ private slots: private: // These 4 methods are virtual slots in the base class. // No need to redeclare them here as slots. - void showMenu(QPoint) override; + void showMenu(const QPoint &) override; void applyFilter(int row) override; void handleNewTorrent(BitTorrent::TorrentHandle *const torrent) override; void torrentAboutToBeDeleted(BitTorrent::TorrentHandle *const torrent) override; diff --git a/src/gui/transferlistwidget.cpp b/src/gui/transferlistwidget.cpp index 002024e78..aa121ca2b 100644 --- a/src/gui/transferlistwidget.cpp +++ b/src/gui/transferlistwidget.cpp @@ -886,59 +886,59 @@ void TransferListWidget::displayListMenu(const QPoint&) if (selectedIndexes.isEmpty()) return; // Create actions - QAction actionStart(GuiIconProvider::instance()->getIcon("media-playback-start"), tr("Resume", "Resume/start the torrent"), nullptr); - connect(&actionStart, &QAction::triggered, this, &TransferListWidget::startSelectedTorrents); - QAction actionPause(GuiIconProvider::instance()->getIcon("media-playback-pause"), tr("Pause", "Pause the torrent"), nullptr); - connect(&actionPause, &QAction::triggered, this, &TransferListWidget::pauseSelectedTorrents); - QAction actionForceStart(GuiIconProvider::instance()->getIcon("media-seek-forward"), tr("Force Resume", "Force Resume/start the torrent"), nullptr); - connect(&actionForceStart, &QAction::triggered, this, &TransferListWidget::forceStartSelectedTorrents); - QAction actionDelete(GuiIconProvider::instance()->getIcon("edit-delete"), tr("Delete", "Delete the torrent"), nullptr); - connect(&actionDelete, &QAction::triggered, this, &TransferListWidget::softDeleteSelectedTorrents); - QAction actionPreviewFile(GuiIconProvider::instance()->getIcon("view-preview"), tr("Preview file..."), nullptr); - connect(&actionPreviewFile, &QAction::triggered, this, &TransferListWidget::previewSelectedTorrents); - QAction actionSetMaxRatio(QIcon(QLatin1String(":/icons/skin/ratio.svg")), tr("Limit share ratio..."), nullptr); - connect(&actionSetMaxRatio, &QAction::triggered, this, &TransferListWidget::setMaxRatioSelectedTorrents); - QAction actionSetUploadLimit(GuiIconProvider::instance()->getIcon("kt-set-max-upload-speed"), tr("Limit upload rate..."), nullptr); - connect(&actionSetUploadLimit, &QAction::triggered, this, &TransferListWidget::setUpLimitSelectedTorrents); - QAction actionSetDownloadLimit(GuiIconProvider::instance()->getIcon("kt-set-max-download-speed"), tr("Limit download rate..."), nullptr); - connect(&actionSetDownloadLimit, &QAction::triggered, this, &TransferListWidget::setDlLimitSelectedTorrents); - QAction actionOpenDestinationFolder(GuiIconProvider::instance()->getIcon("inode-directory"), tr("Open destination folder"), nullptr); - 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); - 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); - 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); - 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); - connect(&actionBottomPriority, &QAction::triggered, this, &TransferListWidget::bottomPrioSelectedTorrents); - QAction actionSetTorrentPath(GuiIconProvider::instance()->getIcon("inode-directory"), tr("Set location..."), nullptr); - connect(&actionSetTorrentPath, &QAction::triggered, this, &TransferListWidget::setSelectedTorrentsLocation); - QAction actionForceRecheck(GuiIconProvider::instance()->getIcon("document-edit-verify"), tr("Force recheck"), nullptr); - connect(&actionForceRecheck, &QAction::triggered, this, &TransferListWidget::recheckSelectedTorrents); - QAction actionForceReannounce(GuiIconProvider::instance()->getIcon("document-edit-verify"), tr("Force reannounce"), nullptr); - connect(&actionForceReannounce, &QAction::triggered, this, &TransferListWidget::reannounceSelectedTorrents); - QAction actionCopyMagnetLink(GuiIconProvider::instance()->getIcon("kt-magnet"), tr("Copy magnet link"), nullptr); - connect(&actionCopyMagnetLink, &QAction::triggered, this, &TransferListWidget::copySelectedMagnetURIs); - QAction actionCopyName(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy name"), nullptr); - connect(&actionCopyName, &QAction::triggered, this, &TransferListWidget::copySelectedNames); - QAction actionCopyHash(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy hash"), nullptr); - connect(&actionCopyHash, &QAction::triggered, this, &TransferListWidget::copySelectedHashes); - QAction actionSuperSeedingMode(tr("Super seeding mode"), nullptr); - actionSuperSeedingMode.setCheckable(true); - connect(&actionSuperSeedingMode, &QAction::triggered, this, &TransferListWidget::toggleSelectedTorrentsSuperSeeding); - QAction actionRename(GuiIconProvider::instance()->getIcon("edit-rename"), tr("Rename..."), nullptr); - connect(&actionRename, &QAction::triggered, this, &TransferListWidget::renameSelectedTorrent); - QAction actionSequentialDownload(tr("Download in sequential order"), nullptr); - actionSequentialDownload.setCheckable(true); - connect(&actionSequentialDownload, &QAction::triggered, this, &TransferListWidget::toggleSelectedTorrentsSequentialDownload); - QAction actionFirstLastPiecePrio(tr("Download first and last pieces first"), nullptr); - actionFirstLastPiecePrio.setCheckable(true); - connect(&actionFirstLastPiecePrio, &QAction::triggered, this, &TransferListWidget::toggleSelectedFirstLastPiecePrio); - QAction actionAutoTMM(tr("Automatic Torrent Management"), nullptr); - actionAutoTMM.setCheckable(true); - 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); + QAction *actionStart = new QAction(GuiIconProvider::instance()->getIcon("media-playback-start"), tr("Resume", "Resume/start the torrent"), this); + connect(actionStart, &QAction::triggered, this, &TransferListWidget::startSelectedTorrents); + QAction *actionPause = new QAction(GuiIconProvider::instance()->getIcon("media-playback-pause"), tr("Pause", "Pause the torrent"), this); + connect(actionPause, &QAction::triggered, this, &TransferListWidget::pauseSelectedTorrents); + 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); + QAction *actionDelete = new QAction(GuiIconProvider::instance()->getIcon("edit-delete"), tr("Delete", "Delete the torrent"), this); + connect(actionDelete, &QAction::triggered, this, &TransferListWidget::softDeleteSelectedTorrents); + QAction *actionPreviewFile = new QAction(GuiIconProvider::instance()->getIcon("view-preview"), tr("Preview file..."), this); + connect(actionPreviewFile, &QAction::triggered, this, &TransferListWidget::previewSelectedTorrents); + QAction *actionSetMaxRatio = new QAction(QIcon(QLatin1String(":/icons/skin/ratio.svg")), tr("Limit share ratio..."), this); + connect(actionSetMaxRatio, &QAction::triggered, this, &TransferListWidget::setMaxRatioSelectedTorrents); + QAction *actionSetUploadLimit = new QAction(GuiIconProvider::instance()->getIcon("kt-set-max-upload-speed"), tr("Limit upload rate..."), this); + connect(actionSetUploadLimit, &QAction::triggered, this, &TransferListWidget::setUpLimitSelectedTorrents); + QAction *actionSetDownloadLimit = new QAction(GuiIconProvider::instance()->getIcon("kt-set-max-download-speed"), tr("Limit download rate..."), this); + connect(actionSetDownloadLimit, &QAction::triggered, this, &TransferListWidget::setDlLimitSelectedTorrents); + QAction *actionOpenDestinationFolder = new QAction(GuiIconProvider::instance()->getIcon("inode-directory"), tr("Open destination folder"), this); + connect(actionOpenDestinationFolder, &QAction::triggered, this, &TransferListWidget::openSelectedTorrentsFolder); + 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); + 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); + 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); + 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); + QAction *actionSetTorrentPath = new QAction(GuiIconProvider::instance()->getIcon("inode-directory"), tr("Set location..."), this); + connect(actionSetTorrentPath, &QAction::triggered, this, &TransferListWidget::setSelectedTorrentsLocation); + QAction *actionForceRecheck = new QAction(GuiIconProvider::instance()->getIcon("document-edit-verify"), tr("Force recheck"), this); + connect(actionForceRecheck, &QAction::triggered, this, &TransferListWidget::recheckSelectedTorrents); + QAction *actionForceReannounce = new QAction(GuiIconProvider::instance()->getIcon("document-edit-verify"), tr("Force reannounce"), this); + connect(actionForceReannounce, &QAction::triggered, this, &TransferListWidget::reannounceSelectedTorrents); + QAction *actionCopyMagnetLink = new QAction(GuiIconProvider::instance()->getIcon("kt-magnet"), tr("Copy magnet link"), this); + connect(actionCopyMagnetLink, &QAction::triggered, this, &TransferListWidget::copySelectedMagnetURIs); + QAction *actionCopyName = new QAction(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy name"), this); + connect(actionCopyName, &QAction::triggered, this, &TransferListWidget::copySelectedNames); + QAction *actionCopyHash = new QAction(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy hash"), this); + connect(actionCopyHash, &QAction::triggered, this, &TransferListWidget::copySelectedHashes); + QAction *actionSuperSeedingMode = new QAction(tr("Super seeding mode"), this); + actionSuperSeedingMode->setCheckable(true); + connect(actionSuperSeedingMode, &QAction::triggered, this, &TransferListWidget::toggleSelectedTorrentsSuperSeeding); + QAction *actionRename = new QAction(GuiIconProvider::instance()->getIcon("edit-rename"), tr("Rename..."), this); + connect(actionRename, &QAction::triggered, this, &TransferListWidget::renameSelectedTorrent); + QAction *actionSequentialDownload = new QAction(tr("Download in sequential order"), this); + actionSequentialDownload->setCheckable(true); + connect(actionSequentialDownload, &QAction::triggered, this, &TransferListWidget::toggleSelectedTorrentsSequentialDownload); + QAction *actionFirstLastPiecePrio = new QAction(tr("Download first and last pieces first"), this); + actionFirstLastPiecePrio->setCheckable(true); + connect(actionFirstLastPiecePrio, &QAction::triggered, this, &TransferListWidget::toggleSelectedFirstLastPiecePrio); + QAction *actionAutoTMM = new QAction(tr("Automatic Torrent Management"), this); + actionAutoTMM->setCheckable(true); + 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); // End of actions // Enable/disable pause/start action given the DL state @@ -956,12 +956,10 @@ void TransferListWidget::displayListMenu(const QPoint&) QSet tagsInAny; QSet tagsInAll; - BitTorrent::TorrentHandle *torrent; - qDebug("Displaying menu"); for (const QModelIndex &index : selectedIndexes) { // Get the file name // 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 (firstCategory.isEmpty() && first) @@ -1023,46 +1021,70 @@ void TransferListWidget::displayListMenu(const QPoint&) break; } } - QMenu listMenu(this); + + QMenu *listMenu = new QMenu(this); + listMenu->setAttribute(Qt::WA_DeleteOnClose); + if (needsStart) - listMenu.addAction(&actionStart); + listMenu->addAction(actionStart); if (needsPause) - listMenu.addAction(&actionPause); + listMenu->addAction(actionPause); if (needsForce) - listMenu.addAction(&actionForceStart); - listMenu.addSeparator(); - listMenu.addAction(&actionDelete); - listMenu.addSeparator(); - listMenu.addAction(&actionSetTorrentPath); + listMenu->addAction(actionForceStart); + listMenu->addSeparator(); + listMenu->addAction(actionDelete); + listMenu->addSeparator(); + listMenu->addAction(actionSetTorrentPath); if (selectedIndexes.size() == 1) - listMenu.addAction(&actionRename); + listMenu->addAction(actionRename); + // Category Menu QStringList categories = BitTorrent::Session::instance()->categories().keys(); std::sort(categories.begin(), categories.end(), Utils::String::naturalLessThan); - QList categoryActions; - 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")); + + QMenu *categoryMenu = listMenu->addMenu(GuiIconProvider::instance()->getIcon("view-categories"), tr("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(); - for (QString category : asConst(categories)) { - category.replace('&', "&&"); // avoid '&' becomes accelerator key - QAction *cat = new QAction(GuiIconProvider::instance()->getIcon("inode-directory"), category, categoryMenu); + + for (const QString &category : asConst(categories)) { + 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)) { cat->setCheckable(true); cat->setChecked(true); } + categoryMenu->addAction(cat); - categoryActions << cat; + connect(cat, &QAction::triggered, this, [this, category]() { setSelectionCategory(category); }); } // Tag Menu QStringList tags(BitTorrent::Session::instance()->tags().toList()); std::sort(tags.begin(), tags.end(), Utils::String::naturalLessThan); - QList tagsActions; - 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")); + + QMenu *tagsMenu = listMenu->addMenu(GuiIconProvider::instance()->getIcon("view-categories"), tr("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(); + for (const QString &tag : asConst(tags)) { const Qt::CheckState initialState = tagsInAll.contains(tag) ? Qt::Checked : tagsInAny.contains(tag) ? Qt::PartiallyChecked @@ -1081,89 +1103,60 @@ void TransferListWidget::displayListMenu(const QPoint&) } if (allSameAutoTMM) { - actionAutoTMM.setChecked(firstAutoTMM); - listMenu.addAction(&actionAutoTMM); + actionAutoTMM->setChecked(firstAutoTMM); + listMenu->addAction(actionAutoTMM); } - listMenu.addSeparator(); + listMenu->addSeparator(); if (oneNotSeed) - listMenu.addAction(&actionSetDownloadLimit); - listMenu.addAction(&actionSetUploadLimit); - listMenu.addAction(&actionSetMaxRatio); + listMenu->addAction(actionSetDownloadLimit); + listMenu->addAction(actionSetUploadLimit); + listMenu->addAction(actionSetMaxRatio); if (!oneNotSeed && allSameSuperSeeding && oneHasMetadata) { - actionSuperSeedingMode.setChecked(superSeedingMode); - listMenu.addAction(&actionSuperSeedingMode); + actionSuperSeedingMode->setChecked(superSeedingMode); + listMenu->addAction(actionSuperSeedingMode); } - listMenu.addSeparator(); + listMenu->addSeparator(); bool addedPreviewAction = false; if (needsPreview) { - listMenu.addAction(&actionPreviewFile); + listMenu->addAction(actionPreviewFile); addedPreviewAction = true; } if (oneNotSeed) { if (allSameSequentialDownloadMode) { - actionSequentialDownload.setChecked(sequentialDownloadMode); - listMenu.addAction(&actionSequentialDownload); + actionSequentialDownload->setChecked(sequentialDownloadMode); + listMenu->addAction(actionSequentialDownload); addedPreviewAction = true; } if (allSamePrioFirstlast) { - actionFirstLastPiecePrio.setChecked(prioritizeFirstLast); - listMenu.addAction(&actionFirstLastPiecePrio); + actionFirstLastPiecePrio->setChecked(prioritizeFirstLast); + listMenu->addAction(actionFirstLastPiecePrio); addedPreviewAction = true; } } if (addedPreviewAction) - listMenu.addSeparator(); + listMenu->addSeparator(); if (oneHasMetadata) { - listMenu.addAction(&actionForceRecheck); - listMenu.addAction(&actionForceReannounce); - listMenu.addSeparator(); + listMenu->addAction(actionForceRecheck); + listMenu->addAction(actionForceReannounce); + listMenu->addSeparator(); } - listMenu.addAction(&actionOpenDestinationFolder); + listMenu->addAction(actionOpenDestinationFolder); if (BitTorrent::Session::instance()->isQueueingSystemEnabled() && oneNotSeed) { - listMenu.addSeparator(); - QMenu *prioMenu = listMenu.addMenu(tr("Priority")); - prioMenu->addAction(&actionTopPriority); - prioMenu->addAction(&actionIncreasePriority); - prioMenu->addAction(&actionDecreasePriority); - prioMenu->addAction(&actionBottomPriority); - } - listMenu.addSeparator(); - listMenu.addAction(&actionCopyName); - listMenu.addAction(&actionCopyHash); - listMenu.addAction(&actionCopyMagnetLink); - // Call menu - QAction *act = nullptr; - 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(); - } + listMenu->addSeparator(); + QMenu *prioMenu = listMenu->addMenu(tr("Priority")); + prioMenu->addAction(actionTopPriority); + prioMenu->addAction(actionIncreasePriority); + prioMenu->addAction(actionDecreasePriority); + prioMenu->addAction(actionBottomPriority); } + listMenu->addSeparator(); + listMenu->addAction(actionCopyName); + listMenu->addAction(actionCopyHash); + listMenu->addAction(actionCopyMagnetLink); + + listMenu->popup(QCursor::pos()); } void TransferListWidget::currentChanged(const QModelIndex ¤t, const QModelIndex&)