phonebookui/pbkcommonui/src/cntnamesview_p.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Mon, 03 May 2010 12:24:20 +0300
changeset 27 de1630741fbe
parent 25 76a2435edfd4
child 31 2a11b5b00470
permissions -rw-r--r--
Revision: 201015 Kit: 201018

/*
* 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 "cntnamesview_p.h"
#include "cntaction.h"
#include "cntextensionmanager.h"
#include "qtpbkglobal.h"

#include <cntuiextensionfactory.h>
#include <cntuisocialextension.h>

#include <qapplication.h>
#include <hbabstractviewitem.h>
#include <hbaction.h>
#include <hbnotificationdialog.h>
#include <hbmenu.h>
#include <hbtoolbar.h>
#include <hbmainwindow.h>
#include <hbview.h>
#include <hbtextitem.h>
#include <hbdocumentloader.h>
#include <hblistview.h>
#include <hblistviewitem.h>
#include <hbindexfeedback.h>
#include <hbscrollbar.h>
#include <hbgroupbox.h>
#include <hbsearchpanel.h>
#include <hbtoolbar.h>
#include <hbframebackground.h>
#include <hbstaticvkbhost.h>
#include <hbmessagebox.h>

#include <QGraphicsLinearLayout>
#include <QList>

const char *CNT_CONTACTLIST_XML = ":/xml/contacts_namelist.docml";

CntNamesViewPrivate::CntNamesViewPrivate(CntExtensionManager &extensionManager) :
    QObject(),
    mExtensionManager(extensionManager),
    mViewManager(NULL),
    mListModel(NULL),
    mListView(NULL),
	mEmptyList(NULL),
    mBanner(NULL),
    mSearchPanel(NULL),
    mLoader(NULL),
    mLayout(NULL),
    mMenuBuilder(NULL),
    mIsDefault(true),
    mId( namesView )
{
    bool ok;
    document()->load( CNT_CONTACTLIST_XML, &ok);
    if (!ok) {
        qFatal("Unable to read %S", CNT_CONTACTLIST_XML);
    }
    mView = static_cast<HbView*> (document()->findWidget("view"));

    mVirtualKeyboard = new HbStaticVkbHost(mView);
    connect(mVirtualKeyboard, SIGNAL(keypadOpened()), this, SLOT(handleKeypadOpen()));
    connect(mVirtualKeyboard, SIGNAL(keypadClosed()), this, SLOT(handleKeypadClose()));
    
    mSoftkey = new HbAction(Hb::BackNaviAction, mView);
       
    HbAction* newContact = static_cast<HbAction*> (document()->findObject("cnt:newcontact"));
    HbAction* findContacts = static_cast<HbAction*> (document()->findObject("cnt:find"));
    HbAction* groups = static_cast<HbAction*> (document()->findObject("cnt:groups"));
    HbAction* importSim = static_cast<HbAction*> (document()->findObject("cnt:importsim"));
    
    HbAction* extension = static_cast<HbAction*> (document()->findObject("cnt:activity"));
       
    connect(mSoftkey, SIGNAL(triggered()), this, SLOT(showPreviousView()));
    connect(newContact, SIGNAL(triggered()), this, SLOT(createNewContact()));
    connect(findContacts, SIGNAL(triggered()), this, SLOT(showFinder()));
    connect(groups, SIGNAL(triggered()), this, SLOT(showCollectionView()));
    connect(importSim, SIGNAL(triggered()), this, SLOT(importSim()));
    connect(extension, SIGNAL(triggered()), this, SLOT(handleExtensionAction()));
    connect(list(), SIGNAL(longPressed(HbAbstractViewItem*,QPointF)), this,
           SLOT(showContextMenu(HbAbstractViewItem*,QPointF)));
    connect(list(), SIGNAL(activated (const QModelIndex&)), this,
           SLOT(showContactView(const QModelIndex&)));
       
}

CntNamesViewPrivate::~CntNamesViewPrivate()
{
    mView->deleteLater();

    delete mListModel;
    mListModel = NULL;

    delete mListView;
    mListView = NULL;

    delete mSearchPanel;
    mSearchPanel = NULL;

    delete mEmptyList;
    mEmptyList = NULL;

    delete mBanner;
    mBanner = NULL;

    delete mLoader;
    mLoader = NULL;

    delete mVirtualKeyboard;
    mVirtualKeyboard = NULL;
    
    delete mMenuBuilder;
    mMenuBuilder = NULL;
}

void CntNamesViewPrivate::activate(CntAbstractViewManager* aMgr, const CntViewParameters aArgs)
{
    mViewManager = aMgr;
    if (!mListModel) {
        QContactSortOrder sortOrderFirstName;
        sortOrderFirstName.setDetailDefinitionName(QContactName::DefinitionName,
            QContactName::FieldFirst);
        sortOrderFirstName.setCaseSensitivity(Qt::CaseInsensitive);

        QContactSortOrder sortOrderLastName;
        sortOrderLastName.setDetailDefinitionName(QContactName::DefinitionName,
            QContactName::FieldLast);
        sortOrderLastName.setCaseSensitivity(Qt::CaseInsensitive);

        QList<QContactSortOrder> sortOrders;
        sortOrders.append(sortOrderFirstName);
        sortOrders.append(sortOrderLastName);

        QContactDetailFilter filter;
        filter.setDetailDefinitionName(QContactType::DefinitionName, QContactType::FieldType);
        QString typeContact = QContactType::TypeContact;
        filter.setValue(typeContact);

        mListModel = new MobCntModel(mViewManager->contactManager(SYMBIAN_BACKEND), filter, sortOrders);
    }

    list()->setModel(mListModel);

    mMenuBuilder = new CntActionMenuBuilder( mListModel->myCardId() );
    connect( mMenuBuilder, SIGNAL(deleteContact(QContact&)), this, SLOT(deleteContact(QContact&)) );
    connect( mMenuBuilder, SIGNAL(editContact(QContact&)), this, SLOT(showContactEditorView(QContact&)) );
    connect( mMenuBuilder, SIGNAL(openContact(QContact&)), this, SLOT(showContactView(QContact&)) );
    connect( mMenuBuilder, SIGNAL(performContactAction(QContact&,QString)), this, SLOT(executeAction(QContact&,QString)));
        
    if ( mView->navigationAction() != mSoftkey)
    {
        mView->setNavigationAction(mSoftkey);
    }
    
    QContactManager* contactManager = aMgr->contactManager( SYMBIAN_BACKEND );
    QString action = aArgs.value(ESelectedAction).toString();
    if ( action == "save" )
    {
        QString name = contactManager->synthesizedDisplayLabel( aArgs.value(ESelectedContact).value<QContact>() );
        HbNotificationDialog::launchDialog(qtTrId("Contact \"%1\" saved").arg(name));

        scrollTo( aArgs.value(ESelectedContact).value<QContact>() );
    }
           
    else if ( action == "delete" )
    {
        QString name = contactManager->synthesizedDisplayLabel( aArgs.value(ESelectedContact).value<QContact>() );
        HbNotificationDialog::launchDialog(qtTrId("%1 deleted").arg(name));
    }    
    else if ( action == "failed")
    {
        HbNotificationDialog::launchDialog(qtTrId("SAVING FAILED!"));
    }
}

void CntNamesViewPrivate::deactivate()
{
    hideFinder();

    // Don't delete the model, default views will retain it between
    // activate/deactivate. do it in destructor.
    list()->setModel(NULL);
    
    delete mMenuBuilder;
    mMenuBuilder = NULL;
    
    // delete the hbsearch since we can not empty text from outside.
    delete mSearchPanel;
    mSearchPanel = NULL;
}

void CntNamesViewPrivate::scrollTo(const QContact &aContact)
{
    if (mListModel) 
    {
        QModelIndex index = mListModel->indexOfContact(aContact);

        if (index.isValid()) 
        {
            list()->scrollTo(index);
        }
    }
}
void CntNamesViewPrivate::setFilter(const QString &filterString)
{
    QStringList searchList = filterString.split(QRegExp("\\s+"), QString::SkipEmptyParts);
    QContactDetailFilter filter;
    filter.setDetailDefinitionName(QContactDisplayLabel::DefinitionName,
        QContactDisplayLabel::FieldLabel);
    filter.setMatchFlags(QContactFilter::MatchStartsWith);
    filter.setValue(searchList);

    mListModel->setFilterAndSortOrder(filter);

    if (mListModel->rowCount() == 0) {
        layout()->removeItem(list());
        layout()->insertItem(1, emptyLabel());
        list()->setVisible(false);
        emptyLabel()->setVisible(true);
    }
    else {
        layout()->removeItem(emptyLabel());
        layout()->insertItem(1, list());
        emptyLabel()->setVisible(false);
        list()->setVisible(true);
    }
    mListModel->showMyCard(false);
}

void CntNamesViewPrivate::handleKeypadOpen()
{
    qreal searchHeight = search()->size().height();
    qreal bannerHeight = groupBox()->size().height();
    qreal heightToSet = mView->size().height() - mVirtualKeyboard->keyboardArea().height()
        - searchHeight - bannerHeight;

    list()->setMaximumHeight(heightToSet);
    emptyLabel()->setMaximumHeight(heightToSet);
}

void CntNamesViewPrivate::handleKeypadClose()
{
    list()->setMaximumHeight(mView->size().height());
    emptyLabel()->setMaximumHeight(mView->size().height());
}

void CntNamesViewPrivate::showBanner(const QString aText)
{
    layout()->insertItem(0, groupBox());
    groupBox()->setHeading(aText);
    groupBox()->setVisible(true);
}

void CntNamesViewPrivate::hideBanner()
{
    layout()->removeItem(groupBox());
    groupBox()->setVisible(false);
}

void CntNamesViewPrivate::showFinder()
{
    showBanner(hbTrId("txt_phob_subtitle_find_all_contacts"));

    mView->toolBar()->hide();
    setFilter(QString());

    list()->setVisible(true);
    layout()->addItem(search());
    search()->setVisible(true);

    mListModel->showMyCard(false);
}

void CntNamesViewPrivate::hideFinder()
{
    layout()->removeItem(emptyLabel());
    layout()->removeItem(search());
    emptyLabel()->setVisible(false);
    search()->setVisible(false);

    hideBanner();

    layout()->addItem(list());
    list()->setVisible(true);

    QContactDetailFilter filter;
    filter.setDetailDefinitionName(QContactType::DefinitionName, QContactType::FieldType);
    QString typeContact = QContactType::TypeContact;
    filter.setValue(typeContact);

    mListModel->setFilterAndSortOrder(filter);
    mListModel->showMyCard(true);

    mView->toolBar()->show();
}

bool CntNamesViewPrivate::isFinderVisible()
{
    return search()->isVisible();
}

void CntNamesViewPrivate::showPreviousView()
{
    if ( !isFinderVisible() )
    {
        qApp->quit();
    }
    hideFinder();
}

void CntNamesViewPrivate::handleExtensionAction()
{
    for(int i = 0;i < mExtensionManager.pluginCount();i++)
    {
        CntUiSocialExtension* socialExtension = mExtensionManager.pluginAt(i)->socialExtension();
        if (socialExtension)
        {
            CntViewParameters params;
            socialExtension->handleToolbarAction(params);
            if (params.count())
            {
                mViewManager->changeView(params);
                break;
            }
        }
    }
}

void CntNamesViewPrivate::createNewContact()
{
    QContact newContact;
    showContactEditorView(newContact);
}

void CntNamesViewPrivate::showContactView( const QModelIndex& aIndex )
{
    QContact c = mListModel->contact(aIndex);
    showContactView( c );
}

void CntNamesViewPrivate::showContactView( QContact& aContact )
{
    CntViewParameters args;
    args.insert(EViewId, commLauncherView);
    if (aContact.localId() == mListModel->myCardId() && aContact.details().count() <= 4)
    {
        args.insert(EViewId, myCardView);
    }

    QVariant contact;
    contact.setValue(aContact);
    args.insert(ESelectedContact, contact);
    mViewManager->changeView(args);
}

void CntNamesViewPrivate::showContextMenu(HbAbstractViewItem* aItem, QPointF aPoint)
{
    QContact contact = mListModel->contact(aItem->modelIndex());
    mMenuBuilder->execActionMenu( contact, aPoint );
}

void CntNamesViewPrivate::executeAction( QContact& aContact, QString aAction )
{
    CntAction* other = new CntAction( aAction );
    connect(other, SIGNAL(actionExecuted(CntAction*)), this, SLOT(actionExecuted(CntAction*)));
    other->execute(aContact, QContactDetail());
}

void CntNamesViewPrivate::actionExecuted(CntAction* aAction)
{
    aAction->deleteLater();
}

void CntNamesViewPrivate::deleteContact(QContact& aContact)
{
    QContactManager* manager = mViewManager->contactManager( SYMBIAN_BACKEND );
    QString name = manager->synthesizedDisplayLabel(aContact);

    HbMessageBox *note = new HbMessageBox(
            hbTrId("txt_phob_info_delete_1").arg(name),
            HbMessageBox::MessageTypeQuestion);

    note->setPrimaryAction(new HbAction(hbTrId("txt_phob_button_delete"), note));
    note->setSecondaryAction(new HbAction(hbTrId("txt_common_button_cancel"), note));

    HbAction *selected = note->exec();
    if (selected == note->primaryAction())
    {
        manager->removeContact(aContact.localId());
        HbNotificationDialog::launchDialog(hbTrId("txt_phob_dpophead_1_deleted").arg(name));
    }
    delete note;
}

void CntNamesViewPrivate::showContactEditorView(QContact& aContact)
{
    CntViewParameters args;
    args.insert(EViewId, editView);
    
    QVariant contact;
    contact.setValue(aContact);
    args.insert(ESelectedContact, contact);

    mViewManager->changeView(args);
}

void CntNamesViewPrivate::showCollectionView()
{
    CntViewParameters args;
    args.insert(EViewId, collectionView);
    mViewManager->changeView(args);
}

void CntNamesViewPrivate::importSim()
{
    int copied(0);
    int failed(0);
    QContactManager* simManager = mViewManager->contactManager( SIM_BACKEND );
    QContactManager* symbianManager = mViewManager->contactManager( SYMBIAN_BACKEND );
    
    QList<QContactLocalId> contactIds = simManager->contactIds();
    if (contactIds.count() == 0) {
        HbMessageBox::information("Nothing to copy: SIM card is empty or not accessible.");
        return;
    }
        
    foreach(QContactLocalId id, contactIds) {
        QContact contact = simManager->contact(id);
        if (contact.localId() > 0) {
            //delete local id before saving to different storage
            QScopedPointer<QContactId> contactId(new QContactId());
            contactId->setLocalId(0);
            contactId->setManagerUri(QString());
            contact.setId(*contactId);

            // custom label contains name information, save it to the first name 
            QList<QContactDetail> names = contact.details(QContactName::DefinitionName);
            if (names.count() > 0) {
                QContactName name = static_cast<QContactName>(names.at(0));
                name.setFirstName(name.customLabel());
                name.setCustomLabel(QString());
                contact.saveDetail(&name);
            }
                
            if (symbianManager->saveContact(&contact)) {
                copied++;
            }
            else {
                failed++;
            }
        }
        else {
            failed++;
        }
    }
    
    QString resultMessage;
    resultMessage.setNum(copied);
    resultMessage.append(" contact copied, ");
    resultMessage.append(QString().setNum(failed));
    resultMessage.append(" failed.");
        
    HbMessageBox::information(resultMessage);
}


//// lazy accessors
HbListView* CntNamesViewPrivate::list()
{
    if (!mListView) {
        mListView = static_cast<HbListView*> (mLoader->findWidget("listView"));
        HbListViewItem *prototype = mListView->listItemPrototype();
        prototype->setGraphicsSize(HbListViewItem::Thumbnail);

        mListView->setFrictionEnabled(true);
        mListView->setScrollingStyle(HbScrollArea::PanWithFollowOn);
        mListView->listItemPrototype()->setGraphicsSize(HbListViewItem::Thumbnail);
        mListView->verticalScrollBar()->setInteractive(true);
        
        HbFrameBackground frame;
        frame.setFrameGraphicsName("qtg_fr_list_normal");
        frame.setFrameType(HbFrameDrawer::NinePieces);
        mListView->itemPrototypes().first()->setDefaultFrame(frame);
        
        mListView->setUniformItemSizes(true);

        HbIndexFeedback *indexFeedback = new HbIndexFeedback(mView);
        indexFeedback->setIndexFeedbackPolicy(HbIndexFeedback::IndexFeedbackSingleCharacter);
        indexFeedback->setItemView(mListView);
    }
    return mListView;
}

HbTextItem* CntNamesViewPrivate::emptyLabel()
{
    if (!mEmptyList) {
        mEmptyList = new HbTextItem(hbTrId("(no matching contacts)"));
        mEmptyList->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
        mEmptyList->setFontSpec(HbFontSpec(HbFontSpec::Primary));
        mEmptyList->setAlignment(Qt::AlignCenter);
    }
    return mEmptyList;
}
HbGroupBox* CntNamesViewPrivate::groupBox()
{
    if (!mBanner)
        mBanner = new HbGroupBox();
    return mBanner;
}

HbSearchPanel* CntNamesViewPrivate::search()
{
    if (!mSearchPanel) {
        mSearchPanel = new HbSearchPanel();
        mSearchPanel->setVisible( false );
        connect(mSearchPanel, SIGNAL(exitClicked()), this, SLOT(hideFinder()));
        connect(mSearchPanel, SIGNAL(criteriaChanged(QString)), this, SLOT(setFilter(QString)));
    }
    return mSearchPanel;
}
QGraphicsLinearLayout* CntNamesViewPrivate::layout()
{
    if (!mLayout) {
        QGraphicsWidget *w = mLoader->findWidget(QString("content"));
        mLayout = static_cast<QGraphicsLinearLayout*> (w->layout());
    }
    return mLayout;
}

HbDocumentLoader* CntNamesViewPrivate::document()
{
    if (!mLoader) {
        mLoader = new HbDocumentLoader();
    }
    return mLoader;
}

// End of File