/*
* 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:
*
*/
// INCLUDES
#include <HbTextItem>
#include <HbIconItem>
#include <HbMainWindow>
#include <HbDeviceProfile>
#include <QImageReader>
#include <QFileInfo>
#include <MsgMediaResolver.h>
#include <MsgImageInfo.h>
#include <HbIconAnimationManager>
#include <HbIconAnimator>
#include <QGraphicsLinearLayout>
#include <HbNotificationDialog>
#include <xqaiwrequest.h>
#include <xqrequestinfo.h>
#include <xqsharablefile.h>
#include <xqappmgr.h>
#include <xqconversions.h>
#include <hbmessagebox.h>
// USER INCLUDES
#include "msgunieditorbody.h"
#include "UniEditorGenUtils.h"
#include "msgunieditormonitor.h"
#include "mmsconformancecheck.h"
#include "msgunieditorpixmapwidget.h"
#include "msgunieditoraudiowidget.h"
#include "msgunieditorview.h"
// Constants
const int BYTES_TO_KBYTES_FACTOR = 1024;
//Localized Constants for item specific menu
#define LOC_UNABLE_TO_ATTACH_ITEM hbTrId("txt_messaging_dpopinfo_unable_to_attach_item_avai")
#define LOC_PROCESSING hbTrId("txt_messaging_formlabel_loading")
#define LOC_ATTACHED_PHOTO_SIZE hbTrId("txt_messaging_dpopinfo_attached_photo_size_is_l1")
const QString ANIMATION_ICON("qtg_anim_loading");
const QString ANIMATION_FILE("qtg_anim_loading.axml");
// LOCAL FUNCTIONS
//---------------------------------------------------------------
// showInsertFailureNote
// @return fullPath of unified editor's temporary dir
//---------------------------------------------------------------
void showInsertFailureNote()
{
int availableSize =
(MsgUnifiedEditorMonitor::maxMmsSize() - MsgUnifiedEditorMonitor::messageSize())
/BYTES_TO_KBYTES_FACTOR;
QString displayStr = QString(LOC_UNABLE_TO_ATTACH_ITEM)
.arg(availableSize);
HbMessageBox::information(displayStr, 0, 0, HbMessageBox::Ok);
}
MsgUnifiedEditorBody::MsgUnifiedEditorBody( QGraphicsItem *parent ) :
MsgUnifiedEditorBaseWidget(parent),
mHasImage(false),
mHasAudio(false),
mPixmapItem(0),
mAudioItem(0),
mImageSize(0),
mAudioSize(0),
mProcessImageOperation(0),
mMediaResolver(0),
mImageInfo(0),
mProcessingWidget(0),
mDraftMessage(false)
{
this->setObjectName("body");
mMmsConformanceCheck = new MmsConformanceCheck;
}
MsgUnifiedEditorBody::~MsgUnifiedEditorBody()
{
delete mMmsConformanceCheck;
delete mProcessImageOperation;
delete mMediaResolver;
delete mImageInfo;
}
void MsgUnifiedEditorBody::setImage(const QString& imagefile, bool draftMessage)
{
// do nothing if filepath is empty
if (imagefile.isEmpty())
{
return;
}
//disable image option in menu.
emit enableMenuAction(PHOTO,false);
mDraftMessage = draftMessage;
if (!mImageInfo)
{
setImage(true);
mImageFile = imagefile;
if (mPixmapItem)
{
mPixmapItem->setParent(NULL);
delete mPixmapItem;
mPixmapItem = NULL;
mImageSize = 0;
}
int error = KErrNone;
if (!mDraftMessage)
{
// if image is in draft, no need to resize it because it is resized already
if (!mProcessImageOperation)
{
TRAP(error,mProcessImageOperation =
CUniEditorProcessImageOperation::NewL(*this));
}
if (!mMediaResolver && error == KErrNone)
{
TRAP(error,mMediaResolver = CMsgMediaResolver::NewL());
}
if (error == KErrNone)
{
mMediaResolver->SetCharacterSetRecognition(EFalse);
HBufC *name = XQConversions::qStringToS60Desc(imagefile);
RFile file;
TRAP(error, file = mMediaResolver->FileHandleL(*name));
if (error == KErrNone)
{
TRAP(error,mImageInfo = static_cast<CMsgImageInfo*>
(mMediaResolver->CreateMediaInfoL(file)));
if (error == KErrNone)
{
TRAP(error, mMediaResolver->ParseInfoDetailsL(
mImageInfo, file));
}
file.Close();
}
delete name;
}
}
if (error == KErrNone && !mDraftMessage)
{
mSavedImageFile = imagefile;
startResizeAnimation();
// image resize is started. set the image resize flag.
emit contentsChanged(true);
mProcessImageOperation->Process(mImageInfo);
}
else
{
if (mImageInfo)
{
delete mImageInfo;
mImageInfo = NULL;
}
mSavedImageFile.clear();
handleSetImage();
}
}
}
void MsgUnifiedEditorBody::handleSetImage()
{
//check for insert conformance
if(EInsertSuccess != mMmsConformanceCheck->checkModeForInsert(mImageFile))
{
//enable image option in menu as insertion failed.
emit enableMenuAction(PHOTO,true);
return;
}
int msgSize = MsgUnifiedEditorMonitor::messageSize();
QFileInfo fileinfo(mImageFile);
int imageSize = fileinfo.size() + KEstimatedMimeHeaderSize;
if ( (imageSize + msgSize) <= MsgUnifiedEditorMonitor::maxMmsSize())
{
mImageSize = imageSize;
}
else
{
mImageFile.clear();
setImage(false);
//Show appropriate note and leave
showInsertFailureNote();
//enable image option in menu as insertion failed.
emit enableMenuAction(PHOTO,true);
return;
}
mPixmapItem = new MsgUnifiedEditorPixmapWidget(this);
mPixmapItem->hide();
HbStyle::setItemName(mPixmapItem, "pixmap");
mPixmapItem->setAlignment(Qt::AlignHCenter | Qt::AlignTop);
mPixmapItem->populate(mImageFile);
connect(mPixmapItem,SIGNAL(remove()),this,SLOT(removeMedia()));
// repolish the body widget
this->repolish();
// emit signal to indicate addition of image
emit contentsChanged(bodySize());
}
void MsgUnifiedEditorBody::setAudio(const QString& audiofile)
{
// do nothing if filepath is empty
if(audiofile.isEmpty())
{
return;
}
//check for insert conformance
if(EInsertSuccess != mMmsConformanceCheck->checkModeForInsert(audiofile))
return;
setAudio(true);
mAudioFile = audiofile;
if(mAudioItem)
{
mAudioItem->setParent(NULL);
delete mAudioItem;
mAudioItem = NULL;
mAudioSize = 0;
}
int msgSize = MsgUnifiedEditorMonitor::messageSize();
QFileInfo fileinfo(mAudioFile);
int audioSize = fileinfo.size() + KEstimatedMimeHeaderSize;
if((audioSize + msgSize) <= MsgUnifiedEditorMonitor::maxMmsSize() )
{
mAudioSize = audioSize;
}
else
{
mAudioFile.clear();
setAudio(false);
//Show appropriate note and leave
showInsertFailureNote();
return;
}
mAudioItem = new MsgUniFiedEditorAudioWidget(this);
mAudioItem->hide();
HbStyle::setItemName(mAudioItem,"audioItem");
mAudioItem->populate(mAudioFile);
connect(mAudioItem,SIGNAL(remove()),this,SLOT(removeMedia()));
// repolish the body widget
this->repolish();
// emit signal to indicate addition of audio
emit contentsChanged(bodySize());
//disable sound option in menu.
emit enableMenuAction(SOUND,false);
}
const QStringList MsgUnifiedEditorBody::mediaContent()
{
QStringList mediaFiles;
// Pick mImageFile only if mSavedImageFile is empty
// as it means we are not in middle of resizing
if (mHasImage && mSavedImageFile.isEmpty())
mediaFiles << mImageFile;
if(mHasAudio)
mediaFiles << mAudioFile;
return mediaFiles;
}
QSizeF MsgUnifiedEditorBody::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
{
QSizeF szHint = HbWidget::sizeHint(which,constraint);
HbMainWindow* mMainWindow = this->mainWindow();
if(!mMainWindow)
{
return szHint;
}
qreal leftMargin = 0.0;
qreal rightMargin = 0.0;
qreal chromeHeight = 0.0;
qreal toolbarHeight = 0.0;
qreal bodyItemSpacing = 0.0;
style()->parameter("hb-param-margin-gene-left",leftMargin);
style()->parameter("hb-param-margin-gene-right",rightMargin);
style()->parameter("hb-param-widget-chrome-height",chromeHeight);
style()->parameter("hb-param-widget-toolbar-height",toolbarHeight);
style()->parameter("hb-param-margin-gene-middle-vertical",bodyItemSpacing);
HbDeviceProfile prf = HbDeviceProfile::profile(mMainWindow);
qreal unt = prf.unitValue();
qreal maxWidth = mMainWindow->width()-leftMargin-rightMargin;
qreal maxHeight = mMainWindow->height()-chromeHeight-toolbarHeight;
szHint.setHeight(0);
// add space for audio
if(mAudioItem)
{
if(mMainWindow->orientation() == Qt::Horizontal)
{
mAudioItem->setStretched(true);
}
else
{
mAudioItem->setStretched(false);
}
QSizeF audioSize = mAudioItem->effectiveSizeHint(which, constraint);
szHint.rheight() += (audioSize.height() + bodyItemSpacing);
mAudioItem->show();
}
if(mPixmapItem || mProcessingWidget)
{
QSizeF imageSize(0.0,0.0);
QSizeF defaultImageSize(QImageReader(mImageFile).size());
if(!defaultImageSize.isEmpty())
{
imageSize.setWidth(maxWidth);
if(mMainWindow->orientation() == Qt::Vertical)
{
szHint.rheight() += bodyItemSpacing;
}
qreal newHeight = 0.0;
if(defaultImageSize.width() <= imageSize.width())
{
// resize not needed
newHeight = qMin(defaultImageSize.height(), maxHeight);
imageSize.setHeight(newHeight);
}
else
{
// keep aspect-ratio and resize
newHeight = imageSize.width()*(defaultImageSize.height()/defaultImageSize.width());
newHeight = qMin(newHeight,maxHeight);
imageSize.setHeight(newHeight);
}
if(newHeight == maxHeight)
{
qreal newWidth = defaultImageSize.width()*newHeight/defaultImageSize.height();
imageSize.setWidth(newWidth);
}
if(mPixmapItem)
{
mPixmapItem->setPreferredSize(imageSize);
mPixmapItem->setSize(imageSize);
mPixmapItem->show();
}
if(mProcessingWidget)
{
imageSize.setHeight(mProcessingWidget->preferredHeight());
mProcessingWidget->setPreferredSize(imageSize);
mProcessingWidget->show();
}
szHint.rheight() += imageSize.height();
}
}
szHint.rheight() += bodyItemSpacing;
return szHint;
}
void MsgUnifiedEditorBody::removeMedia()
{
QObject* senderObject = sender();
MsgUnifiedEditorPixmapWidget* pixmap =
qobject_cast<MsgUnifiedEditorPixmapWidget*>(senderObject);
MsgUniFiedEditorAudioWidget* audio =
qobject_cast<MsgUniFiedEditorAudioWidget*>(senderObject);
if(pixmap) //remove image
{
mImageFile.clear();
if(mPixmapItem)
{
mPixmapItem->setParent(NULL);
delete mPixmapItem;
mPixmapItem = NULL;
}
setImage(false);
mImageSize = 0;
//enable photo option in menu.
emit enableMenuAction(PHOTO,true);
}
else if(audio)//remove audio item
{
mAudioFile.clear();
if(mAudioItem)
{
mAudioItem->setParent(NULL);
delete mAudioItem;
mAudioItem = NULL;
}
setAudio(false);
mAudioSize = 0;
//enable sound option in menu.
emit enableMenuAction(SOUND,true);
}
this->repolish();
emit contentsChanged(bodySize());
}
bool MsgUnifiedEditorBody::hasImage()
{
return mHasImage;
}
void MsgUnifiedEditorBody::setImage(bool image)
{
mHasImage = image;
}
bool MsgUnifiedEditorBody::hasAudio()
{
return mHasAudio;
}
void MsgUnifiedEditorBody::setAudio(bool audio)
{
mHasAudio = audio;
}
int MsgUnifiedEditorBody::bodySize()
{
return mImageSize + mAudioSize;
}
void MsgUnifiedEditorBody::EditorOperationEvent(
TUniEditorProcessImageOperationEvent aEvent, TFileName& aFileName)
{
delete mImageInfo;
mImageInfo = NULL;
if (aEvent == EUniEditorProcessImageOperationComplete &&
aFileName.Length() > 0)
{
mImageFile = XQConversions::s60DescToQString(aFileName);
QSize modifiedSize(QImageReader(mImageFile).size());
QString information = LOC_ATTACHED_PHOTO_SIZE.arg(modifiedSize.width()).arg(modifiedSize.height());
HbNotificationDialog::launchDialog(information);
}
else
{
mImageFile = mSavedImageFile;
}
mSavedImageFile.clear();
// image resize is complete. reset the image resize flag
emit contentsChanged(false);
//handle the processed image from ProcessImage Operation
handleSetImage();
stopResizeAnimation();
}
void MsgUnifiedEditorBody::startResizeAnimation()
{
QGraphicsLinearLayout* processingLayout = new QGraphicsLinearLayout(Qt::Vertical);
mProcessingWidget = new HbWidget(this);
HbStyle::setItemName(mProcessingWidget,"pixmap");
mProcessingWidget->hide();
mProcessingWidget->setLayout(processingLayout);
HbTextItem* processingText = new HbTextItem(LOC_PROCESSING,mProcessingWidget);
processingText->setFontSpec(HbFontSpec(HbFontSpec::Secondary));
processingText->setAlignment(Qt::AlignCenter);
processingLayout->addItem(processingText);
HbIconItem* animationItem = new HbIconItem(ANIMATION_ICON,mProcessingWidget);
animationItem->setAlignment(Qt::AlignHCenter);
processingLayout->addItem(animationItem);
HbIconAnimator& iconAnimator = animationItem->animator();
HbIconAnimationManager* iconAnimationManager = HbIconAnimationManager::global();
iconAnimationManager->addDefinitionFile(ANIMATION_FILE);
iconAnimator.startAnimation();
this->repolish();
}
void MsgUnifiedEditorBody::stopResizeAnimation()
{
if(mProcessingWidget)
{
delete mProcessingWidget;
mProcessingWidget = NULL;
}
}
//---------------------------------------------------------------
// MsgUnifiedEditorBody :: removeMediaContent
// @see header file
//---------------------------------------------------------------
void MsgUnifiedEditorBody::removeMediaContent(QString fileName)
{
if(!(mImageFile.compare(fileName))) //remove image
{
mImageFile.clear();
if(mPixmapItem)
{
mPixmapItem->setParent(NULL);
delete mPixmapItem;
mPixmapItem = NULL;
}
setImage(false);
mImageSize = 0;
}
else if(!(mAudioFile.compare(fileName)))//remove audio item
{
mAudioFile.clear();
if(mAudioItem)
{
mAudioItem->setParent(NULL);
delete mAudioItem;
mAudioItem = NULL;
}
setAudio(false);
mAudioSize = 0;
}
this->repolish();
emit contentsChanged(bodySize());
}
// EOF