Update copyright headers
[qt:qt.git] / demos / embedded / fluidlauncher / fluidlauncher.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the demonstration applications of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include <QXmlStreamReader>
43
44 #include "fluidlauncher.h"
45
46
47 #define DEFAULT_INPUT_TIMEOUT 10000
48 #define SIZING_FACTOR_HEIGHT 6/10
49 #define SIZING_FACTOR_WIDTH 6/10
50
51 FluidLauncher::FluidLauncher(QStringList* args)
52 {
53     pictureFlowWidget = new PictureFlow();
54     slideShowWidget = new SlideShow();
55     inputTimer = new QTimer();
56
57     addWidget(pictureFlowWidget);
58     addWidget(slideShowWidget);
59     setCurrentWidget(pictureFlowWidget);
60     pictureFlowWidget->setFocus();
61
62     QRect screen_size = QApplication::desktop()->screenGeometry();
63
64     QObject::connect(pictureFlowWidget, SIGNAL(itemActivated(int)), this, SLOT(launchApplication(int)));
65     QObject::connect(pictureFlowWidget, SIGNAL(inputReceived()),    this, SLOT(resetInputTimeout()));
66     QObject::connect(slideShowWidget,   SIGNAL(inputReceived()),    this, SLOT(switchToLauncher()));
67     QObject::connect(inputTimer,        SIGNAL(timeout()),          this, SLOT(inputTimedout()));
68
69     inputTimer->setSingleShot(true);
70     inputTimer->setInterval(DEFAULT_INPUT_TIMEOUT);
71
72     const int h = screen_size.height() * SIZING_FACTOR_HEIGHT;
73     const int w = screen_size.width() * SIZING_FACTOR_WIDTH;
74     const int hh = qMin(h, w);
75     const int ww = hh / 3 * 2;
76     pictureFlowWidget->setSlideSize(QSize(ww, hh));
77
78     bool success;
79     int configIndex = args->indexOf("-config");
80     if ( (configIndex != -1) && (configIndex != args->count()-1) )
81         success = loadConfig(args->at(configIndex+1));
82     else
83         success = loadConfig("config.xml");
84
85     if (success) {
86       populatePictureFlow();
87
88       showFullScreen();
89       inputTimer->start();
90     } else {
91         pictureFlowWidget->setAttribute(Qt::WA_DeleteOnClose, true);
92         pictureFlowWidget->close();
93     }
94
95 }
96
97 FluidLauncher::~FluidLauncher()
98 {
99     delete pictureFlowWidget;
100     delete slideShowWidget;
101 }
102
103 bool FluidLauncher::loadConfig(QString configPath)
104 {
105     QFile xmlFile(configPath);
106
107     if (!xmlFile.exists() || (xmlFile.error() != QFile::NoError)) {
108         qDebug() << "ERROR: Unable to open config file " << configPath;
109         return false;
110     }
111
112     slideShowWidget->clearImages();
113
114     xmlFile.open(QIODevice::ReadOnly);
115     QXmlStreamReader reader(&xmlFile);
116     while (!reader.atEnd()) {
117         reader.readNext();
118
119         if (reader.isStartElement()) {
120             if (reader.name() == "demos")
121                 parseDemos(reader);
122             else if(reader.name() == "slideshow")
123                 parseSlideshow(reader);
124         }
125     }
126
127     if (reader.hasError()) {
128        qDebug() << QString("Error parsing %1 on line %2 column %3: \n%4")
129                 .arg(configPath)
130                 .arg(reader.lineNumber())
131                 .arg(reader.columnNumber())
132                 .arg(reader.errorString());
133     }
134
135     // Append an exit Item
136     DemoApplication* exitItem = new DemoApplication(QString(), QLatin1String("Exit Embedded Demo"), QString(), QStringList());
137     demoList.append(exitItem);
138
139     return true;
140 }
141
142
143 void FluidLauncher::parseDemos(QXmlStreamReader& reader)
144 {
145     while (!reader.atEnd()) {
146         reader.readNext();
147         if (reader.isStartElement() && reader.name() == "example") {
148             QXmlStreamAttributes attrs = reader.attributes();
149             QStringRef filename = attrs.value("filename");
150             if (!filename.isEmpty()) {
151                 QStringRef name = attrs.value("name");
152                 QStringRef image = attrs.value("image");
153                 QStringRef args = attrs.value("args");
154
155                 DemoApplication* newDemo = new DemoApplication(
156                         filename.toString(),
157                         name.isEmpty() ? "Unnamed Demo" : name.toString(),
158                         image.toString(),
159                         args.toString().split(" "));
160                 demoList.append(newDemo);
161             }
162         } else if(reader.isEndElement() && reader.name() == "demos") {
163             return;
164         }
165     }
166 }
167
168 void FluidLauncher::parseSlideshow(QXmlStreamReader& reader)
169 {
170     QXmlStreamAttributes attrs = reader.attributes();
171
172     QStringRef timeout = attrs.value("timeout");
173     bool valid;
174     if (!timeout.isEmpty()) {
175         int t = timeout.toString().toInt(&valid);
176         if (valid)
177             inputTimer->setInterval(t);
178     }
179
180     QStringRef interval = attrs.value("interval");
181     if (!interval.isEmpty()) {
182         int i = interval.toString().toInt(&valid);
183         if (valid)
184             slideShowWidget->setSlideInterval(i);
185     }
186
187     while (!reader.atEnd()) {
188         reader.readNext();
189         if (reader.isStartElement()) {
190             QXmlStreamAttributes attrs = reader.attributes();
191             if (reader.name() == "imagedir") {
192                 QStringRef dir = attrs.value("dir");
193                 slideShowWidget->addImageDir(dir.toString());
194             } else if(reader.name() == "image") {
195                 QStringRef image = attrs.value("image");
196                 slideShowWidget->addImage(image.toString());
197             }
198         } else if(reader.isEndElement() && reader.name() == "slideshow") {
199             return;
200         }
201     }
202
203 }
204
205 void FluidLauncher::populatePictureFlow()
206 {
207     pictureFlowWidget->setSlideCount(demoList.count());
208
209     for (int i=demoList.count()-1; i>=0; --i) {
210         pictureFlowWidget->setSlide(i, *(demoList[i]->getImage()));
211         pictureFlowWidget->setSlideCaption(i, demoList[i]->getCaption());
212     }
213
214     pictureFlowWidget->setCurrentSlide(demoList.count()/2);
215 }
216
217
218 void FluidLauncher::launchApplication(int index)
219 {
220     // NOTE: Clearing the caches will free up more memory for the demo but will cause
221     // a delay upon returning, as items are reloaded.
222     //pictureFlowWidget->clearCaches();
223
224     if (index == demoList.size() -1) {
225         qApp->quit();
226         return;
227     }
228
229     inputTimer->stop();
230
231     QObject::connect(demoList[index], SIGNAL(demoFinished()), this, SLOT(demoFinished()));
232
233     demoList[index]->launch();
234 }
235
236
237 void FluidLauncher::switchToLauncher()
238 {
239     slideShowWidget->stopShow();
240     inputTimer->start();
241     setCurrentWidget(pictureFlowWidget);
242 }
243
244
245 void FluidLauncher::resetInputTimeout()
246 {
247     if (inputTimer->isActive())
248         inputTimer->start();
249 }
250
251 void FluidLauncher::inputTimedout()
252 {
253     switchToSlideshow();
254 }
255
256
257 void FluidLauncher::switchToSlideshow()
258 {
259     inputTimer->stop();
260     slideShowWidget->startShow();
261     setCurrentWidget(slideShowWidget);
262 }
263
264 void FluidLauncher::demoFinished()
265 {
266     setCurrentWidget(pictureFlowWidget);
267     inputTimer->start();
268
269     // Bring the Fluidlauncher to the foreground to allow selecting another demo
270     raise();
271     activateWindow();
272 }
273
274 void FluidLauncher::changeEvent(QEvent* event)
275 {
276     if (event->type() == QEvent::ActivationChange) {
277         if (isActiveWindow()) {
278             if(currentWidget() == pictureFlowWidget) {
279                 resetInputTimeout();
280             } else {
281                 slideShowWidget->startShow();
282             }
283         } else {
284             inputTimer->stop();
285             slideShowWidget->stopShow();
286         }
287     }
288     QStackedWidget::changeEvent(event);
289 }