Compare commits

..

20 Commits
1.4 ... 1.8.10

Author SHA1 Message Date
cbb09fe258 version 1.8.10 2023-02-03 12:50:03 +01:00
fa7f3a1ca8 version 1.8.9 2023-02-03 12:48:56 +01:00
c9f85354a6 version 1.8.8 2023-02-03 12:40:18 +01:00
ab91309abd version 1.8.7 2023-02-03 12:29:43 +01:00
7f767b0576 version 1.8.6 2023-02-03 01:04:59 +01:00
9229d3523e debug 2023-02-03 01:04:48 +01:00
7770813647 version 1.8.5 2023-02-03 00:57:23 +01:00
4b434fc393 version 1.8.4 2023-02-03 00:40:32 +01:00
5804e43d1f added context menu to download folders 2023-02-02 17:14:04 +01:00
d70d081139 a lot of debug 2023-02-02 16:10:51 +01:00
9f9c5c19a3 added .desktop file and icon 2023-01-31 14:03:25 +01:00
4dbfa8fa97 débogage et modifications suite perte de code :-( ) 2023-01-31 00:45:53 +01:00
fe74ab906f adding saving of folder by server name\n modifying columns order\some bugs corrected 2023-01-28 15:41:48 +01:00
295c914b12 toolbar added 2023-01-27 19:43:48 +01:00
434b430869 replaced menu by toolbar 2023-01-27 18:14:50 +01:00
0648a06dbc correct version string 2023-01-26 12:04:08 +01:00
ff7a75e168 some traductions 2023-01-26 12:02:12 +01:00
149eb24590 some traductions\nadded init of cursor 2023-01-26 11:48:25 +01:00
012573f89d modified algo filling treeview to speed 2023-01-26 11:31:56 +01:00
eb7795c791 config file is now ~/.config/RsyncUI.conf 2023-01-23 23:42:20 +01:00
17 changed files with 809 additions and 265 deletions

5
README_FR.md Normal file
View File

@ -0,0 +1,5 @@
# RsyncUI
client Rsync - QT5 - KDE
#Compilation:

15
RsyncUI.desktop Normal file
View File

@ -0,0 +1,15 @@
[Desktop Entry]
Name=RsyncUI
GenericName=rsync client
Comment=Client for rsync servers
Comment[fr]=Client pour serveur rsync
Version=1.0
Exec=RsyncUI
Icon=
Type=Application
Terminal=false
StartupNotify=true
Categories=Network
Keywords=internet,rsync

BIN
RsyncUI.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -44,3 +44,18 @@ else: unix:!android: target.path = /usr/bin/
lang.path = /languages/fr_FR/ lang.path = /languages/fr_FR/
lang.files = languages/fr_FR/* lang.files = languages/fr_FR/*
INSTALLS += lang INSTALLS += lang
INSTALLS += documentation
INSTALLS += desktopfile
INSTALLS += icon
RESOURCES +=
DISTFILES += \
RsyncUI.desktop
documentation.path = /usr/share/doc/RsyncUI
documentation.files = README*
desktopfile.path = /usr/share/applications
desktopfile.files = RsyncUI.desktop
icon.path = /usr/share/icons/
icon.files = RsyncUI.png

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-01-11T01:16:59. --> <!-- Written by QtCreator 4.14.2, 2023-02-02T16:28:47. -->
<qtcreator> <qtcreator>
<data> <data>
<variable>EnvironmentId</variable> <variable>EnvironmentId</variable>

72
RsyncUI.spec Normal file
View File

@ -0,0 +1,72 @@
%define oname RsyncUI
Name: rsyncui
Summary: Client for rsync server
Version: 1.8.5
Release: %mkrel 1
License: GPLv3
Group: Networking/Remote access
Source0: %{oname}-%{version}.tar.gz
Packager: dtux@free.fr
Distribution: Mageia
Url: https://www.librepc.fr
Vendor: DTux
BuildRequires: qmake
BuildRequires: make
BuildRequires: pkgconfig(Qt5Core)
BuildRequires: pkgconfig(Qt5Gui)
BuildRequires: pkgconfig(Qt5Concurrent)
BuildRequires: pkgconfig(Qt5Widgets)
BuildRequires: pkgconfig(Qt5Xml)
BuildRequires: pkgconfig(libmagic)
BuildRequires: cmake(KF5Completion)
BuildRequires: cmake(KF5CoreAddons)
BuildRequires: cmake(KF5I18n)
BuildRequires: cmake(KF5DBusAddons)
BuildRequires: cmake(KF5Config)
BuildRequires: cmake(KF5ItemViews)
BuildRequires: pstreams-devel
BuildRequires: boost-devel
#Requires: kitemviews
#Requires: kcompletion
#Requires: kcoreaddons
#Requires: kdbusaddons
Requires: rsync
Requires: bind-utils
%global debug_package %{nil}
%description
RsyncUI can connect to an rsync server, get the list of services,
and download files.
%prep
%setup -q -n %{oname}
%build
%make_build
%install
#INSTALL_ROOT=%{BUILDROOT} make install
mkdir -p %{buildroot}%{_bindir}
mkdir -p %{buildroot}%{_datadir}/applications/
mkdir -p %{buildroot}%{_datadir}/icons/
install -p -m 755 %{oname} %{buildroot}%{_bindir}/%{oname}
install -p -m 644 %{oname}.desktop %{buildroot}%{_datadir}/applications/
install -p -m 644 %{oname}.png %{buildroot}%{_datadir}/icons/
pushd languages
for locale in *;
do
mkdir -p %{buildroot}%{_datadir}/locale/$locale/LC_MESSAGES
install -m 644 $locale/*.qm "%{buildroot}%{_datadir}/locale/$locale/LC_MESSAGES/"
done
popd
%find_lang %{oname} --with-qt
%files -f %{oname}.lang
%{_bindir}/%{oname}
%{_datadir}/applications/%{oname}.desktop
%{_datadir}/icons/%{oname}.png

Binary file not shown.

View File

@ -10,9 +10,12 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>400</width> <width>400</width>
<height>127</height> <height>163</height>
</rect> </rect>
</property> </property>
<property name="contextMenuPolicy">
<enum>Qt::DefaultContextMenu</enum>
</property>
<property name="windowTitle"> <property name="windowTitle">
<string>Configuration</string> <string>Configuration</string>
</property> </property>
@ -22,14 +25,31 @@
<x>9</x> <x>9</x>
<y>9</y> <y>9</y>
<width>381</width> <width>381</width>
<height>61</height> <height>101</height>
</rect> </rect>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</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"> <item row="0" column="1">
<widget class="QSpinBox" name="spinBox"> <widget class="QSpinBox" name="spinBox">
<property name="toolTip"> <property name="toolTip">
<string>Enter the bandwidth limit</string> <string>Enter the bandwidth limit (0 to 1024)</string>
</property> </property>
<property name="toolTipDuration"> <property name="toolTipDuration">
<number>5000</number> <number>5000</number>
@ -42,13 +62,6 @@
</property> </property>
</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="0" column="2"> <item row="0" column="2">
<widget class="QComboBox" name="UnitCombobox"> <widget class="QComboBox" name="UnitCombobox">
<property name="sizePolicy"> <property name="sizePolicy">
@ -74,17 +87,55 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1">
<widget class="QComboBox" name="comboBox">
<property name="maxVisibleItems">
<number>6</number>
</property>
<property name="maxCount">
<number>6</number>
</property>
<item>
<property name="text">
<string>Icon only</string>
</property>
</item>
<item>
<property name="text">
<string>Text only</string>
</property>
</item>
<item>
<property name="text">
<string>Text beside icon</string>
</property>
</item>
<item>
<property name="text">
<string>Text under icon</string>
</property>
</item>
<item>
<property name="text">
<string>Text follow icon</string>
</property>
</item>
</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>70</x> <x>60</x>
<y>80</y> <y>110</y>
<width>321</width> <width>321</width>
<height>34</height> <height>34</height>
</rect> </rect>
</property> </property>
<property name="contextMenuPolicy">
<enum>Qt::NoContextMenu</enum>
</property>
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
@ -95,35 +146,19 @@
</widget> </widget>
<resources/> <resources/>
<connections> <connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Configuration</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection> <connection>
<sender>buttonBox</sender> <sender>buttonBox</sender>
<signal>rejected()</signal> <signal>rejected()</signal>
<receiver>Configuration</receiver> <receiver>Configuration</receiver>
<slot>reject()</slot> <slot>hide()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>316</x> <x>220</x>
<y>260</y> <y>126</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>286</x> <x>199</x>
<y>274</y> <y>81</y>
</hint> </hint>
</hints> </hints>
</connection> </connection>

View File

@ -19,59 +19,73 @@
using namespace std; using namespace std;
// Initialization de la class
downloadFile::downloadFile() downloadFile::downloadFile()
{ {
} }
//Slot activated when download is cancelled
void downloadFile::cancelled(int pid) void downloadFile::cancelled(int pid)
{ {
if (kill(pid, SIGTERM) == -1) if (pid == 0)
{ {
//TODO gestion erreur kill 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
void downloadFile::download(MainWindow *mw) void downloadFile::download(MainWindow *mw)
{ {
string line; string line;
string errorRsync; string errorRsync;
int pos; int pos;
array<string, 7> argv; array<string,8> argv;
stringstream output; stringstream output;
vector<string> v; vector<string> v;
int value; int value;
char buffer[4096]; char buffer[4096];
Downloading d;
d = mw->downloading;
// Populating array with command and parameters for popen2
argv[0] = "/usr/bin/rsync"; argv[0] = "/usr/bin/rsync";
if (mw->connexion.bandwidthLimit == 0) if (mw->connexion.bandwidthLimit == 0)
{ {
argv[1] = "--bwlimit=1000P"; argv[1] = "--bwlimit=1000P";
}else }else
{ {
output << mw->connexion.bandwidthLimit; argv[1] = "--bwlimit=" + to_string(mw->connexion.bandwidthLimit) + mw->connexion.bandwidthLimitUnit;
argv[1] = "--bwlimit=" + output.str() + mw->connexion.bandwidthLimitUnit;
} }
argv[2] = "--port=" + to_string(mw->connexion.port); argv[2] = "--port=" + to_string(mw->connexion.port);
argv[3] = "-P"; argv[3] = "-aP";
argv[4] = mw->connexion.server + "::" + mw->downloading.service + "/" + mw->downloading.path; argv[4] = d.server + "::" + d.service + "/" + d.path;
argv[5] = mw->downloading.savePath + "/"; argv[5] = d.savePath + "/";
argv[6] = ""; argv[6].clear();
//launching downloading thread //launching downloading thread
FILE * fp = popen2(argv, "r", mw->downloading.pid); FILE * fp = popen2(argv, "r", mw->pid);
if (!fp) if (fp <= (FILE *) 0)
{ {
throw runtime_error("popen2() failed!"); sprintf(buffer, "popen2() failed!: returning code:%d", fileno(fp));
throw runtime_error(buffer);
return; return;
} }
// waiting rsync output
while (fgets(buffer, 4096, fp) != nullptr) while (fgets(buffer, 4096, fp) != nullptr)
{ {
// Downloading is cancelled, we return
if (this->canceled == true) if (this->canceled == true)
{ {
return; return;
} }
line = buffer; line = buffer;
// extracting percentage of completion
pos = line.find('%'); pos = line.find('%');
if (pos != -1) if (pos != -1)
{ {
@ -81,14 +95,15 @@ void downloadFile::download(MainWindow *mw)
{ {
line.erase(0, pos); line.erase(0, pos);
value = stoi(line); value = stoi(line);
// sending progress to Main window
emit progressSignal(value); emit progressSignal(value);
} }
} }
// download ended
} }
pclose2(fp, mw->downloading.pid); pclose2(fp, mw->pid);
// ProgressBar to 100% and emit signal finished to main application // ProgressBar to 100% and emit signal finished to main application
emit progressSignal(100); emit progressSignal(100);
emit finishedSignal(true); emit finishedSignal(true);
} }

Binary file not shown.

View File

@ -4,28 +4,57 @@
<context> <context>
<name>Configuration</name> <name>Configuration</name>
<message> <message>
<location filename="../../configuration.ui" line="17"/> <location filename="../../configuration.ui" line="20"/>
<source>Configuration</source> <source>Configuration</source>
<translation>Configuration</translation> <translation>Configuration</translation>
</message> </message>
<message> <message>
<location filename="../../configuration.ui" line="32"/> <location filename="../../configuration.ui" line="38"/>
<source>Enter the bandwidth limit</source> <source>Toolbar view</source>
<translation>Entrez la limite de bande passante <translation>Toolbar</translation>
</translation>
</message> </message>
<message> <message>
<location filename="../../configuration.ui" line="48"/> <location filename="../../configuration.ui" line="45"/>
<source>Bandwidth limit</source> <source>Bandwidth limit</source>
<extracomment>Bandwidth limit</extracomment> <extracomment>Bandwidth limit</extracomment>
<translation>Limite de bande passante</translation> <translation>Limite de bande passante</translation>
</message> </message>
<message> <message>
<location filename="../../configuration.ui" line="61"/> <location filename="../../configuration.ui" line="52"/>
<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="74"/>
<source>Select th unit of bandwidth limit in Bytes, KiloBytes, MegaBytes, GigaBytes or PetaBytes</source> <source>Select th unit of bandwidth limit in Bytes, KiloBytes, MegaBytes, GigaBytes or PetaBytes</source>
<extracomment>Unit of bandwidth</extracomment> <extracomment>Unit of bandwidth</extracomment>
<translation>Sélectionnez l&apos;unité de limite de bande passante en otctets, Ko, Mo, Go, Po</translation> <translation>Sélectionnez l&apos;unité de limite de bande passante en otctets, Ko, Mo, Go, Po</translation>
</message> </message>
<message>
<location filename="../../configuration.ui" line="100"/>
<source>Icon only</source>
<translation>Icône seule</translation>
</message>
<message>
<location filename="../../configuration.ui" line="105"/>
<source>Text only</source>
<translation>Texte seul</translation>
</message>
<message>
<location filename="../../configuration.ui" line="110"/>
<source>Text beside icon</source>
<translation>Text à côté de l&apos;icône</translation>
</message>
<message>
<location filename="../../configuration.ui" line="115"/>
<source>Text under icon</source>
<translation>Texte sous l&apos;icöne</translation>
</message>
<message>
<location filename="../../configuration.ui" line="120"/>
<source>Text follow icon</source>
<translation>Texte suit l&apos;icône</translation>
</message>
</context> </context>
<context> <context>
<name>MainWindow</name> <name>MainWindow</name>
@ -35,197 +64,225 @@
<translation>Fenêtre principale</translation> <translation>Fenêtre principale</translation>
</message> </message>
<message> <message>
<location filename="../../mainwindow.ui" line="80"/> <location filename="../../mainwindow.ui" line="83"/>
<source>Server</source> <source>Server</source>
<oldsource>Serveur</oldsource> <oldsource>Serveur</oldsource>
<translation>Serveur</translation> <translation>Serveur</translation>
</message> </message>
<message> <message>
<location filename="../../mainwindow.ui" line="102"/> <location filename="../../mainwindow.ui" line="105"/>
<source>Enter server&apos;s URL</source> <source>Enter server&apos;s URL</source>
<translation>Entrez l&apos;adresse du serveur</translation> <translation>Entrez l&apos;adresse du serveur</translation>
</message> </message>
<message> <message>
<location filename="../../mainwindow.ui" line="118"/> <location filename="../../mainwindow.ui" line="121"/>
<source>Port</source> <source>Port</source>
<translation>Port</translation> <translation>Port</translation>
</message> </message>
<message> <message>
<location filename="../../mainwindow.ui" line="143"/> <location filename="../../mainwindow.ui" line="149"/>
<source>Enter rsync port on server</source> <source>Enter rsync port on server</source>
<translation>Entrez le port du servuer rsync</translation> <translation>Entrez le port du serveur rsync</translation>
</message> </message>
<message> <message>
<location filename="../../mainwindow.ui" line="177"/> <location filename="../../mainwindow.ui" line="186"/>
<source>Press button to connect to rsync server</source> <source>Press button to connect to rsync server</source>
<extracomment>Connect to server</extracomment> <extracomment>Connect to server</extracomment>
<translation>Cliquez pour se connecter au serveur rsync</translation> <translation>Cliquez pour se connecter au serveur rsync</translation>
</message> </message>
<message> <message>
<location filename="../../mainwindow.ui" line="183"/> <location filename="../../mainwindow.ui" line="192"/>
<source>Connection</source> <source>Connection</source>
<translation>Connexion</translation> <translation>Connexion</translation>
</message> </message>
<message> <message>
<location filename="../../mainwindow.ui" line="186"/> <location filename="../../mainwindow.ui" line="195"/>
<source>Return</source> <source>Return</source>
<translation>Retour</translation> <translation>Retour</translation>
</message> </message>
<message> <message>
<location filename="../../mainwindow.ui" line="209"/> <location filename="../../mainwindow.ui" line="221"/>
<source>Click to view the list of files of this folder</source> <source>Click to view the list of files of this folder</source>
<translation>Cliquez pour afficher la liste des documents</translation> <translation>Cliquez pour afficher la liste des documents</translation>
</message> </message>
<message> <message>
<location filename="../../mainwindow.ui" line="238"/> <location filename="../../mainwindow.ui" line="256"/>
<source>Click to add to download queue</source> <source>Click to add to download queue</source>
<translation>Cliquez pour ajouter à la file de téléchargement</translation> <translation>Cliquez pour ajouter à la file de téléchargement</translation>
</message> </message>
<message> <message>
<location filename="../../mainwindow.ui" line="307"/> <location filename="../../mainwindow.ui" line="334"/>
<source>Click on file to stop downloading</source> <source>Click on file to stop downloading</source>
<translation>Cliquez sur le document pour arrêter le téléchargement et l&apos;enleveer de la file</translation> <translation>Cliquez sur le document pour arrêter le téléchargement et l&apos;enlever de la file</translation>
</message> </message>
<message> <message>
<location filename="../../mainwindow.ui" line="327"/> <location filename="../../mainwindow.ui" line="357"/>
<source>%p%</source> <source>%p%</source>
<extracomment>Downloading</extracomment> <extracomment>Downloading</extracomment>
<translation>Téléchargement</translation> <translation>Téléchargement</translation>
</message> </message>
<message> <message>
<location filename="../../mainwindow.ui" line="344"/> <location filename="../../mainwindow.ui" line="368"/>
<location filename="../../mainwindow.ui" line="362"/> <source>toolBar</source>
<source>Menu</source> <translation>Barre d&apos;outils</translation>
<translation>Menu</translation>
</message> </message>
<message> <message>
<location filename="../../mainwindow.ui" line="351"/> <location filename="../../mainwindow.ui" line="440"/>
<source>help</source> <source>Download</source>
<translation>Aide</translation> <translation>Télécharger</translation>
</message> </message>
<message> <message>
<location filename="../../mainwindow.ui" line="367"/> <location filename="../../mainwindow.ui" line="443"/>
<location filename="../../mainwindow.ui" line="370"/> <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> <source>Change save folder</source>
<translation>Changer le dossier de destination</translation> <translation>Changer le dossier de destination</translation>
</message> </message>
<message> <message>
<source>Default save folder</source> <location filename="../../mainwindow.ui" line="417"/>
<translation type="vanished">Dossier d&apos;enregistrement</translation>
</message>
<message>
<location filename="../../mainwindow.ui" line="375"/>
<source>Bandwidth limit</source>
<translation>Limite de bande passante</translation>
</message>
<message>
<location filename="../../mainwindow.ui" line="380"/>
<source>About</source> <source>About</source>
<translation>À propos</translation> <translation>À propos</translation>
</message> </message>
<message> <message>
<location filename="../../mainwindow.ui" line="385"/> <location filename="../../mainwindow.ui" line="426"/>
<source>About Qt</source> <source>About Qt</source>
<translation>À propos de Qt</translation> <translation>À propos de Qt</translation>
</message> </message>
<message> <message>
<location filename="../../mainwindow.ui" line="390"/> <location filename="../../mainwindow.ui" line="435"/>
<source>Settings</source> <source>Settings</source>
<translation>Paramètres</translation> <translation>Paramètres</translation>
</message> </message>
<message> <message>
<source>debug</source> <location filename="../../mainwindow.cpp" line="28"/>
<translation type="vanished">debug</translation>
</message>
<message>
<location filename="../../mainwindow.cpp" line="21"/>
<source>Byte</source> <source>Byte</source>
<translation>Octet</translation> <translation>Octet</translation>
</message> </message>
<message> <message>
<location filename="../../mainwindow.cpp" line="21"/> <location filename="../../mainwindow.cpp" line="28"/>
<source>KB</source> <source>KB</source>
<translation>Ko</translation> <translation>Ko</translation>
</message> </message>
<message> <message>
<location filename="../../mainwindow.cpp" line="21"/> <location filename="../../mainwindow.cpp" line="28"/>
<source>MB</source> <source>MB</source>
<translation>Mo</translation> <translation>Mo</translation>
</message> </message>
<message> <message>
<location filename="../../mainwindow.cpp" line="21"/> <location filename="../../mainwindow.cpp" line="28"/>
<source>GB</source> <source>GB</source>
<translation>Go</translation> <translation>Go</translation>
</message> </message>
<message> <message>
<location filename="../../mainwindow.cpp" line="21"/> <location filename="../../mainwindow.cpp" line="28"/>
<source>TB</source> <source>TB</source>
<translation>To</translation> <translation>To</translation>
</message> </message>
<message> <message>
<location filename="../../mainwindow.cpp" line="21"/> <location filename="../../mainwindow.cpp" line="28"/>
<location filename="../../mainwindow.cpp" line="517"/> <location filename="../../mainwindow.cpp" line="698"/>
<source>PB</source> <source>PB</source>
<translation>Po</translation> <translation>Po</translation>
</message> </message>
<message> <message>
<location filename="../../mainwindow.cpp" line="35"/> <location filename="../../mainwindow.cpp" line="31"/>
<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="42"/>
<source>Path</source> <source>Path</source>
<translation>Chemin</translation> <translation>Chemin</translation>
</message> </message>
<message> <message>
<location filename="../../mainwindow.cpp" line="35"/> <location filename="../../mainwindow.cpp" line="42"/>
<source>Size</source> <source>Size</source>
<translation>Taille</translation> <translation>Taille</translation>
</message> </message>
<message> <message>
<location filename="../../mainwindow.cpp" line="68"/> <location filename="../../mainwindow.cpp" line="42"/>
<source>Exiting will stop downloading, and will clear the download queue. <source>Type</source>
Do you want to exit ?</source> <translation>Type</translation>
<translation>Soritr stoppera le téléchargement et effacera la file des téléchargements.
Voulez-vous vraiment sortir du programme ?</translation>
</message> </message>
<message> <message>
<location filename="../../mainwindow.cpp" line="297"/> <location filename="../../mainwindow.cpp" line="361"/>
<source>server does not exists</source> <source>server does not exists</source>
<translation>Le serveur n&apos;existe pas</translation> <translation>Le serveur n&apos;existe pas</translation>
</message> </message>
<message> <message>
<location filename="../../mainwindow.cpp" line="479"/> <location filename="../../mainwindow.cpp" line="388"/>
<location filename="../../mainwindow.cpp" line="408"/>
<source>Dir</source>
<translation>Dir</translation>
</message>
<message>
<location filename="../../mainwindow.cpp" line="391"/>
<location filename="../../mainwindow.cpp" line="456"/>
<source>File</source>
<translation></translation>
</message>
<message>
<location filename="../../mainwindow.cpp" line="634"/>
<source>Version</source>
<translation>Version</translation>
</message>
<message>
<location filename="../../mainwindow.cpp" line="635"/>
<source>Licence</source> <source>Licence</source>
<translation>License</translation> <translation>License</translation>
</message> </message>
<message> <message>
<location filename="../../mainwindow.cpp" line="480"/> <location filename="../../mainwindow.cpp" line="636"/>
<source>Author</source> <source>Author</source>
<translation>Auteur</translation> <translation>Auteur</translation>
</message> </message>
<message> <message>
<location filename="../../mainwindow.cpp" line="481"/> <location filename="../../mainwindow.cpp" line="637"/>
<source>EMail</source> <source>EMail</source>
<translation>Courriel</translation> <translation>Courriel</translation>
</message> </message>
<message> <message>
<location filename="../../mainwindow.cpp" line="482"/> <location filename="../../mainwindow.cpp" line="638"/>
<source>Source code</source> <source>Source code</source>
<translation>Code source</translation> <translation>Code source</translation>
</message> </message>
<message> <message>
<location filename="../../mainwindow.cpp" line="495"/> <location filename="../../mainwindow.cpp" line="663"/>
<source>Choose directory to save file</source> <source>Choose directory to save file</source>
<translation>Choisissez le dossier enregistrer</translation> <translation>Choisissez le dossier enregistrer</translation>
</message> </message>
<message> <message>
<location filename="../../mainwindow.cpp" line="413"/> <location filename="../../mainwindow.cpp" line="563"/>
<source>Do you want to stop downloading and delete this file from download queue ?</source> <source>Do you want to stop downloading and delete this file from download queue ?</source>
<translation>Vouslez-vous arrêter le téléchargement et enlever ce fichier de la file de téléchargement ?</translation> <translation>Voulez-vous arrêter le téléchargement et enlever ce fichier de la file de téléchargement ?</translation>
</message> </message>
<message> <message>
<source>Client for rsync server</source> <location filename="../../mainwindow.cpp" line="66"/>
<translation type="vanished">Client pour serveur rsync</translation> <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>
<message> <message>
<location filename="../../mainwindow.cpp" line="425"/> <location filename="../../mainwindow.cpp" line="68"/>
<source>Remove</source>
<translation>Supprimer</translation>
</message>
<message>
<location filename="../../mainwindow.cpp" line="107"/>
<source>Exiting will stop downloading, and will clear the download queue.
You can save the list of downloads
Do you want to exit ?</source>
<translation>Si vous sortez, les téléchargements seront arrêter, mais vous pouvez enregistrer la liste pour la prochaine fois</translation>
</message>
<message>
<location filename="../../mainwindow.cpp" line="575"/>
<source>Do you want to delete this file from download queue ?</source> <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> <translation>Voulez-vous enlever ce fichier de la file de téléchargement ?</translation>
</message> </message>

View File

@ -2,12 +2,14 @@
#include <QTranslator> #include <QTranslator>
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
QApplication a(argc, argv); QApplication a(argc, argv);
QTranslator myappTranslator; QTranslator myappTranslator;
QCoreApplication::setOrganizationName("RsyncUI");
QCoreApplication::setApplicationName("RsyncUI");
// Initialization of localization
QLocale localeName = QLocale::system(); QLocale localeName = QLocale::system();
QString localeFile = "/usr/share/locale/" + localeName.name() + "/LC_MESSAGES/RsyncUI_" + localeName.name() + ".qm"; QString localeFile = "/usr/share/locale/" + localeName.name() + "/LC_MESSAGES/RsyncUI_" + localeName.name() + ".qm";
if (myappTranslator.load(localeFile)) if (myappTranslator.load(localeFile))

View File

@ -1,27 +1,34 @@
#include "mainwindow.h" #include "mainwindow.h"
#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;
MainWindow::MainWindow(QWidget *parent) MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent) : QMainWindow(parent)
, ui(new Ui::MainWindow) , ui(new Ui::MainWindow)
{ {
QAbstractButton * reply;
QMessageBox msgBox;
ui->setupUi(this); ui->setupUi(this);
QCoreApplication::setOrganizationName("RsyncUI"); QCoreApplication::setOrganizationName("RsyncUI");
QCoreApplication::setApplicationName("RsyncUI"); QCoreApplication::setApplicationName("RsyncUI");
// context menu for treewidget
ui->treeWidget->addAction(ui->actionDownload);
// init shortcut // init shortcut
loadSettings(); loadSettings();
config.setupUi(&Configuration); config.setupUi(&Configuration);
config.UnitCombobox->addItems({tr("Byte"), tr("KB"), tr("MB"), tr("GB"), tr("TB"), tr("PB")}); 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(this->about.description.toStdString().c_str()); 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(&downloadO, &downloadFile::progressSignal, ui->progressBar, &QProgressBar::setValue);
@ -32,7 +39,8 @@ MainWindow::MainWindow(QWidget *parent)
// 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("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());
@ -43,9 +51,37 @@ MainWindow::MainWindow(QWidget *parent)
ui->khistorycombobox->clear(); ui->khistorycombobox->clear();
} }
// setting arrowcursor for treeWidget, listWidget and listDownload
ui->treeWidget->setCursor(Qt::ArrowCursor);
ui->listWidget->setCursor(Qt::ArrowCursor);
ui->listDownload->setCursor(Qt::ArrowCursor);
// Hiding progress bar
ui->progressBar->hide(); ui->progressBar->hide();
if (this->settings.value("Downloads/rows").toInt() != 0)
{
this->settings.endArray();
msgBox.setWindowTitle("RsyncUI");
msgBox.setInformativeText(tr("A list of interrupted downloads exists, do you want to continue downloading ? or you can delete the list" ));
QPushButton *remove = msgBox.addButton(tr("Remove"), QMessageBox::ActionRole);
QPushButton *yes = msgBox.addButton(QMessageBox::Yes);
msgBox.addButton(QMessageBox::No);
msgBox.setDefaultButton(QMessageBox::No);
msgBox.exec();
reply = msgBox.clickedButton();
if(reply == yes)
{
loadDownloadList();
}else if (reply == remove)
{
this->settings.remove("Downloads");
}
}
populateList(); populateList();
} }
@ -54,51 +90,66 @@ MainWindow::~MainWindow()
delete ui; delete ui;
} }
// Closing window has been clicked
void MainWindow::closeEvent (QCloseEvent *event) void MainWindow::closeEvent (QCloseEvent *event)
{ {
QMessageBox::StandardButton reply; QMessageBox::StandardButton reply;
// saving settings
saveSettings(); saveSettings();
if (ui->listDownload->count() != 0) if (ui->listDownload->count() != 0) // some downloads waiting
{ {
// Asking for stopping or continuing
reply = QMessageBox::question( reply = QMessageBox::question(
this, this,
"RsyncUI", "RsyncUI",
tr("Exiting will stop downloading, and will clear the download queue.\n Do 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::No, QMessageBox::Yes|QMessageBox::Save|QMessageBox::No,
QMessageBox::No); QMessageBox::No);
if (reply == QMessageBox::No) if (reply == QMessageBox::No)
{ {
// continuing
event->ignore(); event->ignore();
return; return;
}else if(reply == QMessageBox::Yes)
{
// emission of signal to downloading thread and stopping
emit (stopDownloading(this->pid));
waitpid(this->pid, NULL, WUNTRACED);
}else }else
{ {
emit (stopDownloading(this->downloading.pid)); saveDownloadList();
waitpid(this->downloading.pid, NULL, WUNTRACED);
} }
} }
event->accept(); event->accept();
} }
void MainWindow::populateTree() // Populate treeview with list of files
void MainWindow::populateTree(QTreeWidgetItem * parent)
{ {
stringstream ss; stringstream ss;
vector<string> path; vector<string> path;
// 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.empty() and this->connexion.port > 0 and this->connexion.port < 65536)
{ {
// setting cursor to "Wait"
QGuiApplication::setOverrideCursor(Qt::WaitCursor); QGuiApplication::setOverrideCursor(Qt::WaitCursor);
if (validateServer(this->connexion.server)) if (validateServer(this->connexion.server))
{ {
// server is validated
path = explode(ui->listWidget->currentItem()->text().toStdString(), '\n', 2); path = explode(ui->listWidget->currentItem()->text().toStdString(), '\n', 2);
scanDir(this->connexion.server, this->connexion.port, NULL, path[0].append("/") ); scanDir(this->connexion.server, this->connexion.port, parent, path[0].append("/") );
} }
QGuiApplication::restoreOverrideCursor(); //setOverrideCursor(Qt::ArrowCursor); // Restoring cursor
QGuiApplication::restoreOverrideCursor();
} }
} }
// Populate Listview with list of services
void MainWindow::populateList() void MainWindow::populateList()
{ {
stringstream ss; stringstream ss;
@ -110,45 +161,50 @@ void MainWindow::populateList()
port = ui->portEdit->text().toUInt(); port = ui->portEdit->text().toUInt();
if ((server.toStdString() != this->connexion.server) or (port != this->connexion.port)) if ((server.toStdString() != this->connexion.server) or (port != this->connexion.port))
{ {
// clearing listwidget
ui->listWidget->clear(); ui->listWidget->clear();
this->connexion.server.assign(server.toStdString()); this->connexion.server.assign(server.toStdString());
this->connexion.port = port; this->connexion.port = port;
QGuiApplication::setOverrideCursor(Qt::WaitCursor);
// 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))
{ {
// server is in history => setting port value
port = this->settings.value(server).toUInt(); port = this->settings.value(server).toUInt();
ui->portEdit->setText(QString::number(port)); ui->portEdit->setText(QString::number(port));
this->connexion.port = port; this->connexion.port = port;
} listServices();
}else
{
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.toStdString()))
{
//this->settings.beginGroup("connexion/server");
if (!this->settings.contains(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();
// storing in history of combobox // storing in history of combobox
ui->khistorycombobox->addToHistory(server); ui->khistorycombobox->addToHistory(server);
}
// "waiting" cursor // "waiting" cursor
// load and display rsync services of the rsync server // load and display rsync services of the rsync server
QGuiApplication::setOverrideCursor(Qt::WaitCursor);
listServices(); listServices();
QGuiApplication::restoreOverrideCursor(); //setOverrideCursor(Qt::ArrowCursor);
} }
} }
}
this->settings.endGroup(); this->settings.endGroup();
QGuiApplication::restoreOverrideCursor(); //setOverrideCursor(Qt::ArrowCursor); QGuiApplication::restoreOverrideCursor(); //setOverrideCursor(Qt::ArrowCursor);
} }
} }
//list services of the rsync server
void MainWindow::listServices() void MainWindow::listServices()
{ {
char cmd[4096]; char cmd[4096];
@ -169,6 +225,7 @@ void MainWindow::listServices()
} }
} }
// connect to rsync server to get list of files
void MainWindow::scanDir(string server, int portN, QTreeWidgetItem *parent, string path) void MainWindow::scanDir(string server, int portN, QTreeWidgetItem *parent, string path)
{ {
char cmd[4096]; char cmd[4096];
@ -176,37 +233,41 @@ void MainWindow::scanDir(string server, int portN, QTreeWidgetItem *parent, stri
string errorRsync; string errorRsync;
vector<string> v; vector<string> v;
QTreeWidgetItem * item; QTreeWidgetItem * item;
char npath[4096]; bool isDir = false;
sprintf(cmd, "rsync --contimeout=10 -P \"%s::%s\" --port %d ", server.c_str(), path.c_str(), portN ); sprintf(cmd, "rsync --contimeout=10 -P \"%s::%s\" --port %d ", server.c_str(), path.c_str(), portN );
redi::ipstream in(cmd, redi::pstreams::pstdout | redi::pstreams::pstderr); redi::ipstream in(cmd, redi::pstreams::pstdout | redi::pstreams::pstderr);
while (getline(in.out(), line)) while (getline(in.out(), line))
{ {
v = explode(line, ' ', 5); v = explode(line, ' ', 5);
if (v.size() == 5) if (v.size() == 5)
{ {
if (v[4].at(0) != '.' and (v[0].at(0) == '-' or v[0].at(0) == 'd')) if (v[4].at(0) != '.' and (v[0].at(0) == '-' or v[0].at(0) == 'd'))
{ {
if (parent != NULL)
{
item = addTreeChild(parent,QString::fromStdString(v[4]), QString::fromStdString(v[1]));
}else
{
item = addTreeRoot(QString::fromStdString(v[4]), QString::fromStdString(v[1]));
}
if (v[0].at(0) == 'd') if (v[0].at(0) == 'd')
{ {
sprintf(npath, "%s%s/", path.c_str(), v[4].c_str()); isDir = true;
scanDir(server, portN, item, npath); }else
} {
isDir = false;
}
if (parent != NULL)
{
item = addTreeChild(parent,QString::fromStdString(v[4]), QString::fromStdString(v[1]), isDir);
}else
{
item = addTreeRoot(QString::fromStdString(v[4]), QString::fromStdString(v[1]), isDir);
}
} }
} }
} }
// if reading stdout stopped at EOF then reset the state: // if reading stdout stopped at EOF then reset the state:
if (in.eof() && in.fail()) if (in.eof() && in.fail())
in.clear(); in.clear();
// read child's stderr // read child's stderr
while (getline(in.err(), line)) while (getline(in.err(), line))
{ {
@ -214,6 +275,7 @@ void MainWindow::scanDir(string server, int portN, QTreeWidgetItem *parent, stri
errorRsync.append(line); errorRsync.append(line);
errorRsync.append("\n"); errorRsync.append("\n");
} }
if ( !errorRsync.empty()) if ( !errorRsync.empty())
{ {
QMessageBox::warning( QMessageBox::warning(
@ -224,6 +286,7 @@ void MainWindow::scanDir(string server, int portN, QTreeWidgetItem *parent, stri
} }
// Verify if server address is IP address
bool MainWindow::isIpAddress(string server) bool MainWindow::isIpAddress(string server)
{ {
vector<string> r; vector<string> r;
@ -249,6 +312,7 @@ bool MainWindow::isIpAddress(string server)
} }
} }
// validate address server
bool MainWindow::validateServer(string server) bool MainWindow::validateServer(string server)
{ {
char cmd[512]; char cmd[512];
@ -300,79 +364,136 @@ bool MainWindow::validateServer(string server)
return flag; return flag;
} }
void MainWindow::displayTree() // slot activated when combobox is changed
{
populateTree();
}
void MainWindow::on_khistorycombobox_currentIndexChanged(int i) void MainWindow::on_khistorycombobox_currentIndexChanged(int i)
{ {
on_connectButton_clicked(); on_connectButton_clicked();
} }
// slot activated when button connection is clicked
void MainWindow::on_connectButton_clicked() void MainWindow::on_connectButton_clicked()
{ {
populateList(); populateList();
} }
QTreeWidgetItem * MainWindow::addTreeRoot(QString name, QString fileSize) // add a dir in treeview
QTreeWidgetItem * MainWindow::addTreeRoot(QString name, QString fileSize, bool isDir)
{ {
// QTreeWidgetItem(QTreeWidget * parent, int type = Type) // QTreeWidgetItem(QTreeWidget * parent, int type = Type)
QTreeWidgetItem *treeItem = new QTreeWidgetItem(ui->treeWidget); QTreeWidgetItem *treeItem = new QTreeWidgetItem(ui->treeWidget);
// QTreeWidgetItem::setText(int column, const QString & text) // QTreeWidgetItem::setText(int column, const QString & text)
if (isDir == true)
{
treeItem->setText(1, tr("Dir"));
}else
{
treeItem->setText(1,tr("File"));
}
treeItem->setText(0, name); treeItem->setText(0, name);
treeItem->setText(1, fileSize); treeItem->setText(2, fileSize);
return treeItem; return treeItem;
} }
QTreeWidgetItem * MainWindow::addTreeChild(QTreeWidgetItem *parent, QString name, QString fileSize) // add a file in treeview
QTreeWidgetItem * MainWindow::addTreeChild(QTreeWidgetItem *parent, QString name, QString fileSize, bool isDir)
{ {
// QTreeWidgetItem(QTreeWidget * parent, int type = Type) // QTreeWidgetItem(QTreeWidget * parent, int type = Type)
QTreeWidgetItem *treeItem = new QTreeWidgetItem(); QTreeWidgetItem *treeItem = new QTreeWidgetItem();
// QTreeWidgetItem::setText(int column, const QString & text) // QTreeWidgetItem::setText(int column, const QString & text)
if (isDir == true)
{
treeItem->setText(1, tr("Dir"));
}else
{
treeItem->setText(1,("File"));
}
treeItem->setText(0, name); treeItem->setText(0, name);
treeItem->setText(1, fileSize); treeItem->setText(2, fileSize);
// QTreeWidgetItem::addChild(QTreeWidgetItem * child) // QTreeWidgetItem::addChild(QTreeWidgetItem * child)
parent->addChild(treeItem); parent->addChild(treeItem);
return treeItem; return treeItem;
} }
// Slot acivated when a service in the list is clicked
void MainWindow::on_listWidget_clicked() void MainWindow::on_listWidget_clicked()
{ {
vector<string> v; vector<string> v;
QString str;
v = explode(ui->listWidget->currentItem()->text().toStdString(), '\n', 2); v = explode(ui->listWidget->currentItem()->text().toStdString(), '\n', 2);
this->downloading.service = v[0]; this->connexion.service = v[0];
populateTree(); str = QString::fromStdString("Folder/" + this->connexion.server + "/" + this->connexion.service);
if (this->settings.contains(str))
{
this->downloading.savePath = this->settings.value(str).toString().toStdString();
}
populateTree(NULL);
} }
void MainWindow::on_treeWidget_itemClicked(QTreeWidgetItem *item) //Slot activated when a file is clicked in the treeview
void MainWindow::on_treeWidget_itemClicked(QTreeWidgetItem *item, bool downloadDir)
{ {
QFuture<void> future; QFuture<void> future;
QFileDialog dialog; QFileDialog dialog;
QTreeWidgetItem * itemR;
string path;
QString str;
item = ui->treeWidget->currentItem(); //item = ui->treeWidget->currentItem();
this->downloading.path = item->text(0).toStdString(); itemR = item;
while(item->parent() != NULL)
path = item->text(0).toStdString();
while(itemR->parent() != NULL)
{ {
item = item->parent(); itemR = itemR->parent();
this->downloading.path = item->text(0).toStdString() + "/" + this->downloading.path; path = itemR->text(0).toStdString() + "/" + path;
}; };
if (this->downloading.savePath.empty()) if (item->text(1) == tr("File") or downloadDir == true)
{ {
on_DefaultSaveFolder_triggered(); // Item is a file
} this->downloading.path = path;
if (!this->downloading.savePath.empty() && this->downloading.pid == 0) this->downloading.server = this->connexion.server;
this->downloading.service = this->connexion.service;
// exists saving path in settings ?
str = QString::fromStdString("Folder/" + this->connexion.server + "/" + this->downloading.service);
if(!this->settings.contains(str))
{ {
startDownloading(); // saving path do not exists, asking for it
if(!on_DefaultSaveFolder_triggered())
{
cout << "no directory selectioned, ignoring download request";
return;
} }
ui->listDownload->addItem(QString::fromStdString(this->downloading.path));
} }
// is there a downloading process ?
if (this->pid == 0)
{
// no downloading process launching it
startDownloading();
// wit 1 second to process start
//sleep(1);
}
// Adding download in download list
str = QString::fromStdString(this->downloading.path + " => " + this->connexion.server + "/" + this->downloading.service);
ui->listDownload->addItem(str);
}else
{
//Item is a Directory
scanDir(this->connexion.server, this->connexion.port, item, this->connexion.service + "/" + path +"/");
item->setExpanded(true);
}
}
// Launch the thread which download the file
void MainWindow::startDownloading() void MainWindow::startDownloading()
{ {
ui->progressBar->setValue(0); ui->progressBar->setValue(0);
@ -382,23 +503,52 @@ void MainWindow::startDownloading()
} }
// Slot stopping download
void MainWindow::stoppingDownload() void MainWindow::stoppingDownload()
{ {
emit (stopDownloading(this->downloading.pid)); emit (stopDownloading(this->pid));
} }
// when download is finished, launch download of next file in queue
void MainWindow::downloadFinished() void MainWindow::downloadFinished()
{ {
string path;
int pos;
string str;
this->pid = 0;
ui->progressBar->hide(); ui->progressBar->hide();
delete ui->listDownload->takeItem(0); delete ui->listDownload->takeItem(0);
this->downloading.pid = 0; this->downloading.clear();
if (ui->listDownload->count() != 0) if (ui->listDownload->count() != 0)
{ {
this->downloading.path = ui->listDownload->item(0)->text().toStdString(); path = ui->listDownload->item(0)->text().toStdString();
pos = path.rfind("/");
this->downloading.service = path.substr(pos+1);
path.resize(pos);
pos = path.rfind(" => ");
this->downloading.server = path.substr(pos+4);
path.resize(pos);
this->downloading.path = path;
str = "Folder/" + this->downloading.server + "/" + this->downloading.service;
if (this->settings.contains(QString::fromStdString(str)))
{
this->downloading.savePath = this->settings.value(QString::fromStdString(str)).toString().toStdString();
}else
{
if(!on_DefaultSaveFolder_triggered())
{
cout << "Error no save path so deleting download";
downloadFinished();
return;
}
}
startDownloading(); startDownloading();
} }
} }
// Slot activated when a line is clicked in queue list
void MainWindow::on_listDownload_itemClicked(QListWidgetItem *item) void MainWindow::on_listDownload_itemClicked(QListWidgetItem *item)
{ {
QFileDialog dialog; QFileDialog dialog;
@ -415,7 +565,7 @@ void MainWindow::on_listDownload_itemClicked(QListWidgetItem *item)
QMessageBox::No); QMessageBox::No);
if (reply == QMessageBox::Yes) if (reply == QMessageBox::Yes)
{ {
emit (stopDownloading(this->downloading.pid)); emit (stopDownloading(this->pid));
} }
}else }else
{ {
@ -433,14 +583,16 @@ void MainWindow::on_listDownload_itemClicked(QListWidgetItem *item)
} }
} }
// load settings
void MainWindow::loadSettings() void MainWindow::loadSettings()
{ {
// restoring geometry and state of wondow and widgets // restoring geometry and state of window and widgets
this->restoreGeometry(settings.value("window/geometry").toByteArray()); this->restoreGeometry(this->settings.value("window/geometry").toByteArray());
this->restoreState(settings.value("window/state").toByteArray()); this->restoreState(this->settings.value("window/state").toByteArray());
ui->treeWidget->header()->restoreState(settings.value("treeView/state").toByteArray()); ui->treeWidget->header()->restoreState(this->settings.value("treeWidget/state").toByteArray());
ui->splitter->restoreState(settings.value("splitter/state").toByteArray()); ui->splitter->restoreState(this->settings.value("splitter/state").toByteArray());
ui->splitter_2->restoreState(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());
// loading connexion settings // loading connexion settings
// loading servers history // loading servers history
@ -460,22 +612,26 @@ void MainWindow::loadSettings()
this->connexion.bandwidthLimitUnit = this->settings.value("bandwidthlimitunit").toString().toStdString(); this->connexion.bandwidthLimitUnit = this->settings.value("bandwidthlimitunit").toString().toStdString();
} }
// save settings
void MainWindow::saveSettings() void MainWindow::saveSettings()
{ {
this->settings.setValue("window/geometry", saveGeometry()); this->settings.setValue("window/geometry", saveGeometry());
this->settings.setValue("window/state", saveState()); this->settings.setValue("window/state", saveState());
this->settings.setValue("treeView/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", QString::fromStdString(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.sync(); this->settings.sync();
} }
// About
void MainWindow::on_actionAbout_triggered() void MainWindow::on_actionAbout_triggered()
{ {
//TODO => initialisation
QString text = this->about.description + "\n\n" + QString text = this->about.description + "\n\n" +
tr("Version") + ": " + this->about.version + "\n" +
tr("Licence") + ": " + this->about.licence + "\n" + tr("Licence") + ": " + this->about.licence + "\n" +
tr("Author") + ": " + this->about.author + "\n" + tr("Author") + ": " + this->about.author + "\n" +
tr("EMail") + ": " + this->about.email + "\n" + tr("EMail") + ": " + this->about.email + "\n" +
@ -483,28 +639,53 @@ void MainWindow::on_actionAbout_triggered()
QMessageBox::about(this, this->about.title, text); QMessageBox::about(this, this->about.title, text);
} }
// About QT
void MainWindow::on_actionAbout_Qt_triggered() void MainWindow::on_actionAbout_Qt_triggered()
{ {
QMessageBox::aboutQt(this); QMessageBox::aboutQt(this);
} }
void MainWindow::on_DefaultSaveFolder_triggered() // Activated when menu "change folder" is clicked
bool MainWindow::on_DefaultSaveFolder_triggered()
{ {
QFileDialog dialog; QFileDialog dialog;
string folder;
string path;
this->downloading.savePath = dialog.getExistingDirectory(this, tr("Choose directory to save file"), this->downloading.dirPath, QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks).toStdString(); if (this->connexion.service.empty())
// this->downloading.dirPath = this->downloading.savePath.c_str(); {
this->settings.setValue("Folder/", this->downloading.savePath.c_str()); QMessageBox::warning(
NULL,
"RsyncUI",
"Since the save path is linked to service, you need to select a service before you can select a folder");
return false;
}
path = dialog.getExistingDirectory(this, tr("Choose directory to save file"), QString::fromStdString(getpwuid(getuid())->pw_dir), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks).toStdString();
if (!path.empty())
{
this->downloading.savePath = path;
if (!this->connexion.service.empty() and !this->connexion.server.empty())
{
folder = "Folder/" + this->connexion.server + "/" + this->connexion.service;
this->settings.setValue(folder.c_str(), this->downloading.savePath.c_str());
this->settings.sync(); this->settings.sync();
} }
}else
{
return false;
}
return true;
}
// Activated when menu "settings" is clicked
void MainWindow::on_action_Settings_triggered() void MainWindow::on_action_Settings_triggered()
{ {
config.UnitCombobox->setCurrentText(QString::fromStdString(this->connexion.bandwidthLimitUnit)); config.UnitCombobox->setCurrentIndex(bwUnixIndex[this->connexion.bandwidthLimitUnit[0]]);
config.spinBox->setValue(this->connexion.bandwidthLimit); config.spinBox->setValue(this->connexion.bandwidthLimit);
Configuration.show(); Configuration.show();
} }
// Acivated when "Ok" is clicked in Configuration window
void MainWindow::on_buttonBox_accepted() void MainWindow::on_buttonBox_accepted()
{ {
QString unit; QString unit;
@ -518,9 +699,76 @@ void MainWindow::on_buttonBox_accepted()
}else }else
{ {
this->connexion.bandwidthLimit = config.spinBox->value(); this->connexion.bandwidthLimit = config.spinBox->value();
this->connexion.bandwidthLimitUnit = config.UnitCombobox->currentText().toStdString(); this->connexion.bandwidthLimitUnit = config.UnitCombobox->currentText().toStdString()[0];
} }
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.c_str());
this->settings.sync(); this->settings.sync();
Configuration.hide();
}
// Saving download list
void MainWindow::saveDownloadList()
{
int nRows;
nRows = ui->listDownload->count();
//this->settings.beginWriteArray("Downloads/");
this->settings.beginGroup("Downloads");
this->settings.setValue("rows", nRows);
for (int i = 0; i < nRows; i++)
{
this->settings.setValue(QString::number(i), ui->listDownload->item(i)->text());
}
this->settings.endGroup();
this->settings.sync();
}
void MainWindow::loadDownloadList()
{
string path;
string str;
int pos;
this->settings.beginGroup("Downloads");
int size = this->settings.value("rows").toInt();
for (int i = 0; i < size; ++i)
{
ui->listDownload->addItem(this->settings.value(QString::number(i)).toString());
}
this->settings.endGroup();
this->settings.remove("Downloads");
this->settings.sync();
path = ui->listDownload->item(0)->text().toStdString();
pos = path.rfind("/");
this->downloading.service = path.substr(pos+1);
path.resize(pos);
pos = path.rfind(" => ");
this->downloading.server = path.substr(pos+4);
path.resize(pos);
this->downloading.path = path;
str = "Folder/" + this->downloading.server + "/" + this->downloading.service;
if (this->settings.contains(QString::fromStdString(str)))
{
this->downloading.savePath = this->settings.value(QString::fromStdString(str)).toString().toStdString();
}
startDownloading();
}
void Downloading::clear()
{
this->path.clear();
this->server.clear();
this->savePath.clear();
this->service.clear();
}
void MainWindow::on_actionDownload_triggered()
{
// action made in qt-designer and added in init function.
QTreeWidgetItem *item;
item = ui->treeWidget->currentItem();
on_treeWidget_itemClicked(item, true);
} }

View File

@ -1,6 +1,7 @@
#ifndef MAINWINDOW_H #ifndef MAINWINDOW_H
#define MAINWINDOW_H #define MAINWINDOW_H
#define QT_USE_FAST_CONCATENATION
#define QT_USE_FAST_OPERATOR_PLUS
#include "ui_mainwindow.h" #include "ui_mainwindow.h"
#include "ui_configuration.h" #include "ui_configuration.h"
#include "downloadfile.h" #include "downloadfile.h"
@ -31,6 +32,10 @@
#include <QShortcut> #include <QShortcut>
#include <QCloseEvent> #include <QCloseEvent>
#include <unistd.h> #include <unistd.h>
#include <magic.h>
#include <QComboBox>
#include <QStringBuilder>
#include <pwd.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; } namespace Ui { class MainWindow; }
@ -42,27 +47,30 @@ class Connexion
int bandwidthLimit = 0; int bandwidthLimit = 0;
std::string bandwidthLimitUnit = ""; std::string bandwidthLimitUnit = "";
std::string server; std::string server;
std::string service;
int port = 873; int port = 873;
}; };
class Downloading class Downloading
{ {
public: public:
std::string server;
std::string service; std::string service;
std::string path; std::string path;
std::string defaultSavePath;
std::string savePath; std::string savePath;
QString dirPath;
int pid = 0; void clear();
}; };
class About class About
{ {
public: public:
QString title = "RsyncUI"; QString title = "RsyncUI";
QString version = "1.8.10";
QString author = "Daniel TARTAVEL-JEANNOT"; QString author = "Daniel TARTAVEL-JEANNOT";
QString licence = "GPL_V3"; QString licence = "GPL_V3";
QString description = "Client for rsync server\n\nYou click on file to enqueue it, and RyncUI Download one file a time"; QString description;
QString email = "dtux@free.fr"; QString email = "dtux@free.fr";
QString git = "https://git.labolyon.fr/dtux/RsyncUI/issues"; QString git = "https://git.labolyon.fr/dtux/RsyncUI/issues";
}; };
@ -76,20 +84,7 @@ class MainWindow : public QMainWindow
MainWindow(QWidget *parent = nullptr); MainWindow(QWidget *parent = nullptr);
~MainWindow(); ~MainWindow();
QProgressDialog *progress; QProgressDialog *progress;
void displayTree(); int pid = 0;
void populateTree();
void populateList();
void listServices();
bool validateServer(std::string server);
bool isIpAddress(std::string server);
QTreeWidgetItem * addTreeRoot(QString name, QString description);
QTreeWidgetItem * addTreeChild(QTreeWidgetItem *parent, QString name, QString size);
void scanDir(std::string server, int portN, QTreeWidgetItem *parent = NULL, std::string path = "" );
void startDownloading();
void loadSettings();
void saveSettings();
void closeEvent (QCloseEvent *event);
Connexion connexion; Connexion connexion;
Downloading downloading; Downloading downloading;
downloadFile downloadO; downloadFile downloadO;
@ -98,12 +93,35 @@ class MainWindow : public QMainWindow
QDialog Configuration; QDialog Configuration;
Ui::Configuration config; Ui::Configuration config;
std::vector <QString> serversList; std::vector <QString> serversList;
map<char, int> bwUnixIndex {
{'B', 0},
{'K', 1},
{'M', 2},
{'G', 3},
{'P', 4}
};
void displayTree();
void populateTree(QTreeWidgetItem * parent);
void populateList();
void listServices();
bool validateServer(std::string server);
bool isIpAddress(std::string server);
QTreeWidgetItem * addTreeRoot(QString name, QString description, 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 startDownloading();
void loadSettings();
void saveSettings();
void closeEvent (QCloseEvent *event);
void saveDownloadList();
void loadDownloadList();
private slots: private slots:
void on_listWidget_clicked(); void on_listWidget_clicked();
void on_treeWidget_itemClicked(QTreeWidgetItem *item); void on_treeWidget_itemClicked(QTreeWidgetItem *item, bool downloadDir = false);
void downloadFinished(); void downloadFinished();
@ -117,19 +135,19 @@ class MainWindow : public QMainWindow
void on_khistorycombobox_currentIndexChanged(int); void on_khistorycombobox_currentIndexChanged(int);
void on_DefaultSaveFolder_triggered(); bool on_DefaultSaveFolder_triggered();
void on_connectButton_clicked(); void on_connectButton_clicked();
void on_action_Settings_triggered(); void on_action_Settings_triggered();
void on_actionDownload_triggered();
public slots: public slots:
void on_buttonBox_accepted(); void on_buttonBox_accepted();
signals: signals:
void stopDownloading(int); void stopDownloading(int);
// void accepted();
}; };
#endif // MAINWINDOW_H #endif // MAINWINDOW_H

View File

@ -20,6 +20,9 @@
<property name="windowTitle"> <property name="windowTitle">
<string>MainWindow</string> <string>MainWindow</string>
</property> </property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextUnderIcon</enum>
</property>
<property name="documentMode"> <property name="documentMode">
<bool>false</bool> <bool>false</bool>
</property> </property>
@ -57,7 +60,7 @@
<cursorShape>IBeamCursor</cursorShape> <cursorShape>IBeamCursor</cursorShape>
</property> </property>
<property name="focusPolicy"> <property name="focusPolicy">
<enum>Qt::TabFocus</enum> <enum>Qt::WheelFocus</enum>
</property> </property>
<property name="acceptDrops"> <property name="acceptDrops">
<bool>true</bool> <bool>true</bool>
@ -139,6 +142,9 @@
<height>16777215</height> <height>16777215</height>
</size> </size>
</property> </property>
<property name="focusPolicy">
<enum>Qt::WheelFocus</enum>
</property>
<property name="toolTip"> <property name="toolTip">
<string>Enter rsync port on server</string> <string>Enter rsync port on server</string>
</property> </property>
@ -173,6 +179,9 @@
</item> </item>
<item> <item>
<widget class="QPushButton" name="connectButton"> <widget class="QPushButton" name="connectButton">
<property name="focusPolicy">
<enum>Qt::WheelFocus</enum>
</property>
<property name="toolTip"> <property name="toolTip">
<string extracomment="Connect to server">Press button to connect to rsync server</string> <string extracomment="Connect to server">Press button to connect to rsync server</string>
</property> </property>
@ -205,6 +214,9 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="focusPolicy">
<enum>Qt::WheelFocus</enum>
</property>
<property name="toolTip"> <property name="toolTip">
<string>Click to view the list of files of this folder</string> <string>Click to view the list of files of this folder</string>
</property> </property>
@ -214,6 +226,9 @@
<property name="editTriggers"> <property name="editTriggers">
<set>QAbstractItemView::SelectedClicked</set> <set>QAbstractItemView::SelectedClicked</set>
</property> </property>
<property name="tabKeyNavigation">
<bool>true</bool>
</property>
<property name="resizeMode"> <property name="resizeMode">
<enum>QListView::Adjust</enum> <enum>QListView::Adjust</enum>
</property> </property>
@ -231,8 +246,11 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="focusPolicy">
<enum>Qt::WheelFocus</enum>
</property>
<property name="contextMenuPolicy"> <property name="contextMenuPolicy">
<enum>Qt::NoContextMenu</enum> <enum>Qt::ActionsContextMenu</enum>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>Click to add to download queue</string> <string>Click to add to download queue</string>
@ -241,11 +259,14 @@
<number>5000</number> <number>5000</number>
</property> </property>
<property name="whatsThis"> <property name="whatsThis">
<string extracomment="Click to add to download queue"/> <string/>
</property> </property>
<property name="editTriggers"> <property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set> <set>QAbstractItemView::NoEditTriggers</set>
</property> </property>
<property name="tabKeyNavigation">
<bool>true</bool>
</property>
<property name="showDropIndicator" stdset="0"> <property name="showDropIndicator" stdset="0">
<bool>false</bool> <bool>false</bool>
</property> </property>
@ -270,6 +291,9 @@
<property name="sortingEnabled"> <property name="sortingEnabled">
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="animated">
<bool>true</bool>
</property>
<property name="columnCount"> <property name="columnCount">
<number>1</number> <number>1</number>
</property> </property>
@ -303,9 +327,15 @@
</widget> </widget>
</widget> </widget>
<widget class="QListWidget" name="listDownload"> <widget class="QListWidget" name="listDownload">
<property name="focusPolicy">
<enum>Qt::WheelFocus</enum>
</property>
<property name="toolTip"> <property name="toolTip">
<string>Click on file to stop downloading</string> <string>Click on file to stop downloading</string>
</property> </property>
<property name="toolTipDuration">
<number>5000</number>
</property>
<property name="dragEnabled"> <property name="dragEnabled">
<bool>true</bool> <bool>true</bool>
</property> </property>
@ -330,39 +360,47 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<widget class="QMenuBar" name="menubar"> <widget class="QToolBar" name="toolBar">
<property name="geometry"> <property name="contextMenuPolicy">
<rect> <enum>Qt::NoContextMenu</enum>
<x>0</x>
<y>0</y>
<width>500</width>
<height>30</height>
</rect>
</property> </property>
<widget class="QMenu" name="menu"> <property name="windowTitle">
<property name="title"> <string>toolBar</string>
<string>Menu</string>
</property> </property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="autoFillBackground">
<bool>true</bool>
</property>
<property name="movable">
<bool>true</bool>
</property>
<property name="allowedAreas">
<set>Qt::AllToolBarAreas</set>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextUnderIcon</enum>
</property>
<property name="floatable">
<bool>true</bool>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="DefaultSaveFolder"/> <addaction name="DefaultSaveFolder"/>
<addaction name="action_Settings"/> <addaction name="action_Settings"/>
</widget>
<widget class="QMenu" name="menuhelp">
<property name="title">
<string>help</string>
</property>
<addaction name="actionAbout"/> <addaction name="actionAbout"/>
<addaction name="actionAbout_Qt"/> <addaction name="actionAbout_Qt"/>
</widget> </widget>
<addaction name="menu"/>
<addaction name="menuhelp"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<action name="actionMenu">
<property name="text">
<string>Menu</string>
</property>
</action>
<action name="DefaultSaveFolder"> <action name="DefaultSaveFolder">
<property name="icon">
<iconset theme="system-file-manager">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text"> <property name="text">
<string>Change save folder</string> <string>Change save folder</string>
</property> </property>
@ -370,26 +408,41 @@
<string>Change save folder</string> <string>Change save folder</string>
</property> </property>
</action> </action>
<action name="actionBandwidth_limit">
<property name="text">
<string>Bandwidth limit</string>
</property>
</action>
<action name="actionAbout"> <action name="actionAbout">
<property name="icon">
<iconset theme="help-about">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text"> <property name="text">
<string>About</string> <string>About</string>
</property> </property>
</action> </action>
<action name="actionAbout_Qt"> <action name="actionAbout_Qt">
<property name="icon">
<iconset theme="help-browser">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text"> <property name="text">
<string>About Qt</string> <string>About Qt</string>
</property> </property>
</action> </action>
<action name="action_Settings"> <action name="action_Settings">
<property name="icon">
<iconset theme="preferences-other">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text"> <property name="text">
<string>Settings</string> <string>Settings</string>
</property> </property>
</action> </action>
<action name="actionDownload">
<property name="text">
<string>Download</string>
</property>
<property name="toolTip">
<string>Click on menu button to download the entire folder</string>
</property>
</action>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget> <customwidget>

View File

@ -5,6 +5,10 @@ using namespace std;
#define READ 0 #define READ 0
#define WRITE 1 #define WRITE 1
//Take a string and explode it in array
// s => string to explode
// c => character separator
// n => number of results in array, the last is the rest of string to end
const vector<string> explode(const string& s, const char& c, int n = 0) const vector<string> explode(const string& s, const char& c, int n = 0)
{ {
string buff; string buff;
@ -37,7 +41,9 @@ const vector<string> explode(const string& s, const char& c, int n = 0)
return v; return v;
} }
FILE * popen2(char * const argv, string type, int & pid) // open a pipe, fork and return pid of child
// 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; pid_t child_pid;
int fd[2]; int fd[2];
@ -51,6 +57,7 @@ FILE * popen2(char * const argv, string type, int & pid)
NULL, NULL,
"RsyncUI", "RsyncUI",
message); message);
exit(-1);
}else }else
{ {
if((child_pid = fork()) == -1) if((child_pid = fork()) == -1)
@ -74,11 +81,9 @@ FILE * popen2(char * const argv, string type, int & pid)
} }
setpgid(child_pid, child_pid); //Needed so negative PIDs can kill children of /bin/sh setpgid(child_pid, child_pid); //Needed so negative PIDs can kill children of /bin/sh
//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) //TODO : change for execvp
if (execvp(command.c_str(), &argv))
{ 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)
perror("execl error => ");
}
exit (0); exit (0);
} }
else else
@ -103,6 +108,10 @@ FILE * popen2(char * const argv, string type, int & pid)
return 0; return 0;
} }
// 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 pclose2(FILE * fp, pid_t pid)
{ {
int stat; int stat;

View File

@ -9,7 +9,7 @@ using namespace std;
const vector<string> explode(const string& s, const char& c, int n); const vector<string> explode(const string& s, const char& c, int n);
FILE * popen2(char * const argv, string type, int & pid); FILE * popen2(array<string,8> argv, string type, int & pid);
int pclose2(FILE * fp, pid_t pid); int pclose2(FILE * fp, pid_t pid);