1 /**************************************************************************************** 2 * Copyright (c) 2009 Maximilian Kossick <maximilian.kossick@googlemail.com> * 3 * Copyright (c) 2012 Matěj Lait <matej@laitl.cz> * 4 * * 5 * This program is free software; you can redistribute it and/or modify it under * 6 * the terms of the GNU General Public License as published by the Free Software * 7 * Foundation; either version 2 of the License, or (at your option) any later * 8 * version. * 9 * * 10 * This program is distributed in the hope that it will be useful, but WITHOUT ANY * 11 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * 12 * PARTICULAR PURPOSE. See the GNU General Public License for more details. * 13 * * 14 * You should have received a copy of the GNU General Public License along with * 15 * this program. If not, see <http://www.gnu.org/licenses/>. * 16 ****************************************************************************************/ 17 18 #ifndef PERSISTENTSTATISTICSSTORE_H 19 #define PERSISTENTSTATISTICSSTORE_H 20 21 #include "amarok_export.h" 22 #include "core/meta/Observer.h" 23 #include "core/meta/Statistics.h" 24 25 #include <QDateTime> 26 #include <QReadWriteLock> 27 28 /** 29 * Base class for all permanent statistics storage providers. Use one of the subclassed if 30 * your collection cannot store statistics (rating, play count..) natively, but you still 31 * want to provide the functionality. 32 * 33 * All subclasses automatically call notifyObservers() on your track when the statistics 34 * change. PersistentStatisticsStore uses some trickery not to hold reference to your 35 * track to avoid circular reference counting. PersistentStatisticsStore can even deal 36 * with your track being destroyed and is implemented in thread-safe way. You should 37 * store is as StatisticsPtr (a AmarokSharedPointer) in your Track class. 38 */ 39 class AMAROK_EXPORT PersistentStatisticsStore : public Meta::Statistics, private Meta::Observer 40 { 41 public: 42 /** 43 * Create persistent statistics store of @param track statistics. @p track may 44 * not be null. 45 * 46 * This methods takes plain pointer so that you can call it in the Track 47 * constructor without AmarokSharedPointer deleting it right away. 48 */ 49 explicit PersistentStatisticsStore( Meta::Track *track ); 50 ~PersistentStatisticsStore() override; 51 52 // Meta::Statistics methods 53 double score() const override; 54 void setScore( double newScore ) override; 55 56 int rating() const override; 57 void setRating( int newRating ) override; 58 59 QDateTime lastPlayed() const override; 60 void setLastPlayed( const QDateTime &dt ) override; 61 62 QDateTime firstPlayed() const override; 63 void setFirstPlayed( const QDateTime &dt ) override; 64 65 int playCount() const override; 66 void setPlayCount( int playCount ) override; 67 68 void beginUpdate() override; 69 void endUpdate() override; 70 71 // Meta::Observer methods 72 73 /** 74 * Notice that the linked track was destroyed. 75 */ 76 void entityDestroyed() override; 77 78 protected: 79 virtual void save() = 0; // called with m_lock locked for writing! 80 81 static const QString s_sqlDateFormat; 82 83 Meta::Track *m_track; // plain pointer not to hold reference 84 QDateTime m_lastPlayed; 85 QDateTime m_firstPlayed; 86 double m_score; 87 int m_rating; 88 int m_playCount; 89 mutable QReadWriteLock m_lock; // lock protecting access to fields. 90 91 private: 92 void commitIfInNonBatchUpdate(); // must be called with the m_lock locked for writing 93 94 /** 95 * Number of current batch operations started by @see beginUpdate() and not 96 * yet ended by @see endUpdate(). Must only be accessed with m_track held. 97 */ 98 int m_batch; 99 }; 100 101 #endif // PERSISTENTSTATISTICSSTORE_H 102