VisItViewer example program code listing

This page lists the entire source code for a simple visualization application, which is a Qt Main window that uses VisItViewer for graphics. This code is included in the VisIt source code in the src/tools/embedded directory.

SimpleVisApp.h

Declaration for the main class in the simple vis application.

#ifndef SIMPLE_VIS_APP_H
#define SIMPLE_VIS_APP_H
#include <QMainWindow>

class VisItViewer;
class CommandParser;

class QLabel;
class QListWidget;
class QButtonGroup;
class QSpinBox;
class QWidget;
class vtkQtRenderWindow;

class SimpleVisApp : public QMainWindow
{
    Q_OBJECT
public:
    SimpleVisApp(VisItViewer *);
    virtual ~SimpleVisApp();

public slots:
    virtual void show();
private slots:
    void selectFile();
    void openFile(const QString &);
    void changeVariable(const QString &);
    void changeVariableAndUpdate(const QString &);
    void changePlotType(int);
    void setNContours(int);
    void saveWindow();
    void openGUI();
    void execFile();
private:
    static vtkQtRenderWindow *ReturnVisWin(void *);
    void resetWindow();

    QLabel            *scalarLabel;
    QListWidget       *variables;
    QWidget           *plotTypeWidget;
    QButtonGroup      *plotType;
    QWidget           *contourWidget;
    QSpinBox          *nContours;
    vtkQtRenderWindow *viswin;
    VisItViewer       *viewer;

    CommandParser     *cmd;
};

#endif

SimpleVisApp.cpp

Implementation for the main class in the simple vis application.

#include <SimpleVisApp.h>
#include <VisItViewer.h>
#include <ViewerMethods.h>

#include <QButtonGroup>
#include <QDir>
#include <QFileDialog>
#include <QLabel>
#include <QLayout>
#include <QListWidget>
#include <QMenuBar>
#include <QMenu>
#include <QRadioButton>
#include <QSpinBox>
#include <QWidget>

// State objects that we use.
#include <avtDatabaseMetaData.h>
#include <SaveWindowAttributes.h>

// Include this last since something about it on X11 systems seems to
// interfere with some of our other enums. X11 headers must have some
// naughty #define directives.
#include <vtkQtRenderWindow.h>

#include "CommandParser.h"

vtkQtRenderWindow *
SimpleVisApp::ReturnVisWin(void *data)
{
    SimpleVisApp *This = (SimpleVisApp *)data;
    return This->viswin;
}

SimpleVisApp::SimpleVisApp(VisItViewer *v) : QMainWindow()
{
    viewer = v;
    setWindowTitle(tr("Simple visualization"));
    plotType = 0;

    // Create the window.
    QWidget *central = new QWidget(this);
    setCentralWidget(central);

    QHBoxLayout *hLayout = new QHBoxLayout(central);
    hLayout->setMargin(10);
    hLayout->setSpacing(10);
    QVBoxLayout *leftLayout = new QVBoxLayout(0);
    leftLayout->setSpacing(10);
    hLayout->addLayout(leftLayout);

    scalarLabel = new QLabel(tr("Scalar variables"), central);
    leftLayout->addWidget(scalarLabel);

    variables = new QListWidget(central);
    leftLayout->addWidget(variables);
    connect(variables, SIGNAL(currentTextChanged(const QString &)),
            this, SLOT(changeVariable(const QString &)));

    plotTypeWidget = new QWidget(central);
    leftLayout->addWidget(plotTypeWidget);
    QHBoxLayout *ptLayout = new QHBoxLayout(plotTypeWidget);
    ptLayout->setSpacing(10);
    ptLayout->addWidget(new QLabel(tr("Plot type"), plotTypeWidget));
    plotType = new QButtonGroup(plotTypeWidget);
    QRadioButton *rb = new QRadioButton(tr("Pseudocolor"), plotTypeWidget);
    plotType->addButton(rb, 0);
    ptLayout->addWidget(rb);
    rb = new QRadioButton(tr("Contour"), plotTypeWidget);
    plotType->addButton(rb, 1);
    ptLayout->addWidget(rb);
    connect(plotType, SIGNAL(buttonClicked(int)),
            this, SLOT(changePlotType(int)));

    contourWidget = new QWidget(central);
    leftLayout->addWidget(contourWidget);
    QHBoxLayout *cLayout = new QHBoxLayout(contourWidget);
    cLayout->setSpacing(10);
    nContours = new QSpinBox(contourWidget);
    nContours->setRange(1,40);
    nContours->setValue(10);
    connect(nContours, SIGNAL(valueChanged(int)),
            this, SLOT(setNContours(int)));
    cLayout->addWidget(new QLabel(tr("Number of contours"), contourWidget));
    cLayout->addWidget(nContours);

    // Create the vis window directly.
    viswin = new vtkQtRenderWindow(central);
    viswin->setMinimumSize(QSize(500,500));
    hLayout->addWidget(viswin, 100);

    // Create menus
    QMenu *fileMenu = menuBar()->addMenu(tr("File"));
    fileMenu->addAction(tr("Open . . ."), this, SLOT(selectFile()));
    fileMenu->addAction(tr("Open commands. . ."), this, SLOT(execFile()));
    fileMenu->addSeparator();
    fileMenu->addAction(tr("Save window"), this, SLOT(saveWindow()));
    fileMenu->addSeparator();
    fileMenu->addAction(tr("Quit"), qApp, SLOT(quit()));
    
    QMenu *controlsMenu = menuBar()->addMenu(tr("Controls"));
    controlsMenu->addAction(tr("Open GUI"), this, SLOT(openGUI()));

    //
    // Register a window creation function (before Setup) that will
    // return the vtkQtRenderWindow objects that we've already
    // parented into our interface.
    //
    viewer->SetWindowCreationCallback(ReturnVisWin, (void *)this);

    // Set the initial widget sensitivity.
    resetWindow();

    cmd = 0;
}

