homescreenapp/stateplugins/hshomescreenstateplugin/src/hsselectbackgroundstate.cpp
changeset 46 23b5d6a29cce
parent 39 4e8ebe173323
child 51 4785f57bf3d4
--- a/homescreenapp/stateplugins/hshomescreenstateplugin/src/hsselectbackgroundstate.cpp	Mon May 03 12:24:59 2010 +0300
+++ b/homescreenapp/stateplugins/hshomescreenstateplugin/src/hsselectbackgroundstate.cpp	Fri May 14 15:43:04 2010 +0300
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* Copyright (c) 2010 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"
@@ -15,11 +15,15 @@
 *
 */
 
+#include <QApplication>
 #include <QDir>
 #include <QFileInfo>
 #include <QImageReader>
+#include <QThread>
+#include <QTimer>
 
 #include <HbMainWindow>
+#include <HbProgressDialog>
 #include <HbView>
 
 #include "hsselectbackgroundstate.h"
@@ -28,7 +32,6 @@
 #include "hswallpaper.h"
 #include "hsdatabase.h"
 #include "hshomescreenstatecommon.h"
-#include "hswallpaperhelper.h"
 
 #ifdef Q_OS_SYMBIAN
 #include "hsimagefetcherclient.h"
@@ -36,6 +39,9 @@
 #include "xqaiwgetimageclient.h"
 #include "xqaiwcommon.h"
 #endif
