PageRenderTime 150ms CodeModel.GetById 11ms app.highlight 128ms RepoModel.GetById 1ms app.codeStats 0ms

/src/libtomahawk/TomahawkSettings.cpp

Relevant Search: With Applications for Solr and Elasticsearch

For more in depth reading about search, ranking and generally everything you could ever want to know about how lucene, elasticsearch or solr work under the hood I highly suggest this book. Easily one of the most interesting technical books I have read in a long time. If you are tasked with solving search relevance problems even if not in Solr or Elasticsearch it should be your first reference. Amazon Affiliate Link
http://github.com/tomahawk-player/tomahawk
C++ | 1764 lines | 1323 code | 386 blank | 55 comment | 123 complexity | dfe280214602c850b81f1dd9c9da8477 MD5 | raw file
   1/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
   2 *
   3 *   Copyright 2010-2015, Christian Muehlhaeuser <muesli@tomahawk-player.org>
   4 *   Copyright 2010-2011  Leo Franchi <lfranchi@kde.org>
   5 *   Copyright 2010-2012, Jeff Mitchell <jeff@tomahawk-player.org>
   6 *
   7 *   Tomahawk is free software: you can redistribute it and/or modify
   8 *   it under the terms of the GNU General Public License as published by
   9 *   the Free Software Foundation, either version 3 of the License, or
  10 *   (at your option) any later version.
  11 *
  12 *   Tomahawk is distributed in the hope that it will be useful,
  13 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 *   GNU General Public License for more details.
  16 *
  17 *   You should have received a copy of the GNU General Public License
  18 *   along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
  19 */
  20
  21#include "TomahawkSettings.h"
  22
  23#include "collection/Collection.h"
  24#include "database/DatabaseCommand_UpdateSearchIndex.h"
  25#include "database/Database.h"
  26#include "database/fuzzyindex/DatabaseFuzzyIndex.h"
  27#include "infosystem/InfoSystemCache.h"
  28#include "playlist/PlaylistUpdaterInterface.h"
  29#include "utils/Logger.h"
  30#include "utils/Json.h"
  31#include "utils/TomahawkUtils.h"
  32
  33#include "PlaylistEntry.h"
  34#include "PlaylistInterface.h"
  35#include "Source.h"
  36
  37#include <qt5keychain/keychain.h>
  38#include <QStandardPaths>
  39#include <QDir>
  40
  41using namespace Tomahawk;
  42
  43TomahawkSettings* TomahawkSettings::s_instance = 0;
  44
  45
  46inline QDataStream&
  47operator<<(QDataStream& out, const SerializedUpdaters& updaters)
  48{
  49    out <<  TOMAHAWK_SETTINGS_VERSION;
  50    out << (quint32)updaters.count();
  51    SerializedUpdaters::const_iterator iter = updaters.begin();
  52    int count = 0;
  53    for ( ; iter != updaters.end(); ++iter )
  54    {
  55        out << iter.key() << iter->type << iter->customData;
  56        count++;
  57    }
  58    Q_ASSERT( count == updaters.count() );
  59    return out;
  60}
  61
  62
  63inline QDataStream&
  64operator>>(QDataStream& in, SerializedUpdaters& updaters)
  65{
  66    quint32 count = 0, version = 0;
  67    in >> version;
  68    in >> count;
  69
  70    for ( uint i = 0; i < count; i++ )
  71    {
  72        QString key, type;
  73        QVariantHash customData;
  74        in >> key;
  75        in >> type;
  76        in >> customData;
  77        updaters.insert( key, SerializedUpdater( type, customData ) );
  78    }
  79
  80    return in;
  81}
  82
  83
  84TomahawkSettings*
  85TomahawkSettings::instance()
  86{
  87    return s_instance;
  88}
  89
  90
  91TomahawkSettings::TomahawkSettings( QObject* parent )
  92    : QSettings( parent )
  93{
  94    s_instance = this;
  95
  96    #if !(defined(Q_OS_MAC) && defined(Q_OS_WIN))
  97        QFile file( fileName() );
  98        file.setPermissions( file.permissions() & ~( QFile::ReadGroup | QFile::WriteGroup | QFile::ExeGroup | QFile::ReadOther | QFile::WriteOther | QFile::ExeOther ) );
  99    #endif
 100
 101    if ( !contains( "configversion" ) )
 102    {
 103        setValue( "configversion", TOMAHAWK_SETTINGS_VERSION );
 104        doInitialSetup();
 105    }
 106    else if ( value( "configversion" ).toUInt() != TOMAHAWK_SETTINGS_VERSION )
 107    {
 108        qDebug() << "Config version outdated, old:" << value( "configversion" ).toUInt()
 109                 << "new:" << TOMAHAWK_SETTINGS_VERSION
 110                 << "Doing upgrade, if any, and backing up";
 111
 112//         QString newname = QString( "%1.v%2" ).arg( dbname ).arg( version );
 113        if ( format() == IniFormat ||
 114             ( format() == NativeFormat
 115#ifdef Q_OS_WIN
 116               && false
 117#endif
 118             ) )
 119        {
 120            qDebug() << "Backing up old ini-style config file";
 121            const QString path = fileName();
 122            const QString newname = path + QString( ".v%1" ).arg( value( "configversion" ).toString() );
 123            QFile::copy( path, newname );
 124
 125        }
 126        int current = value( "configversion" ).toUInt();
 127        while ( current < TOMAHAWK_SETTINGS_VERSION )
 128        {
 129            doUpgrade( current, current + 1 );
 130
 131            current++;
 132        }
 133        // insert upgrade code here as required
 134        setValue( "configversion", TOMAHAWK_SETTINGS_VERSION );
 135    }
 136
 137    // Ensure last.fm and spotify accounts always exist
 138    QString spotifyAcct, lastfmAcct;
 139    foreach ( const QString& acct, value( "accounts/allaccounts" ).toStringList() )
 140    {
 141        if ( acct.startsWith( "lastfmaccount_" ) )
 142            lastfmAcct = acct;
 143        else if ( acct.startsWith( "spotifyaccount_" ) )
 144            spotifyAcct = acct;
 145    }
 146
 147    if ( spotifyAcct.isEmpty() )
 148        createSpotifyAccount();
 149    if ( lastfmAcct.isEmpty() )
 150        createLastFmAccount();
 151}
 152
 153
 154TomahawkSettings::~TomahawkSettings()
 155{
 156    s_instance = 0;
 157}
 158
 159
 160void
 161TomahawkSettings::doInitialSetup()
 162{
 163    // by default we add a local network resolver
 164    addAccount( "sipzeroconf_autocreated" );
 165
 166    createLastFmAccount();
 167    createSpotifyAccount();
 168}
 169
 170
 171void
 172TomahawkSettings::createLastFmAccount()
 173{
 174    // Add a last.fm account for scrobbling and infosystem
 175    const QString accountKey = QString( "lastfmaccount_%1" ).arg( QUuid::createUuid().toString().mid( 1, 8 ) );
 176    addAccount( accountKey );
 177
 178    beginGroup( "accounts/" + accountKey );
 179    setValue( "enabled", false );
 180    setValue( "autoconnect", true );
 181    setValue( "types", QStringList() << "ResolverType" << "StatusPushType" );
 182    endGroup();
 183
 184    QStringList allAccounts = value( "accounts/allaccounts" ).toStringList();
 185    allAccounts << accountKey;
 186    setValue( "accounts/allaccounts", allAccounts );
 187}
 188
 189
 190void
 191TomahawkSettings::createSpotifyAccount()
 192{
 193    const QString accountKey = QString( "spotifyaccount_%1" ).arg( QUuid::createUuid().toString().mid( 1, 8 ) );
 194    beginGroup( "accounts/" + accountKey );
 195    setValue( "enabled", false );
 196    setValue( "types", QStringList() << "ResolverType" );
 197    setValue( "configuration", QVariantHash() );
 198    setValue( "accountfriendlyname", "Spotify" );
 199    endGroup();
 200
 201    QStringList allAccounts = value( "accounts/allaccounts" ).toStringList();
 202    allAccounts << accountKey;
 203    setValue( "accounts/allaccounts", allAccounts );
 204}
 205
 206
 207void
 208TomahawkSettings::doUpgrade( int oldVersion, int newVersion )
 209{
 210    Q_UNUSED( newVersion );
 211
 212    if ( oldVersion == 1 )
 213    {
 214        qDebug() << "Migrating config from version 1 to 2: script resolver config name";
 215        if( contains( "script/resolvers" ) ) {
 216            setValue( "script/loadedresolvers", value( "script/resolvers" ) );
 217            remove( "script/resolvers" );
 218        }
 219    }
 220    else if ( oldVersion == 2 )
 221    {
 222        qDebug() << "Migrating config from version 2 to 3: Converting jabber and twitter accounts to new SIP Factory approach";
 223        // migrate old accounts to new system. only jabber and twitter, and max one each. create a new plugin for each if needed
 224        // not pretty as we hardcode a plugin id and assume that we know how the config layout is, but hey, this is migration after all
 225        if ( contains( "jabber/username" ) && contains( "jabber/password" ) )
 226        {
 227            QString sipName = "sipjabber";
 228            if ( value( "jabber/username" ).toString().contains( "@gmail" ) )
 229                sipName = "sipgoogle";
 230
 231            setValue( QString( "%1_legacy/username" ).arg( sipName ), value( "jabber/username" ) );
 232            setValue( QString( "%1_legacy/password" ).arg( sipName ), value( "jabber/password" ) );
 233            setValue( QString( "%1_legacy/autoconnect" ).arg( sipName ), value( "jabber/autoconnect" ) );
 234            setValue( QString( "%1_legacy/port" ).arg( sipName ), value( "jabber/port" ) );
 235            setValue( QString( "%1_legacy/server" ).arg( sipName ), value( "jabber/server" ) );
 236
 237            addSipPlugin( QString( "%1_legacy" ).arg( sipName ) );
 238
 239            remove( "jabber/username" );
 240            remove( "jabber/password" );
 241            remove( "jabber/autoconnect" );
 242            remove( "jabber/server" );
 243            remove( "jabber/port" );
 244        }
 245        if ( contains( "twitter/ScreenName" ) && contains( "twitter/OAuthToken" ) )
 246        {
 247            setValue( "siptwitter_legacy/ScreenName", value( "twitter/ScreenName" ) );
 248            setValue( "siptwitter_legacy/OAuthToken", value( "twitter/OAuthToken" ) );
 249            setValue( "siptwitter_legacy/OAuthTokenSecret", value( "twitter/OAuthTokenSecret" ) );
 250            setValue( "siptwitter_legacy/CachedFriendsSinceID", value( "twitter/CachedFriendsSinceID" ) );
 251            setValue( "siptwitter_legacy/CachedMentionsSinceID", value( "twitter/CachedMentionsSinceID" ) );
 252            setValue( "siptwitter_legacy/CachedDirectMessagesSinceID", value( "twitter/CachedDirectMessagesSinceID" ) );
 253            setValue( "siptwitter_legacy/CachedPeers", value( "twitter/CachedPeers" ) );
 254            setValue( "siptwitter_legacy/AutoConnect", value( "jabber/autoconnect" ) );
 255
 256            addSipPlugin( "siptwitter_legacy" );
 257            remove( "twitter/ScreenName" );
 258            remove( "twitter/OAuthToken" );
 259            remove( "twitter/OAuthTokenSecret" );
 260            remove( "twitter/CachedFriendsSinceID" );
 261            remove( "twitter/CachedMentionsSinceID" );
 262            remove( "twitter/CachedDirectMessagesSinceID" );
 263        }
 264        // create a zeroconf plugin too
 265        addSipPlugin( "sipzeroconf_legacy" );
 266    }
 267    else if ( oldVersion == 3 )
 268    {
 269        if ( contains( "script/atticaresolverstates" ) )
 270        {
 271            // Do messy binary upgrade. remove attica resolvers :(
 272            setValue( "script/atticaresolverstates", QVariant() );
 273
 274            QDir resolverDir = TomahawkUtils::appDataDir();
 275            if ( !resolverDir.cd( QString( "atticaresolvers" ) ) )
 276                return;
 277
 278            QStringList toremove;
 279            QStringList resolvers = resolverDir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
 280            QStringList listedResolvers = value( "script/resolvers" ).toStringList();
 281            QStringList enabledResolvers = value( "script/loadedresolvers" ).toStringList();
 282            foreach ( const QString& resolver, resolvers )
 283            {
 284                foreach ( const QString& r, listedResolvers )
 285                {
 286                    if ( r.contains( resolver ) )
 287                    {
 288                        tDebug() << "Deleting listed resolver:" << r;
 289                        listedResolvers.removeAll( r );
 290                    }
 291                }
 292                foreach ( const QString& r, enabledResolvers )
 293                {
 294                    if ( r.contains( resolver ) )
 295                    {
 296                        tDebug() << "Deleting enabled resolver:" << r;
 297                        enabledResolvers.removeAll( r );
 298                    }
 299                }
 300            }
 301            setValue( "script/resolvers", listedResolvers );
 302            setValue( "script/loadedresolvers", enabledResolvers );
 303            tDebug() << "UPGRADING AND DELETING:" << resolverDir.absolutePath();
 304            TomahawkUtils::removeDirectory( resolverDir.absolutePath() );
 305        }
 306    }
 307    else if ( oldVersion == 4 || oldVersion == 5 )
 308    {
 309        // 0.3.0 contained a bug which prevent indexing local files. Force a reindex.
 310        Tomahawk::DatabaseFuzzyIndex::wipeIndex();
 311        updateIndex();
 312    }
 313    else if ( oldVersion == 6 )
 314    {
 315        // Migrate to accounts from sipplugins.
 316        // collect old connected and enabled sip plugins
 317        const QStringList allSip = sipPlugins();
 318        const QStringList enabledSip = enabledSipPlugins();
 319
 320        QStringList accounts;
 321        foreach ( const QString& sipPlugin, allSip )
 322        {
 323            const QStringList parts = sipPlugin.split( "_" );
 324            Q_ASSERT( parts.size() == 2 );
 325
 326            const QString pluginName = parts[ 0 ];
 327            const QString pluginId = parts[ 1 ];
 328
 329            // new key, <plugin>account_<id>
 330            QString rawpluginname = pluginName;
 331            rawpluginname.replace( "sip", "" );
 332            if ( rawpluginname.contains( "jabber" ) )
 333                rawpluginname.replace( "jabber", "xmpp" );
 334
 335            QString accountKey = QString( "%1account_%2" ).arg( rawpluginname ).arg( pluginId );
 336
 337            if ( pluginName == "sipjabber" || pluginName == "sipgoogle" )
 338            {
 339                QVariantHash credentials;
 340                credentials[ "username" ] = value( sipPlugin + "/username" );
 341                credentials[ "password" ] = value( sipPlugin + "/password" );
 342
 343                QVariantHash configuration;
 344                configuration[ "port" ] = value( sipPlugin + "/port" );
 345                configuration[ "server" ] = value( sipPlugin + "/server" );
 346
 347                setValue( QString( "accounts/%1/credentials" ).arg( accountKey ), credentials );
 348                setValue( QString( "accounts/%1/configuration" ).arg( accountKey ), configuration );
 349                setValue( QString( "accounts/%1/accountfriendlyname" ).arg( accountKey ), value( sipPlugin + "/username" ) );
 350
 351            }
 352            else if ( pluginName == "siptwitter" )
 353            {
 354                // Only port twitter plugin if there's a valid twitter config
 355                if ( value( sipPlugin + "/oauthtokensecret" ).toString().isEmpty() &&
 356                     value( sipPlugin + "/oauthtoken" ).toString().isEmpty() &&
 357                     value( sipPlugin + "/screenname" ).toString().isEmpty() )
 358                    continue;
 359
 360                QVariantMap credentials;
 361                credentials[ "oauthtoken" ] = value( sipPlugin + "/oauthtoken" );
 362                credentials[ "oauthtokensecret" ] = value( sipPlugin + "/oauthtokensecret" );
 363                credentials[ "username" ] = value( sipPlugin + "/screenname" );
 364
 365                QVariantHash configuration;
 366                configuration[ "cachedfriendssinceid" ] = value( sipPlugin + "/cachedfriendssinceid" );
 367                configuration[ "cacheddirectmessagessinceid" ] = value( sipPlugin + "/cacheddirectmessagessinceid" );
 368                configuration[ "cachedpeers" ] = value( sipPlugin + "/cachedpeers" );
 369                qDebug() << "FOUND CACHED PEERS:" << value( sipPlugin + "/cachedpeers" ).toHash();
 370                configuration[ "cachedmentionssinceid" ] = value( sipPlugin + "/cachedmentionssinceid" );
 371                configuration[ "saveddbid" ] = value( sipPlugin + "/saveddbid" );
 372
 373                setValue( QString( "accounts/%1/credentials" ).arg( accountKey ), credentials );
 374                setValue( QString( "accounts/%1/configuration" ).arg( accountKey ), configuration );
 375                setValue( QString( "accounts/%1/accountfriendlyname" ).arg( accountKey ), "@" + value( sipPlugin + "/screenname" ).toString() );
 376                sync();
 377            }
 378            else if ( pluginName == "sipzeroconf" )
 379            {
 380                setValue( QString( "accounts/%1/accountfriendlyname" ).arg( accountKey ), tr( "Local Network" ) );
 381            }
 382
 383            beginGroup( "accounts/" + accountKey );
 384            setValue( "enabled", enabledSip.contains( sipPlugin ) == true );
 385            setValue( "autoconnect", true );
 386            setValue( "acl", QVariantHash() );
 387            setValue( "types", QStringList() << "SipType" );
 388            endGroup();
 389            accounts << accountKey;
 390
 391            remove( sipPlugin );
 392        }
 393        remove( "sip" );
 394
 395        // Migrate all resolvers from old resolvers settings to new accounts system
 396        const QStringList allResolvers = value( "script/resolvers" ).toStringList();
 397        const QStringList enabledResolvers = value( "script/loadedresolvers" ).toStringList();
 398
 399        foreach ( const QString& resolver, allResolvers )
 400        {
 401            // We handle last.fm resolvers differently.
 402            if ( resolver.contains( "lastfm" ) )
 403                continue;
 404
 405            const QString accountKey = QString( "resolveraccount_%1" ).arg( QUuid::createUuid().toString().mid( 1, 8 ) );
 406            accounts << accountKey;
 407
 408            beginGroup( "accounts/" + accountKey );
 409            setValue( "accountfriendlyname", resolver );
 410            setValue( "enabled", enabledResolvers.contains( resolver ) == true );
 411            setValue( "autoconnect", true );
 412            setValue( "types", QStringList() << "ResolverType" );
 413
 414            QVariantHash configuration;
 415            configuration[ "path" ] = resolver;
 416
 417            // reasonably ugly check for attica resolvers
 418            if ( resolver.contains( "atticaresolvers" ) && resolver.contains( "code" ) )
 419            {
 420                setValue( "atticaresolver", true );
 421
 422                QFileInfo info( resolver );
 423                configuration[ "atticaId" ] = info.baseName();
 424            }
 425
 426            setValue( "configuration", configuration );
 427            endGroup();
 428        }
 429
 430        // Add a Last.Fm account since we now moved the infoplugin into the account
 431        const QString accountKey = QString( "lastfmaccount_%1" ).arg( QUuid::createUuid().toString().mid( 1, 8 ) );
 432        accounts << accountKey;
 433        const QString lfmUsername = value( "lastfm/username" ).toString();
 434        const QString lfmPassword = value( "lastfm/password" ).toString();
 435        const bool scrobble = value( "lastfm/enablescrobbling", false ).toBool();
 436        beginGroup( "accounts/" + accountKey );
 437        bool hasLastFmEnabled = false;
 438        foreach ( const QString& r, enabledResolvers )
 439        {
 440            if ( r.contains( "lastfm" ) )
 441            {
 442                hasLastFmEnabled = true;
 443                break;
 444            }
 445        }
 446        setValue( "enabled", hasLastFmEnabled );
 447        setValue( "autoconnect", true );
 448        setValue( "types", QStringList() << "ResolverType" << "StatusPushType" );
 449        QVariantMap credentials;
 450        credentials[ "username" ] = lfmUsername;
 451        credentials[ "password" ] = lfmPassword;
 452        credentials[ "session" ] = value( "lastfm/session" ).toString();
 453        setValue( "credentials", credentials );
 454        QVariantHash configuration;
 455        configuration[ "scrobble" ] = scrobble;
 456        setValue( "configuration", configuration );
 457        endGroup();
 458
 459        remove( "lastfm" );
 460
 461        remove( "script/resolvers" );
 462        remove( "script/loadedresolvers" );
 463
 464        setValue( "accounts/allaccounts", accounts );
 465    }
 466    else if ( oldVersion == 7 )
 467    {
 468        // Upgrade spotify resolver to standalone account, if one exists
 469        beginGroup( "accounts" );
 470        QStringList allAccounts = value( "allaccounts" ).toStringList();
 471        foreach ( const QString& account, allAccounts )
 472        {
 473            if ( account.startsWith( "resolveraccount_" ) && value( QString( "%1/accountfriendlyname" ).arg( account ) ).toString().endsWith( "spotify_tomahawkresolver" ) )
 474            {
 475                // This is a spotify resolver, convert!
 476                const QVariantHash configuration = value( QString( "%1/configuration" ).arg( account ) ).toHash();
 477                const bool enabled = value( QString( "%1/enabled" ).arg( account ) ).toBool();
 478                const bool autoconnect = value( QString( "%1/autoconnect" ).arg( account ) ).toBool();
 479
 480                qDebug() << "Migrating Spotify resolver from legacy resolver type, path is:" << configuration[ "path" ].toString();
 481
 482                remove( account );
 483
 484                // Create new account
 485                QString newAccount = account;
 486                newAccount.replace( "resolveraccount_", "spotifyaccount_" );
 487                beginGroup( newAccount );
 488                setValue( "enabled", enabled );
 489                setValue( "autoconnect", autoconnect );
 490                setValue( "types", QStringList() << "ResolverType" );
 491                setValue( "accountfriendlyname", "Spotify" );
 492                setValue( "configuration", configuration );
 493                endGroup();
 494
 495                allAccounts.replace( allAccounts.indexOf( account ), newAccount );
 496            }
 497        }
 498
 499        setValue( "allaccounts", allAccounts );
 500        endGroup();
 501    }
 502    else if ( oldVersion == 8 )
 503    {
 504        // Some users got duplicate accounts for some reason, so make them unique if we can
 505        QSet< QString > uniqueFriendlyNames;
 506        beginGroup("accounts");
 507        const QStringList accounts = childGroups();
 508        QStringList allAccounts = value( "allaccounts" ).toStringList();
 509
 510//        qDebug() << "Got accounts to migrate:" << accounts;
 511        foreach ( const QString& account, accounts )
 512        {
 513            if ( !allAccounts.contains( account ) ) // orphan
 514            {
 515                qDebug() << "Found account not in allaccounts list!" << account << "is a dup!";
 516                remove( account );
 517                continue;
 518            }
 519
 520            const QString friendlyName = value( QString( "%1/accountfriendlyname" ).arg( account ) ).toString();
 521            if ( !uniqueFriendlyNames.contains( friendlyName ) )
 522            {
 523                uniqueFriendlyNames.insert( friendlyName );
 524                continue;
 525            }
 526            else
 527            {
 528                // Duplicate..?
 529                qDebug() << "Found duplicate account friendly name:" << account << friendlyName << "is a dup!";
 530                remove( account );
 531                allAccounts.removeAll( account );
 532            }
 533        }
 534        qDebug() << "Ended up with all accounts list:" << allAccounts << "and all accounts:" << childGroups();
 535        setValue( "allaccounts", allAccounts );
 536        endGroup();
 537    }
 538    else if ( oldVersion == 9 )
 539    {
 540        // Upgrade single-updater-per-playlist to list-per-playlist
 541        beginGroup( "playlistupdaters" );
 542        const QStringList playlists = childGroups();
 543
 544        SerializedUpdaters updaters;
 545        foreach ( const QString& playlist, playlists )
 546        {
 547            beginGroup( playlist );
 548            const QString type = value( "type" ).toString();
 549
 550            QVariantHash extraData;
 551            foreach ( const QString& key, childKeys() )
 552            {
 553                if ( key == "type" )
 554                    continue;
 555
 556                extraData[ key ] = value( key );
 557            }
 558
 559            updaters.insert( playlist, SerializedUpdater( type, extraData ) );
 560
 561            endGroup();
 562        }
 563
 564        endGroup();
 565        remove( "playlistupdaters" );
 566
 567        setValue( "playlists/updaters", QVariant::fromValue< SerializedUpdaters >( updaters ) );
 568
 569    }
 570    else if ( oldVersion == 11 )
 571    {
 572        // If the user doesn't have a spotify account, create one, since now it
 573        // is like the last.fm account and always exists
 574        QStringList allAccounts = value( "accounts/allaccounts" ).toStringList();
 575        QString acct;
 576        foreach ( const QString& account, allAccounts )
 577        {
 578            if ( account.startsWith( "spotifyaccount_" ) )
 579            {
 580                acct = account;
 581                break;
 582            }
 583        }
 584
 585        if ( !acct.isEmpty() )
 586        {
 587            beginGroup( "accounts/" + acct );
 588            QVariantHash conf = value( "configuration" ).toHash();
 589            foreach ( const QString& key, conf.keys() )
 590                qDebug() << key << conf[ key ].toString();
 591            endGroup();
 592        }
 593        else
 594        {
 595            createSpotifyAccount();
 596        }
 597    }
 598    else if ( oldVersion == 12 )
 599    {
 600        // Force attica resolver pixmap cache refresh
 601        QDir cacheDir = TomahawkUtils::appDataDir();
 602        if ( cacheDir.cd( "atticacache" ) )
 603        {
 604            QStringList files = cacheDir.entryList( QStringList() << "*.png" );
 605            foreach ( const QString& file, files )
 606            {
 607                const bool removed = cacheDir.remove( file );
 608                tDebug() << "Tried to remove cached image, succeeded?" << removed << cacheDir.filePath( file );
 609            }
 610        }
 611    }
 612    else if ( oldVersion == 13 )
 613    {
 614        //Delete old echonest_stylesandmoods.dat file
 615        QFile dataFile( TomahawkUtils::appDataDir().absoluteFilePath( "echonest_stylesandmoods.dat" ) );
 616        const bool removed = dataFile.remove();
 617        tDebug() << "Tried to remove echonest_stylesandmoods.dat, succeeded?" << removed;
 618    }
 619    else if ( oldVersion == 14 )
 620    {
 621        //No upgrade on OSX: we keep storing credentials in TomahawkSettings
 622        //because QtKeychain and/or OSX Keychain is flaky. --Teo 12/2013
 623#ifndef Q_OS_MAC
 624        const QStringList accounts = value( "accounts/allaccounts" ).toStringList();
 625        tDebug() << "About to move these accounts to QtKeychain:" << accounts;
 626
 627        //Move storage of Credentials from QSettings to QtKeychain
 628        foreach ( const QString& account, accounts )
 629        {
 630            tDebug() << "beginGroup" << QString( "accounts/%1" ).arg( account );
 631            beginGroup( QString( "accounts/%1" ).arg( account ) );
 632            const QVariantHash hash = value( "credentials" ).toHash();
 633            tDebug() << hash[ "username" ]
 634                     << ( hash[ "password" ].isNull() ? ", no password" : ", has password" );
 635
 636            QVariantMap creds;
 637            for ( QVariantHash::const_iterator it = hash.constBegin(); it != hash.constEnd(); ++it )
 638            {
 639                creds.insert( it.key(), it.value() );
 640
 641            }
 642            if ( !creds.isEmpty() )
 643            {
 644                QKeychain::WritePasswordJob* j = new QKeychain::WritePasswordJob( QLatin1String( "Tomahawk" ), this );
 645                j->setKey( account );
 646                j->setAutoDelete( true );
 647#if defined( Q_OS_UNIX ) && !defined( Q_OS_MAC )
 648                j->setInsecureFallback( true );
 649#endif
 650                bool ok;
 651                QByteArray data = TomahawkUtils::toJson( creds, &ok );
 652
 653                if ( ok )
 654                {
 655                    tDebug() << "Performing upgrade for account" << account;
 656                }
 657                else
 658                {
 659                    tDebug() << "Upgrade error: cannot serialize credentials to JSON for account" << account;
 660                }
 661
 662                j->setTextData( data );
 663                j->start();
 664            }
 665
 666            remove( "credentials" );
 667
 668            endGroup();
 669        }
 670#endif //Q_OS_MAC
 671    }
 672    else if ( oldVersion == 15 )
 673    {
 674        // 0.8.0 switches to Lucene++. Force a reindex.
 675        // (obsoleted by version 16 update)
 676    }
 677    else if ( oldVersion == 16 )
 678    {
 679        Tomahawk::DatabaseFuzzyIndex::wipeIndex();
 680        updateIndex();
 681    }
 682}
 683
 684
 685void
 686TomahawkSettings::setAcceptedLegalWarning( bool accept )
 687{
 688    setValue( "acceptedLegalWarning", accept );
 689}
 690
 691
 692bool
 693TomahawkSettings::acceptedLegalWarning() const
 694{
 695    return value( "acceptedLegalWarning", false ).toBool();
 696}
 697
 698
 699void
 700TomahawkSettings::setInfoSystemCacheVersion( uint version )
 701{
 702    setValue( "infosystemcacheversion", version );
 703}
 704
 705
 706uint
 707TomahawkSettings::infoSystemCacheVersion() const
 708{
 709    return value( "infosystemcacheversion", 0 ).toUInt();
 710}
 711
 712
 713void
 714TomahawkSettings::setGenericCacheVersion( uint version )
 715{
 716    setValue( "genericcacheversion", version );
 717}
 718
 719
 720uint
 721TomahawkSettings::genericCacheVersion() const
 722{
 723    return value( "genericcacheversion", 0 ).toUInt();
 724}
 725
 726
 727QString
 728TomahawkSettings::storageCacheLocation() const
 729{
 730    return QStandardPaths::writableLocation( QStandardPaths::CacheLocation );
 731}
 732
 733
 734QStringList
 735TomahawkSettings::scannerPaths() const
 736{
 737    QString musicLocation;
 738
 739    musicLocation = QStandardPaths::writableLocation( QStandardPaths::MusicLocation );
 740
 741    return value( "scanner/paths", musicLocation ).toStringList();
 742}
 743
 744
 745void
 746TomahawkSettings::setScannerPaths( const QStringList& paths )
 747{
 748    setValue( "scanner/paths", paths );
 749}
 750
 751
 752bool
 753TomahawkSettings::hasScannerPaths() const
 754{
 755    //FIXME: After enough time, remove this hack
 756    return contains( "scanner/paths" ) || contains( "scannerpath" ) || contains( "scannerpaths" );
 757}
 758
 759
 760uint
 761TomahawkSettings::scannerTime() const
 762{
 763    return value( "scanner/intervaltime", 60 ).toUInt();
 764}
 765
 766
 767void
 768TomahawkSettings::setScannerTime( uint time )
 769{
 770    setValue( "scanner/intervaltime", time );
 771}
 772
 773
 774bool
 775TomahawkSettings::watchForChanges() const
 776{
 777    return value( "scanner/watchforchanges", false ).toBool();
 778}
 779
 780
 781void
 782TomahawkSettings::setWatchForChanges( bool watch )
 783{
 784    setValue( "scanner/watchforchanges", watch );
 785}
 786
 787
 788QString
 789TomahawkSettings::downloadsPreferredFormat() const
 790{
 791    return value( "downloadmanager/preferredFormat", "MP3" ).toString();
 792}
 793
 794
 795void
 796TomahawkSettings::setDownloadsPreferredFormat( const QString& format )
 797{
 798    setValue( "downloadmanager/preferredFormat", format );
 799}
 800
 801
 802QString
 803TomahawkSettings::downloadsPath() const
 804{
 805    QString musicLocation;
 806    if ( !scannerPaths().isEmpty() )
 807        musicLocation = scannerPaths().first();
 808
 809    return value( "downloadmanager/path", musicLocation ).toString();
 810}
 811
 812
 813void
 814TomahawkSettings::setDownloadsPath( const QString& path )
 815{
 816    setValue( "downloadmanager/path", path );
 817}
 818
 819
 820QVariantList
 821TomahawkSettings::downloadStates() const
 822{
 823    return value( "downloadmanager/states", QVariantList() ).toList();
 824}
 825
 826
 827void
 828TomahawkSettings::setDownloadStates( const QVariantList& downloads )
 829{
 830    setValue( "downloadmanager/states", downloads );
 831}
 832
 833
 834bool
 835TomahawkSettings::httpEnabled() const
 836{
 837    return value( "network/http", true ).toBool();
 838}
 839
 840
 841void
 842TomahawkSettings::setHttpEnabled( bool enable )
 843{
 844    setValue( "network/http", enable );
 845}
 846
 847
 848bool
 849TomahawkSettings::httpBindAll() const
 850{
 851    return value ( "network/httpbindall", false ).toBool();
 852}
 853
 854
 855void
 856TomahawkSettings::setHttpBindAll( bool bindAll )
 857{
 858    setValue( "network/httpbindall", bindAll );
 859}
 860
 861
 862bool
 863TomahawkSettings::crashReporterEnabled() const
 864{
 865    return value( "ui/crashReporter", true ).toBool();
 866}
 867
 868
 869void
 870TomahawkSettings::setCrashReporterEnabled( bool enable )
 871{
 872    setValue( "ui/crashReporter", enable );
 873}
 874
 875
 876bool
 877TomahawkSettings::songChangeNotificationEnabled() const
 878{
 879    return value( "ui/songChangeNotification", true ).toBool();
 880}
 881
 882
 883void
 884TomahawkSettings::setSongChangeNotificationEnabled(bool enable)
 885{
 886    setValue( "ui/songChangeNotification", enable );
 887}
 888
 889
 890bool
 891TomahawkSettings::autoDetectExternalIp() const
 892{
 893    return value( "network/auto-detect-external-ip" ).toBool();
 894}
 895
 896
 897void
 898TomahawkSettings::setAutoDetectExternalIp( bool autoDetect )
 899{
 900    setValue( "network/auto-detect-external-ip", autoDetect );
 901}
 902
 903
 904unsigned int
 905TomahawkSettings::volume() const
 906{
 907    return value( "audio/volume", 75 ).toUInt();
 908}
 909
 910
 911void
 912TomahawkSettings::setVolume( unsigned int volume )
 913{
 914    setValue( "audio/volume", volume );
 915}
 916
 917
 918bool
 919TomahawkSettings::muted() const
 920{
 921    return value( "audio/muted" ).toBool();
 922}
 923
 924
 925void
 926TomahawkSettings::setMuted( bool muted )
 927{
 928    setValue( "audio/muted", muted );
 929}
 930
 931
 932QString
 933TomahawkSettings::proxyHost() const
 934{
 935    return value( "network/proxy/host", QString() ).toString();
 936}
 937
 938
 939void
 940TomahawkSettings::setProxyHost( const QString& host )
 941{
 942    setValue( "network/proxy/host", host );
 943}
 944
 945
 946QString
 947TomahawkSettings::proxyNoProxyHosts() const
 948{
 949    return value( "network/proxy/noproxyhosts", QString() ).toString();
 950}
 951
 952
 953void
 954TomahawkSettings::setProxyNoProxyHosts( const QString& hosts )
 955{
 956    setValue( "network/proxy/noproxyhosts", hosts );
 957}
 958
 959
 960qulonglong
 961TomahawkSettings::proxyPort() const
 962{
 963    return value( "network/proxy/port", 1080 ).toULongLong();
 964}
 965
 966
 967void
 968TomahawkSettings::setProxyPort( const qulonglong port )
 969{
 970    setValue( "network/proxy/port", port );
 971}
 972
 973
 974QString
 975TomahawkSettings::proxyUsername() const
 976{
 977    return value( "network/proxy/username", QString() ).toString();
 978}
 979
 980
 981void
 982TomahawkSettings::setProxyUsername( const QString& username )
 983{
 984    setValue( "network/proxy/username", username );
 985}
 986
 987
 988QString
 989TomahawkSettings::proxyPassword() const
 990{
 991    return value( "network/proxy/password", QString() ).toString();
 992}
 993
 994
 995void
 996TomahawkSettings::setProxyPassword( const QString& password )
 997{
 998    setValue( "network/proxy/password", password );
 999}
