/* Copyright (C) 2004 Per Johansson
	
	This file is part of netGo.

    netGo 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.

    netGo 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 netGo; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include <qpushbutton.h>
#include <qlabel.h>
#include <qdir.h>
#include <qlistbox.h>
#include <qlineedit.h>
#include <qstring.h>
#include <qmessagebox.h>
#include <qwidgetstack.h>
#include <qcombobox.h>
#include <qregexp.h>
#include <qvalidator.h>
#include <qapplication.h>
#include <qprocess.h>
#include <qsettings.h>
#include <stdlib.h>
#include <qpopupmenu.h>
#include <qevent.h>
#include <qcheckbox.h>
#include <qradiobutton.h>
#include <qgroupbox.h>
#include <qfiledialog.h>

#include "netgodialog.h"
#include "netgodialogbase.h"
#include "settings.h"
#include "setup.h"
#include "profile.h"
#include "process.h"
#include "trayicon.h"
#include "msgbox.h"

// Version-number.
const QString version = "v0.5";

// Constructor for netGoDialog (with GUI).
netGoDialog::netGoDialog(QWidget *parent, const char *name)
			: netGoDialogBase(parent, name)
{
	// Print the current version in the versionLabel.
	versionLabel->setText("<p align=\"right\">" + version + "</p>");
	
	// Set the appropriate background color to the QTextBrowser (used for the process output).
	procBrowser->setPaletteBackgroundColor( runProfileGB->paletteBackgroundColor() ) ; 
	
	// Fetch all the profiles from the textfile and save them in a vector.
	Profile::fetchProfiles();
	
	// Update the profiles in the listbox.
	updateProfiles();
	
	// Update the stringlist with network interfaces.
	updateIfaces();
	
	// Initialize the system tray.
	initTray();
	
	// Signals and slots for the mainpage.
	connect(quitBut, SIGNAL(clicked()), this, SLOT(accept()) );
	connect(mainGoBut, SIGNAL(clicked()), this, SLOT(runProfilePage()) );
	connect(addProfileBut, SIGNAL(clicked()), this, SLOT(clearAddProfile()) );
	connect(editProfileBut, SIGNAL(clicked()), this, SLOT(fillEditProfilePage()) );
	connect(delProfileBut, SIGNAL(clicked()), this, SLOT(deleteProfilePage()) );
	
	// Signals and slots for the addProfilePage.
	connect(addProfileOkBut, SIGNAL(clicked()), this, SLOT(addProfile()) );
	connect(addProfileCancelBut, SIGNAL(clicked()), this, SLOT(mainPage()) );
	connect(moreSettingsBut, SIGNAL(clicked()), this, SLOT(morePage()) );
	connect(moreSettingsBackBut, SIGNAL(clicked()), this, SLOT(addProfilePage()) );
	connect(ipLE, SIGNAL(textChanged(const QString &)), this, SLOT(onDhcp(const QString &)) );
	connect(openBut, SIGNAL(clicked()), this, SLOT(openScript()) );
	connect(asciiBox, SIGNAL(clicked()), this, SLOT(onAsciiCheck()) );
	connect(hexBox, SIGNAL(clicked()), this, SLOT(onHexCheck()) );
	connect(offBox, SIGNAL(clicked()), this, SLOT(onOffCheck()) );
	
	// Signals and slots for the editProfilePage.
	connect(editProfileSaveBut, SIGNAL(clicked()), this, SLOT(editProfile()) );
	connect(editProfileCancelBut, SIGNAL(clicked()), this, SLOT(mainPage()) );
	connect(editMoreSettingsBut, SIGNAL(clicked()), this, SLOT(editMorePage()) );
	connect(editMoreBackBut, SIGNAL(clicked()), this, SLOT(editProfilePage()) );
	connect(editIpLE, SIGNAL(textChanged(const QString &)), this, SLOT(onDhcpEdit(const QString &)) );
	connect(editOpenBut, SIGNAL(clicked()), this, SLOT(editOpenScript()) );
	connect(editAsciiBox, SIGNAL(clicked()), this, SLOT(onEditAsciiCheck()) );
	connect(editHexBox, SIGNAL(clicked()), this, SLOT(onEditHexCheck()) );
	connect(editOffBox, SIGNAL(clicked()), this, SLOT(onEditOffCheck()) );
	
	// Signals and slots for the runProfilePage.
	connect(runProfileOkBut, SIGNAL(clicked()), this, SLOT(mainPage()) );
	connect(runProfileCancelBut, SIGNAL(clicked()), this, SLOT(cancelRunProfile()) );
	
	// Signals and slots for the profile-listbox.
	connect(profileLB, SIGNAL(clicked(QListBoxItem*)), this, SLOT(enableMainGoBut()) );
	connect(profileLB, SIGNAL(clicked(QListBoxItem*)), this, SLOT(enableEditProfileBut()) );
	connect(profileLB, SIGNAL(clicked(QListBoxItem*)), this, SLOT(enableDeleteProfileBut()) );

	// Regular expressions used as input validators.
	common = QRegExp("[^ ]*");
	ip = QRegExp("^[0-9]{1,3}[.]{1}[0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}$");
	ipOrDhcp = QRegExp("(^[0-9]{1,3}[.]{1}[0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}$|dhcp)");
	
	// Apply validators to the line-edits.
	nameLE->setValidator(new QRegExpValidator(common, this) );
	ipLE->setValidator( new QRegExpValidator(ipOrDhcp, this) );
	netmaskLE->setValidator( new QRegExpValidator(ip, this) );
	gwLE->setValidator( new QRegExpValidator(ip, this) );
	ns1LE->setValidator( new QRegExpValidator(ip, this) );
	ns2LE->setValidator( new QRegExpValidator(ip, this) );
	searchLE->setValidator( new QRegExpValidator(common, this) );
	
	editNameLE->setValidator( new QRegExpValidator(common, this) );
	editIpLE->setValidator( new QRegExpValidator(ipOrDhcp, this) );
	editNetmaskLE->setValidator( new QRegExpValidator(ip, this) );
	editGwLE->setValidator( new QRegExpValidator(ip, this) );
	editNs1LE->setValidator( new QRegExpValidator(ip, this) );
	editNs2LE->setValidator( new QRegExpValidator(ip, this) );
	editSearchLE->setValidator( new QRegExpValidator(common, this) );
}

// Constructor for commandline execution (without GUI).
netGoDialog::netGoDialog(QString profile)
{
	// Fetch all the profiles from the textfile and save them in a vector.
	Profile::fetchProfiles();
	
	int i, match = 0;
	// Check that the specified profile exists.
	for (i=0; i<Profile::profiles.size(); i++) {
		if (Profile::profiles.at(i).name == profile) {
			match = 1;
			break;
		}
	}
	
	// Bash colors.
	QString NORMAL = "\e[1m";
	QString normal = "\e[0m";
	
	// If the profile doesn't exist - exit.
	if (match != 1) {
		qWarning("Profile " + NORMAL + profile + normal + " doesn't exist. Aborting.");
		exit(1);
	}
	else {
		// Execute the profile from the commandline.
		cmdlineExecution(profile);
	}
}


// Function for executing a profile from the commandline.
void netGoDialog::cmdlineExecution(const char *profile)
{
	// Bash escape sequences for coloured text.
	QString blue = "\e[0;34m";
	QString BLUE = "\e[1;34m";
	QString green = "\e[0;32m";
	QString GREEN = "\e[1;32m";
	QString normal = "\e[0m";

	qWarning("\n" + blue + "Executing profile: " + BLUE + "%s\n"
			"" + normal + "================================\n", profile);

	// Create a Process-object.
	networkProc = new Process(procBrowser, runProfileOkBut);
	
	// Call the member-method that executes the specified profile's network settings.
	networkProc->runProfile(profile);
	
	// After the execution is finished - exit.
	connect(networkProc, SIGNAL(procsFinished()), this, SLOT(exitCmdline()) );
}


/*------------------------------------------
  Functions that enables/disables widgets.
------------------------------------------*/

