VirtualBox

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

Last change on this file since 43325 was 43324, checked in by vboxsync, 13 years ago

bug #6322: Debugger: Redo the command history

Maintain invariant that the empty line is the last one. That
simplifies the logic and make history actually work as expected.

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

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