VirtualBox

Ignore:
Timestamp:
Dec 18, 2017 10:32:04 AM (7 years ago)
Author:
vboxsync
Message:

FE/Qt bugref:9072 Logviewer widget can be now embedded into machine tools pane

Location:
trunk/src/VBox/Frontends/VirtualBox/src
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/src/converter/UIConverterBackendGlobal.cpp

    r69500 r70185  
    873873        case ToolTypeMachine_Details:   strResult = "Details"; break;
    874874        case ToolTypeMachine_Snapshots: strResult = "Snapshots"; break;
     875        case ToolTypeMachine_LogViewer: strResult = "LogViewer"; break;
    875876        default:
    876877        {
     
    891892    keys << "Details";   values << ToolTypeMachine_Details;
    892893    keys << "Snapshots"; values << ToolTypeMachine_Snapshots;
     894    keys << "LogViewer"; values << ToolTypeMachine_LogViewer;
    893895    /* Invalid type for unknown words: */
    894896    if (!keys.contains(strToolTypeMachine, Qt::CaseInsensitive))
  • trunk/src/VBox/Frontends/VirtualBox/src/extradata/UIExtraDataDefs.h

    r70113 r70185  
    640640    ToolTypeMachine_Details,
    641641    ToolTypeMachine_Snapshots,
     642    ToolTypeMachine_LogViewer
    642643};
    643644Q_DECLARE_METATYPE(ToolTypeMachine);
  • trunk/src/VBox/Frontends/VirtualBox/src/logviewer/UIVMLogViewerDialog.cpp

    r70165 r70185  
    4141# ifdef VBOX_WS_MAC
    4242#  include "VBoxUtils-darwin.h"
    43 # endif
     43# endif /* VBOX_WS_MAC */
    4444
    4545#endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
  • trunk/src/VBox/Frontends/VirtualBox/src/logviewer/UIVMLogViewerWidget.cpp

    r70140 r70185  
    4848#endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
    4949
    50 UIVMLogViewerWidget::UIVMLogViewerWidget(EmbedTo enmEmbedding, QWidget *pParent, const CMachine &machine)
     50UIVMLogViewerWidget::UIVMLogViewerWidget(EmbedTo enmEmbedding, QWidget *pParent /* = 0 */, const CMachine &machine /* = CMachine() */)
    5151    : QIWithRetranslateUI<QWidget>(pParent)
    5252    , m_fIsPolished(false)
     
    7373int UIVMLogViewerWidget::defaultLogPageWidth() const
    7474{
    75     if(!m_pViewerContainer)
     75    if (!m_pViewerContainer)
    7676        return 0;
    7777
    7878    QWidget *pContainer = m_pViewerContainer->currentWidget();
    79     if(!pContainer)
     79    if (!pContainer)
    8080        return 0;
    8181
     
    111111    m_logMap.clear();
    112112    m_pViewerContainer->setEnabled(true);
     113    /* Hide the container widget during updates to avoid flickering: */
     114    m_pViewerContainer->hide();
    113115    while (m_pViewerContainer->count())
    114116    {
     
    118120    }
    119121
    120     bool isAnyLogPresent = false;
    121 
     122    bool noLogsToShow = false;
     123    QString strDummyTabText;
     124    /* check if the machine is valid: */
     125    if (m_comMachine.isNull())
     126    {
     127        noLogsToShow = true;
     128        strDummyTabText = QString(tr("<p><b>No machine</b> is currently selected. Please select a "
     129                                     "Virtual Machine to see its logs"));
     130    }
     131    /* If machine is valid and check if there are any log files and create viewer tabs: */
     132    else if (!createLogViewerPages())
     133    {
     134        noLogsToShow = true;
     135        strDummyTabText = QString(tr("<p>No log files found. Press the "
     136                                     "<b>Refresh</b> button to rescan the log folder "
     137                                     "<nobr><b>%1</b></nobr>.</p>"));
     138    }
     139    /* If the machine is not valid or has no log files show a single viewer tab: */
     140    if (noLogsToShow)
     141    {
     142        QPlainTextEdit *pDummyLog = createLogPage("VBox.log");
     143        pDummyLog->setWordWrapMode(QTextOption::WordWrap);
     144        pDummyLog->appendHtml(strDummyTabText);
     145        /* We don't want it to remain white: */
     146        QPalette pal = pDummyLog->palette();
     147        pal.setColor(QPalette::Base, pal.color(QPalette::Window));
     148        pDummyLog->setPalette(pal);
     149    }
     150
     151    /* Show the first tab widget's page after the refresh: */
     152    m_pViewerContainer->setCurrentIndex(0);
     153
     154    /* Apply the filter settings: */
     155    m_pFilterPanel->applyFilter();
     156
     157    /* Setup this connection after refresh to avoid initial signals during page creation: */
     158    connect(m_pViewerContainer, SIGNAL(currentChanged(int)), m_pFilterPanel, SLOT(applyFilter(int)));
     159
     160    /* Enable/Disable toolbar actions (except Refresh) & tab widget according log presence: */
     161    m_pActionFind->setEnabled(!noLogsToShow);
     162    m_pActionFilter->setEnabled(!noLogsToShow);
     163    m_pActionSave->setEnabled(!noLogsToShow);
     164    m_pViewerContainer->setEnabled(!noLogsToShow);
     165    m_pViewerContainer->show();
     166}
     167
     168void UIVMLogViewerWidget::sltSave()
     169{
     170    if (m_comMachine.isNull())
     171        return;
     172    /* Prepare "save as" dialog: */
     173    const QFileInfo fileInfo(m_book.at(m_pViewerContainer->currentIndex()).first);
     174    /* Prepare default filename: */
     175    const QDateTime dtInfo = fileInfo.lastModified();
     176    const QString strDtString = dtInfo.toString("yyyy-MM-dd-hh-mm-ss");
     177    const QString strDefaultFileName = QString("%1-%2.log").arg(m_comMachine.GetName()).arg(strDtString);
     178    const QString strDefaultFullName = QDir::toNativeSeparators(QDir::home().absolutePath() + "/" + strDefaultFileName);
     179
     180    const QString strNewFileName = QIFileDialog::getSaveFileName(strDefaultFullName,
     181                                                                 "",
     182                                                                 this,
     183                                                                 tr("Save VirtualBox Log As"),
     184                                                                 0 /* selected filter */,
     185                                                                 true /* resolve symlinks */,
     186                                                                 true /* confirm overwrite */);
     187    /* Make sure file-name is not empty: */
     188    if (!strNewFileName.isEmpty())
     189    {
     190        /* Delete the previous file if already exists as user already confirmed: */
     191        if (QFile::exists(strNewFileName))
     192            QFile::remove(strNewFileName);
     193        /* Copy log into the file: */
     194        QFile::copy(m_comMachine.QueryLogFilename(m_pViewerContainer->currentIndex()), strNewFileName);
     195    }
     196}
     197
     198void UIVMLogViewerWidget::sltFilter()
     199{
     200    /* Show/hide filter-panel: */
     201    m_pFilterPanel->isHidden() ? m_pFilterPanel->show() : m_pFilterPanel->hide();
     202}
     203
     204void UIVMLogViewerWidget::setMachine(const CMachine &machine)
     205{
     206    if (machine == m_comMachine)
     207        return;
     208    m_comMachine = machine;
     209    sltRefresh();
     210}
     211
     212void UIVMLogViewerWidget::prepare()
     213{
     214    m_pMainLayout = new QVBoxLayout(this);
     215
     216    prepareActions();
     217
     218    prepareToolBar();
     219    prepareMenu();
     220
     221    /* Prepare widgets: */
     222    prepareWidgets();
     223
     224    /* Reading log files: */
     225    sltRefresh();
     226
     227    /* Loading language constants: */
     228    retranslateUi();
     229}
     230
     231void UIVMLogViewerWidget::prepareWidgets()
     232{
     233    /* Configure layout: */
     234    layout()->setContentsMargins(0, 0, 0, 0);
     235#ifdef VBOX_WS_MAC
     236        layout()->setSpacing(10);
     237#else
     238        const int iS = qApp->style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing) / 2;
     239        layout()->setSpacing(iS);
     240#endif
     241
     242    /* Create VM Log-Viewer container: */
     243    m_pViewerContainer = new QITabWidget(this);
     244    AssertPtrReturnVoid(m_pViewerContainer);
     245    {
     246        /* Add VM Log-Viewer container to main-layout: */
     247        m_pMainLayout->insertWidget(1, m_pViewerContainer);
     248    }
     249
     250    /* Create VM Log-Viewer search-panel: */
     251    m_pSearchPanel = new UIVMLogViewerSearchPanel(this, this);
     252    AssertPtrReturnVoid(m_pSearchPanel);
     253    {
     254        /* Configure VM Log-Viewer search-panel: */
     255        installEventFilter(m_pSearchPanel);
     256        m_pSearchPanel->hide();
     257        /* Add VM Log-Viewer search-panel to main-layout: */
     258        m_pMainLayout->insertWidget(2, m_pSearchPanel);
     259    }
     260
     261    /* Create VM Log-Viewer filter-panel: */
     262    m_pFilterPanel = new UIVMLogViewerFilterPanel(this, this);
     263    AssertPtrReturnVoid(m_pFilterPanel);
     264    {
     265        /* Configure VM Log-Viewer filter-panel: */
     266        installEventFilter(m_pFilterPanel);
     267        m_pFilterPanel->hide();
     268        /* Add VM Log-Viewer filter-panel to main-layout: */
     269        m_pMainLayout->insertWidget(3, m_pFilterPanel);
     270    }
     271}
     272
     273void UIVMLogViewerWidget::prepareActions()
     274{
     275    /* Create and configure 'Find' action: */
     276    m_pActionFind = new QAction(this);
     277    AssertPtrReturnVoid(m_pActionFind);
     278    {
     279        m_pActionFind->setShortcut(QKeySequence("Ctrl+F"));
     280        connect(m_pActionFind, &QAction::triggered, this, &UIVMLogViewerWidget::sltFind);
     281    }
     282
     283    /* Create and configure 'Filter' action: */
     284    m_pActionFilter = new QAction(this);
     285    AssertPtrReturnVoid(m_pActionFilter);
     286    {
     287        m_pActionFilter->setShortcut(QKeySequence("Ctrl+T"));
     288        connect(m_pActionFilter, &QAction::triggered, this, &UIVMLogViewerWidget::sltFilter);
     289    }
     290
     291    /* Create and configure 'Refresh' action: */
     292    m_pActionRefresh = new QAction(this);
     293    AssertPtrReturnVoid(m_pActionRefresh);
     294    {
     295        m_pActionRefresh->setShortcut(QKeySequence("F5"));
     296        connect(m_pActionRefresh, &QAction::triggered, this, &UIVMLogViewerWidget::sltRefresh);
     297    }
     298
     299    /* Create and configure 'Save' action: */
     300    m_pActionSave = new QAction(this);
     301    AssertPtrReturnVoid(m_pActionSave);
     302    {
     303        m_pActionSave->setShortcut(QKeySequence("Ctrl+S"));
     304        connect(m_pActionSave, &QAction::triggered, this, &UIVMLogViewerWidget::sltSave);
     305    }
     306
     307    /* Update action icons: */
     308    prepareActionIcons();
     309}
     310
     311void UIVMLogViewerWidget::prepareActionIcons()
     312{
     313    QString strPrefix = "log_viewer";
     314
     315    if (m_pActionFind)
     316        m_pActionFind->setIcon(UIIconPool::iconSet(QString(":/%1_find_24px.png").arg(strPrefix),
     317                                                       QString(":/%1_find_disabled_24px.png").arg(strPrefix)));
     318
     319    if (m_pActionFilter)
     320        m_pActionFilter->setIcon(UIIconPool::iconSet(QString(":/%1_filter_24px.png").arg(strPrefix),
     321                                                         QString(":/%1_filter_disabled_24px.png").arg(strPrefix)));
     322
     323
     324    if (m_pActionRefresh)
     325        m_pActionRefresh->setIcon(UIIconPool::iconSet(QString(":/%1_refresh_24px.png").arg(strPrefix),
     326                                                          QString(":/%1_refresh_disabled_24px.png").arg(strPrefix)));
     327
     328
     329    if (m_pActionSave)
     330        m_pActionSave->setIcon(UIIconPool::iconSet(QString(":/%1_save_24px.png").arg(strPrefix),
     331                                                       QString(":/%1_save_disabled_24px.png").arg(strPrefix)));
     332
     333
     334}
     335
     336void UIVMLogViewerWidget::prepareToolBar()
     337{
     338    /* Create toolbar: */
     339    m_pToolBar = new UIToolBar(parentWidget());
     340    AssertPtrReturnVoid(m_pToolBar);
     341    {
     342        /* Configure toolbar: */
     343        const int iIconMetric = (int)(QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) * 1.375);
     344        m_pToolBar->setIconSize(QSize(iIconMetric, iIconMetric));
     345        m_pToolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
     346        /* Add toolbar actions: */
     347        if (m_pActionFind)
     348            m_pToolBar->addAction(m_pActionFind);
     349
     350        if (m_pActionFilter)
     351            m_pToolBar->addAction(m_pActionFilter);
     352
     353        if (m_pActionRefresh)
     354            m_pToolBar->addAction(m_pActionRefresh);
     355
     356        if (m_pActionSave)
     357            m_pToolBar->addAction(m_pActionSave);
     358
     359#ifdef VBOX_WS_MAC
     360        /* Check whether we are embedded into a stack: */
     361        if (m_enmEmbedding == EmbedTo_Stack)
     362        {
     363            /* Add into layout: */
     364            layout()->addWidget(m_pToolBar);
     365        }
     366#else
     367        /* Add into layout: */
     368        m_pMainLayout->insertWidget(0, m_pToolBar);
     369#endif
     370    }
     371}
     372
     373void UIVMLogViewerWidget::prepareMenu()
     374{
     375    /* Create 'LogViewer' menu: */
     376    m_pMenu = new QMenu(this);
     377    AssertPtrReturnVoid(m_pMenu);
     378    {
     379        if (m_pActionFind)
     380            m_pMenu->addAction(m_pActionFind);
     381        if (m_pActionFilter)
     382            m_pMenu->addAction(m_pActionFilter);
     383        if (m_pActionRefresh)
     384            m_pMenu->addAction(m_pActionRefresh);
     385        if (m_pActionSave)
     386            m_pMenu->addAction(m_pActionSave);
     387    }
     388}
     389
     390void UIVMLogViewerWidget::cleanup()
     391{
     392}
     393
     394void UIVMLogViewerWidget::retranslateUi()
     395{
     396    if (m_pMenu)
     397    {
     398        m_pMenu->setTitle(tr("&Log Viewer"));
     399    }
     400
     401    if (m_pActionFind)
     402    {
     403        m_pActionFind->setText(tr("&Find"));
     404        m_pActionFind->setToolTip(tr("Find a string within the log"));
     405        m_pActionFind->setStatusTip(tr("Find a string within the log"));
     406    }
     407
     408    if (m_pActionFilter)
     409    {
     410        m_pActionFilter->setText(tr("&Filter"));
     411        m_pActionFilter->setToolTip(tr("Filter the log wrt. the given string"));
     412        m_pActionFilter->setStatusTip(tr("Filter the log wrt. the given string"));
     413    }
     414
     415    if (m_pActionRefresh)
     416    {
     417        m_pActionRefresh->setText(tr("&Refresh"));
     418        m_pActionRefresh->setToolTip(tr("Reload the log"));
     419        m_pActionRefresh->setStatusTip(tr("Reload the log"));
     420    }
     421
     422    if (m_pActionSave)
     423    {
     424        m_pActionSave->setText(tr("&Save..."));
     425        m_pActionSave->setToolTip(tr("Save the log"));
     426        m_pActionSave->setStatusTip(tr("Save the log"));
     427    }
     428
     429    /* Translate toolbar: */
     430#ifdef VBOX_WS_MAC
     431    // WORKAROUND:
     432    // There is a bug in Qt Cocoa which result in showing a "more arrow" when
     433    // the necessary size of the toolbar is increased. Also for some languages
     434    // the with doesn't match if the text increase. So manually adjust the size
     435    // after changing the text. */
     436    if (m_pToolBar)
     437        m_pToolBar->updateLayout();
     438#endif
     439}
     440
     441void UIVMLogViewerWidget::showEvent(QShowEvent *pEvent)
     442{
     443    QWidget::showEvent(pEvent);
     444
     445    /* One may think that QWidget::polish() is the right place to do things
     446     * below, but apparently, by the time when QWidget::polish() is called,
     447     * the widget style & layout are not fully done, at least the minimum
     448     * size hint is not properly calculated. Since this is sometimes necessary,
     449     * we provide our own "polish" implementation: */
     450
     451    if (m_fIsPolished)
     452        return;
     453
     454    m_fIsPolished = true;
     455
     456    /* Make sure the log view widget has the focus: */
     457    QWidget *pCurrentLogPage = currentLogPage();
     458    if (pCurrentLogPage)
     459        pCurrentLogPage->setFocus();
     460}
     461
     462void UIVMLogViewerWidget::keyPressEvent(QKeyEvent *pEvent)
     463{
     464    /* Depending on key pressed: */
     465    switch (pEvent->key())
     466    {
     467        /* Process key escape as VM Log Viewer close: */
     468        case Qt::Key_Escape:
     469        {
     470            return;
     471        }
     472        /* Process Back key as switch to previous tab: */
     473        case Qt::Key_Back:
     474        {
     475            if (m_pViewerContainer->currentIndex() > 0)
     476            {
     477                m_pViewerContainer->setCurrentIndex(m_pViewerContainer->currentIndex() - 1);
     478                return;
     479            }
     480            break;
     481        }
     482        /* Process Forward key as switch to next tab: */
     483        case Qt::Key_Forward:
     484        {
     485            if (m_pViewerContainer->currentIndex() < m_pViewerContainer->count())
     486            {
     487                m_pViewerContainer->setCurrentIndex(m_pViewerContainer->currentIndex() + 1);
     488                return;
     489            }
     490            break;
     491        }
     492        default:
     493            break;
     494    }
     495    QWidget::keyReleaseEvent(pEvent);
     496}
     497
     498QPlainTextEdit* UIVMLogViewerWidget::currentLogPage() const
     499{
     500    /* If viewer-container is enabled: */
     501    if (m_pViewerContainer->isEnabled())
     502    {
     503        /* Get and return current log-page: */
     504        QWidget *pContainer = m_pViewerContainer->currentWidget();
     505        QPlainTextEdit *pBrowser = pContainer->findChild<QPlainTextEdit*>();
     506        Assert(pBrowser);
     507        return pBrowser ? pBrowser : 0;
     508    }
     509    /* Return NULL by default: */
     510    return 0;
     511}
     512
     513bool UIVMLogViewerWidget::createLogViewerPages()
     514{
     515    if (m_comMachine.isNull())
     516        return false;
     517
     518    bool logsExists = false;
    122519    const CSystemProperties &sys = vboxGlobal().virtualBox().GetSystemProperties();
    123520    unsigned cMaxLogs = sys.GetLogHistoryCount() + 1 /*VBox.log*/ + 1 /*VBoxHardening.log*/; /** @todo Add api for getting total possible log count! */
     
    153550                /* Add the log-text to the map: */
    154551                m_logMap[pLogViewer] = strText;
    155                 isAnyLogPresent = true;
     552                logsExists = true;
    156553            }
    157554        }
    158555    }
    159 
    160     /* Create an empty log page if there are no logs at all: */
    161     if (!isAnyLogPresent)
    162     {
    163         QPlainTextEdit *pDummyLog = createLogPage("VBox.log");
    164         pDummyLog->setWordWrapMode(QTextOption::WordWrap);
    165         pDummyLog->appendHtml(tr("<p>No log files found. Press the "
    166                               "<b>Refresh</b> button to rescan the log folder "
    167                               "<nobr><b>%1</b></nobr>.</p>")
    168                               .arg(m_comMachine.GetLogFolder()));
    169         /* We don't want it to remain white: */
    170         QPalette pal = pDummyLog->palette();
    171         pal.setColor(QPalette::Base, pal.color(QPalette::Window));
    172         pDummyLog->setPalette(pal);
    173     }
    174 
    175     /* Show the first tab widget's page after the refresh: */
    176     m_pViewerContainer->setCurrentIndex(0);
    177 
    178     /* Apply the filter settings: */
    179     m_pFilterPanel->applyFilter();
    180 
    181     /* Setup this connection after refresh to avoid initial signals during page creation: */
    182     connect(m_pViewerContainer, SIGNAL(currentChanged(int)), m_pFilterPanel, SLOT(applyFilter(int)));
    183 
    184     /* Enable/Disable toolbar actions (except Refresh) & tab widget according log presence: */
    185     m_pActionFind->setEnabled(isAnyLogPresent);
    186     m_pActionFilter->setEnabled(isAnyLogPresent);
    187     m_pActionSave->setEnabled(isAnyLogPresent);
    188     m_pViewerContainer->setEnabled(isAnyLogPresent);
    189 }
    190 
    191 void UIVMLogViewerWidget::sltSave()
    192 {
    193     /* Prepare "save as" dialog: */
    194     const QFileInfo fileInfo(m_book.at(m_pViewerContainer->currentIndex()).first);
    195     /* Prepare default filename: */
    196     const QDateTime dtInfo = fileInfo.lastModified();
    197     const QString strDtString = dtInfo.toString("yyyy-MM-dd-hh-mm-ss");
    198     const QString strDefaultFileName = QString("%1-%2.log").arg(m_comMachine.GetName()).arg(strDtString);
    199     const QString strDefaultFullName = QDir::toNativeSeparators(QDir::home().absolutePath() + "/" + strDefaultFileName);
    200     /* Show "save as" dialog: */
    201     const QString strNewFileName = QIFileDialog::getSaveFileName(strDefaultFullName,
    202                                                                  "",
    203                                                                  this,
    204                                                                  tr("Save VirtualBox Log As"),
    205                                                                  0 /* selected filter */,
    206                                                                  true /* resolve symlinks */,
    207                                                                  true /* confirm overwrite */);
    208     /* Make sure file-name is not empty: */
    209     if (!strNewFileName.isEmpty())
    210     {
    211         /* Delete the previous file if already exists as user already confirmed: */
    212         if (QFile::exists(strNewFileName))
    213             QFile::remove(strNewFileName);
    214         /* Copy log into the file: */
    215         QFile::copy(m_comMachine.QueryLogFilename(m_pViewerContainer->currentIndex()), strNewFileName);
    216     }
    217 }
    218 
    219 void UIVMLogViewerWidget::sltFilter()
    220 {
    221     /* Show/hide filter-panel: */
    222     m_pFilterPanel->isHidden() ? m_pFilterPanel->show() : m_pFilterPanel->hide();
    223 }
    224 
    225 void UIVMLogViewerWidget::prepare()
    226 {
    227     m_pMainLayout = new QVBoxLayout(this);
    228 
    229     prepareActions();
    230 
    231     prepareToolBar();
    232     prepareMenu();
    233 
    234     /* Prepare widgets: */
    235     prepareWidgets();
    236 
    237     /* Reading log files: */
    238     sltRefresh();
    239 
    240     /* Loading language constants: */
    241     retranslateUi();
    242 }
    243 
    244 void UIVMLogViewerWidget::prepareWidgets()
    245 {
    246     /* Configure layout: */
    247     layout()->setContentsMargins(0, 0, 0, 0);
    248 #ifdef VBOX_WS_MAC
    249         layout()->setSpacing(10);
    250 #else
    251         const int iS = qApp->style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing) / 2;
    252         layout()->setSpacing(iS);
    253 #endif
    254 
    255     /* Create VM Log-Viewer container: */
    256     m_pViewerContainer = new QITabWidget(this);
    257     AssertPtrReturnVoid(m_pViewerContainer);
    258     {
    259         /* Add VM Log-Viewer container to main-layout: */
    260         m_pMainLayout->insertWidget(1, m_pViewerContainer);
    261     }
    262 
    263     /* Create VM Log-Viewer search-panel: */
    264     m_pSearchPanel = new UIVMLogViewerSearchPanel(this, this);
    265     AssertPtrReturnVoid(m_pSearchPanel);
    266     {
    267         /* Configure VM Log-Viewer search-panel: */
    268         installEventFilter(m_pSearchPanel);
    269         m_pSearchPanel->hide();
    270         /* Add VM Log-Viewer search-panel to main-layout: */
    271         m_pMainLayout->insertWidget(2, m_pSearchPanel);
    272     }
    273 
    274     /* Create VM Log-Viewer filter-panel: */
    275     m_pFilterPanel = new UIVMLogViewerFilterPanel(this, this);
    276     AssertPtrReturnVoid(m_pFilterPanel);
    277     {
    278         /* Configure VM Log-Viewer filter-panel: */
    279         installEventFilter(m_pFilterPanel);
    280         m_pFilterPanel->hide();
    281         /* Add VM Log-Viewer filter-panel to main-layout: */
    282         m_pMainLayout->insertWidget(3, m_pFilterPanel);
    283     }
    284 }
    285 
    286 void UIVMLogViewerWidget::prepareActions()
    287 {
    288     /* Create and configure 'Find' action: */
    289     m_pActionFind = new QAction(this);
    290     AssertPtrReturnVoid(m_pActionFind);
    291     {
    292         m_pActionFind->setShortcut(QKeySequence("Ctrl+F"));
    293         connect(m_pActionFind, &QAction::triggered, this, &UIVMLogViewerWidget::sltFind);
    294     }
    295 
    296     /* Create and configure 'Filter' action: */
    297     m_pActionFilter = new QAction(this);
    298     AssertPtrReturnVoid(m_pActionFilter);
    299     {
    300         m_pActionFilter->setShortcut(QKeySequence("Ctrl+T"));
    301         connect(m_pActionFilter, &QAction::triggered, this, &UIVMLogViewerWidget::sltFilter);
    302     }
    303 
    304     /* Create and configure 'Refresh' action: */
    305     m_pActionRefresh = new QAction(this);
    306     AssertPtrReturnVoid(m_pActionRefresh);
    307     {
    308         m_pActionRefresh->setShortcut(QKeySequence("F5"));
    309         connect(m_pActionRefresh, &QAction::triggered, this, &UIVMLogViewerWidget::sltRefresh);
    310     }
    311 
    312     /* Create and configure 'Save' action: */
    313     m_pActionSave = new QAction(this);
    314     AssertPtrReturnVoid(m_pActionSave);
    315     {
    316         m_pActionSave->setShortcut(QKeySequence("Ctrl+S"));
    317         connect(m_pActionSave, &QAction::triggered, this, &UIVMLogViewerWidget::sltSave);
    318     }
    319 
    320     /* Update action icons: */
    321     prepareActionIcons();
    322 }
    323 
    324 void UIVMLogViewerWidget::prepareActionIcons()
    325 {
    326     QString strPrefix = "log_viewer";
    327 
    328     if (m_pActionFind)
    329         m_pActionFind->setIcon(UIIconPool::iconSet(QString(":/%1_find_24px.png").arg(strPrefix),
    330                                                        QString(":/%1_find_disabled_24px.png").arg(strPrefix)));
    331 
    332     if (m_pActionFilter)
    333         m_pActionFilter->setIcon(UIIconPool::iconSet(QString(":/%1_filter_24px.png").arg(strPrefix),
    334                                                          QString(":/%1_filter_disabled_24px.png").arg(strPrefix)));
    335 
    336 
    337     if (m_pActionRefresh)
    338         m_pActionRefresh->setIcon(UIIconPool::iconSet(QString(":/%1_refresh_24px.png").arg(strPrefix),
    339                                                           QString(":/%1_refresh_disabled_24px.png").arg(strPrefix)));
    340 
    341 
    342     if (m_pActionSave)
    343         m_pActionSave->setIcon(UIIconPool::iconSet(QString(":/%1_save_24px.png").arg(strPrefix),
    344                                                        QString(":/%1_save_disabled_24px.png").arg(strPrefix)));
    345 
    346 
    347 }
    348 
    349 void UIVMLogViewerWidget::prepareToolBar()
    350 {
    351     /* Create toolbar: */
    352     m_pToolBar = new UIToolBar(parentWidget());
    353     AssertPtrReturnVoid(m_pToolBar);
    354     {
    355         /* Configure toolbar: */
    356         const int iIconMetric = (int)(QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) * 1.375);
    357         m_pToolBar->setIconSize(QSize(iIconMetric, iIconMetric));
    358         m_pToolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
    359         /* Add toolbar actions: */
    360         if (m_pActionFind)
    361             m_pToolBar->addAction(m_pActionFind);
    362 
    363         if (m_pActionFilter)
    364             m_pToolBar->addAction(m_pActionFilter);
    365 
    366         if (m_pActionRefresh)
    367             m_pToolBar->addAction(m_pActionRefresh);
    368 
    369         if (m_pActionSave)
    370             m_pToolBar->addAction(m_pActionSave);
    371 
    372 #ifdef VBOX_WS_MAC
    373         /* Check whether we are embedded into a stack: */
    374         if (m_enmEmbedding == EmbedTo_Stack)
    375         {
    376             /* Add into layout: */
    377             layout()->addWidget(m_pToolBar);
    378         }
    379 #else
    380         /* Add into layout: */
    381         m_pMainLayout->insertWidget(0, m_pToolBar);
    382 #endif
    383     }
    384 }
    385 
    386 void UIVMLogViewerWidget::prepareMenu()
    387 {
    388     /* Create 'LogViewer' menu: */
    389     m_pMenu = new QMenu(this);
    390     AssertPtrReturnVoid(m_pMenu);
    391     {
    392         if (m_pActionFind)
    393             m_pMenu->addAction(m_pActionFind);
    394         if (m_pActionFilter)
    395             m_pMenu->addAction(m_pActionFilter);
    396         if (m_pActionRefresh)
    397             m_pMenu->addAction(m_pActionRefresh);
    398         if (m_pActionSave)
    399             m_pMenu->addAction(m_pActionSave);
    400     }
    401 }
    402 
    403 void UIVMLogViewerWidget::cleanup()
    404 {
    405 }
    406 
    407 void UIVMLogViewerWidget::retranslateUi()
    408 {
    409     if(m_pMenu)
    410     {
    411         m_pMenu->setTitle(tr("&Log Viewer"));
    412     }
    413 
    414     if (m_pActionFind)
    415     {
    416         m_pActionFind->setText(tr("&Find..."));
    417         m_pActionFind->setToolTip(tr("Find a string within the log"));
    418         m_pActionFind->setStatusTip(tr("Find a string within the log"));
    419     }
    420 
    421     if (m_pActionFilter)
    422     {
    423         m_pActionFilter->setText(tr("&Filter..."));
    424         m_pActionFilter->setToolTip(tr("Filter the log wrt. the given string"));
    425         m_pActionFilter->setStatusTip(tr("Filter the log wrt. the given string"));
    426     }
    427 
    428     if (m_pActionRefresh)
    429     {
    430         m_pActionRefresh->setText(tr("&Refresh..."));
    431         m_pActionRefresh->setToolTip(tr("Reload the log"));
    432         m_pActionRefresh->setStatusTip(tr("Reload the log"));
    433     }
    434 
    435     if (m_pActionSave)
    436     {
    437         m_pActionSave->setText(tr("&Save..."));
    438         m_pActionSave->setToolTip(tr("Save the log"));
    439         m_pActionSave->setStatusTip(tr("Save the log"));
    440     }
    441 
    442     /* Translate toolbar: */
    443 #ifdef VBOX_WS_MAC
    444     // WORKAROUND:
    445     // There is a bug in Qt Cocoa which result in showing a "more arrow" when
    446     // the necessary size of the toolbar is increased. Also for some languages
    447     // the with doesn't match if the text increase. So manually adjust the size
    448     // after changing the text. */
    449     if (m_pToolBar)
    450         m_pToolBar->updateLayout();
    451 #endif
    452 }
    453 
    454 void UIVMLogViewerWidget::showEvent(QShowEvent *pEvent)
    455 {
    456     QWidget::showEvent(pEvent);
    457 
    458     /* One may think that QWidget::polish() is the right place to do things
    459      * below, but apparently, by the time when QWidget::polish() is called,
    460      * the widget style & layout are not fully done, at least the minimum
    461      * size hint is not properly calculated. Since this is sometimes necessary,
    462      * we provide our own "polish" implementation: */
    463 
    464     if (m_fIsPolished)
    465         return;
    466 
    467     m_fIsPolished = true;
    468 
    469     /* Make sure the log view widget has the focus: */
    470     QWidget *pCurrentLogPage = currentLogPage();
    471     if (pCurrentLogPage)
    472         pCurrentLogPage->setFocus();
    473 }
    474 
    475 void UIVMLogViewerWidget::keyPressEvent(QKeyEvent *pEvent)
    476 {
    477     /* Depending on key pressed: */
    478     switch (pEvent->key())
    479     {
    480         /* Process key escape as VM Log Viewer close: */
    481         case Qt::Key_Escape:
    482         {
    483             return;
    484         }
    485         /* Process Back key as switch to previous tab: */
    486         case Qt::Key_Back:
    487         {
    488             if (m_pViewerContainer->currentIndex() > 0)
    489             {
    490                 m_pViewerContainer->setCurrentIndex(m_pViewerContainer->currentIndex() - 1);
    491                 return;
    492             }
    493             break;
    494         }
    495         /* Process Forward key as switch to next tab: */
    496         case Qt::Key_Forward:
    497         {
    498             if (m_pViewerContainer->currentIndex() < m_pViewerContainer->count())
    499             {
    500                 m_pViewerContainer->setCurrentIndex(m_pViewerContainer->currentIndex() + 1);
    501                 return;
    502             }
    503             break;
    504         }
    505         default:
    506             break;
    507     }
    508     QWidget::keyReleaseEvent(pEvent);
    509 }
    510 
    511 QPlainTextEdit* UIVMLogViewerWidget::currentLogPage() const
    512 {
    513     /* If viewer-container is enabled: */
    514     if (m_pViewerContainer->isEnabled())
    515     {
    516         /* Get and return current log-page: */
    517         QWidget *pContainer = m_pViewerContainer->currentWidget();
    518         QPlainTextEdit *pBrowser = pContainer->findChild<QPlainTextEdit*>();
    519         Assert(pBrowser);
    520         return pBrowser ? pBrowser : 0;
    521     }
    522     /* Return NULL by default: */
    523     return 0;
     556    return logsExists;
    524557}
    525558
     
    562595    return m_logMap[currentLogPage()];
    563596}
    564 
  • trunk/src/VBox/Frontends/VirtualBox/src/logviewer/UIVMLogViewerWidget.h

    r70139 r70185  
    5454    /** Constructs the VM Log-Viewer by passing @a pParent to QWidget base-class constructor.
    5555      * @param  machine  Specifies the machine for which VM Log-Viewer is requested. */
    56     UIVMLogViewerWidget(EmbedTo enmEmbedding, QWidget *pParent, const CMachine &machine);
     56    UIVMLogViewerWidget(EmbedTo enmEmbedding, QWidget *pParent = 0, const CMachine &machine = CMachine());
    5757    /** Destructs the VM Log-Viewer. */
    5858    ~UIVMLogViewerWidget();
     
    6767    UIToolBar *toolbar() const { return m_pToolBar; }
    6868#endif
     69
     70    /** Sets the machine whose logs to show. */
     71    void setMachine(const CMachine &machine);
    6972
    7073protected:
     
    120123    const QString& currentLog();
    121124
     125    /** Attempts to read the logs through the API, returns true if there exists any logs, false otherwise. */
     126    bool createLogViewerPages();
     127
    122128    /** Holds whether the dialog is polished. */
    123129    bool m_fIsPolished;
  • trunk/src/VBox/Frontends/VirtualBox/src/selector/UIActionPoolSelector.cpp

    r69500 r70185  
    10211021        setName(QApplication::translate("UIActionPool", "&Snapshots"));
    10221022        setStatusTip(QApplication::translate("UIActionPool", "Open the machine snapshots pane"));
     1023    }
     1024};
     1025
     1026class UIActionSimpleToolsMachineLogViewer : public UIActionSimple
     1027{
     1028    Q_OBJECT;
     1029
     1030public:
     1031
     1032    UIActionSimpleToolsMachineLogViewer(UIActionPool *pParent)
     1033        : UIActionSimple(pParent,
     1034                         ":/vm_show_logs_32px.png", ":/vm_show_logs_32px.png",
     1035                         ":/vm_show_logs_32px.png", ":/vm_show_logs_32px.png") {}
     1036
     1037protected:
     1038
     1039    QString shortcutExtraDataID() const
     1040    {
     1041        return QString("ToolsMachineLogViewer");
     1042    }
     1043
     1044    void retranslateUi()
     1045    {
     1046        setName(QApplication::translate("UIActionPool", "&LogViewer"));
     1047        setStatusTip(QApplication::translate("UIActionPool", "Open the machine logviewer pane"));
    10231048    }
    10241049};
     
    13201345    m_pool[UIActionIndexST_M_Tools_M_Machine_S_Details] = new UIActionSimpleToolsMachineDetails(this);
    13211346    m_pool[UIActionIndexST_M_Tools_M_Machine_S_Snapshots] = new UIActionSimpleToolsMachineSnapshots(this);
     1347    m_pool[UIActionIndexST_M_Tools_M_Machine_S_LogViewer] = new UIActionSimpleToolsMachineLogViewer(this);
    13221348
    13231349    /* Global Tools actions: */
  • trunk/src/VBox/Frontends/VirtualBox/src/selector/UIActionPoolSelector.h

    r69500 r70185  
    9797    UIActionIndexST_M_Tools_M_Machine_S_Details,
    9898    UIActionIndexST_M_Tools_M_Machine_S_Snapshots,
     99    UIActionIndexST_M_Tools_M_Machine_S_LogViewer,
    99100
    100101    /* Global Tools actions: */
  • trunk/src/VBox/Frontends/VirtualBox/src/selector/UISelectorWindow.cpp

    r70147 r70185  
    159159        mapActionsMachine[ToolTypeMachine_Details] = actionPool()->action(UIActionIndexST_M_Tools_M_Machine_S_Details);
    160160        mapActionsMachine[ToolTypeMachine_Snapshots] = actionPool()->action(UIActionIndexST_M_Tools_M_Machine_S_Snapshots);
     161        mapActionsMachine[ToolTypeMachine_LogViewer] = actionPool()->action(UIActionIndexST_M_Tools_M_Machine_S_LogViewer);
    161162        for (int i = m_orderMachine.size() - 1; i >= 0; --i)
    162163            if (m_orderMachine.at(i) != ToolTypeMachine_Invalid)
     
    251252
    252253void UISelectorWindow::sltHandleChooserPaneIndexChange(bool fUpdateDetails /* = true */,
    253                                                        bool fUpdateSnapshots /* = true */)
     254                                                       bool fUpdateSnapshots /* = true */,
     255                                                       bool fUpdateLogViewer /* = true*/)
    254256{
    255257    /* Get current item: */
     
    279281            if (m_pPaneToolsMachine->isToolOpened(ToolTypeMachine_Snapshots))
    280282                actionPool()->action(UIActionIndexST_M_Tools_M_Machine_S_Snapshots)->trigger();
     283            else
     284            if (m_pPaneToolsMachine->isToolOpened(ToolTypeMachine_LogViewer))
     285                actionPool()->action(UIActionIndexST_M_Tools_M_Machine_S_LogViewer)->trigger();
    281286        }
    282287
     
    285290            && m_pPaneToolsMachine->isToolOpened(ToolTypeMachine_Details))
    286291            m_pPaneToolsMachine->setItems(currentItems());
    287         /* Update Snapshots-pane (if requested): */
    288         if (   fUpdateSnapshots
    289             && m_pPaneToolsMachine->isToolOpened(ToolTypeMachine_Snapshots))
     292        /* Update the Snapshots-pane or/and Logviewer-pane (if requested): */
     293        if (fUpdateSnapshots || fUpdateLogViewer)
    290294            m_pPaneToolsMachine->setMachine(pItem->machine());
    291295    }
     
    306310        if (m_pPaneToolsMachine->isToolOpened(ToolTypeMachine_Details))
    307311            m_pPaneToolsMachine->setItems(currentItems());
    308         /* Update Snapshots-pane (in any case): */
    309         if (m_pPaneToolsMachine->isToolOpened(ToolTypeMachine_Snapshots))
    310             m_pPaneToolsMachine->setMachine(CMachine());
     312        /* Update Snapshots-pane and Logviewer-pane (in any case): */
     313        m_pPaneToolsMachine->setMachine(CMachine());
    311314    }
    312315}
     
    11411144
    11421145    /* Make sure chosen item fetched: */
    1143     sltHandleChooserPaneIndexChange(false /* update details? */, false /* update snapshots? */);
     1146    sltHandleChooserPaneIndexChange(false /* update details? */, false /* update snapshots? */, false /* update the logviewer? */);
    11441147}
    11451148
     
    11701173        m_pPaneToolsMachine->setItems(currentItems());
    11711174    /* If that was 'Snapshot' => pass there current or null machine: */
    1172     if (   enmType == ToolTypeMachine_Snapshots
    1173         && m_pPaneToolsMachine->isToolOpened(ToolTypeMachine_Snapshots))
     1175    if (enmType == ToolTypeMachine_Snapshots || enmType == ToolTypeMachine_LogViewer)
    11741176    {
    11751177        UIVMItem *pItem = currentItem();
     
    12261228
    12271229    /* Make sure chosen item fetched: */
    1228     sltHandleChooserPaneIndexChange(false /* update details? */, false /* update snapshots? */);
     1230    sltHandleChooserPaneIndexChange(false /* update details? */, false /* update snapshots? */, false /* update the logviewer? */);
    12291231
    12301232#ifdef VBOX_WS_MAC
     
    24302432    actionPool()->action(UIActionIndexST_M_Tools_M_Machine_S_Details)->setEnabled(isActionEnabled(UIActionIndexST_M_Tools_M_Machine_S_Details, items));
    24312433    actionPool()->action(UIActionIndexST_M_Tools_M_Machine_S_Snapshots)->setEnabled(isActionEnabled(UIActionIndexST_M_Tools_M_Machine_S_Snapshots, items));
     2434    actionPool()->action(UIActionIndexST_M_Tools_M_Machine_S_LogViewer)->setEnabled(isActionEnabled(UIActionIndexST_M_Tools_M_Machine_S_LogViewer, items));
    24322435}
    24332436
     
    25592562        case UIActionIndexST_M_Tools_M_Machine_S_Details:
    25602563        case UIActionIndexST_M_Tools_M_Machine_S_Snapshots:
     2564        case UIActionIndexST_M_Tools_M_Machine_S_LogViewer:
    25612565        {
    25622566            return pItem->accessible();
  • trunk/src/VBox/Frontends/VirtualBox/src/selector/UISelectorWindow.h

    r70029 r70185  
    9393      * @param  fUpdateSnapshots  Brings whether tools should be updated. */
    9494    void sltHandleChooserPaneIndexChange(bool fUpdateDetails = true,
    95                                          bool fUpdateSnapshots = true);
     95                                         bool fUpdateSnapshots = true,
     96                                         bool fUpdateLogViewer = true);
    9697
    9798    /** Handles signal about medium-enumeration finished. */
  • trunk/src/VBox/Frontends/VirtualBox/src/selector/UIToolsPaneMachine.cpp

    r69726 r70185  
    3232# include "UIToolsPaneMachine.h"
    3333# include "UIVMItem.h"
     34# include "UIVMLogViewerWidget.h"
    3435
    3536/* Other VBox includes: */
     
    4748    , m_pPaneDetails(0)
    4849    , m_pPaneSnapshots(0)
     50    , m_pPaneLogViewer(0)
    4951{
    5052    /* Prepare: */
     
    141143                break;
    142144            }
     145            case ToolTypeMachine_LogViewer:
     146            {
     147                /* Create the Logviewer pane: */
     148                m_pPaneLogViewer = new UIVMLogViewerWidget(EmbedTo_Stack);
     149                AssertPtrReturnVoid(m_pPaneLogViewer);
     150                {
     151                    /* Configure pane: */
     152                    m_pPaneLogViewer->setProperty("ToolType", QVariant::fromValue(ToolTypeMachine_LogViewer));
     153
     154                    /* Add into layout: */
     155                    m_pLayout->addWidget(m_pPaneLogViewer);
     156                    m_pLayout->setCurrentWidget(m_pPaneLogViewer);
     157                }
     158                break;
     159            }
    143160            default:
    144161                AssertFailedReturnVoid();
     
    164181            case ToolTypeMachine_Details:   m_pPaneDetails = 0; break;
    165182            case ToolTypeMachine_Snapshots: m_pPaneSnapshots = 0; break;
     183            case ToolTypeMachine_LogViewer: m_pPaneLogViewer = 0; break;
    166184            default: break;
    167185        }
     
    203221void UIToolsPaneMachine::setMachine(const CMachine &comMachine)
    204222{
    205     /* Update snapshots pane: */
    206     AssertPtrReturnVoid(m_pPaneSnapshots);
    207     m_pPaneSnapshots->setMachine(comMachine);
     223    /* Update snapshots pane is it is open: */
     224    if(isToolOpened(ToolTypeMachine_Snapshots))
     225    {
     226        AssertPtrReturnVoid(m_pPaneSnapshots);
     227        m_pPaneSnapshots->setMachine(comMachine);
     228    }
     229    /* Update logviewer pane is it is open: */
     230    if(isToolOpened(ToolTypeMachine_LogViewer))
     231    {
     232        AssertPtrReturnVoid(m_pPaneLogViewer);
     233        m_pPaneLogViewer->setMachine(comMachine);
     234    }
    208235}
    209236
     
    265292                                              "<u>restore</u> (make current) and observe their properties. Allows to "
    266293                                              "<u>edit</u> snapshot attributes like <u>name</u> and <u>description</u>."));
     294        QAction *pAction3 = m_pActionPool->action(UIActionIndexST_M_Tools_M_Machine_S_LogViewer);
     295        m_pPaneDesktop->addToolDescription(pAction3,
     296                                           tr("Tool to display  virtual machine (VM) logs. "));
    267297    }
    268298}
  • trunk/src/VBox/Frontends/VirtualBox/src/selector/UIToolsPaneMachine.h

    r68304 r70185  
    3333class UIDesktopPane;
    3434class UIGDetails;
     35class UIVMLogViewerWidget;
    3536class UISnapshotPane;
    3637class UIVMItem;
     
    103104
    104105    /** Holds the stacked-layout instance. */
    105     QStackedLayout *m_pLayout;
     106    QStackedLayout      *m_pLayout;
    106107    /** Holds the Desktop pane instance. */
    107     UIDesktopPane  *m_pPaneDesktop;
     108    UIDesktopPane       *m_pPaneDesktop;
    108109    /** Holds the Details pane instance. */
    109     UIGDetails     *m_pPaneDetails;
     110    UIGDetails          *m_pPaneDetails;
    110111    /** Holds the Snapshots pane instance. */
    111     UISnapshotPane *m_pPaneSnapshots;
     112    UISnapshotPane      *m_pPaneSnapshots;
     113    /** Holds the Logviewer pane instance. */
     114    UIVMLogViewerWidget *m_pPaneLogViewer;
    112115};
    113116
  • trunk/src/VBox/Frontends/VirtualBox/src/selector/UIToolsToolbar.cpp

    r69260 r70185  
    219219        m_pActionPool->action(UIActionIndexST_M_Tools_M_Machine_S_Snapshots)
    220220            ->setProperty("ToolTypeMachine", QVariant::fromValue(ToolTypeMachine_Snapshots));
     221
     222        /* Add 'LogViewer' action: */
     223        pMenuMachine->addAction(m_pActionPool->action(UIActionIndexST_M_Tools_M_Machine_S_LogViewer));
     224        connect(m_pActionPool->action(UIActionIndexST_M_Tools_M_Machine_S_LogViewer), &UIAction::triggered,
     225                this, &UIToolsToolbar::sltHandleOpenToolMachine);
     226        m_pActionPool->action(UIActionIndexST_M_Tools_M_Machine_S_LogViewer)
     227            ->setProperty("ToolTypeMachine", QVariant::fromValue(ToolTypeMachine_LogViewer));
    221228    }
    222229
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