messagingapp/msgui/unifiedviewer/src/univieweraddresswidget.cpp
changeset 37 518b245aa84c
parent 25 84d9eb65b26f
child 48 4f501b74aeb1
--- a/messagingapp/msgui/unifiedviewer/src/univieweraddresswidget.cpp	Mon May 03 12:29:07 2010 +0300
+++ b/messagingapp/msgui/unifiedviewer/src/univieweraddresswidget.cpp	Fri Jun 25 15:47:40 2010 +0530
@@ -11,51 +11,149 @@
  *
  * Contributors:
  *
- * Description:
+ * Description:Custom widget derived from HbTextEdit which provides rich text
+ *              processing
  *
  */
 
 #include "univieweraddresswidget.h"
-#include "univiewerfeeder_p.h"
+
 // SYSTEM INCLUDES
-#include <HbApplication>
-#include <QString>
 #include <QTextCursor>
+#include <QTextBlock>
+#include <QApplication>
+#include <QClipboard>
+
 #include <HbMenu>
+#include <HbAction>
+#include <HbTapGesture>
 
-// USER INCLUDES
-#include "unitexteditor.h"
+#include <xqservicerequest.h>
+#include <xqappmgr.h>
+#include <cntservicescontact.h>
+#include <qtcontacts.h>
+#include <xqservicerequest.h>
+#include <xqaiwrequest.h>
+#include "msgcontacthandler.h"
 
 // LOCAL CONSTANTS
 const QString ADDRESS_SEPARATOR("; ");
 const QString ADDRESS_OPEN(" (");
 const QString ADDRESS_CLOSE(")");
+const QString SPACE(" ");
 
-//----------------------------------------------------------------------------
+//localization
+#define LOC_OPEN_CONTACT_INFO hbTrId("txt_messaging_menu_open_contact_info")
+#define LOC_CALL              hbTrId("txt_common_menu_call_verb")
+#define LOC_SEND_MESSAGE      hbTrId("txt_common_menu_send_message")
+#define LOC_SAVE_TO_CONTACTS  hbTrId("txt_common_menu_save_to_contacts")
+#define LOC_COPY              hbTrId("txt_common_menu_copy")
+
+const QString BG_FRAME_GRAPHICS("qtg_fr_lineedit_normal");
+
+//---------------------------------------------------------------
 // UniViewerAddressWidget::UniViewerAddressWidget
 // @see header file
-//----------------------------------------------------------------------------
-UniViewerAddressWidget::UniViewerAddressWidget(QGraphicsItem *parent) :
-    HbWidget(parent), mAddress(NULL)
+//---------------------------------------------------------------
+UniViewerAddressWidget::UniViewerAddressWidget(QGraphicsItem * parent) :
+HbTextEdit(parent),
+mCursorPos(-1)
 {
-    mAddress = new UniTextEditor(this);
-    HbStyle::setItemName(mAddress, "addressField");
+    this->setReadOnly(true);    
+    this->setScrollable(false);
+    this->setFlag(QGraphicsItem::ItemIsFocusable,false);
+    this->setCursorVisibility(Hb::TextCursorHidden);
+    this->setBackgroundItem(0);   
 
-    connect(mAddress, SIGNAL(aboutToShowContextMenu(HbMenu *,QPointF)), this,
-        SLOT(handleAboutToShowContextMenu(HbMenu *,QPointF)));
+    HbFontSpec fontSpec(HbFontSpec::Secondary);
+    QFont font = fontSpec.font();
+    this->setFont(font);
 
-    // TODO: Wrapping fix breaking normal scenarios.
-    // this->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
+    mFormatNormal.setForeground(palette().link());
+    mFormatNormal.setBackground(Qt::transparent);
+
+    mFormatHighlight.setBackground(palette().highlight());
+    mFormatHighlight.setForeground(palette().highlightedText());
+
+    connect(this, SIGNAL(aboutToShowContextMenu(HbMenu*,QPointF)),
+            this, SLOT(aboutToShowContextMenu(HbMenu*,QPointF)));
 }
 
-//----------------------------------------------------------------------------
+//---------------------------------------------------------------
 // UniViewerAddressWidget::~UniViewerAddressWidget
 // @see header file
-//----------------------------------------------------------------------------
+//---------------------------------------------------------------
 UniViewerAddressWidget::~UniViewerAddressWidget()
 {
 }
 
