mirror of
https://github.com/qbittorrent/qBittorrent
synced 2025-07-15 09:43:07 -07:00
- Files / Folders can also be renamed directly from torrent addition dialog
This commit is contained in:
parent
533e402bca
commit
add2475700
5 changed files with 248 additions and 97 deletions
|
@ -4,7 +4,7 @@
|
||||||
- FEATURE: Disk cache size can be set from preferences
|
- FEATURE: Disk cache size can be set from preferences
|
||||||
- FEATURE: Peer Exchange (PeX) can be disabled from preferences
|
- FEATURE: Peer Exchange (PeX) can be disabled from preferences
|
||||||
- FEATURE: Append !.qB extension to incomplete files option (libtorrent >= v0.15 only)
|
- FEATURE: Append !.qB extension to incomplete files option (libtorrent >= v0.15 only)
|
||||||
- FEATURE: Torrent files/folders can be renamed
|
- FEATURE: Torrent files/folders can be renamed (torrent addition dialog or files properties)
|
||||||
- FEATURE: uTorrent compatible tracker list support (use torrentz.com url as a default)
|
- FEATURE: uTorrent compatible tracker list support (use torrentz.com url as a default)
|
||||||
- FEATURE: Better proxy support and preferences remodeling
|
- FEATURE: Better proxy support and preferences remodeling
|
||||||
- FEATURE: qBittorrent can identify itself as uTorrent or Vuze (Any version)
|
- FEATURE: qBittorrent can identify itself as uTorrent or Vuze (Any version)
|
||||||
|
|
|
@ -960,6 +960,14 @@ QTorrentHandle Bittorrent::addTorrent(QString path, bool fromScanDir, QString fr
|
||||||
qDebug("addTorrent: Setting download as sequential (from tmp data)");
|
qDebug("addTorrent: Setting download as sequential (from tmp data)");
|
||||||
h.prioritize_files(TorrentTempData::getFilesPriority(hash));
|
h.prioritize_files(TorrentTempData::getFilesPriority(hash));
|
||||||
h.set_sequential_download(TorrentTempData::isSequential(hash));
|
h.set_sequential_download(TorrentTempData::isSequential(hash));
|
||||||
|
// Import Files names from torrent addition dialog
|
||||||
|
QStringList files_path = TorrentTempData::getFilesPath(hash);
|
||||||
|
if(files_path.size() == h.num_files()) {
|
||||||
|
for(int i=0; i<h.num_files(); ++i) {
|
||||||
|
QString path = files_path.at(i);
|
||||||
|
h.rename_file(i, path);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
QString label = TorrentTempData::getLabel(hash);
|
QString label = TorrentTempData::getLabel(hash);
|
||||||
// Save persistent data for new torrent
|
// Save persistent data for new torrent
|
||||||
|
|
|
@ -467,7 +467,7 @@ void PropertiesWidget::displayFilesListMenu(const QPoint&){
|
||||||
QAction *actRename = 0;
|
QAction *actRename = 0;
|
||||||
if(selectedRows.size() == 1) {
|
if(selectedRows.size() == 1) {
|
||||||
actRename = myFilesLlistMenu.addAction(QIcon(QString::fromUtf8(":/Icons/oxygen/edit_clear.png")), tr("Rename..."));
|
actRename = myFilesLlistMenu.addAction(QIcon(QString::fromUtf8(":/Icons/oxygen/edit_clear.png")), tr("Rename..."));
|
||||||
myFilesLlistMenu.addSeparator();
|
//myFilesLlistMenu.addSeparator();
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
#include <QHeaderView>
|
#include <QHeaderView>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QDesktopWidget>
|
#include <QDesktopWidget>
|
||||||
|
#include <QInputDialog>
|
||||||
|
|
||||||
#include <libtorrent/session.hpp>
|
#include <libtorrent/session.hpp>
|
||||||
#include <libtorrent/bencode.hpp>
|
#include <libtorrent/bencode.hpp>
|
||||||
|
@ -67,6 +68,7 @@ private:
|
||||||
PropListDelegate *PropDelegate;
|
PropListDelegate *PropDelegate;
|
||||||
unsigned int nbFiles;
|
unsigned int nbFiles;
|
||||||
boost::intrusive_ptr<torrent_info> t;
|
boost::intrusive_ptr<torrent_info> t;
|
||||||
|
QStringList files_path;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
torrentAdditionDialog(QWidget *parent, Bittorrent* _BTSession) : QDialog(parent) {
|
torrentAdditionDialog(QWidget *parent, Bittorrent* _BTSession) : QDialog(parent) {
|
||||||
|
@ -80,6 +82,7 @@ public:
|
||||||
PropDelegate = new PropListDelegate();
|
PropDelegate = new PropListDelegate();
|
||||||
torrentContentList->setItemDelegate(PropDelegate);
|
torrentContentList->setItemDelegate(PropDelegate);
|
||||||
connect(torrentContentList, SIGNAL(clicked(const QModelIndex&)), torrentContentList, SLOT(edit(const QModelIndex&)));
|
connect(torrentContentList, SIGNAL(clicked(const QModelIndex&)), torrentContentList, SLOT(edit(const QModelIndex&)));
|
||||||
|
connect(torrentContentList, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayContentListMenu(const QPoint&)));
|
||||||
connect(collapseAllButton, SIGNAL(clicked()), torrentContentList, SLOT(collapseAll()));
|
connect(collapseAllButton, SIGNAL(clicked()), torrentContentList, SLOT(collapseAll()));
|
||||||
connect(expandAllButton, SIGNAL(clicked()), torrentContentList, SLOT(expandAll()));
|
connect(expandAllButton, SIGNAL(clicked()), torrentContentList, SLOT(expandAll()));
|
||||||
// Remember columns width
|
// Remember columns width
|
||||||
|
@ -194,12 +197,118 @@ public:
|
||||||
foreach(const QString& label, customLabels) {
|
foreach(const QString& label, customLabels) {
|
||||||
comboLabel->addItem(label);
|
comboLabel->addItem(label);
|
||||||
}
|
}
|
||||||
|
// Loads files path in the torrent
|
||||||
|
for(uint i=0; i<nbFiles; ++i) {
|
||||||
|
files_path << misc::toQString(t->file_at(i).path.string());
|
||||||
|
}
|
||||||
// Show the dialog
|
// Show the dialog
|
||||||
show();
|
show();
|
||||||
}
|
}
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
|
void displayContentListMenu(const QPoint&) {
|
||||||
|
QMenu myFilesLlistMenu;
|
||||||
|
QModelIndexList selectedRows = torrentContentList->selectionModel()->selectedRows(0);
|
||||||
|
QAction *actRename = 0;
|
||||||
|
if(selectedRows.size() == 1) {
|
||||||
|
actRename = myFilesLlistMenu.addAction(QIcon(QString::fromUtf8(":/Icons/oxygen/edit_clear.png")), tr("Rename..."));
|
||||||
|
//myFilesLlistMenu.addSeparator();
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Call menu
|
||||||
|
QAction *act = myFilesLlistMenu.exec(QCursor::pos());
|
||||||
|
if(act) {
|
||||||
|
if(act == actRename) {
|
||||||
|
renameSelectedFile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void renameSelectedFile() {
|
||||||
|
QModelIndexList selectedIndexes = torrentContentList->selectionModel()->selectedRows(0);
|
||||||
|
Q_ASSERT(selectedIndexes.size() == 1);
|
||||||
|
QModelIndex index = selectedIndexes.first();
|
||||||
|
// Ask for new name
|
||||||
|
bool ok;
|
||||||
|
QString new_name_last = QInputDialog::getText(this, tr("Rename torrent file"),
|
||||||
|
tr("New name:"), QLineEdit::Normal,
|
||||||
|
index.data().toString(), &ok);
|
||||||
|
if (ok && !new_name_last.isEmpty()) {
|
||||||
|
if(PropListModel->getType(index)==TFILE) {
|
||||||
|
// File renaming
|
||||||
|
uint file_index = PropListModel->getFileIndex(index);
|
||||||
|
QString old_name = files_path.at(file_index);
|
||||||
|
QStringList path_items = old_name.split(QDir::separator());
|
||||||
|
path_items.removeLast();
|
||||||
|
path_items << new_name_last;
|
||||||
|
QString new_name = path_items.join(QDir::separator());
|
||||||
|
if(old_name == new_name) {
|
||||||
|
qDebug("Name did not change");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Check if that name is already used
|
||||||
|
for(uint i=0; i<nbFiles; ++i) {
|
||||||
|
if(i == file_index) continue;
|
||||||
|
#ifdef Q_WS_WIN
|
||||||
|
if(files_path.at(i).compare(new_name, Qt::CaseInsensitive) == 0) {
|
||||||
|
#else
|
||||||
|
if(files_path.at(i).compare(new_name, Qt::CaseSensitive) == 0) {
|
||||||
|
#endif
|
||||||
|
// Display error message
|
||||||
|
QMessageBox::warning(this, tr("The file could not be renamed"),
|
||||||
|
tr("This name is already in use in this folder. Please use a different name."),
|
||||||
|
QMessageBox::Ok);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
qDebug("Renaming %s to %s", old_name.toLocal8Bit().data(), new_name.toLocal8Bit().data());
|
||||||
|
// Rename file in files_path
|
||||||
|
files_path.replace(file_index, new_name);
|
||||||
|
// Rename in torrent files model too
|
||||||
|
PropListModel->setData(index, new_name_last);
|
||||||
|
} else {
|
||||||
|
// Folder renaming
|
||||||
|
QStringList path_items;
|
||||||
|
path_items << index.data().toString();
|
||||||
|
QModelIndex parent = PropListModel->parent(index);
|
||||||
|
while(parent.isValid()) {
|
||||||
|
path_items.prepend(parent.data().toString());
|
||||||
|
parent = PropListModel->parent(parent);
|
||||||
|
}
|
||||||
|
QString old_path = path_items.join(QDir::separator());
|
||||||
|
path_items.removeLast();
|
||||||
|
path_items << new_name_last;
|
||||||
|
QString new_path = path_items.join(QDir::separator());
|
||||||
|
// Check for overwriting
|
||||||
|
for(uint i=0; i<nbFiles; ++i) {
|
||||||
|
QString current_name = files_path.at(i);
|
||||||
|
#ifdef Q_WS_WIN
|
||||||
|
if(current_name.contains(new_path, Qt::CaseInsensitive)) {
|
||||||
|
#else
|
||||||
|
if(current_name.contains(new_path, Qt::CaseSensitive)) {
|
||||||
|
#endif
|
||||||
|
QMessageBox::warning(this, tr("The folder could not be renamed"),
|
||||||
|
tr("This name is already in use in this folder. Please use a different name."),
|
||||||
|
QMessageBox::Ok);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Replace path in all files
|
||||||
|
for(uint i=0; i<nbFiles; ++i) {
|
||||||
|
QString current_name = files_path.at(i);
|
||||||
|
QString new_name = current_name.replace(old_path, new_path);
|
||||||
|
qDebug("Rename %s to %s", current_name.toLocal8Bit().data(), new_name.toLocal8Bit().data());
|
||||||
|
// Rename in files_path
|
||||||
|
files_path.replace(i, new_name);
|
||||||
|
}
|
||||||
|
// Rename folder in torrent files model too
|
||||||
|
PropListModel->setData(index, new_name_last);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void updateDiskSpaceLabels() {
|
void updateDiskSpaceLabels() {
|
||||||
long long available = misc::freeDiskSpaceOnPath(misc::expandPath(savePathTxt->text()));
|
long long available = misc::freeDiskSpaceOnPath(misc::expandPath(savePathTxt->text()));
|
||||||
lbl_disk_space->setText(misc::friendlyUnit(available));
|
lbl_disk_space->setText(misc::friendlyUnit(available));
|
||||||
|
@ -276,6 +385,22 @@ public slots:
|
||||||
TorrentTempData::setLabel(hash, comboLabel->currentText().trimmed());
|
TorrentTempData::setLabel(hash, comboLabel->currentText().trimmed());
|
||||||
// Is download sequential?
|
// Is download sequential?
|
||||||
TorrentTempData::setSequential(hash, checkIncrementalDL->isChecked());
|
TorrentTempData::setSequential(hash, checkIncrementalDL->isChecked());
|
||||||
|
// Save files path
|
||||||
|
// Loads files path in the torrent
|
||||||
|
bool path_changed = false;
|
||||||
|
for(uint i=0; i<nbFiles; ++i) {
|
||||||
|
#ifdef Q_WS_WIN
|
||||||
|
if(files_path.at(i).compare(misc::toQString(t->file_at(i).path.string()), Qt::CaseInsensitive) != 0) {
|
||||||
|
#else
|
||||||
|
if(files_path.at(i).compare(misc::toQString(t->file_at(i).path.string()), Qt::CaseSensitive) != 0) {
|
||||||
|
#endif
|
||||||
|
path_changed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(path_changed) {
|
||||||
|
TorrentTempData::setFilesPath(hash, files_path);
|
||||||
|
}
|
||||||
#ifdef LIBTORRENT_0_15
|
#ifdef LIBTORRENT_0_15
|
||||||
// Skip file checking and directly start seeding
|
// Skip file checking and directly start seeding
|
||||||
if(addInSeed->isChecked()) {
|
if(addInSeed->isChecked()) {
|
||||||
|
|
|
@ -78,6 +78,15 @@ public:
|
||||||
settings.setValue("torrents-tmp", all_data);
|
settings.setValue("torrents-tmp", all_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void setFilesPath(QString hash, QStringList path_list) {
|
||||||
|
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent-resume"));
|
||||||
|
QHash<QString, QVariant> all_data = settings.value("torrents-tmp", QHash<QString, QVariant>()).toHash();
|
||||||
|
QHash<QString, QVariant> data = all_data[hash].toHash();
|
||||||
|
data["files_path"] = path_list;
|
||||||
|
all_data[hash] = data;
|
||||||
|
settings.setValue("torrents-tmp", all_data);
|
||||||
|
}
|
||||||
|
|
||||||
static void setSavePath(QString hash, QString save_path) {
|
static void setSavePath(QString hash, QString save_path) {
|
||||||
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent-resume"));
|
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent-resume"));
|
||||||
QHash<QString, QVariant> all_data = settings.value("torrents-tmp", QHash<QString, QVariant>()).toHash();
|
QHash<QString, QVariant> all_data = settings.value("torrents-tmp", QHash<QString, QVariant>()).toHash();
|
||||||
|
@ -146,6 +155,15 @@ public:
|
||||||
return QString::null;
|
return QString::null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QStringList getFilesPath(QString hash) {
|
||||||
|
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent-resume"));
|
||||||
|
QHash<QString, QVariant> all_data = settings.value("torrents-tmp", QHash<QString, QVariant>()).toHash();
|
||||||
|
QHash<QString, QVariant> data = all_data[hash].toHash();
|
||||||
|
if(data.contains("files_path"))
|
||||||
|
return data["files_path"].toStringList();
|
||||||
|
return QStringList();
|
||||||
|
}
|
||||||
|
|
||||||
static QString getLabel(QString hash) {
|
static QString getLabel(QString hash) {
|
||||||
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent-resume"));
|
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent-resume"));
|
||||||
QHash<QString, QVariant> all_data = settings.value("torrents-tmp", QHash<QString, QVariant>()).toHash();
|
QHash<QString, QVariant> all_data = settings.value("torrents-tmp", QHash<QString, QVariant>()).toHash();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue