/***************************************************************************
 *   Copyright (C) 2006 by Bram Biesbrouck                                 *
 *   b@beligum.org                                                         *
 *                                                                         *
 *   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; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.             *
 ***************************************************************************/

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <set>

extern "C" {
   #include "../isdvncviewer/vncauth.h"
}

#include <qlayout.h>
#include <qapplication.h>
#include <qcursor.h>

#include <kcursor.h>
#include <kprogress.h>
#include <kprocess.h>
#include <ktempfile.h>
#include <kconfig.h>
#include <kglobal.h>
#include <kmessagebox.h>
#include <klocale.h>
#include <kpassdlg.h>
#include <kdebug.h>
#include <kstandarddirs.h>
#include <kprogress.h>

#include <libinstrudeo/isdvideoproperties.h>
#include <libinstrudeo/isdxmlfile.h>
#include <libinstrudeo/isdrecording.h>
#include <libinstrudeo/isdvnclogimporter.h>

#include "srktransmitrecordingdialog.h"
#include "srkmetainfodialog.h"
#include "srkmainwindow.h"
#include "srkvideopanel.h"
#include "srkprefdialog.h"
#include "srkmainview.h"

//-----CONSTRUCTORS-----
SRKMainView::SRKMainView(QWidget* parent, const char* name)
    : QWidget(parent, name),
      vncServer(NULL),
      videoPanel(new SRKVideoPanel(this)),
      vncViewer(NULL),
      vncTempFile(NULL),
      recording(NULL),
      dirty(false),
      exportProc(NULL),
      exportDialog(NULL)
{
    //check if a vnc server must be started
    checkStartVncServer();

    //layout the video panel to maximum size
    QGridLayout* layout = new QGridLayout(this);
    layout->addWidget(videoPanel, 0, 0);

    //connect the file-state slots
    connect(this, SIGNAL(fireFileOpened(bool)), (SRKMainWindow*)parent, SLOT(setFileOpened(bool)));

    //connect the popup-slots
    connect(this, SIGNAL(firePopupMenu(QString&, QPoint&)), (SRKMainWindow*)parent, SLOT(popupMenu(QString&, QPoint&)));

    //connect the language-combo slots
    connect(this, SIGNAL(fireAddActiveLanguage(QString)),
	    (SRKMainWindow*)parent, SLOT(addActiveLanguage(QString)));
    connect(this, SIGNAL(fireClearActiveLanguages()),
	    (SRKMainWindow*)parent, SLOT(clearActiveLanguages()));
    connect(this, SIGNAL(fireSyncActiveLanguage()),
	    (SRKMainWindow*)parent, SLOT(syncActiveLanguage()));
}

//-----DESTRUCTOR-----
SRKMainView::~SRKMainView()
{
    checkStopVncServer();

    emit fireFileOpened(false);
    
    //cleanup processes
    if (vncViewer){
	if (vncViewer->isRunning()) {
	    vncViewer->kill();
	}
	delete vncViewer;
	vncViewer = NULL;
    }
    if (vncServer){
	if (vncServer->isRunning())
	    vncServer->kill();
	delete(vncServer);
	vncServer = NULL;
    }
    if (exportProc) {
	if (exportProc->isRunning()) {
	    exportProc->kill();
	}
	delete exportProc;
	exportProc = NULL;
    }
    
    //temp file has autodeleted set to true if initialised
    if (vncTempFile!=NULL) {
	delete(vncTempFile);
	vncTempFile = NULL;
    }

    if (recording!=NULL) {
	delete(recording);
	recording = NULL;
    }

    if (exportDialog!=NULL) {
	delete exportDialog;
	exportDialog = NULL;
    }
}

