46#include "graphicsScene.hh"
47#include "graphicsView.hh"
48#include "sceneElement.hh"
49#include "sceneTools.hh"
50#include "elementArea.hh"
52#include "elementInput.hh"
53#include "elementOutput.hh"
54#include "elementFunction.hh"
55#include "connection.hh"
56#include "connectionPoint.hh"
59#include "baseWidget.hh"
61#include <QApplication>
62#include <QPaintEngine>
65#include "../parser/context.hh"
66#include "../parser/output.hh"
67#include "../parser/function.hh"
69#define SELECTION_RED 0x00
70#define SELECTION_GREEN 0x00
71#define SELECTION_BLUE 0x7f
72#define SELECTION_ALPHA 0x7f
87 function_ (_function),
90 selectionActive_ (false),
91 blockChanges_ (false),
92 activeConnection_ (0),
98 tools_->setZValue (10);
101 selection_ =
new QGraphicsRectItem ();
102 addItem (selection_);
103 selection_->setZValue (1);
106 selection_->setBrush(QBrush(QColor(SELECTION_RED,
109 SELECTION_ALPHA / 2)));
111 selection_->setPen(QColor(SELECTION_RED,
117 addItem (elementArea_);
118 elementArea_->setZValue (0.0);
140 view_->setScene (
this);
141 view_->setRenderHint (QPainter::Antialiasing,
true);
146 connect (
this, SIGNAL(sceneRectChanged(
const QRectF& )),
this, SLOT(sceneResized(
const QRectF&)));
147 dontMoveStart_ =
false;
159 view_->deleteLater ();
165void GraphicsScene::drawBackground(QPainter *_painter,
const QRectF &_rect)
167 QGraphicsScene::drawBackground (_painter, _rect);
173void GraphicsScene::dragEnterEvent (QGraphicsSceneDragDropEvent *_event)
176 if (validMimeData (_event->mimeData ()) && !dndElement_ && ctx_->
element (mimeDataElementName (_event->mimeData ())))
178 dndElement_ =
new SceneElement (
this, ctx_->
element (mimeDataElementName (_event->mimeData ())));
179 dndElement_->setOpacity (0.5);
182 QPoint off = mimeDataPoint (_event->mimeData ());
184 QPointF p = elementArea_->mapFromScene (_event->scenePos ().x (), _event->scenePos ().y ());
185 dndElement_->setPos (p.x () - (dndElement_->size ().width () / 2) - off.x(),
186 p.y () - (dndElement_->size ().height () / 2) - off.y());
197void GraphicsScene::dragLeaveEvent (QGraphicsSceneDragDropEvent *_event)
200 if (validMimeData (_event->mimeData ()) && dndElement_)
202 tools_->
mouseRelease (_event->scenePos (), dndElement_);
214void GraphicsScene::dragMoveEvent (QGraphicsSceneDragDropEvent *_event)
217 if (validMimeData (_event->mimeData ()) && dndElement_)
219 QPoint off = mimeDataPoint (_event->mimeData ());
220 QPointF p = elementArea_->mapFromScene (_event->scenePos ().x (), _event->scenePos ().y ());
221 dndElement_->setPos (p.x () - (dndElement_->size ().width () / 2) - off.x (),
222 p.y () - (dndElement_->size ().height () / 2) - off.y ());
233void GraphicsScene::dropEvent (QGraphicsSceneDragDropEvent *_event)
236 if (validMimeData (_event->mimeData ()) && dndElement_)
238 tools_->
mouseRelease (_event->scenePos (), dndElement_);
239 dndElement_->setOpacity (1.0);
261 elementArea_->moveBy (_dx, _dy);
266 foreach (QGraphicsItem *e, elementArea_->
elements ())
267 if (e->isSelected ())
269 QPointF p = elementArea_->mapFromScene (0, 0) -
270 elementArea_->mapFromScene (_dx, _dy);
271 e->moveBy (p.x (), p.y ());
280 QRectF rect = sceneRect();
281 scaleElements (_delta, QPointF (rect.x () + (rect.width () / 2.0),
282 rect.y () + (rect.height () / 2.0)));
290 QPointF p(elementArea_->mapFromScene (_center.x (), _center.y ()));
291 elementArea_->setTransform(QTransform().translate(p.x (), p.y ()).scale(_delta, _delta).translate(-p.x (), -p.y ()),
true);
312 removeItem (_element);
338 return elementArea_->mapToScene (elementArea_->childrenBoundingRect ()).
boundingRect ();
354void GraphicsScene::mousePressEvent (QGraphicsSceneMouseEvent *_event)
358 foreach (QGraphicsItem *e, selectedItems ())
359 p += e->mapToScene (e->shape ());
361 QGraphicsScene::mousePressEvent (_event);
362 selectionStart_ = _event->scenePos ();
364 if (itemAt (selectionStart_,QTransform()) != elementArea_ && !_event->isAccepted ())
366 if (_event->modifiers () & (Qt::ControlModifier | Qt::ShiftModifier))
367 setSelectionArea (p);
369 selectionActive_ =
true;
370 selection_->setRect (QRectF (selectionStart_, QSizeF (0, 0)));
375 dontMoveStart_ =
true;
381void GraphicsScene::mouseMoveEvent (QGraphicsSceneMouseEvent *_event)
383 if (selectionActive_)
385 selection_->setRect (QRectF (selectionStart_, _event->scenePos ()).normalized ());
388 else if (activeConnection_)
390 activeConnection_->mouseMoveEvent (_event);
393 QGraphicsScene::mouseMoveEvent (_event);
399void GraphicsScene::mouseReleaseEvent (QGraphicsSceneMouseEvent *_event)
401 if (selectionActive_)
406 p.addRect (QRectF (selectionStart_, _event->scenePos ()).normalized ());
408 if (_event->modifiers () == Qt::ControlModifier)
410 p += selectionArea ();
411 setSelectionArea (p);
413 else if (_event->modifiers () == Qt::ShiftModifier)
415 foreach (QGraphicsItem *e, items (QRectF (selectionStart_, _event->scenePos ()).normalized ()))
416 if (e->isSelected ())
417 e->setSelected (
false);
420 setSelectionArea (p);
422 selectionActive_ =
false;
426 if (activeConnection_)
428 activeConnection_->mouseReleaseEvent (_event);
431 QGraphicsScene::mouseReleaseEvent (_event);
437QList<SceneElement *> GraphicsScene::getAllElements()
439 QList<SceneElement *> rv;
441 foreach (SceneElement *e, elementArea_->
elements ())
444 foreach (ElementFunction *ef, e->functions ())
446 rv.append (ef->scene ()->getAllElements ());
465 QList<ElementFunction *> functions;
471 functions.append (ef);
476 if (!e->precode ().isEmpty ())
479 rv += e->shortDescription ();
486 if (!functions.isEmpty ())
488 rv +=
"# ------- FUNCTIONS -----------\n\n";
503 param += o->
name () +
", ";
506 if (!param.isEmpty ())
507 param.remove (param.length () - 2, 2);
509 rv +=
" (" + param +
"):\n";
515 QStringList lines = code.split(
"\n");
516 for (
int l=0;l<lines.length();l++) lines[l] = ident + lines[l];
517 code = lines.join(
"\n");
522 if (!functions.isEmpty ())
524 rv +=
"# ------- END FUNCTIONS -------\n\n";
539 if ((!function_ && e->
element ()->
name () ==
"start") ||
542 if ((!function_ && e->
element ()->
name () ==
"end") ||
550 errors +=
"No start element!";
558 if (
elements.isEmpty() && end->inputs().isEmpty ())
561 rv +=
"# --- CODE BEGIN ---\n\n";
563 updateConnections (start,
true);
568 while ((!
elements.empty () || end) && found)
594 if (end->dataIn () && !end->dataIn ()->valid ())
600 if (!end->inputs ().isEmpty ())
613 rv += updateConnections (found,
false);
615 QString dName =
"ask_user_output_" + found->
variableId();
616 QString dInputs =
"";
654 if (!dInputs.isEmpty ())
657 dInputs.remove (dInputs.length () - 1, 1);
658 rv +=
"# Ask user for missing input values\n";
659 rv +=
"" + dName +
" = eval(visualscripting.askForInputs (\"" + found->
element ()->
name ();
660 rv +=
"\", \"" + dInputs +
"\"));\n";
663 rv += found->
code ();
668 rv +=
"# --- CODE END ---\n";
697 QList<SceneElement *> fixE;
712 errors +=
"<dl><dt>";
715 errors +=
"<b>Function: </b>Main";
719 errors +=
"</dt><dd>";
731 if (errors.endsWith (
", "))
732 errors.remove (errors.length () - 2, 2);
733 errors +=
")</i><br>";
736 if (errors.endsWith (
"<br>"))
737 errors.remove (errors.length () - 4, 4);
739 errors +=
"<dd></dl>";
750QString GraphicsScene::updateConnections (
SceneElement *_from,
bool _isStart)
760 rv +=
"" + oName +
" = None;\n";
775 c->input ()->setValid (
true);
776 c->input ()->element ()->replaceCodeBlock (
"input", c->input ()->inOut ()->name (), oName);
784 c->input ()->setValid (
true);
794bool GraphicsScene::validMimeData(
const QMimeData *_m)
796 return _m->hasFormat (
"application/x-openflipper.vsi");
802QString GraphicsScene::mimeDataElementName(
const QMimeData *_m)
804 if (!validMimeData (_m))
806 QStringList sl = QString (_m->data (
"application/x-openflipper.vsi")).split (
";");
808 if (sl.length() != 3)
817QPoint GraphicsScene::mimeDataPoint(
const QMimeData *_m)
819 if (! validMimeData (_m))
820 return QPoint (0, 0);
822 QStringList sl = QString (_m->data (
"application/x-openflipper.vsi")).split (
";");
824 if (sl.length() != 3)
825 return QPoint (0, 0);
828 int x = sl[0].toInt (&ok1);
829 int y = sl[1].toInt (&ok2);
832 return QPoint (0, 0);
834 return QPoint (x, y);
842 QTransform t = elementArea_->transform ();
843 QDomElement s = _doc.createElement(
"transform");
844 _root.appendChild(s);
845 QDomText txt = _doc.createTextNode(
846 QString::number (t.m11 ()) +
"|" + QString::number (t.m12 ()) +
"|" + QString::number (t.m13 ()) +
"|" +
847 QString::number (t.m21 ()) +
"|" + QString::number (t.m22 ()) +
"|" + QString::number (t.m23 ()) +
"|" +
848 QString::number (t.m31 ()) +
"|" + QString::number (t.m32 ()) +
"|" + QString::number (t.m33 ())
852 s = _doc.createElement(
"x");
853 _root.appendChild(s);
854 txt = _doc.createTextNode (QString::number(elementArea_->pos ().x ()));
857 s = _doc.createElement(
"y");
858 _root.appendChild(s);
859 txt = _doc.createTextNode (QString::number(elementArea_->pos ().y ()));
862 QDomElement el = _doc.createElement(
"elements");
863 _root.appendChild(el);
880 if (sl.length () == 9)
886 for (
unsigned int i = 0; i < 9; i++)
888 m[i] = sl[i].toDouble (&ok);
893 elementArea_->setTransform (QTransform (m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]),
false);
901 x = val.toDouble (&ok1);
904 y = val.toDouble (&ok2);
907 elementArea_->setPos (x, y);
911 std::vector<QString> connections;
914 for(QDomElement n = _domElement.firstChildElement(); !n.isNull(); n = n.nextSiblingElement() )
917 if (n.tagName() ==
"elements") {
920 for(QDomElement sceneElement = n.firstChildElement(); !sceneElement.isNull(); sceneElement = sceneElement.nextSiblingElement() )
922 loadElement (sceneElement,connections);
927 for (
auto connection : connections) {
928 loadConnection(connection);
931 QTimer::singleShot(0,
this, SLOT (updateConnections()));
937void GraphicsScene::loadElement(QDomElement & _domElement,std::vector<QString>& _connections)
939 QString name = _domElement.attribute(
"name");
940 if (name.isEmpty () || !ctx_->
element (name))
953void GraphicsScene::loadConnection(QString& _connection)
958 QStringList connectionInfo = _connection.split(
";");
960 if (connectionInfo.size() != 6 ) {
964 QString inEl = connectionInfo[0];
965 QString inElId = connectionInfo[1];
966 QString inIn = connectionInfo[2];
968 QString outEl = connectionInfo[3];
969 QString outElId = connectionInfo[4];
970 QString outOut = connectionInfo[5];
972 inId = inElId.toInt (&ok);
976 outId = outElId.toInt (&ok);
980 SceneElement *in = NULL, *out = NULL;
982 foreach (SceneElement *e,
elements ())
984 if (e->element ()->name () == inEl && e->id () == inId)
986 else if (e->element ()->name () == outEl && e->id () == outId)
993 ConnectionPoint *p1 = NULL, *p2 = NULL;
995 if (in->dataIn () && in->dataIn ()->inOut ()->name () == inIn &&
996 out->dataOut () && out->dataOut ()->inOut ()->name () == outOut)
998 p1 = in->dataIn ()->connectionPointItem ();
999 p2 = out->dataOut ()->connectionPointItem ();
1003 foreach (ElementInput *i, in->inputs())
1004 if (i->inOut ()->name () == inIn)
1006 p1 = i->connectionPointItem ();
1010 foreach (ElementOutput *o, out->outputs())
1011 if (o->inOut ()->name () == outOut)
1013 p2 = o->connectionPointItem ();
1019 new Connection (p1, p2,
this);
1027 elementArea_->resetTransform ();
1028 elementArea_->setPos (0, 0);
1045 start->setPos(5, (height () - start->size ().height ()) / 2);
1050 end->setPos(width () - end->size ().width () - 5, (height () - end->size ().height ()) / 2);
1057 start->setPos(5, (height () - start->size ().height ()) / 2);
1062 end->setPos(width () - end->size ().width () - 5, (height () - end->size ().height ()) / 2);
1065 dontMoveStart_ =
false;
1071void GraphicsScene::updateConnections()
1090 c->updatePositions ();
1104 dontMoveStart_ =
true;
1109void VSI::GraphicsScene::sceneResized(
const QRectF & )
1114 blockChanges_ =
true;
1116 QList<SceneElement *> elements = elementArea_->elements ();
1126 if ((!function_ && e->
element ()->
name () ==
"start") ||
1127 (function_ && function_->function ()->start () == e->
element ()))
1129 if ((!function_ && e->
element ()->
name () ==
"end") ||
1130 (function_ && function_->function ()->end () == e->
element ()))
1135 start->setPos(5, (height () - start->size ().height ()) / 2);
1137 end->setPos(width () - end->size ().width () - 5, (height () - end->size ().height ()) / 2);
1139 blockChanges_ =
false;
ElementInput * input()
Input of this connection.
void updatePositions()
called to update position on element movement
static QString getXmlString(QDomElement &_element, const QString &_tag, QString _default="")
Gets the string of a xml query.
Element * element(const QString &_name)
Returns the element with a given name.
bool removeElement(SceneElement *_element, bool _force=false)
Remove an element, if its removeable or _force is set.
const QList< SceneElement * > & elements() const
All elements.
QRectF boundingRect() const
Bounding rectangle.
void addElement(SceneElement *_element)
Add a child element.
SceneElement * element()
The scene element of this function element.
GraphicsScene * scene()
Scene.
Function * function()
Function class.
InOut * inOut() const
InOut context object.
QList< Connection * > connections() const
Connections.
const QString & shortDescription() const
Short description.
QString name() const
Element name.
const QVector< Output * > & outputs() const
Outputs.
const QString & shortDescription() const
Short description.
Element * end() const
End element of this function (can be NULL)
Element * start() const
Start element of this function.
QString name() const
Name.
void contentChange()
handle content changes
QRectF elementsBoundingRect()
Bounding rectangle of all scene elements.
void loadFromXml(QDomElement &_domElement)
Load from xml.
void clearScene(bool _start=false)
clear the whole scene (_start = keep start element)
void contentChanged()
Informs about content changes.
QString generateCode(QString &errors, bool _codeOnly=false)
Generate textual script code (_codeOnly = only pure code block)
qreal getNewZ()
Returns a new Z value that is above all elements.
void mouseMove(QPointF _pos)
Redirect mouse movement to tools area.
GraphicsScene(VSI::Context *_ctx, ElementFunction *_function=NULL)
Constructor.
void addElement(SceneElement *_element)
Add the element to the scene.
void scaleElements(qreal _delta)
Scale all elements with scaling center in the center of the scene.
const QList< SceneElement * > & elements() const
Scene elements.
void mouseRelease(QPointF _pos, QGraphicsItem *_item)
Redirect mouse release to tools area.
bool removeElement(SceneElement *_element)
Remove the element from the scene.
~GraphicsScene()
Destructor.
void saveToXml(QDomDocument &_doc, QDomElement &_root)
Save to xml.
void moveElements(qreal _dx, qreal _dy, bool _selected=false)
Moves all elements.
const QString & shortDescription() const
Short description.
const QString & name() const
Name.
QString variableId()
Unique variable name for code generation.
QVector< ElementOutput * > outputs()
Outputs.
void replaceCodeBlock(const QString &_name, const QString &_id, const QString &_value)
Replace block with name _name and id _id with _value.
void saveToXml(QDomDocument &_doc, QDomElement &_root)
Save to xml.
void loadFromXml(QDomElement &_domElement, std::vector< QString > &_connections)
Load one scene Element from xml.
ElementInput * dataIn()
Scene input.
void resetCodeGeneration()
Reset code block for code generation.
Element * element() const
Context VSI::Element.
ElementOutput * dataOut()
Scene output.
QString code()
Code block.
QVector< ElementFunction * > functions()
Functions.
QVector< ElementInput * > inputs()
Inputs.