taskswitcher/client/s60/src/tstaskmonitor_p.cpp
author hgs
Mon, 13 Sep 2010 13:26:33 +0300
changeset 116 305818acdca4
child 127 7b66bc3c6dc9
permissions -rw-r--r--
201036

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

#include <eikenv.h>
#include <fbs.h>
#include <s32mem.h>

#include <XQConversions>

#include "tstaskmonitorclient.h"
#include "tstask.h"
#include "tstaskcontent.h"
#include "tstaskchangeinfo.h"
#include "tsutils.h"
#include "tstaskmonitorhistory.h"
using TaskSwitcher::CleanupResetAndDestroyPushL;

TsTaskMonitorPrivate::TsTaskMonitorPrivate(TsTaskMonitor *q) : q_ptr(q), mClient(0), mWsSession(CEikonEnv::Static()->WsSession())
{
    QT_TRAP_THROWING(mClient = CTsTaskMonitorClient::NewL());
    mClient->Subscribe(*this);
}

TsTaskMonitorPrivate::~TsTaskMonitorPrivate()
{
    mClient->CancelSubscribe();
    delete mClient;
}


QList<TsTaskChange> TsTaskMonitorPrivate::changeList(bool fullList)
{
    QList<TsTaskChange> retVal;
     
    QT_TRAP_THROWING (

        HBufC8 *data = mClient->TasksContentLC();
        if (data->Size() == 0) {
            CleanupStack::PopAndDestroy(data);
            return retVal;
        }
        TPtr8 dataPointer(data->Des());
        RDesReadStream dataStream(dataPointer);
        CleanupClosePushL(dataStream);

        int count = dataStream.ReadInt32L();

        QT_TRYCATCH_LEAVING(
            QList< QSharedPointer<TsTaskContent> > taskList;
            QList<TsTaskMonitorHistory> newTaskHistory;
            for (int iter(0); iter < count; iter++) {
                QSharedPointer<TsTaskContent> content(new TsTaskContent);
                TsTaskMonitorHistory newHistoryItem = internalizeContentL(dataStream, content);
                newHistoryItem.setOffset(iter);
                newTaskHistory.append(newHistoryItem);
                taskList.append(content);
            }
            if (fullList) {
                mTaskHistory.clear();
            }
            QList<int> insertsList = findInserts(newTaskHistory);
            QList<int> deletesList = findDeletes(newTaskHistory);
            QList<TsTaskMonitorHistory> newMinusInserts;
            if (insertsList.count() > 0 ) {
                newMinusInserts = substractInsertsFromNew(insertsList, newTaskHistory);
            } else {
                newMinusInserts = newTaskHistory;
            }
            QList<TsTaskMonitorHistory> interimList;
            if (deletesList.count() > 0 ) {
                retVal.append(getDeletesChangeset(deletesList));
                interimList = substractDeletesFromOld(deletesList);
            } else {
                interimList = mTaskHistory;
            }
            retVal.append(findMovesAndUpdates(newMinusInserts, taskList, interimList));
            if (mTaskHistory.isEmpty()) {
                retVal.append(TsTaskChange(TsTaskChangeInfo(), QSharedPointer<TsTask>()));
            }
            retVal.append(getInsertsChangeset(insertsList, taskList));
            mTaskHistory = newTaskHistory;
        )//QT_TRYCATCH_LEAVING
        CleanupStack::PopAndDestroy(&dataStream);
        CleanupStack::PopAndDestroy(data);
    );//QT_TRAP_THROWING
       
    return retVal;
}

TsTaskMonitorHistory TsTaskMonitorPrivate::internalizeContentL(RDesReadStream &  dataStream,
                                    QSharedPointer<TsTaskContent> &content)
{
    // get name
    TInt nameLength(dataStream.ReadInt32L());
    if (0 < nameLength) {
        HBufC* name = HBufC::NewLC(dataStream, nameLength);
        content->mName = XQConversions::s60DescToQString(*name);
        CleanupStack::PopAndDestroy(name);
    }
    TPckgBuf<TTime> updateTime;
    dataStream.ReadL(updateTime);
    QDateTime historyTime =  dateTimeFromS60(updateTime());
    
    // get screenshot
    TInt screenshotHandle = dataStream.ReadInt32L();
    CFbsBitmap *screenshot = new (ELeave) CFbsBitmap;
    CleanupStack::PushL(screenshot);
    if (KErrNone == screenshot->Duplicate(screenshotHandle)) {
        content->mScreenshot = QPixmap::fromSymbianCFbsBitmap(screenshot);
    }
    CleanupStack::PopAndDestroy(screenshot);
    // get key
    TInt keyLength(dataStream.ReadInt32L());
    if (0 < keyLength) {
        HBufC8* key = HBufC8::NewLC(keyLength);
        TPtr8 des(key->Des());
        dataStream.ReadL(des, keyLength);
        content->mKey = XQConversions::s60Desc8ToQByteArray(*key);
        CleanupStack::PopAndDestroy(key);
    }
    // get other values
    content->mActive = dataStream.ReadInt32L();
    content->mClosable = dataStream.ReadInt32L();  
    return TsTaskMonitorHistory(content->mKey, historyTime);
}

