radioapp/radiowidgets/src/radiomainview.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 31 Aug 2010 15:15:02 +0300
branchRCL_3
changeset 19 cce62ebc198e
permissions -rw-r--r--
Revision: 201031 Kit: 201035

/*
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/

// System includes
#include <QTimer>
#include <HbPushButton>
#include <HbAction>
#include <HbMenu>
#include <HbApplication>
#include <HbActivityManager>
#include <QPixmap>
#include <HbLabel>
#include <HbFrameItem>          // Temporarily here until docml supports frame items

// User includes
#include "radiowindow.h"
#include "radiomainview.h"
#include "radiofrequencystrip.h"
#include "radiouiengine.h"
#include "radiologger.h"
#include "radiostationcarousel.h"
#include "radiouiloader.h"
#include "radioutil.h"
#include "radiostationmodel.h"
#include "radiofrequencyscanner.h"

// Constants
const QLatin1String RADIO_MAINVIEW_ACTIVITY_ID( "FMRadioMainView" );

/*!
 * Temporary convenience function to set frame background until DOCML supports frame items
 */
static void initFrameBackground( RadioUiLoader& uiLoader,
                                 const QString backgroundName,
                                 HbFrameDrawer::FrameType frameType )
{
    if ( HbLabel* backgroundLabel = uiLoader.findObject<HbLabel>( backgroundName ) ) {
        QString backgroundName = backgroundLabel->icon().iconName();
        HbFrameItem* frameItem = new HbFrameItem( backgroundName, frameType, backgroundLabel );
        backgroundLabel->setBackgroundItem( frameItem );
    }
}


/*!
 *
 */
RadioMainView::RadioMainView() :
    RadioViewBase( false ),
    mCarousel( NULL ),
    mFrequencyStrip( NULL ),
    mSkippingAction( NULL ),
    mAlternateSkipping( false )
{
}

/*!
 *
 */
RadioMainView::~RadioMainView()
{
}

/*!
 * \reimp
 *
 */
void RadioMainView::setScanningMode( bool scanning )
{
    if ( scanning ) {
        loadSection( DOCML::FILE_MAINVIEW, DOCML::MV_SECTION_SCANNING );
    } else {
        loadSection( DOCML::FILE_MAINVIEW, DOCML::MV_SECTION_NORMAL );
        updateFavoriteButton();
        mFrequencyScanner.take();

        const bool firsTimeStart = mUiEngine->isFirstTimeStart();
        const int rowCount = mUiEngine->stationModel().rowCount();
        if ( firsTimeStart && rowCount != 0 ) {
            mUiEngine->setFirstTimeStartPerformed( true );
        }
    }
}

/*!
 * \reimp
 *
 */
void RadioMainView::preLazyLoadInit()
{
    initFrameBackground( *mUiLoader, DOCML::MV_NAME_FREQUENCY_BACKGROUND, HbFrameDrawer::NinePieces );

    initFrameBackground( *mUiLoader, DOCML::MV_NAME_CAROUSEL_BACKGROUND, HbFrameDrawer::NinePieces );
}

/*!
 * \reimp
 *
 */
