diff --git a/src/gui/properties/propertieswidget.cpp b/src/gui/properties/propertieswidget.cpp index 07209d963..2796740f8 100644 --- a/src/gui/properties/propertieswidget.cpp +++ b/src/gui/properties/propertieswidget.cpp @@ -150,7 +150,8 @@ PropertiesWidget::PropertiesWidget(QWidget *parent) connect(m_tabBar, &PropTabBar::visibilityToggled, this, &PropertiesWidget::saveSettings); m_editHotkeyFile = new QShortcut(Qt::Key_F2, m_ui->filesList, nullptr, nullptr, Qt::WidgetShortcut); - connect(m_editHotkeyFile, &QShortcut::activated, this, &PropertiesWidget::renameSelectedFile); + connect(m_editHotkeyFile, &QShortcut::activated + , this, [this]() { m_ui->filesList->renameSelectedFile(m_torrent); }); m_editHotkeyWeb = new QShortcut(Qt::Key_F2, m_ui->listWebSeeds, nullptr, nullptr, Qt::WidgetShortcut); connect(m_editHotkeyWeb, &QShortcut::activated, this, &PropertiesWidget::editWebSeed); connect(m_ui->listWebSeeds, &QListWidget::doubleClicked, this, &PropertiesWidget::editWebSeed); @@ -621,7 +622,7 @@ void PropertiesWidget::displayFilesListMenu(const QPoint &) openFolder(index, true); } else if (act == actRename) { - renameSelectedFile(); + m_ui->filesList->renameSelectedFile(m_torrent); } else { BitTorrent::DownloadPriority prio = BitTorrent::DownloadPriority::Normal; @@ -673,125 +674,6 @@ void PropertiesWidget::displayWebSeedListMenu(const QPoint &) editWebSeed(); } -void PropertiesWidget::renameSelectedFile() -{ - if (!m_torrent) return; - - const QModelIndexList selectedIndexes = m_ui->filesList->selectionModel()->selectedRows(0); - if (selectedIndexes.size() != 1) return; - - const QModelIndex modelIndex = selectedIndexes.first(); - if (!modelIndex.isValid()) return; - - // Ask for new name - bool ok = false; - const bool isFile = (m_propListModel->itemType(modelIndex) == TorrentContentModelItem::FileType); - QString newName = AutoExpandableDialog::getText(this, tr("Renaming"), tr("New name:"), QLineEdit::Normal - , modelIndex.data().toString(), &ok, isFile).trimmed(); - if (!ok) return; - - if (newName.isEmpty() || !Utils::Fs::isValidFileSystemName(newName)) { - RaisedMessageBox::warning(this, tr("Rename error"), - tr("The name is empty or contains forbidden characters, please choose a different one."), - QMessageBox::Ok); - return; - } - - if (isFile) { - const int fileIndex = m_propListModel->getFileIndex(modelIndex); - - if (newName.endsWith(QB_EXT)) - newName.chop(QB_EXT.size()); - const QString oldFileName = m_torrent->fileName(fileIndex); - const QString oldFilePath = m_torrent->filePath(fileIndex); - - const bool useFilenameExt = BitTorrent::Session::instance()->isAppendExtensionEnabled() - && (m_torrent->filesProgress()[fileIndex] != 1); - const QString newFileName = newName + (useFilenameExt ? QB_EXT : QString()); - const QString newFilePath = oldFilePath.leftRef(oldFilePath.size() - oldFileName.size()) + newFileName; - - if (oldFileName == newFileName) { - qDebug("Name did not change: %s", qUtf8Printable(oldFileName)); - return; - } - - // check if that name is already used - for (int i = 0; i < m_torrent->filesCount(); ++i) { - if (i == fileIndex) continue; - if (Utils::Fs::sameFileNames(m_torrent->filePath(i), newFilePath)) { - RaisedMessageBox::warning(this, tr("Rename error"), - tr("This name is already in use in this folder. Please use a different name."), - QMessageBox::Ok); - return; - } - } - - qDebug("Renaming %s to %s", qUtf8Printable(oldFilePath), qUtf8Printable(newFilePath)); - m_torrent->renameFile(fileIndex, newFilePath); - - m_propListModel->setData(modelIndex, newName); - } - else { - // renaming a folder - QStringList pathItems; - pathItems << modelIndex.data().toString(); - QModelIndex parent = m_propListModel->parent(modelIndex); - while (parent.isValid()) { - pathItems.prepend(parent.data().toString()); - parent = m_propListModel->parent(parent); - } - const QString oldPath = pathItems.join('/'); - pathItems.removeLast(); - pathItems << newName; - QString newPath = pathItems.join('/'); - if (Utils::Fs::sameFileNames(oldPath, newPath)) { - qDebug("Name did not change"); - return; - } - if (!newPath.endsWith('/')) newPath += '/'; - // Check for overwriting - for (int i = 0; i < m_torrent->filesCount(); ++i) { - const QString currentName = m_torrent->filePath(i); -#if defined(Q_OS_UNIX) || defined(Q_WS_QWS) - if (currentName.startsWith(newPath, Qt::CaseSensitive)) { -#else - if (currentName.startsWith(newPath, Qt::CaseInsensitive)) { -#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; - } - } - bool forceRecheck = false; - // Replace path in all files - for (int i = 0; i < m_torrent->filesCount(); ++i) { - const QString currentName = m_torrent->filePath(i); - if (currentName.startsWith(oldPath)) { - QString newName = currentName; - newName.replace(0, oldPath.length(), newPath); - if (!forceRecheck && QDir(m_torrent->savePath(true)).exists(newName)) - forceRecheck = true; - newName = Utils::Fs::expandPath(newName); - qDebug("Rename %s to %s", qUtf8Printable(currentName), qUtf8Printable(newName)); - m_torrent->renameFile(i, newName); - } - } - // Force recheck - if (forceRecheck) m_torrent->forceRecheck(); - // Rename folder in torrent files model too - m_propListModel->setData(modelIndex, newName); - // Remove old folder - const QDir oldFolder(m_torrent->savePath(true) + '/' + oldPath); - int timeout = 10; - while (!QDir().rmpath(oldFolder.absolutePath()) && (timeout > 0)) { - // FIXME: We should not sleep here (freezes the UI for 1 second) - QThread::msleep(100); - --timeout; - } - } -} - void PropertiesWidget::openSelectedFile() { const QModelIndexList selectedIndexes = m_ui->filesList->selectionModel()->selectedRows(0); diff --git a/src/gui/properties/propertieswidget.h b/src/gui/properties/propertieswidget.h index c0c5750d3..7d4265c55 100644 --- a/src/gui/properties/propertieswidget.h +++ b/src/gui/properties/propertieswidget.h @@ -95,7 +95,6 @@ protected slots: void filteredFilesChanged(); void showPiecesDownloaded(bool show); void showPiecesAvailability(bool show); - void renameSelectedFile(); void openSelectedFile(); private slots: diff --git a/src/gui/torrentcontenttreeview.cpp b/src/gui/torrentcontenttreeview.cpp index 712964a95..48a7c7a8e 100644 --- a/src/gui/torrentcontenttreeview.cpp +++ b/src/gui/torrentcontenttreeview.cpp @@ -28,11 +28,22 @@ #include "torrentcontenttreeview.h" +#include #include #include +#include +#include #include #include +#include +#include "base/bittorrent/session.h" +#include "base/bittorrent/torrenthandle.h" +#include "base/global.h" +#include "base/utils/fs.h" +#include "autoexpandabledialog.h" +#include "raisedmessagebox.h" +#include "torrentcontentfiltermodel.h" #include "torrentcontentmodelitem.h" TorrentContentTreeView::TorrentContentTreeView(QWidget *parent) @@ -75,6 +86,128 @@ void TorrentContentTreeView::keyPressEvent(QKeyEvent *event) } } +void TorrentContentTreeView::renameSelectedFile(BitTorrent::TorrentHandle *torrent) +{ + if (!torrent) return; + + const QModelIndexList selectedIndexes = selectionModel()->selectedRows(0); + if (selectedIndexes.size() != 1) return; + + const QModelIndex modelIndex = selectedIndexes.first(); + if (!modelIndex.isValid()) return; + + auto model = dynamic_cast(TorrentContentTreeView::model()); + if (!model) return; + + // Ask for new name + bool ok = false; + const bool isFile = (model->itemType(modelIndex) == TorrentContentModelItem::FileType); + QString newName = AutoExpandableDialog::getText(this, tr("Renaming"), tr("New name:"), QLineEdit::Normal + , modelIndex.data().toString(), &ok, isFile).trimmed(); + if (!ok) return; + + if (newName.isEmpty() || !Utils::Fs::isValidFileSystemName(newName)) { + RaisedMessageBox::warning(this, tr("Rename error"), + tr("The name is empty or contains forbidden characters, please choose a different one."), + QMessageBox::Ok); + return; + } + + if (isFile) { + const int fileIndex = model->getFileIndex(modelIndex); + + if (newName.endsWith(QB_EXT)) + newName.chop(QB_EXT.size()); + const QString oldFileName = torrent->fileName(fileIndex); + const QString oldFilePath = torrent->filePath(fileIndex); + + const bool useFilenameExt = BitTorrent::Session::instance()->isAppendExtensionEnabled() + && (torrent->filesProgress()[fileIndex] != 1); + const QString newFileName = newName + (useFilenameExt ? QB_EXT : QString()); + const QString newFilePath = oldFilePath.leftRef(oldFilePath.size() - oldFileName.size()) + newFileName; + + if (oldFileName == newFileName) { + qDebug("Name did not change: %s", qUtf8Printable(oldFileName)); + return; + } + + // check if that name is already used + for (int i = 0; i < torrent->filesCount(); ++i) { + if (i == fileIndex) continue; + if (Utils::Fs::sameFileNames(torrent->filePath(i), newFilePath)) { + RaisedMessageBox::warning(this, tr("Rename error"), + tr("This name is already in use in this folder. Please use a different name."), + QMessageBox::Ok); + return; + } + } + + qDebug("Renaming %s to %s", qUtf8Printable(oldFilePath), qUtf8Printable(newFilePath)); + torrent->renameFile(fileIndex, newFilePath); + + model->setData(modelIndex, newName); + } + else { + // renaming a folder + QStringList pathItems; + pathItems << modelIndex.data().toString(); + QModelIndex parent = model->parent(modelIndex); + while (parent.isValid()) { + pathItems.prepend(parent.data().toString()); + parent = model->parent(parent); + } + const QString oldPath = pathItems.join('/'); + pathItems.removeLast(); + pathItems << newName; + QString newPath = pathItems.join('/'); + if (Utils::Fs::sameFileNames(oldPath, newPath)) { + qDebug("Name did not change"); + return; + } + if (!newPath.endsWith('/')) newPath += '/'; + // Check for overwriting + for (int i = 0; i < torrent->filesCount(); ++i) { + const QString currentName = torrent->filePath(i); +#if defined(Q_OS_UNIX) || defined(Q_WS_QWS) + if (currentName.startsWith(newPath, Qt::CaseSensitive)) { +#else + if (currentName.startsWith(newPath, Qt::CaseInsensitive)) { +#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; + } + } + bool forceRecheck = false; + // Replace path in all files + for (int i = 0; i < torrent->filesCount(); ++i) { + const QString currentName = torrent->filePath(i); + if (currentName.startsWith(oldPath)) { + QString newName = currentName; + newName.replace(0, oldPath.length(), newPath); + if (!forceRecheck && QDir(torrent->savePath(true)).exists(newName)) + forceRecheck = true; + newName = Utils::Fs::expandPath(newName); + qDebug("Rename %s to %s", qUtf8Printable(currentName), qUtf8Printable(newName)); + torrent->renameFile(i, newName); + } + } + // Force recheck + if (forceRecheck) torrent->forceRecheck(); + // Rename folder in torrent files model too + model->setData(modelIndex, newName); + // Remove old folder + const QDir oldFolder(torrent->savePath(true) + '/' + oldPath); + int timeout = 10; + while (!QDir().rmpath(oldFolder.absolutePath()) && (timeout > 0)) { + // FIXME: We should not sleep here (freezes the UI for 1 second) + QThread::msleep(100); + --timeout; + } + } +} + QModelIndex TorrentContentTreeView::currentNameCell() { QModelIndex current = currentIndex(); diff --git a/src/gui/torrentcontenttreeview.h b/src/gui/torrentcontenttreeview.h index 62c1d4471..d2d75e25a 100644 --- a/src/gui/torrentcontenttreeview.h +++ b/src/gui/torrentcontenttreeview.h @@ -31,6 +31,11 @@ #include +namespace BitTorrent +{ + class TorrentHandle; +} + class TorrentContentTreeView : public QTreeView { Q_OBJECT @@ -39,6 +44,8 @@ public: explicit TorrentContentTreeView(QWidget *parent = nullptr); void keyPressEvent(QKeyEvent *event) override; + void renameSelectedFile(BitTorrent::TorrentHandle *torrent); + private: QModelIndex currentNameCell(); };