Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 3

Qt-interest Archive, January 2008
Little threading problem (QThread)

Pages: Prev | 1 | 2 | Next

Message 1 in thread

Hi,
in the following tiny piece of code a QThread object is instantiated for
which its start() method is called. We wonder why on my machine
[
    Distributor ID: Ubuntu
    Description:    Ubuntu 7.10
    Release:        7.10
    Codename:     gutsy
    Qt Version:     4.3.2
    g++ (GCC) 4.1.3 20070929 (prerelease) (Ubuntu 4.1.2-16ubuntu2)
 ]

the output is:
0
1
2
3

wheras somewhere else (friends machine) the same code produces:
-----------------> i 0
-----------------> i 1
-----------------> i 2
-----------------> i 3
0
1
2
3

as expected.


Compilation:
g++ -c -pipe -g -D_REENTRANT -Wall -W -DQT_SHARED -DQT_GUI_LIB -DQT_CORE_LIB 
-I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore 
-I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4/QtGui 
-I/usr/include/qt4 -I. -I. -o mainprogthread.o mainprogthread.cpp
g++  -o thready mainprogthread.o    -L/usr/lib -lQtGui -lQtCore -lpthread



Code:

mainprogthread.cpp:
----------------------------
#include "mainprogthread.h"

MainProgThread::MainProgThread() {}

MainProgThread::~MainProgThread() {}

void MainProgThread::run() {
    for (int i=0; i < 4; i++) {
        printf("-----------------> i %d: \n", i);
    }
}

int main ( int , char** ) {

    MainProgThread* mainProgThread = new MainProgThread;
    mainProgThread->start();
    //guiThread->wait();
    for (int i=0; i<4; i++) {
        printf("%d \n", i);
    }
}


mainprogthread.h:
--------------------------
#ifndef MAINPROGTHREAD_H
#define MAINPROGTHREAD_H

#include <QThread>
#include <iostream>
/**
    @author Babak Sayyid Hosseini
*/

using namespace std;

class MainProgThread : public QThread {

public:
    MainProgThread();
    ~MainProgThread();
    void run();
};

#endif


After calling start() the OS thread-scheduler should register the new Thread
and branch it away from the main thread. Calling start must end up in a call
to run() which dumps a string on stdout. I wonder why we have 2 different
behaviors.
Any hints are welcome.

Babak Sayyid Hosseini




--
 [ signature omitted ] 

Message 2 in thread

On Monday 21 January 2008 18:08, Babak Sayyid Hosseini wrote:
> Hi,
> in the following tiny piece of code a QThread object is instantiated for
> which its start() method is called. We wonder why on my machine

> the output is:
> 0
> 1
> 2
> 3
>
> wheras somewhere else (friends machine) the same code produces:
> -----------------> i 0
> -----------------> i 1
> -----------------> i 2
> -----------------> i 3
> 0
> 1
> 2
> 3
>
> as expected.

The answer is very simple: 

In the second example the kernel executes the new thread first and after it is 
finished the scheduler has time to execute the remainder of the GUI thread. 
Everything looks as you would expect it.

In the first case the kernel creates the new thread, but first continues with 
the main GUI-Thread putting the sub-thread into the queue to be executed 
later. Unfortunately the main thread ends, hence the whole process ends and 
the sub-thread gets killed before it got a chance to do anything.

You solve your problem by making sure the main thread ends last. Eg. send it 
into its event loop and send a signal that ends the loop from the sub-thread.

This could be accomplished by adding:
--before starting the thread---
QCoreApplication app(argc,argv);
connect(mainProgThread,SIGNAL(finished()),&app,SLOT(quit()));
-----
--at the end of main--
app.exec();
-----

Please read the docu to find out what that means.... ;-)



	Konrad

Attachment:

Attachment: pgpcLTcA1FcER.pgp
Description: PGP signature


Message 3 in thread

Konrad Rosenbaum wrote:

> On Monday 21 January 2008 18:08, Babak Sayyid Hosseini wrote:
>> Hi,
>> in the following tiny piece of code a QThread object is instantiated for
>> which its start() method is called. We wonder why on my machine
> 
>> the output is:
>> 0
>> 1
>> 2
>> 3
>>
>> wheras somewhere else (friends machine) the same code produces:
>> -----------------> i 0
>> -----------------> i 1
>> -----------------> i 2
>> -----------------> i 3
>> 0
>> 1
>> 2
>> 3
>>
>> as expected.
> 
> The answer is very simple:
> 
> In the second example the kernel executes the new thread first and after
> it is finished the scheduler has time to execute the remainder of the GUI
> thread. Everything looks as you would expect it.
> 
> In the first case the kernel creates the new thread, but first continues
> with the main GUI-Thread putting the sub-thread into the queue to be
> executed later. Unfortunately the main thread ends, hence the whole
> process ends and the sub-thread gets killed before it got a chance to do
> anything.
> 
> You solve your problem by making sure the main thread ends last. Eg. send
> it into its event loop and send a signal that ends the loop from the
> sub-thread.
> 
> This could be accomplished by adding:
> --before starting the thread---
> QCoreApplication app(argc,argv);
> connect(mainProgThread,SIGNAL(finished()),&app,SLOT(quit()));
> -----
> --at the end of main--
> app.exec();
> -----
> 
> Please read the docu to find out what that means.... ;-)
> 
> 
> 
> Konrad


Indeed, super simple.

Regards,
Babak Sayyid Hosseini

--
 [ signature omitted ] 

Message 4 in thread

From: Babak Sayyid Hosseini [mailto:babak.sayyid@xxxxxxxxx] 
> [...]. We wonder why on my machine [...]
> the output is:
> 0
> 1
> 2
> 3
> 
> wheras somewhere else (friends machine) the same code produces:
> -----------------> i 0
> -----------------> i 1
> -----------------> i 2
> -----------------> i 3
> 0
> 1
> 2
> 3
> 
> as expected.
> 
> [...]
> void MainProgThread::run() {
>     for (int i=0; i < 4; i++) {
>         printf("-----------------> i %d: \n", i);
>     }
> }
> 
> int main ( int , char** ) {
> 
>     MainProgThread* mainProgThread = new MainProgThread;
>     mainProgThread->start();
>     //guiThread->wait();
>     for (int i=0; i<4; i++) {
>         printf("%d \n", i);
>     }
> }
> [...]

Well, that's one of the pitfalls of threading: Never rely on some order of
execution. Might be your friend has a multicore box and you don't or vice
versa.

In any case, what happens on your machine is that the main thread exits even
before the prog thread reaches the run() method. If you introduce a
"usleep(1); mainProgThread->wait();" after the loop in main(), you should
see at least the output of the prog thread, however the order of the output
is still random.

One of the major pitfalls of QThread::wait() is that it returns even if the
thread has not yet started, so the usleep() (on Linux, Sleep() on Windows)
is needed to force the scheduling. Or use some other synchronization
techniques to tell main() that the thread _really_ started (and is not only
about to do so ...).

Best Regards / Mit freundlichen Grüßen
Rainer Wiesenfarth

-- 
 [ signature omitted ] 

Attachment: smime.p7s
Description: S/MIME cryptographic signature


Message 5 in thread

Rainer Wiesenfarth wrote:

> 
> From: Babak Sayyid Hosseini [mailto:babak.sayyid@xxxxxxxxx]
>> [...]. We wonder why on my machine [...]
>> the output is:
>> 0
>> 1
>> 2
>> 3
>> 
>> wheras somewhere else (friends machine) the same code produces:
>> -----------------> i 0
>> -----------------> i 1
>> -----------------> i 2
>> -----------------> i 3
>> 0
>> 1
>> 2
>> 3
>> 
>> as expected.
>> 
>> [...]
>> void MainProgThread::run() {
>>     for (int i=0; i < 4; i++) {
>>         printf("-----------------> i %d: \n", i);
>>     }
>> }
>> 
>> int main ( int , char** ) {
>> 
>>     MainProgThread* mainProgThread = new MainProgThread;
>>     mainProgThread->start();
>>     //guiThread->wait();
>>     for (int i=0; i<4; i++) {
>>         printf("%d \n", i);
>>     }
>> }
>> [...]
> 
> Well, that's one of the pitfalls of threading: Never rely on some order of
> execution. Might be your friend has a multicore box and you don't or vice
> versa.
> 
> In any case, what happens on your machine is that the main thread exits
> even before the prog thread reaches the run() method. If you introduce a
> "usleep(1); mainProgThread->wait();" after the loop in main(), you should
> see at least the output of the prog thread, however the order of the
> output is still random.
> 
> One of the major pitfalls of QThread::wait() is that it returns even if
> the thread has not yet started, so the usleep() (on Linux, Sleep() on
> Windows) is needed to force the scheduling. Or use some other
> synchronization techniques to tell main() that the thread _really_ started
> (and is not only about to do so ...).
> 
> Best Regards / Mit freundlichen GrÃÃen
> Rainer Wiesenfarth
> 



Hello Rainer,
the fact that the main thread is over before the os thread scheduler starts
my branch thread is just too sorry. Putting a wait() or usleep() is
awkward. Specially wait() is a kind of contra concurrent since it blocks
until the thread is run. I do not want anything to be blocked, though!

I had the suspision that the main thread exits before even the branch thread
gets started, but, due to the fact that it is different in case of java, I
wanted to make sure how the qt thread internals are.

Java Example showing the indenpendence of a main and branch thread:

public class Test {

    public Test() {
        System.out.println("Output from main thread");

        MyThread m = new MyThread();
        m.start();
       
    }


    public static void main(String[] args) {
        Test t = new Test();
        System.out.println("Main thread is exiting now !");
    }

    class MyThread extends Thread {
        public void run() {
            for (int i=0; i<10; i++) {
                System.out.println(" output from MyThread Thread_i : " + i);
            }
        }
    }
}


Output (as expected):

Output from main thread
Main thread is exiting now !
 output from MyThread Thread_i : 0
 output from MyThread Thread_i : 1
 output from MyThread Thread_i : 2
 output from MyThread Thread_i : 3
 output from MyThread Thread_i : 4
 output from MyThread Thread_i : 5
 output from MyThread Thread_i : 6
 output from MyThread Thread_i : 7
 output from MyThread Thread_i : 8
 output from MyThread Thread_i : 9

In java we have to distinguish between daemon threads and user threads.
The state of a daemon thread is not considered in case a java program is
ending. The garbage collector thread is a daemon thread for example. It is
stopped as soon as your program finishes execution.

User thread states are considered though. When finishing a user state, the
runtime checks, whethere there are other user threads and the program is
not finished until those user threads are finished.

So in qt case. we saw a different behavior than in java as far as threads
are considered.
The thread I start in my qt thread example has to be a kind of "daemon
thread" in java terms. I would like to know, whether one can configure that
behavior in qt.

Regards,

Babak Sayyid Hosseini

--
 [ signature omitted ] 

Message 6 in thread

Babak Sayyid Hosseini wrote:
>So in qt case. we saw a different behavior than in java as far as
> threads are considered.
>The thread I start in my qt thread example has to be a kind of "daemon
>thread" in java terms. I would like to know, whether one can configure
> that behavior in qt.

You cannot.

You can only make it exit when the application is about to exit. See the 
QCoreApplication::aboutToQuit() signal.

-- 
 [ signature omitted ] 

Attachment: signature.asc
Description: This is a digitally signed message part.


Message 7 in thread

Thiago Macieira wrote:

> Babak Sayyid Hosseini wrote:
>>So in qt case. we saw a different behavior than in java as far as
>> threads are considered.
>>The thread I start in my qt thread example has to be a kind of "daemon
>>thread" in java terms. I would like to know, whether one can configure
>> that behavior in qt.
> 
> You cannot.
> 
> You can only make it exit when the application is about to exit. See the
> QCoreApplication::aboutToQuit() signal.
> 
 Ok no problem. Will make sure main threads ends last.

Regards,
Babak Sayyid Hosseini

--
 [ signature omitted ] 

Message 8 in thread

> From: Babak Sayyid Hosseini [mailto:babak.sayyid@xxxxxxxxx] 
> Rainer Wiesenfarth wrote:
> > [...]
> > In any case, what happens on your machine is that the main 
> > thread exits even before the prog thread reaches the run()
> > method. If you introduce a
> > "usleep(1); mainProgThread->wait();" after the loop in 
> > main(), you should see at least the output of the prog
> > thread, however the order of the output is still random.
> > [...]
> 
> Hello Rainer,
> the fact that the main thread is over before the os thread 
> scheduler starts
> my branch thread is just too sorry. Putting a wait() or usleep() is
> awkward. Specially wait() is a kind of contra concurrent 
> since it blocks
> until the thread is run. I do not want anything to be blocked, though!
> [...]

There can be concurreny, but you have to make sure that all threads you
started have finished before you return control to the OS by returning from
main(). As soon as you return from main(), the OS assumes that the whole
process (including all potential threads) has finished execution and can be
removed.

So, you should call wait() at the end of your main(), just before returning.

Best Regards / Mit freundlichen Grüßen
Rainer Wiesenfarth

-- 
 [ signature omitted ] 

Attachment: smime.p7s
Description: S/MIME cryptographic signature


Message 9 in thread

Rainer Wiesenfarth wrote:

> 
>> From: Babak Sayyid Hosseini [mailto:babak.sayyid@xxxxxxxxx]
>> Rainer Wiesenfarth wrote:
>> > [...]
>> > In any case, what happens on your machine is that the main
>> > thread exits even before the prog thread reaches the run()
>> > method. If you introduce a
>> > "usleep(1); mainProgThread->wait();" after the loop in
>> > main(), you should see at least the output of the prog
>> > thread, however the order of the output is still random.
>> > [...]
>> 
>> Hello Rainer,
>> the fact that the main thread is over before the os thread
>> scheduler starts
>> my branch thread is just too sorry. Putting a wait() or usleep() is
>> awkward. Specially wait() is a kind of contra concurrent
>> since it blocks
>> until the thread is run. I do not want anything to be blocked, though!
>> [...]
> 
> There can be concurreny, but you have to make sure that all threads you
> started have finished before you return control to the OS by returning
> from main(). As soon as you return from main(), the OS assumes that the
> whole process (including all potential threads) has finished execution and
> can be removed.
> 
> So, you should call wait() at the end of your main(), just before
> returning.
> 
> Best Regards / Mit freundlichen GrÃÃen
> Rainer Wiesenfarth
> 

Hello Rainer,
thank you for your reply. I discussed the topic with a few other people in
this group and it seems like the whole topic can be reduced to the
question:
does any thread started from the main thread stay alive after the main
thread is finished. Is I already said, in java this is the case for
non-daemon threads which is default when you start a branch thread.
The VM waits until are user threads are finished and exits then.

This is different here and knowing this is absolutely enough to adapt the
program the way you proposed.

Regards,

Babak Sayyid Hosseini



--
 [ signature omitted ] 

Message 10 in thread

On 22.01.08 13:05:22, Babak Sayyid Hosseini wrote:
> thank you for your reply. I discussed the topic with a few other people in
> this group and it seems like the whole topic can be reduced to the
> question:
> does any thread started from the main thread stay alive after the main
> thread is finished. Is I already said, in java this is the case for
> non-daemon threads which is default when you start a branch thread.
> The VM waits until are user threads are finished and exits then.

This is not possible in plain C++ (or any other language that produces
native executables). In Java you actually start the Java VM, which runs
in the "main thread", the VM then executes your bytecode. If your code
spawns a new thread and then returns to the VM, the VM still knows about
the separate thread and thus is able to wait for the finishing of that
thread before returning control to the OS, by ending its own main
thread. 

Andreas

-- 
 [ signature omitted ] 

Message 11 in thread

dear All

I need to create a pop up menu which will execute on right clicking a
Graphics Item in the Graphics View. Through that pop up menu , i will
change the properties of the graphics item.

Now my question is

1. Is it better to create a pop up in the MyGraphicsItem class derived
from QGraphicsItem or the MyScene class which is derived from
QGraphicsScene.

2. If I think to create pop up menu with MyGraphicsItem class then
QGraphicsItem is not derived from QObject so signal slot can not work. I
tried to inherit QObject for MyGraphicsItem but it was giving error for
"Undefined vtable refrence for MyGraphicsItem".

