phonebookui/pbkcommonui/src/cntfetchcontactsview.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Wed, 23 Jun 2010 18:02:44 +0300
changeset 46 efe85016a067
parent 40 b46a585f6909
child 47 7cbcb2896f0e
permissions -rw-r--r--
Revision: 201023 Kit: 2010125

/*
* 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 <hbdialog.h>
#include <hbscrollbar.h>
#include <hbindexfeedback.h>
#include <hbaction.h>
#include <hblabel.h>
#include <hbaction.h>
#include <hblineedit.h>
#include <hbmainwindow.h>
#include <hblistviewitem.h>
#include <hblistview.h>
#include <hbsearchpanel.h>
#include <hbstaticvkbhost.h>
#include <QGraphicsLinearLayout>
#include <qcontactid.h>
#include <cntlistmodel.h>
#include "cntfetchcontactsview.h"

/*!
Given a contact manager, CntFetchContacts is responsible for 
retrieving a set of contacts, if any were chosen by the user. 
*/
CntFetchContacts::CntFetchContacts(QContactManager *aManager) :
QObject(),
mPopup(NULL),
mCntModel(NULL),
mListView(NULL),
mEmptyListLabel(NULL),
mSelectionMode(HbAbstractItemView::MultiSelection),
mManager(aManager),
mWasCanceled(false),
mLabel(NULL),
mVirtualKeyboard(NULL),
mPrimaryAction(NULL),
mSecondaryAction(NULL),
mIndexFeedback(NULL)
{
    mSearchPanel = new HbSearchPanel();
    mSearchPanel->setVisible(false);
    mSearchPanel->setCancelEnabled(false);
    connect(mSearchPanel, SIGNAL(criteriaChanged(QString)), this, SLOT(setFilter(QString)));
    
    HbLineEdit *editor = static_cast<HbLineEdit*>(mSearchPanel->primitive("lineedit"));
    editor->setInputMethodHints(Qt::ImhNoPredictiveText);
    
    mLayout = new QGraphicsLinearLayout(Qt::Vertical);
    
    mContainerWidget = new HbWidget();
}

CntFetchContacts::~CntFetchContacts()
{
    delete mCntModel;
    mCntModel = NULL;
    
    delete mVirtualKeyboard;
    mVirtualKeyboard = NULL;
    
    delete mIndexFeedback;
    mIndexFeedback = NULL;
}

/*!
Query to see if the user decided to press Cancel after selecting 
group members. Must be called to see if results are valid.
*/
bool CntFetchContacts::wasCanceled() const
{
    return mWasCanceled;
}

void CntFetchContacts::setDetails(QString aTitle, QString aButtonText)
{
    mButtonText = aButtonText;
    
    if (!mLabel) {
        mLabel = new HbLabel(aTitle);
    }
}

/*!
Brings up a list of contacts, awaiting user response. This function is asynchronous.
When a response is given, a clicked signal will be sent.
*/
void CntFetchContacts::displayContacts(DisplayType aType, HbAbstractItemView::SelectionMode aMode, QSet<QContactLocalId> aContacts)
{
    switch (aType) {
    case view:
    {
        // TODO Currently only services will need a view 
        break;
    }

    case popup:
    {
        doInitialize(aMode,aContacts);
        markMembersInView();
        connectSignal();
        showPopup();
        
        mLayout->addItem(mSearchPanel);
        mContainerWidget->setLayout(mLayout);
        
        // Main window is NULL in unit tests
        HbMainWindow* window = mListView->mainWindow();
        if (window) {
            mContainerWidget->setPreferredHeight(mListView->mainWindow()->size().height());
        }
        mContainerWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
                
        break;
    }

    default:
        break;
    }
}

QSet<QContactLocalId> CntFetchContacts::getSelectedContacts() const
{
   return mCurrentlySelected;
}

