camerauis/cameraxui/cxengine/src/cxesettingsimp.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 31 Aug 2010 15:03:46 +0300
branchRCL_3
changeset 53 61bc0f252b2b
permissions -rw-r--r--
Revision: 201033 Kit: 201035

/*
* Copyright (c) 2009-2010 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:
*
*/
/*
* Symbian specific settings handling
*/

#include <QCoreApplication>
#include <QVariant>
#include <QList>
#include <QMetaType>
#include <QObject>

#include "cxesettingsimp.h"
#include "cxutils.h"
#include "cxenamespace.h"
#include "cxeerror.h"
#include "cxesettingsstore.h"
#include "cxeexception.h"

#ifdef Q_OS_SYMBIAN
#include "OstTraceDefinitions.h"
#ifdef OST_TRACE_COMPILER_IN_USE
#include "cxesettingsimpTraces.h"
#endif
#endif // Q_OS_SYMBIAN


// signatures for setting listener slots
const char *SETTING_LISTENER_SIGNATURE1 = "settingChanged(const QString &, const QVariant &)";
const char *SETTING_LISTENER_SIGNATURE2 = "settingChanged(const QVariant &)";


/*
* CxeSettingsImp::CxeSettingsImp
*/
CxeSettingsImp::CxeSettingsImp(CxeSettingsStore *settingStore)
: mSettingStore(settingStore),
  mVariationSettings(),
  mSceneModeStore(),
  mCameraMode(Cxe::ImageMode)
{
    CX_DEBUG_ENTER_FUNCTION();
    loadVariationSettings();

    CX_DEBUG_EXIT_FUNCTION();
}

/*
* CxeSettingsImp::close
*/
CxeSettingsImp::~CxeSettingsImp()
{
    CX_DEBUG_ENTER_FUNCTION();
    delete mSettingStore;

    mVariationSettings.clear();
    mSettingListeners.clear();
    CX_DEBUG_EXIT_FUNCTION();
}

/*
* Reads a value from cenrep
* @param key   - setting key
* @param uid   - setting UID of the component that owns the setting key
* @param type  - the type of key cr key or P&S key (constantly monitoring value)
* @param value - setting value read from cenrep
*/

void CxeSettingsImp::get(long int uid,
                         unsigned long int key,
                         Cxe::SettingKeyType type,
                         QVariant &value) const
{
    CX_DEBUG_ENTER_FUNCTION();
    CX_DEBUG_ASSERT(mSettingStore);

    mSettingStore->startMonitoring(uid, key, type, value);

    CX_DEBUG_EXIT_FUNCTION();

}


/*!
    Reset static settings (persistent settings)
*/
void CxeSettingsImp::reset()
{
    CX_DEBUG_ENTER_FUNCTION();

    CX_DEBUG_ASSERT(mSettingStore);
    mSettingStore->reset();

    CX_DEBUG_EXIT_FUNCTION();
}

/*!
* Get the configured run-time value associated with the key.
* @Param key - Setting key Id ( refer to CxeSettingIds in cxenums.h )
* @Param value - contains the value associated with the key.
* @returns CxeError::None if successful or any CxeError specific error code.
*/
CxeError::Id CxeSettingsImp::getVariationValue(const QString &key, QVariant &value)
{
    CX_DEBUG_ENTER_FUNCTION();

    CxeError::Id err = CxeError::None;

    // read run-time configuration value
    if ( mVariationSettings.contains(key) ) {
        value = qVariantFromValue<QVariantList > (mVariationSettings.value(key));
    } else {
        err = CxeError::NotFound;
    }

    CX_DEBUG_EXIT_FUNCTION();

    return err;
}


/*!
 * Add listener for changes in one setting. When the value of the setting changes, the given
 * slot is invoked on given object.
 * The validity of the settingKey is not checked.
 *
 * @param settingKey Setting to listen to
 * @param target Object that the slot will be invoked for
 * @param slot Slot that will be invoked. The slot can have either of these two signatures:
 *   slotName(const QVariant&)    only new value of setting is passed as parameter
 *   slotName(const QString&, const QVariant&) both setting key and new value are passed as parameter
 *
 * @return boolean to indicate success
 *
 */
