multiple openGL irrlichtDevice

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
QtGraphDev
Posts: 46
Joined: Mon Jun 12, 2006 9:42 am

multiple openGL irrlichtDevice

Post by QtGraphDev »

Trying to make an app with several irrlicht 1.1 windows.
It worked well with the D3D driver, but with the openGL driver the second window is empty en show the desktop.
kornerr
Posts: 245
Joined: Thu Jul 06, 2006 9:57 am
Location: Russia, Siberia, Kemerovo
Contact:

Post by kornerr »

Any code?
And are you sure the second window shows desktop? May be it simply doesn't get updated?
Open Source all the way, baby ;)
OSRPG
QtGraphDev
Posts: 46
Joined: Mon Jun 12, 2006 9:42 am

Post by QtGraphDev »

the project is a little much big to be able to send source.
But i'm sure the code update very well the screen because when i use the irr::video::EDT_DIRECT3D9 every thing works just fine, but with irr::video::EDT_OPENGL the second window stay empty.
So irrlicht should support several irrlichtDevices ?
QtGraphDev
Posts: 46
Joined: Mon Jun 12, 2006 9:42 am

Post by QtGraphDev »

here a sample project that reproduce the problem. it's could be compiled with QT 4.1.

QIrrlichtWidget.h

Code: Select all

#ifndef QIRRLICHTWIDGET_H
#define QIRRLICHTWIDGET_H

#include <qwidget.h>
#include <irrlicht.h>
#include <qfont.h>

class QPaintEvent;

class QIrrlichtWidget : public QWidget
{
    Q_OBJECT

public:    
    irr::IrrlichtDevice* getIrrlichtDevice();
    
    void setDriverType( irr::video::E_DRIVER_TYPE driver );
    
    QIrrlichtWidget( QWidget *parent=0 );
    ~QIrrlichtWidget();
    
    void init();
    
public slots:
    void autoUpdateIrrlicht( irr::IrrlichtDevice* device );
    
signals:
    void updateIrrlicht( irr::IrrlichtDevice* device );
    
protected:
    irr::video::E_DRIVER_TYPE driverType;
    
    virtual void paintEvent( QPaintEvent* event );
    
    void sendKeyEventToIrrlicht( QKeyEvent* event, bool pressedDown );
    virtual void keyPressEvent( QKeyEvent* event );
    virtual void keyReleaseEvent( QKeyEvent* event );
    
    void sendMouseEventToIrrlicht( QMouseEvent* event, bool pressedDown );
    virtual void mousePressEvent( QMouseEvent* event );
    virtual void mouseReleaseEvent( QMouseEvent* event );
    virtual void wheelEvent( QWheelEvent* event );
    
    virtual void timerEvent( QTimerEvent* event );
    
    virtual void resizeEvent( QResizeEvent* event );
    
    
private:
    irr::IrrlichtDevice* device;
};

#endif // QIRRLICHTWIDGET_H
qirrlichtwidget.cpp

Code: Select all

#include "qirrlichtwidget.h"
#include <irrlicht.h>
#include <line2d.h>
#include <qpalette.h>
#include <QKeyEvent>
#include <QMouseEvent>
#include <qpainter.h>

using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;

QIrrlichtWidget::QIrrlichtWidget( QWidget *parent )
    : QWidget(parent)
{
    // Wait for the init() call
    device = 0;
    
    // Default to Open GL
	driverType = irr::video::EDT_OPENGL;
}

QIrrlichtWidget::~QIrrlichtWidget()
{
    if ( device != 0 )
    {
        device->closeDevice();
        device->run();
        device->drop();
    }
}

void QIrrlichtWidget::init()
{
    // Don't initialize more than once!
    if ( device != 0 ) return;
    
    irr::SIrrlichtCreationParameters params;
    
    params.DriverType = driverType;
    params.WindowId = (irr::s32)winId();
    params.WindowSize.Width = width();
    params.WindowSize.Height = height();
    
    device = irr::createDeviceEx( params );
    
    // Irrlicht will clear the canvas for us, so tell Qt not to do it
    setAttribute( Qt::WA_OpaquePaintEvent );
    
    connect( this, SIGNAL(updateIrrlicht(irr::IrrlichtDevice*)),
             this, SLOT(autoUpdateIrrlicht(irr::IrrlichtDevice*)) );
    startTimer(0);
}


irr::IrrlichtDevice* QIrrlichtWidget::getIrrlichtDevice()
{
    return device;
}

void QIrrlichtWidget::paintEvent( QPaintEvent* event )
{
    if ( device != 0 )
    {
        emit updateIrrlicht( device );
		
    }
	
}

void QIrrlichtWidget::timerEvent( QTimerEvent* event )
{
    if ( device != 0 )
    {
        emit updateIrrlicht( device );
    }
    event->accept();
		
}


void QIrrlichtWidget::resizeEvent( QResizeEvent* event )
{
    if ( device != 0 )
    {
        irr::core::dimension2d<int> size;
        size.Width = event->size().width();
        size.Height = event->size().height();
        device->getVideoDriver()->OnResize( size );
        
        irr::scene::ICameraSceneNode *cam = device->getSceneManager()->getActiveCamera();
        if ( cam != 0 )
        {
            cam->setAspectRatio( size.Height / size.Width );
        }
    }
    QWidget::resizeEvent(event);
}

void QIrrlichtWidget::autoUpdateIrrlicht( irr::IrrlichtDevice* device )
{
    device->getTimer()->tick();
    
    irr::video::SColor color (0,0,0,0);
    
    device->getVideoDriver()->beginScene( true, true, color );
    
    device->getSceneManager()->drawAll();
    device->getGUIEnvironment()->drawAll();
    
    device->getVideoDriver()->endScene();
}

struct SIrrlichtKey
{
    irr::EKEY_CODE code;
    wchar_t ch;
};

SIrrlichtKey convertToIrrlichtKey( int key )
{
    SIrrlichtKey irrKey;
    irrKey.code = (irr::EKEY_CODE)(0);
    irrKey.ch = (wchar_t)(0);
    
    // Letters A..Z and numbers 0..9 are mapped directly
    if ( (key >= Qt::Key_A && key <= Qt::Key_Z) || (key >= Qt::Key_0 && key <= Qt::Key_9) )
    {
        irrKey.code = (irr::EKEY_CODE)( key );
        irrKey.ch = (wchar_t)( key );
    }
    else
    
    // Dang, map keys individually
    switch( key )
    {
    case Qt::Key_Up:
        irrKey.code = irr::KEY_UP;
        break;
        
    case Qt::Key_Down:
        irrKey.code = irr::KEY_DOWN;
        break;
        
    case Qt::Key_Left:
        irrKey.code = irr::KEY_LEFT;
        break;
        
    case Qt::Key_Right:
        irrKey.code = irr::KEY_RIGHT;
        break;
    }
    return irrKey;
}

void QIrrlichtWidget::sendKeyEventToIrrlicht( QKeyEvent* event, bool pressedDown )
{
    irr::SEvent irrEvent;
    
    irrEvent.EventType = irr::EET_KEY_INPUT_EVENT;
    
    SIrrlichtKey irrKey = convertToIrrlichtKey( event->key() );
    
    if ( irrKey.code == 0 ) return; // Could not find a match for this key
    
    irrEvent.KeyInput.Key = irrKey.code;
    irrEvent.KeyInput.Control = ((event->modifiers() & Qt::ControlModifier) != 0);
    irrEvent.KeyInput.Shift = ((event->modifiers() & Qt::ShiftModifier) != 0);
    irrEvent.KeyInput.Char = irrKey.ch;
    irrEvent.KeyInput.PressedDown = pressedDown;
    
    device->postEventFromUser( irrEvent );
}

void QIrrlichtWidget::keyPressEvent( QKeyEvent* event )
{
    if ( device != 0 )
    {
        sendKeyEventToIrrlicht( event, true );
    }
    event->ignore();
}

