VirtualBox

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

Last change on this file was 98103, checked in by vboxsync, 17 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
RevLine 
[71025]1/* $Id: UIGuestControlConsole.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIGuestControlConsole class implementation.
4 */
5
6/*
[98103]7 * Copyright (C) 2016-2023 Oracle and/or its affiliates.
[71025]8 *
[96407]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
[71025]26 */
27
28/* Qt includes: */
[76606]29#include <QVBoxLayout>
30#include <QApplication>
31#include <QTextBlock>
[71025]32
33/* GUI includes: */
[76606]34#include "UIGuestControlConsole.h"
[77822]35#include "UIGuestControlInterface.h"
[71025]36
[77822]37UIGuestControlConsole::UIGuestControlConsole(const CGuest &comGuest, QWidget* parent /* = 0 */)
[71025]38 :QPlainTextEdit(parent)
[77822]39 , m_comGuest(comGuest)
[71025]40 , m_strGreet("Welcome to 'Guest Control Console'. Type 'help' for help\n")
41 , m_strPrompt("$>")
42 , m_uCommandHistoryIndex(0)
[77822]43 , m_pControlInterface(0)
[71025]44{
[77822]45 m_pControlInterface = new UIGuestControlInterface(this, m_comGuest);
46
47 connect(m_pControlInterface, &UIGuestControlInterface::sigOutputString,
48 this, &UIGuestControlConsole::sltOutputReceived);
49
[71025]50 /* Configure this: */
[71066]51 setUndoRedoEnabled(false);
[71025]52 setWordWrapMode(QTextOption::NoWrap);
53 reset();
[71145]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);
[71025]65}
66
[77822]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
[71025]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{
[71049]96 if (strOutput.isNull() || strOutput.length() <= 0)
[71025]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
[71049]107 if (newLineNeeded)
[71025]108 {
109 insertPlainText("\n");
110 startNextLine();
111 }
[71089]112 }
[71025]113
114void UIGuestControlConsole::keyPressEvent(QKeyEvent *pEvent)
115{
[71052]116 /* Check if we at the bottom most line.*/
117 bool lastLine = blockCount() == (textCursor().blockNumber() +1);
[71025]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 {
[71066]129 replaceLineContent(getNextCommandFromHistory(getCommandString()));
[71025]130 break;
131 }
132 case Qt::Key_Backspace:
133 {
134 QTextCursor cursor = textCursor();
[71052]135 if (lastLine && cursor.positionInBlock() > m_strPrompt.length())
[71025]136 cursor.deletePreviousChar();
137 break;
138 }
139 case Qt::Key_Left:
140 case Qt::Key_Right:
141 {
[71135]142 if (textCursor().positionInBlock() > m_strPrompt.length()-1)
[71025]143 QPlainTextEdit::keyPressEvent(pEvent);
144 break;
145 }
146 case Qt::Key_Return:
147 case Qt::Key_Enter:
148 {
[71052]149 if (lastLine)
[71025]150 {
[71052]151 QString strCommand(getCommandString());
152 if (!strCommand.isEmpty())
153 {
[77822]154 commandEntered(strCommand);
[71052]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 }
[71025]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 }
[71145]173 case Qt::Key_Tab:
174 completeByTab();
175 break;
[71025]176 default:
[71066]177 {
[71089]178 if (pEvent->modifiers() == Qt::ControlModifier && pEvent->key() == Qt::Key_C)
[71066]179 {
[71052]180 QPlainTextEdit::keyPressEvent(pEvent);
[71066]181 }
182 else
183 {
184 if (lastLine)
185 QPlainTextEdit::keyPressEvent(pEvent);
186 }
187 }
[71025]188 break;
189 }
190}
191
192void UIGuestControlConsole::mousePressEvent(QMouseEvent *pEvent)
193{
[71049]194 // Q_UNUSED(pEvent);
195 // setFocus();
196 QPlainTextEdit::mousePressEvent(pEvent);
[71025]197}
198
199void UIGuestControlConsole::mouseDoubleClickEvent(QMouseEvent *pEvent)
200{
[71049]201 //Q_UNUSED(pEvent);
202 QPlainTextEdit::mouseDoubleClickEvent(pEvent);
[71025]203}
204
205void UIGuestControlConsole::contextMenuEvent(QContextMenuEvent *pEvent)
206{
[71052]207 Q_UNUSED(pEvent);
208 //QPlainTextEdit::contextMenuEvent(pEvent);
[71025]209}
210
211QString UIGuestControlConsole::getCommandString()
212{
213 QTextDocument* pDocument = document();
[71049]214 if (!pDocument)
[71025]215 return QString();
216 QTextBlock block = pDocument->lastBlock();//findBlockByLineNumber(pDocument->lineCount()-1);
217 if (!block.isValid())
218 return QString();
219 QString lineStr = block.text();
[71049]220 if (lineStr.isNull() || lineStr.length() <= 1)
[71025]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{
[71066]228 moveCursor(QTextCursor::End);
[71025]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{
[71049]241 if (m_tCommandHistory.empty())
[71025]242 return originalString;
243
[71049]244 if (m_uCommandHistoryIndex == (unsigned)(m_tCommandHistory.size() - 1))
[71025]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{
[71049]255 if (m_tCommandHistory.empty())
[71025]256 return originalString;
[71049]257 if (m_uCommandHistoryIndex == 0)
[71025]258 m_uCommandHistoryIndex = m_tCommandHistory.size() - 1;
259 else
260 --m_uCommandHistoryIndex;
261
262 return m_tCommandHistory.at(m_uCommandHistoryIndex);
263}
[71145]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: */
[71191]284 if (matches.empty())
[71145]285 return;
286 /* if there are more than one match list them all and
287 reprint the line: */
[71191]288 if (matches.size() > 1)
[71145]289 {
290 moveCursor(QTextCursor::End);
291 QString strMatches;
[71191]292 for (int i = 0; i < matches.size(); ++i)
[71145]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 */
[71191]309 if (matches.at(0).length() > currentWord.length())
[71145]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: */
[71191]318 for (TabDictionary::const_iterator iterator = m_tabDictinary.begin();
[71145]319 iterator != m_tabDictinary.end(); ++iterator)
320 {
321 const QString &strMap = iterator.key();
[71191]322 if (strMap.startsWith(strSearch))
[71145]323 list.push_back(strMap);
324 }
325 return list;
326}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use