Developer Documentation
sceneElement.cc
1/*===========================================================================*\
2* *
3* OpenFlipper *
4 * Copyright (c) 2001-2015, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openflipper.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenFlipper. *
11 *---------------------------------------------------------------------------*
12 * *
13 * Redistribution and use in source and binary forms, with or without *
14 * modification, are permitted provided that the following conditions *
15 * are met: *
16 * *
17 * 1. Redistributions of source code must retain the above copyright notice, *
18 * this list of conditions and the following disclaimer. *
19 * *
20 * 2. Redistributions in binary form must reproduce the above copyright *
21 * notice, this list of conditions and the following disclaimer in the *
22 * documentation and/or other materials provided with the distribution. *
23 * *
24 * 3. Neither the name of the copyright holder nor the names of its *
25 * contributors may be used to endorse or promote products derived from *
26 * this software without specific prior written permission. *
27 * *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39* *
40\*===========================================================================*/
41
42
43
44//== INCLUDES =================================================================
45#include <QWidget>
46#include <QVBoxLayout>
47#include <QLabel>
48#include <QMessageBox>
49#include <QPainter>
50#include <QGraphicsSceneMouseEvent>
51#include <QGraphicsLinearLayout>
52#include <QGraphicsProxyWidget>
53#include <QGraphicsGridLayout>
54#include <QGraphicsView>
55#include <QRegularExpression>
56
57#include <QDomText>
58
59#include "sceneElement.hh"
60#include "graphicsScene.hh"
61
62#include "text.hh"
63#include "button.hh"
64#include "connectionPoint.hh"
65#include "connection.hh"
66
67#include "elementInput.hh"
68#include "elementOutput.hh"
69#include "elementFunction.hh"
70
71#include "config/configDialog.hh"
72
73#include "../parser/element.hh"
74#include "../parser/context.hh"
75#include "../parser/function.hh"
76
77#define BACKGROUND_RED 0x00
78#define BACKGROUND_GREEN 0x00
79#define BACKGROUND_BLUE 0x00
80#define BACKGROUND_ALPHA 0xff
81
82#define SELECTED_BACKGROUND_RED 0x00
83#define SELECTED_BACKGROUND_GREEN 0x00
84#define SELECTED_BACKGROUND_BLUE 0x6f
85#define SELECTED_BACKGROUND_ALPHA 0xff
86
87//== NAMESPACES ===============================================================
88namespace VSI {
89
90//=============================================================================
91//
92// CLASS VSI::SceneElement - IMPLEMENTATION
93//
94//=============================================================================
95
96
98 scene_ (_scene),
99 element_ (_element),
100 dataIn_ (0),
101 dataOut_ (0),
102 id_ (_element->getNewId ())
103{
104 int index = 1;
105 bool hasConfig = false;
106
107 QGraphicsLinearLayout *layout = new QGraphicsLinearLayout (Qt::Vertical);
108 layout->setSpacing (0);
109
110 nameLayout_ = new QGraphicsLinearLayout (Qt::Vertical);
111 nameLayout_->setSpacing(0);
112 nameLayout_->setContentsMargins(15, 0, 15, 0);
113 // add name text
114 name_ = new Text (element_->shortDescription (), this);
115
116 name_->setAlignment (Qt::AlignHCenter);
117
118 QFont font = name_->font ();
119 if (font.pointSize () != -1)
120 font.setPointSize (font.pointSize () + 1);
121 else
122 font.setPixelSize (font.pixelSize () + 1);
123 font.setBold (true);
124 name_->setFont (font);
125
126 nameLayout_->addItem(name_);
127 nameLayout_->setAlignment (name_, Qt::AlignCenter);
128
129 elementName_ = new Text (element_->shortDescription (), this);
130 font = elementName_->font ();
131 if (font.pointSize () != -1)
132 font.setPointSize (font.pointSize () - 2);
133 else
134 font.setPixelSize (font.pixelSize () - 2);
135 elementName_->setFont (font);
136
137 nameLayout_->addItem(elementName_);
138 nameLayout_->setAlignment (elementName_, Qt::AlignCenter);
139
140 elementName_->hide ();
141
142 layout->addItem(nameLayout_);
143 layout->setAlignment (nameLayout_, Qt::AlignCenter);
144
145 // add inputs
146 QGraphicsGridLayout *inGrid = new QGraphicsGridLayout;
147 inGrid->setContentsMargins (0,0,5,0);
148 int row = 0;
149 qreal typeWidth = 0;
150 qreal height = 1000;
151
152 foreach (Input *in, element_->inputs ())
153 {
154 ElementInput *i = new ElementInput (in, this);
155 inputs_.append (i);
156
157 if (!(in->state () & Input::NoUserInput))
158 {
159 hasConfig = true;
160 configInputs_.append (i);
161 }
162
163 if (in->state () & Input::NoExternalInput)
164 {
165 i->connectionPointItem ()->hide ();
166 i->typeTextItem ()->hide ();
167 i->descriptionTextItem ()->hide ();
168 continue;
169 }
170
171 inGrid->addItem (i->connectionPointItem (), row, 0, Qt::AlignLeft | Qt::AlignVCenter);
172 inGrid->addItem (i->typeTextItem (), row, 1, Qt::AlignLeft | Qt::AlignVCenter);
173 inGrid->addItem (i->descriptionTextItem (), row, 2, Qt::AlignLeft | Qt::AlignVCenter);
174
175 height = qMin (height, i->typeTextItem ()->preferredHeight () / 2);
176 typeWidth = qMax (i->typeTextItem ()->preferredWidth (), typeWidth);
177 row ++;
178 }
179
180 if (!element_->inputs ().isEmpty ())
181 {
182 inGrid->setColumnMinimumWidth (1, qMin (typeWidth, 100.0));
183 inGrid->setHorizontalSpacing (1);
184 layout->insertItem (index, inGrid);
185 layout->setAlignment (inGrid, Qt::AlignLeft);
186 layout->setItemSpacing (index - 1, 10);
187 index++;
188 }
189
190 // add outputs
191 QGraphicsGridLayout *outGrid = new QGraphicsGridLayout;
192 outGrid->setContentsMargins (5,0,0,0);
193 row = 0;
194 typeWidth = 0;
195 height = 1000;
196
197 foreach (Output *out, element_->outputs ())
198 {
199 ElementOutput *o = new ElementOutput (out, this);
200
201 outGrid->addItem (o->connectionPointItem (), row, 2, Qt::AlignRight | Qt::AlignVCenter);
202 outGrid->addItem (o->typeTextItem (), row, 1, Qt::AlignRight | Qt::AlignVCenter);
203 outGrid->addItem (o->descriptionTextItem (), row, 0, Qt::AlignRight | Qt::AlignVCenter);
204
205 height = qMin (height, o->typeTextItem ()->preferredHeight () / 2);
206 typeWidth = qMax (o->typeTextItem ()->preferredWidth (), typeWidth);
207 row ++;
208
209 outputs_.append (o);
210 }
211
212 if (!element_->outputs ().isEmpty ())
213 {
214 outGrid->setColumnMinimumWidth (1, qMin (typeWidth, 100.0));
215 outGrid->setHorizontalSpacing (1);
216 layout->insertItem(index, outGrid);
217 layout->setAlignment (outGrid, Qt::AlignRight);
218 layout->setItemSpacing (index - 1, 10);
219 index++;
220 }
221
222 if (hasConfig || !element_->functions ().isEmpty ())
223 {
224 QGraphicsLinearLayout *hl = new QGraphicsLinearLayout (Qt::Horizontal);
225 QGraphicsLinearLayout *vl = new QGraphicsLinearLayout (Qt::Vertical);
226 hl->setContentsMargins(15, 0, 15, 0);
227
228 // add input config button
229 if (hasConfig)
230 {
231 Button *configButton = new Button ("Configure", this);
232 configButton->setBrush (Qt::black);
233 configButton->setBackgroundBrush (Qt::lightGray);
234 configButton->setBackground (true, true);
235 configButton->setHorizontalStretch (true);
236 configButton->setAlignment (Qt::AlignHCenter);
237
238 vl->addItem (configButton);
239
240 connect (configButton, SIGNAL (pressed()), this, SLOT (showInputConfig()));
241 }
242
243 // add function edit buttons
244 foreach (Function *f, element_->functions ())
245 {
246 ElementFunction *ef = new ElementFunction (f, this);
247
248 Button *config = new Button ("Edit:" + f->shortDescription (), this);
249 config->setBrush (Qt::black);
250 config->setBackgroundBrush (Qt::lightGray);
251 config->setBackground (true, true);
252 config->setAlignment (Qt::AlignHCenter);
253
254 vl->addItem (config);
255
256 connect (config, SIGNAL (pressed()), ef, SLOT (editFunction ()));
257
258 functions_.append (ef);
259 }
260
261 hl->addStretch ();
262 hl->addItem (vl);
263 hl->addStretch ();
264
265 layout->insertItem (index, hl);
266 layout->setAlignment (hl, Qt::AlignCenter);
267 layout->setItemSpacing (index - 1, 10);
268 index++;
269 }
270
271 // add scenegraph input / output
272 if (element_->dataOut () || element_->dataIn ())
273 {
274 QGraphicsGridLayout *sIO = new QGraphicsGridLayout ();
275 int col = 0;
276 int lo = 0, ro = 0;
277
278 // Start node has no scene graph input
279 if (element_->dataIn ())
280 {
281 dataIn_ = new ElementInput (element_->dataIn (), this);
282 dataIn_->typeTextItem ()->hide ();
283 sIO->addItem (dataIn_->connectionPointItem (), 0, col++, Qt::AlignLeft | Qt::AlignVCenter);
284 sIO->addItem (dataIn_->descriptionTextItem (), 0, col++, Qt::AlignCenter);
285 } else
286 lo = 5;
287
288 if (element_->dataOut ())
289 {
290 dataOut_ = new ElementOutput (element_->dataOut (), this);
291 dataOut_->typeTextItem ()->hide ();
292 if (dataIn_)
293 {
294 dataOut_->descriptionTextItem ()->hide ();
295 dataIn_->descriptionTextItem ()->setBackground (false, false);
296 dataIn_->descriptionTextItem ()->setAlignment (Qt::AlignHCenter);
297 }
298 else
299 {
300 sIO->addItem (dataOut_->descriptionTextItem (), 0, col++, Qt::AlignCenter);
301 }
302 sIO->addItem (dataOut_->connectionPointItem (), 0, col, Qt::AlignRight | Qt::AlignVCenter);
303 } else
304 ro = 5;
305
306 sIO->setContentsMargins (lo, 0, ro, 0);
307 sIO->setHorizontalSpacing (1);
308
309 layout->insertItem (index, sIO);
310 layout->setAlignment (sIO, Qt::AlignCenter);
311 layout->setItemSpacing (index - 1, 10);
312 index++;
313 }
314
315 layout->setItemSpacing (0, 1);
316
317 layout->setContentsMargins (0, 2, 0, 6);
318
319 setLayout (layout);
320
321 if (layout->preferredWidth() < 200)
322 setMinimumWidth (layout->preferredWidth());
323 else
324 setMinimumWidth (200);
325
326 setZValue (scene_->getNewZ ());
327
328 setFlag (QGraphicsItem::ItemIsSelectable, true);
329 setFlag (QGraphicsItem::ItemIsMovable, true);
330
331 setMaximumWidth (200);
332
333 setToolTip (element_->longDescription ());
334}
335
336//------------------------------------------------------------------------------
337
340{
341 foreach (ElementInOut *e, inputs_)
342 delete e;
343 foreach (ElementInOut *e, outputs_)
344 delete e;
345
346 if (dataIn_)
347 delete dataIn_;
348 if (dataOut_)
349 delete dataOut_;
350}
351
352//------------------------------------------------------------------------------
353
355void SceneElement::paint (QPainter *_painter, const QStyleOptionGraphicsItem *_option, QWidget *_widget)
356{
357 int w = geometry().width() - 20;
358 int h = geometry().height();
359
360 _painter->setRenderHint(QPainter::Antialiasing, true);
361 if (isSelected ())
362 _painter->setBrush(QBrush(QColor(SELECTED_BACKGROUND_RED,
363 SELECTED_BACKGROUND_GREEN,
364 SELECTED_BACKGROUND_BLUE,
365 SELECTED_BACKGROUND_ALPHA)));
366 else
367 _painter->setBrush(QBrush(QColor(BACKGROUND_RED,
368 BACKGROUND_GREEN,
369 BACKGROUND_BLUE,
370 BACKGROUND_ALPHA)));
371
372 _painter->setPen (Qt::NoPen);
373 _painter->drawRoundedRect(10, 0, w, h, 5, 5);
374
375 float wH = w / 2.0;
376 float wT = w / 3.0;
377
378 QPainterPath path;
379 QRadialGradient rG;
380 QLinearGradient lG;
381
382 path.moveTo (10, 20);
383 path.lineTo (10, 5);
384 path.arcTo (10, 0, 10, 10, 180, -90);
385 path.lineTo (w + 6, 0);
386 path.arcTo (w, 0, 10, 10, 90, -90);
387 path.lineTo (w + 10, 10);
388
389 path.cubicTo (QPointF (10 + wH, 10), QPointF (10 + wH, 20), QPointF (10, 20));
390
391 rG.setCenter (10 + wT, 0);
392 rG.setFocalPoint(10 + wT, 0);
393 rG.setRadius (w);
394 rG.setColorAt(0, QColor (255, 255, 255, 128));
395 rG.setColorAt(1, Qt::transparent);
396 _painter->setBrush (rG);
397 _painter->setPen (Qt::NoPen);
398 _painter->drawPath(path);
399
400 path = QPainterPath ();
401 path.moveTo (w + 5, 0);
402 path.arcTo (w, 0, 10, 10, 90, -90);
403 path.lineTo (w + 10, h - 5);
404 path.lineTo (w + 5, h - 5);
405 path.lineTo (w + 5, 0);
406
407 lG.setStart (w + 5, 0);
408 lG.setFinalStop(w + 10, 0);
409 lG.setColorAt(0, Qt::transparent);
410 lG.setColorAt(1, QColor (255, 255, 255, 128));
411 _painter->setBrush (lG);
412 _painter->drawPath(path);
413
414 path = QPainterPath ();
415 path.moveTo (10, h - 5);
416 path.arcTo (10, h - 10, 10, 10, 180, 90);
417 path.lineTo (w + 5, h);
418 path.lineTo (w + 5, h - 5);
419 path.lineTo (10, h - 5);
420 lG.setStart (0, h - 5);
421 lG.setFinalStop (0, h);
422 _painter->setBrush (lG);
423 _painter->drawPath (path);
424
425 path = QPainterPath ();
426 path.moveTo (w + 5, h);
427 path.arcTo (w, h - 10, 10, 10, -90, 90);
428 path.lineTo (w + 5, h - 5);
429 path.lineTo (w + 5, h);
430 rG.setCenter (w + 5, h - 5);
431 rG.setFocalPoint(w + 5, h - 5);
432 rG.setRadius (5);
433 rG.setColorAt (0, Qt::transparent);
434 rG.setColorAt (1, QColor (255, 255, 255, 128));
435 _painter->setBrush (rG);
436 _painter->drawPath(path);
437
438 QGraphicsWidget::paint (_painter, _option, _widget);
439}
440
441//------------------------------------------------------------------------------
442
443// Start draging on mouse press
444void SceneElement::mousePressEvent (QGraphicsSceneMouseEvent *_event)
445{
446 QGraphicsWidget::mousePressEvent (_event);
447 setZValue (scene_->getNewZ ());
448}
449
450//------------------------------------------------------------------------------
451
452// move all selected elements
453void SceneElement::mouseMoveEvent (QGraphicsSceneMouseEvent *_event)
454{
455 QGraphicsWidget::mouseMoveEvent (_event);
456}
457
458//------------------------------------------------------------------------------
459
460// stop moving
461void SceneElement::mouseReleaseEvent (QGraphicsSceneMouseEvent *_event)
462{
463 QGraphicsWidget::mouseReleaseEvent (_event);
464 scene_->mouseRelease (_event->scenePos (), this);
465}
466
467//------------------------------------------------------------------------------
468
470void SceneElement::mouseDoubleClickEvent (QGraphicsSceneMouseEvent *_event)
471{
472 QPointF _scenePos = _event->scenePos ();
473 if (name_->boundingRect ().contains (name_->mapFromScene (_scenePos)) ||
474 elementName_->boundingRect ().contains (elementName_->mapFromScene (_scenePos)))
475 {
476 ConfigDialog d (QVector<ElementInput *> (), name_->text (), scene ()->views ()[0]);
477 d.setWindowTitle ("Element Name Configuration");
478 if (d.exec () == QDialog::Accepted)
479 {
480 if (d.name ().isEmpty())
481 name_->setText (element_->shortDescription ());
482 else
483 name_->setText (d.name ());
484
485 if (name_->text () == element_->shortDescription ())
486 elementName_->hide ();
487 else
488 elementName_->show ();
489
490 nameLayout_->invalidate ();
491 }
492 return;
493 }
494
495 foreach (ElementInput *i, inputs_)
496 {
497 bool click = false;
498 if (i->connectionPointItem ()->isVisible () &&
499 i->connectionPointItem ()->shape ().contains (i->connectionPointItem ()->mapFromScene (_scenePos)))
500 click = true;
501 if (i->typeTextItem ()->isVisible () &&
502 i->typeTextItem ()->shape ().contains (i->typeTextItem ()->mapFromScene (_scenePos)))
503 click = true;
504 if (i->descriptionTextItem ()->isVisible () &&
505 i->descriptionTextItem ()->shape ().contains (i->descriptionTextItem ()->mapFromScene (_scenePos)))
506 click = true;
507
508 if (!click)
509 continue;
510
511 if (configInputs_.contains (i))
512 {
513 QVector<ElementInput *> inputs;
514 inputs.append (i);
515
516 ConfigDialog d (inputs, QString (), scene ()->views ()[0]);
517 d.setWindowTitle (i->inOut ()->shortDescription () + " Configuration");
518 d.exec ();
519 } else
520 {
521 QMessageBox msgBox (scene ()->views ()[0]);
522 msgBox.setText("No configuration available.");
523 msgBox.exec();
524 }
525 }
526
527}
528
529//------------------------------------------------------------------------------
530
531// update connection on move
532void SceneElement::moveEvent (QGraphicsSceneMoveEvent *_event)
533{
534 QGraphicsWidget::moveEvent (_event);
535
536 foreach (ElementInput *e, inputs_)
537 foreach (Connection *c, e->connections ())
538 c->updatePositions ();
539
540 foreach (ElementOutput *e, outputs_)
541 foreach (Connection *c, e->connections ())
542 c->updatePositions ();
543
544 if (dataIn_) {
545 foreach (Connection *c, dataIn_->connections ())
546 c->updatePositions ();
547 }
548
549 if (dataOut_) {
550 foreach (Connection *c, dataOut_->connections ())
551 c->updatePositions ();
552 }
553
554 scene_->contentChange ();
555}
556
557//------------------------------------------------------------------------------
558
561{
562 foreach (ElementInput *i, inputs ())
563 i->setValid (false);
564 if (dataIn ())
565 dataIn ()->setValid (false);
566
567 code_ = element_->code ();
568}
569
570//------------------------------------------------------------------------------
571
573void SceneElement::replaceCodeBlock(const QString& _name, const QString& _id, const QString& _value)
574{
575 QString regex = "\\[\\s*" + _name + "\\s*=\\s*\"" + _id + "\"\\s*\\]";
576 code_ = code_.replace (QRegularExpression (regex), _value);
577}
578
579//------------------------------------------------------------------------------
580
583{
584 return element_->name () + "_" + QString::number (id_);
585}
586
587//------------------------------------------------------------------------------
588
589// show input configuration dialog
590void SceneElement::showInputConfig()
591{
592 ConfigDialog d (configInputs_, name_->text (), scene ()->views ()[0]);
593 d.setWindowTitle (name_->text () + " Input Configuration");
594 if (d.exec () == QDialog::Accepted)
595 {
596 if (d.name ().isEmpty())
597 name_->setText (element_->shortDescription ());
598 else
599 name_->setText (d.name ());
600
601 if (name_->text () == element_->shortDescription ())
602 elementName_->hide ();
603 else
604 elementName_->show ();
605
606 nameLayout_->invalidate ();
607 }
608}
609
610//------------------------------------------------------------------------------
611
614{
615 foreach (ElementOutput *o, outputs_)
616 {
617 foreach (Connection *c, o->connections ())
618 {
619 if (c->input ()->element () == _e)
620 return true;
621 bool rv = c->input ()->element ()->isBefore (_e);
622 if (rv)
623 return true;
624 }
625 }
626
627 if (dataOut ()) {
628 foreach (Connection *c, dataOut ()->connections ())
629 {
630 if (c->input ()->element () == _e)
631 return true;
632 bool rv = c->input ()->element ()->isBefore (_e);
633 if (rv)
634 return true;
635 }
636 }
637 return false;
638}
639
640//------------------------------------------------------------------------------
641
644{
645 foreach (ElementInput *i, inputs_)
646 {
647 foreach (Connection *c, i->connections ())
648 {
649 if (c->output ()->element () == _e)
650 return true;
651 bool rv = c->output ()->element ()->isAfter (_e);
652 if (rv)
653 return true;
654 }
655 }
656
657 if (dataIn ()) {
658 foreach (Connection *c, dataIn ()->connections ())
659 {
660 if (c->output ()->element () == _e)
661 return true;
662 bool rv = c->output ()->element ()->isAfter (_e);
663 if (rv)
664 return true;
665 }
666 }
667 return false;
668}
669
670//------------------------------------------------------------------------------
671
672// invalidate (reset) all connections of this element
673void VSI::SceneElement::invalidateConnections()
674{
675
676 foreach (ElementInput *e, inputs_)
677 foreach (Connection *c, e->connections ())
678 c->invalidate ();
679
680 foreach (ElementOutput *e, outputs_)
681 foreach (Connection *c, e->connections ())
682 c->invalidate ();
683
684 if (dataIn_) {
685 foreach (Connection *c, dataIn_->connections ())
686 c->invalidate ();
687 }
688
689 if (dataOut_) {
690 foreach (Connection *c, dataOut_->connections ())
691 c->invalidate ();
692 }
693}
694
695//------------------------------------------------------------------------------
696
698void SceneElement::saveToXml(QDomDocument & _doc, QDomElement & _root)
699{
700 QDomText t;
701
702 QDomElement main = _doc.createElement("element");
703 _root.appendChild(main);
704 main.setAttribute ("name",element_->name ());
705
706 if (name_->text () != element_->shortDescription ())
707 {
708 QDomElement name = _doc.createElement("visible_name");
709 main.appendChild(name);
710 t = _doc.createTextNode(name_->text ());
711 name.appendChild(t);
712 }
713
714 QDomElement id = _doc.createElement("id");
715 main.appendChild(id);
716 t = _doc.createTextNode(QString::number (id_));
717 id.appendChild(t);
718
719 QDomElement px = _doc.createElement("x");
720 main.appendChild(px);
721 t = _doc.createTextNode(QString::number (pos ().x ()));
722 px.appendChild(t);
723
724 QDomElement py = _doc.createElement("y");
725 main.appendChild(py);
726 t = _doc.createTextNode(QString::number (pos ().y ()));
727 py.appendChild(t);
728
729 if (!inputs_.isEmpty() || dataIn_)
730 {
731 QDomElement inputs = _doc.createElement("inputs");
732 main.appendChild(inputs);
733 foreach (ElementInput *i, inputs_)
734 i->saveToXml (_doc, inputs);
735 if (dataIn_)
736 dataIn_->saveToXml (_doc, inputs);
737 }
738 if (!functions_.isEmpty ())
739 {
740 QDomElement functions = _doc.createElement("functions");
741 main.appendChild(functions);
742 foreach (ElementFunction *ef, functions_)
743 ef->saveToXml (_doc, functions);
744 }
745}
746
747//------------------------------------------------------------------------------
748
750void SceneElement::loadFromXml(QDomElement& _domElement,std::vector<QString>& _connections)
751{
752 bool ok1, ok2;
753 int id;
754 double x, y;
755 QString val;
756
757 val = Context::getXmlString (_domElement, "visible_name");
758
759 if (!val.isEmpty ())
760 name_->setText (val);
761
762 if (name_->text () == element_->shortDescription ())
763 elementName_->hide ();
764 else
765 elementName_->show ();
766
767 nameLayout_->invalidate ();
768
769 val = Context::getXmlString (_domElement, "id");
770
771 id = val.toUInt (&ok1);
772
773 if (ok1)
774 {
775 id_ = id;
776 element_->setMinId(id + 1);
777 }
778
779 val = Context::getXmlString (_domElement, "x");
780 x = val.toDouble (&ok1);
781
782 val = Context::getXmlString (_domElement, "y");
783 y = val.toDouble (&ok2);
784
785 if (ok1 && ok2)
786 setPos (x, y);
787
788 // Search through all children of the current element if we have inputs, outputs or functions
789 for(QDomElement n = _domElement.firstChildElement(); !n.isNull(); n = n.nextSiblingElement() )
790 {
791 // Found an input Tag!
792 if (n.tagName() == "inputs") {
793
794 // Iterate over all inputs inside it
795 for(QDomElement inputElement = n.firstChildElement(); !inputElement.isNull(); inputElement = inputElement.nextSiblingElement() )
796 {
797 val = inputElement.attribute("name");
798
799
800 if (!val.isEmpty())
801 {
802 if (val == "data" && dataIn_) {
803 dataIn_->loadElementInputFromXml(inputElement);
804 } else
805 {
806 foreach (ElementInput *i, inputs_)
807 if (i->inOut()->name () == val)
808 {
809 i->loadElementInputFromXml(inputElement);
810 break;
811 }
812 }
813
814 // Iterate over all inputs and read the connection info
815 for(QDomElement connectionElement = inputElement.firstChildElement(); !connectionElement.isNull(); connectionElement = connectionElement.nextSiblingElement() )
816 {
817 if (connectionElement.tagName() == "connection") {
818 QString tmp = _domElement.attribute("name") + ";"+ Context::getXmlString (_domElement, "id") + ";" + inputElement.attribute("name") + ";" + connectionElement.attribute("element") + ";" + connectionElement.attribute("element_id") + ";" + connectionElement.attribute("output");
819 _connections.push_back(tmp);
820 }
821 }
822 }
823 }
824 }
825
826 // Found an function Tag!
827 if (n.tagName() == "functions") {
828
829 // Iterate over all functions inside it
830 for(QDomElement functionElement = n.firstChildElement(); !functionElement.isNull(); functionElement = functionElement.nextSiblingElement() )
831 {
832 val = functionElement.attribute("name");
833
834 if (!val.isEmpty())
835 {
836 foreach (ElementFunction *ef, functions_)
837 if (ef->function ()->name () == val)
838 {
839 ef->loadElementFunctionFromXml (functionElement);
840 break;
841 }
842 }
843 }
844
845 }
846
847 }
848
849}
850
851//------------------------------------------------------------------------------
852}
853
854
855
void setBackgroundBrush(QBrush _brush) override
Sets the background brush.
Definition: button.cc:143
QString name()
return entered name
ElementInput * input()
Input of this connection.
Definition: connection.cc:239
void updatePositions()
called to update position on element movement
Definition: connection.cc:232
void invalidate()
invalidate way
Definition: connection.cc:263
ElementOutput * output()
Output of this connection.
Definition: connection.cc:248
static QString getXmlString(QDomElement &_element, const QString &_tag, QString _default="")
Gets the string of a xml query.
Definition: context.cc:514
void loadElementFunctionFromXml(QDomElement &_domElement)
Load from xml.
void saveToXml(QDomDocument &_doc, QDomElement &_root)
Save to xml.
Function * function()
Function class.
Text * descriptionTextItem() const
Short description widget.
Definition: elementInOut.hh:95
Text * typeTextItem() const
Type text widget.
Definition: elementInOut.hh:92
InOut * inOut() const
InOut context object.
QList< Connection * > connections() const
Connections.
Definition: elementInOut.hh:98
SceneElement * element()
Scene element.
ConnectionPoint * connectionPointItem() const
Connection point widget.
Definition: elementInOut.hh:89
void setValid(bool _value)
Sets the valid flag (needed during code generation)
Definition: elementInput.hh:80
void saveToXml(QDomDocument &_doc, QDomElement &_root)
Save to xml.
void loadElementInputFromXml(QDomElement &_domElement)
Load from xml.
Output * dataOut()
Scenegraph output.
Definition: element.hh:106
const QString & shortDescription() const
Short description.
Definition: element.hh:88
const QVector< Input * > & inputs() const
Inputs.
Definition: element.hh:94
QString name() const
Element name.
Definition: element.hh:82
QString code() const
Code segment.
Definition: element.hh:115
const QVector< Function * > & functions() const
Functions.
Definition: element.hh:100
const QString & longDescription() const
Long description.
Definition: element.hh:91
void setMinId(unsigned int _id)
sets the minimum for an unused id
Definition: element.cc:100
const QVector< Output * > & outputs() const
Outputs.
Definition: element.hh:97
Input * dataIn()
Scenegraph input.
Definition: element.hh:103
const QString & shortDescription() const
Short description.
Definition: function.hh:84
QString name() const
Name.
Definition: function.hh:81
void contentChange()
handle content changes
qreal getNewZ()
Returns a new Z value that is above all elements.
void mouseRelease(QPointF _pos, QGraphicsItem *_item)
Redirect mouse release to tools area.
const QString & shortDescription() const
Short description.
Definition: inout.hh:73
const QString & name() const
Name.
Definition: inout.hh:70
QString variableId()
Unique variable name for code generation.
~SceneElement()
Destructor.
SceneElement(GraphicsScene *_scene, Element *_element)
Constructor.
Definition: sceneElement.cc:97
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *_event)
Double click occured. We can't use mouseDoubleClickEvent because we won't get one for the ConecctionP...
void paint(QPainter *_painter, const QStyleOptionGraphicsItem *_option, QWidget *_widget=0)
Background painting.
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.
Definition: sceneElement.hh:99
bool isBefore(SceneElement *_e)
Will this element be executed before _e bacause of its connections?
void resetCodeGeneration()
Reset code block for code generation.
ElementOutput * dataOut()
Scene output.
bool isAfter(SceneElement *_e)
Will this element be executed after _e bacause of its connections?
QVector< ElementFunction * > functions()
Functions.
Definition: sceneElement.hh:96
int id()
Unique id for identification.
QVector< ElementInput * > inputs()
Inputs.
Definition: sceneElement.hh:90
virtual QRectF boundingRect() const
Bounding rectangle.
Definition: text.cc:342
QString text()
Get displayed text.
Definition: text.hh:121
void setAlignment(Qt::Alignment _alignment)
Placement of the text in a stretched widget.
Definition: text.cc:311
void setText(QString _text)
Set displayed text.
Definition: text.hh:118
void setHorizontalStretch(bool _stretch)
Should this widget be stretchable in horizontal direction.
Definition: text.cc:324
void setBackground(bool _leftOut, bool _rightOut)
Enables background painting.
Definition: text.cc:300
QPainterPath shape() const
Returns the shape for proper repainting/event handling.
Definition: text.cc:397