File indexing completed on 2024-05-19 04:49:29
0001 /**************************************************************************************** 0002 * Copyright (c) 2007 Maximilian Kossick <maximilian.kossick@googlemail.com> * 0003 * Copyright (c) 2007 Ian Monroe <ian@monroe.nu> * 0004 * Copyright (c) 2008 Mark Kretschmann <kretschmann@kde.org> * 0005 * Copyright (c) 2013 Matěj Laitl <matej@laitl.cz> * 0006 * * 0007 * This program is free software; you can redistribute it and/or modify it under * 0008 * the terms of the GNU General Public License as published by the Free Software * 0009 * Foundation; either version 2 of the License, or (at your option) any later * 0010 * version. * 0011 * * 0012 * This program is distributed in the hope that it will be useful, but WITHOUT ANY * 0013 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * 0014 * PARTICULAR PURPOSE. See the GNU General Public License for more details. * 0015 * * 0016 * You should have received a copy of the GNU General Public License along with * 0017 * this program. If not, see <http://www.gnu.org/licenses/>. * 0018 ***************************************************************************************/ 0019 0020 #ifndef META_BASE_H 0021 #define META_BASE_H 0022 0023 #include "core/amarokcore_export.h" 0024 #include "core/interfaces/MetaCapability.h" 0025 #include "core/meta/forward_declarations.h" 0026 0027 #include <QMetaType> 0028 #include <QReadWriteLock> 0029 #include <QSet> 0030 0031 namespace Meta { 0032 class Observer; 0033 0034 class AMAROKCORE_EXPORT Base : public virtual QSharedData, public MetaCapability 0035 // virtual inherit. so that implementations can be both Meta::Track and Meta::Statistics 0036 { 0037 public: 0038 Base(); 0039 ~Base() override; 0040 0041 /** 0042 * The textual label for this object. 0043 * 0044 * For a track this is the track title, for an album it is the album name. 0045 * If the name is unknown or unset then this returns an empty string. 0046 */ 0047 virtual QString name() const = 0; 0048 0049 /** 0050 * This is a nicer representation of the object. 0051 * 0052 * We will try to prevent this name from being empty. E.g. a track will fall 0053 * back to the filename if possible. 0054 */ 0055 virtual QString prettyName() const { return name(); } 0056 0057 /** 0058 * A name that can be used for sorting. 0059 * 0060 * This should usually mean that "The Beatles" is returned as "Beatles, The" 0061 */ 0062 virtual QString sortableName() const { return name(); } 0063 0064 protected: 0065 /** 0066 * Helper so that notifyObservers() implementation can be shared. Template 0067 * parameter Obs is just Observer, we add it so that Observer.h doesn't need 0068 * to be included in this header. 0069 */ 0070 template <typename T, typename Obs> 0071 void notifyObserversHelper( const T *self ) const; 0072 0073 private: 0074 // no copy allowed, since it's not safe with observer list 0075 Q_DISABLE_COPY( Base ) 0076 0077 friend class Observer; // so that Observer can call (un)subscribe() 0078 0079 /** 0080 * Subscribe @param observer for change updates. Don't ever think of calling 0081 * this method yourself or overriding it, it's highly coupled with Observer. 0082 */ 0083 void subscribe( Observer *observer ); 0084 0085 /** 0086 * Unsubscribe @param observer from change updates. Don't ever think of 0087 * calling this method yourself or overriding it, it's highly coupled with 0088 * Observer. 0089 */ 0090 void unsubscribe( Observer *observer ); 0091 0092 QSet<Observer *> m_observers; 0093 mutable QReadWriteLock m_observersLock; // guards access to m_observers 0094 }; 0095 0096 template <typename T, typename Obs> 0097 void 0098 Base::notifyObserversHelper( const T *self ) const 0099 { 0100 // observers ale allowed to remove themselves during metadataChanged() call. That's 0101 // why the lock needs to be recursive AND the lock needs to be for writing, because 0102 // a lock for reading cannot be recursively relocked for writing. 0103 QWriteLocker locker( &m_observersLock ); 0104 foreach( Obs *observer, m_observers ) 0105 { 0106 // observers can potentially remove or even destroy other observers during 0107 // metadataChanged() call. Guard against it. The guarding doesn't need to be 0108 // thread-safe, because we already hold m_observersLock (which is recursive), 0109 // so other threads wait on potential unsubscribe(). 0110 if( m_observers.contains( observer ) ) 0111 observer->metadataChanged( AmarokSharedPointer<T>( const_cast<T *>( self ) ) ); 0112 } 0113 } 0114 } 0115 0116 Q_DECLARE_METATYPE( Meta::DataPtr ) 0117 Q_DECLARE_METATYPE( Meta::DataList ) 0118 0119 AMAROKCORE_EXPORT QDebug operator<<( QDebug dbg, const Meta::Base &base ); 0120 0121 #endif // META_BASE_H