PDA

View Full Version : Qt5 and embedwidgets



PstdEr
11th June 2013, 06:05
Hi,

so far i worked with Qt 4.x , and i used QX11EmbedWidgets and QX11EmbedContainer classes for embedding my applications.

now we need to convert this code to Qt5, i heard there are lot of advancements and changes done to Qt5.

if anybody has any idea how embedding of widgets is done in Qt5, please help me.

Uwe
11th June 2013, 07:06
For X11 Qt5 means nothing but regression as the X11 paint engine is gone and only the software renderer is left - with Qt 4.8 you can decide. For an application using vector graphics the hardware acceleration of X11 is way faster, when drawing gradients it is the other way round.

As long as you don't plan to use QML I don't see any strong reason for porting an application to Qt5.

Concerning your question: these classes will be reintroduced with Qt 5.1.

Uwe

PstdEr
11th June 2013, 07:48
For X11 Qt5 means nothing but regression as the X11 paint engine is gone and only the software renderer is left - with Qt 4.8 you can decide. For an application using vector graphics the hardware acceleration of X11 is way faster, when drawing gradients it is the other way round.


i frankley dont understand what you are trying to say :( . I am bit new.




Concerning your question: these classes will be reintroduced with Qt 5.1.


So you mean to say we cannot compile / run any application involving QX11Embed* until 5.1 is released.

is there any other alternate in Qt5 for embedding external apps into a widgets.

Thanks,
Pstd

Uwe
11th June 2013, 08:10
i frankley dont understand what you are trying to say
I'm saying that for a QWidget based application running on X11 better stay with Qt4.

Uwe

anda_skoa
11th June 2013, 08:18
For X11 Qt5 means nothing but regression as the X11 paint engine is gone and only the software renderer is left

The X11 paint device would need to be ported to XCB first, but there is nothing in the QPA that would prevent it from using it or given an option on using it.

It is just very likely that there are not a lot of Qt users who need that and none of them needs it enough to do the port or a new XCB based implementation.


So you mean to say we cannot compile / run any application involving QX11Embed* until 5.1 is released.


You don't have to wait for the release, the beta is already available (has been for quite a while). And the release is expected quite soon IIRC:

Cheers,
_

PstdEr
11th June 2013, 10:15
Going through your reply i understood that , there is a way to use embedwidgets in Qt 5/beta.

I have gone through most of the examples , and found nothing about embed widgets.
will you please provide some links for examples on Qt 5 which use embeding widgets.
i try to compile the code with Qt 5.0 with QX11Embed* and it says cannot find such symbols.


Thanks,

anda_skoa
11th June 2013, 13:48
i try to compile the code with Qt 5.0 with QX11Embed* and it says cannot find such symbols.


Is that 0 a typo? As Uwe said those classes are coming with Qt5.1, so the 5.1 beta should have them as well.

But maybe they got postponed to 5.2?

Cheers,
_

Uwe
11th June 2013, 19:40
The X11 paint device would need to be ported to XCB first, but there is nothing in the QPA that would prevent it from using it or given an option on using it.
It is just very likely that there are not a lot of Qt users who need that and none of them needs it enough to do the port or a new XCB based implementation.
Well everyone doing remote/X11 with a certain performance needs it - but as it seems to be neglected that this use case exists nowadays ...

Uwe

PstdEr
12th June 2013, 07:17
Is that 0 a typo? As Uwe said those classes are coming with Qt5.1, so the 5.1 beta should have them as well.

But maybe they got postponed to 5.2?

Cheers,
_

no , its not a typo, i am currently using Qt 5.0, i thought embedding widgets is available in Qt 5.0.

I found below link:
http://blog.qt.digia.com/blog/2013/02/19/introducing-qwidgetcreatewindowcontainer/
i think this is what i require for achieving emebed functionality but it clearly says it is available in Qt 5.1.

i think i will come back with some code for help..

Uwe
12th June 2013, 07:41
This blog is about how to use Qt widgets and QML stuff together - what has absolutely nothing to do with embedding native X11 code into a Qt widget based application.

Are you sure that you know what you want to do ?

Uwe

anda_skoa
12th June 2013, 09:33
no , its not a typo, i am currently using Qt 5.0, i thought embedding widgets is available in Qt 5.0.

What in "...these classes will be reintroduced with Qt 5.1" made you reach that conclusion?



I found below link:
http://blog.qt.digia.com/blog/2013/02/19/introducing-qwidgetcreatewindowcontainer/

As Uwe pointed out that is to integrate QWidgets into an application that is just using QtGui, e.g. one that is using QtQuick2 or a different UI system.

Cheers,
_

PstdEr
12th June 2013, 13:19
what i have previously was , an application developed using QX11EmbedWidget which accepts a window id argument and opens the application in the specified window id.

so i run the stand alone application usnig ./App 2

where 2 is the winId ( inface we can give any number)

the same appilcation can also be launched into someother application window which is QX11EmbedContainer widget.

what i am expecting from the blog is

createWindowContainer is the replacement for QX11EmbedContainer
and
fromWinId used to embed another window( which is an app in my case)

(QWindow * QWindow::fromWinId(WId id) [static]) (http://doc-snapshot.qt-project.org/5.0/qtgui/qwindow.html#requestActivate)

is my understanding correct. i have not tried these in a program yet and there are no sample snippets .

PstdEr
12th June 2013, 15:50
here is my sample app using Qt 4.8 , i need to find the Qt5 equivalent calls to make it work.

sorry i could not attach zip or tar ..

container related files

applicationwindow.cpp
------------------------------




#include "applicationwindow.h"

ApplicationWindow::ApplicationWindow(QWidget *parent) :
QWidget(parent)
{

}
ApplicationWindow::ApplicationWindow(int min_width,int min_height,int max_width,int max_height,QWidget* parent)
:min_width(min_width),min_height(min_height),max_w idth(max_width),max_height(max_height),QWidget(par ent)
{

}

ApplicationWindow::~ApplicationWindow()
{
/*
if (window != NULL)
{
delete window;
window = NULL;
}*/
}

QX11EmbedContainer* ApplicationWindow::createApplicationWindow()
{
window = new QX11EmbedContainer();
window->setSizePolicy(QSizePolicy::Expanding,QSizePolicy:: Expanding);
// display->showFullScreen();
QPalette pl = QPalette();
pl.setColor(QPalette::Window,Qt::black);
window->setAttribute(Qt::WA_PaintOnScreen,true);
window->setPalette(pl);
// display->setGeometry(0,0,700,256);
window->setMouseTracking(true);
window->setMinimumSize(min_width,min_height);
window->setMaximumSize(max_width,max_height);
return window;
}




applicationwindow.h
-------------------------------




#ifndef APPLICATIONWINDOW_H
#define APPLICATIONWINDOW_H

#include <QWidget>
#include <QX11EmbedContainer>


class ApplicationWindow : public QWidget
{
Q_OBJECT
public:
explicit ApplicationWindow(QWidget *parent = 0);
explicit ApplicationWindow(int min_width,int min_height,int max_width,int max_height,QWidget* parent=0);
QX11EmbedContainer* createApplicationWindow();


public:
virtual ~ApplicationWindow();
private:
int max_width;
int max_height;
int min_width;
int min_height;

QX11EmbedContainer* window;
signals:

public slots:

};

#endif // APPLICATIONWINDOW_H




main.cpp
-----------


#include "mainwindow.h"

MainWindow *Container;
int main(int argc, char *argv[])
{

QApplication qapp(argc, argv);
Container = new MainWindow();

Container->show();
return qapp.exec();

}



mainwindow.cpp
-------------------------


#include "mainwindow.h"

#define HEIGHT 708
#define FTP_HEIGHT 60
#define WIDTH 196

#define HELLOTEST "../hellotest/hellotest"

extern MainWindow *Container;

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{

ApplicationProcess = NULL;
QWidget* mainwindow = new QWidget();

getDisplayProperties(&max_width,&max_height);
setWindowMinimumSizes(max_width - 300,HEIGHT - 100);
setWindowMaximumSizes(max_width,max_height);

createActions();
createMenus();

mainwindow->setMinimumSize(min_width,min_height);
mainwindow->setSizePolicy(QSizePolicy::Expanding,QSizePolicy:: Expanding);
mainwindow->setMaximumSize(max_width,max_height);
setCentralWidget(mainwindow);

QPalette pl ;
pl.setColor(pl.Background,Qt::white);

mainwindow->setAutoFillBackground(true);
mainwindow->setPalette(pl);

vLayout = new QVBoxLayout();
mainLayout = new QHBoxLayout();
vWidget = new QWidget();

appwindow = new ApplicationWindow (min_width - WIDTH ,min_height - (FTP_HEIGHT + 105),max_width - WIDTH,max_height - (100 +FTP_HEIGHT ) );
display = appwindow->createApplicationWindow();

vWidget->setLayout(vLayout);

vLayout->addWidget(display);
vLayout->setSpacing(1);

mainLayout ->addWidget(vWidget);
mainwindow ->setLayout(mainLayout);
vLayout->setContentsMargins(0,0,0,0);
display->setContentsMargins(0,0,0,0);
mainwindow->setContentsMargins(0,0,0,0);

mainwindow->setSizePolicy(QSizePolicy::Expanding,QSizePolicy:: Expanding);
display->setSizePolicy(QSizePolicy::Expanding,QSizePolicy:: Expanding);

}

void MainWindow::getDisplayProperties(int* width,int* height )
{
int x = 0,y = 0;
QRect rec;
QDesktopWidget D;
rec = D.geometry();
rec.getRect(&x,&y,width,height);
}

void MainWindow::setWindowMinimumSizes(int min_width,int min_height)
{

this->min_width = min_width;
this->min_height = min_height;

printf("Minimum Height is %d\n",min_height);

}
void MainWindow::setWindowMaximumSizes(int max_width,int max_height)
{
this->max_width = max_width;
this->max_height = max_height;
}

void MainWindow::createActions()
{
HelloTestAct = new QAction(tr("&HelloTest"),this);
connect(HelloTestAct,SIGNAL(triggered()),this,SLOT (Launch_Hello_Test()));

}

void MainWindow::Launch_Hello_Test()
{

qDebug() << "Launch_Hello_Test";

ApplicationProcess = new QProcess(display);
QString executable(HELLOTEST);
QStringList arguments;
arguments << QString::number(display->winId());
ApplicationProcess->start(executable, arguments);
}

void MainWindow::createMenus()
{
fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(HelloTestAct);
}

MainWindow :: ~MainWindow()
{
}


mainwindow.h
----------------------


#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QDialog>
#include <QtGui>
#include <qwidget.h>
#include <QProcess>
#include <QString>

#include "applicationwindow.h"

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
MainWindow(QWidget *parent = 0);
~MainWindow();

private:

QProcess* ApplicationProcess;
int max_width;
int max_height;
int min_width;
int min_height;

QMenu *fileMenu;


QWidget* mainwindow;

ApplicationWindow* appwindow;
QHBoxLayout* mainLayout;
QVBoxLayout* vLayout;
QWidget* vWidget;
QX11EmbedContainer* display;

QAction* HelloTestAct;
private:
void createActions();
void createMenus();
void getDisplayProperties(int* width,int* height);
void setWindowMinimumSizes(int min_width,int min_height);
void setWindowMaximumSizes(int min_width,int max_width);


private slots:
void Launch_Hello_Test();
};

#endif // MAINWINDOW_H



the sample test app
this can be run by typing ./hellotest 2

hellotest.cpp
-------------------

#include "hellotest.h"

HelloTest :: HelloTest(QWidget *parent):
QWidget(parent)
{

qDebug() << "in hello test";
QWidget *window = new QWidget(parent);
QVBoxLayout *vl = new QVBoxLayout;
window -> resize(500,500);
window -> setPalette(QPalette(QColor(0,255,0,255)));
window -> setAutoFillBackground(true);
this -> setLayout(vl);
vl -> addWidget(window);
}

HelloTest::~HelloTest()
{

}


hellotest.h
------------------





#ifndef HELLOTEST_H
#define HELLOTEST_H

#include <QWidget>
#include <QDebug>
#include <QX11EmbedWidget>
#include <QApplication>
#include <QVBoxLayout>
#include <QDebug>

class HelloTest :public QWidget
{
Q_OBJECT

public:
HelloTest(QWidget *parent = 0);
~HelloTest();
private:



};

#endif // HELLOTEST_H



main.cpp
--------------





#include "hellotest.h"


QX11EmbedWidget *embed;
HelloTest *hellotest;

int main(int argc, char *argv[])
{
QApplication qapp(argc, argv);
QString windowId(qapp.arguments()[1]);
QVBoxLayout* layout = new QVBoxLayout;

embed = new QX11EmbedWidget;
embed -> setMinimumSize(500,500);
embed -> setSizePolicy(QSizePolicy::Expanding,QSizePolicy:: Expanding);

embed -> setPalette(QColor(255,0,0,255));
embed -> setAutoFillBackground(true);

hellotest = new HelloTest(embed);
hellotest -> setContentsMargins(0,0,0,0);

if(NULL == embed)
{
qDebug() << "Unable to create hellotest";
return 0;
}
if(argc < 2)
{
qDebug() << "More Arguments Needed";
return 0;
}
qDebug()<<"windowId in WG:"<<windowId;

layout -> addWidget(hellotest);
embed -> setLayout(layout);
embed -> embedInto(windowId.toULong());
embed -> show();
return qapp.exec();
}

PstdEr
14th June 2013, 13:29
I am trying to embed an application in another application widget using QWindow and createWidowContainer in Qt5.

The problem is that the window is not embedding into the application window.

and also when i launch the applications individually i can get logs from both apps, but when i launch from container application the embedding application logs are not displayed.

please have a look and guide me in proper direction.

The container code:

mainwindow.h


#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QProcess>
#include <QDebug>
#include <QtGui>
#include<QHBoxLayout>
#include <QtWidgets>

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
MainWindow(QWidget *parent = 0);
~MainWindow();

private:

QWidget* display;
QAction* HelloTestAct;
QProcess* ApplicationProcess;
QHBoxLayout* mainLayout;
QMenu *fileMenu;


void createActions();
void createMenus();

private slots:
void Launch_Hello_Test();
void finish(int,QProcess::ExitStatus);
};

