/*
* 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: manages scrollable portion of view.
*
*/
#include "msgunieditorscrollarea.h"
#include <QGraphicsLinearLayout>
#include <HbGroupBox>
#include <HbAction>
#include <QInputContext>
#include <qfile.h>
#include <qapplication.h>
#include <xqconversions.h>
#include <commonphoneparser.h>
#include <HbNotificationDialog>
#include <hbmainwindow.h>
#include "msgunieditoraddress.h"
#include "msgunieditorsubject.h"
#include "msgunieditorbody.h"
#include "msgunieditorsubject.h"
#include "msgunieditorbody.h"
#include "msgunieditormonitor.h"
#include "msgunieditorattachmentcontainer.h"
#include "UniEditorGenUtils.h"
#include "msgunieditorview.h"
// LOCALIZED CONSTANTS
//To,Cc.Bcc
#define LOC_TO hbTrId("txt_messaging_formlabel_to")
#define LOC_CC hbTrId("txt_messaging_formlabel_cc")
#define LOC_BCC hbTrId("txt_messaging_formlabel_bcc")
//group box
#define LOC_OTHER_RECIPIENTS(n) hbTrId("txt_messaging_title_ln_other_recipients",n)
#define LOC_OTHER_RECIPIENTS_EXPAND hbTrId("txt_messaging_title_other_recipients")
// attachment addition failure note
#define LOC_UNABLE_TO_ADD_ATTACHMENTS hbTrId("txt_messaging_dpopinfo_unable_to_attach_l1_of_l2")
//---------------------------------------------------------------
// MsgUnifiedEditorScrollArea::MsgUnifiedEditorScrollArea
//
//---------------------------------------------------------------
MsgUnifiedEditorScrollArea::MsgUnifiedEditorScrollArea(MsgUnifiedEditorMonitor* msgMonitor,QGraphicsItem *parent) :
HbScrollArea(parent),
mMsgMonitor(msgMonitor),
mMainLayout(0),
mToField(0),
mCcField(0),
mBccField(0),
mSubjectField(0),
mBody(0),
mAttachmentContainer(0),
mEnableScrolling(true)
{
init();
}
//---------------------------------------------------------------
// MsgUnifiedEditorScrollArea::~MsgUnifiedEditorScrollArea
//
//---------------------------------------------------------------
MsgUnifiedEditorScrollArea::~MsgUnifiedEditorScrollArea()
{
}
//---------------------------------------------------------------
// MsgUnifiedEditorScrollArea::init
//
//---------------------------------------------------------------
void MsgUnifiedEditorScrollArea::init()
{
HbWidget* contentWidget = new HbWidget(this);
this->setContentWidget(contentWidget);
mMainLayout = new QGraphicsLinearLayout(Qt::Vertical, contentWidget);
qreal vTopSpacing = 0.0;
qreal vItemSpacing = 0.0;
style()->parameter("hb-param-margin-gene-top",vTopSpacing);
style()->parameter("hb-param-margin-gene-middle-vertical",vItemSpacing);
mMainLayout->setContentsMargins(0,0,0,0);
mMainLayout->setSpacing(vItemSpacing);
mToField = new MsgUnifiedEditorAddress( LOC_TO, this );
mToField->setObjectName("to");
mBody = new MsgUnifiedEditorBody(this);
mMainLayout->addItem(mToField);
mMainLayout->addItem(mBody);
mMainLayout->addStretch(2);
connect(mToField, SIGNAL(contentsChanged(const QVariant&)),
mMsgMonitor, SLOT(handleContentsChanged(const QVariant&)));
connect(mBody, SIGNAL(contentsChanged(const QVariant&)),
mMsgMonitor, SLOT(handleContentsChanged(const QVariant&)));
connect(mBody,SIGNAL(enableMenuAction(int,bool)),this,SIGNAL(enableMenuAction(int,bool)));
}
//---------------------------------------------------------------
// MsgUnifiedEditorScrollArea::addCcBcc
//
//---------------------------------------------------------------
void MsgUnifiedEditorScrollArea::addCcBcc(bool needFocus)
{
if(mCcField && mBccField)
{ // do nothing if already present
return;
}
mCcField = new MsgUnifiedEditorAddress( LOC_CC, this );
mCcField->setObjectName("cc");
mBccField = new MsgUnifiedEditorAddress( LOC_BCC, this );
mBccField->setObjectName("bcc");
mCcField->skipMaxRecipientQuery(true);
mBccField->skipMaxRecipientQuery(true);
connect(mCcField, SIGNAL(contentsChanged(const QVariant&)),
mMsgMonitor, SLOT(handleContentsChanged(const QVariant&)));
connect(mBccField, SIGNAL(contentsChanged(const QVariant&)),
mMsgMonitor, SLOT(handleContentsChanged(const QVariant&)));
HbWidget* groupWidget = new HbWidget(this);
groupWidget->setContentsMargins(0,0,0,0);
QGraphicsLinearLayout* ccBccLayout = new QGraphicsLinearLayout(Qt::Vertical, groupWidget);
ccBccLayout->setContentsMargins(0,0,0,0);
qreal vItemSpacing = 0.0;
style()->parameter("hb-param-margin-gene-middle-vertical",vItemSpacing);
ccBccLayout->setSpacing(vItemSpacing);
ccBccLayout->addItem(mCcField);
ccBccLayout->addItem(mBccField);
HbGroupBox* groupBox = new HbGroupBox(0);
groupBox->setObjectName("groupBox");
groupBox->setContentWidget(groupWidget);
groupBox->setHeading(LOC_OTHER_RECIPIENTS_EXPAND);
mMainLayout->insertItem(1,groupBox);
connect(groupBox, SIGNAL(toggled(bool)), this, SLOT(updateOtherRecipientCount(bool)));
//emit signal to remove CcBcc action
emit enableMenuAction(CCBCC, false);
this->updateGeometry();
if(needFocus)
{
setFocus(mCcField);
}
}
//---------------------------------------------------------------
// MsgUnifiedEditorScrollArea::addSubject
//
//---------------------------------------------------------------
void MsgUnifiedEditorScrollArea::addSubject(bool needFocus)
{
// do nothing if already present
if(mSubjectField)
{
return;
}
mSubjectField = new MsgUnifiedEditorSubject(this);
int index = 0;
if(mCcField && mBccField)
{
index = 2;
}
else
{
index = 1;
}
mMainLayout->insertItem(index,mSubjectField);
connect(mSubjectField, SIGNAL(contentsChanged(const QVariant&)),
mMsgMonitor, SLOT(handleContentsChanged(const QVariant&)));
//emit signal to remove CcBcc action
emit enableMenuAction(SUBJECT, false);
if(needFocus)
{
setFocus(mSubjectField);
}
}
//---------------------------------------------------------------
// MsgUnifiedEditorScrollArea::setImage
//
//---------------------------------------------------------------
void MsgUnifiedEditorScrollArea::setImage(const QString& path, bool draftMessage)
{
mBody->setImage(path,draftMessage);
}
//---------------------------------------------------------------
// MsgUnifiedEditorScrollArea::setAudio
//
//---------------------------------------------------------------
void MsgUnifiedEditorScrollArea::setAudio(const QString& filePath)
{
mBody->setAudio(filePath);
}
//---------------------------------------------------------------
// MsgUnifiedEditorScrollArea::setFocus
//
//---------------------------------------------------------------
void MsgUnifiedEditorScrollArea::setFocus(MsgUnifiedEditorBaseWidget* item)
{
if(item)
{
item->setFocus();
}
//open vkb
postInputPanelEvent();
}
//---------------------------------------------------------------
// MsgUnifiedEditorScrollArea::changePriority
//
//---------------------------------------------------------------
void MsgUnifiedEditorScrollArea::changePriority()
{
HbAction* action = qobject_cast<HbAction*>(sender());
ConvergedMessage::Priority priority = ConvergedMessage::Normal;
if(action)
{
int data = action->data().toInt();
priority = ConvergedMessage::Priority(data);
}
addSubject();
mSubjectField->setPriority(priority);
}
//---------------------------------------------------------------
// MsgUnifiedEditorScrollArea::updateOtherRecipientCount
//
//---------------------------------------------------------------
void MsgUnifiedEditorScrollArea::updateOtherRecipientCount(bool state)
{
HbGroupBox* groupBox = qobject_cast<HbGroupBox*>(sender());
if(groupBox)
{
if(!state)
{
groupBox->setHeading(LOC_OTHER_RECIPIENTS_EXPAND);
}
else
{
int addrCount = mCcField->addressCount();
addrCount += mBccField->addressCount();
if(addrCount > 0)
{
groupBox->setHeading(LOC_OTHER_RECIPIENTS(addrCount));
}
}
}
}
//---------------------------------------------------------------
// MsgUnifiedEditorScrollArea::contactsValid
//
//---------------------------------------------------------------
bool MsgUnifiedEditorScrollArea::contactsValid()
{
bool res = ( !mToField->validateContacts() ||
(mCcField && !mCcField->validateContacts()) ||
(mBccField && !mBccField->validateContacts()) );
return !res;
}
//---------------------------------------------------------------
// MsgUnifiedEditorScrollArea::currentAddress
//
//---------------------------------------------------------------
ConvergedMessageAddress* MsgUnifiedEditorScrollArea::currentAddress()
{
ConvergedMessageAddress* currentAdd = NULL;
ConvergedMessageAddressList addList = mToField->addresses();
int count = addList.count();
if(count)
{
currentAdd = addList.takeFirst();
}
while(addList.count())
{
ConvergedMessageAddress* obj = addList.takeFirst();
delete obj;
}
return currentAdd;
}
//---------------------------------------------------------------
// MsgUnifiedEditorScrollArea::packMessage
//
//---------------------------------------------------------------
int MsgUnifiedEditorScrollArea::packMessage(ConvergedMessage &msg, bool isSave)
{
// If isSave is true (save to draft usecase), then don't remove duplicates
// If isSave is false (send usecase), then remove duplicates
bool removeDuplicates = !isSave;
ConvergedMessageAddressList addresses = mToField->addresses(removeDuplicates);
ConvergedMessageAddressList ccAddresses;
ConvergedMessageAddressList bccAddresses;
ConvergedMessageAttachmentList mediaList;
int errorCode = 0;
//Don't format the addresses for save to drfats case
if(!isSave)
{
formatAddresses(addresses);
}
msg.addToRecipients(addresses);
if(MsgUnifiedEditorMonitor::messageType() == ConvergedMessage::Mms)
{
if(mCcField)
{
ccAddresses = mCcField->addresses(removeDuplicates);
}
if(mBccField)
{
bccAddresses = mBccField->addresses(removeDuplicates);
}
if(removeDuplicates)
{
int matchDigitsCount = MsgUnifiedEditorAddress::contactMatchDigits();
//comapre cc and to field,remove duplicate from cc
foreach(ConvergedMessageAddress *ccAddress,ccAddresses)
{
foreach(ConvergedMessageAddress *toAddress,addresses)
{
if(0 == ccAddress->address().right(matchDigitsCount).compare(toAddress->address().right(matchDigitsCount)))
{
ccAddresses.removeOne(ccAddress);
}
}
}
//comapre bcc and cc field,remove duplicate from bcc
foreach(ConvergedMessageAddress *bccAddress,bccAddresses)
{
foreach(ConvergedMessageAddress *ccAddress,ccAddresses)
{
if(0 == bccAddress->address().right(matchDigitsCount).compare(ccAddress->address().right(matchDigitsCount)))
{
bccAddresses.removeOne(bccAddress);
}
}
}
//comapre bcc and to field,remove duplicate from bcc
foreach(ConvergedMessageAddress *bccAddress,bccAddresses)
{
foreach(ConvergedMessageAddress *toAddress,addresses)
{
if(0 == bccAddress->address().right(matchDigitsCount).compare(toAddress->address().right(matchDigitsCount)))
{
bccAddresses.removeOne(bccAddress);
}
}
}
}
if(ccAddresses.count()>0)
{
//Don't format the addresses for save to drfats case
if(!isSave)
{
formatAddresses(ccAddresses);
}
msg.addCcRecipients(ccAddresses);
}
if(bccAddresses.count()>0)
{
//Don't format the addresses for save to drfats case
if(!isSave)
{
formatAddresses(bccAddresses);
}
msg.addBccRecipients(bccAddresses);
}
if(mSubjectField)
{
msg.setSubject(mSubjectField->text());
msg.setPriority(mSubjectField->priority());
}
QStringList mediafiles(mBody->mediaContent());
if (!mediafiles.isEmpty())
{
for (int i = 0; i < mediafiles.size(); ++i)
{
if(QFile::exists(mediafiles.at(i)))
{
ConvergedMessageAttachment* attachment =
new ConvergedMessageAttachment(
mediafiles.at(i),
ConvergedMessageAttachment::EInline);
mediaList << attachment;
}
else
{ mBody->removeMediaContent(mediafiles.at(i));
errorCode = KErrNotFound;
}
}
}
if(mediaList.count() > 0)
{
msg.addAttachments(mediaList);
}
}
// sms/mms attachment list
ConvergedMessageAttachmentList attachmentList;
if(mAttachmentContainer)
{
MsgUnifiedEditorAttachmentList editorAttachmentList =
mAttachmentContainer->attachmentList();
for (int i = 0; i < editorAttachmentList.count(); ++i)
{
if(QFile::exists(editorAttachmentList.at(i)->path()))
{
ConvergedMessageAttachment* attachment =
new ConvergedMessageAttachment(
editorAttachmentList.at(i)->path(),
ConvergedMessageAttachment::EAttachment);
attachmentList << attachment;
}
else
{
mAttachmentContainer->deleteAttachment(editorAttachmentList.at(i));
errorCode = KErrNotFound;
}
}
}
if(attachmentList.count() > 0)
{
msg.addAttachments(attachmentList);
}
return errorCode;
}
// ----------------------------------------------------------------------------
// MsgUnifiedEditorScrollArea::formatAddresses
// @see header
// ----------------------------------------------------------------------------
void MsgUnifiedEditorScrollArea::formatAddresses(ConvergedMessageAddressList& addresses)
{
for(int i=0; i < addresses.count() ;i++ )
{
QString addr = addresses[i]->address();
HBufC *tempAddr = XQConversions::qStringToS60Desc(addr);
TPtr ptr = tempAddr->Des();
// Note: This is just to parse spaces etc away from phonenumbers.
// Ignore EFalse returned for email addresses.
CommonPhoneParser::ParsePhoneNumber(ptr ,
CommonPhoneParser::ESMSNumber );
addr = XQConversions::s60DescToQString(tempAddr->Des());
addresses[i]->setAddress(addr);
delete tempAddr;
}
}
//---------------------------------------------------------------
// MsgUnifiedEditorScrollArea::addAttachment
//
//---------------------------------------------------------------
int MsgUnifiedEditorScrollArea::addAttachment(const QString& filepath)
{
// do nothing if filepath is empty
if(filepath.isEmpty())
{
return MsgAttachmentContainer::EAddSuccess;
}
if(!mAttachmentContainer)
{
mAttachmentContainer = new MsgAttachmentContainer(this);
connect(mAttachmentContainer, SIGNAL(emptyAttachmentContainer()),
this, SLOT(removeAttachmentContainer()));
connect(mAttachmentContainer, SIGNAL(contentsChanged(const QVariant&)),
mMsgMonitor, SLOT(handleContentsChanged(const QVariant&)));
int index = mMainLayout->count() - 1;
mMainLayout->insertItem(index,mAttachmentContainer);
}
int ret = mAttachmentContainer->addAttachment(filepath);
if(ret != MsgAttachmentContainer::EAddSuccess)
{
// delete container, if it is empty
if(mAttachmentContainer->count() == 0)
{
removeAttachmentContainer();
}
}
return ret;
}
//---------------------------------------------------------------
// MsgUnifiedEditorScrollArea::removeAttachmentContainer
//
//---------------------------------------------------------------
void MsgUnifiedEditorScrollArea::removeAttachmentContainer()
{
if(mAttachmentContainer)
{
mMainLayout->removeItem(mAttachmentContainer);
mAttachmentContainer->setParent(NULL);
delete mAttachmentContainer;
mAttachmentContainer = NULL;
}
}
//---------------------------------------------------------------
// MsgUnifiedEditorScrollArea::addAttachments
//
//---------------------------------------------------------------
void MsgUnifiedEditorScrollArea::addAttachments(const QStringList files)
{
int fcount = files.count();
int i=0;
for(i=0; i<fcount; i++)
{
int status = addAttachment(files.at(i));
if(status == MsgAttachmentContainer::EAddSizeExceed)
{
QString displayStr = QString(LOC_UNABLE_TO_ADD_ATTACHMENTS)
.arg(fcount-i).arg(fcount);
HbNotificationDialog::launchDialog(displayStr);
break;
}
}
}
//---------------------------------------------------------------
// MsgUnifiedEditorScrollArea::fileNameInUse
//
//---------------------------------------------------------------
bool MsgUnifiedEditorScrollArea::fileNameInUse(const QString& fileName)
{
bool inUse = false;
if(mAttachmentContainer)
{
inUse = mAttachmentContainer->fileNameInUse(fileName);
}
return inUse;
}
//---------------------------------------------------------------
// MsgUnifiedEditorScrollArea::scrollByAmount
//
//---------------------------------------------------------------
bool MsgUnifiedEditorScrollArea::scrollByAmount(const QPointF &delta)
{
if(mEnableScrolling)
{
return HbScrollArea::scrollByAmount(delta);
}
else
{
return false;
}
}
//---------------------------------------------------------------
// MsgUnifiedEditorScrollArea::enableScrolling
//
//---------------------------------------------------------------
void MsgUnifiedEditorScrollArea::enableScrolling(bool enable)
{
mEnableScrolling = enable;
}
//---------------------------------------------------------------
// MsgUnifiedEditorScrollArea::postInputPanelEvent
//
//---------------------------------------------------------------
void MsgUnifiedEditorScrollArea::postInputPanelEvent()
{
// This opens the VKB
QInputContext *ic = qApp->inputContext();
if (ic)
{
QEvent event(QEvent::RequestSoftwareInputPanel);
ic->filterEvent(&event);
}
}
//---------------------------------------------------------------
// MsgUnifiedEditorScrollArea::populateContent
//
//---------------------------------------------------------------
void MsgUnifiedEditorScrollArea::populateContent(const ConvergedMessage& msg, bool draftMessage, bool checkForInline)
{
mToField->skipMaxRecipientQuery(true);
mToField->setAddresses(msg.toAddressList(),draftMessage);
if(msg.ccAddressList().count() > 0 )
{
if(!mCcField)
{
addCcBcc();
}
mCcField->setAddresses(msg.ccAddressList(),draftMessage);
}
if(msg.bccAddressList().count() > 0 )
{
if(!mBccField)
{
addCcBcc();
}
mBccField->setAddresses(msg.bccAddressList(),draftMessage);
}
if(msg.subject().size() > 0)
{
if(!mSubjectField)
{
addSubject();
}
mSubjectField->setText(msg.subject());
}
if(msg.priority()==ConvergedMessage::High ||
msg.priority() == ConvergedMessage::Low)
{
if(!mSubjectField)
{
addSubject();
}
mSubjectField->setPriority(msg.priority());
}
ConvergedMessageAttachmentList attachmentList = msg.attachments();
UniEditorGenUtils* genUtils = q_check_ptr(new UniEditorGenUtils);
QStringList pendingAttList;
int attachmentCount = attachmentList.count();
for( int i=0; i < attachmentCount; i++ )
{
QString filePath = msg.attachments().at(i)->filePath();
bool inlineContent = true;
if(checkForInline)
{
inlineContent = (attachmentList.at(i)->attachmentType() == ConvergedMessageAttachment::EInline);
}
if (inlineContent)
{
int imageSize=0;
QString mimeType;
TMsgMediaType mediaType = EMsgMediaUnknown;
TRAP_IGNORE(genUtils->getFileInfoL(filePath,imageSize,
mimeType,mediaType));
switch(mediaType)
{
case EMsgMediaImage:
{
mBody->setImage(filePath,draftMessage);
break;
}
case EMsgMediaAudio:
{
mBody->setAudio(filePath);
break;
}
default:
{
pendingAttList << filePath;
break;
}
}
}
else
{
pendingAttList << filePath;
}
}
// add pending attachments to editor
addAttachments(pendingAttList);
delete genUtils;
// ensure that any msg-type change after this are shown
mToField->skipMaxRecipientQuery(false);
}