messagingapp/msgui/unifiedviewer/src/univiewertextitem.cpp
changeset 23 238255e8b033
child 25 84d9eb65b26f
equal deleted inserted replaced
5:4697dfb2d7ad 23:238255e8b033
       
     1 /*
       
     2  * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3  * All rights reserved.
       
     4  * This component and the accompanying materials are made available
       
     5  * under the terms of "Eclipse Public License v1.0"
       
     6  * which accompanies this distribution, and is available
       
     7  * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8  *
       
     9  * Initial Contributors:
       
    10  * Nokia Corporation - initial contribution.
       
    11  *
       
    12  * Contributors:
       
    13  *
       
    14  * Description:
       
    15  * Message body preview class.
       
    16  * has in built logic for finding phone number, email, url.
       
    17  *
       
    18  */
       
    19 
       
    20 #include "univiewertextitem.h"
       
    21 
       
    22 #include <QRegExp>
       
    23 #include <QGraphicsSceneMouseEvent>
       
    24 #include <QApplication>
       
    25 #include <QClipboard>
       
    26 #include <QTextBlock>
       
    27 
       
    28 #include <HbMenu>
       
    29 #include <HbAction>
       
    30 #include <cntservicescontact.h>
       
    31 #include <qtcontacts.h>
       
    32 #include <XQServiceRequest.h>
       
    33 
       
    34 
       
    35 QTM_USE_NAMESPACE
       
    36 
       
    37 //consts
       
    38 
       
    39 //regexp
       
    40 const QString NUMBER_PATTERN("(\\(|\\+|\\d)((?:\\d{2,})((?:[\\s-/.\\)\\()])*(?:(\\d+|\\))))*)|((\\*#)(?:\\d+(\\*|#)(?:\\d+#)?))");
       
    41 
       
    42 const QString EMAIL_PATTERN("[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?");
       
    43 
       
    44 const QString URL_PATTERN("(((ht|f|rt)(tp|sp)(s?)\\:\\/\\/)|(www|wap)(?:\\.))(([-\\w]*[0-9a-zA-Z])+(:(0-9)*)*(\\/?)([a-zA-Z0-9\\-\\?\\,\'\\/\\\\+&amp;%\\$#_=~]*)(\\.)([-\\w]*[0-9a-zA-Z])+(:(0-9)*)*(\\/?)([a-zA-Z0-9\\-\\?\\,\'\\/\\\\+&amp;%\\$#_=~]*))+");
       
    45 
       
    46 //rules
       
    47 const QString NUMBER_RULE("NUMBER_RULE");
       
    48 const QString EMAIL_RULE("EMAIL_RULE");
       
    49 const QString URL_RULE("URL_RULE");
       
    50 
       
    51 //localization
       
    52 #define LOC_OPEN_CONTACT_INFO hbTrId("txt_messaging_menu_open_contact_info")
       
    53 #define LOC_CALL              hbTrId("txt_common_menu_call_verb")
       
    54 #define LOC_SEND_MESSAGE      hbTrId("txt_common_menu_send_message")
       
    55 #define LOC_SAVE_TO_CONTACTS  hbTrId("txt_common_menu_save_to_contacts")
       
    56 #define LOC_COPY              hbTrId("txt_common_menu_copy")
       
    57 #define LOC_CREATE_EMAIL      hbTrId("txt_messaging_menu_create_mail")
       
    58 #define LOC_OPEN_LINK         hbTrId("txt_messaging_menu_open_link")
       
    59 #define LOC_ADD_TO_BOOKMARKS  hbTrId("txt_messaging_menu_add_to_bookmarks")
       
    60 #define LOC_COPY_LINK         hbTrId("txt_messaging_menu_copy_link")
       
    61 
       
    62 UniViewerTextItem::UniViewerTextItem(QGraphicsItem* parent):
       
    63 HbTextEdit(parent),
       
    64 mFindOn(true),
       
    65 mCursorPos(-1)
       
    66 {
       
    67     this->setReadOnly(true);
       
    68     this->setCursorVisibility(Hb::TextCursorHidden);
       
    69 
       
    70     //inserting rules and patterns to map.
       
    71     mRules.insert(NUMBER_RULE,NUMBER_PATTERN);
       
    72     mRules.insert(EMAIL_RULE,EMAIL_PATTERN);
       
    73     mRules.insert(URL_RULE,URL_PATTERN);
       
    74 
       
    75     mFormatNormal.setForeground(palette().link());
       
    76     mFormatNormal.setBackground(Qt::transparent);
       
    77 
       
    78     mFormatHighlight.setBackground(palette().highlight());
       
    79     mFormatHighlight.setForeground(palette().highlightedText());
       
    80 
       
    81     connect(this, SIGNAL(aboutToShowContextMenu(HbMenu*,QPointF)),
       
    82             this, SLOT(aboutToShowContextMenu(HbMenu*,QPointF)));
       
    83 }
       
    84 
       
    85 UniViewerTextItem::~UniViewerTextItem()
       
    86     {
       
    87     }
       
    88 
       
    89 void UniViewerTextItem::setFindOn(bool on)
       
    90 {
       
    91     mFindOn = on;   
       
    92 }
       
    93 
       
    94 void UniViewerTextItem::setText(const QString& text)
       
    95 {
       
    96     
       
    97     this->setPlainText(text);
       
    98     applyRule();
       
    99 }
       
   100 
       
   101 void UniViewerTextItem::applyRule()
       
   102 {
       
   103 
       
   104     if(mFindOn == false)
       
   105     {
       
   106         return;
       
   107     }
       
   108 
       
   109     QMap<QString, QString>::const_iterator i;
       
   110     for (i = mRules.constBegin(); i != mRules.constEnd(); ++i)
       
   111     {
       
   112         QString ruleName = i.key();
       
   113         QString rule = i.value();
       
   114         QRegExp ruleExp(rule);
       
   115 
       
   116         QTextCursor cursor = this->document()->find(ruleExp);
       
   117 
       
   118         while(cursor.hasSelection())
       
   119         {
       
   120             // Insert anchor in the document
       
   121             QTextCharFormat f;
       
   122             f.setFontUnderline(true);
       
   123             f.setForeground(palette().link());
       
   124 
       
   125             //prepending rule name to identiy different fragment to which
       
   126             //catagory it belongs to.
       
   127             QString txt = cursor.selectedText().prepend(ruleName);
       
   128 
       
   129             if(ruleName == NUMBER_RULE)
       
   130             {
       
   131                 //removing special char(s) from phone numbers.
       
   132                 QRegExp numberCharExp("[\\s-/.\\(\\)]");
       
   133                 txt = txt.remove(numberCharExp);
       
   134             }
       
   135 
       
   136             f.setAnchorHref(txt);
       
   137             f.setAnchor(true);
       
   138             cursor.mergeCharFormat(f);
       
   139 
       
   140             // Find next
       
   141             cursor = this->document()->find(ruleExp, cursor);
       
   142         }
       
   143     }
       
   144 }
       
   145 
       
   146 
       
   147 void UniViewerTextItem::aboutToShowContextMenu(HbMenu *contextMenu, const QPointF &pos)
       
   148 {
       
   149     // Check if there is an anchor at this pos
       
   150     QString  anchor = this->anchorAt(pos);
       
   151 
       
   152     if(!anchor.isEmpty() && !this->textCursor().hasSelection())
       
   153     {
       
   154         //remove default actions.
       
   155         contextMenu->clearActions();
       
   156 
       
   157         if(anchor.contains(QRegExp("^"+NUMBER_RULE)))
       
   158         {
       
   159             addNumberMenu(contextMenu,anchor);
       
   160         }
       
   161         else if(anchor.contains(QRegExp("^"+EMAIL_RULE)))
       
   162         {
       
   163             addEmailMenu(contextMenu,anchor);
       
   164         }
       
   165         else if(anchor.contains(QRegExp("^"+URL_RULE)))
       
   166         {
       
   167             addUrlMenu(contextMenu,anchor);
       
   168         }
       
   169     }
       
   170 
       
   171     connect(contextMenu,SIGNAL(aboutToClose()),this,SLOT(menuClosed()));
       
   172     
       
   173 }
       
   174 
       
   175 
       
   176 void UniViewerTextItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
       
   177 {
       
   178     HbTextEdit::mouseReleaseEvent(event);
       
   179 
       
   180     highlightText(false);
       
   181 
       
   182     QString anchor = this->anchorAt(event->pos());
       
   183 
       
   184     if(!anchor.isEmpty() && !this->textCursor().hasSelection())
       
   185     {
       
   186         shortTapAction(anchor);
       
   187     }
       
   188 }
       
   189 
       
   190 void UniViewerTextItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
       
   191 {
       
   192     HbTextEdit::mousePressEvent(event);
       
   193 
       
   194     QTextDocument* doc = this->document();
       
   195 
       
   196     mCursorPos = doc->documentLayout()->hitTest(event->pos(), Qt::ExactHit);
       
   197 
       
   198     highlightText(true);
       
   199 }
       
   200 
       
   201 void UniViewerTextItem::addNumberMenu(HbMenu* contextMenu,const QString& data)
       
   202 {
       
   203     HbAction* action = NULL;
       
   204 
       
   205     action = contextMenu->addAction(LOC_OPEN_CONTACT_INFO, this, SLOT(openContactInfo()));
       
   206     action->setData(data);
       
   207 
       
   208     action = contextMenu->addAction(LOC_CALL, this, SLOT(call()));
       
   209     action->setData(data);
       
   210 
       
   211     action = contextMenu->addAction(LOC_SEND_MESSAGE, this, SLOT(sendMessage()));
       
   212     action->setData(data);
       
   213 
       
   214     action = contextMenu->addAction(LOC_SAVE_TO_CONTACTS, this, SLOT(saveToContacts()));
       
   215     action->setData(data);
       
   216 
       
   217     action = contextMenu->addAction(LOC_COPY, this, SLOT(copyToClipboard()));
       
   218     action->setData(data);
       
   219 }
       
   220 
       
   221 void UniViewerTextItem::addEmailMenu(HbMenu* contextMenu,const QString& data)
       
   222 {
       
   223     HbAction* action = NULL;
       
   224     
       
   225     action = contextMenu->addAction(LOC_CREATE_EMAIL, this, SLOT(createEmail()));
       
   226     action->setData(data);
       
   227     
       
   228     action = contextMenu->addAction(LOC_OPEN_CONTACT_INFO, this, SLOT(openContactInfo()));
       
   229     action->setData(data);
       
   230 
       
   231     action = contextMenu->addAction(LOC_SAVE_TO_CONTACTS, this, SLOT(saveToContacts()));
       
   232     action->setData(data);
       
   233 
       
   234     action = contextMenu->addAction(LOC_COPY, this, SLOT(copyToClipboard()));
       
   235     action->setData(data);
       
   236 }
       
   237 
       
   238 void UniViewerTextItem::addUrlMenu(HbMenu* contextMenu,const QString& data)
       
   239 {
       
   240     HbAction* action = NULL;
       
   241     
       
   242     action = contextMenu->addAction(LOC_OPEN_LINK, this, SLOT(openLink()));
       
   243     action->setData(data);
       
   244 
       
   245     action = contextMenu->addAction(LOC_ADD_TO_BOOKMARKS, this, SLOT(addToBookmarks()));
       
   246     action->setData(data);
       
   247 
       
   248     action = contextMenu->addAction(LOC_COPY_LINK, this, SLOT(copyToClipboard()));
       
   249     action->setData(data);
       
   250 }
       
   251 
       
   252 void UniViewerTextItem::shortTapAction(QString anchor)
       
   253 {
       
   254     HbAction action;
       
   255     action.setData(anchor);
       
   256 
       
   257     if(anchor.contains(NUMBER_RULE))
       
   258     {
       
   259         //open vcard template.
       
   260         connect(&action,SIGNAL(triggered()),this,SLOT(openContactInfo()));
       
   261     }
       
   262     else if(anchor.contains(EMAIL_RULE))
       
   263     {
       
   264         //Create email
       
   265         connect(&action,SIGNAL(triggered()),this,SLOT(createEmail()));
       
   266     }
       
   267     else if(anchor.contains(URL_RULE))
       
   268     {
       
   269         //Open link in the browser
       
   270         connect(&action,SIGNAL(triggered()),this,SLOT(openLink()));
       
   271     }
       
   272     
       
   273     action.trigger();
       
   274 }
       
   275 
       
   276 
       
   277 void UniViewerTextItem::copyToClipboard()
       
   278 {
       
   279     HbAction* action = qobject_cast<HbAction*>(sender());
       
   280 
       
   281     if(action)
       
   282     {
       
   283         QMimeData* data = new QMimeData();
       
   284         QString str = action->data().toString();
       
   285 
       
   286         //removing rule name before setting it to clipboard.
       
   287         str.remove(QRegExp("^"+NUMBER_RULE));
       
   288         str.remove(QRegExp("^"+EMAIL_RULE));
       
   289         str.remove(QRegExp("^"+URL_RULE));
       
   290 
       
   291         data->setText(str);
       
   292         QApplication::clipboard()->setMimeData(data);
       
   293     }
       
   294 }
       
   295 
       
   296 void UniViewerTextItem::call()
       
   297 {
       
   298     HbAction* action = qobject_cast<HbAction*>(sender());
       
   299 
       
   300     if(action)
       
   301     {
       
   302         QString phoneNumber = action->data().toString();
       
   303         phoneNumber.remove(NUMBER_RULE);
       
   304         
       
   305         //invoke dialer service and pass phoneNumber.        
       
   306         QString serviceName("com.nokia.services.telephony");
       
   307         QString operation("dial(QString)");
       
   308         
       
   309         XQServiceRequest* serviceRequest = new XQServiceRequest(serviceName,operation,false);
       
   310         
       
   311         connect(serviceRequest, SIGNAL(requestCompleted(QVariant)),
       
   312                 this, SLOT(onServiceRequestCompleted()));
       
   313         
       
   314         connect(serviceRequest, SIGNAL(requestError(int)),
       
   315                 this, SLOT(onServiceRequestCompleted()));
       
   316         
       
   317        *serviceRequest << phoneNumber;
       
   318        serviceRequest->send();
       
   319     }
       
   320 }
       
   321 
       
   322 void UniViewerTextItem::sendMessage()
       
   323 {
       
   324     HbAction* action = qobject_cast<HbAction*>(sender());
       
   325 
       
   326     if(action)
       
   327     {
       
   328         QString phoneNumber = action->data().toString();
       
   329         phoneNumber.remove(NUMBER_RULE);
       
   330         
       
   331         //invoke editor & pass phoneNumber.
       
   332         emit sendMessage(phoneNumber);
       
   333     }
       
   334 }
       
   335 
       
   336 void UniViewerTextItem::createEmail()
       
   337 {
       
   338     HbAction* action = qobject_cast<HbAction*>(sender());
       
   339 
       
   340     if(action)
       
   341     {
       
   342         QString emailId = action->data().toString();
       
   343         emailId.remove(EMAIL_RULE);
       
   344         //invoke email editor service & pass emailId.
       
   345     }
       
   346 }
       
   347 
       
   348 void UniViewerTextItem::openLink()
       
   349 {
       
   350     HbAction* action = qobject_cast<HbAction*>(sender());
       
   351 
       
   352     if(action)
       
   353     {
       
   354         QString url = action->data().toString();
       
   355         url.remove(URL_RULE);
       
   356         //invoke browser service  & pass url.
       
   357     }
       
   358 }
       
   359 
       
   360 void UniViewerTextItem::addToBookmarks()
       
   361 {
       
   362     HbAction* action = qobject_cast<HbAction*>(sender());
       
   363 
       
   364     if(action)
       
   365     {
       
   366         QString url = action->data().toString();
       
   367         url.remove(URL_RULE);
       
   368         //invoke browser service to save url.
       
   369     }
       
   370 }
       
   371 
       
   372 void UniViewerTextItem::openContactInfo()
       
   373 {
       
   374     HbAction* action = qobject_cast<HbAction*>(sender());
       
   375     
       
   376     if(action)
       
   377     {
       
   378         QList<QVariant> args;
       
   379         QString operation;
       
   380         
       
   381         QString data = action->data().toString();
       
   382         
       
   383         if(data.contains(QRegExp("^"+NUMBER_RULE)))
       
   384         {
       
   385             data.remove(NUMBER_RULE);
       
   386     
       
   387             int contactId = resolveContactId(data, 
       
   388                                              QContactPhoneNumber::DefinitionName,
       
   389                                              QContactPhoneNumber::FieldNumber);
       
   390     
       
   391             if(contactId > 0)
       
   392                 {
       
   393                 //open contact card
       
   394                 operation = QString("open(int)");
       
   395                 args << contactId;
       
   396                 }
       
   397             else
       
   398                 {
       
   399                 //save to contacts with phone number field prefilled.
       
   400         
       
   401                 operation = QString("editCreateNew(QString,QString)");
       
   402                 QString type = QContactPhoneNumber::DefinitionName;
       
   403         
       
   404                 args << type;
       
   405                 args << data;
       
   406                 }
       
   407         }
       
   408         else if(data.contains(QRegExp("^"+EMAIL_RULE)))
       
   409         {
       
   410             data.remove(EMAIL_RULE);
       
   411     
       
   412             int contactId = resolveContactId(data,
       
   413                                              QContactEmailAddress::DefinitionName,
       
   414                                              QContactEmailAddress::FieldEmailAddress);
       
   415             
       
   416             if(contactId > 0)
       
   417                 {
       
   418                 //open contact card
       
   419                 operation = QString("open(int)");
       
   420                 args << contactId;
       
   421                 }
       
   422             else
       
   423                 {
       
   424                 //save to contacts with e-mail field prefilled.
       
   425         
       
   426                 operation = QString("editCreateNew(QString,QString)");                
       
   427                 
       
   428                 QString type = QContactEmailAddress::DefinitionName;
       
   429         
       
   430                 args << type;
       
   431                 args << data;
       
   432                 }
       
   433         }
       
   434         
       
   435         //service stuff.
       
   436         QString serviceName("com.nokia.services.phonebookservices.Fetch");
       
   437      
       
   438         XQServiceRequest* serviceRequest = new XQServiceRequest(serviceName,operation,false);
       
   439         
       
   440         connect(serviceRequest, SIGNAL(requestCompleted(QVariant)),
       
   441                 this, SLOT(onServiceRequestCompleted()));
       
   442         
       
   443         connect(serviceRequest, SIGNAL(requestError(int)),
       
   444                 this, SLOT(onServiceRequestCompleted()));
       
   445         
       
   446         serviceRequest->setArguments(args);
       
   447         serviceRequest->send();
       
   448     }
       
   449 }
       
   450 
       
   451 
       
   452 void UniViewerTextItem::saveToContacts()
       
   453 {
       
   454     //handler for save to contacts.
       
   455 }
       
   456 
       
   457 void UniViewerTextItem::onServiceRequestCompleted()
       
   458     {
       
   459     //service request is now complete. delete it.
       
   460     
       
   461     XQServiceRequest* request = qobject_cast<XQServiceRequest*>(sender());
       
   462     
       
   463     if(request)
       
   464         {
       
   465         delete request;
       
   466         }
       
   467     }
       
   468 
       
   469 int UniViewerTextItem::resolveContactId(const QString& value,
       
   470                                         const QString& fieldName,
       
   471                                         const QString& fieldType)
       
   472     {
       
   473     int contactId = -1;
       
   474     
       
   475     QContactManager phonebookManager("symbian");
       
   476     
       
   477     QContactDetailFilter phoneFilter;
       
   478     phoneFilter.setDetailDefinitionName(fieldName, fieldType);
       
   479     phoneFilter.setValue(value);
       
   480     phoneFilter.setMatchFlags(QContactFilter::MatchEndsWith);
       
   481 
       
   482     QList<QContactLocalId> matchingContacts = phonebookManager.contacts(phoneFilter);
       
   483 
       
   484     if ( matchingContacts.count() > 0 ) 
       
   485         {       
       
   486         contactId = matchingContacts.at(0);   
       
   487         }
       
   488     
       
   489     return contactId;
       
   490     }
       
   491 
       
   492 void UniViewerTextItem::menuClosed()
       
   493 {
       
   494     highlightText(false);
       
   495 }
       
   496 
       
   497 void UniViewerTextItem::highlightText(bool highlight)
       
   498 {
       
   499     QTextBlock textBlock = this->document()->findBlock(mCursorPos);
       
   500 
       
   501     QTextBlock::iterator it;
       
   502 
       
   503     for (it = textBlock.begin(); !(it.atEnd()); ++it)
       
   504     {
       
   505         QTextFragment currentFragment = it.fragment();
       
   506         
       
   507         if (currentFragment.isValid() && currentFragment.contains(mCursorPos)
       
   508             && currentFragment.charFormat().fontUnderline())
       
   509         {
       
   510             int start = currentFragment.position();
       
   511             int length = currentFragment.length();
       
   512 
       
   513             QTextCursor cursor = this->textCursor();
       
   514             cursor.clearSelection();
       
   515             cursor.setPosition(start);
       
   516             cursor.setPosition(start + length,QTextCursor::KeepAnchor);
       
   517 
       
   518             if(highlight)
       
   519             {
       
   520                 cursor.mergeCharFormat(mFormatHighlight);
       
   521             }
       
   522             else
       
   523             {
       
   524                 cursor.mergeCharFormat(mFormatNormal);
       
   525             }
       
   526 
       
   527             cursor.clearSelection();
       
   528         }
       
   529     }
       
   530 }