1 /**
2 * \file playlistdialog.cpp
3 * Create playlist dialog.
4 *
5 * \b Project: Kid3
6 * \author Urs Fleisch
7 * \date 13 Sep 2009
8 *
9 * Copyright (C) 2009-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 "playlistdialog.h"
28 #include <QLayout>
29 #include <QPushButton>
30 #include <QLabel>
31 #include <QString>
32 #include <QCheckBox>
33 #include <QComboBox>
34 #include <QLineEdit>
35 #include <QRadioButton>
36 #include <QButtonGroup>
37 #include <QFrame>
38 #include <QToolTip>
39 #include <QVBoxLayout>
40 #include <QHBoxLayout>
41 #include <QGroupBox>
42 #include "playlistconfig.h"
43 #include "contexthelp.h"
44 #include "trackdata.h"
45
46 /**
47 * Constructor.
48 *
49 * @param parent parent widget
50 */
PlaylistDialog(QWidget * parent)51 PlaylistDialog::PlaylistDialog(QWidget* parent)
52 : QDialog(parent)
53 {
54 setObjectName(QLatin1String("PlaylistDialog"));
55 setModal(true);
56 setWindowTitle(tr("Create Playlist"));
57 setSizeGripEnabled(true);
58
59 auto vlayout = new QVBoxLayout(this);
60 auto fnGroupBox = new QGroupBox(this);
61 auto fnGroupBoxLayout = new QVBoxLayout(fnGroupBox);
62 m_sameAsDirNameButton = new QRadioButton(this);
63 fnGroupBoxLayout->addWidget(m_sameAsDirNameButton);
64 auto fileNameFormatLayout = new QHBoxLayout;
65 m_fileNameFormatButton = new QRadioButton(this);
66 m_fileNameFormatComboBox = new QComboBox(this);
67 m_fileNameFormatComboBox->setToolTip(TrackDataFormatReplacer::getToolTip());
68 fileNameFormatLayout->addWidget(m_fileNameFormatButton);
69 fileNameFormatLayout->addWidget(m_fileNameFormatComboBox);
70 fnGroupBoxLayout->addLayout(fileNameFormatLayout);
71
72 auto fileNameForEmptyLayout = new QHBoxLayout;
73 m_fileNameForEmptyButton = new QRadioButton(this);
74 m_fileNameForEmptyEdit = new QLineEdit(this);
75 fileNameForEmptyLayout->addWidget(m_fileNameForEmptyButton);
76 fileNameForEmptyLayout->addWidget(m_fileNameForEmptyEdit);
77 fnGroupBoxLayout->addLayout(fileNameForEmptyLayout);
78
79 auto locationLayout = new QHBoxLayout;
80 QLabel* locationLabel = new QLabel(this);
81 m_locationComboBox = new QComboBox(this);
82 locationLayout->addWidget(locationLabel);
83 locationLayout->addWidget(m_locationComboBox);
84 fnGroupBoxLayout->addLayout(locationLayout);
85 vlayout->addWidget(fnGroupBox);
86
87 auto pcGroupBox = new QGroupBox(this);
88 auto pcGroupBoxLayout = new QVBoxLayout(pcGroupBox);
89 auto formatLayout = new QHBoxLayout;
90 QLabel* formatLabel = new QLabel(this);
91 m_formatComboBox = new QComboBox(this);
92 formatLayout->addWidget(formatLabel);
93 formatLayout->addWidget(m_formatComboBox);
94 pcGroupBoxLayout->addLayout(formatLayout);
95 m_onlySelectedFilesCheckBox = new QCheckBox(this);
96 pcGroupBoxLayout->addWidget(m_onlySelectedFilesCheckBox);
97
98 QFrame* sortLine = new QFrame(pcGroupBox);
99 sortLine->setFrameShape(QFrame::HLine);
100 sortLine->setFrameShadow(QFrame::Sunken);
101 pcGroupBoxLayout->addWidget(sortLine);
102 auto sortButtonGroup = new QButtonGroup(pcGroupBox);
103 m_sortFileNameButton = new QRadioButton(this);
104 pcGroupBoxLayout->addWidget(m_sortFileNameButton);
105 auto sortTagFieldLayout = new QHBoxLayout;
106 m_sortTagFieldButton = new QRadioButton(this);
107 m_sortTagFieldComboBox = new QComboBox(this);
108 m_sortTagFieldComboBox->setToolTip(TrackDataFormatReplacer::getToolTip());
109 sortTagFieldLayout->addWidget(m_sortTagFieldButton);
110 sortTagFieldLayout->addWidget(m_sortTagFieldComboBox);
111 pcGroupBoxLayout->addLayout(sortTagFieldLayout);
112 sortButtonGroup->addButton(m_sortFileNameButton);
113 sortButtonGroup->addButton(m_sortTagFieldButton);
114
115 QFrame* pathLine = new QFrame(pcGroupBox);
116 pathLine->setFrameShape(QFrame::HLine);
117 pathLine->setFrameShadow(QFrame::Sunken);
118 pcGroupBoxLayout->addWidget(pathLine);
119 auto pathButtonGroup = new QButtonGroup(pcGroupBox);
120 m_relPathButton = new QRadioButton(this);
121 pcGroupBoxLayout->addWidget(m_relPathButton);
122 m_fullPathButton = new QRadioButton(this);
123 pcGroupBoxLayout->addWidget(m_fullPathButton);
124 pathButtonGroup->addButton(m_relPathButton);
125 pathButtonGroup->addButton(m_fullPathButton);
126
127 QFrame* writeLine = new QFrame(pcGroupBox);
128 writeLine->setFrameShape(QFrame::HLine);
129 writeLine->setFrameShadow(QFrame::Sunken);
130 pcGroupBoxLayout->addWidget(writeLine);
131 auto writeButtonGroup = new QButtonGroup(pcGroupBox);
132 m_writeListButton = new QRadioButton(this);
133 pcGroupBoxLayout->addWidget(m_writeListButton);
134 auto writeInfoLayout = new QHBoxLayout;
135 m_writeInfoButton = new QRadioButton(this);
136 m_writeInfoComboBox = new QComboBox(this);
137 m_writeInfoComboBox->setToolTip(TrackDataFormatReplacer::getToolTip());
138 writeInfoLayout->addWidget(m_writeInfoButton);
139 writeInfoLayout->addWidget(m_writeInfoComboBox);
140 pcGroupBoxLayout->addLayout(writeInfoLayout);
141 writeButtonGroup->addButton(m_writeListButton);
142 writeButtonGroup->addButton(m_writeInfoButton);
143 vlayout->addWidget(pcGroupBox);
144 fnGroupBox->setTitle(tr("Playlist File Name"));
145 m_sameAsDirNameButton->setText(tr("Same as &folder name"));
146 m_sameAsDirNameButton->setChecked(true);
147 m_fileNameFormatButton->setText(tr("&Format:"));
148 m_fileNameFormatComboBox->setEditable(true);
149 m_fileNameFormatComboBox->setEnabled(false);
150 m_fileNameFormatComboBox->addItems({
151 QLatin1String("%{artist} - %{album}"),
152 QLatin1String(R"(%{artist} - %{"["year"] "}%{album})"),
153 QLatin1String("%{album}"),
154 QLatin1String("playlist_%{artist}_-_%{album}"),
155 QLatin1String("playlist")
156 });
157 connect(m_fileNameFormatButton, &QAbstractButton::toggled,
158 m_fileNameFormatComboBox, &QWidget::setEnabled);
159 m_fileNameForEmptyButton->setText(tr("Create ne&w empty playlist:"));
160 m_fileNameForEmptyEdit->setText(tr("New"));
161 m_fileNameForEmptyEdit->setEnabled(false);
162 // Position line edit aligned with combo box.
163 m_fileNameForEmptyEdit->setSizePolicy(m_fileNameFormatComboBox->sizePolicy());
164 connect(m_fileNameForEmptyButton, &QAbstractButton::toggled,
165 m_fileNameForEmptyEdit, &QWidget::setEnabled);
166 locationLabel->setText(tr("Cr&eate in:"));
167 locationLabel->setBuddy(m_locationComboBox);
168 m_locationComboBox->addItems({
169 tr("Current folder"),
170 tr("Every folder"),
171 tr("Top-level folder")
172 });
173 pcGroupBox->setTitle(tr("Playlist Content"));
174 formatLabel->setText(tr("For&mat:"));
175 formatLabel->setBuddy(m_formatComboBox);
176 m_formatComboBox->addItems(
177 {QLatin1String("M3U"), QLatin1String("PLS"), QLatin1String("XSPF")});
178 m_onlySelectedFilesCheckBox->setText(tr("Incl&ude only the selected files"));
179 m_sortFileNameButton->setText(tr("Sort by file &name"));
180 m_sortFileNameButton->setChecked(true);
181 m_sortTagFieldButton->setText(tr("Sort by &tag field"));
182 m_sortTagFieldComboBox->setEditable(true);
183 m_sortTagFieldComboBox->setEnabled(false);
184 QStringList lst;
185 lst.reserve(Frame::FT_LastFrame - Frame::FT_FirstFrame + 1);
186 for (int type = Frame::FT_FirstFrame; type <= Frame::FT_LastFrame; ++type) {
187 QString frameName =
188 Frame::ExtendedType(static_cast<Frame::Type>(type), QLatin1String(""))
189 .getName().toLower();
190 if (frameName == QLatin1String("track number")) frameName = QLatin1String("track.3");
191 lst.append(QLatin1String("%{") + frameName + QLatin1String("}"));
192 }
193 m_sortTagFieldComboBox->addItems(lst);
194 connect(m_sortTagFieldButton, &QAbstractButton::toggled,
195 m_sortTagFieldComboBox, &QWidget::setEnabled);
196 m_relPathButton->setText(tr("Use &relative path for files in playlist"));
197 m_relPathButton->setChecked(true);
198 m_fullPathButton->setText(tr("Use full p&ath for files in playlist"));
199 m_writeListButton->setText(tr("Write only &list of files"));
200 m_writeListButton->setChecked(true);
201 m_writeInfoButton->setText(tr("Write &info using"));
202 m_writeInfoComboBox->setEditable(true);
203 m_writeInfoComboBox->setEnabled(false);
204 m_writeInfoComboBox->addItems({
205 QLatin1String("%{artist} - %{title}"), QLatin1String("%{title}"),
206 QLatin1String("%{track.1}/%{tracks} - %{artist} - %{album} - %{title}")
207 });
208 connect(m_writeInfoButton, &QAbstractButton::toggled,
209 m_writeInfoComboBox, &QWidget::setEnabled);
210
211 auto hlayout = new QHBoxLayout;
212 QPushButton* helpButton = new QPushButton(tr("&Help"), this);
213 helpButton->setAutoDefault(false);
214 hlayout->addWidget(helpButton);
215 connect(helpButton, &QAbstractButton::clicked, this, &PlaylistDialog::showHelp);
216 QPushButton* saveButton = new QPushButton(tr("&Save Settings"), this);
217 saveButton->setAutoDefault(false);
218 hlayout->addWidget(saveButton);
219 connect(saveButton, &QAbstractButton::clicked, this, &PlaylistDialog::saveConfig);
220 auto hspacer = new QSpacerItem(16, 0, QSizePolicy::Expanding,
221 QSizePolicy::Minimum);
222 hlayout->addItem(hspacer);
223
224 QPushButton* okButton = new QPushButton(tr("&OK"), this);
225 hlayout->addWidget(okButton);
226 connect(okButton, &QAbstractButton::clicked, this, &QDialog::accept);
227 QPushButton* cancelButton = new QPushButton(tr("&Cancel"), this);
228 hlayout->addWidget(cancelButton);
229 connect(cancelButton, &QAbstractButton::clicked, this, &QDialog::reject);
230 vlayout->addLayout(hlayout);
231 }
232
233 /**
234 * Read the local settings from the configuration.
235 */
readConfig()236 void PlaylistDialog::readConfig()
237 {
238 const PlaylistConfig& playlistCfg = PlaylistConfig::instance();
239 m_fileNameFormatButton->setChecked(
240 playlistCfg.useFileNameFormat());
241 m_sameAsDirNameButton->setChecked(
242 !playlistCfg.useFileNameFormat());
243 m_onlySelectedFilesCheckBox->setChecked(
244 playlistCfg.onlySelectedFiles());
245 m_sortTagFieldButton->setChecked(playlistCfg.useSortTagField());
246 m_sortFileNameButton->setChecked(!playlistCfg.useSortTagField());
247 m_fullPathButton->setChecked(playlistCfg.useFullPath());
248 m_relPathButton->setChecked(!playlistCfg.useFullPath());
249 m_writeInfoButton->setChecked(playlistCfg.writeInfo());
250 m_writeListButton->setChecked(!playlistCfg.writeInfo());
251 m_locationComboBox->setCurrentIndex(playlistCfg.location());
252 m_formatComboBox->setCurrentIndex(playlistCfg.format());
253 m_fileNameFormatComboBox->setEditText(
254 playlistCfg.fileNameFormat());
255 m_sortTagFieldComboBox->setEditText(playlistCfg.sortTagField());
256 m_writeInfoComboBox->setEditText(playlistCfg.infoFormat());
257
258 QByteArray geometry = playlistCfg.windowGeometry();
259 if (!geometry.isEmpty()) {
260 restoreGeometry(geometry);
261 }
262 }
263
264 /**
265 * Get the current dialog configuration.
266 *
267 * @param cfg the current configuration is returned here
268 */
getCurrentConfig(PlaylistConfig & cfg) const269 void PlaylistDialog::getCurrentConfig(PlaylistConfig& cfg) const
270 {
271 cfg.setUseFileNameFormat(m_fileNameFormatButton->isChecked());
272 cfg.setOnlySelectedFiles(m_onlySelectedFilesCheckBox->isChecked());
273 cfg.setUseSortTagField(m_sortTagFieldButton->isChecked());
274 cfg.setUseFullPath(m_fullPathButton->isChecked());
275 cfg.setWriteInfo(m_writeInfoButton->isChecked());
276 cfg.setLocation(static_cast<PlaylistConfig::PlaylistLocation>(
277 m_locationComboBox->currentIndex()));
278 cfg.setFormat(static_cast<PlaylistConfig::PlaylistFormat>(
279 m_formatComboBox->currentIndex()));
280 cfg.setFileNameFormat(m_fileNameFormatComboBox->currentText());
281 cfg.setSortTagField(m_sortTagFieldComboBox->currentText());
282 cfg.setInfoFormat(m_writeInfoComboBox->currentText());
283 QByteArray geometry = saveGeometry();
284 cfg.setWindowGeometry(geometry);
285 }
286
287 /**
288 * Get the entered file name to create a new empty playlist.
289 * @return file name if "Create new empty playlist" is selected, else empty.
290 */
getFileNameForNewEmptyPlaylist() const291 QString PlaylistDialog::getFileNameForNewEmptyPlaylist() const
292 {
293 return m_fileNameForEmptyButton->isChecked()
294 ? m_fileNameForEmptyEdit->text() : QString();
295 }
296
297 /**
298 * Save the local settings to the configuration.
299 */
saveConfig() const300 void PlaylistDialog::saveConfig() const
301 {
302 getCurrentConfig(PlaylistConfig::instance());
303 }
304
305 /**
306 * Show help.
307 */
showHelp()308 void PlaylistDialog::showHelp()
309 {
310 ContextHelp::displayHelp(QLatin1String("create-playlist"));
311 }
312