==========================
HOOPS/QT Integration Guide
==========================

Introduction
============

The following section explains how to build an application with the Qt GUI toolkit and the HOOPS 3D Application Framework. Compiling and linking is first reviewed, followed by a discussion of object relationships in the various components, and then an outline of programming steps needed to correctly create and initialize the objects and launch the Qt event loop.

Developers should start by compiling, linking and running the basic *qt_simple* application as the starting point for their application. It's readable source code is located in the *<hoops>/demo/qt/qt_simple* directory of your HOOPS/3dAF installation while a Qt v4 variant is located in the *<hoops>/demo/qt/qt_simple* directory. Some familiarity with the Qt toolkit, HOOPS/3dGS and HOOPS/MVO is assumed. 


Compiling and Linking
=====================

The Qt toolkit's signals and slots mechanism requires that a pre-compilation step that builds special source files. The Qt Meta-Object Compiler (MOC), supplied as part of the Qt toolkit, must be used prior to the compilation step. Please refer to the Qt documentation for more information.


Compiler Definitions
--------------------

The following definitions must be in place when compiling the HOOPS/Qt and HOOPS/MVO source code together:


General Definition
------------------

``IS_QT // All HOOPS/Qt application``


Window System Specific
----------------------

``IS_WIN // Applications built with HOOPS/Qt for MS Windows``
``IS_X11 // Applications built with HOOPS/Qt for UNIX``


Using OpenGL on UNIX
--------------------

``USE_GLX_VISUAL // Applications built with HOOPS/Qt for UNIX that will use OpenGL; i.e., also IS_X11``


Linking
-------

The HOOPS/Qt Widget is supplied in clear source and should be added directly to the application's source code base. Consequently there is no special HOOPS/Qt library to be linked in with the project.
 

Component Object Relationships
==============================

This section discusses the relationships between the objects in the various Qt and HOOPS/3dAF components. Building an application with both these toolkits minimally involves using the following objects from each component.  


Qt
--

Only one ``QApplication`` and at least ``QMainWindow`` (or derived class) 


HOOPS/Qt
--------

At least one ``HQWidget`` (you would typically create a custom widget derived from ``HQWidget``)


HOOPS/MVO
---------

``HBaseModel``, ``HBaseView``, an ``Operator`` class derived from ``HBaseOperator``. Applications that want to implement selection of geometry will also need a ``HSelectionSet`` object. These objects are all connected by private data members which store pointers to other objects in the following manner: 

.. image:: images/h_3daf_detailed_qt.gif


Steps to Building an Application with Qt and HOOPS
==================================================

Programming with an object oriented GUI framework like Qt involves creating a set of objects, defining the ways in which they are connected, the manner in which they send and receive messages, and then launching the framework's event loop. Building an application using Qt and the HOOPS/3dAF specifically requires the following steps in this order:

* Creation and initialization of:

	* :ref:`Qt objects <prog_guide/misc/qt_integration:Creation and initialization of Qt objects>`
	* :ref:`HOOPS/Qt objects <prog_guide/misc/qt_integration:Creation and Initialization of Qt objects>`
	* :ref:`HOOPS/MVO objects <prog_guide/misc/qt_integration:Creation and initialization of HOOPS/MVO objects>`

* :ref:`Launching the Qt event processing loop <prog_guide/misc/qt_integration:Launching the Qt event loop>`


Creation and Initialization of Qt Objects
=========================================

``QApplication``
----------------

For any GUI application that uses Qt, there is precisely one ``QApplication`` object no matter how many windows the application has. It can be accessed via the global variable ``a``, declared in *QApplication.h*, which must be initialized prior to the creation of any other Qt objects. The *qt_simple* example performs this in the function ``main()``::

	int main( int argc, char **argv ) 
	{  
		...

		// Create the one QApplication object 
		QApplication * a = new QApplication(argc,argv); 

		...
	}


Color Allocation and GUI Style
------------------------------

The ``QApplication`` object's attributes for color allocation and GUI sytle must be configured. For Qt/HOOPS applications the color allocation must be set to "ManyColor". The GUI Style is used to choose between Motif or Windows styles for the visual appearance and default behavior of the Qt GUI created. 


Creation and Initialization of HOOPS/Qt Objects
===============================================

``HQApplication``
-----------------

One ``HQApplication`` object should be created using the constructor that accepts a pointer to a Qt ``QApplication`` object. The *qt_simple* exampleperforms this in the function ``main()``::

	int main( int argc, char **argv ) 
	{  
		...
		
		if(argc == 2)
			HQApplication * ha = new HQApplication(a, argv[1]);
		else
			HQApplication * ha = new HQApplication(a);
			
		...
	}

The ``HQApplication`` object should create any Qt GUI object's to be parented off of it during its initialization. The *qt_simple* example performs this when a ``HQApplication`` object is being initialized by calling its private method ``HQApplication::load()``.


``HQWidget``
------------

As many ``HQWidget`` objects can be created as needed to implement the GUI's design. These are more than likely going to be created by a constructor of a top level Qt widget like ``QMainWindow`` or ``QDialog``. The *qt_simple* example performs this when an ``HQApplication`` object is initialized by calling its private method ``HQApplication::load()``::

	void HQApplication::load(const char * filename)
	{
		...

		SimpleHQWidget * my_widget = new SimpleHQWidget(qframe, "SimpleHQWidget", filename);
							
		...
	}


``HQDeleter``
-------------

One global pointer must be declared and initialized in the application code block. The *qt_simple* example performs the global declaration in the file *main.cpp* and the initialization in the body of the function ``main()``:: 

	// Create a global pointer to HOOPS/Qt class HQDeleter 
	HQDeleter * deleter=0; 

	int main( int argc, char **argv ) 
	{  
		...
		
		// Create an HQDeleter object and initialize the global pointer 
		deleter = new HQDeleter();
		
		...
	}


Creation and Initialization of HOOPS/MVO Objects
================================================

HDB
---

One global pointer to a HOOPS/MVO HDB object should be declared and initialized in the application's ``main`` function. The *qt_simple* example example::

	int main( int argc, char **argv ) 
	{  
		m_pHDB = new HDB(); 
		m_pHDB->Init();

		...
	}


``HBaseModel``
--------------

Multiple ``HBaseModel`` objects can be created as needed. The *qt_simple* example creates one for every ``SimpleHQWidget`` object (i.e., there is a one-to-one mapping of HBaseModel to SimpleHQWidget objects) and does so in the ``SimpleHQWidget`` constructor::

	SimpleHQWidget::SimpleHQWidget(QWidget* parent, const char* name, const char * filename) 
		: HQWidget( parent, name ) 
	{ 
		m_pHBaseModel = new HBaseModel(); 
		m_pHBaseModel->Init(); 
		
		...
	} 


``HBaseView``
-------------

Multiple ``HBaseView`` objects can be created as needed, with one object usually being created for each ``HQWidget``. The ``HBaseView`` needs a valid window id and color map passed to its constructor on object creation; information used to connect a HOOPS/3dGS output driver instance to a Qt ``QWidget``. This requires that the ``QtWidget``, to which the ``HBaseView`` will be attached, must already exist prior to creating the ``HBaseView`` object. 

The ``HBaseView`` object should be created and initialized in an overloaded ``HQWidget::Init`` method. This method is called by the base class HQWidget in its ``HQWidget::paintEvent`` method the first time it is called, which first ensures that the widget is alive and thus the window ID is valid and the ``HBaseView`` object can be created. Here is the *qt_simple* example::

	void SimpleHQWidget::Init() 
	{ 
		m_pHView = new HBaseView(m_pHBaseModel, NULL, NULL, NULL, GetWindowId(), GetColorMap(), GetClipOverride()); 
		m_pHView->Init(); 

		...
	}


``HBaseOperator``
-----------------

The ``HBaseView`` class has a member ``HBaseView::m_pOperator`` that is a pointer to an ``HBaseOperator`` object. A default operator should be created during view initialization. The *qt_simple* example does this in the overloaded method of ``HQWidget::Init``::

	void SimpleHQWidget::Init() 
	{ 
		...

		m_pHView->SetCurrentOperator(new HOpCameraOrbit(m_pHView)); 

		...
	}


``HSelectionSet``
-----------------

Multiple ``HSelectionSet`` object can be created as needed, but usually there is a one-to-one mapping of ``HSelectionSet`` to ``HBaseView`` objects.

The *qt_simple* example does not create a ``HSelectionSet`` object because it does not provide any support for selection at this time.


Launching the Qt Event Loop
===========================

This is performed by calling the ``QApplication::exec()`` method. Refer to the ``main()`` function of the *qt_simple* example.