void RadioMainView::init()
{
    LOG_METHOD;
    loadSection( DOCML::FILE_MAINVIEW, DOCML::SECTION_LAZY_LOAD );
    initFrameBackground( *mUiLoader, DOCML::MV_NAME_CAROUSEL_OVERLAY, HbFrameDrawer::NinePieces );

    mCarousel = mUiLoader->findObject<RadioStationCarousel>( DOCML::MV_NAME_STATION_CAROUSEL );
    mCarousel->init( *mUiLoader, mUiEngine.data() );
    mCarousel->setLandscape( mMainWindow->orientation() == Qt::Horizontal );

    mFrequencyStrip = mUiLoader->findObject<RadioFrequencyStrip>( DOCML::MV_NAME_FREQUENCY_STRIP );
    mFrequencyStrip->init( mUiEngine.data(), *mUiLoader );

    RadioStationModel* stationModel = &mUiEngine->stationModel();

    Radio::connect( mFrequencyStrip,            SIGNAL(frequencyChanged(uint,int,int)),
                    this,                       SLOT(setFrequencyFromWidget(uint,int,int)) );
    Radio::connect( mCarousel,                  SIGNAL(frequencyChanged(uint,int,int)),
                    this,                       SLOT(setFrequencyFromWidget(uint,int,int)) );
    Radio::connect( mUiEngine.data(),           SIGNAL(tunedToFrequency(uint,int)),
                    this,                       SLOT(setFrequencyFromEngine(uint,int)) );
    Radio::connect( mFrequencyStrip,            SIGNAL(manualSeekChanged(bool)),
                    this,                       SLOT(setManualSeekMode(bool)) );

    Radio::connect( mFrequencyStrip,            SIGNAL(skipRequested(int)),
                    this,                       SLOT(skip(int)) );
    Radio::connect( mCarousel,                  SIGNAL(skipRequested(int)),
                    this,                       SLOT(skip(int)) );
    Radio::connect( mFrequencyStrip,            SIGNAL(seekRequested(int)),
                    mUiEngine.data(),           SLOT(seekStation(int)) );

    Radio::connect( mUiEngine.data(),           SIGNAL(seekingStarted(int)),
                    this,                       SLOT(seekingStarted()) );
    Radio::connect( mUiEngine.data(),           SIGNAL(antennaStatusChanged(bool)),
                    this,                       SLOT(updateAntennaStatus(bool)) );
    Radio::connect( mUiEngine.data(),           SIGNAL(audioRouteChanged(bool)),
                    this,                       SLOT(updateAudioRoute(bool)) );

    Radio::connect( stationModel,               SIGNAL(favoriteChanged(RadioStation)),
                    this,                       SLOT(handleFavoriteChange(RadioStation)) );

    connectXmlElement( DOCML::MV_NAME_STATIONS_BUTTON,  SIGNAL(clicked()),
                       mMainWindow,                     SLOT(activateStationsView()) );

    connectXmlElement( DOCML::MV_NAME_FAVORITE_BUTTON,  SIGNAL(clicked()),
                       this,                            SLOT(toggleFavorite()) );

    connectXmlElement( DOCML::MV_NAME_SPEAKER_BUTTON,   SIGNAL(clicked()),
                       mUiEngine.data(),                SLOT(toggleAudioRoute()) );

    connectXmlElement( DOCML::MV_NAME_SCAN_ACTION,      SIGNAL(triggered()),
                       this,                            SLOT(toggleScanning()) );

    updateFavoriteButton();

    connectCommonMenuItem( MenuItem::Exit );

    // "Play history" menu item
    connectViewChangeMenuItem( DOCML::MV_NAME_HISTORYVIEW_ACTION, SLOT(activateHistoryView()) );

    updateAudioRoute( mUiEngine->isUsingLoudspeaker() );

    // Add "back" navigation action to put the application to background
    HbAction* backAction = new HbAction( Hb::BackNaviAction, this );
#ifdef BUILD_WIN32
    Radio::connect( backAction,     SIGNAL(triggered()),
                    this,           SLOT(quit()) );
#else
    Radio::connect( backAction,     SIGNAL(triggered()),
                    mMainWindow,    SLOT(lower()) );
#endif // BUILD_WIN32
    setNavigationAction( backAction );

    const bool firsTimeStart = mUiEngine->isFirstTimeStart();
    const int rowCount = mUiEngine->stationModel().rowCount();

   if ( firsTimeStart && rowCount == 0 ){
            QTimer::singleShot( 4500, this, SLOT(startFirstTimeScanning()) );
        }


    Radio::connect( static_cast<HbApplication*>( qApp ),    SIGNAL(aboutToQuit()),
                    this,                                   SLOT(saveActivity()) );

    emit applicationReady();
}

/*!
 * \reimp
 *
 */
void RadioMainView::setOrientation()
{
    loadSection( DOCML::FILE_MAINVIEW, mMainWindow->orientationSection() );
    if ( mCarousel && mFrequencyStrip ) {
        mCarousel->setFrequency( mFrequencyStrip->frequency(), TuneReason::Unspecified );
        mCarousel->setLandscape( mMainWindow->orientation() == Qt::Horizontal );
    }
}

/*!
 * \reimp
 *
 */
void RadioMainView::userAccepted()
{
    mFrequencyScanner.reset( new RadioFrequencyScanner( *mUiEngine, this ) );
    mFrequencyScanner->startScanning();
}

/*!
 * \reimp
 *
 */
bool RadioMainView::eventFilter( QObject* watched, QEvent* event )
{
    if ( event->type() == QEvent::ApplicationDeactivate ) {
        mFrequencyStrip->cancelManualSeek();
    }

    return RadioViewBase::eventFilter( watched, event );
}

/*!
 * Private slot
 */
