1 /**
2  * \file kid3application.h
3  * Kid3 application logic, independent of GUI.
4  *
5  * \b Project: Kid3
6  * \author Urs Fleisch
7  * \date 10 Jul 2011
8  *
9  * Copyright (C) 2011-2018  Urs Fleisch
10  *
11  * This file is part of Kid3.
12  *
13  * Kid3 is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * Kid3 is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
25  */
26 
27 #pragma once
28 
29 #include <QObject>
30 #include <QPersistentModelIndex>
31 #include <QScopedPointer>
32 #include <QItemSelectionModel>
33 #include "frame.h"
34 #include "framelist.h"
35 #include "fileproxymodel.h"
36 #include "dirproxymodel.h"
37 #include "frametablemodel.h"
38 #include "genremodel.h"
39 #include "downloadclient.h"
40 #include "batchimporter.h"
41 #include "dirrenamer.h"
42 #include "frameeditorobject.h"
43 #include "taggedfileselection.h"
44 #include "trackdata.h"
45 #include "tagsearcher.h"
46 #include "generalconfig.h"
47 #include "config.h"
48 
49 class QItemSelection;
50 class QModelIndex;
51 class QNetworkAccessManager;
52 class QDir;
53 class QUrl;
54 class FileSystemModel;
55 class FileProxyModelIterator;
56 class TrackDataModel;
57 class ConfigStore;
58 class PlaylistConfig;
59 class PlaylistModel;
60 class TaggedFile;
61 class IFrameEditor;
62 class ServerImporter;
63 class ServerTrackImporter;
64 class ITaggedFileFactory;
65 class TextExporter;
66 class BatchImportProfile;
67 class Kid3ApplicationTagContext;
68 class IAbortable;
69 class ICorePlatformTools;
70 class IUserCommandProcessor;
71 class ImageDataProvider;
72 class FileFilter;
73 
74 /**
75  * Kid3 application logic, independent of GUI.
76  */
77 class KID3_CORE_EXPORT Kid3Application : public QObject {
78   Q_OBJECT
79   /** File proxy model. */
80   Q_PROPERTY(FileProxyModel* fileProxyModel READ getFileProxyModel CONSTANT)
81   /** Directory proxy model. */
82   Q_PROPERTY(DirProxyModel* dirProxyModel READ getDirProxyModel CONSTANT)
83   /** File selection model. */
84   Q_PROPERTY(QItemSelectionModel* fileSelectionModel READ getFileSelectionModel CONSTANT)
85   /** Directory selection model. */
86   Q_PROPERTY(QItemSelectionModel* dirSelectionModel READ getDirSelectionModel CONSTANT)
87   /** Information about selected tagged files. */
88   Q_PROPERTY(TaggedFileSelection* selectionInfo READ selectionInfo CONSTANT)
89   /** Root index of opened directory in file proxy model. */
90   Q_PROPERTY(QModelIndex fileRootIndex READ getRootIndex NOTIFY fileRootIndexChanged)
91   /** Root index of opened directory in directory proxy model. */
92   Q_PROPERTY(QModelIndex dirRootIndex READ getDirRootIndex NOTIFY dirRootIndexChanged)
93   /** Directory name. */
94   Q_PROPERTY(QString dirName READ getDirName NOTIFY dirNameChanged)
95   /** Modification state. */
96   Q_PROPERTY(bool modified READ isModified NOTIFY modifiedChanged)
97   /** Filtered state. */
98   Q_PROPERTY(bool filtered READ isFiltered WRITE setFiltered NOTIFY filteredChanged)
99   /** Number of files which have passed the filter. */
100   Q_PROPERTY(int filterPassedCount READ filterPassedCount NOTIFY fileFiltered)
101   /** Total number of files checked by filter. */
102   Q_PROPERTY(int filterTotalCount READ filterTotalCount NOTIFY fileFiltered)
103   /** Frame editor. */
104   Q_PROPERTY(FrameEditorObject* frameEditor READ frameEditor WRITE setFrameEditor
105              NOTIFY frameEditorChanged)
106   /** ID to get cover art image. */
107   Q_PROPERTY(QString coverArtImageId READ coverArtImageId
108              NOTIFY coverArtImageIdChanged)
109   /** Directory renamer. */
110   Q_PROPERTY(DirRenamer* dirRenamer READ getDirRenamer CONSTANT)
111   /** Batch importer. */
112   Q_PROPERTY(BatchImporter* batchImporter READ getBatchImporter CONSTANT)
113   /** Download client */
114   Q_PROPERTY(DownloadClient* downloadClient READ getDownloadClient CONSTANT)
115   Q_FLAGS(NumberTrackOption NumberTrackOptions)
116 public:
117   /** Destination for downloadImage(). */
118   enum DownloadImageDestination {
119     ImageForSelectedFiles,         /**< only for current file */
120     ImageForAllFilesInDirectory, /**< for all files in directory */
121     ImageForImportTrackData      /**< for enabled files in m_trackDataModel */
122   };
123 
124   /** Options for numberTracks(). */
125   enum NumberTrackOption {
126     NumberTracksEnabled = 1,                     /**< Enable track numbering */
127     NumberTracksResetCounterForEachDirectory = 2 /**< Reset counter */
128   };
129   Q_DECLARE_FLAGS(NumberTrackOptions, NumberTrackOption)
130 
131   /**
132    * Constructor.
133    * @param platformTools platform tools
134    * @param parent parent object
135    */
136   explicit Kid3Application(ICorePlatformTools* platformTools,
137                            QObject* parent = nullptr);
138 
139   /**
140    * Destructor.
141    */
142   virtual ~Kid3Application() override;
143 
144 #ifdef HAVE_QTDBUS
145   /**
146    * Activate the D-Bus interface.
147    * This method shall be called only once at initialization.
148    */
149   void activateDbusInterface();
150 #endif
151 
152   /**
153    * Get platform tools.
154    * @return platform tools.
155    */
getPlatformTools()156   ICorePlatformTools* getPlatformTools() { return m_platformTools; }
157 
158  /**
159   * Get file system model.
160   * @return file system model.
161   */
getFileSystemModel()162   FileSystemModel* getFileSystemModel() { return m_fileSystemModel; }
163 
164  /**
165   * Get file proxy model.
166   * @return file proxy model.
167   */
getFileProxyModel()168   FileProxyModel* getFileProxyModel() { return m_fileProxyModel; }
169 
170   /**
171   * Get file proxy model iterator.
172   * @return file proxy model iterator.
173    */
getFileProxyModelIterator()174   FileProxyModelIterator* getFileProxyModelIterator() {
175     return m_fileProxyModelIterator;
176   }
177 
178  /**
179   * Get directory proxy model.
180   * @return directory proxy model.
181   */
getDirProxyModel()182   DirProxyModel* getDirProxyModel() { return m_dirProxyModel; }
183 
184  /**
185   * Get track data model.
186   * @return track data model.
187   */
getTrackDataModel()188   TrackDataModel* getTrackDataModel() { return m_trackDataModel; }
189 
190   /**
191    * Get selection model of files.
192    */
getFileSelectionModel()193   QItemSelectionModel* getFileSelectionModel() { return m_fileSelectionModel; }
194 
195   /**
196    * Get selection model of directories.
197    */
getDirSelectionModel()198   QItemSelectionModel* getDirSelectionModel() { return m_dirSelectionModel; }
199 
200   /**
201    * Store index of directory from where "directory up" (..) is activated.
202    * This directory will then be selected in the new (parent) directory.
203    *
204    * @param index model index of target directory entered when going up
205    */
setDirUpIndex(const QPersistentModelIndex & index)206   void setDirUpIndex(const QPersistentModelIndex& index) {
207     m_dirUpIndex = index;
208   }
209 
210   /**
211    * Get genre model.
212    * @param tagNr tag number
213    * @return genre model.
214    */
genreModel(Frame::TagNumber tagNr)215   GenreModel*  genreModel(Frame::TagNumber tagNr) const { return m_genreModel[tagNr]; }
216 
217   /**
218    * Get frame table model.
219    * @param tagNr tag number
220    * @return frame table.
221    */
frameModel(Frame::TagNumber tagNr)222   FrameTableModel* frameModel(Frame::TagNumber tagNr) { return m_framesModel[tagNr]; }
223 
224   /**
225    * Get selection model of frame table model.
226    * @param tagNr tag number
227    * @return selection model.
228    */
getFramesSelectionModel(Frame::TagNumber tagNr)229   QItemSelectionModel* getFramesSelectionModel(Frame::TagNumber tagNr) {
230     return m_framesSelectionModel[tagNr];
231   }
232 
233   /**
234    * Get frame list.
235    * @param tagNr tag number
236    * @return frame list.
237    */
getFrameList(Frame::TagNumber tagNr)238   FrameList* getFrameList(Frame::TagNumber tagNr) { return m_framelist[tagNr]; }
239 
240   /**
241    * Get settings.
242    * @return settings.
243    */
244   ISettings* getSettings() const;
245 
246   /**
247    * Get download client.
248    * @return download client.
249    */
getDownloadClient()250   DownloadClient* getDownloadClient() { return m_downloadClient; }
251 
252   /**
253    * Get text exporter.
254    * @return text exporter.
255    */
getTextExporter()256   TextExporter* getTextExporter() { return m_textExporter; }
257 
258   /**
259    * Get available server importers.
260    * @return list of server importers.
261    */
getServerImporters()262   QList<ServerImporter*> getServerImporters() { return m_importers; }
263 
264   /**
265    * Get names of available server track importers.
266    * @return list of server track importer names.
267    */
268   Q_INVOKABLE QStringList getServerImporterNames() const;
269 
270   /**
271    * Get available server track importers.
272    * @return list of server track importers.
273    */
getServerTrackImporters()274   QList<ServerTrackImporter*> getServerTrackImporters() {
275     return m_trackImporters;
276   }
277 
278   /**
279    * Get available user command processors.
280    * @return list of user command processors.
281    */
getUserCommandProcessors()282   QList<IUserCommandProcessor*> getUserCommandProcessors() {
283     return m_userCommandProcessors;
284   }
285 
286   /**
287    * Get tag searcher.
288    * @return tag searcher.
289    */
getTagSearcher()290   TagSearcher* getTagSearcher() const { return m_tagSearcher; }
291 
292   /**
293    * Get directory renamer.
294    * @return directory renamer.
295    */
getDirRenamer()296   DirRenamer* getDirRenamer() { return m_dirRenamer; }
297 
298   /**
299    * Get batch importer.
300    * @return batch importer.
301    */
getBatchImporter()302   BatchImporter* getBatchImporter() { return m_batchImporter; }
303 
304   /**
305    * Get audio player.
306    * This method will create an audio player if it does not already exist.
307    * The returned audio player can be deleted after this call, so objects which
308    * hold a pointer must be deleted before deleteAudioPlayer() is called!
309    * @return audio player.
310    */
311   Q_INVOKABLE QObject* getAudioPlayer();
312 
313   /**
314    * Delete audio player.
315    */
316   void deleteAudioPlayer();
317 
318   /**
319    * Get context for tag.
320    * @param tagNr tag number
321    * @return tag context.
322    */
tag(Frame::TagNumber tagNr)323   Q_INVOKABLE Kid3ApplicationTagContext* tag(Frame::TagNumber tagNr) const {
324     return m_tagContext[tagNr];
325   }
326 
327   /**
328    * Get current index in file proxy model or root index if current index is
329    * invalid.
330    * @return current index, root index if not valid.
331    */
332   QModelIndex currentOrRootIndex() const;
333 
334   /**
335    * Apply configuration changes.
336    */
337   Q_INVOKABLE void applyChangedConfiguration();
338 
339   /**
340    * Save settings to the configuration.
341    */
342   Q_INVOKABLE void saveConfig();
343 
344   /**
345    * Read settings from the configuration.
346    */
347   Q_INVOKABLE void readConfig();
348 
349   /**
350    * Open directory.
351    * When finished directoryOpened() is emitted, also if false is returned.
352    *
353    * @param paths file or directory paths, if multiple paths are given, the
354    * common directory is opened and the files are selected
355    * @param fileCheck if true, only open directory if paths exist
356    *
357    * @return true if ok.
358    */
359   Q_INVOKABLE bool openDirectory(const QStringList& paths, bool fileCheck = false);
360 
361   /**
362    * Get root index of opened directory in file proxy model.
363    * @return index of directory root.
364    */
getRootIndex()365   QPersistentModelIndex getRootIndex() const {
366     return m_fileProxyModelRootIndex;
367   }
368 
369   /**
370    * Get root index of opened directory in directory proxy model.
371    * @return index of directory root.
372    */
getDirRootIndex()373   QPersistentModelIndex getDirRootIndex() const {
374     return m_dirProxyModelRootIndex;
375   }
376 
377   /**
378    * Get directory path of opened directory.
379    * @return directory path.
380    */
381   QString getDirPath() const;
382 
383   /**
384    * Handle drop of URLs.
385    *
386    * @param urlList picture, tagged file and folder URLs to handle (if local)
387    * @param isInternal true if this is an internal drop
388    */
389   void dropUrls(const QList<QUrl>& urlList, bool isInternal);
390 
391   /**
392    * Open directory after resetting the file system model.
393    * When finished directoryOpened() is emitted, also if false is returned.
394    *
395    * @param paths file or directory paths, if multiple paths are given, the
396    * common directory is opened and the files are selected, if empty, the
397    * currently open directory is reopened
398    *
399    * @return true if ok.
400    */
401   bool openDirectoryAfterReset(const QStringList& paths = QStringList());
402 
403   /**
404    * Save all changed files.
405    * longRunningOperationProgress() is emitted while saving files.
406    *
407    * @return list of files with error, empty if ok.
408    */
409   Q_INVOKABLE QStringList saveDirectory();
410 
411   /**
412    * Update tags of selected files to contain contents of frame models.
413    */
414   Q_INVOKABLE void frameModelsToTags();
415 
416   /**
417    * Update frame models to contain contents of selected files.
418    * The properties starting with "selection" will be set by this method.
419    */
420   Q_INVOKABLE void tagsToFrameModels();
421 
422   /**
423    * Update frame models to contain contents of item selection.
424    * The properties starting with "selection" will be set by this method.
425    * @param selected item selection
426    */
427   void selectedTagsToFrameModels(const QItemSelection& selected);
428 
429   /**
430    * Access to information about selected tagged files.
431    * @return selection information.
432    */
selectionInfo()433   TaggedFileSelection* selectionInfo() const { return m_selection; }
434 
435   /**
436    * Import.
437    *
438    * @param tagMask tag mask
439    * @param path    path of file, "clipboard" for import from clipboard
440    * @param fmtIdx  index of format
441    *
442    * @return true if ok.
443    */
444   Q_INVOKABLE bool importTags(Frame::TagVersion tagMask, const QString& path,
445                               int fmtIdx);
446 
447   /**
448    * Import from tags.
449    *
450    * @param tagMask tag mask
451    * @param source format to get source text from tags
452    * @param extraction regular expression with frame names and captures to
453    * extract from source text
454    */
455   Q_INVOKABLE void importFromTags(Frame::TagVersion tagMask,
456                                   const QString& source,
457                                   const QString& extraction);
458 
459   /**
460    * Import from tags on selected files.
461    *
462    * @param tagMask tag mask
463    * @param source format to get source text from tags
464    * @param extraction regular expression with frame names and captures to
465    * extract from source text
466    *
467    * @return extracted values for "%{__return}(.+)", empty if not used.
468    */
469   Q_INVOKABLE QStringList importFromTagsToSelection(Frame::TagVersion tagMask,
470                                                     const QString& source,
471                                                     const QString& extraction);
472 
473   /**
474    * Export.
475    *
476    * @param tagVersion tag version
477    * @param path   path of file, "clipboard" for export to clipboard
478    * @param fmtIdx index of format
479    *
480    * @return true if ok.
481    */
482   Q_INVOKABLE bool exportTags(Frame::TagVersion tagVersion,
483                               const QString& path, int fmtIdx);
484 
485   /**
486    * Write playlist according to playlist configuration.
487    *
488    * @param cfg playlist configuration to use
489    *
490    * @return true if ok.
491    */
492   bool writePlaylist(const PlaylistConfig& cfg);
493 
494   /**
495    * Write empty playlist.
496    * @param cfg playlist configuration to use
497    * @param fileName file name for playlist
498    * @return true if ok.
499    */
500   bool writeEmptyPlaylist(const PlaylistConfig& cfg, const QString& fileName);
501 
502   /**
503    * Write playlist using current playlist configuration.
504    *
505    * @return true if ok.
506    */
507   Q_INVOKABLE bool writePlaylist();
508 
509   /**
510    * Get items of a playlist.
511    * @param path path to playlist file
512    * @return list of absolute paths to playlist items.
513    */
514   Q_INVOKABLE QStringList getPlaylistItems(const QString& path);
515 
516   /**
517    * Set items of a playlist.
518    * @param path path to playlist file
519    * @param items list of absolute paths to playlist items
520    * @return true if ok, false if not all @a items were found and added or
521    *         saving failed.
522    */
523   Q_INVOKABLE bool setPlaylistItems(const QString& path, const QStringList& items);
524 
525   /**
526    * Get playlist model for a play list file.
527    * @param path path to playlist file
528    * @return playlist model.
529    */
530   PlaylistModel* playlistModel(const QString& path);
531 
532   /**
533    * Check if any playlist model has unsaved modifications.
534    * @return true if there is a modified playlist model.
535    */
536   bool hasModifiedPlaylistModel() const;
537 
538   /**
539    * Save all modified playlist models.
540    */
541   void saveModifiedPlaylistModels();
542 
543   /**
544    * Perform rename actions and change application directory afterwards if it
545    * was renamed.
546    *
547    * @return error messages, null string if no error occurred.
548    */
549   Q_INVOKABLE QString performRenameActions();
550 
551   /**
552    * Reset the file system model and then try to perform the rename actions.
553    * On Windows, renaming directories fails when they have a subdirectory which
554    * is open in the file system model. This method can be used to retry in such
555    * a situation.
556    */
557   void tryRenameActionsAfterReset();
558 
559   /**
560    * Reset the file system model and then try to rename a file.
561    * On Windows, renaming directories fails when they have a subdirectory which
562    * is open in the file system model. This method can be used to retry in such
563    * a situation.
564    *
565    * @param oldName old file name
566    * @param newName new file name
567    */
568   void tryRenameAfterReset(const QString& oldName, const QString& newName);
569 
570   /**
571    * Set the directory name from the tags.
572    * The directory must not have modified files.
573    * renameActionsScheduled() is emitted when the rename actions have been
574    * scheduled. Then performRenameActions() has to be called to effectively
575    * rename the directory.
576    *
577    * @param tagMask tag mask
578    * @param format  directory name format
579    * @param create  true to create, false to rename
580    *
581    * @return true if ok.
582    */
583   Q_INVOKABLE bool renameDirectory(Frame::TagVersion tagMask,
584                        const QString& format, bool create);
585 
586   /**
587    * Number tracks in selected files of directory.
588    *
589    * @param nr start number
590    * @param total total number of tracks, used if >0
591    * @param tagVersion determines on which tags the numbers are set
592    * @param options options for numbering operation
593    */
594   Q_INVOKABLE void numberTracks(int nr, int total, Frame::TagVersion tagVersion,
595                                 Kid3Application::NumberTrackOptions options = {});
596 
597   /**
598    * Set track data with tagged files of directory.
599    *
600    * @param tagVersion tag version
601    * @param trackDataList is filled with track data
602    */
603   void filesToTrackData(Frame::TagVersion tagVersion,
604                         ImportTrackDataVector& trackDataList);
605 
606   /**
607    * Set track data model with tagged files of directory.
608    *
609    * @param tagVersion tag version
610    */
611   void filesToTrackDataModel(Frame::TagVersion tagVersion);
612 
613   /**
614    * Set tagged files of directory from track data model.
615    *
616    * @param tagVersion tags to set
617    */
618   void trackDataModelToFiles(Frame::TagVersion tagVersion);
619 
620   /**
621    * Download an image file.
622    *
623    * @param url  URL of image
624    * @param dest specifies affected files
625    */
626   void downloadImage(const QUrl& url, DownloadImageDestination dest);
627 
628   /**
629    * Download an image file.
630    *
631    * @param url URL of image
632    * @param allFilesInDir true to add the image to all files in the directory
633    */
634   Q_INVOKABLE void downloadImage(const QString& url, bool allFilesInDir);
635 
636   /**
637    * Get value of frame.
638    * To get binary data like a picture, the name of a file to write can be
639    * added after the @a name, e.g. "Picture:/path/to/file".
640    *
641    * @param tagMask tag bit (1 for tag 1, 2 for tag 2)
642    * @param name    name of frame (e.g. "artist")
643    *
644    * @return value of frame.
645    */
646   Q_INVOKABLE QString getFrame(Frame::TagVersion tagMask,
647                                const QString& name) const;
648 
649   /**
650    * Get names and values of all frames.
651    *
652    * @param tagMask tag bit (1 for tag 1, 2 for tag 2)
653    *
654    * @return map containing frame values.
655    */
656   Q_INVOKABLE QVariantMap getAllFrames(Frame::TagVersion tagMask) const;
657 
658   /**
659    * Set value of frame.
660    * For tag 2 (@a tagMask 2), if no frame with @a name exists, a new frame
661    * is added, if @a value is empty, the frame is deleted.
662    * To add binary data like a picture, a file can be added after the
663    * @a name, e.g. "Picture:/path/to/file".
664    *
665    * @param tagMask tag bit (1 for tag 1, 2 for tag 2)
666    * @param name    name of frame (e.g. "artist")
667    * @param value   value of frame
668    *
669    * @return true if ok.
670    */
671   Q_INVOKABLE bool setFrame(Frame::TagVersion tagMask, const QString& name,
672                             const QString& value);
673 
674   /**
675    * Get data from picture frame.
676    * @return picture data, empty if not found.
677    */
678   Q_INVOKABLE QByteArray getPictureData() const;
679 
680   /**
681    * Set data in picture frame.
682    * @param data picture data
683    */
684   Q_INVOKABLE void setPictureData(const QByteArray& data);
685 
686   /**
687    * Format frames if format while editing is switched on.
688    *
689    * @param frames frames
690    */
691   void formatFramesIfEnabled(FrameCollection& frames) const;
692 
693   /**
694    * Add picture on drop.
695    *
696    * @param frame dropped picture frame
697    */
698   void dropImage(Frame* frame);
699 
700   /**
701    * Handle URL on drop.
702    *
703    * @param url dropped URL.
704    */
705   void dropUrl(const QUrl& url);
706 
707   /**
708    * Get number of tracks in current directory.
709    *
710    * @return number of tracks, 0 if not found.
711    */
712   Q_INVOKABLE int getTotalNumberOfTracksInDir();
713 
714   /**
715    * Get name of selected file.
716    *
717    * @return absolute file name, ends with "/" if it is a directory.
718    */
719   QString getFileNameOfSelectedFile();
720 
721   /**
722    * Create a filter string for the file dialog.
723    * The filter string contains entries for all supported types.
724    *
725    * @return filter string.
726    */
727   Q_INVOKABLE QString createFilterString() const;
728 
729 
730   /**
731    * Remove the file filter if necessary to open the files.
732    * @param filePaths paths to files or directories
733    */
734   void resetFileFilterIfNotMatching(const QStringList& filePaths);
735 
736   /**
737    * Get image destination set by downloadImage().
738    * @return image destination.
739    */
getDownloadImageDestination()740   DownloadImageDestination getDownloadImageDestination() const {
741     return m_downloadImageDest;
742   }
743 
744   /**
745    * Check modification state.
746    *
747    * @return true if a file is modified.
748    */
749   bool isModified() const;
750 
751   /**
752    * Set filter state.
753    *
754    * @param val true if list is filtered
755    */
756   void setFiltered(bool val);
757 
758   /**
759    * Check filter state.
760    *
761    * @return true if list is filtered.
762    */
isFiltered()763   bool isFiltered() const { return m_filtered; }
764 
765   /**
766    * Get number of files which have passed the filter.
767    *
768    * This number is only valid if isFiltered() is true.
769    *
770    * @return number of files which have passed the filter.
771    */
filterPassedCount()772   int filterPassedCount() const { return m_filterPassed; }
773 
774   /**
775    * Get total number of files which have been checked by the filter.
776    *
777    * This number is only valid if isFiltered() is true.
778    *
779    * @return total number of files checked by filter.
780    */
filterTotalCount()781   int filterTotalCount() const { return m_filterTotal; }
782 
783   /**
784    * Get the selected file.
785    *
786    * @return the selected file,
787    *         0 if not exactly one file is selected
788    */
789   TaggedFile* getSelectedFile();
790 
791   /**
792    * Get the stored current selection.
793    * @return stored selection.
794    */
getCurrentSelection()795   const QList<QPersistentModelIndex>& getCurrentSelection() const {
796     return m_currentSelection;
797   }
798 
799   /**
800    * Update the stored current selection with the list of all selected items.
801    */
802   void updateCurrentSelection();
803 
804   /**
805    * Get directory name.
806    * @return directory.
807    */
getDirName()808   QString getDirName() const { return m_dirName; }
809 
810   /**
811    * Get frame editor set with setFrameEditor().
812    * @return frame editor, null if no frame editor is set
813    */
frameEditor()814   FrameEditorObject* frameEditor() const { return m_frameEditor; }
815 
816   /**
817    * Set a frame editor object to act as the frame editor.
818    * @param frameEditor frame editor object, null to disable
819    */
820   void setFrameEditor(FrameEditorObject* frameEditor);
821 
822   /**
823    * Remove frame editor.
824    * Has to be called in the destructor of the frame editor to avoid a dangling
825    * pointer to a deleted object.
826    * @param frameEditor frame editor
827    */
828   void removeFrameEditor(IFrameEditor* frameEditor);
829 
830   /**
831    * Get ID to get cover art image.
832    * @return ID for cover art image.
833    */
coverArtImageId()834   QString coverArtImageId() const { return m_coverArtImageId; }
835 
836   /**
837    * Set the image provider.
838    * @param imageProvider image provider
839    */
840   void setImageProvider(ImageDataProvider* imageProvider);
841 
842   /**
843    * Get the numbers of the selected rows in a list suitable for scripting.
844    * @return list with row numbers.
845    */
846   Q_INVOKABLE QVariantList getFileSelectionRows();
847 
848   /**
849    * Set the file selection from a list of model indexes.
850    * @param indexes list of model indexes suitable for scripting
851    */
852   Q_INVOKABLE void setFileSelectionIndexes(const QVariantList& indexes);
853 
854   /**
855    * Get paths to all selected files.
856    * @param onlyTaggedFiles only consider tagged files
857    * @return list of absolute file paths.
858    */
859   Q_INVOKABLE QStringList getSelectedFilePaths(bool onlyTaggedFiles = true)
860   const;
861 
862   /**
863    * Set picture data for image provider.
864    * @param picture picture data
865    */
866   Q_INVOKABLE void setCoverArtImageData(const QByteArray& picture);
867 
868   /**
869    * Open a file select dialog to get a file name.
870    * For script support, is only supported when a GUI is available.
871    * @param caption dialog caption
872    * @param dir working directory
873    * @param filter file type filter
874    * @param saveFile true to open a save file dialog
875    * @return selected file, empty if canceled.
876    */
877   Q_INVOKABLE QString selectFileName(
878       const QString& caption = QString(), const QString& dir = QString(),
879       const QString& filter = QString(), bool saveFile = false);
880 
881   /**
882    * Open a file select dialog to get a directory name.
883    * For script support, is only supported when a GUI is available.
884    * @param caption dialog caption
885    * @param dir working directory
886    * @return selected directory, empty if canceled.
887    */
888   Q_INVOKABLE QString selectDirName(
889       const QString& caption = QString(), const QString& dir = QString());
890 
891   /**
892    * Notify the tagged file factories about the changed configuration.
893    */
894   static void notifyConfigurationChange();
895 
896   /**
897    * Find directory containing plugins.
898    * @param pluginsDir the plugin directory is returned here
899    * @return true if found.
900    */
901   static bool findPluginsDirectory(QDir& pluginsDir);
902 
903   /**
904    * Set fallback path for directory containing plugins.
905    * @param path path to be searched for plugins if they are not found at the
906    * standard location relative to the application directory
907    */
908   static void setPluginsPathFallback(const QString& path);
909 
910   /**
911    * Load plugins.
912    * @return list of plugin instances.
913    */
914   static QObjectList loadPlugins();
915 
916 public slots:
917   /**
918    * Open directory or add pictures on drop.
919    *
920    * @param paths paths of directories or files in directory
921    */
922   void openDrop(const QStringList& paths);
923 
924   /**
925    * Handle drop of URLs.
926    *
927    * @param urlList picture, tagged file and folder URLs to handle (if local)
928    */
929   void openDropUrls(const QList<QUrl>& urlList);
930 
931   /**
932    * Unload all tags.
933    * The tags of all files which are not modified or selected are freed to
934    * reclaim their memory.
935    */
936   void unloadAllTags();
937 
938   /**
939    * Revert file modifications.
940    * Acts on selected files or all files if no file is selected.
941    */
942   void revertFileModifications();
943 
944   /**
945    * Set name of selected file.
946    * Exactly one file has to be selected.
947    *
948    * @param name file name.
949    */
950   void setFileNameOfSelectedFile(const QString& name);
951 
952   /**
953    * Apply filename format.
954    */
955   void applyFilenameFormat();
956 
957   /**
958    * Apply tag format.
959    */
960   void applyTagFormat();
961 
962   /**
963    * Apply text encoding.
964    * Set the text encoding selected in the settings Tags/ID3v2/Text encoding
965    * for all selected files which have an ID3v2 tag.
966    */
967   void applyTextEncoding();
968 
969   /**
970    * Convert ID3v2.3 to ID3v2.4 tags.
971    */
972   void convertToId3v24();
973 
974   /**
975    * Convert ID3v2.4 to ID3v2.3 tags.
976    */
977   void convertToId3v23();
978 
979   /**
980    * Copy tags into copy buffer.
981    *
982    * @param tagMask tag bit (1 for tag 1, 2 for tag 2)
983    */
984   void copyTags(Frame::TagVersion tagMask);
985 
986   /**
987    * Paste from copy buffer to tags.
988    *
989    * @param tagMask tag bit (1 for tag 1, 2 for tag 2)
990    */
991   void pasteTags(Frame::TagVersion tagMask);
992 
993   /**
994    * Set tag from other tag.
995    *
996    * @param tagMask tag bit (1 for tag 1, 2 for tag 2)
997    */
998   void copyToOtherTag(Frame::TagVersion tagMask);
999 
1000   /**
1001    * Copy from a tag to another tag.
1002    * @param srcTagNr source tag number
1003    * @param dstTagNr destination tag number
1004    */
1005   void copyTag(Frame::TagNumber srcTagNr, Frame::TagNumber dstTagNr);
1006 
1007   /**
1008    * Remove tags in selected files.
1009    *
1010    * @param tagMask tag bit (1 for tag 1, 2 for tag 2)
1011    */
1012   void removeTags(Frame::TagVersion tagMask);
1013 
1014   /**
1015    * Set tags according to filename.
1016    *
1017    * @param tagMask tag bit (1 for tag 1, 2 for tag 2)
1018    */
1019   void getTagsFromFilename(Frame::TagVersion tagMask);
1020 
1021   /**
1022    * Set filename according to tags.
1023    * If a single file is selected the tags in the GUI controls
1024    * are used, else the tags in the multiple selected files.
1025    *
1026    * @param tagVersion tag version
1027    */
1028   void getFilenameFromTags(Frame::TagVersion tagVersion);
1029 
1030   /**
1031    * Edit selected frame.
1032    * @param tagNr tag number
1033    */
1034   void editFrame(Frame::TagNumber tagNr);
1035 
1036   /**
1037    * Delete selected frame.
1038    * @param tagNr tag number
1039    * @param frameName name of frame to delete, empty to delete selected frame
1040    * @param index 0 for first frame with @a frameName, 1 for second, etc.
1041    */
1042   void deleteFrame(Frame::TagNumber tagNr,
1043                    const QString& frameName = QString(), int index = 0);
1044 
1045   /**
1046    * Select a frame type and add such a frame to the frame list.
1047    * @param tagNr tag number
1048    */
1049   void selectAndAddFrame(Frame::TagNumber tagNr);
1050 
1051   /**
1052    * Edit a picture frame if one exists or add a new one.
1053    */
1054   void editOrAddPicture();
1055 
1056   /**
1057    * Add a downloaded image.
1058    *
1059    * @param data     HTTP response of download
1060    * @param mimeType MIME type of data
1061    * @param url      URL of downloaded data
1062    */
1063   void imageDownloaded(const QByteArray& data,
1064                        const QString& mimeType, const QString& url);
1065 
1066   /**
1067    * Set the first file as the current file.
1068    *
1069    * @param select true to select the file
1070    * @param onlyTaggedFiles only consider tagged files
1071    *
1072    * @return true if a file exists.
1073    */
1074   bool firstFile(bool select = true, bool onlyTaggedFiles = false);
1075 
1076   /**
1077    * Set the next file as the current file.
1078    *
1079    * @param select true to select the file
1080    * @param onlyTaggedFiles only consider tagged files
1081    *
1082    * @return true if a next file exists.
1083    */
1084   bool nextFile(bool select = true, bool onlyTaggedFiles = false);
1085 
1086   /**
1087    * Set the previous file as the current file.
1088    *
1089    * @param select true to select the file
1090    * @param onlyTaggedFiles only consider tagged files
1091    *
1092    * @return true if a previous file exists.
1093    */
1094   bool previousFile(bool select = true, bool onlyTaggedFiles = false);
1095 
1096   /**
1097    * Select or deselect the current file.
1098    *
1099    * @param select true to select the file, false to deselect it
1100    *
1101    * @return true if a current file exists.
1102    */
1103   bool selectCurrentFile(bool select = true);
1104 
1105   /**
1106    * Select all files.
1107    */
1108   void selectAllFiles();
1109 
1110   /**
1111    * Deselect all files.
1112    */
1113   void deselectAllFiles();
1114 
1115   /**
1116    * Select all files in the current directory.
1117    */
1118   void selectAllInDirectory();
1119 
1120   /**
1121    * Invert current selection.
1122    */
1123   void invertSelection();
1124 
1125   /**
1126    * Set a specific file as the current file.
1127    *
1128    * @param filePath path to file
1129    * @param select true to select the file
1130    *
1131    * @return true if file exists.
1132    */
1133   bool selectFile(const QString& filePath, bool select = true);
1134 
1135   /**
1136    * Fetch entries of directory if not already fetched.
1137    * This works like FileList::expand(), but without expanding tree view
1138    * items and independent of the GUI. The processing is done in the background
1139    * by FileSystemModel, so the fetched items are not immediately available
1140    * after calling this method.
1141    *
1142    * @param index index of directory item
1143    */
1144   void fetchDirectory(const QModelIndex& index);
1145 
1146   /**
1147    * Fetch entries of directory and toggle expanded state if GUI available.
1148    * @param index index of directory item
1149    */
1150   void expandDirectory(const QModelIndex& index);
1151 
1152   /**
1153    * Expand the whole file list if GUI available.
1154    */
1155   void requestExpandFileList();
1156 
1157   /**
1158    * Called when operation for requestExpandFileList() is finished.
1159    */
1160   void notifyExpandFileListFinished();
1161 
1162   /**
1163    * Process change of selection.
1164    * The GUI is signaled to update the current selection and the controls.
1165    * @param selected selected items
1166    * @param deselected deselected items
1167    */
1168   void fileSelected(const QItemSelection& selected,
1169                     const QItemSelection& deselected);
1170 
1171   /**
1172    * Search in tags for a given text.
1173    * @param params search parameters
1174    */
1175   void findText(const TagSearcher::Parameters& params);
1176 
1177   /**
1178    * Replace found text.
1179    * @param params search parameters
1180    */
1181   void replaceText(const TagSearcher::Parameters& params);
1182 
1183   /**
1184    * Replace all occurrences.
1185    * @param params search parameters
1186    */
1187   void replaceAll(const TagSearcher::Parameters& params);
1188 
1189   /**
1190    * Schedule actions to rename a directory.
1191    * When finished renameActionsScheduled() is emitted.
1192    */
1193   void scheduleRenameActions();
1194 
1195   /**
1196    * Apply a file filter.
1197    *
1198    * @param fileFilter filter to apply.
1199    */
1200   void applyFilter(FileFilter& fileFilter);
1201 
1202   /**
1203    * Apply a file filter.
1204    *
1205    * @param expression filter expression
1206    */
1207   void applyFilter(const QString& expression);
1208 
1209   /**
1210    * Abort expression file filter.
1211    */
1212   void abortFilter();
1213 
1214   /**
1215    * Perform a batch import for the selected directories.
1216    * @param profile batch import profile
1217    * @param tagVersion import destination tag versions
1218    */
1219   void batchImport(const BatchImportProfile& profile,
1220                    Frame::TagVersion tagVersion);
1221 
1222   /**
1223    * Perform a batch import for the selected directories.
1224    * @param profileName batch import profile name
1225    * @param tagVersion import destination tag versions
1226    * @return true if profile with @a profileName found.
1227    */
1228   bool batchImport(const QString& profileName, Frame::TagVersion tagVersion);
1229 
1230   /**
1231    * Play audio file.
1232    */
1233   void playAudio();
1234 
1235   /**
1236    * Show play tool bar.
1237    */
1238   void showAudioPlayer();
1239 
1240 #ifdef HAVE_QTDBUS
1241   /**
1242    * Activate the MPRIS D-Bus Interface if not already active.
1243    */
1244   void activateMprisInterface();
1245 
1246   /**
1247    * Deactivate the MPRIS D-Bus Interface if it is active.
1248    */
1249   void deactivateMprisInterface();
1250 #endif
1251 
1252   /**
1253    * Close the file handle of a tagged file.
1254    * @param filePath path to file
1255    */
1256   void closeFileHandle(const QString& filePath);
1257 
1258 signals:
1259   /**
1260    * Emitted when the file proxy model root index changes.
1261    * @param index new root index
1262    */
1263   void fileRootIndexChanged(const QModelIndex& index);
1264 
1265   /**
1266    * Emitted when the directory proxy model root index changes.
1267    * @param index new root index
1268    */
1269   void dirRootIndexChanged(const QModelIndex& index);
1270 
1271   /**
1272    * Emitted when the directory has been opened, the file and directory proxy
1273    * model root indexes changed and the selection updated.
1274    */
1275   void directoryOpened();
1276 
1277   /**
1278    * Emitted when a confirmed opening of a directory or file is requested.
1279    * @param paths directory or file paths
1280    */
1281   void confirmedOpenDirectoryRequested(const QStringList& paths);
1282 
1283   /**
1284    * Emitted before an operation on the selected files is performed.
1285    * The GUI should update the files of the current selection when
1286    * receiving this signal.
1287    */
1288   void fileSelectionUpdateRequested();
1289 
1290   /**
1291    * Emitted after an operation on the selected files has been performed.
1292    * The GUI should update its controls from the tags in the files when
1293    * receiving this signal.
1294    */
1295   void selectedFilesUpdated();
1296 
1297   /**
1298    * Emitted after the file selection is changed.
1299    * The GUI should update its controls from the tags of the new file selection
1300    * when receiving this signal.
1301    * @param selected selected items
1302    * @param deselected deselected items
1303    */
1304   void selectedFilesChanged(const QItemSelection& selected,
1305                             const QItemSelection& deselected);
1306 
1307   /**
1308    * Emitted after a frame of a tagged file has been modified.
1309    * The GUI should update the corresponding controls when receiving this
1310    * signal.
1311    *
1312    * @param taggedFile tagged file with modified frame
1313    * @param tagNr tag number
1314    */
1315   void frameModified(TaggedFile* taggedFile, Frame::TagNumber tagNr);
1316 
1317   /**
1318    * Emitted when modification state is changed.
1319    * @param modified true if any file is modified
1320    * @see isModified()
1321    */
1322   void modifiedChanged(bool modified);
1323 
1324   /**
1325    * Emitted when filtered state is changed.
1326    * @param filtered true if file list is filtered
1327    * @see isFiltered(), setFiltered()
1328    */
1329   void filteredChanged(bool filtered);
1330 
1331   /**
1332    * Emitted when the directory name is changed.
1333    * @param name current directory name
1334    */
1335   void dirNameChanged(const QString& name);
1336 
1337   /**
1338    * Emitted when a file is filtered.
1339    * @param type filter event type, enum FileFilter::FilterEventType
1340    * @param fileName name of filtered file
1341    * @param passed number of files which passed the filter
1342    * @param total total number of files checked
1343    */
1344   void fileFiltered(int type, const QString& fileName, int passed, int total);
1345 
1346   /**
1347    * Emitted before an audio file is played.
1348    * The GUI can display a player when receiving this signal.
1349    */
1350   void aboutToPlayAudio();
1351 
1352   /**
1353    * Emitted when all rename actions have been scheduled.
1354    * @see scheduleRenameActions()
1355    */
1356   void renameActionsScheduled();
1357 
1358   /**
1359    * Emitted to request toggling of the expanded state of a directory in the
1360    * file list.
1361    * @param index index of directory item
1362    */
1363   void toggleExpandedRequested(const QModelIndex& index);
1364 
1365   /**
1366    * Emitted to request expanding of all directories in the file list.
1367    */
1368   void expandFileListRequested();
1369 
1370   /**
1371    * Emitted when operation requested by requestExpandFileList()
1372    * (signal expandFileListRequested()) is finished.
1373    */
1374   void expandFileListFinished();
1375 
1376   /**
1377    * Emitted when the file selection is changed.
1378    * @see getFileSelectionRows()
1379    */
1380   void fileSelectionChanged();
1381 
1382   /**
1383    * Emitted when a new cover art image is available
1384    * @param id ID of image.
1385    */
1386   void coverArtImageIdChanged(const QString& id);
1387 
1388   /**
1389    * Emitted when the frame editor is changed.
1390    */
1391   void frameEditorChanged();
1392 
1393   /**
1394    * Emitted to report progress about a long running operation.
1395    *
1396    * This signal is used to report different states of a long running operation.
1397    * - Operation is started: done is -1,
1398    * - Operation is finished: done == total and total is not 0,
1399    * - Operation in progress: done < total or both done and total are 0
1400    *
1401    * @param name name of operation
1402    * @param done amount of work done
1403    * @param total total amount of work
1404    * @param abort if not 0, can be set to true to abort the operation
1405    */
1406   void longRunningOperationProgress(const QString& name, int done, int total,
1407                                     bool* abort);
1408 
1409 private slots:
1410   /**
1411    * Apply file filter after the file system model has been reset.
1412    */
1413   void applyFilterAfterReset();
1414 
1415   /**
1416    * Apply single file to file filter.
1417    *
1418    * @param index index of file in file proxy model
1419    */
1420   void filterNextFile(const QPersistentModelIndex& index);
1421 
1422   /**
1423    * Apply single file to batch import.
1424    *
1425    * @param index index of file in file proxy model
1426    */
1427   void batchImportNextFile(const QPersistentModelIndex& index);
1428 
1429   /**
1430    * Schedule rename action for a file.
1431    *
1432    * @param index index of file in file proxy model
1433    */
1434   void scheduleNextRenameAction(const QPersistentModelIndex& index);
1435 
1436   /**
1437    * Perform rename actions after the file system model has been reset.
1438    */
1439   void performRenameActionsAfterReset();
1440 
1441   /**
1442    * Rename after the file system model has been reset.
1443    */
1444   void renameAfterReset();
1445 
1446   /**
1447    * Update selection and emit signals when directory is opened.
1448    */
1449   void onDirectoryOpened();
1450 
1451   /**
1452    * Called when the gatherer thread has finished to load the directory.
1453    */
1454   void onDirectoryLoaded();
1455 
1456   /**
1457    * Called when a frame is edited.
1458    * @param frame edited frame, 0 if canceled
1459    */
1460   void onFrameEdited(const Frame* frame);
1461 
1462   /**
1463    * Called when a frame is added.
1464    * @param frame added frame, 0 if canceled
1465    * @param tagNr tag number used if slot is not invoked by framelist signal
1466    */
1467   void onFrameAdded(const Frame* frame, Frame::TagNumber tagNr = Frame::Tag_2);
1468 
1469   /**
1470    * Called by framelist when a frame is added.
1471    * Same as onFrameAdded() with default argument, provided for functor-based
1472    * connections.
1473    * @param frame added frame, 0 if canceled
1474    */
1475   void onTag2FrameAdded(const Frame* frame);
1476 
1477   /**
1478    * If an image provider is used, update its picture and change the
1479    * coverArtImageId property if the picture of the selection changed.
1480    * This can be used to change a QML image.
1481    */
1482   void updateCoverArtImageId();
1483 
1484   /**
1485    * Save config when suspended, check intents when activated.
1486    * @param state application state
1487    */
1488   void onApplicationStateChanged(Qt::ApplicationState state);
1489 
1490 private:
1491   /**
1492    * Load and initialize plugins depending on configuration.
1493    */
1494   void initPlugins();
1495 
1496   /**
1497    * Check type of a loaded plugin and register it.
1498    * @param plugin instance returned by plugin loader
1499    */
1500   void checkPlugin(QObject* plugin);
1501 
1502   /**
1503    * Update frame models to contain contents of selected files.
1504    * @param indexes tagged file indexes
1505    * @param startSelection true if a new selection is started, false to add to
1506    * the existing selection
1507    * @return true if ok, false if selection operation is already running.
1508    */
1509   bool addTaggedFilesToSelection(
1510       const QList<QPersistentModelIndex>& indexes, bool startSelection);
1511 
1512   /**
1513    * Select a frame type and add such a frame to frame list.
1514    * @param tagNr tag number
1515    * @param frame frame to add, if 0 the user has to select and edit the frame
1516    * @param edit if true and a frame is set, the user can edit the frame before
1517    * it is added
1518    */
1519   void addFrame(Frame::TagNumber tagNr, const Frame* frame, bool edit = false);
1520 
1521   /**
1522    * Open directory or add pictures on drop.
1523    *
1524    * @param paths paths of directories or files in directory
1525    * @param isInternal true if this is an internal drop
1526    */
1527   void dropLocalFiles(const QStringList& paths, bool isInternal);
1528 
1529   /**
1530    * Second stage for applyFilter().
1531    */
1532   void proceedApplyingFilter();
1533 
1534   /**
1535    * Set the coverArtImageId property to a new value.
1536    * This can be used to trigger an update of QML images.
1537    */
1538   void setNextCoverArtImageId();
1539 
1540   void setAllFilesFileFilter();
1541 
1542   ICorePlatformTools* m_platformTools;
1543   /** Configuration */
1544   QScopedPointer<ConfigStore> m_configStore;
1545   /** model of filesystem */
1546   FileSystemModel* m_fileSystemModel;
1547   FileProxyModel* m_fileProxyModel;
1548   FileProxyModelIterator* m_fileProxyModelIterator;
1549   DirProxyModel* m_dirProxyModel;
1550   QItemSelectionModel* m_fileSelectionModel;
1551   QItemSelectionModel* m_dirSelectionModel;
1552   /** Track data model */
1553   TrackDataModel* m_trackDataModel;
1554   GenreModel* m_genreModel[Frame::Tag_NumValues];
1555   FrameTableModel* m_framesModel[Frame::Tag_NumValues];
1556   QItemSelectionModel* m_framesSelectionModel[Frame::Tag_NumValues];
1557   QMap<QString, PlaylistModel*> m_playlistModels;
1558   /** Frame list */
1559   FrameList* m_framelist[Frame::Tag_NumValues];
1560   /** Tag context */
1561   Kid3ApplicationTagContext* m_tagContext[Frame::Tag_NumValues];
1562   /** Network access manager */
1563   QNetworkAccessManager* m_netMgr;
1564   /** Download client */
1565   DownloadClient* m_downloadClient;
1566   /** Text exporter */
1567   TextExporter* m_textExporter;
1568   /** Tag searcher */
1569   TagSearcher* m_tagSearcher;
1570   /** Directory renamer */
1571   DirRenamer* m_dirRenamer;
1572   /** Batch importer */
1573   BatchImporter* m_batchImporter;
1574   /** Audio player */
1575   QObject* m_player;
1576 #ifdef HAVE_QTDBUS
1577   QString m_mprisServiceName;
1578 #endif
1579   FileFilter* m_expressionFileFilter;
1580   /** Information about selected tagged files */
1581   TaggedFileSelection* m_selection;
1582   /** Affected files to add frame when downloading image */
1583   DownloadImageDestination m_downloadImageDest;
1584   /** Copy buffer */
1585   FrameCollection m_copyTags;
1586   /** Root index in file proxy model */
1587   QPersistentModelIndex m_fileProxyModelRootIndex;
1588   /** Root index in directory proxy model */
1589   QPersistentModelIndex m_dirProxyModelRootIndex;
1590   /** Indexes of opened file in file proxy model */
1591   QList<QPersistentModelIndex> m_fileProxyModelFileIndexes;
1592   /** Importers for different servers */
1593   QList<ServerImporter*> m_importers;
1594   /** Importer for MusicBrainz fingerprints */
1595   QList<ServerTrackImporter*> m_trackImporters;
1596   /** Processors for user commands */
1597   QList<IUserCommandProcessor*> m_userCommandProcessors;
1598   /** Current directory */
1599   QString m_dirName;
1600   /** Stored current selection with the list of all selected items */
1601   QList<QPersistentModelIndex> m_currentSelection;
1602   /** directory from where "directory up" (..) was activated. */
1603   QPersistentModelIndex m_dirUpIndex;
1604 
1605   /* Context for filterNextFile() */
1606   FileFilter* m_fileFilter;
1607   QString m_lastProcessedDirName;
1608   int m_filterPassed;
1609   int m_filterTotal;
1610   /* Context for batchImportNextFile() */
1611   QScopedPointer<BatchImportProfile> m_namedBatchImportProfile;
1612   const BatchImportProfile* m_batchImportProfile;
1613   Frame::TagVersion m_batchImportTagVersion;
1614   QList<ImportTrackDataVector> m_batchImportAlbums;
1615   ImportTrackDataVector m_batchImportTrackDataList;
1616 
1617   /* Context for renameAfterReset() */
1618   QString m_renameAfterResetOldName;
1619   QString m_renameAfterResetNewName;
1620 
1621   /* Context for editFrame() */
1622   TaggedFile* m_editFrameTaggedFile;
1623   QString m_editFrameName;
1624 
1625   /* Context for addFrame() */
1626   TaggedFile* m_addFrameTaggedFile;
1627 
1628   /* Support for frame editor object */
1629   FrameEditorObject* m_frameEditor;
1630   IFrameEditor* m_storedFrameEditor;
1631   /* Support for image provider */
1632   ImageDataProvider* m_imageProvider;
1633   QString m_coverArtImageId;
1634 
1635 #ifdef Q_OS_ANDROID
1636   bool m_pendingIntentsChecked;
1637 #endif
1638 #ifdef HAVE_QTDBUS
1639   /** true if D-Bus is enabled */
1640   bool m_dbusEnabled;
1641 #endif
1642   /** true if list is filtered */
1643   bool m_filtered;
1644   /** true if a selection operation is running */
1645   bool m_selectionOperationRunning;
1646 
1647   /** Fallback for path to search for plugins */
1648   static QString s_pluginsPathFallback;
1649 };
1650 
1651 /**
1652  * Facade to have a uniform interface for different tags.
1653  */
1654 class KID3_CORE_EXPORT Kid3ApplicationTagContext : public QObject {
1655   Q_OBJECT
1656   /** Genre model. */
Q_PROPERTY(GenreModel * genreModel READ genreModel CONSTANT)1657   Q_PROPERTY(GenreModel* genreModel READ genreModel CONSTANT)
1658   /** Frame table model. */
1659   Q_PROPERTY(FrameTableModel* frameModel READ frameModel CONSTANT)
1660   /** Frame selection model. */
1661   Q_PROPERTY(QItemSelectionModel* frameSelectionModel READ frameSelectionModel CONSTANT)
1662   /** Frame list. */
1663   Q_PROPERTY(FrameList* frameList READ frameList CONSTANT)
1664 public:
1665   /**
1666    * Constructor.
1667    * @param app application
1668    * @param tagNr tag number
1669    */
1670   Kid3ApplicationTagContext(Kid3Application* app, Frame::TagNumber tagNr)
1671     : QObject(app), m_app(app), m_tagNr(tagNr),
1672       m_tagVersion(Frame::tagVersionFromNumber(tagNr)) {
1673   }
1674 
1675 public slots:
1676   /**
1677    * Copy tags into copy buffer.
1678    */
copyTags()1679   void copyTags() { m_app->copyTags(m_tagVersion); }
1680 
1681   /**
1682    * Paste from copy buffer to tags.
1683    */
pasteTags()1684   void pasteTags() { m_app->pasteTags(m_tagVersion); }
1685 
1686   /**
1687    * Copy tags to other tags of selected files.
1688    */
copyToOtherTag()1689   void copyToOtherTag() { m_app->copyToOtherTag(m_tagVersion); }
1690 
1691   /**
1692    * Remove tags in selected files.
1693    */
removeTags()1694   void removeTags() { m_app->removeTags(m_tagVersion); }
1695 
1696   /**
1697    * Set tags from filename.
1698    */
getTagsFromFilename()1699   void getTagsFromFilename() { m_app->getTagsFromFilename(m_tagVersion); }
1700 
1701   /**
1702    * Set filename from tags.
1703    */
getFilenameFromTags()1704   void getFilenameFromTags() { m_app->getFilenameFromTags(m_tagVersion); }
1705 
1706   /**
1707    * Edit selected frame of tag.
1708    */
editFrame()1709   void editFrame() { m_app->editFrame(m_tagNr); }
1710 
1711   /**
1712    * Delete selected frame from tag.
1713    */
deleteFrame()1714   void deleteFrame() { m_app->deleteFrame(m_tagNr); }
1715 
1716   /**
1717    * Select a frame type and add such a frame to the frame list.
1718    */
addFrame()1719   void addFrame() { m_app->selectAndAddFrame(m_tagNr); }
1720 
1721 private:
1722   /**
1723    * Get genre model.
1724    * @return genre model.
1725    */
genreModel()1726   GenreModel* genreModel() const { return m_app->genreModel(m_tagNr); }
1727 
1728   /**
1729    * Get frame table model.
1730    * @return frame table.
1731    */
frameModel()1732   FrameTableModel* frameModel() { return m_app->frameModel(m_tagNr); }
1733 
1734   /**
1735    * Get selection model of frame table model.
1736    */
frameSelectionModel()1737   QItemSelectionModel* frameSelectionModel() {
1738     return m_app->getFramesSelectionModel(m_tagNr);
1739   }
1740 
1741   /**
1742    * Get frame list.
1743    */
frameList()1744   FrameList* frameList() { return m_app->getFrameList(m_tagNr); }
1745 
1746   Kid3Application* const m_app;
1747   const Frame::TagNumber m_tagNr;
1748   const Frame::TagVersion m_tagVersion;
1749 };
1750