// Function that enables the Go-button on the mainpage.
void netGoDialog::enableMainGoBut()
{
	// Enable the mainGoBut. 
	if (profileLB->numRows() > 0)
		mainGoBut->setEnabled(1);
}

// Function that enables the edit profile-button on the mainpage.
void netGoDialog::enableEditProfileBut()
{
	// Enable the editProfileBut.
	if (profileLB->numRows() > 0)
		editProfileBut->setEnabled(1);
}

// Function that enables the delete profile-button on the mainpage.
void netGoDialog::enableDeleteProfileBut()
{
	// Enable the delProfileBut.
	if (profileLB->numRows() > 0)
		delProfileBut->setEnabled(1);
}

// Function that enables/disables some lineedits depending on
// if the user specified a static ip or dhcp.
void netGoDialog::onDhcp(const QString &text)
{
	if (text == "dhcp") {
		netmaskLE->setEnabled(0);
		gwLE->setEnabled(0);
		ns1LE->setEnabled(0);
		ns2LE->setEnabled(0);
		searchLE->setEnabled(0);
	}
	else {
		netmaskLE->setEnabled(1);
		gwLE->setEnabled(1);
		ns1LE->setEnabled(1);
		ns2LE->setEnabled(1);
		searchLE->setEnabled(1);
	}
}

