#pragma once #include #include #include #include #include "library/coverart.h" #include "library/dao/playlistdao.h" #include "library/trackprocessing.h" #include "preferences/usersettings.h" #include "track/trackref.h" #include "util/color/rgbcolor.h" class ControlProxy; class DlgTagFetcher; class DlgTrackInfo; class ExternalTrackCollection; class TrackCollectionManager; class TrackModel; class WColorPickerAction; class WCoverArtMenu; /// A context menu for track(s). /// Can be used with individual track type widgets based on TrackPointer /// or list/table type track widgets based on QModelIndexList and TrackModel. /// Desired menu features can be selected by passing Feature enum flags /// in constructor. class WTrackMenu : public QMenu { Q_OBJECT public: enum Feature { AutoDJ = 1, // The loadTrackToPlayer signal emitted from this class must be handled to make LoadTo work. LoadTo = 1 << 1, Playlist = 1 << 2, Crate = 1 << 3, Remove = 1 << 4, Metadata = 1 << 5, Reset = 1 << 6, BPM = 1 << 7, Color = 1 << 8, HideUnhidePurge = 1 << 9, FileBrowser = 1 << 10, Properties = 1 << 11, TrackModelFeatures = Remove | HideUnhidePurge, All = AutoDJ | LoadTo | Playlist | Crate | Remove | Metadata | Reset | BPM | Color | HideUnhidePurge | FileBrowser | Properties }; Q_DECLARE_FLAGS(Features, Feature) WTrackMenu(QWidget* parent, UserSettingsPointer pConfig, TrackCollectionManager* pTrackCollectionManager, Features flags = Feature::All, TrackModel* trackModel = nullptr); ~WTrackMenu() override; void loadTrackModelIndex( const QModelIndex& trackIndex) { loadTrackModelIndices(QModelIndexList{trackIndex}); } void loadTrackModelIndices( const QModelIndexList& trackIndexList); void loadTrack( const TrackPointer& pTrack); // WARNING: This function hides non-virtual QMenu::popup(). // This has been done on purpose to ensure menu doesn't popup without loaded track(s). void popup(const QPoint& pos, QAction* at = nullptr); void slotShowDlgTrackInfo(); signals: void loadTrackToPlayer(TrackPointer pTrack, const QString& group, bool play = false); private slots: // File void slotOpenInFileBrowser(); // Row color void slotColorPicked(mixxx::RgbColor::optional_t color); // Reset void slotClearBeats(); void slotClearPlayCount(); void slotClearRating(); void slotClearMainCue(); void slotClearHotCues(); void slotClearIntroCue(); void slotClearOutroCue(); void slotClearLoop(); void slotClearKey(); void slotClearReplayGain(); void slotClearWaveform(); void slotClearAllMetadata(); // BPM void slotLockBpm(); void slotUnlockBpm(); void slotScaleBpm(int); // Info and metadata void slotShowDlgTagFetcher(); void slotImportMetadataFromFileTags(); void slotExportMetadataIntoFileTags(); void slotUpdateExternalTrackCollection(ExternalTrackCollection* externalTrackCollection); // Playlist and crate void slotPopulatePlaylistMenu(); void slotPopulateCrateMenu(); void addSelectionToNewCrate(); // Auto DJ void slotAddToAutoDJBottom(); void slotAddToAutoDJTop(); void slotAddToAutoDJReplace(); // Cover void slotCoverInfoSelected(CoverInfoRelative coverInfo); void slotReloadCoverArt(); // Library management void slotRemove(); void slotHide(); void slotUnhide(); void slotPurge(); private: // This getter verifies that m_pTrackModel is set when // invoked. const QModelIndexList& getTrackIndices() const; TrackIdList getTrackIds() const; QList getTrackRefs() const; TrackPointer getFirstTrackPointer() const; std::unique_ptr newTrackPointerIterator() const; /// WARNING: The provided pTrackPointerOperation must ensure NOT /// TO MODIFY the underlying m_pTrackModel during the iteration!!! /// This might happen not only directly but also indirectly by /// handling signals, e.g. TrackDAO::enforceModelUpdate(). int applyTrackPointerOperation( const QString& progressLabelText, const mixxx::TrackPointerOperation* pTrackPointerOperation, mixxx::ModalTrackBatchOperationProcessor::Mode operationMode = mixxx::ModalTrackBatchOperationProcessor::Mode::Apply) const; bool isEmpty() const { return getTrackCount() == 0; } int getTrackCount() const; void createMenus(); void createActions(); void setupActions(); void updateMenus(); bool featureIsEnabled(Feature flag) const; void addSelectionToPlaylist(int iPlaylistId); void updateSelectionCrates(QWidget* pWidget); void addToAutoDJ(PlaylistDAO::AutoDJSendLoc loc); void lockBpm(bool lock); void loadSelectionToGroup(const QString& group, bool play = false); void clearTrackSelection(); bool isAnyTrackBpmLocked() const; /// Get the common track color of all tracks this menu is shown for, or /// return `nullopt` if there is no common color. Tracks may have no color /// assigned to them. In that case the inner optional is set to `nullopt`. std::optional> getCommonTrackColor() const; CoverInfo getCoverInfoOfLastTrack() const; TrackModel* m_pTrackModel{}; QModelIndexList m_trackIndexList; // Source of track list when TrackModel is not set. TrackPointerList m_trackPointerList; const ControlProxy* m_pNumSamplers{}; const ControlProxy* m_pNumDecks{}; const ControlProxy* m_pNumPreviewDecks{}; // Submenus QMenu* m_pLoadToMenu{}; QMenu* m_pDeckMenu{}; QMenu* m_pSamplerMenu{}; QMenu* m_pPlaylistMenu{}; QMenu* m_pCrateMenu{}; QMenu* m_pMetadataMenu{}; QMenu* m_pMetadataUpdateExternalCollectionsMenu{}; QMenu* m_pClearMetadataMenu{}; QMenu* m_pBPMMenu{}; QMenu* m_pColorMenu{}; WCoverArtMenu* m_pCoverMenu{}; // Reload Track Metadata Action: QAction* m_pImportMetadataFromFileAct{}; QAction* m_pImportMetadataFromMusicBrainzAct{}; // Save Track Metadata Action: QAction* m_pExportMetadataAct{}; // Load Track to PreviewDeck QAction* m_pAddToPreviewDeck{}; // Send to Auto-DJ Action QAction* m_pAutoDJBottomAct{}; QAction* m_pAutoDJTopAct{}; QAction* m_pAutoDJReplaceAct{}; // Remove from table QAction* m_pRemoveAct{}; QAction* m_pRemovePlaylistAct{}; QAction* m_pRemoveCrateAct{}; QAction* m_pHideAct{}; QAction* m_pUnhideAct{}; QAction* m_pPurgeAct{}; // Show track-editor action QAction* m_pPropertiesAct{}; // Open file in default file browser QAction* m_pFileBrowserAct{}; // BPM feature QAction* m_pBpmLockAction{}; QAction* m_pBpmUnlockAction{}; QAction* m_pBpmDoubleAction{}; QAction* m_pBpmHalveAction{}; QAction* m_pBpmTwoThirdsAction{}; QAction* m_pBpmThreeFourthsAction{}; QAction* m_pBpmFourThirdsAction{}; QAction* m_pBpmThreeHalvesAction{}; QAction* m_pBpmResetAction{}; // Track color WColorPickerAction* m_pColorPickerAction{}; // Clear track metadata actions QAction* m_pClearBeatsAction{}; QAction* m_pClearPlayCountAction{}; QAction* m_pClearRatingAction{}; QAction* m_pClearMainCueAction{}; QAction* m_pClearHotCuesAction{}; QAction* m_pClearIntroCueAction{}; QAction* m_pClearOutroCueAction{}; QAction* m_pClearLoopAction{}; QAction* m_pClearWaveformAction{}; QAction* m_pClearKeyAction{}; QAction* m_pClearReplayGainAction{}; QAction* m_pClearAllMetadataAction{}; const UserSettingsPointer m_pConfig; TrackCollectionManager* const m_pTrackCollectionManager; std::unique_ptr m_pDlgTrackInfo; std::unique_ptr m_pDlgTagFetcher; struct UpdateExternalTrackCollection { QPointer externalTrackCollection; QAction* action{}; }; QList m_updateInExternalTrackCollections; bool m_bPlaylistMenuLoaded; bool m_bCrateMenuLoaded; Features m_eActiveFeatures; const Features m_eTrackModelFeatures; }; Q_DECLARE_OPERATORS_FOR_FLAGS(WTrackMenu::Features)