diff -r dcf0eedfc1a3 -r d189ee25cf9d emailuis/nmailui/src/nmeditorheader.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emailuis/nmailui/src/nmeditorheader.cpp Tue Aug 31 15:04:17 2010 +0300 @@ -0,0 +1,507 @@ +/* +* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: Message editor header container class. Collects the header widgets. +* +*/ + +#include "nmuiheaders.h" + +// Layout +// These match to the defintions in nmeditorview.docml +static const char *NMUI_EDITOR_CONTAINER = "scrollAreaContents"; +static const char *NMUI_EDITOR_SUBJECT_FIELD = "editorSubjectField"; +static const char *NMUI_EDITOR_SUBJECT_EDIT = "editorSubjectEdit"; +static const char *NMUI_EDITOR_TO_FIELD = "editorToField"; +static const char *NMUI_EDITOR_CC_FIELD = "editorCcField"; +static const char *NMUI_EDITOR_BCC_FIELD = "editorBccField"; +static const char *NMUI_EDITOR_PRIORITY_ICON = "editPriorityIcon"; +static const char *NMUI_EDITOR_FOLLOWUP_ICON = "editFollowUpIcon"; +static const char *NMUI_EDITOR_ATTACHMENT_LIST = "attachmentListWidget"; +static const char *NMUI_EDITOR_PREFIX_TO = "editorTo"; +static const char *NMUI_EDITOR_PREFIX_CC = "editorCc"; +static const char *NMUI_EDITOR_PREFIX_BCC = "editorBcc"; + +static const int NmMaxRows = 10000; + +// this timeout seems to be long enough for all cases. see sendDelayedHeaderHeightChanged +static const int NmLayoutSystemWaitTimer = 500; // 0.5 sec + +/*! + Constructor +*/ +NmEditorHeader::NmEditorHeader( + QObject *parent, NmApplication &application, HbDocumentLoader *documentLoader) : + QObject(parent), + mApplication(application), + mDocumentLoader(documentLoader), + mHeaderHeight(0), + mIconVisible(false), + mSubjectEdit(NULL), + mRecipientFieldsEmpty(true), + mAttachmentList(NULL), + mToField(NULL), + mCcField(NULL), + mBccField(NULL), + mCcBccFieldVisible(false) +{ + NM_FUNCTION; + + loadWidgets(); + createConnections(); +} + +/*! + Destructor +*/ +NmEditorHeader::~NmEditorHeader() +{ + NM_FUNCTION; +} + +/*! + Load widgets from XML for the header. +*/ +void NmEditorHeader::loadWidgets() +{ + NM_FUNCTION; + + // Load widgets from docml and construct handlers. Those widgets that are not shown by default + // are hidden and removed from the layout at this phase. + HbWidget *contentWidget = + qobject_cast(mDocumentLoader->findWidget(NMUI_EDITOR_CONTAINER)); + if (contentWidget) { + mLayout = static_cast(contentWidget->layout()); + + // base class QObject takes the deleting responsibility + mToField = new NmRecipientField(this, *mDocumentLoader, NMUI_EDITOR_PREFIX_TO); + mCcField = new NmRecipientField(this, *mDocumentLoader, NMUI_EDITOR_PREFIX_CC); + mBccField = new NmRecipientField(this, *mDocumentLoader, NMUI_EDITOR_PREFIX_BCC); + + // Sets up editor properties like no prediction, lower case preferred etc. + HbEditorInterface toEditorInterface(mToField->editor()); + HbEditorInterface ccEditorInterface(mCcField->editor()); + HbEditorInterface bccEditorInterface(mBccField->editor()); + toEditorInterface.setUpAsLatinAlphabetOnlyEditor(); + ccEditorInterface.setUpAsLatinAlphabetOnlyEditor(); + bccEditorInterface.setUpAsLatinAlphabetOnlyEditor(); + + mToWidget = qobject_cast(mDocumentLoader->findWidget(NMUI_EDITOR_TO_FIELD)); + + // Cc field is not shown by default. It needs to be both hidden and removed from the layout. + mCcWidget = qobject_cast(mDocumentLoader->findWidget(NMUI_EDITOR_CC_FIELD)); + mCcWidget->hide(); + mLayout->removeItem(mCcWidget); + + // Bcc field is not shown by default. It needs to be both hidden and removed from the layout. + mBccWidget = qobject_cast(mDocumentLoader->findWidget(NMUI_EDITOR_BCC_FIELD)); + mBccWidget->hide(); + mLayout->removeItem(mBccWidget); + + mSubjectWidget = + qobject_cast(mDocumentLoader->findWidget(NMUI_EDITOR_SUBJECT_FIELD)); + mSubjectLayout = static_cast(mSubjectWidget->layout()); + + // Add Subject: field + mSubjectEdit = qobject_cast + (mDocumentLoader->findWidget(NMUI_EDITOR_SUBJECT_EDIT)); + mSubjectEdit->setMaxRows(NmMaxRows); + + // Add attachment list + mAttachmentListWidget = qobject_cast + (mDocumentLoader->findWidget(NMUI_EDITOR_ATTACHMENT_LIST)); + // Create attachment list handling object + mAttachmentList = new NmAttachmentList(*mAttachmentListWidget); + mAttachmentList->setParent(this); // ownership changes + mAttachmentListWidget->hide(); + mLayout->removeItem(&mAttachmentList->listWidget()); + + // Add priority icon + mPriorityIcon = qobject_cast + (mDocumentLoader->findWidget(NMUI_EDITOR_PRIORITY_ICON)); + mPriorityIcon->hide(); + mSubjectLayout->removeItem(mPriorityIcon); + + // follow-up icon is not yet supported + HbLabel *followUpIcon = qobject_cast + (mDocumentLoader->findWidget(NMUI_EDITOR_FOLLOWUP_ICON)); + followUpIcon->hide(); + mSubjectLayout->removeItem(followUpIcon); + } +} + +/*! + Create signal - slot connections. +*/ +void NmEditorHeader::createConnections() +{ + NM_FUNCTION; + + // Signals for checking if the recipient fields have text. + connect(mToField, SIGNAL(textChanged(const QString &)), + this, SLOT(editorContentChanged())); + connect(mCcField, SIGNAL(textChanged(const QString &)), + this, SLOT(editorContentChanged())); + connect(mBccField, SIGNAL(textChanged(const QString &)), + this, SLOT(editorContentChanged())); + + // Signals for handling the recipient field expanding + connect(mToField, SIGNAL(textChanged(const QString &)), + this, SLOT(sendDelayedHeaderHeightChanged())); + connect(mCcField, SIGNAL(textChanged(const QString &)), + this, SLOT(sendDelayedHeaderHeightChanged())); + connect(mBccField, SIGNAL(textChanged(const QString &)), + this, SLOT(sendDelayedHeaderHeightChanged())); + connect(mSubjectEdit, SIGNAL(contentsChanged()), this, SLOT(sendDelayedHeaderHeightChanged())); + + // Signals for handling the attachment list + connect(&mAttachmentList->listWidget(), SIGNAL(itemActivated(int)), + this, SLOT(attachmentActivated(int))); + connect(&mAttachmentList->listWidget(), SIGNAL(longPressed(int, QPointF)), + this, SLOT(attachmentLongPressed(int, QPointF))); +} + +/*! + Show or hide recipient field +*/ +void NmEditorHeader::setFieldVisibility(bool isVisible) +{ + if ( mCcBccFieldVisible != isVisible ) { + mCcBccFieldVisible = isVisible; + if (mCcBccFieldVisible) { + mLayout->insertItem(1, mBccWidget); + mLayout->insertItem(1, mCcWidget); + mCcWidget->show(); + mBccWidget->show(); + } + else { + mCcWidget->hide(); + mBccWidget->hide(); + mLayout->removeItem(mCcWidget); + mLayout->removeItem(mBccWidget); + } + sendDelayedHeaderHeightChanged(); + } +} + +/*! + Return the sum of the header widget heights. This contains all the spacings a well. + */ +qreal NmEditorHeader::headerHeight() const +{ + NM_FUNCTION; + + // get the layout's vertical spacing + qreal spacing = 0; + HbStyle().parameter("hb-param-margin-gene-middle-vertical", spacing); + + // calculate the height + qreal height = 0; + + height += mToField->height(); // returns widget's geometry height + height += spacing; + + if (mCcBccFieldVisible) { + height += mCcField->height(); // returns widget's geometry height + height += spacing; + + height += mBccField->height(); // returns widget's geometry height + height += spacing; + } + + height += mSubjectWidget->geometry().height(); + height += spacing; + + if (mAttachmentList->listWidget().isVisible()) { + height += mAttachmentList->listWidget().geometry().height(); + height += spacing; + } + + return height; +} + +/*! + This is called when the contents of some of the header widgets have been changed. When the + contents change the widget's actual size may also change. The header area height is needed to + calculate the size hints of the body and the scroll area widgets. We need to use a timer to let + the Orbit FW adjust the heights eg. if the subject and recipient fields are expanded by the FW. + It would be best to find a solution which doesn't depend on the header area's actual height size + information. + */ +void NmEditorHeader::sendDelayedHeaderHeightChanged() +{ + NM_FUNCTION; + QTimer::singleShot(NmLayoutSystemWaitTimer, this, SLOT(sendHeaderHeightChanged())); +} + +/*! + Send a signal that the header area height has been changed if necessary. This is needed for the + body and scroll area widgets. See NmEditorTextEdit::setHeaderHeight for more info. + */ +void NmEditorHeader::sendHeaderHeightChanged() +{ + qreal hHeight = headerHeight(); + if (mHeaderHeight != hHeight) { + mHeaderHeight = hHeight; + emit headerHeightChanged(mHeaderHeight); + } +} + +/*! + Because header filds have fixed size policy. This function must be called to set + new width for every header field when orintation has been changed. + */ +void NmEditorHeader::adjustHeaderWidth() +{ + NM_FUNCTION; + + int newWidth = mApplication.screenSize().width(); + mToWidget->setPreferredWidth(newWidth); + mCcWidget->setPreferredWidth(newWidth); + mBccWidget->setPreferredWidth(newWidth); + mSubjectWidget->setPreferredWidth(newWidth); + mAttachmentListWidget->setPreferredWidth(newWidth); + mSubjectWidget->setPreferredWidth(newWidth); +} + +/*! + Return pointer to to edit + */ +NmRecipientLineEdit* NmEditorHeader::toEdit() const +{ + NM_FUNCTION; + + return mToField->editor(); +} + +/*! + Return pointer to cc edit + */ +NmRecipientLineEdit* NmEditorHeader::ccEdit() const +{ + NM_FUNCTION; + + return mCcField->editor(); +} + +/*! + Return pointer to bcc edit + */ +NmRecipientLineEdit* NmEditorHeader::bccEdit() const +{ + NM_FUNCTION; + + return mBccField->editor(); +} + +/*! + Return pointer to subject field + */ +NmHtmlLineEdit* NmEditorHeader::subjectEdit() const +{ + NM_FUNCTION; + + return mSubjectEdit; +} + +/*! + Checks if recipient editors are empty and emits a signal if + the state is changed. +*/ +void NmEditorHeader::editorContentChanged() +{ + NM_FUNCTION; + + bool recipientsFieldsEmpty(true); + if (mToField->text().length()) { + recipientsFieldsEmpty = false; + } + else if (mCcField->text().length()) { + recipientsFieldsEmpty = false; + } + else if (mBccField->text().length()) { + recipientsFieldsEmpty = false; + } + if (mRecipientFieldsEmpty != recipientsFieldsEmpty) { + mRecipientFieldsEmpty = recipientsFieldsEmpty; + emit recipientFieldsHaveContent(!mRecipientFieldsEmpty); + } +} + +/*! + Sets the icon for priority + */ +void NmEditorHeader::setPriority(NmMessagePriority priority) +{ + NM_FUNCTION; + + switch (priority) { + case NmMessagePriorityHigh: + setPriority(NmActionResponseCommandPriorityHigh); + break; + case NmMessagePriorityLow: + setPriority(NmActionResponseCommandPriorityLow); + break; + default: + setPriority(NmActionResponseCommandNone); + break; + } +} + +/*! + Sets the icon for priority + */ +void NmEditorHeader::setPriority(NmActionResponseCommand prio) +{ + NM_FUNCTION; + + switch(prio) { + case NmActionResponseCommandPriorityHigh: + if (!mIconVisible) { + mIconVisible = true; + // icon widget is just after the subject line edit (see docml) + mSubjectLayout->insertItem(2, mPriorityIcon); + mPriorityIcon->show(); + } + mPriorityIcon->setIcon( + NmIcons::getIcon(NmIcons::NmIconPriorityHigh)); + break; + case NmActionResponseCommandPriorityLow: + if (!mIconVisible) { + mIconVisible = true; + // icon widget is just after the subject line edit (see docml) + mSubjectLayout->insertItem(2, mPriorityIcon); + mPriorityIcon->show(); + } + mPriorityIcon->setIcon( + NmIcons::getIcon(NmIcons::NmIconPriorityLow)); + break; + default: + if (mIconVisible) { + mIconVisible = false; + HbIcon emptyIcon; + mPriorityIcon->setIcon(emptyIcon); + mSubjectLayout->removeItem(mPriorityIcon); + mPriorityIcon->hide(); + } + break; + } + sendDelayedHeaderHeightChanged(); +} + +/*! + Adds an attachment to attachment list for mail. + */ +void NmEditorHeader::addAttachment( + const QString &fileName, const QString &fileSize, const NmId &nmid) +{ + NM_FUNCTION; + + mAttachmentList->insertAttachment(fileName, fileSize, nmid); + + if (!mAttachmentList->listWidget().isVisible()) { + // attachment list is inserted just before the body widget (see docml). + mLayout->insertItem(mLayout->count() - 1, &mAttachmentList->listWidget()); + mAttachmentList->listWidget().show(); + } + + sendHeaderHeightChanged(); +} + +/*! + Remove attachment from the list. This function is used when + attachment adding has failed and attachment id is not known. + */ +void NmEditorHeader::removeAttachment(const QString &fileName) +{ + NM_FUNCTION; + + mAttachmentList->removeAttachment(fileName); + if (mAttachmentList->count() == 0) { + mAttachmentList->listWidget().hide(); + mLayout->removeItem(&mAttachmentList->listWidget()); + } + sendDelayedHeaderHeightChanged(); +} + +/*! + Remove attachment from the list. This function is used when + attachment has been selected for remove. + */ +void NmEditorHeader::removeAttachment(const NmId &nmid) +{ + NM_FUNCTION; + + mAttachmentList->removeAttachment(nmid); + if (mAttachmentList->count() == 0) { + mAttachmentList->listWidget().hide(); + mLayout->removeItem(&mAttachmentList->listWidget()); + } + sendDelayedHeaderHeightChanged(); +} + +/*! + This function set messagePartId and fileSize for attachment. + */ +void NmEditorHeader::setAttachmentParameters( + const QString &fileName, + const NmId &msgPartId, + const QString &fileSize, + int result) +{ + NM_FUNCTION; + + if (result == NmNoError) { + // Attachment adding succesful, set message part id and size for attachment + mAttachmentList->setAttachmentPartId(fileName, msgPartId); + mAttachmentList->setAttachmentSize(msgPartId, fileSize); + } +} + +/*! + Slot attachment activated from attachment list by short tap. + */ +void NmEditorHeader::attachmentActivated(int arrayIndex) +{ + NM_FUNCTION; + + emit attachmentShortPressed(mAttachmentList->nmIdByIndex(arrayIndex)); +} + +/*! + Slot attachment selected from attachment list by longtap. + */ +void NmEditorHeader::attachmentLongPressed(int arrayIndex, QPointF point) +{ + NM_FUNCTION; + + // Remove selected attachment + emit attachmentLongPressed(mAttachmentList->nmIdByIndex(arrayIndex), point); +} + +/*! + This function is called when scroll position has been changed. + Function performs the pre calculated translation to set new positions for header fields + so that header stays visible when body is scrolled horizontally. + */ +void NmEditorHeader::repositHeader(const QTransform &transform) +{ + NM_FUNCTION; + + mToWidget->setTransform(transform); + mCcWidget->setTransform(transform); + mBccWidget->setTransform(transform); + mSubjectWidget->setTransform(transform); + mAttachmentListWidget->setTransform(transform); +} +