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) ==
'.')))
328 int index = QString(comment->
getContent().c_str()).toLower().indexOf(searchText.toLower());
329 if (index == 0 || ((index > 0) && !(QString(comment->
getContent().c_str()).toLower().at(index-1).isLetterOrNumber())))
333 sort(searchResults.begin(), searchResults.end(), itemLessThan);
334 searchResults.erase(std::unique(searchResults.begin(), searchResults.end()), searchResults.end());
336 return searchResults;
342 vector<QGraphicsItem *> VuoSearchBox::findDeprecatedNodes()
348 if (nodeIsDeprecated && !excludeNodeFromSearchResults(node))
352 sort(searchResults.begin(), searchResults.end(), itemLessThan);
353 searchResults.erase(std::unique(searchResults.begin(), searchResults.end()), searchResults.end());
355 return searchResults;
361 vector<QGraphicsItem *> VuoSearchBox::findSubcompositionNodes()
370 if (nodeIsSubcomposition && !excludeNodeFromSearchResults(node))
374 sort(searchResults.begin(), searchResults.end(), itemLessThan);
375 searchResults.erase(std::unique(searchResults.begin(), searchResults.end()), searchResults.end());
377 return searchResults;
383 vector<QGraphicsItem *> VuoSearchBox::findShaderNodes()
392 if (nodeIsShader && !excludeNodeFromSearchResults(node))
396 sort(searchResults.begin(), searchResults.end(), itemLessThan);
397 searchResults.erase(std::unique(searchResults.begin(), searchResults.end()), searchResults.end());
399 return searchResults;
405 vector<QGraphicsItem *> VuoSearchBox::findCLanguageNodes()
411 QString actionText, sourcePath;
415 if (nodeHasExternalSource && !excludeNodeFromSearchResults(node))
419 sort(searchResults.begin(), searchResults.end(), itemLessThan);
420 searchResults.erase(std::unique(searchResults.begin(), searchResults.end()), searchResults.end());
422 return searchResults;
428 vector<QGraphicsItem *> VuoSearchBox::find3rdPartyPrecompiledNodes()
434 QString actionText, sourcePath;
440 if (nodeIs3rdParty && !nodeIsEditable && !excludeNodeFromSearchResults(node))
444 sort(searchResults.begin(), searchResults.end(), itemLessThan);
445 searchResults.erase(std::unique(searchResults.begin(), searchResults.end()), searchResults.end());
447 return searchResults;
454 bool VuoSearchBox::excludeNodeFromSearchResults(
VuoNode *node)
457 bool isCollapsedTypecast =
false;
463 isCollapsedTypecast =
true;
468 return (isCollapsedTypecast || isAttachment);
476 bool startingOver =
false;
477 vector<QGraphicsItem *> newSearchResults = getCurrentSearchResults(ui->searchText->text());
478 if (newSearchResults != searchResults)
480 searchResults.clear();
482 searchResults = newSearchResults;
485 composition->clearSelection();
486 updateSpotlightedItems();
488 if (searchResults.size() > 0)
490 currentResultIndex = (startingOver? 0 : (currentResultIndex + 1) % searchResults.size());
491 searchResults[currentResultIndex]->setSelected(
true);
495 updateViewportToFitResults();
503 bool startingOver =
false;
504 vector<QGraphicsItem *> newSearchResults = getCurrentSearchResults(ui->searchText->text());
505 if (newSearchResults != searchResults)
507 searchResults.clear();
509 searchResults = newSearchResults;
512 composition->clearSelection();
513 updateSpotlightedItems();
515 if (searchResults.size() > 0)
517 currentResultIndex = (startingOver? 0 : currentResultIndex - 1);
518 if (currentResultIndex < 0)
519 currentResultIndex += searchResults.size();
521 searchResults[currentResultIndex]->setSelected(
true);
525 updateViewportToFitResults();
536 bool startingOver =
false;
537 vector<QGraphicsItem *> newSearchResults = getCurrentSearchResults(ui->searchText->text());
538 if (newSearchResults != searchResults)
540 searchResults.clear();
542 searchResults = newSearchResults;
545 composition->clearSelection();
546 updateSpotlightedItems();
548 if (searchResults.size() > 0)
550 currentResultIndex = (startingOver? 0 : currentResultIndex);
551 searchResults[currentResultIndex]->setSelected(
true);
555 updateViewportToFitResults();
562 void VuoSearchBox::updateViewportToFitResults()
567 if (!composition->selectedItems().isEmpty() &&
568 !composition->views()[0]->mapToScene(composition->views()[0]->rect()).boundingRect().
569 contains(QRect(itemsTightBoundingRect.topLeft().toPoint(),
570 itemsTightBoundingRect.bottomRight().toPoint())))
572 composition->views()[0]->ensureVisible(itemsTightBoundingRect);
580 void VuoSearchBox::updateResultCount()
582 if (ui->searchText->text().isEmpty())
583 resultCount->setText(
"");
584 else if (searchResults.size() == 0)
585 resultCount->setText(noResultsText);
587 resultCount->setText(QString(
"%1 of %2").arg(currentResultIndex+1).arg(searchResults.size()));
589 ui->nextButton->setEnabled(searchResults.size() >= 1);
590 ui->nextButton->setAutoRaise(!ui->nextButton->isEnabled());
591 ui->previousButton->setEnabled(searchResults.size() >= 1);
592 ui->previousButton->setAutoRaise(!ui->previousButton->isEnabled());
600 if ((event->type() == QEvent::KeyPress) && (
static_cast<QKeyEvent *
>(event)->key() == Qt::Key_Return))
602 else if ((event->type() == QEvent::KeyPress) && (
static_cast<QKeyEvent *
>(event)->key() == Qt::Key_G)
603 && (
static_cast<QKeyEvent *
>(event)->modifiers() & Qt::ControlModifier)
604 && (!(
static_cast<QKeyEvent *
>(event)->modifiers() & Qt::ShiftModifier)))
606 else if ((event->type() == QEvent::KeyPress) && (
static_cast<QKeyEvent *
>(event)->key() == Qt::Key_G)
607 && (
static_cast<QKeyEvent *
>(event)->modifiers() & Qt::ControlModifier)
608 && (
static_cast<QKeyEvent *
>(event)->modifiers() & Qt::ShiftModifier))
610 else if ((event->type() == QEvent::KeyPress) && (
static_cast<QKeyEvent *
>(event)->key() == Qt::Key_Escape))
614 object->removeEventFilter(
this);
615 QApplication::sendEvent(
object, event);
616 object->installEventFilter(
this);
627 QDockWidget::resizeEvent(event);
628 repositionChildWidgets();
639 QDockWidget::closeEvent(event);
645 void VuoSearchBox::repositionChildWidgets()
647 ui->searchText->resize(widget()->geometry().width()-ui->previousButton->geometry().width()
648 -ui->nextButton->geometry().width()
649 -ui->doneButton->geometry().width()-5,
650 ui->searchText->height());
651 resultCount->move(ui->searchText->geometry().right()-resultCount->width()-5, ui->searchText->pos().y()-5);
652 ui->previousButton->move(ui->searchText->geometry().right()+5, ui->previousButton->y());
653 ui->nextButton->move(ui->previousButton->geometry().right()+2, ui->nextButton->y());
654 ui->doneButton->move(ui->nextButton->geometry().right(), ui->doneButton->y());
661 void VuoSearchBox::updateColor(
bool isDark)
663 QString barBackgroundColor = isDark ?
"#919191" :
"#efefef";
664 QString pressedToolButtonBackgroundColor = isDark ?
"#aaaaaa" :
"#d4d4d4";
665 QString disabledToolButtonArrowColor = isDark ?
"#707070" :
"#c0c0c0";
669 QWidget#searchBoxContents {
670 background-color: %1;
672 QToolButton#previousButton,
673 QToolButton#nextButton {
675 background-color: %1;
678 QToolButton#previousButton:pressed,
679 QToolButton#nextButton:pressed {
680 background-color: %2;
682 QToolButton#previousButton:disabled,
683 QToolButton#nextButton:disabled {
687 .arg(barBackgroundColor)
688 .arg(pressedToolButtonBackgroundColor)
689 .arg(disabledToolButtonArrowColor);
693 QString focusRingColor =
"#1d6ae5";
694 styleSheet += VUO_QSTRINGIFY(
696 border: 1px solid #919191;
701 border: 2px solid %1;
709 margin: 4px 7px 7px 5px;
711 QPushButton:pressed {
715 border: 2px solid %1;
718 .arg(focusRingColor);
721 ui->searchBoxContents->setStyleSheet(styleSheet);
723 ui->searchText->setAttribute(Qt::WA_MacShowFocusRect, !isDark);
731 bool VuoSearchBox::itemLessThan(QGraphicsItem *item1, QGraphicsItem *item2)
736 if (item1RowNum < item2RowNum)
738 else if (item2RowNum < item1RowNum)
740 return (item1->scenePos().x() < item2->scenePos().x());
748 return (ui->nextButton->isEnabled() && ui->previousButton->isEnabled());
751 VuoSearchBox::~VuoSearchBox()