VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/logviewer/UIVMLogViewerFilterWidget.cpp

Last change on this file was 103977, checked in by vboxsync, 2 months ago

Apply RT_OVERRIDE/NS_OVERRIDE where required to shut up clang.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.8 KB
Line 
1/* $Id: UIVMLogViewerFilterWidget.cpp 103977 2024-03-21 02:04:52Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIVMLogViewer class implementation.
4 */
5
6/*
7 * Copyright (C) 2010-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28/* Qt includes: */
29#include <QApplication>
30#include <QButtonGroup>
31#include <QComboBox>
32#include <QHBoxLayout>
33#if defined(RT_OS_SOLARIS)
34# include <QFontDatabase>
35#endif
36#include <QLabel>
37#include <QLineEdit>
38#include <QPlainTextEdit>
39#include <QRegularExpression>
40#include <QTextCursor>
41#include <QRadioButton>
42
43/* GUI includes: */
44#include "QIToolButton.h"
45#include "UIIconPool.h"
46#include "UITranslationEventListener.h"
47#include "UIVMLogPage.h"
48#include "UIVMLogViewerFilterWidget.h"
49#include "UIVMLogViewerWidget.h"
50#ifdef VBOX_WS_MAC
51# include "VBoxUtils-darwin.h"
52#endif
53
54/* Other VBox includes: */
55#include <iprt/assert.h>
56
57
58/*********************************************************************************************************************************
59* UIVMFilterLineEdit definition. *
60*********************************************************************************************************************************/
61
62/** UIVMFilterLineEdit class is used to display and modify the list of filter terms.
63 * the terms are displayed as words with spaces in between and it is possible to
64 * remove these terms one by one by selecting them or completely by the clearAll button
65 * located on the right side of the line edit: */
66class UIVMFilterLineEdit : public QLineEdit
67{
68 Q_OBJECT;
69
70signals:
71
72 void sigFilterTermRemoved(QString removedString);
73 void sigClearAll();
74
75public:
76
77 UIVMFilterLineEdit(QWidget *parent = 0);
78 void addFilterTerm(const QString& filterTermString);
79 void clearAll();
80
81protected:
82
83 /* Delete mouseDoubleClick and mouseMoveEvent implementations of the base class */
84 virtual void mouseDoubleClickEvent(QMouseEvent *) RT_OVERRIDE {}
85 virtual void mouseMoveEvent(QMouseEvent *) RT_OVERRIDE {}
86 /* Override the mousePressEvent to control how selection is done: */
87 virtual void mousePressEvent(QMouseEvent * event) RT_OVERRIDE;
88 virtual void mouseReleaseEvent(QMouseEvent *) RT_OVERRIDE {}
89 virtual void paintEvent(QPaintEvent *event) RT_OVERRIDE;
90
91private slots:
92
93 /* Nofifies the listeners that selected word (filter term) has been removed: */
94 void sltRemoveFilterTerm();
95 /* The whole content is removed. Listeners are notified: */
96 void sltClearAll();
97
98private:
99
100 void createButtons();
101 QToolButton *m_pRemoveTermButton;
102 QToolButton *m_pClearAllButton;
103 const int m_iRemoveTermButtonSize;
104 int m_iTrailingSpaceCount;
105};
106
107
108/*********************************************************************************************************************************
109* UIVMFilterLineEdit implementation. *
110*********************************************************************************************************************************/
111
112UIVMFilterLineEdit::UIVMFilterLineEdit(QWidget *parent /*= 0*/)
113 :QLineEdit(parent)
114 , m_pRemoveTermButton(0)
115 , m_pClearAllButton(0)
116 , m_iRemoveTermButtonSize(16)
117 , m_iTrailingSpaceCount(1)
118{
119 setReadOnly(true);
120 home(false);
121 setContextMenuPolicy(Qt::NoContextMenu);
122 createButtons();
123 /** Try to guess the width of the space between filter terms so that remove button
124 we display when a term is selected does not hide the next/previous word: */
125#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
126 int spaceWidth = fontMetrics().horizontalAdvance(' ');
127#else
128 int spaceWidth = fontMetrics().width(' ');
129#endif
130 if (spaceWidth != 0)
131 m_iTrailingSpaceCount = (m_iRemoveTermButtonSize / spaceWidth) + 1;
132}
133
134void UIVMFilterLineEdit::addFilterTerm(const QString& filterTermString)
135{
136 if (text().isEmpty())
137 insert(filterTermString);
138 else
139 {
140 QString newString(filterTermString);
141 QString space(m_iTrailingSpaceCount, QChar(' '));
142 insert(newString.prepend(space));
143 }
144}
145
146void UIVMFilterLineEdit::clearAll()
147{
148 if (text().isEmpty())
149 return;
150 sltClearAll();
151}
152
153void UIVMFilterLineEdit::mousePressEvent(QMouseEvent * event)
154{
155 /* Simulate double mouse click to select a word with a single click: */
156 QLineEdit::mouseDoubleClickEvent(event);
157}
158
159void UIVMFilterLineEdit::paintEvent(QPaintEvent *event)
160{
161 /* Call to base-class: */
162 QLineEdit::paintEvent(event);
163
164 if (!m_pClearAllButton || !m_pRemoveTermButton)
165 createButtons();
166 int clearButtonSize = height();
167
168 int deltaHeight = 0.5 * (height() - m_pClearAllButton->height());
169#ifdef VBOX_WS_MAC
170 m_pClearAllButton->setGeometry(width() - clearButtonSize - 2, deltaHeight, clearButtonSize, clearButtonSize);
171#else
172 m_pClearAllButton->setGeometry(width() - clearButtonSize - 1, deltaHeight, clearButtonSize, clearButtonSize);
173#endif
174
175 /* If we have a selected term move the m_pRemoveTermButton to the end of the
176 or start of the word (depending on the location of the word within line edit itself: */
177 if (hasSelectedText())
178 {
179 //int deltaHeight = 0.5 * (height() - m_pClearAllButton->height());
180 m_pRemoveTermButton->show();
181 int buttonSize = m_iRemoveTermButtonSize;
182#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
183 int charWidth = fontMetrics().horizontalAdvance('x');
184#else
185 int charWidth = fontMetrics().width('x');
186#endif
187#ifdef VBOX_WS_MAC
188 int buttonLeft = cursorRect().left() + 1;
189#else
190 int buttonLeft = cursorRect().right() - 0.9 * charWidth;
191#endif
192 /* If buttonLeft is in far right of the line edit, move the
193 button to left side of the selected word: */
194 if (buttonLeft + buttonSize >= width() - clearButtonSize)
195 {
196 int selectionWidth = charWidth * selectedText().length();
197 buttonLeft -= (selectionWidth + buttonSize);
198 }
199 m_pRemoveTermButton->setGeometry(buttonLeft, deltaHeight, buttonSize, buttonSize);
200 }
201 else
202 m_pRemoveTermButton->hide();
203}
204
205void UIVMFilterLineEdit::sltRemoveFilterTerm()
206{
207 if (!hasSelectedText())
208 return;
209 emit sigFilterTermRemoved(selectedText());
210 /* Remove the string from text() including the trailing space: */
211 setText(text().remove(selectionStart(), selectedText().length() + m_iTrailingSpaceCount));
212}
213
214void UIVMFilterLineEdit::sltClearAll()
215{
216 /* Check if we have some text to avoid recursive calls: */
217 if (text().isEmpty())
218 return;
219
220 clear();
221 emit sigClearAll();
222}
223
224void UIVMFilterLineEdit::createButtons()
225{
226 if (!m_pRemoveTermButton)
227 {
228 m_pRemoveTermButton = new QToolButton(this);
229 if (m_pRemoveTermButton)
230 {
231 m_pRemoveTermButton->setIcon(UIIconPool::iconSet(":/log_viewer_delete_filter_16px.png"));
232 m_pRemoveTermButton->hide();
233 connect(m_pRemoveTermButton, &QIToolButton::clicked, this, &UIVMFilterLineEdit::sltRemoveFilterTerm);
234 const QSize sh = m_pRemoveTermButton->sizeHint();
235 m_pRemoveTermButton->setStyleSheet("QToolButton { border: 0px none black; margin: 0px 0px 0px 0px; } QToolButton::menu-indicator {image: none;}");
236 m_pRemoveTermButton->setFixedSize(sh);
237 }
238 }
239
240 if (!m_pClearAllButton)
241 {
242 m_pClearAllButton = new QToolButton(this);
243 if (m_pClearAllButton)
244 {
245 m_pClearAllButton->setIcon(UIIconPool::iconSet(":/log_viewer_delete_all_filters_16px.png"));
246 connect(m_pClearAllButton, &QIToolButton::clicked, this, &UIVMFilterLineEdit::sltClearAll);
247 const QSize sh = m_pClearAllButton->sizeHint();
248 m_pClearAllButton->setStyleSheet("QToolButton { border: 0px none black; margin: 0px 0px 0px 0px; } QToolButton::menu-indicator {image: none;}");
249 m_pClearAllButton->setFixedSize(sh);
250 }
251 }
252 if (m_pRemoveTermButton && m_pClearAllButton)
253 setMinimumHeight(qMax(m_pRemoveTermButton->minimumHeight(), m_pClearAllButton->minimumHeight()));
254 else if (m_pRemoveTermButton)
255 setMinimumHeight(m_pRemoveTermButton->minimumHeight());
256 else if (m_pClearAllButton)
257 setMinimumHeight(m_pClearAllButton->minimumHeight());
258}
259
260
261/*********************************************************************************************************************************
262* UIVMLogViewerFilterWidget implementation. *
263*********************************************************************************************************************************/
264
265UIVMLogViewerFilterWidget::UIVMLogViewerFilterWidget(QWidget *pParent, UIVMLogViewerWidget *pViewer)
266 : UIVMLogViewerPane(pParent, pViewer)
267 , m_pFilterLabel(0)
268 , m_pFilterComboBox(0)
269 , m_pButtonGroup(0)
270 , m_pAndRadioButton(0)
271 , m_pOrRadioButton(0)
272 , m_pRadioButtonContainer(0)
273 , m_pAddFilterTermButton(0)
274 , m_eFilterOperatorButton(AndButton)
275 , m_pFilterTermsLineEdit(0)
276 , m_pResultLabel(0)
277 , m_iUnfilteredLineCount(0)
278 , m_iFilteredLineCount(0)
279{
280 prepareWidgets();
281 prepareConnections();
282}
283
284void UIVMLogViewerFilterWidget::applyFilter()
285{
286 if (isVisible())
287 filter();
288 else
289 resetFiltering();
290 sltRetranslateUI();
291 emit sigFilterApplied();
292}
293
294void UIVMLogViewerFilterWidget::filter()
295{
296 if (!viewer())
297 return;
298 QPlainTextEdit *pCurrentTextEdit = textEdit();
299 if (!pCurrentTextEdit)
300 return;
301
302 UIVMLogPage *logPage = viewer()->currentLogPage();
303 if (!logPage)
304 return;
305
306 const QString* originalLogString = logString();
307 m_iUnfilteredLineCount = 0;
308 m_iFilteredLineCount = 0;
309 if (!originalLogString || originalLogString->isNull())
310 return;
311 QTextDocument *document = textDocument();
312 if (!document)
313 return;
314 QStringList stringLines = originalLogString->split("\n");
315 m_iUnfilteredLineCount = stringLines.size();
316
317 if (m_filterTermSet.empty())
318 resetFiltering();
319
320 /* Prepare filter-data: */
321 QString strFilteredText;
322 for (int lineIdx = 0; lineIdx < stringLines.size(); ++lineIdx)
323 {
324 const QString& currentLineString = stringLines[lineIdx];
325 if (currentLineString.isEmpty())
326 continue;
327 if (applyFilterTermsToString(currentLineString))
328 strFilteredText.append(currentLineString).append("\n");
329 }
330
331 document->setPlainText(strFilteredText);
332 m_iFilteredLineCount = document->lineCount();
333
334 /* Move the cursor position to end: */
335 QTextCursor cursor = pCurrentTextEdit->textCursor();
336 cursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
337 pCurrentTextEdit->setTextCursor(cursor);
338 logPage->scrollToEnd();
339}
340
341void UIVMLogViewerFilterWidget::resetFiltering()
342{
343 UIVMLogPage *logPage = viewer()->currentLogPage();
344 QTextDocument *document = textDocument();
345 if (!logPage || !document)
346 return;
347
348 document->setPlainText(logPage->logString());
349 m_iFilteredLineCount = document->lineCount();
350 m_iUnfilteredLineCount = document->lineCount();
351 logPage->scrollToEnd();
352}
353
354bool UIVMLogViewerFilterWidget::applyFilterTermsToString(const QString& string)
355{
356 /* Number of the filter terms contained with the @p string: */
357 int hitCount = 0;
358
359 for (QSet<QString>::const_iterator iterator = m_filterTermSet.begin();
360 iterator != m_filterTermSet.end(); ++iterator)
361 {
362 /* Disregard empty and invalid filter terms: */
363 const QString& filterTerm = *iterator;
364 if (filterTerm.isEmpty())
365 continue;
366 const QRegularExpression rxFilterExp(filterTerm, QRegularExpression::CaseInsensitiveOption);
367 if (!rxFilterExp.isValid())
368 continue;
369
370 if (string.contains(rxFilterExp))
371 {
372 ++hitCount;
373 /* Early return */
374 if (m_eFilterOperatorButton == OrButton)
375 return true;
376 }
377
378 /* Early return */
379 if (!string.contains(rxFilterExp) && m_eFilterOperatorButton == AndButton )
380 return false;
381 }
382 /* All the terms are found within the @p string. To catch AND case: */
383 if (hitCount == m_filterTermSet.size())
384 return true;
385 return false;
386}
387
388
389void UIVMLogViewerFilterWidget::sltAddFilterTerm()
390{
391 if (!m_pFilterComboBox)
392 return;
393 if (m_pFilterComboBox->currentText().isEmpty())
394 return;
395
396 /* Continue only if the term is new. */
397 if (m_filterTermSet.contains(m_pFilterComboBox->currentText()))
398 return;
399 m_filterTermSet.insert(m_pFilterComboBox->currentText());
400
401 /* Add the new filter term to line edit: */
402 if (m_pFilterTermsLineEdit)
403 m_pFilterTermsLineEdit->addFilterTerm(m_pFilterComboBox->currentText());
404
405 /* Clear the content of the combo box: */
406 m_pFilterComboBox->setCurrentText(QString());
407 applyFilter();
408}
409
410void UIVMLogViewerFilterWidget::sltClearFilterTerms()
411{
412 if (m_filterTermSet.empty())
413 return;
414 m_filterTermSet.clear();
415 applyFilter();
416 if (m_pFilterTermsLineEdit)
417 m_pFilterTermsLineEdit->clearAll();
418}
419
420void UIVMLogViewerFilterWidget::sltOperatorButtonChanged(QAbstractButton *pButton)
421{
422 int buttonId = m_pButtonGroup->id(pButton);
423 if (buttonId < 0 || buttonId >= ButtonEnd)
424 return;
425 m_eFilterOperatorButton = static_cast<FilterOperatorButton>(buttonId);
426 applyFilter();
427}
428
429void UIVMLogViewerFilterWidget::sltRemoveFilterTerm(const QString &termString)
430{
431 m_filterTermSet.remove(termString);
432 applyFilter();
433}
434
435void UIVMLogViewerFilterWidget::prepareWidgets()
436{
437 QVBoxLayout *pMainLayout = new QVBoxLayout(this);
438 AssertReturnVoid(pMainLayout);
439
440 prepareRadioButtonGroup(pMainLayout);
441
442 /* Create combo/button layout: */
443 QHBoxLayout *pComboButtonLayout = new QHBoxLayout;
444 if (pComboButtonLayout)
445 {
446 pComboButtonLayout->setContentsMargins(0, 0, 0, 0);
447#ifdef VBOX_WS_MAC
448 pComboButtonLayout->setSpacing(5);
449#else
450 pComboButtonLayout->setSpacing(qApp->style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing) / 2);
451#endif
452
453 /* Create filter combo-box: */
454 m_pFilterComboBox = new QComboBox;
455 if (m_pFilterComboBox)
456 {
457 m_pFilterComboBox->setEditable(true);
458 QStringList strFilterPresets;
459 strFilterPresets << "" << "GUI" << "NAT" << "AHCI" << "VD"
460 << "Audio" << "VUSB" << "SUP" << "PGM" << "HDA"
461 << "HM" << "VMM" << "GIM" << "CPUM";
462 strFilterPresets.sort();
463 m_pFilterComboBox->addItems(strFilterPresets);
464 pComboButtonLayout->addWidget(m_pFilterComboBox);
465 }
466
467 /* Create add filter-term button: */
468 m_pAddFilterTermButton = new QIToolButton;
469 if (m_pAddFilterTermButton)
470 {
471 m_pAddFilterTermButton->setIcon(UIIconPool::iconSet(":/log_viewer_filter_add_16px.png"));
472 pComboButtonLayout->addWidget(m_pAddFilterTermButton);
473 }
474
475 pMainLayout->addLayout(pComboButtonLayout, 1);
476 }
477
478 /* Create filter-term line-edit: */
479 m_pFilterTermsLineEdit = new UIVMFilterLineEdit;
480 if (m_pFilterTermsLineEdit)
481 {
482 m_pFilterTermsLineEdit->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
483 pMainLayout->addWidget(m_pFilterTermsLineEdit, 3);
484 }
485
486 /* Create result label: */
487 m_pResultLabel = new QLabel;
488 if (m_pResultLabel)
489 {
490 m_pResultLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
491 pMainLayout->addWidget(m_pResultLabel, 0);
492 }
493 pMainLayout->addStretch(1);
494}
495
496void UIVMLogViewerFilterWidget::prepareRadioButtonGroup(QVBoxLayout *pLayout)
497{
498 /* Create radio-button container: */
499 m_pRadioButtonContainer = new QFrame;
500 if (m_pRadioButtonContainer)
501 {
502 /* Configure container: */
503 m_pRadioButtonContainer->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
504 m_pRadioButtonContainer->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
505
506 /* Create container layout: */
507 QHBoxLayout *pContainerLayout = new QHBoxLayout(m_pRadioButtonContainer);
508 if (pContainerLayout)
509 {
510 /* Configure layout: */
511#ifdef VBOX_WS_MAC
512 pContainerLayout->setContentsMargins(5, 0, 0, 7);
513 pContainerLayout->setSpacing(5);
514#else
515 pContainerLayout->setContentsMargins(qApp->style()->pixelMetric(QStyle::PM_LayoutLeftMargin) / 2, 0,
516 qApp->style()->pixelMetric(QStyle::PM_LayoutRightMargin) / 2, 0);
517 pContainerLayout->setSpacing(qApp->style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing) / 2);
518#endif
519
520 /* Create button-group: */
521 m_pButtonGroup = new QButtonGroup(this);
522 if (m_pButtonGroup)
523 {
524 /* Create 'Or' radio-button: */
525 m_pOrRadioButton = new QRadioButton;
526 if (m_pOrRadioButton)
527 {
528 /* Configure radio-button: */
529 m_pButtonGroup->addButton(m_pOrRadioButton, static_cast<int>(OrButton));
530 m_pOrRadioButton->setChecked(true);
531 m_pOrRadioButton->setText("Or");
532
533 /* Add into layout: */
534 pContainerLayout->addWidget(m_pOrRadioButton);
535 }
536
537 /* Create 'And' radio-button: */
538 m_pAndRadioButton = new QRadioButton;
539 if (m_pAndRadioButton)
540 {
541 /* Configure radio-button: */
542 m_pButtonGroup->addButton(m_pAndRadioButton, static_cast<int>(AndButton));
543 m_pAndRadioButton->setText("And");
544
545 /* Add into layout: */
546 pContainerLayout->addWidget(m_pAndRadioButton);
547 }
548 }
549 }
550
551 /* Add into layout: */
552 pLayout->addWidget(m_pRadioButtonContainer);
553 }
554
555 /* Initialize other related stuff: */
556 m_eFilterOperatorButton = OrButton;
557}
558
559void UIVMLogViewerFilterWidget::prepareConnections()
560{
561 connect(m_pAddFilterTermButton, &QIToolButton::clicked,
562 this, &UIVMLogViewerFilterWidget::sltAddFilterTerm);
563 connect(m_pButtonGroup, &QButtonGroup::buttonClicked,
564 this, &UIVMLogViewerFilterWidget::sltOperatorButtonChanged);
565 connect(m_pFilterComboBox, &QComboBox::currentIndexChanged,
566 this, &UIVMLogViewerFilterWidget::sltAddFilterTerm);
567 connect(m_pFilterTermsLineEdit, &UIVMFilterLineEdit::sigFilterTermRemoved,
568 this, &UIVMLogViewerFilterWidget::sltRemoveFilterTerm);
569 connect(m_pFilterTermsLineEdit, &UIVMFilterLineEdit::sigClearAll,
570 this, &UIVMLogViewerFilterWidget::sltClearFilterTerms);
571 connect(&translationEventListener(), &UITranslationEventListener::sigRetranslateUI,
572 this, &UIVMLogViewerFilterWidget::sltRetranslateUI);
573}
574
575void UIVMLogViewerFilterWidget::sltRetranslateUI()
576{
577 m_pFilterComboBox->setToolTip(UIVMLogViewerWidget::tr("Select or enter a term which will be used in filtering the log text"));
578 m_pAddFilterTermButton->setToolTip(UIVMLogViewerWidget::tr("Add the filter term to the set of filter terms"));
579 m_pResultLabel->setText(UIVMLogViewerWidget::tr("Showing %1/%2").arg(m_iFilteredLineCount).arg(m_iUnfilteredLineCount));
580 m_pFilterTermsLineEdit->setToolTip(UIVMLogViewerWidget::tr("The filter terms list, select one to remove or click "
581 "the button on the right side to remove them all"));
582 m_pRadioButtonContainer->setToolTip(UIVMLogViewerWidget::tr("The type of boolean operator for filter operation"));
583}
584
585bool UIVMLogViewerFilterWidget::eventFilter(QObject *pObject, QEvent *pEvent)
586{
587 /* Handle only events sent to viewer(): */
588 if (pObject != viewer())
589 return UIVMLogViewerPane::eventFilter(pObject, pEvent);
590
591 /* Depending on event-type: */
592 switch (pEvent->type())
593 {
594 /* Process key press only: */
595 case QEvent::KeyPress:
596 {
597 /* Cast to corresponding key press event: */
598 QKeyEvent *pKeyEvent = static_cast<QKeyEvent*>(pEvent);
599
600 /* Handle Ctrl+T key combination as a shortcut to focus search field: */
601 if (pKeyEvent->QInputEvent::modifiers() == Qt::ControlModifier &&
602 pKeyEvent->key() == Qt::Key_T)
603 {
604 if (isHidden())
605 show();
606 m_pFilterComboBox->setFocus();
607 return true;
608 }
609 else if (pKeyEvent->key() == Qt::Key_Return && m_pFilterComboBox && m_pFilterComboBox->hasFocus())
610 sltAddFilterTerm();
611
612 break;
613 }
614 default:
615 break;
616 }
617
618 /* Call to base-class: */
619 return UIVMLogViewerPane::eventFilter(pObject, pEvent);
620}
621
622/** Handles the Qt show @a pEvent. */
623void UIVMLogViewerFilterWidget::showEvent(QShowEvent *pEvent)
624{
625 UIVMLogViewerPane::showEvent(pEvent);
626 /* Set focus to combo-box: */
627 m_pFilterComboBox->setFocus();
628 applyFilter();
629}
630
631void UIVMLogViewerFilterWidget::hideEvent(QHideEvent *pEvent)
632{
633 UIVMLogViewerPane::hideEvent(pEvent);
634 applyFilter();
635}
636
637#include "UIVMLogViewerFilterWidget.moc"
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use