Appendix A. Reading the Qt Documentation

Qt is originally a C++ GUI toolkit, and PyQt is just a wrapper around it. Fortunately, Qt is very well designed and makes full use of the object-oriented qualities of C++, so the translation is very comfortable, and PyQt feel like a real Python library.

BlackAdder includes a copy of the Qt class documentation (nineteen megabytes of html text) that has been fully translated to Python. Of course, if you want to use a more recent version of PyQt than that which comes with BlackAdder, or if you use PyQt on itself, then you need to read the C++ documentation for all the details that I didn't have space to discuss in this book. After all, this book teaches you how to use the toolkit to create complete applications, and isn't a mere duplication of the class documentation.

Fortunately, reading C++ documentation for use from Python isn't very difficult. In fact, the translation to Python idiom that is included with BlackAdder has been achieved for the greater part with a few find & replace scripts. However, if your knowledge of C++ (or C) is limited to knowing that it exists, then you might want to read this appendix for some guidance.

Using KDE to have quick access to the Qt documentation: If you are using KDE on Unix/X11, you can create new internet shortcuts that take you to the Qt class documentation in an instant.

KDE has a wonderful feature, called the run command window, in which you can type a short abbreviation (like "gg" for the Google search engine), followed by a colon and an argument.

If you add "file://usr/lib/qt2/doc/html/\1.html" in KControl, section Web Browsing/Enhanced Browsing:

Creating a shortcut to the Qt documentation

Then you will be able to access al Qt documentation by typing "qt:qobject", for instance. What you are typing is the name of the html document that contains the class information: all these documents have the classname as a filename, all in lowercase.

Using a shortcut to the Qt documentation

Note that the shortcut (file://usr/lib/qt2/doc/html/\1.html) should point to the place where your qt (or BlackAdder - that would work too) documentation resides. The element after the directory path (\1.html) is a simple substitution argument— \1 is replaced by what you type after the colon.

You can quickly access the run command window by pressing ALT-F2 in KDE's standard configuration.

Let's take a simple Qt class as an example: QLabel. It's a good idea to open the Qt class documentation in your browser window (remember the KDE shortcut) and keep that in view.

First, the documentation tells you that the QLabel class includes qlabel.h: #include <qlabel.h>. This means about the same as a Python import statement. You can disregard it.

The methods that do not return anything, but have the same name as the class, are the C++ constructors. Simply call them with the right arguments. Don't pay attention to any spurious asterisks (*) or ampersands (&) around the arguments to the function: what matters is the type, like QWidget. Don't pay attention to the const keyword either.

If there is an equals sign (=) after the variable name, then the function can use a default parameter, just like in Python. Again, just like in Python, booleans are zero or one. However, a default argument of zero, has a default argument of None in Python. This is important if you want to use two out of three arguments: then you must also mention the middle man (you can safely drop any tailing default arguments you don't need):

label=QLabel("text", None, "name")
  

versus

label=QLabel("text")
  

Public members are instance methods of objects. If you call a public member, you should always prefix the call with the name of the object you have created (or self if you are calling the method from within the object). For example:

print label.text()
  

Slots are in no way different from ordinary functions in Python, so what holds for public members also holds for public slots. Protected member variables are a vague kind of private—if you create the QLabel from Python, you can access the protected members, like drawContents(), without problems, but if the QLabel has been created from a C++ class then you cannot access the protected member functions.

Properties are currently not supported by PyQt—everything you can set and get with properties is also accessible by get() and set() methods.

If you are reading the detailed description of a class, you will often come across snippets of C++ code. These are easy to translate, too. Just keep in mind that both a double semi-colon (::) or an arrow (->) translate to a Python dot (.). And you don't need braces or final semicolons, of course. Or new statements. For instance:

    QLabel *label = new QLabel;
    label->setFrameStyle( QFrame::Panel | QFrame::Sunken );
    label->setText( "first line\nsecond line" );
    label->setAlignment( AlignBottom | AlignRight );
  

Could become in Python:

    label = new QLabel()
    label.setFrameStyle( QFrame.Panel or QFrame.Sunken )
    label.setText( "first line\nsecond line" )
    label.setAlignment( Qt.AlignBottom or Qt.AlignRight )
  

Note also that certain pre-defined values, called constants in C++ (and lots of other languages), are placed either in a certain class, not object instances or in the Qt pseudoclass. Thus, the Panel or Sunken constants are accessed from the QFrame class, while the AlignBottom and AlignRight constants are taken from the Qt pseudoclass. Note also that it isn't necessary to prefix Qt in C++, but that this is obligatory in Python.

A bit like constants are static methods, and are defined on the class:

QObject.connect()  
  

QLabel doesn't have any signals or static members. For those we had better look at another class: QScrollbar.

Signals have already been discussed in detail in Chapter 7. Here I only want to mention the way you must remove any fluff from the declaration. Signals are placed in a Python dictionary by sip, so you really want to get the string argument to SIGNAL() right.

So, if there are no arguments to the signal, you can just copy it, including the brackets. If there are arguments you need to copy the entire argument list, but not the variable name. So:

void valueChanged ( int value ) 
  

Can be used as:

QObject.connect(sbar,SIGNAL("valueChanged(int)"),someFunction)
  

On the other hand, if there are asterisks involved, then you have to copy those, too. In QListView,

void returnPressed ( QListViewItem * ) 
  

Becomes:

    self.connect(self,
                 SIGNAL("returnPressed(QListViewItem *)"),
                 self.slotItemSelected)
  

The Qt documentation is not always consistent in giving signal parameters variable names - sometimes they do, sometimes they don't.

Finally, wherever there is a NULL in C++, you can use None, but you can also use None in many cases where there is a zero (0) (this being a pointer to nowhere). That means that everywhere a function takes an object (instead of a simple integer) as a parameter, you can use None. A zero is often given as a default argument in these cases, and then you don't need to give any parameter. Thus:

QListView ( QWidget * parent = 0, const char * name = 0 ) 
  

Can be called as:

listview = QListView(None, None)
  

or:

listview = QListView()
  

You can also use actual arguments, of course. You almost never need to actually pass something for the name parameter, but it makes for nicer debugging:

listview = QListView(parentWindows, "listview")
  

As you've seen, it's not difficult at all to translate from C++ to Python — even if you don't know any C or C++. If you do want to know more about C++, I can recommend Steven Oualline's book, Practical C++ Programming as a good beginners title.