11 #include "ui_VuoPublishedPortSidebar.h"
36 this->composition = composition;
37 this->isInput = isInput;
38 this->portTypeMenusPopulated =
false;
40 setWindowTitle(isInput ? tr(
"Inputs") : tr(
"Outputs"));
43 setFocusPolicy(Qt::ClickFocus);
46 widget()->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored);
47 widget()->setMinimumWidth(100);
48 widget()->setMaximumWidth(100);
50 ui->newPublishedPortButton->setIcon(QIcon(
":/Icons/new.svg"));
52 menuAddPort =
new QMenu(
this);
53 menuAddPort->setSeparatorsCollapsible(
false);
54 menuAddPort->setTitle(tr(
"New Port"));
55 ui->newPublishedPortButton->setMenu(menuAddPort);
56 connect(menuAddPort, &QMenu::aboutToShow,
this, &VuoPublishedPortSidebar::populatePortTypeMenus);
60 ui->publishedPortList->setAttribute(Qt::WA_MacShowFocusRect,
false);
63 contextMenuPortOptions =
new QMenu(
this);
64 contextMenuPortOptions->setSeparatorsCollapsible(
false);
66 menuChangeProtocol =
new QMenu(contextMenuPortOptions);
67 menuChangeProtocol->setSeparatorsCollapsible(
false);
68 menuChangeProtocol->setTitle(tr(
"Change Protocol"));
69 if (enableProtocolChanges)
70 contextMenuPortOptions->addMenu(menuChangeProtocol);
72 contextMenuRemoveProtocol =
new QMenu(
this);
73 contextMenuRemoveProtocol->setSeparatorsCollapsible(
false);
74 contextMenuActionRemoveProtocol =
new QAction(tr(
"Remove Protocol"), NULL);
76 if (enableProtocolChanges)
77 contextMenuRemoveProtocol->addAction(contextMenuActionRemoveProtocol);
88 connect(
this, &VuoPublishedPortSidebar::visibilityChanged, ui->publishedPortList, &VuoPublishedPortList::setVisible);
91 ui->publishedPortList->setInput(isInput);
92 ui->publishedPortList->setComposition(composition);
95 setMouseTracking(
true);
99 connect(editor, SIGNAL(darkInterfaceToggled(
bool)), ui->publishedPortList, SLOT(repaint()));
102 VuoPublishedPortSidebar_Pro();
112 set<QString> previouslySelectedPorts;
113 QList<QListWidgetItem *> previouslySelectedPortListItems = ui->publishedPortList->selectedItems();
114 for (QList<QListWidgetItem *>::iterator portListItem = previouslySelectedPortListItems.begin(); portListItem != previouslySelectedPortListItems.end(); ++portListItem)
115 previouslySelectedPorts.insert(((*portListItem)->data(Qt::DisplayRole).value<QString>()));
117 ui->publishedPortList->clear();
120 ui->publishedPortList->getInput());
123 bool portWasSelected = previouslySelectedPorts.find(publishedPort->
getClass()->
getName().c_str()) != previouslySelectedPorts.end();
124 appendPublishedPortToList(publishedPort, portWasSelected);
128 ui->publishedPortList->setFixedHeight(ui->publishedPortList->sizeHint().height());
129 ui->publishedPortList->update();
130 ui->publishedPortList->updatePublishedPortLocs();
139 void VuoPublishedPortSidebar::appendPublishedPortToList(
VuoPublishedPort *port,
bool select)
144 QListWidgetItem *item =
new QListWidgetItem(ui->publishedPortList);
146 item->setData(Qt::DisplayRole, publishedPortName.c_str());
149 QString formattedPublishedPortName = QString(
"<b><font size=+2>%1</font></b>").arg(publishedPortName.c_str());
152 QString formattedPublishedPortDataType =
"<font size=+1 color=\"gray\">" + tr(
"Data type") +
": <b>" + QString::fromStdString(publishedPortType) +
"</b></font>";
163 if (publishedPortName ==
"time")
165 if (filter || generator || transition)
166 description = tr(
"A number that changes over time, used to control animations or other changing effects.");
168 description +=
" " + tr(
"<code>time</code> is independent of <code>progress</code>.");
170 else if (publishedPortName ==
"image")
172 if (filter || generator || transition)
173 description = tr(
"The image to be filtered.");
175 else if (publishedPortName ==
"width")
178 description = tr(
"The requested width of the image, in pixels.");
180 else if (publishedPortName ==
"height")
183 description = tr(
"The requested height of the image, in pixels.");
185 else if (publishedPortName ==
"startImage")
188 description = tr(
"The image to transition from.");
190 else if (publishedPortName ==
"endImage")
193 description = tr(
"The image to transition to.");
195 else if (publishedPortName ==
"progress")
198 description = tr(
"A number from 0 to 1 for how far the transition has progressed. At 0, the transition is at the beginning, with only <code>startImage</code> showing. At 0.5, the transition is halfway through. At 1, the transition is complete, with only <code>endImage</code> showing. When previewing the composition in Vuo, the mouse position left to right controls <code>progress</code>.");
202 else if (publishedPortName ==
"outputImage")
205 description = tr(
"The altered image.");
207 description = tr(
"The created image. Its width and height should match the <code>width</code> and <code>height</code> published input ports.");
209 description = tr(
"The resulting image.");
213 else if (publishedPortName ==
"offlineRender")
216 description = tr(
"For movie export: <code>true</code> if the composition is being exported to a movie and <code>false</code> otherwise.");
218 else if (publishedPortName ==
"motionBlur")
221 description = tr(
"For movie export: The number of frames rendered per output frame. 1 means motion blur is disabled; 2, 4, 8, 16, 32, or 64 means motion blur is enabled.");
223 else if (publishedPortName ==
"duration")
226 description = tr(
"For FxPlug: The length, in seconds, of the clip to be filtered.");
228 description = tr(
"For movie export and FxPlug: The length, in seconds, of the movie/clip.");
230 description = tr(
"For FxPlug: The length, in seconds, of the transition.");
232 else if (publishedPortName ==
"framerate")
234 if (filter || transition)
235 description = tr(
"For FxPlug: The framerate of the project, in frames per second.");
237 description = tr(
"For movie export and FxPlug: The framerate of the movie/project, in frames per second.");
239 else if (publishedPortName ==
"frameNumber")
242 description = tr(
"For FxPlug: The number of frames since the beginning of the clip, starting at 0.");
244 description = tr(
"For movie export and FxPlug: The number of frames since the beginning of the movie/clip, starting at 0.");
246 description = tr(
"For FxPlug: The number of frames since the beginning of the transition, starting at 0.");
248 else if (publishedPortName ==
"quality")
250 if (filter || generator || transition)
251 description = tr(
"For FxPlug: The rendering quality or level of detail.");
253 else if (publishedPortName ==
"screen")
256 description = tr(
"For screen savers: Which display the screen saver is running on. (macOS runs a separate instance of the composition on each display.)");
258 else if (publishedPortName ==
"preview")
261 description = tr(
"For screen savers: <code>true</code> when the screen saver is running in the System Preferences preview thumbnail.");
264 if (!description.isEmpty())
265 description =
"<p><font size=+1>" + description +
"</font></p>";
268 item->setToolTip(formattedPublishedPortName.append(
"<BR>")
269 .append(formattedPublishedPortDataType)
270 .append(description));
274 item->setFlags(item->flags() &~ Qt::ItemIsEnabled);
276 ui->publishedPortList->addItem(item);
277 item->setSelected(select);
290 int numPorts = ui->publishedPortList->count();
291 for (
int portIndex = 0; portIndex < numPorts; ++portIndex)
293 QListWidgetItem *portItem = ui->publishedPortList->item(portIndex);
296 QGraphicsItem::CacheMode normalCacheMode = publishedPortToHighlight->cacheMode();
297 publishedPortToHighlight->setCacheMode(QGraphicsItem::NoCache);
303 publishedPortToHighlight->setCacheMode(normalCacheMode);
306 bool publishedPortWellShouldAcceptDrops = (internalFixedPort && canListPublishedPortAliasFor(internalFixedPort) && internalFixedPort->
getPublishable());
307 ui->publishedPortDropBox->setCurrentlyAcceptingDrops(publishedPortWellShouldAcceptDrops);
308 ui->publishedPortDropBox->update();
312 ui->publishedPortList->setFillVerticalSpace(!publishedPortWellShouldAcceptDrops);
313 ui->publishedPortList->viewport()->update();
322 int numPorts = ui->publishedPortList->count();
323 for (
int portIndex = 0; portIndex < numPorts; ++portIndex)
325 QListWidgetItem *portItem = ui->publishedPortList->item(portIndex);
328 QGraphicsItem::CacheMode normalCacheMode = publishedPort->cacheMode();
329 publishedPort->setCacheMode(QGraphicsItem::NoCache);
332 publishedPort->setCacheMode(normalCacheMode);
335 ui->publishedPortDropBox->setCurrentlyAcceptingDrops(
false);
336 ui->publishedPortDropBox->update();
340 ui->publishedPortList->setFillVerticalSpace(
true);
341 ui->publishedPortList->viewport()->update();
353 ui->activeProtocolLabel->setStyleSheet(VUO_QSTRINGIFY(
355 background-color: %1;
356 color: rgba(255,255,255,224);
359 .arg(getActiveProtocolHeadingColor(0, !isInput).name())
363 ui->activeProtocolLabel->setHidden(
false);
368 ui->activeProtocolLabel->setText(
"");
369 ui->activeProtocolLabel->setHidden(
true);
378 return menuChangeProtocol;
386 return contextMenuActionRemoveProtocol;
403 int numPorts = ui->publishedPortList->count();
404 for (
int portIndex = 0; portIndex < numPorts; ++portIndex)
406 QListWidgetItem *portItem = ui->publishedPortList->item(portIndex);
409 if (publishedPort == publishedPortUnderCursor)
418 ui->publishedPortDropBox->setHovered(isPublishedPortDropBoxUnderCursorForEvent(event));
421 ui->publishedPortList->viewport()->update();
433 int numPorts = ui->publishedPortList->count();
434 for (
int portIndex = 0; portIndex < numPorts; ++portIndex)
436 QListWidgetItem *portItem = ui->publishedPortList->item(portIndex);
441 ui->publishedPortDropBox->setHovered(
false);
444 ui->publishedPortList->viewport()->update();
469 string typecastToInsert =
"";
473 string specializedTypeName =
"";
477 bool isCursorOverPublishedPortDropBox = isPublishedPortDropBoxUnderCursorForEvent(event);
480 if (isCursorOverPublishedPortDropBox && canListPublishedPortAliasFor(fixedPort))
485 forceEventOnlyPublication,
495 bool isPublishedInput = !publishedPort->
getInput();
501 || (isPublishedInput? composition->
selectBridgingSolution(publishedPort, fixedPort,
false, &portToSpecialize, specializedTypeName, typecastToInsert) :
502 composition->
selectBridgingSolution(fixedPort, publishedPort,
true, &portToSpecialize, specializedTypeName, typecastToInsert)))
505 VuoCable *dataCableToDisplace = NULL;
506 if (!forceEventOnlyPublication && !ui->publishedPortList->getInput())
509 for (vector<VuoCable *>::iterator cable = previousConnectedCables.begin(); (! dataCableToDisplace) && (cable != previousConnectedCables.end()); ++cable)
510 if ((*cable)->getRenderer()->effectivelyCarriesData())
511 dataCableToDisplace = *cable;
517 bool cableToReplaceHasMatchingDataCarryingStatus = (cableToReplace?
519 cableInProgressExpectedToCarryData) :
521 if (cableToReplace && cableToReplaceHasMatchingDataCarryingStatus)
533 if (recreatingSameConnection)
542 if (dataCableToDisplace)
544 QList<QGraphicsItem *> removedComponents;
545 removedComponents.append(dataCableToDisplace->
getRenderer());
551 if (cableToReplace && !cableToReplaceHasMatchingDataCarryingStatus)
553 QList<QGraphicsItem *> removedComponents;
554 removedComponents.append(cableToReplace->
getRenderer());
560 forceEventOnlyPublication,
561 (portToSpecialize? portToSpecialize->
getBase() : NULL),
579 if (isActiveProtocolLabelUnderCursorForEvent(event))
581 contextMenuActionRemoveProtocol->setData(qVariantFromValue((
void *)composition->
getActiveProtocol()));
582 contextMenuRemoveProtocol->exec(event->globalPos());
586 contextMenuPortOptions->addMenu(menuAddPort);
587 contextMenuPortOptions->exec(event->globalPos());
588 contextMenuPortOptions->removeAction(menuAddPort->menuAction());
606 ui->publishedPortList->clearSelection();
619 ui->publishedPortList->updatePublishedPortLocs();
627 if (event->source() == ui->publishedPortList)
638 QDropEvent modifiedEvent(QPoint(10,10),
641 event->mouseButtons(),
642 event->keyboardModifiers());
643 ui->publishedPortList->adoptDropEvent(&modifiedEvent);
653 QDockWidget::closeEvent(event);
660 bool VuoPublishedPortSidebar::canListPublishedPortAliasFor(
VuoRendererPort *port)
662 return ((ui->publishedPortList->getInput() && port->
getInput()) || ((! ui->publishedPortList->getInput()) && port->
getOutput()));
669 bool VuoPublishedPortSidebar::isPublishedPortDropBoxUnderCursorForEvent(QMouseEvent *event)
671 QPoint cursorPosition = ((QMouseEvent *)(event))->globalPos();
673 QRect publishedPortDropBoxRect = ui->publishedPortDropBox->geometry();
674 publishedPortDropBoxRect.moveTopLeft(ui->publishedPortDropBox->parentWidget()->mapToGlobal(publishedPortDropBoxRect.topLeft()));
676 bool dropBoxUnderCursor = (!ui->publishedPortDropBox->isHidden() && publishedPortDropBoxRect.contains(cursorPosition));
677 return dropBoxUnderCursor;
684 bool VuoPublishedPortSidebar::isActiveProtocolLabelUnderCursorForEvent(QContextMenuEvent *event)
686 QPoint cursorPosition = ((QContextMenuEvent *)(event))->globalPos();
688 QRect activeProtocolLabelRect = ui->activeProtocolLabel->geometry();
689 activeProtocolLabelRect.moveTopLeft(ui->activeProtocolLabel->parentWidget()->mapToGlobal(activeProtocolLabelRect.topLeft()));
691 bool activeProtocolLabelUnderCursor = (!ui->activeProtocolLabel->isHidden() && activeProtocolLabelRect.contains(cursorPosition));
692 return activeProtocolLabelUnderCursor;
701 QPoint cursorPosition = ((QMouseEvent *)(event))->globalPos();
702 return ui->publishedPortList->getPublishedPortAtGlobalPos(cursorPosition, tolerance, limitPortCollisionRange);
710 return ui->publishedPortList->getGlobalPosOfPublishedPort(port);
718 return ui->publishedPortList->getMenuSelectionInProgress();
725 QColor VuoPublishedPortSidebar::getActiveProtocolHeadingColor(
int protocolIndex,
bool isInput)
728 VuoRendererColors::noSelection,
731 return activeProtocolColor.nodeFrame();
741 VuoRendererColors::noSelection,
744 return activeProtocolColor.
nodeFill();
759 int yCenter = portLeftCenterGlobal.y();
760 int xRight = parentWidget()->mapToGlobal( QPoint(x() + width(), 0) ).x();
761 QPoint publishedPortRightCenterGlobal = QPoint(xRight, yCenter);
764 const int focusGlowWidth = 2;
765 publishedPortRightCenterGlobal = publishedPortRightCenterGlobal - QPoint(focusGlowWidth, 0);
766 nameEditor->
setWidth(width() - 2*focusGlowWidth);
769 json_object_object_add(details,
"isDark", json_object_new_boolean(
static_cast<VuoEditor *
>(qApp)->isInterfaceDark()));
771 json_object *originalValueAsJson = json_object_new_string(originalValue.c_str());
772 json_object *newValueAsJson = nameEditor->
show(publishedPortRightCenterGlobal, originalValueAsJson, details);
773 string newValue = json_object_get_string(newValueAsJson);
774 json_object_put(originalValueAsJson);
775 json_object_put(newValueAsJson);
788 if (publishedPort && type &&
797 bool isPublishedInput = !port->
getInput();
802 if (!originalDetails || json_object_get_type(originalDetails) != json_type_object)
803 originalDetails = json_object_new_object();
805 json_object_object_add(originalDetails,
"isDark", json_object_new_boolean(editor->
isInterfaceDark()));
811 newDetails = numericDetailsEditor->
show(portLeftCenterGlobal, originalDetails);
812 numericDetailsEditor->deleteLater();
819 newDetails = pointDetailsEditor->
show(portLeftCenterGlobal, originalDetails);
820 pointDetailsEditor->deleteLater();
824 string originalSuggestedMin, newSuggestedMin, originalSuggestedMax, newSuggestedMax, originalSuggestedStep, newSuggestedStep =
"";
828 if (json_object_object_get_ex(originalDetails,
"suggestedMin", &originalSuggestedMinValue))
829 originalSuggestedMin = json_object_to_json_string(originalSuggestedMinValue);
832 if (json_object_object_get_ex(newDetails,
"suggestedMin", &newSuggestedMinValue))
833 newSuggestedMin = json_object_to_json_string(newSuggestedMinValue);
835 json_object_object_add(newDetails,
"suggestedMin", NULL);
839 if (json_object_object_get_ex(originalDetails,
"suggestedMax", &originalSuggestedMaxValue))
840 originalSuggestedMax = json_object_to_json_string(originalSuggestedMaxValue);
843 if (json_object_object_get_ex(newDetails,
"suggestedMax", &newSuggestedMaxValue))
844 newSuggestedMax = json_object_to_json_string(newSuggestedMaxValue);
846 json_object_object_add(newDetails,
"suggestedMax", NULL);
850 if (json_object_object_get_ex(originalDetails,
"suggestedStep", &originalSuggestedStepValue))
851 originalSuggestedStep = json_object_to_json_string(originalSuggestedStepValue);
854 if (json_object_object_get_ex(newDetails,
"suggestedStep", &newSuggestedStepValue))
855 newSuggestedStep = json_object_to_json_string(newSuggestedStepValue);
857 json_object_object_add(newDetails,
"suggestedStep", NULL);
859 if ((originalSuggestedMin != newSuggestedMin) ||
860 (originalSuggestedMax != newSuggestedMax) ||
861 (originalSuggestedStep != newSuggestedStep))
873 void VuoPublishedPortSidebar::newPublishedPortTypeSelected()
875 QAction *sender = (QAction *)QObject::sender();
876 QList<QVariant> actionData = sender->data().toList();
877 QString typeName = actionData[1].toString();
886 void VuoPublishedPortSidebar::populatePortTypeMenus()
888 if (this->portTypeMenusPopulated)
891 menuAddPort->clear();
894 QAction *addEventOnlyPortAction = menuAddPort->addAction(tr(
"Event-Only"));
895 string typeName =
"";
896 QList<QVariant> portAndSpecializedType;
897 portAndSpecializedType.append(qVariantFromValue((
void *)NULL));
898 portAndSpecializedType.append(typeName.c_str());
899 addEventOnlyPortAction->setData(QVariant(portAndSpecializedType));
902 QMenu *menuNonListType =
new QMenu(menuAddPort);
903 menuNonListType->setSeparatorsCollapsible(
false);
904 menuNonListType->setTitle(tr(
"Single Value"));
905 menuNonListType->setToolTipsVisible(
true);
906 menuAddPort->addMenu(menuNonListType);
909 QMenu *menuListType =
new QMenu(menuAddPort);
910 menuListType->setSeparatorsCollapsible(
false);
911 menuListType->setTitle(tr(
"List"));
912 menuListType->setToolTipsVisible(
true);
913 menuAddPort->addMenu(menuListType);
920 if (allowedPortTypes.empty())
921 types.insert(singleValueTypes.begin(), singleValueTypes.end());
924 vector<string> sortedAllowedPortTypes(allowedPortTypes.begin(), allowedPortTypes.end());
925 std::sort(sortedAllowedPortTypes.begin(), sortedAllowedPortTypes.end());
926 std::sort(singleValueTypes.begin(), singleValueTypes.end());
928 std::set_intersection(singleValueTypes.begin(), singleValueTypes.end(),
929 sortedAllowedPortTypes.begin(), sortedAllowedPortTypes.end(),
930 std::inserter(types, types.begin()));
940 QList<QAction *> allNodeSetActionsToAdd;
941 for (map<
string, set<VuoCompilerType *> >::iterator i = loadedTypesForNodeSet.begin(); i != loadedTypesForNodeSet.end(); ++i)
943 string nodeSetName = i->first;
944 if (!nodeSetName.empty())
945 allNodeSetActionsToAdd += composition->
getCompatibleTypesForMenu(NULL, types, types,
true, nodeSetName, menuNonListType);
948 if ((menuNonListType->actions().size() > 0) && (allNodeSetActionsToAdd.size() > 0))
949 menuNonListType->addSeparator();
959 if (allowedPortTypes.empty())
960 types.insert(listTypes.begin(), listTypes.end());
963 vector<string> sortedAllowedPortTypes(allowedPortTypes.begin(), allowedPortTypes.end());
964 std::sort(sortedAllowedPortTypes.begin(), sortedAllowedPortTypes.end());
965 std::sort(listTypes.begin(), listTypes.end());
967 std::set_intersection(listTypes.begin(), listTypes.end(),
968 sortedAllowedPortTypes.begin(), sortedAllowedPortTypes.end(),
969 std::inserter(types, types.begin()));
979 QList<QAction *> allNodeSetActionsToAdd;
980 for (map<
string, set<VuoCompilerType *> >::iterator i = loadedTypesForNodeSet.begin(); i != loadedTypesForNodeSet.end(); ++i)
982 string nodeSetName = i->first;
983 if (!nodeSetName.empty())
987 if ((menuListType->actions().size() > 0) && (allNodeSetActionsToAdd.size() > 0))
988 menuListType->addSeparator();
994 connect(addEventOnlyPortAction, &QAction::triggered,
this, &VuoPublishedPortSidebar::newPublishedPortTypeSelected);
995 addEventOnlyPortAction->setCheckable(
false);
997 foreach (QAction *setTypeAction, menuAddPort->actions())
999 QMenu *setTypeSubmenu = setTypeAction->menu();
1002 foreach (QAction *setTypeSubaction, setTypeSubmenu->actions())
1004 QMenu *setTypeSubmenu = setTypeSubaction->menu();
1007 foreach (QAction *setTypeSubSubaction, setTypeSubmenu->actions())
1009 connect(setTypeSubSubaction, &QAction::triggered,
this, &VuoPublishedPortSidebar::newPublishedPortTypeSelected);
1010 setTypeSubSubaction->setCheckable(
false);
1015 connect(setTypeSubaction, &QAction::triggered,
this, &VuoPublishedPortSidebar::newPublishedPortTypeSelected);
1016 setTypeSubaction->setCheckable(
false);
1022 this->portTypeMenusPopulated =
true;
1032 this->allowedPortTypes = allowedPortTypes;
1038 void VuoPublishedPortSidebar::updateColor(
bool isDark)
1040 QString titleTextColor = isDark ?
"#303030" :
"#808080";
1041 QString titleBackgroundColor = isDark ?
"#919191" :
"#efefef";
1042 QString dockwidgetBackgroundColor = isDark ?
"#404040" :
"#efefef";
1043 QString buttonTextColor = isDark ?
"#a0a0a0" :
"#707070";
1045 setStyleSheet(VUO_QSTRINGIFY(
1047 titlebar-close-icon: url(:/Icons/dockwidget-close-%3.png);
1052 QDockWidget::title {
1055 background-color: %2;
1058 .arg(titleTextColor)
1059 .arg(titleBackgroundColor)
1060 .arg(isDark ?
"dark" :
"light")
1063 ui->VuoPublishedPortSidebarContents->setStyleSheet(VUO_QSTRINGIFY(
1064 QWidget#VuoPublishedPortSidebarContents {
1065 background-color: %1;
1068 .arg(dockwidgetBackgroundColor)
1071 ui->publishedPortList->setStyleSheet(
1072 ui->publishedPortList->styleSheet().append(
1075 background-color: %1;
1078 .arg(dockwidgetBackgroundColor)
1082 ui->newPublishedPortButton->setStyleSheet(VUO_QSTRINGIFY(
1089 QToolButton::menu-indicator {
1092 ).arg(buttonTextColor));