diff --git a/RsyncUI.pro.user b/RsyncUI.pro.user index 5d12286..2021afe 100644 --- a/RsyncUI.pro.user +++ b/RsyncUI.pro.user @@ -1,6 +1,6 @@ - + EnvironmentId @@ -141,7 +141,7 @@ true QtProjectManager.QMakeBuildStep - false + true @@ -183,7 +183,7 @@ true QtProjectManager.QMakeBuildStep - false + true @@ -292,8 +292,9 @@ 2 - Qt4ProjectManager.Qt4RunConfiguration:/home/daniel/develope/RsyncUI/RsyncUI.pro - /home/daniel/develope/RsyncUI/RsyncUI.pro + RsyncUI2 + Qt4ProjectManager.Qt4RunConfiguration:/home/daniel/develop/RsyncUI/RsyncUI.pro + /home/daniel/develop/RsyncUI/RsyncUI.pro false true true diff --git a/downloadfile.cpp b/downloadfile.cpp index 3de7369..8e6234e 100644 --- a/downloadfile.cpp +++ b/downloadfile.cpp @@ -14,6 +14,8 @@ #include #include #include +#include +#include using namespace std; @@ -21,66 +23,47 @@ downloadFile::downloadFile() { } -void downloadFile::cancelled() +void downloadFile::cancelled(int pid) { - this->canceled = true; + if (kill(pid, SIGTERM) == -1) + { + //TODO gestion erreur kill + } } -void downloadFile::download(QString savePath, MainWindow *mw) +void downloadFile::download(MainWindow *mw) { - string server; - string service; - string path; string line; string errorRsync; - char cmd[4096]; - int portN; int pos; - int pid; - QTreeWidgetItem * item; + array argv; stringstream output; - // QString savePath = "."; vector v; int value; - //char command_out[1024] = {0}; - array buffer; + char buffer[4096]; + argv[0] = "/usr/bin/rsync"; + argv[1] = "--bwlimit=" + mw->connexion.bandwidthLimit; + argv[2] = "--port=" + to_string(mw->connexion.port); + argv[3] = "-P"; + argv[4] = mw->connexion.server + "::" + mw->downloading.service + "/" + mw->downloading.path; + argv[5] = mw->downloading.savePath + "/"; - server.assign(mw->ui->khistorycombobox->currentText().toStdString()); - portN = mw->ui->portEdit->text().toInt(); - service = mw->ui->listWidget->currentItem()->text().toStdString(); - pos = service.find_first_of('\n'); - service.resize(pos); - - item = mw->ui->treeWidget->currentItem(); - path = item->text(0).toStdString(); - while(item->parent() != NULL) - { - item = item->parent(); - path = item->text(0).toStdString() + "/" + path; - - }; - - - sprintf(cmd, "rsync --bwlimit=100K --port %i -P %s::\"%s/%s\" \"%s/\" 2>&1", portN, server.c_str(), service.c_str(), path.c_str(), savePath.toStdString().c_str()); - - - - //unique_ptr pipe(popen(cmd, "r"), pclose); - FILE * fp = popen2(cmd, "r", pid); + //unique_ptr pipe(popen(cmd "r"), pclose); + FILE * fp = popen2(argv, "r", mw->downloading.pid); if (!fp) { throw runtime_error("popen2() failed!"); + return; } - while (fgets(buffer.data(), buffer.size(), fp) != nullptr) + while (fgets(buffer, 4096, fp) != nullptr) { - buffer.data(); if (this->canceled == true) { return; } - line = buffer.data(); + line = buffer; //cout << line << endl; pos = line.find('%'); if (pos != -1) @@ -95,9 +78,10 @@ void downloadFile::download(QString savePath, MainWindow *mw) emit progressSignal(value); } } - buffer.empty(); } - + pclose2(fp, mw->downloading.pid); + emit progressSignal(100); + emit finishedSignal(true); //cout << path << endl; } diff --git a/downloadfile.h b/downloadfile.h index ed85adf..130db1e 100644 --- a/downloadfile.h +++ b/downloadfile.h @@ -11,14 +11,15 @@ class downloadFile : public QObject Q_OBJECT public: downloadFile(); - void download(QString savePath, MainWindow *parent = nullptr); + void download(MainWindow *parent = nullptr); bool canceled; signals: void progressSignal(int); + void finishedSignal(bool = true); public slots: - void cancelled(); + void cancelled(int pid); }; #endif // DOWNLOADFILE_H diff --git a/main.cpp b/main.cpp index 115a22b..21122c2 100644 --- a/main.cpp +++ b/main.cpp @@ -1,5 +1,6 @@ #include "mainwindow.h" #include +#include int main(int argc, char *argv[]) { diff --git a/mainwindow.cpp b/mainwindow.cpp index 5799f9c..3237198 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -19,6 +20,9 @@ #include #include #include +#include +#include +#include using namespace std; @@ -29,67 +33,85 @@ MainWindow::MainWindow(QWidget *parent) , ui(new Ui::MainWindow) { ui->setupUi(this); + connect(&downloadO, &downloadFile::progressSignal, ui->progressBar, &QProgressBar::setValue); + connect(&downloadO, &downloadFile::finishedSignal, this, &MainWindow::downloadFinished); + connect(this, &MainWindow::stopDownloading, &downloadO, &downloadFile::cancelled); + ui->ktreewidgetsearchline->setTreeWidget(ui->treeWidget); ui->ktreewidgetsearchline->setCaseSensitivity(Qt::CaseInsensitive); ui->treeWidget->setHeaderLabels({tr("Path"), tr("Size")} ); ui->progressBar->hide(); + loadSettings(); + populateList(); + } MainWindow::~MainWindow() { + QMessageBox::StandardButton reply; + + + if (ui->listDownload->count() != 0) + { + reply = QMessageBox::question( + this, + "RsyncUI", + tr("Exiting will stop downloading, and will clear the download queue.\n Do you want to exit ?"), + QMessageBox::Yes|QMessageBox::No, + QMessageBox::No); + if (reply == QMessageBox::Yes) + { + emit (stopDownloading(this->downloading.pid)); + } + } + if (this->downloading.pid != 0) + { + waitpid(this->downloading.pid, NULL, WUNTRACED); + } delete ui; } void MainWindow::populateTree() { - string server; - string port; - int portN; stringstream ss; vector path; - server.assign(ui->khistorycombobox->currentText().toStdString()); - port.assign(ui->portEdit->text().toStdString()); - ss << port; - ss >> portN; - if (!server.empty() and !port.empty() and portN < 65536) + if (!this->connexion.server.empty() and this->connexion.port > 0 and this->connexion.port < 65536) { - if (validateServer(server)) + if (validateServer(this->connexion.server)) { - ui->treeWidget->cursor().setShape(Qt::WaitCursor); + QGuiApplication::setOverrideCursor(Qt::WaitCursor); path = explode(ui->listWidget->currentItem()->text().toStdString(), '\n', 2); - scanDir(server, portN, NULL, path[0].append("/") ); - ui->treeWidget->cursor().setShape(Qt::ArrowCursor); - + scanDir(this->connexion.server, this->connexion.port, NULL, path[0].append("/") ); + this->unsetCursor(); + QGuiApplication::setOverrideCursor(Qt::ArrowCursor); } } } void MainWindow::populateList() { - string server; - string port; - int portN; stringstream ss; - server.assign(ui->khistorycombobox->currentText().toStdString()); - port.assign(ui->portEdit->text().toStdString()); - ss << port; - ss >> portN; - if (!server.empty() and !port.empty() and portN < 65536) + this->connexion.server.assign(ui->khistorycombobox->currentText().toStdString()); + ss << ui->portEdit->text().toStdString(); + ss >> this->connexion.port; + if (!this->connexion.server.empty() and this->connexion.port > 0 and this->connexion.port < 65536) { - if (validateServer(server)) + if (validateServer(this->connexion.server)) { + ui->khistorycombobox->addItem(this->connexion.server.c_str()); ui->centralwidget->cursor().setShape(Qt::WaitCursor); - listServices(server, portN); + listServices(); ui->centralwidget->cursor().setShape(Qt::ArrowCursor); - + QStringList test = ui->khistorycombobox->historyItems(); + sleep(1); } } } -void MainWindow::listServices(string server, int portN) +void MainWindow::listServices() { char cmd[4096]; string line; @@ -97,7 +119,7 @@ void MainWindow::listServices(string server, int portN) vector v; char service[4096]; - sprintf(cmd, "rsync --contimeout=10 -P \"%s::\" --port %d ", server.c_str(), portN ); + sprintf(cmd, "rsync --contimeout=10 -P \"%s::\" --port %d ", this->connexion.server.c_str(), this->connexion.port ); redi::ipstream in(cmd, redi::pstreams::pstdout | redi::pstreams::pstderr); while (getline(in.out(), line)) { @@ -167,25 +189,24 @@ void MainWindow::scanDir(string server, int portN, QTreeWidgetItem *parent, stri bool MainWindow::isIpAddress(string server) { - bool returnCode = false; vector r; - stringstream ss; int elementN; + QString qr; + bool ok; - r = explode(server, '.'); + r = explode(server, '.', 5); if (r.size() == 4) { for (auto element : r) { - ss << element; - ss >> elementN; - if (elementN >0 and elementN < 256) + elementN = QString::fromStdString(element).toInt(&ok); + if (elementN < 0 or elementN > 255 or ok == false) { - returnCode &= true; + return false; } } } - return returnCode; + return true; } bool MainWindow::validateServer(string server) @@ -227,6 +248,9 @@ bool MainWindow::validateServer(string server) if ( flag == false) { flag = isIpAddress(server); + } + if ( flag == false) + { QMessageBox::warning( this, "RsyncUI", @@ -247,21 +271,11 @@ void MainWindow::on_khistorycombobox_returnPressed() populateList(); } -/*void MainWindow::on_portEdit_userTextChanged() -{ - populateTree(); -}*/ - void MainWindow::on_portEdit_returnPressed() { populateList(); } -void MainWindow::on_khistorycombobox_textActivated() -{ - populateList(); -} - void MainWindow::on_treeWidget_itemClicked(QTreeWidgetItem *item, int column) { @@ -304,41 +318,110 @@ QTreeWidgetItem * MainWindow::addTreeChild(QTreeWidgetItem *parent, QString name void MainWindow::on_listWidget_clicked(const QModelIndex &index) { + vector v; + v = explode(ui->listWidget->currentItem()->text().toStdString(), '\n', 2); + this->downloading.service = v[0]; populateTree(); } -void MainWindow::on_listDownload_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous) -{ - cout << current->text().toStdString() << endl; -} - void MainWindow::on_treeWidget_itemDoubleClicked(QTreeWidgetItem *item, int column) { - string path; QFuture future; - QFutureWatcher watcher; - QString savePath; QFileDialog dialog; - QString dirPath; - /*int p[2]; + QCheckBox *cb = new QCheckBox("Okay I understand"); - if (pipe(p) < 0) + item = ui->treeWidget->currentItem(); + this->downloading.path = item->text(0).toStdString(); + while(item->parent() != NULL) { - return; - }*/ - dirPath = getenv("HOME"); - dirPath.append("/Vidéos/"); - savePath = dialog.getExistingDirectory(this, tr("Choose directory to save file"), dirPath, QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); - downloadFile downloadO; + item = item->parent(); + this->downloading.path = item->text(0).toStdString() + "/" + this->downloading.path; + }; - //QProgressDialog progress("Downloading file ...", "Abort Download", 0, 100, this); + //dirPath.append("/Vidéos/"); + if (this->downloading.savePath.empty()) + { + if (this->downloading.dirPath.toStdString().empty()) + { + this->downloading.dirPath = getenv("HOME"); + } - ui->progressBar->setWindowModality(Qt::WindowModal); + this->downloading.savePath = dialog.getExistingDirectory(this, tr("Choose directory to save file"), this->downloading.dirPath, QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks).toStdString(); + if (!this->downloading.savePath.empty() && this->downloading.pid == 0) + { + startDownloading(); + } + } + ui->listDownload->addItem(QString::fromStdString(this->downloading.path)); +} + +void MainWindow::startDownloading() +{ ui->progressBar->setValue(0); ui->progressBar->show(); - connect(&watcher, &QFutureWatcherBase::finished, ui->progressBar, &QProgressBar::hide); - connect(&downloadO, &downloadFile::progressSignal, ui->progressBar, &QProgressBar::setValue); - future = QtConcurrent::run(&this->MyObject, &downloadFile::download, savePath, this); - watcher.setFuture(future); + + QtConcurrent::run(&this->downloadO, &downloadFile::download, this); + +} + +void MainWindow::stoppingDownload() +{ + emit (stopDownloading(this->downloading.pid)); +} + +void MainWindow::downloadFinished() +{ + ui->progressBar->hide(); + delete ui->listDownload->takeItem(0); + this->downloading.pid = 0; + if (ui->listDownload->count() != 0) + { + this->downloading.path = ui->listDownload->item(0)->text().toStdString(); + startDownloading(); + } +} + +void MainWindow::on_listDownload_itemClicked(QListWidgetItem *item) +{ + QFileDialog dialog; + QMessageBox::StandardButton reply; + + cout << item->text().toStdString() << endl; + if (item->listWidget()->row(item) == 0) + { + 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) + { + emit (stopDownloading(this->downloading.pid)); + } + }else + { + 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) + { + ui->listDownload->removeItemWidget(item); + delete item; + } + } +} + +void MainWindow::loadSettings() +{ + this->settings.value("serverlist"); +} + +void MainWindow::saveSettings() +{ + //ui->khistorycombobox-> } diff --git a/mainwindow.h b/mainwindow.h index 52bae5f..438e49f 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -7,55 +7,86 @@ #include #include "downloadfile.h" #include +#include QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE +class Connexion +{ + public: + std::string bandwidthLimit = "1M"; + std::string server; + int port = 873; +}; + +class Downloading +{ + public: + std::string service; + std::string path; + std::string defaultSavePath; + std::string savePath; + QString dirPath; + int pid = 0; +}; + class MainWindow : public QMainWindow { Q_OBJECT -public: - Ui::MainWindow *ui; - MainWindow(QWidget *parent = nullptr); - ~MainWindow(); - QProgressDialog *progress; - void displayTree(); - void populateTree(); - void populateList(); - void listServices(std::string server, int portN); - bool validateServer(std::string server); - bool isIpAddress(std::string server); - QTreeWidgetItem * addTreeRoot(QString name, QString description); - QTreeWidgetItem * addTreeChild(QTreeWidgetItem *parent, QString name, QString size); - void scanDir(std::string server, int portN, QTreeWidgetItem *parent = NULL, std::string path = "" ); + public: + Ui::MainWindow *ui; + MainWindow(QWidget *parent = nullptr); + ~MainWindow(); + QProgressDialog *progress; + void displayTree(); + void populateTree(); + void populateList(); + void listServices(); + bool validateServer(std::string server); + bool isIpAddress(std::string server); + QTreeWidgetItem * addTreeRoot(QString name, QString description); + QTreeWidgetItem * addTreeChild(QTreeWidgetItem *parent, QString name, QString size); + void scanDir(std::string server, int portN, QTreeWidgetItem *parent = NULL, std::string path = "" ); + void startDownloading(); + void loadSettings(); + void saveSettings(); -private slots: - void on_khistorycombobox_returnPressed(); + Connexion connexion; + Downloading downloading; + downloadFile downloadO; + QSettings settings; - //void on_portEdit_userTextChanged(); + private slots: + void on_khistorycombobox_returnPressed(); - void on_portEdit_returnPressed(); + //void on_portEdit_userTextChanged(); - void on_khistorycombobox_textActivated(); + void on_portEdit_returnPressed(); - void on_treeWidget_itemClicked(QTreeWidgetItem *item, int column); + void on_treeWidget_itemClicked(QTreeWidgetItem *item, int column); - void on_treeWidget_customContextMenuRequested(); + void on_treeWidget_customContextMenuRequested(); - void on_actionDownload_triggered(); + void on_actionDownload_triggered(); - void on_listWidget_clicked(const QModelIndex &index); + void on_listWidget_clicked(const QModelIndex &index); - void on_listDownload_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous); + void on_treeWidget_itemDoubleClicked(QTreeWidgetItem *item, int column); - void on_treeWidget_itemDoubleClicked(QTreeWidgetItem *item, int column); + void downloadFinished(); -public slots: + void stoppingDownload(); + + void on_listDownload_itemClicked(QListWidgetItem *item); + +signals: + void stopDownloading(int); -private: - downloadFile MyObject; }; + + #endif // MAINWINDOW_H diff --git a/mainwindow.ui b/mainwindow.ui index 594493a..4a8795c 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -226,7 +226,7 @@ true - QAbstractItemView::MultiSelection + QAbstractItemView::SingleSelection QAbstractItemView::SelectItems @@ -290,14 +290,33 @@ 30 - + - debug + Menu + - + + + + Menu + + + + + Default save folder + + + Default save folder + + + + + Bandwidth limit + + diff --git a/tools.cpp b/tools.cpp index 654cc29..3bbef34 100644 --- a/tools.cpp +++ b/tools.cpp @@ -42,7 +42,7 @@ const vector explode(const string& s, const char& c, int n = 0) return v; } -FILE * popen2(char * cmd, string type, int & pid) +FILE * popen2(array argv, string type, int & pid) { pid_t child_pid; int fd[2]; @@ -69,8 +69,11 @@ FILE * popen2(char * cmd, string type, int & pid) } setpgid(child_pid, child_pid); //Needed so negative PIDs can kill children of /bin/sh - execl(cmd, ""); - exit(0); + if (execl(argv[0].c_str(), argv[0].c_str(), argv[1].c_str(), argv[2].c_str(), argv[3].c_str(), argv[4].c_str(), argv[5].c_str(), NULL ) == -1) + { + perror("execl error => "); + } + exit (0); } else { diff --git a/tools.h b/tools.h index 64ec011..cfc25c2 100644 --- a/tools.h +++ b/tools.h @@ -8,7 +8,7 @@ using namespace std; const vector explode(const string& s, const char& c, int n = 0); -FILE * popen2(char * command, string type, int & pid); +FILE * popen2(array argv, string type, int & pid); int pclose2(FILE * fp, pid_t pid); #endif // TOOLS_H