Commit a1995574 authored by alexy's avatar alexy
Browse files

ENH: Qt support

git-svn-id: http://svn.slicer.org/Slicer4/trunk@10300 3bd1e089-480b-0410-8dfb-8563597acbee
parent 581d67b6
......@@ -71,6 +71,12 @@ extern "C" {
#endif
//#define Slicer3_USE_QT
#ifdef Slicer3_USE_QT
#include "QtApp.h"
#endif
#include <vtksys/SystemTools.hxx>
#include <vtksys/Directory.hxx>
#include <vtksys/stl/string>
......@@ -1795,6 +1801,12 @@ int Slicer3_main(int argc, char *argv[])
slicerApp->SplashMessage("Finalizing Startup...");
appGUI->DisplayMainSlicerWindow ( );
#ifdef Slicer3_USE_QT
QtApp *qtApp = new QtApp();
qtApp->SetMRMLScene(scene);
qtApp->BuildGUI();
#endif
//
//--- set home module based on registry settings
......
......@@ -24,6 +24,14 @@ set(include_dirs
${RemoteIO_BINARY_DIR}
)
IF(Slicer3_USE_QT)
set(include_dirs ${include_dirs} ${QT_INCLUDE_DIR} ${QT_QTGUI_INCLUDE_DIR} ${QT_QTCORE_INCLUDE_DIR})
# QT4_WRAP_UI(UI_SRCS GUI4.ui)
QT4_WRAP_CPP(MOC_SRCS QtSlicerNodeSelectorWidget.h)
SET(SRCS ${SRCS} ${MOC_SRCS} QtApp.cxx QtApp.h QtSlicerNodeSelectorWidget.cxx QtSlicerNodeSelectorWidget.h)
ENDIF(Slicer3_USE_QT)
include_directories(${include_dirs})
slicer3_get_persistent_property(Slicer3_Base_INCLUDE_DIRS tmp)
......@@ -142,17 +150,19 @@ set(SlicerBaseGUI_SRCS
vtkSlicerBoxRepresentation.cxx
vtkSlicerBoxWidget2.cxx
vtkSlicerWaitMessageWidget.cxx
${SRCS}
)
# Helper classes
#SET_SOURCE_FILES_PROPERTIES(
# none yet
# vtkSlicerGUIUpdate.cxx
# vtkSlicerLogicUpdate.cxx
# vtkSlicerMRMLUpdate.cxx
# WRAP_EXCLUDE
# )
SET_SOURCE_FILES_PROPERTIES(
QtSlicerNodeSelectorWidget.cxx
moc_QtSlicerNodeSelectorWidget.cxx
QtSlicerNodeSelectorWidget.h
QtApp.cxx
QtApp.h
WRAP_EXCLUDE
)
# --------------------------------------------------------------------------
# Wrapping
......@@ -177,12 +187,6 @@ target_link_libraries(${lib_name}
RemoteIO
)
# Apply user-defined properties to the library target.
IF(Slicer3_LIBRARY_PROPERTIES)
SET_TARGET_PROPERTIES(${lib_name} PROPERTIES
${Slicer3_LIBRARY_PROPERTIES}
)
ENDIF(Slicer3_LIBRARY_PROPERTIES)
slicer3_get_persistent_property(Slicer3_Base_LIBRARIES tmp)
slicer3_set_persistent_property(Slicer3_Base_LIBRARIES ${tmp} ${lib_name})
......
//# ifdef Slicer3_USE_PYTHON
//# include "PythonQt.h"
//# include "PythonQt_QtAll.h"
//# endif
#include <QApplication>
#include <QTextBrowser>
#include <QLayout>
#include <QGroupBox>
#include <QPushButton>
#include <QLineEdit>
#include "QtSlicerNodeSelectorWidget.h"
#include "QtApp.h"
QtApp::QtApp()
{
}
QtApp::~QtApp()
{
}
void QtApp::BuildGUI()
{
// create a small Qt GUI
QVBoxLayout* vbox = new QVBoxLayout;
QGroupBox* box = new QGroupBox;
//QTextBrowser* browser = new QTextBrowser(box);
QLineEdit* edit = new QLineEdit(box);
QPushButton* button = new QPushButton(box);
button->setObjectName("button1");
edit->setObjectName("edit");
//browser->setObjectName("browser");
//vbox->addWidget(browser);
vbox->addWidget(edit);
vbox->addWidget(button);
this->qNodeSelector = new QtSlicerNodeSelectorWidget();
this->qNodeSelector->setObjectName("selector");
this->qNodeSelector->SetMRMLScene(this->MRMLScene);
this->qNodeSelector->SetNodeClass("vtkMRMLScalarVolumeNode", NULL, NULL, NULL);
vbox->addWidget(this->qNodeSelector);
box->setLayout(vbox);
this->qNodeSelector->connect(this->qNodeSelector, SIGNAL(NodeSelected(QString&)), edit, SLOT(setText ( const QString &)));
this->qNodeSelector->connect(this->qNodeSelector, SIGNAL(NodeSelected(QString&)), button, SLOT(setText ( const QString &)));
box->show();
}
/*=auto=========================================================================
Portions (c) Copyright 2005 Brigham and Women's Hospital (BWH) All Rights Reserved.
See Doc/copyright/copyright.txt
or http://www.slicer.org/copyright/copyright.txt for details.
Program: 3D Slicer
Module: $RCSfile: QtApp.h,v $
Date: $Date: 2006/01/08 04:48:05 $
Version: $Revision: 1.45 $
=========================================================================auto=*/
// .NAME QtApp - menu to select volumes from current mrml scene
// .SECTION Description
// Inherits most behavior from kw widget, but is specialized to observe
// the current mrml scene and update the entries of the pop up menu to correspond
// to the currently available volumes. This widget also has a notion of the current selection
// that can be observed or set externally
//
#ifndef __QtApp_h
#define __QtApp_h
//BTX
class QtSlicerNodeSelectorWidget;
#include "vtkMRMLScene.h"
class VTK_SLICER_BASE_GUI_EXPORT QtApp
{
public:
QtApp();
virtual ~QtApp();
vtkMRMLScene* GetMRMLScene()
{
return this->MRMLScene;
};
void SetMRMLScene(vtkMRMLScene *scene)
{
this->MRMLScene = scene;
};
void BuildGUI();
protected:
vtkMRMLScene *MRMLScene;
QtSlicerNodeSelectorWidget *qNodeSelector;
QtApp(const QtApp&); // Not implemented
void operator=(const QtApp&); // Not Implemented
};
//ETX
#endif
/*=auto=========================================================================
Portions (c) Copyright 2005 Brigham and Women's Hospital (BWH) All Rights Reserved.
See Doc/copyright/copyright.txt
or http://www.slicer.org/copyright/copyright.txt for details.
Program: 3D Slicer
Module: $RCSfile: QtSlicerNodeSelectorWidget.cxx,v $
Date: $Date: 2006/03/17 15:10:10 $
Version: $Revision: 1.2 $
=========================================================================auto=*/
#include "QtSlicerNodeSelectorWidget.h"
#include <sstream>
//----------------------------------------------------------------------------
// Description:
// the MRMLCallback is a static function to relay modified events from the
// observed mrml scene back into the logic layer for further processing
// - this can also end up calling observers of the logic (i.e. in the GUI)
//
static void MRMLCallback(vtkObject *caller, unsigned long eid, void *__clientData, void *callData)
{
QtSlicerNodeSelectorWidget *self = reinterpret_cast<QtSlicerNodeSelectorWidget *>(__clientData);
if (self->GetInMRMLCallbackFlag())
{
return;
}
vtkMRMLNode *node = reinterpret_cast<vtkMRMLNode *>(callData);
self->SetInMRMLCallbackFlag(1);
if (node == NULL || self->CheckNodeClass(node))
{
self->UpdateMenu();
}
self->SetInMRMLCallbackFlag(0);
}
//----------------------------------------------------------------------------
QtSlicerNodeSelectorWidget::QtSlicerNodeSelectorWidget()
{
this->NewNodeCount = 0;
this->NewNodeEnabled = 0;
this->NoneEnabled = 0;
this->ShowHidden = 0;
this->ChildClassesEnabled = 1;
this->MRMLScene = NULL;
this->ContextMenuHelper = NULL;
this->MRMLCallbackCommand = vtkCallbackCommand::New();
this->MRMLCallbackCommand->SetClientData( reinterpret_cast<void *> (this) );
this->MRMLCallbackCommand->SetCallback(MRMLCallback);
this->InMRMLCallbackFlag = 0;
connect(this, SIGNAL(triggered(QAction*)), this, SLOT(Select(QAction*)));
}
//----------------------------------------------------------------------------
QtSlicerNodeSelectorWidget::~QtSlicerNodeSelectorWidget()
{
this->SetMRMLScene ( NULL );
if (this->MRMLCallbackCommand)
{
this->MRMLCallbackCommand->Delete();
this->MRMLCallbackCommand = NULL;
}
if (this->ContextMenuHelper)
{
this->ContextMenuHelper->Delete();
}
}
//----------------------------------------------------------------------------
void QtSlicerNodeSelectorWidget::CreateWidget()
{
}
//----------------------------------------------------------------------------
void QtSlicerNodeSelectorWidget::SetMRMLScene( vtkMRMLScene *aMRMLScene)
{
if ( this->MRMLScene )
{
this->MRMLScene->RemoveObserver( this->MRMLCallbackCommand );
this->MRMLScene->Delete ( );
this->MRMLScene = NULL;
// this->MRMLScene->Delete();
}
this->MRMLScene = aMRMLScene;
if ( this->MRMLScene )
{
//this->MRMLScene->Register(this);
this->MRMLScene->AddObserver( vtkMRMLScene::NodeAddedEvent, this->MRMLCallbackCommand );
this->MRMLScene->AddObserver( vtkMRMLScene::NodeRemovedEvent, this->MRMLCallbackCommand );
this->MRMLScene->AddObserver( vtkMRMLScene::NewSceneEvent, this->MRMLCallbackCommand );
this->MRMLScene->AddObserver( vtkMRMLScene::SceneCloseEvent, this->MRMLCallbackCommand );
this->MRMLScene->AddObserver( vtkMRMLScene::SceneEditedEvent, this->MRMLCallbackCommand );
}
this->UpdateMenu();
}
//----------------------------------------------------------------------------
bool QtSlicerNodeSelectorWidget::CheckNodeClass(vtkMRMLNode *node)
{
for (int c=0; c < this->GetNumberOfNodeClasses(); c++)
{
const char *className = this->GetNodeClass(c);
if (this->GetChildClassesEnabled() && node->IsA(className))
{
return true;
}
if (!this->GetChildClassesEnabled() && !strcmp(node->GetClassName(), className))
{
return true;
}
}
return false;
}
//----------------------------------------------------------------------------
void QtSlicerNodeSelectorWidget::SetNodeClass(const char *className,
const char *attName,
const char *attValue,
const char *nodeName)
{
NodeClasses.clear();
NodeNames.clear();
AttributeNames.clear();
AttributeValues.clear();
const char *str = NULL;
if (className)
{
NodeClasses.push_back(std::string(className));
str = nodeName == NULL ? "" : nodeName;
NodeNames.push_back(std::string(str));
str = attName == NULL ? "" : attName;
AttributeNames.push_back(std::string(str));
str = attValue == NULL ? "" : attValue;
AttributeValues.push_back(std::string(str));
}
}
//----------------------------------------------------------------------------
void QtSlicerNodeSelectorWidget::AddNodeClass(const char *className,
const char *attName,
const char *attValue,
const char *nodeName)
{
const char *str = NULL;
if (className)
{
NodeClasses.push_back(std::string(className));
str = nodeName == NULL ? "" : nodeName;
NodeNames.push_back(std::string(str));
str = attName == NULL ? "" : attName;
AttributeNames.push_back(std::string(str));
str = attValue == NULL ? "" : attValue;
AttributeValues.push_back(std::string(str));
}
}
//----------------------------------------------------------------------------
void QtSlicerNodeSelectorWidget::ClearMenu()
{
this->clear();
Action_to_NodeID.clear();
//this->DeleteAllActions();
}
//----------------------------------------------------------------------------
std::string QtSlicerNodeSelectorWidget::MakeEntryName(vtkMRMLNode *node)
{
std::string entryName("");
std::string nodeName("");
if (node == NULL || node->GetName() == NULL)
{
return entryName;
}
else
{
nodeName = node->GetName();
}
entryName = nodeName;
std::map<std::string, std::string>::iterator iter;
int count = 1;
for (iter = this->NodeID_to_EntryName.begin();
iter != this->NodeID_to_EntryName.end();
iter++)
{
if (iter->second == entryName)
{
std::stringstream ss;
ss << nodeName << "_" << count++;
entryName = ss.str();
}
}
return entryName;
}
//----------------------------------------------------------------------------
std::string QtSlicerNodeSelectorWidget::FindEntryName(vtkMRMLNode *node)
{
std::string entryName("");
if (node == NULL || node->GetName() == NULL)
{
return entryName;
}
std::map<std::string, std::string>::iterator iter = this->NodeID_to_EntryName.find(node->GetID());
if (iter != this->NodeID_to_EntryName.end() )
{
entryName = iter->second;
}
return entryName;
}
//----------------------------------------------------------------------------
void QtSlicerNodeSelectorWidget::UpdateMenu()
{
this->UnconditionalUpdateMenu();
}
//----------------------------------------------------------------------------
void QtSlicerNodeSelectorWidget::UnconditionalUpdateMenu()
{
if ( !this || !this->MRMLScene )
{
return;
}
if (this->NodeClasses.size() == 0)
{
return;
}
NodeID_to_EntryName.clear();
vtkMRMLNode *oldSelectedNode = this->GetSelected();
std::string oldSelectedName = this->FindEntryName(oldSelectedNode);
this->ClearMenu();
int count = 0;
int c=0;
if (this->NewNodeEnabled)
{
for (c=0; c < this->GetNumberOfNodeClasses(); c++)
{
const char *name = this->GetNodeName(c);
if (name == NULL || !strcmp(name, "") )
{
name = this->MRMLScene->GetTagByClassName(this->GetNodeClass(c));
}
std::stringstream ss;
const char *node_class = this->GetNodeClass(c);
const char *tag = this->MRMLScene->GetTagByClassName(node_class);
if (!tag)
{
}
else
{
ss << "Create New " << tag;
// Build the command. Since node name can contain spaces, we
// need to quote the node name in the constructed Tcl command
std::stringstream sc;
sc << "ProcessNewNodeCommand " << this->GetNodeClass(c) << " \"" << name << "\"";
QAction *action = new QAction(ss.str().c_str(), this);
this->addAction(action);
//this->GetWidget()->GetWidget()->GetMenu()->SetItemCommand(count++, this, sc.str().c_str() );
//this->GetWidget()->GetWidget()->SetValue(ss.str().c_str());
}
}
}
if (this->NoneEnabled)
{
QAction *action = new QAction("None", this);
this->addAction(action);
//this->GetWidget()->GetWidget()->GetMenu()->SetItemCommand(count++, this, "ProcessCommand None");
}
vtkMRMLNode *node = NULL;
vtkMRMLNode *selectedNode = NULL;
std::string selectedName;
QAction *selectedAction = NULL;
bool selected = false;
int resultAddAdditionalNodes=this->AddAditionalNodes();
count +=resultAddAdditionalNodes;
for (c=0; c < this->GetNumberOfNodeClasses(); c++)
{
const char *className = this->GetNodeClass(c);
this->MRMLScene->InitTraversal();
while ( (node = this->MRMLScene->GetNextNodeByClass(className) ) != NULL)
{
if (!node->GetSelectable())
{
continue;
}
if (!this->ShowHidden && node->GetHideFromEditors())
{
continue;
}
if (!this->GetChildClassesEnabled() && strcmp(node->GetClassName(), className) != 0)
{
continue;
}
// If there is a Attribute Name-Value specified, then only include nodes that
// match both the NodeClass and Attribute
if ((this->GetNodeAttributeName(c)== NULL ||
this->GetNodeAttributeValue(c)== NULL ||
(node->GetAttribute( this->GetNodeAttributeName(c)) != NULL &&
strcmp( node->GetAttribute( this->GetNodeAttributeName(c) ), this->GetNodeAttributeValue(c) ) == 0) )&&this->CheckAdditionalConditions(node))
{
std::stringstream sc;
sc << "ProcessCommand " << node->GetID();
std::string entryName = this->MakeEntryName(node);
this->NodeID_to_EntryName[node->GetID()] = entryName.c_str();
QAction *action = new QAction(entryName.c_str(), this);
action->setCheckable(true);
this->addAction(action);
this->Action_to_NodeID[action] = node->GetID();
// do we need a column break?
if (count != 0 && count % 30 == 0)
{
//this->GetWidget()->GetWidget()->GetMenu()->SetItemColumnBreak(count, 1);
}
//this->GetWidget()->GetWidget()->GetMenu()->SetItemCommand(count++, this, sc.str().c_str());
if (oldSelectedNode == node)
{
selectedNode = node;
selected = true;
selectedName = entryName;
selectedAction = action;
}
//Only choose first one wenn the Additional Nodes didn't take care about this
else if (!selected && !this->NoneEnabled&&(resultAddAdditionalNodes==0))
{
selectedNode = node;
selected = true;
selectedName = entryName;
selectedAction = action;
}
}
}
}
//Node already selected in additonal Nodes
if(resultAddAdditionalNodes!=0&&selectedNode==NULL)
{
selectedNode=this->GetSelected();
selectedName = this->FindEntryName(selectedNode);
}
if (selectedNode != NULL)
{
this->setActiveAction(selectedAction);
this->UncheckAll();
selectedAction->setChecked(true);
//this->GetWidget()->GetWidget()->SetValue(selectedName.c_str());
this->SelectedID = std::string(selectedNode->GetID());
}
else
{
const char *name = "";
if (this->NoneEnabled)
{
name = "None";
}
//this->setActiveAction(xxx);
//this->GetWidget()->GetWidget()->SetValue(name);
this->SelectedID = std::string(name);
}
// Add Context menu for operations on selected node
// - first create it if needed
// - then populate it based on the currently selected node