File indexing completed on 2024-05-19 04:55:58

0001 /**
0002  * \file useractionsconfig.cpp
0003  * User actions configuration.
0004  *
0005  * \b Project: Kid3
0006  * \author Urs Fleisch
0007  * \date 29 Jun 2013
0008  *
0009  * Copyright (C) 2013-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 "useractionsconfig.h"
0028 #include <QStringList>
0029 #include <cstdlib>
0030 #include "isettings.h"
0031 #include "config.h"
0032 
0033 int UserActionsConfig::s_index = -1;
0034 
0035 /**
0036  * Constructor.
0037  */
0038 UserActionsConfig::UserActionsConfig()
0039   : StoredConfig(QLatin1String("MenuCommands"))
0040 {
0041 }
0042 
0043 /**
0044  * Persist configuration.
0045  *
0046  * @param config configuration
0047  */
0048 void UserActionsConfig::writeToConfig(ISettings* config) const
0049 {
0050   config->beginGroup(m_group);
0051   int cmdNr = 1;
0052   for (auto it = m_contextMenuCommands.constBegin();
0053        it != m_contextMenuCommands.constEnd();
0054        ++it) {
0055     config->setValue(QString(QLatin1String("Command%1")).arg(cmdNr++),
0056                      QVariant(it->toStringList()));
0057   }
0058   // delete entries which are no longer used
0059   for (;;) {
0060     if (QStringList strList =
0061           config->value(QString(QLatin1String("Command%1")).arg(cmdNr),
0062                         QStringList()).toStringList();
0063         strList.empty()) {
0064       break;
0065     }
0066     config->remove(QString(QLatin1String("Command%1")).arg(cmdNr));
0067     ++cmdNr;
0068   }
0069   config->endGroup();
0070 }
0071 
0072 /**
0073  * Read persisted configuration.
0074  *
0075  * @param config configuration
0076  */
0077 void UserActionsConfig::readFromConfig(ISettings* config)
0078 {
0079   config->beginGroup(m_group);
0080   m_contextMenuCommands.clear();
0081   int cmdNr = 1;
0082   for (;;) {
0083     QStringList strList =
0084         config->value(QString(QLatin1String("Command%1")).arg(cmdNr),
0085                       QStringList()).toStringList();
0086     if (strList.empty()) {
0087       break;
0088     }
0089     if (strList.size() > 1 &&
0090         strList.at(1) == QLatin1String(
0091           "%{browser} http://images.google.com/images?q=%u{artist}%20%u{album}")) {
0092       strList[1] = QLatin1String(
0093         "%{browser} http://www.google.com/search?tbm=isch&q=%u{artist}%20%u{album}");
0094     }
0095     m_contextMenuCommands.push_back(UserActionsConfig::MenuCommand(strList));
0096     ++cmdNr;
0097   }
0098   config->endGroup();
0099 
0100   setDefaultUserActions(cmdNr != 1);
0101 }
0102 
0103 /**
0104  * Set default user actions.
0105  * @param upgradeOnly if true only upgrade configuration with new actions
0106  */
0107 void UserActionsConfig::setDefaultUserActions(bool upgradeOnly)
0108 {
0109   if (!upgradeOnly) {
0110     m_contextMenuCommands.clear();
0111     m_contextMenuCommands.push_back(
0112       UserActionsConfig::MenuCommand(QString(), QLatin1String("@separator")));
0113     m_contextMenuCommands.push_back(
0114       UserActionsConfig::MenuCommand(QLatin1String("Album Art"),
0115                                      QLatin1String("@beginmenu")));
0116   }
0117 #ifdef HAVE_QML
0118   if (!upgradeOnly || ConfigStore::getConfigVersion() < 2) {
0119     m_contextMenuCommands.push_back(
0120       UserActionsConfig::MenuCommand(
0121             QLatin1String("Resize Album Art"),
0122             QLatin1String("@qml %{qmlpath}/script/ResizeAlbumArt.qml"),
0123             false, true));
0124     m_contextMenuCommands.push_back(
0125       UserActionsConfig::MenuCommand(
0126             QLatin1String("Extract Album Art"),
0127             QLatin1String("@qml %{qmlpath}/script/ExtractAlbumArt.qml"),
0128             false, true));
0129     m_contextMenuCommands.push_back(
0130       UserActionsConfig::MenuCommand(
0131             QLatin1String("Embed Album Art"),
0132             QLatin1String("@qml %{qmlpath}/script/EmbedAlbumArt.qml"),
0133             false, true));
0134   }
0135 #endif
0136   if (!upgradeOnly) {
0137     m_contextMenuCommands.push_back(
0138       UserActionsConfig::MenuCommand(
0139             QLatin1String("Google Images"),
0140             QLatin1String("%{browser} http://www.google.com/"
0141                           "search?tbm=isch&q=%u{artist}%20%u{album}")));
0142     m_contextMenuCommands.push_back(
0143       UserActionsConfig::MenuCommand(
0144             QLatin1String("Amazon"),
0145             QLatin1String("%{browser} http://www.amazon.com/s?search-alias=aps&"
0146                           "field-keywords=%u{artist}+%u{album}")));
0147     m_contextMenuCommands.push_back(
0148       UserActionsConfig::MenuCommand(QString(), QLatin1String("@endmenu")));
0149     m_contextMenuCommands.push_back(
0150       UserActionsConfig::MenuCommand(QLatin1String("Lyrics"),
0151                                      QLatin1String("@beginmenu")));
0152     m_contextMenuCommands.push_back(
0153       UserActionsConfig::MenuCommand(
0154             QLatin1String("Letras"),
0155             QLatin1String("%{browser} https://www.letras.com/%u{artist}/%u{title}")));
0156   }
0157 #ifdef HAVE_QML
0158   if (!upgradeOnly || ConfigStore::getConfigVersion() < 2) {
0159     m_contextMenuCommands.push_back(
0160       UserActionsConfig::MenuCommand(
0161             QLatin1String("Embed Lyrics"),
0162             QLatin1String("@qml %{qmlpath}/script/EmbedLyrics.qml"),
0163             false, true));
0164   }
0165 #endif
0166   if (!upgradeOnly) {
0167     m_contextMenuCommands.push_back(
0168       UserActionsConfig::MenuCommand(
0169             QLatin1String("Lyrics.com"),
0170             QLatin1String("%{browser} http://www.lyrics.com/lyrics/"
0171                           "%u{artist}+%u{title}")));
0172     m_contextMenuCommands.push_back(
0173       UserActionsConfig::MenuCommand(
0174             QLatin1String("AZLyrics"),
0175             QLatin1String("%{browser} http://search.azlyrics.com/"
0176                           "search.php?q=%u{artist}+%u{title}")));
0177     m_contextMenuCommands.push_back(
0178       UserActionsConfig::MenuCommand(
0179             QLatin1String("Dark Lyrics"),
0180             QLatin1String("%{browser} http://www.darklyrics.com/"
0181                           "search?q=%u{album}")));
0182     m_contextMenuCommands.push_back(
0183       UserActionsConfig::MenuCommand(
0184             QLatin1String("SongLyrics"),
0185             QLatin1String("%{browser} http://www.songlyrics.com/index.php"
0186                           "?section=search&searchW=%u{artist}+%u{title}")));
0187     m_contextMenuCommands.push_back(
0188       UserActionsConfig::MenuCommand(
0189             QLatin1String("LyricsMode"),
0190             QLatin1String("%{browser} http://www.lyricsmode.com/search.php"
0191                           "?search=%u{artist}+%u{title}")));
0192     m_contextMenuCommands.push_back(
0193       UserActionsConfig::MenuCommand(
0194             QLatin1String("MP3 Lyrics"),
0195             QLatin1String("%{browser} http://mp3lyrics.com/Search/Advanced/"
0196                           "?Track=%u{title}&Artist=%u{artist}")));
0197     m_contextMenuCommands.push_back(
0198       UserActionsConfig::MenuCommand(QString(), QLatin1String("@endmenu")));
0199   }
0200 #ifdef HAVE_QML
0201   if (!upgradeOnly || ConfigStore::getConfigVersion() < 2) {
0202     m_contextMenuCommands.push_back(
0203       UserActionsConfig::MenuCommand(
0204             QLatin1String("QML Console"),
0205             QLatin1String("@qmlview %{qmlpath}/script/QmlConsole.qml"),
0206             false, true));
0207     m_contextMenuCommands.push_back(
0208       UserActionsConfig::MenuCommand(
0209             QLatin1String("ReplayGain to SoundCheck"),
0210             QLatin1String("@qml %{qmlpath}/script/ReplayGain2SoundCheck.qml"),
0211             false, true));
0212     m_contextMenuCommands.push_back(
0213       UserActionsConfig::MenuCommand(
0214             QLatin1String("Text Encoding ID3v1"),
0215             QLatin1String("@qml %{qmlpath}/script/ShowTextEncodingV1.qml"),
0216             false, true));
0217     m_contextMenuCommands.push_back(
0218       UserActionsConfig::MenuCommand(
0219             QLatin1String("Export CSV"),
0220             QLatin1String("@qml %{qmlpath}/script/ExportCsv.qml"),
0221             false, true));
0222   } else if (ConfigStore::getConfigVersion() == 2) {
0223     // Remove default argument from "Export CSV", a file selector is now used.
0224     if (int exportCsvIdx = m_contextMenuCommands.indexOf(
0225           UserActionsConfig::MenuCommand(
0226             QLatin1String("Export CSV"),
0227             QLatin1String("@qml %{qmlpath}/script/ExportCsv.qml "
0228               "%{directory}/export.csv"), false, true));
0229         exportCsvIdx != -1) {
0230       m_contextMenuCommands[exportCsvIdx].setCommand(
0231             QLatin1String("@qml %{qmlpath}/script/ExportCsv.qml"));
0232     }
0233   }
0234   if (!upgradeOnly || ConfigStore::getConfigVersion() < 3) {
0235     m_contextMenuCommands.push_back(
0236       UserActionsConfig::MenuCommand(
0237             QLatin1String("Import CSV"),
0238             QLatin1String("@qml %{qmlpath}/script/ImportCsv.qml"),
0239             false, true));
0240   }
0241   if (!upgradeOnly || ConfigStore::getConfigVersion() < 4) {
0242     m_contextMenuCommands.push_back(
0243       UserActionsConfig::MenuCommand(
0244             QLatin1String("Export Playlist Folder"),
0245             QLatin1String("@qml %{qmlpath}/script/ExportPlaylist.qml"),
0246             false, true));
0247   }
0248   if (!upgradeOnly || ConfigStore::getConfigVersion() < 5) {
0249     m_contextMenuCommands.push_back(
0250       UserActionsConfig::MenuCommand(
0251             QLatin1String("ID3v1 to ASCII"),
0252             QLatin1String("@qml %{qmlpath}/script/Tag1ToAscii.qml")));
0253     m_contextMenuCommands.push_back(
0254       UserActionsConfig::MenuCommand(
0255             QLatin1String("English Title Case"),
0256             QLatin1String("@qml %{qmlpath}/script/TitleCase.qml")));
0257   }
0258   if (!upgradeOnly || ConfigStore::getConfigVersion() < 6) {
0259     m_contextMenuCommands.push_back(
0260       UserActionsConfig::MenuCommand(
0261             QLatin1String("Rewrite Tags"),
0262             QLatin1String("@qml %{qmlpath}/script/RewriteTags.qml")));
0263   }
0264   if (!upgradeOnly || ConfigStore::getConfigVersion() < 7) {
0265     m_contextMenuCommands.push_back(
0266       UserActionsConfig::MenuCommand(
0267             QLatin1String("Export JSON"),
0268             QLatin1String("@qml %{qmlpath}/script/ExportJson.qml"),
0269             false, true));
0270     m_contextMenuCommands.push_back(
0271       UserActionsConfig::MenuCommand(
0272             QLatin1String("Import JSON"),
0273             QLatin1String("@qml %{qmlpath}/script/ImportJson.qml"),
0274             false, true));
0275   }
0276   if (!upgradeOnly || ConfigStore::getConfigVersion() < 8) {
0277     m_contextMenuCommands.push_back(
0278       UserActionsConfig::MenuCommand(
0279             QLatin1String("Fix ID3v2 Standard Violations"),
0280             QLatin1String("@qml %{qmlpath}/script/FixId3v2StandardViolations.qml"),
0281             false, true));
0282   }
0283 #endif
0284 }
0285 
0286 void UserActionsConfig::setContextMenuCommands(
0287     const QList<MenuCommand>& contextMenuCommands)
0288 {
0289   if (m_contextMenuCommands != contextMenuCommands) {
0290     m_contextMenuCommands = contextMenuCommands;
0291     emit contextMenuCommandsChanged();
0292   }
0293 }
0294 
0295 QVariantList UserActionsConfig::contextMenuCommandVariantList() const
0296 {
0297   QVariantList lst;
0298   for (auto it = m_contextMenuCommands.constBegin();
0299        it != m_contextMenuCommands.constEnd();
0300        ++it) {
0301     lst.append(it->toStringList());
0302   }
0303   return lst;
0304 }
0305 
0306 void UserActionsConfig::setContextMenuCommandVariantList(const QVariantList& lst)
0307 {
0308   QList<MenuCommand> commands;
0309   for (auto it = lst.constBegin(); it != lst.constEnd(); ++it) {
0310     commands.append(MenuCommand(it->toStringList()));
0311   }
0312   setContextMenuCommands(commands);
0313 }
0314 
0315 
0316 /**
0317  * Constructor.
0318  *
0319  * @param name display name
0320  * @param cmd  command string with argument codes
0321  * @param confirm true if confirmation required
0322  * @param showOutput true if output of command shall be shown
0323  */
0324 UserActionsConfig::MenuCommand::MenuCommand(
0325     const QString& name, const QString& cmd, bool confirm, bool showOutput)
0326   : m_name(name), m_cmd(cmd), m_confirm(confirm), m_showOutput(showOutput)
0327 {
0328 }
0329 
0330 /**
0331  * Constructor.
0332  *
0333  * @param strList string list with encoded command
0334  */
0335 UserActionsConfig::MenuCommand::MenuCommand(const QStringList& strList)
0336 {
0337   if (strList.size() == 3) {
0338     bool ok;
0339     uint flags = strList[2].toUInt(&ok);
0340     if (ok) {
0341       m_confirm = (flags & 1) != 0;
0342       m_showOutput = (flags & 2) != 0;
0343       m_name = strList[0];
0344       m_cmd = strList[1];
0345     } else {
0346       m_confirm = false;
0347       m_showOutput = false;
0348     }
0349   }
0350 }
0351 
0352 /**
0353  * Encode into string list.
0354  *
0355  * @return string list with encoded command.
0356  */
0357 QStringList UserActionsConfig::MenuCommand::toStringList() const {
0358   QStringList strList;
0359   strList.push_back(m_name);
0360   strList.push_back(m_cmd);
0361   uint flags = (m_confirm ? 1 : 0) | (m_showOutput ? 2 : 0);
0362   strList.push_back(QString::number(flags));
0363   return strList;
0364 }