File indexing completed on 2024-05-05 04:47:29

0001 /****************************************************************************************
0002  * Copyright (c) 2007 Alexandre Pereira de Oliveira <aleprj@gmail.com>                  *
0003  * Copyright (c) 2007-2009 Maximilian Kossick <maximilian.kossick@googlemail.com>       *
0004  * Copyright (c) 2007 Nikolaj Hald Nielsen <nhn@kde.org>                                *
0005  *                                                                                      *
0006  * This program is free software; you can redistribute it and/or modify it under        *
0007  * the terms of the GNU General Public License as published by the Free Software        *
0008  * Foundation; either version 2 of the License, or (at your option) any later           *
0009  * version.                                                                             *
0010  *                                                                                      *
0011  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
0012  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
0013  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
0014  *                                                                                      *
0015  * You should have received a copy of the GNU General Public License along with         *
0016  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
0017  ****************************************************************************************/
0018 
0019 #ifndef COLLECTIONTREEITEMMODELBASE_H
0020 #define COLLECTIONTREEITEMMODELBASE_H
0021 
0022 #include "amarok_export.h"
0023 
0024 #include "core/collections/QueryMaker.h"
0025 #include "core/meta/forward_declarations.h"
0026 #include "CollectionTreeItem.h"
0027 
0028 #include <QAbstractItemModel>
0029 #include <QDateTime>
0030 #include <QHash>
0031 #include <QPair>
0032 #include <QPixmap>
0033 #include <QSet>
0034 
0035 namespace Collections
0036 {
0037     class Collection;
0038 }
0039 class CollectionTreeItem;
0040 class QTimeLine;
0041 class TrackLoaderJob;
0042 
0043 typedef QPair<Collections::Collection*, CollectionTreeItem* > CollectionRoot;
0044 
0045 /**
0046     @author Nikolaj Hald Nielsen <nhn@kde.org>
0047 */
0048 class AMAROK_EXPORT CollectionTreeItemModelBase : public QAbstractItemModel
0049 {
0050         Q_OBJECT
0051 
0052     friend class TrackLoaderJob;
0053 
0054     public:
0055         CollectionTreeItemModelBase();
0056         ~CollectionTreeItemModelBase() override;
0057 
0058         Qt::ItemFlags flags(const QModelIndex &index) const override;
0059         QVariant headerData(int section, Qt::Orientation orientation,
0060                             int role = Qt::DisplayRole) const override;
0061         QModelIndex index(int row, int column,
0062                         const QModelIndex &parent = QModelIndex()) const override;
0063         QModelIndex parent(const QModelIndex &index) const override;
0064         int rowCount(const QModelIndex &parent = QModelIndex()) const override;
0065         int columnCount(const QModelIndex &parent = QModelIndex()) const override;
0066         bool hasChildren ( const QModelIndex & parent = QModelIndex() ) const override;
0067 
0068         // Writable..
0069         bool setData( const QModelIndex &index, const QVariant &value, int role = Qt::EditRole ) override;
0070 
0071         QStringList mimeTypes() const override;
0072         QMimeData* mimeData( const QModelIndexList &indices ) const override;
0073         virtual QMimeData* mimeData( const QList<CollectionTreeItem *> &items ) const;
0074 
0075         virtual void listForLevel( int level, Collections::QueryMaker *qm, CollectionTreeItem* parent );
0076 
0077         virtual void setLevels( const QList<CategoryId::CatMenuId> &levelType );
0078         virtual QList<CategoryId::CatMenuId> levels() const { return m_levelType; }
0079         virtual CategoryId::CatMenuId levelCategory( const int level ) const;
0080 
0081         QString currentFilter() const;
0082         void setCurrentFilter( const QString &filter );
0083 
0084         void itemAboutToBeDeleted( CollectionTreeItem *item );
0085 
0086         /**
0087          * This should be called every time a drag enters collection browser
0088          */
0089         void setDragSourceCollections( const QSet<Collections::Collection*> &collections );
0090 
0091         /**
0092          * Return true if there are any queries still running. If this returns true,
0093          * you can expect allQueriesFinished(bool) signal in some time.
0094          */
0095         bool hasRunningQueries() const;
0096 
0097         static QIcon iconForCategory( CategoryId::CatMenuId category );
0098         static QString nameForCategory( CategoryId::CatMenuId category, bool showYears = false );
0099 
0100         void ensureChildrenLoaded( CollectionTreeItem *item );
0101 
0102         /**
0103          * Get a pointer to collection tree item given its index. It is not safe to
0104          * cache this pointer unless QPointer is used.
0105          */
0106         CollectionTreeItem *treeItem( const QModelIndex &index ) const;
0107 
0108         /**
0109          * Get (create) index for a collection tree item. The caller must ensure this
0110          * item is in this model. Invalid model index is returned on null or root item.
0111          */
0112         QModelIndex itemIndex( CollectionTreeItem *item ) const;
0113 
0114     Q_SIGNALS:
0115         void expandIndex( const QModelIndex &index );
0116         void allQueriesFinished( bool autoExpand );
0117 
0118     public Q_SLOTS:
0119         virtual void queryDone();
0120         void newTracksReady( const Meta::TrackList &);
0121         void newArtistsReady( const Meta::ArtistList &);
0122         void newAlbumsReady( const Meta::AlbumList &);
0123         void newGenresReady( const Meta::GenreList &);
0124         void newComposersReady( const Meta::ComposerList &);
0125         void newYearsReady( const Meta::YearList &);
0126         void newLabelsReady( const Meta::LabelList &);
0127         virtual void newDataReady( const Meta::DataList &data );
0128 
0129         /**
0130          * Apply the current filter.
0131          *
0132          * @param autoExpand whether to trigger automatic expansion of the tree after
0133          * filtering is done. This should be set to true only if filter is run after
0134          * user has actually just typed something and defaults to false.
0135          */
0136         void slotFilter( bool autoExpand = false );
0137         void slotFilterWithoutAutoExpand() { slotFilter( false ); }
0138 
0139         void slotCollapsed( const QModelIndex &index );
0140         void slotExpanded( const QModelIndex &index );
0141 
0142     private:
0143         void handleSpecialQueryResult( CollectionTreeItem::Type type, Collections::QueryMaker *qm, const Meta::DataList &dataList );
0144         void handleNormalQueryResult( Collections::QueryMaker *qm, const Meta::DataList &dataList );
0145 
0146         Collections::QueryMaker::QueryType mapCategoryToQueryType( int levelType ) const;
0147         void tracksLoaded( const Meta::AlbumPtr &album, const QModelIndex &index, const Meta::TrackList &tracks );
0148 
0149         QHash<Meta::Album *, int> m_years;
0150         mutable QSet<Meta::AlbumPtr> m_loadingAlbums;
0151 
0152     protected:
0153         /** Adds the query maker to the running queries and connects the slots */
0154         void addQueryMaker( CollectionTreeItem* item,
0155                             Collections::QueryMaker *qm ) const;
0156 
0157         virtual void populateChildren(const Meta::DataList &dataList, CollectionTreeItem *parent, const QModelIndex &parentIndex );
0158         virtual void updateHeaderText();
0159 
0160         virtual QIcon iconForLevel( int level ) const;
0161         virtual QString nameForLevel( int level ) const;
0162 
0163         virtual int levelModifier() const = 0;
0164         virtual QVariant dataForItem( CollectionTreeItem *item, int role, int level = -1 ) const;
0165 
0166         virtual void filterChildren() = 0;
0167 
0168         void markSubTreeAsDirty( CollectionTreeItem *item );
0169 
0170         /** Initiates a special search for albums without artists */
0171         void handleCompilations( Collections::QueryMaker::QueryType queryType, CollectionTreeItem *parent ) const;
0172 
0173         /** Initiates a special search for tracks without label */
0174         void handleTracksWithoutLabels( Collections::QueryMaker::QueryType queryType, CollectionTreeItem *parent ) const;
0175 
0176         QString m_headerText;
0177         CollectionTreeItem *m_rootItem;
0178         QList<CategoryId::CatMenuId> m_levelType;
0179 
0180         QTimeLine *m_timeLine;
0181         int m_animFrame;
0182         QPixmap m_loading1, m_loading2, m_currentAnimPixmap;    //icons for loading animation
0183 
0184         QString m_currentFilter;
0185         QSet<Meta::DataPtr> m_expandedItems;
0186         QSet<Collections::Collection*> m_expandedCollections;
0187         QSet<Collections::Collection*> m_expandedSpecialNodes;
0188 
0189         /**
0190          * Contents of this set are undefined if there is no active drag 'n drop operation.
0191          * Additionally, you may _never_ dereference pointers in this set, just compare
0192          * them with other pointers
0193          */
0194         QSet<Collections::Collection*> m_dragSourceCollections;
0195 
0196         QHash<QString, CollectionRoot > m_collections;  //I'll concide this one... :-)
0197         mutable QHash<Collections::QueryMaker* , CollectionTreeItem* > m_childQueries;
0198         mutable QHash<Collections::QueryMaker* , CollectionTreeItem* > m_compilationQueries;
0199         mutable QHash<Collections::QueryMaker* , CollectionTreeItem* > m_noLabelsQueries;
0200         mutable QMultiHash<CollectionTreeItem*, Collections::QueryMaker*> m_runningQueries;
0201         bool m_autoExpand; // whether to expand tree after queries are done
0202 
0203     protected Q_SLOTS:
0204         void startAnimationTick();
0205         void loadingAnimationTick();
0206 };
0207 
0208 
0209 #endif