+//---------------------------------------------------------------
+//UniViewerAddressWidget :: gestureEvent
+// @see header file
+//---------------------------------------------------------------
+void UniViewerAddressWidget::gestureEvent(QGestureEvent* event)
+{
+    //handle gesture to highlight and dehighlight find item.
+    
+    if(HbTapGesture *tap = qobject_cast<HbTapGesture*>(event->gesture(Qt::TapGesture)))
+    {
+        //capturing gesture position, and map to local co-ordinates.
+        QPointF pos = mapFromScene(tap->scenePosition());
+        
+        switch (tap->state()) 
+        {
+            case Qt::GestureStarted:
+            {
+                //highlight find item.
+                QTextDocument* doc = this->document();
+                mCursorPos = doc->documentLayout()->hitTest(pos, Qt::ExactHit);
+                highlightText(true);
+                break;
+            }  
+            
+            case Qt::GestureFinished:
+            {
+                if (HbTapGesture::Tap == tap->tapStyleHint()) 
+                {
+                    //gesture is finshed dehighlight text.
+                    highlightText(false);
+                    
+                    QString anchor = this->anchorAt(pos);
+                    
+                    //do short tap action.
+                    if (!anchor.isEmpty() && !this->textCursor().hasSelection())
+                    {
+                        shortTapAction(anchor);
+                    }
+                }
+                break;
+            }
+            
+            case Qt::GestureCanceled:
+            {
+                //gesture is canceled due to pan or swipe, dehighlight text.
+                if (HbTapGesture::Tap == tap->tapStyleHint()) 
+                {
+                highlightText(false);
+                break;
+                }
+            }
+            default:
+                break;
+        }
+        
+        event->accept();
+    }
+    else
+    {
+        event->ignore();
+    }
+    
+    //passing gesture event to base class.
+    HbTextEdit::gestureEvent(event);
+}
+
+
 //----------------------------------------------------------------------------
 // UniViewerAddressWidget::populate
 // @see header file