// Identical function to the one above, for the edit page.
void netGoDialog::onDhcpEdit(const QString &text)
{
	if (text == "dhcp") {
		editNetmaskLE->setEnabled(0);
		editGwLE->setEnabled(0);
		editNs1LE->setEnabled(0);
		editNs2LE->setEnabled(0);
		editSearchLE->setEnabled(0);
	}
	else {
		editNetmaskLE->setEnabled(1);
		editGwLE->setEnabled(1);
		editNs1LE->setEnabled(1);
		editNs2LE->setEnabled(1);
		editSearchLE->setEnabled(1);
	}
} 

// Function called when asciiBox checked.
void netGoDialog::onAsciiCheck()
{
	asciiBox->setChecked(1);
	hexBox->setChecked(0);
	offBox->setChecked(0);

	// Enable the key lineedit.	
	keyLE->setEnabled(1);
	keyLE->setFocus();
	keyLabel->setEnabled(1);
	
	// Remove the (possible) hex-key validation.
	keyLE->clear();
	keyLE->setValidator(new QRegExpValidator(QRegExp(".*"), this) );
}

// Function called when hexBox checked.
void netGoDialog::onHexCheck()
{
	hexBox->setChecked(1);
	asciiBox->setChecked(0);
	offBox->setChecked(0);

	// Enable the key lineedit.	
	keyLE->setEnabled(1);
	keyLE->setFocus();
	keyLabel->setEnabled(1);
	
	// Apply an validator for the hex-key.
	keyLE->clear();
	keyLE->setValidator(new QRegExpValidator(QRegExp("([a-fA-F0-9-]*|off)"), this) );
}

// Function called when offBox checked.
void netGoDialog::onOffCheck()
{
	offBox->setChecked(1);
	asciiBox->setChecked(0);
	hexBox->setChecked(0);

	// Disable the key lineedit.	
	keyLE->clear();
	keyLE->setEnabled(0);
	keyLabel->setEnabled(0);
}

// Function called when editAsciiBox checked.
void netGoDialog::onEditAsciiCheck()
{
	editAsciiBox->setChecked(1);
	editHexBox->setChecked(0);
	editOffBox->setChecked(0);
		
	// Enable the key lineedit.
	editKeyLE->setFocus();
	editKeyLE->setEnabled(1);
	editKeyLabel->setEnabled(1);

	// Remove the (possible) hex-validation.
	editKeyLE->clear();
	editKeyLE->setValidator(new QRegExpValidator(QRegExp(".*"), this) );
}

