examples/tools/qtdemo/launcher.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** Copyright (C) 2005-2006 Trolltech ASA. All rights reserved.
00004 **
00005 ** This file is part of the example classes of the Qt Toolkit.
00006 **
00007 ** This file may be used under the terms of the GNU General Public
00008 ** License version 2.0 as published by the Free Software Foundation
00009 ** and appearing in the file LICENSE.GPL included in the packaging of
00010 ** this file.  Please review the following information to ensure GNU
00011 ** General Public Licensing requirements will be met:
00012 ** http://www.trolltech.com/products/qt/opensource.html
00013 **
00014 ** If you are unsure which license is appropriate for your use, please
00015 ** review the following information:
00016 ** http://www.trolltech.com/products/qt/licensing.html or contact the
00017 ** sales department at sales@trolltech.com.
00018 **
00019 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00020 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00021 **
00022 ****************************************************************************/
00023 
00024 #include <QtGui>
00025 #include <QDomDocument>
00026 #include <QtAssistant/QAssistantClient>
00027 
00028 #include "displayshape.h"
00029 #include "displaywidget.h"
00030 #include "launcher.h"
00031 
00032 Launcher::Launcher(QWidget *parent)
00033     : QMainWindow(parent)
00034 {
00035     titleFont = font();
00036     titleFont.setWeight(QFont::Bold);
00037     buttonFont = font();
00038     fontRatio = 0.8;
00039     documentFont = font();
00040     inFullScreenResize = false;
00041     currentCategory = "[starting]";
00042 
00043     QAction *parentPageAction1 = new QAction(tr("Show Parent Page"), this);
00044     QAction *parentPageAction2 = new QAction(tr("Show Parent Page"), this);
00045     QAction *parentPageAction3 = new QAction(tr("Show Parent Page"), this);
00046     parentPageAction1->setShortcut(QKeySequence(tr("Escape")));
00047     parentPageAction2->setShortcut(QKeySequence(tr("Backspace")));
00048     parentPageAction3->setShortcut(QKeySequence(tr("Alt+Left")));
00049 
00050     QAction *fullScreenAction = new QAction(tr("Toggle &Full Screen"), this);
00051     fullScreenAction->setShortcut(QKeySequence(tr("Ctrl+F")));
00052 
00053     QAction *exitAction = new QAction(tr("E&xit"), this);
00054     exitAction->setShortcut(QKeySequence(tr("Ctrl+Q")));
00055 
00056     connect(parentPageAction1, SIGNAL(triggered()), this, SIGNAL(showPage()));
00057     connect(parentPageAction2, SIGNAL(triggered()), this, SIGNAL(showPage()));
00058     connect(parentPageAction3, SIGNAL(triggered()), this, SIGNAL(showPage()));
00059     connect(fullScreenAction, SIGNAL(triggered()),
00060             this, SLOT(toggleFullScreen()));
00061     connect(exitAction, SIGNAL(triggered()), this, SLOT(close()));
00062 
00063     display = new DisplayWidget;
00064 
00065     addAction(parentPageAction1);
00066     addAction(parentPageAction2);
00067     addAction(parentPageAction3);
00068     addAction(fullScreenAction);
00069     addAction(exitAction);
00070 
00071     slideshowTimer = new QTimer(this);
00072     slideshowTimer->setInterval(5000);
00073     resizeTimer = new QTimer(this);
00074     resizeTimer->setSingleShot(true);
00075     connect(resizeTimer, SIGNAL(timeout()), this, SLOT(redisplayWindow()));
00076 
00077     assistant = new QAssistantClient(
00078         QLibraryInfo::location(QLibraryInfo::BinariesPath), this);
00079 
00080     connect(display, SIGNAL(actionRequested(const QString &)),
00081             this, SLOT(executeAction(const QString &)));
00082     connect(display, SIGNAL(categoryRequested(const QString &)),
00083             this, SLOT(showExamples(const QString &)));
00084     connect(display, SIGNAL(documentationRequested(const QString &)),
00085             this, SLOT(showExampleDocumentation(const QString &)));
00086     connect(display, SIGNAL(exampleRequested(const QString &)),
00087             this, SLOT(showExampleSummary(const QString &)));
00088 
00089     connect(display, SIGNAL(launchRequested(const QString &)),
00090             this, SLOT(launchExample(const QString &)));
00091 
00092     connect(this, SIGNAL(showPage()), this, SLOT(showParentPage()),
00093             Qt::QueuedConnection);
00094     connect(this, SIGNAL(windowResized()), this, SLOT(redisplayWindow()),
00095             Qt::QueuedConnection);
00096 
00097     setCentralWidget(display);
00098     setMaximumSize(QApplication::desktop()->screenGeometry().size());
00099     setWindowTitle(tr("Qt Examples and Demos"));
00100     setWindowIcon(QPixmap(":/images/qt4-logo.png"));
00101 }
00102 
00103 bool Launcher::setup()
00104 {
00105     documentationDir = QDir(QLibraryInfo::location(
00106                             QLibraryInfo::DocumentationPath));
00107 
00108     if (!documentationDir.cd("html")) {
00109         // Failed to find the HTML documentation.
00110         // We can continue without it.
00111         QMessageBox::warning(this, tr("No Documentation Found"),
00112             tr("I could not find the Qt documentation."),
00113             QMessageBox::Cancel);
00114     }
00115 
00116     imagesDir = documentationDir;
00117     if (!imagesDir.cd("images")) {
00118         // Failed to find the accompanying images for the documentation.
00119         // We can continue without them.
00120         QMessageBox::warning(this, tr("No Images Found"),
00121             tr("I could not find any images for the Qt documentation."),
00122             QMessageBox::Cancel);
00123     }
00124 
00125     maximumLabels = 0;
00126 
00127     demosDir = QDir(QLibraryInfo::location(QLibraryInfo::DemosPath));
00128     int demoCategories = readInfo(":/demos.xml", demosDir);
00129 
00130     examplesDir = QDir(QLibraryInfo::location(QLibraryInfo::ExamplesPath));
00131     int exampleCategories = readInfo(":/examples.xml", examplesDir);
00132 
00133     if (demoCategories + exampleCategories <= 0) {
00134         // Failed to find the examples.
00135         QMessageBox::warning(this, tr("No Examples or Demos found"),
00136             tr("I could not find any Qt examples or demos.\n"
00137                "Please ensure that Qt is installed correctly."),
00138             QMessageBox::Cancel);
00139         return false;
00140     }
00141 
00142     maximumLabels = qMax(demoCategories + exampleCategories, maximumLabels);
00143 
00144     // For example menus, remember that the menu has to include a Back button.
00145     foreach (QString category, categories)
00146         maximumLabels = qMax(examples[category].size() + 1, maximumLabels);
00147 
00148     QString mainDescription = categoryDescriptions["[main]"];
00149     if (!mainDescription.isEmpty())
00150         mainDescription += tr("\n");
00151 
00152     categoryDescriptions["[main]"] = mainDescription + tr(
00153         "<p>Press <b>Escape</b>, <b>Backspace</b>, or <b>%1</b> to "
00154         "return to a previous menu.</p>\n"
00155         "<p>Press <b>%2</b> to switch between normal and full screen "
00156         "modes.</p>\n"
00157         "<p>Use <b>%3</b> to exit the launcher.</p>").arg(QString(
00158             QKeySequence(tr("Alt+Left")))).arg(QString(
00159             QKeySequence(tr("Ctrl+F")))).arg(QString(
00160             QKeySequence(tr("Ctrl+Q"))));
00161 
00162     emit showPage();
00163     return true;
00164 }
00165 
00166 void Launcher::findDescriptionAndImages(const QString &uniqueName,
00167                                         const QString &docName)
00168 {
00169     if (documentationDir.exists(docName)) {
00170         exampleDetails[uniqueName]["document path"] = \
00171             documentationDir.absoluteFilePath(docName);
00172 
00173         QDomDocument exampleDoc;
00174         QFile exampleFile(exampleDetails[uniqueName]["document path"]);
00175         exampleDoc.setContent(&exampleFile);
00176 
00177         QDomNodeList paragraphs = exampleDoc.elementsByTagName("p");
00178         QString description;
00179 
00180         for (int p = 0; p < int(paragraphs.length()); ++p) {
00181             QDomNode descriptionNode = paragraphs.item(p);
00182             description = readExampleDescription(descriptionNode);
00183 
00184             if (description.indexOf(QRegExp(QString(
00185                 "((The|This) )?(%1 )?.*(example|demo)").arg(
00186                     exampleDetails[uniqueName]["name"]),
00187                 Qt::CaseInsensitive)) != -1) {
00188                 exampleDetails[uniqueName]["description"] = description;
00189                 break;
00190             }
00191         }
00192 
00193         QDomNodeList images = exampleDoc.elementsByTagName("img");
00194         QStringList imageFiles;
00195 
00196         for (int i = 0; i < int(images.length()); ++i) {
00197             QDomElement imageElement = images.item(i).toElement();
00198             QString source = imageElement.attribute("src");
00199             if (!source.contains("-logo"))
00200                 imageFiles.append(documentationDir.absoluteFilePath(source));
00201         }
00202 
00203         if (imageFiles.size() > 0)
00204             imagePaths[uniqueName] = imageFiles;
00205     }
00206 }
00207 
00208 int Launcher::readInfo(const QString &resource, const QDir &dir)
00209 {
00210     QFile categoriesFile(resource);
00211     QDomDocument document;
00212     document.setContent(&categoriesFile);
00213     QDomElement documentElement = document.documentElement();
00214     QDomNodeList categoryNodes = documentElement.elementsByTagName("category");
00215 
00216     readCategoryDescription(dir, "[main]");
00217     qtLogo.load(imagesDir.absoluteFilePath(":/images/qt4-logo.png"));
00218     trolltechLogo.load(imagesDir.absoluteFilePath(":/images/trolltech-logo.png"));
00219 
00220     for (int i = 0; i < int(categoryNodes.length()); ++i) {
00221 
00222         QDomNode categoryNode = categoryNodes.item(i);
00223         QDomElement element = categoryNode.toElement();
00224         QString categoryName = element.attribute("name");
00225         QString categoryDirName = element.attribute("dirname");
00226         QString categoryDocName = element.attribute("docname");
00227         QString categoryColor = element.attribute("color", "#f0f0f0");
00228 
00229         QDir categoryDir = dir;
00230         if (categoryDir.cd(categoryDirName)) {
00231 
00232             readCategoryDescription(categoryDir, categoryName);
00233 
00234             examples[categoryName] = QStringList();
00235 
00236             QDomNodeList exampleNodes = element.elementsByTagName("example");
00237             maximumLabels = qMax(maximumLabels, int(exampleNodes.length()));
00238 
00239             for (int j = 0; j < int(exampleNodes.length()); ++j) {
00240 
00241                 QDir exampleDir = categoryDir;
00242 
00243                 QDomNode exampleNode = exampleNodes.item(j);
00244                 element = exampleNode.toElement();
00245                 QString exampleName = element.attribute("name");
00246                 QString exampleFileName = element.attribute("filename");
00247                 QString exampleDirName = element.attribute("dirname");
00248 
00249                 examples[categoryName].append(exampleName);
00250 
00251                 QString uniqueName = categoryName+"-"+exampleName;
00252                 exampleOptions[uniqueName] = QMap<QString,QString>();
00253                 exampleDetails[uniqueName] = QMap<QString,QString>();
00254 
00255                 QString docName;
00256                 if (!categoryDocName.isEmpty())
00257                     docName = categoryDocName+"-"+exampleFileName+".html";
00258                 else
00259                     docName = categoryDirName+"-"+exampleFileName+".html";
00260 
00261                 exampleDetails[uniqueName]["name"] = exampleName;
00262                 findDescriptionAndImages(uniqueName, docName);
00263 
00264                 exampleOptions[uniqueName]["changedirectory"] = element.attribute("changedirectory", "true");
00265                 exampleOptions[uniqueName]["color"] = element.attribute("color", "#f0f0f0");
00266 
00267                 if (!exampleDirName.isEmpty() && !exampleDir.cd(exampleDirName))
00268                     continue;
00269 
00270                 if (element.attribute("executable", "true") != "true")
00271                     continue;
00272 
00273                 if (exampleDir.cd(exampleFileName)) {
00274                     QString examplePath = findExecutable(exampleDir);
00275                     if (!examplePath.isNull()) {
00276                         exampleDetails[uniqueName]["absolute path"] = exampleDir.absolutePath();
00277                         exampleDetails[uniqueName]["path"] = examplePath;
00278                     }
00279                 }
00280             }
00281 
00282             categories.append(categoryName);
00283             categoryColors[categoryName] = categoryColor;
00284         }
00285     }
00286 
00287     return categories.size();
00288 }
00289 
00290 QString Launcher::findExecutable(const QDir &dir) const
00291 {
00292     QDir parentDir = dir;
00293     parentDir.cdUp();
00294 
00295     QFileInfo releaseDir(dir, "release");
00296     if (releaseDir.isDir()) {
00297         QDir currentDir(releaseDir.absoluteFilePath());
00298         QString path = findExecutable(currentDir);
00299         if (!path.isEmpty())
00300             return path;
00301     }
00302 
00303     foreach (QFileInfo info, dir.entryInfoList(QDir::Dirs)) {
00304         if (info.fileName().endsWith(".app"))
00305             return info.absoluteFilePath();
00306         QDir currentDir(info.absoluteFilePath());
00307         if (currentDir != dir && currentDir != parentDir &&
00308             currentDir.dirName() != "plugins") {
00309             QString path = findExecutable(currentDir);
00310             if (!path.isNull())
00311                 return path;
00312         }
00313     }
00314         
00315     foreach (QFileInfo info, dir.entryInfoList(QDir::Files)) {
00316         if (info.isExecutable())
00317             return info.absoluteFilePath();
00318     }
00319     return QString();
00320 }
00321 
00322 void Launcher::readCategoryDescription(const QDir &categoryDir,
00323                                        const QString &categoryName)
00324 {
00325     if (categoryDir.exists("README")) {
00326         QFile file(categoryDir.absoluteFilePath("README"));
00327         if (!file.open(QFile::ReadOnly))
00328             return;
00329 
00330         QTextStream inputStream(&file);
00331 
00332         QStringList paragraphs;
00333         QStringList currentPara;
00334         bool openQuote = true;
00335 
00336         while (!inputStream.atEnd()) {
00337             QString line = inputStream.readLine();
00338             int at = 0;
00339             while ((at = line.indexOf("\"", at)) != -1) {
00340                 if (openQuote)
00341                     line[at] = QChar::Punctuation_InitialQuote;
00342                 else
00343                     line[at] = QChar::Punctuation_FinalQuote;
00344                 openQuote = !openQuote;
00345             }
00346 
00347             if (!line.trimmed().isEmpty()) {
00348                 currentPara.append(line.trimmed());
00349             } else if (!currentPara.isEmpty()) {
00350                 paragraphs.append(currentPara.join(" "));
00351                 currentPara.clear();
00352             } else
00353                 break;
00354         }
00355 
00356         if (!currentPara.isEmpty())
00357             paragraphs.append(currentPara.join(" "));
00358 
00359         categoryDescriptions[categoryName] = "<p>" + \
00360             paragraphs.join("\n</p><p>") + "</p>\n";
00361     }
00362 }
00363 
00364 QString Launcher::readExampleDescription(const QDomNode &parentNode) const
00365 {
00366     QString description;
00367     QDomNode node = parentNode.firstChild();
00368 
00369     while (!node.isNull()) {
00370         QString beginTag;
00371         QString endTag;
00372         if (node.isText())
00373             description += node.nodeValue();
00374         else if (node.hasChildNodes()) {
00375             if (node.nodeName() == "b") {
00376                 beginTag = "<b>";
00377                 endTag = "</b>";
00378             } else if (node.nodeName() == "a") {
00379                 beginTag = "<font color=\"blue\">";
00380                 endTag = "</font>";
00381             } else if (node.nodeName() == "i") {
00382                 beginTag = "<i>";
00383                 endTag = "</i>";
00384             } else if (node.nodeName() == "tt") {
00385                 beginTag = "<tt>";
00386                 endTag = "</tt>";
00387             }
00388             description += beginTag + readExampleDescription(node) + endTag;
00389         }
00390 
00391         node = node.nextSibling();
00392     }
00393 
00394     return description;
00395 }
00396 
00397 void Launcher::launchExample(const QString &uniqueName)
00398 {
00399     if (runningExamples.contains(uniqueName))
00400         return;
00401 
00402     QProcess *process = new QProcess(this);
00403     connect(process, SIGNAL(finished(int)), this, SLOT(enableLaunching()));
00404 
00405 #ifdef Q_OS_WIN
00406     //make sure it finds the dlls on windows
00407     QString curpath = QString::fromLocal8Bit(qgetenv("PATH").constData());
00408     QString newpath = QString("PATH=%1;%2").arg(
00409         QLibraryInfo::location(QLibraryInfo::BinariesPath), curpath);
00410     process->setEnvironment(QStringList(newpath));
00411 #endif
00412 
00413     runningExamples.append(uniqueName);
00414     runningProcesses[process] = uniqueName;
00415 
00416     if (exampleOptions[uniqueName]["changedirectory"] == "true")
00417         process->setWorkingDirectory(exampleDetails[uniqueName]["absolute path"]);
00418 
00419     process->start(exampleDetails[uniqueName]["path"]);
00420 
00421     if (process->state() == QProcess::Starting)
00422         slideshowTimer->stop();
00423 }
00424 
00425 void Launcher::enableLaunching()
00426 {
00427     QProcess *process = static_cast<QProcess*>(sender());
00428     QString example = runningProcesses.take(process);
00429     process->deleteLater();
00430     runningExamples.removeAll(example);
00431 
00432     if (example == currentExample) {
00433         for (int i = 0; i < display->shapesCount(); ++i) {
00434             DisplayShape *shape = display->shape(i);
00435             if (shape->metaData("launch").toString() == example) {
00436                 shape->setMetaData("fade", 15);
00437                 display->enableUpdates();
00438             }
00439         }
00440         slideshowTimer->start();
00441     }
00442 }
00443 
00444 void Launcher::executeAction(const QString &action)
00445 {
00446     if (action == "parent")
00447         showParentPage();
00448     else if (action == "exit") {
00449         if (runningExamples.size() == 0) {
00450             connect(display, SIGNAL(displayEmpty()), this, SLOT(close()));
00451             display->reset();
00452         } else
00453             close();
00454     }
00455 }
00456 
00457 void Launcher::closeEvent(QCloseEvent *event)
00458 {
00459     if (runningExamples.size() > 0) {
00460         if (QMessageBox::warning(this, tr("Examples Running"),
00461                 tr("There are examples running. Do you really want to exit?"),
00462                 QMessageBox::Yes|QMessageBox::No) == QMessageBox::No)
00463             event->ignore();
00464             return;
00465     }
00466 
00467     foreach (QProcess *example, runningProcesses.keys()) {
00468         example->terminate();
00469         example->waitForFinished(1000);
00470     }
00471 
00472     qDeleteAll(runningProcesses.keys());
00473     resizeTimer->stop();
00474     slideshowTimer->stop();
00475 }
00476 
00477 void Launcher::showParentPage()
00478 {
00479     slideshowTimer->stop();
00480     disconnect(slideshowTimer, SIGNAL(timeout()), this, 0);
00481 
00482     if (!currentExample.isEmpty()) {
00483         currentExample = "";
00484         redisplayWindow();
00485     } else if (!currentCategory.isEmpty()) {
00486         currentCategory = "";
00487         redisplayWindow();
00488     }
00489 }
00490 
00491 void Launcher::newPage()
00492 {
00493     slideshowTimer->stop();
00494     disconnect(slideshowTimer, SIGNAL(timeout()), this, 0);
00495     disconnect(display, SIGNAL(displayEmpty()), this, 0);
00496 }
00497 
00498 DisplayShape *Launcher::addTitle(const QString &title, qreal verticalMargin)
00499 {
00500     QPointF titlePosition = QPointF(0.0, 2*verticalMargin);
00501 
00502     DisplayShape *newTitle = new TitleShape(title, titleFont,
00503         QPen(Qt::white), titlePosition,
00504         QSizeF(0.5 * width(), 2*verticalMargin),
00505         Qt::AlignHCenter | Qt::AlignTop);
00506 
00507     newTitle->setPosition(QPointF(-newTitle->rect().width(), titlePosition.y()));
00508     newTitle->setTarget(QPointF(0.25*width(), titlePosition.y()));
00509     newTitle->setMetaData("fade", 15);
00510 
00511     display->appendShape(newTitle);
00512 
00513     return newTitle;
00514 }
00515 
00516 DisplayShape *Launcher::addTitleBackground(DisplayShape *titleShape)
00517 {
00518     QPainterPath backgroundPath;
00519     backgroundPath.addRect(0, -titleShape->rect().height()*0.3,
00520                            width(), titleShape->rect().height()*1.6);
00521 
00522     DisplayShape *titleBackground = new PanelShape(backgroundPath,
00523         QBrush(QColor("#a6ce39")), QBrush(QColor("#a6ce39")), Qt::NoPen,
00524             QPointF(width(), titleShape->position().y()),
00525             backgroundPath.boundingRect().size());
00526 
00527     titleBackground->setTarget(QPointF(0.0, titleShape->position().y()));
00528 
00529     display->insertShape(0, titleBackground);
00530 
00531     return titleBackground;
00532 }
00533 
00534 void Launcher::addVersionAndCopyright(const QRectF &rect)
00535 {
00536     DisplayShape *versionCaption = new TitleShape(
00537         QString("Qt %1").arg(QT_VERSION_STR), font(),
00538         QPen(QColor(0,0,0,0)),
00539         QPointF(rect.center().x(), rect.top()),
00540         QSizeF(0.5*rect.width(), rect.height()),
00541         Qt::AlignRight | Qt::AlignVCenter);
00542 
00543     versionCaption->setMetaData("fade", 15);
00544     display->appendShape(versionCaption);
00545 
00546     DisplayShape *copyrightCaption = new TitleShape(
00547         QString("Copyright \xa9 2005-2006 Trolltech ASA"), font(),
00548         QPen(QColor(0,0,0,0)),
00549         rect.topLeft(), QSizeF(0.5*rect.width(), rect.height()),
00550         Qt::AlignLeft | Qt::AlignVCenter);
00551 
00552     copyrightCaption->setMetaData("fade", 15);
00553     display->appendShape(copyrightCaption);
00554 }
00555 
00556 void Launcher::fadeShapes()
00557 {
00558     for (int i = 0; i < display->shapesCount(); ++i) {
00559         DisplayShape *shape = display->shape(i);
00560 
00561         shape->setMetaData("fade", -15);
00562         shape->setMetaData("fade minimum", 0);
00563     }
00564 }
00565 
00566 void Launcher::showCategories()
00567 {
00568     newPage();
00569     fadeShapes();
00570     currentCategory = "";
00571     currentExample = "";
00572 
00573     qreal horizontalMargin = 0.025*width();
00574     qreal verticalMargin = 0.025*height();
00575 
00576     DisplayShape *title = new TitleShape(tr("Qt Examples and Demos"),
00577         titleFont, QPen(QColor("#a6ce39")), QPointF(),
00578         QSizeF(0.5*width(), 4*verticalMargin));
00579 
00580     title->setPosition(QPointF(width()/2 - title->rect().width()/2,
00581                                -title->rect().height()));
00582     title->setTarget(QPointF(title->position().x(), verticalMargin));
00583 
00584     display->appendShape(title);
00585 
00586     qreal topMargin = 6*verticalMargin;
00587     qreal bottomMargin = height() - 3.2*verticalMargin;
00588     qreal space = bottomMargin - topMargin;
00589     qreal step = qMin(title->rect().height() / fontRatio,
00590                       space/qreal(maximumLabels));
00591     qreal textHeight = fontRatio * step;
00592 
00593     QPointF startPosition = QPointF(0.0, topMargin);
00594     QSizeF maxSize(10.8*horizontalMargin, textHeight);
00595     qreal maxWidth = 0.0;
00596 
00597     QList<DisplayShape*> newShapes;
00598 
00599     foreach (QString category, categories) {
00600 
00601         DisplayShape *caption = new TitleShape(category, font(), QPen(),
00602             startPosition, maxSize);
00603         caption->setPosition(QPointF(-caption->rect().width(),
00604                                      caption->position().y()));
00605         caption->setTarget(QPointF(2*horizontalMargin, caption->position().y()));
00606 
00607         newShapes.append(caption);
00608 
00609         startPosition += QPointF(0.0, step);
00610         maxWidth = qMax(maxWidth, caption->rect().width());
00611     }
00612 
00613     DisplayShape *exitButton = new TitleShape(tr("Exit"), font(),
00614         QPen(Qt::white), startPosition, maxSize);
00615 
00616     exitButton->setTarget(QPointF(2*horizontalMargin, exitButton->position().y()));
00617     newShapes.append(exitButton);
00618 
00619     startPosition = QPointF(width(), topMargin);
00620     qreal extra = (step - textHeight)/4;
00621 
00622     QPainterPath backgroundPath;
00623     backgroundPath.addRect(-2*extra, -extra, maxWidth + 4*extra, textHeight + 2*extra);
00624 
00625     foreach (QString category, categories) {
00626 
00627         DisplayShape *background = new PanelShape(backgroundPath,
00628             QBrush(categoryColors[category]), QBrush(QColor("#e0e0ff")),
00629             Qt::NoPen, startPosition,
00630             QSizeF(maxWidth + 4*extra, textHeight + 2*extra));
00631 
00632         background->setMetaData("category", category);
00633         background->setInteractive(true);
00634         background->setTarget(QPointF(2*horizontalMargin,
00635                                       background->position().y()));
00636         display->insertShape(0, background);
00637         startPosition += QPointF(0.0, step);
00638     }
00639 
00640     QPainterPath exitPath;
00641     exitPath.moveTo(-2*extra, -extra);
00642     exitPath.lineTo(-8*extra, textHeight/2);
00643     exitPath.lineTo(-extra, textHeight + extra);
00644     exitPath.lineTo(maxWidth + 2*extra, textHeight + extra);
00645     exitPath.lineTo(maxWidth + 2*extra, -extra);
00646     exitPath.closeSubpath();
00647 
00648     DisplayShape *exitBackground = new PanelShape(exitPath,
00649         QBrush(QColor("#a6ce39")), QBrush(QColor("#c7f745")), Qt::NoPen,
00650         startPosition, QSizeF(maxWidth + 10*extra, textHeight + 2*extra));
00651 
00652     exitBackground->setMetaData("action", "exit");
00653     exitBackground->setInteractive(true);
00654     exitBackground->setTarget(QPointF(2*horizontalMargin,
00655                                       exitBackground->position().y()));
00656     display->insertShape(0, exitBackground);
00657 
00658     foreach (DisplayShape *caption, newShapes) {
00659         QPointF position = caption->target();
00660         QSizeF size = caption->rect().size();
00661         caption->setPosition(QPointF(-maxWidth, position.y()));
00662         display->appendShape(caption);
00663     }
00664 
00665     qreal leftMargin = 3*horizontalMargin + maxWidth;
00666     qreal rightMargin = width() - 3*horizontalMargin;
00667 
00668     DocumentShape *description = new DocumentShape(categoryDescriptions["[main]"],
00669         documentFont, QPointF(leftMargin, topMargin),
00670         QSizeF(rightMargin - leftMargin, space), 0);
00671 
00672     description->setMetaData("fade", 10);
00673     display->appendShape(description);
00674 
00675     qreal imageHeight = title->rect().height() + verticalMargin;
00676 
00677     qreal qtLength = qMin(imageHeight, title->rect().left()-3*horizontalMargin);
00678     QSizeF qtMaxSize = QSizeF(qtLength, qtLength);
00679 
00680     DisplayShape *qtShape = new ImageShape(qtLogo,
00681         QPointF(2*horizontalMargin-extra, -imageHeight), qtMaxSize, 0,
00682         Qt::AlignLeft | Qt::AlignVCenter);
00683 
00684     qtShape->setMetaData("fade", 15);
00685     qtShape->setTarget(QPointF(qtShape->rect().x(), verticalMargin));
00686     display->insertShape(0, qtShape);
00687 
00688     QSizeF trolltechMaxSize = QSizeF(
00689         width()-3*horizontalMargin-title->rect().right(), imageHeight);
00690 
00691     DisplayShape *trolltechShape = new ImageShape(trolltechLogo,
00692         QPointF(width()-2*horizontalMargin-trolltechMaxSize.width()+extra,
00693                 -imageHeight),
00694         trolltechMaxSize, 0, Qt::AlignRight | Qt::AlignVCenter);
00695 
00696     trolltechShape->setMetaData("fade", 15);
00697     trolltechShape->setTarget(QPointF(trolltechShape->rect().x(),
00698                                       verticalMargin));
00699     display->insertShape(0, trolltechShape);
00700 
00701     addVersionAndCopyright(QRectF(2*horizontalMargin,
00702                            height() - verticalMargin - textHeight,
00703                            width()-4*horizontalMargin, textHeight));
00704 }
00705 
00706 void Launcher::showExamples(const QString &category)
00707 {
00708     newPage();
00709     fadeShapes();
00710     currentCategory = category;
00711     currentExample = "";
00712 
00713     qreal horizontalMargin = 0.025*width();
00714     qreal verticalMargin = 0.025*height();
00715 
00716     DisplayShape *newTitle = addTitle(category, verticalMargin);
00717     addTitleBackground(newTitle);
00718 
00719     qreal topMargin = 6*verticalMargin;
00720     qreal bottomMargin = height() - 3.2*verticalMargin;
00721     qreal space = bottomMargin - topMargin;
00722     qreal step = qMin(newTitle->rect().height() / fontRatio,
00723                       space/qreal(maximumLabels));
00724     qreal textHeight = fontRatio * step;
00725 
00726     QPointF startPosition = QPointF(2*horizontalMargin, height() + topMargin);
00727     QPointF finishPosition = QPointF(2*horizontalMargin, topMargin);
00728     QSizeF maxSize(32*horizontalMargin, textHeight);
00729     qreal maxWidth = 0.0;
00730 
00731     foreach (QString example, examples[currentCategory]) {
00732 
00733         DisplayShape *caption = new TitleShape(example, font(), QPen(),
00734             startPosition, maxSize);
00735         caption->setTarget(finishPosition);
00736 
00737         display->appendShape(caption);
00738 
00739         startPosition += QPointF(0.0, step);
00740         finishPosition += QPointF(0.0, step);
00741         maxWidth = qMax(maxWidth, caption->rect().width());
00742     }
00743 
00744     DisplayShape *menuButton = new TitleShape(tr("Main Menu"), font(),
00745         QPen(Qt::white), startPosition, maxSize);
00746     menuButton->setTarget(finishPosition);
00747 
00748     display->appendShape(menuButton);
00749     maxWidth = qMax(maxWidth, menuButton->rect().width());
00750 
00751     startPosition = QPointF(width(), topMargin);
00752     qreal extra = (step - textHeight)/4;
00753 
00754     foreach (QString example, examples[currentCategory]) {
00755 
00756         QString uniqueName = currentCategory+"-"+example;
00757         QPainterPath path;
00758         path.addRect(-2*extra, -extra, maxWidth + 4*extra, textHeight + 2*extra);
00759 
00760         DisplayShape *background = new PanelShape(path,
00761             QBrush(QColor(exampleOptions[uniqueName]["color"])),
00762             QBrush(QColor("#e0e0ff")),
00763             Qt::NoPen, startPosition,
00764             QSizeF(maxWidth + 4*extra, textHeight + 2*extra));
00765 
00766         background->setMetaData("example", uniqueName);
00767         background->setInteractive(true);
00768         background->setTarget(QPointF(2*horizontalMargin,
00769                                       background->position().y()));
00770         display->insertShape(0, background);
00771         startPosition += QPointF(0.0, step);
00772     }
00773 
00774     QPainterPath backPath;
00775     backPath.moveTo(-2*extra, -extra);
00776     backPath.lineTo(-8*extra, textHeight/2);
00777     backPath.lineTo(-extra, textHeight + extra);
00778     backPath.lineTo(maxWidth + 2*extra, textHeight + extra);
00779     backPath.lineTo(maxWidth + 2*extra, -extra);
00780     backPath.closeSubpath();
00781 
00782     DisplayShape *buttonBackground = new PanelShape(backPath,
00783         QBrush(QColor("#a6ce39")), QBrush(QColor("#c7f745")), Qt::NoPen,
00784         startPosition, QSizeF(maxWidth + 10*extra, textHeight + 2*extra));
00785 
00786     buttonBackground->setMetaData("action", "parent");
00787     buttonBackground->setInteractive(true);
00788     buttonBackground->setTarget(QPointF(2*horizontalMargin,
00789                                         buttonBackground->position().y()));
00790     display->insertShape(0, buttonBackground);
00791 
00792     qreal leftMargin = 3*horizontalMargin + maxWidth;
00793     qreal rightMargin = width() - 3*horizontalMargin;
00794 
00795     DocumentShape *description = new DocumentShape(
00796         categoryDescriptions[currentCategory], documentFont,
00797         QPointF(leftMargin, topMargin), QSizeF(rightMargin - leftMargin, space),
00798         0);
00799 
00800     description->setMetaData("fade", 10);
00801 
00802     display->appendShape(description);
00803 
00804     addVersionAndCopyright(QRectF(2*horizontalMargin,
00805                            height() - verticalMargin - textHeight,
00806                            width()-4*horizontalMargin, textHeight));
00807 }
00808 
00809 void Launcher::showExampleDocumentation(const QString &uniqueName)
00810 {
00811     disconnect(display, SIGNAL(displayEmpty()), this, 0);
00812     currentExample = uniqueName;
00813 
00814     assistant->showPage(exampleDetails[uniqueName]["document path"]);
00815 }
00816 
00817 void Launcher::showExampleSummary(const QString &uniqueName)
00818 {
00819     newPage();
00820     fadeShapes();
00821     currentExample = uniqueName;
00822 
00823     qreal horizontalMargin = 0.025*width();
00824     qreal verticalMargin = 0.025*height();
00825 
00826     DisplayShape *newTitle = addTitle(exampleDetails[currentExample]["name"],
00827                                       verticalMargin);
00828     DisplayShape *titleBackground = addTitleBackground(newTitle);
00829 
00830     qreal topMargin = 2*verticalMargin + titleBackground->rect().bottom();
00831     qreal bottomMargin = height() - 8*verticalMargin;
00832     qreal space = bottomMargin - topMargin;
00833     qreal step = qMin(newTitle->rect().height() / fontRatio,
00834                       (bottomMargin + qreal(4.8)*verticalMargin - topMargin)
00835                       /qreal(maximumLabels));
00836     qreal textHeight = fontRatio * step;
00837 
00838     qreal leftMargin = 3*horizontalMargin;
00839     qreal rightMargin = width() - 3*horizontalMargin;
00840 
00841     if (exampleDetails[currentExample].contains("description")) {
00842         DocumentShape *description = new DocumentShape(
00843             exampleDetails[currentExample]["description"], documentFont,
00844             QPointF(leftMargin, topMargin),
00845             QSizeF(rightMargin-leftMargin, space), 0);
00846 
00847         description->setMetaData("fade", 10);
00848 
00849         description->setPosition(QPointF(description->position().x(),
00850             0.8*height() - description->rect().height()));
00851 
00852         display->appendShape(description);
00853         space = description->position().y() - topMargin - 2*verticalMargin;
00854     }
00855 
00856     if (imagePaths.contains(currentExample)) {
00857 
00858         QImage image(imagePaths[currentExample][0]);
00859 
00860         QSizeF imageMaxSize = QSizeF(width() - 8*horizontalMargin, space);
00861 
00862         currentFrame = new ImageShape(image,
00863             QPointF(width() - imageMaxSize.width()/2, topMargin),
00864             imageMaxSize);
00865 
00866         currentFrame->setMetaData("fade", 15);
00867         currentFrame->setTarget(QPointF(width()/2 - imageMaxSize.width()/2,
00868                                         topMargin));
00869 
00870         display->appendShape(currentFrame);
00871 
00872         if (imagePaths[currentExample].size() > 1) {
00873             connect(slideshowTimer, SIGNAL(timeout()),
00874                     this, SLOT(updateExampleSummary()));
00875 
00876             slideshowFrame = 0;
00877             slideshowTimer->start();
00878         }
00879     }
00880 
00881     QSizeF maxSize(0.3 * width(), 2*verticalMargin);
00882     leftMargin = 0.0;
00883     rightMargin = 0.0;
00884 
00885     if (true) {
00886         DisplayShape *backButton = new TitleShape(currentCategory, font(),
00887             QPen(Qt::white), QPointF(0.1*width(), height()), maxSize,
00888             Qt::AlignLeft | Qt::AlignTop);
00889         backButton->setTarget(QPointF(backButton->position().x(),
00890                                       height() - 5.2*verticalMargin));
00891 
00892         display->appendShape(backButton);
00893 
00894         qreal maxWidth = backButton->rect().width();
00895         qreal textHeight = backButton->rect().height();
00896         qreal extra = (3*verticalMargin - textHeight)/4;
00897 
00898         QPainterPath path;
00899         path.moveTo(-extra, -extra);
00900         path.lineTo(-4*extra, textHeight/2);
00901         path.lineTo(-extra, textHeight + extra);
00902         path.lineTo(maxWidth + 2*extra, textHeight + extra);
00903         path.lineTo(maxWidth + 2*extra, -extra);
00904         path.closeSubpath();
00905 
00906         DisplayShape *buttonBackground = new PanelShape(path,
00907             QBrush(QColor("#a6ce39")), QBrush(QColor("#c7f745")), Qt::NoPen,
00908             backButton->position(),
00909             QSizeF(maxWidth + 6*extra, textHeight + 2*extra));
00910 
00911         buttonBackground->setMetaData("category", currentCategory);
00912         buttonBackground->setInteractive(true);
00913         buttonBackground->setTarget(backButton->target());
00914 
00915         display->insertShape(0, buttonBackground);
00916 
00917         leftMargin = buttonBackground->rect().right();
00918     }
00919 
00920     if (exampleDetails[currentExample].contains("absolute path")) {
00921 
00922         DisplayShape *launchCaption = new TitleShape(tr("Launch"),
00923             font(), QPen(Qt::white), QPointF(0.0, 0.0), maxSize,
00924             Qt::AlignLeft | Qt::AlignTop);
00925         launchCaption->setPosition(QPointF(
00926             0.9*width() - launchCaption->rect().width(), height()));
00927         launchCaption->setTarget(QPointF(launchCaption->position().x(),
00928                                          height() - 5.2*verticalMargin));
00929 
00930         display->appendShape(launchCaption);
00931 
00932         qreal maxWidth = launchCaption->rect().width();
00933         qreal textHeight = launchCaption->rect().height();
00934         qreal extra = (3*verticalMargin - textHeight)/4;
00935 
00936         QPainterPath path;
00937         path.addRect(-2*extra, -extra, maxWidth + 4*extra, textHeight + 2*extra);
00938 
00939         QColor backgroundColor = QColor("#a63e39");
00940         QColor highlightedColor = QColor("#f95e56");
00941 
00942         DisplayShape *background = new PanelShape(path,
00943             QBrush(backgroundColor), QBrush(highlightedColor), Qt::NoPen,
00944             launchCaption->position(),
00945             QSizeF(maxWidth + 4*extra, textHeight + 2*extra));
00946 
00947         background->setMetaData("fade minimum", 120);
00948         background->setMetaData("launch", currentExample);
00949         background->setInteractive(true);
00950         background->setTarget(launchCaption->target());
00951 
00952         if (runningExamples.contains(currentExample)) {
00953             background->setMetaData("highlight", true);
00954             background->setMetaData("highlight scale", 0.99);
00955             background->animate();
00956             background->setMetaData("fade", -135);
00957             slideshowTimer->stop();
00958         }
00959 
00960         display->insertShape(0, background);
00961 
00962         rightMargin = background->rect().left();
00963     }
00964 
00965     if (exampleDetails[currentExample].contains("document path")) {
00966 
00967         DisplayShape *documentCaption = new TitleShape(tr("Show Documentation"),
00968             font(), QPen(Qt::white), QPointF(0.0, 0.0), maxSize,
00969             Qt::AlignLeft | Qt::AlignTop);
00970 
00971         if (rightMargin == 0.0) {
00972             documentCaption->setPosition(QPointF(
00973                 0.9*width() - documentCaption->rect().width(), height()));
00974         } else {
00975             documentCaption->setPosition(QPointF(
00976                 leftMargin/2 + rightMargin/2 - documentCaption->rect().width()/2,
00977                 height()));
00978         }
00979         documentCaption->setTarget(QPointF(documentCaption->position().x(),
00980                                            height() - 5.2*verticalMargin));
00981 
00982         display->appendShape(documentCaption);
00983 
00984         qreal maxWidth = documentCaption->rect().width();
00985         qreal textHeight = documentCaption->rect().height();
00986         qreal extra = (3*verticalMargin - textHeight)/4;
00987 
00988         QPainterPath path;
00989         path.addRect(-2*extra, -extra, maxWidth + 4*extra, textHeight + 2*extra);
00990 
00991         DisplayShape *background = new PanelShape(path,
00992             QBrush(QColor("#9c9cff")), QBrush(QColor("#cfcfff")), Qt::NoPen,
00993             documentCaption->position(),
00994             QSizeF(maxWidth + 4*extra, textHeight + 2*extra));
00995 
00996         background->setMetaData("fade minimum", 120);
00997         background->setMetaData("documentation", currentExample);
00998         background->setInteractive(true);
00999         background->setTarget(documentCaption->target());
01000 
01001         display->insertShape(0, background);
01002     }
01003 
01004     addVersionAndCopyright(QRectF(2*horizontalMargin,
01005                            height() - verticalMargin - textHeight,
01006                            width()-4*horizontalMargin, textHeight));
01007 }
01008 
01009 void Launcher::updateExampleSummary()
01010 {
01011     if (imagePaths.contains(currentExample)) {
01012 
01013         currentFrame->setMetaData("fade", -15);
01014         currentFrame->setTarget(currentFrame->position() - QPointF(0.5*width(),
01015                                 0));
01016 
01017         slideshowFrame = (slideshowFrame+1) % imagePaths[currentExample].size();
01018         QImage image(imagePaths[currentExample][slideshowFrame]);
01019 
01020         QSizeF imageSize = currentFrame->size();
01021         QPointF imagePosition = QPointF(width() - imageSize.width()/2,
01022                                         currentFrame->position().y());
01023 
01024         currentFrame = new ImageShape(image, imagePosition, imageSize);
01025         currentFrame->setMetaData("fade", 15);
01026         currentFrame->setTarget(QPointF(width()/2 - imageSize.width()/2,
01027                                         imagePosition.y()));
01028 
01029         display->appendShape(currentFrame);
01030     }
01031 }
01032 
01033 void Launcher::toggleFullScreen()
01034 {
01035     if (inFullScreenResize)
01036         return;
01037 
01038     inFullScreenResize = true;
01039 
01040     connect(display, SIGNAL(displayEmpty()), this, SLOT(resizeWindow()),
01041             Qt::QueuedConnection);
01042     display->reset();
01043 }
01044 
01045 void Launcher::resizeWindow()
01046 {
01047     disconnect(display, SIGNAL(displayEmpty()), this, 0);
01048 
01049     if (isFullScreen())
01050         showNormal();
01051     else
01052         showFullScreen();
01053 }
01054 
01055 void Launcher::resizeEvent(QResizeEvent *event)
01056 {
01057     Q_UNUSED(event);
01058 
01059     documentFont = font();
01060     documentFont.setPointSizeF(qMin(documentFont.pointSizeF()*width()/640.0,
01061                                     documentFont.pointSizeF()*height()/480.0));
01062 
01063     if (inFullScreenResize)
01064         inFullScreenResize = false;
01065 
01066     if (currentCategory != "[starting]")
01067         resizeTimer->start(500);
01068 }
01069 
01070 void Launcher::redisplayWindow()
01071 {
01072     if (!currentExample.isEmpty())
01073         showExampleSummary(currentExample);
01074     else if (!currentCategory.isEmpty())
01075         showExamples(currentCategory);
01076     else
01077         showCategories();
01078 }

Generated on Thu Mar 15 11:52:54 2007 for Qt 4.2 User's Guide by  doxygen 1.5.1