home | codereading | contact | math | misc | patches | tech


Qt notes

General tips

Qt environment variables

If you installed Qt in path different from the default (e. g., /opt/qt-<version>), you need to set up some environment variables to get your program compile and run fine:

  • QTDIR - Path where Qt is installed.
  • PATH - Add the path where qmake and Qt applications are located. (usually $QTDIR/bin.
  • LD_LIBRARY_PATH - Two directories (separeted by colons) need to be added here: the qt library directory and the X11 library directory. Usually $QTDIR/lib and /usr/X11/lib

Defining #define's when using qmake

To use the -D option of gcc, in a Makefile created by qmake, when creating the .pro file, use the DEFINES variable, like here.

Example:

$ qmake -project -nopwd -o file.pro foo.cpp bar.cpp "DEFINES+=Linux"

Qt: QTableView Cell with Widget

In QTableView, sometimes it is necessary to override default appearance for some cells. For example: change color, font, or even the text having the database value as reference.

This reference and this give tips about how to make that.

The following example shows how to do that inheritting class QItemDelegate and overloading the paint() method.

class ColorDelegate : public QItemDelegate
{
    Q_OBJECT

public:
    ColorDelegate(QWidget *parent = 0) : QItemDelegate(parent) { };

    void paint(QPainter *painter, const QStyleOptionViewItem &option,
            const QModelIndex &index) const;
}; /* class ColorDelegate */

void
ColorDelegate::paint(QPainter *painter,
        const QStyleOptionViewItem &option,
        const QModelIndex &index ) const
{
    int column;

    column = index.column();

    if (column == PROCCOL_STATUS) {
        int status;
        QColor color;
        QString statusstr;

        status = index.data().toInt();

        if (status == 0) { /* not started */
            color = QColor(Qt::white);
            statusstr = STATUS_NOT_STARTED;
        } else if (status == 1) { /* paused */
            color = QColor(255, 69, 0); /* orange */
            statusstr = STATUS_INTERRUPTED;
        } else if (status == 2) { /* finished */
                color = QColor(Qt::green);
                statusstr = STATUS_FINISHED;
        }

        painter->fillRect(option.rect, QBrush(color));
        drawDisplay(painter, option, option.rect, statusstr);
    } else if (column == PROCCOL_SATISF) {
            int satisf;
            QColor color;
            QString satisfstr;

            satisf = index.data().toInt();

            if (satisf == 0) {/* no entry */
                color = QColor(Qt::white);
                satisfstr = SATISF_NOT_FILLED;
            } else if (satisf == 1) { /* unsatisfied */
                color = QColor(Qt::red);
                satisfstr = SATISF_NOTSATISF;
            } else if (satisf == 2) { /* satisfied */
                color = QColor(Qt::green);
                satisfstr = SATISF_SATISF;
            }

            painter->fillRect(option.rect, QBrush(color));
            drawDisplay(painter, option, option.rect, satisfstr);
    } else
            /* all other cells are painted normally */
            QItemDelegate::paint(painter, option, index);
}

Troubleshooting

Wrong connect

Sometimes the compiler outputs something saying that it cannot connect because of one of the arguments (the first one, mainly) is a pointer to a reference:

tlmarchiver_rec.cpp:10: error: invalid use of undefined type `struct
QTimer' /opt/qt3/include/qwindowdefs.h:79: error: forward declaration of
`struct QTimer'
tlmarchiver_rec.cpp:12: error: no matching function for call to
`TlmArchiverRec ::connect(QTimer*&, const char[11], const char[12])'
/opt/qt3/include/qobject.h:116: error: candidates are: static bool
QObject::connect(const QObject*, const char*, const QObject*, const char*)
/opt/qt3/include/qobject.h:227: error:                 bool
QObject::connect(const QObject*, const char*, const char*) const

Solution: check if you included the header of the class of the object you want to connect. In this case, I just added:

#include <qtimer.h>

at the top of the file.

"undefined reference to vtable"

When linking, the compiler can exit with the following error:

main.o(.text+0x18): In function `Test::Test(QObject*)':
: undefined reference to `vtable for Test'
main.o(.text+0xc0): In function `Test::Test(QObject*)':
: undefined reference to `vtable for Test'
main.o(.text+0x195): In function `main':
: undefined reference to `vtable for Test'
main.o(.text+0x1c0): In function `main':
: undefined reference to `vtable for Test'
*** Error code 1

In this case, the definition and the implementation of the Test class, as well as the main() function are all in the main.cpp file. After much time looking for a solution, I found this link:

That made me find the solution: I forgot to put the following include at the end of the file:

#include "main.moc"

See also this reference

errors when compiling ".h" file generated by uic

You can sometimes get erros like the following:

In file included from smdb_restartevtgui.h:13, from
smdb_mainwindow.cpp:21:
ui_smdb_restartevtgui.h: In member function `void
Ui_RestartEvtGui::setupUi(QWidget*)':
ui_smdb_restartevtgui.h:41: error: `setLeftMargin' undeclared (first use
this function)
ui_smdb_restartevtgui.h:41: error: (Each undeclared identifier is reported
only once for each function it appears in.)
ui_smdb_restartevtgui.h:42: error: `setTopMargin' undeclared (first use
this function)
ui_smdb_restartevtgui.h:43: error: `setRightMargin' undeclared (first use
this function)
ui_smdb_restartevtgui.h:44: error: `setBottomMargin' undeclared (first use
this function)
ui_smdb_restartevtgui.h:45: error: `setHorizontalSpacing' undeclared
(first use this function)
ui_smdb_restartevtgui.h:46: error: `setVerticalSpacing' undeclared (first
use this function)
gmake[1]: *** [.objs/smdb_mainwindow.o] Error 1
gmake[1]: Leaving directory `/home/nohope/devel/cla-smdb/smdb'
gmake: *** [smdb] Error 2

The .h file, in this case, is a file generated by Qt's uic. See that this Qt version you are trying to use to compile the program is the same version that was used to save the .ui files. You can easily solve this problem by opening the .ui file (in this case, smdb_restartevtgui.ui) in designer and just saving it again, making sure that the XML on it conforms to the version of Qt in your computer.

wrong fonts in Qt 3

If fonts appear wrong and too big (them doesn't appear in widgets), try to put in the user ${HOME}/.qt/qtrc (the one that runs the application):

[General]
font=Sans,10,-1,5,48,0,0,0,0,0

"Memory Fault" in constructor

When receiving "Memory fault" and gdb -c foo.core foo tells you that the error is in a connect:

#0  0xbcffd832 in QObject::connect(QObject const*, char const*, QObject
const*, char const*, Qt::ConnectionType) () from
/opt/qt4/lib/libQtCore.so.4
(gdb) bt
#0  0xbcffd832 in QObject::connect(QObject const*, char const*, QObject
const*, char const*, Qt::ConnectionType) () from
/opt/qt4/lib/libQtCore.so.4
#1  0x08049d28 in FrmStart::popupMenuBelow(QWidget*) (this=0xbfbfe7c4,
w=0x0)
at frmstart.cpp:44
#2  0x08049f23 in main (argc=1, argv=0xbfbfe890) at main.cpp:20
#3  0x08049736 in ___start ()

Try to move the connect away the constructor. There can be many reasons, like using a null pointer.

"staticMetaObject" is not a member of type...

Whenever you receive an error like:

error: `staticMetaObject' is not a member of type `

