VirtualBox

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

Last change on this file since 102493 was 101563, checked in by vboxsync, 11 months ago

FE/Qt: bugref:10450: Get rid of Qt5 stuff; This one is about signal connection ambiguity stuff.

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette