PDA

View Full Version : query on QCoreApplication::exec



psadhukhan
2nd December 2008, 10:43
Hi,

From http://doc.trolltech.com/4.4/threads.html, I found that
Note that QCoreApplication::exec() must always be called from the main thread (the thread that executes main()), not from a QThread. In GUI applications, the main thread is also called the GUI thread because it's the only thread that is allowed to perform GUI-related operations.

but in the attached application, I tried creating a linux thread from main and tries to call exec from the spawned thread and exec works.
I guess as per above line, exec() should only be calling from thread running main() and not from the spawned thread, am I right?
My question is is any thread a main thread (even though it's not running main()) and therefore can call exec() so long it's not spawned by QThread api?



#include <pthread.h>
#include <Qt>
#include <QtCore>
#include <QtGui>
#include <QPainter>
#include <QWidget>
#include <QImage>

class QPen;
class QBrush;
class QImage;

#define SCREEN_X_RESOLUTION 800
#define SCREEN_Y_RESOLUTION 600

struct qtimagedesc {
QPaintDevice *qpd;
};
typedef struct qtimagedesc QtImageDesc;

QtImageDesc *QtImageDescPool = NULL;
bool initDone = false;

#define qtApp ((QtApplication *)qApp)
void threadfunc(void *arg);
void AWT_drawline(int x1, int y1, int x2, int y2);
void AWT_drawrect(int x, int y, int w, int h);
void getQtColorModel();
void Qtexec();


QImage img(SCREEN_X_RESOLUTION,SCREEN_Y_RESOLUTION,QImage ::Format_ARGB32);

class QtWindow : public QWidget
{
QBitmap transMask;

public:
QtWindow(int flags,
const char *name = "Sun AWT/Qt",
QWidget *parent = NULL) ;
virtual void setMask(const QBitmap &);
virtual void paintEvent(QPaintEvent *);

};

class QtApplication : public QApplication {
public :
QtApplication(int &argc, char **argv);
int exec(); //overloadded exec from QApplication
};

class QtScreen
{
protected :
int m_x;
int m_y;
int m_width;
int m_height;
QtWindow *m_window;
bool m_bounds_restricted;
/* virtual char **getArgs(int *argc);
virtual void computeBounds();
virtual void createQtWindow();
virtual void windowShown();
*/

public :
QtScreen();
bool init();
/* void close();
void showWindow();
void setMouseCursor(int cursor);
void beep();
int width();
int height();
int dotsPerInch();
QtWindow *window();
int x();
int y();
*/
};

class QtScreenFactory
{
static QtScreen *theScreen;
public:
static QtScreen *getScreen();
};


QtWindow *m_window;
QtScreen *QtScreenFactory::theScreen = NULL;
QtApplication::QtApplication(int &argc, char **argv) : QApplication(argc, argv) {
}

int
QtApplication::exec(void) {
printf("QApplication exec called %x\n", pthread_self());
QApplication::exec();
printf("QApplication exec done\n");
}

QtWindow::QtWindow(int flags, const char *name, QWidget *parent) :
QWidget(parent, (Qt::WindowFlags)flags)
{
setMouseTracking(true);
}

void QtWindow::setMask(const QBitmap &bm)
{
printf("QtWindow::setMask\n");
}

void
QtWindow::paintEvent(QPaintEvent *event)
{
printf("paintEvent called\n");
#if 0
QPen *qp = new QPen();
QColor c(0xffff0000);
qp->setColor(c);
QBrush *qb = new QBrush();
QPainter p(this);
p.setCompositionMode(QPainter::CompositionMode_Sou rceOver);
p.setPen(*qp);
p.setClipRect(0,0,800,600);
p.drawLine(30,135,790,135);
#endif
QPainter p(QtImageDescPool[0].qpd);
QPoint pt(0,0);
p.drawImage(pt, img);
}

int main(int argc, char **argv)
{
pthread_t tid;
printf("main thread %x, argc %d, argv %s\n",pthread_self(), argc, *argv);
#if 1
pthread_create(&tid, NULL, (void *(*)(void *))threadfunc, NULL);
#endif
while(!initDone);
AWT_drawline(0,599,799,599);
usleep(1000);
AWT_drawrect(30,135,190,100);
while(true) {}
// img = new QImage(800,600,QImage::Format_ARGB32);
}

QtScreen *
QtScreenFactory::getScreen() {
printf("QtScreenFactory::getScreen()\n");
if ( QtScreenFactory::theScreen == NULL ) {
QtScreenFactory::theScreen = new QtScreen();
if(QtScreenFactory::theScreen != NULL) {
QtScreenFactory::theScreen->init();
}
}
return QtScreenFactory::theScreen;
}

QtScreen::QtScreen()
{
printf("QtScreen::QtScreen()\n");
QtImageDescPool = (QtImageDesc *) calloc(sizeof(QtImageDesc), 128);
}

void getQtColorModel()
{
int depth = 0;
int amask=0,rmask=0,gmask=0,bmask=0;

QWidget *d = QApplication::desktop();
depth = d->depth();
printf ("Depth = %d\n", depth);
switch(depth) {
case 32:
amask = 0xff000000;
case 24:
rmask = 0x00ff0000;
gmask = 0x0000ff00;
bmask = 0x000000ff;
break;
}
}

void Qtexec()
{
qtApp->exec();
}

bool
QtScreen::init()
{
printf("QtScreen::init() %x\n", pthread_self());
int m_x = 0,m_y=0,m_width=SCREEN_X_RESOLUTION,m_height=SCREE N_Y_RESOLUTION;

int argc = 1;
// char *argv[3] = {"a.out", "-qws", NULL};

char **argv = (char**)malloc(sizeof(char**) * 2);
argv[0] = (char *)malloc(sizeof(char) * 128);
argv[1] = NULL;
strcpy(argv[0], "cvm");

new QtApplication(argc, argv);
QRect screen_bounds = QApplication::desktop()->frameGeometry();
m_window = new QtWindow(Qt::FramelessWindowHint|Qt::Window);
printf("m_window %x\n", this->m_window);
QBitmap bitmap(m_width, m_height);
m_window->setMask(bitmap);
qtApp->setActiveWindow(this->m_window);
this->m_window->move(0,0);
this->m_window->setFixedSize(SCREEN_X_RESOLUTION, SCREEN_Y_RESOLUTION);
this->m_window->show();

QtImageDescPool[0].qpd = this->m_window;

getQtColorModel();
initDone = true;

}


void threadfunc(void *arg)
{
printf("threadfunc called\n");
QtScreen *screen = QtScreenFactory::getScreen();
Qtexec();
}

void
AWT_drawline(int x1, int y1, int x2, int y2)
{
#if 0
QPen *qp = new QPen();
QBrush *qb = new QBrush();
QPainter p(qpd);
p.setCompositionMode(QPainter::CompositionMode_Sou rceOver);
p.setPen(*qp);
p.setClipRect(0,0,800,600);
p.drawLine(30,135,790,135);
#endif
printf("drawline called\n");
QPainter p(&img);
p.setCompositionMode(QPainter::CompositionMode_Sou rceOver);
QPen *qp = new QPen();
QColor c(0xffff0000);
qp->setColor(c);
QBrush *qb = new QBrush();
p.setPen(*qp);
p.setClipRect(0,0,SCREEN_X_RESOLUTION,SCREEN_Y_RES OLUTION);
p.drawLine(x1, y1, x2, y2);
printf("m_window %x\n", ((QtWindow *)QtImageDescPool[0].qpd));
//((QtWindow *)arg)->update(0,0,800,600);
((QtWindow *)QtImageDescPool[0].qpd)->update(0,0,SCREEN_X_RESOLUTION,SCREEN_Y_RESOLUTION );
}

void
AWT_drawrect(int x, int y, int w, int h)
{
printf("drawrect called\n");
QPainter p(&img);
p.setCompositionMode(QPainter::CompositionMode_Sou rceOver);
QPen *qp = new QPen();
QColor c(0xffff0000);
qp->setColor(c);
p.setPen(*qp);
p.setClipRect(0,0,800,600);
p.drawRect(x, y, w, h);
printf("m_window %x\n", ((QtWindow *)QtImageDescPool[0].qpd));
//((QtWindow *)arg)->update(0,0,800,600);
((QtWindow *)QtImageDescPool[0].qpd)->update(0,0,SCREEN_X_RESOLUTION,SCREEN_Y_RESOLUTION );
}

psadhukhan
2nd December 2008, 12:33
I also saw that from QCoreApplication::exec() that


int QCoreApplication::exec()
{
if (!QCoreApplicationPrivate::checkInstance("exec"))
return -1;

QThreadData *threadData = self->d_func()->threadData;
if (threadData != QThreadData::current()) {
qWarning("%s::exec: Must be called from the main thread", self->metaObject()->className());
return -1;
}
if (!threadData->eventLoops.isEmpty()) {
qWarning("QCoreApplication::exec: The event loop is already running");
return -1;
}

that it will throw an warning as shown above if not called from main thread but I did not get any warning, so I guess any thread can call exec() so long the thread also does QApplication(argc, argv) and it's not spawned by QThread api?
Can you please confirm?