SimpleVisApp::~SimpleVisApp()
{
    delete cmd;
}

void
SimpleVisApp::resetWindow()
{
    variables->blockSignals(true);
    variables->clear();
    variables->blockSignals(false);

    plotType->blockSignals(true);
    plotType->button(0)->setChecked(true);
    plotType->blockSignals(false);

    scalarLabel->setEnabled(false);
    variables->setEnabled(false);
    plotTypeWidget->setEnabled(false);
    contourWidget->setEnabled(false);

    viewer->Methods()->DeleteActivePlots();
}

//
// Qt slots
//

void
SimpleVisApp::show()
{
    // Tell the viewer to hide toolbars in all windows.
    viewer->Methods()->HideToolbars(true);
    // Tell the viewer to show all windows. This does not show our windows
    // since our windows are embedded but it does do some extra setup for
    // the windows and thus needs to be called.
    viewer->Methods()->ShowAllWindows();

    QMainWindow::show();
}

void
SimpleVisApp::selectFile()
{
    // Get a filename from the file dialog.
    QString filename = QFileDialog::getOpenFileName(this,
               tr("Open File"),
               QDir::current().path(),
               tr("Data files (*.silo *.vtk *.cgns *.nc *.h5 *.pdb *.visit)"));

    openFile(filename);
}

void
SimpleVisApp::openFile(const QString &filename)
{
    if(!filename.isEmpty())
    {
        // Open the file.
        viewer->Methods()->OpenDatabase(filename.toStdString());

        // Get the file's metadata and populate the variable list.
        const avtDatabaseMetaData *md = viewer->GetMetaData(filename.toStdString());
        if(md != 0)
        {
            variables->blockSignals(true);
            for(int i = 0; i < md->GetNumScalars(); ++i)
                variables->addItem(md->GetScalar(i)->name.c_str());
            variables->setCurrentRow(0);
            variables->blockSignals(false);
            if(md->GetNumScalars() > 0)
            {
                variables->setEnabled(true);
                plotTypeWidget->setEnabled(true);
                contourWidget->setEnabled(plotType->checkedId() == 1);
                // Add a plot of the first variable
                changePlotType(plotType->checkedId());
            }
            scalarLabel->setEnabled(true);
            variables->setEnabled(true);
        }
        else
            resetWindow();
    }
    else
        resetWindow();
}

void
SimpleVisApp::changeVariable(const QString &var)
{
    viewer->Methods()->ChangeActivePlotsVar(var.toStdString());
}

void
SimpleVisApp::changeVariableAndUpdate(const QString &var)
{
    changeVariable(var);

    variables->blockSignals(true);
    for(int i = 0; i < variables->count(); ++i)
    {
        if(variables->item(i)->text() == var)
        {
            variables->setCurrentRow(i);
            break;
        }
    }
    variables->blockSignals(false);
}

