src/hbservers/hbsplashgenerator/hbsplashgenerator.cpp
changeset 3 11d3954df52a
parent 2 06ff229162e9
child 5 627c4a0fd0e7
equal deleted inserted replaced
2:06ff229162e9 3:11d3954df52a
    23 **
    23 **
    24 ****************************************************************************/
    24 ****************************************************************************/
    25 
    25 
    26 #include "hbsplashgenerator_p.h"
    26 #include "hbsplashgenerator_p.h"
    27 #include "hbsplashdirs_p.h"
    27 #include "hbsplashdirs_p.h"
       
    28 #include "hbsplashdefs_p.h"
    28 #include "hbmainwindow.h"
    29 #include "hbmainwindow.h"
    29 #include "hbmainwindow_p.h"
    30 #include "hbmainwindow_p.h"
    30 #include "hbinstance.h"
    31 #include "hbinstance.h"
    31 #include "hbtheme.h"
    32 #include "hbtheme.h"
    32 #include "hbeffectinternal_p.h"
    33 #include "hbeffectinternal_p.h"
    43 #include <QPainter>
    44 #include <QPainter>
    44 #include <QDir>
    45 #include <QDir>
    45 #include <QFile>
    46 #include <QFile>
    46 #include <QFileInfo>
    47 #include <QFileInfo>
    47 #include <QSet>
    48 #include <QSet>
       
    49 #include <QSettings>
    48 #include <QTranslator>
    50 #include <QTranslator>
    49 #include <QLocale>
    51 #include <QLocale>
    50 #include <QTimer>
    52 #include <QTimer>
       
    53 
       
    54 #if defined(Q_OS_SYMBIAN)
       
    55 #include <f32file.h>
       
    56 #include <coemain.h>
       
    57 #endif
    51 
    58 
    52 const char *last_theme_key = "lasttheme";
    59 const char *last_theme_key = "lasttheme";
    53 const char *last_lang_key = "lastlang";
    60 const char *last_lang_key = "lastlang";
    54 const char *last_file_count_key = "lastfilecount";
    61 const char *last_file_count_key = "lastfilecount";
    55 const char *last_output_dir_key = "lastoutdir";
    62 const char *last_output_dir_key = "lastoutdir";
    56 
    63 
    57 HbSplashGenerator::HbSplashGenerator()
    64 HbSplashGenerator::HbSplashGenerator()
    58     : mBusy(false), mForceRegen(false), mMainWindow(0), mFirstRegenerate(true),
    65     : mBusy(false), mForceRegen(false), mMainWindow(0), mFirstRegenerate(true)
    59       mSettings("Nokia", "HbSplash")
    66 {
    60 {
    67 #if defined(Q_OS_SYMBIAN)
       
    68     CCoeEnv::Static()->FsSession().CreatePrivatePath(EDriveC);
       
    69     QString iniFileName = QString("c:/private/%1/hbsplashgen.ini")
       
    70         .arg(QString::number(hbsplash_server_uid3.iUid, 16));
       
    71     mSettings = new QSettings(iniFileName, QSettings::IniFormat, this);
       
    72 #else
       
    73     mSettings = new QSettings("Nokia", "HbSplash", this);
       
    74 #endif
    61     // Effects on decorators (started when they are shown) would ruin
    75     // Effects on decorators (started when they are shown) would ruin
    62     // the screenshot. So disable everything (except the orientation
    76     // the screenshot. So disable everything (except the orientation
    63     // switch effect which is needed for a proper rotated image).
    77     // switch effect which is needed for a proper rotated image).
    64     HbEffectInternal::setEffectsEnabled(false);
    78     HbEffectInternal::setEffectsEnabled(false);
    65 }
    79 }
   127 
   141 
   128     // Regenerate screens on startup only when the theme, the language, the
   142     // Regenerate screens on startup only when the theme, the language, the
   129     // number of files in the splash screen directory, or the splash screen
   143     // number of files in the splash screen directory, or the splash screen
   130     // directory path is different than the recorded values. (or when
   144     // directory path is different than the recorded values. (or when
   131     // regeneration is forced via command line arg)
   145     // regeneration is forced via command line arg)
   132     QString lastTheme = mSettings.value(QLatin1String(last_theme_key)).toString();
   146     QString lastTheme = mSettings->value(QLatin1String(last_theme_key)).toString();
   133     QString lastLang = mSettings.value(QLatin1String(last_lang_key)).toString();
   147     QString lastLang = mSettings->value(QLatin1String(last_lang_key)).toString();
   134     int lastFileCount = mSettings.value(QLatin1String(last_file_count_key)).toInt();
   148     int lastFileCount = mSettings->value(QLatin1String(last_file_count_key)).toInt();
   135     QString lastOutputDir = mSettings.value(QLatin1String(last_output_dir_key)).toString();
   149     QString lastOutputDir = mSettings->value(QLatin1String(last_output_dir_key)).toString();
   136     QString currentTheme = theme->name();
   150     QString currentTheme = theme->name();
   137     QString currentLang = QLocale::system().name();
   151     QString currentLang = QLocale::system().name();
   138     QString currentOutputDir = hbsplash_output_dir();
   152     QString currentOutputDir = hbsplash_output_dir();
   139     int currentFileCount = updateOutputDirContents(currentOutputDir);
   153     int currentFileCount = updateOutputDirContents(currentOutputDir);
   140     qDebug() << PRE << "last regen:" << lastTheme << lastLang << lastFileCount << lastOutputDir
   154     qDebug() << PRE << "last regen:" << lastTheme << lastLang << lastFileCount << lastOutputDir
   161 {
   175 {
   162     QString themeName = hbInstance->theme()->name();
   176     QString themeName = hbInstance->theme()->name();
   163     qDebug() << PRE << "regenerate() theme:" << themeName;
   177     qDebug() << PRE << "regenerate() theme:" << themeName;
   164     if (!themeName.isEmpty()) {
   178     if (!themeName.isEmpty()) {
   165         try {
   179         try {
       
   180             emit regenerateStarted();
   166             QTime queuePrepTime;
   181             QTime queuePrepTime;
   167             queuePrepTime.start();
   182             queuePrepTime.start();
   168             // Delete existing splash screens. This is important because apps
   183             // Delete existing splash screens. This is important because apps
   169             // should never pick up a screen with the previous theme or
   184             // should never pick up a screen with the previous theme or
   170             // language. If the generation of the new screens (at least the
   185             // language. If the generation of the new screens (at least the
   200             cleanup();
   215             cleanup();
   201         }
   216         }
   202     }
   217     }
   203 }
   218 }
   204 
   219 
   205 void HbSplashGenerator::regenerateOne(const QString &splashmlFileName)
   220 void HbSplashGenerator::regenerateOne(const QString &splashmlFileName, const QString &customTrDir)
   206 {
   221 {
   207     mQueue.clear();
   222     mQueue.clear();
   208     QueueItem item(hbInstance->theme()->name(), Qt::Vertical);
   223     QueueItem item(hbInstance->theme()->name(), Qt::Vertical);
   209     item.mWorkDirForSingleFileRegen = QFileInfo(splashmlFileName).path(); // e.g. for translations
   224     QString path = QFileInfo(splashmlFileName).path();
       
   225     item.mCustomTrDirs.append(path);
       
   226     if (!customTrDir.isEmpty()) {
       
   227         item.mCustomTrDirs.append(customTrDir);
       
   228     }
   210     parseSplashml(splashmlFileName, item);
   229     parseSplashml(splashmlFileName, item);
   211     item.mDocmlFileName = QDir(item.mWorkDirForSingleFileRegen).filePath(item.mDocmlFileName);
   230     item.mDocmlFileName = QDir(path).filePath(item.mDocmlFileName);
   212     mQueue.enqueue(item); // generate it regardless of the fixed orientation setting
   231     mQueue.enqueue(item); // generate it regardless of the fixed orientation setting
   213     item.mOrientation = Qt::Horizontal;
   232     item.mOrientation = Qt::Horizontal;
   214     mQueue.enqueue(item);
   233     mQueue.enqueue(item);
   215     QMetaObject::invokeMethod(this, "processQueue", Qt::QueuedConnection);
   234     QMetaObject::invokeMethod(this, "processQueue", Qt::QueuedConnection);
   216 }
   235 }
   243     // If the queue is empty then the splash regeneraton is complete so store
   262     // If the queue is empty then the splash regeneraton is complete so store
   244     // the current theme and language names as the last fully processed ones in
   263     // the current theme and language names as the last fully processed ones in
   245     // the settings and stop.
   264     // the settings and stop.
   246     if (mQueue.isEmpty()) {
   265     if (mQueue.isEmpty()) {
   247         qDebug() << PRE << "queue is empty  regen finished";
   266         qDebug() << PRE << "queue is empty  regen finished";
   248         mSettings.setValue(last_theme_key, hbInstance->theme()->name());
   267         mSettings->setValue(last_theme_key, hbInstance->theme()->name());
   249         mSettings.setValue(last_lang_key, QLocale::system().name());
   268         mSettings->setValue(last_lang_key, QLocale::system().name());
   250         QString outDir = hbsplash_output_dir();
   269         QString outDir = hbsplash_output_dir();
   251         mSettings.setValue(last_file_count_key, updateOutputDirContents(outDir));
   270         mSettings->setValue(last_file_count_key, updateOutputDirContents(outDir));
   252         mSettings.setValue(last_output_dir_key, outDir);
   271         mSettings->setValue(last_output_dir_key, outDir);
   253         emit finished();
   272         emit finished();
   254         qDebug() << PRE << "processQueue() over";
   273         qDebug() << PRE << "processQueue() over";
   255         return;
   274         return;
   256     }
   275     }
   257     // If a previous splash generation is still in progress then do nothing.
   276     // If a previous splash generation is still in progress then do nothing.
   263         mBusy = true;
   282         mBusy = true;
   264         mItem = mQueue.dequeue();
   283         mItem = mQueue.dequeue();
   265         mItemTime.start();
   284         mItemTime.start();
   266         log("generating splash screen", mItem.mThemeName, mItem.mOrientation);
   285         log("generating splash screen", mItem.mThemeName, mItem.mOrientation);
   267 
   286 
   268         if (!mMainWindow) {
   287         ensureMainWindow();
   269             // The FixedVertical flag is used just to disable the sensor-based
       
   270             // orientation switching.
       
   271             mMainWindow = new HbMainWindow(0, Hb::WindowFlagFixedVertical);
       
   272             // Make sure that at least the 1st phase of the delayed
       
   273             // construction is done right now.
       
   274             HbMainWindowPrivate::d_ptr(mMainWindow)->_q_delayedConstruction();
       
   275         }
       
   276         mMainWindow->setOrientation(mItem.mOrientation, false);
   288         mMainWindow->setOrientation(mItem.mOrientation, false);
   277         qDebug() << PRE << "mainwindow init time (ms):" << mItemTime.elapsed();
   289         qDebug() << PRE << "mainwindow init time (ms):" << mItemTime.elapsed();
   278 
   290 
   279         QTime setupTime;
   291         QTime setupTime;
   280         setupTime.start();
   292         setupTime.start();
   286 
   298 
   287     } catch (const std::bad_alloc &) {
   299     } catch (const std::bad_alloc &) {
   288         cleanup();
   300         cleanup();
   289     }
   301     }
   290     qDebug() << PRE << "processQueue() over";
   302     qDebug() << PRE << "processQueue() over";
       
   303 }
       
   304 
       
   305 void HbSplashGenerator::ensureMainWindow()
       
   306 {
       
   307     if (!mMainWindow) {
       
   308         // The FixedVertical flag is used just to disable the sensor-based
       
   309         // orientation switching.
       
   310         mMainWindow = new HbMainWindow(0, Hb::WindowFlagFixedVertical);
       
   311         // Make sure that at least the 1st phase of the delayed
       
   312         // construction is done right now.
       
   313         HbMainWindowPrivate::d_ptr(mMainWindow)->_q_delayedConstruction();
       
   314     }
   291 }
   315 }
   292 
   316 
   293 void HbSplashGenerator::processWindow()
   317 void HbSplashGenerator::processWindow()
   294 {
   318 {
   295     // Take the screenshot, remove content, and move on to the next request in the queue.
   319     // Take the screenshot, remove content, and move on to the next request in the queue.
   323         QImage image = renderView();
   347         QImage image = renderView();
   324         QTime t;
   348         QTime t;
   325         t.start();
   349         t.start();
   326         QString splashFile = splashFileName();
   350         QString splashFile = splashFileName();
   327         qDebug() << PRE << "saving to" << splashFile;
   351         qDebug() << PRE << "saving to" << splashFile;
   328         if (saveSpl(splashFile, image)) {
   352         if (saveSpl(splashFile, image, mItem.mFlagsToStore)) {
   329 #if !defined(Q_OS_SYMBIAN) && defined(QT_DEBUG)
   353 #if !defined(Q_OS_SYMBIAN) && defined(QT_DEBUG)
   330             image.save(splashFile + QLatin1String(".png"));
   354             image.save(splashFile + QLatin1String(".png"));
   331 #endif
   355 #endif
   332         } else {
   356         } else {
   333             qWarning() << PRE << "file write failed for" << splashFile;
   357             qWarning() << PRE << "file write failed for" << splashFile;
   366 inline const uchar *imageBits(const QImage &image)
   390 inline const uchar *imageBits(const QImage &image)
   367 {
   391 {
   368     return image.bits();
   392     return image.bits();
   369 }
   393 }
   370 
   394 
   371 bool HbSplashGenerator::saveSpl(const QString &nameWithoutExt, const QImage &image)
   395 bool HbSplashGenerator::saveSpl(const QString &nameWithoutExt, const QImage &image, quint32 extra)
   372 {
   396 {
   373     QString fn(nameWithoutExt);
   397     QString fn(nameWithoutExt);
   374     fn.append(".spl");
   398     fn.append(".spl");
   375     QFile f(fn);
   399     QFile f(fn);
   376     if (f.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
   400     if (f.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
   377         int w = image.width();
   401         quint32 w = (quint32) image.width();
   378         int h = image.height();
   402         quint32 h = (quint32) image.height();
   379         int bpl = image.bytesPerLine();
   403         quint32 bpl = (quint32) image.bytesPerLine();
   380         QImage::Format fmt = image.format();
   404         qint32 fmt = (qint32) image.format();
   381         f.write((char *) &w, sizeof(int));
   405         f.write((char *) &w, sizeof(quint32));
   382         f.write((char *) &h, sizeof(int));
   406         f.write((char *) &h, sizeof(quint32));
   383         f.write((char *) &bpl, sizeof(int));
   407         f.write((char *) &bpl, sizeof(quint32));
   384         f.write((char *) &fmt, sizeof(QImage::Format));
   408         f.write((char *) &fmt, sizeof(qint32));
       
   409         f.write((char *) &extra, sizeof(quint32));
   385         f.write((const char *) imageBits(image), bpl * h);
   410         f.write((const char *) imageBits(image), bpl * h);
   386         f.close();
   411         f.close();
   387         return true;
   412         return true;
   388     }
   413     }
   389     return false;
   414     return false;
   412     return dbg;
   437     return dbg;
   413 }
   438 }
   414 
   439 
   415 HbSplashGenerator::QueueItem::QueueItem()
   440 HbSplashGenerator::QueueItem::QueueItem()
   416     : mOrientation(Qt::Vertical),
   441     : mOrientation(Qt::Vertical),
   417       mHideBackground(false)
   442       mHideBackground(false),
       
   443       mFlagsToStore(0)
   418 {
   444 {
   419 }
   445 }
   420 
   446 
   421 HbSplashGenerator::QueueItem::QueueItem(const QString &themeName, Qt::Orientation orientation)
   447 HbSplashGenerator::QueueItem::QueueItem(const QString &themeName, Qt::Orientation orientation)
   422     : mThemeName(themeName), mOrientation(orientation),
   448     : mThemeName(themeName),
   423       mHideBackground(false)
   449       mOrientation(orientation),
       
   450       mHideBackground(false),
       
   451       mFlagsToStore(0)
   424 {
   452 {
   425 }
   453 }
   426 
   454 
   427 void HbSplashGenerator::addSplashmlItemToQueue(const QueueItem &item)
   455 void HbSplashGenerator::addSplashmlItemToQueue(const QueueItem &item)
   428 {
   456 {
   715     }
   743     }
   716 }
   744 }
   717 
   745 
   718 void HbSplashGenerator::finishWindow()
   746 void HbSplashGenerator::finishWindow()
   719 {
   747 {
   720     // Process additional settings.
   748     // There must be a view always in order to support view-specific settings.
   721     if (mMainWindow->views().isEmpty()) {
   749     if (mMainWindow->views().isEmpty()) {
   722         // There must be a view always in order to support view-specific settings.
       
   723         mMainWindow->addView(new HbWidget);
   750         mMainWindow->addView(new HbWidget);
   724     }
   751     }
   725 
   752 
   726     QList<HbView *> views = mMainWindow->views();
   753     QList<HbView *> views = mMainWindow->views();
   727     if (!views.isEmpty()) {
   754     if (!views.isEmpty()) {
   728         HbView *view = views.at(0);
   755         HbView *view = views.at(0);
   729 
   756 
   730         // view-flags
   757         // view-flags
   731         HbView::HbViewFlags viewFlags = HbView::ViewFlagNone;
   758         HbView::HbViewFlags viewFlags = view->viewFlags();
   732         if (mItem.mViewFlags.contains("tb-minimizable")) {
   759         if (mItem.mViewFlags.contains("tb-minimizable")) {
   733             viewFlags |= HbView::ViewTitleBarMinimizable;
   760             viewFlags |= HbView::ViewTitleBarMinimizable;
   734         }
   761         }
   735         if (mItem.mViewFlags.contains("tb-minimized")) {
   762         if (mItem.mViewFlags.contains("tb-minimized")) {
   736             viewFlags |= HbView::ViewTitleBarMinimized;
   763             viewFlags |= HbView::ViewTitleBarMinimized;
   752         }
   779         }
   753         if (mItem.mViewFlags.contains("sb-floating")) {
   780         if (mItem.mViewFlags.contains("sb-floating")) {
   754             viewFlags |= HbView::ViewStatusBarFloating;
   781             viewFlags |= HbView::ViewStatusBarFloating;
   755         }
   782         }
   756         view->setViewFlags(viewFlags);
   783         view->setViewFlags(viewFlags);
       
   784         if (viewFlags.testFlag(HbView::ViewStatusBarHidden)
       
   785             || viewFlags.testFlag(HbView::ViewStatusBarTransparent))
       
   786         {
       
   787             mItem.mFlagsToStore |= 1;
       
   788         }
   757 
   789 
   758         // navi-action-icon
   790         // navi-action-icon
   759         if (!mItem.mNaviActionIcon.isEmpty()) {
   791         if (!mItem.mNaviActionIcon.isEmpty()) {
   760             view->setNavigationAction(new HbAction(HbIcon(mItem.mNaviActionIcon), QString(), view));
   792             view->setNavigationAction(new HbAction(HbIcon(mItem.mNaviActionIcon), QString(), view));
   761         } // else will use the default navigation action (e.g. quit)
   793         } // else will use the default navigation action (e.g. quit)
   790             mMainWindow->setBackgroundImageName(mItem.mOrientation, backgroundImageName);
   822             mMainWindow->setBackgroundImageName(mItem.mOrientation, backgroundImageName);
   791         }
   823         }
   792     }
   824     }
   793 
   825 
   794     // Hide dynamic content from status bar (clock, indicators).
   826     // Hide dynamic content from status bar (clock, indicators).
       
   827     setStatusBarElementsVisible(false);
       
   828 }
       
   829 
       
   830 void HbSplashGenerator::setStatusBarElementsVisible(bool visible)
       
   831 {
       
   832     HbMainWindowPrivate *mwd = HbMainWindowPrivate::d_ptr(mMainWindow);
   795     HbStatusBar *statusBar = mwd->mStatusBar;
   833     HbStatusBar *statusBar = mwd->mStatusBar;
   796     if (statusBar) {
   834     if (statusBar) {
   797         foreach (QGraphicsItem *item, statusBar->childItems()) {
   835         foreach (QGraphicsItem *item, statusBar->childItems()) {
   798             QString name = HbStyle::itemName(item);
   836             QString name = HbStyle::itemName(item);
   799             bool hideItem = name == QLatin1String("signal")
   837             bool knownItem =
       
   838                 name == QLatin1String("signal")
   800                 || name == QLatin1String("battery")
   839                 || name == QLatin1String("battery")
   801                 || name == QLatin1String("notificationindicators")
   840                 || name == QLatin1String("notificationindicators")
   802                 || name == QLatin1String("settingsindicators")
   841                 || name == QLatin1String("settingsindicators")
   803                 || name == QLatin1String("timetext");
   842                 || name == QLatin1String("timetext");
   804             if (hideItem) {
   843             if (knownItem) {
   805                 item->setVisible(false);
   844                 item->setVisible(visible);
   806             }
   845             }
   807         }
   846         }
   808     }
   847     }
   809 }
   848 }
   810 
   849 
   812 {
   851 {
   813     QString lang = QLocale::system().name();
   852     QString lang = QLocale::system().name();
   814     QTranslator *translator = new QTranslator;
   853     QTranslator *translator = new QTranslator;
   815     bool ok = false;
   854     bool ok = false;
   816     QStringList dirNames(hbsplash_translation_dirs());
   855     QStringList dirNames(hbsplash_translation_dirs());
   817     if (!mItem.mWorkDirForSingleFileRegen.isEmpty()) {
   856     dirNames.append(mItem.mCustomTrDirs);
   818         dirNames.append(mItem.mWorkDirForSingleFileRegen);
       
   819     }
       
   820     foreach (const QString &dirName, dirNames) {
   857     foreach (const QString &dirName, dirNames) {
   821         QDir dir(dirName);
   858         QDir dir(dirName);
   822         QString fullName = dir.filePath(name + '_' + lang);
   859         QString fullName = dir.filePath(name + '_' + lang);
   823         // fullName is not necessarily an existing file, however the translator
   860         // fullName is not necessarily an existing file, however the translator
   824         // may still pick up another suitable file based on this name.
   861         // may still pick up another suitable file based on this name.