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 <QCheckBox>
# include <sys/wait.h>
# include <QGuiApplication>
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-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-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-15 13:26:14 +01:00
2023-01-12 09:23:45 +01:00
loadSettings ( ) ;
2023-01-07 12:44:45 +01:00
populateList ( ) ;
2023-01-12 09:23:45 +01:00
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 ) ) ;
}
2023-01-15 13:26:14 +01:00
}
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-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
{
2023-01-15 13:26:14 +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 13:26:14 +01:00
QGuiApplication : : setOverrideCursor ( Qt : : ArrowCursor ) ;
2023-01-07 12:44:45 +01:00
}
}
void MainWindow : : populateList ( )
{
stringstream ss ;
2023-01-15 13:26:14 +01:00
QString str ;
QString server ;
QString port ;
2023-01-07 12:44:45 +01:00
2023-01-15 13:26:14 +01:00
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 ;
2023-01-15 13:26:14 +01:00
QGuiApplication : : setOverrideCursor ( Qt : : WaitCursor ) ;
this - > settings . beginGroup ( " connexion/server " ) ;
if ( this - > settings . contains ( server ) )
2023-01-07 12:44:45 +01:00
{
2023-01-15 13:26:14 +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
{
2023-01-15 13:26:14 +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-12 09:23:45 +01:00
listServices ( ) ;
2023-01-07 12:44:45 +01:00
}
}
2023-01-15 13:26:14 +01:00
this - > settings . endGroup ( ) ;
QGuiApplication : : 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-15 13:26:14 +01:00
ui - > listWidget - > clear ( ) ;
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 ) )
{
2023-01-15 13:26:14 +01:00
//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-12 09:23:45 +01:00
return true ;
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 ) )
{
2023-01-15 13:26:14 +01:00
//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 ( )
{
2023-01-15 13:26:14 +01:00
//populateList();
2023-01-07 12:44:45 +01:00
}
2023-01-15 13:26:14 +01:00
void MainWindow : : on_khistorycombobox_currentIndexChanged ( int i )
2023-01-07 12:44:45 +01:00
{
2023-01-15 13:26:14 +01:00
/*QString server = ui->khistorycombobox->currentText();
this - > settings . beginGroup ( " connexion/server " ) ;
ui - > portEdit - > setText ( this - > settings . value ( server ) . toString ( ) ) ;
this - > settings . endGroup ( ) ; */
this - > populateList ( ) ;
2023-01-07 12:44:45 +01:00
}
2023-01-15 13:26:14 +01:00
void MainWindow : : on_portEdit_returnPressed ( )
2023-01-07 12:44:45 +01:00
{
2023-01-15 13:26:14 +01:00
populateList ( ) ;
2023-01-07 12:44:45 +01:00
}
void MainWindow : : on_actionDownload_triggered ( )
{
}
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 ;
}
void MainWindow : : on_listWidget_clicked ( const QModelIndex & index )
{
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 ( ) ;
}
void MainWindow : : on_treeWidget_itemDoubleClicked ( QTreeWidgetItem * item , int column )
{
QFuture < void > future ;
QFileDialog dialog ;
2023-01-12 09:23:45 +01:00
QCheckBox * cb = new QCheckBox ( " Okay I understand " ) ;
2023-01-07 12:44:45 +01:00
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-07 12:44:45 +01:00
2023-01-12 09:23:45 +01:00
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 ( )
{
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 ;
2023-01-15 13:26:14 +01:00
//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 ( )
{
2023-01-15 13:26:14 +01:00
this - > restoreGeometry ( settings . value ( " window/geometry " ) . toByteArray ( ) ) ;
this - > settings . beginGroup ( " connexion/server " ) ;
QStringList servers = this - > settings . allKeys ( ) ;
this - > settings . endGroup ( ) ;
for ( const QString & server : servers )
{
ui - > khistorycombobox - > addToHistory ( server ) ;
}
2023-01-12 09:23:45 +01:00
}
2023-01-15 13:26:14 +01:00
2023-01-12 09:23:45 +01:00
void MainWindow : : saveSettings ( )
{
2023-01-15 13:26:14 +01:00
this - > settings . setValue ( " window/geometry " , saveGeometry ( ) ) ;
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
}