bool CxeSettingsImp::listenForSetting(const QString &settingKey, QObject *target, const char *slot)
{

    CX_DEBUG_ENTER_FUNCTION();
    CX_DEBUG_ASSERT(target && slot);

    // SLOT() macro adds '1' to the beginning of string so we use slot+1 to get the name of the slot
    CX_DEBUG(("Adding listener %s::%s for key %s", target->metaObject()->className(), slot+1, settingKey.toAscii().data()));
    QByteArray normalizedSlotName = QMetaObject::normalizedSignature(slot+1);

    int slotIndex = target->metaObject()->indexOfSlot(normalizedSlotName);

    bool ok = false;
    if (slotIndex > -1) {
        CX_DEBUG(("Slot found, checking signature"));
        // verify that slot is correct type
        if (QMetaObject::checkConnectArgs(QMetaObject::normalizedSignature(SETTING_LISTENER_SIGNATURE1), normalizedSlotName) ||
            QMetaObject::checkConnectArgs(QMetaObject::normalizedSignature(SETTING_LISTENER_SIGNATURE2), normalizedSlotName)) {

            CX_DEBUG(("Slot signature ok, adding listener"));

            // check if list for given key already exists
            if (!mSettingListeners.contains(settingKey)) {
                mSettingListeners.insert(settingKey, CxeSettingListenerList());
            }

            // get QMetaMethod object
            QMetaMethod method = target->metaObject()->method(slotIndex);
            // add listener to the list
            CxeSettingListenerList& list = mSettingListeners[settingKey];
            list.append(CxeSettingListener(target, method));

            // connect to destroyed() signal so we can remove listener if it's deleted
            connect(target, SIGNAL(destroyed(QObject*)), this, SLOT(handleListenerDestroyed(QObject*)));

            ok = true;
        } else {
            CX_DEBUG(("Slot signature doesn't match, can't add listener"));
        }

    } else {
        CX_DEBUG(("Slot not found, can't add listener"));
    }

    CX_DEBUG_EXIT_FUNCTION();
    return ok;
}

/*!
    Load image/video specific settings during mode change or startup
*/
void CxeSettingsImp::loadSettings(Cxe::CameraMode mode)
{
    CX_DEBUG_ENTER_FUNCTION();
    OstTrace0(camerax_performance, CXESETTINGSIMP_LOADSETTINGS_IN, "msg: e_CX_SETTINGS_LOADSETTINGS 1");

    mCameraMode = mode;

    // inform the settings model for the change in mode.
    if (mode == Cxe::ImageMode) {
        restoreImageSettings();
        notifyListeners(CxeSettingIds::IMAGE_SCENE_DATA, mSceneModeStore.currentScene(Cxe::ImageMode));
        notifyListeners(CxeSettingIds::IMAGE_SCENE, mSceneModeStore.currentSceneId(Cxe::ImageMode));
        emit settingValueChanged(CxeSettingIds::IMAGE_SCENE, mSceneModeStore.currentSceneId(Cxe::ImageMode));
    } else {
        restoreVideoSettings();
        notifyListeners(CxeSettingIds::VIDEO_SCENE_DATA, mSceneModeStore.currentScene(Cxe::VideoMode));
        notifyListeners(CxeSettingIds::VIDEO_SCENE, mSceneModeStore.currentSceneId(Cxe::VideoMode));
        emit settingValueChanged(CxeSettingIds::VIDEO_SCENE, mSceneModeStore.currentSceneId(Cxe::VideoMode));
    }

    OstTrace0(camerax_performance, CXESETTINGSIMP_LOADSETTINGS_OUT, "msg: e_CX_SETTINGS_LOADSETTINGS 0");
    CX_DEBUG_EXIT_FUNCTION();
}

/*!
* Get setting value associated with the key.
* @Param key - Setting key Id ( refer to CxeSettingIds in cxenums.h )
* @Param value - contains the value associated with the key.
* @returns CxeError::None if successful or any CxeError specific error code.
*/
void CxeSettingsImp::getValue(const QString &key, QVariant &value) const
{
    CX_DEBUG_ENTER_FUNCTION();
    CX_DEBUG_ASSERT(mSettingStore);


    CxeError::Id err = CxeError::None;

    // check if getting scene mode
    if(key == CxeSettingIds::IMAGE_SCENE_DATA) {
        value = mSceneModeStore.currentScene(Cxe::ImageMode);
    } else if(key == CxeSettingIds::VIDEO_SCENE_DATA) {
        value = mSceneModeStore.currentScene(Cxe::VideoMode);
    } else {
        // Try first to find the item from cenrep store.
        err = mSettingStore->get(key, value);

        // If setting is not in cenrep store, try fetching it from scene settings.
        if (!err) {
            CX_DEBUG(("Got value %s from settings store", value.toString().toAscii().data()));
        } else {
            // setting not found in setting store, try finding if its scene specific setting.
            CX_DEBUG(( "fetching value from scene settings" ));
            err = mSceneModeStore.sceneSettingValue(mCameraMode, key, value);
        }
        if (err) {
            throw CxeException(err);
        }
    }

    CX_DEBUG_EXIT_FUNCTION();

}

/*!
* Set a value to the key.
* @Param key - Setting key Id ( refer to CxeSettingIds in cxenums.h )
* @Param value - contains the value associated with the key.
* @returns CxeError::None if successful or any CxeError specific error code.
*/
void CxeSettingsImp::setValue(const QString &key, const QVariant &newValue)
{
    CX_DEBUG_ENTER_FUNCTION();
    CX_DEBUG_ASSERT(mSettingStore);

    CxeError::Id err;
    // check if setting scene mode
    if(key == CxeSettingIds::IMAGE_SCENE) {
        setImageScene(newValue.toString());
    } else if(key == CxeSettingIds::VIDEO_SCENE) {
        setVideoScene(newValue.toString());
    } else if(key == CxeSettingIds::IMAGE_SCENE_DATA || key == CxeSettingIds::VIDEO_SCENE_DATA) {
        // setting whole scene by value is not supported
        throw CxeException(CxeError::NotSupported);
    } else {
        // Try storing new value to cenrep
        err = mSettingStore->set(key, newValue);

        if (err) {
            CX_DEBUG(( "Key not found in cenrepstore, writing value to scene settings" ));
            err = mSceneModeStore.setSceneSettingValue(mCameraMode, key, newValue);
        }

        if (err) {
            throw CxeException(err);
        }

        // send notifications
        emit settingValueChanged(key, newValue);
        notifyListeners(key, newValue);
    }

    CX_DEBUG_EXIT_FUNCTION();

}

/*!
* Restores image settings, during mode change or during startup.
*/
void CxeSettingsImp::restoreImageSettings()
{
    CX_DEBUG_ENTER_FUNCTION();

    QString currentSceneInUse = mSceneModeStore.currentSceneId(Cxe::ImageMode);

    // get the image scene value from cenrep and load the scene settings
    QString key(CxeSettingIds::IMAGE_SCENE);
    QString cenrepSceneValue = CxeSettings::get<QString>(key);

    bool ok2LoadSceneSettings = (cenrepSceneValue != currentSceneInUse);

    if (ok2LoadSceneSettings) {
        // loading scene settings
        mSceneModeStore.setCurrentScene(Cxe::ImageMode, cenrepSceneValue);
    }

    // Updating Flash setting from cenrep
    key = CxeSettingIds::FLASH_MODE;
    int flashMode = CxeSettings::get<int>(key);

    // update local datastructure with flash setting value from cenrep.
    CX_DEBUG(( "flash setting value %d", flashMode));
    mSceneModeStore.setSceneSettingValue(Cxe::ImageMode, key, flashMode);

    // Updating Face Tracking setting from cenrep
    key = CxeSettingIds::FACE_TRACKING;
    int faceTracking = CxeSettings::get<int>(key);

    // update local datastructure with flash setting value from cenrep.
    CX_DEBUG(( "Face Tracking setting value %d", faceTracking));
    mSceneModeStore.setSceneSettingValue(Cxe::ImageMode, key, faceTracking);


    CX_DEBUG_EXIT_FUNCTION();
}


/*!
* Restores video settings, during mode change or during startup.
*/
void CxeSettingsImp::restoreVideoSettings()
{
    CX_DEBUG_ENTER_FUNCTION();

    QString currentSceneInUse = mSceneModeStore.currentSceneId(Cxe::VideoMode);

    // get the video scene value from cenrep and load the scene settings
    QString cenrepSceneValue = CxeSettings::get<QString>(CxeSettingIds::VIDEO_SCENE);

    bool ok2LoadSceneSettings = (cenrepSceneValue != currentSceneInUse);

    if (ok2LoadSceneSettings) {
        // loading video scene settings
        mSceneModeStore.setCurrentScene(Cxe::VideoMode, cenrepSceneValue);
    }

    CX_DEBUG_EXIT_FUNCTION();
}

/*!
* Set new Image scene mode.
* @returns CxeError::None if successful or any CxeError specific error code.
*/
void CxeSettingsImp::setImageScene(const QString &newScene)
{
    CX_DEBUG_ENTER_FUNCTION();

    // load scene specific settings
    mSceneModeStore.setCurrentScene(Cxe::ImageMode, newScene);

    // saving current image scene to cenrep
    CxeError::Id err = mSettingStore->set(CxeSettingIds::IMAGE_SCENE, newScene);
    CxeException::throwIfError(err);

    // saving flash value from scene to cenrep
    // call CxeSettingStore::set directly because we don't want to send notifications
    // about these changes
    QString key(CxeSettingIds::FLASH_MODE);
    err = mSettingStore->set(key, mSceneModeStore.currentScene(Cxe::ImageMode)[key].toInt());

    CxeException::throwIfError(err);
    // saving face tracking value from scene to cenrep
    key = CxeSettingIds::FACE_TRACKING;
    err = mSettingStore->set(key, mSceneModeStore.currentScene(Cxe::ImageMode)[key].toInt());
    CxeException::throwIfError(err);

    // send notifications
    emit settingValueChanged(CxeSettingIds::IMAGE_SCENE, mSceneModeStore.currentSceneId(Cxe::ImageMode));
    notifyListeners(CxeSettingIds::IMAGE_SCENE, mSceneModeStore.currentSceneId(Cxe::ImageMode));
    notifyListeners(CxeSettingIds::IMAGE_SCENE_DATA, mSceneModeStore.currentScene(Cxe::ImageMode));

    CX_DEBUG_EXIT_FUNCTION();

}