void RadioMainView::setFrequencyFromWidget( uint frequency, int reason, int direction )
{
//    LOG_FORMAT( "RadioMainView::setFrequencyFromWidget: %u, reason = %d", frequency, reason );
    if ( !RadioUtil::isScannerAlive() ) {
        if ( reason == TuneReason::FrequencyStrip ) {
//            mCarousel->setFrequency( frequency, reason, direction );
//            mUiEngine->tuneWithDelay( frequency, reason );
        } else if ( reason == TuneReason::ManualSeekUpdate ) {
            mCarousel->setFrequency( frequency, reason, RadioUtil::scrollDirection( direction ) );
        } else if ( reason == TuneReason::ManualSeekTune ) {
            LOG_FORMAT( "--------Manual seek tune: %u", frequency );
            mUiEngine->setFrequency( frequency, reason );
        } else if ( reason == TuneReason::StationCarousel ) {
            mFrequencyStrip->setFrequency( frequency, reason, RadioUtil::scrollDirection( direction ) );
            mUiEngine->setFrequency( frequency, reason );
        }
    }
}

/*!
 * Private slot
 */
void RadioMainView::setFrequencyFromEngine( uint frequency, int reason )
{
    LOG_FORMAT( "RadioMainView::setFrequencyFromEngine reason: %d", reason );
    if ( RadioUtil::scanStatus() != Scan::ScanningInMainView && !mFrequencyStrip->isInManualSeekMode() ) {
        mCarousel->clearInfoText();
        updateFavoriteButton();
        if ( reason != TuneReason::FrequencyStrip &&
             reason != TuneReason::StationCarousel &&
             reason != TuneReason::Skip ) {
            mCarousel->setFrequency( frequency, reason, Scroll::Shortest );
            mFrequencyStrip->setFrequency( frequency, reason, Scroll::Shortest );
        }
    }
}

/*!
 * Private slot
 */
void RadioMainView::skip( int skipMode )
{
//    if ( !mAlternateSkipping && ( skipMode == StationSkip::PreviousFavorite || skipMode == StationSkip::NextFavorite ) &&
//        mUiEngine->stationModel().favoriteCount() == 0 ) {
//        mCarousel->setInfoText( CarouselInfoText::NoFavorites );
//    } else {
        const uint currentFrequency = mFrequencyStrip->frequency();
        RadioStation station;
        mUiEngine->stationModel().findFrequency( currentFrequency, station );

        if ( mAlternateSkipping ) { //TODO: Remove. Temporary test code
            if ( sender() == mFrequencyStrip ) {
                if ( skipMode == StationSkip::NextFavorite ) {
                    skipMode = StationSkip::Next;
                } else if ( skipMode == StationSkip::PreviousFavorite ) {
                    skipMode = StationSkip::Previous;
                }
            } else if ( sender() == mCarousel ) {
                if ( skipMode == StationSkip::Next ) {
                    skipMode = StationSkip::NextFavorite;
                } else if ( skipMode == StationSkip::Previous ) {
                    skipMode = StationSkip::PreviousFavorite;
                }
            }
        }

        const uint frequency = mUiEngine->skipStation( static_cast<StationSkip::Mode>( skipMode ),
                                                                currentFrequency);

        if ( currentFrequency != frequency || station.isFavorite() ) {
            const Scroll::Direction direction = RadioUtil::scrollDirectionFromSkipMode( skipMode );
            mCarousel->setFrequency( frequency, TuneReason::Skip, direction );
            mFrequencyStrip->setFrequency( frequency, TuneReason::Skip, direction );
        }
//    }
}

/*!
 * Private slot
 */
void RadioMainView::openStationsView()
{
    mFrequencyStrip->cancelManualSeek();
    mMainWindow->activateStationsView();
}

/*!
 * Private slot
 */
void RadioMainView::startFirstTimeScanning()
{
    if ( mUiEngine->isAntennaAttached() ){
        QTimer::singleShot( 100, this, SLOT(toggleScanning()) );
    }
}

/*!
 * Private slot
 */
void RadioMainView::toggleScanning()
{
    mFrequencyStrip->cancelManualSeek();
    if ( mFrequencyScanner ) {
        mFrequencyScanner->cancelScanning();
    } else {
        const int rowCount =  mUiEngine->stationModel().rowCount();
        if ( rowCount > 0 ) {
            askQuestion( hbTrId( "txt_rad_info_all_stations_in_stations_list_will_be" ) );
        } else {
            userAccepted();
        }
    }
}

/*!
 * Private slot
 */
void RadioMainView::toggleFavorite()
{
    if ( RadioUtil::isScannerAlive() ) {
        toggleScanning();
    } else {
        mUiEngine->stationModel().setData( QModelIndex(), mFrequencyStrip->frequency(), RadioRole::ToggleFavoriteRole );
    }
}

/*!
 * Private slot
 */
void RadioMainView::seekingStarted()
{
    if ( !RadioUtil::isScannerAlive() ) {
        mCarousel->setInfoText( CarouselInfoText::Seeking );
    }
}

/*!
 * Private slot
 */
