[multimedia/kid3] /: Allow playlist file name formats to be edited

Urs Fleisch null at kde.org
Sat Jul 9 10:26:53 BST 2022


Git commit 4e31b66e3ebe3177156b2548a14f740e0bd29810 by Urs Fleisch.
Committed on 09/07/2022 at 08:56.
Pushed by ufleisch into branch 'master'.

Allow playlist file name formats to be edited

The playlist file name formats can be edited from the settings
"Files/Format/Playlist..." and can then be used in the "Format"
combobox of the "Create Playlist" dialog.

BUG 450402

M  +8    -0    doc/en/index.docbook
M  +42   -1    src/core/config/playlistconfig.cpp
M  +14   -0    src/core/config/playlistconfig.h
M  +36   -6    src/gui/dialogs/configdialogpages.cpp
M  +6    -1    src/gui/dialogs/configdialogpages.h
M  +2    -7    src/gui/dialogs/playlistdialog.cpp

https://invent.kde.org/multimedia/kid3/commit/4e31b66e3ebe3177156b2548a14f740e0bd29810

diff --git a/doc/en/index.docbook b/doc/en/index.docbook
index 6c94e9b0..ca874030 100644
--- a/doc/en/index.docbook
+++ b/doc/en/index.docbook
@@ -1612,6 +1612,9 @@ or use a <guibutton>Format</guibutton> with values from the tags, <abbrev>e.g.</
 "<userinput>%{artist} - %{album}</userinput>" to have the artist and album
 name in the playlist file name. The format codes are the same as for
 <link linkend="export">Export</link>.
+The list of available formats can be edited in the <guilabel>Format</guilabel>
+section of the <guilabel>Files</guilabel> tab in the
+<link linkend="configure-kid3">settings</link>.
 <guibutton>Create new empty playlist</guibutton> will make an empty playlist
 with the given name.
 The extension depends on the playlist format.
@@ -2458,6 +2461,11 @@ boxes (with arrows up and down), which can be found in the
 <link linkend="file">File</link> section of the main window.
 </para>
 <para>
+The <guibutton>Playlist</guibutton> button can be used to edit the file name
+formats available in the <link linkend="create-playlist">Create Playlist</link>
+dialog.
+</para>
+<para>
 <guilabel>Filename Format</guilabel> contains options for the format of the
 filenames. The same options as in <guilabel>Tag Format</guilabel> are available.
 </para>
diff --git a/src/core/config/playlistconfig.cpp b/src/core/config/playlistconfig.cpp
index 65bccce2..a83d8b3d 100644
--- a/src/core/config/playlistconfig.cpp
+++ b/src/core/config/playlistconfig.cpp
@@ -30,19 +30,34 @@
 
 int PlaylistConfig::s_index = -1;
 
+namespace {
+
+/** Default file name format list */
+const char* defaultFileNameFormats[] = {
+  "%{artist} - %{album}",
+ R"(%{artist} - %{"["year"] "}%{album})",
+  "%{album}",
+  "playlist_%{artist}_-_%{album}",
+  "playlist",
+  nullptr
+};
+
+}
+
 /**
  * Constructor.
  */
 PlaylistConfig::PlaylistConfig()
   : StoredConfig<PlaylistConfig>(QLatin1String("Playlist")),
     m_location(PL_CurrentDirectory), m_format(PF_M3U),
