File indexing completed on 2024-06-02 04:59:26
0001 /** 0002 * \file basemainwindow.h 0003 * Base class for main window. 0004 * 0005 * \b Project: Kid3 0006 * \author Urs Fleisch 0007 * \date 9 Jan 2003 0008 * 0009 * Copyright (C) 2003-2024 Urs Fleisch 0010 * 0011 * This file is part of Kid3. 0012 * 0013 * Kid3 is free software; you can redistribute it and/or modify 0014 * it under the terms of the GNU General Public License as published by 0015 * the Free Software Foundation; either version 2 of the License, or 0016 * (at your option) any later version. 0017 * 0018 * Kid3 is distributed in the hope that it will be useful, 0019 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0020 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0021 * GNU General Public License for more details. 0022 * 0023 * You should have received a copy of the GNU General Public License 0024 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0025 */ 0026 0027 #pragma once 0028 0029 #include <QMainWindow> 0030 #include <QDateTime> 0031 #include <QScopedPointer> 0032 #include "iframeeditor.h" 0033 #include "frame.h" 0034 #include "kid3api.h" 0035 0036 class QLabel; 0037 class QProgressBar; 0038 class QToolButton; 0039 class QItemSelection; 0040 class QTimer; 0041 class ProgressWidget; 0042 class Kid3Form; 0043 class Kid3Application; 0044 class TaggedFile; 0045 class ImportDialog; 0046 class TagImportDialog; 0047 class BatchImportDialog; 0048 class ExportDialog; 0049 class FindReplaceDialog; 0050 class BrowseCoverArtDialog; 0051 class RenDirDialog; 0052 class NumberTracksDialog; 0053 class RenDirDialog; 0054 class FilterDialog; 0055 class FileFilter; 0056 class DownloadDialog; 0057 class PlaylistDialog; 0058 class PlaylistEditDialog; 0059 class PlaylistConfig; 0060 class EditFrameFieldsDialog; 0061 class PlayToolBar; 0062 class DirContents; 0063 class FileProxyModel; 0064 class DirProxyModel; 0065 class TrackDataModel; 0066 class IPlatformTools; 0067 class BaseMainWindow; 0068 0069 /** 0070 * Implementation class for BaseMainWindow. 0071 * The reason for this implementation class is that a QObject is needed to 0072 * have slots. However, BaseMainWindow cannot inherit from QObject because it 0073 * is used with multiple inheritance together with another class which is a 0074 * QObject (actually a QMainWindow). Therefore the functionality of the main 0075 * put into this class which is then used as an implementation class by 0076 * BaseMainWindow. 0077 */ 0078 class KID3_GUI_EXPORT BaseMainWindowImpl : public QObject, public IFrameEditor { 0079 Q_OBJECT 0080 public: 0081 /** 0082 * Constructor. 0083 * 0084 * @param mainWin main window widget 0085 * @param platformTools platform specific tools 0086 */ 0087 BaseMainWindowImpl(QMainWindow* mainWin, IPlatformTools* platformTools, Kid3Application *app); 0088 0089 /** 0090 * Destructor. 0091 */ 0092 ~BaseMainWindowImpl() override; 0093 0094 /** 0095 * Create dialog to edit a frame and update the fields 0096 * if Ok is returned. 0097 * frameEdited() is emitted when the edit dialog is closed with the edited 0098 * frame as a parameter if it was accepted. 0099 * 0100 * @param frame frame to edit 0101 * @param taggedFile tagged file where frame has to be set 0102 */ 0103 void editFrameOfTaggedFile(const Frame* frame, TaggedFile* taggedFile) override; 0104 0105 /** 0106 * Let user select a frame type. 0107 * frameSelected() is emitted when the edit dialog is closed with the selected 0108 * frame as a parameter if a frame is selected. 0109 * 0110 * @param frame is filled with the selected frame 0111 * @param taggedFile tagged file for which frame has to be selected 0112 */ 0113 void selectFrame(Frame* frame, const TaggedFile* taggedFile) override; 0114 0115 /** 0116 * Return object which emits frameSelected(), frameEdited() signals. 0117 * 0118 * @return object which emits signals. 0119 */ 0120 QObject* qobject() override; 0121 0122 /** 0123 * Get the tag number of the edited frame. 0124 * @return tag number. 0125 */ 0126 Frame::TagNumber tagNumber() const override; 0127 0128 /** 0129 * Set the tag number of the edited frame. 0130 * @param tagNr tag number 0131 */ 0132 void setTagNumber(Frame::TagNumber tagNr) override; 0133 0134 /** 0135 * Set back pointer for implementation class. 0136 * 0137 * @param self back pointer 0138 */ 0139 void setBackPointer(BaseMainWindow* self) { m_self = self; } 0140 0141 /** 0142 * Initialize main window. 0143 * Shall be called at end of constructor body. 0144 */ 0145 void init(); 0146 0147 /** 0148 * Change visibility of status bar. 0149 * @param visible true to show status bar 0150 */ 0151 void setStatusBarVisible(bool visible); 0152 0153 /** 0154 * Update modification state before closing. 0155 * If anything was modified, save after asking user. 0156 * Save options before closing. 0157 * This method shall be called by closeEvent() (Qt) or 0158 * queryClose() (KDE). 0159 * 0160 * @return false if user canceled, 0161 * true will quit the application. 0162 */ 0163 bool queryBeforeClosing(); 0164 0165 /** 0166 * Open recent directory. 0167 * 0168 * @param dir directory to open 0169 */ 0170 void openRecentDirectory(const QString& dir); 0171 0172 /** 0173 * Apply configuration changes. 0174 */ 0175 void applyChangedConfiguration(); 0176 0177 /** 0178 * Apply keyboard shortcut changes. 0179 */ 0180 void applyChangedShortcuts(); 0181 0182 /** 0183 * Get media player actions. 0184 * @return list with named actions for "audio_play", "audio_stop", 0185 * "audio_previous", "audio_next". 0186 */ 0187 QList<QAction*> mediaActions() const; 0188 0189 /** 0190 * Access to application. 0191 * @return application. 0192 */ 0193 Kid3Application* app() { return m_app; } 0194 0195 /** 0196 * Access to main form. 0197 * @return main form. 0198 */ 0199 Kid3Form* form() { return m_form; } 0200 0201 public slots: 0202 /** 0203 * Set window title with information from directory, filter and modification 0204 * state. 0205 */ 0206 void updateWindowCaption(); 0207 0208 /** 0209 * Open directory, user has to confirm if current directory modified. 0210 * 0211 * @param paths directory or file paths 0212 */ 0213 void confirmedOpenDirectory(const QStringList& paths); 0214 0215 /** 0216 * Update the recent file list and the caption when a new directory 0217 * is opened. 0218 */ 0219 void onDirectoryOpened(); 0220 0221 /** 0222 * Request new directory and open it. 0223 */ 0224 void slotFileOpen(); 0225 0226 /** 0227 * Request new directory and open it. 0228 */ 0229 void slotFileOpenDirectory(); 0230 0231 /** 0232 * Reload the current directory. 0233 */ 0234 void slotFileReload(); 0235 0236 /** 0237 * Save modified files. 0238 */ 0239 void slotFileSave(); 0240 0241 /** 0242 * Quit application. 0243 */ 0244 void slotFileQuit(); 0245 0246 /** 0247 * Change status message. 0248 * 0249 * @param text message 0250 */ 0251 void slotStatusMsg(const QString& text); 0252 0253 /** 0254 * Clear status message. 0255 * To be called when a message set with slotStatusMsg() is no longer valid. 0256 */ 0257 void slotClearStatusMsg(); 0258 0259 /** 0260 * Show playlist dialog. 0261 */ 0262 void slotPlaylistDialog(); 0263 0264 /** 0265 * Create playlist. 0266 * 0267 * @return true if ok. 0268 */ 0269 bool slotCreatePlaylist(); 0270 0271 /** 0272 * Open dialog to edit playlist. 0273 * @param playlistPath path to playlist file 0274 */ 0275 void showPlaylistEditDialog(const QString& playlistPath); 0276 0277 /** 0278 * Import. 0279 */ 0280 void slotImport(); 0281 0282 /** 0283 * Tag import. 0284 */ 0285 void slotTagImport(); 0286 0287 /** 0288 * Batch import. 0289 */ 0290 void slotBatchImport(); 0291 0292 /** 0293 * Browse album cover artwork. 0294 */ 0295 void slotBrowseCoverArt(); 0296 0297 /** 0298 * Export. 0299 */ 0300 void slotExport(); 0301 0302 /** 0303 * Toggle auto hiding of tags. 0304 */ 0305 void slotSettingsAutoHideTags(); 0306 0307 /** 0308 * Show or hide picture. 0309 */ 0310 void slotSettingsShowHidePicture(); 0311 0312 /** 0313 * Find in tags of files. 0314 */ 0315 void find() { findReplace(true); } 0316 0317 /** 0318 * Find and replace in tags of files. 0319 * @param findOnly true to display only find part of dialog 0320 */ 0321 void findReplace(bool findOnly = false); 0322 0323 /** 0324 * Rename directory. 0325 */ 0326 void slotRenameDirectory(); 0327 0328 /** 0329 * Number tracks. 0330 */ 0331 void slotNumberTracks(); 0332 0333 /** 0334 * Filter. 0335 */ 0336 void slotFilter(); 0337 0338 /** 0339 * Play audio file. 0340 */ 0341 void slotPlayAudio(); 0342 0343 /** 0344 * Update files of current selection. 0345 */ 0346 void updateCurrentSelection(); 0347 0348 /** 0349 * Apply selection change and update GUI controls. 0350 * The new selection is stored and the GUI controls and frame list 0351 * updated accordingly (filtered for multiple selection). 0352 * @param selected selected items 0353 * @param deselected deselected items 0354 */ 0355 void applySelectionChange(const QItemSelection& selected, 0356 const QItemSelection& deselected); 0357 0358 /** 0359 * Update GUI controls from the tags in the files. 0360 * The new selection is stored and the GUI controls and frame list 0361 * updated accordingly (filtered for multiple selection). 0362 */ 0363 void updateGuiControls(); 0364 0365 /** 0366 * Rename the selected file(s). 0367 */ 0368 void renameFile(); 0369 0370 /** 0371 * Delete the selected file(s). 0372 */ 0373 void deleteFile(); 0374 0375 /** 0376 * Expand the file list. 0377 */ 0378 void expandFileList(); 0379 0380 signals: 0381 /** 0382 * Emitted when the dialog to add and edit a frame is closed. 0383 * @param tagNr tag number 0384 * @param frame edited frame if dialog was accepted, else 0 0385 */ 0386 void frameEdited(Frame::TagNumber tagNr, const Frame* frame); 0387 0388 /** 0389 * Emitted when the dialog to select a frame is closed. 0390 * @param tagNr tag number 0391 * @param frame selected frame if dialog was accepted, else 0 0392 */ 0393 void frameSelected(Frame::TagNumber tagNr, const Frame* frame); 0394 0395 private slots: 0396 /** 0397 * Update ID3v2 tags in GUI controls from file displayed in frame list. 0398 * 0399 * @param taggedFile the selected file 0400 * @param tagNr tag number 0401 */ 0402 void updateAfterFrameModification(TaggedFile* taggedFile, 0403 Frame::TagNumber tagNr); 0404 0405 /** 0406 * Show play tool bar. 0407 */ 0408 void showPlayToolBar(); 0409 0410 /** 0411 * Expand item if it is a directory. 0412 * 0413 * @param index index of file in file proxy model 0414 */ 0415 void expandNextDirectory(const QPersistentModelIndex& index); 0416 0417 /** 0418 * Show filter operation progress. 0419 * @param type filter event type 0420 * @param fileName name of file processed 0421 * @param passed number of files which passed the filter 0422 * @param total total number of files checked 0423 */ 0424 void filterProgress(int type, const QString& fileName, int passed, int total); 0425 0426 /** 0427 * Set tagged files of directory from imported track data model. 0428 */ 0429 void applyImportedTrackData(); 0430 0431 /** 0432 * Called when the edit frame dialog is finished. 0433 * @param result dialog result 0434 */ 0435 void onEditFrameDialogFinished(int result); 0436 0437 /** 0438 * Called when a playlist edit dialog is closed. 0439 */ 0440 void onPlaylistEditDialogFinished(); 0441 0442 /** 0443 * Toggle expanded state of directory in the file list. 0444 * @param index index of directory 0445 */ 0446 void toggleExpanded(const QModelIndex& index); 0447 0448 /** 0449 * Deactivate showing of find replace results. 0450 */ 0451 void deactivateFindReplace(); 0452 0453 /** 0454 * Ensure that found text is made visible in the GUI. 0455 */ 0456 void showFoundText(); 0457 0458 /** 0459 * Update GUI controls after text has been replaced. 0460 */ 0461 void updateReplacedText(); 0462 0463 /** 0464 * Show progress of long running operation in status bar. 0465 * @param name name of operation 0466 * @param done amount of work done 0467 * @param total total amount of work 0468 * @param abort if not 0, can be set to true to abort operation 0469 */ 0470 void showOperationProgress(const QString& name, int done, int total, 0471 bool* abort); 0472 0473 /** 0474 * Called when the item count of the file proxy model changed. 0475 */ 0476 void onItemCountChanged(); 0477 0478 /** 0479 * Called when the item count of the file selection model changed. 0480 */ 0481 void onSelectionCountChanged(); 0482 0483 private: 0484 /** 0485 * Free allocated resources. 0486 * Our destructor may not be called, so cleanup is done here. 0487 */ 0488 void cleanup(); 0489 0490 /** 0491 * Save application options. 0492 */ 0493 void saveOptions(); 0494 0495 /** 0496 * Load application options. 0497 */ 0498 void readOptions(); 0499 0500 /** 0501 * Save state of play tool bar. 0502 */ 0503 void savePlayToolBarConfig(); 0504 0505 /** 0506 * Restore state of play tool bar. 0507 */ 0508 void readPlayToolBarConfig(); 0509 0510 0511 /** 0512 * Save all changed files. 0513 * 0514 * @param updateGui true to update GUI (controls, status, cursor) 0515 */ 0516 void saveDirectory(bool updateGui = false); 0517 0518 /** 0519 * If anything was modified, save after asking user. 0520 * 0521 * @param doNotRevert if true, modifications are not reverted, this can be 0522 * used to skip the possibly long process if the application is not be closed 0523 * 0524 * @return false if user canceled. 0525 */ 0526 bool saveModified(bool doNotRevert = false); 0527 0528 /** 0529 * If a playlist was modified, save after asking user. 0530 * @return false if user canceled. 0531 */ 0532 bool saveModifiedPlaylists(); 0533 0534 /** 0535 * Update track data and create import dialog. 0536 */ 0537 void setupImportDialog(); 0538 0539 /** 0540 * Write playlist according to playlist configuration. 0541 * 0542 * @param cfg playlist configuration to use 0543 * 0544 * @return true if ok. 0545 */ 0546 bool writePlaylist(const PlaylistConfig& cfg); 0547 0548 /** 0549 * Terminate expanding the file list. 0550 */ 0551 void terminateExpandFileList(); 0552 0553 /** 0554 * Terminate filtering the file list. 0555 */ 0556 void terminateFilter(); 0557 0558 /** 0559 * Update GUI controls from the current selection. 0560 */ 0561 void updateGuiControlsFromSelection(); 0562 0563 /** 0564 * Start monitoring the progress of a possibly long operation. 0565 * 0566 * If the operation takes longer than 3 seconds, a progress widget is shown. 0567 * 0568 * @param title title to be displayed in progress widget 0569 * @param terminationHandler method to be called to terminate operation 0570 * @param disconnectModel true to disconnect the file list models while the 0571 * progress widget is shown 0572 */ 0573 void startProgressMonitoring(const QString& title, 0574 void (BaseMainWindowImpl::*terminationHandler)(), 0575 bool disconnectModel); 0576 0577 /** 0578 * Stop monitoring the progress started with startProgressMonitoring(). 0579 */ 0580 void stopProgressMonitoring(); 0581 0582 /** 0583 * Check progress of a possibly long operation. 0584 * 0585 * Progress monitoring is started with startProgressMonitoring(). This method 0586 * will check if the opeation is running long enough to show a progress widget 0587 * and update the progress information. It will call stopProgressMonitoring() 0588 * when the operation is aborted. 0589 * 0590 * @param done amount of work done 0591 * @param total total amount of work 0592 * @param text text for progress label 0593 */ 0594 void checkProgressMonitoring(int done, int total, const QString& text); 0595 0596 /** 0597 * Update label of status bar with information about the number of files. 0598 */ 0599 void updateStatusLabel(); 0600 0601 IPlatformTools* m_platformTools; 0602 QMainWindow* m_w; 0603 BaseMainWindow* m_self; 0604 0605 QTimer* m_deferredItemCountTimer; 0606 QTimer* m_deferredSelectionCountTimer; 0607 /** Label with normal status message */ 0608 QLabel* m_statusLabel; 0609 /** GUI with controls */ 0610 Kid3Form* m_form; 0611 /** Application logic */ 0612 Kid3Application* m_app; 0613 /** Import dialog */ 0614 QScopedPointer<ImportDialog> m_importDialog; 0615 /** Import from Tags dialog */ 0616 QScopedPointer<TagImportDialog> m_tagImportDialog; 0617 /** Batch import dialog */ 0618 QScopedPointer<BatchImportDialog> m_batchImportDialog; 0619 /** Browse cover art dialog */ 0620 QScopedPointer<BrowseCoverArtDialog> m_browseCoverArtDialog; 0621 /** Export dialog */ 0622 ExportDialog* m_exportDialog; 0623 /** Find and replace dialog */ 0624 FindReplaceDialog* m_findReplaceDialog; 0625 /** Rename directory dialog */ 0626 QScopedPointer<RenDirDialog> m_renDirDialog; 0627 /** Number tracks dialog */ 0628 QScopedPointer<NumberTracksDialog> m_numberTracksDialog; 0629 /** Filter dialog */ 0630 QScopedPointer<FilterDialog> m_filterDialog; 0631 /** Download dialog */ 0632 DownloadDialog* m_downloadDialog; 0633 /** Playlist dialog */ 0634 QScopedPointer<PlaylistDialog> m_playlistDialog; 0635 /** Playlist edit dialogs */ 0636 QMap<QString, PlaylistEditDialog*> m_playlistEditDialogs; 0637 /** Progress dialog */ 0638 ProgressWidget* m_progressWidget; 0639 QLabel* m_progressLabel; 0640 QProgressBar* m_progressBar; 0641 QToolButton* m_progressAbortButton; 0642 /** Edit frame dialog */ 0643 EditFrameFieldsDialog* m_editFrameDialog; 0644 /** Play toolbar */ 0645 PlayToolBar* m_playToolBar; 0646 Frame m_editFrame; 0647 TaggedFile* m_editFrameTaggedFile; 0648 Frame::TagNumber m_editFrameTagNr; 0649 QDateTime m_progressStartTime; 0650 QString m_progressTitle; 0651 void (BaseMainWindowImpl::*m_progressTerminationHandler)(); 0652 int m_folderCount; 0653 int m_fileCount; 0654 int m_selectionCount; 0655 bool m_progressDisconnected; 0656 bool m_findReplaceActive; 0657 bool m_expandNotificationNeeded; 0658 }; 0659 0660 0661 /** 0662 * Base class for the main window. 0663 * The main window classes for Qt (QMainWindow) and KDE (KXmlGuiWindow) 0664 * have common functionality. The actual Kid3 main window can inherit from both 0665 * the platform dependent main window class and this base class. Differences 0666 * between the platforms can be handled by implementing the pure virtual methods 0667 * of this class. Because this class cannot be a QObject (QMainWindow is 0668 * already a QObject), most of its functionality is delegated to a QObject 0669 * implementation class. 0670 */ 0671 class KID3_GUI_EXPORT BaseMainWindow { 0672 public: 0673 /** 0674 * Constructor. 0675 * 0676 * @param mainWin main window 0677 * @param platformTools platform specific tools 0678 * @param app application context 0679 */ 0680 BaseMainWindow(QMainWindow* mainWin, IPlatformTools* platformTools, 0681 Kid3Application *app); 0682 0683 /** 0684 * Destructor. 0685 */ 0686 virtual ~BaseMainWindow(); 0687 0688 /** 0689 * Init menu and toolbar actions. 0690 */ 0691 virtual void initActions() = 0; 0692 0693 /** 0694 * Get keyboard shortcuts. 0695 * @return mapping of action names to key sequences. 0696 */ 0697 virtual QMap<QString, QKeySequence> shortcutsMap() const = 0; 0698 0699 /** 0700 * Add directory to recent files list. 0701 * 0702 * @param dirName path to directory 0703 */ 0704 virtual void addDirectoryToRecentFiles(const QString& dirName) = 0; 0705 0706 /** 0707 * Read settings from the configuration. 0708 */ 0709 virtual void readConfig() = 0; 0710 0711 /** 0712 * Store geometry and recent files in settings. 0713 */ 0714 virtual void saveConfig() = 0; 0715 0716 /** 0717 * Get action for Settings/Auto Hide Tags. 0718 * @return action. 0719 */ 0720 virtual QAction* autoHideTagsAction() = 0; 0721 0722 /** 0723 * Get action for Settings/Hide Picture. 0724 * @return action. 0725 */ 0726 virtual QAction* showHidePictureAction() = 0; 0727 0728 /** 0729 * Set main window caption. 0730 * 0731 * @param caption caption without application name 0732 * @param modified true if any file is modified 0733 */ 0734 virtual void setWindowCaption(const QString& caption, bool modified) = 0; 0735 0736 /** 0737 * Play audio file. 0738 */ 0739 void slotPlayAudio(); 0740 0741 /** 0742 * Update files of current selection. 0743 */ 0744 void updateCurrentSelection(); 0745 0746 /** 0747 * Open directory, user has to confirm if current directory modified. 0748 * 0749 * @param paths directory or file paths 0750 */ 0751 void confirmedOpenDirectory(const QStringList& paths); 0752 0753 /** 0754 * Access to implementation object. 0755 * @return implementation object. 0756 */ 0757 BaseMainWindowImpl* impl() { return m_impl.data(); } 0758 0759 protected: 0760 /** 0761 * Initialize main window. 0762 * Shall be called at end of constructor body in derived classes. 0763 */ 0764 void init(); 0765 0766 /** 0767 * Change visibility of status bar. 0768 * @param visible true to show status bar 0769 */ 0770 void setStatusBarVisible(bool visible); 0771 0772 /** 0773 * Update modification state before closing. 0774 * If anything was modified, save after asking user. 0775 * Save options before closing. 0776 * This method shall be called by closeEvent() (Qt) or 0777 * queryClose() (KDE). 0778 * 0779 * @return false if user canceled, 0780 * true will quit the application. 0781 */ 0782 bool queryBeforeClosing(); 0783 0784 /** 0785 * Open recent directory. 0786 * 0787 * @param dir directory to open 0788 */ 0789 void openRecentDirectory(const QString& dir); 0790 0791 /** 0792 * Set window title with information from directory, filter and modification 0793 * state. 0794 */ 0795 void updateWindowCaption(); 0796 0797 /** 0798 * Access to application. 0799 * @return application. 0800 */ 0801 Kid3Application* app(); 0802 0803 /** 0804 * Access to main form. 0805 * @return main form. 0806 */ 0807 Kid3Form* form(); 0808 0809 private: 0810 QScopedPointer<BaseMainWindowImpl> m_impl; 0811 };