diff --git a/RsyncUI.pro b/RsyncUI.pro
new file mode 100644
index 0000000..7d096b4
--- /dev/null
+++ b/RsyncUI.pro
@@ -0,0 +1,38 @@
+QT += core gui concurrent
+QT += KItemViews
+QT += KCompletion
+QT += widgets
+
+#LIBS += -lKF5WindowSystem
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+CONFIG += c++11
+
+# 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
+
+SOURCES += \
+ downloadfile.cpp \
+ main.cpp \
+ mainwindow.cpp \
+ tools.cpp
+
+HEADERS += \
+ downloadfile.h \
+ mainwindow.h \
+ tools.h
+
+FORMS += \
+ mainwindow.ui
+
+TRANSLATIONS += \
+ RsyncUI_fr_FR.ts
+
+INCLUDEPATH += \
+ /usr/include/KF5
+
+# Default rules for deployment.
+qnx: target.path = /tmp/$${TARGET}/bin
+else: unix:!android: target.path = /opt/$${TARGET}/bin
+!isEmpty(target.path): INSTALLS += target
diff --git a/RsyncUI.pro.user b/RsyncUI.pro.user
new file mode 100644
index 0000000..5d12286
--- /dev/null
+++ b/RsyncUI.pro.user
@@ -0,0 +1,319 @@
+
+
+
+
+
+ EnvironmentId
+ {a3117c94-e673-4dca-aa4c-050bbea034fe}
+
+
+ ProjectExplorer.Project.ActiveTarget
+ 0
+
+
+ ProjectExplorer.Project.EditorSettings
+
+ true
+ false
+ true
+
+ Cpp
+
+ CppGlobal
+
+
+
+ QmlJS
+
+ QmlJSGlobal
+
+
+ 2
+ UTF-8
+ false
+ 4
+ false
+ 80
+ true
+ true
+ 1
+ true
+ false
+ 0
+ true
+ true
+ 0
+ 8
+ true
+ 1
+ true
+ true
+ true
+ *.md, *.MD, Makefile
+ false
+ true
+
+
+
+ ProjectExplorer.Project.PluginSettings
+
+
+ true
+ true
+ true
+ true
+ true
+
+
+ 0
+ true
+
+ true
+ Builtin.Questionable
+
+ true
+ true
+ Builtin.DefaultTidyAndClazy
+ 2
+
+
+
+ true
+
+
+
+
+ ProjectExplorer.Project.Target.0
+
+ Desktop
+ Desktop
+ Desktop
+ {893f9ca6-0efa-4c08-a4a6-5a818f60a8a0}
+ 0
+ 0
+ 0
+
+ 0
+ /home/daniel/develope/build-RsyncUI-Desktop-Debug
+ /home/daniel/develope/build-RsyncUI-Desktop-Debug
+
+
+ true
+ QtProjectManager.QMakeBuildStep
+
+ false
+
+
+
+ true
+ Qt4ProjectManager.MakeStep
+
+ 2
+ Build
+ Build
+ ProjectExplorer.BuildSteps.Build
+
+
+
+ true
+ Qt4ProjectManager.MakeStep
+ clean
+
+ 1
+ Clean
+ Clean
+ ProjectExplorer.BuildSteps.Clean
+
+ 2
+ false
+
+
+ Debug
+ Qt4ProjectManager.Qt4BuildConfiguration
+ 2
+ 0
+
+
+ /home/daniel/develope/build-RsyncUI-Desktop-Release
+ /home/daniel/develope/build-RsyncUI-Desktop-Release
+
+
+ true
+ QtProjectManager.QMakeBuildStep
+
+ false
+
+
+
+ true
+ Qt4ProjectManager.MakeStep
+
+ 2
+ Build
+ Build
+ ProjectExplorer.BuildSteps.Build
+
+
+
+ true
+ Qt4ProjectManager.MakeStep
+ clean
+
+ 1
+ Clean
+ Clean
+ ProjectExplorer.BuildSteps.Clean
+
+ 2
+ false
+
+
+ Release
+ Qt4ProjectManager.Qt4BuildConfiguration
+ 0
+ 0
+ 0
+
+
+ 0
+ /home/daniel/develope/build-RsyncUI-Desktop-Profile
+ /home/daniel/develope/build-RsyncUI-Desktop-Profile
+
+
+ true
+ QtProjectManager.QMakeBuildStep
+
+ false
+
+
+
+ true
+ Qt4ProjectManager.MakeStep
+
+ 2
+ Build
+ Build
+ ProjectExplorer.BuildSteps.Build
+
+
+
+ true
+ Qt4ProjectManager.MakeStep
+ clean
+
+ 1
+ Clean
+ Clean
+ ProjectExplorer.BuildSteps.Clean
+
+ 2
+ false
+
+
+ Profile
+ Qt4ProjectManager.Qt4BuildConfiguration
+ 0
+ 0
+ 0
+ 0
+
+ 3
+
+
+ 0
+ Deploy
+ Deploy
+ ProjectExplorer.BuildSteps.Deploy
+
+ 1
+
+ false
+ ProjectExplorer.DefaultDeployConfiguration
+
+ 1
+
+ dwarf
+
+ cpu-cycles
+
+
+ 250
+
+ -e
+ cpu-cycles
+ --call-graph
+ dwarf,4096
+ -F
+ 250
+
+ -F
+ true
+ 4096
+ false
+ false
+ 1000
+
+ true
+
+ false
+ false
+ false
+ false
+ true
+ 0.01
+ 10
+ true
+ kcachegrind
+ 1
+ 25
+
+ 1
+ true
+ false
+ true
+ valgrind
+
+ 0
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 10
+ 11
+ 12
+ 13
+ 14
+
+
+ 2
+
+ Qt4ProjectManager.Qt4RunConfiguration:/home/daniel/develope/RsyncUI/RsyncUI.pro
+ /home/daniel/develope/RsyncUI/RsyncUI.pro
+ false
+ true
+ true
+ false
+ true
+ /home/daniel/develope/build-RsyncUI-Desktop-Debug
+
+ 1
+
+
+
+ ProjectExplorer.Project.TargetCount
+ 1
+
+
+ ProjectExplorer.Project.Updater.FileVersion
+ 22
+
+
+ Version
+ 22
+
+
diff --git a/RsyncUI_fr_FR.qm b/RsyncUI_fr_FR.qm
new file mode 100644
index 0000000..644c776
Binary files /dev/null and b/RsyncUI_fr_FR.qm differ
diff --git a/RsyncUI_fr_FR.ts b/RsyncUI_fr_FR.ts
new file mode 100644
index 0000000..531267a
--- /dev/null
+++ b/RsyncUI_fr_FR.ts
@@ -0,0 +1,67 @@
+
+
+
+
+ Dialog
+
+
+
+
+
+
+
+
+
+
+
+
+ MainWindow
+
+
+
+ Fenêtre principale
+
+
+
+
+ Serveur
+ Serveur
+
+
+
+
+ Port
+
+
+
+
+ Downloading
+ Téléchargement
+
+
+
+
+ debug
+
+
+
+
+ Chemin
+
+
+
+
+ Taille
+
+
+
+
+ Le serveur n'existe pas
+
+
+
+
+ Choisissez le dossier où enregistrer
+
+
+
diff --git a/downloadfile.cpp b/downloadfile.cpp
new file mode 100644
index 0000000..3de7369
--- /dev/null
+++ b/downloadfile.cpp
@@ -0,0 +1,103 @@
+#include "downloadfile.h"
+#include "mainwindow.h"
+#include "ui_mainwindow.h"
+#include "tools.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+using namespace std;
+
+downloadFile::downloadFile()
+{
+}
+
+void downloadFile::cancelled()
+{
+ this->canceled = true;
+}
+
+void downloadFile::download(QString savePath, MainWindow *mw)
+{
+ string server;
+ string service;
+ string path;
+ string line;
+ string errorRsync;
+ char cmd[4096];
+ int portN;
+ int pos;
+ int pid;
+ QTreeWidgetItem * item;
+ stringstream output;
+ // QString savePath = ".";
+ vector v;
+ int value;
+ //char command_out[1024] = {0};
+ array buffer;
+
+ server.assign(mw->ui->khistorycombobox->currentText().toStdString());
+ portN = mw->ui->portEdit->text().toInt();
+ service = mw->ui->listWidget->currentItem()->text().toStdString();
+ pos = service.find_first_of('\n');
+ service.resize(pos);
+
+ item = mw->ui->treeWidget->currentItem();
+ path = item->text(0).toStdString();
+ while(item->parent() != NULL)
+ {
+ item = item->parent();
+ path = item->text(0).toStdString() + "/" + path;
+
+ };
+
+
+ sprintf(cmd, "rsync --bwlimit=100K --port %i -P %s::\"%s/%s\" \"%s/\" 2>&1", portN, server.c_str(), service.c_str(), path.c_str(), savePath.toStdString().c_str());
+
+
+
+ //unique_ptr pipe(popen(cmd, "r"), pclose);
+ FILE * fp = popen2(cmd, "r", pid);
+
+ if (!fp)
+ {
+ throw runtime_error("popen2() failed!");
+ }
+
+ while (fgets(buffer.data(), buffer.size(), fp) != nullptr)
+ {
+ buffer.data();
+ if (this->canceled == true)
+ {
+ return;
+ }
+ line = buffer.data();
+ //cout << line << endl;
+ pos = line.find('%');
+ if (pos != -1)
+ {
+ line.erase(pos);
+ pos = line.find_last_of(' ');
+ if (pos != -1)
+ {
+ line.erase(0, pos);
+ value = stoi(line);
+ cout << value << endl;
+ emit progressSignal(value);
+ }
+ }
+ buffer.empty();
+ }
+
+ //cout << path << endl;
+}
+
diff --git a/downloadfile.h b/downloadfile.h
new file mode 100644
index 0000000..ed85adf
--- /dev/null
+++ b/downloadfile.h
@@ -0,0 +1,24 @@
+#ifndef DOWNLOADFILE_H
+#define DOWNLOADFILE_H
+
+#include
+#include "ui_mainwindow.h"
+
+class MainWindow;
+
+class downloadFile : public QObject
+{
+ Q_OBJECT
+public:
+ downloadFile();
+ void download(QString savePath, MainWindow *parent = nullptr);
+ bool canceled;
+
+signals:
+ void progressSignal(int);
+
+public slots:
+ void cancelled();
+};
+
+#endif // DOWNLOADFILE_H
diff --git a/main.cpp b/main.cpp
new file mode 100644
index 0000000..115a22b
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,10 @@
+#include "mainwindow.h"
+#include
+
+int main(int argc, char *argv[])
+{
+ QApplication a(argc, argv);
+ MainWindow w;
+ w.show();
+ return a.exec();
+}
diff --git a/mainwindow.cpp b/mainwindow.cpp
new file mode 100644
index 0000000..5799f9c
--- /dev/null
+++ b/mainwindow.cpp
@@ -0,0 +1,344 @@
+#include "mainwindow.h"
+#include "ui_mainwindow.h"
+#include "downloadfile.h"
+#include "tools.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+using namespace std;
+
+bool display = false;
+
+MainWindow::MainWindow(QWidget *parent)
+ : QMainWindow(parent)
+ , ui(new Ui::MainWindow)
+{
+ ui->setupUi(this);
+ ui->ktreewidgetsearchline->setTreeWidget(ui->treeWidget);
+ ui->ktreewidgetsearchline->setCaseSensitivity(Qt::CaseInsensitive);
+ ui->treeWidget->setHeaderLabels({tr("Path"), tr("Size")} );
+ ui->progressBar->hide();
+ populateList();
+}
+
+MainWindow::~MainWindow()
+{
+ delete ui;
+}
+
+void MainWindow::populateTree()
+{
+ string server;
+ string port;
+ int portN;
+ stringstream ss;
+ vector path;
+
+ server.assign(ui->khistorycombobox->currentText().toStdString());
+ port.assign(ui->portEdit->text().toStdString());
+ ss << port;
+ ss >> portN;
+ if (!server.empty() and !port.empty() and portN < 65536)
+ {
+ if (validateServer(server))
+ {
+ ui->treeWidget->cursor().setShape(Qt::WaitCursor);
+ path = explode(ui->listWidget->currentItem()->text().toStdString(), '\n', 2);
+ scanDir(server, portN, NULL, path[0].append("/") );
+ ui->treeWidget->cursor().setShape(Qt::ArrowCursor);
+
+ }
+ }
+}
+
+void MainWindow::populateList()
+{
+ string server;
+ string port;
+ int portN;
+ stringstream ss;
+
+ server.assign(ui->khistorycombobox->currentText().toStdString());
+ port.assign(ui->portEdit->text().toStdString());
+ ss << port;
+ ss >> portN;
+ if (!server.empty() and !port.empty() and portN < 65536)
+ {
+ if (validateServer(server))
+ {
+ ui->centralwidget->cursor().setShape(Qt::WaitCursor);
+ listServices(server, portN);
+ ui->centralwidget->cursor().setShape(Qt::ArrowCursor);
+
+ }
+ }
+}
+
+void MainWindow::listServices(string server, int portN)
+{
+ char cmd[4096];
+ string line;
+ string errorRsync;
+ vector v;
+ char service[4096];
+
+ sprintf(cmd, "rsync --contimeout=10 -P \"%s::\" --port %d ", server.c_str(), portN );
+ redi::ipstream in(cmd, redi::pstreams::pstdout | redi::pstreams::pstderr);
+ while (getline(in.out(), line))
+ {
+ cout << "stdout: " << line << endl;
+ boost::replace_all(line," ","");
+ boost::replace_all(line, "\t", " - ");
+ v = explode(line, ' ', 3 );
+ sprintf(service, "%s\n\t%s", v[0].c_str(), v[2].c_str());
+ ui->listWidget->addItem(service);
+ }
+}
+
+void MainWindow::scanDir(string server, int portN, QTreeWidgetItem *parent, string path)
+{
+ char cmd[4096];
+ string line;
+ string errorRsync;
+ vector v;
+ QTreeWidgetItem * item;
+ char npath[4096];
+
+ sprintf(cmd, "rsync --contimeout=10 -P \"%s::%s\" --port %d ", server.c_str(), path.c_str(), portN );
+ redi::ipstream in(cmd, redi::pstreams::pstdout | redi::pstreams::pstderr);
+
+ while (getline(in.out(), line))
+ {
+
+ v = explode(line, ' ', 5);
+ if (v.size() == 5)
+ {
+ if (v[4].at(0) != '.' and (v[0].at(0) == '-' or v[0].at(0) == 'd'))
+ {
+ if (parent != NULL)
+ {
+ item = addTreeChild(parent,QString::fromStdString(v[4]), QString::fromStdString(v[1]));
+ }else
+ {
+ item = addTreeRoot(QString::fromStdString(v[4]), QString::fromStdString(v[1]));
+ }
+ if (v[0].at(0) == 'd')
+ {
+ sprintf(npath, "%s%s/", path.c_str(), v[4].c_str());
+ scanDir(server, portN, item, npath);
+ }
+ }
+ }
+ }
+ // if reading stdout stopped at EOF then reset the state:
+ if (in.eof() && in.fail())
+ in.clear();
+ // read child's stderr
+ while (getline(in.err(), line))
+ {
+ cout << "stderr: " << line << endl;
+ errorRsync.append(line);
+ errorRsync.append("\n");
+ }
+ if ( !errorRsync.empty())
+ {
+ QMessageBox::warning(
+ this,
+ "RsyncUI",
+ errorRsync.c_str());
+ }
+
+}
+
+bool MainWindow::isIpAddress(string server)
+{
+ bool returnCode = false;
+ vector r;
+ stringstream ss;
+ int elementN;
+
+ r = explode(server, '.');
+ if (r.size() == 4)
+ {
+ for (auto element : r)
+ {
+ ss << element;
+ ss >> elementN;
+ if (elementN >0 and elementN < 256)
+ {
+ returnCode &= true;
+ }
+ }
+ }
+ return returnCode;
+}
+
+bool MainWindow::validateServer(string server)
+{
+ char cmd[512];
+ string line;
+ string errorDig;
+ bool flag = false;
+
+ sprintf(cmd, "dig %s", server.c_str());
+ redi::ipstream in(cmd, redi::pstreams::pstdout | redi::pstreams::pstderr);
+
+ while (getline(in.out(), line))
+ {
+ cout << "stdout: " << line << '\n';
+ if (line.find(";; ANSWER SECTION:") != string::npos)
+ {
+ flag = true;
+ }
+ }
+ // if reading stdout stopped at EOF then reset the state:
+ if (in.eof() && in.fail())
+ in.clear();
+ // read child's stderr
+ while (std::getline(in.err(), line))
+ {
+ cout << "stderr: " << line << '\n';
+ errorDig.append(line);
+ errorDig.append("\n");
+ }
+ if ( !errorDig.empty())
+ {
+ QMessageBox::warning(
+ this,
+ "RsyncUI",
+ errorDig.c_str()
+ );
+ }
+ if ( flag == false)
+ {
+ flag = isIpAddress(server);
+ QMessageBox::warning(
+ this,
+ "RsyncUI",
+ tr("server does not exists" )
+ );
+ }
+ return flag;
+}
+
+void MainWindow::displayTree()
+{
+ populateTree();
+
+}
+
+void MainWindow::on_khistorycombobox_returnPressed()
+{
+ populateList();
+}
+
+/*void MainWindow::on_portEdit_userTextChanged()
+{
+ populateTree();
+}*/
+
+void MainWindow::on_portEdit_returnPressed()
+{
+ populateList();
+}
+
+void MainWindow::on_khistorycombobox_textActivated()
+{
+ populateList();
+}
+
+void MainWindow::on_treeWidget_itemClicked(QTreeWidgetItem *item, int column)
+{
+
+}
+
+void MainWindow::on_treeWidget_customContextMenuRequested()
+{
+
+}
+
+void MainWindow::on_actionDownload_triggered()
+{
+
+}
+
+QTreeWidgetItem * MainWindow::addTreeRoot(QString name, QString fileSize)
+{
+ // QTreeWidgetItem(QTreeWidget * parent, int type = Type)
+ QTreeWidgetItem *treeItem = new QTreeWidgetItem(ui->treeWidget);
+
+ // QTreeWidgetItem::setText(int column, const QString & text)
+ treeItem->setText(0, name);
+ treeItem->setText(1, fileSize);
+ return treeItem;
+}
+
+QTreeWidgetItem * MainWindow::addTreeChild(QTreeWidgetItem *parent, QString name, QString fileSize)
+{
+ // QTreeWidgetItem(QTreeWidget * parent, int type = Type)
+ QTreeWidgetItem *treeItem = new QTreeWidgetItem();
+
+ // QTreeWidgetItem::setText(int column, const QString & text)
+ treeItem->setText(0, name);
+ treeItem->setText(1, fileSize);
+
+ // QTreeWidgetItem::addChild(QTreeWidgetItem * child)
+ parent->addChild(treeItem);
+ return treeItem;
+}
+
+void MainWindow::on_listWidget_clicked(const QModelIndex &index)
+{
+ populateTree();
+}
+
+void MainWindow::on_listDownload_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)
+{
+ cout << current->text().toStdString() << endl;
+}
+
+void MainWindow::on_treeWidget_itemDoubleClicked(QTreeWidgetItem *item, int column)
+{
+ string path;
+ QFuture future;
+ QFutureWatcher watcher;
+ QString savePath;
+ QFileDialog dialog;
+ QString dirPath;
+ /*int p[2];
+
+ if (pipe(p) < 0)
+ {
+ return;
+ }*/
+ dirPath = getenv("HOME");
+ dirPath.append("/Vidéos/");
+ savePath = dialog.getExistingDirectory(this, tr("Choose directory to save file"), dirPath, QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
+ downloadFile downloadO;
+
+
+ //QProgressDialog progress("Downloading file ...", "Abort Download", 0, 100, this);
+
+ ui->progressBar->setWindowModality(Qt::WindowModal);
+ ui->progressBar->setValue(0);
+ ui->progressBar->show();
+ connect(&watcher, &QFutureWatcherBase::finished, ui->progressBar, &QProgressBar::hide);
+ connect(&downloadO, &downloadFile::progressSignal, ui->progressBar, &QProgressBar::setValue);
+ future = QtConcurrent::run(&this->MyObject, &downloadFile::download, savePath, this);
+ watcher.setFuture(future);
+}
diff --git a/mainwindow.h b/mainwindow.h
new file mode 100644
index 0000000..52bae5f
--- /dev/null
+++ b/mainwindow.h
@@ -0,0 +1,61 @@
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include
+#include
+#include
+#include
+#include "downloadfile.h"
+#include
+
+QT_BEGIN_NAMESPACE
+namespace Ui { class MainWindow; }
+QT_END_NAMESPACE
+
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ Ui::MainWindow *ui;
+ MainWindow(QWidget *parent = nullptr);
+ ~MainWindow();
+ QProgressDialog *progress;
+ void displayTree();
+ void populateTree();
+ void populateList();
+ void listServices(std::string server, int portN);
+ 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 = "" );
+
+private slots:
+ void on_khistorycombobox_returnPressed();
+
+ //void on_portEdit_userTextChanged();
+
+ void on_portEdit_returnPressed();
+
+ void on_khistorycombobox_textActivated();
+
+ void on_treeWidget_itemClicked(QTreeWidgetItem *item, int column);
+
+ void on_treeWidget_customContextMenuRequested();
+
+ void on_actionDownload_triggered();
+
+ void on_listWidget_clicked(const QModelIndex &index);
+
+ void on_listDownload_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous);
+
+ void on_treeWidget_itemDoubleClicked(QTreeWidgetItem *item, int column);
+
+public slots:
+
+private:
+ downloadFile MyObject;
+};
+
+#endif // MAINWINDOW_H
diff --git a/mainwindow.ui b/mainwindow.ui
new file mode 100644
index 0000000..594493a
--- /dev/null
+++ b/mainwindow.ui
@@ -0,0 +1,326 @@
+
+
+ DTux
+ MainWindow
+
+
+
+ 0
+ 0
+ 500
+ 571
+
+
+
+
+ 0
+ 0
+
+
+
+ MainWindow
+
+
+ false
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 32763
+ 32765
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 11
+
+
+
+ IBeamCursor
+
+
+ Qt::TabFocus
+
+
+ true
+
+
+
+
+
+ -
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Server
+
+
+ false
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Port
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 100
+ 0
+
+
+
+
+ 70
+ 16777215
+
+
+
+ Qt::ImhPreferNumbers
+
+
+
+
+
+ 6
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+ true
+
+
+ true
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ Qt::Horizontal
+
+
+
+
+ 0
+ 0
+
+
+
+ QAbstractItemView::SelectedClicked
+
+
+ QListView::Adjust
+
+
+ true
+
+
+
+
+
-
+
+
+
+ 1
+ 0
+
+
+
+ Qt::ImhNoAutoUppercase
+
+
+
+ -
+
+
+
+ 1
+ 0
+
+
+
+ Qt::CustomContextMenu
+
+
+ QAbstractItemView::NoEditTriggers
+
+
+ false
+
+
+ true
+
+
+ QAbstractItemView::DragOnly
+
+
+ true
+
+
+ QAbstractItemView::MultiSelection
+
+
+ QAbstractItemView::SelectItems
+
+
+ true
+
+
+ true
+
+
+ 1
+
+
+ true
+
+
+ true
+
+
+
+ 1
+
+
+
+
+
+
+
+
+
+ true
+
+
+ QAbstractItemView::DropOnly
+
+
+
+
+ -
+
+
+ true
+
+
+ 0
+
+
+ %p%
+
+
+
+
+
+
+
+
+
+
+ KComboBox
+ QComboBox
+
+
+
+ KHistoryComboBox
+ KComboBox
+
+
+
+ KLineEdit
+ QLineEdit
+
+
+
+ KTreeWidgetSearchLine
+ QLineEdit
+
+
+
+
+
+
diff --git a/tools.cpp b/tools.cpp
new file mode 100644
index 0000000..654cc29
--- /dev/null
+++ b/tools.cpp
@@ -0,0 +1,113 @@
+#include
+#include
+#include
+#include
+#include
+#include
+
+using namespace std;
+
+#define READ 0
+#define WRITE 1
+
+const vector explode(const string& s, const char& c, int n = 0)
+{
+ string buff;
+ vector v;
+ size_t pos = 0;
+ size_t ppos = 0;
+ int i = 0;
+
+ while (i < n - 1)
+ {
+ pos = s.find(c, ppos);
+ if (pos != string::npos)
+ {
+ buff = s.substr(ppos, pos - ppos);
+ if (buff != "")
+ {
+ i++;
+ v.push_back(s.substr(ppos, pos - ppos));
+ }
+ ppos = pos + 1;
+ }else
+ {
+ break;
+ }
+ }
+ if (ppos < s.size())
+ {
+ v.push_back(s.substr(ppos));
+ }
+ return v;
+}
+
+FILE * popen2(char * cmd, string type, int & pid)
+{
+ pid_t child_pid;
+ int fd[2];
+ pipe(fd);
+
+ if((child_pid = fork()) == -1)
+ {
+ perror("fork");
+ exit(1);
+ }
+
+ /* child process */
+ if (child_pid == 0)
+ {
+ if (type == "r")
+ {
+ close(fd[READ]); //Close the READ end of the pipe since the child's fd is write-only
+ dup2(fd[WRITE], 1); //Redirect stdout to pipe
+ }
+ else
+ {
+ close(fd[WRITE]); //Close the WRITE end of the pipe since the child's fd is read-only
+ dup2(fd[READ], 0); //Redirect stdin to pipe
+ }
+
+ setpgid(child_pid, child_pid); //Needed so negative PIDs can kill children of /bin/sh
+ execl(cmd, "");
+ exit(0);
+ }
+ else
+ {
+ if (type == "r")
+ {
+ close(fd[WRITE]); //Close the WRITE end of the pipe since parent's fd is read-only
+ }
+ else
+ {
+ close(fd[READ]); //Close the READ end of the pipe since parent's fd is write-only
+ }
+ }
+
+ pid = child_pid;
+
+ if (type == "r")
+ {
+ return fdopen(fd[READ], "r");
+ }
+
+ return fdopen(fd[WRITE], "w");
+}
+
+int pclose2(FILE * fp, pid_t pid)
+{
+ int stat;
+
+ fclose(fp);
+ while (waitpid(pid, &stat, 0) == -1)
+ {
+ if (errno != EINTR)
+ {
+ stat = -1;
+ break;
+ }
+ }
+
+ return stat;
+}
+
diff --git a/tools.h b/tools.h
new file mode 100644
index 0000000..64ec011
--- /dev/null
+++ b/tools.h
@@ -0,0 +1,14 @@
+#ifndef TOOLS_H
+#define TOOLS_H
+
+#include
+#include
+#include "mainwindow.h"
+
+using namespace std;
+
+const vector explode(const string& s, const char& c, int n = 0);
+FILE * popen2(char * command, string type, int & pid);
+int pclose2(FILE * fp, pid_t pid);
+
+#endif // TOOLS_H