-    m_fileNameFormat(QLatin1String("%{artist} - %{album}")),
+    m_fileNameFormat(QLatin1String(defaultFileNameFormats[0])),
     m_sortTagField(QLatin1String("%{track.3}")),
     m_infoFormat(QLatin1String("%{artist} - %{title}")),
     m_useFileNameFormat(false),
     m_onlySelectedFiles(false),
     m_useSortTagField(false), m_useFullPath(false), m_writeInfo(false)
 {
+  initFormatListsIfEmpty();
 }
 
 /**
@@ -54,6 +69,7 @@ PlaylistConfig::PlaylistConfig(const PlaylistConfig& other)
     m_location(other.m_location),
     m_format(other.m_format),
     m_fileNameFormat(other.m_fileNameFormat),
+    m_fileNameFormatItems(other.m_fileNameFormatItems),
     m_sortTagField(other.m_sortTagField),
     m_infoFormat(other.m_infoFormat),
     m_useFileNameFormat(other.m_useFileNameFormat),
@@ -75,6 +91,7 @@ PlaylistConfig& PlaylistConfig::operator=(const PlaylistConfig& other)
     m_location = other.m_location;
     m_format = other.m_format;
     m_fileNameFormat = other.m_fileNameFormat;
+    m_fileNameFormatItems = other.m_fileNameFormatItems;
     m_sortTagField = other.m_sortTagField;
     m_infoFormat = other.m_infoFormat;
     m_useFileNameFormat = other.m_useFileNameFormat;
@@ -107,6 +124,7 @@ void PlaylistConfig::writeToConfig(ISettings* config) const
   config->setValue(QLatin1String("Format"),
                    QVariant(static_cast<int>(m_format)));
   config->setValue(QLatin1String("FileNameFormat"), QVariant(m_fileNameFormat));
+  config->setValue(QLatin1String("FileNameFormatItems"), QVariant(m_fileNameFormatItems));
   config->setValue(QLatin1String("SortTagField"), QVariant(m_sortTagField));
   config->setValue(QLatin1String("InfoFormat"), QVariant(m_infoFormat));
   config->endGroup();
@@ -139,6 +157,8 @@ void PlaylistConfig::readFromConfig(ISettings* config)
     static_cast<int>(m_format)).toInt());
   m_fileNameFormat = config->value(QLatin1String("FileNameFormat"),
                                    m_fileNameFormat).toString();
+  m_fileNameFormatItems = config->value(QLatin1String("FileNameFormatItems"),
+                                        m_fileNameFormatItems).toStringList();
   m_sortTagField = config->value(QLatin1String("SortTagField"),
                                  m_sortTagField).toString();
   m_infoFormat = config->value(QLatin1String("InfoFormat"),
@@ -148,8 +168,20 @@ void PlaylistConfig::readFromConfig(ISettings* config)
   m_windowGeometry = config->value(QLatin1String("WindowGeometry"),
                                    m_windowGeometry).toByteArray();
   config->endGroup();
+
+  initFormatListsIfEmpty();
+}
+
+void PlaylistConfig::initFormatListsIfEmpty()
+{
+  if (m_fileNameFormatItems.size() <= 1) {
+    for (const char** sl = defaultFileNameFormats; *sl != nullptr; ++sl) {
+      m_fileNameFormatItems += QString::fromLatin1(*sl);
+    }
+  }
 }
 
+
 void PlaylistConfig::setLocation(PlaylistLocation location)
 {
   if (m_location != location) {
@@ -174,6 +206,15 @@ void PlaylistConfig::setFileNameFormat(const QString& fileNameFormat)
   }
 }
 
+void PlaylistConfig::setFileNameFormats(const QStringList& fileNameFormatItems)
+{
+  if (m_fileNameFormatItems != fileNameFormatItems) {
+    m_fileNameFormatItems = fileNameFormatItems;
+    m_fileNameFormatItems.removeDuplicates();
+    emit fileNameFormatsChanged(m_fileNameFormatItems);
+  }
+}
+
 void PlaylistConfig::setSortTagField(const QString& sortTagField)
 {
   if (m_sortTagField != sortTagField) {
diff --git a/src/core/config/playlistconfig.h b/src/core/config/playlistconfig.h
index d1c81b89..5eaf5fb2 100644
--- a/src/core/config/playlistconfig.h
+++ b/src/core/config/playlistconfig.h
@@ -143,6 +143,14 @@ public:
   /** Set playlist file name format. */
   void setFileNameFormat(const QString& fileNameFormat);
 
+  /** Get playlist file name formats. */
+  QStringList fileNameFormats() const {
+    return m_fileNameFormatItems;
+  }
+
+  /** Set playlist file name formats. */
+  void setFileNameFormats(const QStringList& fileNameFormatItems);
+
   /** Get tag field used for sorting. */
   QString sortTagField() const { return m_sortTagField; }
 
@@ -222,6 +230,9 @@ signals:
   /** Emitted when @a fileNameFormat changed. */
   void fileNameFormatChanged(const QString& fileNameFormat);
 
+  /** Emitted when @a fileNameFormats changed. */
+  void fileNameFormatsChanged(const QStringList& fileNameFormats);
+
   /** Emitted when @a sortTagField changed. */
   void sortTagFieldChanged(const QString& sortTagField);
 
@@ -249,6 +260,8 @@ signals:
 private:
   friend PlaylistConfig& StoredConfig<PlaylistConfig>::instance();
 
+  void initFormatListsIfEmpty();
+
   void setLocationInt(int location) {
     setLocation(static_cast<PlaylistLocation>(location));
   }
@@ -260,6 +273,7 @@ private:
   PlaylistLocation m_location;
   PlaylistFormat m_format;
   QString m_fileNameFormat;
+  QStringList m_fileNameFormatItems;
   QString m_sortTagField;
   QString m_infoFormat;
   QByteArray m_windowGeometry;
diff --git a/src/gui/dialogs/configdialogpages.cpp b/src/gui/dialogs/configdialogpages.cpp
index 9c18e0c9..d0339213 100644
--- a/src/gui/dialogs/configdialogpages.cpp
+++ b/src/gui/dialogs/configdialogpages.cpp
@@ -52,6 +52,7 @@
 #include "guiconfig.h"
 #include "networkconfig.h"
 #include "importconfig.h"
+#include "playlistconfig.h"
 #include "stringlistedit.h"
 #include "stringlisteditdialog.h"
 #include "configtable.h"
@@ -435,17 +436,24 @@ QWidget* ConfigDialogPages::createFilesPage()
   rightLayout->addWidget(fileListGroupBox);
 
   auto formatGroupBox = new QGroupBox(tr("Format"), filesPage);
-  auto formatLayout = new QHBoxLayout(formatGroupBox);
+  auto formatLayout = new QVBoxLayout(formatGroupBox);
+  auto filenameTagFormatLayout = new QHBoxLayout;
   auto editFormatsFromTagButton =
           new QPushButton(tr("Filename from tag") + QLatin1String("..."));
   connect(editFormatsFromTagButton, &QPushButton::clicked,
           this, &ConfigDialogPages::editFormatsFromTag);
-  formatLayout->addWidget(editFormatsFromTagButton);
+  filenameTagFormatLayout->addWidget(editFormatsFromTagButton);
   auto editFormatsToTagButton =
           new QPushButton(tr("Tag from filename") + QLatin1String("..."));
   connect(editFormatsToTagButton, &QPushButton::clicked,
           this, &ConfigDialogPages::editFormatsToTag);
-  formatLayout->addWidget(editFormatsToTagButton);
+  filenameTagFormatLayout->addWidget(editFormatsToTagButton);
+  formatLayout->addLayout(filenameTagFormatLayout);
+  auto editPlaylistFormatsButton =
+          new QPushButton(tr("Playlist") + QLatin1String("..."));
+  connect(editPlaylistFormatsButton, &QPushButton::clicked,
+          this, &ConfigDialogPages::editPlaylistFormats);
+  formatLayout->addWidget(editPlaylistFormatsButton);
   rightLayout->addWidget(formatGroupBox);
 
   rightLayout->addStretch();
@@ -492,6 +500,22 @@ void ConfigDialogPages::editFormatsToTag()
   }
 }
 
