Tulip  4.0.0
Better Visualization Through Research
 All Classes Files Functions Variables Enumerations Enumerator Properties Groups Pages
interactor_plugin/interactor_plugin.cpp

This example gives a minimalistic approach of interaction with a graphIn this example, we are making an interactor plugin for Node link diagram view that will activate zoom and pan and display informations when you click on a node/edge.

The code contains a step-by-step explanation of the process, please refer to classes documentation for more informations about their usage.

#include <QtCore/QPropertyAnimation>
#include <QtGui/QGraphicsView>
#include <QtGui/QLabel>
#include <QtGui/QGraphicsProxyWidget>
#include <tulip/MouseInteractors.h>
#include <tulip/Interactor.h>
#include <tulip/GlMainView.h>
#include <tulip/GlMainWidget.h>
#include <tulip/GlScene.h>
using namespace tlp;
/*
In this class we create an GLInteractorComponent
In first see InteractorPlugin
*/
class InteractorPluginComponent : public InteractorComponent {
QGraphicsProxyWidget *_informationWidgetItem;
QLabel *_informationLabel;
public :
/*
Basic constructor
In this constructor we create a label to display informations
And a QGraphicsProxyWidget to show informations in Tulip QGraphics system
*/
InteractorPluginComponent() {
_informationLabel=new QLabel();
_informationWidgetItem=new QGraphicsProxyWidget();
_informationWidgetItem->setWidget(_informationLabel);
_informationWidgetItem->setVisible(false);
}
/*
This function is call when the view associated to this interactor is changed
So at this moment we add information QGraphicsItem to the QGraphicsScene
*/
void viewChanged(View * view) {
view->graphicsView()->scene()->addItem(_informationWidgetItem);
}
/*
Most important function of an interactor component
When an event arrive on your interactor : this function is call
You have to process it and return true. If the event do nothing in your interactor : this function return false;
*/
bool eventFilter(QObject *, QEvent* e) {
/*
If you have clicked on a node/edge, information widget is visible.
And if you use the wheel of the mouse we hide the informations widget
*/
if(_informationWidgetItem->isVisible() && e->type()==QEvent::Wheel) {
_informationWidgetItem->setVisible(false);
return false;
}
/*
Check if the event is a mouse event
*/
QMouseEvent * qMouseEv = dynamic_cast<QMouseEvent *>(e);
if(qMouseEv != NULL) {
GlMainView *glMainView=dynamic_cast<GlMainView*>(view());
/*
Check if event is a left mouse button press
*/
if (e->type() == QEvent::MouseButtonPress && qMouseEv->button() == Qt::LeftButton) {
/*
If you have clicked on a node/edge, information widget is visible.
And if you reclick : hide it
*/
if(_informationWidgetItem->isVisible()) {
_informationWidgetItem->setVisible(false);
}
else {
/*
Select entities under the mouse cursor
The result of selection is stored in SelectedEntity
And pickNodesEdges return true if you click on node or edge
*/
SelectedEntity selectedEntity;
if (glMainView->getGlMainWidget()->pickNodesEdges(qMouseEv->x(),qMouseEv->y(),selectedEntity)) {
/*
Change text of the information label with
- If you click on a node : "Click on node id : nodeId"
- If you click on an edge : "Click on edge id : edgeId"
*/
QString text("Click on ");
if(selectedEntity.getEntityType() == SelectedEntity::NODE_SELECTED)
text+="node ";
else
text+="edge ";
text+=" id : "+QString::number(selectedEntity.getComplexEntityId());
/*
- Update QLabel with new text
- Auto resize QLabel
- Set position of the label at mouse position
- Display it
*/
_informationLabel->setText(text);
_informationLabel->adjustSize();
_informationWidgetItem->setPos(qMouseEv->pos());
_informationWidgetItem->setVisible(true);
/*
Here we just add a small smooth animation on the label pop
*/
QPropertyAnimation *animation = new QPropertyAnimation(_informationWidgetItem, "opacity");
animation->setDuration(100);
animation->setStartValue(0.);
animation->setEndValue(0.99);
animation->start();
/*
We have treated the event so we return true
*/
return true;
}
}
}
}
/*
We don't have treated the event se we return false
*/
return false;
}
};
/*
If you want to create an interactor plugin, the first think to do is to create a sub class of InteractorComposite
*/
class InteractorPlugin : public InteractorComposite {
QLabel *_configurationLabel;
public:
/*
This macro is here to register informations about the plugin
PLUGININFORMATIONS(Plugin name, Author, Date, Plugin long name, version, type of plugin (Navigation,Information...))
*/
PLUGININFORMATIONS("InteractorPlugin", "Tulip Team", "05/10/2012", "Demo Interactor", "1.0", "Information")
/*
The constructor
Here we specify the icon of interactor with Qt qrc system, and the ToolTip text of the plugin
*/
InteractorPlugin(const tlp::PluginContext*):InteractorComposite(QIcon(":/i_interactor_plugin.png"),"Demo Interactor") {
/*
Here we create a label with a minimal configuration text
This text will be displayed when you click on the name of the plugin
*/
_configurationLabel=new QLabel(QString("This is a demo interactor.<br>")
+"You can zoom and pan and display informations if you click on a node/edge.");
}
~InteractorPlugin() {
delete _configurationLabel;
}
/*
Here we construct the interactor
An InteractorComposite is a list of InteractorComponent.
It's like a chain of responsibility :
- When an event arrive the first InteractorComponent catch it in eventFilter function.
- If the InteractorComponent don't process this event (if eventFilter function return false), the event is passed to the second InteractorComponent
In this example we have two InteractorComponent
The first one : InteractorPluginComponent is the example InteractorComponent
The second one : MouseNKeysNavigation is a standard Tulip InteractorComponent who activate Zoom and pan interaction
*/
void construct() {
push_back(new MouseNKeysNavigator);
push_back(new InteractorPluginComponent);
}
/*
In this function we say : this plugin is compatible with Node Link Diagram View
If you don't implement this function your plugin won't be displayed in interactors tool bar
*/
bool isCompatible(const std::string &viewName) {
if(viewName=="Node Link Diagram view")
return true;
return false;
}
/*
In this function we say : _configurationLabel is the configuration widget
*/
QWidget* configurationWidget() const {
return _configurationLabel;
}
/*
In Plugin system we have a priority system to display interactor icon
If priority is low, you interactor will be at the left of the interactord tool bar
*/
unsigned int priority() const {
return 5;
}
};
/*
With this macro you register your plugin in Tulip plugin engine
*/
PLUGIN(InteractorPlugin)