1 
2 
3 #include "toonzqt/fxschematicnode.h"
4 
5 // TnzQt includes
6 #include "toonzqt/fxtypes.h"
7 #include "toonzqt/fxschematicscene.h"
8 #include "toonzqt/icongenerator.h"
9 #include "toonzqt/gutil.h"
10 #include "toonzqt/fxselection.h"
11 #include "toonzqt/menubarcommand.h"
12 #include "toonzqt/fxiconmanager.h"
13 
14 // TnzLib includes
15 #include "toonz/tcolumnfx.h"
16 #include "toonz/tcolumnfxset.h"
17 #include "toonz/txshchildlevel.h"
18 #include "toonz/txsheet.h"
19 #include "toonz/fxdag.h"
20 #include "toonz/tstageobjectid.h"
21 #include "toonz/tstageobject.h"
22 #include "toonz/txshcell.h"
23 #include "toonz/txsheethandle.h"
24 #include "toonz/tframehandle.h"
25 #include "toonz/fxcommand.h"
26 #include "toonz/tstageobjectcmd.h"
27 #include "toonz/txshlevelcolumn.h"
28 #include "toonz/txshzeraryfxcolumn.h"
29 #include "toonz/txshcolumn.h"
30 #include "toonz/txshsimplelevel.h"
31 #include "toonz/txshleveltypes.h"
32 #include "toonz/toonzscene.h"
33 #include "toonz/sceneproperties.h"
34 #include "toonz/tcolumnhandle.h"
35 #include "toonz/preferences.h"
36 
37 #include "tw/stringtable.h"
38 
39 // TnzBase includes
40 #include "tfx.h"
41 #include "tfxattributes.h"
42 #include "tmacrofx.h"
43 #include "trasterfx.h"
44 #include "tpassivecachemanager.h"
45 
46 // TnzCore includes
47 #include "tconst.h"
48 
49 #include "../toonz/menubarcommandids.h"
50 
51 // Qt includes
52 #include <QAction>
53 #include <QApplication>
54 #include <QMenu>
55 #include <QGraphicsSceneMouseEvent>
56 #include <QDesktopWidget>
57 
58 //********************************************************************************
59 //    Local namespace
60 //********************************************************************************
61 
62 namespace {
isAInnerMacroFx(TFx * fx,TXsheet * xsh)63 bool isAInnerMacroFx(TFx *fx, TXsheet *xsh) {
64   if (!fx) return false;
65   TColumnFx *cfx      = dynamic_cast<TColumnFx *>(fx);
66   TXsheetFx *xfx      = dynamic_cast<TXsheetFx *>(fx);
67   TOutputFx *ofx      = dynamic_cast<TOutputFx *>(fx);
68   TFxSet *internalFxs = xsh->getFxDag()->getInternalFxs();
69   return !cfx && !xfx && !ofx && !internalFxs->containsFx(fx);
70 }
71 
72 //-----------------------------------------------------
73 
drawCachedFxFlap(QPainter * painter,const QPointF & pos)74 void drawCachedFxFlap(QPainter *painter, const QPointF &pos) {
75   painter->save();
76   painter->setPen(QColor(0, 0, 0, 255));
77   painter->setBrush(QColor(120, 120, 120, 255));
78 
79   QPainterPath path(pos);
80   path.lineTo(pos.x(), pos.y() - 10.0);
81   path.lineTo(pos.x() - 10.0, pos.y());
82   path.lineTo(pos);
83 
84   painter->drawPath(path);
85   painter->setBrush(QColor(255, 255, 255, 255));
86 
87   QPointF newPos = pos + QPointF(-10.0, -10.0);
88   path           = QPainterPath(newPos);
89   path.lineTo(newPos.x(), newPos.y() + 10.0);
90   path.lineTo(newPos.x() + 10.0, newPos.y());
91   path.lineTo(newPos);
92 
93   painter->drawPath(path);
94   painter->restore();
95 }
96 
97 //-----------------------------------------------------
98 
getIndex(TFxPort * port,const std::vector<TFxPort * > & ports)99 int getIndex(TFxPort *port, const std::vector<TFxPort *> &ports) {
100   std::vector<TFxPort *>::const_iterator it =
101       std::find(ports.begin(), ports.end(), port);
102   if (it == ports.end()) return -1;
103   return std::distance(ports.begin(), it);
104 }
105 
106 //-----------------------------------------------------
107 
getInputPortIndex(TFxPort * port,TFx * fx)108 int getInputPortIndex(TFxPort *port, TFx *fx) {
109   int count = fx->getInputPortCount();
110   int i;
111   for (i = 0; i < count; i++) {
112     if (port == fx->getInputPort(i)) return i;
113   }
114   return -1;
115 }
116 }  // namespace
117 
118 //*****************************************************
119 //
120 // FxColumnPainter
121 //
122 //*****************************************************
123 
FxColumnPainter(FxSchematicColumnNode * parent,double width,double height,const QString & name)124 FxColumnPainter::FxColumnPainter(FxSchematicColumnNode *parent, double width,
125                                  double height, const QString &name)
126     : QGraphicsItem(parent)
127     , m_parent(parent)
128     , m_name(name)
129     , m_width(width)
130     , m_height(height) {
131   setFlag(QGraphicsItem::ItemIsMovable, false);
132   setFlag(QGraphicsItem::ItemIsSelectable, false);
133   setFlag(QGraphicsItem::ItemIsFocusable, false);
134   connect(IconGenerator::instance(), SIGNAL(iconGenerated()), this,
135           SLOT(onIconGenerated()));
136 
137   TLevelColumnFx *lcfx = dynamic_cast<TLevelColumnFx *>(parent->getFx());
138   if (lcfx) {
139     int index = lcfx->getColumnIndex();
140 
141     FxSchematicScene *fxScene = dynamic_cast<FxSchematicScene *>(scene());
142     if (!fxScene) return;
143 
144     TXsheet *xsh = fxScene->getXsheet();
145     int r0, r1;
146     xsh->getCellRange(index, r0, r1);
147     if (r0 > r1) return;
148     TXshCell firstCell = xsh->getCell(r0, index);
149     m_type             = firstCell.m_level->getType();
150   }
151 }
152 
153 //-----------------------------------------------------
154 
~FxColumnPainter()155 FxColumnPainter::~FxColumnPainter() {}
156 
157 //-----------------------------------------------------
158 
boundingRect() const159 QRectF FxColumnPainter::boundingRect() const {
160   if (m_parent->isOpened() && m_parent->isNormalIconView())
161     return QRectF(-5, -54, m_width + 10, m_height + 59);
162   else
163     return QRectF(-5, -5, m_width + 10, m_height + 10);
164 }
165 
166 //-----------------------------------------------------
167 
paint(QPainter * painter,const QStyleOptionGraphicsItem * option,QWidget * widget)168 void FxColumnPainter::paint(QPainter *painter,
169                             const QStyleOptionGraphicsItem *option,
170                             QWidget *widget) {
171   FxSchematicScene *sceneFx = dynamic_cast<FxSchematicScene *>(scene());
172   if (!sceneFx) return;
173   int levelType;
174   QString levelName;
175   m_parent->getLevelTypeAndName(levelType, levelName);
176 
177   QColor nodeColor;
178   SchematicViewer *viewer = sceneFx->getSchematicViewer();
179   viewer->getNodeColor(levelType, nodeColor);
180 
181   if (m_isReference) {
182     painter->setBrush(viewer->getReferenceColumnColor());
183     painter->setPen(nodeColor);
184   } else {
185     painter->setBrush(nodeColor);
186     painter->setPen(Qt::NoPen);
187   }
188   painter->drawRect(0, 0, m_width, m_height);
189 
190   if (m_parent->isOpened() && m_parent->isNormalIconView()) {
191     // Draw the pixmap
192     painter->setBrush(Qt::NoBrush);
193     painter->setPen(QColor(0, 0, 0, 255));
194     QPixmap pixmap = scalePixmapKeepingAspectRatio(
195         m_parent->getPixmap(), QSize(m_width, 49), Qt::transparent);
196     if (!pixmap.isNull()) {
197       painter->drawPixmap(QPointF(0, -pixmap.height()), pixmap);
198     } else {
199       painter->setBrush(QColor(255, 255, 255, 255));
200       painter->drawRect(0, -pixmap.height(), m_width, pixmap.height());
201     }
202   }
203 
204   painter->setPen(viewer->getTextColor());
205   painter->setBrush(Qt::NoBrush);
206 
207   QRectF columnNameRect;
208   QRectF levelNameRect;
209   if (m_parent->isNormalIconView()) {
210     columnNameRect = QRect(18, 2, 54, 14);
211     levelNameRect  = QRectF(18, 16, 54, 14);
212   } else {
213     columnNameRect = QRect(4, 2, 78, 22);
214     levelNameRect  = QRectF(4, 26, 78, 22);
215 
216     QFont fnt = painter->font();
217     fnt.setPixelSize(fnt.pixelSize() * 2);
218     painter->setFont(fnt);
219   }
220 
221   // column name
222   if (!m_parent->isNameEditing()) {
223     // if this is a current object
224     if (sceneFx->getCurrentFx() == m_parent->getFx())
225       painter->setPen(viewer->getSelectedNodeTextColor());
226     QString elidedName =
227         elideText(m_name, painter->font(), columnNameRect.width());
228     painter->drawText(columnNameRect, Qt::AlignLeft | Qt::AlignVCenter,
229                       elidedName);
230   }
231 
232   // level name
233   QString elidedName =
234       elideText(levelName, painter->font(), levelNameRect.width());
235   painter->drawText(levelNameRect, Qt::AlignLeft | Qt::AlignVCenter,
236                     elidedName);
237 }
238 
239 //-----------------------------------------------------
contextMenuEvent(QGraphicsSceneContextMenuEvent * cme)240 void FxColumnPainter::contextMenuEvent(QGraphicsSceneContextMenuEvent *cme) {
241   FxSchematicScene *fxScene = dynamic_cast<FxSchematicScene *>(scene());
242   QMenu menu(fxScene->views()[0]);
243 
244   QAction *copy = CommandManager::instance()->getAction("MI_Copy");
245   QAction *cut  = CommandManager::instance()->getAction("MI_Cut");
246 
247   bool enebleInsertAction =
248       !m_parent->getFx()->getAttributes()->isGrouped() ||
249       m_parent->getFx()->getAttributes()->isGroupEditing();
250   if (enebleInsertAction) {
251     // repeat the latest action
252     if (cme->modifiers() & Qt::ControlModifier) {
253       menu.addAction(fxScene->getAgainAction(AddFxContextMenu::Add |
254                                              AddFxContextMenu::Insert));
255       if (!menu.actions().isEmpty()) {
256         menu.exec(cme->screenPos());
257         return;
258       }
259     }
260   }
261 
262   QMenu *insertMenu = fxScene->getInsertFxMenu();
263   fxScene->initCursorScenePos();
264   QMenu *addMenu = fxScene->getAddFxMenu();
265 
266   QAction *disconnectFromXSheet =
267       new QAction(tr("&Disconnect from Xsheet"), &menu);
268   connect(disconnectFromXSheet, SIGNAL(triggered()), fxScene,
269           SLOT(onDisconnectFromXSheet()));
270 
271   QAction *connectToXSheet = new QAction(tr("&Connect to Xsheet"), &menu);
272   connect(connectToXSheet, SIGNAL(triggered()), fxScene,
273           SLOT(onConnectToXSheet()));
274 
275   QAction *addOutputFx =
276       CommandManager::instance()->getAction("MI_NewOutputFx");
277 
278   QAction *addPaste = new QAction(tr("&Paste Add"), &menu);
279   connect(addPaste, SIGNAL(triggered()), fxScene, SLOT(onAddPaste()));
280 
281   QAction *preview = new QAction(tr("&Preview"), &menu);
282   connect(preview, SIGNAL(triggered()), fxScene, SLOT(onPreview()));
283 
284   bool cacheEnabled =
285       TPassiveCacheManager::instance()->cacheEnabled(m_parent->getFx());
286 
287   QAction *cacheFx =
288       new QAction(cacheEnabled ? tr("&Uncache Fx") : tr("&Cache FX"), &menu);
289   if (cacheEnabled)
290     connect(cacheFx, SIGNAL(triggered()), fxScene, SLOT(onUncacheFx()));
291   else
292     connect(cacheFx, SIGNAL(triggered()), fxScene, SLOT(onCacheFx()));
293 
294   QAction *collapse = CommandManager::instance()->getAction("MI_Collapse");
295 
296   QAction *openSubxsh = CommandManager::instance()->getAction("MI_OpenChild");
297 
298   QAction *explodeChild =
299       CommandManager::instance()->getAction("MI_ExplodeChild");
300 
301   QAction *group = CommandManager::instance()->getAction("MI_Group");
302 
303   menu.addMenu(insertMenu);
304   menu.addMenu(addMenu);
305   menu.addSeparator();
306   if (!m_parent->getFx()->getAttributes()->isGrouped()) {
307     menu.addAction(copy);
308     menu.addAction(cut);
309     menu.addAction(addPaste);
310   }
311   menu.addSeparator();
312   if (fxScene->getXsheet()->getFxDag()->getTerminalFxs()->containsFx(
313           m_parent->getFx()))
314     menu.addAction(disconnectFromXSheet);
315   else
316     menu.addAction(connectToXSheet);
317   if (!m_parent->getFx()->getAttributes()->isGrouped())
318     menu.addAction(addOutputFx);
319   menu.addAction(preview);
320   menu.addAction(cacheFx);
321   menu.addSeparator();
322   if (enebleInsertAction) {
323     menu.addAction(collapse);
324   }
325 
326   TFrameHandle *frameHandle = fxScene->getFrameHandle();
327   if (frameHandle->getFrameType() == TFrameHandle::SceneFrame) {
328     TLevelColumnFx *colFx = dynamic_cast<TLevelColumnFx *>(m_parent->getFx());
329     assert(colFx);
330     int col       = colFx->getColumnIndex();
331     int fr        = frameHandle->getFrame();
332     TXsheet *xsh  = fxScene->getXsheet();
333     TXshCell cell = xsh->getCell(fr, col);
334     if (dynamic_cast<TXshChildLevel *>(cell.m_level.getPointer())) {
335       menu.addAction(openSubxsh);
336       menu.addAction(explodeChild);
337     }
338   }
339   menu.addSeparator();
340   menu.addAction(group);
341 
342   if (m_type == OVL_XSHLEVEL || m_type == TZP_XSHLEVEL ||
343       m_type == PLI_XSHLEVEL) {
344     QAction *viewFileCommand =
345         CommandManager::instance()->getAction("MI_ViewFile");
346     menu.addSeparator();
347     menu.addAction(viewFileCommand);
348     QAction *levelSettings =
349         CommandManager::instance()->getAction("MI_LevelSettings");
350     menu.addAction(levelSettings);
351   }
352 
353   menu.exec(cme->screenPos());
354 }
355 
356 //-----------------------------------------------------
357 
onIconGenerated()358 void FxColumnPainter::onIconGenerated() {
359   if (m_type != OVL_XSHLEVEL) return;
360 
361   TLevelColumnFx *lcfx = dynamic_cast<TLevelColumnFx *>(m_parent->getFx());
362   if (lcfx) {
363     int index = lcfx->getColumnIndex();
364 
365     FxSchematicScene *fxScene = dynamic_cast<FxSchematicScene *>(scene());
366     if (!fxScene) return;
367 
368     TXsheet *xsh = fxScene->getXsheet();
369     int r0, r1;
370     xsh->getCellRange(index, r0, r1);
371     if (r0 > r1) return;
372     TXshCell firstCell = xsh->getCell(r0, index);
373     int type           = firstCell.m_level->getType();
374     if (m_type != type) {
375       m_type = type;
376       update();
377     }
378   }
379 }
380 
381 //*****************************************************
382 //
383 // FxPalettePainter
384 //
385 //*****************************************************
386 
FxPalettePainter(FxSchematicPaletteNode * parent,double width,double height,const QString & name)387 FxPalettePainter::FxPalettePainter(FxSchematicPaletteNode *parent, double width,
388                                    double height, const QString &name)
389     : QGraphicsItem(parent)
390     , m_parent(parent)
391     , m_name(name)
392     , m_width(width)
393     , m_height(height) {
394   setFlag(QGraphicsItem::ItemIsMovable, false);
395   setFlag(QGraphicsItem::ItemIsSelectable, false);
396   setFlag(QGraphicsItem::ItemIsFocusable, false);
397 }
398 
399 //-----------------------------------------------------
400 
~FxPalettePainter()401 FxPalettePainter::~FxPalettePainter() {}
402 
403 //-----------------------------------------------------
404 
boundingRect() const405 QRectF FxPalettePainter::boundingRect() const {
406   return QRectF(-5, -5, m_width + 10, m_height + 10);
407 }
408 
409 //-----------------------------------------------------
410 
paint(QPainter * painter,const QStyleOptionGraphicsItem * option,QWidget * widget)411 void FxPalettePainter::paint(QPainter *painter,
412                              const QStyleOptionGraphicsItem *option,
413                              QWidget *widget) {
414   FxSchematicScene *sceneFx = dynamic_cast<FxSchematicScene *>(scene());
415   if (!sceneFx) return;
416 
417   QPixmap palettePm = QPixmap(":Resources/schematic_palette.png");
418 
419   int alpha = 200;
420 
421   SchematicViewer *viewer = sceneFx->getSchematicViewer();
422 
423   painter->setBrush(viewer->getPaletteColumnColor());
424 
425   painter->setPen(Qt::NoPen);
426 
427   if (m_parent->isNormalIconView())
428     painter->drawRoundRect(QRectF(0, 0, m_width, m_height), 35, 99);
429   else
430     painter->drawRoundRect(QRectF(0, 0, m_width, m_height), 10, 30);
431 
432   // draw icon
433   QRect paletteRect;
434   QRectF idRect;
435   QRectF palNameRect;
436   if (m_parent->isNormalIconView()) {
437     paletteRect = QRect(-3, -1, 20, 16);
438     idRect      = QRectF(18, 2, 54, 14);
439     palNameRect = QRectF(18, 16, 54, 14);
440   } else {
441     paletteRect = QRect(4, -6, 35, 28);
442     idRect      = QRectF(25, 2, 49, 22);
443     palNameRect = QRectF(4, 26, 78, 22);
444 
445     QFont fnt = painter->font();
446     fnt.setPixelSize(fnt.pixelSize() * 2);
447     painter->setFont(fnt);
448   }
449 
450   painter->drawPixmap(paletteRect, palettePm);
451 
452   //! draw the name only if it is not editing
453   painter->setPen(viewer->getTextColor());
454 
455   if (!m_parent->isNameEditing()) {
456     if (sceneFx->getCurrentFx() == m_parent->getFx())
457       painter->setPen(viewer->getSelectedNodeTextColor());
458 
459     int w = idRect.width();
460 
461     if (m_parent->isNormalIconView()) {
462       QString elidedName = elideText(m_name, painter->font(), w);
463       painter->drawText(idRect, Qt::AlignLeft | Qt::AlignVCenter, elidedName);
464     } else
465       painter->drawText(idRect, Qt::AlignRight | Qt::AlignVCenter,
466                         QString::number(m_parent->getColumnIndex() + 1));
467   }
468 
469   // level name
470   QString paletteName = m_parent->getPaletteName();
471   QString elidedName =
472       elideText(paletteName, painter->font(), palNameRect.width());
473   painter->drawText(palNameRect, Qt::AlignLeft | Qt::AlignVCenter, elidedName);
474 }
475 
476 //-----------------------------------------------------
477 
contextMenuEvent(QGraphicsSceneContextMenuEvent * cme)478 void FxPalettePainter::contextMenuEvent(QGraphicsSceneContextMenuEvent *cme) {
479   FxSchematicScene *fxScene = dynamic_cast<FxSchematicScene *>(scene());
480   QMenu menu(fxScene->views()[0]);
481 
482   QAction *disconnectFromXSheet =
483       new QAction(tr("&Disconnect from Xsheet"), &menu);
484   connect(disconnectFromXSheet, SIGNAL(triggered()), fxScene,
485           SLOT(onDisconnectFromXSheet()));
486 
487   QAction *connectToXSheet = new QAction(tr("&Connect to Xsheet"), &menu);
488   connect(connectToXSheet, SIGNAL(triggered()), fxScene,
489           SLOT(onConnectToXSheet()));
490 
491   QAction *preview = new QAction(tr("&Preview"), &menu);
492   connect(preview, SIGNAL(triggered()), fxScene, SLOT(onPreview()));
493 
494   QAction *collapse = CommandManager::instance()->getAction("MI_Collapse");
495 
496   QAction *group = CommandManager::instance()->getAction("MI_Group");
497 
498   bool enebleInsertAction =
499       !m_parent->getFx()->getAttributes()->isGrouped() ||
500       m_parent->getFx()->getAttributes()->isGroupEditing();
501 
502   if (enebleInsertAction) {
503     if (fxScene->getXsheet()->getFxDag()->getTerminalFxs()->containsFx(
504             m_parent->getFx()))
505       menu.addAction(disconnectFromXSheet);
506     else
507       menu.addAction(connectToXSheet);
508     menu.addAction(preview);
509     menu.addSeparator();
510     menu.addAction(collapse);
511     menu.addSeparator();
512   }
513   menu.addAction(group);
514 
515   menu.exec(cme->screenPos());
516 }
517 
518 //*****************************************************
519 //
520 // FxPainter
521 //
522 //*****************************************************
523 
FxPainter(FxSchematicNode * parent,double width,double height,const QString & name,eFxType type,std::string fxType)524 FxPainter::FxPainter(FxSchematicNode *parent, double width, double height,
525                      const QString &name, eFxType type, std::string fxType)
526     : QGraphicsItem(parent)
527     , m_parent(parent)
528     , m_name(name)
529     , m_width(width)
530     , m_height(height)
531     , m_type(type)
532     , m_fxType(fxType) {
533   setFlag(QGraphicsItem::ItemIsMovable, false);
534   setFlag(QGraphicsItem::ItemIsSelectable, false);
535   setFlag(QGraphicsItem::ItemIsFocusable, false);
536 
537   switch (m_type) {
538   case eNormalFx:
539   case eMacroFx:
540   case eNormalLayerBlendingFx:
541   case eNormalMatteFx:
542   case eNormalImageAdjustFx:
543     m_label = QString::fromStdWString(
544         TStringTable::translate(parent->getFx()->getFxType()));
545     break;
546   case eZeraryFx: {
547     TZeraryColumnFx *zfx = dynamic_cast<TZeraryColumnFx *>(parent->getFx());
548     if (zfx) {
549       TFx *zeraryFx = zfx->getZeraryFx();
550       if (zeraryFx) {
551         m_label = QString::fromStdWString(
552             TStringTable::translate(zeraryFx->getFxType()));
553       }
554     }
555     break;
556   }
557   default:
558     break;
559   }
560 }
561 
562 //-----------------------------------------------------
563 
~FxPainter()564 FxPainter::~FxPainter() {}
565 
566 //-----------------------------------------------------
567 
boundingRect() const568 QRectF FxPainter::boundingRect() const {
569   return QRectF(-5, -5, m_width + 10, m_height + 10);
570 }
571 
572 //-----------------------------------------------------
573 
paint(QPainter * painter,const QStyleOptionGraphicsItem * option,QWidget * widget)574 void FxPainter::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
575                       QWidget *widget) {
576   FxSchematicScene *sceneFx = dynamic_cast<FxSchematicScene *>(scene());
577   if (!sceneFx) return;
578 
579   // if the scale is small, display with fx icons
580   if (!m_parent->isNormalIconView()) {
581     paint_small(painter);
582     return;
583   }
584 
585   if (m_type == eGroupedFx) {
586     painter->save();
587     QPen pen;
588     if (m_parent->isSelected()) {
589       painter->setBrush(QColor(0, 0, 0, 0));
590       pen.setColor(QColor(255, 255, 255, 255));
591       pen.setWidth(4.0);
592       pen.setJoinStyle(Qt::RoundJoin);
593       painter->setPen(pen);
594       painter->drawRect(-2, -2, m_width + 4, m_height + 4);
595     }
596     painter->restore();
597   }
598 
599   QColor nodeColor;
600   SchematicViewer *viewer = sceneFx->getSchematicViewer();
601   viewer->getNodeColor(m_type, nodeColor);
602 
603   painter->setBrush(nodeColor);
604   painter->setPen(Qt::NoPen);
605   painter->drawRect(0, 0, m_width, m_height);
606 
607   // draw diagonal line for disabled fx
608   bool is_enabled = m_parent->isEnabled();
609   if (!is_enabled) {
610     painter->save();
611     painter->setPen(QColor(255, 0, 0, 255));
612     painter->drawLine(QPointF(0, m_height), QPointF(m_width, 0));
613     painter->drawLine(QPointF(0, 0), QPointF(m_width, m_height));
614     painter->restore();
615   }
616 
617   QFont columnFont(painter->font());
618   columnFont.setPixelSize(columnFont.pixelSize() - 1);
619   painter->setFont(columnFont);
620 
621   // draw fxId in the bottom part
622   painter->setPen(viewer->getTextColor());
623   QString label;
624   if (m_type == eGroupedFx)
625     label = "Group " +
626             QString::number(m_parent->getFx()->getAttributes()->getGroupId());
627   else {
628     // for zerary fx
629     if (m_type == eZeraryFx) {
630       TZeraryColumnFx *zcFx =
631           dynamic_cast<TZeraryColumnFx *>(m_parent->getFx());
632       if (!zcFx) return;
633       label = QString::fromStdWString(zcFx->getZeraryFx()->getFxId());
634     } else
635       label = QString::fromStdWString(m_parent->getFx()->getFxId());
636   }
637 
638   if (label != m_name) {
639     label = elideText(label, painter->font(), m_width - 21);
640     painter->drawText(QRectF(3, 16, m_width - 21, 14),
641                       Qt::AlignLeft | Qt::AlignVCenter, label);
642   }
643 
644   // draw user-defined fx name in the upper part
645   //! draw the name only if it is not editing
646   if (!m_parent->isNameEditing()) {
647     FxSchematicScene *sceneFx = dynamic_cast<FxSchematicScene *>(scene());
648     if (!sceneFx) return;
649     if (sceneFx->getCurrentFx() == m_parent->getFx())
650       painter->setPen(viewer->getSelectedNodeTextColor());
651     QRectF rect(3, 2, m_width - 21, 14);
652     int w = rect.width();
653     if (label == m_name) {
654       rect.adjust(0, 0, 0, 14);
655       w *= 2;
656     }
657     QString elidedName = elideText(m_name, painter->font(), w);
658     painter->drawText(rect, Qt::TextWrapAnywhere, elidedName);
659   }
660 }
661 
662 //-----------------------------------------------------
663 
contextMenuEvent(QGraphicsSceneContextMenuEvent * cme)664 void FxPainter::contextMenuEvent(QGraphicsSceneContextMenuEvent *cme) {
665   FxSchematicScene *fxScene = dynamic_cast<FxSchematicScene *>(scene());
666   QMenu menu(scene()->views()[0]);
667 
668   TFx *fx = m_parent->getFx();
669   bool isInternalFx =
670       fxScene->getXsheet()->getFxDag()->getInternalFxs()->containsFx(fx) ||
671       m_type == eGroupedFx;
672   bool enableGroupAction = m_parent->isA(eZeraryFx) || isInternalFx;
673   bool enableInsertAction =
674       enableGroupAction && (fx->getAttributes()->isGroupEditing() ||
675                             !fx->getAttributes()->isGrouped());
676   if (enableInsertAction) {
677     // repeat the last command
678     if (cme->modifiers() & Qt::ControlModifier) {
679       int commands = (m_type != eGroupedFx)
680                          ? AddFxContextMenu::Add | AddFxContextMenu::Insert |
681                                AddFxContextMenu::Replace
682                          : AddFxContextMenu::Add | AddFxContextMenu::Insert;
683       menu.addAction(fxScene->getAgainAction(commands));
684       if (!menu.actions().isEmpty()) {
685         menu.exec(cme->screenPos());
686         return;
687       }
688     }
689   }
690 
691   QMenu *insertMenu    = fxScene->getInsertFxMenu();
692   QMenu *replacefxMenu = fxScene->getReplaceFxMenu();
693   fxScene->initCursorScenePos();
694   QMenu *addMenu = fxScene->getAddFxMenu();
695 
696   QAction *fxEditorPopup =
697       CommandManager::instance()->getAction(MI_FxParamEditor);
698   QAction *copy    = CommandManager::instance()->getAction("MI_Copy");
699   QAction *cut     = CommandManager::instance()->getAction("MI_Cut");
700   QAction *group   = CommandManager::instance()->getAction("MI_Group");
701   QAction *ungroup = CommandManager::instance()->getAction("MI_Ungroup");
702 
703   QAction *editGroup = new QAction(tr("&Open Group"), &menu);
704   connect(editGroup, SIGNAL(triggered()), fxScene, SLOT(onEditGroup()));
705 
706   QAction *replacePaste = new QAction(tr("&Paste Replace"), &menu);
707   connect(replacePaste, SIGNAL(triggered()), fxScene, SLOT(onReplacePaste()));
708 
709   QAction *addPaste = new QAction(tr("&Paste Add"), &menu);
710   connect(addPaste, SIGNAL(triggered()), fxScene, SLOT(onAddPaste()));
711 
712   QAction *addOutputFx =
713       CommandManager::instance()->getAction("MI_NewOutputFx");
714 
715   QAction *deleteFx = new QAction(tr("&Delete"), &menu);
716   connect(deleteFx, SIGNAL(triggered()), fxScene, SLOT(onDeleteFx()));
717 
718   QAction *disconnectFromXSheet =
719       new QAction(tr("&Disconnect from Xsheet"), &menu);
720   connect(disconnectFromXSheet, SIGNAL(triggered()), fxScene,
721           SLOT(onDisconnectFromXSheet()));
722 
723   QAction *connectToXSheet = new QAction(tr("&Connect to Xsheet"), &menu);
724   connect(connectToXSheet, SIGNAL(triggered()), fxScene,
725           SLOT(onConnectToXSheet()));
726 
727   QAction *duplicateFx = new QAction(tr("&Create Linked FX"), &menu);
728   connect(duplicateFx, SIGNAL(triggered()), fxScene, SLOT(onDuplicateFx()));
729 
730   QAction *unlinkFx = new QAction(tr("&Unlink"), &menu);
731   connect(unlinkFx, SIGNAL(triggered()), fxScene, SLOT(onUnlinkFx()));
732 
733   QAction *macroFx = new QAction(tr("&Make Macro FX"), &menu);
734   connect(macroFx, SIGNAL(triggered()), fxScene, SLOT(onMacroFx()));
735 
736   QAction *explodeMacroFx = new QAction(tr("&Explode Macro FX"), &menu);
737   connect(explodeMacroFx, SIGNAL(triggered()), fxScene,
738           SLOT(onExplodeMacroFx()));
739 
740   QAction *openMacroFx = new QAction(tr("&Open Macro FX"), &menu);
741   connect(openMacroFx, SIGNAL(triggered()), fxScene, SLOT(onOpenMacroFx()));
742 
743   QAction *savePresetFx = new QAction(tr("&Save As Preset..."), &menu);
744   connect(savePresetFx, SIGNAL(triggered()), fxScene, SLOT(onSavePresetFx()));
745 
746   QAction *preview = new QAction(tr("&Preview"), &menu);
747   connect(preview, SIGNAL(triggered()), fxScene, SLOT(onPreview()));
748 
749   bool cacheEnabled = m_parent->isCached();
750 
751   QAction *cacheFx =
752       new QAction(cacheEnabled ? tr("&Uncache FX") : tr("&Cache FX"), &menu);
753   if (cacheEnabled)
754     connect(cacheFx, SIGNAL(triggered()), fxScene, SLOT(onUncacheFx()));
755   else
756     connect(cacheFx, SIGNAL(triggered()), fxScene, SLOT(onCacheFx()));
757 
758   QAction *collapse = CommandManager::instance()->getAction("MI_Collapse");
759 
760   TZeraryColumnFx *zsrc = dynamic_cast<TZeraryColumnFx *>(fx);
761   // if(m_type != eGroupedFx)
762   // {
763   if (enableInsertAction) {
764     menu.addMenu(insertMenu);
765     menu.addMenu(addMenu);
766     if (m_type != eGroupedFx) menu.addMenu(replacefxMenu);
767   }
768   if (m_type != eGroupedFx) menu.addAction(fxEditorPopup);
769   if (enableInsertAction) {
770     menu.addSeparator();
771     menu.addAction(copy);
772     menu.addAction(cut);
773     if (m_type != eGroupedFx && !fx->getAttributes()->isGrouped()) {
774       menu.addAction(replacePaste);
775       menu.addAction(addPaste);
776     }
777     menu.addAction(deleteFx);
778 
779     menu.addSeparator();
780     if (fxScene->getXsheetHandle()
781             ->getXsheet()
782             ->getFxDag()
783             ->getTerminalFxs()
784             ->containsFx(m_parent->getFx()))
785       menu.addAction(disconnectFromXSheet);
786     else
787       menu.addAction(connectToXSheet);
788     menu.addAction(duplicateFx);
789     if ((zsrc && zsrc->getZeraryFx() &&
790             zsrc->getZeraryFx()->getLinkedFx() != zsrc->getZeraryFx()) ||
791         fx->getLinkedFx() != fx)
792       menu.addAction(unlinkFx);
793   }
794   menu.addSeparator();
795   //}
796   if (!fx->getAttributes()->isGrouped()) menu.addAction(addOutputFx);
797   menu.addAction(preview);
798   if (enableGroupAction) menu.addAction(cacheFx);
799   menu.addSeparator();
800   if (m_type != eGroupedFx && enableInsertAction) {
801     menu.addAction(macroFx);
802     if (scene()->selectedItems().size() == 1 && m_parent->isA(eMacroFx)) {
803       menu.addAction(explodeMacroFx);
804       menu.addAction(openMacroFx);
805     }
806     menu.addAction(savePresetFx);
807     if (zsrc) {
808       menu.addSeparator();
809       menu.addAction(collapse);
810     }
811     menu.addSeparator();
812   }
813   if (enableGroupAction) {
814     menu.addAction(group);
815     if (m_type == eGroupedFx) {
816       menu.addAction(ungroup);
817       menu.addAction(editGroup);
818     }
819   }
820   menu.exec(cme->screenPos());
821 }
822 
823 //------------------------------------------------------------------------
824 /*! for small-scaled display
825 */
paint_small(QPainter * painter)826 void FxPainter::paint_small(QPainter *painter) {
827   FxSchematicScene *sceneFx = dynamic_cast<FxSchematicScene *>(scene());
828   if (!sceneFx) return;
829 
830   if (m_type == eGroupedFx) {
831     painter->save();
832     QPen pen;
833     if (m_parent->isSelected()) {
834       painter->setBrush(QColor(0, 0, 0, 0));
835       pen.setColor(QColor(255, 255, 255, 255));
836       pen.setWidth(4.0);
837       pen.setJoinStyle(Qt::RoundJoin);
838       painter->setPen(pen);
839       painter->drawRect(-2, -2, m_width + 4, m_height + 4);
840     }
841     painter->restore();
842   }
843 
844   QColor nodeColor;
845   SchematicViewer *viewer = sceneFx->getSchematicViewer();
846   viewer->getNodeColor(m_type, nodeColor);
847 
848   painter->setBrush(nodeColor);
849   painter->setPen(Qt::NoPen);
850   painter->drawRect(0, 0, m_width, m_height);
851 
852   if (m_type == eGroupedFx || m_type == eZeraryFx) {
853     QFont fnt = painter->font();
854     fnt.setPixelSize(fnt.pixelSize() * 2);
855     painter->setFont(fnt);
856     painter->setPen(viewer->getTextColor());
857     FxSchematicScene *sceneFx = dynamic_cast<FxSchematicScene *>(scene());
858     if (!sceneFx) return;
859     if (sceneFx->getCurrentFx() == m_parent->getFx())
860       painter->setPen(viewer->getSelectedNodeTextColor());
861   }
862 
863   if (m_type == eGroupedFx) {
864     if (!m_parent->isNameEditing()) {
865       QRectF rect(14, 2, 68, 22);
866       int w              = rect.width();
867       QString elidedName = elideText(m_name, painter->font(), w);
868       painter->drawText(rect, elidedName);
869     }
870   } else {
871     painter->drawPixmap(16, 6, 38, 38,
872                         FxIconPixmapManager::instance()->getFxIconPm(m_fxType));
873   }
874 
875   // show column number on the right side of icon
876   if (m_type == eZeraryFx) {
877     FxSchematicZeraryNode *zeraryNode =
878         dynamic_cast<FxSchematicZeraryNode *>(m_parent);
879     if (zeraryNode) {
880       QRect idRect(30, 10, 46, 38);
881       painter->drawText(idRect, Qt::AlignRight | Qt::AlignBottom,
882                         QString::number(zeraryNode->getColumnIndex() + 1));
883     }
884   }
885 
886   // diagonal line for disabled fx
887   bool is_enabled = false;
888   if (TZeraryColumnFx *zcFx =
889           dynamic_cast<TZeraryColumnFx *>(m_parent->getFx()))
890     is_enabled = zcFx->getColumn()->isPreviewVisible();
891   else
892     is_enabled = m_parent->getFx()->getAttributes()->isEnabled();
893   if (!is_enabled) {
894     painter->save();
895     painter->setPen(QColor(255, 0, 0, 255));
896     painter->drawLine(QPointF(10, m_height), QPointF(m_width - 10, 0));
897     painter->drawLine(QPointF(10, 0), QPointF(m_width - 10, m_height));
898     painter->restore();
899   }
900 }
901 
902 //*****************************************************
903 //
904 // FxXSheetPainter
905 //
906 //*****************************************************
907 
FxXSheetPainter(FxSchematicXSheetNode * parent,double width,double height)908 FxXSheetPainter::FxXSheetPainter(FxSchematicXSheetNode *parent, double width,
909                                  double height)
910     : QGraphicsItem(parent)
911     , m_width(width)
912     , m_height(height)
913     , m_parent(parent) {
914   setFlag(QGraphicsItem::ItemIsMovable, false);
915   setFlag(QGraphicsItem::ItemIsSelectable, false);
916   setFlag(QGraphicsItem::ItemIsFocusable, false);
917 }
918 
919 //-----------------------------------------------------
920 
~FxXSheetPainter()921 FxXSheetPainter::~FxXSheetPainter() {}
922 
923 //-----------------------------------------------------
924 
boundingRect() const925 QRectF FxXSheetPainter::boundingRect() const {
926   return QRectF(-5, -5, m_width + 10, m_height + 10);
927 }
928 
929 //-----------------------------------------------------
930 
paint(QPainter * painter,const QStyleOptionGraphicsItem * option,QWidget * widget)931 void FxXSheetPainter::paint(QPainter *painter,
932                             const QStyleOptionGraphicsItem *option,
933                             QWidget *widget) {
934   FxSchematicScene *sceneFx = dynamic_cast<FxSchematicScene *>(scene());
935   if (!sceneFx) return;
936 
937   SchematicViewer *viewer = sceneFx->getSchematicViewer();
938 
939   painter->setBrush(viewer->getXsheetColor());
940   painter->setPen(Qt::NoPen);
941   painter->drawRect(QRectF(0, 0, m_width, m_height));
942 
943   if (sceneFx->getCurrentFx() == m_parent->getFx())
944     painter->setPen(viewer->getSelectedNodeTextColor());
945   else
946     painter->setPen(viewer->getTextColor());
947   if (m_parent->isNormalIconView()) {
948     // Draw the name
949     QRectF rect(18, 0, 54, 18);
950     painter->drawText(rect, Qt::AlignLeft | Qt::AlignVCenter,
951                       QString(tr("XSheet")));
952   }
953   // small scaled
954   else {
955     QRectF rect(28, 4, 32, 32);
956     QFont fnt = painter->font();
957     fnt.setPixelSize(fnt.pixelSize() * 2);
958     painter->setFont(fnt);
959     painter->drawText(rect, Qt::AlignLeft | Qt::AlignVCenter, QString("X"));
960   }
961 }
962 
963 //-----------------------------------------------------
964 
contextMenuEvent(QGraphicsSceneContextMenuEvent * cme)965 void FxXSheetPainter::contextMenuEvent(QGraphicsSceneContextMenuEvent *cme) {
966   FxSchematicScene *fxScene = dynamic_cast<FxSchematicScene *>(scene());
967   QMenu menu(fxScene->views()[0]);
968 
969   if (cme->modifiers() & Qt::ControlModifier) {
970     menu.addAction(fxScene->getAgainAction(AddFxContextMenu::Add |
971                                            AddFxContextMenu::Insert));
972     if (!menu.actions().isEmpty()) {
973       menu.exec(cme->screenPos());
974       return;
975     }
976   }
977 
978   QMenu *insertMenu = fxScene->getInsertFxMenu();
979   fxScene->initCursorScenePos();
980   QMenu *addMenu = fxScene->getAddFxMenu();
981 
982   QAction *addOutputFx =
983       CommandManager::instance()->getAction("MI_NewOutputFx");
984 
985   QAction *addPaste = new QAction(tr("&Paste Add"), &menu);
986   connect(addPaste, SIGNAL(triggered()), fxScene, SLOT(onAddPaste()));
987 
988   QAction *preview = new QAction(tr("&Preview"), &menu);
989   connect(preview, SIGNAL(triggered()), fxScene, SLOT(onPreview()));
990 
991   menu.addMenu(insertMenu);
992   menu.addMenu(addMenu);
993   menu.addSeparator();
994   menu.addAction(addPaste);
995   menu.addAction(addOutputFx);
996   menu.addAction(preview);
997   menu.exec(cme->screenPos());
998 }
999 
1000 //*****************************************************
1001 //
1002 // FxOutputPainter
1003 //
1004 //*****************************************************
1005 
FxOutputPainter(FxSchematicOutputNode * parent,double width,double height)1006 FxOutputPainter::FxOutputPainter(FxSchematicOutputNode *parent, double width,
1007                                  double height)
1008     : QGraphicsItem(parent)
1009     , m_width(width)
1010     , m_height(height)
1011     , m_parent(parent) {
1012   setFlag(QGraphicsItem::ItemIsMovable, false);
1013   setFlag(QGraphicsItem::ItemIsSelectable, false);
1014   setFlag(QGraphicsItem::ItemIsFocusable, false);
1015   FxSchematicScene *fxScene = dynamic_cast<FxSchematicScene *>(scene());
1016   if (!fxScene) return;
1017   TFx *currentOutFx = fxScene->getXsheet()->getFxDag()->getCurrentOutputFx();
1018   m_isActive        = currentOutFx == parent->getFx();
1019 }
1020 
1021 //-----------------------------------------------------
1022 
~FxOutputPainter()1023 FxOutputPainter::~FxOutputPainter() {}
1024 
1025 //-----------------------------------------------------
1026 
boundingRect() const1027 QRectF FxOutputPainter::boundingRect() const {
1028   return QRectF(-5, -5, m_width + 10, m_height + 10);
1029 }
1030 
1031 //-----------------------------------------------------
1032 
paint(QPainter * painter,const QStyleOptionGraphicsItem * option,QWidget * widget)1033 void FxOutputPainter::paint(QPainter *painter,
1034                             const QStyleOptionGraphicsItem *option,
1035                             QWidget *widget) {
1036   FxSchematicScene *sceneFx = dynamic_cast<FxSchematicScene *>(scene());
1037   if (!sceneFx) return;
1038 
1039   SchematicViewer *viewer = sceneFx->getSchematicViewer();
1040   QColor outputColor      = m_isActive ? viewer->getActiveOutputColor()
1041                                   : viewer->getOtherOutputColor();
1042 
1043   painter->setBrush(outputColor);
1044   painter->setPen(Qt::NoPen);
1045   painter->drawRect(QRectF(0, 0, m_width, m_height));
1046 
1047   if (sceneFx->getCurrentFx() == m_parent->getFx())
1048     painter->setPen(viewer->getSelectedNodeTextColor());
1049   else
1050     painter->setPen(viewer->getTextColor());
1051   if (m_parent->isNormalIconView()) {
1052     // Draw the name
1053     QRectF rect(18, 0, 72, 18);
1054     painter->drawText(rect, Qt::AlignLeft | Qt::AlignVCenter,
1055                       QString(tr("Output")));
1056   }
1057   // small view
1058   else {
1059     QRectF rect(16, 0, 50, 36);
1060     QFont fnt = painter->font();
1061     fnt.setPixelSize(fnt.pixelSize() * 2);
1062     painter->setFont(fnt);
1063     painter->drawText(rect, Qt::AlignLeft | Qt::AlignVCenter, QString("Out"));
1064   }
1065 }
1066 
1067 //-----------------------------------------------------
1068 
contextMenuEvent(QGraphicsSceneContextMenuEvent * cme)1069 void FxOutputPainter::contextMenuEvent(QGraphicsSceneContextMenuEvent *cme) {
1070   FxSchematicScene *fxScene = dynamic_cast<FxSchematicScene *>(scene());
1071   QMenu menu(fxScene->views()[0]);
1072   if (fxScene->getXsheet()->getFxDag()->getOutputFxCount() > 1) {
1073     QAction *removeOutput = new QAction(tr("&Delete"), &menu);
1074     connect(removeOutput, SIGNAL(triggered()), fxScene, SLOT(onRemoveOutput()));
1075 
1076     QAction *activateOutput = new QAction(tr("&Activate"), &menu);
1077     connect(activateOutput, SIGNAL(triggered()), fxScene,
1078             SLOT(onActivateOutput()));
1079 
1080     TFx *currentOutFx = fxScene->getXsheet()->getFxDag()->getCurrentOutputFx();
1081     if (currentOutFx != m_parent->getFx()) menu.addAction(activateOutput);
1082     menu.addAction(removeOutput);
1083   } else {
1084     QAction *addOutputFx =
1085         CommandManager::instance()->getAction("MI_NewOutputFx");
1086     menu.addAction(addOutputFx);
1087   }
1088   menu.exec(cme->screenPos());
1089 }
1090 
1091 //*****************************************************
1092 //
1093 // FxSchematicLink
1094 //
1095 //*****************************************************
1096 
FxSchematicLink(QGraphicsItem * parent,QGraphicsScene * scene)1097 FxSchematicLink::FxSchematicLink(QGraphicsItem *parent, QGraphicsScene *scene)
1098     : SchematicLink(parent, scene) {}
1099 
1100 //-----------------------------------------------------
1101 
~FxSchematicLink()1102 FxSchematicLink::~FxSchematicLink() {}
1103 
1104 //-----------------------------------------------------
1105 
contextMenuEvent(QGraphicsSceneContextMenuEvent * cme)1106 void FxSchematicLink::contextMenuEvent(QGraphicsSceneContextMenuEvent *cme) {
1107   FxSchematicScene *fxScene = dynamic_cast<FxSchematicScene *>(scene());
1108   TFxCommand::Link link     = fxScene->getFxSelection()->getBoundingFxs(this);
1109   if (link == TFxCommand::Link()) return;
1110 
1111   QMenu menu(fxScene->views()[0]);
1112 
1113   if (cme->modifiers() & Qt::ControlModifier) {
1114     menu.addAction(fxScene->getAgainAction(AddFxContextMenu::Insert));
1115     if (!menu.actions().isEmpty()) {
1116       menu.exec(cme->screenPos());
1117       return;
1118     }
1119   }
1120 
1121   QAction *deleteFx = new QAction(tr("&Delete"), &menu);
1122   connect(deleteFx, SIGNAL(triggered()), fxScene, SLOT(onDeleteFx()));
1123 
1124   QAction *insertPaste = new QAction(tr("&Paste Insert"), &menu);
1125   connect(insertPaste, SIGNAL(triggered()), fxScene, SLOT(onInsertPaste()));
1126 
1127   menu.addMenu(fxScene->getInsertFxMenu());
1128   menu.addSeparator();
1129   menu.addAction(insertPaste);
1130   menu.addAction(deleteFx);
1131 
1132   menu.exec(cme->screenPos());
1133 }
1134 
1135 //*****************************************************
1136 //
1137 // FxSchematicPort
1138 //
1139 //*****************************************************
1140 
FxSchematicPort(FxSchematicDock * parent,int type)1141 FxSchematicPort::FxSchematicPort(FxSchematicDock *parent, int type)
1142     : SchematicPort(parent, parent->getNode(), type), m_currentTargetPort(0) {
1143   QRectF rect = boundingRect();
1144   if (getType() == eFxInputPort || getType() == eFxGroupedInPort)
1145     m_hook = QPointF(rect.left(), (rect.top() + rect.bottom()) * 0.5);
1146   else if (getType() == eFxOutputPort || getType() == eFxGroupedOutPort)
1147     m_hook = QPointF(rect.right(), (rect.top() + rect.bottom()) * 0.5);
1148   else  // link port
1149     m_hook  = QPointF(rect.right(), (rect.top() + rect.bottom()) * 0.5);
1150   m_ownerFx = getOwnerFx();
1151   TZeraryColumnFx *colFx = dynamic_cast<TZeraryColumnFx *>(m_ownerFx);
1152   if (colFx) m_ownerFx   = colFx->getZeraryFx();
1153 }
1154 
1155 //-----------------------------------------------------
1156 
~FxSchematicPort()1157 FxSchematicPort::~FxSchematicPort() {}
1158 
1159 //-----------------------------------------------------
1160 
boundingRect() const1161 QRectF FxSchematicPort::boundingRect() const {
1162   // large scaled
1163   if (getDock()->getNode()->isNormalIconView()) {
1164     switch (getType()) {
1165     case eFxInputPort:
1166     case eFxGroupedInPort:
1167       return QRectF(0, 0, 14, 14);
1168       break;
1169 
1170     case eFxOutputPort:
1171     case eFxGroupedOutPort:
1172       return QRectF(0, 0, 18, 18);
1173       break;
1174 
1175     case eFxLinkPort:  // LinkPort
1176     default:
1177       return QRectF(0, 0, 18, 7);
1178     }
1179   }
1180   // small scaled
1181   else {
1182     switch (getType()) {
1183     case eFxInputPort: {
1184       FxSchematicNode *node = getDock()->getNode();
1185       float nodeHeight =
1186           node->boundingRect().height() - 10.0f;  // 10.0 is margin
1187 
1188       TFx *fx = 0;
1189       FxSchematicZeraryNode *zeraryNode =
1190           dynamic_cast<FxSchematicZeraryNode *>(node);
1191       if (zeraryNode) {
1192         TZeraryColumnFx *zcfx =
1193             dynamic_cast<TZeraryColumnFx *>(zeraryNode->getFx());
1194         fx = zcfx->getZeraryFx();
1195       } else {
1196         fx = node->getFx();
1197       }
1198 
1199       if (fx && fx->getInputPortCount()) {
1200         // ex. particles fx etc. For fxs of which amount of ports may change
1201         if (fx->hasDynamicPortGroups())
1202           nodeHeight =
1203               (nodeHeight - (float)(2 * (fx->getInputPortCount() - 1))) /
1204               (float)fx->getInputPortCount();
1205         else
1206           nodeHeight =
1207               (nodeHeight - (float)(4 * (fx->getInputPortCount() - 1))) /
1208               (float)fx->getInputPortCount();
1209       }
1210 
1211       return QRectF(0, 0, 10, nodeHeight);
1212     } break;
1213 
1214     case eFxGroupedInPort:
1215     case eFxOutputPort:
1216     case eFxGroupedOutPort: {
1217       FxSchematicNode *node = getDock()->getNode();
1218       float nodeHeight =
1219           node->boundingRect().height() - 10.0f;  // 10.0 is margin
1220       return QRectF(0, 0, 10, nodeHeight);
1221     } break;
1222 
1223     case eFxLinkPort:  // LinkPort
1224     default:
1225       return QRectF(0, 0, 10, 5);
1226       break;
1227     }
1228   }
1229   return QRectF();
1230 }
1231 
1232 //-----------------------------------------------------
1233 
paint(QPainter * painter,const QStyleOptionGraphicsItem * option,QWidget * widget)1234 void FxSchematicPort::paint(QPainter *painter,
1235                             const QStyleOptionGraphicsItem *option,
1236                             QWidget *widget) {
1237   // large scaled
1238   if (getDock()->getNode()->isNormalIconView()) {
1239     switch (getType()) {
1240     case eFxInputPort:
1241     case eFxGroupedInPort: {
1242       QRect sourceRect =
1243           scene()->views()[0]->matrix().mapRect(boundingRect()).toRect();
1244       static QIcon fxPortRedIcon(":Resources/fxport_red.svg");
1245       QPixmap redPm = fxPortRedIcon.pixmap(sourceRect.size());
1246       sourceRect    = QRect(0, 0, sourceRect.width() * getDevPixRatio(),
1247                          sourceRect.height() * getDevPixRatio());
1248       painter->drawPixmap(boundingRect(), redPm, sourceRect);
1249     } break;
1250 
1251     case eFxOutputPort:
1252     case eFxGroupedOutPort: {
1253       QRect sourceRect =
1254           scene()->views()[0]->matrix().mapRect(boundingRect()).toRect();
1255       static QIcon fxPortBlueIcon(":Resources/fxport_blue.svg");
1256       QPixmap bluePm = fxPortBlueIcon.pixmap(sourceRect.size());
1257       sourceRect     = QRect(0, 0, sourceRect.width() * getDevPixRatio(),
1258                          sourceRect.height() * getDevPixRatio());
1259       painter->drawPixmap(boundingRect(), bluePm, sourceRect);
1260       FxSchematicDock *parentDock =
1261           dynamic_cast<FxSchematicDock *>(parentItem());
1262       if (parentDock) {
1263         FxSchematicNode *parentFxNode =
1264             dynamic_cast<FxSchematicNode *>(parentDock->parentItem());
1265         if (parentFxNode) {
1266           bool isCached = parentFxNode->isCached();
1267           if (isCached) {
1268             QPixmap cachePm = QPixmap(":Resources/cachefx.png");
1269             painter->drawPixmap(QRectF(0, 0, 18, 36), cachePm,
1270                                 QRectF(0, 0, 50, 100));
1271           }
1272         }
1273       }
1274     } break;
1275 
1276     case eFxLinkPort:  // LinkPort
1277     default: {         //ここから!!!
1278       QRect sourceRect =
1279           scene()->views()[0]->matrix().mapRect(boundingRect()).toRect();
1280       QPixmap linkPm =
1281           QIcon(":Resources/schematic_link.svg").pixmap(sourceRect.size());
1282       sourceRect = QRect(0, 0, sourceRect.width() * getDevPixRatio(),
1283                          sourceRect.height() * getDevPixRatio());
1284       painter->drawPixmap(boundingRect(), linkPm, sourceRect);
1285     } break;
1286     }
1287   }
1288   // small scaled
1289   else {
1290     painter->setPen(Qt::NoPen);
1291     switch (getType()) {
1292     case eFxInputPort:
1293     case eFxGroupedInPort: {
1294       painter->setBrush(QColor(223, 100, 100, 255));
1295     } break;
1296 
1297     case eFxOutputPort:
1298     case eFxGroupedOutPort: {
1299       painter->setBrush(QColor(100, 100, 223, 255));
1300     } break;
1301 
1302     case eFxLinkPort:  // LinkPort
1303     {
1304       QRect sourceRect =
1305           scene()->views()[0]->matrix().mapRect(boundingRect()).toRect();
1306       QPixmap linkPm = QIcon(":Resources/schematic_link_small.svg")
1307                            .pixmap(sourceRect.size());
1308       sourceRect = QRect(0, 0, sourceRect.width() * getDevPixRatio(),
1309                          sourceRect.height() * getDevPixRatio());
1310       painter->drawPixmap(boundingRect(), linkPm, sourceRect);
1311     } break;
1312     }
1313     painter->drawRect(boundingRect());
1314   }
1315 }
1316 
1317 //-----------------------------------------------------
1318 
getDock() const1319 FxSchematicDock *FxSchematicPort::getDock() const {
1320   return dynamic_cast<FxSchematicDock *>(parentItem());
1321 }
1322 
1323 //-----------------------------------------------------
1324 
makeLink(SchematicPort * port)1325 SchematicLink *FxSchematicPort::makeLink(SchematicPort *port) {
1326   if (isLinkedTo(port) || !port) return 0;
1327   FxSchematicLink *link = new FxSchematicLink(0, scene());
1328   if (getType() == eFxLinkPort && port->getType() == eFxLinkPort)
1329     link->setLineShaped(true);
1330 
1331   link->setStartPort(this);
1332   link->setEndPort(port);
1333   addLink(link);
1334   port->addLink(link);
1335   link->updatePath();
1336   return link;
1337 }
1338 
1339 //-----------------------------------------------------
1340 
linkTo(SchematicPort * port,bool checkOnly)1341 bool FxSchematicPort::linkTo(SchematicPort *port, bool checkOnly) {
1342   if (port == this) return false;
1343 
1344   FxSchematicNode *dstNode = dynamic_cast<FxSchematicNode *>(port->getNode());
1345   FxSchematicNode *srcNode = dynamic_cast<FxSchematicNode *>(getNode());
1346   if (dstNode == srcNode) return false;
1347 
1348   TFx *inputFx = 0, *fx = 0;
1349   int portIndex = 0;
1350   if (getType() == eFxInputPort && port->getType() == eFxOutputPort) {
1351     inputFx   = dstNode->getFx();
1352     fx        = srcNode->getFx();
1353     portIndex = srcNode->getInputDockId(this->getDock());
1354   } else if (getType() == eFxOutputPort && port->getType() == eFxInputPort) {
1355     inputFx   = srcNode->getFx();
1356     fx        = dstNode->getFx();
1357     portIndex = dstNode->getInputDockId(
1358         (dynamic_cast<FxSchematicPort *>(port))->getDock());
1359   } else
1360     return false;
1361   if (inputFx->getAttributes()->isGrouped() &&
1362       fx->getAttributes()->isGrouped() &&
1363       inputFx->getAttributes()->getEditingGroupId() !=
1364           fx->getAttributes()->getEditingGroupId())
1365     return false;
1366 
1367   FxSchematicScene *fxScene = dynamic_cast<FxSchematicScene *>(scene());
1368   if (!fxScene) return false;
1369   FxDag *fxDag = fxScene->getXsheet()->getFxDag();
1370   if (fxDag->checkLoop(inputFx, fx)) return false;
1371   if (!checkOnly) linkEffects(inputFx, fx, portIndex);
1372   return true;
1373 }
1374 
1375 //-----------------------------------------------------
1376 
linkEffects(TFx * inputFx,TFx * fx,int inputId)1377 void FxSchematicPort::linkEffects(TFx *inputFx, TFx *fx, int inputId) {
1378   FxSchematicScene *fxScene = dynamic_cast<FxSchematicScene *>(scene());
1379   if (!fxScene) return;
1380   TFxCommand::setParent(inputFx, fx, inputId, fxScene->getXsheetHandle());
1381 }
1382 
1383 //-----------------------------------------------------
1384 
hideSnappedLinks(SchematicPort *)1385 void FxSchematicPort::hideSnappedLinks(SchematicPort *) {
1386   if (!m_linkingTo) return;
1387   if (m_linkingTo->getType() == eFxInputPort &&
1388       m_linkingTo->getLinkCount() == 1) {
1389     FxSchematicXSheetNode *xsheetNode =
1390         dynamic_cast<FxSchematicXSheetNode *>(m_linkingTo->getNode());
1391     if (!xsheetNode) m_linkingTo->getLink(0)->hide();
1392   }
1393   if (m_linkingTo->getType() == eFxOutputPort &&
1394       m_linkingTo->getLinkCount() >= 1) {
1395     int i;
1396     for (i = 0; i < m_linkingTo->getLinkCount(); i++) {
1397       SchematicLink *link               = m_linkingTo->getLink(i);
1398       FxSchematicXSheetNode *xsheetNode = dynamic_cast<FxSchematicXSheetNode *>(
1399           link->getOtherNode(m_linkingTo->getNode()));
1400       if (xsheetNode) link->hide();
1401     }
1402   }
1403   if (getType() == eFxInputPort && getLinkCount() == 1) {
1404     FxSchematicXSheetNode *xsheetNode =
1405         dynamic_cast<FxSchematicXSheetNode *>(getNode());
1406     if (!xsheetNode) getLink(0)->hide();
1407   }
1408   if (getType() == eFxOutputPort && getLinkCount() == 1) {
1409     FxSchematicXSheetNode *xsheetNode = dynamic_cast<FxSchematicXSheetNode *>(
1410         getLink(0)->getOtherNode(this->getNode()));
1411     if (xsheetNode) getLink(0)->hide();
1412   }
1413 }
1414 
1415 //-----------------------------------------------------
1416 
showSnappedLinks(SchematicPort *)1417 void FxSchematicPort::showSnappedLinks(SchematicPort *) {
1418   if (!m_linkingTo) return;
1419   if (m_linkingTo->getType() == eFxInputPort &&
1420       m_linkingTo->getLinkCount() == 1) {
1421     FxSchematicXSheetNode *xsheetNode =
1422         dynamic_cast<FxSchematicXSheetNode *>(m_linkingTo->getNode());
1423     if (!xsheetNode) m_linkingTo->getLink(0)->show();
1424   }
1425   if (m_linkingTo->getType() == eFxOutputPort &&
1426       m_linkingTo->getLinkCount() >= 1) {
1427     int i;
1428     for (i = 0; i < m_linkingTo->getLinkCount(); i++) {
1429       SchematicLink *link               = m_linkingTo->getLink(i);
1430       FxSchematicXSheetNode *xsheetNode = dynamic_cast<FxSchematicXSheetNode *>(
1431           link->getOtherNode(m_linkingTo->getNode()));
1432       if (xsheetNode) link->show();
1433     }
1434   }
1435   if (getType() == eFxInputPort && getLinkCount() == 1) {
1436     FxSchematicXSheetNode *xsheetNode =
1437         dynamic_cast<FxSchematicXSheetNode *>(getNode());
1438     if (!xsheetNode) getLink(0)->show();
1439   }
1440   if (getType() == eFxOutputPort && getLinkCount() == 1) {
1441     FxSchematicXSheetNode *xsheetNode = dynamic_cast<FxSchematicXSheetNode *>(
1442         getLink(0)->getOtherNode(this->getNode()));
1443     if (xsheetNode) getLink(0)->show();
1444   }
1445 }
1446 
1447 //-----------------------------------------------------
1448 
searchPort(const QPointF & scenePos)1449 SchematicPort *FxSchematicPort::searchPort(const QPointF &scenePos) {
1450   FxSchematicScene *fxScene = dynamic_cast<FxSchematicScene *>(scene());
1451   assert(fxScene);
1452   TXsheet *xsh                 = fxScene->getXsheet();
1453   QList<QGraphicsItem *> items = scene()->items(scenePos);
1454   int i;
1455   for (i = 0; i < items.size(); i++) {
1456     FxSchematicPort *linkingTo = dynamic_cast<FxSchematicPort *>(items[i]);
1457     if (linkingTo && linkingTo->getType() != eFxLinkPort) {
1458       TFx *fx = linkingTo->getDock()->getNode()->getFx();
1459       assert(fx);
1460       if ((!fx->getAttributes()->isGrouped() ||
1461            fx->getAttributes()->isGroupEditing()) &&
1462           !isAInnerMacroFx(fx, xsh))
1463         return linkingTo;
1464     }
1465     FxSchematicDock *linkingDock = dynamic_cast<FxSchematicDock *>(items[i]);
1466     if (linkingDock && linkingDock->getPort()->getType() != eFxLinkPort) {
1467       TFx *fx = linkingDock->getNode()->getFx();
1468       assert(fx);
1469       if ((!fx->getAttributes()->isGrouped() ||
1470            fx->getAttributes()->isGroupEditing()) &&
1471           !isAInnerMacroFx(fx, xsh))
1472         return linkingDock->getPort();
1473     }
1474     FxSchematicXSheetNode *linkingNode =
1475         dynamic_cast<FxSchematicXSheetNode *>(items[i]);
1476     if (linkingNode && getType() == eFxOutputPort)
1477       return linkingNode->getInputPort(0);
1478     if (linkingNode && getType() == eFxInputPort)
1479       return linkingNode->getOutputPort();
1480     FxSchematicOutputNode *outFx =
1481         dynamic_cast<FxSchematicOutputNode *>(items[i]);
1482     if (outFx && getType() == eFxOutputPort) return outFx->getInputPort(0);
1483   }
1484   return 0;
1485 }
1486 //-----------------------------------------------------
1487 
handleSnappedLinksOnDynamicPortFx(const std::vector<TFxPort * > & groupedPorts,int targetIndex,int startIndex)1488 void FxSchematicPort::handleSnappedLinksOnDynamicPortFx(
1489     const std::vector<TFxPort *> &groupedPorts, int targetIndex,
1490     int startIndex) {
1491   FxSchematicNode *node = dynamic_cast<FxSchematicNode *>(getNode());
1492   if (!m_ownerFx->hasDynamicPortGroups() || !node) return;
1493   int groupedPortCount           = groupedPorts.size();
1494   if (startIndex < 0) startIndex = groupedPortCount - 1;
1495   if (startIndex >= groupedPortCount || targetIndex >= groupedPortCount) return;
1496   int i;
1497 
1498   // hide existing links
1499   QMap<int, SchematicPort *> linkedPorts;
1500   int minIndex = std::min(targetIndex, startIndex);
1501   int maxIndex = std::max(targetIndex, startIndex);
1502   for (i = minIndex; i <= maxIndex; i++) {
1503     TFxPort *currentPort = groupedPorts[i];
1504     int portId = getInputPortIndex(currentPort, currentPort->getOwnerFx());
1505     if (portId == -1) continue;
1506     FxSchematicPort *port = node->getInputPort(portId);
1507     SchematicLink *link   = port->getLink(0);
1508     if (link) {
1509       linkedPorts[i] = link->getOtherPort(port);
1510       link->hide();
1511       m_hiddenLinks.append(link);
1512     }
1513   }
1514 
1515   // create ghost links
1516   if (targetIndex < startIndex) {
1517     for (i = targetIndex + 1; i <= startIndex; i++) {
1518       TFxPort *currentPort = groupedPorts[i];
1519       int portId = getInputPortIndex(currentPort, currentPort->getOwnerFx());
1520       if (portId == -1) continue;
1521       FxSchematicPort *port = node->getInputPort(portId);
1522       SchematicLink *link   = port->makeLink(linkedPorts[i - 1]);
1523       if (link) m_ghostLinks.append(link);
1524     }
1525   } else {
1526     for (i = startIndex; i < targetIndex; i++) {
1527       TFxPort *currentPort = groupedPorts[i];
1528       int portId = getInputPortIndex(currentPort, currentPort->getOwnerFx());
1529       if (portId == -1) continue;
1530       FxSchematicPort *port = node->getInputPort(portId);
1531       SchematicLink *link   = port->makeLink(linkedPorts[i + 1]);
1532       if (link) m_ghostLinks.append(link);
1533     }
1534   }
1535 }
1536 
1537 //-----------------------------------------------------
1538 
resetSnappedLinksOnDynamicPortFx()1539 void FxSchematicPort::resetSnappedLinksOnDynamicPortFx() {
1540   int i;
1541   for (i = 0; i < m_hiddenLinks.size(); i++) m_hiddenLinks.at(i)->show();
1542   m_hiddenLinks.clear();
1543   for (i = 0; i < m_ghostLinks.size(); i++) {
1544     SchematicLink *link = m_ghostLinks.at(i);
1545     link->getStartPort()->removeLink(link);
1546     link->getEndPort()->removeLink(link);
1547     scene()->removeItem(link);
1548     delete link;
1549   }
1550   m_ghostLinks.clear();
1551 }
1552 
1553 //-----------------------------------------------------
1554 
contextMenuEvent(QGraphicsSceneContextMenuEvent * cme)1555 void FxSchematicPort::contextMenuEvent(QGraphicsSceneContextMenuEvent *cme) {
1556   FxSchematicScene *fxScene = dynamic_cast<FxSchematicScene *>(scene());
1557   QMenu menu(fxScene->views()[0]);
1558 
1559   TFx *fx = getDock()->getNode()->getFx();
1560   bool enableInsertAction =
1561       fxScene->getXsheet()->getFxDag()->getInternalFxs()->containsFx(fx) &&
1562       (!fx->getAttributes()->isGrouped() ||
1563        fx->getAttributes()->isGroupEditing());
1564 
1565   if ((getType() == eFxOutputPort || getType() == eFxGroupedOutPort) &&
1566       enableInsertAction) {
1567     fxScene->initCursorScenePos();
1568     if (cme->modifiers() & Qt::ControlModifier) {
1569       menu.addAction(fxScene->getAgainAction(AddFxContextMenu::Add));
1570       if (!menu.actions().isEmpty()) {
1571         menu.exec(cme->screenPos());
1572         return;
1573       }
1574     }
1575 
1576     QAction *disconnectFromXSheet =
1577         new QAction(tr("&Disconnect from Xsheet"), &menu);
1578     connect(disconnectFromXSheet, SIGNAL(triggered()), fxScene,
1579             SLOT(onDisconnectFromXSheet()));
1580 
1581     QAction *connectToXSheet = new QAction(tr("&Connect to Xsheet"), &menu);
1582     connect(connectToXSheet, SIGNAL(triggered()), fxScene,
1583             SLOT(onConnectToXSheet()));
1584 
1585     QAction *fxEditorPopup =
1586         CommandManager::instance()->getAction(MI_FxParamEditor);
1587 
1588     menu.addMenu(fxScene->getAddFxMenu());
1589     menu.addAction(fxEditorPopup);
1590     if (fxScene->getXsheet()->getFxDag()->getTerminalFxs()->containsFx(
1591             getDock()->getNode()->getFx()))
1592       menu.addAction(disconnectFromXSheet);
1593     else
1594       menu.addAction(connectToXSheet);
1595   }
1596   menu.exec(cme->screenPos());
1597 }
1598 
1599 //-----------------------------------------------------
1600 
mouseMoveEvent(QGraphicsSceneMouseEvent * me)1601 void FxSchematicPort::mouseMoveEvent(QGraphicsSceneMouseEvent *me) {
1602   SchematicPort::mouseMoveEvent(me);
1603   if (!m_ghostLinks.isEmpty() && !m_ghostLinks[0]->isVisible())
1604     m_ghostLinks[0]->show();
1605   bool cntr = me->modifiers() == Qt::ControlModifier;
1606   if (m_currentTargetPort) {
1607     m_currentTargetPort->resetSnappedLinksOnDynamicPortFx();
1608     m_currentTargetPort = 0;
1609   }
1610   if (!m_linkingTo) return;
1611   FxSchematicPort *targetPort = dynamic_cast<FxSchematicPort *>(m_linkingTo);
1612   assert(targetPort);
1613   m_currentTargetPort    = targetPort;
1614   TFx *targetFx          = targetPort->getOwnerFx();
1615   TZeraryColumnFx *colFx = dynamic_cast<TZeraryColumnFx *>(targetFx);
1616   if (colFx) targetFx    = colFx->getZeraryFx();
1617   if (targetPort->getType() != eFxInputPort ||
1618       !targetFx->hasDynamicPortGroups() || targetPort == this)
1619     return;
1620 
1621   FxSchematicNode *node =
1622       dynamic_cast<FxSchematicNode *>(targetPort->getNode());
1623   int id                = node->getInputDockId(targetPort->getDock());
1624   TFxPort *targetFxPort = targetFx->getInputPort(id);
1625   int groupId           = targetFxPort->getGroupIndex();
1626 
1627   if (groupId < 0) return;
1628 
1629   std::vector<TFxPort *> groupedPorts =
1630       targetFx->dynamicPortGroup(groupId)->ports();
1631   int portId = getIndex(targetFxPort, groupedPorts);
1632   if (portId == -1) return;
1633   if (targetFx != m_ownerFx && cntr && getType() == eFxOutputPort)
1634     targetPort->handleSnappedLinksOnDynamicPortFx(groupedPorts, portId);
1635   else if (targetFx == m_ownerFx && getType() == eFxInputPort) {
1636     if (!m_ghostLinks.isEmpty()) {
1637       for (SchematicLink *ghostLink : m_ghostLinks)
1638         scene()->removeItem(ghostLink);
1639       qDeleteAll(m_ghostLinks.begin(), m_ghostLinks.end());
1640       m_ghostLinks.clear();
1641     }
1642     FxSchematicNode *thisNode = dynamic_cast<FxSchematicNode *>(getNode());
1643     int thisId                = thisNode->getInputDockId(getDock());
1644     TFxPort *thisFxPort       = targetFx->getInputPort(thisId);
1645     int thisGroupId           = thisFxPort->getGroupIndex();
1646     if (thisGroupId != groupId) return;
1647     int thisPortId = getIndex(thisFxPort, groupedPorts);
1648     if (thisPortId == -1) return;
1649     targetPort->handleSnappedLinksOnDynamicPortFx(groupedPorts, portId,
1650                                                   thisPortId);
1651     SchematicLink *link = getLink(0);
1652     assert(link);
1653     SchematicLink *ghostLink = targetPort->makeLink(link->getOtherPort(this));
1654     if (ghostLink) {
1655       targetPort->m_ghostLinks.append(ghostLink);
1656     }
1657   }
1658 }
1659 
1660 //-----------------------------------------------------
1661 
mouseReleaseEvent(QGraphicsSceneMouseEvent * me)1662 void FxSchematicPort::mouseReleaseEvent(QGraphicsSceneMouseEvent *me) {
1663   if (m_currentTargetPort)
1664     m_currentTargetPort->resetSnappedLinksOnDynamicPortFx();
1665   m_currentTargetPort = 0;
1666   FxSchematicPort *targetPort =
1667       dynamic_cast<FxSchematicPort *>(searchPort(me->scenePos()));
1668   if (!targetPort)  // not over a port: do nothing
1669   {
1670     SchematicPort::mouseReleaseEvent(me);
1671     return;
1672   }
1673   TFx *targetOwnerFx       = targetPort->getOwnerFx();
1674   TZeraryColumnFx *colFx   = dynamic_cast<TZeraryColumnFx *>(targetOwnerFx);
1675   if (colFx) targetOwnerFx = colFx->getZeraryFx();
1676 
1677   // if the target fx has no dynamic port or has dinamic ports but the tatgert
1678   // port is not an input port: do nothing!
1679   if (!targetOwnerFx || !targetOwnerFx->hasDynamicPortGroups() ||
1680       targetPort->getType() != eFxInputPort) {
1681     SchematicPort::mouseReleaseEvent(me);
1682     return;
1683   }
1684   FxSchematicNode *targetNode =
1685       dynamic_cast<FxSchematicNode *>(targetPort->getNode());
1686   int targetFxId        = targetNode->getInputDockId(targetPort->getDock());
1687   TFxPort *targetFxPort = targetOwnerFx->getInputPort(targetFxId);
1688   int targetGroupId     = targetFxPort->getGroupIndex();
1689 
1690   if (targetGroupId < 0) {
1691     SchematicPort::mouseReleaseEvent(me);
1692     return;
1693   }
1694 
1695   std::vector<TFxPort *> groupedPorts =
1696       targetOwnerFx->dynamicPortGroup(targetGroupId)->ports();
1697   int groupedPortCount = groupedPorts.size();
1698   if (targetOwnerFx != m_ownerFx && me->modifiers() == Qt::ControlModifier &&
1699       linkTo(targetPort, true)) {
1700     // trying to link different fxs insertin the new link and shifting the
1701     // others
1702     int targetIndex = getIndex(targetFxPort, groupedPorts);
1703     if (targetIndex == -1) {
1704       SchematicPort::mouseReleaseEvent(me);
1705       return;
1706     }
1707 
1708     int i;
1709     TUndoManager::manager()->beginBlock();
1710     for (i = groupedPortCount - 1; i > targetIndex; i--) {
1711       TFxPort *currentPort   = groupedPorts[i];
1712       TFxPort *precedentPort = groupedPorts[i - 1];
1713       int currentPortIndex   = getInputPortIndex(currentPort, targetOwnerFx);
1714       linkEffects(precedentPort->getFx(), colFx ? colFx : targetOwnerFx,
1715                   currentPortIndex);
1716     }
1717     linkTo(targetPort);
1718     TUndoManager::manager()->endBlock();
1719     emit sceneChanged();
1720     emit xsheetChanged();
1721   } else if (targetOwnerFx == m_ownerFx && m_type == eFxInputPort &&
1722              getLink(0) && targetPort != this) {
1723     // reordering of links in input of the same fxs
1724     /*FxSchematicNode* linkedNode =
1725 dynamic_cast<FxSchematicNode*>(getLinkedNode(0));
1726 assert(linkedNode);
1727 TFx* linkedFx = linkedNode->getFx();
1728 assert(linkedFx);*/
1729 
1730     int thisFxId        = targetNode->getInputDockId(getDock());
1731     TFxPort *thisFxPort = m_ownerFx->getInputPort(thisFxId);
1732     TFx *linkedFx       = thisFxPort->getFx();
1733 
1734     int targetIndex = getIndex(targetFxPort, groupedPorts);
1735     int thisIndex   = getIndex(thisFxPort, groupedPorts);
1736     if (targetIndex != -1 && thisIndex != -1 && thisIndex != targetIndex) {
1737       TUndoManager::manager()->beginBlock();
1738 
1739       // linkEffects(0,colFx ? colFx : m_ownerFx,thisFxId);
1740       if (thisIndex > targetIndex) {
1741         int i;
1742         for (i = thisIndex; i > targetIndex; i--) {
1743           TFxPort *currentPort   = groupedPorts[i];
1744           TFxPort *precedentPort = groupedPorts[i - 1];
1745           int currentId          = getInputPortIndex(currentPort, m_ownerFx);
1746           linkEffects(precedentPort->getFx(), colFx ? colFx : m_ownerFx,
1747                       currentId);
1748         }
1749       } else {
1750         int i;
1751         for (i = thisIndex; i < targetIndex; i++) {
1752           TFxPort *currentPort = groupedPorts[i];
1753           TFxPort *nextPort    = groupedPorts[i + 1];
1754           int currentId        = getInputPortIndex(currentPort, m_ownerFx);
1755           linkEffects(nextPort->getFx(), colFx ? colFx : m_ownerFx, currentId);
1756         }
1757       }
1758       linkEffects(linkedFx, colFx ? colFx : m_ownerFx, targetFxId);
1759       TUndoManager::manager()->endBlock();
1760       emit sceneChanged();
1761       emit xsheetChanged();
1762     } else
1763       SchematicPort::mouseReleaseEvent(me);
1764   } else
1765     SchematicPort::mouseReleaseEvent(me);
1766 }
1767 
1768 //-----------------------------------------------------
1769 
getOwnerFx() const1770 TFx *FxSchematicPort::getOwnerFx() const {
1771   FxSchematicNode *node = dynamic_cast<FxSchematicNode *>(this->getNode());
1772   if (!node) return 0;
1773   return node->getFx();
1774 }
1775 
1776 //*****************************************************
1777 //
1778 // FxSchematicDock
1779 //
1780 //*****************************************************
1781 
FxSchematicDock(FxSchematicNode * parent,const QString & name,double width,eFxSchematicPortType type)1782 FxSchematicDock::FxSchematicDock(FxSchematicNode *parent, const QString &name,
1783                                  double width, eFxSchematicPortType type)
1784     : QGraphicsItem(parent), m_name(name), m_width(width) {
1785   m_port = new FxSchematicPort(this, type);
1786   m_port->setPos(0, 0);
1787   if (parent) {
1788     TFx *fx       = parent->getFx();
1789     TFxPort *port = fx->getInputPort(name.toStdString());
1790     if (port) {
1791       TFx *inputFx = port->getFx();
1792       if (inputFx) {
1793         TLevelColumnFx *levelFx    = dynamic_cast<TLevelColumnFx *>(inputFx);
1794         TPaletteColumnFx *palettFx = dynamic_cast<TPaletteColumnFx *>(inputFx);
1795         if (levelFx || palettFx) {
1796           int index =
1797               levelFx ? levelFx->getColumnIndex() : palettFx->getColumnIndex();
1798           TStageObjectId objId         = TStageObjectId::ColumnId(index);
1799           QGraphicsScene *graphicScene = scene();
1800           FxSchematicScene *schematicScene =
1801               dynamic_cast<FxSchematicScene *>(graphicScene);
1802           if (schematicScene) {
1803             std::string colName =
1804                 schematicScene->getXsheet()->getStageObject(objId)->getName();
1805             setToolTip(QString::fromStdString(colName));
1806           }
1807         } else {
1808           TZeraryColumnFx *zeraryFx = dynamic_cast<TZeraryColumnFx *>(inputFx);
1809           if (zeraryFx) inputFx     = zeraryFx->getZeraryFx();
1810           setToolTip(QString::fromStdWString(inputFx->getName()));
1811         }
1812       }
1813     }
1814   }
1815   connect(m_port, SIGNAL(sceneChanged()), parent, SIGNAL(sceneChanged()));
1816   connect(m_port, SIGNAL(xsheetChanged()), parent, SIGNAL(xsheetChanged()));
1817 }
1818 
1819 //-----------------------------------------------------
1820 
~FxSchematicDock()1821 FxSchematicDock::~FxSchematicDock() {}
1822 
1823 //-----------------------------------------------------
1824 
boundingRect() const1825 QRectF FxSchematicDock::boundingRect() const {
1826   return QRectF(0, 0, m_width, m_port->boundingRect().height());
1827 }
1828 
1829 //-----------------------------------------------------
1830 
paint(QPainter * painter,const QStyleOptionGraphicsItem * option,QWidget * widget)1831 void FxSchematicDock::paint(QPainter *painter,
1832                             const QStyleOptionGraphicsItem *option,
1833                             QWidget *widget) {
1834   if (m_port->getType() == eFxInputPort ||
1835       m_port->getType() == eFxGroupedInPort) {
1836     // do nothing when small scaled
1837     if (!getNode()->isNormalIconView()) return;
1838 
1839     painter->setPen(Qt::NoPen);
1840     painter->setBrush(QColor(0, 0, 0, 192));
1841     painter->drawRect(boundingRect());
1842 
1843     QFont tempFont(painter->font());
1844     tempFont.setPixelSize(tempFont.pixelSize() - 1);
1845     painter->setFont(tempFont);
1846 
1847     painter->setPen(Qt::white);
1848     painter->drawText(boundingRect().adjusted(18, 0, 0, 0),
1849                       Qt::AlignLeft | Qt::AlignVCenter, m_name);
1850   }
1851 }
1852 
1853 //-----------------------------------------------------
1854 
getNode()1855 FxSchematicNode *FxSchematicDock::getNode() {
1856   FxSchematicNode *node = dynamic_cast<FxSchematicNode *>(parentItem());
1857   return node;
1858 }
1859 
1860 //*****************************************************
1861 //
1862 // FxSchematicNode
1863 //
1864 //*****************************************************
1865 
FxSchematicNode(FxSchematicScene * scene,TFx * fx,qreal width,qreal height,eFxType type)1866 FxSchematicNode::FxSchematicNode(FxSchematicScene *scene, TFx *fx, qreal width,
1867                                  qreal height, eFxType type)
1868     : SchematicNode(scene)
1869     , m_fx(fx)
1870     , m_type(type)
1871     , m_isCurrentFxLinked(false)
1872     , m_isNormalIconView(scene->isNormalIconView()) {
1873   if (m_type == eGroupedFx)
1874     m_actualFx = 0;
1875   else {
1876     // m_fx could be the zerary wrapper to the actual (user-coded) fx - find and
1877     // store it.
1878     TZeraryColumnFx *zfx = dynamic_cast<TZeraryColumnFx *>(m_fx.getPointer());
1879     m_actualFx           = zfx ? zfx->getZeraryFx() : m_fx;
1880   }
1881 
1882   setWidth(width);
1883   setHeight(height);
1884 }
1885 
1886 //-----------------------------------------------------
1887 
setSchematicNodePos(const QPointF & pos) const1888 void FxSchematicNode::setSchematicNodePos(const QPointF &pos) const {
1889   TPointD p(pos.x(), pos.y());
1890   if (!m_fx->getAttributes()->isGrouped() ||
1891       m_fx->getAttributes()->isGroupEditing()) {
1892     TPointD oldFxPos = m_fx->getAttributes()->getDagNodePos();
1893     m_fx->getAttributes()->setDagNodePos(p);
1894     TMacroFx *macro = dynamic_cast<TMacroFx *>(m_fx.getPointer());
1895     if (macro) {
1896       TPointD delta =
1897           p - (oldFxPos != TConst::nowhere ? oldFxPos : TPointD(0, 0));
1898       std::vector<TFxP> fxs = macro->getFxs();
1899       int i;
1900       for (i = 0; i < (int)fxs.size(); i++) {
1901         TPointD oldPos = fxs[i]->getAttributes()->getDagNodePos();
1902         if (oldPos != TConst::nowhere)
1903           fxs[i]->getAttributes()->setDagNodePos(oldPos + delta);
1904       }
1905     }
1906   } else {
1907     const FxGroupNode *groupNode = dynamic_cast<const FxGroupNode *>(this);
1908     assert(groupNode);
1909     groupNode->updateFxsDagPosition(p);
1910   }
1911 }
1912 
1913 //-----------------------------------------------------
1914 
getInputDockId(FxSchematicDock * dock)1915 int FxSchematicNode::getInputDockId(FxSchematicDock *dock) {
1916   return m_inDocks.indexOf(dock);
1917 }
1918 
1919 //-----------------------------------------------------
1920 
onClicked()1921 void FxSchematicNode::onClicked() {
1922   emit switchCurrentFx(m_fx.getPointer());
1923   if (TColumnFx *cfx = dynamic_cast<TColumnFx *>(m_fx.getPointer())) {
1924     int columnIndex = cfx->getColumnIndex();
1925     if (columnIndex >= 0) emit currentColumnChanged(columnIndex);
1926   }
1927 }
1928 
1929 //-----------------------------------------------------
1930 
setIsCurrentFxLinked(bool value,FxSchematicNode * comingNode)1931 void FxSchematicNode::setIsCurrentFxLinked(bool value,
1932                                            FxSchematicNode *comingNode) {
1933   m_isCurrentFxLinked = value;
1934   update();
1935   if (!m_linkDock) return;
1936   int i;
1937   for (i = 0; i < m_linkDock->getPort()->getLinkCount(); i++) {
1938     SchematicNode *node = m_linkDock->getPort()->getLinkedNode(i);
1939     if (!node || node == comingNode) continue;
1940     FxSchematicNode *fxNode = dynamic_cast<FxSchematicNode *>(node);
1941     assert(fxNode);
1942     fxNode->setIsCurrentFxLinked(value, this);
1943   }
1944 }
1945 
1946 //-----------------------------------------------------
1947 
setPosition(const QPointF & newPos)1948 void FxSchematicNode::setPosition(const QPointF &newPos) {
1949   FxSchematicScene *fxScene = dynamic_cast<FxSchematicScene *>(scene());
1950   assert(fxScene);
1951   fxScene->updateNestedGroupEditors(this, newPos);
1952 }
1953 
1954 //-----------------------------------------------------
1955 
isEnabled() const1956 bool FxSchematicNode::isEnabled() const {
1957   TZeraryColumnFx *zcFx = dynamic_cast<TZeraryColumnFx *>(m_fx.getPointer());
1958   return zcFx ? zcFx->getColumn()->isPreviewVisible()
1959               : m_fx->getAttributes()->isEnabled();
1960 }
1961 
1962 //-----------------------------------------------------
1963 
isCached() const1964 bool FxSchematicNode::isCached() const {
1965   return TPassiveCacheManager::instance()->cacheEnabled(m_fx.getPointer());
1966 }
1967 
1968 //-----------------------------------------------------
1969 
checkDynamicInputPortSize() const1970 void FxSchematicNode::checkDynamicInputPortSize() const {
1971   assert(m_actualFx);
1972 
1973   if (!m_actualFx->hasDynamicPortGroups()) return;
1974 
1975   // Shift holes in each dynamic port group links toward the end of the group
1976   shiftLinks();
1977 
1978   // Treat each dynamic port group independently
1979   int g, gCount = m_actualFx->dynamicPortGroupsCount();
1980   for (g = 0; g != gCount; ++g) {
1981     const TFxPortDG *group = m_actualFx->dynamicPortGroup(g);
1982     int gSize              = group->ports().size();
1983 
1984     int minPortsCount = group->minPortsCount();
1985 
1986     if (gSize < minPortsCount) {
1987       // Add empty ports up to the group's minimal required quota
1988       for (; gSize != minPortsCount; ++gSize) addDynamicInputPort(g);
1989     }
1990 
1991     // Must remove all unlinked ports beyond the minimal - however, we'll be
1992     // iterating
1993     // on the ports container, so it's easier if we avoid removing WHILE
1994     // iterating
1995 
1996     // So, fill in a list of all the fx's unlinked ports first
1997     QList<std::string> unlinkedPorts;
1998 
1999     int p, portCount = m_actualFx->getInputPortCount();
2000     for (p = 0; p != portCount; ++p) {
2001       TFxPort *port = m_actualFx->getInputPort(p);
2002       assert(port);
2003 
2004       if ((port->getGroupIndex() == g) && !port->isConnected())
2005         unlinkedPorts.append(m_actualFx->getInputPortName(p));
2006     }
2007 
2008     // Remove excess empty ports save for 1 (needed to let the user insert new
2009     // links)
2010     if (unlinkedPorts.empty())
2011       addDynamicInputPort(g);
2012     else {
2013       while (unlinkedPorts.size() > 1 &&
2014              m_actualFx->getInputPortCount() > minPortsCount) {
2015         removeDynamicInputPort(unlinkedPorts.last());
2016         unlinkedPorts.pop_back();
2017       }
2018     }
2019   }
2020 }
2021 
2022 //-----------------------------------------------------
2023 
addDynamicInputPort(int groupIdx) const2024 void FxSchematicNode::addDynamicInputPort(int groupIdx) const {
2025   assert(m_actualFx);
2026   assert(groupIdx < m_actualFx->dynamicPortGroupsCount());
2027 
2028   TFxPort *port = new TRasterFxPort;
2029 
2030   // Add the port with a suitable port name
2031   const TFxPortDG *group = m_actualFx->dynamicPortGroup(groupIdx);
2032 
2033   for (int n =
2034            group->ports().size() + 1;  // +1 since ports start from <prefix>1
2035        !m_actualFx->addInputPort(
2036            group->portsPrefix() + QString::number(n).toStdString(), port,
2037            groupIdx);
2038        ++n)
2039     ;
2040 }
2041 
2042 //-----------------------------------------------------
2043 
removeDynamicInputPort(const std::string & name) const2044 bool FxSchematicNode::removeDynamicInputPort(const std::string &name) const {
2045   assert(m_actualFx);
2046 
2047   TFxPort *port = m_actualFx->getInputPort(
2048       name);  // Must retrieve the port to access its infos
2049   if (!port || port->getFx() || port->getGroupIndex() < 0) {
2050     assert(port && !port->isConnected() && port->getGroupIndex() >= 0);
2051     return false;
2052   }
2053 
2054   m_actualFx->removeInputPort(name);
2055   // delete port;                                                // TFxPortDG
2056   // owns it - so it would be wrong
2057 
2058   return true;
2059 }
2060 
2061 //-----------------------------------------------------
2062 
shiftLinks() const2063 void FxSchematicNode::shiftLinks() const {
2064   struct locals {
2065     // Advances p along the ports array, stopping at the first port in the group
2066     // with the specified
2067     // connection state. Returns whether the port index is in the ports array
2068     // range.
2069     static inline bool moveToNext(const TFxPortDG &group, bool connected,
2070                                   int &p) {
2071       int pCount = group.ports().size();
2072       while (p < pCount && (group.ports()[p]->isConnected() != connected)) ++p;
2073 
2074       return (p < pCount);
2075     }
2076 
2077   };  // locals
2078 
2079   assert(m_actualFx);
2080 
2081   // Treat each dynamic port group individually
2082   int g, gCount = m_actualFx->dynamicPortGroupsCount();
2083   for (g = 0; g != gCount; ++g) {
2084     const TFxPortDG *group = m_actualFx->dynamicPortGroup(g);
2085 
2086     // Traverse fx ports, moving all the group links to the front
2087 
2088     // First, couple empty and not-empty ports manually
2089     int e = 0;
2090     locals::moveToNext(*group, false, e);  // manual advance
2091 
2092     int ne = e + 1;
2093 
2094     if (locals::moveToNext(*group, true, ne))  // manual advance
2095     {
2096       do {
2097         // Swap links between the empty and not-empty ports
2098         TFxPort *ePort  = group->ports()[e];
2099         TFxPort *nePort = group->ports()[ne];
2100 
2101         ePort->setFx(nePort->getFx());
2102         nePort->setFx(0);
2103 
2104         ++e, ++ne;
2105 
2106         // Then, advance coupled from there
2107       } while (locals::moveToNext(*group, false, e) &&
2108                locals::moveToNext(*group, true, ne));
2109     }
2110   }
2111 }
2112 
2113 //-----------------------------------------------------
2114 
updateOutputDockToolTips(const QString & name)2115 void FxSchematicNode::updateOutputDockToolTips(const QString &name) {
2116   FxSchematicPort *outPort = getOutputPort();
2117   int i;
2118   for (i = 0; i < outPort->getLinkCount(); i++) {
2119     SchematicLink *link = outPort->getLink(i);
2120     if (!link) continue;
2121     SchematicPort *linkedPort = link->getOtherPort(outPort);
2122     assert(linkedPort);
2123     FxSchematicPort *linkedFxPort = dynamic_cast<FxSchematicPort *>(linkedPort);
2124     FxSchematicDock *linkedFxDock = linkedFxPort->getDock();
2125     linkedFxDock->setToolTip(name);
2126   }
2127 }
2128 
2129 //-----------------------------------------------------
2130 
updatePortsPosition()2131 void FxSchematicNode::updatePortsPosition() {
2132   struct locals {
2133     struct PositionAssigner {
2134       double m_lastYPos;
2135       bool isLarge;
2136 
2137       inline void assign(FxSchematicDock *dock) {
2138         dock->setPos(0, m_lastYPos);
2139 
2140         if (isLarge)
2141           m_lastYPos += dock->boundingRect().height();
2142         else
2143           m_lastYPos += dock->boundingRect().height() + 4;  // 4 is margin
2144       }
2145     };
2146 
2147   };  // locals
2148 
2149   locals::PositionAssigner positioner;
2150   if (m_isNormalIconView) {
2151     positioner.m_lastYPos = m_height;
2152     positioner.isLarge    = true;
2153   } else {
2154     positioner.m_lastYPos = 0;
2155     positioner.isLarge    = false;
2156   }
2157 
2158   if (!(m_actualFx && m_actualFx->hasDynamicPortGroups())) {
2159     // 'Fake' or common schematic fx nodes can just list the prepared m_inDocks
2160     // container incrementally
2161     for (int i = 0; i != m_inDocks.size(); ++i) positioner.assign(m_inDocks[i]);
2162   } else {
2163     // Otherwise, port groups must be treated
2164     assert(m_inDocks.size() == m_actualFx->getInputPortCount());
2165 
2166     int incrementalGroupIndex = -1;  // We'll assume that groups are encountered
2167     // incrementally (requires not ill-formed fxs).
2168     int p, pCount = m_actualFx->getInputPortCount();
2169     for (p = 0; p != pCount; ++p) {
2170       int g = m_actualFx->getInputPort(p)->getGroupIndex();
2171       if (g < 0)
2172         positioner.assign(
2173             m_inDocks[p]);  // The port is in no group - just add it
2174       else if (g > incrementalGroupIndex) {
2175         // Position the whole group
2176         incrementalGroupIndex = g;
2177 
2178         for (int gp = p; gp != pCount; ++gp)
2179           if (m_actualFx->getInputPort(gp)->getGroupIndex() == g)
2180             positioner.assign(m_inDocks[gp]);
2181       }
2182     }
2183   }
2184 }
2185 
2186 //*****************************************************
2187 //
2188 // FxSchematicOutputNode
2189 //
2190 //*****************************************************
2191 
FxSchematicOutputNode(FxSchematicScene * scene,TOutputFx * fx)2192 FxSchematicOutputNode::FxSchematicOutputNode(FxSchematicScene *scene,
2193                                              TOutputFx *fx)
2194     : FxSchematicNode(scene, fx, 67, 18, eOutpuFx) {
2195   // resize if small scaled
2196   if (!m_isNormalIconView) {
2197     setWidth(60);
2198     setHeight(36);
2199   }
2200 
2201   m_linkedNode            = 0;
2202   m_outDock               = 0;
2203   m_linkDock              = 0;
2204   FxSchematicDock *inDock = new FxSchematicDock(this, "", 0, eFxInputPort);
2205   if (m_isNormalIconView)
2206     inDock->setPos(0, 2);
2207   else
2208     inDock->setPos(0, 0);
2209   inDock->setZValue(2);
2210   m_inDocks.push_back(inDock);
2211   addPort(0, inDock->getPort());
2212   m_outputPainter = new FxOutputPainter(this, m_width, m_height);
2213   m_outputPainter->setZValue(1);
2214 
2215   setToolTip(tr("Output"));
2216 }
2217 
2218 //-----------------------------------------------------
2219 
~FxSchematicOutputNode()2220 FxSchematicOutputNode::~FxSchematicOutputNode() {}
2221 
2222 //-----------------------------------------------------
2223 
boundingRect() const2224 QRectF FxSchematicOutputNode::boundingRect() const {
2225   return QRectF(-5, -5, m_width + 10, m_height + 10);
2226 }
2227 
2228 //-----------------------------------------------------
2229 
paint(QPainter * painter,const QStyleOptionGraphicsItem * option,QWidget * widget)2230 void FxSchematicOutputNode::paint(QPainter *painter,
2231                                   const QStyleOptionGraphicsItem *option,
2232                                   QWidget *widget) {
2233   FxSchematicNode::paint(painter, option, widget);
2234 }
2235 
2236 //-----------------------------------------------------
2237 
mouseDoubleClickEvent(QGraphicsSceneMouseEvent * me)2238 void FxSchematicOutputNode::mouseDoubleClickEvent(
2239     QGraphicsSceneMouseEvent *me) {
2240   QAction *outputSettingsPopup =
2241       CommandManager::instance()->getAction("MI_OutputSettings");
2242   outputSettingsPopup->trigger();
2243 }
2244 
mousePressEvent(QGraphicsSceneMouseEvent * me)2245 void FxSchematicOutputNode::mousePressEvent(QGraphicsSceneMouseEvent *me) {
2246   FxSchematicNode::mousePressEvent(me);
2247 
2248   QAction *fxEditorPopup =
2249       CommandManager::instance()->getAction(MI_FxParamEditor);
2250   // this signal cause the update the contents of the FxSettings
2251   if (fxEditorPopup->isVisible()) emit fxNodeDoubleClicked();
2252 }
2253 
2254 //*****************************************************
2255 //
2256 // FxSchematicXSheetNode
2257 //
2258 //*****************************************************
2259 
FxSchematicXSheetNode(FxSchematicScene * scene,TXsheetFx * fx)2260 FxSchematicXSheetNode::FxSchematicXSheetNode(FxSchematicScene *scene,
2261                                              TXsheetFx *fx)
2262     : FxSchematicNode(scene, fx, 90, 18, eXSheetFx) {
2263   if (!m_isNormalIconView) {
2264     setWidth(70);
2265     setHeight(36);
2266   }
2267 
2268   m_linkedNode = 0;
2269   m_linkDock   = 0;
2270 
2271   m_outDock               = new FxSchematicDock(this, "", 0, eFxOutputPort);
2272   FxSchematicDock *inDock = new FxSchematicDock(this, "", 0, eFxInputPort);
2273   m_xsheetPainter         = new FxXSheetPainter(this, m_width, m_height);
2274 
2275   addPort(0, m_outDock->getPort());
2276   addPort(1, inDock->getPort());
2277 
2278   m_inDocks.push_back(inDock);
2279 
2280   if (m_isNormalIconView) {
2281     m_outDock->setPos(72, 0);
2282     inDock->setPos(0, 2);
2283   } else {
2284     m_outDock->setPos(60, 0);
2285     inDock->setPos(0, 0);
2286   }
2287 
2288   m_outDock->setZValue(2);
2289   inDock->setZValue(2);
2290   m_xsheetPainter->setZValue(1);
2291 
2292   setToolTip(tr("XSheet"));
2293 }
2294 
2295 //-----------------------------------------------------
2296 
~FxSchematicXSheetNode()2297 FxSchematicXSheetNode::~FxSchematicXSheetNode() {}
2298 
2299 //-----------------------------------------------------
2300 
boundingRect() const2301 QRectF FxSchematicXSheetNode::boundingRect() const {
2302   return QRectF(-5, -5, m_width + 10, m_height + 10);
2303 }
2304 
2305 //-----------------------------------------------------
2306 
paint(QPainter * painter,const QStyleOptionGraphicsItem * option,QWidget * widget)2307 void FxSchematicXSheetNode::paint(QPainter *painter,
2308                                   const QStyleOptionGraphicsItem *option,
2309                                   QWidget *widget) {
2310   FxSchematicNode::paint(painter, option, widget);
2311 }
2312 
2313 //-----------------------------------------------------
2314 
mouseDoubleClickEvent(QGraphicsSceneMouseEvent * me)2315 void FxSchematicXSheetNode::mouseDoubleClickEvent(
2316     QGraphicsSceneMouseEvent *me) {
2317   QAction *sceneSettingsPopup =
2318       CommandManager::instance()->getAction("MI_SceneSettings");
2319   sceneSettingsPopup->trigger();
2320 }
2321 
mousePressEvent(QGraphicsSceneMouseEvent * me)2322 void FxSchematicXSheetNode::mousePressEvent(QGraphicsSceneMouseEvent *me) {
2323   FxSchematicNode::mousePressEvent(me);
2324 
2325   QAction *fxEditorPopup =
2326       CommandManager::instance()->getAction(MI_FxParamEditor);
2327   // this signal cause the update the contents of the FxSettings
2328   if (fxEditorPopup->isVisible()) emit fxNodeDoubleClicked();
2329 }
2330 
2331 //*****************************************************
2332 //
2333 // FxSchematicNormalFxNode
2334 //
2335 //*****************************************************
2336 
2337 // TODO: Fxの分類、各Fxに自己申告させるべき 2016/1/8 shun_iwasawa
2338 namespace {
isImageAdjustFx(std::string id)2339 bool isImageAdjustFx(std::string id) {
2340   if (id == "STD_toneCurveFx" || id == "STD_inoChannelSelectorFx" ||
2341       id == "STD_inoDensityFx" || id == "STD_inohlsAddFx" ||
2342       id == "STD_inohlsAdjustFx" || id == "STD_inohsvAddFx" ||
2343       id == "STD_inohsvAdjustFx" || id == "STD_inoLevelAutoFx" ||
2344       id == "STD_inoLevelMasterFx" || id == "STD_inoLevelrgbaFx" ||
2345       id == "STD_inoNegateFx" || id == "STD_localTransparencyFx" ||
2346       id == "STD_multiToneFx" || id == "STD_premultiplyFx" ||
2347       id == "STD_rgbmCutFx" || id == "STD_rgbmFadeFx" ||
2348       id == "STD_rgbmScaleFx" || id == "STD_sharpenFx" || id == "STD_fadeFx")
2349     return true;
2350   else
2351     return false;
2352 }
2353 
isLayerBlendingFx(std::string id)2354 bool isLayerBlendingFx(std::string id) {
2355   if (id == "STD_inoOverFx" || id == "STD_inoCrossDissolveFx" ||
2356       id == "STD_inoDarkenFx" || id == "STD_inoMultiplyFx" ||
2357       id == "STD_inoColorBurnFx" || id == "STD_inoLinearBurnFx" ||
2358       id == "STD_inoDarkerColorFx" || id == "STD_inoAddFx" ||
2359       id == "STD_inoLightenFx" || id == "STD_inoScreenFx" ||
2360       id == "STD_inoColorDodgeFx" || id == "STD_inoLinearDodgeFx" ||
2361       id == "STD_inoLighterColorFx" || id == "STD_inoOverlayFx" ||
2362       id == "STD_inoSoftLightFx" || id == "STD_inoHardLightFx" ||
2363       id == "STD_inoVividLightFx" || id == "STD_inoLinearLightFx" ||
2364       id == "STD_inoPinLightFx" || id == "STD_inoHardMixFx" ||
2365       id == "STD_inoDivideFx" || id == "STD_inoSubtractFx")
2366     return true;
2367   else
2368     return false;
2369 }
2370 
isMatteFx(std::string id)2371 bool isMatteFx(std::string id) {
2372   if (id == "STD_hsvKeyFx" || id == "inFx" || id == "outFx" ||
2373       id == "STD_rgbKeyFx" || id == "atopFx")
2374     return true;
2375   else
2376     return false;
2377 }
2378 };
2379 
FxSchematicNormalFxNode(FxSchematicScene * scene,TFx * fx)2380 FxSchematicNormalFxNode::FxSchematicNormalFxNode(FxSchematicScene *scene,
2381                                                  TFx *fx)
2382     : FxSchematicNode(scene, fx, 90, 32, eNormalFx) {
2383   SchematicViewer *viewer = scene->getSchematicViewer();
2384 
2385   checkDynamicInputPortSize();
2386 
2387   // resize if small scaled
2388   if (!m_isNormalIconView) {
2389     setWidth(70);
2390     setHeight(50);
2391   }
2392 
2393   TMacroFx *macroFx = dynamic_cast<TMacroFx *>(fx);
2394   if (macroFx) {
2395     m_type                = eMacroFx;
2396     std::vector<TFxP> fxs = macroFx->getFxs();
2397     bool enable           = false;
2398     int i;
2399     for (i = 0; i < (int)fxs.size(); i++)
2400       enable = enable || fxs[i]->getAttributes()->isEnabled();
2401     macroFx->getAttributes()->enable(enable);
2402   }
2403   m_name       = QString::fromStdWString(fx->getName());
2404   m_linkedNode = 0;
2405 
2406   // set fx type
2407   std::string id = fx->getFxType();
2408   if (isImageAdjustFx(id))
2409     m_type = eNormalImageAdjustFx;
2410   else if (isLayerBlendingFx(id))
2411     m_type = eNormalLayerBlendingFx;
2412   else if (isMatteFx(id))
2413     m_type = eNormalMatteFx;
2414 
2415   switch (m_type) {
2416   case eNormalFx:
2417   case eMacroFx:
2418   case eNormalLayerBlendingFx:
2419   case eNormalMatteFx:
2420   case eNormalImageAdjustFx: {
2421     QString fxId = QString::fromStdWString(getFx()->getFxId());
2422     if (m_name != fxId)
2423       setToolTip(QString("%1 : %2").arg(m_name, fxId));
2424     else
2425       setToolTip(m_name);
2426   } break;
2427   case eZeraryFx: {
2428     TZeraryColumnFx *zfx = dynamic_cast<TZeraryColumnFx *>(getFx());
2429     if (zfx) {
2430       TFx *zeraryFx = zfx->getZeraryFx();
2431       if (zeraryFx) {
2432         setToolTip(QString("%1 : %2").arg(
2433             m_name, QString::fromStdWString(zeraryFx->getFxId())));
2434       }
2435     }
2436     break;
2437   }
2438   case eGroupedFx: {
2439     QString fxId =
2440         "Group " + QString::number(getFx()->getAttributes()->getGroupId());
2441     if (m_name != fxId)
2442       setToolTip(QString("%1 (%2)").arg(m_name, fxId));
2443     else
2444       setToolTip(m_name);
2445   }
2446   default:
2447     break;
2448   }
2449 
2450   m_nameItem = new SchematicName(this, 72, 20);  // for rename
2451   m_outDock  = new FxSchematicDock(this, "", 0, eFxOutputPort);
2452   m_linkDock = new FxSchematicDock(this, "", 0, eFxLinkPort);
2453 
2454   m_renderToggle = new SchematicToggle(
2455       this, viewer->getSchematicPreviewButtonOnImage(),
2456       viewer->getSchematicPreviewButtonBgOnColor(),
2457       viewer->getSchematicPreviewButtonOffImage(),
2458       viewer->getSchematicPreviewButtonBgOffColor(), 0, m_isNormalIconView);
2459 
2460   m_painter =
2461       new FxPainter(this, m_width, m_height, m_name, m_type, fx->getFxType());
2462 
2463   m_linkedNode = 0;
2464   //-----
2465   m_nameItem->setName(m_name);
2466   m_renderToggle->setIsActive(m_fx->getAttributes()->isEnabled());
2467 
2468   addPort(0, m_outDock->getPort());
2469   addPort(-1, m_linkDock->getPort());
2470 
2471   if (m_isNormalIconView) {
2472     m_nameItem->setPos(1, -1);
2473     m_outDock->setPos(72, 14);
2474     m_linkDock->setPos(72, 7);
2475     m_renderToggle->setPos(72, 0);
2476   } else {
2477     QFont fnt = m_nameItem->font();
2478     fnt.setPixelSize(fnt.pixelSize() * 2);
2479     m_nameItem->setFont(fnt);
2480 
2481     m_nameItem->setPos(-1, 0);
2482     m_outDock->setPos(60, 0);
2483     m_linkDock->setPos(60, -5);
2484     m_renderToggle->setPos(30, -5);
2485   }
2486 
2487   m_nameItem->setZValue(3);
2488   m_outDock->setZValue(2);
2489   m_linkDock->setZValue(2);
2490   m_renderToggle->setZValue(2);
2491   m_painter->setZValue(1);
2492 
2493   connect(m_nameItem, SIGNAL(focusOut()), this, SLOT(onNameChanged()));
2494   connect(m_renderToggle, SIGNAL(toggled(bool)), this,
2495           SLOT(onRenderToggleClicked(bool)));
2496   m_nameItem->hide();
2497 
2498   int i, inputPorts = fx->getInputPortCount();
2499   double lastPosY = (m_isNormalIconView) ? m_height : 0;
2500   for (i = 0; i < inputPorts; i++) {
2501     std::string portName = fx->getInputPortName(i);
2502     QString qPortName    = QString::fromStdString(portName);
2503     QString toolTip      = "";
2504     if (isA(eMacroFx)) {
2505       // Add a Tool Tip to the Dock showing the name of the port and the
2506       // original fx id.
2507       int firstIndex  = qPortName.indexOf("_");
2508       int secondIndex = qPortName.indexOf("_", firstIndex + 1);
2509       qPortName.remove(qPortName.indexOf("_"), secondIndex - firstIndex);
2510       toolTip = qPortName;
2511       toolTip.replace("_", "(");
2512       toolTip.append(")");
2513       QString qInMacroFxId = qPortName;
2514       qInMacroFxId.remove(0, qInMacroFxId.indexOf("_") + 1);
2515       std::vector<TFxP> macroFxs = macroFx->getFxs();
2516       int j;
2517       for (j = 0; j < (int)macroFxs.size(); j++) {
2518         TFx *inMacroFx      = macroFxs[j].getPointer();
2519         std::wstring fxName = inMacroFx->getName();
2520         QString qFxName     = QString::fromStdWString(fxName);
2521         if (inMacroFx->getFxId() == qInMacroFxId.toStdWString()) {
2522           int count = inMacroFx->getInputPortCount();
2523           if (count == 1)
2524             qPortName = qFxName;
2525           else {
2526             qPortName.remove(1, qPortName.size());
2527             qPortName += ". " + qFxName;
2528           }
2529         }
2530       }
2531     }
2532 
2533     FxSchematicDock *inDock;
2534 
2535     if (m_isNormalIconView) {
2536       inDock = new FxSchematicDock(this, qPortName, m_width - 18, eFxInputPort);
2537       inDock->setPos(0, lastPosY);
2538       lastPosY += inDock->boundingRect().height();
2539     } else {
2540       inDock = new FxSchematicDock(this, qPortName, 10, eFxInputPort);
2541       inDock->setPos(0, lastPosY);
2542       lastPosY += inDock->boundingRect().height() + 4;  // 4 is margin
2543     }
2544 
2545     inDock->setZValue(2);
2546     m_inDocks.push_back(inDock);
2547     addPort(i + 1, inDock->getPort());
2548     if (toolTip != "") inDock->setToolTip(toolTip);
2549   }
2550 }
2551 
2552 //-----------------------------------------------------
2553 
~FxSchematicNormalFxNode()2554 FxSchematicNormalFxNode::~FxSchematicNormalFxNode() {}
2555 
2556 //-----------------------------------------------------
2557 
boundingRect() const2558 QRectF FxSchematicNormalFxNode::boundingRect() const {
2559   return QRectF(-5, -5, m_width + 10, m_height + 10);
2560 }
2561 
2562 //-----------------------------------------------------
2563 
paint(QPainter * painter,const QStyleOptionGraphicsItem * option,QWidget * widget)2564 void FxSchematicNormalFxNode::paint(QPainter *painter,
2565                                     const QStyleOptionGraphicsItem *option,
2566                                     QWidget *widget) {
2567   FxSchematicNode::paint(painter, option, widget);
2568 }
2569 
2570 //-----------------------------------------------------
2571 
onNameChanged()2572 void FxSchematicNormalFxNode::onNameChanged() {
2573   m_nameItem->hide();
2574   m_name = m_nameItem->toPlainText();
2575   m_painter->setName(m_name);
2576 
2577   switch (m_type) {
2578   case eNormalFx:
2579   case eMacroFx:
2580   case eNormalLayerBlendingFx:
2581   case eNormalMatteFx:
2582   case eNormalImageAdjustFx: {
2583     QString fxId = QString::fromStdWString(getFx()->getFxId());
2584     if (m_name != fxId)
2585       setToolTip(QString("%1 : %2").arg(m_name, fxId));
2586     else
2587       setToolTip(m_name);
2588   } break;
2589   case eZeraryFx: {
2590     TZeraryColumnFx *zfx = dynamic_cast<TZeraryColumnFx *>(getFx());
2591     if (zfx) {
2592       TFx *zeraryFx = zfx->getZeraryFx();
2593       if (zeraryFx) {
2594         setToolTip(QString("%1 : %2").arg(
2595             m_name, QString::fromStdWString(zeraryFx->getFxId())));
2596       }
2597     }
2598     break;
2599   }
2600   case eGroupedFx: {
2601     QString fxId =
2602         "Group " + QString::number(getFx()->getAttributes()->getGroupId());
2603     if (m_name != fxId)
2604       setToolTip(QString("%1 (%2)").arg(m_name, fxId));
2605     else
2606       setToolTip(m_name);
2607   }
2608   default:
2609     break;
2610   }
2611 
2612   setFlag(QGraphicsItem::ItemIsSelectable, true);
2613   FxSchematicScene *fxScene = dynamic_cast<FxSchematicScene *>(scene());
2614   if (!fxScene) return;
2615   TFxCommand::renameFx(m_fx.getPointer(), m_name.toStdWString(),
2616                        fxScene->getXsheetHandle());
2617   updateOutputDockToolTips(m_name);
2618   emit sceneChanged();
2619   update();
2620 }
2621 
2622 //-----------------------------------------------------
2623 
onRenderToggleClicked(bool value)2624 void FxSchematicNormalFxNode::onRenderToggleClicked(bool value) {
2625   m_fx->getAttributes()->enable(value);
2626   TMacroFx *macro = dynamic_cast<TMacroFx *>(m_fx.getPointer());
2627   if (macro) {
2628     std::vector<TFxP> fxs = macro->getFxs();
2629     int i;
2630     for (i = 0; i < (int)fxs.size(); i++)
2631       fxs[i]->getAttributes()->enable(value);
2632   }
2633   update();
2634   emit sceneChanged();
2635   emit xsheetChanged();
2636 }
2637 
2638 //-----------------------------------------------------
2639 
mouseDoubleClickEvent(QGraphicsSceneMouseEvent * me)2640 void FxSchematicNormalFxNode::mouseDoubleClickEvent(
2641     QGraphicsSceneMouseEvent *me) {
2642   QRectF nameArea(0, 0, m_width, 14);
2643   if (nameArea.contains(me->pos()) && me->modifiers() == Qt::ControlModifier) {
2644     m_nameItem->setPlainText(m_name);
2645     m_nameItem->show();
2646     m_nameItem->setFocus();
2647     setFlag(QGraphicsItem::ItemIsSelectable, false);
2648   } else {
2649     QAction *fxEditorPopup =
2650         CommandManager::instance()->getAction(MI_FxParamEditor);
2651     fxEditorPopup->trigger();
2652     // this signal cause the update the contents of the FxSettings
2653     emit fxNodeDoubleClicked();
2654   }
2655 }
2656 
2657 //-----------------------------------------------------
2658 
mousePressEvent(QGraphicsSceneMouseEvent * me)2659 void FxSchematicNormalFxNode::mousePressEvent(QGraphicsSceneMouseEvent *me) {
2660   FxSchematicNode::mousePressEvent(me);
2661 
2662   QAction *fxEditorPopup =
2663       CommandManager::instance()->getAction(MI_FxParamEditor);
2664   // this signal cause the update the contents of the FxSettings
2665   if (fxEditorPopup->isVisible()) emit fxNodeDoubleClicked();
2666 }
2667 
2668 //-----------------------------------------------------
2669 
resize(bool maximized)2670 void FxSchematicNormalFxNode::resize(bool maximized) {}
2671 
2672 //*****************************************************
2673 //
2674 // FxSchematicZeraryNode
2675 //
2676 //*****************************************************
2677 
FxSchematicZeraryNode(FxSchematicScene * scene,TZeraryColumnFx * fx)2678 FxSchematicZeraryNode::FxSchematicZeraryNode(FxSchematicScene *scene,
2679                                              TZeraryColumnFx *fx)
2680     : FxSchematicNode(scene, fx, 90, 32, eZeraryFx) {
2681   SchematicViewer *viewer = scene->getSchematicViewer();
2682 
2683   checkDynamicInputPortSize();
2684 
2685   if (!m_isNormalIconView) {
2686     setWidth(90);
2687     setHeight(50);
2688   }
2689 
2690   m_columnIndex = fx->getColumnIndex();
2691 
2692   TXshColumn *column = scene->getXsheet()->getColumn(m_columnIndex);
2693 
2694   TFx *zeraryFx     = fx->getZeraryFx();
2695   TStageObjectId id = TStageObjectId::ColumnId(m_columnIndex);
2696   std::string name  = scene->getXsheet()->getStageObject(id)->getName();
2697 
2698   if (column) {
2699     // ZeraryFx columns store name elsewhere
2700     TXshZeraryFxColumn *zColumn = dynamic_cast<TXshZeraryFxColumn *>(column);
2701     if (zColumn)
2702       name =
2703           ::to_string(zColumn->getZeraryColumnFx()->getZeraryFx()->getName());
2704   }
2705 
2706   m_name = QString::fromStdString(name);
2707 
2708   setToolTip(QString("%1 : %2").arg(
2709       m_name, QString::fromStdWString(zeraryFx->getFxId())));
2710 
2711   m_nameItem = new SchematicName(this, 72, 20);  // for rename
2712   m_outDock  = new FxSchematicDock(this, "", 0, eFxOutputPort);
2713   m_linkDock = new FxSchematicDock(this, "", 0, eFxLinkPort);
2714   m_renderToggle =
2715       new SchematicToggle(this, viewer->getSchematicPreviewButtonOnImage(),
2716                           viewer->getSchematicPreviewButtonBgOnColor(),
2717                           viewer->getSchematicPreviewButtonOffImage(),
2718                           viewer->getSchematicPreviewButtonBgOffColor(),
2719                           SchematicToggle::eIsParentColumn, m_isNormalIconView);
2720 
2721   m_cameraStandToggle = new SchematicToggle(
2722       this, viewer->getSchematicCamstandButtonOnImage(),
2723       viewer->getSchematicCamstandButtonTranspImage(),
2724       viewer->getSchematicCamstandButtonBgOnColor(),
2725       viewer->getSchematicCamstandButtonOffImage(),
2726       viewer->getSchematicCamstandButtonBgOffColor(),
2727       SchematicToggle::eIsParentColumn | SchematicToggle::eEnableNullState,
2728       m_isNormalIconView);
2729 
2730   // get the fx icons according to the fx type
2731   m_painter = new FxPainter(this, m_width, m_height, m_name, m_type,
2732                             zeraryFx->getFxType());
2733 
2734   m_linkedNode = 0;
2735 
2736   //---
2737   m_nameItem->setName(m_name);
2738   m_nameItem->hide();
2739 
2740   addPort(0, m_outDock->getPort());
2741   addPort(-1, m_linkDock->getPort());
2742 
2743   if (column) {
2744     m_renderToggle->setIsActive(column->isPreviewVisible());
2745     m_cameraStandToggle->setState(
2746         column->isCamstandVisible() ? (column->getOpacity() < 255 ? 2 : 1) : 0);
2747   }
2748 
2749   // define positions
2750   if (m_isNormalIconView) {
2751     m_nameItem->setPos(1, -1);
2752     m_outDock->setPos(72, 14);
2753     m_linkDock->setPos(72, m_height);
2754     m_renderToggle->setPos(72, 0);
2755     m_cameraStandToggle->setPos(72, 7);
2756 
2757   } else {
2758     QFont fnt = m_nameItem->font();
2759     fnt.setPixelSize(fnt.pixelSize() * 2);
2760     m_nameItem->setFont(fnt);
2761 
2762     m_nameItem->setPos(-1, 0);
2763     m_outDock->setPos(80, 0);
2764     m_linkDock->setPos(80, -5);
2765     m_renderToggle->setPos(50, -5);
2766     m_cameraStandToggle->setPos(20, -5);
2767   }
2768 
2769   m_nameItem->setZValue(3);
2770   m_outDock->setZValue(2);
2771   m_renderToggle->setZValue(2);
2772   m_cameraStandToggle->setZValue(2);
2773   m_painter->setZValue(1);
2774 
2775   connect(m_nameItem, SIGNAL(focusOut()), this, SLOT(onNameChanged()));
2776   connect(m_renderToggle, SIGNAL(toggled(bool)), this,
2777           SLOT(onRenderToggleClicked(bool)));
2778   connect(m_cameraStandToggle, SIGNAL(stateChanged(int)), this,
2779           SLOT(onCameraStandToggleClicked(int)));
2780 
2781   if (zeraryFx) {
2782     int i, inputPorts = zeraryFx->getInputPortCount();
2783     double lastPosY = (m_isNormalIconView) ? m_height : 0;
2784 
2785     for (i = 0; i < inputPorts; i++) {
2786       FxSchematicDock *inDock;
2787       if (m_isNormalIconView) {
2788         inDock = new FxSchematicDock(
2789             this, QString::fromStdString(zeraryFx->getInputPortName(i)),
2790             m_width - 18, eFxInputPort);
2791         inDock->setPos(0, lastPosY);
2792         lastPosY += inDock->boundingRect().height();
2793       } else {
2794         inDock = new FxSchematicDock(
2795             this, QString::fromStdString(zeraryFx->getInputPortName(i)), 10,
2796             eFxInputPort);
2797         inDock->setPos(0, lastPosY);
2798         lastPosY += inDock->boundingRect().height() + 4;  // 4 is margin
2799       }
2800 
2801       m_inDocks.push_back(inDock);
2802       addPort(i + 1, inDock->getPort());
2803     }
2804   }
2805 
2806   updatePortsPosition();
2807   updateLinksGeometry();
2808 }
2809 
2810 //-----------------------------------------------------
2811 
~FxSchematicZeraryNode()2812 FxSchematicZeraryNode::~FxSchematicZeraryNode() {}
2813 
2814 //-----------------------------------------------------
2815 
boundingRect() const2816 QRectF FxSchematicZeraryNode::boundingRect() const {
2817   return QRectF(-5, -5, m_width + 10, m_height + 10);
2818 }
2819 
2820 //-----------------------------------------------------
2821 
paint(QPainter * painter,const QStyleOptionGraphicsItem * option,QWidget * widget)2822 void FxSchematicZeraryNode::paint(QPainter *painter,
2823                                   const QStyleOptionGraphicsItem *option,
2824                                   QWidget *widget) {
2825   FxSchematicNode::paint(painter, option, widget);
2826 }
2827 
2828 //-----------------------------------------------------
2829 
onRenderToggleClicked(bool toggled)2830 void FxSchematicZeraryNode::onRenderToggleClicked(bool toggled) {
2831   FxSchematicScene *fxScene = dynamic_cast<FxSchematicScene *>(scene());
2832   if (!fxScene) return;
2833   TXshColumn *column = fxScene->getXsheet()->getColumn(m_columnIndex);
2834   if (column) {
2835     column->setPreviewVisible(toggled);
2836     emit sceneChanged();
2837     emit xsheetChanged();
2838   }
2839 }
2840 
2841 //-----------------------------------------------------
2842 
onCameraStandToggleClicked(int state)2843 void FxSchematicZeraryNode::onCameraStandToggleClicked(int state) {
2844   FxSchematicScene *fxScene = dynamic_cast<FxSchematicScene *>(scene());
2845   if (!fxScene) return;
2846   TXshColumn *column = fxScene->getXsheet()->getColumn(m_columnIndex);
2847   if (column) {
2848     column->setCamstandVisible(!column->isCamstandVisible());
2849     // column->setCamstandVisible(toggled);
2850     emit sceneChanged();
2851     emit xsheetChanged();
2852   }
2853 }
2854 
2855 //-----------------------------------------------------
2856 
isCached() const2857 bool FxSchematicZeraryNode::isCached() const {
2858   TZeraryColumnFx *zfx = dynamic_cast<TZeraryColumnFx *>(m_fx.getPointer());
2859   if (!zfx)
2860     return TPassiveCacheManager::instance()->cacheEnabled(m_fx.getPointer());
2861   TFx *zeraryFx = zfx->getZeraryFx();
2862 
2863   if (zeraryFx)
2864     return TPassiveCacheManager::instance()->cacheEnabled(zeraryFx);
2865   else
2866     return TPassiveCacheManager::instance()->cacheEnabled(m_fx.getPointer());
2867 }
2868 
2869 //-----------------------------------------------------
2870 
mouseDoubleClickEvent(QGraphicsSceneMouseEvent * me)2871 void FxSchematicZeraryNode::mouseDoubleClickEvent(
2872     QGraphicsSceneMouseEvent *me) {
2873   QRectF nameArea(0, 0, m_width, 14);
2874   if (nameArea.contains(me->pos()) && me->modifiers() == Qt::ControlModifier) {
2875     FxSchematicScene *fxScene = dynamic_cast<FxSchematicScene *>(scene());
2876     TXshColumn *column        = fxScene->getXsheet()->getColumn(m_columnIndex);
2877     TStageObjectId id         = TStageObjectId::ColumnId(m_columnIndex);
2878     std::string name = fxScene->getXsheet()->getStageObject(id)->getName();
2879 
2880     if (column) {
2881       // ZeraryFx columns store name elsewhere
2882       TXshZeraryFxColumn *zColumn = dynamic_cast<TXshZeraryFxColumn *>(column);
2883       if (zColumn)
2884         name =
2885             ::to_string(zColumn->getZeraryColumnFx()->getZeraryFx()->getName());
2886     }
2887 
2888     m_name = QString::fromStdString(name);
2889 
2890     m_nameItem->setPlainText(m_name);
2891     m_nameItem->show();
2892     m_nameItem->setFocus();
2893     setFlag(QGraphicsItem::ItemIsSelectable, false);
2894   } else {
2895     QAction *fxEditorPopup =
2896         CommandManager::instance()->getAction(MI_FxParamEditor);
2897     fxEditorPopup->trigger();
2898 
2899     // this signal cause the update the contents of the FxSettings
2900     emit fxNodeDoubleClicked();
2901   }
2902 }
2903 
2904 //-----------------------------------------------------
2905 
mousePressEvent(QGraphicsSceneMouseEvent * me)2906 void FxSchematicZeraryNode::mousePressEvent(QGraphicsSceneMouseEvent *me) {
2907   FxSchematicNode::mousePressEvent(me);
2908 
2909   QAction *fxEditorPopup =
2910       CommandManager::instance()->getAction(MI_FxParamEditor);
2911   // this signal cause the update the contents of the FxSettings
2912   if (fxEditorPopup->isVisible()) emit fxNodeDoubleClicked();
2913 }
2914 
2915 //-----------------------------------------------------
2916 
onNameChanged()2917 void FxSchematicZeraryNode::onNameChanged() {
2918   m_nameItem->hide();
2919   m_name = m_nameItem->toPlainText();
2920   m_painter->setName(m_name);
2921 
2922   setFlag(QGraphicsItem::ItemIsSelectable, true);
2923   FxSchematicScene *fxScene = dynamic_cast<FxSchematicScene *>(scene());
2924   if (!fxScene) return;
2925 
2926   TXshZeraryFxColumn *zColumn = dynamic_cast<TXshZeraryFxColumn *>(
2927       fxScene->getXsheet()->getColumn(m_columnIndex));
2928   if (zColumn) {
2929     TFx *fx = zColumn->getZeraryColumnFx()->getZeraryFx();
2930     setToolTip(
2931         QString("%1 : %2").arg(m_name, QString::fromStdWString(fx->getFxId())));
2932   }
2933 
2934   TFxCommand::renameFx(m_fx.getPointer(), m_name.toStdWString(),
2935                        fxScene->getXsheetHandle());
2936   updateOutputDockToolTips(m_name);
2937   emit sceneChanged();
2938   update();
2939 }
2940 
2941 //-----------------------------------------------------
2942 
resize(bool maximized)2943 void FxSchematicZeraryNode::resize(bool maximized) {}
2944 
2945 //*****************************************************
2946 //
2947 // FxSchematicColumnNode
2948 //
2949 //*****************************************************
2950 
FxSchematicColumnNode(FxSchematicScene * scene,TLevelColumnFx * fx)2951 FxSchematicColumnNode::FxSchematicColumnNode(FxSchematicScene *scene,
2952                                              TLevelColumnFx *fx)
2953     : FxSchematicNode(scene, fx, 90, 32, eColumnFx)
2954     , m_isOpened(false)  // iwasawa
2955 {
2956   SchematicViewer *viewer = scene->getSchematicViewer();
2957 
2958   if (!m_isNormalIconView) {
2959     setWidth(90);
2960     setHeight(50);
2961   }
2962   m_columnIndex     = fx->getColumnIndex();
2963   TStageObjectId id = TStageObjectId::ColumnId(m_columnIndex);
2964   std::string name  = scene->getXsheet()->getStageObject(id)->getName();
2965   m_name            = QString::fromStdString(name);
2966 
2967   m_resizeItem = new SchematicThumbnailToggle(
2968       this, fx->getAttributes()->isOpened());    //サムネイル矢印
2969   m_nameItem = new SchematicName(this, 54, 20);  //リネーム部分
2970   m_outDock  = new FxSchematicDock(this, "", 0, eFxOutputPort);  // Outポート
2971   m_renderToggle =
2972       new SchematicToggle(this, viewer->getSchematicPreviewButtonOnImage(),
2973                           viewer->getSchematicPreviewButtonBgOnColor(),
2974                           viewer->getSchematicPreviewButtonOffImage(),
2975                           viewer->getSchematicPreviewButtonBgOffColor(),
2976                           SchematicToggle::eIsParentColumn, m_isNormalIconView);
2977   m_cameraStandToggle = new SchematicToggle(
2978       this, viewer->getSchematicCamstandButtonOnImage(),
2979       viewer->getSchematicCamstandButtonTranspImage(),
2980       viewer->getSchematicCamstandButtonBgOnColor(),
2981       viewer->getSchematicCamstandButtonOffImage(),
2982       viewer->getSchematicCamstandButtonBgOffColor(),
2983       SchematicToggle::eIsParentColumn | SchematicToggle::eEnableNullState,
2984       m_isNormalIconView);
2985   m_columnPainter = new FxColumnPainter(this, m_width, m_height, m_name);
2986 
2987   // no link port
2988   m_linkedNode = 0;
2989   m_linkDock   = 0;
2990 
2991   //-----
2992   m_nameItem->setName(m_name);
2993 
2994   int levelType;
2995   QString levelName;
2996   FxSchematicColumnNode::getLevelTypeAndName(levelType, levelName);
2997   setToolTip(QString("%1 : %2").arg(m_name, levelName));
2998 
2999   addPort(0, m_outDock->getPort());
3000 
3001   m_nameItem->hide();
3002   TXshColumn *column = scene->getXsheet()->getColumn(m_columnIndex);
3003   if (column) {
3004     m_renderToggle->setIsActive(column->isPreviewVisible());
3005     m_cameraStandToggle->setState(
3006         column->isCamstandVisible() ? (column->getOpacity() < 255 ? 2 : 1) : 0);
3007     if (!column->isControl() && !column->isRendered() &&
3008         !column->getMeshColumn())
3009       m_columnPainter->setIsReference();
3010   }
3011 
3012   // set geometry
3013   if (m_isNormalIconView) {
3014     m_resizeItem->setPos(2, 0);
3015     m_nameItem->setPos(16, -1);
3016     m_outDock->setPos(72, 14);
3017     m_renderToggle->setPos(72, 0);
3018     m_cameraStandToggle->setPos(72, 7);
3019   } else {
3020     m_resizeItem->hide();
3021     m_nameItem->setPos(0, 0);
3022     m_outDock->setPos(80, 0);
3023     m_renderToggle->setPos(60, -5);
3024     m_cameraStandToggle->setPos(30, -5);
3025   }
3026 
3027   m_resizeItem->setZValue(2);
3028   m_nameItem->setZValue(2);
3029   m_outDock->setZValue(2);
3030   m_renderToggle->setZValue(2);
3031   m_cameraStandToggle->setZValue(2);
3032   m_columnPainter->setZValue(1);
3033 
3034   bool ret = true;
3035   ret      = ret && connect(m_resizeItem, SIGNAL(toggled(bool)), this,
3036                        SLOT(onChangedSize(bool)));
3037   ret = ret &&
3038         connect(m_nameItem, SIGNAL(focusOut()), this, SLOT(onNameChanged()));
3039   ret = ret && connect(m_renderToggle, SIGNAL(toggled(bool)), this,
3040                        SLOT(onRenderToggleClicked(bool)));
3041   ret = ret && connect(m_cameraStandToggle, SIGNAL(stateChanged(int)), this,
3042                        SLOT(onCameraStandToggleClicked(int)));
3043 
3044   assert(ret);
3045 
3046   onChangedSize(fx->getAttributes()->isOpened());
3047 }
3048 
3049 //-----------------------------------------------------
3050 
~FxSchematicColumnNode()3051 FxSchematicColumnNode::~FxSchematicColumnNode() {}
3052 
3053 //-----------------------------------------------------
3054 
boundingRect() const3055 QRectF FxSchematicColumnNode::boundingRect() const {
3056   if (m_isOpened && m_isNormalIconView)
3057     return QRectF(-5, -54, m_width + 10, m_height + 59);
3058   else
3059     return QRectF(-5, -5, m_width + 10, m_height + 10);
3060 }
3061 
3062 //-----------------------------------------------------
3063 
paint(QPainter * painter,const QStyleOptionGraphicsItem * option,QWidget * widget)3064 void FxSchematicColumnNode::paint(QPainter *painter,
3065                                   const QStyleOptionGraphicsItem *option,
3066                                   QWidget *widget) {
3067   FxSchematicNode::paint(painter, option, widget);
3068 }
3069 
3070 //-----------------------------------------------------
3071 
onRenderToggleClicked(bool toggled)3072 void FxSchematicColumnNode::onRenderToggleClicked(bool toggled) {
3073   FxSchematicScene *fxScene = dynamic_cast<FxSchematicScene *>(scene());
3074   if (!fxScene) return;
3075   TXshColumn *column = fxScene->getXsheet()->getColumn(m_columnIndex);
3076   if (column) {
3077     column->setPreviewVisible(toggled);
3078     emit sceneChanged();
3079     emit xsheetChanged();
3080   }
3081 }
3082 
3083 //-----------------------------------------------------
3084 
onCameraStandToggleClicked(int state)3085 void FxSchematicColumnNode::onCameraStandToggleClicked(int state) {
3086   FxSchematicScene *fxScene = dynamic_cast<FxSchematicScene *>(scene());
3087   if (!fxScene) return;
3088   TXshColumn *column = fxScene->getXsheet()->getColumn(m_columnIndex);
3089   if (column) {
3090     column->setCamstandVisible(!column->isCamstandVisible());
3091     // column->setCamstandVisible(toggled);
3092     emit sceneChanged();
3093     emit xsheetChanged();
3094   }
3095 }
3096 
3097 //-----------------------------------------------------
3098 
getPixmap()3099 QPixmap FxSchematicColumnNode::getPixmap() {
3100   FxSchematicScene *fxScene = dynamic_cast<FxSchematicScene *>(scene());
3101   if (!fxScene) return QPixmap();
3102   TXsheet *xsh = fxScene->getXsheet();
3103   if (xsh && !xsh->isColumnEmpty(m_columnIndex)) {
3104     int r0, r1;
3105     xsh->getCellRange(m_columnIndex, r0, r1);
3106     if (r1 >= r0) {
3107       TXshCell cell = xsh->getCell(r0, m_columnIndex);
3108       TXshLevel *xl = cell.m_level.getPointer();
3109       if (xl)
3110         return IconGenerator::instance()->getIcon(xl, cell.m_frameId, false);
3111     }
3112   }
3113   return QPixmap();
3114 }
3115 
3116 //--------------------------------------------------------
3117 
getLevelTypeAndName(int & ltype,QString & levelName)3118 void FxSchematicColumnNode::getLevelTypeAndName(int &ltype,
3119                                                 QString &levelName) {
3120   FxSchematicScene *fxScene = dynamic_cast<FxSchematicScene *>(scene());
3121   if (!fxScene) {
3122     ltype     = NO_XSHLEVEL;
3123     levelName = QString();
3124     return;
3125   }
3126 
3127   TXsheet *xsh = fxScene->getXsheet();
3128   if (xsh && !xsh->isColumnEmpty(m_columnIndex)) {
3129     int r0, r1;
3130     xsh->getCellRange(m_columnIndex, r0, r1);
3131     if (r1 >= r0) {
3132       TXshCell cell = xsh->getCell(r0, m_columnIndex);
3133       TXshLevel *xl = cell.m_level.getPointer();
3134       if (xl) {
3135         ltype = cell.m_level->getType();
3136 
3137         // for Zerary Fx, display FxId
3138         if (ltype == ZERARYFX_XSHLEVEL) {
3139           TXshZeraryFxColumn *zColumn =
3140               dynamic_cast<TXshZeraryFxColumn *>(xsh->getColumn(m_columnIndex));
3141           if (zColumn) {
3142             TFx *fx   = zColumn->getZeraryColumnFx()->getZeraryFx();
3143             levelName = QString::fromStdWString(fx->getFxId());
3144             return;
3145           }
3146         }
3147 
3148         levelName = QString::fromStdWString(xl->getName());
3149         return;
3150       }
3151     }
3152   }
3153 
3154   ltype     = NO_XSHLEVEL;
3155   levelName = QString();
3156   return;
3157 }
3158 
3159 //-----------------------------------------------------
3160 
onChangedSize(bool expand)3161 void FxSchematicColumnNode::onChangedSize(bool expand) {
3162   prepareGeometryChange();
3163   m_isOpened = expand;
3164   m_fx->getAttributes()->setIsOpened(m_isOpened);
3165   m_height = (m_isNormalIconView) ? 32 : 50;
3166   updateLinksGeometry();
3167   update();
3168   emit nodeChangedSize();
3169 }
3170 
3171 //-----------------------------------------------------
3172 
onNameChanged()3173 void FxSchematicColumnNode::onNameChanged() {
3174   m_nameItem->hide();
3175   m_name = m_nameItem->toPlainText();
3176   m_columnPainter->setName(m_name);
3177 
3178   int levelType;
3179   QString levelName;
3180   getLevelTypeAndName(levelType, levelName);
3181 
3182   setToolTip(QString("%1 : %2").arg(m_name, levelName));
3183 
3184   setFlag(QGraphicsItem::ItemIsSelectable, true);
3185 
3186   TStageObjectId id = TStageObjectId::ColumnId(m_columnIndex);
3187   renameObject(id, m_name.toStdString());
3188   updateOutputDockToolTips(m_name);
3189   emit sceneChanged();
3190   update();
3191 }
3192 
3193 //-----------------------------------------------------
3194 
resize(bool maximized)3195 void FxSchematicColumnNode::resize(bool maximized) {
3196   m_resizeItem->setIsDown(!maximized);
3197 }
3198 
3199 //-----------------------------------------------------
3200 
mouseDoubleClickEvent(QGraphicsSceneMouseEvent * me)3201 void FxSchematicColumnNode::mouseDoubleClickEvent(
3202     QGraphicsSceneMouseEvent *me) {
3203   QRectF nameArea(14, 0, m_width - 15, 14);
3204   if (nameArea.contains(me->pos()) && me->modifiers() == Qt::ControlModifier) {
3205     TStageObjectId id         = TStageObjectId::ColumnId(m_columnIndex);
3206     FxSchematicScene *fxScene = dynamic_cast<FxSchematicScene *>(scene());
3207     if (!fxScene) return;
3208     TStageObject *pegbar = fxScene->getXsheet()->getStageObject(id);
3209     if (!pegbar) return;
3210     m_name = QString::fromStdString(pegbar->getName());
3211     m_nameItem->setPlainText(m_name);
3212     m_nameItem->show();
3213     m_nameItem->setFocus();
3214     setFlag(QGraphicsItem::ItemIsSelectable, false);
3215   } else {
3216     QAction *fxEditorPopup =
3217         CommandManager::instance()->getAction(MI_FxParamEditor);
3218     fxEditorPopup->trigger();
3219     // this signal cause the update the contents of the FxSettings
3220     emit fxNodeDoubleClicked();
3221   }
3222 }
3223 
3224 //-----------------------------------------------------
3225 
mousePressEvent(QGraphicsSceneMouseEvent * me)3226 void FxSchematicColumnNode::mousePressEvent(QGraphicsSceneMouseEvent *me) {
3227   FxSchematicNode::mousePressEvent(me);
3228 
3229   QAction *fxEditorPopup =
3230       CommandManager::instance()->getAction(MI_FxParamEditor);
3231   // this signal cause the update the contents of the FxSettings
3232   if (fxEditorPopup->isVisible()) emit fxNodeDoubleClicked();
3233 }
3234 
3235 //-----------------------------------------------------
3236 
renameObject(const TStageObjectId & id,std::string name)3237 void FxSchematicColumnNode::renameObject(const TStageObjectId &id,
3238                                          std::string name) {
3239   FxSchematicScene *fxScene = dynamic_cast<FxSchematicScene *>(scene());
3240   if (!fxScene) return;
3241   TStageObjectCmd::rename(id, name, fxScene->getXsheetHandle());
3242 }
3243 
3244 //*****************************************************
3245 //
3246 // FxSchematicPaletteNode
3247 //
3248 //*****************************************************
3249 
FxSchematicPaletteNode(FxSchematicScene * scene,TPaletteColumnFx * fx)3250 FxSchematicPaletteNode::FxSchematicPaletteNode(FxSchematicScene *scene,
3251                                                TPaletteColumnFx *fx)
3252     : FxSchematicNode(scene, fx, 90, 32, eColumnFx) {
3253   SchematicViewer *viewer = scene->getSchematicViewer();
3254 
3255   if (!m_isNormalIconView) {
3256     setWidth(90);
3257     setHeight(50);
3258   }
3259   m_columnIndex     = fx->getColumnIndex();
3260   TStageObjectId id = TStageObjectId::ColumnId(m_columnIndex);
3261   std::string name  = scene->getXsheet()->getStageObject(id)->getName();
3262   m_name            = QString::fromStdString(name);
3263 
3264   m_linkedNode = 0;
3265   m_linkDock   = 0;
3266   m_nameItem   = new SchematicName(this, 54, 20);  // for rename
3267   m_outDock    = new FxSchematicDock(this, "", 0, eFxOutputPort);
3268   m_renderToggle =
3269       new SchematicToggle(this, viewer->getSchematicPreviewButtonOnImage(),
3270                           viewer->getSchematicPreviewButtonBgOnColor(),
3271                           viewer->getSchematicPreviewButtonOffImage(),
3272                           viewer->getSchematicPreviewButtonBgOffColor(),
3273                           SchematicToggle::eIsParentColumn, m_isNormalIconView);
3274   m_palettePainter = new FxPalettePainter(this, m_width, m_height, m_name);
3275 
3276   //----
3277   QString paletteName = getPaletteName();
3278   setToolTip(QString("%1 : %2").arg(m_name, paletteName));
3279 
3280   m_nameItem->setName(m_name);
3281 
3282   addPort(0, m_outDock->getPort());
3283 
3284   TXshColumn *column = scene->getXsheet()->getColumn(m_columnIndex);
3285   if (column) m_renderToggle->setIsActive(column->isPreviewVisible());
3286 
3287   // set geometry
3288   if (m_isNormalIconView) {
3289     m_nameItem->setPos(19, -1);
3290     m_outDock->setPos(72, 14);
3291     m_renderToggle->setPos(72, 0);
3292   } else {
3293     QFont fnt = m_nameItem->font();
3294     fnt.setPixelSize(fnt.pixelSize() * 2);
3295     m_nameItem->setFont(fnt);
3296 
3297     m_nameItem->setPos(-1, 0);
3298     m_outDock->setPos(80, 0);
3299     m_renderToggle->setPos(60, -5);
3300   }
3301 
3302   m_nameItem->setZValue(2);
3303   m_outDock->setZValue(2);
3304   m_renderToggle->setZValue(2);
3305   m_palettePainter->setZValue(1);
3306 
3307   connect(m_nameItem, SIGNAL(focusOut()), this, SLOT(onNameChanged()));
3308   connect(m_renderToggle, SIGNAL(toggled(bool)), this,
3309           SLOT(onRenderToggleClicked(bool)));
3310 
3311   m_nameItem->hide();
3312   prepareGeometryChange();
3313   m_fx->getAttributes()->setIsOpened(false);
3314 }
3315 
3316 //-----------------------------------------------------
3317 
getPaletteName()3318 QString FxSchematicPaletteNode::getPaletteName() {
3319   FxSchematicScene *fxScene = dynamic_cast<FxSchematicScene *>(scene());
3320   if (!fxScene) {
3321     return QString();
3322   }
3323 
3324   TXsheet *xsh = fxScene->getXsheet();
3325   if (xsh && !xsh->isColumnEmpty(m_columnIndex)) {
3326     int r0, r1;
3327     xsh->getCellRange(m_columnIndex, r0, r1);
3328     if (r1 >= r0) {
3329       TXshCell cell = xsh->getCell(r0, m_columnIndex);
3330       TXshLevel *xl = cell.m_level.getPointer();
3331       if (xl) {
3332         return QString::fromStdWString(xl->getName());
3333       }
3334     }
3335   }
3336 
3337   return QString();
3338 }
3339 
3340 //-----------------------------------------------------
3341 
~FxSchematicPaletteNode()3342 FxSchematicPaletteNode::~FxSchematicPaletteNode() {}
3343 
3344 //-----------------------------------------------------
3345 
boundingRect() const3346 QRectF FxSchematicPaletteNode::boundingRect() const {
3347   return QRectF(-5, -5, m_width + 10, m_height + 10);
3348 }
3349 
3350 //-----------------------------------------------------
3351 
paint(QPainter * painter,const QStyleOptionGraphicsItem * option,QWidget * widget)3352 void FxSchematicPaletteNode::paint(QPainter *painter,
3353                                    const QStyleOptionGraphicsItem *option,
3354                                    QWidget *widget) {
3355   FxSchematicNode::paint(painter, option, widget);
3356 }
3357 
3358 //-----------------------------------------------------
3359 
onRenderToggleClicked(bool toggled)3360 void FxSchematicPaletteNode::onRenderToggleClicked(bool toggled) {
3361   FxSchematicScene *fxScene = dynamic_cast<FxSchematicScene *>(scene());
3362   if (!fxScene) return;
3363   TXshColumn *column = fxScene->getXsheet()->getColumn(m_columnIndex);
3364   if (column) {
3365     column->setPreviewVisible(toggled);
3366     emit sceneChanged();
3367     emit xsheetChanged();
3368   }
3369 }
3370 
3371 //-----------------------------------------------------
3372 
getPixmap()3373 QPixmap FxSchematicPaletteNode::getPixmap() { return QPixmap(); }
3374 
3375 //-----------------------------------------------------
3376 
onNameChanged()3377 void FxSchematicPaletteNode::onNameChanged() {
3378   m_nameItem->hide();
3379   m_name = m_nameItem->toPlainText();
3380   m_palettePainter->setName(m_name);
3381   QString paletteName = getPaletteName();
3382   setToolTip(QString("%1 : %2").arg(m_name, paletteName));
3383   setFlag(QGraphicsItem::ItemIsSelectable, true);
3384 
3385   TStageObjectId id = TStageObjectId::ColumnId(m_columnIndex);
3386   renameObject(id, m_name.toStdString());
3387   updateOutputDockToolTips(m_name);
3388   emit sceneChanged();
3389   update();
3390 }
3391 
3392 //-----------------------------------------------------
3393 
mouseDoubleClickEvent(QGraphicsSceneMouseEvent * me)3394 void FxSchematicPaletteNode::mouseDoubleClickEvent(
3395     QGraphicsSceneMouseEvent *me) {
3396   QRectF nameArea(18, 2, 54, 14);
3397   if (nameArea.contains(me->pos()) && me->modifiers() == Qt::ControlModifier) {
3398     m_nameItem->setPlainText(m_name);
3399     m_nameItem->show();
3400     m_nameItem->setFocus();
3401     setFlag(QGraphicsItem::ItemIsSelectable, false);
3402   } else {
3403     QAction *fxEditorPopup =
3404         CommandManager::instance()->getAction(MI_FxParamEditor);
3405     fxEditorPopup->trigger();
3406   }
3407 }
3408 
3409 //-----------------------------------------------------
3410 
mousePressEvent(QGraphicsSceneMouseEvent * me)3411 void FxSchematicPaletteNode::mousePressEvent(QGraphicsSceneMouseEvent *me) {
3412   FxSchematicNode::mousePressEvent(me);
3413 
3414   QAction *fxEditorPopup =
3415       CommandManager::instance()->getAction(MI_FxParamEditor);
3416   // this signal cause the update the contents of the FxSettings
3417   if (fxEditorPopup->isVisible()) emit fxNodeDoubleClicked();
3418 }
3419 
3420 //-----------------------------------------------------
3421 
renameObject(const TStageObjectId & id,std::string name)3422 void FxSchematicPaletteNode::renameObject(const TStageObjectId &id,
3423                                           std::string name) {
3424   FxSchematicScene *fxScene = dynamic_cast<FxSchematicScene *>(scene());
3425   if (!fxScene) return;
3426   TStageObjectCmd::rename(id, name, fxScene->getXsheetHandle());
3427 }
3428 
3429 //*****************************************************
3430 //
3431 // FxGroupNode
3432 //
3433 //*****************************************************
3434 
FxGroupNode(FxSchematicScene * scene,const QList<TFxP> & groupedFx,const QList<TFxP> & roots,int groupId,const std::wstring & groupName)3435 FxGroupNode::FxGroupNode(FxSchematicScene *scene, const QList<TFxP> &groupedFx,
3436                          const QList<TFxP> &roots, int groupId,
3437                          const std::wstring &groupName)
3438     : FxSchematicNode(scene, roots[0].getPointer(), 90, 32, eGroupedFx)
3439     , m_groupId(groupId)
3440     , m_groupedFxs(groupedFx) {
3441   SchematicViewer *viewer = scene->getSchematicViewer();
3442 
3443   if (!m_isNormalIconView) {
3444     setWidth(90);
3445     setHeight(50);
3446   }
3447 
3448   m_name  = QString::fromStdWString(groupName);
3449   m_roots = roots;
3450 
3451   QString fxId = "Group " + QString::number(m_groupId);
3452   if (m_name != fxId)
3453     setToolTip(QString("%1 (%2)").arg(m_name, fxId));
3454   else
3455     setToolTip(m_name);
3456 
3457   m_nameItem = new SchematicName(this, 72, 20);  // for rename
3458   m_renderToggle =
3459       new SchematicToggle(this, viewer->getSchematicPreviewButtonOnImage(),
3460                           viewer->getSchematicPreviewButtonBgOnColor(),
3461                           viewer->getSchematicPreviewButtonOffImage(),
3462                           viewer->getSchematicPreviewButtonBgOffColor(),
3463                           SchematicToggle::eIsParentColumn, m_isNormalIconView);
3464   m_outDock               = new FxSchematicDock(this, "", 0, eFxGroupedOutPort);
3465   FxSchematicDock *inDock = new FxSchematicDock(
3466       this, "Source", (m_isNormalIconView) ? m_width - 18 : 10,
3467       eFxGroupedInPort);
3468 
3469   m_painter = new FxPainter(this, m_width, m_height, m_name, m_type,
3470                             roots[0]->getFxType());
3471 
3472   m_linkedNode = 0;
3473   m_linkDock   = 0;
3474 
3475   //-----
3476   m_nameItem->setName(m_name);
3477   m_renderToggle->setIsActive(m_fx->getAttributes()->isEnabled());
3478 
3479   addPort(0, m_outDock->getPort());
3480   addPort(1, inDock->getPort());
3481   m_inDocks.push_back(inDock);
3482 
3483   // set geometry
3484   if (m_isNormalIconView) {
3485     m_nameItem->setPos(1, -1);
3486     m_renderToggle->setPos(72, 0);
3487     m_outDock->setPos(72, 14);
3488     inDock->setPos(0, m_height);
3489   } else {
3490     QFont fnt = m_nameItem->font();
3491     fnt.setPixelSize(fnt.pixelSize() * 2);
3492     m_nameItem->setFont(fnt);
3493 
3494     m_nameItem->setPos(-1, 0);
3495     m_renderToggle->setPos(60, -5);
3496     m_outDock->setPos(80, 0);
3497     inDock->setPos(0, 0);
3498   }
3499 
3500   m_nameItem->setZValue(3);
3501   m_renderToggle->setZValue(2);
3502   m_outDock->setZValue(2);
3503   inDock->setZValue(2);
3504   m_painter->setZValue(1);
3505 
3506   connect(m_nameItem, SIGNAL(focusOut()), this, SLOT(onNameChanged()));
3507   connect(m_renderToggle, SIGNAL(toggled(bool)), this,
3508           SLOT(onRenderToggleClicked(bool)));
3509   m_nameItem->hide();
3510 
3511   setPos(computePos());
3512 }
3513 
3514 //-----------------------------------------------------
3515 
~FxGroupNode()3516 FxGroupNode::~FxGroupNode() {}
3517 
3518 //-----------------------------------------------------
3519 
boundingRect() const3520 QRectF FxGroupNode::boundingRect() const {
3521   return QRectF(-5, -5, m_width + 10, m_height + 10);
3522 }
3523 
3524 //-----------------------------------------------------
3525 
paint(QPainter * painter,const QStyleOptionGraphicsItem * option,QWidget * widget)3526 void FxGroupNode::paint(QPainter *painter,
3527                         const QStyleOptionGraphicsItem *option,
3528                         QWidget *widget) {
3529   // FxSchematicNode::paint(painter,option,widget);
3530 }
3531 
3532 //-----------------------------------------------------
3533 
updateFxsDagPosition(const TPointD & pos) const3534 void FxGroupNode::updateFxsDagPosition(const TPointD &pos) const {
3535   QPointF qOldPos = computePos();
3536   TPointD oldPos(qOldPos.x(), qOldPos.y());
3537   TPointD delta = pos - oldPos;
3538   int i;
3539   for (i = 0; i < m_groupedFxs.size(); i++) {
3540     // If the node position is unidentified, then leave the placement of it to
3541     // placeNode() function.
3542     // if (m_groupedFxs[i]->getAttributes()->getDagNodePos() != TConst::nowhere)
3543     {
3544       TPointD groupPos = m_groupedFxs[i]->getAttributes()->getDagNodePos();
3545       if (groupPos != TConst::nowhere)
3546         m_groupedFxs[i]->getAttributes()->setDagNodePos(groupPos + delta);
3547       TMacroFx *macro = dynamic_cast<TMacroFx *>(m_groupedFxs[i].getPointer());
3548       if (macro) {
3549         std::vector<TFxP> fxs = macro->getFxs();
3550         int i;
3551         for (i = 0; i < (int)fxs.size(); i++) {
3552           TPointD oldP = fxs[i]->getAttributes()->getDagNodePos();
3553           if (oldP != TConst::nowhere)
3554             fxs[i]->getAttributes()->setDagNodePos(oldP + delta);
3555         }
3556       }
3557     }
3558   }
3559 }
3560 
3561 //-----------------------------------------------------
3562 
mouseDoubleClickEvent(QGraphicsSceneMouseEvent * me)3563 void FxGroupNode::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *me) {
3564   QRectF nameArea(0, 0, m_width, 14);
3565   if (nameArea.contains(me->pos())) {
3566     m_nameItem->setPlainText(m_name);
3567     m_nameItem->show();
3568     m_nameItem->setFocus();
3569     setFlag(QGraphicsItem::ItemIsSelectable, false);
3570   }
3571 }
3572 
mousePressEvent(QGraphicsSceneMouseEvent * me)3573 void FxGroupNode::mousePressEvent(QGraphicsSceneMouseEvent *me) {
3574   FxSchematicNode::mousePressEvent(me);
3575 
3576   QAction *fxEditorPopup =
3577       CommandManager::instance()->getAction(MI_FxParamEditor);
3578   // this signal cause the update the contents of the FxSettings
3579   if (fxEditorPopup->isVisible()) emit fxNodeDoubleClicked();
3580 }
3581 
3582 //-----------------------------------------------------
3583 
computePos() const3584 QPointF FxGroupNode::computePos() const {
3585   int i, notCounted = 0, fxCount = m_groupedFxs.size();
3586   TPointD pos;
3587   for (i = 0; i < fxCount; i++) {
3588     TFx *fx       = m_groupedFxs[i].getPointer();
3589     TPointD fxPos = fx->getAttributes()->getDagNodePos();
3590     if (fxPos != TConst::nowhere)
3591       pos += fxPos;
3592     else
3593       notCounted++;
3594   }
3595   fxCount -= notCounted;
3596   if (fxCount > 0)
3597     return QPointF(pos.x / fxCount, pos.y / fxCount);
3598   else if (fxCount == 0 && pos != TPointD())
3599     return QPointF(pos.x, pos.y);
3600   return QPointF(25000, 25000);  // Qualcosa e' andato male... posiziono nel
3601                                  // cebntro della scena per non far danni
3602 }
3603 
3604 //-----------------------------------------------------
3605 
onNameChanged()3606 void FxGroupNode::onNameChanged() {
3607   m_nameItem->hide();
3608   m_name = m_nameItem->toPlainText();
3609   m_painter->setName(m_name);
3610   QString fxId = "Group " + QString::number(m_groupId);
3611   if (m_name != fxId)
3612     setToolTip(QString("%1 (%2)").arg(m_name, fxId));
3613   else
3614     setToolTip(m_name);
3615   setFlag(QGraphicsItem::ItemIsSelectable, true);
3616   FxSchematicScene *fxScene = dynamic_cast<FxSchematicScene *>(scene());
3617   if (!fxScene) return;
3618   TFxCommand::renameGroup(m_groupedFxs.toStdList(), m_name.toStdWString(),
3619                           false, fxScene->getXsheetHandle());
3620   update();
3621 }
3622 
3623 //-----------------------------------------------------
3624 
onRenderToggleClicked(bool value)3625 void FxGroupNode::onRenderToggleClicked(bool value) {
3626   int i;
3627   for (i = 0; i < m_groupedFxs.size(); i++) {
3628     TFxP fx = m_groupedFxs[i];
3629     if (TLevelColumnFx *lcFx = dynamic_cast<TLevelColumnFx *>(fx.getPointer()))
3630       lcFx->getColumn()->setPreviewVisible(value);
3631     else
3632       fx->getAttributes()->enable(value);
3633   }
3634   update();
3635   emit sceneChanged();
3636   emit xsheetChanged();
3637 }
3638 
3639 //-----------------------------------------------------
3640 
resize(bool maximized)3641 void FxGroupNode::resize(bool maximized) {}
3642 
3643 //-----------------------------------------------------
3644 
contains(TFxP fx)3645 bool FxGroupNode::contains(TFxP fx) {
3646   int i;
3647   for (i = 0; i < m_groupedFxs.size(); i++) {
3648     if (m_groupedFxs[i].getPointer() == fx.getPointer()) return true;
3649   }
3650   return false;
3651 }
3652 
3653 //-----------------------------------------------------
3654 
getOutputConnectionsCount() const3655 int FxGroupNode::getOutputConnectionsCount() const {
3656   FxSchematicScene *fxScene = dynamic_cast<FxSchematicScene *>(scene());
3657   assert(fxScene);
3658   TXsheet *xsh = fxScene->getXsheet();
3659   assert(xsh);
3660 
3661   int i, count = 0;
3662   for (i = 0; i < m_roots.size(); i++) {
3663     TFx *fx = m_roots[i].getPointer();
3664     count += fx->getOutputConnectionCount();
3665 
3666     if (xsh->getFxDag()->getTerminalFxs()->containsFx(fx)) count++;
3667   }
3668   return count;
3669 }
3670 
3671 //-----------------------------------------------------
3672 
isEnabled() const3673 bool FxGroupNode::isEnabled() const {
3674   int i;
3675   bool isEnabled = true;
3676   for (i = 0; i < m_roots.size(); i++) {
3677     TFx *fx = m_roots[i].getPointer();
3678     if (TZeraryColumnFx *zcFx = dynamic_cast<TZeraryColumnFx *>(fx))
3679       isEnabled = isEnabled && zcFx->getColumn()->isPreviewVisible();
3680     else
3681       isEnabled = isEnabled && fx->getAttributes()->isEnabled();
3682   }
3683   return isEnabled;
3684 }
3685 
3686 //-----------------------------------------------------
3687 
isCached() const3688 bool FxGroupNode::isCached() const {
3689   int i;
3690   bool isCached = true;
3691   for (i = 0; i < m_roots.size(); i++) {
3692     TFx *fx = m_roots[i].getPointer();
3693     if (TZeraryColumnFx *zcFx = dynamic_cast<TZeraryColumnFx *>(fx))
3694       isCached =
3695           isCached &&
3696           TPassiveCacheManager::instance()->cacheEnabled(zcFx->getZeraryFx());
3697     else
3698       isCached = isCached && TPassiveCacheManager::instance()->cacheEnabled(fx);
3699   }
3700   return isCached;
3701 }
3702