@@ -64,22 +162,40 @@
                                       const QString &address,
                                       const QString &alias)
 {
-
-    QTextCursor cursor(mAddress->document());
-
-    QTextCharFormat addressFormat = cursor.charFormat();
-    addressFormat.setFontWeight(QFont::Bold);
-    addressFormat.setForeground(QApplication::palette().link());
-    addressFormat.setUnderlineStyle(QTextCharFormat::SingleUnderline);
+    QString labelText = label;
+    labelText.trimmed();
+    labelText += SPACE;
+    
+    //Font.
+    HbFontSpec fontSpec(HbFontSpec::Secondary);
+    qreal fontHeight = 0.0;
+    style()->parameter("hb-param-text-height-tiny", fontHeight);
+    fontSpec.setTextHeight(fontHeight);    
+    QFont font = fontSpec.font();
+    
+    QTextCharFormat labelFormat;
+    labelFormat.setFont(font);
+    
+    QTextCharFormat addressFormat;
+    addressFormat.setForeground(palette().link());
+    addressFormat.setFontUnderline(true);
 
     // Insert the label then the addresses
-    cursor.insertText(label);
+    QTextCursor cursor(this->textCursor());
+    cursor.insertText(labelText,labelFormat);
+    
     QString address1 = QString();
     if (!(alias.isEmpty()))
     {
         address1.append(alias);
         QString alias1 = QString();
-        if (UniViewerFeederPrivate::GetNameFromContacts(address, alias1) > 1)
+        
+        int totalNumbers = 0;
+        MsgContactHandler::resolveContactDisplayName(
+                        address,
+                        alias1,
+                        totalNumbers);
+        if (totalNumbers > 1)
         {
             address1.append(ADDRESS_OPEN);
             address1.append(address);
@@ -92,7 +208,6 @@
     }
     addressFormat.setAnchorHref(address);
     cursor.insertText(address1, addressFormat);
-    repolish();
 }
 
 //----------------------------------------------------------------------------
@@ -102,19 +217,30 @@
 void UniViewerAddressWidget::populate(const QString &label,
                                       ConvergedMessageAddressList addressList)
 {
-    QTextCursor cursor(mAddress->document());
+    QString labelText = label;
+    labelText.trimmed();
+    labelText += SPACE;
+    
+    //Font.
+    HbFontSpec fontSpec(HbFontSpec::Secondary);
+    qreal fontHeight = 0.0;
+    style()->parameter("hb-param-text-height-tiny", fontHeight);
+    fontSpec.setTextHeight(fontHeight);    
+    QFont font = fontSpec.font();
+    
+    QTextCharFormat labelFormat;
+    labelFormat.setFont(font);
+    
+    QTextCharFormat defaultFormat;
+    defaultFormat.setForeground(palette().link());
 
-    QTextCharFormat defaultFormat = cursor.charFormat();
-    defaultFormat.setFontWeight(QFont::Bold);
-    defaultFormat.setForeground(QApplication::palette().link());
-
-    QTextCharFormat addressFormat = cursor.charFormat();
-    addressFormat.setFontWeight(QFont::Bold);
-    addressFormat.setForeground(QApplication::palette().link());
-    addressFormat.setUnderlineStyle(QTextCharFormat::SingleUnderline);
+    QTextCharFormat addressFormat;
+    addressFormat.setForeground(palette().link());
+    addressFormat.setFontUnderline(true);
 
     // Insert the label then the addresses
-    cursor.insertText(label);
+    QTextCursor cursor(this->document());
+    cursor.insertText(labelText,labelFormat);
 
     int addressCount = addressList.count();
 
@@ -126,8 +252,13 @@
         {
             address.append(addressList[i]->alias());
             QString alias = QString();
-            if (UniViewerFeederPrivate::GetNameFromContacts(addressList[i]->address(),
-                                                            alias) > 1)
+            
+            int totalNumbers = 0;
+            MsgContactHandler::resolveContactDisplayName(
+                            addressList[i]->address(),
+                            alias,
+                            totalNumbers);
+            if (totalNumbers > 1)
             {
                 address.append(ADDRESS_OPEN);
                 address.append(addressList[i]->address());
@@ -148,7 +279,6 @@
         }
         
     }
-    repolish();
 }
 
 //----------------------------------------------------------------------------
@@ -157,17 +287,264 @@
 //----------------------------------------------------------------------------
 void UniViewerAddressWidget::clearContent()
 {
-    mAddress->document()->clear();
+    this->document()->clear();
+}
+
+//----------------------------------------------------------------------------
+// UniViewerAddressWidget::menuClosed
+// @see header file
+//----------------------------------------------------------------------------
+void UniViewerAddressWidget::menuClosed()
+{
+    highlightText(false);
 }
 
 //----------------------------------------------------------------------------
-// UniViewerAddressWidget::handleAboutToShowContextMenu
+// UniViewerAddressWidget::highlightText
 // @see header file
 //----------------------------------------------------------------------------
-void UniViewerAddressWidget::handleAboutToShowContextMenu(HbMenu *contextMenu, const QPointF &pos)
+void UniViewerAddressWidget::highlightText(bool highlight)
+{
+    QTextBlock textBlock = this->document()->findBlock(mCursorPos);
+
+    QTextBlock::iterator it;
+
+    for (it = textBlock.begin(); !(it.atEnd()); ++it)
+    {
+        QTextFragment currentFragment = it.fragment();
+        
+        if (currentFragment.isValid() && currentFragment.contains(mCursorPos)
+            && currentFragment.charFormat().fontUnderline())
+        {
+            int start = currentFragment.position();
+            int length = currentFragment.length();
+
+            QTextCursor cursor = this->textCursor();
+            cursor.clearSelection();
+            cursor.setPosition(start);
+            cursor.setPosition(start + length,QTextCursor::KeepAnchor);
+
+            if(highlight)
+            {
+                cursor.mergeCharFormat(mFormatHighlight);
+            }
+            else
+            {
+                cursor.mergeCharFormat(mFormatNormal);
+            }
+
+            cursor.clearSelection();
+            break;
+        }
+    }
+}
+
+void UniViewerAddressWidget::aboutToShowContextMenu(HbMenu *contextMenu, const QPointF &pos)
+{
+    //remove default actions.
+    contextMenu->clearActions();
+    
+    // Check if there is an anchor at this pos
+    QString  anchor = this->anchorAt(pos);
+
+    if(!anchor.isEmpty() && !this->textCursor().hasSelection())
+    {
+
+        HbAction* action = NULL;
+
+        action = contextMenu->addAction(LOC_OPEN_CONTACT_INFO, this, SLOT(openContactInfo()));
+        action->setData(anchor);
+
+        action = contextMenu->addAction(LOC_CALL, this, SLOT(call()));
+        action->setData(anchor);
+
+        action = contextMenu->addAction(LOC_SEND_MESSAGE, this, SLOT(sendMessage()));
+        action->setData(anchor);
+
+        action = contextMenu->addAction(LOC_SAVE_TO_CONTACTS, this, SLOT(saveToContacts()));
+        action->setData(anchor);
+
+        action = contextMenu->addAction(LOC_COPY, this, SLOT(copyToClipboard()));
+        action->setData(anchor);
+
+    }
+
+    connect(contextMenu,SIGNAL(aboutToClose()),this,SLOT(menuClosed()));    
+}
+
+void UniViewerAddressWidget::shortTapAction(QString anchor)
+{
+    HbAction action;
+    action.setData(anchor);
+    connect(&action,SIGNAL(triggered()),this,SLOT(openContactInfo()));
+    action.trigger();
+}
+
+void UniViewerAddressWidget::copyToClipboard()
+{
+    HbAction* action = qobject_cast<HbAction*>(sender());
+
+    if(action)
+    {
+        QMimeData* data = new QMimeData();
+        QString str = action->data().toString();
+        data->setText(str);
+        QApplication::clipboard()->setMimeData(data);
+    }
+}
+
+void UniViewerAddressWidget::call()
 {
-    Q_UNUSED(pos)
-    contextMenu->clearActions();
+    HbAction* action = qobject_cast<HbAction*>(sender());
+
+    if(action)
+    {
+        QString phoneNumber = action->data().toString();
+        
+        //invoke dialer service and pass phoneNumber.        
+        QString serviceName("com.nokia.symbian.ICallDial");
+        QString operation("dial(QString)");
+        
+        XQServiceRequest* serviceRequest = new XQServiceRequest(serviceName,operation,false);
+        
+        connect(serviceRequest, SIGNAL(requestCompleted(QVariant)),
+                this, SLOT(onServiceRequestCompleted()));
+        
+        connect(serviceRequest, SIGNAL(requestError(int)),
+                this, SLOT(onServiceRequestCompleted()));
+        
+        *serviceRequest << phoneNumber;
+        serviceRequest->send();
+    }
+}
+
+void UniViewerAddressWidget::onServiceRequestCompleted()
+    {
+    //service request is now complete. delete it.    
+    XQServiceRequest* request = qobject_cast<XQServiceRequest*>(sender());
+    
+    if(request)
+        {
+        delete request;
+        }
+    }
+
+
+void UniViewerAddressWidget::openContactInfo()
+{
+    HbAction* action = qobject_cast<HbAction*>(sender());
+    
+    if(action)
+    {
+        QList<QVariant> args;
+        QString operation;
+        
+        QString data = action->data().toString();        
+    
+        int contactId = MsgContactHandler::resolveContactDisplayName(
+                data,
+                QContactPhoneNumber::DefinitionName,
+                QContactPhoneNumber::FieldNumber);
+
+        // if contact is unresolved on phone number field
+        // then, try resolving it on email address field
+        if(contactId <= 0)
+        {
+            contactId = MsgContactHandler::resolveContactDisplayName(
+                data,
+                QContactEmailAddress::DefinitionName,
+                QContactEmailAddress::FieldEmailAddress);
+        }
+
+        if(contactId > 0)
+        {
+            //open contact card
+            operation = QString("open(int)");
+            args << contactId;
+        }
+        else
+        {
+            //save to contacts with phone number field prefilled.
+
+            operation = QString("editCreateNew(QString,QString)");
+            QString type = QContactPhoneNumber::DefinitionName;
+
+            args << type;
+            args << data;
+        }
+        
+        //service stuff.
+        QString serviceName("com.nokia.services.phonebookservices");
+     
+        XQAiwRequest* request;
+        XQApplicationManager appManager;
+        request = appManager.create(serviceName, "Fetch", operation, true); // embedded
+        if ( request == NULL )
+            {
+            return;       
+            }
+
+        // Result handlers
+        connect (request, SIGNAL(requestOk(const QVariant&)), 
+            this, SLOT(handleOk(const QVariant&)));
+        connect (request, SIGNAL(requestError(const QVariant&)), 
+            this, SLOT(handleError(const QVariant&)));
+        
+        request->setArguments(args);
+        request->send();
+        delete request;
+    }
+}
+
+void UniViewerAddressWidget::handleOk(const QVariant& result)
+    {
+    Q_UNUSED(result)
+    }
+
+void UniViewerAddressWidget::handleError(int errorCode, const QString& errorMessage)
+    {
+    Q_UNUSED(errorMessage)
+    Q_UNUSED(errorCode)
+    }
+
+void UniViewerAddressWidget::saveToContacts()
+{
+    //handler for save to contacts.
+}
+
+void UniViewerAddressWidget::sendMessage()
+{
+    HbAction* action = qobject_cast<HbAction*>(sender());
+
+    if(action)
+    {
+        QString phoneNumber = action->data().toString();
+        QString alias;
+
+        QTextBlock textBlock = this->document()->findBlock(mCursorPos);
+
+        QTextBlock::iterator it;
+
+        for (it = textBlock.begin(); !(it.atEnd()); ++it)
+        {
+            QTextFragment currentFragment = it.fragment();
+
+            if (currentFragment.isValid() && currentFragment.contains(mCursorPos)
+                && currentFragment.charFormat().fontUnderline())
+            {
+                QString txt = currentFragment.text();
+                if(txt != phoneNumber)
+                {
+                    alias = txt;  
+                }
+                break;
+            }
+        }
+        
+
+        //invoke editor & pass phoneNumber.
+        emit sendMessage(phoneNumber,alias);
+    }
 }
 
 // EOF