|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the tools applications of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #include "qdeclarative.h" |
|
43 #include "qmlruntime.h" |
|
44 #include "qdeclarativeengine.h" |
|
45 #include "loggerwidget.h" |
|
46 #include <QWidget> |
|
47 #include <QDir> |
|
48 #include <QApplication> |
|
49 #include <QTranslator> |
|
50 #include <QDebug> |
|
51 #include <QMessageBox> |
|
52 #include "qdeclarativetester.h" |
|
53 |
|
54 QT_USE_NAMESPACE |
|
55 |
|
56 QtMsgHandler systemMsgOutput = 0; |
|
57 |
|
58 #if defined (Q_OS_SYMBIAN) |
|
59 #include <unistd.h> |
|
60 #include <sys/types.h> |
|
61 #include <sys/stat.h> |
|
62 #include <fcntl.h> |
|
63 |
|
64 void myMessageOutput(QtMsgType type, const char *msg) |
|
65 { |
|
66 static int fd = -1; |
|
67 if (fd == -1) |
|
68 fd = ::open("E:\\qml.log", O_WRONLY | O_CREAT); |
|
69 |
|
70 ::write(fd, msg, strlen(msg)); |
|
71 ::write(fd, "\n", 1); |
|
72 ::fsync(fd); |
|
73 |
|
74 switch (type) { |
|
75 case QtFatalMsg: |
|
76 abort(); |
|
77 } |
|
78 } |
|
79 |
|
80 #else // !defined (Q_OS_SYMBIAN) |
|
81 |
|
82 QWeakPointer<LoggerWidget> logger; |
|
83 |
|
84 QString warnings; |
|
85 void showWarnings() |
|
86 { |
|
87 if (!warnings.isEmpty()) { |
|
88 QMessageBox::warning(0, QApplication::tr("Qt QML Viewer"), warnings); |
|
89 } |
|
90 } |
|
91 |
|
92 void myMessageOutput(QtMsgType type, const char *msg) |
|
93 { |
|
94 if (!logger.isNull()) { |
|
95 QString strMsg = QString::fromAscii(msg); |
|
96 QMetaObject::invokeMethod(logger.data(), "append", Q_ARG(QString, strMsg)); |
|
97 } else { |
|
98 warnings += msg; |
|
99 warnings += QLatin1Char('\n'); |
|
100 } |
|
101 if (systemMsgOutput) { // Windows |
|
102 systemMsgOutput(type, msg); |
|
103 } else { // Unix |
|
104 fprintf(stderr, "%s\n",msg); |
|
105 fflush(stderr); |
|
106 } |
|
107 } |
|
108 |
|
109 #endif |
|
110 |
|
111 void usage() |
|
112 { |
|
113 qWarning("Usage: qmlviewer [options] <filename>"); |
|
114 qWarning(" "); |
|
115 qWarning(" options:"); |
|
116 qWarning(" -v, -version ............................. display version"); |
|
117 qWarning(" -frameless ............................... run with no window frame"); |
|
118 qWarning(" -maximized................................ run maximized"); |
|
119 qWarning(" -fullscreen............................... run fullscreen"); |
|
120 qWarning(" -stayontop................................ keep viewer window on top"); |
|
121 qWarning(" -sizeviewtorootobject .................... the view resizes to the changes in the content"); |
|
122 qWarning(" -sizerootobjecttoview .................... the content resizes to the changes in the view"); |
|
123 qWarning(" -qmlbrowser .............................. use a QML-based file browser"); |
|
124 qWarning(" -warnings [show|hide]..................... show warnings in a separate log window"); |
|
125 qWarning(" -recordfile <output> ..................... set video recording file"); |
|
126 qWarning(" - ImageMagick 'convert' for GIF)"); |
|
127 qWarning(" - png file for raw frames"); |
|
128 qWarning(" - 'ffmpeg' for other formats"); |
|
129 qWarning(" -recorddither ordered|threshold|floyd .... set GIF dither recording mode"); |
|
130 qWarning(" -recordrate <fps> ........................ set recording frame rate"); |
|
131 qWarning(" -record arg .............................. add a recording process argument"); |
|
132 qWarning(" -autorecord [from-]<tomilliseconds> ...... set recording to start and stop"); |
|
133 qWarning(" -devicekeys .............................. use numeric keys (see F1)"); |
|
134 qWarning(" -dragthreshold <size> .................... set mouse drag threshold size"); |
|
135 qWarning(" -netcache <size> ......................... set disk cache to size bytes"); |
|
136 qWarning(" -translation <translationfile> ........... set the language to run in"); |
|
137 qWarning(" -I <directory> ........................... prepend to the module import search path,"); |
|
138 qWarning(" display path if <directory> is empty"); |
|
139 qWarning(" -P <directory> ........................... prepend to the plugin search path"); |
|
140 qWarning(" -opengl .................................. use a QGLWidget for the viewport"); |
|
141 qWarning(" -script <path> ........................... set the script to use"); |
|
142 qWarning(" -scriptopts <options>|help ............... set the script options to use"); |
|
143 |
|
144 qWarning(" "); |
|
145 qWarning(" Press F1 for interactive help"); |
|
146 exit(1); |
|
147 } |
|
148 |
|
149 void scriptOptsUsage() |
|
150 { |
|
151 qWarning("Usage: qmlviewer -scriptopts <option>[,<option>...] ..."); |
|
152 qWarning(" options:"); |
|
153 qWarning(" record ................................... record a new script"); |
|
154 qWarning(" play ..................................... playback an existing script"); |
|
155 qWarning(" testimages ............................... record images or compare images on playback"); |
|
156 qWarning(" testerror ................................ test 'error' property of root item on playback"); |
|
157 qWarning(" snapshot ................................. file being recorded is static,"); |
|
158 qWarning(" only one frame will be recorded or tested"); |
|
159 qWarning(" exitoncomplete ........................... cleanly exit the viewer on script completion"); |
|
160 qWarning(" exitonfailure ............................ immediately exit the viewer on script failure"); |
|
161 qWarning(" saveonexit ............................... save recording on viewer exit"); |
|
162 qWarning(" "); |
|
163 qWarning(" One of record, play or both must be specified."); |
|
164 exit(1); |
|
165 } |
|
166 |
|
167 enum WarningsConfig { ShowWarnings, HideWarnings, DefaultWarnings }; |
|
168 |
|
169 int main(int argc, char ** argv) |
|
170 { |
|
171 #if defined (Q_OS_SYMBIAN) |
|
172 qInstallMsgHandler(myMessageOutput); |
|
173 #else |
|
174 systemMsgOutput = qInstallMsgHandler(myMessageOutput); |
|
175 #endif |
|
176 |
|
177 #if defined (Q_OS_WIN) |
|
178 // Debugging output is not visible by default on Windows - |
|
179 // therefore show modal dialog with errors instad. |
|
180 atexit(showWarnings); |
|
181 #endif |
|
182 |
|
183 #if defined (Q_WS_X11) || defined (Q_WS_MAC) |
|
184 //### default to using raster graphics backend for now |
|
185 bool gsSpecified = false; |
|
186 for (int i = 0; i < argc; ++i) { |
|
187 QString arg = argv[i]; |
|
188 if (arg == "-graphicssystem") { |
|
189 gsSpecified = true; |
|
190 break; |
|
191 } |
|
192 } |
|
193 |
|
194 if (!gsSpecified) |
|
195 QApplication::setGraphicsSystem("raster"); |
|
196 #endif |
|
197 |
|
198 QApplication app(argc, argv); |
|
199 app.setApplicationName("QtQmlViewer"); |
|
200 app.setOrganizationName("Nokia"); |
|
201 app.setOrganizationDomain("nokia.com"); |
|
202 |
|
203 QDeclarativeViewer::registerTypes(); |
|
204 QDeclarativeTester::registerTypes(); |
|
205 |
|
206 bool frameless = false; |
|
207 QString fileName; |
|
208 double fps = 0; |
|
209 int autorecord_from = 0; |
|
210 int autorecord_to = 0; |
|
211 QString dither = "none"; |
|
212 QString recordfile; |
|
213 QStringList recordargs; |
|
214 QStringList imports; |
|
215 QStringList plugins; |
|
216 QString script; |
|
217 QString scriptopts; |
|
218 bool runScript = false; |
|
219 bool devkeys = false; |
|
220 int cache = 0; |
|
221 QString translationFile; |
|
222 bool useGL = false; |
|
223 bool fullScreen = false; |
|
224 bool stayOnTop = false; |
|
225 bool maximized = false; |
|
226 bool useNativeFileBrowser = true; |
|
227 bool experimentalGestures = false; |
|
228 |
|
229 WarningsConfig warningsConfig = DefaultWarnings; |
|
230 bool sizeToView = true; |
|
231 |
|
232 #if defined(Q_OS_SYMBIAN) |
|
233 maximized = true; |
|
234 useNativeFileBrowser = false; |
|
235 #endif |
|
236 |
|
237 #if defined(Q_WS_MAC) |
|
238 useGL = true; |
|
239 #endif |
|
240 |
|
241 for (int i = 1; i < argc; ++i) { |
|
242 bool lastArg = (i == argc - 1); |
|
243 QString arg = argv[i]; |
|
244 if (arg == "-frameless") { |
|
245 frameless = true; |
|
246 } else if (arg == "-maximized") { |
|
247 maximized = true; |
|
248 } else if (arg == "-fullscreen") { |
|
249 fullScreen = true; |
|
250 } else if (arg == "-stayontop") { |
|
251 stayOnTop = true; |
|
252 } else if (arg == "-netcache") { |
|
253 if (lastArg) usage(); |
|
254 cache = QString(argv[++i]).toInt(); |
|
255 } else if (arg == "-recordrate") { |
|
256 if (lastArg) usage(); |
|
257 fps = QString(argv[++i]).toDouble(); |
|
258 } else if (arg == "-recordfile") { |
|
259 if (lastArg) usage(); |
|
260 recordfile = QString(argv[++i]); |
|
261 } else if (arg == "-record") { |
|
262 if (lastArg) usage(); |
|
263 recordargs << QString(argv[++i]); |
|
264 } else if (arg == "-recorddither") { |
|
265 if (lastArg) usage(); |
|
266 dither = QString(argv[++i]); |
|
267 } else if (arg == "-autorecord") { |
|
268 if (lastArg) usage(); |
|
269 QString range = QString(argv[++i]); |
|
270 int dash = range.indexOf('-'); |
|
271 if (dash > 0) |
|
272 autorecord_from = range.left(dash).toInt(); |
|
273 autorecord_to = range.mid(dash+1).toInt(); |
|
274 } else if (arg == "-devicekeys") { |
|
275 devkeys = true; |
|
276 } else if (arg == "-dragthreshold") { |
|
277 if (lastArg) usage(); |
|
278 app.setStartDragDistance(QString(argv[++i]).toInt()); |
|
279 } else if (arg == QLatin1String("-v") || arg == QLatin1String("-version")) { |
|
280 qWarning("Qt QML Viewer version %s", QT_VERSION_STR); |
|
281 exit(0); |
|
282 } else if (arg == "-translation") { |
|
283 if (lastArg) usage(); |
|
284 translationFile = argv[++i]; |
|
285 } else if (arg == "-opengl") { |
|
286 useGL = true; |
|
287 } else if (arg == "-qmlbrowser") { |
|
288 useNativeFileBrowser = false; |
|
289 } else if (arg == "-warnings") { |
|
290 if (lastArg) usage(); |
|
291 QString warningsStr = QString(argv[++i]); |
|
292 if (warningsStr == QLatin1String("show")) { |
|
293 warningsConfig = ShowWarnings; |
|
294 } else if (warningsStr == QLatin1String("hide")) { |
|
295 warningsConfig = HideWarnings; |
|
296 } else { |
|
297 usage(); |
|
298 } |
|
299 } else if (arg == "-I" || arg == "-L") { |
|
300 if (arg == "-L") |
|
301 qWarning("-L option provided for compatibility only, use -I instead"); |
|
302 if (lastArg) { |
|
303 QDeclarativeEngine tmpEngine; |
|
304 QString paths = tmpEngine.importPathList().join(QLatin1String(":")); |
|
305 qWarning("Current search path: %s", paths.toLocal8Bit().constData()); |
|
306 exit(0); |
|
307 } |
|
308 imports << QString(argv[++i]); |
|
309 } else if (arg == "-P") { |
|
310 if (lastArg) usage(); |
|
311 plugins << QString(argv[++i]); |
|
312 } else if (arg == "-script") { |
|
313 if (lastArg) usage(); |
|
314 script = QString(argv[++i]); |
|
315 } else if (arg == "-scriptopts") { |
|
316 if (lastArg) usage(); |
|
317 scriptopts = QString(argv[++i]); |
|
318 } else if (arg == "-savescript") { |
|
319 if (lastArg) usage(); |
|
320 script = QString(argv[++i]); |
|
321 runScript = false; |
|
322 } else if (arg == "-playscript") { |
|
323 if (lastArg) usage(); |
|
324 script = QString(argv[++i]); |
|
325 runScript = true; |
|
326 } else if (arg == "-sizeviewtorootobject") { |
|
327 sizeToView = false; |
|
328 } else if (arg == "-sizerootobjecttoview") { |
|
329 sizeToView = true; |
|
330 } else if (arg == "-experimentalgestures") { |
|
331 experimentalGestures = true; |
|
332 } else if (arg[0] != '-') { |
|
333 fileName = arg; |
|
334 } else if (1 || arg == "-help") { |
|
335 usage(); |
|
336 } |
|
337 } |
|
338 |
|
339 QTranslator qmlTranslator; |
|
340 if (!translationFile.isEmpty()) { |
|
341 qmlTranslator.load(translationFile); |
|
342 app.installTranslator(&qmlTranslator); |
|
343 } |
|
344 |
|
345 Qt::WFlags wflags = (frameless ? Qt::FramelessWindowHint : Qt::Widget); |
|
346 if (stayOnTop) |
|
347 wflags |= Qt::WindowStaysOnTopHint; |
|
348 |
|
349 QDeclarativeViewer *viewer = new QDeclarativeViewer(0, wflags); |
|
350 if (!scriptopts.isEmpty()) { |
|
351 QStringList options = |
|
352 scriptopts.split(QLatin1Char(','), QString::SkipEmptyParts); |
|
353 |
|
354 QDeclarativeViewer::ScriptOptions scriptOptions = 0; |
|
355 for (int i = 0; i < options.count(); ++i) { |
|
356 const QString &option = options.at(i); |
|
357 if (option == QLatin1String("help")) { |
|
358 scriptOptsUsage(); |
|
359 } else if (option == QLatin1String("play")) { |
|
360 scriptOptions |= QDeclarativeViewer::Play; |
|
361 } else if (option == QLatin1String("record")) { |
|
362 scriptOptions |= QDeclarativeViewer::Record; |
|
363 } else if (option == QLatin1String("testimages")) { |
|
364 scriptOptions |= QDeclarativeViewer::TestImages; |
|
365 } else if (option == QLatin1String("testerror")) { |
|
366 scriptOptions |= QDeclarativeViewer::TestErrorProperty; |
|
367 } else if (option == QLatin1String("exitoncomplete")) { |
|
368 scriptOptions |= QDeclarativeViewer::ExitOnComplete; |
|
369 } else if (option == QLatin1String("exitonfailure")) { |
|
370 scriptOptions |= QDeclarativeViewer::ExitOnFailure; |
|
371 } else if (option == QLatin1String("saveonexit")) { |
|
372 scriptOptions |= QDeclarativeViewer::SaveOnExit; |
|
373 } else if (option == QLatin1String("snapshot")) { |
|
374 scriptOptions |= QDeclarativeViewer::Snapshot; |
|
375 } else { |
|
376 scriptOptsUsage(); |
|
377 } |
|
378 } |
|
379 |
|
380 if (script.isEmpty()) |
|
381 usage(); |
|
382 |
|
383 if (!(scriptOptions & QDeclarativeViewer::Record) && !(scriptOptions & QDeclarativeViewer::Play)) |
|
384 scriptOptsUsage(); |
|
385 viewer->setScriptOptions(scriptOptions); |
|
386 viewer->setScript(script); |
|
387 } else if (!script.isEmpty()) { |
|
388 usage(); |
|
389 } |
|
390 |
|
391 #if !defined(Q_OS_SYMBIAN) |
|
392 logger = viewer->warningsWidget(); |
|
393 if (warningsConfig == ShowWarnings) { |
|
394 logger.data()->setDefaultVisibility(LoggerWidget::ShowWarnings); |
|
395 logger.data()->show(); |
|
396 } else if (warningsConfig == HideWarnings){ |
|
397 logger.data()->setDefaultVisibility(LoggerWidget::HideWarnings); |
|
398 } |
|
399 #endif |
|
400 |
|
401 if (experimentalGestures) |
|
402 viewer->enableExperimentalGestures(); |
|
403 |
|
404 foreach (QString lib, imports) |
|
405 viewer->addLibraryPath(lib); |
|
406 |
|
407 foreach (QString plugin, plugins) |
|
408 viewer->addPluginPath(plugin); |
|
409 |
|
410 viewer->setNetworkCacheSize(cache); |
|
411 viewer->setRecordFile(recordfile); |
|
412 viewer->setSizeToView(sizeToView); |
|
413 if (fps>0) |
|
414 viewer->setRecordRate(fps); |
|
415 if (autorecord_to) |
|
416 viewer->setAutoRecord(autorecord_from,autorecord_to); |
|
417 if (devkeys) |
|
418 viewer->setDeviceKeys(true); |
|
419 viewer->setRecordDither(dither); |
|
420 if (recordargs.count()) |
|
421 viewer->setRecordArgs(recordargs); |
|
422 |
|
423 viewer->setUseNativeFileBrowser(useNativeFileBrowser); |
|
424 if (fullScreen && maximized) |
|
425 qWarning() << "Both -fullscreen and -maximized specified. Using -fullscreen."; |
|
426 |
|
427 if (fileName.isEmpty()) { |
|
428 QFile qmlapp(QLatin1String("qmlapp")); |
|
429 if (qmlapp.exists() && qmlapp.open(QFile::ReadOnly)) { |
|
430 QString content = QString::fromUtf8(qmlapp.readAll()); |
|
431 qmlapp.close(); |
|
432 |
|
433 int newline = content.indexOf(QLatin1Char('\n')); |
|
434 if (newline >= 0) |
|
435 fileName = content.left(newline); |
|
436 else |
|
437 fileName = content; |
|
438 } |
|
439 } |
|
440 |
|
441 if (!fileName.isEmpty()) { |
|
442 viewer->open(fileName); |
|
443 fullScreen ? viewer->showFullScreen() : maximized ? viewer->showMaximized() : viewer->show(); |
|
444 } else { |
|
445 if (!useNativeFileBrowser) |
|
446 viewer->openFile(); |
|
447 fullScreen ? viewer->showFullScreen() : maximized ? viewer->showMaximized() : viewer->show(); |
|
448 if (useNativeFileBrowser) |
|
449 viewer->openFile(); |
|
450 } |
|
451 viewer->setUseGL(useGL); |
|
452 viewer->raise(); |
|
453 |
|
454 int rv = app.exec(); |
|
455 delete viewer; |
|
456 exit(rv); |
|
457 } |