/*!
* Set new video scene mode.
* @returns CxeError::None if successful or any CxeError specific error code.
*/
void CxeSettingsImp::setVideoScene(const QString &newScene)
{
    CX_DEBUG_ENTER_FUNCTION();

    mSceneModeStore.setCurrentScene(Cxe::VideoMode, newScene);

    // video scene set successfully, store the scene value to cenrep
    CxeError::Id err = mSettingStore->set(CxeSettingIds::VIDEO_SCENE, newScene);
    CxeException::throwIfError(err);

    emit settingValueChanged(CxeSettingIds::VIDEO_SCENE, mSceneModeStore.currentSceneId(Cxe::VideoMode));
    notifyListeners(CxeSettingIds::VIDEO_SCENE, mSceneModeStore.currentSceneId(Cxe::VideoMode));
    notifyListeners(CxeSettingIds::VIDEO_SCENE_DATA, mSceneModeStore.currentScene(Cxe::VideoMode));

    CX_DEBUG_EXIT_FUNCTION();

}

/*!
* Loads all run-time variation settings
*/
void CxeSettingsImp::loadVariationSettings()
{
    CX_DEBUG_ENTER_FUNCTION();
    CX_DEBUG_ASSERT( mSettingStore );

    QList<QString> variationKeys;
    // all supported runtime variation keys are fetched from here.
    variationKeys.append(CxeVariationKeys::FREE_MEMORY_LEVELS);
    variationKeys.append(CxeVariationKeys::STILL_MAX_ZOOM_LIMITS);
    variationKeys.append(CxeVariationKeys::VIDEO_MAX_ZOOM_LIMITS);

    // load all run-time setting values from cenrep.
    mVariationSettings = mSettingStore->loadVariationSettings(variationKeys);

    CX_DEBUG_EXIT_FUNCTION();
}

/*!
 * Notify setting listeners that setting has changed
 * @param settingKey Setting that has changed
 * @param newValue New value of the setting
 */
void CxeSettingsImp::notifyListeners(const QString &settingKey, const QVariant &newValue)
{
    CX_DEBUG_ENTER_FUNCTION();

    CX_DEBUG(("CxeSettingsImp::notifyListeners settingKey=%s", settingKey.toAscii().data()));

    if (mSettingListeners.contains(settingKey)) {
        CX_DEBUG(("Listeners found"));
        // get list of listener
        CxeSettingListenerList& list = mSettingListeners[settingKey];

        // iterate through the list and call all listeners
        CxeSettingListenerList::const_iterator i = list.constBegin();
        for(; i != list.constEnd(); ++i) {

            QObject *object = (*i).first;
            QMetaMethod slot = (*i).second;

            CX_DEBUG_ASSERT(object);

            // invoke the slot
            CX_DEBUG(("Calling slot %s::%s", object->metaObject()->className(), slot.signature()));

            bool ok = false;
            if (slot.parameterTypes().size() == 2) {
                // slot has two parameters, send settingKey as well
                ok = slot.invoke(object,
                                  Qt::AutoConnection,
                                  Q_ARG(QString, settingKey),
                                  Q_ARG(QVariant, newValue));
            } else {
                // don't send settingKey as parameter
                ok = slot.invoke(object,
                                 Qt::AutoConnection,
                                 Q_ARG(QVariant, newValue));
            }

            if (!ok) {
                CX_DEBUG(("QMetaMethod::invoke() failed, listener not notified"))
            }

        }

    } else {
        CX_DEBUG(("NO listeners found"));
    }



    CX_DEBUG_EXIT_FUNCTION();
}

/*!
 * Handle deletion of registered listener.
 */
void CxeSettingsImp::handleListenerDestroyed(QObject *object)
{
    CX_DEBUG_ENTER_FUNCTION();

    QList<QString> keyList = mSettingListeners.keys();

    for (int i = 0; i < keyList.size(); i++) {

        QString key = keyList[i];
        CxeSettingListenerList& list = mSettingListeners[key];

        for (int j = 0; j < list.size(); j++) {
            CxeSettingListener &listener = list[j];
            if (listener.first == object) {
                list.removeAt(j--);
            }
        }

        // removed last listener for this key
        if (list.size() == 0) {
            mSettingListeners.remove(key);
        }
    }

    CX_DEBUG_EXIT_FUNCTION();
}

// end of file