VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/guestctrl/UIGuestControlConsole.cpp@ 77822

Last change on this file since 77822 was 77822, checked in by vboxsync, 6 years ago

FE/Qt: bugref:6699. Adding guest control console to machine's debug menu.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.5 KB
Line 
1/* $Id: UIGuestControlConsole.cpp 77822 2019-03-21 08:23:11Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIGuestControlConsole class implementation.
4 */
5
6/*
7 * Copyright (C) 2016-2019 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/* Qt includes: */
19#include <QVBoxLayout>
20#include <QApplication>
21#include <QTextBlock>
22
23/* GUI includes: */
24#include "UIGuestControlConsole.h"
25#include "UIGuestControlInterface.h"
26
27UIGuestControlConsole::UIGuestControlConsole(const CGuest &comGuest, QWidget* parent /* = 0 */)
28 :QPlainTextEdit(parent)
29 , m_comGuest(comGuest)
30 , m_strGreet("Welcome to 'Guest Control Console'. Type 'help' for help\n")
31 , m_strPrompt("$>")
32 , m_uCommandHistoryIndex(0)
33 , m_pControlInterface(0)
34{
35 m_pControlInterface = new UIGuestControlInterface(this, m_comGuest);
36
37 connect(m_pControlInterface, &UIGuestControlInterface::sigOutputString,
38 this, &UIGuestControlConsole::sltOutputReceived);
39
40 /* Configure this: */
41 setUndoRedoEnabled(false);
42 setWordWrapMode(QTextOption::NoWrap);
43 reset();
44
45 m_tabDictinary.insert("username", 0);
46 m_tabDictinary.insert("createsession", 0);
47 m_tabDictinary.insert("exe", 0);
48 m_tabDictinary.insert("sessionid", 0);
49 m_tabDictinary.insert("sessionname", 0);
50 m_tabDictinary.insert("timeout", 0);
51 m_tabDictinary.insert("password", 0);
52 m_tabDictinary.insert("start", 0);
53 m_tabDictinary.insert("ls", 0);
54 m_tabDictinary.insert("stat", 0);
55}
56
57void UIGuestControlConsole::commandEntered(const QString &strCommand)
58{
59 if (m_pControlInterface)
60 m_pControlInterface->putCommand(strCommand);
61}
62
63void UIGuestControlConsole::sltOutputReceived(const QString &strOutput)
64{
65 putOutput(strOutput);
66}
67
68void UIGuestControlConsole::reset()
69{
70 clear();
71 startNextLine();
72 insertPlainText(m_strGreet);
73 startNextLine();
74}
75
76void UIGuestControlConsole::startNextLine()
77{
78 moveCursor(QTextCursor::End);
79 insertPlainText(m_strPrompt);
80 moveCursor(QTextCursor::End);
81}
82
83
84void UIGuestControlConsole::putOutput(const QString &strOutput)
85{
86 if (strOutput.isNull() || strOutput.length() <= 0)
87 return;
88
89 bool newLineNeeded = getCommandString().isEmpty();
90
91 QString strOwn("\n");
92 strOwn.append(strOutput);
93 moveCursor(QTextCursor::End);
94 insertPlainText(strOwn);
95 moveCursor(QTextCursor::End);
96
97 if (newLineNeeded)
98 {
99 insertPlainText("\n");
100 startNextLine();
101 }
102 }
103
104void UIGuestControlConsole::keyPressEvent(QKeyEvent *pEvent)
105{
106 /* Check if we at the bottom most line.*/
107 bool lastLine = blockCount() == (textCursor().blockNumber() +1);
108
109 switch (pEvent->key()) {
110 case Qt::Key_PageUp:
111 case Qt::Key_Up:
112 {
113 replaceLineContent(getPreviousCommandFromHistory(getCommandString()));
114 break;
115 }
116 case Qt::Key_PageDown:
117 case Qt::Key_Down:
118 {
119 replaceLineContent(getNextCommandFromHistory(getCommandString()));
120 break;
121 }
122 case Qt::Key_Backspace:
123 {
124 QTextCursor cursor = textCursor();
125 if (lastLine && cursor.positionInBlock() > m_strPrompt.length())
126 cursor.deletePreviousChar();
127 break;
128 }
129 case Qt::Key_Left:
130 case Qt::Key_Right:
131 {
132 if (textCursor().positionInBlock() > m_strPrompt.length()-1)
133 QPlainTextEdit::keyPressEvent(pEvent);
134 break;
135 }
136 case Qt::Key_Return:
137 case Qt::Key_Enter:
138 {
139 if (lastLine)
140 {
141 QString strCommand(getCommandString());
142 if (!strCommand.isEmpty())
143 {
144 commandEntered(strCommand);
145 if (!m_tCommandHistory.contains(strCommand))
146 m_tCommandHistory.push_back(strCommand);
147 m_uCommandHistoryIndex = m_tCommandHistory.size()-1;
148 moveCursor(QTextCursor::End);
149 QPlainTextEdit::keyPressEvent(pEvent);
150 startNextLine();
151 }
152 }
153 break;
154 }
155 case Qt::Key_Home:
156 {
157 QTextCursor cursor = textCursor();
158 cursor.movePosition(QTextCursor::StartOfLine);
159 cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::MoveAnchor, m_strPrompt.length());
160 setTextCursor(cursor);
161 break;
162 }
163 case Qt::Key_Tab:
164 completeByTab();
165 break;
166 default:
167 {
168 if (pEvent->modifiers() == Qt::ControlModifier && pEvent->key() == Qt::Key_C)
169 {
170 QPlainTextEdit::keyPressEvent(pEvent);
171 }
172 else
173 {
174 if (lastLine)
175 QPlainTextEdit::keyPressEvent(pEvent);
176 }
177 }
178 break;
179 }
180}
181
182void UIGuestControlConsole::mousePressEvent(QMouseEvent *pEvent)
183{
184 // Q_UNUSED(pEvent);
185 // setFocus();
186 QPlainTextEdit::mousePressEvent(pEvent);
187}
188
189void UIGuestControlConsole::mouseDoubleClickEvent(QMouseEvent *pEvent)
190{
191 //Q_UNUSED(pEvent);
192 QPlainTextEdit::mouseDoubleClickEvent(pEvent);
193}
194
195void UIGuestControlConsole::contextMenuEvent(QContextMenuEvent *pEvent)
196{
197 Q_UNUSED(pEvent);
198 //QPlainTextEdit::contextMenuEvent(pEvent);
199}
200
201QString UIGuestControlConsole::getCommandString()
202{
203 QTextDocument* pDocument = document();
204 if (!pDocument)
205 return QString();
206 QTextBlock block = pDocument->lastBlock();//findBlockByLineNumber(pDocument->lineCount()-1);
207 if (!block.isValid())
208 return QString();
209 QString lineStr = block.text();
210 if (lineStr.isNull() || lineStr.length() <= 1)
211 return QString();
212 /* Remove m_strPrompt from the line string: */
213 return (lineStr.right(lineStr.length()-m_strPrompt.length()));
214}
215
216void UIGuestControlConsole::replaceLineContent(const QString &stringNewContent)
217{
218 moveCursor(QTextCursor::End);
219 QTextCursor cursor = textCursor();
220 cursor.movePosition(QTextCursor::StartOfLine, QTextCursor::KeepAnchor);
221 cursor.removeSelectedText();
222
223 QString newString(m_strPrompt);
224 newString.append(stringNewContent);
225 insertPlainText(newString);
226 moveCursor(QTextCursor::End);
227}
228
229QString UIGuestControlConsole::getNextCommandFromHistory(const QString &originalString /* = QString() */)
230{
231 if (m_tCommandHistory.empty())
232 return originalString;
233
234 if (m_uCommandHistoryIndex == (unsigned)(m_tCommandHistory.size() - 1))
235 m_uCommandHistoryIndex = 0;
236 else
237 ++m_uCommandHistoryIndex;
238
239 return m_tCommandHistory.at(m_uCommandHistoryIndex);
240}
241
242
243QString UIGuestControlConsole::getPreviousCommandFromHistory(const QString &originalString /* = QString() */)
244{
245 if (m_tCommandHistory.empty())
246 return originalString;
247 if (m_uCommandHistoryIndex == 0)
248 m_uCommandHistoryIndex = m_tCommandHistory.size() - 1;
249 else
250 --m_uCommandHistoryIndex;
251
252 return m_tCommandHistory.at(m_uCommandHistoryIndex);
253}
254
255void UIGuestControlConsole::completeByTab()
256{
257 bool lastLine = blockCount() == (textCursor().blockNumber() +1);
258 if (!lastLine)
259 return;
260 /* Save whatever we have currently on this line: */
261 QString currentCommand = getCommandString();
262
263 QTextCursor cursor = textCursor();
264 /* Save the cursor's position within the line */
265 int cursorBlockPosition = cursor.positionInBlock();
266
267 /* Find out on which word the cursor is. This is the word we will
268 complete: */
269 cursor.select(QTextCursor::WordUnderCursor);
270 QString currentWord = cursor.selectedText();
271
272 const QList<QString> &matches = matchedWords(currentWord);
273 /* If there are no matches do nothing: */
274 if (matches.empty())
275 return;
276 /* if there are more than one match list them all and
277 reprint the line: */
278 if (matches.size() > 1)
279 {
280 moveCursor(QTextCursor::End);
281 QString strMatches;
282 for (int i = 0; i < matches.size(); ++i)
283 {
284 strMatches.append(matches.at(i));
285 strMatches.append(" ");
286 }
287 appendPlainText(strMatches);
288 insertPlainText(QString("\n").append(m_strPrompt));
289 insertPlainText(currentCommand);
290 /* Put the cursor in its previous position within the line: */
291 int blockPosition = textCursor().block().position();
292 QTextCursor nCursor = textCursor();
293 nCursor.setPosition(blockPosition + cursorBlockPosition);
294 setTextCursor(nCursor);
295 return;
296 }
297 /* if there is only one word just complete: */
298 /* some sanity checks */
299 if (matches.at(0).length() > currentWord.length())
300 insertPlainText(matches.at(0).right(matches.at(0).length() - currentWord.length()));
301}
302
303
304QList<QString> UIGuestControlConsole::matchedWords(const QString &strSearch) const
305{
306 QList<QString> list;
307 /* Go thru the map and find which of its elements start with @pstrSearch: */
308 for (TabDictionary::const_iterator iterator = m_tabDictinary.begin();
309 iterator != m_tabDictinary.end(); ++iterator)
310 {
311 const QString &strMap = iterator.key();
312 if (strMap.startsWith(strSearch))
313 list.push_back(strMap);
314 }
315 return list;
316}
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