Sorry for my stupid questions but i am confused and new to QT and c++ world.

thanks alot.

--
 [ signature omitted ] 

Message 12 in thread

Please any one suugest, how i can create a Pop Up Menu on a MyGrpahicsItem
(derived from QGraphicsItem)!!!!!!
If i inherit publically QWidget in MyGrpahicsItem then there is ambiguity
in the functions with the same name in QGraphicsItem and QWidget.

help

> dear All
>
> I need to create a pop up menu which will execute on right clicking a
> Graphics Item in the Graphics View. Through that pop up menu , i will
> change the properties of the graphics item.
>
> Now my question is
>
> 1. Is it better to create a pop up in the MyGraphicsItem class derived
> from QGraphicsItem or the MyScene class which is derived from
> QGraphicsScene.
>
> 2. If I think to create pop up menu with MyGraphicsItem class then
> QGraphicsItem is not derived from QObject so signal slot can not work. I
> tried to inherit QObject for MyGraphicsItem but it was giving error for
> "Undefined vtable refrence for MyGraphicsItem".
>
> Sorry for my stupid questions but i am confused and new to QT and c++
> world.
>
> thanks alot.
>
> --
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with
> "unsubscribe" in the subject or the body.
> List archive and information: http://lists.trolltech.com/qt-interest/
>


--
 [ signature omitted ] 

Message 13 in thread

Hi,

If you derive a class from QGraphicsItem and QObject just make sure to inherit 
from QObject first. That is:

class MyGraphicsItem: public QObject, public QGraphicsItem
{
Q_OBJECT
...
};

Then this will get rid of the "Undefined vtable refrence for MyGraphicsItem" 
problem and signals/slots will work as usual.

Hope this helps,

Sean

On Tuesday 22 January 2008, rohitj@xxxxxxxxxxxxxx wrote:
> Please any one suugest, how i can create a Pop Up Menu on a MyGrpahicsItem
> (derived from QGraphicsItem)!!!!!!
> If i inherit publically QWidget in MyGrpahicsItem then there is ambiguity
> in the functions with the same name in QGraphicsItem and QWidget.
>
> help
>
> > dear All
> >
> > I need to create a pop up menu which will execute on right clicking a
> > Graphics Item in the Graphics View. Through that pop up menu , i will
> > change the properties of the graphics item.
> >
> > Now my question is
> >
> > 1. Is it better to create a pop up in the MyGraphicsItem class derived
> > from QGraphicsItem or the MyScene class which is derived from
> > QGraphicsScene.
> >
> > 2. If I think to create pop up menu with MyGraphicsItem class then
> > QGraphicsItem is not derived from QObject so signal slot can not work. I
> > tried to inherit QObject for MyGraphicsItem but it was giving error for
> > "Undefined vtable refrence for MyGraphicsItem".
> >
> > Sorry for my stupid questions but i am confused and new to QT and c++
> > world.
> >
> > thanks alot.
> >
> > --
> > To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with
> > "unsubscribe" in the subject or the body.
> > List archive and information: http://lists.trolltech.com/qt-interest/
>
> --
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with
> "unsubscribe" in the subject or the body. List archive and information:
> http://lists.trolltech.com/qt-interest/



-- 
 [ signature omitted ] 

Message 14 in thread

Thanks alot for the reply Sean

I tried the way, you suggested me but it is still giving the error of
"Undefined Vtable ". Is there is something i have to do in the constructor
of the class?  I am fed up with this problem.

Thankssss