void QIrrlichtWidget::keyReleaseEvent( QKeyEvent* event )
{
    if ( device != 0 )
    {
        sendKeyEventToIrrlicht( event, false );
    }
    event->ignore();
}

void QIrrlichtWidget::sendMouseEventToIrrlicht( QMouseEvent* event, bool pressedDown )
{
    irr::SEvent irrEvent;
    
    irrEvent.EventType = irr::EET_MOUSE_INPUT_EVENT;
    
    switch ( event->button() )
    {
    case Qt::LeftButton:
        irrEvent.MouseInput.Event = pressedDown? irr::EMIE_LMOUSE_PRESSED_DOWN:irr::EMIE_LMOUSE_LEFT_UP;
        break;
    
    case Qt::MidButton:
        irrEvent.MouseInput.Event = pressedDown? irr::EMIE_MMOUSE_PRESSED_DOWN:irr::EMIE_MMOUSE_LEFT_UP;
        break;
    
    case Qt::RightButton:
        irrEvent.MouseInput.Event = pressedDown? irr::EMIE_RMOUSE_PRESSED_DOWN:irr::EMIE_RMOUSE_LEFT_UP;
        break;
    
    default:
        return; // Cannot handle this mouse event
    }
    
    irrEvent.MouseInput.X = event->x();
    irrEvent.MouseInput.Y = event->y();
    irrEvent.MouseInput.Wheel = 0.0f; // Zero is better than undefined
    
    device->postEventFromUser( irrEvent );
}

void QIrrlichtWidget::mousePressEvent( QMouseEvent* event )
{
    if ( device != 0 )
    {
        sendMouseEventToIrrlicht( event, true );
    }
    event->ignore();
}

void QIrrlichtWidget::mouseReleaseEvent( QMouseEvent* event )
{
    if ( device != 0 )
    {
        sendMouseEventToIrrlicht( event, false );
    }
    event->ignore();
}

void QIrrlichtWidget::wheelEvent( QWheelEvent* event )
{
    if ( device != 0 && event->orientation() == Qt::Vertical )
    {
        irr::SEvent irrEvent;
        
        irrEvent.EventType = irr::EET_MOUSE_INPUT_EVENT;
        
        irrEvent.MouseInput.Event = irr::EMIE_MOUSE_WHEEL;
        irrEvent.MouseInput.X = 0; // We don't know these,
        irrEvent.MouseInput.Y = 0; // but better zero them instead of letting them be undefined
        irrEvent.MouseInput.Wheel = event->delta() / 120.0f;
        
        device->postEventFromUser( irrEvent );
    }
    event->ignore();
}

main.cpp

Code: Select all

#include <qstring.h>
#include <qapplication.h>
#include <qpushbutton.h>
#include <QVBoxLayout>

#include "qirrlichtwidget.h"

#include <irrlicht.h>

using namespace irr;

void setupIrrlicht( IrrlichtDevice* device )
{    
    // Get the scene manager
    scene::ISceneManager* manager = device->getSceneManager();
    
    // Create a small box
    scene::ISceneNode* node = manager->addTestSceneNode();
    node->setMaterialFlag( video::EMF_LIGHTING, false );
    
    // Create a camera to view the box
    scene::ICameraSceneNode* cam = manager->addCameraSceneNode();
    
    cam->setPosition( core::vector3df(100,100,0) );
    cam->setTarget( core::vector3df(0,0,0) );
    
    scene::ISceneNodeAnimator* anim = manager->createFlyCircleAnimator( core::vector3df(0,0,0), 20 );
    node->addAnimator(anim);
    anim->drop();
}

int main(int argc, char **argv)
{    
    QApplication    app(argc, argv);
    
    QWidget         window;
	QWidget         window1;
    
    QVBoxLayout     layout;
	
    
    QPushButton     quit("Quit");
    QObject::connect( &quit, SIGNAL(clicked()), &app, SLOT(quit()) );
    
    QIrrlichtWidget irrWidget;
	QIrrlichtWidget irrWidget1;
    
    layout.addWidget(&quit);
    layout.addWidget(&irrWidget);
    layout.addWidget(&irrWidget1);
    
    window.setLayout(&layout);
    window.resize(400,400);
    
    window.show();
    
    irrWidget.init();
	irrWidget1.init();
    
    setupIrrlicht( irrWidget.getIrrlichtDevice() );
	setupIrrlicht( irrWidget1.getIrrlichtDevice() );
    
    return app.exec();
}
if we use irr::video::EDT_DIRECT3D9 than irr::video::EDT_OPENGL as driver type, irrWidget and irrWidget1 will work and show without any problem.
QtGraphDev
Posts: 46
Joined: Mon Jun 12, 2006 9:42 am

Post by QtGraphDev »

it seems then to be an openGL driver bug :(
i hope it will be fixed soon
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

It might be the difference between device, window and render context in OpenGL. But I never tried such a thing myself.
chriswit
Posts: 2
Joined: Sat Aug 26, 2006 7:58 pm

Following doues not work, too

Post by chriswit »

The folowing code, extends the example from the example directory.
With D3D it works correctly, but not with opengl.

PS mixed opengl with D3d is also possible


WHY ?????


// this example only runs in windows and demonstrates that Irrlicht
// can run inside a win32 window.

#include <irrlicht.h>
#include <windows.h> // this example only runs with windows

using namespace irr;

#pragma comment(lib, "irrlicht.lib")

HWND hOKButton;
HWND hWnd;

static LRESULT CALLBACK CustomWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
HWND hwndCtl = (HWND)lParam;
int code = HIWORD(wParam);

if (hwndCtl == hOKButton)
{
DestroyWindow(hWnd);
PostQuitMessage(0);
return 0;
}
}
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;

}

return DefWindowProc(hWnd, message, wParam, lParam);
}





int main()
//int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hpre, LPSTR cmd, int cc)
{
HINSTANCE hInstance = 0;
// create dialog

const char* Win32ClassName = "CIrrlichtWindowsTestDialog";

WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)CustomWndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = DLGWINDOWEXTRA;
wcex.hInstance = hInstance;
wcex.hIcon = NULL;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW);
wcex.lpszMenuName = 0;
wcex.lpszClassName = Win32ClassName;
wcex.hIconSm = 0;

RegisterClassEx(&wcex);

DWORD style = WS_SYSMENU | WS_BORDER | WS_CAPTION |
WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SIZEBOX;

int windowWidth = 440;
int windowHeight = 380;

hWnd = CreateWindow( Win32ClassName, "Irrlicht Win32 window example",
style, 100, 100, windowWidth, windowHeight,
NULL, NULL, hInstance, NULL);

RECT clientRect;
GetClientRect(hWnd, &clientRect);
windowWidth = clientRect.right;
windowHeight = clientRect.bottom;

// create ok button

hOKButton = CreateWindow("BUTTON", "OK - Close", WS_CHILD | WS_VISIBLE | BS_TEXT,
windowWidth - 160, windowHeight - 40, 150, 30, hWnd, NULL, hInstance, NULL);

// create some text

CreateWindow("STATIC", "This is Irrlicht running inside a standard Win32 window.\n"\
"Also mixing with MFC and .NET Windows.Forms is possible.",
WS_CHILD | WS_VISIBLE, 20, 20, 400, 40, hWnd, NULL, hInstance, NULL);

// create window to put irrlicht in

HWND hIrrlichtWindow = CreateWindow("BUTTON", "", WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,
50, 80, 450, 430, hWnd, NULL, hInstance, NULL);

HWND hIrrlichtWindow2 = CreateWindow("BUTTON", "", WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,
510, 80, 450, 430, hWnd, NULL, hInstance, NULL);

// create irrlicht device in the button window

irr::SIrrlichtCreationParameters param;
param.WindowId = reinterpret_cast<s32>(hIrrlichtWindow); // hColorButton
param.DriverType = video::EDT_OPENGL;//EDT_DIRECT3D9;//EDT_OPENGL;

