Vuo 2.4.4
Loading...
Searching...
No Matches
VuoSearchBox.cc
Go to the documentation of this file.
1
10#include "VuoSearchBox.hh"
11#include "ui_VuoSearchBox.h"
12
14#include "VuoComment.hh"
15#include "VuoComposition.hh"
16#include "VuoRendererComment.hh"
17#include "VuoEditor.hh"
19#include "VuoEditorUtilities.hh"
21#include "VuoNodeClass.hh"
22
23extern "C" {
24#include "VuoTextHtml.h"
25}
26
30VuoSearchBox::VuoSearchBox(VuoEditorComposition *composition, QWidget *parent, Qt::WindowFlags flags) :
31 QDockWidget(parent, flags),
32 ui(new Ui::VuoSearchBox)
33{
34 this->composition = composition;
35
36 ui->setupUi(this);
37 setWindowTitle(tr("Find"));
38 setAllowedAreas(Qt::TopDockWidgetArea);
39 setFloating(false);
40
41 ui->searchText->installEventFilter(this);
42
43 ui->doneButton->setDefault(false);
44 ui->doneButton->setAutoDefault(false);
45
46 connect(ui->doneButton, &QPushButton::clicked, this, &QDockWidget::close);
47 connect(ui->previousButton, &QPushButton::clicked, this, &VuoSearchBox::goToPreviousResult);
48 connect(ui->nextButton, &QPushButton::clicked, this, &VuoSearchBox::goToNextResult);
49 connect(ui->searchText, &QLineEdit::textChanged, this, &VuoSearchBox::searchForText);
50
51 setTitleBarWidget(new QWidget()); // Disable the titlebar.
52
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());
57
58 resultCount->setFixedSize(resultCountTextWidth, resultCount->height());
59 resultCount->setStyleSheet("QLabel { color : gray; }");
60 resultCount->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
61
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; }");
67
68 const int leftPadding = searchButton->iconSize().width()+4;
69 setStyleSheet(VUO_QSTRINGIFY(
70 QLineEdit {
71 padding-left: %2px; // Space for search button
72 padding-right: %1px; // Space for result count
73 }
74 QLineEdit:focus {
75 padding-left: %2px; // Space for search button
76 padding-right: %1px; // Space for result count
77 }
78 )
79 .arg(resultCount->width()+10)
80 .arg(leftPadding)
81 );
82
83 VuoEditor *editor = (VuoEditor *)qApp;
84 connect(editor, &VuoEditor::darkInterfaceToggled, this, &VuoSearchBox::updateColor);
85 updateColor(editor->isInterfaceDark());
86}
87
92{
93 ui->searchText->setFocus();
94 ui->searchText->selectAll();
95 searchForText(ui->searchText->text());
96 QDockWidget::show();
97 repositionChildWidgets();
98
99 setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed);
100 setMinimumHeight(geometry().height());
101 setMaximumHeight(geometry().height());
102}
103
107void VuoSearchBox::updateSpotlightedItems()
108{
109 // Don't interfere with node execution spotlighting while in "Show Events" mode.
110 if (composition->getShowEventsMode())
111 return;
112
113 if (ui->searchText->text().isEmpty())
114 {
115 if (composition->getRenderNodeActivity())
116 composition->stopDisplayingActivity();
117 }
118 else
119 {
120 if (!composition->getRenderNodeActivity())
121 composition->beginDisplayingActivity(false);
122
123 foreach (VuoNode *node, composition->getBase()->getNodes())
124 {
125 if (node->getRenderer()->getTimeLastExecutionEnded() == VuoRendererItem::activityInProgress)
127 }
128
129 foreach (QGraphicsItem *matchingItem, searchResults)
130 {
131 VuoRendererNode *matchingNode = dynamic_cast<VuoRendererNode *>(matchingItem);
132 if (matchingNode)
133 matchingNode->setExecutionBegun();
134 }
135
136 // @todo https://b33p.net/kosada/node/9986 : Implement fade for comments?
137 }
138}
139
143void VuoSearchBox::searchForText(const QString &searchText)
144{
145 searchResults.clear();
146 currentResultIndex = 0;
147
148 if (searchText.isEmpty())
149 {
150 composition->clearSelection();
151 updateSpotlightedItems();
152 updateResultCount();
153 return;
154 }
155
156 searchResults = getCurrentSearchResults(searchText);
157
158 composition->clearSelection();
159 if (searchResults.size() >= 1)
160 searchResults[currentResultIndex]->setSelected(true);
161
162 updateSpotlightedItems();
163 updateResultCount();
164 updateViewportToFitResults();
165 emit searchPerformed();
166}
167
172vector<QGraphicsItem *> VuoSearchBox::getCurrentSearchResults(const QString &searchText)
173{
174 vector<QGraphicsItem *> searchResults;
175
176 // Special handling for the "deprecated" search keyword: return all deprecated nodes in the composition.
177 if (searchText.toLower().trimmed() == "deprecated")
178 return findDeprecatedNodes();
179
180 // Special handling for the "subcomposition" and ".vuo" search keywords: return all subcompositions.
181 if (searchText.toLower().trimmed() == "subcomposition" || searchText.toLower().trimmed() == ".vuo"
182 || searchText.toLower().trimmed() == "source:.vuo")
183 return findSubcompositionNodes();
184
185 // Special handling for the ".fs" search keyword: return all shaders.
186 if (searchText.toLower().trimmed() == ".fs" || searchText.toLower().trimmed() == "source:.fs")
187 return findShaderNodes();
188
189 // Special handling for the ".c" search keyword: return all C-language nodes.
190 if (searchText.toLower().trimmed() == ".c" || searchText.toLower().trimmed() == "source:.c")
191 return findCLanguageNodes();
192
193 // Special handling for the ".vuonode" search keyword: return all pre-compiled 3rd-party nodes.
194 if (searchText.toLower().trimmed() == ".vuonode" || searchText.toLower().trimmed() == "source:.vuonode")
195 return find3rdPartyPrecompiledNodes();
196
197 // Search nodes.
198 foreach (VuoNode *node, composition->getBase()->getNodes())
199 {
200 // Retrieve the node class name, as rendered on the canvas.
201 VuoNodeClass *nodeClass = node->getNodeClass();
202 QString nodeClassName = "";
203 if (nodeClass->hasCompiler() && dynamic_cast<VuoCompilerSpecializedNodeClass *>(nodeClass->getCompiler()))
204 nodeClassName = QString::fromUtf8(dynamic_cast<VuoCompilerSpecializedNodeClass *>(nodeClass->getCompiler())->getOriginalGenericNodeClassName().c_str());
205 else
206 nodeClassName = QString::fromUtf8(nodeClass->getClassName().c_str());
207
208 // Check whether we're dealing with a collapsed typecast.
209 bool isCollapsedTypecast = false;
210 vector<VuoPort *> inputPorts = node->getInputPorts();
211 VuoPort *typecastInPort = (inputPorts.size() >= VuoNodeClass::unreservedInputPortStartIndex+1?
213 NULL);
214
215 if (typecastInPort && typecastInPort->hasRenderer())
216 {
217 VuoRendererPort *typecastParent = typecastInPort->getRenderer()->getTypecastParentPort();
218 if (typecastParent)
219 isCollapsedTypecast = true;
220 }
221
222 // Check whether we're dealing with another type of attachment.
223 bool isAttachment = false;
224 if (dynamic_cast<VuoRendererInputAttachment *>(node->getRenderer()))
225 isAttachment = true;
226
227 bool nodeMatched = false;
228
229 // Match against node title.
230 if (!isCollapsedTypecast && !isAttachment)
231 {
232 // Only match starting at the beginning of words within the title.
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) == ' ')))
235 {
236 searchResults.push_back(node->getRenderer());
237 nodeMatched = true;
238 }
239 }
240
241 // Match against node class name.
242 if (!nodeMatched && !isCollapsedTypecast && !isAttachment)
243 {
244 // Only match starting at the beginning of '.'-delimited segments within the class name.
245 int index = nodeClassName.toLower().indexOf(searchText.toLower());
246 if (index == 0 || ((index > 0) && (nodeClassName.toLower().at(index-1) == '.')))
247 {
248 searchResults.push_back(node->getRenderer());
249 nodeMatched = true;
250 }
251 }
252
253 // Match against port display name.
254 if (!nodeMatched)
255 {
256 foreach (VuoPort *port, node->getInputPorts())
257 {
258 if (nodeMatched)
259 break;
260
261 if (node->getRefreshPort() == port)
262 continue;
263
264 if (port && port->hasRenderer())
265 {
266 // Only match starting at the beginning of words within the display name.
267 int index = QString(port->getRenderer()->getPortNameToRenderWhenDisplayed().c_str()).toLower().indexOf(searchText.toLower());
268 if (index == 0 || ((index > 0) && (QString(port->getRenderer()->getPortNameToRenderWhenDisplayed().c_str()).toLower().at(index-1) == ' ')))
269 {
270 if (isCollapsedTypecast && typecastInPort->getRenderer()->getTypecastParentPort()->getRenderedParentNode())
271 searchResults.push_back(typecastInPort->getRenderer()->getTypecastParentPort()->getRenderedParentNode());
272 else
273 searchResults.push_back(node->getRenderer());
274 nodeMatched = true;
275 }
276 }
277 }
278
279 foreach (VuoPort *port, node->getOutputPorts())
280 {
281 if (nodeMatched)
282 break;
283
284 if (port && port->hasRenderer())
285 {
286 // Only match starting at the beginning of words within the display name.
287 int index = QString(port->getRenderer()->getPortNameToRenderWhenDisplayed().c_str()).toLower().indexOf(searchText.toLower());
288 if (index == 0 || ((index > 0) && (QString(port->getRenderer()->getPortNameToRenderWhenDisplayed().c_str()).toLower().at(index-1) == ' ')))
289 {
290 if (isCollapsedTypecast && typecastInPort->getRenderer()->getTypecastParentPort()->getRenderedParentNode())
291 searchResults.push_back(typecastInPort->getRenderer()->getTypecastParentPort()->getRenderedParentNode());
292 else
293 searchResults.push_back(node->getRenderer());
294 nodeMatched = true;
295 }
296 }
297 }
298 }
299
300 // Match against port constants.
301 if (!nodeMatched)
302 {
303 foreach (VuoPort *port, node->getInputPorts())
304 {
305 if (nodeMatched)
306 break;
307
308 if (port && port->hasRenderer() && port->getRenderer()->isConstant())
309 {
310 VuoText constantWithoutHtml = VuoText_removeHtml(port->getRenderer()->getConstantAsStringToRender().c_str());
311 VuoRetain(constantWithoutHtml);
312 if (QString(constantWithoutHtml).contains(searchText, Qt::CaseInsensitive))
313 {
314 if (isCollapsedTypecast && typecastInPort->getRenderer()->getTypecastParentPort()->getRenderedParentNode())
315 searchResults.push_back(typecastInPort->getRenderer()->getTypecastParentPort()->getRenderedParentNode());
316 else
317 searchResults.push_back(node->getRenderer());
318 nodeMatched = true;
319 }
320 VuoRelease(constantWithoutHtml);
321 }
322 }
323 }
324 }
325
326 // Now search comments.
327 foreach (VuoComment *comment, composition->getBase()->getComments())
328 {
329 // Only match starting at the beginning of words within the comment text.
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())))
332 searchResults.push_back(comment->getRenderer());
333 }
334
335 sort(searchResults.begin(), searchResults.end(), itemLessThan);
336 searchResults.erase(std::unique(searchResults.begin(), searchResults.end()), searchResults.end());
337
338 return searchResults;
339}
340
344vector<QGraphicsItem *> VuoSearchBox::findDeprecatedNodes()
345{
346 // Search nodes.
347 foreach (VuoNode *node, composition->getBase()->getNodes())
348 {
349 bool nodeIsDeprecated = node->getNodeClass()->getDeprecated();
350 if (nodeIsDeprecated && !excludeNodeFromSearchResults(node))
351 searchResults.push_back(node->getRenderer());
352 }
353
354 sort(searchResults.begin(), searchResults.end(), itemLessThan);
355 searchResults.erase(std::unique(searchResults.begin(), searchResults.end()), searchResults.end());
356
357 return searchResults;
358}
359
363vector<QGraphicsItem *> VuoSearchBox::findSubcompositionNodes()
364{
365 // Search nodes.
366 foreach (VuoNode *node, composition->getBase()->getNodes())
367 {
368
369 bool nodeIsSubcomposition = node->getNodeClass()->hasCompiler()?
371 false;
372 if (nodeIsSubcomposition && !excludeNodeFromSearchResults(node))
373 searchResults.push_back(node->getRenderer());
374 }
375
376 sort(searchResults.begin(), searchResults.end(), itemLessThan);
377 searchResults.erase(std::unique(searchResults.begin(), searchResults.end()), searchResults.end());
378
379 return searchResults;
380}
381
385vector<QGraphicsItem *> VuoSearchBox::findShaderNodes()
386{
387 // Search nodes.
388 foreach (VuoNode *node, composition->getBase()->getNodes())
389 {
390
391 bool nodeIsShader = node->getNodeClass()->hasCompiler()?
392 node->getNodeClass()->getCompiler()->isIsf() :
393 false;
394 if (nodeIsShader && !excludeNodeFromSearchResults(node))
395 searchResults.push_back(node->getRenderer());
396 }
397
398 sort(searchResults.begin(), searchResults.end(), itemLessThan);
399 searchResults.erase(std::unique(searchResults.begin(), searchResults.end()), searchResults.end());
400
401 return searchResults;
402}
403
407vector<QGraphicsItem *> VuoSearchBox::findCLanguageNodes()
408{
409 // Search nodes.
410 foreach (VuoNode *node, composition->getBase()->getNodes())
411 {
412 VuoNodeClass *nodeClass = node->getNodeClass();
413 QString actionText, sourcePath;
414 bool nodeIsEditable = VuoEditorUtilities::isNodeClassEditable(nodeClass, actionText, sourcePath);
415 bool nodeHasExternalSource = nodeIsEditable && !nodeClass->getCompiler()->isSubcomposition() && !nodeClass->getCompiler()->isIsf();
416
417 if (nodeHasExternalSource && !excludeNodeFromSearchResults(node))
418 searchResults.push_back(node->getRenderer());
419 }
420
421 sort(searchResults.begin(), searchResults.end(), itemLessThan);
422 searchResults.erase(std::unique(searchResults.begin(), searchResults.end()), searchResults.end());
423
424 return searchResults;
425}
426
430vector<QGraphicsItem *> VuoSearchBox::find3rdPartyPrecompiledNodes()
431{
432 // Search nodes.
433 foreach (VuoNode *node, composition->getBase()->getNodes())
434 {
435 VuoNodeClass *nodeClass = node->getNodeClass();
436 QString actionText, sourcePath;
437 bool nodeIs3rdParty = node->getNodeClass()->hasCompiler()?
438 !nodeClass->getCompiler()->isBuiltIn():
439 false;
440 bool nodeIsEditable = VuoEditorUtilities::isNodeClassEditable(nodeClass, actionText, sourcePath);
441
442 if (nodeIs3rdParty && !nodeIsEditable && !excludeNodeFromSearchResults(node))
443 searchResults.push_back(node->getRenderer());
444 }
445
446 sort(searchResults.begin(), searchResults.end(), itemLessThan);
447 searchResults.erase(std::unique(searchResults.begin(), searchResults.end()), searchResults.end());
448
449 return searchResults;
450}
451
456bool VuoSearchBox::excludeNodeFromSearchResults(VuoNode *node)
457{
458 // Check whether we're dealing with a collapsed typecast.
459 bool isCollapsedTypecast = false;
460 vector<VuoPort *> inputPorts = node->getInputPorts();
461 VuoPort *typecastInPort = (inputPorts.size() >= VuoNodeClass::unreservedInputPortStartIndex+1?
463 NULL);
464 if (typecastInPort && typecastInPort->hasRenderer() && typecastInPort->getRenderer()->getTypecastParentPort())
465 isCollapsedTypecast = true;
466
467 // Check whether we're dealing with another type of attachment.
468 bool isAttachment = (dynamic_cast<VuoRendererInputAttachment *>(node->getRenderer()));
469
470 return (isCollapsedTypecast || isAttachment);
471}
472
477{
478 bool startingOver = false;
479 vector<QGraphicsItem *> newSearchResults = getCurrentSearchResults(ui->searchText->text());
480 if (newSearchResults != searchResults)
481 {
482 searchResults.clear();
483 startingOver = true;
484 searchResults = newSearchResults;
485 }
486
487 composition->clearSelection();
488 updateSpotlightedItems();
489
490 if (searchResults.size() > 0)
491 {
492 currentResultIndex = (startingOver? 0 : (currentResultIndex + 1) % searchResults.size());
493 searchResults[currentResultIndex]->setSelected(true);
494 }
495
496 updateResultCount();
497 updateViewportToFitResults();
498}
499
504{
505 bool startingOver = false;
506 vector<QGraphicsItem *> newSearchResults = getCurrentSearchResults(ui->searchText->text());
507 if (newSearchResults != searchResults)
508 {
509 searchResults.clear();
510 startingOver = true;
511 searchResults = newSearchResults;
512 }
513
514 composition->clearSelection();
515 updateSpotlightedItems();
516
517 if (searchResults.size() > 0)
518 {
519 currentResultIndex = (startingOver? 0 : currentResultIndex - 1);
520 if (currentResultIndex < 0)
521 currentResultIndex += searchResults.size();
522
523 searchResults[currentResultIndex]->setSelected(true);
524 }
525
526 updateResultCount();
527 updateViewportToFitResults();
528}
529
534{
535 if (isHidden())
536 return;
537
538 bool startingOver = false;
539 vector<QGraphicsItem *> newSearchResults = getCurrentSearchResults(ui->searchText->text());
540 if (newSearchResults != searchResults)
541 {
542 searchResults.clear();
543 startingOver = true;
544 searchResults = newSearchResults;
545 }
546
547 composition->clearSelection();
548 updateSpotlightedItems();
549
550 if (searchResults.size() > 0)
551 {
552 currentResultIndex = (startingOver? 0 : currentResultIndex);
553 searchResults[currentResultIndex]->setSelected(true);
554 }
555
556 updateResultCount();
557 updateViewportToFitResults();
558}
559
560
564void VuoSearchBox::updateViewportToFitResults()
565{
566 QRectF itemsTightBoundingRect = (!composition->selectedItems().isEmpty()? composition->internalSelectedItemsChildrenBoundingRect() :
567 composition->internalItemsBoundingRect());
568
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())))
573 {
574 composition->views()[0]->ensureVisible(itemsTightBoundingRect);
575 }
576}
577
582void VuoSearchBox::updateResultCount()
583{
584 if (ui->searchText->text().isEmpty())
585 resultCount->setText("");
586 else if (searchResults.size() == 0)
587 resultCount->setText(noResultsText);
588 else
589 resultCount->setText(QString("%1 of %2").arg(currentResultIndex+1).arg(searchResults.size()));
590
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());
595}
596
600bool VuoSearchBox::eventFilter(QObject *object, QEvent *event)
601{
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))
613 close();
614 else
615 {
616 object->removeEventFilter(this);
617 QApplication::sendEvent(object, event);
618 object->installEventFilter(this);
619 }
620
621 return true;
622}
623
627void VuoSearchBox::resizeEvent(QResizeEvent *event)
628{
629 QDockWidget::resizeEvent(event);
630 repositionChildWidgets();
631}
632
636void VuoSearchBox::closeEvent(QCloseEvent *event)
637{
638 if (!composition->getShowEventsMode() && composition->getRenderNodeActivity())
639 composition->stopDisplayingActivity();
640
641 QDockWidget::closeEvent(event);
642}
643
647void VuoSearchBox::repositionChildWidgets()
648{
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());
657 update();
658}
659
663void VuoSearchBox::updateColor(bool isDark)
664{
665 QString barBackgroundColor = isDark ? "#919191" : "#efefef";
666 QString pressedToolButtonBackgroundColor = isDark ? "#aaaaaa" : "#d4d4d4";
667 QString disabledToolButtonArrowColor = isDark ? "#707070" : "#c0c0c0";
668
669 QString styleSheet = VUO_QSTRINGIFY(
670 QWidget#searchBoxContents {
671 background-color: %1;
672 }
673 QToolButton#previousButton,
674 QToolButton#nextButton {
675 border: 1px;
676 background-color: %1;
677 border-radius: 4px;
678 }
679 QToolButton#previousButton:pressed,
680 QToolButton#nextButton:pressed {
681 background-color: %2;
682 }
683 QToolButton#previousButton:disabled,
684 QToolButton#nextButton:disabled {
685 color: %3;
686 }
687 )
688 .arg(barBackgroundColor)
689 .arg(pressedToolButtonBackgroundColor)
690 .arg(disabledToolButtonArrowColor);
691
692 if (isDark)
693 {
694 QString focusRingColor = "#1d6ae5";
695 styleSheet += VUO_QSTRINGIFY(
696 QLineEdit {
697 border: 1px solid #919191;
698 background: #262626;
699 padding-top: 2px;
700 }
701 QLineEdit:focus {
702 border: 2px solid %1;
703 padding-top: 1px;
704 }
705
706 QPushButton {
707 border: none;
708 background: #aaaaaa;
709 border-radius: 4px;
710 margin: 4px 7px 7px 5px;
711 }
712 QPushButton:pressed {
713 background: #cccccc;
714 }
715 QPushButton:focus {
716 border: 2px solid %1;
717 }
718 )
719 .arg(focusRingColor);
720 }
721
722 ui->searchBoxContents->setStyleSheet(styleSheet);
723
724 ui->searchText->setAttribute(Qt::WA_MacShowFocusRect, !isDark);
725}
726
732bool VuoSearchBox::itemLessThan(QGraphicsItem *item1, QGraphicsItem *item2)
733{
734 int item1RowNum = item1->scenePos().y()/VuoRendererComposition::majorGridLineSpacing;
735 int item2RowNum = item2->scenePos().y()/VuoRendererComposition::majorGridLineSpacing;
736
737 if (item1RowNum < item2RowNum)
738 return true;
739 else if (item2RowNum < item1RowNum)
740 return false;
741 return (item1->scenePos().x() < item2->scenePos().x());
742}
743
748{
749 return (ui->nextButton->isEnabled() && ui->previousButton->isEnabled());
750}
751
752VuoSearchBox::~VuoSearchBox()
753{
754 delete ui;
755}