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(); +}