Salome HOME
f1285362488b36f7189be88bb877d355f114f757
[modules/yacs.git] / src / genericgui / SceneHeaderNodeItem.cxx
1 // Copyright (C) 2006-2023  CEA, EDF
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "SceneHeaderNodeItem.hxx"
21 #include "SceneComposedNodeItem.hxx"
22 #include "SceneProcItem.hxx"
23 #include "SceneCtrlInPortItem.hxx"
24 #include "SceneCtrlOutPortItem.hxx"
25 #include "SceneInPortItem.hxx"
26 #include "SceneOutPortItem.hxx"
27 #include "Scene.hxx"
28
29 #include "QtGuiContext.hxx"
30 #include "GuiEditor.hxx"
31 #include "Resource.hxx"
32 #include "Menus.hxx"
33 #include <QGraphicsSceneHoverEvent>
34 #include <QGraphicsSceneMouseEvent>
35 #include <QPointF>
36
37 #include <cassert>
38
39 //#define _DEVDEBUG_
40 #include "YacsTrace.hxx"
41
42 using namespace std;
43 using namespace YACS::ENGINE;
44 using namespace YACS::HMI;
45
46 SceneHeaderNodeItem::SceneHeaderNodeItem(QGraphicsScene *scene, SceneItem *parent,
47                                          QString label)
48   : SceneHeaderItem(scene, parent, label)
49 {
50    _fatherNode= dynamic_cast<SceneNodeItem*>(parent);
51   _width  = 2*Resource::Corner_Margin + 2*Resource::DataPort_Width + Resource::Space_Margin;
52   _height = Resource::Header_Height;
53   _maxPorts = 0;
54
55   _header = 0;
56   _controlIn = 0;
57   _controlOut = 0;
58   _label = "H_" + _label;
59   _hasHeader = true;
60
61   _controlIn = new SceneCtrlInPortItem(_scene, this, "in");
62   _controlIn->setTopLeft(QPointF(Resource::Corner_Margin, Resource::Corner_Margin));
63
64   _header = new SceneHeaderItem(_scene, this, "header_"+_label);
65   _header->setText(label);
66   _header->setTopLeft(QPointF(Resource::Corner_Margin + Resource::CtrlPort_Width + Resource::Space_Margin, Resource::Corner_Margin));
67
68   _controlOut = new SceneCtrlOutPortItem(_scene, this, "out");
69   _controlOut->setTopLeft(QPointF(Resource::Corner_Margin + 2*Resource::DataPort_Width + Resource::Space_Margin - Resource::CtrlPort_Width, Resource::Corner_Margin));
70
71   if (QtGuiContext::getQtCurrent()->isEdition())
72     _brushColor = Resource::normalNodeBrushColor;
73   else
74     _brushColor = Resource::runNodeBrushColor;
75   _execState = YACS::UNDEFINED;
76   _sc = Resource::validNodeColor;
77   _stateDef = "";
78   _isProc = dynamic_cast<SceneProcItem*>(_parent);
79   _isValid = true;
80   _isEdited = false;
81 }
82
83 SceneHeaderNodeItem::~SceneHeaderNodeItem()
84 {
85 }
86
87 void SceneHeaderNodeItem::paint(QPainter *painter,
88                                 const QStyleOptionGraphicsItem *option,
89                                 QWidget *widget)
90 {
91   //DEBTRACE("SceneHeaderNodeItem::paint");
92   painter->save();
93
94   int x = Resource::Border_Margin + 1;
95   int y = Resource::Header_Height - Resource::Line_Space;
96   if (_fatherNode && _fatherNode->hasProgressBar())
97     y += Resource::progressBar_Height;
98   int w = Resource::Corner_Margin + 2*Resource::DataPort_Width + 2*Resource::Space_Margin;
99   if (_parent->getWidth() > w) w = _parent->getWidth() - Resource::Border_Margin;
100   QPen pen(getPenColor());
101   pen.setWidth(Resource::Line_Width);
102   painter->setPen(pen);
103   painter->drawLine(x, y, w, y);
104
105   x = Resource::Corner_Margin + Resource::CtrlPort_Width + Resource::Space_Margin;
106   y = Resource::Corner_Margin;
107   w = w - 2*Resource::CtrlPort_Width - 3*Resource::Space_Margin - Resource::Corner_Margin;
108   int h = Resource::CtrlPort_Height;
109   pen.setWidth(Resource::Thickness);
110   painter->setPen(pen);
111   
112   bool expanded = (_fatherNode && _fatherNode->isExpanded());
113   QColor baseColor = getBrushColor();
114   if (expanded)
115     painter->setBrush(baseColor);
116   else
117     {
118        int h, s, v, a, h2;
119        baseColor.getHsv(&h, &s, &v, &a);
120        DEBTRACE("h="<<h<<" s="<<s<<" v="<<v);
121        h2 = h+60;
122        if (h>359) h2 = h2-359;
123        QLinearGradient gradient;
124        gradient.setCoordinateMode(QGradient::ObjectBoundingMode);
125        gradient.setColorAt(0, baseColor.darker(200));
126        //gradient.setColorAt(1, baseColor.lighter(150));
127        //gradient.setColorAt(0, QColor::fromHsv(h-60, s, v, a));
128        gradient.setColorAt(1, QColor::fromHsv(h2, s, v, a));
129        QBrush brush(gradient);
130        painter->setBrush(brush);
131     }
132   painter->drawRoundedRect(QRect(x, y, w, h), Resource::Radius, Resource::Radius);
133
134   painter->restore();
135 }
136
137 void SceneHeaderNodeItem::setText(QString label)
138 {
139   if (_header) _header->setText(label);
140 }
141
142 qreal SceneHeaderNodeItem::getHeaderBottom() const
143 {
144   qreal res = 0;
145   if (_hasHeader) {
146     res += Resource::Header_Height + _maxPorts * (Resource::DataPort_Height + Resource::Space_Margin);
147     if (_fatherNode && _fatherNode->hasProgressBar())
148       res += Resource::progressBar_Height;
149   }
150   return res;
151 }
152
153 void SceneHeaderNodeItem::autoPosControl(AbstractSceneItem *item)
154 {
155 }
156
157 void SceneHeaderNodeItem::autoPosNewPort(AbstractSceneItem *item)
158 {
159   DEBTRACE("SceneHeaderNodeItem::autoPosNewPort");
160   SceneInPortItem* inPortItem = dynamic_cast<SceneInPortItem*>(item);
161
162   int nbPorts;
163   qreal xLeft;
164   if (inPortItem) {
165     xLeft = Resource::Corner_Margin;
166     nbPorts = _inPorts.size();
167     _inPorts.push_back(inPortItem);
168   } else {
169     if (_parent->getWidth() > (2*Resource::Corner_Margin + 2*Resource::DataPort_Width + Resource::Space_Margin)) {
170       xLeft = _parent->getWidth() - Resource::Corner_Margin - Resource::DataPort_Width;
171     } else {
172       xLeft = Resource::Corner_Margin + Resource::DataPort_Width + Resource::Space_Margin;
173     };
174     nbPorts = _outPorts.size();
175     _outPorts.push_back(dynamic_cast<SceneOutPortItem*>(item));
176   };
177   qreal yTop   = Resource::Header_Height;
178   if (_fatherNode && _fatherNode->hasProgressBar())
179     yTop += Resource::progressBar_Height;
180   qreal deltaY = Resource::DataPort_Height + Resource::Space_Margin;
181   yTop += nbPorts * deltaY;
182   if (nbPorts >=_maxPorts) {
183     _maxPorts = nbPorts+1;
184   };
185   //DEBTRACE("left, top " << xLeft  << " " << yTop);
186   QPointF topLeft(xLeft, yTop);
187   item->setTopLeft(topLeft);
188   adaptComposedNode(dynamic_cast<SceneItem*>(item), deltaY);
189 }
190
191 void SceneHeaderNodeItem::reorganizePorts(shownState ss)
192 {
193   DEBTRACE("SceneHeaderNodeItem::reorganizePorts() " << ss << " " << _label.toStdString());
194
195   qreal yTop;
196   qreal href = Resource::Header_Height;
197   if (_fatherNode && _fatherNode->hasProgressBar())
198     href += Resource::progressBar_Height;
199   bool isShown = (ss != shrinkHidden);
200   if (!isShown) href = Resource::Corner_Margin;
201
202   std::list<SceneInPortItem*>::iterator iti = _inPorts.begin();
203   int nbPorts = 0;
204   for (; iti != _inPorts.end(); ++iti)
205     {
206       yTop = href + nbPorts * (Resource::DataPort_Height + Resource::Space_Margin);
207       QPointF topLeft(Resource::Corner_Margin, yTop);
208       (*iti)->setTopLeft(topLeft);
209       if (isShown) nbPorts++; // otherwise (shrink from ancestor) put all ports at the same position
210     }
211
212   std::list<SceneOutPortItem*>::iterator ito = _outPorts.begin();
213   nbPorts = 0;
214   qreal xLeft;
215   if (ss == expandShown) {
216     xLeft = _parent->getWidth() - Resource::Corner_Margin - Resource::DataPort_Width;
217   } else {
218     xLeft = Resource::Corner_Margin + Resource::DataPort_Width + Resource::Space_Margin;
219   };
220   for (; ito != _outPorts.end(); ++ito)
221     {
222       yTop = href + nbPorts * (Resource::DataPort_Height + Resource::Space_Margin);
223       QPointF topLeft(xLeft, yTop);
224       (*ito)->setTopLeft(topLeft);
225       if (isShown) nbPorts++; // otherwise (shrink from ancestor) put all ports at the same position
226     }
227   //updateLinks();
228 }
229
230 void SceneHeaderNodeItem::popupMenu(QWidget *caller, const QPoint &globalPos)
231 {
232   if (_parent) _parent->popupMenu(caller, globalPos);
233 //   HeaderNodeMenu m;
234 //   m.popupMenu(caller, globalPos);
235 }
236
237 void SceneHeaderNodeItem::adjustGeometry()
238 {
239   DEBTRACE("SceneHeaderNodeItem::adjustGeometry() " << _label.toStdString());
240   prepareGeometryChange();
241   _width = _parent->getWidth();
242   if (_header) _header->adjustGeometry();
243   adjustPosPorts();
244   update();
245 }
246
247 void SceneHeaderNodeItem::adjustPosPorts()
248 {
249   YASSERT(_fatherNode);
250   shownState ss = _fatherNode->getShownState();
251   if (_controlOut)
252     {
253       int x = Resource::Corner_Margin + 2*Resource::DataPort_Width + Resource::Space_Margin;
254       if ((ss == expandShown)  && (_parent->getWidth() > (x + Resource::Corner_Margin)))
255         x = _parent->getWidth() - Resource::Corner_Margin;
256     _controlOut->setTopLeft(QPointF(x - Resource::CtrlPort_Width, Resource::Corner_Margin));
257   };
258   reorganizePorts(ss);
259 }
260
261 QRectF SceneHeaderNodeItem::getMinimalBoundingRect() const
262 {
263   qreal width  = 2*Resource::Corner_Margin + 2*Resource::DataPort_Width + Resource::Space_Margin;
264   qreal height = Resource::Header_Height + Resource::Border_Margin;
265   int nbPorts  = _inPorts.size();
266   if (_outPorts.size() > nbPorts) nbPorts = _outPorts.size();
267   if (nbPorts) height += nbPorts*(Resource::DataPort_Height + Resource::Space_Margin);
268   if (_fatherNode && _fatherNode->hasProgressBar())
269     height += Resource::progressBar_Height;
270   //DEBTRACE(nbPorts << " " << width << " " << height);
271   return QRectF(x(), y(), width, height);
272 }
273
274 void SceneHeaderNodeItem::adaptComposedNode(SceneItem* port, qreal deltaY)
275 {
276   DEBTRACE("SceneHeaderNodeItem::adaptComposedNode " << deltaY);
277   QPointF oldPos(x(),y() - deltaY);
278   if (_parent)
279     {
280       if (SceneComposedNodeItem *bloc = dynamic_cast<SceneComposedNodeItem*>(_parent))
281         bloc->collisionResolv(port, oldPos);
282       //_parent->checkGeometryChange();
283     }
284 }
285
286 void SceneHeaderNodeItem::setEdited(bool isEdited)
287 {
288   DEBTRACE("SceneHeaderNodeItem::setEdited " << isEdited);
289   if (isEdited)
290     _brushColor = Resource::editedNodeBrushColor;
291   else
292     {
293       if (QtGuiContext::getQtCurrent()->isEdition())
294         _brushColor = Resource::normalNodeBrushColor;
295       else
296         _brushColor = Resource::runNodeBrushColor;
297     }
298   if (isEdited != _isEdited)
299     _parent->update();
300   _isEdited = isEdited;
301 }
302
303 void SceneHeaderNodeItem::setValid(bool isValid)
304 {
305   DEBTRACE("SceneHeaderNodeItem::setValid " << isValid);
306   if (_isValid != isValid)
307     {
308       _isValid = isValid;
309       _parent->update();
310     }
311 }
312
313 void SceneHeaderNodeItem::setExecState(int execState)
314 {
315   DEBTRACE("SceneHeaderNodeItem::setExecState " << execState);
316   _execState = execState;
317   if (!_isValid) return;
318   QColor oldsc = _sc;
319   if (_isProc)
320     switch (_execState)
321       {
322       case YACS::NOTYETINITIALIZED: _sc = Resource::NOTYETINITIALIZED; _stateDef = "Not Yet Initialized"; break;
323       case YACS::INITIALISED:       _sc = Resource::INITIALISED      ; _stateDef = "Initialized"        ; break;
324       case YACS::RUNNING:           _sc = Resource::RUNNING          ; _stateDef = "Running"            ; break;
325       case YACS::WAITINGTASKS:      _sc = Resource::WAITINGTASKS     ; _stateDef = "Waiting Tasks"      ; break;
326       case YACS::PAUSED:            _sc = Resource::PAUSED           ; _stateDef = "Paused"             ; break;
327       case YACS::FINISHED:          _sc = Resource::FINISHED         ; _stateDef = "Finished"           ; break;
328       case YACS::STOPPED:           _sc = Resource::STOPPED          ; _stateDef = "Stopped"            ; break;
329       default:                      _sc = Resource::UNKNOWN          ; _stateDef = "Unknown Status"     ;
330       }
331   else
332     switch (_execState)
333       {
334       case YACS::UNDEFINED:         _sc = Resource::UNDEFINED        ; _stateDef = "UNDEFINED"          ; break;
335       case YACS::INVALID:           _sc = Resource::INVALID          ; _stateDef = "INVALID"            ; break;
336       case YACS::READY:             _sc = Resource::READY            ; _stateDef = "READY"              ; break;
337       case YACS::TOLOAD:            _sc = Resource::TOLOAD           ; _stateDef = "TOLOAD"             ; break;
338       case YACS::LOADED:            _sc = Resource::LOADED           ; _stateDef = "LOADED"             ; break;
339       case YACS::TOACTIVATE:        _sc = Resource::TOACTIVATE       ; _stateDef = "TOACTIVATE"         ; break;
340       case YACS::ACTIVATED:         _sc = Resource::ACTIVATED        ; _stateDef = "ACTIVATED"          ; break;
341       case YACS::DESACTIVATED:      _sc = Resource::DESACTIVATED     ; _stateDef = "DESACTIVATED"       ; break;
342       case YACS::DONE:              _sc = Resource::DONE             ; _stateDef = "DONE"               ; break;
343       case YACS::SUSPENDED:         _sc = Resource::SUSPENDED        ; _stateDef = "SUSPENDED"          ; break;
344       case YACS::LOADFAILED:        _sc = Resource::LOADFAILED       ; _stateDef = "LOADFAILED"         ; break;
345       case YACS::EXECFAILED:        _sc = Resource::EXECFAILED       ; _stateDef = "EXECFAILED"         ; break;
346       case YACS::PAUSE:             _sc = Resource::PAUSE            ; _stateDef = "PAUSE"              ; break;
347       case YACS::INTERNALERR:       _sc = Resource::INTERNALERR      ; _stateDef = "INTERNALERR"        ; break;
348       case YACS::DISABLED:          _sc = Resource::DISABLED         ; _stateDef = "DISABLED"           ; break;
349       case YACS::FAILED:            _sc = Resource::FAILED           ; _stateDef = "FAILED"             ; break;
350       case YACS::ERROR:             _sc = Resource::ERROR            ; _stateDef = "ERROR"              ; break;
351       default:                      _sc = Resource::DEFAULT          ; _stateDef = "---"                ;
352       }
353   DEBTRACE("  - stateDef = " << _stateDef.toStdString());
354   if(oldsc != _sc)
355     _parent->update();
356 }
357
358 SceneCtrlPortItem* SceneHeaderNodeItem::getCtrlInPortItem()
359 {
360   return _controlIn;
361 }
362
363 SceneCtrlPortItem* SceneHeaderNodeItem::getCtrlOutPortItem()
364 {
365   return _controlOut;
366 }
367
368
369
370 void SceneHeaderNodeItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
371 {
372   event->ignore();
373 }
374
375 void SceneHeaderNodeItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
376 {
377   event->ignore();
378 }
379
380 QColor SceneHeaderNodeItem::getValidColor()
381 {
382   if (_isValid)
383     return _sc;
384   else
385     return Resource::invalidNodeColor;
386 }