Sunday, September 12, 2010

QtCreator IDE Tips

To quickly switch between different modes.

Switching between modes




  • Welcome mode Ctrl+1
  • Edit mode Ctrl+2
  • Design mode Ctrl+3
  • Debug mode Ctrl+4
  • Projects mode Ctrl+5
  • Help mode Ctrl+6

Moving Between Open Files


press Ctrl+Tab.

Moving To the Edit Mode - and currently active file.


press Esc.

Showing and Hiding the Sidebar


press Alt+0 or 
Cmd+0 on Mac OS X

Default Keyboard Shortcuts

Action                                       
                                                         Keyboard shortcut


Open file or project                                                                                                           ctrl+o                 
                              

New file or project                                                                                                           Ctrl+N                 
                               

Open in external editor                                                                                                  Alt+V, Alt+I            
Go back                                                                                                        Alt+Left                                    
Go forward                                                                                                        Alt+Right                              
Activate Locator                                                                                                       ctrl+k                           
Auto-indent selection                                                                                                           ctrl+I                  
Collapse                                                                                                           Ctrl+<                                     
Expand                                                                                                           ctrl+>                                       
Trigger a completion in this scope                                                                               Ctrl+Space                  
Copy line down                                                                                                           Ctrl+Alt+Down            
Copy line up                                                                                                          Ctrl+Alt+Up                      
Cut line                                                                                                         Shift+Del                                    
Join lines                                                                                                           Ctrl+J                                     
Decrease font size                                                                                            ctrl+-                                       
Increase font size                                                                                            Ctrl++                                       
Toggle Vim-style editing                                                                               Alt+V, Alt+V                              
Enable text wrapping                                                                                         Ctrl+E, Ctrl+W                      
Visualize whitespace                                                                                         Ctrl+E, Ctrl+V                         
Adjust size                                                                                                        Ctrl+J                                      


Start debugging                                                                                                          F5                    


Stop or interrupt debugger                                                                                       Shift+F5                   


Reset debugger                                                                                                        Ctrl+Shift+F5


Step over                                                                                                       F10                  

Step into                                                                                                        F11                    

Step out                                                                                                     Shift+F11
                                                                                                                     

Toggle breakpoint                                                                                     F9
              

Build project                                                                                        Ctrl+B
                                                                                                                      F1               
View context-sensitive help

Build all                                                                                                         Build all                   



QSignalSpy Introspection



    QTime timer;
    timer.start();
    while(timer.elapsed() < 300 && !spy.count())
    QCoreApplication::processEvents();

    QCOMPARE(spy.count(), 1);

Tuesday, August 31, 2010

Testing Qt slots and signals

Testing slots

Testing slots is very easy, because a slot is just a specially annotated method. You can call slots just like any other method you'd like to test, as shown below:
Example 25. QLabel test code, showing testing of a couple of slots
  1. #include
  2. #include
  3. #include
  4.  
  5. class testLabel: public QObject
  6. {
  7. Q_OBJECT
  8. private slots:
  9. void testChanges();
  10. };
  11.  
  12. void testLabel::testChanges()
  13. {
  14. QLabel label;
  15.  
  16. // setNum() is a QLabel slot, but we can just call it like any
  17. // other method.
  18. label.setNum( 3 );
  19. QCOMPARE( label.text(), QString("3") );
  20.  
  21. // clear() is also a slot.
  22. label.clear();
  23. QVERIFY( label.text().isEmpty() );
  24. }
  25.  
  26. QTEST_MAIN(testLabel)
  27. #include "tutorial5.moc"

Testing signals

