diff -r 2922f70fca82 -r 67457b2ffb33 camerauis/cameraxui/cxui/src/cxuiviewmanager.cpp --- a/camerauis/cameraxui/cxui/src/cxuiviewmanager.cpp Thu Jul 15 01:49:11 2010 +0300 +++ b/camerauis/cameraxui/cxui/src/cxuiviewmanager.cpp Thu Jul 15 01:52:14 2010 +0300 @@ -20,9 +20,11 @@ #include #include #include +#include +#include #include "cxuiapplication.h" -#include "cxuiapplicationframeworkmonitor.h" +#include "cxuiapplicationstate.h" #include "cxuiviewmanager.h" #include "cxuivideoprecaptureview.h" #include "cxuistillprecaptureview.h" @@ -36,8 +38,6 @@ #include "cxuienums.h" #include "cxutils.h" #include "cxuidocumentloader.h" -#include "cxuistandby.h" -#include "cxuierrormanager.h" #include "cxesettings.h" #include "cxememorymonitor.h" #include "cxuiserviceprovider.h" @@ -52,68 +52,67 @@ 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), + mApplicationState(NULL), + mErrorManager(NULL), mSceneModeView(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(mApplicationMonitor, SIGNAL(usbMassMemoryModeToggled(bool)), this, SLOT(showUsbErrorPopup(bool))); - - // 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(STILL_SCENES_VIEW, SCENEMODE_SETTING_XML); // Key handler mKeyHandler = new CxuiCaptureKeyHandler(mEngine); - mMainWindow.installEventFilter(this); // in order to filter capture and AF keys - + // Document loader OstTrace0( camerax_performance, CXUIVIEWMANAGER_CXUIVIEWMANAGER, "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())); + // Application state + mApplicationState = new CxuiApplicationState(mApplication, mEngine.settings(), *mKeyHandler, 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); - // error manager, handling errors and notifying users based on their severity - mErrorManager = new CxuiErrorManager(*mKeyHandler, mCameraDocumentLoader); + // Standby timer + mStandbyTimer.setInterval(CXUI_STANDBY_CAMERA_TIMEOUT); + mStandbyTimer.setSingleShot(true); + connect(&mStandbyTimer, SIGNAL(timeout()), mApplicationState, SLOT(enterStandby())); - // 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())); + // 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(showPopup(CxeError::Id))); + mApplicationState, SLOT(handleApplicationError(CxeError::Id))); connect(&mEngine.stillCaptureControl(), SIGNAL(imageCaptured(CxeError::Id, int)), - mErrorManager, SLOT(showPopup(CxeError::Id))); + mApplicationState, SLOT(handleApplicationError(CxeError::Id))); // Register stylesheet. It will be automatically destroyed on application // exit. @@ -123,58 +122,154 @@ // 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(); } -// --------------------------------------------------------------------------- -// CxuiViewManager::~CxuiViewManager -// -// --------------------------------------------------------------------------- -// -CxuiViewManager::~CxuiViewManager() + + +/*! +* 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 (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)); - delete mCameraDocumentLoader; - delete mKeyHandler; - delete mApplicationMonitor; + // 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(); } /** -* Temporary method to check if camera startup should be proceeded after creating view mananger. -*/ -bool CxuiViewManager::proceedStartup() + * Init engine to correct mode based on activity being restored. + */ +void CxuiViewManager::initEngine() { - return !mStandbyHandler->isActive(); -} - - -// --------------------------------------------------------------------------- -// CxuiViewManager::prepareWindow -// -// --------------------------------------------------------------------------- -// -void CxuiViewManager::prepareWindow() -{ - getPrecaptureView(mEngine.mode(), mEngine.cameraDeviceControl().cameraIndex())->prepareWindow(); + Cxe::CameraMode mode = Cxe::ImageMode; + QString activityId = mApplication.activateId(); + if (activityId == CxuiActivityIds::VIDEO_PRECAPTURE_ACTIVITY || + activityId == CxuiActivityIds::VIDEO_POSTCAPTURE_ACTIVITY) { + mode = Cxe::VideoMode; + } + if (activityId == CxuiActivityIds::STILL_PRECAPTURE_ACTIVITY || + activityId == CxuiActivityIds::VIDEO_PRECAPTURE_ACTIVITY) { + // init engine only if going to pre-capture + mEngine.initMode(mode); + } else { + // in post-capture don't init but set the correct mode to engine + // so init can be done later + mEngine.setMode(mode); + } } /*! -* Check if we need to take special actions in startup. -* USB mass memory mode atleast requires us to enter error standby mode, -* where user can only exit or fix the issue (remove cable). -*/ -void CxuiViewManager::startupCheck() + * Helper function to return current view cast to CxuiView. + */ +CxuiView* CxuiViewManager::currentView() const { - CX_DEBUG_ENTER_FUNCTION(); - - if (mApplicationMonitor && mApplicationMonitor->isUsbMassMemoryModeActive()) { - showUsbErrorPopup(true); - } - - CX_DEBUG_EXIT_FUNCTION(); + CxuiView *view = qobject_cast (mMainWindow.currentView()); + CX_ASSERT_ALWAYS(view); + return view; } /*! @@ -184,25 +279,7 @@ { CX_DEBUG_ENTER_FUNCTION(); - 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(); - - startupCheck(); - } else { + 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)), @@ -210,86 +287,132 @@ 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::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() +/*! +* Create view and add it to main window. +*/ +CxuiView* CxuiViewManager::createView(const QString &viewName) { CX_DEBUG_ENTER_FUNCTION(); - bool ok = false; - CX_DEBUG_ASSERT(mCameraDocumentLoader); - CxuiDocumentLoader *documentLoader = new CxuiDocumentLoader(&mEngine); - // Use document loader to create widgets and layouts - // (non-sectioned parts are parsed and loaded) - documentLoader->load(SCENEMODE_SETTING_XML, &ok); + OstTrace0( camerax_performance, CXUIVIEWMANAGER_CREATEVIEW, "msg: e_CX_CREATE_VIEW 1" ); + + CX_DEBUG(("View name: %s", viewName.toAscii().data())); - QGraphicsWidget *widget = NULL; + 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_DEBUG_ASSERT(mCameraDocumentLoader); + CX_ASSERT_ALWAYS(!docmlFile.isNull()); + + OstTrace0( camerax_performance, DUP2_CXUIVIEWMANAGER_ADDPRECAPTUREVIEWS, "msg: e_CX_DOCLOADER_LOAD 1" ); + + mCameraDocumentLoader->load(docmlFile, &ok); + + Q_ASSERT_X(ok, "createView", "error in xml file parsing"); + + OstTrace0( camerax_performance, DUP2_CXUIVIEWMANAGER_CREATEVIEW, "msg: e_CX_DOCLOADER_LOAD 0" ); - // ask for the scenes mode view widget pointer - widget = documentLoader->findWidget(STILL_SCENES_VIEW); - Q_ASSERT_X(ok && (widget != 0), "camerax ui", "invalid xml file"); - mSceneModeView = qobject_cast (widget); + OstTrace0( camerax_performance, DUP4_CXUIVIEWMANAGER_ADDVIEWS, "msg: e_CX_DOCLOADER_FINDWIDGET 1" ); + QGraphicsWidget *widget = NULL; + // ask for the view widget pointer + widget = mCameraDocumentLoader->findWidget(viewName); + view = qobject_cast (widget); + CX_DEBUG_ASSERT(view); + OstTrace0( camerax_performance, DUP5_CXUIVIEWMANAGER_ADDVIEWS, "msg: e_CX_DOCLOADER_FINDWIDGET 0" ); + + // 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, DUP1_CXUIVIEWMANAGER_MAINWINDOW_ADDVIEW, "msg: e_CX_MAINWINDOW_ADDVIEW 1" ); + mMainWindow.addView(view); + mViews.insert(viewName, view); - // call for needed construction methods - mSceneModeView->construct(&mMainWindow, &mEngine, documentLoader, mKeyHandler); - // .. and add to main window (which also takes ownership) - mMainWindow.addView(widget); + OstTrace0( camerax_performance, DUP2_CXUIVIEWMANAGER_MAINWINDOW_ADDVIEW, "msg: e_CX_MAINWINDOW_ADDVIEW 0" ); + OstTrace0( camerax_performance, DUP1_CXUIVIEWMANAGER_CREATEVIEW, "msg: e_CX_CREATE_STILLPRECAPTUREVIEW 0" ); + + } + + CX_DEBUG_EXIT_FUNCTION(); + return view; +} + +/*! +* Create scene mode view. +*/ +CxuiView* CxuiViewManager::createSceneModesView() +{ + CX_DEBUG_ENTER_FUNCTION(); + + mSceneModeView = qobject_cast(createView(STILL_SCENES_VIEW)); mSceneModeView->loadBackgroundImages(); - connect(mSceneModeView, SIGNAL(viewCloseEvent()), this, SLOT(changeToPrecaptureView())); - delete documentLoader; CX_DEBUG_EXIT_FUNCTION(); + return mSceneModeView; } /*! @@ -299,6 +422,9 @@ void CxuiViewManager::showScenesView() { CX_DEBUG_ENTER_FUNCTION(); + // Disconnect signals from old view. + disconnectSignals(); + if (!mSceneModeView) { createSceneModesView(); } @@ -306,141 +432,80 @@ mSceneModeView->loadBackgroundImages(); } CX_DEBUG_ASSERT(mSceneModeView); - mMainWindow.blockSignals(true); mMainWindow.setCurrentView(mSceneModeView, false); - emit disableStandbyTimer(); - connectCaptureKeySignals(); - mMainWindow.blockSignals(false); - CX_DEBUG_EXIT_FUNCTION(); -} - - -// --------------------------------------------------------------------------- -// CxuiViewManager::createVideoPrecaptureView -// -// --------------------------------------------------------------------------- -// -void CxuiViewManager::createVideoPrecaptureView() -{ - CX_DEBUG_ENTER_FUNCTION(); - OstTrace0( camerax_performance, CXUIVIEWMANAGER_CREATEVIDEOPRECAPTUREVIEW, "msg: e_CX_CREATE_VIDEOPRECAPTUREVIEW 1" ); - - CX_DEBUG_ASSERT(mCameraDocumentLoader); - - 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" ); + 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() +/*! +* Get a pointer to the document loader instance. +*/ +CxuiDocumentLoader *CxuiViewManager::documentLoader() { return mCameraDocumentLoader; } -// --------------------------------------------------------------------------- -// CxuiViewManager::changeToPostcaptureView -// -// --------------------------------------------------------------------------- -// +/*! +* Get reference to application state instance. +*/ +CxuiApplicationState &CxuiViewManager::applicationState() +{ + return *mApplicationState; +} + + +/*! +* 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(); @@ -453,33 +518,38 @@ this, SLOT(changeToPrecaptureView())); } - // If standby mode is active, don't switch to precapture view and reserve camera now. - if (mStandbyHandler->isActive()) { - CX_DEBUG(("CxuiViewManager - Change to precapture blocked as standby mode still active.")); + // 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.blockSignals(true); mMainWindow.setCurrentView(view, false); - mMainWindow.blockSignals(false); if (mSceneModeView){ + mViews.remove(STILL_SCENES_VIEW); delete mSceneModeView; mSceneModeView = NULL; } // connecting necessary pre-capture view signals connectPreCaptureSignals(); - emit startStandbyTimer(); + + // 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(); @@ -496,12 +566,8 @@ } CxuiPrecaptureView* view = getPrecaptureView(mEngine.mode(), nextCamera); - - mMainWindow.blockSignals(true); mMainWindow.setCurrentView(view, false); - mMainWindow.blockSignals(false); view->updateOrientation(nextViewOrientation); - view->prepareWindow(); connectPreCaptureSignals(); @@ -510,34 +576,190 @@ 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(); + if (view) { + if (view == mViews[POSTCAPTURE_VIEW]) { + connectPostCaptureSignals(); + } else if (view == mSceneModeView) { + connectSceneModeSignals(); + } else { + connectPreCaptureSignals(); + } + } + 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(); + + // 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); + } + + 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(); + + connectCaptureKeySignals(); + + // Standby signals for releasing camera + connect(this, SIGNAL(normalStateEntered()), mSceneModeView, SLOT(exitStandby())); + connect(this, SIGNAL(normalStateExited()), mSceneModeView, SLOT(enterStandby())); + + // Moving back to pre-capture view + connect(mSceneModeView, SIGNAL(viewCloseEvent()), this, SLOT(changeToPrecaptureView())); + + CX_DEBUG_EXIT_FUNCTION(); +} + +/*! +* Connect key handler capture key signals. +*/ void CxuiViewManager::connectCaptureKeySignals() { CX_DEBUG_ENTER_FUNCTION(); @@ -559,104 +781,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(showPopup(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(handleFocusGained()), 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); } /*! @@ -666,10 +800,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(); } @@ -677,112 +810,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; - } -} - -/*! -* Show or hide error popup based on change in USB mass memory mode activity. -* @param show Show the popup? -*/ -void CxuiViewManager::showUsbErrorPopup(bool show) -{ - CX_DEBUG_ENTER_FUNCTION(); - if (show) { - mStandbyHandler->enterStandby(); - mStandbyHandler->allowDismiss(false); - // Emulate "mass memory not accessible" error to Error Manager - // to get the same functionality as if the error came from CxEngine. - mErrorManager->showPopup(CxeError::MemoryNotAccessible); - } else { - mStandbyHandler->allowDismiss(true); - // If we are in postcapture view or scene view, we can return right away to normal mode. - // For precapture views we expect user action before reserving camera - // and starting viewfinder again. - QObject *currentView = mMainWindow.currentView(); - if (currentView == mPostcaptureView || currentView == mSceneModeView) { - mStandbyHandler->exitStandby(); - } - mErrorManager->hidePopup(CxeError::MemoryNotAccessible); - } - CX_DEBUG_EXIT_FUNCTION(); -} - -// --------------------------------------------------------------------------- -// 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(); - - // If standby mode is still active, no action is needed yet. - // This is the case when USB mass memory mode error is cleared. - if (mStandbyHandler->isActive()) { - CX_DEBUG(("CxuiViewManager - Focus gain event ignored as standby mode still active.")); - } else { - - // 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