+
+const char hsLocTextId_ProgressDialog_WallpaperLoading[] = "txt_homescreen_dpopinfo_loading_wallpaper";
+
 /*! 
     \class HsSelectBackgroundState
     \ingroup group_hshomescreenstateprovider
@@ -51,15 +57,22 @@
 HsSelectBackgroundState::HsSelectBackgroundState(QState *parent):
     QState(parent),
     mImageFetcher(0),
-    mSourceView(0)
+    mSourceView(0),
+    mWallpaperImageReaderThread(0),
+    mWallpaperImageReader(0),
+    mProgressDialog(0),
+    mImageProcessingState(NotRunning),
+    mShowAnimation(false)
 {
 #ifdef Q_OS_SYMBIAN
     mImageFetcher = new HsImageFetcherClient(this);
 #else    
     mImageFetcher = new XQAIWGetImageClient;
 #endif
+
     connect(this, SIGNAL(entered()), SLOT(action_selectWallpaper()));
     connect(this, SIGNAL(exited()), SLOT(action_disconnectImageFetcher()));
+    connect(this, SIGNAL(handleError()), SLOT(onHandleError()));
 }
 
 /*!
@@ -69,18 +82,23 @@
 HsSelectBackgroundState::~HsSelectBackgroundState()
 {
     delete mImageFetcher;
+    delete mWallpaperImageReaderThread;
+    delete mWallpaperImageReader;
 }
 
 /*!
     \internal
     Connects to image fetcher and launches "remote" ui from photos
     from which user can select background image
- */
+*/
 void HsSelectBackgroundState::action_selectWallpaper()
 {
     mSourceView = HsScene::mainWindow()->currentView();
 
-#ifdef Q_OS_SYMBIAN    
+    mImageProcessingState = NotRunning;
+    mShowAnimation = false;
+
+#ifdef Q_OS_SYMBIAN
     connect(mImageFetcher, SIGNAL(fetchCompleted(const QString&)),
             this, SLOT(fetchCompleted(const QString&)));
     connect(mImageFetcher, SIGNAL(fetchFailed(int, const QString&)),
@@ -92,14 +110,13 @@
     connect(mImageFetcher, SIGNAL(fetchFailed(int)),
             SLOT(onFetchFailed(int)));
     mImageFetcher->fetch(QVariantMap(), SelectionSingle);
-#endif    
+#endif
 }
 
 /*!
     \internal
     disconnects photos image fetcher services slots.
 */
-
 void HsSelectBackgroundState::action_disconnectImageFetcher()
 {
     HsScene::mainWindow()->setCurrentView(mSourceView);
@@ -108,6 +125,240 @@
 
 /*!
     \internal
+    Called when user has selected an image 
+*/
+void HsSelectBackgroundState::onFetchComplete(QStringList imageStringList)
+{
+    if (mImageProcessingState == NotRunning) {
+        // TODO: temporarily show animation immediately (~0.5 sec delay)
+        onShowAnimation();
+        // start counting time for possible animation
+        // TODO: from UX the real response time
+        // TODO: cannot use timer since UI does not respond during hardcore image processing
+        //QTimer::singleShot(1000, this, SLOT(onShowAnimation()));
+    }
+
+    HsDatabase *db = HsDatabase::instance();
+    Q_ASSERT(db);
+
+    HsSceneData sceneData;
+    if (!db->scene(sceneData)) {
+        emit handleError();
+        return;
+    }
+
+    // clean thread instances
+    delete mWallpaperImageReader;
+    delete mWallpaperImageReaderThread;
+    mWallpaperImageReader = NULL;
+    mWallpaperImageReaderThread = NULL;
+
+    mWallpaperImageReaderThread = new QThread();
+    mWallpaperImageReader = new HsWallpaperImageReader();
+
+    // setup processing when image is fetched at first time
+    if (mImageProcessingState == NotRunning) {
+        // delete old wallpapers
+        QFile::remove(sceneData.portraitWallpaper);
+        QFile::remove(sceneData.landscapeWallpaper);
+        
+        QString wallpaperDir = HsWallpaper::wallpaperDirectory();            
+        QDir dir(wallpaperDir);
+        if (!dir.exists()) {
+            dir.mkpath(wallpaperDir);
+        }
+        HsScene *scene = HsScene::instance();
+        Qt::Orientation orientation = scene->orientation();
+        // based on screen orientation select first image to process
+        if (orientation == Qt::Vertical) {
+            mImageProcessingState = ProcessPortraitAsFirst;
+        } else {
+            mImageProcessingState = ProcessLandscapeAsFirst;
+        }
+    }
+
+    QRect targetRect;
+
+    switch (mImageProcessingState) {
+    case ProcessPortraitAsFirst:
+    case ProcessPortraitAsSecond:
+        targetRect = QRect(0, 0, (2 * 360) + HSBOUNDARYEFFECT, 640);
+        break;
+    case ProcessLandscapeAsFirst:
+    case ProcessLandscapeAsSecond:
+        targetRect = QRect(0, 0, (2 * 640) + HSBOUNDARYEFFECT, 360);
+        break;
+    default:
+        emit handleError();
+        return;        
+    }
+
+    // left empty to signal we want to use full size image as source
+    QRect sourceRect;
+    mWallpaperImageReader->setSourcePath(imageStringList.first());
+    mWallpaperImageReader->setSourceRect(sourceRect);
+    mWallpaperImageReader->setTargetRect(targetRect);
+    mWallpaperImageReader->setCenterTarget(true);
+    mWallpaperImageReader->moveToThread(mWallpaperImageReaderThread);
+
+    mWallpaperImageReader->connect(mWallpaperImageReaderThread,
+                      SIGNAL(started()),
+                      SLOT(processImage()));
+    
+    connect(mWallpaperImageReader,
+            SIGNAL(processingFinished()),
+            SLOT(onImageProcessed()));
+  
+    // start image processing in thread
+    mWallpaperImageReaderThread->start(QThread::IdlePriority);
+}
+
+/*!
+    \internal
+    Called when selection of background image fails  
+*/
+void HsSelectBackgroundState::onFetchFailed(int error)
+{
+    Q_UNUSED(error)
+    emit handleError();
+}
+
+/*!
+    \internal
+    Called when image processing is finished in thread  
+*/
+void HsSelectBackgroundState::onImageProcessed()
+{
+    HsScene *scene = HsScene::instance();
+    HsDatabase *db = HsDatabase::instance();
+    Q_ASSERT(db);
+    HsSceneData sceneData;
+    if (!db->scene(sceneData)) {
+        emit handleError();
+        return;
+    }
+    QFileInfo fileInfo(mWallpaperImageReader->getSourcePath());
+    QString fileExtension("");
+    if (!fileInfo.suffix().isEmpty()) {
+        fileExtension = fileInfo.suffix();
+    }
+    // set image path to sceneData
+    QString path;
+    if (mImageProcessingState == ProcessPortraitAsFirst ||
+        mImageProcessingState == ProcessPortraitAsSecond) {
+        path = HsWallpaper::wallpaperPath(Qt::Vertical, QString(), fileExtension);
+        sceneData.portraitWallpaper = path;
+    } else {
+        path = HsWallpaper::wallpaperPath(Qt::Horizontal, QString(), fileExtension);
+        sceneData.landscapeWallpaper = path;
+    }
+    // get image from renderer and save it
+    QImage image = mWallpaperImageReader->getProcessedImage();
+    image.save(path);
+    if (!image.isNull()) {
+        // update scenedata and set new image to background
+        if (db->updateScene(sceneData)) {
+            switch (mImageProcessingState) {
+            case ProcessPortraitAsFirst:
+                scene->wallpaper()->setPortraitImage(path, true);
+                break;
+            case ProcessPortraitAsSecond:
+                // if orientation changed during first image settings
+                if (HsScene::orientation() == Qt::Vertical) {
+                    scene->wallpaper()->setPortraitImage(path, true);
+                } else {
+                    scene->wallpaper()->setPortraitImage(path);
+                }
+                break;
+            case ProcessLandscapeAsFirst:
+                scene->wallpaper()->setLandscapeImage(path, true);
+                break;
+            case ProcessLandscapeAsSecond:
+                if (HsScene::orientation() == Qt::Horizontal) {
+                    scene->wallpaper()->setLandscapeImage(path, true);
+                } else {
+                    scene->wallpaper()->setLandscapeImage(path);
+                }
+                break;
+            default:
+                emit handleError();
+                break;
+            }
+        }
+    } else {
+        emit handleError();
+        return;
+    }
+
+    switch (mImageProcessingState) {
+    case ProcessPortraitAsFirst:
+        mImageProcessingState = ProcessLandscapeAsSecond;
+        if (mShowAnimation) {
+            mProgressDialog->setProgressValue(2);
+        }
+        // process second orientation
+        onFetchComplete(QStringList(mWallpaperImageReader->getSourcePath()));
+        break;
+    case ProcessLandscapeAsFirst:
+        mImageProcessingState = ProcessPortraitAsSecond;
+        if (mShowAnimation) {
+            mProgressDialog->setProgressValue(2);
+        }
+        onFetchComplete(QStringList(mWallpaperImageReader->getSourcePath()));
+        break;
+    case ProcessPortraitAsSecond:
+    case ProcessLandscapeAsSecond:
+        mImageProcessingState = NotRunning;
+        if (mShowAnimation) {
+            mProgressDialog->setProgressValue(3);
+        }
+        // let user control again homescreen
+        emit event_waitInput();
+        break;
+    default:
+        emit handleError();
+        break;
+    }
+}
+
+/*!
+    \internal
+    Shows animation for longer processing
+*/
+void HsSelectBackgroundState::onShowAnimation()
+{
+    delete mProgressDialog;
+    mProgressDialog = new HbProgressDialog(HbProgressDialog::ProgressDialog);
+    // TODO: setPrimaryAction is deprecated, clearActions does the same but crashes when dialog closes, check orbit list
+    mProgressDialog->setPrimaryAction(0);
+    mProgressDialog->setIcon(HbIcon("note_info"));
+    mProgressDialog->setText(hbTrId(hsLocTextId_ProgressDialog_WallpaperLoading));
+    mProgressDialog->setMinimum(0);
+    mProgressDialog->setMaximum(3);
+    mProgressDialog->setBackgroundFaded(true);
+    mProgressDialog->setAutoClose(true);
+    mProgressDialog->setProgressValue(1);
+    mProgressDialog->show();
+    // TODO: temporary solution to minimize progress dialog resizing problem
+    QApplication::processEvents();
+    mShowAnimation = true;
+}
+
+/*!
+    \internal
+    Called when error occurs during image processing  
+*/
+void HsSelectBackgroundState::onHandleError()
+{
+    mImageProcessingState = Error;
+    if (mShowAnimation) {
+        mProgressDialog->close();
+    }
+    emit event_waitInput();
+}
+
+/*!
+    \internal
     Called when user has selected an image on emulator or HW
 */
 #ifdef Q_OS_SYMBIAN
@@ -120,81 +371,6 @@
 
 /*!
     \internal
-    Called when user has selected an image 
-*/
-void HsSelectBackgroundState::onFetchComplete(QStringList imageStringList)
-{
-    HsScene *scene = HsScene::instance();
-        
-    HsDatabase *db = HsDatabase::instance();
-    Q_ASSERT(db);
-
-    HsSceneData sceneData;
-    if (!db->scene(sceneData)) {
-        emit event_waitInput();
-        return;
-    }
-   
-    QFileInfo fileInfo(imageStringList.first());
-    QString fileExtension("");
-    if (!fileInfo.suffix().isEmpty()) {
-        fileExtension = fileInfo.suffix();
-    }
-
-    QFile::remove(sceneData.portraitWallpaper);
-    QFile::remove(sceneData.landscapeWallpaper); 
-
-    QString wallpaperDir = HsWallpaper::wallpaperDirectory();            
-    QDir dir(wallpaperDir);
-    if (!dir.exists()) {
-        dir.mkpath(wallpaperDir);
-    }
-
-    QString portraitPath = HsWallpaper::wallpaperPath(
-        Qt::Vertical, QString(), fileExtension);
-    QString landscapePath = HsWallpaper::wallpaperPath(
-        Qt::Horizontal, QString(), fileExtension);
-    
-    QRect portraitRect = QRect(0, 0, (2 * 360) + HSBOUNDARYEFFECT, 640);
-    QRect landscapeRect = QRect(0, 0, (2 * 640) + HSBOUNDARYEFFECT, 360);
-    QRect sourceRect; // left empty to signal we want to use full size image as source
-    
-    QImage portraitImage = HsWallpaperHelper::processImage(imageStringList.first(),
-            portraitRect, sourceRect);
-    
-    QImage landscapeImage = HsWallpaperHelper::processImage(imageStringList.first(),
-            landscapeRect, sourceRect);
-    
-    if (!portraitImage.isNull() && !landscapeImage.isNull()) {
-        portraitImage.save(portraitPath);
-        sceneData.portraitWallpaper = portraitPath;
-        
-        landscapeImage.save(landscapePath);
-        sceneData.landscapeWallpaper = landscapePath;
-        
-        if (db->updateScene(sceneData)) {
-            scene->wallpaper()->setImagesById(QString(), fileInfo.suffix());
-        }
-    }
-    else {
-        // display some error note here
-    }
-  
-    emit event_waitInput();
-}
-
-/*!
-    \internal
-    Called when selection of background image fails  
-*/
-void HsSelectBackgroundState::onFetchFailed(int error)
-{
-    Q_UNUSED(error)
-    emit event_waitInput();
-}
-
-/*!
-    \internal
     Called when selection of background image fails on emulator or HW
 */
 #ifdef Q_OS_SYMBIAN
@@ -203,4 +379,4 @@
     Q_UNUSED(errorString)
     onFetchFailed(error);        
 }
-#endif
\ No newline at end of file
+#endif