mirror of
https://github.com/qbittorrent/qBittorrent
synced 2025-08-14 02:27:09 -07:00
Allow drop action only on transfer list
Now drop action is only allowed on transfer list, previously it was on main window. Having drop action on the whole main window is not preferred because it could allow drop action on other unrelated widgets, such as execution log or RSS widget which is unexpected behavior. PR #21332.
This commit is contained in:
parent
8b2d8f3afd
commit
10eb921d70
6 changed files with 104 additions and 91 deletions
|
@ -47,6 +47,7 @@
|
|||
#include <QStringView>
|
||||
#include <QSysInfo>
|
||||
|
||||
#include "base/net/downloadmanager.h"
|
||||
#include "base/path.h"
|
||||
#include "base/unicodestrings.h"
|
||||
#include "base/utils/string.h"
|
||||
|
@ -212,6 +213,14 @@ bool Utils::Misc::isPreviewable(const Path &filePath)
|
|||
return multimediaExtensions.contains(filePath.extension().toUpper());
|
||||
}
|
||||
|
||||
bool Utils::Misc::isTorrentLink(const QString &str)
|
||||
{
|
||||
return str.startsWith(u"magnet:", Qt::CaseInsensitive)
|
||||
|| str.endsWith(TORRENT_FILE_EXTENSION, Qt::CaseInsensitive)
|
||||
|| (!str.startsWith(u"file:", Qt::CaseInsensitive)
|
||||
&& Net::DownloadManager::hasSupportedScheme(str));
|
||||
}
|
||||
|
||||
QString Utils::Misc::userFriendlyDuration(const qlonglong seconds, const qlonglong maxCap, const TimeResolution resolution)
|
||||
{
|
||||
if (seconds < 0)
|
||||
|
|
|
@ -78,6 +78,7 @@ namespace Utils::Misc
|
|||
qint64 sizeInBytes(qreal size, SizeUnit unit);
|
||||
|
||||
bool isPreviewable(const Path &filePath);
|
||||
bool isTorrentLink(const QString &str);
|
||||
|
||||
// Take a number of seconds and return a user-friendly
|
||||
// time duration like "1d 2h 10m".
|
||||
|
|
|
@ -43,7 +43,6 @@
|
|||
#include <QDesktopServices>
|
||||
#include <QFileDialog>
|
||||
#include <QFileSystemWatcher>
|
||||
#include <QKeyEvent>
|
||||
#include <QLabel>
|
||||
#include <QMenu>
|
||||
#include <QMessageBox>
|
||||
|
@ -113,14 +112,6 @@ namespace
|
|||
#define EXECUTIONLOG_SETTINGS_KEY(name) (SETTINGS_KEY(u"Log/"_s) name)
|
||||
|
||||
const std::chrono::seconds PREVENT_SUSPEND_INTERVAL {60};
|
||||
|
||||
bool isTorrentLink(const QString &str)
|
||||
{
|
||||
return str.startsWith(u"magnet:", Qt::CaseInsensitive)
|
||||
|| str.endsWith(TORRENT_FILE_EXTENSION, Qt::CaseInsensitive)
|
||||
|| (!str.startsWith(u"file:", Qt::CaseInsensitive)
|
||||
&& Net::DownloadManager::hasSupportedScheme(str));
|
||||
}
|
||||
}
|
||||
|
||||
MainWindow::MainWindow(IGUIApplication *app, const WindowState initialState, const QString &titleSuffix)
|
||||
|
@ -241,7 +232,7 @@ MainWindow::MainWindow(IGUIApplication *app, const WindowState initialState, con
|
|||
m_ui->toolBar->insertWidget(m_columnFilterAction, spacer);
|
||||
|
||||
// Transfer List tab
|
||||
m_transferListWidget = new TransferListWidget(hSplitter, this);
|
||||
m_transferListWidget = new TransferListWidget(app, this);
|
||||
m_propertiesWidget = new PropertiesWidget(hSplitter);
|
||||
connect(m_transferListWidget, &TransferListWidget::currentTorrentChanged, m_propertiesWidget, &PropertiesWidget::loadTorrentInfos);
|
||||
hSplitter->addWidget(m_transferListWidget);
|
||||
|
@ -347,8 +338,6 @@ MainWindow::MainWindow(IGUIApplication *app, const WindowState initialState, con
|
|||
connect(BitTorrent::Session::instance(), &BitTorrent::Session::statsUpdated, this, &MainWindow::loadSessionStats);
|
||||
connect(BitTorrent::Session::instance(), &BitTorrent::Session::torrentsUpdated, this, &MainWindow::reloadTorrentStats);
|
||||
|
||||
// Accept drag 'n drops
|
||||
setAcceptDrops(true);
|
||||
createKeyboardShortcuts();
|
||||
|
||||
#ifdef Q_OS_MACOS
|
||||
|
@ -1124,16 +1113,13 @@ void MainWindow::keyPressEvent(QKeyEvent *event)
|
|||
if (event->matches(QKeySequence::Paste))
|
||||
{
|
||||
const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData();
|
||||
|
||||
if (mimeData->hasText())
|
||||
{
|
||||
const QStringList lines = mimeData->text().split(u'\n', Qt::SkipEmptyParts);
|
||||
|
||||
for (QString line : lines)
|
||||
{
|
||||
line = line.trimmed();
|
||||
|
||||
if (!isTorrentLink(line))
|
||||
if (!Utils::Misc::isTorrentLink(line))
|
||||
continue;
|
||||
|
||||
app()->addTorrentManager()->addTorrent(line);
|
||||
|
@ -1284,66 +1270,6 @@ bool MainWindow::event(QEvent *e)
|
|||
return QMainWindow::event(e);
|
||||
}
|
||||
|
||||
// action executed when a file is dropped
|
||||
void MainWindow::dropEvent(QDropEvent *event)
|
||||
{
|
||||
event->acceptProposedAction();
|
||||
|
||||
// remove scheme
|
||||
QStringList files;
|
||||
if (event->mimeData()->hasUrls())
|
||||
{
|
||||
for (const QUrl &url : asConst(event->mimeData()->urls()))
|
||||
{
|
||||
if (url.isEmpty())
|
||||
continue;
|
||||
|
||||
files << ((url.scheme().compare(u"file", Qt::CaseInsensitive) == 0)
|
||||
? url.toLocalFile()
|
||||
: url.toString());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
files = event->mimeData()->text().split(u'\n');
|
||||
}
|
||||
|
||||
// differentiate ".torrent" files/links & magnet links from others
|
||||
QStringList torrentFiles, otherFiles;
|
||||
for (const QString &file : asConst(files))
|
||||
{
|
||||
if (isTorrentLink(file))
|
||||
torrentFiles << file;
|
||||
else
|
||||
otherFiles << file;
|
||||
}
|
||||
|
||||
// Download torrents
|
||||
for (const QString &file : asConst(torrentFiles))
|
||||
app()->addTorrentManager()->addTorrent(file);
|
||||
if (!torrentFiles.isEmpty()) return;
|
||||
|
||||
// Create torrent
|
||||
for (const QString &file : asConst(otherFiles))
|
||||
{
|
||||
createTorrentTriggered(Path(file));
|
||||
|
||||
// currently only handle the first entry
|
||||
// this is a stub that can be expanded later to create many torrents at once
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Decode if we accept drag 'n drop or not
|
||||
void MainWindow::dragEnterEvent(QDragEnterEvent *event)
|
||||
{
|
||||
for (const QString &mime : asConst(event->mimeData()->formats()))
|
||||
qDebug("mimeData: %s", mime.toLocal8Bit().data());
|
||||
|
||||
if (event->mimeData()->hasFormat(u"text/plain"_s) || event->mimeData()->hasFormat(u"text/uri-list"_s))
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
|
||||
// Display a dialog to allow user to add
|
||||
// torrents to download list
|
||||
void MainWindow::on_actionOpen_triggered()
|
||||
|
|
|
@ -191,8 +191,6 @@ private:
|
|||
void installPython();
|
||||
#endif
|
||||
|
||||
void dropEvent(QDropEvent *event) override;
|
||||
void dragEnterEvent(QDragEnterEvent *event) override;
|
||||
void closeEvent(QCloseEvent *) override;
|
||||
void showEvent(QShowEvent *) override;
|
||||
void keyPressEvent(QKeyEvent *event) override;
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <QList>
|
||||
#include <QMenu>
|
||||
#include <QMessageBox>
|
||||
#include <QMimeData>
|
||||
#include <QRegularExpression>
|
||||
#include <QSet>
|
||||
#include <QShortcut>
|
||||
|
@ -57,11 +58,13 @@
|
|||
#include "base/utils/string.h"
|
||||
#include "autoexpandabledialog.h"
|
||||
#include "deletionconfirmationdialog.h"
|
||||
#include "interfaces/iguiapplication.h"
|
||||
#include "mainwindow.h"
|
||||
#include "optionsdialog.h"
|
||||
#include "previewselectdialog.h"
|
||||
#include "speedlimitdialog.h"
|
||||
#include "torrentcategorydialog.h"
|
||||
#include "torrentcreatordialog.h"
|
||||
#include "torrentoptionsdialog.h"
|
||||
#include "trackerentriesdialog.h"
|
||||
#include "transferlistdelegate.h"
|
||||
|
@ -123,11 +126,10 @@ namespace
|
|||
}
|
||||
}
|
||||
|
||||
TransferListWidget::TransferListWidget(QWidget *parent, MainWindow *mainWindow)
|
||||
: QTreeView {parent}
|
||||
TransferListWidget::TransferListWidget(IGUIApplication *app, QWidget *parent)
|
||||
: GUIApplicationComponent(app, parent)
|
||||
, m_listModel {new TransferListModel {this}}
|
||||
, m_sortFilterModel {new TransferListSortModel {this}}
|
||||
, m_mainWindow {mainWindow}
|
||||
{
|
||||
// Load settings
|
||||
const bool columnLoaded = loadSettings();
|
||||
|
@ -151,7 +153,9 @@ TransferListWidget::TransferListWidget(QWidget *parent, MainWindow *mainWindow)
|
|||
setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
setItemsExpandable(false);
|
||||
setAutoScroll(true);
|
||||
setDragDropMode(QAbstractItemView::DragOnly);
|
||||
setAcceptDrops(true);
|
||||
setDragDropMode(QAbstractItemView::DropOnly);
|
||||
setDropIndicatorShown(true);
|
||||
#if defined(Q_OS_MACOS)
|
||||
setAttribute(Qt::WA_MacShowFocusRect, false);
|
||||
#endif
|
||||
|
@ -431,7 +435,7 @@ void TransferListWidget::permDeleteSelectedTorrents()
|
|||
|
||||
void TransferListWidget::deleteSelectedTorrents(const bool deleteLocalFiles)
|
||||
{
|
||||
if (m_mainWindow->currentTabWidget() != this) return;
|
||||
if (app()->mainWindow()->currentTabWidget() != this) return;
|
||||
|
||||
const QList<BitTorrent::Torrent *> torrents = getSelectedTorrents();
|
||||
if (torrents.empty()) return;
|
||||
|
@ -480,26 +484,26 @@ void TransferListWidget::deleteVisibleTorrents()
|
|||
void TransferListWidget::increaseQueuePosSelectedTorrents()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
if (m_mainWindow->currentTabWidget() == this)
|
||||
if (app()->mainWindow()->currentTabWidget() == this)
|
||||
BitTorrent::Session::instance()->increaseTorrentsQueuePos(extractIDs(getSelectedTorrents()));
|
||||
}
|
||||
|
||||
void TransferListWidget::decreaseQueuePosSelectedTorrents()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
if (m_mainWindow->currentTabWidget() == this)
|
||||
if (app()->mainWindow()->currentTabWidget() == this)
|
||||
BitTorrent::Session::instance()->decreaseTorrentsQueuePos(extractIDs(getSelectedTorrents()));
|
||||
}
|
||||
|
||||
void TransferListWidget::topQueuePosSelectedTorrents()
|
||||
{
|
||||
if (m_mainWindow->currentTabWidget() == this)
|
||||
if (app()->mainWindow()->currentTabWidget() == this)
|
||||
BitTorrent::Session::instance()->topTorrentsQueuePos(extractIDs(getSelectedTorrents()));
|
||||
}
|
||||
|
||||
void TransferListWidget::bottomQueuePosSelectedTorrents()
|
||||
{
|
||||
if (m_mainWindow->currentTabWidget() == this)
|
||||
if (app()->mainWindow()->currentTabWidget() == this)
|
||||
BitTorrent::Session::instance()->bottomTorrentsQueuePos(extractIDs(getSelectedTorrents()));
|
||||
}
|
||||
|
||||
|
@ -1354,6 +1358,79 @@ bool TransferListWidget::loadSettings()
|
|||
return header()->restoreState(Preferences::instance()->getTransHeaderState());
|
||||
}
|
||||
|
||||
void TransferListWidget::dragEnterEvent(QDragEnterEvent *event)
|
||||
{
|
||||
if (const QMimeData *data = event->mimeData(); data->hasText() || data->hasUrls())
|
||||
{
|
||||
event->setDropAction(Qt::CopyAction);
|
||||
event->accept();
|
||||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::dragMoveEvent(QDragMoveEvent *event)
|
||||
{
|
||||
event->acceptProposedAction(); // required, otherwise we won't get `dropEvent`
|
||||
}
|
||||
|
||||
void TransferListWidget::dropEvent(QDropEvent *event)
|
||||
{
|
||||
event->acceptProposedAction();
|
||||
// remove scheme
|
||||
QStringList files;
|
||||
if (const QMimeData *data = event->mimeData(); data->hasUrls())
|
||||
{
|
||||
const QList<QUrl> urls = data->urls();
|
||||
files.reserve(urls.size());
|
||||
|
||||
for (const QUrl &url : urls)
|
||||
{
|
||||
if (url.isEmpty())
|
||||
continue;
|
||||
|
||||
files.append(url.isLocalFile()
|
||||
? url.toLocalFile()
|
||||
: url.toString());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
files = data->text().split(u'\n', Qt::SkipEmptyParts);
|
||||
}
|
||||
|
||||
// differentiate ".torrent" files/links & magnet links from others
|
||||
QStringList torrentFiles, otherFiles;
|
||||
torrentFiles.reserve(files.size());
|
||||
otherFiles.reserve(files.size());
|
||||
for (const QString &file : asConst(files))
|
||||
{
|
||||
if (Utils::Misc::isTorrentLink(file))
|
||||
torrentFiles << file;
|
||||
else
|
||||
otherFiles << file;
|
||||
}
|
||||
|
||||
// Download torrents
|
||||
if (!torrentFiles.isEmpty())
|
||||
{
|
||||
for (const QString &file : asConst(torrentFiles))
|
||||
app()->addTorrentManager()->addTorrent(file);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Create torrent
|
||||
for (const QString &file : asConst(otherFiles))
|
||||
{
|
||||
auto torrentCreator = new TorrentCreatorDialog(this, Path(file));
|
||||
torrentCreator->setAttribute(Qt::WA_DeleteOnClose);
|
||||
torrentCreator->show();
|
||||
|
||||
// currently only handle the first entry
|
||||
// this is a stub that can be expanded later to create many torrents at once
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void TransferListWidget::wheelEvent(QWheelEvent *event)
|
||||
{
|
||||
if (event->modifiers() & Qt::ShiftModifier)
|
||||
|
|
|
@ -35,9 +35,9 @@
|
|||
#include <QTreeView>
|
||||
|
||||
#include "base/bittorrent/infohash.h"
|
||||
#include "guiapplicationcomponent.h"
|
||||
#include "transferlistmodel.h"
|
||||
|
||||
class MainWindow;
|
||||
class Path;
|
||||
class TransferListSortModel;
|
||||
|
||||
|
@ -52,13 +52,13 @@ enum class CopyInfohashPolicy
|
|||
Version2
|
||||
};
|
||||
|
||||
class TransferListWidget final : public QTreeView
|
||||
class TransferListWidget final : public GUIApplicationComponent<QTreeView>
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY_MOVE(TransferListWidget)
|
||||
|
||||
public:
|
||||
TransferListWidget(QWidget *parent, MainWindow *mainWindow);
|
||||
TransferListWidget(IGUIApplication *app, QWidget *parent);
|
||||
~TransferListWidget() override;
|
||||
TransferListModel *getSourceModel() const;
|
||||
|
||||
|
@ -119,6 +119,9 @@ private slots:
|
|||
void saveSettings();
|
||||
|
||||
private:
|
||||
void dragEnterEvent(QDragEnterEvent *event) override;
|
||||
void dragMoveEvent(QDragMoveEvent *event) override;
|
||||
void dropEvent(QDropEvent *event) override;
|
||||
void wheelEvent(QWheelEvent *event) override;
|
||||
QModelIndex mapToSource(const QModelIndex &index) const;
|
||||
QModelIndexList mapToSource(const QModelIndexList &indexes) const;
|
||||
|
@ -136,5 +139,4 @@ private:
|
|||
|
||||
TransferListModel *m_listModel = nullptr;
|
||||
TransferListSortModel *m_sortFilterModel = nullptr;
|
||||
MainWindow *m_mainWindow = nullptr;
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue