VirtualBox

source: vbox/trunk/src/VBox/Debugger/VBoxDbgConsole.cpp@ 49221

Last change on this file since 49221 was 49142, checked in by vboxsync, 11 years ago

Debugger/VBoxDbgConsole: Customized context-menu to toggle colors/fonts.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.6 KB
Line 
1/* $Id: VBoxDbgConsole.cpp 49142 2013-10-16 14:34:08Z vboxsync $ */
2/** @file
3 * VBox Debugger GUI - Console.
4 */
5
6/*
7 * Copyright (C) 2006-2012 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#define LOG_GROUP LOG_GROUP_DBGG
23#include "VBoxDbgConsole.h"
24
25#include <QLabel>
26#include <QApplication>
27#include <QFont>
28#include <QLineEdit>
29#include <QHBoxLayout>
30#include <QAction>
31#include <QContextMenuEvent>
32#include <QMenu>
33
34#include <VBox/dbg.h>
35#include <VBox/vmm/cfgm.h>
36#include <VBox/err.h>
37
38#include <iprt/thread.h>
39#include <iprt/tcp.h>
40#include <VBox/log.h>
41#include <iprt/assert.h>
42#include <iprt/asm.h>
43#include <iprt/alloc.h>
44#include <iprt/string.h>
45
46
47
48
49/*
50 *
51 * V B o x D b g C o n s o l e O u t p u t
52 * V B o x D b g C o n s o l e O u t p u t
53 * V B o x D b g C o n s o l e O u t p u t
54 *
55 *
56 */
57
58
59VBoxDbgConsoleOutput::VBoxDbgConsoleOutput(QWidget *pParent/* = NULL*/, const char *pszName/* = NULL*/)
60 : QTextEdit(pParent), m_uCurLine(0), m_uCurPos(0), m_hGUIThread(RTThreadNativeSelf())
61{
62 setReadOnly(true);
63 setUndoRedoEnabled(false);
64 setOverwriteMode(false);
65 setPlainText("");
66 setTextInteractionFlags(Qt::TextBrowserInteraction);
67 setAutoFormatting(QTextEdit::AutoAll);
68 setTabChangesFocus(true);
69 setAcceptRichText(false);
70
71#ifdef Q_WS_MAC
72 QFont Font("Monaco", 10, QFont::Normal, FALSE);
73 Font.setStyleStrategy(QFont::NoAntialias);
74#else
75 QFont Font = font();
76 Font.setStyleHint(QFont::TypeWriter);
77 Font.setFamily("Courier [Monotype]");
78#endif
79 setFont(Font);
80
81 /* green on black */
82 QPalette Pal(palette());
83 Pal.setColor(QPalette::All, QPalette::Base, QColor(Qt::black));
84 setPalette(Pal);
85 setTextColor(QColor(qRgb(0, 0xe0, 0)));
86 m_fGreenOnBlack = true;
87
88 NOREF(pszName);
89}
90
91
92VBoxDbgConsoleOutput::~VBoxDbgConsoleOutput()
93{
94 Assert(m_hGUIThread == RTThreadNativeSelf());
95}
96
97void
98VBoxDbgConsoleOutput::contextMenuEvent(QContextMenuEvent *pEvent)
99{
100 QMenu *pMenu = createStandardContextMenu();
101
102 QAction *pToggleAction = new QAction(tr("Toggle Theme"), this);
103 pMenu->addSeparator();
104 pMenu->addAction(pToggleAction);
105 connect(pToggleAction, SIGNAL(triggered()), this, SLOT(toggleTheme()));
106
107 pMenu->exec(pEvent->globalPos());
108 delete pMenu;
109}
110
111
112void
113VBoxDbgConsoleOutput::toggleTheme()
114{
115 QFont Font = font();
116 Font.setStyleHint(QFont::TypeWriter);
117 QPalette Pal(palette());
118
119 /* Don't switch fonts on Mac for now. Haven't tested it. */
120 if (m_fGreenOnBlack)
121 {
122 /* Black on White. */
123#ifndef Q_WS_MAC
124 Font.setFamily("Monospace [Monotype]");
125 setFont(Font);
126#endif
127 Pal.setColor(QPalette::All, QPalette::Base, QColor(Qt::white));
128 setPalette(Pal);
129 setTextColor(QColor(qRgb(0, 0, 0)));
130 m_fGreenOnBlack = false;
131 }
132 else
133 {
134 /* Green on Black */
135#ifndef Q_WS_MAC
136 Font.setFamily("Courier [Monotype]");
137 setFont(Font);
138#endif
139 QPalette Pal(palette());
140 Pal.setColor(QPalette::All, QPalette::Base, QColor(Qt::black));
141 setPalette(Pal);
142 setTextColor(QColor(qRgb(0, 0xe0, 0)));
143 m_fGreenOnBlack = true;
144 }
145}
146
147
148void
149VBoxDbgConsoleOutput::appendText(const QString &rStr, bool fClearSelection)
150{
151 Assert(m_hGUIThread == RTThreadNativeSelf());
152
153 if (rStr.isEmpty() || rStr.isNull() || !rStr.length())
154 return;
155
156 /*
157 * Insert all in one go and make sure it's visible.
158 *
159 * We need to move the cursor and unselect any selected text before
160 * inserting anything, otherwise, text will disappear.
161 */
162 QTextCursor Cursor = textCursor();
163 if (!fClearSelection && Cursor.hasSelection())
164 {
165 QTextCursor SavedCursor = Cursor;
166 Cursor.clearSelection();
167 Cursor.movePosition(QTextCursor::End);
168
169 Cursor.insertText(rStr);
170
171 setTextCursor(SavedCursor);
172 }
173 else
174 {
175 if (Cursor.hasSelection())
176 Cursor.clearSelection();
177 if (!Cursor.atEnd())
178 Cursor.movePosition(QTextCursor::End);
179
180 Cursor.insertText(rStr);
181
182 setTextCursor(Cursor);
183 ensureCursorVisible();
184 }
185}
186
187
188
189
190/*
191 *
192 * V B o x D b g C o n s o l e I n p u t
193 * V B o x D b g C o n s o l e I n p u t
194 * V B o x D b g C o n s o l e I n p u t
195 *
196 *
197 */
198
199
200VBoxDbgConsoleInput::VBoxDbgConsoleInput(QWidget *pParent/* = NULL*/, const char *pszName/* = NULL*/)
201 : QComboBox(pParent), m_hGUIThread(RTThreadNativeSelf())
202{
203 addItem(""); /* invariant: empty command line is the last item */
204
205 setEditable(true);
206 setInsertPolicy(NoInsert);
207 setAutoCompletion(false);
208 setMaxCount(50);
209 const QLineEdit *pEdit = lineEdit();
210 if (pEdit)
211 connect(pEdit, SIGNAL(returnPressed()), this, SLOT(returnPressed()));
212
213 NOREF(pszName);
214}
215
216
217VBoxDbgConsoleInput::~VBoxDbgConsoleInput()
218{
219 Assert(m_hGUIThread == RTThreadNativeSelf());
220}
221
222
223void
224VBoxDbgConsoleInput::setLineEdit(QLineEdit *pEdit)
225{
226 Assert(m_hGUIThread == RTThreadNativeSelf());
227 QComboBox::setLineEdit(pEdit);
228 if (lineEdit() == pEdit && pEdit)
229 connect(pEdit, SIGNAL(returnPressed()), this, SLOT(returnPressed()));
230}
231
232
233void
234VBoxDbgConsoleInput::returnPressed()
235{
236 Assert(m_hGUIThread == RTThreadNativeSelf());
237
238 QString strCommand = currentText();
239 /* TODO: trim whitespace? */
240 if (strCommand.isEmpty())
241 return;
242
243 /* deal with the current command. */
244 emit commandSubmitted(strCommand);
245
246
247 /*
248 * Add current command to history.
249 */
250 bool fNeedsAppending = true;
251
252 /* invariant: empty line at the end */
253 int iLastItem = count() - 1;
254 Assert(itemText(iLastItem).isEmpty());
255
256 /* have previous command? check duplicate. */
257 if (iLastItem > 0)
258 {
259 const QString strPrevCommand(itemText(iLastItem - 1));
260 if (strCommand == strPrevCommand)
261 fNeedsAppending = false;
262 }
263
264 if (fNeedsAppending)
265 {
266 /* history full? drop the oldest command. */
267 if (count() == maxCount())
268 {
269 removeItem(0);
270 --iLastItem;
271 }
272
273 /* insert before the empty line. */
274 insertItem(iLastItem, strCommand);
275 }
276
277 /* invariant: empty line at the end */
278 int iNewLastItem = count() - 1;
279 Assert(itemText(iNewLastItem).isEmpty());
280
281 /* select empty line to present "new" command line to the user */
282 setCurrentIndex(iNewLastItem);
283}
284
285
286
287
288
289
290/*
291 *
292 * V B o x D b g C o n s o l e
293 * V B o x D b g C o n s o l e
294 * V B o x D b g C o n s o l e
295 *
296 *
297 */
298
299
300VBoxDbgConsole::VBoxDbgConsole(VBoxDbgGui *a_pDbgGui, QWidget *a_pParent/* = NULL*/)
301 : VBoxDbgBaseWindow(a_pDbgGui, a_pParent), m_pOutput(NULL), m_pInput(NULL), m_fInputRestoreFocus(false),
302 m_pszInputBuf(NULL), m_cbInputBuf(0), m_cbInputBufAlloc(0),
303 m_pszOutputBuf(NULL), m_cbOutputBuf(0), m_cbOutputBufAlloc(0),
304 m_pTimer(NULL), m_fUpdatePending(false), m_Thread(NIL_RTTHREAD), m_EventSem(NIL_RTSEMEVENT),
305 m_fTerminate(false), m_fThreadTerminated(false)
306{
307 setWindowTitle("VBoxDbg - Console");
308
309 /*
310 * Create the output text box.
311 */
312 m_pOutput = new VBoxDbgConsoleOutput(this);
313
314 /* try figure a suitable size */
315 QLabel *pLabel = new QLabel( "11111111111111111111111111111111111111111111111111111111111111111111111111111112222222222", this);
316 pLabel->setFont(m_pOutput->font());
317 QSize Size = pLabel->sizeHint();
318 delete pLabel;
319 Size.setWidth((int)(Size.width() * 1.10));
320 Size.setHeight(Size.width() / 2);
321 resize(Size);
322
323 /*
324 * Create the input combo box (with a label).
325 */
326 QHBoxLayout *pLayout = new QHBoxLayout();
327 //pLayout->setSizeConstraint(QLayout::SetMaximumSize);
328
329 pLabel = new QLabel(" Command ");
330 pLayout->addWidget(pLabel);
331 pLabel->setMaximumSize(pLabel->sizeHint());
332 pLabel->setAlignment(Qt::AlignCenter);
333
334 m_pInput = new VBoxDbgConsoleInput(NULL);
335 pLayout->addWidget(m_pInput);
336 m_pInput->setDuplicatesEnabled(false);
337 connect(m_pInput, SIGNAL(commandSubmitted(const QString &)), this, SLOT(commandSubmitted(const QString &)));
338
339# if 0//def Q_WS_MAC
340 pLabel = new QLabel(" ");
341 pLayout->addWidget(pLabel);
342 pLabel->setMaximumSize(20, m_pInput->sizeHint().height() + 6);
343 pLabel->setMinimumSize(20, m_pInput->sizeHint().height() + 6);
344# endif
345
346 QWidget *pHBox = new QWidget(this);
347 pHBox->setLayout(pLayout);
348
349 m_pInput->setEnabled(false); /* (we'll get a ready notification) */
350
351
352 /*
353 * Vertical layout box on the whole widget.
354 */
355 QVBoxLayout *pVLayout = new QVBoxLayout();
356 pVLayout->setContentsMargins(0, 0, 0, 0);
357 pVLayout->setSpacing(5);
358 pVLayout->addWidget(m_pOutput);
359 pVLayout->addWidget(pHBox);
360 setLayout(pVLayout);
361
362 /*
363 * The tab order is from input to output, not the other way around as it is by default.
364 */
365 setTabOrder(m_pInput, m_pOutput);
366 m_fInputRestoreFocus = true; /* hack */
367
368 /*
369 * Setup the timer.
370 */
371 m_pTimer = new QTimer(this);
372 connect(m_pTimer, SIGNAL(timeout()), SLOT(updateOutput()));
373
374 /*
375 * Init the backend structure.
376 */
377 m_Back.Core.pfnInput = backInput;
378 m_Back.Core.pfnRead = backRead;
379 m_Back.Core.pfnWrite = backWrite;
380 m_Back.Core.pfnSetReady = backSetReady;
381 m_Back.pSelf = this;
382
383 /*
384 * Create the critical section, the event semaphore and the debug console thread.
385 */
386 int rc = RTCritSectInit(&m_Lock);
387 AssertRC(rc);
388
389 rc = RTSemEventCreate(&m_EventSem);
390 AssertRC(rc);
391
392 rc = RTThreadCreate(&m_Thread, backThread, this, 0, RTTHREADTYPE_DEBUGGER, RTTHREADFLAGS_WAITABLE, "VBoxDbgC");
393 AssertRC(rc);
394 if (RT_FAILURE(rc))
395 m_Thread = NIL_RTTHREAD;
396
397 /*
398 * Shortcuts.
399 */
400 m_pFocusToInput = new QAction("", this);
401 m_pFocusToInput->setShortcut(QKeySequence("Ctrl+L"));
402 addAction(m_pFocusToInput);
403 connect(m_pFocusToInput, SIGNAL(triggered(bool)), this, SLOT(actFocusToInput()));
404
405 m_pFocusToOutput = new QAction("", this);
406 m_pFocusToOutput->setShortcut(QKeySequence("Ctrl+O"));
407 addAction(m_pFocusToOutput);
408 connect(m_pFocusToOutput, SIGNAL(triggered(bool)), this, SLOT(actFocusToOutput()));
409}
410
411
412VBoxDbgConsole::~VBoxDbgConsole()
413{
414 Assert(isGUIThread());
415
416 /*
417 * Wait for the thread.
418 */
419 ASMAtomicWriteBool(&m_fTerminate, true);
420 RTSemEventSignal(m_EventSem);
421 if (m_Thread != NIL_RTTHREAD)
422 {
423 int rc = RTThreadWait(m_Thread, 15000, NULL);
424 AssertRC(rc);
425 m_Thread = NIL_RTTHREAD;
426 }
427
428 /*
429 * Free resources.
430 */
431 delete m_pTimer;
432 m_pTimer = NULL;
433 RTCritSectDelete(&m_Lock);
434 RTSemEventDestroy(m_EventSem);
435 m_EventSem = 0;
436 m_pOutput = NULL;
437 m_pInput = NULL;
438 if (m_pszInputBuf)
439 {
440 RTMemFree(m_pszInputBuf);
441 m_pszInputBuf = NULL;
442 }
443 m_cbInputBuf = 0;
444 m_cbInputBufAlloc = 0;
445
446 delete m_pFocusToInput;
447 m_pFocusToInput = NULL;
448 delete m_pFocusToOutput;
449 m_pFocusToOutput = NULL;
450}
451
452
453void
454VBoxDbgConsole::commandSubmitted(const QString &rCommand)
455{
456 Assert(isGUIThread());
457
458 lock();
459 RTSemEventSignal(m_EventSem);
460
461 QByteArray Utf8Array = rCommand.toUtf8();
462 const char *psz = Utf8Array.constData();
463 size_t cb = strlen(psz);
464
465 /*
466 * Make sure we've got space for the input.
467 */
468 if (cb + m_cbInputBuf >= m_cbInputBufAlloc)
469 {
470 size_t cbNew = RT_ALIGN_Z(cb + m_cbInputBufAlloc + 1, 128);
471 void *pv = RTMemRealloc(m_pszInputBuf, cbNew);
472 if (!pv)
473 {
474 unlock();
475 return;
476 }
477 m_pszInputBuf = (char *)pv;
478 m_cbInputBufAlloc = cbNew;
479 }
480
481 /*
482 * Add the input and output it.
483 */
484 memcpy(m_pszInputBuf + m_cbInputBuf, psz, cb);
485 m_cbInputBuf += cb;
486 m_pszInputBuf[m_cbInputBuf++] = '\n';
487
488 m_pOutput->appendText(rCommand + "\n", true /*fClearSelection*/);
489 m_pOutput->ensureCursorVisible();
490
491 m_fInputRestoreFocus = m_pInput->hasFocus(); /* dirty focus hack */
492 m_pInput->setEnabled(false);
493
494 Log(("VBoxDbgConsole::commandSubmitted: %s (input-enabled=%RTbool)\n", psz, m_pInput->isEnabled()));
495 unlock();
496}
497
498
499void
500VBoxDbgConsole::updateOutput()
501{
502 Assert(isGUIThread());
503
504 lock();
505 m_fUpdatePending = false;
506 if (m_cbOutputBuf)
507 {
508 m_pOutput->appendText(QString::fromUtf8((const char *)m_pszOutputBuf, (int)m_cbOutputBuf), false /*fClearSelection*/);
509 m_cbOutputBuf = 0;
510 }
511 unlock();
512}
513
514
515/**
516 * Lock the object.
517 */
518void
519VBoxDbgConsole::lock()
520{
521 RTCritSectEnter(&m_Lock);
522}
523
524
525/**
526 * Unlocks the object.
527 */
528void
529VBoxDbgConsole::unlock()
530{
531 RTCritSectLeave(&m_Lock);
532}
533
534
535
536/**
537 * Checks if there is input.
538 *
539 * @returns true if there is input ready.
540 * @returns false if there not input ready.
541 * @param pBack Pointer to VBoxDbgConsole::m_Back.
542 * @param cMillies Number of milliseconds to wait on input data.
543 */
544/*static*/ DECLCALLBACK(bool)
545VBoxDbgConsole::backInput(PDBGCBACK pBack, uint32_t cMillies)
546{
547 VBoxDbgConsole *pThis = VBOXDBGCONSOLE_FROM_DBGCBACK(pBack);
548 pThis->lock();
549
550 bool fRc = true;
551 if (!pThis->m_cbInputBuf)
552 {
553 /*
554 * Wait outside the lock for the requested time, then check again.
555 */
556 pThis->unlock();
557 RTSemEventWait(pThis->m_EventSem, cMillies);
558 pThis->lock();
559 fRc = pThis->m_cbInputBuf
560 || ASMAtomicUoReadBool(&pThis->m_fTerminate);
561 }
562
563 pThis->unlock();
564 return fRc;
565}
566
567
568/**
569 * Read input.
570 *
571 * @returns VBox status code.
572 * @param pBack Pointer to VBoxDbgConsole::m_Back.
573 * @param pvBuf Where to put the bytes we read.
574 * @param cbBuf Maximum nymber of bytes to read.
575 * @param pcbRead Where to store the number of bytes actually read.
576 * If NULL the entire buffer must be filled for a
577 * successful return.
578 */
579/*static*/ DECLCALLBACK(int)
580VBoxDbgConsole::backRead(PDBGCBACK pBack, void *pvBuf, size_t cbBuf, size_t *pcbRead)
581{
582 VBoxDbgConsole *pThis = VBOXDBGCONSOLE_FROM_DBGCBACK(pBack);
583 Assert(pcbRead); /** @todo implement this bit */
584 if (pcbRead)
585 *pcbRead = 0;
586
587 pThis->lock();
588 int rc = VINF_SUCCESS;
589 if (!ASMAtomicUoReadBool(&pThis->m_fTerminate))
590 {
591 if (pThis->m_cbInputBuf)
592 {
593 const char *psz = pThis->m_pszInputBuf;
594 size_t cbRead = RT_MIN(pThis->m_cbInputBuf, cbBuf);
595 memcpy(pvBuf, psz, cbRead);
596 psz += cbRead;
597 pThis->m_cbInputBuf -= cbRead;
598 if (*psz)
599 memmove(pThis->m_pszInputBuf, psz, pThis->m_cbInputBuf);
600 pThis->m_pszInputBuf[pThis->m_cbInputBuf] = '\0';
601 *pcbRead = cbRead;
602 }
603 }
604 else
605 rc = VERR_GENERAL_FAILURE;
606 pThis->unlock();
607 return rc;
608}
609
610
611/**
612 * Write (output).
613 *
614 * @returns VBox status code.
615 * @param pBack Pointer to VBoxDbgConsole::m_Back.
616 * @param pvBuf What to write.
617 * @param cbBuf Number of bytes to write.
618 * @param pcbWritten Where to store the number of bytes actually written.
619 * If NULL the entire buffer must be successfully written.
620 */
621/*static*/ DECLCALLBACK(int)
622VBoxDbgConsole::backWrite(PDBGCBACK pBack, const void *pvBuf, size_t cbBuf, size_t *pcbWritten)
623{
624 VBoxDbgConsole *pThis = VBOXDBGCONSOLE_FROM_DBGCBACK(pBack);
625 int rc = VINF_SUCCESS;
626
627 pThis->lock();
628 if (cbBuf + pThis->m_cbOutputBuf >= pThis->m_cbOutputBufAlloc)
629 {
630 size_t cbNew = RT_ALIGN_Z(cbBuf + pThis->m_cbOutputBufAlloc + 1, 1024);
631 void *pv = RTMemRealloc(pThis->m_pszOutputBuf, cbNew);
632 if (!pv)
633 {
634 pThis->unlock();
635 if (pcbWritten)
636 *pcbWritten = 0;
637 return VERR_NO_MEMORY;
638 }
639 pThis->m_pszOutputBuf = (char *)pv;
640 pThis->m_cbOutputBufAlloc = cbNew;
641 }
642
643 /*
644 * Add the output.
645 */
646 memcpy(pThis->m_pszOutputBuf + pThis->m_cbOutputBuf, pvBuf, cbBuf);
647 pThis->m_cbOutputBuf += cbBuf;
648 pThis->m_pszOutputBuf[pThis->m_cbOutputBuf] = '\0';
649 if (pcbWritten)
650 *pcbWritten = cbBuf;
651
652 if (ASMAtomicUoReadBool(&pThis->m_fTerminate))
653 rc = VERR_GENERAL_FAILURE;
654
655 /*
656 * Tell the GUI thread to draw this text.
657 * We cannot do it from here without frequent crashes.
658 */
659 if (!pThis->m_fUpdatePending)
660 QApplication::postEvent(pThis, new VBoxDbgConsoleEvent(VBoxDbgConsoleEvent::kUpdate));
661
662 pThis->unlock();
663
664 return rc;
665}
666
667
668/*static*/ DECLCALLBACK(void)
669VBoxDbgConsole::backSetReady(PDBGCBACK pBack, bool fReady)
670{
671 VBoxDbgConsole *pThis = VBOXDBGCONSOLE_FROM_DBGCBACK(pBack);
672 if (fReady)
673 QApplication::postEvent(pThis, new VBoxDbgConsoleEvent(VBoxDbgConsoleEvent::kInputEnable));
674}
675
676
677/**
678 * The Debugger Console Thread
679 *
680 * @returns VBox status code (ignored).
681 * @param Thread The thread handle.
682 * @param pvUser Pointer to the VBoxDbgConsole object.s
683 */
684/*static*/ DECLCALLBACK(int)
685VBoxDbgConsole::backThread(RTTHREAD Thread, void *pvUser)
686{
687 VBoxDbgConsole *pThis = (VBoxDbgConsole *)pvUser;
688 LogFlow(("backThread: Thread=%p pvUser=%p\n", (void *)Thread, pvUser));
689
690 NOREF(Thread);
691
692 /*
693 * Create and execute the console.
694 */
695 int rc = pThis->dbgcCreate(&pThis->m_Back.Core, 0);
696
697 ASMAtomicUoWriteBool(&pThis->m_fThreadTerminated, true);
698 if (!ASMAtomicUoReadBool(&pThis->m_fTerminate))
699 QApplication::postEvent(pThis, new VBoxDbgConsoleEvent(rc == VINF_SUCCESS
700 ? VBoxDbgConsoleEvent::kTerminatedUser
701 : VBoxDbgConsoleEvent::kTerminatedOther));
702 LogFlow(("backThread: returns %Rrc (m_fTerminate=%RTbool)\n", rc, ASMAtomicUoReadBool(&pThis->m_fTerminate)));
703 return rc;
704}
705
706
707bool
708VBoxDbgConsole::event(QEvent *pGenEvent)
709{
710 Assert(isGUIThread());
711 if (pGenEvent->type() == (QEvent::Type)VBoxDbgConsoleEvent::kEventNumber)
712 {
713 VBoxDbgConsoleEvent *pEvent = (VBoxDbgConsoleEvent *)pGenEvent;
714
715 switch (pEvent->command())
716 {
717 /* make update pending. */
718 case VBoxDbgConsoleEvent::kUpdate:
719 lock();
720 if (!m_fUpdatePending)
721 {
722 m_fUpdatePending = true;
723 m_pTimer->setSingleShot(true);
724 m_pTimer->start(10);
725 }
726 unlock();
727 break;
728
729 /* Re-enable the input field and restore focus. */
730 case VBoxDbgConsoleEvent::kInputEnable:
731 Log(("VBoxDbgConsole: kInputEnable (input-enabled=%RTbool)\n", m_pInput->isEnabled()));
732 m_pInput->setEnabled(true);
733 if ( m_fInputRestoreFocus
734 && !m_pInput->hasFocus())
735 m_pInput->setFocus(); /* this is a hack. */
736 m_fInputRestoreFocus = false;
737 break;
738
739 /* The thread terminated by user command (exit, quit, bye). */
740 case VBoxDbgConsoleEvent::kTerminatedUser:
741 Log(("VBoxDbgConsole: kTerminatedUser (input-enabled=%RTbool)\n", m_pInput->isEnabled()));
742 m_pInput->setEnabled(false);
743 close();
744 break;
745
746 /* The thread terminated for some unknown reason., disable input */
747 case VBoxDbgConsoleEvent::kTerminatedOther:
748 Log(("VBoxDbgConsole: kTerminatedOther (input-enabled=%RTbool)\n", m_pInput->isEnabled()));
749 m_pInput->setEnabled(false);
750 break;
751
752 /* paranoia */
753 default:
754 AssertMsgFailed(("command=%d\n", pEvent->command()));
755 break;
756 }
757 return true;
758 }
759
760 return VBoxDbgBaseWindow::event(pGenEvent);
761}
762
763
764void
765VBoxDbgConsole::closeEvent(QCloseEvent *a_pCloseEvt)
766{
767 if (m_fThreadTerminated)
768 {
769 a_pCloseEvt->accept();
770 delete this;
771 }
772}
773
774
775void
776VBoxDbgConsole::actFocusToInput()
777{
778 if (!m_pInput->hasFocus())
779 m_pInput->setFocus(Qt::ShortcutFocusReason);
780}
781
782
783void
784VBoxDbgConsole::actFocusToOutput()
785{
786 if (!m_pOutput->hasFocus())
787 m_pOutput->setFocus(Qt::ShortcutFocusReason);
788}
789
Note: See TracBrowser for help on using the repository browser.

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