1000
1001
1002QNetworkProxy::ProxyType
1003TomahawkSettings::proxyType() const
1004{
1005    return static_cast< QNetworkProxy::ProxyType>( value( "network/proxy/type", QNetworkProxy::NoProxy ).toInt() );
1006}
1007
1008
1009void
1010TomahawkSettings::setProxyType( const QNetworkProxy::ProxyType type )
1011{
1012    setValue( "network/proxy/type", static_cast< uint >( type ) );
1013}
1014
1015
1016bool
1017TomahawkSettings::proxyDns() const
1018{
1019    return value( "network/proxy/dns", false ).toBool();
1020}
1021
1022
1023void
1024TomahawkSettings::setProxyDns( bool lookupViaProxy )
1025{
1026    setValue( "network/proxy/dns", lookupViaProxy );
1027}
1028
1029
1030QVariantList
1031TomahawkSettings::aclEntries() const
1032{
1033    QVariant retVal = value( "acl/entries", QVariantList() );
1034    if ( retVal.isValid() && retVal.canConvert< QVariantList >() )
1035        return retVal.toList();
1036
1037    return QVariantList();
1038}
1039
1040
1041void
1042TomahawkSettings::setAclEntries( const QVariantList &entries )
1043{
1044    tDebug() << "Setting entries";
1045    setValue( "acl/entries", entries );
1046    sync();
1047    tDebug() << "Done setting entries";
1048}
1049
1050
1051bool
1052TomahawkSettings::isSslCertKnown( const QByteArray& sslDigest ) const
1053{
1054    return value( "network/ssl/certs" ).toMap().contains( sslDigest );
1055}
1056
1057
1058bool
1059TomahawkSettings::isSslCertTrusted( const QByteArray& sslDigest ) const
1060{
1061    return value( "network/ssl/certs" ).toMap().value( sslDigest, false ).toBool();
1062}
1063
1064
1065void
1066TomahawkSettings::setSslCertTrusted( const QByteArray& sslDigest, bool trusted )
1067{
1068    QVariantMap map = value( "network/ssl/certs" ).toMap();
1069    map[ sslDigest ] = trusted;
1070
1071    setValue( "network/ssl/certs", map );
1072}
1073
1074
1075QByteArray
1076TomahawkSettings::mainWindowGeometry() const
1077{
1078    return value( "ui/mainwindow/geometry" ).toByteArray();
1079}
1080
1081
1082void
1083TomahawkSettings::setMainWindowGeometry( const QByteArray& geom )
1084{
1085    setValue( "ui/mainwindow/geometry", geom );
1086}
1087
1088
1089QByteArray
1090TomahawkSettings::mainWindowState() const
1091{
1092    return value( "ui/mainwindow/state" ).toByteArray();
1093}
1094
1095
1096void
1097TomahawkSettings::setMainWindowState( const QByteArray& state )
1098{
1099    setValue( "ui/mainwindow/state", state );
1100}
1101
1102
1103QByteArray
1104TomahawkSettings::mainWindowSplitterState() const
1105{
1106    return value( "ui/mainwindow/splitterState" ).toByteArray();
1107}
1108
1109
1110void
1111TomahawkSettings::setMainWindowSplitterState( const QByteArray& state )
1112{
1113    setValue( "ui/mainwindow/splitterState", state );
1114}
1115
1116
1117bool
1118TomahawkSettings::verboseNotifications() const
1119{
1120    return value( "ui/notifications/verbose", false ).toBool();
1121}
1122
1123
1124void
1125TomahawkSettings::setVerboseNotifications( bool notifications )
1126{
1127    setValue( "ui/notifications/verbose", notifications );
1128}
1129
1130
1131bool
1132TomahawkSettings::menuBarVisible() const
1133{
1134#ifndef Q_OS_MAC
1135    return value( "ui/mainwindow/menuBarVisible", true ).toBool();
1136#else
1137    return true;
1138#endif
1139}
1140
1141
1142void
1143TomahawkSettings::setMenuBarVisible( bool visible )
1144{
1145#ifndef Q_OS_MAC
1146    setValue( "ui/mainwindow/menuBarVisible", visible );
1147#endif
1148}
1149
1150
1151bool
1152TomahawkSettings::fullscreenEnabled() const
1153{
1154    return value( "ui/mainwindow/fullscreenEnabled", false ).toBool();
1155}
1156
1157
1158void
1159TomahawkSettings::setFullscreenEnabled( bool enabled )
1160{
1161    setValue( "ui/mainwindow/fullscreenEnabled", enabled );
1162}
1163
1164
1165bool
1166TomahawkSettings::showOfflineSources() const
1167{
1168    return value( "collection/sources/showoffline", false ).toBool();
1169}
1170
1171
1172void
1173TomahawkSettings::setShowOfflineSources( bool show )
1174{
1175    setValue( "collection/sources/showoffline", show );
1176}
1177
1178
1179bool
1180TomahawkSettings::enableEchonestCatalogs() const
1181{
1182    return value( "collection/enable_catalogs", false ).toBool();
1183}
1184
1185
1186void
1187TomahawkSettings::setEnableEchonestCatalogs( bool enable )
1188{
1189    setValue( "collection/enable_catalogs", enable );
1190}
1191
1192
1193QByteArray
1194TomahawkSettings::playlistColumnSizes( const QString& playlistid ) const
1195{
1196    return value( QString( "ui/playlist/%1/columnSizes" ).arg( playlistid ) ).toByteArray();
1197}
1198
1199
1200void
1201TomahawkSettings::setPlaylistColumnSizes( const QString& playlistid, const QByteArray& state )
1202{
1203    if ( playlistid.isEmpty() )
1204        return;
1205
1206    setValue( QString( "ui/playlist/%1/columnSizes" ).arg( playlistid ), state );
1207}
1208
1209
1210bool
1211TomahawkSettings::shuffleState( const QString& playlistid ) const
1212{
1213    return value( QString( "ui/playlist/%1/shuffleState" ).arg( playlistid ) ).toBool();
1214}
1215
1216
1217void
1218TomahawkSettings::setShuffleState( const QString& playlistid, bool state)
1219{
1220    setValue( QString( "ui/playlist/%1/shuffleState" ).arg( playlistid ), state );
1221}
1222
1223
1224void
1225TomahawkSettings::removePlaylistSettings( const QString& playlistid )
1226{
1227    remove( QString( "ui/playlist/%1/shuffleState" ).arg( playlistid ) );
1228    remove( QString( "ui/playlist/%1/repeatMode" ).arg( playlistid ) );
1229}
1230
1231
1232QVariant
1233TomahawkSettings::queueState() const
1234{
1235    return value( QString( "playlists/queue/state" ) );
1236}
1237
1238
1239void
1240TomahawkSettings::setQueueState( const QVariant& state )
1241{
1242    setValue( QString( "playlists/queue/state" ), state );
1243}
1244
1245
1246void
1247TomahawkSettings::setRepeatMode( const QString& playlistid, Tomahawk::PlaylistModes::RepeatMode mode )
1248{
1249    setValue( QString( "ui/playlist/%1/repeatMode" ).arg( playlistid ), (int)mode );
1250}
1251
1252
1253Tomahawk::PlaylistModes::RepeatMode
1254TomahawkSettings::repeatMode( const QString& playlistid )
1255{
1256    return (PlaylistModes::RepeatMode)value( QString( "ui/playlist/%1/repeatMode" ).arg( playlistid ) ).toInt();
1257}
1258
1259
1260QStringList
1261TomahawkSettings::recentlyPlayedPlaylistGuids( unsigned int amount ) const
1262{
1263    QStringList p = value( "playlists/recentlyPlayed" ).toStringList();
1264
1265    while ( amount && p.count() > (int)amount )
1266        p.removeAt( 0 );
1267
1268    return p;
1269}
1270
1271
1272void
1273TomahawkSettings::appendRecentlyPlayedPlaylist( const QString& playlistguid, int sourceId )
1274{
1275    QStringList playlist_guids = value( "playlists/recentlyPlayed" ).toStringList();
1276
1277    playlist_guids.removeAll( playlistguid );
1278    playlist_guids.append( playlistguid );
1279
1280    setValue( "playlists/recentlyPlayed", playlist_guids );
1281
1282    emit recentlyPlayedPlaylistAdded( playlistguid, sourceId );
1283}
1284
1285
1286QString
1287TomahawkSettings::bookmarkPlaylist() const
1288{
1289    return value( "playlists/bookmark", QString() ).toString();
1290}
1291
1292
1293void
1294TomahawkSettings::setBookmarkPlaylist( const QString& guid )
1295{
1296    setValue( "playlists/bookmark", guid );
1297}
1298
1299
1300QStringList
1301TomahawkSettings::sipPlugins() const
1302{
1303    return value( "sip/allplugins", QStringList() ).toStringList();
1304}
1305
1306
1307void
1308TomahawkSettings::setSipPlugins( const QStringList& plugins )
1309{
1310    setValue( "sip/allplugins", plugins );
1311}
1312
1313
1314QStringList
1315TomahawkSettings::enabledSipPlugins() const
1316{
1317    return value( "sip/enabledplugins", QStringList() ).toStringList();
1318}
1319
1320
1321void
1322TomahawkSettings::setEnabledSipPlugins( const QStringList& list )
1323{
1324    setValue( "sip/enabledplugins", list );
1325}
1326
1327
1328void
1329TomahawkSettings::enableSipPlugin( const QString& pluginId )
1330{
1331    QStringList list = enabledSipPlugins();
1332    list << pluginId;
1333    setEnabledSipPlugins( list );
1334}
1335
1336
1337void
1338TomahawkSettings::disableSipPlugin( const QString& pluginId )
1339{
1340    QStringList list = enabledSipPlugins();
1341    list.removeAll( pluginId );
1342    setEnabledSipPlugins( list );
1343}
1344
1345
1346void
1347TomahawkSettings::addSipPlugin( const QString& pluginId, bool enable )
1348{
1349    QStringList list = sipPlugins();
1350    list << pluginId;
1351    setSipPlugins( list );
1352
1353    if ( enable )
1354        enableSipPlugin( pluginId );
1355}
1356
1357
1358void
1359TomahawkSettings::removeSipPlugin( const QString& pluginId )
1360{
1361    QStringList list = sipPlugins();
1362    list.removeAll( pluginId );
1363    setSipPlugins( list );
1364
1365    if( enabledSipPlugins().contains( pluginId ) )
1366        disableSipPlugin( pluginId );
1367}
1368
1369
1370QStringList
1371TomahawkSettings::accounts() const
1372{
1373    QStringList accounts = value( "accounts/allaccounts", QStringList() ).toStringList();
1374    accounts.removeDuplicates();
1375
1376    return accounts;
1377}
1378
1379
1380void
1381TomahawkSettings::setAccounts( const QStringList& accountIds )
1382{
1383    QStringList accounts = accountIds;
1384    accounts.removeDuplicates();
1385
1386    setValue( "accounts/allaccounts", accounts );
1387}
1388
1389
1390void
1391TomahawkSettings::addAccount( const QString& accountId )
1392{
1393    QStringList list = accounts();
1394    list << accountId;
1395    setAccounts( list );
1396}
1397
1398
1399void
1400TomahawkSettings::removeAccount( const QString& accountId )
1401{
1402    QStringList list = accounts();
1403    list.removeAll( accountId );
1404    setAccounts( list );
1405}
1406
1407
1408Tomahawk::Network::ExternalAddress::Mode
1409TomahawkSettings::externalAddressMode()
1410{
1411    if ( value( "network/prefer-static-host-and-port", false ).toBool() )
1412    {
1413        remove( "network/prefer-static-host-and-port" );
1414        setValue( "network/external-address-mode", Tomahawk::Network::ExternalAddress::Static );
1415    }
1416    return (Tomahawk::Network::ExternalAddress::Mode) value( "network/external-address-mode", Tomahawk::Network::ExternalAddress::Upnp ).toInt();
1417}
1418
1419
1420void
1421TomahawkSettings::setExternalAddressMode( Tomahawk::Network::ExternalAddress::Mode externalAddressMode )
1422{
1423    setValue( "network/external-address-mode", externalAddressMode );
1424}
1425
1426
1427QString
1428TomahawkSettings::externalHostname() const
1429{
1430    return value( "network/external-hostname" ).toString();
1431}
1432
1433
1434void
1435TomahawkSettings::setExternalHostname(const QString& externalHostname)
1436{
1437    setValue( "network/external-hostname", externalHostname );
1438}
1439
1440
1441int
1442TomahawkSettings::defaultPort() const
1443{
1444    return 50210;
1445}
1446
1447
1448int
1449TomahawkSettings::externalPort() const
1450{
1451    return value( "network/external-port", 50210 ).toInt();
1452}
1453
1454
1455void
1456TomahawkSettings::setExternalPort(int externalPort)
1457{
1458    if ( externalPort == 0 )
1459        setValue( "network/external-port", 50210);
1460    else
1461        setValue( "network/external-port", externalPort);
1462}
1463
1464
1465QString
1466TomahawkSettings::xmppBotServer() const
1467{
1468    return value( "xmppBot/server", QString() ).toString();
1469}
1470
1471
1472void
1473TomahawkSettings::setXmppBotServer( const QString& server )
1474{
1475    setValue( "xmppBot/server", server );
1476}
1477
1478
1479QString
1480TomahawkSettings::xmppBotJid() const
1481{
1482    return value( "xmppBot/jid", QString() ).toString();
1483}
1484
1485
1486void
1487TomahawkSettings::setXmppBotJid( const QString& component )
1488{
1489    setValue( "xmppBot/jid", component );
1490}
1491
1492
1493QString
1494TomahawkSettings::xmppBotPassword() const
1495{
1496    return value( "xmppBot/password", QString() ).toString();
1497}
1498
1499
1500void
1501TomahawkSettings::setXmppBotPassword( const QString& password )
1502{
1503    setValue( "xmppBot/password", password );
1504}
1505
1506
1507int
1508TomahawkSettings::xmppBotPort() const
1509{
1510    return value( "xmppBot/port", -1 ).toInt();
1511}
1512
1513
1514void
1515TomahawkSettings::setXmppBotPort( const int port )
1516{
1517    setValue( "xmppBot/port", port );
1518}
1519
1520
1521QString
1522TomahawkSettings::scriptDefaultPath() const
1523{
1524    return value( "script/defaultpath", QDir::homePath() ).toString();
1525}
1526
1527
1528void
1529TomahawkSettings::setScriptDefaultPath( const QString& path )
1530{
1531    setValue( "script/defaultpath", path );
1532}
1533
1534
1535QString
1536TomahawkSettings::playlistDefaultPath() const
1537{
1538    return value( "playlists/defaultpath", QDir::homePath() ).toString();
1539}
1540
1541
1542void
1543TomahawkSettings::setPlaylistDefaultPath( const QString& path )
1544{
1545    setValue( "playlists/defaultpath", path );
1546}
1547
1548
1549bool
1550TomahawkSettings::nowPlayingEnabled() const
1551{
1552    return value( "adium/enablenowplaying", false ).toBool();
1553}
1554
1555
1556void
1557TomahawkSettings::setNowPlayingEnabled( bool enable )
1558{
1559    setValue( "adium/enablenowplaying", enable );
1560}
1561
1562
1563TomahawkSettings::PrivateListeningMode
1564TomahawkSettings::privateListeningMode() const
1565{
1566    return ( TomahawkSettings::PrivateListeningMode ) value( "privatelisteningmode", TomahawkSettings::PublicListening ).toInt();
1567}
1568
1569
1570void
1571TomahawkSettings::setPrivateListeningMode( TomahawkSettings::PrivateListeningMode mode )
1572{
1573    setValue( "privatelisteningmode", mode );
1574}
1575
1576
1577void
1578TomahawkSettings::updateIndex()
1579{
1580    if ( !Database::instance() || !Database::instance()->isReady() )
1581    {
1582        QTimer::singleShot( 0, this, SLOT( updateIndex() ) );
1583        return;
1584    }
1585
1586    tDebug() << Q_FUNC_INFO << "Updating fuzzy index.";
1587
1588    Tomahawk::DatabaseCommand* cmd = new Tomahawk::DatabaseCommand_UpdateSearchIndex();
1589    Database::instance()->enqueue( QSharedPointer<Tomahawk::DatabaseCommand>( cmd ) );
1590}
1591
1592
1593QString
1594TomahawkSettings::importPlaylistPath() const
1595{
1596    if ( contains( "importPlaylistPath" ) )
1597        return value( "importPlaylistPath" ).toString();
1598    else
1599        return QDir::homePath();
1600}
1601
1602
1603void
1604TomahawkSettings::setImportPlaylistPath( const QString& path )
1605{
1606    setValue( "importPlaylistPath", path );
1607}
1608
1609
1610SerializedUpdaters
1611TomahawkSettings::playlistUpdaters() const
1612{
1613    return value( "playlists/updaters" ).value< SerializedUpdaters >();
1614}
1615
1616
1617void
1618TomahawkSettings::setPlaylistUpdaters( const SerializedUpdaters& updaters )
1619{
1620    setValue( "playlists/updaters", QVariant::fromValue< SerializedUpdaters >( updaters ) );
1621}
1622
1623
1624void
1625TomahawkSettings::setLastChartIds( const QMap<QString, QVariant>& ids ){
1626
1627    setValue( "chartIds", QVariant::fromValue<QMap<QString, QVariant> >( ids ) );
1628}
1629
1630
1631QMap<QString, QVariant> TomahawkSettings::lastChartIds(){
1632
1633    return value( "chartIds" ).value<QMap<QString, QVariant> >();
1634}
1635
1636
1637inline QDataStream&
1638operator<<( QDataStream& out, const AtticaManager::StateHash& states )
1639{
1640    out <<  TOMAHAWK_SETTINGS_VERSION;
1641    out << (quint32)states.count();
1642    foreach( const QString& key, states.keys() )
1643    {
1644        AtticaManager::Resolver resolver = states[ key ];
1645        out << key << resolver.version << resolver.scriptPath << (qint32)resolver.state << resolver.userRating << resolver.binary;
1646    }
1647    return out;
1648}
1649
1650
1651inline QDataStream&
1652operator>>( QDataStream& in, AtticaManager::StateHash& states )
1653{
1654    quint32 count = 0, configVersion = 0;
1655    in >> configVersion;
1656    in >> count;
1657    for ( uint i = 0; i < count; i++ )
1658    {
1659        QString key, version, scriptPath;
1660        qint32 state, userRating;
1661        bool binary = false;
1662        in >> key;
1663        in >> version;
1664        in >> scriptPath;
1665        in >> state;
1666        in >> userRating;
1667        if ( configVersion > 10 )
1668        {
1669            // V11 includes 'bool binary' flag
1670            in >> binary;
1671        }
1672        states[ key ] = AtticaManager::Resolver( version, scriptPath, userRating, (AtticaManager::ResolverState)state, binary );
1673    }
1674    return in;
1675}
1676
1677
1678void
1679TomahawkSettings::registerCustomSettingsHandlers()
1680{
1681    qRegisterMetaType< Tomahawk::SerializedUpdater >( "Tomahawk::SerializedUpdater" );
1682    qRegisterMetaType< Tomahawk::SerializedUpdaters >( "Tomahawk::SerializedUpdaters" );
1683    qRegisterMetaTypeStreamOperators< Tomahawk::SerializedUpdaters >( "Tomahawk::SerializedUpdaters" );
1684
1685    qRegisterMetaType< AtticaManager::StateHash >( "AtticaManager::StateHash" );
1686    qRegisterMetaTypeStreamOperators< AtticaManager::StateHash >( "AtticaManager::StateHash" );
1687}
1688
1689
1690void
1691TomahawkSettings::setAtticaResolverState( const QString& resolver, AtticaManager::ResolverState state )
1692{
1693    AtticaManager::StateHash resolvers = value( "script/atticaresolverstates" ).value< AtticaManager::StateHash >();
1694    AtticaManager::Resolver r = resolvers.value( resolver );
1695    r.state = state;
1696    resolvers.insert( resolver, r );
1697    setValue( "script/atticaresolverstates", QVariant::fromValue< AtticaManager::StateHash >( resolvers ) );
1698
1699    sync();
1700}
1701
1702
1703AtticaManager::StateHash
1704TomahawkSettings::atticaResolverStates() const
1705{
1706    return value( "script/atticaresolverstates" ).value< AtticaManager::StateHash >();
1707}
1708
1709
1710void
1711TomahawkSettings::setAtticaResolverStates( const AtticaManager::StateHash states )
1712{
1713    setValue( "script/atticaresolverstates", QVariant::fromValue< AtticaManager::StateHash >( states ) );
1714}
1715
1716
1717void
1718TomahawkSettings::removeAtticaResolverState ( const QString& resolver )
1719{
1720    AtticaManager::StateHash resolvers = value( "script/atticaresolverstates" ).value< AtticaManager::StateHash >();
1721    resolvers.remove( resolver );
1722    setValue( "script/atticaresolverstates", QVariant::fromValue< AtticaManager::StateHash >( resolvers ) );
1723}
1724
1725
1726QByteArray
1727TomahawkSettings::playdarCertificate() const
1728{
1729    return value( "playdar/certificate").value< QByteArray >();
1730}
1731
1732
1733void
1734TomahawkSettings::setPlaydarCertificate( const QByteArray& cert )
1735{
1736    setValue( "playdar/certificate", cert );
1737}
1738
1739
1740QByteArray
1741TomahawkSettings::playdarKey() const
1742{
1743    return value( "playdar/key" ).value< QByteArray >();
1744}
1745
1746
1747void
1748TomahawkSettings::setPlaydarKey( const QByteArray& key )
1749{
1750    setValue( "playdar/key", key );
1751}
1752
1753QString
1754TomahawkSettings::vlcArguments() const
1755{
1756    return value( "vlc/cmdline_args" ).value< QString >();
1757}
1758
1759void
1760TomahawkSettings::setVlcArguments( const QString& args )
1761{
1762    setValue( "vlc/cmdline_args", args);
1763}
1764