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
Abhinav Kannan [Fri, 21 Dec 2012 19:26:04 +0000 (13:26 -0600)]
36 files changed:
linux_usr/gui/Palacios.pro [new file with mode: 0644]
linux_usr/gui/Palacios.pro.locallibs [new file with mode: 0644]
linux_usr/gui/README [new file with mode: 0644]
linux_usr/gui/images/activate_vm.png [new file with mode: 0644]
linux_usr/gui/images/exit.png [new file with mode: 0644]
linux_usr/gui/images/icon_no_preview.png [new file with mode: 0644]
linux_usr/gui/images/new_vm.png [new file with mode: 0644]
linux_usr/gui/images/palacios.png [new file with mode: 0755]
linux_usr/gui/images/pause_vm.png [new file with mode: 0644]
linux_usr/gui/images/reload_vm.png [new file with mode: 0644]
linux_usr/gui/images/start_vm.png [new file with mode: 0644]
linux_usr/gui/images/stop_vm.png [new file with mode: 0644]
linux_usr/gui/images/vm_pause.png [new file with mode: 0644]
linux_usr/gui/images/vm_refresh.png [new file with mode: 0644]
linux_usr/gui/images/vm_start.png [new file with mode: 0644]
linux_usr/gui/images/vm_stop.png [new file with mode: 0644]
linux_usr/gui/palacios/defs.h [new file with mode: 0644]
linux_usr/gui/palacios/main.cpp [new file with mode: 0644]
linux_usr/gui/palacios/newpalacios.cpp [new file with mode: 0644]
linux_usr/gui/palacios/newpalacios.h [new file with mode: 0644]
linux_usr/gui/palacios/vm_console_widget.cpp [new file with mode: 0644]
linux_usr/gui/palacios/vm_console_widget.h [new file with mode: 0644]
linux_usr/gui/palacios/vm_creation_wizard.cpp [new file with mode: 0644]
linux_usr/gui/palacios/vm_creation_wizard.h [new file with mode: 0644]
linux_usr/gui/palacios/vm_info_widget.cpp [new file with mode: 0644]
linux_usr/gui/palacios/vm_mode_dialog.cpp [new file with mode: 0644]
linux_usr/gui/palacios/vm_threads.cpp [new file with mode: 0644]
linux_usr/gui/palacios/vm_view.cpp [new file with mode: 0644]
linux_usr/gui/palacios/vnc_module/remoteview.cpp [new file with mode: 0644]
linux_usr/gui/palacios/vnc_module/remoteview.h [new file with mode: 0644]
linux_usr/gui/palacios/vnc_module/vncclientthread.cpp [new file with mode: 0644]
linux_usr/gui/palacios/vnc_module/vncclientthread.h [new file with mode: 0644]
linux_usr/gui/palacios/vnc_module/vncview.cpp [new file with mode: 0644]
linux_usr/gui/palacios/vnc_module/vncview.h [new file with mode: 0644]
linux_usr/gui/palacios_resources.qrc [new file with mode: 0644]
linux_usr/gui/report.pdf [new file with mode: 0644]

diff --git a/linux_usr/gui/Palacios.pro b/linux_usr/gui/Palacios.pro
new file mode 100644 (file)
index 0000000..1b75532
--- /dev/null
@@ -0,0 +1,31 @@
+TEMPLATE = app
+TARGET = Palacios
+QT += core \
+    gui \
+    xml
+CONFIG += debug_and_release
+DEFINES += QTONLY
+
+LIBS += -lvncclient -lgnutls -lX11
+
+
+HEADERS += palacios/vm_console_widget.h \
+    palacios/vm_creation_wizard.h \
+    palacios/newpalacios.h \
+    palacios/defs.h \
+    palacios/vnc_module/remoteview.h \
+    palacios/vnc_module/vncclientthread.h \
+    palacios/vnc_module/vncview.h
+SOURCES += palacios/vm_view.cpp \
+    palacios/vm_console_widget.cpp \
+    palacios/vm_mode_dialog.cpp \
+    palacios/vm_info_widget.cpp \
+    palacios/vm_creation_wizard.cpp \
+    palacios/main.cpp \
+    palacios/newpalacios.cpp \
+    palacios/vm_threads.cpp \
+    palacios/vnc_module/remoteview.cpp \
+    palacios/vnc_module/vncclientthread.cpp \
+    palacios/vnc_module/vncview.cpp
+FORMS += 
+RESOURCES += palacios_resources.qrc
diff --git a/linux_usr/gui/Palacios.pro.locallibs b/linux_usr/gui/Palacios.pro.locallibs
new file mode 100644 (file)
index 0000000..6704d76
--- /dev/null
@@ -0,0 +1,34 @@
+TEMPLATE = app
+TARGET = Palacios
+QT += core \
+    gui \
+    xml
+CONFIG += debug_and_release
+DEFINES += QTONLY
+
+INCLUDEPATH += . \
+        $$PWD/ext/include
+DEPENDPATH += . \
+        $$PWD/external_libs/include
+LIBS += -L$$PWD/ext/lib -lvncclient -lgnutls
+
+HEADERS += palacios/vm_console_widget.h \
+    palacios/vm_creation_wizard.h \
+    palacios/newpalacios.h \
+    palacios/defs.h \
+    palacios/vnc_module/remoteview.h \
+    palacios/vnc_module/vncclientthread.h \
+    palacios/vnc_module/vncview.h
+SOURCES += palacios/vm_view.cpp \
+    palacios/vm_console_widget.cpp \
+    palacios/vm_mode_dialog.cpp \
+    palacios/vm_info_widget.cpp \
+    palacios/vm_creation_wizard.cpp \
+    palacios/main.cpp \
+    palacios/newpalacios.cpp \
+    palacios/vm_threads.cpp \
+    palacios/vnc_module/remoteview.cpp \
+    palacios/vnc_module/vncclientthread.cpp \
+    palacios/vnc_module/vncview.cpp
+FORMS += 
+RESOURCES += palacios_resources.qrc
diff --git a/linux_usr/gui/README b/linux_usr/gui/README
new file mode 100644 (file)
index 0000000..867c9b0
--- /dev/null
@@ -0,0 +1,75 @@
+This directory contains an implementation of a graphical user
+interface for Palacios VMs, analogous to the "server console" tool in
+VMware or VirtualBox, etc.  The GUI builds directly on top of the
+Palacios command-line utilities.  
+
+The GUI was initially implemented by Abhinav Kannan and is:
+
+(c) 2012 Abhinav Kannan
+(c) 2012 V3VEE Project
+
+As with other Linux interface components of Palacios, it is released
+under GPL.  Palacios itself is released under a BSD license. 
+
+
+PREREQUISITES
+=============
+
+To build the GUI, you will need to install various libraries and
+components.  Specifically, you need:
+
+- QT4
+- QT4 development support and tools (qmake)
+- LibVNCServer
+- GNUTLS and GNUTLS development support
+
+
+The easiest way to do this is to become root and then use
+your package manager.  
+
+For example, on a Red Hat or Fedora system:
+
+su - (become root)
+yum install qt4
+yum install qt4-devel
+yum install libvncsever
+yum install libvncserver-devel
+yum install gnutls
+yum install gnutls-devel
+exit (return to normal user)
+
+If you need to set up as a none-root user, please see the file
+report.pdf.  
+   
+
+BUILDING
+========
+
+1. Use qmake to build a Makefile for your machine:
+
+qmake Palacos.Pro
+
+2. make it
+
+make 
+
+3. you should now have an executable file "Palacios"
+   this will become palacios/linux_usr/v3_x0gui
+   and will be wrapped by the script palacios/linux_usr/v3_gui
+
+If you would like to change things, please read report.pdf.
+The "Palacios.pro" file mentioned in the report is 
+included here as "Palacios.pro.locallibs"
+
+RUNNING
+=======
+
+To run the GUI, the Palacios command-line utilities and xterm need to
+be on your path, and v3vee.ko kernel module must be inserted into
+the running kernel.    For example:
+
+export PATH=$PATH:/home/foo/palacios/linxu_usr:/path/to/xterm
+insmod /home/foo/palacios/v3vee.ko
+Palacios &
+
+
diff --git a/linux_usr/gui/images/activate_vm.png b/linux_usr/gui/images/activate_vm.png
new file mode 100644 (file)
index 0000000..d92f6f7
Binary files /dev/null and b/linux_usr/gui/images/activate_vm.png differ
diff --git a/linux_usr/gui/images/exit.png b/linux_usr/gui/images/exit.png
new file mode 100644 (file)
index 0000000..2feef30
Binary files /dev/null and b/linux_usr/gui/images/exit.png differ
diff --git a/linux_usr/gui/images/icon_no_preview.png b/linux_usr/gui/images/icon_no_preview.png
new file mode 100644 (file)
index 0000000..a9cd4f3
Binary files /dev/null and b/linux_usr/gui/images/icon_no_preview.png differ
diff --git a/linux_usr/gui/images/new_vm.png b/linux_usr/gui/images/new_vm.png
new file mode 100644 (file)
index 0000000..b0a8667
Binary files /dev/null and b/linux_usr/gui/images/new_vm.png differ
diff --git a/linux_usr/gui/images/palacios.png b/linux_usr/gui/images/palacios.png
new file mode 100755 (executable)
index 0000000..2d1a539
Binary files /dev/null and b/linux_usr/gui/images/palacios.png differ
diff --git a/linux_usr/gui/images/pause_vm.png b/linux_usr/gui/images/pause_vm.png
new file mode 100644 (file)
index 0000000..a116757
Binary files /dev/null and b/linux_usr/gui/images/pause_vm.png differ
diff --git a/linux_usr/gui/images/reload_vm.png b/linux_usr/gui/images/reload_vm.png
new file mode 100644 (file)
index 0000000..541ffad
Binary files /dev/null and b/linux_usr/gui/images/reload_vm.png differ
diff --git a/linux_usr/gui/images/start_vm.png b/linux_usr/gui/images/start_vm.png
new file mode 100644 (file)
index 0000000..32fb017
Binary files /dev/null and b/linux_usr/gui/images/start_vm.png differ
diff --git a/linux_usr/gui/images/stop_vm.png b/linux_usr/gui/images/stop_vm.png
new file mode 100644 (file)
index 0000000..8dd6826
Binary files /dev/null and b/linux_usr/gui/images/stop_vm.png differ
diff --git a/linux_usr/gui/images/vm_pause.png b/linux_usr/gui/images/vm_pause.png
new file mode 100644 (file)
index 0000000..8a8d4fa
Binary files /dev/null and b/linux_usr/gui/images/vm_pause.png differ
diff --git a/linux_usr/gui/images/vm_refresh.png b/linux_usr/gui/images/vm_refresh.png
new file mode 100644 (file)
index 0000000..8ff580b
Binary files /dev/null and b/linux_usr/gui/images/vm_refresh.png differ
diff --git a/linux_usr/gui/images/vm_start.png b/linux_usr/gui/images/vm_start.png
new file mode 100644 (file)
index 0000000..437811d
Binary files /dev/null and b/linux_usr/gui/images/vm_start.png differ
diff --git a/linux_usr/gui/images/vm_stop.png b/linux_usr/gui/images/vm_stop.png
new file mode 100644 (file)
index 0000000..d8e7799
Binary files /dev/null and b/linux_usr/gui/images/vm_stop.png differ
diff --git a/linux_usr/gui/palacios/defs.h b/linux_usr/gui/palacios/defs.h
new file mode 100644 (file)
index 0000000..424f88b
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * defs.h
+ *
+ *  Created on: Oct 4, 2012
+ *      Author: Abhinav Kannan
+ */
+
+#ifndef DEFS_H_
+#define DEFS_H_
+
+const char* STATUS_BAR_MSG_READY = "Ready";
+
+const char* TITLE_MAIN_WINDOW = "Palacios";
+const char* TITLE_DOCK_TELEMETRY = "Kernel messages";
+const char* TITLE_DOCK_VM_LIST = "List of VMs";
+
+const char* MENU_FILE = "File";
+const char* MENU_VIEW = "View";
+const char* MENU_VM = "VM";
+const char* MENU_HELP = "Help";
+
+const char* FILE_MENU_NEW_VM = "New VM";
+const char* NEW_VM_STATUS_TIP = "Create a new virtual machine";
+const char* FILE_MENU_EXIT = "Exit";
+const char* EXIT_STATUS_TIP = "Exit Palacios VMM";
+
+const char* VM_MENU_START = "Start VM";
+const char* VM_MENU_STOP = "Stop VM";
+const char* VM_MENU_PAUSE = "Pause VM";
+const char* VM_MENU_RESTART = "Restart VM";
+const char* VM_MENU_REMOVE = "Delete VM";
+const char* VM_MENU_ACTIVATE = "Activate VM";
+const char* VM_MENU_RELOAD = "Reload VMs";
+
+const char* VM_STOP_WARNING_MESSAGE = "You are about to stop a running virtual machine. Please stop all executing processes"
+               "within the virtual machine to insure safe termination of VM. Do you want to continue?";
+const char* VM_DELETE_WARNING_MESSAGE = "Are you sure you want to delete this VM?";
+const char* DELETE_RUNNING_VM_ERROR = "This VM is currently running! Please stop the VM before deleting";
+
+const char* HELP_MENU_ABOUT = "About Palacios";
+const char* ABOUT_PALACIOS =
+               "Palacios is a virtual machine monitor (VMM) "
+                               "that is available for public use as a community resource. Palacios is highly configurable "
+                               "and designed to be embeddable into different host operating systems, such as Linux and the "
+                               "Kitten lightweight kernel. Palacios is a non-paravirtualized VMM that makes extensive use of "
+                               "the virtualization extensions in modern Intel and AMD x86 processors. "
+                               "Palacios is a compact codebase that has been designed to be easy to understand and readily "
+                               "configurable for different environments. It is unique in being designed to be embeddable into "
+                               "other OSes instead of being implemented in the context of a specific OS. Palacios is distributed under the BSD license."
+
+                               "\nPalacios is part of the V3VEE Project";
+
+const char* XTERM_CMD = "/usr/bin/xterm";
+
+const char* FILE_VM_LIST = "virtual_machines_list.txt";
+
+const char* TAG_VM = "vm";
+
+const char* ERROR_TELEMETRY = "Telemetry information currently unavailable";
+
+const char* LABEL_ACTIVE_INVENTORY = "Active Inventory";
+const char* LABEL_ACTIVE_NOT_INVENTORY = "Not in inventory";
+const char* LABEL_INACTIVE_INVENTORY = "Inactive Inventory";
+
+const char* ERROR_SETUP_MODULE_INSTALL = "Kernel Module not installed";
+const char* ERROR_SETUP_MODULE_INSTALL_FAILED = "Kernel module not installed correctly";
+const char* ERROR_SETUP_MEMORY = "Memory not intialized";
+
+const char* ERROR_APP_CLOSE = "There are running VMs in the current session. Stop or pause the VMs before exiting";
+const char* ERROR_VM_RUNNING = "VM is already running";
+const char* ERROR_UPDATE_VM_STATE = "Error could not update VM state";
+const char* ERROR_RUN_ACTIVE_NOT_INVENTORY = "VM instance exists on the system but has not been added to the inventory. Activate VM to proceed";
+const char* ERROR_RUN_INACTIVE_INVENTORY = "VM instance has not been activated";
+const char* ERROR_NO_DEVFILE_FOR_LAUNCH = "Could not find /dev/v3-vm# file to launch VM";
+const char* ERROR_STOP_VM = "VM is not running";
+const char* ERROR_VM_NOT_INVENTORY = "Cannot stop VM. VM is either inactive or not available in inventory";
+const char* ERROR_LAUNCH_VM_DEVICE_NOT_FOUND = "Error launching VM! Device file not found";
+const char* ERROR_LAUNCH_VM_IOCTL = "VM Launch: IOCTL error! Check kernel logs for details";
+const char* ERROR_STOP_VM_PATH = "Error executing stop command. Check path variable";
+const char* ERROR_STOP_VM_IOCTL = "VM Stop: IOCTL error! Check kernel logs for details";
+const char* ERROR_STOP_VM_DEVICE_NOT_FOUND = "Could not stop VM! Device file not found";
+const char* ERROR_PAUSE_VM_IOCTL = "VM Pause: IOCTL error! Check kernel logs for details";
+const char* ERROR_PAUSE_VM_DEVICE_NOT_FOUND = "Error pausing VM! Could not open device file";
+const char* ERROR_RESTART_VM_IOCTL = "VM Restart: IOCTL error! Check kernel logs for details";
+const char* ERROR_RESTART_VM_DEVICE_NOT_FOUND = "Error restarting VM! Device file not found.";
+
+const char* ERROR_VM_CREATE_PATH = "VM creation failed: Check PATH variable";
+const char* ERROR_VM_CREATE_IOCTL = "VM creation failed: Check kernel logs for more details";
+const char* ERROR_VM_CREATE_DB = "VM creation failed: Could not save VM. Error in database";
+const char* ERROR_VM_CREATE_PROC = "VM creation failed: Unable to get dev file";
+const char* ERROR_VM_CREATE_FAILED = "VM creation failed: Could not create dev file for new VM. Check kernel logs for more details";
+const char* SUCCESS_VM_ADDED = "VM added to inventory. Activate to use";
+const char* SUCCESS_VM_CREATE = "VM created successfully!";
+
+const char* VM_TAB_TITLE = "VM Details";
+
+const char* ERROR_VM_LAUNCH = "VM Launch failed: Check kernel logs for details";
+
+const char* ERROR_VM_DELETE_PATH = "VM Deletion failed: Check PATH variable";
+const char* ERROR_VM_DELETE_IOCTL = "VM Deletion failed: Check kernel logs for more details";
+const char* ERROR_VM_DELETE_DB = "VM Deletion failed: Database error";
+const char* ERROR_VM_DELETE_INVALID_ARGUMENT = "VM Deletion failed: Could not find dev file!";
+const char* SUCCESS_VM_DELETE = "VM deleted successfully";
+#endif /* DEFS_H_ */
diff --git a/linux_usr/gui/palacios/main.cpp b/linux_usr/gui/palacios/main.cpp
new file mode 100644 (file)
index 0000000..74cd084
--- /dev/null
@@ -0,0 +1,23 @@
+#include "newpalacios.h"
+
+int main(int argc, char *argv[])
+{
+    QApplication a(argc, argv);
+    NewPalacios w;
+    /*int checkSetup = w.checkPalacios();
+
+    if (checkSetup == -1) {
+        a.exit();
+        return 0;
+    } else {
+        w.setMinimumSize(820, 640);
+        w.showMaximized();
+        return a.exec();
+    }*/
+    
+    w.setMinimumSize(820, 640);
+    w.showMaximized();
+    //w.checkPalacios();
+    int eventLoop = a.exec();
+    return eventLoop;
+}
diff --git a/linux_usr/gui/palacios/newpalacios.cpp b/linux_usr/gui/palacios/newpalacios.cpp
new file mode 100644 (file)
index 0000000..35d14a4
--- /dev/null
@@ -0,0 +1,1450 @@
+#include <QMessageBox>
+#include <QDebug>
+#include <QtGui>
+#include <QtAlgorithms>
+
+#include "newpalacios.h"
+#include "defs.h"
+
+NewPalacios::NewPalacios(QWidget *parent) :
+               QMainWindow(parent) {
+
+       // Call UI setup methods
+       createWizard();
+       createCentralWidget();
+       createActions();
+       createMenus();
+       createToolBars();
+       createStatusBar();
+       createDockWindows();
+               readExistingVmsFile();
+
+       setWindowTitle(tr(TITLE_MAIN_WINDOW));
+
+        mExitAppFromMenu = false;
+}
+
+NewPalacios::~NewPalacios() {
+    // Cleanup actions
+    delete mExitApp;
+    delete mVmNew;
+    delete mVmStop;
+    delete mVmPause;
+    delete mVmStart;
+    delete mVmActivate;
+    delete mReloadVms;
+    delete mAboutApp;
+
+    // Clean up menu
+    delete mFileMenu;
+    delete mViewMenu;
+    delete mVmMenu;
+    delete mHelpMenu;
+
+    // Clean up toolbar
+    delete mVmToolBar;
+    delete mVmCtrlToolBar;
+
+    /*if (mLoadVmsThread != NULL)
+        delete mLoadVmsThread;
+    if (mAddVmThread != NULL)
+        delete mAddVmThread;
+    if (mDeleteVmThread != NULL)
+        delete mDeleteVmThread;*/
+
+    delete mVmTreeView;
+    delete mVmTelemetryView;
+    delete mVmWizard;
+    delete mVmInfoWidget;
+
+    // Delete the central widget at the end
+    delete mVmControlPanel;
+}
+
+void NewPalacios::createCentralWidget() {
+        // The VM View will be the central widget
+        // of this window. The List of VMs will
+        // be docked in the left corner
+       mVmControlPanel = new QTabWidget();
+        mVmControlPanel->setTabsClosable(true);
+        connect(mVmControlPanel, SIGNAL(tabCloseRequested(int)), 
+                this, SLOT(vmTabClosed(int)));
+
+        mVmInfoWidget = new VmInfoWidget(mVmControlPanel);
+        
+        // Set the widget to the window
+        this->setCentralWidget(mVmControlPanel);
+}
+
+void NewPalacios::createActions() {
+       mVmNew = new QAction(QIcon(":/images/images/new_vm.png"),
+                       tr(FILE_MENU_NEW_VM), this);
+       connect(mVmNew, SIGNAL(triggered()), this, SLOT(createVmInstance()));
+
+       mExitApp = new QAction(QIcon(":/images/images/exit.png"),
+                       tr(FILE_MENU_EXIT), this);
+       connect(mExitApp, SIGNAL(triggered()), this, SLOT(exitApplication()));
+
+       mVmStart = new QAction(QIcon(":/images/images/start_vm.png"),
+                       tr(VM_MENU_START), this);
+       connect(mVmStart, SIGNAL(triggered()), this, SLOT(selectVmMode()));
+
+       mVmStop = new QAction(QIcon(":/images/images/stop_vm.png"),
+                       tr(VM_MENU_STOP), this);
+        connect(mVmStop, SIGNAL(triggered()), this, SLOT(stopVm()));
+
+       mVmPause = new QAction(QIcon(":/images/images/pause_vm.png"),
+                       tr(VM_MENU_PAUSE), this);
+        connect(mVmPause, SIGNAL(triggered()), this, SLOT(pauseVm()));
+
+       mVmActivate = new QAction(QIcon(":/images/images/activate_vm.png"),
+                       tr(VM_MENU_ACTIVATE), this);
+        connect(mVmActivate, SIGNAL(triggered()), this, SLOT(activateVm()));
+
+       mAboutApp = new QAction(tr(HELP_MENU_ABOUT), this);
+       connect(mAboutApp, SIGNAL(triggered()), this, SLOT(aboutPalacios()));
+       
+       mReloadVms = new QAction(QIcon(":/images/images/reload_vm.png"), tr(VM_MENU_RELOAD), this);
+       connect(mReloadVms, SIGNAL(triggered()), this, SLOT(reloadVms()));
+
+       connect(mVmWizard, SIGNAL(accepted()), this, SLOT(addNewVm()));
+}
+
+void NewPalacios::createMenus() {
+       mFileMenu = menuBar()->addMenu(tr(MENU_FILE));
+       mFileMenu->addAction(mVmNew);
+       mFileMenu->addSeparator();
+       mFileMenu->addAction(mExitApp);
+
+       mViewMenu = menuBar()->addMenu(tr(MENU_VIEW));
+
+       mVmMenu = menuBar()->addMenu(tr(MENU_VM));
+       mVmMenu->addAction(mVmStart);
+       mVmMenu->addAction(mVmStop);
+       mVmMenu->addAction(mVmPause);
+       mVmMenu->addAction(mVmActivate);
+       mVmMenu->addAction(mReloadVms);
+
+       mHelpMenu = menuBar()->addMenu(tr(MENU_HELP));
+       mHelpMenu->addAction(mAboutApp);
+}
+
+void NewPalacios::createToolBars() {
+       mVmToolBar = addToolBar(tr(MENU_FILE));
+       mVmToolBar->addAction(mVmNew);
+
+       mVmCtrlToolBar = addToolBar(tr(MENU_VM));
+       mVmCtrlToolBar->addAction(mVmStart);
+       mVmCtrlToolBar->addAction(mVmStop);
+       mVmCtrlToolBar->addAction(mVmPause);
+       mVmCtrlToolBar->addAction(mVmActivate);
+       mVmCtrlToolBar->addAction(mReloadVms);
+}
+
+void NewPalacios::createStatusBar() {
+       statusBar()->showMessage(tr(STATUS_BAR_MSG_READY));
+}
+
+void NewPalacios::createDockWindows() {
+       QDockWidget* dockVmList = new QDockWidget(tr(TITLE_DOCK_VM_LIST), this);
+              
+        // Setup VM instance tree view
+        mVmTreeView = new QTreeWidget(dockVmList);
+        mVmTreeView->setColumnCount(1);
+        mVmTreeView->headerItem()->setHidden(true);
+        // Header for active VMs
+        QTreeWidgetItem* activeVms = new QTreeWidgetItem(mVmTreeView);
+        activeVms->setText(0, tr(LABEL_ACTIVE_INVENTORY));
+        mVmTreeView->addTopLevelItem(activeVms);
+        
+        // Header for inactive VMs in the inventory
+        QTreeWidgetItem* inactiveVms = new QTreeWidgetItem(mVmTreeView);
+        inactiveVms->setText(0, tr(LABEL_INACTIVE_INVENTORY));
+        mVmTreeView->addTopLevelItem(inactiveVms);
+        
+        // Header for active VMs not in inventory
+        QTreeWidgetItem* activeNotInventoryVms = new QTreeWidgetItem(mVmTreeView);
+        activeNotInventoryVms->setText(0, tr(LABEL_ACTIVE_NOT_INVENTORY));
+        mVmTreeView->addTopLevelItem(activeNotInventoryVms);
+        
+        mVmTreeView->setContextMenuPolicy(Qt::CustomContextMenu);
+        connect(mVmTreeView, SIGNAL(customContextMenuRequested(const QPoint &)),
+                    this, SLOT(vmContextMenu(const QPoint &)));
+        connect(mVmTreeView, SIGNAL(itemClicked(QTreeWidgetItem*, int)), this,
+                    SLOT(vmItemClickListener(QTreeWidgetItem*, int)));
+
+        dockVmList->setAllowedAreas(Qt::LeftDockWidgetArea);
+       dockVmList->setFeatures(QDockWidget::DockWidgetClosable);
+       dockVmList->setWidget(mVmTreeView);
+       addDockWidget(Qt::LeftDockWidgetArea, dockVmList);
+       mViewMenu->addAction(dockVmList->toggleViewAction());
+       
+       // Telemetry dock
+       QDockWidget* dockTelemetry = new QDockWidget(tr(TITLE_DOCK_TELEMETRY), this);
+       mVmTelemetryView = new QTextEdit(dockTelemetry);
+       mVmTelemetryView->setReadOnly(true);
+       dockTelemetry->setAllowedAreas(Qt::BottomDockWidgetArea);
+       dockTelemetry->setFeatures(QDockWidget::NoDockWidgetFeatures);
+       dockTelemetry->setWidget(mVmTelemetryView);
+       addDockWidget(Qt::BottomDockWidgetArea, dockTelemetry);
+       connect(dockTelemetry, SIGNAL(visibilityChanged(bool)), this, SLOT(updateTelemetry(bool)));
+}
+
+void NewPalacios::updateTelemetry(bool visible) {
+       if (visible) {
+               mTelemProc = new QProcess();
+               mTelemProc->setProcessChannelMode(QProcess::MergedChannels);
+               QStringList args;
+               args << "-c" << "tail -f /var/log/messages";
+               
+               // Slots used for debugging
+                //connect(mTelemProc, SIGNAL(started()), this, SLOT(processStarted()));
+                //connect(mTelemProc, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(processExit(int, QProcess::ExitStatus)));
+                //connect(mTelemProc, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processError(QProcess::ProcessError)));
+                
+                // Connect output of dmesg to text widget
+                connect(mTelemProc, SIGNAL(readyReadStandardOutput()), this, SLOT(updateTelemetryView()));
+                
+                mTelemProc->start("sh", args);
+                if (!mTelemProc->waitForStarted()) {
+                       if (mVmTelemetryView != NULL) {
+                               mVmTelemetryView->setText(tr(ERROR_TELEMETRY));
+                       }
+                }
+        } else {
+                /*if (mTelemProc != NULL) {
+                       mTelemProc->close();
+                       mTelemProc->terminate();
+                        delete mTelemProc;
+                }*/
+        }
+}
+
+void NewPalacios::updateTelemetryView() {
+       if (mVmTelemetryView != NULL && mTelemProc != NULL) {
+               mVmTelemetryView->setText(mTelemProc->readAllStandardOutput());
+       }
+}
+
+void NewPalacios::createWizard() {
+       mVmWizard = new NewVmWizard();
+}
+
+// Listener for VM item clicks
+void NewPalacios::vmItemClickListener(QTreeWidgetItem* item, int col) {
+        if (item->text(0).compare(LABEL_ACTIVE_INVENTORY) == 0
+                || item->text(0).compare(LABEL_INACTIVE_INVENTORY) == 0
+                || item->text(0).compare(LABEL_ACTIVE_NOT_INVENTORY) == 0) {
+                // If user clicks on the main headers
+                // do nothing
+                isHeaderClicked = true;
+                return;
+        }
+        
+        isHeaderClicked = false;
+
+       QString vmName = item->text(col);
+        mVmName = vmName;
+        
+        // Locate the VM clicked in the list. This is inefficient because each time we need 
+        // to search the list. If a better way is found. replace here
+       VmInfo* vm = NULL;
+       for (int i = 0; i < mVmList.size(); i++) {
+               if (vmName.compare(mVmList[i]->getVmName()) == 0) {
+                        mVmPos = i;
+                       vm = mVmList[i];
+                       break;
+               }
+       }
+        // Load the details of the seleted VM
+       if (vm != NULL) {
+            mVmInfoWidget->updateInfoView(vm);
+        }
+}
+
+void NewPalacios::vmContextMenu(const QPoint &pos) {
+       //QPoint globalPos = mVmListView->mapToGlobal(pos);
+       QPoint globalPos = mVmTreeView->mapToGlobal(pos);
+        
+        QTreeWidgetItem* item = mVmTreeView->itemAt(pos);
+        if (item->text(0).compare(LABEL_ACTIVE_INVENTORY) == 0
+                || item->text(0).compare(LABEL_INACTIVE_INVENTORY) == 0
+                || item->text(0).compare(LABEL_ACTIVE_NOT_INVENTORY) == 0) {
+               // Clicked on the headers
+                // do nothing
+                isHeaderClicked = true;
+                return;
+        }
+        
+        isHeaderClicked = false;
+        
+        // Update VM pos, the global index locator for VMs
+        QString vmName = item->text(0);
+        // Update global VM name
+        mVmName = vmName;
+        for (int i=0; i<mVmList.size(); i++) {
+                if (vmName.compare(mVmList[i]->getVmName()) == 0) {
+                        mVmPos = i;
+                        break;
+                }
+        }
+        
+        QMenu *menu = new QMenu();
+        if (mVmList[mVmPos]->getCategory() == VmInfo::INACTIVE_INVENTORY
+               || mVmList[mVmPos]->getCategory() == VmInfo::ACTIVE_NOT_INVENTORY) {
+               
+                menu->addAction(new QAction(tr(VM_MENU_ACTIVATE), this));
+        } else {
+                if (mVmList[mVmPos]->getState() == VmInfo::RUNNING) {
+                        menu->addAction(new QAction(tr(VM_MENU_PAUSE), this));
+
+                } else if (mVmList[mVmPos]->getState() == VmInfo::PAUSED) {
+                        menu->addAction(new QAction(tr(VM_MENU_RESTART), this));
+        
+                } else if (mVmList[mVmPos]->getState() == VmInfo::STOPPED) {
+                        menu->addAction(new QAction(tr(VM_MENU_START), this));
+       
+                }
+                menu->addAction(new QAction(tr(VM_MENU_STOP), this));
+       }
+        
+        menu->addAction(new QAction(tr(VM_MENU_REMOVE), this));
+        
+        QAction* selectedAction = menu->exec(globalPos);
+        if (selectedAction == NULL) {
+               // User did not select any option
+                return;
+        }
+       
+        QString actionItem = selectedAction->text();
+       if (actionItem.compare(tr(VM_MENU_START)) == 0
+                    || actionItem.compare(tr(VM_MENU_RESTART)) == 0) {
+                // If VM was stopped or paused
+                selectVmMode();
+
+       } else if (actionItem.compare(tr(VM_MENU_PAUSE)) == 0) {
+                // Pause VM
+                pauseVm();
+
+        } else if (actionItem.compare(tr(VM_MENU_RESTART)) == 0) {
+                // Restart VM
+                restartVm();
+        
+        } else if (actionItem.compare(tr(VM_MENU_STOP)) == 0) {
+               // Stop the VM if possible
+               stopVm();
+
+       } else if (actionItem.compare(tr(VM_MENU_REMOVE)) == 0) {
+                bool isVmRunning = false;
+                for (int i=0; i < mRunningVms.size(); i++) {
+                        if (mVmName.compare(mRunningVms[i]->getVmName()) == 0) {
+                                isVmRunning = true;
+                                break;
+                        }
+                }
+                
+               QMessageBox vmDeleteWarningBox;
+
+               if (isVmRunning) {
+                       vmDeleteWarningBox.setText(DELETE_RUNNING_VM_ERROR);
+                       vmDeleteWarningBox.setIcon(QMessageBox::Critical);
+               } else {
+                       vmDeleteWarningBox.setText(VM_DELETE_WARNING_MESSAGE);
+                       vmDeleteWarningBox.setIcon(QMessageBox::Warning);
+               }
+
+               vmDeleteWarningBox.setStandardButtons(
+                               QMessageBox::Ok | QMessageBox::Cancel);
+               vmDeleteWarningBox.setDefaultButton(QMessageBox::Cancel);
+               int retVal = vmDeleteWarningBox.exec();
+
+               switch (retVal) {
+               case QMessageBox::Ok:
+                       if (!isVmRunning) {
+                               deleteVm(mVmName);
+                       }
+                       break;
+               case QMessageBox::Cancel:
+                       break;
+               }
+               
+       } else if (actionItem.compare(tr(VM_MENU_ACTIVATE)) == 0) {
+                activateVm();
+                return;
+        }
+
+}
+
+void NewPalacios::aboutPalacios() {
+       QMessageBox::about(this, tr(HELP_MENU_ABOUT), tr(ABOUT_PALACIOS));
+}
+
+// This function checks for the necessary setup
+// required by palacios to run. The setup for palacios
+// includes:
+// 1. Check for v3vee.ko module
+// 2. Check if palacios has been allocated memory
+void NewPalacios::checkPalacios() {
+       int err = 0;
+        QMessageBox setupError;
+        setupError.setStandardButtons(QMessageBox::Ok);
+        setupError.setIcon(QMessageBox::Critical);
+        
+        // v3vee.ko check
+        QProcess* v3 = new QProcess();
+        v3->setProcessChannelMode(QProcess::MergedChannels);
+        v3->start("lsmod");
+        v3->waitForFinished();
+        QByteArray reply = v3->readAllStandardOutput();
+
+        if (reply.isEmpty() || !reply.contains("v3vee")) {
+                       setupError.setText(tr(ERROR_SETUP_MODULE_INSTALL));
+                err = -1;
+        }
+        
+        QFile file("/proc/v3vee/v3-mem");
+        if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+                setupError.setText(tr(ERROR_SETUP_MODULE_INSTALL_FAILED));
+                err = -1;
+        }
+
+        QTextStream in(&file);
+
+        while(in.atEnd()) {
+                QString line = in.readLine();
+                if (line.contains("null")) {
+                        setupError.setText(tr(ERROR_SETUP_MEMORY));
+                        err = -1;
+                        break;
+                }
+        }
+        
+       if (err != 0) {
+               int ret = setupError.exec();
+               
+               if (ret == QMessageBox::Ok) {
+                       // Palacios not setup correctly, exit
+                       this->close();
+               }
+       }
+}
+
+void NewPalacios::closeEvent(QCloseEvent* event) {
+        if (mExitAppFromMenu == true) {
+            event->accept();
+            return;
+        }
+
+        bool flag = false;
+
+        for (int i=0; i<mVmList.size(); i++) {
+                if (mVmList[i]->getState() == VmInfo::RUNNING) {
+                        flag = true;
+                        break;
+                }
+        }
+
+        if (!flag) {
+               if (mTelemProc != NULL) {
+                       mTelemProc->close();
+                       mTelemProc->terminate();
+                        delete mTelemProc;
+               }
+                event->accept();
+        } else {
+                
+                QMessageBox appCloseWarning;
+                appCloseWarning.setText(tr("There are still running VMs. It is suggested to close the running VMs tab before exiting. Click cancel to go back"));
+                appCloseWarning.setIcon(QMessageBox::Warning);
+                appCloseWarning.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
+
+                int ret = appCloseWarning.exec();
+                switch (ret) {
+                case QMessageBox::Ok:
+                    event->accept();
+                    break;
+                case QMessageBox::Cancel:
+                    event->ignore();
+                    break;
+                }
+        }
+}
+
+void NewPalacios::exitApplication() {
+        QMessageBox appCloseWarning;
+        appCloseWarning.setText(tr("There are still running VMs. It is suggested to close the running VMs tab before exiting. Click cancel to go back"));
+        appCloseWarning.setIcon(QMessageBox::Warning);
+        appCloseWarning.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
+
+        bool flag = false;
+        
+        // Check if there are running VMs
+        for (int i=0; i<mVmList.size(); i++) {
+                if (mVmList[i]->getState() == VmInfo::RUNNING) {
+                        flag = true;
+                        break;
+                }
+        }
+        
+        // If there are no running VMs
+        // exit
+        if (!flag) {
+               if (mTelemProc != NULL) {
+                       mTelemProc->close();
+                       mTelemProc->terminate();
+                        delete mTelemProc;
+               }
+                mExitAppFromMenu = true;
+                this->close();
+        } else {
+                // Inform user about running VMs and ask for consent
+                // before closing application
+                int ret = appCloseWarning.exec();
+                switch (ret) {
+                case QMessageBox::Ok:
+                    mExitAppFromMenu = true;
+                    this->close();
+                    break;
+                case QMessageBox::Cancel:
+                    mExitAppFromMenu = false;
+                    break;
+                }
+       }
+}
+
+// Convenience method for showing messages
+void NewPalacios::showMessage(QString msg, bool err, bool warning) {
+        QMessageBox msgBox;
+        msgBox.setText(msg);
+        if (err == true) {
+                msgBox.setIcon(QMessageBox::Critical);
+        } else if (warning == true) {
+               msgBox.setIcon(QMessageBox::Warning);
+        }
+        
+        msgBox.setStandardButtons(QMessageBox::Ok);
+        msgBox.exec();
+}
+
+/*void NewPalacios::processStarted() {
+       //qDebug() << "Process started...";
+}
+
+void NewPalacios::processExit(int errorCode, QProcess::ExitStatus exitStatus) {
+       if (exitStatus == QProcess::CrashExit) {
+               //qDebug() << "The process crashed!!";
+       } else {
+               //qDebug() << "The process exited normally..";
+       }
+}
+
+void NewPalacios::processError(QProcess::ProcessError error) {
+       //qDebug() << "There was an error in the process execution...";
+       
+       switch (error) {
+       case QProcess::FailedToStart:
+               //qDebug() << "Process failed to start...";
+               break;
+       case QProcess::Crashed:
+               //qDebug() << "Process crashed...";
+               break;
+       case QProcess::Timedout:
+               //qDebug() << "Process timed out...";
+               break;
+       case QProcess::WriteError:
+               //qDebug() << "Process had write error...";
+               break;
+       case QProcess::ReadError:
+               //qDebug() << "Process had read error...";
+               break;
+       case QProcess::UnknownError:
+               //qDebug() << "Process unknown error...";
+               break;
+
+       }
+}*/
+
+void NewPalacios::createVmInstance() {
+       if (mVmWizard != NULL) {
+               mVmWizard->restart();
+               mVmWizard->show();
+       }
+}
+
+void NewPalacios::selectVmMode() {
+        if (isHeaderClicked) {
+                return;
+        }
+        
+        if (mVmList[mVmPos]->getCategory() != VmInfo::ACTIVE_INVENTORY) {
+                QMessageBox warning;
+                showMessage(tr("VM is not active!"), true);
+                return;
+        }
+           
+
+        if (mVmList[mVmPos]->getState() == VmInfo::PAUSED) {
+                // If machine is paused, we just restart using the previous selected mode
+                restartVm();
+        } else {
+                // Machine is started fresh
+                mVmModeDialog = new VmModeDialog(this);
+                connect(mVmModeDialog, SIGNAL(setMode(int, QString)), 
+                       this, SLOT(getVmMode(int, QString)));
+                mVmModeDialog->show();
+        }
+}
+
+void NewPalacios::getVmMode(int mode, QString streamName) {
+        mVmMode = mode;
+        mStreamName = streamName;
+        // Start VM
+        startVm();
+}
+
+void NewPalacios::startVm() {
+        if (mVmList.isEmpty()) {
+                // There is no VM in the list
+                return;
+        }
+        
+        // Check if we are trying to start an inactive VM
+        if (mVmList[mVmPos]->getCategory() == VmInfo::INACTIVE_INVENTORY) {
+                showMessage(tr(ERROR_RUN_INACTIVE_INVENTORY), true);
+                return;
+        }
+        
+        // Check if we are trying to start a VM not in the inventory
+        if (mVmList[mVmPos]->getCategory() == VmInfo::ACTIVE_NOT_INVENTORY) {
+                showMessage(tr(ERROR_RUN_ACTIVE_NOT_INVENTORY), true);
+                return;
+        }
+
+        int pos = 0;
+        // Check if the VM is already running        
+        for (int i=0; i < mRunningVms.size(); i++) {
+                if (mVmName.compare(mRunningVms[i]->getVmName()) == 0 
+                        && mVmMode != VmConsoleWidget::STREAM) {
+                        // If we are running the VM in stream mode then we
+                        // can have multiple streams open simultaneously
+                        // For the other modes, only one instance can be running
+                        showMessage(tr(ERROR_VM_RUNNING), true);
+                        return;
+                }
+        }
+       
+       QString v3_devfile = mVmList[mVmPos]->getVmDevFile();
+        if (v3_devfile == NULL) {
+                showMessage(tr(ERROR_NO_DEVFILE_FOR_LAUNCH), true);
+                return;
+        }
+        
+        int vm_status = mVmList[mVmPos]->getState();
+        
+        QProcess* v3LaunchProc = NULL;
+        QStringList args;
+        bool flag = false;
+        QByteArray message;
+
+        switch (vm_status) {
+            case VmInfo::STOPPED:
+                // If VM is stopped, launch it <v3_launch>
+                v3LaunchProc = new QProcess();
+                v3LaunchProc->setProcessChannelMode(QProcess::MergedChannels);
+                
+                // Connect debug slots
+                //connect(v3LaunchProc, SIGNAL(started()), this, SLOT(processStarted()));
+                //connect(v3LaunchProc, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(processExit(int, QProcess::ExitStatus)));
+                //connect(v3LaunchProc, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processError(QProcess::ProcessError)));
+                
+                args << v3_devfile;
+                v3LaunchProc->start("v3_launch", args);
+
+                flag = v3LaunchProc->waitForFinished();
+               message = v3LaunchProc->readAllStandardOutput();
+
+                if (!flag) {
+                        showMessage(tr(ERROR_VM_LAUNCH), true);
+                        delete v3LaunchProc;
+                        return;
+                        
+                } else if (message.contains("Error opening V3Vee VM device")) {
+                        showMessage(tr(ERROR_LAUNCH_VM_DEVICE_NOT_FOUND), true);
+                        delete v3LaunchProc;
+                        return;
+                       
+                } 
+
+                break;
+            /*case VmInfo::PAUSED:
+                // If VM is paused, call <v3_continue>
+                restartVm();
+                break;*/
+            case VmInfo::RUNNING:
+                // If VM is running, do nothing
+                // We will be just calling v3_cons_sc/v3_stream/vnc to
+                // connect to it
+                break;
+        }
+        
+        QString name = mVmList[mVmPos]->getVmName();
+        // Create a new console instance and set the launch file
+        VmXConsoleParent* consoleParent = new VmXConsoleParent(name);
+        
+        // Add it to list of running VMs
+        mRunningVms.append(consoleParent);
+        pos = mRunningVms.indexOf(consoleParent);
+        
+        // Launch in new tab
+        // Disable updates in widgets to reduce screen flicker
+        // due to layouting in widgets
+        consoleParent->setUpdatesEnabled(false);
+        mVmControlPanel->setUpdatesEnabled(false);
+        if (mVmMode != VmConsoleWidget::STREAM) {
+            // If not in stream mode, header will be VM name
+            mVmControlPanel->insertTab(mVmControlPanel->count(), consoleParent, name);
+        } else {
+            // If stream mode, header will be stream name
+            mVmControlPanel->insertTab(mVmControlPanel->count(), consoleParent, mStreamName);
+        }
+        mVmControlPanel->setCurrentWidget(consoleParent);
+        
+        // Start VM
+       consoleParent->showWidget(mVmMode, v3_devfile, mStreamName);
+        // Re-enable updates to widgets
+        mVmControlPanel->setUpdatesEnabled(true);
+        consoleParent->setUpdatesEnabled(true);
+
+        // Signal to tell the background xterm process to quit when console widget is closed
+        connect(mRunningVms[pos], SIGNAL(windowClosingWithId(QString)), this,
+                       SLOT(consoleWindowClosed(QString)));
+       // Update VM state
+        updateVmState(VmInfo::RUNNING);
+        
+        for (int i=0; i<mVmTreeView->topLevelItem(VmInfo::ACTIVE_INVENTORY)->childCount(); i++) {
+               QTreeWidgetItem* child = mVmTreeView->topLevelItem(VmInfo::ACTIVE_INVENTORY)->child(i);
+               if (mVmName.compare(child->text(0)) == 0) {
+                       child->setIcon(0, QIcon(":/images/images/start_vm.png"));
+                       break;
+               }
+        }
+}
+
+void NewPalacios::updateVmState(int mode) {
+        // TODO: Move this to a background thread
+        QString vm_name = mVmList[mVmPos]->getVmName();
+        
+        QFile file("virtual_machines_list.txt");
+        if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+                showMessage(tr(ERROR_UPDATE_VM_STATE), true);
+                stopVm();
+                return;
+        }
+
+        QFile temp("temp.txt");
+        if (!temp.open(QIODevice::WriteOnly | QIODevice::Text)) {
+                showMessage(tr(ERROR_UPDATE_VM_STATE), true);
+                stopVm();
+                return;
+        }
+
+        QTextStream in(&file);
+        QTextStream out(&temp);
+
+        while (!in.atEnd()) {
+                QString line = in.readLine();
+                if (line.compare("\n") == 0) {
+                       continue;
+                }
+                
+                QStringList vmDet = line.split(",");
+                QString nameStr = vmDet.at(0);
+
+                if (nameStr.compare(vm_name) == 0) {
+                        QString configStr = vmDet.at(1);
+                        QString devfileStr = vmDet.at(2);
+                        QString stateStr = vmDet.at(3);
+                        QString imageStr = vmDet.at(4);
+
+                        out << nameStr << "," << configStr << "," << devfileStr << "," << QString::number(mode) <<"," << imageStr << endl;
+                } else {
+                        out << line << endl;
+                }
+        }
+
+        out.flush();
+        file.remove("virtual_machines_list.txt");
+        temp.rename("virtual_machines_list.txt");
+
+        file.close();
+        temp.close();
+
+        // Update VM object
+        mVmList[mVmPos]->setState(mode);
+}
+
+void NewPalacios::stopVm() {
+        if (mVmList.isEmpty() 
+                || mVmList[mVmPos]->getState() == VmInfo::STOPPED) {
+                // If the VM list is empty or the VM is already stopped
+                // or if the VM is passive
+                // return
+                showMessage(tr(ERROR_STOP_VM), false, true);
+                return;
+        }
+
+        if (mVmList[mVmPos]->getCategory() == VmInfo::INACTIVE_INVENTORY
+               || mVmList[mVmPos]->getCategory() == VmInfo::ACTIVE_NOT_INVENTORY) {
+                // If the VM is inactive or active not inventory
+                showMessage(tr(ERROR_VM_NOT_INVENTORY), true);
+                return;
+        }
+
+       QString name = NULL;
+       QMessageBox vmStopWarningBox;
+       vmStopWarningBox.setText(VM_STOP_WARNING_MESSAGE);
+       vmStopWarningBox.setIcon(QMessageBox::Warning);
+       vmStopWarningBox.setStandardButtons(
+                       QMessageBox::Cancel | QMessageBox::Ok);
+       vmStopWarningBox.setDefaultButton(QMessageBox::Cancel);
+       int ret = vmStopWarningBox.exec();
+        int posInTabWidget = -1;
+        QStringList args;
+        QProcess* v3StopProc = NULL;
+
+       switch (ret) {
+       case QMessageBox::Ok:
+                
+                v3StopProc = new QProcess();
+                v3StopProc->setProcessChannelMode(QProcess::MergedChannels);
+                args << mVmList[mVmPos]->getVmDevFile();
+                v3StopProc->start("v3_stop", args);
+                if (!v3StopProc->waitForFinished()) {
+                    showMessage(tr(ERROR_STOP_VM_PATH), true);
+                    delete v3StopProc;
+                    return;
+
+                } else if (v3StopProc->readAllStandardOutput().contains("Error opening V3Vee VM device")) {
+                    showMessage(tr(ERROR_STOP_VM_DEVICE_NOT_FOUND), true);
+                    delete v3StopProc;
+                    return;
+                }
+
+               name = mVmList[mVmPos]->getVmName();
+               for (int i=0; i<mRunningVms.length(); i++) {
+                       if (name.compare(mRunningVms[i]->getVmName()) == 0) {
+                               // Remove widget from tab if placed there
+                               posInTabWidget = mVmControlPanel->indexOf(mRunningVms[i]);
+                                if (posInTabWidget != -1) {
+                                       // Console is present in tab
+                                        mVmControlPanel->removeTab(posInTabWidget);
+                               }
+                                // Close the console
+                               mRunningVms[i]->close();
+                                // Remove it from list of running console windows
+                               mRunningVms.removeAt(i);
+                                       break;
+                               }
+               }
+
+                // Update VM state
+                updateVmState(VmInfo::STOPPED);
+                
+                // Update icon
+                for (int i=0; i<mVmTreeView->topLevelItem(VmInfo::ACTIVE_INVENTORY)->childCount(); i++) {
+                       QTreeWidgetItem* child = mVmTreeView->topLevelItem(VmInfo::ACTIVE_INVENTORY)->child(i);
+                       if (mVmName.compare(child->text(0)) == 0) {
+                               child->setIcon(0, QIcon(":/images/images/stop_vm.png"));
+                               break;
+                       }
+               }
+                
+               break;
+       case QMessageBox::Cancel:
+               break;
+       }
+}
+
+void NewPalacios::pauseVm() {
+    if (mVmList.isEmpty()) {
+       return;
+    }
+       
+    if (mVmList[mVmPos]->getCategory() == VmInfo::INACTIVE_INVENTORY
+       || mVmList[mVmPos]->getCategory() == VmInfo::ACTIVE_NOT_INVENTORY) {
+        showMessage(tr(ERROR_VM_NOT_INVENTORY), false, true);
+        return;
+    }
+       
+    QString v3_devfile = mVmList[mVmPos]->getVmDevFile();
+    if (v3_devfile == NULL) {
+            showMessage(tr("Device file not found"), true);
+            return;
+    }
+
+    QProcess* v3Pauseproc = new QProcess();
+    v3Pauseproc->setProcessChannelMode(QProcess::MergedChannels);
+    QStringList args;
+    args << v3_devfile;
+    v3Pauseproc->start("v3_pause", args);
+    if (!v3Pauseproc->waitForFinished()) {
+        showMessage(v3Pauseproc->errorString(), true);
+    } else if (v3Pauseproc->readAllStandardOutput().contains("Error opening V3Vee VM device")) {
+        showMessage(tr(ERROR_PAUSE_VM_DEVICE_NOT_FOUND), true);
+    }
+        
+    // Update VM state
+    updateVmState(VmInfo::PAUSED);
+    
+    // Update icon
+    for (int i=0; i<mVmTreeView->topLevelItem(VmInfo::ACTIVE_INVENTORY)->childCount(); i++) {
+               QTreeWidgetItem* child = mVmTreeView->topLevelItem(VmInfo::ACTIVE_INVENTORY)->child(i);
+               if (mVmName.compare(child->text(0)) == 0) {
+                       child->setIcon(0, QIcon(":/images/images/pause_vm.png"));
+                       break;
+               }
+    }
+    
+    delete v3Pauseproc;
+}
+
+void NewPalacios::restartVm() {
+    if (mVmList.isEmpty()) {
+       return;
+    }
+
+    if (mVmList[mVmPos]->getCategory() == VmInfo::INACTIVE_INVENTORY
+       || mVmList[mVmPos]->getCategory() == VmInfo::ACTIVE_NOT_INVENTORY) {
+        showMessage(tr(ERROR_VM_NOT_INVENTORY), false, true);
+        return;
+    }
+
+    QString v3_devfile = mVmList[mVmPos]->getVmDevFile();
+    if (v3_devfile == NULL) {
+            showMessage(tr("Device file not found"), true);
+            return;
+    }
+
+    QProcess* v3Continueproc = new QProcess();
+    v3Continueproc->setProcessChannelMode(QProcess::MergedChannels);
+    QStringList args;
+    args << v3_devfile;
+    v3Continueproc->start("v3_continue", args);
+    
+    if (!v3Continueproc->waitForFinished()) {
+        showMessage(v3Continueproc->errorString(), true);
+    } else if (v3Continueproc->readAllStandardOutput().contains("Error opening V3Vee VM device")) {
+        showMessage(tr(ERROR_RESTART_VM_IOCTL), true);
+    }
+
+    // Update icon
+    for (int i=0; i<mVmTreeView->topLevelItem(VmInfo::ACTIVE_INVENTORY)->childCount(); i++) {
+               QTreeWidgetItem* child = mVmTreeView->topLevelItem(VmInfo::ACTIVE_INVENTORY)->child(i);
+               if (mVmName.compare(child->text(0)) == 0) {
+                       child->setIcon(0, QIcon(":/images/images/start_vm.png"));
+                       break;
+               }
+    }
+
+    delete v3Continueproc;
+}
+
+// Method to create a VM from inactive list
+int NewPalacios::createInactiveVm() {
+       QString vmImageFile = mVmList[mVmPos]->getImageFile();
+       QString vmName = mVmList[mVmPos]->getVmName();
+       
+       // Create the VM instance
+       QProcess* v3CreateProc = new QProcess();
+        QStringList args;
+        args.clear();
+        args << vmImageFile << vmName;
+        v3CreateProc->start("v3_create", args);
+                
+        if (v3CreateProc->waitForFinished()) {
+               if (v3CreateProc->readAllStandardOutput().contains("Error (-1)")) {
+                       // v3_create has failed with IOCTL error
+                        showMessage(tr(ERROR_VM_CREATE_IOCTL), true);
+                        delete v3CreateProc;
+                       return -1;
+                }
+       } else {
+               showMessage(tr(ERROR_VM_CREATE_PATH), true);
+                delete v3CreateProc;
+                return -1;
+       }
+       
+       // Cleanup
+       delete v3CreateProc;
+       
+       // Check the last line of /proc/v3vee/v3-guests 
+        // to see the /dev/v3-vm# of the new VM
+        bool isCreated = false;
+        QProcess* proc = new QProcess();
+        proc->setProcessChannelMode(QProcess::MergedChannels);
+        proc->start("cat /proc/v3vee/v3-guests");
+                
+        if (!proc->waitForFinished()) {
+               showMessage(tr(ERROR_VM_CREATE_PROC), true);
+                delete proc;
+                return -1;
+       }
+       
+        //QByteArray temp = vmName.toAscii();
+        //const char* vmEntry = temp.data();
+        
+        // Read standard output of process
+        QByteArray val = proc->readAllStandardOutput();
+        if (!val.isNull()) {
+                // The created VM can be defined anywhere in the /proc file
+                // we need to go over all entries till we find it
+                QList<QByteArray> procs = val.split('\n');
+                for (int i=0; i<procs.size(); i++) {
+                       QList<QByteArray> temp = procs[i].split('\t');
+                        QByteArray a = temp.at(0);
+                        QString vmProcName(a);
+                        if (vmName.compare(vmProcName) == 0) {
+                                       // We have found the VM, get dev file name
+                                       QByteArray b = temp.at(1);
+                                       QString vmDevFile(b);
+                                vmDevFile.remove(QChar('\n'), Qt::CaseInsensitive);
+                               mVmList[mVmPos]->setVmDevFile(vmDevFile);
+                               // Make VM instance active
+                               mVmList[mVmPos]->setCategory(VmInfo::ACTIVE_INVENTORY);
+                               isCreated = true;
+                               break;
+                       }
+                }
+        }
+                
+        if (!isCreated) {
+               // We did not find an entry in
+                // /proc file so there must have
+                // been an error in creation
+                showMessage(tr(ERROR_VM_CREATE_FAILED), true);
+                delete proc;
+                return -1;
+        }
+        
+        if (proc != NULL) 
+            delete proc;
+
+       return 0;
+}
+
+int NewPalacios::updateDb(int cat) {
+       QString vm_name = mVmList[mVmPos]->getVmName();
+        
+        QFile file("virtual_machines_list.txt");
+        if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+                showMessage("Error opening DB! Please restart application", true);
+                return -1;
+        }
+
+        QFile temp("temp.txt");
+        if (!temp.open(QIODevice::WriteOnly | QIODevice::Text)) {
+                showMessage("Error opening DB! Please restart application", true);
+                return -1;
+        }
+        
+        QTextStream in(&file);
+        QTextStream out(&temp);
+        
+
+        if (cat == VmInfo::INACTIVE_INVENTORY) {
+                // If we are updating an inactive entry
+                // search the file and update
+                while (!in.atEnd()) {
+                        QString line = in.readLine();
+                        if (line.compare("\n") == 0) {
+                               continue;
+                        }
+                        QStringList vmDet = line.split(",");
+                        QString nameStr = vmDet.at(0);
+                        
+                        if (vm_name.compare(nameStr) != 0) {
+                                // If the name does not match, then copy to new place
+                                out << line << endl;
+                        } else {
+                               // Update DB state
+                               VmInfo* v = mVmList[mVmPos];
+                               QString updateLine = v->getVmName()
+                                       + "," + v->getVmConfigFile()
+                                       + "," + v->getVmDevFile()
+                                       + "," + QString::number(VmInfo::STOPPED)
+                                       + "," + v->getImageFile();
+                               out << updateLine << endl;
+                        }
+                }
+        } else if (cat == VmInfo::ACTIVE_NOT_INVENTORY) {
+               
+               while (!in.atEnd()) {
+                        QString line = in.readLine();
+                        if (line.compare("\n") == 0) {
+                               continue;
+                        }
+                        
+                        // Copy all the contents into new file
+                        out << line << endl;
+                }
+                
+                // Copy the new VM info
+                VmInfo* vv = mVmList[mVmPos];
+                QString updateLine = vv->getVmName()
+                       + "," + vv->getVmConfigFile()
+                       + "," + vv->getVmDevFile()
+                       + "," + QString::number(VmInfo::STOPPED)
+                       + "," + vv->getImageFile();
+                       out << updateLine << endl;
+        }
+
+       out.flush();
+        file.remove("virtual_machines_list.txt");
+        temp.rename("virtual_machines_list.txt");
+
+        file.close();
+        temp.close();
+        
+        return 0;
+}
+
+void NewPalacios::activateVm() {
+        // 1. Check VM category
+        //     1a. If VM is active but not in inventory, upgrade category
+        //     1b. If VM is inactive, create VM and upgrade category
+       QTreeWidgetItem* item = NULL;
+       
+        // Remove VM from inactive list
+        // The list could be from either the inactive inventory or
+        // active not inventory
+        int category = mVmList[mVmPos]->getCategory();
+        
+        if (category == VmInfo::ACTIVE_NOT_INVENTORY) {
+               // The VM exists in the /proc file and 
+               // is already created. We will only update
+               // VM category.
+               
+               // Ask user for Config file and Image file
+               QString configFile = QFileDialog::getOpenFileName(this, tr("Select config file"), ".",
+                       "XML file (*.xml)");
+               if (configFile == NULL) {
+                       // User pressed cancel
+                       return;
+               }
+               QString imageFile = QFileDialog::getOpenFileName(this, tr("Select image file"), ".",
+                       "Image file (*.img *.bZ)");
+               if (imageFile == NULL) {
+                       // User pressed cancel
+                       return;
+               }
+               
+               mVmList[mVmPos]->setVmConfigFile(configFile);
+               mVmList[mVmPos]->setImageFile(imageFile);
+               
+                // Remove from active not inventory list
+               for (int i=0; i<mVmTreeView->topLevelItem(VmInfo::ACTIVE_NOT_INVENTORY)->childCount(); i++) {
+                       item = mVmTreeView->topLevelItem(VmInfo::ACTIVE_NOT_INVENTORY)->child(i);
+                       if (item->text(0).compare(mVmList[mVmPos]->getVmName()) == 0) {
+                               item = mVmTreeView->topLevelItem(VmInfo::ACTIVE_NOT_INVENTORY)->takeChild(i);
+                               break;
+                       }
+               }
+               
+               // Add it to active list
+               QTreeWidgetItem* subParent = mVmTreeView->topLevelItem(VmInfo::ACTIVE_INVENTORY);
+                subParent->addChild(item);
+               
+               // Update Category
+               mVmList[mVmPos]->setCategory(VmInfo::ACTIVE_INVENTORY);
+               
+               // Update DB with newly created entry
+                updateDb(VmInfo::ACTIVE_NOT_INVENTORY);
+               return;
+               
+        } else if (category == VmInfo::INACTIVE_INVENTORY) {
+               // The VM is in the inventory but inactive.
+               // This means that we need to create it.
+               int ret = createInactiveVm();
+               
+               if (ret != 0) {
+                       // VM was not created due to some problem
+                       // TODO: Decide if you want to delete the reference
+                       // from the text file or keep it there for a while and
+                       // try again
+                       return;
+               }
+               
+               // Once VM is created, we need to first remove it from the 
+               // inactive list and add it to active list
+               for (int i=0; i<mVmTreeView->topLevelItem(VmInfo::INACTIVE_INVENTORY)->childCount(); i++) {
+                       item = mVmTreeView->topLevelItem(VmInfo::INACTIVE_INVENTORY)->child(i);
+                       if (item->text(0).compare(mVmList[mVmPos]->getVmName()) == 0) {
+                               item = mVmTreeView->topLevelItem(VmInfo::INACTIVE_INVENTORY)->takeChild(i);
+                               break;
+                       }
+               }
+               
+               // Add it to active list
+               QTreeWidgetItem* subParent = mVmTreeView->topLevelItem(VmInfo::ACTIVE_INVENTORY);
+                subParent->addChild(item);
+                
+                // Update DB with newly created entry
+                updateDb(VmInfo::INACTIVE_INVENTORY);
+        }
+}
+
+void NewPalacios::reloadVms() {
+       // Clear all previous entries
+       for (int i=0; i<mVmTreeView->topLevelItemCount(); i++) {
+               qDeleteAll(mVmTreeView->topLevelItem(i)->takeChildren());
+       }
+       
+       // Call load VM thread
+       readExistingVmsFile();
+}
+
+// This handler is used in serial mode when user clicks
+// the close button of the floating window
+void NewPalacios::consoleWindowClosed(QString name) {
+        // Remove the console from the list of
+        // running consoles
+        for (int i=0; i < mRunningVms.length(); i++) {
+                if (name.compare(mRunningVms[i]->getVmName()) == 0) {
+                        mRunningVms.removeAt(i);
+                        break;
+                }
+        }
+}
+
+// This handler is used in v3_cons_sc mode when the user clicks
+// the close button on the tab widget
+void NewPalacios::vmTabClosed(int index) {
+        if (index == 0) {
+                // As of now do not remove the info tab
+                return;
+        }
+
+        // Get the name of the VM tab which we need to close
+        // Need to cast the return value of TabWidget->widget as it returns an object
+        // of the base class. static_cast is used because the conversion is from base
+        // class object to derived class object
+        VmXConsoleParent* widget = static_cast<VmXConsoleParent*>(mVmControlPanel->widget(index));
+        QString name = widget->getVmName();
+        for (int i=0; i<mRunningVms.length(); i++) {
+                if (name.compare(mRunningVms[i]->getVmName()) == 0) {
+                        // Remove the tab
+                        mVmControlPanel->removeTab(index);
+                        // Remove the console from running vm instances
+                        mRunningVms.removeAt(i);
+                        // Send close event to widget
+                        widget->close();
+                        break;
+                }
+        }
+}
+
+/* This function reads from the vm list file */
+void NewPalacios::readExistingVmsFile() {
+       mThread = new QThread();
+       mLoadVmsThread = new LoadVmsThread();
+       mLoadVmsThread->moveToThread(mThread);
+       connect(mThread, SIGNAL(started()), mLoadVmsThread, SLOT(loadVms()));
+       connect(mLoadVmsThread, SIGNAL(finished()), mThread, SLOT(quit()));
+       // Action which listens to completion of initial VM loading
+       connect(mLoadVmsThread, SIGNAL(finished()), this,
+                       SLOT(finishLoadingVmsFromFile()));
+       mThread->start();
+}
+
+// Update UI with VMs loaded from file
+void NewPalacios::finishLoadingVmsFromFile() {
+       if (mLoadVmsThread->getStatus() == LoadVmsThread::STATUS_OK) {
+               mVmList.clear();
+               mVmPos = 0;
+               
+               int category = -1;
+               
+               // Load VMs into memory
+               mVmList.append(mLoadVmsThread->getVmList());
+               
+                QTreeWidgetItem* item = NULL;
+                for (int i = 0; i < mVmList.size(); i++) {
+                        if (mVmList[i]->getCategory() == VmInfo::ACTIVE_INVENTORY) {
+                               item = new QTreeWidgetItem();
+                               item->setText(0, mVmList[i]->getVmName());
+                               
+                               category = mVmList[i]->getState();
+                               switch (category) {
+                               case VmInfo::STOPPED:
+                                       item->setIcon(0, QIcon(":/images/images/stop_vm.png"));
+                                               break;
+                               case VmInfo::PAUSED:
+                                       item->setIcon(0, QIcon(":/images/images/pause_vm.png"));
+                                               break;
+                               case VmInfo::RUNNING:
+                                       item->setIcon(0, QIcon(":/images/images/start_vm.png"));
+                                               break;
+                               }
+                               
+                               mVmTreeView->topLevelItem(VmInfo::ACTIVE_INVENTORY)->addChild(item);
+                               
+                        } else if (mVmList[i]->getCategory() == VmInfo::INACTIVE_INVENTORY) {
+                               item = new QTreeWidgetItem();
+                               item->setText(0, mVmList[i]->getVmName()); 
+                               mVmTreeView->topLevelItem(VmInfo::INACTIVE_INVENTORY)->addChild(item);
+                               
+                        } else if (mVmList[i]->getCategory() == VmInfo::ACTIVE_NOT_INVENTORY) {
+                               item = new QTreeWidgetItem();
+                               item->setText(0, mVmList[i]->getVmName()); 
+                               mVmTreeView->topLevelItem(VmInfo::ACTIVE_NOT_INVENTORY)->addChild(item);
+                        }
+               }
+                
+                mVmControlPanel->insertTab(0, mVmInfoWidget, tr(VM_TAB_TITLE));
+
+                if (mThread != NULL)
+                    delete mThread;
+
+       }
+}
+
+/* This method is called after completion of the VM wizard
+ * It updates the backend vm file with new vm */
+void NewPalacios::addNewVm() {
+        QString name = mVmWizard->field("guestName").toString();
+       QString file = mVmWizard->field("configLoc").toString();
+        QFileInfo f(mVmWizard->field("imageLoc").toString());
+        QString img = f.fileName();
+        
+        mThread = new QThread();
+       mAddVmThread = new AddVmThread(name, file, img);
+       mAddVmThread->moveToThread(mThread);
+       connect(mThread, SIGNAL(started()), mAddVmThread, SLOT(addVm()));
+       connect(mAddVmThread, SIGNAL(finished()), mThread, SLOT(quit()));
+       // Call method on window to update the vm list
+       connect(mAddVmThread, SIGNAL(finished()), this, SLOT(updateVmList()));
+       mThread->start();
+}
+
+/* Update UI with new VM added to list */
+void NewPalacios::updateVmList() {
+       if(mAddVmThread != NULL && mAddVmThread->getStatus()
+                        == AddVmThread::ERROR_V3CREATE_DB) {
+                showMessage(tr(ERROR_VM_CREATE_DB), true);
+
+        } else if (mAddVmThread != NULL &&
+                        mAddVmThread->getStatus() == AddVmThread::STATUS_OK) {
+                // Newly created VM is inactive but in inventory
+                showMessage(tr(SUCCESS_VM_ADDED), false);
+               mVmList.append(mAddVmThread->getNewVm());
+                QTreeWidgetItem* item = new QTreeWidgetItem();
+                item->setText(0, mAddVmThread->getName());
+
+                QTreeWidgetItem* subParent = mVmTreeView->topLevelItem(VmInfo::INACTIVE_INVENTORY);
+                subParent->addChild(item);
+       }
+
+        if (mThread != NULL)
+            delete mThread;
+}
+
+/* Handler to delete VM instance from list and backend file */
+void NewPalacios::deleteVm(QString item) {
+        int category = -1;
+        QString devfile;
+
+       for (int i = 0; i < mVmList.size(); i++) {
+               if (item.compare(mVmList[i]->getVmName()) == 0) {
+                        category = mVmList[i]->getCategory();
+                        devfile = mVmList[i]->getVmDevFile();
+                       break;
+               }
+       }
+
+       mThread = new QThread();
+       mDeleteVmThread = new DeleteVmThread(category, item, devfile);
+       mDeleteVmThread->moveToThread(mThread);
+       connect(mThread, SIGNAL(started()), mDeleteVmThread, SLOT(deleteVm()));
+        connect(mDeleteVmThread, SIGNAL(finished()), mThread, SLOT(quit()));
+        connect(mDeleteVmThread, SIGNAL(finished()), this, SLOT(handleVmDeletion()));
+       mThread->start();
+}
+
+void NewPalacios::handleVmDeletion() {
+        if (mDeleteVmThread->getStatus()
+                        == DeleteVmThread::ERROR_V3FREE_PATH) {
+                showMessage(tr(ERROR_VM_DELETE_PATH), true);
+
+        } else if (mDeleteVmThread->getStatus()
+                        == DeleteVmThread::ERROR_V3FREE_IOCTL) {
+                showMessage(tr(ERROR_VM_DELETE_IOCTL), true);
+
+        } else if (mDeleteVmThread->getStatus()
+                        == DeleteVmThread::ERROR_V3FREE_DB) {
+                showMessage(tr(ERROR_VM_DELETE_DB), true);
+
+        } else if (mDeleteVmThread->getStatus()
+                        == DeleteVmThread::ERROR_V3FREE_INVALID_ARGUMENT) {
+                showMessage(tr(ERROR_VM_DELETE_INVALID_ARGUMENT), true);    
+
+        } else if (mDeleteVmThread->getStatus()
+                        == DeleteVmThread::STATUS_OK) {
+                // Delete VM from list
+               for (int i = 0; i < mVmList.size(); i++) {
+                       if (mVmName.compare(mVmList[i]->getVmName()) == 0) {
+                                // Deletion is a little tricky
+                                // 1. Find the VM to be deleted and get its name
+                                // 2. Remove VM from list
+                                // 3. Determine the category
+                                // 4. Search the appropriate category for the VM
+                                // 5. Remove from UI widget and delete
+                               int cat = mVmList[i]->getCategory();
+                                mVmList.removeAt(i);
+                                
+                                if (cat == VmInfo::ACTIVE_INVENTORY) {
+                                    QTreeWidgetItem* activeItems = mVmTreeView->topLevelItem(VmInfo::ACTIVE_INVENTORY);
+                                    for (int j=0; j<activeItems->childCount(); j++) {
+                                        QString n = activeItems->child(j)->text(0);
+                                        if (mVmName.compare(n) == 0) {
+                                                QTreeWidgetItem* achild = activeItems->takeChild(j);
+                                                delete achild;
+                                                break;
+                                        }
+                                                
+                                    }
+                                } else if (cat == VmInfo::INACTIVE_INVENTORY) {
+                                   QTreeWidgetItem* inactiveItems = mVmTreeView->topLevelItem(VmInfo::INACTIVE_INVENTORY);
+                                   for (int j=0; j<inactiveItems->childCount(); j++) {
+                                        QString in = inactiveItems->child(j)->text(0);
+                                        if (mVmName.compare(in) == 0) {
+                                                QTreeWidgetItem* ichild = inactiveItems->takeChild(j);
+                                                delete ichild;
+                                                break;
+                                        }
+                                   }
+                                } else if (cat == VmInfo::ACTIVE_NOT_INVENTORY) {
+                                       QTreeWidgetItem* activeNotInvItems = mVmTreeView->topLevelItem(VmInfo::ACTIVE_NOT_INVENTORY);
+                                       for (int j=0; j<activeNotInvItems->childCount(); j++) {
+                                            QString an = activeNotInvItems->child(j)->text(0);
+                                            if (mVmName.compare(an) == 0) {
+                                                    QTreeWidgetItem* aichild = activeNotInvItems->takeChild(j);
+                                                    delete aichild;
+                                                    break;
+                                               }
+                                       }
+                                
+                                }
+                               
+                               // Clear VM from Info widget view
+                                mVmInfoWidget->deleteVm();
+                               break;
+                       }
+               }
+
+                showMessage(tr(SUCCESS_VM_DELETE), false);
+        }
+
+        if (mThread != NULL)
+            delete mThread;
+}
diff --git a/linux_usr/gui/palacios/newpalacios.h b/linux_usr/gui/palacios/newpalacios.h
new file mode 100644 (file)
index 0000000..47c23b6
--- /dev/null
@@ -0,0 +1,425 @@
+#ifndef NEWPALACIOS_H
+#define NEWPALACIOS_H
+
+#include <QtGui>
+#include <QApplication>
+#include <QMainWindow>
+#include <QWidget>
+#include <QListWidget>
+#include <QTableWidget>
+#include <QVBoxLayout>
+#include <QTextEdit>
+#include <QFile>
+#include <QTextStream>
+#include <QList>
+#include <QAction>
+#include <QMenu>
+#include <QMenuBar>
+#include <QToolBar>
+#include <QStatusBar>
+#include <QProcess>
+#include <QObject>
+#include <QDomDocument>
+#include <QDomNode>
+#include <QDomNodeList>
+#include <QDomElement>
+#include <QDomText>
+#include <QDomAttr>
+#include <QDomNamedNodeMap>
+
+#include "vm_creation_wizard.h"
+#include "vm_console_widget.h"
+
+class VmInfo;
+class VmInfoWidget;
+class VmXConsoleParent;
+class VmVncWidget;
+class LoadVmsThread;
+class AddVmThread;
+class DeleteVmThread;
+class VmModeDialog;
+
+class NewPalacios: public QMainWindow {
+Q_OBJECT
+
+public:
+       NewPalacios(QWidget *parent = 0);
+       ~NewPalacios();
+
+protected:
+        void closeEvent(QCloseEvent*);
+
+private slots:
+       void createVmInstance();
+       void aboutPalacios();
+       void exitApplication();
+       void startVm();
+        void stopVm();
+        void pauseVm();
+        void restartVm();
+        void activateVm();
+        void reloadVms();
+        // Item click listener for tree items
+        void vmItemClickListener(QTreeWidgetItem*, int);
+       void finishLoadingVmsFromFile();
+       void addNewVm();
+       void updateVmList();
+       void deleteVm(QString);
+        void handleVmDeletion();
+        // Context menu for VMs
+        void vmContextMenu(const QPoint &p);
+       void consoleWindowClosed(QString);
+        void vmTabClosed(int);
+        // This slot will be triggered when play/menu start
+        // button is pressed. This will launch a dialog which
+        // will allow the user to select operating mode
+        void selectVmMode();
+        // This slot will be triggered from the mode selection
+        // dialog when the user has finished selection. 
+        void getVmMode(int, QString);
+        void updateTelemetry(bool);
+        void updateTelemetryView();
+        
+private slots:
+       // These are used for debugging QProcess commands
+       //void processStarted();
+       //void processExit(int, QProcess::ExitStatus);
+       //void processError(QProcess::ProcessError);
+
+signals:
+       void vmLoadingComplete();
+
+public:
+       void readExistingVmsFile();
+       // Check for Palacios setup
+        void checkPalacios();
+
+private:
+       // Functions to setup different components of the window
+       void createCentralWidget();
+       void createActions();
+       void createMenus();
+       void createToolBars();
+       void createStatusBar();
+       void createDockWindows();
+       void createWizard();
+       void createEventHandler();
+        // Show error message boxes
+        void showMessage(QString err, bool error, bool warning=false);
+        // Update state of VM
+        void updateVmState(int);
+        // Create inactive VM
+        int createInactiveVm();
+        // Update DB
+        int updateDb(int);
+        
+private:
+       // Main view of the application.
+        QTabWidget* mVmControlPanel;
+       VmInfoWidget* mVmInfoWidget;
+        // This is used to represent the classes of VM
+        QTreeWidget* mVmTreeView;
+        QTextEdit* mVmTelemetryView;
+
+        // Progress dialog to inform user about background thread processing
+        //QProgressDialog* mProgress;
+
+       // Runs Palacios in terminal mode
+        QList<VmXConsoleParent*> mRunningVms;
+        
+        bool mExitAppFromMenu;
+        // Used to identify VMs inside list
+        int mVmPos;
+        QString mVmName;
+        
+       // Action variables used to handle events such as menu clicks, button clicks etc.
+       QAction* mExitApp;
+       QAction* mVmNew;
+       QAction* mVmStop;
+       QAction* mVmPause;
+       QAction* mVmStart;
+       QAction* mVmActivate;
+        QAction* mReloadVms;
+       QAction* mAboutApp;
+
+       // Menu variables
+       QMenu* mFileMenu;
+       QMenu* mViewMenu;
+       QMenu* mVmMenu;
+       QMenu* mHelpMenu;
+
+       // Toolbar variables
+       QToolBar* mVmToolBar;
+       QToolBar* mVmCtrlToolBar;
+        
+        // This dialog will be used to give option
+        // to user to select from three modes of
+        // operation
+        VmModeDialog* mVmModeDialog;
+        int mVmMode;
+        QString mStreamName;
+        bool isHeaderClicked;
+
+        // Process to read kernel logs
+        QProcess* mLogProc;
+
+       // Wizard to help in vm creation
+       NewVmWizard* mVmWizard;
+
+       // List of created VMs. Each VM object contains information parsed from
+       // the config files provided as part of VM creation
+       QList<VmInfo*> mVmList;
+        //QList<VM*> mVmList;
+
+       /* We save the information about VMs in a text file. We store the name of the VM instance
+        * and the path of the configuration file used to create the VM. Every time we create/add/delete
+        * a VM instance, this file is edited. This is simplest way as of now to store this information.
+        * If in future we need more information to be stored we could use a database and Qt's
+        * model-view system */
+        
+        QThread* mThread;
+
+       // Thread to load existing VM intances
+       LoadVmsThread* mLoadVmsThread;
+       // Thread to add a new VM instance
+       AddVmThread* mAddVmThread;
+       // Thread to delete a VM instance
+       DeleteVmThread* mDeleteVmThread;
+       
+       // Telemetry process
+       QProcess* mTelemProc;
+};
+
+class VmModeDialog : public QWidget {
+Q_OBJECT
+public:
+    VmModeDialog(QWidget* parent = 0);
+
+private slots:
+    void selectMode(bool);
+    void okButton();
+    void cancelButton();
+
+signals:
+    // This signal will be caught in the main window
+    // and the mode will be set accordingly
+    void setMode(int, QString);
+
+private:
+    void setupDialog();
+
+private:
+    bool isV3Cons;
+    bool isV3Stream;
+    bool isV3Vnc;
+    int mode;
+    QGroupBox* v3_modes;
+    QRadioButton* v3_stream;
+    QRadioButton* v3_cons;
+    QRadioButton* v3_vnc;
+    QWidget* v3_stream_info;
+    QLineEdit* v3_stream_name;
+};
+
+// Class to hold information about a VM instance
+class VmInfo {
+public:
+       VmInfo() {
+       }
+       
+       ~VmInfo() {
+       }
+       
+       // Tells us about the state of the VM
+        enum {
+                STOPPED, PAUSED, RUNNING
+        };
+
+        // Tells about the category of VM
+        enum {
+                ACTIVE_INVENTORY, INACTIVE_INVENTORY, ACTIVE_NOT_INVENTORY
+        };
+       
+       // Return state of VM
+        int getState() {
+                return mVmState;     
+        }
+       
+       // Ser state of VM
+        void setState(int state) {
+                this->mVmState = state;
+        }
+
+        void setCategory(int cat) {
+                this->mVmCategory = cat;
+        }
+
+        int getCategory() {
+                return mVmCategory;
+        }
+
+        void setImageFile(QString img) {
+                this->mVmImageFile = img;
+        }
+
+        QString getImageFile() {
+                return mVmImageFile;
+        }
+        
+        QString getVmName() {
+               return mVmName;
+       }
+
+       void setVmName(QString name) {
+               this->mVmName = name;
+       }
+
+        QString getVmDevFile() {
+                return mVmDevFile;
+        }
+
+        void setVmDevFile(QString name) {
+                this->mVmDevFile = name;
+        }
+        
+        QString getVmConfigFile() {
+               return this->mVmConfigFile;
+        }
+        
+        void setVmConfigFile(QString file) {
+               this->mVmConfigFile = file;
+        }
+        
+private:
+        int mVmState;
+        int mVmCategory;
+       QString mVmName;
+        QString mVmDevFile;
+        QString mVmImageFile;
+        QString mVmConfigFile;
+};
+
+class VmInfoWidget: public QWidget {
+Q_OBJECT
+public:
+       VmInfoWidget(QWidget* parent = 0);
+        ~VmInfoWidget();
+       
+private:
+       void setInfoView();
+       void setupUi();
+
+public:
+       void parseElement(const QDomElement&, QTreeWidgetItem*);
+       void parseAttribute(const QDomElement&, QTreeWidgetItem*);
+       void parseText(const QDomElement&, QTreeWidgetItem*);
+        void updateInfoView(VmInfo* vm);
+       void deleteVm();
+
+private:
+       QTreeWidget* mVmInfoView;
+};
+
+class VmXConsoleParent: public QWidget {
+Q_OBJECT
+public:
+       VmXConsoleParent(QString name, QWidget* parent = 0);
+        void showWidget(int mode, QString devfile, QString streamName);
+       void showTelemetryInfo();
+       bool isRunning();
+        QString getVmName();
+       
+signals:
+       void windowClosingWithId(QString name);
+        void windowClosing();
+
+protected:
+       void closeEvent(QCloseEvent* event);
+
+private:
+       bool mIsConsoleRunning;
+       QString mVmName;
+       VmConsoleWidget* mConsole;
+};
+
+class LoadVmsThread: public QObject {
+Q_OBJECT
+public:
+       static const int STATUS_OK = 0;
+       static const int ERROR_FILE_CANNOT_BE_OPENED = -1;
+
+       int getStatus();
+       QList<VmInfo*> getVmList();
+
+signals:
+       void finished();
+
+public slots:
+       void loadVms();
+private:
+       int status;
+       QList<VmInfo*> list;
+};
+
+class AddVmThread: public QObject {
+Q_OBJECT
+public:
+       static const int STATUS_OK = 0;
+        static const int ERROR_V3CREATE_PATH = -1;
+        static const int ERROR_V3CREATE_IOCTL = -2;
+        static const int ERROR_V3CREATE_PROC = -3;
+        static const int ERROR_V3CREATE_DEV = -4;
+        static const int ERROR_V3CREATE_DB = -5;
+        
+       AddVmThread(QString name, QString conf, QString img);
+       int getStatus();
+       QString getName();
+       VmInfo* getNewVm();
+
+signals:
+       void finished();
+
+public slots:
+       void addVm();
+
+private:
+       int status;
+       QString vmName;
+        QString vmDevFile;
+        QString vmConfigFile;
+        QString vmImageFile;
+       VmInfo* vm;
+};
+
+class DeleteVmThread: public QObject {
+Q_OBJECT
+public:
+       static const int STATUS_OK = 0;
+        static const int ERROR_V3FREE_PATH = -1;
+        static const int ERROR_V3FREE_IOCTL = -2;
+        static const int ERROR_V3FREE_DB = -3;
+        static const int ERROR_V3FREE_INVALID_ARGUMENT = -4;
+
+       DeleteVmThread(int, QString, QString);
+       int getStatus();
+
+signals:
+        void finished();
+
+public slots:
+       void deleteVm();
+       
+private slots:
+       // These are used for debugging QProcess commands
+       //void processStarted();
+       //void processExit(int, QProcess::ExitStatus);
+       //void processError(QProcess::ProcessError);
+
+private:
+       int status;
+        int vmCategory;
+       QString vmToDelete;
+        QString vmDevfile;
+};
+
+#endif // NEWPALACIOS_H
diff --git a/linux_usr/gui/palacios/vm_console_widget.cpp b/linux_usr/gui/palacios/vm_console_widget.cpp
new file mode 100644 (file)
index 0000000..ec0081b
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ * vm_console_widget.cpp
+ *
+ *  Created on: Oct 4, 2012
+ *      Author: abhinav
+ */
+
+#include "vm_console_widget.h"
+
+#include <QDebug>
+#include <QMessageBox>
+#include <QVBoxLayout>
+#include <X11/Xlib.h>
+
+VmConsoleWidget::VmConsoleWidget(QWidget* parent) :
+               QWidget(parent), mCols(100), mRows(25), mTermProcess(0) {
+        mTermProcess = NULL;
+        mVncServer = NULL;
+}
+
+VmConsoleWidget::~VmConsoleWidget() {
+
+}
+
+bool VmConsoleWidget::tryTerminate() {
+       if (mTermProcess == NULL) {
+               return true;
+       }
+
+       if (mTermProcess != NULL && mTermProcess->state() == QProcess::Running) {
+               mTermProcess->terminate();
+               bool xwindow_closed = mTermProcess->waitForFinished();
+                delete mTermProcess;
+                return xwindow_closed;
+
+        } else if (mVncView != NULL) {
+                mVncServer->terminate();
+                bool vncserver_exited = mVncServer->waitForFinished();
+                delete mVncView;
+                delete mVncServer;
+                return vncserver_exited;
+        }
+
+       return true;
+}
+
+void VmConsoleWidget::mainWindowClosing() {
+       close();
+}
+
+void VmConsoleWidget::closeEvent(QCloseEvent* e) {
+       if (!tryTerminate())
+               qDebug() << "Warning: could not terminate process...there could be a leak";
+       else
+               qDebug() << "Process terminated";
+
+       e->accept();
+}
+
+void VmConsoleWidget::resizeEvent(QResizeEvent* re) {
+       QWidget::resizeEvent(re);
+
+       if (mTermProcess == NULL)
+               return;
+
+       // Search for xterm window and update its size
+       Display *dsp = XOpenDisplay(NULL);
+       Window wnd = winId();
+
+       bool childFound = false;
+       while (!childFound && mTermProcess->state() == QProcess::Running) {
+               Window root, parent, *children;
+               uint numwin;
+               XQueryTree(dsp, wnd, &root, &parent, &children, &numwin);
+               childFound = (children != NULL);
+
+               if (childFound) {
+                       XResizeWindow(dsp, *children, width(), height());
+                       XFree(children);
+               }
+       }
+
+       XCloseDisplay(dsp);
+}
+
+bool VmConsoleWidget::isRunning() {
+       if (mTermProcess == NULL) {
+               return false;
+       }
+        
+        // FIXME: This function is currently very unreliable
+        // The QProcess->state() function should return the correct
+        // state of the process but it is currently not working as expected
+        // Debugging with GDB also does not reveal the problem
+        // Maybe the way this method is being called is incorrect
+       return (mTermProcess->state() == QProcess::Running) ? true : false;
+}
+
+bool VmConsoleWidget::start(int mode, QString devfile, QString streamName) {
+       qDebug() << "VmConsoleWidget : start() [" << streamName << "]";
+        
+        // Start VM in correct mode
+        if (mode == VmConsoleWidget::STREAM) {
+                mVmMode = "v3_stream";
+        } else if (mode == VmConsoleWidget::CONSOLE) {
+                mVmMode = "v3_cons_sc";
+        } else {
+                mVmMode = "v3_vncclient";
+        }
+        
+        qDebug() << "Vm Mode: " << mVmMode;
+        qDebug() << "Vm dev file: " << devfile;
+
+       QStringList args;
+        
+        if (streamName.compare("") != 0) {
+            // This is v3_stream mode
+           args << "-sb" << "-geometry" << QString("%1x%2").arg(mCols).arg(mRows) << "-j"
+               << "-into" << QString::number(winId()) << "-e" << mVmMode << devfile << streamName;
+                
+                // Start the xterm process
+               qDebug() << "Starting terminal with arguments '" << args.join(" ");
+                mTermProcess = new QProcess();
+
+                // Connect signals and slots
+               connect(mTermProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, 
+                       SLOT(termProcessExited(int, QProcess::ExitStatus)));
+
+               connect(mTermProcess, SIGNAL(error(QProcess::ProcessError)), this, 
+                       SLOT(errorMessage(QProcess::ProcessError)));
+
+               mTermProcess->start("/usr/bin/xterm", args);
+
+        } else {
+            // This is non-stream mode
+            
+            if (mVmMode.compare("v3_cons_sc") == 0) {
+                // Console mode
+                args << "-sb" << "-geometry" << QString("%1x%2").arg(mCols).arg(mRows) << "-j"
+                       << "-into" << QString::number(winId()) << "-e" << mVmMode << devfile;
+
+
+               qDebug() << "Starting terminal with arguments '" << args.join(" ");
+                mTermProcess = new QProcess();
+
+                // Connect signals and slots
+               connect(mTermProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, 
+                       SLOT(termProcessExited(int, QProcess::ExitStatus)));
+
+               connect(mTermProcess, SIGNAL(error(QProcess::ProcessError)), this, 
+                       SLOT(errorMessage(QProcess::ProcessError)));
+       
+                mTermProcess->start("/usr/bin/xterm", args);
+            
+            } else {
+                // VNC mode
+                mVncServer = new QProcess();
+                mVncServer->setProcessChannelMode(QProcess::MergedChannels);
+
+               connect(mVncServer, SIGNAL(finished(int, QProcess::ExitStatus)), this, 
+                       SLOT(termProcessExited(int, QProcess::ExitStatus)));
+
+               connect(mVncServer, SIGNAL(error(QProcess::ProcessError)), this, 
+                       SLOT(errorMessage(QProcess::ProcessError)));
+                
+                QStringList args;
+                args << "--port=5951" << "--password=test123" << devfile;
+                qDebug() << "arguments: " << args.join(" ");
+                mVncServer->start("v3_vncserver", args);
+
+                if (!mVncServer->waitForFinished()) {
+                        qDebug() << "Error with VNC server";
+                        QMessageBox msg;
+                        msg.setText("Error with VNC server!");
+                        msg.setStandardButtons(QMessageBox::Ok);
+                        msg.setIcon(QMessageBox::Critical);
+                        msg.exec();
+                        return false;
+                }
+                
+                //args << "-sb" << "-geometry" << QString("%1x%2").arg(mCols).arg(mRows) << "-j"
+               //        << "-into" << QString::number(winId()) << "-e" << "vncviewer localhost:5951";
+                
+                QVBoxLayout* vncBox = new QVBoxLayout();
+                mVncView = new VncView(this, QUrl("vnc://localhost:5951"), KConfigGroup());
+                //mVncView = new VncView(this, QUrl("vnc://localhost:5901"), KConfigGroup());
+                vncBox->addWidget(mVncView);
+                this->setLayout(vncBox);
+                
+                mVncView->show();
+                mVncView->start();
+            }
+        }
+        
+        // Flag to indicate success and failure
+        bool status = false;
+
+        if (mVmMode.compare("v3_vncclient") == 0) {
+                // This is VNC mode
+                status = true;       
+                
+        } else {
+            int success;
+
+            // This is v3_stream or v3_cons_sc mode
+            if (mTermProcess != NULL && mTermProcess->waitForStarted()) {
+                   success = 0;
+                   qDebug() << "Process started";
+           } else {
+                   success = -1;
+                    qDebug() << "Process did not start";
+            }
+            
+           if (success == 0) {
+               /* Wait for the xterm window to be opened and resize it
+                 * to our own widget size.
+                */
+               Display *dsp = XOpenDisplay(NULL);
+               Window wnd = winId();
+
+               bool childFound = false;
+               while (!childFound && mTermProcess->state() == QProcess::Running) {
+                       Window root, parent, *children;
+                       uint numwin;
+                       XQueryTree(dsp, wnd, &root, &parent, &children, &numwin);
+                       childFound = (children != NULL);
+        
+                        if (childFound) {
+                               XResizeWindow(dsp, *children, width(), height());
+                       }
+               }
+
+               XCloseDisplay(dsp);
+
+               if (!childFound)
+                       success = -2;
+           }
+        
+            if (success < 0) {
+               qDebug() << (success == -1 ? "Starting the process failed" 
+                        : "Process started, but exited before opening a terminal");
+
+               if (success < -1)
+                       tryTerminate();
+           }
+        
+           status = (success == 0);
+        }
+
+        return status;
+}
+
+void VmConsoleWidget::termProcessExited(int a, QProcess::ExitStatus b) {
+       qDebug() << "Term Process Exited: " << a << " :  " << b;
+
+       if (mTermProcess != NULL) {
+            delete mTermProcess;
+        }
+
+        if (mVncServer != NULL) {
+            delete mVncServer;
+        }
+
+       mTermProcess = NULL;
+        mVncServer = NULL;
+
+       emit exited();
+}
+
+void VmConsoleWidget::errorMessage(QProcess::ProcessError err) {
+        qDebug() << "Process error: " << err;
+}
diff --git a/linux_usr/gui/palacios/vm_console_widget.h b/linux_usr/gui/palacios/vm_console_widget.h
new file mode 100644 (file)
index 0000000..6871d6e
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * vm_console_widget.h
+ *
+ *  Created on: Oct 5, 2012
+ *      Author: abhinav
+ */
+
+#ifndef VM_CONSOLE_WIDGET_H_
+#define VM_CONSOLE_WIDGET_H_
+
+#include "vnc_module/vncview.h"
+
+#include <QProcess>
+#include <QWidget>
+#include <QCloseEvent>
+
+class VmConsoleWidget: public QWidget {
+Q_OBJECT
+
+public:
+        // Different operation modes of VM
+        enum {
+                STREAM, CONSOLE, VNC
+        };
+        
+       VmConsoleWidget(QWidget* parent = 0);
+       virtual ~VmConsoleWidget();
+       bool isRunning();
+
+public slots:
+       bool start(int mode, QString devfile, QString streamName);
+       bool tryTerminate();
+       void mainWindowClosing();
+
+protected slots:
+       void termProcessExited(int, QProcess::ExitStatus);
+        void errorMessage(QProcess::ProcessError);
+
+signals:
+       void exited();
+
+protected:
+       void closeEvent(QCloseEvent *);
+       void resizeEvent(QResizeEvent *);
+
+private:
+       int mCols;
+       int mRows;
+        QString mVmMode;
+        // Process for xterm
+       QProcess* mTermProcess;
+        // VNC
+        QProcess* mVncServer;
+        VncView* mVncView;
+
+};
+
+
+#endif /* VM_CONSOLE_WIDGET_H_ */
diff --git a/linux_usr/gui/palacios/vm_creation_wizard.cpp b/linux_usr/gui/palacios/vm_creation_wizard.cpp
new file mode 100644 (file)
index 0000000..200fb5c
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * newvmwizard.cpp
+ *
+ *  Created on: Sep 20, 2012
+ *      Author: abhinav
+ */
+
+#include <QMessageBox>
+#include "vm_creation_wizard.h"
+
+NewVmWizard::NewVmWizard(QWidget* parent) :
+               QWizard(parent) {
+        
+        setPage(Page_Intro, new IntroPage);
+       setPage(Page_Image_File, new GuestImagePage);
+       setPage(Page_Final, new FinalPage);
+        setStartId(Page_Intro);
+        
+        setOptions(QWizard::NoBackButtonOnLastPage);
+       setWindowTitle(tr("New Virtual Machine"));
+}
+
+NewVmWizard::~NewVmWizard() {
+}
+
+IntroPage::IntroPage(QWidget* parent) :
+               QWizardPage(parent) {
+       setTitle(tr("Introduction"));
+       setPixmap(QWizard::WatermarkPixmap, QPixmap(":/images/images/palacios.png"));
+
+       topLabel = new QLabel(
+                       tr("This wizard will help you to create a new virtual machine"));
+       topLabel->setWordWrap(true);
+
+       QVBoxLayout *layout = new QVBoxLayout;
+       layout->addWidget(topLabel);
+       setLayout(layout);
+}
+
+IntroPage::~IntroPage() {
+        delete topLabel;
+}
+
+int IntroPage::nextId() const {
+       return NewVmWizard::Page_Image_File;
+}
+
+GuestImagePage::GuestImagePage(QWidget* parent) :
+               QWizardPage(parent) {
+       setTitle(tr("VM Creation"));
+       setSubTitle(
+                       tr(
+                                       "Please fill all the fields. Make sure all file paths are correct"));
+
+       guestNameLabel = new QLabel(tr("Enter a name for the guest"));
+       guestName = new QLineEdit();
+       guestNameLabel->setBuddy(guestName);
+
+       configLocLabel = new QLabel(tr("Enter path of config file"));
+       configLoc = new QLineEdit();
+       configLocLabel->setBuddy(configLoc);
+
+       imageLocLabel = new QLabel(tr("Enter path of image file"));
+       imageLoc = new QLineEdit();
+       imageLocLabel->setBuddy(imageLoc);
+
+       browseConfig = new QPushButton(tr("Browse"));
+       browseImage = new QPushButton(tr("Browse"));
+
+       registerField("guestName*", guestName);
+       registerField("configLoc*", configLoc);
+       registerField("imageLoc*", imageLoc);
+       //registerField("memory*", memory);
+
+       connect(browseConfig, SIGNAL(clicked()), this, SLOT(locateConfigFile()));
+       connect(browseImage, SIGNAL(clicked()), this, SLOT(locateImageFile()));
+
+       QGridLayout* layout = new QGridLayout();
+       layout->addWidget(guestNameLabel, 0, 0);
+       layout->addWidget(guestName, 0, 1);
+       layout->addWidget(configLocLabel, 1, 0);
+       layout->addWidget(configLoc, 1, 1);
+       layout->addWidget(browseConfig, 1, 2);
+       layout->addWidget(imageLocLabel, 2, 0);
+       layout->addWidget(imageLoc, 2, 1);
+       layout->addWidget(browseImage, 2, 2);
+
+       setLayout(layout);
+}
+
+GuestImagePage::~GuestImagePage() {
+        delete guestNameLabel;
+        delete guestName;
+        delete configLocLabel;
+        delete configLoc;
+        delete imageLocLabel;
+        delete imageLoc;
+        delete browseConfig;
+        delete browseImage;
+}
+
+void GuestImagePage::locateConfigFile() {
+       QString configFile = QFileDialog::getOpenFileName(this, tr("Open file"), ".",
+                       "XML file (*.xml)");
+       configLoc->setText(configFile);
+}
+
+void GuestImagePage::locateImageFile() {
+       QString imageFile = QFileDialog::getOpenFileName(this, tr("Open file"), ".",
+                       "Image file (*.img *.bZ)");
+       imageLoc->setText(imageFile);
+}
+
+int GuestImagePage::nextId() const {
+       return NewVmWizard::Page_Final;
+}
+
+bool GuestImagePage::validatePage() {        
+        v3Proc = new QProcess();
+        v3Proc->setProcessChannelMode(QProcess::MergedChannels);
+        v3Proc->start("cat /proc/v3vee/v3-guests");
+        v3Proc->waitForFinished();
+        qDebug() << "Reply from proc to check for new VM creation: " << v3Proc->readAllStandardOutput();
+        QString name = field("guestName").toString();
+        QByteArray temp = name.toLocal8Bit();
+        const char* vmEntry = temp.data();
+        bool exists = false;
+
+        QByteArray val = v3Proc->readAllStandardOutput();
+        if (!val.isNull()) {
+                QList<QByteArray> procLine = val.split('\n');
+                if (procLine.size() > 0) {
+                        for (int i=0; i<procLine.size(); i++) {
+                                if (procLine[i].contains(vmEntry)) {
+                                        exists = true;
+                                        break;
+                                }
+                        }
+                }
+        }
+
+        if (exists) {
+               QMessageBox warning;
+               warning.setText("A Virtual Machine with this name already exists! Please use another name");
+               warning.setIcon(QMessageBox::Critical);
+               warning.setStandardButtons(
+                               QMessageBox::Ok);
+               warning.exec();
+                return false;
+        }
+        
+        delete v3Proc;
+        return true;
+}
+
+FinalPage::FinalPage(QWidget* parent) :
+               QWizardPage(parent) {
+        this->setCommitPage(true);
+        this->setFinalPage(true);
+       setTitle(tr("Status"));
+       setPixmap(QWizard::WatermarkPixmap, QPixmap(":/images/images/palacios.png"));
+
+       finalLabel = new QLabel("VM Creation Successful");
+
+       QVBoxLayout* layout = new QVBoxLayout();
+       layout->addWidget(finalLabel);
+
+       setLayout(layout);
+}
+
+FinalPage::~FinalPage() {
+        delete finalLabel;
+}
+
+int FinalPage::nextId() const {
+        return -1;
+}
diff --git a/linux_usr/gui/palacios/vm_creation_wizard.h b/linux_usr/gui/palacios/vm_creation_wizard.h
new file mode 100644 (file)
index 0000000..7be86b4
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * newvmwizard.h
+ *
+ *  Created on: Sep 20, 2012
+ *      Author: abhinav
+ */
+
+#ifndef NEWVMWIZARD_H_
+#define NEWVMWIZARD_H_
+
+#include <QtGui>
+#include <QWizard>
+
+class IntroPage;
+class GuestImagePage;
+class FinalPage;
+
+class NewVmWizard: public QWizard {
+Q_OBJECT
+public:
+       enum {
+               Page_Intro, Page_Image_File, Page_Final
+       };
+       NewVmWizard(QWidget* parent = 0);
+       ~NewVmWizard();
+
+signals:
+       void finishedWizard(QString guestName);
+
+private:
+        IntroPage* mIntroPage;
+        GuestImagePage* mImagePage;
+        FinalPage* mFinalPage;
+};
+
+class IntroPage: public QWizardPage {
+Q_OBJECT
+
+public:
+       IntroPage(QWidget* parent = 0);
+        ~IntroPage();
+       int nextId() const;
+
+private:
+       QLabel* topLabel;
+};
+
+class GuestImagePage: public QWizardPage {
+Q_OBJECT
+
+public:
+       GuestImagePage(QWidget* parent = 0);
+        ~GuestImagePage();
+        bool validatePage();
+       int nextId() const;
+
+private slots:
+       void locateConfigFile();
+       void locateImageFile();
+
+private:
+       QLabel* guestNameLabel;
+       QLabel* configLocLabel;
+       QLabel* imageLocLabel;
+
+       QLineEdit* guestName;
+       QLineEdit* configLoc;
+       QLineEdit* imageLoc;
+
+       QPushButton* browseConfig;
+       QPushButton* browseImage;
+
+        QProcess* v3Proc;
+};
+
+class FinalPage: public QWizardPage {
+Q_OBJECT
+
+public:
+       FinalPage(QWidget* parent = 0);
+        ~FinalPage();
+       int nextId() const;
+
+private:
+       QLabel* finalLabel;
+};
+
+#endif /* NEWVMWIZARD_H_ */
diff --git a/linux_usr/gui/palacios/vm_info_widget.cpp b/linux_usr/gui/palacios/vm_info_widget.cpp
new file mode 100644 (file)
index 0000000..a1c1845
--- /dev/null
@@ -0,0 +1,356 @@
+#include "newpalacios.h"
+
+VmInfoWidget::VmInfoWidget(QWidget* parent) :
+               QWidget(parent) {
+       setInfoView();
+       setupUi();
+}
+
+VmInfoWidget::~VmInfoWidget() {
+        delete mVmInfoView;
+}
+
+void VmInfoWidget::setInfoView() {
+       // Create the main tree widget
+       mVmInfoView = new QTreeWidget();
+       mVmInfoView->setColumnCount(2);
+       QStringList headerLabels;
+       headerLabels << "Property" << "Value";
+       mVmInfoView->setHeaderLabels(headerLabels);
+}
+
+void VmInfoWidget::setupUi() {
+       QVBoxLayout* vmDetailsLayout = new QVBoxLayout(this);
+       vmDetailsLayout->addWidget(mVmInfoView);
+        setLayout(vmDetailsLayout);
+}
+
+void VmInfoWidget::parseAttribute(const QDomElement &element,
+                              QTreeWidgetItem* parent) {
+    QDomNamedNodeMap atts = element.attributes();
+
+    for (unsigned int i=0; i<atts.length(); i++) {
+        QTreeWidgetItem* item = new QTreeWidgetItem(parent);
+
+        item->setText(0, "[" + atts.item(i).nodeName() +"]");
+        item->setText(1, "[" + atts.item(i).nodeValue() +"]");
+    }
+}
+
+void VmInfoWidget::parseText(const QDomElement &element,
+                              QTreeWidgetItem* parent) {
+    QString value = element.text();
+    parent->setText(1, value);
+}
+
+void VmInfoWidget::parseElement(const QDomElement &element,
+                              QTreeWidgetItem* parent) {
+
+    QTreeWidgetItem* item = new QTreeWidgetItem(parent);
+
+    if (element.tagName().compare("memory") == 0) {
+        // Memory tag
+        item->setText(0, "memory");
+        parseAttribute(element, item);
+        parseText(element, item);
+
+    } else if (element.tagName().compare("telemetry") == 0) {
+        // Telemetry tag
+        item->setText(0, "telemetry");
+        parseText(element, item);
+
+    } else if (element.tagName().compare("extensions") == 0) {
+        // Extensions tag
+        item->setText(0, "extensions");
+        QDomNode child = element.firstChild();
+        while (!child.isNull()) {
+            if (!child.isElement()) {
+                child = child.nextSibling();
+                continue;
+            }
+
+            parseElement(child.toElement(), item);
+            child = child.nextSibling();
+        }
+
+    } else if (element.tagName().compare("extension") == 0) {
+      // Specific Extension
+        item->setText(0, "extension");
+        parseAttribute(element, item);
+        parseText(element, item);
+
+    } else if (element.tagName().compare("paging") == 0) {
+        // Paging tag
+        item->setText(0, "paging");
+        parseAttribute(element, item);
+        QDomNode child = element.firstChild();
+        while (!child.isNull()) {
+            if (!child.isElement()) {
+                child = child.nextSibling();
+                continue;
+            }
+
+            parseElement(child.toElement(), item);
+            child = child.nextSibling();
+        }
+
+    } else if (element.tagName().compare("strategy") == 0) {
+        item->setText(0, "strategy");
+        parseText(element, item);
+
+    } else if (element.tagName().compare("large_pages") == 0) {
+        item->setText(0, "large_pages");
+        parseText(element, item);
+
+    } else if (element.tagName().compare("schedule_hz") == 0) {
+        // Schedule Hz
+        item->setText(0, "schedule_hz");
+        parseText(element, item);
+
+    } else if (element.tagName().compare("cores") == 0) {
+        // Cores
+        item->setText(0, "cores");
+        parseAttribute(element, item);
+
+    } else if (element.tagName().compare("core") == 0) {
+        item->setText(0, "core");
+
+    } else if (element.tagName().compare("memmap") == 0) {
+        item->setText(0, "memmap");
+        QDomNode child = element.firstChild();
+        while (!child.isNull()) {
+
+            if (!child.isElement()) {
+                child = child.nextSibling();
+                continue;
+            }
+
+            parseElement(child.toElement(), item);
+            child = child.nextSibling();
+        }
+
+    } else if (element.tagName().compare("region") == 0) {
+        item->setText(0, "region");
+        QDomNode child = element.firstChild();
+        while (!child.isNull()) {
+            if (!child.isElement()) {
+                child = child.nextSibling();
+                continue;
+            }
+
+            parseElement(child.toElement(), item);
+            child = child.nextSibling();
+        }
+
+    } else if (element.tagName().compare("start") == 0) {
+        item->setText(0, "start");
+        parseText(element, item);
+
+    } else if (element.tagName().compare("end") == 0) {
+        item->setText(0, "end");
+        parseText(element, item);
+
+    } else if (element.tagName().compare("host_addr") == 0) {
+        item->setText(0, "host_addr");
+        parseText(element, item);
+
+    } else if (element.tagName().compare("files") == 0) {
+        item->setText(0, "files");
+        QDomNode child = element.firstChild();
+        while (!child.isNull()) {
+            if (!child.isElement()) {
+                child = child.nextSibling();
+                continue;
+            }
+
+            parseElement(child.toElement(), item);
+            child = child.nextSibling();
+        }
+
+    } else if (element.tagName().compare("file") == 0) {
+        item->setText(0, "file");
+        parseAttribute(element, item);
+
+    } else if (element.tagName().compare("devices") == 0) {
+        // Devices
+        item->setText(0, "devices");
+        QDomNode child = element.firstChild();
+        while (!child.isNull()) {
+            if (!child.isElement()) {
+                child = child.nextSibling();
+                continue;
+            }
+
+            parseElement(child.toElement(), item);
+            child = child.nextSibling();
+        }
+
+    } else if (element.tagName().compare("device") == 0) {
+        // Device
+        item->setText(0, "device");
+        parseAttribute(element, item);
+        QDomNode child = element.firstChild();
+        while (!child.isNull()) {
+            if (!child.isElement()) {
+                child = child.nextSibling();
+                continue;
+            }
+
+            parseElement(child.toElement(), item);
+            child = child.nextSibling();
+        }
+
+    } else if (element.tagName().compare("storage") == 0) {
+        item->setText(0, "storage");
+        parseText(element, item);
+
+    } else if (element.tagName().compare("apic") == 0) {
+        item->setText(0, "apic");
+        parseText(element, item);
+
+    } else if (element.tagName().compare("bus") == 0) {
+        // Bus tag, is seen in many device tags
+
+    } else if (element.tagName().compare("vendor_id") == 0) {
+        item->setText(0, "vendor_id");
+        parseText(element, item);
+
+    } else if (element.tagName().compare("device_id") == 0) {
+        item->setText(0, "device_id");
+        parseText(element, item);
+
+    } else if (element.tagName().compare("irq") == 0) {
+        item->setText(0, "irq");
+        parseText(element, item);
+
+    } else if (element.tagName().compare("controller") == 0) {
+        // Controller tag, is also seen in some device files
+        item->setText(0, "controller");
+        parseText(element, item);
+
+    } else if (element.tagName().compare("file") == 0) {
+        item->setText(0, "file");
+        parseText(element, item);
+
+    } else if (element.tagName().compare("frontend") == 0) {
+        item->setText(0, "frontend");
+        parseAttribute(element, item);
+        QDomNode child = element.firstChild();
+        while (!child.isNull()) {
+            if (!child.isElement()) {
+                child = child.nextSibling();
+                continue;
+            }
+
+            parseElement(child.toElement(), item);
+            child = child.nextSibling();
+        }
+
+    } else if (element.tagName().compare("model") == 0) {
+        item->setText(0, "model");
+        parseText(element, item);
+
+    } else if (element.tagName().compare("type") == 0) {
+        item->setText(0, "type");
+        parseText(element, item);
+
+    } else if (element.tagName().compare("bus_num") == 0) {
+        item->setText(0, "bus_num");
+        parseText(element, item);
+
+    } else if (element.tagName().compare("drive_num") == 0) {
+        item->setText(0, "drive_num");
+        parseText(element, item);
+
+    } else if (element.tagName().compare("path") == 0) {
+        item->setText(0, "path");
+        parseText(element, item);
+
+    } else if (element.tagName().compare("ip") == 0) {
+        item->setText(0, "ip");
+        parseText(element, item);
+
+    } else if (element.tagName().compare("port") == 0) {
+        item->setText(0, "port");
+        parseText(element, item);
+
+    } else if (element.tagName().compare("tag") == 0) {
+        item->setText(0, "tag");
+        parseText(element, item);
+
+    } else if (element.tagName().compare("size") == 0) {
+        item->setText(0, "size");
+        parseText(element, item);
+
+    } else if (element.tagName().compare("mac") == 0) {
+        item->setText(0, "mac");
+        parseText(element, item);
+
+    } else if (element.tagName().compare("name") == 0) {
+        item->setText(0, "name");
+        parseText(element, item);
+
+    } else if (element.tagName().compare("ports") == 0) {
+        item->setText(0, "ports");
+        QDomNode child = element.firstChild();
+        while (!child.isNull()) {
+            if (!child.isElement()) {
+                child = child.nextSibling();
+                continue;
+            }
+
+            parseElement(child.toElement(), item);
+            child = child.nextSibling();
+        }
+
+    } else if (element.tagName().compare("mode") == 0) {
+        item->setText(0, "mode");
+        parseText(element, item);
+
+    }
+}
+
+void VmInfoWidget::updateInfoView(VmInfo* vm) {
+       // Open config file
+       QFile file(vm->getVmConfigFile());
+       if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+               qDebug() << "File cannot be opened!";
+               return;
+       }
+
+       // Setup DOM parser
+       QDomDocument doc("vm_config");
+       if (!doc.setContent(&file)) {
+               qDebug() << "Error setting content";
+               return;
+       }
+       
+       file.close();
+       
+       // Root element
+       QTreeWidgetItem* rootItem = new QTreeWidgetItem();
+       QDomElement root = doc.documentElement();
+       
+       rootItem->setText(0, root.tagName());
+       parseAttribute(root, rootItem);
+       mVmInfoView->takeTopLevelItem(0);
+       mVmInfoView->addTopLevelItem(rootItem);
+
+       // Elements
+       QDomNode n = root.firstChild();
+       while (!n.isNull()) {
+
+               if (n.isElement()) {
+                       parseElement(n.toElement(), rootItem);
+               }
+
+               n = n.nextSibling();
+       }
+
+       mVmInfoView->expandAll();
+}
+
+void VmInfoWidget::deleteVm() {
+       QTreeWidgetItem* item = mVmInfoView->takeTopLevelItem(0);
+       delete item;
+}
diff --git a/linux_usr/gui/palacios/vm_mode_dialog.cpp b/linux_usr/gui/palacios/vm_mode_dialog.cpp
new file mode 100644 (file)
index 0000000..8d8ae70
--- /dev/null
@@ -0,0 +1,120 @@
+#include <QDebug>
+
+#include "newpalacios.h"
+
+VmModeDialog::VmModeDialog(QWidget* parent) {
+        setupDialog();
+}
+
+void VmModeDialog::setupDialog() {
+        isV3Cons = false;
+        isV3Stream = false;
+        isV3Vnc = false;
+        
+        // Group box to hold radio buttons
+        v3_modes = new QGroupBox(tr("Select VM mode"));
+        // Widget to give information about stream name
+        // for v3_stream
+        v3_stream_info = new QWidget(v3_modes);
+
+        v3_stream = new QRadioButton(tr("Stream Mode"));
+        v3_cons = new QRadioButton(tr("Console Mode"));
+        v3_vnc = new QRadioButton(tr("VNC mode"));
+        
+        // Setup stream info widget
+        QLabel* v3_stream_label = new QLabel(tr("Stream name"));
+        v3_stream_name = new QLineEdit();
+        
+        QGridLayout* grid = new QGridLayout();
+        grid->addWidget(v3_stream_label, 0, 0);
+        grid->addWidget(v3_stream_name, 0, 1);
+        v3_stream_info->setLayout(grid);
+        v3_stream_info->setVisible(false);
+        
+        // Setup group box
+        QVBoxLayout* box = new QVBoxLayout();
+        box->addWidget(v3_cons);
+        box->addWidget(v3_stream);
+        box->addWidget(v3_stream_info);
+        box->addWidget(v3_vnc);
+        v3_modes->setLayout(box);
+        
+        // Setup main layout for dialog
+        QVBoxLayout* mainLayout = new QVBoxLayout();
+        mainLayout->addWidget(v3_modes);
+        QHBoxLayout* actionLayout = new QHBoxLayout();
+        QPushButton* ok = new QPushButton(tr("OK"));
+        QPushButton* cancel = new QPushButton(tr("Cancel"));
+        actionLayout->addWidget(ok);
+        actionLayout->addWidget(cancel);
+        mainLayout->addLayout(actionLayout);
+        
+        setLayout(mainLayout);
+        resize(300, 200);
+        move(200, 200);
+        setWindowTitle("Select VM mode");
+
+        // Connect signals and slots
+        connect(v3_cons, SIGNAL(toggled(bool)), this, SLOT(selectMode(bool)));
+        connect(v3_stream, SIGNAL(toggled(bool)), this, SLOT(selectMode(bool)));
+        connect(v3_vnc, SIGNAL(toggled(bool)), this, SLOT(selectMode(bool)));
+        connect(ok, SIGNAL(clicked()), this, SLOT(okButton()));
+        connect(cancel, SIGNAL(clicked()), this, SLOT(cancelButton()));
+}
+
+void VmModeDialog::okButton() {
+        if (isV3Cons == false
+                && isV3Stream == false
+                && isV3Vnc == false) {
+            
+            // Do not emit anything
+            close();
+            return;
+        }
+
+        QString name = "";
+        
+        if (isV3Stream) {
+                name = v3_stream_name->text();
+        }
+        
+        emit setMode(mode, name);
+        close();
+}
+
+void VmModeDialog::cancelButton() {
+        close();
+}
+
+void VmModeDialog::selectMode(bool checked) {
+        if (checked == true) {
+                if (v3_cons->isChecked()) {
+                        // If console is checked, then set
+                        // mode to v3_cons
+                        mode = VmConsoleWidget::CONSOLE;
+                        isV3Cons = true;
+                        isV3Stream = false;
+                        isV3Vnc = false;
+                        v3_stream_info->setVisible(false);
+
+                } else if (v3_stream->isChecked()) {
+                        mode = VmConsoleWidget::STREAM;
+                        isV3Cons = false;
+                        isV3Stream = true;
+                        isV3Vnc = false;
+                        v3_stream_info->setVisible(true);
+
+                } else if (v3_vnc->isChecked()) {
+                        mode = VmConsoleWidget::VNC;
+                        isV3Cons = false;
+                        isV3Stream = false;
+                        isV3Vnc = true;
+                        v3_stream_info->setVisible(false);
+
+                } else {
+                        isV3Cons = false;
+                        isV3Stream = false;
+                        isV3Vnc = false;
+                }
+        }
+}
diff --git a/linux_usr/gui/palacios/vm_threads.cpp b/linux_usr/gui/palacios/vm_threads.cpp
new file mode 100644 (file)
index 0000000..2acedd8
--- /dev/null
@@ -0,0 +1,446 @@
+#include <QDebug>
+
+#include "newpalacios.h"
+
+class ProcVm {
+public:
+       QString name;
+       QString devFile;
+};
+
+class DbVm {
+public:
+       QString name;
+       QString config;
+       QString image;
+       int state;
+       QString dev;
+};
+
+int LoadVmsThread::getStatus() {
+       return status;
+}
+
+QList<VmInfo*> LoadVmsThread::getVmList() {
+       return list;
+}
+
+void LoadVmsThread::loadVms() {
+        bool doesProcExist = false;
+        bool isDbPresent = false;
+        
+        // Check if /proc file exists
+        QFileInfo procInfo("/proc/v3vee/v3-guests");
+        if (procInfo.exists()) {
+                // Proc file exists
+                doesProcExist = true;
+        } 
+       
+        // Read proc file
+        //QStringList procVms;
+        QList<ProcVm> procVms;
+        
+        if (doesProcExist) {
+                QProcess* p = new QProcess();
+                p->setProcessChannelMode(QProcess::MergedChannels);
+                QStringList args;
+                args << "-c" << "cat /proc/v3vee/v3-guests";
+                p->start("sh", args);
+                if (!p->waitForFinished()) {
+                        // Since we are unable to open the proc file
+                        // for whatever some reason, the only way
+                        // to identify this state would be to mark /proc
+                        // as not existing                        
+                        doesProcExist = false;
+                        
+                } else {
+                        QByteArray procFile = p->readAllStandardOutput();
+                        if (!procFile.isNull()) {
+                            if (procFile.isEmpty()) {
+                                doesProcExist = false;
+
+                            } else {
+                                QList<QByteArray> procContents = procFile.split('\n');
+                                
+                                for (int i=0; i<procContents.size(); i++) {
+                                        QByteArray b = procContents.at(i);
+                                        QString procentry(b);
+                                        QStringList vals = procentry.split('\t');
+                                                                            
+                                        if (vals.size() == 2) {
+                                               ProcVm procVm;
+                                                QString val = vals.at(0);
+                                                val.remove(QChar('\n'), Qt::CaseInsensitive);
+                                               procVm.name = val;
+                                                
+                                                val = vals.at(1);
+                                                val.remove(QChar('\n'), Qt::CaseInsensitive);
+                                               procVm.devFile = val;
+                                               procVms.append(procVm);
+                                        }
+                                }
+                            }
+                        } 
+                }
+                
+                // Delete proc process
+                delete p;
+        }
+        
+        // Check if proc is empty
+        if (doesProcExist && procVms.size() == 0) {
+                // There was nothing in the proc file
+                doesProcExist = true;
+        }
+        
+        // Check if DB exists
+        QFileInfo dbFile("virtual_machines_list.txt");
+        if (dbFile.exists()) {
+               isDbPresent = true;
+        }
+        
+        QFile file("virtual_machines_list.txt");
+        // Open DB file
+        if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+                // The DB file is missing
+               isDbPresent = false;
+       }
+       
+       // Check if there is any source to load the VM
+       if (!doesProcExist && !isDbPresent) {
+               // If proc file does not exist or is empty
+               // and the DB does not exist then there are 
+               // no VMs to load
+               // return with STATUS_OK
+               status = STATUS_OK;
+               emit finished();
+               return; 
+       }
+       
+       //QStringList dbVms;
+        QList<DbVm> dbVms;
+
+       if (isDbPresent) {
+               // Read the DB file
+                       QTextStream in(&file);
+               while (!in.atEnd()) {
+                       QString line = in.readLine();
+                       if (line.compare("\n") == 0) {
+                               continue;
+                       }
+               
+                       QStringList vmDet = line.split(",");
+                       DbVm dbVm;
+                       dbVm.name = vmDet.at(0);
+                       dbVm.config = vmDet.at(1);
+                       dbVm.dev = vmDet.at(2);
+                       dbVm.state = vmDet.at(3).toInt();
+                       dbVm.image = vmDet.at(4);
+                       
+                       dbVms.append(dbVm);
+               }
+       }
+                       
+       if (!doesProcExist && isDbPresent) {
+               // If /proc does not exist but DB does
+               // then all VMs are inactive
+               for (int i=0; i<dbVms.size(); i++) {
+                       VmInfo* vmDb = new VmInfo();
+                       vmDb->setVmName(dbVms[i].name);
+                       vmDb->setVmConfigFile(dbVms[i].config);
+                       vmDb->setVmDevFile(dbVms[i].dev);
+                       vmDb->setState(dbVms[i].state);
+                       vmDb->setImageFile(dbVms[i].image);
+                       vmDb->setCategory(VmInfo::INACTIVE_INVENTORY);
+                       // Add VM to loading list
+                       list.append(vmDb);
+               }
+                               
+       } else if (doesProcExist && !isDbPresent) {
+               // If /proc exists but DB does not
+               for (int i=0; i<procVms.size(); i++) {
+                       VmInfo* vmProc = new VmInfo();
+                       vmProc->setVmName(procVms[i].name);
+                       vmProc->setVmConfigFile("");
+                       vmProc->setVmDevFile(procVms[i].devFile);
+                       vmProc->setState(VmInfo::STOPPED);
+                       vmProc->setImageFile("");
+                       vmProc->setCategory(VmInfo::ACTIVE_NOT_INVENTORY);
+                       // Add VM to loading list
+                       list.append(vmProc);
+               }
+               
+       } else if (doesProcExist && isDbPresent) {
+               // Both files exist
+               // Compare entries in /proc and text file, mark non-matching entries in /proc as active not inventory
+               QList<int> procIndices;
+               QList<int> dbIndices;           
+               
+                int found = -1;
+
+               for (int i=0; i<procVms.size(); i++) {
+                       for (int j=0; j<dbVms.size(); j++) {
+                               if ((procVms[i].devFile.compare(dbVms[j].dev) == 0)
+                                       && (procVms[i].name.compare(dbVms[j].name) == 0)) {
+                                        found = j;
+                                       procIndices.append(i);
+                                       dbIndices.append(j);
+                                       break;
+                               }               
+                       }
+                       
+                        if (found >= 0) {
+                               VmInfo* vm = new VmInfo();
+                               vm->setVmName(dbVms[found].name);
+                               vm->setVmConfigFile(dbVms[found].config);
+                               vm->setVmDevFile(dbVms[found].dev);
+                               vm->setState(dbVms[found].state);
+                               vm->setImageFile(dbVms[found].image);
+                               
+                               vm->setCategory(VmInfo::ACTIVE_INVENTORY);
+                               // Add VM to loading list
+                               list.append(vm);
+                                found = -1;
+                        }
+               }
+               
+               // Once we have compared /proc with the DB and marked matching indices
+               // we mark the rest of the entries in /proc as active not inventory
+               for (int j=0; j<procVms.size(); j++) {
+                       if (!procIndices.contains(j)) {
+                               VmInfo* vmProcOnly = new VmInfo();
+                               vmProcOnly->setVmName(procVms[j].name);
+                               vmProcOnly->setVmConfigFile("");
+                               vmProcOnly->setVmDevFile(procVms[j].devFile);
+                               vmProcOnly->setState(VmInfo::STOPPED);
+                               vmProcOnly->setImageFile("");
+                               vmProcOnly->setCategory(VmInfo::ACTIVE_NOT_INVENTORY);
+                               list.append(vmProcOnly);
+                       }
+               }
+               
+               // Once we have compared /proc with the DB and marked matching indices
+               // we mark the rest of the entries in dbVms as inactive
+               for (int j=0; j<dbVms.size(); j++) {
+                       if (!dbIndices.contains(j)) {
+                               VmInfo* vmDbOnly = new VmInfo();
+                               vmDbOnly->setVmName(dbVms[j].name);
+                               vmDbOnly->setVmConfigFile(dbVms[j].config);
+                               vmDbOnly->setVmDevFile("");
+                               vmDbOnly->setState(dbVms[j].state);
+                               vmDbOnly->setImageFile(dbVms[j].image);
+                               vmDbOnly->setCategory(VmInfo::INACTIVE_INVENTORY);
+                               list.append(vmDbOnly);
+                       }
+               }
+       }
+       
+       status = STATUS_OK;
+       file.close();
+
+       emit finished();
+}
+
+AddVmThread::AddVmThread(QString name, QString conf, QString img) {
+       this->status = STATUS_OK;
+       this->vmName = name;
+       this->vmConfigFile = conf;
+        this->vmImageFile = img;
+}
+
+int AddVmThread::getStatus() {
+       return status;
+}
+
+VmInfo* AddVmThread::getNewVm() {
+       return vm;
+}
+
+QString AddVmThread::getName() {
+       return vmName;
+}
+
+void AddVmThread::addVm() {
+       QFile file("virtual_machines_list.txt");
+       if (!file.open(QIODevice::Append | QIODevice::Text)) {
+               status = ERROR_V3CREATE_DB;
+               emit finished();
+               return;
+       }
+       
+       // Add VM to the inventory (database). The VM still needs to be
+        // activated to run
+        // Create new VM instance
+        // The dev file for this VM will be set when it is activated
+        vm = new VmInfo();
+        vm->setVmName(vmName);
+        vm->setVmConfigFile(vmConfigFile);
+        vm->setImageFile(vmImageFile);
+        vm->setCategory(VmInfo::INACTIVE_INVENTORY);
+       
+       QTextStream out(&file);
+       
+        out << vmName;
+        out << ",";
+        out << vmConfigFile;
+        out << ",";
+        out << vmDevFile;
+        out << ",";
+        out << QString::number(VmInfo::STOPPED);
+        out << ",";
+        out << vmImageFile;
+        out << endl;
+       
+        out.flush();
+       file.close();
+        
+        status = STATUS_OK;
+
+       emit finished();
+}
+
+DeleteVmThread::DeleteVmThread(int category, QString name, QString devfile) {
+        this->vmCategory = category;
+       this->vmToDelete = name;
+       this->status = -2;
+        this->vmDevfile = devfile;
+}
+
+int DeleteVmThread::getStatus() {
+       return status;
+}
+
+/*void DeleteVmThread::processStarted() {
+       //qDebug() << "V3 Free process started";
+}
+
+void DeleteVmThread::processExit(int errorCode, QProcess::ExitStatus exitStatus) {
+       if (exitStatus == QProcess::CrashExit) {
+               //qDebug() << "v3_free process crashed!!";
+       } else {
+               //qDebug() << "v3_free process exited normally..";
+       }
+}
+
+void DeleteVmThread::processError(QProcess::ProcessError error) {
+       //qDebug() << "There was an error in the v3_free process execution...";
+       
+       switch (error) {
+       case QProcess::FailedToStart:
+               //qDebug() << "Process failed to start...";
+               break;
+       case QProcess::Crashed:
+               //qDebug() << "Process crashed...";
+               break;
+       case QProcess::Timedout:
+               //qDebug() << "Process timed out...";
+               break;
+       case QProcess::WriteError:
+               //qDebug() << "Process had write error...";
+               break;
+       case QProcess::ReadError:
+               //qDebug() << "Process had read error...";
+               break;
+       case QProcess::UnknownError:
+               //qDebug() << "Process unknown error...";
+               break;
+
+       }
+}*/
+
+void DeleteVmThread::deleteVm() {
+     
+     // Check for the category of VM being deleted
+     // If Active or Active not inventory then only
+     // invoke v3_free since we have an instance of the 
+     // VM in proc. If it is Inactive and we are deleting
+     // then we need to just remove it from the DB
+     
+     // Create variables
+     // C++ complains if we create variables inside switch statement
+     QProcess* v3Freeproc;
+     QStringList args;
+     QByteArray procOutput;
+     
+     switch (vmCategory) {
+     case VmInfo::ACTIVE_INVENTORY:
+     case VmInfo::ACTIVE_NOT_INVENTORY:
+       if (vmDevfile == NULL) {
+               // Cannot delete VM without dev file
+                status = ERROR_V3FREE_INVALID_ARGUMENT;
+                emit finished();
+                return;
+        }
+       
+               v3Freeproc = new QProcess();
+        v3Freeproc->setProcessChannelMode(QProcess::MergedChannels);
+        
+        // Connect debug slots
+        connect(v3Freeproc, SIGNAL(started()), this, SLOT(processStarted()));
+        connect(v3Freeproc, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(processExit(int, QProcess::ExitStatus)));
+        connect(v3Freeproc, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processError(QProcess::ProcessError)));
+        
+        args << vmDevfile;
+        v3Freeproc->start("v3_free", args);
+        
+        if (!v3Freeproc->waitForFinished()) {
+               // Reinsert data into database since v3_free was not successful
+                status = ERROR_V3FREE_PATH;
+                delete v3Freeproc;
+                emit finished();
+                return;
+        } else {
+               procOutput = v3Freeproc->readAllStandardOutput();
+
+               if (procOutput.contains("IOCTL error")) {
+                       status = ERROR_V3FREE_IOCTL;
+                       delete v3Freeproc;
+                       emit finished();
+                       return;
+               }
+        }
+                                
+        // V3_free success
+        if (v3Freeproc != NULL) {
+               delete v3Freeproc;
+        }
+       
+       break;
+     case VmInfo::INACTIVE_INVENTORY:
+     default:
+       break;
+     }
+     
+     QFile file("virtual_machines_list.txt");
+     QFile tempFile("temp.txt");
+
+     bool oldFile = file.open(QIODevice::ReadOnly | QIODevice::Text);
+     bool newFile = tempFile.open(QIODevice::WriteOnly | QIODevice::Text);
+
+     if (!oldFile || !newFile) {
+        status = ERROR_V3FREE_DB;
+       emit finished();
+        return;
+     }
+
+     QTextStream in(&file);
+     QTextStream out(&tempFile);
+
+     while (!in.atEnd()) {
+        QString line = in.readLine();
+       QStringList vm = line.split(",");
+        if (vm.at(0).compare(vmToDelete) != 0) {
+               out << line << endl;
+       }
+     }
+
+    out.flush();
+    file.remove("virtual_machines_list.txt");
+    tempFile.rename("virtual_machines_list.txt");
+      
+    file.close();
+    tempFile.close();
+    status = STATUS_OK;
+        
+    emit finished();
+}
diff --git a/linux_usr/gui/palacios/vm_view.cpp b/linux_usr/gui/palacios/vm_view.cpp
new file mode 100644 (file)
index 0000000..48e5a3d
--- /dev/null
@@ -0,0 +1,58 @@
+#include <QDebug>
+#include <QWidget>
+#include <QStringList>
+#include <QCloseEvent>
+#include <QResizeEvent>
+
+#include "newpalacios.h"
+
+VmXConsoleParent::VmXConsoleParent(QString name, QWidget* parent)
+       : QWidget(parent) {
+       
+       mVmName = name;
+        
+        QVBoxLayout* l = new QVBoxLayout;
+        mConsole = new VmConsoleWidget(this);
+               l->addWidget(mConsole);
+               l->setStretchFactor(mConsole, 1000);
+        
+               this->setLayout(l);
+               this->setWindowTitle(name);
+        
+               connect(this, SIGNAL(windowClosing()), mConsole,
+               SLOT(mainWindowClosing()));
+}
+
+void VmXConsoleParent::showWidget(int mode, QString devfile, QString streamName) {
+       mConsole->start(mode, devfile, streamName);
+               
+       // Workaround for QProcess error
+       mIsConsoleRunning = true;
+}
+
+bool VmXConsoleParent::isRunning() {
+       // FIXME: For some reason QProcess does not seem to return the correct state
+        // Qprocess->state() should give the correct state of the running process
+        // but currently there is a problem with geting the right state.
+        // For the time being a boolean flag is used to represent the state (running/not running)
+               
+        //return mConsole->isRunning();
+        return mIsConsoleRunning;
+}
+
+QString VmXConsoleParent::getVmName() {
+       return mVmName;
+}
+
+void VmXConsoleParent::closeEvent(QCloseEvent* event) {
+        // Workaround for QProcess error
+        /*if (!tryTerminate())
+               qDebug() << "Warning: could not terminate process...there could be a leak";
+       else
+               qDebug() << "Process terminated";*/
+               
+        mIsConsoleRunning = false;
+       emit windowClosingWithId(mVmName);
+        emit windowClosing();
+       event->accept();
+}
diff --git a/linux_usr/gui/palacios/vnc_module/remoteview.cpp b/linux_usr/gui/palacios/vnc_module/remoteview.cpp
new file mode 100644 (file)
index 0000000..e45a1a1
--- /dev/null
@@ -0,0 +1,283 @@
+/****************************************************************************
+**
+** Copyright (C) 2002-2003 Tim Jansen <tim@tjansen.de>
+** Copyright (C) 2007-2008 Urs Wolfer <uwolfer @ kde.org>
+**
+** This file is part of KDE.
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; see the file COPYING. If not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+** Boston, MA 02110-1301, USA.
+**
+****************************************************************************/
+
+#include "remoteview.h"
+
+#ifndef QTONLY
+    #include <KDebug>
+    #include <KStandardDirs>
+#endif
+
+#include <QBitmap>
+
+RemoteView::RemoteView(QWidget *parent)
+        : QWidget(parent),
+        m_status(Disconnected),
+        m_host(QString()),
+        m_port(0),
+        m_viewOnly(false),
+        m_grabAllKeys(false),
+        m_scale(false),
+        m_keyboardIsGrabbed(false),
+#ifndef QTONLY
+        m_wallet(0),
+#endif
+        m_dotCursorState(CursorOff)
+{
+}
+
+RemoteView::~RemoteView()
+{
+#ifndef QTONLY
+    delete m_wallet;
+#endif
+}
+
+RemoteView::RemoteStatus RemoteView::status()
+{
+    return m_status;
+}
+
+void RemoteView::setStatus(RemoteView::RemoteStatus s)
+{
+    if (m_status == s)
+        return;
+
+    if (((1+ m_status) != s) && (s != Disconnected)) {
+        // follow state transition rules
+
+        if (s == Disconnecting) {
+            if (m_status == Disconnected)
+                return;
+        } else {
+            Q_ASSERT(((int) s) >= 0);
+            if (m_status > s) {
+                m_status = Disconnected;
+                emit statusChanged(Disconnected);
+            }
+            // smooth state transition
+            RemoteStatus origState = m_status;
+            for (int i = origState; i < s; ++i) {
+                m_status = (RemoteStatus) i;
+                emit statusChanged((RemoteStatus) i);
+            }
+        }
+    }
+    m_status = s;
+    emit statusChanged(m_status);
+}
+
+bool RemoteView::supportsScaling() const
+{
+    return false;
+}
+
+bool RemoteView::supportsLocalCursor() const
+{
+    return false;
+}
+
+QString RemoteView::host()
+{
+    return m_host;
+}
+
+QSize RemoteView::framebufferSize()
+{
+    return QSize(0, 0);
+}
+
+void RemoteView::startQuitting()
+{
+}
+
+bool RemoteView::isQuitting()
+{
+    return false;
+}
+
+int RemoteView::port()
+{
+    return m_port;
+}
+
+void RemoteView::updateConfiguration()
+{
+}
+
+void RemoteView::keyEvent(QKeyEvent *)
+{
+}
+
+bool RemoteView::viewOnly()
+{
+    return m_viewOnly;
+}
+
+void RemoteView::setViewOnly(bool viewOnly)
+{
+    m_viewOnly = viewOnly;
+}
+
+bool RemoteView::grabAllKeys()
+{
+    return m_grabAllKeys;
+}
+
+void RemoteView::setGrabAllKeys(bool grabAllKeys)
+{
+    m_grabAllKeys = grabAllKeys;
+
+    if (grabAllKeys) {
+        m_keyboardIsGrabbed = true;
+        grabKeyboard();
+    } else if (m_keyboardIsGrabbed) {
+        releaseKeyboard();
+    }
+}
+
+QPixmap RemoteView::takeScreenshot() 
+{
+    return QPixmap::grabWidget(this);
+}
+
+void RemoteView::showDotCursor(DotCursorState state)
+{
+    m_dotCursorState = state;
+}
+
+RemoteView::DotCursorState RemoteView::dotCursorState() const
+{
+    return m_dotCursorState;
+}
+
+bool RemoteView::scaling() const
+{
+    return m_scale;
+}
+
+void RemoteView::enableScaling(bool scale)
+{
+    m_scale = scale;
+}
+
+void RemoteView::switchFullscreen(bool)
+{
+}
+
+void RemoteView::scaleResize(int, int)
+{
+}
+
+KUrl RemoteView::url()
+{
+    return m_url;
+}
+
+#ifndef QTONLY
+QString RemoteView::readWalletPassword(bool fromUserNameOnly)
+{
+    const QString KRDCFOLDER = "KRDC";
+
+    window()->setDisabled(true); // WORKAROUND: disable inputs so users cannot close the current tab (see #181230)
+    m_wallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), window()->winId());
+    window()->setDisabled(false);
+
+    if (m_wallet) {
+        bool walletOK = m_wallet->hasFolder(KRDCFOLDER);
+        if (!walletOK) {
+            walletOK = m_wallet->createFolder(KRDCFOLDER);
+            kDebug(5010) << "Wallet folder created";
+        }
+        if (walletOK) {
+            kDebug(5010) << "Wallet OK";
+            m_wallet->setFolder(KRDCFOLDER);
+            QString password;
+            
+            QString key;
+            if (fromUserNameOnly)
+                key = m_url.userName();
+            else
+                key = m_url.prettyUrl(KUrl::RemoveTrailingSlash);
+
+            if (m_wallet->hasEntry(key) &&
+                    !m_wallet->readPassword(key, password)) {
+                kDebug(5010) << "Password read OK";
+
+                return password;
+            }
+        }
+    }
+    return QString();
+}
+
+void RemoteView::saveWalletPassword(const QString &password, bool fromUserNameOnly)
+{
+    QString key;
+    if (fromUserNameOnly)
+        key = m_url.userName();
+    else
+        key = m_url.prettyUrl(KUrl::RemoveTrailingSlash);
+
+    if (m_wallet && m_wallet->isOpen()) {
+        kDebug(5010) << "Write wallet password";
+        m_wallet->writePassword(key, password);
+    }
+}
+#endif
+
+QCursor RemoteView::localDotCursor() const
+{
+#ifdef QTONLY
+    return QCursor(); //TODO
+#else
+    QBitmap cursorBitmap(KGlobal::dirs()->findResource("appdata",
+                                                       "pics/pointcursor.png"));
+    QBitmap cursorMask(KGlobal::dirs()->findResource("appdata",
+                                                     "pics/pointcursormask.png"));
+    return QCursor(cursorBitmap, cursorMask);
+#endif
+}
+
+void RemoteView::focusInEvent(QFocusEvent *event)
+{
+    if (m_grabAllKeys) {
+        m_keyboardIsGrabbed = true;
+        grabKeyboard();
+    }
+
+    QWidget::focusInEvent(event);
+}
+
+void RemoteView::focusOutEvent(QFocusEvent *event)
+{
+    if (m_grabAllKeys || m_keyboardIsGrabbed) {
+        m_keyboardIsGrabbed = false;
+        releaseKeyboard();
+    }
+
+    QWidget::focusOutEvent(event);
+}
+
+#include "moc_remoteview.cpp"
diff --git a/linux_usr/gui/palacios/vnc_module/remoteview.h b/linux_usr/gui/palacios/vnc_module/remoteview.h
new file mode 100644 (file)
index 0000000..10d22e0
--- /dev/null
@@ -0,0 +1,415 @@
+/****************************************************************************
+**
+** Copyright (C) 2002-2003 Tim Jansen <tim@tjansen.de>
+** Copyright (C) 2007-2008 Urs Wolfer <uwolfer @ kde.org>
+**
+** This file is part of KDE.
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; see the file COPYING. If not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+** Boston, MA 02110-1301, USA.
+**
+****************************************************************************/
+
+#ifndef REMOTEVIEW_H
+#define REMOTEVIEW_H
+
+#ifdef QTONLY
+    #include <QUrl>
+    #define KUrl QUrl
+    #define KRDCCORE_EXPORT
+#else
+    #include <KUrl>
+    #include <KWallet/Wallet>
+    #include <krdc_export.h>
+#endif
+
+#include <QWidget>
+
+class HostPreferences;
+
+/**
+ * Generic widget that displays a remote framebuffer.
+ * Implement this if you want to add another backend.
+ *
+ * Things to take care of:
+ * @li The RemoteView is responsible for its size. In
+ *     non-scaling mode, set the fixed size of the widget
+ *     to the remote resolution. In scaling mode, set the
+ *     maximum size to the remote size and minimum size to the
+ *     smallest resolution that your scaler can handle.
+ * @li if you override mouseMoveEvent()
+ *     you must ignore the QEvent, because the KRDC widget will
+ *     need it for stuff like toolbar auto-hide and bump
+ *     scrolling. If you use x11Event(), make sure that
+ *     MotionNotify events will be forwarded.
+ *
+ */
+class KRDCCORE_EXPORT RemoteView : public QWidget
+{
+    Q_OBJECT
+
+public:
+
+    Q_ENUMS(Quality)
+
+    enum Quality {
+        Unknown,
+        High,
+        Medium,
+        Low
+    };
+
+    /**
+    * Describes the state of a local cursor, if there is such a concept in the backend.
+    * With local cursors, there are two cursors: the cursor on the local machine (client),
+    * and the cursor on the remote machine (server). Because there is usually some lag,
+    * some backends show both cursors simultanously. In the VNC backend the local cursor
+    * is a dot and the remote cursor is the 'real' cursor, usually an arrow.
+    */
+
+    Q_ENUMS(DotCursorState)
+
+    enum DotCursorState {
+        CursorOn,  ///< Always show local cursor (and the remote one).
+        CursorOff, ///< Never show local cursor, only the remote one.
+        /// Try to measure the lag and enable the local cursor if the latency is too high.
+        CursorAuto
+    };
+
+    /**
+    * State of the connection. The state of the connection is returned
+    * by @ref RemoteView::status().
+    *
+    * Not every state transition is allowed. You are only allowed to transition
+    * a state to the following state, with three exceptions:
+    * @li You can move from every state directly to Disconnected
+    * @li You can move from every state except Disconnected to
+    *     Disconnecting
+    * @li You can move from Disconnected to Connecting
+    *
+    * @ref RemoteView::setStatus() will follow this rules for you.
+    * (If you add/remove a state here, you must adapt it)
+    */
+
+    Q_ENUMS(RemoteStatus)
+
+    enum RemoteStatus {
+        Connecting     = 0,
+        Authenticating = 1,
+        Preparing      = 2,
+        Connected      = 3,
+        Disconnecting  = -1,
+        Disconnected   = -2
+    };
+
+    Q_ENUMS(ErrorCode)
+
+    enum ErrorCode {
+        Nonne = 0,
+        Internal,
+        Connection,
+        Protocol,
+        IO,
+        Name,
+        NoServer,
+        ServerBlocked,
+        Authentication
+    };
+
+    virtual ~RemoteView();
+
+    /**
+     * Checks whether the backend supports scaling. The
+     * default implementation returns false.
+     * @return true if scaling is supported
+     * @see scaling()
+     */
+    virtual bool supportsScaling() const;
+
+    /**
+     * Checks whether the widget is in scale mode. The
+     * default implementation always returns false.
+     * @return true if scaling is activated. Must always be
+     *         false if @ref supportsScaling() returns false
+     * @see supportsScaling()
+     */
+    virtual bool scaling() const;
+
+    /**
+     * Checks whether the backend supports the concept of local cursors. The
+     * default implementation returns false.
+     * @return true if local cursors are supported/known
+     * @see DotCursorState
+     * @see showDotCursor()
+     * @see dotCursorState()
+     */
+    virtual bool supportsLocalCursor() const;
+
+    /**
+     * Sets the state of the dot cursor, if supported by the backend.
+     * The default implementation does nothing.
+     * @param state the new state (CursorOn, CursorOff or
+     *        CursorAuto)
+     * @see dotCursorState()
+     * @see supportsLocalCursor()
+     */
+    virtual void showDotCursor(DotCursorState state);
+
+    /**
+     * Returns the state of the local cursor. The default implementation returns
+     * always CursorOff.
+     * @return true if local cursors are supported/known
+     * @see showDotCursor()
+     * @see supportsLocalCursor()
+     */
+    virtual DotCursorState dotCursorState() const;
+
+    /**
+     * Checks whether the view is in view-only mode. This means
+     * that all input is ignored.
+     */
+    virtual bool viewOnly();
+
+    /**
+     * Checks whether grabbing all possible keys is enabled.
+     */
+    virtual bool grabAllKeys();
+
+    /**
+     * Returns the resolution of the remote framebuffer.
+     * It should return a null @ref QSize when the size
+     * is not known.
+     * The backend must also emit a @ref framebufferSizeChanged()
+     * when the size of the framebuffer becomes available
+     * for the first time or the size changed.
+     * @return the remote framebuffer size, a null QSize
+     *         if unknown
+     */
+    virtual QSize framebufferSize();
+
+    /**
+     * Initiate the disconnection. This doesn't need to happen
+     * immediately. The call must not block.
+     * @see isQuitting()
+     */
+    virtual void startQuitting();
+
+    /**
+     * Checks whether the view is currently quitting.
+     * @return true if it is quitting
+     * @see startQuitting()
+     * @see setStatus()
+     */
+    virtual bool isQuitting();
+
+    /**
+     * @return the host the view is connected to
+     */
+    virtual QString host();
+
+    /**
+     * @return the port the view is connected to
+     */
+    virtual int port();
+
+    /**
+     * Initialize the view (for example by showing configuration
+     * dialogs to the user) and start connecting. Should not block
+     * without running the event loop (so displaying a dialog is ok).
+     * When the view starts connecting the application must call
+     * @ref setStatus() with the status Connecting.
+     * @return true if successful (so far), false
+     *         otherwise
+     * @see connected()
+     * @see disconnected()
+     * @see disconnectedError()
+     * @see statusChanged()
+     */
+    virtual bool start() = 0;
+    
+    /**
+     * Called when the configuration is changed.
+     * The default implementation does nothing.
+     */
+    virtual void updateConfiguration();
+    
+    /**
+     * @return screenshot of the view
+     */
+    virtual QPixmap takeScreenshot();
+    
+#ifndef QTONLY
+    /**
+     * Returns the current host preferences of this view.
+     */
+    virtual HostPreferences* hostPreferences() = 0;
+#endif
+    
+    /**
+     * Returns the current status of the connection.
+     * @return the status of the connection
+     * @see setStatus()
+     */
+    RemoteStatus status();
+
+    /**
+     * @return the current url
+     */
+    KUrl url();
+
+public slots:
+    /**
+     * Called to enable or disable scaling.
+     * Ignored if @ref supportsScaling() is false.
+     * The default implementation does nothing.
+     * @param s true to enable, false to disable.
+     * @see supportsScaling()
+     * @see scaling()
+     */
+    virtual void enableScaling(bool scale);
+
+    /**
+     * Enables/disables the view-only mode.
+     * Ignored if @ref supportsScaling() is false.
+     * The default implementation does nothing.
+     * @param viewOnly true to enable, false to disable.
+     * @see supportsScaling()
+     * @see viewOnly()
+     */
+    virtual void setViewOnly(bool viewOnly);
+
+    /**
+     * Enables/disables grabbing all possible keys.
+     * @param grabAllKeys true to enable, false to disable.
+     * Default is false.
+     * @see grabAllKeys()
+     */
+    virtual void setGrabAllKeys(bool grabAllKeys);
+
+    /**
+     * Called to let the backend know it when
+     * we switch from/to fullscreen.
+     * @param on true when switching to fullscreen,
+     *           false when switching from fullscreen.
+     */
+    virtual void switchFullscreen(bool on);
+
+    /**
+     * Sends a QKeyEvent to the remote server.
+     * @param event the key to send
+     */
+    virtual void keyEvent(QKeyEvent *event);
+
+    /**
+     * Called when the visible place changed so remote
+     * view can resize itself.
+     */
+    virtual void scaleResize(int w, int h);
+
+signals:
+    /**
+     * Emitted when the size of the remote screen changes. Also
+     * called when the size is known for the first time.
+     * @param x the width of the screen
+     * @param y the height of the screen
+     */
+    void framebufferSizeChanged(int w, int h);
+
+    /**
+     * Emitted when the view connected successfully.
+     */
+    void connected();
+
+    /**
+     * Emitted when the view disconnected without error.
+     */
+    void disconnected();
+
+    /**
+     * Emitted when the view disconnected with error.
+     */
+    void disconnectedError();
+
+    /**
+     * Emitted when the view has a specific error.
+     */
+    void errorMessage(const QString &title, const QString &message);
+    /**
+     * Emitted when the status of the view changed.
+     * @param s the new status
+        */
+    void statusChanged(RemoteView::RemoteStatus s);
+
+    /**
+     * Emitted when the password dialog is shown or hidden.
+     * @param b true when the dialog is shown, false when it has been hidden
+     */
+    void showingPasswordDialog(bool b);
+
+    /**
+     * Emitted when the mouse on the remote side has been moved.
+     * @param x the new x coordinate
+     * @param y the new y coordinate
+     * @param buttonMask the mask of mouse buttons (bit 0 for first mouse
+     *                   button, 1 for second button etc)a
+     */
+    void mouseStateChanged(int x, int y, int buttonMask);
+
+protected:
+    RemoteView(QWidget *parent = 0);
+
+    void focusInEvent(QFocusEvent *event);
+    void focusOutEvent(QFocusEvent *event);
+
+    /**
+     * The status of the remote view.
+     */
+    RemoteStatus m_status;
+
+    /**
+     * Set the status of the connection.
+     * Emits a statusChanged() signal.
+     * Note that the states need to be set in a certain order,
+     * see @ref Status. setStatus() will try to do this
+     * transition automatically, so if you are in Connecting
+     * and call setStatus(Preparing), setStatus() will
+     * emit a Authenticating and then Preparing.
+     * If you transition backwards, it will emit a
+     * Disconnected before doing the transition.
+     * @param s the new status
+     */
+    virtual void setStatus(RemoteStatus s);
+
+    QCursor localDotCursor() const;
+
+    QString m_host;
+    int m_port;
+    bool m_viewOnly;
+    bool m_grabAllKeys;
+    bool m_scale;
+    bool m_keyboardIsGrabbed;
+    KUrl m_url;
+
+#ifndef QTONLY
+    QString readWalletPassword(bool fromUserNameOnly = false);
+    void saveWalletPassword(const QString &password, bool fromUserNameOnly = false);
+    KWallet::Wallet *m_wallet;
+#endif
+
+    DotCursorState m_dotCursorState;
+};
+
+#endif
diff --git a/linux_usr/gui/palacios/vnc_module/vncclientthread.cpp b/linux_usr/gui/palacios/vnc_module/vncclientthread.cpp
new file mode 100644 (file)
index 0000000..bb43b90
--- /dev/null
@@ -0,0 +1,454 @@
+/****************************************************************************
+**
+** Copyright (C) 2007-2008 Urs Wolfer <uwolfer @ kde.org>
+**
+** This file is part of KDE.
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; see the file COPYING. If not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+** Boston, MA 02110-1301, USA.
+**
+****************************************************************************/
+
+#include "vncclientthread.h"
+
+#include <QMutexLocker>
+#include <QTimer>
+
+//for detecting intel AMT KVM vnc server
+static const QString INTEL_AMT_KVM_STRING= "Intel(r) AMT KVM";
+static QString outputErrorMessageString;
+
+QVector<QRgb> VncClientThread::m_colorTable;
+
+void VncClientThread::setClientColorDepth(rfbClient* cl, VncClientThread::ColorDepth cd)
+{
+    switch(cd) {
+    case bpp8:
+        if (m_colorTable.isEmpty()) {
+            m_colorTable.resize(256);
+            int r,g,b;
+            for (int i = 0; i < 256; ++i) {
+                //pick out the red (3 bits), green (3 bits) and blue (2 bits) bits and make them maximum significant in 8bits
+                //this gives a colortable for 8bit true colors
+                r= (i & 0x07) << 5;
+                g= (i & 0x38) << 2;
+                b= i & 0xc0;
+                m_colorTable[i] = qRgb(r, g, b);
+            }
+        }
+        cl->format.depth = 8;
+        cl->format.bitsPerPixel = 8;
+        cl->format.redShift = 0;
+        cl->format.greenShift = 3;
+        cl->format.blueShift = 6;
+        cl->format.redMax = 7;
+        cl->format.greenMax = 7;
+        cl->format.blueMax = 3;
+        break;
+    case bpp16:
+        cl->format.depth = 16;
+        cl->format.bitsPerPixel = 16;
+        cl->format.redShift = 11;
+        cl->format.greenShift = 5;
+        cl->format.blueShift = 0;
+        cl->format.redMax = 0x1f;
+        cl->format.greenMax = 0x3f;
+        cl->format.blueMax = 0x1f;
+        break;
+    case bpp32:
+    default:
+        cl->format.depth = 24;
+        cl->format.bitsPerPixel = 32;
+        cl->format.redShift = 16;
+        cl->format.greenShift = 8;
+        cl->format.blueShift = 0;
+        cl->format.redMax = 0xff;
+        cl->format.greenMax = 0xff;
+        cl->format.blueMax = 0xff;
+    }
+}
+
+rfbBool VncClientThread::newclient(rfbClient *cl)
+{
+    VncClientThread *t = (VncClientThread*)rfbClientGetClientData(cl, 0);
+    Q_ASSERT(t);
+
+    //8bit color hack for Intel(r) AMT KVM "classic vnc" = vnc server built in in Intel Vpro chipsets.
+    if (INTEL_AMT_KVM_STRING == cl->desktopName) {
+        kDebug(5011) << "Intel(R) AMT KVM: switching to 8 bit color depth (workaround, recent libvncserver needed)";
+        t->setColorDepth(bpp8);
+    }
+    setClientColorDepth(cl, t->colorDepth());
+
+    const int width = cl->width, height = cl->height, depth = cl->format.bitsPerPixel;
+    const int size = width * height * (depth / 8);
+    if (t->frameBuffer)
+        delete [] t->frameBuffer; // do not leak if we get a new framebuffer size
+    t->frameBuffer = new uint8_t[size];
+    cl->frameBuffer = t->frameBuffer;
+    memset(cl->frameBuffer, '\0', size);
+
+    switch (t->quality()) {
+    case RemoteView::High:
+        cl->appData.encodingsString = "copyrect zlib hextile raw";
+        cl->appData.compressLevel = 0;
+        cl->appData.qualityLevel = 9;
+        break;
+    case RemoteView::Medium:
+        cl->appData.encodingsString = "copyrect tight zrle ultra zlib hextile corre rre raw";
+        cl->appData.compressLevel = 5;
+        cl->appData.qualityLevel = 7;
+        break;
+    case RemoteView::Low:
+    case RemoteView::Unknown:
+    default:
+        cl->appData.encodingsString = "copyrect tight zrle ultra zlib hextile corre rre raw";
+        cl->appData.compressLevel = 9;
+        cl->appData.qualityLevel = 1;
+    }
+
+    SetFormatAndEncodings(cl);
+    kDebug(5011) << "Client created";
+    return true;
+}
+
+void VncClientThread::updatefb(rfbClient* cl, int x, int y, int w, int h)
+{
+//     kDebug(5011) << "updated client: x: " << x << ", y: " << y << ", w: " << w << ", h: " << h;
+    VncClientThread *t = (VncClientThread*)rfbClientGetClientData(cl, 0);
+    Q_ASSERT(t);
+
+    const int width = cl->width, height = cl->height;
+    QImage img;
+    switch(t->colorDepth()) {
+    case bpp8:
+        img = QImage(cl->frameBuffer, width, height, QImage::Format_Indexed8);
+        img.setColorTable(m_colorTable);
+        break;
+    case bpp16:
+        img = QImage(cl->frameBuffer, width, height, QImage::Format_RGB16);
+        break;
+    case bpp32:
+        img = QImage(cl->frameBuffer, width, height, QImage::Format_RGB32);
+        break;
+    }
+
+    if (img.isNull()) {
+        kDebug(5011) << "image not loaded";
+    }
+
+    t->setImage(img);
+
+    t->emitUpdated(x, y, w, h);
+}
+
+void VncClientThread::cuttext(rfbClient* cl, const char *text, int textlen)
+{
+    const QString cutText = QString::fromUtf8(text, textlen);
+    kDebug(5011) << cutText;
+
+    if (!cutText.isEmpty()) {
+        VncClientThread *t = (VncClientThread*)rfbClientGetClientData(cl, 0);
+        Q_ASSERT(t);
+
+        t->emitGotCut(cutText);
+    }
+}
+
+char *VncClientThread::passwdHandler(rfbClient *cl)
+{
+    kDebug(5011) << "password request" << kBacktrace();
+
+    VncClientThread *t = (VncClientThread*)rfbClientGetClientData(cl, 0);
+    Q_ASSERT(t);
+
+    t->passwordRequest();
+    t->m_passwordError = true;
+
+    return strdup(t->password().toLocal8Bit());
+}
+
+void VncClientThread::outputHandler(const char *format, ...)
+{
+    va_list args;
+    va_start(args, format);
+
+    QString message;
+    message.vsprintf(format, args);
+
+    va_end(args);
+
+    message = message.trimmed();
+
+    kDebug(5011) << message;
+
+    if ((message.contains("Couldn't convert ")) ||
+            (message.contains("Unable to connect to VNC server")))
+        outputErrorMessageString = i18n("Server not found.");
+
+    if ((message.contains("VNC connection failed: Authentication failed, too many tries")) ||
+            (message.contains("VNC connection failed: Too many authentication failures")))
+        outputErrorMessageString = i18n("VNC authentication failed because of too many authentication tries.");
+
+    if (message.contains("VNC connection failed: Authentication failed"))
+        outputErrorMessageString = i18n("VNC authentication failed.");
+
+    if (message.contains("VNC server closed connection"))
+        outputErrorMessageString = i18n("VNC server closed connection.");
+
+    // internal messages, not displayed to user
+    if (message.contains("VNC server supports protocol version 3.889")) // see http://bugs.kde.org/162640
+        outputErrorMessageString = "INTERNAL:APPLE_VNC_COMPATIBILTY";
+}
+
+VncClientThread::VncClientThread(QObject *parent)
+        : QThread(parent)
+        , frameBuffer(0)
+        , cl(0)
+        , m_stopped(false)
+{
+    QMutexLocker locker(&mutex);
+
+    QTimer *outputErrorMessagesCheckTimer = new QTimer(this);
+    outputErrorMessagesCheckTimer->setInterval(500);
+    connect(outputErrorMessagesCheckTimer, SIGNAL(timeout()), this, SLOT(checkOutputErrorMessage()));
+    outputErrorMessagesCheckTimer->start();
+}
+
+VncClientThread::~VncClientThread()
+{
+    if(isRunning()) {
+        stop();
+        terminate();
+        const bool quitSuccess = wait(1000);
+        kDebug(5011) << "Attempting to stop in deconstructor, will crash if this fails:" << quitSuccess;
+    }
+
+    if (cl) {
+        // Disconnect from vnc server & cleanup allocated resources
+        rfbClientCleanup(cl);
+    }
+
+    delete [] frameBuffer;
+}
+
+void VncClientThread::checkOutputErrorMessage()
+{
+    if (!outputErrorMessageString.isEmpty()) {
+        kDebug(5011) << outputErrorMessageString;
+        QString errorMessage = outputErrorMessageString;
+        outputErrorMessageString.clear();
+        // show authentication failure error only after the 3rd unsuccessful try
+        if ((errorMessage != i18n("VNC authentication failed.")) || m_passwordError)
+            outputErrorMessage(errorMessage);
+    }
+}
+
+void VncClientThread::setHost(const QString &host)
+{
+    QMutexLocker locker(&mutex);
+    m_host = host;
+}
+
+void VncClientThread::setPort(int port)
+{
+    QMutexLocker locker(&mutex);
+    m_port = port;
+}
+
+void VncClientThread::setQuality(RemoteView::Quality quality)
+{
+    m_quality = quality;
+    //set color depth dependent on quality
+    switch(quality) {
+    case RemoteView::Low:
+        setColorDepth(bpp8);
+        break;
+    case RemoteView::High:
+        setColorDepth(bpp32);
+        break;
+    case RemoteView::Medium:
+    default:
+        setColorDepth(bpp16);
+    }
+}
+
+void VncClientThread::setColorDepth(ColorDepth colorDepth)
+{
+    m_colorDepth= colorDepth;
+}
+
+RemoteView::Quality VncClientThread::quality() const
+{
+    return m_quality;
+}
+
+VncClientThread::ColorDepth VncClientThread::colorDepth() const
+{
+    return m_colorDepth;
+}
+
+void VncClientThread::setImage(const QImage &img)
+{
+    QMutexLocker locker(&mutex);
+    m_image = img;
+}
+
+const QImage VncClientThread::image(int x, int y, int w, int h)
+{
+    QMutexLocker locker(&mutex);
+
+    if (w == 0) // full image requested
+        return m_image;
+    else
+        return m_image.copy(x, y, w, h);
+}
+
+void VncClientThread::emitUpdated(int x, int y, int w, int h)
+{
+    emit imageUpdated(x, y, w, h);
+}
+
+void VncClientThread::emitGotCut(const QString &text)
+{
+    emit gotCut(text);
+}
+
+void VncClientThread::stop()
+{
+    QMutexLocker locker(&mutex);
+    m_stopped = true;
+}
+
+void VncClientThread::run()
+{
+    QMutexLocker locker(&mutex);
+
+    while (!m_stopped) { // try to connect as long as the server allows
+        locker.relock();
+        m_passwordError = false;
+        locker.unlock();
+
+        rfbClientLog = outputHandler;
+        rfbClientErr = outputHandler;
+        //24bit color dept in 32 bits per pixel = default. Will change colordepth and bpp later if needed
+        cl = rfbGetClient(8, 3, 4);
+        setClientColorDepth(cl, this->colorDepth());
+        cl->MallocFrameBuffer = newclient;
+        cl->canHandleNewFBSize = true;
+        cl->GetPassword = passwdHandler;
+        cl->GotFrameBufferUpdate = updatefb;
+        cl->GotXCutText = cuttext;
+        rfbClientSetClientData(cl, 0, this);
+
+        locker.relock();
+        cl->serverHost = strdup(m_host.toUtf8().constData());
+
+        if (m_port < 0 || !m_port) // port is invalid or empty...
+            m_port = 5900; // fallback: try an often used VNC port
+
+        if (m_port >= 0 && m_port < 100) // the user most likely used the short form (e.g. :1)
+            m_port += 5900;
+        cl->serverPort = m_port;
+        locker.unlock();
+
+        kDebug(5011) << "--------------------- trying init ---------------------";
+
+        if (rfbInitClient(cl, 0, 0))
+            break;
+        else
+            cl = 0;
+
+        locker.relock();
+        if (m_passwordError)
+            continue;
+
+        return;
+    }
+
+    locker.relock();
+    kDebug(5011) << "--------------------- Starting main VNC event loop ---------------------";
+    while (!m_stopped) {
+        locker.unlock();
+        const int i = WaitForMessage(cl, 500);
+        if (i < 0) {
+            break;
+        }
+        if (i) {
+            if (!HandleRFBServerMessage(cl)) {
+                break;
+            }
+        }
+
+        locker.relock();
+        while (!m_eventQueue.isEmpty()) {
+            ClientEvent* clientEvent = m_eventQueue.dequeue();
+            locker.unlock();
+            clientEvent->fire(cl);
+            delete clientEvent;
+            locker.relock();
+        }
+    }
+
+    m_stopped = true;
+}
+
+ClientEvent::~ClientEvent()
+{
+}
+
+void PointerClientEvent::fire(rfbClient* cl)
+{
+    SendPointerEvent(cl, m_x, m_y, m_buttonMask);
+}
+
+void KeyClientEvent::fire(rfbClient* cl)
+{
+    SendKeyEvent(cl, m_key, m_pressed);
+}
+
+void ClientCutEvent::fire(rfbClient* cl)
+{
+    SendClientCutText(cl, text.toUtf8().data(), text.size());
+}
+
+void VncClientThread::mouseEvent(int x, int y, int buttonMask)
+{
+    QMutexLocker lock(&mutex);
+    if (m_stopped)
+        return;
+
+    m_eventQueue.enqueue(new PointerClientEvent(x, y, buttonMask));
+}
+
+void VncClientThread::keyEvent(int key, bool pressed)
+{
+    QMutexLocker lock(&mutex);
+    if (m_stopped)
+        return;
+
+    m_eventQueue.enqueue(new KeyClientEvent(key, pressed));
+}
+
+void VncClientThread::clientCut(const QString &text)
+{
+    QMutexLocker lock(&mutex);
+    if (m_stopped)
+        return;
+
+    m_eventQueue.enqueue(new ClientCutEvent(text));
+}
+
+#include "moc_vncclientthread.cpp"
diff --git a/linux_usr/gui/palacios/vnc_module/vncclientthread.h b/linux_usr/gui/palacios/vnc_module/vncclientthread.h
new file mode 100644 (file)
index 0000000..0c7c172
--- /dev/null
@@ -0,0 +1,172 @@
+/****************************************************************************
+**
+** Copyright (C) 2007-2008 Urs Wolfer <uwolfer @ kde.org>
+**
+** This file is part of KDE.
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; see the file COPYING. If not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+** Boston, MA 02110-1301, USA.
+**
+****************************************************************************/
+
+#ifndef VNCCLIENTTHREAD_H
+#define VNCCLIENTTHREAD_H
+
+#ifdef QTONLY
+    #include <QDebug>
+    #define kDebug(n) qDebug()
+    #define kBacktrace() ""
+    #define i18n tr
+#else
+    #include <KDebug>
+    #include <KLocale>
+#endif
+
+#include "remoteview.h"
+
+#include <QQueue>
+#include <QThread>
+#include <QImage>
+#include <QMutex>
+
+extern "C" {
+#include <rfb/rfbclient.h>
+}
+
+class ClientEvent
+{
+public:
+    virtual ~ClientEvent();
+
+    virtual void fire(rfbClient*) = 0;
+};
+
+class KeyClientEvent : public ClientEvent
+{
+public:
+    KeyClientEvent(int key, int pressed)
+            : m_key(key), m_pressed(pressed) {}
+
+    void fire(rfbClient*);
+
+private:
+    int m_key;
+    int m_pressed;
+};
+
+class PointerClientEvent : public ClientEvent
+{
+public:
+    PointerClientEvent(int x, int y, int buttonMask)
+            : m_x(x), m_y(y), m_buttonMask(buttonMask) {}
+
+    void fire(rfbClient*);
+
+private:
+    int m_x;
+    int m_y;
+    int m_buttonMask;
+};
+
+class ClientCutEvent : public ClientEvent
+{
+public:
+    ClientCutEvent(const QString &text)
+            : text(text) {}
+
+    void fire(rfbClient*);
+
+private:
+    QString text;
+};
+
+class VncClientThread: public QThread
+{
+    Q_OBJECT
+
+public:
+    Q_ENUMS(ColorDepth)
+
+    enum ColorDepth {
+        bpp32,
+        bpp16,
+        bpp8
+    };
+
+    explicit VncClientThread(QObject *parent = 0);
+    ~VncClientThread();
+    const QImage image(int x = 0, int y = 0, int w = 0, int h = 0);
+    void setImage(const QImage &img);
+    void emitUpdated(int x, int y, int w, int h);
+    void emitGotCut(const QString &text);
+    void stop();
+    void setHost(const QString &host);
+    void setPort(int port);
+    void setQuality(RemoteView::Quality quality);
+    void setPassword(const QString &password) {
+        m_password = password;
+    }
+    const QString password() const {
+        return m_password;
+    }
+
+    RemoteView::Quality quality() const;
+    ColorDepth colorDepth() const;
+    uint8_t *frameBuffer;
+
+signals:
+    void imageUpdated(int x, int y, int w, int h);
+    void gotCut(const QString &text);
+    void passwordRequest();
+    void outputErrorMessage(const QString &message);
+
+public slots:
+    void mouseEvent(int x, int y, int buttonMask);
+    void keyEvent(int key, bool pressed);
+    void clientCut(const QString &text);
+
+protected:
+    void run();
+
+private:
+    static void setClientColorDepth(rfbClient *cl, ColorDepth cd);
+    void setColorDepth(ColorDepth colorDepth);
+    //these static methods are callback functions for libvncclient
+    static rfbBool newclient(rfbClient *cl);
+    static void updatefb(rfbClient *cl, int x, int y, int w, int h);
+    static void cuttext(rfbClient *cl, const char *text, int textlen);
+    static char* passwdHandler(rfbClient *cl);
+    static void outputHandler(const char *format, ...);
+
+    QImage m_image;
+    rfbClient *cl;
+    QString m_host;
+    QString m_password;
+    int m_port;
+    QMutex mutex;
+    RemoteView::Quality m_quality;
+    ColorDepth m_colorDepth;
+    QQueue<ClientEvent* > m_eventQueue;
+    //color table for 8bit indexed colors
+    static QVector<QRgb> m_colorTable;
+
+    volatile bool m_stopped;
+    volatile bool m_passwordError;
+
+private slots:
+    void checkOutputErrorMessage();
+};
+
+#endif
diff --git a/linux_usr/gui/palacios/vnc_module/vncview.cpp b/linux_usr/gui/palacios/vnc_module/vncview.cpp
new file mode 100644 (file)
index 0000000..223359b
--- /dev/null
@@ -0,0 +1,597 @@
+/****************************************************************************
+**
+** Copyright (C) 2007-2012 Urs Wolfer <uwolfer @ kde.org>
+**
+** This file is part of KDE.
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; see the file COPYING. If not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+** Boston, MA 02110-1301, USA.
+**
+****************************************************************************/
+
+#include "vncview.h"
+
+#ifdef QTONLY
+    #include <QMessageBox>
+    #include <QInputDialog>
+    #define KMessageBox QMessageBox
+    /*#define error(parent, message, caption) \
+        critical(parent, caption, message)*/
+#else
+    #include "settings.h"
+    #include <KActionCollection>
+    #include <KMainWindow>
+    #include <KMessageBox>
+    #include <KPasswordDialog>
+    #include <KXMLGUIClient>
+#endif
+
+#include <QApplication>
+#include <QImage>
+#include <QPainter>
+#include <QMouseEvent>
+
+// Definition of key modifier mask constants
+#define KMOD_Alt_R     0x01
+#define KMOD_Alt_L     0x02
+#define KMOD_Meta_L    0x04
+#define KMOD_Control_L         0x08
+#define KMOD_Shift_L   0x10
+
+VncView::VncView(QWidget *parent, const KUrl &url, KConfigGroup configGroup)
+        : RemoteView(parent),
+        m_initDone(false),
+        m_buttonMask(0),
+        m_repaint(false),
+        m_quitFlag(false),
+        m_firstPasswordTry(true),
+        m_dontSendClipboard(false),
+        m_horizontalFactor(1.0),
+        m_verticalFactor(1.0),
+        m_forceLocalCursor(false)
+{
+    m_url = url;
+    m_host = url.host();
+    m_port = url.port();
+
+    connect(&vncThread, SIGNAL(imageUpdated(int,int,int,int)), this, SLOT(updateImage(int,int,int,int)), Qt::BlockingQueuedConnection);
+    connect(&vncThread, SIGNAL(gotCut(QString)), this, SLOT(setCut(QString)), Qt::BlockingQueuedConnection);
+    connect(&vncThread, SIGNAL(passwordRequest()), this, SLOT(requestPassword()), Qt::BlockingQueuedConnection);
+    connect(&vncThread, SIGNAL(outputErrorMessage(QString)), this, SLOT(outputErrorMessage(QString)));
+
+    m_clipboard = QApplication::clipboard();
+    connect(m_clipboard, SIGNAL(dataChanged()), this, SLOT(clipboardDataChanged()));
+    
+#ifndef QTONLY
+    m_hostPreferences = new VncHostPreferences(configGroup, this);
+#else
+    Q_UNUSED(configGroup);
+#endif
+}
+
+VncView::~VncView()
+{   
+    startQuitting();
+}
+
+bool VncView::eventFilter(QObject *obj, QEvent *event)
+{
+    if (m_viewOnly) {
+        if (event->type() == QEvent::KeyPress ||
+                event->type() == QEvent::KeyRelease ||
+                event->type() == QEvent::MouseButtonDblClick ||
+                event->type() == QEvent::MouseButtonPress ||
+                event->type() == QEvent::MouseButtonRelease ||
+                event->type() == QEvent::Wheel ||
+                event->type() == QEvent::MouseMove)
+            return true;
+    }
+
+    return RemoteView::eventFilter(obj, event);
+}
+
+QSize VncView::framebufferSize()
+{
+    return m_frame.size();
+}
+
+QSize VncView::sizeHint() const
+{
+    return size();
+}
+
+QSize VncView::minimumSizeHint() const
+{
+    return size();
+}
+
+void VncView::scaleResize(int w, int h)
+{
+    RemoteView::scaleResize(w, h);
+    
+    kDebug(5011) << w << h;
+    if (m_scale) {
+        m_verticalFactor = (qreal) h / m_frame.height();
+        m_horizontalFactor = (qreal) w / m_frame.width();
+
+#ifndef QTONLY
+        if (Settings::keepAspectRatio()) {
+            m_verticalFactor = m_horizontalFactor = qMin(m_verticalFactor, m_horizontalFactor);
+        }
+#else
+        m_verticalFactor = m_horizontalFactor = qMin(m_verticalFactor, m_horizontalFactor);
+#endif
+
+        const qreal newW = m_frame.width() * m_horizontalFactor;
+        const qreal newH = m_frame.height() * m_verticalFactor;
+        setMaximumSize(newW, newH); //This is a hack to force Qt to center the view in the scroll area
+        resize(newW, newH);
+    } 
+}
+
+void VncView::updateConfiguration()
+{
+    RemoteView::updateConfiguration();
+
+    // Update the scaling mode in case KeepAspectRatio changed
+    scaleResize(parentWidget()->width(), parentWidget()->height());
+}
+
+void VncView::startQuitting()
+{
+    kDebug(5011) << "about to quit";
+
+    setStatus(Disconnecting);
+
+    m_quitFlag = true;
+
+    vncThread.stop();
+
+    unpressModifiers();
+
+    // Disconnect all signals so that we don't get any more callbacks from the client thread
+    bool imageUpdatedDisconnect = disconnect(&vncThread, SIGNAL(imageUpdated(int,int,int,int)), this, SLOT(updateImage(int,int,int,int)));
+    bool gotCutDisconnect = disconnect(&vncThread, SIGNAL(gotCut(QString)), this, SLOT(setCut(QString)));
+    bool passwordRequestDisconnect = disconnect(&vncThread, SIGNAL(passwordRequest()), this, SLOT(requestPassword()));
+    bool outputErrorMessageDisconnect = disconnect(&vncThread, SIGNAL(outputErrorMessage(QString)), this, SLOT(outputErrorMessage(QString)));
+
+    kDebug(5011) << "Signals disconnected: imageUpdated: " << imageUpdatedDisconnect << "gotCut: " << gotCutDisconnect << "passwordRequest: " << passwordRequestDisconnect << "outputErrorMessage: " << outputErrorMessageDisconnect;
+
+    vncThread.quit();
+
+    const bool quitSuccess = vncThread.wait(1000);
+
+    kDebug(5011) << "Quit VNC thread success:" << quitSuccess;
+
+    setStatus(Disconnected);
+}
+
+bool VncView::isQuitting()
+{
+    return m_quitFlag;
+}
+
+bool VncView::start()
+{
+    vncThread.setHost(m_host);
+    vncThread.setPort(m_port);
+    RemoteView::Quality quality;
+#ifdef QTONLY
+    quality = (RemoteView::Quality)((QCoreApplication::arguments().count() > 2) ?
+        QCoreApplication::arguments().at(2).toInt() : 2);
+#else
+    quality = m_hostPreferences->quality();
+#endif
+
+    vncThread.setQuality(quality);
+
+    kDebug(5011) << "Host: " << m_host;
+    kDebug(5011) << "Port: " << m_port;
+    kDebug(5011) << "Quality: " << quality;
+
+    // set local cursor on by default because low quality mostly means slow internet connection
+    if (quality == RemoteView::Low) {
+        showDotCursor(RemoteView::CursorOn);
+#ifndef QTONLY
+        // KRDC does always just have one main window, so at(0) is safe
+        KXMLGUIClient *mainWindow = dynamic_cast<KXMLGUIClient*>(KMainWindow::memberList().at(0));
+        if (mainWindow)
+            mainWindow->actionCollection()->action("show_local_cursor")->setChecked(true);
+#endif
+    }
+
+    setStatus(Connecting);
+
+    vncThread.start();
+    return true;
+}
+
+bool VncView::supportsScaling() const
+{
+    return true;
+}
+
+bool VncView::supportsLocalCursor() const
+{
+    return true;
+}
+
+void VncView::requestPassword()
+{
+    kDebug(5011) << "request password";
+
+    setStatus(Authenticating);
+    
+    kDebug(5011) << "After setting authentication state";
+/*#ifndef QTONLY
+    // just try to get the passwort from the wallet the first time, otherwise it will loop (see issue #226283)
+    if (m_firstPasswordTry && m_hostPreferences->walletSupport()) {
+        QString walletPassword = readWalletPassword();
+
+        if (!walletPassword.isNull()) {
+            vncThread.setPassword(walletPassword);
+            m_firstPasswordTry = false;
+            return;
+        }
+    }
+#endif
+
+    if (m_firstPasswordTry && !m_url.password().isNull()) {
+        vncThread.setPassword(m_url.password());
+        m_firstPasswordTry = false;
+        return;
+    }*/
+
+#ifdef QTONLY
+    bool ok = true;
+    QString password = QInputDialog::getText(this, //krazy:exclude=qclasses
+                                             tr("Password required"),
+                                             tr("Please enter the password for the remote desktop:"),
+                                             QLineEdit::Password, QString(), &ok);
+    m_firstPasswordTry = false;
+    if (ok)
+        vncThread.setPassword(password);
+    else
+        startQuitting();
+#else
+    KPasswordDialog dialog(this);
+    dialog.setPrompt(m_firstPasswordTry ? i18n("Access to the system requires a password.")
+                                        : i18n("Authentication failed. Please try again."));
+    if (dialog.exec() == KPasswordDialog::Accepted) {
+        m_firstPasswordTry = false;
+        vncThread.setPassword(dialog.password());
+    } else {
+        kDebug(5011) << "password dialog not accepted";
+        startQuitting();
+    }
+#endif
+}
+
+void VncView::outputErrorMessage(const QString &message)
+{
+    kDebug(5011) << message;
+
+    if (message == "INTERNAL:APPLE_VNC_COMPATIBILTY") {
+        setCursor(localDotCursor());
+        m_forceLocalCursor = true;
+        return;
+    }
+
+    startQuitting();
+
+#ifndef QTONLY
+    KMessageBox::error(this, message, i18n("VNC failure"));
+#endif
+    emit errorMessage(i18n("VNC failure"), message);
+}
+
+#ifndef QTONLY
+HostPreferences* VncView::hostPreferences()
+{
+    return m_hostPreferences;
+}
+#endif
+
+void VncView::updateImage(int x, int y, int w, int h)
+{
+//     kDebug(5011) << "got update" << width() << height();
+
+    m_x = x;
+    m_y = y;
+    m_w = w;
+    m_h = h;
+
+    if (m_horizontalFactor != 1.0 || m_verticalFactor != 1.0) {
+        // If the view is scaled, grow the update rectangle to avoid artifacts
+        m_x-=1;
+        m_y-=1;
+        m_w+=2;
+        m_h+=2;
+    }
+
+    m_frame = vncThread.image();
+
+    if (!m_initDone) {
+        setAttribute(Qt::WA_StaticContents);
+        setAttribute(Qt::WA_OpaquePaintEvent);
+        installEventFilter(this);
+
+        setCursor(((m_dotCursorState == CursorOn) || m_forceLocalCursor) ? localDotCursor() : Qt::BlankCursor);
+
+        setMouseTracking(true); // get mouse events even when there is no mousebutton pressed
+        setFocusPolicy(Qt::WheelFocus);
+        setStatus(Connected);
+        emit connected();
+        
+        if (m_scale) {
+#ifndef QTONLY
+            kDebug(5011) << "Setting initial size w:" <<m_hostPreferences->width() << " h:" << m_hostPreferences->height();
+            emit framebufferSizeChanged(m_hostPreferences->width(), m_hostPreferences->height());
+            scaleResize(m_hostPreferences->width(), m_hostPreferences->height());
+            kDebug() << "m_frame.size():" << m_frame.size() << "size()" << size();
+#else
+//TODO: qtonly alternative
+#endif
+        }
+
+        m_initDone = true;
+
+#ifndef QTONLY
+        if (m_hostPreferences->walletSupport()) {
+            saveWalletPassword(vncThread.password());
+        }
+#endif
+    }
+
+    if ((y == 0 && x == 0) && (m_frame.size() != size())) {
+        kDebug(5011) << "Updating framebuffer size";
+        if (m_scale) {
+            setMaximumSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
+            if (parentWidget())
+                scaleResize(parentWidget()->width(), parentWidget()->height());
+        } else {
+            kDebug(5011) << "Resizing: " << m_frame.width() << m_frame.height();
+            resize(m_frame.width(), m_frame.height());
+            setMaximumSize(m_frame.width(), m_frame.height()); //This is a hack to force Qt to center the view in the scroll area
+            setMinimumSize(m_frame.width(), m_frame.height());
+            emit framebufferSizeChanged(m_frame.width(), m_frame.height());
+        }
+    }
+
+    m_repaint = true;
+    repaint(qRound(m_x * m_horizontalFactor), qRound(m_y * m_verticalFactor), qRound(m_w * m_horizontalFactor), qRound(m_h * m_verticalFactor));
+    m_repaint = false;
+}
+
+void VncView::setViewOnly(bool viewOnly)
+{
+    RemoteView::setViewOnly(viewOnly);
+
+    m_dontSendClipboard = viewOnly;
+
+    if (viewOnly)
+        setCursor(Qt::ArrowCursor);
+    else
+        setCursor(m_dotCursorState == CursorOn ? localDotCursor() : Qt::BlankCursor);
+}
+
+void VncView::showDotCursor(DotCursorState state)
+{
+    RemoteView::showDotCursor(state);
+
+    setCursor(state == CursorOn ? localDotCursor() : Qt::BlankCursor);
+}
+
+void VncView::enableScaling(bool scale)
+{
+    RemoteView::enableScaling(scale);
+
+    if (scale) {
+        setMaximumSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
+        setMinimumSize(1, 1);
+        if (parentWidget())
+            scaleResize(parentWidget()->width(), parentWidget()->height());
+    } else {
+        m_verticalFactor = 1.0;
+        m_horizontalFactor = 1.0;
+
+        setMaximumSize(m_frame.width(), m_frame.height()); //This is a hack to force Qt to center the view in the scroll area
+        setMinimumSize(m_frame.width(), m_frame.height());
+        resize(m_frame.width(), m_frame.height());
+    }
+}
+
+void VncView::setCut(const QString &text)
+{
+    m_dontSendClipboard = true;
+    m_clipboard->setText(text, QClipboard::Clipboard);
+    m_dontSendClipboard = false;
+}
+
+void VncView::paintEvent(QPaintEvent *event)
+{
+//     kDebug(5011) << "paint event: x: " << m_x << ", y: " << m_y << ", w: " << m_w << ", h: " << m_h;
+    if (m_frame.isNull() || m_frame.format() == QImage::Format_Invalid) {
+        kDebug(5011) << "no valid image to paint";
+        RemoteView::paintEvent(event);
+        return;
+    }
+
+    event->accept();
+
+    QPainter painter(this);
+
+    if (m_repaint) {
+//         kDebug(5011) << "normal repaint";
+        painter.drawImage(QRect(qRound(m_x*m_horizontalFactor), qRound(m_y*m_verticalFactor),
+                                qRound(m_w*m_horizontalFactor), qRound(m_h*m_verticalFactor)), 
+                          m_frame.copy(m_x, m_y, m_w, m_h).scaled(qRound(m_w*m_horizontalFactor), 
+                                                                  qRound(m_h*m_verticalFactor),
+                                                                  Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
+    } else {
+//         kDebug(5011) << "resize repaint";
+        QRect rect = event->rect();
+        if (rect.width() != width() || rect.height() != height()) {
+//             kDebug(5011) << "Partial repaint";
+            const int sx = rect.x()/m_horizontalFactor;
+            const int sy = rect.y()/m_verticalFactor;
+            const int sw = rect.width()/m_horizontalFactor;
+            const int sh = rect.height()/m_verticalFactor;
+            painter.drawImage(rect, 
+                              m_frame.copy(sx, sy, sw, sh).scaled(rect.width(), rect.height(),
+                                                                  Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
+        } else {
+//             kDebug(5011) << "Full repaint" << width() << height() << m_frame.width() << m_frame.height();
+            painter.drawImage(QRect(0, 0, width(), height()), 
+                              m_frame.scaled(m_frame.width() * m_horizontalFactor, m_frame.height() * m_verticalFactor,
+                                             Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
+        }
+    }
+
+    RemoteView::paintEvent(event);
+}
+
+void VncView::resizeEvent(QResizeEvent *event)
+{
+    RemoteView::resizeEvent(event);
+    update();
+}
+
+bool VncView::event(QEvent *event)
+{
+    switch (event->type()) {
+    case QEvent::KeyPress:
+    case QEvent::KeyRelease:
+//         kDebug(5011) << "keyEvent";
+        keyEventHandler(static_cast<QKeyEvent*>(event));
+        return true;
+        break;
+    case QEvent::MouseButtonDblClick:
+    case QEvent::MouseButtonPress:
+    case QEvent::MouseButtonRelease:
+    case QEvent::MouseMove:
+//         kDebug(5011) << "mouseEvent";
+        mouseEventHandler(static_cast<QMouseEvent*>(event));
+        return true;
+        break;
+    case QEvent::Wheel:
+//         kDebug(5011) << "wheelEvent";
+        wheelEventHandler(static_cast<QWheelEvent*>(event));
+        return true;
+        break;
+    default:
+        return RemoteView::event(event);
+    }
+}
+
+void VncView::mouseEventHandler(QMouseEvent *e)
+{
+    if (e->type() != QEvent::MouseMove) {
+        if ((e->type() == QEvent::MouseButtonPress) ||
+                (e->type() == QEvent::MouseButtonDblClick)) {
+            if (e->button() & Qt::LeftButton)
+                m_buttonMask |= 0x01;
+            if (e->button() & Qt::MidButton)
+                m_buttonMask |= 0x02;
+            if (e->button() & Qt::RightButton)
+                m_buttonMask |= 0x04;
+        } else if (e->type() == QEvent::MouseButtonRelease) {
+            if (e->button() & Qt::LeftButton)
+                m_buttonMask &= 0xfe;
+            if (e->button() & Qt::MidButton)
+                m_buttonMask &= 0xfd;
+            if (e->button() & Qt::RightButton)
+                m_buttonMask &= 0xfb;
+        }
+    }
+
+    vncThread.mouseEvent(qRound(e->x() / m_horizontalFactor), qRound(e->y() / m_verticalFactor), m_buttonMask);
+}
+
+void VncView::wheelEventHandler(QWheelEvent *event)
+{
+    int eb = 0;
+    if (event->delta() < 0)
+        eb |= 0x10;
+    else
+        eb |= 0x8;
+
+    const int x = qRound(event->x() / m_horizontalFactor);
+    const int y = qRound(event->y() / m_verticalFactor);
+
+    vncThread.mouseEvent(x, y, eb | m_buttonMask);
+    vncThread.mouseEvent(x, y, m_buttonMask);
+}
+
+void VncView::keyEventHandler(QKeyEvent *e)
+{
+    // strip away autorepeating KeyRelease; see bug #206598
+    if (e->isAutoRepeat() && (e->type() == QEvent::KeyRelease))
+        return;
+
+// parts of this code are based on http://italc.sourcearchive.com/documentation/1.0.9.1/vncview_8cpp-source.html
+    rfbKeySym k = e->nativeVirtualKey();
+
+    // we do not handle Key_Backtab separately as the Shift-modifier
+    // is already enabled
+    if (e->key() == Qt::Key_Backtab) {
+        k = XK_Tab;
+    }
+
+    const bool pressed = (e->type() == QEvent::KeyPress);
+
+    // handle modifiers
+    if (k == XK_Shift_L || k == XK_Control_L || k == XK_Meta_L || k == XK_Alt_L) {
+        if (pressed) {
+            m_mods[k] = true;
+        } else if (m_mods.contains(k)) {
+            m_mods.remove(k);
+        } else {
+            unpressModifiers();
+        }
+    }
+
+    if (k) {
+        vncThread.keyEvent(k, pressed);
+    }
+}
+
+void VncView::unpressModifiers()
+{
+    const QList<unsigned int> keys = m_mods.keys();
+    QList<unsigned int>::const_iterator it = keys.constBegin();
+    while (it != keys.end()) {
+        vncThread.keyEvent(*it, false);
+        it++;
+    }
+    m_mods.clear();
+}
+
+void VncView::clipboardDataChanged()
+{
+    kDebug(5011);
+
+    if (m_status != Connected)
+        return;
+
+    if (m_clipboard->ownsClipboard() || m_dontSendClipboard)
+        return;
+
+    const QString text = m_clipboard->text(QClipboard::Clipboard);
+
+    vncThread.clientCut(text);
+}
+
+#include "moc_vncview.cpp"
diff --git a/linux_usr/gui/palacios/vnc_module/vncview.h b/linux_usr/gui/palacios/vnc_module/vncview.h
new file mode 100644 (file)
index 0000000..241d5dc
--- /dev/null
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2007-2012 Urs Wolfer <uwolfer @ kde.org>
+**
+** This file is part of KDE.
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; see the file COPYING. If not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+** Boston, MA 02110-1301, USA.
+**
+****************************************************************************/
+
+#ifndef VNCVIEW_H
+#define VNCVIEW_H
+
+#include "remoteview.h"
+#include "vncclientthread.h"
+
+#ifdef QTONLY
+    class KConfigGroup{};
+#else
+    #include "vnchostpreferences.h"
+#endif
+
+#include <QClipboard>
+
+extern "C" {
+#include <rfb/rfbclient.h>
+}
+
+class VncView: public RemoteView
+{
+    Q_OBJECT
+
+public:
+    explicit VncView(QWidget *parent = 0, const KUrl &url = KUrl(), KConfigGroup configGroup = KConfigGroup());
+    ~VncView();
+
+    QSize framebufferSize();
+    QSize sizeHint() const;
+    QSize minimumSizeHint() const;
+    void startQuitting();
+    bool isQuitting();
+    bool start();
+    bool supportsScaling() const;
+    bool supportsLocalCursor() const;
+    
+#ifndef QTONLY
+    HostPreferences* hostPreferences();
+#endif
+
+    void setViewOnly(bool viewOnly);
+    void showDotCursor(DotCursorState state);
+    void enableScaling(bool scale);
+    
+    virtual void updateConfiguration();
+
+public slots:
+    void scaleResize(int w, int h);
+
+protected:
+    void paintEvent(QPaintEvent *event);
+    bool event(QEvent *event);
+    void resizeEvent(QResizeEvent *event);
+    bool eventFilter(QObject *obj, QEvent *event);
+
+private:
+    VncClientThread vncThread;
+    QClipboard *m_clipboard;
+    bool m_initDone;
+    int m_buttonMask;
+    QMap<unsigned int, bool> m_mods;
+    int m_x, m_y, m_w, m_h;
+    bool m_repaint;
+    bool m_quitFlag;
+    bool m_firstPasswordTry;
+    bool m_dontSendClipboard;
+    qreal m_horizontalFactor;
+    qreal m_verticalFactor;
+#ifndef QTONLY
+    VncHostPreferences *m_hostPreferences;
+#endif
+    QImage m_frame;
+    bool m_forceLocalCursor;
+
+    void keyEventHandler(QKeyEvent *e);
+    void unpressModifiers();
+    void wheelEventHandler(QWheelEvent *event);
+    void mouseEventHandler(QMouseEvent *event);
+    
+private slots:
+    void updateImage(int x, int y, int w, int h);
+    void setCut(const QString &text);
+    void requestPassword();
+    void outputErrorMessage(const QString &message);
+    void clipboardDataChanged();
+};
+
+#endif
diff --git a/linux_usr/gui/palacios_resources.qrc b/linux_usr/gui/palacios_resources.qrc
new file mode 100644 (file)
index 0000000..a9dfad1
--- /dev/null
@@ -0,0 +1,17 @@
+<RCC>
+    <qresource prefix="/images">
+        <file>images/exit.png</file>
+        <file>images/icon_no_preview.png</file>
+        <file>images/new_vm.png</file>
+        <file>images/palacios.png</file>
+        <file>images/vm_pause.png</file>
+        <file>images/vm_refresh.png</file>
+        <file>images/vm_start.png</file>
+        <file>images/vm_stop.png</file>
+        <file>images/start_vm.png</file>
+        <file>images/stop_vm.png</file>
+        <file>images/activate_vm.png</file>
+        <file>images/pause_vm.png</file>
+        <file>images/reload_vm.png</file>
+    </qresource>
+</RCC>
diff --git a/linux_usr/gui/report.pdf b/linux_usr/gui/report.pdf
new file mode 100644 (file)
index 0000000..3e10189
Binary files /dev/null and b/linux_usr/gui/report.pdf differ