Compare commits

...

36 Commits

Author SHA1 Message Date
6a381c05c8 removed includes of unused libraries and code correction 2023-03-11 13:59:55 +01:00
106727506d removed includes of unused libraries 2023-03-11 13:56:19 +01:00
e10558ff5b bug correction: when stopping a dl an error when prompted 2023-03-11 13:53:05 +01:00
f40e4f9485 version 2.10.1 2023-03-11 13:31:19 +01:00
d82c8c942d debugging 2023-03-11 13:30:17 +01:00
1739b0adf3 version 2.10 2023-03-09 18:14:03 +01:00
fada0ebeb0 added storing password in a secure way 2023-03-09 18:13:46 +01:00
bc90ce2269 version 2.9.2 2023-03-08 16:15:18 +01:00
0a1aa6c4fd code cleaning 2023-03-08 16:09:17 +01:00
8df2a651a3 version 2.9.1 2023-03-08 16:03:44 +01:00
5f5277199a correction of password managment 2023-03-08 16:03:24 +01:00
63bcc965b5 added selecting user for password protected services 2023-03-05 14:18:43 +01:00
42a7376f58 version 2.9 2023-03-05 13:39:39 +01:00
83ef43fab1 testing password encryption 2023-03-05 13:39:16 +01:00
9d305b0b3b added date in qtreeview\nadded retry in case of download error 2023-03-05 13:38:28 +01:00
711ca7d1cd added mime filetype in qtreeview 2023-03-04 19:12:13 +01:00
927c4a932a some code cleaning\nSize in treeview is now hulan readable\nbegin of password encryption 2023-03-04 17:33:18 +01:00
8227c76a88 version 2.8 2023-03-02 20:20:08 +01:00
d326e63a2f added icon to directory in qtreeview 2023-03-02 20:19:20 +01:00
85dc65fc9e version 2.7 2023-03-02 17:06:46 +01:00
04b46b1b86 added access to gidden services 2023-03-02 17:06:15 +01:00
6bfbfe1c78 version 2.6.1 2023-03-01 15:50:55 +01:00
7e736b524e bug correction in making treeview 2023-03-01 15:50:37 +01:00
3345a65b28 version 2.6 2023-03-01 14:25:31 +01:00
63f7aafc68 translation 2023-03-01 14:25:06 +01:00
f47160622c Added support for password protected services 2023-03-01 14:12:38 +01:00
e7eafb3117 added password protected connexion
correction bug on detection of already downloaded file
2023-02-27 23:48:05 +01:00
10060ee2c4 version 2.5 2023-02-22 00:57:07 +01:00
e14d1539fe Merge branch 'master' of git.labolyon.fr:dtux/RsyncUI 2023-02-22 00:53:29 +01:00
a8e888e20d corrected regression: resuming downloadlist download did not start\n added downloading speed in progress bar 2023-02-22 00:52:53 +01:00
f3c361f155 corrected regression: resuming downloadlist download did not start\n added downloading speed in progress bar 2023-02-22 00:48:16 +01:00
e8743ff802 version 2.4.1 2023-02-16 21:33:53 +01:00
1145c74440 - resolved regression: no icon on menutray. 2023-02-16 21:28:58 +01:00
c42baaa2c8 changed qtcreator config 2023-02-15 14:25:21 +01:00
8419f8ad90 - resolved a bug in filelist: when clicking again on a directory add
again files
- resolved bug: at startup relaoding download do not start downloading
- added downloading filename in progress bar
2023-02-15 13:49:31 +01:00
623ad81c6b version 2.4 2023-02-15 13:48:38 +01:00
15 changed files with 906 additions and 335 deletions

View File

@ -22,6 +22,7 @@ Un clic gauche sur un fichier l'ajoute à la file des téléchargements, sur un
Un clic droit sur un dossier ouvre un menu contextuel permettant de télécharger le dossier entier.
Une notification s'affiche lors du début, de la fin, et lorsque l'on stoppe un téléchargement.
Le gadget de fermeture ferme la fenêtre mais ne quitte pas l'application, pour afficher à nouveau la fenêtre, cliquez sur l'icône dans la boite à miniatures.
Un identifiant et un mot de passe lorsqu'un service est protégé par mot de passe, celui-ci est enregistré dans le portefeuille système(gome-keyring ou kwallet)
## File de téléchargement
@ -30,7 +31,7 @@ Cliquez sur un fichier pour le supprimer de la file et une fenêtre de confirmat
## Barre d'outils
1er icône: Changer le dossier de destination
Permet de changer le dossier de téléchargement par défaut pour chaque service de chaque serveur.
- Permet de changer le dossier de téléchargement par défaut pour chaque service de chaque serveur.
2ème icône: Paramètres de l'application
- Limite de bande passante
@ -41,7 +42,7 @@ Cliquez sur un fichier pour le supprimer de la file et une fenêtre de confirmat
- Enregistrement automatique
Enregistre automatiquement la liste des téléchargements en cours.(activé par défaut)
3ème icône: À propos
Affiche les propriétés de l'application.
- Affiche les propriétés de l'application.
4ème icône: À propos de QT
5 ème icône: Quitter
5ème icône: Quitter
Permet de quitter le programme.

View File

@ -6,11 +6,14 @@ QT += KConfigCore KConfigGui
QT += KCoreAddons
QT += KDBusAddons
#LIBS += -lKF5WindowSystem
LIBS += -lqt5keychain
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
DEFINES += QTKEYCHAIN_NO_EXPORT
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
@ -19,11 +22,13 @@ SOURCES += \
downloadfile.cpp \
main.cpp \
mainwindow.cpp \
password.cpp \
tools.cpp
HEADERS += \
downloadfile.h \
mainwindow.h \
password.h \
tools.h
FORMS += \
@ -35,7 +40,8 @@ TRANSLATIONS += \
RsyncUI_fr_FR.ts
INCLUDEPATH += \
/usr/include/KF5
/usr/include/KF5 \
/usr/include/qt5keychain/
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
@ -61,3 +67,4 @@ desktopfile.path = /usr/share/applications
desktopfile.files = RsyncUI.desktop
icon.path = /usr/share/icons/
icon.files = RsyncUI.png
-lqt5keychain

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 4.14.2, 2023-02-13T00:55:51. -->
<!-- Written by QtCreator 4.14.2, 2023-03-09T22:37:54. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>

View File

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

View File

