VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/UIVMLogViewer.cpp@ 43138

Last change on this file since 43138 was 41587, checked in by vboxsync, 12 years ago

FE/Qt: 6227: Decrease GUI build time: Rework COM wrappers generator to create one header per each COM interface. Update all GUI files to use newly generated headers.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Revision Author Id
File size: 22.3 KB
Line 
1/* $Id: UIVMLogViewer.cpp 41587 2012-06-06 04:19:03Z vboxsync $ */
2/** @file
3 *
4 * VBox frontends: Qt4 GUI ("VirtualBox"):
5 * UIVMLogViewer class implementation
6 */
7
8/*
9 * Copyright (C) 2008-2011 Oracle Corporation
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 */
19
20#ifdef VBOX_WITH_PRECOMPILED_HEADERS
21# include "precomp.h"
22#else /* !VBOX_WITH_PRECOMPILED_HEADERS */
23
24/* Qt includes: */
25#include <QCheckBox>
26#include <QDateTime>
27#include <QDir>
28#include <QFileDialog>
29#include <QKeyEvent>
30#include <QLabel>
31#include <QScrollBar>
32#include <QTextEdit>
33
34/* GUI includes: */
35#include "UIVMLogViewer.h"
36#include "QITabWidget.h"
37#include "UIIconPool.h"
38#include "UISpecialControls.h"
39#include "VBoxGlobal.h"
40#include "UIMessageCenter.h"
41#include "VBoxUtils.h"
42
43/* COM includes: */
44#include "COMEnums.h"
45#include "CSystemProperties.h"
46
47#endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
48
49/* VM Log Viewer search panel: */
50class UIVMLogViewerSearchPanel : public QIWithRetranslateUI<QWidget>
51{
52 Q_OBJECT;
53
54public:
55
56 /* Constructor: */
57 UIVMLogViewerSearchPanel(QWidget *pParent, UIVMLogViewer *pViewer)
58 : QIWithRetranslateUI<QWidget>(pParent)
59 , m_pViewer(pViewer)
60 , m_pCloseButton(0)
61 , m_pSearchLabel(0), m_pSearchEditor(0)
62 , m_pNextPrevButtons(0)
63 , m_pCaseSensitiveCheckBox(0)
64 , m_pWarningSpacer(0), m_pWarningIcon(0), m_pWarningLabel(0)
65 {
66 /* Close button: */
67 m_pCloseButton = new UIMiniCancelButton(this);
68
69 /* Search field: */
70 m_pSearchLabel = new QLabel(this);
71 m_pSearchEditor = new UISearchField(this);
72 m_pSearchEditor->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
73 m_pSearchLabel->setBuddy(m_pSearchEditor);
74
75 /* Next/Previous buttons: */
76 m_pNextPrevButtons = new UIRoundRectSegmentedButton(2, this);
77 m_pNextPrevButtons->setEnabled(0, false);
78 m_pNextPrevButtons->setEnabled(1, false);
79#ifndef Q_WS_MAC
80 /* No icons on the Mac: */
81 m_pNextPrevButtons->setIcon(0, UIIconPool::defaultIcon(UIIconPool::ArrowBackIcon, this));
82 m_pNextPrevButtons->setIcon(1, UIIconPool::defaultIcon(UIIconPool::ArrowForwardIcon, this));
83#endif /* !Q_WS_MAC */
84
85 /* Case sensitive check-box: */
86 m_pCaseSensitiveCheckBox = new QCheckBox(this);
87
88 /* Warning label: */
89 m_pWarningSpacer = new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::Minimum);
90 m_pWarningIcon = new QLabel(this);
91 m_pWarningIcon->hide();
92 QIcon icon = UIIconPool::defaultIcon(UIIconPool::MessageBoxWarningIcon, this);
93 if (!icon.isNull())
94 m_pWarningIcon->setPixmap(icon.pixmap(16, 16));
95 m_pWarningLabel = new QLabel(this);
96 m_pWarningLabel->hide();
97 QSpacerItem *pSpacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum);
98
99#ifdef VBOX_DARWIN_USE_NATIVE_CONTROLS
100 QFont font = m_pSearchLabel->font();
101 font.setPointSize(::darwinSmallFontSize());
102 m_pSearchLabel->setFont(font);
103 m_pCaseSensitiveCheckBox->setFont(font);
104 m_pWarningLabel->setFont(font);
105#endif /* VBOX_DARWIN_USE_NATIVE_CONTROLS */
106
107 /* Placing widgets: */
108 QHBoxLayout *pMainLayout = new QHBoxLayout(this);
109 pMainLayout->setSpacing(5);
110 pMainLayout->setContentsMargins(0, 0, 0, 0);
111 pMainLayout->addWidget(m_pCloseButton);
112 pMainLayout->addWidget(m_pSearchLabel);
113 pMainLayout->addWidget(m_pSearchEditor);
114 pMainLayout->addWidget(m_pNextPrevButtons);
115 pMainLayout->addWidget(m_pCaseSensitiveCheckBox);
116 pMainLayout->addItem(m_pWarningSpacer);
117 pMainLayout->addWidget(m_pWarningIcon);
118 pMainLayout->addWidget(m_pWarningLabel);
119 pMainLayout->addItem(pSpacer);
120
121 /* Setup focus proxy: */
122 setFocusProxy(m_pCaseSensitiveCheckBox);
123
124 /* Setup connections: */
125 connect(m_pCloseButton, SIGNAL(clicked()), this, SLOT(hide()));
126 connect(m_pSearchEditor, SIGNAL(textChanged(const QString &)),
127 this, SLOT(findCurrent(const QString &)));
128 connect(m_pNextPrevButtons, SIGNAL(clicked(int)), this, SLOT(find(int)));
129
130 /* Retranslate finally: */
131 retranslateUi();
132 }
133
134private slots:
135
136 /* Slot to find specified tag,
137 * called by next/previous buttons: */
138 void find(int iButton)
139 {
140 if (iButton)
141 findNext();
142 else
143 findBack();
144 }
145
146 /* Slot to find specified tag,
147 * called when text changed in search editor: */
148 void findCurrent(const QString &strSearchString)
149 {
150 m_pNextPrevButtons->setEnabled(0, strSearchString.length());
151 m_pNextPrevButtons->setEnabled(1, strSearchString.length());
152 toggleWarning(!strSearchString.length());
153 if (strSearchString.length())
154 search(true, true);
155 else
156 {
157 QTextEdit *pBrowser = m_pViewer->currentLogPage();
158 if (pBrowser && pBrowser->textCursor().hasSelection())
159 {
160 QTextCursor cursor = pBrowser->textCursor();
161 cursor.setPosition(cursor.anchor());
162 pBrowser->setTextCursor(cursor);
163 }
164 }
165 }
166
167private:
168
169 /* Translation stuff: */
170 void retranslateUi()
171 {
172 m_pCloseButton->setToolTip(UIVMLogViewer::tr("Close the search panel"));
173
174 m_pSearchLabel->setText(QString("%1 ").arg(UIVMLogViewer::tr("&Find")));
175 m_pSearchEditor->setToolTip(UIVMLogViewer::tr("Enter a search string here"));
176
177 m_pNextPrevButtons->setTitle(0, UIVMLogViewer::tr("&Previous"));
178 m_pNextPrevButtons->setToolTip(0, UIVMLogViewer::tr("Search for the previous occurrence of the string"));
179 m_pNextPrevButtons->setTitle(1, UIVMLogViewer::tr("&Next"));
180 m_pNextPrevButtons->setToolTip(1, UIVMLogViewer::tr("Search for the next occurrence of the string"));
181
182 m_pCaseSensitiveCheckBox->setText(UIVMLogViewer::tr("C&ase Sensitive"));
183 m_pCaseSensitiveCheckBox->setToolTip(UIVMLogViewer::tr("Perform case sensitive search (when checked)"));
184
185 m_pWarningLabel->setText(UIVMLogViewer::tr("String not found"));
186 }
187
188 /* Key press filter: */
189 void keyPressEvent(QKeyEvent *pEvent)
190 {
191 switch (pEvent->key())
192 {
193 /* Process Enter press as 'search next',
194 * performed for any search panel widget: */
195 case Qt::Key_Enter:
196 case Qt::Key_Return:
197 {
198 if (pEvent->modifiers() == 0 ||
199 pEvent->modifiers() & Qt::KeypadModifier)
200 {
201 m_pNextPrevButtons->animateClick(1);
202 return;
203 }
204 break;
205 }
206 default:
207 break;
208 }
209 QWidget::keyPressEvent(pEvent);
210 }
211
212 /* Event filter, used for keyboard processing: */
213 bool eventFilter(QObject *pObject, QEvent *pEvent)
214 {
215 /* Depending on event-type: */
216 switch (pEvent->type())
217 {
218 /* Process key press only: */
219 case QEvent::KeyPress:
220 {
221 /* Cast to corresponding key press event: */
222 QKeyEvent *pKeyEvent = static_cast<QKeyEvent*>(pEvent);
223
224 /* Handle F3/Shift+F3 as search next/previous shortcuts: */
225 if (pKeyEvent->key() == Qt::Key_F3)
226 {
227 if (pKeyEvent->QInputEvent::modifiers() == 0)
228 {
229 m_pNextPrevButtons->animateClick(1);
230 return true;
231 }
232 else if (pKeyEvent->QInputEvent::modifiers() == Qt::ShiftModifier)
233 {
234 m_pNextPrevButtons->animateClick(0);
235 return true;
236 }
237 }
238 /* Handle Ctrl+F key combination as a shortcut to focus search field: */
239 else if (pKeyEvent->QInputEvent::modifiers() == Qt::ControlModifier &&
240 pKeyEvent->key() == Qt::Key_F)
241 {
242 if (m_pViewer->currentLogPage())
243 {
244 if (isHidden())
245 show();
246 m_pSearchEditor->setFocus();
247 return true;
248 }
249 }
250 /* Handle alpha-numeric keys to implement the "find as you type" feature: */
251 else if ((pKeyEvent->QInputEvent::modifiers() & ~Qt::ShiftModifier) == 0 &&
252 pKeyEvent->key() >= Qt::Key_Exclam && pKeyEvent->key() <= Qt::Key_AsciiTilde)
253 {
254 if (m_pViewer->currentLogPage())
255 {
256 if (isHidden())
257 show();
258 m_pSearchEditor->setFocus();
259 m_pSearchEditor->insert(pKeyEvent->text());
260 return true;
261 }
262 }
263 break;
264 }
265 default:
266 break;
267 }
268 /* Call to base-class: */
269 return QWidget::eventFilter(pObject, pEvent);
270 }
271
272 /* Show event reimplementation: */
273 void showEvent(QShowEvent *pEvent)
274 {
275 QWidget::showEvent(pEvent);
276 m_pSearchEditor->setFocus();
277 m_pSearchEditor->selectAll();
278 }
279
280 /* Hide event reimplementation: */
281 void hideEvent(QHideEvent *pEvent)
282 {
283 QWidget *pFocus = QApplication::focusWidget();
284 if (pFocus && pFocus->parent() == this)
285 focusNextPrevChild(true);
286 QWidget::hideEvent(pEvent);
287 }
288
289 /* Search routine: */
290 void search(bool fForward, bool fStartCurrent = false)
291 {
292 QTextEdit *pBrowser = m_pViewer->currentLogPage();
293 if (!pBrowser) return;
294
295 QTextCursor cursor = pBrowser->textCursor();
296 int iPos = cursor.position();
297 int iAnc = cursor.anchor();
298
299 QString strText = pBrowser->toPlainText();
300 int iDiff = fStartCurrent ? 0 : 1;
301
302 int iResult = -1;
303 if (fForward && (fStartCurrent || iPos < strText.size() - 1))
304 iResult = strText.indexOf(m_pSearchEditor->text(), iAnc + iDiff,
305 m_pCaseSensitiveCheckBox->isChecked() ?
306 Qt::CaseSensitive : Qt::CaseInsensitive);
307 else if (!fForward && iAnc > 0)
308 iResult = strText.lastIndexOf(m_pSearchEditor->text(), iAnc - 1,
309 m_pCaseSensitiveCheckBox->isChecked() ?
310 Qt::CaseSensitive : Qt::CaseInsensitive);
311
312 if (iResult != -1)
313 {
314 cursor.movePosition(QTextCursor::Start,
315 QTextCursor::MoveAnchor);
316 cursor.movePosition(QTextCursor::NextCharacter,
317 QTextCursor::MoveAnchor, iResult);
318 cursor.movePosition(QTextCursor::NextCharacter,
319 QTextCursor::KeepAnchor,
320 m_pSearchEditor->text().size());
321 pBrowser->setTextCursor(cursor);
322 }
323
324 toggleWarning(iResult != -1);
325 }
326
327 /* Search routine wrappers: */
328 void findNext() { search(true); }
329 void findBack() { search(false); }
330
331 /* Function to show/hide search border warning: */
332 void toggleWarning(bool fHide)
333 {
334 m_pWarningSpacer->changeSize(fHide ? 0 : 16, 0, QSizePolicy::Fixed, QSizePolicy::Minimum);
335 if (!fHide)
336 m_pSearchEditor->markError();
337 else
338 m_pSearchEditor->unmarkError();
339 m_pWarningIcon->setHidden(fHide);
340 m_pWarningLabel->setHidden(fHide);
341 }
342
343 /* Widgets: */
344 UIVMLogViewer *m_pViewer;
345 UIMiniCancelButton *m_pCloseButton;
346 QLabel *m_pSearchLabel;
347 UISearchField *m_pSearchEditor;
348 UIRoundRectSegmentedButton *m_pNextPrevButtons;
349 QCheckBox *m_pCaseSensitiveCheckBox;
350 QSpacerItem *m_pWarningSpacer;
351 QLabel *m_pWarningIcon;
352 QLabel *m_pWarningLabel;
353};
354
355/* VM Log Viewer array: */
356VMLogViewerMap UIVMLogViewer::m_viewers = VMLogViewerMap();
357
358void UIVMLogViewer::showLogViewerFor(QWidget *pCenterWidget, const CMachine &machine)
359{
360 /* If there is no corresponding VM Log Viewer created: */
361 if (!m_viewers.contains(machine.GetName()))
362 {
363 /* Creating new VM Log Viewer: */
364 UIVMLogViewer *pLogViewer = new UIVMLogViewer(pCenterWidget, Qt::Window, machine);
365 pLogViewer->setAttribute(Qt::WA_DeleteOnClose);
366 m_viewers[machine.GetName()] = pLogViewer;
367 }
368
369 /* Show VM Log Viewer: */
370 UIVMLogViewer *pViewer = m_viewers[machine.GetName()];
371 pViewer->show();
372 pViewer->raise();
373 pViewer->setWindowState(pViewer->windowState() & ~Qt::WindowMinimized);
374 pViewer->activateWindow();
375}
376
377UIVMLogViewer::UIVMLogViewer(QWidget *pParent, Qt::WindowFlags flags, const CMachine &machine)
378 : QIWithRetranslateUI2<QMainWindow>(pParent, flags)
379 , m_fIsPolished(false)
380 , m_machine(machine)
381{
382 /* Apply UI decorations: */
383 Ui::UIVMLogViewer::setupUi(this);
384
385 /* Apply window icons: */
386 setWindowIcon(UIIconPool::iconSetFull(QSize(32, 32), QSize(16, 16),
387 ":/vm_show_logs_32px.png",
388 ":/show_logs_16px.png"));
389
390 /* Create VM Log Vewer container: */
391 m_pViewerContainer = new QITabWidget(centralWidget());
392 m_pMainLayout->insertWidget(0, m_pViewerContainer);
393
394 /* Create VM Log Vewer search panel: */
395 m_pSearchPanel = new UIVMLogViewerSearchPanel(centralWidget(), this);
396 centralWidget()->installEventFilter(m_pSearchPanel);
397 m_pSearchPanel->hide();
398 m_pMainLayout->insertWidget(1, m_pSearchPanel);
399
400 /* Add missing buttons & retrieve standard buttons: */
401 mBtnHelp = m_pButtonBox->button(QDialogButtonBox::Help);
402 mBtnFind = m_pButtonBox->addButton(QString::null, QDialogButtonBox::ActionRole);
403 mBtnRefresh = m_pButtonBox->addButton(QString::null, QDialogButtonBox::ActionRole);
404 mBtnClose = m_pButtonBox->button(QDialogButtonBox::Close);
405 mBtnSave = m_pButtonBox->button(QDialogButtonBox::Save);
406
407 /* Setup connections: */
408 connect(m_pButtonBox, SIGNAL(helpRequested()), &msgCenter(), SLOT(sltShowHelpHelpDialog()));
409 connect(mBtnFind, SIGNAL(clicked()), this, SLOT(search()));
410 connect(mBtnRefresh, SIGNAL(clicked()), this, SLOT(refresh()));
411 connect(mBtnClose, SIGNAL(clicked()), this, SLOT(close()));
412 connect(mBtnSave, SIGNAL(clicked()), this, SLOT(save()));
413
414 /* Reading log files: */
415 refresh();
416
417 /* Loading language constants */
418 retranslateUi();
419}
420
421UIVMLogViewer::~UIVMLogViewer()
422{
423 if (!m_machine.isNull())
424 m_viewers.remove(m_machine.GetName());
425}
426
427QTextEdit* UIVMLogViewer::currentLogPage()
428{
429 if (m_pViewerContainer->isEnabled())
430 {
431 QWidget *pContainer = m_pViewerContainer->currentWidget();
432 QTextEdit *pBrowser = pContainer->findChild<QTextEdit*>();
433 Assert(pBrowser);
434 return pBrowser ? pBrowser : 0;
435 }
436 else
437 return 0;
438}
439
440void UIVMLogViewer::search()
441{
442 m_pSearchPanel->isHidden() ? m_pSearchPanel->show() : m_pSearchPanel->hide();
443}
444
445void UIVMLogViewer::refresh()
446{
447 /* Clearing old data if any: */
448 m_book.clear();
449 m_pViewerContainer->setEnabled(true);
450 while (m_pViewerContainer->count())
451 {
452 QWidget *pFirstPage = m_pViewerContainer->widget(0);
453 m_pViewerContainer->removeTab(0);
454 delete pFirstPage;
455 }
456
457 bool isAnyLogPresent = false;
458
459 const CSystemProperties &sys = vboxGlobal().virtualBox().GetSystemProperties();
460 int cMaxLogs = sys.GetLogHistoryCount();
461 for (int i=0; i <= cMaxLogs; ++i)
462 {
463 /* Query the log file name for index i: */
464 QString strFileName = m_machine.QueryLogFilename(i);
465 if (!strFileName.isEmpty())
466 {
467 /* Try to read the log file with the index i: */
468 ULONG uOffset = 0;
469 QString strText;
470 while (true)
471 {
472 QVector<BYTE> data = m_machine.ReadLog(i, uOffset, _1M);
473 if (data.size() == 0)
474 break;
475 strText.append(QString::fromUtf8((char*)data.data(), data.size()));
476 uOffset += data.size();
477 }
478 /* Anything read at all? */
479 if (uOffset > 0)
480 {
481 /* Create a log viewer page and append the read text to it: */
482 QTextEdit *pLogViewer = createLogPage(QFileInfo(strFileName).fileName());
483 pLogViewer->setPlainText(strText);
484 /* Add the actual file name and the QTextEdit containing the content to a list: */
485 m_book << qMakePair(strFileName, pLogViewer);
486 isAnyLogPresent = true;
487 }
488 }
489 }
490
491 /* Create an empty log page if there are no logs at all: */
492 if (!isAnyLogPresent)
493 {
494 QTextEdit *pDummyLog = createLogPage("VBox.log");
495 pDummyLog->setWordWrapMode(QTextOption::WordWrap);
496 pDummyLog->setHtml(tr("<p>No log files found. Press the "
497 "<b>Refresh</b> button to rescan the log folder "
498 "<nobr><b>%1</b></nobr>.</p>")
499 .arg(m_machine.GetLogFolder()));
500 /* We don't want it to remain white: */
501 QPalette pal = pDummyLog->palette();
502 pal.setColor(QPalette::Base, pal.color(QPalette::Window));
503 pDummyLog->setPalette(pal);
504 }
505
506 /* Show the first tab widget's page after the refresh: */
507 m_pViewerContainer->setCurrentIndex(0);
508
509 /* Enable/Disable save button & tab widget according log presence: */
510 mBtnFind->setEnabled(isAnyLogPresent);
511 mBtnSave->setEnabled(isAnyLogPresent);
512 m_pViewerContainer->setEnabled(isAnyLogPresent);
513}
514
515bool UIVMLogViewer::close()
516{
517 m_pSearchPanel->hide();
518 return QMainWindow::close();
519}
520
521void UIVMLogViewer::save()
522{
523 /* Prepare "save as" dialog: */
524 QFileInfo fileInfo(m_book.at(m_pViewerContainer->currentIndex()).first);
525 QDateTime dtInfo = fileInfo.lastModified();
526 QString strDtString = dtInfo.toString("yyyy-MM-dd-hh-mm-ss");
527 QString strDefaultFileName = QString("%1-%2.log").arg(m_machine.GetName()).arg(strDtString);
528 QString strDefaultFullName = QDir::toNativeSeparators(QDir::home().absolutePath() + "/" + strDefaultFileName);
529 QString strNewFileName = QFileDialog::getSaveFileName(this, tr("Save VirtualBox Log As"), strDefaultFullName);
530
531 /* Copy log into the file: */
532 if (!strNewFileName.isEmpty())
533 QFile::copy(m_machine.QueryLogFilename(m_pViewerContainer->currentIndex()), strNewFileName);
534}
535
536void UIVMLogViewer::retranslateUi()
537{
538 /* Translate uic generated strings: */
539 Ui::UIVMLogViewer::retranslateUi(this);
540
541 /* Setup a dialog caption: */
542 if (!m_machine.isNull())
543 setWindowTitle(tr("%1 - VirtualBox Log Viewer").arg(m_machine.GetName()));
544
545 /* Translate other tags: */
546 mBtnFind->setText(tr("&Find"));
547 mBtnRefresh->setText(tr("&Refresh"));
548 mBtnSave->setText(tr("&Save"));
549 mBtnClose->setText(tr("Close"));
550}
551
552void UIVMLogViewer::showEvent(QShowEvent *pEvent)
553{
554 QMainWindow::showEvent(pEvent);
555
556 /* One may think that QWidget::polish() is the right place to do things
557 * below, but apparently, by the time when QWidget::polish() is called,
558 * the widget style & layout are not fully done, at least the minimum
559 * size hint is not properly calculated. Since this is sometimes necessary,
560 * we provide our own "polish" implementation. */
561
562 if (m_fIsPolished)
563 return;
564
565 m_fIsPolished = true;
566
567 /* Resize the whole log-viewer to fit 80 symbols in
568 * text-browser for the first time started: */
569 QTextEdit *pFirstPage = currentLogPage();
570 if (pFirstPage)
571 {
572 int fullWidth = pFirstPage->fontMetrics().width(QChar('x')) * 80 +
573 pFirstPage->verticalScrollBar()->width() +
574 pFirstPage->frameWidth() * 2 +
575 /* m_pViewerContainer margin */ 10 * 2 +
576 /* CentralWidget margin */ 10 * 2;
577 resize(fullWidth, height());
578 }
579
580 /* Make sure the log view widget has the focus */
581 QWidget *pCurrentLogPage = currentLogPage();
582 if (pCurrentLogPage)
583 pCurrentLogPage->setFocus();
584
585 /* Explicit widget centering relatively to it's parent: */
586 VBoxGlobal::centerWidget(this, parentWidget(), false);
587}
588
589void UIVMLogViewer::keyPressEvent(QKeyEvent *pEvent)
590{
591 /* Depending on key pressed: */
592 switch (pEvent->key())
593 {
594 /* Process key escape as VM Log Viewer close: */
595 case Qt::Key_Escape:
596 {
597 mBtnClose->animateClick();
598 return;
599 }
600 /* Precess Back key as switch to previous tab: */
601 case Qt::Key_Back:
602 {
603 if (m_pViewerContainer->currentIndex() > 0)
604 {
605 m_pViewerContainer->setCurrentIndex(m_pViewerContainer->currentIndex() - 1);
606 return;
607 }
608 break;
609 }
610 /* Precess Forward key as switch to next tab: */
611 case Qt::Key_Forward:
612 {
613 if (m_pViewerContainer->currentIndex() < m_pViewerContainer->count())
614 {
615 m_pViewerContainer->setCurrentIndex(m_pViewerContainer->currentIndex() + 1);
616 return;
617 }
618 break;
619 }
620 default:
621 break;
622 }
623 QMainWindow::keyReleaseEvent(pEvent);
624}
625
626QTextEdit* UIVMLogViewer::createLogPage(const QString &strName)
627{
628 QWidget *pPageContainer = new QWidget;
629 QVBoxLayout *pPageLayout = new QVBoxLayout(pPageContainer);
630 QTextEdit *pLogViewer = new QTextEdit(pPageContainer);
631 pPageLayout->addWidget(pLogViewer);
632 pPageLayout->setContentsMargins(10, 10, 10, 10);
633
634 QFont font = pLogViewer->currentFont();
635 font.setFamily("Courier New,courier");
636 pLogViewer->setFont(font);
637 pLogViewer->setWordWrapMode(QTextOption::NoWrap);
638 pLogViewer->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
639 pLogViewer->setReadOnly(true);
640
641 m_pViewerContainer->addTab(pPageContainer, strName);
642 return pLogViewer;
643}
644
645#include "UIVMLogViewer.moc"
646
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use