void CntFetchContacts::setFilter(const QString &filterString)
{
    QStringList searchList = filterString.split(QRegExp("\\s+"), QString::SkipEmptyParts);

    QContactDetailFilter detailfilter;
    detailfilter.setDetailDefinitionName(QContactDisplayLabel::DefinitionName, QContactDisplayLabel::FieldLabel);
    detailfilter.setMatchFlags(QContactFilter::MatchStartsWith);
    detailfilter.setValue(searchList);
    
    mCntModel->setFilter(detailfilter);

    markMembersInView();

    if (mCntModel->rowCount() == 0) {
        mLayout->removeItem(mListView);
        
        if (mEmptyListLabel) {
            qreal searchHeight = mSearchPanel->size().height();
            HbLabel* heading = static_cast<HbLabel*>(mPopup->headingWidget());
            qreal heightToSet =  mPopup->size().height() - mVirtualKeyboard->keyboardArea().height() - searchHeight - heading->size().height();
            mEmptyListLabel->setMaximumHeight(heightToSet);
            mEmptyListLabel->setVisible(true);
            mLayout->insertItem(0, mEmptyListLabel);
        }

        mListView->setVisible(false);
        mSearchPanel->setVisible(true);
    }
    else {
        if (mEmptyListLabel) {
            mEmptyListLabel->setVisible(false);
        }
        mLayout->removeItem(mEmptyListLabel);
        mLayout->insertItem(0, mListView);
        mListView->setVisible(true);
    }
}

void CntFetchContacts::handleKeypadOpen()
{
    qreal searchHeight = mSearchPanel->size().height();
    HbLabel* heading = static_cast<HbLabel*>(mPopup->headingWidget());
    qreal heightToSet =  mPopup->size().height() - mVirtualKeyboard->keyboardArea().height() - searchHeight - heading->size().height();

    if (mEmptyListLabel) {
        mEmptyListLabel->setMaximumHeight( heightToSet - mEmptyListLabel->size().height() );
    }
    
    mListView->setMaximumHeight(heightToSet);
}

void CntFetchContacts::handleKeypadClose()
{
    mListView->setMaximumHeight(mPopup->size().height());

    if (mEmptyListLabel) {
        mEmptyListLabel->setMaximumHeight(mPopup->size().height());
    }
}

void CntFetchContacts::handleUserResponse(HbAction* action)
{
    HbDialog *popup = static_cast<HbDialog*>(sender());
    
    bool userCanceled = (action == mSecondaryAction); 
    if (popup && userCanceled) {
        mCurrentlySelected.clear();
        
        mWasCanceled = true;
    }
    else {
        mWasCanceled = false;
    }
    
    mPopup->setVisible(false);
    mListView->setModel(NULL);
    delete mCntModel;
    mCntModel = NULL;
    
    emit clicked();
}

void CntFetchContacts::memberSelectionChanged(const QModelIndex &index)
{
    if (!index.isValid()) return;

    if (mSelectionMode == HbAbstractItemView::SingleSelection) {
        mCurrentlySelected.clear();
    }

    QContactLocalId contactId = mCntModel->contact(index).localId();

    bool isSelected = mListView->selectionModel()->isSelected(index);
    if (isSelected != mCurrentlySelected.contains(contactId)) {
        if (isSelected) {
            mCurrentlySelected.insert(contactId);
        }
        else {
            mCurrentlySelected.remove(contactId);
        }
    }
    
    // Check for the case where there is a cancel button only. If so, 
    // after selecting any contact, should dismiss the dialog immediately.
    if (mButtonText.isEmpty() && mSelectionMode == HbAbstractItemView::SingleSelection) {
        mPopup->close();
    }
}

