--- /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<HbWidget *>(mDocumentLoader->findWidget(NMUI_EDITOR_CONTAINER));
+ if (contentWidget) {
+ mLayout = static_cast<QGraphicsLinearLayout *>(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<HbWidget *>(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<HbWidget *>(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<HbWidget *>(mDocumentLoader->findWidget(NMUI_EDITOR_BCC_FIELD));
+ mBccWidget->hide();
+ mLayout->removeItem(mBccWidget);
+
+ mSubjectWidget =
+ qobject_cast<HbWidget *>(mDocumentLoader->findWidget(NMUI_EDITOR_SUBJECT_FIELD));
+ mSubjectLayout = static_cast<QGraphicsLinearLayout *>(mSubjectWidget->layout());
+
+ // Add Subject: field
+ mSubjectEdit = qobject_cast<NmHtmlLineEdit *>
+ (mDocumentLoader->findWidget(NMUI_EDITOR_SUBJECT_EDIT));
+ mSubjectEdit->setMaxRows(NmMaxRows);
+
+ // Add attachment list
+ mAttachmentListWidget = qobject_cast<NmAttachmentListWidget *>
+ (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<HbLabel *>
+ (mDocumentLoader->findWidget(NMUI_EDITOR_PRIORITY_ICON));
+ mPriorityIcon->hide();
+ mSubjectLayout->removeItem(mPriorityIcon);
+
+ // follow-up icon is not yet supported
+ HbLabel *followUpIcon = qobject_cast<HbLabel *>
+ (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);
+}
+