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 <QXmlResultItems> 67 #include "../parser/context.hh" 68 #include "../parser/output.hh" 69 #include "../parser/function.hh" 71 #define SELECTION_RED 0x00 72 #define SELECTION_GREEN 0x00 73 #define SELECTION_BLUE 0x7f 74 #define SELECTION_ALPHA 0x7f 89 function_ (_function),
92 selectionActive_ (false),
93 blockChanges_ (false),
94 activeConnection_ (0),
100 tools_->setZValue (10);
103 selection_ =
new QGraphicsRectItem ();
104 addItem (selection_);
105 selection_->setZValue (1);
108 selection_->setBrush(QBrush(QColor(SELECTION_RED,
111 SELECTION_ALPHA / 2)));
113 selection_->setPen(QColor(SELECTION_RED,
119 addItem (elementArea_);
120 elementArea_->setZValue (0.0);
142 view_->setScene (
this);
143 view_->setRenderHint (QPainter::Antialiasing,
true);
148 connect (
this, SIGNAL(sceneRectChanged(
const QRectF& )),
this, SLOT(sceneResized(
const QRectF&)));
149 dontMoveStart_ =
false;
161 view_->deleteLater ();
167 void GraphicsScene::drawBackground(QPainter *_painter,
const QRectF &_rect)
169 QGraphicsScene::drawBackground (_painter, _rect);
175 void GraphicsScene::dragEnterEvent (QGraphicsSceneDragDropEvent *_event)
178 if (validMimeData (_event->mimeData ()) && !dndElement_ && ctx_->
element (mimeDataElementName (_event->mimeData ())))
180 dndElement_ =
new SceneElement (
this, ctx_->
element (mimeDataElementName (_event->mimeData ())));
181 dndElement_->setOpacity (0.5);
184 QPoint off = mimeDataPoint (_event->mimeData ());
186 QPointF p = elementArea_->mapFromScene (_event->scenePos ().x (), _event->scenePos ().y ());
187 dndElement_->setPos (p.x () - (dndElement_->size ().width () / 2) - off.x(),
188 p.y () - (dndElement_->size ().height () / 2) - off.y());
199 void GraphicsScene::dragLeaveEvent (QGraphicsSceneDragDropEvent *_event)
202 if (validMimeData (_event->mimeData ()) && dndElement_)
204 tools_->
mouseRelease (_event->scenePos (), dndElement_);
216 void GraphicsScene::dragMoveEvent (QGraphicsSceneDragDropEvent *_event)
219 if (validMimeData (_event->mimeData ()) && dndElement_)
221 QPoint off = mimeDataPoint (_event->mimeData ());
222 QPointF p = elementArea_->mapFromScene (_event->scenePos ().x (), _event->scenePos ().y ());
223 dndElement_->setPos (p.x () - (dndElement_->size ().width () / 2) - off.x (),
224 p.y () - (dndElement_->size ().height () / 2) - off.y ());
235 void GraphicsScene::dropEvent (QGraphicsSceneDragDropEvent *_event)
238 if (validMimeData (_event->mimeData ()) && dndElement_)
240 tools_->
mouseRelease (_event->scenePos (), dndElement_);
241 dndElement_->setOpacity (1.0);
263 elementArea_->moveBy (_dx, _dy);
268 foreach (QGraphicsItem *e, elementArea_->
elements ())
269 if (e->isSelected ())
271 QPointF p = elementArea_->mapFromScene (0, 0) -
272 elementArea_->mapFromScene (_dx, _dy);
273 e->moveBy (p.x (), p.y ());
282 QRectF rect = sceneRect();
283 scaleElements (_delta, QPointF (rect.x () + (rect.width () / 2.0),
284 rect.y () + (rect.height () / 2.0)));
292 QPointF p(elementArea_->mapFromScene (_center.x (), _center.y ()));
293 elementArea_->setTransform(QTransform().translate(p.x (), p.y ()).scale(_delta, _delta).translate(-p.x (), -p.y ()),
true);
314 removeItem (_element);
340 return elementArea_->mapToScene (elementArea_->childrenBoundingRect ()).boundingRect ();
356 void GraphicsScene::mousePressEvent (QGraphicsSceneMouseEvent *_event)
360 foreach (QGraphicsItem *e, selectedItems ())
361 p += e->mapToScene (e->shape ());
363 QGraphicsScene::mousePressEvent (_event);
364 selectionStart_ = _event->scenePos ();
366 if (itemAt (selectionStart_,QTransform()) != elementArea_ && !_event->isAccepted ())
368 if (_event->modifiers () & (Qt::ControlModifier | Qt::ShiftModifier))
369 setSelectionArea (p);
371 selectionActive_ =
true;
372 selection_->setRect (QRectF (selectionStart_, QSizeF (0, 0)));
377 dontMoveStart_ =
true;
383 void GraphicsScene::mouseMoveEvent (QGraphicsSceneMouseEvent *_event)
385 if (selectionActive_)
387 selection_->setRect (QRectF (selectionStart_, _event->scenePos ()).normalized ());
390 else if (activeConnection_)
392 activeConnection_->mouseMoveEvent (_event);
395 QGraphicsScene::mouseMoveEvent (_event);
401 void GraphicsScene::mouseReleaseEvent (QGraphicsSceneMouseEvent *_event)
403 if (selectionActive_)
408 p.addRect (QRectF (selectionStart_, _event->scenePos ()).normalized ());
410 if (_event->modifiers () == Qt::ControlModifier)
412 p += selectionArea ();
413 setSelectionArea (p);
415 else if (_event->modifiers () == Qt::ShiftModifier)
417 foreach (QGraphicsItem *e, items (QRectF (selectionStart_, _event->scenePos ()).normalized ()))
418 if (e->isSelected ())
419 e->setSelected (
false);
422 setSelectionArea (p);
424 selectionActive_ =
false;
428 if (activeConnection_)
430 activeConnection_->mouseReleaseEvent (_event);
433 QGraphicsScene::mouseReleaseEvent (_event);
439 QList<SceneElement *> GraphicsScene::getAllElements()
441 QList<SceneElement *> rv;
448 rv.append (ef->
scene ()->getAllElements ());
467 QList<ElementFunction *> functions;
473 functions.append (ef);
488 if (!functions.isEmpty ())
490 rv +=
"// ------- FUNCTIONS -----------\n\n";
505 param += o->
name () +
", ";
508 if (!param.isEmpty ())
509 param.remove (param.length () - 2, 2);
511 rv +=
" (" + param +
")\n{\n";
515 rv += code +
"}\n\n";
518 if (!functions.isEmpty ())
520 rv +=
"// ------- END FUNCTIONS -------\n\n";
535 if ((!function_ && e->
element ()->
name () ==
"start") ||
538 if ((!function_ && e->
element ()->
name () ==
"end") ||
546 errors +=
"No start element!";
550 elements.removeAll (start);
551 elements.removeAll (end);
554 if (elements.isEmpty() && end->
inputs().isEmpty ())
557 rv +=
"// --- CODE BEGIN ---\n\n";
559 updateConnections (start,
true);
564 while ((!elements.empty () || end) && found)
596 if (!end->
inputs ().isEmpty ())
604 elements.removeAll (found);
609 rv += updateConnections (found,
false);
611 QString dName =
"ask_user_output_" + found->
variableId();
612 QString dInputs =
"";
650 if (!dInputs.isEmpty ())
653 dInputs.remove (dInputs.length () - 1, 1);
654 rv +=
"// Ask user for missing input values\n";
655 rv +=
"var " + dName +
" = visualscripting.askForInputs (\"" + found->
element ()->
name ();
656 rv +=
"\", \"" + dInputs +
"\");\n";
659 rv += found->
code ();
664 rv +=
"// --- CODE END ---\n";
667 elements.append (end);
669 if (!elements.isEmpty ())
692 QList<SceneElement *> fixE;
707 errors +=
"<dl><dt>";
710 errors +=
"<b>Function: </b>Main";
714 errors +=
"</dt><dd>";
726 if (errors.endsWith (
", "))
727 errors.remove (errors.length () - 2, 2);
728 errors +=
")</i><br>";
731 if (errors.endsWith (
"<br>"))
732 errors.remove (errors.length () - 4, 4);
734 errors +=
"<dd></dl>";
742 QStringList code = rv.split (
'\n');
746 foreach (QString s, code)
748 if (s.contains (
'}') && !indent.isEmpty ())
749 indent.remove (indent.length () - 2, 2);
750 rv += indent + s +
"\n";
751 if (s.contains (
'{'))
762 QString GraphicsScene::updateConnections (
SceneElement *_from,
bool _isStart)
772 rv +=
"var " + oName +
"\n";
805 bool GraphicsScene::validMimeData(
const QMimeData *_m)
807 return _m->hasFormat (
"application/x-openflipper.vsi");
813 QString GraphicsScene::mimeDataElementName(
const QMimeData *_m)
815 if (!validMimeData (_m))
817 QStringList sl = QString (_m->data (
"application/x-openflipper.vsi")).split (
";");
819 if (sl.length() != 3)
828 QPoint GraphicsScene::mimeDataPoint(
const QMimeData *_m)
830 if (! validMimeData (_m))
831 return QPoint (0, 0);
833 QStringList sl = QString (_m->data (
"application/x-openflipper.vsi")).split (
";");
835 if (sl.length() != 3)
836 return QPoint (0, 0);
839 int x = sl[0].toInt (&ok1);
840 int y = sl[1].toInt (&ok2);
843 return QPoint (0, 0);
845 return QPoint (x, y);
853 QTransform t = elementArea_->transform ();
854 QDomElement s = _doc.createElement(
"transform");
855 _root.appendChild(s);
856 QDomText txt = _doc.createTextNode(
857 QString::number (t.m11 ()) +
"|" + QString::number (t.m12 ()) +
"|" + QString::number (t.m13 ()) +
"|" +
858 QString::number (t.m21 ()) +
"|" + QString::number (t.m22 ()) +
"|" + QString::number (t.m23 ()) +
"|" +
859 QString::number (t.m31 ()) +
"|" + QString::number (t.m32 ()) +
"|" + QString::number (t.m33 ())
863 s = _doc.createElement(
"x");
864 _root.appendChild(s);
865 txt = _doc.createTextNode (QString::number(elementArea_->pos ().x ()));
868 s = _doc.createElement(
"y");
869 _root.appendChild(s);
870 txt = _doc.createTextNode (QString::number(elementArea_->pos ().y ()));
873 QDomElement el = _doc.createElement(
"elements");
874 _root.appendChild(el);
891 if (sl.length () == 9)
894 for (
unsigned int i = 0; i < 9; i++)
896 m[i] = sl[i].toDouble (&ok);
901 elementArea_->setTransform (QTransform (m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]),
false);
909 x = val.toDouble (&ok1);
912 y = val.toDouble (&ok2);
915 elementArea_->setPos (x, y);
917 _xml.setQuery (
"elements/element");
923 _xml.evaluateTo (&el);
924 QXmlItem item (el.next ());
925 while (!item.isNull ())
934 _xml.setQuery (
"elements/element/inputs/input/connection");
938 _xml.evaluateTo (&el);
939 QXmlItem item (el.next ());
940 while (!item.isNull ())
949 QTimer::singleShot(0,
this, SLOT (updateConnections()));
955 void GraphicsScene::loadElement(QXmlQuery & _xml)
958 if (name.isEmpty () || !ctx_->
element (name))
970 void GraphicsScene::loadConnection(QXmlQuery & _xml)
979 inId = inElId.toInt (&ok);
987 outId = outElId.toInt (&ok);
997 else if (e->
element ()->
name () == outEl && e->
id () == outId)
1007 out->dataOut () && out->dataOut ()->inOut ()->name () == outOut)
1010 p2 = out->dataOut ()->connectionPointItem ();
1038 elementArea_->resetTransform ();
1039 elementArea_->setPos (0, 0);
1056 start->setPos(5, (height () - start->size ().height ()) / 2);
1061 end->setPos(width () - end->size ().width () - 5, (height () - end->size ().height ()) / 2);
1068 start->setPos(5, (height () - start->size ().height ()) / 2);
1073 end->setPos(width () - end->size ().width () - 5, (height () - end->size ().height ()) / 2);
1076 dontMoveStart_ =
false;
1082 void GraphicsScene::updateConnections()
1113 dontMoveStart_ =
true;
1118 void VSI::GraphicsScene::sceneResized(
const QRectF & )
1123 blockChanges_ =
true;
1135 if ((!function_ && e->
element ()->
name () ==
"start") ||
1138 if ((!function_ && e->
element ()->
name () ==
"end") ||
1144 start->setPos(5, (height () - start->size ().height ()) / 2);
1146 end->setPos(width () - end->size ().width () - 5, (height () - end->size ().height ()) / 2);
1148 blockChanges_ =
false;
void scaleElements(qreal _delta)
Scale all elements with scaling center in the center of the scene.
InOut * inOut() const
InOut context object.
const QList< SceneElement * > & elements() const
Scene elements.
void loadFromXml(QXmlQuery &_xml)
Load from xml.
void contentChange()
handle content changes
void addElement(SceneElement *_element)
Add a child element.
const QVector< Output * > & outputs() const
Outputs.
SceneElement * element()
The scene element of this function element.
QString generateCode(QString &errors, bool _codeOnly=false)
Generate textual script code (_codeOnly = only pure code block)
const QString & name() const
Name.
QString variableId()
Unique variable name for code generation.
ElementInput * dataIn()
Scene input.
static QString getXmlString(QXmlQuery &_xml, QString _expr, QString _default="")
Gets the string of a xml query.
void updatePositions()
called to update position on element movement
int id()
Unique id for identification.
bool removeElement(SceneElement *_element)
Remove the element from the scene.
ConnectionPoint * connectionPointItem() const
Connection point widget.
QString name() const
Name.
QString code()
Code block.
QRectF elementsBoundingRect()
Bounding rectangle of all scene elements.
QVector< ElementOutput * > outputs()
Outputs.
QString precode() const
Precode segment.
void loadFromXml(QXmlQuery &_xml)
Load from xml.
void moveElements(qreal _dx, qreal _dy, bool _selected=false)
Moves all elements.
SceneElement * element()
Scene element.
ElementOutput * dataOut()
Scene output.
void contentChanged()
Informs about content changes.
Element * end() const
End element of this function (can be NULL)
void mouseMove(QPointF _pos)
Redirect mouse movement to tools area.
void mouseRelease(QPointF _pos, QGraphicsItem *_item)
Redirect mouse release to tools area.
const QString & shortDescription() const
Short description.
void addElement(SceneElement *_element)
Add the element to the scene.
Element * element(QString _name)
Returns the element with a given name.
GraphicsScene(VSI::Context *_ctx, ElementFunction *_function=NULL)
Constructor.
void clearScene(bool _start=false)
clear the whole scene (_start = keep start element)
GraphicsScene * scene()
Scene.
const QString & shortDescription() const
Short description.
QString name() const
Element name.
const QList< SceneElement * > & elements() const
All elements.
bool removeElement(SceneElement *_element, bool _force=false)
Remove an element, if its removeable or _force is set.
qreal getNewZ()
Returns a new Z value that is above all elements.
void saveToXml(QDomDocument &_doc, QDomElement &_root)
Save to xml.
ElementInput * input()
Input of this connection.
Element * start() const
Start element of this function.
QVector< ElementFunction * > functions()
Functions.
Element * element() const
Context VSI::Element.
void resetCodeGeneration()
Reset code block for code generation.
Function * function()
Function class.
~GraphicsScene()
Destructor.
void replaceCodeBlock(QString _name, QString _id, QString _value)
Replace block with name _name and id _id with _value.
QVector< ElementInput * > inputs()
Inputs.
void saveToXml(QDomDocument &_doc, QDomElement &_root)
Save to xml.
QList< Connection * > connections() const
Connections.
const QString & shortDescription() const
Short description.