Go to your class declaration, and let it inherits QObject before any other class:

class Foo : public QObject, public Bar, public Baz ...

This reference helped me.

Error "[method()...] is inaccessible"

If you get an error like:

error: 'void QWidget::show()' is inaccessible

Check if you inherited your class in a public manner, like this:

class MainWindow : public QMainWindow

(note the public keyword).

"undefined reference" when linking with SQL module

When linker says that there are undefined reference for methods in QSqlDatabase like above:

.objs/frmevents.o(.text+0x43): In function
`Ui_FrmEvents::Ui_FrmEvents()':
/opt/qt-4.2.2/include/QtCore/qstring.h: undefined reference to
`QSqlDatabase::defaultConnection'
.objs/frmevents.o(.text+0x80):/opt/qt-4.2.2/include/QtCore/qstring.h:
undefined reference to `QSqlDatabase::addDatabase(QString const&, QString
const&)'
.objs/frmevents.o(.text+0x92):/opt/qt-4.2.2/include/QtCore/qstring.h:
undefined reference to `QSqlDatabase::operator=(QSqlDatabase const&)'
.objs/frmevents.o(.text+0xa9):/opt/qt-4.2.2/include/QtCore/qstring.h:
undefined reference to `QSqlDatabase::~QSqlDatabase()'
.objs/frmevents.o(.text+0xbd):/opt/qt-4.2.2/include/QtCore/qstring.h:
undefined reference to `QSqlDatabase::~QSqlDatabase()'
.objs/frmevents.o(.text+0x139):/opt/qt-4.2.2/include/QtCore/qstring.h:
undefined reference to `QSqlDatabase::setDatabaseName(QString const&)'
.objs/frmevents.o(.text+0x175):/opt/qt-4.2.2/include/QtCore/qstring.h:
undefined reference to `QSqlDatabase::open()'

Do that:

Add this line to the .pro file:

QT += sql

A very useful reference.

Thanks to Tymothy Sullivan (tpsulliv -at- ualberta -dot- ca) for the following suggestion:

This error also shows up if you're providing incorrect column definitions in an INSERT or UPDATE statement, so the db thinks the table is wrong. It could be as simple as forgetting quotes around inputted values, causing the db to flag the value as a column name.

"No Fields to Update" or "Unable to find table <tablename>"

If you get this strange behaviour, check if you created the database (with QSqlDatabase) before your model. Also, don't declare the model as a static object in your header file, since the constructor will be executed before QSqlDatabase that you is probably running latter.

The following code works:

d_db = QSqlDatabase::addDatabase("QSQLITE");
d_db.setDatabaseName(dbname);
if (!d_db.open()) {
    qWarning("Bad database");
    return;
}

d_model = new QSqlTableModel(this);
d_model->setTable("tablename");
d_model->setEditStrategy(QSqlTableModel::OnManualSubmit);
d_model->select();

Another cause that can make you get "No Fields to update", is a wrong row number in the QSqlTableModel::index() method. See the following example:

int c = d_model->rowCount();
d_model->setData(d_model->index(c, POS_EL_IDX), d_data.pos.el);

In this example, we are trying to set values for line c. But it was not added yet! So, when getting the value of c, we need to subtract one:

int c = d_model->rowCount() - 1;

So, always check if you are passing the line number correctly.

"multiple definition of ..."

When linking, if you get erros like this:

moc_dialog_systeme.o: In function
`Dialog_systeme::hideEvent(QHideEvent*)':
moc_dialog_systeme.cpp:(.text+0x10): multiple definition of
`Dialog_systeme::hideEvent(QHideEvent*)'
dialog_systeme.o:dialog_systeme.cpp:(.text+0x0): first defined here
moc_dialog_instalation.o: In function
`Dialog_instalation::hideEvent(QHideEvent*)':
moc_dialog_instalation.cpp:(.text+0x10): multiple definition of
`Dialog_instalation::hideEvent(QHideEvent*)'
dialog_instalation.o:dialog_instalation.cpp:(.text+0x0): first defined
here
moc_dialog_options.o: In function
`Dialog_options::hideEvent(QHideEvent*)':
moc_dialog_options.cpp:(.text+0x10): multiple definition of
`Dialog_options::hideEvent(QHideEvent*)'
dialog_options.o:dialog_options.cpp:(.text+0x0): first defined here
collect2: ld returned 1 exit status
make: *** [VIS9000] Error 1

It means that you probably declared as a signal an already existent method (that is probably not a signal). In this case, void hideEvent(QHideEvent *) was wrongly declared as a signal, when it is a protected method inherited from the base class.

"error: " ...constructor.. "is private"

If you get an error like "error: `QObject::QObject(const QObject&)' is private", you are probably trying to making a copy of a class that inherits from QObject.

Can't you use a pointer? Or does this class really need to inherit from QObject (does it use slots and signals?). Check this qtforum entry for more information.

"undefined reference to " static data member

If you get an "undefined reference to " error when trying to instance a static object, like in the class:

class Foo {
public:
    Foo();
    ~Foo();
private:
    QFile _file;
};

Remember that "static objects must also be declared outside any function or class just like normal globals" (see this devshed forum entry).

So, you should just make declare it:

QFile Foo:_file;

in a global scope.

"error: expected class-name before '{' token"

You probably have some a class declaration like this:

class Window : public QMainWindow, private Ui::Winwdow {

Are you sure the name of Ui::Window is right?

Zombie ([defunct]) subprocess

You want to call a subprocess using the QProcess class. It runs fine, but doesn't start. When you run top or ps its state is "[defunct]". Your main process can't event get it started. Why?

In my case, the subprocess needed a lib that was not in the default place. so I should export LD_LIBRARY_PATH. So it couldn't be executed, since the loader couldn't find the libraries.

Try to run the program of your subprocess first, to get any error that prevented it from working.

A more detailed explanation is got from the Advanced Programming in the Unix Environment, the famous and great (yeah, really great) book by Richard Stevens. Here is a piece of the section "8.5 exit Functions", of the second edition, co-authored with Stephen A. Rago:

Another condition we have to worry about is when a child terminates before its parent. If the child completely disappeared, the parent wouldn't be able to fetch its termination status when and if the parent were finally ready to check if the child had terminated. The kernel keeps a small amount of information for every terminating process, so that the information is available when the parent of the terminating process calls wait or waitpid. Minimally, this information consists of the process ID, the termination status of the process, and the amount of CPU time taken by the process. The kernel can discard all the memory used by the process and close its open files. In UNIX System terminology, a process that has terminated, but whose parent has not yet waited for it, is called a zombie. The ps(1) command prints the state of a zombie process as Z. If we write a long-running program that forks many child processes, they become zombies unless we wait for them and fetch their termination status.

Where is the configuration file for Qt 4 set by qtconfig?

Have you looked at ~/.config/Trolltech.conf?

Error "No query Unable to fetch row" with QSqlQuery

When a query does not succeed, you can get the error with the QSqlQuery::lastError() method, that returns a QSqlError class.

If the string representation of this says something like "No query Unable to fetch row", the database probably exists, but the tables (or at least the table you are trying to insert data to) not. Check if you created them correctly.

Some Qt3 notes

Building

To compile qt 3 with debug symbols, multi-thread support and the sqlite driver:

./configure -debug -thread -qt-sql-sqlite -prefix /opt/qt3

Qt3 Troubleshooting

ld cannot create libraries

If ld cannot create the shared libraries, and exit with an strange error, like this:

collect2: ld returned 1 exit status
gmake[2]: *** [../lib/libqt-mt.so.3.3.8] Error 1
gmake[2]: Leaving directory `/tmp/qt-x11-free-3.3.8/src'
gmake[1]: *** [sub-src] Error 2
gmake[1]: Leaving directory `/tmp/qt-x11-free-3.3.8'
gmake: *** [init] Error 2

Check if you have enough free space in the partition you are compiling Qt.