Trolltech | Documentation | Qt Quarterly | Diving into Splash Screens »

Qt 3.1 -- A Better Qt
 
Qt 3.1 introduces many improvements to make Qt programming even easier and more productive. This article explains how to make the best use of the new functionality in your Qt projects. For a complete list of what has changed, see http://www.trolltech.com/developer/changes/3.1.html.



New Features

The main new features in Qt 3.1 are these:

More Powerful

Many existing Qt classes are now more powerful in Qt 3.1. Some of these changes will be appreciated by Qt application users, others by application developers.

Text editor improvements

The QTextEdit class has been improved in many ways since Qt 3.0. Most importantly, it now supports interactive syntax highlighting through a new abstract class, QSyntaxHighlighter.

Syntaxhighlight  Logtext

Another significant improvement to QTextEdit is the addition of the LogText mode for displaying very large texts. In this mode, the widget stores its data in a very memory-efficient manner, and provides a subset of the RichText mode's features.

Data compression support

Qt 3.1 includes two functions that perform data compression and uncompression on a QByteArray: qCompress() and qUncompress().

Widget customization

QToolButton, QGroupBox, and QColorDialog are more customizable in Qt 3.1.

Widgets31

More flexible event processing

The subclassable QEventLoop class added in Qt 3.1 provides more flexible event queue handling. For most applications, the important addition is the ability to maintain a responsive user interface during heavy processing while disabling user input. This is achieved by calling

    QEventLoop *loop = qApp->eventLoop();
    loop->processEvents( QEventLoop::ExcludeUserInput );

Invisible menu items

Qt 3.1 supports invisible menu items. Unlike disabled items, which are shown grayed out, invisible items are not shown at all.

Menuitem1  Menuitem2  Menuitem3

To make a menu-bar item or a popup-menu item invisible, call setItemVisible(id, FALSE). To make a QAction invisible, call setVisible(FALSE).

Dynamic layouts

QLayout has two new functions, remove() and removeItem(), that remove a widget or another kind of layout item from a layout. These functions make it possible to move a widget from one layout to another at run-time.

Refined screen size

The QDesktopWidget class was introduced in Qt 3.0 to provide access to screen information on multi-head systems. In Qt 3.1, screenGeometry() and availableGeometry() have been added. The former returns the geometry of a screen (a QRect), while the latter returns the subset of a screen's geometry that isn't taken by the taskbar on Windows or by the dock and menubar on Mac OS X.

More control over HTTP and FTP

The QHttp and QFtp classes are subclasses of QNetworkProtocol. This gives them a uniform high-level interface that insulates developers from the low-level details. In Qt 3.1, their interfaces have been extended: They can be used as before, but now they also offer lower-level access for finer control. Both classes work asynchronously and can schedule (i.e. "queue") requests.

Multiple-key accelerators

Qt 3.0 introduced a class called QKeySequence to store an accelerator key (e.g. "Ctrl+Q"). With Qt 3.1, the word "sequence" in the class name is fully realized, and multi-key accelerators such as "Ctrl+X,Ctrl+S" and "Alt+M,A,Z" are now supported:

    action->setAccel( tr("Ctrl+X,Ctrl+S") );
    action->setAccel( QKeySequence(ALT+Key_M, Key_A, Key_Z) );

Improved thread-safety and reentrancy

Thread support in Qt has been vastly improved in Qt 3.1. Almost all tool classes (QString, QRegExp, QValueList, etc.) have been made reentrant. QApplication::postEvent() and a few other functions are now thread-safe if Qt is compiled as a multi-threaded library. The Qt documentation now specifically states if a class or function is reentrant/thread-safe.

Easier and Better

Each new Qt minor and major release features new overloads and convenience functions. Qt 3.1 includes some functions that will potentially change the way you write Qt code.

QWidget::setShown() and setHidden()

QWidget's API made this type of code frequent:

    void MyWidget::showChildWidget( bool showIt )
    {
        if ( showIt )
            childWidget->show();
        else
            childWidget->hide();
    }

With Qt 3.1, it's now possible to write
    childWidget->setShown( showIt );

Both setShown(), and its inverse setHidden(), are slots, so you can easily connect them to a signal with a bool parameter.

Codec for C strings

Before Qt 3.1, the default conversions between QString and 8-bit strings assumed that the strings were expressed in Latin-1. This can now be changed. For example, the following code sets a QString to the Korean string "Korean":

    QTextCodec::setCodecForCStrings(
            QTextCodec::codecForName("EUC-KR") );
    str = "\273\363\300\247 \265\360\267\272\305\344\270\256";

Normally a Korean programmer would simply type this in a file encoded using EUC-KR:
    str = "Koreangreen";

In a Latin-1 editor, the file looks like this:
    str = "상위 디렉토 ";

This small addition makes using a non-Latin-1 source code language just as easy as using Latin-1.

New QWidget::setSizePolicy() overload

Most developers only use QSizePolicy in conjunction with Qt Designer, but if you use hand-written code, you can now replace

    widget->setSizePolicy( QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed) );

with
    widget->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );

New QString::replace() overloads

Until Qt 3.1, the only QString::replace() overload that replaced all occurrences of its first argument with its second argument took a QRegExp as first argument. This led to the use of trivial regular expressions, for example:

    str.replace( QRegExp("\r\n"), "\n" );

Qt 3.1 now provides a QString::replace() overload that accepts a QString as its first argument:
    str.replace( "\r\n", "\n" );

This is faster at run-time and avoids the need to include <qregexp.h>.

The QString::replace() family of functions has been extended in many other important ways:

The same is true of QCString. In addition, find(), findRev(), and contains() are now significantly faster on large strings.

Standard C++ string compatibility

Qt 3.0 introduced a compatibility layer for STL containers. In Qt 3.1 this support has been extended to include the standard C++ std::string class. So now you can write

    std::string stroustrup = "Hello";
    QString eng = stroustrup;

and
    QString nord = "World";
    std::string stroustrup = nord;

By default QString assumes that std::string stores Latin-1 characters. You can change this behavior globally by calling QTextCodec::setCodecForCStrings().

QMap::keys() and QMap::values()

QMap supports very fast (logarithmic-time) lookup, insertion, and removal, with nice syntax thanks to C++'s operator overloading. But many Qt interfaces take a QValueList (or a QStringList), so you need to extract all the keys:

    QStringList keys;
    QMap<QString, int>::ConstIterator it = map.begin();
    while ( it != map.end() ) {
        keys.append( it.key() );
        ++it;
    }

This is much easier in Qt 3.1:
    QStringList keys = map.keys();

Qt 3.1 also includes a QMap::values() function, which returns a QValueList of all the values stored in the map:
    QValueList<int> values = map.values();

QString::startsWith() and endsWith()

QString::startsWith() was introduced in Qt 2.2, and QString::endsWith() was introduced in Qt 3.0. While they don't really belong in an article about Qt 3.1, many developers still don't know about them. Old-style code:

    if ( url.left(5) == "http:" &&
         (url.right(5) == ".html" || url.right(4) == ".xml") )

New-style code:
    if ( url.startsWith("http:") &&
         (url.endsWith(".html") || url.endsWith(".xml")) )

The new-style version is easier to read, less error-prone, and slightly reduces the executable size.

Easy mutex locking and unlocking

The new QMutexLocker class simplifies the locking and unlocking of mutexes. It is a very simple class: Its constructor locks a mutex and its destructor unlocks it. Here's an example:

    int complex_function( int flag )
    {
        QMutexLocker locker( &my_mutex );
        if ( flag == 0 || flag == 1 ) {
            return less_complex_function( flag );
        } else if ( flag > 10 ) {
            return -1;
        }
        return 0;
    }

This is less error-prone than calling QMutex::lock() at the beginning of the function and QMutex::unlock() before every "return" statement.


This document is licensed under the Creative Commons Attribution-Share Alike 2.5 license.

Copyright © 2002 Trolltech. Trademarks Diving into Splash Screens »