Changeset View
Changeset View
Standalone View
Standalone View
src/views/renamedialog.cpp
Show All 18 Lines | |||||
19 | 19 | | |||
20 | #include "renamedialog.h" | 20 | #include "renamedialog.h" | ||
21 | 21 | | |||
22 | #include <KLocalizedString> | 22 | #include <KLocalizedString> | ||
23 | #include <KJobWidgets> | 23 | #include <KJobWidgets> | ||
24 | #include <KIO/CopyJob> | 24 | #include <KIO/CopyJob> | ||
25 | #include <KIO/FileUndoManager> | 25 | #include <KIO/FileUndoManager> | ||
26 | #include <KJobUiDelegate> | 26 | #include <KJobUiDelegate> | ||
27 | #include <KIO/BatchRenameJob> | ||||
27 | 28 | | |||
28 | #include <QHBoxLayout> | 29 | #include <QHBoxLayout> | ||
29 | #include <QLabel> | 30 | #include <QLabel> | ||
30 | #include <QVBoxLayout> | 31 | #include <QVBoxLayout> | ||
31 | #include <QMimeDatabase> | 32 | #include <QMimeDatabase> | ||
32 | #include <QDialogButtonBox> | 33 | #include <QDialogButtonBox> | ||
33 | #include <QPushButton> | 34 | #include <QPushButton> | ||
34 | #include <QLineEdit> | 35 | #include <QLineEdit> | ||
▲ Show 20 Lines • Show All 108 Lines • ▼ Show 20 Line(s) | 116 | if (!m_renameOneItem) { | |||
143 | topLayout->addLayout(horizontalLayout); | 144 | topLayout->addLayout(horizontalLayout); | ||
144 | } | 145 | } | ||
145 | } | 146 | } | ||
146 | 147 | | |||
147 | RenameDialog::~RenameDialog() | 148 | RenameDialog::~RenameDialog() | ||
148 | { | 149 | { | ||
149 | } | 150 | } | ||
150 | 151 | | |||
151 | void RenameDialog::renameItem(const KFileItem &item, const QString& newName) | 152 | void RenameDialog::slotAccepted() | ||
152 | { | 153 | { | ||
153 | const QUrl oldUrl = item.url(); | | |||
154 | QUrl newUrl = oldUrl.adjusted(QUrl::RemoveFilename); | | |||
155 | newUrl.setPath(newUrl.path() + KIO::encodeFileName(newName)); | | |||
156 | | ||||
157 | QWidget* widget = parentWidget(); | 154 | QWidget* widget = parentWidget(); | ||
158 | if (!widget) { | 155 | if (!widget) { | ||
159 | widget = this; | 156 | widget = this; | ||
160 | } | 157 | } | ||
161 | 158 | | |||
162 | KIO::Job * job = KIO::moveAs(oldUrl, newUrl, KIO::HideProgressInfo); | 159 | KIO::FileUndoManager::CommandType cmdType; | ||
160 | if (m_renameOneItem) { | ||||
161 | Q_ASSERT(m_items.count() == 1); | ||||
162 | cmdType = KIO::FileUndoManager::Rename; | ||||
163 | } else { | ||||
164 | cmdType = KIO::FileUndoManager::BatchRename; | ||||
165 | } | ||||
166 | | ||||
167 | const QList<QUrl> srcList = m_items.urlList(); | ||||
168 | KIO::BatchRenameJob* job = KIO::batchRename(srcList, m_lineEdit->text(), m_spinBox->value(), QLatin1Char('#')); | ||||
163 | KJobWidgets::setWindow(job, widget); | 169 | KJobWidgets::setWindow(job, widget); | ||
164 | KIO::FileUndoManager::self()->recordJob(KIO::FileUndoManager::Rename, {oldUrl}, newUrl, job); | 170 | const QUrl parentUrl = srcList.first().adjusted(QUrl::RemoveFilename | QUrl::StripTrailingSlash); | ||
171 | KIO::FileUndoManager::self()->recordJob(cmdType, srcList, parentUrl, job); | ||||
165 | 172 | | |||
166 | if (!job->error()) { | 173 | connect(job, &KIO::BatchRenameJob::fileRenamed, this, &RenameDialog::slotFileRenamed); | ||
broulik: `KFileItemList` has a `urlList()` method that does that | |||||
167 | m_renamedItems << newUrl; | 174 | connect(job, &KIO::BatchRenameJob::result, this, &RenameDialog::slotResult); | ||
168 | } | | |||
169 | 175 | | |||
170 | job->uiDelegate()->setAutoErrorHandlingEnabled(true); | 176 | job->uiDelegate()->setAutoErrorHandlingEnabled(true); | ||
171 | } | | |||
172 | 177 | | |||
173 | void RenameDialog::slotAccepted() | | |||
174 | { | | |||
175 | m_newName = m_lineEdit->text(); | | |||
176 | | ||||
177 | if (m_renameOneItem) { | | |||
178 | Q_ASSERT(m_items.count() == 1); | | |||
179 | renameItem(m_items.first(), m_newName); | | |||
180 | } else { | | |||
181 | renameItems(); | | |||
182 | } | | |||
183 | accept(); | 178 | accept(); | ||
Do we need QUrl::StripTrailingSlash here? At least most other places in KIO that use RemoveFileName set it broulik: Do we need `QUrl::StripTrailingSlash` here? At least most other places in KIO that use… | |||||
When undoing BatchRename parentUrl is not used. So IMO setting QUrl::StripTrailingSlash won't make any difference. chinmoyr: When undoing BatchRename parentUrl is not used. So IMO setting QUrl::StripTrailingSlash won't… | |||||
The job is async, so by the time you end up here the job hasn't even started yet, your handling should be in slotFileRenamed or rather connect to result signal? broulik: The job is async, so by the time you end up here the job hasn't even started yet, your handling… | |||||
184 | } | 179 | } | ||
185 | 180 | | |||
186 | void RenameDialog::slotTextChanged(const QString& newName) | 181 | void RenameDialog::slotTextChanged(const QString& newName) | ||
187 | { | 182 | { | ||
188 | bool enable = !newName.isEmpty() && (newName != QLatin1String("..")) && (newName != QLatin1String(".")); | 183 | bool enable = !newName.isEmpty() && (newName != QLatin1String("..")) && (newName != QLatin1String(".")); | ||
189 | if (enable && !m_renameOneItem) { | 184 | if (enable && !m_renameOneItem) { | ||
190 | const int count = newName.count(QLatin1Char('#')); | 185 | const int count = newName.count(QLatin1Char('#')); | ||
191 | if (count == 0) { | 186 | if (count == 0) { | ||
192 | // Renaming multiple files without '#' will only work if all extensions are different. | 187 | // Renaming multiple files without '#' will only work if all extensions are different. | ||
193 | enable = m_allExtensionsDifferent; | 188 | enable = m_allExtensionsDifferent; | ||
194 | } else { | 189 | } else { | ||
195 | // Assure that the new name contains exactly one # (or a connected sequence of #'s) | 190 | // Assure that the new name contains exactly one # (or a connected sequence of #'s) | ||
196 | const int first = newName.indexOf(QLatin1Char('#')); | 191 | const int first = newName.indexOf(QLatin1Char('#')); | ||
197 | const int last = newName.lastIndexOf(QLatin1Char('#')); | 192 | const int last = newName.lastIndexOf(QLatin1Char('#')); | ||
198 | enable = (last - first + 1 == count); | 193 | enable = (last - first + 1 == count); | ||
199 | } | 194 | } | ||
200 | } | 195 | } | ||
201 | m_okButton->setEnabled(enable); | 196 | m_okButton->setEnabled(enable); | ||
202 | } | 197 | } | ||
203 | 198 | | |||
204 | void RenameDialog::showEvent(QShowEvent* event) | 199 | void RenameDialog::slotFileRenamed(const QUrl &oldUrl, const QUrl &newUrl) | ||
205 | { | 200 | { | ||
206 | m_lineEdit->setFocus(); | 201 | Q_UNUSED(oldUrl); | ||
elvisangelaccio: Nitpick, semicolon not necessary. | |||||
207 | 202 | m_renamedItems << newUrl; | |||
208 | QDialog::showEvent(event); | | |||
209 | } | 203 | } | ||
210 | 204 | | |||
211 | void RenameDialog::renameItems() | 205 | void RenameDialog::slotResult(KJob *job) | ||
212 | { | 206 | { | ||
213 | // Iterate through all items and rename them... | 207 | if (!job->error()) { | ||
214 | int index = m_spinBox->value(); | | |||
215 | foreach (const KFileItem& item, m_items) { | | |||
216 | QString newName = indexedName(m_newName, index, QLatin1Char('#')); | | |||
217 | ++index; | | |||
218 | | ||||
219 | const QUrl oldUrl = item.url(); | | |||
220 | QMimeDatabase db; | | |||
221 | const QString extension = db.suffixForFileName(oldUrl.path().toLower()); | | |||
222 | if (!extension.isEmpty()) { | | |||
223 | newName.append(QLatin1Char('.')); | | |||
224 | newName.append(extension); | | |||
225 | } | | |||
226 | | ||||
227 | if (oldUrl.fileName() != newName) { | | |||
228 | renameItem(item, newName); | | |||
229 | } | | |||
230 | } | | |||
231 | | ||||
232 | if (!m_items.empty()) { | | |||
233 | emit renamingFinished(m_renamedItems); | 208 | emit renamingFinished(m_renamedItems); | ||
234 | } | 209 | } | ||
235 | } | 210 | } | ||
236 | 211 | | |||
237 | QString RenameDialog::indexedName(const QString& name, int index, const QChar& indexPlaceHolder) | 212 | void RenameDialog::showEvent(QShowEvent* event) | ||
238 | { | 213 | { | ||
239 | QString newName = name; | 214 | m_lineEdit->setFocus(); | ||
240 | | ||||
241 | QString indexString = QString::number(index); | | |||
242 | | ||||
243 | // Insert leading zeros if necessary | | |||
244 | const int minIndexLength = name.count(indexPlaceHolder); | | |||
245 | while (indexString.length() < minIndexLength) { | | |||
246 | indexString.prepend(QLatin1Char('0')); | | |||
247 | } | | |||
248 | | ||||
249 | // Replace the index placeholders by the indexString | | |||
250 | const int placeHolderStart = newName.indexOf(indexPlaceHolder); | | |||
251 | newName.replace(placeHolderStart, minIndexLength, indexString); | | |||
252 | 215 | | |||
253 | return newName; | 216 | QDialog::showEvent(event); | ||
254 | } | 217 | } | ||
255 | |
KFileItemList has a urlList() method that does that