New keywords implemented.
[qa-tools:qtuitest-mbt-adapter.git] / src / keyword.cpp
1 /*
2  * This file is part of qtuitest-mbt-adapter
3  *
4  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
5  *
6  * Contact: Riku Halonen <riku-halonen@nokia.com>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * version 2.1 as published by the Free Software Foundation.
11  *
12  * This library is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20  * 02110-1301 USA
21  *
22  */
23
24 // System Includes.
25 #include <QMutableStringListIterator>
26 #include <QMetaEnum>
27
28 // User includes.
29 #include "keyword.h"
30
31 // Public Methods.
32
33 KeywordController::KeywordController() :
34     m_delay(0),
35     m_verificationTimeout(false),
36     m_verificationTimerId(0)
37 {
38     m_validKeywords = validKeywords();
39     // Supress test message query warnings.
40     enableQueryWarnings(false);
41 }
42
43 KeywordController::~KeywordController()
44 {
45 }
46
47 void KeywordController::processCommandLine(QStringList &arguments)
48 {
49     QSystemTest::processCommandLine(arguments);
50 }
51
52 bool KeywordController::fail(const QString &msg)
53 {
54     Result res;
55     res.pass = false;
56     res.msg = msg;
57     m_current->setResult(res);
58
59     qWarning("FAIL!: %s", qPrintable(msg));
60     return true;
61 }
62
63 /*!
64  * Creates new keyword from \a str_Keyword.
65  *
66  * \return Pointer to keyword instance on success; otherwise NULL.
67  */
68 Keyword* KeywordController::createKeyword(const QString &str_Keyword) const
69 {
70     // Check, that the string matches the keyword format.
71     // Format is, kw_[keyword](arg0, arg1, ...)
72     if (!str_Keyword.contains(QRegExp("kw_.*\\(.*\\)"))) {
73         qWarning("Invalid keyword format: %s", qPrintable(str_Keyword));
74         return 0;
75     }
76
77     Keyword *kw = new Keyword();
78
79     int paramStart = str_Keyword.indexOf("(");
80     // Set name of the keyword.
81     kw->setKeyword(str_Keyword.left(paramStart));
82
83     int paramEnd = str_Keyword.lastIndexOf(")");
84     // Split parameters.
85     QString paramsSection = str_Keyword.mid((paramStart + 1), (paramEnd - paramStart - 1));
86     QStringList params = paramsSection.split(",");
87
88     // If only one argument, check that it's valid (not just plain whitespaces).
89     if (params.count() == 1 && params.at(0).trimmed().isEmpty()) return kw;
90
91     QMutableStringListIterator iter(params);
92     QStringList keywordArguments;
93
94     while (iter.hasNext()) {
95         QString param = iter.next();
96         // Remove whitespaces and ' characters.
97         param = param.remove(QChar('\''));
98         param = param.trimmed();
99
100         if (param.startsWith('{')) {
101             if (!param.endsWith('}')) {
102                 while (iter.hasNext()) {
103
104                     param.append(",");
105                     QString token = iter.next();
106                     param.append(token);
107
108                     if (param.endsWith('}')) break;
109                 }
110             }
111             param = param.remove(QChar('{'));
112             param = param.remove(QChar('}'));
113             param = param.trimmed();
114         }
115
116         keywordArguments << param;
117     }
118
119     // Set aruments.
120     kw->setArguments(keywordArguments);
121     return kw;
122 }
123
124 /*!
125  * Executes keyword \a kw.
126  *
127  * \param kw Keyword to execute.
128  * \return True, if execution succeeds; otherwise false.
129  */
130 bool KeywordController::executeKeyword(Keyword &kw)
131 {
132     m_current = &kw;
133
134     if (!m_validKeywords.contains(m_current->keyword())) {
135         qCritical("Keyword: %s not supported.",
136                   qPrintable(m_current->keyword()));
137         return false;
138     }
139     qDebug("Executing keyword: %s...", qPrintable(m_current->keyword()));
140
141     bool retVal;
142
143     if (!QMetaObject::invokeMethod(this, m_current->keyword().toLatin1().data(),
144                               Qt::AutoConnection,
145                               Q_RETURN_ARG(bool, retVal),
146                               Q_ARG(QStringList, m_current->arguments()))) {
147         qCritical("Failed to execute keyword: %s.",
148                   qPrintable(m_current->keyword()));
149         return false;
150     }
151
152     if (!retVal) return false;
153
154     if (!m_current->result().pass) return true;
155
156     // Check the status of last query. Returns false, if query was successful.
157     bool failed = queryFailed();
158
159     if (failed) {
160         fail("Test message query to AUT failed!");
161     }
162
163     return true;
164 }
165
166 /*!
167  * Returns list of supported keywords.
168  *
169  * \return Supported keywords.
170  */
171 QStringList KeywordController::validKeywords() const
172 {
173     return QStringList()
174             << "kw_Activate"
175             << "kw_EnterText"
176            // << "kw_SetProperty"
177             << "kw_Select"
178            // << "kw_SelectMenu"
179             << "kw_SelectTabBar"
180            // << "kw_SelectIndex"
181             << "kw_KeyPress"
182             << "kw_KeyClick"
183             << "kw_KeyClickSequence"
184             << "kw_KeyClickHold"
185             << "kw_KeyRelease"
186             << "kw_MouseClick"
187             << "kw_Tap"
188             << "kw_MouseClickRelative"
189             << "kw_TapRelative"
190             << "kw_MouseClickHold"
191             << "kw_TapHold"
192             << "kw_MouseClickHoldRelative"
193             << "kw_TapHoldRelative"
194             << "kw_MousePress"
195             << "kw_TapDown"
196             << "kw_MousePressRelative"
197             << "kw_TapDownRelative"
198             << "kw_MouseRelease"
199             << "kw_TapRelease"
200             << "kw_MouseReleaseRelative"
201             << "kw_TapReleaseRelative"
202             << "kw_VerifyText"
203             << "kw_VerifyTitle"
204            // << "kw_VerifyProperty"
205             << "kw_WaitForText"
206             << "kw_StartApplication"
207             << "kw_Wait"
208             ;
209 }
210
211 // Keyword implementations.
212
213 /*! @defgroup keywords %Keyword reference
214  *
215  *  @{
216  */
217
218 /*!
219  * Activates the specified widget Typically used to activate button widgets.
220  *
221  * Format:
222  * \code
223  *      kw_Activate(queryPath)
224  * \endcode
225  *
226  * Example(s):
227  * \code
228  *      kw_Activate('test')
229  * \endcode
230  *
231  * \param args Specifies widget to be activated (\a args[0]).
232  * \return True, if executed sucessfully; otherwise false.
233  */
234 bool KeywordController::kw_Activate(const QStringList &args)
235 {
236     if (args.count() != 1) {
237         qCritical("kw_Activate: Invalid number of arguments.\n"
238                   "Format: kw_Activate(queryPath)"
239                   );
240         return false;
241     }
242     activate(args[0]);
243     return true;
244 }
245
246 /*!
247  * Simulates a value being entered into widget. By default the text will be
248  * commited and edit mode will be left.
249  *
250  * Format:
251  * \code
252  *      kw_EnterText(value[,queryPath][,QSystemTest::EnterMode])
253  * \endcode
254  *
255  * Example(s):
256  * \code
257  *      kw_EnterText('some text')
258  *
259  *      kw_EnterText('some text', 'field', NoCommit)
260  * \endcode
261  *
262  * \param args Specifies value (\a args[0]) to enter in widget (\a args[1])
263  *        with mode (\a args[0]).
264  * \return True, if executed sucessfully; otherwise false.
265  */
266 bool KeywordController::kw_EnterText(const QStringList &args)
267 {
268     if (args.count() < 1 || args.count() >= 4) {
269         qCritical("kw_EnterText: Invalid number of keyword arguments.\n"
270                   "Format: kw_EnterText(value[,queryPath][,QSystemTest::EnterMode])"
271                   );
272         return false;
273     }
274
275     if (args.count() == 1) {
276         enter(args[0]);
277         return true;
278     }
279
280     QSystemTest::EnterMode enterMode = QSystemTest::Commit;
281
282     if (args.count() == 3) {
283         if (args.at(2).contains("NoCommit")) {
284             enterMode = QSystemTest::NoCommit;
285         }
286         else if (!args.at(2).contains("Commit") ||
287                  args.at(2).isEmpty()) {
288             qWarning("%s is not a valid enter mode. Using default.",
289                      qPrintable(args[2]));
290         }
291     }
292     enter(args[0], args[1], enterMode);
293     return true;
294 }
295
296 /*!
297  * Sets Qt property of widget to a specified value..
298  *
299  * Format:
300  * \code
301  *      kw_SetProperty(queryPath,name,Type:value)
302  * \endcode
303  *
304  * Example(s):
305  * \code
306  *
307  *      kw_SetProperty('Name', 'text', {QString:'John'})
308  *
309  * \endcode
310  *
311  * \param args Specifies name of the widget (\a args[0]) which property
312  *        (\a args[1]) is set to value (\a args[2]).
313  * \return True, if executed sucessfully; otherwise false.
314  */
315 bool KeywordController::kw_SetProperty(const QStringList &args)
316 {
317     if (args.count() != 3) {
318         qCritical("kw_SetProperty: Invalid number of keyword arguments.\n"
319                   "Format: kw_SetProperty(queryPath,name,Type:value)"
320                   );
321         return false;
322     }
323     /*! \todo implement conversion from string to QVariant */
324
325     return false;
326 }
327
328 /*!
329  * Selects item from specified application or widget.
330  *
331  * This can be used to select a certain item from a list widget or combo box.
332  * Works with list type of widgets, including list views, combo boxes and menus.
333  *
334  * \li When used with a list widget, the specified item is navigated and selected
335  * \li When used with a combo box, the drop-down list is opened, the item is selected,
336  *     and the drop-down list is closed again.
337  *
338  * Format:
339  * \code
340  *      kw_Select(item[,queryPath])
341  * \endcode
342  *
343  * Example(s):
344  * \code
345  *      kw_Select('John', 'Name')
346  * \endcode
347  *
348  * \param args Specifies item (\a args[0]) to select from application/ widget
349  *        (\a args[1]).
350  * \return True, if executed sucessfully; otherwise false.
351  */
352 bool KeywordController::kw_Select(const QStringList &args)
353 {
354     if (args.count() < 1 || args.count() >= 3) {
355         qCritical("kw_Select: Invalid number of keyword arguments.\n"
356                   "Format: kw_Select(item[,queryPath])"
357                   );
358         return false;
359     }
360     else if (args.count() == 1) {
361         select(args[0]);
362     }
363     else if (args.count() == 2) {
364         select(args[0], args[1]);
365     }
366     return true;
367 }
368
369 /*!
370  * Selects item from application menu.
371  *
372  * Format:
373  * \code
374  *      kw_SelectMenu(item[,index])
375  * \endcode
376  *
377  * Example(s):
378  * \code
379  *      kw_SelectMenu('foo')
380  * \endcode
381  *
382  * \param args Specifies item (\a args[0]) to select from menu.
383  * \return True, if executed sucessfully; otherwise false.
384  */
385 bool KeywordController::kw_SelectMenu(const QStringList &/*args*/)
386 {
387     return false;
388 }
389
390 /*!
391  * Selects tab specified by query path from application tab bar.
392  *
393  * Format:
394  * \code
395  *      kw_SelectTabBar(tab[,index])
396  * \endcode
397  *
398  * Example(s):
399  * \code
400  *      kw_SelectTabBar('item')
401  * \endcode
402  *
403  * \param args Specifies tab (\a args[0]) to select. If application has multiple
404  *        tab bars (\a args[1]) is used to distinguish between them.
405  * \return True, if executed sucessfully; otherwise false.
406  */
407 bool KeywordController::kw_SelectTabBar(const QStringList &args)
408 {
409     if (args.count() < 1 || args.count() >= 3) {
410         qCritical("kw_SelectTabBar: Invalid number of keyword arguments.\n"
411                   "Format: kw_SelectTabBar(tab[,index])"
412                   );
413         return false;
414     }
415
416     QStringList tabbars = findByProperty("inherits", "QTabBar");
417
418     if (tabbars.count() == 0) {
419         qCritical("Tab widget not found");
420         return false;
421     }
422
423     if (args.count() == 1) {
424         select(args[0], tabbars[0]);
425     }
426     else {
427         bool ok;
428         int index = args.at(1).toInt(&ok);
429
430         if (!ok) {
431             qCritical("%s is not a valid index specifier.",
432                       qPrintable(args[1]));
433             return false;
434         }
435         else if (index >= tabbars.count()) {
436             qCritical("Tab bar with index %s not found.",
437                       qPrintable(args[1]));
438             return false;
439         }
440         else {
441             select(args[0], tabbars[index]);
442         }
443     }
444     return true;
445 }
446
447 /*!
448  * Selects the item from indexed widget from specified query path.
449  *
450  * Format:
451  * \code
452  *      kw_SelectIndex([row,column][,queryPath])
453  * \endcode
454  *
455  * Example(s):
456  * \code
457  *      kw_SelectIndex([2, 3])
458  *
459  *      kw_SelectIndex([2, 3], table)
460  * \endcode
461  *
462  * Index is specified as list of row and column values enclosed by \b[ and \b].
463  *
464  * \param args Specifies row and column (\a args[0]) to select from query path
465  *        (\a args[0]).
466  * \return True, if executed sucessfully; otherwise false.
467  * \sa kw_Select
468  */
469 bool KeywordController::kw_SelectIndex(const QStringList &/*args*/)
470 {
471     /*! \todo Implement kw_SelectIndex */
472     return false;
473 }
474
475 /*!
476  * Simulates a key press (do not release) sent to the application.
477  *
478  * Format:
479  * \code
480  *      kw_KeyPress(Qt::Key[,queryPath])
481  * \endcode
482  *
483  * Example(s):
484  * \code
485  *      kw_KeyPress(Key_Up)
486  *
487  *      kw_KeyPress(Key_Up, 'application')
488  * \endcode
489  *
490  * \param args Specifies key (\a args[0]) to press and optionally target
491           application (\a args[1]).
492  * \return True, if executed sucessfully; otherwise false.
493  * \sa <a href="http://doc.qt.nokia.com/4.7/qt.html#Key-enum">enum Qt:Key</a>
494  */
495 bool KeywordController::kw_KeyPress(const QStringList &args)
496 {
497     if (args.count() < 1 || args.count() >= 3) {
498         qCritical("kw_KeyPress: Invalid number of keyword arguments.\n"
499                   "Format: kw_KeyPress(Qt::Key[,queryPath])"
500                   );
501         return false;
502     }
503
504     int keyValue = enumConstantToInteger(args[0], "Key");
505
506     if (keyValue == -1) {
507         qCritical("kw_KeyPress: Invalid key name: %s", qPrintable(args[0]));
508         return false;
509     }
510
511     if (args.count() == 1) {
512         keyPress(static_cast<Qt::Key>(keyValue));
513     }
514     else {
515         keyPress(static_cast<Qt::Key>(keyValue), args[1]);
516     }
517     return true;
518 }
519
520 /*!
521  * Simulates a key click (press and release) sent to the application.
522  *
523  * Format:
524  * \code
525  *      kw_KeyClick(Qt::Key[,queryPath])
526  * \endcode
527  *
528  * Example(s):
529  * \code
530  *      kw_KeyClick(Key_Up)
531  *
532  *      kw_KeyClick(Key_Up, 'application')
533  * \endcode
534  *
535  * \param args Specifies key (\a args[0]) to click and optionally target
536  *         application (\a args[1]).
537  * \return True, if executed sucessfully; otherwise false.
538  * \sa <a href="http://doc.qt.nokia.com/4.7/qt.html#Key-enum">enum Qt:Key</a>
539  */
540 bool KeywordController::kw_KeyClick(const QStringList &args)
541 {
542     if (args.count() < 1 || args.count() >= 3) {
543         qCritical("kw_KeyClick: Invalid number of keyword arguments.\n"
544                   "Format: kw_KeyClick(Qt::Key[,queryPath])"
545                   );
546         return false;
547     }
548
549     int keyValue = enumConstantToInteger(args[0], "Key");
550
551     if (keyValue == -1) {
552         qCritical("kw_KeyClick: Invalid key name: %s", qPrintable(args[0]));
553         return false;
554     }
555
556     if (args.count() == 1) {
557         keyClick(static_cast<Qt::Key>(keyValue));
558     }
559     else {
560         keyClick(static_cast<Qt::Key>(keyValue), args[1]);
561     }
562     return true;
563 }
564
565 /*!
566  * Simulates a sequence of key clicks (press and release) sent to the application.
567  *
568  * Format:
569  * \code
570  *      kw_KeyClickSequence(Qt::Key,times[,queryPath])
571  * \endcode
572  *
573  * Example(s):
574  * \code
575  *      kw_KeyClickSequence(Key_Up, 2)
576  *
577  *      kw_KeyClickSequence(Key_Up, 3, 'application')
578  * \endcode
579  *
580  * \param args Specifies key (\a args[0]) to click (\a args[1]) times and
581  *        optionally target application (\a args[2]).
582  * \return True, if executed sucessfully; otherwise false.
583  * \sa <a href="http://doc.qt.nokia.com/4.7/qt.html#Key-enum">enum Qt:Key</a>
584  */
585 bool KeywordController::kw_KeyClickSequence(const QStringList &args)
586 {
587     if (args.count() < 2 || args.count() >= 4) {
588         qCritical("kw_KeyClickSequence: Invalid number of keyword arguments.\n"
589                   "Format: kw_KeyClickSequence(Qt::Key,times[,queryPath])"
590                   );
591         return false;
592     }
593
594     int keyValue = enumConstantToInteger(args[0], "Key");
595
596     if (keyValue == -1) {
597         qCritical("kw_KeyClickSequence: Invalid key name: %s", qPrintable(args[0]));
598         return false;
599     }
600
601     bool ok;
602     uint times = args.at(1).toUInt(&ok);
603
604     if (!ok) {
605         qCritical("kw_KeyClickSequence: Not a valid sequence value: %s",
606                   qPrintable(args[1]));
607         return false;
608     }
609
610     if (args.count() == 2) {
611         for (uint i = 0; i < times; i++) {
612             if (m_delay) QTest::qSleep(m_delay);
613             keyClick(static_cast<Qt::Key>(keyValue));
614         }
615     }
616     else {
617         for (uint i = 0; i < times; i++) {
618             if (m_delay) QTest::qSleep(m_delay);
619             keyClick(static_cast<Qt::Key>(keyValue), args[1]);
620         }
621     }
622     return true;
623 }
624
625 /*!
626  * Simulates a key click and hold (press + wait + release) sent to the application.
627  * Interval between press and release is defined in milliseconds.
628  *
629  * Format:
630  * \code
631  *      kw_KeyClickHold(Qt::Key,duration[,queryPath])
632  * \endcode
633  *
634  * Example(s):
635  * \code
636  *      kw_KeyClickHold(Key_Up, 2000)
637  *
638  *      kw_KeyClickHold(Key_Up, 3000, 'application')
639  * \endcode
640  *
641  * \param args Specifies key (\a args[0]) to click and hold (\a args[1]) msecs
642  *        before releasing. If (\a args[2]) is not defined, key event is sent to
643  *        the current application.
644  * \return True, if executed sucessfully; otherwise false.
645  * \sa <a href="http://doc.qt.nokia.com/4.7/qt.html#Key-enum">enum Qt:Key</a>
646  */
647 bool KeywordController::kw_KeyClickHold(const QStringList &args)
648 {
649     if (args.count() < 2 || args.count() >= 4) {
650         qCritical("kw_KeyClickHold: Invalid number of keyword arguments.\n"
651                   "Format: kw_KeyClickHold(Qt::Key,duration[,queryPath])"
652                   );
653         return false;
654     }
655
656     int keyValue = enumConstantToInteger(args[0], "Key");
657
658     if (keyValue == -1) {
659         qCritical("kw_KeyClickHold: Invalid key name: %s", qPrintable(args[0]));
660         return false;
661     }
662
663     bool ok;
664     uint duration = args.at(1).toUInt(&ok);
665
666     if (!ok) {
667         qCritical("kw_KeyClickHold: Not a valid duration value: %s.",
668                   qPrintable(args[1]));
669         return false;
670     }
671
672     if (args.count() == 2) {
673         keyClickHold(static_cast<Qt::Key>(keyValue), duration);
674     }
675     else {
676         keyClickHold(static_cast<Qt::Key>(keyValue), duration, args[1]);
677     }
678     return true;
679 }
680
681 /*!
682  * Simulates a key release sent to the application.
683  *
684  * Format:
685  * \code
686  *      kw_KeyRelease(Qt::Key[,queryPath])
687  * \endcode
688  *
689  * Example(s):
690  * \code
691  *      kw_KeyRelease(Key_Up)
692  *
693  *      kw_KeyRelease(Key_Up, 'application')
694  * \endcode
695  *
696  * \param args Specifies key (\a args[0]) to release. If (\a args[1]) is not
697  *        defined, key event is sent to the current application.
698  * \return True, if executed sucessfully; otherwise false.
699  * \sa <a href="http://doc.qt.nokia.com/4.7/qt.html#Key-enum">enum Qt:Key</a>
700  */
701 bool KeywordController::kw_KeyRelease(const QStringList &args)
702 {
703     if (args.count() < 1 || args.count() >= 3) {
704         qCritical("kw_KeyRelease: Invalid number of keyword arguments.\n"
705                   "Format: kw_KeyRelease(Qt::Key[,queryPath])"
706                   );
707         return false;
708     }
709
710     int keyValue = enumConstantToInteger(args[0], "Key");
711
712     if (keyValue == -1) {
713         qCritical("kw_KeyRelease: Invalid key name: %s", qPrintable(args[0]));
714         return false;
715     }
716
717     if (args.count() == 1) {
718         keyRelease(static_cast<Qt::Key>(keyValue));
719     }
720     else {
721         keyRelease(static_cast<Qt::Key>(keyValue), args[1]);
722     }
723     return true;
724 }
725
726 /*!
727  * Simulates a mouse click / touchscreen tap at the center of the widget.
728  *
729  * Format:
730  * \code
731  *      kw_MouseClick(queryPath[,Qt::MouseButton])
732  * \endcode
733  *
734  * Example(s):
735  * \code
736  *      kw_MouseClick('widget')
737  *
738  *      kw_MouseClick('widget', RightButton)
739  * \endcode
740  *
741  * \param args Specifies widget (\a args[0]) to click/ tap. If (\a args[1]) is
742  *        not defined, left mouse button click is performed.
743  * \return True, if executed sucessfully; otherwise false.
744  * \sa <a href="http://doc.qt.nokia.com/4.7/qt.html#MouseButton-enum">enum Qt::MouseButton</a>
745  */
746 bool KeywordController::kw_MouseClick(const QStringList &args)
747 {
748     if (args.count() < 1 || args.count() >= 3) {
749         qCritical("kw_MouseClick: Invalid number of keyword arguments.\n"
750                   "Format: kw_MouseClick(queryPath[,Qt::MouseButton])"
751                   );
752         return false;
753     }
754
755     if (args.count() == 1) {
756         mouseClick(args[0]);
757     }
758     else {
759         int buttonValue = enumConstantToInteger(args[1], "MouseButtons");
760
761         if (buttonValue == -1) {
762             qCritical("kw_MouseClick: Invalid mouse button: %s", qPrintable(args[1]));
763             return false;
764         }
765         mouseClick(args[0], static_cast<Qt::MouseButton>(buttonValue));
766     }
767     return true;
768 }
769
770 /*!
771  * Convenience keyword for touchscreen devices. Simulates a touchscreen tap
772  * at the center of the widget.
773  *
774  * Format:
775  * \code
776  *      kw_Tap(queryPath)
777  * \endcode
778  *
779  * Example(s):
780  * \code
781  *      kw_Tap('widget')
782  * \endcode
783  *
784  * \param args Specifies widget (\a args[0]) to tap.
785  * \return True, if executed sucessfully; otherwise false.
786  * \sa kw_MouseClick
787  */
788 bool KeywordController::kw_Tap(const QStringList &args)
789 {
790     if (args.count() != 1) {
791         qCritical("kw_Tap: Invalid number of keyword arguments.\n"
792                   "Format: kw_Tap(queryPath)"
793                   );
794         return false;
795     }
796     return kw_MouseClick(args);
797 }
798
799 /*!
800  * Simulates a mouse click / touchscreen tap at the specified coordinates (x, y).
801  *
802  * Format:
803  * \code
804  *      kw_MouseClickRelative(x,y[,Qt::MouseButton])
805  * \endcode
806  *
807  * Example(s):
808  * \code
809  *      kw_MouseClickRelative(200, 300)
810  *
811  *      kw_MouseClickRelative(200, 300, RightButton)
812  * \endcode
813  *
814  * \param args Specifies x (\a args[0]) and y (\a args[1]) coordinates to click.
815  *        If (\a args[2]) is not defined, left mouse button click is performed.
816  * \return True, if executed sucessfully; otherwise false.
817  * \sa <a href="http://doc.qt.nokia.com/4.7/qt.html#MouseButton-enum">enum Qt::MouseButton</a>
818  */
819 bool KeywordController::kw_MouseClickRelative(const QStringList &args)
820 {
821     if (args.count() < 2 || args.count() >= 4) {
822         qCritical("kw_MouseClickRelative: Invalid number of keyword arguments.\n"
823                   "Format: kw_MouseClickRelative(x,y[,Qt::MouseButton])"
824                   );
825         return false;
826     }
827
828     bool ok;
829     int x = args.at(0).toInt(&ok);
830
831     if (!ok) {
832         qCritical("kw_MouseClickRelative: Invalid x coordinate: %s.",
833                   qPrintable(args[0]));
834         return false;
835     }
836
837     int y = args.at(1).toInt(&ok);
838
839     if (!ok) {
840         qCritical("kw_MouseClickRelative: Invalid y coordinate: %s.",
841                   qPrintable(args[1]));
842         return false;
843     }
844
845     if (args.count() == 2) {
846         mouseClick(x, y);
847     }
848     else {
849         int buttonValue = enumConstantToInteger(args[2], "MouseButtons");
850
851         if (buttonValue == -1) {
852             qCritical("kw_MouseClickRelative: Invalid mouse button: %s", qPrintable(args[2]));
853             return false;
854         }
855         mouseClick(x, y, static_cast<Qt::MouseButton>(buttonValue));
856     }
857     return true;
858 }
859
860 /*!
861  * Convenience keyword for touchscreen devices. Simulates a touchscreen tap
862  * at the specified coordinates (x, y).
863  *
864  * Format:
865  * \code
866  *      kw_TapRelative(x,y)
867  * \endcode
868  *
869  * Example(s):
870  * \code
871  *      kw_TapRelative(200, 300)
872  * \endcode
873  *
874  * \param args Specifies x (\a args[0]) and y (\a args[1]) coordinates to tap.
875  * \return True, if executed sucessfully; otherwise false.
876  * \sa kw_MouseClickRelative
877  */
878 bool KeywordController::kw_TapRelative(const QStringList &args)
879 {
880     if (args.count() != 2) {
881         qCritical("kw_TapRelative: Invalid number of keyword arguments.\n"
882                   "Format: kw_TapRelative(x,y)"
883                   );
884         return false;
885     }
886     return kw_MouseClickRelative(args);
887 }
888
889 /*!
890  * Simulates a mouse click and hold (press + wait + release) / touchscreen tap
891  * and hold (tap down + wait + release) at the center of a specified widget.
892  *
893  * Format:
894  * \code
895  *      kw_MouseClickHold(queryPath,duration[,Qt::MouseButton])
896  * \endcode
897  *
898  * Example(s):
899  * \code
900  *      kw_MouseClickHold('widget', 5000)
901  *
902  *      kw_MouseClickHold('widget', 5000, RightButton)
903  * \endcode
904  *
905  * \param args Specifies widget (\a args[0]) to click/ tap, wait for (\a args[1])
906  *        msecs and release. If (\a args[2]) is not specified, left mouse button
907  *        click is performed.
908  * \return True, if executed sucessfully; otherwise false.
909  * \sa <a href="http://doc.qt.nokia.com/4.7/qt.html#MouseButton-enum">enum Qt::MouseButton</a>
910  */
911 bool KeywordController::kw_MouseClickHold(const QStringList &args)
912 {
913     if (args.count() < 2 || args.count() >= 4) {
914         qCritical("kw_MouseClickHold: Invalid number of keyword arguments.\n"
915                   "Format: kw_MouseClickHold(queryPath,duration[,Qt::MouseButton]");
916         return false;
917     }
918
919     bool ok;
920     int duration = args.at(1).toInt(&ok);
921
922     if (!ok) {
923         qCritical("kw_MouseClickHold: Invalid duration value: %s.",
924                   qPrintable(args[1]));
925         return false;
926     }
927
928     if (args.count() == 2) {
929         mouseClickHold(args[0], duration);
930     }
931     else {
932         int buttonValue = enumConstantToInteger(args[2], "MouseButtons");
933
934         if (buttonValue == -1) {
935             qCritical("kw_MouseClickHold: Invalid mouse button: %s", qPrintable(args[2]));
936             return false;
937         }
938         mouseClickHold(args[0], duration, static_cast<Qt::MouseButton>(buttonValue));
939     }
940     return true;
941 }
942
943 /*!
944  * Convenience keyword for touchscreen devices. Simulates touchscreen tap and
945  * hold (tap down + wait + release) at the center of a specified widget.
946  *
947  * Format:
948  * \code
949  *      kw_TapHold(queryPath,duration)
950  * \endcode
951  *
952  * Example(s):
953  * \code
954  *      kw_TapHold('widget', 5000)
955  * \endcode
956  *
957  * \param args Specifies widget (\a args[0]) to tap, wait for (\a args[1]) msecs
958  *        and release.
959  * \return True, if executed sucessfully; otherwise false.
960  * \sa kw_MouseClickHold
961  */
962 bool KeywordController::kw_TapHold(const QStringList &args)
963 {
964     if (args.count() != 2) {
965         qCritical("kw_TapHold: Invalid number of keyword arguments.\n"
966                   "Format: kw_MouseTapHold(queryPath,duration)"
967                   );
968         return false;
969     }
970     return kw_MouseClickHold(args);
971 }
972
973 /*!
974  * Simulates a mouse click and hold (press + wait + release) / touchscreen tap
975  * and hold (tap down + wait + release) at the specified coordinates.
976  *
977  * Format:
978  * \code
979  *      kw_MouseClickHoldRelative(x,y,duration[,Qt::MouseButton])
980  * \endcode
981  *
982  * Example(s):
983  * \code
984  *      kw_MouseClickHoldRelative(200, 300, 5000)
985  *
986  *      kw_MouseClickHoldRelative(200, 300, 5000, RightButton)
987  * \endcode
988  *
989  * \param args Specifies x (\a args[0]) and y (\a args[1]) coordinates to
990  *        click/ tap, wait for (\a args[2]) msecs and release.
991  *        If (\a args[2]) is not specified, left mouse button click is performed.
992  * \return True, if executed sucessfully; otherwise false.
993  * \sa <a href="http://doc.qt.nokia.com/4.7/qt.html#MouseButton-enum">enum Qt::MouseButton</a>
994  */
995 bool KeywordController::kw_MouseClickHoldRelative(const QStringList &args)
996 {
997     if (args.count() < 3 || args.count() >= 5) {
998         qCritical("kw_MouseClickHoldRelative: Invalid number of keyword arguments.\n"
999                   "Format: kw_MouseClickHoldRelative(x,y,duration[,Qt::MouseButton]");
1000         return false;
1001     }
1002
1003     bool ok;
1004     int x = args.at(0).toInt(&ok);
1005
1006     if (!ok) {
1007         qCritical("kw_MouseClickHoldRelative: Invalid x coordinate: %s.",
1008                   qPrintable(args[0]));
1009         return false;
1010     }
1011
1012     int y = args.at(1).toInt(&ok);
1013
1014     if (!ok) {
1015         qCritical("kw_MouseClickHoldRelative: Invalid y coordinate: %s.",
1016                   qPrintable(args[1]));
1017         return false;
1018     }
1019
1020     int duration = args.at(2).toInt(&ok);
1021
1022     if (!ok) {
1023         qCritical("kw_MouseClickHoldRelative: Invalid duration value: %s.",
1024                   qPrintable(args[1]));
1025         return false;
1026     }
1027
1028     if (args.count() == 3) {
1029         mouseClickHold(x, y, duration);
1030     }
1031     else {
1032         int buttonValue = enumConstantToInteger(args[3], "MouseButtons");
1033
1034         if (buttonValue == -1) {
1035             qCritical("kw_MouseClickHoldRelative: Invalid mouse button: %s", qPrintable(args[3]));
1036             return false;
1037         }
1038         mouseClickHold(x, y, duration, static_cast<Qt::MouseButton>(buttonValue));
1039     }
1040     return true;
1041 }
1042
1043 /*!
1044  * Convenience keyword for touchscreen devices. Simulates a touchscreen tap and
1045  * hold (tap + wait + release) at the specified coordinates.
1046  *
1047  * Format:
1048  * \code
1049  *      kw_TapHoldRelative(x,y,duration)
1050  * \endcode
1051  *
1052  * Example(s):
1053  * \code
1054  *      kw_TapHoldRelative(200, 300, 5000)
1055  * \endcode
1056  *
1057  * \param args Specifies x (\a args[0]) and y (\a args[1]) coordinates to
1058  *        tap, wait for (\a args[2]) msecs and release.
1059  * \return True, if executed sucessfully; otherwise false.
1060  * \sa kw_MouseClickHoldRelative
1061  */
1062 bool KeywordController::kw_TapHoldRelative(const QStringList &args)
1063 {
1064     if (args.count() != 3) {
1065         qCritical("kw_TapHoldRelative: Invalid number of keyword arguments.\n"
1066                   "Format: kw_MouseTapHoldRelative(x,y,duration)"
1067                   );
1068         return false;
1069     }
1070     return kw_MouseClickHoldRelative(args);
1071 }
1072
1073 /*!
1074  * Simulates a mouse press/ touchscreen down tap at the center of the widget.
1075  *
1076  * Format:
1077  * \code
1078  *      kw_MousePress(queryPath[,Qt::MouseButton])
1079  * \endcode
1080  *
1081  * Example(s):
1082  * \code
1083  *      kw_MousePress('widget')
1084  *
1085  *      kw_MousePress('widget', RightButton)
1086  * \endcode
1087  *
1088  * \param args Specifies widget (\a args[0]) to press/ tap down. If (\a args[1]) is
1089  *        not defined, left mouse button press is performed.
1090  * \return True, if executed sucessfully; otherwise false.
1091  * \sa <a href="http://doc.qt.nokia.com/4.7/qt.html#MouseButton-enum">enum Qt::MouseButton</a>
1092  */
1093 bool KeywordController::kw_MousePress(const QStringList &args)
1094 {
1095     if (args.count() < 1 || args.count() >= 3) {
1096         qCritical("kw_MousePress: Invalid number of keyword arguments.\n"
1097                   "Format: kw_MousePress(queryPath[,Qt::MouseButton])"
1098                   );
1099         return false;
1100     }
1101
1102     if (args.count() == 1) {
1103         mousePress(args[0]);
1104     }
1105     else {
1106         int buttonValue = enumConstantToInteger(args[1], "MouseButtons");
1107
1108         if (buttonValue == -1) {
1109             qCritical("kw_MousePress: Invalid mouse button: %s", qPrintable(args[1]));
1110             return false;
1111         }
1112         mousePress(args[0], static_cast<Qt::MouseButton>(buttonValue));
1113     }
1114     return true;
1115 }
1116
1117 /*!
1118  * Convenience keyword for touchscreen devices. Simulates a touchscreen down tap
1119  * at the center of the widget.
1120  *
1121  * Format:
1122  * \code
1123  *      kw_TapDown(queryPath)
1124  * \endcode
1125  *
1126  * Example(s):
1127  * \code
1128  *      kw_TapDown('widget')
1129  * \endcode
1130  *
1131  * \param args Specifies widget (\a args[0]) to tap.
1132  * \return True, if executed sucessfully; otherwise false.
1133  * \sa kw_MousePress
1134  */
1135 bool KeywordController::kw_TapDown(const QStringList &args)
1136 {
1137     if (args.count() != 1) {
1138         qCritical("kw_TapDown: Invalid number of keyword arguments.\n"
1139                   "Format: kw_TapDown(queryPath)"
1140                   );
1141         return false;
1142     }
1143     return kw_MousePress(args);
1144 }
1145
1146 /*!
1147  * Simulates a mouse press/ touchscreen down tap at the specified coordinates.
1148  *
1149  * Format:
1150  * \code
1151  *      kw_MousePressRelative(x,y[,Qt::MouseButton])
1152  * \endcode
1153  *
1154  * Example(s):
1155  * \code
1156  *      kw_MousePressRelative(200, 300)
1157  *
1158  *      kw_MousePressRelative(200, 300, RightButton)
1159  * \endcode
1160  *
1161  * \param args Specifies x (\a args[0]) and y (\a args[1]) coordinates to
1162  *        press/ tap down. If (\a args[2]) is not defined, left mouse
1163  *        button press is performed.
1164  * \return True, if executed sucessfully; otherwise false.
1165  * \sa <a href="http://doc.qt.nokia.com/4.7/qt.html#MouseButton-enum">enum Qt::MouseButton</a>
1166  */
1167 bool KeywordController::kw_MousePressRelative(const QStringList &args)
1168 {
1169     if (args.count() < 2 || args.count() >= 4) {
1170         qCritical("kw_MousePressRelative: Invalid number of keyword arguments.\n"
1171                   "Format: kw_MousePressRelative(x,y[,Qt::MouseButton])"
1172                   );
1173         return false;
1174     }
1175
1176     bool ok;
1177     int x = args.at(0).toInt(&ok);
1178
1179     if (!ok) {
1180         qCritical("kw_MousePressRelative: Invalid x coordinate: %s.",
1181                   qPrintable(args[0]));
1182         return false;
1183     }
1184
1185     int y = args.at(1).toInt(&ok);
1186
1187     if (!ok) {
1188         qCritical("kw_MousePressRelative: Invalid y coordinate: %s.",
1189                   qPrintable(args[1]));
1190         return false;
1191     }
1192
1193     if (args.count() == 2) {
1194         mousePress(x, y);
1195     }
1196     else {
1197         int buttonValue = enumConstantToInteger(args[2], "MouseButtons");
1198
1199         if (buttonValue == -1) {
1200             qCritical("kw_MousePressRelative: Invalid mouse button: %s", qPrintable(args[2]));
1201             return false;
1202         }
1203         mousePress(x, y, static_cast<Qt::MouseButton>(buttonValue));
1204     }
1205     return true;
1206 }
1207
1208 /*!
1209  * Convenience keyword for touchscreen devices. Simulates a touchscreen down
1210  * tap at the specified coordinates (x, y).
1211  *
1212  * Format:
1213  * \code
1214  *      kw_TapDownRelative(x,y)
1215  * \endcode
1216  *
1217  * Example(s):
1218  * \code
1219  *      kw_TapDownRelative(200, 300)
1220  * \endcode
1221  *
1222  * \param args Specifies x (\a args[0]) and y (\a args[1]) coordinates to tap.
1223  * \return True, if executed sucessfully; otherwise false.
1224  * \sa kw_MousePressRelative
1225  */
1226 bool KeywordController::kw_TapDownRelative(const QStringList &args)
1227 {
1228     if (args.count() != 2) {
1229         qCritical("kw_TapDownRelative: Invalid number of keyword arguments.\n"
1230                   "Format: kw_TapDownRelative(x,y)"
1231                   );
1232         return false;
1233     }
1234     return kw_MouseClickRelative(args);
1235 }
1236
1237 /*!
1238  * Simulates a mouse press/ touchscreen release at the center of the
1239  * specified widget.
1240  *
1241  * Format:
1242  * \code
1243  *      kw_MouseRelease(queryPath[,Qt::MouseButton])
1244  * \endcode
1245  *
1246  * Example(s):
1247  * \code
1248  *      kw_MouseRelease('widget')
1249  *
1250  *      kw_MouseRelease('widget', RightButton)
1251  * \endcode
1252  *
1253  * \param args Specifies widget (\a args[0]) to release. If (\a args[1]) is
1254  *        not defined, left mouse button release is performed.
1255  * \return True, if executed sucessfully; otherwise false.
1256  * \sa <a href="http://doc.qt.nokia.com/4.7/qt.html#MouseButton-enum">enum Qt::MouseButton</a>
1257  */
1258 bool KeywordController::kw_MouseRelease(const QStringList &args)
1259 {
1260     if (args.count() < 1 || args.count() >= 3) {
1261         qCritical("kw_MouseRelease: Invalid number of keyword arguments.\n"
1262                   "Format: kw_MouseRelease(queryPath[,Qt::MouseButton])"
1263                   );
1264         return false;
1265     }
1266
1267     if (args.count() == 1) {
1268         mouseRelease(args[0]);
1269     }
1270     else {
1271         int buttonValue = enumConstantToInteger(args[1], "MouseButtons");
1272
1273         if (buttonValue == -1) {
1274             qCritical("kw_MouseRelease: Invalid mouse button: %s", qPrintable(args[1]));
1275             return false;
1276         }
1277         mouseRelease(args[0], static_cast<Qt::MouseButton>(buttonValue));
1278     }
1279     return true;
1280 }
1281
1282 /*!
1283  * Convenience keyword for touchscreen devices. Simulates a touchscreen release
1284  * at the center of the widget.
1285  *
1286  * Format:
1287  * \code
1288  *      kw_TapRelease(queryPath)
1289  * \endcode
1290  *
1291  * Example(s):
1292  * \code
1293  *      kw_TapRelease('widget')
1294  * \endcode
1295  *
1296  * \param args Specifies widget (\a args[0]) to tap.
1297  * \return True, if executed sucessfully; otherwise false.
1298  * \sa kw_MouseRelease
1299  */
1300 bool KeywordController::kw_TapRelease(const QStringList &args)
1301 {
1302     if (args.count() != 1) {
1303         qCritical("kw_TapRelease: Invalid number of keyword arguments.\n"
1304                   "Format: kw_TapRelease(queryPath)"
1305                   );
1306         return false;
1307     }
1308     return kw_MouseRelease(args);
1309 }
1310
1311 /*!
1312  * Simulates a mouse press/ touchscreen release at the specified coordinates.
1313  *
1314  * Format:
1315  * \code
1316  *      kw_MouseReleaseRelative(x,y[,Qt::MouseButton])
1317  * \endcode
1318  *
1319  * Example(s):
1320  * \code
1321  *      kw_MouseReleaseRelative(200, 300)
1322  *
1323  *      kw_MouseReleaseRelative(200, 300, RightButton)
1324  * \endcode
1325  *
1326  * \param args Specifies x (\a args[0]) and y (\a args[1]) coordinates to
1327  *        release. If (\a args[2]) is not defined, left mouse
1328  *        button release is performed.
1329  * \return True, if executed sucessfully; otherwise false.
1330  * \sa <a href="http://doc.qt.nokia.com/4.7/qt.html#MouseButton-enum">enum Qt::MouseButton</a>
1331  */
1332 bool KeywordController::kw_MouseReleaseRelative(const QStringList &args)
1333 {
1334     if (args.count() < 2 || args.count() >= 4) {
1335         qCritical("kw_MouseReleaseRelative: Invalid number of keyword arguments.\n"
1336                   "Format: kw_MouseReleaseRelative(x,y[,Qt::MouseButton])"
1337                   );
1338         return false;
1339     }
1340
1341     bool ok;
1342     int x = args.at(0).toInt(&ok);
1343
1344     if (!ok) {
1345         qCritical("kw_MouseReleaseRelative: Invalid x coordinate: %s.",
1346                   qPrintable(args[0]));
1347         return false;
1348     }
1349
1350     int y = args.at(1).toInt(&ok);
1351
1352     if (!ok) {
1353         qCritical("kw_MouseReleaseRelative: Invalid y coordinate: %s.",
1354                   qPrintable(args[1]));
1355         return false;
1356     }
1357
1358     if (args.count() == 2) {
1359         mouseRelease(x, y);
1360     }
1361     else {
1362         int buttonValue = enumConstantToInteger(args[2], "MouseButtons");
1363
1364         if (buttonValue == -1) {
1365             qCritical("kw_MouseReleaseRelative: Invalid mouse button: %s", qPrintable(args[2]));
1366             return false;
1367         }
1368         mouseRelease(x, y, static_cast<Qt::MouseButton>(buttonValue));
1369     }
1370     return true;
1371 }
1372
1373 /*!
1374  * Convenience keyword for touchscreen devices. Simulates a touchscreen down
1375  * release at the specified coordinates (x, y).
1376  *
1377  * Format:
1378  * \code
1379  *      kw_TapReleaseRelative(x,y)
1380  * \endcode
1381  *
1382  * Example(s):
1383  * \code
1384  *      kw_TapReleaseRelative(200, 300)
1385  * \endcode
1386  *
1387  * \param args Specifies x (\a args[0]) and y (\a args[1]) coordinates to release.
1388  * \return True, if executed sucessfully; otherwise false.
1389  * \sa kw_MouseReleaseRelative
1390  */
1391 bool KeywordController::kw_TapReleaseRelative(const QStringList &args)
1392 {
1393     if (args.count() != 2) {
1394         qCritical("kw_TapReleaseRelative: Invalid number of keyword arguments.\n"
1395                   "Format: kw_TapReleaseRelative(x,y)"
1396                   );
1397         return false;
1398     }
1399     return kw_MouseReleaseRelative(args);
1400 }
1401
1402 /*!
1403  * Verifies text from the screen or widget.
1404  *
1405  * Format:
1406  * \code
1407  *      kw_VerifyText(text[,queryPath])
1408  * \endcode
1409  *
1410  * Example(s):
1411  * \code
1412  *      kw_VerifyText('some text')
1413  *
1414  *      kw_VerifyText('some text', 'widget')
1415  * \endcode
1416  *
1417  * \param args Specifies text (\a args[0]) to search from (\a args[1])
1418  * query path.
1419  * \return True, if executed sucessfully; otherwise false.
1420  */
1421 bool KeywordController::kw_VerifyText(const QStringList &args)
1422 {
1423     if (args.count() < 1 || args.count() >= 3) {
1424         qCritical("kw_VerifyText: Invalid number of keyword arguments.\n"
1425                   "Format: kw_VerifyText(text[,queryPath])"
1426                   );
1427         return false;
1428     }
1429
1430     QString text; // Text from widget.
1431
1432     if (args.count() == 2) {
1433         text = getText(args[1]);
1434         if (queryFailed()) {
1435             fail(QString("Failed to get text from widget: %1.").arg(args[1]));
1436             return true;
1437         }
1438     }
1439     else {
1440         text = getText();
1441         if (queryFailed()) {
1442             fail("Failed to get text from application.");
1443             return true;
1444         }
1445     }
1446
1447     if (!text.contains(args[0]))
1448         fail(QString("Expected: %1 != Current: %2").arg(args[0]).arg(text));
1449
1450     return true;
1451 }
1452
1453 /*!
1454  * Verifies the current window title of the application specified.
1455  *
1456  * Format:
1457  * \code
1458  *      kw_VerifyTitle(title[,queryPath])
1459  * \endcode
1460  *
1461  * Example(s):
1462  * \code
1463  *      kw_VerifyTitle('Calculator')
1464  *
1465  *      kw_VerifyTitle('View title', 'TestApplication')
1466  * \endcode
1467  *
1468  * \param args Specifies application title (\a args[0]) to search from (\a args[1])
1469  * query path. Query path has to be an application.
1470  * \return True, if executed sucessfully; otherwise false.
1471  */
1472 bool KeywordController::kw_VerifyTitle(const QStringList &args)
1473 {
1474     if (args.count() < 1 || args.count() >= 3) {
1475         qCritical("kw_VerifyTitle: Invalid number of keyword arguments.\n"
1476                   "Format: kw_VerifyTitle(title[,queryPath])"
1477                   );
1478         return false;
1479     }
1480
1481     QString title; // Application title.
1482
1483     if (args.count() == 2) {
1484         title = currentTitle(args[1]);
1485         if (queryFailed()) {
1486             fail(QString("Failed to get title from application: %1.").arg(args[1]));
1487             return true;
1488         }
1489     }
1490     else {
1491         title = currentTitle();
1492         if (queryFailed()) {
1493             fail("Failed to get current title.");
1494             return true;
1495         }
1496     }
1497
1498     if (!title.contains(args[0]))
1499         fail(QString("Expected: %1 != Current: %2").arg(args[0]).arg(title));
1500
1501     return true;
1502 }
1503
1504 bool KeywordController::kw_VerifyProperty(const QStringList &/*args*/)
1505 {
1506     /*! \todo Implement kw_VerifyProperty */
1507     return false;
1508 }
1509
1510 /*!
1511  * Waits for text to appear in the widget specified by query path.
1512  *
1513  * Format:
1514  * \code
1515  *      kw_WaitForText(timeout,text[,queryPath])
1516  * \endcode
1517  *
1518  * Example(s):
1519  * \code
1520  *      kw_WaitForText(5, 'John')
1521  *
1522  *      kw_WaitForText(5, 'John', 'Name')
1523  * \endcode
1524  *
1525  * \param args Specifies seconds (\a args[0]) to wait for text (\a args[1])
1526  *        to appear in the query path (\a args[2]).
1527  * \return True, if executed sucessfully; otherwise false.
1528  * \sa kw_VerifyText
1529  */
1530 bool KeywordController::kw_WaitForText(const QStringList &args)
1531 {   
1532     if (args.count() < 2 || args.count() >= 4) {
1533         qCritical("kw_WaitForText: Invalid number of keyword arguments.\n"
1534                   "Format: kw_WaitForText(timeout,text[,queryPath])"
1535                   );
1536         return false;
1537     }
1538
1539     bool ok;
1540     int timeout = args.at(0).toInt(&ok);
1541
1542     if (!ok) {
1543         qCritical("kw_WaitForText: %s is not a valid timeout value.",
1544                   qPrintable(args[0]));
1545         return false;
1546     }
1547
1548     QString text;
1549     m_verificationTimeout = false;
1550
1551     m_verificationTimerId = startTimer(timeout * 1000);
1552     if (m_verificationTimerId == 0) {
1553         qCritical("Failed to start timer.");
1554         return false;
1555     }
1556
1557     do {
1558         if (args.count() == 2) {
1559             text = getText();
1560         }
1561         else {
1562             text = getText(args[2]);
1563         }
1564
1565         if (queryFailed()) {
1566             fail(QString("Failed to get text: %1.").arg(args[1]));
1567             killTimer(m_verificationTimerId);
1568             return true;
1569         }
1570         // Break, if text is found.
1571         if (text.contains(args[1])) break;
1572
1573     } while (!m_verificationTimeout);
1574
1575     if (m_verificationTimeout) {
1576         fail(QString("Failed to find text: %1, within %2 seconds.")
1577              .arg(args[1]).arg(args[0]));
1578     }
1579     killTimer(m_verificationTimerId);
1580     return true;
1581 }
1582
1583
1584 /*!
1585  * Starts the specified application.
1586  *
1587  * Format:
1588  * \code
1589  *      kw_StartApplication(application[,{arguments}][,timeout][,QSystemTest::StartApplicationFlag])
1590  * \endcode
1591  *
1592  * Example(s):
1593  * \code
1594  *      kw_StartApplication('testapp')
1595  *
1596  *      kw_StartApplication('testapp', {-opt1 arg1, -opt2 arg2}, 10000, NoFlag)
1597  * \endcode
1598  *
1599  * \param args Specifies application (\a args[0]) to launch with arguments
1600  * (\a args[1]). Keyword fails application doesn't connect to test framework
1601  * within (\a args[2]) msecs. args[3] specifies additional behaviour.
1602  * \return True, if executed sucessfully; otherwise false.
1603  */
1604 bool KeywordController::kw_StartApplication(const QStringList &args)
1605 {
1606     if (args.count() < 1 || args.count() >= 5) {
1607         qCritical("kw_StartApplication: Invalid number of keyword arguments.\n"
1608                   "Format: kw_StartApplication(application[,{arguments}]"
1609                   "[,timeout][,QSystemTest::StartApplicationFlag])"
1610                   );
1611         return false;
1612     }
1613     // Keyword kw_StartApplication cannot fail.
1614     m_current->setCanFail(false);
1615
1616     if (args.count() == 1) {
1617         // Launch application without arguments.
1618         startApplication(args[0]);
1619         return true;
1620     }
1621
1622     QStringList argumentList = QStringList(); // Application argument.
1623     int timeout = 5000; // Timeout to wait for application to connect test framework.
1624     QSystemTest::StartApplicationFlag flag = QSystemTest::WaitForFocus; // Wait for keyboard focus.
1625
1626     if (args.count() >= 2) {
1627         QString arguments = args[1];
1628         arguments.remove(QChar('{'));
1629         arguments.remove(QChar('}'));
1630         arguments.replace(QChar(' '), QChar(','));
1631
1632         if (!arguments.isEmpty()) {
1633             argumentList = arguments.split(",", QString::SkipEmptyParts);
1634             QMutableStringListIterator iter(argumentList);
1635
1636             while (iter.hasNext()) {
1637                 QString item = iter.next();
1638                 item.trimmed();
1639                 iter.setValue(item);
1640             }
1641         }
1642     }
1643
1644     if (args.count() >= 3 && !args.at(2).isEmpty()) {
1645         bool ok;
1646         timeout = args.at(2).toInt(&ok);
1647         if (!ok) {
1648             qWarning("Invalid timeout value: %s. Using default value.",
1649                 qPrintable(args[2]));
1650             timeout = 5000;
1651         }
1652     }
1653
1654     if (args.count() == 4 && !args.at(3).isEmpty()) {
1655
1656         if (args.at(3).contains("NoFlag")) {
1657             flag = QSystemTest::NoFlag;
1658         }
1659         else if (args.at(3).contains("WaitForFocus")) {
1660             flag = QSystemTest::WaitForFocus;
1661         }
1662         else if (args.at(3).contains("BackgroundCurrentApplication")) {
1663             flag = QSystemTest::BackgroundCurrentApplication;
1664         }
1665         else {
1666             qWarning("Invalid flag: %s. Using default.", qPrintable(args[3]));
1667         }
1668     }
1669
1670     startApplication(args[0], argumentList, timeout, flag);
1671     return true;
1672 }
1673
1674 /*!
1675  * Wait for milliseconds, while still processing events from the event loop.
1676  *
1677  * Format:
1678  * \code
1679  *      kw_Wait(msecs)
1680  * \endcode
1681  *
1682  * Example(s):
1683  * \code
1684  *      kw_Wait(5000)
1685  * \endcode
1686  *
1687  * \param args Specifies milliseconds (\a args[0]) to wait.
1688  * \return True, if executed sucessfully; otherwise false.
1689  */
1690 bool KeywordController::kw_Wait(const QStringList &args)
1691 {
1692     if (args.count() != 1) {
1693         qCritical("kw_Wait: Invalid number of keyword arguments.\n"
1694                   "Format: kw_Wait(msecs)"
1695                   );
1696         return false;
1697     }
1698
1699     bool ok;
1700     int msecs = args.at(0).toInt(&ok);
1701
1702     if (!ok) {
1703         qCritical("kw_Wait: Invalid msecs value: %s.", qPrintable(args[0]));
1704         return false;
1705     }
1706     wait(msecs);
1707     return true;
1708 }
1709
1710 /*! @} */
1711
1712 // Protected methods.
1713
1714 void KeywordController::timerEvent(QTimerEvent *event)
1715 {
1716     Q_UNUSED(event);
1717     // Kill timer and set timeout flag.
1718     killTimer(m_verificationTimerId);
1719     m_verificationTimeout = true;
1720 }
1721
1722 // Private Methods.
1723
1724 /*!
1725  * Returns integer value of \a key constant from enumeration \a type used by Qt.
1726  *
1727  * \param key Name of the constant.
1728  * \param type Enumeration type to search from.
1729  * \return Integer value of constant.
1730  */
1731 int KeywordController::enumConstantToInteger(const QString &key, const QString &type)
1732 {
1733     int index = QObject::staticQtMetaObject.indexOfEnumerator(type.toLatin1().constData());
1734     QMetaEnum metaEnum = QObject::staticQtMetaObject.enumerator(index);
1735
1736     return metaEnum.keyToValue(key.toLatin1().constData());
1737 }