// Function called when editHexBox checked.
void netGoDialog::onEditHexCheck()
{
	editHexBox->setChecked(1);
	editAsciiBox->setChecked(0);
	editOffBox->setChecked(0);
	
	// Enable the key lineedit.	
	editKeyLE->setFocus();
	editKeyLE->setEnabled(1);
	editKeyLabel->setEnabled(1);

	// Apply an validator for the hex-key.
	editKeyLE->clear();
	editKeyLE->setValidator(new QRegExpValidator(QRegExp("([a-fA-F0-9-]*|off)"), this) );
}

// Function called when editOffBox checked.
void netGoDialog::onEditOffCheck()
{
	editOffBox->setChecked(1);
	editAsciiBox->setChecked(0);
	editHexBox->setChecked(0);

	// Disable the key lineedit.	
	editKeyLE->clear();
	editKeyLE->setEnabled(0);
	editKeyLabel->setEnabled(0);
}

/*------------------------------------------
      Functions that raises pages.
------------------------------------------*/

// Function that shows the mainpage.  
void netGoDialog::mainPage()
{
	// Update the profiles in the listbox before showing the mainpage.
	updateProfiles();
	
	// Raise the mainpage.
	widgetStack->raiseWidget(0);
}

// Function that shows the add profile-page.
void netGoDialog::addProfilePage()
{	
	// Raise the add profile-page.
	widgetStack->raiseWidget(1);
}

// Function that clear all the settings on the add profile-page.
void netGoDialog::clearAddProfile()
{
	// Clear all the lineedit's.
	nameLE->clear();
	ipLE->clear();
	netmaskLE->clear();
	gwLE->clear();
	ns1LE->clear();
	ns2LE->clear();
	searchLE->clear();
	modeCB->setCurrentText("None");
	essidLE->clear();
	keyLE->clear();
	scriptLE->clear();
	onOffCheck(); // Make the key-off checkbox checked by default.
	
	// Set focus to the first line-edit.
	nameLE->setFocus();

	// Show "None" as interface.
	ifaceCB->setCurrentText("None");
	
	// Raise the add profile-page.
	addProfilePage();	
}

// Function that shows the more page.
void netGoDialog::morePage()
{
	// Raise the more page and set focus to the script lineedit.
	widgetStack->raiseWidget(4);
	scriptLE->setFocus();
}

// Function that shows the run profile-page.
void netGoDialog::runProfilePage()
{
	// Raise the run profile-page.
	widgetStack->raiseWidget(2);
	
	// Create a Process-object.
	networkProc = new Process(procBrowser, runProfileOkBut);
	// Call the member-method that executes the selected profile's network-settings.
	networkProc->runProfile(profileLB->currentText() ); 
}

// Function that shows the edit profile-page.
void netGoDialog::editProfilePage()
{
	// Raise the edit profile-page.
	widgetStack->raiseWidget(3);
}

// Function that shows the edit profile-page and fills up the profile's settings.
void netGoDialog::fillEditProfilePage()
{
	// Raise the edit profile-page.
	widgetStack->raiseWidget(3);
	
	// Search after the appropriate profile and print its settings in the line-edit's.
	int i;
	for (i=0; i<Profile::profiles.size(); i++) {
		if (Profile::profiles.at(i).name == profileLB->currentText()) // Check if it's the one.
		{
			// Fill in the corresponding settings in the textfields.
			editNameLE->setText(Profile::profiles.at(i).name);
			editIfaceCB->setCurrentText(Profile::profiles.at(i).iface);
			editIpLE->setText(Profile::profiles.at(i).ip);
			editNetmaskLE->setText(Profile::profiles.at(i).netmask);
			editGwLE->setText(Profile::profiles.at(i).gw);
			editNs1LE->setText(Profile::profiles.at(i).ns1);
			editNs2LE->setText(Profile::profiles.at(i).ns2);
			editSearchLE->setText(Profile::profiles.at(i).search);	
			editScriptLE->setText(Profile::profiles.at(i).scriptPath);
			editModeCB->setCurrentText(Profile::profiles.at(i).mode);
			editEssidLE->setText(Profile::profiles.at(i).essid);
			
			// Determine the key type (off, ascii or hex). 
			if (Profile::profiles.at(i).keyType == "ascii")
				onEditAsciiCheck();
			else if (Profile::profiles.at(i).keyType == "hex")
				onEditHexCheck();
			else
				onEditOffCheck();
			
			// Print the key value.
			editKeyLE->setText(Profile::profiles.at(i).key);
		}
	}
	
	// Set focus to the lineedit on the top.
	editNameLE->setFocus();	
}

// Function that shows the edit more-page.
void netGoDialog::editMorePage()
{
	// Raise the edit more-page.
	widgetStack->raiseWidget(5);
	
	// Set focus to the script lineedit at the top.
	editScriptLE->setFocus();
}

// Function that shows the delete profile-page.
void netGoDialog::deleteProfilePage()
{
	// Call the function that does the actually "deleting".
	deleteProfile(profileLB->currentText() );
}

// Function for opening a script.
void netGoDialog::openScript()
{
	// Open a file dialog which allows opening a file.
	QString file = QFileDialog::getOpenFileName(QDir::homeDirPath(), "*", this, "open file dialog", "Choose a file");

	// If the user selected any file, add it to the lineedit.
	if (!file.isEmpty())
		scriptLE->setText(file);
}

// Same function as above (for the edit page).
void netGoDialog::editOpenScript()
{
	// Open a file dialog which allows opening a file.
	QString file = QFileDialog::getOpenFileName(QDir::homeDirPath(), "*", this, "open file dialog", "Choose a file");

	// If the user selected any file, add it to the lineedit.
	if (!file.isEmpty())
		editScriptLE->setText(file);
}

/*------------------------------------------
     Functions that handles the profiles.
------------------------------------------*/

// Function that adds a profile
void netGoDialog::addProfile()
{
	// Make sure that a profile name is filled in.
 	if (nameLE->text().isEmpty() ) {
	 	QMessageBox::information(0, "Missing info", "You have to specify a profile name.");
		return;
	}
	
	// Make sure that an interface is set, depending on other settings.
	if (ifaceCB->currentText() == "None") {
		if (!ipLE->text().isEmpty() ) {
			QMessageBox::information(0, "Missing info", "You have to select an interface in order to set an ip address.");
			return;
		}
		else if (!netmaskLE->text().isEmpty() ) {
			QMessageBox::information(0, "Missing info", "You have to select an interface in order to set a netmask.");
			return;
		}
		else if (modeCB->currentText() != "None" || !essidLE->text().isEmpty() || !keyLE->text().isEmpty() ) {
			QMessageBox::information(0, "Missing info", "You have to select an interface in order to set any wireless options."); 
			return;
		}
	}
	
	// Check that the user has specified an unique profile-name.
	int i;
	for (i=0; i<Profile::profiles.size(); i++) {
		if (Profile::profiles.at(i).name == nameLE->text() ) {
			QMessageBox::information(0, "Invalid profile name", "You have choosen a profile name that already exists.");
			return;
		}
	}

	// Determine the key type (ascii or hex).
	QString keyType;
	if (asciiBox->isChecked())
		keyType = "ascii";
	else if (hexBox->isChecked())
		keyType = "hex";
	else if (offBox->isChecked())
		keyType = "off";
	
	// Create a QSettings object so we can access the profiles.
	settings = new QSettings();
	settings->insertSearchPath(QSettings::Unix, QDir::homeDirPath() + "/.qt");
	
	// Write the profile.
	settings->beginGroup("/netgo/profiles/" + nameLE->text() );
		settings->writeEntry("interface", ifaceCB->currentText() );
		settings->writeEntry("ip", ipLE->text() );
		settings->writeEntry("netmask", netmaskLE->text() );
		settings->writeEntry("gateway", gwLE->text() );
		settings->writeEntry("ns1", ns1LE->text() );
		settings->writeEntry("ns2", ns2LE->text() );
		settings->writeEntry("search", searchLE->text() );
		settings->writeEntry("mode", modeCB->currentText() );
		settings->writeEntry("essid", essidLE->text() );
		settings->writeEntry("key", keyLE->text() );
		settings->writeEntry("key type", keyType );
		settings->writeEntry("script", scriptLE->text() );
	settings->endGroup();
	
	delete settings;
	
	// Update the profile-vector.
	Profile::fetchProfiles();
	
	// Return to the main-page.
	mainPage();
}

// Function that edits a profile's settings.
void netGoDialog::editProfile()
{
	// Make sure that a profile name is filled in.
 	if (editNameLE->text().isEmpty() ) {
	 	QMessageBox::information(0, "Missing info", "You have to specify a profile name.");
		return;
	}
	
	// Make sure that an interface is set, depending on other settings.
	if (editIfaceCB->currentText() == "None") {
		if (!editIpLE->text().isEmpty() ) {
			QMessageBox::information(0, "Missing info", "You have to select an interface in order to set an ip address.");
			return;
		}
		else if (!editNetmaskLE->text().isEmpty() ) {
			QMessageBox::information(0, "Missing info", "You have to select an interface in order to set a netmask.");
			return;
		}
		else if (editModeCB->currentText() != "None" || !editEssidLE->text().isEmpty() || !editKeyLE->text().isEmpty() ) {
			QMessageBox::information(0, "Missing info", "You have to select an interface in order to set any wireless options."); 
			return;
		}
	}
	
	// Check that the user has specified an unique profile-name.
	int i;
	for (i=0; i<Profile::profiles.size(); i++) {
		if (Profile::profiles.at(i).name == editNameLE->text() && editNameLE->text() != profileLB->currentText() ) {
			QMessageBox::information(0, "Invalid profile-name", "You have choosen a profile-name that allready exists.");
			return;
		}
	}
	
	// Determine the key type (ascii or hex).
	QString keyType;
	if (editAsciiBox->isChecked())
		keyType = "ascii";
	else if (editHexBox->isChecked())
		keyType = "hex";
	else if (editOffBox->isChecked())
		keyType = "off";
	
	// Create a QSettings object so we can access the profiles.
	settings = new QSettings();
	settings->insertSearchPath(QSettings::Unix, QDir::homeDirPath() + "/.qt");
	
	// Delete the profile's old settings before writing the new.
	settings->beginGroup("/netgo/profiles/" + profileLB->currentText() );
		settings->removeEntry("interface");
		settings->removeEntry("ip");
		settings->removeEntry("netmask");
		settings->removeEntry("gateway");
		settings->removeEntry("ns1");
		settings->removeEntry("ns2");
		settings->removeEntry("search");
		settings->removeEntry("mode");
		settings->removeEntry("essid");
		settings->removeEntry("key");
		settings->removeEntry("key type");
		settings->removeEntry("script");
	settings->endGroup();
	
	// Write the new edited settings.
	settings->beginGroup("/netgo/profiles/" + editNameLE->text() );
		settings->writeEntry("interface", editIfaceCB->currentText() );
		settings->writeEntry("ip", editIpLE->text() );
		settings->writeEntry("netmask", editNetmaskLE->text() );
		settings->writeEntry("gateway", editGwLE->text() );
		settings->writeEntry("ns1", editNs1LE->text() );
		settings->writeEntry("ns2", editNs2LE->text() );
		settings->writeEntry("search", editSearchLE->text() );
		settings->writeEntry("mode", editModeCB->currentText() );
		settings->writeEntry("essid", editEssidLE->text() );
		settings->writeEntry("key", editKeyLE->text() );
		settings->writeEntry("key type", keyType );
		settings->writeEntry("script", editScriptLE->text() );
	settings->endGroup();
	
	delete settings;
	
	// Update the vector that contains all the profiles.
	Profile::fetchProfiles();
	
	// Return to mainPage.
	mainPage();
}

// Function that deletes a profile.
void netGoDialog::deleteProfile(const QString &profile)
{
	// Ask the user if he's sure..
	if (QMessageBox::critical( this, "Delete profile", "Are you sure you want to delete profile: " + profileLB->currentText() + " ?", "Yes", "No", 0, 0, 1 ) )
		return;	
	
	// Loop through the vector...
	for (int i=0; i<Profile::profiles.size(); i++) {
		if (Profile::profiles.at(i).name == profile) { // Check if the current profile is matching the arg.
			QValueVector<Profile>::iterator it = Profile::profiles.begin() + i;
			Profile::profiles.erase(it); // Delete the profile that was matching the argument.
		}
	}
	
	// Create a QSettings object so we can access the profiles.
	settings = new QSettings();
	settings->insertSearchPath(QSettings::Unix, QDir::homeDirPath() + "/.qt");
	
	// Delete the specified profile.
	settings->beginGroup("/netgo/profiles/" + profile );
		settings->removeEntry("interface");
		settings->removeEntry("ip");
		settings->removeEntry("netmask");
		settings->removeEntry("gateway");
		settings->removeEntry("ns1");
		settings->removeEntry("ns2");
		settings->removeEntry("search");
		settings->removeEntry("mode");
		settings->removeEntry("essid");
		settings->removeEntry("key");
		settings->removeEntry("key type");
		settings->removeEntry("script");
	settings->endGroup();
	
	delete settings;
	
	// Let the user know that we've deleted the profile.
	QMessageBox::information(0, "Profile deleted", "Profile deleted successfully!");
	
	// Update the profile-vector.
	Profile::fetchProfiles();
	
	// Return to mainpage.
	mainPage();
}



/*------------------------------------------
         Systemtray functions.
------------------------------------------*/


// Function that initializes the system tray.
void netGoDialog::initTray()
{
	// Create a menu for the profiles.
	profileMenu = new QPopupMenu();
	
	// Make sure that we update the profiles before showing the menu.
	connect(profileMenu, SIGNAL(aboutToShow()), this, SLOT(updateTrayProfiles()) );
	
	// Create the "main menu" for the tray.
	trayMenu = new QPopupMenu();
	
	// Make sure that we update the menu before showing it.
	connect(trayMenu, SIGNAL(aboutToShow()), this, SLOT(updateTray()) );
	
	// Create the trayicon using Psi's class (God bless GPL!)
	tray = new TrayIcon( QPixmap::fromMimeSource("globe_22x22.png"), "netGo", trayMenu);
	QObject::connect(tray, SIGNAL(clicked( const QPoint&, int)), this, SLOT(showOrHide()) );
	
	// Make the trayicon visible.
	tray->show();
}

// Function that updates the profiles in the systemtray.
void netGoDialog::updateTrayProfiles()
{
	// Clear the profile menu.
	profileMenu->clear();
	
	// Insert the profiles.
	for (int i=0; i<Profile::profiles.size(); i++)
		profileMenu->insertItem(QPixmap::fromMimeSource("satelite_16x16.png"), Profile::profiles.at(i).name, this, SLOT(runFromTray(int)) );
}

// Function that updates the "main menu" in the systemtray.
void netGoDialog::updateTray()
{
	// Clear the "main menu".
	trayMenu->clear();
	
	// Insert all the items.
	if (this->isVisible()) // Insert "Hide" or "Unhide".
		trayMenu->insertItem("&Hide", this, SLOT(hide()) );
	else
		trayMenu->insertItem("Un&hide", this, SLOT(show()) );
	
	trayMenu->insertItem(QPixmap::fromMimeSource("globe_16x16.png"), "&Profiles", profileMenu);
	trayMenu->insertSeparator();
	trayMenu->insertItem(QPixmap::fromMimeSource("quit_16x16.png"), "&Quit", qApp, SLOT(quit()) );
}

// Function for executing a profile.
// Used by the systemtray.
void netGoDialog::runFromTray(int id)
{
	// Show the app.
	this->showNormal();
	
	// Raise the run profile-page.
	widgetStack->raiseWidget(2);
	
	// Create a Process-object.
	networkProc = new Process(procBrowser, runProfileOkBut);
	// Call the member-method that executes the selected profile's network-settings.
	networkProc->runProfile(profileMenu->text(id));
}

// Either show or hide the app when the user clicks the trayicon.
void netGoDialog::showOrHide()
{
	// Show or hide.
	if (this->isVisible())
		this->hide();
	else
		this->showNormal();
}


/*------------------------------------------
             Misc functions.
------------------------------------------*/


// Function that updates the profiles in the listbox.
void netGoDialog::updateProfiles()
{
	// Remove all the old items in the listbox.
	profileLB->clear();

	// Loop through all the profiles and parse out all the profile-names.
	for (int i=0; i<Profile::profiles.size(); i++)
		profileLB->insertItem(QPixmap::fromMimeSource("satelite_32x32.png"), Profile::profiles.at(i).name);
	
	// Sort all the profiles in alphabetical order.
	profileLB->sort(TRUE);
	
	// Disable a couple of buttons if there are'nt any profiles.
	if (profileLB->numRows() < 1) {
		mainGoBut->setEnabled(0);
		editProfileBut->setEnabled(0);
		delProfileBut->setEnabled(0);
	}
}

// Function that is called when the user press Cancel during
// execution of a profile.
void netGoDialog::cancelRunProfile()
{
	// Call the function that terminates the current process.
	networkProc->terminateProc();
	
	// Delete the Process class.
	delete networkProc;
	
	// Return to the main-page.
	mainPage();
}

// Function that exits the app after the commandline execution.
void netGoDialog::exitCmdline()
{
	// Exit the application.
	exit(0);
}

// Function for fetching the available interfaces from 'ifconfig -a'.
void netGoDialog::updateIfaces()
{
	
	// Open /proc/net/dev for reading.
	QFile file("/proc/net/dev");
	if (!file.open(IO_ReadOnly)) {
		qWarning("Could not find /proc/net/dev");
		QMessageBox::critical(this, "profiles.txt", "Couldn't find, or open profiles.txt.");
		return;
	}	
	
	// Regexp for fetching the interaces.
	QRegExp iface("\\s+([^ ]+):");
	QTextStream dev(&file);
	QString row;

	// Clear the stringlist before inserting the new interfaces.
	ifaces.clear();
	
	// Start with adding this item.
	ifaces = "None";

	// Loop through /proc/net/dev
	while (!file.atEnd()) {
		
		// Check if the line contains an interface.
		row = dev.readLine();
		if (iface.search(row) != -1 && iface.cap(1) != "lo")
			ifaces += iface.cap(1);
	}
	
	// Insert the stringlist in the comboboxes.
	ifaceCB->clear();
	ifaceCB->insertStringList(ifaces);
	editIfaceCB->clear();
	editIfaceCB->insertStringList(ifaces);
}

// Reimplement this function so the app is hidden instead of exited.
void netGoDialog::closeEvent(QCloseEvent *ce)
{
	// Check if we need to show the msgbox about the trayicon.
	if (Settings::NOTIFY_TRAY == "yes") {
		MsgBox *notify = new MsgBox();
		notify->exec();
		
		// If the checkbox was checked.
		if (notify->checkBox->isChecked() ) {
			// Write the new settings.
			settings = new QSettings();
			settings->insertSearchPath(QSettings::Unix, QDir::homeDirPath() + "/.qt");
			settings->writeEntry("/netgo/misc/notify tray", "no");
			delete settings;

			// Update the settings.
			Settings::fetchSettings();
		}
	}

	// Ignore the closing and hide the app instead.
	ce->ignore();
	this->hide();
}

