11 #include "ui_VuoSearchBox.h"
31 QDockWidget(parent, flags),
34 this->composition = composition;
37 setWindowTitle(tr(
"Find"));
38 setAllowedAreas(Qt::TopDockWidgetArea);
41 ui->searchText->installEventFilter(
this);
43 ui->doneButton->setDefault(
false);
44 ui->doneButton->setAutoDefault(
false);
46 connect(ui->doneButton, &QPushButton::clicked,
this, &QDockWidget::close);
49 connect(ui->searchText, &QLineEdit::textChanged,
this, &VuoSearchBox::searchForText);
51 setTitleBarWidget(
new QWidget());
53 currentResultIndex = 0;
54 noResultsText = QApplication::translate(
"VuoSearchBox",
"No results");
55 resultCount =
new QLabel(
this);
56 int resultCountTextWidth = qMax(70, QFontMetrics(resultCount->font()).size(0,noResultsText).width());
58 resultCount->setFixedSize(resultCountTextWidth, resultCount->height());
59 resultCount->setStyleSheet(
"QLabel { color : gray; }");
60 resultCount->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
62 searchIcon = QIcon(QApplication::applicationDirPath().append(
"/../Resources/search-loupe.png"));
63 searchButton =
new QToolButton(ui->searchText);
64 searchButton->setIcon(searchIcon);
65 searchButton->setCursor(Qt::ArrowCursor);
66 searchButton->setStyleSheet(
"QToolButton { border: none; padding: 2px 3px 3px 3px; }");
68 const int leftPadding = searchButton->iconSize().width()+4;
69 setStyleSheet(VUO_QSTRINGIFY(
79 .arg(resultCount->width()+10)
93 ui->searchText->setFocus();
94 ui->searchText->selectAll();
95 searchForText(ui->searchText->text());
97 repositionChildWidgets();
99 setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed);
100 setMinimumHeight(geometry().height());
101 setMaximumHeight(geometry().height());
107 void VuoSearchBox::updateSpotlightedItems()
113 if (ui->searchText->text().isEmpty())
129 foreach (QGraphicsItem *matchingItem, searchResults)
143 void VuoSearchBox::searchForText(
const QString &searchText)
145 searchResults.clear();
146 currentResultIndex = 0;
148 if (searchText.isEmpty())
150 composition->clearSelection();
151 updateSpotlightedItems();
156 searchResults = getCurrentSearchResults(searchText);
158 composition->clearSelection();
159 if (searchResults.size() >= 1)
160 searchResults[currentResultIndex]->setSelected(
true);
162 updateSpotlightedItems();
164 updateViewportToFitResults();
172 vector<QGraphicsItem *> VuoSearchBox::getCurrentSearchResults(
const QString &searchText)
174 vector<QGraphicsItem *> searchResults;
177 if (searchText.toLower().trimmed() ==
"deprecated")
178 return findDeprecatedNodes();
181 if (searchText.toLower().trimmed() ==
"subcomposition" || searchText.toLower().trimmed() ==
".vuo"
182 || searchText.toLower().trimmed() ==
"source:.vuo")
183 return findSubcompositionNodes();
186 if (searchText.toLower().trimmed() ==
".fs" || searchText.toLower().trimmed() ==
"source:.fs")
187 return findShaderNodes();
190 if (searchText.toLower().trimmed() ==
".c" || searchText.toLower().trimmed() ==
"source:.c")
191 return findCLanguageNodes();
194 if (searchText.toLower().trimmed() ==
".vuonode" || searchText.toLower().trimmed() ==
"source:.vuonode")
195 return find3rdPartyPrecompiledNodes();
202 QString nodeClassName =
"";
206 nodeClassName = QString::fromUtf8(nodeClass->
getClassName().c_str());
209 bool isCollapsedTypecast =
false;
215 if (typecastInPort && typecastInPort->
hasRenderer())
219 isCollapsedTypecast =
true;
223 bool isAttachment =
false;
227 bool nodeMatched =
false;
230 if (!isCollapsedTypecast && !isAttachment)
233 int index = QString(node->
getTitle().c_str()).toLower().indexOf(searchText.toLower());
234 if (index == 0 || ((index > 0) && (QString(node->
getTitle().c_str()).toLower().at(index-1) ==
' ')))
242 if (!nodeMatched && !isCollapsedTypecast && !isAttachment)
245 int index = nodeClassName.toLower().indexOf(searchText.toLower());
246 if (index == 0 || ((index > 0) && (nodeClassName.toLower().at(index-1) ==
'.')))
312 if (QString(constantWithoutHtml).contains(searchText, Qt::CaseInsensitive))
330 int index = QString(comment->
getContent().c_str()).toLower().indexOf(searchText.toLower());
331 if (index == 0 || ((index > 0) && !(QString(comment->
getContent().c_str()).toLower().at(index-1).isLetterOrNumber())))
335 sort(searchResults.begin(), searchResults.end(), itemLessThan);
336 searchResults.erase(std::unique(searchResults.begin(), searchResults.end()), searchResults.end());
338 return searchResults;
344 vector<QGraphicsItem *> VuoSearchBox::findDeprecatedNodes()
350 if (nodeIsDeprecated && !excludeNodeFromSearchResults(node))
354 sort(searchResults.begin(), searchResults.end(), itemLessThan);
355 searchResults.erase(std::unique(searchResults.begin(), searchResults.end()), searchResults.end());
357 return searchResults;
363 vector<QGraphicsItem *> VuoSearchBox::findSubcompositionNodes()
372 if (nodeIsSubcomposition && !excludeNodeFromSearchResults(node))
376 sort(searchResults.begin(), searchResults.end(), itemLessThan);
377 searchResults.erase(std::unique(searchResults.begin(), searchResults.end()), searchResults.end());
379 return searchResults;
385 vector<QGraphicsItem *> VuoSearchBox::findShaderNodes()
394 if (nodeIsShader && !excludeNodeFromSearchResults(node))
398 sort(searchResults.begin(), searchResults.end(), itemLessThan);
399 searchResults.erase(std::unique(searchResults.begin(), searchResults.end()), searchResults.end());
401 return searchResults;
407 vector<QGraphicsItem *> VuoSearchBox::findCLanguageNodes()
413 QString actionText, sourcePath;
417 if (nodeHasExternalSource && !excludeNodeFromSearchResults(node))
421 sort(searchResults.begin(), searchResults.end(), itemLessThan);
422 searchResults.erase(std::unique(searchResults.begin(), searchResults.end()), searchResults.end());
424 return searchResults;
430 vector<QGraphicsItem *> VuoSearchBox::find3rdPartyPrecompiledNodes()
436 QString actionText, sourcePath;
442 if (nodeIs3rdParty && !nodeIsEditable && !excludeNodeFromSearchResults(node))
446 sort(searchResults.begin(), searchResults.end(), itemLessThan);
447 searchResults.erase(std::unique(searchResults.begin(), searchResults.end()), searchResults.end());
449 return searchResults;
456 bool VuoSearchBox::excludeNodeFromSearchResults(
VuoNode *node)
459 bool isCollapsedTypecast =
false;
465 isCollapsedTypecast =
true;
470 return (isCollapsedTypecast || isAttachment);
478 bool startingOver =
false;
479 vector<QGraphicsItem *> newSearchResults = getCurrentSearchResults(ui->searchText->text());
480 if (newSearchResults != searchResults)
482 searchResults.clear();
484 searchResults = newSearchResults;
487 composition->clearSelection();
488 updateSpotlightedItems();
490 if (searchResults.size() > 0)
492 currentResultIndex = (startingOver? 0 : (currentResultIndex + 1) % searchResults.size());
493 searchResults[currentResultIndex]->setSelected(
true);
497 updateViewportToFitResults();
505 bool startingOver =
false;
506 vector<QGraphicsItem *> newSearchResults = getCurrentSearchResults(ui->searchText->text());
507 if (newSearchResults != searchResults)
509 searchResults.clear();
511 searchResults = newSearchResults;
514 composition->clearSelection();
515 updateSpotlightedItems();
517 if (searchResults.size() > 0)
519 currentResultIndex = (startingOver? 0 : currentResultIndex - 1);
520 if (currentResultIndex < 0)
521 currentResultIndex += searchResults.size();
523 searchResults[currentResultIndex]->setSelected(
true);
527 updateViewportToFitResults();
538 bool startingOver =
false;
539 vector<QGraphicsItem *> newSearchResults = getCurrentSearchResults(ui->searchText->text());
540 if (newSearchResults != searchResults)
542 searchResults.clear();
544 searchResults = newSearchResults;
547 composition->clearSelection();
548 updateSpotlightedItems();
550 if (searchResults.size() > 0)
552 currentResultIndex = (startingOver? 0 : currentResultIndex);
553 searchResults[currentResultIndex]->setSelected(
true);
557 updateViewportToFitResults();
564 void VuoSearchBox::updateViewportToFitResults()
569 if (!composition->selectedItems().isEmpty() &&
570 !composition->views()[0]->mapToScene(composition->views()[0]->rect()).boundingRect().
571 contains(QRect(itemsTightBoundingRect.topLeft().toPoint(),
572 itemsTightBoundingRect.bottomRight().toPoint())))
574 composition->views()[0]->ensureVisible(itemsTightBoundingRect);
582 void VuoSearchBox::updateResultCount()
584 if (ui->searchText->text().isEmpty())
585 resultCount->setText(
"");
586 else if (searchResults.size() == 0)
587 resultCount->setText(noResultsText);
589 resultCount->setText(QString(
"%1 of %2").arg(currentResultIndex+1).arg(searchResults.size()));
591 ui->nextButton->setEnabled(searchResults.size() >= 1);
592 ui->nextButton->setAutoRaise(!ui->nextButton->isEnabled());
593 ui->previousButton->setEnabled(searchResults.size() >= 1);
594 ui->previousButton->setAutoRaise(!ui->previousButton->isEnabled());
602 if ((event->type() == QEvent::KeyPress) && (
static_cast<QKeyEvent *
>(event)->key() == Qt::Key_Return))
604 else if ((event->type() == QEvent::KeyPress) && (
static_cast<QKeyEvent *
>(event)->key() == Qt::Key_G)
605 && (
static_cast<QKeyEvent *
>(event)->modifiers() & Qt::ControlModifier)
606 && (!(
static_cast<QKeyEvent *
>(event)->modifiers() & Qt::ShiftModifier)))
608 else if ((event->type() == QEvent::KeyPress) && (
static_cast<QKeyEvent *
>(event)->key() == Qt::Key_G)
609 && (
static_cast<QKeyEvent *
>(event)->modifiers() & Qt::ControlModifier)
610 && (
static_cast<QKeyEvent *
>(event)->modifiers() & Qt::ShiftModifier))
612 else if ((event->type() == QEvent::KeyPress) && (
static_cast<QKeyEvent *
>(event)->key() == Qt::Key_Escape))
616 object->removeEventFilter(
this);
617 QApplication::sendEvent(
object, event);
618 object->installEventFilter(
this);
629 QDockWidget::resizeEvent(event);
630 repositionChildWidgets();
641 QDockWidget::closeEvent(event);
647 void VuoSearchBox::repositionChildWidgets()
649 ui->searchText->resize(widget()->geometry().width()-ui->previousButton->geometry().width()
650 -ui->nextButton->geometry().width()
651 -ui->doneButton->geometry().width()-5,
652 ui->searchText->height());
653 resultCount->move(ui->searchText->geometry().right()-resultCount->width()-5, ui->searchText->pos().y()-5);
654 ui->previousButton->move(ui->searchText->geometry().right()+5, ui->previousButton->y());
655 ui->nextButton->move(ui->previousButton->geometry().right()+2, ui->nextButton->y());
656 ui->doneButton->move(ui->nextButton->geometry().right(), ui->doneButton->y());
663 void VuoSearchBox::updateColor(
bool isDark)
665 QString barBackgroundColor = isDark ?
"#919191" :
"#efefef";
666 QString pressedToolButtonBackgroundColor = isDark ?
"#aaaaaa" :
"#d4d4d4";
667 QString disabledToolButtonArrowColor = isDark ?
"#707070" :
"#c0c0c0";
671 QWidget#searchBoxContents {
672 background-color: %1;
674 QToolButton#previousButton,
675 QToolButton#nextButton {
677 background-color: %1;
680 QToolButton#previousButton:pressed,
681 QToolButton#nextButton:pressed {
682 background-color: %2;
684 QToolButton#previousButton:disabled,
685 QToolButton#nextButton:disabled {
689 .arg(barBackgroundColor)
690 .arg(pressedToolButtonBackgroundColor)
691 .arg(disabledToolButtonArrowColor);
695 QString focusRingColor =
"#1d6ae5";
696 styleSheet += VUO_QSTRINGIFY(
698 border: 1px solid #919191;
703 border: 2px solid %1;
711 margin: 4px 7px 7px 5px;
713 QPushButton:pressed {
717 border: 2px solid %1;
720 .arg(focusRingColor);
723 ui->searchBoxContents->setStyleSheet(styleSheet);
725 ui->searchText->setAttribute(Qt::WA_MacShowFocusRect, !isDark);
733 bool VuoSearchBox::itemLessThan(QGraphicsItem *item1, QGraphicsItem *item2)
738 if (item1RowNum < item2RowNum)
740 else if (item2RowNum < item1RowNum)
742 return (item1->scenePos().x() < item2->scenePos().x());
750 return (ui->nextButton->isEnabled() && ui->previousButton->isEnabled());
753 VuoSearchBox::~VuoSearchBox()