52 #include "graphicsScene.hh"
53 #include "graphicsView.hh"
54 #include "sceneElement.hh"
55 #include "sceneTools.hh"
56 #include "elementArea.hh"
58 #include "elementInput.hh"
59 #include "elementOutput.hh"
60 #include "elementFunction.hh"
61 #include "connection.hh"
62 #include "connectionPoint.hh"
65 #include "baseWidget.hh"
67 #include <QApplication>
68 #include <QPaintEngine>
71 #include <QXmlResultItems>
73 #include "../parser/context.hh"
74 #include "../parser/output.hh"
75 #include "../parser/function.hh"
77 #define SELECTION_RED 0x00
78 #define SELECTION_GREEN 0x00
79 #define SELECTION_BLUE 0x7f
80 #define SELECTION_ALPHA 0x7f
95 function_ (_function),
98 selectionActive_ (false),
99 blockChanges_ (false),
100 activeConnection_ (0),
106 tools_->setZValue (10);
109 selection_ =
new QGraphicsRectItem ();
110 addItem (selection_);
111 selection_->setZValue (1);
114 selection_->setBrush(QBrush(QColor(SELECTION_RED,
117 SELECTION_ALPHA / 2)));
119 selection_->setPen(QColor(SELECTION_RED,
125 addItem (elementArea_);
126 elementArea_->setZValue (0.0);
148 view_->setScene (
this);
149 view_->setRenderHint (QPainter::Antialiasing,
true);
154 connect (
this, SIGNAL(sceneRectChanged(
const QRectF& )),
this, SLOT(sceneResized(
const QRectF&)));
155 dontMoveStart_ =
false;
167 view_->deleteLater ();
173 void GraphicsScene::drawBackground(QPainter *_painter,
const QRectF &_rect)
175 QGraphicsScene::drawBackground (_painter, _rect);
181 void GraphicsScene::dragEnterEvent (QGraphicsSceneDragDropEvent *_event)
184 if (validMimeData (_event->mimeData ()) && !dndElement_ && ctx_->
element (mimeDataElementName (_event->mimeData ())))
186 dndElement_ =
new SceneElement (
this, ctx_->
element (mimeDataElementName (_event->mimeData ())));
187 dndElement_->setOpacity (0.5);
190 QPoint off = mimeDataPoint (_event->mimeData ());
192 QPointF p = elementArea_->mapFromScene (_event->scenePos ().x (), _event->scenePos ().y ());
193 dndElement_->setPos (p.x () - (dndElement_->size ().width () / 2) - off.x(),
194 p.y () - (dndElement_->size ().height () / 2) - off.y());
205 void GraphicsScene::dragLeaveEvent (QGraphicsSceneDragDropEvent *_event)
208 if (validMimeData (_event->mimeData ()) && dndElement_)
210 tools_->
mouseRelease (_event->scenePos (), dndElement_);
222 void GraphicsScene::dragMoveEvent (QGraphicsSceneDragDropEvent *_event)
225 if (validMimeData (_event->mimeData ()) && dndElement_)
227 QPoint off = mimeDataPoint (_event->mimeData ());
228 QPointF p = elementArea_->mapFromScene (_event->scenePos ().x (), _event->scenePos ().y ());
229 dndElement_->setPos (p.x () - (dndElement_->size ().width () / 2) - off.x (),
230 p.y () - (dndElement_->size ().height () / 2) - off.y ());
241 void GraphicsScene::dropEvent (QGraphicsSceneDragDropEvent *_event)
244 if (validMimeData (_event->mimeData ()) && dndElement_)
246 tools_->
mouseRelease (_event->scenePos (), dndElement_);
247 dndElement_->setOpacity (1.0);
269 elementArea_->moveBy (_dx, _dy);
274 foreach (QGraphicsItem *e, elementArea_->
elements ())
275 if (e->isSelected ())
277 QPointF p = elementArea_->mapFromScene (0, 0) -
278 elementArea_->mapFromScene (_dx, _dy);
279 e->moveBy (p.x (), p.y ());
288 QRectF rect = sceneRect();
289 scaleElements (_delta, QPointF (rect.x () + (rect.width () / 2.0),
290 rect.y () + (rect.height () / 2.0)));
298 QPointF p(elementArea_->mapFromScene (_center.x (), _center.y ()));
299 elementArea_->setTransform(QTransform().translate(p.x (), p.y ()).scale(_delta, _delta).translate(-p.x (), -p.y ()),
true);
320 removeItem (_element);
346 return elementArea_->mapToScene (elementArea_->childrenBoundingRect ()).boundingRect ();
362 void GraphicsScene::mousePressEvent (QGraphicsSceneMouseEvent *_event)
366 foreach (QGraphicsItem *e, selectedItems ())
367 p += e->mapToScene (e->shape ());
369 QGraphicsScene::mousePressEvent (_event);
370 selectionStart_ = _event->scenePos ();
372 if (itemAt (selectionStart_,QTransform()) != elementArea_ && !_event->isAccepted ())
374 if (_event->modifiers () & (Qt::ControlModifier | Qt::ShiftModifier))
375 setSelectionArea (p);
377 selectionActive_ =
true;
378 selection_->setRect (QRectF (selectionStart_, QSizeF (0, 0)));
383 dontMoveStart_ =
true;
389 void GraphicsScene::mouseMoveEvent (QGraphicsSceneMouseEvent *_event)
391 if (selectionActive_)
393 selection_->setRect (QRectF (selectionStart_, _event->scenePos ()).normalized ());
396 else if (activeConnection_)
398 activeConnection_->mouseMoveEvent (_event);
401 QGraphicsScene::mouseMoveEvent (_event);
407 void GraphicsScene::mouseReleaseEvent (QGraphicsSceneMouseEvent *_event)
409 if (selectionActive_)
414 p.addRect (QRectF (selectionStart_, _event->scenePos ()).normalized ());
416 if (_event->modifiers () == Qt::ControlModifier)
418 p += selectionArea ();
419 setSelectionArea (p);
421 else if (_event->modifiers () == Qt::ShiftModifier)
423 foreach (QGraphicsItem *e, items (QRectF (selectionStart_, _event->scenePos ()).normalized ()))
424 if (e->isSelected ())
425 e->setSelected (
false);
428 setSelectionArea (p);
430 selectionActive_ =
false;
434 if (activeConnection_)
436 activeConnection_->mouseReleaseEvent (_event);
439 QGraphicsScene::mouseReleaseEvent (_event);
445 QList<SceneElement *> GraphicsScene::getAllElements()
447 QList<SceneElement *> rv;
449 foreach (SceneElement *e, elementArea_->
elements ())
452 foreach (ElementFunction *ef, e->functions ())
454 rv.append (ef->scene ()->getAllElements ());
473 QList<ElementFunction *> functions;
479 functions.append (ef);
494 if (!functions.isEmpty ())
496 rv +=
"// ------- FUNCTIONS -----------\n\n";
511 param += o->
name () +
", ";
514 if (!param.isEmpty ())
515 param.remove (param.length () - 2, 2);
517 rv +=
" (" + param +
")\n{\n";
521 rv += code +
"}\n\n";
524 if (!functions.isEmpty ())
526 rv +=
"// ------- END FUNCTIONS -------\n\n";
541 if ((!function_ && e->
element ()->
name () ==
"start") ||
544 if ((!function_ && e->
element ()->
name () ==
"end") ||
552 errors +=
"No start element!";
556 elements.removeAll (start);
557 elements.removeAll (end);
560 if (elements.isEmpty() && end->
inputs().isEmpty ())
563 rv +=
"// --- CODE BEGIN ---\n\n";
565 updateConnections (start,
true);
570 while ((!elements.empty () || end) && found)
602 if (!end->
inputs ().isEmpty ())
610 elements.removeAll (found);
615 rv += updateConnections (found,
false);
617 QString dName =
"ask_user_output_" + found->
variableId();
618 QString dInputs =
"";
656 if (!dInputs.isEmpty ())
659 dInputs.remove (dInputs.length () - 1, 1);
660 rv +=
"// Ask user for missing input values\n";
661 rv +=
"var " + dName +
" = visualscripting.askForInputs (\"" + found->
element ()->
name ();
662 rv +=
"\", \"" + dInputs +
"\");\n";
665 rv += found->
code ();
670 rv +=
"// --- CODE END ---\n";
673 elements.append (end);
675 if (!elements.isEmpty ())
698 QList<SceneElement *> fixE;
713 errors +=
"<dl><dt>";
716 errors +=
"<b>Function: </b>Main";
720 errors +=
"</dt><dd>";
732 if (errors.endsWith (
", "))
733 errors.remove (errors.length () - 2, 2);
734 errors +=
")</i><br>";
737 if (errors.endsWith (
"<br>"))
738 errors.remove (errors.length () - 4, 4);
740 errors +=
"<dd></dl>";
748 QStringList code = rv.split (
'\n');
752 foreach (QString s, code)
754 if (s.contains (
'}') && !indent.isEmpty ())
755 indent.remove (indent.length () - 2, 2);
756 rv += indent + s +
"\n";
757 if (s.contains (
'{'))
768 QString GraphicsScene::updateConnections (
SceneElement *_from,
bool _isStart)
778 rv +=
"var " + oName +
"\n";
793 c->input ()->setValid (
true);
794 c->input ()->element ()->replaceCodeBlock (
"input", c->input ()->inOut ()->name (), oName);
802 c->input ()->setValid (
true);
811 bool GraphicsScene::validMimeData(
const QMimeData *_m)
813 return _m->hasFormat (
"application/x-openflipper.vsi");
819 QString GraphicsScene::mimeDataElementName(
const QMimeData *_m)
821 if (!validMimeData (_m))
823 QStringList sl = QString (_m->data (
"application/x-openflipper.vsi")).split (
";");
825 if (sl.length() != 3)
834 QPoint GraphicsScene::mimeDataPoint(
const QMimeData *_m)
836 if (! validMimeData (_m))
837 return QPoint (0, 0);
839 QStringList sl = QString (_m->data (
"application/x-openflipper.vsi")).split (
";");
841 if (sl.length() != 3)
842 return QPoint (0, 0);
845 int x = sl[0].toInt (&ok1);
846 int y = sl[1].toInt (&ok2);
849 return QPoint (0, 0);
851 return QPoint (x, y);
859 QTransform t = elementArea_->transform ();
860 QDomElement s = _doc.createElement(
"transform");
861 _root.appendChild(s);
862 QDomText txt = _doc.createTextNode(
863 QString::number (t.m11 ()) +
"|" + QString::number (t.m12 ()) +
"|" + QString::number (t.m13 ()) +
"|" +
864 QString::number (t.m21 ()) +
"|" + QString::number (t.m22 ()) +
"|" + QString::number (t.m23 ()) +
"|" +
865 QString::number (t.m31 ()) +
"|" + QString::number (t.m32 ()) +
"|" + QString::number (t.m33 ())
869 s = _doc.createElement(
"x");
870 _root.appendChild(s);
871 txt = _doc.createTextNode (QString::number(elementArea_->pos ().x ()));
874 s = _doc.createElement(
"y");
875 _root.appendChild(s);
876 txt = _doc.createTextNode (QString::number(elementArea_->pos ().y ()));
879 QDomElement el = _doc.createElement(
"elements");
880 _root.appendChild(el);
897 if (sl.length () == 9)
900 for (
unsigned int i = 0; i < 9; i++)
902 m[i] = sl[i].toDouble (&ok);
907 elementArea_->setTransform (QTransform (m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]),
false);
915 x = val.toDouble (&ok1);
918 y = val.toDouble (&ok2);
921 elementArea_->setPos (x, y);
923 _xml.setQuery (
"elements/element");
929 _xml.evaluateTo (&el);
930 QXmlItem item (el.next ());
931 while (!item.isNull ())
940 _xml.setQuery (
"elements/element/inputs/input/connection");
944 _xml.evaluateTo (&el);
945 QXmlItem item (el.next ());
946 while (!item.isNull ())
955 QTimer::singleShot(0,
this, SLOT (updateConnections()));
961 void GraphicsScene::loadElement(QXmlQuery & _xml)
964 if (name.isEmpty () || !ctx_->
element (name))
976 void GraphicsScene::loadConnection(QXmlQuery & _xml)
985 inId = inElId.toInt (&ok);
993 outId = outElId.toInt (&ok);
997 SceneElement *in = NULL, *out = NULL;
999 foreach (SceneElement *e,
elements ())
1001 if (e->element ()->name () == inEl && e->id () == inId)
1003 else if (e->element ()->name () == outEl && e->id () == outId)
1010 ConnectionPoint *p1 = NULL, *p2 = NULL;
1012 if (in->dataIn () && in->dataIn ()->inOut ()->name () == inIn &&
1013 out->dataOut () && out->dataOut ()->inOut ()->name () == outOut)
1015 p1 = in->dataIn ()->connectionPointItem ();
1016 p2 = out->dataOut ()->connectionPointItem ();
1020 foreach (ElementInput *i, in->inputs())
1021 if (i->inOut ()->name () == inIn)
1023 p1 = i->connectionPointItem ();
1027 foreach (ElementOutput *o, out->outputs())
1028 if (o->inOut ()->name () == outOut)
1030 p2 = o->connectionPointItem ();
1036 new Connection (p1, p2,
this);
1044 elementArea_->resetTransform ();
1045 elementArea_->setPos (0, 0);
1062 start->setPos(5, (height () - start->size ().height ()) / 2);
1067 end->setPos(width () - end->size ().width () - 5, (height () - end->size ().height ()) / 2);
1074 start->setPos(5, (height () - start->size ().height ()) / 2);
1079 end->setPos(width () - end->size ().width () - 5, (height () - end->size ().height ()) / 2);
1082 dontMoveStart_ =
false;
1088 void GraphicsScene::updateConnections()
1119 dontMoveStart_ =
true;
1124 void VSI::GraphicsScene::sceneResized(
const QRectF & )
1129 blockChanges_ =
true;
1131 QList<SceneElement *> elements = elementArea_->elements ();
1141 if ((!function_ && e->
element ()->
name () ==
"start") ||
1142 (function_ && function_->function ()->start () == e->
element ()))
1144 if ((!function_ && e->
element ()->
name () ==
"end") ||
1145 (function_ && function_->function ()->end () == e->
element ()))
1150 start->setPos(5, (height () - start->size ().height ()) / 2);
1152 end->setPos(width () - end->size ().width () - 5, (height () - end->size ().height ()) / 2);
1154 blockChanges_ =
false;
bool valid()
Returns state of valid flag (needed during code generation)
bool removeElement(SceneElement *_element)
Remove the element from the scene.
void mouseMove(QPointF _pos)
Handles mouse movement (will be called by the scene, if the mouse with a draged element is moved) ...
QString value() const
Returns value set by user.
const QString & shortDescription() const
Short description.
QRectF elementsBoundingRect()
Bounding rectangle of all scene elements.
const QString & name() const
Name.
SceneElement * element()
The scene element of this function element.
void contentChanged()
Informs about content changes.
QVector< ElementInput * > inputs()
Inputs.
const QList< SceneElement * > & elements() const
Scene elements.
const QString & shortDescription() const
Short description.
void loadFromXml(QXmlQuery &_xml)
Load from xml.
static BaseWidget * getBaseWidget()
Returns singleton.
void clearScene(bool _start=false)
clear the whole scene (_start = keep start element)
void scaleElements(qreal _delta)
Scale all elements with scaling center in the center of the scene.
void saveToXml(QDomDocument &_doc, QDomElement &_root)
Save to xml.
Element * start() const
Start element of this function.
void mouseRelease(QPointF _pos, QGraphicsItem *_item)
Handles mouse release (will be called by the scene, if the element is dropped)
InOut * inOut() const
InOut context object.
QString name() const
Name.
~GraphicsScene()
Destructor.
static QString getXmlString(QXmlQuery &_xml, QString _expr, QString _default="")
Gets the string of a xml query.
bool isSet()
Return "set" flag.
const QVector< Output * > & outputs() const
Outputs.
void addScene(GraphicsScene *_scene)
add a new scene
void loadFromXml(QXmlQuery &_xml)
Load from xml.
QString name() const
Element name.
Element * element(QString _name)
Returns the element with a given name.
void setValid(bool _value)
Sets the valid flag (needed during code generation)
ElementInput * input()
Input of this connection.
QList< Connection * > connections() const
Connections.
GraphicsScene(VSI::Context *_ctx, ElementFunction *_function=NULL)
Constructor.
QVector< ElementFunction * > functions()
Functions.
Function * function()
Function class.
void saveToXml(QDomDocument &_doc, QDomElement &_root)
Save to xml.
Element * element() const
Context VSI::Element.
QString precode() const
Precode segment.
void moveElements(qreal _dx, qreal _dy, bool _selected=false)
Moves all elements.
bool removeElement(SceneElement *_element, bool _force=false)
Remove an element, if its removeable or _force is set.
void contentChange()
handle content changes
Element * end() const
End element of this function (can be NULL)
const QString & shortDescription() const
Short description.
void addElement(SceneElement *_element)
Add the element to the scene.
qreal getNewZ()
Returns a new Z value that is above all elements.
ElementInput * dataIn()
Scene input.
unsigned int state()
VSI::Input state passthrough.
GraphicsScene * scene()
Scene.
QString generateCode(QString &errors, bool _codeOnly=false)
Generate textual script code (_codeOnly = only pure code block)
bool isForceAskSet() const
Return "ForceAsk" flag.
ElementOutput * dataOut()
Scene output.
void replaceCodeBlock(QString _name, QString _id, QString _value)
Replace block with name _name and id _id with _value.
QString code()
Code block.
QString variableId()
Unique variable name for code generation.
void mouseMove(QPointF _pos)
Redirect mouse movement to tools area.
void updatePositions()
called to update position on element movement
const QList< SceneElement * > & elements() const
All elements.
void removeScene(GraphicsScene *_scene)
remove a scene
QVector< ElementOutput * > outputs()
Outputs.
void addElement(SceneElement *_element)
Add a child element.
void mouseRelease(QPointF _pos, QGraphicsItem *_item)
Redirect mouse release to tools area.
void resetCodeGeneration()
Reset code block for code generation.