1 /**
2 * \file rendirdialog.cpp
3 * Rename directory dialog.
4 *
5 * \b Project: Kid3
6 * \author Urs Fleisch
7 * \date 21 Mar 2004
8 *
9 * Copyright (C) 2004-2018 Urs Fleisch
10 *
11 * This file is part of Kid3.
12 *
13 * Kid3 is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * Kid3 is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25 */
26
27 #include "rendirdialog.h"
28 #include <QLayout>
29 #include <QPushButton>
30 #include <QComboBox>
31 #include <QLabel>
32 #include <QDir>
33 #include <QApplication>
34 #include <QTextEdit>
35 #include <QCursor>
36 #include <QVBoxLayout>
37 #include <QFormLayout>
38 #include "taggedfile.h"
39 #include "frame.h"
40 #include "trackdata.h"
41 #include "contexthelp.h"
42 #include "rendirconfig.h"
43 #include "dirrenamer.h"
44 #include "stringlisteditdialog.h"
45
46 /**
47 * Constructor.
48 *
49 * @param parent parent widget
50 * @param dirRenamer directory renamer
51 */
RenDirDialog(QWidget * parent,DirRenamer * dirRenamer)52 RenDirDialog::RenDirDialog(QWidget* parent, DirRenamer* dirRenamer)
53 : QWizard(parent), m_taggedFile(nullptr), m_dirRenamer(dirRenamer)
54 {
55 setObjectName(QLatin1String("RenDirDialog"));
56 setModal(true);
57 setWindowTitle(tr("Rename Folder"));
58 setSizeGripEnabled(true);
59
60 auto mainPage = new QWizardPage;
61
62 auto mainLayout = new QVBoxLayout(mainPage);
63 setupMainPage(mainPage, mainLayout);
64 mainPage->setTitle(tr("Format"));
65 addPage(mainPage);
66
67 auto previewPage = new QWizardPage;
68 setupPreviewPage(previewPage);
69 previewPage->setTitle(tr("Preview"));
70 addPage(previewPage);
71
72 setOptions(HaveHelpButton | HaveCustomButton1);
73 setButtonText(CustomButton1, tr("&Save Settings"));
74 connect(this, &QWizard::helpRequested, this, &RenDirDialog::showHelp);
75 connect(this, &QWizard::customButtonClicked, this, &RenDirDialog::saveConfig);
76 connect(this, &QWizard::currentIdChanged, this, &RenDirDialog::pageChanged);
77 }
78
79 /**
80 * Set up the main wizard page.
81 *
82 * @param page widget
83 * @param vlayout layout
84 */
setupMainPage(QWidget * page,QVBoxLayout * vlayout)85 void RenDirDialog::setupMainPage(QWidget* page, QVBoxLayout* vlayout)
86 {
87 if (!page || !vlayout) {
88 return;
89 }
90
91 auto actionLayout = new QFormLayout;
92 actionLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
93 m_actionComboBox = new QComboBox(page);
94 m_tagversionComboBox = new QComboBox(page);
95 m_actionComboBox->insertItem(ActionRename, tr("Rename Folder"));
96 m_actionComboBox->insertItem(ActionCreate, tr("Create Folder"));
97 actionLayout->addRow(tr("&Action:"), m_actionComboBox);
98 connect(m_actionComboBox, static_cast<void (QComboBox::*)(int)>(
99 &QComboBox::activated), this, &RenDirDialog::slotUpdateNewDirname);
100 const QList<QPair<Frame::TagVersion, QString> > tagVersions =
101 Frame::availableTagVersions();
102 for (auto it = tagVersions.constBegin(); it != tagVersions.constEnd(); ++it) {
103 m_tagversionComboBox->addItem(it->second, it->first);
104 }
105 actionLayout->addRow(tr("&Source:"), m_tagversionComboBox);
106 connect(m_tagversionComboBox, static_cast<void (QComboBox::*)(int)>(
107 &QComboBox::activated), this, &RenDirDialog::slotUpdateNewDirname);
108
109 auto formatLayout = new QHBoxLayout;
110 m_formatComboBox = new QComboBox(page);
111 m_formatComboBox->setEditable(true);
112 const RenDirConfig& renDirCfg = RenDirConfig::instance();
113 m_formats = renDirCfg.dirFormats();
114 m_format = renDirCfg.dirFormat();
115 setFormats();
116 formatLayout->addWidget(m_formatComboBox, 1);
117 auto editFormatsButton = new QPushButton(tr("&Edit..."));
118 connect(editFormatsButton, &QPushButton::clicked,
119 this, &RenDirDialog::editFormats);
120 formatLayout->addWidget(editFormatsButton);
121 auto formatLabel = new QLabel(tr("&Format:"));
122 formatLabel->setBuddy(m_formatComboBox);
123 actionLayout->addRow(formatLabel, formatLayout);
124 m_tagversionComboBox->setCurrentIndex(
125 m_tagversionComboBox->findData(renDirCfg.renDirSource()));
126 connect(m_formatComboBox, static_cast<void (QComboBox::*)(int)>(
127 &QComboBox::activated), this, &RenDirDialog::slotUpdateNewDirname);
128 connect(m_formatComboBox, &QComboBox::editTextChanged,
129 this, &RenDirDialog::slotUpdateNewDirname);
130
131 m_currentDirLabel = new QLabel(page);
132 m_newDirLabel = new QLabel(page);
133 actionLayout->addRow(tr("From:"), m_currentDirLabel);
134 actionLayout->addRow(tr("To:"), m_newDirLabel);
135
136 vlayout->addLayout(actionLayout);
137
138 QByteArray geometry = renDirCfg.windowGeometry();
139 if (!geometry.isEmpty()) {
140 restoreGeometry(geometry);
141 }
142 }
143
144 /**
145 * Set up the preview wizard page.
146 *
147 * @param page widget
148 */
setupPreviewPage(QWidget * page)149 void RenDirDialog::setupPreviewPage(QWidget* page)
150 {
151 auto vlayout = new QVBoxLayout(page);
152 m_edit = new QTextEdit(page);
153 m_edit->setReadOnly(true);
154 m_edit->setAcceptRichText(false);
155 vlayout->addWidget(m_edit);
156 }
157
158 /**
159 * Start dialog.
160 *
161 * @param taggedFile file to use for rename preview
162 * @param dirName if taggedFile is 0, the directory can be set here
163 */
startDialog(TaggedFile * taggedFile,const QString & dirName)164 void RenDirDialog::startDialog(TaggedFile* taggedFile, const QString& dirName)
165 {
166 m_taggedFile = taggedFile;
167 if (m_taggedFile) {
168 slotUpdateNewDirname();
169 } else {
170 m_currentDirLabel->setText(dirName);
171 m_newDirLabel->clear();
172 }
173 restart();
174 }
175
176 /**
177 * Set new directory name.
178 *
179 * @param dir new directory name
180 */
setNewDirname(const QString & dir)181 void RenDirDialog::setNewDirname(const QString& dir)
182 {
183 m_newDirLabel->setText(dir);
184 }
185
186 /**
187 * Get new directory name.
188 *
189 * @return new directory name.
190 */
getNewDirname() const191 QString RenDirDialog::getNewDirname() const
192 {
193 return m_newDirLabel->text();
194 }
195
196 /**
197 * Set configuration from dialog in directory renamer.
198 */
setDirRenamerConfiguration()199 void RenDirDialog::setDirRenamerConfiguration() {
200 m_dirRenamer->setTagVersion(Frame::tagVersionCast(
201 m_tagversionComboBox->itemData(m_tagversionComboBox->currentIndex()).toInt()));
202 m_dirRenamer->setAction(m_actionComboBox->currentIndex() == ActionCreate);
203 m_format = m_formatComboBox->currentText();
204 m_dirRenamer->setFormat(m_format);
205 }
206
207 /**
208 * Set new directory name according to current settings.
209 */
slotUpdateNewDirname()210 void RenDirDialog::slotUpdateNewDirname()
211 {
212 if (m_taggedFile) {
213 setDirRenamerConfiguration();
214 QString currentDirname;
215 QString newDirname(m_dirRenamer->generateNewDirname(m_taggedFile,
216 ¤tDirname));
217 m_currentDirLabel->setText(currentDirname);
218 setNewDirname(newDirname);
219 }
220 }
221
222 /**
223 * Save the local settings to the configuration.
224 */
saveConfig()225 void RenDirDialog::saveConfig()
226 {
227 RenDirConfig& renDirCfg = RenDirConfig::instance();
228 m_format = m_formatComboBox->currentText();
229 setFormats();
230 renDirCfg.setDirFormats(m_formats);
231 renDirCfg.setDirFormat(m_format);
232 renDirCfg.setRenDirSource(Frame::tagVersionCast(
233 m_tagversionComboBox->itemData(m_tagversionComboBox->currentIndex()).toInt()));
234 QByteArray geometry = saveGeometry();
235 renDirCfg.setWindowGeometry(geometry);
236 restoreGeometry(geometry); // Keep geometry when dialog is reopened
237 }
238
239 /**
240 * Show help.
241 */
showHelp()242 void RenDirDialog::showHelp()
243 {
244 ContextHelp::displayHelp(QLatin1String("rename-directory"));
245 }
246
247 /**
248 * Request action scheduling and then accept dialog.
249 */
requestActionSchedulingAndAccept()250 void RenDirDialog::requestActionSchedulingAndAccept()
251 {
252 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
253 setDirRenamerConfiguration();
254 emit actionSchedulingRequested();
255 QApplication::restoreOverrideCursor();
256 accept();
257 }
258
259 /**
260 * Clear action preview.
261 */
clearPreview()262 void RenDirDialog::clearPreview()
263 {
264 if (m_edit) {
265 m_edit->clear();
266 m_edit->setLineWrapMode(QTextEdit::NoWrap);
267 }
268 }
269
270 /**
271 * Display action preview.
272 *
273 * @param actionStrs description of action
274 */
displayActionPreview(const QStringList & actionStrs)275 void RenDirDialog::displayActionPreview(const QStringList& actionStrs)
276 {
277 QString str = actionStrs.at(0);
278 #if QT_VERSION >= 0x050b00
279 int width = fontMetrics().horizontalAdvance(str) + 8;
280 #else
281 int width = fontMetrics().width(str) + 8;
282 #endif
283 #if QT_VERSION >= 0x050a00
284 if (m_edit->tabStopDistance() < width) {
285 m_edit->setTabStopDistance(width);
286 }
287 #else
288 if (m_edit->tabStopWidth() < width) {
289 m_edit->setTabStopWidth(width);
290 }
291 #endif
292 if (actionStrs.size() > 1) {
293 str += QLatin1Char('\t');
294 str += actionStrs.at(1);
295 }
296 if (actionStrs.size() > 2) {
297 str += QLatin1String("\n\t");
298 str += actionStrs.at(2);
299 }
300 m_edit->append(str);
301 }
302
303 /**
304 * Wizard page changed.
305 */
pageChanged()306 void RenDirDialog::pageChanged()
307 {
308 if (currentId() == 1) {
309 clearPreview();
310 setDirRenamerConfiguration();
311 emit actionSchedulingRequested();
312 }
313 }
314
315 /**
316 * Open dialog to edit formats.
317 */
editFormats()318 void RenDirDialog::editFormats()
319 {
320 setFormats();
321 StringListEditDialog dialog(m_formats, tr("Folder Name from Tag"), this);
322 if (dialog.exec() == QDialog::Accepted) {
323 m_formats = dialog.stringList();
324 setFormats();
325 }
326 }
327
328 /**
329 * Set items of format combo box from configuration.
330 */
setFormats()331 void RenDirDialog::setFormats()
332 {
333 int idx = m_formats.indexOf(m_format);
334 if (idx == -1) {
335 m_formats.append(m_format);
336 idx = m_formats.size() - 1;
337 }
338 m_formatComboBox->blockSignals(true);
339 if (!m_formats.isEmpty()) {
340 m_formatComboBox->clear();
341 m_formatComboBox->addItems(m_formats);
342 }
343 m_formatComboBox->setCurrentIndex(idx);
344 m_formatComboBox->blockSignals(false);
345 }
346
347 /**
348 * Called when the wizard is canceled.
349 */
reject()350 void RenDirDialog::reject()
351 {
352 m_dirRenamer->abort();
353 QWizard::reject();
354 }
355