QDateTime TsTaskMonitorPrivate::dateTimeFromS60(const TTime &s60Time)
{
    TTime posixEpoch(_L("19700000:"));
    TTimeIntervalSeconds secondsFrom;
    TTimeIntervalMicroSeconds microSecondsFrom;
    s60Time.SecondsFrom(posixEpoch, secondsFrom);
    microSecondsFrom = s60Time.MicroSecondsFrom(posixEpoch);
    QDateTime retVal = QDateTime::fromTime_t(secondsFrom.Int());
    retVal = retVal.addMSecs((microSecondsFrom.Int64() % TInt64(1000000) ) / TInt64(1000));
    return retVal;    
}

int TsTaskMonitorPrivate::findItemIndex(
                          const QList<TsTaskMonitorHistory> &historyList,
                          const TsTaskMonitorHistory &item )
{
    for (int iter(0); iter < historyList.count(); iter++) {
        if(historyList[iter].isEqual(item)) {
            return iter;
        }
    }
    return -1;
}

QList<int>  TsTaskMonitorPrivate::findInserts(
                                 const QList<TsTaskMonitorHistory> &newHistory)
{
    QList<int> retVal = QList<int>();
    for (int iter(0); iter < newHistory.count(); iter++) {
        if (findItemIndex(mTaskHistory, newHistory[iter]) == -1) {
            retVal.append(iter);
        }
    }
    return retVal;
}

QList<int> TsTaskMonitorPrivate::findDeletes(
                                 const QList<TsTaskMonitorHistory> &newHistory)
{
    QList<int> retVal = QList<int>();
    //iterate backwards to keep order during model operations
    for (int iter(mTaskHistory.count() -1); iter >= 0 ; iter--) {
        if (findItemIndex(newHistory, mTaskHistory[iter]) == -1) {
            retVal.append(iter);
        }
    }
    return retVal;    
}

QList<TsTaskChange> TsTaskMonitorPrivate::getDeletesChangeset(
                                                      const QList<int> &deleteList)
{
    QList<TsTaskChange> retVal;
    foreach (int index, deleteList) {
        TsTaskChangeInfo deleteChange(TsTaskChangeInfo::KInvalidOffset,
                                                                   index);
        retVal.append(TsTaskChange(deleteChange, QSharedPointer<TsTask>()));
    }
    return retVal;
}

QList<TsTaskChange> TsTaskMonitorPrivate::getInsertsChangeset(const QList<int> &insertList,
                                        const QList< QSharedPointer<TsTaskContent> > &taskList)
{
    QList<TsTaskChange> retVal;
    foreach (int index, insertList) {
        TsTaskChangeInfo insertChange(index,
                                 TsTaskChangeInfo::KInvalidOffset);
        retVal.append(TsTaskChange(
                            insertChange,
                            QSharedPointer<TsTask>(new TsTask(taskList[index], *this))));
    }
    return retVal;
}

QList<TsTaskMonitorHistory> TsTaskMonitorPrivate::substractInsertsFromNew(
                                      const QList<int> &insertList,
                                      const QList<TsTaskMonitorHistory> &newHistory )
{
    QList<TsTaskMonitorHistory> retVal(newHistory);
    for ( int iter(insertList.count() - 1); iter >= 0 ; iter--) {
        retVal.removeAt(insertList[iter]);
    }
    return retVal;
}

QList<TsTaskMonitorHistory> TsTaskMonitorPrivate::substractDeletesFromOld(
                                      const QList<int> &deleteList)
{
    QList<TsTaskMonitorHistory> retVal(mTaskHistory);  
    for (int iter(0); iter < deleteList.count() ; iter++) {
        retVal.removeAt(deleteList[iter]);
    }
    return retVal;
}

QList<TsTaskChange> TsTaskMonitorPrivate::findMovesAndUpdates( 
                                     const QList<TsTaskMonitorHistory> &newMinusInserts,
                                     const QList< QSharedPointer<TsTaskContent> > &taskList,
                                     QList<TsTaskMonitorHistory> &workingList)
{
    QList<TsTaskChange> retVal;
    for (int newPos(0); newPos < newMinusInserts.count(); newPos++) {
        //case 1 item has moved
        int previousPos = findItemIndex(workingList, newMinusInserts[newPos]);
        if (newPos != previousPos) {
            TsTaskChangeInfo moveChange(newPos, previousPos);
            retVal.append(
                TsTaskChange(moveChange, QSharedPointer<TsTask>()));
            workingList.move(previousPos, newPos);
        }
        // case 2 item has changed
        if (newMinusInserts[newPos].isUpdated(workingList[newPos])) {
            TsTaskChangeInfo updateChange(newPos, newPos);
            int taskListOffset = newMinusInserts[newPos].offset();
            retVal.append( TsTaskChange(
                              updateChange,
                              QSharedPointer<TsTask>(new TsTask(taskList[taskListOffset], *this)))); 
        }
    }
    return retVal;
}

void TsTaskMonitorPrivate::HandleRunningAppChange()
{
    emit q_ptr->taskListChanged();
}

void TsTaskMonitorPrivate::openTask(const QByteArray &key)
{
    TPtrC8 desC(reinterpret_cast<const TUint8*>(key.constData()), key.length());
    mClient->OpenTask(desC);
    
}

void TsTaskMonitorPrivate::closeTask(const QByteArray &key)
{
    TPtrC8 desC(reinterpret_cast<const TUint8*>(key.constData()), key.length());
    mClient->CloseTask(desC);
}