VirtualBox

Changeset 70487 in vbox


Ignore:
Timestamp:
Jan 8, 2018 8:04:54 PM (7 years ago)
Author:
vboxsync
Message:

FE/Qt: bugref:9072 The first attempt on logviewer's bookmark panel

Location:
trunk/src/VBox/Frontends/VirtualBox
Files:
5 edited
2 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk

    r70466 r70487  
    335335        src/hostnetwork/UIHostNetworkDetailsWidget.h \
    336336        src/hostnetwork/UIHostNetworkManager.h \
     337        src/logviewer/UIVMLogViewerBookmarksPanel.h \
    337338        src/logviewer/UIVMLogViewerDialog.h \
    338339        src/logviewer/UIVMLogViewerFilterPanel.h \
     
    651652        src/hostnetwork/UIHostNetworkManager.cpp \
    652653        src/hostnetwork/UIHostNetworkUtils.cpp \
     654        src/logviewer/UIVMLogViewerBookmarksPanel.cpp \
    653655        src/logviewer/UIVMLogViewerDialog.cpp \
    654656        src/logviewer/UIVMLogViewerFilterPanel.cpp \
  • trunk/src/VBox/Frontends/VirtualBox/src/logviewer/UIVMLogViewerBookmarksPanel.cpp

    r70474 r70487  
    2121
    2222/* Qt includes: */
    23 # include <QButtonGroup>
    2423# include <QComboBox>
    25 # include <QFrame>
    2624# include <QHBoxLayout>
    2725# if defined(RT_OS_SOLARIS)
     
    3432# include <QTextCursor>
    3533# include <QToolButton>
    36 # include <QRadioButton>
    3734# include <QScrollArea>
    3835
     
    4037# include "UIIconPool.h"
    4138# include "UISpecialControls.h"
    42 # include "UIVMLogViewerFilterPanel.h"
     39# include "UIVMLogViewerBookmarksPanel.h"
    4340# include "UIVMLogViewerWidget.h"
    4441# ifdef VBOX_WS_MAC
     
    4744#endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
    4845
    49 /* UIVMFilterLineEdit class is used to display and modify the list of filter terms.
    50    the terms are displayed as words with spaces in between and it is possible to
    51    remove these terms one by one by selecting them or completely by the clearAll button
    52    located on the right side of the line edit: */
    53 class UIVMFilterLineEdit : public QLineEdit
    54 {
    55     Q_OBJECT;
    5646
    57 signals:
    58 
    59     void sigFilterTermRemoved(QString removedString);
    60     void sigClearAll();
    61 
    62 public:
    63 
    64     UIVMFilterLineEdit(QWidget *parent = 0)
    65         :QLineEdit(parent)
    66         , m_pRemoveTermButton(0)
    67     {
    68         setReadOnly(true);
    69         home(false);
    70         createButtons();
    71     }
    72 
    73     void addFilterTerm(const QString& filterTermString)
    74     {
    75         if (text().isEmpty())
    76             insert(filterTermString);
    77         else
    78         {
    79             QString newString(filterTermString);
    80             insert(newString.prepend(' '));
    81         }
    82     }
    83 
    84     void clearAll()
    85     {
    86         if (text().isEmpty())
    87             return;
    88         sltClearAll();
    89     }
    90 
    91 protected:
    92 
    93     /* Overload the mouseXXXEvent to control how selection is done: */
    94     virtual void        mouseDoubleClickEvent(QMouseEvent *){}
    95     virtual void        mouseMoveEvent(QMouseEvent *){}
    96     virtual void        mousePressEvent(QMouseEvent * event)
    97     {
    98         /* Simulate double mouse click to select a word with a single click: */
    99         QLineEdit::mouseDoubleClickEvent(event);
    100     }
    101 
    102     virtual void        mouseReleaseEvent(QMouseEvent *){}
    103     virtual void paintEvent(QPaintEvent *event)
    104     {
    105         QLineEdit::paintEvent(event);
    106         int clearButtonSize = height();
    107         m_pClearAllButton->setGeometry(width() - clearButtonSize, 0, clearButtonSize, clearButtonSize);
    108         /* If we have a selected term move the m_pRemoveTermButton to the end of the
    109            or start of the word (depending on the location of the word within line edit itself: */
    110         if (hasSelectedText())
    111         {
    112             m_pRemoveTermButton->show();
    113             int buttonY = 0.5 * (height() - 16);
    114             int buttonSize = 16;
    115             int charWidth = fontMetrics().width('x');
    116             int buttonLeft = cursorRect().right() - 0.5 * charWidth;
    117             /* If buttonLeft is in far left of the line edit, move the
    118                button to left side of the selected word: */
    119             if (buttonLeft + buttonSize  >=  width() - clearButtonSize)
    120             {
    121                 int selectionWidth = charWidth * selectedText().length();
    122                 buttonLeft -= (selectionWidth + buttonSize);
    123             }
    124             m_pRemoveTermButton->setGeometry(buttonLeft, buttonY, buttonSize, buttonSize);
    125         }
    126         else
    127             m_pRemoveTermButton->hide();
    128     }
    129 
    130 private slots:
    131 
    132     /* Nofifies the listeners that selected word (filter term) has been removed: */
    133     void sltRemoveFilterTerm()
    134     {
    135         if (!hasSelectedText())
    136             return;
    137         emit sigFilterTermRemoved(selectedText());
    138         /* Remove the string from text() including the trailing space: */
    139         setText(text().remove(selectionStart(), selectedText().length()+1));
    140     }
    141 
    142     /* The whole content is removed. Listeners are notified: */
    143     void sltClearAll()
    144     {
    145         /* Check if we have some text to avoid recursive calls: */
    146         if (text().isEmpty())
    147             return;
    148 
    149         clear();
    150         emit sigClearAll();
    151     }
    152 
    153 private:
    154 
    155     void createButtons()
    156     {
    157         m_pRemoveTermButton = new QToolButton(this);
    158         AssertReturnVoid(m_pRemoveTermButton);
    159         m_pRemoveTermButton->setIcon(m_pRemoveTermButton->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
    160         m_pRemoveTermButton->hide();
    161 
    162         m_pClearAllButton = new QToolButton(this);
    163         AssertReturnVoid(m_pClearAllButton);
    164         m_pClearAllButton->setIcon(m_pRemoveTermButton->style()->standardIcon(QStyle::SP_LineEditClearButton));
    165 
    166         connect(m_pRemoveTermButton, &QToolButton::clicked, this, &UIVMFilterLineEdit::sltRemoveFilterTerm);
    167         connect(m_pClearAllButton, &QToolButton::clicked, this, &UIVMFilterLineEdit::sltClearAll);
    168     }
    169 
    170     QToolButton *m_pRemoveTermButton;
    171     QToolButton *m_pClearAllButton;
    172 };
    173 
    174 UIVMLogViewerFilterPanel::UIVMLogViewerFilterPanel(QWidget *pParent, UIVMLogViewerWidget *pViewer)
     47UIVMLogViewerBookmarksPanel::UIVMLogViewerBookmarksPanel(QWidget *pParent, UIVMLogViewerWidget *pViewer)
    17548    : QIWithRetranslateUI<QWidget>(pParent)
     49    , m_iMaxBookmarkTextLength(60)
    17650    , m_pViewer(pViewer)
    17751    , m_pMainLayout(0)
    17852    , m_pCloseButton(0)
    179     , m_pFilterLabel(0)
    180     , m_pFilterComboBox(0)
    181     , m_pButtonGroup(0)
    182     , m_pAndRadioButton(0)
    183     , m_pOrRadioButton(0)
    184     , m_pRadioButtonContainer(0)
    185     , m_pAddFilterTermButton(0)
    186     , m_eFilterOperatorButton(AndButton)
    187     , m_pFilterTermsLineEdit(0)
    188     , m_pResultLabel(0)
    189     , m_iUnfilteredLineCount(0)
    190     , m_iFilteredLineCount(0)
     53    , m_pBookmarksComboBox(0)
    19154{
    19255    prepare();
    19356}
    19457
    195 void UIVMLogViewerFilterPanel::applyFilter(const int iCurrentIndex /* = 0 */)
     58void UIVMLogViewerBookmarksPanel::update()
    19659{
    197     Q_UNUSED(iCurrentIndex);
    198     filter();
    199     retranslateUi();
     60    if(!m_pBookmarksComboBox)
     61        return;
     62    const QVector<QPair<int, QString> > *bookmarkVector = m_pViewer->currentBookmarkVector();
     63    if(!bookmarkVector)
     64        return;
     65
     66    m_pBookmarksComboBox->clear();
     67    QStringList bList;
     68    for(int i = 0; i < bookmarkVector->size(); ++i)
     69    {
     70        QString strItem = QString("BookMark %1 at Line %2: %3").arg(QString::number(i)).
     71            arg(QString::number(bookmarkVector->at(i).first)).arg(bookmarkVector->at(i).second);
     72
     73        if(strItem.length() > m_iMaxBookmarkTextLength)
     74        {
     75            strItem.resize(m_iMaxBookmarkTextLength);
     76            strItem.replace(m_iMaxBookmarkTextLength, 3, QString("..."));
     77        }
     78        bList << strItem;
     79    }
     80    m_pBookmarksComboBox->addItems(bList);
    20081}
    20182
    202 void UIVMLogViewerFilterPanel::filter()
     83void UIVMLogViewerBookmarksPanel::setBookmarkIndex(int index)
    20384{
    204     QPlainTextEdit *pCurrentPage = m_pViewer->currentLogPage();
    205     AssertReturnVoid(pCurrentPage);
    206     const QString& strInputText = m_pViewer->currentLog();
    207     m_iUnfilteredLineCount = 0;
    208     m_iFilteredLineCount = 0;
    209     if (strInputText.isNull())
     85    if (!m_pBookmarksComboBox)
    21086        return;
    211     QTextDocument *document = pCurrentPage->document();
    212     if (!document)
     87    if (index >= m_pBookmarksComboBox->count())
    21388        return;
    214     QStringList stringLines = strInputText.split("\n");
    215     m_iUnfilteredLineCount = stringLines.size();
    216     if (m_filterTermList.empty())
    217     {
    218         document->setPlainText(strInputText);
    219         emit sigFilterApplied();
    220         m_iFilteredLineCount = document->lineCount();
    221         return;
    222     }
    223 
    224     /* Prepare filter-data: */
    225     QString strFilteredText;
    226     int count = 0;
    227     for (int lineIdx = 0; lineIdx < stringLines.size(); ++lineIdx)
    228     {
    229         const QString& currentLineString = stringLines[lineIdx];
    230         if (currentLineString.isEmpty())
    231             continue;
    232         if (applyFilterTermsToString(currentLineString))
    233         {
    234             strFilteredText.append(currentLineString).append("\n");
    235             ++count;
    236         }
    237     }
    238 
    239     document->setPlainText(strFilteredText);
    240     m_iFilteredLineCount = document->lineCount();
    241 
    242     /* Move the cursor position to end: */
    243     QTextCursor cursor = pCurrentPage->textCursor();
    244     cursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
    245     pCurrentPage->setTextCursor(cursor);
    246 
    247     emit sigFilterApplied();
     89    m_pBookmarksComboBox->setCurrentIndex(index);
    24890}
    24991
    250 
    251 bool UIVMLogViewerFilterPanel::applyFilterTermsToString(const QString& string)
    252 {
    253     /* Number of the filter terms contained with the @p string: */
    254     int hitCount = 0;
    255     for (int i = 0; i < m_filterTermList.size(); ++i)
    256     {
    257         const QRegExp rxFilterExp(m_filterTermList.at(i), Qt::CaseInsensitive);
    258         /* Disregard empty and invalid filter terms: */
    259         if (rxFilterExp.isEmpty() || !rxFilterExp.isValid())
    260             continue;
    261 
    262         if (string.contains(rxFilterExp))
    263         {
    264             ++hitCount;
    265             /* Early return */
    266             if (m_eFilterOperatorButton == OrButton)
    267                 return true;
    268         }
    269 
    270         /* Early return */
    271         if (!string.contains(rxFilterExp) && m_eFilterOperatorButton == AndButton )
    272             return false;
    273     }
    274     /* All the terms are found within the @p string. To catch AND case: */
    275     if (hitCount == m_filterTermList.size())
    276         return true;
    277     return false;
    278 }
    279 
    280 
    281 void UIVMLogViewerFilterPanel::sltAddFilterTerm()
    282 {
    283     if (!m_pFilterComboBox)
    284         return;
    285     if (m_pFilterComboBox->currentText().isEmpty())
    286         return;
    287 
    288     /* Continue only if the term is new. */
    289     if (m_filterTermList.contains(m_pFilterComboBox->currentText()))
    290         return;
    291     m_filterTermList.push_back(m_pFilterComboBox->currentText());
    292 
    293     /* Add the new filter term to line edit: */
    294     if (m_pFilterTermsLineEdit)
    295         m_pFilterTermsLineEdit->addFilterTerm(m_pFilterComboBox->currentText());
    296 
    297     /* Clear the content of the combo box: */
    298     m_pFilterComboBox->setCurrentText(QString());
    299     applyFilter();
    300 }
    301 
    302 void UIVMLogViewerFilterPanel::sltClearFilterTerms()
    303 {
    304     if (m_filterTermList.empty())
    305         return;
    306     m_filterTermList.clear();
    307     applyFilter();
    308     if (m_pFilterTermsLineEdit)
    309         m_pFilterTermsLineEdit->clearAll();
    310 }
    311 
    312 void UIVMLogViewerFilterPanel::sltOperatorButtonChanged(int buttonId)
    313 {
    314     if (buttonId < 0 || buttonId >= ButtonEnd)
    315         return;
    316     m_eFilterOperatorButton = static_cast<FilterOperatorButton>(buttonId);
    317     applyFilter();
    318 }
    319 
    320 void UIVMLogViewerFilterPanel::sltRemoveFilterTerm(const QString &termString)
    321 {
    322     QStringList newList;
    323     for (QStringList::iterator iterator = m_filterTermList.begin();
    324         iterator != m_filterTermList.end(); ++iterator)
    325     {
    326         if ((*iterator) != termString)
    327             newList.push_back(*iterator);
    328     }
    329     m_filterTermList = newList;
    330     applyFilter();
    331 }
    332 
    333 void UIVMLogViewerFilterPanel::prepare()
     92void UIVMLogViewerBookmarksPanel::prepare()
    33493{
    33594    prepareWidgets();
     
    33897}
    33998
    340 void UIVMLogViewerFilterPanel::prepareWidgets()
     99void UIVMLogViewerBookmarksPanel::prepareWidgets()
    341100{
    342101    m_pMainLayout = new QHBoxLayout(this);
     
    347106    m_pCloseButton = new UIMiniCancelButton(this);
    348107    AssertPtrReturnVoid(m_pCloseButton);
    349     m_pMainLayout->addWidget(m_pCloseButton);
     108    m_pMainLayout->addWidget(m_pCloseButton, 0, Qt::AlignLeft);
    350109
    351     prepareRadioButtonGroup();
     110    m_pBookmarksComboBox = new QComboBox(this);
     111    QFontMetrics fontMetrics = m_pBookmarksComboBox->fontMetrics();
     112    AssertPtrReturnVoid(m_pBookmarksComboBox);
     113    m_pBookmarksComboBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
     114    m_pBookmarksComboBox->setMaximumWidth(fontMetrics.width('a') * (m_iMaxBookmarkTextLength + 2));
     115    printf("max max %d\n", fontMetrics.width('a') * (m_iMaxBookmarkTextLength + 2));
     116    m_pMainLayout->addWidget(m_pBookmarksComboBox, 2, Qt::AlignLeft);
    352117
    353     m_pFilterComboBox = new QComboBox(this);
    354     AssertPtrReturnVoid(m_pFilterComboBox);
    355     {
    356         m_pFilterComboBox->setEditable(true);
    357         QStringList strFilterPresets;
    358         strFilterPresets << "" << "GUI" << "NAT" << "AHCI" << "VD" << "Audio" << "VUSB" << "SUP" << "PGM" << "HDA"
    359                          << "HM" << "VMM" << "GIM" << "CPUM";
    360         strFilterPresets.sort();
    361         m_pFilterComboBox->addItems(strFilterPresets);
    362         m_pMainLayout->addWidget(m_pFilterComboBox,1);
    363     }
    364 
    365     m_pAddFilterTermButton = new QPushButton(this);
    366     AssertPtrReturnVoid(m_pAddFilterTermButton);
    367     {
    368         m_pAddFilterTermButton->setIcon(UIIconPool::defaultIcon(UIIconPool::UIDefaultIconType_ArrowForward, this));
    369         m_pMainLayout->addWidget(m_pAddFilterTermButton,0);
    370     }
    371 
    372     m_pFilterTermsLineEdit = new UIVMFilterLineEdit(this);
    373     AssertPtrReturnVoid(m_pFilterTermsLineEdit);
    374     {
    375         m_pMainLayout->addWidget(m_pFilterTermsLineEdit, 4);
    376         m_pFilterTermsLineEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum /*vertical */);
    377     }
    378 
    379     m_pResultLabel = new QLabel(this);
    380     AssertPtrReturnVoid(m_pResultLabel);
    381     {
    382         m_pMainLayout->addWidget(m_pResultLabel,0);
    383     }
    384         /* Create filter-label: */
    385 //         m_pFilterLabel = new QLabel(this);
    386 //         AssertPtrReturnVoid(m_pFilterLabel);
    387 //         {
    388 //             /* Configure filter-label: */
    389 //             m_pFilterLabel->setBuddy(m_pFilterComboBox);
    390 // #ifdef VBOX_DARWIN_USE_NATIVE_CONTROLS
    391 //             QFont font = m_pFilterLabel->font();
    392 //             font.setPointSize(::darwinSmallFontSize());
    393 //             m_pFilterLabel->setFont(font);
    394 // #endif /* VBOX_DARWIN_USE_NATIVE_CONTROLS */
    395 //             /* Add filter-label to main-layout: */
    396 //             m_pMainLayout->addWidget(m_pFilterLabel);
    397 //         }
    398118}
    399119
    400 void UIVMLogViewerFilterPanel::prepareRadioButtonGroup()
     120void UIVMLogViewerBookmarksPanel::prepareConnections()
    401121{
    402     m_pButtonGroup = new QButtonGroup(this);
    403     AssertPtrReturnVoid(m_pButtonGroup);
     122    connect(m_pCloseButton, &UIMiniCancelButton::clicked, this, &UIVMLogViewerBookmarksPanel::hide);
    404123
    405     m_pRadioButtonContainer = new QFrame(this);
    406     m_pRadioButtonContainer->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
    407     AssertPtrReturnVoid(m_pRadioButtonContainer);
    408 
    409     QHBoxLayout* containerLayout = (new QHBoxLayout(m_pRadioButtonContainer));
    410     AssertPtrReturnVoid(containerLayout);
    411     containerLayout->setContentsMargins(0, 0, 0, 0);
    412     containerLayout->setSpacing(0);
    413 
    414     m_pAndRadioButton = new QRadioButton(this);
    415     m_pOrRadioButton =  new QRadioButton(this);
    416     AssertPtrReturnVoid(m_pAndRadioButton);
    417     AssertPtrReturnVoid(m_pOrRadioButton);
    418 
    419     m_pButtonGroup->addButton(m_pAndRadioButton, static_cast<int>(AndButton));
    420     m_pButtonGroup->addButton(m_pOrRadioButton, static_cast<int>(OrButton));
    421     m_pOrRadioButton->setText("Or");
    422     m_pAndRadioButton->setText("And");
    423     m_pOrRadioButton->setChecked(true);
    424     m_eFilterOperatorButton = OrButton;
    425 
    426     containerLayout->addWidget(m_pOrRadioButton);
    427     containerLayout->addWidget(m_pAndRadioButton);
    428     m_pMainLayout->addWidget(m_pRadioButtonContainer);
    429 }
    430 
    431 void UIVMLogViewerFilterPanel::prepareConnections()
    432 {
    433     connect(m_pCloseButton, &UIMiniCancelButton::clicked, this, &UIVMLogViewerFilterPanel::hide);
    434     connect(m_pAddFilterTermButton, &QPushButton::clicked, this,  &UIVMLogViewerFilterPanel::sltAddFilterTerm);
    435     connect(m_pButtonGroup, static_cast<void (QButtonGroup::*)(int)>(&QButtonGroup::buttonClicked),
    436             this, &UIVMLogViewerFilterPanel::sltOperatorButtonChanged);
    437     connect(m_pFilterComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
    438             this, &UIVMLogViewerFilterPanel::sltAddFilterTerm);
    439     connect(m_pFilterTermsLineEdit, &UIVMFilterLineEdit::sigFilterTermRemoved,
    440             this, &UIVMLogViewerFilterPanel::sltRemoveFilterTerm);
    441     connect(m_pFilterTermsLineEdit, &UIVMFilterLineEdit::sigClearAll,
    442             this, &UIVMLogViewerFilterPanel::sltClearFilterTerms);
    443124}
    444125
    445126
    446 void UIVMLogViewerFilterPanel::retranslateUi()
     127void UIVMLogViewerBookmarksPanel::retranslateUi()
    447128{
    448129    m_pCloseButton->setToolTip(UIVMLogViewerWidget::tr("Close the search panel."));
    449     m_pFilterComboBox->setToolTip(UIVMLogViewerWidget::tr("Enter filtering string here."));
    450     m_pAddFilterTermButton->setToolTip(UIVMLogViewerWidget::tr("Add filter term."));
    451     m_pResultLabel->setText(UIVMLogViewerWidget::tr("Showing %1/%2").arg(m_iFilteredLineCount).arg(m_iUnfilteredLineCount));
    452     m_pFilterTermsLineEdit->setToolTip(UIVMLogViewerWidget::tr("The filter terms list. Select one to remove or click the button on the right side to remove them all."));
    453     m_pRadioButtonContainer->setToolTip(UIVMLogViewerWidget::tr("The type of boolean operator for filter operation."));
    454130}
    455131
    456 bool UIVMLogViewerFilterPanel::eventFilter(QObject *pObject, QEvent *pEvent)
     132bool UIVMLogViewerBookmarksPanel::eventFilter(QObject *pObject, QEvent *pEvent)
    457133{
    458134    /* Depending on event-type: */
     
    462138    case QEvent::KeyPress:
    463139        {
    464             /* Cast to corresponding key press event: */
    465             QKeyEvent *pKeyEvent = static_cast<QKeyEvent*>(pEvent);
    466 
    467             /* Handle Ctrl+T key combination as a shortcut to focus search field: */
    468             if (pKeyEvent->QInputEvent::modifiers() == Qt::ControlModifier &&
    469                 pKeyEvent->key() == Qt::Key_T)
    470             {
    471                 if (m_pViewer->currentLogPage())
    472                 {
    473                     if (isHidden())
    474                         show();
    475                     m_pFilterComboBox->setFocus();
    476                     return true;
    477                 }
    478             }
    479             else if (pKeyEvent->key() == Qt::Key_Return && m_pFilterComboBox && m_pFilterComboBox->hasFocus())
    480                 sltAddFilterTerm();
    481 
    482140            break;
    483141        }
     
    490148
    491149/** Handles the Qt show @a pEvent. */
    492 void UIVMLogViewerFilterPanel::showEvent(QShowEvent *pEvent)
     150void UIVMLogViewerBookmarksPanel::showEvent(QShowEvent *pEvent)
    493151{
    494152    /* Call to base-class: */
    495153    QWidget::showEvent(pEvent);
    496     /* Set focus to combo-box: */
    497     m_pFilterComboBox->setFocus();
    498154}
    499155
    500156/** Handles the Qt hide @a pEvent. */
    501 void UIVMLogViewerFilterPanel::hideEvent(QHideEvent *pEvent)
     157void UIVMLogViewerBookmarksPanel::hideEvent(QHideEvent *pEvent)
    502158{
    503159    /* Get focused widget: */
     
    510166    QWidget::hideEvent(pEvent);
    511167}
    512 
    513 #include "UIVMLogViewerFilterPanel.moc"
  • trunk/src/VBox/Frontends/VirtualBox/src/logviewer/UIVMLogViewerBookmarksPanel.h

    r70474 r70487  
    1616 */
    1717
    18 #ifndef ___UIVMLogViewerFilterPanel_h___
    19 #define ___UIVMLogViewerFilterPanel_h___
     18#ifndef ___UIVMLogViewerBookmarksPanel_h___
     19#define ___UIVMLogViewerBookmarksPanel_h___
    2020
    2121/* Qt includes: */
     
    2626
    2727/* Forward declarations: */
    28 class QButtonGroup;
    2928class QComboBox;
    30 class QFrame;
    3129class QHBoxLayout;
    3230class QLabel;
    3331class QLineEdit;
    3432class QPushButton;
    35 class QRadioButton;
    3633class UIVMFilterLineEdit;
    3734class UIMiniCancelButton;
     
    4037
    4138/** QWidget extension
    42   * providing GUI for filter panel in VM Log Viewer. */
    43 class UIVMLogViewerFilterPanel : public QIWithRetranslateUI<QWidget>
     39  * providing GUI for bookmark management. Show a list of bookmarks currently set
     40  for displayed log page. It has controls to navigate and clear bookmarks. */
     41class UIVMLogViewerBookmarksPanel : public QIWithRetranslateUI<QWidget>
    4442{
    4543    Q_OBJECT;
     
    4745signals:
    4846
    49     /* Notifies listeners that the filter has been applied. */
    50     void sigFilterApplied();
    51 
    5247public:
    5348
    54     /** Constructs the filter-panel by passing @a pParent to the QWidget base-class constructor.
    55       * @param  pViewer  Specifies reference to the VM Log-Viewer this filter-panel belongs to. */
    56     UIVMLogViewerFilterPanel(QWidget *pParent, UIVMLogViewerWidget *pViewer);
     49    UIVMLogViewerBookmarksPanel(QWidget *pParent, UIVMLogViewerWidget *pViewer);
     50
     51    /* Adds a single bookmark to an existing list of bookmarks. Possibly called
     52       by UIVMLogViewerWidget when user adds a bookmark thru context menu etc. */
     53    void addBookmark(const QPair<int, QString> &newBookmark);
     54    /* Clear the bookmark list and show this list instead. Probably done after
     55       user switches to another log page tab etc. */
     56    void setBookmarksList(const QVector<QPair<int, QString> > &bookmarkList);
     57    void update();
     58    /* @a index is the index of the curent bookmark. */
     59    void setBookmarkIndex(int index);
    5760
    5861public slots:
    5962
    60     /** Applies filter settings and filters the current log-page.
    61       * @param  iCurrentIndex  Specifies index of current log-page, but it is actually not used in the method. */
    62     void applyFilter(const int iCurrentIndex = 0);
    6363
    6464private slots:
    6565
    66     /** Adds the new filter term and reapplies the filter. */
    67     void sltAddFilterTerm();
    68     /** Clear all the filter terms and reset the filtering. */
    69     void sltClearFilterTerms();
    70     /** Executes the necessary code to handle filter's boolean operator change ('And', 'Or'). */
    71     void sltOperatorButtonChanged(int buttonId);
    72     void sltRemoveFilterTerm(const QString &termString);
    7366
    7467private:
    7568
    76     enum FilterOperatorButton{
    77         AndButton = 0,
    78         OrButton,
    79         ButtonEnd
    80     };
    81 
    82     /** Prepares filter-panel. */
    8369    void prepare();
    8470    void prepareWidgets();
    85     void prepareRadioButtonGroup();
    8671    void prepareConnections();
    8772
     
    9681    void hideEvent(QHideEvent *pEvent);
    9782
    98     bool applyFilterTermsToString(const QString& string);
    99     void filter();
    100 
    101     /** Holds the reference to VM Log-Viewer this filter-panel belongs to. */
     83    const int m_iMaxBookmarkTextLength;
     84    /** Holds the reference to VM Log-Viewer this panel belongs to. */
    10285    UIVMLogViewerWidget *m_pViewer;
    10386    /** Holds the instance of main-layout we create. */
     
    10588    /** Holds the instance of close-button we create. */
    10689    UIMiniCancelButton  *m_pCloseButton;
    107     /** Holds the instance of filter-label we create. */
    108     QLabel              *m_pFilterLabel;
    109     /** Holds instance of filter combo-box we create. */
    110     QComboBox           *m_pFilterComboBox;
     90    QComboBox           *m_pBookmarksComboBox;
    11191
    112     QButtonGroup        *m_pButtonGroup;
    113     QRadioButton        *m_pAndRadioButton;
    114     QRadioButton        *m_pOrRadioButton;
    115     QFrame              *m_pRadioButtonContainer;
    116     QPushButton         *m_pAddFilterTermButton;
    117     QStringList          m_filterTermList;
    118     FilterOperatorButton m_eFilterOperatorButton;
    119     UIVMFilterLineEdit  *m_pFilterTermsLineEdit;
    120     QLabel              *m_pResultLabel;
    121     int                  m_iUnfilteredLineCount;
    122     int                  m_iFilteredLineCount;
    12392};
    12493
    125 #endif /* !___UIVMLogViewerFilterPanel_h___ */
     94#endif /* !___UIVMLogViewerBookmarksPanel_h___ */
  • trunk/src/VBox/Frontends/VirtualBox/src/logviewer/UIVMLogViewerFilterPanel.cpp

    r70474 r70487  
    204204    QPlainTextEdit *pCurrentPage = m_pViewer->currentLogPage();
    205205    AssertReturnVoid(pCurrentPage);
    206     const QString& strInputText = m_pViewer->currentLog();
     206    const QString* strInputText = m_pViewer->currentLog();
    207207    m_iUnfilteredLineCount = 0;
    208208    m_iFilteredLineCount = 0;
    209     if (strInputText.isNull())
     209    if (!strInputText || strInputText->isNull())
    210210        return;
    211211    QTextDocument *document = pCurrentPage->document();
    212212    if (!document)
    213213        return;
    214     QStringList stringLines = strInputText.split("\n");
     214    QStringList stringLines = strInputText->split("\n");
    215215    m_iUnfilteredLineCount = stringLines.size();
    216216    if (m_filterTermList.empty())
    217217    {
    218         document->setPlainText(strInputText);
     218        document->setPlainText(*strInputText);
    219219        emit sigFilterApplied();
    220220        m_iFilteredLineCount = document->lineCount();
  • trunk/src/VBox/Frontends/VirtualBox/src/logviewer/UIVMLogViewerWidget.cpp

    r70476 r70487  
    3030# include <QPlainTextEdit>
    3131# include <QScrollBar>
     32# include <QTextBlock>
    3233
    3334/* GUI includes: */
     
    3839# include "UIMessageCenter.h"
    3940# include "UIVMLogViewerWidget.h"
     41# include "UIVMLogViewerBookmarksPanel.h"
    4042# include "UIVMLogViewerFilterPanel.h"
    4143# include "UIVMLogViewerSearchPanel.h"
     
    4850
    4951#endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
     52
    5053
    5154/** We use a modified scrollbar style for our QPlainTextEdits to get the
     
    116119};
    117120
     121/* Sub-class QPlainTextEdit for some addtional context menu items: */
     122class UIVMLogViewerTextEdit : public QPlainTextEdit
     123{
     124    Q_OBJECT;
     125
     126signals:
     127
     128    void sigContextMenuBookmarkAction(LogBookmark bookmark);
     129
     130public:
     131    UIVMLogViewerTextEdit(QWidget* parent = 0, const QString& logFileName = QString())
     132        :QPlainTextEdit(parent),
     133         m_logFileName(logFileName)
     134    {
     135        //setStyleSheet("background-color: rgba(240, 240, 240, 75%) ");
     136    }
     137
     138    const QString& logFileName() const
     139    {
     140        return m_logFileName;
     141    }
     142
     143protected:
     144
     145    void contextMenuEvent(QContextMenuEvent *pEvent)
     146    {
     147        QMenu *menu = createStandardContextMenu();
     148        QAction *pAction = menu->addAction(tr("Bookmark"));
     149        QTextBlock block = cursorForPosition(pEvent->pos()).block();
     150        m_iContextMenuBookmark.first = block.firstLineNumber();
     151        m_iContextMenuBookmark.second = block.text();
     152
     153        if(pAction)
     154            connect(pAction, &QAction::triggered, this, &UIVMLogViewerTextEdit::sltBookmark);
     155
     156        menu->exec(pEvent->globalPos());
     157
     158        if(pAction)
     159            disconnect(pAction, &QAction::triggered, this, &UIVMLogViewerTextEdit::sltBookmark);
     160
     161        delete menu;
     162    }
     163
     164    virtual void mousePressEvent(QMouseEvent *pEvent)
     165    {
     166        QPlainTextEdit::mousePressEvent(pEvent);
     167    }
     168
     169private slots:
     170    /// remove
     171    void sltBookmark()
     172    {
     173        emit sigContextMenuBookmarkAction(m_iContextMenuBookmark);
     174    }
     175
     176private:
     177
     178    /* Line number and text at the context menu position */
     179    LogBookmark m_iContextMenuBookmark;
     180    /* Name of the log file this text edit created to show. */
     181    QString m_logFileName;
     182};
     183
    118184UIVMLogViewerWidget::UIVMLogViewerWidget(EmbedTo enmEmbedding, QWidget *pParent /* = 0 */, const CMachine &machine /* = CMachine() */)
    119185    : QIWithRetranslateUI<QWidget>(pParent)
     
    122188    , m_pViewerContainer(0)
    123189    , m_iCurrentTabIndex(-1)
     190    , m_pSearchPanel(0)
     191    , m_pFilterPanel(0)
     192    , m_pBookmarksPanel(0)
    124193    , m_pMainLayout(0)
    125194    , m_enmEmbedding(enmEmbedding)
     
    129198    , m_pActionRefresh(0)
    130199    , m_pActionSave(0)
     200    , m_pActionBookmark(0)
    131201    , m_pMenu(0)
    132202{
     
    166236}
    167237
    168 void UIVMLogViewerWidget::sltFind()
    169 {
     238void UIVMLogViewerWidget::sltShowHideSearchPanel()
     239{
     240    if(!m_pSearchPanel)
     241        return;
    170242    /* Show/hide search-panel: */
    171243    m_pSearchPanel->isHidden() ? m_pSearchPanel->show() : m_pSearchPanel->hide();
     
    178250    disconnect(m_pViewerContainer, &QITabWidget::currentChanged, this, &UIVMLogViewerWidget::sltTabIndexChange);
    179251
    180     /* Clearing old data if any: */
    181     m_book.clear();
    182252    m_logMap.clear();
    183253    m_pViewerContainer->setEnabled(true);
     
    226296
    227297    /* Apply the filter settings: */
    228     m_pFilterPanel->applyFilter();
     298    if(m_pFilterPanel)
     299        m_pFilterPanel->applyFilter();
    229300
    230301    /* Setup this connection after refresh to avoid initial signals during page creation: */
     
    238309    m_pActionFilter->setEnabled(!noLogsToShow);
    239310    m_pActionSave->setEnabled(!noLogsToShow);
     311    m_pActionBookmark->setEnabled(!noLogsToShow);
    240312    m_pViewerContainer->setEnabled(!noLogsToShow);
    241313    m_pViewerContainer->show();
     
    248320    if (m_comMachine.isNull())
    249321        return;
     322    UIVMLogViewerTextEdit *logPage = qobject_cast<UIVMLogViewerTextEdit*>(currentLogPage());
     323    if(!logPage)
     324        return;
    250325    /* Prepare "save as" dialog: */
    251     const QFileInfo fileInfo(m_book.at(m_pViewerContainer->currentIndex()).first);
     326    const QFileInfo fileInfo(logPage->logFileName());
    252327    /* Prepare default filename: */
    253328    const QDateTime dtInfo = fileInfo.lastModified();
     
    274349}
    275350
    276 void UIVMLogViewerWidget::sltFilter()
    277 {
     351void UIVMLogViewerWidget::sltShowHideFilterPanel()
     352{
     353    if(!m_pFilterPanel)
     354        return;
    278355    /* Show/hide filter-panel: */
    279356    m_pFilterPanel->isHidden() ? m_pFilterPanel->show() : m_pFilterPanel->hide();
     
    305382}
    306383
    307 void UIVMLogViewerWidget::
    308 sltFilterApplied()
     384void UIVMLogViewerWidget::sltFilterApplied()
    309385{
    310386    /* Reapply the search to get highlighting etc. correctly */
    311387    if (m_pSearchPanel && m_pSearchPanel->isVisible())
    312388        m_pSearchPanel->refresh();
     389}
     390
     391void UIVMLogViewerWidget::sltShowHideBookmarkPanel()
     392{
     393    if(!m_pBookmarksPanel)
     394        return;
     395    m_pBookmarksPanel->isHidden() ? m_pBookmarksPanel->show() : m_pBookmarksPanel->hide();
     396}
     397
     398void UIVMLogViewerWidget::sltCreateBookmarkAtCurrent()
     399{
     400    if(!currentLogPage())
     401        return;
     402    QWidget* viewport = currentLogPage()->viewport();
     403    if (!viewport)
     404        return;
     405    QPoint point(0.5 * viewport->width(), 0.5 * viewport->height());
     406    QTextBlock block = currentLogPage()->cursorForPosition(point).block();
     407    LogBookmark bookmark;
     408    bookmark.first = block.firstLineNumber();
     409    bookmark.second = block.text();
     410    sltCreateBookmarkAtLine(bookmark);
     411}
     412
     413void UIVMLogViewerWidget::sltCreateBookmarkAtLine(LogBookmark bookmark)
     414{
     415    QVector<LogBookmark> *pBookmarkVector = currentBookmarkVector();
     416    if(!pBookmarkVector)
     417        return;
     418    pBookmarkVector->push_back(bookmark);
     419    if(m_pBookmarksPanel)
     420    {
     421        m_pBookmarksPanel->update();
     422        m_pBookmarksPanel->setBookmarkIndex(pBookmarkVector->size() - 1);
     423    }
    313424}
    314425
     
    384495                this, &UIVMLogViewerWidget::sltFilterApplied);
    385496    }
     497
     498    m_pBookmarksPanel = new UIVMLogViewerBookmarksPanel(this, this);
     499    AssertPtrReturnVoid(m_pBookmarksPanel);
     500    {
     501        installEventFilter(m_pBookmarksPanel);
     502        m_pBookmarksPanel->hide();
     503        m_pMainLayout->insertWidget(4, m_pBookmarksPanel);
     504    }
    386505}
    387506
     
    393512    {
    394513        m_pActionFind->setShortcut(QKeySequence("Ctrl+F"));
    395         connect(m_pActionFind, &QAction::triggered, this, &UIVMLogViewerWidget::sltFind);
     514        m_pActionFind->setCheckable(true);
     515        connect(m_pActionFind, &QAction::triggered, this, &UIVMLogViewerWidget::sltShowHideSearchPanel);
    396516    }
    397517
     
    401521    {
    402522        m_pActionFilter->setShortcut(QKeySequence("Ctrl+T"));
    403         connect(m_pActionFilter, &QAction::triggered, this, &UIVMLogViewerWidget::sltFilter);
     523        m_pActionFilter->setCheckable(true);
     524        connect(m_pActionFilter, &QAction::triggered, this, &UIVMLogViewerWidget::sltShowHideFilterPanel);
    404525    }
    405526
     
    419540           already assigned to another action in the selector UI: */
    420541        if (m_enmEmbedding == EmbedTo_Dialog)
    421         {
    422542            m_pActionSave->setShortcut(QKeySequence("Ctrl+S"));
    423             connect(m_pActionSave, &QAction::triggered, this, &UIVMLogViewerWidget::sltSave);
    424         }
     543        connect(m_pActionSave, &QAction::triggered, this, &UIVMLogViewerWidget::sltSave);
     544     }
     545
     546    /* Create and configure 'Bookmark' action: */
     547    m_pActionBookmark = new QAction(this);
     548    AssertPtrReturnVoid(m_pActionBookmark);
     549    {
     550        /* tie Ctrl+D to save only if we show this in a dialog since Ctrl+D is
     551           already assigned to another action in the selector UI: */
     552        if (m_enmEmbedding == EmbedTo_Dialog)
     553            m_pActionBookmark->setShortcut(QKeySequence("Ctrl+D"));
     554        m_pActionBookmark->setCheckable(true);
     555        connect(m_pActionBookmark, &QAction::triggered, this, &UIVMLogViewerWidget::sltShowHideBookmarkPanel);
    425556    }
    426557
     
    451582                                                       QString(":/%1_save_disabled_24px.png").arg(strPrefix)));
    452583
    453 
     584    if (m_pActionBookmark)
     585        m_pActionBookmark->setIcon(UIIconPool::iconSet(QString(":/%1_bookmark_24px.png").arg(strPrefix),
     586                                                       QString(":/%1_bookmark_disabled_24px.png").arg(strPrefix)));
    454587}
    455588
     
    476609        if (m_pActionSave)
    477610            m_pToolBar->addAction(m_pActionSave);
     611
     612        if (m_pActionBookmark)
     613            m_pToolBar->addAction(m_pActionBookmark);
    478614
    479615#ifdef VBOX_WS_MAC
     
    505641        if (m_pActionSave)
    506642            m_pMenu->addAction(m_pActionSave);
     643        if (m_pActionBookmark)
     644            m_pMenu->addAction(m_pActionBookmark);
     645
    507646    }
    508647}
     
    545684        m_pActionSave->setToolTip(tr("Save the log"));
    546685        m_pActionSave->setStatusTip(tr("Save the log"));
     686    }
     687
     688    if (m_pActionBookmark)
     689    {
     690        m_pActionBookmark->setText(tr("&Bookmark..."));
     691        m_pActionBookmark->setToolTip(tr("Bookmark the line"));
     692        m_pActionBookmark->setStatusTip(tr("Bookmark the line"));
    547693    }
    548694
     
    616762}
    617763
     764const QString* UIVMLogViewerWidget::currentLog()
     765{
     766    if(!currentLogPage())
     767        return 0;
     768    return &(m_logMap[currentLogPage()]);
     769}
     770
    618771QPlainTextEdit* UIVMLogViewerWidget::currentLogPage() const
    619772{
     
    630783    return 0;
    631784}
     785
     786const QVector<LogBookmark>* UIVMLogViewerWidget::currentBookmarkVector() const
     787{
     788    UIVMLogViewerTextEdit *logPage = qobject_cast<UIVMLogViewerTextEdit*>(currentLogPage());
     789    if(!logPage)
     790        return 0;
     791    QString logFileName = logPage->logFileName();
     792    if(logFileName.isEmpty())
     793        return 0;
     794
     795    return &(m_bookmarkMap[logFileName]);
     796}
     797
     798QVector<LogBookmark>* UIVMLogViewerWidget::currentBookmarkVector()
     799{
     800    UIVMLogViewerTextEdit *logPage = qobject_cast<UIVMLogViewerTextEdit*>(currentLogPage());
     801    if(!logPage)
     802        return 0;
     803    QString logFileName = logPage->logFileName();
     804    if(logFileName.isEmpty())
     805        return 0;
     806
     807    return &(m_bookmarkMap[logFileName]);
     808}
     809
    632810
    633811QPlainTextEdit* UIVMLogViewerWidget::logPage(int pIndex) const
     
    671849            {
    672850                /* Create a log viewer page and append the read text to it: */
    673                 QPlainTextEdit *pLogViewer = createLogPage(QFileInfo(strFileName).fileName());
     851                QPlainTextEdit *pLogViewer = createLogPage(strFileName);
    674852                pLogViewer->setPlainText(strText);
    675853                /* Move the cursor position to end: */
     
    677855                cursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
    678856                pLogViewer->setTextCursor(cursor);
    679                 /* Add the actual file name and the QPlainTextEdit containing the content to a list: */
    680                 m_book << qMakePair(strFileName, pLogViewer);
    681857                /* Add the log-text to the map: */
    682858                m_logMap[pLogViewer] = strText;
     
    688864}
    689865
    690 QPlainTextEdit* UIVMLogViewerWidget::createLogPage(const QString &strName)
     866QPlainTextEdit* UIVMLogViewerWidget::createLogPage(const QString &strFileName)
    691867{
    692868    /* Create page-container: */
     
    698874        AssertPtrReturn(pPageLayout, 0);
    699875        /* Create Log-Viewer: */
    700         QPlainTextEdit *pLogViewer = new QPlainTextEdit(pPageContainer);
     876        UIVMLogViewerTextEdit *pLogViewer = new UIVMLogViewerTextEdit(pPageContainer, strFileName);
     877        connect(pLogViewer, &UIVMLogViewerTextEdit::sigContextMenuBookmarkAction,
     878                this, &UIVMLogViewerWidget::sltCreateBookmarkAtLine);
    701879
    702880        AssertPtrReturn(pLogViewer, 0);
     
    722900        }
    723901        /* Add page-container to viewer-container: */
    724         m_pViewerContainer->addTab(pPageContainer, strName);
     902        m_pViewerContainer->addTab(pPageContainer, QFileInfo(strFileName).fileName());
    725903        return pLogViewer;
    726904    }
    727 }
    728 
    729 const QString& UIVMLogViewerWidget::currentLog()
    730 {
    731     return m_logMap[currentLogPage()];
    732905}
    733906
  • trunk/src/VBox/Frontends/VirtualBox/src/logviewer/UIVMLogViewerWidget.h

    r70308 r70487  
    3737class QVBoxLayout;
    3838class UIToolBar;
     39class UIVMLogViewerBookmarksPanel;
    3940class UIVMLogViewerFilterPanel;
    4041class UIVMLogViewerSearchPanel;
    4142
    4243/* Type definitions: */
    43 typedef QPair<QString, QPlainTextEdit*> LogPage;
    44 typedef QList<LogPage> LogBook;
     44/** value is the content of the log file */
    4545typedef QMap<QPlainTextEdit*, QString> VMLogMap;
     46/** first is line number, second is block text */
     47typedef QPair<int, QString> LogBookmark;
     48/** key is log file name, value is a vector of bookmarks. */
     49typedef QMap<QString, QVector<LogBookmark> > BookmarkMap;
     50
    4651
    4752/** QIMainWindow extension
     
    7883private slots:
    7984
    80     /** Handles search action triggering. */
    81     void sltFind();
    8285    /** Handles refresh action triggering. */
    8386    void sltRefresh();
    8487    /** Handles save action triggering. */
    8588    void sltSave();
    86     /** Handles filter action triggering. */
    87     void sltFilter();
     89
     90    void sltShowHideFilterPanel();
     91    void sltShowHideSearchPanel();
     92    void sltShowHideBookmarkPanel();
    8893
    8994    /** Handles the search result highlight changes. */
    9095    void sltSearchResultHighLigting();
    91 
    9296    /** Handles the tab change of the logviewer. */
    9397    void sltTabIndexChange(int tabIndex);
    94 
    9598    void sltFilterApplied();
     99    /* create a bookmark out of line number and block text. */
     100    void sltCreateBookmarkAtLine(QPair<int, QString> bookmark);
     101    /* Determines the (middle) line number of the visible text and calls sltCreateBookmarkAtLine. */
     102    void sltCreateBookmarkAtCurrent();
     103
    96104
    97105private:
     
    129137    /** Returns the newly created log-page using @a strPage filename. */
    130138    QPlainTextEdit* createLogPage(const QString &strPage);
    131     /** Returns the content of current log-page. */
    132     const QString& currentLog();
     139    /** Returns the content of current log-file as it is read. */
     140    const QString* currentLog();
    133141
    134142    /** Attempts to read the logs through the API, returns true if there exists any logs, false otherwise. */
     
    138146    void resetHighlighthing();
    139147
     148    /** Returns the vector of bookmarks for the current log page */
     149    QVector<LogBookmark>* currentBookmarkVector();
     150    const QVector<LogBookmark>* currentBookmarkVector() const;
     151
    140152    /** Holds whether the dialog is polished. */
    141153    bool m_fIsPolished;
     
    152164    /** Holds the instance of search-panel. */
    153165    UIVMLogViewerSearchPanel *m_pSearchPanel;
    154 
    155     /** Holds the list of log-pages. */
    156     LogBook m_book;
    157 
    158166    /** Holds the instance of filter panel. */
    159167    UIVMLogViewerFilterPanel *m_pFilterPanel;
    160 
    161     /** Holds the list of log-content. */
    162     VMLogMap m_logMap;
     168    UIVMLogViewerBookmarksPanel *m_pBookmarksPanel;
     169
     170    /** Holds the list of log file content. */
     171    VMLogMap             m_logMap;
     172    mutable BookmarkMap  m_bookmarkMap;
    163173
    164174    QVBoxLayout      *m_pMainLayout;
     
    179189        /** Holds the Save action instance. */
    180190        QAction   *m_pActionSave;
     191        /** Holds the Bookmark action instance. */
     192        QAction   *m_pActionBookmark;
     193
    181194        /** Holds the menu object instance. */
    182195        QMenu     *m_pMenu;
    183196    /** @} */
    184197
     198    friend class UIVMLogViewerBookmarksPanel;
     199    friend class UIVMLogViewerFilterPanel;
    185200    friend class UIVMLogViewerSearchPanel;
    186     friend class UIVMLogViewerFilterPanel;
    187201};
    188202
  • trunk/src/VBox/Frontends/VirtualBox/src/medium/UIMediumManager.cpp

    r69821 r70487  
    24682468    return qobject_cast<UIMediumManagerWidget*>(QIManagerDialog::widget());
    24692469}
    2470 
Note: See TracChangeset for help on using the changeset viewer.

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