|
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:Custom widget derived from HbTextEdit which provides rich text |
|
15 * processing |
|
16 * |
|
17 */ |
|
18 |
|
19 #include "univieweraddresswidget.h" |
|
20 |
|
21 // SYSTEM INCLUDES |
|
22 #include <QTextCursor> |
|
23 #include <QTextBlock> |
|
24 #include <QApplication> |
|
25 #include <QClipboard> |
|
26 |
|
27 #include <HbMenu> |
|
28 #include <HbAction> |
|
29 #include <HbTapGesture> |
|
30 |
|
31 #include <xqservicerequest.h> |
|
32 #include <xqappmgr.h> |
|
33 #include <cntservicescontact.h> |
|
34 #include <qtcontacts.h> |
|
35 #include <xqservicerequest.h> |
|
36 #include <xqaiwrequest.h> |
|
37 #include "msgcontacthandler.h" |
|
38 |
|
39 // LOCAL CONSTANTS |
|
40 const QString ADDRESS_SEPARATOR("; "); |
|
41 const QString ADDRESS_OPEN(" ("); |
|
42 const QString ADDRESS_CLOSE(")"); |
|
43 const QString SPACE(" "); |
|
44 |
|
45 //localization |
|
46 #define LOC_CONTACT_INFO hbTrId("txt_messaging_menu_contact_info") |
|
47 #define LOC_CALL hbTrId("txt_common_menu_call_verb") |
|
48 #define LOC_SEND_MESSAGE hbTrId("txt_common_menu_send_message") |
|
49 #define LOC_SAVE_TO_CONTACTS hbTrId("txt_common_menu_save_to_contacts") |
|
50 #define LOC_COPY hbTrId("txt_common_menu_copy") |
|
51 |
|
52 const QString BG_FRAME_GRAPHICS("qtg_fr_lineedit_normal"); |
|
53 |
|
54 //--------------------------------------------------------------- |
|
55 // UniViewerAddressWidget::UniViewerAddressWidget |
|
56 // @see header file |
|
57 //--------------------------------------------------------------- |
|
58 UniViewerAddressWidget::UniViewerAddressWidget(QGraphicsItem * parent) : |
|
59 HbTextEdit(parent), |
|
60 mCursorPos(-1) |
|
61 { |
|
62 this->setReadOnly(true); |
|
63 this->setScrollable(false); |
|
64 this->setFlag(QGraphicsItem::ItemIsFocusable,false); |
|
65 this->setCursorVisibility(Hb::TextCursorHidden); |
|
66 this->setBackgroundItem(0); |
|
67 |
|
68 HbFontSpec fontSpec(HbFontSpec::Secondary); |
|
69 QFont font = fontSpec.font(); |
|
70 this->setFont(font); |
|
71 |
|
72 mFormatNormal.setForeground(palette().link()); |
|
73 mFormatNormal.setBackground(Qt::transparent); |
|
74 |
|
75 mFormatHighlight.setBackground(palette().highlight()); |
|
76 mFormatHighlight.setForeground(palette().highlightedText()); |
|
77 |
|
78 connect(this, SIGNAL(aboutToShowContextMenu(HbMenu*,QPointF)), |
|
79 this, SLOT(aboutToShowContextMenu(HbMenu*,QPointF))); |
|
80 } |
|
81 |
|
82 //--------------------------------------------------------------- |
|
83 // UniViewerAddressWidget::~UniViewerAddressWidget |
|
84 // @see header file |
|
85 //--------------------------------------------------------------- |
|
86 UniViewerAddressWidget::~UniViewerAddressWidget() |
|
87 { |
|
88 } |
|
89 |
|
90 //--------------------------------------------------------------- |
|
91 //UniViewerAddressWidget :: gestureEvent |
|
92 // @see header file |
|
93 //--------------------------------------------------------------- |
|
94 void UniViewerAddressWidget::gestureEvent(QGestureEvent* event) |
|
95 { |
|
96 //handle gesture to highlight and dehighlight find item. |
|
97 |
|
98 if(HbTapGesture *tap = qobject_cast<HbTapGesture*>(event->gesture(Qt::TapGesture))) |
|
99 { |
|
100 //capturing gesture position, and map to local co-ordinates. |
|
101 QPointF pos = mapFromScene(tap->scenePosition()); |
|
102 |
|
103 switch (tap->state()) |
|
104 { |
|
105 case Qt::GestureStarted: |
|
106 { |
|
107 //highlight find item. |
|
108 QTextDocument* doc = this->document(); |
|
109 mCursorPos = doc->documentLayout()->hitTest(pos, Qt::ExactHit); |
|
110 highlightText(true); |
|
111 break; |
|
112 } |
|
113 |
|
114 case Qt::GestureFinished: |
|
115 { |
|
116 if (HbTapGesture::Tap == tap->tapStyleHint()) |
|
117 { |
|
118 //gesture is finshed dehighlight text. |
|
119 highlightText(false); |
|
120 |
|
121 QString anchor = this->anchorAt(pos); |
|
122 |
|
123 //do short tap action. |
|
124 if (!anchor.isEmpty() && !this->textCursor().hasSelection()) |
|
125 { |
|
126 shortTapAction(anchor,tap->scenePosition()); |
|
127 } |
|
128 } |
|
129 break; |
|
130 } |
|
131 |
|
132 case Qt::GestureCanceled: |
|
133 { |
|
134 //gesture is canceled due to pan or swipe, dehighlight text. |
|
135 if (HbTapGesture::Tap == tap->tapStyleHint()) |
|
136 { |
|
137 highlightText(false); |
|
138 break; |
|
139 } |
|
140 } |
|
141 default: |
|
142 break; |
|
143 } |
|
144 |
|
145 event->accept(); |
|
146 } |
|
147 else |
|
148 { |
|
149 event->ignore(); |
|
150 } |
|
151 |
|
152 //passing gesture event to base class. |
|
153 HbTextEdit::gestureEvent(event); |
|
154 } |
|
155 |
|
156 |
|
157 //---------------------------------------------------------------------------- |
|
158 // UniViewerAddressWidget::populate |
|
159 // @see header file |
|
160 //---------------------------------------------------------------------------- |
|
161 void UniViewerAddressWidget::populate(const QString &label, |
|
162 const QString &address, |
|
163 const QString &alias) |
|
164 { |
|
165 QString labelText = label; |
|
166 labelText.trimmed(); |
|
167 labelText += SPACE; |
|
168 |
|
169 //Font. |
|
170 HbFontSpec fontSpec(HbFontSpec::Secondary); |
|
171 qreal fontHeight = 0.0; |
|
172 style()->parameter("hb-param-text-height-tiny", fontHeight); |
|
173 fontSpec.setTextHeight(fontHeight); |
|
174 QFont font = fontSpec.font(); |
|
175 |
|
176 QTextCharFormat labelFormat; |
|
177 labelFormat.setFont(font); |
|
178 |
|
179 QTextCharFormat addressFormat; |
|
180 addressFormat.setForeground(palette().link()); |
|
181 addressFormat.setFontUnderline(true); |
|
182 |
|
183 // Insert the label then the addresses |
|
184 QTextCursor cursor(this->textCursor()); |
|
185 cursor.insertText(labelText,labelFormat); |
|
186 |
|
187 QString address1 = QString(); |
|
188 if (!(alias.isEmpty())) |
|
189 { |
|
190 address1.append(alias); |
|
191 QString alias1 = QString(); |
|
192 |
|
193 int totalNumbers = 0; |
|
194 MsgContactHandler::resolveContactDisplayName( |
|
195 address, |
|
196 alias1, |
|
197 totalNumbers); |
|
198 if (totalNumbers > 1) |
|
199 { |
|
200 address1.append(ADDRESS_OPEN); |
|
201 address1.append(address); |
|
202 address1.append(ADDRESS_CLOSE); |
|
203 } |
|
204 } |
|
205 else |
|
206 { |
|
207 address1.append(address); |
|
208 } |
|
209 addressFormat.setAnchorHref(address); |
|
210 cursor.insertText(address1, addressFormat); |
|
211 } |
|
212 |
|
213 //---------------------------------------------------------------------------- |
|
214 // UniViewerAddressWidget::populate |
|
215 // @see header file |
|
216 //---------------------------------------------------------------------------- |
|
217 void UniViewerAddressWidget::populate(const QString &label, |
|
218 ConvergedMessageAddressList addressList) |
|
219 { |
|
220 QString labelText = label; |
|
221 labelText.trimmed(); |
|
222 labelText += SPACE; |
|
223 |
|
224 //Font. |
|
225 HbFontSpec fontSpec(HbFontSpec::Secondary); |
|
226 qreal fontHeight = 0.0; |
|
227 style()->parameter("hb-param-text-height-tiny", fontHeight); |
|
228 fontSpec.setTextHeight(fontHeight); |
|
229 QFont font = fontSpec.font(); |
|
230 |
|
231 QTextCharFormat labelFormat; |
|
232 labelFormat.setFont(font); |
|
233 |
|
234 QTextCharFormat defaultFormat; |
|
235 defaultFormat.setForeground(palette().link()); |
|
236 |
|
237 QTextCharFormat addressFormat; |
|
238 addressFormat.setForeground(palette().link()); |
|
239 addressFormat.setFontUnderline(true); |
|
240 |
|
241 // Insert the label then the addresses |
|
242 QTextCursor cursor(this->document()); |
|
243 cursor.insertText(labelText,labelFormat); |
|
244 |
|
245 int addressCount = addressList.count(); |
|
246 |
|
247 for (int i = 0; i < addressCount; ++i) |
|
248 { |
|
249 |
|
250 QString address = QString(); |
|
251 if (! (addressList[i]->alias().isEmpty())) |
|
252 { |
|
253 address.append(addressList[i]->alias()); |
|
254 QString alias = QString(); |
|
255 |
|
256 int totalNumbers = 0; |
|
257 MsgContactHandler::resolveContactDisplayName( |
|
258 addressList[i]->address(), |
|
259 alias, |
|
260 totalNumbers); |
|
261 if (totalNumbers > 1) |
|
262 { |
|
263 address.append(ADDRESS_OPEN); |
|
264 address.append(addressList[i]->address()); |
|
265 address.append(ADDRESS_CLOSE); |
|
266 } |
|
267 } |
|
268 else |
|
269 { |
|
270 address.append(addressList[i]->address()); |
|
271 } |
|
272 |
|
273 addressFormat.setAnchorHref(addressList[i]->address()); |
|
274 cursor.insertText(address, addressFormat); |
|
275 |
|
276 if (addressCount - 1 != i) |
|
277 { |
|
278 cursor.insertText(ADDRESS_SEPARATOR, defaultFormat); |
|
279 } |
|
280 |
|
281 } |
|
282 } |
|
283 |
|
284 //---------------------------------------------------------------------------- |
|
285 // UniViewerAddressWidget::clearContent |
|
286 // @see header file |
|
287 //---------------------------------------------------------------------------- |
|
288 void UniViewerAddressWidget::clearContent() |
|
289 { |
|
290 this->document()->clear(); |
|
291 } |
|
292 |
|
293 //---------------------------------------------------------------------------- |
|
294 // UniViewerAddressWidget::menuClosed |
|
295 // @see header file |
|
296 //---------------------------------------------------------------------------- |
|
297 void UniViewerAddressWidget::menuClosed() |
|
298 { |
|
299 highlightText(false); |
|
300 } |
|
301 |
|
302 //---------------------------------------------------------------------------- |
|
303 // UniViewerAddressWidget::highlightText |
|
304 // @see header file |
|
305 //---------------------------------------------------------------------------- |
|
306 void UniViewerAddressWidget::highlightText(bool highlight) |
|
307 { |
|
308 QTextBlock textBlock = this->document()->findBlock(mCursorPos); |
|
309 |
|
310 QTextBlock::iterator it; |
|
311 |
|
312 for (it = textBlock.begin(); !(it.atEnd()); ++it) |
|
313 { |
|
314 QTextFragment currentFragment = it.fragment(); |
|
315 |
|
316 if (currentFragment.isValid() && currentFragment.contains(mCursorPos) |
|
317 && currentFragment.charFormat().fontUnderline()) |
|
318 { |
|
319 int start = currentFragment.position(); |
|
320 int length = currentFragment.length(); |
|
321 |
|
322 QTextCursor cursor = this->textCursor(); |
|
323 cursor.clearSelection(); |
|
324 cursor.setPosition(start); |
|
325 cursor.setPosition(start + length,QTextCursor::KeepAnchor); |
|
326 |
|
327 if(highlight) |
|
328 { |
|
329 cursor.mergeCharFormat(mFormatHighlight); |
|
330 } |
|
331 else |
|
332 { |
|
333 cursor.mergeCharFormat(mFormatNormal); |
|
334 } |
|
335 |
|
336 cursor.clearSelection(); |
|
337 break; |
|
338 } |
|
339 } |
|
340 } |
|
341 |
|
342 void UniViewerAddressWidget::aboutToShowContextMenu(HbMenu *contextMenu, const QPointF &pos) |
|
343 { |
|
344 //remove default actions. |
|
345 contextMenu->clearActions(); |
|
346 |
|
347 // Check if there is an anchor at this pos |
|
348 QString anchor = this->anchorAt(pos); |
|
349 |
|
350 if(!anchor.isEmpty() && !this->textCursor().hasSelection()) |
|
351 { |
|
352 populateMenu(contextMenu,anchor); |
|
353 } |
|
354 } |
|
355 |
|
356 void UniViewerAddressWidget::populateMenu(HbMenu* contextMenu,const QString& data) |
|
357 { |
|
358 HbAction* action = NULL; |
|
359 |
|
360 int contactId = MsgContactHandler::resolveContactDisplayName( |
|
361 data, |
|
362 QContactPhoneNumber::DefinitionName, |
|
363 QContactPhoneNumber::FieldNumber); |
|
364 |
|
365 if(contactId > 0) |
|
366 { |
|
367 action = contextMenu->addAction(LOC_CONTACT_INFO, this, SLOT(openContactInfo())); |
|
368 action->setData(data); |
|
369 } |
|
370 else |
|
371 { |
|
372 action = contextMenu->addAction(LOC_SAVE_TO_CONTACTS, this, SLOT(saveToContacts())); |
|
373 action->setData(data); |
|
374 } |
|
375 |
|
376 action = contextMenu->addAction(LOC_CALL, this, SLOT(call())); |
|
377 action->setData(data); |
|
378 |
|
379 action = contextMenu->addAction(LOC_SEND_MESSAGE, this, SLOT(sendMessage())); |
|
380 action->setData(data); |
|
381 |
|
382 action = contextMenu->addAction(LOC_COPY, this, SLOT(copyToClipboard())); |
|
383 action->setData(data); |
|
384 |
|
385 connect(contextMenu,SIGNAL(aboutToClose()),this,SLOT(menuClosed())); |
|
386 } |
|
387 |
|
388 void UniViewerAddressWidget::shortTapAction(QString anchor,const QPointF& pos) |
|
389 { |
|
390 HbAction action; |
|
391 action.setData(anchor); |
|
392 |
|
393 |
|
394 int contactId = MsgContactHandler::resolveContactDisplayName( |
|
395 anchor, |
|
396 QContactPhoneNumber::DefinitionName, |
|
397 QContactPhoneNumber::FieldNumber); |
|
398 |
|
399 if(contactId > 0 ) |
|
400 { |
|
401 //if resolved conatct open contact card |
|
402 connect(&action,SIGNAL(triggered()),this,SLOT(openContactInfo())); |
|
403 } |
|
404 else |
|
405 { |
|
406 //unresolved contact show popup. |
|
407 highlightText(true); |
|
408 |
|
409 HbMenu* contextMenu = new HbMenu(); |
|
410 contextMenu->setDismissPolicy(HbPopup::TapAnywhere); |
|
411 contextMenu->setAttribute(Qt::WA_DeleteOnClose, true); |
|
412 contextMenu->setPreferredPos(pos); |
|
413 |
|
414 populateMenu(contextMenu,anchor); |
|
415 |
|
416 contextMenu->show(); |
|
417 } |
|
418 |
|
419 action.trigger(); |
|
420 } |
|
421 |
|
422 void UniViewerAddressWidget::copyToClipboard() |
|
423 { |
|
424 HbAction* action = qobject_cast<HbAction*>(sender()); |
|
425 |
|
426 if(action) |
|
427 { |
|
428 QMimeData* data = new QMimeData(); |
|
429 QString str = action->data().toString(); |
|
430 data->setText(str); |
|
431 QApplication::clipboard()->setMimeData(data); |
|
432 } |
|
433 } |
|
434 |
|
435 void UniViewerAddressWidget::call() |
|
436 { |
|
437 HbAction* action = qobject_cast<HbAction*>(sender()); |
|
438 |
|
439 if(action) |
|
440 { |
|
441 QString phoneNumber = action->data().toString(); |
|
442 |
|
443 //invoke dialer service and pass phoneNumber. |
|
444 QString serviceName("com.nokia.symbian.ICallDial"); |
|
445 QString operation("dial(QString)"); |
|
446 |
|
447 XQServiceRequest* serviceRequest = new XQServiceRequest(serviceName,operation,false); |
|
448 |
|
449 connect(serviceRequest, SIGNAL(requestCompleted(QVariant)), |
|
450 this, SLOT(onServiceRequestCompleted())); |
|
451 |
|
452 connect(serviceRequest, SIGNAL(requestError(int)), |
|
453 this, SLOT(onServiceRequestCompleted())); |
|
454 |
|
455 *serviceRequest << phoneNumber; |
|
456 serviceRequest->send(); |
|
457 } |
|
458 } |
|
459 |
|
460 void UniViewerAddressWidget::onServiceRequestCompleted() |
|
461 { |
|
462 //service request is now complete. delete it. |
|
463 XQServiceRequest* request = qobject_cast<XQServiceRequest*>(sender()); |
|
464 |
|
465 if(request) |
|
466 { |
|
467 delete request; |
|
468 } |
|
469 } |
|
470 |
|
471 |
|
472 void UniViewerAddressWidget::openContactInfo() |
|
473 { |
|
474 HbAction* action = qobject_cast<HbAction*>(sender()); |
|
475 |
|
476 if(action) |
|
477 { |
|
478 QList<QVariant> args; |
|
479 QString operation; |
|
480 |
|
481 QString data = action->data().toString(); |
|
482 |
|
483 int contactId = MsgContactHandler::resolveContactDisplayName( |
|
484 data, |
|
485 QContactPhoneNumber::DefinitionName, |
|
486 QContactPhoneNumber::FieldNumber); |
|
487 |
|
488 // if contact is unresolved on phone number field |
|
489 // then, try resolving it on email address field |
|
490 if(contactId <= 0) |
|
491 { |
|
492 contactId = MsgContactHandler::resolveContactDisplayName( |
|
493 data, |
|
494 QContactEmailAddress::DefinitionName, |
|
495 QContactEmailAddress::FieldEmailAddress); |
|
496 } |
|
497 |
|
498 if(contactId > 0) |
|
499 { |
|
500 //open contact card |
|
501 operation = QString("open(int)"); |
|
502 args << contactId; |
|
503 } |
|
504 else |
|
505 { |
|
506 //save to contacts with phone number field prefilled. |
|
507 |
|
508 operation = QString("editCreateNew(QString,QString)"); |
|
509 QString type = QContactPhoneNumber::DefinitionName; |
|
510 |
|
511 args << type; |
|
512 args << data; |
|
513 } |
|
514 |
|
515 //service stuff. |
|
516 QString serviceName("com.nokia.services.phonebookservices"); |
|
517 |
|
518 XQAiwRequest* request; |
|
519 XQApplicationManager appManager; |
|
520 request = appManager.create(serviceName, "Fetch", operation, true); // embedded |
|
521 if ( request == NULL ) |
|
522 { |
|
523 return; |
|
524 } |
|
525 |
|
526 // Result handlers |
|
527 connect (request, SIGNAL(requestOk(const QVariant&)), |
|
528 this, SLOT(handleOk(const QVariant&))); |
|
529 connect (request, SIGNAL(requestError(const QVariant&)), |
|
530 this, SLOT(handleError(const QVariant&))); |
|
531 |
|
532 request->setArguments(args); |
|
533 request->send(); |
|
534 delete request; |
|
535 } |
|
536 } |
|
537 |
|
538 void UniViewerAddressWidget::handleOk(const QVariant& result) |
|
539 { |
|
540 Q_UNUSED(result) |
|
541 } |
|
542 |
|
543 void UniViewerAddressWidget::handleError(int errorCode, const QString& errorMessage) |
|
544 { |
|
545 Q_UNUSED(errorMessage) |
|
546 Q_UNUSED(errorCode) |
|
547 } |
|
548 |
|
549 void UniViewerAddressWidget::saveToContacts() |
|
550 { |
|
551 openContactInfo(); |
|
552 } |
|
553 |
|
554 void UniViewerAddressWidget::sendMessage() |
|
555 { |
|
556 HbAction* action = qobject_cast<HbAction*>(sender()); |
|
557 |
|
558 if(action) |
|
559 { |
|
560 QString phoneNumber = action->data().toString(); |
|
561 QString alias; |
|
562 |
|
563 QTextBlock textBlock = this->document()->findBlock(mCursorPos); |
|
564 |
|
565 QTextBlock::iterator it; |
|
566 |
|
567 for (it = textBlock.begin(); !(it.atEnd()); ++it) |
|
568 { |
|
569 QTextFragment currentFragment = it.fragment(); |
|
570 |
|
571 if (currentFragment.isValid() && currentFragment.contains(mCursorPos) |
|
572 && currentFragment.charFormat().fontUnderline()) |
|
573 { |
|
574 QString txt = currentFragment.text(); |
|
575 if(txt != phoneNumber) |
|
576 { |
|
577 alias = txt; |
|
578 } |
|
579 break; |
|
580 } |
|
581 } |
|
582 |
|
583 |
|
584 //invoke editor & pass phoneNumber. |
|
585 emit sendMessage(phoneNumber,alias); |
|
586 } |
|
587 } |
|
588 |
|
589 // EOF |