59 const char *last_theme_key = "lasttheme"; |
59 const char *last_theme_key = "lasttheme"; |
60 const char *last_lang_key = "lastlang"; |
60 const char *last_lang_key = "lastlang"; |
61 const char *last_file_count_key = "lastfilecount"; |
61 const char *last_file_count_key = "lastfilecount"; |
62 const char *last_output_dir_key = "lastoutdir"; |
62 const char *last_output_dir_key = "lastoutdir"; |
63 |
63 |
|
64 // Using invokeMethod with QueuedConnection is not good enough as it can |
|
65 // cause starvation for Symbian active objects (at least in Qt versions |
|
66 // before 4.7.2) so the theme change notification would get delayed until |
|
67 // an entire regeneration cycle is finished, which is not acceptable. So |
|
68 // use a QTimer with a small timeout instead. A small delay is beneficial |
|
69 // anyway to divide the load a bit better so perf does not drop that much |
|
70 // in apps while regeneration is on-going. |
|
71 #define NEXT_STAGE(obj, func) QTimer::singleShot(10, this, SLOT(func())) |
|
72 |
64 HbSplashGenerator::HbSplashGenerator() |
73 HbSplashGenerator::HbSplashGenerator() |
65 : mMainWindowLocked(false), |
74 : mMainWindowLocked(false), |
66 mProcessQueuePending(false), |
75 mProcessQueuePending(false), |
67 mForceRegen(false), |
76 mForceRegen(false), |
68 mMainWindow(0), |
77 mMainWindow(0), |
69 mFirstRegenerate(true) |
78 mFirstRegenerate(true), |
|
79 mSaveSplFailed(false) |
70 { |
80 { |
71 #if defined(Q_OS_SYMBIAN) |
81 #if defined(Q_OS_SYMBIAN) |
72 CCoeEnv::Static()->FsSession().CreatePrivatePath(EDriveC); |
82 CCoeEnv::Static()->FsSession().CreatePrivatePath(EDriveC); |
73 QString iniFileName = QString("c:/private/%1/hbsplashgen.ini") |
83 QString iniFileName = QString("c:/private/%1/hbsplashgen.ini") |
74 .arg(QString::number(hbsplash_server_uid3.iUid, 16)); |
84 .arg(QString::number(hbsplash_server_uid3.iUid, 16)); |
142 if (QDir(dir).exists()) { |
154 if (QDir(dir).exists()) { |
143 mFsWatcher.addPath(dir); |
155 mFsWatcher.addPath(dir); |
144 } |
156 } |
145 } |
157 } |
146 |
158 |
|
159 // Regenerate screens, if needed. |
|
160 scheduleRegen(); |
|
161 } |
|
162 |
|
163 void HbSplashGenerator::scheduleRegen() |
|
164 { |
147 // Regenerate screens on startup only when the theme, the language, the |
165 // Regenerate screens on startup only when the theme, the language, the |
148 // number of files in the splash screen directory, or the splash screen |
166 // number of files in the splash screen directory, or the splash screen |
149 // directory path is different than the recorded values. (or when |
167 // directory path is different than the recorded values. (or when |
150 // regeneration is forced via command line arg) |
168 // regeneration is forced via command line arg) |
151 QString lastTheme = mSettings->value(QLatin1String(last_theme_key)).toString(); |
169 QString lastTheme = mSettings->value(QLatin1String(last_theme_key)).toString(); |
152 QString lastLang = mSettings->value(QLatin1String(last_lang_key)).toString(); |
170 QString lastLang = mSettings->value(QLatin1String(last_lang_key)).toString(); |
153 int lastFileCount = mSettings->value(QLatin1String(last_file_count_key)).toInt(); |
171 int lastFileCount = mSettings->value(QLatin1String(last_file_count_key)).toInt(); |
154 QString lastOutputDir = mSettings->value(QLatin1String(last_output_dir_key)).toString(); |
172 QString lastOutputDir = mSettings->value(QLatin1String(last_output_dir_key)).toString(); |
155 QString currentTheme = theme->name(); |
173 QString currentTheme = hbInstance->theme()->name(); |
156 QString currentLang = QLocale::system().name(); |
174 QString currentLang = QLocale::system().name(); |
157 QString currentOutputDir = hbsplash_output_dir(); |
175 QString currentOutputDir = hbsplash_output_dir(); |
158 int currentFileCount = updateOutputDirContents(currentOutputDir); |
176 int currentFileCount = updateOutputDirContents(currentOutputDir); |
159 qDebug() << PRE << "last regen:" << lastTheme << lastLang << lastFileCount << lastOutputDir |
177 qDebug() << PRE << "last regen:" << lastTheme << lastLang << lastFileCount << lastOutputDir |
160 << "current:" << currentTheme << currentLang << currentFileCount << currentOutputDir; |
178 << "current:" << currentTheme << currentLang << currentFileCount << currentOutputDir; |
184 try { |
214 try { |
185 emit regenerateStarted(); |
215 emit regenerateStarted(); |
186 QTime queuePrepTime; |
216 QTime queuePrepTime; |
187 queuePrepTime.start(); |
217 queuePrepTime.start(); |
188 // Delete existing splash screens. This is important because apps |
218 // Delete existing splash screens. This is important because apps |
189 // should never pick up a screen with the previous theme or |
219 // should never pick up a screen with the previous theme or language |
190 // language. If the generation of the new screens (at least the |
220 // (not even when generating screens with the new theme fails). If |
191 // empty view) has not finished when a new app is started then it is |
221 // the generation of the new screens (at least the empty view) has |
192 // better to show no splash screen at all. |
222 // not finished when a new app is started then it is better to show |
193 QDir outDir(hbsplash_output_dir()); |
223 // no splash screen at all. |
194 if (outDir.exists()) { |
224 delete_splash_screens(); |
195 QStringList names = outDir.entryList(QStringList() << "*", QDir::Files); |
|
196 foreach(const QString & name, names) { |
|
197 outDir.remove(name); |
|
198 } |
|
199 } |
|
200 // Clear the queue, generating screens with a non-current theme is |
225 // Clear the queue, generating screens with a non-current theme is |
201 // not possible anyway. |
226 // not possible anyway. |
202 mQueue.clear(); |
227 mQueue.clear(); |
203 // If this is the first invocation then put some requests for |
228 // If this is the first invocation then put some requests for |
204 // screens we won't use. On certain platforms the very first |
229 // screens we won't use. On certain platforms the very first |
212 // Queue the screenshot request for both orientations. |
237 // Queue the screenshot request for both orientations. |
213 mQueue.enqueue(QueueItem(themeName, Qt::Vertical)); |
238 mQueue.enqueue(QueueItem(themeName, Qt::Vertical)); |
214 mQueue.enqueue(QueueItem(themeName, Qt::Horizontal)); |
239 mQueue.enqueue(QueueItem(themeName, Qt::Horizontal)); |
215 queueAppSpecificItems(themeName, Qt::Vertical); |
240 queueAppSpecificItems(themeName, Qt::Vertical); |
216 queueAppSpecificItems(themeName, Qt::Horizontal); |
241 queueAppSpecificItems(themeName, Qt::Horizontal); |
217 qDebug() << PRE << "queue preparation time (ms):" << queuePrepTime.elapsed(); |
242 mSaveSplFailed = false; |
218 QMetaObject::invokeMethod(this, "processQueue", Qt::QueuedConnection); |
243 // If a previous regenerate is on-going, the mainwindow is locked |
|
244 // and we will not get to process the new queue entries before the |
|
245 // one screen, that is in progress, is done. However that one last |
|
246 // screen must not be rendered and written to file. To indicate |
|
247 // this, use a flag in the first queue entry. |
|
248 // |
|
249 // Note that removing the metacalls or timers is not an option as |
|
250 // that would lead to possibly leaving the mainwindow locked (and we |
|
251 // must never unlock it "manually" as it may be locked by some other |
|
252 // entity, e.g. the statusbar generator), so we have to let the last |
|
253 // screen to finish normally (excluding rendering and storage). |
|
254 mQueue.head().mFirstInRegen = true; |
|
255 splDeb() << PRE << "queue preparation time (ms):" << queuePrepTime.elapsed(); |
|
256 NEXT_STAGE(this, processQueue); |
219 } catch (const std::bad_alloc &) { |
257 } catch (const std::bad_alloc &) { |
220 cleanup(); |
258 cleanup(); |
221 } |
259 } |
222 } |
260 } |
223 } |
261 } |
224 |
262 |
|
263 // This function is for the splashviewer tool only, do not use from elsewhere. |
225 void HbSplashGenerator::regenerateOne(const QString &splashmlFileName, const QString &customTrDir) |
264 void HbSplashGenerator::regenerateOne(const QString &splashmlFileName, const QString &customTrDir) |
226 { |
265 { |
227 mQueue.clear(); |
266 mQueue.clear(); |
228 QueueItem item(hbInstance->theme()->name(), Qt::Vertical); |
267 QueueItem item(hbInstance->theme()->name(), Qt::Vertical); |
229 QString path = QFileInfo(splashmlFileName).path(); |
268 QString path = QFileInfo(splashmlFileName).path(); |
255 // these images) |
294 // these images) |
256 QImage image(mMainWindow->size(), QImage::Format_ARGB32_Premultiplied); |
295 QImage image(mMainWindow->size(), QImage::Format_ARGB32_Premultiplied); |
257 image.fill(QColor(Qt::transparent).rgba()); |
296 image.fill(QColor(Qt::transparent).rgba()); |
258 QPainter painter(&image); |
297 QPainter painter(&image); |
259 mMainWindow->render(&painter); |
298 mMainWindow->render(&painter); |
260 qDebug() << PRE << "rendering time (ms):" << t.elapsed(); |
299 splDeb() << PRE << "rendering time (ms):" << t.elapsed(); |
261 return image; |
300 return image; |
262 } |
301 } |
263 |
302 |
264 void HbSplashGenerator::processQueue() |
303 void HbSplashGenerator::processQueue() |
265 { |
304 { |
266 qDebug() << PRE << "processQueue()"; |
305 splDeb() << PRE << "processQueue()"; |
267 // If the queue is empty then the splash regeneraton is complete so store |
306 // If the queue is empty then the splash regeneraton is complete so store |
268 // the current theme and language names as the last fully processed ones in |
307 // the current theme and language names as the last fully processed ones in |
269 // the settings and stop. |
308 // the settings and stop. |
270 if (mQueue.isEmpty()) { |
309 if (mQueue.isEmpty()) { |
271 qDebug() << PRE << "queue is empty regen finished"; |
310 qDebug() << PRE << "queue is empty regen finished"; |
272 mSettings->setValue(last_theme_key, hbInstance->theme()->name()); |
311 mSettings->setValue(last_theme_key, hbInstance->theme()->name()); |
273 mSettings->setValue(last_lang_key, QLocale::system().name()); |
312 mSettings->setValue(last_lang_key, QLocale::system().name()); |
274 QString outDir = hbsplash_output_dir(); |
313 QString outDir = hbsplash_output_dir(); |
275 mSettings->setValue(last_file_count_key, updateOutputDirContents(outDir)); |
314 // Notify the server and get the number of generated files... |
|
315 int fileCount = updateOutputDirContents(outDir); |
|
316 // ...but store zero if some file writing failed at some point |
|
317 // so there will be a regeneration on next boot at least. |
|
318 if (mSaveSplFailed) { |
|
319 qWarning() << PRE << "some files not ok, ignoring file count"; |
|
320 fileCount = 0; |
|
321 // Waiting until next boot is not always the best solution so try |
|
322 // again a bit later. This has to be limited, though, to prevent |
|
323 // continously flooding the system with regenerate requests in case |
|
324 // of an unusable drive. So retry only for a limited number of |
|
325 // times, if all else fails we will try again on next boot. |
|
326 static int retriesLeft = 3; |
|
327 if (retriesLeft-- > 0) { |
|
328 QTimer::singleShot(60000, this, SLOT(scheduleRegen())); // 1 min |
|
329 } |
|
330 } else { |
|
331 splDeb() << PRE << "all files ok"; |
|
332 } |
|
333 mSettings->setValue(last_file_count_key, fileCount); |
276 mSettings->setValue(last_output_dir_key, outDir); |
334 mSettings->setValue(last_output_dir_key, outDir); |
277 emit finished(); |
335 emit finished(); |
278 qDebug() << PRE << "processQueue() over"; |
336 splDeb() << PRE << "processQueue() over"; |
279 return; |
337 return; |
280 } |
338 } |
281 // If a previous splash generation is still in progress or a compositor is |
339 // If a previous splash generation is still in progress or a compositor is |
282 // working then do nothing. |
340 // working then do nothing. |
283 if (!lockMainWindow()) { |
341 if (!lockMainWindow()) { |
284 mProcessQueuePending = true; |
342 mProcessQueuePending = true; |
285 qDebug() << PRE << "still busy processQueue() over"; |
343 splDeb() << PRE << "still busy processQueue() over"; |
286 return; |
344 return; |
287 } |
345 } |
288 try { |
346 try { |
289 mProcessQueuePending = false; |
347 mProcessQueuePending = false; |
290 mItem = mQueue.dequeue(); |
348 mItem = mQueue.dequeue(); |
291 mItemTime.start(); |
349 mItemTime.start(); |
292 log("generating splash screen", mItem.mThemeName, mItem.mOrientation); |
350 log("generating splash screen", mItem.mThemeName, mItem.mOrientation); |
293 |
351 |
294 ensureMainWindow(); |
352 ensureMainWindow(); |
295 mMainWindow->setOrientation(mItem.mOrientation, false); |
353 mMainWindow->setOrientation(mItem.mOrientation, false); |
296 qDebug() << PRE << "mainwindow init time (ms):" << mItemTime.elapsed(); |
354 splDeb() << PRE << "mainwindow init time (ms):" << mItemTime.elapsed(); |
297 |
355 |
298 QTime setupTime; |
356 QTime setupTime; |
299 setupTime.start(); |
357 setupTime.start(); |
300 setupAppSpecificWindow(); |
358 setupAppSpecificWindow(); |
301 finishWindow(); |
359 splDeb() << PRE << "content setup time (ms):" << setupTime.elapsed(); |
302 qDebug() << PRE << "content setup time(ms):" << setupTime.elapsed(); |
360 |
303 |
361 // The async call chain goes like this: |
304 QMetaObject::invokeMethod(this, "processWindow", Qt::QueuedConnection); |
362 // processQueue -> finishWindow -> processWindow -> processQueue -> ... |
|
363 // finishWindow() cannot be called directly from here because that would |
|
364 // result in asserts in QGraphicsScene with certain Qt versions. |
|
365 NEXT_STAGE(this, finishWindow); |
305 |
366 |
306 } catch (const std::bad_alloc &) { |
367 } catch (const std::bad_alloc &) { |
307 cleanup(); |
368 cleanup(); |
308 } |
369 } |
309 qDebug() << PRE << "processQueue() over"; |
370 splDeb() << PRE << "processQueue() over"; |
310 } |
371 } |
311 |
372 |
312 HbMainWindow *HbSplashGenerator::ensureMainWindow() |
373 HbMainWindow *HbSplashGenerator::ensureMainWindow() |
313 { |
374 { |
314 if (!mMainWindow) { |
375 if (!mMainWindow) { |
315 // The FixedVertical flag is used just to disable the sensor-based |
376 // The FixedVertical flag is used just to disable the sensor-based |
316 // orientation switching. |
377 // orientation switching. |
317 mMainWindow = new HbMainWindow(0, Hb::WindowFlagFixedVertical); |
378 mMainWindow = new HbMainWindow(0, Hb::WindowFlagFixedVertical); |
318 // Make sure that at least the 1st phase of the delayed |
379 // Make sure that at least the 1st phase of the delayed |
319 // construction is done right now. |
380 // construction is done right now. |
320 HbMainWindowPrivate::d_ptr(mMainWindow)->_q_delayedConstruction(); |
381 HbMainWindowPrivate *mwd = HbMainWindowPrivate::d_ptr(mMainWindow); |
|
382 mwd->_q_delayedConstruction(); |
|
383 mwd->mStatusBar->startClockTimer(); // may not start otherwise as it gets no visibility events |
321 } |
384 } |
322 return mMainWindow; |
385 return mMainWindow; |
323 } |
386 } |
324 |
387 |
325 void HbSplashGenerator::processWindow() |
388 void HbSplashGenerator::processWindow() |
326 { |
389 { |
327 // Take the screenshot, remove content, and move on to the next request in the queue. |
390 // Take the screenshot, remove content, and move on to the next request in the queue. |
328 log("processWindow() rendering splash screen", mItem.mThemeName, mItem.mOrientation); |
391 if (!newRegenPending()) { |
329 takeScreenshot(); |
392 log("processWindow() rendering splash screen", mItem.mThemeName, mItem.mOrientation); |
330 qDebug() << PRE << "total time for screen (ms):" << mItemTime.elapsed(); |
393 takeScreenshot(); |
|
394 splDeb() << PRE << "total time for screen (ms):" << mItemTime.elapsed(); |
|
395 } |
331 |
396 |
332 QList<HbView *> views = mMainWindow->views(); |
397 QList<HbView *> views = mMainWindow->views(); |
333 foreach(HbView * view, views) { |
398 foreach(HbView * view, views) { |
334 mMainWindow->removeView(view); |
399 mMainWindow->removeView(view); |
335 delete view; |
400 delete view; |
336 } |
401 } |
337 clearTranslators(); |
402 clearTranslators(); |
338 |
403 |
339 unlockMainWindowInternal(); |
404 unlockMainWindowInternal(); |
340 QMetaObject::invokeMethod(this, "processQueue", Qt::QueuedConnection); |
405 NEXT_STAGE(this, processQueue); |
341 log("processWindow() over", mItem.mThemeName, mItem.mOrientation); |
406 log("processWindow() over", mItem.mThemeName, mItem.mOrientation); |
342 } |
407 } |
343 |
408 |
344 void HbSplashGenerator::takeScreenshot() |
409 void HbSplashGenerator::takeScreenshot() |
345 { |
410 { |
354 // change. |
419 // change. |
355 QImage image = renderView(); |
420 QImage image = renderView(); |
356 QTime t; |
421 QTime t; |
357 t.start(); |
422 t.start(); |
358 QString splashFile = splashFileName(); |
423 QString splashFile = splashFileName(); |
359 qDebug() << PRE << "saving to" << splashFile; |
424 splDeb() << PRE << "saving to" << splashFile; |
360 if (saveSpl(splashFile, image, mItem.mFlagsToStore)) { |
425 if (saveSpl(splashFile, image, mItem.mFlagsToStore)) { |
361 #if !defined(Q_OS_SYMBIAN) && defined(QT_DEBUG) |
426 #if !defined(Q_OS_SYMBIAN) && defined(QT_DEBUG) |
362 image.save(splashFile + QLatin1String(".png")); |
427 image.save(splashFile + QLatin1String(".png")); |
363 #endif |
428 #endif |
364 } else { |
429 } else { |
365 qWarning() << PRE << "file write failed for" << splashFile; |
430 qWarning() << PRE << "file write failed for" << splashFile; |
366 } |
431 mSaveSplFailed = true; |
367 qDebug() << PRE << "save time (ms):" << t.elapsed(); |
432 // After setting the fail flag, clear the queue to stop processing |
|
433 // further screens because file writes would probably fail anyway. |
|
434 // Instead, processQueue() will schedule a retry at a later time. |
|
435 mQueue.clear(); |
|
436 } |
|
437 splDeb() << PRE << "save time (ms):" << t.elapsed(); |
368 log("takeScreenshot() over", mItem.mThemeName, mItem.mOrientation); |
438 log("takeScreenshot() over", mItem.mThemeName, mItem.mOrientation); |
369 } catch (const std::bad_alloc &) { |
439 } catch (const std::bad_alloc &) { |
370 cleanup(); |
440 cleanup(); |
371 } |
441 } |
372 } |
442 } |
373 |
443 |
374 QString HbSplashGenerator::splashFileName() |
444 QString HbSplashGenerator::splashFileName() |
375 { |
445 { |
376 QString outDirName = hbsplash_output_dir(); |
446 QString outDirName = hbsplash_output_dir(); |
377 QDir dir(outDirName); |
447 QDir dir(outDirName); |
|
448 #ifdef Q_OS_SYMBIAN |
|
449 // Do not use QDir::mkpath() on Symbian. It is not able to create the |
|
450 // 'private' directory itself in case it does not exist (which is possible |
|
451 // during first boot because splashgen is started relatively early and the |
|
452 // eMMC may be totally empty at that point). RFs::MkDirAll() works better in |
|
453 // this respect. |
|
454 QString nativeOutPath = QDir::toNativeSeparators(outDirName); |
|
455 if (!nativeOutPath.endsWith('\\')) { |
|
456 nativeOutPath.append('\\'); |
|
457 } |
|
458 TPtrC nativeOutPathDes(static_cast<const TUint16 *>(nativeOutPath.utf16()), |
|
459 nativeOutPath.length()); |
|
460 TInt err = CCoeEnv::Static()->FsSession().MkDirAll(nativeOutPathDes); |
|
461 if (err != KErrNone && err != KErrAlreadyExists) { |
|
462 qWarning() << PRE << "MkDirAll failed with" << err << "for" << nativeOutPath; |
|
463 } |
|
464 #else |
378 if (!dir.exists()) { |
465 if (!dir.exists()) { |
379 if (!QDir(".").mkdir(outDirName)) { |
466 if (!QDir(".").mkpath(outDirName)) { |
380 qWarning() << PRE << "mkdir failed for" << outDirName; |
467 qWarning() << PRE << "mkpath failed for" << outDirName; |
381 } |
468 } |
382 } |
469 } |
|
470 #endif |
383 // "splash_<orientation>_<appid>_<screenid>" |
471 // "splash_<orientation>_<appid>_<screenid>" |
384 QString splashFile = dir.filePath("splash_"); |
472 QString splashFile = dir.filePath("splash_"); |
385 splashFile.append(orientationName(mItem.mOrientation)); |
473 splashFile.append(orientationName(mItem.mOrientation)); |
386 if (!mItem.mAppId.isEmpty()) { |
474 if (!mItem.mAppId.isEmpty()) { |
387 splashFile.append('_'); |
475 splashFile.append('_'); |
407 f.write((char *) &w, sizeof(quint32)); |
495 f.write((char *) &w, sizeof(quint32)); |
408 f.write((char *) &h, sizeof(quint32)); |
496 f.write((char *) &h, sizeof(quint32)); |
409 f.write((char *) &bpl, sizeof(quint32)); |
497 f.write((char *) &bpl, sizeof(quint32)); |
410 f.write((char *) &fmt, sizeof(qint32)); |
498 f.write((char *) &fmt, sizeof(qint32)); |
411 f.write((char *) &extra, sizeof(quint32)); |
499 f.write((char *) &extra, sizeof(quint32)); |
412 f.write((const char *) image.bits(), bpl * h); |
500 #ifdef HB_SPLASH_COMPRESSION |
|
501 QTime t; |
|
502 t.start(); |
|
503 QByteArray compData = qCompress((const uchar *) image.bits(), bpl * h); |
|
504 quint32 len = compData.size(); |
|
505 splDeb() << PRE << "compressed" << bpl * h << "to" << len << "in" << t.elapsed() << "ms"; |
|
506 f.write((char *) &len, sizeof(quint32)); |
|
507 qint64 wcount = f.write(compData.constData(), len); |
|
508 #else |
|
509 quint32 len = 0; // 0 compressed length indicates uncompressed data |
|
510 f.write((char *) &len, sizeof(quint32)); |
|
511 len = bpl * h; |
|
512 qint64 wcount = f.write((const char *) image.bits(), len); |
|
513 #endif |
413 f.close(); |
514 f.close(); |
414 return true; |
515 return wcount == len; |
415 } |
516 } |
416 return false; |
517 return false; |
417 } |
518 } |
418 |
519 |
419 void HbSplashGenerator::cleanup() |
520 void HbSplashGenerator::cleanup() |
480 QStringList entries = dir.entryList(QStringList() << "*.splashml", QDir::Files); |
583 QStringList entries = dir.entryList(QStringList() << "*.splashml", QDir::Files); |
481 foreach(const QString & entry, entries) { |
584 foreach(const QString & entry, entries) { |
482 // Skip if a file with the same name has already been processed from |
585 // Skip if a file with the same name has already been processed from |
483 // a different location. |
586 // a different location. |
484 if (processedFileNames.contains(entry)) { |
587 if (processedFileNames.contains(entry)) { |
485 qDebug() << PRE << "skipping splashml (already found at other location)" << dir.filePath(entry); |
588 splDeb() << PRE << "skipping splashml (already found at other location)" << dir.filePath(entry); |
486 continue; |
589 continue; |
487 } |
590 } |
488 processedFileNames.insert(entry); |
591 processedFileNames.insert(entry); |
489 QString fullName = dir.filePath(entry); |
592 QString fullName = dir.filePath(entry); |
490 qDebug() << PRE << "parsing splashml" << fullName; |
593 splDeb() << PRE << "parsing splashml" << fullName; |
491 if (mParsedSplashmls.contains(fullName)) { |
594 if (mParsedSplashmls.contains(fullName)) { |
492 QueueItem item(mParsedSplashmls.value(fullName)); |
595 QueueItem item(mParsedSplashmls.value(fullName)); |
493 item.mThemeName = themeName; |
596 item.mThemeName = themeName; |
494 item.mOrientation = orientation; |
597 item.mOrientation = orientation; |
495 qDebug() << PRE << "splashml already parsed queuing request" << item; |
598 splDeb() << PRE << "splashml already parsed queuing request" << item; |
496 addSplashmlItemToQueue(item); |
599 addSplashmlItemToQueue(item); |
497 continue; |
600 continue; |
498 } |
601 } |
499 QueueItem item(themeName, orientation); |
602 QueueItem item(themeName, orientation); |
500 bool ok = parseSplashml(fullName, item); |
603 bool ok = parseSplashml(fullName, item); |
698 } else if (mItem.mCondSections.contains(lscKey) && mItem.mOrientation == Qt::Horizontal) { |
801 } else if (mItem.mCondSections.contains(lscKey) && mItem.mOrientation == Qt::Horizontal) { |
699 sections << mItem.mCondSections.value(lscKey); |
802 sections << mItem.mCondSections.value(lscKey); |
700 } |
803 } |
701 } |
804 } |
702 sections << mItem.mForcedSections; |
805 sections << mItem.mForcedSections; |
703 qDebug() << PRE << "loading" << mItem.mDocmlFileName << "common section"; |
806 splDeb() << PRE << "loading" << mItem.mDocmlFileName << "common section"; |
704 bool ok; |
807 bool ok; |
705 loader.load(mItem.mDocmlFileName, &ok); |
808 loader.load(mItem.mDocmlFileName, &ok); |
706 if (ok && !sections.isEmpty()) { |
809 if (ok && !sections.isEmpty()) { |
707 foreach(const QString & section, sections) { |
810 foreach(const QString & section, sections) { |
708 qDebug() << PRE << "loading" << mItem.mDocmlFileName << "section" << section; |
811 splDeb() << PRE << "loading" << mItem.mDocmlFileName << "section" << section; |
709 loader.load(mItem.mDocmlFileName, section, &ok); |
812 loader.load(mItem.mDocmlFileName, section, &ok); |
710 } |
813 } |
711 } |
814 } |
712 if (ok) { |
815 if (ok) { |
713 // Apply child widget settings. |
816 // Apply child widget settings. |
714 setupNameBasedWidgetProps(loader); |
817 setupNameBasedWidgetProps(loader); |
715 // Find the root view and add it to the mainwindow. |
818 // Find the root view and add it to the mainwindow. |
716 QGraphicsWidget *widget = loader.findWidget(mItem.mDocmlWidgetName); |
819 QGraphicsWidget *widget = loader.findWidget(mItem.mDocmlWidgetName); |
717 if (widget) { |
820 if (widget) { |
718 qDebug() << PRE << "widget created from" << mItem; |
821 splDeb() << PRE << "widget created from" << mItem; |
719 mMainWindow->addView(widget); |
822 mMainWindow->addView(widget); |
720 } else { |
823 } else { |
721 qWarning() << PRE << "widget creation failed from" << mItem; |
824 qWarning() << PRE << "widget creation failed from" << mItem; |
722 } |
825 } |
723 } else { |
826 } else { |