irr::SIrrlichtCreationParameters param2;
param2.WindowId = reinterpret_cast<s32>(hIrrlichtWindow2); // hColorButton
param2.DriverType = video::EDT_OPENGL;//EDT_DIRECT3D9;//EDT_OPENGL;

irr::IrrlichtDevice* device = irr::createDeviceEx(param);
irr::IrrlichtDevice* device2 = irr::createDeviceEx(param2);

// setup a simple 3d scene

irr::scene::ISceneManager* smgr = device->getSceneManager();
video::IVideoDriver* driver = device->getVideoDriver();

scene::ICameraSceneNode* cam = smgr->addCameraSceneNode();
cam->setTarget(core::vector3df(0,0,0));

scene::ISceneNodeAnimator* anim = smgr->createFlyCircleAnimator(core::vector3df(0,15,0), 30.0f);
cam->addAnimator(anim);
anim->drop();

scene::ISceneNode* cube = smgr->addCubeSceneNode(20);

cube->setMaterialTexture(0, driver->getTexture("../../media/wall.bmp"));
cube->setMaterialTexture(1, driver->getTexture("../../media/water.jpg"));
cube->setMaterialFlag( video::EMF_LIGHTING, false );
cube->setMaterialType( video::EMT_REFLECTION_2_LAYER );

smgr->addSkyBoxSceneNode(
driver->getTexture("../../media/irrlicht2_up.jpg"),
driver->getTexture("../../media/irrlicht2_dn.jpg"),
driver->getTexture("../../media/irrlicht2_lf.jpg"),
driver->getTexture("../../media/irrlicht2_rt.jpg"),
driver->getTexture("../../media/irrlicht2_ft.jpg"),
driver->getTexture("../../media/irrlicht2_bk.jpg"));


irr::scene::ISceneManager* smgr2 = device2->getSceneManager();
video::IVideoDriver* driver2 = device2->getVideoDriver();

scene::ICameraSceneNode* cam2 = smgr2->addCameraSceneNode();
cam2->setTarget(core::vector3df(0,0,0));

scene::ISceneNodeAnimator* anim2= smgr2->createFlyCircleAnimator(core::vector3df(0,15,0), 30.0f);
cam2->addAnimator(anim2);
anim2->drop();

scene::ISceneNode* cube2 = smgr2->addCubeSceneNode(20);

cube2->setMaterialTexture(0, driver2->getTexture("../../media/wall.bmp"));
cube2->setMaterialTexture(1, driver2->getTexture("../../media/water.jpg"));
cube2->setMaterialFlag( video::EMF_LIGHTING, false );
cube2->setMaterialType( video::EMT_REFLECTION_2_LAYER );

smgr2->addSkyBoxSceneNode(
driver2->getTexture("../../media/irrlicht2_up.jpg"),
driver2->getTexture("../../media/irrlicht2_dn.jpg"),
driver2->getTexture("../../media/irrlicht2_lf.jpg"),
driver2->getTexture("../../media/irrlicht2_rt.jpg"),
driver2->getTexture("../../media/irrlicht2_ft.jpg"),
driver2->getTexture("../../media/irrlicht2_bk.jpg"));

// show and execute dialog

ShowWindow(hWnd , SW_SHOW);
UpdateWindow(hWnd);

// do message queue

// Instead of this, you can also simply use your own message loop
// using GetMessage, DispatchMessage and whatever. Calling
// Device->run() will cause Irrlicht to dispatch messages internally too.
// You need not call Device->run() if you want to do your own message
// dispatching loop, but Irrlicht will not be able to fetch
// user input then and you have to do it on your own using the window
// messages, DirectInput, or whatever.

/* while (device->run())
{
driver->beginScene(true, true, 0);
smgr->drawAll();
driver->endScene();
}*/

// the alternative, own message dispatching loop without Device->run() would
// look like this:

MSG msg;
while (true)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);

if (msg.message == WM_QUIT)
break;
}

// advance virtual time
device2->getTimer()->tick();

// draw engine picture
driver2->beginScene(true, true, 0);
smgr2->drawAll();
driver2->endScene();


