28 const int VuoNodePopover::defaultPopoverTextWidth = 192;
29 const int VuoNodePopover::margin = 8;
38 this->nodeClass = nodeClass;
40 this->modelNode = NULL;
41 this->compiler = compiler;
48 void VuoNodePopover::initialize()
57 this->popoverHasBeenShown =
false;
68 this->headerLabel =
new QLabel(
"",
this);
69 headerLabel->setText(generateNodePopoverTextHeader());
70 headerLabel->setTextInteractionFlags(headerLabel->textInteractionFlags() | Qt::TextSelectableByMouse);
73 this->textLabel =
new QLabel(
"",
this);
74 textLabel->setText(generateNodePopoverText(isDark));
75 textLabel->setTextInteractionFlags(textLabel->textInteractionFlags() | Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse);
76 textLabel->setOpenExternalLinks(
false);
79 QTextDocument *doc = textLabel->findChild<QTextDocument *>();
80 doc->setIndentWidth(20);
92 this->modelNodeView =
new QGraphicsView(
this);
93 modelNodeView->setBackgroundBrush(Qt::transparent);
94 modelNodeView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
95 modelNodeView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
96 modelNodeView->setScene(composition);
97 modelNodeView->setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform);
98 modelNodeView->setFrameShape(QFrame::NoFrame);
100 modelNodeView->setEnabled(
false);
104 layout =
new QVBoxLayout(
this);
105 layout->setContentsMargins(margin, margin, margin, margin);
107 layout->addWidget(headerLabel, 0, Qt::AlignTop);
108 layout->setStretch(0, 0);
110 if (displayModelNode)
112 layout->addWidget(modelNodeView, 0, Qt::AlignTop|Qt::AlignLeft);
113 layout->setStretch(1, 0);
116 layout->addWidget(textLabel, 0, Qt::AlignTop);
117 layout->setStretch(2, 1);
150 void VuoNodePopover::setStyle()
153 textLabel->setMargin(0);
154 textLabel->setFixedWidth(defaultPopoverTextWidth);
155 textLabel->setWordWrap(
true);
158 headerLabel->setMargin(0);
159 headerLabel->setFixedWidth(defaultPopoverTextWidth);
160 headerLabel->setWordWrap(
true);
161 headerLabel->setOpenExternalLinks(
true);
163 Qt::WindowFlags flags = windowFlags();
164 flags |= Qt::FramelessWindowHint;
165 flags |= Qt::WindowStaysOnTopHint;
166 flags |= Qt::ToolTip;
167 setWindowFlags(flags);
170 setBackgroundRole(QPalette::Base);
172 pal.setColor(QPalette::Base, QColor(Qt::transparent));
175 QSizePolicy sizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
176 textLabel->setSizePolicy(sizePolicy);
177 headerLabel->setSizePolicy(sizePolicy);
179 if (displayModelNode)
181 modelNodeView->setSizePolicy(sizePolicy);
187 setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
193 QString VuoNodePopover::generateNodePopoverTextHeader()
197 QString nodeSetName = (nodeSet? nodeSet->
getName().c_str() :
"");
198 QString nodeClassBreadcrumbsBar = QString(
"<h3>")
201 QString(
"<a href=\"").
209 append(nodeClassTitle))
218 QString VuoNodePopover::generateNodePopoverText(
bool isDark)
220 QString nodeClassDescription = generateNodeClassDescription(isDark ?
"#606060" :
"#b0b0b0");
224 nodeClassDescription = nodeClassDescription.normalized(QString::NormalizationForm_C);
228 QString exampleCompositionLinks =
"";
230 foreach (
string compositionFilePath, exampleCompositions)
232 string formattedCompositionName =
"";
233 string compositionAsString =
"";
235 string genericNodeClassName;
241 exampleCompositionLinks.append(
"<li>")
242 .append(
"<a href=\"");
252 QString nodeSetName = nodeSet->
getName().c_str();
255 exampleCompositionLinks
267 QUrl exampleUrl(compositionFilePath.c_str());
268 string exampleNodeSetName = exampleUrl.host().toUtf8().constData();
280 string customizedName = metadata.getCustomizedName();
281 if (! customizedName.empty())
282 formattedCompositionName = customizedName;
284 string description = metadata.getDescription();
288 exampleCompositionLinks
289 .append(compositionFilePath.c_str())
293 .append(genericNodeClassName.c_str())
295 .append(formattedCompositionName.c_str())
298 if (!compositionDescription.isEmpty())
299 exampleCompositionLinks.append(
": ").append(compositionDescription);
301 exampleCompositionLinks.append(
"</li>");
304 if (exampleCompositions.size() > 0)
306 exampleCompositionLinks =
"<BR><font size=+1><b>" + tr(
"Example composition(s)",
"", exampleCompositions.size()) +
":</b></font><ul>" + exampleCompositionLinks +
"</ul>";
308 QString proNodeIndicator;
310 if (nodeClass->isPro())
311 proNodeIndicator = (nodeClass->
hasCompiler() ? installedProNodeText : missingProNodeText);
317 ?
"<p><b>" + tr(
"This node is deprecated.") +
"</b></p>"
321 .append(nodeClassDescription)
322 .append(exampleCompositionLinks)
323 .append(proNodeIndicator)
324 .append(deprecatedNodeIndicator);
330 QString VuoNodePopover::generateNodeClassDescription(
string smallTextColor)
332 string className =
"";
333 string description =
"";
358 if (description.empty())
360 description = tr(
"This node is not installed. "
361 "You can either remove it from the composition or install it on your computer.").toUtf8().data();
364 QString editLink =
"";
365 QString enclosingFolderLink =
"";
366 QString editLabel, sourcePath;
370 if (nodeClassIsEditable)
371 editLink = QString(
"<a href=\"file://%1\">%2</a>").arg(sourcePath).arg(editLabel);
373 if (nodeClassIsEditable || nodeClassIs3rdParty)
376 if (!modulePath.isEmpty())
377 enclosingFolderLink = QString(
"<a href=\"file://%1\">%2</a>")
378 .arg(QFileInfo(modulePath).dir().absolutePath())
380 .arg(tr(
"Show in Finder"));
386 QString formattedVersion = version.empty()
389 : tr(
"Version %1").arg(QString::fromStdString(version));
392 tooltipBody.append(QString(
"<font color=\"%2\">%1</font>")
393 .arg(formattedDescription)
394 .arg(smallTextColor.c_str()));
396 tooltipBody.append(
"<p>");
398 tooltipBody.append(QString(
"<font color=\"%2\">%1</font>")
399 .arg(className.c_str())
400 .arg(smallTextColor.c_str()));
402 if (!formattedVersion.isEmpty())
403 tooltipBody.append(QString(
"<br><font color=\"%2\">%1</font>")
404 .arg(formattedVersion)
405 .arg(smallTextColor.c_str()));
407 if (!editLink.isEmpty() || !enclosingFolderLink.isEmpty())
408 tooltipBody.append(
"<br>");
410 if (!editLink.isEmpty())
411 tooltipBody.append(QString(
"<br><font color=\"%2\">%1</font>")
413 .arg(smallTextColor.c_str()));
415 if (!enclosingFolderLink.isEmpty())
416 tooltipBody.append(QString(
"<br><font color=\"%2\">%1</font>")
417 .arg(enclosingFolderLink)
418 .arg(smallTextColor.c_str()));
420 tooltipBody.append(
"</p>");
430 return textLabel->maximumWidth();
439 if (textLabel->hasSelectedText())
440 return textLabel->selectedText();
441 else if (headerLabel->hasSelectedText())
442 return headerLabel->selectedText();
453 int adjustedWidth = width-2*margin;
454 if (adjustedWidth != textLabel->width())
456 textLabel->setFixedWidth(adjustedWidth);
457 headerLabel->setFixedWidth(adjustedWidth);
462 textLabel->setWordWrap(
true);
463 headerLabel->setWordWrap(
true);
472 dispatch_async(((
VuoEditor *)qApp)->getDocumentationQueue(), ^{
473 string tmpSaveDir =
"";
480 string preexistingNodeSetResourceDir = ((
VuoEditor *)qApp)->getResourceDirectoryForNodeSet(nodeSet->
getName());
483 if (tmpSaveDir != preexistingNodeSetResourceDir)
501 QRegExp embeddedImageHtml(
"<img\\s+", Qt::CaseInsensitive);
502 return textLabel->text().contains(embeddedImageHtml);
551 .arg(isDark ?
"#a0a0a0" :
"#606060")
552 .arg(isDark ?
"#6882be" :
"#74acec")
553 .arg(isDark ?
"#909090" :
"#606060")
560 void VuoNodePopover::updateColor(
bool isDark)
562 headerLabel->setText(generateNodePopoverTextHeader());
563 textLabel->setText(generateNodePopoverText(isDark));
566 QColor bulletColor = isDark ?
"#a0a0a0" :
"#606060";
567 p.setColor(QPalette::Normal, QPalette::Text, bulletColor);
568 p.setColor(QPalette::Inactive, QPalette::Text, bulletColor);
569 textLabel->setPalette(p);
578 if (
event->buttons() & Qt::LeftButton)
582 qreal dpRatio = devicePixelRatio();
583 QPixmap pixmap(dpRatio*r.width(), dpRatio*r.height());
584 pixmap.setDevicePixelRatio(dpRatio);
585 pixmap.fill(Qt::transparent);
587 QPainter painter(&pixmap);
588 painter.setRenderHint(QPainter::Antialiasing,
true);
589 painter.setRenderHint(QPainter::HighQualityAntialiasing,
true);
590 painter.setRenderHint(QPainter::TextAntialiasing,
true);
591 painter.setRenderHint(QPainter::SmoothPixmapTransform,
true);
593 painter.translate(-r.topLeft());
594 modelNode->
paint(&painter, NULL, NULL);
598 QDrag *drag =
new QDrag(
this);
599 drag->setPixmap(pixmap);
600 drag->setHotSpot(
event->pos()-(modelNodeView->pos()
605 QMimeData *mimeData =
new QMimeData();
606 const QString dropText = QString(nodeClass->
getClassName().c_str())
607 .append(QLatin1Char(
'\n'))
608 .append(QString::number(drag->hotSpot().x()))
609 .append(QLatin1Char(
'\n'))
610 .append(QString::number(drag->hotSpot().y()));
611 mimeData->setData(
"text/plain", dropText.toUtf8().constData());
612 drag->setMimeData(mimeData);
613 drag->exec(Qt::CopyAction);
629 QList<QGraphicsItem *> newNodes;
631 newNodes.append((QGraphicsItem *)newNode);
641 QMenu *contextMenu =
new QMenu(
this);
642 contextMenu->setSeparatorsCollapsible(
false);
644 contextMenu->exec(
event->globalPos());