app/src/mpmainwindow.cpp
author hgs
Fri, 09 Jul 2010 16:27:03 -0500
changeset 43 0f32e550d9d8
parent 38 b93f525c9244
child 45 612c4815aebe
permissions -rw-r--r--
201027

/*
* 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: MpMainWindow implementation.
*
*/


#include <hbapplication.h>
#include <hbactivitymanager.h>
#include <hbview.h>
#include <mpxviewpluginqt.h>
#include <xqpluginloader.h>
#include <xqplugininfo.h>
#include <xqserviceutil.h>
#include <xqsharablefile.h>

#include "mpmainwindow.h"
#include "mpviewbase.h"
#include "musicservices.h"
#include "mpenginefactory.h"
#include "mpsettingsmanager.h"
#include "mpglobalpopuphandler.h"
#include "mptrace.h"

const QString MUSIC_MAIN_VIEW = "MusicMainView";
const QString MUSIC_NOW_PLAYING_VIEW = "MusicNowPlayingView";

/*!
   \class MpMainWindow
   \brief The MpMainWindow class provides Main Window functionalities.

   MpMainWindow handles activation of views

*/

/*!
    Constructs the main winsdow.
 */

MpMainWindow::MpMainWindow()
    : MpxViewFramework(),
      mCollectionViewPlugin(0),
      mPlaybackViewPlugin(0),
      mSettingsViewPlugin(0),
      mDetailsViewPlugin(0),
      mMediaWallViewPlugin(0),
      mCurrentViewPlugin(0),
      mVerticalViewType( CollectionView ),
      mMusicServices(0),
      mPopupHandler(0),
      mUserExit( false ),
      mActivityManager(0)
{
    TX_LOG
}

/*!
 Destructs the main window.
 */
MpMainWindow::~MpMainWindow()
{
    TX_ENTRY
    if(mMusicServices){
        delete mMusicServices;
    }
    
    if (mCollectionViewPlugin) {
        mCollectionViewPlugin->destroyView();
        delete mCollectionViewPlugin;
    }
    if (mPlaybackViewPlugin) {
        mPlaybackViewPlugin->destroyView();
        delete mPlaybackViewPlugin;
    }
    if (mSettingsViewPlugin) {
        mSettingsViewPlugin->destroyView();
        delete mSettingsViewPlugin;
    }
    if (mDetailsViewPlugin) {
        mDetailsViewPlugin->destroyView();
        delete mDetailsViewPlugin;
    }
    if (mMediaWallViewPlugin) {
        mMediaWallViewPlugin->destroyView();
        delete mMediaWallViewPlugin;
    }    
    MpEngineFactory::close();


    TX_EXIT
}


/*!
Initialize and activate the collection view
 */