void CntFetchContacts::doInitialize(HbAbstractItemView::SelectionMode aMode,
                                                QSet<QContactLocalId> aContacts)
{
    mSelectionMode = aMode;
    mCurrentlySelected = aContacts;

    mSearchPanel->setVisible(true);

    if (!mPopup) {
        mPopup = new HbDialog;
    }

    QContactDetailFilter contactsFilter;
    contactsFilter.setDetailDefinitionName(QContactType::DefinitionName, QContactType::FieldType);
    contactsFilter.setValue(QString(QLatin1String(QContactType::TypeContact)));
    if (!mCntModel) {
        mCntModel = new CntListModel(mManager, contactsFilter, false);
    }
    
    if (!mListView) {
        mListView = new HbListView(mPopup);
        mListView->setModel(mCntModel);
        mListView->setSelectionMode(mSelectionMode);
        mListView->setFrictionEnabled(true);
        mListView->setScrollingStyle(HbScrollArea::PanWithFollowOn);
        mListView->verticalScrollBar()->setInteractive(true);

        HbListViewItem *prototype = mListView->listItemPrototype();
        prototype->setGraphicsSize(HbListViewItem::Thumbnail);
        prototype->setStretchingStyle(HbListViewItem::StretchLandscape);

        mIndexFeedback = new HbIndexFeedback(mPopup);
        mIndexFeedback->setIndexFeedbackPolicy(HbIndexFeedback::IndexFeedbackSingleCharacter);
        mIndexFeedback->setItemView(mListView);

        // Note that the layout takes ownership of the item(s) it contains.
        if (!mCntModel->rowCount()) {
            mListView->setVisible(false);
            if (!mEmptyListLabel) {
                mEmptyListLabel = new HbTextItem(hbTrId("txt_phob_info_no_matching_contacts"));
                mEmptyListLabel->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
                mEmptyListLabel->setFontSpec(HbFontSpec(HbFontSpec::Primary));
                mEmptyListLabel->setAlignment(Qt::AlignCenter);
                mLayout->insertItem(0, mEmptyListLabel);
            }
        }
        else {
            mLayout->addItem(mListView);
        }

        mCntModel->showMyCard(false);
    }
    
    // Handle the case where the model was removed for the list view
    if (!mListView->model()) {
        mListView->setModel(mCntModel);
    }
}

void CntFetchContacts::connectSignal()
{
    connect(mListView, SIGNAL(activated(const QModelIndex&)),
            this, SLOT(memberSelectionChanged(const QModelIndex&)));
}

void CntFetchContacts::showPopup()
{
    mPopup->setTimeout(HbPopup::NoTimeout);
    mPopup->setDismissPolicy(HbPopup::NoDismiss);
    mPopup->setModal(true);
    mPopup->setContentWidget(mContainerWidget);

    if (!mVirtualKeyboard) {
        mVirtualKeyboard = new HbStaticVkbHost(mPopup);
        connect(mVirtualKeyboard, SIGNAL(keypadOpened()), this, SLOT(handleKeypadOpen()));
        connect(mVirtualKeyboard, SIGNAL(keypadClosed()), this, SLOT(handleKeypadClose()));
    }
    
    if (!mLabel) {
        mLabel = new HbLabel(hbTrId("txt_phob_title_contacts"));
    }
    mPopup->setHeadingWidget(mLabel);

    if (!mButtonText.isEmpty() && !mPrimaryAction) {
        mPrimaryAction = new HbAction(hbTrId(mButtonText.toAscii()));
        mPopup->addAction(mPrimaryAction);
    }
    
    if (!mSecondaryAction) {
        mSecondaryAction = new HbAction(hbTrId("txt_common_button_cancel"));
        mPopup->addAction(mSecondaryAction);
    }

    mPopup->open(this, SLOT(handleUserResponse(HbAction*)));
}

void CntFetchContacts::markMembersInView()
{
    // If there are no contacts matching the current filter,
    // show "no matching contacts" label
    if (mCntModel->rowCount() == 0) {
        if (!mEmptyListLabel) {
            mEmptyListLabel = new HbTextItem(hbTrId("txt_phob_info_no_matching_contacts"));
            mEmptyListLabel->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
            mEmptyListLabel->setFontSpec(HbFontSpec(HbFontSpec::Primary));
            mEmptyListLabel->setAlignment(Qt::AlignCenter);
            mLayout->insertItem(1, mEmptyListLabel);
        }
    }
    else {
        mLayout->removeItem(mEmptyListLabel);
        delete mEmptyListLabel;
        mEmptyListLabel = 0;
    }

    // Mark group members in the listview
    foreach (QContactLocalId id, mCurrentlySelected) {
        QContact contact = mManager->contact(id);
        QModelIndex contactIndex = mCntModel->indexOfContact(contact);
        mListView->selectionModel()->select(contactIndex, QItemSelectionModel::Select);
    }
}

// End of file