#endif // MAINWINDOW_H


mainwindow.cpp


#include "mainwindow.h"

#define HELLOTEST "/home/Documents/5.1example/rasterwindow/rasterwindow"

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
qDebug()<<"MainWindow";
ApplicationProcess = NULL;
QWidget* mainwindow = new QWidget();
mainLayout = new QHBoxLayout();
mainwindow->setMinimumSize(500,500);
createActions();
createMenus();
setCentralWidget(mainwindow);

QPalette pl ;
pl.setColor(pl.Background,Qt::white);

mainwindow->setAutoFillBackground(true);
mainwindow->setPalette(pl);
mainwindow ->setLayout(mainLayout);
display= createWindowContainer(0,0,0);
display= createWindowContainer(0,0,0);
pl.setColor(QPalette::Window,Qt::black);
display->setAttribute(Qt::WA_PaintOnScreen,true);
display->setPalette(pl);
}

void MainWindow::createActions()
{
HelloTestAct = new QAction(tr("&HelloTest"),this);
connect(HelloTestAct,SIGNAL(triggered()),this,SLOT (Launch_Hello_Test()));

}

void MainWindow::Launch_Hello_Test()
{

qDebug() << "Launch_Hello_Test";

ApplicationProcess = new QProcess(display);
QString executable(HELLOTEST);
QStringList arguments;
arguments << QString::number(display->winId());
qDebug() << "window id" << arguments.at(0);
connect(ApplicationProcess,SIGNAL(finished(int,QPr ocess::ExitStatus)),this,SLOT(finish(int,QProcess: :ExitStatus)));
ApplicationProcess->start(executable, arguments);
}

