completely migrate to QT and some bugs corrected

This commit is contained in:
Daniel Tartavel 2023-02-10 23:27:44 +01:00
parent 13d2c1384b
commit 9671a5cea8
6 changed files with 113 additions and 48 deletions

View File

@ -6,7 +6,7 @@ Comment=Client for rsync servers
Comment[fr]=Client pour serveur rsync
Version=1.0
Exec=RsyncUI
Icon=
Icon=/usr/share/icons/RsyncUI.png
Type=Application
Terminal=false
StartupNotify=true

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 4.14.2, 2023-02-10T14:36:52. -->
<!-- Written by QtCreator 4.14.2, 2023-02-10T23:24:32. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>

View File

@ -96,6 +96,7 @@ void MainWindow::readRsyncOutput()
);
}*/
// process raise error
void MainWindow::downloadProcessStderr()
{
QByteArray errorLine;

View File

@ -9,6 +9,7 @@ int main(int argc, char *argv[])
QCoreApplication::setOrganizationName("RsyncUI");
QCoreApplication::setApplicationName("RsyncUI");
// Initialization of localization
QLocale localeName = QLocale::system();
QString localeFile = "/usr/share/locale/" + localeName.name() + "/LC_MESSAGES/RsyncUI_" + localeName.name() + ".qm";

View File

@ -40,10 +40,10 @@ MainWindow::MainWindow(QWidget *parent)
QCoreApplication::setOrganizationName("RsyncUI");
QCoreApplication::setApplicationName("RsyncUI");
// context menu for treewidget
// context menu for treewidget (list of files)
ui->treeWidget->addAction(ui->actionDownload);
// init shortcut
// init configuration window
config.setupUi(&Configuration);
// init of About
@ -57,12 +57,14 @@ MainWindow::MainWindow(QWidget *parent)
connect(config.comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &MainWindow::on_comboBox_currentIndexChanged);
// init of widgets
ui->ktreewidgetsearchline->setTreeWidget(ui->treeWidget);
ui->ktreewidgetsearchline->setCaseSensitivity(Qt::CaseInsensitive);
ui->treeWidget->setHeaderLabels({tr("Path"), tr("Type"), tr("Size")} );
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
@ -71,7 +73,7 @@ MainWindow::MainWindow(QWidget *parent)
ui->khistorycombobox->clear();
}
// setting arrowcursor for treeWidget, listWidget and listDownload
// setting arrowcursor for treeWidget, listWidget and listDownload to arrow
ui->treeWidget->setCursor(Qt::ArrowCursor);
ui->listWidget->setCursor(Qt::ArrowCursor);
ui->listDownload->setCursor(Qt::ArrowCursor);
@ -82,28 +84,32 @@ MainWindow::MainWindow(QWidget *parent)
loadSettings();
//setting configuration window
config.comboBox->setCurrentIndex(ui->toolBar->toolButtonStyle());
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)
{
//this->settings.endArray();
// 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 *remove = msgBox.addButton(tr("Remove"), QMessageBox::ActionRole);
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();
}
@ -112,11 +118,12 @@ MainWindow::~MainWindow()
delete ui;
}
// Closing window has been clicked
// Close window has been clicked
void MainWindow::closeEvent (QCloseEvent *event)
{
QMessageBox::StandardButton reply;
QMessageBox::StandardButtons param;
QString displayText;
// saving settings
saveSettings();
@ -128,13 +135,15 @@ void MainWindow::closeEvent (QCloseEvent *event)
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.\nYou can save the list of downloads\nDo you want to exit ?"),
tr("Exiting will stop downloading, and will clear the download queue.\nDo you want to exit ?") + displayText,
param,
QMessageBox::No);
if (reply == QMessageBox::No)
{
// continuing
@ -155,7 +164,6 @@ void MainWindow::closeEvent (QCloseEvent *event)
// Populate treeview with list of files
void MainWindow::populateTree(QTreeWidgetItem * parent)
{
stringstream ss;
QString path;
// Clear treewidget
@ -165,6 +173,7 @@ void MainWindow::populateTree(QTreeWidgetItem * parent)
// setting cursor to "Wait"
QGuiApplication::setOverrideCursor(Qt::WaitCursor);
// validating server's address
if (validateServer(this->connexion.server))
{
// server is validated
@ -179,8 +188,6 @@ void MainWindow::populateTree(QTreeWidgetItem * parent)
// Populate Listview with list of services
void MainWindow::populateList()
{
//stringstream ss;
QString str;
QString server;
int port;
@ -190,9 +197,11 @@ void MainWindow::populateList()
{
// 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
@ -203,6 +212,8 @@ void MainWindow::populateList()
port = this->settings.value(server).toUInt();
ui->portEdit->setText(QString::number(port));
this->connexion.port = port;
//display list of services
listServices();
}else
{
@ -211,6 +222,7 @@ void MainWindow::populateList()
if (validateServer(server))
{
cout << server.toStdString() << endl;
// storing serverURL and port in settings
this->settings.setValue(server, port);
this->settings.sync();
@ -219,14 +231,13 @@ void MainWindow::populateList()
// storing in history of combobox
ui->khistorycombobox->addToHistory(server);
// "waiting" cursor
// load and display rsync services of the rsync server
listServices();
}
}
}
this->settings.endGroup();
QGuiApplication::restoreOverrideCursor(); //setOverrideCursor(Qt::ArrowCursor);
QGuiApplication::restoreOverrideCursor(); //setting cursor to default
}
}
@ -247,26 +258,32 @@ void MainWindow::listServices()
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);
}
@ -276,10 +293,8 @@ void MainWindow::scanDir(QString server, int portN, QTreeWidgetItem *parent, QSt
QString cmd;
QStringList param;
QString line;
QString errorRsync;
QString size;
QString filename;
QString dir;
QTreeWidgetItem * item;
QProcess * myProcess;
bool isDir = false;
@ -291,16 +306,19 @@ void MainWindow::scanDir(QString server, int portN, QTreeWidgetItem *parent, QSt
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);
@ -315,16 +333,19 @@ void MainWindow::scanDir(QString server, int portN, QTreeWidgetItem *parent, QSt
}
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);
}
@ -333,7 +354,6 @@ bool MainWindow::isIpAddress(QString server)
{
QStringList r;
int elementN;
QString qr;
bool ok;
r = server.split('.');
@ -360,9 +380,9 @@ bool MainWindow::validateServer(QString server)
QString cmd;
QStringList param;
QString line;
QString errorDig;
QProcess * myProcess;
bool flag = false;
bool bflag = false;
cmd = "dig";
param << server;
@ -370,23 +390,35 @@ bool MainWindow::validateServer(QString 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());
if (line.indexOf(";; ANSWER SECTION:") != -1)
// 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",
@ -412,15 +444,15 @@ void MainWindow::on_connectButton_clicked()
// add a dir in treeview
QTreeWidgetItem * MainWindow::addTreeRoot(QString name, QString fileSize, bool isDir)
{
// QTreeWidgetItem(QTreeWidget * parent, int type = Type)
QTreeWidgetItem *treeItem = new QTreeWidgetItem(ui->treeWidget);
// QTreeWidgetItem::setText(int column, const QString & text)
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);
@ -432,15 +464,15 @@ QTreeWidgetItem * MainWindow::addTreeRoot(QString name, QString fileSize, bool i
// add a file in treeview
QTreeWidgetItem * MainWindow::addTreeChild(QTreeWidgetItem *parent, QString name, QString fileSize, bool isDir)
{
// QTreeWidgetItem(QTreeWidget * parent, int type = Type)
QTreeWidgetItem *treeItem = new QTreeWidgetItem();
// QTreeWidgetItem::setText(int column, const QString & text)
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);
@ -454,13 +486,14 @@ QTreeWidgetItem * MainWindow::addTreeChild(QTreeWidgetItem *parent, QString name
// Slot acivated when a service in the list is clicked
void MainWindow::on_listWidget_clicked()
{
QString service;
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);
@ -477,17 +510,18 @@ void MainWindow::on_treeWidget_itemClicked(QTreeWidgetItem *item, bool downloadD
itemR = item;
// assembling path from treewidget
path = item->text(0);
while(itemR->parent() != NULL)
{
itemR = itemR->parent();
path = itemR->text(0) + "/" + path;
// concatening parent to path
path.prepend(itemR->text(0) + "/");
};
if (item->text(1) == tr("File") or downloadDir == true)
{
// Item is a file
if(ui->listDownload->findItems(path, Qt::MatchStartsWith).empty())
{
// exists saving path in settings ?
@ -550,9 +584,10 @@ void MainWindow::stoppingDownload()
void MainWindow::downloadFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
QString path;
int pos;
QString str;
int pos;
// test if process crashed
if (exitStatus == QProcess::CrashExit)
{
QMessageBox::warning(
@ -560,25 +595,36 @@ void MainWindow::downloadFinished(int exitCode, QProcess::ExitStatus exitStatus)
"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();
@ -587,12 +633,17 @@ void MainWindow::downloadFinished(int exitCode, QProcess::ExitStatus exitStatus)
this->downloading.server = path.midRef(pos+4).toString();
path.resize(pos);
this->downloading.path = path;
// save path 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";
@ -600,7 +651,6 @@ void MainWindow::downloadFinished(int exitCode, QProcess::ExitStatus exitStatus)
return;
}
}
startDownloading();
}
}
@ -608,12 +658,11 @@ void MainWindow::downloadFinished(int exitCode, QProcess::ExitStatus exitStatus)
// Slot activated when a line is clicked in queue list
void MainWindow::on_listDownload_itemClicked(QListWidgetItem *item)
{
QFileDialog dialog;
QMessageBox::StandardButton reply;
//cout << item->text().toStdString() << endl;
if (item->listWidget()->row(item) == 0)
{
// first line clicked on download list
reply = QMessageBox::question(
this,
"RsyncUI",
@ -622,10 +671,12 @@ void MainWindow::on_listDownload_itemClicked(QListWidgetItem *item)
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",
@ -634,10 +685,12 @@ void MainWindow::on_listDownload_itemClicked(QListWidgetItem *item)
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();
}
}
@ -694,7 +747,6 @@ void MainWindow::saveSettings()
// About
void MainWindow::on_actionAbout_triggered()
{
//TODO => initialisation
QString text = this->about.description + "\n\n" +
tr("Version") + ": " + this->about.version + "\n" +
tr("Licence") + ": " + this->about.licence + "\n" +
@ -717,6 +769,7 @@ bool MainWindow::on_DefaultSaveFolder_triggered()
QString folder;
QString path;
// if service not selected display a message
if (this->connexion.service.isEmpty())
{
QMessageBox::warning(
@ -725,12 +778,15 @@ bool MainWindow::on_DefaultSaveFolder_triggered()
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();
@ -759,6 +815,7 @@ void MainWindow::on_buttonBox_accepted()
bw = config.spinBox->text();
if (bw.toInt() == 0)
{
// bandwidth = 0
this->connexion.bandwidthLimit = 0;
this->connexion.bandwidthLimitUnit = 0;
}else
@ -780,9 +837,11 @@ void MainWindow::saveDownloadList()
{
int nRows;
// remove list of downloads
this->settings.remove("Downloads/");
// Saving list of current downloads
nRows = ui->listDownload->count();
//this->settings.beginWriteArray("Downloads/");
this->settings.beginGroup("Downloads");
this->settings.setValue("rows", nRows);
for (int i = 0; i < nRows; i++)
@ -793,12 +852,14 @@ void MainWindow::saveDownloadList()
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)
@ -807,8 +868,6 @@ void MainWindow::loadDownloadList()
}
this->settings.endGroup();
this->settings.sync();
path = ui->listDownload->item(0)->text();
pos = path.lastIndexOf("/");
this->downloading.service = path.midRef(pos+1).toString();
@ -825,6 +884,7 @@ void MainWindow::loadDownloadList()
startDownloading();
}
// clear object downloading
void Downloading::clear()
{
this->path.clear();
@ -833,6 +893,7 @@ void Downloading::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.
@ -852,6 +913,7 @@ void MainWindow::on_actionDownload_triggered()
}
*/
// Chnage toolbar style
void MainWindow::on_comboBox_currentIndexChanged(int index)
{
ui->toolBar->setToolButtonStyle((Qt::ToolButtonStyle)index);

View File

@ -43,6 +43,7 @@ const vector<string> explode(const string& s, const char& c, int n = 0)
return v;
}
// test return code of rsync
bool testRsyncReturn(QProcess * myProcess)
{
if (myProcess->exitStatus() != 0)