1621 lines
47 KiB
C++
1621 lines
47 KiB
C++
#include "mainwindow.h"
|
|
#include <QtGlobal>
|
|
//#include <QComboBox>
|
|
#include <QTextBlock>
|
|
#include "ui_configuration.h"
|
|
#include "version.h"
|
|
#include "tools.h"
|
|
#include "password.h"
|
|
#include <kcombobox.h>
|
|
|
|
/*
|
|
#include <klineedit.h>
|
|
#include <khistorycombobox.h>
|
|
#include <kcompletion.h>
|
|
*/
|
|
|
|
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.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 + "]::" + 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)
|
|
{
|
|
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;
|
|
|
|
info(DEBUGMACRO, "scandir() => connect to rsync server to get list of files");
|
|
|
|
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 + "]::" + 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
|
|
|
|
testRsyncReturn(this, myProcess);
|
|
myProcess->close();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// validate address server
|
|
uint MainWindow::validateServer(QString server)
|
|
{
|
|
QString cmd;
|
|
QStringList param;
|
|
QString line;
|
|
QProcess * myProcess;
|
|
QStringList responseList;
|
|
|
|
uint ipversion;
|
|
int answerFound = 0;
|
|
int queryPos = 0;
|
|
|
|
info(DEBUGMACRO, "ValidateServer() => Validating server address");
|
|
|
|
ipversion = whatIpVersion(server);
|
|
|
|
if (ipversion == 0) // not an Ip address, perhaps a server name
|
|
{
|
|
info(DEBUGMACRO, "Digging server name");
|
|
|
|
cmd = "dig";
|
|
param << server.trimmed() ;
|
|
param << "A"; // IP V4 query
|
|
param << server.trimmed() ;
|
|
param << "AAAA"; // IP V6 query
|
|
|
|
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(QRegExp("\\s+"));
|
|
info(DEBUGMACRO, "ip Address is => " + responseList.at(4));
|
|
if(responseList.at(3) == "A")
|
|
{
|
|
return 4;
|
|
}else if(responseList.at(3) == "AAAA")
|
|
{
|
|
return 6;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
myProcess->close();
|
|
}
|
|
info(DEBUGMACRO, "Returning ip version: " + QString::number(ipversion));
|
|
return ipversion;
|
|
|
|
return 0;
|
|
}
|
|
|
|
// slot activated when button connection is clicked
|
|
void MainWindow::on_connectButton_clicked()
|
|
{
|
|
QString server;
|
|
uint port;
|
|
|
|
info(DEBUGMACRO, "on_connectButton_clicked() => Connexion button clicked");
|
|
port = ui->portEdit->text().toUInt();
|
|
if (port > 0 and port < 65535)
|
|
{
|
|
server = ui->khistorycombobox->currentText();
|
|
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 + "/" + 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;
|
|
|
|
info(DEBUGMACRO, "on_treeWidget_itemClicked() => Slot activated when a file is clicked in the treeview");
|
|
|
|
if (this->treeviewClicked == true)
|
|
{
|
|
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 + "/" + 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 + "/" + 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 +"/");
|
|
scanDir(&this->connexion, item, this->connexion.service + "/" + path +"/");
|
|
item->setExpanded(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
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.midRef(pos+1).toString();
|
|
path.resize(pos);
|
|
pos = path.lastIndexOf(" => ");
|
|
this->downloading.server = path.midRef(pos+4).toString();
|
|
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 + "/" + 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 + "/" + 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.midRef(pos+1).toString();
|
|
path.resize(pos);
|
|
pos = path.lastIndexOf(" => ");
|
|
this->downloading.server = path.midRef(pos+4).toString();
|
|
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 + "/" + 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();
|
|
}
|
|
|
|
|
|
void MainWindow::on_treeWidget_doubleClicked(const QModelIndex &index)
|
|
{
|
|
void();
|
|
}
|
|
|