void
SimpleVisApp::changePlotType(int val)
{
    if(variables->currentRow() == -1)
        return;

    // Determine the variable.
    std::string var(variables->currentItem()->text().toStdString());

    // Delete the active plots.
    viewer->Methods()->DeleteActivePlots();
    if(val == 0)
    {
        int Pseudocolor = viewer->GetPlotIndex("Pseudocolor");
        viewer->Methods()->AddPlot(Pseudocolor, var);
    }
    else
    {
        int Contour = viewer->GetPlotIndex("Contour");
        viewer->Methods()->AddPlot(Contour, var);
    }
    contourWidget->setEnabled(val == 1);
    viewer->Methods()->DrawPlots();
}

void
SimpleVisApp::setNContours(int nc)
{
    int Contour = viewer->GetPlotIndex("Contour");
    AttributeSubject *contourAtts = viewer->DelayedState()->GetPlotAttributes(Contour);
    if(contourAtts != 0)
    {
        contourAtts->SetValue("contourNLevels", nc);
        contourAtts->Notify();
        viewer->DelayedMethods()->SetPlotOptions(Contour);
    }
}

void
SimpleVisApp::saveWindow()
{
    // Set the output format to JPEG
    SaveWindowAttributes *swa = viewer->State()->GetSaveWindowAttributes();
    swa->SetFormat(SaveWindowAttributes::JPEG);
    swa->SetScreenCapture(true);

    // Save the window
    viewer->Methods()->SaveWindow();
}

void
SimpleVisApp::openGUI()
{
    stringVector args;
    viewer->DelayedMethods()->OpenClient("GUI", viewer->GetVisItCommand(), args);
}

void
SimpleVisApp::execFile()
{
    // Get a filename from the file dialog.
    QString filename = QFileDialog::getOpenFileName(this,
               tr("Open File"),
               QDir::current().path(),
               tr("command files (*.txt)"));
        
    if(!filename.isEmpty())
    {
        if(cmd == NULL)
        {
            // Create the command parser.
            cmd = new CommandParser(viewer);
            connect(cmd, SIGNAL(openFile(const QString &)),
                    this, SLOT(openFile(const QString &)));
            connect(cmd, SIGNAL(changeVariable(const QString &)),
                    this, SLOT(changeVariableAndUpdate(const QString &)));
            connect(cmd, SIGNAL(changePlotType(int)),
                    this, SLOT(changePlotType(int)));
            connect(cmd, SIGNAL(setNContours(int)),
                    this, SLOT(setNContours(int)));
            connect(cmd, SIGNAL(saveWindow()),
                    this, SLOT(saveWindow()));
        }

        cmd->ProcessCommands(filename);
    }
}

CommandParser.h

Declaration for the command parser class in the simple vis application. The CommandParser class is a simple class for translating textual commands into Qt signals that we hook up to slots in the SimpleVisApp.

#ifndef COMMAND_PARSER_H
#define COMMAND_PARSER_H
#include <QObject>
#include <QStringList>

#include <VisItViewer.h>
#include "Synchronizer.h"

class CommandParser : public QObject
{
   Q_OBJECT
public:
   CommandParser(VisItViewer *v);
   virtual ~CommandParser();

   void ProcessCommands(const QString &filename);
signals:
    void openFile(const QString &);
    void changeVariable(const QString &);
    void changePlotType(int);
    void setNContours(int);
    void saveWindow();

private slots:
   void ProcessOneCommand();
private:
    VisItViewer  *viewer;
    QStringList   commands;
    Synchronizer *sync;
};

#endif

CommandParser.cpp

Implementation for the command parser class in the simple vis application.

#include <QFile>
#include <QTextStream>
#include "CommandParser.h"

CommandParser::CommandParser(VisItViewer *v) : QObject(), viewer(v)
{
    // This is called after VisItViewer::Setup. This is CRITICAL!
    sync = new Synchronizer(
        v->State()->GetSyncAttributes(),    // The object that we observe
        v->DelayedState()->GetSyncAttributes() // The object that we use to post syncs
        );
}

CommandParser::~CommandParser()
{
}

void CommandParser::ProcessCommands(const QString &filename)
{
    commands.clear();

    QFile f(filename);
    if(f.open(QIODevice::ReadOnly))
    {
        QTextStream s(&f);
        while(!s.atEnd())
            commands.push_back(s.readLine());
    }

    if(commands.size() > 0)
    {
        connect(sync, SIGNAL(synchronized()),
                this, SLOT(ProcessOneCommand()));
        sync->PostSynchronize();
    }
}