@ -66,6 +66,34 @@
<translation>Enregistrement automatique de la file d&apos;enregistrement</translation>
</message>
</context>
<context>
<name>LoginDialog</name>
<message>
<location filename="login.ui" line="17"/>
<source>RsyncUI request</source>
<translation>Requête RsyncUI</translation>
</message>
<message>
<location filename="login.ui" line="51"/>
<source>Login name</source>
<translation>Identifiant</translation>
</message>
<message>
<location filename="login.ui" line="79"/>
<source>Enter login</source>
<translation>Entrez votre identifiant</translation>
</message>
<message>
<location filename="login.ui" line="86"/>
<source>Password</source>
<translation>Mot de passe</translation>
</message>
<message>
<location filename="login.ui" line="102"/>
<source>Enter password</source>
<translation>Entrez votre mot de passe</translation>
</message>
</context>
<context>
<name>MainWindow</name>
<message>
@ -74,141 +102,151 @@
<translation>Fenêtre principale</translation>
</message>
<message>
<location filename="mainwindow.ui" line="86"/>
<location filename="mainwindow.ui" line="87"/>
<source>Server</source>
<oldsource>Serveur</oldsource>
<translation>Serveur</translation>
</message>
<message>
<location filename="mainwindow.ui" line="108"/>
<location filename="mainwindow.ui" line="109"/>
<source>Enter server&apos;s URL</source>
<translation>Entrez l&apos;adresse du serveur</translation>
</message>
<message>
<location filename="mainwindow.ui" line="124"/>
<location filename="mainwindow.ui" line="125"/>
<source>Port</source>
<translation>Port</translation>
</message>
<message>
<location filename="mainwindow.ui" line="152"/>
<location filename="mainwindow.ui" line="153"/>
<source>Enter rsync port on server</source>
<translation>Entrez le port du serveur rsync</translation>
</message>
<message>
<location filename="mainwindow.ui" line="189"/>
<location filename="mainwindow.ui" line="190"/>
<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="195"/>
<location filename="mainwindow.ui" line="196"/>
<source>Connection</source>
<translation>Connexion</translation>
</message>
<message>
<location filename="mainwindow.ui" line="198"/>
<location filename="mainwindow.ui" line="199"/>
<source>Return</source>
<translation>Retour</translation>
</message>
<message>
<location filename="mainwindow.ui" line="224"/>
<location filename="mainwindow.ui" line="225"/>
<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="259"/>
<location filename="mainwindow.ui" line="260"/>
<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="337"/>
<location filename="mainwindow.ui" line="329"/>
<source>Filter...</source>
<translation>Filtrer...</translation>
</message>
<message>
<location filename="mainwindow.ui" line="341"/>
<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="360"/>
<location filename="mainwindow.ui" line="367"/>
<source>%p%</source>
<extracomment>Downloading</extracomment>
<translation>Téléchargement</translation>
</message>
<message>
<location filename="mainwindow.ui" line="371"/>
<location filename="mainwindow.ui" line="378"/>
<source>toolBar</source>
<translation>Barre d&apos;outils</translation>
</message>
<message>
<location filename="mainwindow.ui" line="444"/>
<location filename="mainwindow.ui" line="452"/>
<source>Download</source>
<translation>Télécharger</translation>
</message>
<message>
<location filename="mainwindow.ui" line="447"/>
<location filename="mainwindow.ui" line="455"/>
<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="455"/>
<location filename="mainwindow.ui" line="464"/>
<source>Exit</source>
<translation>Quitter</translation>
</message>
<message>
<location filename="mainwindow.ui" line="458"/>
<location filename="mainwindow.ui" line="467"/>
<source>Terminate the program</source>
<translation>Terminer le programme</translation>
</message>
<message>
<location filename="mainwindow.ui" line="461"/>
<location filename="mainwindow.ui" line="470"/>
<source>Ctrl+Q</source>
<translation>Ctrl+Q</translation>
</message>
<message>
<location filename="mainwindow.ui" line="409"/>
<location filename="mainwindow.ui" line="412"/>
<location filename="mainwindow.ui" line="479"/>
<source>hidden service</source>
<translation>Service caché</translation>
</message>
<message>
<location filename="mainwindow.ui" line="417"/>
<location filename="mainwindow.ui" line="420"/>
<source>Change save folder</source>
<translation>Changer le dossier de destination</translation>
</message>
<message>
<location filename="mainwindow.ui" line="421"/>
<location filename="mainwindow.ui" line="429"/>
<source>About</source>
<translation>À propos</translation>
</message>
<message>
<location filename="mainwindow.ui" line="430"/>
<location filename="mainwindow.ui" line="438"/>
<source>About Qt</source>
<translation>À propos de Qt</translation>
</message>
<message>
<location filename="mainwindow.ui" line="439"/>
<location filename="mainwindow.ui" line="447"/>
<source>Settings</source>
<translation>Paramètres</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="101"/>
<location filename="mainwindow.h" line="123"/>
<source>KB</source>
<translation>Ko</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="101"/>
<location filename="mainwindow.h" line="124"/>
<source>MB</source>
<translation>Mo</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="101"/>
<location filename="mainwindow.h" line="125"/>
<source>GB</source>
<translation>Go</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="101"/>
<location filename="mainwindow.h" line="126"/>
<source>TB</source>
<translation>To</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="101"/>
<location filename="mainwindow.h" line="127"/>
<source>PB</source>
<translation>Po</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="59"/>
<location filename="mainwindow.cpp" line="61"/>
<source>You click on file to enqueue it, and RyncUI Download one file a time</source>
<oldsource>Client for rsync server&lt;br&gt;&lt;br&gt;You click on file to enqueue it, and RyncUI Download one file a time</oldsource>
<translation>&lt;h3&gt;Utilisation&lt;/h3&gt;
@ -241,180 +279,240 @@ Cliquez sur un fichier pour le supprimer de la file et une fenêtre de confirmat
Permet de quitter le programme</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="53"/>
<source>&lt;h2&gt;Client for rsync server&lt;2&gt;&lt;br&gt;&lt;br&gt;</source>
<translation>&lt;h2&gt;Client pour serveur rsync&lt;2&gt;&lt;br&gt;&lt;br&gt;éaa</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="73"/>
<location filename="mainwindow.cpp" line="78"/>
<source>Path</source>
<translation>Chemin</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="73"/>
<location filename="mainwindow.cpp" line="78"/>
<source>Size</source>
<translation>Taille</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="73"/>
<location filename="mainwindow.cpp" line="78"/>
<source>Type</source>
<translation>Type</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="108"/>
<location filename="mainwindow.cpp" line="78"/>
<source>Date</source>
<translation>Date</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="105"/>
<source>KB/s</source>
<translation>Ko/s</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="105"/>
<source>MB/s</source>
<translation>Mo/s</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="105"/>
<source>GB/s</source>
<translation>Go/s</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="105"/>
<source>TB/s</source>
<translation>To/s</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="105"/>
<source>PB/s</source>
<translation>Po/s</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="123"/>
<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="136"/>
<location filename="mainwindow.cpp" line="152"/>
<source>&amp;Quit</source>
<translation>&amp;Quitter</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="193"/>
<location filename="mainwindow.cpp" line="209"/>
<source>Clicking Save button, You can save the list of downloads
</source>
<translation>Vous pouvez enregistrer la liste des téléchargements en cliquant sur &quot;enregister&quot;
</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="198"/>
<location filename="mainwindow.cpp" line="215"/>
<source>Exiting will stop downloading, and will clear the download queue.
Do you want to exit ?</source>
<translation>Si vous sortez, les téléchargements seront arrêter.
Voulez-vous vraiment sortir ?</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="226"/>
<location filename="mainwindow.cpp" line="253"/>
<source>The program will keep running in the system tray. To terminate the program, choose &lt;b&gt;Quit&lt;/b&gt; in the context menu of the system tray entry.</source>
<translation>Le programme continue dans la boîte à miniatures. Pour quitter le programme cliquez sur l&apos;icône &lt;b&gt;Quitter&lt;/b&gt; ou dans les menu contextuel.</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="511"/>
<location filename="mainwindow.cpp" line="513"/>
<source>The processus does&apos;nt respond: </source>
<translation>Le processus ne répond pas: </translation>
</message>
<message>
<location filename="mainwindow.cpp" line="599"/>
<source>server does not exists</source>
<translation>Le serveur n&apos;existe pas</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="538"/>
<location filename="mainwindow.cpp" line="558"/>
<location filename="mainwindow.cpp" line="633"/>
<location filename="mainwindow.cpp" line="745"/>
<source>Dir</source>
<translation>dossier</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="542"/>
<location filename="mainwindow.cpp" line="626"/>
<source>File</source>
<translation>Doc</translation>
<translation type="vanished">Doc</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="635"/>
<location filename="mainwindow.cpp" line="773"/>
<source>File is partially downloaded. Do you want to resume download ? if no, the file will be deleted from destination directory</source>
<translation>Le document est déjà partiellement téléchargé. Voulez vous continuer le téléchargemnt ? Si non, il sera supprimer du dossier de destination</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="790"/>
<source>File is already downloaded. Do you want to reload it ? The old file will be deleted</source>
<translation>Le document est déjà téléchargé. Voulez-vous le télécharger à nouveau ? L&apos;ancien fichier sera effacé</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="670"/>
<location filename="mainwindow.cpp" line="827"/>
<source>File is already downloading</source>
<translation>Le document est déjà en téléchargement</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="693"/>
<location filename="mainwindow.cpp" line="852"/>
<source>Starting downloading
</source>
<translation>Démarrage du téléchargement
</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="708"/>
<location filename="mainwindow.cpp" line="867"/>
<source>finished</source>
<translation>Terminé</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="716"/>
<location filename="mainwindow.cpp" line="877"/>
<source>Rsync process crashed</source>
<translation>Le processus rsync à planté</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="728"/>
<location filename="mainwindow.cpp" line="884"/>
<source>stopped by user</source>
<translation>stoppé par l&apos;utilisateur</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="732"/>
<location filename="mainwindow.cpp" line="895"/>
<source>
Do you want to retry?</source>
<translation>
Voulez-vous -essayer?</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="904"/>
<source>Download </source>
<translation>Téléchargement </translation>
</message>
<message>
<location filename="mainwindow.cpp" line="54"/>
<location filename="mainwindow.cpp" line="1257"/>
<source>RsyncUI Request</source>
<translation>Requête RsyncUI</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="1258"/>
<source>Hidden service name</source>
<translation>Nom du servcice caché</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="56"/>
<source>Version</source>
<translation>Version</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="55"/>
<source>&lt;h2&gt;Client for rsync server&lt;/h2&gt;</source>
<translation>&lt;h2&gt;Client pour serveur rsync&lt;/h2&gt;</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="57"/>
<source>Licence</source>
<translation>License</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="56"/>
<location filename="mainwindow.cpp" line="58"/>
<source>Author</source>
<translation>Auteur</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="57"/>
<location filename="mainwindow.cpp" line="59"/>
<source>EMail</source>
<translation>Courriel</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="58"/>
<location filename="mainwindow.cpp" line="60"/>
<source>Source code</source>
<translation>Code source</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="899"/>
<location filename="mainwindow.cpp" line="1073"/>
<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="904"/>
<location filename="mainwindow.cpp" line="1078"/>
<source>Choose folder where to save file</source>
<translation>Choisissez un dossier enregistrer le document</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="796"/>
<location filename="mainwindow.cpp" line="969"/>
<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="810"/>
<location filename="mainwindow.cpp" line="983"/>
<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="125"/>
<location filename="mainwindow.h" line="122"/>
<source>B</source>
<translation>o</translation>
</message>
<message>
<location filename="mainwindow.h" line="139"/>
<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="126"/>
<location filename="mainwindow.h" line="140"/>
<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="127"/>
<location filename="mainwindow.h" line="141"/>
<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="128"/>
<location filename="mainwindow.h" line="142"/>
<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="129"/>
<location filename="mainwindow.h" line="143"/>
<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="130"/>
<location filename="mainwindow.h" line="144"/>
<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>

