File indexing completed on 2024-05-05 04:49:21

0001 /****************************************************************************************
0002  * Copyright (c) 2012 Matěj Laitl <matej@laitl.cz>                                      *
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 STATSYNCING_TRACKTUPLE_H
0018 #define STATSYNCING_TRACKTUPLE_H
0019 
0020 #include "statsyncing/Provider.h"
0021 #include "statsyncing/Track.h"
0022 
0023 #include <QMap>
0024 
0025 namespace StatSyncing
0026 {
0027     class Options;
0028 
0029     /**
0030      * Smallest element of synchronization, a container for provider-to-one-track map with
0031      * methods to perform statistics synchronization and querying methods.
0032      */
0033     class TrackTuple
0034     {
0035         public:
0036             /**
0037              * Constructs an empty tuple.
0038              */
0039             TrackTuple();
0040 
0041             /**
0042              * Inserts a track into this tuple; if it already contains a track from
0043              * provider, the old track si replaced with the new one.
0044              *
0045              * It does make sense to only add tracks that are in some sence equal to tracks
0046              * already present in the tuple.
0047              *
0048              * @param provider the provider
0049              * @param track the track
0050              */
0051             void insert( ProviderPtr provider, const TrackPtr &track );
0052 
0053             /**
0054              * Returns a list of providers that have tracks in this tuple.
0055              */
0056             ProviderPtrList providers() const;
0057 
0058             /**
0059              * Returns provider of the i-th track in this tuple. If i is out of bounds,
0060              * returns null.
0061              */
0062             ProviderPtr provider( int i ) const;
0063 
0064             /**
0065              * Returns track associated with @p provider. Asserts that there's
0066              * a track from @param provider
0067              */
0068             TrackPtr track( const ProviderPtr &provider ) const;
0069 
0070             /**
0071              * Returns a number of tracks in this tuple.
0072              */
0073             int count() const;
0074 
0075             /**
0076              * Returns true if there are no tracks in the tuple, false otherwise.
0077              */
0078             bool isEmpty() const;
0079 
0080             /**
0081              * Return true if Meta::val* field @p field is going to be updated.
0082              * If @p provider is null, returns true if at least one child track
0083              * is going to be updated; otherwise works on a track from @p provider.
0084              *
0085              * @param field the field.
0086              * @param options the options.
0087              * @param provider the provider.
0088              */
0089             bool fieldUpdated( qint64 field, const Options &options, ProviderPtr provider = ProviderPtr() ) const;
0090 
0091             /**
0092              * Return true if there's at least one field going to be updated.
0093              */
0094             bool hasUpdate( const Options &options ) const;
0095 
0096             /**
0097              * Returns true if there's a (perhaps resolved) conflict in field &field
0098              */
0099             bool fieldHasConflict( qint64 field, const Options &options, bool includeResolved = true ) const;
0100 
0101             /**
0102              * Return true if there's a (perhaps resolved) conflict in this tuple.
0103              */
0104             bool hasConflict( const Options &options ) const;
0105 
0106             /**
0107              * Returns a provider whose track's rating will be used in case of conflict.
0108              * Will be null if rating provider hasn't been explicitly set.
0109              */
0110             ProviderPtr ratingProvider() const;
0111 
0112             /**
0113              * Sets the rating provider. Only accepts null provider or a provider of one
0114              * track in this tuple.
0115              */
0116             void setRatingProvider( const ProviderPtr &provider );
0117 
0118             /**
0119              * Returns providers whose labels will be OR-ed together in case of conflict.
0120              * Will be empty if no provider hasn't been explicitly set.
0121              */
0122             ProviderPtrSet labelProviders() const;
0123 
0124             /**
0125              * Sets label providers. Only accepts empty set a or a set of providers that
0126              * are contained in this tuple.
0127              */
0128             void setLabelProviders( const ProviderPtrSet &providers );
0129 
0130             /**
0131              * Return synchronized rating. Specifically, returns -1 if there's unsolved
0132              * rating conflict.
0133              */
0134             int syncedRating( const Options &options ) const;
0135             QDateTime syncedFirstPlayed( const Options &options ) const;
0136             QDateTime syncedLastPlayed( const Options &options ) const;
0137             int syncedPlaycount( const Options &options ) const;
0138             QSet<QString> syncedLabels( const Options &options ) const;
0139 
0140             /**
0141              * Perform actual synchronization. For each track, only sets fields that are
0142              * in fieldUpdated( .., .., provider). Specifically this method does not write
0143              * ratings or labels if there's unresolved rating/label conflict. Can only be
0144              * called from non-main thread and may block for longer time.
0145              *
0146              * @return a set of providers that had their track updated
0147              */
0148             ProviderPtrSet synchronize( const Options &options ) const;
0149 
0150         private:
0151             int syncedRating( const Options &options, ProviderPtr ratingProvider ) const;
0152             // @param hasConflict is set to true or false
0153             QSet<QString> syncedLabels( const Options &options, const ProviderPtrSet &labelProviders,
0154                                         bool &hasConflict ) const;
0155 
0156             static const QList<qint64> s_fields; /// list of Meta::val* fields capable of syncing
0157             QMap<ProviderPtr, TrackPtr> m_map;
0158             ProviderPtr m_ratingProvider; /// source of rating in the event of conflict
0159             ProviderPtrSet m_labelProviders; /// sources of labels in the event of conflict
0160     };
0161 
0162 } // namespace StatSyncing
0163 
0164 #endif // STATSYNCING_TRACKTUPLE_H