PDA

View Full Version : ui_....h issue



stevey
15th November 2007, 13:27
Hi,

I've started a new Qt library project in Visual Studio 2005 and Qt 4.3.2.
I've create a new solution with a Qt library template, created a Qt Gui class and put the macro for exporting the class I want to expose to the win32 world. I'm getting a .lib with my dll and everything's cool in that respect.

I also created a tester gui application to test out my dll's ui controls.
The dll exports 'ProcessDesigner' which is defined in 'processdesigner.h'.
As soon as I #include this header in my tester application, I get the following error 3 times:


Error 1 fatal error C1083: Cannot open include file: 'ui_processdesigner.h': No such file or directory D:\SourceRepository\Imaging Tools\ImagingSystemTools\ProcessDesigner\processde signer.h 7


Given that the ui_ file is auto generated and linked into the dll, why is the gui application running a muck?

I've used this structure a few times, but it was a while ago now, so my memory on things might be lacking a little.

I've attached the solution for your examination.

Thanks

jacek
15th November 2007, 13:34
You have #include "ui_processdesigner.h" directive in processdesigner.h. Either you have to distribute that file too (which isn't a good idea) or you have to change your code in such way that would allow you to move that #include directive to a .cpp file. For example you can change ProcessDesigner::ui into a pointer and use forward declaration or use the pimpl pattern.

Edit: Since it's going to be a library, the pimpl is the best approach.

stevey
15th November 2007, 13:41
Actually thinking about this further, I've never linked to a dll that had a Qt UI subclass as it's entry point, so that's probably why I'm having this issue.
I could always use a static create function I guess.

Thanks for your suggestions Jacek, I'll do some experimenting.

stevey
26th November 2007, 13:19
Hi again,

I have to confess that I'm getting lost trying to do this.
I've followed the PIMPL exercise in Herb Sutter's book and come up with the VS solution I've attached to this post.

My goal is to create a subclass of QFrame which which will have a QGraphicsView among other controls. I need to be able to use this class from many applications, so a Qt Library is the way to go.
The way I see it, is that I need to use a PIMPL approach so as to hide the #include "ui_..." line so that the client of the library doesn't end up including a file not in it's search path so that it can compile.

So this is what I've done so far:


// processdesigner_impl.h
#include <QFrame>
#include "ui_processdesigner.h"


class ProcessDesignerImpl : public QFrame
{
Q_OBJECT

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

private:
Ui::ProcessDesignerClass ui;
};




// processdesigner_impl.cpp
#include "processdesigner_impl.h"


ProcessDesignerImpl::ProcessDesignerImpl(QWidget *parent)
: QFrame(parent)
{
ui.setupUi(this);
}

ProcessDesignerImpl::~ProcessDesignerImpl()
{

}





// ProcessDesigner.h
#include "processdesigner_global.h"
#include <QWidget>

class PROCESSDESIGNER_EXPORT ProcessDesigner : public QWidget
{
Q_OBJECT

public:
ProcessDesigner(QWidget* parent = 0);

private:
class ProcessDesignerImpl;
ProcessDesignerImpl* procDesImpl;


};





// ProcessDesigner.cpp

#include "ProcessDesigner.h"
#include "processdesigner_impl.h"

ProcessDesigner::ProcessDesigner()
{
//procDesImpl = new ProcessDesignerImpl(parent);
}




This was compiling at one point (or maybe a slight variation) but now I'm getting these errors:


Error 3 error LNK2001: unresolved external symbol "public: virtual int __thiscall ProcessDesignerImpl::qt_metacall(enum QMetaObject::Call,int,void * *)" (?qt_metacall@ProcessDesignerImpl@@UAEHW4Call@QMet aObject@@HPAPAX@Z) processdesigner_impl.obj
Error 1 error LNK2001: unresolved external symbol "public: virtual struct QMetaObject const * __thiscall ProcessDesignerImpl::metaObject(void)const " (?metaObject@ProcessDesignerImpl@@UBEPBUQMetaObjec t@@XZ) processdesigner_impl.obj
Error 2 error LNK2001: unresolved external symbol "public: virtual void * __thiscall ProcessDesignerImpl::qt_metacast(char const *)" (?qt_metacast@ProcessDesignerImpl@@UAEPAXPBD@Z) processdesigner_impl.obj
Error 4 fatal error LNK1120: 3 unresolved externals D:\SourceRepository\Imaging Tools\ImagingSystemTools\Debug\ProcessDesigner.dll



I'm not sure where to turn next.
Part of my confusion lies in the fact the ProcessDesigner needs to be able to be placed on another dialog, so I need to subclass it as well. If I just subclass QWidget, then I can see that I'll have to create a one-to-one mapping on every custom function I want to expose on the ProcessDesignerImpl, because if I subclass from ProcessDesignerImpl I'll be back where I started.

The real question is, how do I actually return a ProcessDesignerImpl to the client?
I was thinking about maybe casting "procDesImpl back to a basic QWidget then returning that somewhow, or maybe the key lies in the client passing "this" into the constructor of ProcessDesigner, then that pointer gets passed into ProcessDesignerImpl, then use in the setupUp line like this:


ui.setupUi(parent);


First I need to resolve these linking errors in the attached solution, then decide how to proceed. Can anyone offer any suggestions?


Regards,

Steve York

wysota
26th November 2007, 13:30
Wow... hmm... strange solution... how about:


#ifndef __FRAME_H
#define __FRAME_H
#include <QFrame>
class FramePrivate;
class Frame : public QFrame {
public:
Frame(QWidget *parent=0);
~Frame();
private:
FramePrivate *d;
};
#endif

#include "frame.h"
#include "ui_frame.h"
struct FramePrivate {
Ui::Frame ui;
};

Frame::Frame(QWidget *parent) : QFrame(parent), d(new FramePrivate){
d->ui.setupUi(this);
}

Frame::~Frame(){ delete d; }

This way the only place where you include the ui_xxx.h file is the implementation file and only the private class (P-IMPL) that is defined there needs the Ui component.

stevey
27th November 2007, 04:54
Ok, after extensive analysis, I believe I see the light now.
That's what I love (or hate) about C++, there's ALWAYS some new concept to learn :)
Just learning about forward declaration has been a good lesson. I've seen it before, but never been forced to implement it.
Much reading of sutter's book ahead.

Thanks heaps.