1036 lines
33 KiB
C++
1036 lines
33 KiB
C++
#include "mainwindow.h"
|
|
#include <QComboBox>
|
|
|
|
using namespace std;
|
|
|
|
bool display = false;
|
|
//extern QDialog Configuration;
|
|
extern Ui::Configuration config;
|
|
extern bool testRsyncReturn(QProcess *);
|
|
|
|
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)
|
|
{
|
|
QAbstractButton * reply;
|
|
QMessageBox msgBox;
|
|
ui->setupUi(this);
|
|
|
|
QCoreApplication::setOrganizationName("RsyncUI");
|
|
QCoreApplication::setApplicationName("RsyncUI");
|
|
|
|
// context menu for treewidget (list of files)
|
|
ui->treeWidget->addAction(ui->actionDownload);
|
|
|
|
// init configuration window
|
|
config.setupUi(&Configuration);
|
|
|
|
// init of About
|
|
this->about.description = tr("Client for rsync server\n\nYou click on file to enqueue it, and RyncUI Download one file a time");
|
|
|
|
// connectors
|
|
connect(this, &MainWindow::progressSignal, ui->progressBar, &QProgressBar::setValue);
|
|
//connect(this, &MainWindow::errorSignal, this, &MainWindow::downloadingErrorSlot);
|
|
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);
|
|
|
|
// 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")} ); // set header of columns of tree widget
|
|
|
|
// if last server exists in settings
|
|
if (this->settings.contains("connexion/lastServer"))
|
|
{
|
|
// set window to precedent server/port configuration
|
|
ui->portEdit->setText(this->settings.value("connexion/port").toString());
|
|
ui->khistorycombobox->setCurrentText(this->settings.value("connexion/lastServer").toString());
|
|
}else
|
|
{
|
|
ui->portEdit->text() = QString::number(this->connexion.port);
|
|
ui->khistorycombobox->clear();
|
|
}
|
|
|
|
// setting arrowcursor for treeWidget, listWidget and listDownload to arrow
|
|
ui->treeWidget->setCursor(Qt::ArrowCursor);
|
|
ui->listWidget->setCursor(Qt::ArrowCursor);
|
|
ui->listDownload->setCursor(Qt::ArrowCursor);
|
|
|
|
// Hiding progress bar
|
|
ui->progressBar->hide();
|
|
|
|
loadSettings();
|
|
|
|
//setting configuration window
|
|
config.comboBox->setCurrentIndex(ui->toolBar->toolButtonStyle()); // setting combobox to saved settings
|
|
|
|
//setting unit of bandwidth limit
|
|
config.UnitCombobox->addItems({tr("KB"), tr("MB"), tr("GB"), tr("TB"), tr("PB")});
|
|
|
|
//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("RsyncUI");
|
|
msgBox.setInformativeText(tr("A list of interrupted downloads exists, do you want to continue downloading ? if not the list will be cleared" ));
|
|
|
|
QPushButton *yes = msgBox.addButton(QMessageBox::Yes);
|
|
msgBox.addButton(QMessageBox::No);
|
|
msgBox.setDefaultButton(QMessageBox::Yes);
|
|
|
|
msgBox.exec();
|
|
reply = msgBox.clickedButton();
|
|
|
|
// if response is yes then loading list
|
|
if(reply == yes)
|
|
{
|
|
loadDownloadList();
|
|
}
|
|
}
|
|
// load list of services
|
|
populateList();
|
|
initSystemTrayIcon();
|
|
}
|
|
|
|
void MainWindow::initSystemTrayIcon()
|
|
{
|
|
QMenu *trayIconMenu;
|
|
QAction * quitAction;
|
|
|
|
this->trayIcon = new QSystemTrayIcon;
|
|
this->trayIcon->setIcon(this->windowIcon());
|
|
|
|
quitAction = new QAction(tr("&Quit"), this);
|
|
connect(quitAction, &QAction::triggered, this, &MainWindow::quitApp);
|
|
|
|
trayIconMenu = new QMenu(this);
|
|
trayIconMenu->addAction(quitAction);
|
|
trayIcon->setContextMenu(trayIconMenu);
|
|
|
|
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)
|
|
{
|
|
if (reason == QSystemTrayIcon::Trigger)
|
|
{
|
|
if (this->isHidden())
|
|
{
|
|
this->show();
|
|
}else
|
|
{
|
|
this->hide();
|
|
}
|
|
}
|
|
}
|
|
|
|
void MainWindow::hideWindow()
|
|
{
|
|
this->hide();
|
|
}
|
|
|
|
void MainWindow::showWindow()
|
|
{
|
|
this->show();
|
|
}
|
|
|
|
MainWindow::~MainWindow()
|
|
{
|
|
delete ui;
|
|
QCoreApplication::quit();
|
|
}
|
|
|
|
void MainWindow::quitApp()
|
|
{
|
|
QMessageBox::StandardButton reply;
|
|
QMessageBox::StandardButtons param;
|
|
QString displayText;
|
|
|
|
// saving settings
|
|
saveSettings();
|
|
|
|
if (ui->listDownload->count() != 0) // some downloads waiting
|
|
{
|
|
// 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,
|
|
"RsyncUI",
|
|
tr("Exiting will stop downloading, and will clear the download queue.\nDo you want to exit ?") + displayText,
|
|
param,
|
|
QMessageBox::No);
|
|
|
|
if(reply == QMessageBox::Yes)
|
|
{
|
|
// emission of signal to downloading thread and stopping
|
|
emit (stopDownloading(this->downloading.process));
|
|
}else
|
|
{
|
|
saveDownloadList();
|
|
}
|
|
}
|
|
delete ui;
|
|
QCoreApplication::quit();
|
|
}
|
|
|
|
// Close window has been clicked
|
|
void MainWindow::closeEvent (QCloseEvent *event)
|
|
{
|
|
QMessageBox msgBox;
|
|
QCheckBox *cb = new QCheckBox("Don't show this again ?");
|
|
QAbstractButton * reply;
|
|
|
|
if (!event->spontaneous() || !isVisible())
|
|
return;
|
|
if (trayIcon->isVisible() and this->settings.value("CloseCheckbox").toBool() == false)
|
|
{
|
|
msgBox.setWindowTitle("RsyncUI");
|
|
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.addButton(QMessageBox::No);
|
|
// msgBox.setDefaultButton(QMessageBox::Yes);
|
|
msgBox.setCheckBox(cb);
|
|
msgBox.exec();
|
|
reply = 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(QTreeWidgetItem * parent)
|
|
{
|
|
QString path;
|
|
|
|
// 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);
|
|
|
|
// validating server's address
|
|
if (validateServer(this->connexion.server))
|
|
{
|
|
// server is validated
|
|
path = ui->listWidget->currentItem()->text().section('\n', 0, 0) + "/";
|
|
scanDir(this->connexion.server, this->connexion.port, parent, path);
|
|
}
|
|
// Restoring cursor
|
|
QGuiApplication::restoreOverrideCursor();
|
|
}
|
|
}
|
|
|
|
// Populate Listview with list of services
|
|
void MainWindow::populateList()
|
|
{
|
|
QString server;
|
|
int port;
|
|
|
|
server = ui->khistorycombobox->currentText();
|
|
port = ui->portEdit->text().toUInt();
|
|
if ((server != this->connexion.server) or (port != this->connexion.port))
|
|
{
|
|
// clearing listwidget
|
|
ui->listWidget->clear();
|
|
|
|
this->connexion.server = server;
|
|
this->connexion.port = port;
|
|
|
|
// setting cursor to "Wait"
|
|
QGuiApplication::setOverrideCursor(Qt::WaitCursor);
|
|
|
|
// verify if server is in history
|
|
this->settings.beginGroup("connexion/server");
|
|
if (this->settings.contains(server) and this->connexion.comboboxChanged)
|
|
{
|
|
// server is in history => setting port value
|
|
port = this->settings.value(server).toUInt();
|
|
ui->portEdit->setText(QString::number(port));
|
|
this->connexion.port = port;
|
|
|
|
//display list of services
|
|
listServices();
|
|
}else
|
|
{
|
|
if (!server.isEmpty() and (port > 0 and port < 65536))
|
|
{
|
|
if (validateServer(server))
|
|
{
|
|
cout << server.toStdString() << endl;
|
|
|
|
// storing serverURL and port in settings
|
|
this->settings.setValue(server, port);
|
|
this->settings.sync();
|
|
this->downloading.server = server;
|
|
|
|
// storing in history of combobox
|
|
ui->khistorycombobox->addToHistory(server);
|
|
|
|
// load and display rsync services of the rsync server
|
|
listServices();
|
|
}
|
|
}
|
|
}
|
|
this->settings.endGroup();
|
|
QGuiApplication::restoreOverrideCursor(); //setting cursor to default
|
|
}
|
|
}
|
|
|
|
//list services of the rsync server
|
|
void MainWindow::listServices()
|
|
{
|
|
QString cmd;
|
|
QStringList param;
|
|
QString line;
|
|
QString errorRsync;
|
|
QStringList v;
|
|
QString service;
|
|
QProcess *myProcess;
|
|
bool flag = false;
|
|
|
|
cmd = "/usr/bin/rsync";
|
|
param << "--contimeout=10" << "--port=" + QString::number(this->connexion.port) << this->connexion.server + "::";
|
|
myProcess = new QProcess(this);
|
|
myProcess->start(cmd, param);
|
|
|
|
// waiting for response of the server with a timeout of 10 seconds
|
|
while(myProcess->waitForReadyRead(10000))
|
|
{
|
|
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;
|
|
}
|
|
// 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];
|
|
|
|
// adding to list of services
|
|
ui->listWidget->addItem(service);
|
|
}
|
|
// buffer empty go to waiting new datas
|
|
flag =false;
|
|
}
|
|
|
|
// verifying error code
|
|
testRsyncReturn(myProcess);
|
|
}
|
|
|
|
// connect to rsync server to get list of files
|
|
void MainWindow::scanDir(QString server, int portN, QTreeWidgetItem *parent, QString path)
|
|
{
|
|
QString cmd;
|
|
QStringList param;
|
|
QString line;
|
|
QString size;
|
|
QString filename;
|
|
QTreeWidgetItem * item;
|
|
QProcess * myProcess;
|
|
bool isDir = false;
|
|
bool flag = false;
|
|
|
|
cmd = "rsync";
|
|
param << "--contimeout=10" << "--port=" + QString::number(portN) << server + "::" + path;
|
|
|
|
myProcess = new QProcess(this);
|
|
myProcess->start(cmd, param);
|
|
|
|
// waiting for response of the server with a timeout of 10 seconds
|
|
while(myProcess->waitForReadyRead(100000))
|
|
{
|
|
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;
|
|
}
|
|
// extracting name, size and is dir/file
|
|
line = line.simplified();
|
|
size = line.section(" ", 1, 1);
|
|
filename = line.section(" ", 4);
|
|
if (filename != '.')
|
|
{
|
|
if (line[0] == "d")
|
|
{
|
|
isDir = true;
|
|
}else
|
|
{
|
|
isDir = false;
|
|
}
|
|
if (parent != NULL)
|
|
{
|
|
//adding item to tree
|
|
item = addTreeChild(parent, filename, size, isDir);
|
|
}else
|
|
{
|
|
//adding item to tree (as directory)
|
|
item = addTreeRoot(filename, size, isDir);
|
|
}
|
|
}
|
|
}
|
|
|
|
flag = false;
|
|
}
|
|
// buffer empty go to waiting new datas
|
|
testRsyncReturn(myProcess);
|
|
}
|
|
|
|
// Verify if server address is IP address
|
|
bool MainWindow::isIpAddress(QString server)
|
|
{
|
|
QStringList r;
|
|
int elementN;
|
|
bool ok;
|
|
|
|
r = server.split('.');
|
|
if (r.size() == 4)
|
|
{
|
|
for (auto element : r)
|
|
{
|
|
elementN = element.toInt(&ok);
|
|
if (elementN < 0 or elementN > 255 or ok == false)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// validate address server
|
|
bool MainWindow::validateServer(QString server)
|
|
{
|
|
QString cmd;
|
|
QStringList param;
|
|
QString line;
|
|
QProcess * myProcess;
|
|
bool flag = false;
|
|
bool bflag = false;
|
|
|
|
cmd = "dig";
|
|
param << server;
|
|
|
|
myProcess = new QProcess(this);
|
|
myProcess->start(cmd, param);
|
|
|
|
// maiking a dig on the server's address
|
|
while(myProcess->waitForReadyRead())
|
|
{
|
|
while (!bflag)
|
|
{
|
|
line = QString::fromUtf8(myProcess->readAllStandardOutput());
|
|
// line empty then buffer is empty so returning to wait new datas
|
|
if (line.isEmpty())
|
|
{
|
|
bflag = true;
|
|
break;
|
|
}else if (line.indexOf(";; ANSWER SECTION:") != -1)
|
|
{
|
|
flag = true;
|
|
}
|
|
}
|
|
bflag = false;
|
|
}
|
|
|
|
//testRsyncReturn(myProcess);
|
|
|
|
if ( flag == false)
|
|
{
|
|
//server's address is not valid testing if ip address is valid
|
|
flag = isIpAddress(server);
|
|
}
|
|
if ( flag == false)
|
|
{
|
|
// server-s address not valid
|
|
QMessageBox::warning(
|
|
this,
|
|
"RsyncUI",
|
|
tr("server does not exists" )
|
|
);
|
|
}
|
|
return flag;
|
|
}
|
|
|
|
// slot activated when combobox is changed
|
|
void MainWindow::on_khistorycombobox_currentIndexChanged(int i)
|
|
{
|
|
this->connexion.comboboxChanged = true;
|
|
populateList();
|
|
}
|
|
|
|
// slot activated when button connection is clicked
|
|
void MainWindow::on_connectButton_clicked()
|
|
{
|
|
populateList();
|
|
}
|
|
|
|
// add a dir in treeview
|
|
QTreeWidgetItem * MainWindow::addTreeRoot(QString name, QString fileSize, bool isDir)
|
|
{
|
|
QTreeWidgetItem *treeItem = new QTreeWidgetItem(ui->treeWidget);
|
|
|
|
if (isDir == true)
|
|
{
|
|
// item is a dir
|
|
treeItem->setText(1, tr("Dir"));
|
|
}else
|
|
{
|
|
// item is a file
|
|
treeItem->setText(1,tr("File"));
|
|
}
|
|
treeItem->setText(0, name);
|
|
treeItem->setText(2, fileSize);
|
|
|
|
return treeItem;
|
|
}
|
|
|
|
// add a file in treeview
|
|
QTreeWidgetItem * MainWindow::addTreeChild(QTreeWidgetItem *parent, QString name, QString fileSize, bool isDir)
|
|
{
|
|
QTreeWidgetItem *treeItem = new QTreeWidgetItem();
|
|
|
|
if (isDir == true)
|
|
{
|
|
// item is a dir
|
|
treeItem->setText(1, tr("Dir"));
|
|
}else
|
|
{
|
|
// item is a file
|
|
treeItem->setText(1,("File"));
|
|
}
|
|
treeItem->setText(0, name);
|
|
treeItem->setText(2, fileSize);
|
|
|
|
// QTreeWidgetItem::addChild(QTreeWidgetItem * child)
|
|
parent->addChild(treeItem);
|
|
return treeItem;
|
|
}
|
|
|
|
// Slot acivated when a service in the list is clicked
|
|
void MainWindow::on_listWidget_clicked()
|
|
{
|
|
QString str;
|
|
|
|
this->connexion.service = ui->listWidget->currentItem()->text().section("\n", 0 ,0);
|
|
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(NULL);
|
|
}
|
|
|
|
//Slot activated when a file is clicked in the treeview
|
|
void MainWindow::on_treeWidget_itemClicked(QTreeWidgetItem *item, bool downloadDir)
|
|
{
|
|
QFuture<void> future;
|
|
QFileDialog dialog;
|
|
QTreeWidgetItem * itemR;
|
|
QString path;
|
|
QString str;
|
|
QMessageBox::StandardButton reply;
|
|
|
|
itemR = item;
|
|
|
|
// assembling path from treewidget
|
|
path = item->text(0);
|
|
|
|
// exists saving path in settings ?
|
|
str = "Folder/" + this->connexion.server + "/" + this->connexion.service;
|
|
if(!this->settings.contains(str))
|
|
{
|
|
// saving path do not exists, asking for it
|
|
if(!on_DefaultSaveFolder_triggered())
|
|
{
|
|
cout << "no directory selectioned, ignoring download request";
|
|
return;
|
|
}
|
|
}else
|
|
{
|
|
this->downloading.savePath = this->settings.value(str).toString();
|
|
}
|
|
|
|
|
|
while(itemR->parent() != NULL)
|
|
{
|
|
itemR = itemR->parent();
|
|
// concatening parent to path
|
|
path.prepend(itemR->text(0) + "/");
|
|
};
|
|
|
|
if (item->text(1) == tr("File") or downloadDir == true)
|
|
{
|
|
// Item is a file
|
|
// searching if file exists in savepath
|
|
if (QFile::exists(this->downloading.savePath + "/" + path))
|
|
{
|
|
reply = QMessageBox::question(
|
|
this,
|
|
"RsyncUI",
|
|
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)
|
|
{
|
|
return;
|
|
}else
|
|
{
|
|
QFile::remove(this->downloading.savePath + "/" + path);
|
|
}
|
|
}
|
|
|
|
if(ui->listDownload->findItems(path, Qt::MatchStartsWith).empty())
|
|
{
|
|
// is there a downloading process ?
|
|
if (this->downloading.process == nullptr)
|
|
{
|
|
// no downloading process launching it
|
|
this->downloading.path = path;
|
|
this->downloading.server = this->connexion.server;
|
|
this->downloading.service = this->connexion.service;
|
|
startDownloading();
|
|
// wait 1 second to process start
|
|
//sleep(1);
|
|
}
|
|
|
|
// Adding download in download list
|
|
str = path + " => " + this->connexion.server + "/" + this->connexion.service;
|
|
ui->listDownload->addItem(str);
|
|
}else
|
|
{
|
|
QMessageBox::warning(
|
|
this,
|
|
"RsyncUI",
|
|
tr("File is already downloading" )
|
|
);
|
|
}
|
|
}else
|
|
{
|
|
//Item is a Directory
|
|
scanDir(this->connexion.server, this->connexion.port, item, this->connexion.service + "/" + path +"/");
|
|
item->setExpanded(true);
|
|
}
|
|
if (config.autosaveCheckbox->checkState() == Qt::Checked)
|
|
{
|
|
saveDownloadList();
|
|
}
|
|
}
|
|
|
|
// Launch the thread which download the file
|
|
void MainWindow::startDownloading()
|
|
{
|
|
ui->progressBar->setValue(0);
|
|
ui->progressBar->show();
|
|
|
|
//QtConcurrent::run(&this->downloadO, &downloadFile::download, this);
|
|
download();
|
|
}
|
|
|
|
// Slot stopping download
|
|
void MainWindow::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;
|
|
|
|
// test if process crashed
|
|
if (exitStatus == QProcess::CrashExit)
|
|
{
|
|
QMessageBox::warning(
|
|
NULL,
|
|
"RsyncUI",
|
|
tr("Rsync process crashed"));
|
|
}
|
|
//test result code of command (if 20 then command stopped by user)
|
|
if (exitCode != 0 and exitCode != 20)
|
|
{
|
|
// displaying warning with exit code
|
|
QMessageBox::warning(
|
|
NULL,
|
|
"RsyncUI",
|
|
rsyncErrorStrings[exitCode]);
|
|
}
|
|
|
|
// disconnecting signals to slots
|
|
disconnect(this->downloading.process, 0, 0, 0);
|
|
|
|
// reset variables and window
|
|
this->downloading.process = nullptr;
|
|
ui->progressBar->hide();
|
|
delete ui->listDownload->takeItem(0);
|
|
this->downloading.clear();
|
|
|
|
// Some downloads staying in queue
|
|
if (ui->listDownload->count() != 0)
|
|
{
|
|
// autosave is activated
|
|
if (config.autosaveCheckbox->checkState() == Qt::Checked)
|
|
{
|
|
// saving download list
|
|
saveDownloadList();
|
|
}
|
|
|
|
// 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.path = path;
|
|
|
|
// 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();
|
|
startDownloading();
|
|
}else
|
|
{
|
|
// no save path
|
|
if(!on_DefaultSaveFolder_triggered())
|
|
{
|
|
cout << "Error no save path so deleting download";
|
|
//downloadFinished();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
saveDownloadList();
|
|
}
|
|
|
|
|
|
// Slot activated when a line is clicked in queue list
|
|
void MainWindow::on_listDownload_itemClicked(QListWidgetItem *item)
|
|
{
|
|
QMessageBox::StandardButton reply;
|
|
|
|
if (item->listWidget()->row(item) == 0)
|
|
{
|
|
// first line clicked on download list
|
|
reply = QMessageBox::question(
|
|
this,
|
|
"RsyncUI",
|
|
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
|
|
emit (stopDownloading(this->downloading.process));
|
|
}
|
|
}else
|
|
{
|
|
// not first line on download list
|
|
reply = QMessageBox::question(
|
|
this,
|
|
"RsyncUI",
|
|
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()
|
|
{
|
|
// 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
|
|
this->settings.beginGroup("connexion/server");
|
|
QStringList servers = this->settings.allKeys();
|
|
this->settings.endGroup();
|
|
for( const QString &server : servers )
|
|
{
|
|
ui->khistorycombobox->addToHistory(server);
|
|
}
|
|
|
|
// 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()
|
|
{
|
|
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("toolbar/state", ui->toolBar->toolButtonStyle());
|
|
this->settings.setValue("Autosave", this->config.autosaveCheckbox->checkState());
|
|
this->settings.sync();
|
|
}
|
|
|
|
// About
|
|
void MainWindow::on_actionAbout_triggered()
|
|
{
|
|
QString text = this->about.description + "\n\n" +
|
|
tr("Version") + ": " + this->about.version + "\n" +
|
|
tr("Licence") + ": " + this->about.licence + "\n" +
|
|
tr("Author") + ": " + this->about.author + "\n" +
|
|
tr("EMail") + ": " + this->about.email + "\n" +
|
|
tr("Source code") + ": " + this->about.git;
|
|
QMessageBox::about(this, this->about.title, text);
|
|
}
|
|
|
|
// About QT
|
|
void MainWindow::on_actionAbout_Qt_triggered()
|
|
{
|
|
QMessageBox::aboutQt(this);
|
|
}
|
|
|
|
// Activated when menu "change folder" is clicked
|
|
bool MainWindow::on_DefaultSaveFolder_triggered()
|
|
{
|
|
QFileDialog dialog;
|
|
QString folder;
|
|
QString path;
|
|
|
|
// if service not selected display a message
|
|
if (this->connexion.service.isEmpty())
|
|
{
|
|
QMessageBox::warning(
|
|
NULL,
|
|
"RsyncUI",
|
|
tr("Since the save path is linked to service, you need to select a service before you can select a folder"));
|
|
return false;
|
|
}
|
|
|
|
// Asking for directory to save files
|
|
path = dialog.getExistingDirectory(this, tr("Choose folder where to save file"), QDir::homePath(), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
|
|
if (!path.isEmpty())
|
|
{
|
|
this->downloading.savePath = path;
|
|
if (!this->connexion.service.isEmpty() and !this->connexion.server.isEmpty())
|
|
{
|
|
// saving save path in settings
|
|
folder = "Folder/" + this->connexion.server + "/" + this->connexion.service;
|
|
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()
|
|
{
|
|
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;
|
|
|
|
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;
|
|
|
|
// 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;
|
|
|
|
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();
|
|
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();
|
|
}
|
|
|
|
// clear object downloading
|
|
void Downloading::clear()
|
|
{
|
|
this->path.clear();
|
|
this->server.clear();
|
|
this->savePath.clear();
|
|
this->service.clear();
|
|
}
|
|
|
|
// 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);
|
|
}
|
|
|
|
/*void MainWindow::downloadingErrorSlot(QString errorString)
|
|
{
|
|
QMessageBox::warning(
|
|
this,
|
|
"RsyncUI",
|
|
errorString,
|
|
QMessageBox::Ok,
|
|
QMessageBox::Ok);
|
|
}
|
|
*/
|
|
|
|
// Chnage toolbar style
|
|
void MainWindow::on_comboBox_currentIndexChanged(int index)
|
|
{
|
|
ui->toolBar->setToolButtonStyle((Qt::ToolButtonStyle)index);
|
|
}
|
|
|
|
void MainWindow::on_actionExit_triggered()
|
|
{
|
|
quitApp();
|
|
}
|