/**
@page customapps_root Building custom applications
The @b HippoDraw C++ library can be used for creating custom applications
with either C++ or Python. In both cases the
Qt
library, version 3.1 or
later, is needed. For building with Python,
PyQt
is needed as well. Versions 3.5 and 3.6 of PyQt have been used in the
past. This release was tested with version 3.14.1.
For both C++ and Python, one can build a custom application using
the CanvasWindow and Inspector, or displaying a data representation
with the @b HippoDraw widget, QtViewWidget or both in the same
application. Displaying the %Inspector is
optional in both cases.
@ref customapps_cplusplus and @ref python_appli give some examples of
usage.
If your custom application uses Doxygen for its documentation, you
can use
the hippodraw tag file and an entry in your Doxygen configuration
file such as
@verbatim
TAGFILES = hippodraw.tag=http://www.slac.stanford.edu/grp/ek/hippodraw/
@endverbatim
to link your documentation to @b HippoDraw's
See the @ref customapps_examples page.
*/
/**
@page customapps_examples Examples of custom applications with HippoDraw
This page contains examples of using the HippoDraw class library in
other applications.
@section customapps_opensci Open Scientist
The Open Scientist
application combines 3D high energy physics event display with OpenGL
and @b HippoDraw. A screen dump is shown below.
@image html onX.jpg Open Scientist application
@image latex onX.eps "Open Scientist application" width=\textwidth
It is shown running on Mac OS X. The application is written in C++ by
.
@section customapps_iguana Iguana
Iguana is a plotting and single event display package for the CMS LHC
experiment at CERN. Below shows a HippoDraw QtViewWidget alongside
other widgets
@image html iguana.jpg Iguana with HippoDraw
@image latex iguana.eps "Iguana with HippoDraw" width=\textwidth
More detaits can be found in a
presentation of the project made by the author, Giulio Eulisse
to the collaboration in April 2005.
*/
/**
@page customapps_cplusplus Building custom applications with C++
One can build custom applications with @b HippoDraw's C++ class library
along with Qt.
@section customapps_canvas Custom application with canvas
To build an application with the CanvasWindow and
Inspector, it can be as simple as the one shown below...
@code
#include "QtApp.h"
int main ( int argc, char** argv)
{
QtApp app ( argc, argv );
app.setFirstWindow();
return app.exec();
}
@endcode
Your custom code, say to generate the @ref ntuple_root data should be inserted
before the call to @c app.exec() as that function starts the Qt event
loop and doesn't return until the application is terminated.
If you already have a Qt application, then you can add the @b @b
HippoDraw %CanvasWindow and @b %Inspector to your application by adding
code to your main with something like the implementation of
QtApp::setFirstWindow does. The result might look like this ...
@code
#include "qt/CanvasWindow.h"
#include "qapplication.h"
int main ( int argc, char** argv)
{
MyApp app ( argc, argv );
CanvasWindow * window = new CanvasWindow ();
window->show();
return app.exec();
}
@endcode
One doesn't need to create the CanvasWindow before starting the Qt
event loop. It can be created at any time.
@section customapps_widget Custom application with widget in window
This section describes how to put a @b HippoDraw plot in a single window.
First the %QApplication object is created and the NTupleController is used
to create an NTuple by reading a file as shown here.
@code
int main ( int argc, char **argv )
{
QApplication app ( argc, argv );
const string filename ( "../../../hippodraw/examples/aptuple.tnt" );
NTupleController * nt_controller = NTupleController::instance ();
NTuple * nt
= nt_controller->createNTuple ( filename );
@endcode
In a custom application, you will probably have other ways of creating
the %NTuple. If you want the %NTuple visible to the %Inspector, then
you must register it with the %NTupleController like this ...
@code
NTuple * nt = // create your NTuple somehow
NTupleController * nt_controller = NTupleController::instance ();
nt_controller->registerNTuple ( nt );
@endcode
Next a display is created bound to the %NTuple and one of its columns.
@code
const string histo ( "Histogram" );
vector < string > bindings;
bindings.push_back ( "Cost" );
DisplayController * dc_controller = DisplayController::instance ();
PlotterBase * plotter
= dc_controller->createDisplay ( histo, *nt, bindings );
@endcode
Note that DisplayController creates the appropriate class derived from
PlotterBase for the kind of display you requested.
Plotter objects are used both for canvas items and widgets. In this
case, a QtViewWidget is created and the plotter is attached to it.
@code
QtViewWidget * view = new QtViewWidget ( );
view->setPlotter ( plotter );
@endcode
Finally, the view it set into the Qt main window, resized, captioned,
and the event loop started.
@code
view->resize ( 200, 200 );
app.setMainWidget( view );
view->setCaption ( "Qt HippoDraw - View widget" );
view->show();
int result = a.exec();
@endcode
Note that the above code used methods that %QtViewWidget inherits from
Qt's QWidget class.
Don't forget to clean up when you are done.
@code
delete view;
delete nt;
return result;
}
@endcode
The resulting application window looks like this ...
@image html widget_window.png QtViewWidget set as application's main window.
@image latex widget_window.eps QtViewWidget set as application's main window.
The complete code is shown below ...
@includelineno qt/examples/testwidget.cc
@section customapps_window Custom application with custom widget in Qt Designer
One can use @b HippoDraw's QtViewWidget as a custom widget within Qt
Designer. When doing so, your main program may look like this
@code
#include
#include "QtViewWidgetWindow.h"
int main( int argc, char ** argv )
{
QApplication app ( argc, argv );
QtViewWidgetWindow w;
w.show();
app.connect( &a, SIGNAL( lastWindowClosed() ), &a, SLOT( quit() ) );
return app.exec();
}
@endcode
In this example, the class QtViewWidgetWindow was built with Qt
Designer. It was created by asking for a new main window.
QtViewWidget was inserted in Qt Designer as a custom widget. The
results look like this ...
@image html custom_widget_designer.png QtViewWidget as custom widget
@image latex custom_widget_designer.eps QtViewWidget as custom widget
In this example, the fileOpen() slot as implemented like the
implementation in the @ref customapps_canvas example. But in
addition, the implementation creates an Inspector and signals it to
update itself with the created plotter. The code look like this ...
@code
m_inspector = new Inspector ();
m_inspector->show();
QCustomEvent * event = new QCustomEvent ( QEvent::User, plotter );
QApplication::postEvent ( m_inspector, event );
@endcode
One might have expected a direct call to Inspector::update following
the Observer pattern instead of this implementation. However, it was
found that under the Windows operating system, such a direct call
caused problems with the OS's threading model. So the QCustomEvent is
used to avoid the problem.
Some part of the application may cause a change to the plotter.
When that happens, one needs to update the %Inspector. Following the
%Observer pattern, when something in the plotter changes, it sends an
update message to its observer which is the %QtViewWidget. It in
turn, needs to send a message to its parent which is the
%QtViewWidgetWindow object. It uses a QCustomEvent to do this, so the
implementation of the %QtViewWidgetWindow must implement it something
like this ...
@code
void QtViewWidgetWindow::customEvent ( QCustomEvent * event )
{
void * data = event->data();
QCustomEvent * e = new QCustomEvent ( QEvent::User, data );
QApplication::postEvent ( m_inspector, e );
}
@endcode
After opening the file, the window looks like this ...
@image html custom_window.png QtViewWidgetWindow after opening file
@image latex custom_window.eps QtViewWidgetWindow after opening file
The complete source code is show below ...
@includelineno qt/examples/QtViewWidgetWindow.ui.h
*/