VirtualBox

Changeset 70539 in vbox for trunk/src/VBox/Frontends


Ignore:
Timestamp:
Jan 11, 2018 2:11:16 PM (7 years ago)
Author:
vboxsync
Message:

FE/Qt: bugref:9072. Refactor UIVMLogViewerWidget class

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

Legend:

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

    r70500 r70539  
    335335        src/hostnetwork/UIHostNetworkDetailsWidget.h \
    336336        src/hostnetwork/UIHostNetworkManager.h \
     337        src/logviewer/UIVMLogPage.h \
    337338        src/logviewer/UIVMLogViewerBookmarksPanel.h \
    338339        src/logviewer/UIVMLogViewerDialog.h \
     
    547548        src/globals/UIMainEventListener.cpp \
    548549        src/globals/UIThreadPool.cpp \
     550        src/logviewer/UIVMLogPage.cpp \
    549551        src/logviewer/UIVMLogViewerFilterPanel.cpp \
    550         src/logviewer/UIVMLogViewerWidget.cpp \
    551552        src/medium/UIMediumEnumerator.cpp \
    552553        src/runtime/UIActionPoolRuntime.cpp \
     
    653654        src/hostnetwork/UIHostNetworkManager.cpp \
    654655        src/hostnetwork/UIHostNetworkUtils.cpp \
     656        src/logviewer/UIVMLogPage.cpp \
    655657        src/logviewer/UIVMLogViewerBookmarksPanel.cpp \
    656658        src/logviewer/UIVMLogViewerDialog.cpp \
  • trunk/src/VBox/Frontends/VirtualBox/src/logviewer/UIVMLogPage.cpp

    r70529 r70539  
    3838# include "UIIconPool.h"
    3939# include "UIMessageCenter.h"
    40 # include "UIVMLogViewerWidget.h"
     40# include "UIVMLogPage.h"
    4141# include "UIVMLogViewerBookmarksPanel.h"
    4242# include "UIVMLogViewerFilterPanel.h"
     
    9595    }
    9696
     97    void clearMarkingsVector()
     98    {
     99        m_markingsVector.clear();
     100    }
     101
    97102protected:
    98103
     
    130135
    131136public:
    132     UIVMLogViewerTextEdit(QWidget* parent = 0, const QString& logFileName = QString())
    133         :QPlainTextEdit(parent),
    134          m_logFileName(logFileName)
     137    UIVMLogViewerTextEdit(QWidget* parent = 0)
     138        :QPlainTextEdit(parent)
    135139    {
    136140        //setStyleSheet("background-color: rgba(240, 240, 240, 75%) ");
    137     }
    138 
    139     const QString& logFileName() const
    140     {
    141         return m_logFileName;
    142141    }
    143142
     
    179178    /* Line number and text at the context menu position */
    180179    LogBookmark m_iContextMenuBookmark;
    181     /* Name of the log file this text edit created to show. */
    182     QString m_logFileName;
    183180};
    184181
    185182
    186 UIVMLogViewerWidget::UIVMLogViewerWidget(EmbedTo enmEmbedding, QWidget *pParent /* = 0 */, const CMachine &machine /* = CMachine() */)
     183UIVMLogPage::UIVMLogPage(QWidget *pParent /* = 0 */, int tabIndex /*= -1 */)
    187184    : QIWithRetranslateUI<QWidget>(pParent)
    188     , m_fIsPolished(false)
    189     , m_comMachine(machine)
    190     , m_pViewerContainer(0)
    191     , m_iCurrentTabIndex(-1)
    192     , m_pSearchPanel(0)
    193     , m_pFilterPanel(0)
    194     , m_pBookmarksPanel(0)
    195185    , m_pMainLayout(0)
    196     , m_enmEmbedding(enmEmbedding)
    197     , m_pToolBar(0)
    198     , m_pActionFind(0)
    199     , m_pActionFilter(0)
    200     , m_pActionRefresh(0)
    201     , m_pActionSave(0)
    202     , m_pActionBookmark(0)
    203     , m_pMenu(0)
    204     , m_bMarkBookmarkLines(0)
    205 {
    206     /* Prepare VM Log-Viewer: */
     186    , m_pPlainTextEdit(0)
     187    , m_tabIndex(tabIndex)
     188{
    207189    prepare();
    208190}
    209191
    210 UIVMLogViewerWidget::~UIVMLogViewerWidget()
    211 {
    212     /* Cleanup VM Log-Viewer: */
     192UIVMLogPage::~UIVMLogPage()
     193{
    213194    cleanup();
    214195}
    215196
    216 int UIVMLogViewerWidget::defaultLogPageWidth() const
    217 {
    218     if (!m_pViewerContainer)
     197int UIVMLogPage::defaultLogPageWidth() const
     198{
     199    if (!m_pPlainTextEdit)
    219200        return 0;
    220201
    221     QWidget *pContainer = m_pViewerContainer->currentWidget();
    222     if (!pContainer)
     202    /* Compute a width for 132 characters plus scrollbar and frame width: */
     203    int iDefaultWidth = m_pPlainTextEdit->fontMetrics().width(QChar('x')) * 132 +
     204                        m_pPlainTextEdit->verticalScrollBar()->width() +
     205                        m_pPlainTextEdit->frameWidth() * 2;
     206
     207    return iDefaultWidth;
     208}
     209
     210
     211void UIVMLogPage::prepare()
     212{
     213    prepareWidgets();
     214//     prepareActions();
     215
     216//     prepareToolBar();
     217//     prepareMenu();
     218
     219//     /* Reading log files: */
     220//     sltRefresh();
     221
     222//     /* Loading language constants: */
     223    retranslateUi();
     224}
     225
     226void UIVMLogPage::prepareWidgets()
     227{
     228    m_pMainLayout = new QHBoxLayout();
     229    setLayout(m_pMainLayout);
     230    m_pMainLayout->setSpacing(0);
     231    m_pMainLayout->setContentsMargins(0, 0, 0, 0);
     232
     233    m_pPlainTextEdit = new UIVMLogViewerTextEdit(this);
     234    m_pMainLayout->addWidget(m_pPlainTextEdit);
     235
     236    m_pPlainTextEdit->setVerticalScrollBar(new UIIndicatorScrollBar());
     237    m_pPlainTextEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
     238    QScrollBar *pHorizontalScrollBar = m_pPlainTextEdit->horizontalScrollBar();
     239    if (pHorizontalScrollBar)
     240        pHorizontalScrollBar->setStyleSheet(horizontalScrollBarStyle);
     241
     242#if defined(RT_OS_SOLARIS)
     243    /* Use system fixed-width font on Solaris hosts as the Courier family fonts don't render well. */
     244    QFont font = QFontDatabase::systemFont(QFontDatabase::FixedFont);
     245#else
     246    QFont font;
     247    font.setFamily("Courier New,courier");
     248#endif
     249    m_pPlainTextEdit->setFont(font);
     250    m_pPlainTextEdit->setWordWrapMode(QTextOption::NoWrap);
     251    m_pPlainTextEdit->setReadOnly(true);
     252
     253}
     254
     255QPlainTextEdit *UIVMLogPage::textEdit()
     256{
     257    return m_pPlainTextEdit;
     258}
     259
     260QTextDocument* UIVMLogPage::document()
     261{
     262    if (!m_pPlainTextEdit)
    223263        return 0;
    224 
    225     QPlainTextEdit *pBrowser = pContainer->findChild<QPlainTextEdit*>();
    226     if (!pBrowser)
    227         return 0;
    228     /* Compute a width for 132 characters plus scrollbar and frame width: */
    229     int iDefaultWidth = pBrowser->fontMetrics().width(QChar('x')) * 132 +
    230                         pBrowser->verticalScrollBar()->width() +
    231                         pBrowser->frameWidth() * 2;
    232 
    233     return iDefaultWidth;
    234 }
    235 
    236 bool UIVMLogViewerWidget::shouldBeMaximized() const
    237 {
    238     return gEDataManager->logWindowShouldBeMaximized();
    239 }
    240 
    241 void UIVMLogViewerWidget::sltDeleteBookmark(int index)
    242 {
    243     QVector<LogBookmark>* bookmarkVector = currentBookmarkVector();
    244     if(!bookmarkVector || bookmarkVector->size() <= index)
     264    return m_pPlainTextEdit->document();
     265}
     266
     267void UIVMLogPage::setTabIndex(int index)
     268{
     269    m_tabIndex = index;
     270}
     271
     272int UIVMLogPage::tabIndex()  const
     273{
     274    return m_tabIndex;
     275}
     276
     277void UIVMLogPage::retranslateUi()
     278{
     279}
     280
     281void UIVMLogPage::cleanup()
     282{
     283}
     284
     285void UIVMLogPage::setLogString(const QString &strLog)
     286{
     287    m_strLog = strLog;
     288}
     289
     290const QString& UIVMLogPage::logString() const
     291{
     292    return m_strLog;
     293}
     294
     295void UIVMLogPage::setFileName(const QString &strFileName)
     296{
     297    m_strFileName = strFileName;
     298}
     299
     300const QString& UIVMLogPage::fileName() const
     301{
     302    return m_strFileName;
     303}
     304
     305void UIVMLogPage::setTextEdit(const QString &strText)
     306{
     307    m_pPlainTextEdit->setPlainText(strText);
     308    /* Move the cursor position to end: */
     309    QTextCursor cursor = m_pPlainTextEdit->textCursor();
     310    cursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
     311    m_pPlainTextEdit->setTextCursor(cursor);
     312    repaint();
     313}
     314
     315void UIVMLogPage::markForError()
     316{
     317    QPalette pal = m_pPlainTextEdit->palette();
     318    pal.setColor(QPalette::Base, pal.color(QPalette::Window));
     319    m_pPlainTextEdit->setPalette(pal);
     320}
     321
     322void UIVMLogPage::setScrollBarMarkingsVector(const QVector<float> &vector)
     323{
     324    if (!m_pPlainTextEdit)
    245325        return;
    246     bookmarkVector->remove(index, 1);
    247     if (m_pBookmarksPanel)
    248         m_pBookmarksPanel->updateBookmarkList(bookmarkVector);
    249 }
    250 
    251 void UIVMLogViewerWidget::sltDeleteAllBookmarks()
    252 {
    253     QVector<LogBookmark>* bookmarkVector = currentBookmarkVector();
    254     if(!bookmarkVector)
     326    UIIndicatorScrollBar* scrollBar = qobject_cast<UIIndicatorScrollBar*>(m_pPlainTextEdit->verticalScrollBar());
     327    if (scrollBar)
     328        scrollBar->setMarkingsVector(vector);
     329    repaint();
     330}
     331
     332void UIVMLogPage::clearScrollBarMarkingsVector()
     333{
     334    if (!m_pPlainTextEdit)
    255335        return;
    256     bookmarkVector->clear();
    257     if (m_pBookmarksPanel)
    258         m_pBookmarksPanel->updateBookmarkList(bookmarkVector);
    259 }
    260 
    261 void UIVMLogViewerWidget::sltBookmarkSelected(int index)
    262 {
    263     QVector<LogBookmark>* bookmarkVector = currentBookmarkVector();
    264     if(!bookmarkVector || index >= bookmarkVector->size())
     336    UIIndicatorScrollBar* scrollBar = qobject_cast<UIIndicatorScrollBar*>(m_pPlainTextEdit->verticalScrollBar());
     337    if (scrollBar)
     338        scrollBar->clearMarkingsVector();
     339    repaint();
     340}
     341
     342void UIVMLogPage::documentUndo()
     343{
     344    if (!m_pPlainTextEdit)
    265345        return;
    266     if(!currentLogPage() || !currentLogPage()->document())
    267         return;
    268 
    269     int lineNumber = bookmarkVector->at(index).first;
    270     QTextCursor cursor(currentLogPage()->document()->findBlockByLineNumber(lineNumber));
    271     currentLogPage()->setTextCursor(cursor);
    272 
    273 }
    274 
    275 void UIVMLogViewerWidget::sltPanelActionTriggered(bool checked)
    276 {
    277     QAction *pSenderAction = qobject_cast<QAction*>(sender());
    278     if (!pSenderAction)
    279         return;
    280     UIVMLogViewerPanel* pPanel = 0;
    281     /* Look for the sender() within the m_panelActionMap's values: */
    282     for (QMap<UIVMLogViewerPanel*, QAction*>::const_iterator iterator = m_panelActionMap.begin();
    283         iterator != m_panelActionMap.end(); ++iterator)
    284     {
    285         if (iterator.value() == pSenderAction)
    286             pPanel = iterator.key();
    287     }
    288     if (!pPanel)
    289         return;
    290     if (checked)
    291         showPanel(pPanel);
    292     else
    293         hidePanel(pPanel);
    294 }
    295 
    296 void UIVMLogViewerWidget::sltRefresh()
    297 {
    298     /* Disconnect this connection to avoid initial signals during page creation/deletion: */
    299     disconnect(m_pViewerContainer, &QITabWidget::currentChanged, m_pFilterPanel, &UIVMLogViewerFilterPanel::applyFilter);
    300     disconnect(m_pViewerContainer, &QITabWidget::currentChanged, this, &UIVMLogViewerWidget::sltTabIndexChange);
    301 
    302     m_logMap.clear();
    303     m_pViewerContainer->setEnabled(true);
    304     /* Hide the container widget during updates to avoid flickering: */
    305     m_pViewerContainer->hide();
    306     while (m_pViewerContainer->count())
    307     {
    308         QWidget *pFirstPage = m_pViewerContainer->widget(0);
    309         m_pViewerContainer->removeTab(0);
    310         delete pFirstPage;
    311     }
    312 
    313     m_iCurrentTabIndex = -1;
    314     bool noLogsToShow = false;
    315     QString strDummyTabText;
    316     /* check if the machine is valid: */
    317     if (m_comMachine.isNull())
    318     {
    319         noLogsToShow = true;
    320         strDummyTabText = QString(tr("<p><b>No machine</b> is currently selected. Please select a "
    321                                      "Virtual Machine to see its logs"));
    322     }
    323     /* If machine is valid and check if there are any log files and create viewer tabs: */
    324     else if (!createLogViewerPages())
    325     {
    326         noLogsToShow = true;
    327         strDummyTabText = QString(tr("<p>No log files found. Press the "
    328                                      "<b>Refresh</b> button to rescan the log folder "
    329                                      "<nobr><b>%1</b></nobr>.</p>")
    330                                      .arg(m_comMachine.GetLogFolder()));
    331     }
    332     /* If the machine is not valid or has no log files show a single viewer tab: */
    333     if (noLogsToShow)
    334     {
    335         QPlainTextEdit *pDummyLog = createLogPage("VBox.log");
    336         pDummyLog->setWordWrapMode(QTextOption::WordWrap);
    337         pDummyLog->appendHtml(strDummyTabText);
    338         /* We don't want it to remain white: */
    339         QPalette pal = pDummyLog->palette();
    340         pal.setColor(QPalette::Base, pal.color(QPalette::Window));
    341         pDummyLog->setPalette(pal);
    342     }
    343 
    344     /* Show the first tab widget's page after the refresh: */
    345     m_pViewerContainer->setCurrentIndex(0);
    346 
    347     /* Apply the filter settings: */
    348     if (m_pFilterPanel)
    349         m_pFilterPanel->applyFilter();
    350 
    351     /* Setup this connection after refresh to avoid initial signals during page creation: */
    352     connect(m_pViewerContainer, &QITabWidget::currentChanged, m_pFilterPanel, &UIVMLogViewerFilterPanel::applyFilter);
    353     connect(m_pViewerContainer, &QITabWidget::currentChanged, this, &UIVMLogViewerWidget::sltTabIndexChange);
    354 
    355     m_iCurrentTabIndex = 0;
    356 
    357     /* Enable/Disable toolbar actions (except Refresh) & tab widget according log presence: */
    358     m_pActionFind->setEnabled(!noLogsToShow);
    359     m_pActionFilter->setEnabled(!noLogsToShow);
    360     m_pActionSave->setEnabled(!noLogsToShow);
    361     m_pActionBookmark->setEnabled(!noLogsToShow);
    362     m_pViewerContainer->setEnabled(!noLogsToShow);
    363     m_pViewerContainer->show();
    364     if (m_pSearchPanel && m_pSearchPanel->isVisible())
    365         m_pSearchPanel->refresh();
    366 }
    367 
    368 void UIVMLogViewerWidget::sltSave()
    369 {
    370     if (m_comMachine.isNull())
    371         return;
    372     UIVMLogViewerTextEdit *logPage = qobject_cast<UIVMLogViewerTextEdit*>(currentLogPage());
    373     if (!logPage)
    374         return;
    375     /* Prepare "save as" dialog: */
    376     const QFileInfo fileInfo(logPage->logFileName());
    377     /* Prepare default filename: */
    378     const QDateTime dtInfo = fileInfo.lastModified();
    379     const QString strDtString = dtInfo.toString("yyyy-MM-dd-hh-mm-ss");
    380     const QString strDefaultFileName = QString("%1-%2.log").arg(m_comMachine.GetName()).arg(strDtString);
    381     const QString strDefaultFullName = QDir::toNativeSeparators(QDir::home().absolutePath() + "/" + strDefaultFileName);
    382 
    383     const QString strNewFileName = QIFileDialog::getSaveFileName(strDefaultFullName,
    384                                                                  "",
    385                                                                  this,
    386                                                                  tr("Save VirtualBox Log As"),
    387                                                                  0 /* selected filter */,
    388                                                                  true /* resolve symlinks */,
    389                                                                  true /* confirm overwrite */);
    390     /* Make sure file-name is not empty: */
    391     if (!strNewFileName.isEmpty())
    392     {
    393         /* Delete the previous file if already exists as user already confirmed: */
    394         if (QFile::exists(strNewFileName))
    395             QFile::remove(strNewFileName);
    396         /* Copy log into the file: */
    397         QFile::copy(m_comMachine.QueryLogFilename(m_pViewerContainer->currentIndex()), strNewFileName);
    398     }
    399 }
    400 
    401 void UIVMLogViewerWidget::sltSearchResultHighLigting()
    402 {
    403     if (!m_pSearchPanel)
    404         return;
    405 
    406     if (!currentLogPage())
    407         return;
    408     UIIndicatorScrollBar* scrollBar = qobject_cast<UIIndicatorScrollBar*>(currentLogPage()->verticalScrollBar());
    409     if (scrollBar)
    410         scrollBar->setMarkingsVector(m_pSearchPanel->getMatchLocationVector());
    411 
    412     currentLogPage()->repaint();
    413 }
    414 
    415 void UIVMLogViewerWidget::sltTabIndexChange(int tabIndex)
    416 {
    417     if (m_iCurrentTabIndex == tabIndex)
    418         return;
    419 
    420     resetHighlighthing();
    421     if (m_pSearchPanel)
    422         m_pSearchPanel->reset();
    423     m_iCurrentTabIndex = tabIndex;
    424     /* We keep a separate QVector<LogBookmark> for each log page: */
    425     QVector<LogBookmark>* bookmarkVector = currentBookmarkVector();
    426     if(bookmarkVector && m_pBookmarksPanel)
    427         m_pBookmarksPanel->updateBookmarkList(bookmarkVector);
    428 }
    429 
    430 void UIVMLogViewerWidget::sltFilterApplied()
    431 {
    432     /* Reapply the search to get highlighting etc. correctly */
    433     if (m_pSearchPanel && m_pSearchPanel->isVisible())
    434         m_pSearchPanel->refresh();
    435 }
    436 
    437 void UIVMLogViewerWidget::sltCreateBookmarkAtCurrent()
    438 {
    439     if (!currentLogPage())
    440         return;
    441     QWidget* viewport = currentLogPage()->viewport();
    442     if (!viewport)
    443         return;
    444     QPoint point(0.5 * viewport->width(), 0.5 * viewport->height());
    445     QTextBlock block = currentLogPage()->cursorForPosition(point).block();
    446     LogBookmark bookmark;
    447     bookmark.first = block.firstLineNumber();
    448     bookmark.second = block.text();
    449     sltCreateBookmarkAtLine(bookmark);
    450 }
    451 
    452 void UIVMLogViewerWidget::sltCreateBookmarkAtLine(LogBookmark bookmark)
    453 {
    454     QVector<LogBookmark> *pBookmarkVector = currentBookmarkVector();
    455     if (!pBookmarkVector)
    456         return;
    457     pBookmarkVector->push_back(bookmark);
    458     if (m_pBookmarksPanel)
    459         m_pBookmarksPanel->updateBookmarkList(pBookmarkVector);
    460 }
    461 
    462 void UIVMLogViewerWidget::setMachine(const CMachine &machine)
    463 {
    464     if (machine == m_comMachine)
    465         return;
    466     m_comMachine = machine;
    467     sltRefresh();
    468 }
    469 
    470 void UIVMLogViewerWidget::prepare()
    471 {
    472     m_pMainLayout = new QVBoxLayout(this);
    473 
    474     /* Prepare widgets: */
    475     prepareWidgets();
    476 
    477 
    478     prepareActions();
    479 
    480     prepareToolBar();
    481     prepareMenu();
    482 
    483     /* Reading log files: */
    484     sltRefresh();
    485 
    486     /* Loading language constants: */
    487     retranslateUi();
    488 
    489     m_panelActionMap.insert(m_pBookmarksPanel, m_pActionBookmark);
    490     m_panelActionMap.insert(m_pSearchPanel, m_pActionFind);
    491     m_panelActionMap.insert(m_pFilterPanel, m_pActionFilter);
    492 }
    493 
    494 void UIVMLogViewerWidget::prepareWidgets()
    495 {
    496     /* Configure layout: */
    497     layout()->setContentsMargins(0, 0, 0, 0);
    498 #ifdef VBOX_WS_MAC
    499         layout()->setSpacing(10);
    500 #else
    501         layout()->setSpacing(qApp->style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing) / 2);
    502 #endif
    503 
    504     /* Create VM Log-Viewer container: */
    505     m_pViewerContainer = new QITabWidget(this);
    506     AssertPtrReturnVoid(m_pViewerContainer);
    507     {
    508         /* Add VM Log-Viewer container to main-layout: */
    509         m_pMainLayout->insertWidget(1, m_pViewerContainer);
    510     }
    511 
    512     /* Create VM Log-Viewer search-panel: */
    513     m_pSearchPanel = new UIVMLogViewerSearchPanel(this, this);
    514     AssertPtrReturnVoid(m_pSearchPanel);
    515     {
    516         /* Configure VM Log-Viewer search-panel: */
    517         installEventFilter(m_pSearchPanel);
    518         m_pSearchPanel->hide();
    519         /* Add VM Log-Viewer search-panel to main-layout: */
    520         m_pMainLayout->insertWidget(2, m_pSearchPanel);
    521         connect(m_pSearchPanel, &UIVMLogViewerSearchPanel::sigHighlightingUpdated,
    522                 this, &UIVMLogViewerWidget::sltSearchResultHighLigting);
    523     }
    524 
    525     /* Create VM Log-Viewer filter-panel: */
    526     m_pFilterPanel = new UIVMLogViewerFilterPanel(this, this);
    527     AssertPtrReturnVoid(m_pFilterPanel);
    528     {
    529         /* Configure VM Log-Viewer filter-panel: */
    530         installEventFilter(m_pFilterPanel);
    531         m_pFilterPanel->hide();
    532         /* Add VM Log-Viewer filter-panel to main-layout: */
    533         m_pMainLayout->insertWidget(3, m_pFilterPanel);
    534         connect(m_pFilterPanel, &UIVMLogViewerFilterPanel::sigFilterApplied,
    535                 this, &UIVMLogViewerWidget::sltFilterApplied);
    536     }
    537 
    538     m_pBookmarksPanel = new UIVMLogViewerBookmarksPanel(this, this);
    539     AssertPtrReturnVoid(m_pBookmarksPanel);
    540     {
    541         installEventFilter(m_pBookmarksPanel);
    542         m_pBookmarksPanel->hide();
    543         m_pMainLayout->insertWidget(4, m_pBookmarksPanel);
    544         connect(m_pBookmarksPanel, &UIVMLogViewerBookmarksPanel::sigDeleteBookmark,
    545                 this, &UIVMLogViewerWidget::sltDeleteBookmark);
    546         connect(m_pBookmarksPanel, &UIVMLogViewerBookmarksPanel::sigDeleteAllBookmarks,
    547                 this, &UIVMLogViewerWidget::sltDeleteAllBookmarks);
    548         connect(m_pBookmarksPanel, &UIVMLogViewerBookmarksPanel::sigBookmarkSelected,
    549                 this, &UIVMLogViewerWidget::sltBookmarkSelected);
    550     }
    551 }
    552 
    553 void UIVMLogViewerWidget::prepareActions()
    554 {
    555     /* Create and configure 'Find' action: */
    556     m_pActionFind = new QAction(this);
    557     AssertPtrReturnVoid(m_pActionFind);
    558     {
    559         m_pActionFind->setShortcut(QKeySequence("Ctrl+F"));
    560         m_pActionFind->setCheckable(true);
    561         connect(m_pActionFind, &QAction::triggered, this, &UIVMLogViewerWidget::sltPanelActionTriggered);
    562     }
    563 
    564     /* Create and configure 'Filter' action: */
    565     m_pActionFilter = new QAction(this);
    566     AssertPtrReturnVoid(m_pActionFilter);
    567     {
    568         m_pActionFilter->setShortcut(QKeySequence("Ctrl+T"));
    569         m_pActionFilter->setCheckable(true);
    570         connect(m_pActionFilter, &QAction::triggered, this, &UIVMLogViewerWidget::sltPanelActionTriggered);
    571     }
    572     /* Create and configure 'Bookmark' action: */
    573     m_pActionBookmark = new QAction(this);
    574     AssertPtrReturnVoid(m_pActionBookmark);
    575     {
    576         /* tie Ctrl+D to save only if we show this in a dialog since Ctrl+D is
    577            already assigned to another action in the selector UI: */
    578         if (m_enmEmbedding == EmbedTo_Dialog)
    579             m_pActionBookmark->setShortcut(QKeySequence("Ctrl+D"));
    580         m_pActionBookmark->setCheckable(true);
    581         connect(m_pActionBookmark, &QAction::triggered, this, &UIVMLogViewerWidget::sltPanelActionTriggered);
    582     }
    583 
    584     /* Create and configure 'Refresh' action: */
    585     m_pActionRefresh = new QAction(this);
    586     AssertPtrReturnVoid(m_pActionRefresh);
    587     {
    588         m_pActionRefresh->setShortcut(QKeySequence("F5"));
    589         connect(m_pActionRefresh, &QAction::triggered, this, &UIVMLogViewerWidget::sltRefresh);
    590     }
    591 
    592     /* Create and configure 'Save' action: */
    593     m_pActionSave = new QAction(this);
    594     AssertPtrReturnVoid(m_pActionSave);
    595     {
    596         /* tie Ctrl+S to save only if we show this in a dialog since Ctrl+S is
    597            already assigned to another action in the selector UI: */
    598         if (m_enmEmbedding == EmbedTo_Dialog)
    599             m_pActionSave->setShortcut(QKeySequence("Ctrl+S"));
    600         connect(m_pActionSave, &QAction::triggered, this, &UIVMLogViewerWidget::sltSave);
    601      }
    602 
    603     /* Update action icons: */
    604     prepareActionIcons();
    605 }
    606 
    607 void UIVMLogViewerWidget::prepareActionIcons()
    608 {
    609     QString strPrefix = "log_viewer";
    610 
    611     if (m_pActionFind)
    612         m_pActionFind->setIcon(UIIconPool::iconSet(QString(":/%1_find_24px.png").arg(strPrefix),
    613                                                        QString(":/%1_find_disabled_24px.png").arg(strPrefix)));
    614 
    615     if (m_pActionFilter)
    616         m_pActionFilter->setIcon(UIIconPool::iconSet(QString(":/%1_filter_24px.png").arg(strPrefix),
    617                                                          QString(":/%1_filter_disabled_24px.png").arg(strPrefix)));
    618 
    619 
    620     if (m_pActionRefresh)
    621         m_pActionRefresh->setIcon(UIIconPool::iconSet(QString(":/%1_refresh_24px.png").arg(strPrefix),
    622                                                           QString(":/%1_refresh_disabled_24px.png").arg(strPrefix)));
    623 
    624 
    625     if (m_pActionSave)
    626         m_pActionSave->setIcon(UIIconPool::iconSet(QString(":/%1_save_24px.png").arg(strPrefix),
    627                                                        QString(":/%1_save_disabled_24px.png").arg(strPrefix)));
    628 
    629     if (m_pActionBookmark)
    630         m_pActionBookmark->setIcon(UIIconPool::iconSet(QString(":/%1_bookmark_24px.png").arg(strPrefix),
    631                                                        QString(":/%1_bookmark_disabled_24px.png").arg(strPrefix)));
    632 }
    633 
    634 void UIVMLogViewerWidget::prepareToolBar()
    635 {
    636     /* Create toolbar: */
    637     m_pToolBar = new UIToolBar(parentWidget());
    638     AssertPtrReturnVoid(m_pToolBar);
    639     {
    640         /* Configure toolbar: */
    641         const int iIconMetric = (int)(QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) * 1.375);
    642         m_pToolBar->setIconSize(QSize(iIconMetric, iIconMetric));
    643         m_pToolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
    644         /* Add toolbar actions: */
    645         if (m_pActionFind)
    646             m_pToolBar->addAction(m_pActionFind);
    647 
    648         if (m_pActionFilter)
    649             m_pToolBar->addAction(m_pActionFilter);
    650 
    651         if (m_pActionRefresh)
    652             m_pToolBar->addAction(m_pActionRefresh);
    653 
    654         if (m_pActionSave)
    655             m_pToolBar->addAction(m_pActionSave);
    656 
    657         if (m_pActionBookmark)
    658             m_pToolBar->addAction(m_pActionBookmark);
    659 
    660 #ifdef VBOX_WS_MAC
    661         /* Check whether we are embedded into a stack: */
    662         if (m_enmEmbedding == EmbedTo_Stack)
    663         {
    664             /* Add into layout: */
    665             layout()->addWidget(m_pToolBar);
    666         }
    667 #else
    668         /* Add into layout: */
    669         m_pMainLayout->insertWidget(0, m_pToolBar);
    670 #endif
    671     }
    672 }
    673 
    674 void UIVMLogViewerWidget::prepareMenu()
    675 {
    676     /* Create 'LogViewer' menu: */
    677     m_pMenu = new QMenu(this);
    678     AssertPtrReturnVoid(m_pMenu);
    679     {
    680         if (m_pActionFind)
    681             m_pMenu->addAction(m_pActionFind);
    682         if (m_pActionFilter)
    683             m_pMenu->addAction(m_pActionFilter);
    684         if (m_pActionRefresh)
    685             m_pMenu->addAction(m_pActionRefresh);
    686         if (m_pActionSave)
    687             m_pMenu->addAction(m_pActionSave);
    688         if (m_pActionBookmark)
    689             m_pMenu->addAction(m_pActionBookmark);
    690 
    691     }
    692 }
    693 
    694 void UIVMLogViewerWidget::cleanup()
    695 {
    696 }
    697 
    698 void UIVMLogViewerWidget::retranslateUi()
    699 {
    700     if (m_pMenu)
    701     {
    702         m_pMenu->setTitle(tr("&Log Viewer"));
    703     }
    704 
    705     if (m_pActionFind)
    706     {
    707         m_pActionFind->setText(tr("&Find"));
    708         m_pActionFind->setToolTip(tr("Find a string within the log"));
    709         m_pActionFind->setStatusTip(tr("Find a string within the log"));
    710     }
    711 
    712     if (m_pActionFilter)
    713     {
    714         m_pActionFilter->setText(tr("&Filter"));
    715         m_pActionFilter->setToolTip(tr("Filter the log wrt. the given string"));
    716         m_pActionFilter->setStatusTip(tr("Filter the log wrt. the given string"));
    717     }
    718 
    719     if (m_pActionRefresh)
    720     {
    721         m_pActionRefresh->setText(tr("&Refresh"));
    722         m_pActionRefresh->setToolTip(tr("Reload the log"));
    723         m_pActionRefresh->setStatusTip(tr("Reload the log"));
    724     }
    725 
    726     if (m_pActionSave)
    727     {
    728         m_pActionSave->setText(tr("&Save..."));
    729         m_pActionSave->setToolTip(tr("Save the log"));
    730         m_pActionSave->setStatusTip(tr("Save the log"));
    731     }
    732 
    733     if (m_pActionBookmark)
    734     {
    735         m_pActionBookmark->setText(tr("&Bookmarks"));
    736         m_pActionBookmark->setToolTip(tr("Bookmark the line"));
    737         m_pActionBookmark->setStatusTip(tr("Bookmark the line"));
    738     }
    739 
    740     /* Translate toolbar: */
    741 #ifdef VBOX_WS_MAC
    742     // WORKAROUND:
    743     // There is a bug in Qt Cocoa which result in showing a "more arrow" when
    744     // the necessary size of the toolbar is increased. Also for some languages
    745     // the with doesn't match if the text increase. So manually adjust the size
    746     // after changing the text. */
    747     if (m_pToolBar)
    748         m_pToolBar->updateLayout();
    749 #endif
    750 }
    751 
    752 void UIVMLogViewerWidget::showEvent(QShowEvent *pEvent)
    753 {
    754     QWidget::showEvent(pEvent);
    755 
    756     /* One may think that QWidget::polish() is the right place to do things
    757      * below, but apparently, by the time when QWidget::polish() is called,
    758      * the widget style & layout are not fully done, at least the minimum
    759      * size hint is not properly calculated. Since this is sometimes necessary,
    760      * we provide our own "polish" implementation: */
    761 
    762     if (m_fIsPolished)
    763         return;
    764 
    765     m_fIsPolished = true;
    766 
    767     /* Make sure the log view widget has the focus: */
    768     QWidget *pCurrentLogPage = currentLogPage();
    769     if (pCurrentLogPage)
    770         pCurrentLogPage->setFocus();
    771 }
    772 
    773 void UIVMLogViewerWidget::keyPressEvent(QKeyEvent *pEvent)
    774 {
    775     /* Depending on key pressed: */
    776     switch (pEvent->key())
    777     {
    778         /* Process key escape as VM Log Viewer close: */
    779         case Qt::Key_Escape:
    780         {
    781             return;
    782         }
    783         /* Process Back key as switch to previous tab: */
    784         case Qt::Key_Back:
    785         {
    786             if (m_pViewerContainer->currentIndex() > 0)
    787             {
    788                 m_pViewerContainer->setCurrentIndex(m_pViewerContainer->currentIndex() - 1);
    789                 return;
    790             }
    791             break;
    792         }
    793         /* Process Forward key as switch to next tab: */
    794         case Qt::Key_Forward:
    795         {
    796             if (m_pViewerContainer->currentIndex() < m_pViewerContainer->count())
    797             {
    798                 m_pViewerContainer->setCurrentIndex(m_pViewerContainer->currentIndex() + 1);
    799                 return;
    800             }
    801             break;
    802         }
    803         default:
    804             break;
    805     }
    806     QWidget::keyReleaseEvent(pEvent);
    807 }
    808 
    809 const QString* UIVMLogViewerWidget::currentLog()
    810 {
    811     if (!currentLogPage())
    812         return 0;
    813     return &(m_logMap[currentLogPage()]);
    814 }
    815 
    816 QPlainTextEdit* UIVMLogViewerWidget::currentLogPage() const
    817 {
    818     /* If viewer-container is enabled: */
    819     if (m_pViewerContainer->isEnabled())
    820     {
    821         /* Get and return current log-page: */
    822         QWidget *pContainer = m_pViewerContainer->currentWidget();
    823         QPlainTextEdit *pBrowser = pContainer->findChild<QPlainTextEdit*>();
    824         Assert(pBrowser);
    825         return pBrowser ? pBrowser : 0;
    826     }
    827     /* Return NULL by default: */
    828     return 0;
    829 }
    830 
    831 const QVector<LogBookmark>* UIVMLogViewerWidget::currentBookmarkVector() const
    832 {
    833     UIVMLogViewerTextEdit *logPage = qobject_cast<UIVMLogViewerTextEdit*>(currentLogPage());
    834     if (!logPage)
    835         return 0;
    836     QString logFileName = logPage->logFileName();
    837     if (logFileName.isEmpty())
    838         return 0;
    839 
    840     return &(m_bookmarkMap[logFileName]);
    841 }
    842 
    843 QVector<LogBookmark>* UIVMLogViewerWidget::currentBookmarkVector()
    844 {
    845     UIVMLogViewerTextEdit *logPage = qobject_cast<UIVMLogViewerTextEdit*>(currentLogPage());
    846     if (!logPage)
    847         return 0;
    848     QString logFileName = logPage->logFileName();
    849     if (logFileName.isEmpty())
    850         return 0;
    851 
    852     return &(m_bookmarkMap[logFileName]);
    853 }
    854 
    855 void UIVMLogViewerWidget::hidePanel(UIVMLogViewerPanel* panel)
    856 {
    857     if (panel && panel->isVisible())
    858         panel->setVisible(false);
    859     QMap<UIVMLogViewerPanel*, QAction*>::iterator iterator = m_panelActionMap.find(panel);
    860     if (iterator != m_panelActionMap.end())
    861     {
    862         if (iterator.value()->isChecked())
    863             iterator.value()->setChecked(false);
    864     }
    865 }
    866 
    867 void UIVMLogViewerWidget::showPanel(UIVMLogViewerPanel* panel)
    868 {
    869     if (panel && panel->isHidden())
    870         panel->setVisible(true);
    871     QMap<UIVMLogViewerPanel*, QAction*>::iterator iterator = m_panelActionMap.find(panel);
    872     if (iterator != m_panelActionMap.end())
    873     {
    874         if (!iterator.value()->isChecked())
    875             iterator.value()->setChecked(true);
    876     }
    877 }
    878 
    879 QPlainTextEdit* UIVMLogViewerWidget::logPage(int pIndex) const
    880 {
    881     if (!m_pViewerContainer->isEnabled())
    882         return 0;
    883     QWidget* pContainer = m_pViewerContainer->widget(pIndex);
    884     if (!pContainer)
    885         return 0;
    886     QPlainTextEdit *pBrowser = pContainer->findChild<QPlainTextEdit*>();
    887     return pBrowser;
    888 }
    889 
    890 bool UIVMLogViewerWidget::createLogViewerPages()
    891 {
    892     if (m_comMachine.isNull())
    893         return false;
    894 
    895     bool logsExists = false;
    896     const CSystemProperties &sys = vboxGlobal().virtualBox().GetSystemProperties();
    897     unsigned cMaxLogs = sys.GetLogHistoryCount() + 1 /*VBox.log*/ + 1 /*VBoxHardening.log*/; /** @todo Add api for getting total possible log count! */
    898     for (unsigned i = 0; i < cMaxLogs; ++i)
    899     {
    900         /* Query the log file name for index i: */
    901         QString strFileName = m_comMachine.QueryLogFilename(i);
    902         if (!strFileName.isEmpty())
    903         {
    904             /* Try to read the log file with the index i: */
    905             ULONG uOffset = 0;
    906             QString strText;
    907             while (true)
    908             {
    909                 QVector<BYTE> data = m_comMachine.ReadLog(i, uOffset, _1M);
    910                 if (data.size() == 0)
    911                     break;
    912                 strText.append(QString::fromUtf8((char*)data.data(), data.size()));
    913                 uOffset += data.size();
    914             }
    915             /* Anything read at all? */
    916             if (uOffset > 0)
    917             {
    918                 /* Create a log viewer page and append the read text to it: */
    919                 QPlainTextEdit *pLogViewer = createLogPage(strFileName);
    920                 pLogViewer->setPlainText(strText);
    921                 /* Move the cursor position to end: */
    922                 QTextCursor cursor = pLogViewer->textCursor();
    923                 cursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
    924                 pLogViewer->setTextCursor(cursor);
    925                 /* Add the log-text to the map: */
    926                 m_logMap[pLogViewer] = strText;
    927                 logsExists = true;
    928             }
    929         }
    930     }
    931     return logsExists;
    932 }
    933 
    934 QPlainTextEdit* UIVMLogViewerWidget::createLogPage(const QString &strFileName)
    935 {
    936     /* Create page-container: */
    937     QWidget *pPageContainer = new QWidget;
    938     AssertPtrReturn(pPageContainer, 0);
    939     {
    940         /* Create page-layout: */
    941         QVBoxLayout *pPageLayout = new QVBoxLayout(pPageContainer);
    942         AssertPtrReturn(pPageLayout, 0);
    943         /* Create Log-Viewer: */
    944         UIVMLogViewerTextEdit *pLogViewer = new UIVMLogViewerTextEdit(pPageContainer, strFileName);
    945         connect(pLogViewer, &UIVMLogViewerTextEdit::sigContextMenuBookmarkAction,
    946                 this, &UIVMLogViewerWidget::sltCreateBookmarkAtLine);
    947 
    948         AssertPtrReturn(pLogViewer, 0);
    949         {
    950             /* Configure Log-Viewer: */
    951             pLogViewer->setVerticalScrollBar(new UIIndicatorScrollBar());
    952             pLogViewer->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
    953             QScrollBar *pHorizontalScrollBar = pLogViewer->horizontalScrollBar();
    954             if (pHorizontalScrollBar)
    955                 pHorizontalScrollBar->setStyleSheet(horizontalScrollBarStyle);
    956 #if defined(RT_OS_SOLARIS)
    957             /* Use system fixed-width font on Solaris hosts as the Courier family fonts don't render well. */
    958             QFont font = QFontDatabase::systemFont(QFontDatabase::FixedFont);
    959 #else
    960             QFont font;
    961             font.setFamily("Courier New,courier");
    962 #endif
    963             pLogViewer->setFont(font);
    964             pLogViewer->setWordWrapMode(QTextOption::NoWrap);
    965             pLogViewer->setReadOnly(true);
    966             /* Add Log-Viewer to page-layout: */
    967             pPageLayout->addWidget(pLogViewer);
    968         }
    969         /* Add page-container to viewer-container: */
    970         m_pViewerContainer->addTab(pPageContainer, QFileInfo(strFileName).fileName());
    971         return pLogViewer;
    972     }
    973 }
    974 
    975 void UIVMLogViewerWidget::resetHighlighthing()
    976 {
    977     /* Undo the document changes to remove highlighting: */
    978     QPlainTextEdit *pTextEdit = logPage(m_iCurrentTabIndex);
    979     if (pTextEdit)
    980     {
    981         QTextDocument *pDocument = pTextEdit->document();
    982         if (pDocument)
    983             pDocument->undo();
    984     }
    985     UIIndicatorScrollBar* scrollBar = qobject_cast<UIIndicatorScrollBar*>(pTextEdit->verticalScrollBar());
    986     if (scrollBar)
    987     {
    988         scrollBar->setMarkingsVector(QVector<float>());
    989         pTextEdit->repaint();
    990     }
    991 }
    992 
    993 #include "UIVMLogViewerWidget.moc"
     346    if (m_pPlainTextEdit->document())
     347        m_pPlainTextEdit->document()->undo();
     348}
     349
     350#include "UIVMLogPage.moc"
  • trunk/src/VBox/Frontends/VirtualBox/src/logviewer/UIVMLogPage.h

    r70529 r70539  
    1616 */
    1717
    18 #ifndef ___UIVMLogViewerWidget_h___
    19 #define ___UIVMLogViewerWidget_h___
     18#ifndef ___UIVMLogPage_h___
     19#define ___UIVMLogPage_h___
    2020
    2121/* Qt includes: */
     
    3535class QITabWidget;
    3636class QPlainTextEdit;
    37 class QVBoxLayout;
     37class QHBoxLayout;
    3838class UIToolBar;
    3939class UIVMLogViewerBookmarksPanel;
     
    4343
    4444/* Type definitions: */
    45 /** value is the content of the log file */
    46 typedef QMap<QPlainTextEdit*, QString> VMLogMap;
    4745/** first is line number, second is block text */
    4846typedef QPair<int, QString> LogBookmark;
    49 /** key is log file name, value is a vector of bookmarks. */
    50 typedef QMap<QString, QVector<LogBookmark> > BookmarkMap;
    5147
    52 
    53 /** QIMainWindow extension
    54   * providing GUI with VirtualBox LogViewer. */
    55 class UIVMLogViewerWidget  : public QIWithRetranslateUI<QWidget>
     48class UIVMLogPage  : public QIWithRetranslateUI<QWidget>
    5649{
    5750    Q_OBJECT;
    5851
    5952public:
    60     /** Constructs the VM Log-Viewer by passing @a pParent to QWidget base-class constructor.
    61       * @param  machine  Specifies the machine for which VM Log-Viewer is requested. */
    62     UIVMLogViewerWidget(EmbedTo enmEmbedding, QWidget *pParent = 0, const CMachine &machine = CMachine());
     53
     54    UIVMLogPage(QWidget *pParent = 0, int tabIndex = -1);
    6355    /** Destructs the VM Log-Viewer. */
    64     ~UIVMLogViewerWidget();
     56    ~UIVMLogPage();
    6557    /** Returns the width of the current log page. return 0 if there is no current log page: */
    6658    int defaultLogPageWidth() const;
    6759
    68     /** Returns the menu. */
    69     QMenu *menu() const { return m_pMenu; }
     60    QPlainTextEdit *textEdit();
     61    QTextDocument  *document();
    7062
    71 #ifdef VBOX_WS_MAC
    72     /** Returns the toolbar. */
    73     UIToolBar *toolbar() const { return m_pToolBar; }
    74 #endif
     63    void setTabIndex(int index);
     64    int tabIndex()  const;
    7565
    76     /** Sets the machine whose logs to show. */
    77     void setMachine(const CMachine &machine);
     66    /* Only to be called when log file is re-read. */
     67    void setLogString(const QString &strLog);
     68    const QString& logString() const;
     69
     70    void setFileName(const QString &strFileName);
     71    const QString& fileName() const;
     72
     73    /** Ses plaintextEdit's text. Note that the text we
     74        show currently might be different than
     75        m_strLog. For example during filtering. */
     76    void setTextEdit(const QString &strText);
     77
     78    /* Marks the plain text edit When we dont have a log content. */
     79    void markForError();
     80
     81    void setScrollBarMarkingsVector(const QVector<float> &vector);
     82    void clearScrollBarMarkingsVector();
     83
     84    /* Undos the changes done to textDocument */
     85    void documentUndo();
    7886
    7987protected:
    8088
    81     /** Returns whether the window should be maximized when geometry being restored. */
    82     virtual bool shouldBeMaximized() const /* override */;
    83 
    8489private slots:
    8590
    86     /** Handles refresh action triggering. */
    87     void sltRefresh();
    88     /** Handles save action triggering. */
    89     void sltSave();
    90 
    91     /** @name Bookmark related slots
    92      * @{ */
    93     /** Deletes the bookmark with @p index from the current logs bookmark list. */
    94         void sltDeleteBookmark(int index);
    95         void sltDeleteAllBookmarks();
    96         /** Scroll the plain text edit to the selected bookmark. */
    97         void sltBookmarkSelected(int index);
    98         /** Creates a bookmark out of line number and block text. */
    99         void sltCreateBookmarkAtLine(QPair<int, QString> bookmark);
    100         /** Determines the (middle) line number of the visible text and calls sltCreateBookmarkAtLine. */
    101         void sltCreateBookmarkAtCurrent();
    102     /** @} */
    103 
    104     void sltPanelActionTriggered(bool checked);
    105     /** Handles the search result highlight changes. */
    106     void sltSearchResultHighLigting();
    107     /** Handles the tab change of the logviewer. */
    108     void sltTabIndexChange(int tabIndex);
    109     void sltFilterApplied();
    11091
    11192private:
     93    void prepare();
     94    void prepareWidgets();
     95    void cleanup();
     96    void retranslateUi();
    11297
    113     /** @name Prepare/Cleanup
    114       * @{ */
    115         /** Prepares VM Log-Viewer. */
    116         void prepare();
    117         /** Prepares widgets. */
    118         void prepareWidgets();
    119         void prepareActions();
    120         void prepareActionIcons();
    121         void prepareToolBar();
    122         void prepareMenu();
     98    QHBoxLayout    *m_pMainLayout;
     99    QPlainTextEdit *m_pPlainTextEdit;
     100    /** Stores the log file (unmodified) content. */
     101    QString         m_strLog;
     102    /** Stores full path and name of the log file. */
     103    QString         m_strFileName;
     104    /** This is the index of the tab containing this widget in UIVMLogViewerWidget. */
     105    int             m_tabIndex;
    123106
    124         /** Cleanups VM Log-Viewer. */
    125         void cleanup();
    126     /** @} */
     107    QVector<LogBookmark> m_bookmarkMap;
    127108
    128     /** @name Event handling stuff.
    129       * @{ */
    130         /** Handles translation event. */
    131         void retranslateUi();
    132 
    133         /** Handles Qt show @a pEvent. */
    134         void showEvent(QShowEvent *pEvent);
    135         /** Handles Qt key-press @a pEvent. */
    136         void keyPressEvent(QKeyEvent *pEvent);
    137     /** @} */
    138 
    139     /** Returns the current log-page. */
    140     QPlainTextEdit* currentLogPage() const;
    141     /** Returns the log-page from the tab with index @a pIndex. */
    142     QPlainTextEdit* logPage(int pIndex) const;
    143     /** Returns the newly created log-page using @a strPage filename. */
    144     QPlainTextEdit* createLogPage(const QString &strPage);
    145     /** Returns the content of current log-file as it is read. */
    146     const QString* currentLog();
    147 
    148     /** Attempts to read the logs through the API, returns true if there exists any logs, false otherwise. */
    149     bool createLogViewerPages();
    150 
    151     /** Resets document (of the curent tab) and scrollbar highligthing */
    152     void resetHighlighthing();
    153 
    154     /** Returns the vector of bookmarks for the current log page */
    155     QVector<LogBookmark>* currentBookmarkVector();
    156     const QVector<LogBookmark>* currentBookmarkVector() const;
    157 
    158     void hidePanel(UIVMLogViewerPanel* panel);
    159     void showPanel(UIVMLogViewerPanel* panel);
    160 
    161     /** Holds whether the dialog is polished. */
    162     bool m_fIsPolished;
    163 
    164     /** Holds the machine instance. */
    165     CMachine m_comMachine;
    166 
    167     /** Holds container for log-pages. */
    168     QITabWidget *m_pViewerContainer;
    169 
    170     /** Holds the index to the current tab: */
    171     int          m_iCurrentTabIndex;
    172 
    173     /** Holds the instance of search-panel. */
    174     UIVMLogViewerSearchPanel    *m_pSearchPanel;
    175     /** Holds the instance of filter panel. */
    176     UIVMLogViewerFilterPanel    *m_pFilterPanel;
    177     UIVMLogViewerBookmarksPanel *m_pBookmarksPanel;
    178     QMap<UIVMLogViewerPanel*, QAction*> m_panelActionMap;
    179 
    180     /** Holds the list of log file content. */
    181     VMLogMap             m_logMap;
    182     mutable BookmarkMap  m_bookmarkMap;
    183     QVBoxLayout         *m_pMainLayout;
    184 
    185     /** Holds the widget's embedding type. */
    186     const EmbedTo m_enmEmbedding;
    187 
    188     /** @name Toolbar and menu variables.
    189       * @{ */
    190         /** Holds the toolbar widget instance. */
    191         UIToolBar *m_pToolBar;
    192         /** Holds the Find action instance. */
    193         QAction   *m_pActionFind;
    194         /** Holds the Filter action instance. */
    195         QAction   *m_pActionFilter;
    196         /** Holds the Refresh action instance. */
    197         QAction   *m_pActionRefresh;
    198         /** Holds the Save action instance. */
    199         QAction   *m_pActionSave;
    200         /** Holds the Bookmark action instance. */
    201         QAction   *m_pActionBookmark;
    202         /** Holds the menu object instance. */
    203         QMenu     *m_pMenu;
    204     /** @} */
    205     const bool     m_bMarkBookmarkLines;
    206     friend class UIVMLogViewerBookmarksPanel;
    207     friend class UIVMLogViewerFilterPanel;
    208     friend class UIVMLogViewerSearchPanel;
    209     friend class UIVMLogViewerPanel;
    210109};
    211110
    212 #endif /* !___UIVMLogViewerWidget_h___ */
     111#endif /* !___UIVMLogPage_h___ */
  • trunk/src/VBox/Frontends/VirtualBox/src/logviewer/UIVMLogViewerFilterPanel.cpp

    r70500 r70539  
    199199void UIVMLogViewerFilterPanel::filter()
    200200{
    201     QPlainTextEdit *pCurrentPage = viewer()->currentLogPage();
    202     AssertReturnVoid(pCurrentPage);
    203     const QString* strInputText = viewer()->currentLog();
     201    if (!viewer())
     202        return;
     203    QPlainTextEdit *pCurrentTextEdit = textEdit();
     204    if (!pCurrentTextEdit)
     205        return;
     206    const QString* originalLogString = logString();
    204207    m_iUnfilteredLineCount = 0;
    205208    m_iFilteredLineCount = 0;
    206     if (!strInputText || strInputText->isNull())
    207         return;
    208     QTextDocument *document = pCurrentPage->document();
     209    if (!originalLogString || originalLogString->isNull())
     210        return;
     211    QTextDocument *document = textDocument();
    209212    if (!document)
    210213        return;
    211     QStringList stringLines = strInputText->split("\n");
     214    QStringList stringLines = originalLogString->split("\n");
    212215    m_iUnfilteredLineCount = stringLines.size();
    213216    if (m_filterTermList.empty())
    214217    {
    215         document->setPlainText(*strInputText);
     218        document->setPlainText(*originalLogString);
    216219        emit sigFilterApplied();
    217220        m_iFilteredLineCount = document->lineCount();
     
    238241
    239242    /* Move the cursor position to end: */
    240     QTextCursor cursor = pCurrentPage->textCursor();
     243    QTextCursor cursor = pCurrentTextEdit->textCursor();
    241244    cursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
    242     pCurrentPage->setTextCursor(cursor);
     245    pCurrentTextEdit->setTextCursor(cursor);
    243246
    244247    emit sigFilterApplied();
     
    452455                pKeyEvent->key() == Qt::Key_T)
    453456            {
    454                 if (viewer()->currentLogPage())
    455                 {
    456                     if (isHidden())
    457                         show();
    458                     m_pFilterComboBox->setFocus();
    459                     return true;
    460                 }
     457                if (isHidden())
     458                    show();
     459                m_pFilterComboBox->setFocus();
     460                return true;
    461461            }
    462462            else if (pKeyEvent->key() == Qt::Key_Return && m_pFilterComboBox && m_pFilterComboBox->hasFocus())
  • trunk/src/VBox/Frontends/VirtualBox/src/logviewer/UIVMLogViewerPanel.cpp

    r70529 r70539  
    2323# include <QComboBox>
    2424# include <QHBoxLayout>
    25 # if defined(RT_OS_SOLARIS)
    26 #  include <QFontDatabase>
    27 # endif
    2825# include <QLabel>
    29 # include <QLineEdit>
    3026# include <QPlainTextEdit>
    31 # include <QPushButton>
    3227# include <QTextCursor>
    3328# include <QToolButton>
    34 # include <QScrollArea>
    3529
    3630/* GUI includes: */
    3731# include "UIIconPool.h"
    3832# include "UISpecialControls.h"
     33# include "UIVMLogPage.h"
    3934# include "UIVMLogViewerPanel.h"
    4035# include "UIVMLogViewerWidget.h"
     
    125120    QWidget::hideEvent(pEvent);
    126121}
     122
     123QTextDocument  *UIVMLogViewerPanel::textDocument()
     124{
     125    QPlainTextEdit *pEdit = textEdit();
     126    if (!pEdit)
     127        return 0;
     128    return textEdit()->document();
     129}
     130
     131QPlainTextEdit *UIVMLogViewerPanel::textEdit()
     132{
     133    if (!viewer())
     134        return 0;
     135    UIVMLogPage *logPage = viewer()->currentLogPage();
     136    if (!logPage)
     137        return 0;
     138    return logPage->textEdit();
     139}
     140
     141const QString* UIVMLogViewerPanel::logString() const
     142{
     143    if (!viewer())
     144        return 0;
     145    const UIVMLogPage* const page = qobject_cast<const UIVMLogPage* const>(viewer()->currentLogPage());
     146    if (!page)
     147        return 0;
     148    return &(page->logString());
     149}
  • trunk/src/VBox/Frontends/VirtualBox/src/logviewer/UIVMLogViewerPanel.h

    r70519 r70539  
    2626
    2727/* Forward declarations: */
    28 class QComboBox;
    2928class QHBoxLayout;
    30 class QLabel;
    31 class QLineEdit;
    32 class QPushButton;
    33 class UIVMFilterLineEdit;
     29class QPlainTextEdit;
     30class QTextDocument;
    3431class UIMiniCancelButton;
    3532class UIVMLogViewerWidget;
     
    6966    void hideEvent(QHideEvent *pEvent);
    7067
     68    QTextDocument  *textDocument();
     69    QPlainTextEdit *textEdit();
     70    /* Return the unmodified log. */
     71    const QString* logString() const;
    7172private slots:
    7273
  • trunk/src/VBox/Frontends/VirtualBox/src/logviewer/UIVMLogViewerSearchPanel.cpp

    r70519 r70539  
    3535# include "UIIconPool.h"
    3636# include "UISpecialControls.h"
     37# include "UIVMLogPage.h"
    3738# include "UIVMLogViewerSearchPanel.h"
    3839# include "UIVMLogViewerWidget.h"
     
    121122        search(BackwardSearch, true);
    122123        emit sigHighlightingUpdated();
     124        return;
    123125    }
    124126    /* If search-string is empty, reset cursor position: */
    125     else
    126     {
    127         if (viewer())
    128         {
    129             /* Get current log-page: */
    130             QPlainTextEdit *pBrowser = viewer()->currentLogPage();
    131             /* If current log-page is valid and cursor has selection: */
    132             if (pBrowser && pBrowser->textCursor().hasSelection())
    133             {
    134                 /* Get cursor and reset position: */
    135                 QTextCursor cursor = pBrowser->textCursor();
    136                 cursor.setPosition(cursor.anchor());
    137                 pBrowser->setTextCursor(cursor);
    138             }
    139             m_iSearchPosition = -1;
    140             clearHighlighting(-1);
    141         }
    142     }
     127    if (!viewer())
     128        return;
     129
     130    QPlainTextEdit *pBrowser = textEdit();
     131    if (!pBrowser)
     132        return;
     133    /* If  cursor has selection: */
     134    if (pBrowser->textCursor().hasSelection())
     135    {
     136        /* Get cursor and reset position: */
     137        QTextCursor cursor = pBrowser->textCursor();
     138        cursor.setPosition(cursor.anchor());
     139        pBrowser->setTextCursor(cursor);
     140    }
     141    m_iSearchPosition = -1;
     142    clearHighlighting(-1);
    143143}
    144144
     
    147147    if (!viewer())
    148148        return;
    149     QPlainTextEdit *pTextEdit = viewer()->currentLogPage();
    150     if (!pTextEdit)
    151         return;
    152     QTextDocument *pDocument = pTextEdit->document();
     149
     150    QTextDocument *pDocument = textDocument();
    153151    if (!pDocument)
    154152        return;
     
    410408                     pKeyEvent->key() == Qt::Key_F)
    411409            {
    412                 if (viewer() && viewer()->currentLogPage())
    413                 {
    414                     /* Make sure current log-page is visible: */
    415                     if (isHidden())
    416                         show();
    417                     /* Set focus on search-editor: */
    418                     m_pSearchEditor->setFocus();
    419                     return true;
    420                 }
     410                /* Make sure current log-page is visible: */
     411                if (isHidden())
     412                    show();
     413                /* Set focus on search-editor: */
     414                m_pSearchEditor->setFocus();
     415                return true;
    421416            }
    422417            /* Handle alpha-numeric keys to implement the "find as you type" feature: */
     
    425420            {
    426421                /* Make sure current log-page is visible: */
    427                 if (viewer() && viewer()->currentLogPage())
    428                 {
    429                     if (isHidden())
    430                         show();
    431                     /* Set focus on search-editor: */
    432                     m_pSearchEditor->setFocus();
    433                     /* Insert the text to search-editor, which triggers the search-operation for new text: */
    434                     m_pSearchEditor->insert(pKeyEvent->text());
    435                     return true;
    436                 }
     422                if (isHidden())
     423                    show();
     424                /* Set focus on search-editor: */
     425                m_pSearchEditor->setFocus();
     426                /* Insert the text to search-editor, which triggers the search-operation for new text: */
     427                m_pSearchEditor->insert(pKeyEvent->text());
     428                return true;
    437429            }
    438430            break;
     
    457449void UIVMLogViewerSearchPanel::search(SearchDirection direction, bool highlight)
    458450{
    459     if (!viewer())
    460         return;
    461     QPlainTextEdit *pTextEdit = viewer()->currentLogPage();
    462     if (!pTextEdit) return;
    463     QTextDocument *pDocument = pTextEdit->document();
     451    QPlainTextEdit *pTextEdit = textEdit();
     452    if (!pTextEdit)
     453        return;
     454    QTextDocument *pDocument = textDocument();
    464455    if (!pDocument)
    465456        return;
     
    541532    m_matchLocationVector.clear();
    542533
    543     QPlainTextEdit *pBrowser = viewer()->currentLogPage();
    544     if (pBrowser)
    545     {
    546         QTextDocument* pDocument = pBrowser->document();
    547         if (pDocument)
    548             pDocument->undo();
    549     }
     534    QTextDocument* pDocument = textDocument();
     535    if (pDocument)
     536        pDocument->undo();
     537
    550538    configureInfoLabels();
    551539    emit sigHighlightingUpdated();
  • trunk/src/VBox/Frontends/VirtualBox/src/logviewer/UIVMLogViewerSearchPanel.h

    r70500 r70539  
    107107    QTextDocument::FindFlags constructFindFlags(SearchDirection eDirection);
    108108
     109
    109110    /** Holds the instance of search-label we create. */
    110111    QLabel *m_pSearchLabel;
  • trunk/src/VBox/Frontends/VirtualBox/src/logviewer/UIVMLogViewerWidget.cpp

    r70529 r70539  
    3838# include "UIIconPool.h"
    3939# include "UIMessageCenter.h"
     40# include "UIVMLogPage.h"
    4041# include "UIVMLogViewerWidget.h"
    4142# include "UIVMLogViewerBookmarksPanel.h"
     
    5253
    5354
    54 /** We use a modified scrollbar style for our QPlainTextEdits to get the
    55     markings on the scrollbars correctly. The default scrollbarstyle does not
    56     reveal the height of the pushbuttons on the scrollbar (on either side of it, with arrow on them)
    57     to compute the marking locations correctly. Thus we turn these push buttons off: */
    58 const QString verticalScrollBarStyle("QScrollBar:vertical {"
    59                                      "border: 1px ridge grey; "
    60                                      "margin: 0px 0px 0 0px;}"
    61                                      "QScrollBar::handle:vertical {"
    62                                      "min-height: 10px;"
    63                                      "background: grey;}"
    64                                      "QScrollBar::add-line:vertical {"
    65                                      "width: 0px;}"
    66                                      "QScrollBar::sub-line:vertical {"
    67                                      "width: 0px;}");
    68 
    69 const QString horizontalScrollBarStyle("QScrollBar:horizontal {"
    70                                        "border: 1px ridge grey; "
    71                                        "margin: 0px 0px 0 0px;}"
    72                                        "QScrollBar::handle:horizontal {"
    73                                        "min-height: 10px;"
    74                                        "background: grey;}"
    75                                        "QScrollBar::add-line:horizontal {"
    76                                        "height: 0px;}"
    77                                        "QScrollBar::sub-line:horizontal {"
    78                                        "height: 0px;}");
    79 
    80 class UIIndicatorScrollBar : public QScrollBar
    81 {
    82     Q_OBJECT;
    83 
    84 public:
    85 
    86     UIIndicatorScrollBar(QWidget *parent = 0)
    87         :QScrollBar(parent)
    88     {
    89         setStyleSheet(verticalScrollBarStyle);
    90     }
    91 
    92     void setMarkingsVector(const QVector<float> &vector)
    93     {
    94         m_markingsVector = vector;
    95     }
    96 
    97 protected:
    98 
    99     virtual void paintEvent(QPaintEvent *pEvent) /* override */
    100     {
    101         QScrollBar::paintEvent(pEvent);
    102         /* Put a red line to marking position: */
    103         for (int i = 0; i < m_markingsVector.size(); ++i)
    104         {
    105             QPointF p1 = QPointF(0, m_markingsVector[i] * height());
    106             QPointF p2 = QPointF(width(), m_markingsVector[i] * height());
    107 
    108             QPainter painter(this);
    109             painter.setRenderHint(QPainter::Antialiasing, true);
    110             painter.setPen(QPen(QColor(255, 0, 0, 75), 1.1f));
    111             painter.drawLine(p1, p2);
    112         }
    113     }
    114 
    115 private:
    116 
    117     /* Stores the relative (to scrollbar's height) positions of markings,
    118        where we draw a horizontal line. Values are in [0.0, 1.0]*/
    119     QVector<float> m_markingsVector;
    120 };
    121 
    122 /* Sub-class QPlainTextEdit for some addtional context menu items: */
    123 class UIVMLogViewerTextEdit : public QPlainTextEdit
    124 {
    125     Q_OBJECT;
    126 
    127 signals:
    128 
    129     void sigContextMenuBookmarkAction(LogBookmark bookmark);
    130 
    131 public:
    132     UIVMLogViewerTextEdit(QWidget* parent = 0, const QString& logFileName = QString())
    133         :QPlainTextEdit(parent),
    134          m_logFileName(logFileName)
    135     {
    136         //setStyleSheet("background-color: rgba(240, 240, 240, 75%) ");
    137     }
    138 
    139     const QString& logFileName() const
    140     {
    141         return m_logFileName;
    142     }
    143 
    144 protected:
    145 
    146     void contextMenuEvent(QContextMenuEvent *pEvent)
    147     {
    148         QMenu *menu = createStandardContextMenu();
    149         QAction *pAction = menu->addAction(tr("Bookmark"));
    150         QTextBlock block = cursorForPosition(pEvent->pos()).block();
    151         m_iContextMenuBookmark.first = block.firstLineNumber();
    152         m_iContextMenuBookmark.second = block.text();
    153 
    154         if (pAction)
    155             connect(pAction, &QAction::triggered, this, &UIVMLogViewerTextEdit::sltBookmark);
    156 
    157         menu->exec(pEvent->globalPos());
    158 
    159         if (pAction)
    160             disconnect(pAction, &QAction::triggered, this, &UIVMLogViewerTextEdit::sltBookmark);
    161 
    162         delete menu;
    163     }
    164 
    165     virtual void mousePressEvent(QMouseEvent *pEvent)
    166     {
    167         QPlainTextEdit::mousePressEvent(pEvent);
    168     }
    169 
    170 private slots:
    171     /// remove
    172     void sltBookmark()
    173     {
    174         emit sigContextMenuBookmarkAction(m_iContextMenuBookmark);
    175     }
    176 
    177 private:
    178 
    179     /* Line number and text at the context menu position */
    180     LogBookmark m_iContextMenuBookmark;
    181     /* Name of the log file this text edit created to show. */
    182     QString m_logFileName;
    183 };
    184 
    185 
    18655UIVMLogViewerWidget::UIVMLogViewerWidget(EmbedTo enmEmbedding, QWidget *pParent /* = 0 */, const CMachine &machine /* = CMachine() */)
    18756    : QIWithRetranslateUI<QWidget>(pParent)
    18857    , m_fIsPolished(false)
    18958    , m_comMachine(machine)
    190     , m_pViewerContainer(0)
    191     , m_iCurrentTabIndex(-1)
     59    , m_pTabWidget(0)
    19260    , m_pSearchPanel(0)
    19361    , m_pFilterPanel(0)
     
    21684int UIVMLogViewerWidget::defaultLogPageWidth() const
    21785{
    218     if (!m_pViewerContainer)
     86    if (!m_pTabWidget)
    21987        return 0;
    22088
    221     QWidget *pContainer = m_pViewerContainer->currentWidget();
     89    QWidget *pContainer = m_pTabWidget->currentWidget();
    22290    if (!pContainer)
    22391        return 0;
     
    239107}
    240108
    241 void UIVMLogViewerWidget::sltDeleteBookmark(int index)
    242 {
    243     QVector<LogBookmark>* bookmarkVector = currentBookmarkVector();
    244     if(!bookmarkVector || bookmarkVector->size() <= index)
    245         return;
    246     bookmarkVector->remove(index, 1);
    247     if (m_pBookmarksPanel)
    248         m_pBookmarksPanel->updateBookmarkList(bookmarkVector);
     109void UIVMLogViewerWidget::sltDeleteBookmark(int /*index*/)
     110{
     111    // QVector<LogBookmark>* bookmarkVector = currentBookmarkVector();
     112    // if (!bookmarkVector || bookmarkVector->size() <= index)
     113    //     return;
     114    // bookmarkVector->remove(index, 1);
     115    // if (m_pBookmarksPanel)
     116    //     m_pBookmarksPanel->updateBookmarkList(bookmarkVector);
    249117}
    250118
    251119void UIVMLogViewerWidget::sltDeleteAllBookmarks()
    252120{
    253     QVector<LogBookmark>* bookmarkVector = currentBookmarkVector();
    254     if(!bookmarkVector)
    255         return;
    256     bookmarkVector->clear();
    257     if (m_pBookmarksPanel)
    258         m_pBookmarksPanel->updateBookmarkList(bookmarkVector);
    259 }
    260 
    261 void UIVMLogViewerWidget::sltBookmarkSelected(int index)
    262 {
    263     QVector<LogBookmark>* bookmarkVector = currentBookmarkVector();
    264     if(!bookmarkVector || index >= bookmarkVector->size())
    265         return;
    266     if(!currentLogPage() || !currentLogPage()->document())
    267         return;
    268 
    269     int lineNumber = bookmarkVector->at(index).first;
    270     QTextCursor cursor(currentLogPage()->document()->findBlockByLineNumber(lineNumber));
    271     currentLogPage()->setTextCursor(cursor);
     121    // QVector<LogBookmark>* bookmarkVector = currentBookmarkVector();
     122    // if (!bookmarkVector)
     123    //     return;
     124    // bookmarkVector->clear();
     125    // if (m_pBookmarksPanel)
     126    //     m_pBookmarksPanel->updateBookmarkList(bookmarkVector);
     127}
     128
     129void UIVMLogViewerWidget::sltBookmarkSelected(int /*index*/)
     130{
     131    // QVector<LogBookmark>* bookmarkVector = currentBookmarkVector();
     132    // if (!bookmarkVector || index >= bookmarkVector->size())
     133    //     return;
     134    // if (!currentLogPage() || !currentLogPage()->document())
     135    //     return;
     136
     137    // int lineNumber = bookmarkVector->at(index).first;
     138    // QTextCursor cursor(currentLogPage()->document()->findBlockByLineNumber(lineNumber));
     139    // currentLogPage()->setTextCursor(cursor);
    272140
    273141}
     
    297165{
    298166    /* Disconnect this connection to avoid initial signals during page creation/deletion: */
    299     disconnect(m_pViewerContainer, &QITabWidget::currentChanged, m_pFilterPanel, &UIVMLogViewerFilterPanel::applyFilter);
    300     disconnect(m_pViewerContainer, &QITabWidget::currentChanged, this, &UIVMLogViewerWidget::sltTabIndexChange);
    301 
    302     m_logMap.clear();
    303     m_pViewerContainer->setEnabled(true);
     167    disconnect(m_pTabWidget, &QITabWidget::currentChanged, m_pFilterPanel, &UIVMLogViewerFilterPanel::applyFilter);
     168    disconnect(m_pTabWidget, &QITabWidget::currentChanged, this, &UIVMLogViewerWidget::sltTabIndexChange);
     169
     170    // m_logMap.clear();
     171    m_logPageList.clear();
     172    m_pTabWidget->setEnabled(true);
    304173    /* Hide the container widget during updates to avoid flickering: */
    305     m_pViewerContainer->hide();
    306     while (m_pViewerContainer->count())
    307     {
    308         QWidget *pFirstPage = m_pViewerContainer->widget(0);
    309         m_pViewerContainer->removeTab(0);
     174    m_pTabWidget->hide();
     175    /* Clear the tab widget. This might be an overkill but most secure way to deal with the case where
     176       number of the log files changes. */
     177    while (m_pTabWidget->count())
     178    {
     179        QWidget *pFirstPage = m_pTabWidget->widget(0);
     180        m_pTabWidget->removeTab(0);
    310181        delete pFirstPage;
    311182    }
    312183
    313     m_iCurrentTabIndex = -1;
    314     bool noLogsToShow = false;
    315     QString strDummyTabText;
    316     /* check if the machine is valid: */
    317     if (m_comMachine.isNull())
    318     {
    319         noLogsToShow = true;
    320         strDummyTabText = QString(tr("<p><b>No machine</b> is currently selected. Please select a "
    321                                      "Virtual Machine to see its logs"));
    322     }
    323     /* If machine is valid and check if there are any log files and create viewer tabs: */
    324     else if (!createLogViewerPages())
    325     {
    326         noLogsToShow = true;
    327         strDummyTabText = QString(tr("<p>No log files found. Press the "
    328                                      "<b>Refresh</b> button to rescan the log folder "
    329                                      "<nobr><b>%1</b></nobr>.</p>")
    330                                      .arg(m_comMachine.GetLogFolder()));
    331     }
    332     /* If the machine is not valid or has no log files show a single viewer tab: */
    333     if (noLogsToShow)
    334     {
    335         QPlainTextEdit *pDummyLog = createLogPage("VBox.log");
    336         pDummyLog->setWordWrapMode(QTextOption::WordWrap);
    337         pDummyLog->appendHtml(strDummyTabText);
    338         /* We don't want it to remain white: */
    339         QPalette pal = pDummyLog->palette();
    340         pal.setColor(QPalette::Base, pal.color(QPalette::Window));
    341         pDummyLog->setPalette(pal);
    342     }
     184    bool noLogsToShow = createLogViewerPages();
    343185
    344186    /* Show the first tab widget's page after the refresh: */
    345     m_pViewerContainer->setCurrentIndex(0);
     187    m_pTabWidget->setCurrentIndex(0);
    346188
    347189    /* Apply the filter settings: */
     
    350192
    351193    /* Setup this connection after refresh to avoid initial signals during page creation: */
    352     connect(m_pViewerContainer, &QITabWidget::currentChanged, m_pFilterPanel, &UIVMLogViewerFilterPanel::applyFilter);
    353     connect(m_pViewerContainer, &QITabWidget::currentChanged, this, &UIVMLogViewerWidget::sltTabIndexChange);
    354 
    355     m_iCurrentTabIndex = 0;
     194    connect(m_pTabWidget, &QITabWidget::currentChanged, m_pFilterPanel, &UIVMLogViewerFilterPanel::applyFilter);
     195    connect(m_pTabWidget, &QITabWidget::currentChanged, this, &UIVMLogViewerWidget::sltTabIndexChange);
    356196
    357197    /* Enable/Disable toolbar actions (except Refresh) & tab widget according log presence: */
     
    360200    m_pActionSave->setEnabled(!noLogsToShow);
    361201    m_pActionBookmark->setEnabled(!noLogsToShow);
    362     m_pViewerContainer->setEnabled(!noLogsToShow);
    363     m_pViewerContainer->show();
     202    m_pTabWidget->setEnabled(!noLogsToShow);
     203    m_pTabWidget->show();
    364204    if (m_pSearchPanel && m_pSearchPanel->isVisible())
    365205        m_pSearchPanel->refresh();
     
    370210    if (m_comMachine.isNull())
    371211        return;
    372     UIVMLogViewerTextEdit *logPage = qobject_cast<UIVMLogViewerTextEdit*>(currentLogPage());
     212
     213    UIVMLogPage *logPage = currentLogPage();
    373214    if (!logPage)
    374215        return;
     216
     217    const QString& fileName = logPage->fileName();
     218    if (fileName.isEmpty())
     219        return;
    375220    /* Prepare "save as" dialog: */
    376     const QFileInfo fileInfo(logPage->logFileName());
     221    const QFileInfo fileInfo(fileName);
    377222    /* Prepare default filename: */
    378223    const QDateTime dtInfo = fileInfo.lastModified();
     
    395240            QFile::remove(strNewFileName);
    396241        /* Copy log into the file: */
    397         QFile::copy(m_comMachine.QueryLogFilename(m_pViewerContainer->currentIndex()), strNewFileName);
     242        QFile::copy(m_comMachine.QueryLogFilename(m_pTabWidget->currentIndex()), strNewFileName);
    398243    }
    399244}
     
    406251    if (!currentLogPage())
    407252        return;
    408     UIIndicatorScrollBar* scrollBar = qobject_cast<UIIndicatorScrollBar*>(currentLogPage()->verticalScrollBar());
    409     if (scrollBar)
    410         scrollBar->setMarkingsVector(m_pSearchPanel->getMatchLocationVector());
    411 
    412     currentLogPage()->repaint();
     253    currentLogPage()->setScrollBarMarkingsVector(m_pSearchPanel->getMatchLocationVector());
    413254}
    414255
    415256void UIVMLogViewerWidget::sltTabIndexChange(int tabIndex)
    416257{
    417     if (m_iCurrentTabIndex == tabIndex)
    418         return;
     258    // if (m_iCurrentTabIndex == tabIndex)
     259    //     return;
    419260
    420261    resetHighlighthing();
    421     if (m_pSearchPanel)
    422         m_pSearchPanel->reset();
    423     m_iCurrentTabIndex = tabIndex;
     262    // if (m_pSearchPanel)
     263    //     m_pSearchPanel->reset();
     264    // m_iCurrentTabIndex = tabIndex;
    424265    /* We keep a separate QVector<LogBookmark> for each log page: */
    425     QVector<LogBookmark>* bookmarkVector = currentBookmarkVector();
    426     if(bookmarkVector && m_pBookmarksPanel)
    427         m_pBookmarksPanel->updateBookmarkList(bookmarkVector);
     266    // QVector<LogBookmark>* bookmarkVector = currentBookmarkVector();
     267    // if (bookmarkVector && m_pBookmarksPanel)
     268    //     m_pBookmarksPanel->updateBookmarkList(bookmarkVector);
    428269}
    429270
     
    437278void UIVMLogViewerWidget::sltCreateBookmarkAtCurrent()
    438279{
    439     if (!currentLogPage())
    440         return;
    441     QWidget* viewport = currentLogPage()->viewport();
    442     if (!viewport)
    443         return;
    444     QPoint point(0.5 * viewport->width(), 0.5 * viewport->height());
    445     QTextBlock block = currentLogPage()->cursorForPosition(point).block();
    446     LogBookmark bookmark;
    447     bookmark.first = block.firstLineNumber();
    448     bookmark.second = block.text();
    449     sltCreateBookmarkAtLine(bookmark);
     280    // if (!currentTextEdit())
     281    //     return;
     282    // QWidget* viewport = currentTextEdit()->viewport();
     283    // if (!viewport)
     284    //     return;
     285    // QPoint point(0.5 * viewport->width(), 0.5 * viewport->height());
     286    // QTextBlock block = currentTextEdit()->cursorForPosition(point).block();
     287    // LogBookmark bookmark;
     288    // bookmark.first = block.firstLineNumber();
     289    // bookmark.second = block.text();
     290    // sltCreateBookmarkAtLine(bookmark);
    450291}
    451292
    452293void UIVMLogViewerWidget::sltCreateBookmarkAtLine(LogBookmark bookmark)
    453294{
    454     QVector<LogBookmark> *pBookmarkVector = currentBookmarkVector();
    455     if (!pBookmarkVector)
    456         return;
    457     pBookmarkVector->push_back(bookmark);
    458     if (m_pBookmarksPanel)
    459         m_pBookmarksPanel->updateBookmarkList(pBookmarkVector);
     295    // QVector<LogBookmark> *pBookmarkVector = currentBookmarkVector();
     296    // if (!pBookmarkVector)
     297    //     return;
     298    // pBookmarkVector->push_back(bookmark);
     299    // if (m_pBookmarksPanel)
     300    //     m_pBookmarksPanel->updateBookmarkList(pBookmarkVector);
    460301}
    461302
     
    503344
    504345    /* Create VM Log-Viewer container: */
    505     m_pViewerContainer = new QITabWidget(this);
    506     AssertPtrReturnVoid(m_pViewerContainer);
     346    m_pTabWidget = new QITabWidget(this);
     347    AssertPtrReturnVoid(m_pTabWidget);
    507348    {
    508349        /* Add VM Log-Viewer container to main-layout: */
    509         m_pMainLayout->insertWidget(1, m_pViewerContainer);
     350        m_pMainLayout->insertWidget(1, m_pTabWidget);
    510351    }
    511352
     
    766607
    767608    /* Make sure the log view widget has the focus: */
    768     QWidget *pCurrentLogPage = currentLogPage();
    769     if (pCurrentLogPage)
    770         pCurrentLogPage->setFocus();
     609    // QWidget *pCurrentLogPage = currentTextEdit();
     610    // if (pCurrentLogPage)
     611    //     pCurrentLogPage->setFocus();
    771612}
    772613
     
    784625        case Qt::Key_Back:
    785626        {
    786             if (m_pViewerContainer->currentIndex() > 0)
     627            if (m_pTabWidget->currentIndex() > 0)
    787628            {
    788                 m_pViewerContainer->setCurrentIndex(m_pViewerContainer->currentIndex() - 1);
     629                m_pTabWidget->setCurrentIndex(m_pTabWidget->currentIndex() - 1);
    789630                return;
    790631            }
     
    794635        case Qt::Key_Forward:
    795636        {
    796             if (m_pViewerContainer->currentIndex() < m_pViewerContainer->count())
     637            if (m_pTabWidget->currentIndex() < m_pTabWidget->count())
    797638            {
    798                 m_pViewerContainer->setCurrentIndex(m_pViewerContainer->currentIndex() + 1);
     639                m_pTabWidget->setCurrentIndex(m_pTabWidget->currentIndex() + 1);
    799640                return;
    800641            }
     
    807648}
    808649
    809 const QString* UIVMLogViewerWidget::currentLog()
    810 {
    811     if (!currentLogPage())
     650const UIVMLogPage *UIVMLogViewerWidget::currentLogPage() const
     651{
     652    int currentTabIndex = m_pTabWidget->currentIndex();
     653    if (currentTabIndex >= m_logPageList.size())
    812654        return 0;
    813     return &(m_logMap[currentLogPage()]);
    814 }
    815 
    816 QPlainTextEdit* UIVMLogViewerWidget::currentLogPage() const
    817 {
    818     /* If viewer-container is enabled: */
    819     if (m_pViewerContainer->isEnabled())
    820     {
    821         /* Get and return current log-page: */
    822         QWidget *pContainer = m_pViewerContainer->currentWidget();
    823         QPlainTextEdit *pBrowser = pContainer->findChild<QPlainTextEdit*>();
    824         Assert(pBrowser);
    825         return pBrowser ? pBrowser : 0;
    826     }
    827     /* Return NULL by default: */
    828     return 0;
    829 }
    830 
    831 const QVector<LogBookmark>* UIVMLogViewerWidget::currentBookmarkVector() const
    832 {
    833     UIVMLogViewerTextEdit *logPage = qobject_cast<UIVMLogViewerTextEdit*>(currentLogPage());
    834     if (!logPage)
     655    return qobject_cast<const UIVMLogPage*>(m_logPageList.at(currentTabIndex));
     656}
     657UIVMLogPage *UIVMLogViewerWidget::currentLogPage()
     658{
     659    int currentTabIndex = m_pTabWidget->currentIndex();
     660    if (currentTabIndex >= m_logPageList.size())
    835661        return 0;
    836     QString logFileName = logPage->logFileName();
    837     if (logFileName.isEmpty())
    838         return 0;
    839 
    840     return &(m_bookmarkMap[logFileName]);
    841 }
    842 
    843 QVector<LogBookmark>* UIVMLogViewerWidget::currentBookmarkVector()
    844 {
    845     UIVMLogViewerTextEdit *logPage = qobject_cast<UIVMLogViewerTextEdit*>(currentLogPage());
    846     if (!logPage)
    847         return 0;
    848     QString logFileName = logPage->logFileName();
    849     if (logFileName.isEmpty())
    850         return 0;
    851 
    852     return &(m_bookmarkMap[logFileName]);
    853 }
     662    return qobject_cast<UIVMLogPage*>(m_logPageList.at(currentTabIndex));
     663}
     664
     665// const QVector<LogBookmark>* UIVMLogViewerWidget::currentBookmarkVector() const
     666// {
     667//     UIVMLogViewerTextEdit *logPage = qobject_cast<UIVMLogViewerTextEdit*>(currentLogPage());
     668//     if (!logPage)
     669//         return 0;
     670//     QString logFileName = logPage->logFileName();
     671//     if (logFileName.isEmpty())
     672//         return 0;
     673
     674//     return &(m_bookmarkMap[logFileName]);
     675// }
     676
     677// QVector<LogBookmark>* UIVMLogViewerWidget::currentBookmarkVector()
     678// {
     679//     UIVMLogViewerTextEdit *logPage = qobject_cast<UIVMLogViewerTextEdit*>(currentLogPage());
     680//     if (!logPage)
     681//         return 0;
     682//     QString logFileName = logPage->logFileName();
     683//     if (logFileName.isEmpty())
     684//         return 0;
     685
     686//     return &(m_bookmarkMap[logFileName]);
     687// }
    854688
    855689void UIVMLogViewerWidget::hidePanel(UIVMLogViewerPanel* panel)
     
    879713QPlainTextEdit* UIVMLogViewerWidget::logPage(int pIndex) const
    880714{
    881     if (!m_pViewerContainer->isEnabled())
     715    if (!m_pTabWidget->isEnabled())
    882716        return 0;
    883     QWidget* pContainer = m_pViewerContainer->widget(pIndex);
     717    QWidget* pContainer = m_pTabWidget->widget(pIndex);
    884718    if (!pContainer)
    885719        return 0;
     
    890724bool UIVMLogViewerWidget::createLogViewerPages()
    891725{
     726    bool noLogsToShow = false;
     727
     728    QString strDummyTabText;
     729    /* check if the machine is valid: */
    892730    if (m_comMachine.isNull())
    893         return false;
    894 
    895     bool logsExists = false;
     731    {
     732        noLogsToShow = true;
     733        strDummyTabText = QString(tr("<p><b>No machine</b> is currently selected. Please select a "
     734                                     "Virtual Machine to see its logs"));
     735    }
     736
    896737    const CSystemProperties &sys = vboxGlobal().virtualBox().GetSystemProperties();
    897738    unsigned cMaxLogs = sys.GetLogHistoryCount() + 1 /*VBox.log*/ + 1 /*VBoxHardening.log*/; /** @todo Add api for getting total possible log count! */
    898     for (unsigned i = 0; i < cMaxLogs; ++i)
    899     {
    900         /* Query the log file name for index i: */
    901         QString strFileName = m_comMachine.QueryLogFilename(i);
    902         if (!strFileName.isEmpty())
     739
     740    /* If machine is valid then check if there are any log files and create viewer tabs: */
     741    if (cMaxLogs == 0)
     742    {
     743        noLogsToShow = true;
     744        strDummyTabText = QString(tr("<p>No log files found. Press the "
     745                                     "<b>Refresh</b> button to rescan the log folder "
     746                                     "<nobr><b>%1</b></nobr>.</p>")
     747                                     .arg(m_comMachine.GetLogFolder()));
     748    }
     749    else{
     750        for (unsigned i = 0; i < cMaxLogs; ++i)
    903751        {
    904             /* Try to read the log file with the index i: */
    905             ULONG uOffset = 0;
    906             QString strText;
    907             while (true)
     752            /* Query the log file name for index i: */
     753            QString strFileName = m_comMachine.QueryLogFilename(i);
     754            if (!strFileName.isEmpty())
    908755            {
    909                 QVector<BYTE> data = m_comMachine.ReadLog(i, uOffset, _1M);
    910                 if (data.size() == 0)
    911                     break;
    912                 strText.append(QString::fromUtf8((char*)data.data(), data.size()));
    913                 uOffset += data.size();
    914             }
    915             /* Anything read at all? */
    916             if (uOffset > 0)
    917             {
    918                 /* Create a log viewer page and append the read text to it: */
    919                 QPlainTextEdit *pLogViewer = createLogPage(strFileName);
    920                 pLogViewer->setPlainText(strText);
    921                 /* Move the cursor position to end: */
    922                 QTextCursor cursor = pLogViewer->textCursor();
    923                 cursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
    924                 pLogViewer->setTextCursor(cursor);
    925                 /* Add the log-text to the map: */
    926                 m_logMap[pLogViewer] = strText;
    927                 logsExists = true;
     756                /* Try to read the log file with the index i: */
     757                ULONG uOffset = 0;
     758                QString strText;
     759                while (true)
     760                {
     761                    QVector<BYTE> data = m_comMachine.ReadLog(i, uOffset, _1M);
     762                    if (data.size() == 0)
     763                        break;
     764                    strText.append(QString::fromUtf8((char*)data.data(), data.size()));
     765                    uOffset += data.size();
     766                }
     767                /* Anything read at all? */
     768                if (uOffset > 0)
     769                {
     770                    createLogPage(strFileName, strText);
     771                }
    928772            }
    929773        }
    930774    }
    931     return logsExists;
    932 }
    933 
    934 QPlainTextEdit* UIVMLogViewerWidget::createLogPage(const QString &strFileName)
    935 {
     775    /* if noLogsToShow then ceate a single log page with an error message: */
     776    if (noLogsToShow)
     777    {
     778        createLogPage("No Logs", strDummyTabText, noLogsToShow);
     779    }
     780    return noLogsToShow;
     781}
     782
     783void UIVMLogViewerWidget::createLogPage(const QString &strFileName, const QString &strLogContent, bool noLogsToShow /* = false */)
     784{
     785    AssertPtrReturnVoid(m_pTabWidget);
     786
    936787    /* Create page-container: */
    937     QWidget *pPageContainer = new QWidget;
    938     AssertPtrReturn(pPageContainer, 0);
    939     {
    940         /* Create page-layout: */
    941         QVBoxLayout *pPageLayout = new QVBoxLayout(pPageContainer);
    942         AssertPtrReturn(pPageLayout, 0);
    943         /* Create Log-Viewer: */
    944         UIVMLogViewerTextEdit *pLogViewer = new UIVMLogViewerTextEdit(pPageContainer, strFileName);
    945         connect(pLogViewer, &UIVMLogViewerTextEdit::sigContextMenuBookmarkAction,
    946                 this, &UIVMLogViewerWidget::sltCreateBookmarkAtLine);
    947 
    948         AssertPtrReturn(pLogViewer, 0);
    949         {
    950             /* Configure Log-Viewer: */
    951             pLogViewer->setVerticalScrollBar(new UIIndicatorScrollBar());
    952             pLogViewer->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
    953             QScrollBar *pHorizontalScrollBar = pLogViewer->horizontalScrollBar();
    954             if (pHorizontalScrollBar)
    955                 pHorizontalScrollBar->setStyleSheet(horizontalScrollBarStyle);
    956 #if defined(RT_OS_SOLARIS)
    957             /* Use system fixed-width font on Solaris hosts as the Courier family fonts don't render well. */
    958             QFont font = QFontDatabase::systemFont(QFontDatabase::FixedFont);
    959 #else
    960             QFont font;
    961             font.setFamily("Courier New,courier");
    962 #endif
    963             pLogViewer->setFont(font);
    964             pLogViewer->setWordWrapMode(QTextOption::NoWrap);
    965             pLogViewer->setReadOnly(true);
    966             /* Add Log-Viewer to page-layout: */
    967             pPageLayout->addWidget(pLogViewer);
    968         }
    969         /* Add page-container to viewer-container: */
    970         m_pViewerContainer->addTab(pPageContainer, QFileInfo(strFileName).fileName());
    971         return pLogViewer;
    972     }
     788    UIVMLogPage* pLogPage = new UIVMLogPage(this);
     789    AssertPtrReturnVoid(pLogPage);
     790    /* Set the file name only if we really have log file to read. */
     791    if (!noLogsToShow)
     792        pLogPage->setFileName(strFileName);
     793
     794    /* Add page-container to viewer-container: */
     795    int tabIndex = m_pTabWidget->insertTab(m_pTabWidget->count(), pLogPage, QFileInfo(strFileName).fileName());
     796
     797    pLogPage->setTabIndex(tabIndex);
     798    m_logPageList.resize(m_pTabWidget->count());
     799    m_logPageList[tabIndex] = pLogPage;
     800
     801    /* Set the log string of the UIVMLogPage: */
     802    pLogPage->setLogString(strLogContent);
     803    /* Also set text edit since we want to display this text: */
     804    pLogPage->setTextEdit(strLogContent);
     805    if (noLogsToShow)
     806        pLogPage->markForError();
    973807}
    974808
     
    976810{
    977811    /* Undo the document changes to remove highlighting: */
    978     QPlainTextEdit *pTextEdit = logPage(m_iCurrentTabIndex);
    979     if (pTextEdit)
    980     {
    981         QTextDocument *pDocument = pTextEdit->document();
    982         if (pDocument)
    983             pDocument->undo();
    984     }
    985     UIIndicatorScrollBar* scrollBar = qobject_cast<UIIndicatorScrollBar*>(pTextEdit->verticalScrollBar());
    986     if (scrollBar)
    987     {
    988         scrollBar->setMarkingsVector(QVector<float>());
    989         pTextEdit->repaint();
    990     }
    991 }
    992 
    993 #include "UIVMLogViewerWidget.moc"
     812    UIVMLogPage* logPage = currentLogPage();
     813    if (!logPage)
     814        return;
     815    logPage->documentUndo();
     816    logPage->clearScrollBarMarkingsVector();
     817    // QPlainTextEdit *pTextEdit = logPage(m_iCurrentTabIndex);
     818    // if (pTextEdit)
     819    // {
     820    //     QTextDocument *pDocument = pTextEdit->document();
     821    //     if (pDocument)
     822    //         pDocument->undo();
     823    // }
     824    // UIIndicatorScrollBar* scrollBar = qobject_cast<UIIndicatorScrollBar*>(pTextEdit->verticalScrollBar());
     825    // if (scrollBar)
     826    // {
     827    //     scrollBar->setMarkingsVector(QVector<float>());
     828    //     pTextEdit->repaint();
     829    // }
     830}
  • trunk/src/VBox/Frontends/VirtualBox/src/logviewer/UIVMLogViewerWidget.h

    r70529 r70539  
    3737class QVBoxLayout;
    3838class UIToolBar;
     39class UIVMLogPage;
    3940class UIVMLogViewerBookmarksPanel;
    4041class UIVMLogViewerFilterPanel;
     
    4445/* Type definitions: */
    4546/** value is the content of the log file */
    46 typedef QMap<QPlainTextEdit*, QString> VMLogMap;
     47//typedef QMap<QPlainTextEdit*, QString> VMLogMap;
    4748/** first is line number, second is block text */
    48 typedef QPair<int, QString> LogBookmark;
     49//typedef QPair<int, QString> LogBookmark;
    4950/** key is log file name, value is a vector of bookmarks. */
    50 typedef QMap<QString, QVector<LogBookmark> > BookmarkMap;
    51 
    52 
    53 /** QIMainWindow extension
    54   * providing GUI with VirtualBox LogViewer. */
     51//typedef QMap<QString, QVector<LogBookmark> > BookmarkMap;
     52
     53
     54/** QWidget extension providing GUI for VirtualBox LogViewer. It
     55 *  encapsulates log pages, toolbar, a tab widget and manages
     56 *  interaction between these classes. */
    5557class UIVMLogViewerWidget  : public QIWithRetranslateUI<QWidget>
    5658{
     
    137139    /** @} */
    138140
    139     /** Returns the current log-page. */
    140     QPlainTextEdit* currentLogPage() const;
     141
    141142    /** Returns the log-page from the tab with index @a pIndex. */
    142143    QPlainTextEdit* logPage(int pIndex) const;
    143144    /** Returns the newly created log-page using @a strPage filename. */
    144     QPlainTextEdit* createLogPage(const QString &strPage);
    145     /** Returns the content of current log-file as it is read. */
    146     const QString* currentLog();
     145    void createLogPage(const QString &strFileName, const QString &strLogContent, bool noLogsToShow = false);
     146
     147
     148    UIVMLogPage *currentLogPage();
     149    const UIVMLogPage *currentLogPage() const;
    147150
    148151    /** Attempts to read the logs through the API, returns true if there exists any logs, false otherwise. */
     
    152155    void resetHighlighthing();
    153156
    154     /** Returns the vector of bookmarks for the current log page */
    155     QVector<LogBookmark>* currentBookmarkVector();
    156     const QVector<LogBookmark>* currentBookmarkVector() const;
    157 
    158157    void hidePanel(UIVMLogViewerPanel* panel);
    159158    void showPanel(UIVMLogViewerPanel* panel);
     
    166165
    167166    /** Holds container for log-pages. */
    168     QITabWidget *m_pViewerContainer;
     167    QITabWidget        *m_pTabWidget;
     168    /** Stores the UIVMLogPage instances. This is modified as we add and remove new tabs
     169     *  to the m_pTabWidget. Index is the index of the tab widget. */
     170    QVector<QWidget*>  m_logPageList;
    169171
    170172    /** Holds the index to the current tab: */
    171     int          m_iCurrentTabIndex;
     173    //int          m_iCurrentTabIndex;
    172174
    173175    /** Holds the instance of search-panel. */
     
    179181
    180182    /** Holds the list of log file content. */
    181     VMLogMap             m_logMap;
    182     mutable BookmarkMap  m_bookmarkMap;
     183    // VMLogMap             m_logMap;
     184    // mutable BookmarkMap  m_bookmarkMap;
    183185    QVBoxLayout         *m_pMainLayout;
    184186
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