homescreenapp/stateplugins/hshomescreenstateplugin/src/hsselectbackgroundstate.cpp
branchGCC_SURGE
changeset 68 4c11ecddf6b2
parent 53 f75922b9e380
parent 61 2b1b11a301d2
equal deleted inserted replaced
53:f75922b9e380 68:4c11ecddf6b2
     1 /*
       
     2 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  
       
    15 *
       
    16 */
       
    17 
       
    18 #include <QApplication>
       
    19 #include <QDir>
       
    20 #include <QFileInfo>
       
    21 #include <QImageReader>
       
    22 #include <QThread>
       
    23 #include <QTimer>
       
    24 
       
    25 #include <HbMainWindow>
       
    26 #include <HbProgressDialog>
       
    27 #include <HbView>
       
    28 
       
    29 #include "hsselectbackgroundstate.h"
       
    30 #include "hsscene.h"
       
    31 #include "hsdomainmodeldatastructures.h"
       
    32 #include "hswallpaper.h"
       
    33 #include "hsdatabase.h"
       
    34 #include "hshomescreenstatecommon.h"
       
    35 
       
    36 #ifdef Q_OS_SYMBIAN
       
    37 #include "hsimagefetcherclient.h"
       
    38 #else
       
    39 #include "xqaiwgetimageclient.h"
       
    40 #include "xqaiwcommon.h"
       
    41 #endif
       
    42 
       
    43 const char hsLocTextId_ProgressDialog_WallpaperLoading[] = "txt_homescreen_dpopinfo_loading_wallpaper";
       
    44 
       
    45 /*! 
       
    46     \class HsSelectBackgroundState
       
    47     \ingroup group_hshomescreenstateprovider
       
    48     \brief Implements imagefetcher event listening and handles those events.
       
    49 
       
    50     \sa StateMachine
       
    51 */
       
    52 
       
    53 /*!
       
    54     Constructor.         
       
    55     \a parent Owner.
       
    56 */
       
    57 HsSelectBackgroundState::HsSelectBackgroundState(QState *parent):
       
    58     QState(parent),
       
    59     mImageFetcher(0),
       
    60     mSourceView(0),
       
    61     mWallpaperImageReaderThread(0),
       
    62     mWallpaperImageReader(0),
       
    63     mProgressDialog(0),
       
    64     mImageProcessingState(NotRunning),
       
    65     mShowAnimation(false)
       
    66 {
       
    67 #ifdef Q_OS_SYMBIAN
       
    68     mImageFetcher = new HsImageFetcherClient(this);
       
    69 #else    
       
    70     mImageFetcher = new XQAIWGetImageClient;
       
    71 #endif
       
    72 
       
    73     connect(this, SIGNAL(entered()), SLOT(action_selectWallpaper()));
       
    74     connect(this, SIGNAL(exited()), SLOT(action_disconnectImageFetcher()));
       
    75     connect(this, SIGNAL(handleError()), SLOT(onHandleError()));
       
    76 }
       
    77 
       
    78 /*!
       
    79     Destructor.
       
    80     
       
    81 */
       
    82 HsSelectBackgroundState::~HsSelectBackgroundState()
       
    83 {
       
    84     delete mImageFetcher;
       
    85     delete mWallpaperImageReaderThread;
       
    86     delete mWallpaperImageReader;
       
    87 }
       
    88 
       
    89 /*!
       
    90     \internal
       
    91     Connects to image fetcher and launches "remote" ui from photos
       
    92     from which user can select background image
       
    93 */
       
    94 void HsSelectBackgroundState::action_selectWallpaper()
       
    95 {
       
    96     mSourceView = HsScene::mainWindow()->currentView();
       
    97 
       
    98     mImageProcessingState = NotRunning;
       
    99     mShowAnimation = false;
       
   100 
       
   101 #ifdef Q_OS_SYMBIAN
       
   102     connect(mImageFetcher, SIGNAL(fetchCompleted(const QString&)),
       
   103             this, SLOT(fetchCompleted(const QString&)));
       
   104     connect(mImageFetcher, SIGNAL(fetchFailed(int, const QString&)),
       
   105             this, SLOT(fetchFailed(int, const QString&)));
       
   106     mImageFetcher->fetch();
       
   107 #else
       
   108     connect(mImageFetcher, SIGNAL(fetchComplete(QStringList)),
       
   109             SLOT(onFetchComplete(QStringList)));
       
   110     connect(mImageFetcher, SIGNAL(fetchFailed(int)),
       
   111             SLOT(onFetchFailed(int)));
       
   112     mImageFetcher->fetch(QVariantMap(), SelectionSingle);
       
   113 #endif
       
   114 }
       
   115 
       
   116 /*!
       
   117     \internal
       
   118     disconnects photos image fetcher services slots.
       
   119 */
       
   120 void HsSelectBackgroundState::action_disconnectImageFetcher()
       
   121 {
       
   122     HsScene::mainWindow()->setCurrentView(mSourceView);
       
   123     mImageFetcher->disconnect(this);
       
   124 }
       
   125 
       
   126 /*!
       
   127     \internal
       
   128     Called when user has selected an image 
       
   129 */
       
   130 void HsSelectBackgroundState::onFetchComplete(QStringList imageStringList)
       
   131 {
       
   132     if (mImageProcessingState == NotRunning) {
       
   133         // TODO: temporarily show animation immediately (~0.5 sec delay)
       
   134         onShowAnimation();
       
   135         // start counting time for possible animation
       
   136         // TODO: from UX the real response time
       
   137         // TODO: cannot use timer since UI does not respond during hardcore image processing
       
   138         //QTimer::singleShot(1000, this, SLOT(onShowAnimation()));
       
   139     }
       
   140 
       
   141     HsDatabase *db = HsDatabase::instance();
       
   142     Q_ASSERT(db);
       
   143 
       
   144     HsSceneData sceneData;
       
   145     if (!db->scene(sceneData)) {
       
   146         emit handleError();
       
   147         return;
       
   148     }
       
   149 
       
   150     // clean thread instances
       
   151     delete mWallpaperImageReader;
       
   152     delete mWallpaperImageReaderThread;
       
   153     mWallpaperImageReader = NULL;
       
   154     mWallpaperImageReaderThread = NULL;
       
   155 
       
   156     mWallpaperImageReaderThread = new QThread();
       
   157     mWallpaperImageReader = new HsWallpaperImageReader();
       
   158 
       
   159     // setup processing when image is fetched at first time
       
   160     if (mImageProcessingState == NotRunning) {
       
   161         // delete old wallpapers
       
   162         QFile::remove(sceneData.portraitWallpaper);
       
   163         QFile::remove(sceneData.landscapeWallpaper);
       
   164         
       
   165         QString wallpaperDir = HsWallpaper::wallpaperDirectory();            
       
   166         QDir dir(wallpaperDir);
       
   167         if (!dir.exists()) {
       
   168             dir.mkpath(wallpaperDir);
       
   169         }
       
   170         HsScene *scene = HsScene::instance();
       
   171         Qt::Orientation orientation = scene->orientation();
       
   172         // based on screen orientation select first image to process
       
   173         if (orientation == Qt::Vertical) {
       
   174             mImageProcessingState = ProcessPortraitAsFirst;
       
   175         } else {
       
   176             mImageProcessingState = ProcessLandscapeAsFirst;
       
   177         }
       
   178     }
       
   179 
       
   180     QRect targetRect;
       
   181 
       
   182     switch (mImageProcessingState) {
       
   183     case ProcessPortraitAsFirst:
       
   184     case ProcessPortraitAsSecond:
       
   185         targetRect = QRect(0, 0, (2 * 360) + HSBOUNDARYEFFECT, 640);
       
   186         break;
       
   187     case ProcessLandscapeAsFirst:
       
   188     case ProcessLandscapeAsSecond:
       
   189         targetRect = QRect(0, 0, (2 * 640) + HSBOUNDARYEFFECT, 360);
       
   190         break;
       
   191     default:
       
   192         emit handleError();
       
   193         return;        
       
   194     }
       
   195 
       
   196     // left empty to signal we want to use full size image as source
       
   197     QRect sourceRect;
       
   198     mWallpaperImageReader->setSourcePath(imageStringList.first());
       
   199     mWallpaperImageReader->setSourceRect(sourceRect);
       
   200     mWallpaperImageReader->setTargetRect(targetRect);
       
   201     mWallpaperImageReader->setCenterTarget(true);
       
   202     mWallpaperImageReader->moveToThread(mWallpaperImageReaderThread);
       
   203 
       
   204     mWallpaperImageReader->connect(mWallpaperImageReaderThread,
       
   205                       SIGNAL(started()),
       
   206                       SLOT(processImage()));
       
   207     
       
   208     connect(mWallpaperImageReader,
       
   209             SIGNAL(processingFinished()),
       
   210             SLOT(onImageProcessed()));
       
   211   
       
   212     // start image processing in thread
       
   213     mWallpaperImageReaderThread->start(QThread::IdlePriority);
       
   214 }
       
   215 
       
   216 /*!
       
   217     \internal
       
   218     Called when selection of background image fails  
       
   219 */
       
   220 void HsSelectBackgroundState::onFetchFailed(int error)
       
   221 {
       
   222     Q_UNUSED(error)
       
   223     emit handleError();
       
   224 }
       
   225 
       
   226 /*!
       
   227     \internal
       
   228     Called when image processing is finished in thread  
       
   229 */
       
   230 void HsSelectBackgroundState::onImageProcessed()
       
   231 {
       
   232     HsScene *scene = HsScene::instance();
       
   233     HsDatabase *db = HsDatabase::instance();
       
   234     Q_ASSERT(db);
       
   235     HsSceneData sceneData;
       
   236     if (!db->scene(sceneData)) {
       
   237         emit handleError();
       
   238         return;
       
   239     }
       
   240     QFileInfo fileInfo(mWallpaperImageReader->getSourcePath());
       
   241     QString fileExtension("");
       
   242     if (!fileInfo.suffix().isEmpty()) {
       
   243         fileExtension = fileInfo.suffix();
       
   244     }
       
   245     // set image path to sceneData
       
   246     QString path;
       
   247     if (mImageProcessingState == ProcessPortraitAsFirst ||
       
   248         mImageProcessingState == ProcessPortraitAsSecond) {
       
   249         path = HsWallpaper::wallpaperPath(Qt::Vertical, QString(), fileExtension);
       
   250         sceneData.portraitWallpaper = path;
       
   251     } else {
       
   252         path = HsWallpaper::wallpaperPath(Qt::Horizontal, QString(), fileExtension);
       
   253         sceneData.landscapeWallpaper = path;
       
   254     }
       
   255     // get image from renderer and save it
       
   256     QImage image = mWallpaperImageReader->getProcessedImage();
       
   257     image.save(path);
       
   258     if (!image.isNull()) {
       
   259         // update scenedata and set new image to background
       
   260         if (db->updateScene(sceneData)) {
       
   261             switch (mImageProcessingState) {
       
   262             case ProcessPortraitAsFirst:
       
   263                 scene->wallpaper()->setPortraitImage(path, true);
       
   264                 break;
       
   265             case ProcessPortraitAsSecond:
       
   266                 // if orientation changed during first image settings
       
   267                 if (HsScene::orientation() == Qt::Vertical) {
       
   268                     scene->wallpaper()->setPortraitImage(path, true);
       
   269                 } else {
       
   270                     scene->wallpaper()->setPortraitImage(path);
       
   271                 }
       
   272                 break;
       
   273             case ProcessLandscapeAsFirst:
       
   274                 scene->wallpaper()->setLandscapeImage(path, true);
       
   275                 break;
       
   276             case ProcessLandscapeAsSecond:
       
   277                 if (HsScene::orientation() == Qt::Horizontal) {
       
   278                     scene->wallpaper()->setLandscapeImage(path, true);
       
   279                 } else {
       
   280                     scene->wallpaper()->setLandscapeImage(path);
       
   281                 }
       
   282                 break;
       
   283             default:
       
   284                 emit handleError();
       
   285                 break;
       
   286             }
       
   287         }
       
   288     } else {
       
   289         emit handleError();
       
   290         return;
       
   291     }
       
   292 
       
   293     switch (mImageProcessingState) {
       
   294     case ProcessPortraitAsFirst:
       
   295         mImageProcessingState = ProcessLandscapeAsSecond;
       
   296         if (mShowAnimation) {
       
   297             mProgressDialog->setProgressValue(2);
       
   298         }
       
   299         // process second orientation
       
   300         onFetchComplete(QStringList(mWallpaperImageReader->getSourcePath()));
       
   301         break;
       
   302     case ProcessLandscapeAsFirst:
       
   303         mImageProcessingState = ProcessPortraitAsSecond;
       
   304         if (mShowAnimation) {
       
   305             mProgressDialog->setProgressValue(2);
       
   306         }
       
   307         onFetchComplete(QStringList(mWallpaperImageReader->getSourcePath()));
       
   308         break;
       
   309     case ProcessPortraitAsSecond:
       
   310     case ProcessLandscapeAsSecond:
       
   311         mImageProcessingState = NotRunning;
       
   312         if (mShowAnimation) {
       
   313             mProgressDialog->setProgressValue(3);
       
   314         }
       
   315         // let user control again homescreen
       
   316         emit event_waitInput();
       
   317         break;
       
   318     default:
       
   319         emit handleError();
       
   320         break;
       
   321     }
       
   322 }
       
   323 
       
   324 /*!
       
   325     \internal
       
   326     Shows animation for longer processing
       
   327 */
       
   328 void HsSelectBackgroundState::onShowAnimation()
       
   329 {
       
   330     delete mProgressDialog;
       
   331     mProgressDialog = new HbProgressDialog(HbProgressDialog::ProgressDialog);
       
   332     // TODO: setPrimaryAction is deprecated, clearActions does the same but crashes when dialog closes, check orbit list
       
   333     mProgressDialog->setPrimaryAction(0);
       
   334     mProgressDialog->setIcon(HbIcon("note_info"));
       
   335     mProgressDialog->setText(hbTrId(hsLocTextId_ProgressDialog_WallpaperLoading));
       
   336     mProgressDialog->setMinimum(0);
       
   337     mProgressDialog->setMaximum(3);
       
   338     mProgressDialog->setBackgroundFaded(true);
       
   339     mProgressDialog->setAutoClose(true);
       
   340     mProgressDialog->setProgressValue(1);
       
   341     mProgressDialog->show();
       
   342     // TODO: temporary solution to minimize progress dialog resizing problem
       
   343     QApplication::processEvents();
       
   344     mShowAnimation = true;
       
   345 }
       
   346 
       
   347 /*!
       
   348     \internal
       
   349     Called when error occurs during image processing  
       
   350 */
       
   351 void HsSelectBackgroundState::onHandleError()
       
   352 {
       
   353     mImageProcessingState = Error;
       
   354     if (mShowAnimation) {
       
   355         mProgressDialog->close();
       
   356     }
       
   357     emit event_waitInput();
       
   358 }
       
   359 
       
   360 /*!
       
   361     \internal
       
   362     Called when user has selected an image on emulator or HW
       
   363 */
       
   364 #ifdef Q_OS_SYMBIAN
       
   365 void HsSelectBackgroundState::fetchCompleted(const QString& imageFileName)
       
   366 {
       
   367     QStringList imageFileNameAsList(imageFileName);
       
   368     onFetchComplete(imageFileNameAsList);
       
   369 }
       
   370 #endif
       
   371 
       
   372 /*!
       
   373     \internal
       
   374     Called when selection of background image fails on emulator or HW
       
   375 */
       
   376 #ifdef Q_OS_SYMBIAN
       
   377 void HsSelectBackgroundState::fetchFailed(int error, const QString& errorString)
       
   378 {
       
   379     Q_UNUSED(errorString)
       
   380     onFetchFailed(error);        
       
   381 }
       
   382 #endif