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