> Hi,
>
> If you derive a class from QGraphicsItem and QObject just make sure to
> inherit
> from QObject first. That is:
>
> class MyGraphicsItem: public QObject, public QGraphicsItem
> {
> Q_OBJECT
> ...
> };
>
> Then this will get rid of the "Undefined vtable refrence for
> MyGraphicsItem"
> problem and signals/slots will work as usual.
>
> Hope this helps,
>
> Sean
>
> On Tuesday 22 January 2008, rohitj@xxxxxxxxxxxxxx wrote:
>> Please any one suugest, how i can create a Pop Up Menu on a
>> MyGrpahicsItem
>> (derived from QGraphicsItem)!!!!!!
>> If i inherit publically QWidget in MyGrpahicsItem then there is
>> ambiguity
>> in the functions with the same name in QGraphicsItem and QWidget.
>>
>> help
>>
>> > dear All
>> >
>> > I need to create a pop up menu which will execute on right clicking a
>> > Graphics Item in the Graphics View. Through that pop up menu , i will
>> > change the properties of the graphics item.
>> >
>> > Now my question is
>> >
>> > 1. Is it better to create a pop up in the MyGraphicsItem class derived
>> > from QGraphicsItem or the MyScene class which is derived from
>> > QGraphicsScene.
>> >
>> > 2. If I think to create pop up menu with MyGraphicsItem class then
>> > QGraphicsItem is not derived from QObject so signal slot can not work.
>> I
>> > tried to inherit QObject for MyGraphicsItem but it was giving error
>> for
>> > "Undefined vtable refrence for MyGraphicsItem".
>> >
>> > Sorry for my stupid questions but i am confused and new to QT and c++
>> > world.
>> >
>> > thanks alot.
>> >
>> > --
>> > To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with
>> > "unsubscribe" in the subject or the body.
>> > List archive and information: http://lists.trolltech.com/qt-interest/
>>
>> --
>> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with
>> "unsubscribe" in the subject or the body. List archive and information:
>> http://lists.trolltech.com/qt-interest/
>
>
>
> --
> Dr Sean Harmer
> ESR Technology Ltd
> Whittle House
> 410 The Quadrant
> Birchwood Park
> Warrington
> Cheshire
> WA3 6FW
> UK
>
> Tel: +44 (0)1925 843469
> Mob: +44 (0)7968 861691
> Fax: +44 (0)1925 843500
>
> --
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with
> "unsubscribe" in the subject or the body.
> List archive and information: http://lists.trolltech.com/qt-interest/
>


--
 [ signature omitted ] 

Message 15 in thread

I am not sure that creating a QMenu as a member of QGraphicsItem is a good
idea, as you will have in memory a copy of the menu for each item in your
scene. This is totally unefficient.
Also, moing multiple inheritance from QObject and QGraphicsItem is in your
case useless, hard to fully understand and potentially dangerous.

I am almost sure that in your case, the clean and simple approach to what
you want to do is adding a static member function to your QGraphicItem
derived classes, that creates a menu, popup it, destroy it, do some actions
on the item depending on the user choice, and return the user choice.
You can for instance declare it like this in your item classes:

class MyGraphicItem : public QGraphicItem
{
  static int contextMenu();
  ...
}





2008/1/22, rohitj@xxxxxxxxxxxxxx <rohitj@xxxxxxxxxxxxxx>:
>
> Please any one suugest, how i can create a Pop Up Menu on a MyGrpahicsItem
> (derived from QGraphicsItem)!!!!!!
> If i inherit publically QWidget in MyGrpahicsItem then there is ambiguity
> in the functions with the same name in QGraphicsItem and QWidget.
>
> help
>
> > dear All
> >
> > I need to create a pop up menu which will execute on right clicking a
> > Graphics Item in the Graphics View. Through that pop up menu , i will
> > change the properties of the graphics item.
> >
> > Now my question is
> >
> > 1. Is it better to create a pop up in the MyGraphicsItem class derived
> > from QGraphicsItem or the MyScene class which is derived from
> > QGraphicsScene.
> >
> > 2. If I think to create pop up menu with MyGraphicsItem class then
> > QGraphicsItem is not derived from QObject so signal slot can not work. I
> > tried to inherit QObject for MyGraphicsItem but it was giving error for
> > "Undefined vtable refrence for MyGraphicsItem".
> >
> > Sorry for my stupid questions but i am confused and new to QT and c++
> > world.
> >
> > thanks alot.
> >
> > --
> > To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with
> > "unsubscribe" in the subject or the body.
> > List archive and information: http://lists.trolltech.com/qt-interest/
> >
>
>
> --
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with
> "unsubscribe" in the subject or the body.
> List archive and information: http://lists.trolltech.com/qt-interest/
>
>

Pages: Prev | 1 | 2 | Next