Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Palacios GUI Added
[palacios.git] / linux_usr / gui / palacios / vm_console_widget.cpp
1 /*
2  * vm_console_widget.cpp
3  *
4  *  Created on: Oct 4, 2012
5  *      Author: abhinav
6  */
7
8 #include "vm_console_widget.h"
9
10 #include <QDebug>
11 #include <QMessageBox>
12 #include <QVBoxLayout>
13 #include <X11/Xlib.h>
14
15 VmConsoleWidget::VmConsoleWidget(QWidget* parent) :
16                 QWidget(parent), mCols(100), mRows(25), mTermProcess(0) {
17         mTermProcess = NULL;
18         mVncServer = NULL;
19 }
20
21 VmConsoleWidget::~VmConsoleWidget() {
22
23 }
24
25 bool VmConsoleWidget::tryTerminate() {
26         if (mTermProcess == NULL) {
27                 return true;
28         }
29
30         if (mTermProcess != NULL && mTermProcess->state() == QProcess::Running) {
31                 mTermProcess->terminate();
32                 bool xwindow_closed = mTermProcess->waitForFinished();
33                 delete mTermProcess;
34                 return xwindow_closed;
35
36         } else if (mVncView != NULL) {
37                 mVncServer->terminate();
38                 bool vncserver_exited = mVncServer->waitForFinished();
39                 delete mVncView;
40                 delete mVncServer;
41                 return vncserver_exited;
42         }
43
44         return true;
45 }
46
47 void VmConsoleWidget::mainWindowClosing() {
48         close();
49 }
50
51 void VmConsoleWidget::closeEvent(QCloseEvent* e) {
52         if (!tryTerminate())
53                 qDebug() << "Warning: could not terminate process...there could be a leak";
54         else
55                 qDebug() << "Process terminated";
56
57         e->accept();
58 }
59
60 void VmConsoleWidget::resizeEvent(QResizeEvent* re) {
61         QWidget::resizeEvent(re);
62
63         if (mTermProcess == NULL)
64                 return;
65
66         // Search for xterm window and update its size
67         Display *dsp = XOpenDisplay(NULL);
68         Window wnd = winId();
69
70         bool childFound = false;
71         while (!childFound && mTermProcess->state() == QProcess::Running) {
72                 Window root, parent, *children;
73                 uint numwin;
74                 XQueryTree(dsp, wnd, &root, &parent, &children, &numwin);
75                 childFound = (children != NULL);
76
77                 if (childFound) {
78                         XResizeWindow(dsp, *children, width(), height());
79                         XFree(children);
80                 }
81         }
82
83         XCloseDisplay(dsp);
84 }
85
86 bool VmConsoleWidget::isRunning() {
87         if (mTermProcess == NULL) {
88                 return false;
89         }
90         
91         // FIXME: This function is currently very unreliable
92         // The QProcess->state() function should return the correct
93         // state of the process but it is currently not working as expected
94         // Debugging with GDB also does not reveal the problem
95         // Maybe the way this method is being called is incorrect
96         return (mTermProcess->state() == QProcess::Running) ? true : false;
97 }
98
99 bool VmConsoleWidget::start(int mode, QString devfile, QString streamName) {
100         qDebug() << "VmConsoleWidget : start() [" << streamName << "]";
101         
102         // Start VM in correct mode
103         if (mode == VmConsoleWidget::STREAM) {
104                 mVmMode = "v3_stream";
105         } else if (mode == VmConsoleWidget::CONSOLE) {
106                 mVmMode = "v3_cons_sc";
107         } else {
108                 mVmMode = "v3_vncclient";
109         }
110         
111         qDebug() << "Vm Mode: " << mVmMode;
112         qDebug() << "Vm dev file: " << devfile;
113
114         QStringList args;
115         
116         if (streamName.compare("") != 0) {
117             // This is v3_stream mode
118             args << "-sb" << "-geometry" << QString("%1x%2").arg(mCols).arg(mRows) << "-j"
119                 << "-into" << QString::number(winId()) << "-e" << mVmMode << devfile << streamName;
120                 
121                 // Start the xterm process
122                 qDebug() << "Starting terminal with arguments '" << args.join(" ");
123                 mTermProcess = new QProcess();
124
125                 // Connect signals and slots
126                 connect(mTermProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, 
127                         SLOT(termProcessExited(int, QProcess::ExitStatus)));
128
129                 connect(mTermProcess, SIGNAL(error(QProcess::ProcessError)), this, 
130                         SLOT(errorMessage(QProcess::ProcessError)));
131
132                 mTermProcess->start("/usr/bin/xterm", args);
133
134         } else {
135             // This is non-stream mode
136             
137             if (mVmMode.compare("v3_cons_sc") == 0) {
138                 // Console mode
139                 args << "-sb" << "-geometry" << QString("%1x%2").arg(mCols).arg(mRows) << "-j"
140                         << "-into" << QString::number(winId()) << "-e" << mVmMode << devfile;
141
142
143                 qDebug() << "Starting terminal with arguments '" << args.join(" ");
144                 mTermProcess = new QProcess();
145
146                 // Connect signals and slots
147                 connect(mTermProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, 
148                         SLOT(termProcessExited(int, QProcess::ExitStatus)));
149
150                 connect(mTermProcess, SIGNAL(error(QProcess::ProcessError)), this, 
151                         SLOT(errorMessage(QProcess::ProcessError)));
152         
153                 mTermProcess->start("/usr/bin/xterm", args);
154             
155             } else {
156                 // VNC mode
157                 mVncServer = new QProcess();
158                 mVncServer->setProcessChannelMode(QProcess::MergedChannels);
159
160                 connect(mVncServer, SIGNAL(finished(int, QProcess::ExitStatus)), this, 
161                         SLOT(termProcessExited(int, QProcess::ExitStatus)));
162
163                 connect(mVncServer, SIGNAL(error(QProcess::ProcessError)), this, 
164                         SLOT(errorMessage(QProcess::ProcessError)));
165                 
166                 QStringList args;
167                 args << "--port=5951" << "--password=test123" << devfile;
168                 qDebug() << "arguments: " << args.join(" ");
169                 mVncServer->start("v3_vncserver", args);
170
171                 if (!mVncServer->waitForFinished()) {
172                         qDebug() << "Error with VNC server";
173                         QMessageBox msg;
174                         msg.setText("Error with VNC server!");
175                         msg.setStandardButtons(QMessageBox::Ok);
176                         msg.setIcon(QMessageBox::Critical);
177                         msg.exec();
178                         return false;
179                 }
180                 
181                 //args << "-sb" << "-geometry" << QString("%1x%2").arg(mCols).arg(mRows) << "-j"
182                 //        << "-into" << QString::number(winId()) << "-e" << "vncviewer localhost:5951";
183                 
184                 QVBoxLayout* vncBox = new QVBoxLayout();
185                 mVncView = new VncView(this, QUrl("vnc://localhost:5951"), KConfigGroup());
186                 //mVncView = new VncView(this, QUrl("vnc://localhost:5901"), KConfigGroup());
187                 vncBox->addWidget(mVncView);
188                 this->setLayout(vncBox);
189                 
190                 mVncView->show();
191                 mVncView->start();
192             }
193         }
194         
195         // Flag to indicate success and failure
196         bool status = false;
197
198         if (mVmMode.compare("v3_vncclient") == 0) {
199                 // This is VNC mode
200                 status = true;       
201                 
202         } else {
203             int success;
204
205             // This is v3_stream or v3_cons_sc mode
206             if (mTermProcess != NULL && mTermProcess->waitForStarted()) {
207                     success = 0;
208                     qDebug() << "Process started";
209             } else {
210                     success = -1;
211                     qDebug() << "Process did not start";
212             }
213             
214             if (success == 0) {
215                 /* Wait for the xterm window to be opened and resize it
216                  * to our own widget size.
217                  */
218                 Display *dsp = XOpenDisplay(NULL);
219                 Window wnd = winId();
220
221                 bool childFound = false;
222                 while (!childFound && mTermProcess->state() == QProcess::Running) {
223                         Window root, parent, *children;
224                         uint numwin;
225                         XQueryTree(dsp, wnd, &root, &parent, &children, &numwin);
226                         childFound = (children != NULL);
227         
228                         if (childFound) {
229                                 XResizeWindow(dsp, *children, width(), height());
230                         }
231                 }
232
233                 XCloseDisplay(dsp);
234
235                 if (!childFound)
236                         success = -2;
237             }
238         
239             if (success < 0) {
240                 qDebug() << (success == -1 ? "Starting the process failed" 
241                         : "Process started, but exited before opening a terminal");
242
243                 if (success < -1)
244                         tryTerminate();
245             }
246         
247             status = (success == 0);
248         }
249
250         return status;
251 }
252
253 void VmConsoleWidget::termProcessExited(int a, QProcess::ExitStatus b) {
254         qDebug() << "Term Process Exited: " << a << " :  " << b;
255
256         if (mTermProcess != NULL) {
257             delete mTermProcess;
258         }
259
260         if (mVncServer != NULL) {
261             delete mVncServer;
262         }
263
264         mTermProcess = NULL;
265         mVncServer = NULL;
266
267         emit exited();
268 }
269
270 void VmConsoleWidget::errorMessage(QProcess::ProcessError err) {
271         qDebug() << "Process error: " << err;
272 }