diff --git a/src/panels/folders/folderspanel.cpp b/src/panels/folders/folderspanel.cpp index 729dac3727..1dabefd110 100644 --- a/src/panels/folders/folderspanel.cpp +++ b/src/panels/folders/folderspanel.cpp @@ -95,18 +95,11 @@ void FoldersPanel::rename(const KFileItem& item) const QModelIndex proxyIndex = m_proxyModel->mapFromSource(dirIndex); m_treeView->edit(proxyIndex); } else { - KFileItemList items; - items.append(item); - QPointer dialog = new RenameDialog(this, items); - if (dialog->exec() == QDialog::Accepted) { - const QString newName = dialog->newName(); - if (!newName.isEmpty()) { - KUrl newUrl = item.url(); - newUrl.setFileName(newName); - KonqOperations::rename(this, item.url(), newUrl); - } - } - delete dialog; + RenameDialog* dialog = new RenameDialog(this, KFileItemList() << item); + dialog->setAttribute(Qt::WA_DeleteOnClose); + dialog->show(); + dialog->raise(); + dialog->activateWindow(); } } diff --git a/src/views/dolphinview.cpp b/src/views/dolphinview.cpp index e9bee31863..79706358ff 100644 --- a/src/views/dolphinview.cpp +++ b/src/views/dolphinview.cpp @@ -45,7 +45,6 @@ #include #include #include -#include #include #include @@ -68,15 +67,6 @@ #include "zoomlevelinfo.h" #include "dolphindetailsviewexpander.h" -/** - * Helper function for sorting items with qSort() in - * DolphinView::renameSelectedItems(). - */ -bool lessThan(const KFileItem& item1, const KFileItem& item2) -{ - return KStringHandler::naturalCompare(item1.name(), item2.name()) < 0; -} - DolphinView::DolphinView(QWidget* parent, const KUrl& url, DolphinSortFilterProxyModel* proxyModel) : @@ -600,7 +590,7 @@ void DolphinView::renameSelectedItems() if (itemCount < 1) { return; } - +/* if (itemCount > 1) { // More than one item has been selected for renaming. Open // a rename dialog and rename all items afterwards. @@ -646,16 +636,21 @@ void DolphinView::renameSelectedItems() KonqOperations::rename(this, oldUrl, newUrl); } } - } else if (DolphinSettings::instance().generalSettings()->renameInline()) { - Q_ASSERT(itemCount == 1); + } else*/ + + if ((itemCount == 1) && DolphinSettings::instance().generalSettings()->renameInline()) { const QModelIndex dirIndex = m_viewAccessor.dirModel()->indexForItem(items.first()); const QModelIndex proxyIndex = m_viewAccessor.proxyModel()->mapFromSource(dirIndex); m_viewAccessor.itemView()->edit(proxyIndex); } else { - Q_ASSERT(itemCount == 1); + RenameDialog* dialog = new RenameDialog(this, items); + dialog->setAttribute(Qt::WA_DeleteOnClose); + dialog->show(); + dialog->raise(); + dialog->activateWindow(); - QPointer dialog = new RenameDialog(this, items); - if (dialog->exec() == QDialog::Rejected) { + // XXX + /* if (dialog->exec() == QDialog::Rejected) { delete dialog; return; } @@ -671,7 +666,7 @@ void DolphinView::renameSelectedItems() const KUrl& oldUrl = items.first().url(); KUrl newUrl = oldUrl; newUrl.setFileName(newName); - KonqOperations::rename(this, oldUrl, newUrl); + KonqOperations::rename(this, oldUrl, newUrl);*/ } // assure that the current index remains visible when KDirLister diff --git a/src/views/renamedialog.cpp b/src/views/renamedialog.cpp index aae546e7a8..7f79b0d430 100644 --- a/src/views/renamedialog.cpp +++ b/src/views/renamedialog.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2006 by Peter Penz (peter.penz@gmx.at) * + * Copyright (C) 2006-2010 by Peter Penz (peter.penz@gmx.at) * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -19,16 +19,29 @@ #include "renamedialog.h" -#include #include #include +#include +#include -#include -#include +#include +#include + +/** + * Helper function for sorting items with qSort() in + * DolphinView::renameSelectedItems(). + */ +bool lessThan(const KFileItem& item1, const KFileItem& item2) +{ + return KStringHandler::naturalCompare(item1.name(), item2.name()) < 0; +} RenameDialog::RenameDialog(QWidget *parent, const KFileItemList& items) : KDialog(parent), - m_renameOneItem(false) + m_renameOneItem(false), + m_newName(), + m_lineEdit(0), + m_items(items) { const QSize minSize = minimumSize(); setMinimumSize(QSize(320, minSize.height())); @@ -116,25 +129,77 @@ RenameDialog::~RenameDialog() void RenameDialog::slotButtonClicked(int button) { - if (button == Ok) { - m_newName = m_lineEdit->text(); - if (m_newName.isEmpty()) { - m_errorString = i18nc("@info:status", - "The new name is empty. A name with at least one character must be entered."); - } else if (!m_renameOneItem && (m_newName.count('#') == 0)) { - m_newName.truncate(0); - m_errorString = i18nc("@info:status", "The name must contain at least one # character."); - } + if (button == KDialog::Ok) { + renameItems(); } KDialog::slotButtonClicked(button); } -void RenameDialog::slotTextChanged(const QString &newName) +void RenameDialog::slotTextChanged(const QString& newName) { - const bool enable = !newName.isEmpty() && (m_renameOneItem ? (newName != m_newName) : newName.contains('#')); + m_newName = m_lineEdit->text(); + + bool enable = !newName.isEmpty() && (m_renameOneItem ? (newName != m_newName) : newName.contains('#')); + if (enable) { + if (m_renameOneItem) { + enable = enable && (newName != m_newName); + } else { + // Assure that the new name contains exactly one # (or a connected sequence of #'s) + const int minSplitCount = 1; + int maxSplitCount = 2; + if (newName.startsWith(QLatin1Char('#'))) { + --maxSplitCount; + } + if (newName.endsWith(QLatin1Char('#'))) { + --maxSplitCount; + } + const int splitCount = newName.split(QLatin1Char('#'), QString::SkipEmptyParts).count(); + enable = enable && (splitCount >= minSplitCount) && (splitCount <= maxSplitCount); + } + } enableButtonOk(enable); } +void RenameDialog::renameItems() +{ + // Currently the items are sorted by the selection order, resort + // them by the filename. This assures that the new sort order is similar to + // the current filename sort order. + qSort(m_items.begin(), m_items.end(), lessThan); + + // Iterate through all items and rename them... + int index = 1; + foreach (const KFileItem& item, m_items) { + const QString newName = indexedName(m_newName, index, QLatin1Char('#')); + ++index; + + const KUrl oldUrl = item.url(); + if (oldUrl.fileName() != newName) { + KUrl newUrl = oldUrl; + newUrl.setFileName(newName); + KonqOperations::rename(this, oldUrl, newUrl); + } + } +} + +QString RenameDialog::indexedName(const QString& name, int index, const QChar& indexPlaceHolder) +{ + QString newName = name; + + QString indexString = QString::number(index); + + // Insert leading zeros if necessary + const int minIndexLength = name.count(indexPlaceHolder); + while (indexString.length() < minIndexLength) { + indexString.prepend(QLatin1Char('0')); + } + + // Replace the index placeholders by the indexString + const int placeHolderStart = newName.indexOf(indexPlaceHolder); + newName.replace(placeHolderStart, minIndexLength, indexString); + + return newName; +} #include "renamedialog.moc" diff --git a/src/views/renamedialog.h b/src/views/renamedialog.h index 5015b51bd2..73414093ca 100644 --- a/src/views/renamedialog.h +++ b/src/views/renamedialog.h @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2006 by Peter Penz (peter.penz@gmx.at) * + * Copyright (C) 2006-2010 by Peter Penz (peter.penz@gmx.at) * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -16,86 +16,54 @@ * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * ***************************************************************************/ + #ifndef RENAMEDIALOG_H #define RENAMEDIALOG_H #include "libdolphin_export.h" #include -#include +#include -class KFileItem; -class KFileItemList; class KLineEdit; #include /** * @brief Dialog for renaming a variable number of files. - * - * The renaming is not done by the dialog, the invoker - * must do this itself: - * \code - * RenameDialog dialog(...); - * if (dialog.exec() == QDialog::Accepted) { - * const QString& newName = dialog.newName(); - * if (newName.isEmpty()) { - * // an invalid name has been chosen, use - * // dialog.errorString() to tell the user about this - * } - * else { - * // rename items corresponding to the new name - * } - * } - * \endcode */ class LIBDOLPHINPRIVATE_EXPORT RenameDialog : public KDialog { Q_OBJECT public: - explicit RenameDialog(QWidget *parent, const KFileItemList& items); + explicit RenameDialog(QWidget* parent, const KFileItemList& items); virtual ~RenameDialog(); - /** - * Returns the new name of the items. If more than one - * item should be renamed, then it is assured that the # character - * is part of the returned string. If the returned string is empty, - * then RenameDialog::errorString() should be used to show the reason - * of having an empty string (e. g. if the # character has - * been deleted by the user, although more than one item should be - * renamed). - */ - QString newName() const; - - /** - * Returns the error string, if Dialog::newName() returned an empty string. - */ - QString errorString() const; - protected slots: virtual void slotButtonClicked(int button); private slots: - void slotTextChanged(const QString &newName); + void slotTextChanged(const QString& newName); + +private: + void renameItems(); + + + /** + * @return Returns the string \p name, where the characters represented by + * \p indexPlaceHolder get replaced by the index \p index. + * E. g. Calling indexedName("Test #.jpg", 12, '#') returns "Test 12.jpg". + * A connected sequence of placeholders results in leading zeros: + * indexedName("Test ####.jpg", 12, '#') returns "Test 0012.jpg". + */ + static QString indexedName(const QString& name, int index, const QChar& indexPlaceHolder); private: bool m_renameOneItem; - KLineEdit* m_lineEdit; QString m_newName; - QString m_errorString; - - friend class RenameDialogTest; // allow access for unit testing + KLineEdit* m_lineEdit; + KFileItemList m_items; }; -inline QString RenameDialog::newName() const -{ - return m_newName; -} - -inline QString RenameDialog::errorString() const -{ - return m_errorString; -} - #endif