phonebookui/pbkcommonui/src/cntcollectionlistmodelworker.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 02 Sep 2010 20:16:15 +0300
changeset 65 ae724a111993
parent 59 a642906a277a
child 66 554fe4dbbb59
permissions -rw-r--r--
Revision: 201033 Kit: 201035

/*
* 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 "cntcollectionlistmodelworker.h"
#include "cntfavourite.h"
#include "cntdebug.h"

#include <hbglobal.h>
#include <hbapplication.h>

#include <cntuids.h>
#include <xqsettingskey.h>

// CONSTANTS
const int CntNamesLengthLimit = 30;

/*!
    Constructor
*/
CntCollectionListModelWorker::CntCollectionListModelWorker(QString unnamed, QString noFavs, QString noMembers, int sortOrder) :
    mStarted(false),
    mProcessingJobs(false),
    mStopped(false),
    mManager(NULL),
    mUnnamed(unnamed),
    mNoFavorites(noFavs),
    mNoMembers(noMembers),
    mSortOrder(sortOrder)
{
    CNT_ENTRY
    
    moveToThread(this);
    
    CNT_EXIT
}

/*!
    Destructor
    
    Clears any remaining jobs and waits until the last one gets completed.
*/
CntCollectionListModelWorker::~CntCollectionListModelWorker()
{
    CNT_ENTRY
    
    mMutex.lock();
    
    mJobs.clear();
    
    mMutex.unlock();

    exit();
    
    // Ugly as hell, but needed for UTs or otherwise they'll freeze
#ifndef PBK_UNIT_TEST
    wait();
#else
    wait(5000);
#endif

    CNT_EXIT
}

/*!
    Re-implemented from QThread, start the event loop.
*/
void CntCollectionListModelWorker::run()
{
    CNT_ENTRY

    exec();
    
    delete mManager;
    mManager = NULL;
    
    CNT_EXIT
}

/*!
    Re-implemented from QThread to capture QEvent::User type events
    in order to start the job processing loop.

    \param event the event sent to this object
    \return bool
*/
bool CntCollectionListModelWorker::event(QEvent *event)
{
    if (event->type() == QEvent::User)
    {
        processJobs();
        return true;
    }

    return QThread::event(event);
}

/*!
    Schedule an asynch job for the given contact id.

    \param id the QContactLocalId of the group
*/
void CntCollectionListModelWorker::scheduleJob(int id)
{
    CNT_ENTRY
    
    mMutex.lock();

    if (!mStarted) {
        // starting the event loop; minimum priority is used as this thread
        // should interfere as little as possible with more time-critical tasks,
        // like updating the UI during scrolling
        start(QThread::IdlePriority);
        mStarted = true;
    }

    if (!mProcessingJobs) {
        // new job => start processing jobs
        mProcessingJobs = true;
        HbApplication::instance()->postEvent(this, new QEvent(QEvent::User));
    }

    mJobs.append(id);
    
    mMutex.unlock();
    
    CNT_EXIT
}

/*!
    Job processing loop. Loops forever until there are no more jobs left.
    If jobs exist, takes the first one from the list and processes it.
*/
void CntCollectionListModelWorker::processJobs()
{
    CNT_ENTRY
    
    forever
    {
        mMutex.lock();
        int jobCount = mJobs.count();

        if (jobCount == 0)
        {
            mProcessingJobs = false;
            mMutex.unlock();
            break;
        }
        else
        {
            // get next job
            int id = mJobs.takeFirst();

            mMutex.unlock();
            fetchInformation(id);
        }

        HbApplication::processEvents();
    }
    
    CNT_EXIT
}

/*!
    Fetch the second row text (member names or placeholder text if no members exist)
    and the amount of contacts in the group. Emits the result as a signal for
    CntCollectionListModel to handle.

    \param id the QContactLocalId of the group in the given row
*/
void CntCollectionListModelWorker::fetchInformation(int id)
{
    CNT_ENTRY
    
    if (!mManager)
    {
        mManager = new QContactManager("symbian");
    }
    
    QContact contact = mManager->contact(id);

    int favoriteGroupId = CntFavourite::favouriteGroupId( mManager );

    QString secondLineText;
    int memberCount = 0;

    QContactRelationshipFilter rFilter;
    rFilter.setRelationshipType(QContactRelationship::HasMember);
    rFilter.setRelatedContactRole(QContactRelationship::First);
    rFilter.setRelatedContactId(contact.id());

    QContactSortOrder sortOrderFirstName;
    sortOrderFirstName.setDetailDefinitionName(QContactName::DefinitionName,
            QContactName::FieldFirstName);
    sortOrderFirstName.setCaseSensitivity(Qt::CaseInsensitive);

    QContactSortOrder sortOrderLastName;
    sortOrderLastName.setDetailDefinitionName(QContactName::DefinitionName,
            QContactName::FieldLastName);
    sortOrderLastName.setCaseSensitivity(Qt::CaseInsensitive);
    
    QList<QContactSortOrder> sortOrders;

    if (mSortOrder == CntOrderFirstLast)
    {
        sortOrders.append(sortOrderFirstName);
        sortOrders.append(sortOrderLastName);
    } 
    else
    {
        sortOrders.append(sortOrderLastName);
        sortOrders.append(sortOrderFirstName);
    }

    // group members and their count
    QList<QContactLocalId> groupMemberIds = mManager->contactIds(rFilter, sortOrders);

    if (!groupMemberIds.isEmpty())
    {
        QStringList nameList;
        for(int i = 0;i < groupMemberIds.count();i++)
        {
            QContactFetchHint nameOnlyFetchHint;
            /*QStringList details;
            details << QContactDisplayLabel::DefinitionName;
            nameOnlyFetchHint.setDetailDefinitionsHint(details);*/
            nameOnlyFetchHint.setOptimizationHints(QContactFetchHint::NoRelationships);

            QContact contact = mManager->contact(groupMemberIds.at(i), nameOnlyFetchHint);
            QString memberName = contact.displayLabel();
            if (memberName.isEmpty())
            {
                memberName = mUnnamed;
            }

            // Incase the format is LastnameCommaFirstname, remove the commas
            memberName = memberName.replace(", ", " ");
            nameList << memberName;
            if (nameList.join(", ").length() > CntNamesLengthLimit)
            {
                break;
            }
        }
        QString names = nameList.join(", ").trimmed();

        secondLineText = names;
        memberCount = groupMemberIds.count();
    }
    else
    {
        if (id == favoriteGroupId)
        {
            secondLineText = mNoFavorites;
        }
        else
        {
            secondLineText = mNoMembers;
        }
    }

    emit fetchDone(id, secondLineText, memberCount);
    
    CNT_EXIT
}