File indexing completed on 2024-05-12 04:55:02

0001 /**
0002  * \file kid3mainwindow.cpp
0003  * Kid3 main window.
0004  *
0005  * \b Project: Kid3
0006  * \author Urs Fleisch
0007  * \date 9 Jan 2003
0008  *
0009  * Copyright (C) 2003-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 "kid3mainwindow.h"
0028 #include <QMessageBox>
0029 #include <QCloseEvent>
0030 #include <QIcon>
0031 #include <QToolBar>
0032 #include <QApplication>
0033 #include <QMenuBar>
0034 #include <QMenu>
0035 #include <QAction>
0036 #include <QStyle>
0037 #include <QStatusBar>
0038 #include <QSessionManager>
0039 #include "config.h"
0040 #include "recentfilesmenu.h"
0041 #include "shortcutsmodel.h"
0042 #include "mainwindowconfig.h"
0043 #include "kid3form.h"
0044 #include "filelist.h"
0045 #include "sectionactions.h"
0046 #include "kid3application.h"
0047 #include "configdialog.h"
0048 #include "guiconfig.h"
0049 #include "tagconfig.h"
0050 #include "fileconfig.h"
0051 #include "useractionsconfig.h"
0052 #include "contexthelp.h"
0053 #include "serverimporter.h"
0054 #include "servertrackimporter.h"
0055 #include "loadtranslation.h"
0056 #include "fileproxymodel.h"
0057 
0058 /**
0059  * Constructor.
0060  *
0061  * @param platformTools platform specific tools
0062  * @param app application context
0063  * @param parent parent widget
0064  */
0065 Kid3MainWindow::Kid3MainWindow(IPlatformTools* platformTools,
0066                                Kid3Application* app, QWidget* parent)
0067   : QMainWindow(parent), BaseMainWindow(this, platformTools, app),
0068     m_platformTools(platformTools),
0069     m_fileOpenRecent(nullptr), m_shortcutsModel(new ShortcutsModel(this)),
0070     m_viewToolBar(nullptr), m_viewStatusBar(nullptr),
0071     m_settingsAutoHideTags(nullptr), m_settingsShowHidePicture(nullptr)
0072 {
0073 #if !defined Q_OS_WIN32 && defined CFG_DATAROOTDIR
0074   QString dataRootDir(QLatin1String(CFG_DATAROOTDIR));
0075   Utils::prependApplicationDirPathIfRelative(dataRootDir);
0076 
0077   if (QPixmap icon;
0078       icon.load(dataRootDir +
0079 #ifndef Q_OS_MAC
0080                 QLatin1String("/icons/hicolor/128x128/apps/kid3-qt.png")
0081 #else
0082                 QLatin1String("/kid3.png")
0083 #endif
0084         )) {
0085     setWindowIcon(icon);
0086   }
0087 #endif
0088   readFontAndStyleOptions();
0089   init();
0090 
0091   connect(qApp, &QGuiApplication::commitDataRequest,
0092           this, &Kid3MainWindow::onCommitDataRequest);
0093 }
0094 
0095 /** Only defined for generation of translation files */
0096 #define MAIN_TOOLBAR_FOR_PO QT_TRANSLATE_NOOP("@default", "Main Toolbar")
0097 
0098 /**
0099  * Init menu and toolbar actions.
0100  */
0101 void Kid3MainWindow::initActions()
0102 {
0103   auto toolBar = new QToolBar(this);
0104   toolBar->setObjectName(QLatin1String("MainToolbar"));
0105 #ifdef Q_OS_MAC
0106   toolBar->setStyleSheet(QLatin1String("QToolButton { border: 0; }"));
0107 #endif
0108   QMenuBar* menubar = menuBar();
0109   QString menuTitle(tr("&File"));
0110   QMenu* fileMenu = menubar->addMenu(menuTitle);
0111 
0112   auto fileOpen = new QAction(this);
0113   fileOpen->setStatusTip(tr("Open files"));
0114   fileOpen->setText(tr("&Open..."));
0115   fileOpen->setShortcut(QKeySequence::Open);
0116   fileOpen->setIcon(QIcon::fromTheme(QLatin1String("document-open"),
0117       QIcon(QLatin1String(":/images/document-open.png"))));
0118   fileOpen->setObjectName(QLatin1String("file_open"));
0119   m_shortcutsModel->registerAction(fileOpen, menuTitle);
0120   connect(fileOpen, &QAction::triggered,
0121     impl(), &BaseMainWindowImpl::slotFileOpen);
0122   fileMenu->addAction(fileOpen);
0123   toolBar->addAction(fileOpen);
0124 
0125   m_fileOpenRecent = new RecentFilesMenu(fileMenu);
0126   connect(m_fileOpenRecent, &RecentFilesMenu::loadFile,
0127           this, &Kid3MainWindow::slotFileOpenRecentDirectory);
0128   m_fileOpenRecent->setStatusTip(tr("Opens a recently used folder"));
0129   m_fileOpenRecent->setTitle(tr("Open &Recent"));
0130   m_fileOpenRecent->setIcon(QIcon::fromTheme(
0131       QLatin1String("document-open-recent"),
0132       QIcon(QLatin1String(":/images/document-open-recent.png"))));
0133   fileMenu->addMenu(m_fileOpenRecent);
0134 
0135   auto fileOpenDirectory = new QAction(this);
0136   fileOpenDirectory->setStatusTip(tr("Opens a folder"));
0137   fileOpenDirectory->setText(tr("O&pen Folder..."));
0138   fileOpenDirectory->setShortcut(Qt::CTRL | Qt::Key_D);
0139   fileOpenDirectory->setIcon(QIcon::fromTheme(QLatin1String("document-open"),
0140       QIcon(QLatin1String(":/images/document-open.png"))));
0141   fileOpenDirectory->setObjectName(QLatin1String("open_directory"));
0142   m_shortcutsModel->registerAction(fileOpenDirectory, menuTitle);
0143   connect(fileOpenDirectory, &QAction::triggered,
0144     impl(), &BaseMainWindowImpl::slotFileOpenDirectory);
0145   fileMenu->addAction(fileOpenDirectory);
0146 
0147   auto fileReload = new QAction(this);
0148   fileReload->setStatusTip(tr("Reload folder"));
0149   fileReload->setText(tr("Re&load"));
0150   fileReload->setShortcut(QKeySequence::Refresh);
0151   fileReload->setIcon(QIcon::fromTheme(QLatin1String("view-refresh"),
0152       QIcon(QLatin1String(":/images/view-refresh.png"))));
0153   fileReload->setObjectName(QLatin1String("reload"));
0154   m_shortcutsModel->registerAction(fileReload, menuTitle);
0155   connect(fileReload, &QAction::triggered,
0156     impl(), &BaseMainWindowImpl::slotFileReload);
0157   fileMenu->addAction(fileReload);
0158 
0159   auto fileUnload = new QAction(this);
0160   fileUnload->setText(tr("Unload"));
0161   fileUnload->setObjectName(QLatin1String("unload"));
0162   m_shortcutsModel->registerAction(fileUnload, menuTitle);
0163   connect(fileUnload, &QAction::triggered,
0164           app(), &Kid3Application::unloadAllTags);
0165   addAction(fileUnload);
0166 
0167   fileMenu->addSeparator();
0168 
0169   auto fileSave = new QAction(this);
0170   fileSave->setStatusTip(tr("Saves the changed files"));
0171   fileSave->setText(tr("&Save"));
0172   fileSave->setShortcut(QKeySequence::Save);
0173   fileSave->setIcon(QIcon::fromTheme(QLatin1String("document-save"),
0174       QIcon(QLatin1String(":/images/document-save.png"))));
0175   fileSave->setObjectName(QLatin1String("file_save"));
0176   m_shortcutsModel->registerAction(fileSave, menuTitle);
0177   connect(fileSave, &QAction::triggered,
0178     impl(), &BaseMainWindowImpl::slotFileSave);
0179   fileMenu->addAction(fileSave);
0180   toolBar->addAction(fileSave);
0181 
0182   auto fileRevert = new QAction(this);
0183   fileRevert->setStatusTip(
0184       tr("Reverts the changes of all or the selected files"));
0185   fileRevert->setText(tr("Re&vert"));
0186   fileRevert->setShortcut(QKeySequence::Undo);
0187   fileRevert->setIcon(QIcon::fromTheme(QLatin1String("document-revert"),
0188       QIcon(QLatin1String(":/images/document-revert.png"))));
0189   fileRevert->setObjectName(QLatin1String("file_revert"));
0190   m_shortcutsModel->registerAction(fileRevert, menuTitle);
0191   connect(fileRevert, &QAction::triggered,
0192           app(), &Kid3Application::revertFileModifications);
0193   fileMenu->addAction(fileRevert);
0194   toolBar->addAction(fileRevert);
0195   fileMenu->addSeparator();
0196 
0197   auto fileImport = new QAction(this);
0198   fileImport->setData(-1);
0199   fileImport->setStatusTip(tr("Import from file or clipboard"));
0200   fileImport->setText(tr("&Import..."));
0201   fileImport->setIcon(QIcon::fromTheme(QLatin1String("document-import"),
0202       QIcon(QLatin1String(":/images/document-import.png"))));
0203   fileImport->setObjectName(QLatin1String("import"));
0204   m_shortcutsModel->registerAction(fileImport, menuTitle);
0205   connect(fileImport, &QAction::triggered,
0206     impl(), &BaseMainWindowImpl::slotImport);
0207   fileMenu->addAction(fileImport);
0208 
0209   int importerIdx = 0;
0210   const auto sis = app()->getServerImporters();
0211   for (const ServerImporter* si : sis) {
0212     QString serverName(QCoreApplication::translate("@default", si->name()));
0213     QString actionName = QString::fromLatin1(
0214           si->name()).toLower().remove(QLatin1Char(' '));
0215     if (int dotPos = actionName.indexOf(QLatin1Char('.')); dotPos != -1)
0216       actionName.truncate(dotPos);
0217     actionName = QLatin1String("import_") + actionName;
0218     auto fileImportServer = new QAction(this);
0219     fileImportServer->setData(importerIdx);
0220     fileImportServer->setStatusTip(tr("Import from %1").arg(serverName));
0221     fileImportServer->setText(tr("Import from %1...").arg(serverName));
0222     fileImportServer->setObjectName(actionName);
0223     m_shortcutsModel->registerAction(fileImportServer, menuTitle);
0224     connect(fileImportServer, &QAction::triggered,
0225       impl(), &BaseMainWindowImpl::slotImport);
0226     fileMenu->addAction(fileImportServer);
0227     ++importerIdx;
0228   }
0229 
0230   const auto stis = app()->getServerTrackImporters();
0231   for (const ServerTrackImporter* si : stis) {
0232     QString serverName(QCoreApplication::translate("@default", si->name()));
0233     QString actionName = QString::fromLatin1(
0234           si->name()).toLower().remove(QLatin1Char(' '));
0235     if (int dotPos = actionName.indexOf(QLatin1Char('.')); dotPos != -1)
0236       actionName.truncate(dotPos);
0237     actionName = QLatin1String("import_") + actionName;
0238     auto fileImportServer = new QAction(this);
0239     fileImportServer->setData(importerIdx);
0240     fileImportServer->setStatusTip(tr("Import from %1").arg(serverName));
0241     fileImportServer->setText(tr("Import from %1...").arg(serverName));
0242     fileImportServer->setObjectName(actionName);
0243     m_shortcutsModel->registerAction(fileImportServer, menuTitle);
0244     connect(fileImportServer, &QAction::triggered,
0245       impl(), &BaseMainWindowImpl::slotImport);
0246     fileMenu->addAction(fileImportServer);
0247     ++importerIdx;
0248   }
0249 
0250   auto fileTagImport = new QAction(this);
0251   fileTagImport->setStatusTip(tr("Import from Tags"));
0252   fileTagImport->setText(tr("Import from Tags..."));
0253   fileTagImport->setObjectName(QLatin1String("import_tags"));
0254   m_shortcutsModel->registerAction(fileTagImport, menuTitle);
0255   connect(fileTagImport, &QAction::triggered,
0256     impl(), &BaseMainWindowImpl::slotTagImport);
0257   fileMenu->addAction(fileTagImport);
0258 
0259   auto fileBatchImport = new QAction(this);
0260   fileBatchImport->setStatusTip(tr("Automatic import"));
0261   fileBatchImport->setText(tr("Automatic I&mport..."));
0262   fileBatchImport->setObjectName(QLatin1String("batch_import"));
0263   m_shortcutsModel->registerAction(fileBatchImport, menuTitle);
0264   connect(fileBatchImport, &QAction::triggered,
0265     impl(), &BaseMainWindowImpl::slotBatchImport);
0266   fileMenu->addAction(fileBatchImport);
0267 
0268   auto fileBrowseCoverArt = new QAction(this);
0269   fileBrowseCoverArt->setStatusTip(tr("Browse album cover artwork"));
0270   fileBrowseCoverArt->setText(tr("&Browse Cover Art..."));
0271   fileBrowseCoverArt->setObjectName(QLatin1String("browse_cover_art"));
0272   m_shortcutsModel->registerAction(fileBrowseCoverArt, menuTitle);
0273   connect(fileBrowseCoverArt, &QAction::triggered,
0274     impl(), &BaseMainWindowImpl::slotBrowseCoverArt);
0275   fileMenu->addAction(fileBrowseCoverArt);
0276   fileMenu->addSeparator();
0277 
0278   auto fileExport = new QAction(this);
0279   fileExport->setStatusTip(tr("Export to file or clipboard"));
0280   fileExport->setText(tr("&Export..."));
0281   fileExport->setIcon(QIcon::fromTheme(QLatin1String("document-export"),
0282       QIcon(QLatin1String(":/images/document-export.png"))));
0283   fileExport->setObjectName(QLatin1String("export"));
0284   m_shortcutsModel->registerAction(fileExport, menuTitle);
0285   connect(fileExport, &QAction::triggered,
0286     impl(), &BaseMainWindowImpl::slotExport);
0287   fileMenu->addAction(fileExport);
0288 
0289   auto fileCreatePlaylist = new QAction(this);
0290   fileCreatePlaylist->setStatusTip(tr("Create M3U Playlist"));
0291   fileCreatePlaylist->setText(tr("&Create Playlist..."));
0292   fileCreatePlaylist->setIcon(
0293         QIcon::fromTheme(QLatin1String("format-justify-fill"),
0294             QIcon(QLatin1String(":/images/view-media-playlist.png"))));
0295   fileCreatePlaylist->setObjectName(QLatin1String("create_playlist"));
0296   m_shortcutsModel->registerAction(fileCreatePlaylist, menuTitle);
0297   connect(fileCreatePlaylist, &QAction::triggered,
0298     impl(), &BaseMainWindowImpl::slotPlaylistDialog);
0299   fileMenu->addAction(fileCreatePlaylist);
0300   toolBar->addAction(fileCreatePlaylist);
0301   fileMenu->addSeparator();
0302 
0303   auto fileQuit = new QAction(this);
0304   fileQuit->setStatusTip(tr("Quits the application"));
0305   fileQuit->setText(tr("&Quit"));
0306   fileQuit->setShortcut(Qt::CTRL | Qt::Key_Q);
0307   fileQuit->setIcon(QIcon::fromTheme(QLatin1String("application-exit"),
0308       QIcon(QLatin1String(":/images/application-exit.png"))));
0309   fileQuit->setMenuRole(QAction::QuitRole);
0310   fileQuit->setObjectName(QLatin1String("file_quit"));
0311   m_shortcutsModel->registerAction(fileQuit, menuTitle);
0312   connect(fileQuit, &QAction::triggered,
0313     impl(), &BaseMainWindowImpl::slotFileQuit);
0314   fileMenu->addAction(fileQuit);
0315 
0316   menuTitle = tr("&Edit");
0317   QMenu* editMenu = menubar->addMenu(menuTitle);
0318   auto editSelectAll = new QAction(this);
0319   editSelectAll->setStatusTip(tr("Select all files"));
0320   editSelectAll->setText(tr("Select &All"));
0321   editSelectAll->setShortcut(Qt::ALT | Qt::Key_A);
0322   editSelectAll->setIcon(QIcon::fromTheme(QLatin1String("edit-select-all"),
0323       QIcon(QLatin1String(":/images/edit-select-all.png"))));
0324 #if defined Q_OS_MAC && QT_VERSION == 0x050400
0325   // Workaround for QTBUG-43471 from QTBUG-39934
0326   editSelectAll->setMenuRole(QAction::NoRole);
0327 #endif
0328   editSelectAll->setObjectName(QLatin1String("edit_select_all"));
0329   m_shortcutsModel->registerAction(editSelectAll, menuTitle);
0330   connect(editSelectAll, &QAction::triggered,
0331           form(), &Kid3Form::selectAllFiles);
0332   editMenu->addAction(editSelectAll);
0333 
0334   auto editDeselect = new QAction(this);
0335   editDeselect->setStatusTip(tr("Deselect all files"));
0336   editDeselect->setText(tr("Dese&lect"));
0337   editDeselect->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_A);
0338   editDeselect->setObjectName(QLatin1String("edit_deselect"));
0339   m_shortcutsModel->registerAction(editDeselect, menuTitle);
0340   connect(editDeselect, &QAction::triggered,
0341           form(), &Kid3Form::deselectAllFiles);
0342   editMenu->addAction(editDeselect);
0343 
0344   auto editSelectAllInDir = new QAction(this);
0345   editSelectAllInDir->setStatusTip(
0346         tr("Select all files in the current folder"));
0347   editSelectAllInDir->setText(tr("Select All in &Folder"));
0348   editSelectAllInDir->setObjectName(QLatin1String("select_all_in_directory"));
0349   m_shortcutsModel->registerAction(editSelectAllInDir, menuTitle);
0350   connect(editSelectAllInDir, &QAction::triggered,
0351     app(), &Kid3Application::selectAllInDirectory);
0352   editMenu->addAction(editSelectAllInDir);
0353 
0354   auto editInvertSelection = new QAction(this);
0355   editInvertSelection->setText(tr("&Invert Selection"));
0356   editInvertSelection->setObjectName(QLatin1String("invert_selection"));
0357   m_shortcutsModel->registerAction(editInvertSelection, menuTitle);
0358   connect(editInvertSelection, &QAction::triggered,
0359     app(), &Kid3Application::invertSelection);
0360   editMenu->addAction(editInvertSelection);
0361 
0362   auto editPreviousFile = new QAction(this);
0363   editPreviousFile->setStatusTip(tr("Select previous file"));
0364   editPreviousFile->setText(tr("&Previous File"));
0365   editPreviousFile->setShortcut(Qt::ALT | Qt::Key_Up);
0366   editPreviousFile->setIcon(QIcon::fromTheme(QLatin1String("go-previous"),
0367       QIcon(QLatin1String(":/images/go-previous.png"))));
0368   editPreviousFile->setObjectName(QLatin1String("previous_file"));
0369   m_shortcutsModel->registerAction(editPreviousFile, menuTitle);
0370   connect(editPreviousFile, &QAction::triggered,
0371     form(), &Kid3Form::selectPreviousTaggedFile);
0372   editMenu->addAction(editPreviousFile);
0373   toolBar->addAction(editPreviousFile);
0374 
0375   auto editNextFile = new QAction(this);
0376   editNextFile->setStatusTip(tr("Select next file"));
0377   editNextFile->setText(tr("&Next File"));
0378   editNextFile->setShortcut(Qt::ALT | Qt::Key_Down);
0379   editNextFile->setIcon(QIcon::fromTheme(QLatin1String("go-next"),
0380       QIcon(QLatin1String(":/images/go-next.png"))));
0381   editNextFile->setObjectName(QLatin1String("next_file"));
0382   m_shortcutsModel->registerAction(editNextFile, menuTitle);
0383   connect(editNextFile, &QAction::triggered,
0384     form(), &Kid3Form::selectNextTaggedFile);
0385   editMenu->addAction(editNextFile);
0386   toolBar->addAction(editNextFile);
0387   editMenu->addSeparator();
0388 
0389   auto editFind = new QAction(this);
0390   editFind->setStatusTip(tr("Find"));
0391   editFind->setText(tr("&Find..."));
0392   editFind->setShortcut(QKeySequence::Find);
0393 #ifndef Q_OS_MAC
0394   editFind->setIcon(QIcon::fromTheme(QLatin1String("edit-find"),
0395       QIcon(QLatin1String(":/images/edit-find.png"))));
0396 #endif
0397   editFind->setObjectName(QLatin1String("edit_find"));
0398   m_shortcutsModel->registerAction(editFind, menuTitle);
0399   connect(editFind, &QAction::triggered,
0400     impl(), &BaseMainWindowImpl::find);
0401   editMenu->addAction(editFind);
0402 
0403   auto editReplace = new QAction(this);
0404   editReplace->setStatusTip(tr("Find and replace"));
0405   editReplace->setText(tr("&Replace..."));
0406   editReplace->setShortcut(QKeySequence::Replace);
0407 #ifndef Q_OS_MAC
0408   editReplace->setIcon(QIcon::fromTheme(QLatin1String("edit-find-replace"),
0409       QIcon(QLatin1String(":/images/edit-find-replace.png"))));
0410 #endif
0411   editReplace->setObjectName(QLatin1String("edit_replace"));
0412   m_shortcutsModel->registerAction(editReplace, menuTitle);
0413   connect(editReplace, &QAction::triggered,
0414     impl(), &BaseMainWindowImpl::findReplace);
0415   editMenu->addAction(editReplace);
0416 
0417   menuTitle = tr("&Tools");
0418   QMenu* toolsMenu = menubar->addMenu(menuTitle);
0419   auto toolsApplyFilenameFormat = new QAction(this);
0420   toolsApplyFilenameFormat->setStatusTip(tr("Apply Filename Format"));
0421   toolsApplyFilenameFormat->setText(tr("Apply &Filename Format"));
0422   toolsApplyFilenameFormat->setObjectName(
0423         QLatin1String("apply_filename_format"));
0424   m_shortcutsModel->registerAction(toolsApplyFilenameFormat, menuTitle);
0425   connect(toolsApplyFilenameFormat, &QAction::triggered,
0426     app(), &Kid3Application::applyFilenameFormat);
0427   toolsMenu->addAction(toolsApplyFilenameFormat);
0428 
0429   auto toolsApplyTagFormat = new QAction(this);
0430   toolsApplyTagFormat->setStatusTip(tr("Apply Tag Format"));
0431   toolsApplyTagFormat->setText(tr("Apply &Tag Format"));
0432   toolsApplyTagFormat->setObjectName(QLatin1String("apply_id3_format"));
0433   m_shortcutsModel->registerAction(toolsApplyTagFormat, menuTitle);
0434   connect(toolsApplyTagFormat, &QAction::triggered,
0435     app(), &Kid3Application::applyTagFormat);
0436   toolsMenu->addAction(toolsApplyTagFormat);
0437 
0438   auto toolsApplyTextEncoding = new QAction(this);
0439   toolsApplyTextEncoding->setStatusTip(tr("Apply Text Encoding"));
0440   toolsApplyTextEncoding->setText(tr("Apply Text &Encoding"));
0441   toolsApplyTextEncoding->setObjectName(QLatin1String("apply_text_encoding"));
0442   m_shortcutsModel->registerAction(toolsApplyTextEncoding, menuTitle);
0443   connect(toolsApplyTextEncoding, &QAction::triggered,
0444     app(), &Kid3Application::applyTextEncoding);
0445   toolsMenu->addAction(toolsApplyTextEncoding);
0446   toolsMenu->addSeparator();
0447 
0448   auto toolsRenameDirectory = new QAction(this);
0449   toolsRenameDirectory->setStatusTip(tr("Rename Folder"));
0450   toolsRenameDirectory->setText(tr("&Rename Folder..."));
0451   toolsRenameDirectory->setObjectName(QLatin1String("rename_directory"));
0452   m_shortcutsModel->registerAction(toolsRenameDirectory, menuTitle);
0453   connect(toolsRenameDirectory, &QAction::triggered,
0454     impl(), &BaseMainWindowImpl::slotRenameDirectory);
0455   toolsMenu->addAction(toolsRenameDirectory);
0456 
0457   auto toolsNumberTracks = new QAction(this);
0458   toolsNumberTracks->setStatusTip(tr("Number Tracks"));
0459   toolsNumberTracks->setText(tr("&Number Tracks..."));
0460   toolsNumberTracks->setObjectName(QLatin1String("number_tracks"));
0461   m_shortcutsModel->registerAction(toolsNumberTracks, menuTitle);
0462   connect(toolsNumberTracks, &QAction::triggered,
0463     impl(), &BaseMainWindowImpl::slotNumberTracks);
0464   toolsMenu->addAction(toolsNumberTracks);
0465 
0466   auto toolsFilter = new QAction(this);
0467   toolsFilter->setStatusTip(tr("Filter"));
0468   toolsFilter->setText(tr("F&ilter..."));
0469   toolsFilter->setObjectName(QLatin1String("filter"));
0470   m_shortcutsModel->registerAction(toolsFilter, menuTitle);
0471   connect(toolsFilter, &QAction::triggered,
0472     impl(), &BaseMainWindowImpl::slotFilter);
0473   toolsMenu->addAction(toolsFilter);
0474   toolsMenu->addSeparator();
0475 
0476   if (const TagConfig& tagCfg = TagConfig::instance();
0477       tagCfg.taggedFileFeatures() & TaggedFile::TF_ID3v24) {
0478     auto toolsConvertToId3v24 = new QAction(this);
0479     toolsConvertToId3v24->setStatusTip(tr("Convert ID3v2.3 to ID3v2.4"));
0480     toolsConvertToId3v24->setText(tr("Convert ID3v2.3 to ID3v2.&4"));
0481     toolsConvertToId3v24->setObjectName(QLatin1String("convert_to_id3v24"));
0482     m_shortcutsModel->registerAction(toolsConvertToId3v24, menuTitle);
0483     connect(toolsConvertToId3v24, &QAction::triggered,
0484       app(), &Kid3Application::convertToId3v24);
0485     toolsMenu->addAction(toolsConvertToId3v24);
0486 
0487     if (tagCfg.taggedFileFeatures() & TaggedFile::TF_ID3v23) {
0488       auto toolsConvertToId3v23 = new QAction(this);
0489       toolsConvertToId3v23->setStatusTip(tr("Convert ID3v2.4 to ID3v2.3"));
0490       toolsConvertToId3v23->setText(tr("Convert ID3v2.4 to ID3v2.&3"));
0491       toolsConvertToId3v23->setObjectName(QLatin1String("convert_to_id3v23"));
0492       m_shortcutsModel->registerAction(toolsConvertToId3v23, menuTitle);
0493       connect(toolsConvertToId3v23, &QAction::triggered,
0494         app(), &Kid3Application::convertToId3v23);
0495       toolsMenu->addAction(toolsConvertToId3v23);
0496     }
0497   }
0498 
0499 #ifdef HAVE_QTMULTIMEDIA
0500   toolsMenu->addSeparator();
0501   auto toolsPlay = new QAction(this);
0502   toolsPlay->setStatusTip(tr("Play"));
0503   toolsPlay->setText(tr("&Play"));
0504   toolsPlay->setIcon(QIcon(style()->standardIcon(QStyle::SP_MediaPlay)));
0505   toolsPlay->setObjectName(QLatin1String("play"));
0506   m_shortcutsModel->registerAction(toolsPlay, menuTitle);
0507   connect(toolsPlay, &QAction::triggered,
0508     app(), &Kid3Application::playAudio);
0509   toolsMenu->addAction(toolsPlay);
0510   toolBar->addAction(toolsPlay);
0511 #endif
0512 
0513   menuTitle = tr("&Settings");
0514   QMenu* settingsMenu = menubar->addMenu(menuTitle);
0515   m_viewToolBar = toolBar->toggleViewAction();
0516   if (m_viewToolBar) {
0517     m_viewToolBar->setStatusTip(tr("Enables/disables the toolbar"));
0518     m_viewToolBar->setText(tr("Show &Toolbar"));
0519     m_viewToolBar->setObjectName(QLatin1String("options_configure_toolbars"));
0520     m_shortcutsModel->registerAction(m_viewToolBar, menuTitle);
0521     m_viewToolBar->setChecked(!MainWindowConfig::instance().hideToolBar());
0522     settingsMenu->addAction(m_viewToolBar);
0523   }
0524   if (MainWindowConfig::instance().hideToolBar())
0525     toolBar->hide();
0526 
0527   m_viewStatusBar = new QAction(this);
0528   m_viewStatusBar->setStatusTip(tr("Enables/disables the statusbar"));
0529   m_viewStatusBar->setText(tr("Show St&atusbar"));
0530   m_viewStatusBar->setCheckable(true);
0531   m_viewStatusBar->setObjectName(QLatin1String("options_show_statusbar"));
0532   m_shortcutsModel->registerAction(m_viewStatusBar, menuTitle);
0533   connect(m_viewStatusBar, &QAction::triggered,
0534     this, &Kid3MainWindow::slotViewStatusBar);
0535   settingsMenu->addAction(m_viewStatusBar);
0536 
0537   m_settingsShowHidePicture = new QAction(this);
0538   m_settingsShowHidePicture->setStatusTip(tr("Show Picture"));
0539   m_settingsShowHidePicture->setText(tr("Show &Picture"));
0540   m_settingsShowHidePicture->setCheckable(true);
0541   m_settingsShowHidePicture->setObjectName(QLatin1String("hide_picture"));
0542   m_shortcutsModel->registerAction(m_settingsShowHidePicture, menuTitle);
0543   connect(m_settingsShowHidePicture, &QAction::triggered,
0544     impl(), &BaseMainWindowImpl::slotSettingsShowHidePicture);
0545   settingsMenu->addAction(m_settingsShowHidePicture);
0546 
0547   m_settingsAutoHideTags = new QAction(this);
0548   m_settingsAutoHideTags->setStatusTip(tr("Auto Hide Tags"));
0549   m_settingsAutoHideTags->setText(tr("Auto &Hide Tags"));
0550   m_settingsAutoHideTags->setCheckable(true);
0551   m_settingsAutoHideTags->setObjectName(QLatin1String("auto_hide_tags"));
0552   m_shortcutsModel->registerAction(m_settingsAutoHideTags, menuTitle);
0553   connect(m_settingsAutoHideTags, &QAction::triggered,
0554     impl(), &BaseMainWindowImpl::slotSettingsAutoHideTags);
0555   settingsMenu->addAction(m_settingsAutoHideTags);
0556 
0557   auto settingsConfigure = new QAction(this);
0558   settingsConfigure->setStatusTip(tr("Configure Kid3"));
0559   settingsConfigure->setText(tr("&Configure Kid3..."));
0560   settingsConfigure->setIcon(QIcon::fromTheme(
0561       QLatin1String("configure"),
0562       QIcon(QLatin1String(":/images/configure.png"))));
0563   settingsConfigure->setShortcut(QKeySequence::Preferences);
0564   settingsConfigure->setMenuRole(QAction::PreferencesRole);
0565   settingsConfigure->setObjectName(QLatin1String("options_configure"));
0566   m_shortcutsModel->registerAction(settingsConfigure, menuTitle);
0567   connect(settingsConfigure, &QAction::triggered,
0568     this, &Kid3MainWindow::slotSettingsConfigure);
0569   settingsMenu->addSeparator();
0570   settingsMenu->addAction(settingsConfigure);
0571   toolBar->addAction(settingsConfigure);
0572 
0573   menuTitle = tr("&Help");
0574   QMenu* helpMenu = menubar->addMenu(menuTitle);
0575   auto helpHandbook = new QAction(this);
0576   helpHandbook->setStatusTip(tr("Kid3 Handbook"));
0577   helpHandbook->setText(tr("Kid3 &Handbook"));
0578   helpHandbook->setIcon(QIcon::fromTheme(QLatin1String("help-contents"),
0579       QIcon(QLatin1String(":/images/help-contents.png"))));
0580   helpHandbook->setShortcut(QKeySequence::HelpContents);
0581   helpHandbook->setObjectName(QLatin1String("help_contents"));
0582   m_shortcutsModel->registerAction(helpHandbook, menuTitle);
0583   connect(helpHandbook, &QAction::triggered,
0584     this, &Kid3MainWindow::slotHelpHandbook);
0585   helpMenu->addAction(helpHandbook);
0586 
0587   auto helpAbout = new QAction(this);
0588   helpAbout->setStatusTip(tr("About Kid3"));
0589   helpAbout->setText(tr("&About Kid3"));
0590 #ifndef Q_OS_MAC
0591   helpAbout->setIcon(QIcon::fromTheme(QLatin1String("help-about"),
0592       QIcon(QLatin1String(":/images/help-about.png"))));
0593 #endif
0594   helpAbout->setMenuRole(QAction::AboutRole);
0595   helpAbout->setObjectName(QLatin1String("help_about_app"));
0596   m_shortcutsModel->registerAction(helpAbout, menuTitle);
0597   connect(helpAbout, &QAction::triggered,
0598     this, &Kid3MainWindow::slotHelpAbout);
0599   helpMenu->addAction(helpAbout);
0600 
0601   auto helpAboutQt = new QAction(this);
0602   helpAboutQt->setStatusTip(tr("About Qt"));
0603   helpAboutQt->setText(tr("About &Qt"));
0604   helpAboutQt->setMenuRole(QAction::AboutQtRole);
0605   helpAboutQt->setObjectName(QLatin1String("help_about_qt"));
0606   m_shortcutsModel->registerAction(helpAboutQt, menuTitle);
0607   connect(helpAboutQt, &QAction::triggered,
0608     this, &Kid3MainWindow::slotHelpAboutQt);
0609   helpMenu->addAction(helpAboutQt);
0610 
0611   addToolBar(toolBar);
0612 
0613   updateWindowCaption();
0614 
0615   initFormActions();
0616 
0617   FileList* fileList = form()->getFileList();
0618   connect(fileList, &FileList::userActionAdded,
0619           this, &Kid3MainWindow::onUserActionAdded);
0620   connect(fileList, &FileList::userActionRemoved,
0621           this, &Kid3MainWindow::onUserActionRemoved);
0622   fileList->initUserActions();
0623   const UserActionsConfig& userActionsCfg = UserActionsConfig::instance();
0624   connect(&userActionsCfg, &UserActionsConfig::contextMenuCommandsChanged,
0625           fileList, &FileList::initUserActions);
0626 
0627   const QString ctx = tr("Player");
0628   const auto actions = impl()->mediaActions();
0629   for (QAction* action : actions) {
0630     m_shortcutsModel->registerAction(action, ctx);
0631   }
0632 }
0633 
0634 /**
0635  * Get keyboard shortcuts.
0636  * @return mapping of action names to key sequences.
0637  */
0638 QMap<QString, QKeySequence> Kid3MainWindow::shortcutsMap() const
0639 {
0640   if (m_shortcutsModel) {
0641     return m_shortcutsModel->shortcutsMap();
0642   }
0643   return {};
0644 }
0645 
0646 /**
0647  * Init actions of form.
0648  */
0649 void Kid3MainWindow::initFormActions()
0650 {
0651   QString ctx(tr("Filename"));
0652   FOR_ALL_TAGS(tagNr) {
0653     QString tagStr = Frame::tagNumberToString(tagNr);
0654     connect(addFormAction(tr("From Tag %1").arg(tagStr),
0655                           QLatin1String("filename_from_v") + tagStr, ctx),
0656             &QAction::triggered,
0657             app()->tag(tagNr), &Kid3ApplicationTagContext::getFilenameFromTags);
0658   }
0659   connect(addFormAction(tr("Focus"), QLatin1String("filename_focus"), ctx),
0660           &QAction::triggered,
0661           form(), &Kid3Form::setFocusFilename);
0662   FOR_ALL_TAGS(tagNr) {
0663     Frame::TagNumber otherTagNr = tagNr == Frame::Tag_1
0664         ? Frame::Tag_2
0665         : tagNr == Frame::Tag_2 ? Frame::Tag_1 : Frame::Tag_NumValues;
0666     QString tagStr = Frame::tagNumberToString(tagNr);
0667     Kid3ApplicationTagContext* appTag = app()->tag(tagNr);
0668     Kid3FormTagContext* formTag = form()->tag(tagNr);
0669     ctx = tr("Tag %1").arg(tagStr);
0670     tagStr = QLatin1Char('v') + tagStr + QLatin1Char('_');
0671     connect(addFormAction(tr("From Filename"),
0672                           tagStr + QLatin1String("from_filename"), ctx),
0673             &QAction::triggered,
0674             appTag, &Kid3ApplicationTagContext::getTagsFromFilename);
0675     if (otherTagNr < Frame::Tag_NumValues) {
0676       QString otherTagStr = Frame::tagNumberToString(otherTagNr);
0677       connect(addFormAction(tr("From Tag %1").arg(otherTagStr),
0678                             tagStr + QLatin1String("from_v") + otherTagStr, ctx),
0679               &QAction::triggered,
0680               appTag, &Kid3ApplicationTagContext::copyToOtherTag);
0681     }
0682     connect(addFormAction(tr("Copy"), tagStr + QLatin1String("copy"), ctx),
0683             &QAction::triggered,
0684             appTag, &Kid3ApplicationTagContext::copyTags);
0685     connect(addFormAction(tr("Paste"), tagStr + QLatin1String("paste"), ctx),
0686             &QAction::triggered,
0687             appTag, &Kid3ApplicationTagContext::pasteTags);
0688     connect(addFormAction(tr("Remove"), tagStr + QLatin1String("remove"), ctx),
0689             &QAction::triggered,
0690             appTag, &Kid3ApplicationTagContext::removeTags);
0691     if (tagNr != Frame::Tag_Id3v1) {
0692       connect(addFormAction(tr("Edit"), tagStr + QLatin1String("frames_edit"), ctx),
0693               &QAction::triggered,
0694               appTag, &Kid3ApplicationTagContext::editFrame);
0695       connect(addFormAction(tr("Add"), tagStr + QLatin1String("frames_add"), ctx),
0696               &QAction::triggered,
0697               appTag, &Kid3ApplicationTagContext::addFrame);
0698       connect(addFormAction(tr("Delete"), tagStr + QLatin1String("frames_delete"), ctx),
0699               &QAction::triggered,
0700               appTag, &Kid3ApplicationTagContext::deleteFrame);
0701     }
0702     connect(addFormAction(tr("Focus"), tagStr + QLatin1String("focus"), ctx),
0703             &QAction::triggered,
0704             formTag, &Kid3FormTagContext::setFocusTag);
0705   }
0706   ctx = tr("File List");
0707   connect(addFormAction(tr("Focus"), QLatin1String("filelist_focus"), ctx),
0708           &QAction::triggered,
0709           form(), &Kid3Form::setFocusFileList);
0710   auto renameAction = new QAction(tr("&Rename"), this);
0711   renameAction->setObjectName(QLatin1String("filelist_rename"));
0712   renameAction->setShortcut(QKeySequence(Qt::Key_F2));
0713   renameAction->setShortcutContext(Qt::WidgetShortcut);
0714   connect(renameAction, &QAction::triggered, impl(), &BaseMainWindowImpl::renameFile);
0715   form()->getFileList()->setRenameAction(renameAction);
0716   m_shortcutsModel->registerAction(renameAction, ctx);
0717   auto deleteAction = new QAction(tr("&Move to Trash"), this);
0718   deleteAction->setObjectName(QLatin1String("filelist_delete"));
0719   deleteAction->setShortcut(QKeySequence::Delete);
0720   deleteAction->setShortcutContext(Qt::WidgetShortcut);
0721   connect(deleteAction, &QAction::triggered, impl(), &BaseMainWindowImpl::deleteFile);
0722   form()->getFileList()->setDeleteAction(deleteAction);
0723   m_shortcutsModel->registerAction(deleteAction, ctx);
0724   ctx = tr("Folder List");
0725   connect(addFormAction(tr("Focus"), QLatin1String("dirlist_focus"), ctx),
0726           &QAction::triggered,
0727           form(), &Kid3Form::setFocusDirList);
0728 
0729   const auto sectionShortcuts = SectionActions::defaultShortcuts();
0730   ctx = tr("Section");
0731   for (auto it = sectionShortcuts.constBegin();
0732        it != sectionShortcuts.constEnd();
0733        ++it) {
0734     const auto& tpl = *it;
0735     auto action = new QAction(std::get<1>(tpl), this);
0736     action->setObjectName(std::get<0>(tpl));
0737     action->setShortcut(std::get<2>(tpl));
0738     action->setShortcutContext(Qt::WidgetShortcut);
0739     action->setEnabled(false);
0740     m_shortcutsModel->registerAction(action, ctx);
0741   }
0742 }
0743 
0744 /**
0745  * Add action of form.
0746  */
0747 QAction* Kid3MainWindow::addFormAction(const QString& text, const QString& name,
0748                                        const QString& context)
0749 {
0750   auto action = new QAction(form());
0751   action->setStatusTip(text);
0752   action->setText(text);
0753   action->setObjectName(name);
0754   m_shortcutsModel->registerAction(action, context);
0755   addAction(action);
0756   return action;
0757 }
0758 
0759 /**
0760  * Add directory to recent files list.
0761  *
0762  * @param dirName path to directory
0763  */
0764 void Kid3MainWindow::addDirectoryToRecentFiles(const QString& dirName)
0765 {
0766   m_fileOpenRecent->addDirectory(dirName);
0767 }
0768 
0769 /**
0770  * Read settings from the configuration.
0771  */
0772 void Kid3MainWindow::readConfig()
0773 {
0774   const MainWindowConfig& mainWindowConfig = MainWindowConfig::instance();
0775   setStatusBarVisible(!mainWindowConfig.hideStatusBar());
0776   m_viewStatusBar->setChecked(!mainWindowConfig.hideStatusBar());
0777   m_settingsShowHidePicture->setChecked(!GuiConfig::instance().hidePicture());
0778   m_settingsAutoHideTags->setChecked(GuiConfig::instance().autoHideTags());
0779   m_fileOpenRecent->loadEntries(app()->getSettings());
0780   m_shortcutsModel->readFromConfig(app()->getSettings());
0781   if (!mainWindowConfig.geometry().isEmpty()) {
0782     restoreGeometry(mainWindowConfig.geometry());
0783   } else {
0784     resize(1000, 900);
0785   }
0786   if (!mainWindowConfig.windowState().isEmpty()) {
0787     restoreState(mainWindowConfig.windowState());
0788   }
0789 }
0790 
0791 /**
0792  * Store geometry and recent files in settings.
0793  */
0794 void Kid3MainWindow::saveConfig()
0795 {
0796   MainWindowConfig& mainWindowConfig = MainWindowConfig::instance();
0797   m_fileOpenRecent->saveEntries(app()->getSettings());
0798   m_shortcutsModel->writeToConfig(app()->getSettings());
0799   mainWindowConfig.setHideToolBar(!m_viewToolBar->isChecked());
0800   mainWindowConfig.setGeometry(saveGeometry());
0801   mainWindowConfig.setWindowState(saveState());
0802   mainWindowConfig.writeToConfig(app()->getSettings());
0803 }
0804 
0805 /**
0806  * Set main window caption.
0807  *
0808  * @param caption caption without application name
0809  * @param modified true if any file is modified
0810  */
0811 void Kid3MainWindow::setWindowCaption(const QString& caption, bool modified)
0812 {
0813   QString cap(caption);
0814   if (modified) {
0815     cap += tr(" [modified]");
0816   }
0817   if (!cap.isEmpty()) {
0818     cap += QLatin1String(" - ");
0819   }
0820   cap += QLatin1String("Kid3");
0821   setWindowTitle(cap);
0822 }
0823 
0824 /**
0825  * Get action for Settings/Auto Hide Tags.
0826  * @return action.
0827  */
0828 QAction* Kid3MainWindow::autoHideTagsAction()
0829 {
0830   return m_settingsAutoHideTags;
0831 }
0832 
0833 /**
0834  * Get action for Settings/Hide Picture.
0835  * @return action.
0836  */
0837 QAction* Kid3MainWindow::showHidePictureAction()
0838 {
0839  return m_settingsShowHidePicture;
0840 }
0841 
0842 /**
0843  * Window is closed.
0844  *
0845  * @param ce close event
0846  */
0847 void Kid3MainWindow::closeEvent(QCloseEvent* ce)
0848 {
0849   if (queryBeforeClosing()) {
0850     ce->accept();
0851   }
0852   else {
0853     ce->ignore();
0854   }
0855 }
0856 
0857 /**
0858  * Read font and style options.
0859  */
0860 void Kid3MainWindow::readFontAndStyleOptions()
0861 {
0862   const MainWindowConfig& mainWindowConfig = MainWindowConfig::instance();
0863   if (mainWindowConfig.useFont() &&
0864       !mainWindowConfig.fontFamily().isEmpty() &&
0865       mainWindowConfig.fontSize() > 0) {
0866     QApplication::setFont(QFont(mainWindowConfig.fontFamily(),
0867                                 mainWindowConfig.fontSize()));
0868   }
0869   if (!mainWindowConfig.style().isEmpty()) {
0870     QApplication::setStyle(mainWindowConfig.style());
0871   }
0872 }
0873 
0874 /**
0875  * Open recent directory.
0876  *
0877  * @param dir directory to open
0878  */
0879 void Kid3MainWindow::slotFileOpenRecentDirectory(const QString& dir)
0880 {
0881   openRecentDirectory(dir);
0882 }
0883 
0884 /**
0885  * Turn status bar on or off.
0886  */
0887 void Kid3MainWindow::slotViewStatusBar()
0888 {
0889   MainWindowConfig::instance().setHideStatusBar(!m_viewStatusBar->isChecked());
0890   setStatusBarVisible(!MainWindowConfig::instance().hideStatusBar());
0891 }
0892 
0893 /**
0894  * Display handbook.
0895  */
0896 void Kid3MainWindow::slotHelpHandbook()
0897 {
0898   ContextHelp::displayHelp();
0899 }
0900 
0901 /**
0902  * Display "About" dialog.
0903  */
0904 void Kid3MainWindow::slotHelpAbout()
0905 {
0906     QMessageBox::about(
0907     this, QLatin1String("Kid3"),
0908     QLatin1String("<big><b>Kid3 " VERSION
0909     "</b></big><br/><br/>") +
0910     tr("Audio Tag Editor") +
0911     QLatin1String("<br/><br/>(c) 2003-" RELEASE_YEAR
0912     " <a href=\"mailto:ufleisch@users.sourceforge.net\">Urs Fleisch</a>"
0913     "<br/><br/>"
0914     "<a href=\"https://kid3.kde.org/\">https://kid3.kde.org</a>"
0915     "<br/>") + tr("License") +
0916     QLatin1String(": <a href=\"http://www.gnu.org/licenses/licenses.html#GPL\">"
0917     "GNU General Public License</a><br/> "));
0918 }
0919 
0920 /**
0921  * Display "About Qt" dialog.
0922  */
0923 void Kid3MainWindow::slotHelpAboutQt()
0924 {
0925   QMessageBox::aboutQt(this, QLatin1String("Kid3"));
0926 }
0927 
0928 /**
0929  * Preferences.
0930  */
0931 void Kid3MainWindow::slotSettingsConfigure()
0932 {
0933   QString caption(tr("Configure - Kid3"));
0934   auto dialog = new ConfigDialog(m_platformTools, this, caption,
0935                                           m_shortcutsModel);
0936   dialog->setConfig();
0937   if (dialog->exec() == QDialog::Accepted) {
0938     dialog->getConfig();
0939     impl()->applyChangedConfiguration();
0940     impl()->applyChangedShortcuts();
0941   }
0942 }
0943 
0944 /**
0945  * Called when session manager wants application to commit its data.
0946  * @param manager session manager
0947  */
0948 void Kid3MainWindow::onCommitDataRequest(QSessionManager& manager)
0949 {
0950   // Make sure that current file is saved even if "load last opened file"
0951   // is not enabled.
0952   if (FileConfig& fileCfg = FileConfig::instance();
0953       !fileCfg.loadLastOpenedFile()) {
0954     fileCfg.setLastOpenedFile(
0955         app()->getFileProxyModel()->filePath(app()->currentOrRootIndex()));
0956   }
0957 
0958   // Ask user if there are unsaved data.
0959   if (manager.allowsInteraction()) {
0960     if (queryBeforeClosing()) {
0961       manager.release();
0962     } else {
0963       manager.cancel();
0964     }
0965   }
0966 }
0967 
0968 /**
0969  * Add user action to shortcuts.
0970  * @param name name of action
0971  * @param action action to add
0972  */
0973 void Kid3MainWindow::onUserActionAdded(const QString& name, QAction* action)
0974 {
0975   action->setObjectName(name);
0976   action->setShortcutContext(Qt::ApplicationShortcut);
0977   m_shortcutsModel->registerAction(action, tr("User Actions"));
0978   addAction(action);
0979 }
0980 
0981 /**
0982  * Remove user action from shortcuts.
0983  * @param name name of action
0984  * @param action action to remove
0985  */
0986 void Kid3MainWindow::onUserActionRemoved(const QString& name, QAction* action)
0987 {
0988   Q_UNUSED(name)
0989   m_shortcutsModel->unregisterAction(action, tr("User Actions"));
0990   removeAction(action);
0991 }