Testing of signals is a little more difficult than testing of slots, however Qt offers a very useful class called QSignalSpy that helps a lot.
QSignalSpy is a class provided with Qt that allows you to record the signals that have been emitted from a particular QObject subclass object. You can then check that the right number of signals have been emitted, and that the right kind of signals were emitted. You can find more information on the QSignalSpy class in your Qt documentation.
An example of how you can use QSignalSpy to test a class that has signals is shown below.
Example 26. QCheckBox test code, showing testing of signals
  1. #include
  2. #include
  3. #include
  4.  
  5. class testCheckBox: public QObject
  6. {
  7. Q_OBJECT
  8. private slots:
  9. void testSignals();
  10. };
  11.  
  12. void testCheckBox::testSignals()
  13. {
  14. // You don't need to use an object created with "new" for
  15. // QSignalSpy, I just needed it in this case to test the emission
  16. // of a destroyed() signal.
  17. QCheckBox *xbox = new QCheckBox;
  18.  
  19. // We are going to have two signal monitoring classes in use for
  20. // this test.
  21. // The first monitors the stateChanged() signal.
  22. // Also note that QSignalSpy takes a pointer to the object.
  23. QSignalSpy stateSpy( xbox, SIGNAL( stateChanged(int) ) );
  24.  
  25. // Not strictly necessary, but I like to check that I have set up
  26. // my QSignalSpy correctly.
  27. QVERIFY( stateSpy.isValid() );
  28.  
  29. // Now we check to make sure we don't have any signals already
  30. QCOMPARE( stateSpy.count(), 0 );
  31.  
  32. // Here is a second monitoring class - this one for the
  33. // destroyed() signal.
  34. QSignalSpy destroyedSpy( xbox, SIGNAL( destroyed() ) );
  35. QVERIFY( destroyedSpy.isValid() );
  36.  
  37. // A sanity check to verify the initial state
  38. // This also shows that you can mix normal method checks with
  39. // signal checks.
  40. QCOMPARE( xbox->checkState(), Qt::Unchecked );
  41.  
  42. // Shouldn't already have any signals
  43. QCOMPARE( destroyedSpy.count(), 0 );
  44.  
  45. // If we change the state, we should get a signal.
  46. xbox->setCheckState( Qt::Checked );
  47. QCOMPARE( stateSpy.count(), 1 );
  48.  
  49. xbox->setCheckState( Qt::Unchecked );
  50. QCOMPARE( stateSpy.count(), 2 );
  51.  
  52. xbox->setCheckState( Qt::PartiallyChecked );
  53. QCOMPARE( stateSpy.count(), 3 );
  54.  
  55. // If we destroy the object, the signal should be emitted.
  56. delete xbox;
  57.  
  58. // So the count of objects should increase.
  59. QCOMPARE( destroyedSpy.count(), 1 );
  60.  
  61. // We can also review the signals that we collected
  62. // QSignalSpy is really a QList of QLists, so we take the first
  63. // list, which corresponds to the arguments for the first signal
  64. // we caught.
  65. QList<QVariant> firstSignalArgs = stateSpy.takeFirst();
  66. // stateChanged() only has one argument - an enumerated type (int)
  67. // So we take that argument from the list, and turn it into an integer.
  68. int firstSignalState = firstSignalArgs.at(0).toInt();
  69. // We can then check we got the right kind of signal.
  70. QCOMPARE( firstSignalState, static_cast<int>(Qt::Checked) );
  71.  
  72. // check the next signal - note that takeFirst() removes from the list
  73. QList<QVariant> nextSignalArgs = stateSpy.takeFirst();
  74. // this shows another way of fudging the argument types
  75. Qt::CheckState nextSignalState = (Qt::CheckState)nextSignalArgs.at(0).toInt();
  76. QCOMPARE( nextSignalState, Qt::Unchecked );
  77.  
  78. // and again for the third signal
  79. nextSignalArgs = stateSpy.takeFirst();
  80. nextSignalState = (Qt::CheckState)nextSignalArgs.at(0).toInt();
  81. QCOMPARE( nextSignalState, Qt::PartiallyChecked );
  82. }
  83.  
  84. QTEST_MAIN(testCheckBox)
  85. #include "tutorial5a.moc"
The first 11 lines are essentially unchanged from previous examples that we've seen. Line 15 creates the object that will be tested - as noted in the comments in lines 12-14, the only reason that I'm creating it with new is because I need to delete it in line 45 to cause the destroyed() signal to be emitted.
Line 20 sets up the first of our two QSignalSpy instances. The one in line 20 monitors the stateChanged(int) signal, and the one in line 29 monitors the destroyed() signal. If you get the name or signature of the signal wrong (for example, if you use stateChanged() instead of stateChanged(int)), then this will not be caught at compile time, but will result in a runtime failure. You can test if things were set up correctly using the isValid(), as shown in lines 24 and 30.
As shown in line 34, there is no reason why you cannot test normal methods, signals and slots in the same test.
Line 38 changes the state of the object under test, which is supposed to result in a stateChanged(int) signal being emitted. Line 39 checks that the number of signals increases from zero to one. Lines 40 and 41 repeat the process, and again in lines 42 and 43.
Line 45 deletes the object under test, and line 47 tests that the destroyed() signal has been emitted.
For signals that have arguments (such as our stateChanged(int) signal), you may also wish to check that the arguments were correct. You can do this by looking at the list of signal arguments. Exactly how you do this is fairly flexible, however for simple tests like the one in the example, you can manually work through the list using takeFirst() and check that each argument is correct. This is shown in line 52, 55 and 57 for the first signal. The same approach is shown in lines 59, 61 and 62 for the second signal, and the in lines 64 to 66 for the third signal. For a more complex set of tests, you may wish to apply some data driven techniques.

Dica
noframe
Note: You should be aware that, for some class implementations, you may need to return control to the event loop to have signals emitted. If you need this, try using the QTest::qWait() function.