void MpMainWindow::initialize( ActivityMode mode )
{
    TX_ENTRY

#ifdef _DEBUG
    QList<XQPluginInfo> impls;
    XQPluginLoader::listImplementations("org.nokia.mmdt.MpxViewPlugin/1.0", impls);
    TX_LOG_ARGS("Available plugins:");
    for ( int i = 0; i < impls.size(); i++ ) {
        TX_LOG_ARGS("Plugin " << i << ": " << impls[i].uid() << ", " << impls[i].dllName() );
    }
#endif // _DEBUG

    if ( XQServiceUtil::isService() ) {
        // Music Service mode
        // Set the Collection View and Playback View to fetcher mode
        mMusicServices = new MusicServices();
        int err = connect(mMusicServices, SIGNAL(serviceActive( TUid )), this, SLOT(initializeServiceView( TUid )));
        TX_LOG_ARGS("connection error: " << err);
        XQServiceUtil::toBackground( false );
    }

    if ( !mMusicServices ) {
        HbApplication* app = qobject_cast<HbApplication*>(qApp);
        QVariantHash params = app->activateParams();
        MpEngineFactory::createSharedEngine();
        mPopupHandler = new MpGlobalPopupHandler( this );
        if( app->activateReason() == Hb::ActivationReasonActivity ) {
            // Restoring an activity, not a fresh startup or a service
            // Activities from Task switcher only have one parameter
            if( params.count() == 1 ) {
                 loadActivity( app->activateData() );
            }
        }
        if ( orientation() == Qt::Vertical ) {
            // If first startup ignore shuffleAll and send to collection view to refresh library
            if ( mode == MusicMainView  || MpSettingsManager::firstStartup() ) {
                loadView( CollectionView );
                activateView( CollectionView );
                loadView( MediaWallView );
                loadView( PlaybackView );
            } else if ( mode == MusicNowPlayingView ) {
                if( params.contains( "shuffle" ) ) {
                    if( !params.value( "shuffle" ).toString().compare( "yes" ) ) {
                        MpEngineFactory::sharedEngine()->shuffleAll();
                    }
                }
                loadView( PlaybackView );
                activateView( PlaybackView );
                loadView( CollectionView );
                loadView( MediaWallView );
            }
        }
        else {
            // If first startup ignore shuffleAll and send to refresh library
            if( mode == MusicNowPlayingView && !MpSettingsManager::firstStartup() ) {
                if( params.contains( "shuffle" ) ) {
                    if( !params.value( "shuffle" ).toString().compare( "yes" ) ) {
                        MpEngineFactory::sharedEngine()->shuffleAll();
                    }
                }
                mVerticalViewType = PlaybackView;
            }
            loadView( MediaWallView );
            activateView( MediaWallView );
            loadView( CollectionView );
            loadView( PlaybackView );
        }
        connect(this, SIGNAL( orientationChanged( Qt::Orientation ) ), SLOT( switchView( Qt::Orientation ) ) );
        connect( MpEngineFactory::sharedEngine(), SIGNAL( libraryUpdated() ), SLOT( handleLibraryUpdated() ) );
        MpEngineFactory::sharedEngine()->checkForSystemEvents();
        //Register to application manager to wait for activities and clear previous activities on the task switcher
        mActivityManager = qobject_cast<HbApplication*>(qApp)->activityManager();
        mActivityManager->waitActivity();
        mActivityManager->removeActivity( MUSIC_MAIN_VIEW );
        mActivityManager->removeActivity( MUSIC_NOW_PLAYING_VIEW );
        connect( app, SIGNAL( activate() ), this , SLOT( handleActivity() ) );
        connect( app, SIGNAL( aboutToQuit() ), this, SLOT( saveActivity() ) );
        emit applicationReady();
        
    }
    else {
        setOrientation(Qt::Vertical, true);//This sould prevent media wall activation.
    }
    //since we only have one landscape view, media wall, disable automatic 
    //orientation transitions, they look like a flicker.
    //This will make the view switch faster.
    setAutomaticOrientationEffectEnabled( false );    
    TX_EXIT
}

/*!
 Slot to be called to handle the \a commandCode.
 */
void MpMainWindow::handleCommand( int commandCode )
{
    TX_ENTRY_ARGS("commandCode=" << commandCode );
    
    switch ( commandCode ) {
        case MpCommon::Exit:
            if ( mCurrentViewPlugin ) {
                disconnectView();
            }
            mUserExit = true;
            qApp->quit();
            break;
        case MpCommon::SendToBackground:
            lower();
            break;
        case MpCommon::ActivateCollectionView:
            activateView(CollectionView);
            break;
        case MpCommon::ActivatePlaybackView:
            activateView(PlaybackView);
            break;
        case MpCommon::ActivateSettingsView:
            activateView(SettingsView);
            break;
        case MpCommon::ActivateDetailsView:
            activateView(DetailsView);
            break;
        case MpCommon::ActivatePreviousView:
            activateView(mVerticalViewType);
            break;
    }
    TX_EXIT
}

/*!
 Slot to be called to switch view based on \a orientation.
 */
void MpMainWindow::switchView( Qt::Orientation orientation )
{
        if (orientation == Qt::Vertical) {
            activateView( mVerticalViewType );   
        }
        else {
            activateView(MediaWallView);
        }
}

/*!
 Activate the \a viewType view.
 */
void MpMainWindow::activateView(MpMainWindow::ViewType viewType)
{
    TX_ENTRY_ARGS("viewType=" << viewType );

    bool doTransition = true;
    Hb::ViewSwitchFlags  transitionFlags = Hb::ViewSwitchDefault;
    
    if ( mCurrentViewPlugin ) {     
        disconnectView();
        mCurrentViewPlugin->deactivateView();
        if ( viewType  == MediaWallView || mCurrentViewPlugin == mMediaWallViewPlugin ) {
            doTransition = false;
        }
        else if ( viewType  == CollectionView && mCurrentViewPlugin == mPlaybackViewPlugin ||
                  viewType  == PlaybackView && mCurrentViewPlugin == mDetailsViewPlugin ||
                  viewType  == PlaybackView && mCurrentViewPlugin == mSettingsViewPlugin ) {
            transitionFlags |= Hb::ViewSwitchUseBackAnim;
        }
        mCurrentViewPlugin = 0;
    }

    // loadView will not reload the view if is already loaded.
    mCurrentViewPlugin = loadView( viewType );
    Q_ASSERT( mCurrentViewPlugin );

    if ( mCurrentViewPlugin ) {
        if ( viewType != MediaWallView && viewType != DetailsView ) {
            mVerticalViewType = viewType;
        }
        addView( reinterpret_cast<HbView*>( mCurrentViewPlugin->getView() ) );
        setCurrentView( reinterpret_cast<HbView*>( mCurrentViewPlugin->getView() ) , doTransition , transitionFlags);
        mCurrentViewPlugin->activateView();
        connectView();
    }
    TX_EXIT
}