void MainWindow::finish(int,QProcess::ExitStatus)
{
qDebug()<<"finish";
}

void MainWindow::createMenus()
{
fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(HelloTestAct);
}

MainWindow :: ~MainWindow()
{
}



main.cpp


#include "mainwindow.h"
#include <QApplication>

MainWindow *Container;
int main(int argc, char *argv[])
{
QApplication qapp(argc, argv);
qDebug()<<"in Main";
Container = new MainWindow();
Container->show();
return qapp.exec();

#if 0
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
#endif

}



The Embedding application:I am trying to embed an application from Qt Example itself
from Rasterwindow in Qt Examples

rasterwindow.h


#ifndef RASTERWINDOW_H
#define RASTERWINDOW_H
#include <QtGui>
class RasterWindow : public QWindow
{
Q_OBJECT
public:
explicit RasterWindow(QWindow *parent = 0);
virtual void render(QPainter *painter);
public slots:
void renderLater();
void renderNow();
protected:
bool event(QEvent *event);
void resizeEvent(QResizeEvent *event);
void exposeEvent(QExposeEvent *event);

private:
QBackingStore *m_backingStore;
bool m_update_pending;
};

#endif // RASTERWINDOW_H



main.cpp


#include "rasterwindow.h"

int main(int argc, char **argv)
{
QGuiApplication app(argc, argv);
QString windowId(app.arguments()[2]);
qDebug()<<"in main form raster "<< app.arguments()[0];
qDebug()<<"in main form raster "<< app.arguments()[1];
qDebug()<<"in main form raster "<< app.arguments()[2];

RasterWindow window;
window.fromWinId(windowId.toULong());

window.show();

return app.exec();
}



rasterwindow.cpp



#include "rasterwindow.h"

RasterWindow::RasterWindow(QWindow *parent)
: QWindow(parent)
, m_update_pending(false)
{
m_backingStore = new QBackingStore(this);
create();

setGeometry(100, 100, 300, 200);

}

bool RasterWindow::event(QEvent *event)
{
if (event->type() == QEvent::UpdateRequest) {
m_update_pending = false;
renderNow();
return true;
}
return QWindow::event(event);
}

void RasterWindow::renderLater()
{
if (!m_update_pending) {
m_update_pending = true;
QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
}
}


void RasterWindow::resizeEvent(QResizeEvent *resizeEvent)
{
m_backingStore->resize(resizeEvent->size());
if (isExposed())
renderNow();
}

void RasterWindow::exposeEvent(QExposeEvent *)
{
if (isExposed()) {
renderNow();
}
}

void RasterWindow::renderNow()
{
if (!isExposed())
return;

QRect rect(0, 0, width(), height());
m_backingStore->beginPaint(rect);

QPaintDevice *device = m_backingStore->paintDevice();
QPainter painter(device);

painter.fillRect(0, 0, width(), height(), Qt::white);
render(&painter);

m_backingStore->endPaint();
m_backingStore->flush(rect);
}

void RasterWindow::render(QPainter *painter)
{
painter->drawText(QRectF(0, 0, width(), height()), Qt::AlignCenter, QStringLiteral("QWindow"));
}

wysota
15th June 2013, 09:18
what i am expecting from the blog is

createWindowContainer is the replacement for QX11EmbedContainer
No, it is not.

anda_skoa
15th June 2013, 12:49
The current code doesn't make any sense, you are passing the window ID into the wrong direction.

The child application needs to determine its window's ID and send it to the host application.
The host then needs to wrap it in a QWindow using fromWinId() and then put that window into its widget tree by using createWindowContainer()

Cheers,
_

PstdEr
17th June 2013, 15:43
No, it is not.

Will you please show me sample code on how to embed a widget in container in Qt5.


The current code doesn't make any sense, you are passing the window ID into the wrong direction.

The child application needs to determine its window's ID and send it to the host application.
The host then needs to wrap it in a QWindow using fromWinId() and then put that window into its widget tree by using createWindowContainer()

Cheers,
_

thank you very much , i modified the code .


Now the problem is
when i run the apps separately ,my message queue is working (receive and send )
but if i launch from the container ->File->Hellotest , the container is not able to receive the message.

below is the only functions i modified , rest all is same as old.

please help/suggest a way, i dont have other go i have to finish this ... :(

Still the window is not embedding...

mainwindow.cpp - container




#include "mainwindow.h"
#include <QWindow>
#include <QObject>

#define HEIGHT 708
#define FTP_HEIGHT 60
#define WIDTH 196
#include <pthread.h>
#include <mqueue.h>
#include <QtWidgets/qwidget.h>
#include <qwindow.h>
#include <qwindowdefs.h>

#define HELLOTEST "/home/Documents/5.1example/rasterwindow/rasterwindow"

void *wait_for_id(void * arg);

extern MainWindow *Container;

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
qDebug()<< "MainWindow";
ApplicationProcess = NULL;
QWidget* mainwindow = new QWidget();

getDisplayProperties(&max_width,&max_height);
setWindowMinimumSizes(max_width - 300,HEIGHT - 100);
setWindowMaximumSizes(max_width,max_height);

createActions();
createMenus();

mainwindow->setMinimumSize(min_width,min_height);
mainwindow->setSizePolicy(QSizePolicy::Expanding,QSizePolicy:: Expanding);
mainwindow->setMaximumSize(max_width,max_height);
setCentralWidget(mainwindow);

QPalette pl ;
pl.setColor(pl.Background,Qt::white);

mainwindow->setAutoFillBackground(true);
mainwindow->setPalette(pl);

vLayout = new QVBoxLayout();
mainLayout = new QHBoxLayout();
vWidget = new QWidget();

appwindow = new ApplicationWindow (min_width - WIDTH ,min_height - (FTP_HEIGHT + 105),max_width - WIDTH,max_height - (100 +FTP_HEIGHT ) );
display = appwindow->createApplicationWindow();

vWidget->setLayout(vLayout);

vLayout->addWidget(display);
vLayout->setSpacing(1);

mainLayout ->addWidget(vWidget);
mainwindow ->setLayout(mainLayout);
vLayout->setContentsMargins(0,0,0,0);
display->setContentsMargins(0,0,0,0);

mainwindow->setContentsMargins(0,0,0,0);

mainwindow->setSizePolicy(QSizePolicy::Expanding,QSizePolicy:: Expanding);
display->setSizePolicy(QSizePolicy::Expanding,QSizePolicy:: Expanding);

pthread_t tid;
if (-1 == pthread_create(&tid,NULL,wait_for_id,NULL)){
perror("pthread_create");
}else{
qDebug()<<"thread create success";
}

}

void MainWindow::getDisplayProperties(int* width,int* height )
{
int x = 0,y = 0;
QRect rec;
QDesktopWidget D;
rec = D.geometry();
rec.getRect(&x,&y,width,height);
}

void MainWindow::setWindowMinimumSizes(int min_width,int min_height)
{

this->min_width = min_width;
this->min_height = min_height;

printf("Minimum Height is %d\n",min_height);

}

void MainWindow::setWindowMaximumSizes(int max_width,int max_height)
{
this->max_width = max_width;
this->max_height = max_height;
}


void MainWindow::createActions()
{

HelloTestAct = new QAction(tr("&HelloTest"),this);
connect(HelloTestAct,SIGNAL(triggered()),this,SLOT (Launch_Hello_Test()));
connect(this,SIGNAL(send_winid(int)),this,SLOT(lau nch_app(int)));
}


void MainWindow::Launch_Hello_Test()
{

qDebug() << "Launch_Hello_Test";
pthread_t tid;

ApplicationProcess = new QProcess(display);
QString executable(HELLOTEST);
QStringList arguments;

//connect( ApplicationProcess,SIGNAL(readyReadStandardError() ),logwindow,SLOT(readStandardError()));
//connect( ApplicationProcess,SIGNAL(readyReadStandardOutput( )),logwindow,SLOT(readStandardOutput()));

connect(ApplicationProcess,SIGNAL(finished(int,QPr ocess::ExitStatus)),this,SLOT(finish(int,QProcess: :ExitStatus)));
ApplicationProcess->start(executable, arguments);


}

