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

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 #include "Config.h"
0018 
0019 #include "MetaValues.h"
0020 #include "core/meta/support/MetaConstants.h"
0021 #include "core/support/Amarok.h"
0022 
0023 #include <KConfigGroup>
0024 #include <QIcon>
0025 #include <KLocalizedString>
0026 
0027 #include <QBrush>
0028 #include <QPalette>
0029 
0030 namespace StatSyncing
0031 {
0032     struct ProviderData {
0033         ProviderData( const QString &id_, const QString &name_, const QIcon &icon_, bool online_, bool enabled_ )
0034             : id( id_ ), name( name_ ), icon( icon_ ), online( online_ ), enabled( enabled_ )
0035         {}
0036 
0037         QString id;
0038         QString name;
0039         QIcon icon;
0040         bool online;
0041         bool enabled;
0042     };
0043 }
0044 
0045 using namespace StatSyncing;
0046 
0047 Config::Config( QObject *parent )
0048     : QAbstractListModel( parent )
0049     , m_checkedFields( 0 )
0050     , m_hasChanged( false )
0051 {
0052     read();
0053 }
0054 
0055 Config::~Config()
0056 {
0057 }
0058 
0059 int
0060 Config::rowCount( const QModelIndex &parent ) const
0061 {
0062     return parent.isValid() ? 0 : m_providerData.count();
0063 }
0064 
0065 QVariant
0066 Config::data( const QModelIndex &index, int role ) const
0067 {
0068     if( !index.isValid() )
0069         return QVariant();
0070     if( index.row() < 0 || index.row() >= m_providerData.count() )
0071         return QVariant();
0072     if( index.column() != 0 )
0073         return QVariant();
0074 
0075     const ProviderData &provider = m_providerData.at( index.row() );
0076     switch( role )
0077     {
0078         case Qt::DisplayRole:
0079             return provider.name;
0080         case Qt::DecorationRole:
0081         {
0082             if( !provider.icon.isNull() )
0083                 return provider.icon;
0084             return QIcon::fromTheme( provider.online ? "image-missing" : "network-disconnect" );
0085         }
0086         case Qt::CheckStateRole:
0087             return provider.enabled ? Qt::Checked : Qt::Unchecked;
0088         case ProviderIdRole:
0089             return provider.id;
0090         case Qt::ForegroundRole:
0091         {
0092             // we need to do this trick, because not having ItemIsEnabled in flags() has
0093             // unwanded side-effects
0094             QBrush brush;
0095             QPalette::ColorGroup group = provider.online ? QPalette::Active : QPalette::Disabled;
0096             brush.setColor( QPalette().color( group, QPalette::Text ) );
0097             return brush;
0098         }
0099         case Qt::ToolTipRole:
0100             return provider.online ? QString() : i18n( "This collection is currently offline" );
0101     }
0102     return QVariant();
0103 }
0104 
0105 bool
0106 Config::setData( const QModelIndex &index, const QVariant &value, int role )
0107 {
0108     if( !index.isValid() )
0109         return false;
0110     if( index.row() < 0 || index.row() >= m_providerData.count() )
0111         return false;
0112     if( index.column() != 0 )
0113         return false;
0114     if( role != Qt::CheckStateRole )
0115         return false;
0116 
0117     Qt::CheckState state = Qt::CheckState( value.toInt() );
0118     m_providerData[ index.row() ].enabled = ( state == Qt::Checked ) ? true : false;
0119     m_hasChanged = true;
0120     Q_EMIT dataChanged( index, index );
0121     return true;
0122 }
0123 
0124 Qt::ItemFlags
0125 Config::flags( const QModelIndex &index ) const
0126 {
0127     if( !index.isValid() )
0128         return Qt::ItemFlags();
0129     if( index.row() < 0 || index.row() >= m_providerData.count() )
0130         return Qt::ItemFlags();
0131     if( index.column() != 0 )
0132         return Qt::ItemFlags();
0133 
0134     Qt::ItemFlags flags = Qt::ItemIsUserCheckable | Qt::ItemIsEnabled;
0135     if( !m_providerData.at( index.row() ).online )
0136         flags |= Qt::ItemIsSelectable;
0137     return flags;
0138 }
0139 
0140 void
0141 Config::updateProvider( const QString &id, const QString &name, const QIcon &icon,
0142                         bool online, bool enabled )
0143 {
0144     ProviderData providerData( id, name, icon, online, enabled );
0145     for( int i = 0; i < m_providerData.count(); i++ )
0146     {
0147         if( m_providerData.at( i ).id == id )
0148         {
0149             m_providerData[ i ] = providerData;
0150             m_hasChanged = true;
0151             Q_EMIT dataChanged( index( i ), index( i ) );
0152             return;
0153         }
0154     }
0155     beginInsertRows( QModelIndex(), m_providerData.count(), m_providerData.count() );
0156     m_providerData << providerData;
0157     m_hasChanged = true;
0158     endInsertRows();
0159 }
0160 
0161 void
0162 Config::updateProvider( const QString &id, const QString &name, const QIcon &icon,
0163                         bool online )
0164 {
0165     updateProvider( id, name, icon, online, providerEnabled( id, false ) );
0166 }
0167 
0168 bool
0169 Config::forgetProvider( const QString &id )
0170 {
0171     QMutableListIterator<ProviderData> it( m_providerData );
0172     int i = 0;
0173     while( it.hasNext() )
0174     {
0175         if( it.next().id == id )
0176         {
0177             if( it.value().online )
0178                 continue; // refuse to forget online provider
0179             beginRemoveRows( QModelIndex(), i, i );
0180             it.remove();
0181             m_hasChanged = true;
0182             endRemoveRows();
0183             Q_EMIT providerForgotten( id );
0184             return true;
0185         }
0186         i++;
0187     }
0188     return false;
0189 }
0190 
0191 bool
0192 Config::providerKnown( const QString &id ) const
0193 {
0194     foreach( const ProviderData &data, m_providerData )
0195     {
0196         if( data.id == id )
0197             return true;
0198     }
0199     return false;
0200 }
0201 
0202 bool
0203 Config::providerEnabled( const QString &id, bool aDefault ) const
0204 {
0205     foreach( const ProviderData &data, m_providerData )
0206     {
0207         if( data.id == id )
0208             return data.enabled;
0209     }
0210     return aDefault;
0211 }
0212 
0213 bool
0214 Config::providerOnline( const QString &id, bool aDefault ) const
0215 {
0216     foreach( const ProviderData &data, m_providerData )
0217     {
0218         if( data.id == id )
0219             return data.online;
0220     }
0221     return aDefault;
0222 }
0223 
0224 QIcon
0225 Config::providerIcon( const QString &id ) const
0226 {
0227     foreach( const ProviderData &data, m_providerData )
0228     {
0229         if( data.id == id )
0230             return data.icon;
0231     }
0232     return QIcon();
0233 }
0234 
0235 qint64
0236 Config::checkedFields() const
0237 {
0238     return m_checkedFields;
0239 }
0240 
0241 void
0242 Config::setCheckedFields( qint64 fields )
0243 {
0244     m_checkedFields = fields;
0245     m_hasChanged = true;
0246 }
0247 
0248 QSet<QString>
0249 Config::excludedLabels() const
0250 {
0251     return m_excludedLabels;
0252 }
0253 
0254 void
0255 Config::setExcludedLabels( const QSet<QString> &labels )
0256 {
0257     m_excludedLabels = labels;
0258     m_hasChanged = true;
0259 }
0260 
0261 bool
0262 Config::hasChanged() const
0263 {
0264     return m_hasChanged;
0265 }
0266 
0267 void
0268 Config::read()
0269 {
0270     KConfigGroup group = Amarok::config( QStringLiteral("StatSyncing") );
0271 
0272     QStringList providerIds = group.readEntry( "providerIds", QStringList() );
0273     QStringList providerNames = group.readEntry( "providerNames", QStringList() );
0274     QList<bool> providerEnabledStatuses = group.readEntry( "providerEnabledStatuses", QList<bool>() );
0275     int count = qMin( providerIds.count(), providerNames.count() );
0276     count = qMin( count, providerEnabledStatuses.count() );
0277 
0278     beginResetModel();
0279     QList<ProviderData> newData;
0280     for( int i = 0; i < count; i++ )
0281     {
0282         QString id = providerIds.at( i );
0283         newData << ProviderData( id, providerNames.at( i ), providerIcon( id ),
0284                                  providerOnline( id ), providerEnabledStatuses.at( i ) );
0285     }
0286     m_providerData = newData;
0287     endResetModel();
0288 
0289     m_checkedFields = 0;
0290     QStringList fieldNames = group.readEntry( "checkedFields", QStringList( QStringLiteral("FIRST") ) );
0291     if( fieldNames == QStringList( QStringLiteral("FIRST") ) )
0292         m_checkedFields = Meta::valRating | Meta::valFirstPlayed | Meta::valLastPlayed |
0293                           Meta::valPlaycount | Meta::valLabel;
0294     else
0295     {
0296         foreach( const QString &fieldName, fieldNames )
0297             m_checkedFields |= Meta::fieldForName( fieldName );
0298     }
0299 
0300     QStringList list = group.readEntry( "excludedLabels", QStringList() );
0301     QSet<QString> addEntrySet(list.begin(), list.end());
0302     m_excludedLabels += addEntrySet;
0303 
0304     m_hasChanged = false;
0305 }
0306 
0307 void
0308 Config::save()
0309 {
0310     QStringList providerIds;
0311     QStringList providerNames;
0312     QList<bool> providerEnabledStatuses;
0313     foreach( const ProviderData &data, m_providerData )
0314     {
0315         providerIds << data.id;
0316         providerNames << data.name;
0317         providerEnabledStatuses << data.enabled;
0318     }
0319 
0320     KConfigGroup group = Amarok::config( QStringLiteral("StatSyncing") );
0321     group.writeEntry( "providerIds", providerIds );
0322     group.writeEntry( "providerNames", providerNames );
0323     group.writeEntry( "providerEnabledStatuses", providerEnabledStatuses );
0324 
0325     // prefer string representation for fwd compatibility and user-readability
0326     QStringList fieldNames;
0327     for( qint64 i = 0; i < 64; i++ )
0328     {
0329         qint64 field = 1LL << i;
0330         if( field & m_checkedFields )
0331             fieldNames << Meta::nameForField( field );
0332     }
0333     group.writeEntry( "checkedFields", fieldNames );
0334 
0335     group.writeEntry( "excludedLabels", m_excludedLabels.values() );
0336 
0337     group.sync();
0338     m_hasChanged = false;
0339 }