File indexing completed on 2024-05-19 04:56:07

0001 /**
0002  * \file kid3application.h
0003  * Kid3 application logic, independent of GUI.
0004  *
0005  * \b Project: Kid3
0006  * \author Urs Fleisch
0007  * \date 10 Jul 2011
0008  *
0009  * Copyright (C) 2011-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 #pragma once
0028 
0029 #include <QObject>
0030 #include <QPersistentModelIndex>
0031 #include <QScopedPointer>
0032 #include <QItemSelectionModel>
0033 #include "frame.h"
0034 #include "framelist.h"
0035 #include "taggedfilesystemmodel.h"
0036 #include "fileproxymodel.h"
0037 #include "dirproxymodel.h"
0038 #include "frametablemodel.h"
0039 #include "genremodel.h"
0040 #include "downloadclient.h"
0041 #include "batchimporter.h"
0042 #include "dirrenamer.h"
0043 #include "frameeditorobject.h"
0044 #include "taggedfileselection.h"
0045 #include "trackdata.h"
0046 #include "tagsearcher.h"
0047 #include "generalconfig.h"
0048 #include "config.h"
0049 
0050 class QItemSelection;
0051 class QModelIndex;
0052 class QNetworkAccessManager;
0053 class QDir;
0054 class QUrl;
0055 class TaggedFileSystemModel;
0056 class FileProxyModelIterator;
0057 class TrackDataModel;
0058 class ConfigStore;
0059 class PlaylistConfig;
0060 class PlaylistModel;
0061 class TaggedFile;
0062 class IFrameEditor;
0063 class ServerImporter;
0064 class ServerTrackImporter;
0065 class ITaggedFileFactory;
0066 class TextExporter;
0067 class BatchImportProfile;
0068 class Kid3ApplicationTagContext;
0069 class IAbortable;
0070 class ICorePlatformTools;
0071 class IUserCommandProcessor;
0072 class ImageDataProvider;
0073 class FileFilter;
0074 
0075 /**
0076  * Kid3 application logic, independent of GUI.
0077  */
0078 class KID3_CORE_EXPORT Kid3Application : public QObject {
0079   Q_OBJECT
0080   /** File proxy model. */
0081   Q_PROPERTY(FileProxyModel* fileProxyModel READ getFileProxyModel CONSTANT)
0082   /** Directory proxy model. */
0083   Q_PROPERTY(DirProxyModel* dirProxyModel READ getDirProxyModel CONSTANT)
0084   /** File selection model. */
0085   Q_PROPERTY(QItemSelectionModel* fileSelectionModel READ getFileSelectionModel CONSTANT)
0086   /** Directory selection model. */
0087   Q_PROPERTY(QItemSelectionModel* dirSelectionModel READ getDirSelectionModel CONSTANT)
0088   /** Information about selected tagged files. */
0089   Q_PROPERTY(TaggedFileSelection* selectionInfo READ selectionInfo CONSTANT)
0090   /** Root index of opened directory in file proxy model. */
0091   Q_PROPERTY(QModelIndex fileRootIndex READ getRootIndex NOTIFY fileRootIndexChanged)
0092   /** Root index of opened directory in directory proxy model. */
0093   Q_PROPERTY(QModelIndex dirRootIndex READ getDirRootIndex NOTIFY dirRootIndexChanged)
0094   /** Directory name. */
0095   Q_PROPERTY(QString dirName READ getDirName NOTIFY dirNameChanged)
0096   /** Modification state. */
0097   Q_PROPERTY(bool modified READ isModified NOTIFY modifiedChanged)
0098   /** Filtered state. */
0099   Q_PROPERTY(bool filtered READ isFiltered WRITE setFiltered NOTIFY filteredChanged)
0100   /** Number of files which have passed the filter. */
0101   Q_PROPERTY(int filterPassedCount READ filterPassedCount NOTIFY fileFiltered)
0102   /** Total number of files checked by filter. */
0103   Q_PROPERTY(int filterTotalCount READ filterTotalCount NOTIFY fileFiltered)
0104   /** Frame editor. */
0105   Q_PROPERTY(FrameEditorObject* frameEditor READ frameEditor WRITE setFrameEditor
0106              NOTIFY frameEditorChanged)
0107   /** ID to get cover art image. */
0108   Q_PROPERTY(QString coverArtImageId READ coverArtImageId
0109              NOTIFY coverArtImageIdChanged)
0110   /** Directory renamer. */
0111   Q_PROPERTY(DirRenamer* dirRenamer READ getDirRenamer CONSTANT)
0112   /** Batch importer. */
0113   Q_PROPERTY(BatchImporter* batchImporter READ getBatchImporter CONSTANT)
0114   /** Download client */
0115   Q_PROPERTY(DownloadClient* downloadClient READ getDownloadClient CONSTANT)
0116   Q_FLAGS(NumberTrackOption NumberTrackOptions)
0117 public:
0118   /** Destination for downloadImage(). */
0119   enum DownloadImageDestination {
0120     ImageForSelectedFiles,         /**< only for current file */
0121     ImageForAllFilesInDirectory, /**< for all files in directory */
0122     ImageForImportTrackData      /**< for enabled files in m_trackDataModel */
0123   };
0124 
0125   /** Options for numberTracks(). */
0126   enum NumberTrackOption {
0127     NumberTracksEnabled = 1,                     /**< Enable track numbering */
0128     NumberTracksResetCounterForEachDirectory = 2 /**< Reset counter */
0129   };
0130   Q_DECLARE_FLAGS(NumberTrackOptions, NumberTrackOption)
0131 
0132   /**
0133    * Constructor.
0134    * @param platformTools platform tools
0135    * @param parent parent object
0136    */
0137   explicit Kid3Application(ICorePlatformTools* platformTools,
0138                            QObject* parent = nullptr);
0139 
0140   /**
0141    * Destructor.
0142    */
0143   ~Kid3Application() override;
0144 
0145 #ifdef HAVE_QTDBUS
0146   /**
0147    * Activate the D-Bus interface.
0148    * This method shall be called only once at initialization.
0149    */
0150   void activateDbusInterface();
0151 #endif
0152 
0153   /**
0154    * Get platform tools.
0155    * @return platform tools.
0156    */
0157   ICorePlatformTools* getPlatformTools() { return m_platformTools; }
0158 
0159  /**
0160   * Get file system model.
0161   * @return file system model.
0162   */
0163   TaggedFileSystemModel* getFileSystemModel() { return m_fileSystemModel; }
0164 
0165  /**
0166   * Get file proxy model.
0167   * @return file proxy model.
0168   */
0169   FileProxyModel* getFileProxyModel() { return m_fileProxyModel; }
0170 
0171   /**
0172   * Get file proxy model iterator.
0173   * @return file proxy model iterator.
0174    */
0175   FileProxyModelIterator* getFileProxyModelIterator() {
0176     return m_fileProxyModelIterator;
0177   }
0178 
0179  /**
0180   * Get directory proxy model.
0181   * @return directory proxy model.
0182   */
0183   DirProxyModel* getDirProxyModel() { return m_dirProxyModel; }
0184 
0185  /**
0186   * Get track data model.
0187   * @return track data model.
0188   */
0189   TrackDataModel* getTrackDataModel() { return m_trackDataModel; }
0190 
0191   /**
0192    * Get selection model of files.
0193    */
0194   QItemSelectionModel* getFileSelectionModel() { return m_fileSelectionModel; }
0195 
0196   /**
0197    * Get selection model of directories.
0198    */
0199   QItemSelectionModel* getDirSelectionModel() { return m_dirSelectionModel; }
0200 
0201   /**
0202    * Store index of directory from where "directory up" (..) is activated.
0203    * This directory will then be selected in the new (parent) directory.
0204    *
0205    * @param index model index of target directory entered when going up
0206    */
0207   void setDirUpIndex(const QPersistentModelIndex& index) {
0208     m_dirUpIndex = index;
0209   }
0210 
0211   /**
0212    * Get genre model.
0213    * @param tagNr tag number
0214    * @return genre model.
0215    */
0216   GenreModel*  genreModel(Frame::TagNumber tagNr) const { return m_genreModel[tagNr]; }
0217 
0218   /**
0219    * Get frame table model.
0220    * @param tagNr tag number
0221    * @return frame table.
0222    */
0223   FrameTableModel* frameModel(Frame::TagNumber tagNr) { return m_framesModel[tagNr]; }
0224 
0225   /**
0226    * Get selection model of frame table model.
0227    * @param tagNr tag number
0228    * @return selection model.
0229    */
0230   QItemSelectionModel* getFramesSelectionModel(Frame::TagNumber tagNr) {
0231     return m_framesSelectionModel[tagNr];
0232   }
0233 
0234   /**
0235    * Get frame list.
0236    * @param tagNr tag number
0237    * @return frame list.
0238    */
0239   FrameList* getFrameList(Frame::TagNumber tagNr) { return m_framelist[tagNr]; }
0240 
0241   /**
0242    * Get settings.
0243    * @return settings.
0244    */
0245   ISettings* getSettings() const;
0246 
0247   /**
0248    * Get download client.
0249    * @return download client.
0250    */
0251   DownloadClient* getDownloadClient() { return m_downloadClient; }
0252 
0253   /**
0254    * Get text exporter.
0255    * @return text exporter.
0256    */
0257   TextExporter* getTextExporter() { return m_textExporter; }
0258 
0259   /**
0260    * Get available server importers.
0261    * @return list of server importers.
0262    */
0263   QList<ServerImporter*> getServerImporters() { return m_importers; }
0264 
0265   /**
0266    * Get names of available server track importers.
0267    * @return list of server track importer names.
0268    */
0269   Q_INVOKABLE QStringList getServerImporterNames() const;
0270 
0271   /**
0272    * Get available server track importers.
0273    * @return list of server track importers.
0274    */
0275   QList<ServerTrackImporter*> getServerTrackImporters() {
0276     return m_trackImporters;
0277   }
0278 
0279   /**
0280    * Get available user command processors.
0281    * @return list of user command processors.
0282    */
0283   QList<IUserCommandProcessor*> getUserCommandProcessors() {
0284     return m_userCommandProcessors;
0285   }
0286 
0287   /**
0288    * Get tag searcher.
0289    * @return tag searcher.
0290    */
0291   TagSearcher* getTagSearcher() const { return m_tagSearcher; }
0292 
0293   /**
0294    * Get directory renamer.
0295    * @return directory renamer.
0296    */
0297   DirRenamer* getDirRenamer() { return m_dirRenamer; }
0298 
0299   /**
0300    * Get batch importer.
0301    * @return batch importer.
0302    */
0303   BatchImporter* getBatchImporter() { return m_batchImporter; }
0304 
0305   /**
0306    * Get audio player.
0307    * This method will create an audio player if it does not already exist.
0308    * The returned audio player can be deleted after this call, so objects which
0309    * hold a pointer must be deleted before deleteAudioPlayer() is called!
0310    * @return audio player.
0311    */
0312   Q_INVOKABLE QObject* getAudioPlayer();
0313 
0314   /**
0315    * Get context for tag.
0316    * @param tagNr tag number
0317    * @return tag context.
0318    */
0319   Q_INVOKABLE Kid3ApplicationTagContext* tag(Frame::TagNumber tagNr) const {
0320     return m_tagContext[tagNr];
0321   }
0322 
0323   /**
0324    * Get current index in file proxy model or root index if current index is
0325    * invalid.
0326    * @return current index, root index if not valid.
0327    */
0328   QModelIndex currentOrRootIndex() const;
0329 
0330   /**
0331    * Apply configuration changes.
0332    */
0333   Q_INVOKABLE void applyChangedConfiguration();
0334 
0335   /**
0336    * Save settings to the configuration.
0337    */
0338   Q_INVOKABLE void saveConfig();
0339 
0340   /**
0341    * Read settings from the configuration.
0342    */
0343   Q_INVOKABLE void readConfig();
0344 
0345   /**
0346    * Open directory.
0347    * When finished directoryOpened() is emitted, also if false is returned.
0348    *
0349    * @param paths file or directory paths, if multiple paths are given, the
0350    * common directory is opened and the files are selected
0351    * @param fileCheck if true, only open directory if paths exist
0352    *
0353    * @return true if ok.
0354    */
0355   Q_INVOKABLE bool openDirectory(const QStringList& paths, bool fileCheck = false);
0356 
0357   /**
0358    * Get root index of opened directory in file proxy model.
0359    * @return index of directory root.
0360    */
0361   QPersistentModelIndex getRootIndex() const {
0362     return m_fileProxyModelRootIndex;
0363   }
0364 
0365   /**
0366    * Get root index of opened directory in directory proxy model.
0367    * @return index of directory root.
0368    */
0369   QPersistentModelIndex getDirRootIndex() const {
0370     return m_dirProxyModelRootIndex;
0371   }
0372 
0373   /**
0374    * Get directory path of opened directory.
0375    * @return directory path.
0376    */
0377   QString getDirPath() const;
0378 
0379   /**
0380    * Handle drop of URLs.
0381    *
0382    * @param urlList picture, tagged file and folder URLs to handle (if local)
0383    * @param isInternal true if this is an internal drop
0384    */
0385   void dropUrls(const QList<QUrl>& urlList, bool isInternal);
0386 
0387   /**
0388    * Open directory after resetting the file system model.
0389    * When finished directoryOpened() is emitted, also if false is returned.
0390    *
0391    * @param paths file or directory paths, if multiple paths are given, the
0392    * common directory is opened and the files are selected, if empty, the
0393    * currently open directory is reopened
0394    *
0395    * @return true if ok.
0396    */
0397   bool openDirectoryAfterReset(const QStringList& paths = QStringList());
0398 
0399   /**
0400    * Save all changed files.
0401    * longRunningOperationProgress() is emitted while saving files.
0402    *
0403    * @param errorDescriptions if not NULL, a list with error descriptions
0404    * corresponding to the errored files in the returned file list
0405    * is returned here. Null strings are used where no error description
0406    * is available.
0407    *
0408    * @return list of files with error, empty if ok.
0409    */
0410   QStringList saveDirectory(QStringList* errorDescriptions);
0411 
0412   /**
0413    * Save all changed files.
0414    * longRunningOperationProgress() is emitted while saving files.
0415    *
0416    * @return list of files with error, empty if ok.
0417    */
0418   Q_INVOKABLE QStringList saveDirectory();
0419 
0420   /**
0421    * Merge entries of two string lists.
0422    *
0423    * Combine two string lists to a resulting list with all strings from
0424    * @a leftStrs having the corresponding string from @a rightStrs appended
0425    * if available. A @a separator can be given to join the two parts.
0426    * The @a rightStrs can contain fewer elements than @a leftStrs, the
0427    * resulting string will then be only the element from @a leftStrs.
0428    * This function can be used to add details to an error message, e.g.
0429    * mergeStringLists(errorMsgs, errorDescriptions, ": ").
0430    *
0431    * @param leftStrs strings for left part
0432    * @param rightStrs strings for right part
0433    * @param separator separator between left and right parts
0434    * @return string list with combined left and right parts.
0435    */
0436   static QStringList mergeStringLists(
0437       const QStringList& leftStrs, const QStringList& rightStrs,
0438       const QString& separator);
0439 
0440   /**
0441    * Update tags of selected files to contain contents of frame models.
0442    */
0443   Q_INVOKABLE void frameModelsToTags();
0444 
0445   /**
0446    * Update frame models to contain contents of selected files.
0447    * The properties starting with "selection" will be set by this method.
0448    */
0449   Q_INVOKABLE void tagsToFrameModels();
0450 
0451   /**
0452    * Update frame models to contain contents of item selection.
0453    * The properties starting with "selection" will be set by this method.
0454    * @param selected item selection
0455    */
0456   void selectedTagsToFrameModels(const QItemSelection& selected);
0457 
0458   /**
0459    * Access to information about selected tagged files.
0460    * @return selection information.
0461    */
0462   TaggedFileSelection* selectionInfo() const { return m_selection; }
0463 
0464   /**
0465    * Import.
0466    *
0467    * @param tagMask tag mask
0468    * @param path    path of file, "clipboard" for import from clipboard
0469    * @param fmtIdx  index of format
0470    *
0471    * @return true if ok.
0472    */
0473   Q_INVOKABLE bool importTags(Frame::TagVersion tagMask, const QString& path,
0474                               int fmtIdx);
0475 
0476   /**
0477    * Import from tags.
0478    *
0479    * @param tagMask tag mask
0480    * @param source format to get source text from tags
0481    * @param extraction regular expression with frame names and captures to
0482    * extract from source text
0483    */
0484   Q_INVOKABLE void importFromTags(Frame::TagVersion tagMask,
0485                                   const QString& source,
0486                                   const QString& extraction);
0487 
0488   /**
0489    * Import from tags on selected files.
0490    *
0491    * @param tagMask tag mask
0492    * @param source format to get source text from tags
0493    * @param extraction regular expression with frame names and captures to
0494    * extract from source text
0495    *
0496    * @return extracted values for "%{__return}(.+)", empty if not used.
0497    */
0498   Q_INVOKABLE QStringList importFromTagsToSelection(Frame::TagVersion tagMask,
0499                                                     const QString& source,
0500                                                     const QString& extraction);
0501 
0502   /**
0503    * Export.
0504    *
0505    * @param tagVersion tag version
0506    * @param path   path of file, "clipboard" for export to clipboard
0507    * @param fmtIdx index of format
0508    *
0509    * @return true if ok.
0510    */
0511   Q_INVOKABLE bool exportTags(Frame::TagVersion tagVersion,
0512                               const QString& path, int fmtIdx);
0513 
0514   /**
0515    * Write playlist according to playlist configuration.
0516    *
0517    * @param cfg playlist configuration to use
0518    *
0519    * @return true if ok.
0520    */
0521   bool writePlaylist(const PlaylistConfig& cfg);
0522 
0523   /**
0524    * Write empty playlist.
0525    * @param cfg playlist configuration to use
0526    * @param fileName file name for playlist
0527    * @return true if ok.
0528    */
0529   bool writeEmptyPlaylist(const PlaylistConfig& cfg, const QString& fileName);
0530 
0531   /**
0532    * Write playlist using current playlist configuration.
0533    *
0534    * @return true if ok.
0535    */
0536   Q_INVOKABLE bool writePlaylist();
0537 
0538   /**
0539    * Get items of a playlist.
0540    * @param path path to playlist file
0541    * @return list of absolute paths to playlist items.
0542    */
0543   Q_INVOKABLE QStringList getPlaylistItems(const QString& path);
0544 
0545   /**
0546    * Set items of a playlist.
0547    * @param path path to playlist file
0548    * @param items list of absolute paths to playlist items
0549    * @return true if ok, false if not all @a items were found and added or
0550    *         saving failed.
0551    */
0552   Q_INVOKABLE bool setPlaylistItems(const QString& path, const QStringList& items);
0553 
0554   /**
0555    * Get playlist model for a play list file.
0556    * @param path path to playlist file
0557    * @return playlist model.
0558    */
0559   PlaylistModel* playlistModel(const QString& path);
0560 
0561   /**
0562    * Check if any playlist model has unsaved modifications.
0563    * @return true if there is a modified playlist model.
0564    */
0565   bool hasModifiedPlaylistModel() const;
0566 
0567   /**
0568    * Save all modified playlist models.
0569    */
0570   void saveModifiedPlaylistModels();
0571 
0572   /**
0573    * Perform rename actions and change application directory afterwards if it
0574    * was renamed.
0575    *
0576    * @return error messages, null string if no error occurred.
0577    */
0578   Q_INVOKABLE QString performRenameActions();
0579 
0580   /**
0581    * Reset the file system model and then try to perform the rename actions.
0582    * On Windows, renaming directories fails when they have a subdirectory which
0583    * is open in the file system model. This method can be used to retry in such
0584    * a situation.
0585    */
0586   void tryRenameActionsAfterReset();
0587 
0588   /**
0589    * Reset the file system model and then try to rename a file.
0590    * On Windows, renaming directories fails when they have a subdirectory which
0591    * is open in the file system model. This method can be used to retry in such
0592    * a situation.
0593    *
0594    * @param oldName old file name
0595    * @param newName new file name
0596    */
0597   void tryRenameAfterReset(const QString& oldName, const QString& newName);
0598 
0599   /**
0600    * Set the directory name from the tags.
0601    * The directory must not have modified files.
0602    * renameActionsScheduled() is emitted when the rename actions have been
0603    * scheduled. Then performRenameActions() has to be called to effectively
0604    * rename the directory.
0605    *
0606    * @param tagMask tag mask
0607    * @param format  directory name format
0608    * @param create  true to create, false to rename
0609    *
0610    * @return true if ok.
0611    */
0612   Q_INVOKABLE bool renameDirectory(Frame::TagVersion tagMask,
0613                        const QString& format, bool create);
0614 
0615   /**
0616    * Number tracks in selected files of directory.
0617    *
0618    * @param nr start number
0619    * @param total total number of tracks, used if >0
0620    * @param tagVersion determines on which tags the numbers are set
0621    * @param options options for numbering operation
0622    */
0623   Q_INVOKABLE void numberTracks(int nr, int total, Frame::TagVersion tagVersion,
0624                                 Kid3Application::NumberTrackOptions options = {});
0625 
0626   /**
0627    * Set track data with tagged files of directory.
0628    *
0629    * @param tagVersion tag version
0630    * @param trackDataList is filled with track data
0631    */
0632   void filesToTrackData(Frame::TagVersion tagVersion,
0633                         ImportTrackDataVector& trackDataList);
0634 
0635   /**
0636    * Set track data model with tagged files of directory.
0637    *
0638    * @param tagVersion tag version
0639    */
0640   void filesToTrackDataModel(Frame::TagVersion tagVersion);
0641 
0642   /**
0643    * Set tagged files of directory from track data model.
0644    *
0645    * @param tagVersion tags to set
0646    */
0647   void trackDataModelToFiles(Frame::TagVersion tagVersion);
0648 
0649   /**
0650    * Download an image file.
0651    *
0652    * @param url  URL of image
0653    * @param dest specifies affected files
0654    */
0655   void downloadImage(const QUrl& url, DownloadImageDestination dest);
0656 
0657   /**
0658    * Download an image file.
0659    *
0660    * @param url URL of image
0661    * @param allFilesInDir true to add the image to all files in the directory
0662    */
0663   Q_INVOKABLE void downloadImage(const QString& url, bool allFilesInDir);
0664 
0665   /**
0666    * Get value of frame.
0667    * To get binary data like a picture, the name of a file to write can be
0668    * added after the @a name, e.g. "Picture:/path/to/file".
0669    *
0670    * @param tagMask tag bit (1 for tag 1, 2 for tag 2)
0671    * @param name    name of frame (e.g. "artist")
0672    *
0673    * @return value of frame.
0674    */
0675   Q_INVOKABLE QString getFrame(Frame::TagVersion tagMask,
0676                                const QString& name) const;
0677 
0678   /**
0679    * Get names and values of all frames.
0680    *
0681    * @param tagMask tag bit (1 for tag 1, 2 for tag 2)
0682    *
0683    * @return map containing frame values.
0684    */
0685   Q_INVOKABLE QVariantMap getAllFrames(Frame::TagVersion tagMask) const;
0686 
0687   /**
0688    * Set value of frame.
0689    * For tag 2 (@a tagMask 2), if no frame with @a name exists, a new frame
0690    * is added, if @a value is empty, the frame is deleted.
0691    * To add binary data like a picture, a file can be added after the
0692    * @a name, e.g. "Picture:/path/to/file".
0693    *
0694    * @param tagMask tag bit (1 for tag 1, 2 for tag 2)
0695    * @param name    name of frame (e.g. "artist")
0696    * @param value   value of frame
0697    *
0698    * @return true if ok.
0699    */
0700   Q_INVOKABLE bool setFrame(Frame::TagVersion tagMask, const QString& name,
0701                             const QString& value);
0702 
0703   /**
0704    * Get data from picture frame.
0705    * @return picture data, empty if not found.
0706    */
0707   Q_INVOKABLE QByteArray getPictureData() const;
0708 
0709   /**
0710    * Set data in picture frame.
0711    * @param data picture data
0712    */
0713   Q_INVOKABLE void setPictureData(const QByteArray& data);
0714 
0715   /**
0716    * Format frames if format while editing is switched on.
0717    *
0718    * @param frames frames
0719    */
0720   void formatFramesIfEnabled(FrameCollection& frames) const;
0721 
0722   /**
0723    * Add picture on drop.
0724    *
0725    * @param frame dropped picture frame
0726    */
0727   void dropImage(Frame* frame);
0728 
0729   /**
0730    * Handle URL on drop.
0731    *
0732    * @param url dropped URL.
0733    */
0734   void dropUrl(const QUrl& url);
0735 
0736   /**
0737    * Get number of tracks in current directory.
0738    *
0739    * @return number of tracks, 0 if not found.
0740    */
0741   Q_INVOKABLE int getTotalNumberOfTracksInDir() const;
0742 
0743   /**
0744    * Get name of selected file.
0745    *
0746    * @return absolute file name, ends with "/" if it is a directory.
0747    */
0748   QString getFileNameOfSelectedFile();
0749 
0750   /**
0751    * Create a filter string for the file dialog.
0752    * The filter string contains entries for all supported types.
0753    *
0754    * @return filter string.
0755    */
0756   Q_INVOKABLE QString createFilterString() const;
0757 
0758 
0759   /**
0760    * Remove the file filter if necessary to open the files.
0761    * @param filePaths paths to files or directories
0762    */
0763   void resetFileFilterIfNotMatching(const QStringList& filePaths);
0764 
0765   /**
0766    * Get image destination set by downloadImage().
0767    * @return image destination.
0768    */
0769   DownloadImageDestination getDownloadImageDestination() const {
0770     return m_downloadImageDest;
0771   }
0772 
0773   /**
0774    * Check modification state.
0775    *
0776    * @return true if a file is modified.
0777    */
0778   bool isModified() const;
0779 
0780   /**
0781    * Set filter state.
0782    *
0783    * @param val true if list is filtered
0784    */
0785   void setFiltered(bool val);
0786 
0787   /**
0788    * Check filter state.
0789    *
0790    * @return true if list is filtered.
0791    */
0792   bool isFiltered() const { return m_filtered; }
0793 
0794   /**
0795    * Get number of files which have passed the filter.
0796    *
0797    * This number is only valid if isFiltered() is true.
0798    *
0799    * @return number of files which have passed the filter.
0800    */
0801   int filterPassedCount() const { return m_filterPassed; }
0802 
0803   /**
0804    * Get total number of files which have been checked by the filter.
0805    *
0806    * This number is only valid if isFiltered() is true.
0807    *
0808    * @return total number of files checked by filter.
0809    */
0810   int filterTotalCount() const { return m_filterTotal; }
0811 
0812   /**
0813    * Get the selected file.
0814    *
0815    * @return the selected file,
0816    *         0 if not exactly one file is selected
0817    */
0818   TaggedFile* getSelectedFile();
0819 
0820   /**
0821    * Get the stored current selection.
0822    * @return stored selection.
0823    */
0824   const QList<QPersistentModelIndex>& getCurrentSelection() const {
0825     return m_currentSelection;
0826   }
0827 
0828   /**
0829    * Update the stored current selection with the list of all selected items.
0830    */
0831   void updateCurrentSelection();
0832 
0833   /**
0834    * Get directory name.
0835    * @return directory.
0836    */
0837   QString getDirName() const { return m_dirName; }
0838 
0839   /**
0840    * Get frame editor set with setFrameEditor().
0841    * @return frame editor, null if no frame editor is set
0842    */
0843   FrameEditorObject* frameEditor() const { return m_frameEditor; }
0844 
0845   /**
0846    * Set a frame editor object to act as the frame editor.
0847    * @param frameEditor frame editor object, null to disable
0848    */
0849   void setFrameEditor(FrameEditorObject* frameEditor);
0850 
0851   /**
0852    * Remove frame editor.
0853    * Has to be called in the destructor of the frame editor to avoid a dangling
0854    * pointer to a deleted object.
0855    * @param frameEditor frame editor
0856    */
0857   void removeFrameEditor(const IFrameEditor* frameEditor);
0858 
0859   /**
0860    * Get ID to get cover art image.
0861    * @return ID for cover art image.
0862    */
0863   QString coverArtImageId() const { return m_coverArtImageId; }
0864 
0865   /**
0866    * Set the image provider.
0867    * @param imageProvider image provider
0868    */
0869   void setImageProvider(ImageDataProvider* imageProvider);
0870 
0871   /**
0872    * Get the numbers of the selected rows in a list suitable for scripting.
0873    * @return list with row numbers.
0874    */
0875   Q_INVOKABLE QVariantList getFileSelectionRows() const;
0876 
0877   /**
0878    * Set the file selection from a list of model indexes.
0879    * @param indexes list of model indexes suitable for scripting
0880    */
0881   Q_INVOKABLE void setFileSelectionIndexes(const QVariantList& indexes);
0882 
0883   /**
0884    * Get paths to all selected files.
0885    * @param onlyTaggedFiles only consider tagged files
0886    * @return list of absolute file paths.
0887    */
0888   Q_INVOKABLE QStringList getSelectedFilePaths(bool onlyTaggedFiles = true)
0889   const;
0890 
0891   /**
0892    * Set picture data for image provider.
0893    * @param picture picture data
0894    */
0895   Q_INVOKABLE void setCoverArtImageData(const QByteArray& picture);
0896 
0897   /**
0898    * Open a file select dialog to get a file name.
0899    * For script support, is only supported when a GUI is available.
0900    * @param caption dialog caption
0901    * @param dir working directory
0902    * @param filter file type filter
0903    * @param saveFile true to open a save file dialog
0904    * @return selected file, empty if canceled.
0905    */
0906   Q_INVOKABLE QString selectFileName(
0907       const QString& caption = QString(), const QString& dir = QString(),
0908       const QString& filter = QString(), bool saveFile = false);
0909 
0910   /**
0911    * Open a file select dialog to get a directory name.
0912    * For script support, is only supported when a GUI is available.
0913    * @param caption dialog caption
0914    * @param dir working directory
0915    * @return selected directory, empty if canceled.
0916    */
0917   Q_INVOKABLE QString selectDirName(
0918       const QString& caption = QString(), const QString& dir = QString());
0919 
0920   /**
0921    * Check if application is running with a graphical user interface.
0922    * @return true if application has a GUI.
0923    */
0924   Q_INVOKABLE bool hasGui() const;
0925 
0926   /**
0927    * Notify the tagged file factories about the changed configuration.
0928    */
0929   static void notifyConfigurationChange();
0930 
0931   /**
0932    * Find directory containing plugins.
0933    * @param pluginsDir the plugin directory is returned here
0934    * @return true if found.
0935    */
0936   static bool findPluginsDirectory(QDir& pluginsDir);
0937 
0938   /**
0939    * Set fallback path for directory containing plugins.
0940    * @param path path to be searched for plugins if they are not found at the
0941    * standard location relative to the application directory
0942    */
0943   static void setPluginsPathFallback(const QString& path);
0944 
0945   /**
0946    * Load plugins.
0947    * @return list of plugin instances.
0948    */
0949   static QObjectList loadPlugins();
0950 
0951 public slots:
0952   /**
0953    * Open directory or add pictures on drop.
0954    *
0955    * @param paths paths of directories or files in directory
0956    */
0957   void openDrop(const QStringList& paths);
0958 
0959   /**
0960    * Handle drop of URLs.
0961    *
0962    * @param urlList picture, tagged file and folder URLs to handle (if local)
0963    */
0964   void openDropUrls(const QList<QUrl>& urlList);
0965 
0966   /**
0967    * Unload all tags.
0968    * The tags of all files which are not modified or selected are freed to
0969    * reclaim their memory.
0970    */
0971   void unloadAllTags();
0972 
0973   /**
0974    * Revert file modifications.
0975    * Acts on selected files or all files if no file is selected.
0976    */
0977   void revertFileModifications();
0978 
0979   /**
0980    * Set name of selected file.
0981    * Exactly one file has to be selected.
0982    *
0983    * @param name file name.
0984    */
0985   void setFileNameOfSelectedFile(const QString& name);
0986 
0987   /**
0988    * Apply filename format.
0989    */
0990   void applyFilenameFormat();
0991 
0992   /**
0993    * Apply tag format.
0994    */
0995   void applyTagFormat();
0996 
0997   /**
0998    * Apply text encoding.
0999    * Set the text encoding selected in the settings Tags/ID3v2/Text encoding
1000    * for all selected files which have an ID3v2 tag.
1001    */
1002   void applyTextEncoding();
1003 
1004   /**
1005    * Convert ID3v2.3 to ID3v2.4 tags.
1006    */
1007   void convertToId3v24();
1008 
1009   /**
1010    * Convert ID3v2.4 to ID3v2.3 tags.
1011    */
1012   void convertToId3v23();
1013 
1014   /**
1015    * Copy tags into copy buffer.
1016    *
1017    * @param tagMask tag bit (1 for tag 1, 2 for tag 2)
1018    */
1019   void copyTags(Frame::TagVersion tagMask);
1020 
1021   /**
1022    * Paste from copy buffer to tags.
1023    *
1024    * @param tagMask tag bit (1 for tag 1, 2 for tag 2)
1025    */
1026   void pasteTags(Frame::TagVersion tagMask);
1027 
1028   /**
1029    * Set tag from other tag.
1030    *
1031    * @param tagMask tag bit (1 for tag 1, 2 for tag 2)
1032    */
1033   void copyToOtherTag(Frame::TagVersion tagMask);
1034 
1035   /**
1036    * Copy from a tag to another tag.
1037    * @param srcTagNr source tag number
1038    * @param dstTagNr destination tag number
1039    */
1040   void copyTag(Frame::TagNumber srcTagNr, Frame::TagNumber dstTagNr);
1041 
1042   /**
1043    * Remove tags in selected files.
1044    *
1045    * @param tagMask tag bit (1 for tag 1, 2 for tag 2)
1046    */
1047   void removeTags(Frame::TagVersion tagMask);
1048 
1049   /**
1050    * Set tags according to filename.
1051    *
1052    * @param tagMask tag bit (1 for tag 1, 2 for tag 2)
1053    */
1054   void getTagsFromFilename(Frame::TagVersion tagMask);
1055 
1056   /**
1057    * Set filename according to tags.
1058    * If a single file is selected the tags in the GUI controls
1059    * are used, else the tags in the multiple selected files.
1060    *
1061    * @param tagVersion tag version
1062    */
1063   void getFilenameFromTags(Frame::TagVersion tagVersion);
1064 
1065   /**
1066    * Edit selected frame.
1067    * @param tagNr tag number
1068    */
1069   void editFrame(Frame::TagNumber tagNr);
1070 
1071   /**
1072    * Delete selected frame.
1073    * @param tagNr tag number
1074    * @param frameName name of frame to delete, empty to delete selected frame
1075    * @param index 0 for first frame with @a frameName, 1 for second, etc.
1076    */
1077   void deleteFrame(Frame::TagNumber tagNr,
1078                    const QString& frameName = QString(), int index = 0);
1079 
1080   /**
1081    * Select a frame type and add such a frame to the frame list.
1082    * @param tagNr tag number
1083    */
1084   void selectAndAddFrame(Frame::TagNumber tagNr);
1085 
1086   /**
1087    * Edit a picture frame if one exists or add a new one.
1088    */
1089   void editOrAddPicture();
1090 
1091   /**
1092    * Add a downloaded image.
1093    *
1094    * @param data     HTTP response of download
1095    * @param mimeType MIME type of data
1096    * @param url      URL of downloaded data
1097    */
1098   void imageDownloaded(const QByteArray& data,
1099                        const QString& mimeType, const QString& url);
1100 
1101   /**
1102    * Set the first file as the current file.
1103    *
1104    * @param select true to select the file
1105    * @param onlyTaggedFiles only consider tagged files
1106    *
1107    * @return true if a file exists.
1108    */
1109   bool firstFile(bool select = true, bool onlyTaggedFiles = false);
1110 
1111   /**
1112    * Set the next file as the current file.
1113    *
1114    * @param select true to select the file
1115    * @param onlyTaggedFiles only consider tagged files
1116    *
1117    * @return true if a next file exists.
1118    */
1119   bool nextFile(bool select = true, bool onlyTaggedFiles = false);
1120 
1121   /**
1122    * Set the previous file as the current file.
1123    *
1124    * @param select true to select the file
1125    * @param onlyTaggedFiles only consider tagged files
1126    *
1127    * @return true if a previous file exists.
1128    */
1129   bool previousFile(bool select = true, bool onlyTaggedFiles = false);
1130 
1131   /**
1132    * Select or deselect the current file.
1133    *
1134    * @param select true to select the file, false to deselect it
1135    *
1136    * @return true if a current file exists.
1137    */
1138   bool selectCurrentFile(bool select = true);
1139 
1140   /**
1141    * Select all files.
1142    */
1143   void selectAllFiles();
1144 
1145   /**
1146    * Deselect all files.
1147    */
1148   void deselectAllFiles();
1149 
1150   /**
1151    * Select all files in the current directory.
1152    */
1153   void selectAllInDirectory();
1154 
1155   /**
1156    * Invert current selection.
1157    */
1158   void invertSelection();
1159 
1160   /**
1161    * Set a specific file as the current file.
1162    *
1163    * @param filePath path to file
1164    * @param select true to select the file
1165    *
1166    * @return true if file exists.
1167    */
1168   bool selectFile(const QString& filePath, bool select = true);
1169 
1170   /**
1171    * Fetch entries of directory if not already fetched.
1172    * This works like FileList::expand(), but without expanding tree view
1173    * items and independent of the GUI. The processing is done in the background
1174    * by FileSystemModel, so the fetched items are not immediately available
1175    * after calling this method.
1176    *
1177    * @param index index of directory item
1178    */
1179   void fetchDirectory(const QModelIndex& index);
1180 
1181   /**
1182    * Fetch entries of directory and toggle expanded state if GUI available.
1183    * @param index index of directory item
1184    */
1185   void expandDirectory(const QModelIndex& index);
1186 
1187   /**
1188    * Expand the whole file list if GUI available.
1189    */
1190   void requestExpandFileList();
1191 
1192   /**
1193    * Called when operation for requestExpandFileList() is finished.
1194    */
1195   void notifyExpandFileListFinished();
1196 
1197   /**
1198    * Process change of selection.
1199    * The GUI is signaled to update the current selection and the controls.
1200    * @param selected selected items
1201    * @param deselected deselected items
1202    */
1203   void fileSelected(const QItemSelection& selected,
1204                     const QItemSelection& deselected);
1205 
1206   /**
1207    * Search in tags for a given text.
1208    * @param params search parameters
1209    */
1210   void findText(const TagSearcher::Parameters& params);
1211 
1212   /**
1213    * Replace found text.
1214    * @param params search parameters
1215    */
1216   void replaceText(const TagSearcher::Parameters& params);
1217 
1218   /**
1219    * Replace all occurrences.
1220    * @param params search parameters
1221    */
1222   void replaceAll(const TagSearcher::Parameters& params);
1223 
1224   /**
1225    * Schedule actions to rename a directory.
1226    * When finished renameActionsScheduled() is emitted.
1227    */
1228   void scheduleRenameActions();
1229 
1230   /**
1231    * Apply a file filter.
1232    *
1233    * @param fileFilter filter to apply.
1234    */
1235   void applyFilter(FileFilter& fileFilter);
1236 
1237   /**
1238    * Apply a file filter.
1239    *
1240    * @param expression filter expression
1241    */
1242   void applyFilter(const QString& expression);
1243 
1244   /**
1245    * Abort expression file filter.
1246    */
1247   void abortFilter();
1248 
1249   /**
1250    * Perform a batch import for the selected directories.
1251    * @param profile batch import profile
1252    * @param tagVersion import destination tag versions
1253    */
1254   void batchImport(const BatchImportProfile& profile,
1255                    Frame::TagVersion tagVersion);
1256 
1257   /**
1258    * Perform a batch import for the selected directories.
1259    * @param profileName batch import profile name
1260    * @param tagVersion import destination tag versions
1261    * @return true if profile with @a profileName found.
1262    */
1263   bool batchImport(const QString& profileName, Frame::TagVersion tagVersion);
1264 
1265   /**
1266    * Play audio file.
1267    */
1268   void playAudio();
1269 
1270   /**
1271    * Show play tool bar.
1272    */
1273   void showAudioPlayer();
1274 
1275 #ifdef HAVE_QTDBUS
1276   /**
1277    * Activate the MPRIS D-Bus Interface if not already active.
1278    */
1279   void activateMprisInterface();
1280 
1281   /**
1282    * Deactivate the MPRIS D-Bus Interface if it is active.
1283    */
1284   void deactivateMprisInterface();
1285 #endif
1286 
1287   /**
1288    * Update state when file is about to be played.
1289    * @param filePath path to file
1290    */
1291   void onAboutToPlay(const QString& filePath);
1292 
1293   /**
1294    * Close the file handle of a tagged file.
1295    * @param filePath path to file
1296    */
1297   void closeFileHandle(const QString& filePath);
1298 
1299 signals:
1300   /**
1301    * Emitted when the file proxy model root index changes.
1302    * @param index new root index
1303    */
1304   void fileRootIndexChanged(const QModelIndex& index);
1305 
1306   /**
1307    * Emitted when the directory proxy model root index changes.
1308    * @param index new root index
1309    */
1310   void dirRootIndexChanged(const QModelIndex& index);
1311 
1312   /**
1313    * Emitted when the directory has been opened, the file and directory proxy
1314    * model root indexes changed and the selection updated.
1315    */
1316   void directoryOpened();
1317 
1318   /**
1319    * Emitted when a confirmed opening of a directory or file is requested.
1320    * @param paths directory or file paths
1321    */
1322   void confirmedOpenDirectoryRequested(const QStringList& paths);
1323 
1324   /**
1325    * Emitted before an operation on the selected files is performed.
1326    * The GUI should update the files of the current selection when
1327    * receiving this signal.
1328    */
1329   void fileSelectionUpdateRequested();
1330 
1331   /**
1332    * Emitted after an operation on the selected files has been performed.
1333    * The GUI should update its controls from the tags in the files when
1334    * receiving this signal.
1335    */
1336   void selectedFilesUpdated();
1337 
1338   /**
1339    * Emitted after the file selection is changed.
1340    * The GUI should update its controls from the tags of the new file selection
1341    * when receiving this signal.
1342    * @param selected selected items
1343    * @param deselected deselected items
1344    */
1345   void selectedFilesChanged(const QItemSelection& selected,
1346                             const QItemSelection& deselected);
1347 
1348   /**
1349    * Emitted after a frame of a tagged file has been modified.
1350    * The GUI should update the corresponding controls when receiving this
1351    * signal.
1352    *
1353    * @param taggedFile tagged file with modified frame
1354    * @param tagNr tag number
1355    */
1356   void frameModified(TaggedFile* taggedFile, Frame::TagNumber tagNr);
1357 
1358   /**
1359    * Emitted when modification state is changed.
1360    * @param modified true if any file is modified
1361    * @see isModified()
1362    */
1363   void modifiedChanged(bool modified);
1364 
1365   /**
1366    * Emitted when filtered state is changed.
1367    * @param filtered true if file list is filtered
1368    * @see isFiltered(), setFiltered()
1369    */
1370   void filteredChanged(bool filtered);
1371 
1372   /**
1373    * Emitted when the directory name is changed.
1374    * @param name current directory name
1375    */
1376   void dirNameChanged(const QString& name);
1377 
1378   /**
1379    * Emitted when a file is filtered.
1380    * @param type filter event type, enum FileFilter::FilterEventType
1381    * @param fileName name of filtered file
1382    * @param passed number of files which passed the filter
1383    * @param total total number of files checked
1384    */
1385   void fileFiltered(int type, const QString& fileName, int passed, int total);
1386 
1387   /**
1388    * Emitted before an audio file is played.
1389    * The GUI can display a player when receiving this signal.
1390    */
1391   void aboutToPlayAudio();
1392 
1393   /**
1394    * Emitted when all rename actions have been scheduled.
1395    * @see scheduleRenameActions()
1396    */
1397   void renameActionsScheduled();
1398 
1399   /**
1400    * Emitted to request toggling of the expanded state of a directory in the
1401    * file list.
1402    * @param index index of directory item
1403    */
1404   void toggleExpandedRequested(const QModelIndex& index);
1405 
1406   /**
1407    * Emitted to request expanding of all directories in the file list.
1408    */
1409   void expandFileListRequested();
1410 
1411   /**
1412    * Emitted when operation requested by requestExpandFileList()
1413    * (signal expandFileListRequested()) is finished.
1414    */
1415   void expandFileListFinished();
1416 
1417   /**
1418    * Emitted when the file selection is changed.
1419    * @see getFileSelectionRows()
1420    */
1421   void fileSelectionChanged();
1422 
1423   /**
1424    * Emitted when a new cover art image is available
1425    * @param id ID of image.
1426    */
1427   void coverArtImageIdChanged(const QString& id);
1428 
1429   /**
1430    * Emitted when the frame editor is changed.
1431    */
1432   void frameEditorChanged();
1433 
1434   /**
1435    * Emitted to report progress about a long running operation.
1436    *
1437    * This signal is used to report different states of a long running operation.
1438    * - Operation is started: done is -1,
1439    * - Operation is finished: done == total and total is not 0,
1440    * - Operation in progress: done < total or both done and total are 0
1441    *
1442    * @param name name of operation
1443    * @param done amount of work done
1444    * @param total total amount of work
1445    * @param abort if not 0, can be set to true to abort the operation
1446    */
1447   void longRunningOperationProgress(const QString& name, int done, int total,
1448                                     bool* abort);
1449 
1450 private slots:
1451   /**
1452    * Apply file filter after the file system model has been reset.
1453    */
1454   void applyFilterAfterReset();
1455 
1456   /**
1457    * Apply single file to file filter.
1458    *
1459    * @param index index of file in file proxy model
1460    */
1461   void filterNextFile(const QPersistentModelIndex& index);
1462 
1463   /**
1464    * Apply single file to batch import.
1465    *
1466    * @param index index of file in file proxy model
1467    */
1468   void batchImportNextFile(const QPersistentModelIndex& index);
1469 
1470   /**
1471    * Schedule rename action for a file.
1472    *
1473    * @param index index of file in file proxy model
1474    */
1475   void scheduleNextRenameAction(const QPersistentModelIndex& index);
1476 
1477   /**
1478    * Perform rename actions after the file system model has been reset.
1479    */
1480   void performRenameActionsAfterReset();
1481 
1482   /**
1483    * Rename after the file system model has been reset.
1484    */
1485   void renameAfterReset();
1486 
1487   /**
1488    * Update selection and emit signals when directory is opened.
1489    */
1490   void onDirectoryOpened();
1491 
1492   /**
1493    * Called when the gatherer thread has finished to load the directory.
1494    */
1495   void onDirectoryLoaded();
1496 
1497   /**
1498    * Called when a frame is edited.
1499    * @param frame edited frame, 0 if canceled
1500    */
1501   void onFrameEdited(const Frame* frame);
1502 
1503   /**
1504    * Called when a frame is added.
1505    * @param frame added frame, 0 if canceled
1506    * @param tagNr tag number used if slot is not invoked by framelist signal
1507    */
1508   void onFrameAdded(const Frame* frame, Frame::TagNumber tagNr = Frame::Tag_2);
1509 
1510   /**
1511    * Called by framelist when a frame is added.
1512    * Same as onFrameAdded() with default argument, provided for functor-based
1513    * connections.
1514    * @param frame added frame, 0 if canceled
1515    */
1516   void onTag2FrameAdded(const Frame* frame);
1517 
1518   /**
1519    * If an image provider is used, update its picture and change the
1520    * coverArtImageId property if the picture of the selection changed.
1521    * This can be used to change a QML image.
1522    */
1523   void updateCoverArtImageId();
1524 
1525   /**
1526    * Save config when suspended, check intents when activated.
1527    * @param state application state
1528    */
1529   void onApplicationStateChanged(Qt::ApplicationState state);
1530 
1531 private:
1532   /**
1533    * Load and initialize plugins depending on configuration.
1534    */
1535   void initPlugins();
1536 
1537   /**
1538    * Check type of a loaded plugin and register it.
1539    * @param plugin instance returned by plugin loader
1540    */
1541   void checkPlugin(QObject* plugin);
1542 
1543   /**
1544    * Update frame models to contain contents of selected files.
1545    * @param indexes tagged file indexes
1546    * @param startSelection true if a new selection is started, false to add to
1547    * the existing selection
1548    * @return true if ok, false if selection operation is already running.
1549    */
1550   bool addTaggedFilesToSelection(
1551       const QList<QPersistentModelIndex>& indexes, bool startSelection);
1552 
1553   /**
1554    * Select a frame type and add such a frame to frame list.
1555    * @param tagNr tag number
1556    * @param frame frame to add, if 0 the user has to select and edit the frame
1557    * @param edit if true and a frame is set, the user can edit the frame before
1558    * it is added
1559    */
1560   void addFrame(Frame::TagNumber tagNr, const Frame* frame, bool edit = false);
1561 
1562   /**
1563    * Open directory or add pictures on drop.
1564    *
1565    * @param paths paths of directories or files in directory
1566    * @param isInternal true if this is an internal drop
1567    */
1568   void dropLocalFiles(const QStringList& paths, bool isInternal);
1569 
1570   /**
1571    * Second stage for applyFilter().
1572    */
1573   void proceedApplyingFilter();
1574 
1575   /**
1576    * Set the coverArtImageId property to a new value.
1577    * This can be used to trigger an update of QML images.
1578    */
1579   void setNextCoverArtImageId();
1580 
1581   void setAllFilesFileFilter();
1582 
1583   ICorePlatformTools* m_platformTools;
1584   /** Configuration */
1585   QScopedPointer<ConfigStore> m_configStore;
1586   /** model of filesystem */
1587   TaggedFileSystemModel* m_fileSystemModel;
1588   FileProxyModel* m_fileProxyModel;
1589   FileProxyModelIterator* m_fileProxyModelIterator;
1590   DirProxyModel* m_dirProxyModel;
1591   QItemSelectionModel* m_fileSelectionModel;
1592   QItemSelectionModel* m_dirSelectionModel;
1593   /** Track data model */
1594   TrackDataModel* m_trackDataModel;
1595   GenreModel* m_genreModel[Frame::Tag_NumValues];
1596   FrameTableModel* m_framesModel[Frame::Tag_NumValues];
1597   QItemSelectionModel* m_framesSelectionModel[Frame::Tag_NumValues];
1598   QMap<QString, PlaylistModel*> m_playlistModels;
1599   /** Frame list */
1600   FrameList* m_framelist[Frame::Tag_NumValues];
1601   /** Tag context */
1602   Kid3ApplicationTagContext* m_tagContext[Frame::Tag_NumValues];
1603   /** Network access manager */
1604   QNetworkAccessManager* m_netMgr;
1605   /** Download client */
1606   DownloadClient* m_downloadClient;
1607   /** Text exporter */
1608   TextExporter* m_textExporter;
1609   /** Tag searcher */
1610   TagSearcher* m_tagSearcher;
1611   /** Directory renamer */
1612   DirRenamer* m_dirRenamer;
1613   /** Batch importer */
1614   BatchImporter* m_batchImporter;
1615   /** Audio player */
1616   QObject* m_player;
1617 #ifdef HAVE_QTDBUS
1618   QString m_mprisServiceName;
1619 #endif
1620   FileFilter* m_expressionFileFilter;
1621   /** Information about selected tagged files */
1622   TaggedFileSelection* m_selection;
1623   /** Affected files to add frame when downloading image */
1624   DownloadImageDestination m_downloadImageDest;
1625   /** Copy buffer */
1626   FrameCollection m_copyTags;
1627   /** Root index in file proxy model */
1628   QPersistentModelIndex m_fileProxyModelRootIndex;
1629   /** Root index in directory proxy model */
1630   QPersistentModelIndex m_dirProxyModelRootIndex;
1631   /** Indexes of opened file in file proxy model */
1632   QList<QPersistentModelIndex> m_fileProxyModelFileIndexes;
1633   /** Importers for different servers */
1634   QList<ServerImporter*> m_importers;
1635   /** Importer for MusicBrainz fingerprints */
1636   QList<ServerTrackImporter*> m_trackImporters;
1637   /** Processors for user commands */
1638   QList<IUserCommandProcessor*> m_userCommandProcessors;
1639   /** Current directory */
1640   QString m_dirName;
1641   /** Stored current selection with the list of all selected items */
1642   QList<QPersistentModelIndex> m_currentSelection;
1643   /** directory from where "directory up" (..) was activated. */
1644   QPersistentModelIndex m_dirUpIndex;
1645 
1646   /* Context for filterNextFile() */
1647   FileFilter* m_fileFilter;
1648   QString m_lastProcessedDirName;
1649   int m_filterPassed;
1650   int m_filterTotal;
1651   /* Context for batchImportNextFile() */
1652   QScopedPointer<BatchImportProfile> m_namedBatchImportProfile;
1653   const BatchImportProfile* m_batchImportProfile;
1654   Frame::TagVersion m_batchImportTagVersion;
1655   QList<ImportTrackDataVector> m_batchImportAlbums;
1656   ImportTrackDataVector m_batchImportTrackDataList;
1657 
1658   /* Context for renameAfterReset() */
1659   QString m_renameAfterResetOldName;
1660   QString m_renameAfterResetNewName;
1661 
1662   /* Context for editFrame() */
1663   TaggedFile* m_editFrameTaggedFile;
1664   QString m_editFrameName;
1665 
1666   /* Context for addFrame() */
1667   TaggedFile* m_addFrameTaggedFile;
1668 
1669   /* Support for frame editor object */
1670   FrameEditorObject* m_frameEditor;
1671   IFrameEditor* m_storedFrameEditor;
1672   /* Support for image provider */
1673   ImageDataProvider* m_imageProvider;
1674   QString m_coverArtImageId;
1675 
1676 #ifdef Q_OS_ANDROID
1677   bool m_pendingIntentsChecked;
1678 #endif
1679 #ifdef HAVE_QTDBUS
1680   /** true if D-Bus is enabled */
1681   bool m_dbusEnabled;
1682 #endif
1683   /** true if list is filtered */
1684   bool m_filtered;
1685   /** true if a selection operation is running */
1686   bool m_selectionOperationRunning;
1687 
1688   /** Fallback for path to search for plugins */
1689   static QString s_pluginsPathFallback;
1690 };
1691 
1692 /**
1693  * Facade to have a uniform interface for different tags.
1694  */
1695 class KID3_CORE_EXPORT Kid3ApplicationTagContext : public QObject {
1696   Q_OBJECT
1697   /** Genre model. */
1698   Q_PROPERTY(GenreModel* genreModel READ genreModel CONSTANT)
1699   /** Frame table model. */
1700   Q_PROPERTY(FrameTableModel* frameModel READ frameModel CONSTANT)
1701   /** Frame selection model. */
1702   Q_PROPERTY(QItemSelectionModel* frameSelectionModel READ frameSelectionModel CONSTANT)
1703   /** Frame list. */
1704   Q_PROPERTY(FrameList* frameList READ frameList CONSTANT)
1705 public:
1706   /**
1707    * Constructor.
1708    * @param app application
1709    * @param tagNr tag number
1710    */
1711   Kid3ApplicationTagContext(Kid3Application* app, Frame::TagNumber tagNr)
1712     : QObject(app), m_app(app), m_tagNr(tagNr),
1713       m_tagVersion(Frame::tagVersionFromNumber(tagNr)) {
1714   }
1715 
1716 public slots:
1717   /**
1718    * Copy tags into copy buffer.
1719    */
1720   void copyTags() { m_app->copyTags(m_tagVersion); }
1721 
1722   /**
1723    * Paste from copy buffer to tags.
1724    */
1725   void pasteTags() { m_app->pasteTags(m_tagVersion); }
1726 
1727   /**
1728    * Copy tags to other tags of selected files.
1729    */
1730   void copyToOtherTag() { m_app->copyToOtherTag(m_tagVersion); }
1731 
1732   /**
1733    * Remove tags in selected files.
1734    */
1735   void removeTags() { m_app->removeTags(m_tagVersion); }
1736 
1737   /**
1738    * Set tags from filename.
1739    */
1740   void getTagsFromFilename() { m_app->getTagsFromFilename(m_tagVersion); }
1741 
1742   /**
1743    * Set filename from tags.
1744    */
1745   void getFilenameFromTags() { m_app->getFilenameFromTags(m_tagVersion); }
1746 
1747   /**
1748    * Edit selected frame of tag.
1749    */
1750   void editFrame() { m_app->editFrame(m_tagNr); }
1751 
1752   /**
1753    * Delete selected frame from tag.
1754    */
1755   void deleteFrame() { m_app->deleteFrame(m_tagNr); }
1756 
1757   /**
1758    * Select a frame type and add such a frame to the frame list.
1759    */
1760   void addFrame() { m_app->selectAndAddFrame(m_tagNr); }
1761 
1762 private:
1763   /**
1764    * Get genre model.
1765    * @return genre model.
1766    */
1767   GenreModel* genreModel() const { return m_app->genreModel(m_tagNr); }
1768 
1769   /**
1770    * Get frame table model.
1771    * @return frame table.
1772    */
1773   FrameTableModel* frameModel() { return m_app->frameModel(m_tagNr); }
1774 
1775   /**
1776    * Get selection model of frame table model.
1777    */
1778   QItemSelectionModel* frameSelectionModel() {
1779     return m_app->getFramesSelectionModel(m_tagNr);
1780   }
1781 
1782   /**
1783    * Get frame list.
1784    */
1785   FrameList* frameList() { return m_app->getFrameList(m_tagNr); }
1786 
1787   Kid3Application* const m_app;
1788   const Frame::TagNumber m_tagNr;
1789   const Frame::TagVersion m_tagVersion;
1790 };