void * wait_for_id( void *arg)
{
struct mq_attr mqAttr;
char buffer[1024];
mqd_t msgid;
int ret_val;
int winid;
mqAttr.mq_maxmsg = 10;
mqAttr.mq_msgsize = 512;

if(mq_unlink("/embed6")<0)
qDebug()<<"Init unable to unlink";
else
qDebug()<<"Init unlink success";

msgid = mq_open("/embed6",O_RDWR|O_CREAT,0777,&mqAttr);

if(-1 == msgid){
perror("mq_open");
return NULL;
}else{
qDebug()<< "mq_open success";
}

ret_val = mq_receive(msgid,buffer,sizeof(buffer),NULL);

if(-1 == ret_val) {
qDebug() << "mq_receive ret_val(Err) = "<< ret_val;
}
else {
qDebug() << "window id received is :"<< buffer;
mq_close(msgid);
winid = atoi(buffer);
Container->embed_window(winid);
if(mq_unlink("/embed6")<0)
qDebug()<<"unable to unlink";
else
qDebug()<<"unlink success";
}

}

void MainWindow ::embed_window(int id)
{
emit send_winid(id);

}

void MainWindow::launch_app(int id)
{
qDebug()<<"In launch_app";
QVBoxLayout *vl = new QVBoxLayout;
WId winid = (WId) id;
display->setLayout(vl);
QWindow *wind = QWindow::fromWinId(winid);
window = createWindowContainer(wind,display,0);

//vl->addWidget(window);

}

void MainWindow::finish(int,QProcess::ExitStatus)
{
qDebug()<<"finish";
}

void MainWindow::createMenus()
{
fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(HelloTestAct);
}

MainWindow :: ~MainWindow()
{
}




mainwindow.h - container


#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include<QtWidgets/QMainWindow>
#include <QtWidgets/QDialog>
#include <QtGui>
#include <QtWidgets/qwidget.h>
#include <QProcess>
#include <QString>

#include "applicationwindow.h"

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
MainWindow(QWidget *parent = 0);
~MainWindow();
void embed_window(int id);
private:

QProcess* ApplicationProcess;
int max_width;
int max_height;
int min_width;
int min_height;

QMenu *fileMenu;
QWidget* mainwindow;

ApplicationWindow* appwindow;
QHBoxLayout* mainLayout;
QVBoxLayout* vLayout;
QWidget* vWidget;
QWidget* display;
QAction* HelloTestAct;
QWidget* window;

private:
void createActions();
void createMenus();
void getDisplayProperties(int* width,int* height);
void setWindowMinimumSizes(int min_width,int min_height);
void setWindowMaximumSizes(int min_width,int max_width);


private slots:
void Launch_Hello_Test();
void finish(int,QProcess::ExitStatus);
void launch_app(int id);
signals:
void send_winid(int id);
};

#endif // MAINWINDOW_H





main.cpp - rasterwindow



#include "rasterwindow.h"
#include<mqueue.h>
#include <stdio.h>
#include<qwindow.h>
#include<qwindowdefs.h>
int main(int argc, char **argv)
{
struct mq_attr mqAttr;
char buffer[512];
mqd_t msgid;
int ret_val;
int winid_int;
WId winid ;
mqAttr.mq_maxmsg = 10;
mqAttr.mq_msgsize = 512;

QGuiApplication app(argc, argv);
RasterWindow window;
qDebug()<<"before mq_open";
winid = window.winId();
qDebug()<<"window id is :"<< winid;
winid_int = (int) winid;
qDebug()<<"window id int :"<< winid;
msgid = mq_open("/embed6",O_RDWR);
if(-1 == msgid){
perror("mq_open");
return NULL;
}else{
qDebug()<<"mq_open success";
}

sprintf(buffer,"%d",winid_int);

ret_val = mq_send(msgid,buffer,strlen(buffer)+1,1);
if(-1 == ret_val)
perror("mq_receive");
else {
qDebug () << "window id sent is"<< buffer;
mq_close(msgid);
}
window.show();
return app.exec();
}

anda_skoa
17th June 2013, 16:09
Using a low level thread and having it emit a signal is most likely the problem because the slot will likely be called in the secondary thread's context and not in the one handling the UI.

My recommendation is to try something simpler first, e.g. letting the rasterwindow program write its winId to stdout (followed by newline and maybe flush), which you then read in the main application through QProcess (see signal readyReadStandardOutput())

That way you can test the child process manually, e.g. start it in a shell window and see if it correctly outputs its window id.

i'd also recommend that you put some empty placeholder widget into the central widget and when you got the winId and have create the window container, you put the window container into a layout in that placeholder.
You obviously need to keep a pointer to that placerholder as a member of the main window instance so you can access it from the slot connected to readyReadStandardOutput()

Cheers,
_

PstdEr
18th June 2013, 06:17
Thanks anda_skoa,
i will try what you said,but before that i would like let you know the output i am getting with current program.

When i run the raster example alone i am getting the window id printed in Qt Creator Log.
and also if i run container first and raster second seperately i am able to receive the winid in the container but the window is not embedded into it.

logs when running rasterwindow
In RasterWindow
before mq_open
window id is : 121634822
window id int : 121634822
mq_open success
window id sent is 121634822

logs when running container

in Main
MainWindow
thread create success
Init unable to unlink
mq_open success
window id received is : 121634822
unlink success
In launch_app

some times i am getting below errors:

QXcbConnection: XCB error: 8 (BadMatch), sequence: 1131, resource id: 121634822, major code: 1 (CreateWindow), minor code: 0
QXcbConnection: XCB error: 3 (BadWindow), sequence: 1134, resource id: 109051937, major code: 18 (ChangeProperty), minor code: 0

anda_skoa
18th June 2013, 09:12
It might be helpful to see the actual code of launch_app()
the one you posted will obviously never embed the window since the widget is never added to any layout.

Cheers,
_

PstdEr
19th June 2013, 08:26
Hi anda_skoa,
I have added the following code in the container.




