2023-02-10 21:32:20 +01:00
# include "mainwindow.h"
2024-08-22 23:08:42 +02:00
# include <QtGlobal>
//#include <QComboBox>
2023-03-17 13:04:03 +01:00
# include <QTextBlock>
2024-08-22 23:08:42 +02:00
# include "ui_configuration.h"
2023-04-27 11:42:53 +02:00
# include "version.h"
2024-08-22 23:08:42 +02:00
# include "tools.h"
# include "password.h"
# include <kcombobox.h>
/*
# include <klineedit.h>
# include <khistorycombobox.h>
# include <kcompletion.h>
*/
2023-02-10 21:32:20 +01:00
using namespace std ;
bool display = false ;
extern Ui : : Configuration config ;
extern bool testRsyncReturn ( QProcess * ) ;
2023-03-09 18:13:46 +01:00
extern QApplication a ;
2023-02-10 21:32:20 +01:00
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 )
2024-08-22 23:08:42 +02:00
: QMainWindow ( parent )
, ui ( new Ui : : MainWindow )
2023-02-10 21:32:20 +01:00
{
ui - > setupUi ( this ) ;
QCoreApplication : : setOrganizationName ( " RsyncUI " ) ;
QCoreApplication : : setApplicationName ( " RsyncUI " ) ;
2023-03-09 18:13:46 +01:00
this - > setWindowTitle ( a . applicationName ( ) ) ;
2023-02-10 23:27:44 +01:00
// context menu for treewidget (list of files)
2023-02-10 21:32:20 +01:00
ui - > treeWidget - > addAction ( ui - > actionDownload ) ;
2023-02-10 23:27:44 +01:00
// init configuration window
2023-02-10 21:32:20 +01:00
config . setupUi ( & Configuration ) ;
2023-02-13 16:54:56 +01:00
// init about window
AboutW . setupUi ( & aboutDialog ) ;
// text of About
2023-04-27 11:42:53 +02:00
this - > about . version = version ;
2023-02-13 16:54:56 +01:00
QString aboutText = tr ( " <h2>Client for rsync server</h2> " ) +
2024-08-22 23:08:42 +02:00
" <b> " + tr ( " Version " ) + " : " + version + " </b><br> " +
" <b> " + tr ( " Licence " ) + " : " + this - > about . licence + " </b><br> " +
" <b> " + tr ( " Author " ) + " : " + this - > about . author + " </b><br> " +
" <b> " + tr ( " EMail " ) + " : " + this - > about . email + " </b><br> " +
" <b> " + tr ( " Source code " ) + " : " + this - > about . git + " </b><br> " +
tr ( " You click on file to enqueue it, and RyncUI Download one file a time " ) ;
2023-02-13 16:54:56 +01:00
AboutW . TextAbout - > setHtml ( aboutText ) ;
2024-08-22 23:08:42 +02:00
// initialization = true;
2023-02-10 21:32:20 +01:00
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " Initialization of widgets " ) ;
2023-02-10 21:32:20 +01:00
// init of widgets
2023-02-10 23:27:44 +01:00
ui - > ktreewidgetsearchline - > setTreeWidget ( ui - > treeWidget ) ; // attach search widget to treewidget
ui - > ktreewidgetsearchline - > setCaseSensitivity ( Qt : : CaseInsensitive ) ; // and set it case insensitive
2023-03-05 13:38:28 +01:00
ui - > treeWidget - > setHeaderLabels ( { tr ( " Path " ) , tr ( " Type " ) , tr ( " Size " ) , tr ( " Date " ) , " fullSize " } ) ; // set header of columns of tree widget
2024-08-22 23:08:42 +02:00
2023-02-10 23:27:44 +01:00
// setting arrowcursor for treeWidget, listWidget and listDownload to arrow
2023-02-10 21:32:20 +01:00
ui - > treeWidget - > setCursor ( Qt : : ArrowCursor ) ;
ui - > listWidget - > setCursor ( Qt : : ArrowCursor ) ;
ui - > listDownload - > setCursor ( Qt : : ArrowCursor ) ;
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " Hiding progress bar " ) ;
2023-02-10 21:32:20 +01:00
// Hiding progress bar
ui - > progressBar - > hide ( ) ;
//setting configuration window
2023-02-10 23:27:44 +01:00
config . comboBox - > setCurrentIndex ( ui - > toolBar - > toolButtonStyle ( ) ) ; // setting combobox to saved settings
//setting unit of bandwidth limit
2023-03-04 17:33:18 +01:00
config . UnitCombobox - > addItems ( { tr ( " KB/s " ) , tr ( " MB/s " ) , tr ( " GB/s " ) , tr ( " TB/s " ) , tr ( " PB/s " ) } ) ;
// hide fullsize column of treeview
2023-03-05 13:38:28 +01:00
ui - > treeWidget - > setColumnHidden ( 4 , true ) ;
2023-02-10 21:32:20 +01:00
2024-08-22 23:08:42 +02:00
loadSettings ( ) ;
2023-02-15 13:49:31 +01:00
initSystemTrayIcon ( ) ;
2024-08-22 23:08:42 +02:00
init ( ) ;
// if last server exists in settings
if ( this - > settings . contains ( " connexion/lastServer " ) )
{
info ( DEBUGMACRO , " Setting previous server " ) ;
// set window to previous server/port configuration
ui - > portEdit - > setText ( this - > settings . value ( " connexion/lastPort " ) . toString ( ) ) ;
ui - > khistorycombobox - > setCurrentText ( this - > settings . value ( " connexion/lastServer " ) . toString ( ) ) ;
} else
{
info ( DEBUGMACRO , " No previous server, so setting only default port " ) ;
ui - > portEdit - > setText ( QString : : number ( this - > connexion . port ) ) ;
ui - > khistorycombobox - > clear ( ) ;
}
// connectors
connect ( this , & MainWindow : : fileName , ui - > progressBar , & QProgressBar : : setFormat ) ;
connect ( this , & MainWindow : : progressSignal , ui - > progressBar , & QProgressBar : : setValue ) ;
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 ) ;
populateList ( ui - > khistorycombobox - > currentText ( ) , ui - > portEdit - > text ( ) . toUInt ( ) ) ;
initialization = false ;
2023-02-15 13:49:31 +01:00
}
void MainWindow : : init ( )
{
QAbstractButton * reply ;
QMessageBox msgBox ;
2023-02-10 23:27:44 +01:00
//if exists list of donwloads in saved settings
2023-02-10 21:32:20 +01:00
if ( this - > settings . value ( " Downloads/rows " ) . toInt ( ) ! = 0 )
{
2024-08-22 23:08:42 +02:00
// asking if we load the list and continue downloading
msgBox . setWindowTitle ( a . applicationName ( ) ) ;
msgBox . setInformativeText ( tr ( " A list of interrupted downloads exists, do you want to continue downloading ? if not the list will be cleared " ) ) ;
QPushButton * deleteButton = msgBox . addButton ( tr ( " Delete " ) , QMessageBox : : ActionRole ) ;
msgBox . addButton ( QMessageBox : : No ) ;
QPushButton * yes = msgBox . addButton ( QMessageBox : : Yes ) ;
msgBox . setDefaultButton ( QMessageBox : : Yes ) ;
msgBox . exec ( ) ;
reply = msgBox . clickedButton ( ) ;
info ( DEBUGMACRO , " Response => " + reply - > text ( ) ) ;
// if response is yes then loading list
info ( DEBUGMACRO , " reply text is : " + reply - > text ( ) ) ;
if ( reply = = yes )
{
loadDownloadList ( ) ;
} else if ( reply = = deleteButton )
{
// delete saved download list
deleteDownloadList ( ) ;
}
2023-02-10 21:32:20 +01:00
}
2023-02-12 00:37:50 +01:00
}
void MainWindow : : initSystemTrayIcon ( )
{
QMenu * trayIconMenu ;
QAction * quitAction ;
2023-02-16 21:28:58 +01:00
QIcon icon ;
2023-02-12 00:37:50 +01:00
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " initSystemTrayIcon " ) ;
2023-02-16 21:28:58 +01:00
icon . addFile ( this - > icon ) ;
2023-02-12 00:37:50 +01:00
this - > trayIcon = new QSystemTrayIcon ;
2023-02-16 21:28:58 +01:00
this - > trayIcon - > setIcon ( icon ) ;
2023-02-12 00:37:50 +01:00
quitAction = new QAction ( tr ( " &Quit " ) , this ) ;
connect ( quitAction , & QAction : : triggered , this , & MainWindow : : quitApp ) ;
trayIconMenu = new QMenu ( this ) ;
trayIconMenu - > addAction ( quitAction ) ;
trayIcon - > setContextMenu ( trayIconMenu ) ;
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " Connecting signal of trayIcon " ) ;
2023-02-12 00:37:50 +01:00
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 )
{
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " on_trayIcon_clicked " ) ;
2023-02-12 00:37:50 +01:00
if ( reason = = QSystemTrayIcon : : Trigger )
{
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " trayIcon is clicked " ) ;
if ( this - > isHidden ( ) )
{
this - > show ( ) ;
} else
{
this - > hide ( ) ;
}
2023-02-12 00:37:50 +01:00
}
}
void MainWindow : : hideWindow ( )
{
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " hideWindow() \n Hiding window " ) ;
2023-02-12 00:37:50 +01:00
this - > hide ( ) ;
}
void MainWindow : : showWindow ( )
{
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " showWindow() \n showing window " ) ;
2023-02-12 00:37:50 +01:00
this - > show ( ) ;
2023-02-10 21:32:20 +01:00
}
MainWindow : : ~ MainWindow ( )
{
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " Exiting application " ) ;
2023-02-10 21:32:20 +01:00
delete ui ;
2023-02-12 00:37:50 +01:00
QCoreApplication : : quit ( ) ;
2023-02-10 21:32:20 +01:00
}
2023-02-12 00:37:50 +01:00
void MainWindow : : quitApp ( )
2023-02-10 21:32:20 +01:00
{
QMessageBox : : StandardButton reply ;
QMessageBox : : StandardButtons param ;
2023-02-10 23:27:44 +01:00
QString displayText ;
2023-02-10 21:32:20 +01:00
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " Exiting application " ) ;
2023-02-10 21:32:20 +01:00
// saving settings
saveSettings ( ) ;
if ( ui - > listDownload - > count ( ) ! = 0 ) // some downloads waiting
{
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " Asking confirmation to exit " ) ;
// 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 ,
a . applicationName ( ) ,
tr ( " Exiting will stop downloading, and will clear the download queue. \n Do you want to exit ? " ) + displayText ,
param ,
QMessageBox : : No ) ;
this - > downloading . quit = true ;
if ( reply = = QMessageBox : : Yes )
{
info ( DEBUGMACRO , " Stopping downloads " ) ;
if ( this - > downloading . process - > state ( ) ! = QProcess : : NotRunning )
{
// emission of signal to downloading thread and stopping
emit ( stopDownloading ( this - > downloading . process ) ) ;
}
} else if ( reply = = QMessageBox : : Save )
{
if ( config . autosaveCheckbox - > checkState ( ) = = Qt : : Unchecked )
{
info ( DEBUGMACRO , " Saving download list " ) ;
//saveDownloadList();
emit ( stopDownloading ( this - > downloading . process ) ) ;
}
} else if ( reply = = QMessageBox : : No )
{
return ;
}
2023-02-10 21:32:20 +01:00
}
2023-02-12 00:37:50 +01:00
QCoreApplication : : quit ( ) ;
}
// Close window has been clicked
void MainWindow : : closeEvent ( QCloseEvent * event )
{
QMessageBox msgBox ;
2023-05-01 14:27:20 +02:00
QCheckBox * cb ;
2023-02-12 00:37:50 +01:00
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " closeEvent() => Closing window to systray " ) ;
2023-02-12 00:37:50 +01:00
if ( ! event - > spontaneous ( ) | | ! isVisible ( ) )
2024-08-22 23:08:42 +02:00
return ;
2023-05-01 14:27:20 +02:00
if ( trayIcon - > isVisible ( ) and this - > settings . value ( " CloseCheckbox " ) . toBool ( ) = = false )
{
2024-08-22 23:08:42 +02:00
cb = new QCheckBox ( " Don't show this again ? " ) ;
msgBox . setWindowTitle ( a . applicationName ( ) ) ;
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 . setCheckBox ( cb ) ;
msgBox . exec ( ) ;
msgBox . clickedButton ( ) ;
// if response is yes then loading list
if ( cb - > isChecked ( ) )
{
this - > settings . setValue ( " CloseCheckbox " , true ) ;
}
hide ( ) ;
//event->accept();
event - > ignore ( ) ;
2023-05-01 14:27:20 +02:00
}
2023-02-10 21:32:20 +01:00
}
// Populate treeview with list of files
2023-03-04 17:33:18 +01:00
void MainWindow : : populateTree ( )
2023-02-10 21:32:20 +01:00
{
QString path ;
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " populateTree() =>Populating listview " ) ;
2023-02-10 21:32:20 +01:00
// Clear treewidget
ui - > treeWidget - > clear ( ) ;
if ( ! this - > connexion . server . isEmpty ( ) and this - > connexion . port > 0 and this - > connexion . port < 65536 )
{
2024-08-22 23:08:42 +02:00
// setting cursor to "Wait"
QGuiApplication : : setOverrideCursor ( Qt : : WaitCursor ) ;
info ( DEBUGMACRO , " Validating server " ) ;
// validating server's address
this - > connexion . ipversion = validateServer ( this - > connexion . server ) ;
if ( this - > connexion . ipversion ! = 0 )
{
// server is validated, scanning directory
path = this - > connexion . service + " / " ;
while ( this - > rescan )
{
scanDir ( & this - > connexion , nullptr , path ) ;
}
}
// Restoring cursor
QGuiApplication : : restoreOverrideCursor ( ) ;
2023-02-10 21:32:20 +01:00
}
2024-08-22 23:08:42 +02:00
2023-02-10 21:32:20 +01:00
}
// Populate Listview with list of services
2024-08-22 23:08:42 +02:00
void MainWindow : : populateList ( QString server , uint port )
2023-02-10 21:32:20 +01:00
{
2023-03-08 16:03:24 +01:00
QString service ;
2023-03-02 17:06:15 +01:00
QStringList hidden ;
int i ;
2024-08-22 23:08:42 +02:00
bool ok = false ;
info ( DEBUGMACRO , " populateList() => Populating list of services " ) ;
info ( DEBUGMACRO , " port: " + QString : : number ( port ) + " - server: " + server ) ;
if ( server . isEmpty ( ) )
{
ui - > listWidget - > clear ( ) ;
ui - > treeWidget - > clear ( ) ;
return ;
}
if ( ( server ! = this - > connexion . server ) )
{
// Determine version of Ip Protocol
info ( DEBUGMACRO , " Server changed " ) ;
this - > connexion . server = server ;
if ( port ! = false )
{
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 ) )
{
info ( DEBUGMACRO , " Server configuration exists in settings " ) ;
// server is in history => setting port value
port = this - > settings . value ( server ) . toUInt ( ) ;
this - > connexion . ipversion = this - > settings . value ( " ipversion " ) . toUInt ( ) ;
ui - > portEdit - > setText ( QString : : number ( port ) ) ;
this - > connexion . port = port ;
ok = true ;
//display list of services
//listServices(); // TODO clear in listServices
}
this - > settings . endGroup ( ) ;
}
if ( port ! = this - > connexion . port )
{
info ( DEBUGMACRO , " Port changed " ) ;
this - > connexion . port = port ;
ok = true ;
//listServices(); // TODO clear in listServices
}
2023-02-10 21:32:20 +01:00
2024-08-22 23:08:42 +02:00
if ( ok = = true )
2023-10-10 23:14:31 +02:00
{
2024-08-22 23:08:42 +02:00
if ( this - > connexion . ipversion = = 0 )
{
this - > connexion . ipversion = validateServer ( server ) ;
info ( DEBUGMACRO , QString : : number ( this - > connexion . ipversion ) ) ;
}
if ( this - > connexion . ipversion ! = 0 )
{
info ( DEBUGMACRO , QString : : number ( this - > connexion . ipversion ) ) ;
info ( DEBUGMACRO , " server: " + server ) ;
info ( DEBUGMACRO , " Saving server configuration in settings " ) ;
// storing serverURL and port in settings
this - > settings . setValue ( server , port ) ;
this - > settings . setValue ( server , this - > connexion . ipversion ) ;
this - > settings . sync ( ) ;
this - > downloading . server = server ;
this - > downloading . ipversion = this - > connexion . ipversion ;
// storing in history of combobox
ui - > khistorycombobox - > addToHistory ( server ) ;
// load and display rsync services of the rsync server
}
2023-10-10 23:14:31 +02:00
} else
{
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " Error server not changed " ) ;
2023-10-10 23:14:31 +02:00
}
2024-08-22 23:08:42 +02:00
listServices ( ) ;
this - > settings . beginGroup ( " Hidden/ " + server ) ;
hidden = this - > settings . allKeys ( ) ;
if ( hidden . count ( ) > 0 )
2023-02-10 21:32:20 +01:00
{
2024-08-22 23:08:42 +02:00
for ( i = 0 ; i < hidden . size ( ) ; i + + )
{
service = hidden [ i ] ;
//TODO detect if service is already present
if ( testServerPresence ( service , false ) )
{
ui - > listWidget - > addItem ( service + " \n \t " ) ;
}
}
2023-02-10 21:32:20 +01:00
}
2024-08-22 23:08:42 +02:00
this - > settings . endGroup ( ) ;
// clearing listview
ui - > treeWidget - > clear ( ) ;
QGuiApplication : : restoreOverrideCursor ( ) ; //setting cursor to default
2023-02-10 21:32:20 +01:00
}
2023-03-08 16:03:24 +01:00
// Test if service is already present on the server
2024-08-22 23:08:42 +02:00
bool MainWindow : : testServerPresence ( QString service , bool askPassword )
2023-03-08 16:03:24 +01:00
{
QString cmd ;
QStringList param ;
QString line ;
QString errorRsync ;
QStringList v ;
QProcess * myProcess ;
bool returnValue = false ;
2023-04-26 17:30:38 +02:00
int loop = 0 ;
bool r = false ;
2023-03-08 16:03:24 +01:00
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " testServerPresence() => Test of rsync server " ) ;
info ( DEBUGMACRO , " ipversion = " + QString : : number ( this - > connexion . ipversion ) ) ;
2023-03-08 16:03:24 +01:00
cmd = " /usr/bin/rsync " ;
2024-08-22 23:08:42 +02:00
if ( this - > connexion . ipversion = = 4 | | this - > connexion . ipversion = = 6 )
{
param < < " - " + QString : : number ( this - > connexion . ipversion ) ;
}
param < < " --contimeout=10 " < < " -nq " < < " --port= " + QString : : number ( this - > connexion . port ) < < + " [ " + this - > connexion . server + " ]:: " + service ;
2023-03-08 16:03:24 +01:00
myProcess = new QProcess ( this ) ;
myProcess - > setProcessChannelMode ( QProcess : : MergedChannels ) ;
myProcess - > start ( cmd , param ) ;
myProcess - > waitForStarted ( ) ;
myProcess - > write ( " \n " ) ;
while ( myProcess - > waitForReadyRead ( 10000 ) )
{
2024-08-22 23:08:42 +02:00
while ( 1 )
{
// line empty then buffer is empty so returning to wait new datas
line = QString : : fromUtf8 ( myProcess - > readLine ( ) ) ;
if ( line . isEmpty ( ) )
{
break ;
}
if ( line . contains ( " auth failed " ) )
{
if ( askPassword = = true and loop > = 2 and r = = true )
{
r = getUserPassword ( & this - > connexion ) ;
loop + + ;
}
returnValue = true ;
}
}
2023-03-08 16:03:24 +01:00
}
if ( myProcess - > exitCode ( ) = = 0 )
{
2024-08-22 23:08:42 +02:00
returnValue = true ;
2023-03-08 16:03:24 +01:00
}
myProcess - > close ( ) ;
return returnValue ;
}
2023-02-10 21:32:20 +01:00
//list services of the rsync server
void MainWindow : : listServices ( )
{
QString cmd ;
QStringList param ;
QString line ;
QString errorRsync ;
QStringList v ;
QString service ;
2024-08-22 23:08:42 +02:00
QString server ;
2023-02-10 21:32:20 +01:00
QProcess * myProcess ;
bool flag = false ;
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " listServices() => Listing services offered by server " ) ;
// clearing listwidget
ui - > listWidget - > clear ( ) ;
2023-02-10 21:32:20 +01:00
cmd = " /usr/bin/rsync " ;
2024-08-22 23:08:42 +02:00
if ( this - > connexion . ipversion = = 0 )
{
this - > connexion . ipversion = whatIpVersion ( this - > connexion . server ) ;
}
if ( this - > connexion . ipversion = = 4 )
{
param < < " - " + QString : : number ( this - > connexion . ipversion ) . trimmed ( ) ;
server = this - > connexion . server . trimmed ( ) ;
} else if ( this - > connexion . ipversion = = 6 )
{
param < < " - " + QString : : number ( this - > connexion . ipversion ) . trimmed ( ) ;
server = " [ " + this - > connexion . server + " ] " ;
}
param < < " --contimeout=20 " < < " --port= " + QString : : number ( this - > connexion . port ) < < server + " :: " ;
2023-02-10 21:32:20 +01:00
myProcess = new QProcess ( this ) ;
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , cmd + " " + param . join ( " " ) ) ;
2023-02-10 21:32:20 +01:00
myProcess - > start ( cmd , param ) ;
2023-02-10 23:27:44 +01:00
// waiting for response of the server with a timeout of 10 seconds
2023-02-10 21:32:20 +01:00
while ( myProcess - > waitForReadyRead ( 10000 ) )
{
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " Reading " ) ;
while ( ! flag )
{
line = QString : : fromUtf8 ( myProcess - > readLine ( ) ) ;
// line empty then buffer is empty so returning to wait new datas
info ( DEBUGMACRO , " line: # " + line + " # " ) ;
if ( line . isEmpty ( ) )
{
info ( DEBUGMACRO , " line is empty " ) ;
flag = true ;
break ;
}
info ( DEBUGMACRO , " extracting services inforamtions " ) ;
// 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 ] ;
info ( DEBUGMACRO , " service is: " + service ) ;
info ( DEBUGMACRO , " adding to list widget of services " ) ;
ui - > listWidget - > addItem ( service ) ;
}
// buffer empty go to waiting new datas
flag = false ;
2023-02-10 21:32:20 +01:00
}
2023-02-10 23:27:44 +01:00
// verifying error code
2023-02-27 23:48:05 +01:00
testRsyncReturn ( this , myProcess ) ;
myProcess - > close ( ) ;
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " listServices finished " ) ;
2023-02-10 21:32:20 +01:00
}
// connect to rsync server to get list of files
2024-08-22 23:08:42 +02:00
bool MainWindow : : scanDir ( Connexion * connexion , QTreeWidgetItem * parent , QString path )
2023-02-10 21:32:20 +01:00
{
QString cmd ;
QStringList param ;
2023-03-04 17:33:18 +01:00
QStringList sizeA ;
2023-02-10 21:32:20 +01:00
QString line ;
QString size ;
2023-03-04 17:33:18 +01:00
QString fullsize ;
2023-02-10 21:32:20 +01:00
QString filename ;
2023-03-04 17:33:18 +01:00
QString fileType ;
2023-03-05 13:38:28 +01:00
QString date ;
2023-05-01 14:27:20 +02:00
QString dirName = " " ;
2023-02-10 21:32:20 +01:00
QProcess * myProcess ;
2023-03-08 16:03:24 +01:00
QProcessEnvironment env = QProcessEnvironment : : systemEnvironment ( ) ;
2023-02-10 21:32:20 +01:00
bool isDir = false ;
bool flag = false ;
2023-02-27 23:48:05 +01:00
bool readOk = false ;
2023-03-08 16:03:24 +01:00
bool passwdOk = false ;
2023-02-15 13:49:31 +01:00
int nChild = 0 ;
2023-04-26 17:30:38 +02:00
static uint looping ;
2023-05-01 14:27:20 +02:00
QStringList dirs ;
2024-08-22 23:08:42 +02:00
QString server = connexion - > server ;
info ( DEBUGMACRO , " scandir() => connect to rsync server to get list of files " ) ;
2023-02-10 21:32:20 +01:00
2023-02-27 23:48:05 +01:00
myProcess = new QProcess ( this ) ;
2023-03-08 16:03:24 +01:00
myProcess - > setProcessChannelMode ( QProcess : : MergedChannels ) ;
2023-03-01 14:12:38 +01:00
2023-02-27 23:48:05 +01:00
if ( parent ! = nullptr )
2023-02-15 13:49:31 +01:00
{
2024-08-22 23:08:42 +02:00
nChild = parent - > childCount ( ) ;
2023-02-15 13:49:31 +01:00
}
if ( nChild = = 0 )
{
2024-08-22 23:08:42 +02:00
if ( ! connexion - > user . isEmpty ( ) )
{
server . prepend ( connexion - > user + " @ " ) ;
env . insert ( " RSYNC_PASSWORD " , connexion - > password ) ; // Add an environment variable
} else
{
server . prepend ( " anonymous@ " ) ;
env . insert ( " RSYNC_PASSWORD " , " anonymous " ) ; // Add an environment variable
}
myProcess - > setProcessEnvironment ( env ) ;
info ( DEBUGMACRO , " ipversion => " + QString : : number ( connexion - > ipversion ) ) ;
cmd = " rsync " ;
if ( this - > connexion . ipversion = = 4 | | this - > connexion . ipversion = = 6 )
{
param < < " - " + QString : : number ( connexion - > ipversion ) . trimmed ( ) ;
}
param < < " --contimeout=20 " < < " --port= " + QString : : number ( connexion - > port ) < < " [ " + server + " ]:: " + path ;
info ( DEBUGMACRO , cmd + " " + param . join ( " " ) ) ;
myProcess - > start ( cmd , param ) ;
this - > rescan = true ;
info ( DEBUGMACRO , " Waiting server response " ) ;
// waiting for response of the server with a timeout of 10 seconds
do
{
readOk = myProcess - > waitForReadyRead ( 10000 ) ;
if ( readOk )
{
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 ;
}
if ( line . contains ( " auth failed " ) )
{
myProcess - > readAllStandardOutput ( ) ;
getUserPassword ( connexion ) ;
if ( looping < = 1 )
{
this - > rescan = true ;
looping + + ;
} else
{
this - > rescan = false ;
looping = 0 ;
warning ( tr ( " Authentication failed " ) ) ;
}
return false ;
}
// extracting name, size and is dir/file
line = line . simplified ( ) ;
filename = line . section ( " " , 4 ) ;
if ( filename ! = ' . ' )
{
size = line . section ( " " , 1 , 1 ) ;
fullsize = size ;
fullsize . remove ( " , " ) ;
sizeA = size . split ( ' , ' ) ;
if ( sizeA . count ( ) < = 1 )
{
size = sizeA . at ( 0 ) + " " + UnitText [ 0 ] + " " ;
} else
{
myProcess - > setProcessEnvironment ( env ) ;
size = sizeA . at ( 0 ) + " , " + sizeA . at ( 1 ) . left ( 2 ) + " " + UnitText [ sizeA . count ( ) - 1 ] + " " ;
}
if ( line [ 0 ] = = " d " )
{
isDir = true ;
} else
{
isDir = false ;
}
date = line . section ( ' ' , 2 , 2 ) ;
fileType = getFileType ( filename ) ;
if ( ! path . isEmpty ( ) )
{
if ( path . endsWith ( ' / ' ) )
{
path . chop ( 1 ) ;
}
dirs = path . split ( ' / ' ) ;
dirName = dirs [ dirs . size ( ) - 1 ] ;
}
addTreeItem ( filename , size , fullsize , fileType , date , isDir , dirName , parent ) ;
if ( passwdOk = = false and ! connexion - > password . isEmpty ( ) )
{
this - > settings . setValue ( " Passwords/ " + connexion - > server + " / " + connexion - > service + " / " + connexion - > user , true ) ;
setPassword ( connexion - > user , connexion - > password ) ;
this - > settings . sync ( ) ;
}
this - > rescan = false ;
}
}
flag = false ;
} else
{
if ( myProcess - > state ( ) = = QProcess : : Running )
{
if ( myProcess - > waitForFinished ( 10000 ) = = 0 )
{
warning ( tr ( " The processus does'nt respond: " ) + myProcess - > errorString ( ) ) ;
}
}
}
} while ( readOk ) ;
// buffer empty go to waiting new datas
testRsyncReturn ( this , myProcess ) ;
myProcess - > close ( ) ;
2023-02-10 21:32:20 +01:00
}
2023-04-26 17:30:38 +02:00
return false ;
2023-02-10 21:32:20 +01:00
}
// validate address server
2024-08-22 23:08:42 +02:00
uint MainWindow : : validateServer ( QString server )
2023-02-10 21:32:20 +01:00
{
QString cmd ;
QStringList param ;
QString line ;
QProcess * myProcess ;
2024-08-22 23:08:42 +02:00
QStringList responseList ;
2023-02-10 21:32:20 +01:00
2024-08-22 23:08:42 +02:00
uint ipversion ;
int answerFound = 0 ;
int queryPos = 0 ;
2023-02-10 21:32:20 +01:00
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " ValidateServer() => Validating server address " ) ;
2023-02-10 21:32:20 +01:00
2024-08-22 23:08:42 +02:00
ipversion = whatIpVersion ( server ) ;
2023-02-10 21:32:20 +01:00
2024-08-22 23:08:42 +02:00
if ( ipversion = = 0 ) // not an Ip address, perhaps a server name
2023-02-10 21:32:20 +01:00
{
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " Digging server name " ) ;
cmd = " dig " ;
param < < " -t A " ; // IP V4 query
param < < " -t AAAA " ; // IP V6 query
param < < server . trimmed ( ) ;
info ( DEBUGMACRO , cmd + " " + param . join ( " " ) ) ;
myProcess = new QProcess ( this ) ;
myProcess - > start ( cmd , param ) ;
// making a dig on the server's address
while ( myProcess - > waitForReadyRead ( ) )
{
while ( 1 ) //!bflag)
{
line = QString : : fromUtf8 ( myProcess - > readAllStandardOutput ( ) ) ;
info ( DEBUGMACRO , line ) ;
// line empty then buffer is empty so returning to wait new datas
if ( line . isEmpty ( ) )
{
break ;
} else
{
answerFound = line . indexOf ( " ;; ANSWER SECTION: " ) + 19 ;
info ( DEBUGMACRO , " Position of answer line is : " + QString : : number ( answerFound ) ) ;
if ( answerFound ! = - 1 )
{
info ( DEBUGMACRO , " Serching IP address " ) ;
queryPos = line . indexOf ( " ;; Query " ) ;
info ( DEBUGMACRO , " Position of Query line is : " + QString : : number ( queryPos ) ) ;
if ( answerFound < queryPos )
{
line = line . mid ( answerFound , queryPos - answerFound ) ;
info ( DEBUGMACRO , " line is: \n " + line ) ;
responseList = line . split ( QRegExp ( " \\ s+ " ) ) ;
info ( DEBUGMACRO , " ip Address is => " + responseList . at ( 4 ) ) ;
if ( responseList . at ( 3 ) = = " A " )
{
return 4 ;
} else if ( responseList . at ( 3 ) = = " AAAA " )
{
return 6 ;
}
}
}
}
}
}
myProcess - > close ( ) ;
2023-02-10 21:32:20 +01:00
}
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " Returning ip version: " + QString : : number ( ipversion ) ) ;
return ipversion ;
2023-02-10 21:32:20 +01:00
2024-08-22 23:08:42 +02:00
return 0 ;
2023-02-10 21:32:20 +01:00
}
// slot activated when button connection is clicked
void MainWindow : : on_connectButton_clicked ( )
{
2024-08-22 23:08:42 +02:00
QString server ;
uint port ;
info ( DEBUGMACRO , " on_connectButton_clicked() => Connexion button clicked " ) ;
server = ui - > khistorycombobox - > currentText ( ) ;
port = ui - > portEdit - > text ( ) . toUInt ( ) ;
populateList ( server , port ) ;
2023-02-10 21:32:20 +01:00
}
2023-03-04 17:33:18 +01:00
// add parent in treeview
2023-05-01 14:27:20 +02:00
void MainWindow : : addTreeItem ( QString name , QString fileSize , QString fullsize , QString type , QString date , bool isDir = false , QString dirName = " " , QTreeWidgetItem * parent = nullptr )
2023-03-04 17:33:18 +01:00
{
2023-05-01 14:27:20 +02:00
QFont font ;
2023-03-04 17:33:18 +01:00
QTreeWidgetItem * treeItem ;
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " addTreeItem() => adding item to treeview " ) ;
2023-03-04 17:33:18 +01:00
if ( parent ! = nullptr )
{
2024-08-22 23:08:42 +02:00
treeItem = new QTreeWidgetItem ( ) ;
2023-03-04 17:33:18 +01:00
} else
{
2024-08-22 23:08:42 +02:00
treeItem = new QTreeWidgetItem ( ui - > treeWidget ) ;
2023-03-04 17:33:18 +01:00
}
2023-05-01 14:27:20 +02:00
// item is a file
if ( QFile : : exists ( this - > downloading . savePath + " / " + name ) or QFile : : exists ( this - > downloading . savePath + " / " + dirName + " / " + name ) )
{
2024-08-22 23:08:42 +02:00
QBrush b ( Qt : : green ) ;
treeItem - > setForeground ( 0 , b ) ;
treeItem - > setFont ( 0 , font ) ;
2023-05-01 14:27:20 +02:00
} else if ( this - > settings . contains ( name ) )
{
2024-08-22 23:08:42 +02:00
QBrush b ( Qt : : red ) ;
treeItem - > setForeground ( 0 , b ) ;
treeItem - > setFont ( 0 , font ) ;
2023-05-01 14:27:20 +02:00
}
2023-03-04 17:33:18 +01:00
if ( isDir = = true )
{
2024-08-22 23:08:42 +02:00
// item is a dir
treeItem - > setText ( 1 , tr ( " Dir " ) ) ;
treeItem - > setIcon ( 0 , QIcon : : fromTheme ( " folder " ) ) ;
2023-03-04 17:33:18 +01:00
} else
{
2024-08-22 23:08:42 +02:00
// item is a file
this - > settings . beginGroup ( " Downloaded/ " ) ;
this - > settings . endGroup ( ) ;
treeItem - > setText ( 1 , type ) ;
2023-03-04 17:33:18 +01:00
}
treeItem - > setText ( 0 , name ) ;
treeItem - > setText ( 2 , fileSize ) ;
2023-03-05 13:38:28 +01:00
treeItem - > setText ( 3 , date ) ;
treeItem - > setText ( 4 , fullsize ) ;
2023-03-04 17:33:18 +01:00
treeItem - > setTextAlignment ( 2 , Qt : : AlignRight ) ;
if ( parent ! = nullptr )
{
2024-08-22 23:08:42 +02:00
parent - > addChild ( treeItem ) ;
2023-03-04 17:33:18 +01:00
}
}
2023-02-10 21:32:20 +01:00
2023-03-02 17:06:15 +01:00
// Slot activated when a service in the list is clicked
2023-02-10 21:32:20 +01:00
void MainWindow : : on_listWidget_clicked ( )
2023-03-02 17:06:15 +01:00
{
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " on_listWidget_clicked() => Slot activated when a service in the list is clicked " ) ;
2023-03-02 17:06:15 +01:00
this - > connexion . service = ui - > listWidget - > currentItem ( ) - > text ( ) . section ( " \n " , 0 , 0 ) ;
2023-03-08 16:03:24 +01:00
ui - > treeWidget - > clear ( ) ;
2023-03-02 17:06:15 +01:00
preparePopulateTree ( ) ;
}
void MainWindow : : preparePopulateTree ( )
2023-02-10 21:32:20 +01:00
{
QString str ;
2023-02-27 23:48:05 +01:00
QStringList logins ;
2023-02-10 21:32:20 +01:00
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " preparePopulateTree() " ) ;
2023-03-01 14:12:38 +01:00
this - > rescan = true ;
2023-02-27 23:48:05 +01:00
this - > connexion . user = nullptr ;
2023-03-02 17:06:15 +01:00
this - > connexion . password = nullptr ;
2023-02-10 21:32:20 +01:00
str = " Folder/ " + this - > connexion . server + " / " + this - > connexion . service ;
2024-08-22 23:08:42 +02:00
2023-02-10 23:27:44 +01:00
// if service exists in settings for this server
2023-02-10 21:32:20 +01:00
if ( this - > settings . contains ( str ) )
{
2024-08-22 23:08:42 +02:00
// setting savePath from settings
this - > downloading . savePath = this - > settings . value ( str ) . toString ( ) ;
2023-02-10 21:32:20 +01:00
}
2023-03-04 17:33:18 +01:00
populateTree ( ) ;
2023-02-10 21:32:20 +01:00
}
2023-03-01 14:12:38 +01:00
// get password and user login
// if object = false ==> searching from connexion object
// else searching from downloading object
2023-03-08 16:03:24 +01:00
bool MainWindow : : getUserPassword ( Connexion * object )
2023-02-27 23:48:05 +01:00
{
QStringList logins ;
2023-04-26 17:30:38 +02:00
QString login = " " ;
QString password = " " ;
2023-03-08 16:03:24 +01:00
QString server ;
QString service ;
2023-03-11 13:30:17 +01:00
int c ;
2023-03-08 16:03:24 +01:00
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " getUserPassword() => get password and user login " ) ;
2023-03-08 16:03:24 +01:00
bool returnValue = false ;
2023-03-05 14:18:43 +01:00
bool ok = false ;
2023-02-27 23:48:05 +01:00
2023-03-08 16:03:24 +01:00
server = object - > server ;
service = object - > service ;
object - > user = " " ;
object - > password = " " ;
2023-03-05 14:18:43 +01:00
2023-03-08 16:03:24 +01:00
this - > settings . beginGroup ( " Passwords/ " + server + " / " + service ) ;
logins = this - > settings . allKeys ( ) ;
2023-03-11 13:30:17 +01:00
c = logins . count ( ) ;
if ( c ! = 1 )
2023-02-27 23:48:05 +01:00
{
2024-08-22 23:08:42 +02:00
//choose login in case of multiples logins
login = QInputDialog : : getItem ( this ,
" RsincUI " ,
tr ( " Select the user you want to connect with or enter a new one " ) ,
logins ,
0 ,
true ,
& ok ,
Qt : : Popup ,
Qt : : ImhNoPredictiveText
) ;
if ( ok and ! login . isEmpty ( ) )
{
if ( ! logins . contains ( login ) )
{
password = QInputDialog : : getText ( this ,
a . applicationName ( ) + tr ( " Request " ) ,
tr ( " Enter password " ) , QLineEdit : : Password ,
" " , & ok , Qt : : Popup ,
Qt : : ImhNoPredictiveText ) ;
if ( ! ok or password . isEmpty ( ) )
{
password = " " ;
returnValue = false ;
}
} else
{
password = getPassword ( login ) ;
returnValue = true ;
}
object - > user = login ;
object - > password = password ;
}
2023-02-27 23:48:05 +01:00
} else
{
2024-08-22 23:08:42 +02:00
object - > user = logins . at ( 0 ) ;
object - > password = getPassword ( object - > user ) ;
returnValue = true ;
2023-02-27 23:48:05 +01:00
}
this - > settings . endGroup ( ) ;
return returnValue ;
}
2023-02-10 21:32:20 +01:00
//Slot activated when a file is clicked in the treeview
void MainWindow : : on_treeWidget_itemClicked ( QTreeWidgetItem * item , bool downloadDir )
{
QTreeWidgetItem * itemR ;
QString path ;
QString str ;
2023-02-11 01:14:14 +01:00
QMessageBox : : StandardButton reply ;
2023-02-15 13:49:31 +01:00
int sizeFromRsync ;
2023-02-10 21:32:20 +01:00
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " on_treeWidget_itemClicked() => Slot activated when a file is clicked in the treeview " ) ;
if ( this - > treeviewClicked = = true )
2023-10-10 23:14:31 +02:00
{
2024-08-22 23:08:42 +02:00
return ;
2023-10-10 23:14:31 +02:00
}
2024-08-22 23:08:42 +02:00
this - > treeviewClicked = true ;
2023-02-10 21:32:20 +01:00
itemR = item ;
2023-03-18 12:48:39 +01:00
this - > rescan = true ;
2023-02-10 21:32:20 +01:00
2023-02-10 23:27:44 +01:00
// assembling path from treewidget
2023-02-10 21:32:20 +01:00
path = item - > text ( 0 ) ;
2023-03-05 13:38:28 +01:00
sizeFromRsync = item - > text ( 4 ) . toUInt ( ) ;
2023-02-11 01:14:14 +01:00
2023-02-10 21:32:20 +01:00
while ( itemR - > parent ( ) ! = NULL )
{
2024-08-22 23:08:42 +02:00
itemR = itemR - > parent ( ) ;
// concatening parent to path
path . prepend ( itemR - > text ( 0 ) + " / " ) ;
2023-02-10 21:32:20 +01:00
} ;
2023-03-02 17:06:15 +01:00
2023-03-01 15:50:37 +01:00
cout < < item - > text ( 1 ) . toStdString ( ) < < endl ;
2023-03-05 13:38:28 +01:00
if ( item - > text ( 1 ) ! = tr ( " Dir " ) or downloadDir = = true )
2023-02-10 21:32:20 +01:00
{
2024-08-22 23:08:42 +02:00
// 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 " < < endl ;
this - > treeviewClicked = false ;
return ;
}
} else
{
this - > downloading . savePath = this - > settings . value ( str ) . toString ( ) ;
}
// Item is a file
// searching if file exists in savepath
if ( QFile : : exists ( this - > downloading . savePath + " / " + path ) )
{
QFileInfo fileinfo ( this - > downloading . savePath + " / " + path ) ;
if ( fileinfo . size ( ) < sizeFromRsync )
{
reply = QMessageBox : : question (
this ,
a . applicationName ( ) ,
tr ( " File is partially downloaded. Do you want to resume download ? if no, the file will be deleted from destination directory " ) ,
QMessageBox : : Yes | QMessageBox : : No | QMessageBox : : Cancel ,
QMessageBox : : Cancel ) ;
if ( reply = = QMessageBox : : Cancel )
{
this - > treeviewClicked = false ;
return ;
} else if ( reply = = QMessageBox : : No )
{
QFile : : remove ( this - > downloading . savePath + " / " + path ) ;
this - > treeviewClicked = false ;
return ;
}
} else
{
reply = QMessageBox : : question (
this ,
a . applicationName ( ) ,
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 )
{
this - > treeviewClicked = false ;
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 . port = this - > connexion . port ;
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
{
warning ( tr ( " File is already downloading " ) ) ;
}
2023-02-10 21:32:20 +01:00
} else
{
2024-08-22 23:08:42 +02:00
//Item is a Directory
if ( item - > isExpanded ( ) = = false )
{
while ( this - > rescan )
{
scanDir ( & this - > connexion , item , this - > connexion . service + " / " + path + " / " ) ;
item - > setExpanded ( true ) ;
}
}
2023-02-10 21:32:20 +01:00
}
2023-03-11 13:30:17 +01:00
2023-02-10 21:32:20 +01:00
if ( config . autosaveCheckbox - > checkState ( ) = = Qt : : Checked )
{
2024-08-22 23:08:42 +02:00
saveDownloadList ( ) ;
2023-02-10 21:32:20 +01:00
}
2024-08-22 23:08:42 +02:00
this - > treeviewClicked = false ;
2023-02-10 21:32:20 +01:00
}
// Launch the thread which download the file
void MainWindow : : startDownloading ( )
{
2023-02-27 23:48:05 +01:00
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " startDownloading() => Launch the thread which download the file " ) ;
2023-02-10 21:32:20 +01:00
ui - > progressBar - > setValue ( 0 ) ;
ui - > progressBar - > show ( ) ;
2023-03-08 16:03:24 +01:00
//getUserPassword();
2023-02-10 21:32:20 +01:00
//QtConcurrent::run(&this->downloadO, &downloadFile::download, this);
2023-02-15 13:49:31 +01:00
this - > download ( ) ;
2023-03-09 18:13:46 +01:00
this - > trayIcon - > showMessage ( a . applicationName ( ) , tr ( " Starting downloading \n " ) + this - > downloading . path , QSystemTrayIcon : : Information ) ;
2023-02-10 21:32:20 +01:00
}
// Slot stopping download
void MainWindow : : stoppingDownload ( )
{
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " stoppingDownload " ) ;
2023-02-10 21:32:20 +01:00
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 ;
2023-02-10 23:27:44 +01:00
int pos ;
2023-02-12 19:11:06 +01:00
QString aborted = tr ( " finished " ) ;
2023-03-05 13:38:28 +01:00
QMessageBox : : StandardButton reply ;
bool retry = false ;
2023-02-10 21:32:20 +01:00
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " downloadFinished() => when download is finished, launch download of next file in queue " ) ;
info ( DEBUGMACRO , " Download finished with status " + QString : : number ( exitCode ) ) ;
2023-02-10 23:27:44 +01:00
// test if process crashed
2023-02-10 21:32:20 +01:00
if ( exitStatus = = QProcess : : CrashExit )
{
2024-08-22 23:08:42 +02:00
warning ( tr ( " Rsync process crashed " ) ) ;
2023-02-10 21:32:20 +01:00
}
2023-02-10 23:27:44 +01:00
//test result code of command (if 20 then command stopped by user)
2023-03-11 13:53:05 +01:00
if ( exitCode ! = 0 and this - > stopDlAsked ! = true )
2023-02-10 21:32:20 +01:00
{
2024-08-22 23:08:42 +02:00
if ( exitCode = = 20 )
{
if ( this - > exiting )
{
return ;
}
aborted = tr ( " stopped by user " ) ;
} else if ( exitCode = = 5 ) // password asked
{
getUserPassword ( & this - > downloading ) ;
retry = true ;
}
// displaying warning with exit code
reply = QMessageBox : : warning (
this ,
a . applicationName ( ) ,
tr ( rsyncErrorStrings [ exitCode ] . toStdString ( ) . c_str ( ) ) + tr ( " \n Do you want to retry? " ) ,
QMessageBox : : Yes | QMessageBox : : No ,
QMessageBox : : Yes ) ;
if ( reply = = QMessageBox : : Yes )
{
retry = true ;
}
2023-02-10 21:32:20 +01:00
}
2023-03-11 13:53:05 +01:00
this - > stopDlAsked = false ;
2023-03-09 18:13:46 +01:00
this - > trayIcon - > showMessage ( a . applicationName ( ) , tr ( " Download " ) + aborted + " \n " + this - > downloading . path , QSystemTrayIcon : : Information ) ;
2023-02-12 19:11:06 +01:00
2023-02-10 23:27:44 +01:00
// disconnecting signals to slots
2023-02-10 21:32:20 +01:00
disconnect ( this - > downloading . process , 0 , 0 , 0 ) ;
2023-02-10 23:27:44 +01:00
2023-03-08 16:03:24 +01:00
// reset variables and window, close process
2023-02-27 23:48:05 +01:00
this - > downloading . process - > close ( ) ;
2023-02-10 21:32:20 +01:00
ui - > progressBar - > hide ( ) ;
2023-03-05 13:38:28 +01:00
if ( retry = = false )
{
2024-08-22 23:08:42 +02:00
QString filename = ui - > listDownload - > item ( 0 ) - > text ( ) ;
pos = filename . contains ( " => " ) ;
filename . resize ( pos ) ;
delete ui - > listDownload - > takeItem ( 0 ) ;
2023-03-05 13:38:28 +01:00
}
2023-02-10 21:32:20 +01:00
this - > downloading . clear ( ) ;
2023-02-10 23:27:44 +01:00
// Some downloads staying in queue
2023-02-10 21:32:20 +01:00
if ( ui - > listDownload - > count ( ) ! = 0 )
{
2024-08-22 23:08:42 +02:00
// 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 . port = this - > settings . value ( " connexion/server/ " + this - > downloading . server ) . toInt ( ) ;
this - > downloading . path = path ;
//getUserPassword(true);
testServerPresence ( this - > downloading . service , true ) ;
// 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 ( ) ;
sleep ( 2 ) ;
startDownloading ( ) ;
} else
{
// no save path
if ( ! on_DefaultSaveFolder_triggered ( ) )
{
cout < < " Error no save path so removing download " ;
return ;
}
}
2023-02-10 21:32:20 +01:00
}
2023-02-15 13:49:31 +01:00
if ( config . autosaveCheckbox - > checkState ( ) = = Qt : : Checked and this - > downloading . quit = = false )
{
2024-08-22 23:08:42 +02:00
saveDownloadList ( ) ;
2023-02-15 13:49:31 +01:00
}
2023-02-10 21:32:20 +01:00
}
// Slot activated when a line is clicked in queue list
void MainWindow : : on_listDownload_itemClicked ( QListWidgetItem * item )
{
QMessageBox : : StandardButton reply ;
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " on_listDownload_itemClicked() => Slot activated when a line is clicked in queue list " ) ;
2023-02-10 21:32:20 +01:00
if ( item - > listWidget ( ) - > row ( item ) = = 0 )
{
2024-08-22 23:08:42 +02:00
// first line clicked on download list
reply = QMessageBox : : question (
this ,
a . applicationName ( ) ,
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
this - > stopDlAsked = true ;
emit ( stopDownloading ( this - > downloading . process ) ) ;
}
2023-02-10 21:32:20 +01:00
} else
{
2024-08-22 23:08:42 +02:00
// not first line on download list
reply = QMessageBox : : question (
this ,
a . applicationName ( ) ,
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 ;
}
2023-02-10 21:32:20 +01:00
}
2023-02-15 13:49:31 +01:00
if ( config . autosaveCheckbox - > checkState ( ) = = Qt : : Checked )
{
2024-08-22 23:08:42 +02:00
// autosave acivated,so saving download list
saveDownloadList ( ) ;
2023-02-15 13:49:31 +01:00
}
2023-02-10 21:32:20 +01:00
}
// load settings
void MainWindow : : loadSettings ( )
{
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " loadSettings() => restoring geometry and state of window and widgets " ) ;
2023-02-10 21:32:20 +01:00
// 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 )
{
2024-08-22 23:08:42 +02:00
this - > config . autosaveCheckbox - > setChecked ( true ) ;
2023-02-10 21:32:20 +01:00
}
// loading connexion settings
// loading servers history
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " Restoring server combobox history " ) ;
2023-02-10 21:32:20 +01:00
this - > settings . beginGroup ( " connexion/server " ) ;
QStringList servers = this - > settings . allKeys ( ) ;
this - > settings . endGroup ( ) ;
2024-08-22 23:08:42 +02:00
ui - > khistorycombobox - > insertItems ( 1 , this - > settings . value ( " kHistoryComboBox " ) . toStringList ( ) ) ;
2023-02-10 21:32:20 +01:00
// 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 ( )
{
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " saveSettings() => Saving settings " ) ;
2023-02-10 21:32:20 +01:00
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 ) ) ;
2024-08-22 23:08:42 +02:00
this - > settings . setValue ( " connexion/lastIpversion " , QString : : number ( this - > connexion . ipversion ) ) ;
2023-02-10 21:32:20 +01:00
this - > settings . setValue ( " toolbar/state " , ui - > toolBar - > toolButtonStyle ( ) ) ;
this - > settings . setValue ( " Autosave " , this - > config . autosaveCheckbox - > checkState ( ) ) ;
2024-08-22 23:08:42 +02:00
this - > settings . setValue ( " kHistoryComboBox " , ui - > khistorycombobox - > historyItems ( ) ) ;
2023-02-10 21:32:20 +01:00
this - > settings . sync ( ) ;
}
// About
void MainWindow : : on_actionAbout_triggered ( )
{
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " on_actionAbout_triggered() => display about informations " ) ;
2023-02-13 16:54:56 +01:00
aboutDialog . show ( ) ;
2023-02-10 21:32:20 +01:00
}
// About QT
void MainWindow : : on_actionAbout_Qt_triggered ( )
{
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " on_actionAbout_Qt_triggered() => display QT about information " ) ;
2023-02-10 21:32:20 +01:00
QMessageBox : : aboutQt ( this ) ;
}
// Activated when menu "change folder" is clicked
bool MainWindow : : on_DefaultSaveFolder_triggered ( )
{
2024-08-22 23:08:42 +02:00
QFileDialog dialog ;
QString folder ;
QString path ;
info ( DEBUGMACRO , " on_DefaultSaveFolder_triggered() => Activated when menu 'change folder' is clicked " ) ;
// if service not selected display a message
if ( this - > connexion . service . isEmpty ( ) )
{
warning ( 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 ;
2023-02-10 21:32:20 +01:00
}
// Activated when menu "settings" is clicked
void MainWindow : : on_action_Settings_triggered ( )
{
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " on_action_Settings_triggered() => Activated when menu 'settings' is clicked " ) ;
2023-02-10 21:32:20 +01:00
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 ;
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " on_buttonBox_accepted() => Acivated when 'Ok' is clicked in Configuration window " ) ;
2023-02-10 21:32:20 +01:00
bw = config . spinBox - > text ( ) ;
if ( bw . toInt ( ) = = 0 )
{
2024-08-22 23:08:42 +02:00
// bandwidth = 0
this - > connexion . bandwidthLimit = 0 ;
this - > connexion . bandwidthLimitUnit = 0 ;
2023-02-10 21:32:20 +01:00
} else
{
2024-08-22 23:08:42 +02:00
this - > connexion . bandwidthLimit = config . spinBox - > value ( ) ;
this - > connexion . bandwidthLimitUnit = config . UnitCombobox - > currentIndex ( ) ;
2023-02-10 21:32:20 +01:00
}
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 ;
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " saveDownloadList() => Saving download list " ) ;
2023-02-10 23:27:44 +01:00
// remove list of downloads
2023-02-10 21:32:20 +01:00
this - > settings . remove ( " Downloads/ " ) ;
2023-02-10 23:27:44 +01:00
// Saving list of current downloads
2023-02-10 21:32:20 +01:00
nRows = ui - > listDownload - > count ( ) ;
this - > settings . beginGroup ( " Downloads " ) ;
this - > settings . setValue ( " rows " , nRows ) ;
for ( int i = 0 ; i < nRows ; i + + )
{
2024-08-22 23:08:42 +02:00
this - > settings . setValue ( QString : : number ( i ) , ui - > listDownload - > item ( i ) - > text ( ) ) ;
2023-02-10 21:32:20 +01:00
}
this - > settings . endGroup ( ) ;
this - > settings . sync ( ) ;
}
2023-02-10 23:27:44 +01:00
// Loading download list
2023-02-10 21:32:20 +01:00
void MainWindow : : loadDownloadList ( )
{
QString path ;
QString str ;
int pos ;
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " loadDownloadList() => loading download list " ) ;
2023-02-10 23:27:44 +01:00
this - > settings . sync ( ) ;
2023-02-10 21:32:20 +01:00
this - > settings . beginGroup ( " Downloads " ) ;
int size = this - > settings . value ( " rows " ) . toInt ( ) ;
for ( int i = 0 ; i < size ; + + i )
{
2024-08-22 23:08:42 +02:00
ui - > listDownload - > addItem ( this - > settings . value ( QString : : number ( i ) ) . toString ( ) ) ;
2023-02-10 21:32:20 +01:00
}
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 ( ) ;
2023-02-22 00:48:16 +01:00
this - > downloading . port = this - > settings . value ( " connexion/server/ " + this - > downloading . server ) . toInt ( ) ;
2023-02-10 21:32:20 +01:00
path . resize ( pos ) ;
this - > downloading . path = path ;
str = " Folder/ " + this - > downloading . server + " / " + this - > downloading . service ;
if ( this - > settings . contains ( str ) )
{
2024-08-22 23:08:42 +02:00
this - > downloading . savePath = this - > settings . value ( str ) . toString ( ) ;
2023-02-10 21:32:20 +01:00
}
startDownloading ( ) ;
}
2024-08-22 23:08:42 +02:00
// Deleting download list
void MainWindow : : deleteDownloadList ( )
{
info ( DEBUGMACRO , " deleteDownloadList() => Deleting existing download list " ) ;
this - > settings . remove ( " Downloads " ) ;
}
2023-02-10 23:27:44 +01:00
// clear object downloading
2023-03-08 16:03:24 +01:00
void Connexion : : clear ( )
2023-02-10 21:32:20 +01:00
{
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " clear() => clear object 'downloading' " ) ;
2023-02-10 21:32:20 +01:00
this - > path . clear ( ) ;
this - > server . clear ( ) ;
this - > savePath . clear ( ) ;
this - > service . clear ( ) ;
2023-02-27 23:48:05 +01:00
this - > user . clear ( ) ;
this - > password . clear ( ) ;
this - > port = 0 ;
this - > process = nullptr ;
this - > quit = false ;
2023-02-10 21:32:20 +01:00
}
2023-02-10 23:27:44 +01:00
// Context menu of file list clicked
2023-02-10 21:32:20 +01:00
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 ) ;
}
2023-02-13 16:54:56 +01:00
// Change toolbar style
2023-02-10 21:32:20 +01:00
void MainWindow : : on_comboBox_currentIndexChanged ( int index )
{
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " on_comboBox_currentIndexChanged() " ) ;
2023-02-10 21:32:20 +01:00
ui - > toolBar - > setToolButtonStyle ( ( Qt : : ToolButtonStyle ) index ) ;
}
2023-02-12 00:37:50 +01:00
void MainWindow : : on_actionExit_triggered ( )
{
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " on_actionExit_triggered() => slot activated when button exit clicked " ) ;
this - > exiting = true ;
2023-02-12 00:37:50 +01:00
quitApp ( ) ;
}
2023-02-22 00:48:16 +01:00
void MainWindow : : setDlSpeed ( QString speed )
{
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " setDlSpeed(= => setting download speed " ) ;
2023-02-22 00:48:16 +01:00
speed . squeeze ( ) ;
}
2023-02-27 23:48:05 +01:00
2023-03-02 17:06:15 +01:00
void MainWindow : : on_actionHiddenService_triggered ( )
{
QInputDialog hiddenFolderDialog ;
2024-08-22 23:08:42 +02:00
info ( DEBUGMACRO , " on_actionHiddenService_triggered() => activated when the 'hidden service' button " ) ;
2023-03-02 17:06:15 +01:00
bool ok ;
2023-03-09 18:13:46 +01:00
QString text = QInputDialog : : getText ( this , a . applicationName ( ) + tr ( " Request " ) ,
2024-08-22 23:08:42 +02:00
tr ( " Hidden service name " ) , QLineEdit : : Normal ,
" test " , & ok ) ;
2023-03-02 17:06:15 +01:00
if ( ok & & ! text . isEmpty ( ) )
{
2024-08-22 23:08:42 +02:00
this - > connexion . service = text ;
this - > settings . setValue ( " Hidden/ " + this - > connexion . server + ' / ' + text , true ) ;
ui - > listWidget - > addItem ( text + " \n \t " ) ;
preparePopulateTree ( ) ;
2023-03-02 17:06:15 +01:00
}
}