View File

@ -27,7 +27,14 @@ downloadFile::downloadFile()
//Slot activated when download is cancelled
void MainWindow::cancelled(QProcess * process)
{
bool n = 0;
process->terminate();
n = process->waitForFinished(30000);
if (n == false)
{
process->close();
}
}
// launch a rsync processus downloading a file
@ -35,18 +42,26 @@ void MainWindow::download()
{
QString cmd;
QStringList param;
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
this->downloading.process = new QProcess(this);
if (!this->downloading.user.isEmpty())
{
this->downloading.server.prepend(this->connexion.user + "@");
env.insert("RSYNC_PASSWORD", this->downloading.password); // Add an environment variable
this->downloading.process->setProcessEnvironment(env);
}
// Populating array with command and parameters for popen2
cmd = "rsync";
if (this->connexion.bandwidthLimit != 0)
{
param << "--bwlimit=" + QString::number(this->connexion.bandwidthLimit) + bwUnitChar[this->connexion.bandwidthLimitUnit];
}
param << "--port=" + QString::number(this->connexion.port);
param << "--port=" + QString::number(this->downloading.port);
param << "-aXP";
param << this->downloading.server + "::" + this->downloading.service + "/" + this->downloading.path << this->downloading.savePath + "/";
this->downloading.process = new QProcess(this);
connect(this->downloading.process, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(downloadFinished(int, QProcess::ExitStatus)));
//connect(this->downloading.process, SIGNAL(errorOccurred(QProcess::ProcessError error)), this, SLOT(downloadProcessError(QProcess::ProcessError error)));
@ -62,50 +77,51 @@ void MainWindow::readRsyncOutput()
bool flag = false;
int value;
int pos;
static QString dlSpeed;
QStringList list;
static QString filename;
int i;
int listSize;
while(!flag)
{
list.clear();
line = QString::fromUtf8(this->downloading.process->readLine());
if (line.isEmpty())
{
flag = true;
break;
}
}else
{
pos = line.indexOf("%");
if (pos != -1)
{
line.resize(pos);
line = line.simplified();
list = line.split(" ");
listSize = list.count() / 4;
for (i = 0; i < listSize; i++)
{
value = list.at(i *4 + 1).chopped(1).toInt();
dlSpeed = list.at(i * 4 + 2);
/*line.resize(pos);
pos = line.lastIndexOf(' ');
if (pos != -1)
{
line.remove(0, pos);
value = line.toInt();
value = line.toInt();*/
// sending progress to Main window
emit progressSignal(value);
emit fileName(filename + " %p%" + "\t " + dlSpeed);
}
}else
{
if (!line.contains("receiving"))
{
filename = line.remove(QChar('\n'), Qt::CaseInsensitive);
emit fileName(filename + " %p%\t " + dlSpeed);
}
}
}
}
}
/*void MainWindow::downloadProcessError(QProcess::ProcessError error)
{
QMessageBox::warning(
this,
"RsyncUI",
downloadProcessErrorString[error].toStdString().c_str()
);
}*/
// process raise error
void MainWindow::downloadProcessStderr()
{
QByteArray errorLine;
errorLine = this->downloading.process->readAllStandardError();
QMessageBox::warning(
this,
"RsyncUI",
errorLine
);
}

View File

@ -21,7 +21,11 @@ int main(int argc, char *argv[])
a.installTranslator(&myappTranslator);
}
static const QString appName = "RsyncUI";
//Password passwdJob;
MainWindow w;
w.show();
w.init();
return a.exec();
}

View File

@ -4,9 +4,9 @@
using namespace std;
bool display = false;
//extern QDialog Configuration;
extern Ui::Configuration config;
extern bool testRsyncReturn(QProcess *);
extern QApplication a;
QMap<int, QString> rsyncErrorStrings {
{0, QTranslator::tr("Success. The rsync command completed successfully without any errors.")},
@ -33,16 +33,15 @@ MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
QAbstractButton * reply;
QMessageBox msgBox;
ui->setupUi(this);
QCoreApplication::setOrganizationName("RsyncUI");
QCoreApplication::setApplicationName("RsyncUI");
this->setWindowTitle(a.applicationName());
// context menu for treewidget (list of files)
ui->treeWidget->addAction(ui->actionDownload);
// init configuration window
config.setupUi(&Configuration);
@ -61,16 +60,27 @@ MainWindow::MainWindow(QWidget *parent)
AboutW.TextAbout->setHtml(aboutText);
// connectors
connect(this, &MainWindow::fileName, ui->progressBar, &QProgressBar::setFormat);
connect(this, &MainWindow::progressSignal, ui->progressBar, &QProgressBar::setValue);
//connect(this, &MainWindow::errorSignal, this, &MainWindow::downloadingErrorSlot);
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);
loadSettings();
// init of widgets
ui->ktreewidgetsearchline->setTreeWidget(ui->treeWidget); // attach search widget to treewidget
ui->ktreewidgetsearchline->setCaseSensitivity(Qt::CaseInsensitive); // and set it case insensitive
ui->treeWidget->setHeaderLabels({tr("Path"), tr("Type"), tr("Size")} ); // set header of columns of tree widget
ui->treeWidget->setHeaderLabels({tr("Path"), tr("Type"), tr("Size"), tr("Date"), "fullSize"} ); // set header of columns of tree widget
//ui->treeWidget->header()->setContextMenuPolicy();
// setting arrowcursor for treeWidget, listWidget and listDownload to arrow
ui->treeWidget->setCursor(Qt::ArrowCursor);
ui->listWidget->setCursor(Qt::ArrowCursor);
ui->listDownload->setCursor(Qt::ArrowCursor);
// Hiding progress bar
ui->progressBar->hide();
// if last server exists in settings
if (this->settings.contains("connexion/lastServer"))
@ -80,31 +90,32 @@ MainWindow::MainWindow(QWidget *parent)
ui->khistorycombobox->setCurrentText(this->settings.value("connexion/lastServer").toString());
}else
{
ui->portEdit->text() = QString::number(this->connexion.port);
ui->portEdit->setText(QString::number(this->connexion.port));
ui->khistorycombobox->clear();
}
// setting arrowcursor for treeWidget, listWidget and listDownload to arrow
ui->treeWidget->setCursor(Qt::ArrowCursor);
ui->listWidget->setCursor(Qt::ArrowCursor);
ui->listDownload->setCursor(Qt::ArrowCursor);
// Hiding progress bar
ui->progressBar->hide();
loadSettings();
//setting configuration window
config.comboBox->setCurrentIndex(ui->toolBar->toolButtonStyle()); // setting combobox to saved settings
//setting unit of bandwidth limit
config.UnitCombobox->addItems({tr("KB"), tr("MB"), tr("GB"), tr("TB"), tr("PB")});
config.UnitCombobox->addItems({tr("KB/s"), tr("MB/s"), tr("GB/s"), tr("TB/s"), tr("PB/s")});
// hide fullsize column of treeview
ui->treeWidget->setColumnHidden(4, true);
initSystemTrayIcon();
}
void MainWindow::init()
{
QAbstractButton * reply;
QMessageBox msgBox;
//if exists list of donwloads in saved settings
if (this->settings.value("Downloads/rows").toInt() != 0)
{
// asking if we load the list and continue downloading
msgBox.setWindowTitle("RsyncUI");
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 *yes = msgBox.addButton(QMessageBox::Yes);
@ -121,17 +132,18 @@ MainWindow::MainWindow(QWidget *parent)
}
}
// load list of services
populateList();
initSystemTrayIcon();
populateList(ui->khistorycombobox->currentIndex());
}
void MainWindow::initSystemTrayIcon()
{
QMenu *trayIconMenu;
QAction * quitAction;
QIcon icon;
icon.addFile(this->icon);
this->trayIcon = new QSystemTrayIcon;
this->trayIcon->setIcon(this->windowIcon());
this->trayIcon->setIcon(icon);
quitAction = new QAction(tr("&Quit"), this);
connect(quitAction, &QAction::triggered, this, &MainWindow::quitApp);
@ -192,23 +204,34 @@ void MainWindow::quitApp()
param |= QMessageBox::Save;
displayText = tr("Clicking Save button, You can save the list of downloads\n");
}
reply = QMessageBox::question(
this,
"RsyncUI",
a.applicationName(),
tr("Exiting will stop downloading, and will clear the download queue.\nDo you want to exit ?") + displayText,
param,
QMessageBox::No);
this->downloading.quit = true;
if(reply == QMessageBox::Yes)
{
if (this->downloading.process->state() != QProcess::NotRunning)
{
// emission of signal to downloading thread and stopping
emit (stopDownloading(this->downloading.process));
}else
}
}else if (reply == QMessageBox::Save)
{
saveDownloadList();
if (config.autosaveCheckbox->checkState() == Qt::Unchecked)
{
//saveDownloadList();
emit (stopDownloading(this->downloading.process));
}
}else if (reply == QMessageBox::No)
{
return;
}
}
//delete ui;
QCoreApplication::quit();
}
@ -222,7 +245,7 @@ void MainWindow::closeEvent (QCloseEvent *event)
return;
if (trayIcon->isVisible() and this->settings.value("CloseCheckbox").toBool() == false)
{
msgBox.setWindowTitle("RsyncUI");
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 "
@ -249,7 +272,7 @@ void MainWindow::closeEvent (QCloseEvent *event)
}
// Populate treeview with list of files
void MainWindow::populateTree(QTreeWidgetItem * parent)
void MainWindow::populateTree()
{
QString path;
@ -263,9 +286,12 @@ void MainWindow::populateTree(QTreeWidgetItem * parent)
// validating server's address
if (validateServer(this->connexion.server))
{
// server is validated
path = ui->listWidget->currentItem()->text().section('\n', 0, 0) + "/";
scanDir(this->connexion.server, this->connexion.port, parent, path);
// server is validated, scanning directory
path = this->connexion.service + "/";
while (this->rescan)
{
scanDir(this->connexion.server, this->connexion.port, nullptr, path);
}
}
// Restoring cursor
QGuiApplication::restoreOverrideCursor();
@ -273,12 +299,15 @@ void MainWindow::populateTree(QTreeWidgetItem * parent)
}
// Populate Listview with list of services
void MainWindow::populateList()
void MainWindow::populateList(int item)
{
QString server;
QString service;
QStringList hidden;
int port;
int i;
server = ui->khistorycombobox->currentText();
server = ui->khistorycombobox->itemText(item);
port = ui->portEdit->text().toUInt();
if ((server != this->connexion.server) or (port != this->connexion.port))
{
@ -324,10 +353,73 @@ void MainWindow::populateList()
}
}
this->settings.endGroup();
this->settings.beginGroup("Hidden/" + server);
hidden = this->settings.allKeys();
if (hidden.count() > 0)
{
for (i = 0; i < hidden.size(); i++)
{
service = hidden[i];
//TODO detect if service is already present
if (testServicePresence(service, false))
{
ui->listWidget->addItem(service + "\n\t");
}
}
}
this->settings.endGroup();
QGuiApplication::restoreOverrideCursor(); //setting cursor to default
}
}
// Test if service is already present on the server
bool MainWindow::testServicePresence(QString service, bool askPassword)
{
QString cmd;
QStringList param;
QString line;
QString errorRsync;
QStringList v;
QProcess *myProcess;
bool returnValue = false;
QEventLoop loop;
cmd = "/usr/bin/rsync";
param << "--contimeout=10" << "-nq" << "--port=" + QString::number(this->connexion.port) << this->connexion.server + "::" + service;
myProcess = new QProcess(this);
myProcess->setProcessChannelMode(QProcess::MergedChannels);
myProcess->start(cmd, param);
myProcess->waitForStarted();
myProcess->write("\n");
//myProcess->waitForFinished(12000);
while(myProcess->waitForReadyRead(10000))
{
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)
{
getUserPassword(&this->connexion);
}
returnValue = true;
}
}
}
if (myProcess->exitCode() == 0)
{
returnValue = true;
}
myProcess->close();
return returnValue;
}
//list services of the rsync server
void MainWindow::listServices()
{
@ -341,7 +433,7 @@ void MainWindow::listServices()
bool flag = false;
cmd = "/usr/bin/rsync";
param << "--contimeout=10" << "--port=" + QString::number(this->connexion.port) << this->connexion.server + "::";
param << "--contimeout=20" << "--port=" + QString::number(this->connexion.port) << this->connexion.server + "::";
myProcess = new QProcess(this);
myProcess->start(cmd, param);
@ -371,29 +463,60 @@ void MainWindow::listServices()
}
// verifying error code
testRsyncReturn(myProcess);
testRsyncReturn(this, myProcess);
myProcess->close();
}
// connect to rsync server to get list of files
void MainWindow::scanDir(QString server, int portN, QTreeWidgetItem *parent, QString path)
bool MainWindow::scanDir(QString server, int portN, QTreeWidgetItem *parent, QString path)
{
QString cmd;
QStringList param;
QStringList sizeA;
QString line;
QString size;
QString fullsize;
QString filename;
QString fileType;
QString date;
QProcess * myProcess;
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
bool isDir = false;
bool flag = false;
cmd = "rsync";
param << "--contimeout=10" << "--port=" + QString::number(portN) << server + "::" + path;
bool readOk = false;
bool passwdOk = false;
int nChild = 0;
myProcess = new QProcess(this);
myProcess->setProcessChannelMode(QProcess::MergedChannels);
if (parent != nullptr)
{
nChild = parent->childCount();
}
if (nChild == 0)
{
if (!this->connexion.user.isEmpty())
{
server.prepend(this->connexion.user + "@");
env.insert("RSYNC_PASSWORD", this->connexion.password); // Add an environment variable
}else
{
server.prepend("anonymous@");
env.insert("RSYNC_PASSWORD", "anonymous"); // Add an environment variable
}
myProcess->setProcessEnvironment(env);
cmd = "rsync";
param << "--contimeout=20" << "--port=" + QString::number(portN) << server + "::" + path;
myProcess->start(cmd, param);
// waiting for responsiteme of the server with a timeout of 10 seconds
while(myProcess->waitForReadyRead(100000))
// waiting for response of the server with a timeout of 10 seconds
do
{
readOk = myProcess->waitForReadyRead(10000);
if (readOk)
{
while (!flag)
{
@ -404,12 +527,32 @@ void MainWindow::scanDir(QString server, int portN, QTreeWidgetItem *parent, QSt
flag = true;
break;
}
// extracting name, size and is dir/file
if (line.contains("auth failed"))
{
myProcess->readAllStandardOutput();
getUserPassword(&this->connexion);
this->rescan = true;
return 0;
}
// extracting name, size and if is dir/file
line = line.simplified();
size = line.section(" ", 1, 1);
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;
@ -417,22 +560,39 @@ void MainWindow::scanDir(QString server, int portN, QTreeWidgetItem *parent, QSt
{
isDir = false;
}
if (parent != NULL)
date = line.section(' ', 2, 2);
fileType = getFileType(filename);
addTreeItem(filename, size, fullsize, fileType, date, isDir, parent);
if (passwdOk == false and !this->connexion.password.isEmpty())
{
//adding item to tree
addTreeChild(parent, filename, size, isDir);
this->settings.setValue("Passwords/" + this->connexion.server + "/" + this->connexion.service + "/" + this->connexion.user, true);
setPassword(this->connexion.user, this->connexion.password);
this->settings.sync();
}
this->rescan = false;
}
}
flag = false;
}else
{
//adding item to tree (as directory)
addTreeRoot(filename, size, isDir);
if (myProcess->state() == QProcess::Running)
{
if (myProcess->waitForFinished(10000) == 0)
{
QMessageBox::warning(
this,
a.applicationName(),
tr("The processus does'nt respond: ") + myProcess->errorString());
}
}
}
flag = false;
}
}while(readOk);
// buffer empty go to waiting new datas
testRsyncReturn(myProcess);
testRsyncReturn(this, myProcess);
myProcess->close();
}
return 0;
}
// Verify if server address is IP address
@ -507,74 +667,78 @@ bool MainWindow::validateServer(QString server)
// server-s address not valid
QMessageBox::warning(
this,
"RsyncUI",
a.applicationName(),
tr("server does not exists" )
);
}
myProcess->close();
return flag;
}
// slot activated when combobox is changed
void MainWindow::on_khistorycombobox_currentIndexChanged(int i)
void MainWindow::on_khistorycombobox_currentIndexChanged(int item)
{
this->connexion.comboboxChanged = true;
populateList();
populateList(item);
}
// slot activated when button connection is clicked
void MainWindow::on_connectButton_clicked()
{
populateList();
populateList(ui->khistorycombobox->currentIndex());
}
// add a dir in treeview
QTreeWidgetItem * MainWindow::addTreeRoot(QString name, QString fileSize, bool isDir)
// add parent in treeview
void MainWindow::addTreeItem(QString name, QString fileSize, QString fullsize, QString type, QString date, bool isDir=false, QTreeWidgetItem *parent=nullptr)
{
QTreeWidgetItem *treeItem = new QTreeWidgetItem(ui->treeWidget);
QTreeWidgetItem *treeItem;
if (parent != nullptr)
{
treeItem = new QTreeWidgetItem();
}else
{
treeItem = new QTreeWidgetItem(ui->treeWidget);
}
if (isDir == true)
{
// item is a dir
treeItem->setText(1, tr("Dir"));
treeItem->setIcon(0, QIcon::fromTheme("folder"));
}else
{
// item is a file
treeItem->setText(1,tr("File"));
treeItem->setText(1,type);
}
treeItem->setText(0, name);
treeItem->setText(2, fileSize);
treeItem->setText(3, date);
treeItem->setText(4, fullsize);
return treeItem;
}
treeItem->setTextAlignment(2, Qt::AlignRight);
// add a file in treeview
QTreeWidgetItem * MainWindow::addTreeChild(QTreeWidgetItem *parent, QString name, QString fileSize, bool isDir)
{
QTreeWidgetItem *treeItem = new QTreeWidgetItem();
if (isDir == true)
if (parent != nullptr)
{
// item is a dir
treeItem->setText(1, tr("Dir"));
}else
{
// item is a file
treeItem->setText(1,("File"));
}
treeItem->setText(0, name);
treeItem->setText(2, fileSize);
// QTreeWidgetItem::addChild(QTreeWidgetItem * child)
parent->addChild(treeItem);
return treeItem;
}
}
// Slot acivated when a service in the list is clicked
// Slot activated when a service in the list is clicked
void MainWindow::on_listWidget_clicked()
{
QString str;
this->connexion.service = ui->listWidget->currentItem()->text().section("\n", 0 ,0);
ui->treeWidget->clear();
preparePopulateTree();
}
void MainWindow::preparePopulateTree()
{
QString str;
QStringList logins;
this->rescan = true;
this->connexion.user = nullptr;
this->connexion.password = nullptr;
str = "Folder/" + this->connexion.server + "/" + this->connexion.service;
// if service exists in settings for this server
if (this->settings.contains(str))
@ -582,24 +746,105 @@ void MainWindow::on_listWidget_clicked()
// setting savePath from settings
this->downloading.savePath = this->settings.value(str).toString();
}
populateTree(NULL);
//getUserPassword(&this->connexion);
populateTree();
}
// get password and user login
// if object = false ==> searching from connexion object
// else searching from downloading object
bool MainWindow::getUserPassword(Connexion * object)
{
QStringList logins;
QString login;
QString password;
QString server;
QString service;
int c;
bool returnValue = false;
bool ok = false;
server = object->server;
service = object->service;
object->user = "";
object->password = "";
this->settings.beginGroup("Passwords/" + server + "/" + service);
logins = this->settings.allKeys();
c = logins.count();
if ( c != 1)
{
//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 = "";
}
}else
{
password = getPassword(login);
}
object->user = login;
object->password = password;
}
}else
{
object->user = logins.at(0);
object->password = getPassword(object->user);
returnValue = true;
}
this->settings.endGroup();
return returnValue;
}
//Slot activated when a file is clicked in the treeview
void MainWindow::on_treeWidget_itemClicked(QTreeWidgetItem *item, bool downloadDir)
{
QFuture<void> future;
QFileDialog dialog;
QTreeWidgetItem * itemR;
QString path;
QString str;
QMessageBox::StandardButton reply;
int sizeFromRsync;
itemR = item;
// assembling path from treewidget
path = item->text(0);
sizeFromRsync = item->text(4).toUInt();
while(itemR->parent() != NULL)
{
itemR = itemR->parent();
// concatening parent to path
path.prepend(itemR->text(0) + "/");
};
cout << item->text(1).toStdString() <<endl;
if (item->text(1) != tr("Dir") or downloadDir == true)
{
// exists saving path in settings ?
str = "Folder/" + this->connexion.server + "/" + this->connexion.service;
if(!this->settings.contains(str))
@ -615,23 +860,34 @@ void MainWindow::on_treeWidget_itemClicked(QTreeWidgetItem *item, bool downloadD
this->downloading.savePath = this->settings.value(str).toString();
}
while(itemR->parent() != NULL)
{
itemR = itemR->parent();
// concatening parent to path
path.prepend(itemR->text(0) + "/");
};
if (item->text(1) == tr("File") or downloadDir == true)
{
// Item is a file
// searching if file exists in savepath
if (QFile::exists(this->downloading.savePath + "/" + path))
{
QFileInfo info(this->downloading.savePath + "/" + path);
if (info.size() < sizeFromRsync)
{
reply = QMessageBox::question(
this,
"RsyncUI",
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)
{
return;
}else if(reply == QMessageBox::No)
{
QFile::remove(this->downloading.savePath + "/" + path);
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);
@ -644,6 +900,7 @@ void MainWindow::on_treeWidget_itemClicked(QTreeWidgetItem *item, bool downloadD
QFile::remove(this->downloading.savePath + "/" + path);
}
}
}
if(ui->listDownload->findItems(path, Qt::MatchStartsWith).empty())
{
@ -653,6 +910,7 @@ void MainWindow::on_treeWidget_itemClicked(QTreeWidgetItem *item, bool downloadD
// 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
@ -666,16 +924,20 @@ void MainWindow::on_treeWidget_itemClicked(QTreeWidgetItem *item, bool downloadD
{
QMessageBox::warning(
this,
"RsyncUI",
a.applicationName(),
tr("File is already downloading" )
);
}
}else
{
//Item is a Directory
while (this->rescan)
{
scanDir(this->connexion.server, this->connexion.port, item, this->connexion.service + "/" + path +"/");
item->setExpanded(true);
}
}
if (config.autosaveCheckbox->checkState() == Qt::Checked)
{
saveDownloadList();
@ -685,12 +947,14 @@ void MainWindow::on_treeWidget_itemClicked(QTreeWidgetItem *item, bool downloadD
// Launch the thread which download the file
void MainWindow::startDownloading()
{
ui->progressBar->setValue(0);
ui->progressBar->show();
//getUserPassword();
//QtConcurrent::run(&this->downloadO, &downloadFile::download, this);
download();
this->trayIcon->showMessage("RsyncUI", tr("Starting downloading\n") + this->downloading.path, QSystemTrayIcon::Information);
this->download();
this->trayIcon->showMessage(a.applicationName(), tr("Starting downloading\n") + this->downloading.path, QSystemTrayIcon::Information);
}
// Slot stopping download
@ -706,50 +970,60 @@ void MainWindow::downloadFinished(int exitCode, QProcess::ExitStatus exitStatus)
QString str;
int pos;
QString aborted = tr("finished");
QMessageBox::StandardButton reply;
bool retry = false;
// test if process crashed
if (exitStatus == QProcess::CrashExit)
{
QMessageBox::warning(
NULL,
"RsyncUI",
a.applicationName(),
tr("Rsync process crashed"));
}
//test result code of command (if 20 then command stopped by user)
if (exitCode != 0 and exitCode != 20)
if (exitCode != 0 and this->stopDlAsked != true)
{
// displaying warning with exit code
QMessageBox::warning(
NULL,
"RsyncUI",
rsyncErrorStrings[exitCode]);
}else if (exitCode == 20)
if (exitCode == 20)
{
aborted = tr("stopped by user");
}else if (exitCode == 5) // password asked
{
getUserPassword(&this->downloading);
retry = true;
}
this->trayIcon->showMessage("RsyncUI", tr("Download ") + aborted + "\n" + this->downloading.path, QSystemTrayIcon::Information);
// displaying warning with exit code
reply = QMessageBox::warning(
this,
a.applicationName(),
rsyncErrorStrings[exitCode] + tr("\nDo you want to retry?"),
QMessageBox::Yes|QMessageBox::No,
QMessageBox::Yes);
if (reply == QMessageBox::Yes)
{
retry = true;
}
}
this->stopDlAsked = false;
this->trayIcon->showMessage(a.applicationName(), tr("Download ") + aborted + "\n" + this->downloading.path, QSystemTrayIcon::Information);
// disconnecting signals to slots
disconnect(this->downloading.process, 0, 0, 0);
// reset variables and window
this->downloading.process = nullptr;
// reset variables and window, close process
this->downloading.process->close();
ui->progressBar->hide();
if (retry == false)
{
delete ui->listDownload->takeItem(0);
}
this->downloading.clear();
// Some downloads staying in queue
if (ui->listDownload->count() != 0)
{
// autosave is activated
if (config.autosaveCheckbox->checkState() == Qt::Checked)
{
// saving download list
saveDownloadList();
}
// initializing download
path = ui->listDownload->item(0)->text();
pos = path.lastIndexOf("/");
@ -760,25 +1034,31 @@ void MainWindow::downloadFinished(int exitCode, QProcess::ExitStatus exitStatus)
path.resize(pos);
this->downloading.path = path;
//getUserPassword(true);
testServicePresence(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 deleting download";
//downloadFinished();
cout << "Error no save path so removing download";
return;
}
}
}
if(config.autosaveCheckbox->checkState() == Qt::Checked and this->downloading.quit == false)
{
saveDownloadList();
}
}
@ -792,13 +1072,14 @@ void MainWindow::on_listDownload_itemClicked(QListWidgetItem *item)
// first line clicked on download list
reply = QMessageBox::question(
this,
"RsyncUI",
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));
}
}else
@ -806,7 +1087,7 @@ void MainWindow::on_listDownload_itemClicked(QListWidgetItem *item)
// not first line on download list
reply = QMessageBox::question(
this,
"RsyncUI",
a.applicationName(),
tr("Do you want to delete this file from download queue ?"),
QMessageBox::Yes|QMessageBox::No,
QMessageBox::No);
@ -815,13 +1096,13 @@ void MainWindow::on_listDownload_itemClicked(QListWidgetItem *item)
// removing line from download list
ui->listDownload->removeItemWidget(item);
delete item;
}
}
if (config.autosaveCheckbox->checkState() == Qt::Checked)
{
// autosave acivated,so saving download list
saveDownloadList();
}
}
}
}
// load settings
@ -895,7 +1176,7 @@ bool MainWindow::on_DefaultSaveFolder_triggered()
{
QMessageBox::warning(
NULL,
"RsyncUI",
a.applicationName(),
tr("Since the save path is linked to service, you need to select a service before you can select a folder"));
return false;
}
@ -995,6 +1276,7 @@ void MainWindow::loadDownloadList()
path.resize(pos);
pos = path.lastIndexOf(" => ");
this->downloading.server = path.midRef(pos+4).toString();
this->downloading.port = this->settings.value("connexion/server/" + this->downloading.server).toInt();
path.resize(pos);
this->downloading.path = path;
str = "Folder/" + this->downloading.server + "/" + this->downloading.service;
@ -1006,12 +1288,17 @@ void MainWindow::loadDownloadList()
}
// clear object downloading
void Downloading::clear()
void Connexion::clear()
{
this->path.clear();
this->server.clear();
this->savePath.clear();
this->service.clear();
this->user.clear();
this->password.clear();
this->port = 0;
this->process = nullptr;
this->quit = false;
}
// Context menu of file list clicked
@ -1027,7 +1314,7 @@ void MainWindow::on_actionDownload_triggered()
{
QMessageBox::warning(
this,
"RsyncUI",
a.applicationName(),
errorString,
QMessageBox::Ok,
QMessageBox::Ok);
@ -1044,3 +1331,25 @@ void MainWindow::on_actionExit_triggered()
{
quitApp();
}
void MainWindow::setDlSpeed(QString speed)
{
speed.squeeze();
}
void MainWindow::on_actionHiddenService_triggered()
{
QInputDialog hiddenFolderDialog;
bool ok;
QString text = QInputDialog::getText(this, a.applicationName() + tr(" Request"),
tr("Hidden service name"), QLineEdit::Normal,
"test", &ok);
if (ok && !text.isEmpty())
{
this->connexion.service = text;
this->settings.setValue("Hidden/" + this->connexion.server + '/' + text, true);
ui->listWidget->addItem(text + "\n\t");
preparePopulateTree();
}
}

View File

@ -7,9 +7,11 @@
#include "ui_about.h"
#include "downloadfile.h"
#include "tools.h"
#include "password.h"
#include <QMainWindow>
#include <string>
#include <QTreeWidgetItem>
#include <QList>
#include <QListWidgetItem>
#include <QProgressDialog>
#include <QSettings>
@ -23,8 +25,6 @@
#include <cstdio>
#include <QMessageBox>
#include <boost/algorithm/string/replace.hpp>
#include <QFuture>
#include <qtconcurrentrun.h>
#include <QFileDialog>
#include <QThread>
#include <QProgressDialog>
@ -42,7 +42,8 @@
#include <QDir>
#include <QSystemTrayIcon>
#include <QMenu>
#include<QTranslator>
#include <QTranslator>
#include <QInputDialog>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
@ -55,10 +56,18 @@ class Connexion
public:
int bandwidthLimit = 0;
int bandwidthLimitUnit;
int contimeout = 20;
QString server;
QString service;
QString path;
QString savePath;
QString user;
QString password;
QProcess * process = nullptr;
int port = 873;
bool comboboxChanged;
bool quit = false;
void clear();
};
class Downloading
@ -68,16 +77,18 @@ class Downloading
QString service;
QString path;
QString savePath;
QString user;
QString password;
int port = 873;
QProcess * process = nullptr;
bool quit = false;
void clear();
};
class About
{
public:
QString title = "RsyncUI";
QString version = "2.3.1";
QString version = "2.10.1";
QString author = "Daniel TARTAVEL-JEANNOT";
QString licence = "GPL_V3";
QString description;
@ -93,10 +104,10 @@ class MainWindow : public QMainWindow
Ui::MainWindow *ui;
MainWindow(QWidget *parent = nullptr);
~MainWindow();
// passwdManager;
QProgressDialog *progress;
Connexion connexion;
Downloading downloading;
//downloadFile downloadO;
Connexion downloading;
QSettings settings;
About about;
QDialog Configuration;
@ -105,12 +116,17 @@ class MainWindow : public QMainWindow
Ui::windowAbout AboutW;
std::vector <QString> serversList;
QSystemTrayIcon * trayIcon;
QList<QString> bwUnitText {
"KB",
"MB",
"TB",
"GB",
"PB"
QString icon = "/usr/share/icons/RsyncUI.png";
bool rescan = false;
bool stopDlAsked;
QList<QString> UnitText {
tr("B"),
tr("KB"),
tr("MB"),
tr("GB"),
tr("TB"),
tr("PB")
};
QList<QChar> bwUnitChar{
'K',
@ -131,14 +147,13 @@ class MainWindow : public QMainWindow
};
void displayTree();
void populateTree(QTreeWidgetItem * parent);
void populateList();
void populateTree();
void populateList(int);
void listServices();
bool validateServer(QString server);
bool isIpAddress(QString server);
QTreeWidgetItem * addTreeRoot(QString name, QString description, bool isDir);
QTreeWidgetItem * addTreeChild(QTreeWidgetItem *parent, QString name, QString size, bool isDir);
void scanDir(QString server, int portN, QTreeWidgetItem *parent = NULL, QString path = "" );
void addTreeItem(QString name, QString fileSize, QString fullsize, QString type, QString date, bool isDir, QTreeWidgetItem *parent);
bool scanDir(QString server, int portN, QTreeWidgetItem *parent = NULL, QString path = "" );
void startDownloading();
void loadSettings();
void saveSettings();
@ -149,6 +164,12 @@ class MainWindow : public QMainWindow
void initSystemTrayIcon();
void hideWindow();
void showWindow();
void init();
bool getUserPassword(Connexion *);
void preparePopulateTree();
bool testServicePresence(QString, bool=false);
void passwordStore (QString account, QString password);
QString passwordGet (QString account);
private slots:
@ -158,10 +179,6 @@ class MainWindow : public QMainWindow
void downloadFinished(int exitCode, QProcess::ExitStatus exitStatus);
// void downloadProcessError(QProcess::ProcessError error);
void downloadProcessStderr();
void readRsyncOutput();
void stoppingDownload();
@ -196,12 +213,17 @@ class MainWindow : public QMainWindow
void on_actionExit_triggered();
void setDlSpeed(QString speed);
void on_actionHiddenService_triggered();
signals:
void stopDownloading(QProcess *);
void progressSignal(int);
void speed(QString);
void finishedSignal(bool = true);
//void errorSignal(QString);
void fileName(QString);
void passwordReady();
};
#endif // MAINWINDOW_H

View File

@ -21,7 +21,8 @@
<string>MainWindow</string>
</property>
<property name="windowIcon">
<iconset theme="/usr/share/icons/RsyncUI.png"/>
<iconset theme="/usr/share/icons/RsyncUI.png">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextUnderIcon</enum>
@ -274,10 +275,10 @@
<bool>false</bool>
</property>
<property name="dragEnabled">
<bool>true</bool>
<bool>false</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::DragOnly</enum>
<enum>QAbstractItemView::NoDragDrop</enum>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
@ -324,6 +325,9 @@
<property name="inputMethodHints">
<set>Qt::ImhNoAutoUppercase</set>
</property>
<property name="placeholderText">
<string>Filter...</string>
</property>
</widget>
</item>
</layout>
@ -356,6 +360,9 @@
<property name="value">
<number>0</number>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="format">
<string extracomment="Downloading">%p%</string>
</property>
@ -395,6 +402,7 @@
<bool>false</bool>
</attribute>
<addaction name="DefaultSaveFolder"/>
<addaction name="actionHiddenService"/>
<addaction name="action_Settings"/>
<addaction name="actionAbout"/>
<addaction name="actionAbout_Qt"/>
@ -449,7 +457,8 @@
</action>
<action name="actionExit">
<property name="icon">
<iconset theme="application-exit"/>
<iconset theme="application-exit">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Exit</string>
@ -461,6 +470,15 @@
<string>Ctrl+Q</string>
</property>
</action>
<action name="actionHiddenService">
<property name="icon">
<iconset theme="folder-open">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>hidden service</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>

55
password.cpp Normal file
View File

@ -0,0 +1,55 @@
#include "mainwindow.h"
#include "password.h"
#include <qt5keychain/keychain.h>
#include <qt5keychain/qkeychain_export.h>
#include <QSettings>
using namespace std;
extern QApplication a;
QString appName = "RsyncUI";
static QSettings sett{appName, appName};
void setPassword(QString account, QString pass)
{
QKeychain::WritePasswordJob write(appName);
write.setSettings(&sett);
// write.setAutoDelete(false);
write.setKey(account);
write.setTextData(pass);
QEventLoop loop;
write.connect(&write, &QKeychain::WritePasswordJob::finished, &loop, &QEventLoop::quit);
write.start();
loop.exec();
if(write.error())
cout << "Error writing key1. Error: " << write.errorString().toStdString();
}
QString getPassword(const QString& name)
{
QKeychain::ReadPasswordJob readPass(appName);
readPass.setSettings(&sett);
// readPass.setAutoDelete(false);
readPass.setKey(name);
QEventLoop loop;
readPass.connect(&readPass, &QKeychain::ReadPasswordJob::finished, &loop, &QEventLoop::quit);
readPass.start();
loop.exec();
if(readPass.error())
{
cout << "KeyHandler~Error reading decrypt Pass. Error: " + readPass.errorString() . toStdString() << endl;
return "";
}
else
{
QString data = readPass.textData();
return data;
}
}

35
password.h Normal file
View File

@ -0,0 +1,35 @@
#ifndef PASSWORD_H
#define PASSWORD_H
#include "mainwindow.h"
#include <qt5keychain/keychain.h>
#include <qt5keychain/qkeychain_export.h>
extern QApplication a;
void setPassword(QString account, QString pass);
QString getPassword(const QString& name);
/*class Password : QObject
{
public:
QString appName;
QKeychain::WritePasswordJob * passwdJob;
QKeychain::ReadPasswordJob * readPass;
MainWindow * mw;
QString password;
QSettings passwdSettings{a.applicationName(),a.applicationName()};
Password();
~Password();
void store(QString, QString);
QString read(QString);
bool remove(QString);
private slots:
void storeFinished();
void readFinished();
};*/
#endif // PASSWORD_H

View File

@ -6,6 +6,7 @@ using namespace std;
#define WRITE 1
extern QMap<int, QString> rsyncErrorStrings;
extern QApplication a;
//Take a string and explode it in array
// s => string to explode
@ -44,26 +45,28 @@ const vector<string> explode(const string& s, const char& c, int n = 0)
}
// test return code of rsync
bool testRsyncReturn(QProcess * myProcess)
// return true in case of error
bool testRsyncReturn(MainWindow * w, QProcess * myProcess)
{
if (myProcess->exitStatus() != 0)
if (myProcess->exitStatus() != 0 and w->stopDlAsked != true)
{
QMessageBox::warning(
NULL,
"RsyncUI",
w,
a.applicationName(),
myProcess->errorString(),
QMessageBox::Ok,
QMessageBox::Ok);
return true;
}else if (myProcess->exitCode() != 0)
{
QMessageBox::warning(
NULL,
"RsyncUI",
rsyncErrorStrings[myProcess->exitCode()],
QMessageBox::Ok,
QMessageBox::Ok);
return true;
}
w->stopDlAsked = false;
return false;
}
QString getFileType(QString filename)
{
QMimeDatabase db;
QMimeType mime = db.mimeTypeForFile(filename);
QString returnValue = mime.name().section('/',0 ,0);
return returnValue;
}

View File

@ -1,6 +1,7 @@
#ifndef TOOLS_H
#define TOOLS_H
#include "mainwindow.h"
#include <string>
#include <vector>
#include <array>
@ -8,6 +9,8 @@
#include <QMap>
#include <QTranslator>
#include <QProcess>
#include <QMimeDatabase>
#include <QMimeType>
using namespace std;
@ -17,7 +20,7 @@ FILE * popen2(array<string,8> argv, string type, int & pid);
int pclose2(FILE * fp, pid_t pid);
bool testRsyncReturn(QProcess *);
bool testRsyncReturn(MainWindow *, QProcess *);
QString getFileType(QString finename);
#endif // TOOLS_H