void MainWindow::launch_app(int id)
{
qDebug()<<"In launch_app win id is "<< id;
QVBoxLayout *vl = new QVBoxLayout;
WId winid = (WId) id;
display->setLayout(vl);
window = createWindowContainer(QWindow::fromWinId(winid),di splay,Qt::WindowMinMaxButtonsHint|Qt::WindowCloseB uttonHint|Qt::WindowCancelButtonHint);
vl->addWidget(window);
}

void MainWindow::Launch_Hello_Test()
{
qDebug() << "Launch_Hello_Test";

ApplicationProcess = new QProcess();
QString executable(HELLOTEST);
QStringList arguments;
Container->process = ApplicationProcess;

connect( ApplicationProcess,SIGNAL(readyReadStandardError() ),this,SLOT(readStandardError()));
connect( ApplicationProcess,SIGNAL(readyReadStandardOutput( )),this,SLOT(readStandardOutput()));
connect(ApplicationProcess,SIGNAL(finished(int,QPr ocess::ExitStatus)),this,SLOT(finish(int,QProcess: :ExitStatus)));

ApplicationProcess->start(executable, arguments);
}

void MainWindow :: readStandardOutput()
{
QString Output;

if(ApplicationProcess){
Output = ApplicationProcess->readAllStandardOutput();
qDebug()<<Output;
}else{
qDebug()<<"Problem StdOut";
}
}

void MainWindow :: readStandardError()
{
QString Output;
if(ApplicationProcess){
Output = ApplicationProcess->readAllStandardError();
qDebug()<<Output;
}else{
qDebug()<<"Problem StdErr";
}
}


after launching the rasterwindow appliction conatiner is detecting only finished signal from rasterwindow, but the logs are not getting redirected.

I could see 1 ,2 times the window embedding in container, but its not stable and proper and not always.
embedding is happening in old code also one with thread and message queue

Added after 17 minutes:

is there any other way to embed an application using createWindowContainer or other way in Qt5 ?
I am actually spending a lot of time on this and there are no much examples are references.

PstdEr
19th June 2013, 10:29
I modified the code a bit... with QQuickView.


#include<QtQuick/QQuickView>

void MainWindow::launch_app(int id)
{
WId winid = (WId) id;
QQuickView *view = new QQuickView();//QWindow::fromWinId(winid)) ;
qDebug()<<"In launch_app win id is "<< id;
QVBoxLayout *vl = new QVBoxLayout;

display->setLayout(vl);
qDebug()<<"display->setLayout(vl);";
//QWindow *wind = QWindow::fromWinId(winid);
//window = createWindowContainer(wind,display,Qt::WindowMinMa xButtonsHint|Qt::WindowCloseButtonHint|Qt::WindowC ancelButtonHint);
window = QWidget::createWindowContainer(view);
qDebug()<<"createWindowContainer";
window -> setFocusPolicy(Qt::TabFocus);
qDebug()<<"setFocusPolicy";
/*
window = createWindowContainer(QWindow::fromWinId(winid),di splay,\
Qt::WindowMinMaxButtonsHint|Qt::WindowCloseButtonH int
|Qt::WindowCancelButtonHint
|Qt::FramelessWindowHint);*/
vl -> addWidget(window);
qDebug()<<"addWidget";
}


QQuickView *view = new QQuickView();//QWindow::fromWinId(winid)) ;
QQuickView *view = new QQuickView(QWindow::fromWinId(winid)) ;

i have checked with above two this time i am able to see the logs when i launch rasterwindow from container, but the problem is that the container is closed and only rasterwindow is displayed.

following warning is getting genearated "Xlib: extension "GLX" missing on display ":4".".

anda_skoa
19th June 2013, 14:28
maybe you could upload a buildable and runnable example?

Cheers,
_

PstdEr
20th June 2013, 08:43
rasterwindow related code:

main.cpp
-----------



#include "rasterwindow.h"
#include<mqueue.h>
#include <stdio.h>
#include<qwindow.h>
#include<qwindowdefs.h>

int main(int argc, char **argv)
{
struct mq_attr mqAttr;
char buffer[512];
mqd_t msgid;
int ret_val;
int winid_int;
WId winid ;
mqAttr.mq_maxmsg = 10;
mqAttr.mq_msgsize = 512;

QGuiApplication app(argc, argv);
qDebug()<<"in main";
RasterWindow window;

winid = window.winId();
qDebug()<<"window id is :"<< winid;
winid_int = (int) winid;
qDebug()<<"window id int :"<< winid;

msgid = mq_open("/embed6",O_RDWR);
if(-1 == msgid){
perror("mq_open");
//return NULL;
}else{
qDebug()<<"mq_open success";
}

sprintf(buffer,"%d",winid_int);

ret_val = mq_send(msgid,buffer,strlen(buffer)+1,1);
if(-1 == ret_val)
perror("mq_send");
else {
qDebug () << "window id sent is"<< buffer;
mq_close(msgid);
}

window.show();
return app.exec();
}


rasterwindow.cpp
---------------------


#include "rasterwindow.h"
#include<mqueue.h>
#include <stdio.h>
#include<qwindow.h>
#include<qwindowdefs.h>

RasterWindow::RasterWindow(QWindow *parent)
: QWindow(parent)
, m_update_pending(false)
{
qDebug()<<"In RasterWindow";
m_backingStore = new QBackingStore(this);
create();
setGeometry(100, 100, 300, 200);
setMinimumWidth(800);
setMinimumHeight(600);
//setGeometry(0, 0, 0, 0);
}

bool RasterWindow::event(QEvent *event)
{
if (event->type() == QEvent::UpdateRequest) {
m_update_pending = false;
renderNow();
return true;
}
return QWindow::event(event);
}

void RasterWindow::renderLater()
{
if (!m_update_pending) {
m_update_pending = true;
QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
}
}

void RasterWindow::resizeEvent(QResizeEvent *resizeEvent)
{
m_backingStore->resize(resizeEvent->size());
if (isExposed())
renderNow();
}

void RasterWindow::exposeEvent(QExposeEvent *)
{
if (isExposed()) {
renderNow();
}
}

void RasterWindow::renderNow()
{
if (!isExposed())
return;

QRect rect(0, 0, width(), height());
m_backingStore->beginPaint(rect);

QPaintDevice *device = m_backingStore->paintDevice();
QPainter painter(device);

painter.fillRect(0, 0, width(), height(), Qt::white);
render(&painter);

m_backingStore->endPaint();
m_backingStore->flush(rect);
}

void RasterWindow::render(QPainter *painter)
{
painter->drawText(QRectF(0, 0, width(), height()), Qt::AlignCenter, QStringLiteral("QWindow"));
}


rasterwindow.h
------------------



#ifndef RASTERWINDOW_H
#define RASTERWINDOW_H

#include <QtGui>

class RasterWindow : public QWindow
{
Q_OBJECT
public:
explicit RasterWindow(QWindow *parent = 0);

virtual void render(QPainter *painter);

public slots:
void renderLater();
void renderNow();

protected:
bool event(QEvent *event);

void resizeEvent(QResizeEvent *event);
void exposeEvent(QExposeEvent *event);

private:
QBackingStore *m_backingStore;
bool m_update_pending;
};
#endif // RASTERWINDOW_H




following is the log when i run the application:



QML debugging is enabled. Only use this in a safe environment.
in Main
MainWindow
thread create success
Init unable to unlink
mq_open success
Launch_Hello_Test
"in main
"
"In RasterWindow
"
"window id is : 113246214
window id int : 113246214
"
window id received is : 113246214
embed_window
"mq_open success
window id sent is 113246214
"
unlink success
In launch_app win id is 113246214
addWidget
Minimum Height is 608
/home/Documents/5.1example/appr2/container-build-Qt5_1Alpha-Debug/container exited with code 0



Added after 11 minutes:

main.cpp
-----------


#include "mainwindow.h"
MainWindow *Container;
int main(int argc, char *argv[])
{
QApplication qapp(argc, argv);
qDebug()<<"in Main";
Container = new MainWindow();
Container->show();
return qapp.exec();
}


mainwindow.cpp
----------------



#include "mainwindow.h"
#include <QWindow>
#include <QObject>

#define HEIGHT 708
#define FTP_HEIGHT 60
#define WIDTH 196
#include <pthread.h>
#include <mqueue.h>
#include <QtWidgets/qwidget.h>
#include <qwindow.h>
#include <qwindowdefs.h>

#define HELLOTEST "/home/Documents/5.1example/appr2/rasterwindow-build-Desktop-Release/rasterwindow"

void *wait_for_id(void * arg);

extern MainWindow *Container;

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
qDebug()<< "MainWindow";
ApplicationProcess = NULL;
QWidget* mainwindow = new QWidget();

getDisplayProperties(&max_width,&max_height);
setWindowMinimumSizes(max_width - 300,HEIGHT - 100);
setWindowMaximumSizes(max_width,max_height);

createActions();
createMenus();

mainwindow->setMinimumSize(min_width,min_height);
mainwindow->setSizePolicy(QSizePolicy::Expanding,QSizePolicy:: Expanding);
mainwindow->setMaximumSize(max_width,max_height);
setCentralWidget(mainwindow);

QPalette pl ;
pl.setColor(pl.Background,Qt::white);

mainwindow->setAutoFillBackground(true);
mainwindow->setPalette(pl);

vLayout = new QVBoxLayout();
mainLayout = new QHBoxLayout();
vWidget = new QWidget();

appwindow = new ApplicationWindow (min_width - WIDTH ,min_height - (FTP_HEIGHT + 105),max_width - WIDTH,max_height - (100 +FTP_HEIGHT ) );
display = appwindow->createApplicationWindow();

vWidget->setLayout(vLayout);

vLayout->addWidget(display);
vLayout->setSpacing(1);
display->setPalette(QPalette(QColor(10,0,10,255)));
display->setAutoFillBackground(true);
mainLayout ->addWidget(vWidget);
mainwindow ->setLayout(mainLayout);
vLayout->setContentsMargins(0,0,0,0);
display->setContentsMargins(0,0,0,0);
mainwindow->setContentsMargins(0,0,0,0);

mainwindow->setSizePolicy(QSizePolicy::Expanding,QSizePolicy:: Expanding);
display->setSizePolicy(QSizePolicy::Expanding,QSizePolicy:: Expanding);

pthread_t tid;
if (-1 == pthread_create(&tid,NULL,wait_for_id,NULL)){
perror("pthread_create");
}else{
qDebug()<<"thread create success";
}
}

void MainWindow::getDisplayProperties(int* width,int* height )
{
int x = 0,y = 0;
QRect rec;
QDesktopWidget D;
rec = D.geometry();
rec.getRect(&x,&y,width,height);
}

void MainWindow::setWindowMinimumSizes(int min_width,int min_height)
{
this->min_width = min_width;
this->min_height = min_height;
qDebug()<<"Minimum Height is"<<min_height;
}

void MainWindow::setWindowMaximumSizes(int max_width,int max_height)
{
this->max_width = max_width;
this->max_height = max_height;
}


void MainWindow::createActions()
{

HelloTestAct = new QAction(tr("&HelloTest"),this);
connect(HelloTestAct,SIGNAL(triggered()),this,SLOT (Launch_Hello_Test()));
connect(this,SIGNAL(send_winid(int)),this,SLOT(lau nch_app(int)));
}


void MainWindow::Launch_Hello_Test()
{
qDebug() << "Launch_Hello_Test";

ApplicationProcess = new QProcess();
QString executable(HELLOTEST);
QStringList arguments;
Container->process = ApplicationProcess;

connect( ApplicationProcess,SIGNAL(readyReadStandardError() ),this,SLOT(readStandardError()));
connect( ApplicationProcess,SIGNAL(readyReadStandardOutput( )),this,SLOT(readStandardOutput()));

connect(ApplicationProcess,SIGNAL(finished(int,QPr ocess::ExitStatus)),this,SLOT(finish(int,QProcess: :ExitStatus)));

ApplicationProcess->start(executable, arguments);
}