/*!
 Connect the signals to the current active view.
 */
void MpMainWindow::connectView()
{
    TX_ENTRY

	QObject::connect(mCurrentViewPlugin,
					 SIGNAL(command(int)),
					 this,
					 SLOT(handleCommand(int)));
    TX_EXIT
}

/*!
 Disonnect the signals from the current active view.
 */
void MpMainWindow::disconnectView()
{
    TX_ENTRY

	QObject::disconnect(mCurrentViewPlugin,
					 SIGNAL(command(int)),
					 this,
					 SLOT(handleCommand(int)));
    TX_EXIT
}

/*!
 Slot to be called when Library has changed.
 */
void MpMainWindow::handleLibraryUpdated()
{
    TX_ENTRY

    // If library changed while playing back, always return to AllSongs collection view.
    if ( mPlaybackViewPlugin &&
         mCurrentViewPlugin == mPlaybackViewPlugin &&
         mCollectionViewPlugin ) {

        activateView( CollectionView );
        MpViewBase* collectionView = reinterpret_cast<MpViewBase*>(mCollectionViewPlugin->getView());
        collectionView->setDefaultView();
    }

    TX_EXIT
}

/*!
 Reimp.
 */
void 	MpMainWindow::keyPressEvent(QKeyEvent *event)
{
    switch(event->key()) {
    case 16842753:
    case Qt::Key_Call:
        if (orientation () == Qt::Vertical) {
            setOrientation(Qt::Horizontal, false);
        }
        else {
            setOrientation(Qt::Vertical, false);
        }
        break;
    default:
        HbMainWindow::keyPressEvent (event);
        break;          
    }
}

/*!
  Slot to initialize the view that corresponds to the requested service  
 */
void MpMainWindow::initializeServiceView( TUid hostUid )
{
    switch (mMusicServices->currentService()) {
 
    case MusicServices::EUriFetcher:
        {
            MpEngineFactory::createSharedEngine( hostUid , MpEngine::Fetch );
            mPopupHandler = new MpGlobalPopupHandler( this );
            loadView( CollectionView, MpCommon::FetchView );
            MpViewBase* collectionView = reinterpret_cast<MpViewBase*>(mCollectionViewPlugin->getView());
            connect(collectionView, SIGNAL(songSelected(QString)), mMusicServices, SLOT(itemSelected(QString)));
            activateView( CollectionView );           
            loadView(PlaybackView, MpCommon::FetchView );
            MpViewBase* playbackView = reinterpret_cast<MpViewBase*>(mPlaybackViewPlugin->getView());
            connect(playbackView, SIGNAL(songSelected(QString)), mMusicServices, SLOT(itemSelected(QString)));
            connect( MpEngineFactory::sharedEngine(), SIGNAL( libraryUpdated() ), this, SLOT( handleLibraryUpdated() ) );
            MpEngineFactory::sharedEngine()->checkForSystemEvents();
            break;
        }
    case MusicServices::EPlayback:
        {
            MpEngineFactory::createSharedEngine( hostUid , MpEngine::Embedded );
            loadView(PlaybackView, MpCommon::EmbeddedView );   
            MpViewBase* playbackView = reinterpret_cast<MpViewBase*>(mPlaybackViewPlugin->getView());
            connect(mMusicServices, SIGNAL(playReady(QString)), MpEngineFactory::sharedEngine(), SLOT(playEmbedded(QString)));
            connect(mMusicServices, SIGNAL(playReady(const XQSharableFile&)), MpEngineFactory::sharedEngine(), SLOT(playEmbedded(const XQSharableFile&)));
            connect(playbackView, SIGNAL(songSelected(QString)), mMusicServices, SLOT(itemSelected(QString)));
            activateView( PlaybackView );
            break;
        }
    default:
        Q_ASSERT_X(false, "MpMainWindow::initializeServiceView", "undefined service");
        break;
    }
    emit applicationReady();
}

