radioapp/radiowidgets/src/radiostationcarousel.cpp
changeset 28 075425b8d9a4
parent 24 6df133bd92e1
child 32 189d20c34778
child 34 bc10a61bd7d3
equal deleted inserted replaced
24:6df133bd92e1 28:075425b8d9a4
    15 *
    15 *
    16 */
    16 */
    17 
    17 
    18 // System includes
    18 // System includes
    19 #include <QGraphicsLinearLayout>
    19 #include <QGraphicsLinearLayout>
    20 #include <HbAnchorLayout>
    20 #include <QGraphicsSceneResizeEvent>
    21 #include <QPixmap>
       
    22 #include <QGraphicsSceneMouseEvent>
       
    23 #include <HbEffect>
       
    24 #include <QTimer>
    21 #include <QTimer>
    25 #include <QTimeLine>
       
    26 #include <HbPanGesture>
    22 #include <HbPanGesture>
       
    23 #include <HbSwipeGesture>
       
    24 #include <HbFontSpec>
    27 
    25 
    28 // User includes
    26 // User includes
    29 #include "radiostationcarousel.h"
    27 #include "radiostationcarousel.h"
       
    28 #include "radiocarouselanimator.h"
    30 #include "radiouiloader.h"
    29 #include "radiouiloader.h"
    31 #include "radiostationitem.h"
    30 #include "radiocarouselitem.h"
    32 #include "radiostation.h"
    31 #include "radiostation.h"
    33 #include "radiouiengine.h"
    32 #include "radiouiengine.h"
    34 #include "radiostationmodel.h"
    33 #include "radiostationmodel.h"
    35 #include "radiofadinglabel.h"
    34 #include "radiofadinglabel.h"
    36 #include "radiologger.h"
    35 #include "radiologger.h"
    37 #include "radiocarouselmodel.h"
    36 #include "radioutil.h"
    38 #include "radiouiutilities.h"
       
    39 #include "radio_global.h"
    37 #include "radio_global.h"
    40 
    38 
    41 #ifdef USE_LAYOUT_FROM_E_DRIVE
    39 // Constants
    42     const QString KFavoriteIconPath = "e:/radiotest/images/favoriteiconactive.png";
    40 const int RTPLUS_CHECK_TIMEOUT = 700;
    43     const QString KNonFavoriteIconPath = "e:/radiotest/images/favoriteiconinactive.png";
    41 const int INFOTEXT_NOFAVORITES_TIMEOUT = 5000;
       
    42 const int SET_FREQUENCY_TIMEOUT = 500;
       
    43 const int FAVORITE_HINT_SHOW_DELAY = 1000;
       
    44 const int FAVORITE_HINT_HIDE_DELAY = 2000;
       
    45 
       
    46 #ifdef BUILD_WIN32
       
    47 #   define SCROLLBAR_POLICY ScrollBarAlwaysOn
    44 #else
    48 #else
    45     const QString KFavoriteIconPath = ":/images/favoriteiconactive.png";
    49 #   define SCROLLBAR_POLICY ScrollBarAlwaysOff
    46     const QString KNonFavoriteIconPath = ":/images/favoriteiconinactive.png";
    50 #endif // BUILD_WIN32
    47 #endif
    51 
    48 
    52 #define CALL_TO_ALL_ITEMS( expr ) \
    49 const int KRadioTextPlusCheckTimeout = 700; // 700 ms
    53     mItems[LeftItem]->expr; \
    50 const int KFreqScrollDivider = 100000;
    54     mItems[CenterItem]->expr; \
    51 const int INFOTEXT_NOFAVORITES_TIMEOUT = 15000;
    55     mItems[RightItem]->expr;
    52 
    56 
    53 // ===============================================================
    57 /*!
    54 //  Scanning helper
    58  *
    55 // ===============================================================
    59  */
    56 
    60 RadioStationCarousel::RadioStationCarousel( QGraphicsItem* parent ) :
    57 /*!
    61     HbScrollArea( parent ),
    58  *
    62     mUiEngine( NULL ),
    59  */
       
    60 ScanningHelper::ScanningHelper( RadioStationCarousel& carousel ) :
       
    61     mCarousel( carousel ),
       
    62     mCurrentFrequency( 0 ),
       
    63     mPreviousFrequency( 0 ),
       
    64     mStationItem( 0 ),
       
    65     mNumberScrollingTimeLine( new QTimeLine( 1000, this ) )
       
    66 {
       
    67     mNumberScrollingTimeLine->setCurveShape( QTimeLine::EaseInCurve );
       
    68     connectAndTest( mNumberScrollingTimeLine,  SIGNAL(finished()),
       
    69                     &mCarousel,                SIGNAL(scanAnimationFinished()) );
       
    70     connectAndTest( mNumberScrollingTimeLine,  SIGNAL(frameChanged(int)),
       
    71                     this,                      SLOT(numberScrollUpdate(int)) );
       
    72 }
       
    73 
       
    74 /*!
       
    75  *
       
    76  */
       
    77 void ScanningHelper::start()
       
    78 {
       
    79     QTimer::singleShot( 0, this, SLOT(startSlide()) );
       
    80 }
       
    81 
       
    82 /*!
       
    83  * Private slot
       
    84  */
       
    85 void ScanningHelper::startSlide()
       
    86 {
       
    87     mCarousel.scrollToIndex( mModelIndex, RadioStationCarousel::NoSignal );
       
    88     startNumberScroll();
       
    89 }
       
    90 
       
    91 /*!
       
    92  * Private slot
       
    93  */
       
    94 void ScanningHelper::startNumberScroll()
       
    95 {
       
    96     //TODO: Take italy case into account
       
    97     if ( mPreviousFrequency ) {
       
    98         mNumberScrollingTimeLine->setFrameRange( mPreviousFrequency / KFreqScrollDivider, mCurrentFrequency / KFreqScrollDivider );
       
    99         mNumberScrollingTimeLine->start();
       
   100     } else {
       
   101         emit mCarousel.scanAnimationFinished();
       
   102     }
       
   103 }
       
   104 
       
   105 /*!
       
   106  * Private slot
       
   107  */
       
   108 void ScanningHelper::numberScrollUpdate( int value )
       
   109 {
       
   110     if ( mStationItem ) {
       
   111         mStationItem->setFrequency( value * KFreqScrollDivider );
       
   112     }
       
   113 }
       
   114 
       
   115 // ===============================================================
       
   116 //  Carousel
       
   117 // ===============================================================
       
   118 
       
   119 /*!
       
   120  *
       
   121  */
       
   122 RadioStationCarousel::RadioStationCarousel( RadioUiEngine* uiEngine ) :
       
   123     HbGridView( 0 ),
       
   124     mUiEngine( uiEngine ),
       
   125     mAntennaAttached( false ),
       
   126     mAutoScrollTime( 300 ),
    63     mAutoScrollTime( 300 ),
   127     mGenericTimer( new QTimer( this ) ),
    64     mGenericTimer( new QTimer( this ) ),
   128     mTimerMode( NoTimer ),
    65     mTimerMode( NoTimer ),
   129     mScanningHelper( 0 ),
    66     mAnimator( NULL ),
   130     mInfoText( 0 ),
    67     mInfoText( NULL ),
   131     mCurrentItem( 0 ),
    68     mContainer( new HbWidget( this ) ),
   132     mPanStartPos( 0 )
    69     mMidScrollPos( 0 ),
       
    70     mMaxScrollPos( 0 ),
       
    71     mCurrentIndex( 0 ),
       
    72     mTargetIndex( -1 ),
       
    73     mIsCustomFreq( false ),
       
    74     mInfoTextType( CarouselInfoText::None ),
       
    75     mModel( NULL ),
       
    76     mPosAdjustmentDisabled( false ),
       
    77     mScrollDirection( Scroll::Shortest ),
       
    78     mManualSeekMode( false ),
       
    79     mAlternateSkipping( false )
   133 #ifdef USE_DEBUGGING_CONTROLS
    80 #ifdef USE_DEBUGGING_CONTROLS
   134     ,mRdsLabel( new RadioFadingLabel( this ) )
    81     ,mRdsLabel( new RadioFadingLabel( this ) )
   135 #endif // USE_DEBUGGING_CONTROLS
    82 #endif // USE_DEBUGGING_CONTROLS
   136 {
    83 {
   137     RadioUiUtilities::setCarousel( this );
       
   138     setClampingStyle( HbScrollArea::StrictClamping );
       
   139     setScrollingStyle( HbScrollArea::Pan );
       
   140 }
    84 }
   141 
    85 
   142 /*!
    86 /*!
   143  * Property
    87  * Property
   144  *
    88  *
   195  *
   139  *
   196  */
   140  */
   197 void RadioStationCarousel::init( RadioUiLoader& uiLoader, RadioUiEngine* uiEngine )
   141 void RadioStationCarousel::init( RadioUiLoader& uiLoader, RadioUiEngine* uiEngine )
   198 {
   142 {
   199     mUiEngine = uiEngine;
   143     mUiEngine = uiEngine;
   200     mAntennaAttached = mUiEngine->isAntennaAttached();
   144     RadioUtil::setCarousel( this );
       
   145 
       
   146     mItems[LeftItem] = new RadioCarouselItem( *this );
       
   147     mItems[CenterItem] = new RadioCarouselItem( *this );
       
   148     mItems[RightItem] = new RadioCarouselItem( *this );
       
   149 
       
   150     QGraphicsLinearLayout* layout = new QGraphicsLinearLayout( Qt::Horizontal );
       
   151     layout->setContentsMargins( 0, 0, 0, 0 );
       
   152     layout->setSpacing( 0 );
       
   153     layout->addItem( mItems[LeftItem] );
       
   154     layout->addItem( mItems[CenterItem] );
       
   155     layout->addItem( mItems[RightItem] );
       
   156     mContainer->setLayout( layout );
       
   157     setContentWidget( mContainer );
       
   158 
       
   159     setClampingStyle( HbScrollArea::NoClamping );
       
   160     setScrollDirections( Qt::Horizontal );
       
   161 
       
   162     setFrictionEnabled( true );
       
   163     setHorizontalScrollBarPolicy( HbScrollArea::SCROLLBAR_POLICY );
       
   164     setVerticalScrollBarPolicy( HbScrollArea::ScrollBarAlwaysOff );
   201 
   165 
   202     mInfoText = uiLoader.findWidget<HbLabel>( DOCML::MV_NAME_INFO_TEXT );
   166     mInfoText = uiLoader.findWidget<HbLabel>( DOCML::MV_NAME_INFO_TEXT );
   203     mInfoText->setTextWrapping( Hb::TextWordWrap );
   167     mInfoText->setTextWrapping( Hb::TextWordWrap );
   204 
   168 
   205     setRowCount( 1 );
   169 #ifdef BUILD_WIN32
   206     setColumnCount( 1 );
   170     HbFontSpec spec = mInfoText->fontSpec();
       
   171     spec.setRole( HbFontSpec::Secondary );
       
   172     mInfoText->setFontSpec( spec );
       
   173 #endif
       
   174 
   207     setScrollDirections( Qt::Horizontal );
   175     setScrollDirections( Qt::Horizontal );
   208     setFrictionEnabled( true );
   176 //    grabGesture( Qt::SwipeGesture );
   209     setLongPressEnabled( false );
   177 
   210     setItemRecycling( false );
   178 //    Radio::connect( this,           SIGNAL(scrollPositionChanged(QPointF)),
   211     setUniformItemSizes( true );
   179 //                    this,           SLOT(scrollPosChanged(QPointF)) );
   212     setItemPrototype( new RadioStationItem( *this ) );
   180     Radio::connect( this,           SIGNAL(scrollingEnded()),
   213     setSelectionMode( NoSelection );
   181                     this,           SLOT(adjustAfterScroll()) );
   214 
   182 
   215 //    grabGesture( Qt::PanGesture );
   183     mModel = &mUiEngine->stationModel();
   216 
   184     Radio::connect( mModel,         SIGNAL(favoriteChanged(RadioStation)),
   217     RadioCarouselModel* carouselModel = mUiEngine->carouselModel();
       
   218     setCarouselModel( carouselModel );
       
   219 
       
   220     mCurrentItem = static_cast<RadioStationItem*>( itemByIndex( carouselModel->index( 0, 0 ) ) );
       
   221 
       
   222     RadioStationModel* stationModel = &mUiEngine->stationModel();
       
   223     connectAndTest( stationModel,   SIGNAL(favoriteChanged(RadioStation)),
       
   224                     this,           SLOT(update(RadioStation)) );
   185                     this,           SLOT(update(RadioStation)) );
   225     connectAndTest( stationModel,   SIGNAL(stationDataChanged(RadioStation)),
   186     Radio::connect( mModel,         SIGNAL(stationDataChanged(RadioStation)),
   226                     this,           SLOT(update(RadioStation)));
   187                     this,           SLOT(update(RadioStation)));
   227     connectAndTest( stationModel,   SIGNAL(radioTextReceived(RadioStation)),
   188     Radio::connect( mModel,         SIGNAL(radioTextReceived(RadioStation)),
   228                     this,           SLOT(updateRadioText(RadioStation)));
   189                     this,           SLOT(updateRadioText(RadioStation)));
   229     connectAndTest( stationModel,   SIGNAL(dynamicPsChanged(RadioStation)),
   190     Radio::connect( mModel,         SIGNAL(dynamicPsChanged(RadioStation)),
   230                     this,           SLOT(update(RadioStation)));
   191                     this,           SLOT(update(RadioStation)));
   231 
   192 
   232     updateClampingStyle();
       
   233 
       
   234     connectAndTest( this,           SIGNAL(longPressed(HbAbstractViewItem*,QPointF)),
       
   235                     this,           SLOT(openContextMenu(HbAbstractViewItem*,QPointF)) );
       
   236     setLongPressEnabled( true );
       
   237 
       
   238     mGenericTimer->setSingleShot( true );
   193     mGenericTimer->setSingleShot( true );
   239     connectAndTest( mGenericTimer,  SIGNAL(timeout()),
   194     Radio::connect( mGenericTimer,  SIGNAL(timeout()),
   240                     this,           SLOT(timerFired()));
   195                     this,           SLOT(timerFired()));
   241 
   196 
   242     initToLastTunedFrequency();
   197     Radio::connect( mModel,         SIGNAL(rowsInserted(QModelIndex,int,int)),
       
   198                     this,           SLOT(updateStations()) );
       
   199     Radio::connect( mModel,         SIGNAL(modelReset()),
       
   200                     this,           SLOT(updateStations()) );
       
   201     Radio::connect( mModel,         SIGNAL(rowsRemoved(QModelIndex,int,int)),
       
   202                     this,           SLOT(updateStations()) );
       
   203 
       
   204     setFrequency( mUiEngine->currentFrequency(), TuneReason::Unspecified );
   243 
   205 
   244 #ifdef USE_DEBUGGING_CONTROLS
   206 #ifdef USE_DEBUGGING_CONTROLS
   245     mRdsLabel->setPos( QPoint( 300, 10 ) );
   207     mRdsLabel->setPos( QPoint( 300, 10 ) );
   246     mRdsLabel->setText( "RDS" );
   208     mRdsLabel->setText( "RDS" );
   247     mRdsLabel->setElideMode( Qt::ElideNone );
   209     mRdsLabel->setElideMode( Qt::ElideNone );
   249     spec.setTextPaneHeight( 10 );
   211     spec.setTextPaneHeight( 10 );
   250     spec.setRole( HbFontSpec::Secondary );
   212     spec.setRole( HbFontSpec::Secondary );
   251     mRdsLabel->setFontSpec( spec );
   213     mRdsLabel->setFontSpec( spec );
   252     mRdsLabel->setTextColor( Qt::gray );
   214     mRdsLabel->setTextColor( Qt::gray );
   253     if ( mUiEngine ) {
   215     if ( mUiEngine ) {
   254         connectAndTest( mUiEngine,      SIGNAL(rdsAvailabilityChanged(bool)),
   216         Radio::connect( mUiEngine,      SIGNAL(rdsAvailabilityChanged(bool)),
   255                         this,           SLOT(setRdsAvailable(bool)) );
   217                         this,           SLOT(setRdsAvailable(bool)) );
   256     }
   218     }
   257 #endif // USE_DEBUGGING_CONTROLS
   219 #endif // USE_DEBUGGING_CONTROLS
   258 }
   220 }
   259 
   221 
   260 /*!
   222 /*!
   261  *
   223  *
   262  */
   224  */
   263 void RadioStationCarousel::setCarouselModel( RadioCarouselModel* carouselModel )
   225 void RadioStationCarousel::setFrequency( uint frequency, int reason, Scroll::Direction direction )
   264 {
   226 {
   265     if ( carouselModel ) {
   227     if ( mModel ) {
   266         connectAndTest( carouselModel,  SIGNAL(rowsInserted(QModelIndex,int,int)),
   228         if ( !mManualSeekMode ) {
   267                         this,           SLOT(insertFrequency(QModelIndex,int,int)) );
   229 
   268         connectAndTest( carouselModel,  SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
   230             if ( mModel->rowCount() <= 1 ) {
   269                         this,           SLOT(prepareToRemoveFrequency(QModelIndex,int,int)) );
   231                 mItems[LeftItem]->setStation( RadioStation() );
   270         connectAndTest( carouselModel,  SIGNAL(rowsRemoved(QModelIndex,int,int)),
   232                 mItems[RightItem]->setStation( RadioStation() );
   271                         this,           SLOT(removeFrequency(QModelIndex,int,int)) );
   233             }
       
   234 
       
   235             mIsCustomFreq = false;
       
   236             if ( reason == TuneReason::Skip || reason == TuneReason::StationScanFinalize ) {
       
   237                 const int newIndex = mModel->indexFromFrequency( frequency );
       
   238                 scrollToIndex( newIndex, direction, NoSignal );
       
   239                 mCurrentIndex = newIndex;
       
   240             } else {
       
   241                 if ( mModel->contains( frequency ) ) {
       
   242                     mCurrentIndex = mModel->indexFromFrequency( frequency );
       
   243                 } else {
       
   244                     const RadioStation prevStation = mModel->findClosest( frequency, StationSkip::Previous );
       
   245                     if ( prevStation.isValid() ) {
       
   246                         mCurrentIndex = mModel->indexFromFrequency( prevStation.frequency() );
       
   247                     } else {
       
   248                         mCurrentIndex = -1;
       
   249                     }
       
   250 
       
   251                     mIsCustomFreq = true;
       
   252                 }
       
   253 
       
   254                 mItems[CenterItem]->setFrequency( frequency );
       
   255                 mTimerMode = SetFrequency;
       
   256                 mGenericTimer->stop();
       
   257                 mGenericTimer->start( SET_FREQUENCY_TIMEOUT );
       
   258             }
       
   259         } else {
       
   260             mItems[CenterItem]->setFrequency( frequency );
       
   261         }
       
   262     }
       
   263 }
       
   264 
       
   265 /*!
       
   266  *
       
   267  */
       
   268 RadioUiEngine* RadioStationCarousel::uiEngine()
       
   269 {
       
   270     return mUiEngine;
       
   271 }
       
   272 
       
   273 /*!
       
   274  *
       
   275  */
       
   276 bool RadioStationCarousel::isAntennaAttached() const
       
   277 {
       
   278     return mUiEngine->isAntennaAttached();
       
   279 }
       
   280 
       
   281 /*!
       
   282  *
       
   283  */
       
   284 void RadioStationCarousel::setScanningMode( bool scanning )
       
   285 {
       
   286     CALL_TO_ALL_ITEMS( setSeekLayout( scanning ) );
       
   287 
       
   288     if ( scanning ) {
       
   289         setInfoText( CarouselInfoText::Scanning );
       
   290         if ( !mAnimator ) {
       
   291             mAnimator = new RadioCarouselAnimator( *this );
       
   292         }
       
   293         mAnimator->startFlashingText();
   272     } else {
   294     } else {
   273         QAbstractItemModel* currentModel = model();
   295         if ( mAnimator ) {
   274         disconnect( currentModel,   SIGNAL(rowsInserted(QModelIndex,int,int)),
   296             mAnimator->stopFlashingText();
   275                     this,           SLOT(insertFrequency(QModelIndex,int,int)) );
   297         }
   276         disconnect( currentModel,   SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
       
   277                     this,           SLOT(prepareToRemoveFrequency(QModelIndex,int,int)) );
       
   278         disconnect( currentModel,   SIGNAL(rowsRemoved(QModelIndex,int,int)),
       
   279                     this,           SLOT(removeFrequency(QModelIndex,int,int)) );
       
   280     }
       
   281     setModel( carouselModel );
       
   282     updateFrequencies();
       
   283     initCurrentStationItem();
       
   284 }
       
   285 
       
   286 /*!
       
   287  *
       
   288  */
       
   289 void RadioStationCarousel::setFrequency( uint frequency, int reason )
       
   290 {
       
   291     RadioStationItem* item = currentStationItem();
       
   292 //    if ( item && item->mFrequency == frequency ) {
       
   293 //        return;
       
   294 //    }
       
   295 
       
   296     if ( mModelIndexes.contains( frequency ) ) {
       
   297         QModelIndex index = mModelIndexes.value( frequency );
       
   298 
       
   299         if ( reason == TuneReason::FrequencyStrip || reason == TuneReason::StationsList ) {
       
   300             scrollToIndex( index, RadioStationCarousel::NoAnim | RadioStationCarousel::NoSignal );
       
   301         } else if ( reason == TuneReason::Skip || reason == TuneReason::StationScan ) {
       
   302             scrollToIndex( index, RadioStationCarousel::NoSignal );
       
   303         } else {
       
   304             scrollToIndex( index );
       
   305         }
       
   306     } else {
       
   307         if ( item ) {
       
   308             item->setFrequency( frequency );
       
   309         }
       
   310     }
       
   311 }
       
   312 
       
   313 /*!
       
   314  *
       
   315  */
       
   316 RadioUiEngine* RadioStationCarousel::uiEngine()
       
   317 {
       
   318     return mUiEngine;
       
   319 }
       
   320 
       
   321 /*!
       
   322  *
       
   323  */
       
   324 bool RadioStationCarousel::isAntennaAttached() const
       
   325 {
       
   326     return mAntennaAttached;
       
   327 }
       
   328 
       
   329 /*!
       
   330  *
       
   331  */
       
   332 void RadioStationCarousel::setScanningMode( bool scanning )
       
   333 {
       
   334     initCurrentStationItem();
       
   335 
       
   336     if ( scanning ) {
       
   337 
       
   338         setInfoText( CarouselInfoText::Scanning );
       
   339         if ( !mScanningHelper ) {
       
   340             mScanningHelper = new ScanningHelper( *this );
       
   341         }
       
   342     } else {
       
   343         delete mScanningHelper;
       
   344         mScanningHelper = 0;
       
   345         clearInfoText();
   298         clearInfoText();
   346     }
   299         setCenterIndex( 0 );
       
   300         mTimerMode = FavoriteHintShow;
       
   301         mGenericTimer->start( FAVORITE_HINT_SHOW_DELAY );
       
   302     }
       
   303 
   347     setEnabled( !scanning );
   304     setEnabled( !scanning );
   348 }
   305 }
   349 
   306 
   350 /*!
   307 /*!
   351  *
   308  *
   352  */
   309  */
   353 bool RadioStationCarousel::isInScanningMode() const
   310 bool RadioStationCarousel::isInScanningMode() const
   354 {
   311 {
   355     return RadioUiUtilities::isScannerAlive();
   312     return RadioUtil::scanStatus() == Scan::ScanningInMainView;
   356 }
   313 }
   357 
   314 
   358 /*!
   315 /*!
   359  *
   316  *
   360  */
   317  */
   361 void RadioStationCarousel::cleanRdsData()
   318 void RadioStationCarousel::cleanRdsData()
   362 {
   319 {
   363     RadioStationItem* item = currentStationItem();
   320     mItems[CenterItem]->cleanRdsData();
   364     if ( item ) {
       
   365         item->cleanRdsData();
       
   366     }
       
   367 }
       
   368 
       
   369 /*!
       
   370  *
       
   371  */
       
   372 void RadioStationCarousel::updateCurrentItem()
       
   373 {
       
   374     RadioStationItem* item = currentStationItem();
       
   375     if ( item ) {
       
   376         item->update();
       
   377     }
       
   378 }
   321 }
   379 
   322 
   380 /*!
   323 /*!
   381  *
   324  *
   382  */
   325  */
   383 void RadioStationCarousel::animateNewStation( const RadioStation& station )
   326 void RadioStationCarousel::animateNewStation( const RadioStation& station )
   384 {
   327 {
   385     if ( mScanningHelper ) {
   328     if ( mAnimator && mUiEngine ) {
   386         RadioCarouselModel* model = carouselModel();
   329         const uint previousFrequency = mItems[CenterItem]->frequency();
   387         const QModelIndex index = model->modelIndexFromFrequency( station.frequency() );
   330 
   388         mScanningHelper->mModelIndex = index;
   331         mItems[RightItem]->setFrequency( previousFrequency );
   389         mScanningHelper->mCurrentFrequency = station.frequency();
   332         mCurrentIndex = mModel->indexFromFrequency( station.frequency() );
   390         mScanningHelper->mStationItem = static_cast<RadioStationItem*>( itemByIndex( index ) );
   333 
   391 
   334         mAnimator->startNumberScroll( previousFrequency, station.frequency() );
   392         uint prevFrequency = 0;
   335     }
   393         if ( model->rowCount() > 1 ) {
   336 }
   394             const int prevIndex = index.row() - 1;
   337 
   395             RadioStation prevStation = model->data( model->index( prevIndex, 0 ), RadioStationModel::RadioStationRole ).value<RadioStation>();
   338 /*!
   396             prevFrequency = prevStation.frequency();
   339  *
   397         } else if ( mUiEngine ) {
   340  */
   398             prevFrequency = mUiEngine->minFrequency();
   341 void RadioStationCarousel::cancelAnimation()
   399         }
   342 {
   400 
   343     if ( mAnimator ) {
   401         mScanningHelper->mPreviousFrequency = prevFrequency;
   344         mAnimator->stopAll();
   402         if ( mScanningHelper->mStationItem ) {
       
   403             mScanningHelper->mStationItem->setFrequency( prevFrequency );
       
   404             mScanningHelper->mStationItem->cleanRdsData();
       
   405         }
       
   406 
       
   407         mScanningHelper->start();
       
   408     }
       
   409 }
       
   410 
       
   411 /*!
       
   412  *
       
   413  */
       
   414 void RadioStationCarousel::setItemVisible( bool visible )
       
   415 {
       
   416     RadioStationItem* item = currentStationItem();
       
   417     if ( item ) {
       
   418         item->setVisible( visible );
       
   419     }
   345     }
   420 }
   346 }
   421 
   347 
   422 /*!
   348 /*!
   423  *
   349  *
   424  */
   350  */
   425 void RadioStationCarousel::setInfoText( CarouselInfoText::Type type )
   351 void RadioStationCarousel::setInfoText( CarouselInfoText::Type type )
   426 {
   352 {
   427     mInfoTextType = type;
   353     mInfoTextType = type;
   428     if ( type == CarouselInfoText::NoFavorites ) {
   354     if ( type == CarouselInfoText::NoFavorites || type == CarouselInfoText::FavoriteIconHint ) {
   429         mInfoText->setPlainText( hbTrId( "txt_rad_dialog_long_press_arrow_keys_to_search_str" ) );
   355 //        mInfoText->setPlainText( hbTrId( "txt_rad_dialog_long_press_arrow_keys_to_search_str" ) );
       
   356     //TODO: Remove hardcoding. Temporarily hardcoded for usability testing
       
   357         mInfoText->setPlainText( "Tap star to mark favourites" );
   430         mInfoText->setAlignment( Qt::AlignCenter );
   358         mInfoText->setAlignment( Qt::AlignCenter );
   431         setItemVisible( false );
   359         mItems[CenterItem]->setItemVisibility( RadioCarouselItem::IconVisible );
   432         mTimerMode = InfoText;
   360         mTimerMode = InfoText;
   433         mGenericTimer->setInterval( INFOTEXT_NOFAVORITES_TIMEOUT );
   361         mGenericTimer->setInterval( INFOTEXT_NOFAVORITES_TIMEOUT );
   434         mGenericTimer->start();
   362         mGenericTimer->start();
       
   363 
       
   364         if ( !mAnimator ) {
       
   365             mAnimator = new RadioCarouselAnimator( *this );
       
   366         }
       
   367         mAnimator->startFlashingIcon();
       
   368 
   435     } else if ( type == CarouselInfoText::ConnectAntenna ) {
   369     } else if ( type == CarouselInfoText::ConnectAntenna ) {
   436         cleanRdsData();
   370         cleanRdsData();
   437         mInfoText->setPlainText( hbTrId( "txt_rad_info_connect_wired_headset1" ) );
   371         mInfoText->setPlainText( hbTrId( "txt_rad_info_connect_wired_headset1" ) );
   438         mInfoText->setAlignment( Qt::AlignBottom | Qt::AlignHCenter );
   372         mInfoText->setAlignment( Qt::AlignBottom | Qt::AlignHCenter );
   439     } else if ( type == CarouselInfoText::Seeking ) {
   373     } else if ( type == CarouselInfoText::Seeking ) {
   442         mInfoText->setPlainText( hbTrId( "txt_rad_list_seeking" ) );
   376         mInfoText->setPlainText( hbTrId( "txt_rad_list_seeking" ) );
   443     } else if ( type == CarouselInfoText::Scanning ) {
   377     } else if ( type == CarouselInfoText::Scanning ) {
   444         cleanRdsData();
   378         cleanRdsData();
   445         mInfoText->setAlignment( Qt::AlignBottom | Qt::AlignHCenter );
   379         mInfoText->setAlignment( Qt::AlignBottom | Qt::AlignHCenter );
   446         mInfoText->setPlainText( hbTrId( "txt_rad_list_searching_all_available_stations_ple" ) );
   380         mInfoText->setPlainText( hbTrId( "txt_rad_list_searching_all_available_stations_ple" ) );
       
   381     } else if ( type == CarouselInfoText::ManualSeek ) {
       
   382         mInfoText->setAlignment( Qt::AlignBottom | Qt::AlignHCenter );
       
   383         mInfoText->setPlainText( "Manual Seek Mode" );
   447     }
   384     }
   448 
   385 
   449     mInfoText->setVisible( true );
   386     mInfoText->setVisible( true );
   450 }
   387 }
   451 
   388 
   453  *
   390  *
   454  */
   391  */
   455 void RadioStationCarousel::clearInfoText()
   392 void RadioStationCarousel::clearInfoText()
   456 {
   393 {
   457     if ( mInfoTextType != CarouselInfoText::None ) {
   394     if ( mInfoTextType != CarouselInfoText::None ) {
       
   395         if ( mAnimator ) {
       
   396             mAnimator->stopFlashingIcon();
       
   397         }
       
   398 
   458         mGenericTimer->stop();
   399         mGenericTimer->stop();
   459         mInfoTextType = CarouselInfoText::None;
   400         mInfoTextType = CarouselInfoText::None;
   460         mInfoText->setVisible( false );
   401         mInfoText->setVisible( false );
   461         mInfoText->clear();
   402         mInfoText->clear();
   462         setItemVisible( true );
   403         mItems[CenterItem]->setItemVisibility( RadioCarouselItem::AllVisible );
   463         updateCurrentItem();
   404     }
   464     }
   405 }
       
   406 
       
   407 /*!
       
   408  *
       
   409  */
       
   410 void RadioStationCarousel::setManualSeekMode( bool manualSeekActive )
       
   411 {
       
   412     mManualSeekMode = manualSeekActive;
       
   413     setEnabled( !manualSeekActive );
       
   414 
       
   415     mItems[CenterItem]->setSeekLayout( manualSeekActive );
       
   416     if ( manualSeekActive ) {
       
   417         setInfoText( CarouselInfoText::ManualSeek );
       
   418     } else {
       
   419         clearInfoText();
       
   420         setFrequency( mUiEngine->currentFrequency(), TuneReason::Unspecified );
       
   421     }
       
   422 }
       
   423 
       
   424 /*!
       
   425  * TODO: Remove this! This is test code
       
   426  */
       
   427 void RadioStationCarousel::setAlternateSkippingMode( bool alternateSkipping )
       
   428 {
       
   429     mAlternateSkipping = alternateSkipping;
   465 }
   430 }
   466 
   431 
   467 /*!
   432 /*!
   468  * Private slot
   433  * Private slot
       
   434  *
       
   435  */
       
   436 void RadioStationCarousel::scrollPosChanged( const QPointF& newPosition )
       
   437 {
       
   438     Q_UNUSED( newPosition );
       
   439 //    const int xPos = static_cast<int>( newPosition.x() );
       
   440 //    mItems[CenterItem]->setPos( xPos - mMidScrollPos, 0 );
       
   441 }
       
   442 
       
   443 /*!
       
   444  * Private slot
       
   445  ''
       
   446  */
       
   447 void RadioStationCarousel::adjustAfterScroll()
       
   448 {
       
   449     if ( isInScanningMode() ) {
       
   450         return;
       
   451     }
       
   452 
       
   453     if ( mTargetIndex != -1 ) {
       
   454         setCenterIndex( mTargetIndex );
       
   455     }
       
   456 }
       
   457 
       
   458 /*!
       
   459  * Private slot
       
   460  *
   469  */
   461  */
   470 void RadioStationCarousel::update( const RadioStation& station )
   462 void RadioStationCarousel::update( const RadioStation& station )
   471 {
   463 {
   472     RadioStationItem* item = currentStationItem();
   464     if ( !mManualSeekMode && !isInScanningMode() ) {
   473     if ( item && item->frequency() == station.frequency() && !isInScanningMode() ) {
   465         for ( int i = LeftItem; i <= RightItem; ++i ) {
   474         item->update( &station );
   466             if ( mItems[i]->frequency() == station.frequency() ) {
       
   467                 mItems[i]->update( &station );
       
   468             }
       
   469         }
   475     }
   470     }
   476 }
   471 }
   477 
   472 
   478 /*!
   473 /*!
   479  * Private slot
   474  * Private slot
   480  */
   475  */
   481 void RadioStationCarousel::updateRadioText( const RadioStation& station )
   476 void RadioStationCarousel::updateRadioText( const RadioStation& station )
   482 {
   477 {
   483     if ( isAntennaAttached() && !isInScanningMode() ) {
   478     if ( isAntennaAttached() && !isInScanningMode() ) {
   484         if ( station.radioText().isEmpty() ) {
   479         if ( station.radioText().isEmpty() ) {
   485             RadioStationItem* item = currentStationItem();
   480             mItems[CenterItem]->setRadioText( "" );
   486             if ( item ) {
       
   487                 item->mRadiotextLabel->setText( "" );
       
   488             }
       
   489         } else {
   481         } else {
   490             mRadioTextHolder = station.radioText();
   482             mRadioTextHolder = station.radioText();
   491             mTimerMode = RtPlusCheck;
   483             mTimerMode = RtPlusCheck;
   492             mGenericTimer->stop();
   484             mGenericTimer->stop();
   493             mGenericTimer->setInterval( KRadioTextPlusCheckTimeout );
   485             mGenericTimer->setInterval( RTPLUS_CHECK_TIMEOUT );
   494             mGenericTimer->start();
   486             mGenericTimer->start();
   495         }
   487         }
   496     }
   488     }
   497 }
   489 }
   498 
   490 
   499 /*!
   491 /*!
   500  * Private slot
   492  * Private slot
   501  */
   493  */
   502 void RadioStationCarousel::insertFrequency( const QModelIndex& parent, int first, int last )
   494 void RadioStationCarousel::updateStations()
   503 {
   495 {
   504     Q_UNUSED( parent );
   496     if ( isInScanningMode() ) {
   505     QAbstractItemModel* freqModel = model();
   497         return;
   506 
   498     }
   507     for ( int i = first; freqModel && i <= last; ++i ) {
   499 
   508         QModelIndex index = freqModel->index( i, 0 );
   500     setFrequency( mUiEngine->currentFrequency(), TuneReason::Unspecified );
   509         RadioStation station = freqModel->data( index, RadioStationModel::RadioStationRole ).value<RadioStation>();
       
   510         mModelIndexes.insert( station.frequency(), index );
       
   511         LOG_FORMAT( "Added frequency %u", station.frequency() );
       
   512         if ( !isInScanningMode() ) {
       
   513             scrollToIndex( index, RadioStationCarousel::NoAnim | RadioStationCarousel::NoSignal );
       
   514         }
       
   515     }
       
   516 
       
   517     initCurrentStationItem();
       
   518 
       
   519     updateClampingStyle();
       
   520 }
   501 }
   521 
   502 
   522 /*!
   503 /*!
   523  * Private slot
   504  * Private slot
   524  */
   505  */
   525 void RadioStationCarousel::prepareToRemoveFrequency( const QModelIndex& parent, int first, int last )
       
   526 {
       
   527     Q_UNUSED( parent );
       
   528     QAbstractItemModel* freqModel = model();
       
   529     for ( int i = first; freqModel && i <= last; ++i ) {
       
   530         QModelIndex index = freqModel->index( i, 0 );
       
   531         RadioStation station = freqModel->data( index, RadioStationModel::RadioStationRole ).value<RadioStation>();
       
   532         mModelIndexes.remove( station.frequency() );
       
   533     }
       
   534 }
       
   535 
       
   536 /*!
       
   537  * Private slot
       
   538  */
       
   539 void RadioStationCarousel::removeFrequency( const QModelIndex& parent, int first, int last )
       
   540 {
       
   541     Q_UNUSED( parent );
       
   542     Q_UNUSED( first );
       
   543     Q_UNUSED( last );
       
   544 
       
   545     initCurrentStationItem();
       
   546     updateClampingStyle();
       
   547 }
       
   548 
       
   549 /*!
       
   550  * Private slot
       
   551  */
       
   552 void RadioStationCarousel::updateFrequencies()
       
   553 {
       
   554     mModelIndexes.clear();
       
   555     QAbstractItemModel* itemModel = model();
       
   556     if ( itemModel ) {
       
   557         const int count = itemModel->rowCount();
       
   558         for ( int i = 0; i < count; ++i ) {
       
   559             QModelIndex index = itemModel->index( i, 0 );
       
   560             uint frequency = itemModel->data( index, RadioStationModel::RadioStationRole ).value<RadioStation>().frequency();
       
   561             mModelIndexes.insert( frequency, index );
       
   562         }
       
   563     }
       
   564 }
       
   565 
       
   566 /*!
       
   567  * Private slot
       
   568  */
       
   569 void RadioStationCarousel::timerFired()
   506 void RadioStationCarousel::timerFired()
   570 {
   507 {
   571     if ( mTimerMode == RtPlusCheck ) {
   508     if ( mTimerMode == SetFrequency ) {
   572         RadioStationItem* item = currentStationItem();
   509         setCenterIndex( mCurrentIndex, NoSignal | IgnoreCenter );
   573         if ( item ) {
   510         mTimerMode = NoTimer;
   574             item->mRadiotextLabel->setText( mRadioTextHolder );
   511     } else if ( mTimerMode == RtPlusCheck ) {
   575         }
   512         //mItems[CenterItem]->mRadiotextLabel->setText( mRadioTextHolder );
   576         mRadioTextHolder = "";
   513         mRadioTextHolder = "";
       
   514         mTimerMode = NoTimer;
   577     } else if ( mTimerMode == InfoText ) {
   515     } else if ( mTimerMode == InfoText ) {
   578         clearInfoText();
   516         clearInfoText();
   579     }
   517         mTimerMode = NoTimer;
   580 
   518     } else if ( mTimerMode == FavoriteHintShow ) {
   581     mTimerMode = NoTimer;
   519         setInfoText( CarouselInfoText::FavoriteIconHint );
       
   520         mTimerMode = FavoriteHintHide;
       
   521         mGenericTimer->start( FAVORITE_HINT_HIDE_DELAY );
       
   522     } else if ( mTimerMode == FavoriteHintHide ) {
       
   523         clearInfoText();
       
   524         mTimerMode = NoTimer;
       
   525     }
   582 }
   526 }
   583 
   527 
   584 /*!
   528 /*!
   585  * Private slot
   529  * Private slot
   586  */
   530  */
   587 void RadioStationCarousel::openContextMenu( HbAbstractViewItem* item, const QPointF& coords )
   531 void RadioStationCarousel::toggleFavorite()
   588 {
   532 {
   589     if ( item ) {
   533     if ( mModel ) {
   590         static_cast<RadioStationItem*>( item )->handleLongPress( coords );
   534         mModel->setData( QModelIndex(), mItems[CenterItem]->frequency(), RadioRole::ToggleFavoriteRole );
   591     }
   535     }
   592 }
   536 }
       
   537 
       
   538 /*!
       
   539  * Private slot
       
   540  */
       
   541 //void RadioStationCarousel::openContextMenu( HbAbstractViewItem* item, const QPointF& coords )
       
   542 //{
       
   543 //    if ( item ) {
       
   544 //        static_cast<RadioStationItem*>( item )->handleLongPress( coords );
       
   545 //    }
       
   546 //}
   593 
   547 
   594 #ifdef USE_DEBUGGING_CONTROLS
   548 #ifdef USE_DEBUGGING_CONTROLS
   595 /*!
   549 /*!
   596  * Public slot
   550  * Public slot
   597  */
   551  */
   612 /*!
   566 /*!
   613  * Public slot
   567  * Public slot
   614  */
   568  */
   615 void RadioStationCarousel::updateAntennaStatus( bool connected )
   569 void RadioStationCarousel::updateAntennaStatus( bool connected )
   616 {
   570 {
   617     mAntennaAttached = connected;
       
   618     mGenericTimer->stop();
   571     mGenericTimer->stop();
   619 
   572 
   620     if ( !connected ) {
   573     if ( !connected ) {
   621         setInfoText( CarouselInfoText::ConnectAntenna );
   574         setInfoText( CarouselInfoText::ConnectAntenna );
   622     } else {
   575     } else {
   627 /*!
   580 /*!
   628  * \reimp
   581  * \reimp
   629  */
   582  */
   630 void RadioStationCarousel::mousePressEvent( QGraphicsSceneMouseEvent* event )
   583 void RadioStationCarousel::mousePressEvent( QGraphicsSceneMouseEvent* event )
   631 {
   584 {
   632     if ( mInfoTextType == CarouselInfoText::NoFavorites ) {
   585     if ( mInfoTextType == CarouselInfoText::NoFavorites || mInfoTextType == CarouselInfoText::FavoriteIconHint ) {
   633         clearInfoText();
   586         clearInfoText();
   634     }
   587     }
   635 
   588 
   636     HbGridView::mousePressEvent( event );
   589     HbScrollArea::mousePressEvent( event );
   637 }
   590 }
   638 
   591 
   639 /*!
   592 /*!
   640  * \reimp
   593  * \reimp
   641  */
   594  */
       
   595 void RadioStationCarousel::resizeEvent( QGraphicsSceneResizeEvent* event )
       
   596 {
       
   597     HbScrollArea::resizeEvent( event );
       
   598 
       
   599     const int width = (int)event->newSize().width();
       
   600 
       
   601     mMidScrollPos = -width;
       
   602     mMaxScrollPos = mMidScrollPos * 2;
       
   603 
       
   604     if ( isInitialized() ) {
       
   605         mItems[LeftItem]->setMinimumWidth( width );
       
   606         mItems[CenterItem]->setMinimumWidth( width );
       
   607         mItems[RightItem]->setMinimumWidth( width );
       
   608     }
       
   609 }
       
   610 
       
   611 /*!
       
   612  * \reimp
       
   613  */
       
   614 void RadioStationCarousel::showEvent( QShowEvent* event )
       
   615 {
       
   616     HbScrollArea::showEvent( event );
       
   617 //    mContainer->setPos( mMidScrollPos, 0 );
       
   618 }
       
   619 
       
   620 /*!
       
   621  * \reimp
       
   622  */
   642 void RadioStationCarousel::gestureEvent( QGestureEvent* event )
   623 void RadioStationCarousel::gestureEvent( QGestureEvent* event )
   643 {
   624 {
   644     HbGridView::gestureEvent( event );
   625 //    if ( HbSwipeGesture* swipeGesture = static_cast<HbSwipeGesture*>( event->gesture( Qt::SwipeGesture ) ) ) {
       
   626 //        if ( swipeGesture->state() == Qt::GestureFinished ) {
       
   627 //            if ( swipeGesture->horizontalDirection() == QSwipeGesture::Left ) {
       
   628 //                emit skipRequested( StationSkip::Next );
       
   629 //            } else if ( swipeGesture->horizontalDirection() == QSwipeGesture::Right ) {
       
   630 //                emit skipRequested( StationSkip::Previous );
       
   631 //            }
       
   632 //            mIsCustomFreq = false;
       
   633 //        }
       
   634 //        return;
       
   635 //    }
       
   636 
       
   637     HbScrollArea::gestureEvent( event );
   645 
   638 
   646     if ( HbPanGesture* gesture = qobject_cast<HbPanGesture*>( event->gesture( Qt::PanGesture ) ) ) {
   639     if ( HbPanGesture* gesture = qobject_cast<HbPanGesture*>( event->gesture( Qt::PanGesture ) ) ) {
   647         if ( gesture->state() == Qt::GestureFinished ) {
   640         if ( gesture->state() == Qt::GestureFinished ) {
   648             updatePos( (int)gesture->offset().x() );
   641             adjustPos( (int)gesture->offset().x() );
   649         }
   642         }
   650     }
   643     }
   651 }
   644 }
   652 
   645 
   653 /*!
   646 /*!
   654  *
   647  *
   655  */
   648  */
   656 void RadioStationCarousel::initToLastTunedFrequency()
   649 bool RadioStationCarousel::isInitialized() const
   657 {
   650 {
   658     const uint currentFrequency = mUiEngine->currentFrequency();
   651     return mUiEngine != NULL;
   659     const QModelIndex currentIndex = carouselModel()->modelIndexFromFrequency( currentFrequency );
   652 }
   660 
   653 
   661     if ( currentIndex.isValid() ) {//&& itemByIndex( currentIndex ) ) {
   654 /*!
   662         scrollToIndex( currentIndex, RadioStationCarousel::NoSignal | RadioStationCarousel::NoAnim );
   655  *
   663     } else {
   656  */
   664         RadioStationItem* item = static_cast<RadioStationItem*>( itemAt( 0, 0 ) );
   657 void RadioStationCarousel::setCenterIndex( int index, ScrollMode mode )
   665         if ( item ) {
   658 {
   666             item->setFrequency( currentFrequency );
   659     Q_UNUSED( mode );
   667         }
   660     if ( mModel ) {
   668     }
   661         const int newIndex = trimIndex( index );
   669 }
   662         mCurrentIndex = newIndex;
   670 
   663         mTargetIndex = -1;
   671 /*!
   664 
   672  *
   665         if ( !mIsCustomFreq ) {
   673  */
   666             mItems[CenterItem]->setStation( mModel->stationAt( mCurrentIndex ) );
   674 void RadioStationCarousel::updateClampingStyle()
   667         }
   675 {
   668 
   676     if ( model()->rowCount() > 1 ) {
   669         if ( mModel->rowCount() > 1 ) {
   677         setClampingStyle( HbScrollArea::StrictClamping );
   670             const int leftIndex = prevIndex( mCurrentIndex );
   678     } else {
   671             const int rightIndex = nextIndex( mCurrentIndex );
   679         setClampingStyle( HbScrollArea::BounceBackClamping );
   672             mItems[LeftItem]->setStation( mModel->stationAt( leftIndex ) );
   680         update( mUiEngine->stationModel().currentStation() );
   673             mItems[RightItem]->setStation( mModel->stationAt( rightIndex ) );
   681     }
   674         } else {
   682 }
   675 
   683 
   676             if ( mIsCustomFreq ) {
   684 /*!
   677                 const uint frequency = mItems[CenterItem]->frequency();
   685  *
   678                 mItems[LeftItem]->setStation( mModel->findClosest( frequency, StationSkip::Previous ) );
   686  */
   679                 mItems[RightItem]->setStation( mModel->findClosest( frequency, StationSkip::Next ) );
   687 void RadioStationCarousel::initCurrentStationItem()
   680             } else {
   688 {
   681                 mItems[LeftItem]->setStation( RadioStation() );
   689     mCurrentItem = static_cast<RadioStationItem*>( visibleItems().first() );
   682                 mItems[RightItem]->setStation( RadioStation() );
   690 }
   683             }
   691 
   684         }
   692 /*!
   685 
   693  *
   686         scrollContentsTo( QPointF( -mMidScrollPos /* + delta */, 0 ), 0 );
   694  */
   687 
   695 RadioStationItem* RadioStationCarousel::currentStationItem()
   688 //        if ( !mode.testFlag( NoSignal ) ) {
   696 {
   689 //            uint frequency = mModel->stationAt( mCurrentIndex ).frequency();
   697     return mCurrentItem;
   690 //            emit frequencyChanged( frequency, TuneReason::StationCarousel, mScrollDirection );
   698 }
   691 //            mScrollDirection = Scroll::Shortest;
   699 
   692 //        }
   700 /*!
   693     }
   701  *
   694 }
   702  */
   695 
   703 RadioCarouselModel* RadioStationCarousel::carouselModel() const
   696 /*!
   704 {
   697  *
   705     return static_cast<RadioCarouselModel*>( model() );
   698  */
   706 }
   699 void RadioStationCarousel::scrollToIndex( int index, Scroll::Direction direction, ScrollMode mode )
   707 
   700 {
   708 /*!
   701     if ( mModel && index >= 0  ) {
   709  *
   702         mTargetIndex = index;
   710  */
   703         const int difference = calculateDifference( index, direction );
   711 void RadioStationCarousel::scrollToIndex( const QModelIndex& index, RadioStationCarousel::ScrollMode mode )
   704         int scrollTime = mAutoScrollTime;
   712 {
   705 
   713     RadioStationItem* item = static_cast<RadioStationItem*>( itemByIndex( index ) );
   706         int posX = direction == Scroll::Left ? -mMaxScrollPos : 0;
   714     if ( index.isValid() && item ) {
   707         if ( difference == 1 ) {
   715         const int posX = index.row() * (int)size().width();
   708             if ( direction == Scroll::Right ) {
   716         setCurrentIndex( index, QItemSelectionModel::ClearAndSelect );
   709                 posX = 0;
       
   710             } else if ( direction == Scroll::Left ) {
       
   711                 posX = -mMaxScrollPos;
       
   712             }
       
   713         } else {
       
   714             if ( direction == Scroll::Right ) {
       
   715                 // Item where the scrolling starts
       
   716                 mItems[RightItem]->setStation( mModel->stationAt( mCurrentIndex ) );
       
   717 
       
   718                 // Item that is skipped over
       
   719                 const uint centerFreq = mModel->stationAt( nextIndex( index ) ).frequency();
       
   720                 mItems[CenterItem]->setFrequency( centerFreq );
       
   721 
       
   722                 // Item where the scrolling ends
       
   723                 const RadioStation station = mModel->stationAt( index );
       
   724                 mItems[LeftItem]->setStation( station );
       
   725 
       
   726                 mContainer->setPos( mMaxScrollPos, 0 );
       
   727                 posX = 0;
       
   728             } else if ( direction == Scroll::Left ) {
       
   729                 // Item where the scrolling starts
       
   730                 mItems[LeftItem]->setStation( mModel->stationAt( mCurrentIndex ) );
       
   731 
       
   732                 // Item that is skipped over
       
   733                 const uint centerFreq = mModel->stationAt( prevIndex( index ) ).frequency();
       
   734                 mItems[CenterItem]->setFrequency( centerFreq );
       
   735 
       
   736                 // Item where the scrolling ends
       
   737                 const RadioStation station = mModel->stationAt( index );
       
   738                 mItems[RightItem]->setStation( station );
       
   739 
       
   740                 mContainer->setPos( 0, 0 );
       
   741                 posX = -mMaxScrollPos;
       
   742             }
       
   743         }
   717 
   744 
   718         if ( mode.testFlag( UpdateItem ) ) {
   745         if ( mode.testFlag( UpdateItem ) ) {
   719             item->update();
   746             //item->update();
   720         }
   747         }
   721 
   748 
   722         int scrollTime = mAutoScrollTime;
       
   723         if ( mode.testFlag( NoAnim ) ) {
   749         if ( mode.testFlag( NoAnim ) ) {
   724             scrollTime = 0;
   750             scrollTime = 0;
   725         }
   751         } else if ( mode.testFlag( FromPanGesture ) ) {
       
   752             if ( mAlternateSkipping ) { //TODO: Remove this! This is test code
       
   753                 scrollTime = 500;
       
   754             } else {
       
   755                 scrollTime = 300;
       
   756             }
       
   757         } else if ( mode.testFlag( FromSwipeGesture ) ) {
       
   758             scrollTime = 100;
       
   759         }
       
   760 
   726         scrollContentsTo( QPointF( posX, 0 ), scrollTime );
   761         scrollContentsTo( QPointF( posX, 0 ), scrollTime );
   727         mCurrentItem = static_cast<RadioStationItem*>( item );
   762     }
   728         if ( !mode.testFlag( NoSignal ) ) {
   763 }
   729             uint frequency = model()->data( index, RadioStationModel::RadioStationRole ).value<RadioStation>().frequency();
   764 
   730             emit frequencyChanged( frequency, TuneReason::StationCarousel );
   765 /*!
   731         }
   766  *
   732     }
   767  */
   733 }
   768 int RadioStationCarousel::calculateDifference( int targetIndex, Scroll::Direction& direction )
   734 
   769 {
   735 /*!
   770     int difference = 0;
   736  *
   771     const int rowCount = mModel->rowCount();
   737  */
   772 
   738 void RadioStationCarousel::updatePos( int offset )
   773     int diffToLeft = 0;
   739 {
   774     int diffToRight = 0;
   740 //    QModelIndex index = currentIndex();
   775     if ( targetIndex > mCurrentIndex ) {
   741 //
   776         const int loopedDiff = mCurrentIndex + rowCount - targetIndex;
   742 //    ScrollMode mode = 0;
   777         const int directDiff = targetIndex - mCurrentIndex;
   743 //    const qreal threshold = size().width() / 3;
   778         diffToLeft = loopedDiff;
   744 //    if ( abs( offset ) >= threshold ) {
   779         diffToRight = directDiff;
   745 //        if ( offset > 0 ) {
   780     } else {
   746 //            index = previousIndex( index );
   781         const int loopedDiff = targetIndex + rowCount - mCurrentIndex;
   747 //        } else {
   782         const int directDiff = mIsCustomFreq ? 1 : mCurrentIndex - targetIndex;
   748 //            index = nextIndex( index );
   783         diffToLeft = directDiff;
   749 //        }
   784         diffToRight = loopedDiff;
   750 //    } else {
   785     }
   751 //        mode |= RadioStationCarousel::NoSignal;
   786 
   752 //    }
   787     if ( direction == Scroll::Right ) {
   753 //
   788         difference = diffToLeft;
   754 //    scrollToIndex( index, mode );
   789     } else if ( direction == Scroll::Left ) {
       
   790         difference = diffToRight;
       
   791     } else {
       
   792         if ( diffToLeft < diffToRight ) {
       
   793             difference = diffToLeft;
       
   794             direction = Scroll::Right;
       
   795         } else {
       
   796             difference = diffToRight;
       
   797             direction = Scroll::Left;
       
   798         }
       
   799     }
       
   800 
       
   801     return difference;
       
   802 }
       
   803 
       
   804 /*!
       
   805  *
       
   806  */
       
   807 bool RadioStationCarousel::isScrollingAllowed() const
       
   808 {
       
   809     const int rowCount = mModel->rowCount();
       
   810     return rowCount > 1 || ( rowCount == 1 && mIsCustomFreq );
       
   811 }
       
   812 
       
   813 /*!
       
   814  *
       
   815  */
       
   816 void RadioStationCarousel::adjustPos( int offset )
       
   817 {
       
   818     int newPos = mMidScrollPos;
       
   819     const int threshold = (int)size().width() / 5;
       
   820     int newIndex = mCurrentIndex;
       
   821     bool needsToScroll = false;
       
   822 
       
   823     if ( isScrollingAllowed() && abs( offset ) >= threshold ) {
       
   824         needsToScroll = true;
       
   825         if ( offset > 0 ) {
       
   826             newPos = 0;
       
   827             mScrollDirection = Scroll::Right;
       
   828             if ( !mIsCustomFreq ) {
       
   829 
       
   830                 if ( mAlternateSkipping ) { //TODO: Remove this! This is test code
       
   831                     const uint newFreq = mModel->findClosest( mItems[CenterItem]->frequency(), StationSkip::PreviousFavorite ).frequency();
       
   832                     if ( newFreq > 0 ) {
       
   833                         newIndex = mModel->indexFromFrequency( newFreq );
       
   834                     } else {
       
   835                         needsToScroll = false;
       
   836                         newPos = mMidScrollPos;
       
   837                     } // End test code
       
   838 
       
   839                 } else {
       
   840                     --newIndex;
       
   841                 }
       
   842             }
       
   843         } else {
       
   844             mScrollDirection = Scroll::Left;
       
   845             newPos = mMaxScrollPos;
       
   846 
       
   847             if ( mAlternateSkipping ) { //TODO: Remove this! This is test code
       
   848                 const uint newFreq = mModel->findClosest( mItems[CenterItem]->frequency(), StationSkip::NextFavorite ).frequency();
       
   849                 if ( newFreq > 0 ) {
       
   850                     newIndex = mModel->indexFromFrequency( newFreq );
       
   851                 } else {
       
   852                     needsToScroll = false;
       
   853                     newPos = mMidScrollPos;
       
   854                 } // End test code
       
   855 
       
   856             } else {
       
   857                 ++newIndex;
       
   858             }
       
   859         }
       
   860     }
       
   861 
       
   862     newIndex = trimIndex( newIndex );
       
   863     if ( needsToScroll ) {
       
   864         const uint frequency = mModel->stationAt( newIndex ).frequency();
       
   865         emit frequencyChanged( frequency, TuneReason::StationCarousel, mScrollDirection );
       
   866         scrollToIndex( newIndex, mScrollDirection, RadioStationCarousel::FromPanGesture );
       
   867         mIsCustomFreq = false;
       
   868     } else {
       
   869         scrollContentsTo( QPointF( -newPos, 0 ), 300 );
       
   870     }
       
   871 }
       
   872 
       
   873 /*!
       
   874  *
       
   875  */
       
   876 int RadioStationCarousel::trimIndex( int index )
       
   877 {
       
   878     const int count = mModel ? mModel->rowCount() : 0;
       
   879 
       
   880     if ( count == 0 ) {
       
   881         return -1;
       
   882     }
       
   883 
       
   884     if ( index < 0 ) {
       
   885         index = count - 1;
       
   886     }
       
   887     index %= count;
       
   888     return index;
       
   889 }
       
   890 
       
   891 /*!
       
   892  *
       
   893  */
       
   894 int RadioStationCarousel::prevIndex( int index )
       
   895 {
       
   896     if ( !mIsCustomFreq ) {
       
   897         --index;
       
   898     }
       
   899     return trimIndex( index );
       
   900 }
       
   901 
       
   902 /*!
       
   903  *
       
   904  */
       
   905 int RadioStationCarousel::nextIndex( int index )
       
   906 {
       
   907     return trimIndex( index + 1 );
   755 }
   908 }
   756 
   909 
   757 /*!
   910 /*!
   758  *
   911  *
   759  */
   912  */
   760 void RadioStationCarousel::skip( StationSkip::Mode mode )
   913 void RadioStationCarousel::skip( StationSkip::Mode mode )
   761 {
   914 {
   762     RadioStationItem* item = currentStationItem();
   915     if ( mModel ) {
   763     if ( item ) {
   916         const uint frequency = mModel->findClosest( mItems[CenterItem]->frequency(), mode ).frequency();
   764         RadioCarouselModel* model = carouselModel();
   917         const int index = mModel->indexFromFrequency( frequency );
   765         const uint frequency = model->findClosest( item->frequency(), mode ).frequency();
   918         const Scroll::Direction direction = RadioUtil::scrollDirectionFromSkipMode( mode );
   766         const QModelIndex& index = model->modelIndexFromFrequency( frequency );
   919         scrollToIndex( index, direction, RadioStationCarousel::NoSignal );
   767         scrollToIndex( index, RadioStationCarousel::NoSignal );
   920     }
   768     }
   921 }
   769 }