diff -r 3075d9b614e6 -r 0e652f8f1fbd camerauis/cameraxui/cxui/src/cxuiviewmanager.cpp --- a/camerauis/cameraxui/cxui/src/cxuiviewmanager.cpp Thu May 13 21:30:19 2010 +0300 +++ b/camerauis/cameraxui/cxui/src/cxuiviewmanager.cpp Thu Jul 15 01:55:05 2010 +0300 @@ -17,12 +17,13 @@ #include #include #include -#include #include - +#include +#include +#include #include "cxuiapplication.h" -#include "cxuiapplicationframeworkmonitor.h" +#include "cxuiapplicationstate.h" #include "cxuiviewmanager.h" #include "cxuivideoprecaptureview.h" #include "cxuistillprecaptureview.h" @@ -36,217 +37,346 @@ #include "cxuienums.h" #include "cxutils.h" #include "cxuidocumentloader.h" -#include "cxuistandby.h" -#include "cxuierrormanager.h" #include "cxesettings.h" #include "cxememorymonitor.h" #include "cxuiserviceprovider.h" #include "cxuiscenemodeview.h" + +#ifdef Q_OS_SYMBIAN #include "OstTraceDefinitions.h" + #ifdef OST_TRACE_COMPILER_IN_USE #include "cxuiviewmanagerTraces.h" #endif +#endif //Q_OS_SYMBIAN + using namespace Cxe; using namespace CxUiLayout; +namespace +{ + static const int CXUI_STANDBY_CAMERA_TIMEOUT = 60000; // 60 seconds +} -// --------------------------------------------------------------------------- -// CxuiViewManager::CxuiViewManager -// -// --------------------------------------------------------------------------- -// + +/*! +* Constructor. +*/ CxuiViewManager::CxuiViewManager(CxuiApplication &application, HbMainWindow &mainWindow, CxeEngine &engine) : mApplication(application), mMainWindow(mainWindow), - mStillPrecaptureView(NULL), - mVideoPrecaptureView(NULL), - mPostcaptureView(NULL), mEngine(engine), mKeyHandler(NULL), - mApplicationMonitor(NULL), mCameraDocumentLoader(NULL), - mSceneModeView(NULL) + mApplicationState(NULL), + mErrorManager(NULL) { CX_DEBUG_ENTER_FUNCTION(); - // Application monitor - mApplicationMonitor = new CxuiApplicationFrameworkMonitor(mApplication, mEngine.settings()); - connect(mApplicationMonitor, SIGNAL(foregroundStateChanged(CxuiApplicationFrameworkMonitor::ForegroundState)), - this, SLOT(handleForegroundStateChanged(CxuiApplicationFrameworkMonitor::ForegroundState))); - connect(mApplicationMonitor, SIGNAL(batteryEmpty()), - this, SLOT(handleBatteryEmpty())); - - // Connect memory monitor start / stop to focused status - connect(this, SIGNAL(focusGained()), &mEngine.memoryMonitor(), SLOT(startMonitoring())); - connect(this, SIGNAL(focusLost()), &mEngine.memoryMonitor(), SLOT(stopMonitoring())); + // create mappings to map view name to correct docml file + mDocmlFilesByView.insert(STILL_PRE_CAPTURE_VIEW, STILL_1ST_XML); + mDocmlFilesByView.insert(VIDEO_PRE_CAPTURE_VIEW, VIDEO_1ST_XML); + mDocmlFilesByView.insert(POSTCAPTURE_VIEW, POSTCAPTURE_XML); + mDocmlFilesByView.insert(SCENE_MODE_VIEW, SCENEMODE_SETTING_XML); // Key handler mKeyHandler = new CxuiCaptureKeyHandler(mEngine); - mMainWindow.installEventFilter(this); // in order to filter capture and AF keys - - OstTrace0( camerax_performance, CXUIVIEWMANAGER_CXUIVIEWMANAGER, "msg: e_CX_VIEWMANAGER_CREATE_DOCLOADER 1" ); + // Document loader + OstTrace0(camerax_performance, CXUIVIEWMANAGER_CXUIVIEWMANAGER_1, "msg: e_CX_VIEWMANAGER_CREATE_DOCLOADER 1"); mCameraDocumentLoader = new CxuiDocumentLoader(&engine); - OstTrace0( camerax_performance, DUP1_CXUIVIEWMANAGER_CXUIVIEWMANAGER, "msg: e_CX_VIEWMANAGER_CREATE_DOCLOADER 0" ); - - // standby functionality and necessary signal connections - mStandbyHandler = new CxuiStandby(*mKeyHandler, mCameraDocumentLoader, &mEngine); - - connect(mStandbyHandler, SIGNAL(aboutToEnterStandby()),this, SLOT(aboutToLooseFocus())); - connect(mStandbyHandler, SIGNAL(aboutToExitStandby()),this, SLOT(aboutToGainFocus())); - - // error manager, handling errors and notifying users based on their severity - mErrorManager = new CxuiErrorManager(*mKeyHandler, mCameraDocumentLoader); + OstTrace0(camerax_performance, CXUIVIEWMANAGER_CXUIVIEWMANAGER_2, "msg: e_CX_VIEWMANAGER_CREATE_DOCLOADER 0"); - // connecting necessary signals from error manager to release and init camera. - connect(mErrorManager, SIGNAL(aboutToRecoverError()), this, SLOT(aboutToLooseFocus())); - connect(mErrorManager, SIGNAL(errorRecovered()), this, SLOT(aboutToGainFocus())); + // Application state + mApplicationState = new CxuiApplicationState(mApplication, mEngine.settings(), mCameraDocumentLoader); + CX_ASSERT_ALWAYS(mApplicationState); + bool ok = connect(mApplicationState, SIGNAL(stateChanged(CxuiApplicationState::State, CxuiApplicationState::State)), + this, SLOT(handleApplicationStateChanged(CxuiApplicationState::State, CxuiApplicationState::State))); + Q_ASSERT_X(ok, "CxuiViewManager", "Application state change signal connect failed."); + connect(this, SIGNAL(standbyExitRequested()), mApplicationState, SLOT(exitStandby()), Qt::QueuedConnection); - if (!CxuiServiceProvider::isCameraEmbedded()) { - // For embedded mode: don't create view yet, create - // when engine inits to correct mode - CX_DEBUG_ASSERT(mEngine.cameraDeviceControl().cameraIndex() == Cxe::PrimaryCameraIndex); - if (mEngine.mode() == Cxe::VideoMode) { - createVideoPrecaptureView(); - mMainWindow.blockSignals(true); - mMainWindow.setCurrentView(mVideoPrecaptureView, false); - mMainWindow.blockSignals(false); - } else { - createStillPrecaptureView(); - mMainWindow.blockSignals(true); - mMainWindow.setCurrentView(mStillPrecaptureView, false); - mMainWindow.blockSignals(false); - } - connectPreCaptureSignals(); - } + // Standby timer + mStandbyTimer.setInterval(CXUI_STANDBY_CAMERA_TIMEOUT); + mStandbyTimer.setSingleShot(true); + connect(&mStandbyTimer, SIGNAL(timeout()), mApplicationState, SLOT(enterStandby())); + + // Filter capture and AF keys and follow user activity from mouse events. + QCoreApplication::instance()->installEventFilter(this); + + // Monitor memory on normal state, not on standby, error or background. + connect(this, SIGNAL(normalStateEntered()), &mEngine.memoryMonitor(), SLOT(startMonitoring())); + connect(this, SIGNAL(normalStateExited()), &mEngine.memoryMonitor(), SLOT(stopMonitoring())); //connecting initmode signals connect(&mEngine.cameraDeviceControl(), SIGNAL(initModeComplete(CxeError::Id)), - this, SLOT(createPostcaptureView())); - - connect(&mEngine.cameraDeviceControl(), SIGNAL(initModeComplete(CxeError::Id)), - mErrorManager, SLOT(analyze(CxeError::Id))); + mApplicationState, SLOT(handleApplicationError(CxeError::Id))); connect(&mEngine.stillCaptureControl(), SIGNAL(imageCaptured(CxeError::Id, int)), - mErrorManager, SLOT(analyze(CxeError::Id))); + mApplicationState, SLOT(handleApplicationError(CxeError::Id))); + + // Register stylesheet. It will be automatically destroyed on application + // exit. + HbStyleLoader::registerFilePath(":/camerax/cxui.css"); + + // Create the view we are starting in, or connect signals so it + // will be created once we know the mode we are starting to. + initStartupView(); + + // For UI startup testing, we need to emit applicationReady signal once UI is ready to be used. + connect(mMainWindow.currentView(), SIGNAL(viewReady()), &mApplication, SIGNAL(applicationReady())); + + CX_DEBUG_EXIT_FUNCTION(); +} + + +/*! +* Destructor. +*/ +CxuiViewManager::~CxuiViewManager() +{ + CX_DEBUG_ENTER_FUNCTION(); + QCoreApplication::instance()->removeEventFilter(this); + + if (!CxuiServiceProvider::isCameraEmbedded()) { + currentView()->saveActivity(); + } + + delete mApplicationState; + delete mCameraDocumentLoader; + delete mKeyHandler; + + CX_DEBUG_EXIT_FUNCTION(); +} + + + +/*! +* Handle change in overall state of application. +* @param newState The new application state. +*/ +void CxuiViewManager::handleApplicationStateChanged(CxuiApplicationState::State newState, + CxuiApplicationState::State oldState) +{ + Q_UNUSED(oldState); + CX_DEBUG_ENTER_FUNCTION(); + + CxuiView *view = qobject_cast(mMainWindow.currentView()); + CX_DEBUG(("CxuiViewManager - current view %d", view)); + + switch (newState) { + case CxuiApplicationState::Normal: + // Disable raising to foreground with capture key. + disconnect(mKeyHandler, SIGNAL(captureKeyPressed()), this, SLOT(toForeground())); + + connectSignals(view); + + CX_DEBUG(("CxuiViewManager - emitting normalStateEntered")); + emit normalStateEntered(); + break; + case CxuiApplicationState::Standby: + if (view && !view->isStandbyModeSupported()) { + // If we move to Stanby, and current view does not + // support standby mode, move to Normal mode right away. + CX_DEBUG(("CxuiViewManager - view does not support stanbdy, exiting standby right away..")); + mApplicationState->exitStandby(); + } else { + handleExitingNormalState(); + } + break; + case CxuiApplicationState::Error: + case CxuiApplicationState::Background: + handleExitingNormalState(); - if (CxuiServiceProvider::isCameraEmbedded()) { - // connect signals to set up the view after image/video prepare + if (newState == CxuiApplicationState::Background) { + // Moved to background. + // Bring application back to foreground by capture key press + connect(mKeyHandler, SIGNAL(captureKeyPressed()), this, SLOT(toForeground())); + } + break; + } + + CX_DEBUG_EXIT_FUNCTION(); +} + +/*! +* Helper method to handle (possible) exiting from normal state. +* @param oldState The previous state. +*/ +void CxuiViewManager::handleExitingNormalState() +{ + CX_DEBUG_ENTER_FUNCTION(); + // Store view that is active now. + CxuiView *view = qobject_cast(mMainWindow.currentView()); + CX_DEBUG(("CxuiViewManager - current view %d", view)); + + // Emit signal so current view can enter standby. + emit normalStateExited(); + // Disconnect signals so we don't send key event's etc. + // Using the view before normalStateExited() signal was emitted, + // just in case it caused view switch. + disconnectSignals(view); + // Make sure standby timer is not running. + stopStandbyTimer(); + + CX_DEBUG_EXIT_FUNCTION(); +} + +/*! +* Slot for starting standby timer. +*/ +void CxuiViewManager::startStandbyTimer() +{ + CX_DEBUG_ENTER_FUNCTION(); + mStandbyTimer.start(); + CX_DEBUG_EXIT_FUNCTION(); +} + +/*! +* Slot for stopping standby timer. +*/ +void CxuiViewManager::stopStandbyTimer() +{ + CX_DEBUG_ENTER_FUNCTION(); + mStandbyTimer.stop(); + CX_DEBUG_EXIT_FUNCTION(); +} + +/*! + * Helper function to return current view cast to CxuiView. + */ +CxuiView* CxuiViewManager::currentView() const +{ + CxuiView *view = qobject_cast (mMainWindow.currentView()); + CX_ASSERT_ALWAYS(view); + return view; +} + +/*! +* Select and initialize the view we need to start into. +*/ +void CxuiViewManager::initStartupView() +{ + CX_DEBUG_ENTER_FUNCTION(); + + if (mApplication.activateReason() == Hb::ActivationReasonService) { + // For embedded mode: don't create view yet, create when engine inits to correct mode. + // Connect signals to set up the view after image/video prepare connect(&mEngine.stillCaptureControl(), SIGNAL(imagePrepareComplete(CxeError::Id)), this, SLOT(changeToPrecaptureView())); connect(&mEngine.videoCaptureControl(), SIGNAL(videoPrepareComplete(CxeError::Id)), this, SLOT(changeToPrecaptureView())); - // start standby timer now because view will not be ready when viewfinder is started - mStandbyHandler->startTimer(); + } else if (mApplication.activateReason() == Hb::ActivationReasonActivity) { + // restoring activity, read startup view from stored activity + + // view to start in + QString viewName = STILL_PRE_CAPTURE_VIEW; + + bool preCapture = true; + QString activityId = mApplication.activateId(); + if (activityId == CxuiActivityIds::STILL_PRECAPTURE_ACTIVITY) { + viewName = STILL_PRE_CAPTURE_VIEW; + } else if (activityId == CxuiActivityIds::STILL_POSTCAPTURE_ACTIVITY) { + viewName = POSTCAPTURE_VIEW; + preCapture = false; + } else if (activityId == CxuiActivityIds::VIDEO_PRECAPTURE_ACTIVITY) { + viewName = VIDEO_PRE_CAPTURE_VIEW; + } else if (activityId == CxuiActivityIds::VIDEO_POSTCAPTURE_ACTIVITY) { + viewName = POSTCAPTURE_VIEW; + preCapture = false; + } + + CxuiView *view = createView(viewName); + mMainWindow.setCurrentView(view, false); + + if (preCapture) { + connectPreCaptureSignals(); + } else { + connectPostCaptureSignals(); + } + + // Check the current application state, signalled to handleApplicationStateChanged. + mApplicationState->startMonitoring(); + + // restore view from activity + bool ok = mApplication.activityManager()->waitActivity(); + + view->restoreActivity(activityId, + mApplication.activityManager()->activityData(mApplication.activateId())); + + clearAllActivities(); + } else { + // normal start + // no activity id, get default view from engine state + CxuiView *view = NULL; + if (mEngine.mode() == Cxe::VideoMode) { + view = createView(VIDEO_PRE_CAPTURE_VIEW); + } else { + view = createView(STILL_PRE_CAPTURE_VIEW); + } + + mMainWindow.setCurrentView(view, false); + connectPreCaptureSignals(); + + // Check the current application state, signalled to handleApplicationStateChanged. + mApplicationState->startMonitoring(); + + clearAllActivities(); } CX_DEBUG_EXIT_FUNCTION(); } -// --------------------------------------------------------------------------- -// CxuiViewManager::~CxuiViewManager -// -// --------------------------------------------------------------------------- -// -CxuiViewManager::~CxuiViewManager() +/*! +* Create view and add it to main window. +*/ +CxuiView* CxuiViewManager::createView(const QString &viewName) { CX_DEBUG_ENTER_FUNCTION(); - delete mCameraDocumentLoader; - delete mKeyHandler; - delete mApplicationMonitor; + OstTrace0(camerax_performance, CXUIVIEWMANAGER_CREATEVIEW_IN, "msg: e_CX_CREATE_VIEW 1"); + + CX_DEBUG(("View name: %s", viewName.toAscii().data())); + + CxuiView* view = mViews[viewName]; + if (view == NULL) { + CX_DEBUG(("View not loaded yet, loading now")); + bool ok = false; + // Use document loader to create widgets and layouts + // (non-sectioned parts are parsed and loaded) + QString docmlFile = mDocmlFilesByView[viewName]; + CX_ASSERT_ALWAYS(mCameraDocumentLoader); + CX_ASSERT_ALWAYS(!docmlFile.isNull()); + + OstTrace0(camerax_performance, CXUIVIEWMANAGER_CREATEVIEW_2, "msg: e_CX_DOCUMENTLOADER_LOAD 1"); + mCameraDocumentLoader->load(docmlFile, &ok); + OstTrace0(camerax_performance, CXUIVIEWMANAGER_CREATEVIEW_4, "msg: e_CX_DOCUMENTLOADER_LOAD 0"); + Q_ASSERT_X(ok, "createView", "error in xml file parsing"); + + OstTrace0(camerax_performance, CXUIVIEWMANAGER_CREATEVIEW_6, "msg: e_CX_DOCUMENTLOADER_FINDWIDGET 1"); + QGraphicsWidget *widget = NULL; + // ask for the view widget pointer + widget = mCameraDocumentLoader->findWidget(viewName); + view = qobject_cast (widget); + CX_ASSERT_ALWAYS(view); + OstTrace0(camerax_performance, CXUIVIEWMANAGER_CREATEVIEW_8, "msg: e_CX_DOCUMENTLOADER_FINDWIDGET 1"); + + // call for needed consturction methods + view->construct(&mMainWindow, &mEngine, mCameraDocumentLoader, mKeyHandler, mApplication.activityManager()); + // .. and add to main window (which also takes ownership) + OstTrace0(camerax_performance, CXUIVIEWMANAGER_CREATEVIEW_10, "msg: e_CX_MAINWINDOW_ADDVIEW 1"); + mMainWindow.addView(view); + mViews.insert(viewName, view); + OstTrace0(camerax_performance, CXUIVIEWMANAGER_CREATEVIEW_12, "msg: e_CX_MAINWINDOW_ADDVIEW 0"); + } + + OstTrace0(camerax_performance, CXUIVIEWMANAGER_CREATEVIEW_OUT, "msg: e_CX_CREATE_VIEW 0"); CX_DEBUG_EXIT_FUNCTION(); -} - - -// --------------------------------------------------------------------------- -// CxuiViewManager::prepareWindow -// -// --------------------------------------------------------------------------- -// -void CxuiViewManager::prepareWindow() -{ - getPrecaptureView(mEngine.mode(), mEngine.cameraDeviceControl().cameraIndex())->prepareWindow(); -} - - -// --------------------------------------------------------------------------- -// CxuiViewManager::createStillPrecaptureView -// -// --------------------------------------------------------------------------- -// -void CxuiViewManager::createStillPrecaptureView() -{ - CX_DEBUG_ENTER_FUNCTION(); - OstTrace0( camerax_performance, CXUIVIEWMANAGER_CREATESTILLPRECAPTUREVIEW, "msg: e_CX_CREATE_STILLPRECAPTUREVIEW 1" ); - - // Use document loader to create widgets and layouts - // (non-sectioned parts are parsed and loaded) - OstTrace0( camerax_performance, DUP2_CXUIVIEWMANAGER_ADDPRECAPTUREVIEWS, "msg: e_CX_DOCLOADER_LOAD 1" ); - - bool ok = false; - CX_DEBUG_ASSERT(mCameraDocumentLoader); - mCameraDocumentLoader->load(STILL_1ST_XML, &ok); - Q_ASSERT_X(ok, "createStillPrecaptureView", "error in xml file parsing"); - - OstTrace0( camerax_performance, DUP2_CXUIVIEWMANAGER_CREATESTILLPRECAPTUREVIEW, "msg: e_CX_DOCLOADER_LOAD 0" ); - - OstTrace0( camerax_performance, DUP4_CXUIVIEWMANAGER_ADDPRECAPTUREVIEWS, "msg: e_CX_DOCLOADER_FINDWIDGET 1" ); - QGraphicsWidget *widget = NULL; - // ask for the still precapture view widget pointer - widget = mCameraDocumentLoader->findWidget(STILL_PRE_CAPTURE_VIEW); - mStillPrecaptureView = qobject_cast (widget); - CX_DEBUG_ASSERT(mStillPrecaptureView); - OstTrace0( camerax_performance, DUP5_CXUIVIEWMANAGER_ADDPRECAPTUREVIEWS, "msg: e_CX_DOCLOADER_FINDWIDGET 0" ); - - // call for needed consturction methods - mStillPrecaptureView->construct(&mMainWindow, &mEngine, mCameraDocumentLoader, mKeyHandler); - // .. and add to main window (which also takes ownership) - OstTrace0( camerax_performance, DUP1_CXUIVIEWMANAGER_MAINWINDOW_ADDVIEW, "msg: e_CX_MAINWINDOW_ADDVIEW 1" ); - mMainWindow.addView(widget); - OstTrace0( camerax_performance, DUP2_CXUIVIEWMANAGER_MAINWINDOW_ADDVIEW, "msg: e_CX_MAINWINDOW_ADDVIEW 0" ); - - OstTrace0( camerax_performance, DUP1_CXUIVIEWMANAGER_CREATESTILLPRECAPTUREVIEW, "msg: e_CX_CREATE_STILLPRECAPTUREVIEW 0" ); - - CX_DEBUG_EXIT_FUNCTION(); -} - -// --------------------------------------------------------------------------- -// CxuiViewManager::createStillScenesView -// -// --------------------------------------------------------------------------- -// -void CxuiViewManager::createSceneModesView() -{ - CX_DEBUG_ENTER_FUNCTION(); - - bool ok = false; - CX_DEBUG_ASSERT(mCameraDocumentLoader); - - // Use document loader to create widgets and layouts - // (non-sectioned parts are parsed and loaded) - mCameraDocumentLoader->load(SCENEMODE_SETTING_XML, &ok); - - QGraphicsWidget *widget = NULL; - - // ask for the scenes mode view widget pointer - widget = mCameraDocumentLoader->findWidget(STILL_SCENES_VIEW); - Q_ASSERT_X(ok && (widget != 0), "camerax ui", "invalid xml file"); - mSceneModeView = qobject_cast (widget); - - // call for needed construction methods - mSceneModeView->construct(&mMainWindow, &mEngine, mCameraDocumentLoader, mKeyHandler); - // .. and add to main window (which also takes ownership) - mMainWindow.addView(widget); - mSceneModeView->loadBackgroundImages(); - - connect(mSceneModeView, SIGNAL(viewCloseEvent()), this, SLOT(changeToPrecaptureView())); - CX_DEBUG_EXIT_FUNCTION(); + return view; } /*! @@ -256,148 +386,70 @@ void CxuiViewManager::showScenesView() { CX_DEBUG_ENTER_FUNCTION(); - if (!mSceneModeView) { - createSceneModesView(); - } - else { - mSceneModeView->loadBackgroundImages(); - } - CX_DEBUG_ASSERT(mSceneModeView); - mMainWindow.blockSignals(true); - mMainWindow.setCurrentView(mSceneModeView, false); - emit disableStandbyTimer(); - connectCaptureKeySignals(); - mMainWindow.blockSignals(false); - CX_DEBUG_EXIT_FUNCTION(); -} - + // Disconnect signals from old view. + disconnectSignals(); -// --------------------------------------------------------------------------- -// CxuiViewManager::createVideoPrecaptureView -// -// --------------------------------------------------------------------------- -// -void CxuiViewManager::createVideoPrecaptureView() -{ - CX_DEBUG_ENTER_FUNCTION(); - OstTrace0( camerax_performance, CXUIVIEWMANAGER_CREATEVIDEOPRECAPTUREVIEW, "msg: e_CX_CREATE_VIDEOPRECAPTUREVIEW 1" ); - - CX_DEBUG_ASSERT(mCameraDocumentLoader); + CxuiSceneModeView *view = qobject_cast(createView(SCENE_MODE_VIEW)); + CX_ASSERT_ALWAYS(view); + view->loadBackgroundImages(); - bool ok = false; - // load and create the default widgets in video xml - mCameraDocumentLoader->load(VIDEO_1ST_XML, &ok); - CX_DEBUG_ASSERT(ok); - - // get pointer to videoprecaptureview and do some initialisation - QGraphicsWidget *widget = NULL; - widget = mCameraDocumentLoader->findWidget(VIDEO_PRE_CAPTURE_VIEW); - mVideoPrecaptureView = qobject_cast (widget); - CX_DEBUG_ASSERT(mVideoPrecaptureView); - mVideoPrecaptureView->construct(&mMainWindow, &mEngine, mCameraDocumentLoader, mKeyHandler); - - // add view to main window - OstTrace0( camerax_performance, DUP3_CXUIVIEWMANAGER_MAINWINDOW_ADDVIEW, "msg: e_CX_MAINWINDOW_ADDVIEW 1" ); - mMainWindow.addView(mVideoPrecaptureView); - OstTrace0( camerax_performance, DUP4_CXUIVIEWMANAGER_MAINWINDOW_ADDVIEW, "msg: e_CX_MAINWINDOW_ADDVIEW 0" ); - OstTrace0( camerax_performance, DUP1_CXUIVIEWMANAGER_CREATEVIDEOPRECAPTUREVIEW, "msg: e_CX_CREATE_VIDEOPRECAPTUREVIEW 0" ); + mMainWindow.setCurrentView(view, false); + stopStandbyTimer(); + connectSceneModeSignals(); CX_DEBUG_EXIT_FUNCTION(); } -// --------------------------------------------------------------------------- -// CxuiViewManager::createStillPostcaptureView -// -// --------------------------------------------------------------------------- -// -void CxuiViewManager::createPostcaptureView() -{ - CX_DEBUG_ENTER_FUNCTION(); - CX_DEBUG_ASSERT(mCameraDocumentLoader); - OstTrace0( camerax_performance, CXUIVIEWMANAGER_CREATESTILLPOSTCAPTUREVIEW, "msg: e_CX_CREATE_STILLPOSTCAPTUREVIEW 1" ); - - if (!mPostcaptureView) { - bool ok = false; - mCameraDocumentLoader->load(POSTCAPTURE_XML, &ok); - CX_DEBUG_ASSERT(ok); - - // get pointer to videoprecaptureview and do some initialisation - QGraphicsWidget *widget = NULL; - widget = mCameraDocumentLoader->findWidget(POSTCAPTURE_VIEW); - mPostcaptureView = qobject_cast (widget); - CX_DEBUG_ASSERT(mPostcaptureView); - mPostcaptureView->construct(&mMainWindow, &mEngine, mCameraDocumentLoader); - - mMainWindow.addView(mPostcaptureView); - connect(mPostcaptureView, SIGNAL(changeToPrecaptureView()), this, SLOT(changeToPrecaptureView())); - - } - - OstTrace0( camerax_performance, DUP1_CXUIVIEWMANAGER_CREATESTILLPOSTCAPTUREVIEW, "msg: e_CX_CREATE_STILLPOSTCAPTUREVIEW 0" ); - CX_DEBUG_EXIT_FUNCTION(); -} - -// --------------------------------------------------------------------------- -// CxuiViewManager::getPrecaptureView -// -// --------------------------------------------------------------------------- -// +/*! +* Get the precapture view appropriate for given camera mode and index. +* If the view does not exist, it is created. +* @param mode Which camera mode the view should match. +* @param index Which camera index the view should match. +*/ CxuiPrecaptureView* CxuiViewManager::getPrecaptureView(Cxe::CameraMode mode, Cxe::CameraIndex camera) { CX_DEBUG_ENTER_FUNCTION(); - CX_DEBUG(("CxuiViewManager::getPrecaptureView() mode=%d, camera index=%d", mode, camera)); + CX_DEBUG(("CxuiViewManager::getPrecaptureView - mode=%d, camera index=%d", mode, camera)); CX_DEBUG_ASSERT(camera == Cxe::PrimaryCameraIndex); if (mode == ImageMode) { - CX_DEBUG(("CxuiViewManager::getPrecaptureView() image mode")); - if(!mStillPrecaptureView) { - createStillPrecaptureView(); - } - return mStillPrecaptureView; + CX_DEBUG(("CxuiViewManager::getPrecaptureView - image mode")); + return qobject_cast(createView(STILL_PRE_CAPTURE_VIEW)); + } else { - CX_DEBUG(("CxuiViewManager::getPrecaptureView() video mode")); - if(!mVideoPrecaptureView) { - createVideoPrecaptureView(); - } - return mVideoPrecaptureView; + CX_DEBUG(("CxuiViewManager::getPrecaptureView - video mode")); + return qobject_cast(createView(VIDEO_PRE_CAPTURE_VIEW)); } } -CxuiDocumentLoader* CxuiViewManager::documentLoader() -{ - return mCameraDocumentLoader; -} - -// --------------------------------------------------------------------------- -// CxuiViewManager::changeToPostcaptureView -// -// --------------------------------------------------------------------------- -// +/*! +* Move to post-capture view. +*/ void CxuiViewManager::changeToPostcaptureView() { CX_DEBUG_ENTER_FUNCTION(); + // Disconnect signals from old view. + disconnectSignals(); - if (!mPostcaptureView) { - createPostcaptureView(); - } + CxuiView *postCaptureView = createView(POSTCAPTURE_VIEW); + + mMainWindow.setCurrentView(postCaptureView, false); - mMainWindow.blockSignals(true); - mMainWindow.setCurrentView(mPostcaptureView, false); - mMainWindow.blockSignals(false); - - // connecting all necessary signals for postcapture view - connectPostCaptureSignals(); + // Connecting all necessary signals for postcapture view. + // Not connected yet if not in normal state. We connect the signals + // once we enter normal state again. + if (mApplicationState->currentState() == CxuiApplicationState::Normal) { + connectPostCaptureSignals(); + } CX_DEBUG_EXIT_FUNCTION(); } -// --------------------------------------------------------------------------- -// CxuiViewManager::changeToPrecaptureView -// -// --------------------------------------------------------------------------- -// +/*! +* Move to pre-capture view. +*/ void CxuiViewManager::changeToPrecaptureView() { CX_DEBUG_ENTER_FUNCTION(); @@ -410,25 +462,43 @@ this, SLOT(changeToPrecaptureView())); } - HbView *view = getPrecaptureView(mEngine.mode(), - mEngine.cameraDeviceControl().cameraIndex()); + // If normal mode is not active, don't switch to precapture view and reserve camera now. + if (mApplicationState->currentState() != CxuiApplicationState::Normal) { + CX_DEBUG(("CxuiViewManager - Change to precapture blocked as not normal mode (error, standby, background).")); + } else { + + // Disconnect signals from old view. + disconnectSignals(); + + HbView *view = getPrecaptureView(mEngine.mode(), + mEngine.cameraDeviceControl().cameraIndex()); + mMainWindow.setCurrentView(view, false); - mMainWindow.blockSignals(true); - mMainWindow.setCurrentView(view, false); - mMainWindow.blockSignals(false); + // Release resources needed by scene view. + HbView *sceneView = mViews.take(SCENE_MODE_VIEW); + if (sceneView) { + // This will not delete the view. + mMainWindow.removeView(sceneView); + // We can get to this slot from scene view, so don't delete the object too early. + sceneView->deleteLater(); + sceneView = NULL; + } - // connecting necessary pre-capture view signals - connectPreCaptureSignals(); - emit startStandbyTimer(); + // connecting necessary pre-capture view signals + connectPreCaptureSignals(); + // Make sure engine prepares for new image/video if necessary + mEngine.initMode(mEngine.mode()); + + startStandbyTimer(); + + } CX_DEBUG_EXIT_FUNCTION(); } -// --------------------------------------------------------------------------- -// CxuiViewManager::switchCamera -// -// --------------------------------------------------------------------------- -// +/*! +* Switch between cameras. +*/ void CxuiViewManager::switchCamera() { CX_DEBUG_ENTER_FUNCTION(); @@ -445,12 +515,8 @@ } CxuiPrecaptureView* view = getPrecaptureView(mEngine.mode(), nextCamera); - - mMainWindow.blockSignals(true); mMainWindow.setCurrentView(view, false); - mMainWindow.blockSignals(false); view->updateOrientation(nextViewOrientation); - view->prepareWindow(); connectPreCaptureSignals(); @@ -459,34 +525,201 @@ CX_DEBUG_EXIT_FUNCTION(); } -// --------------------------------------------------------------------------- -// CxuiViewManager::eventFilter -// -// --------------------------------------------------------------------------- -// +/*! +* Event filter function. +* Used to get mouse and key events for standby and capture key handling. +* @param object Target object. +* @param event Event to be checked. +*/ bool CxuiViewManager::eventFilter(QObject *object, QEvent *event) { Q_UNUSED(object) bool eventWasConsumed = false; + bool userActivity = false; - switch (event->type()) - { + switch (event->type()) { case QEvent::KeyPress: case QEvent::KeyRelease: + userActivity = true; eventWasConsumed = mKeyHandler->handleKeyEvent(event); + if (eventWasConsumed && mApplicationState->currentState() == CxuiApplicationState::Standby) { + // Queued exit from standby. + emit standbyExitRequested(); + } + break; + + case QEvent::GraphicsSceneMouseMove: + case QEvent::GraphicsSceneMousePress: + userActivity = true; + break; + case QEvent::GraphicsSceneMouseRelease: + userActivity = true; + if (mApplicationState->currentState() == CxuiApplicationState::Standby) { + // Queued exit from standby. + // Standby popup in view can receive mouse event before it is dismissed. + emit standbyExitRequested(); + } break; } + + // Restart standby timer if there is user activity. + // Only restart the timer if it is running, do not set it running here. + if (userActivity && mStandbyTimer.isActive()) { + startStandbyTimer(); + } + // No need to call base class implementation, because we derive from QObject directly. // QObject::eventFilter() implementation always returns false. return eventWasConsumed; } -// --------------------------------------------------------------------------- -// CxuiViewManager::connectCaptureKeySignals -// -// --------------------------------------------------------------------------- -// +/*! +* Connect signals specific to given view. +*/ +void CxuiViewManager::connectSignals(QObject *view) +{ + CX_DEBUG_ENTER_FUNCTION(); + OstTrace0(camerax_performance, CXUIVIEWMANAGER_CONNECTSIGNALS_1, "msg: e_CX_VIEWMANAGER_CONNECT_SIGNALS 1"); + + if (view) { + if (view == mViews[POSTCAPTURE_VIEW]) { + connectPostCaptureSignals(); + } else if (view == mViews[SCENE_MODE_VIEW]) { + connectSceneModeSignals(); + } else { + connectPreCaptureSignals(); + } + } + + OstTrace0(camerax_performance, CXUIVIEWMANAGER_CONNECTSIGNALS_2, "msg: e_CX_VIEWMANAGER_CONNECT_SIGNALS 0"); + CX_DEBUG_EXIT_FUNCTION(); +} + +/*! +* Disconnect signals. +* We don't want to send or receive signals with inactive views, so this is done every time changing a view. +* @param view View object from which signals are disconnected. If NULL is given, current view is used. +*/ +void CxuiViewManager::disconnectSignals(QObject *view) +{ + CX_DEBUG_ENTER_FUNCTION(); + OstTrace0(camerax_performance, CXUIVIEWMANAGER_DISCONNECT_1, "msg: e_CX_VIEWMANAGER_DISCONNECT_SIGNALS 1"); + + // Disconnect all existing capture key signals + mKeyHandler->disconnect(); + + if (!view) { + // If view is not given, take current view. + view = mMainWindow.currentView(); + } + + CX_DEBUG(("CxuiViewManager - disconnecting from view %d", view)); + if (view) { + // Disconnect all signals from current view to us. + disconnect(view, 0, this, 0); + // Disconnect all signals from us to current view. + disconnect(this, 0, view, 0); + } + + OstTrace0(camerax_performance, CXUIVIEWMANAGER_DISCONNECT_2, "msg: e_CX_VIEWMANAGER_DISCONNECT_SIGNALS 0"); + CX_DEBUG_EXIT_FUNCTION(); +} + +/*! +* Connect signals to pre-capture view. +*/ +void CxuiViewManager::connectPreCaptureSignals() +{ + CX_DEBUG_ENTER_FUNCTION(); + + disconnectSignals(); + + HbView *currentView = mMainWindow.currentView(); + + if (currentView != mViews[POSTCAPTURE_VIEW]) { + // connects all capture key signals. + connectCaptureKeySignals(); + + // connecting pre-capture view signals to standby timer. + connect(currentView, SIGNAL(startStandbyTimer()), this, SLOT(startStandbyTimer()), Qt::UniqueConnection); + connect(currentView, SIGNAL(stopStandbyTimer()), this, SLOT(stopStandbyTimer()), Qt::UniqueConnection); + connect(currentView, SIGNAL(changeToPrecaptureView()), this, SLOT(startStandbyTimer()), Qt::UniqueConnection); + connect(currentView, SIGNAL(changeToPostcaptureView()), this, SLOT(stopStandbyTimer()), Qt::UniqueConnection); + + // connecting pre-capture view signals to viewmanager slots + connect(currentView, SIGNAL(changeToPostcaptureView()), this, SLOT(changeToPostcaptureView()), Qt::UniqueConnection); + connect(currentView, SIGNAL(changeToPrecaptureView()), this, SLOT(changeToPrecaptureView()), Qt::UniqueConnection); + + //connecting scene modes signal + connect(currentView, SIGNAL(showScenesView()), this, SLOT(showScenesView()), Qt::UniqueConnection); + + connect(currentView, SIGNAL(switchCamera()), this, SLOT(switchCamera()), Qt::UniqueConnection); + + // connecting error signals from precapture view to application state. + connect(currentView, SIGNAL(errorEncountered(CxeError::Id)), + mApplicationState, SLOT(handleApplicationError(CxeError::Id)), + Qt::UniqueConnection); + + // Standby signals + connect(this, SIGNAL(normalStateEntered()), currentView, SLOT(exitStandby()), Qt::UniqueConnection); + connect(this, SIGNAL(normalStateExited()), currentView, SLOT(enterStandby()), Qt::UniqueConnection); + } + + CX_DEBUG_EXIT_FUNCTION(); +} + +/*! +* Connect signals to post-capture view. +*/ +void CxuiViewManager::connectPostCaptureSignals() +{ + CX_DEBUG_ENTER_FUNCTION(); + + disconnectSignals(); + QObject *currentView = mMainWindow.currentView(); + if (currentView == mViews[POSTCAPTURE_VIEW]) { + + connect(currentView, SIGNAL(changeToPrecaptureView()), this, SLOT(changeToPrecaptureView()), Qt::UniqueConnection); + + // Standby signals + connect(this, SIGNAL(normalStateEntered()), currentView, SLOT(exitStandby()), Qt::UniqueConnection); + connect(this, SIGNAL(normalStateExited()), currentView, SLOT(enterStandby()), Qt::UniqueConnection); + + // connect necessary capturekey signals + connectCaptureKeySignals(); + } + + CX_DEBUG_EXIT_FUNCTION(); +} + +/*! +* Connect signals to scene mode view. +*/ +void CxuiViewManager::connectSceneModeSignals() +{ + CX_DEBUG_ENTER_FUNCTION(); + disconnectSignals(); + + HbView *currentView = mMainWindow.currentView(); + + if (currentView == mViews[SCENE_MODE_VIEW]) { + + connectCaptureKeySignals(); + + // Standby signals for releasing camera + connect(this, SIGNAL(normalStateEntered()), currentView, SLOT(exitStandby())); + connect(this, SIGNAL(normalStateExited()), currentView, SLOT(enterStandby())); + + // Moving back to pre-capture view + connect(currentView, SIGNAL(viewCloseEvent()), this, SLOT(changeToPrecaptureView())); + } + CX_DEBUG_EXIT_FUNCTION(); +} + +/*! +* Connect key handler capture key signals. +*/ void CxuiViewManager::connectCaptureKeySignals() { CX_DEBUG_ENTER_FUNCTION(); @@ -508,104 +741,16 @@ CX_DEBUG_EXIT_FUNCTION(); } - -// --------------------------------------------------------------------------- -// CxuiViewManager::connectPreCaptureSignals -// -// --------------------------------------------------------------------------- -// -void CxuiViewManager::connectPreCaptureSignals() +/*! + * Clears all camera activities from activity manager. + */ +void CxuiViewManager::clearAllActivities() { - CX_DEBUG_ENTER_FUNCTION(); - - disconnectSignals(); - - QObject *currentView = mMainWindow.currentView(); - - if (currentView != mPostcaptureView) { - // connects all capture key signals. - connectCaptureKeySignals(); - - // connecting view manager focus events to pre-capture views - connect(this, SIGNAL(focusGained()), currentView, SLOT(handleFocusGained()), Qt::UniqueConnection); - connect(this, SIGNAL(focusLost()), currentView, SLOT(handleFocusLost()), Qt::UniqueConnection); - connect(this, SIGNAL(batteryEmpty()), currentView, SLOT(handleBatteryEmpty()), Qt::UniqueConnection); - - // in standby mode, we are interested in focus gain events for dismissing standby - connect(this, SIGNAL(focusGained()), mStandbyHandler, SLOT(handleMouseEvent()), Qt::UniqueConnection); - - // connecting key events to standby. - connect(mKeyHandler, SIGNAL(autofocusKeyPressed()), mStandbyHandler, SLOT(stopTimer()), Qt::UniqueConnection); - connect(mKeyHandler, SIGNAL(autofocusKeyReleased()), mStandbyHandler, SLOT(startTimer()), Qt::UniqueConnection); - connect(mKeyHandler, SIGNAL(captureKeyPressed()), mStandbyHandler, SLOT(startTimer()), Qt::UniqueConnection); - connect(mKeyHandler, SIGNAL(captureKeyReleased()), mStandbyHandler, SLOT(startTimer()), Qt::UniqueConnection); - connect(this, SIGNAL(disableStandbyTimer()), mStandbyHandler, SLOT(stopTimer()), Qt::UniqueConnection); - connect(this, SIGNAL(startStandbyTimer()), mStandbyHandler, SLOT(startTimer()), Qt::UniqueConnection); - - // connecting pre-capture view signals to standby. - connect(currentView, SIGNAL(startStandbyTimer()), mStandbyHandler, SLOT(startTimer()), Qt::UniqueConnection); - connect(currentView, SIGNAL(changeToPrecaptureView()), mStandbyHandler, SLOT(startTimer()), Qt::UniqueConnection); - connect(currentView, SIGNAL(stopStandbyTimer()), mStandbyHandler, SLOT(stopTimer()), Qt::UniqueConnection); - connect(currentView, SIGNAL(changeToPostcaptureView()), mStandbyHandler, SLOT(stopTimer()), Qt::UniqueConnection); - - // connecting precapture view signals to viewmanager slots - connect(currentView, SIGNAL(changeToPostcaptureView()), this, SLOT(changeToPostcaptureView()), Qt::UniqueConnection); - connect(currentView, SIGNAL(changeToPrecaptureView()), this, SLOT(changeToPrecaptureView()), Qt::UniqueConnection); - - //connecting scene modes signal - connect(currentView, SIGNAL(showScenesView()), this, SLOT(showScenesView()), Qt::UniqueConnection); - - connect(currentView, SIGNAL(switchCamera()), this, SLOT(switchCamera()), Qt::UniqueConnection); - - // connecting error signals from precapture view to errormanager. - connect(currentView, SIGNAL(reportError(CxeError::Id)), mErrorManager, SLOT(analyze(CxeError::Id)), Qt::UniqueConnection); - } - - CX_DEBUG_EXIT_FUNCTION(); -} - - -// --------------------------------------------------------------------------- -// CxuiViewManager::connectPostCaptureSignals -// -// --------------------------------------------------------------------------- -// -void CxuiViewManager::connectPostCaptureSignals() -{ - CX_DEBUG_ENTER_FUNCTION(); - - disconnectSignals(); - QObject *currentView = mMainWindow.currentView(); - if (currentView == mPostcaptureView) { - // connecting view manager focus events to pre-capture views - connect(this, SIGNAL(focusGained()), currentView, SLOT(startTimers()), Qt::UniqueConnection); - connect(this, SIGNAL(focusLost()), currentView, SLOT(handleFocusLost()), Qt::UniqueConnection); - connect(currentView, SIGNAL(changeToPrecaptureView()), mStandbyHandler, SLOT(startTimer()), Qt::UniqueConnection); - - // connect necessary capturekey signals - connectCaptureKeySignals(); - } - - CX_DEBUG_EXIT_FUNCTION(); -} - - - -/* -* CxuiViewManager::disconnectPreCaptureSignals -*/ -void CxuiViewManager::disconnectSignals() -{ - CX_DEBUG_ENTER_FUNCTION(); - - // Disconnect all existing capture key signals - mKeyHandler->disconnect(); - - disconnect(SIGNAL(focusGained())); - disconnect(SIGNAL(focusLost())); - disconnect(SIGNAL(batteryEmpty())); - - CX_DEBUG_EXIT_FUNCTION(); + HbActivityManager *activityManager = mApplication.activityManager(); + activityManager->removeActivity(CxuiActivityIds::STILL_PRECAPTURE_ACTIVITY); + activityManager->removeActivity(CxuiActivityIds::STILL_POSTCAPTURE_ACTIVITY); + activityManager->removeActivity(CxuiActivityIds::VIDEO_PRECAPTURE_ACTIVITY); + activityManager->removeActivity(CxuiActivityIds::VIDEO_POSTCAPTURE_ACTIVITY); } /*! @@ -615,10 +760,9 @@ { CX_DEBUG_ENTER_FUNCTION(); - if (mApplicationMonitor - && mApplicationMonitor->foregroundState() == CxuiApplicationFrameworkMonitor::ForegroundFullyLost) { + if (mApplicationState->currentState() == CxuiApplicationState::Background) { // Bring to foreground and gain focus. - CX_DEBUG(("CxuiViewManager - fully in background, bringing to foreground now.")); + CX_DEBUG(("CxuiViewManager - in background, bringing to foreground now.")); mMainWindow.raise(); mMainWindow.activateWindow(); } @@ -626,78 +770,4 @@ CX_DEBUG_EXIT_FUNCTION(); } -/*! -* Handle change in foreground state. -*/ -void CxuiViewManager::handleForegroundStateChanged(CxuiApplicationFrameworkMonitor::ForegroundState state) -{ - switch (state) { - case CxuiApplicationFrameworkMonitor::ForegroundPartiallyLost: - break; - case CxuiApplicationFrameworkMonitor::ForegroundFullyLost: - aboutToLooseFocus(); - break; - case CxuiApplicationFrameworkMonitor::ForegroundOwned: - aboutToGainFocus(); - break; - } -} - -// --------------------------------------------------------------------------- -// CxuiViewManager::aboutToLooseFocus() -// -// --------------------------------------------------------------------------- -// -void CxuiViewManager::aboutToLooseFocus() -{ - CX_DEBUG_ENTER_FUNCTION(); - - emit focusLost(); - disconnectSignals(); - - // We do not stop listening to capture key events even if we go to background, - // as capture key brings us back to foreground. - connect(mKeyHandler, SIGNAL(captureKeyPressed()), this, SLOT(toForeground())); - - CX_DEBUG_EXIT_FUNCTION(); -} - - -// --------------------------------------------------------------------------- -// CxuiViewManager::aboutToGainFocus -// -// --------------------------------------------------------------------------- -// -void CxuiViewManager::aboutToGainFocus() -{ - CX_DEBUG_ENTER_FUNCTION(); - - // Disconnect capture key event and bringing us to foreground connection (if there is one). - disconnect(mKeyHandler, SIGNAL(captureKeyPressed()), this, SLOT(toForeground())); - - // we are getting the focus. - if (mMainWindow.currentView() != mPostcaptureView) { - connectPreCaptureSignals(); - } else { - connectPostCaptureSignals(); - } - - if (mKeyHandler) { - mKeyHandler->listenKeys(true); - } - emit focusGained(); - - CX_DEBUG_EXIT_FUNCTION(); -} - -/*! -* Handle battery emptying -*/ -void CxuiViewManager::handleBatteryEmpty() -{ - CX_DEBUG_ENTER_FUNCTION(); - emit batteryEmpty(); - CX_DEBUG_EXIT_FUNCTION(); -} - // end of file