radioapp/radiouiengine/src/radiostationmodel.cpp
branchRCL_3
changeset 45 cce62ebc198e
equal deleted inserted replaced
43:1a6714c53019 45:cce62ebc198e
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 
       
    18 // System includes
       
    19 #include <QStringList>
       
    20 
       
    21 // User includes
       
    22 #include "radiostationmodel.h"
       
    23 #include "radiostationmodel_p.h"
       
    24 #include "radiopresetstorage.h"
       
    25 #include "radioenginewrapper.h"
       
    26 #include "radiouiengine.h"
       
    27 #include "radiouiengine_p.h"
       
    28 #include "radiostation.h"
       
    29 #include "radiostation_p.h"
       
    30 #include "radiologger.h"
       
    31 
       
    32 /*!
       
    33  *
       
    34  */
       
    35 static QString parseLine( const RadioStation& station )
       
    36 {
       
    37     QString line = "";
       
    38     const QString parsedFrequency = qtTrId( "txt_rad_dblist_l1_mhz" ).arg( RadioStation::parseFrequency( station.frequency() ) );
       
    39     line.append( parsedFrequency );
       
    40 
       
    41     QString name = station.name();
       
    42     if ( !name.isEmpty() )
       
    43     {
       
    44         line.append( " - " );
       
    45         line.append( name.trimmed() );
       
    46     }
       
    47 
       
    48     LOG_FORMAT( "RadioStationModel: Returning line %s", GETSTRING(line) );
       
    49     return line;
       
    50 }
       
    51 
       
    52 /*!
       
    53  *
       
    54  */
       
    55 RadioStationModel::RadioStationModel( RadioUiEnginePrivate& uiEngine ) :
       
    56     QAbstractListModel( &uiEngine.api() ),
       
    57     d_ptr( new RadioStationModelPrivate( this, uiEngine ) )
       
    58 {
       
    59 }
       
    60 
       
    61 /*!
       
    62  *
       
    63  */
       
    64 RadioStationModel::~RadioStationModel()
       
    65 {
       
    66 }
       
    67 
       
    68 /*!
       
    69  *
       
    70  */
       
    71 Qt::ItemFlags RadioStationModel::flags ( const QModelIndex& index ) const
       
    72 {
       
    73     Qt::ItemFlags flags = QAbstractListModel::flags( index );
       
    74     flags |= Qt::ItemIsEditable;
       
    75     return flags;
       
    76 }
       
    77 
       
    78 /*!
       
    79  *
       
    80  */
       
    81 int RadioStationModel::rowCount( const QModelIndex& parent ) const
       
    82 {
       
    83     Q_UNUSED( parent );
       
    84     Q_D( const RadioStationModel );
       
    85     const int count = d->mStations.keys().count();
       
    86     return count;
       
    87 }
       
    88 
       
    89 /*!
       
    90  * Checks the given station and emits signals based on what member variables had been changed
       
    91  */
       
    92 QVariant RadioStationModel::data( const QModelIndex& index, int role ) const
       
    93 {
       
    94     if ( !index.isValid() ) {
       
    95         return QVariant();
       
    96     }
       
    97 
       
    98     Q_D( const RadioStationModel );
       
    99     if ( role == Qt::DisplayRole ) {
       
   100         RadioStation station = stationAt( index.row() );
       
   101         QString firstLine = parseLine( station );
       
   102         if ( d->mDetailLevel.testFlag( RadioStationModel::ShowGenre ) ) {
       
   103             QStringList list;
       
   104             list.append( firstLine );
       
   105             QString genre = " "; // Empty space so that the listbox generates the second row
       
   106             if ( station.genre() != -1 ) {
       
   107                 genre = d->mUiEngine.api().genreToString( station.genre(), GenreTarget::StationsList );
       
   108             }
       
   109             list.append( genre );
       
   110 
       
   111             return list;
       
   112         }
       
   113 
       
   114         return firstLine;
       
   115     } else if ( role == RadioRole::RadioStationRole ) {
       
   116         QVariant variant;
       
   117         variant.setValue( stationAt( index.row() ) );
       
   118         return variant;
       
   119     } else if ( role == Qt::DecorationRole &&
       
   120                 d->mDetailLevel.testFlag( RadioStationModel::ShowIcons ) ) {
       
   121         RadioStation station = stationAt( index.row() );
       
   122         QVariantList list;
       
   123         if ( station.isFavorite() && !d->mFavoriteIcon.isNull() ) {
       
   124             list.append( d->mFavoriteIcon );
       
   125         } else {
       
   126             list.append( QIcon() );
       
   127         }
       
   128         if ( currentStation().frequency() == station.frequency() && !d->mNowPlayingIcon.isNull() ) {
       
   129             list.append( d->mNowPlayingIcon );
       
   130         }
       
   131         return list;
       
   132     } else if ( role == RadioRole::IsFavoriteRole ) {
       
   133         QVariant variant;
       
   134         variant.setValue( stationAt( index.row() ).isFavorite() );
       
   135         return variant;
       
   136     }
       
   137 
       
   138     return QVariant();
       
   139 }
       
   140 
       
   141 /*!
       
   142  * Checks the given station and emits signals based on what member variables had been changed
       
   143  */
       
   144 bool RadioStationModel::setData( const QModelIndex& index, const QVariant& value, int role )
       
   145 {
       
   146     Q_UNUSED( index );
       
   147 
       
   148     if ( role == RadioRole::ToggleFavoriteRole ) {
       
   149         const uint frequency = value.toUInt();
       
   150         RadioStation station;
       
   151         if ( findFrequency( frequency, station ) ) {
       
   152             setFavoriteByPreset( station.presetIndex(), !station.isFavorite() );
       
   153         } else {
       
   154             setFavoriteByFrequency( frequency, true );
       
   155         }
       
   156 
       
   157         return true;
       
   158     }
       
   159 
       
   160     return false;
       
   161 }
       
   162 
       
   163 /*!
       
   164  * Called by the engine to initialize the list with given amount of presets
       
   165  */
       
   166 void RadioStationModel::initialize( RadioPresetStorage* storage, RadioEngineWrapper* wrapper )
       
   167 {
       
   168     Q_D( RadioStationModel );
       
   169     d->mPresetStorage = storage;
       
   170     d->mWrapper = wrapper;
       
   171 
       
   172     int index = d->mPresetStorage->firstPreset();
       
   173     LOG_FORMAT( "RadioStationModel::initialize: presetCount: %d, firstIndex: %d",
       
   174                                             d->mPresetStorage->presetCount(), index );
       
   175 
       
   176     while ( index >= 0 ) {
       
   177         RadioStation station;
       
   178 
       
   179         RadioStationIf* stationInterface = static_cast<RadioStationIf*>( station.data_ptr() );
       
   180         if ( d->mPresetStorage->readPreset( index, *stationInterface ) ) {
       
   181             if ( station.isValid() && d->mWrapper->isFrequencyValid( station.frequency() ) ) {
       
   182 
       
   183 #ifdef INIT_STATIONS_WITH_DUMMY_RT
       
   184                 station.setGenre( GenreEurope::RdsChildrensProgrammes );
       
   185                 if ( index % 3 == 0 ) {
       
   186                     station.setName( "Radio Rock" );
       
   187                     station.setRadioText( "Now playing: <font color='cyan'>The Presidents of the United States of America</font> - <font color='cyan'>Dune Buggy and diipa daapa jhkjhui erjlkej rewjtl</font>" );
       
   188                 } else if ( index % 2 == 0 ) {
       
   189                     station.setName( "Radio Rock" );
       
   190                 } else {
       
   191                     station.setDynamicPsText( "DYN PS" );
       
   192                 }
       
   193 #endif // INIT_STATIONS_WITH_DUMMY_RT
       
   194 
       
   195                 // Check if the station seems to send RDS or not.
       
   196                 // Note that radiotext is not checked because it is not saved to cenrep
       
   197                 // TODO: Consider saving this state flag to cenrep
       
   198                 if ( ( station.hasName() && !station.isRenamed() ) || station.hasUrl() ) {
       
   199                     static_cast<RadioStationIf*>( station.data_ptr() )->setStationHasSentRds( true );
       
   200                 }
       
   201 
       
   202                 d->mStations.insert( station.frequency(), station );
       
   203             } else {
       
   204                 LOG( "RadioStationModel::initialize: Invalid station!" );
       
   205                 LOG_FORMAT( "Invalid station freq: %d", station.frequency() );
       
   206             }
       
   207         }
       
   208 
       
   209         index = d->mPresetStorage->nextPreset( index );
       
   210     }
       
   211 
       
   212     d->setCurrentStation( d->mWrapper->currentFrequency() );
       
   213 
       
   214     wrapper->addObserver( d );
       
   215 }
       
   216 
       
   217 /*!
       
   218  * Sets the icons to be used in the lists
       
   219  */
       
   220 void RadioStationModel::setIcons( const QIcon& favoriteIcon, const QIcon& nowPlayingIcon )
       
   221 {
       
   222     Q_D( RadioStationModel );
       
   223     d->mFavoriteIcon = favoriteIcon;
       
   224     d->mNowPlayingIcon = nowPlayingIcon;
       
   225 }
       
   226 
       
   227 /*!
       
   228  * Returns a reference to the station handler interface
       
   229  */
       
   230 RadioStationHandlerIf& RadioStationModel::stationHandlerIf()
       
   231 {
       
   232     Q_D( RadioStationModel );
       
   233     return *d;
       
   234 }
       
   235 
       
   236 /*!
       
   237  * Returns a reference to the underlying QList so that it can be easily looped
       
   238  */
       
   239 const Stations& RadioStationModel::list() const
       
   240 {
       
   241     Q_D( const RadioStationModel );
       
   242     return d->mStations;
       
   243 }
       
   244 
       
   245 /*!
       
   246  * Returns the station at the given index.
       
   247  */
       
   248 RadioStation RadioStationModel::stationAt( int index ) const
       
   249 {
       
   250     // Get the value from the keys list instead of directly accessing the values list
       
   251     // because QMap may have added a default-constructed value to the values list
       
   252     Q_D( const RadioStationModel );
       
   253     if ( index >= 0 && index < d->mStations.keys().count() ) {
       
   254         uint frequency = d->mStations.keys().at( index );
       
   255         return d->mStations.value( frequency );
       
   256     }
       
   257     return RadioStation();
       
   258 }
       
   259 
       
   260 /*!
       
   261  * Finds a station by frequency
       
   262  */
       
   263 bool RadioStationModel::findFrequency( uint frequency, RadioStation& station, FindCriteria::Criteria criteria ) const
       
   264 {
       
   265     Q_D( const RadioStationModel );
       
   266 
       
   267     if ( criteria == FindCriteria::IncludeManualStation && d->mCurrentStation->frequency() == frequency ) {
       
   268         station = *d->mCurrentStation;
       
   269         return true;
       
   270     }
       
   271 
       
   272     if ( d->mStations.contains( frequency ) ) {
       
   273         station = d->mStations.value( frequency );
       
   274         return true;
       
   275     }
       
   276     return false;
       
   277 }
       
   278 
       
   279 /*!
       
   280  * Convenience function to find a radio station.
       
   281  */
       
   282 RadioStation RadioStationModel::findStation( uint frequency, FindCriteria::Criteria criteria ) const
       
   283 {
       
   284     RadioStation station;
       
   285     findFrequency( frequency, station, criteria ); // Return value ignored
       
   286     return station;
       
   287 }
       
   288 
       
   289 /*!
       
   290  * Finds a station by preset index
       
   291  */
       
   292 int RadioStationModel::findPresetIndex( int presetIndex )
       
   293 {
       
   294     Q_D( RadioStationModel );
       
   295     int index = 0;
       
   296     foreach( const RadioStation& tempStation, d->mStations ) {
       
   297         if ( tempStation.presetIndex() == presetIndex ) {
       
   298             return index;
       
   299         }
       
   300         ++index;
       
   301     }
       
   302 
       
   303     return RadioStation::NotFound;
       
   304 }
       
   305 
       
   306 /*!
       
   307  * Finds a station by preset index
       
   308  */
       
   309 int RadioStationModel::findPresetIndex( int presetIndex, RadioStation& station )
       
   310 {
       
   311     Q_D( RadioStationModel );
       
   312     const int index = findPresetIndex( presetIndex );
       
   313     if ( index != RadioStation::NotFound ) {
       
   314         station = d->mStations.values().at( index );
       
   315     }
       
   316     return index;
       
   317 }
       
   318 
       
   319 /*!
       
   320  * Finds the closest station from the given frequency
       
   321  */
       
   322 RadioStation RadioStationModel::findClosest( const uint frequency, StationSkip::Mode mode )
       
   323 {
       
   324     Q_D( RadioStationModel );
       
   325     const bool findFavorite = mode == StationSkip::PreviousFavorite || mode == StationSkip::NextFavorite;
       
   326     const bool findNext = mode == StationSkip::Next || mode == StationSkip::NextFavorite;
       
   327     QList<RadioStation> list = findFavorite ? d->favorites() : d->mStations.values();
       
   328 
       
   329     if ( list.isEmpty() ) {
       
   330         return RadioStation();
       
   331     }
       
   332 
       
   333     // Find the previous and next station from current frequency
       
   334     RadioStation previous;
       
   335     RadioStation next;
       
   336     foreach( const RadioStation& station, list ) {
       
   337         const uint testFreq = station.frequency();
       
   338         if ( testFreq == frequency ) {
       
   339             continue;
       
   340         }
       
   341 
       
   342         if ( testFreq > frequency ) {
       
   343             next = station;
       
   344             break;
       
   345         }
       
   346         previous = station;
       
   347     }
       
   348 
       
   349     // Check if we need to loop around
       
   350     if ( findNext && !next.isValid() ) {
       
   351         next = list.first();
       
   352     } else if ( !findNext && !previous.isValid() ) {
       
   353         previous = list.last();
       
   354     }
       
   355 
       
   356     return findNext ? next : previous;
       
   357 }
       
   358 
       
   359 /*!
       
   360  * Checks if the model contains the given frequency
       
   361  */
       
   362 bool RadioStationModel::contains( const uint frequency ) const
       
   363 {
       
   364     RadioStation unused;
       
   365     return findFrequency( frequency, unused );
       
   366 }
       
   367 
       
   368 /*!
       
   369  * Removes a station by frequency
       
   370  */
       
   371 void RadioStationModel::removeByFrequency( uint frequency )
       
   372 {
       
   373     RadioStation station;
       
   374     if ( findFrequency( frequency, station ) ) {
       
   375         removeStation( station );
       
   376     }
       
   377 }
       
   378 
       
   379 /*!
       
   380  * Removes a station by preset index
       
   381  */
       
   382 void RadioStationModel::removeByPresetIndex( int presetIndex )
       
   383 {
       
   384     RadioStation station;
       
   385     const int index = findPresetIndex( presetIndex, station );
       
   386     if ( index >= 0 ) {
       
   387         removeStation( station );
       
   388     }
       
   389 }
       
   390 
       
   391 /*!
       
   392  * Removes the given station
       
   393  */
       
   394 void RadioStationModel::removeStation( const RadioStation& station )
       
   395 {
       
   396     Q_D( RadioStationModel );
       
   397     const uint frequency = station.frequency();
       
   398     if ( d->mStations.contains( frequency ) ) {
       
   399 
       
   400         // If we are removing the current station, copy its data to the current station pointer
       
   401         // to keep all of the received RDS data still available. They will be discarded when
       
   402         // the user tunes to another frequency, but they are available if the user decides to add it back.
       
   403         if ( d->mCurrentStation->frequency() == frequency ) {
       
   404             *d->mCurrentStation = station;
       
   405         }
       
   406 
       
   407         // Copy the station to a temporary variable that can be used as signal parameter
       
   408         RadioStation tempStation = station;
       
   409 
       
   410         const int row = indexFromFrequency( tempStation.frequency() );
       
   411         beginRemoveRows( QModelIndex(), row, row );
       
   412 
       
   413         d->mPresetStorage->deletePreset( tempStation.presetIndex() );
       
   414         d->mStations.remove( frequency );
       
   415 
       
   416         d->mCurrentStation = NULL;
       
   417         d->setCurrentStation( d->mWrapper->currentFrequency() );
       
   418 
       
   419         endRemoveRows();
       
   420     }
       
   421 }
       
   422 
       
   423 /*!
       
   424  * Public slot
       
   425  * Removes all stations
       
   426  */
       
   427 void RadioStationModel::removeAll( RemoveMode mode )
       
   428 {
       
   429     Q_D( RadioStationModel );
       
   430     if ( d->mStations.count() == 0 ) {
       
   431         return;
       
   432     }
       
   433 
       
   434     if ( mode == RemoveAll ) {
       
   435         beginRemoveRows( QModelIndex(), 0, rowCount() - 1 );
       
   436 
       
   437         // Preset utility deletes all presets with index -1
       
   438         bool success = d->mPresetStorage->deletePreset( -1 );
       
   439         Q_UNUSED( success );
       
   440         RADIO_ASSERT( success, "FMRadio", "Failed to remove station" );
       
   441 
       
   442         d->mStations.clear();
       
   443         d->mCurrentStation = NULL;
       
   444         d->setCurrentStation( d->mWrapper->currentFrequency() );
       
   445 
       
   446         endRemoveRows();
       
   447     } else {
       
   448         foreach( const RadioStation& station, d->mStations ) {
       
   449 
       
   450             if ( mode == RemoveLocalStations ) {
       
   451                 if ( station.isType( RadioStation::LocalStation ) && !station.isFavorite() ) {
       
   452                     removeStation( station );
       
   453                 }
       
   454             } else {
       
   455                 if ( station.isFavorite() ) {
       
   456                     RadioStation newStation( station );
       
   457                     newStation.setFavorite( false );
       
   458                     saveStation( newStation );
       
   459                 }
       
   460             }
       
   461         }
       
   462     }
       
   463 }
       
   464 
       
   465 /*!
       
   466  * Adds a new station to the list
       
   467  */
       
   468 void RadioStationModel::addStation( const RadioStation& station )
       
   469 {
       
   470     Q_D( RadioStationModel );
       
   471     const int newIndex = findUnusedPresetIndex();
       
   472     LOG_FORMAT( "RadioStationModel::addStation: Adding station to index %d", newIndex );
       
   473 
       
   474     RadioStation newStation = station;
       
   475     newStation.setPresetIndex( newIndex );
       
   476     newStation.unsetType( RadioStation::ManualStation );
       
   477 
       
   478     // We have to call beginInsertRows() BEFORE the addition is actually done so we must figure out where
       
   479     // the new station will go in the sorted frequency order
       
   480     int row = 0;
       
   481     const int count = rowCount();
       
   482     if ( count > 1 ) {
       
   483         Stations::const_iterator iter = d->mStations.upperBound( newStation.frequency() );
       
   484         if ( d->mStations.contains( iter.key() ) ) {
       
   485             row = d->mStations.keys().indexOf( iter.key() );
       
   486         } else {
       
   487             row = count;
       
   488         }
       
   489     } else if ( count == 1 ) {
       
   490         uint existingFreq = d->mStations.keys().first();
       
   491         if ( station.frequency() > existingFreq ) {
       
   492             row = 1;
       
   493         }
       
   494     }
       
   495 
       
   496     beginInsertRows( QModelIndex(), row, row );
       
   497 
       
   498     d->doSaveStation( newStation );
       
   499 
       
   500     d->setCurrentStation( d->mWrapper->currentFrequency() );
       
   501 
       
   502     endInsertRows();
       
   503 
       
   504     // Not all UI components listen to rowsInserted() signal so emit the favorite signal
       
   505     if ( newStation.isFavorite() ) {
       
   506         emit favoriteChanged( *d->mCurrentStation );
       
   507     }
       
   508 }
       
   509 
       
   510 /*!
       
   511  * Saves the given station. It is expected to already exist in the list
       
   512  */
       
   513 void RadioStationModel::saveStation( RadioStation& station )
       
   514 {
       
   515     Q_D( RadioStationModel );
       
   516     const bool stationHasChanged = station.hasChanged();
       
   517     RadioStation::Change changeFlags = station.changeFlags();
       
   518     station.resetChangeFlags();
       
   519 
       
   520     if ( station.isType( RadioStation::ManualStation ) ) {
       
   521 
       
   522         d->mManualStation = station;
       
   523         emitChangeSignals( station, changeFlags );
       
   524 
       
   525     } else if ( station.isValid() && stationHasChanged && d->mStations.contains( station.frequency() )) {
       
   526 
       
   527         d->doSaveStation( station, changeFlags.testFlag( RadioStation::PersistentDataChanged ) );
       
   528         d->setCurrentStation( d->mWrapper->currentFrequency() );
       
   529 
       
   530         emitChangeSignals( station, changeFlags );
       
   531     }
       
   532 }
       
   533 
       
   534 /*!
       
   535  * Finds number of favorite stations
       
   536  */
       
   537 int RadioStationModel::favoriteCount()
       
   538 {
       
   539     Q_D( const RadioStationModel );
       
   540     return d->favorites().count();
       
   541 }
       
   542 
       
   543 /*!
       
   544  * Changes the favorite status of a station by its frequency. If the station does
       
   545  * not yet exist, it is added.
       
   546  */
       
   547 void RadioStationModel::setFavoriteByFrequency( uint frequency, bool favorite )
       
   548 {
       
   549     Q_D( RadioStationModel );
       
   550     if ( d->mWrapper->isFrequencyValid( frequency ) ) {
       
   551         LOG_FORMAT( "RadioStationModel::setFavoriteByFrequency, frequency: %d", frequency );
       
   552         RadioStation station;
       
   553         if ( findFrequency( frequency, station ) ) { // Update existing preset
       
   554             if ( station.isFavorite() != favorite ) {
       
   555                 station.setFavorite( favorite );
       
   556                 saveStation( station );
       
   557             }
       
   558         } else if ( favorite ) {                    // Add new preset if setting as favorite
       
   559             RadioStation newStation;
       
   560             if ( d->mCurrentStation->frequency() == frequency ) {
       
   561                 newStation = *d->mCurrentStation;
       
   562             } else {
       
   563                 LOG( "CurrentStation frequency mismatch!" );
       
   564                 newStation.setFrequency( frequency );
       
   565             }
       
   566 
       
   567             newStation.setType( RadioStation::LocalStation | RadioStation::Favorite );
       
   568 
       
   569             // Emit the signals only after adding the preset and reinitializing the current station
       
   570             // because the UI will probably query the current station in its slots that get called.
       
   571             addStation( newStation );
       
   572         }
       
   573     }
       
   574 }
       
   575 
       
   576 /*!
       
   577  * Changes the favorite status of a station by its preset index
       
   578  */
       
   579 void RadioStationModel::setFavoriteByPreset( int presetIndex, bool favorite )
       
   580 {
       
   581     LOG_FORMAT( "RadioStationModel::setFavoriteByPreset, presetIndex: %d", presetIndex );
       
   582     RadioStation station;
       
   583     if ( findPresetIndex( presetIndex, station ) != RadioStation::NotFound ) {
       
   584         station.setFavorite( favorite );
       
   585         saveStation( station );
       
   586     }
       
   587 }
       
   588 
       
   589 /*!
       
   590  * Renames a station by its preset index
       
   591  */
       
   592 void RadioStationModel::renameStation( int presetIndex, const QString& name )
       
   593 {
       
   594     LOG_FORMAT( "RadioStationModel::renameStation, presetIndex: %d, name: %s", presetIndex, GETSTRING(name) );
       
   595     RadioStation station;
       
   596     if ( findPresetIndex( presetIndex, station ) != RadioStation::NotFound ) {
       
   597         station.setUserDefinedName( name );
       
   598         saveStation( station );
       
   599     }
       
   600 }
       
   601 
       
   602 /*!
       
   603  *
       
   604  */
       
   605 void RadioStationModel::setFavorites( const QModelIndexList& favorites )
       
   606 {
       
   607     foreach ( const QModelIndex& index, favorites ) {
       
   608         RadioStation station = stationAt( index.row() );
       
   609         RADIO_ASSERT( station.isValid() , "RadioStationModel::setFavorites", "invalid RadioStation");
       
   610         setFavoriteByPreset( station.presetIndex(), true );
       
   611     }
       
   612 }
       
   613 
       
   614 /*!
       
   615  * Returns the currently tuned station
       
   616  */
       
   617 RadioStation& RadioStationModel::currentStation()
       
   618 {
       
   619     Q_D( RadioStationModel );
       
   620     return *d->mCurrentStation;
       
   621 }
       
   622 
       
   623 /*!
       
   624  * Returns the currently tuned station
       
   625  */
       
   626 const RadioStation& RadioStationModel::currentStation() const
       
   627 {
       
   628     Q_D( const RadioStationModel );
       
   629     return *d->mCurrentStation;
       
   630 }
       
   631 
       
   632 /*!
       
   633  * Sets the model detail level
       
   634  */
       
   635 void RadioStationModel::setDetail( Detail level )
       
   636 {
       
   637     Q_D( RadioStationModel );
       
   638     d->mDetailLevel = level;
       
   639 }
       
   640 
       
   641 /*!
       
   642  * Returns a list of radio stations in the given frequency range
       
   643  */
       
   644 QList<RadioStation> RadioStationModel::stationsInRange( uint minFrequency, uint maxFrequency )
       
   645 {
       
   646     Q_D( RadioStationModel );
       
   647     QList<RadioStation> stations;
       
   648     foreach( const RadioStation& station, d->mStations ) {
       
   649         if ( station.frequency() >= minFrequency && station.frequency() <= maxFrequency ) {
       
   650             stations.append( station );
       
   651         }
       
   652     }
       
   653 
       
   654     return stations;
       
   655 }
       
   656 
       
   657 /*!
       
   658  * Returns the model index corresponding to the given frequency
       
   659  */
       
   660 int RadioStationModel::indexFromFrequency( uint frequency )
       
   661 {
       
   662     RadioStation station;
       
   663     if ( findFrequency( frequency, station ) ) {
       
   664         return findPresetIndex( station.presetIndex() );
       
   665     }
       
   666     return -1;
       
   667 }
       
   668 
       
   669 /*!
       
   670  * Private slot
       
   671  * Timer timeout slot to indicate that the dynamic PS check has ended
       
   672  */
       
   673 void RadioStationModel::dynamicPsCheckEnded()
       
   674 {
       
   675     Q_D( RadioStationModel );
       
   676     LOG_TIMESTAMP( "Finished dynamic PS check." );
       
   677     if ( d->mCurrentStation->psType() != RadioStation::Dynamic && !d->mCurrentStation->dynamicPsText().isEmpty() )
       
   678     {
       
   679         d->mCurrentStation->setPsType( RadioStation::Static );
       
   680         d->mCurrentStation->setName( d->mCurrentStation->dynamicPsText() );
       
   681         d->mCurrentStation->setDynamicPsText( "" );
       
   682         saveStation( *d->mCurrentStation );
       
   683     }
       
   684 }
       
   685 
       
   686 /*!
       
   687  * Checks the given station and emits signals based on what member variables had been changed
       
   688  */
       
   689 void RadioStationModel::emitChangeSignals( const RadioStation& station, RadioStation::Change flags )
       
   690 {
       
   691     if ( flags.testFlag( RadioStation::NameChanged ) ||
       
   692          flags.testFlag( RadioStation::GenreChanged ) ||
       
   693          flags.testFlag( RadioStation::UrlChanged ) ||
       
   694          flags.testFlag( RadioStation::TypeChanged ) ||
       
   695          flags.testFlag( RadioStation::PiCodeChanged ) ) {
       
   696 
       
   697         // Create a temporary RadioStation for the duration of the signal-slot processing
       
   698         // The receivers can ask the station what data has changed and update accordingly
       
   699         RadioStation tempStation( station );
       
   700         tempStation.setChangeFlags( flags );
       
   701         emit stationDataChanged( tempStation );
       
   702 
       
   703         emitDataChanged( tempStation );
       
   704     }
       
   705 
       
   706     if ( flags.testFlag( RadioStation::RadioTextChanged ) ) {
       
   707         emit radioTextReceived( station );
       
   708         emitDataChanged( station );
       
   709     }
       
   710 
       
   711     if ( flags.testFlag( RadioStation::DynamicPsChanged ) ) {
       
   712         emit dynamicPsChanged( station );
       
   713         emitDataChanged( station );
       
   714     }
       
   715 
       
   716     if ( flags.testFlag( RadioStation::FavoriteChanged ) && station.isValid() ) {
       
   717         emit favoriteChanged( station );
       
   718         emitDataChanged( station );
       
   719     }
       
   720 }
       
   721 
       
   722 /*!
       
   723  *
       
   724  */
       
   725 void RadioStationModel::emitDataChanged( const RadioStation& station )
       
   726 {
       
   727     const int row = findPresetIndex( station.presetIndex() );
       
   728     QModelIndex top = index( row, 0, QModelIndex() );
       
   729     QModelIndex bottom = index( row, 0, QModelIndex() );
       
   730     emit dataChanged( top, bottom );
       
   731 }
       
   732 
       
   733 /*!
       
   734  * Finds an unused preset index
       
   735  */
       
   736 int RadioStationModel::findUnusedPresetIndex()
       
   737 {
       
   738     Q_D( RadioStationModel );
       
   739     QList<int> indexes;
       
   740     foreach( const RadioStation& station, d->mStations ) {
       
   741         if ( station.isValid() ) {
       
   742             indexes.append( station.presetIndex() );
       
   743         }
       
   744     }
       
   745 
       
   746     int index = 0;
       
   747     for ( ; indexes.contains( index ); ++index ) {
       
   748         // Nothing to do here
       
   749     }
       
   750 
       
   751     LOG_FORMAT( "RadioStationModel::findUnusedPresetIndex, index: %d", index );
       
   752     return index;
       
   753 }