rsyncui/mainwindow.cpp

514 lines
14 KiB
C++
Raw Permalink Normal View History

2023-01-07 12:44:45 +01:00
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "downloadfile.h"
#include "tools.h"
#include <iostream>
#include <KTreeWidgetSearchLineWidget>
#include <pstreams/pstream.h>
#include <sstream>
#include <string>
#include <cstring>
#include <iostream>
#include <stdio.h>
2023-01-12 09:23:45 +01:00
#include <cstdio>
2023-01-07 12:44:45 +01:00
#include <QMessageBox>
#include <vector>
#include <boost/algorithm/string/replace.hpp>
#include <QFuture>
#include <QtConcurrent>
#include <qtconcurrentrun.h>
#include <QFileDialog>
#include <QThread>
#include <QProgressDialog>
2023-01-12 09:23:45 +01:00
#include <sys/wait.h>
#include <QGuiApplication>
2023-01-18 23:12:21 +01:00
#include <QShortcut>
2023-01-07 12:44:45 +01:00
using namespace std;
bool display = false;
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
2023-01-15 15:25:22 +01:00
QCoreApplication::setOrganizationName("RsyncUI");
QCoreApplication::setApplicationName("RsyncUI");
2023-01-18 23:12:21 +01:00
// init shortcut
// QShortcut * shortcut = new QShortcut(QKeySequence("Return"), this);
loadSettings();
2023-01-15 15:25:22 +01:00
// connectors
2023-01-12 09:23:45 +01:00
connect(&downloadO, &downloadFile::progressSignal, ui->progressBar, &QProgressBar::setValue);
connect(&downloadO, &downloadFile::finishedSignal, this, &MainWindow::downloadFinished);
connect(this, &MainWindow::stopDownloading, &downloadO, &downloadFile::cancelled);
2023-01-18 23:12:21 +01:00
//connect(shortcut, SIGNAL(activated()), this, SLOT(returnPressed()));
2023-01-12 09:23:45 +01:00
2023-01-15 15:25:22 +01:00
// init of widgets
2023-01-07 12:44:45 +01:00
ui->ktreewidgetsearchline->setTreeWidget(ui->treeWidget);
ui->ktreewidgetsearchline->setCaseSensitivity(Qt::CaseInsensitive);
ui->treeWidget->setHeaderLabels({tr("Path"), tr("Size")} );
ui->progressBar->hide();
2023-01-07 12:44:45 +01:00
populateList();
2023-01-18 23:12:21 +01:00
}
2023-01-12 09:23:45 +01:00
2023-01-18 23:12:21 +01:00
void MainWindow::returnPressed()
{
populateList();
2023-01-07 12:44:45 +01:00
}
MainWindow::~MainWindow()
{
2023-01-12 09:23:45 +01:00
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));
}
}
saveSettings();
2023-01-12 09:23:45 +01:00
if (this->downloading.pid != 0)
{
waitpid(this->downloading.pid, NULL, WUNTRACED);
}
2023-01-07 12:44:45 +01:00
delete ui;
}
void MainWindow::populateTree()
{
stringstream ss;
vector<string> path;
2023-01-18 23:12:21 +01:00
ui->treeWidget->clear();
2023-01-12 09:23:45 +01:00
if (!this->connexion.server.empty() and this->connexion.port > 0 and this->connexion.port < 65536)
2023-01-07 12:44:45 +01:00
{
QGuiApplication::setOverrideCursor(Qt::WaitCursor);
2023-01-12 09:23:45 +01:00
if (validateServer(this->connexion.server))
2023-01-07 12:44:45 +01:00
{
path = explode(ui->listWidget->currentItem()->text().toStdString(), '\n', 2);
2023-01-12 09:23:45 +01:00
scanDir(this->connexion.server, this->connexion.port, NULL, path[0].append("/") );
2023-01-07 12:44:45 +01:00
}
2023-01-15 15:25:22 +01:00
QGuiApplication::restoreOverrideCursor(); //setOverrideCursor(Qt::ArrowCursor);
2023-01-07 12:44:45 +01:00
}
}
void MainWindow::populateList()
{
stringstream ss;
QString str;
QString server;
QString port;
2023-01-07 12:44:45 +01:00
2023-01-18 23:12:21 +01:00
ui->listWidget->clear();
server = ui->khistorycombobox->currentText();
this->connexion.server.assign(server.toStdString());
2023-01-12 09:23:45 +01:00
ss << ui->portEdit->text().toStdString();
ss >> this->connexion.port;
this->settings.beginGroup("connexion/server");
if (this->settings.contains(server))
2023-01-07 12:44:45 +01:00
{
port = this->settings.value(server).toString();
ui->portEdit->setText(port);
this->connexion.port = this->settings.value(server).toInt();
}
if (!server.isEmpty() and this->connexion.port > 0 and this->connexion.port < 65536)
{
if (validateServer(server.toStdString()))
2023-01-07 12:44:45 +01:00
{
//this->settings.beginGroup("connexion/server");
if (!this->settings.contains(server))
{
cout << server.toStdString() << endl;
// storing serverURL and port in settings
this->settings.setValue(server, this->connexion.port);
this->settings.sync();
// storing in history of combobox
ui->khistorycombobox->addToHistory(server);
}
// "waiting" cursor
// load and display rsync services of the rsync server
2023-01-18 23:12:21 +01:00
QGuiApplication::setOverrideCursor(Qt::WaitCursor);
2023-01-12 09:23:45 +01:00
listServices();
2023-01-18 23:12:21 +01:00
QGuiApplication::restoreOverrideCursor(); //setOverrideCursor(Qt::ArrowCursor);
2023-01-07 12:44:45 +01:00
}
}
this->settings.endGroup();
2023-01-15 15:25:22 +01:00
QGuiApplication::restoreOverrideCursor(); //setOverrideCursor(Qt::ArrowCursor);
2023-01-07 12:44:45 +01:00
}
2023-01-12 09:23:45 +01:00
void MainWindow::listServices()
2023-01-07 12:44:45 +01:00
{
char cmd[4096];
string line;
string errorRsync;
vector<string> v;
char service[4096];
2023-01-12 09:23:45 +01:00
sprintf(cmd, "rsync --contimeout=10 -P \"%s::\" --port %d ", this->connexion.server.c_str(), this->connexion.port );
2023-01-07 12:44:45 +01:00
redi::ipstream in(cmd, redi::pstreams::pstdout | redi::pstreams::pstderr);
while (getline(in.out(), line))
{
//cout << "stdout: " << line << endl;
2023-01-07 12:44:45 +01:00
boost::replace_all(line," ","");
boost::replace_all(line, "\t", " - ");
v = explode(line, ' ', 3 );
sprintf(service, "%s\n\t%s", v[0].c_str(), v[2].c_str());
ui->listWidget->addItem(service);
}
}
void MainWindow::scanDir(string server, int portN, QTreeWidgetItem *parent, string path)
{
char cmd[4096];
string line;
string errorRsync;
vector<string> v;
QTreeWidgetItem * item;
char npath[4096];
sprintf(cmd, "rsync --contimeout=10 -P \"%s::%s\" --port %d ", server.c_str(), path.c_str(), portN );
redi::ipstream in(cmd, redi::pstreams::pstdout | redi::pstreams::pstderr);
while (getline(in.out(), line))
{
v = explode(line, ' ', 5);
if (v.size() == 5)
{
if (v[4].at(0) != '.' and (v[0].at(0) == '-' or v[0].at(0) == 'd'))
{
if (parent != NULL)
{
item = addTreeChild(parent,QString::fromStdString(v[4]), QString::fromStdString(v[1]));
}else
{
item = addTreeRoot(QString::fromStdString(v[4]), QString::fromStdString(v[1]));
}
if (v[0].at(0) == 'd')
{
sprintf(npath, "%s%s/", path.c_str(), v[4].c_str());
scanDir(server, portN, item, npath);
}
}
}
}
// if reading stdout stopped at EOF then reset the state:
if (in.eof() && in.fail())
in.clear();
// read child's stderr
while (getline(in.err(), line))
{
cout << "stderr: " << line << endl;
errorRsync.append(line);
errorRsync.append("\n");
}
if ( !errorRsync.empty())
{
QMessageBox::warning(
this,
"RsyncUI",
errorRsync.c_str());
}
}
bool MainWindow::isIpAddress(string server)
{
vector<string> r;
int elementN;
2023-01-12 09:23:45 +01:00
QString qr;
bool ok;
2023-01-07 12:44:45 +01:00
2023-01-12 09:23:45 +01:00
r = explode(server, '.', 5);
2023-01-07 12:44:45 +01:00
if (r.size() == 4)
{
for (auto element : r)
{
2023-01-12 09:23:45 +01:00
elementN = QString::fromStdString(element).toInt(&ok);
if (elementN < 0 or elementN > 255 or ok == false)
2023-01-07 12:44:45 +01:00
{
2023-01-12 09:23:45 +01:00
return false;
2023-01-07 12:44:45 +01:00
}
}
2023-01-18 23:12:21 +01:00
return true;
}else
{
return false;
2023-01-07 12:44:45 +01:00
}
}
bool MainWindow::validateServer(string server)
{
char cmd[512];
string line;
string errorDig;
bool flag = false;
sprintf(cmd, "dig %s", server.c_str());
redi::ipstream in(cmd, redi::pstreams::pstdout | redi::pstreams::pstderr);
while (getline(in.out(), line))
{
//cout << "stdout: " << line << '\n';
2023-01-07 12:44:45 +01:00
if (line.find(";; ANSWER SECTION:") != string::npos)
{
flag = true;
}
}
// if reading stdout stopped at EOF then reset the state:
if (in.eof() && in.fail())
in.clear();
// read child's stderr
while (std::getline(in.err(), line))
{
cout << "stderr: " << line << '\n';
errorDig.append(line);
errorDig.append("\n");
}
if ( !errorDig.empty())
{
QMessageBox::warning(
this,
"RsyncUI",
errorDig.c_str()
);
}
if ( flag == false)
{
flag = isIpAddress(server);
2023-01-12 09:23:45 +01:00
}
if ( flag == false)
{
2023-01-07 12:44:45 +01:00
QMessageBox::warning(
this,
"RsyncUI",
tr("server does not exists" )
);
}
return flag;
}
void MainWindow::displayTree()
{
populateTree();
}
void MainWindow::on_khistorycombobox_returnPressed()
{
//populateList();
2023-01-07 12:44:45 +01:00
}
void MainWindow::on_khistorycombobox_currentIndexChanged(int i)
2023-01-07 12:44:45 +01:00
{
2023-01-18 23:12:21 +01:00
populateList();
2023-01-07 12:44:45 +01:00
}
void MainWindow::on_portEdit_returnPressed()
2023-01-07 12:44:45 +01:00
{
2023-01-18 23:12:21 +01:00
//populateList();
2023-01-07 12:44:45 +01:00
}
2023-01-18 23:12:21 +01:00
void MainWindow::on_connectButton_clicked()
2023-01-07 12:44:45 +01:00
{
2023-01-18 23:12:21 +01:00
populateList();
2023-01-07 12:44:45 +01:00
}
QTreeWidgetItem * MainWindow::addTreeRoot(QString name, QString fileSize)
{
// QTreeWidgetItem(QTreeWidget * parent, int type = Type)
QTreeWidgetItem *treeItem = new QTreeWidgetItem(ui->treeWidget);
// QTreeWidgetItem::setText(int column, const QString & text)
treeItem->setText(0, name);
treeItem->setText(1, fileSize);
return treeItem;
}
QTreeWidgetItem * MainWindow::addTreeChild(QTreeWidgetItem *parent, QString name, QString fileSize)
{
// QTreeWidgetItem(QTreeWidget * parent, int type = Type)
QTreeWidgetItem *treeItem = new QTreeWidgetItem();
// QTreeWidgetItem::setText(int column, const QString & text)
treeItem->setText(0, name);
treeItem->setText(1, fileSize);
// QTreeWidgetItem::addChild(QTreeWidgetItem * child)
parent->addChild(treeItem);
return treeItem;
}
2023-01-18 23:12:21 +01:00
void MainWindow::on_listWidget_clicked()
2023-01-07 12:44:45 +01:00
{
2023-01-12 09:23:45 +01:00
vector<string> v;
v = explode(ui->listWidget->currentItem()->text().toStdString(), '\n', 2);
this->downloading.service = v[0];
2023-01-07 12:44:45 +01:00
populateTree();
}
2023-01-18 23:12:21 +01:00
void MainWindow::on_treeWidget_itemDoubleClicked(QTreeWidgetItem *item)
2023-01-07 12:44:45 +01:00
{
QFuture<void> future;
QFileDialog dialog;
2023-01-12 09:23:45 +01:00
item = ui->treeWidget->currentItem();
this->downloading.path = item->text(0).toStdString();
while(item->parent() != NULL)
2023-01-07 12:44:45 +01:00
{
2023-01-12 09:23:45 +01:00
item = item->parent();
this->downloading.path = item->text(0).toStdString() + "/" + this->downloading.path;
2023-01-07 12:44:45 +01:00
2023-01-12 09:23:45 +01:00
};
2023-01-07 12:44:45 +01:00
2023-01-12 09:23:45 +01:00
//dirPath.append("/Vidéos/");
if (this->downloading.savePath.empty())
{
if (this->downloading.dirPath.toStdString().empty())
{
this->downloading.dirPath = getenv("HOME");
}
2023-01-15 15:25:22 +01:00
if (this->downloading.savePath.empty())
{
on_DefaultSaveFolder_triggered();
}
2023-01-12 09:23:45 +01:00
if (!this->downloading.savePath.empty() && this->downloading.pid == 0)
{
startDownloading();
}
}
ui->listDownload->addItem(QString::fromStdString(this->downloading.path));
}
void MainWindow::startDownloading()
{
2023-01-07 12:44:45 +01:00
ui->progressBar->setValue(0);
ui->progressBar->show();
2023-01-12 09:23:45 +01:00
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;
2023-01-12 09:23:45 +01:00
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->restoreGeometry(settings.value("window/geometry").toByteArray());
2023-01-15 15:25:22 +01:00
this->restoreState(settings.value("window/state").toByteArray());
ui->treeWidget->header()->restoreState(settings.value("treeView/state").toByteArray());
ui->splitter->restoreState(settings.value("splitter/state").toByteArray());
ui->splitter_2->restoreState(settings.value("splitter2/state").toByteArray());
this->settings.beginGroup("connexion/server");
QStringList servers = this->settings.allKeys();
this->settings.endGroup();
2023-01-15 15:25:22 +01:00
this->downloading.dirPath = this->settings.value("Folder").toString();
for( const QString &server : servers )
{
ui->khistorycombobox->addToHistory(server);
}
2023-01-12 09:23:45 +01:00
}
2023-01-12 09:23:45 +01:00
void MainWindow::saveSettings()
{
this->settings.setValue("window/geometry", saveGeometry());
2023-01-15 15:25:22 +01:00
this->settings.setValue("window/state", saveState());
//ui->treeWidget->header()->saveState();
this->settings.setValue("treeView/state", ui->treeWidget->header()->saveState());
this->settings.setValue("splitter/state", ui->splitter->saveState());
this->settings.setValue("splitter2/state", ui->splitter_2->saveState());
this->settings.sync();
}
void MainWindow::on_actionAbout_triggered()
{
QString text = this->about.description + "\n\n" +
"Licence: " + this->about.licence + "\n" +
"Author: " + this->about.author + "\n" +
"EMail : " + this->about.email + "\n" +
"Source code: " + this->about.git;
QMessageBox::about(this, this->about.title, text);
}
void MainWindow::on_actionAbout_Qt_triggered()
{
QMessageBox::aboutQt(this);
2023-01-07 12:44:45 +01:00
}
2023-01-15 15:25:22 +01:00
void MainWindow::on_DefaultSaveFolder_triggered()
{
QFileDialog dialog;
this->downloading.savePath = dialog.getExistingDirectory(this, tr("Choose directory to save file"), this->downloading.dirPath, QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks).toStdString();
this->downloading.dirPath = this->downloading.savePath.c_str();
this->settings.setValue("Folder/", this->downloading.dirPath);
}