emailuis/nmailui/src/nmeditorheader.cpp
branchRCL_3
changeset 63 d189ee25cf9d
equal deleted inserted replaced
61:dcf0eedfc1a3 63:d189ee25cf9d
       
     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