#include "mainwindow.h"
#include <QtGlobal>
#include <QTextBlock>
#include "ui_configuration.h"
#include "version.h"
#include "tools.h"
#include "password.h"
#include <kcombobox.h>
#include <signal.h>
#include <iostream>
#include <QInputDialog>
#include <QMenu>

using namespace std;

bool display = false;
extern Ui::Configuration config;
extern bool testRsyncReturn(QProcess *);
extern QApplication a;

QMap<int, QString> rsyncErrorStrings {
	{0, QTranslator::tr("Success. The rsync command completed successfully without any errors.")},
	{1, QTranslator::tr("Syntax or usage error. There was a problem with the syntax of the rsync command or with the options specified.")},
	{2, QTranslator::tr("Protocol incompatibility. There was a problem with the protocol version or negotiation between the rsync client and server.")},
	{3, QTranslator::tr("Errors selecting input/output files, dirs. There was a problem with the source or destination file or directory specified in the rsync command.")},
	{4, QTranslator::tr("Requested action not supported: An attempt was made to use an unsupported action or option.")},
	{5, QTranslator::tr("Error starting client-server protocol. There was an error starting the client-server protocol.")},
	{6, QTranslator::tr("Daemon unable to append to log-file. The rsync daemon was unable to write to its log file.")},
	{10, QTranslator::tr("Error in socket I/O. There was an error with the socket input/output.")},
	{11, QTranslator::tr("Error in file I/O. There was an error reading or writing to a file.")},
	{12, QTranslator::tr("Error in rsync protocol data stream. There was an error in the rsync protocol data stream.")},
	{13, QTranslator::tr("Errors with program diagnostics. There was an error generating program diagnostics.")},
	{14, QTranslator::tr("Error in IPC code. There was an error in the inter-process communication (IPC) code.")},
	{20, QTranslator::tr("Received SIGUSR1 or SIGINT. The rsync process was interrupted by a signal.")},
	{21, QTranslator::tr("Some error returned by waitpid(). An error occurred while waiting for a child process to complete.")},
	{22, QTranslator::tr("Error allocating core memory buffers. There was an error allocating memory buffers.")},
	{23, QTranslator::tr("Partial transfer due to error. The rsync command completed with an error, but some files may have been transferred successfully.")},
	{24, QTranslator::tr("Partial transfer due to vanished source files. Some source files disappeared before they could be transferred.")}
};

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
	ui->setupUi(this);

	QCoreApplication::setOrganizationName("RsyncUI");
	QCoreApplication::setApplicationName("RsyncUI");

	this->setWindowTitle(a.applicationName());

	// context menu for treewidget (list of files)
	ui->treeWidget->addAction(ui->actionDownload);
	// init configuration window
	config.setupUi(&Configuration);

	// init about window
	AboutW.setupUi(&aboutDialog);

	// text of About
	this->about.version = version;
	QString aboutText = tr("<h2>Client for rsync server</h2>") +
	"<b>" + tr("Version") + ":     " + version + "</b><br>" +
	"<b>" + tr("Licence") + ":     " + this->about.licence + "</b><br>" +
	"<b>" + tr("Author") + ":      " + this->about.author + "</b><br>" +
	"<b>" + tr("EMail") + ":      " + this->about.email + "</b><br>" +
	"<b>" + tr("Source code") + ": " + this->about.git + "</b><br>" +
	tr("You click on file to enqueue it, and RyncUI Download one file a time");

	AboutW.TextAbout->setHtml(aboutText);
//	initialization = true;

	info(DEBUGMACRO, "Initialization of widgets");
	// init of widgets
	ui->ktreewidgetsearchline->setTreeWidget(ui->treeWidget);               // attach search widget to treewidget
	ui->ktreewidgetsearchline->setCaseSensitivity(Qt::CaseInsensitive);     // and set it case insensitive
	ui->treeWidget->setHeaderLabels({tr("Path"), tr("Type"), tr("Size"), tr("Date"), "fullSize"} ); // set header of columns of tree widget

	// setting arrowcursor for treeWidget, listWidget and listDownload to arrow
	ui->treeWidget->setCursor(Qt::ArrowCursor);
	ui->listWidget->setCursor(Qt::ArrowCursor);
	ui->listDownload->setCursor(Qt::ArrowCursor);

	info(DEBUGMACRO, "Hiding progress bar");
	// Hiding progress bar
	ui->progressBar->hide();

	//setting configuration window
	config.comboBox->setCurrentIndex(ui->toolBar->toolButtonStyle());       // setting combobox to saved settings

	//setting unit of bandwidth limit
	config.UnitCombobox->addItems({tr("KB/s"), tr("MB/s"), tr("GB/s"), tr("TB/s"), tr("PB/s")});

	// hide fullsize column of treeview
	ui->treeWidget->setColumnHidden(4, true);

	loadSettings();
	initSystemTrayIcon();
	init();

	// if last server exists in settings
	if (this->settings.contains("connexion/lastServer"))
	{
		info(DEBUGMACRO, "Setting previous server");
		// set window to previous server/port configuration
		ui->portEdit->setText(this->settings.value("connexion/lastPort").toString());
		ui->khistorycombobox->setCurrentText(this->settings.value("connexion/lastServer").toString());
	}else
	{
		info(DEBUGMACRO, "No previous server, so setting only default port");
		ui->portEdit->setText(QString::number(this->connexion.port));
		ui->khistorycombobox->clear();
	}

	// connectors
	connect(this, &MainWindow::fileName, ui->progressBar, &QProgressBar::setFormat);
	connect(this, &MainWindow::progressSignal, ui->progressBar, &QProgressBar::setValue);
	connect(this, &MainWindow::stopDownloading, this, &MainWindow::cancelled);
	connect(config.buttonBox, SIGNAL(accepted()), this, SLOT(on_buttonBox_accepted()));
	connect(config.comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &MainWindow::on_comboBox_currentIndexChanged);
	populateList(ui->khistorycombobox->currentText(), ui->portEdit->text().toUInt());
	initialization = false;
}

void MainWindow::init()
{
	QAbstractButton * reply;
	QMessageBox msgBox;

	//if exists list of donwloads in saved settings
	if (this->settings.value("Downloads/rows").toInt() != 0)
	{
		// asking if we load the list and continue downloading
		msgBox.setWindowTitle(a.applicationName());
		msgBox.setInformativeText(tr("A list of interrupted downloads exists, do you want to continue downloading ? if not the list will be cleared" ));

		QPushButton *deleteButton = msgBox.addButton(tr("Delete"), QMessageBox::ActionRole);
		msgBox.addButton(QMessageBox::No);
		QPushButton *yes = msgBox.addButton(QMessageBox::Yes);
		msgBox.setDefaultButton(QMessageBox::Yes);

		msgBox.exec();
		reply = msgBox.clickedButton();
		info(DEBUGMACRO, "Response => " + reply->text());
		// if response is yes then loading list
		info(DEBUGMACRO, "reply text is : " + reply->text());
		if(reply == yes)
		{
			loadDownloadList();
		}else if (reply == deleteButton)
		{
			// delete saved download list
			deleteDownloadList();
		}
	}
}

void MainWindow::initSystemTrayIcon()
{
	QMenu *trayIconMenu;
	QAction * quitAction;
	QIcon icon;

	info(DEBUGMACRO, "initSystemTrayIcon");
	icon.addFile(this->icon);
	this->trayIcon = new QSystemTrayIcon;
	this->trayIcon->setIcon(icon);

	quitAction = new QAction(tr("&Quit"), this);
	connect(quitAction, &QAction::triggered, this, &MainWindow::quitApp);

	trayIconMenu = new QMenu(this);
	trayIconMenu->addAction(quitAction);
	trayIcon->setContextMenu(trayIconMenu);

	info(DEBUGMACRO, "Connecting signal of trayIcon");
	connect(this->trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(on_trayIcon_clicked(QSystemTrayIcon::ActivationReason)));
	this->trayIcon->show();
}

void MainWindow::on_trayIcon_clicked(QSystemTrayIcon::ActivationReason reason)
{
	info(DEBUGMACRO, "on_trayIcon_clicked");
	if (reason == QSystemTrayIcon::Trigger)
	{
		info(DEBUGMACRO, "trayIcon is clicked");
		if (this->isHidden())
		{
			this->show();
		}else
		{
			this->hide();
		}
	}
}

void MainWindow::hideWindow()
{
	info(DEBUGMACRO, "hideWindow()\n Hiding window");
	this->hide();
}

void MainWindow::showWindow()
{
	info(DEBUGMACRO, "showWindow()\n showing window");
	this->show();
}

MainWindow::~MainWindow()
{
	info(DEBUGMACRO, "Exiting application");
	delete ui;
	QCoreApplication::quit();
}

void MainWindow::quitApp()
{
	QMessageBox::StandardButton reply;
	QMessageBox::StandardButtons param;
	QString displayText;

	info(DEBUGMACRO, "Exiting application");

	// saving settings
	saveSettings();

	if (ui->listDownload->count() != 0)         // some downloads waiting
	{

		info(DEBUGMACRO, "Asking confirmation to exit");
		//  Asking for stopping or continuing
		param = QMessageBox::Yes|QMessageBox::No;
		if (config.autosaveCheckbox->checkState() != Qt::Checked)
		{
			param |= QMessageBox::Save;
			displayText = tr("Clicking Save button, You can save the list of downloads\n");
		}

		reply = QMessageBox::question(
		this,
		a.applicationName(),
		tr("Exiting will stop downloading, and will clear the download queue.\nDo you want to exit ?") + displayText,
		param,
		QMessageBox::No);
		this->downloading.quit = true;
		if(reply == QMessageBox::Yes)
		{
			info(DEBUGMACRO,"Stopping downloads");
			if (this->downloading.process->state() != QProcess::NotRunning)
			{
				// emission of signal to downloading thread and stopping
				emit (stopDownloading(this->downloading.process));
			}
		}else if (reply == QMessageBox::Save)
		{
			if (config.autosaveCheckbox->checkState() == Qt::Unchecked)
			{
				info(DEBUGMACRO, "Saving download list");
				//saveDownloadList();
				emit (stopDownloading(this->downloading.process));
			}
		}else if (reply == QMessageBox::No)
		{
			return;
		}
	}
	QCoreApplication::quit();
}

// Close window has been clicked
void MainWindow::closeEvent (QCloseEvent *event)
{
	QMessageBox msgBox;
	QCheckBox *cb;

	info(DEBUGMACRO, "closeEvent() => Closing window to systray");

	if (!event->spontaneous() || !isVisible())
		return;
	if (trayIcon->isVisible() and this->settings.value("CloseCheckbox").toBool() == false)
	{
		cb = new QCheckBox("Don't show this again ?");
		msgBox.setWindowTitle(a.applicationName());
		msgBox.setInformativeText(tr("The program will keep running in the "
		"system tray. To terminate the program, "
		"choose <b>Quit</b> in the context menu "
		"of the system tray entry."));

		msgBox.addButton(QMessageBox::Ok);
		msgBox.setCheckBox(cb);
		msgBox.exec();
		msgBox.clickedButton();

		// if response is yes then loading list
		if (cb->isChecked())
		{
			this->settings.setValue("CloseCheckbox", true);
		}
		hide();


		//event->accept();
		event->ignore();
   }
}

// Populate treeview with list of files
void MainWindow::populateTree()
{
	QString path;

	info(DEBUGMACRO, "populateTree() =>Populating listview");

	// Clear treewidget
	ui->treeWidget->clear();
	if (!this->connexion.server.isEmpty() and this->connexion.port > 0 and this->connexion.port < 65536)
	{
		// setting cursor to "Wait"
		QGuiApplication::setOverrideCursor(Qt::WaitCursor);

		info(DEBUGMACRO, "Validating server");
		// validating server's address
		this->connexion.ipversion = validateServer(&this->connexion.server);
		if (this->connexion.ipversion != 0)
		{
			// server is validated, scanning directory
			path = this->connexion.service + "/";
			while (this->rescan)
			{
				scanDir(&this->connexion, nullptr, path);
			}
		}
		// Restoring cursor
		QGuiApplication::restoreOverrideCursor();
	}

}