void MainWindow :: readStandardOutput()
{
QString Output;

if(ApplicationProcess){
Output = ApplicationProcess->readAllStandardOutput();
qDebug()<<Output;
}else{
qDebug()<<"Problem StdOut";
}
}


void MainWindow :: readStandardError()
{
QString Output;
if(ApplicationProcess){
Output = ApplicationProcess->readAllStandardError();
qDebug()<<Output;
}else{
qDebug()<<"Problem StdErr";
}
}

void * wait_for_id( void *arg)
{
struct mq_attr mqAttr;
char buffer[1024];
mqd_t msgid;
int ret_val;
int winid;
mqAttr.mq_maxmsg = 10;
mqAttr.mq_msgsize = 512;

if(mq_unlink("/embed6")<0)
qDebug()<<"Init unable to unlink";
else
qDebug()<<"Init unlink success";

msgid = mq_open("/embed6",O_RDWR|O_CREAT,0777,&mqAttr);

if(-1 == msgid){
perror("mq_open");
}else{
qDebug()<< "mq_open success";
ret_val = mq_receive(msgid,buffer,sizeof(buffer),NULL);

if(-1 == ret_val) {
qDebug() << "mq_receive ret_val(Err) = "<< ret_val;
}
else {
qDebug() << "window id received is :"<< buffer;
mq_close(msgid);
winid = atoi(buffer);
Container->embed_window(winid);

if(mq_unlink("/embed6")<0)
qDebug()<<"unable to unlink";
else
qDebug()<<"unlink success";
}
}
}

void MainWindow ::embed_window(int id)
{
qDebug() << "embed_window";

emit send_winid(id);

}

void MainWindow::launch_app(int id)
{
WId winid = (WId) id;
qDebug()<<"In launch_app win id is "<< id;
QVBoxLayout *vl = new QVBoxLayout;
display->setLayout(vl);
window = createWindowContainer(QWindow::fromWinId(winid),di splay,\
Qt::WindowMinMaxButtonsHint|Qt::WindowCloseButtonH int
|Qt::WindowCancelButtonHint
|Qt::FramelessWindowHint);

vl -> addWidget(window);
qDebug()<<"addWidget";
}

void MainWindow::finish(int,QProcess::ExitStatus)
{
qDebug()<<"finish";
}

void MainWindow::createMenus()
{
fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(HelloTestAct);
}

MainWindow :: ~MainWindow()
{
}


applicationwindow.cpp
----------------------



#include "applicationwindow.h"

#include <QtWidgets/qwidget.h>

ApplicationWindow::ApplicationWindow(QWidget *parent) :
QWidget(parent)
{

}
ApplicationWindow::ApplicationWindow(int min_width,int min_height,int max_width,int max_height,QWidget* parent)
:min_width(min_width),min_height(min_height),max_w idth(max_width),max_height(max_height),QWidget(par ent)
{

}

ApplicationWindow::~ApplicationWindow()
{

}

QWidget* ApplicationWindow::createApplicationWindow()
{
window = new QWidget;
window->setSizePolicy(QSizePolicy::Expanding,QSizePolicy:: Expanding);
window->setMouseTracking(true);
window->setMinimumSize(min_width,min_height);
window->setMaximumSize(max_width,max_height);
return window;
}


mainwindow.h
---------------


#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include<QtWidgets/QMainWindow>
#include <QtWidgets/QDialog>
#include <QtGui>
#include <QtWidgets/qwidget.h>
#include <QProcess>
#include <QString>

#include "applicationwindow.h"

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
MainWindow(QWidget *parent = 0);
~MainWindow();
void embed_window(int id);
QProcess *process;
private:

QProcess* ApplicationProcess;
int max_width;
int max_height;
int min_width;
int min_height;

QMenu *fileMenu;
QWidget* mainwindow;

ApplicationWindow* appwindow;
QHBoxLayout* mainLayout;
QVBoxLayout* vLayout;
QWidget* vWidget;
QWidget* display;
QAction* HelloTestAct;
QWidget* window;

private:
void createActions();
void createMenus();
void getDisplayProperties(int* width,int* height);
void setWindowMinimumSizes(int min_width,int min_height);
void setWindowMaximumSizes(int min_width,int max_width);
public slots:
void Launch_Hello_Test();
void finish(int,QProcess::ExitStatus);
void launch_app(int id);
void readStandardOutput();
void readStandardError();
signals:
void send_winid(int id);
};

#endif // MAINWINDOW_H



applicationwindow.h
-------------------



#ifndef APPLICATIONWINDOW_H
#define APPLICATIONWINDOW_H
#include <QtWidgets/QtWidgets>

class ApplicationWindow : public QWidget
{
Q_OBJECT
public:
explicit ApplicationWindow(QWidget *parent = 0);
explicit ApplicationWindow(int min_width,int min_height,int max_width,int max_height,QWidget* parent=0);
QWidget * createApplicationWindow();
public:
virtual ~ApplicationWindow();
private:
int max_width;
int max_height;
int min_width;
int min_height;
QWidget* window;
signals:

public slots:

};

#endif
// APPLICATIONWINDOW_H

PstdEr
21st June 2013, 11:06
Hi anda_skoa,

When i run this application some times the window is embedding into the container some time not.
and also some times getting error:


QXcbConnection: XCB error: 8 (BadMatch), sequence: 429, resource id: 134217734, major code: 1 (CreateWindow), minor code: 0
QXcbConnection: XCB error: 3 (BadWindow), sequence: 432, resource id: 117440551, major code: 18 (ChangeProperty), minor code: 0


I obersved the log the message , receive print is coming before send print, does it cause any problem.

anda_skoa
21st June 2013, 16:45
One thing you can try is to write the window Id once the window has actually shown up, e.g. as a one-time reaction to the first ShowEvent.

I am unsure whether the cross-thread signal/slot handling works with a pure native thread, so you could check if enforcing a Qt::QueuedConnection helps (5th argument to connect) or using a QThread for the secondary thread.

While I currently don't have a Qt5.1 build around, if anyone else would want to test it they would need a buildable project, something they can run qmake and make on or open in QtCreator, e.g. attached as a ZIP

Cheers,
_