source: trunk/demos/qtdemo/menumanager.cpp@ 1147

Last change on this file since 1147 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 41.8 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the demonstration applications of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "menumanager.h"
43#include "colors.h"
44#include "menucontent.h"
45#include "examplecontent.h"
46
47MenuManager *MenuManager::pInstance = 0;
48
49MenuManager * MenuManager::instance()
50{
51 if (!MenuManager::pInstance)
52 MenuManager::pInstance = new MenuManager();
53 return MenuManager::pInstance;
54}
55
56MenuManager::MenuManager()
57{
58 this->ticker = 0;
59 this->tickerInAnim = 0;
60 this->upButton = 0;
61 this->downButton = 0;
62 this->helpEngine = 0;
63 this->score = new Score();
64 this->currentMenu = QLatin1String("[no menu visible]");
65 this->currentCategory = QLatin1String("[no category visible]");
66 this->currentMenuButtons = QLatin1String("[no menu buttons visible]");
67 this->currentInfo = QLatin1String("[no info visible]");
68 this->currentMenuCode = -1;
69 this->readXmlDocument();
70 this->initHelpEngine();
71}
72
73MenuManager::~MenuManager()
74{
75 delete this->score;
76 delete this->contentsDoc;
77 delete this->helpEngine;
78}
79
80QByteArray MenuManager::getResource(const QString &name)
81{
82 QByteArray ba = this->helpEngine->fileData(name);
83 if (Colors::verbose && ba.isEmpty())
84 qDebug() << " - WARNING: Could not get " << name;
85 return ba;
86}
87
88void MenuManager::readXmlDocument()
89{
90 this->contentsDoc = new QDomDocument();
91 QString errorStr;
92 int errorLine;
93 int errorColumn;
94
95 QFile file(":/xml/examples.xml");
96 bool statusOK = this->contentsDoc->setContent(&file, true, &errorStr, &errorLine, &errorColumn);
97 if (!statusOK){
98 QMessageBox::critical(0,
99 QObject::tr("DOM Parser"),
100 QObject::tr("Could not read or find the contents document. Error at line %1, column %2:\n%3")
101 .arg(errorLine).arg(errorColumn).arg(errorStr)
102 );
103 exit(-1);
104 }
105}
106
107void MenuManager::initHelpEngine()
108{
109 this->helpRootUrl = QString("qthelp://com.trolltech.qt.%1%2%3/qdoc/")
110 .arg(QT_VERSION >> 16).arg((QT_VERSION >> 8) & 0xFF)
111 .arg(QT_VERSION & 0xFF);
112
113 // Store help collection file in cache dir of assistant
114 QString cacheDir = QDesktopServices::storageLocation(QDesktopServices::DataLocation)
115 + QLatin1String("/Trolltech/Assistant/");
116 QString helpDataFile = QString(QLatin1String("qtdemo_%1.qhc")).arg(QLatin1String(QT_VERSION_STR));
117
118 QDir dir;
119 if (!dir.exists(cacheDir))
120 dir.mkpath(cacheDir);
121
122 // Create help engine (and new
123 // helpDataFile if it does not exist):
124 this->helpEngine = new QHelpEngineCore(cacheDir + helpDataFile);
125 this->helpEngine->setupData();
126
127 QString qtDocRoot = QLibraryInfo::location(QLibraryInfo::DocumentationPath) + QLatin1String("/qch");
128 qtDocRoot = QDir(qtDocRoot).absolutePath();
129
130 QStringList qchFiles;
131 qchFiles << QLatin1String("/qt.qch")
132 << QLatin1String("/designer.qch")
133 << QLatin1String("/linguist.qch");
134
135 QString oldDir = helpEngine->customValue(QLatin1String("docDir"), QString()).toString();
136 if (oldDir != qtDocRoot) {
137 foreach (const QString &qchFile, qchFiles)
138 helpEngine->unregisterDocumentation(QHelpEngineCore::namespaceName(qtDocRoot + qchFile));
139 }
140
141 // If the data that the engine will work
142 // on is not yet registered, do it now:
143 foreach (const QString &qchFile, qchFiles)
144 helpEngine->registerDocumentation(qtDocRoot + qchFile);
145
146 helpEngine->setCustomValue(QLatin1String("docDir"), qtDocRoot);
147}
148
149void MenuManager::itemSelected(int userCode, const QString &menuName)
150{
151 switch (userCode){
152 case LAUNCH:
153 this->launchExample(this->currentInfo);
154 break;
155 case LAUNCH_QML:
156 this->launchQmlExample(this->currentInfo);
157 break;
158 case DOCUMENTATION:
159 this->showDocInAssistant(this->currentInfo);
160 break;
161 case QUIT:
162 this->window->loop = false;
163 QCoreApplication::quit();
164 break;
165 case FULLSCREEN:
166 this->window->toggleFullscreen();
167 break;
168 case ROOT:
169 // out:
170 this->score->queueMovie(this->currentMenu + " -out", Score::FROM_START, Score::LOCK_ITEMS);
171 this->score->queueMovie(this->currentMenuButtons + " -out", Score::FROM_START, Score::LOCK_ITEMS);
172 this->score->queueMovie(this->currentInfo + " -out");
173 this->score->queueMovie(this->currentInfo + " -buttons -out", Score::NEW_ANIMATION_ONLY);
174 this->score->queueMovie("back -out", Score::ONLY_IF_VISIBLE);
175 if(qmlRoot)
176 qmlRoot->setProperty("show", QVariant(false));
177 // book-keeping:
178 this->currentMenuCode = ROOT;
179 this->currentMenu = menuName + " -menu1";
180 this->currentMenuButtons = menuName + " -buttons";
181 this->currentInfo = menuName + " -info";
182 // in:
183 this->score->queueMovie("upndown -shake");
184 this->score->queueMovie(this->currentMenu, Score::FROM_START, Score::UNLOCK_ITEMS);
185 this->score->queueMovie(this->currentMenuButtons, Score::FROM_START, Score::UNLOCK_ITEMS);
186 this->score->queueMovie(this->currentInfo);
187 if (!Colors::noTicker){
188 this->ticker->doIntroTransitions = true;
189 this->tickerInAnim->startDelay = 2000;
190 this->ticker->useGuideQt();
191 this->score->queueMovie("ticker", Score::NEW_ANIMATION_ONLY);
192 }
193 break;
194 case MENU1:
195 // out:
196 this->score->queueMovie(this->currentMenu + " -out", Score::FROM_START, Score::LOCK_ITEMS);
197 this->score->queueMovie(this->currentMenuButtons + " -out", Score::FROM_START, Score::LOCK_ITEMS);
198 this->score->queueMovie(this->currentInfo + " -out");
199 if(qmlRoot)
200 qmlRoot->setProperty("show", QVariant(false));
201 // book-keeping:
202 this->currentMenuCode = MENU1;
203 this->currentCategory = menuName;
204 this->currentMenu = menuName + " -menu1";
205 this->currentInfo = menuName + " -info";
206 // in:
207 this->score->queueMovie("upndown -shake");
208 this->score->queueMovie("back -in");
209 this->score->queueMovie(this->currentMenu, Score::FROM_START, Score::UNLOCK_ITEMS);
210 this->score->queueMovie(this->currentInfo);
211 if (!Colors::noTicker)
212 this->ticker->useGuideTt();
213 break;
214 case MENU2:
215 // out:
216 this->score->queueMovie(this->currentInfo + " -out", Score::NEW_ANIMATION_ONLY);
217 this->score->queueMovie(this->currentInfo + " -buttons -out", Score::NEW_ANIMATION_ONLY);
218 if(qmlRoot)
219 qmlRoot->setProperty("show", QVariant(false));
220 // book-keeping:
221 this->currentMenuCode = MENU2;
222 this->currentInfo = menuName;
223 // in / shake:
224 this->score->queueMovie("upndown -shake");
225 this->score->queueMovie("back -shake");
226 this->score->queueMovie(this->currentMenu + " -shake");
227 this->score->queueMovie(this->currentInfo, Score::NEW_ANIMATION_ONLY);
228 this->score->queueMovie(this->currentInfo + " -buttons", Score::NEW_ANIMATION_ONLY);
229 if (!Colors::noTicker){
230 this->score->queueMovie("ticker -out", Score::NEW_ANIMATION_ONLY);
231 }
232 break;
233 case UP:{
234 QString backMenu = this->info[this->currentMenu]["back"];
235 if (!backMenu.isNull()){
236 this->score->queueMovie(this->currentMenu + " -top_out", Score::FROM_START, Score::LOCK_ITEMS);
237 this->score->queueMovie(backMenu + " -bottom_in", Score::FROM_START, Score::UNLOCK_ITEMS);
238 this->currentMenu = backMenu;
239 }
240 break; }
241 case DOWN:{
242 QString moreMenu = this->info[this->currentMenu]["more"];
243 if (!moreMenu.isNull()){
244 this->score->queueMovie(this->currentMenu + " -bottom_out", Score::FROM_START, Score::LOCK_ITEMS);
245 this->score->queueMovie(moreMenu + " -top_in", Score::FROM_START, Score::UNLOCK_ITEMS);
246 this->currentMenu = moreMenu;
247 }
248 break; }
249 case BACK:{
250 if (this->currentMenuCode == MENU2){
251 // out:
252 this->score->queueMovie(this->currentInfo + " -out", Score::NEW_ANIMATION_ONLY);
253 this->score->queueMovie(this->currentInfo + " -buttons -out", Score::NEW_ANIMATION_ONLY);
254 if(qmlRoot)
255 qmlRoot->setProperty("show", QVariant(false));
256 // book-keeping:
257 this->currentMenuCode = MENU1;
258 this->currentMenuButtons = this->currentCategory + " -buttons";
259 this->currentInfo = this->currentCategory + " -info";
260 // in / shake:
261 this->score->queueMovie("upndown -shake");
262 this->score->queueMovie(this->currentMenu + " -shake");
263 this->score->queueMovie(this->currentInfo, Score::NEW_ANIMATION_ONLY);
264 this->score->queueMovie(this->currentInfo + " -buttons", Score::NEW_ANIMATION_ONLY);
265 if (!Colors::noTicker){
266 this->ticker->doIntroTransitions = false;
267 this->tickerInAnim->startDelay = 500;
268 this->score->queueMovie("ticker", Score::NEW_ANIMATION_ONLY);
269 }
270 } else if (this->currentMenuCode != ROOT)
271 itemSelected(ROOT, Colors::rootMenuName);
272 break; }
273 }
274
275 // update back- and more buttons
276 bool noBackMenu = this->info[this->currentMenu]["back"].isNull();
277 bool noMoreMenu = this->info[this->currentMenu]["more"].isNull();
278 this->upButton->setState(noBackMenu ? TextButton::DISABLED : TextButton::OFF);
279 this->downButton->setState(noMoreMenu ? TextButton::DISABLED : TextButton::OFF);
280
281 if (this->score->hasQueuedMovies()){
282 this->score->playQue();
283 // Playing new movies might include
284 // loading etc. So ignore the FPS
285 // at this point
286 this->window->fpsHistory.clear();
287 }
288}
289
290void MenuManager::showDocInAssistant(const QString &name)
291{
292 QString url = this->resolveDocUrl(name);
293 if (Colors::verbose)
294 qDebug() << "Sending URL to Assistant:" << url;
295
296 // Start assistant if it's not already running:
297 if (this->assistantProcess.state() != QProcess::Running){
298 QString app = QLibraryInfo::location(QLibraryInfo::BinariesPath) + QDir::separator();
299#if !defined(Q_OS_MAC)
300 app += QLatin1String("assistant");
301#else
302 app += QLatin1String("Assistant.app/Contents/MacOS/Assistant");
303#endif
304 QStringList args;
305 args << QLatin1String("-enableRemoteControl");
306 this->assistantProcess.start(app, args);
307 if (!this->assistantProcess.waitForStarted()) {
308 QMessageBox::critical(0, tr("Qt Demo"), tr("Could not start Qt Assistant.").arg(app));
309 return;
310 }
311 }
312
313 // Send command through remote control even if the process
314 // was started to activate assistant and bring it to front:
315 QTextStream str(&this->assistantProcess);
316 str << "SetSource " << url << QLatin1Char('\n') << endl;
317}
318
319void MenuManager::launchExample(const QString &name)
320{
321 QString executable = this->resolveExeFile(name);
322#ifdef Q_OS_MAC
323 if (Colors::verbose)
324 qDebug() << "Launching:" << executable;
325 bool success = QDesktopServices::openUrl(QUrl::fromLocalFile(executable));
326 if (!success){
327 QMessageBox::critical(0, tr("Failed to launch the example"),
328 tr("Could not launch the example. Ensure that it has been built."),
329 QMessageBox::Cancel);
330 }
331#else // Not mac. To not break anything regarding dll's etc, keep it the way it was before:
332 QProcess *process = new QProcess(this);
333 connect(process, SIGNAL(finished(int)), this, SLOT(exampleFinished()));
334 connect(process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(exampleError(QProcess::ProcessError)));
335
336#ifdef Q_OS_WIN
337 //make sure it finds the dlls on windows
338 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
339 env.insert(QLatin1String("PATH"), QLibraryInfo::location(QLibraryInfo::BinariesPath)
340 + QLatin1Char(';') + env.value(QLatin1String("Path")));
341 process->setProcessEnvironment(env);
342#endif
343
344 if (info[name]["changedirectory"] != "false"){
345 QString workingDirectory = resolveDataDir(name);
346 process->setWorkingDirectory(workingDirectory);
347 if (Colors::verbose)
348 qDebug() << "Setting working directory:" << workingDirectory;
349 }
350
351 if (Colors::verbose)
352 qDebug() << "Launching:" << executable;
353 process->start(executable);
354#endif
355}
356
357void MenuManager::launchQmlExample(const QString &name)
358{
359#ifndef QT_NO_DECLARATIVE
360 if(!qmlRoot){
361 exampleError(QProcess::UnknownError);
362 return;
363 }
364 //resolveQmlFilename - refactor to separate fn?
365 QString dirName = this->info[name]["dirname"];
366 QString category = this->info[name]["category"];
367 QString fileName = this->info[name]["filename"];
368 QDir dir;
369 if (category == "demos")
370 dir = QDir(QLibraryInfo::location(QLibraryInfo::DemosPath));
371 else
372 dir = QDir(QLibraryInfo::location(QLibraryInfo::ExamplesPath));
373 QFile file(dir.path() + "/" + dirName + "/" + fileName + "/" + "main.qml");
374 if(!file.exists()){
375 //try dirname.qml as well
376 file.setFileName(dir.path() + "/" + dirName + "/" + fileName + "/" + fileName.split('/').last() + ".qml");
377 if(!file.exists()){
378 exampleError(QProcess::UnknownError);
379 return;
380 }
381 }
382
383 qmlRoot->setProperty("qmlFile", QVariant(""));//unload component
384 qmlRoot->setProperty("show", QVariant(true));
385 qmlRoot->setProperty("qmlFile", QUrl::fromLocalFile(file.fileName()));
386#else
387 exampleError(QProcess::UnknownError);
388#endif
389}
390
391void MenuManager::quitQML()
392{
393 if(qmlRoot)
394 qmlRoot->setProperty("show", QVariant(false));
395}
396
397void MenuManager::exampleFinished()
398{
399}
400
401void MenuManager::exampleError(QProcess::ProcessError error)
402{
403 if (error != QProcess::Crashed)
404 QMessageBox::critical(0, tr("Failed to launch the example"),
405 tr("Could not launch the example. Ensure that it has been built."),
406 QMessageBox::Cancel);
407}
408
409void MenuManager::init(MainWindow *window)
410{
411 this->window = window;
412
413 // Create div:
414 this->createTicker();
415 this->createUpnDownButtons();
416 this->createBackButton();
417
418 // Create first level menu:
419 QDomElement rootElement = this->contentsDoc->documentElement();
420 this->createRootMenu(rootElement);
421
422 // Create second level menus:
423 QDomNode level2MenuNode = rootElement.firstChild();
424 while (!level2MenuNode.isNull()){
425 QDomElement level2MenuElement = level2MenuNode.toElement();
426 this->createSubMenu(level2MenuElement);
427
428 // create leaf menu and example info:
429 QDomNode exampleNode = level2MenuElement.firstChild();
430 while (!exampleNode.isNull()){
431 QDomElement exampleElement = exampleNode.toElement();
432 this->readInfoAboutExample(exampleElement);
433 this->createLeafMenu(exampleElement);
434 exampleNode = exampleNode.nextSibling();
435 }
436
437 level2MenuNode = level2MenuNode.nextSibling();
438 }
439
440 qmlRoot = 0;
441#ifndef QT_NO_DECLARATIVE
442 // Create QML Loader
443 declarativeEngine = new QDeclarativeEngine(this);
444 connect(declarativeEngine, SIGNAL(quit()),
445 this, SLOT(quitQML()));
446
447 QDeclarativeComponent component(declarativeEngine, QUrl("qrc:qml/qmlShell.qml"), this);
448 QDeclarativeItem* qmlRootItem = 0;
449 if(component.isReady()){
450 qmlRoot = component.create();
451 qmlRootItem = qobject_cast<QDeclarativeItem*>(qmlRoot);
452 }else{
453 qDebug() << component.status() << component.errorString();
454 }
455
456 if(qmlRootItem){
457 qmlRootItem->setHeight(this->window->scene->sceneRect().height());
458 qmlRootItem->setWidth(this->window->scene->sceneRect().width());
459 qmlRootItem->setZValue(101);//Above other items
460 qmlRootItem->setCursor(Qt::ArrowCursor);
461 window->scene->addItem(qmlRootItem);
462
463 //Note that QML adds key handling to the app.
464 window->viewport()->setFocusPolicy(Qt::NoFocus);//Correct keyboard focus handling
465 window->setFocusPolicy(Qt::StrongFocus);
466 window->scene->setStickyFocus(true);
467 window->setFocus();
468 }else{
469 qDebug() << "Error initializing QML subsystem, Declarative examples will not work";
470 }
471#endif
472}
473
474void MenuManager::readInfoAboutExample(const QDomElement &example)
475{
476 QString name = example.attribute("name");
477 if (this->info.contains(name))
478 qWarning() << "__WARNING: MenuManager::readInfoAboutExample: Demo/example with name"
479 << name << "appears twice in the xml-file!__";
480
481 this->info[name]["filename"] = example.attribute("filename");
482 this->info[name]["category"] = example.parentNode().toElement().tagName();
483 this->info[name]["dirname"] = example.parentNode().toElement().attribute("dirname");
484 this->info[name]["changedirectory"] = example.attribute("changedirectory");
485 this->info[name]["image"] = example.attribute("image");
486 this->info[name]["qml"] = example.attribute("qml");
487}
488
489QString MenuManager::resolveDataDir(const QString &name)
490{
491 QString dirName = this->info[name]["dirname"];
492 QString category = this->info[name]["category"];
493 QString fileName = this->info[name]["filename"];
494
495 QDir dir;
496 if (category == "demos")
497 dir = QDir(QLibraryInfo::location(QLibraryInfo::DemosPath));
498 else
499 dir = QDir(QLibraryInfo::location(QLibraryInfo::ExamplesPath));
500
501 dir.cd(dirName);
502 dir.cd(fileName);
503 return dir.absolutePath();
504}
505
506QString MenuManager::resolveExeFile(const QString &name)
507{
508 QString dirName = this->info[name]["dirname"];
509 QString category = this->info[name]["category"];
510 QString fileName = this->info[name]["filename"];
511
512 QDir dir;
513 if (category == "demos")
514 dir = QDir(QLibraryInfo::location(QLibraryInfo::DemosPath));
515 else
516 dir = QDir(QLibraryInfo::location(QLibraryInfo::ExamplesPath));
517
518 dir.cd(dirName);
519 dir.cd(fileName);
520
521 fileName = fileName.split("/").last();
522 QFile unixFile(dir.path() + "/" + fileName);
523 if (unixFile.exists()) return unixFile.fileName();
524 QFile os2File(dir.path() + "\\" + fileName + ".exe");
525 if (os2File.exists()) return os2File.fileName();
526 QFile winR(dir.path() + "\\release\\" + fileName + ".exe");
527 if (winR.exists()) return winR.fileName();
528 QFile winD(dir.path() + "\\debug\\" + fileName + ".exe");
529 if (winD.exists()) return winD.fileName();
530 QFile mac(dir.path() + "/" + fileName + ".app");
531 if (mac.exists()) return mac.fileName();
532
533 if (Colors::verbose)
534 qDebug() << "- WARNING: Could not resolve executable:" << dir.path() << fileName;
535 return "__executable not found__";
536}
537
538QString MenuManager::resolveDocUrl(const QString &name)
539{
540 QString dirName = this->info[name]["dirname"];
541 QString category = this->info[name]["category"];
542 QString fileName = this->info[name]["filename"];
543
544 if (category == "demos")
545 return this->helpRootUrl + "demos-" + fileName.replace("/", "-") + ".html";
546 else
547 return this->helpRootUrl + dirName.replace("/", "-") + "-" + fileName + ".html";
548}
549
550QString MenuManager::resolveImageUrl(const QString &name)
551{
552 return this->helpRootUrl + "images/" + name;
553}
554
555QByteArray MenuManager::getHtml(const QString &name)
556{
557 return getResource(this->resolveDocUrl(name));
558}
559
560QByteArray MenuManager::getImage(const QString &name)
561{
562 QString imageName = this->info[name]["image"];
563 QString category = this->info[name]["category"];
564 QString fileName = this->info[name]["filename"];
565 bool qml = (this->info[name]["qml"] == QLatin1String("true"));
566 if(qml)
567 fileName = QLatin1String("qml-") + fileName.split('/').last();
568
569 if (imageName.isEmpty()){
570 if (category == "demos")
571 imageName = fileName + "-demo.png";
572 else
573 imageName = fileName + "-example.png";
574 if ((getResource(resolveImageUrl(imageName))).isEmpty())
575 imageName = fileName + ".png";
576 if ((getResource(resolveImageUrl(imageName))).isEmpty())
577 imageName = fileName + "example.png";
578 }
579 return getResource(resolveImageUrl(imageName));
580}
581
582
583void MenuManager::createRootMenu(const QDomElement &el)
584{
585 QString name = el.attribute("name");
586 createMenu(el, MENU1);
587 createInfo(new MenuContentItem(el, this->window->scene, this->window->mainSceneRoot), name + " -info");
588
589 Movie *menuButtonsIn = this->score->insertMovie(name + " -buttons");
590 Movie *menuButtonsOut = this->score->insertMovie(name + " -buttons -out");
591 createLowLeftButton(QLatin1String("Quit"), QUIT, menuButtonsIn, menuButtonsOut, 0);
592 createLowRightButton("Toggle fullscreen", FULLSCREEN, menuButtonsIn, menuButtonsOut, 0);
593}
594
595void MenuManager::createSubMenu(const QDomElement &el)
596{
597 QString name = el.attribute("name");
598 createMenu(el, MENU2);
599 createInfo(new MenuContentItem(el, this->window->scene, this->window->mainSceneRoot), name + " -info");
600}
601
602void MenuManager::createLeafMenu(const QDomElement &el)
603{
604 QString name = el.attribute("name");
605 createInfo(new ExampleContent(name, this->window->scene, this->window->mainSceneRoot), name);
606
607 Movie *infoButtonsIn = this->score->insertMovie(name + " -buttons");
608 Movie *infoButtonsOut = this->score->insertMovie(name + " -buttons -out");
609 createLowRightLeafButton("Documentation", 600, DOCUMENTATION, infoButtonsIn, infoButtonsOut, 0);
610 if (el.attribute("executable") != "false")
611 createLowRightLeafButton("Launch", 405, LAUNCH, infoButtonsIn, infoButtonsOut, 0);
612 else if(el.attribute("qml") == "true")
613 createLowRightLeafButton("Display", 405, LAUNCH_QML, infoButtonsIn, infoButtonsOut, 0);
614}
615
616void MenuManager::createMenu(const QDomElement &category, BUTTON_TYPE type)
617{
618 qreal sw = this->window->scene->sceneRect().width();
619 int xOffset = 15;
620 int yOffset = 10;
621 int maxExamples = Colors::menuCount;
622 int menuIndex = 1;
623 QString name = category.attribute("name");
624 QDomNode currentNode = category.firstChild();
625 QString currentMenu = name + QLatin1String(" -menu") + QString::number(menuIndex);
626
627 while (!currentNode.isNull()){
628 Movie *movieIn = this->score->insertMovie(currentMenu);
629 Movie *movieOut = this->score->insertMovie(currentMenu + " -out");
630 Movie *movieNextTopOut = this->score->insertMovie(currentMenu + " -top_out");
631 Movie *movieNextBottomOut = this->score->insertMovie(currentMenu + " -bottom_out");
632 Movie *movieNextTopIn = this->score->insertMovie(currentMenu + " -top_in");
633 Movie *movieNextBottomIn = this->score->insertMovie(currentMenu + " -bottom_in");
634 Movie *movieShake = this->score->insertMovie(currentMenu + " -shake");
635
636 int i = 0;
637 while (!currentNode.isNull() && i < maxExamples){
638 TextButton *item;
639
640 // create normal menu button
641 QString label = currentNode.toElement().attribute("name");
642 item = new TextButton(label, TextButton::LEFT, type, this->window->scene, this->window->mainSceneRoot);
643 currentNode = currentNode.nextSibling();
644
645#ifndef QT_OPENGL_SUPPORT
646 if (currentNode.toElement().attribute("dirname") == "opengl")
647 currentNode = currentNode.nextSibling();
648#endif
649
650 item->setRecursiveVisible(false);
651 item->setZValue(10);
652 qreal ih = item->sceneBoundingRect().height();
653 qreal iw = item->sceneBoundingRect().width();
654 qreal ihp = ih + 3;
655
656 // create in-animation:
657 DemoItemAnimation *anim = new DemoItemAnimation(item, DemoItemAnimation::ANIM_IN);
658 anim->setDuration(float(1000 + (i * 20)) * Colors::animSpeedButtons);
659 anim->setStartPos(QPointF(xOffset, -ih));
660 anim->setPosAt(0.20, QPointF(xOffset, -ih));
661 anim->setPosAt(0.50, QPointF(xOffset, (i * ihp) + yOffset + Colors::contentStartY + (10 * float(i / 4.0f))));
662 anim->setPosAt(0.60, QPointF(xOffset, (i * ihp) + yOffset + Colors::contentStartY));
663 anim->setPosAt(0.70, QPointF(xOffset, (i * ihp) + yOffset + Colors::contentStartY + (5 * float(i / 4.0f))));
664 anim->setPosAt(0.80, QPointF(xOffset, (i * ihp) + yOffset + Colors::contentStartY));
665 anim->setPosAt(0.90, QPointF(xOffset, (i * ihp) + yOffset + Colors::contentStartY + (2 * float(i / 4.0f))));
666 anim->setPosAt(1.00, QPointF(xOffset, (i * ihp) + yOffset + Colors::contentStartY));
667 movieIn->append(anim);
668
669 // create out-animation:
670 anim = new DemoItemAnimation(item, DemoItemAnimation::ANIM_OUT);
671 anim->hideOnFinished = true;
672 anim->setDuration((700 + (30 * i)) * Colors::animSpeedButtons);
673 anim->setStartPos(QPointF(xOffset, (i * ihp) + yOffset + Colors::contentStartY));
674 anim->setPosAt(0.60, QPointF(xOffset, 600 - ih - ih));
675 anim->setPosAt(0.65, QPointF(xOffset + 20, 600 - ih));
676 anim->setPosAt(1.00, QPointF(sw + iw, 600 - ih));
677 movieOut->append(anim);
678
679 // create shake-animation:
680 anim = new DemoItemAnimation(item);
681 anim->setDuration(700 * Colors::animSpeedButtons);
682 anim->setStartPos(QPointF(xOffset, (i * ihp) + yOffset + Colors::contentStartY));
683 anim->setPosAt(0.55, QPointF(xOffset, (i * ihp) + yOffset + Colors::contentStartY - i*2.0));
684 anim->setPosAt(0.70, QPointF(xOffset - 10, (i * ihp) + yOffset + Colors::contentStartY - i*1.5));
685 anim->setPosAt(0.80, QPointF(xOffset, (i * ihp) + yOffset + Colors::contentStartY - i*1.0));
686 anim->setPosAt(0.90, QPointF(xOffset - 2, (i * ihp) + yOffset + Colors::contentStartY - i*0.5));
687 anim->setPosAt(1.00, QPointF(xOffset, (i * ihp) + yOffset + Colors::contentStartY));
688 movieShake->append(anim);
689
690 // create next-menu top-out-animation:
691 anim = new DemoItemAnimation(item, DemoItemAnimation::ANIM_OUT);
692 anim->hideOnFinished = true;
693 anim->setDuration((200 + (30 * i)) * Colors::animSpeedButtons);
694 anim->setStartPos(QPointF(xOffset, (i * ihp) + yOffset + Colors::contentStartY));
695 anim->setPosAt(0.70, QPointF(xOffset, yOffset + Colors::contentStartY));
696 anim->setPosAt(1.00, QPointF(-iw, yOffset + Colors::contentStartY));
697 movieNextTopOut->append(anim);
698
699 // create next-menu bottom-out-animation:
700 anim = new DemoItemAnimation(item, DemoItemAnimation::ANIM_OUT);
701 anim->hideOnFinished = true;
702 anim->setDuration((200 + (30 * i)) * Colors::animSpeedButtons);
703 anim->setStartPos(QPointF(xOffset, (i * ihp) + yOffset + Colors::contentStartY));
704 anim->setPosAt(0.70, QPointF(xOffset, (maxExamples * ihp) + yOffset + Colors::contentStartY));
705 anim->setPosAt(1.00, QPointF(-iw, (maxExamples * ihp) + yOffset + Colors::contentStartY));
706 movieNextBottomOut->append(anim);
707
708 // create next-menu top-in-animation:
709 anim = new DemoItemAnimation(item, DemoItemAnimation::ANIM_IN);
710 anim->setDuration((700 - (30 * i)) * Colors::animSpeedButtons);
711 anim->setStartPos(QPointF(-iw, yOffset + Colors::contentStartY));
712 anim->setPosAt(0.30, QPointF(xOffset, yOffset + Colors::contentStartY));
713 anim->setPosAt(1.00, QPointF(xOffset, (i * ihp) + yOffset + Colors::contentStartY));
714 movieNextTopIn->append(anim);
715
716 // create next-menu bottom-in-animation:
717 int reverse = maxExamples - i;
718 anim = new DemoItemAnimation(item, DemoItemAnimation::ANIM_IN);
719 anim->setDuration((1000 - (30 * reverse)) * Colors::animSpeedButtons);
720 anim->setStartPos(QPointF(-iw, (maxExamples * ihp) + yOffset + Colors::contentStartY));
721 anim->setPosAt(0.30, QPointF(xOffset, (maxExamples * ihp) + yOffset + Colors::contentStartY));
722 anim->setPosAt(1.00, QPointF(xOffset, (i * ihp) + yOffset + Colors::contentStartY));
723 movieNextBottomIn->append(anim);
724
725 i++;
726 }
727
728 if (!currentNode.isNull() && i == maxExamples){
729 // We need another menu, so register for 'more' and 'back' buttons
730 ++menuIndex;
731 this->info[currentMenu]["more"] = name + QLatin1String(" -menu") + QString::number(menuIndex);
732 currentMenu = name + QLatin1String(" -menu") + QString::number(menuIndex);
733 this->info[currentMenu]["back"] = name + QLatin1String(" -menu") + QString::number(menuIndex - 1);
734 }
735 }
736}
737
738
739void MenuManager::createLowLeftButton(const QString &label, BUTTON_TYPE type,
740 Movie *movieIn, Movie *movieOut, Movie *movieShake, const QString &menuString)
741{
742 TextButton *button = new TextButton(label, TextButton::RIGHT, type, this->window->scene, this->window->mainSceneRoot, TextButton::PANEL);
743 if (!menuString.isNull())
744 button->setMenuString(menuString);
745 button->setRecursiveVisible(false);
746 button->setZValue(10);
747
748 qreal iw = button->sceneBoundingRect().width();
749 int xOffset = 15;
750
751 // create in-animation:
752 DemoItemAnimation *buttonIn = new DemoItemAnimation(button, DemoItemAnimation::ANIM_IN);
753 buttonIn->setDuration(1800 * Colors::animSpeedButtons);
754 buttonIn->setStartPos(QPointF(-iw, Colors::contentStartY + Colors::contentHeight - 35));
755 buttonIn->setPosAt(0.5, QPointF(-iw, Colors::contentStartY + Colors::contentHeight - 35));
756 buttonIn->setPosAt(0.7, QPointF(xOffset, Colors::contentStartY + Colors::contentHeight - 35));
757 buttonIn->setPosAt(1.0, QPointF(xOffset, Colors::contentStartY + Colors::contentHeight - 26));
758 movieIn->append(buttonIn);
759
760 // create out-animation:
761 DemoItemAnimation *buttonOut = new DemoItemAnimation(button, DemoItemAnimation::ANIM_OUT);
762 buttonOut->hideOnFinished = true;
763 buttonOut->setDuration(400 * Colors::animSpeedButtons);
764 buttonOut->setStartPos(QPointF(xOffset, Colors::contentStartY + Colors::contentHeight - 26));
765 buttonOut->setPosAt(1.0, QPointF(-iw, Colors::contentStartY + Colors::contentHeight - 26));
766 movieOut->append(buttonOut);
767
768 if (movieShake){
769 DemoItemAnimation *shakeAnim = new DemoItemAnimation(button, DemoItemAnimation::ANIM_UNSPECIFIED);
770 shakeAnim->timeline->setCurveShape(QTimeLine::LinearCurve);
771 shakeAnim->setDuration(650);
772 shakeAnim->setStartPos(buttonIn->posAt(1.0f));
773 shakeAnim->setPosAt(0.60, buttonIn->posAt(1.0f));
774 shakeAnim->setPosAt(0.70, buttonIn->posAt(1.0f) + QPointF(-3, 0));
775 shakeAnim->setPosAt(0.80, buttonIn->posAt(1.0f) + QPointF(2, 0));
776 shakeAnim->setPosAt(0.90, buttonIn->posAt(1.0f) + QPointF(-1, 0));
777 shakeAnim->setPosAt(1.00, buttonIn->posAt(1.0f));
778 movieShake->append(shakeAnim);
779 }
780}
781
782void MenuManager::createLowRightButton(const QString &label, BUTTON_TYPE type, Movie *movieIn, Movie *movieOut, Movie * /*movieShake*/)
783{
784 TextButton *item = new TextButton(label, TextButton::RIGHT, type, this->window->scene, this->window->mainSceneRoot, TextButton::PANEL);
785 item->setRecursiveVisible(false);
786 item->setZValue(10);
787
788 qreal sw = this->window->scene->sceneRect().width();
789 int xOffset = 70;
790
791 // create in-animation:
792 DemoItemAnimation *anim = new DemoItemAnimation(item, DemoItemAnimation::ANIM_IN);
793 anim->setDuration(1800 * Colors::animSpeedButtons);
794 anim->setStartPos(QPointF(sw, Colors::contentStartY + Colors::contentHeight - 35));
795 anim->setPosAt(0.5, QPointF(sw, Colors::contentStartY + Colors::contentHeight - 35));
796 anim->setPosAt(0.7, QPointF(xOffset + 535, Colors::contentStartY + Colors::contentHeight - 35));
797 anim->setPosAt(1.0, QPointF(xOffset + 535, Colors::contentStartY + Colors::contentHeight - 26));
798 movieIn->append(anim);
799
800 // create out-animation:
801 anim = new DemoItemAnimation(item, DemoItemAnimation::ANIM_OUT);
802 anim->hideOnFinished = true;
803 anim->setDuration(400 * Colors::animSpeedButtons);
804 anim->setStartPos(QPointF(xOffset + 535, Colors::contentStartY + Colors::contentHeight - 26));
805 anim->setPosAt(1.0, QPointF(sw, Colors::contentStartY + Colors::contentHeight - 26));
806 movieOut->append(anim);
807}
808
809void MenuManager::createLowRightLeafButton(const QString &label, int xOffset, BUTTON_TYPE type, Movie *movieIn, Movie *movieOut, Movie * /*movieShake*/)
810{
811 TextButton *item = new TextButton(label, TextButton::RIGHT, type, this->window->scene, this->window->mainSceneRoot, TextButton::PANEL);
812 item->setRecursiveVisible(false);
813 item->setZValue(10);
814
815 qreal sw = this->window->scene->sceneRect().width();
816 qreal sh = this->window->scene->sceneRect().height();
817
818 // create in-animation:
819 DemoItemAnimation *anim = new DemoItemAnimation(item, DemoItemAnimation::ANIM_IN);
820 anim->setDuration(1050 * Colors::animSpeedButtons);
821 anim->setStartPos(QPointF(sw, Colors::contentStartY + Colors::contentHeight - 35));
822 anim->setPosAt(0.10, QPointF(sw, Colors::contentStartY + Colors::contentHeight - 35));
823 anim->setPosAt(0.30, QPointF(xOffset, Colors::contentStartY + Colors::contentHeight - 35));
824 anim->setPosAt(0.35, QPointF(xOffset + 30, Colors::contentStartY + Colors::contentHeight - 35));
825 anim->setPosAt(0.40, QPointF(xOffset, Colors::contentStartY + Colors::contentHeight - 35));
826 anim->setPosAt(0.45, QPointF(xOffset + 5, Colors::contentStartY + Colors::contentHeight - 35));
827 anim->setPosAt(0.50, QPointF(xOffset, Colors::contentStartY + Colors::contentHeight - 35));
828 anim->setPosAt(1.00, QPointF(xOffset, Colors::contentStartY + Colors::contentHeight - 26));
829 movieIn->append(anim);
830
831 // create out-animation:
832 anim = new DemoItemAnimation(item, DemoItemAnimation::ANIM_OUT);
833 anim->hideOnFinished = true;
834 anim->setDuration(300 * Colors::animSpeedButtons);
835 anim->setStartPos(QPointF(xOffset, Colors::contentStartY + Colors::contentHeight - 26));
836 anim->setPosAt(1.0, QPointF(xOffset, sh));
837 movieOut->append(anim);
838}
839
840void MenuManager::createInfo(DemoItem *item, const QString &name)
841{
842 Movie *movie_in = this->score->insertMovie(name);
843 Movie *movie_out = this->score->insertMovie(name + " -out");
844 item->setZValue(8);
845 item->setRecursiveVisible(false);
846
847 float xOffset = 230.0f;
848 DemoItemAnimation *infoIn = new DemoItemAnimation(item, DemoItemAnimation::ANIM_IN);
849 infoIn->timeline->setCurveShape(QTimeLine::LinearCurve);
850 infoIn->setDuration(650);
851 infoIn->setStartPos(QPointF(this->window->scene->sceneRect().width(), Colors::contentStartY));
852 infoIn->setPosAt(0.60, QPointF(xOffset, Colors::contentStartY));
853 infoIn->setPosAt(0.70, QPointF(xOffset + 20, Colors::contentStartY));
854 infoIn->setPosAt(0.80, QPointF(xOffset, Colors::contentStartY));
855 infoIn->setPosAt(0.90, QPointF(xOffset + 7, Colors::contentStartY));
856 infoIn->setPosAt(1.00, QPointF(xOffset, Colors::contentStartY));
857 movie_in->append(infoIn);
858
859 DemoItemAnimation *infoOut = new DemoItemAnimation(item, DemoItemAnimation::ANIM_OUT);
860 infoOut->timeline->setCurveShape(QTimeLine::EaseInCurve);
861 infoOut->setDuration(300);
862 infoOut->hideOnFinished = true;
863 infoOut->setStartPos(QPointF(xOffset, Colors::contentStartY));
864 infoOut->setPosAt(1.0, QPointF(-600, Colors::contentStartY));
865 movie_out->append(infoOut);
866}
867
868void MenuManager::createTicker()
869{
870 if (!Colors::noTicker){
871 Movie *movie_in = this->score->insertMovie("ticker");
872 Movie *movie_out = this->score->insertMovie("ticker -out");
873 Movie *movie_activate = this->score->insertMovie("ticker -activate");
874 Movie *movie_deactivate = this->score->insertMovie("ticker -deactivate");
875
876 this->ticker = new ItemCircleAnimation(this->window->scene, 0);
877 this->ticker->setZValue(50);
878 this->ticker->hide();
879
880 // Move ticker in:
881 int qtendpos = 485;
882 int qtPosY = 120;
883 this->tickerInAnim = new DemoItemAnimation(this->ticker, DemoItemAnimation::ANIM_IN);
884 this->tickerInAnim->setDuration(500);
885 this->tickerInAnim->setStartPos(QPointF(this->window->scene->sceneRect().width(), Colors::contentStartY + qtPosY));
886 this->tickerInAnim->setPosAt(0.60, QPointF(qtendpos, Colors::contentStartY + qtPosY));
887 this->tickerInAnim->setPosAt(0.70, QPointF(qtendpos + 30, Colors::contentStartY + qtPosY));
888 this->tickerInAnim->setPosAt(0.80, QPointF(qtendpos, Colors::contentStartY + qtPosY));
889 this->tickerInAnim->setPosAt(0.90, QPointF(qtendpos + 5, Colors::contentStartY + qtPosY));
890 this->tickerInAnim->setPosAt(1.00, QPointF(qtendpos, Colors::contentStartY + qtPosY));
891 movie_in->append(this->tickerInAnim);
892
893 // Move ticker out:
894 DemoItemAnimation *qtOut = new DemoItemAnimation(this->ticker, DemoItemAnimation::ANIM_OUT);
895 qtOut->hideOnFinished = true;
896 qtOut->setDuration(500);
897 qtOut->setStartPos(QPointF(qtendpos, Colors::contentStartY + qtPosY));
898 qtOut->setPosAt(1.00, QPointF(this->window->scene->sceneRect().width() + 700, Colors::contentStartY + qtPosY));
899 movie_out->append(qtOut);
900
901 // Move ticker in on activate:
902 DemoItemAnimation *qtActivate = new DemoItemAnimation(this->ticker);
903 qtActivate->setDuration(400);
904 qtActivate->setStartPos(QPointF(this->window->scene->sceneRect().width(), Colors::contentStartY + qtPosY));
905 qtActivate->setPosAt(0.60, QPointF(qtendpos, Colors::contentStartY + qtPosY));
906 qtActivate->setPosAt(0.70, QPointF(qtendpos + 30, Colors::contentStartY + qtPosY));
907 qtActivate->setPosAt(0.80, QPointF(qtendpos, Colors::contentStartY + qtPosY));
908 qtActivate->setPosAt(0.90, QPointF(qtendpos + 5, Colors::contentStartY + qtPosY));
909 qtActivate->setPosAt(1.00, QPointF(qtendpos, Colors::contentStartY + qtPosY));
910 movie_activate->append(qtActivate);
911
912 // Move ticker out on deactivate:
913 DemoItemAnimation *qtDeactivate = new DemoItemAnimation(this->ticker);
914 qtDeactivate->hideOnFinished = true;
915 qtDeactivate->setDuration(400);
916 qtDeactivate->setStartPos(QPointF(qtendpos, Colors::contentStartY + qtPosY));
917 qtDeactivate->setPosAt(1.00, QPointF(qtendpos, 800));
918 movie_deactivate->append(qtDeactivate);
919 }
920}
921
922void MenuManager::createUpnDownButtons()
923{
924 float xOffset = 15.0f;
925 float yOffset = 450.0f;
926
927 this->upButton = new TextButton("", TextButton::LEFT, MenuManager::UP, this->window->scene, this->window->mainSceneRoot, TextButton::UP);
928 this->upButton->prepare();
929 this->upButton->setPos(xOffset, yOffset);
930 this->upButton->setState(TextButton::DISABLED);
931
932 this->downButton = new TextButton("", TextButton::LEFT, MenuManager::DOWN, this->window->scene, this->window->mainSceneRoot, TextButton::DOWN);
933 this->downButton->prepare();
934 this->downButton->setPos(xOffset + 10 + this->downButton->sceneBoundingRect().width(), yOffset);
935
936 Movie *movieShake = this->score->insertMovie("upndown -shake");
937
938 DemoItemAnimation *shakeAnim = new DemoItemAnimation(this->upButton, DemoItemAnimation::ANIM_UNSPECIFIED);
939 shakeAnim->timeline->setCurveShape(QTimeLine::LinearCurve);
940 shakeAnim->setDuration(650);
941 shakeAnim->setStartPos(this->upButton->pos());
942 shakeAnim->setPosAt(0.60, this->upButton->pos());
943 shakeAnim->setPosAt(0.70, this->upButton->pos() + QPointF(-2, 0));
944 shakeAnim->setPosAt(0.80, this->upButton->pos() + QPointF(1, 0));
945 shakeAnim->setPosAt(0.90, this->upButton->pos() + QPointF(-1, 0));
946 shakeAnim->setPosAt(1.00, this->upButton->pos());
947 movieShake->append(shakeAnim);
948
949 shakeAnim = new DemoItemAnimation(this->downButton, DemoItemAnimation::ANIM_UNSPECIFIED);
950 shakeAnim->timeline->setCurveShape(QTimeLine::LinearCurve);
951 shakeAnim->setDuration(650);
952 shakeAnim->setStartPos(this->downButton->pos());
953 shakeAnim->setPosAt(0.60, this->downButton->pos());
954 shakeAnim->setPosAt(0.70, this->downButton->pos() + QPointF(-5, 0));
955 shakeAnim->setPosAt(0.80, this->downButton->pos() + QPointF(-3, 0));
956 shakeAnim->setPosAt(0.90, this->downButton->pos() + QPointF(-1, 0));
957 shakeAnim->setPosAt(1.00, this->downButton->pos());
958 movieShake->append(shakeAnim);
959}
960
961void MenuManager::createBackButton()
962{
963 Movie *backIn = this->score->insertMovie("back -in");
964 Movie *backOut = this->score->insertMovie("back -out");
965 Movie *backShake = this->score->insertMovie("back -shake");
966 createLowLeftButton(QLatin1String("Back"), ROOT, backIn, backOut, backShake, Colors::rootMenuName);
967}
Note: See TracBrowser for help on using the repository browser.