/*!
  Slot to handle activity switching once the stand alone instance is running and registered 
  in the activity manager to wait for activities.
  Only running activity supported at the moment is "MusicNowPlayingView"
 */
void MpMainWindow::handleActivity()
{
    TX_ENTRY
    HbApplication* app = qobject_cast<HbApplication*>(qApp);
    QString activityId = app->activateId();
    
    if( !activityId.compare( MUSIC_NOW_PLAYING_VIEW ) ) {
        if ( orientation() == Qt::Vertical ) {
            if( mVerticalViewType != PlaybackView ) {
                activateView( PlaybackView );
            }
        }
    }
    
    mActivityManager->waitActivity();
    TX_EXIT
}

/*!
  Slot to save activity upon exiting application
 */
void MpMainWindow::saveActivity()
{
    TX_ENTRY
    QString activity = ( mVerticalViewType == CollectionView ) ? MUSIC_MAIN_VIEW : MUSIC_NOW_PLAYING_VIEW;
    //Get data from engine
    QByteArray serializedRestorePath;
    if ( mUserExit ) {
        //Internal exit will always return to the main view
        activity = MUSIC_MAIN_VIEW;
    }
    else {
        //Only saved data if exited via task switcher or GOOM
        MpEngineFactory::sharedEngine()->saveActivityData( serializedRestorePath );
    }
    QVariantHash activityParameters;
    activityParameters.insert( "screenshot", QPixmap::grabWidget( this, this->rect() ) );
    QVariantHash activityData;
    activityData.insert( "restorePath", serializedRestorePath );
       
    
    bool ok = mActivityManager->addActivity( activity , activityData, activityParameters );
    if ( !ok ){
        TX_LOG_ARGS( "Error: Add Failed; should never get here." );
    }
    TX_EXIT
}

/*!
  Slot to handle a failed path restoration. Switch to collection view if not already there.
 */
void MpMainWindow::handleRestorePathFailed()
{
    TX_ENTRY
    if ( orientation() == Qt::Vertical ) {
        if( mVerticalViewType != CollectionView ) {
            activateView( CollectionView );
        }
    }
    TX_EXIT
}

/*!
  loads a view if type \a  type, return the view plugin, if view is already loaded it will not reload the view.
 */
MpxViewPlugin* MpMainWindow::loadView( ViewType type, MpCommon::MpViewMode viewMode )
{
    MpxViewPlugin** plugin = 0;
    long int pluginUid = 0;    
    switch (type) { 
    case CollectionView:
        pluginUid = MpCommon::KCollectionViewUid;
        plugin = &mCollectionViewPlugin;
        break;
    case PlaybackView:
        pluginUid = MpCommon::KPlaybackViewUid;
        plugin = &mPlaybackViewPlugin;
        break;
    case SettingsView:
        pluginUid = MpCommon::KSettingsViewUid;
        plugin = &mSettingsViewPlugin;
        break;
    case DetailsView:
        pluginUid = MpCommon::KDetailsViewUid;
        plugin = &mDetailsViewPlugin;
        break;
    case MediaWallView:
        pluginUid = MpCommon::KMediaWallViewUid;
        plugin = &mMediaWallViewPlugin;
        break;
    default:
        Q_ASSERT_X(false, "MpMainWindow::loadView", "undefined view type");
        break;
    }
    Q_ASSERT( plugin && pluginUid);
    if ( plugin && !(*plugin) ) {
        //plugin was not loded before, loding plugin.
        XQPluginLoader pluginLoader( pluginUid );
        QObject* pluginInstance = pluginLoader.instance();
        (*plugin) = qobject_cast<MpxViewPlugin*>( pluginInstance )->viewPlugin();
        Q_ASSERT( *plugin );
        
        if ( *plugin ) {
            (*plugin)->createView();
            MpViewBase* view = reinterpret_cast<MpViewBase*>( (*plugin)->getView() );
            view->setTitle( mMusicServices ? mMusicServices->contextTitle() : hbTrId("txt_mus_title_music"));
            view->setViewMode( viewMode );
        }
    }
    Q_ASSERT( plugin ? *plugin : 0 );
    return plugin ? *plugin : 0;
}

/*!
  Load activity called via task switcher
  Restore view and playback path if applicable
 */
void MpMainWindow::loadActivity( QVariant data )
{
    TX_ENTRY
    QVariantHash activityData = data.toHash();
    QByteArray serializedRestorePath = activityData.value( "restorePath" ).toByteArray();
    MpEngineFactory::sharedEngine()->loadActivityData( serializedRestorePath );
    TX_EXIT
}