|
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: Message editor header container class. Collects the header widgets. |
|
15 * |
|
16 */ |
|
17 |
|
18 #include "nmuiheaders.h" |
|
19 |
|
20 // Layout |
|
21 // These match to the defintions in nmeditorview.docml |
|
22 static const char *NMUI_EDITOR_CONTAINER = "scrollAreaContents"; |
|
23 static const char *NMUI_EDITOR_SUBJECT_FIELD = "editorSubjectField"; |
|
24 static const char *NMUI_EDITOR_SUBJECT_EDIT = "editorSubjectEdit"; |
|
25 static const char *NMUI_EDITOR_TO_FIELD = "editorToField"; |
|
26 static const char *NMUI_EDITOR_CC_FIELD = "editorCcField"; |
|
27 static const char *NMUI_EDITOR_BCC_FIELD = "editorBccField"; |
|
28 static const char *NMUI_EDITOR_PRIORITY_ICON = "editPriorityIcon"; |
|
29 static const char *NMUI_EDITOR_FOLLOWUP_ICON = "editFollowUpIcon"; |
|
30 static const char *NMUI_EDITOR_ATTACHMENT_LIST = "attachmentListWidget"; |
|
31 static const char *NMUI_EDITOR_PREFIX_TO = "editorTo"; |
|
32 static const char *NMUI_EDITOR_PREFIX_CC = "editorCc"; |
|
33 static const char *NMUI_EDITOR_PREFIX_BCC = "editorBcc"; |
|
34 |
|
35 static const int NmMaxRows = 10000; |
|
36 |
|
37 // this timeout seems to be long enough for all cases. see sendDelayedHeaderHeightChanged |
|
38 static const int NmLayoutSystemWaitTimer = 500; // 0.5 sec |
|
39 |
|
40 /*! |
|
41 Constructor |
|
42 */ |
|
43 NmEditorHeader::NmEditorHeader( |
|
44 QObject *parent, NmApplication &application, HbDocumentLoader *documentLoader) : |
|
45 QObject(parent), |
|
46 mApplication(application), |
|
47 mDocumentLoader(documentLoader), |
|
48 mHeaderHeight(0), |
|
49 mIconVisible(false), |
|
50 mSubjectEdit(NULL), |
|
51 mRecipientFieldsEmpty(true), |
|
52 mAttachmentList(NULL), |
|
53 mToField(NULL), |
|
54 mCcField(NULL), |
|
55 mBccField(NULL), |
|
56 mCcBccFieldVisible(false) |
|
57 { |
|
58 NM_FUNCTION; |
|
59 |
|
60 loadWidgets(); |
|
61 createConnections(); |
|
62 } |
|
63 |
|
64 /*! |
|
65 Destructor |
|
66 */ |
|
67 NmEditorHeader::~NmEditorHeader() |
|
68 { |
|
69 NM_FUNCTION; |
|
70 } |
|
71 |
|
72 /*! |
|
73 Load widgets from XML for the header. |
|
74 */ |
|
75 void NmEditorHeader::loadWidgets() |
|
76 { |
|
77 NM_FUNCTION; |
|
78 |
|
79 // Load widgets from docml and construct handlers. Those widgets that are not shown by default |
|
80 // are hidden and removed from the layout at this phase. |
|
81 HbWidget *contentWidget = |
|
82 qobject_cast<HbWidget *>(mDocumentLoader->findWidget(NMUI_EDITOR_CONTAINER)); |
|
83 if (contentWidget) { |
|
84 mLayout = static_cast<QGraphicsLinearLayout *>(contentWidget->layout()); |
|
85 |
|
86 // base class QObject takes the deleting responsibility |
|
87 mToField = new NmRecipientField(this, *mDocumentLoader, NMUI_EDITOR_PREFIX_TO); |
|
88 mCcField = new NmRecipientField(this, *mDocumentLoader, NMUI_EDITOR_PREFIX_CC); |
|
89 mBccField = new NmRecipientField(this, *mDocumentLoader, NMUI_EDITOR_PREFIX_BCC); |
|
90 |
|
91 // Sets up editor properties like no prediction, lower case preferred etc. |
|
92 HbEditorInterface toEditorInterface(mToField->editor()); |
|
93 HbEditorInterface ccEditorInterface(mCcField->editor()); |
|
94 HbEditorInterface bccEditorInterface(mBccField->editor()); |
|
95 toEditorInterface.setUpAsLatinAlphabetOnlyEditor(); |
|
96 ccEditorInterface.setUpAsLatinAlphabetOnlyEditor(); |
|
97 bccEditorInterface.setUpAsLatinAlphabetOnlyEditor(); |
|
98 |
|
99 mToWidget = qobject_cast<HbWidget *>(mDocumentLoader->findWidget(NMUI_EDITOR_TO_FIELD)); |
|
100 |
|
101 // Cc field is not shown by default. It needs to be both hidden and removed from the layout. |
|
102 mCcWidget = qobject_cast<HbWidget *>(mDocumentLoader->findWidget(NMUI_EDITOR_CC_FIELD)); |
|
103 mCcWidget->hide(); |
|
104 mLayout->removeItem(mCcWidget); |
|
105 |
|
106 // Bcc field is not shown by default. It needs to be both hidden and removed from the layout. |
|
107 mBccWidget = qobject_cast<HbWidget *>(mDocumentLoader->findWidget(NMUI_EDITOR_BCC_FIELD)); |
|
108 mBccWidget->hide(); |
|
109 mLayout->removeItem(mBccWidget); |
|
110 |
|
111 mSubjectWidget = |
|
112 qobject_cast<HbWidget *>(mDocumentLoader->findWidget(NMUI_EDITOR_SUBJECT_FIELD)); |
|
113 mSubjectLayout = static_cast<QGraphicsLinearLayout *>(mSubjectWidget->layout()); |
|
114 |
|
115 // Add Subject: field |
|
116 mSubjectEdit = qobject_cast<NmHtmlLineEdit *> |
|
117 (mDocumentLoader->findWidget(NMUI_EDITOR_SUBJECT_EDIT)); |
|
118 mSubjectEdit->setMaxRows(NmMaxRows); |
|
119 |
|
120 // Add attachment list |
|
121 mAttachmentListWidget = qobject_cast<NmAttachmentListWidget *> |
|
122 (mDocumentLoader->findWidget(NMUI_EDITOR_ATTACHMENT_LIST)); |
|
123 // Create attachment list handling object |
|
124 mAttachmentList = new NmAttachmentList(*mAttachmentListWidget); |
|
125 mAttachmentList->setParent(this); // ownership changes |
|
126 mAttachmentListWidget->hide(); |
|
127 mLayout->removeItem(&mAttachmentList->listWidget()); |
|
128 |
|
129 // Add priority icon |
|
130 mPriorityIcon = qobject_cast<HbLabel *> |
|
131 (mDocumentLoader->findWidget(NMUI_EDITOR_PRIORITY_ICON)); |
|
132 mPriorityIcon->hide(); |
|
133 mSubjectLayout->removeItem(mPriorityIcon); |
|
134 |
|
135 // follow-up icon is not yet supported |
|
136 HbLabel *followUpIcon = qobject_cast<HbLabel *> |
|
137 (mDocumentLoader->findWidget(NMUI_EDITOR_FOLLOWUP_ICON)); |
|
138 followUpIcon->hide(); |
|
139 mSubjectLayout->removeItem(followUpIcon); |
|
140 } |
|
141 } |
|
142 |
|
143 /*! |
|
144 Create signal - slot connections. |
|
145 */ |
|
146 void NmEditorHeader::createConnections() |
|
147 { |
|
148 NM_FUNCTION; |
|
149 |
|
150 // Signals for checking if the recipient fields have text. |
|
151 connect(mToField, SIGNAL(textChanged(const QString &)), |
|
152 this, SLOT(editorContentChanged())); |
|
153 connect(mCcField, SIGNAL(textChanged(const QString &)), |
|
154 this, SLOT(editorContentChanged())); |
|
155 connect(mBccField, SIGNAL(textChanged(const QString &)), |
|
156 this, SLOT(editorContentChanged())); |
|
157 |
|
158 // Signals for handling the recipient field expanding |
|
159 connect(mToField, SIGNAL(textChanged(const QString &)), |
|
160 this, SLOT(sendDelayedHeaderHeightChanged())); |
|
161 connect(mCcField, SIGNAL(textChanged(const QString &)), |
|
162 this, SLOT(sendDelayedHeaderHeightChanged())); |
|
163 connect(mBccField, SIGNAL(textChanged(const QString &)), |
|
164 this, SLOT(sendDelayedHeaderHeightChanged())); |
|
165 connect(mSubjectEdit, SIGNAL(contentsChanged()), this, SLOT(sendDelayedHeaderHeightChanged())); |
|
166 |
|
167 // Signals for handling the attachment list |
|
168 connect(&mAttachmentList->listWidget(), SIGNAL(itemActivated(int)), |
|
169 this, SLOT(attachmentActivated(int))); |
|
170 connect(&mAttachmentList->listWidget(), SIGNAL(longPressed(int, QPointF)), |
|
171 this, SLOT(attachmentLongPressed(int, QPointF))); |
|
172 } |
|
173 |
|
174 /*! |
|
175 Show or hide recipient field |
|
176 */ |
|
177 void NmEditorHeader::setFieldVisibility(bool isVisible) |
|
178 { |
|
179 if ( mCcBccFieldVisible != isVisible ) { |
|
180 mCcBccFieldVisible = isVisible; |
|
181 if (mCcBccFieldVisible) { |
|
182 mLayout->insertItem(1, mBccWidget); |
|
183 mLayout->insertItem(1, mCcWidget); |
|
184 mCcWidget->show(); |
|
185 mBccWidget->show(); |
|
186 } |
|
187 else { |
|
188 mCcWidget->hide(); |
|
189 mBccWidget->hide(); |
|
190 mLayout->removeItem(mCcWidget); |
|
191 mLayout->removeItem(mBccWidget); |
|
192 } |
|
193 sendDelayedHeaderHeightChanged(); |
|
194 } |
|
195 } |
|
196 |
|
197 /*! |
|
198 Return the sum of the header widget heights. This contains all the spacings a well. |
|
199 */ |
|
200 qreal NmEditorHeader::headerHeight() const |
|
201 { |
|
202 NM_FUNCTION; |
|
203 |
|
204 // get the layout's vertical spacing |
|
205 qreal spacing = 0; |
|
206 HbStyle().parameter("hb-param-margin-gene-middle-vertical", spacing); |
|
207 |
|
208 // calculate the height |
|
209 qreal height = 0; |
|
210 |
|
211 height += mToField->height(); // returns widget's geometry height |
|
212 height += spacing; |
|
213 |
|
214 if (mCcBccFieldVisible) { |
|
215 height += mCcField->height(); // returns widget's geometry height |
|
216 height += spacing; |
|
217 |
|
218 height += mBccField->height(); // returns widget's geometry height |
|
219 height += spacing; |
|
220 } |
|
221 |
|
222 height += mSubjectWidget->geometry().height(); |
|
223 height += spacing; |
|
224 |
|
225 if (mAttachmentList->listWidget().isVisible()) { |
|
226 height += mAttachmentList->listWidget().geometry().height(); |
|
227 height += spacing; |
|
228 } |
|
229 |
|
230 return height; |
|
231 } |
|
232 |
|
233 /*! |
|
234 This is called when the contents of some of the header widgets have been changed. When the |
|
235 contents change the widget's actual size may also change. The header area height is needed to |
|
236 calculate the size hints of the body and the scroll area widgets. We need to use a timer to let |
|
237 the Orbit FW adjust the heights eg. if the subject and recipient fields are expanded by the FW. |
|
238 It would be best to find a solution which doesn't depend on the header area's actual height size |
|
239 information. |
|
240 */ |
|
241 void NmEditorHeader::sendDelayedHeaderHeightChanged() |
|
242 { |
|
243 NM_FUNCTION; |
|
244 QTimer::singleShot(NmLayoutSystemWaitTimer, this, SLOT(sendHeaderHeightChanged())); |
|
245 } |
|
246 |
|
247 /*! |
|
248 Send a signal that the header area height has been changed if necessary. This is needed for the |
|
249 body and scroll area widgets. See NmEditorTextEdit::setHeaderHeight for more info. |
|
250 */ |
|
251 void NmEditorHeader::sendHeaderHeightChanged() |
|
252 { |
|
253 qreal hHeight = headerHeight(); |
|
254 if (mHeaderHeight != hHeight) { |
|
255 mHeaderHeight = hHeight; |
|
256 emit headerHeightChanged(mHeaderHeight); |
|
257 } |
|
258 } |
|
259 |
|
260 /*! |
|
261 Because header filds have fixed size policy. This function must be called to set |
|
262 new width for every header field when orintation has been changed. |
|
263 */ |
|
264 void NmEditorHeader::adjustHeaderWidth() |
|
265 { |
|
266 NM_FUNCTION; |
|
267 |
|
268 int newWidth = mApplication.screenSize().width(); |
|
269 mToWidget->setPreferredWidth(newWidth); |
|
270 mCcWidget->setPreferredWidth(newWidth); |
|
271 mBccWidget->setPreferredWidth(newWidth); |
|
272 mSubjectWidget->setPreferredWidth(newWidth); |
|
273 mAttachmentListWidget->setPreferredWidth(newWidth); |
|
274 mSubjectWidget->setPreferredWidth(newWidth); |
|
275 } |
|
276 |
|
277 /*! |
|
278 Return pointer to to edit |
|
279 */ |
|
280 NmRecipientLineEdit* NmEditorHeader::toEdit() const |
|
281 { |
|
282 NM_FUNCTION; |
|
283 |
|
284 return mToField->editor(); |
|
285 } |
|
286 |
|
287 /*! |
|
288 Return pointer to cc edit |
|
289 */ |
|
290 NmRecipientLineEdit* NmEditorHeader::ccEdit() const |
|
291 { |
|
292 NM_FUNCTION; |
|
293 |
|
294 return mCcField->editor(); |
|
295 } |
|
296 |
|
297 /*! |
|
298 Return pointer to bcc edit |
|
299 */ |
|
300 NmRecipientLineEdit* NmEditorHeader::bccEdit() const |
|
301 { |
|
302 NM_FUNCTION; |
|
303 |
|
304 return mBccField->editor(); |
|
305 } |
|
306 |
|
307 /*! |
|
308 Return pointer to subject field |
|
309 */ |
|
310 NmHtmlLineEdit* NmEditorHeader::subjectEdit() const |
|
311 { |
|
312 NM_FUNCTION; |
|
313 |
|
314 return mSubjectEdit; |
|
315 } |
|
316 |
|
317 /*! |
|
318 Checks if recipient editors are empty and emits a signal if |
|
319 the state is changed. |
|
320 */ |
|
321 void NmEditorHeader::editorContentChanged() |
|
322 { |
|
323 NM_FUNCTION; |
|
324 |
|
325 bool recipientsFieldsEmpty(true); |
|
326 if (mToField->text().length()) { |
|
327 recipientsFieldsEmpty = false; |
|
328 } |
|
329 else if (mCcField->text().length()) { |
|
330 recipientsFieldsEmpty = false; |
|
331 } |
|
332 else if (mBccField->text().length()) { |
|
333 recipientsFieldsEmpty = false; |
|
334 } |
|
335 if (mRecipientFieldsEmpty != recipientsFieldsEmpty) { |
|
336 mRecipientFieldsEmpty = recipientsFieldsEmpty; |
|
337 emit recipientFieldsHaveContent(!mRecipientFieldsEmpty); |
|
338 } |
|
339 } |
|
340 |
|
341 /*! |
|
342 Sets the icon for priority |
|
343 */ |
|
344 void NmEditorHeader::setPriority(NmMessagePriority priority) |
|
345 { |
|
346 NM_FUNCTION; |
|
347 |
|
348 switch (priority) { |
|
349 case NmMessagePriorityHigh: |
|
350 setPriority(NmActionResponseCommandPriorityHigh); |
|
351 break; |
|
352 case NmMessagePriorityLow: |
|
353 setPriority(NmActionResponseCommandPriorityLow); |
|
354 break; |
|
355 default: |
|
356 setPriority(NmActionResponseCommandNone); |
|
357 break; |
|
358 } |
|
359 } |
|
360 |
|
361 /*! |
|
362 Sets the icon for priority |
|
363 */ |
|
364 void NmEditorHeader::setPriority(NmActionResponseCommand prio) |
|
365 { |
|
366 NM_FUNCTION; |
|
367 |
|
368 switch(prio) { |
|
369 case NmActionResponseCommandPriorityHigh: |
|
370 if (!mIconVisible) { |
|
371 mIconVisible = true; |
|
372 // icon widget is just after the subject line edit (see docml) |
|
373 mSubjectLayout->insertItem(2, mPriorityIcon); |
|
374 mPriorityIcon->show(); |
|
375 } |
|
376 mPriorityIcon->setIcon( |
|
377 NmIcons::getIcon(NmIcons::NmIconPriorityHigh)); |
|
378 break; |
|
379 case NmActionResponseCommandPriorityLow: |
|
380 if (!mIconVisible) { |
|
381 mIconVisible = true; |
|
382 // icon widget is just after the subject line edit (see docml) |
|
383 mSubjectLayout->insertItem(2, mPriorityIcon); |
|
384 mPriorityIcon->show(); |
|
385 } |
|
386 mPriorityIcon->setIcon( |
|
387 NmIcons::getIcon(NmIcons::NmIconPriorityLow)); |
|
388 break; |
|
389 default: |
|
390 if (mIconVisible) { |
|
391 mIconVisible = false; |
|
392 HbIcon emptyIcon; |
|
393 mPriorityIcon->setIcon(emptyIcon); |
|
394 mSubjectLayout->removeItem(mPriorityIcon); |
|
395 mPriorityIcon->hide(); |
|
396 } |
|
397 break; |
|
398 } |
|
399 sendDelayedHeaderHeightChanged(); |
|
400 } |
|
401 |
|
402 /*! |
|
403 Adds an attachment to attachment list for mail. |
|
404 */ |
|
405 void NmEditorHeader::addAttachment( |
|
406 const QString &fileName, const QString &fileSize, const NmId &nmid) |
|
407 { |
|
408 NM_FUNCTION; |
|
409 |
|
410 mAttachmentList->insertAttachment(fileName, fileSize, nmid); |
|
411 |
|
412 if (!mAttachmentList->listWidget().isVisible()) { |
|
413 // attachment list is inserted just before the body widget (see docml). |
|
414 mLayout->insertItem(mLayout->count() - 1, &mAttachmentList->listWidget()); |
|
415 mAttachmentList->listWidget().show(); |
|
416 } |
|
417 |
|
418 sendHeaderHeightChanged(); |
|
419 } |
|
420 |
|
421 /*! |
|
422 Remove attachment from the list. This function is used when |
|
423 attachment adding has failed and attachment id is not known. |
|
424 */ |
|
425 void NmEditorHeader::removeAttachment(const QString &fileName) |
|
426 { |
|
427 NM_FUNCTION; |
|
428 |
|
429 mAttachmentList->removeAttachment(fileName); |
|
430 if (mAttachmentList->count() == 0) { |
|
431 mAttachmentList->listWidget().hide(); |
|
432 mLayout->removeItem(&mAttachmentList->listWidget()); |
|
433 } |
|
434 sendDelayedHeaderHeightChanged(); |
|
435 } |
|
436 |
|
437 /*! |
|
438 Remove attachment from the list. This function is used when |
|
439 attachment has been selected for remove. |
|
440 */ |
|
441 void NmEditorHeader::removeAttachment(const NmId &nmid) |
|
442 { |
|
443 NM_FUNCTION; |
|
444 |
|
445 mAttachmentList->removeAttachment(nmid); |
|
446 if (mAttachmentList->count() == 0) { |
|
447 mAttachmentList->listWidget().hide(); |
|
448 mLayout->removeItem(&mAttachmentList->listWidget()); |
|
449 } |
|
450 sendDelayedHeaderHeightChanged(); |
|
451 } |
|
452 |
|
453 /*! |
|
454 This function set messagePartId and fileSize for attachment. |
|
455 */ |
|
456 void NmEditorHeader::setAttachmentParameters( |
|
457 const QString &fileName, |
|
458 const NmId &msgPartId, |
|
459 const QString &fileSize, |
|
460 int result) |
|
461 { |
|
462 NM_FUNCTION; |
|
463 |
|
464 if (result == NmNoError) { |
|
465 // Attachment adding succesful, set message part id and size for attachment |
|
466 mAttachmentList->setAttachmentPartId(fileName, msgPartId); |
|
467 mAttachmentList->setAttachmentSize(msgPartId, fileSize); |
|
468 } |
|
469 } |
|
470 |
|
471 /*! |
|
472 Slot attachment activated from attachment list by short tap. |
|
473 */ |
|
474 void NmEditorHeader::attachmentActivated(int arrayIndex) |
|
475 { |
|
476 NM_FUNCTION; |
|
477 |
|
478 emit attachmentShortPressed(mAttachmentList->nmIdByIndex(arrayIndex)); |
|
479 } |
|
480 |
|
481 /*! |
|
482 Slot attachment selected from attachment list by longtap. |
|
483 */ |
|
484 void NmEditorHeader::attachmentLongPressed(int arrayIndex, QPointF point) |
|
485 { |
|
486 NM_FUNCTION; |
|
487 |
|
488 // Remove selected attachment |
|
489 emit attachmentLongPressed(mAttachmentList->nmIdByIndex(arrayIndex), point); |
|
490 } |
|
491 |
|
492 /*! |
|
493 This function is called when scroll position has been changed. |
|
494 Function performs the pre calculated translation to set new positions for header fields |
|
495 so that header stays visible when body is scrolled horizontally. |
|
496 */ |
|
497 void NmEditorHeader::repositHeader(const QTransform &transform) |
|
498 { |
|
499 NM_FUNCTION; |
|
500 |
|
501 mToWidget->setTransform(transform); |
|
502 mCcWidget->setTransform(transform); |
|
503 mBccWidget->setTransform(transform); |
|
504 mSubjectWidget->setTransform(transform); |
|
505 mAttachmentListWidget->setTransform(transform); |
|
506 } |
|
507 |