// advance virtual time
device->getTimer()->tick();

// draw engine picture
driver->beginScene(true, true, 0);
smgr->drawAll();
driver->endScene();
Sleep(20);
}

device->closeDevice();
device->drop();

return 0;
}
chriswit
Posts: 2
Joined: Sat Aug 26, 2006 7:58 pm

possible solution

Post by chriswit »

With irrlicht 1.1 it is not possibple to create multiple opengl-devices in the same thread. I solved this problem with creating seperate thread for each device.

ATTENTION: use Critical sections or something else to synchronise the threads, b.o. irrlicht is not realy threadsafe :)
mefisto
Posts: 1
Joined: Tue Dec 12, 2006 8:29 am
Location: Russia, Rostov-on-Don

Post by mefisto »

the problem consist in that OpenGL driver can render only in one context per thread. If you want to use several rendering contexts in one thread, you have to swith contexts by

Code: Select all

wglMakeCurent(...)
in

Code: Select all

beginScene(...)
member of COpenGLDriver, but not only in constructor of this class.
QuantumLeap
Posts: 38
Joined: Mon Sep 25, 2006 6:31 pm
Location: San Francisco, California

Post by QuantumLeap »

Did anyone manage to actually receive mouse and keyboard events within the Irrlicht widget created like this?

The redefinition of some virtual methods of QWidget is the standard way to implement it, as in the code above. But it doesn't seem to be working. Namely,

Code: Select all

virtual void keyPressEvent ( QKeyEvent * event )
virtual void keyReleaseEvent ( QKeyEvent * event )
virtual void mousePressEvent ( QMouseEvent * event )
virtual void mouseReleaseEvent ( QMouseEvent * event )
and
virtual void mouseMoveEvent ( QMouseEvent * event )
are never called when the QWidget in cause is an instance of Irrlicht. To test we can for example invoke a standard Qt::Beep() from within the redefinition of mousePressEvent. However if we comment

Code: Select all

params.WindowId = (void*)winId();
the events start being processed normally (but the Irrlicht frame is not displayed, despite being active and running because there's no handle).
Did anyone manage to solve this? Next I'll try to force the call of said methods with a set of slots/signals within the main application.
It's easier to curse a candle than light the darkness
Escen
Competition winner
Posts: 167
Joined: Sun Jul 19, 2009 11:27 am
Location: the Netherlands
Contact:

Post by Escen »

Hello Guys,

I pasted the above QIrrlichtWidget class into an empty codeblocks Qt4 project and added Irrlicht to this project.
When I want to compile I get the following error message.
undefined reference to `vtable for QIrrlichtWidget'|
Is there anyone so kind to explain what I'm missing here?
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

You are probably missing some implementations of the virtual function declarations. In that case the vtable is not complete and this message can result.
Escen
Competition winner
Posts: 167
Joined: Sun Jul 19, 2009 11:27 am
Location: the Netherlands
Contact:

Post by Escen »

Can you explain a little bit more?

Which implementations is missing.

The first appearing in above qirrlichtwidget.cpp is here:

Code: Select all

QIrrlichtWidget::QIrrlichtWidget( QWidget *parent )
    : QWidget(parent)
{
    // Wait for the init() call
    device = 0;

    // Default to Open GL
   driverType = irr::video::EDT_OPENGL;
}
Escen
Competition winner
Posts: 167
Joined: Sun Jul 19, 2009 11:27 am
Location: the Netherlands
Contact:

Post by Escen »

Aha... I forgot to use QtWorkbench custom Makefile for CodeBlocks, compiling fine now...
That's what happens when you getting older. 8)

Cheers
Virion
Competition winner
Posts: 2148
Joined: Mon Dec 18, 2006 5:04 am

Post by Virion »

Escen wrote:Aha... I forgot to use QtWorkbench custom Makefile for CodeBlocks, compiling fine now...
That's what happens when you getting older. 8)

Cheers
hi Escen. I got the same error what should I do? I've installed QtWorkbench plugin for C::B, what to do next?
Post Reply