VirtualBox

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

Last change on this file since 103982 was 98103, checked in by vboxsync, 23 months ago

Copyright year updates by scm.

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