File indexing completed on 2025-02-23 04:34:18

0001 /**
0002  * \file playlistdialog.cpp
0003  * Create playlist dialog.
0004  *
0005  * \b Project: Kid3
0006  * \author Urs Fleisch
0007  * \date 13 Sep 2009
0008  *
0009  * Copyright (C) 2009-2024  Urs Fleisch
0010  *
0011  * This file is part of Kid3.
0012  *
0013  * Kid3 is free software; you can redistribute it and/or modify
0014  * it under the terms of the GNU General Public License as published by
0015  * the Free Software Foundation; either version 2 of the License, or
0016  * (at your option) any later version.
0017  *
0018  * Kid3 is distributed in the hope that it will be useful,
0019  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0020  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0021  * GNU General Public License for more details.
0022  *
0023  * You should have received a copy of the GNU General Public License
0024  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
0025  */
0026 
0027 #include "playlistdialog.h"
0028 #include <QLayout>
0029 #include <QPushButton>
0030 #include <QLabel>
0031 #include <QString>
0032 #include <QCheckBox>
0033 #include <QComboBox>
0034 #include <QLineEdit>
0035 #include <QRadioButton>
0036 #include <QButtonGroup>
0037 #include <QFrame>
0038 #include <QToolTip>
0039 #include <QVBoxLayout>
0040 #include <QHBoxLayout>
0041 #include <QGroupBox>
0042 #include "playlistconfig.h"
0043 #include "contexthelp.h"
0044 #include "trackdata.h"
0045 
0046 /**
0047  * Constructor.
0048  *
0049  * @param parent  parent widget
0050  */
0051 PlaylistDialog::PlaylistDialog(QWidget* parent)
0052   : QDialog(parent)
0053 {
0054   setObjectName(QLatin1String("PlaylistDialog"));
0055   setModal(true);
0056   setWindowTitle(tr("Create Playlist"));
0057   setSizeGripEnabled(true);
0058 
0059   auto vlayout = new QVBoxLayout(this);
0060   auto fnGroupBox = new QGroupBox(this);
0061   auto fnGroupBoxLayout = new QVBoxLayout(fnGroupBox);
0062   m_sameAsDirNameButton = new QRadioButton(this);
0063   fnGroupBoxLayout->addWidget(m_sameAsDirNameButton);
0064   auto fileNameFormatLayout = new QHBoxLayout;
0065   m_fileNameFormatButton = new QRadioButton(this);
0066   m_fileNameFormatComboBox = new QComboBox(this);
0067   m_fileNameFormatComboBox->setToolTip(TrackDataFormatReplacer::getToolTip());
0068   fileNameFormatLayout->addWidget(m_fileNameFormatButton);
0069   fileNameFormatLayout->addWidget(m_fileNameFormatComboBox);
0070   fnGroupBoxLayout->addLayout(fileNameFormatLayout);
0071 
0072   auto fileNameForEmptyLayout = new QHBoxLayout;
0073   m_fileNameForEmptyButton = new QRadioButton(this);
0074   m_fileNameForEmptyEdit = new QLineEdit(this);
0075   fileNameForEmptyLayout->addWidget(m_fileNameForEmptyButton);
0076   fileNameForEmptyLayout->addWidget(m_fileNameForEmptyEdit);
0077   fnGroupBoxLayout->addLayout(fileNameForEmptyLayout);
0078 
0079   auto locationLayout = new QHBoxLayout;
0080   auto locationLabel = new QLabel(this);
0081   m_locationComboBox = new QComboBox(this);
0082   locationLayout->addWidget(locationLabel);
0083   locationLayout->addWidget(m_locationComboBox);
0084   fnGroupBoxLayout->addLayout(locationLayout);
0085   vlayout->addWidget(fnGroupBox);
0086 
0087   auto pcGroupBox = new QGroupBox(this);
0088   auto pcGroupBoxLayout = new QVBoxLayout(pcGroupBox);
0089   auto formatLayout = new QHBoxLayout;
0090   auto formatLabel = new QLabel(this);
0091   m_formatComboBox = new QComboBox(this);
0092   formatLayout->addWidget(formatLabel);
0093   formatLayout->addWidget(m_formatComboBox);
0094   pcGroupBoxLayout->addLayout(formatLayout);
0095   m_onlySelectedFilesCheckBox = new QCheckBox(this);
0096   pcGroupBoxLayout->addWidget(m_onlySelectedFilesCheckBox);
0097 
0098   auto sortLine = new QFrame(pcGroupBox);
0099   sortLine->setFrameShape(QFrame::HLine);
0100   sortLine->setFrameShadow(QFrame::Sunken);
0101   pcGroupBoxLayout->addWidget(sortLine);
0102   auto sortButtonGroup = new QButtonGroup(pcGroupBox);
0103   m_sortFileNameButton = new QRadioButton(this);
0104   pcGroupBoxLayout->addWidget(m_sortFileNameButton);
0105   auto sortTagFieldLayout = new QHBoxLayout;
0106   m_sortTagFieldButton = new QRadioButton(this);
0107   m_sortTagFieldComboBox = new QComboBox(this);
0108   m_sortTagFieldComboBox->setToolTip(TrackDataFormatReplacer::getToolTip());
0109   sortTagFieldLayout->addWidget(m_sortTagFieldButton);
0110   sortTagFieldLayout->addWidget(m_sortTagFieldComboBox);
0111   pcGroupBoxLayout->addLayout(sortTagFieldLayout);
0112   sortButtonGroup->addButton(m_sortFileNameButton);
0113   sortButtonGroup->addButton(m_sortTagFieldButton);
0114 
0115   auto pathLine = new QFrame(pcGroupBox);
0116   pathLine->setFrameShape(QFrame::HLine);
0117   pathLine->setFrameShadow(QFrame::Sunken);
0118   pcGroupBoxLayout->addWidget(pathLine);
0119   auto pathButtonGroup = new QButtonGroup(pcGroupBox);
0120   m_relPathButton = new QRadioButton(this);
0121   pcGroupBoxLayout->addWidget(m_relPathButton);
0122   m_fullPathButton = new QRadioButton(this);
0123   pcGroupBoxLayout->addWidget(m_fullPathButton);
0124   pathButtonGroup->addButton(m_relPathButton);
0125   pathButtonGroup->addButton(m_fullPathButton);
0126 
0127   auto writeLine = new QFrame(pcGroupBox);
0128   writeLine->setFrameShape(QFrame::HLine);
0129   writeLine->setFrameShadow(QFrame::Sunken);
0130   pcGroupBoxLayout->addWidget(writeLine);
0131   auto writeButtonGroup = new QButtonGroup(pcGroupBox);
0132   m_writeListButton = new QRadioButton(this);
0133   pcGroupBoxLayout->addWidget(m_writeListButton);
0134   auto writeInfoLayout = new QHBoxLayout;
0135   m_writeInfoButton = new QRadioButton(this);
0136   m_writeInfoComboBox = new QComboBox(this);
0137   m_writeInfoComboBox->setToolTip(TrackDataFormatReplacer::getToolTip());
0138   writeInfoLayout->addWidget(m_writeInfoButton);
0139   writeInfoLayout->addWidget(m_writeInfoComboBox);
0140   pcGroupBoxLayout->addLayout(writeInfoLayout);
0141   writeButtonGroup->addButton(m_writeListButton);
0142   writeButtonGroup->addButton(m_writeInfoButton);
0143   vlayout->addWidget(pcGroupBox);
0144   fnGroupBox->setTitle(tr("Playlist File Name"));
0145   m_sameAsDirNameButton->setText(tr("Same as &folder name"));
0146   m_sameAsDirNameButton->setChecked(true);
0147   m_fileNameFormatButton->setText(tr("&Format:"));
0148   m_fileNameFormatComboBox->setEditable(true);
0149   m_fileNameFormatComboBox->setEnabled(false);
0150   connect(m_fileNameFormatButton, &QAbstractButton::toggled,
0151           m_fileNameFormatComboBox, &QWidget::setEnabled);
0152   m_fileNameForEmptyButton->setText(tr("Create ne&w empty playlist:"));
0153   m_fileNameForEmptyEdit->setText(tr("New"));
0154   m_fileNameForEmptyEdit->setEnabled(false);
0155   // Position line edit aligned with combo box.
0156   m_fileNameForEmptyEdit->setSizePolicy(m_fileNameFormatComboBox->sizePolicy());
0157   connect(m_fileNameForEmptyButton, &QAbstractButton::toggled,
0158           m_fileNameForEmptyEdit, &QWidget::setEnabled);
0159   locationLabel->setText(tr("Cr&eate in:"));
0160   locationLabel->setBuddy(m_locationComboBox);
0161   m_locationComboBox->addItems({
0162     tr("Current folder"),
0163     tr("Every folder"),
0164     tr("Top-level folder")
0165   });
0166   pcGroupBox->setTitle(tr("Playlist Content"));
0167   formatLabel->setText(tr("For&mat:"));
0168   formatLabel->setBuddy(m_formatComboBox);
0169   m_formatComboBox->addItems(
0170     {QLatin1String("M3U"), QLatin1String("PLS"), QLatin1String("XSPF")});
0171   m_onlySelectedFilesCheckBox->setText(tr("Incl&ude only the selected files"));
0172   m_sortFileNameButton->setText(tr("Sort by file &name"));
0173   m_sortFileNameButton->setChecked(true);
0174   m_sortTagFieldButton->setText(tr("Sort by &tag field"));
0175   m_sortTagFieldComboBox->setEditable(true);
0176   m_sortTagFieldComboBox->setEnabled(false);
0177   QStringList lst;
0178   lst.reserve(Frame::FT_LastFrame - Frame::FT_FirstFrame + 1);
0179   for (int type = Frame::FT_FirstFrame; type <= Frame::FT_LastFrame; ++type) {
0180     QString frameName =
0181         Frame::ExtendedType(static_cast<Frame::Type>(type), QLatin1String(""))
0182         .getName().toLower();
0183     if (frameName == QLatin1String("track number")) frameName = QLatin1String("track.3");
0184     if (!frameName.isEmpty()) {
0185       lst.append(QLatin1String("%{") + frameName + QLatin1String("}"));
0186     }
0187   }
0188   m_sortTagFieldComboBox->addItems(lst);
0189   connect(m_sortTagFieldButton, &QAbstractButton::toggled,
0190           m_sortTagFieldComboBox, &QWidget::setEnabled);
0191   m_relPathButton->setText(tr("Use &relative path for files in playlist"));
0192   m_relPathButton->setChecked(true);
0193   m_fullPathButton->setText(tr("Use full p&ath for files in playlist"));
0194   m_writeListButton->setText(tr("Write only &list of files"));
0195   m_writeListButton->setChecked(true);
0196   m_writeInfoButton->setText(tr("Write &info using"));
0197   m_writeInfoComboBox->setEditable(true);
0198   m_writeInfoComboBox->setEnabled(false);
0199   m_writeInfoComboBox->addItems({
0200     QLatin1String("%{artist} - %{title}"), QLatin1String("%{title}"),
0201     QLatin1String("%{track.1}/%{tracks} - %{artist} - %{album} - %{title}")
0202   });
0203   connect(m_writeInfoButton, &QAbstractButton::toggled,
0204           m_writeInfoComboBox, &QWidget::setEnabled);
0205 
0206   auto hlayout = new QHBoxLayout;
0207   auto helpButton = new QPushButton(tr("&Help"), this);
0208   helpButton->setAutoDefault(false);
0209   hlayout->addWidget(helpButton);
0210   connect(helpButton, &QAbstractButton::clicked, this, &PlaylistDialog::showHelp);
0211   auto saveButton = new QPushButton(tr("&Save Settings"), this);
0212   saveButton->setAutoDefault(false);
0213   hlayout->addWidget(saveButton);
0214   connect(saveButton, &QAbstractButton::clicked, this, &PlaylistDialog::saveConfig);
0215   auto hspacer = new QSpacerItem(16, 0, QSizePolicy::Expanding,
0216                                          QSizePolicy::Minimum);
0217   hlayout->addItem(hspacer);
0218 
0219   auto okButton = new QPushButton(tr("&OK"), this);
0220   hlayout->addWidget(okButton);
0221   connect(okButton, &QAbstractButton::clicked, this, &QDialog::accept);
0222   auto cancelButton = new QPushButton(tr("&Cancel"), this);
0223   hlayout->addWidget(cancelButton);
0224   connect(cancelButton, &QAbstractButton::clicked, this, &QDialog::reject);
0225   vlayout->addLayout(hlayout);
0226 }
0227 
0228 /**
0229  * Read the local settings from the configuration.
0230  */
0231 void PlaylistDialog::readConfig()
0232 {
0233   const PlaylistConfig& playlistCfg = PlaylistConfig::instance();
0234   m_fileNameFormatButton->setChecked(
0235     playlistCfg.useFileNameFormat());
0236   m_sameAsDirNameButton->setChecked(
0237     !playlistCfg.useFileNameFormat());
0238   m_onlySelectedFilesCheckBox->setChecked(
0239     playlistCfg.onlySelectedFiles());
0240   m_sortTagFieldButton->setChecked(playlistCfg.useSortTagField());
0241   m_sortFileNameButton->setChecked(!playlistCfg.useSortTagField());
0242   m_fullPathButton->setChecked(playlistCfg.useFullPath());
0243   m_relPathButton->setChecked(!playlistCfg.useFullPath());
0244   m_writeInfoButton->setChecked(playlistCfg.writeInfo());
0245   m_writeListButton->setChecked(!playlistCfg.writeInfo());
0246   m_locationComboBox->setCurrentIndex(playlistCfg.location());
0247   m_formatComboBox->setCurrentIndex(playlistCfg.format());
0248   m_fileNameFormatComboBox->clear();
0249   m_fileNameFormatComboBox->addItems(playlistCfg.fileNameFormats());
0250   m_fileNameFormatComboBox->setEditText(
0251     playlistCfg.fileNameFormat());
0252   m_sortTagFieldComboBox->setEditText(playlistCfg.sortTagField());
0253   m_writeInfoComboBox->setEditText(playlistCfg.infoFormat());
0254 
0255   if (QByteArray geometry = playlistCfg.windowGeometry(); !geometry.isEmpty()) {
0256     restoreGeometry(geometry);
0257   }
0258 }
0259 
0260 /**
0261  * Get the current dialog configuration.
0262  *
0263  * @param cfg the current configuration is returned here
0264  */
0265 void PlaylistDialog::getCurrentConfig(PlaylistConfig& cfg) const
0266 {
0267   cfg.setUseFileNameFormat(m_fileNameFormatButton->isChecked());
0268   cfg.setOnlySelectedFiles(m_onlySelectedFilesCheckBox->isChecked());
0269   cfg.setUseSortTagField(m_sortTagFieldButton->isChecked());
0270   cfg.setUseFullPath(m_fullPathButton->isChecked());
0271   cfg.setWriteInfo(m_writeInfoButton->isChecked());
0272   cfg.setLocation(static_cast<PlaylistConfig::PlaylistLocation>(
0273     m_locationComboBox->currentIndex()));
0274   cfg.setFormat(static_cast<PlaylistConfig::PlaylistFormat>(
0275     m_formatComboBox->currentIndex()));
0276   cfg.setFileNameFormat(m_fileNameFormatComboBox->currentText());
0277   cfg.setSortTagField(m_sortTagFieldComboBox->currentText());
0278   cfg.setInfoFormat(m_writeInfoComboBox->currentText());
0279   QByteArray geometry = saveGeometry();
0280   cfg.setWindowGeometry(geometry);
0281 }
0282 
0283 /**
0284  * Get the entered file name to create a new empty playlist.
0285  * @return file name if "Create new empty playlist" is selected, else empty.
0286  */
0287 QString PlaylistDialog::getFileNameForNewEmptyPlaylist() const
0288 {
0289   return m_fileNameForEmptyButton->isChecked()
0290       ? m_fileNameForEmptyEdit->text() : QString();
0291 }
0292 
0293 /**
0294  * Save the local settings to the configuration.
0295  */
0296 void PlaylistDialog::saveConfig() const
0297 {
0298   getCurrentConfig(PlaylistConfig::instance());
0299 }
0300 
0301 /**
0302  * Show help.
0303  */
0304 void PlaylistDialog::showHelp()
0305 {
0306   ContextHelp::displayHelp(QLatin1String("create-playlist"));
0307 }