mirror of
https://github.com/qbittorrent/qBittorrent
synced 2025-08-21 05:43:32 -07:00
Select the file of single file torrents when opening destination folder
Also, add the support for Nautilus (Gnome 3), Caja and Nemo. Backport of #2544.
This commit is contained in:
parent
8679b70b4c
commit
4696fbff4a
5 changed files with 91 additions and 82 deletions
|
@ -31,6 +31,7 @@
|
||||||
#include "core/unicodestrings.h"
|
#include "core/unicodestrings.h"
|
||||||
#include "core/logger.h"
|
#include "core/logger.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
|
#include "fs_utils.h"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
|
@ -52,6 +53,11 @@
|
||||||
#include <QDesktopWidget>
|
#include <QDesktopWidget>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef DISABLE_GUI
|
||||||
|
#include <QDesktopServices>
|
||||||
|
#include <QProcess>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <PowrProf.h>
|
#include <PowrProf.h>
|
||||||
|
@ -692,6 +698,64 @@ void misc::loadBencodedFile(const QString &filename, std::vector<char> &buffer,
|
||||||
lazy_bdecode(&buffer[0], &buffer[0] + buffer.size(), entry, ec);
|
lazy_bdecode(&buffer[0], &buffer[0] + buffer.size(), entry, ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef DISABLE_GUI
|
||||||
|
// Open the given path with an appropriate application
|
||||||
|
void misc::openPath(const QString& absolutePath)
|
||||||
|
{
|
||||||
|
const QString path = fsutils::fromNativePath(absolutePath);
|
||||||
|
// Hack to access samba shares with QDesktopServices::openUrl
|
||||||
|
if (path.startsWith("//"))
|
||||||
|
QDesktopServices::openUrl(fsutils::toNativePath("file:" + path));
|
||||||
|
else
|
||||||
|
QDesktopServices::openUrl(QUrl::fromLocalFile(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the parent directory of the given path with a file manager and select
|
||||||
|
// (if possible) the item at the given path
|
||||||
|
void misc::openFolderSelect(const QString& absolutePath)
|
||||||
|
{
|
||||||
|
const QString path = fsutils::fromNativePath(absolutePath);
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
if (QFileInfo(path).exists()) {
|
||||||
|
// Syntax is: explorer /select, "C:\Folder1\Folder2\file_to_select"
|
||||||
|
// Dir separators MUST be win-style slashes
|
||||||
|
QProcess::startDetached("explorer.exe", QStringList() << "/select," << fsutils::toNativePath(absolutePath));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// If the item to select doesn't exist, try to open its parent
|
||||||
|
openPath(path.left(path.lastIndexOf("/")));
|
||||||
|
}
|
||||||
|
#elif defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
|
||||||
|
if (QFileInfo(path).exists()) {
|
||||||
|
QProcess proc;
|
||||||
|
QString output;
|
||||||
|
proc.start("xdg-mime", QStringList() << "query" << "default" << "inode/directory");
|
||||||
|
proc.waitForFinished();
|
||||||
|
output = proc.readLine().simplified();
|
||||||
|
if (output == "dolphin.desktop")
|
||||||
|
proc.startDetached("dolphin", QStringList() << "--select" << fsutils::toNativePath(path));
|
||||||
|
else if (output == "nautilus.desktop" || output == "org.gnome.Nautilus.desktop"
|
||||||
|
|| output == "nautilus-folder-handler.desktop")
|
||||||
|
proc.startDetached("nautilus", QStringList() << "--no-desktop" << fsutils::toNativePath(path));
|
||||||
|
else if (output == "caja-folder-handler.desktop")
|
||||||
|
proc.startDetached("caja", QStringList() << "--no-desktop" << fsutils::toNativePath(path));
|
||||||
|
else if (output == "nemo.desktop")
|
||||||
|
proc.startDetached("nemo", QStringList() << "--no-desktop" << fsutils::toNativePath(path));
|
||||||
|
else if (output == "kfmclient_dir.desktop")
|
||||||
|
proc.startDetached("konqueror", QStringList() << "--select" << fsutils::toNativePath(path));
|
||||||
|
else
|
||||||
|
openPath(path.left(path.lastIndexOf("/")));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// If the item to select doesn't exist, try to open its parent
|
||||||
|
openPath(path.left(path.lastIndexOf("/")));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
openPath(path.left(path.lastIndexOf("/")));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif // DISABLE_GUI
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
// Trick to get a portable sleep() function
|
// Trick to get a portable sleep() function
|
||||||
class SleeperThread: public QThread {
|
class SleeperThread: public QThread {
|
||||||
|
|
|
@ -114,6 +114,11 @@ namespace misc
|
||||||
bool slowEquals(const QByteArray &a, const QByteArray &b);
|
bool slowEquals(const QByteArray &a, const QByteArray &b);
|
||||||
void loadBencodedFile(const QString &filename, std::vector<char> &buffer, libtorrent::lazy_entry &entry, libtorrent::error_code &ec);
|
void loadBencodedFile(const QString &filename, std::vector<char> &buffer, libtorrent::lazy_entry &entry, libtorrent::error_code &ec);
|
||||||
|
|
||||||
|
#ifndef DISABLE_GUI
|
||||||
|
void openPath(const QString& absolutePath);
|
||||||
|
void openFolderSelect(const QString& absolutePath);
|
||||||
|
#endif
|
||||||
|
|
||||||
void msleep(unsigned long msecs);
|
void msleep(unsigned long msecs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,6 @@
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QDesktopServices>
|
|
||||||
#include <libtorrent/version.hpp>
|
#include <libtorrent/version.hpp>
|
||||||
#include "propertieswidget.h"
|
#include "propertieswidget.h"
|
||||||
#include "transferlistwidget.h"
|
#include "transferlistwidget.h"
|
||||||
|
@ -501,15 +500,7 @@ void PropertiesWidget::openFile(const QModelIndex &index) {
|
||||||
qDebug("Trying to open file at %s", qPrintable(file_path));
|
qDebug("Trying to open file at %s", qPrintable(file_path));
|
||||||
// Flush data
|
// Flush data
|
||||||
h.flush_cache();
|
h.flush_cache();
|
||||||
if (QFile::exists(file_path)) {
|
misc::openPath(file_path);
|
||||||
if (file_path.startsWith("//"))
|
|
||||||
QDesktopServices::openUrl(fsutils::toNativePath("file:" + file_path));
|
|
||||||
else
|
|
||||||
QDesktopServices::openUrl(QUrl::fromLocalFile(file_path));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
QMessageBox::warning(this, tr("I/O Error"), tr("This file does not exist yet."));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertiesWidget::openFolder(const QModelIndex &index, bool containing_folder) {
|
void PropertiesWidget::openFolder(const QModelIndex &index, bool containing_folder) {
|
||||||
|
@ -526,10 +517,6 @@ void PropertiesWidget::openFolder(const QModelIndex &index, bool containing_fold
|
||||||
}
|
}
|
||||||
if (path_items.isEmpty())
|
if (path_items.isEmpty())
|
||||||
return;
|
return;
|
||||||
#if !(defined(Q_OS_WIN) || (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)))
|
|
||||||
if (containing_folder)
|
|
||||||
path_items.removeLast();
|
|
||||||
#endif
|
|
||||||
const QDir saveDir(h.save_path());
|
const QDir saveDir(h.save_path());
|
||||||
const QString relative_path = path_items.join("/");
|
const QString relative_path = path_items.join("/");
|
||||||
absolute_path = fsutils::expandPath(saveDir.absoluteFilePath(relative_path));
|
absolute_path = fsutils::expandPath(saveDir.absoluteFilePath(relative_path));
|
||||||
|
@ -539,54 +526,14 @@ void PropertiesWidget::openFolder(const QModelIndex &index, bool containing_fold
|
||||||
const QDir saveDir(h.save_path());
|
const QDir saveDir(h.save_path());
|
||||||
const QString relative_path = h.filepath_at(i);
|
const QString relative_path = h.filepath_at(i);
|
||||||
absolute_path = fsutils::expandPath(saveDir.absoluteFilePath(relative_path));
|
absolute_path = fsutils::expandPath(saveDir.absoluteFilePath(relative_path));
|
||||||
|
|
||||||
#if !(defined(Q_OS_WIN) || (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)))
|
|
||||||
if (containing_folder)
|
|
||||||
absolute_path = fsutils::folderName(absolute_path);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flush data
|
// Flush data
|
||||||
h.flush_cache();
|
h.flush_cache();
|
||||||
if (!QFile::exists(absolute_path))
|
if (containing_folder)
|
||||||
return;
|
misc::openFolderSelect(absolute_path);
|
||||||
qDebug("Trying to open folder at %s", qPrintable(absolute_path));
|
else
|
||||||
|
misc::openPath(absolute_path);
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
if (containing_folder) {
|
|
||||||
// Syntax is: explorer /select, "C:\Folder1\Folder2\file_to_select"
|
|
||||||
// Dir separators MUST be win-style slashes
|
|
||||||
QProcess::startDetached("explorer.exe", QStringList() << "/select," << fsutils::toNativePath(absolute_path));
|
|
||||||
} else {
|
|
||||||
#elif defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
|
|
||||||
if (containing_folder) {
|
|
||||||
QProcess proc;
|
|
||||||
QString output;
|
|
||||||
proc.start("xdg-mime", QStringList() << "query" << "default" << "inode/directory");
|
|
||||||
proc.waitForFinished();
|
|
||||||
output = proc.readLine().simplified();
|
|
||||||
if (output == "dolphin.desktop")
|
|
||||||
proc.startDetached("dolphin", QStringList() << "--select" << fsutils::toNativePath(absolute_path));
|
|
||||||
else if (output == "nautilus-folder-handler.desktop")
|
|
||||||
proc.startDetached("nautilus", QStringList() << "--no-desktop" << fsutils::toNativePath(absolute_path));
|
|
||||||
else if (output == "kfmclient_dir.desktop")
|
|
||||||
proc.startDetached("konqueror", QStringList() << "--select" << fsutils::toNativePath(absolute_path));
|
|
||||||
else
|
|
||||||
QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(absolute_path).absolutePath()));
|
|
||||||
} else {
|
|
||||||
#endif
|
|
||||||
if (QFile::exists(absolute_path)) {
|
|
||||||
// Hack to access samba shares with QDesktopServices::openUrl
|
|
||||||
if (absolute_path.startsWith("//"))
|
|
||||||
QDesktopServices::openUrl(fsutils::toNativePath("file:" + absolute_path));
|
|
||||||
else
|
|
||||||
QDesktopServices::openUrl(QUrl::fromLocalFile(absolute_path));
|
|
||||||
} else {
|
|
||||||
QMessageBox::warning(this, tr("I/O Error"), tr("This folder does not exist yet."));
|
|
||||||
}
|
|
||||||
#if defined(Q_OS_WIN) || (defined(Q_OS_UNIX) && !defined(Q_OS_MAC))
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertiesWidget::displayFilesListMenu(const QPoint&) {
|
void PropertiesWidget::displayFilesListMenu(const QPoint&) {
|
||||||
|
|
|
@ -32,7 +32,6 @@
|
||||||
#include <QShortcut>
|
#include <QShortcut>
|
||||||
#include <QStandardItemModel>
|
#include <QStandardItemModel>
|
||||||
#include <QSortFilterProxyModel>
|
#include <QSortFilterProxyModel>
|
||||||
#include <QDesktopServices>
|
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QClipboard>
|
#include <QClipboard>
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
|
@ -179,7 +178,7 @@ TorrentModel* TransferListWidget::getSourceModel() const
|
||||||
|
|
||||||
void TransferListWidget::previewFile(QString filePath)
|
void TransferListWidget::previewFile(QString filePath)
|
||||||
{
|
{
|
||||||
openUrl(filePath);
|
misc::openPath(filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransferListWidget::setRefreshInterval(int t)
|
void TransferListWidget::setRefreshInterval(int t)
|
||||||
|
@ -233,8 +232,11 @@ void TransferListWidget::torrentDoubleClicked(const QModelIndex& index)
|
||||||
h.pause();
|
h.pause();
|
||||||
break;
|
break;
|
||||||
case OPEN_DEST:
|
case OPEN_DEST:
|
||||||
const QString path = h.root_path();
|
if (h.num_files() == 1)
|
||||||
openUrl(path);
|
misc::openFolderSelect(QDir(h.root_path()).absoluteFilePath(h.filepath_at(0)));
|
||||||
|
else
|
||||||
|
misc::openPath(h.root_path());
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -458,14 +460,18 @@ void TransferListWidget::openSelectedTorrentsFolder() const
|
||||||
const QStringList hashes = getSelectedTorrentsHashes();
|
const QStringList hashes = getSelectedTorrentsHashes();
|
||||||
foreach (const QString &hash, hashes) {
|
foreach (const QString &hash, hashes) {
|
||||||
const QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
const QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||||
if (h.is_valid()) {
|
QString path;
|
||||||
QString rootFolder = h.root_path();
|
if (h.num_files() == 1) {
|
||||||
qDebug("Opening path at %s", qPrintable(rootFolder));
|
path = QDir(h.root_path()).absoluteFilePath(h.filepath_at(0));
|
||||||
if (!pathsList.contains(rootFolder)) {
|
if (!pathsList.contains(path))
|
||||||
pathsList.insert(rootFolder);
|
misc::openFolderSelect(path);
|
||||||
openUrl(rootFolder);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
path = h.root_path();
|
||||||
|
if (!pathsList.contains(path))
|
||||||
|
misc::openPath(path);
|
||||||
|
}
|
||||||
|
pathsList.insert(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -670,16 +676,6 @@ void TransferListWidget::askNewLabelForSelection()
|
||||||
} while(invalid);
|
} while(invalid);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TransferListWidget::openUrl(const QString &_path) const
|
|
||||||
{
|
|
||||||
const QString path = fsutils::fromNativePath(_path);
|
|
||||||
// Hack to access samba shares with QDesktopServices::openUrl
|
|
||||||
if (path.startsWith("//"))
|
|
||||||
return QDesktopServices::openUrl(fsutils::toNativePath("file:" + path));
|
|
||||||
else
|
|
||||||
return QDesktopServices::openUrl(QUrl::fromLocalFile(path));
|
|
||||||
}
|
|
||||||
|
|
||||||
void TransferListWidget::renameSelectedTorrent()
|
void TransferListWidget::renameSelectedTorrent()
|
||||||
{
|
{
|
||||||
const QModelIndexList selectedIndexes = selectionModel()->selectedRows();
|
const QModelIndexList selectedIndexes = selectionModel()->selectedRows();
|
||||||
|
|
|
@ -109,9 +109,6 @@ protected slots:
|
||||||
void askNewLabelForSelection();
|
void askNewLabelForSelection();
|
||||||
void saveSettings();
|
void saveSettings();
|
||||||
|
|
||||||
private:
|
|
||||||
bool openUrl(const QString& _path) const;
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void currentTorrentChanged(const QTorrentHandle &h);
|
void currentTorrentChanged(const QTorrentHandle &h);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue