version 1.9.2

This commit is contained in:
Daniel Tartavel 2023-02-10 21:32:20 +01:00
parent 6aa69ddd08
commit 13d2c1384b
13 changed files with 1504 additions and 1286 deletions

View File

@ -31,7 +31,7 @@ FORMS += \
mainwindow.ui mainwindow.ui
TRANSLATIONS += \ TRANSLATIONS += \
languages/fr_FR/RsyncUI_fr_FR.ts RsyncUI_fr_FR.ts
INCLUDEPATH += \ INCLUDEPATH += \
/usr/include/KF5 /usr/include/KF5
@ -41,7 +41,6 @@ qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /usr/bin/ else: unix:!android: target.path = /usr/bin/
!isEmpty(target.path): INSTALLS += target !isEmpty(target.path): INSTALLS += target
INSTALLS += lang INSTALLS += lang
INSTALLS += documentation INSTALLS += documentation
INSTALLS += desktopfile INSTALLS += desktopfile
@ -53,6 +52,7 @@ DISTFILES += \
RsyncUI.desktop RsyncUI.desktop
lang.path = /languages/ lang.path = /languages/
lang.path = /usr/share/locale/
lang.files = languages/* lang.files = languages/*
documentation.path = /usr/share/doc/RsyncUI documentation.path = /usr/share/doc/RsyncUI
documentation.files = README* documentation.files = README*

View File

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

View File

@ -2,7 +2,7 @@
Name: rsyncui Name: rsyncui
Summary: Client for rsync server Summary: Client for rsync server
Version: 1.9.1 Version: 1.9.2
Release: %mkrel 1 Release: %mkrel 1
License: GPLv3 License: GPLv3
Group: Networking/Remote access Group: Networking/Remote access

431
RsyncUI_fr_FR.ts Normal file
View File

@ -0,0 +1,431 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="fr_FR">
<context>
<name>Configuration</name>
<message>
<location filename="configuration.ui" line="20"/>
<source>Configuration</source>
<translation>Configuration</translation>
</message>
<message>
<location filename="configuration.ui" line="106"/>
<source>Text follow style</source>
<translation>Le texte suit le style</translation>
</message>
<message>
<location filename="configuration.ui" line="121"/>
<source>Toolbar view</source>
<translation>Toolbar</translation>
</message>
<message>
<location filename="configuration.ui" line="114"/>
<source>Bandwidth limit</source>
<extracomment>Bandwidth limit</extracomment>
<translation>Limite de bande passante</translation>
</message>
<message>
<location filename="configuration.ui" line="63"/>
<source>Enter the bandwidth limit (0 to 1024)</source>
<translation>Entrez la limite de bande passante (0 à 1024)</translation>
</message>
<message>
<location filename="configuration.ui" line="44"/>
<source>Select th unit of bandwidth limit in Bytes, KiloBytes, MegaBytes, GigaBytes or PetaBytes</source>
<extracomment>Unit of bandwidth</extracomment>
<translation>Sélectionnez l&apos;unité de limite de bande passante en otctets, Ko, Mo, Go, Po</translation>
</message>
<message>
<location filename="configuration.ui" line="86"/>
<source>Icon only</source>
<translation>Icône seule</translation>
</message>
<message>
<location filename="configuration.ui" line="91"/>
<source>Text only</source>
<translation>Texte seul</translation>
</message>
<message>
<location filename="configuration.ui" line="96"/>
<source>Text beside icon</source>
<translation>Text à côté de l&apos;icône</translation>
</message>
<message>
<location filename="configuration.ui" line="101"/>
<source>Text under icon</source>
<translation>Texte sous l&apos;icöne</translation>
</message>
<message>
<location filename="configuration.ui" line="159"/>
<source>Automatic saving of download queue</source>
<translation>Enregistrement automatique de la file</translation>
</message>
<message>
<location filename="configuration.ui" line="165"/>
<source>Auto save download queue</source>
<translation>Enregistrement automatique de la file d&apos;enregistrement</translation>
</message>
</context>
<context>
<name>MainWindow</name>
<message>
<location filename="mainwindow.ui" line="21"/>
<source>MainWindow</source>
<translation>Fenêtre principale</translation>
</message>
<message>
<location filename="mainwindow.ui" line="83"/>
<source>Server</source>
<oldsource>Serveur</oldsource>
<translation>Serveur</translation>
</message>
<message>
<location filename="mainwindow.ui" line="105"/>
<source>Enter server&apos;s URL</source>
<translation>Entrez l&apos;adresse du serveur</translation>
</message>
<message>
<location filename="mainwindow.ui" line="121"/>
<source>Port</source>
<translation>Port</translation>
</message>
<message>
<location filename="mainwindow.ui" line="149"/>
<source>Enter rsync port on server</source>
<translation>Entrez le port du serveur rsync</translation>
</message>
<message>
<location filename="mainwindow.ui" line="186"/>
<source>Press button to connect to rsync server</source>
<extracomment>Connect to server</extracomment>
<translation>Cliquez pour se connecter au serveur rsync</translation>
</message>
<message>
<location filename="mainwindow.ui" line="192"/>
<source>Connection</source>
<translation>Connexion</translation>
</message>
<message>
<location filename="mainwindow.ui" line="195"/>
<source>Return</source>
<translation>Retour</translation>
</message>
<message>
<location filename="mainwindow.ui" line="221"/>
<source>Click to view the list of files of this folder</source>
<translation>Cliquez pour afficher la liste des documents</translation>
</message>
<message>
<location filename="mainwindow.ui" line="256"/>
<source>Click to add to download queue</source>
<translation>Cliquez pour ajouter à la file de téléchargement</translation>
</message>
<message>
<location filename="mainwindow.ui" line="334"/>
<source>Click on file to stop downloading</source>
<translation>Cliquez sur le document pour arrêter le téléchargement et l&apos;enlever de la file</translation>
</message>
<message>
<location filename="mainwindow.ui" line="357"/>
<source>%p%</source>
<extracomment>Downloading</extracomment>
<translation>Téléchargement</translation>
</message>
<message>
<location filename="mainwindow.ui" line="368"/>
<source>toolBar</source>
<translation>Barre d&apos;outils</translation>
</message>
<message>
<location filename="mainwindow.ui" line="440"/>
<source>Download</source>
<translation>Télécharger</translation>
</message>
<message>
<location filename="mainwindow.ui" line="443"/>
<source>Click on menu button to download the entire folder</source>
<translation>Cliquer sur le bouton droit de la souris pour télécharger le dossier entier</translation>
</message>
<message>
<location filename="mainwindow.ui" line="405"/>
<location filename="mainwindow.ui" line="408"/>
<source>Change save folder</source>
<translation>Changer le dossier de destination</translation>
</message>
<message>
<location filename="mainwindow.ui" line="417"/>
<source>About</source>
<translation>À propos</translation>
</message>
<message>
<location filename="mainwindow.ui" line="426"/>
<source>About Qt</source>
<translation>À propos de Qt</translation>
</message>
<message>
<location filename="mainwindow.ui" line="435"/>
<source>Settings</source>
<translation>Paramètres</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="86"/>
<source>KB</source>
<translation>Ko</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="86"/>
<source>MB</source>
<translation>Mo</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="86"/>
<source>GB</source>
<translation>Go</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="86"/>
<source>TB</source>
<translation>To</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="86"/>
<source>PB</source>
<translation>Po</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="50"/>
<source>Client for rsync server
You click on file to enqueue it, and RyncUI Download one file a time</source>
<translation>Client pour serveur rsync
Cliquez sur un fichier pour l&apos;ajouter dans la file de téléchargement</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="62"/>
<source>Path</source>
<translation>Chemin</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="62"/>
<source>Size</source>
<translation>Taille</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="62"/>
<source>Type</source>
<translation>Type</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="92"/>
<source>A list of interrupted downloads exists, do you want to continue downloading ? if not the list will be cleared</source>
<translation>Une liste de téléchargement existe, voulez-vous utiliser cette liste ? si non, elle sera effacée</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="393"/>
<source>server does not exists</source>
<translation>Le serveur n&apos;existe pas</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="421"/>
<location filename="mainwindow.cpp" line="441"/>
<source>Dir</source>
<translation>dossier</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="424"/>
<location filename="mainwindow.cpp" line="487"/>
<source>File</source>
<translation>Doc</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="561"/>
<source>Rsync process crashed</source>
<translation>Le processus rsync à planté</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="699"/>
<source>Version</source>
<translation>Version</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="700"/>
<source>Licence</source>
<translation>License</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="701"/>
<source>Author</source>
<translation>Auteur</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="702"/>
<source>EMail</source>
<translation>Courriel</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="703"/>
<source>Source code</source>
<translation>Code source</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="725"/>
<source>Since the save path is linked to service, you need to select a service before you can select a folder</source>
<translation>Vous devez sélectionnez un service pour pouvoir sélectionnez un dossier par défaut</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="728"/>
<source>Choose folder where to save file</source>
<translation>Choisissez un dossier enregistrer le document</translation>
</message>
<message>
<source>Choose directory to save file</source>
<translation type="vanished">Choisissez le dossier enregistrer</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="620"/>
<source>Do you want to stop downloading and delete this file from download queue ?</source>
<translation>Voulez-vous arrêter le téléchargement et enlever ce fichier de la file de téléchargement ?</translation>
</message>
<message>
<source>A list of interrupted downloads exists, do you want to continue downloading ? or you can delete the list</source>
<translation type="vanished">Voulez-vous reprendre les téléchargements interrompus la fois précédente? ou vous pouvez supprimer la liste</translation>
</message>
<message>
<source>Remove</source>
<translation type="vanished">Supprimer</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="135"/>
<source>Exiting will stop downloading, and will clear the download queue.
You can save the list of downloads
Do you want to exit ?</source>
<translatorcomment>i</translatorcomment>
<translation>Si vous sortez, les téléchargements seront arrêter, mais vous pouvez enregistrer la liste pour la prochaine fois.
Voulez-vous vraiment sortir ?</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="632"/>
<source>Do you want to delete this file from download queue ?</source>
<translation>Voulez-vous enlever ce fichier de la file de téléchargement ?</translation>
</message>
<message>
<location filename="mainwindow.h" line="118"/>
<source>The process failed to start. Either the invoked program is missing, or you may have insufficient permissions or resources to invoke the program.</source>
<translation>Le processus échoué, soit le programme est manquant, soit vous n&apos;avez pas l&apos;autorisation de l&apos;exécuter.</translation>
</message>
<message>
<location filename="mainwindow.h" line="119"/>
<source>The process crashed some time after starting successfully.</source>
<translation>Le processus à planté après avoir démarré avec succès.</translation>
</message>
<message>
<location filename="mainwindow.h" line="120"/>
<source>The last waitFor...() function timed out. The state of QProcess is unchanged, and you can try calling waitFor...() again.</source>
<translation>La fonction waitFor...() a dépassé la limite de temps, you pouvez essayer de la relancer.</translation>
</message>
<message>
<location filename="mainwindow.h" line="121"/>
<source>An error occurred when attempting to write to the process. For example, the process may not be running, or it may have closed its input channel.</source>
<translation>Une erreur est survenue lors de l&apos;envoi des données vers le processus. Le processus est peut être arrté ou il a fermé son canal d&apos;entrée.</translation>
</message>
<message>
<location filename="mainwindow.h" line="122"/>
<source>An error occurred when attempting to read from the process. For example, the process may not be running.</source>
<translation>Une erreur est survenue lors de la lecturee de données, le processus est probablement arrêté.</translation>
</message>
<message>
<location filename="mainwindow.h" line="123"/>
<source>An unknown error occurred. This is the default return value of error().</source>
<translation>Une erreur inconnue est survenue. C&apos;est la valeur de retour par défaut de error().</translation>
</message>
</context>
<context>
<name>QTranslator</name>
<message>
<location filename="mainwindow.cpp" line="12"/>
<source>Success. The rsync command completed successfully without any errors.</source>
<translation>Succès. La command rsync s&apos;est terminée sans erreurs.</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="13"/>
<source>Syntax or usage error. There was a problem with the syntax of the rsync command or with the options specified.</source>
<translation>Erreur de syntaxe ou d&apos;usage. il y a un problème avec la synaxe de rsync ou avec les paramètres spécifiés.</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="14"/>
<source>Protocol incompatibility. There was a problem with the protocol version or negotiation between the rsync client and server.</source>
<translation>Incompatibilité de protocole. Il y a eu un problème avec la version du protocole ou la négotiation avec le serveur rsync.</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="15"/>
<source>Errors selecting input/output files, dirs. There was a problem with the source or destination file or directory specified in the rsync command.</source>
<translation>Erreurs dans la sélection des fichiers ou dossiers. il y a eu une problème avec le fichier/dossier source ou destination spécifié.</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="16"/>
<source>Requested action not supported: An attempt was made to use an unsupported action or option.</source>
<translation>Action non suportée. Une tentative d&apos;utiliser une action, ou une option, non supportée à é faite.</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="17"/>
<source>Error starting client-server protocol. There was an error starting the client-server protocol.</source>
<translation>Erreur de démarrage du protocole client-seveur. Il ya eu une erreur en démarrant le protocole slient-serveur.</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="18"/>
<source>Daemon unable to append to log-file. The rsync daemon was unable to write to its log file.</source>
<translation>Le démon rsyncd n&apos;arrive pas écrire dans son fichier de log.</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="19"/>
<source>Error in socket I/O. There was an error with the socket input/output.</source>
<translation>Erreur d&apos;entrée/sortie socket. Il y a eu une erreur d&apos;entrée/sortie sur le socket.</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="20"/>
<source>Error in file I/O. There was an error reading or writing to a file.</source>
<translation>Erreur de &apos;entrée/sortie. Il y a eu une erreur de lecture/écriture sur un fichier.</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="21"/>
<source>Error in rsync protocol data stream. There was an error in the rsync protocol data stream.</source>
<translation>Erreur dans le protocole de flux de données de rsync.</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="22"/>
<source>Errors with program diagnostics. There was an error generating program diagnostics.</source>
<translation>Erreur avec les diagnostiques du programme.</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="23"/>
<source>Error in IPC code. There was an error in the inter-process communication (IPC) code.</source>
<translation>Erreur dans le code IPC. IL y a eu une erreur dans la communication inter-processus.</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="24"/>
<source>Received SIGUSR1 or SIGINT. The rsync process was interrupted by a signal.</source>
<translation>Reçu les signaux SIGUSR1 ou SIGINT. Le processus rsync a é interrompu par un signal.</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="25"/>
<source>Some error returned by waitpid(). An error occurred while waiting for a child process to complete.</source>
<translation>Erreurs retournées par waitpid().Une erreur est survenue pendant l&apos;attente de la complétion du processus fils.</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="26"/>
<source>Error allocating core memory buffers. There was an error allocating memory buffers.</source>
<translation>Erreur d&apos;allocation des buffers mémoire.</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="27"/>
<source>Partial transfer due to error. The rsync command completed with an error, but some files may have been transferred successfully.</source>
<translation>Transfert partiel due à une erreur. La command rsync s&apos;est terminée avec une erreur, mais des fichiers on é transférés avec succès.</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="28"/>
<source>Partial transfer due to vanished source files. Some source files disappeared before they could be transferred.</source>
<translation>Transfert partiel à la disparition des fichiers source. Des fichiers source ont disparu avec d&apos;avoir é transférés.</translation>
</message>
</context>
</TS>

View File

@ -9,8 +9,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>400</width> <width>491</width>
<height>163</height> <height>196</height>
</rect> </rect>
</property> </property>
<property name="contextMenuPolicy"> <property name="contextMenuPolicy">
@ -24,44 +24,14 @@
<rect> <rect>
<x>9</x> <x>9</x>
<y>9</y> <y>9</y>
<width>381</width> <width>464</width>
<height>101</height> <height>109</height>
</rect> </rect>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<property name="sizeConstraint"> <property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum> <enum>QLayout::SetDefaultConstraint</enum>
</property> </property>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Toolbar view</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label1">
<property name="text">
<string extracomment="Bandwidth limit">Bandwidth limit</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="spinBox">
<property name="toolTip">
<string>Enter the bandwidth limit (0 to 1024)</string>
</property>
<property name="toolTipDuration">
<number>5000</number>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="maximum">
<number>1024</number>
</property>
</widget>
</item>
<item row="0" column="2"> <item row="0" column="2">
<widget class="QComboBox" name="UnitCombobox"> <widget class="QComboBox" name="UnitCombobox">
<property name="sizePolicy"> <property name="sizePolicy">
@ -87,6 +57,22 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="1">
<widget class="QSpinBox" name="spinBox">
<property name="toolTip">
<string>Enter the bandwidth limit (0 to 1024)</string>
</property>
<property name="toolTipDuration">
<number>5000</number>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="maximum">
<number>1024</number>
</property>
</widget>
</item>
<item row="1" column="1"> <item row="1" column="1">
<widget class="QComboBox" name="comboBox"> <widget class="QComboBox" name="comboBox">
<property name="maxVisibleItems"> <property name="maxVisibleItems">
@ -117,18 +103,32 @@
</item> </item>
<item> <item>
<property name="text"> <property name="text">
<string>Text follow icon</string> <string>Text follow style</string>
</property> </property>
</item> </item>
</widget> </widget>
</item> </item>
<item row="0" column="0">
<widget class="QLabel" name="label1">
<property name="text">
<string extracomment="Bandwidth limit">Bandwidth limit</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Toolbar view</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<widget class="QDialogButtonBox" name="buttonBox"> <widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>60</x> <x>150</x>
<y>110</y> <y>160</y>
<width>321</width> <width>321</width>
<height>34</height> <height>34</height>
</rect> </rect>
@ -143,6 +143,34 @@
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property> </property>
</widget> </widget>
<widget class="QWidget" name="verticalLayoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>120</y>
<width>461</width>
<height>31</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QCheckBox" name="autosaveCheckbox">
<property name="toolTip">
<string>Automatic saving of download queue</string>
</property>
<property name="toolTipDuration">
<number>5000</number>
</property>
<property name="text">
<string>Auto save download queue</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget> </widget>
<resources/> <resources/>
<connections> <connections>

View File

@ -25,85 +25,86 @@ downloadFile::downloadFile()
} }
//Slot activated when download is cancelled //Slot activated when download is cancelled
void downloadFile::cancelled(int pid) void MainWindow::cancelled(QProcess * process)
{ {
if (pid == 0) process->terminate();
{
perror("Pid = 0 : I do not kill"); // Error rsync process not launched so it can't be killed
}else if (kill(pid, SIGTERM) == -1)
{
//TODO managing error of kill
}
} }
// launch a rsync processus downloading a file // launch a rsync processus downloading a file
void downloadFile::download(MainWindow *mw) void MainWindow::download()
{ {
string line; QString cmd;
string errorRsync; QStringList param;
int pos;
array<string,8> argv;
stringstream output;
vector<string> v;
int value;
char buffer[4096];
Downloading d;
d = mw->downloading;
// Populating array with command and parameters for popen2 // Populating array with command and parameters for popen2
argv[0] = "/usr/bin/rsync"; cmd = "rsync";
if (mw->connexion.bandwidthLimit == 0) if (this->connexion.bandwidthLimit != 0)
{ {
argv[1] = "--bwlimit=1000P"; param << "--bwlimit=" + QString::number(this->connexion.bandwidthLimit) + bwUnitChar[this->connexion.bandwidthLimitUnit];
}else
{
argv[1] = "--bwlimit=" + to_string(mw->connexion.bandwidthLimit) + mw->connexion.bandwidthLimitUnit;
} }
argv[2] = "--port=" + to_string(mw->connexion.port); param << "--port=" + QString::number(this->connexion.port);
argv[3] = "-aP"; param << "-aXP";
argv[4] = d.server + "::" + d.service + "/" + d.path; param << this->downloading.server + "::" + this->downloading.service + "/" + this->downloading.path << this->downloading.savePath + "/";
argv[5] = d.savePath + "/";
argv[6].clear();
//launching downloading thread this->downloading.process = new QProcess(this);
FILE * fp = popen2(argv, "r", mw->pid);
if (fp <= (FILE *) 0)
{
sprintf(buffer, "popen2() failed!: returning code:%d", fileno(fp));
throw runtime_error(buffer);
return;
}
// waiting rsync output connect(this->downloading.process, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(downloadFinished(int, QProcess::ExitStatus)));
while (fgets(buffer, 4096, fp) != nullptr) //connect(this->downloading.process, SIGNAL(errorOccurred(QProcess::ProcessError error)), this, SLOT(downloadProcessError(QProcess::ProcessError error)));
//connect(this->downloading.process, SIGNAL(readyReadStandardError()), this, SLOT(downloadProcessStderr()));
connect(this->downloading.process, SIGNAL(readyReadStandardOutput()), this, SLOT(readRsyncOutput()));
this->downloading.process->start(cmd, param);
}
void MainWindow::readRsyncOutput()
{
QString line;
bool flag = false;
int value;
int pos;
while(!flag)
{ {
// Downloading is cancelled, we return line = QString::fromUtf8(this->downloading.process->readLine());
if (this->canceled == true) if (line.isEmpty())
{ {
return; flag = true;
break;
} }
line = buffer; pos = line.indexOf("%");
// extracting percentage of completion
pos = line.find('%');
if (pos != -1) if (pos != -1)
{ {
line.erase(pos); line.resize(pos);
pos = line.find_last_of(' '); pos = line.lastIndexOf(' ');
if (pos != -1) if (pos != -1)
{ {
line.erase(0, pos); line.remove(0, pos);
value = stoi(line); value = line.toInt();
// sending progress to Main window // sending progress to Main window
emit progressSignal(value); emit progressSignal(value);
} }
} }
// download ended
} }
pclose2(fp, mw->pid);
// ProgressBar to 100% and emit signal finished to main application
emit progressSignal(100);
emit finishedSignal(true);
} }
/*void MainWindow::downloadProcessError(QProcess::ProcessError error)
{
QMessageBox::warning(
this,
"RsyncUI",
downloadProcessErrorString[error].toStdString().c_str()
);
}*/
void MainWindow::downloadProcessStderr()
{
QByteArray errorLine;
errorLine = this->downloading.process->readAllStandardError();
QMessageBox::warning(
this,
"RsyncUI",
errorLine
);
}

View File

@ -13,15 +13,8 @@ class downloadFile : public QObject
Q_OBJECT Q_OBJECT
public: public:
downloadFile(); downloadFile();
void download(MainWindow *parent = nullptr);
bool canceled; bool canceled;
signals:
void progressSignal(int);
void finishedSignal(bool = true);
public slots:
void cancelled(int pid);
}; };
#endif // DOWNLOADFILE_H #endif // DOWNLOADFILE_H

Binary file not shown.

View File

@ -1,302 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="fr_FR">
<context>
<name>Configuration</name>
<message>
<location filename="../../configuration.ui" line="20"/>
<source>Configuration</source>
<translation>Configuration</translation>
</message>
<message>
<location filename="../../configuration.ui" line="38"/>
<source>Toolbar view</source>
<translation>Toolbar</translation>
</message>
<message>
<location filename="../../configuration.ui" line="121"/>
<source>Bandwidth limit</source>
<extracomment>Bandwidth limit</extracomment>
<translation>Limite de bande passante</translation>
</message>
<message>
<location filename="../../configuration.ui" line="70"/>
<source>Enter the bandwidth limit (0 to 1024)</source>
<translation>Entrez la limite de bande passante (0 à 1024)</translation>
</message>
<message>
<location filename="../../configuration.ui" line="51"/>
<source>Select th unit of bandwidth limit in Bytes, KiloBytes, MegaBytes, GigaBytes or PetaBytes</source>
<extracomment>Unit of bandwidth</extracomment>
<translation>Sélectionnez l&apos;unité de limite de bande passante en otctets, Ko, Mo, Go, Po</translation>
</message>
<message>
<location filename="../../configuration.ui" line="93"/>
<source>Icon only</source>
<translation>Icône seule</translation>
</message>
<message>
<location filename="../../configuration.ui" line="98"/>
<source>Text only</source>
<translation>Texte seul</translation>
</message>
<message>
<location filename="../../configuration.ui" line="103"/>
<source>Text beside icon</source>
<translation>Text à côté de l&apos;icône</translation>
</message>
<message>
<location filename="../../configuration.ui" line="108"/>
<source>Text under icon</source>
<translation>Texte sous l&apos;icöne</translation>
</message>
<message>
<location filename="../../configuration.ui" line="113"/>
<source>Text follow icon</source>
<translation>Texte suit l&apos;icône</translation>
</message>
<message>
<location filename="../../configuration.ui" line="128"/>
<source>Automatic saving of download queue</source>
<translation>Enregistrement automatique de la file</translation>
</message>
<message>
<location filename="../../configuration.ui" line="134"/>
<source>Auto save download queue</source>
<translation>Enregistrement automatique de la file d&apos;enregistrement</translation>
</message>
</context>
<context>
<name>MainWindow</name>
<message>
<location filename="../../mainwindow.ui" line="21"/>
<source>MainWindow</source>
<translation>Fenêtre principale</translation>
</message>
<message>
<location filename="../../mainwindow.ui" line="83"/>
<source>Server</source>
<oldsource>Serveur</oldsource>
<translation>Serveur</translation>
</message>
<message>
<location filename="../../mainwindow.ui" line="105"/>
<source>Enter server&apos;s URL</source>
<translation>Entrez l&apos;adresse du serveur</translation>
</message>
<message>
<location filename="../../mainwindow.ui" line="121"/>
<source>Port</source>
<translation>Port</translation>
</message>
<message>
<location filename="../../mainwindow.ui" line="149"/>
<source>Enter rsync port on server</source>
<translation>Entrez le port du serveur rsync</translation>
</message>
<message>
<location filename="../../mainwindow.ui" line="186"/>
<source>Press button to connect to rsync server</source>
<extracomment>Connect to server</extracomment>
<translation>Cliquez pour se connecter au serveur rsync</translation>
</message>
<message>
<location filename="../../mainwindow.ui" line="192"/>
<source>Connection</source>
<translation>Connexion</translation>
</message>
<message>
<location filename="../../mainwindow.ui" line="195"/>
<source>Return</source>
<translation>Retour</translation>
</message>
<message>
<location filename="../../mainwindow.ui" line="221"/>
<source>Click to view the list of files of this folder</source>
<translation>Cliquez pour afficher la liste des documents</translation>
</message>
<message>
<location filename="../../mainwindow.ui" line="256"/>
<source>Click to add to download queue</source>
<translation>Cliquez pour ajouter à la file de téléchargement</translation>
</message>
<message>
<location filename="../../mainwindow.ui" line="334"/>
<source>Click on file to stop downloading</source>
<translation>Cliquez sur le document pour arrêter le téléchargement et l&apos;enlever de la file</translation>
</message>
<message>
<location filename="../../mainwindow.ui" line="357"/>
<source>%p%</source>
<extracomment>Downloading</extracomment>
<translation>Téléchargement</translation>
</message>
<message>
<location filename="../../mainwindow.ui" line="368"/>
<source>toolBar</source>
<translation>Barre d&apos;outils</translation>
</message>
<message>
<location filename="../../mainwindow.ui" line="440"/>
<source>Download</source>
<translation>Télécharger</translation>
</message>
<message>
<location filename="../../mainwindow.ui" line="443"/>
<source>Click on menu button to download the entire folder</source>
<translation>Cliquer sur le bouton droit de la souris pour télécharger le dossier entier</translation>
</message>
<message>
<location filename="../../mainwindow.ui" line="405"/>
<location filename="../../mainwindow.ui" line="408"/>
<source>Change save folder</source>
<translation>Changer le dossier de destination</translation>
</message>
<message>
<location filename="../../mainwindow.ui" line="417"/>
<source>About</source>
<translation>À propos</translation>
</message>
<message>
<location filename="../../mainwindow.ui" line="426"/>
<source>About Qt</source>
<translation>À propos de Qt</translation>
</message>
<message>
<location filename="../../mainwindow.ui" line="435"/>
<source>Settings</source>
<translation>Paramètres</translation>
</message>
<message>
<location filename="../../mainwindow.cpp" line="27"/>
<source>Byte</source>
<translation>Octet</translation>
</message>
<message>
<location filename="../../mainwindow.cpp" line="27"/>
<source>KB</source>
<translation>Ko</translation>
</message>
<message>
<location filename="../../mainwindow.cpp" line="27"/>
<source>MB</source>
<translation>Mo</translation>
</message>
<message>
<location filename="../../mainwindow.cpp" line="27"/>
<source>GB</source>
<translation>Go</translation>
</message>
<message>
<location filename="../../mainwindow.cpp" line="27"/>
<source>TB</source>
<translation>To</translation>
</message>
<message>
<location filename="../../mainwindow.cpp" line="27"/>
<location filename="../../mainwindow.cpp" line="708"/>
<source>PB</source>
<translation>Po</translation>
</message>
<message>
<location filename="../../mainwindow.cpp" line="30"/>
<source>Client for rsync server
You click on file to enqueue it, and RyncUI Download one file a time</source>
<translation>Client pour serveur rsync
Cliquez sur un fichier pour l&apos;ajouter dans la file de téléchargement</translation>
</message>
<message>
<location filename="../../mainwindow.cpp" line="41"/>
<source>Path</source>
<translation>Chemin</translation>
</message>
<message>
<location filename="../../mainwindow.cpp" line="41"/>
<source>Size</source>
<translation>Taille</translation>
</message>
<message>
<location filename="../../mainwindow.cpp" line="41"/>
<source>Type</source>
<translation>Type</translation>
</message>
<message>
<location filename="../../mainwindow.cpp" line="360"/>
<source>server does not exists</source>
<translation>Le serveur n&apos;existe pas</translation>
</message>
<message>
<location filename="../../mainwindow.cpp" line="387"/>
<location filename="../../mainwindow.cpp" line="407"/>
<source>Dir</source>
<translation>dossier</translation>
</message>
<message>
<location filename="../../mainwindow.cpp" line="390"/>
<location filename="../../mainwindow.cpp" line="455"/>
<source>File</source>
<translation>Doc</translation>
</message>
<message>
<location filename="../../mainwindow.cpp" line="644"/>
<source>Version</source>
<translation>Version</translation>
</message>
<message>
<location filename="../../mainwindow.cpp" line="645"/>
<source>Licence</source>
<translation>License</translation>
</message>
<message>
<location filename="../../mainwindow.cpp" line="646"/>
<source>Author</source>
<translation>Auteur</translation>
</message>
<message>
<location filename="../../mainwindow.cpp" line="647"/>
<source>EMail</source>
<translation>Courriel</translation>
</message>
<message>
<location filename="../../mainwindow.cpp" line="648"/>
<source>Source code</source>
<translation>Code source</translation>
</message>
<message>
<location filename="../../mainwindow.cpp" line="673"/>
<source>Choose directory to save file</source>
<translation>Choisissez le dossier enregistrer</translation>
</message>
<message>
<location filename="../../mainwindow.cpp" line="569"/>
<source>Do you want to stop downloading and delete this file from download queue ?</source>
<translation>Voulez-vous arrêter le téléchargement et enlever ce fichier de la file de téléchargement ?</translation>
</message>
<message>
<location filename="../../mainwindow.cpp" line="65"/>
<source>A list of interrupted downloads exists, do you want to continue downloading ? or you can delete the list</source>
<translation>Voulez-vous reprendre les téléchargements interrompus la fois précédente? ou vous pouvez supprimer la liste</translation>
</message>
<message>
<location filename="../../mainwindow.cpp" line="67"/>
<source>Remove</source>
<translation>Supprimer</translation>
</message>
<message>
<location filename="../../mainwindow.cpp" line="106"/>
<source>Exiting will stop downloading, and will clear the download queue.
You can save the list of downloads
Do you want to exit ?</source>
<translatorcomment>i</translatorcomment>
<translation>Si vous sortez, les téléchargements seront arrêter, mais vous pouvez enregistrer la liste pour la prochaine fois.
Voulez-vous vraiment sortir ?</translation>
</message>
<message>
<location filename="../../mainwindow.cpp" line="581"/>
<source>Do you want to delete this file from download queue ?</source>
<translation>Voulez-vous enlever ce fichier de la file de téléchargement ?</translation>
</message>
</context>
</TS>

View File

@ -1,12 +1,33 @@
#include "mainwindow.h" #include "mainwindow.h"
#include <QComboBox> #include <QComboBox>
#include <QToolBar>
using namespace std; using namespace std;
bool display = false; bool display = false;
//extern QDialog Configuration; //extern QDialog Configuration;
extern Ui::Configuration config; extern Ui::Configuration config;
extern bool testRsyncReturn(QProcess *);
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) MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent) : QMainWindow(parent)
@ -23,24 +44,23 @@ MainWindow::MainWindow(QWidget *parent)
ui->treeWidget->addAction(ui->actionDownload); ui->treeWidget->addAction(ui->actionDownload);
// init shortcut // init shortcut
loadSettings();
config.setupUi(&Configuration); config.setupUi(&Configuration);
config.UnitCombobox->addItems({tr("Byte"), tr("KB"), tr("MB"), tr("GB"), tr("TB"), tr("PB")});
// init of About // init of About
this->about.description = tr("Client for rsync server\n\nYou click on file to enqueue it, and RyncUI Download one file a time"); this->about.description = tr("Client for rsync server\n\nYou click on file to enqueue it, and RyncUI Download one file a time");
// connectors // connectors
connect(&downloadO, &downloadFile::progressSignal, ui->progressBar, &QProgressBar::setValue); connect(this, &MainWindow::progressSignal, ui->progressBar, &QProgressBar::setValue);
connect(&downloadO, &downloadFile::finishedSignal, this, &MainWindow::downloadFinished); //connect(this, &MainWindow::errorSignal, this, &MainWindow::downloadingErrorSlot);
connect(this, &MainWindow::stopDownloading, &downloadO, &downloadFile::cancelled); connect(this, &MainWindow::stopDownloading, this, &MainWindow::cancelled);
connect(config.buttonBox, SIGNAL(accepted()), this, SLOT(on_buttonBox_accepted())); connect(config.buttonBox, SIGNAL(accepted()), this, SLOT(on_buttonBox_accepted()));
connect(config.comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &MainWindow::on_comboBox_currentIndexChanged);
// init of widgets // init of widgets
ui->ktreewidgetsearchline->setTreeWidget(ui->treeWidget); ui->ktreewidgetsearchline->setTreeWidget(ui->treeWidget);
ui->ktreewidgetsearchline->setCaseSensitivity(Qt::CaseInsensitive); ui->ktreewidgetsearchline->setCaseSensitivity(Qt::CaseInsensitive);
ui->treeWidget->setHeaderLabels({tr("Path"), tr("Type"), tr("Size")} ); ui->treeWidget->setHeaderLabels({tr("Path"), tr("Type"), tr("Size")} );
config.comboBox->setCurrentIndex(ui->toolBar->toolButtonStyle());
if (this->settings.contains("connexion/lastServer")) if (this->settings.contains("connexion/lastServer"))
{ {
ui->portEdit->setText(this->settings.value("connexion/port").toString()); ui->portEdit->setText(this->settings.value("connexion/port").toString());
@ -59,29 +79,31 @@ MainWindow::MainWindow(QWidget *parent)
// Hiding progress bar // Hiding progress bar
ui->progressBar->hide(); ui->progressBar->hide();
loadSettings();
//setting configuration window
config.comboBox->setCurrentIndex(ui->toolBar->toolButtonStyle());
config.UnitCombobox->addItems({tr("KB"), tr("MB"), tr("GB"), tr("TB"), tr("PB")});
if (this->settings.value("Downloads/rows").toInt() != 0) if (this->settings.value("Downloads/rows").toInt() != 0)
{ {
this->settings.endArray(); //this->settings.endArray();
msgBox.setWindowTitle("RsyncUI"); msgBox.setWindowTitle("RsyncUI");
msgBox.setInformativeText(tr("A list of interrupted downloads exists, do you want to continue downloading ? or you can delete the list" )); 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 *remove = msgBox.addButton(tr("Remove"), QMessageBox::ActionRole);
QPushButton *yes = msgBox.addButton(QMessageBox::Yes); QPushButton *yes = msgBox.addButton(QMessageBox::Yes);
msgBox.addButton(QMessageBox::No); msgBox.addButton(QMessageBox::No);
msgBox.setDefaultButton(QMessageBox::No); msgBox.setDefaultButton(QMessageBox::Yes);
msgBox.exec(); msgBox.exec();
reply = msgBox.clickedButton(); reply = msgBox.clickedButton();
if(reply == yes) if(reply == yes)
{ {
loadDownloadList(); loadDownloadList();
}else if (reply == remove)
{
this->settings.remove("Downloads");
} }
} }
populateList(); populateList();
} }
@ -94,6 +116,7 @@ MainWindow::~MainWindow()
void MainWindow::closeEvent (QCloseEvent *event) void MainWindow::closeEvent (QCloseEvent *event)
{ {
QMessageBox::StandardButton reply; QMessageBox::StandardButton reply;
QMessageBox::StandardButtons param;
// saving settings // saving settings
saveSettings(); saveSettings();
@ -101,11 +124,16 @@ void MainWindow::closeEvent (QCloseEvent *event)
if (ui->listDownload->count() != 0) // some downloads waiting if (ui->listDownload->count() != 0) // some downloads waiting
{ {
// Asking for stopping or continuing // Asking for stopping or continuing
param = QMessageBox::Yes|QMessageBox::No;
if (config.autosaveCheckbox->checkState() != Qt::Checked)
{
param |= QMessageBox::Save;
}
reply = QMessageBox::question( reply = QMessageBox::question(
this, this,
"RsyncUI", "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.\nYou can save the list of downloads\nDo you want to exit ?"),
QMessageBox::Yes|QMessageBox::Save|QMessageBox::No, param,
QMessageBox::No); QMessageBox::No);
if (reply == QMessageBox::No) if (reply == QMessageBox::No)
{ {
@ -115,8 +143,7 @@ void MainWindow::closeEvent (QCloseEvent *event)
}else if(reply == QMessageBox::Yes) }else if(reply == QMessageBox::Yes)
{ {
// emission of signal to downloading thread and stopping // emission of signal to downloading thread and stopping
emit (stopDownloading(this->pid)); emit (stopDownloading(this->downloading.process));
waitpid(this->pid, NULL, WUNTRACED);
}else }else
{ {
saveDownloadList(); saveDownloadList();
@ -129,11 +156,11 @@ void MainWindow::closeEvent (QCloseEvent *event)
void MainWindow::populateTree(QTreeWidgetItem * parent) void MainWindow::populateTree(QTreeWidgetItem * parent)
{ {
stringstream ss; stringstream ss;
vector<string> path; QString path;
// Clear treewidget // Clear treewidget
ui->treeWidget->clear(); ui->treeWidget->clear();
if (!this->connexion.server.empty() and this->connexion.port > 0 and this->connexion.port < 65536) if (!this->connexion.server.isEmpty() and this->connexion.port > 0 and this->connexion.port < 65536)
{ {
// setting cursor to "Wait" // setting cursor to "Wait"
QGuiApplication::setOverrideCursor(Qt::WaitCursor); QGuiApplication::setOverrideCursor(Qt::WaitCursor);
@ -141,8 +168,8 @@ void MainWindow::populateTree(QTreeWidgetItem * parent)
if (validateServer(this->connexion.server)) if (validateServer(this->connexion.server))
{ {
// server is validated // server is validated
path = explode(ui->listWidget->currentItem()->text().toStdString(), '\n', 2); path = ui->listWidget->currentItem()->text().section('\n', 0, 0) + "/";
scanDir(this->connexion.server, this->connexion.port, parent, path[0].append("/") ); scanDir(this->connexion.server, this->connexion.port, parent, path);
} }
// Restoring cursor // Restoring cursor
QGuiApplication::restoreOverrideCursor(); QGuiApplication::restoreOverrideCursor();
@ -152,25 +179,25 @@ void MainWindow::populateTree(QTreeWidgetItem * parent)
// Populate Listview with list of services // Populate Listview with list of services
void MainWindow::populateList() void MainWindow::populateList()
{ {
stringstream ss; //stringstream ss;
QString str; QString str;
QString server; QString server;
int port; int port;
server = ui->khistorycombobox->currentText(); server = ui->khistorycombobox->currentText();
port = ui->portEdit->text().toUInt(); port = ui->portEdit->text().toUInt();
if ((server.toStdString() != this->connexion.server) or (port != this->connexion.port)) if ((server != this->connexion.server) or (port != this->connexion.port))
{ {
// clearing listwidget // clearing listwidget
ui->listWidget->clear(); ui->listWidget->clear();
this->connexion.server.assign(server.toStdString()); this->connexion.server = server;
this->connexion.port = port; this->connexion.port = port;
QGuiApplication::setOverrideCursor(Qt::WaitCursor); QGuiApplication::setOverrideCursor(Qt::WaitCursor);
// verify if server is in history // verify if server is in history
this->settings.beginGroup("connexion/server"); this->settings.beginGroup("connexion/server");
if (this->settings.contains(server)) if (this->settings.contains(server) and this->connexion.comboboxChanged)
{ {
// server is in history => setting port value // server is in history => setting port value
port = this->settings.value(server).toUInt(); port = this->settings.value(server).toUInt();
@ -181,13 +208,13 @@ void MainWindow::populateList()
{ {
if (!server.isEmpty() and (port > 0 and port < 65536)) if (!server.isEmpty() and (port > 0 and port < 65536))
{ {
if (validateServer(server.toStdString())) if (validateServer(server))
{ {
cout << server.toStdString() << endl; cout << server.toStdString() << endl;
// storing serverURL and port in settings // storing serverURL and port in settings
this->settings.setValue(server, port); this->settings.setValue(server, port);
this->settings.sync(); this->settings.sync();
this->downloading.server = server.toStdString(); this->downloading.server = server;
// storing in history of combobox // storing in history of combobox
ui->khistorycombobox->addToHistory(server); ui->khistorycombobox->addToHistory(server);
@ -197,7 +224,6 @@ void MainWindow::populateList()
listServices(); listServices();
} }
} }
} }
this->settings.endGroup(); this->settings.endGroup();
QGuiApplication::restoreOverrideCursor(); //setOverrideCursor(Qt::ArrowCursor); QGuiApplication::restoreOverrideCursor(); //setOverrideCursor(Qt::ArrowCursor);
@ -207,99 +233,115 @@ void MainWindow::populateList()
//list services of the rsync server //list services of the rsync server
void MainWindow::listServices() void MainWindow::listServices()
{ {
char cmd[4096]; QString cmd;
string line; QStringList param;
string errorRsync; QString line;
vector<string> v; QString errorRsync;
char service[4096]; QStringList v;
QString service;
QProcess *myProcess;
bool flag = false;
sprintf(cmd, "rsync --contimeout=10 -P \"%s::\" --port %d ", this->connexion.server.c_str(), this->connexion.port ); cmd = "/usr/bin/rsync";
redi::ipstream in(cmd, redi::pstreams::pstdout | redi::pstreams::pstderr); param << "--contimeout=10" << "--port=" + QString::number(this->connexion.port) << this->connexion.server + "::";
while (getline(in.out(), line)) myProcess = new QProcess(this);
myProcess->start(cmd, param);
while(myProcess->waitForReadyRead(10000))
{ {
boost::replace_all(line," ",""); while(!flag)
boost::replace_all(line, "\t", " - "); {
v = explode(line, ' ', 3 ); line = QString::fromUtf8(myProcess->readLine());
sprintf(service, "%s\n\t%s", v[0].c_str(), v[2].c_str()); if (line.isEmpty())
ui->listWidget->addItem(service); {
flag = true;
break;
}
v = line.split("\t");
v[0].replace(" ", "");
v[1].replace("\n", "");
service = v[0] + "\n\t" + v[1];
ui->listWidget->addItem(service);
}
flag =false;
} }
testRsyncReturn(myProcess);
} }
// connect to rsync server to get list of files // connect to rsync server to get list of files
void MainWindow::scanDir(string server, int portN, QTreeWidgetItem *parent, string path) void MainWindow::scanDir(QString server, int portN, QTreeWidgetItem *parent, QString path)
{ {
char cmd[4096]; QString cmd;
string line; QStringList param;
string errorRsync; QString line;
vector<string> v; QString errorRsync;
QString size;
QString filename;
QString dir;
QTreeWidgetItem * item; QTreeWidgetItem * item;
QProcess * myProcess;
bool isDir = false; bool isDir = false;
bool flag = false;
sprintf(cmd, "rsync --contimeout=10 -P \"%s::%s\" --port %d ", server.c_str(), path.c_str(), portN ); cmd = "rsync";
redi::ipstream in(cmd, redi::pstreams::pstdout | redi::pstreams::pstderr); param << "--contimeout=10" << "--port=" + QString::number(portN) << server + "::" + path;
while (getline(in.out(), line)) myProcess = new QProcess(this);
myProcess->start(cmd, param);
while(myProcess->waitForReadyRead(100000))
{ {
v = explode(line, ' ', 5); while (!flag)
if (v.size() == 5)
{ {
if (v[4].at(0) != '.' and (v[0].at(0) == '-' or v[0].at(0) == 'd')) line = QString::fromUtf8(myProcess->readLine());
if (line.isEmpty())
{ {
if (v[0].at(0) == 'd') flag = true;
break;
}
line = line.simplified();
size = line.section(" ", 1, 1);
filename = line.section(" ", 4);
if (filename != '.')
{
if (line[0] == "d")
{ {
isDir = true; isDir = true;
}else }else
{ {
isDir = false; isDir = false;
} }
if (parent != NULL) if (parent != NULL)
{ {
item = addTreeChild(parent,QString::fromStdString(v[4]), QString::fromStdString(v[1]), isDir); item = addTreeChild(parent, filename, size, isDir);
}else }else
{ {
item = addTreeRoot(QString::fromStdString(v[4]), QString::fromStdString(v[1]), isDir); item = addTreeRoot(filename, size, isDir);
} }
} }
} }
flag = false;
} }
// if reading stdout stopped at EOF then reset the state: testRsyncReturn(myProcess);
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());
}
} }
// Verify if server address is IP address // Verify if server address is IP address
bool MainWindow::isIpAddress(string server) bool MainWindow::isIpAddress(QString server)
{ {
vector<string> r; QStringList r;
int elementN; int elementN;
QString qr; QString qr;
bool ok; bool ok;
r = explode(server, '.', 5); r = server.split('.');
if (r.size() == 4) if (r.size() == 4)
{ {
for (auto element : r) for (auto element : r)
{ {
elementN = QString::fromStdString(element).toInt(&ok); elementN = element.toInt(&ok);
if (elementN < 0 or elementN > 255 or ok == false) if (elementN < 0 or elementN > 255 or ok == false)
{ {
return false; return false;
@ -313,42 +355,32 @@ bool MainWindow::isIpAddress(string server)
} }
// validate address server // validate address server
bool MainWindow::validateServer(string server) bool MainWindow::validateServer(QString server)
{ {
char cmd[512]; QString cmd;
string line; QStringList param;
string errorDig; QString line;
QString errorDig;
QProcess * myProcess;
bool flag = false; bool flag = false;
sprintf(cmd, "dig %s", server.c_str()); cmd = "dig";
redi::ipstream in(cmd, redi::pstreams::pstdout | redi::pstreams::pstderr); param << server;
while (getline(in.out(), line)) myProcess = new QProcess(this);
myProcess->start(cmd, param);
while(myProcess->waitForReadyRead())
{ {
//cout << "stdout: " << line << '\n'; line = QString::fromUtf8(myProcess->readAllStandardOutput());
if (line.find(";; ANSWER SECTION:") != string::npos) if (line.indexOf(";; ANSWER SECTION:") != -1)
{ {
flag = true; flag = true;
} }
} }
// if reading stdout stopped at EOF then reset the state:
if (in.eof() && in.fail()) //testRsyncReturn(myProcess);
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) if ( flag == false)
{ {
flag = isIpAddress(server); flag = isIpAddress(server);
@ -367,7 +399,8 @@ bool MainWindow::validateServer(string server)
// slot activated when combobox is changed // slot activated when combobox is changed
void MainWindow::on_khistorycombobox_currentIndexChanged(int i) void MainWindow::on_khistorycombobox_currentIndexChanged(int i)
{ {
on_connectButton_clicked(); this->connexion.comboboxChanged = true;
populateList();
} }
// slot activated when button connection is clicked // slot activated when button connection is clicked
@ -421,15 +454,14 @@ QTreeWidgetItem * MainWindow::addTreeChild(QTreeWidgetItem *parent, QString name
// Slot acivated when a service in the list is clicked // Slot acivated when a service in the list is clicked
void MainWindow::on_listWidget_clicked() void MainWindow::on_listWidget_clicked()
{ {
vector<string> v; QString service;
QString str; QString str;
v = explode(ui->listWidget->currentItem()->text().toStdString(), '\n', 2); this->connexion.service = ui->listWidget->currentItem()->text().section("\n", 0 ,0);
this->connexion.service = v[0]; str = "Folder/" + this->connexion.server + "/" + this->connexion.service;
str = QString::fromStdString("Folder/" + this->connexion.server + "/" + this->connexion.service);
if (this->settings.contains(str)) if (this->settings.contains(str))
{ {
this->downloading.savePath = this->settings.value(str).toString().toStdString(); this->downloading.savePath = this->settings.value(str).toString();
} }
populateTree(NULL); populateTree(NULL);
} }
@ -440,57 +472,62 @@ void MainWindow::on_treeWidget_itemClicked(QTreeWidgetItem *item, bool downloadD
QFuture<void> future; QFuture<void> future;
QFileDialog dialog; QFileDialog dialog;
QTreeWidgetItem * itemR; QTreeWidgetItem * itemR;
string path; QString path;
QString str; QString str;
//item = ui->treeWidget->currentItem();
itemR = item; itemR = item;
path = item->text(0).toStdString(); path = item->text(0);
while(itemR->parent() != NULL) while(itemR->parent() != NULL)
{ {
itemR = itemR->parent(); itemR = itemR->parent();
path = itemR->text(0).toStdString() + "/" + path; path = itemR->text(0) + "/" + path;
}; };
if (item->text(1) == tr("File") or downloadDir == true) if (item->text(1) == tr("File") or downloadDir == true)
{ {
// Item is a file // Item is a file
this->downloading.path = path;
this->downloading.server = this->connexion.server;
this->downloading.service = this->connexion.service;
// exists saving path in settings ? if(ui->listDownload->findItems(path, Qt::MatchStartsWith).empty())
str = QString::fromStdString("Folder/" + this->connexion.server + "/" + this->downloading.service);
if(!this->settings.contains(str))
{ {
// saving path do not exists, asking for it // exists saving path in settings ?
if(!on_DefaultSaveFolder_triggered()) str = "Folder/" + this->connexion.server + "/" + this->downloading.service;
if(!this->settings.contains(str))
{ {
cout << "no directory selectioned, ignoring download request"; // saving path do not exists, asking for it
return; if(!on_DefaultSaveFolder_triggered())
{
cout << "no directory selectioned, ignoring download request";
return;
}
} }
}
// is there a downloading process ? // is there a downloading process ?
if (this->pid == 0) if (this->downloading.process == nullptr)
{ {
// no downloading process launching it // no downloading process launching it
startDownloading(); this->downloading.path = path;
// wit 1 second to process start this->downloading.server = this->connexion.server;
//sleep(1); this->downloading.service = this->connexion.service;
} startDownloading();
// wit 1 second to process start
//sleep(1);
}
// Adding download in download list // Adding download in download list
str = QString::fromStdString(this->downloading.path + " => " + this->connexion.server + "/" + this->downloading.service); str = path + " => " + this->connexion.server + "/" + this->connexion.service;
ui->listDownload->addItem(str); ui->listDownload->addItem(str);
}
}else }else
{ {
//Item is a Directory //Item is a Directory
scanDir(this->connexion.server, this->connexion.port, item, this->connexion.service + "/" + path +"/"); scanDir(this->connexion.server, this->connexion.port, item, this->connexion.service + "/" + path +"/");
item->setExpanded(true); item->setExpanded(true);
} }
if (config.autosaveCheckbox->checkState() == Qt::Checked)
{
saveDownloadList();
}
} }
// Launch the thread which download the file // Launch the thread which download the file
@ -499,47 +536,67 @@ void MainWindow::startDownloading()
ui->progressBar->setValue(0); ui->progressBar->setValue(0);
ui->progressBar->show(); ui->progressBar->show();
QtConcurrent::run(&this->downloadO, &downloadFile::download, this); //QtConcurrent::run(&this->downloadO, &downloadFile::download, this);
download();
} }
// Slot stopping download // Slot stopping download
void MainWindow::stoppingDownload() void MainWindow::stoppingDownload()
{ {
emit (stopDownloading(this->pid)); emit (stopDownloading(this->downloading.process));
} }
// when download is finished, launch download of next file in queue // when download is finished, launch download of next file in queue
void MainWindow::downloadFinished() void MainWindow::downloadFinished(int exitCode, QProcess::ExitStatus exitStatus)
{ {
string path; QString path;
int pos; int pos;
string str; QString str;
this->pid = 0; if (exitStatus == QProcess::CrashExit)
{
QMessageBox::warning(
NULL,
"RsyncUI",
tr("Rsync process crashed"));
}
if (exitCode != 0 and exitCode != 20)
{
QMessageBox::warning(
NULL,
"RsyncUI",
rsyncErrorStrings[exitCode]);
}
disconnect(this->downloading.process, 0, 0, 0);
this->downloading.process= nullptr;
ui->progressBar->hide(); ui->progressBar->hide();
delete ui->listDownload->takeItem(0); delete ui->listDownload->takeItem(0);
this->downloading.clear(); this->downloading.clear();
if (ui->listDownload->count() != 0) if (ui->listDownload->count() != 0)
{ {
path = ui->listDownload->item(0)->text().toStdString(); if (config.autosaveCheckbox->checkState() == Qt::Checked)
pos = path.rfind("/"); {
this->downloading.service = path.substr(pos+1); saveDownloadList();
}
path = ui->listDownload->item(0)->text();
pos = path.lastIndexOf("/");
this->downloading.service = path.midRef(pos+1).toString();
path.resize(pos); path.resize(pos);
pos = path.rfind(" => "); pos = path.lastIndexOf(" => ");
this->downloading.server = path.substr(pos+4); this->downloading.server = path.midRef(pos+4).toString();
path.resize(pos); path.resize(pos);
this->downloading.path = path; this->downloading.path = path;
str = "Folder/" + this->downloading.server + "/" + this->downloading.service; str = "Folder/" + this->downloading.server + "/" + this->downloading.service;
if (this->settings.contains(QString::fromStdString(str))) if (this->settings.contains(str))
{ {
this->downloading.savePath = this->settings.value(QString::fromStdString(str)).toString().toStdString(); this->downloading.savePath = this->settings.value(str).toString();
}else }else
{ {
if(!on_DefaultSaveFolder_triggered()) if(!on_DefaultSaveFolder_triggered())
{ {
cout << "Error no save path so deleting download"; cout << "Error no save path so deleting download";
downloadFinished(); //downloadFinished();
return; return;
} }
} }
@ -565,7 +622,7 @@ void MainWindow::on_listDownload_itemClicked(QListWidgetItem *item)
QMessageBox::No); QMessageBox::No);
if (reply == QMessageBox::Yes) if (reply == QMessageBox::Yes)
{ {
emit (stopDownloading(this->pid)); emit (stopDownloading(this->downloading.process));
} }
}else }else
{ {
@ -579,6 +636,10 @@ void MainWindow::on_listDownload_itemClicked(QListWidgetItem *item)
{ {
ui->listDownload->removeItemWidget(item); ui->listDownload->removeItemWidget(item);
delete item; delete item;
if (config.autosaveCheckbox->checkState() == Qt::Checked)
{
saveDownloadList();
}
} }
} }
} }
@ -593,7 +654,10 @@ void MainWindow::loadSettings()
ui->splitter->restoreState(this->settings.value("splitter/state").toByteArray()); ui->splitter->restoreState(this->settings.value("splitter/state").toByteArray());
ui->splitter_2->restoreState(this->settings.value("splitter2/state").toByteArray()); ui->splitter_2->restoreState(this->settings.value("splitter2/state").toByteArray());
ui->toolBar->setToolButtonStyle((Qt::ToolButtonStyle)this->settings.value("toolbar/state").toInt()); ui->toolBar->setToolButtonStyle((Qt::ToolButtonStyle)this->settings.value("toolbar/state").toInt());
if (this->settings.value("Autosave").toInt() == Qt::Checked)
{
this->config.autosaveCheckbox->setChecked(true);
}
// loading connexion settings // loading connexion settings
// loading servers history // loading servers history
this->settings.beginGroup("connexion/server"); this->settings.beginGroup("connexion/server");
@ -605,11 +669,11 @@ void MainWindow::loadSettings()
} }
// loading save path // loading save path
this->downloading.savePath = this->settings.value("Folder").toString().toStdString(); this->downloading.savePath = this->settings.value("Folder").toString();
// loading bandwidth limit // loading bandwidth limit
this->connexion.bandwidthLimit = this->settings.value("bandwidthlimit").toUInt(); this->connexion.bandwidthLimit = this->settings.value("bandwidthlimit").toUInt();
this->connexion.bandwidthLimitUnit = this->settings.value("bandwidthlimitunit").toString().toStdString(); this->connexion.bandwidthLimitUnit = this->settings.value("bandwidthlimitunit").toInt();
} }
// save settings // save settings
@ -620,9 +684,10 @@ void MainWindow::saveSettings()
this->settings.setValue("treeWidget/state", ui->treeWidget->header()->saveState()); this->settings.setValue("treeWidget/state", ui->treeWidget->header()->saveState());
this->settings.setValue("splitter/state", ui->splitter->saveState()); this->settings.setValue("splitter/state", ui->splitter->saveState());
this->settings.setValue("splitter2/state", ui->splitter_2->saveState()); this->settings.setValue("splitter2/state", ui->splitter_2->saveState());
this->settings.setValue("connexion/lastServer", QString::fromStdString(this->connexion.server)); this->settings.setValue("connexion/lastServer", this->connexion.server);
this->settings.setValue("connexion/lastPort", QString::number(this->connexion.port)); this->settings.setValue("connexion/lastPort", QString::number(this->connexion.port));
this->settings.setValue("toolbar/state", ui->toolBar->toolButtonStyle()); this->settings.setValue("toolbar/state", ui->toolBar->toolButtonStyle());
this->settings.setValue("Autosave", this->config.autosaveCheckbox->checkState());
this->settings.sync(); this->settings.sync();
} }
@ -649,25 +714,25 @@ void MainWindow::on_actionAbout_Qt_triggered()
bool MainWindow::on_DefaultSaveFolder_triggered() bool MainWindow::on_DefaultSaveFolder_triggered()
{ {
QFileDialog dialog; QFileDialog dialog;
string folder; QString folder;
string path; QString path;
if (this->connexion.service.empty()) if (this->connexion.service.isEmpty())
{ {
QMessageBox::warning( QMessageBox::warning(
NULL, NULL,
"RsyncUI", "RsyncUI",
"Since the save path is linked to service, you need to select a service before you can select a folder"); tr("Since the save path is linked to service, you need to select a service before you can select a folder"));
return false; return false;
} }
path = dialog.getExistingDirectory(this, tr("Choose directory to save file"), QString::fromStdString(getpwuid(getuid())->pw_dir), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks).toStdString(); path = dialog.getExistingDirectory(this, tr("Choose folder where to save file"), QDir::homePath(), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
if (!path.empty()) if (!path.isEmpty())
{ {
this->downloading.savePath = path; this->downloading.savePath = path;
if (!this->connexion.service.empty() and !this->connexion.server.empty()) if (!this->connexion.service.isEmpty() and !this->connexion.server.isEmpty())
{ {
folder = "Folder/" + this->connexion.server + "/" + this->connexion.service; folder = "Folder/" + this->connexion.server + "/" + this->connexion.service;
this->settings.setValue(folder.c_str(), this->downloading.savePath.c_str()); this->settings.setValue(folder, this->downloading.savePath);
this->settings.sync(); this->settings.sync();
} }
}else }else
@ -680,7 +745,7 @@ bool MainWindow::on_DefaultSaveFolder_triggered()
// Activated when menu "settings" is clicked // Activated when menu "settings" is clicked
void MainWindow::on_action_Settings_triggered() void MainWindow::on_action_Settings_triggered()
{ {
config.UnitCombobox->setCurrentIndex(bwUnixIndex[this->connexion.bandwidthLimitUnit[0]]); config.UnitCombobox->setCurrentIndex(this->connexion.bandwidthLimitUnit);
config.spinBox->setValue(this->connexion.bandwidthLimit); config.spinBox->setValue(this->connexion.bandwidthLimit);
Configuration.show(); Configuration.show();
} }
@ -694,15 +759,18 @@ void MainWindow::on_buttonBox_accepted()
bw = config.spinBox->text(); bw = config.spinBox->text();
if (bw.toInt() == 0) if (bw.toInt() == 0)
{ {
this->connexion.bandwidthLimit = 1000; this->connexion.bandwidthLimit = 0;
this->connexion.bandwidthLimitUnit = tr("PB").toStdString(); this->connexion.bandwidthLimitUnit = 0;
}else }else
{ {
this->connexion.bandwidthLimit = config.spinBox->value(); this->connexion.bandwidthLimit = config.spinBox->value();
this->connexion.bandwidthLimitUnit = config.UnitCombobox->currentText().toStdString()[0]; this->connexion.bandwidthLimitUnit = config.UnitCombobox->currentIndex();
} }
this->settings.setValue("bandwidthlimit", this->connexion.bandwidthLimit); this->settings.setValue("bandwidthlimit", this->connexion.bandwidthLimit);
this->settings.setValue("bandwidthlimitunit", this->connexion.bandwidthLimitUnit.c_str()); this->settings.setValue("bandwidthlimitunit", this->connexion.bandwidthLimitUnit);
this->settings.setValue("Autosave", this->config.autosaveCheckbox->checkState());
this->settings.sync(); this->settings.sync();
Configuration.hide(); Configuration.hide();
} }
@ -712,6 +780,7 @@ void MainWindow::saveDownloadList()
{ {
int nRows; int nRows;
this->settings.remove("Downloads/");
nRows = ui->listDownload->count(); nRows = ui->listDownload->count();
//this->settings.beginWriteArray("Downloads/"); //this->settings.beginWriteArray("Downloads/");
this->settings.beginGroup("Downloads"); this->settings.beginGroup("Downloads");
@ -726,8 +795,8 @@ void MainWindow::saveDownloadList()
void MainWindow::loadDownloadList() void MainWindow::loadDownloadList()
{ {
string path; QString path;
string str; QString str;
int pos; int pos;
this->settings.beginGroup("Downloads"); this->settings.beginGroup("Downloads");
@ -738,21 +807,20 @@ void MainWindow::loadDownloadList()
} }
this->settings.endGroup(); this->settings.endGroup();
this->settings.remove("Downloads");
this->settings.sync(); this->settings.sync();
path = ui->listDownload->item(0)->text().toStdString(); path = ui->listDownload->item(0)->text();
pos = path.rfind("/"); pos = path.lastIndexOf("/");
this->downloading.service = path.substr(pos+1); this->downloading.service = path.midRef(pos+1).toString();
path.resize(pos); path.resize(pos);
pos = path.rfind(" => "); pos = path.lastIndexOf(" => ");
this->downloading.server = path.substr(pos+4); this->downloading.server = path.midRef(pos+4).toString();
path.resize(pos); path.resize(pos);
this->downloading.path = path; this->downloading.path = path;
str = "Folder/" + this->downloading.server + "/" + this->downloading.service; str = "Folder/" + this->downloading.server + "/" + this->downloading.service;
if (this->settings.contains(QString::fromStdString(str))) if (this->settings.contains(str))
{ {
this->downloading.savePath = this->settings.value(QString::fromStdString(str)).toString().toStdString(); this->downloading.savePath = this->settings.value(str).toString();
} }
startDownloading(); startDownloading();
} }
@ -772,3 +840,19 @@ void MainWindow::on_actionDownload_triggered()
item = ui->treeWidget->currentItem(); item = ui->treeWidget->currentItem();
on_treeWidget_itemClicked(item, true); on_treeWidget_itemClicked(item, true);
} }
/*void MainWindow::downloadingErrorSlot(QString errorString)
{
QMessageBox::warning(
this,
"RsyncUI",
errorString,
QMessageBox::Ok,
QMessageBox::Ok);
}
*/
void MainWindow::on_comboBox_currentIndexChanged(int index)
{
ui->toolBar->setToolButtonStyle((Qt::ToolButtonStyle)index);
}

View File

@ -36,29 +36,35 @@
#include <QComboBox> #include <QComboBox>
#include <QStringBuilder> #include <QStringBuilder>
#include <pwd.h> #include <pwd.h>
#include <QProcess>
#include <QToolBar>
#include <QDir>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; } namespace Ui { class MainWindow; }
QT_END_NAMESPACE QT_END_NAMESPACE
extern QMap<int, QString> rsyncErrorStrings;
class Connexion class Connexion
{ {
public: public:
int bandwidthLimit = 0; int bandwidthLimit = 0;
std::string bandwidthLimitUnit = ""; int bandwidthLimitUnit;
std::string server; QString server;
std::string service; QString service;
int port = 873; int port = 873;
bool comboboxChanged;
}; };
class Downloading class Downloading
{ {
public: public:
std::string server; QString server;
std::string service; QString service;
std::string path; QString path;
std::string savePath; QString savePath;
QProcess * process = nullptr;
void clear(); void clear();
}; };
@ -67,7 +73,7 @@ class About
{ {
public: public:
QString title = "RsyncUI"; QString title = "RsyncUI";
QString version = "1.9.1"; QString version = "1.9.2";
QString author = "Daniel TARTAVEL-JEANNOT"; QString author = "Daniel TARTAVEL-JEANNOT";
QString licence = "GPL_V3"; QString licence = "GPL_V3";
QString description; QString description;
@ -84,38 +90,55 @@ class MainWindow : public QMainWindow
MainWindow(QWidget *parent = nullptr); MainWindow(QWidget *parent = nullptr);
~MainWindow(); ~MainWindow();
QProgressDialog *progress; QProgressDialog *progress;
int pid = 0;
Connexion connexion; Connexion connexion;
Downloading downloading; Downloading downloading;
downloadFile downloadO; //downloadFile downloadO;
QSettings settings; QSettings settings;
About about; About about;
QDialog Configuration; QDialog Configuration;
Ui::Configuration config; Ui::Configuration config;
std::vector <QString> serversList; std::vector <QString> serversList;
map<char, int> bwUnixIndex { QList<QString> bwUnitText {
{'B', 0}, "KB",
{'K', 1}, "MB",
{'M', 2}, "TB",
{'G', 3}, "GB",
{'P', 4} "PB"
};
QList<QChar> bwUnitChar{
'K',
'M',
'T',
'G',
'P'
};
QVector<QString> downloadProcessErrorString =
{
tr("The process failed to start. Either the invoked program is missing, or you may have insufficient permissions or resources to invoke the program."),
tr("The process crashed some time after starting successfully."),
tr("The last waitFor...() function timed out. The state of QProcess is unchanged, and you can try calling waitFor...() again."),
tr("An error occurred when attempting to write to the process. For example, the process may not be running, or it may have closed its input channel."),
tr("An error occurred when attempting to read from the process. For example, the process may not be running."),
tr("An unknown error occurred. This is the default return value of error().")
}; };
void displayTree(); void displayTree();
void populateTree(QTreeWidgetItem * parent); void populateTree(QTreeWidgetItem * parent);
void populateList(); void populateList();
void listServices(); void listServices();
bool validateServer(std::string server); bool validateServer(QString server);
bool isIpAddress(std::string server); bool isIpAddress(QString server);
QTreeWidgetItem * addTreeRoot(QString name, QString description, bool isDir); QTreeWidgetItem * addTreeRoot(QString name, QString description, bool isDir);
QTreeWidgetItem * addTreeChild(QTreeWidgetItem *parent, QString name, QString size, bool isDir); QTreeWidgetItem * addTreeChild(QTreeWidgetItem *parent, QString name, QString size, bool isDir);
void scanDir(std::string server, int portN, QTreeWidgetItem *parent = NULL, std::string path = "" ); void scanDir(QString server, int portN, QTreeWidgetItem *parent = NULL, QString path = "" );
void startDownloading(); void startDownloading();
void loadSettings(); void loadSettings();
void saveSettings(); void saveSettings();
void closeEvent (QCloseEvent *event); void closeEvent (QCloseEvent *event);
void saveDownloadList(); void saveDownloadList();
void loadDownloadList(); void loadDownloadList();
void download();
private slots: private slots:
@ -123,7 +146,13 @@ class MainWindow : public QMainWindow
void on_treeWidget_itemClicked(QTreeWidgetItem *item, bool downloadDir = false); void on_treeWidget_itemClicked(QTreeWidgetItem *item, bool downloadDir = false);
void downloadFinished(); void downloadFinished(int exitCode, QProcess::ExitStatus exitStatus);
// void downloadProcessError(QProcess::ProcessError error);
void downloadProcessStderr();
void readRsyncOutput();
void stoppingDownload(); void stoppingDownload();
@ -143,11 +172,20 @@ class MainWindow : public QMainWindow
void on_actionDownload_triggered(); void on_actionDownload_triggered();
public slots: //void downloadingErrorSlot(QString);
void on_comboBox_currentIndexChanged(int index);
void on_buttonBox_accepted(); void on_buttonBox_accepted();
void cancelled(QProcess *);
signals: signals:
void stopDownloading(int); void stopDownloading(QProcess *);
void progressSignal(int);
void finishedSignal(bool = true);
//void errorSignal(QString);
}; };
#endif // MAINWINDOW_H #endif // MAINWINDOW_H

100
tools.cpp
View File

@ -5,6 +5,8 @@ using namespace std;
#define READ 0 #define READ 0
#define WRITE 1 #define WRITE 1
extern QMap<int, QString> rsyncErrorStrings;
//Take a string and explode it in array //Take a string and explode it in array
// s => string to explode // s => string to explode
// c => character separator // c => character separator
@ -41,90 +43,26 @@ const vector<string> explode(const string& s, const char& c, int n = 0)
return v; return v;
} }
// open a pipe, fork and return pid of child bool testRsyncReturn(QProcess * myProcess)
// argv => array of string with command in first and parameters following
FILE * popen2(array<string,8> argv, string type, int & pid)
{ {
pid_t child_pid; if (myProcess->exitStatus() != 0)
int fd[2];
QString message;
string command;
if (pipe(fd) == -1)
{ {
message = "Open pipe failed" + QString::fromStdString(strerror(errno));
QMessageBox::warning( QMessageBox::warning(
NULL, NULL,
"RsyncUI", "RsyncUI",
message); myProcess->errorString(),
exit(-1); QMessageBox::Ok,
}else QMessageBox::Ok);
return true;
}else if (myProcess->exitCode() != 0)
{ {
if((child_pid = fork()) == -1) QMessageBox::warning(
{ NULL,
perror("fork"); "RsyncUI",
exit(1); rsyncErrorStrings[myProcess->exitCode()],
} QMessageBox::Ok,
QMessageBox::Ok);
/* child process */ return true;
if (child_pid == 0)
{
if (type == "r")
{
close(fd[READ]); //Close the READ end of the pipe since the child's fd is write-only
dup2(fd[WRITE], 1); //Redirect stdout to pipe
}
else
{
close(fd[WRITE]); //Close the WRITE end of the pipe since the child's fd is read-only
dup2(fd[READ], 0); //Redirect stdin to pipe
}
setpgid(child_pid, child_pid); //Needed so negative PIDs can kill children of /bin/sh
//TODO : change for execvp
if (execlp(argv[0].c_str(), argv[0].c_str(), argv[1].c_str(), argv[2].c_str(), argv[3].c_str(), argv[4].c_str(), argv[5].c_str(), NULL ) == -1)
exit (0);
}
else
{
if (type == "r")
{
close(fd[WRITE]); //Close the WRITE end of the pipe since parent's fd is read-only
}
else
{
close(fd[READ]); //Close the READ end of the pipe since parent's fd is write-only
}
}
pid = child_pid;
if (type == "r")
{
return fdopen(fd[READ], "r");
}
return fdopen(fd[WRITE], "w");
} }
return 0; return false;
} }
// close pipe open by popen2 while pid is finished
// fp => file pointer
// pid => pid of the processus open bu popen2
int pclose2(FILE * fp, pid_t pid)
{
int stat;
fclose(fp);
while (waitpid(pid, &stat, 0) == -1)
{
if (errno != EINTR)
{
stat = -1;
break;
}
}
return stat;
}

View File

@ -4,6 +4,10 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <array> #include <array>
#include <QString>
#include <QMap>
#include <QTranslator>
#include <QProcess>
using namespace std; using namespace std;
@ -13,4 +17,7 @@ FILE * popen2(array<string,8> argv, string type, int & pid);
int pclose2(FILE * fp, pid_t pid); int pclose2(FILE * fp, pid_t pid);
bool testRsyncReturn(QProcess *);
#endif // TOOLS_H #endif // TOOLS_H