//-----PUBLIC METHODS-----
SRKError::SRKErrorCode SRKMainView::newRecording()
{
    //check for the password file
    //if no file is set, ask the user for the password
    //if the user chooses to remember the password, save it in the default appdata folder
    //if not, create a temp file and delete the file after successfull authentication
    KConfig* config = KGlobal::config();
    config->setGroup("VNC");
    QCString passLocation(config->readEntry("PasswordFile"));

    if (passLocation.isNull()) {
	keepPass = 1;
	QCString password;
	int retVal = KPasswordDialog::getPassword(password, i18n("Enter the password for the vncserver."), &keepPass);
	if (retVal==KPasswordDialog::Accepted){
	    //init the passwd file location
	    if (keepPass){
		//save the password location, this will be erased if the password was false
		//to avoid a continuous password failure
		QString tempLoc = KGlobal::dirs()->saveLocation("appdata")+"vncpasswd";
		config->writeEntry("PasswordFile",  tempLoc);
		config->sync();
		vncPassFile.setName(tempLoc);
	    }
	    else{
		vncPassFile.setName(KTempFile().name());
	    }

	    passLocation = vncPassFile.name();
	    char cPass[password.length()+1], cLoc[passLocation.length()+1];
	    qstrcpy(cPass, password);
	    qstrcpy(cLoc, passLocation);
	    if (vncEncryptAndStorePasswd(cPass, cLoc)) {
		RETURN_ERROR(SRKError::SRK_VNC_PASSWD_ERROR);
	    }

	    startVncViewer();
	}
	//the user cancelled the password dialog
    }
    //if the password file is set, try to launch the viewer
    else{
	vncPassFile.setName(passLocation);
	startVncViewer();
    }

    RETURN_SUCCESS;
}
SRKError::SRKErrorCode SRKMainView::loadFile(QString& fileName)
{
    recording = new ISDRecording(fileName.ascii());
    if (recording->error()) {
	KMessageBox::error(this, i18n("Error while opening the file, see the console for details."), i18n("Error"));
	RETURN_ERROR(SRKError::SRK_FILE_ERROR);
    }
    else {
	videoPanel->loadRecording(recording);

	//update the language-commentbox of the main window
	set<Glib::ustring> langList;
	if (recording->getXmlFile()->getCommentLanguages(langList) != ISDObject::ISD_SUCCESS) {
	    KMessageBox::error(this, i18n("Error while opening the file, see the console for details."), i18n("Error"));
	    RETURN_ERROR(SRKError::SRK_FILE_ERROR);
	}
	else {
	    //clear the entire language-combo before adding
	    emit fireClearActiveLanguages();
	    set<Glib::ustring>::const_iterator iter;
	    for (iter=langList.begin();iter!=langList.end();iter++) {
		QString lang(*iter);
		emit fireAddActiveLanguage(lang);
	    }

	    //sync when all languages are added
	    emit fireSyncActiveLanguage();
	}

	emit fireFileOpened(true);
	dirty = false;
    }

    RETURN_SUCCESS;
}
SRKError::SRKErrorCode SRKMainView::importFile(QString& fileName)
{
    //init the progress dialog
    KProgressDialog progress(NULL, 0, i18n("Importing file"), i18n("Please wait while importing file..."), true);
    progress.setAllowCancel(true);
    progress.setModal(true);
    progress.setAutoClose(true);
    //wait one second before showing the dialog
    progress.setMinimumDuration(1000);
    //we're showing percentages
    progress.progressBar()->setTotalSteps(100);

    SRKImportProgressCallback callback(&progress);

    //create an empty recording
    ISDVncLogImporter importer(fileName);
    recording = new ISDRecording(importer, &callback);
    //we can safely delete the temp file now
    delete vncTempFile;
    vncTempFile = NULL;

    if (recording->error()) {
	RETURN_ERROR(SRKError::SRK_IMPORT_ERROR);
    }
    else{
	//open the file
	videoPanel->loadRecording(recording);
	dirty = true;
    }
    
    RETURN_SUCCESS;
}
SRKError::SRKErrorCode SRKMainView::saveRecording(QString& fileName)
{
    if (recording==NULL) {
	RETURN_ERROR(SRKError::SRK_INIT_ERROR);
    }

    if (recording->packRecording(string(fileName.ascii())) != ISDObject::ISD_SUCCESS) {
	RETURN_ERROR(SRKError::SRK_FILE_ERROR);
    }

    dirty = false;

    RETURN_SUCCESS;
}
SRKError::SRKErrorCode SRKMainView::editMetaInfo()
{
    if (recording==NULL) {
	RETURN_ERROR(SRKError::SRK_INIT_ERROR);
    }

    SRKMetaInfoDialog dlg(recording->getXmlFile()->getMetaInfo(), this);

    //if OK was pressed
    if (dlg.exec()) {
	dirty = true;
    }
    
    RETURN_SUCCESS;
}
SRKError::SRKErrorCode SRKMainView::transmitRecording(QString& fileName)
{
    if (recording==NULL) {
	RETURN_ERROR(SRKError::SRK_INIT_ERROR);
    }
    
    SRKTransmitRecordingDialog dlg(fileName, this);

    dlg.exec();

    RETURN_SUCCESS;
}
bool SRKMainView::applyTransmitFilter()
{
    bool retVal = true;

    if (recording==NULL) {
	return false;
    }

    QString errorString = i18n("You must solve the following before you can send the recording:");

    ISDVideoProperties* videoProperties = recording->getVideoProperties();
    if (videoProperties->getWidth()>WEBSERVICE_MAXIMAL_RESOLUTION_W || 
	videoProperties->getHeight()>WEBSERVICE_MAXIMAL_RESOLUTION_H)
	{
	    errorString += i18n("\n -- Resolution: The maximal resolution the webservice accepts is ");
	    errorString += i18n(ISDUtils::getInstance()->intToString(WEBSERVICE_MAXIMAL_RESOLUTION_W).c_str()) + i18n("x");
	    errorString += i18n(ISDUtils::getInstance()->intToString(WEBSERVICE_MAXIMAL_RESOLUTION_H).c_str()) + i18n(" pixels.\n");
	    errorString += i18n("Please visit http://www.captorials.com to learn how to scale your recording.");
	    retVal = false;
	}


    ISDRecordingMetaInfo* metaInfo = recording->getXmlFile()->getMetaInfo();
    if (!metaInfo) {
	return false;
    }

    if (metaInfo->getTitle()=="") {
	errorString += i18n("\n -- Meta information: Please supply a title for the recording.");
	retVal = false;
    }
    if (metaInfo->getQuestion()=="") {
	errorString += i18n("\n -- Meta information: Please supply a question this recording answers to.");
	retVal = false;
    }
    if (metaInfo->getDescription()=="") {
	errorString += i18n("\n -- Meta information: Please supply a description for the recording.");
	retVal = false;
    }

    if (!retVal) {
	KMessageBox::error(this, errorString, i18n("Error"));
    }

    return retVal;
}
SRKError::SRKErrorCode SRKMainView::exportRecording(QString& currentFileName, QString& fileName)
{
    if (recording==NULL) {
	RETURN_ERROR(SRKError::SRK_INIT_ERROR);
    }

    KConfig* config = KGlobal::config();
    config->setGroup("Paths");    
    QString isdexportLocation = config->readEntry("IsdExportLocation", DEFAULT_ISD_EXPORT_LOCATION);
    //first test if that location exists
    if (!QFile::exists(isdexportLocation)) {
	KMessageBox::error(this, i18n("The specified isdexport-location is invalid, please edit your preferences."), i18n("Error"));
	RETURN_ERROR(SRKError::SRK_EXPORT_ERROR);
    }

    //init the progress dialog
    exportDialog = new KProgressDialog(NULL, 0, i18n("Exporting file"), i18n("Please wait while exporting file..."), true);
    exportDialog->setAllowCancel(true);
    exportDialog->setModal(true);
    exportDialog->setAutoClose(true);
    exportDialog->setMinimumDuration(0);
    //we're showing percentages
    exportDialog->progressBar()->setTotalSteps(100);
    
    exportDialog->show();
    qApp->processEvents();
    
    exportProc = new KProcess(this);
    *exportProc << isdexportLocation;
    *exportProc << currentFileName;
    *exportProc << fileName;
    *exportProc << currentCommentsLanguage;
    //we want the program to show progress in stdout
    *exportProc << "-p";

    connect(exportProc, SIGNAL(processExited(KProcess*)),
	    this, SLOT(exportFinished(KProcess*)));
    connect(exportProc, SIGNAL(receivedStdout(KProcess*, char*, int)),
	    this, SLOT(updateExportDialog(KProcess*, char*, int)));

    bool started = exportProc->start(KProcess::NotifyOnExit, KProcess::Stdout);
    if (!started){
	kdDebug() << i18n("Error while starting the export routines.") << endl;
	
	delete(exportProc);
	exportProc = NULL;
	delete(exportDialog);
	exportDialog = NULL;
	
	RETURN_ERROR(SRKError::SRK_EXPORT_ERROR);
    }
    
    RETURN_SUCCESS;
}
SRKError::SRKErrorCode SRKMainView::closeRecording()
{
    //this deletes the temporary files on disk
    if (recording!=NULL) {
	delete recording;
	recording = NULL;

	emit fireFileOpened(false);
    }
    return videoPanel->closeRecording();
}
SRKError::SRKErrorCode SRKMainView::addComment(ISDCommentbox::commentboxType type)
{
    dirty = true;
    return videoPanel->addComment(type);
}
SRKError::SRKErrorCode SRKMainView::deleteActiveComment()
{
    dirty = true;
    return videoPanel->deleteActiveComment();
}
SRKError::SRKErrorCode SRKMainView::editActiveCommentProperties()
{
    //optimistic dirty-flag; comment-window can be cancelled
    dirty = true;
    return videoPanel->editActiveCommentProperties();
}
SRKError::SRKErrorCode SRKMainView::endActiveCommentHere()
{
    dirty = true;
    return videoPanel->endActiveCommentHere();
}
SRKError::SRKErrorCode SRKMainView::startVncServer(int xRes, int yRes, int disp, bool killOnExit)
{
    KConfig* config = KGlobal::config();

    config->setGroup("VNC");

    QString serverLocation = config->readEntry("ServerLocation", DEFAULT_SERVER_LOCATION);

    //first test if that location exists
    if (!QFile::exists(serverLocation)) {
	KMessageBox::error(this, i18n("The specified vncserver-location is invalid, please edit your preferences."), i18n("Error"));
	RETURN_ERROR(SRKError::SRK_VNC_SERVER_ERROR);
    }

    //create the server process
    vncServer = new KProcess(this);
    
    //create the geometry-argument
    QString geom = QString::number(xRes);
    geom += "x";
    geom += QString::number(yRes);
    
    //create the display-argument
    QString display = ":";
    display += QString::number(disp);
    
    *vncServer << serverLocation;
    *vncServer << "-geometry" << geom << display;
    
    bool started = vncServer->start();
    
    if (!started){
	//clean up on error
	delete vncServer;
	vncServer = NULL;
	RETURN_ERROR(SRKError::SRK_VNC_SERVER_ERROR);
    }
    else{
	if (!killOnExit){
	    //detach the process from this one
	    vncServer->detach();
	    //this evades the kill check on exit in checkStopVncServer
	    delete(vncServer);
	    vncServer = NULL;
	}
    }
    
    RETURN_SUCCESS;
}
SRKError::SRKErrorCode SRKMainView::stopVncServer(int disp)
{
    KConfig* config = KGlobal::config();

    config->setGroup("VNC");

    QString serverLocation = config->readEntry("ServerLocation", DEFAULT_SERVER_LOCATION);

    //first test if that location exists
    if (!QFile::exists(serverLocation)) {
	KMessageBox::error(this, i18n("The specified vncserver-location is invalid, please edit your preferences."), i18n("Error"));
	RETURN_ERROR(SRKError::SRK_VNC_SERVER_ERROR);
    }

    //do a clean kill of the server through "vncserver -kill"
    KProcess vncStopServer(this);
    
    QString display(":");
    display += QString::number(disp);
    
    vncStopServer << serverLocation;
    vncStopServer << "-kill" << display;

    //we wait for the kill to finish
    bool stopped = vncStopServer.start(KProcess::Block);
	
    if (!stopped) {
	RETURN_ERROR(SRKError::SRK_VNC_SERVER_ERROR);
    }

    //return success if everything went well; if no server was started, nothing has to be done
    RETURN_SUCCESS;
}
SRKError::SRKErrorCode SRKMainView::changeZoomFactor(int factor)
{
    return videoPanel->changeZoomFactor(factor);
}
SRKError::SRKErrorCode SRKMainView::changeCommentsLanguage(QString& lang)
{
    //Note: rec doesn't get dirty...
    currentCommentsLanguage = lang;
    return videoPanel->changeCommentsLanguage(lang);
}
bool SRKMainView::recIsDirty()
{
    return dirty;
}

//-----PUBLIC SLOTS-----
void SRKMainView::popupMenu(QString& name, QPoint& pos)
{
    emit firePopupMenu(name, pos);
}
void SRKMainView::markDirty()
{
    dirty = true;
}

//-----PROTECTED SLOTS-----
void SRKMainView::recordingFinished(KProcess* proc)
{
    //delete the password file if no longer necessary
    if (!keepPass){
	vncPassFile.remove();
    }
    
    //check for a clean exit status
    // 0 = everything OK
    // 1 = general error
    // 2 = authentication error
    if (proc->exitStatus()==0){
	//the recording finished ok, import it.
	QString fileName = vncTempFile->name();
	if (importFile(fileName) != SRKError::SRK_SUCCESS) {
	    KMessageBox::error(this, i18n("Error while importing the recorded session."), i18n("Error"));
	}
	else {
	    emit fireFileOpened(true);
	}
    }
    else if (proc->exitStatus()==1){
	KMessageBox::error(this, i18n("Error during starting of isdvncviewer.\n \
				      The vncserver is probably not running."), i18n("Error"));
    }
    else if (proc->exitStatus()==2){
	//if the password was saved, erase it, to avoid a continuous authentication failure
	KConfig* config = KGlobal::config();
	config->setGroup("VNC");
	if (!config->readEntry("PasswordFile").isNull()){
	    config->deleteEntry("PasswordFile");
	    config->sync();
	}
	KMessageBox::error(this, i18n("Error during starting of isdvncviewer.\n \
				      Authentication failed."), i18n("Error"));
    }
    else{
	KMessageBox::error(this, i18n("The isdvncviewer returned an unknown error value.\n \
				      This shouldn't happen."), i18n("Error"));
    }
    /*
     * always delete the temp files here, because otherwise, the disk
     * will get seriously crowded if a lot of failed recordings occur.
     */
    delete(vncTempFile);
    vncTempFile = NULL;
    
    //don't know if this really needs to be done, but it's safe I guess
    delete(vncViewer);
    vncViewer = NULL;
}
void SRKMainView::exportFinished(KProcess* proc)
{
    if (exportDialog != NULL) {
	bool cancelled = exportDialog->wasCancelled();
	delete(exportDialog);
	exportDialog = NULL;
	if (cancelled) {
	    return;
	}
    }

    switch (proc->exitStatus()) {
    
    case EXIT_SUCCESS:
	KMessageBox::information(this, i18n("Recording was exported successfully."), i18n("Information"));
	break;
	
    default:
	//TODO: filter the different export-codes
	KMessageBox::error(this, i18n("Error while exporting recording."), i18n("Error"));
	break;
    }
}
void SRKMainView::updateExportDialog(KProcess*, char* out, int outLen)
{
    if (exportDialog != NULL) {
	if (exportDialog->wasCancelled()) {
	    exportProc->kill();
	}
	QString procentStr = QString::fromAscii(out, outLen);
	procentStr = procentStr.remove('\n');
	bool ok;
	float procent = procentStr.toFloat(&ok);
	if (ok) {
	    exportDialog->progressBar()->setProgress((int)procent);
	    qApp->processEvents();
	}
    }   
}
SRKError::SRKErrorCode SRKMainView::startVncViewer(KProcess*)
{
    KConfig* config = KGlobal::config();
    //create and init the vncviewer process
    QString server;

    config->setGroup("Paths");    
    QString viewerLocation = config->readEntry("IsdViewerLocation", DEFAULT_ISD_VIEWER_LOCATION);
    //first test if that location exists
    if (!QFile::exists(viewerLocation)) {
	KMessageBox::error(this, i18n("The specified isdvncviewer-location is invalid, please edit your preferences."), i18n("Error"));
	RETURN_ERROR(SRKError::SRK_VNC_VIEWER_ERROR);
    }

    config->setGroup("VNC");

    vncTempFile = new KTempFile();
    vncTempFile->setAutoDelete(true);
    
    vncViewer = new KProcess(this);

    *vncViewer << viewerLocation;
    *vncViewer << "-recfile" << vncTempFile->name();
    *vncViewer << "-nocursorshape" << "-encodings" << "raw";
    
    //locate the passwd file
    *vncViewer << "-passwd" << vncPassFile.name();
    
    switch (config->readEntry("ServerMode", QString::number(DEFAULT_SERVER_MODE)).toInt()) {
        case SRKPrefDialog::LAUNCH_NEW:
	    server = "localhost:";
	    server += config->readEntry("LaunchServerDisplay", QString::number(DEFAULT_LAUNCH_SERVER_DISPLAY));
	    break;
        case SRKPrefDialog::USE_EXISTING:
	    server = config->readEntry("ExistingServerHost", DEFAULT_EXISTING_SERVER_HOST);
	    server += ":";
	    server += config->readEntry("ExistingServerDisplay", QString::number(DEFAULT_EXISTING_SERVER_DISPLAY));
	    break;
        default:
	    kdDebug() << i18n("Unsupported VNC Server mode in configuration file, using default.") << endl;
	    server = config->readEntry("ExistingServerHost", DEFAULT_EXISTING_SERVER_HOST);
	    server += ":";
	    server += config->readEntry("ExistingServerDisplay", QString::number(DEFAULT_EXISTING_SERVER_DISPLAY));
	    break;
    }
    
    *vncViewer << server;
    
    //connect slot to exit of process
    connect(vncViewer, SIGNAL(processExited(KProcess*)), this, SLOT(recordingFinished(KProcess*)));
    
    bool started = vncViewer->start();
    
    if (!started){
	KMessageBox::error(this, i18n("Error while starting the vnc viewer."), i18n("Error"));
	delete(vncViewer);
	vncViewer = NULL;

	//file gets deleted too: autodelete
	delete(vncTempFile);
	vncTempFile = NULL;

	RETURN_ERROR(SRKError::SRK_VNC_VIEWER_ERROR);
    }
    
    RETURN_SUCCESS;
}

//-----PROTECTED CHILD CLASS-----
SRKMainView::SRKImportProgressCallback::SRKImportProgressCallback(KProgressDialog* progressDialog)
    : progressDialog(progressDialog)
{
}
SRKMainView::SRKImportProgressCallback::~SRKImportProgressCallback()
{
}
void SRKMainView::SRKImportProgressCallback::procentDone(float procent)
{
    progressDialog->progressBar()->setProgress((int)procent);
    qApp->processEvents();
}
bool SRKMainView::SRKImportProgressCallback::wasCancelled()
{
    return progressDialog->wasCancelled();
}

//-----PROTECTED METHODS------
SRKError::SRKErrorCode SRKMainView::checkStartVncServer()
{
    SRKError::SRKErrorCode retVal;
    KConfig* config = KGlobal::config();

    config->setGroup("VNC");

    if (config->hasKey("ServerMode") && config->readEntry("ServerMode").toInt()==SRKPrefDialog::LAUNCH_NEW){
	/*
	 * When the server is launched on startup, it is killed on exit.
	 */
	if ((retVal = startVncServer(
				    config->readEntry("LaunchServerXRes", QString::number(DEFAULT_SERVER_X_RESOLUTION)).toInt(),
				    config->readEntry("LaunchServerYRes", QString::number(DEFAULT_SERVER_Y_RESOLUTION)).toInt(),
				    config->readEntry("LaunchServerDisplay", QString::number(DEFAULT_LAUNCH_SERVER_DISPLAY)).toInt(),
				    true
				    )) != SRKError::SRK_SUCCESS)
	    {
		KMessageBox::error(this, i18n("Error while launching the VNC server on startup."), i18n("Error"));
		RETURN_ERROR(retVal);
	    }
    }
    
    RETURN_SUCCESS;
}
SRKError::SRKErrorCode SRKMainView::checkStopVncServer()
{
    SRKError::SRKErrorCode retVal;
    KConfig* config = KGlobal::config();

    if (vncServer!=NULL) {
	int displayNumber = config->readEntry("LaunchServerDisplay",
					      QString::number(DEFAULT_LAUNCH_SERVER_DISPLAY)
					      ).toInt();

	if ((retVal = stopVncServer(displayNumber)) != SRKError::SRK_SUCCESS) {
	    KMessageBox::error(this, i18n("Error while stopping the vnc server."), i18n("Error"));
	    RETURN_ERROR(retVal);
	}
    }

    RETURN_SUCCESS;
}

