demos/qtdemo/menumanager.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 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 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    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 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "menumanager.h"
       
    43 #include "colors.h"
       
    44 #include "menucontent.h"
       
    45 #include "examplecontent.h"
       
    46 
       
    47 MenuManager *MenuManager::pInstance = 0;
       
    48 
       
    49 MenuManager * MenuManager::instance()
       
    50 {
       
    51     if (!MenuManager::pInstance)
       
    52         MenuManager::pInstance = new MenuManager();
       
    53     return MenuManager::pInstance;
       
    54 }
       
    55 
       
    56 MenuManager::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 
       
    73 MenuManager::~MenuManager()
       
    74 {
       
    75     delete this->score;
       
    76     delete this->contentsDoc;
       
    77     delete this->helpEngine;
       
    78 }
       
    79 
       
    80 QByteArray 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 
       
    88 void 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 
       
   107 void 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 
       
   149 void MenuManager::itemSelected(int userCode, const QString &menuName)
       
   150 {
       
   151     switch (userCode){
       
   152     case LAUNCH:
       
   153         this->launchExample(this->currentInfo);
       
   154         break;
       
   155     case DOCUMENTATION:
       
   156         this->showDocInAssistant(this->currentInfo);
       
   157         break;
       
   158     case QUIT:
       
   159         this->window->loop = false;
       
   160         QCoreApplication::quit();
       
   161         break;
       
   162     case FULLSCREEN:
       
   163         this->window->toggleFullscreen();
       
   164         break;
       
   165     case ROOT:
       
   166         // out:
       
   167         this->score->queueMovie(this->currentMenu + " -out", Score::FROM_START, Score::LOCK_ITEMS);
       
   168         this->score->queueMovie(this->currentMenuButtons + " -out", Score::FROM_START, Score::LOCK_ITEMS);
       
   169         this->score->queueMovie(this->currentInfo + " -out");
       
   170         this->score->queueMovie(this->currentInfo + " -buttons -out", Score::NEW_ANIMATION_ONLY);
       
   171         this->score->queueMovie("back -out", Score::ONLY_IF_VISIBLE);
       
   172         // book-keeping:
       
   173         this->currentMenuCode = ROOT;
       
   174         this->currentMenu = menuName + " -menu1";
       
   175         this->currentMenuButtons = menuName + " -buttons";
       
   176         this->currentInfo = menuName + " -info";
       
   177         // in:
       
   178         this->score->queueMovie("upndown -shake");
       
   179         this->score->queueMovie(this->currentMenu, Score::FROM_START, Score::UNLOCK_ITEMS);
       
   180         this->score->queueMovie(this->currentMenuButtons, Score::FROM_START, Score::UNLOCK_ITEMS);
       
   181         this->score->queueMovie(this->currentInfo);
       
   182         if (!Colors::noTicker){
       
   183             this->ticker->doIntroTransitions = true;
       
   184             this->tickerInAnim->startDelay = 2000;
       
   185             this->ticker->useGuideQt();
       
   186             this->score->queueMovie("ticker", Score::NEW_ANIMATION_ONLY);
       
   187         }
       
   188         break;
       
   189     case MENU1:
       
   190         // out:
       
   191         this->score->queueMovie(this->currentMenu + " -out", Score::FROM_START, Score::LOCK_ITEMS);
       
   192         this->score->queueMovie(this->currentMenuButtons + " -out", Score::FROM_START, Score::LOCK_ITEMS);
       
   193         this->score->queueMovie(this->currentInfo + " -out");
       
   194         // book-keeping:
       
   195         this->currentMenuCode = MENU1;
       
   196         this->currentCategory = menuName;
       
   197         this->currentMenu = menuName + " -menu1";
       
   198         this->currentInfo = menuName + " -info";
       
   199         // in:
       
   200         this->score->queueMovie("upndown -shake");
       
   201         this->score->queueMovie("back -in");
       
   202         this->score->queueMovie(this->currentMenu, Score::FROM_START, Score::UNLOCK_ITEMS);
       
   203         this->score->queueMovie(this->currentInfo);
       
   204         if (!Colors::noTicker)
       
   205             this->ticker->useGuideTt();
       
   206         break;
       
   207     case MENU2:
       
   208         // out:
       
   209         this->score->queueMovie(this->currentInfo + " -out", Score::NEW_ANIMATION_ONLY);
       
   210         this->score->queueMovie(this->currentInfo + " -buttons -out", Score::NEW_ANIMATION_ONLY);
       
   211         // book-keeping:
       
   212         this->currentMenuCode = MENU2;
       
   213         this->currentInfo = menuName;
       
   214         // in / shake:
       
   215         this->score->queueMovie("upndown -shake");
       
   216         this->score->queueMovie("back -shake");
       
   217         this->score->queueMovie(this->currentMenu + " -shake");
       
   218         this->score->queueMovie(this->currentInfo, Score::NEW_ANIMATION_ONLY);
       
   219         this->score->queueMovie(this->currentInfo + " -buttons", Score::NEW_ANIMATION_ONLY);
       
   220         if (!Colors::noTicker){
       
   221             this->score->queueMovie("ticker -out", Score::NEW_ANIMATION_ONLY);
       
   222         }
       
   223         break;
       
   224     case UP:{
       
   225         QString backMenu = this->info[this->currentMenu]["back"];
       
   226         if (!backMenu.isNull()){
       
   227             this->score->queueMovie(this->currentMenu + " -top_out", Score::FROM_START, Score::LOCK_ITEMS);
       
   228             this->score->queueMovie(backMenu + " -bottom_in", Score::FROM_START, Score::UNLOCK_ITEMS);
       
   229             this->currentMenu = backMenu;
       
   230         }
       
   231         break; }
       
   232     case DOWN:{
       
   233         QString moreMenu = this->info[this->currentMenu]["more"];
       
   234         if (!moreMenu.isNull()){
       
   235             this->score->queueMovie(this->currentMenu + " -bottom_out", Score::FROM_START, Score::LOCK_ITEMS);
       
   236             this->score->queueMovie(moreMenu + " -top_in", Score::FROM_START, Score::UNLOCK_ITEMS);
       
   237             this->currentMenu = moreMenu;
       
   238         }
       
   239         break; }
       
   240     case BACK:{
       
   241         if (this->currentMenuCode == MENU2){
       
   242             // out:
       
   243             this->score->queueMovie(this->currentInfo + " -out", Score::NEW_ANIMATION_ONLY);
       
   244             this->score->queueMovie(this->currentInfo + " -buttons -out", Score::NEW_ANIMATION_ONLY);
       
   245             // book-keeping:
       
   246             this->currentMenuCode = MENU1;
       
   247             this->currentMenuButtons = this->currentCategory + " -buttons";
       
   248             this->currentInfo = this->currentCategory + " -info";
       
   249             // in / shake:
       
   250             this->score->queueMovie("upndown -shake");
       
   251             this->score->queueMovie(this->currentMenu + " -shake");
       
   252             this->score->queueMovie(this->currentInfo, Score::NEW_ANIMATION_ONLY);
       
   253             this->score->queueMovie(this->currentInfo + " -buttons", Score::NEW_ANIMATION_ONLY);
       
   254             if (!Colors::noTicker){
       
   255                 this->ticker->doIntroTransitions = false;
       
   256                 this->tickerInAnim->startDelay = 500;
       
   257                 this->score->queueMovie("ticker", Score::NEW_ANIMATION_ONLY);
       
   258             }
       
   259         } else if (this->currentMenuCode != ROOT)
       
   260             itemSelected(ROOT, Colors::rootMenuName);
       
   261         break; }
       
   262     }
       
   263 
       
   264     // update back- and more buttons
       
   265     bool noBackMenu = this->info[this->currentMenu]["back"].isNull();
       
   266     bool noMoreMenu = this->info[this->currentMenu]["more"].isNull();
       
   267     this->upButton->setState(noBackMenu ? TextButton::DISABLED : TextButton::OFF);
       
   268     this->downButton->setState(noMoreMenu ? TextButton::DISABLED : TextButton::OFF);
       
   269 
       
   270     if (this->score->hasQueuedMovies()){
       
   271         this->score->playQue();
       
   272         // Playing new movies might include
       
   273         // loading etc. So ignore the FPS
       
   274         // at this point
       
   275         this->window->fpsHistory.clear();
       
   276     }
       
   277 }
       
   278 
       
   279 void MenuManager::showDocInAssistant(const QString &name)
       
   280 {
       
   281     QString url = this->resolveDocUrl(name);
       
   282     if (Colors::verbose)
       
   283         qDebug() << "Sending URL to Assistant:" << url;
       
   284 
       
   285     // Start assistant if it's not already running:
       
   286     if (this->assistantProcess.state() != QProcess::Running){
       
   287         QString app = QLibraryInfo::location(QLibraryInfo::BinariesPath) + QDir::separator();
       
   288 #if !defined(Q_OS_MAC)
       
   289         app += QLatin1String("assistant");
       
   290 #else
       
   291         app += QLatin1String("Assistant.app/Contents/MacOS/Assistant");
       
   292 #endif
       
   293         QStringList args;
       
   294         args << QLatin1String("-enableRemoteControl");
       
   295         this->assistantProcess.start(app, args);
       
   296         if (!this->assistantProcess.waitForStarted()) {
       
   297             QMessageBox::critical(0, tr("Qt Demo"), tr("Could not start Qt Assistant.").arg(app));
       
   298             return;
       
   299         }
       
   300     }
       
   301 
       
   302     // Send command through remote control even if the process
       
   303     // was started to activate assistant and bring it to front:
       
   304     QTextStream str(&this->assistantProcess);
       
   305     str << "SetSource " << url << QLatin1Char('\0') << endl;
       
   306 }
       
   307 
       
   308 void MenuManager::launchExample(const QString &name)
       
   309 {
       
   310     QString executable = this->resolveExeFile(name);
       
   311 #ifdef Q_OS_MAC
       
   312     if (Colors::verbose)
       
   313         qDebug() << "Launching:" << executable;
       
   314     bool success = QDesktopServices::openUrl(QUrl::fromLocalFile(executable));
       
   315     if (!success){
       
   316         QMessageBox::critical(0, tr("Failed to launch the example"),
       
   317                           tr("Could not launch the example. Ensure that it has been built."),
       
   318                           QMessageBox::Cancel);
       
   319     }
       
   320 #else // Not mac. To not break anything regarding dll's etc, keep it the way it was before:
       
   321     QProcess *process = new QProcess(this);
       
   322     connect(process, SIGNAL(finished(int)), this, SLOT(exampleFinished()));
       
   323     connect(process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(exampleError(QProcess::ProcessError)));
       
   324 
       
   325 #ifdef Q_OS_WIN
       
   326     //make sure it finds the dlls on windows
       
   327     QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
       
   328     env.insert(QLatin1String("PATH"), QLibraryInfo::location(QLibraryInfo::BinariesPath) 
       
   329                + QLatin1Char(';') + env.value(QLatin1String("Path")));
       
   330     process->setProcessEnvironment(env);
       
   331 #endif
       
   332 
       
   333     if (info[name]["changedirectory"] != "false"){
       
   334         QString workingDirectory = resolveDataDir(name);
       
   335         process->setWorkingDirectory(workingDirectory);
       
   336         if (Colors::verbose)
       
   337             qDebug() << "Setting working directory:" << workingDirectory;
       
   338     }
       
   339 
       
   340     if (Colors::verbose)
       
   341         qDebug() << "Launching:" << executable;
       
   342     process->start(executable);
       
   343 #endif
       
   344 }
       
   345 
       
   346 void MenuManager::exampleFinished()
       
   347 {
       
   348 }
       
   349 
       
   350 void MenuManager::exampleError(QProcess::ProcessError error)
       
   351 {
       
   352     if (error != QProcess::Crashed)
       
   353         QMessageBox::critical(0, tr("Failed to launch the example"),
       
   354                           tr("Could not launch the example. Ensure that it has been built."),
       
   355                           QMessageBox::Cancel);
       
   356 }
       
   357 
       
   358 void MenuManager::init(MainWindow *window)
       
   359 {
       
   360     this->window = window;
       
   361 
       
   362     // Create div:
       
   363     this->createTicker();
       
   364     this->createUpnDownButtons();
       
   365     this->createBackButton();
       
   366 
       
   367     // Create first level menu:
       
   368     QDomElement rootElement = this->contentsDoc->documentElement();
       
   369     this->createRootMenu(rootElement);
       
   370 
       
   371     // Create second level menus:
       
   372     QDomNode level2MenuNode = rootElement.firstChild();
       
   373     while (!level2MenuNode.isNull()){
       
   374         QDomElement level2MenuElement = level2MenuNode.toElement();
       
   375         this->createSubMenu(level2MenuElement);
       
   376 
       
   377         // create leaf menu and example info:
       
   378         QDomNode exampleNode = level2MenuElement.firstChild();
       
   379         while (!exampleNode.isNull()){
       
   380             QDomElement exampleElement = exampleNode.toElement();
       
   381             this->readInfoAboutExample(exampleElement);
       
   382             this->createLeafMenu(exampleElement);
       
   383             exampleNode = exampleNode.nextSibling();
       
   384         }
       
   385 
       
   386         level2MenuNode = level2MenuNode.nextSibling();
       
   387     }
       
   388 }
       
   389 
       
   390 void MenuManager::readInfoAboutExample(const QDomElement &example)
       
   391 {
       
   392     QString name = example.attribute("name");
       
   393     if (this->info.contains(name))
       
   394         qWarning() << "__WARNING: MenuManager::readInfoAboutExample: Demo/example with name"
       
   395                     << name << "appears twize in the xml-file!__";
       
   396 
       
   397     this->info[name]["filename"] = example.attribute("filename");
       
   398     this->info[name]["category"] = example.parentNode().toElement().tagName();
       
   399     this->info[name]["dirname"] = example.parentNode().toElement().attribute("dirname");
       
   400     this->info[name]["changedirectory"] = example.attribute("changedirectory");
       
   401     this->info[name]["image"] = example.attribute("image");
       
   402 }
       
   403 
       
   404 QString MenuManager::resolveDataDir(const QString &name)
       
   405 {
       
   406     QString dirName = this->info[name]["dirname"];
       
   407     QString category = this->info[name]["category"];
       
   408     QString fileName = this->info[name]["filename"];
       
   409 
       
   410     QDir dir;
       
   411     if (category == "demos")
       
   412         dir = QDir(QLibraryInfo::location(QLibraryInfo::DemosPath));
       
   413     else
       
   414         dir = QDir(QLibraryInfo::location(QLibraryInfo::ExamplesPath));
       
   415 
       
   416     dir.cd(dirName);
       
   417     dir.cd(fileName);
       
   418     return dir.absolutePath();
       
   419 }
       
   420 
       
   421 QString MenuManager::resolveExeFile(const QString &name)
       
   422 {
       
   423     QString dirName = this->info[name]["dirname"];
       
   424     QString category = this->info[name]["category"];
       
   425     QString fileName = this->info[name]["filename"];
       
   426 
       
   427     QDir dir;
       
   428     if (category == "demos")
       
   429         dir = QDir(QLibraryInfo::location(QLibraryInfo::DemosPath));
       
   430     else
       
   431         dir = QDir(QLibraryInfo::location(QLibraryInfo::ExamplesPath));
       
   432 
       
   433     dir.cd(dirName);
       
   434     dir.cd(fileName);
       
   435 
       
   436     QFile unixFile(dir.path() + "/" + fileName);
       
   437     if (unixFile.exists()) return unixFile.fileName();
       
   438     QFile winR(dir.path() + "\\release\\" + fileName + ".exe");
       
   439     if (winR.exists()) return winR.fileName();
       
   440     QFile winD(dir.path() + "\\debug\\" + fileName + ".exe");
       
   441     if (winD.exists()) return winD.fileName();
       
   442     QFile mac(dir.path() + "/" + fileName + ".app");
       
   443     if (mac.exists()) return mac.fileName();
       
   444 
       
   445     if (Colors::verbose)
       
   446         qDebug() << "- WARNING: Could not resolve executable:" << dir.path() << fileName;
       
   447     return "__executable not found__";
       
   448 }
       
   449 
       
   450 QString MenuManager::resolveDocUrl(const QString &name)
       
   451 {
       
   452     QString dirName = this->info[name]["dirname"];
       
   453     QString category = this->info[name]["category"];
       
   454     QString fileName = this->info[name]["filename"];
       
   455 
       
   456     if (category == "demos")
       
   457         return this->helpRootUrl + "demos-" + fileName + ".html";
       
   458     else
       
   459         return this->helpRootUrl + dirName.replace("/", "-") + "-" + fileName + ".html";
       
   460 }
       
   461 
       
   462 QString MenuManager::resolveImageUrl(const QString &name)
       
   463 {
       
   464     return this->helpRootUrl + "images/" + name;
       
   465 }
       
   466 
       
   467 QByteArray MenuManager::getHtml(const QString &name)
       
   468 {
       
   469     return getResource(this->resolveDocUrl(name));
       
   470 }
       
   471 
       
   472 QByteArray MenuManager::getImage(const QString &name)
       
   473 {
       
   474     QString imageName = this->info[name]["image"];
       
   475     QString category = this->info[name]["category"];
       
   476     QString fileName = this->info[name]["filename"];
       
   477 
       
   478     if (imageName.isEmpty()){
       
   479         if (category == "demos")
       
   480             imageName = fileName + "-demo.png";
       
   481         else
       
   482             imageName = fileName + "-example.png";
       
   483         if ((getResource(resolveImageUrl(imageName))).isEmpty())
       
   484             imageName = fileName + ".png";
       
   485         if ((getResource(resolveImageUrl(imageName))).isEmpty())
       
   486             imageName = fileName + "example.png";
       
   487     }
       
   488     return getResource(resolveImageUrl(imageName));
       
   489 }
       
   490 
       
   491 
       
   492 void MenuManager::createRootMenu(const QDomElement &el)
       
   493 {
       
   494     QString name = el.attribute("name");
       
   495     createMenu(el, MENU1);
       
   496     createInfo(new MenuContentItem(el, this->window->scene, 0), name + " -info");
       
   497 
       
   498     Movie *menuButtonsIn = this->score->insertMovie(name + " -buttons");
       
   499     Movie *menuButtonsOut = this->score->insertMovie(name + " -buttons -out");
       
   500     createLowLeftButton(QLatin1String("Quit"), QUIT, menuButtonsIn, menuButtonsOut, 0);
       
   501     createLowRightButton("Toggle fullscreen", FULLSCREEN, menuButtonsIn, menuButtonsOut, 0);
       
   502 }
       
   503 
       
   504 void MenuManager::createSubMenu(const QDomElement &el)
       
   505 {
       
   506     QString name = el.attribute("name");
       
   507     createMenu(el, MENU2);
       
   508     createInfo(new MenuContentItem(el, this->window->scene, 0), name + " -info");
       
   509 }
       
   510 
       
   511 void MenuManager::createLeafMenu(const QDomElement &el)
       
   512 {
       
   513     QString name = el.attribute("name");
       
   514     createInfo(new ExampleContent(name, this->window->scene, 0), name);
       
   515 
       
   516     Movie *infoButtonsIn = this->score->insertMovie(name + " -buttons");
       
   517     Movie *infoButtonsOut = this->score->insertMovie(name + " -buttons -out");
       
   518     createLowRightLeafButton("Documentation", 600, DOCUMENTATION, infoButtonsIn, infoButtonsOut, 0);
       
   519     if (el.attribute("executable") != "false")
       
   520         createLowRightLeafButton("Launch", 405, LAUNCH, infoButtonsIn, infoButtonsOut, 0);
       
   521 }
       
   522 
       
   523 void MenuManager::createMenu(const QDomElement &category, BUTTON_TYPE type)
       
   524 {
       
   525     qreal sw = this->window->scene->sceneRect().width();
       
   526     int xOffset = 15;
       
   527     int yOffset = 10;
       
   528     int maxExamples = Colors::menuCount;
       
   529     int menuIndex = 1;
       
   530     QString name = category.attribute("name");
       
   531     QDomNode currentNode = category.firstChild();
       
   532     QString currentMenu = name + QLatin1String(" -menu") + QString::number(menuIndex);
       
   533 
       
   534     while (!currentNode.isNull()){
       
   535         Movie *movieIn = this->score->insertMovie(currentMenu);
       
   536         Movie *movieOut = this->score->insertMovie(currentMenu + " -out");
       
   537         Movie *movieNextTopOut = this->score->insertMovie(currentMenu + " -top_out");
       
   538         Movie *movieNextBottomOut = this->score->insertMovie(currentMenu + " -bottom_out");
       
   539         Movie *movieNextTopIn = this->score->insertMovie(currentMenu + " -top_in");
       
   540         Movie *movieNextBottomIn = this->score->insertMovie(currentMenu + " -bottom_in");
       
   541         Movie *movieShake = this->score->insertMovie(currentMenu + " -shake");
       
   542 
       
   543         int i = 0;
       
   544         while (!currentNode.isNull() && i < maxExamples){
       
   545             TextButton *item;
       
   546 
       
   547             // create normal menu button
       
   548             QString label = currentNode.toElement().attribute("name");
       
   549             item = new TextButton(label, TextButton::LEFT, type, this->window->scene, 0);
       
   550             currentNode = currentNode.nextSibling();
       
   551 
       
   552 #ifndef QT_OPENGL_SUPPORT
       
   553             if (currentNode.toElement().attribute("dirname") == "opengl")
       
   554                 currentNode = currentNode.nextSibling();
       
   555 #endif
       
   556 
       
   557             item->setRecursiveVisible(false);
       
   558             item->setZValue(10);
       
   559             qreal ih = item->sceneBoundingRect().height();
       
   560             qreal iw = item->sceneBoundingRect().width();
       
   561             qreal ihp = ih + 3;
       
   562 
       
   563             // create in-animation:
       
   564             DemoItemAnimation *anim = new DemoItemAnimation(item, DemoItemAnimation::ANIM_IN);
       
   565             anim->setDuration(float(1000 + (i * 20)) * Colors::animSpeedButtons);
       
   566             anim->setStartPos(QPointF(xOffset, -ih));
       
   567             anim->setPosAt(0.20, QPointF(xOffset, -ih));
       
   568             anim->setPosAt(0.50, QPointF(xOffset, (i * ihp) + yOffset + Colors::contentStartY + (10 * float(i / 4.0f))));
       
   569             anim->setPosAt(0.60, QPointF(xOffset, (i * ihp) + yOffset + Colors::contentStartY));
       
   570             anim->setPosAt(0.70, QPointF(xOffset, (i * ihp) + yOffset + Colors::contentStartY + (5 * float(i / 4.0f))));
       
   571             anim->setPosAt(0.80, QPointF(xOffset, (i * ihp) + yOffset + Colors::contentStartY));
       
   572             anim->setPosAt(0.90, QPointF(xOffset, (i * ihp) + yOffset + Colors::contentStartY + (2 * float(i / 4.0f))));
       
   573             anim->setPosAt(1.00, QPointF(xOffset, (i * ihp) + yOffset + Colors::contentStartY));
       
   574             movieIn->append(anim);
       
   575 
       
   576             // create out-animation:
       
   577             anim = new DemoItemAnimation(item, DemoItemAnimation::ANIM_OUT);
       
   578             anim->hideOnFinished = true;
       
   579             anim->setDuration((700 + (30 * i)) * Colors::animSpeedButtons);
       
   580             anim->setStartPos(QPointF(xOffset, (i * ihp) + yOffset + Colors::contentStartY));
       
   581             anim->setPosAt(0.60, QPointF(xOffset, 600 - ih - ih));
       
   582             anim->setPosAt(0.65, QPointF(xOffset + 20, 600 - ih));
       
   583             anim->setPosAt(1.00, QPointF(sw + iw, 600 - ih));
       
   584             movieOut->append(anim);
       
   585 
       
   586             // create shake-animation:
       
   587             anim = new DemoItemAnimation(item);
       
   588             anim->setDuration(700 * Colors::animSpeedButtons);
       
   589             anim->setStartPos(QPointF(xOffset, (i * ihp) + yOffset + Colors::contentStartY));
       
   590             anim->setPosAt(0.55, QPointF(xOffset, (i * ihp) + yOffset + Colors::contentStartY - i*2.0));
       
   591             anim->setPosAt(0.70, QPointF(xOffset - 10, (i * ihp) + yOffset + Colors::contentStartY - i*1.5));
       
   592             anim->setPosAt(0.80, QPointF(xOffset, (i * ihp) + yOffset + Colors::contentStartY - i*1.0));
       
   593             anim->setPosAt(0.90, QPointF(xOffset - 2, (i * ihp) + yOffset + Colors::contentStartY - i*0.5));
       
   594             anim->setPosAt(1.00, QPointF(xOffset, (i * ihp) + yOffset + Colors::contentStartY));
       
   595             movieShake->append(anim);
       
   596 
       
   597             // create next-menu top-out-animation:
       
   598             anim = new DemoItemAnimation(item, DemoItemAnimation::ANIM_OUT);
       
   599             anim->hideOnFinished = true;
       
   600             anim->setDuration((200 + (30 * i)) * Colors::animSpeedButtons);
       
   601             anim->setStartPos(QPointF(xOffset, (i * ihp) + yOffset + Colors::contentStartY));
       
   602             anim->setPosAt(0.70, QPointF(xOffset, yOffset + Colors::contentStartY));
       
   603             anim->setPosAt(1.00, QPointF(-iw, yOffset + Colors::contentStartY));
       
   604             movieNextTopOut->append(anim);
       
   605 
       
   606             // create next-menu bottom-out-animation:
       
   607             anim = new DemoItemAnimation(item, DemoItemAnimation::ANIM_OUT);
       
   608             anim->hideOnFinished = true;
       
   609             anim->setDuration((200 + (30 * i)) * Colors::animSpeedButtons);
       
   610             anim->setStartPos(QPointF(xOffset, (i * ihp) + yOffset + Colors::contentStartY));
       
   611             anim->setPosAt(0.70, QPointF(xOffset, (maxExamples * ihp) + yOffset + Colors::contentStartY));
       
   612             anim->setPosAt(1.00, QPointF(-iw, (maxExamples * ihp) + yOffset + Colors::contentStartY));
       
   613             movieNextBottomOut->append(anim);
       
   614 
       
   615             // create next-menu top-in-animation:
       
   616             anim = new DemoItemAnimation(item, DemoItemAnimation::ANIM_IN);
       
   617             anim->setDuration((700 - (30 * i)) * Colors::animSpeedButtons);
       
   618             anim->setStartPos(QPointF(-iw, yOffset + Colors::contentStartY));
       
   619             anim->setPosAt(0.30, QPointF(xOffset, yOffset + Colors::contentStartY));
       
   620             anim->setPosAt(1.00, QPointF(xOffset, (i * ihp) + yOffset + Colors::contentStartY));
       
   621             movieNextTopIn->append(anim);
       
   622 
       
   623             // create next-menu bottom-in-animation:
       
   624             int reverse = maxExamples - i;
       
   625             anim = new DemoItemAnimation(item, DemoItemAnimation::ANIM_IN);
       
   626             anim->setDuration((1000 - (30 * reverse)) * Colors::animSpeedButtons);
       
   627             anim->setStartPos(QPointF(-iw, (maxExamples * ihp) + yOffset + Colors::contentStartY));
       
   628             anim->setPosAt(0.30, QPointF(xOffset, (maxExamples * ihp) + yOffset + Colors::contentStartY));
       
   629             anim->setPosAt(1.00, QPointF(xOffset, (i * ihp) + yOffset + Colors::contentStartY));
       
   630             movieNextBottomIn->append(anim);
       
   631 
       
   632             i++;
       
   633         }
       
   634 
       
   635         if (!currentNode.isNull() && i == maxExamples){
       
   636             // We need another menu, so register for 'more' and 'back' buttons
       
   637             ++menuIndex;
       
   638             this->info[currentMenu]["more"] = name + QLatin1String(" -menu") + QString::number(menuIndex);
       
   639             currentMenu = name + QLatin1String(" -menu") + QString::number(menuIndex);
       
   640             this->info[currentMenu]["back"] = name + QLatin1String(" -menu") + QString::number(menuIndex - 1);
       
   641         }
       
   642     }
       
   643 }
       
   644 
       
   645 
       
   646 void MenuManager::createLowLeftButton(const QString &label, BUTTON_TYPE type,
       
   647     Movie *movieIn, Movie *movieOut, Movie *movieShake, const QString &menuString)
       
   648 {
       
   649     TextButton *button = new TextButton(label, TextButton::RIGHT, type, this->window->scene, 0, TextButton::PANEL);
       
   650     if (!menuString.isNull())
       
   651         button->setMenuString(menuString);
       
   652     button->setRecursiveVisible(false);
       
   653     button->setZValue(10);
       
   654 
       
   655     qreal iw = button->sceneBoundingRect().width();
       
   656     int xOffset = 15;
       
   657 
       
   658     // create in-animation:
       
   659     DemoItemAnimation *buttonIn = new DemoItemAnimation(button, DemoItemAnimation::ANIM_IN);
       
   660     buttonIn->setDuration(1800 * Colors::animSpeedButtons);
       
   661     buttonIn->setStartPos(QPointF(-iw, Colors::contentStartY + Colors::contentHeight - 35));
       
   662     buttonIn->setPosAt(0.5, QPointF(-iw, Colors::contentStartY + Colors::contentHeight - 35));
       
   663     buttonIn->setPosAt(0.7, QPointF(xOffset, Colors::contentStartY + Colors::contentHeight - 35));
       
   664     buttonIn->setPosAt(1.0, QPointF(xOffset, Colors::contentStartY + Colors::contentHeight - 26));
       
   665     movieIn->append(buttonIn);
       
   666 
       
   667     // create out-animation:
       
   668     DemoItemAnimation *buttonOut = new DemoItemAnimation(button, DemoItemAnimation::ANIM_OUT);
       
   669     buttonOut->hideOnFinished = true;
       
   670     buttonOut->setDuration(400 * Colors::animSpeedButtons);
       
   671     buttonOut->setStartPos(QPointF(xOffset, Colors::contentStartY + Colors::contentHeight - 26));
       
   672     buttonOut->setPosAt(1.0, QPointF(-iw, Colors::contentStartY + Colors::contentHeight - 26));
       
   673     movieOut->append(buttonOut);
       
   674 
       
   675     if (movieShake){
       
   676         DemoItemAnimation *shakeAnim = new DemoItemAnimation(button, DemoItemAnimation::ANIM_UNSPECIFIED);
       
   677         shakeAnim->timeline->setCurveShape(QTimeLine::LinearCurve);
       
   678         shakeAnim->setDuration(650);
       
   679         shakeAnim->setStartPos(buttonIn->posAt(1.0f));
       
   680         shakeAnim->setPosAt(0.60, buttonIn->posAt(1.0f));
       
   681         shakeAnim->setPosAt(0.70, buttonIn->posAt(1.0f) + QPointF(-3, 0));
       
   682         shakeAnim->setPosAt(0.80, buttonIn->posAt(1.0f) + QPointF(2, 0));
       
   683         shakeAnim->setPosAt(0.90, buttonIn->posAt(1.0f) + QPointF(-1, 0));
       
   684         shakeAnim->setPosAt(1.00, buttonIn->posAt(1.0f));
       
   685         movieShake->append(shakeAnim);
       
   686     }
       
   687 }
       
   688 
       
   689 void MenuManager::createLowRightButton(const QString &label, BUTTON_TYPE type, Movie *movieIn, Movie *movieOut, Movie * /*movieShake*/)
       
   690 {
       
   691     TextButton *item = new TextButton(label, TextButton::RIGHT, type, this->window->scene, 0, TextButton::PANEL);
       
   692     item->setRecursiveVisible(false);
       
   693     item->setZValue(10);
       
   694 
       
   695     qreal sw = this->window->scene->sceneRect().width();
       
   696     int xOffset = 70;
       
   697 
       
   698     // create in-animation:
       
   699     DemoItemAnimation *anim = new DemoItemAnimation(item, DemoItemAnimation::ANIM_IN);
       
   700     anim->setDuration(1800 * Colors::animSpeedButtons);
       
   701     anim->setStartPos(QPointF(sw, Colors::contentStartY + Colors::contentHeight - 35));
       
   702     anim->setPosAt(0.5, QPointF(sw, Colors::contentStartY + Colors::contentHeight - 35));
       
   703     anim->setPosAt(0.7, QPointF(xOffset + 535, Colors::contentStartY + Colors::contentHeight - 35));
       
   704     anim->setPosAt(1.0, QPointF(xOffset + 535, Colors::contentStartY + Colors::contentHeight - 26));
       
   705     movieIn->append(anim);
       
   706 
       
   707     // create out-animation:
       
   708     anim = new DemoItemAnimation(item, DemoItemAnimation::ANIM_OUT);
       
   709     anim->hideOnFinished = true;
       
   710     anim->setDuration(400 * Colors::animSpeedButtons);
       
   711     anim->setStartPos(QPointF(xOffset + 535, Colors::contentStartY + Colors::contentHeight - 26));
       
   712     anim->setPosAt(1.0, QPointF(sw, Colors::contentStartY + Colors::contentHeight - 26));
       
   713     movieOut->append(anim);
       
   714 }
       
   715 
       
   716 void MenuManager::createLowRightLeafButton(const QString &label, int xOffset, BUTTON_TYPE type, Movie *movieIn, Movie *movieOut, Movie * /*movieShake*/)
       
   717 {
       
   718     TextButton *item = new TextButton(label, TextButton::RIGHT, type, this->window->scene, 0, TextButton::PANEL);
       
   719     item->setRecursiveVisible(false);
       
   720     item->setZValue(10);
       
   721 
       
   722     qreal sw = this->window->scene->sceneRect().width();
       
   723     qreal sh = this->window->scene->sceneRect().height();
       
   724 
       
   725     // create in-animation:
       
   726     DemoItemAnimation *anim = new DemoItemAnimation(item, DemoItemAnimation::ANIM_IN);
       
   727     anim->setDuration(1050 * Colors::animSpeedButtons);
       
   728     anim->setStartPos(QPointF(sw, Colors::contentStartY + Colors::contentHeight - 35));
       
   729     anim->setPosAt(0.10, QPointF(sw, Colors::contentStartY + Colors::contentHeight - 35));
       
   730     anim->setPosAt(0.30, QPointF(xOffset, Colors::contentStartY + Colors::contentHeight - 35));
       
   731     anim->setPosAt(0.35, QPointF(xOffset + 30, Colors::contentStartY + Colors::contentHeight - 35));
       
   732     anim->setPosAt(0.40, QPointF(xOffset, Colors::contentStartY + Colors::contentHeight - 35));
       
   733     anim->setPosAt(0.45, QPointF(xOffset + 5, Colors::contentStartY + Colors::contentHeight - 35));
       
   734     anim->setPosAt(0.50, QPointF(xOffset, Colors::contentStartY + Colors::contentHeight - 35));
       
   735     anim->setPosAt(1.00, QPointF(xOffset, Colors::contentStartY + Colors::contentHeight - 26));
       
   736     movieIn->append(anim);
       
   737 
       
   738     // create out-animation:
       
   739     anim = new DemoItemAnimation(item, DemoItemAnimation::ANIM_OUT);
       
   740     anim->hideOnFinished = true;
       
   741     anim->setDuration(300 * Colors::animSpeedButtons);
       
   742     anim->setStartPos(QPointF(xOffset, Colors::contentStartY + Colors::contentHeight - 26));
       
   743     anim->setPosAt(1.0, QPointF(xOffset, sh));
       
   744     movieOut->append(anim);
       
   745 }
       
   746 
       
   747 void MenuManager::createInfo(DemoItem *item, const QString &name)
       
   748 {
       
   749     Movie *movie_in = this->score->insertMovie(name);
       
   750     Movie *movie_out = this->score->insertMovie(name + " -out");
       
   751     item->setZValue(8);
       
   752     item->setRecursiveVisible(false);
       
   753 
       
   754     float xOffset = 230.0f;
       
   755     DemoItemAnimation *infoIn = new DemoItemAnimation(item, DemoItemAnimation::ANIM_IN);
       
   756     infoIn->timeline->setCurveShape(QTimeLine::LinearCurve);
       
   757     infoIn->setDuration(650);
       
   758     infoIn->setStartPos(QPointF(this->window->scene->sceneRect().width(), Colors::contentStartY));
       
   759     infoIn->setPosAt(0.60, QPointF(xOffset, Colors::contentStartY));
       
   760     infoIn->setPosAt(0.70, QPointF(xOffset + 20, Colors::contentStartY));
       
   761     infoIn->setPosAt(0.80, QPointF(xOffset, Colors::contentStartY));
       
   762     infoIn->setPosAt(0.90, QPointF(xOffset + 7, Colors::contentStartY));
       
   763     infoIn->setPosAt(1.00, QPointF(xOffset, Colors::contentStartY));
       
   764     movie_in->append(infoIn);
       
   765 
       
   766     DemoItemAnimation *infoOut = new DemoItemAnimation(item, DemoItemAnimation::ANIM_OUT);
       
   767     infoOut->timeline->setCurveShape(QTimeLine::EaseInCurve);
       
   768     infoOut->setDuration(300);
       
   769     infoOut->hideOnFinished = true;
       
   770     infoOut->setStartPos(QPointF(xOffset, Colors::contentStartY));
       
   771     infoOut->setPosAt(1.0, QPointF(-600, Colors::contentStartY));
       
   772     movie_out->append(infoOut);
       
   773 }
       
   774 
       
   775 void MenuManager::createTicker()
       
   776 {
       
   777     if (!Colors::noTicker){
       
   778         Movie *movie_in = this->score->insertMovie("ticker");
       
   779         Movie *movie_out = this->score->insertMovie("ticker -out");
       
   780         Movie *movie_activate = this->score->insertMovie("ticker -activate");
       
   781         Movie *movie_deactivate = this->score->insertMovie("ticker -deactivate");
       
   782 
       
   783         this->ticker = new ItemCircleAnimation(this->window->scene, 0);
       
   784         this->ticker->setZValue(50);
       
   785         this->ticker->hide();
       
   786 
       
   787         // Move ticker in:
       
   788         int qtendpos = 485;
       
   789         int qtPosY = 120;
       
   790         this->tickerInAnim = new DemoItemAnimation(this->ticker, DemoItemAnimation::ANIM_IN);
       
   791         this->tickerInAnim->setDuration(500);
       
   792         this->tickerInAnim->setStartPos(QPointF(this->window->scene->sceneRect().width(), Colors::contentStartY + qtPosY));
       
   793         this->tickerInAnim->setPosAt(0.60, QPointF(qtendpos, Colors::contentStartY + qtPosY));
       
   794         this->tickerInAnim->setPosAt(0.70, QPointF(qtendpos + 30, Colors::contentStartY + qtPosY));
       
   795         this->tickerInAnim->setPosAt(0.80, QPointF(qtendpos, Colors::contentStartY + qtPosY));
       
   796         this->tickerInAnim->setPosAt(0.90, QPointF(qtendpos + 5, Colors::contentStartY + qtPosY));
       
   797         this->tickerInAnim->setPosAt(1.00, QPointF(qtendpos, Colors::contentStartY + qtPosY));
       
   798         movie_in->append(this->tickerInAnim);
       
   799 
       
   800         // Move ticker out:
       
   801         DemoItemAnimation *qtOut = new DemoItemAnimation(this->ticker, DemoItemAnimation::ANIM_OUT);
       
   802         qtOut->hideOnFinished = true;
       
   803         qtOut->setDuration(500);
       
   804         qtOut->setStartPos(QPointF(qtendpos, Colors::contentStartY + qtPosY));
       
   805         qtOut->setPosAt(1.00, QPointF(this->window->scene->sceneRect().width() + 700, Colors::contentStartY + qtPosY));
       
   806         movie_out->append(qtOut);
       
   807 
       
   808         // Move ticker in on activate:
       
   809         DemoItemAnimation *qtActivate = new DemoItemAnimation(this->ticker);
       
   810         qtActivate->setDuration(400);
       
   811         qtActivate->setStartPos(QPointF(this->window->scene->sceneRect().width(), Colors::contentStartY + qtPosY));
       
   812         qtActivate->setPosAt(0.60, QPointF(qtendpos, Colors::contentStartY + qtPosY));
       
   813         qtActivate->setPosAt(0.70, QPointF(qtendpos + 30, Colors::contentStartY + qtPosY));
       
   814         qtActivate->setPosAt(0.80, QPointF(qtendpos, Colors::contentStartY + qtPosY));
       
   815         qtActivate->setPosAt(0.90, QPointF(qtendpos + 5, Colors::contentStartY + qtPosY));
       
   816         qtActivate->setPosAt(1.00, QPointF(qtendpos, Colors::contentStartY + qtPosY));
       
   817         movie_activate->append(qtActivate);
       
   818 
       
   819         // Move ticker out on deactivate:
       
   820         DemoItemAnimation *qtDeactivate = new DemoItemAnimation(this->ticker);
       
   821         qtDeactivate->hideOnFinished = true;
       
   822         qtDeactivate->setDuration(400);
       
   823         qtDeactivate->setStartPos(QPointF(qtendpos, Colors::contentStartY + qtPosY));
       
   824         qtDeactivate->setPosAt(1.00, QPointF(qtendpos, 800));
       
   825         movie_deactivate->append(qtDeactivate);
       
   826     }
       
   827 }
       
   828 
       
   829 void MenuManager::createUpnDownButtons()
       
   830 {
       
   831     float xOffset = 15.0f;
       
   832     float yOffset = 450.0f;
       
   833 
       
   834     this->upButton = new TextButton("", TextButton::LEFT, MenuManager::UP, this->window->scene, 0, TextButton::UP);
       
   835     this->upButton->prepare();
       
   836     this->upButton->setPos(xOffset, yOffset);
       
   837     this->upButton->setState(TextButton::DISABLED);
       
   838 
       
   839     this->downButton = new TextButton("", TextButton::LEFT, MenuManager::DOWN, this->window->scene, 0, TextButton::DOWN);
       
   840     this->downButton->prepare();
       
   841     this->downButton->setPos(xOffset + 10 + this->downButton->sceneBoundingRect().width(), yOffset);
       
   842 
       
   843     Movie *movieShake = this->score->insertMovie("upndown -shake");
       
   844 
       
   845     DemoItemAnimation *shakeAnim = new DemoItemAnimation(this->upButton, DemoItemAnimation::ANIM_UNSPECIFIED);
       
   846     shakeAnim->timeline->setCurveShape(QTimeLine::LinearCurve);
       
   847     shakeAnim->setDuration(650);
       
   848     shakeAnim->setStartPos(this->upButton->pos());
       
   849     shakeAnim->setPosAt(0.60, this->upButton->pos());
       
   850     shakeAnim->setPosAt(0.70, this->upButton->pos() + QPointF(-2, 0));
       
   851     shakeAnim->setPosAt(0.80, this->upButton->pos() + QPointF(1, 0));
       
   852     shakeAnim->setPosAt(0.90, this->upButton->pos() + QPointF(-1, 0));
       
   853     shakeAnim->setPosAt(1.00, this->upButton->pos());
       
   854     movieShake->append(shakeAnim);
       
   855 
       
   856     shakeAnim = new DemoItemAnimation(this->downButton, DemoItemAnimation::ANIM_UNSPECIFIED);
       
   857     shakeAnim->timeline->setCurveShape(QTimeLine::LinearCurve);
       
   858     shakeAnim->setDuration(650);
       
   859     shakeAnim->setStartPos(this->downButton->pos());
       
   860     shakeAnim->setPosAt(0.60, this->downButton->pos());
       
   861     shakeAnim->setPosAt(0.70, this->downButton->pos() + QPointF(-5, 0));
       
   862     shakeAnim->setPosAt(0.80, this->downButton->pos() + QPointF(-3, 0));
       
   863     shakeAnim->setPosAt(0.90, this->downButton->pos() + QPointF(-1, 0));
       
   864     shakeAnim->setPosAt(1.00, this->downButton->pos());
       
   865     movieShake->append(shakeAnim);
       
   866 }
       
   867 
       
   868 void MenuManager::createBackButton()
       
   869 {
       
   870     Movie *backIn = this->score->insertMovie("back -in");
       
   871     Movie *backOut = this->score->insertMovie("back -out");
       
   872     Movie *backShake = this->score->insertMovie("back -shake");
       
   873     createLowLeftButton(QLatin1String("Back"), ROOT, backIn, backOut, backShake, Colors::rootMenuName);
       
   874 }