homescreenapp/stateplugins/hshomescreenstateplugin/src/hsselectbackgroundstate.cpp
changeset 51 4785f57bf3d4
parent 46 23b5d6a29cce
equal deleted inserted replaced
46:23b5d6a29cce 51:4785f57bf3d4
    13 *
    13 *
    14 * Description:  
    14 * Description:  
    15 *
    15 *
    16 */
    16 */
    17 
    17 
       
    18 #include <QAction>
    18 #include <QApplication>
    19 #include <QApplication>
    19 #include <QDir>
    20 #include <QDir>
    20 #include <QFileInfo>
    21 #include <QFileInfo>
    21 #include <QImageReader>
       
    22 #include <QThread>
       
    23 #include <QTimer>
       
    24 
    22 
    25 #include <HbMainWindow>
    23 #include <HbMainWindow>
    26 #include <HbProgressDialog>
    24 #include <HbProgressDialog>
    27 #include <HbView>
       
    28 
    25 
    29 #include "hsselectbackgroundstate.h"
    26 #include "hsselectbackgroundstate.h"
    30 #include "hsscene.h"
    27 #include "hsscene.h"
    31 #include "hsdomainmodeldatastructures.h"
    28 #include "hsdomainmodeldatastructures.h"
    32 #include "hswallpaper.h"
    29 #include "hswallpaper.h"
    33 #include "hsdatabase.h"
    30 #include "hsdatabase.h"
    34 #include "hshomescreenstatecommon.h"
    31 #include "hshomescreenstatecommon.h"
       
    32 #include "hsconfiguration.h"
    35 
    33 
    36 #ifdef Q_OS_SYMBIAN
    34 #ifdef Q_OS_SYMBIAN
    37 #include "hsimagefetcherclient.h"
    35 #include "hsimagefetcherclient.h"
    38 #else
    36 #else
    39 #include "xqaiwgetimageclient.h"
    37 #include "xqaiwgetimageclient.h"
    40 #include "xqaiwcommon.h"
    38 #include "xqaiwcommon.h"
    41 #endif
    39 #endif
    42 
    40 
    43 const char hsLocTextId_ProgressDialog_WallpaperLoading[] = "txt_homescreen_dpopinfo_loading_wallpaper";
    41 const char hsLocTextId_ProgressDialog_WallpaperLoading[] =
       
    42             "txt_homescreen_dpopinfo_loading_wallpaper";
    44 
    43 
    45 /*! 
    44 /*! 
    46     \class HsSelectBackgroundState
    45     \class HsSelectBackgroundState
    47     \ingroup group_hshomescreenstateprovider
    46     \ingroup group_hshomescreenstateprovider
    48     \brief Implements imagefetcher event listening and handles those events.
    47     \brief Implements imagefetcher event listening and handles those events.
    56 */
    55 */
    57 HsSelectBackgroundState::HsSelectBackgroundState(QState *parent):
    56 HsSelectBackgroundState::HsSelectBackgroundState(QState *parent):
    58     QState(parent),
    57     QState(parent),
    59     mImageFetcher(0),
    58     mImageFetcher(0),
    60     mSourceView(0),
    59     mSourceView(0),
    61     mWallpaperImageReaderThread(0),
    60     mPortraitWallpaperImageReader(0),
    62     mWallpaperImageReader(0),
    61     mLandscapeWallpaperImageReader(0),
    63     mProgressDialog(0),
    62     mProgressDialog(0),
    64     mImageProcessingState(NotRunning),
    63     mRunningThreadAmount(0),
    65     mShowAnimation(false)
    64     mShowAnimation(false)
    66 {
    65 {
    67 #ifdef Q_OS_SYMBIAN
    66 #ifdef Q_OS_SYMBIAN
    68     mImageFetcher = new HsImageFetcherClient(this);
    67     mImageFetcher = new HsImageFetcherClient(this);
    69 #else    
    68 #else    
    80     
    79     
    81 */
    80 */
    82 HsSelectBackgroundState::~HsSelectBackgroundState()
    81 HsSelectBackgroundState::~HsSelectBackgroundState()
    83 {
    82 {
    84     delete mImageFetcher;
    83     delete mImageFetcher;
    85     delete mWallpaperImageReaderThread;
    84     delete mPortraitWallpaperImageReader;
    86     delete mWallpaperImageReader;
    85     delete mLandscapeWallpaperImageReader;
    87 }
    86 }
    88 
    87 
    89 /*!
    88 /*!
    90     \internal
    89     \internal
    91     Connects to image fetcher and launches "remote" ui from photos
    90     Connects to image fetcher and launches "remote" ui from photos
    93 */
    92 */
    94 void HsSelectBackgroundState::action_selectWallpaper()
    93 void HsSelectBackgroundState::action_selectWallpaper()
    95 {
    94 {
    96     mSourceView = HsScene::mainWindow()->currentView();
    95     mSourceView = HsScene::mainWindow()->currentView();
    97 
    96 
    98     mImageProcessingState = NotRunning;
    97     mRunningThreadAmount = 0;
    99     mShowAnimation = false;
    98     mShowAnimation = false;
   100 
    99 
   101 #ifdef Q_OS_SYMBIAN
   100 #ifdef Q_OS_SYMBIAN
   102     connect(mImageFetcher, SIGNAL(fetchCompleted(const QString&)),
   101     connect(mImageFetcher, SIGNAL(fetchCompleted(const QString&)),
   103             this, SLOT(fetchCompleted(const QString&)));
   102             this, SLOT(fetchCompleted(const QString&)));
   127     \internal
   126     \internal
   128     Called when user has selected an image 
   127     Called when user has selected an image 
   129 */
   128 */
   130 void HsSelectBackgroundState::onFetchComplete(QStringList imageStringList)
   129 void HsSelectBackgroundState::onFetchComplete(QStringList imageStringList)
   131 {
   130 {
   132     if (mImageProcessingState == NotRunning) {
   131     // start animation immediately
   133         // TODO: temporarily show animation immediately (~0.5 sec delay)
   132     onShowAnimation();
   134         onShowAnimation();
   133 
   135         // start counting time for possible animation
   134     // check that sceneData is available
   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();
   135     HsDatabase *db = HsDatabase::instance();
   234     Q_ASSERT(db);
   136     Q_ASSERT(db);
   235     HsSceneData sceneData;
   137     HsSceneData sceneData;
   236     if (!db->scene(sceneData)) {
   138     if (!db->scene(sceneData)) {
   237         emit handleError();
   139         emit handleError();
   238         return;
   140         return;
   239     }
   141     }
   240     QFileInfo fileInfo(mWallpaperImageReader->getSourcePath());
   142 
       
   143     // clean thread instances
       
   144     delete mPortraitWallpaperImageReader;
       
   145     delete mLandscapeWallpaperImageReader;
       
   146     mPortraitWallpaperImageReader = NULL;
       
   147     mLandscapeWallpaperImageReader = NULL;
       
   148 
       
   149     mPortraitWallpaperImageReader = new HsWallpaperImageReader();
       
   150     mLandscapeWallpaperImageReader = new HsWallpaperImageReader();
       
   151 
       
   152     mRunningThreadAmount = 2;
       
   153 
       
   154     // delete old wallpapers
       
   155     QFile::remove(sceneData.portraitWallpaper);
       
   156     QFile::remove(sceneData.landscapeWallpaper);
       
   157 
       
   158     QString wallpaperDir = HsWallpaper::wallpaperDirectory();            
       
   159     QDir dir(wallpaperDir);
       
   160     if (!dir.exists()) {
       
   161         dir.mkpath(wallpaperDir);
       
   162     }
       
   163 
       
   164     // left empty to signal we want to use full size image as source
       
   165     QRect sourceRect;
       
   166 
       
   167     // Initialize portrait image threading
       
   168     QRect targetRectPortrait(0, 0, (2 * 360) + HsConfiguration::bounceEffect(), 640);
       
   169     mPortraitWallpaperImageReader->setSourcePath(imageStringList.first());
       
   170     mPortraitWallpaperImageReader->setSourceRect(sourceRect);
       
   171     mPortraitWallpaperImageReader->setTargetRect(targetRectPortrait);
       
   172     mPortraitWallpaperImageReader->setCenterTarget(true);
       
   173 
       
   174     connect(mPortraitWallpaperImageReader,
       
   175             SIGNAL(finished()),
       
   176             SLOT(onImageProcessed()));
       
   177 
       
   178     // Initialize landscape image threading
       
   179     QRect targetRectLandscape(0, 0, (2 * 640) + HsConfiguration::bounceEffect(), 360);
       
   180     mLandscapeWallpaperImageReader->setSourcePath(imageStringList.first());
       
   181     mLandscapeWallpaperImageReader->setSourceRect(sourceRect);
       
   182     mLandscapeWallpaperImageReader->setTargetRect(targetRectLandscape);
       
   183     mLandscapeWallpaperImageReader->setCenterTarget(true);
       
   184 
       
   185     connect(mLandscapeWallpaperImageReader,
       
   186             SIGNAL(finished()),
       
   187             SLOT(onImageProcessed()));
       
   188   
       
   189     // start image processing in thread
       
   190     mPortraitWallpaperImageReader->start();
       
   191     mLandscapeWallpaperImageReader->start();
       
   192 }
       
   193 
       
   194 /*!
       
   195     \internal
       
   196     Called when selection of background image fails  
       
   197 */
       
   198 void HsSelectBackgroundState::onFetchFailed(int error)
       
   199 {
       
   200     Q_UNUSED(error)
       
   201     emit handleError();
       
   202 }
       
   203 
       
   204 /*!
       
   205     \internal
       
   206     Called when image processing is finished in thread  
       
   207 */
       
   208 void HsSelectBackgroundState::onImageProcessed()
       
   209 {
       
   210     mRunningThreadAmount--;
       
   211 
       
   212     HsDatabase *db = HsDatabase::instance();
       
   213     Q_ASSERT(db);
       
   214     HsSceneData sceneData;
       
   215     if (!db->scene(sceneData)) {
       
   216         emit handleError();
       
   217         return;
       
   218     }
       
   219 
       
   220     QFileInfo fileInfo;
       
   221     // get image path
       
   222     if (sender() == mPortraitWallpaperImageReader) {
       
   223         fileInfo = mPortraitWallpaperImageReader->sourcePath();
       
   224     } else {
       
   225         fileInfo = mLandscapeWallpaperImageReader->sourcePath();
       
   226     }
       
   227     // suffix is same for both orientations
   241     QString fileExtension("");
   228     QString fileExtension("");
   242     if (!fileInfo.suffix().isEmpty()) {
   229     if (!fileInfo.suffix().isEmpty()) {
   243         fileExtension = fileInfo.suffix();
   230         fileExtension = fileInfo.suffix();
   244     }
   231     }
   245     // set image path to sceneData
   232 
   246     QString path;
   233     QImage image;
   247     if (mImageProcessingState == ProcessPortraitAsFirst ||
   234     // set portrait image path to sceneData
   248         mImageProcessingState == ProcessPortraitAsSecond) {
   235     QString portraitPath(HsWallpaper::wallpaperPath(Qt::Vertical, QString(),
   249         path = HsWallpaper::wallpaperPath(Qt::Vertical, QString(), fileExtension);
   236                                                     fileExtension));
   250         sceneData.portraitWallpaper = path;
   237     // we need to set this always as image to be activated can be either orientation
       
   238     sceneData.portraitWallpaper = portraitPath;
       
   239     QString landscapePath(HsWallpaper::wallpaperPath(Qt::Horizontal, QString(),
       
   240                                                      fileExtension));
       
   241     sceneData.landscapeWallpaper = landscapePath;
       
   242 
       
   243     if (sender() == mPortraitWallpaperImageReader) {
       
   244         // get image from thread
       
   245         image = mPortraitWallpaperImageReader->processedImage();
       
   246         // save image
       
   247         image.save(portraitPath);
   251     } else {
   248     } else {
   252         path = HsWallpaper::wallpaperPath(Qt::Horizontal, QString(), fileExtension);
   249         image = mLandscapeWallpaperImageReader->processedImage();
   253         sceneData.landscapeWallpaper = path;
   250         image.save(landscapePath);
   254     }
   251     }
   255     // get image from renderer and save it
   252 
   256     QImage image = mWallpaperImageReader->getProcessedImage();
   253     if (image.isNull()) {
   257     image.save(path);
   254         emit handleError();
   258     if (!image.isNull()) {
   255         return;
   259         // update scenedata and set new image to background
   256     }
   260         if (db->updateScene(sceneData)) {
   257     // update scenedata and set new image to background
   261             switch (mImageProcessingState) {
   258     if (db->updateScene(sceneData)) {
   262             case ProcessPortraitAsFirst:
   259         HsScene *scene = HsScene::instance();
   263                 scene->wallpaper()->setPortraitImage(path, true);
   260         // set image to wallpaper (don't activate yet)
   264                 break;
   261         if (sender() == mPortraitWallpaperImageReader) {
   265             case ProcessPortraitAsSecond:
   262             scene->wallpaper()->setPortraitImage(portraitPath, false);
   266                 // if orientation changed during first image settings
   263         } else {
   267                 if (HsScene::orientation() == Qt::Vertical) {
   264             scene->wallpaper()->setLandscapeImage(landscapePath, false);
   268                     scene->wallpaper()->setPortraitImage(path, true);
   265         }
   269                 } else {
   266         // if last thread running
   270                     scene->wallpaper()->setPortraitImage(path);
   267         if (mRunningThreadAmount == 0) {
   271                 }
   268             // if current orientation matches -> set to active wallpaper
   272                 break;
   269             if (HsScene::orientation() == Qt::Vertical) {
   273             case ProcessLandscapeAsFirst:
   270                 scene->wallpaper()->setPortraitImage(portraitPath, true);
   274                 scene->wallpaper()->setLandscapeImage(path, true);
   271             } else {
   275                 break;
   272                 scene->wallpaper()->setLandscapeImage(landscapePath, true);
   276             case ProcessLandscapeAsSecond:
   273             }
   277                 if (HsScene::orientation() == Qt::Horizontal) {
   274             // finish progress bar
   278                     scene->wallpaper()->setLandscapeImage(path, true);
   275             if (mShowAnimation) {
   279                 } else {
   276                 mProgressDialog->setProgressValue(3);
   280                     scene->wallpaper()->setLandscapeImage(path);
   277             }
   281                 }
   278             // let user control again homescreen
   282                 break;
   279             emit event_waitInput();
   283             default:
   280         } else {
   284                 emit handleError();
   281             // update progress information
   285                 break;
   282             if (mShowAnimation) {
       
   283                 mProgressDialog->setProgressValue(2);
   286             }
   284             }
   287         }
   285         }
   288     } else {
   286     }     
   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 }
   287 }
   323 
   288 
   324 /*!
   289 /*!
   325     \internal
   290     \internal
   326     Shows animation for longer processing
   291     Shows animation for longer processing
   327 */
   292 */
   328 void HsSelectBackgroundState::onShowAnimation()
   293 void HsSelectBackgroundState::onShowAnimation()
   329 {
   294 {
   330     delete mProgressDialog;
   295     delete mProgressDialog;
   331     mProgressDialog = new HbProgressDialog(HbProgressDialog::ProgressDialog);
   296     mProgressDialog = new HbProgressDialog(HbProgressDialog::ProgressDialog);
   332     // TODO: setPrimaryAction is deprecated, clearActions does the same but crashes when dialog closes, check orbit list
   297     /* TODO: workaround to remove cancel button (setPrimaryAction(0) is deprecated).
   333     mProgressDialog->setPrimaryAction(0);
   298      * clearActions does the same but crashes, fix should be in wk16, check orbit list
       
   299      */
       
   300     QList<QAction*> actions = mProgressDialog->actions();
       
   301     actions[0]->setVisible(false);
   334     mProgressDialog->setIcon(HbIcon("note_info"));
   302     mProgressDialog->setIcon(HbIcon("note_info"));
   335     mProgressDialog->setText(hbTrId(hsLocTextId_ProgressDialog_WallpaperLoading));
   303     mProgressDialog->setText(hbTrId(hsLocTextId_ProgressDialog_WallpaperLoading));
   336     mProgressDialog->setMinimum(0);
   304     mProgressDialog->setMinimum(0);
   337     mProgressDialog->setMaximum(3);
   305     mProgressDialog->setMaximum(3);
   338     mProgressDialog->setBackgroundFaded(true);
   306     mProgressDialog->setBackgroundFaded(true);
   339     mProgressDialog->setAutoClose(true);
   307     mProgressDialog->setAutoClose(true);
       
   308     // set initial value to appear as loading
   340     mProgressDialog->setProgressValue(1);
   309     mProgressDialog->setProgressValue(1);
   341     mProgressDialog->show();
   310     mProgressDialog->show();
   342     // TODO: temporary solution to minimize progress dialog resizing problem
       
   343     QApplication::processEvents();
       
   344     mShowAnimation = true;
   311     mShowAnimation = true;
   345 }
   312 }
   346 
   313 
   347 /*!
   314 /*!
   348     \internal
   315     \internal
   349     Called when error occurs during image processing  
   316     Called when error occurs during image processing  
   350 */
   317 */
   351 void HsSelectBackgroundState::onHandleError()
   318 void HsSelectBackgroundState::onHandleError()
   352 {
   319 {
   353     mImageProcessingState = Error;
       
   354     if (mShowAnimation) {
   320     if (mShowAnimation) {
   355         mProgressDialog->close();
   321         mProgressDialog->close();
   356     }
   322     }
   357     emit event_waitInput();
   323     emit event_waitInput();
   358 }
   324 }