// Populate Listview with list of services
void MainWindow::populateList(QString server, uint port)
{
	QString service;
	QStringList hidden;
	int i;
	bool ok = false;

	info(DEBUGMACRO, "populateList() => Populating list of services");

	info(DEBUGMACRO, "port: " + QString::number(port) + " - server: " + server);

	if (server.isEmpty())
	{
		ui->listWidget->clear();
		ui->treeWidget->clear();
		return;
	}

	if (server != this->connexion.server)
	{
		// Determine version of Ip Protocol
		info(DEBUGMACRO, "Server changed");

		this->connexion.ipversion = validateServer(&server);
		this->connexion.server = server;

		if (port != false)
		{
			this->connexion.port = port;
		}
		// setting cursor to "Wait"
		QGuiApplication::setOverrideCursor(Qt::WaitCursor);

		// verify if server is in history
		this->settings.beginGroup("connexion/Servers");
		if (this->settings.contains(server))
		{
			this->settings.beginGroup(server);
			info(DEBUGMACRO, "Server configuration exists in settings");

			// server is in history => setting port value
			port = this->settings.value("port").toUInt();
			this->connexion.ipversion = this->settings.value("ipversion").toUInt();
			ui->portEdit->setText(QString::number(port));
			this->connexion.port = port;

			ok = true;
			//display list of services
			//listServices();						// TODO clear in listServices
			this->settings.endGroup();
		}
		this->settings.endGroup();
		this->settings.endGroup();
	}
	if (port != this->connexion.port)
	{
		info(DEBUGMACRO, "Port changed");

		this->connexion.port = port;
		ok = true;
		//listServices();						// TODO clear in listServices
	}

	if (ok == true)
	{
		if (this->connexion.ipversion == 0)
		{
			this->connexion.ipversion = validateServer(&server);
			info(DEBUGMACRO, "IP version : " + QString::number(this->connexion.ipversion));
		}

		if (this->connexion.ipversion != 0)
		{
			info(DEBUGMACRO, QString::number(this->connexion.ipversion));
			info(DEBUGMACRO, "server: " + server);
			info(DEBUGMACRO,"Saving server configuration in settings");

			// storing serverURL and port in settings
			this->settings.beginGroup("connnexion");
			this->settings.beginGroup("Servers");
			this->settings.beginGroup(server);
			this->settings.setValue("port", port);
			this->settings.setValue("ipversion", this->connexion.ipversion);
			this->settings.endGroup();
			this->settings.endGroup();
			this->settings.endGroup();

			this->settings.sync();
			this->downloading.server = server;
			this->downloading.port = port;
			this->downloading.ipversion = this->connexion.ipversion;

			// storing in history of combobox
			ui->khistorycombobox->addToHistory(server);

			// load and display rsync services of the rsync server
		}else
		{
			info(DEBUGMACRO, "ERROR : Unknown IP version");
		}
	}else
	{
		info(DEBUGMACRO, "Error server not changed");
	}
	listServices();

	this->settings.beginGroup("Hidden");
	this->settings.beginGroup(server);
	hidden = this->settings.allKeys();
	if (hidden.count() > 0)
	{
		for (i = 0; i < hidden.size(); i++)
		{
			service = hidden[i];
			//TODO detect if service is already present
			if (testServerPresence(service, false))
			{
				ui->listWidget->addItem(service + "\n\t");
			}
		}
	}
	this->settings.endGroup();
	this->settings.endGroup();
	// clearing listview
	ui->treeWidget->clear();
	QGuiApplication::restoreOverrideCursor();  //setting cursor to default
}

// Test if service is already present on the server
bool MainWindow::testServerPresence(QString service, bool askPassword)
{
	QString cmd;
	QStringList param;
	QString line;
	QString errorRsync;
	QStringList v;
	QProcess *myProcess;
	bool returnValue = false;
	int loop =0;
	bool r = false;

	info(DEBUGMACRO, "testServerPresence() => Test of rsync server");
	info(DEBUGMACRO, "ipversion = " + QString::number(this->connexion.ipversion ));
	cmd  = "/usr/bin/rsync";


	if (this->connexion.ipversion == 4 || this->connexion.ipversion ==6)
	{
		param << "-" + QString::number(this->connexion.ipversion);
	}
	param << "--contimeout=10" << "-nq" << "--port=" + QString::number(this->connexion.port) << + "[" + this->connexion.server + "]::" + preparePath(service);
	myProcess = new QProcess(this);
	myProcess->setProcessChannelMode(QProcess::MergedChannels);
	myProcess->start(cmd, param);
	myProcess->waitForStarted();
	myProcess->write("\n");
	while(myProcess->waitForReadyRead(10000))
	{
		while(1)
		{
			// line empty then buffer is empty so returning to wait new datas
			line = QString::fromUtf8(myProcess->readLine());
			if (line.isEmpty())
			{
				break;
			}
			if (line.contains("auth failed"))
			{
				if (askPassword == true and loop >=2 and r == true)
				{
					r = getUserPassword(&this->connexion);
					loop++;
				}
				returnValue = true;
			}
		}
	}
	if (myProcess->exitCode() == 0)
	{
	   returnValue = true;
	}
	myProcess->close();
	return returnValue;
}

//list services of the rsync server
void MainWindow::listServices()
{
	QString cmd = "/usr/bin/rsync";
	QStringList param;
	QString line;
	QString errorRsync;
	QStringList v;
	QString service;
	QString server;
	QProcess *myProcess;
	bool flag = false;

	info(DEBUGMACRO, "listServices() => Listing services offered by server");

	// clearing listwidget
	ui->listWidget->clear();

	if (this->connexion.ipversion == 0)
	{
		info(DEBUGMACRO, "test version of ip address of " + this->connexion.server);
		this->connexion.ipversion = whatIpVersion(this->connexion.server);
	}

	if (this->connexion.ipversion == 4)
	{
		param << "-" + QString::number(this->connexion.ipversion).trimmed();
		server = this->connexion.server.trimmed();
	}else if (this->connexion.ipversion == 6)
	{
		param << "-" + QString::number(this->connexion.ipversion).trimmed();
		server = "[" + this->connexion.server + "]";
	}else
	{
		error(tr("Error : Unknown IP version"));
		return;
	}

	param << "--contimeout=20" << "--port=" + QString::number(this->connexion.port) << server + "::";
	myProcess = new QProcess(this);

	info(DEBUGMACRO, cmd + " " + param.join(" "));

	myProcess->start(cmd, param);

	// waiting for response of the server with a timeout of 10 seconds
	while(myProcess->waitForReadyRead(10000))
	{
		info(DEBUGMACRO, "Reading");
		while(!flag)
		{
			line = QString::fromUtf8(myProcess->readLine());
			// line empty then buffer is empty so returning to wait new datas
			info(DEBUGMACRO, "line: #" + line + "#");
			if (line.isEmpty())
			{
				info(DEBUGMACRO, "line is empty");
				flag = true;
				break;
			}
			info(DEBUGMACRO, "extracting services informations");
			// extracting name and comment of the service
			v = line.split("\t");
			v[0].replace(" ", "");
			v[1].replace("\n", "");
			service = v[0] + "\n\t" + v[1];
			info(DEBUGMACRO, "service is:" + service);
			info(DEBUGMACRO, "adding to list widget of services");
			ui->listWidget->addItem(service);
		}
		// buffer empty go to waiting new datas
		flag = false;
	}
	// verifying error code
	testRsyncReturn(this, myProcess);
	myProcess->close();
	info(DEBUGMACRO, "listServices finished");
}

// connect to rsync server to get list of files
bool MainWindow::scanDir(Connexion * connexion, QTreeWidgetItem *parent, QString path)
{
	QString cmd = "rsync";
	QStringList param;
	QStringList sizeA;
	QString line;
	QString size;
	QString fullsize;
	QString filename;
	QString fileType;
	QString date;
	QString dirName = "";
	QString user;
	QProcess * myProcess;
	QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
	bool isDir = false;
	bool flag = false;
	bool readOk = false;
	bool passwdOk = false;
	int nChild = 0;
	static uint looping;
	QStringList dirs;
	QString server = connexion->server;
	bool ret = false;

	info(DEBUGMACRO, "scandir() => connect to rsync server to get list of files");

	ui->listWidget->setCursor(Qt::WaitCursor);

	myProcess = new QProcess(this);
	myProcess->setProcessChannelMode(QProcess::MergedChannels);

	if (parent != nullptr)
	{
		nChild = parent->childCount();
	}
	if (nChild == 0)
	{

		myProcess->setProcessEnvironment(env);

		info(DEBUGMACRO, "ipversion => " + QString::number(connexion->ipversion));
		if(this->connexion.ipversion == 4 || this->connexion.ipversion == 6)
		{
			param << "-" + QString::number(connexion->ipversion).trimmed();
		}


		if (!connexion->user.isEmpty())
		{
			user = connexion->user + "@";
			env.insert("RSYNC_PASSWORD", connexion->password); // Add an environment variable
		}else
		{
			user = "anonymous@";
			env.insert("RSYNC_PASSWORD", "anonymous"); // Add an environment variable
		}
		param << "--contimeout=20" << "--port=" + QString::number(connexion->port) << user + "[" + server + "]::" + preparePath(path) ;

		info(DEBUGMACRO, cmd + " " + param.join(" "));

		myProcess->start(cmd, param);
		this->rescan = true;

		info(DEBUGMACRO, "Waiting server response");
		// waiting for response of the server with a timeout of 10 seconds
		do
		{
			readOk = myProcess->waitForReadyRead(10000);
			if (readOk)
			{
				while (!flag)
				{
					line = QString::fromUtf8(myProcess->readLine());
					// line empty then buffer is empty so returning to wait new datas
					if (line.isEmpty())
					{
						flag = true;
						break;
					}
					if (line.contains("auth failed"))
					{
						myProcess->readAllStandardOutput();
						getUserPassword(connexion);
						if (looping <= 1)
						{
							this->rescan = true;
							looping++;
						}else
						{
							this->rescan = false;
							looping = 0;
							warning(tr("Authentication failed" ));
						}
						return false;
					}

					// extracting name, size and is dir/file
					line = line.simplified();
					filename = line.section(" ", 4);
					if (filename != '.')
					{
						size = line.section(" ", 1, 1);
						fullsize = size;
						fullsize.remove(",");
						sizeA = size.split(',');
						if (sizeA.count() <= 1)
						{
							size = sizeA.at(0) + " " + UnitText[0] + " ";
						}else
						{
							myProcess->setProcessEnvironment(env);
							size = sizeA.at(0) + "," + sizeA.at(1).left(2) + " " + UnitText[sizeA.count()-1] + " ";
						}

						if (line[0] == 'd')
						{
							isDir = true;
						}else
						{
							isDir = false;
						}

						date = line.section(' ', 2, 2);
						fileType = getFileType(filename);
						if (!path.isEmpty())
						{
							if (path.endsWith('/'))
							{
								path.chop(1);
							}
							dirs = path.split('/');
							dirName = dirs[dirs.size()-1];
						}
						addTreeItem(filename, size, fullsize, fileType, date, isDir, dirName, parent);
						if (passwdOk == false and !connexion->password.isEmpty())
						{
							this->settings.setValue("Passwords/" + connexion->server + "/" + connexion->service + "/" + connexion->user, true);
							setPassword(connexion->user, connexion->password);
							this->settings.sync();
						}
						this->rescan = false;
					}
				}
				flag = false;
			}else
			{
				if (myProcess->state() == QProcess::Running)
				{
					if (myProcess->waitForFinished(10000) == 0)
					{
						warning(tr("The processus does'nt respond: ") + myProcess->errorString());
					}
				}
			}
		}while(readOk);
	// buffer empty go to waiting new datas

	ret = testRsyncReturn(this, myProcess);
	myProcess->close();
	}
	ui->listWidget->setCursor(Qt::ArrowCursor);

	return ret;
}

// validate address server
uint MainWindow::validateServer(QString *server)
{
	QString cmd;
	QStringList param;
	QString line;
	QProcess * myProcess;
	QStringList responseList;
	QFile fileHandle("/etc/hosts");

	uint ipversion = 0;
	int answerFound = 0;
	int queryPos = 0;
	QHostAddress serverAddress;

	info(DEBUGMACRO, "ValidateServer() => Validating server address");

	//if (ipversion == 0)					// not an Ip address, perhaps a server name
	//{

	serverAddress = searchHosts(*server);
	if (!serverAddress.isNull())
	{
		server->clear();
		server->append(serverAddress.toString());
		info(DEBUGMACRO, "Server address : " + *server);
	}else
	{
		if (!serverAddress.setAddress(*server))
		{

			info(DEBUGMACRO, "Digging server name");

			cmd = "dig";
			param << server->trimmed() ;
			if (ipversion == IPV4)
			{
				param << "A";				// IP V4 query
			}else if (ipversion == IPV6)
			{
				param << "AAAA";				// IP V6 query
			}else
			{
				error("Protocol is not IPV4 or IPV6 !!");
			}

			info(DEBUGMACRO, cmd + " " + param.join(" "));

			myProcess = new QProcess(this);
			myProcess->start(cmd, param);

			// making a dig on the server's address
			while(myProcess->waitForReadyRead())
			{
				while (1)		//!bflag)
				{
					line = QString::fromUtf8(myProcess->readAllStandardOutput());
					info(DEBUGMACRO, line);
					// line empty then buffer is empty so returning to wait new datas
					if (line.isEmpty())
					{
						break;
					}else
					{
						answerFound = line.indexOf(";; ANSWER SECTION:") + 19;
						info(DEBUGMACRO, "Position of answer line is : " + QString::number(answerFound));

						if (answerFound != -1)
						{
							info(DEBUGMACRO, "Serching IP address");
							queryPos = line.indexOf(";; Query");
							info(DEBUGMACRO, "Position of Query line is : " + QString::number(queryPos));
							if (answerFound < queryPos)
							{
								line = line.mid(answerFound, queryPos - answerFound);
								info(DEBUGMACRO, "line is:\n" + line);
								responseList = line.split(QRegularExpression("\\s+"));
								info(DEBUGMACRO, "ip Address is => " + responseList.at(4));
								if (serverAddress.setAddress(responseList.at(4)))
								{
									//error ("Address " + responseList.at(4) + " is bad");
									server->clear();
									server->append(serverAddress.toString());
								}
							}
						}
					}
				}
			}
			myProcess->close();
		}
	}

	//ipversion = whatIpVersion(*server);

	ipversion = serverAddress.protocol();
	info(DEBUGMACRO, "Returning ip version: " + QString::number(ipversion));

	return (ipversion == QAbstractSocket::IPv4Protocol?4:6);
}


// slot activated when button connection is clicked
void MainWindow::on_connectButton_clicked()
{
	QString server;
	uint port;
	//uint ipversion;

	info(DEBUGMACRO, "on_connectButton_clicked() => Connexion button clicked");
	port = ui->portEdit->text().toUInt();
	if (port > 0 and port < 65535)
	{
		server = ui->khistorycombobox->currentText();
		//ipversion = validateServer(&server);
		populateList(server, port);
	}else
	{
		error(tr("Bad port number, correct it"));
		ui->portEdit->clear();
		ui->portEdit->setFocus();
	}
}

// add parent in treeview
void MainWindow::addTreeItem(QString name, QString fileSize, QString fullsize, QString type, QString date, bool isDir=false, QString dirName="", QTreeWidgetItem *parent=nullptr)
{
	QFont font;
	QTreeWidgetItem *treeItem;

	//info(DEBUGMACRO, "addTreeItem() => adding item to treeview");

	if (parent != nullptr)
	{
		treeItem = new QTreeWidgetItem();
	}else
	{
		treeItem = new QTreeWidgetItem(ui->treeWidget);
	}

	// item is a file
	if (QFile::exists(this->downloading.savePath + "/" + name) or QFile::exists(this->downloading.savePath + "/" + dirName + "/" + name))
	{
		QBrush b (Qt::green);
		treeItem->setForeground(0, b);
		treeItem->setFont(0, font);
	}else if (this->settings.contains(name))
	{
		QBrush b (Qt::red);
		treeItem->setForeground(0, b);
		treeItem->setFont(0, font);
	}

	if (isDir == true)
	{
		// item is a dir
		treeItem->setText(1, tr("Dir"));
		treeItem->setIcon(0, QIcon::fromTheme("folder"));
	}else
	{
		// item is a file
		this->settings.beginGroup("Downloaded");
//TODO add to settings
		this->settings.endGroup();
		treeItem->setText(1,type);
	}
	treeItem->setText(0, name);
	treeItem->setText(2, fileSize);
	treeItem->setText(3, date);
	treeItem->setText(4, fullsize);

	treeItem->setTextAlignment(2, Qt::AlignRight);

	if (parent != nullptr)
	{
		parent->addChild(treeItem);
	}
}

// Slot activated when a service in the list is clicked
void MainWindow::on_listWidget_clicked()
{
	info(DEBUGMACRO, "on_listWidget_clicked() => Slot activated when a service in the list is clicked");

	this->connexion.service = ui->listWidget->currentItem()->text().section("\n", 0 ,0);
	ui->treeWidget->clear();
	preparePopulateTree();
}

void MainWindow::preparePopulateTree()
{
	QString str;
	QStringList logins;

	info(DEBUGMACRO, "preparePopulateTree()");
	this->rescan = true;
	this->connexion.user = nullptr;
	this->connexion.password = nullptr;
	str = "Folder/" + this->connexion.server + ":" + QByteArray::number(this->connexion.port) + "/" + this->connexion.service;

	// if service exists in settings for this server
	if (this->settings.contains(str))
	{
		// setting savePath from settings
		this->downloading.savePath = this->settings.value(str).toString();
	}
	populateTree();
}

// get password and user login
// if object = false ==> searching from connexion object
// else searching from downloading object
bool MainWindow::getUserPassword(Connexion * object)
{
	QStringList logins;
	QString login = "";
	QString password = "";
	QString server;
	QString service;
	int c;

	info(DEBUGMACRO, "getUserPassword() => get password and user login");
	bool returnValue = false;
	bool ok = false;

	server = object->server;
	service = object->service;

	object->user = "";
	object->password = "";

	this->settings.beginGroup("Passwords/" + server + "/" + service);
	logins = this->settings.allKeys();
	c = logins.count();
	if ( c != 1)
	{
		//choose login in case of multiples logins
		login = QInputDialog::getItem(this,
		"RsincUI",
		tr("Select the user you want to connect with or enter a new one"),
		logins,
		0,
		true,
		&ok,
		Qt::Popup,
		Qt::ImhNoPredictiveText
		);
		if (ok and !login.isEmpty())
		{
			if (!logins.contains(login))
			{
				password = QInputDialog::getText(this,
				a.applicationName() + tr(" Request"),
				tr("Enter password"), QLineEdit::Password,
				"", &ok, Qt::Popup,
				Qt::ImhNoPredictiveText);
				if (!ok or password.isEmpty())
				{
					password = "";
					returnValue = false;
				}
			}else
			{
				password = getPassword(login);
				returnValue = true;
			}
			object->user = login;
			object->password = password;
		}
	}else
	{
		object->user = logins.at(0);
		object->password = getPassword(object->user);
		returnValue = true;
	}
	this->settings.endGroup();
	return returnValue;
}

//Slot activated when a file is clicked in the treeview
void MainWindow::on_treeWidget_itemClicked(QTreeWidgetItem *item, bool downloadDir)
{
	QTreeWidgetItem * itemR;
	QString path;
	QString str;
	QMessageBox::StandardButton reply;
	int sizeFromRsync;
	bool ret = false;

	info(DEBUGMACRO, "on_treeWidget_itemClicked() => Slot activated when a file is clicked in the treeview");

	if (this->treeviewClicked == true)
	{
		info(DEBUGMACRO, "double click ignored");
		return;
	}

	this->treeviewClicked = true;
	itemR = item;
	this->rescan = true;

	// assembling path from treewidget
	path = item->text(0);
	sizeFromRsync = item->text(4).toUInt();

	while(itemR->parent() != NULL)
	{
		itemR = itemR->parent();
		// concatening parent to path
		path.prepend(itemR->text(0) + "/");
	};

	cout << item->text(1).toStdString() <<endl;
	if (item->text(1) != tr("Dir") or downloadDir == true)
	{
		// exists saving path in settings ?
		str = "Folder/" + this->connexion.server + ":" + QByteArray::number(this->connexion.port) + "/" + this->connexion.service;
		if(!this->settings.contains(str))
		{
			info(DEBUGMACRO, "saving path do not exists, asking for it");
			// saving path do not exists, asking for it
			if(!on_DefaultSaveFolder_triggered())
			{
				info(DEBUGMACRO, "no directory selectioned, ignoring download request");
				this->treeviewClicked = false;
				return;
			}
		}else
		{
			this->downloading.savePath = this->settings.value(str).toString();
			info(DEBUGMACRO, "saving folder : " + this->downloading.savePath);
		}

		// Item is a file
		// searching if file exists in savepath
		info(DEBUGMACRO, "searching if file exists in savepath");
		if (QFile::exists(this->downloading.savePath + "/" + path))
		{
			info(DEBUGMACRO, "file exists in savepath");
			QFileInfo fileinfo(this->downloading.savePath + "/" + path);
			if (fileinfo.size() < sizeFromRsync)
			{
				reply = QMessageBox::question(
				this,
				a.applicationName(),
				tr("File is partially downloaded. Do you want to resume download ? if no, the file will be deleted from destination directory"),
				QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel,
				QMessageBox::Cancel);

				if (reply == QMessageBox::Cancel)
				{
					this->treeviewClicked = false;
					return;
				}else if(reply == QMessageBox::No)
				{
					QFile::remove(this->downloading.savePath + "/" + path);
					this->treeviewClicked = false;
					return;
				}
			}else
			{
				reply = QMessageBox::question(
				this,
				a.applicationName(),
				tr("File is already downloaded. Do you want to reload it ? The old file will be deleted"),
				QMessageBox::Yes|QMessageBox::No,
				QMessageBox::No);

				if (reply == QMessageBox::No)
				{
					this->treeviewClicked = false;
					return;
				}else
				{
					QFile::remove(this->downloading.savePath + "/" + path);
				}
			}
		}

		if(ui->listDownload->findItems(path, Qt::MatchStartsWith).empty())
		{
			// is there a downloading process ?
			info(DEBUGMACRO, "is there a downloading process ?");
			if (this->downloading.process == nullptr)
			{
				// no downloading process launching it
				info(DEBUGMACRO, "no downloading process launching it");
				this->downloading.path = path;
				this->downloading.server = this->connexion.server;
				this->downloading.port = this->connexion.port;
				this->downloading.service = this->connexion.service;
				startDownloading();
				// wait 1 second to process start
				//sleep(1);
			}
			info(DEBUGMACRO, "Downloading process exist, adding download to download list");
			// Adding download to download list
			str = path + " => " + this->connexion.server + ":" + QByteArray::number(this->connexion.port) + "/" + this->connexion.service;
			ui->listDownload->addItem(str);
		}else
		{
			warning(tr("File is already downloading" ));
		}
	}else
	{
		//Item is a Directory
		info(DEBUGMACRO, "Item is a Directory");
		if (item->isExpanded() == false)
		{
			info(DEBUGMACRO, "Item is not expanded");
			//if (this->rescan)
			//{
				info(DEBUGMACRO, "Re-scanning path: " + this->connexion.service + "/" + path +"/");
				ret = scanDir(&this->connexion, item,  this->connexion.service + "/" + path +"/");
				if(!ret)
				{
					item->setExpanded(true);
				}
			//}
		}else
		{
			item->setExpanded(false);
		}

	}

	if (config.autosaveCheckbox->checkState() == Qt::Checked)
	{
		info(DEBUGMACRO, "Saving download list");
		saveDownloadList();
	}
	info(DEBUGMACRO, "Exiting");
	this->treeviewClicked = false;
}

// Launch the thread which download the file
void MainWindow::startDownloading()
{

	info(DEBUGMACRO, "startDownloading() => Launch the thread which download the file");

	ui->progressBar->setValue(0);
	ui->progressBar->show();
	//getUserPassword();

	//QtConcurrent::run(&this->downloadO, &downloadFile::download, this);
	this->download();
	this->trayIcon->showMessage(a.applicationName(), tr("Starting downloading\n") + this->downloading.path, QSystemTrayIcon::Information);
}

// Slot stopping download
void MainWindow::stoppingDownload()
{
	info(DEBUGMACRO, "stoppingDownload");

	emit (stopDownloading(this->downloading.process));
}

// when download is finished, launch download of next file in queue
void MainWindow::downloadFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
	QString path;
	QString str;
	int pos;
	QString aborted = tr("finished");
	QMessageBox::StandardButton reply;
	bool retry = false;

	info(DEBUGMACRO, "downloadFinished() => when download is finished, launch download of next file in queue");
	info(DEBUGMACRO, "Download finished with status " + QString::number(exitCode));

	// test if process crashed
	if (exitStatus == QProcess::CrashExit)
	{
		warning(tr("Rsync process crashed"));
	}
	//test result code of command (if 20 then command stopped by user)
	if (exitCode != 0 and this->stopDlAsked != true)
	{
		if (exitCode == 20)
		{
			if (this->exiting)
			{
				return;
			}
			aborted = tr("stopped by user");
		}else if (exitCode == 5)                            // password asked
		{
			getUserPassword(&this->downloading);
			retry = true;
		}

		// displaying warning with exit code
		reply = QMessageBox::warning(
		this,
		a.applicationName(),
		tr(rsyncErrorStrings[exitCode].toStdString().c_str()) + tr("\nDo you want to retry?"),
		QMessageBox::Yes|QMessageBox::No,
		QMessageBox::Yes);
		if (reply == QMessageBox::Yes)
		{
			retry = true;
		}else
		{
			this->stopDlAsked = false;
			this->trayIcon->showMessage(a.applicationName(), tr("Download ") + aborted + "\n" + this->downloading.path, QSystemTrayIcon::Information);
		}
	}

	// disconnecting signals to slots
	disconnect(this->downloading.process, 0, 0, 0);

	// reset variables and window, close process
	this->downloading.process->close();
	ui->progressBar->hide();

	if (retry == false)
	{
		//QString filename = ui->listDownload->item(0)->text();
		//pos = filename.contains(" => ");
		//filename.resize(pos);
		delete ui->listDownload->takeItem(0);
	}
	this->downloading.clear();

	// Some downloads staying in queue
	if (ui->listDownload->count() != 0)
	{
		// initializing download
		path = ui->listDownload->item(0)->text();
		pos = path.lastIndexOf("/");
		this->downloading.service = path.mid(pos+1);
		path.resize(pos);
		pos = path.lastIndexOf(":");
		this->downloading.port = path.mid(pos+1).toUInt();
		path.resize(pos);
		pos = path.lastIndexOf(" => ");
		this->downloading.server = path.mid(pos+4);
		path.resize(pos);
		//this->downloading.port = this->settings.value("connexion/Servers/" + this->downloading.server + "/port").toInt();
		this->downloading.path = path;

		//getUserPassword(true);
		testServerPresence(this->downloading.service, true);

		// savepath exists in settings ?
		str = "Folder/" + this->downloading.server + ":" + QByteArray::number(this->downloading.port) + "/" + this->downloading.service;
		if (this->settings.contains(str))
		{
			// setting savepath from saved settings
			this->downloading.savePath = this->settings.value(str).toString();
			sleep(2);
			startDownloading();
		}else
		{
			// no save path
			if(!on_DefaultSaveFolder_triggered())
			{
				cout << "Error no save path so removing download";
				return;
			}
		}
	}
	if(config.autosaveCheckbox->checkState() == Qt::Checked and this->downloading.quit == false)
	{
		saveDownloadList();
	}
}


// Slot activated when a line is clicked in queue list
void MainWindow::on_listDownload_itemClicked(QListWidgetItem *item)
{
	QMessageBox::StandardButton reply;

	info(DEBUGMACRO, "on_listDownload_itemClicked() => Slot activated when a line is clicked in queue list");

	if (item->listWidget()->row(item) == 0)
	{
		// first line clicked on download list
		reply = QMessageBox::question(
		this,
		a.applicationName(),
		tr("Do you want to stop downloading and delete this file from download queue ?"),
		QMessageBox::Yes|QMessageBox::No,
		QMessageBox::No);
		if (reply == QMessageBox::Yes)
		{
			// stopping download
			this->stopDlAsked = true;
			emit (stopDownloading(this->downloading.process));
		}
	}else
	{
		// not first line on download list
		reply = QMessageBox::question(
		this,
		a.applicationName(),
		tr("Do you want to delete this file from download queue ?"),
		QMessageBox::Yes|QMessageBox::No,
		QMessageBox::No);
		if (reply == QMessageBox::Yes)
		{
			// removing line from download list
			ui->listDownload->removeItemWidget(item);
			delete item;
		}
	}
	if (config.autosaveCheckbox->checkState() == Qt::Checked)
	{
		// autosave acivated,so saving download list
		saveDownloadList();
	}
}

// load settings
void MainWindow::loadSettings()
{
	info(DEBUGMACRO, "loadSettings() => restoring geometry and state of window and widgets");
	// restoring geometry and state of window and widgets
	this->restoreGeometry(this->settings.value("window/geometry").toByteArray());
	this->restoreState(this->settings.value("window/state").toByteArray());
	ui->treeWidget->header()->restoreState(this->settings.value("treeWidget/state").toByteArray());
	ui->splitter->restoreState(this->settings.value("splitter/state").toByteArray());
	ui->splitter_2->restoreState(this->settings.value("splitter2/state").toByteArray());
	ui->toolBar->setToolButtonStyle((Qt::ToolButtonStyle)this->settings.value("toolbar/state").toInt());
	if (this->settings.value("Autosave").toInt() == Qt::Checked)
	{
		this->config.autosaveCheckbox->setChecked(true);
	}
	// loading connexion settings
	// loading servers history
	info(DEBUGMACRO, "Restoring server combobox history");
	this->settings.beginGroup("connexion/Servers");
	QStringList servers = this->settings.allKeys();
	this->settings.endGroup();
	ui->khistorycombobox->insertItems(1,this->settings.value("kHistoryComboBox").toStringList());

	// loading save path
	this->downloading.savePath = this->settings.value("Folder").toString();

	// loading bandwidth limit
	this->connexion.bandwidthLimit = this->settings.value("bandwidthlimit").toUInt();
	this->connexion.bandwidthLimitUnit = this->settings.value("bandwidthlimitunit").toInt();
}

// save settings
void MainWindow::saveSettings()
{
	info(DEBUGMACRO, "saveSettings() => Saving settings");

	this->settings.setValue("window/geometry", saveGeometry());
	this->settings.setValue("window/state", saveState());
	this->settings.setValue("treeWidget/state", ui->treeWidget->header()->saveState());
	this->settings.setValue("splitter/state", ui->splitter->saveState());
	this->settings.setValue("splitter2/state", ui->splitter_2->saveState());
	this->settings.setValue("connexion/lastServer", this->connexion.server);
	this->settings.setValue("connexion/lastPort", QString::number(this->connexion.port));
	this->settings.setValue("connexion/lastIpversion", QString::number(this->connexion.ipversion));
	this->settings.setValue("toolbar/state", ui->toolBar->toolButtonStyle());
	this->settings.setValue("Autosave", this->config.autosaveCheckbox->checkState());
	this->settings.setValue("kHistoryComboBox", ui->khistorycombobox->historyItems());
	this->settings.sync();
}

// About
void MainWindow::on_actionAbout_triggered()
{
	info(DEBUGMACRO, "on_actionAbout_triggered() => display about informations");

	aboutDialog.show();
}

// About QT
void MainWindow::on_actionAbout_Qt_triggered()
{
	info(DEBUGMACRO, "on_actionAbout_Qt_triggered() => display QT about information");

	QMessageBox::aboutQt(this);
}

// Activated when menu "change folder" is clicked
bool MainWindow::on_DefaultSaveFolder_triggered()
{
	QFileDialog dialog;
	QString folder;
	QString path;
	QString dir;

	info(DEBUGMACRO, "on_DefaultSaveFolder_triggered() => Activated when menu 'change folder' is clicked");

	// if service not selected display a message
	if (this->connexion.service.isEmpty() or this->connexion.server.isEmpty())
	{
		 warning(tr("You need to select a service before you can select a folder"));
		 return false;
	}

	// Asking for directory to save files
	folder = "Folder/" + this->connexion.server  + ":" + QByteArray::number(this->connexion.port )+ "/" + this->connexion.service;
	path = this->settings.value(folder).toString();
	info(DEBUGMACRO, "Path = " + path);
	dir = dialog.getExistingDirectory(this, tr("Choose folder where to save file"), path, QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
	if (!dir.isEmpty())
	{
		 this->downloading.savePath = dir;
		// saving save path in settings
		this->settings.setValue(folder, this->downloading.savePath);
		this->settings.sync();

	}else
	{
		 return false;
	}
	return true;
}

// Activated when menu "settings" is clicked
void MainWindow::on_action_Settings_triggered()
{
	info(DEBUGMACRO, "on_action_Settings_triggered() => Activated when menu 'settings' is clicked");

	config.UnitCombobox->setCurrentIndex(this->connexion.bandwidthLimitUnit);
	config.spinBox->setValue(this->connexion.bandwidthLimit);
	Configuration.show();
}

// Acivated when "Ok" is clicked in Configuration window
void MainWindow::on_buttonBox_accepted()
{
	QString unit;
	QString bw;

	info(DEBUGMACRO, "on_buttonBox_accepted() => Acivated when 'Ok' is clicked in Configuration window");

	bw = config.spinBox->text();
	if (bw.toInt() == 0)
	{
		// bandwidth = 0
		this->connexion.bandwidthLimit = 0;
		this->connexion.bandwidthLimitUnit = 0;
	}else
	{
		this->connexion.bandwidthLimit = config.spinBox->value();
		this->connexion.bandwidthLimitUnit = config.UnitCombobox->currentIndex();
	}
	this->settings.setValue("bandwidthlimit", this->connexion.bandwidthLimit);
	this->settings.setValue("bandwidthlimitunit", this->connexion.bandwidthLimitUnit);

	this->settings.setValue("Autosave", this->config.autosaveCheckbox->checkState());

	this->settings.sync();
	Configuration.hide();
}

// Saving download list
void MainWindow::saveDownloadList()
{
	int nRows;

	info(DEBUGMACRO, "saveDownloadList() => Saving download list");
	// remove list of downloads
	this->settings.remove("Downloads/");

	// Saving list of current downloads
	nRows = ui->listDownload->count();
	this->settings.beginGroup("Downloads");
	this->settings.setValue("rows", nRows);
	for (int i = 0; i < nRows; i++)
	{
		this->settings.setValue(QString::number(i), ui->listDownload->item(i)->text());
	}
	this->settings.endGroup();
	this->settings.sync();
}

// Loading download list
void MainWindow::loadDownloadList()
{
	QString path;
	QString str;
	int pos;

	info(DEBUGMACRO, "loadDownloadList() => loading download list");

	this->settings.sync();
	this->settings.beginGroup("Downloads");
	int size = this->settings.value("rows").toInt();
	for (int i = 0; i < size; ++i)
	{
		ui->listDownload->addItem(this->settings.value(QString::number(i)).toString());
	}
	this->settings.endGroup();

	path = ui->listDownload->item(0)->text();
	pos = path.lastIndexOf("/");
	this->downloading.service = path.mid(pos+1);
	path.resize(pos);
	pos = path.lastIndexOf(" => ");
	this->downloading.server = path.mid(pos+4);
	this->downloading.port = this->settings.value("connexion/Servers/" + this->downloading.server+ "/port").toInt();
	path.resize(pos);
	this->downloading.path = path;
	str = "Folder/" + this->downloading.server + ":" + QByteArray::number(this->downloading.port) + "/" + this->downloading.service;
	if (this->settings.contains(str))
	{
		this->downloading.savePath = this->settings.value(str).toString();
	}
	startDownloading();
}

// Deleting download list
void MainWindow::deleteDownloadList()
{
	info(DEBUGMACRO, "deleteDownloadList() => Deleting existing download list");
	this->settings.remove("Downloads");
}

// clear object downloading
void Connexion::clear()
{
	info(DEBUGMACRO, "clear() => clear object 'downloading'");

	this->path.clear();
	this->server.clear();
	this->savePath.clear();
	this->service.clear();
	this->user.clear();
	this->password.clear();
	this->port = 0;
	this->process = nullptr;
	this->quit = false;
}

// Context menu of file list clicked
void MainWindow::on_actionDownload_triggered()
{
	// action made in qt-designer and added in init function.
	QTreeWidgetItem *item;
	item = ui->treeWidget->currentItem();
	on_treeWidget_itemClicked(item, true);
}

// Change toolbar style
void MainWindow::on_comboBox_currentIndexChanged(int index)
{
	info(DEBUGMACRO, "on_comboBox_currentIndexChanged()");

	ui->toolBar->setToolButtonStyle((Qt::ToolButtonStyle)index);
}

void MainWindow::on_actionExit_triggered()
{
	info(DEBUGMACRO, "on_actionExit_triggered() => slot activated when button exit clicked");

	this->exiting = true;
	quitApp();
}

void MainWindow::setDlSpeed(QString speed)
{
	info(DEBUGMACRO, "setDlSpeed(= => setting download speed");

	speed.squeeze();
}

void MainWindow::on_actionHiddenService_triggered()
{
	QInputDialog hiddenFolderDialog;

	info(DEBUGMACRO, "on_actionHiddenService_triggered() => activated when the 'hidden service' button");

	bool ok;
	QString text = QInputDialog::getText(this, a.applicationName() + tr(" Request"),
	tr("Hidden service name"), QLineEdit::Normal,
	"test", &ok);
	if (ok && !text.isEmpty())
	{
		this->connexion.service = text;
		this->settings.setValue("Hidden/" + this->connexion.server + '/' + text, true);
		ui->listWidget->addItem(text + "\n\t");
		preparePopulateTree();
	}
}

void MainWindow::on_treeWidget_itemDoubleClicked(QTreeWidgetItem *item, int column)
{
	(void) item;
	(void) column;
}


void MainWindow::on_treeWidget_doubleClicked(const QModelIndex &index)
{
	(void) index;
}


void MainWindow::on_actionPause_downloads_triggered()
{
	quint64 processID = this->downloading.process->processId();
	QString fileStr = "/proc/" + QString::number(processID) + "/task/" + QString::number(processID) + "/children";
	static QMessageBox msgBox;

	//msgBox = new QMessageBox(this);
	msgBox.setIcon( QMessageBox::Warning );
	msgBox.setText("Download suspended");
	//QPushButton *btnCancel =  msgBox->addButton( "Cancel", QMessageBox::RejectRole );
	//msgBox.setAttribute(Qt::WA_DeleteOnClose); // delete pointer after close
	msgBox.setModal(false);

	info (DEBUGMACRO, "downloading state : " + QString::fromUtf8((this->downloading.paused==0)?"running":"paused"));
	info (DEBUGMACRO, "Downloading process ID : " + QString::number(processID));
	info (DEBUGMACRO, fileStr);

	QFile file(fileStr);
	if(!file.open(QIODevice::ReadOnly))
	{
		QMessageBox::information(0, "error", file.errorString());
	}

	QTextStream in(&file);
	QString children = in.readLine();
	info (DEBUGMACRO, "Child process is : " + children);
	if (this->downloading.paused)
	{
		info(DEBUGMACRO, "resuming Download");
		if (kill(children.toLongLong(), SIGCONT))
		{
			info(DEBUGMACRO, "resuming failed : " + QString::number(errno));
		}

		if (msgBox.isVisible())
		{
			msgBox.close();
		}
		this->downloading.paused = false;
	}else
	{
		info(DEBUGMACRO, "pausing Download");
		if (kill(children.toLongLong(), SIGTSTP))
		{
			info(DEBUGMACRO, "resuming failed : " + QString::number(errno));
		}

		msgBox.show();

		this->downloading.paused = true;
	}
}
