Changeset 70539 in vbox for trunk/src/VBox/Frontends
- Timestamp:
- Jan 11, 2018 2:11:16 PM (7 years ago)
- Location:
- trunk/src/VBox/Frontends/VirtualBox
- Files:
-
- 8 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk
r70500 r70539 335 335 src/hostnetwork/UIHostNetworkDetailsWidget.h \ 336 336 src/hostnetwork/UIHostNetworkManager.h \ 337 src/logviewer/UIVMLogPage.h \ 337 338 src/logviewer/UIVMLogViewerBookmarksPanel.h \ 338 339 src/logviewer/UIVMLogViewerDialog.h \ … … 547 548 src/globals/UIMainEventListener.cpp \ 548 549 src/globals/UIThreadPool.cpp \ 550 src/logviewer/UIVMLogPage.cpp \ 549 551 src/logviewer/UIVMLogViewerFilterPanel.cpp \ 550 src/logviewer/UIVMLogViewerWidget.cpp \551 552 src/medium/UIMediumEnumerator.cpp \ 552 553 src/runtime/UIActionPoolRuntime.cpp \ … … 653 654 src/hostnetwork/UIHostNetworkManager.cpp \ 654 655 src/hostnetwork/UIHostNetworkUtils.cpp \ 656 src/logviewer/UIVMLogPage.cpp \ 655 657 src/logviewer/UIVMLogViewerBookmarksPanel.cpp \ 656 658 src/logviewer/UIVMLogViewerDialog.cpp \ -
trunk/src/VBox/Frontends/VirtualBox/src/logviewer/UIVMLogPage.cpp
r70529 r70539 38 38 # include "UIIconPool.h" 39 39 # include "UIMessageCenter.h" 40 # include "UIVMLog ViewerWidget.h"40 # include "UIVMLogPage.h" 41 41 # include "UIVMLogViewerBookmarksPanel.h" 42 42 # include "UIVMLogViewerFilterPanel.h" … … 95 95 } 96 96 97 void clearMarkingsVector() 98 { 99 m_markingsVector.clear(); 100 } 101 97 102 protected: 98 103 … … 130 135 131 136 public: 132 UIVMLogViewerTextEdit(QWidget* parent = 0, const QString& logFileName = QString()) 133 :QPlainTextEdit(parent), 134 m_logFileName(logFileName) 137 UIVMLogViewerTextEdit(QWidget* parent = 0) 138 :QPlainTextEdit(parent) 135 139 { 136 140 //setStyleSheet("background-color: rgba(240, 240, 240, 75%) "); 137 }138 139 const QString& logFileName() const140 {141 return m_logFileName;142 141 } 143 142 … … 179 178 /* Line number and text at the context menu position */ 180 179 LogBookmark m_iContextMenuBookmark; 181 /* Name of the log file this text edit created to show. */182 QString m_logFileName;183 180 }; 184 181 185 182 186 UIVMLog ViewerWidget::UIVMLogViewerWidget(EmbedTo enmEmbedding, QWidget *pParent /* = 0 */, const CMachine &machine /* = CMachine()*/)183 UIVMLogPage::UIVMLogPage(QWidget *pParent /* = 0 */, int tabIndex /*= -1 */) 187 184 : 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)195 185 , 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 { 207 189 prepare(); 208 190 } 209 191 210 UIVMLogViewerWidget::~UIVMLogViewerWidget() 211 { 212 /* Cleanup VM Log-Viewer: */ 192 UIVMLogPage::~UIVMLogPage() 193 { 213 194 cleanup(); 214 195 } 215 196 216 int UIVMLog ViewerWidget::defaultLogPageWidth() const217 { 218 if (!m_p ViewerContainer)197 int UIVMLogPage::defaultLogPageWidth() const 198 { 199 if (!m_pPlainTextEdit) 219 200 return 0; 220 201 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 211 void 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 226 void 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 255 QPlainTextEdit *UIVMLogPage::textEdit() 256 { 257 return m_pPlainTextEdit; 258 } 259 260 QTextDocument* UIVMLogPage::document() 261 { 262 if (!m_pPlainTextEdit) 223 263 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 267 void UIVMLogPage::setTabIndex(int index) 268 { 269 m_tabIndex = index; 270 } 271 272 int UIVMLogPage::tabIndex() const 273 { 274 return m_tabIndex; 275 } 276 277 void UIVMLogPage::retranslateUi() 278 { 279 } 280 281 void UIVMLogPage::cleanup() 282 { 283 } 284 285 void UIVMLogPage::setLogString(const QString &strLog) 286 { 287 m_strLog = strLog; 288 } 289 290 const QString& UIVMLogPage::logString() const 291 { 292 return m_strLog; 293 } 294 295 void UIVMLogPage::setFileName(const QString &strFileName) 296 { 297 m_strFileName = strFileName; 298 } 299 300 const QString& UIVMLogPage::fileName() const 301 { 302 return m_strFileName; 303 } 304 305 void 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 315 void 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 322 void UIVMLogPage::setScrollBarMarkingsVector(const QVector<float> &vector) 323 { 324 if (!m_pPlainTextEdit) 245 325 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 332 void UIVMLogPage::clearScrollBarMarkingsVector() 333 { 334 if (!m_pPlainTextEdit) 255 335 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 342 void UIVMLogPage::documentUndo() 343 { 344 if (!m_pPlainTextEdit) 265 345 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 16 16 */ 17 17 18 #ifndef ___UIVMLog ViewerWidget_h___19 #define ___UIVMLog ViewerWidget_h___18 #ifndef ___UIVMLogPage_h___ 19 #define ___UIVMLogPage_h___ 20 20 21 21 /* Qt includes: */ … … 35 35 class QITabWidget; 36 36 class QPlainTextEdit; 37 class Q VBoxLayout;37 class QHBoxLayout; 38 38 class UIToolBar; 39 39 class UIVMLogViewerBookmarksPanel; … … 43 43 44 44 /* Type definitions: */ 45 /** value is the content of the log file */46 typedef QMap<QPlainTextEdit*, QString> VMLogMap;47 45 /** first is line number, second is block text */ 48 46 typedef QPair<int, QString> LogBookmark; 49 /** key is log file name, value is a vector of bookmarks. */50 typedef QMap<QString, QVector<LogBookmark> > BookmarkMap;51 47 52 53 /** QIMainWindow extension 54 * providing GUI with VirtualBox LogViewer. */ 55 class UIVMLogViewerWidget : public QIWithRetranslateUI<QWidget> 48 class UIVMLogPage : public QIWithRetranslateUI<QWidget> 56 49 { 57 50 Q_OBJECT; 58 51 59 52 public: 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); 63 55 /** Destructs the VM Log-Viewer. */ 64 ~UIVMLog ViewerWidget();56 ~UIVMLogPage(); 65 57 /** Returns the width of the current log page. return 0 if there is no current log page: */ 66 58 int defaultLogPageWidth() const; 67 59 68 /** Returns the menu. */69 Q Menu *menu() const { return m_pMenu; }60 QPlainTextEdit *textEdit(); 61 QTextDocument *document(); 70 62 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; 75 65 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(); 78 86 79 87 protected: 80 88 81 /** Returns whether the window should be maximized when geometry being restored. */82 virtual bool shouldBeMaximized() const /* override */;83 84 89 private slots: 85 90 86 /** Handles refresh action triggering. */87 void sltRefresh();88 /** Handles save action triggering. */89 void sltSave();90 91 /** @name Bookmark related slots92 * @{ */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();110 91 111 92 private: 93 void prepare(); 94 void prepareWidgets(); 95 void cleanup(); 96 void retranslateUi(); 112 97 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; 123 106 124 /** Cleanups VM Log-Viewer. */ 125 void cleanup(); 126 /** @} */ 107 QVector<LogBookmark> m_bookmarkMap; 127 108 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;210 109 }; 211 110 212 #endif /* !___UIVMLog ViewerWidget_h___ */111 #endif /* !___UIVMLogPage_h___ */ -
trunk/src/VBox/Frontends/VirtualBox/src/logviewer/UIVMLogViewerFilterPanel.cpp
r70500 r70539 199 199 void UIVMLogViewerFilterPanel::filter() 200 200 { 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(); 204 207 m_iUnfilteredLineCount = 0; 205 208 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(); 209 212 if (!document) 210 213 return; 211 QStringList stringLines = strInputText->split("\n");214 QStringList stringLines = originalLogString->split("\n"); 212 215 m_iUnfilteredLineCount = stringLines.size(); 213 216 if (m_filterTermList.empty()) 214 217 { 215 document->setPlainText(* strInputText);218 document->setPlainText(*originalLogString); 216 219 emit sigFilterApplied(); 217 220 m_iFilteredLineCount = document->lineCount(); … … 238 241 239 242 /* Move the cursor position to end: */ 240 QTextCursor cursor = pCurrent Page->textCursor();243 QTextCursor cursor = pCurrentTextEdit->textCursor(); 241 244 cursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor); 242 pCurrent Page->setTextCursor(cursor);245 pCurrentTextEdit->setTextCursor(cursor); 243 246 244 247 emit sigFilterApplied(); … … 452 455 pKeyEvent->key() == Qt::Key_T) 453 456 { 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; 461 461 } 462 462 else if (pKeyEvent->key() == Qt::Key_Return && m_pFilterComboBox && m_pFilterComboBox->hasFocus()) -
trunk/src/VBox/Frontends/VirtualBox/src/logviewer/UIVMLogViewerPanel.cpp
r70529 r70539 23 23 # include <QComboBox> 24 24 # include <QHBoxLayout> 25 # if defined(RT_OS_SOLARIS)26 # include <QFontDatabase>27 # endif28 25 # include <QLabel> 29 # include <QLineEdit>30 26 # include <QPlainTextEdit> 31 # include <QPushButton>32 27 # include <QTextCursor> 33 28 # include <QToolButton> 34 # include <QScrollArea>35 29 36 30 /* GUI includes: */ 37 31 # include "UIIconPool.h" 38 32 # include "UISpecialControls.h" 33 # include "UIVMLogPage.h" 39 34 # include "UIVMLogViewerPanel.h" 40 35 # include "UIVMLogViewerWidget.h" … … 125 120 QWidget::hideEvent(pEvent); 126 121 } 122 123 QTextDocument *UIVMLogViewerPanel::textDocument() 124 { 125 QPlainTextEdit *pEdit = textEdit(); 126 if (!pEdit) 127 return 0; 128 return textEdit()->document(); 129 } 130 131 QPlainTextEdit *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 141 const 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 26 26 27 27 /* Forward declarations: */ 28 class QComboBox;29 28 class QHBoxLayout; 30 class QLabel; 31 class QLineEdit; 32 class QPushButton; 33 class UIVMFilterLineEdit; 29 class QPlainTextEdit; 30 class QTextDocument; 34 31 class UIMiniCancelButton; 35 32 class UIVMLogViewerWidget; … … 69 66 void hideEvent(QHideEvent *pEvent); 70 67 68 QTextDocument *textDocument(); 69 QPlainTextEdit *textEdit(); 70 /* Return the unmodified log. */ 71 const QString* logString() const; 71 72 private slots: 72 73 -
trunk/src/VBox/Frontends/VirtualBox/src/logviewer/UIVMLogViewerSearchPanel.cpp
r70519 r70539 35 35 # include "UIIconPool.h" 36 36 # include "UISpecialControls.h" 37 # include "UIVMLogPage.h" 37 38 # include "UIVMLogViewerSearchPanel.h" 38 39 # include "UIVMLogViewerWidget.h" … … 121 122 search(BackwardSearch, true); 122 123 emit sigHighlightingUpdated(); 124 return; 123 125 } 124 126 /* 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); 143 143 } 144 144 … … 147 147 if (!viewer()) 148 148 return; 149 QPlainTextEdit *pTextEdit = viewer()->currentLogPage(); 150 if (!pTextEdit) 151 return; 152 QTextDocument *pDocument = pTextEdit->document(); 149 150 QTextDocument *pDocument = textDocument(); 153 151 if (!pDocument) 154 152 return; … … 410 408 pKeyEvent->key() == Qt::Key_F) 411 409 { 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; 421 416 } 422 417 /* Handle alpha-numeric keys to implement the "find as you type" feature: */ … … 425 420 { 426 421 /* 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; 437 429 } 438 430 break; … … 457 449 void UIVMLogViewerSearchPanel::search(SearchDirection direction, bool highlight) 458 450 { 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(); 464 455 if (!pDocument) 465 456 return; … … 541 532 m_matchLocationVector.clear(); 542 533 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 550 538 configureInfoLabels(); 551 539 emit sigHighlightingUpdated(); -
trunk/src/VBox/Frontends/VirtualBox/src/logviewer/UIVMLogViewerSearchPanel.h
r70500 r70539 107 107 QTextDocument::FindFlags constructFindFlags(SearchDirection eDirection); 108 108 109 109 110 /** Holds the instance of search-label we create. */ 110 111 QLabel *m_pSearchLabel; -
trunk/src/VBox/Frontends/VirtualBox/src/logviewer/UIVMLogViewerWidget.cpp
r70529 r70539 38 38 # include "UIIconPool.h" 39 39 # include "UIMessageCenter.h" 40 # include "UIVMLogPage.h" 40 41 # include "UIVMLogViewerWidget.h" 41 42 # include "UIVMLogViewerBookmarksPanel.h" … … 52 53 53 54 54 /** We use a modified scrollbar style for our QPlainTextEdits to get the55 markings on the scrollbars correctly. The default scrollbarstyle does not56 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 QScrollBar81 {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 QPlainTextEdit124 {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() const140 {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 /// remove172 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 186 55 UIVMLogViewerWidget::UIVMLogViewerWidget(EmbedTo enmEmbedding, QWidget *pParent /* = 0 */, const CMachine &machine /* = CMachine() */) 187 56 : QIWithRetranslateUI<QWidget>(pParent) 188 57 , m_fIsPolished(false) 189 58 , m_comMachine(machine) 190 , m_pViewerContainer(0) 191 , m_iCurrentTabIndex(-1) 59 , m_pTabWidget(0) 192 60 , m_pSearchPanel(0) 193 61 , m_pFilterPanel(0) … … 216 84 int UIVMLogViewerWidget::defaultLogPageWidth() const 217 85 { 218 if (!m_p ViewerContainer)86 if (!m_pTabWidget) 219 87 return 0; 220 88 221 QWidget *pContainer = m_p ViewerContainer->currentWidget();89 QWidget *pContainer = m_pTabWidget->currentWidget(); 222 90 if (!pContainer) 223 91 return 0; … … 239 107 } 240 108 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);109 void 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); 249 117 } 250 118 251 119 void UIVMLogViewerWidget::sltDeleteAllBookmarks() 252 120 { 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 129 void 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); 272 140 273 141 } … … 297 165 { 298 166 /* 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); 304 173 /* 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); 310 181 delete pFirstPage; 311 182 } 312 183 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(); 343 185 344 186 /* Show the first tab widget's page after the refresh: */ 345 m_p ViewerContainer->setCurrentIndex(0);187 m_pTabWidget->setCurrentIndex(0); 346 188 347 189 /* Apply the filter settings: */ … … 350 192 351 193 /* 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); 356 196 357 197 /* Enable/Disable toolbar actions (except Refresh) & tab widget according log presence: */ … … 360 200 m_pActionSave->setEnabled(!noLogsToShow); 361 201 m_pActionBookmark->setEnabled(!noLogsToShow); 362 m_p ViewerContainer->setEnabled(!noLogsToShow);363 m_p ViewerContainer->show();202 m_pTabWidget->setEnabled(!noLogsToShow); 203 m_pTabWidget->show(); 364 204 if (m_pSearchPanel && m_pSearchPanel->isVisible()) 365 205 m_pSearchPanel->refresh(); … … 370 210 if (m_comMachine.isNull()) 371 211 return; 372 UIVMLogViewerTextEdit *logPage = qobject_cast<UIVMLogViewerTextEdit*>(currentLogPage()); 212 213 UIVMLogPage *logPage = currentLogPage(); 373 214 if (!logPage) 374 215 return; 216 217 const QString& fileName = logPage->fileName(); 218 if (fileName.isEmpty()) 219 return; 375 220 /* Prepare "save as" dialog: */ 376 const QFileInfo fileInfo( logPage->logFileName());221 const QFileInfo fileInfo(fileName); 377 222 /* Prepare default filename: */ 378 223 const QDateTime dtInfo = fileInfo.lastModified(); … … 395 240 QFile::remove(strNewFileName); 396 241 /* Copy log into the file: */ 397 QFile::copy(m_comMachine.QueryLogFilename(m_p ViewerContainer->currentIndex()), strNewFileName);242 QFile::copy(m_comMachine.QueryLogFilename(m_pTabWidget->currentIndex()), strNewFileName); 398 243 } 399 244 } … … 406 251 if (!currentLogPage()) 407 252 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()); 413 254 } 414 255 415 256 void UIVMLogViewerWidget::sltTabIndexChange(int tabIndex) 416 257 { 417 if (m_iCurrentTabIndex == tabIndex)418 return;258 // if (m_iCurrentTabIndex == tabIndex) 259 // return; 419 260 420 261 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; 424 265 /* 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); 428 269 } 429 270 … … 437 278 void UIVMLogViewerWidget::sltCreateBookmarkAtCurrent() 438 279 { 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); 450 291 } 451 292 452 293 void UIVMLogViewerWidget::sltCreateBookmarkAtLine(LogBookmark bookmark) 453 294 { 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); 460 301 } 461 302 … … 503 344 504 345 /* Create VM Log-Viewer container: */ 505 m_p ViewerContainer= new QITabWidget(this);506 AssertPtrReturnVoid(m_p ViewerContainer);346 m_pTabWidget = new QITabWidget(this); 347 AssertPtrReturnVoid(m_pTabWidget); 507 348 { 508 349 /* Add VM Log-Viewer container to main-layout: */ 509 m_pMainLayout->insertWidget(1, m_p ViewerContainer);350 m_pMainLayout->insertWidget(1, m_pTabWidget); 510 351 } 511 352 … … 766 607 767 608 /* 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(); 771 612 } 772 613 … … 784 625 case Qt::Key_Back: 785 626 { 786 if (m_p ViewerContainer->currentIndex() > 0)627 if (m_pTabWidget->currentIndex() > 0) 787 628 { 788 m_p ViewerContainer->setCurrentIndex(m_pViewerContainer->currentIndex() - 1);629 m_pTabWidget->setCurrentIndex(m_pTabWidget->currentIndex() - 1); 789 630 return; 790 631 } … … 794 635 case Qt::Key_Forward: 795 636 { 796 if (m_p ViewerContainer->currentIndex() < m_pViewerContainer->count())637 if (m_pTabWidget->currentIndex() < m_pTabWidget->count()) 797 638 { 798 m_p ViewerContainer->setCurrentIndex(m_pViewerContainer->currentIndex() + 1);639 m_pTabWidget->setCurrentIndex(m_pTabWidget->currentIndex() + 1); 799 640 return; 800 641 } … … 807 648 } 808 649 809 const QString* UIVMLogViewerWidget::currentLog() 810 { 811 if (!currentLogPage()) 650 const UIVMLogPage *UIVMLogViewerWidget::currentLogPage() const 651 { 652 int currentTabIndex = m_pTabWidget->currentIndex(); 653 if (currentTabIndex >= m_logPageList.size()) 812 654 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 } 657 UIVMLogPage *UIVMLogViewerWidget::currentLogPage() 658 { 659 int currentTabIndex = m_pTabWidget->currentIndex(); 660 if (currentTabIndex >= m_logPageList.size()) 835 661 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 // } 854 688 855 689 void UIVMLogViewerWidget::hidePanel(UIVMLogViewerPanel* panel) … … 879 713 QPlainTextEdit* UIVMLogViewerWidget::logPage(int pIndex) const 880 714 { 881 if (!m_p ViewerContainer->isEnabled())715 if (!m_pTabWidget->isEnabled()) 882 716 return 0; 883 QWidget* pContainer = m_p ViewerContainer->widget(pIndex);717 QWidget* pContainer = m_pTabWidget->widget(pIndex); 884 718 if (!pContainer) 885 719 return 0; … … 890 724 bool UIVMLogViewerWidget::createLogViewerPages() 891 725 { 726 bool noLogsToShow = false; 727 728 QString strDummyTabText; 729 /* check if the machine is valid: */ 892 730 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 896 737 const CSystemProperties &sys = vboxGlobal().virtualBox().GetSystemProperties(); 897 738 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) 903 751 { 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()) 908 755 { 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 } 928 772 } 929 773 } 930 774 } 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 783 void UIVMLogViewerWidget::createLogPage(const QString &strFileName, const QString &strLogContent, bool noLogsToShow /* = false */) 784 { 785 AssertPtrReturnVoid(m_pTabWidget); 786 936 787 /* 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(); 973 807 } 974 808 … … 976 810 { 977 811 /* 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 37 37 class QVBoxLayout; 38 38 class UIToolBar; 39 class UIVMLogPage; 39 40 class UIVMLogViewerBookmarksPanel; 40 41 class UIVMLogViewerFilterPanel; … … 44 45 /* Type definitions: */ 45 46 /** value is the content of the log file */ 46 typedef QMap<QPlainTextEdit*, QString> VMLogMap;47 //typedef QMap<QPlainTextEdit*, QString> VMLogMap; 47 48 /** first is line number, second is block text */ 48 typedef QPair<int, QString> LogBookmark;49 //typedef QPair<int, QString> LogBookmark; 49 50 /** 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. */ 55 57 class UIVMLogViewerWidget : public QIWithRetranslateUI<QWidget> 56 58 { … … 137 139 /** @} */ 138 140 139 /** Returns the current log-page. */ 140 QPlainTextEdit* currentLogPage() const; 141 141 142 /** Returns the log-page from the tab with index @a pIndex. */ 142 143 QPlainTextEdit* logPage(int pIndex) const; 143 144 /** 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; 147 150 148 151 /** Attempts to read the logs through the API, returns true if there exists any logs, false otherwise. */ … … 152 155 void resetHighlighthing(); 153 156 154 /** Returns the vector of bookmarks for the current log page */155 QVector<LogBookmark>* currentBookmarkVector();156 const QVector<LogBookmark>* currentBookmarkVector() const;157 158 157 void hidePanel(UIVMLogViewerPanel* panel); 159 158 void showPanel(UIVMLogViewerPanel* panel); … … 166 165 167 166 /** 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; 169 171 170 172 /** Holds the index to the current tab: */ 171 int m_iCurrentTabIndex;173 //int m_iCurrentTabIndex; 172 174 173 175 /** Holds the instance of search-panel. */ … … 179 181 180 182 /** 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; 183 185 QVBoxLayout *m_pMainLayout; 184 186
Note:
See TracChangeset
for help on using the changeset viewer.