void CommandParser::ProcessOneCommand()
{
    if(commands.empty())
    {
        disconnect(sync, SIGNAL(synchronized()),
                   this, SLOT(ProcessOneCommand()));
        return;
    }

    QString cmd = commands.front();
    commands.pop_front();

    // translate the command into viewer calls
    if(cmd.left(8) == "openFile")
    {
        qDebug("Executing command: %s", cmd.toStdString().c_str());
        std::string var =  cmd.right(cmd.size()-8-1).toStdString();
        emit openFile(QString(var.c_str()));
    }
    else if(cmd.left(14) == "changeVariable")
    {
        qDebug("Executing command: %s", cmd.toStdString().c_str());
        std::string var =  cmd.right(cmd.size()-14-1).toStdString();
        emit changeVariable(QString(var.c_str()));
    }
    else if(cmd.left(14) == "changePlotType")
    {
        qDebug("Executing command: %s", cmd.toStdString().c_str());
        QString pt = cmd.right(cmd.size()-14-1);
        emit changePlotType(pt.toInt());
    }
    else if(cmd.left(12) == "setNContours")
    {
        qDebug("Executing command: %s", cmd.toStdString().c_str());
        QString nc = cmd.right(cmd.size()-12-1);
        emit setNContours(nc.toInt());
    }
    else if(cmd == "saveWindow")
    {
        qDebug("Executing command: %s", cmd.toStdString().c_str());
        emit saveWindow();
    }

    // issue a synchronize. We'll get back to this method when
    // the synchronizer issues its signal.
    sync->PostSynchronize();
}

Synchronizer.h

Declaration for the synchronizer class in the simple vis application. The synchronizer is used by the command parser to ensure that the next command is not issued to the viewer until the viewer has completed the current command.

#ifndef SYNCHRONIZER_H
#define SYNCHRONIZER_H
#include <QObject>
#include <Observer.h>
#include <SyncAttributes.h>

class Synchronizer : public QObject, public Observer
{
   Q_OBJECT
public:
   Synchronizer(Subject *s, Subject *ds);
   virtual ~Synchronizer();

   void PostSynchronize();

signals:
   void synchronized();
private:
   virtual void Update(Subject *s);

   int syncCount;
   SyncAttributes *sync, *delayedSync;
};

#endif

Synchronizer.cpp

Implementation for the synchronizer class in the simple vis application.

#include "Synchronizer.h"

Synchronizer::Synchronizer(Subject *s, Subject *ds) : QObject(), Observer(s)
{
    syncCount = 100;
    sync = (SyncAttributes *)s;
    delayedSync = (SyncAttributes *)ds;
}

Synchronizer::~Synchronizer()
{
}

void
Synchronizer::PostSynchronize()
{
    delayedSync->SetSyncTag(syncCount++);
    delayedSync->Notify();
}

void Synchronizer::Update(Subject *)
{
    emit synchronized();
}

main.cpp

#include <qapplication.h>
#include <qdir.h>

#include <visitstream.h>
#include <VisItViewer.h>
#include <VisItException.h>

#include <SimpleVisApp.h>

int
main(int argc, char *argv[])
{
    int retval = 0;

    //
    // Do basic initialization. This is only done once to initialize the
    // viewer library.
    //
    VisItViewer::Initialize(&argc, &argv);

    TRY
    {
        //
        // Create the viewer.
        //
        VisItViewer viewer;

        // Set up VISITHOME so it finds our development version of VisIt when 
        // run from this directory.
        QDir d("../../");
        std::string visithome(d.absolutePath().toStdString());
        viewer.SetVISITHOME(visithome);

        //
        // Process the command line arguments first since some may be removed
        // by QApplication::QApplication.
        //
        viewer.ProcessCommandLine(argc, argv);

        //
        // Create the QApplication. This sets the qApp pointer.
        //
        QApplication *mainApp = new QApplication(argc, argv);

        //
        // Create our visualization app. We have to do it before the call to Setup()
        // since we're embedding vis windows.
        //
        SimpleVisApp *visapp = new SimpleVisApp(&viewer);

        //
        // Now that we've created the QApplication, let's call the viewer's
        // setup routine.
        //
        viewer.Setup();

        //
        // Show our app's main window
        //
        visapp->show();
        visapp->raise();

        //
        // Execute the viewer.
        //
        retval = mainApp->exec();
    }
    CATCH2(VisItException, e)
    {
        cerr << "VisIt's viewer encountered the following fatal "
                "initialization error: " << endl
             << e.Message().c_str() << endl;
        retval = -1;
    }
    ENDTRY

    // Finalize the viewer library.
    VisItViewer::Finalize();

    return retval;
}