00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
00110
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
00119
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
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
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
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 }