+/**
+ * Open dialog to edit playlist file name formats.
+ */
+void ConfigDialogPages::editPlaylistFormats()
+{
+  QWidget* parentWindow = nullptr;
+  if (auto button = qobject_cast<QPushButton*>(sender())) {
+    parentWindow = button->window();
+  }
+  StringListEditDialog dialog(
+        m_playlistFileNameFormats, tr("Playlist"), parentWindow);
+  if (dialog.exec() == QDialog::Accepted) {
+    m_playlistFileNameFormats = dialog.stringList();
+  }
+}
+
 /**
  * Create page with actions settings.
  * @return actions page.
@@ -624,8 +648,9 @@ void ConfigDialogPages::setDefaultConfig()
   networkCfg.setDefaultBrowser();
   ImportConfig importCfg;
   importCfg.setAvailablePlugins(ImportConfig::instance().availablePlugins());
+  PlaylistConfig playlistCfg;
   setConfigs(fnCfg, id3Cfg, tagCfg, fileCfg, userActionsCfg, guiCfg, networkCfg,
-            importCfg);
+            importCfg, playlistCfg);
 }
 
 /**
@@ -641,8 +666,9 @@ void ConfigDialogPages::setConfig()
   const GuiConfig& guiCfg = GuiConfig::instance();
   const NetworkConfig& networkCfg = NetworkConfig::instance();
   const ImportConfig& importCfg = ImportConfig::instance();
+  const PlaylistConfig& playlistCfg = PlaylistConfig::instance();
   setConfigs(fnCfg, id3Cfg, tagCfg, fileCfg, userActionsCfg, guiCfg, networkCfg,
-            importCfg);
+            importCfg, playlistCfg);
 }
 
 /**
@@ -652,7 +678,8 @@ void ConfigDialogPages::setConfigs(
     const FormatConfig& fnCfg, const FormatConfig& id3Cfg,
     const TagConfig& tagCfg, const FileConfig& fileCfg,
     const UserActionsConfig& userActionsCfg, const GuiConfig& guiCfg,
-    const NetworkConfig& networkCfg, const ImportConfig& importCfg)
+    const NetworkConfig& networkCfg, const ImportConfig& importCfg,
+    const PlaylistConfig& playlistCfg)
 {
   m_fnFormatBox->fromFormatConfig(fnCfg);
   m_tagFormatBox->fromFormatConfig(id3Cfg);
@@ -672,6 +699,7 @@ void ConfigDialogPages::setConfigs(
   m_fileTextEncodingComboBox->setCurrentIndex(fileCfg.textEncodingIndex());
   m_toFilenameFormats = fileCfg.toFilenameFormats();
   m_fromFilenameFormats = fileCfg.fromFilenameFormats();
+  m_playlistFileNameFormats = playlistCfg.fileNameFormats();
   m_onlyCustomGenresCheckBox->setChecked(tagCfg.onlyCustomGenres());
   m_genresEditModel->setStringList(tagCfg.customGenres());
   m_customFramesEditModel->setStringList(
@@ -774,6 +802,7 @@ void ConfigDialogPages::getConfig() const
   GuiConfig& guiCfg = GuiConfig::instance();
   NetworkConfig& networkCfg = NetworkConfig::instance();
   ImportConfig& importCfg = ImportConfig::instance();
+  PlaylistConfig& playlistCfg = PlaylistConfig::instance();
 
   m_fnFormatBox->toFormatConfig(fnCfg);
   m_tagFormatBox->toFormatConfig(id3Cfg);
@@ -792,6 +821,7 @@ void ConfigDialogPages::getConfig() const
   fileCfg.setTextEncodingIndex(m_fileTextEncodingComboBox->currentIndex());
   fileCfg.setToFilenameFormats(m_toFilenameFormats);
   fileCfg.setFromFilenameFormats(m_fromFilenameFormats);
+  playlistCfg.setFileNameFormats(m_playlistFileNameFormats);
   tagCfg.setOnlyCustomGenres(m_onlyCustomGenresCheckBox->isChecked());
   tagCfg.setCustomGenres(m_genresEditModel->stringList());
   tagCfg.setCustomFrames(TagConfig::customFrameNamesFromDisplayNames(
diff --git a/src/gui/dialogs/configdialogpages.h b/src/gui/dialogs/configdialogpages.h
index 0926bd5f..21549b52 100644
--- a/src/gui/dialogs/configdialogpages.h
+++ b/src/gui/dialogs/configdialogpages.h
@@ -49,6 +49,7 @@ class UserActionsConfig;
 class GuiConfig;
 class NetworkConfig;
 class ImportConfig;
+class PlaylistConfig;
 class IPlatformTools;
 
 /**
@@ -116,6 +117,7 @@ public slots:
 private slots:
   void editFormatsFromTag();
   void editFormatsToTag();
+  void editPlaylistFormats();
   void onCustomFramesEditModelChanged();
 
 private:
@@ -126,7 +128,8 @@ private:
       const FormatConfig& fnCfg, const FormatConfig& id3Cfg,
       const TagConfig& tagCfg, const FileConfig& fileCfg,
       const UserActionsConfig& userActionsCfg, const GuiConfig& guiCfg,
-      const NetworkConfig& networkCfg, const ImportConfig& importCfg);
+      const NetworkConfig& networkCfg, const ImportConfig& importCfg,
+      const PlaylistConfig& playlistCfg);
 
   void getQuickAccessFramesConfig(QList<int>& frameTypes,
                                   quint64& frameMask) const;
@@ -220,4 +223,6 @@ private:
   QStringList m_toFilenameFormats;
   /** Available formats for tag from filename */
   QStringList m_fromFilenameFormats;
+  /** Available playlist file name formats */
+  QStringList m_playlistFileNameFormats;
 };
diff --git a/src/gui/dialogs/playlistdialog.cpp b/src/gui/dialogs/playlistdialog.cpp
index 81e22dc2..88d8ff88 100644
--- a/src/gui/dialogs/playlistdialog.cpp
+++ b/src/gui/dialogs/playlistdialog.cpp
@@ -147,13 +147,6 @@ PlaylistDialog::PlaylistDialog(QWidget* parent)
   m_fileNameFormatButton->setText(tr("&Format:"));
   m_fileNameFormatComboBox->setEditable(true);
   m_fileNameFormatComboBox->setEnabled(false);
-  m_fileNameFormatComboBox->addItems({
-    QLatin1String("%{artist} - %{album}"),
-    QLatin1String(R"(%{artist} - %{"["year"] "}%{album})"),
-    QLatin1String("%{album}"),
-    QLatin1String("playlist_%{artist}_-_%{album}"),
-    QLatin1String("playlist")
-  });
   connect(m_fileNameFormatButton, &QAbstractButton::toggled,
           m_fileNameFormatComboBox, &QWidget::setEnabled);
   m_fileNameForEmptyButton->setText(tr("Create ne&w empty playlist:"));
@@ -252,6 +245,8 @@ void PlaylistDialog::readConfig()
   m_writeListButton->setChecked(!playlistCfg.writeInfo());
   m_locationComboBox->setCurrentIndex(playlistCfg.location());
   m_formatComboBox->setCurrentIndex(playlistCfg.format());
+  m_fileNameFormatComboBox->clear();
+  m_fileNameFormatComboBox->addItems(playlistCfg.fileNameFormats());
   m_fileNameFormatComboBox->setEditText(
     playlistCfg.fileNameFormat());
   m_sortTagFieldComboBox->setEditText(playlistCfg.sortTagField());



More information about the kde-doc-english mailing list