Browse Source

- Files / Folders can also be renamed directly from torrent addition dialog

adaptive-webui-19844
Christophe Dumez 15 years ago
parent
commit
add2475700
  1. 2
      Changelog
  2. 8
      src/bittorrent.cpp
  3. 2
      src/propertieswidget.cpp
  4. 305
      src/torrentadditiondlg.h
  5. 18
      src/torrentpersistentdata.h

2
Changelog

@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
- FEATURE: Disk cache size can be set from preferences
- FEATURE: Peer Exchange (PeX) can be disabled from preferences
- 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: Better proxy support and preferences remodeling
- FEATURE: qBittorrent can identify itself as uTorrent or Vuze (Any version)

8
src/bittorrent.cpp

@ -960,6 +960,14 @@ QTorrentHandle Bittorrent::addTorrent(QString path, bool fromScanDir, QString fr @@ -960,6 +960,14 @@ QTorrentHandle Bittorrent::addTorrent(QString path, bool fromScanDir, QString fr
qDebug("addTorrent: Setting download as sequential (from tmp data)");
h.prioritize_files(TorrentTempData::getFilesPriority(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);
// Save persistent data for new torrent

2
src/propertieswidget.cpp

@ -467,7 +467,7 @@ void PropertiesWidget::displayFilesListMenu(const QPoint&){ @@ -467,7 +467,7 @@ void PropertiesWidget::displayFilesListMenu(const QPoint&){
QAction *actRename = 0;
if(selectedRows.size() == 1) {
actRename = myFilesLlistMenu.addAction(QIcon(QString::fromUtf8(":/Icons/oxygen/edit_clear.png")), tr("Rename..."));
myFilesLlistMenu.addSeparator();
//myFilesLlistMenu.addSeparator();
} else {
return;
}

305
src/torrentadditiondlg.h

@ -41,6 +41,7 @@ @@ -41,6 +41,7 @@
#include <QHeaderView>
#include <QApplication>
#include <QDesktopWidget>
#include <QInputDialog>
#include <libtorrent/session.hpp>
#include <libtorrent/bencode.hpp>
@ -67,6 +68,7 @@ private: @@ -67,6 +68,7 @@ private:
PropListDelegate *PropDelegate;
unsigned int nbFiles;
boost::intrusive_ptr<torrent_info> t;
QStringList files_path;
public:
torrentAdditionDialog(QWidget *parent, Bittorrent* _BTSession) : QDialog(parent) {
@ -80,6 +82,7 @@ public: @@ -80,6 +82,7 @@ public:
PropDelegate = new PropListDelegate();
torrentContentList->setItemDelegate(PropDelegate);
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(expandAllButton, SIGNAL(clicked()), torrentContentList, SLOT(expandAll()));
// Remember columns width
@ -194,113 +197,235 @@ public: @@ -194,113 +197,235 @@ public:
foreach(const QString& label, customLabels) {
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();
}
public slots:
void updateDiskSpaceLabels() {
long long available = misc::freeDiskSpaceOnPath(misc::expandPath(savePathTxt->text()));
lbl_disk_space->setText(misc::friendlyUnit(available));
// Determine torrent size
qulonglong torrent_size = 0;
unsigned int nbFiles = t->num_files();
std::vector<int> priorities = PropListModel->getFilesPriorities(nbFiles);
for(unsigned int i=0; i<nbFiles; ++i) {
if(priorities[i] > 0)
torrent_size += t->file_at(i).size;
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;
}
lbl_torrent_size->setText(misc::friendlyUnit(torrent_size));
// Check if free space is sufficient
if(available > 0) {
if((unsigned long long)available > torrent_size) {
// Space is sufficient
label_space_msg->setText(tr("(%1 left after torrent download)", "e.g. (100MiB left after torrent download)").arg(misc::friendlyUnit(available-torrent_size)));
} else {
// Space is unsufficient
label_space_msg->setText("<font color=\"red\">"+tr("(%1 more are required to download)", "e.g. (100MiB more are required to download)").arg(misc::friendlyUnit(torrent_size-available))+"</font>");
// Call menu
QAction *act = myFilesLlistMenu.exec(QCursor::pos());
if(act) {
if(act == actRename) {
renameSelectedFile();
}
} else {
// Available disk space is unknown
label_space_msg->setText("");
}
}
void on_browseButton_clicked(){
QString dir;
QString save_path = misc::expandPath(savePathTxt->text());
QDir saveDir(save_path);
if(!save_path.isEmpty() && saveDir.exists()){
dir = QFileDialog::getExistingDirectory(this, tr("Choose save path"), saveDir.absolutePath());
}else{
dir = QFileDialog::getExistingDirectory(this, tr("Choose save path"), QDir::homePath());
}
if(!dir.isNull()){
savePathTxt->setText(dir);
}
}
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 on_CancelButton_clicked(){
close();
}
void updateDiskSpaceLabels() {
long long available = misc::freeDiskSpaceOnPath(misc::expandPath(savePathTxt->text()));
lbl_disk_space->setText(misc::friendlyUnit(available));
bool allFiltered() const {
return PropListModel->allFiltered();
}
// Determine torrent size
qulonglong torrent_size = 0;
unsigned int nbFiles = t->num_files();
std::vector<int> priorities = PropListModel->getFilesPriorities(nbFiles);
void savePiecesPriorities(){
qDebug("Saving pieces priorities");
std::vector<int> priorities = PropListModel->getFilesPriorities(t->num_files());
TorrentTempData::setFilesPriority(hash, priorities);
}
for(unsigned int i=0; i<nbFiles; ++i) {
if(priorities[i] > 0)
torrent_size += t->file_at(i).size;
}
lbl_torrent_size->setText(misc::friendlyUnit(torrent_size));
// Check if free space is sufficient
if(available > 0) {
if((unsigned long long)available > torrent_size) {
// Space is sufficient
label_space_msg->setText(tr("(%1 left after torrent download)", "e.g. (100MiB left after torrent download)").arg(misc::friendlyUnit(available-torrent_size)));
} else {
// Space is unsufficient
label_space_msg->setText("<font color=\"red\">"+tr("(%1 more are required to download)", "e.g. (100MiB more are required to download)").arg(misc::friendlyUnit(torrent_size-available))+"</font>");
}
} else {
// Available disk space is unknown
label_space_msg->setText("");
}
}
void on_OkButton_clicked(){
if(savePathTxt->text().trimmed().isEmpty()){
QMessageBox::critical(0, tr("Empty save path"), tr("Please enter a save path"));
return;
}
QDir savePath(misc::expandPath(savePathTxt->text()));
// Check if savePath exists
if(!savePath.exists()){
if(!savePath.mkpath(savePath.path())){
QMessageBox::critical(0, tr("Save path creation error"), tr("Could not create the save path"));
return;
void on_browseButton_clicked(){
QString dir;
QString save_path = misc::expandPath(savePathTxt->text());
QDir saveDir(save_path);
if(!save_path.isEmpty() && saveDir.exists()){
dir = QFileDialog::getExistingDirectory(this, tr("Choose save path"), saveDir.absolutePath());
}else{
dir = QFileDialog::getExistingDirectory(this, tr("Choose save path"), QDir::homePath());
}
if(!dir.isNull()){
savePathTxt->setText(dir);
}
}
}
// Save savepath
TorrentTempData::setSavePath(hash, savePath.path());
qDebug("Torrent label is: %s", comboLabel->currentText().trimmed().toLocal8Bit().data());
TorrentTempData::setLabel(hash, comboLabel->currentText().trimmed());
// Is download sequential?
TorrentTempData::setSequential(hash, checkIncrementalDL->isChecked());
#ifdef LIBTORRENT_0_15
// Skip file checking and directly start seeding
if(addInSeed->isChecked()) {
// Check if local file(s) actually exist
if(savePath.exists(misc::toQString(t->name()))) {
TorrentTempData::setSeedingMode(hash, true);
} else {
QMessageBox::warning(0, tr("Seeding mode error"), tr("You chose to skip file checking. However, local files do not seem to exist in the current destionation folder. Please disable this feature or update the save path."));
return;
void on_CancelButton_clicked(){
close();
}
}
bool allFiltered() const {
return PropListModel->allFiltered();
}
void savePiecesPriorities(){
qDebug("Saving pieces priorities");
std::vector<int> priorities = PropListModel->getFilesPriorities(t->num_files());
TorrentTempData::setFilesPriority(hash, priorities);
}
void on_OkButton_clicked(){
if(savePathTxt->text().trimmed().isEmpty()){
QMessageBox::critical(0, tr("Empty save path"), tr("Please enter a save path"));
return;
}
QDir savePath(misc::expandPath(savePathTxt->text()));
// Check if savePath exists
if(!savePath.exists()){
if(!savePath.mkpath(savePath.path())){
QMessageBox::critical(0, tr("Save path creation error"), tr("Could not create the save path"));
return;
}
}
// Save savepath
TorrentTempData::setSavePath(hash, savePath.path());
qDebug("Torrent label is: %s", comboLabel->currentText().trimmed().toLocal8Bit().data());
TorrentTempData::setLabel(hash, comboLabel->currentText().trimmed());
// Is download sequential?
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
// Check if there is at least one selected file
if(allFiltered()){
QMessageBox::warning(0, tr("Invalid file selection"), tr("You must select at least one file in the torrent"));
return;
}
// save filtered files
savePiecesPriorities();
// Add to download list
QTorrentHandle h = BTSession->addTorrent(filePath, false, from_url);
if(addInPause->isChecked() && h.is_valid())
h.pause();
close();
}
};
path_changed = true;
break;
}
}
if(path_changed) {
TorrentTempData::setFilesPath(hash, files_path);
}
#ifdef LIBTORRENT_0_15
// Skip file checking and directly start seeding
if(addInSeed->isChecked()) {
// Check if local file(s) actually exist
if(savePath.exists(misc::toQString(t->name()))) {
TorrentTempData::setSeedingMode(hash, true);
} else {
QMessageBox::warning(0, tr("Seeding mode error"), tr("You chose to skip file checking. However, local files do not seem to exist in the current destionation folder. Please disable this feature or update the save path."));
return;
}
}
#endif
// Check if there is at least one selected file
if(allFiltered()){
QMessageBox::warning(0, tr("Invalid file selection"), tr("You must select at least one file in the torrent"));
return;
}
// save filtered files
savePiecesPriorities();
// Add to download list
QTorrentHandle h = BTSession->addTorrent(filePath, false, from_url);
if(addInPause->isChecked() && h.is_valid())
h.pause();
close();
}
};
#endif

18
src/torrentpersistentdata.h

@ -78,6 +78,15 @@ public: @@ -78,6 +78,15 @@ public:
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) {
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent-resume"));
QHash<QString, QVariant> all_data = settings.value("torrents-tmp", QHash<QString, QVariant>()).toHash();
@ -146,6 +155,15 @@ public: @@ -146,6 +155,15 @@ public:
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) {
QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent-resume"));
QHash<QString, QVariant> all_data = settings.value("torrents-tmp", QHash<QString, QVariant>()).toHash();

Loading…
Cancel
Save