File indexing completed on 2023-05-30 11:30:50

0001 /**
0002  * Copyright (C) 2002-2004 Scott Wheeler <wheeler@kde.org>
0003  *
0004  * This program is free software; you can redistribute it and/or modify it under
0005  * the terms of the GNU General Public License as published by the Free Software
0006  * Foundation; either version 2 of the License, or (at your option) any later
0007  * version.
0008  *
0009  * This program is distributed in the hope that it will be useful, but WITHOUT ANY
0010  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
0011  * PARTICULAR PURPOSE. See the GNU General Public License for more details.
0012  *
0013  * You should have received a copy of the GNU General Public License along with
0014  * this program.  If not, see <http://www.gnu.org/licenses/>.
0015  */
0016 
0017 #ifndef JUK_PLAYLISTITEM_H
0018 #define JUK_PLAYLISTITEM_H
0019 
0020 #include <QExplicitlySharedDataPointer>
0021 #include <QVector>
0022 #include <QHash>
0023 #include <QTreeWidgetItem>
0024 
0025 #include "tagguesser.h"
0026 #include "filehandle.h"
0027 #include "juk_debug.h"
0028 
0029 class Playlist;
0030 class PlaylistItem;
0031 class CollectionListItem;
0032 class CollectionList;
0033 
0034 typedef QVector<PlaylistItem *> PlaylistItemList;
0035 
0036 /**
0037  * Items for the Playlist and the baseclass for CollectionListItem.
0038  * The constructors and destructor are protected and new items should be
0039  * created via Playlist::createItem().  Items should be removed by
0040  * Playlist::clear(), Playlist::deleteFromDisk(), Playlist::clearItem() or
0041  * Playlist::clearItem().
0042  */
0043 
0044 class PlaylistItem : public QTreeWidgetItem
0045 {
0046     friend class Playlist;
0047     friend class SearchPlaylist;
0048     friend class UpcomingPlaylist;
0049     friend class CollectionList;
0050     friend class CollectionListItem;
0051     friend class Pointer;
0052 
0053 public:
0054     enum ColumnType { TrackColumn       = 0,
0055                       ArtistColumn      = 1,
0056                       AlbumColumn       = 2,
0057                       CoverColumn       = 3,
0058                       TrackNumberColumn = 4,
0059                       GenreColumn       = 5,
0060                       YearColumn        = 6,
0061                       LengthColumn      = 7,
0062                       BitrateColumn     = 8,
0063                       CommentColumn     = 9,
0064                       FileNameColumn    = 10,
0065                       FullPathColumn    = 11 };
0066 
0067     /**
0068      * A helper class to implement guarded pointer semantics.
0069      */
0070 
0071     class Pointer
0072     {
0073     public:
0074         Pointer() : m_item(0) {}
0075         Pointer(PlaylistItem *item);
0076         Pointer(const Pointer &p);
0077         ~Pointer();
0078         Pointer &operator=(PlaylistItem *item);
0079         bool operator==(const Pointer &p) const { return m_item == p.m_item; }
0080         bool operator!=(const Pointer &p) const { return m_item != p.m_item; }
0081         PlaylistItem *operator->() const { return m_item; }
0082         PlaylistItem &operator*() const { return *m_item; }
0083         operator PlaylistItem*() const { return m_item; }
0084         static void clear(PlaylistItem *item);
0085 
0086     private:
0087         PlaylistItem *m_item;
0088         static QHash<PlaylistItem *, QVector<Pointer *> > m_itemPointers;
0089     };
0090     friend class Pointer;
0091 
0092     static int lastColumn() { return FullPathColumn; }
0093 
0094     void setFile(const FileHandle &file);
0095     void setFile(const QString &file);
0096     FileHandle file() const;
0097 
0098     virtual QString text(int column) const;
0099     virtual void setText(int column, const QString &text);
0100 
0101     bool isPlaying() const;
0102     void setPlaying(bool playing = true, bool master = true);
0103 
0104     void guessTagInfo(TagGuesser::Type type);
0105 
0106     Playlist *playlist() const;
0107 
0108     virtual CollectionListItem *collectionItem() { return m_collectionItem; }
0109 
0110     /**
0111      * This is an identifier for the playlist item which will remain unique
0112      * throughout the process lifetime. It stays constant once the PlaylistItem
0113      * is created.
0114      */
0115     quint32 trackId() const { return m_trackId; }
0116 
0117     /**
0118      * The widths of items are cached when they're updated for us in computations
0119      * in the "weighted" listview column width mode.
0120      */
0121     QVector<int> cachedWidths() const;
0122 
0123     /**
0124      * This just refreshes from the in memory data.  This may seem pointless at
0125      * first, but this data is shared between all of the list view items that are
0126      * based on the same file, so if another one of those items changes its data
0127      * it is important to refresh the others.
0128      */
0129     virtual void refresh();
0130 
0131     /**
0132      * This rereads the tag from disk.  This affects all PlaylistItems based on
0133      * the same file.
0134      */
0135     virtual void refreshFromDisk();
0136 
0137     /**
0138      * Asks the item's playlist to remove the item (which uses deleteLater()).
0139      */
0140     virtual void clear();
0141 
0142     /**
0143      * Returns properly casted item below this one.
0144      */
0145     PlaylistItem *itemBelow() { return static_cast<PlaylistItem *>(treeWidget()->itemBelow(this)); }
0146 
0147     /**
0148      * Returns properly casted item above this one.
0149      */
0150     PlaylistItem *itemAbove() { return static_cast<PlaylistItem *>(treeWidget()->itemAbove(this)); }
0151 
0152     /**
0153      * Returns a reference to the list of the currently playing items, with the
0154      * first being the "master" item (i.e. the item from which the next track is
0155      * chosen).
0156      */
0157     static const PlaylistItemList &playingItems() { return m_playingItems; }
0158 
0159 protected:
0160     /**
0161      * Items should always be created using Playlist::createItem() or through a
0162      * subclass or friend class.
0163      */
0164     PlaylistItem(CollectionListItem *item, Playlist *parent);
0165     PlaylistItem(CollectionListItem *item, Playlist *parent, QTreeWidgetItem *after);
0166 
0167     /**
0168      * See the class documentation for an explanation of construction and deletion
0169      * of PlaylistItems.
0170      */
0171     virtual ~PlaylistItem();
0172 
0173     virtual int compare(const QTreeWidgetItem *item, int column, bool ascending) const;
0174     int compare(const PlaylistItem *firstItem, const PlaylistItem *secondItem, int column, bool ascending) const;
0175 
0176     bool operator<(const QTreeWidgetItem &other) const override;
0177 
0178     bool isValid() const;
0179 
0180     void setTrackId(quint32 id);
0181 
0182     /**
0183      * Shared data between all PlaylistItems from the same track (incl. the CollectionItem
0184      * representing said track.
0185      */
0186     struct Data : public QSharedData
0187     {
0188         FileHandle fileHandle; // Set within CollectionList
0189         QVector<QString> metadata; ///< Artist, album, or genre tags.  Other columns unfilled
0190         QVector<int> cachedWidths;
0191     };
0192 
0193     using DataPtr = QExplicitlySharedDataPointer<Data>;
0194     DataPtr sharedData() const { return d; }
0195 
0196 private:
0197     DataPtr d;
0198 
0199     /**
0200      * This is the constructor that should be used by CollectionList.
0201      */
0202     PlaylistItem(CollectionList *parent);
0203     friend class CollectionList;
0204 
0205     void setup(CollectionListItem *item);
0206 
0207     CollectionListItem *m_collectionItem;
0208     quint32 m_trackId;
0209     bool m_watched;
0210     static PlaylistItemList m_playingItems;
0211 };
0212 
0213 inline QDebug operator<<(QDebug s, const PlaylistItem &item)
0214 {
0215     s << item.text(PlaylistItem::TrackColumn);
0216     return s;
0217 }
0218 
0219 #endif
0220 
0221 // vim: set et sw=4 tw=0 sta: