contactwidgethsplugin/contactwidgeths/src/contactwidgeths.cpp
changeset 47 7cbcb2896f0e
child 51 81c360d47083
child 59 a642906a277a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contactwidgethsplugin/contactwidgeths/src/contactwidgeths.cpp	Tue Jul 06 14:05:47 2010 +0300
@@ -0,0 +1,814 @@
+/*
+* Copyright (c) 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:  Contact Friend widget 
+*
+*/
+#include <QDebug>
+#include <QLocale>
+#include <HbTranslator>
+#include <QGraphicsGridLayout>
+#include <hbcolorscheme.h>
+#include <HbDialog>
+#include <HbWidget>
+#include <HbLabel>
+#include <HbIconItem>
+#include <HbFrameDrawer>
+#include <HbFrameItem>
+#include <HbDeviceProfile>
+#include <hbdevicemessagebox>
+#include <hbdocumentloader.h>
+#include <QPixmap>
+#include <QGraphicsSceneMouseEvent>
+#include <HbEvent>
+
+#include <cntservicescontact.h>
+#include <hbaction.h>
+
+#include <HbInstance>
+
+#include "contactwidgeths.h"
+#include "commlauncherwidget.h"
+#include "ihswidgetpreferenceservice.h"
+ 
+const QString defaultAvatar = "qtg_large_avatar";
+const QString addContactAvatar = "qtg_small_add";
+const QString normalFrameName = "qtg_fr_hsshortcut_normal";
+const QString normalTextColor = "qtc_hs_list_item_title_normal";
+const QString latchedFrameName = "qtg_fr_hsitems_latched";
+const QString latchedTextColor = "qtc_hs_list_item_latched";
+// Preferences properties
+const QString widgetPrefContactId = "contactId";
+// Docml file
+const QString contactWidgetDocml = ":/commlauncherwidget.docml";
+
+/*!
+  \class ContactWidgetHs
+*/
+
+/*!
+    Constructor
+*/
+ContactWidgetHs::ContactWidgetHs(QGraphicsItem *parent, Qt::WindowFlags flags )
+: HbWidget(parent, flags),
+  mAvatarIconItem(0),
+  mContactNameLabel(0),
+  mLauncherRect(QRectF(0,0,0,70)),
+  mWidgetFrameDrawer(0),
+  mShareFrameDrawer(0),
+  mContactLocalId(unUsedContactId),
+  mAvatar(0),	
+  mContactHasAvatarDetail(false),  
+  mContactManager(0),
+  mAppManager(0),
+  mContactSelectRequest(0),
+  mMainWindow(0),
+  mThumbnailManager(0),
+  mThumbnailPixmap(QPixmap()),
+  mThumbnailInProgress(false),
+  mTranslator(0)
+{
+    // Localization file loading   
+	mTranslator = new HbTranslator();
+	mTranslator->loadCommon();    
+    
+    // UI creation done in onInitialize()
+    if (mainWindow()) {
+        mMainWindow = mainWindow();
+        connect(mMainWindow, SIGNAL(aboutToChangeOrientation()), 
+                this, SLOT(orientationChange()));
+        qDebug() << "mMainWindow(x,y): " << mMainWindow->width() << mMainWindow->height();
+    }
+
+    // avatar icon item has to be created without parent else the drawing goes wrong
+    mAvatarIconItem = new HbIconItem();
+    
+    //Create Communication launcher
+    //Has to be created without parent, otherwise timout, dismissPolicy and modality have no effect
+    mLauncher = new CommLauncherWidget();
+    mLauncher->setTimeout(0);
+    mLauncher->setDismissPolicy(HbPopup::TapAnywhere); 
+    mLauncher->setBackgroundFaded(false);
+    mLauncher->setModal(false);
+    mLauncher->hide();
+    // USE CONNECT WHEN THE LATCHED GRAPHICS IS IN THE PLATFORM
+    //connect(mLauncher, SIGNAL(launcherClosed()),
+    //        this, SLOT(loadNormalLayout()));
+    
+    mAppManager = new XQApplicationManager();
+    ASSERT(mAppManager);
+    mLauncher->setApplicationManager(*mAppManager);
+    
+    // Thumbnail manager so we can handle large size images as contact avatars
+    mThumbnailManager = new ThumbnailManager(this);
+    mThumbnailManager->setMode(ThumbnailManager::Default);
+    mThumbnailManager->setQualityPreference(ThumbnailManager::OptimizeForQuality);
+    mThumbnailManager->setThumbnailSize(ThumbnailManager::ThumbnailMedium );
+    
+    connect(mThumbnailManager, SIGNAL(thumbnailReady(QPixmap, void*, int, int)),
+        this, SLOT(thumbnailReady(QPixmap, void*, int, int)));
+    
+    mWidgetFrameDrawer = new HbFrameDrawer(normalFrameName, 
+                                           HbFrameDrawer::NinePieces);
+    ASSERT(mWidgetFrameDrawer);
+    
+    mShareFrameDrawer = new HbFrameDrawer(normalFrameName, 
+                                          HbFrameDrawer::NinePieces);
+    ASSERT(mShareFrameDrawer);
+}
+
+/*!
+    Destructor
+*/
+ContactWidgetHs::~ContactWidgetHs()
+{
+    delete mLauncher;
+    delete mContactManager;
+    delete mAppManager;
+    delete mAvatar;	
+    // Deleting request cancels all pending requests 
+    delete mContactSelectRequest;
+    //,,first cancel?
+    delete mThumbnailManager;
+    delete mTranslator;
+}
+
+/*!
+    Updates the UI based on data from current contact
+*/
+void ContactWidgetHs::updateUiFromContact()
+{
+    if (!mContactManager) {
+        createContactManager();	
+    }
+    if (mContactManager) {
+        mContact = mContactManager->contact(mContactLocalId);
+        getContactData();
+        mLauncher->setContact(mContact);
+        
+        update();
+    }
+}
+
+/*!
+    Selects current avatar based on member variables
+*/
+void ContactWidgetHs::setAvatar()
+{
+    if (mContactLocalId > unUsedContactId) {
+        if (mContactHasAvatarDetail) {
+			if (mContactImageFileName == "") {
+				setContactImage(mThumbnailPixmap);
+			}
+			else {
+				setContactImage(mContactImageFileName);
+			}
+        } else {
+            setContactImage(defaultAvatar);
+        }
+    } else {
+        setContactImage(addContactAvatar);	
+    }
+}
+
+/*!
+    Called when ThumbnailManager has thumbnail ready
+*/
+void ContactWidgetHs::thumbnailReady(QPixmap pixmap, void *data, int id, int error)
+{
+    Q_UNUSED(data);
+    Q_UNUSED(id);
+    qDebug() << "ContactWidgetHs::thumbnailReady() error: " << error;
+    mThumbnailInProgress=false;
+    if (!error)
+    {
+		mThumbnailPixmap = pixmap;
+		setAvatar();
+		
+    }
+}
+/*!
+    Returns the name of current image file including path.
+*/
+QString ContactWidgetHs::contactImage() const
+{
+    return mContactImageFileName;
+}
+
+
+/*!
+    Set contact avatar image used in Paint()
+*/
+// THIS IS THE FIRST VERSION OF THUMBNAIL HANDLING, STILL IN PROGRESS 4.6.2010
+bool ContactWidgetHs::setContactImage(QPixmap& inputPixmap)
+{
+    bool ret = false;
+        
+    HbFrameDrawer *avatarDrawer = new HbFrameDrawer("qtg_fr_hsshortcut_normal", HbFrameDrawer::NinePieces);
+    ASSERT(avatarDrawer);
+
+    // Try to load the image first, because setFrameGraphicsName() returns void.
+    //,,mContactImageFileName = imageFile;
+    
+    ret=true;
+    qDebug() << "setContactImage av 0, inputsize " << inputPixmap.width() << "x" << inputPixmap.height(); 
+    
+    qreal unit = HbDeviceProfile::current().unitValue();
+    const int contactIconSize = 11 * unit;
+        
+    // Render frame drawer into pixmap
+    QPixmap avatarPixmap(contactIconSize, contactIconSize);
+    avatarPixmap.fill(QColor(0, 0, 0, 0)); //transparent background
+    qDebug() << "setContactImage av 1"; //,,
+  
+    QPainter painter(&avatarPixmap); 
+    QStyleOptionGraphicsItem *item = new QStyleOptionGraphicsItem;
+    avatarDrawer->paint(&painter, QRectF(0, 0, contactIconSize, contactIconSize));
+    painter.end();
+    qDebug() << "setContactImage av 2"; //,,             
+
+    // We may draw the icon when thumnail processing is still in progress, 
+    // so can't show the thumbnail yet.
+	if (inputPixmap.width()>0) {
+		QPixmap pm2 = inputPixmap.scaled( QSize(contactIconSize, contactIconSize), Qt::IgnoreAspectRatio );
+		qDebug() << "pm2 " << pm2.width() << " " << pm2.height();
+		avatarPixmap = pm2; //
+	} 
+    
+    HbIcon *avatarIcon = new HbIcon(QIcon(avatarPixmap));
+       
+    mAvatarIconItem->setIcon(*avatarIcon);
+        
+    // Then display the new image
+    update();
+    qDebug() << "setContactImage av 3"; //,,
+    
+    return ret;
+}
+
+/*!
+    Set contact avatar image used in Paint()
+*/
+bool ContactWidgetHs::setContactImage(const QString &imageFile)
+{
+    bool ret = false;
+        
+    HbFrameDrawer *avatarDrawer = new HbFrameDrawer("qtg_fr_hsshortcut_normal", HbFrameDrawer::NinePieces);
+    ASSERT(avatarDrawer);
+
+    // Try to load the image first, because setFrameGraphicsName() returns void.
+    mContactImageFileName = imageFile;
+    qDebug() << "setContactImage ok " << imageFile;
+    if (imageFile == addContactAvatar) {
+        avatarDrawer->setFrameGraphicsName(defaultAvatar);
+        ret = true;
+    } else {
+        avatarDrawer->setFrameGraphicsName(imageFile);
+        ret = true;
+    }
+    
+    qreal unit = HbDeviceProfile::current().unitValue();
+    const int contactIconSize = 11 * unit;
+        
+    // Render frame drawer into pixmap
+    QPixmap avatarPixmap(contactIconSize, contactIconSize);
+    avatarPixmap.fill(QColor(0, 0, 0, 0)); //transparent background
+        
+    QPainter painter(&avatarPixmap);
+    QStyleOptionGraphicsItem *item = new QStyleOptionGraphicsItem;
+    avatarDrawer->paint(&painter, QRectF(0, 0, contactIconSize, contactIconSize));
+    painter.end();
+             
+    HbIcon *avatarIcon = new HbIcon(QIcon(avatarPixmap));
+    
+    // Add badge if needed
+    if (imageFile == addContactAvatar) {
+        HbIcon addIcon(addContactAvatar);
+        QSizeF avatarSize = avatarIcon->size();
+        addIcon.setSize(QSize(avatarSize.width()/2, avatarSize.height()/2));
+        avatarIcon->addBadge(Qt::AlignTop | Qt::AlignRight, addIcon, 1);    
+    }
+    
+    mAvatarIconItem->setIcon(*avatarIcon);
+        
+    // Then display the new image
+    update();
+
+    return ret;
+}
+
+
+void ContactWidgetHs::setName(const QString &sName)
+{
+    if (mContactNameLabel) {
+        mContactNameLabel->setPlainText(sName);
+    }    
+
+    update();
+}
+
+/*!
+    Creates the UI for the widget
+*/
+void ContactWidgetHs::createUI()
+{
+    
+    qreal unit = HbDeviceProfile::current().unitValue();
+    // Currently not possible to create a hbframedrawer using docml, so the size is fixed here. 
+    const int contactIconSize = 11 * unit;
+    const int widgetMargin =   0.5 * unit;
+    const int textRow = 2;
+    const int rows = 4; // 4 using 2 margins
+    
+    QGraphicsGridLayout *layout = new QGraphicsGridLayout(this);
+
+    // Widget frame
+    qreal corner = 1.5 * unit; // from shortcut widget layout spec: 1.5un    
+    mWidgetFrameDrawer->setBorderWidths(corner, corner); 
+    HbFrameItem *widgetFrame = new HbFrameItem(mWidgetFrameDrawer); //drawer ownership transfered to item
+    layout->addItem(widgetFrame, 0, 0, rows, 3);
+          
+    // Avatar frame    
+    HbFrameItem *shareFrame = new HbFrameItem(mShareFrameDrawer); //drawer ownership transfered to item
+    layout->addItem(shareFrame, 1, 1, 1, 1);
+    
+    // Contact icon  
+    layout->addItem(mAvatarIconItem, 1, 1, 1, 1);
+    
+    // Contact name
+    HbFontSpec fontSpec(HbFontSpec::Secondary);
+    qreal textHeight = 0.0; 
+    style()->parameter("hb-param-text-height-tiny", textHeight);	
+    if (textHeight > 0) {
+        fontSpec.setTextHeight(textHeight);
+    }
+
+    if (mContactLocalId == unUsedContactId) {
+        mContactNameLabel = new HbLabel("");
+    } else {
+		QString name = getContactDisplayName(mContact);
+        mContactNameLabel = new HbLabel(name);
+    }            
+    
+    mContactNameLabel->setAlignment(Qt::AlignHCenter);
+    mContactNameLabel->setFontSpec(fontSpec);
+    // color from theme
+    QColor textColor = HbColorScheme::color(normalTextColor);
+    if (textColor.isValid()) {
+        mContactNameLabel->setTextColor(textColor);
+    } else {
+        qDebug() << "ContactWidgetHs::createUI()  textColor is NOT Valid!! using default color";
+    }
+    mContactNameLabel->setZValue(1);
+    layout->addItem(mContactNameLabel, textRow, 1, 1, 1);
+    
+    layout->setColumnFixedWidth(0, widgetMargin);
+    layout->setColumnFixedWidth(1, contactIconSize); 
+    layout->setColumnFixedWidth(2, widgetMargin);
+    layout->setRowFixedHeight(0, widgetMargin);
+    layout->setRowFixedHeight(1, contactIconSize);
+    layout->setRowFixedHeight(textRow,   fontSpec.textHeight());    
+    layout->setRowFixedHeight(textRow+1, widgetMargin);
+    
+    setLayout(layout);
+
+    // Widget size
+    qreal sizeX = widgetMargin * 2 * unit;  //margins from layout spec
+    qreal sizeY = widgetMargin * 3 * unit;  //margins from layout spec
+    sizeY += fontSpec.textHeight();
+    sizeY += contactIconSize;
+    sizeX += contactIconSize;
+    
+    qDebug() << "widget sizex, sizey, unit, rows " << sizeX << sizeY << unit << rows;
+    
+    // Without preferredSize() moving widgets to another page doesn't work
+    setPreferredSize( sizeX, sizeY ); 
+    resize(preferredSize());
+}
+
+QString ContactWidgetHs::getContactDisplayName(QContact& contact)
+{
+	QString name = mContactManager->synthesizedDisplayLabel(contact);
+    if (name.isEmpty()) {
+        name = hbTrId("txt_friend_widget_contact_unnamed");    
+	}
+    return name;
+}
+
+/*!
+    Implemented to receive mouse press events.
+    Otherwise these events will propagate to any topmost item beneath this item.
+*/
+void ContactWidgetHs::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+    if (event && event->type() == QEvent::GraphicsSceneMousePress) {
+        // If the widget doesn't have contact yet and
+        // there are contacts, select one.    
+        if (mContactLocalId == unUsedContactId) {
+            if (contactsExist()) {				    
+                launchSingleContactSelecting();                  
+            } else {
+                // Otherwise ask if user wants to open phonebook
+                // tmp variable used for title, otherwise parent param is ignored in mb
+                QString title = hbTrId("txt_friend_widget_info_you_can_not_use_this_widge");
+                HbDeviceMessageBox mb( title, HbMessageBox::MessageTypeQuestion, this);
+                mb.setAction(new QAction(hbTrId("txt_common_button_open"),   &mb), 
+                    HbDeviceMessageBox::AcceptButtonRole);
+                mb.setAction(new QAction(hbTrId("txt_common_button_cancel"), &mb), 
+                    HbDeviceMessageBox::RejectButtonRole);
+                mb.setIconVisible(false);
+                if (mb.exec() == mb.action(HbDeviceMessageBox::AcceptButtonRole)) {				        
+                    mLauncher->openPhonebookCreateNew();
+                }
+            }
+        } else if (!mLauncher->isVisible()) {
+            // create and show CommunicationsLauncher
+            createLauncherWithPosition();
+            mLauncher->show();
+            // USE LOADLAYOUT-FUNCTION WHEN THE LATCHED GRAPHICS IS IN THE PLATFORM
+            //loadLayout(latchedFrameName, latchedTextColor);
+
+            mLauncherRect = mLauncher->boundingRect();
+            qDebug() << "after exec rect() " << mLauncherRect;
+        }
+    }
+}
+
+/*!
+    \fn void ContactWidgetHs::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
+
+    Widget start is triggered from release \a event.
+    \sa 
+*/
+void ContactWidgetHs::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
+{
+    Q_UNUSED(event);
+}
+
+
+// Store contact data to member variables and to UI
+void ContactWidgetHs::getContactData()
+{
+    if (!mContactManager) { 
+        createContactManager();
+    }
+    if (mContact.isEmpty()) {
+        qDebug() << "Empty contact with id " << mContactLocalId << ".  UI cleared, id=0";  
+        clearContactData();
+    } else {
+    
+        // Id
+        mContactLocalId = mContact.localId();
+        qDebug() << "contact id " << mContactLocalId;   
+        // Name
+        QString name = getContactDisplayName(mContact);
+        setName( name );
+        // Avatar
+        QString avatarFile;
+        QList<QContactAvatar> details = mContact.details<QContactAvatar>();
+        for (int i=0; i<details.count(); i++)
+        {
+            if (details.at(i).imageUrl().isValid())
+            {
+				delete mAvatar;				
+				mAvatar = new QContactAvatar(details.at(i));
+				avatarFile = mAvatar->imageUrl().toString();  //,,remove this once tn is working
+
+				mThumbnailInProgress = true;
+				qDebug() << "calling mThumbnailManager->getThumbnail";
+				mThumbnailManager->getThumbnail(mAvatar->imageUrl().toString());
+                break;                
+            }
+        }        
+        qDebug() << "ContactWidgetHs::getContactData() av.file" << avatarFile;
+        if (avatarFile.length() > 0) {
+            mContactHasAvatarDetail = true;
+            mContactImageFileName = ""; 
+            //,,mContactImageFileName = avatarFile;
+        }
+        else {
+            mContactHasAvatarDetail = false;
+        } 
+    }
+    if (!mThumbnailInProgress) {
+		setAvatar();
+    }
+}
+
+void ContactWidgetHs::clearContactData()
+{
+    mContactLocalId = unUsedContactId;
+    setName("");
+    mContactHasAvatarDetail = false;
+    mContactImageFileName = "";
+}
+
+/*!
+    Create contact manager
+*/
+void ContactWidgetHs::createContactManager()
+{
+    QString sBackend = "memory"; // not localised
+#ifdef Q_OS_SYMBIAN
+    sBackend = "symbian";
+#endif
+    if (mContactManager) {
+        delete mContactManager;		
+    }    
+    qDebug() << "createContactManager() backend " << sBackend;
+    mContactManager = new QContactManager(sBackend);
+    if (mContactManager->error()) {
+        qDebug() << "cm can't connect to backend " << sBackend;
+    } else { // connect contact change observation
+        connect(mContactManager, SIGNAL(contactsChanged(QList<QContactLocalId>)),
+            this, SLOT(onContactsChanged(QList<QContactLocalId>)));
+        connect(mContactManager, SIGNAL(contactsRemoved(QList<QContactLocalId>)),
+            this, SLOT(onContactsRemoved(QList<QContactLocalId>)));
+    }
+}
+
+/*!
+    Initializes the widget.
+*/
+void ContactWidgetHs::onInitialize()
+{
+    qDebug() << "ContactWidgetHs::onInitialize()";    
+    createUI();
+    setAvatar();
+    
+    // Update the UI
+    update();
+}
+
+/*!
+    Uninitializes the widget.
+*/
+void ContactWidgetHs::onUninitialize()
+{
+    qDebug() << "ContactWidgetHs::onUninitialize()";
+    hide();
+}
+
+/*!
+    \fn void ContactWidgetHs::onShow()
+
+    Called when the widget is shown.
+    This method is needed. Otherwise the widget cannot be added to HS.    
+*/
+void ContactWidgetHs::onShow()
+{
+    qDebug() << "ContactWidgetHs::onShow()";
+}
+
+
+/*!
+    \fn void ContactWidgetHs::onHide()
+
+    Called when the widget is hidden.
+    This method is needed. Otherwise the widget cannot be added to HS.
+*/
+void ContactWidgetHs::onHide()
+{
+    qDebug() << "ContactWidgetHs::onHide()";	
+}
+
+
+/*!
+    Orientation changed slot
+*/
+void ContactWidgetHs::orientationChange()
+{    
+    // Close the launcher if it's visible
+    if (mLauncher->isVisible()) {
+        mLauncher->hide();
+    }
+}    
+
+/*!
+    Checks if there are contacts to select.
+ */
+bool ContactWidgetHs::contactsExist()
+{
+    if (!mContactManager) { 
+        createContactManager();
+    }
+    bool ret=false;
+    // 
+    if (mContactManager) {
+        QList<QContactLocalId> contactIds = mContactManager->contactIds();
+        qDebug() << "contact count " << contactIds.count();
+        if (contactIds.count() > 0) {
+        qDebug() << "first " << contactIds.first();
+        int i;
+        for(i=0; i<contactIds.count(); i++) {
+			qDebug() << "contactIds i " << i << " id " << contactIds.at(i);
+        }                        
+            if (contactIds.first() != mContactManager->selfContactId() ||
+                contactIds.count() > 1) {
+                ret=true;
+            }
+        }
+    }
+    
+    return ret;
+}
+
+/*!
+    This launches SINGLE contact selecting.
+*/
+bool ContactWidgetHs::launchSingleContactSelecting()
+{
+	bool result = false;
+	   
+    if (mContactSelectRequest) {
+        delete mContactSelectRequest;
+        mContactSelectRequest = 0;
+    }
+    qDebug() << "- launchSingleContactSelecting() starts";  //,,
+    mContactLocalId = unUsedContactId;
+    
+    /* TODO! THIS SERVICE WILL BE RENAMED TO com.nokia.services.phonebook.Services */                                      
+    mContactSelectRequest = mAppManager->create(
+        "com.nokia.services.phonebookservices",
+        "Fetch", 
+        "Dofetch(QString,QString,QString,QString)", 
+        false);   
+    connect(mContactSelectRequest, SIGNAL(requestOk(QVariant)),
+            this, SLOT(onContactSelectCompleted(QVariant)));  
+    QList<QVariant> args;
+    args << hbTrId("txt_friend_widget_title_select_contact");
+    args << KCntActionAll;
+    args << KCntFilterDisplayAll;
+    args << KCntSingleSelectionMode;
+    mContactSelectRequest->setArguments(args);
+    
+    qDebug() << "---- setArgs done ---------------------"; //,,28.5.          
+    
+    result = mContactSelectRequest->send();
+    if (!result) {
+        qDebug() << "Sending XQServiceRequest failed";
+    }  
+    
+    qDebug() << "- launchSingleContactSelecting() done"; //,,
+   
+    return result;
+}
+
+/*!
+   This slot gets selected contact's id from value parameter.
+*/
+void ContactWidgetHs::onContactSelectCompleted(const QVariant &value)
+{
+    qDebug() << "- onContactSelectCompleted() start";
+
+    CntServicesContactList returnValue;
+    if(value.canConvert<CntServicesContactList>()) {
+        returnValue = qVariantValue<CntServicesContactList>(value);
+
+        if (returnValue.count() == 0) {
+            // User didn't select any contact
+			mContactLocalId = ContactWidgetHs::unUsedContactId;
+            qDebug() << "No contact selected";
+        } else {
+            for (int i = 0; i < returnValue.count(); ++i) {
+                QString recipientName = returnValue[i].mDisplayName;
+                qDebug() << recipientName << " id from param " << returnValue[i].mContactId;
+                mContactLocalId = returnValue[i].mContactId;
+            }
+        }
+    } else {
+        qDebug() << "Can't convert CntServicesContactList! no contact selected";
+        mContactLocalId = ContactWidgetHs::unUsedContactId;
+    }
+    // Save localId preference
+    emit setPreferences( QStringList() << widgetPrefContactId );
+    updateUiFromContact();
+
+    qDebug() << "- onContactSelectCompleted() end, mContactLocalId " << mContactLocalId; //,,
+}
+
+
+/*!
+    Set contact id
+*/
+void ContactWidgetHs::setContactId(const QString &Id)
+{
+    qDebug() << "ContactWidgetHs::setContactId() " << Id;
+    mContactLocalId = Id.toInt();
+    updateUiFromContact();
+}
+
+/*!
+    Returns contact id
+*/
+QString ContactWidgetHs::contactId() const
+{
+    QString sId;
+    sId.setNum((int) mContactLocalId);
+    qDebug() << "ContactWidgetHs::contactId() " << sId;
+    return sId;
+}
+
+/*!
+    Slot gets called when contact details changed
+*/
+void ContactWidgetHs::onContactsChanged( const QList<QContactLocalId> &contactIds )
+{
+    qDebug() << "ContactWidgetHs::onContactsChanged";
+    int i;
+    for(i=0; i<contactIds.count(); i++) {
+        if (contactIds.at(i) == mContactLocalId) {
+            qDebug() << "-updating widget from contact " << mContactLocalId;
+            updateUiFromContact();
+        }
+    }
+}
+
+/*!
+    Slot gets called when contact removed
+*/
+void ContactWidgetHs::onContactsRemoved( const QList<QContactLocalId> &contactIds )
+{
+    qDebug() << "ContactWidgetHs::onContactsRemoved, removed count " << contactIds.count();
+    int i;
+    for(i=0; i<contactIds.count(); i++) {
+        if (contactIds.at(i) == mContactLocalId) {
+            qDebug() << "-deleting widget with removed contact " << mContactLocalId;
+            // TODO this deletes the widget. Can we always delete the object immediately?
+            emit finished();
+            break;
+        }
+    }
+}
+
+/*!
+    Implemented to receive theme change event.
+*/
+void ContactWidgetHs::changeEvent(QEvent *event)
+{
+    if (event->type() == HbEvent::ThemeChanged) {
+        // get the text color from theme and set it to name label
+        QColor textColor = HbColorScheme::color(normalTextColor);
+        if (textColor.isValid()) {
+            mContactNameLabel->setTextColor(textColor);
+        } else {
+            qDebug() << "ContactWidgetHs::changeEvent()  textColor is NOT Valid!! using default color";
+        }
+    }
+}
+
+/*!
+    Creates communication launcher UI if needed and 
+    sets the correct position for launcher
+*/
+void ContactWidgetHs::createLauncherWithPosition() 
+{
+    QRectF boundingRect = this->sceneBoundingRect(); // Widget size
+    QRectF sceneRect(0, 0, 0, 0);
+    if (mMainWindow) {
+        sceneRect = mMainWindow->sceneRect();
+    }
+    
+    mLauncher->createUI();    
+    QPointF pos = mLauncher->commLauncherPosition(scenePos(), boundingRect, sceneRect, mLauncherRect);
+    mLauncher->setPreferredPos(pos);
+    mLauncher->selectAppearEffect(scenePos(), pos);
+}
+
+/*!
+    Updates the layout with normal frame and text color
+*/
+void ContactWidgetHs::loadNormalLayout()
+{
+    loadLayout(normalFrameName, normalTextColor);
+}
+
+/*!
+    Updates the layout with given frame and text color
+*/
+void ContactWidgetHs::loadLayout(const QString frameName, const QString textColor)
+{
+    mWidgetFrameDrawer->setFrameGraphicsName(frameName);
+    mWidgetFrameDrawer->themeChanged();
+    
+    mShareFrameDrawer->setFrameGraphicsName(frameName);
+    mShareFrameDrawer->themeChanged();
+    
+    QColor color = HbColorScheme::color(textColor);
+    mContactNameLabel->setTextColor(color);
+
+    update();
+}
+
+Q_IMPLEMENT_USER_METATYPE(CntServicesContact)
+Q_IMPLEMENT_USER_METATYPE_NO_OPERATORS(CntServicesContactList)