diff --git a/bootstrap/runPharos/CHANGELOG b/bootstrap/runPharos/CHANGELOG
new file mode 100644
index 00000000..bc95b8c6
--- /dev/null
+++ b/bootstrap/runPharos/CHANGELOG
@@ -0,0 +1,21 @@
+## VERSION 1.0 --- 19 février 2010
+- First releasable version tested on Mac Os and Linux
+
+## VERSION 0.6 --- 19 février 2010
+- Adds settings support to configure the application.
+
+## VERSION 0.5 --- 16 février 2010
+- Adds compile.sh script to easily compile the application.
+The script uses cmake and can be run under Mac / Linux.
+
+## VERSION 0.4
+- Adds support for several technologies.
+
+## VERSION 0.3 --- novembre 2010
+- Can Show / Hide console.
+
+## VERSION 0.2
+- Adds a text console to catch all output from Pharos.
+
+## VERSION 0.1
+- First version : can run Pharos.
diff --git a/bootstrap/runPharos/CMakeLists.txt b/bootstrap/runPharos/CMakeLists.txt
new file mode 100644
index 00000000..bde18a62
--- /dev/null
+++ b/bootstrap/runPharos/CMakeLists.txt
@@ -0,0 +1,22 @@
+PROJECT(RUNPHAROS)
+
+CMAKE_MINIMUM_REQUIRED(VERSION 2.4.0)
+
+SET(CMAKE_BUILD_TYPE release)
+
+FIND_PACKAGE(Qt4 REQUIRED)
+
+INCLUDE(${QT_USE_FILE})
+
+SET(CPP_FILES main.cpp MainWindow.cpp MyWidget.cpp ConfigDialog.cpp TechnoRow.cpp)
+
+QT4_WRAP_CPP(MOC_RUNPHAROS MainWindow.h MyWidget.h ConfigDialog.h TechnoRow.h)
+
+IF(APPLE)
+ ADD_EXECUTABLE(runPharos MACOSX_BUNDLE ${MOC_RUNPHAROS} ${CPP_FILES})
+ELSE(APPLE)
+ ADD_EXECUTABLE(runPharos ${MOC_RUNPHAROS} ${CPP_FILES})
+ENDIF(APPLE)
+
+TARGET_LINK_LIBRARIES(runPharos ${QT_LIBRARIES})
+INSTALL(TARGETS runPharos DESTINATION /)
diff --git a/bootstrap/runPharos/ConfigDialog.cpp b/bootstrap/runPharos/ConfigDialog.cpp
new file mode 100644
index 00000000..a0a0c362
--- /dev/null
+++ b/bootstrap/runPharos/ConfigDialog.cpp
@@ -0,0 +1,152 @@
+#include
+using namespace std;
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "ConfigDialog.h"
+#include "TechnoRow.h"
+
+#define LINEEDITWIDTH 300
+
+int ConfigDialog::_rowID = 0;
+
+ConfigDialog::ConfigDialog() {
+ setStyleSheet("font-weight: normal;");
+ // First GroupBox : Directories
+ // Create widgets
+ QLabel* programL = new QLabel(tr("Pharos binary") , this);
+ QLabel* libraryL = new QLabel(tr("LD_LIBRARY_PATH") , this);
+ _programE = new QLineEdit ("", this);
+ _libraryE = new QLineEdit ("", this);
+ _programE->setFixedWidth(LINEEDITWIDTH);
+ _libraryE->setFixedWidth(LINEEDITWIDTH);
+ _programE->setToolTip(tr("Select Pharos binary file."));
+ _libraryE->setToolTip(tr("Select the directory containing c++ dynamic libraries used by Pharos."));
+ QPushButton* programB = new QPushButton(tr("&Browse"));
+ QPushButton* libraryB = new QPushButton(tr("&Browse"));
+ // Connect SIGNAL/SLOTS
+ connect(programB , SIGNAL(clicked()), this, SLOT(chooseProgram()));
+ connect(libraryB , SIGNAL(clicked()), this, SLOT(chooseLibrary()));
+ // Create GroupBox
+ QGroupBox* directories = new QGroupBox("Directories", this);
+ QGridLayout* gLayout = new QGridLayout(this);
+ gLayout->addWidget( programL , 0, 0, 1, 1);
+ gLayout->addWidget(_programE , 0, 1, 1, 1);
+ gLayout->addWidget( programB , 0, 2, 1, 1);
+ gLayout->addWidget( libraryL , 1, 0, 1, 1);
+ gLayout->addWidget(_libraryE , 1, 1, 1, 1);
+ gLayout->addWidget( libraryB , 1, 2, 1, 1);
+ directories->setLayout(gLayout);
+ // Second GroupBox : Technos
+ // Create Widgets / Layout
+ QLabel* name = new QLabel(tr("Name"));
+ QLabel* file = new QLabel(tr("XML Config File"));
+ name->setFixedWidth(80);
+ file->setFixedWidth(LINEEDITWIDTH);
+ _rowLayout = new QVBoxLayout();
+ _rowLayout->setContentsMargins(0,0,0,0);
+ _rowLayout->setSpacing(0);
+ addRow();
+ // Create GroupBox
+ QGroupBox* technos = new QGroupBox("Technologies", this);
+ QHBoxLayout* headerLayout = new QHBoxLayout();
+ headerLayout->addSpacing(20);
+ headerLayout->addWidget(name);
+ headerLayout->addWidget(file);
+ QVBoxLayout* techLayout = new QVBoxLayout();
+ techLayout->addLayout(headerLayout);
+ techLayout->addLayout(_rowLayout);
+ technos->setLayout(techLayout);
+
+ QDialogButtonBox* dbBox = new QDialogButtonBox(QDialogButtonBox::Ok);
+ _add = new QPushButton("&Add technology", this);
+ dbBox->addButton(_add, QDialogButtonBox::ActionRole);
+ connect(_add , SIGNAL(clicked()) , this, SLOT(addRow()));
+ connect(dbBox, SIGNAL(accepted()), this, SLOT(doConfig()));
+
+ QVBoxLayout* tLayout = new QVBoxLayout();
+ tLayout->setContentsMargins(0,0,0,0);
+ tLayout->addWidget(directories);
+ tLayout->addWidget(technos);
+ tLayout->addWidget(dbBox);
+ setLayout(tLayout);
+ setWindowTitle(tr("Configure runPharos"));
+ layout()->setSizeConstraint(QLayout::SetFixedSize);
+}
+
+
+void ConfigDialog::addRow() {
+ TechnoRow* row = new TechnoRow(_rowID++, this);
+ connect(row, SIGNAL(suppressed(int)), this, SLOT(removeRow(int)));
+ row->setContentsMargins(0,0,0,0);
+ _rows.push_back(row);
+ _rowLayout->addWidget(row);
+}
+
+void ConfigDialog::addRow(QString& name, QString& file) {
+ TechnoRow* row = new TechnoRow(_rowID++, this);
+ row->setName(name);
+ row->setFile(file);
+ connect(row, SIGNAL(suppressed(int)), this, SLOT(removeRow(int)));
+ row->setContentsMargins(0,0,0,0);
+ _rows.push_back(row);
+ _rowLayout->addWidget(row);
+}
+
+void ConfigDialog::removeRow(int id) {
+ TechnoRow* row = _rows[id];
+ _rowLayout->removeWidget(row);
+ row->hide();
+}
+
+void ConfigDialog::doConfig() {
+ QStringList list;
+ if ( _programE->text().isEmpty() || _libraryE->text().isEmpty() ) {
+ QMessageBox::warning(this, tr("runPharos warning"), tr("You must set all directories."));
+ return;
+ }
+ list << _programE->text() << _libraryE->text();
+ vector > technos;
+ for ( size_t i = 0 ; i < _rows.size() ; i++ ) {
+ TechnoRow* row = _rows[i];
+ if (row->isVisible()) {
+ if((row->getName() != "") && (row->getFile() != "")) {
+ technos.push_back(pair(row->getName(), row->getFile()));
+ } else {
+ QMessageBox::warning(this, tr("runPharos warning"), tr("You must set a valid name and file for each technology."));
+ return;
+ }
+ }
+ }
+ if (technos.size() > 0) {
+ emit(configDone(list, technos));
+ accept();
+ } else {
+ QMessageBox::warning(this, tr("runPharos warning"), tr("You must set at least one valid technology."));
+ }
+}
+
+void ConfigDialog::chooseProgram() {
+ _programE->setText(QFileDialog::getOpenFileName(this, tr("Select Pharos binary file"), "", tr("Executable file (*)")));
+}
+
+void ConfigDialog::chooseLibrary() {
+ _libraryE->setText(QFileDialog::getExistingDirectory(this, tr("Select directory containing c++ dynamic libraries")));
+}
+
+void ConfigDialog::setProgram(QString program) {
+ _programE->setText(program);
+}
+
+void ConfigDialog::setLibrary(QString library) {
+ _libraryE->setText(library);
+}
+
diff --git a/bootstrap/runPharos/ConfigDialog.h b/bootstrap/runPharos/ConfigDialog.h
new file mode 100644
index 00000000..118027ca
--- /dev/null
+++ b/bootstrap/runPharos/ConfigDialog.h
@@ -0,0 +1,43 @@
+#ifndef CONFIGDIALOG_H
+#define CONFIGDIALOG_H
+
+#include
+
+#include
+
+class QVBoxLayout;
+class QPushButton;
+class QLineEdit;
+class QStringList;
+class TechnoRow;
+
+class ConfigDialog : public QDialog {
+ Q_OBJECT
+
+public:
+ ConfigDialog();
+ void setProgram(QString);
+ void setLibrary(QString);
+
+signals:
+ void configDone(QStringList&, std::vector >&);
+
+public slots:
+ void addRow();
+ void addRow(QString&, QString&);
+ void removeRow(int);
+ void doConfig();
+ void chooseProgram();
+ void chooseLibrary();
+
+
+private:
+ QLineEdit* _programE;
+ QLineEdit* _libraryE;
+ static int _rowID;
+ QPushButton* _add;
+ QVBoxLayout* _rowLayout;
+ std::vector _rows;
+};
+
+#endif
diff --git a/bootstrap/runPharos/MainWindow.cpp b/bootstrap/runPharos/MainWindow.cpp
new file mode 100644
index 00000000..3d9d292c
--- /dev/null
+++ b/bootstrap/runPharos/MainWindow.cpp
@@ -0,0 +1,23 @@
+#include
+#include
+#include
+
+#include "MainWindow.h"
+#include "MyWidget.h"
+
+MainWindow::MainWindow()
+{
+ MyWidget* mWidget = new MyWidget(this);
+ setCentralWidget(mWidget);
+
+ QAction* configAct = new QAction(tr("&Configure"), this);
+ configAct->setStatusTip(tr("Configure the application"));
+ connect(configAct, SIGNAL(triggered()), mWidget, SLOT(reconfig()));
+ QAction* aboutAct = new QAction(tr("&About"), this);
+ aboutAct->setStatusTip(tr("Show the about dialog box"));
+ connect(aboutAct, SIGNAL(triggered()), mWidget, SLOT(about()));
+ QMenu* editMenu = menuBar()->addMenu(tr("&Edit"));
+ editMenu->addAction(configAct);
+ QMenu* helpMenu = menuBar()->addMenu(tr("&Help"));
+ helpMenu->addAction(aboutAct);
+}
diff --git a/bootstrap/runPharos/MainWindow.h b/bootstrap/runPharos/MainWindow.h
new file mode 100644
index 00000000..ef0bf8be
--- /dev/null
+++ b/bootstrap/runPharos/MainWindow.h
@@ -0,0 +1,13 @@
+#ifndef __MAINWINDOW_H
+#define __MAINWINDOW_H
+
+#include
+
+class MainWindow : public QMainWindow {
+ Q_OBJECT
+
+ public:
+ MainWindow ();
+ ~MainWindow () {};
+};
+#endif
diff --git a/bootstrap/runPharos/MyWidget.cpp b/bootstrap/runPharos/MyWidget.cpp
new file mode 100644
index 00000000..5e1b6921
--- /dev/null
+++ b/bootstrap/runPharos/MyWidget.cpp
@@ -0,0 +1,204 @@
+#include
+using namespace std;
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "MyWidget.h"
+#include "ConfigDialog.h"
+
+MyWidget::MyWidget(QWidget *parent) : QWidget(parent) {
+
+ setStyleSheet("font-weight: normal;");
+
+ _technoCB = new QComboBox(this);
+ _technoCB->setFixedWidth(120);
+ readSettings();
+ updateComboBox();
+
+ _console = new QTextEdit(this);
+ _console->setFixedSize(600,350);
+ _console->setFontPointSize(10);
+
+ _execute = new QPushButton ( "&Execute", this );
+ _execute->setDefault(true);
+ _stop = new QPushButton ( "&Stop", this );
+ _stop->setEnabled(false);
+ _show = new QPushButton ( "&Show console", this );
+ _clear = new QPushButton ( "&Clear", this );
+
+ QDialogButtonBox* buttons = new QDialogButtonBox();
+ buttons->addButton ( _execute, QDialogButtonBox::RejectRole );
+ buttons->addButton ( _stop , QDialogButtonBox::AcceptRole );
+ buttons->addButton ( _show , QDialogButtonBox::ResetRole );
+ buttons->addButton ( _clear , QDialogButtonBox::ResetRole );
+
+ connect ( _execute, SIGNAL(clicked()), this , SLOT(execute()) );
+ connect ( _stop , SIGNAL(clicked()), this , SLOT(stop()) );
+ connect ( _show , SIGNAL(clicked()), this , SLOT(showOrHide()) );
+ connect ( _clear , SIGNAL(clicked()), _console, SLOT(clear()) );
+
+ QHBoxLayout* hLayout = new QHBoxLayout();
+ hLayout->addWidget(buttons, Qt::AlignRight);
+ QVBoxLayout* layout = new QVBoxLayout();
+ layout->addWidget(_technoCB);
+ layout->addWidget(_console);
+ layout->addLayout(hLayout);
+ setLayout(layout);
+ _clear->hide();
+ _console->hide();
+ setWindowTitle("Run Pharos");
+ setFixedSize(400,110);
+}
+
+void MyWidget::readSettings() {
+ _settings = new QSettings("chams", "runPharos");
+
+ if ( !_settings->contains("Program") ) {
+ QMessageBox::warning(this, tr("runPharos"), tr("It seems you do not have configured the application. Let's configure it now."), QMessageBox::Ok, QMessageBox::Ok);
+ runConfigDialog(true);
+ } else {
+ _program = _settings->value("Program").toString();
+ _library = _settings->value("Library").toString();
+ _nbTechno = _settings->value("NbTechno").toInt();
+ _technos.clear();
+ for ( int i = 0 ; i < _nbTechno ; i++ ) {
+ QString name = QString("name_%1").arg(i);
+ QString file = QString("file_%1").arg(i);
+ _technos.push_back(pair(_settings->value(name).toString(), _settings->value(file).toString()));
+ }
+ }
+}
+
+void MyWidget::runConfigDialog(bool first) {
+ ConfigDialog* cfg = new ConfigDialog;
+ connect(cfg, SIGNAL(configDone(QStringList&, std::vector >&)), this, SLOT(updateConfig(QStringList&, std::vector >&)));
+ if(!first) {
+ cfg->setProgram(_program);
+ cfg->setLibrary(_library);
+ // on enleve la row par defaut vide
+ cfg->removeRow(0);
+ // on rajoute toutes les technos lues dans les settings:
+ for ( size_t i = 0 ; i < _technos.size() ; i++ ) {
+ cfg->addRow(_technos[i].first, _technos[i].second);
+ }
+ }
+ cfg->exec();
+ writeSettings();
+}
+
+void MyWidget::reconfig() {
+ runConfigDialog(false);
+}
+
+void MyWidget::writeSettings() {
+ _settings->setValue("Program" , _program);
+ _settings->setValue("Library" , _library);
+ _settings->setValue("NbTechno" , _nbTechno);
+ for ( size_t i = 0 ; i < _technos.size() ; i++ ) {
+ QString name = QString("name_%1").arg(i);
+ QString file = QString("file_%1").arg(i);
+ _settings->setValue(name, _technos[i].first);
+ _settings->setValue(file, _technos[i].second);
+ }
+}
+
+void MyWidget::updateConfig(QStringList& list, vector >& technos) {
+ _program = list.value(0);
+ _library = list.value(1);
+ _technos.clear();
+ for ( size_t i = 0 ; i < technos.size() ; i++ ) {
+ _technos.push_back(pair(technos[i].first, technos[i].second));
+ }
+ _nbTechno = _technos.size();
+ updateComboBox();
+}
+
+void MyWidget::updateComboBox() {
+ if (_technoCB->count() != 0)
+ _technoCB->clear();
+ QStringList choices;
+ for ( size_t i = 0 ; i < _technos.size() ; i++ ) {
+ choices << _technos[i].first;
+ }
+ _technoCB->addItems(choices);
+}
+
+void MyWidget::about() {
+ QMessageBox::about(this, tr("About runPharos"), tr("runPharos
"
+ "This tool allows every one to easily run pharos on a specified technology.
"
+ "Version 1.0
19/02/2010
by D.Dupuis
"));
+
+}
+
+void MyWidget::execute() {
+ QStringList arguments;
+ QString techno ("");
+ QString name = _technoCB->currentText();
+ for ( size_t i = 0 ; i < _technos.size() ; i++ ) {
+ if ( _technos[i].first == name )
+ techno = _technos[i].second;
+ }
+ if ( techno == "" )
+ return;
+ arguments << techno;
+
+ _myProcess = new QProcess(this);
+ QStringList env = QProcess::systemEnvironment();
+ QString DYLD = QString("DYLD_LIBRARY_PATH=%1").arg(_library);
+ QString LD = QString("LD_LIBRARY_PATH=%1").arg(_library);
+ QString PP = QString("PYTHONPATH=%1/python").arg(_library);
+ env << DYLD << LD << PP;
+ _myProcess->setEnvironment(env);
+ connect(_myProcess, SIGNAL(readyReadStandardError()) , this, SLOT(updateError()));
+ connect(_myProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(updateText()));
+ connect(_myProcess, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(finished(int, QProcess::ExitStatus)) );
+ _myProcess->start(_program, arguments);
+ _execute->setEnabled(false);
+ _stop->setEnabled(true);
+}
+
+void MyWidget::stop() {
+ _myProcess->terminate();
+ _execute->setEnabled(true);
+ _stop->setEnabled(false);
+}
+
+void MyWidget::showOrHide() {
+ if ( _console->isHidden() ) {
+ _show->setText("&Hide console");
+ _console->show();
+ _clear->show();
+ setFixedSize(620,450);
+ }
+ else {
+ _show->setText("&Show console");
+ _console->hide();
+ _clear->hide();
+ setFixedSize(400,110);
+ }
+}
+
+void MyWidget::updateError() {
+ QByteArray data = _myProcess->readAllStandardError();
+ _console->insertPlainText(QString(data));
+}
+
+void MyWidget::updateText() {
+ QByteArray data = _myProcess->readAllStandardOutput();
+ _console->insertPlainText(QString(data));
+}
+
+void MyWidget::finished(int exitCode, QProcess::ExitStatus exitStatus) {
+ _execute->setEnabled(true);
+ _stop->setEnabled(false);
+}
diff --git a/bootstrap/runPharos/MyWidget.h b/bootstrap/runPharos/MyWidget.h
new file mode 100644
index 00000000..90d66fdc
--- /dev/null
+++ b/bootstrap/runPharos/MyWidget.h
@@ -0,0 +1,56 @@
+#ifndef __MY_WIDGET_H
+#define __MY_WIDGET_H
+
+#include
+
+#include
+#include
+#include
+
+class QComboBox;
+class QPushButton;
+class QTextEdit;
+class QSettings;
+class QStringList;
+
+class MyWidget : public QWidget {
+ Q_OBJECT
+
+ public:
+ MyWidget (QWidget *parent =0);
+ ~MyWidget () {};
+
+ QComboBox* _technoCB;
+ QPushButton* _execute;
+ QPushButton* _stop;
+ QPushButton* _show;
+ QPushButton* _clear;
+ QTextEdit* _console;
+
+ QProcess* _myProcess;
+
+ QSettings* _settings;
+ QString _program;
+ QString _library;
+ int _nbTechno;
+ std::vector > _technos;
+
+ private:
+ void readSettings();
+ void writeSettings();
+ void runConfigDialog(bool);
+ void updateComboBox();
+
+ public slots:
+ void about();
+ void reconfig();
+ void execute();
+ void stop();
+ void finished(int exitCode, QProcess::ExitStatus exitStatus);
+ void showOrHide();
+ void updateError();
+ void updateText();
+ void updateConfig(QStringList&, std::vector >&);
+};
+
+#endif
diff --git a/bootstrap/runPharos/TechnoRow.cpp b/bootstrap/runPharos/TechnoRow.cpp
new file mode 100644
index 00000000..c689c0a8
--- /dev/null
+++ b/bootstrap/runPharos/TechnoRow.cpp
@@ -0,0 +1,68 @@
+#include
+using namespace std;
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "TechnoRow.h"
+
+TechnoRow::TechnoRow(int id, QWidget *parent) : QWidget(parent), _id(id) {
+ _suppress = new QPushButton( tr("-"), this);
+ _suppress->setStyleSheet("font: bold 24pt; color: red; border: 0px");
+ _suppress->setFixedWidth(_suppress->height());
+ _name = new QLineEdit(this);
+ _name->setFixedWidth(80);
+ _file = new QLineEdit(this);
+ _file->setFixedWidth(300);
+ _browse = new QPushButton( tr("&browse"), this);
+
+ connect(_suppress, SIGNAL(clicked()), this, SLOT(suppress()));
+ connect(_browse , SIGNAL(clicked()), this, SLOT(chooseFile()));
+
+ //QDialogButtonBox* buttons = new QDialogButtonBox();
+ //buttons->addButton ( _execute, QDialogButtonBox::RejectRole );
+ //buttons->addButton ( _stop , QDialogButtonBox::AcceptRole );
+ //buttons->addButton ( _show , QDialogButtonBox::ResetRole );
+ //buttons->addButton ( _clear , QDialogButtonBox::ResetRole );
+
+ //connect ( _execute, SIGNAL(clicked()), this , SLOT(execute()) );
+ //connect ( _stop , SIGNAL(clicked()), this , SLOT(stop()) );
+ //connect ( _show , SIGNAL(clicked()), this , SLOT(showOrHide()) );
+ //connect ( _clear , SIGNAL(clicked()), _console, SLOT(clear()) );
+
+ QHBoxLayout* hLayout = new QHBoxLayout();
+ hLayout->setContentsMargins(0,0,0,0);
+ hLayout->addWidget(_suppress);
+ hLayout->addWidget(_name);
+ hLayout->addWidget(_file);
+ hLayout->addWidget(_browse);
+ setLayout(hLayout);
+}
+
+QString TechnoRow::getName() {
+ return _name->text();
+}
+
+QString TechnoRow::getFile() {
+ return _file->text();
+}
+
+void TechnoRow::setName(QString& name) {
+ _name->setText(name);
+}
+
+void TechnoRow::setFile(QString& file) {
+ _file->setText(file);
+}
+
+void TechnoRow::suppress() {
+ emit(suppressed(_id));
+}
+
+void TechnoRow::chooseFile() {
+ _file->setText(QFileDialog::getOpenFileName(this, tr("Select dtr file"), "", tr("Xml file (*.xml)")));
+}
diff --git a/bootstrap/runPharos/TechnoRow.h b/bootstrap/runPharos/TechnoRow.h
new file mode 100644
index 00000000..ca789dae
--- /dev/null
+++ b/bootstrap/runPharos/TechnoRow.h
@@ -0,0 +1,35 @@
+#ifndef __TECHNOROW_H
+#define __TECHNOROW_H
+
+#include
+
+class QPushButton;
+class QLineEdit;
+
+class TechnoRow : public QWidget {
+ Q_OBJECT
+
+ public:
+ TechnoRow (int id, QWidget *parent =0);
+ ~TechnoRow () {};
+
+ QString getName();
+ QString getFile();
+ void setName(QString&);
+ void setFile(QString&);
+
+ int _id;
+ QLineEdit* _name;
+ QLineEdit* _file;
+ QPushButton* _suppress;
+ QPushButton* _browse;
+
+ signals:
+ void suppressed(int);
+
+ public slots:
+ void suppress();
+ void chooseFile();
+};
+
+#endif
diff --git a/bootstrap/runPharos/compile.sh b/bootstrap/runPharos/compile.sh
new file mode 100755
index 00000000..05a21de7
--- /dev/null
+++ b/bootstrap/runPharos/compile.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+if [ ! -e "./compile.sh" ]; then
+ echo "You must run compile.sh in its own directory : ./compile.sh"
+ exit 1
+fi
+
+if [ ! -d "build" ]; then
+ echo "Creating build directory"
+ mkdir build
+fi
+
+cd build && cmake .. && make DESTDIR=.. -j2 install
+
diff --git a/bootstrap/runPharos/main.cpp b/bootstrap/runPharos/main.cpp
new file mode 100644
index 00000000..e1efbbc4
--- /dev/null
+++ b/bootstrap/runPharos/main.cpp
@@ -0,0 +1,11 @@
+#include
+#include "MainWindow.h"
+
+int main ( int argc, char **argv ) {
+ QApplication app ( argc, argv );
+
+ MainWindow mWindow;
+ mWindow.show();
+
+ return app.exec();
+}