28const int VuoNodePopover::defaultPopoverTextWidth = 192;
29const int VuoNodePopover::margin = 8;
38 this->nodeClass = nodeClass;
40 this->modelNode = NULL;
41 this->compiler = compiler;
48void VuoNodePopover::initialize()
57 this->popoverHasBeenShown =
false;
68 this->headerLabel =
new QLabel(
"",
this);
69 headerLabel->setText(generateNodePopoverTextHeader());
70 headerLabel->setTextInteractionFlags(headerLabel->textInteractionFlags() | Qt::TextSelectableByMouse);
74 this->textLabel =
new QLabel(
"",
this);
75 textLabel->setText(generateNodePopoverText(isDark));
76 textLabel->setTextInteractionFlags(textLabel->textInteractionFlags() | Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse);
77 textLabel->setOpenExternalLinks(
false);
81 QTextDocument *doc = textLabel->findChild<QTextDocument *>();
82 doc->setIndentWidth(20);
94 this->modelNodeView =
new QGraphicsView(
this);
95 modelNodeView->setBackgroundBrush(Qt::transparent);
96 modelNodeView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
97 modelNodeView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
98 modelNodeView->setScene(composition);
99 modelNodeView->setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform);
100 modelNodeView->setFrameShape(QFrame::NoFrame);
101 modelNodeView->ensureVisible(modelNode->
boundingRect());
102 modelNodeView->setEnabled(
false);
103 modelNodeView->setToolTip(tr(
"Drag this onto the canvas to add it to your composition."));
107 layout =
new QVBoxLayout(
this);
108 layout->setContentsMargins(margin, margin, margin, margin);
110 layout->addWidget(headerLabel, 0, Qt::AlignTop);
111 layout->setStretch(0, 0);
113 if (displayModelNode)
115 layout->addWidget(modelNodeView, 0, Qt::AlignTop|Qt::AlignLeft);
116 layout->setStretch(1, 0);
119 layout->addWidget(textLabel, 0, Qt::AlignTop);
120 layout->setStretch(2, 1);
155void VuoNodePopover::setStyle()
158 textLabel->setMargin(0);
159 textLabel->setFixedWidth(defaultPopoverTextWidth);
160 textLabel->setWordWrap(
true);
163 headerLabel->setMargin(0);
164 headerLabel->setFixedWidth(defaultPopoverTextWidth);
165 headerLabel->setWordWrap(
true);
166 headerLabel->setOpenExternalLinks(
true);
168 Qt::WindowFlags flags = windowFlags();
169 flags |= Qt::FramelessWindowHint;
170 flags |= Qt::WindowStaysOnTopHint;
171 flags |= Qt::ToolTip;
172 setWindowFlags(flags);
175 setBackgroundRole(QPalette::Base);
177 pal.setColor(QPalette::Base, QColor(Qt::transparent));
180 QSizePolicy sizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
181 textLabel->setSizePolicy(sizePolicy);
182 headerLabel->setSizePolicy(sizePolicy);
184 if (displayModelNode)
186 modelNodeView->setSizePolicy(sizePolicy);
192 setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
198QString VuoNodePopover::generateNodePopoverTextHeader()
202 QString nodeSetName = (nodeSet? nodeSet->
getName().c_str() :
"");
203 QString nodeClassBreadcrumbsBar = QString(
"<h3>")
206 QString(
"<a href=\"").
207 append(
VuoEditor::vuoNodeSetDocumentationScheme).
214 append(nodeClassTitle))
223QString VuoNodePopover::generateNodePopoverText(
bool isDark)
225 QString nodeClassDescription = generateNodeClassDescription(isDark ?
"#606060" :
"#b0b0b0");
229 nodeClassDescription = nodeClassDescription.normalized(QString::NormalizationForm_C);
233 QString exampleCompositionLinks =
"";
235 foreach (
string compositionFilePath, exampleCompositions)
237 string formattedCompositionName =
"";
238 string compositionAsString =
"";
240 string genericNodeClassName;
246 exampleCompositionLinks.append(
"<li>")
247 .append(
"<a href=\"");
257 QString nodeSetName = nodeSet->
getName().c_str();
260 exampleCompositionLinks
272 QUrl exampleUrl(compositionFilePath.c_str());
273 string exampleNodeSetName = exampleUrl.host().toUtf8().constData();
285 string customizedName = metadata.getCustomizedName();
286 if (! customizedName.empty())
287 formattedCompositionName = customizedName;
289 string description = metadata.getDescription();
293 exampleCompositionLinks
294 .append(compositionFilePath.c_str())
298 .append(genericNodeClassName.c_str())
300 .append(formattedCompositionName.c_str())
303 if (!compositionDescription.isEmpty())
304 exampleCompositionLinks.append(
": ").append(compositionDescription);
306 exampleCompositionLinks.append(
"</li>");
309 if (exampleCompositions.size() > 0)
311 exampleCompositionLinks =
"<BR><font size=+1><b>" + tr(
"Example composition(s)",
"", exampleCompositions.size()) +
":</b></font><ul>" + exampleCompositionLinks +
"</ul>";
313 QString proNodeIndicator;
315 if (nodeClass->isPro())
316 proNodeIndicator = (nodeClass->
hasCompiler() ? installedProNodeText : missingProNodeText);
322 ?
"<p><b>" + tr(
"This node is deprecated.") +
"</b></p>"
326 .append(nodeClassDescription)
327 .append(exampleCompositionLinks)
328 .append(proNodeIndicator)
329 .append(deprecatedNodeIndicator);
335QString VuoNodePopover::generateNodeClassDescription(
string smallTextColor)
337 string className =
"";
338 string description =
"";
363 if (description.empty())
365 description = tr(
"This node is not installed. "
366 "You can either remove it from the composition or install it on your computer.").toUtf8().data();
369 QString editLink =
"";
370 QString enclosingFolderLink =
"";
371 QString editLabel, sourcePath;
375 if (nodeClassIsEditable)
376 editLink = QString(
"<a href=\"file://%1\">%2</a>").arg(sourcePath).arg(editLabel);
378 if (nodeClassIsEditable || nodeClassIs3rdParty)
381 if (!modulePath.isEmpty())
382 enclosingFolderLink = QString(
"<a href=\"file://%1\">%2</a>")
383 .arg(QFileInfo(modulePath).dir().absolutePath())
385 .arg(tr(
"Show in Finder"));
391 QString formattedVersion = version.empty()
394 : tr(
"Version %1").arg(QString::fromStdString(version));
397 tooltipBody.append(QString(
"<font color=\"%2\">%1</font>")
398 .arg(formattedDescription)
399 .arg(smallTextColor.c_str()));
401 tooltipBody.append(
"<p>");
403 tooltipBody.append(QString(
"<font color=\"%2\">%1</font>")
404 .arg(className.c_str())
405 .arg(smallTextColor.c_str()));
407 if (!formattedVersion.isEmpty())
408 tooltipBody.append(QString(
"<br><font color=\"%2\">%1</font>")
409 .arg(formattedVersion)
410 .arg(smallTextColor.c_str()));
412 if (!editLink.isEmpty() || !enclosingFolderLink.isEmpty())
413 tooltipBody.append(
"<br>");
415 if (!editLink.isEmpty())
416 tooltipBody.append(QString(
"<br><font color=\"%2\">%1</font>")
418 .arg(smallTextColor.c_str()));
420 if (!enclosingFolderLink.isEmpty())
421 tooltipBody.append(QString(
"<br><font color=\"%2\">%1</font>")
422 .arg(enclosingFolderLink)
423 .arg(smallTextColor.c_str()));
425 tooltipBody.append(
"</p>");
435 return textLabel->maximumWidth();
444 if (textLabel->hasSelectedText())
445 return textLabel->selectedText();
446 else if (headerLabel->hasSelectedText())
447 return headerLabel->selectedText();
458 int adjustedWidth = width-2*margin;
459 if (adjustedWidth != textLabel->width())
461 textLabel->setFixedWidth(adjustedWidth);
462 headerLabel->setFixedWidth(adjustedWidth);
467 textLabel->setWordWrap(
true);
468 headerLabel->setWordWrap(
true);
477 dispatch_async(((
VuoEditor *)qApp)->getDocumentationQueue(), ^{
478 string tmpSaveDir =
"";
485 string preexistingNodeSetResourceDir = ((
VuoEditor *)qApp)->getResourceDirectoryForNodeSet(nodeSet->
getName());
488 if (tmpSaveDir != preexistingNodeSetResourceDir)
506 QRegExp embeddedImageHtml(
"<img\\s+", Qt::CaseInsensitive);
507 return textLabel->text().contains(embeddedImageHtml);
556 .arg(isDark ?
"#a0a0a0" :
"#606060")
557 .arg(isDark ?
"#6882be" :
"#74acec")
558 .arg(isDark ?
"#909090" :
"#606060")
565void VuoNodePopover::updateColor(
bool isDark)
567 headerLabel->setText(generateNodePopoverTextHeader());
568 textLabel->setText(generateNodePopoverText(isDark));
571 QColor bulletColor = isDark ?
"#a0a0a0" :
"#606060";
572 p.setColor(QPalette::Normal, QPalette::Text, bulletColor);
573 p.setColor(QPalette::Inactive, QPalette::Text, bulletColor);
574 textLabel->setPalette(p);
583 if (
event->buttons() & Qt::LeftButton)
587 qreal dpRatio = devicePixelRatio();
588 QPixmap pixmap(dpRatio*r.width(), dpRatio*r.height());
589 pixmap.setDevicePixelRatio(dpRatio);
590 pixmap.fill(Qt::transparent);
592 QPainter painter(&pixmap);
593 painter.setRenderHint(QPainter::Antialiasing,
true);
594 painter.setRenderHint(QPainter::HighQualityAntialiasing,
true);
595 painter.setRenderHint(QPainter::TextAntialiasing,
true);
596 painter.setRenderHint(QPainter::SmoothPixmapTransform,
true);
598 painter.translate(-r.topLeft());
599 modelNode->
paint(&painter, NULL, NULL);
603 QDrag *drag =
new QDrag(
this);
604 drag->setPixmap(pixmap);
605 drag->setHotSpot(
event->pos()-(modelNodeView->pos()
610 QMimeData *mimeData =
new QMimeData();
611 const QString dropText = QString(nodeClass->
getClassName().c_str())
612 .append(QLatin1Char(
'\n'))
613 .append(QString::number(drag->hotSpot().x()))
614 .append(QLatin1Char(
'\n'))
615 .append(QString::number(drag->hotSpot().y()));
616 mimeData->setData(
"text/plain", dropText.toUtf8().constData());
617 drag->setMimeData(mimeData);
618 drag->exec(Qt::CopyAction);
634 QList<QGraphicsItem *> newNodes;
636 newNodes.append((QGraphicsItem *)newNode);
646 QMenu *contextMenu =
new QMenu(
this);
647 contextMenu->setSeparatorsCollapsible(
false);
649 contextMenu->exec(
event->globalPos());