void RadioMainView::updateAntennaStatus( bool connected )
{
    if ( !connected ) {
        mFrequencyStrip->cancelManualSeek();
    }

    HbAction* scanAction = mUiLoader->findObject<HbAction>( DOCML::MV_NAME_SCAN_ACTION );
    scanAction->setEnabled( connected );
    mCarousel->updateAntennaStatus( connected );
    const bool firsTimeStart = mUiEngine->isFirstTimeStart();
    const int rowCount = mUiEngine->stationModel().rowCount();
    if ( firsTimeStart && rowCount == 0 && connected ){
            QTimer::singleShot( 100, this, SLOT(toggleScanning()) );
        }
}

/*!
 * Private slot
 */
void RadioMainView::updateAudioRoute( bool loudspeaker )
{
    HbPushButton* loudspeakerButton = mUiLoader->findWidget<HbPushButton>( DOCML::MV_NAME_SPEAKER_BUTTON );
    if ( loudspeaker ) {
        loudspeakerButton->setIcon( HbIcon( "qtg_mono_speaker_off" ) );
        loudspeakerButton->setText( hbTrId( "txt_rad_button_deactivate_loudspeaker" ) );
    } else {
        loudspeakerButton->setIcon( HbIcon( "qtg_mono_speaker" ) );
        loudspeakerButton->setText( hbTrId( "txt_rad_button_activate_loudspeaker" ) );
    }
}

/*!
 * Private slot
 */
void RadioMainView::setManualSeekMode( bool manualSeekActive )
{
    if ( manualSeekActive ) {
        qApp->installEventFilter( this );

        mUiLoader->findWidget<HbPushButton>( DOCML::MV_NAME_FAVORITE_BUTTON )->setText( hbTrId( "txt_rad_button_add_to_favourites" ) );
    } else {
        qApp->removeEventFilter( this );

        updateFavoriteButton();
    }

    mUiEngine->setManualSeekMode( manualSeekActive );

    mCarousel->setManualSeekMode( manualSeekActive );
}

/*!
 * Private slot
 */
void RadioMainView::handleFavoriteChange( const RadioStation& station )
{
    mFrequencyStrip->updateFavorite( station.frequency() );
    updateFavoriteButton();
}

/*!
 * Private slot
 */
void RadioMainView::saveActivity()
{
    HbActivityManager* activityManager = qobject_cast<HbApplication*>(qApp)->activityManager();

    // Get a screenshot for saving to the activity manager
    QSize screenShotSize = mCarousel->size().toSize();
    QPixmap screenShot( screenShotSize );
    QPainter painter( &screenShot );

    // Draw the background and overlay
    HbLabel* backgroundLabel = mUiLoader->findWidget<HbLabel>( DOCML::MV_NAME_CAROUSEL_BACKGROUND );
    painter.drawPixmap( 0, 0, backgroundLabel->icon().pixmap().scaled( screenShotSize ) );
    backgroundLabel = mUiLoader->findWidget<HbLabel>( DOCML::MV_NAME_CAROUSEL_OVERLAY );
    painter.drawPixmap( 0, 0, backgroundLabel->icon().pixmap().scaled( screenShotSize ) );

    mCarousel->drawOffScreen( painter );

    QVariantHash metadata;
    metadata.insert( "screenshot", screenShot );

    #ifdef __WINS__
        screenShot.save( "c:\\radio.bmp" );
    #elif defined BUILD_WIN32
        screenShot.save( "radio.bmp" );
    #endif

    // Update the activity to the activity manager
    bool ok = activityManager->removeActivity( RADIO_MAINVIEW_ACTIVITY_ID );
    LOG_ASSERT( ok, LOG( "Failed to remove old activity from Activity Manager!" ) );
    ok = activityManager->addActivity( RADIO_MAINVIEW_ACTIVITY_ID, QVariant(), metadata );
    LOG_ASSERT( ok, LOG( "Failed to update activity to Activity Manager!" ) );
}

/*!
 *
 */
void RadioMainView::updateFavoriteButton()
{
    RadioStation station;
    RadioStationModel& model = mUiEngine->stationModel();
    model.findFrequency( mUiEngine->currentFrequency(), station );
    HbPushButton* favoriteButton = mUiLoader->findWidget<HbPushButton>( DOCML::MV_NAME_FAVORITE_BUTTON );
    if ( station.isFavorite() ) {
        favoriteButton->setText( hbTrId( "txt_fmradio_button_remove_from_favourites" ) );
        favoriteButton->setIcon( HbIcon( "qtg_mono_favourites_remove" ) );
    } else {
        favoriteButton->setText( hbTrId( "txt_rad_button_add_to_favourites" ) );
        favoriteButton->setIcon( HbIcon( "qtg_mono_add_to_favourites" ) );
    }
}