Skip to content
This repository has been archived by the owner on Mar 29, 2024. It is now read-only.

Towards python interactors: enhance C++ interactors #2

Open
renoust opened this issue Jun 23, 2016 · 0 comments
Open

Towards python interactors: enhance C++ interactors #2

renoust opened this issue Jun 23, 2016 · 0 comments

Comments

@renoust
Copy link

renoust commented Jun 23, 2016

Before we can handle pure python interactors, we can enhance current C++ interactors with a python call mechanism.

Here is the simple modification I made with @anlambert MouseLassoNodesSelector. This allows me to root the call of the selection event through a python code, which itself can filter whatever it wants in return (especially in that case, the selected nodes have viewSelection set to True).

I believe we may generalize the case, and want some mechanism to pipe some python script after interaction, which allows us to refine the behavior of our interactors on the fly and really accelerate prototyping. Two classes of selectors will be particularly useful, group selectors-types (e.g. lasso) and node information type.

It may be done as a registration system, like with plugins, instead a python script would register to interactors and be executed after they have been applied. Or it can be the other way around, in the parameters of the interactor, we could specify an optional python plugin to run.

void MouseLassoNodesPythonSelectorInteractorComponent::callPython(){
  std::string e_output;
  python_script_name = "Default Python Selector";
  graph->applyAlgorithm(python_script_name, e_output);
}
bool MouseLassoNodesPythonSelectorInteractorComponent::eventFilter(QObject *obj, QEvent *e) {
  GlMainWidget *glWidget=static_cast<GlMainWidget *>(obj);

  if (!glWidget->hasMouseTracking()) {
    glWidget->setMouseTracking(true);
  }

  QMouseEvent *me = dynamic_cast<QMouseEvent *>(e);

  if (!me) return false;

  camera = &glWidget->getScene()->getLayer("Main")->getCamera();
  graph = glWidget->getScene()->getGlGraphComposite()->getInputData()->getGraph();
  viewSelection = graph->getProperty<BooleanProperty>("viewSelection");

  currentPointerScreenCoord = Coord(me->x(), glWidget->height() - me->y());

  if (me->type() == QEvent::MouseMove) {
    if (dragStarted) {
      polygon.push_back(glWidget->screenToViewport(currentPointerScreenCoord));
      drawInteractor = true;
      glWidget->redraw();

    }

    return true;
  }
  else if (me->type() == QEvent::MouseButtonPress) {
    if (me->button() == Qt::LeftButton) {
      dragStarted = true;
      polygon.push_back(glWidget->screenToViewport(currentPointerScreenCoord));
    }
    else if (me->button() == Qt::RightButton) {
      dragStarted = false;

      if (!polygon.empty()) {
        polygon.clear();
        drawInteractor = true;
        glWidget->redraw();
      }
      else {
        Observable::holdObservers();
        SelectedEntity selectedEntity;
        bool result = glWidget->pickNodesEdges(me->x(), me->y(),  selectedEntity);

        if (result && selectedEntity.getEntityType() == SelectedEntity::NODE_SELECTED) {
          bool sel = viewSelection->getNodeValue(node(selectedEntity.getComplexEntityId()));
          viewSelection->setNodeValue(node(selectedEntity.getComplexEntityId()), !sel);
        }

        Observable::unholdObservers();
      }
    }

    return true;
  }
  else if (me->type() == QEvent::MouseButtonRelease) {
    dragStarted = false;

    if (me->button() == Qt::LeftButton && polygon.size() > 10) {
      Observable::holdObservers();

      if (me->modifiers() != Qt::ControlModifier) {
        viewSelection->setAllNodeValue(false);
        viewSelection->setAllEdgeValue(false);
      }

      selectGraphElementsUnderPolygon(glWidget);
      callPython();
      Observable::unholdObservers();

    }

    polygon.clear();

  }

  return false;
}

Here is a dummy example of the Default Python Selector, depending on the graph name, it routes the right plugin to apply, doubles the size of the selected nodes, then deselect them.

from tulip import *
import tulipplugins

class DefaultPythonSelector(tlp.Algorithm):
    def __init__(self, context):
        tlp.Algorithm.__init__(self, context)

    def check(self):
        return (True, "")

    def run(self):

        viewSelection = self.graph.getBooleanProperty("viewSelection")
        viewSize = self.graph.getSizeProperty("viewSize")
        if self.graph.getName() == "meta-overview":
            tlp.getDefaultPluginParameters("Explore cabinet")
            self.graph.applyAlgorithm("Explore cabinet")

        elif self.graph.getName() == "timeline":
            tlp.getDefaultPluginParameters("Timeline Selection")
            self.graph.applyAlgorithm("Timeline Selection")

        for n in viewSelection.getNodesEqualTo(True):
            viewSize[n] = tlp.Size(viewSize[n] [0]*2, viewSize[n] [1]*2, viewSize[n] [2]*2)
            viewSelection[n] = False

        return True

tulipplugins.registerPluginOfGroup("DefaultPythonSelector", "Default Python Selector", "Benjamin Renoust", "30/01/2016", "Default Python Selection", "1.0", "Interactor")
bpinaud referenced this issue Jan 29, 2019

Unverified

No user is associated with the committer email.
TravisCI: Migrate Linux builds from trusty to xenial
p-mary referenced this issue Mar 12, 2019
…bProcessEngineProcess is still running after a geographic has been created, so force an exit call
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant